Spaces:
Running
Running
| import { useEffect, useState } from 'react'; | |
| import type { ArtifactDocument } from '../../lib/agent-tools'; | |
| interface ArtifactPaneProps { | |
| artifact: ArtifactDocument | null; | |
| onClose: () => void; | |
| } | |
| export function ArtifactPane({ artifact, onClose }: ArtifactPaneProps) { | |
| const [tab, setTab] = useState<'preview' | 'code'>('code'); | |
| const [running, setRunning] = useState(false); | |
| const [runId, setRunId] = useState(0); | |
| useEffect(() => { | |
| setTab('code'); | |
| setRunning(false); | |
| }, [artifact?.id]); | |
| const run = () => { | |
| setTab('preview'); | |
| setRunId((current) => current + 1); | |
| setRunning(true); | |
| }; | |
| return ( | |
| <section className="inspector-section artifact-section" aria-labelledby="artifact-title"> | |
| <div className="section-heading compact"> | |
| <h2 id="artifact-title">Artifact</h2> | |
| {artifact && <button className="artifact-close" type="button" onClick={onClose} aria-label="Close artifact">×</button>} | |
| </div> | |
| {!artifact ? ( | |
| <p className="artifact-empty">An inert HTML/CSS tool result will open here. Scripts and network access are blocked.</p> | |
| ) : ( | |
| <div className="artifact-pane"> | |
| <div className="artifact-tabs" role="tablist" aria-label="Artifact view"> | |
| <button type="button" role="tab" aria-selected={tab === 'code'} onClick={() => { setTab('code'); setRunning(false); }}>Code</button> | |
| <button type="button" role="tab" aria-selected={tab === 'preview'} onClick={() => setTab('preview')}>Preview</button> | |
| <span>{artifact.title}</span> | |
| </div> | |
| {tab === 'code' ? ( | |
| <pre className="artifact-code"><code>{artifact.source}</code></pre> | |
| ) : running ? ( | |
| <div className="artifact-running"> | |
| <button type="button" onClick={() => setRunning(false)}>Stop preview</button> | |
| <iframe | |
| key={`${artifact.id}-${runId}`} | |
| ref={(node) => node?.setAttribute('credentialless', '')} | |
| title={artifact.title} | |
| sandbox="" | |
| srcDoc={artifact.sandboxedSource} | |
| /> | |
| </div> | |
| ) : ( | |
| <div className="artifact-launch"> | |
| <p>Scripts are inert until you explicitly run this artifact. The preview has an opaque origin and no network access.</p> | |
| <button type="button" onClick={run}>Run isolated preview</button> | |
| </div> | |
| )} | |
| </div> | |
| )} | |
| </section> | |
| ); | |
| } | |