/** * Modern Status Indicator Component * Enhanced status indicators with true color and Unicode support * Requirements: 12.1, 12.2, 12.3 */ const React = require("react"); const { Box, Text } = require("ink"); const useModernTerminal = require("../../hooks/useModernTerminal.js"); /** * Modern status indicator with enhanced visuals */ const ModernStatusIndicator = ({ status = "idle", label = "", showLabel = true, size = "medium", animated = false, customColor, customIcon, ...props }) => { const { colors, unicode, utils, capabilities } = useModernTerminal(); const [animationFrame, setAnimationFrame] = React.useState(0); // Status configurations const statusConfig = { success: { color: "#00FF00", icon: "checkMark", fallback: "✓", label: "Success", }, error: { color: "#FF0000", icon: "crossMark", fallback: "✗", label: "Error", }, warning: { color: "#FFFF00", icon: "warning", fallback: "!", label: "Warning", }, info: { color: "#00FFFF", icon: "info", fallback: "i", label: "Info", }, loading: { color: "#0080FF", icon: "spinner", fallback: "...", label: "Loading", animated: true, }, idle: { color: "#808080", icon: "circle", fallback: "○", label: "Idle", }, connected: { color: "#00FF00", icon: "filledCircle", fallback: "●", label: "Connected", }, disconnected: { color: "#FF0000", icon: "circle", fallback: "○", label: "Disconnected", }, processing: { color: "#FF8000", icon: "spinner", fallback: "⟳", label: "Processing", animated: true, }, }; const config = statusConfig[status] || statusConfig.idle; const shouldAnimate = animated || config.animated; // Animation effect React.useEffect(() => { if (!shouldAnimate) return; const interval = setInterval(() => { setAnimationFrame((frame) => (frame + 1) % 8); }, 200); return () => clearInterval(interval); }, [shouldAnimate]); // Generate status icon const generateIcon = () => { let icon; if (customIcon) { icon = customIcon; } else if (config.icon === "spinner" && shouldAnimate) { icon = utils.createSpinner(animationFrame); } else { icon = unicode.getChar("symbols", config.icon, config.fallback); } const iconColor = customColor || (capabilities.trueColor ? colors.getInkColor(config.color) : config.color.toLowerCase().replace("#", "")); const sizeStyle = { small: {}, medium: { bold: true }, large: { bold: true }, }; return ( {icon} ); }; // Generate status label const generateLabel = () => { if (!showLabel) return null; const labelText = label || config.label; const labelColor = capabilities.trueColor ? colors.getInkColor("#FFFFFF") : "white"; return ( {labelText} ); }; return ( {generateIcon()} {generateLabel()} ); }; /** * Connection status indicator with pulse animation */ const ModernConnectionStatus = ({ isConnected = false, label = "", showDetails = false, details = {}, ...props }) => { const { colors, unicode, capabilities } = useModernTerminal(); const [pulseFrame, setPulseFrame] = React.useState(0); // Pulse animation for connected state React.useEffect(() => { if (!isConnected) return; const interval = setInterval(() => { setPulseFrame((frame) => (frame + 1) % 6); }, 300); return () => clearInterval(interval); }, [isConnected]); const generateConnectionIcon = () => { if (isConnected) { // Pulsing connected indicator const intensity = Math.sin((pulseFrame / 6) * Math.PI * 2) * 0.3 + 0.7; const baseColor = capabilities.trueColor ? "#00FF00" : "green"; // For true color terminals, we could adjust brightness // For now, just use the base color const icon = unicode.getChar("symbols", "filledCircle", "●"); return ( {icon} ); } else { // Disconnected indicator const icon = unicode.getChar("symbols", "circle", "○"); const color = capabilities.trueColor ? colors.getInkColor("#FF0000") : "red"; return {icon}; } }; const generateDetails = () => { if (!showDetails || !details) return null; return ( {Object.entries(details).map(([key, value]) => ( {key}: {value} ))} ); }; return ( {generateConnectionIcon()} {label || (isConnected ? "Connected" : "Disconnected")} {generateDetails()} ); }; /** * Multi-state status indicator */ const ModernMultiStateIndicator = ({ states = [], currentState = 0, showProgress = false, orientation = "horizontal", ...props }) => { const { colors, unicode, capabilities } = useModernTerminal(); const generateStateIndicators = () => { return states.map((state, index) => { const isActive = index === currentState; const isCompleted = index < currentState; const isPending = index > currentState; let icon, color; if (isCompleted) { icon = unicode.getChar("symbols", "checkMark", "✓"); color = capabilities.trueColor ? colors.getInkColor("#00FF00") : "green"; } else if (isActive) { icon = unicode.getChar("symbols", "pointer", "►"); color = capabilities.trueColor ? colors.getInkColor("#0080FF") : "blue"; } else { icon = unicode.getChar("symbols", "circle", "○"); color = capabilities.trueColor ? colors.getInkColor("#808080") : "gray"; } const connector = index < states.length - 1 ? ( {orientation === "horizontal" ? "─" : "│"} ) : null; return ( {icon} {state.label || `State ${index + 1}`} {connector} ); }); }; const generateProgress = () => { if (!showProgress) return null; const progress = ((currentState + 1) / states.length) * 100; return ( Progress: {Math.round(progress)}% ({currentState + 1}/{states.length}) ); }; return ( {generateStateIndicators()} {generateProgress()} ); }; /** * Health status indicator with metrics */ const ModernHealthIndicator = ({ health = "unknown", metrics = {}, showMetrics = false, thresholds = {}, ...props }) => { const { colors, unicode, utils, capabilities } = useModernTerminal(); // Health status configurations const healthConfig = { healthy: { color: "#00FF00", icon: "checkMark", label: "Healthy", }, degraded: { color: "#FFFF00", icon: "warning", label: "Degraded", }, unhealthy: { color: "#FF0000", icon: "crossMark", label: "Unhealthy", }, unknown: { color: "#808080", icon: "info", label: "Unknown", }, }; const config = healthConfig[health] || healthConfig.unknown; const generateHealthIcon = () => { const icon = unicode.getChar("symbols", config.icon, "?"); const color = capabilities.trueColor ? colors.getInkColor(config.color) : config.color.toLowerCase().replace("#", ""); return ( {icon} ); }; const generateMetrics = () => { if (!showMetrics || !metrics) return null; return ( {Object.entries(metrics).map(([key, value]) => { const threshold = thresholds[key]; let metricColor = "white"; if (threshold) { if (value > threshold.critical) { metricColor = "red"; } else if (value > threshold.warning) { metricColor = "yellow"; } else { metricColor = "green"; } } return ( {key}: {value} ); })} ); }; return ( {generateHealthIcon()} {config.label} {generateMetrics()} ); }; module.exports = { ModernStatusIndicator, ModernConnectionStatus, ModernMultiStateIndicator, ModernHealthIndicator, };