File size: 2,806 Bytes
4386567 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | import { useRef, useEffect } from 'react';
export default function Preview({ html, consoleOutput, isGenerating }) {
const iframeRef = useRef(null);
useEffect(() => {
if (iframeRef.current && html) {
iframeRef.current.srcdoc = html;
}
}, [html]);
return (
<div className="preview-panel">
<div className="preview-header">
<div className="preview-title">
{html && <span className="preview-dot" />}
<span>Preview</span>
</div>
<div className="preview-actions">
{html && (
<button className="preview-btn" title="Open in new tab" onClick={() => {
const w = window.open('', '_blank');
if (w) { w.document.open(); w.document.write(html); w.document.close(); }
}}>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<path d="M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6" />
<polyline points="15 3 21 3 21 9" />
<line x1="10" y1="14" x2="21" y2="3" />
</svg>
</button>
)}
{html && (
<button className="preview-btn" title="Copy HTML" onClick={() => {
navigator.clipboard.writeText(html).catch(() => {});
}}>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<rect x="9" y="9" width="13" height="13" rx="2" />
<path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1" />
</svg>
</button>
)}
</div>
</div>
<div className="preview-frame-wrap">
{html ? (
<iframe
ref={iframeRef}
className="preview-frame"
title="Live Preview"
sandbox="allow-scripts allow-same-origin"
/>
) : (
<div className="preview-empty">
<div className="preview-empty-icon">
{isGenerating ? '⏳' : '👁️'}
</div>
<p>{isGenerating ? 'Generating preview...' : 'Live Preview'}</p>
<p>{isGenerating ? 'Your website will appear here' : 'Generated code will render here in real-time'}</p>
</div>
)}
</div>
<div className="console-panel">
<div className="console-header">Console</div>
<div className="console-body">
{consoleOutput.length === 0 ? (
<span style={{ color: 'var(--text-dim)' }}>No output yet</span>
) : (
consoleOutput.map((entry, i) => (
<div key={i} className={entry.type === 'error' ? 'error' : ''}>
{entry.text}
</div>
))
)}
</div>
</div>
</div>
);
}
|