"use client"; import { useSyncExternalStore } from "react"; import type { ChangeEvent, FormEvent, KeyboardEvent, RefObject } from "react"; import { ArrowUp, Square } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Textarea } from "@/components/ui/textarea"; import { characterRemainingVisible } from "@/lib/character-remaining"; import { composerDraftSnapshot, serverComposerDraftSnapshot, subscribeComposerDraft, } from "@/lib/composer-draft"; export const composerRemainingId = "composer-character-remaining"; export function useComposerDraft(): string { return useSyncExternalStore( subscribeComposerDraft, composerDraftSnapshot, serverComposerDraftSnapshot, ); } type ChatComposerProps = { readonly inputRef: RefObject; readonly inputLabel: string; readonly placeholder: string; readonly maxLength: number; readonly inputDisabled: boolean; readonly submitLabel: string; readonly submitBlocked: boolean; readonly stopVisible: boolean; readonly stopLabel: string; readonly stopTitle: string; readonly onSubmit: (event: FormEvent) => void; readonly onChange: (event: ChangeEvent) => void; readonly onKeyDown: (event: KeyboardEvent) => void; readonly onStop: () => void; }; export function ChatComposer({ inputRef, inputLabel, placeholder, maxLength, inputDisabled, submitLabel, submitBlocked, stopVisible, stopLabel, stopTitle, onSubmit, onChange, onKeyDown, onStop, }: ChatComposerProps) { const draft = useComposerDraft(); const showRemaining = characterRemainingVisible(draft.length, maxLength); return (