import React, { useEffect } from 'react'; import { View, StyleSheet } from 'react-native'; import Animated, { useAnimatedStyle, useSharedValue, withTiming, } from 'react-native-reanimated'; import { Modifiers } from '../../utils/modifiers'; import { getCornerRadius } from '../../utils/cornerRadius'; import { getPadding } from '../../utils/padding'; import { getBorder } from '../../utils/border'; import { getShadow } from '../../utils/shadow'; import { getSliderWidth, value2Position } from '../Slider/utils'; import { useLifecycle } from '../../hooks/useLifecycle'; import { getTransform } from '../../utils/transform'; import { useColorScheme } from '../../hooks/useColorScheme'; import { UIColor, getColor } from '../../utils/colors'; import { useAlert } from '../../hooks/useAlert'; type LinearProps = Modifiers & { value: number; total?: number; tint?: UIColor; }; export const Linear = ({ value, total = 100, backgroundColor, opacity, frame, cornerRadius, rotationEffect, scaleEffect, padding, border, shadow, zIndex, style, tint, alert, onAppear, onDisappear, }: LinearProps) => { useAlert(alert); useLifecycle(onAppear, onDisappear); const colorScheme = useColorScheme(); const [sliderWidth, sliderHeight] = getSliderWidth(frame); const midPoint = total / 2; const slope = midPoint / (sliderWidth / 2); const progress = useSharedValue(value2Position(value, midPoint, slope)); useEffect(() => { if (value > total) { progress.value = withTiming(value2Position(total, midPoint, slope)); } else if (value < 0) { progress.value = withTiming(0); } else { const newPos = value2Position(value, midPoint, slope); progress.value = withTiming(newPos); } }, [value, total]); const animatedFillStyle = useAnimatedStyle(() => { return { width: progress.value + sliderWidth / 2, }; }, [progress.value]); return ( <View style={[ { opacity, zIndex, backgroundColor: getColor(backgroundColor, colorScheme), ...getCornerRadius(cornerRadius), ...getPadding(padding), ...getBorder(border), ...getShadow(shadow), ...getTransform(scaleEffect, rotationEffect), }, style, ]} > <View style={[ styles.progressBar, { width: sliderWidth, height: sliderHeight, backgroundColor: getColor('systemGray4', colorScheme), }, ]} > <Animated.View style={[ { height: sliderHeight, borderRadius: 10, backgroundColor: getColor(tint, colorScheme, 'systemBlue'), }, animatedFillStyle, ]} /> </View> </View> ); }; const styles = StyleSheet.create({ progressBar: { flexDirection: 'row', borderRadius: 10, }, });