Spaces:
Running
Running
File size: 3,565 Bytes
cc43e3c 052672d c69ef3e 3ba9c0c f80b091 c69ef3e 8e3dbd3 cc43e3c 8e3dbd3 3ba9c0c 8e3dbd3 f80b091 38448fc 8e3dbd3 3ba9c0c f80b091 38448fc 8e3dbd3 3ba9c0c f80b091 3ba9c0c f80b091 38448fc 3a22cf3 38448fc 8e3dbd3 3a22cf3 8e3dbd3 38448fc f80b091 38448fc f80b091 8e3dbd3 f80b091 3ba9c0c |
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 |
import * as React from 'react';
import Textarea from 'react-textarea-autosize';
import { UseChatHelpers } from 'ai/react';
import { useEnterSubmit } from '@/lib/hooks/useEnterSubmit';
import { Button, buttonVariants } from '@/components/ui/Button';
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from '@/components/ui/Tooltip';
import {
IconArrowElbow,
IconPlus,
IconRefresh,
IconStop,
} from '@/components/ui/Icons';
import { useRouter } from 'next/navigation';
import Img from '../ui/Img';
import { MessageBase } from '@/lib/types';
export interface PromptProps
extends Pick<UseChatHelpers, 'input' | 'setInput' | 'reload'> {
onSubmit: (value: string) => void;
isLoading: boolean;
url?: string;
messages: MessageBase[];
}
export function PromptForm({
onSubmit,
input,
setInput,
isLoading,
url,
messages,
reload,
}: PromptProps) {
const { formRef, onKeyDown } = useEnterSubmit();
const inputRef = React.useRef<HTMLTextAreaElement>(null);
const router = useRouter();
React.useEffect(() => {
if (inputRef.current) {
inputRef.current.focus();
}
}, []);
return (
<form
onSubmit={async e => {
e.preventDefault();
if (!input?.trim()) {
return;
}
setInput('');
await onSubmit(input);
}}
ref={formRef}
>
<div className="relative flex w-full px-8 pl-2 overflow-hidden max-h-60 grow bg-background sm:rounded-md sm:border sm:px-12 sm:pl-2">
{url && (
<Tooltip>
<TooltipTrigger asChild>
<Img
alt="prompt-image"
src={url}
className="w-1/5 my-4 mx-2 cursor-zoom-in"
/>
</TooltipTrigger>
<TooltipContent>
<Img alt="prompt-hovered-image" src={url} className="m-2" />
</TooltipContent>
</Tooltip>
)}
<Textarea
ref={inputRef}
tabIndex={0}
onKeyDown={onKeyDown}
rows={1}
value={input}
onChange={e => setInput(e.target.value)}
placeholder="Ask questions about the images."
spellCheck={false}
className="min-h-[60px] w-4/5 resize-none bg-transparent px-4 py-[1.3rem] focus-within:outline-none sm:text-sm"
/>
<div className="absolute left-1/2 -translate-x-1/2 bottom-0 h-12 z-40">
{isLoading ? (
<Button
variant="outline"
onClick={() => stop()}
className="bg-background"
>
<IconStop className="mr-2" />
Stop generating
</Button>
) : (
messages?.length >= 2 && (
<div className="flex space-x-2">
<Button variant="outline" onClick={() => reload()}>
<IconRefresh className="mr-2" />
Regenerate response
</Button>
</div>
)
)}
</div>
<div className="absolute top-1/2 -translate-y-1/2 right-4">
<Tooltip>
<TooltipTrigger asChild>
<Button
type="submit"
size="icon"
disabled={isLoading || input === ''}
>
<IconArrowElbow />
<span className="sr-only">Send message</span>
</Button>
</TooltipTrigger>
<TooltipContent>Send message</TooltipContent>
</Tooltip>
</div>
</div>
</form>
);
}
|