"use client"; import { useEffect, useRef, useState } from "react"; export type JsDosPlayerProps = { zipUrl?: string; className?: string; }; export type JsDosHandle = { stop: () => void; }; interface DosInstance { stop(): void; } export function JsDosPlayer({ zipUrl, className = "" }: JsDosPlayerProps) { const containerRef = useRef(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); const dosInstanceRef = useRef(null); const ensureJsDosCss = () => { if (typeof document === "undefined") return; if (!document.querySelector('link[data-jsdos]')) { const link = document.createElement("link"); link.rel = "stylesheet"; link.href = "https://v8.js-dos.com/v7/js-dos.css"; link.setAttribute("data-jsdos", "true"); document.head.appendChild(link); } }; useEffect(() => { if (!containerRef.current || !zipUrl) return; let isMounted = true; const loadEmulator = async () => { try { setIsLoading(true); setError(null); // Dynamically import js-dos at runtime (CSS injected via CDN) ensureJsDosCss(); const jsDosModule = await import("js-dos"); const { Dos } = jsDosModule; if (!isMounted || !containerRef.current) return; // Create DOS instance const dos = Dos(containerRef.current); dosInstanceRef.current = dos; // Run the provided archive await dos.run(zipUrl); if (isMounted) { setIsLoading(false); } } catch (err) { console.error("Failed to load js-dos:", err); if (isMounted) { setError(err instanceof Error ? err.message : "Failed to load emulator"); setIsLoading(false); } } }; loadEmulator(); return () => { isMounted = false; // Cleanup DOS instance if (dosInstanceRef.current) { try { dosInstanceRef.current.stop(); } catch (err) { console.error("Error stopping DOS instance:", err); } dosInstanceRef.current = null; } }; }, [zipUrl]); const handleStop = () => { if (dosInstanceRef.current) { try { dosInstanceRef.current.stop(); dosInstanceRef.current = null; } catch (err) { console.error("Error stopping DOS instance:", err); } } }; if (!zipUrl) { return (

No archive URL provided

); } if (error) { return (

Error: {error}

Please check the archive URL or try a different file.

); } return (
{isLoading && (
Loading emulator...
)}
); }