import React, { FunctionComponent, CSSProperties, ReactNode, useState, useEffect, useRef, } from 'react'; import { View, Text, Animated, Platform } from 'react-native'; import Icon from '../icon'; import { IComponent, ComponentDefaults } from '../utils/typings'; import pt from '../utils/pt'; import * as LinearGradient from 'expo-linear-gradient'; export type ProgressSize = 'small' | 'base' | 'large'; export type TextType = 'icon' | 'text'; import { useConfig } from '../configprovider'; import progressStyles from './styles'; export interface ProgressProps extends IComponent { className: string; style: CSSProperties; isShowPercentage: boolean; percentage: number; fillColor: string; strokeColor: Array; strokeWidth: string; size: ProgressSize; textColor: string; textWidth: string; showText: boolean; textInside: boolean; textBackground: Array; textType: TextType; status: boolean; iconName: string; iconColor: string; iconSize: string; children: ReactNode; } const defaultProps = { ...ComponentDefaults, className: '', style: {}, isShowPercentage: true, percentage: 0, fillColor: '#f3f3f3', strokeColor: ['#fa2c19', '#fa6419'], strokeWidth: '10', textColor: '', textWidth: '', showText: true, textInside: false, textBackground: ['#fa2c19', '#fa6419'], textType: 'text', status: false, iconName: 'checked', iconColor: '#439422', iconSize: '16px', children: undefined, } as ProgressProps; export const Progress: FunctionComponent< Partial & React.HTMLAttributes > = (props) => { const [proWidth, setProWidth] = useState(0); const [proHeight, setProHeight] = useState(0); const [proInnerWidth, setProInnerWidth] = useState(0); const [proInnerHeight, setProInnerHeight] = useState(0); const animationRef = useRef(new Animated.Value(0)); const animationRefTag = useRef(new Animated.Value(0)); const { className, style, isShowPercentage, percentage, fillColor, strokeColor, strokeWidth, size, textColor, textWidth, showText, textInside, textBackground, textType, status, iconName, iconColor, iconSize, children, iconClassPrefix, iconFontClassName, ...rest } = { ...defaultProps, ...props, }; const { theme } = useConfig(); const styles = progressStyles(theme); useEffect(() => { //setValue(props.value) startAnimated(); }, [props.percentage, proWidth]); const startAnimated = () => { Animated.timing(animationRef.current, { toValue: parseInt((props.percentage / 100) * proWidth), duration: 800, useNativeDriver: false, }).start(); //let leftV = 0; Animated.timing(animationRefTag.current, { toValue: parseInt((props.percentage / 100) * proWidth) - proInnerWidth / 2, duration: 800, useNativeDriver: false, }).start(); }; const getHeight = () => { let height; switch (size) { case 'small': height = pt(12); break; case 'base': height = pt(20); break; case 'large': height = pt(30); break; default: height = parseInt(strokeWidth); break; } return height; }; //hex -> rgba const hexToRgba = (hex, opacity) => { return ( 'rgba(' + parseInt('0x' + hex.slice(1, 3)) + ',' + parseInt('0x' + hex.slice(3, 5)) + ',' + parseInt('0x' + hex.slice(5, 7)) + ',' + opacity + ')' ); }; const LinearGradientModuleRef = (LinearGradient as any); const LinearGradientComponent = LinearGradientModuleRef.LinearGradient || LinearGradientModuleRef.default; return ( { setProWidth(e.nativeEvent.layout.width); setProHeight(e.nativeEvent.layout.height); }} > {Platform.OS === 'web' ? ( ) : ( )} {showText && textInside && ( { setProInnerWidth(e.nativeEvent.layout.width); setProInnerHeight(e.nativeEvent.layout.height); }} > {textType === 'icon' ? ( ) : {textType === 'text' && ( {percentage} {isShowPercentage ? '%' : ''} )} } {Platform.OS === 'web' ? ( {textType === 'text' && ( {percentage} {isShowPercentage ? '%' : ''} )} ) : ( {textType === 'text' && ( {percentage} {isShowPercentage ? '%' : ''} )} )} )} {showText && !textInside && ( <> {children ? ( {children} ) : ( {percentage} {isShowPercentage ? '%' : ''} )} )} ); }; Progress.defaultProps = defaultProps; Progress.displayName = 'NutProgress';