/* Copyright 2026 Marimo. All rights reserved. */
import { CheckIcon, CopyIcon, KeyIcon, PlusIcon } from "lucide-react";
import React from "react";
import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
import { Spinner } from "@/components/icons/spinner";
import { useImperativeModal } from "@/components/modal/ImperativeModal";
import { Badge } from "@/components/ui/badge";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { toast } from "@/components/ui/use-toast";
import { SECRETS_REGISTRY } from "@/core/secrets/request-registry";
import { useAsyncData } from "@/hooks/useAsyncData";
import { ErrorBanner } from "@/plugins/impl/common/error-banner";
import { cn } from "@/utils/cn";
import { copyToClipboard } from "@/utils/copy";
import { PanelEmptyState } from "./empty-state";
import { sortProviders, WriteSecretModal } from "./write-secret-modal";
const SecretsPanel: React.FC = () => {
const { openModal, closeModal } = useImperativeModal();
const {
data: secretKeyProviders,
isPending,
error,
refetch,
} = useAsyncData(async () => {
const result = await SECRETS_REGISTRY.request({});
return sortProviders(result.secrets);
}, []);
// Only show on the first load
if (isPending) {
return ;
}
if (error) {
return ;
}
// Provider names without 'env' provider
const providerNames = secretKeyProviders
.filter((provider) => provider.provider !== "env")
.map((provider) => provider.name);
if (secretKeyProviders.length === 0) {
return (
}
/>
);
}
return (
Environment Variable
Source
{secretKeyProviders.map((provider) => {
return provider.keys.map((key) => (
{key}
{provider.provider !== "env" && (
{provider.name}
)}
{
await copyToClipboard(`os.environ["${key}"]`);
toast({
title: "Copied to clipboard",
description: `os.environ["${key}"] has been copied to your clipboard.`,
});
}}
className={cn(
"float-right px-2 h-full text-xs text-muted-foreground hover:text-foreground",
"invisible group-hover:visible",
)}
/>
));
})}
);
};
export default SecretsPanel;
const CopyButton: React.FC<{
className?: string;
ariaLabel: string;
onCopy: () => void;
}> = ({ className, ariaLabel, onCopy }) => {
const [copied, setCopied] = React.useState(false);
const handleCopy = () => {
onCopy();
setCopied(true);
setTimeout(() => setCopied(false), 1000);
};
return (
);
};