forked from a16z-infra/ai-getting-started
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTextToImgModal.tsx
127 lines (123 loc) · 4.56 KB
/
TextToImgModal.tsx
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
import dotenv from "dotenv";
dotenv.config({ path: `.env.local` });
import { Fragment, useState } from "react";
import { Dialog, Transition } from "@headlessui/react";
import Image from "next/image";
export default function TextToImgModal({
open,
setOpen,
}: {
open: boolean;
setOpen: any;
}) {
const [imgSrc, setImgSrc] = useState("");
const [loading, setLoading] = useState(false);
const onSubmit = async (e: any) => {
e.preventDefault();
setLoading(true);
const response = await fetch("/api/txt2img", {
method: "POST",
body: JSON.stringify({
prompt: e.target.value,
}),
headers: {
"Content-Type": "application/json",
},
});
const data = await response.json();
setImgSrc(data[0]);
setLoading(false);
};
return (
<Transition.Root show={open} as={Fragment}>
<Dialog as="div" className="relative z-10" onClose={setOpen}>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-gray-950 bg-opacity-75 transition-opacity" />
</Transition.Child>
<div className="fixed inset-0 z-10 overflow-y-auto">
<div className="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
enterTo="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<Dialog.Panel className="relative transform overflow-hidden rounded-lg bg-gray-800 px-4 pb-4 pt-5 text-left shadow-xl transition-all sm:my-8 sm:p-6 w-full max-w-3xl">
<div>
<input
className="w-full flex-auto rounded-md border-0 bg-white/5 px-3.5 py-2 text-white shadow-sm focus:outline-none sm:text-sm sm:leading-6"
placeholder="Describe the image you want"
// when user click enter key, submit the form
onKeyDown={(e) => {
if (e.key === "Enter") {
onSubmit(e);
}
}}
></input>
<div className="mt-3">
<div className="my-2">
<p className="text-sm text-gray-500">
Powered by{" "}
<a
className="underline"
href="https://replicate.com/stability-ai/stable-diffusion"
>
stability-ai/stable-diffusion
</a>
</p>
</div>
</div>
</div>
{imgSrc && !loading && (
<Image
width={0}
height={0}
sizes="100vw"
src={imgSrc}
alt="img"
className="w-full h-full object-contain"
/>
)}
{loading && (
<p className="flex items-center justify-center mt-4">
<svg
className="animate-spin -ml-1 mr-3 h-5 w-5 text-white"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
></circle>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
</p>
)}
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition.Root>
);
}