import React, {CSSProperties, ReactNode, useId} from 'react'; import clsx from 'clsx'; import {InputSize} from '../forms/input-field/input-size'; import {getInputFieldClassNames} from '../forms/input-field/get-input-field-class-names'; import {useNumberFormatter} from '../../i18n/use-number-formatter'; import {clamp} from '../../utils/number/clamp'; export interface ProgressBarBaseProps { value?: number; minValue?: number; maxValue?: number; className?: string; showValueLabel?: boolean; size?: 'xs' | 'sm' | 'md'; labelPosition?: 'top' | 'bottom'; isIndeterminate?: boolean; label?: ReactNode; formatOptions?: Intl.NumberFormatOptions; role?: string; radius?: string; trackColor?: string; trackHeight?: string; progressColor?: string; } export function ProgressBarBase(props: ProgressBarBaseProps) { let { value = 0, minValue = 0, maxValue = 100, size = 'md', label, showValueLabel = !!label, isIndeterminate = false, labelPosition = 'top', className, role, formatOptions = { style: 'percent', }, radius = 'rounded', trackColor = 'bg-primary-light', progressColor = 'bg-primary', trackHeight = getSize(size), } = props; const id = useId(); value = clamp(value, minValue, maxValue); const percentage = (value - minValue) / (maxValue - minValue); const formatter = useNumberFormatter(formatOptions); let valueLabel = ''; if (!isIndeterminate && showValueLabel) { const valueToFormat = formatOptions.style === 'percent' ? percentage : value; valueLabel = formatter.format(valueToFormat); } const barStyle: CSSProperties = {}; if (!isIndeterminate) { barStyle.width = `${Math.round(percentage * 100)}%`; } const style = getInputFieldClassNames({size}); const labelEl = (label || valueLabel) && (
{label && {label}} {valueLabel &&
{valueLabel}
}
); return (
{labelPosition === 'top' && labelEl}
{labelPosition === 'bottom' && labelEl}
); } function getSize(size: InputSize) { switch (size) { case 'sm': return 'h-6'; case 'xs': return 'h-4'; default: return 'h-8'; } }