import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; import { cn } from '@/lib/utils'; import { SENCHO_OPEN_STACK_EVENT, type SenchoOpenStackDetail } from '@/lib/events'; import type { ImageExposureContext } from '@/types/security'; function openNetworking(nodeId: number | undefined, stackName: string) { if (nodeId === undefined) return; window.dispatchEvent(new CustomEvent(SENCHO_OPEN_STACK_EVENT, { detail: { nodeId, stackName, destination: 'anatomy-networking' }, })); } function networkingActionLabel(ctx: ImageExposureContext): string { return ctx.intentConflict ? 'Review networking' : 'View networking'; } function NetworkingContextList({ contexts, nodeId, showConflictHint = false, }: { contexts: ImageExposureContext[]; nodeId: number; showConflictHint?: boolean; }) { return ( ); } /** Network exposed badge + optional multi-context Networking popover. */ export function NetworkExposedControl({ contexts, nodeId, className, }: { contexts: ImageExposureContext[]; nodeId?: number; className?: string; }) { const badge = ( Network exposed ); if (contexts.length === 0 || nodeId === undefined) { return badge; } if (contexts.length === 1) { const only = contexts[0]!; return ( ); } return ( e.stopPropagation()}> ); } /** Banner-only View networking control (single dispatch or multi popover). */ export function ViewNetworkingAction({ contexts, nodeId, }: { contexts: ImageExposureContext[]; nodeId?: number; }) { if (contexts.length === 0 || nodeId === undefined) return null; if (contexts.length === 1) { const only = contexts[0]!; return ( ); } return ( ); }