import Image from "next/image"; import { FC, useRef } from "react"; import TypeAnimation from "../../TypeAnimation"; type TInputAreaProps = { promptValue: string; setPromptValue: React.Dispatch<React.SetStateAction<string>>; handleSubmit: (query: string) => void; handleSecondary?: (query: string) => void; disabled?: boolean; reset?: () => void; isStopped?: boolean; }; // Debounce function to limit the rate at which a function can fire function debounce(func: Function, wait: number) { let timeout: NodeJS.Timeout | undefined; return function executedFunction(...args: any[]) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } const InputArea: FC<TInputAreaProps> = ({ promptValue, setPromptValue, handleSubmit, handleSecondary, disabled, reset, isStopped, }) => { // Only show input if not stopped if (isStopped) { return null; } const placeholder = handleSecondary ? "Any questions about this report?" : "What would you like to research next?"; const textareaRef = useRef<HTMLTextAreaElement>(null); const resetHeight = () => { if (textareaRef.current) { textareaRef.current.style.height = '3em'; // Reset to base height } }; const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => { if (e.key === 'Enter') { if (e.shiftKey) { return; // Allow new line on Shift+Enter } else { e.preventDefault(); if (!disabled) { if (reset) reset(); handleSubmit(promptValue); setPromptValue(''); // Clear prompt value resetHeight(); // Reset height after submit } } } }; // Debounced version of the height adjustment function const adjustHeight = debounce((target: HTMLTextAreaElement) => { target.style.height = 'auto'; // Reset height to auto to allow shrinking target.style.height = `${target.scrollHeight}px`; // Adjust height }, 100); // Adjust the delay as needed const handleTextareaChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => { const target = e.target; adjustHeight(target); // Use debounced function setPromptValue(target.value); }; return ( <form className="mx-auto flex pt-2 pb-2 w-full items-center justify-between rounded-lg border bg-white px-3 shadow-[2px_2px_38px_0px_rgba(0,0,0,0.25),0px_-2px_4px_0px_rgba(0,0,0,0.25)_inset,1px_2px_4px_0px_rgba(0,0,0,0.25)_inset]" onSubmit={(e) => { e.preventDefault(); if (reset) reset(); handleSubmit(promptValue); setPromptValue(''); // Clear prompt value resetHeight(); }} > <textarea placeholder={placeholder} ref={textareaRef} className="focus-visible::outline-0 my-1 w-full pl-5 font-light not-italic leading-[normal] text-[#1B1B16]/30 text-black outline-none focus-visible:ring-0 focus-visible:ring-offset-0 sm:text-xl min-h-[3em] resize-none" disabled={disabled} value={promptValue} required rows={2} onKeyDown={handleKeyDown} onChange={handleTextareaChange} /> <button disabled={disabled} type="submit" className="relative flex h-[50px] w-[50px] shrink-0 items-center justify-center rounded-[3px] bg-[linear-gradient(154deg,#1B1B16_23.37%,#565646_91.91%)] disabled:pointer-events-none disabled:opacity-75" > {disabled && ( <div className="absolute inset-0 flex items-center justify-center"> <TypeAnimation /> </div> )} <Image unoptimized src={"/img/arrow-narrow-right.svg"} alt="search" width={24} height={24} className={disabled ? "invisible" : ""} /> </button> </form> ); }; export default InputArea;