import { FileSpreadsheetIcon, FileTextIcon, LoaderCircleIcon, PresentationIcon, } from "lucide-react"; import type { ReactNode } from "react"; import { cn } from "../../lib/cn"; import { useOpenGeniText, type OpenGeniText } from "../../messages/runtime"; export type ArtifactModality = "spreadsheet" | "document" | "presentation"; export type ArtifactSurfaceProps = { modality: ArtifactModality; title: string; /** An embedding host may already provide the artifact title and navigation. */ showHeader?: boolean | undefined; subtitle?: ReactNode | undefined; actions?: ReactNode | undefined; children: ReactNode; footer?: ReactNode | undefined; busy?: boolean | undefined; className?: string | undefined; }; const MODALITY_LABEL = (t: OpenGeniText): Record => ({ spreadsheet: t("artifacts.artifactSurface.spreadsheet"), document: t("artifacts.artifactSurface.document"), presentation: t("artifacts.artifactSurface.presentation"), }); function ModalityIcon({ modality }: { modality: ArtifactModality }) { switch (modality) { case "spreadsheet": return ; case "document": return ; case "presentation": return ; } } /** * Modality-neutral artifact chrome. It deliberately owns no file, session, or * persistence state: hosts can use the same surface for a local draft, a * durable Opengeni artifact, or a collaborative projection. */ export function ArtifactSurface({ modality, title, showHeader = true, subtitle, actions, children, footer, busy = false, className, }: ArtifactSurfaceProps) { const t = useOpenGeniText(); return (
{showHeader ? (

{title}

{subtitle ? (
{subtitle}
) : null}
{busy ? ( ) : null} {actions ?
{actions}
: null}
) : ( <> {typeof subtitle === "string" || typeof subtitle === "number" ? ( {subtitle} ) : null} {actions ? (
{actions}
) : null} )}
{children}
{footer ? ( ) : null}
); }