import { useTheme } from "../../theme/ThemeContext"; import React, { useEffect } from "react"; import { View, Text, StyleSheet, ViewStyle, TextStyle } from "react-native"; import Animated, { useSharedValue, useAnimatedStyle, withTiming, Easing, } from "react-native-reanimated"; export type ProgressBarTextPosition = "inside" | "above" | "below"; export type ProgressBarTextAlign = "center" | "left" | "right"; interface ProgressBarProps { progress?: number; text?: string; containerStyle?: ViewStyle; barContainerStyle?: ViewStyle; progressStyle?: ViewStyle; remainingStyle?: ViewStyle; textStyle?: TextStyle; progressColor?: string; remainingColor?: string; textColor?: string; height?: number; width?: number; borderRadius?: number; textPosition?: ProgressBarTextPosition; textAlign?: "center" | "left" | "right"; showText?: boolean; isRTL?: boolean; animationDuration?: number; } const ProgressBar: React.FC = ({ progress = 0.5, text = "", containerStyle = {}, barContainerStyle = {}, progressStyle = {}, remainingStyle = {}, textStyle = {}, progressColor: progressColorProp, remainingColor: remainingColorProp, textColor: textColorProp, height = 40, width, borderRadius = 5, textPosition = "inside", textAlign = "left", showText = true, isRTL = false, animationDuration = 500, }) => { const { theme, isRTL: rtl } = useTheme(); isRTL = rtl; const progressColor = progressColorProp ?? theme.primary; const remainingColor = remainingColorProp ?? theme.border; const textColor = textColorProp ?? theme.onPrimary; const clampedProgress: number = Math.min(Math.max(progress, 0), 1); const progressWidth = useSharedValue(clampedProgress); useEffect(() => { progressWidth.value = withTiming(clampedProgress, { duration: animationDuration, easing: Easing.bezier(0.25, 0.1, 0.25, 1), }); }, [clampedProgress, animationDuration, progressWidth]); const animatedProgressStyle = useAnimatedStyle(() => { return { width: `${progressWidth.value * 100}%`, }; }); return ( {textPosition === "above" && showText && ( {text} )} {textPosition === "inside" && showText && ( {text} )} {textPosition === "below" && showText && ( {text} )} ); }; const styles = StyleSheet.create({ container: { width: "100%", justifyContent: "center", }, barContainer: { width: "100%", overflow: "hidden", position: "relative", }, progressBar: { position: "absolute", top: 0, }, textInside: { position: "absolute", left: 0, right: 0, top: 0, bottom: 0, textAlign: "center", textAlignVertical: "center", paddingHorizontal: 10, fontWeight: "bold", }, textAbove: { marginBottom: 5, fontWeight: "bold", }, textBelow: { marginTop: 5, fontWeight: "bold", }, }); export default ProgressBar;