File
Blob: src/client/main.tsx
| 1 | import { useState, useEffect } from "react"; |
| 2 | import { createRoot } from "react-dom/client"; |
| 3 | import { App } from "./app"; |
| 4 | import "./styles/app.css"; |
| 5 | |
| 6 | // ghostty-web requires WASM initialisation before any Terminal is created. |
| 7 | // Instead of blocking the React tree on init(), we render immediately and |
| 8 | // show a loading screen until the WASM module is ready. |
| 9 | import { init } from "ghostty-web"; |
| 10 | |
| 11 | function Root() { |
| 12 | const [wasmReady, setWasmReady] = useState(false); |
| 13 | const [wasmError, setWasmError] = useState<string | null>(null); |
| 14 | |
| 15 | useEffect(() => { |
| 16 | init() |
| 17 | .then(() => setWasmReady(true)) |
| 18 | .catch((err: unknown) => { |
| 19 | const msg = err instanceof Error ? err.message : String(err); |
| 20 | setWasmError(msg); |
| 21 | }); |
| 22 | }, []); |
| 23 | |
| 24 | if (wasmError) { |
| 25 | return ( |
| 26 | <div className="flex flex-col h-full"> |
| 27 | <div className="flex items-center justify-center w-full h-full bg-canvas"> |
| 28 | <div className="flex flex-col items-center gap-4"> |
| 29 | <div className="text-red-400 text-sm text-center max-w-[400px] leading-relaxed"> |
| 30 | Failed to initialize terminal: {wasmError} |
| 31 | </div> |
| 32 | </div> |
| 33 | </div> |
| 34 | </div> |
| 35 | ); |
| 36 | } |
| 37 | |
| 38 | if (!wasmReady) { |
| 39 | return ( |
| 40 | <div className="flex flex-col h-full"> |
| 41 | <div className="flex items-center justify-center w-full h-full bg-canvas" role="status" aria-live="polite"> |
| 42 | <div className="flex flex-col items-center gap-4"> |
| 43 | <div className="size-8 rounded-full border-3 border-zinc-700 border-t-zinc-100 animate-spinner" /> |
| 44 | <div className="text-zinc-100 text-sm">Initializing terminal…</div> |
| 45 | </div> |
| 46 | </div> |
| 47 | </div> |
| 48 | ); |
| 49 | } |
| 50 | |
| 51 | return <App />; |
| 52 | } |
| 53 | |
| 54 | const el = document.getElementById("root"); |
| 55 | if (!el) throw new Error("Missing #root element"); |
| 56 | createRoot(el).render(<Root />); |