// AlignUI ProgressCircle v0.0.0 import * as React from 'react'; import { cn } from '@/utils/cn'; import { tv, type VariantProps } from '@/utils/tv'; export const progressCircleVariants = tv({ slots: { text: '', }, variants: { size: { '80': { text: 'text-label-sm' }, '72': { text: 'text-label-sm' }, '64': { text: 'text-label-sm' }, '56': { text: 'text-label-xs' }, '48': { text: 'text-label-xs' }, }, }, defaultVariants: { size: '80', }, }); function getSizes({ size, }: Pick, 'size'>) { switch (size) { case '80': return { strokeWidth: 6.4, radius: 40, }; case '72': return { strokeWidth: 5.75, radius: 36, }; case '64': return { strokeWidth: 5.1, radius: 32, }; case '56': return { strokeWidth: 4.5, radius: 28, }; case '48': return { strokeWidth: 6.7, radius: 24, }; default: return { strokeWidth: 6.4, radius: 40, }; } } type ProgressCircleRootProps = Omit, 'value'> & VariantProps & { value?: number; max?: number; children?: React.ReactNode; }; const ProgressCircleRoot = React.forwardRef< SVGSVGElement, ProgressCircleRootProps >( ( { value = 0, max = 100, size, className, children, ...rest }: ProgressCircleRootProps, forwardedRef, ) => { const { text } = progressCircleVariants({ size }); const { strokeWidth, radius } = getSizes({ size }); const safeValue = Math.min(max, Math.max(value, 0)); const normalizedRadius = radius - strokeWidth / 2; const circumference = normalizedRadius * 2 * Math.PI; const offset = circumference - (safeValue / max) * circumference; return ( <>
{safeValue >= 0 && ( )} {children && (
{children}
)}
); }, ); ProgressCircleRoot.displayName = 'ProgressCircleRoot'; export { ProgressCircleRoot as Root };