/** * DT ProgressBar Component * * A themed progress bar wrapping React Native Paper's ProgressBar * with the Dangerous Things angular aesthetic. * * Web CSS reference (.progress / .progress-indicator): * - Vertical or horizontal bar showing progress 0-100% * - Mode-colored fill */ import {StyleSheet, View, ViewStyle, StyleProp} from 'react-native'; import {ProgressBar, Text} from 'react-native-paper'; import {useDTTheme} from '../theme/DTThemeProvider'; import {type DTVariant, getVariantColor} from '../utils/variantColors'; import {useComponentLayout} from '../utils/useComponentLayout'; interface DTProgressBarProps { /** * Progress value between 0 and 1 */ value: number; /** * Visual variant * @default 'normal' */ variant?: DTVariant; /** * Orientation of the bar * @default 'horizontal' */ orientation?: 'horizontal' | 'vertical'; /** * Bar thickness in pixels * @default 4 */ height?: number; /** * Whether to animate progress changes * @default true */ animated?: boolean; /** * Show percentage label * @default false */ showLabel?: boolean; /** * Custom color (overrides variant) */ color?: string; /** * Additional styles */ style?: StyleProp; } /** * DT-styled ProgressBar wrapping React Native Paper ProgressBar * * @example * * * @example * * * @example * */ export function DTProgressBar({ value, variant = 'normal', orientation = 'horizontal', height = 4, animated: _animated = true, showLabel = false, color, style, }: DTProgressBarProps) { const theme = useDTTheme(); const accentColor = getVariantColor(theme, variant, color); const clampedValue = Math.max(0, Math.min(1, value)); if (orientation === 'vertical') { return ( ); } return ( {showLabel && ( {Math.round(clampedValue * 100)}% )} ); } /** * Vertical progress bar using measured pixel height instead of * percentage strings (which don't animate smoothly in RN). */ function VerticalProgressBar({ value, color, trackColor, width, showLabel, style, }: { value: number; color: string; trackColor: string; width: number; showLabel: boolean; style?: StyleProp; }) { const {dimensions, onLayout, hasDimensions} = useComponentLayout(); const fillHeight = hasDimensions ? dimensions.height * value : 0; return ( {showLabel && ( {Math.round(value * 100)}% )} ); } const styles = StyleSheet.create({ horizontalContainer: { gap: 8, }, bar: { borderRadius: 0, }, verticalContainer: { alignItems: 'center', gap: 8, }, verticalTrack: { flex: 1, width: '100%', justifyContent: 'flex-end', }, verticalFill: { width: '100%', }, label: { fontSize: 11, fontWeight: '600', letterSpacing: 0.5, }, });