TownieProjectsRoute.tsx7 matches
48user: {
49username: string;
50profileImageUrl: string|null;
51};
52project: any;
55<div className="card">
5657{project.imageUrl ? (
58<img src={project.imageUrl} className="card-image" />
59) : user.profileImageUrl ? (
60<div className="card-image">
61<img
62src={user.profileImageUrl}
63width="48"
64height="48"
67</div>
68) : (
69<div className="card-image placeholder" />
70)}
71<div className="card-body">
TownieInputBox.tsx46 matches
2import { useRef, useState, useEffect } from "https://esm.sh/react@18.2.0?dev";
3import { PlusIcon, ArrowUpIcon, Square, XIcon } from "./icons.tsx";
4import { processFiles } from "../utils/images.ts";
56export function InputBox ({
11running,
12error,
13images,
14setImages,
15} : {
16value: string;
20running: boolean;
21error: any;
22images: (string|null)[];
23setImages: (images: (string|null)[]) => void;
24}) {
25const form = useRef(null);
57autoFocus={true}
58/>
59<ImageRow images={images} setImages={setImages} />
60<div className="toolbar">
61<UploadButton
62disabled={running}
63images={images}
64setImages={setImages}
65/>
66<div className="spacer" />
88}
8990export function ImageDropContainer ({
91images,
92setImages,
93running,
94children,
95}: {
96images: (string|null)[];
97setImages: (images: (string|null)[]) => void;
98running: boolean;
99children: React.ReactNode;
100}) {
101const dragging = useImageDrop({ images, setImages, running });
102103return (
105{children}
106{dragging && (
107<div className="image-drop-overlay">
108<div className="image-drop-inner">
109Drop images here to upload
110</div>
111</div>
115}
116117export function useImageDrop ({ images, setImages, running }: {
118images: (string|null)[];
119setImages(images: (string|null)[]) => void;
120running: boolean;
121}) {
143setDragging(false);
144if (e.dataTransfer?.files && !running) {
145processFiles(Array.from(e.dataTransfer.files), images, setImages);
146}
147}
164}
165166function ImageRow ({ images, setImages }: {
167images: (string|null)[];
168setImages: (images: (string|null)[]) => void;
169}) {
170return (
171<div className="image-row">
172{images.map((image, i) => (
173<Thumbnail
174key={i}
175image={image}
176onRemove={() => {
177setImages([
178...images.slice(0, i),
179...images.slice(i + 1),
180]);
181}}
186}
187188function Thumbnail ({ image, onRemove }: {
189image: string|null;
190onRemove: () => void;
191}) {
192if (!image) return null;
193194return (
195<div className="input-image">
196<img
197src={image}
198alt="User uploaded image"
199className="image-thumbnail"
200/>
201<button
202type="button"
203title="Remove image"
204className="remove-image-button"
205onClick={onRemove}
206>
212213function UploadButton ({
214images,
215setImages,
216disabled,
217}: {
218images: (string|null)[];
219setImages: (images: (string|null)[]) => void;
220disabled: boolean;
221}) {
226<button
227type="button"
228title="Upload image"
229disabled={disabled}
230onClick={e => {
234<PlusIcon />
235<div className="sr-only">
236Upload image
237</div>
238</button>
243onChange={e => {
244if (e.target.files) {
245processFiles(Array.from(e.target.files), images, setImages);
246}
247}}
12export const PROMPT_IMAGE_LIMIT = 5;
34export const processFiles = async (files: File[], images: (string | null)[], setImages: (images: (string | null)[]) => void) => {
5const imageFiles = files.filter(file => file.type.startsWith('image/'));
6const filesToProcess = imageFiles.slice(0, PROMPT_IMAGE_LIMIT - images.filter(Boolean).length);
78if (filesToProcess.length === 0) return;
910const newImages = [...images, ...Array(filesToProcess.length).fill(null)];
11setImages(newImages);
1213const processedImages = await Promise.all(
14filesToProcess.map(async (file) => {
15return await readFileAsDataURL(file);
17);
1819const updatedImages = [...images];
20processedImages.forEach((dataUrl, index) => {
21updatedImages[images.length + index] = dataUrl;
22});
2324setImages(updatedImages.slice(0, PROMPT_IMAGE_LIMIT));
25};
2630reader.onload = () => {
31const result = reader.result as string;
32console.log("Image loaded, size:", result.length, "bytes");
33resolve(result);
34};
Towniefavicon.http.tsx1 match
13return new Response(svg, {
14headers: {
15"Content-Type": "image/svg+xml",
16},
17});
TownieChatRoute.tsx13 matches
10import { useUsageStats } from "../hooks/useUsageStats.ts";
11import { Messages } from "./Messages.tsx";
12import { InputBox, ImageDropContainer } from "./InputBox.tsx";
13import { PreviewFrame } from "./PreviewFrame.tsx";
14import { BranchSelect } from "./BranchSelect.tsx";
64}) {
65const { token, anthropicApiKey } = useAuth();
66const [images, setImages] = useState<(string|null)[]>([]);
67const [selectedFiles, setSelectedFiles] = useState<string[]>([]);
68const { audio } = useContext(AppContext);
84bearerToken: token,
85selectedFiles,
86images,
87soundEnabled: audio,
88});
108109return (
110<ImageDropContainer
111running={running}
112images={images}
113setImages={setImages}>
114<div
115className="chat-container container">
131onSubmit={e => {
132handleSubmit(e);
133setImages([]);
134}}
135onCancel={handleStop}
136running={running}
137error={error}
138images={images}
139setImages={setImages}
140/>
141</div>
149rel="norefferer"
150className="block-link text-link lockup">
151{project.imageUrl ? (
152<img src={project.imageUrl} className="image-thumbnail" />
153) : (
154<div className="image-placeholder" />
155)}
156<div>
173</div>
174<pre hidden>{JSON.stringify(messages, null, 2)}</pre>
175</ImageDropContainer>
176);
177}
test-blogmarkdown-cheatsheet.md3 matches
69```
7071## Images
7273```markdown
74
75
76```
77
redditTestREADME.md3 matches
13## Example
14This val tracks mentions of "Val Town" and related terms on Reddit, filtering results from the last 7 days and sending alerts to a Discord webhook.
15
1617---
21### 1. Fork this Val
22To start using this template, fork this val by clicking the fork button at the top-right corner of the page.
23
2425---
26### 2. View Source Code
27<em>The `CODE` box shows you the the full source code of this val, you may need to scroll down to see it.</em>
28
2930---
image-inpaintingApp.tsx16 matches
45export default function App() {
6const [imageSrc, setImageSrc] = useState<string | null>(null);
7const [ready, setReady] = useState(false);
89// Canvas refs
10const baseCanvas = useRef<HTMLCanvasElement>(null); // shows uploaded image
11const drawCanvas = useRef<HTMLCanvasElement>(null); // red overlay for drawing
12const maskCanvas = useRef<HTMLCanvasElement>(null); // hidden, true mask (white bg, transparent strokes)
20const reader = new FileReader();
21reader.onload = () => {
22setImageSrc(reader.result as string);
23setReady(false); // will flip true once image is loaded
24};
25reader.readAsDataURL(file);
26};
2728/** Once imageSrc changes, draw it onto baseCanvas and size all canvases */
29useEffect(() => {
30if (!imageSrc) return;
31const img = new Image();
32img.src = imageSrc;
33img.onload = () => {
34const { width, height } = img;
39});
4041// Draw uploaded image
42baseCanvas.current!.getContext("2d")!.drawImage(img, 0, 0);
4344// Prepare mask canvas: opaque white everywhere to start
50setReady(true);
51};
52}, [imageSrc]);
5354/* Helper: convert pointer to canvas coords */
126const link = document.createElement("a");
127link.download = "mask.png";
128link.href = maskCanvas.current!.toDataURL("image/png");
129link.click();
130};
144<h1>OpenAI In-painting Mask Editor</h1>
145146<input type="file" accept="image/*" onChange={onFileChange} />
147148{imageSrc && (
149<div
150style={{
168)}
169170{imageSrc && (
171<div style={{ marginTop: 12 }}>
172<button onClick={clearMask}>Clear Mask</button>
184correspond to your strokes – exactly what{" "}
185<a
186href="https://platform.openai.com/docs/guides/image-generation#mask-requirements"
187target="_blank"
188rel="noopener noreferrer"
pondiverseaddCreation5 matches
9// - data (string)
10// - type (string)
11// - image (data url string)
1213// sanity checks:
15// - data, hmm this needs to be long i guess.. maybe some crazy upper limit sanity check though
16// - type, not too long
17// - image, not toooo large a file size
18let body;
19try {
26const data = body.data;
27const type = body.type;
28const image = body.image;
2930// Sanity checks
38}
3940if (image.length > 20 * 1024 * 1024) {
41return Response.json({ ok: false, error: "Thumbnail too large" });
42}
58);
5960await blob.set("pondiverse_image" + id.lastInsertRowid, image);
61return Response.json({ ok: true });
62}
pondiverseupdateTable1 match
9data TEXT,
10type TEXT,
11image TEXT,
12time DATETIME NOT NULL,
13hidden BOOLEAN