1// @jsxImportSource https://esm.sh/react@18.2.0
2import { render } from "https://esm.sh/react-dom@18.2.0/client";
3import React, { useRef, useState } from "https://esm.sh/react@18.2.0";
4
5/**
6 * A button component that handles AI generation with loading state and cancellation
7 */
8const AIGenerationButton: React.FC = () => {
9 const [isGenerating, setIsGenerating] = useState(false);
10 const abortControllerRef = useRef<AbortController | null>(null);
125
126// Demo component that includes the button and styles
127const Demo: React.FC = () => {
128 return (
129 <div className="container">
1/** @jsxImportSource https://esm.sh/react@18.2.0?dev */
2import { useLocalStorage } from "https://esm.sh/react-use?dev&deps=react@18.2.0&react-dom@18.2.0";
3import React, { useState } from "https://esm.sh/react@18.2.0?dev";
4import { Chat } from "./Chat.tsx";
5import { Login } from "./Login.tsx";
1# Link Shortener
2
3A simple and fast link shortener service built with React Router 7 and Hono on Val Town.
4
5## Features
8- Track click counts for each shortened link
9- Responsive design with Tailwind CSS
10- Client-side routing with React Router 7
11- SQLite database for persistent storage
12
21โโโ frontend/
22โ โโโ components/
23โ โ โโโ App.tsx # Main React component with routing
24โ โ โโโ CreateLink.tsx # Form to create short links
25โ โ โโโ LinkList.tsx # List of created links
27โ โโโ favicon.svg # Site favicon
28โ โโโ index.html # HTML template
29โ โโโ index.tsx # React entry point
30โโโ index.ts # Entry point that exports the backend
31โโโ shared/
36
37- **Frontend**:
38 - React 18.2.0
39 - React Router 7
40 - Tailwind CSS (via CDN)
41
1// @jsxImportSource https://esm.sh/react@18.2.0
2import { StrictMode } from "https://esm.sh/react@18.2.0";
3import { createRoot } from "https://esm.sh/react-dom@18.2.0/client";
4import { App } from "./components/App.tsx";
5
1// @jsxImportSource https://esm.sh/react@18.2.0
2import { useState, useEffect } from "https://esm.sh/react@18.2.0";
3import {
4 createBrowserRouter,
10 useParams,
11 useNavigate
12} from "https://esm.sh/react-router-dom@7.0.0-rc.0?deps=react@18.2.0,react-dom@18.2.0";
13import { CreateLink } from "./CreateLink.tsx";
14import { LinkList } from "./LinkList.tsx";
56 <footer className="bg-gray-100 border-t border-gray-200">
57 <div className="container mx-auto px-4 py-4 text-center text-gray-600 text-sm">
58 <p>Link Shortener - Built with React Router 7 on Val Town</p>
59 <a
60 href={import.meta.url.replace("esm.town", "val.town")}
1// @jsxImportSource https://esm.sh/react@18.2.0
2import { Link } from "https://esm.sh/react-router-dom@7.0.0-rc.0?deps=react@18.2.0,react-dom@18.2.0";
3
4export function NotFound() {
1// @jsxImportSource https://esm.sh/react@18.2.0
2import { useState } from "https://esm.sh/react@18.2.0";
3import { Link } from "../../shared/types.ts";
4
1/** @jsxImportSource https://esm.sh/react */
2import React from "https://esm.sh/react";
3import { createRoot } from "https://esm.sh/react-dom/client";
4
5function App() {
1// @jsxImportSource https://esm.sh/react@18.2.0
2import { useState } from "https://esm.sh/react@18.2.0";
3import { Link } from "../../shared/types.ts";
4
14 const [showAdvanced, setShowAdvanced] = useState(false);
15
16 const handleSubmit = async (e: React.FormEvent) => {
17 e.preventDefault();
18 setError("");
1/** @jsxImportSource https://esm.sh/react@18.2.0?dev */
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 React, { useState } from "https://esm.sh/react@18.2.0?dev";
5import { ImagePreview } from "./ImageUpload.tsx";
6
84 };
85
86 if (part.type === "text") return <ReactMarkdown>{part.text}</ReactMarkdown>;
87 if (part.type === "reasoning")
88 return (
92 </summary>
93 <div>
94 <ReactMarkdown>{part.reasoning}</ReactMarkdown>
95 {part.details && part.details.map((detail, index) => (
96 <div key={index} className="mt-2">
97 <ReactMarkdown>{detail.text}</ReactMarkdown>
98 </div>
99 ))}