Val Town Code SearchReturn to Val Town

API Access

You can access search results via JSON API by adding format=json to your query:

https://codesearch.val.run/$1?q=image&page=778&format=json

For typeahead suggestions, use the /typeahead endpoint:

https://codesearch.val.run/typeahead?q=image

Returns an array of strings in format "username" or "username/projectName"

Found 11329 results for "image"(3278ms)

OpenTownieMessagePart.tsx11 matches

@maxm•Updated 4 months ago
2import { type Message } from "https://esm.sh/@ai-sdk/react?dev&deps=react@18.2.0&react-dom@18.2.0";
3import ReactMarkdown from "https://esm.sh/react-markdown?dev&deps=react@18.2.0&react-dom@18.2.0";
4import { ImagePreview } from "./ImageUpload.tsx";
5
6export function MessagePart({ part }: { part: NonNullable<Message["parts"]>[number] }) {
61 );
62 }
63 if (part.type === "image") {
64 // Handle both formats: {image: {url: string}} and {image: string}
65 const imageUrl = typeof part.image === 'string'
66 ? part.image
67 : part.image.url || (part.image as any).source?.url;
68
69 return (
70 <div className="mt-2">
71 <img
72 src={imageUrl}
73 alt="Uploaded image"
74 className="max-h-64 max-w-full object-contain rounded"
75 />
77 );
78 }
79 // Handle multiple images in a single part
80 if (part.type === "images") {
81 return <ImagePreview images={part.images.map(img => img.url)} />;
82 }
83}

OpenTownieindex.ts11 matches

@maxm•Updated 4 months ago
51 }
52
53 const { messages, project, branchId, anthropicApiKey, selectedFiles, images } = await c.req.json();
54 console.log("Original messages:", JSON.stringify(messages, null, 2));
55 console.log("Images received:", JSON.stringify(images, null, 2));
56
57 // Check if API key is available
79 let coreMessages = convertToCoreMessages(messages);
80
81 // If there are images, we need to add them to the last user message
82 if (images && Array.isArray(images) && images.length > 0) {
83 // Find the last user message
84 const lastUserMessageIndex = coreMessages.findIndex(
103 });
104
105 // Add each image to the content array using the correct ImagePart format
106 for (const image of images) {
107 if (image && image.url) {
108 // Extract mime type from data URL if available
109 let mimeType = undefined;
110 if (image.url.startsWith("data:")) {
111 const matches = image.url.match(/^data:([^;]+);/);
112 if (matches && matches.length > 1) {
113 mimeType = matches[1];
116
117 newUserMessage.content.push({
118 type: "image",
119 image: image.url,
120 mimeType,
121 });

OpenTownieImageUpload.tsx49 matches

@maxm•Updated 4 months ago
2import React, { useRef, useState } from "https://esm.sh/react@18.2.0?dev";
3
4// Maximum number of images that can be uploaded
5export const PROMPT_IMAGE_LIMIT = 5;
6
7interface ImageUploadProps {
8 images: (string | null)[];
9 setImages: (images: (string | null)[]) => void;
10}
11
12export function ImageUpload({ images, setImages }: ImageUploadProps) {
13 const fileInputRef = useRef<HTMLInputElement>(null);
14 const [isDragging, setIsDragging] = useState(false);
23 // Process the selected files
24 const processFiles = async (files: File[]) => {
25 // Filter for image files only
26 const imageFiles = files.filter(file => file.type.startsWith('image/'));
27
28 // Limit the number of images
29 const filesToProcess = imageFiles.slice(0, PROMPT_IMAGE_LIMIT - images.filter(Boolean).length);
30
31 if (filesToProcess.length === 0) return;
32
33 // Add null placeholders for loading state
34 const newImages = [...images, ...Array(filesToProcess.length).fill(null)];
35 setImages(newImages);
36
37 // Process each file
38 const processedImages = await Promise.all(
39 filesToProcess.map(async (file) => {
40 return await readFileAsDataURL(file);
42 );
43
44 // Replace null placeholders with actual images
45 const updatedImages = [...images];
46 processedImages.forEach((dataUrl, index) => {
47 updatedImages[images.length + index] = dataUrl;
48 });
49
50 setImages(updatedImages.slice(0, PROMPT_IMAGE_LIMIT));
51 };
52
57 reader.onload = () => {
58 const result = reader.result as string;
59 console.log("Image loaded, size:", result.length, "bytes");
60 resolve(result);
61 };
93 };
94
95 // Handle removing an image
96 const removeImage = (index: number) => {
97 const newImages = [...images];
98 newImages.splice(index, 1);
99 setImages(newImages);
100 };
101
102 // Check if we've reached the image limit
103 const isAtLimit = images.filter(Boolean).length >= PROMPT_IMAGE_LIMIT;
104
105 return (
106 <div className="w-full">
107 {/* Image previews */}
108 {images.length > 0 && (
109 <div className="flex flex-wrap gap-2 mb-2">
110 {images.map((image, index) => (
111 <div key={index} className="relative">
112 {image ? (
113 <div className="relative group">
114 <img
115 src={image}
116 alt={`Uploaded ${index + 1}`}
117 className="h-16 w-16 object-cover rounded border border-gray-300"
119 <button
120 className="absolute top-0 right-0 bg-red-500 text-white rounded-full w-5 h-5 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity"
121 onClick={() => removeImage(index)}
122 title="Remove image"
123 >
124 ×
151 ref={fileInputRef}
152 onChange={handleFileChange}
153 accept="image/*"
154 multiple
155 className="hidden"
157 <div className="text-sm text-gray-500">
158 {isDragging ? (
159 "Drop images here"
160 ) : (
161 <>
162 <span className="text-blue-500">Upload images</span> or drag and drop
163 <div className="text-xs mt-1">
164 {images.filter(Boolean).length}/{PROMPT_IMAGE_LIMIT} images
165 </div>
166 </>
173}
174
175// Component to display images in messages
176export function ImagePreview({ images }: { images: string[] }) {
177 const [expandedImage, setExpandedImage] = useState<string | null>(null);
178
179 if (!images || images.length === 0) return null;
180
181 return (
182 <div className="mt-2">
183 <div className="flex flex-wrap gap-2">
184 {images.map((image, index) => (
185 <div key={index} className="relative">
186 <img
187 src={image}
188 alt={`Image ${index + 1}`}
189 className="max-h-32 max-w-32 object-contain rounded cursor-pointer"
190 onClick={() => setExpandedImage(image)}
191 />
192 </div>
194 </div>
195
196 {/* Modal for expanded image */}
197 {expandedImage && (
198 <div
199 className="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center z-50"
200 onClick={() => setExpandedImage(null)}
201 >
202 <div className="max-w-[90%] max-h-[90%]">
203 <img
204 src={expandedImage}
205 alt="Expanded view"
206 className="max-w-full max-h-full object-contain"

OpenTownieChat.tsx4 matches

@maxm•Updated 4 months ago
24 const [soundEnabled, setSoundEnabled] = useLocalStorage<boolean>("soundEnabled", true);
25 const [selectedFiles, setSelectedFiles] = useState<string[]>([]);
26 const [images, setImages] = useState<(string | null)[]>([]);
27
28 // Use custom hook to fetch project files
57 bearerToken,
58 selectedFiles,
59 images,
60 soundEnabled,
61 });
96 handleSubmit={handleSubmit}
97 running={running}
98 images={images}
99 setImages={setImages}
100 />
101 </div>

OpenTownieChatInput.tsx13 matches

@maxm•Updated 4 months ago
1/** @jsxImportSource https://esm.sh/react@18.2.0?dev */
2import React, { useState, useEffect } from "https://esm.sh/react@18.2.0?dev";
3import { ImageUpload } from "./ImageUpload.tsx";
4
5interface ChatInputProps {
8 handleSubmit: (e: React.FormEvent<HTMLFormElement>) => void;
9 running: boolean;
10 images: (string | null)[];
11 setImages: React.Dispatch<React.SetStateAction<(string | null)[]>>;
12}
13
17 handleSubmit,
18 running,
19 images,
20 setImages
21}: ChatInputProps) {
22 // State to detect if the user is on a mobile device
40 const handleFormSubmit = (e: React.FormEvent<HTMLFormElement>) => {
41 e.preventDefault();
42 const validImages = images.filter((img): img is string => typeof img === "string");
43 console.log("Submitting with images:", validImages);
44 if (input.trim() || validImages.length > 0) {
45 handleSubmit(e);
46 setImages([]);
47 }
48 };
54 disabled={running}
55 >
56 {(images.length > 0 || !running) && <ImageUpload images={images} setImages={setImages} />}
57
58 <div className="flex gap-2">
69 if (e.key === "Enter" && !e.shiftKey && !isMobile) {
70 e.preventDefault();
71 if (input.trim() || images.filter(Boolean).length > 0) {
72 handleFormSubmit(e as any);
73 }
91 }
92 }}
93 title="Attach images"
94 >
95 Attach images 📎
96 </button>
97 )}

sqliteExplorerAppREADME.md1 match

@sysoleg•Updated 4 months ago
3View and interact with your Val Town SQLite data. It's based off Steve's excellent [SQLite Admin](https://www.val.town/v/stevekrouse/sqlite_admin?v=46) val, adding the ability to run SQLite queries directly in the interface. This new version has a revised UI and that's heavily inspired by [LibSQL Studio](https://github.com/invisal/libsql-studio) by [invisal](https://github.com/invisal). This is now more an SPA, with tables, queries and results showing up on the same page.
4
5![image.webp](https://imagedelivery.net/iHX6Ovru0O7AjmyT5yZRoA/c8e102fd-39ca-4bfb-372a-8d36daf43900/public)
6
7## Install

tolerantGreenLadybugmain.tsx42 matches

@Alifdvl•Updated 4 months ago
54
55function Kix() {
56 const [image, setImage] = useState<string | null>(null);
57 const [filter, setFilter] = useState<string>("none");
58 const [error, setError] = useState<string | null>(null);
67 const [cropArea, setCropArea] = useState({ x: 0, y: 0, width: 0, height: 0 });
68 const [startPoint, setStartPoint] = useState({ x: 0, y: 0 });
69 const imageRef = useRef<HTMLImageElement>(null);
70 const canvasRef = useRef<HTMLCanvasElement>(null);
71
72 // Add missing methods
73 const handleImageUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
74 const file = e.target.files?.[0];
75 setError(null);
81
82 // Validate file type and size
83 const validTypes = ["image/jpeg", "image/png", "image/gif", "image/webp"];
84 const maxSize = 10 * 1024 * 1024; // 10MB
85
86 if (!validTypes.includes(file.type)) {
87 setError("Invalid file type. Please upload an image (JPEG, PNG, GIF, WebP)");
88 return;
89 }
99 if (result && typeof result === "string") {
100 // Validate the data URL
101 if (result.startsWith("data:image/")) {
102 setImage(result);
103 } else {
104 setError("Invalid image file");
105 }
106 }
133 };
134
135 const rotateImage = () => {
136 const canvas = canvasRef.current;
137 const ctx = canvas?.getContext("2d");
138 if (canvas && ctx && image) {
139 const img = new Image();
140 img.onload = () => {
141 canvas.width = img.height;
143 ctx.translate(canvas.width / 2, canvas.height / 2);
144 ctx.rotate(Math.PI / 2);
145 ctx.drawImage(img, -img.width / 2, -img.height / 2);
146 setImage(canvas.toDataURL());
147 };
148 img.src = image;
149 }
150 };
155
156 const handleMouseDown = (e: React.MouseEvent) => {
157 if (!isCropping || !imageRef.current) return;
158 const rect = imageRef.current.getBoundingClientRect();
159 const x = e.clientX - rect.left;
160 const y = e.clientY - rect.top;
164
165 const handleMouseMove = (e: React.MouseEvent) => {
166 if (!isCropping || !imageRef.current || !startPoint) return;
167 const rect = imageRef.current.getBoundingClientRect();
168 const currentX = e.clientX - rect.left;
169 const currentY = e.clientY - rect.top;
177 };
178
179 const cropImage = () => {
180 const canvas = canvasRef.current;
181 const ctx = canvas?.getContext("2d");
182 const img = new Image();
183
184 if (canvas && ctx && image) {
185 img.onload = () => {
186 const scaleX = img.naturalWidth / imageRef.current!.width;
187 const scaleY = img.naturalHeight / imageRef.current!.height;
188
189 canvas.width = cropArea.width * scaleX;
190 canvas.height = cropArea.height * scaleY;
191
192 ctx.drawImage(
193 img,
194 cropArea.x * scaleX,
202 );
203
204 setImage(canvas.toDataURL());
205 setIsCropping(false);
206 setCropArea({ x: 0, y: 0, width: 0, height: 0 });
207 };
208 img.src = image;
209 }
210 };
211
212 const downloadImage = () => {
213 if (image) {
214 const link = document.createElement("a");
215 link.href = image;
216 link.download = "edited_image.png";
217 link.click();
218 }
220
221 const removeBackground = async () => {
222 if (!image) return;
223
224 setIsLoading(true);
231 "Content-Type": "application/json",
232 },
233 body: JSON.stringify({ image }),
234 });
235
239
240 const result = await response.json();
241 setImage(result.image);
242 } catch (err) {
243 setError(err instanceof Error ? err.message : "Unknown error occurred");
247 };
248
249 const enhanceImage = async (type: string) => {
250 if (!image) return;
251
252 setIsLoading(true);
261 },
262 body: JSON.stringify({
263 image,
264 enhanceType: type,
265 }),
267
268 if (!response.ok) {
269 throw new Error("Image enhancement failed");
270 }
271
272 const result = await response.json();
273 setImage(result.image);
274 } catch (err) {
275 setError(err instanceof Error ? err.message : "Unknown error occurred");
312 <div className="header">
313 <KixLogo />
314 <h1>Kix Image Editor</h1>
315 </div>
316 <input
317 type="file"
318 accept="image/*"
319 onChange={handleImageUpload}
320 />
321 {error && (
344 <html>
345 <head>
346 <title>Kix Image Editor</title>
347 <meta name="viewport" content="width=device-width, initial-scale=1">
348 <script src="https://esm.town/v/std/catch"></script>

OutfitPlannermain.tsx4 matches

@ChidinmaOgwumike•Updated 4 months ago
55 const newClothes = await Promise.all(
56 Array.from(files).map(async (file) => {
57 const imageUrl = URL.createObjectURL(file);
58 return {
59 id: Date.now(),
60 name: file.name,
61 url: imageUrl,
62 type: file.type.startsWith('image/') ? 'image' : 'other',
63 metadata: {
64 color: '',
163 type="file"
164 multiple
165 accept="image/*"
166 onChange={handleFileUpload}
167 style={{

svgRenderertabletopRPG-renderer.ts1 match

@dcm31•Updated 4 months ago
48 return new Response(svg, {
49 headers: {
50 "Content-Type": "image/svg+xml",
51 "Cache-Control": "no-store, no-cache, must-revalidate, proxy-revalidate",
52 "Pragma": "no-cache",

OpenTownieuseChatLogic.ts4 matches

@stevekrouse•Updated 4 months ago
9 bearerToken: string;
10 selectedFiles: string[];
11 images: (string | null)[];
12 soundEnabled: boolean;
13}
19 bearerToken,
20 selectedFiles,
21 images,
22 soundEnabled,
23}: UseChatLogicProps) {
41 anthropicApiKey,
42 selectedFiles,
43 images: images
44 .filter((img): img is string => {
45 const isValid = typeof img === "string" && img.startsWith("data:");
46 if (!isValid && img !== null) {
47 console.warn("Invalid image format:", img?.substring(0, 50) + "...");
48 }
49 return isValid;

imageurl2 file matches

@lchtao26•Updated 2 days ago

thilenius-webcam1 file match

@stabbylambda•Updated 1 week ago
Image proxy for the latest from https://gliderport.thilenius.com
Chrimage
Atiq
"Focal Lens with Atig Wazir" "Welcome to my photography journey! I'm Atiq Wazir, a passionate photographer capturing life's beauty one frame at a time. Explore my gallery for stunning images, behind-the-scenes stories, and tips & tricks to enhance your own