import type { ReactNode } from "react"; import { ErrorBoundary } from "./ErrorBoundary"; import { DroidCliProviderCard } from "./DroidCliProviderCard"; import { usePluginUiSlots } from "../hooks/usePluginUiSlots"; import "./PluginSlot.css"; interface PluginSlotProps { /** The slot identifier to render (e.g., "task-detail-tab", "header-action") */ slotId: string; /** Optional project ID for multi-project slot scoping */ projectId?: string; /** Optional plugin IDs to restrict rendering to a subset of matching entries */ pluginIds?: string[]; /** Render fallback shell placeholders while dynamic slot component mounting is unavailable */ renderPlaceholder?: boolean; } function renderKnownPluginSlot(slotId: string, pluginId: string): ReactNode | null { if (pluginId === "fusion-plugin-droid-runtime" && slotId === "settings-provider-card") { return ; } return null; } /** * Renders plugin slot registrations for a host surface. */ export function PluginSlot({ slotId, projectId, pluginIds, renderPlaceholder = true }: PluginSlotProps): ReactNode { const { getSlotsForId, loading, error } = usePluginUiSlots(projectId); if (loading || error || !slotId) { return null; } const matchingEntries = getSlotsForId(slotId).filter((entry) => pluginIds && pluginIds.length > 0 ? pluginIds.includes(entry.pluginId) : true, ); if (matchingEntries.length === 0) { return null; } return ( <> {matchingEntries.map((entry, index) => { const knownSlot = renderKnownPluginSlot(entry.slot.slotId, entry.pluginId); if (knownSlot) { return
{knownSlot}
; } if (!renderPlaceholder) { return null; } return (

{entry.slot.label}

Extension content available.

); })}
); }