Spaces:
Running
Running
File size: 4,078 Bytes
372531f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
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;
|