/* Copyright 2026 Marimo. All rights reserved. */ import { atom, useAtomValue } from "jotai"; import { ArrowLeftIcon } from "lucide-react"; import { useEffect } from "react"; import { KernelStartupErrorModal } from "@/components/editor/KernelStartupErrorModal"; import { AppContainer } from "@/components/editor/app-container"; import { AppHeader } from "@/components/editor/header/app-header"; import { ProgressiveBoundary } from "@/components/lifecycle/ProgressiveBoundary"; import { Spinner } from "@/components/icons/spinner"; import { buttonVariants } from "@/components/ui/button"; import { cn } from "@/utils/cn"; import { CellsRenderer } from "../components/editor/renderers/cells-renderer"; import { hasCellsAtom, notebookIsRunningAtom, useCellActions, } from "./cells/cells"; import type { AppConfig } from "./config/config-schema"; import { RuntimeState } from "./kernel/RuntimeState"; import { getSessionId } from "./kernel/session"; import { connectionAtom } from "./network/connection"; import { useRequestClient } from "./network/requests"; import { isAppConnecting } from "./websocket/connection-utils"; import { useMarimoKernelConnection } from "./websocket/useMarimoKernelConnection"; interface AppProps { appConfig: AppConfig; hideHeader?: boolean; } /** * Paint the (possibly empty) app once we have cells, or as soon as we are no * longer actively connecting. Without the connection check, a connected or * disconnected notebook with no cells would sit on a misleading "Connecting…" * spinner instead of rendering the empty app. */ const canPaintRunAppAtom = atom( (get) => get(hasCellsAtom) || !isAppConnecting(get(connectionAtom).state), ); export const RunApp: React.FC = ({ appConfig, hideHeader }) => { const { setCells } = useCellActions(); const { sendComponentValues } = useRequestClient(); // Initialize RuntimeState event-listeners useEffect(() => { RuntimeState.INSTANCE.start(sendComponentValues); return () => { RuntimeState.INSTANCE.stop(); }; }, []); const { connection, reconnect } = useMarimoKernelConnection({ autoInstantiate: true, setCells: setCells, sessionId: getSessionId(), }); const isRunning = useAtomValue(notebookIsRunningAtom); const galleryHref = (() => { if (typeof window === "undefined") { return null; } const url = new URL(window.location.href); if (!url.searchParams.has("file")) { return null; } url.searchParams.delete("file"); const search = url.searchParams.toString(); return search ? `${url.pathname}?${search}` : url.pathname; })(); return ( {galleryHref && (
Back
)}

Connecting...

} >
); };