UNPKG

@adonis-agora/agent

Version:

Governed, durable-backed AI agent (chat + tool-calling + governance) for AdonisJS — part of the Agora ecosystem.

69 lines • 3.74 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { useEffect, useState } from 'react'; import { useSpeechRecognition } from './use-speech-recognition.js'; /** * Styling-agnostic chat composer. Enter submits, Shift+Enter inserts a * newline. Optional dictation streams interim transcripts into the draft * and commits finalized chunks, and `onStop` surfaces the backend's * cancel next to send. No design-system or icon-library deps — * style it entirely through the `*ClassName` props. */ export function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = true, speechLang = 'en-US', sendLabel = 'Send', onStop, isStreaming = false, stopLabel = 'Stop generating', className, textareaClassName, sendButtonClassName, micButtonClassName, stopButtonClassName, renderMic, }) { const [value, setValue] = useState(''); // Interim dictation transcript shown appended to the draft until the // engine finalizes it — kept out of `value` so editing the rest of the // text doesn't persist a partial guess. const [interim, setInterim] = useState(''); const speech = useSpeechRecognition({ lang: speechLang, onFinalTranscript: (text) => { const trimmed = text.trim(); if (!trimmed) return; setValue((prev) => (prev.length === 0 ? trimmed : `${prev.trimEnd()} ${trimmed}`)); setInterim(''); }, onInterimTranscript: (text) => setInterim(text), }); useEffect(() => { if (!speech.isListening) setInterim(''); }, [speech.isListening]); function submit() { const trimmed = value.trim(); if (!trimmed) return; onSubmit(trimmed); setValue(''); setInterim(''); } function handleKeyDown(event) { if (event.key === 'Enter' && !event.shiftKey) { event.preventDefault(); submit(); } } function toggleMic() { if (speech.isListening) speech.stop(); else speech.start(); } const displayValue = speech.isListening && interim ? `${value}${value && !value.endsWith(' ') ? ' ' : ''}${interim}` : value; const showMic = enableSpeech && speech.isSupported; const showStop = isStreaming && onStop !== undefined; return (_jsxs("div", { className: className, children: [_jsx("textarea", { className: textareaClassName, rows: rows, value: displayValue, disabled: disabled, onChange: (event) => { // Ignore changes while interim text is injected — the engine // overwrites it on the next result. Editing works when idle. if (speech.isListening && interim) return; setValue(event.target.value); }, onKeyDown: handleKeyDown, placeholder: placeholder ?? 'Ask something (Enter to send, Shift+Enter for newline)' }), _jsx("button", { type: "button", className: sendButtonClassName, onClick: submit, disabled: disabled || !value.trim(), children: sendLabel }), showStop ? (_jsx("button", { type: "button", className: stopButtonClassName, onClick: () => void onStop(), "aria-label": "Stop generating", children: stopLabel })) : null, showMic ? (_jsx("button", { type: "button", className: micButtonClassName, onClick: toggleMic, disabled: disabled, "aria-label": speech.isListening ? 'Stop dictating' : 'Start dictating', children: renderMic ? renderMic({ isListening: speech.isListening }) : speech.isListening ? 'Stop' : 'Speak' })) : null] })); } //# sourceMappingURL=chat-input.js.map