@unicity/design-system
Version:
A comprehensive React component library built on Material-UI with advanced theming capabilities including neumorphism design support
81 lines • 5.67 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useEffect, useRef, useState } from 'react';
import { Box, Typography, } from '@mui/material';
import { StyledLinearProgress, StyledCircularProgress, ProgressContainer, StyledPillLabelProgress, StyledPillLabelFill, StyledPillLabelTextSplit } from './Progress.style';
export const Progress = ({ variant = 'linear', value = 0, color = 'primary', size = 'medium', showValue = false, label, thickness = 4, indeterminate = false, linearProgressProps, circularProgressProps, }) => {
const progressValue = Math.min(Math.max(value, 0), 100);
// Animation on view logic
const [animatedValue, setAnimatedValue] = useState(0);
const ref = useRef(null);
const [hasAnimated, setHasAnimated] = useState(false);
useEffect(() => {
if ((variant !== 'linear' && variant !== 'pillLabel') || indeterminate)
return;
const node = ref.current;
if (!node)
return;
let observer = null;
let animationFrame;
let startValue = animatedValue;
let targetValue = progressValue;
const animateToValue = () => {
setAnimatedValue((prev) => {
if (prev < targetValue) {
const next = Math.min(prev + Math.max(1, Math.abs(targetValue - prev) / 15), targetValue);
animationFrame = requestAnimationFrame(animateToValue);
return next;
}
else if (prev > targetValue) {
const next = Math.max(prev - Math.max(1, Math.abs(targetValue - prev) / 15), targetValue);
animationFrame = requestAnimationFrame(animateToValue);
return next;
}
else {
cancelAnimationFrame(animationFrame);
return targetValue;
}
});
};
const handleIntersect = (entries) => {
if (entries[0].isIntersecting && !hasAnimated) {
setHasAnimated(true);
setAnimatedValue(startValue);
animationFrame = requestAnimationFrame(animateToValue);
}
};
observer = new window.IntersectionObserver(handleIntersect, { threshold: 0.1 });
observer.observe(node);
// Animate to new value whenever progressValue changes
if (hasAnimated) {
startValue = animatedValue;
targetValue = progressValue;
animationFrame = requestAnimationFrame(animateToValue);
}
return () => {
if (observer && node)
observer.unobserve(node);
cancelAnimationFrame(animationFrame);
};
// eslint-disable-next-line
}, [progressValue, variant, indeterminate]);
const getCircularSize = () => {
if (typeof size === 'number')
return size;
switch (size) {
case 'small':
return 32;
case 'large':
return 64;
default:
return 40;
}
};
if (variant === 'pillLabel') {
return (_jsx(ProgressContainer, { ref: ref, children: _jsxs(StyledPillLabelProgress, { value: animatedValue, label: label || '', color: color, children: [_jsx(StyledPillLabelFill, { value: animatedValue, color: color }), _jsx(StyledPillLabelTextSplit, { value: animatedValue, color: color, contrast: "dark", children: label }), _jsx(StyledPillLabelTextSplit, { value: animatedValue, color: color, contrast: "light", children: label })] }) }));
}
if (variant === 'circular') {
return (_jsxs(ProgressContainer, { children: [_jsxs(Box, { position: "relative", display: "inline-flex", children: [_jsx(StyledCircularProgress, { variant: indeterminate ? 'indeterminate' : 'determinate', value: progressValue, color: ['primary', 'secondary', 'success', 'error', 'warning', 'info', 'unicityBlue', 'unicityGreen', 'unicityPurple', 'unicityOrange', 'unicityNavy'].includes(color) ? color : 'primary', size: getCircularSize(), thickness: thickness, ...circularProgressProps }), showValue && !indeterminate && (_jsx(Box, { position: "absolute", top: 0, left: 0, bottom: 0, right: 0, display: "flex", alignItems: "center", justifyContent: "center", children: _jsx(Typography, { variant: "caption", component: "div", color: "textSecondary", fontSize: size === 'small' ? '0.625rem' : '0.75rem', children: `${Math.round(progressValue)}%` }) }))] }), label && (_jsx(Typography, { variant: "body2", color: "textSecondary", mt: 1, sx: { overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, children: label }))] }));
}
return (_jsxs(ProgressContainer, { ref: ref, children: [label && (_jsxs(Box, { display: "flex", justifyContent: "space-between", alignItems: "center", mb: 0.5, children: [_jsx(Typography, { variant: "body2", color: "textSecondary", sx: { overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', flex: 1, mr: 1 }, children: label }), showValue && !indeterminate && (_jsx(Typography, { variant: "body2", color: "textSecondary", sx: { flexShrink: 0 }, children: `${Math.round((!indeterminate ? animatedValue : progressValue))}%` }))] })), _jsx(StyledLinearProgress, { variant: indeterminate ? 'indeterminate' : 'determinate', ...(indeterminate ? {} : { value: animatedValue }), color: ['primary', 'secondary', 'success', 'error', 'warning', 'info', 'unicityBlue', 'unicityGreen', 'unicityPurple', 'unicityOrange', 'unicityNavy'].includes(color) ? color : 'primary', size: size, ...linearProgressProps })] }));
};
//# sourceMappingURL=Progress.js.map