import { useEffect, useMemo, useRef, useState } from "react"; import type { VirtualFile } from "../hooks/useVirtualFS"; import { compileScript, isCompilable } from "../lib/bundler"; import type { Diagnostic } from "../hooks/usePreviewDiagnostics"; interface PreviewFrameProps { files: VirtualFile[]; version: number; /** * Hugging Face access token from the parent app. When set, the preview * injects it as `window.__REACHY_MINI_PREVIEW_TOKEN__` so the generated * app can skip its own OAuth flow (which can't work from a srcDoc * iframe - the redirect URI would be `about:srcdoc`). */ accessToken?: string | null; /** * Called with the latest `docId` as soon as a new preview HTML document * is prepared. The parent uses this to discard stale postMessage * diagnostics from an older iframe that may still be flushing after a * re-render. */ onDocReady?: (docId: number) => void; /** * Called with compile errors produced by esbuild-wasm BEFORE the iframe * starts running. Runtime errors come through the `postMessage` channel * instead and are collected by the parent's diagnostics hook. */ onCompileError?: (diagnostic: Diagnostic) => void; } /** * Render the virtual FS inside a sandboxed iframe. * * Pipeline: * 1. Take `index.html` from the virtual FS. * 2. For each local ``, ); } else { const { file, line, column, text } = result.error; onCompileError?.({ docId, kind: "compile-error", message: text, file, line, col: column, timestamp: Date.now(), }); const escaped = JSON.stringify( `[${file}:${line}:${column}] ${text}`, ); replacements.set( match, ``, ); } return; } if (normalized.endsWith(".js") || normalized.endsWith(".mjs")) { replacements.set( match, ``, ); } }), ); const inlined = rawHtml.replace(assetRegex, (m) => replacements.get(m) ?? m); const tokenScript = accessToken ? `` : ""; const reporterScript = ``; const headInjections = `${reporterScript}${tokenScript ? "\n" + tokenScript : ""}`; const withInjections = /
]*>/i.test(inlined) ? inlined.replace(/]*>/i, (m) => `${m}\n${headInjections}`) : `${headInjections}\n${inlined}`; const bannerDoc = ``; return `${bannerDoc}\n${withInjections}`; } export function PreviewFrame({ files, version, accessToken, onDocReady, onCompileError, }: PreviewFrameProps) { const [docHtml, setDocHtml] = useStateNo index.html in the virtual FS yet.
Ask the agent to create one.