UNPKG

@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
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