export function LoadingSpinner({ size = 'md' }: { size?: 'sm' | 'md' | 'lg' }) { const sizeClasses = { sm: 'w-4 h-4 border-2', md: 'w-8 h-8 border-3', lg: 'w-12 h-12 border-4', } return (
) } /** * CharonLoader - Boat on Waves animation (Charon ferrying across the Styx) * Used for general proxy/configuration operations */ export function CharonLoader({ size = 'md' }: { size?: 'sm' | 'md' | 'lg' }) { const sizeClasses = { sm: 'w-12 h-12', md: 'w-20 h-20', lg: 'w-28 h-28', } return (
{/* Water waves */} {/* Boat (bobbing animation) */} {/* Hull */} {/* Deck */} {/* Mast */} {/* Sail */} {/* Charon silhouette */}
) } /** * CharonCoinLoader - Spinning Obol Coin animation (Payment to the Ferryman) * Used for authentication/login operations */ export function CharonCoinLoader({ size = 'md' }: { size?: 'sm' | 'md' | 'lg' }) { const sizeClasses = { sm: 'w-12 h-12', md: 'w-20 h-20', lg: 'w-28 h-28', } return (
{/* Outer glow */} {/* Spinning coin */} {/* Coin face */} {/* Inner circle */} {/* Charon's boat symbol (simplified) */} {/* Gradient definition */}
) } /** * CerberusLoader - Three-Headed Guardian animation * Used for security operations (WAF, CrowdSec, ACL, Rate Limiting) */ export function CerberusLoader({ size = 'md' }: { size?: 'sm' | 'md' | 'lg' }) { const sizeClasses = { sm: 'w-12 h-12', md: 'w-20 h-20', lg: 'w-28 h-28', } return (
{/* Shield background */} {/* Inner shield detail */} {/* Three heads (simplified circles with animation) */} {/* Left head */} {/* Center head (larger) */} {/* Right head */} {/* Body */} {/* Paws */}
) } /** * ConfigReloadOverlay - Full-screen blocking overlay for Caddy configuration reloads * * Displays thematic loading animation based on operation type: * - 'charon' (blue): Proxy hosts, certificates, general config operations * - 'coin' (gold): Authentication/login operations * - 'cerberus' (red): Security operations (WAF, CrowdSec, ACL, Rate Limiting) * * @param message - Primary message (e.g., "Ferrying new host...") * @param submessage - Secondary context (e.g., "Charon is crossing the Styx") * @param type - Theme variant: 'charon', 'coin', or 'cerberus' */ export function ConfigReloadOverlay({ message = 'Ferrying configuration...', submessage = 'Charon is crossing the Styx', type = 'charon', }: { message?: string submessage?: string type?: 'charon' | 'coin' | 'cerberus' }) { const Loader = type === 'cerberus' ? CerberusLoader : type === 'coin' ? CharonCoinLoader : CharonLoader const bgColor = type === 'cerberus' ? 'bg-red-950/90' : type === 'coin' ? 'bg-amber-950/90' : 'bg-blue-950/90' const borderColor = type === 'cerberus' ? 'border-red-900/50' : type === 'coin' ? 'border-amber-900/50' : 'border-blue-900/50' return (

{message}

{submessage}

) } export function LoadingOverlay({ message = 'Loading...' }: { message?: string }) { return (

{message}

) } export function LoadingCard() { return (
) } export function EmptyState({ icon = '📦', title, description, action, }: { icon?: string title: string description: string action?: React.ReactNode }) { return (
{icon}

{title}

{description}

{action}
) }