import React from 'react'; import { ViewStyle, StyleSheet, Animated, Easing } from 'react-native'; import { Box, IBoxProps, ITextProps, Text } from '../../primitives'; import styled from 'styled-components'; import { color, border } from 'styled-system'; import { usePropsConfig } from '../../../theme'; type sizes = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl'; export type ICircularProgressProps = IBoxProps & { style?: ViewStyle; children?: JSX.Element | JSX.Element[]; value: number; size?: number | sizes; thickness?: number; color?: string; trackColor?: string; isIndeterminate?: any; max?: number; min?: number; }; const StyleAnimatedView = styled(Animated.View)(color, border); const CircularProgress = ({ value, size, isIndeterminate, thickness, color: colorProp, trackColor, max, min, ...props }: ICircularProgressProps) => { if (min) { value = value - min; } if (!size) { size = 'md'; } let sizeProps; let newProps = usePropsConfig('CircularProgress', { size: size }); if (typeof size === 'string') { sizeProps = { height: newProps.height, width: newProps.width, }; } else { sizeProps = { height: size, width: size }; } let defaultThickness = 4; if (thickness) { defaultThickness = thickness; } const degree: any = new Animated.Value(0); if (isIndeterminate) { Animated.loop( Animated.timing(degree, { toValue: 1, duration: 600, easing: Easing.linear, useNativeDriver: true, }) ).start(); } const defaultStyling: any = { borderRadius: 100, position: 'absolute', borderLeftColor: 'transparent', borderBottomColor: 'transparent', ...sizeProps, }; const styles = StyleSheet.create({ firstProgressLayer: { borderWidth: defaultThickness, ...defaultStyling, transform: [{ rotateZ: '-135deg' }], }, secondProgressLayer: { borderWidth: defaultThickness, ...defaultStyling, transform: [{ rotateZ: '45deg' }], }, offsetLayer: { borderWidth: defaultThickness, ...defaultStyling, transform: [{ rotateZ: '-135deg' }], }, animateStyle: { borderWidth: defaultThickness, ...defaultStyling, borderTopColor: 'transparent', transform: [ { rotateZ: degree.interpolate({ inputRange: [0, 1], outputRange: ['0deg', '360deg'], }), }, ], }, }); let halfSide = (max ? (min ? max - min : max) : 100) / 2; // calculating the halfvalue of the progress according to min and max const propStyle = (percent: number, base_degrees: number) => { const rotateBy = base_degrees + (percent * 180) / halfSide; return { transform: [{ rotateZ: rotateBy + 'deg' }], }; }; const renderThirdLayer = (percent: number) => { if (percent > halfSide) { return ( ); } else { return ( ); } }; let firstProgressLayerStyle; if (value > halfSide) { firstProgressLayerStyle = propStyle(halfSide, -135); } else { firstProgressLayerStyle = propStyle(value, -135); } return ( {!isIndeterminate ? ( <> {renderThirdLayer(value)} {props.children} ) : ( )} ); }; export const CircularProgressLabel = (props: ITextProps) => { return ; }; export default CircularProgress;