18โโโ frontend/
19โ โโโ components/
20โ โ โโโ App.tsx # Main React application
21โ โ โโโ PdfSplitter.tsx # PDF splitting component
22โ โ โโโ PdfMerger.tsx # PDF merging component
49
50- **Backend**: Hono (TypeScript)
51- **Frontend**: React 18.2.0 with TypeScript
52- **PDF Processing**: PDF-lib library
53- **Styling**: TailwindCSS
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import { createRoot } from "https://esm.sh/react-dom@18.2.0/client?deps=react@18.2.0";
3import { Prism as SyntaxHighlighter } from "https://esm.sh/react-syntax-highlighter?deps=react@18.2.0,react-dom@18.2.0";
4import React, { useEffect, useState } from "https://esm.sh/react@18.2.0";
5import STARTER_PROMPTS from "./starter-prompts.js";
6
30}: {
31 prompt: string;
32 setPrompt: React.Dispatch<React.SetStateAction<string>>;
33 handleSubmit: (e: React.FormEvent) => void;
34 handleStarterPromptClick: (promptItem: PromptItem) => void;
35}) {
116
117function App() {
118 const previewRef = React.useRef<HTMLDivElement>(null);
119 const [prompt, setPrompt] = useState("");
120 const [projectId, setProjectId] = useState<number | null>(null);
174 }
175
176 async function handleSubmit(e: React.FormEvent | string) {
177 if (typeof e !== "string") {
178 e.preventDefault();
673 </div>
674 <div className="bg-white w-full h-full flex flex-col grow rounded-xl border-2 border-white overflow-hidden">
675 <React.Fragment key={iframeKey}>
676 <iframe
677 srcDoc={code}
679 className="w-full grow"
680 />
681 </React.Fragment>
682 </div>
683 </div>
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React from "https://esm.sh/react@18.2.0";
3import { BlogPost } from "../utils/types.ts";
4import { Layout } from "./Layout.tsx";
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React, { useState } from "https://esm.sh/react@18.2.0";
3import { MediaService } from "../services/MediaService.ts";
4import { formatDate } from "../../shared/utils.ts";
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React from "https://esm.sh/react@18.2.0";
3
4interface MediaAnalysisProps {
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React, { useState, useRef } from "https://esm.sh/react@18.2.0";
3import { MediaService } from "../services/MediaService.ts";
4import { formatFileSize } from "../../shared/utils.ts";
23 const streamRef = useRef<MediaStream | null>(null);
24
25 const handleFileSelect = (event: React.ChangeEvent<HTMLInputElement>) => {
26 const file = event.target.files?.[0];
27 if (!file) return;
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React, { useState } from "https://esm.sh/react@18.2.0";
3import MediaCapture from "./MediaCapture.tsx";
4import MediaAnalysis from "./MediaAnalysis.tsx";
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React, { useState } from "https://esm.sh/react@18.2.0";
3import { AuthService } from "../services/AuthService.ts";
4import { validateEmail, validatePassword } from "../../shared/utils.ts";
21 });
22
23 const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
24 const { name, value } = e.target;
25 setFormData(prev => ({ ...prev, [name]: value }));
59 };
60
61 const handleSubmit = async (e: React.FormEvent) => {
62 e.preventDefault();
63
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React, { useState, useEffect } from "https://esm.sh/react@18.2.0";
3import AuthComponent from "./AuthComponent.tsx";
4import Dashboard from "./Dashboard.tsx";
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2import React 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