102 lines
3.8 KiB
TypeScript
102 lines
3.8 KiB
TypeScript
import { ScrollArea } from "@/components/ui/scroll-area";
|
|
import { useEditorStore } from "@/stores/editorStore";
|
|
import { renderMicron } from "./micronRenderer";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
type PreviewMode = "ascii" | "micron" | "raw" | "script";
|
|
|
|
export default function PreviewPane() {
|
|
const previewMode = useEditorStore((s) => s.previewMode);
|
|
const setPreviewMode = useEditorStore((s) => s.setPreviewMode);
|
|
const compiledAscii = useEditorStore((s) => s.compiledAscii);
|
|
const compiledMicron = useEditorStore((s) => s.compiledMicron);
|
|
const compiledScript = useEditorStore((s) => s.compiledScript);
|
|
const isDynamic = useEditorStore((s) => s.isDynamic);
|
|
const isCompiling = useEditorStore((s) => s.isCompiling);
|
|
const compileError = useEditorStore((s) => s.compileError);
|
|
|
|
const tabs: { value: PreviewMode; label: string; show: boolean }[] = [
|
|
{ value: "ascii", label: "ASCII", show: true },
|
|
{ value: "micron", label: "Micron", show: true },
|
|
{ value: "raw", label: "Raw", show: true },
|
|
{ value: "script", label: "Script", show: isDynamic },
|
|
];
|
|
|
|
return (
|
|
<div className="flex flex-col h-full">
|
|
<div className="flex items-center px-3 py-1.5 border-b shrink-0 gap-2">
|
|
<span className="text-xs text-muted-foreground flex-1">
|
|
Preview
|
|
{isDynamic && (
|
|
<span className="ml-1.5 text-amber-400" title="This page has dynamic features (source, if, for)">
|
|
⚡ dynamic
|
|
</span>
|
|
)}
|
|
{isCompiling && (
|
|
<span className="ml-2 text-yellow-500 animate-pulse">
|
|
compiling…
|
|
</span>
|
|
)}
|
|
{compileError && (
|
|
<span className="ml-2 text-red-400" title={compileError}>
|
|
✗ error
|
|
</span>
|
|
)}
|
|
</span>
|
|
<div className="flex gap-0.5 bg-muted rounded-md p-0.5">
|
|
{tabs
|
|
.filter((t) => t.show)
|
|
.map((tab) => (
|
|
<button
|
|
key={tab.value}
|
|
onClick={() => setPreviewMode(tab.value)}
|
|
className={cn(
|
|
"text-xs px-2 py-0.5 rounded transition-colors",
|
|
previewMode === tab.value
|
|
? "bg-background text-foreground shadow-sm"
|
|
: "text-muted-foreground hover:text-foreground",
|
|
)}
|
|
>
|
|
{tab.label}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
<ScrollArea className="flex-1 bg-background">
|
|
{previewMode === "ascii" ? (
|
|
<pre className="p-4 font-mono text-sm whitespace-pre leading-tight text-green-100/90">
|
|
{compiledAscii || (
|
|
<span className="text-muted-foreground">
|
|
ASCII preview will appear here…
|
|
</span>
|
|
)}
|
|
</pre>
|
|
) : previewMode === "micron" ? (
|
|
compiledMicron ? (
|
|
<div
|
|
className="p-4 font-mono text-sm whitespace-pre leading-tight"
|
|
dangerouslySetInnerHTML={{
|
|
__html: renderMicron(compiledMicron),
|
|
}}
|
|
/>
|
|
) : (
|
|
<div className="p-4">
|
|
<span className="text-muted-foreground text-sm">
|
|
Micron preview will appear here…
|
|
</span>
|
|
</div>
|
|
)
|
|
) : previewMode === "script" ? (
|
|
<pre className="p-4 font-mono text-xs whitespace-pre-wrap break-words text-amber-200/80 leading-relaxed">
|
|
{compiledScript || "No dynamic script generated."}
|
|
</pre>
|
|
) : (
|
|
<pre className="p-4 font-mono text-sm whitespace-pre-wrap break-words text-muted-foreground">
|
|
{compiledMicron || "Raw Micron output will appear here…"}
|
|
</pre>
|
|
)}
|
|
</ScrollArea>
|
|
</div>
|
|
);
|
|
}
|