import { ChatTools } from '@agent/components/ChatTools'; import { cancelRequest } from '@agent/icons'; import { useGlobalStore } from '@agent/state/global'; import { useWorkflowStore } from '@agent/state/workflows'; import { useCallback, useEffect, useLayoutEffect, useRef, useState, } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { arrowUp, Icon } from '@wordpress/icons'; import classNames from 'classnames'; export const ChatInput = ({ disabled, handleSubmit }) => { const textareaRef = useRef(null); const [input, setInput] = useState(''); const [history, setHistory] = useState([]); const dirtyRef = useRef(false); const [historyIndex, setHistoryIndex] = useState(null); const { getWorkflowsByFeature, block } = useWorkflowStore(); const { isMobile } = useGlobalStore(); const domTool = getWorkflowsByFeature({ requires: ['block'] })?.length > 0 && !isMobile; const INPUT_LIMIT = 1500; const inputTrimmed = input.trim(); const overLimit = inputTrimmed.length > INPUT_LIMIT; // resize the height of the textarea based on the content const adjustHeight = useCallback(() => { if (!textareaRef.current) return; textareaRef.current.style.height = 'auto'; const chat = textareaRef.current.closest('#extendify-agent-chat').offsetHeight * 0.55; const h = Math.min(chat, textareaRef.current.scrollHeight); textareaRef.current.style.height = `${block && h < 60 ? 60 : h}px`; }, [block]); useLayoutEffect(() => { window.addEventListener('extendify-agent:resize-end', adjustHeight); adjustHeight(); return () => window.removeEventListener('extendify-agent:resize-end', adjustHeight); }, [adjustHeight]); useEffect(() => { const watchForSubmit = ({ detail }) => { setHistory((prev) => { // avoid duplicates if (prev?.at(-1) === detail.message) return prev; return [...prev, detail.message]; }); setHistoryIndex(null); }; window.addEventListener('extendify-agent:chat-submit', watchForSubmit); return () => window.removeEventListener('extendify-agent:chat-submit', watchForSubmit); }, []); useEffect(() => { adjustHeight(); }, [input, adjustHeight]); useEffect(() => { const userMessages = Array.from( document.querySelectorAll( '#extendify-agent-chat-scroll-area > [data-agent-message-role="user"]', ), )?.map((el) => el.textContent || ''); const deduped = userMessages.filter( (msg, i, arr) => i === 0 || msg !== arr[i - 1], ); setHistory(deduped); }, []); const submitForm = useCallback( (e) => { e?.preventDefault(); if (!input.trim() || overLimit) return; handleSubmit(input.trim()); setHistory((prev) => { // avoid duplicates if (prev?.at(-1) === input) return prev; return [...prev, input]; }); setHistoryIndex(null); setInput(''); requestAnimationFrame(() => { dirtyRef.current = false; adjustHeight(); textareaRef.current?.focus(); }); }, [input, handleSubmit, adjustHeight, overLimit], ); const handleKeyDown = useCallback( (event) => { if ( event.key === 'Enter' && !event.shiftKey && !event.nativeEvent.isComposing ) { event.preventDefault(); if (!overLimit) submitForm(); return; } if (dirtyRef.current) return; if (event.key === 'ArrowUp') { if (!history.length) return; if (event.shiftKey || event.ctrlKey || event.altKey || event.metaKey) return; setHistoryIndex((prev) => { const next = prev === null ? history.length - 1 : Math.max(prev - 1, 0); setInput(history[next]); return next; }); event.preventDefault(); return; } if (event.key === 'ArrowDown') { if (historyIndex === null) return; if (event.shiftKey || event.ctrlKey || event.altKey || event.metaKey) return; setHistoryIndex((prev) => { if (prev === null) return null; const next = prev + 1; if (next >= history.length) { setInput(''); return null; } setInput(history[next]); return next; }); event.preventDefault(); return; } dirtyRef.current = true; }, [history, historyIndex, submitForm, overLimit], ); const handleCancel = useCallback((e) => { e.stopPropagation(); window.dispatchEvent(new CustomEvent('extendify-agent:cancel-workflow')); }, []); return ( // biome-ignore lint: allow onClick without keyboard
); }; const SubmitButton = ({ disabled, noInput, overLimit, handleCancel }) => { if (disabled) { return ( ); } return ( ); };