/* Copyright 2026 Marimo. All rights reserved. */ import { useAtomValue } from "jotai"; import { AlertCircleIcon, CheckIcon, CircleIcon } from "lucide-react"; import { Spinner } from "@/components/icons/spinner"; import { preparationAtom } from "@/core/packages/sandbox-state"; import { startupProgressAtom } from "@/core/network/connection"; import type { DisplayConnectionNotice } from "@/core/network/useConnectionNotice"; import { cn } from "@/utils/cn"; import { StartupOutput, type StartupOutputState } from "./startup-output"; const STEPS = [ { phase: "preparing-environment", titles: { complete: "Environment prepared", failed: "Environment setup failed", pending: "Preparing environment", waiting: "Prepare environment", }, descriptions: { complete: "Python and dependencies are available.", failed: "Setup could not finish.", pending: "Set up Python and dependencies.", waiting: "Set up Python and dependencies.", }, }, { phase: "starting-kernel", titles: { complete: "Kernel started", failed: "Kernel failed to start", pending: "Starting kernel", waiting: "Start kernel", }, descriptions: { complete: "The notebook is ready to run.", failed: "The kernel could not connect.", pending: "Connecting to this notebook.", waiting: "After the environment is ready.", }, }, ] as const; interface StartupProgressProps { notice: DisplayConnectionNotice; surface: "notebook" | "sidebar"; } function StartupStepOutput({ phase, state, }: { phase: (typeof STEPS)[number]["phase"]; state: StartupOutputState; }) { const preparation = useAtomValue(preparationAtom); const progress = useAtomValue(startupProgressAtom); const preparing = phase === "preparing-environment"; const logs = preparing ? (preparation?.logs.environment ?? "") : progress?.phase === phase ? progress.logs : ""; return ( ); } function StartupSummary({ notice }: { notice: DisplayConnectionNotice }) { return (
{notice.title}

{notice.ready ? "Your notebook is ready" : "Getting your notebook ready"}

{notice.ready ? "Your environment and kernel are ready." : notice.pending ? "Preparing Python and dependencies for this notebook." : "Review the setup details below to continue."}

); } export function ConnectionStatusIcon({ notice, }: { notice: DisplayConnectionNotice; }) { if (notice.ready) { return ( ); } if (notice.pending) { return ( ); } return ( ); } export function StartupProgress({ notice, surface }: StartupProgressProps) { return ( <> {surface === "notebook" && }
    {STEPS.map(({ phase, titles, descriptions }, index) => { const complete = notice.ready || (index === 0 && notice.phase === "starting-kernel"); const active = !notice.ready && notice.phase === phase; const failed = active && !notice.pending; const state = complete ? "complete" : failed ? "failed" : active ? "pending" : "waiting"; return (
  1. {index === 0 && ( )} {complete ? ( ) : active ? ( ) : ( )}
    {titles[state]}

    {descriptions[state]}

    {surface === "sidebar" && ( )}
  2. ); })}
); }