"use client" import { useEffect, useMemo, useRef, useState } from "react" import { Button } from "@/components/ui/button" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { buildCodeSandboxHtml } from "@/lib/code-sandbox-html" import { cn } from "@/lib/utils" type SandboxLine = { type: "log" | "err" value: string } type CodeSandboxButtonProps = { language: string code: string } export function CodeSandboxButton({ language, code }: CodeSandboxButtonProps) { const [open, setOpen] = useState(false) const [running, setRunning] = useState(false) const [frameKey, setFrameKey] = useState(0) const [lines, setLines] = useState([]) const iframeRef = useRef(null) const srcDoc = useMemo(() => (running ? buildCodeSandboxHtml(language, code) : ""), [code, language, running]) const errors = lines.filter((line) => line.type === "err") const logs = lines.filter((line) => line.type !== "err") useEffect(() => { if (!open) return function handleMessage(event: MessageEvent) { if (event.source !== iframeRef.current?.contentWindow) return const data = event.data if (!data || (data.sb !== "log" && data.sb !== "err")) return setLines((current) => [...current, { type: data.sb, value: String(data.v ?? "") }]) } window.addEventListener("message", handleMessage) return () => window.removeEventListener("message", handleMessage) }, [open]) function run() { setLines([]) setOpen(true) setRunning(true) setFrameKey((key) => key + 1) } function stop() { setRunning(false) } function close() { setRunning(false) setOpen(false) } return ( <> {open && (
Sandbox: {language || "code"}
{running ? ( ) : ( )}
{running &&