/**
* Modern Progress Bar Component
* Enhanced progress bar 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 progress bar with enhanced features
*/
const ModernProgressBar = ({
progress = 0,
total = 100,
width = 40,
label = "",
showPercentage = true,
showNumbers = false,
color = "#00FF00",
backgroundColor = "#333333",
style = "blocks",
animated = false,
...props
}) => {
const { colors, unicode, utils, capabilities } = useModernTerminal();
const [animationFrame, setAnimationFrame] = React.useState(0);
// Calculate progress percentage
const percentage = Math.min(100, Math.max(0, (progress / total) * 100));
const filled = Math.round((percentage / 100) * width);
const empty = width - filled;
// Animation effect
React.useEffect(() => {
if (!animated || !capabilities.enhancedUnicode) return;
const interval = setInterval(() => {
setAnimationFrame((frame) => (frame + 1) % 8);
}, 150);
return () => clearInterval(interval);
}, [animated, capabilities.enhancedUnicode]);
// Generate progress bar content
const generateProgressBar = () => {
if (style === "blocks" && capabilities.enhancedUnicode) {
// Use Unicode block characters
const fullChar = unicode.getChar("progress", "full", "█");
const emptyChar = unicode.getChar("progress", "empty", "░");
let progressContent = "";
if (capabilities.trueColor) {
// Use true colors
const fillColor = colors.getInkColor(color);
const bgColor = colors.getInkColor(backgroundColor);
progressContent = (
<>
{fullChar.repeat(filled)}
{emptyChar.repeat(empty)}
>
);
} else {
// Fallback to standard colors
progressContent = (
<>
{fullChar.repeat(filled)}
{emptyChar.repeat(empty)}
>
);
}
return progressContent;
}
// ASCII fallback
const fillChar = "#";
const emptyChar = "-";
return (
<>
{fillChar.repeat(filled)}
{emptyChar.repeat(empty)}
>
);
};
// Generate animated spinner if enabled
const generateSpinner = () => {
if (!animated) return null;
const spinnerChar = utils.createSpinner(animationFrame);
return (
{spinnerChar}
);
};
// Generate percentage display
const generatePercentage = () => {
if (!showPercentage) return null;
const percentText = `${Math.round(percentage)}%`;
return {percentText};
};
// Generate numbers display
const generateNumbers = () => {
if (!showNumbers) return null;
const numbersText = `${progress}/${total}`;
return (
({numbersText})
);
};
return (
{label && {label}}
{generateSpinner()}
{generateProgressBar()}
{generatePercentage()}
{generateNumbers()}
);
};
/**
* Circular progress indicator using Unicode characters
*/
const ModernCircularProgress = ({
progress = 0,
total = 100,
size = "medium",
color = "#00FF00",
showPercentage = true,
...props
}) => {
const { colors, unicode, capabilities } = useModernTerminal();
const percentage = Math.min(100, Math.max(0, (progress / total) * 100));
// Size configurations
const sizeConfig = {
small: { radius: 1, chars: ["○", "◐", "◑", "◒", "●"] },
medium: { radius: 2, chars: ["○", "◔", "◑", "◕", "●"] },
large: { radius: 3, chars: ["○", "◔", "◑", "◕", "●"] },
};
const config = sizeConfig[size] || sizeConfig.medium;
const charIndex = Math.floor((percentage / 100) * (config.chars.length - 1));
const progressChar = config.chars[charIndex];
const displayColor = capabilities.trueColor
? colors.getInkColor(color)
: "green";
return (
{progressChar}
{showPercentage && {Math.round(percentage)}%}
);
};
/**
* Multi-segment progress bar
*/
const ModernSegmentedProgress = ({
segments = [],
width = 40,
showLabels = true,
...props
}) => {
const { colors, unicode, capabilities } = useModernTerminal();
const total = segments.reduce((sum, segment) => sum + segment.value, 0);
const generateSegments = () => {
let currentPosition = 0;
return segments.map((segment, index) => {
const segmentWidth = Math.round((segment.value / total) * width);
const char = capabilities.enhancedUnicode
? unicode.getChar("progress", "full", "█")
: "#";
const segmentColor = capabilities.trueColor
? colors.getInkColor(segment.color || "#00FF00")
: segment.color || "green";
currentPosition += segmentWidth;
return (
{char.repeat(segmentWidth)}
);
});
};
const generateLabels = () => {
if (!showLabels) return null;
return (
{segments.map((segment, index) => (
■
{segment.label} ({segment.value})
))}
);
};
return (
{generateSegments()}
{generateLabels()}
);
};
module.exports = {
ModernProgressBar,
ModernCircularProgress,
ModernSegmentedProgress,
};