"use client";
import { ThemeProvider as BjorkDemoThemeProvider } from "next-themes";
import { useEffect, useMemo, useState } from "react";
import { AgentTrace, type AgentStep } from "@/components/ui/bjork-agent-trace";
const RUN = [
{ id: "parse", kind: "think", label: "Parse request", seconds: 0.6 },
{
id: "search",
kind: "search",
label: 'Search docs: "optical alignment"',
seconds: 1.8,
detail:
"Matched 3 files: OPTICAL-ALIGNMENT.md, AGENTS.md (sections 8 and 31), and components/bjork-ui/misc/timer.tsx, which uses the play-glyph nudge.",
},
{ id: "read", kind: "read", label: "Read OPTICAL-ALIGNMENT.md", seconds: 1.1 },
{ id: "draft", kind: "code", label: "Draft component spec", seconds: 5.2 },
{
id: "typecheck",
kind: "tool",
label: "Run type check",
seconds: 2.0,
error: true,
detail: "tsc --noEmit: 2 errors in agent-trace.tsx",
},
{ id: "retry", kind: "tool", label: "Retry type check", seconds: 1.4 },
{ id: "compose", kind: "think", label: "Compose answer", seconds: 0.9 },
] as const;
const RETRY_INDEX = RUN.findIndex((step) => step.id === "retry");
function stepsAt(stage: number, forceError: boolean, startedAt?: number): AgentStep[] {
return RUN.map((step, i): AgentStep => {
const base = { id: step.id, kind: step.kind, label: step.label, detail: "detail" in step ? step.detail : undefined };
if (i < stage) {
if (i === RETRY_INDEX && !forceError) return { ...base, status: "skipped" };
return {
...base,
status: forceError && "error" in step && step.error ? "error" : "done",
durationMs: Math.round(step.seconds * 1000),
};
}
if (i === stage) return { ...base, status: "active", startedAt };
return { ...base, status: "pending" };
});
}
const POSE = 1_700_000_000_000;
type Density = "comfortable" | "compact";
function Demo({
forceError,
density,
replay,
}: {
forceError: boolean;
density: Density;
replay: number;
}) {
const isPreview = false;
const [stage, setStage] = useState(0);
useEffect(() => {
if (isPreview || stage >= RUN.length) return;
const id = window.setTimeout(
() => setStage((s) => (s + 1 === RETRY_INDEX && !forceError ? s + 2 : s + 1)),
RUN[stage].seconds * 1000,
);
return () => window.clearTimeout(id);
}, [isPreview, stage, forceError]);
// Preview posed frame: steps 1 to 4 are done (draft is amber at 5.2s), and step 5 has run for 1.2s.
const steps = useMemo(
() => (isPreview ? stepsAt(4, false, POSE) : stepsAt(stage, forceError)),
[isPreview, stage, forceError],
);
return (
<div className="flex w-[min(520px,calc(100vw-56px))] flex-col items-center gap-6">
{/* A new replay value remounts the trace, so a folded trace opens again. */}
<AgentTrace key={replay} steps={steps} density={density} now={isPreview ? POSE + 1200 : undefined} />
</div>
);
}
const DEFAULT_DENSITY: Density = "comfortable";
function SourceDemo(){
const [forceError, setForceError] = useState(false);
const [density, setDensity] = useState<Density>(DEFAULT_DENSITY);
const [replay, setReplay] = useState(0);
const reset = () => {
setForceError(false);
setDensity(DEFAULT_DENSITY);
setReplay((r) => r + 1);
};
return <>
<Demo forceError={forceError} density={density} replay={replay} />
</>;
}
export default function BjorkRegistryPreview(){return <BjorkDemoThemeProvider attribute="class" defaultTheme="dark" enableSystem={false} storageKey="bjork-review-demo-theme"><div data-component-demo className="dark flex min-h-screen w-full items-center justify-center bg-[var(--bjork-bg)] p-8 text-[var(--bjork-text)]"><div className="w-full max-w-[850px]"><SourceDemo/></div></div></BjorkDemoThemeProvider>}