import { useEffect, useState } from "react"; import type { PluginPanelChrome, PluginPanelCloseDecision, PluginPanelOpenOptions } from "@edgeever/plugin-api"; import { useTranslation } from "react-i18next"; import { AppConfirmDialog } from "@/components/dialogs/ConfirmDialogs"; import { PluginPanelEmpty, PluginPanelHeaderActions, PluginPanelToolbar } from "@/components/plugins/PluginPanelChrome"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import type { EdgeEverPluginHost, RegisteredPluginPanel } from "@/lib/plugins/plugin-host"; import { cn } from "@/lib/utils"; export const PluginPanelDialog = ({ host, panel, options, onClose }: { host: EdgeEverPluginHost; panel: RegisteredPluginPanel | null; options?: PluginPanelOpenOptions; onClose: () => void; }) => { const { t } = useTranslation(); const [container, setContainer] = useState(null); const [chrome, setChrome] = useState({}); const [chromeEnabled, setChromeEnabled] = useState(false); const [mountError, setMountError] = useState(null); const [closeConfirmation, setCloseConfirmation] = useState | null>(null); const [checkingClose, setCheckingClose] = useState(false); const panelPluginId = panel?.pluginId ?? null; const panelId = panel?.id ?? null; useEffect(() => { setChrome({}); setChromeEnabled(false); }, [panelPluginId, panelId]); useEffect(() => { // Container is reactive so delayed portal attachment mounts the plugin. if (!container || !panelPluginId || !panelId) return; let disposed = false; let disposePanel: (() => void) | null = null; setMountError(null); container.replaceChildren(); void host.mountPanel(panelPluginId, panelId, container, options, requestClose, { set(next) { if (disposed) return; setChromeEnabled(true); setChrome(next); }, }).then((dispose) => { if (disposed) dispose(); else disposePanel = dispose; }).catch((error: unknown) => { if (!disposed) setMountError(error instanceof Error ? error.message : String(error)); }); return () => { disposed = true; disposePanel?.(); container.replaceChildren(); }; }, [container, host, options, panelId, panelPluginId]); const requestClose = async () => { if (!panelPluginId || !panelId || checkingClose) return; setCheckingClose(true); try { const decision = await host.getPanelCloseDecision(panelPluginId, panelId); if (decision === true) onClose(); else if (decision && typeof decision === "object") setCloseConfirmation(decision); } catch (error) { setMountError(error instanceof Error ? error.message : String(error)); } finally { setCheckingClose(false); } }; const title = chrome.header?.title || panel?.title || t("plugins.panel"); const hideDescription = chromeEnabled && chrome.header?.description === null; const description = chrome.header?.description || t("plugins.panelDescription"); return ( <> { if (!open) void requestClose(); }}>
{title} {description}
{chromeEnabled ? : null}
{chromeEnabled ? : null} {mountError ?
{mountError}
: null} {chrome.empty ? : null}
{closeConfirmation ? ( setCloseConfirmation(null)} onConfirm={() => { setCloseConfirmation(null); onClose(); }} /> ) : null} ); };