/* Copyright 2026 Marimo. All rights reserved. */
import { AlertCircleIcon, DownloadCloudIcon } from "lucide-react";
import type { PropsWithChildren } from "react";
import { Spinner } from "@/components/icons/spinner";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Button } from "@/components/ui/button";
import { assertNever } from "@/utils/assertNever";
import { cn } from "@/utils/cn";
import type {
ExportBlockReason,
ExportFormat,
ExportFormatStatus,
ExportSetupRequirement,
} from "./state";
const SETUP_REQUIREMENTS: Record<
ExportSetupRequirement["name"],
{ description: string }
> = {
"playwright-chromium": {
description: "PDF export requires Playwright Chromium.",
},
};
export function FormatStatusIcon({ status }: { status: ExportFormatStatus }) {
if (status.available && !status.availabilityCheckFailed) {
return null;
}
if (status.reason?.type === "checking-requirements") {
return (
Checking requirements
);
}
const statusLabel = status.availabilityCheckFailed
? "Requirements unknown"
: "Unavailable";
return (
{statusLabel}
);
}
export function FormatNotice({
format,
formatLabel,
status,
onInstall,
isInstalling = false,
}: {
format: ExportFormat;
formatLabel: string;
status: ExportFormatStatus;
onInstall?: () => void;
isInstalling?: boolean;
}) {
if (status.availabilityCheckFailed) {
return (
Couldn't check whether this export is available. You can still try it.
);
}
if (!status.reason) {
return null;
}
return (
);
}
function Notice({
children,
onInstall,
isInstalling = false,
}: PropsWithChildren<{
onInstall?: () => void;
isInstalling?: boolean;
}>) {
return (
{children}
{onInstall ? (
) : null}
);
}
function ReasonNotice({
format,
formatLabel,
reason,
onInstall,
isInstalling,
}: {
format: ExportFormat;
formatLabel: string;
reason: ExportBlockReason;
onInstall?: () => void;
isInstalling: boolean;
}) {
switch (reason.type) {
case "checking-requirements":
return (
Checking {formatLabel} requirements…
);
case "notebook-must-be-named":
return Name and save this notebook before exporting.;
case "missing-packages":
return (
{formatLabel} export requires{" "}
{reason.packages.join(", ")}
.
);
case "missing-setup":
return (
{onInstall ? (
reason.requirements
.map(
(requirement) =>
SETUP_REQUIREMENTS[requirement.name].description,
)
.join(" ")
) : (
{reason.requirements.map((requirement) => {
const details = SETUP_REQUIREMENTS[requirement.name];
return (
{details.description}
{requirement.command}
);
})}
)}
);
case "wasm-runtime":
return (
{format === "pdf"
? "Use your browser's print dialog to save the current app view as a PDF."
: "Open this notebook in a local marimo session to use this export."}
);
default:
assertNever(reason);
}
}