react-native#Easing TypeScript Examples

The following examples show how to use react-native#Easing. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: animation.ts    From react-native-base-ui with MIT License 6 votes vote down vote up
animation: Animation = {
  timing100: 100,
  timing200: 200,
  timing300: 300,
  timing400: 400,
  timing500: 500,
  timing600: 600,
  timing700: 700,
  timing800: 800,
  timing900: 900,
  timing1000: 1000,
  easeInCurve: Easing.bezier(0.8, 0.2, 0.6, 1),
  easeOutCurve: Easing.bezier(0.2, 0.8, 0.4, 1),
  easeInOutCurve: Easing.bezier(0.4, 0, 0.2, 1),
  easeInQuinticCurve: Easing.bezier(0.755, 0.05, 0.855, 0.06),
  easeOutQuinticCurve: Easing.bezier(0.23, 1, 0.32, 1),
  easeInOutQuinticCurve: Easing.bezier(0.86, 0, 0.07, 1),
  linearCurve: Easing.bezier(0, 0, 1, 1),
}
Example #2
Source File: TestAnimatedCard.tsx    From react-native-anchor-point with MIT License 6 votes vote down vote up
componentDidMount() {
       this._animation = Animated
           .loop(
               Animated.timing(this._rotateAnimatedValue, {
                   toValue: 1,
                   duration: 1500,
                   useNativeDriver: true,
                   easing: Easing.cubic
               }),
               { iterations: 1000 },
           )
           .start();
    }
Example #3
Source File: toolbar-context.tsx    From react-native-cn-quill with MIT License 6 votes vote down vote up
hide = () => {
    if (this.state.isAnimating) return;
    const { theme } = this.props;
    if (theme) {
      this.setState({ isAnimating: true }, () => {
        Animated.timing(this.animatedValue, {
          toValue: theme.size + 10,
          duration: 200,
          easing: Easing.linear,
          useNativeDriver: false,
        }).start(() => {
          this.setState({
            name: '',
            open: false,
            options: [],
            isAnimating: false,
          });
        });
      });
    }
  };
Example #4
Source File: toolbar-context.tsx    From react-native-cn-quill with MIT License 6 votes vote down vote up
show = (name: string, options: Array<ToggleData>) => {
    if (this.state.isAnimating) return;

    const { theme } = this.props;
    if (theme) {
      this.setState({ options, name, isAnimating: true }, () => {
        Animated.timing(this.animatedValue, {
          toValue: 2 * theme.size + 14,
          duration: 200,
          easing: Easing.sin,
          useNativeDriver: false,
        }).start(() => this.setState({ open: true, isAnimating: false }));
      });
    }
  };
Example #5
Source File: TransitionSpecs.tsx    From nlw2-proffy with MIT License 6 votes vote down vote up
ScaleFromCenterAndroidSpec: TransitionSpec = {
  animation: 'timing',
  config: {
    duration: 400,
    // This is super rough approximation of the path used for the curve by android
    // See http://aosp.opersys.com/xref/android-10.0.0_r2/xref/frameworks/base/core/res/res/interpolator/fast_out_extra_slow_in.xml
    easing: Easing.bezier(0.35, 0.45, 0, 1),
  },
}
Example #6
Source File: TransitionSpecs.tsx    From nlw2-proffy with MIT License 6 votes vote down vote up
RevealFromBottomAndroidSpec: TransitionSpec = {
  animation: 'timing',
  config: {
    duration: 425,
    // This is super rough approximation of the path used for the curve by android
    // See http://aosp.opersys.com/xref/android-9.0.0_r47/xref/frameworks/base/core/res/res/interpolator/fast_out_extra_slow_in.xml
    easing: Easing.bezier(0.35, 0.45, 0, 1),
  },
}
Example #7
Source File: ProgressBar.tsx    From react-native-jigsaw with MIT License 6 votes vote down vote up
animate() {
    const { useNativeDriver = false, indeterminateAnimationDuration = 1000 } =
      this.props;
    this.state.animationValue.setValue(0);
    Animated.timing(this.state.animationValue, {
      toValue: 1,
      duration: indeterminateAnimationDuration,
      easing: Easing.linear,
      isInteraction: false,
      useNativeDriver,
    }).start((endState) => {
      if (endState.finished) {
        this.animate();
      }
    });
  }
Example #8
Source File: HudView.tsx    From SQUID with MIT License 6 votes vote down vote up
_initializeRotationAnimation(isRotating) {
    this.state.rotationAnim.setValue(0);
    if (!isRotating && !this.state.isVisible) {
      return;
    }

    Animated.timing(this.state.rotationAnim, {
      toValue: 1,
      duration: 800,
      easing: Easing.linear
    }).start(() => {
      this._initializeRotationAnimation();
    });
  }
Example #9
Source File: RefreshButton.tsx    From BitcoinWalletMobile with MIT License 6 votes vote down vote up
RefreshButton : React.FC<Props> = (props) => {

    let rotation = new Animated.Value(0)
    const animation = Animated.loop(Animated.timing(rotation, {
        toValue: 1,
        duration: 1000,
        easing: Easing.linear,
        useNativeDriver: true,
      })).start()

    const spin = rotation.interpolate({
        inputRange: [0, 1],
        outputRange: ['0deg', '360deg']
    })

    return (
    <View>
        <TouchableOpacity onPress={props.pressed} style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
            <Animated.Image style={[styles.icon, {transform: props.refeshing ? [{rotate: spin}] : []}]} source={require('../assets/images/refresh.png')} />
        </TouchableOpacity>
    </View>
    );
}
Example #10
Source File: AnimatedCircularProgress.tsx    From react-native-jigsaw with MIT License 5 votes vote down vote up
AnimatedCircularProgress: React.FC<Props> = ({
  duration = 500,
  easing = Easing.out(Easing.ease),
  fill,
  prefill = 0,
  useNativeDriver = false,
  tintColorSecondary,
  onAnimationComplete,
  tintColor = "black",
  ...other
}) => {
  const [fillAnimation] = React.useState<Animated.Value>(
    new Animated.Value(prefill)
  );

  const animate = React.useCallback(
    (
      toVal: number = -1,
      dur?: number,
      ease?: EasingFunction
    ): Animated.CompositeAnimation => {
      const toValue = toVal >= 0 ? toVal : fill;
      const dura = dur || duration;
      const eas = ease || easing;
      const useNative = useNativeDriver;

      const anim = Animated.timing(fillAnimation, {
        useNativeDriver: useNative,
        toValue,
        easing: eas,
        duration: dura,
      });
      anim.start(onAnimationComplete);

      return anim;
    },
    [
      duration,
      easing,
      fill,
      useNativeDriver,
      fillAnimation,
      onAnimationComplete,
    ]
  );

  const animateColor = () => {
    if (!tintColorSecondary) {
      return tintColor;
    }

    const tintAnimation = fillAnimation.interpolate({
      inputRange: [0, 100],
      outputRange: [tintColor, tintColorSecondary],
    });

    return tintAnimation;
  };

  React.useEffect(() => {
    animate();
  }, [fill, animate]);

  return (
    <AnimatedProgress
      {...other}
      style={other.style as Animated.WithAnimatedValue<StyleProp<ViewStyle>>}
      childrenContainerStyle={
        other.childrenContainerStyle as Animated.WithAnimatedValue<
          StyleProp<ViewStyle>
        >
      }
      fill={fillAnimation}
      tintColor={animateColor()}
    />
  );
}
Example #11
Source File: ProgressIndicator.tsx    From natds-rn with ISC License 5 votes vote down vote up
ProgressIndicatorComponent = ({
  size = 'medium',
  showLayer = false
}: ProgressIndicatorProps) => {
  /**
   * Duration specify how much the circle will take to make a 720deg loop around itself,
   * decrease it will speed up the animation speed and increase will slow the animation speed
   * The default speed is 1.4 second per loop
   */
  const duration = 1400
  /**
   * This animation/Animated.timing, is responsible for looping the border around the view.
   */
  const timer = useRef(new Animated.Value(0)).current
  const rotation = Animated.timing(timer, {
    duration,
    easing: Easing.inOut(Easing.quad),
    isInteraction: false,
    toValue: 1,
    useNativeDriver: Platform.OS !== 'web'
  })
  /**
   * The rotate animation will take from 0deg to 720deg to make a full loop around itself
   */
  const minCircularRange = '0deg'
  const maxCircularRange = '720deg'

  const layerStyle = {
    transform: [
      {
        rotate: timer.interpolate({
          inputRange: [0, 1],
          outputRange: [minCircularRange, maxCircularRange]
        })
      }
    ]
  }

  /**
   * Loop rotation animation continuously,
   * each time it reaches the end, it resets and begins again from the start.
   */

  const startRotation = useCallback((): void => {
    timer.setValue(0)
    Animated.loop(rotation).start()
  }, [rotation, timer])

  /**
   * Reset the timer and loop the animation again on each update
   */
  useEffect(() => {
    startRotation()
  }, [startRotation])

  return (
    <View size={size} showLayer={showLayer}>
      <Layer as={Animated.View} size={size} style={layerStyle}>
        <Container as={Animated.View} size={size}>
          <Line as={Animated.View} size={size} />
        </Container>
      </Layer>
    </View>
  )
}
Example #12
Source File: index.tsx    From krmanga with MIT License 5 votes vote down vote up
function LightDrawer({ chapterList, bookInfo, headerHeight, drawerX, goMangaView, hideDrawer }: IProps) {

    const spinValue = useRef(new Animated.Value(0)).current;
    const spin = spinValue.interpolate({
        inputRange: [0, 1],
        outputRange: ["0deg", "360deg"]
    });

    const [isSpin, setIsSpin] = useState<boolean>(true);
    const [data, setData] = useState<IChapter[] | []>([]);

    useEffect(() => {
        setData(chapterList);
    }, [chapterList]);

    const onPress = () => {
        if (typeof hideDrawer === "function") {
            hideDrawer();
        }
    };

    const renderItem = ({ item }: ListRenderItemInfo<IChapter>) => {
        return (
            <Item data={item} goMangaView={goMangaView} />
        );
    };

    const reverse = () => {
        if (isSpin) {
            Animated.timing(
                spinValue,
                {
                    toValue: 0.5,
                    duration: 250,
                    easing: Easing.linear,
                    useNativeDriver: true
                }
            ).start();
        } else {
            Animated.timing(
                spinValue,
                {
                    toValue: 1,
                    duration: 250,
                    easing: Easing.linear,
                    useNativeDriver: true
                }
            ).start(() => spinValue.setValue(0));
        }

        setData([...data.reverse()]);
        setIsSpin(!isSpin);
    };

    return (
        <Animated.View style={[styles.wrapper, {
            transform: [{ translateX: drawerX }]
        }]}>
            <View style={styles.container}>
                <Touchable onPress={onPress} style={styles.transparentView} />
                <View style={[styles.listContainer, {
                    paddingTop: headerHeight
                }]}>
                    <Header bookInfo={bookInfo} spin={spin} reverse={reverse} />
                    <FlatList
                        data={data}
                        renderItem={renderItem}
                        keyExtractor={(item, key) => `item-${key}-item-${item.id}`}
                    />
                </View>
            </View>
        </Animated.View>
    );
}
Example #13
Source File: index.tsx    From krmanga with MIT License 5 votes vote down vote up
function DarkDrawer({ chapterList, bookInfo, headerHeight, drawerX, goMangaView, hideDrawer }: IProps) {

    const spinValue = useRef(new Animated.Value(0)).current;
    const spin = spinValue.interpolate({
        inputRange: [0, 1],
        outputRange: ["0deg", "360deg"]
    });

    const [isSpin, setIsSpin] = useState<boolean>(true);
    const [data, setData] = useState<IChapter[] | []>([]);

    useEffect(() => {
        setData(chapterList);
    }, [chapterList]);

    const onPress = () => {
        if (typeof hideDrawer === "function") {
            hideDrawer();
        }
    };

    const renderItem = ({ item }: ListRenderItemInfo<IChapter>) => {
        return (
            <Item data={item} goMangaView={goMangaView} />
        );
    };

    const reverse = () => {
        if (isSpin) {
            Animated.timing(
                spinValue,
                {
                    toValue: 0.5,
                    duration: 250,
                    easing: Easing.linear,
                    useNativeDriver: true
                }
            ).start();
        } else {
            Animated.timing(
                spinValue,
                {
                    toValue: 1,
                    duration: 250,
                    easing: Easing.linear,
                    useNativeDriver: true
                }
            ).start(() => spinValue.setValue(0));
        }
        setData([...data.reverse()]);
        setIsSpin(!isSpin);
    };

    return (
        <Animated.View style={[styles.wrapper, {
            transform: [{ translateX: drawerX }]
        }]}>
            <View style={styles.container}>
                <View style={[styles.listContainer, {
                    paddingTop: headerHeight
                }]}>
                    <Header bookInfo={bookInfo} spin={spin} reverse={reverse} />
                    <FlatList
                        data={data}
                        renderItem={renderItem}
                        keyExtractor={(item, key) => `item-${key}-item-${item.id}`}
                    />
                </View>
                <Touchable onPress={onPress} style={styles.transparentView} />
            </View>
        </Animated.View>
    );
}
Example #14
Source File: SegmentedControl.tsx    From lexicon with MIT License 5 votes vote down vote up
export function SegmentedControl<T>(props: Props<T>) {
  const styles = useStyles();
  const { spacing } = useTheme();

  const { values, selectedIndex, width, labelExtractor, onItemPress } = props;

  const positionValue = useRef(new Animated.Value(0)).current;

  const onSegmentSelected = (value: T, index: number) => {
    onItemPress(value, index);
    Animated.timing(positionValue, {
      toValue: index,
      duration: 100,
      easing: Easing.ease,
      useNativeDriver: false,
    }).start(() => {});
  };

  // 20 is coming from the text line height (medium)
  // SPACING.s (4) is coming from the segment padding
  const IOS_SEGMENT_HEIGHT = 20 + spacing.s * 2;
  // SPACING.xxl (24) is coming from the padding inside the Home Screen (Left and Right)
  // SPACING.s (4) is coming from the initial (left) padding of the Segmented Control container
  const IOS_SEGMENT_WIDTH =
    (width - (spacing.xxl * 2 + spacing.s)) / values.length;

  return (
    <View style={styles.container}>
      {ios && (
        <Animated.View
          style={[
            {
              transform: [
                {
                  translateX: positionValue.interpolate({
                    inputRange: [0, values.length - 1],
                    // 4 is coming from initial padding of the container
                    outputRange: [4, (values.length - 1) * IOS_SEGMENT_WIDTH],
                  }),
                },
              ],
            },
            styles.animatedSegment,
            {
              height: IOS_SEGMENT_HEIGHT,
              width: IOS_SEGMENT_WIDTH,
            },
          ]}
        />
      )}
      {values.map((value, index) => (
        <TouchableOpacity
          key={index}
          style={[styles.item, selectedIndex === index && styles.itemChosen]}
          onPress={() => onSegmentSelected(value, index)}
          disabled={selectedIndex === index}
        >
          <Text
            style={[styles.text, selectedIndex === index && styles.textChosen]}
          >
            {labelExtractor(value)}
          </Text>
        </TouchableOpacity>
      ))}
    </View>
  );
}
Example #15
Source File: index.tsx    From jellyfin-audio-player with MIT License 5 votes vote down vote up
function NowPlaying() {
    const { index, track } = useCurrentTrack();
    const { buffered, duration, position } = useProgress();
    const defaultStyles = useDefaultStyles();
    const previousIndex = usePrevious(index);
    const navigation = useNavigation<MusicNavigationProp>();

    const bufferAnimation = useRef(new Animated.Value(0));
    const progressAnimation = useRef(new Animated.Value(0));

    const openNowPlayingModal = useCallback(() => {
        navigation.navigate('Player');
    }, [navigation]);

    useEffect(() => {
        const hasChangedTrack = previousIndex !== index || duration === 0;

        Animated.timing(bufferAnimation.current, {
            toValue: calculateProgressTranslation(buffered, duration, NOW_PLAYING_POPOVER_WIDTH),
            duration: hasChangedTrack ? 0 : 500,
            useNativeDriver: true,
            easing: Easing.ease,
        }).start();
        Animated.timing(progressAnimation.current, {
            toValue: calculateProgressTranslation(position, duration, NOW_PLAYING_POPOVER_WIDTH),
            duration: hasChangedTrack ? 0 : 500,
            useNativeDriver: true,
        }).start();
    }, [buffered, duration, position, index, previousIndex]);

    if (!track) {
        return null;
    }

    return (
        <Container>
            <ShadowOverlay pointerEvents='none'>
                <Shadow distance={30} viewStyle={{ alignSelf: 'stretch', flexBasis: '100%' }} startColor="#00000017">
                    <View style={{ flex: 1, borderRadius: 8 }} />
                </Shadow>
            </ShadowOverlay>
            <ColoredBlurView style={{ borderRadius: 8 }}>
                <InnerContainer onPress={openNowPlayingModal} activeOpacity={0.5}>
                    <ShadowWrapper size="small">
                        <Cover source={{ uri: (track.artwork || '') as string }} style={defaultStyles.imageBackground} />
                    </ShadowWrapper>
                    <TrackNameContainer>
                        <Text numberOfLines={1}>{track.title}</Text>
                        <Text style={{ opacity: 0.5 }} numberOfLines={1}>
                            {track.artist}{track.album ? ` — ${track.album}` : ''}
                        </Text>
                    </TrackNameContainer>
                    <ActionButton>
                        <SelectActionButton />
                    </ActionButton>
                    <ProgressTrack
                        style={{ transform: [{ translateX: bufferAnimation.current }]}}
                        opacity={0.15}
                        stroke={4}
                    />
                    <ProgressTrack
                        style={{ transform: [{ translateX: progressAnimation.current }]}}
                        stroke={4}
                    />
                </InnerContainer>
            </ColoredBlurView>
        </Container>
    );
}
Example #16
Source File: AddToBagButton.tsx    From RNChallenge_2 with MIT License 5 votes vote down vote up
AddToBagButton = ({addToCart}: Props) => {
  const shakeAnim = useRef(new Animated.Value(0)).current;
  const shakeAnimation = () => {
    Animated.sequence([
      Animated.timing(shakeAnim, {
        toValue: 3,
        duration: 100,
        easing: Easing.cubic,
        useNativeDriver: true,
      }),
      Animated.timing(shakeAnim, {
        toValue: -3,
        duration: 100,
        easing: Easing.cubic,
        useNativeDriver: true,
      }),
      Animated.timing(shakeAnim, {
        toValue: 3,
        duration: 100,
        easing: Easing.cubic,
        useNativeDriver: true,
      }),
      Animated.timing(shakeAnim, {
        toValue: 0,
        duration: 100,
        easing: Easing.cubic,
        useNativeDriver: true,
      }),
    ]).start();
    addToCart();
  };
  return (
    <TouchableOpacity
      onPress={shakeAnimation}
      activeOpacity={0.7}
      style={[styles.container]}>
      <Animated.Image
        resizeMethod={'resize'}
        resizeMode={'contain'}
        style={{
          width: 25,
          height: 25,
          transform: [{translateY: shakeAnim}],
        }}
        source={require('../Assets/Icons/bag.png')}
      />
      <Text style={[styles.Add]}>Add To Bag</Text>
    </TouchableOpacity>
  );
}
Example #17
Source File: index.tsx    From expo-dark-mode-switch with MIT License 5 votes vote down vote up
MoonIcon = ({ isClicked, ...props }) => {
  const value = createAnimatedValue(isClicked);

  React.useEffect(() => {
    Animated.timing(value.current, {
      toValue: isClicked ? 1 : 0,
      duration: transitionTime,
      useNativeDriver: false,
      easing: Easing.inOut(Easing.linear)
    }).start();
  }, [isClicked]);

  return (
    <Animated.View
      style={[
        styles.moonSvg,
        {
          opacity: value.current,
          transform: [
            {
              translateY: value.current.interpolate({
                inputRange: [0, 1],
                outputRange: [30, 0],
              }),
            },
          ],
        },
        props.style,
      ]}
    >
      <SVG.Svg
        pointerEvents="none"
        {...props}
        style={[styles.moonSvg, props.style]}
        viewBox="0 0 30 32"
      >
        <SVG.Path
          fill="white"
          d="M22.592 21.504q3.36 0 6.56-1.792-1.344 4.64-5.184 7.616t-8.8 2.976q-6.016 0-10.304-4.288t-4.288-10.336q0-4.928 2.976-8.768t7.584-5.216q-1.792 3.2-1.792 6.56 0 5.504 3.904 9.376t9.344 3.872z"
        />
      </SVG.Svg>
    </Animated.View>
  );
}
Example #18
Source File: ConcentricCircles.tsx    From companion-kit with MIT License 5 votes vote down vote up
export function ConcentricCircle(props: ConcentricCircleProps) {
    const { strokeBgColor, strokeColor, strokeWidth, radiusDecremented, radius, progress, animationStep } = props;
    const diameter = radiusDecremented * 2;
    const length = Math.round(diameter * Math.PI);

    const offset = React.useMemo(() => {
        if (!animationStep) {
            return null;
        }

        const startProgress = progress - animationStep;
        return new Animated.Value(getOffset(diameter, startProgress));
    }, [animationStep, diameter, progress]);

    React.useEffect(() => {
        if (offset != null) {
            Animated.timing(offset, {
                toValue: getOffset(diameter, progress),
                duration: 1500,
                easing: Easing.inOut(Easing.ease),
            }).start();
        }
    }, [progress]);

    return (
        <>
            <Circle
                cx={radius}
                cy={radius}
                r={radiusDecremented}
                strokeWidth={strokeWidth}
                stroke={strokeBgColor}
                fill="none"
            />
            <AnimatedContainer
                fill="none"
                cx={radius}
                cy={radius}
                r={radiusDecremented}
                strokeWidth={strokeWidth}
                stroke={strokeColor}
                strokeDasharray={length}
                strokeDashoffset={offset}
                origin={`${radius}, ${radius}`}
                rotation={-90}
            />
        </>
    );
}
Example #19
Source File: TransitionSpecs.tsx    From nlw2-proffy with MIT License 5 votes vote down vote up
FadeOutToBottomAndroidSpec: TransitionSpec = {
  animation: 'timing',
  config: {
    duration: 150,
    easing: Easing.in(Easing.linear),
  },
}
Example #20
Source File: TransitionSpecs.tsx    From nlw2-proffy with MIT License 5 votes vote down vote up
FadeInFromBottomAndroidSpec: TransitionSpec = {
  animation: 'timing',
  config: {
    duration: 350,
    easing: Easing.out(Easing.poly(5)),
  },
}
Example #21
Source File: FeedSideBar.tsx    From react-native-tiktok-clone with MIT License 5 votes vote down vote up
FeedSideBar: React.FC<Props> = (props) => {
  // Animate spinning song cover
  const spinValue = useRef(new Animated.Value(0)).current;
  const spin = spinValue.interpolate({
    inputRange: [0, 1],
    outputRange: ['0deg', '360deg'],
  });
  useEffect(() => {
    Animated.loop(
      Animated.timing(spinValue, {
        toValue: 1,
        duration: 11000,
        easing: Easing.linear,
        useNativeDriver: true,
      }),
    ).start();
  }, []);

  let abbrLoveCount = abbreviateNum(props.love);

  const onLovePress = useCallback(() => { props.onLoveReact(props.feedId) }, []);

  return (
    <View style={props.style}>
      <Image
        source={require('../../assets/icons/profile_img_frame.png')}
        style={styles.profImageFrame}
      />
      <Image source={{ uri: props.accountAvatar }} style={styles.profImage} />
      <View style={styles.icon}>
        <TouchableOpacity onPress={onLovePress}>
          <Image
            source={require('../../assets/icons/love.png')}
            style={[styles.iconImg, props.isLoved && styles.loved]}
          />
        </TouchableOpacity>
      </View>
      <Text style={styles.text}>{abbrLoveCount}</Text>
      <View style={styles.icon}>
        <TouchableOpacity>
          <Image
            source={require('../../assets/icons/comment.png')}
            style={styles.iconImg}
          />
        </TouchableOpacity>
      </View>
      <Text style={styles.text}>{props.comment}</Text>
      <View style={styles.icon}>
        <TouchableOpacity>
          <Image
            source={require('../../assets/icons/share.png')}
            style={styles.iconImg}
          />
        </TouchableOpacity>
      </View>
      <Text style={styles.text}>{props.share}</Text>
      <Animated.Image
        source={require('../../assets/icons/song_cover.png')}
        style={[styles.songCover, { transform: [{ rotate: spin }] }]}
      />
    </View>
  );
}
Example #22
Source File: TextField.tsx    From rn-credit-card with MIT License 4 votes vote down vote up
TextField = React.forwardRef<TextInput, Props>((props, ref) => {
  const {
    label,
    errorText,
    value,
    endEnhancer,
    style,
    onBlur,
    onFocus,
    ...restOfProps
  } = props
  const { inputColors = {}, fonts, overrides } = useContext(LibraryContext)
  const {
    errored: errorColor = '#B00020',
    focused: focusedColor = '#080F9C',
    regular: regularColor = '#B9C4CA',
  } = inputColors

  const [isFocused, setIsFocused] = useState(false)

  const focusAnim = useRef(new Animated.Value(0)).current

  useEffect(() => {
    Animated.timing(focusAnim, {
      toValue: isFocused || !!value ? 1 : 0,
      duration: 150,
      easing: Easing.bezier(0.4, 0, 0.2, 1),
      useNativeDriver: true,
    }).start()
  }, [focusAnim, isFocused, value])

  let color = isFocused ? focusedColor : regularColor
  if (errorText) {
    color = errorColor
  }

  return (
    <View style={style}>
      <TextInput
        style={[
          styles.input,
          {
            fontFamily: fonts.regular,
          },
          overrides.input,
          {
            borderColor: color,
          },
        ]}
        ref={ref}
        {...restOfProps}
        value={value}
        onBlur={(event) => {
          setIsFocused(false)
          onBlur?.(event)
        }}
        onFocus={(event) => {
          setIsFocused(true)
          onFocus?.(event)
        }}
      />
      <TouchableWithoutFeedback
        onPress={() => {
          // @ts-ignore
          ref?.current?.focus()
        }}
      >
        <Animated.View
          style={[
            styles.labelContainer,
            {
              transform: [
                {
                  scale: focusAnim.interpolate({
                    inputRange: [0, 1],
                    outputRange: [1, 0.75],
                  }),
                },
                {
                  translateY: focusAnim.interpolate({
                    inputRange: [0, 1],
                    outputRange: [24, -12],
                  }),
                },
                {
                  translateX: focusAnim.interpolate({
                    inputRange: [0, 1],
                    outputRange: [16, 0],
                  }),
                },
              ],
            },
            overrides.labelContainer,
          ]}
        >
          <Text
            style={[
              styles.label,
              overrides.inputLabel,
              {
                color,
              },
            ]}
            bold
          >
            {label}
            {errorText ? '*' : ''}
          </Text>
        </Animated.View>
      </TouchableWithoutFeedback>
      {endEnhancer && (
        <View style={styles.enhancerContainer}>{endEnhancer}</View>
      )}
      {!!errorText && (
        <Text style={[styles.error, overrides.errorText]}>{errorText}</Text>
      )}
    </View>
  )
})
Example #23
Source File: Ripple.tsx    From mobile with Apache License 2.0 4 votes vote down vote up
Ripple = ({
  children,
  disabled,
  rippleColor = 'rgb(0, 0, 0)',
  rippleCentered = false,
  rippleOpacity = 0.3,
  rippleExpandDuration = 500,
  rippleFadeDuration = 200,
  rippleContainerBorderRadius = 0,
  rippleSize = 0,
  ...touchableWithoutFeedbackProps
}: RippleProps) => {
  const [width, setWidth] = useState(0);
  const [height, setHeight] = useState(0);
  const uuid = useRef(0);
  const [ripples, setRipples] = useState<AnimatedRipple[]>([]);
  const [fadings, setFadings] = useState<number[]>([]);

  const startFade = useCallback(
    (ripple: AnimatedRipple, duration: number) => {
      if (fadings.indexOf(ripple.id) >= 0) {
        return;
      }
      setFadings([...fadings, ripple.id]);
      Animated.timing(ripple.fadeAnimatedValue, {
        toValue: 1,
        easing: Easing.out(Easing.ease),
        duration,
        useNativeDriver: true,
      }).start(() => {
        setRipples(ripples.filter(item => item !== ripple));
      });
    },
    [fadings, ripples],
  );

  const startExpand = useCallback(
    (event: GestureResponderEvent) => {
      if (!width || !height) {
        return;
      }

      const timestamp = Date.now();
      if (ripples.length > 0 && timestamp < ripples[ripples.length - 1].timestamp + DEBOUNCE) {
        return;
      }

      const w2 = 0.5 * width;
      const h2 = 0.5 * height;

      const {locationX, locationY} = rippleCentered ? {locationX: w2, locationY: h2} : event.nativeEvent;

      const offsetX = Math.abs(w2 - locationX);
      const offsetY = Math.abs(h2 - locationY);

      const radius = rippleSize > 0 ? 0.5 * rippleSize : Math.sqrt((w2 + offsetX) ** 2 + (h2 + offsetY) ** 2);

      const id = uuid.current;
      uuid.current += 1;

      const ripple: AnimatedRipple = {
        id,
        locationX,
        locationY,
        radius,
        timestamp,
        expandAnimatedValue: new Animated.Value(0),
        fadeAnimatedValue: new Animated.Value(0),
      };

      Animated.timing(ripple.expandAnimatedValue, {
        toValue: 1,
        easing: Easing.out(Easing.ease),
        duration: rippleExpandDuration,
        useNativeDriver: true,
      }).start();

      setRipples(ripples.concat(ripple));
    },
    [height, rippleCentered, rippleExpandDuration, rippleSize, ripples, width],
  );

  const onLayout = useCallback(
    (event: LayoutChangeEvent) => {
      const {
        nativeEvent: {
          layout: {height, width},
        },
      } = event;
      setWidth(width);
      setHeight(height);
      touchableWithoutFeedbackProps.onLayout?.(event);
    },
    [touchableWithoutFeedbackProps.onLayout],
  );

  const onPressIn = useCallback(
    (event: GestureResponderEvent) => {
      startExpand(event);
      touchableWithoutFeedbackProps.onPressIn?.(event);
    },
    [startExpand, touchableWithoutFeedbackProps.onPressIn],
  );

  const onPressOut = useCallback(
    (event: GestureResponderEvent) => {
      ripples.forEach(ripple => startFade(ripple, rippleFadeDuration + rippleExpandDuration / 2));
      touchableWithoutFeedbackProps.onPressOut?.(event);
    },
    [rippleExpandDuration, rippleFadeDuration, ripples, startFade, touchableWithoutFeedbackProps.onPressOut],
  );

  const onPress = useCallback(
    (event: GestureResponderEvent) => {
      requestAnimationFrame(() => {
        touchableWithoutFeedbackProps.onPress?.(event);
      });
    },
    [touchableWithoutFeedbackProps.onPress],
  );

  const renderRipple = useCallback(
    ({locationX, locationY, radius, id, expandAnimatedValue, fadeAnimatedValue}: AnimatedRipple) => {
      const rippleStyle = {
        top: locationY - RADIUS,
        [I18nManager.isRTL ? 'right' : 'left']: locationX - RADIUS,
        backgroundColor: rippleColor,
        transform: [
          {
            scale: expandAnimatedValue.interpolate({
              inputRange: [0, 1],
              outputRange: [0.5 / RADIUS, radius / RADIUS],
            }),
          },
        ],
        opacity: fadeAnimatedValue.interpolate({
          inputRange: [0, 1],
          outputRange: [rippleOpacity, 0],
        }),
      };
      return <Animated.View style={[styles.ripple, rippleStyle]} key={id} />;
    },
    [rippleColor, rippleOpacity],
  );

  const style = useMemo(
    () => [
      styles.container,
      {
        borderRadius: rippleContainerBorderRadius,
      },
    ],
    [rippleContainerBorderRadius],
  );

  return (
    <TouchableWithoutFeedback
      {...touchableWithoutFeedbackProps}
      disabled={disabled}
      onPressIn={onPressIn}
      onPressOut={onPressOut}
      onPress={onPress}
      onLayout={onLayout}
    >
      <Animated.View pointerEvents="box-only">
        <View style={style}>{ripples.map(renderRipple)}</View>
        {children}
      </Animated.View>
    </TouchableWithoutFeedback>
  );
}
Example #24
Source File: index.tsx    From react-native-gifted-charts with MIT License 4 votes vote down vote up
BarChart = (props: PropTypes) => {
  const scrollRef = useRef();
  const [points, setPoints] = useState('');
  const [selectedIndex, setSelectedIndex] = useState(-1);
  const showLine = props.showLine || false;
  const initialSpacing =
    props.initialSpacing === 0 ? 0 : props.initialSpacing || 40;
  const data = useMemo(() => props.data || [], [props.data]);
  const lineData = props.lineData || data;
  const defaultLineConfig = {
    initialSpacing: initialSpacing,
    curved: false,
    isAnimated: false,
    thickness: 1,
    color: 'black',
    hideDataPoints: false,
    dataPointsShape: 'circular',
    dataPointsWidth: 2,
    dataPointsHeight: 2,
    dataPointsColor: 'black',
    dataPointsRadius: 3,
    textColor: 'gray',
    textFontSize: 10,
    textShiftX: 0,
    textShiftY: 0,
    shiftY: 0,
    delay: 0,
    startIndex: 0,
    endIndex: lineData.length - 1,
  };
  const lineConfig = props.lineConfig
    ? {
        initialSpacing:
          props.lineConfig.initialSpacing === 0
            ? 0
            : props.lineConfig.initialSpacing ||
              defaultLineConfig.initialSpacing,
        curved: props.lineConfig.curved || defaultLineConfig.curved,
        isAnimated: props.lineConfig.isAnimated || defaultLineConfig.isAnimated,
        thickness: props.lineConfig.thickness || defaultLineConfig.thickness,
        color: props.lineConfig.color || defaultLineConfig.color,
        hideDataPoints:
          props.lineConfig.hideDataPoints || defaultLineConfig.hideDataPoints,
        dataPointsShape:
          props.lineConfig.dataPointsShape || defaultLineConfig.dataPointsShape,
        dataPointsHeight:
          props.lineConfig.dataPointsHeight ||
          defaultLineConfig.dataPointsHeight,
        dataPointsWidth:
          props.lineConfig.dataPointsWidth || defaultLineConfig.dataPointsWidth,
        dataPointsColor:
          props.lineConfig.dataPointsColor || defaultLineConfig.dataPointsColor,
        dataPointsRadius:
          props.lineConfig.dataPointsRadius ||
          defaultLineConfig.dataPointsRadius,
        textColor: props.lineConfig.textColor || defaultLineConfig.textColor,
        textFontSize:
          props.lineConfig.textFontSize || defaultLineConfig.textFontSize,
        textShiftX: props.lineConfig.textShiftX || defaultLineConfig.textShiftX,
        textShiftY: props.lineConfig.textShiftY || defaultLineConfig.textShiftY,
        shiftY: props.lineConfig.shiftY || defaultLineConfig.shiftY,
        delay: props.lineConfig.delay || defaultLineConfig.delay,
        startIndex: props.lineConfig.startIndex || defaultLineConfig.startIndex,
        endIndex:
          props.lineConfig.endIndex === 0
            ? 0
            : props.lineConfig.endIndex || defaultLineConfig.endIndex,
      }
    : defaultLineConfig;
  const containerHeight = props.height || 200;
  const noOfSections = props.noOfSections || 10;
  const horizSections = [{value: '0'}];
  const horizSectionsBelow = [];
  const stepHeight = props.stepHeight || containerHeight / noOfSections;
  const spacing = props.spacing === 0 ? 0 : props.spacing || 20;
  const labelWidth = props.labelWidth || 0;
  const scrollToEnd = props.scrollToEnd || false;
  const scrollAnimation = props.scrollAnimation === false ? false : true;
  const labelsExtraHeight = props.labelsExtraHeight || 0;

  let totalWidth = spacing;
  let maxItem = 0,
    minItem = 0;
  if (props.stackData) {
    props.stackData.forEach(stackItem => {
      // console.log('stackItem', stackItem);
      let stackSum = stackItem.stacks.reduce(
        (acc, stack) => acc + stack.value,
        0,
      );
      // console.log('stackSum--->', stackSum);
      if (stackSum > maxItem) {
        maxItem = stackSum;
      }
      if (stackSum < minItem) {
        minItem = stackSum;
      }
      totalWidth +=
        (stackItem.stacks[0].barWidth || props.barWidth || 30) + spacing;
      // console.log('totalWidth for stack===', totalWidth);
    });
  } else {
    data.forEach((item: itemType) => {
      if (item.value > maxItem) {
        maxItem = item.value;
      }
      if (item.value < minItem) {
        minItem = item.value;
      }
      totalWidth +=
        (item.barWidth || props.barWidth || 30) +
        (item.spacing === 0 ? 0 : item.spacing || spacing);
      // console.log('totalWidth for bar===', totalWidth);
    });
  }
  if (props.showFractionalValues || props.roundToDigits) {
    maxItem *= 10 * (props.roundToDigits || 1);
    maxItem = maxItem + (10 - (maxItem % 10));
    maxItem /= 10 * (props.roundToDigits || 1);
    maxItem = parseFloat(maxItem.toFixed(props.roundToDigits || 1));
    if (minItem !== 0) {
      minItem *= 10 * (props.roundToDigits || 1);
      minItem = minItem - (10 + (minItem % 10));
      minItem /= 10 * (props.roundToDigits || 1);
      minItem = parseFloat(minItem.toFixed(props.roundToDigits || 1));
    }
  } else {
    maxItem = maxItem + (10 - (maxItem % 10));
    if (minItem !== 0) {
      minItem = minItem - (10 + (minItem % 10));
    }
  }

  const maxValue = props.maxValue || maxItem;
  const minValue = props.minValue || minItem;

  const stepValue = props.stepValue || maxValue / noOfSections;
  const noOfSectionsBelowXAxis =
    props.noOfSectionsBelowXAxis || -minValue / stepValue;
  const disableScroll = props.disableScroll || false;
  const showScrollIndicator = props.showScrollIndicator || false;
  // const oldData = props.oldData || [];
  const side = props.side || '';
  const rotateLabel = props.rotateLabel || false;
  const isAnimated = props.isAnimated || false;
  const animationDuration = props.animationDuration || 800;
  // const animationEasing = props.animationEasing || Easing.ease;
  const opacity = props.opacity || 1;
  const isThreeD = props.isThreeD || false;

  const showVerticalLines = props.showVerticalLines || false;
  const rulesThickness =
    props.rulesThickness === 0 ? 0 : props.rulesThickness || 1;
  const rulesColor = props.rulesColor || 'lightgray';
  const verticalLinesThickness =
    props.verticalLinesThickness === 0 ? 0 : props.verticalLinesThickness || 1;
  const verticalLinesHeight = props.verticalLinesHeight;
  const verticalLinesColor = props.verticalLinesColor || 'lightgray';
  const verticalLinesZIndex = props.verticalLinesZIndex || -1;
  let verticalLinesAr = [];
  props.noOfVerticalLines
    ? (verticalLinesAr = [...Array(props.noOfVerticalLines).keys()])
    : (verticalLinesAr = [
        ...Array(props.stackData ? props.stackData.length : data.length).keys(),
      ]);
  const verticalLinesSpacing = props.verticalLinesSpacing || 0;

  const showYAxisIndices = props.showYAxisIndices || false;
  const showXAxisIndices = props.showXAxisIndices || false;
  const yAxisIndicesHeight = props.yAxisIndicesHeight || 2;
  const xAxisIndicesHeight = props.xAxisIndicesHeight || 2;
  const yAxisIndicesWidth = props.yAxisIndicesWidth || 4;
  const xAxisIndicesWidth = props.xAxisIndicesWidth || 4;
  const xAxisIndicesColor = props.xAxisIndicesColor || 'black';
  const yAxisIndicesColor = props.yAxisIndicesColor || 'black';

  const yAxisLabelPrefix = props.yAxisLabelPrefix || '';
  const yAxisLabelSuffix = props.yAxisLabelSuffix || '';
  const yAxisSide = props.yAxisSide || 'left';

  const xAxisThickness =
    props.xAxisThickness === 0
      ? props.xAxisThickness
      : props.xAxisThickness || 1;
  const xAxisColor = props.xAxisColor || 'black';

  const hideRules = props.hideRules || false;

  const yAxisThickness =
    props.yAxisThickness === 0
      ? props.yAxisThickness
      : props.yAxisThickness || 1;
  const yAxisColor = props.yAxisColor || 'black';
  const yAxisTextStyle = props.yAxisTextStyle;
  const yAxisTextNumberOfLines = props.yAxisTextNumberOfLines || 1;
  const xAxisTextNumberOfLines = props.xAxisTextNumberOfLines || 1;
  const yAxisLabelContainerStyle = props.yAxisLabelContainerStyle;
  const horizontalRulesStyle = props.horizontalRulesStyle;
  const showFractionalValues = props.showFractionalValues || false;
  const yAxisLabelWidth = props.yAxisLabelWidth || 35;
  const hideYAxisText = props.hideYAxisText || false;

  const backgroundColor = props.backgroundColor || 'transparent';
  const horizontal = props.horizontal || false;
  const yAxisAtTop = props.yAxisAtTop || false;
  const intactTopLabel = props.intactTopLabel || false;
  const hideOrigin = props.hideOrigin || false;

  const rulesType = props.rulesType || 'line';
  const xAxisType = props.xAxisType || 'solid';
  const dashWidth = props.dashWidth === 0 ? 0 : props.dashWidth || 4;
  const dashGap = props.dashGap === 0 ? 0 : props.dashGap || 8;

  const heightValue = useMemo(() => new Animated.Value(0), []);
  const opacValue = useMemo(() => new Animated.Value(0), []);
  const widthValue = useMemo(() => new Animated.Value(0), []);
  const autoShiftLabels = props.autoShiftLabels || false;

  const labelsAppear = useCallback(() => {
    opacValue.setValue(0);
    Animated.timing(opacValue, {
      toValue: 1,
      duration: 500,
      easing: Easing.ease,
      useNativeDriver: false,
    }).start();
  }, [opacValue]);
  // const moveBar = useCallback(() => {
  //   heightValue.setValue(0);
  //   Animated.timing(heightValue, {
  //     toValue: 1,
  //     duration: animationDuration,
  //     easing: animationEasing,
  //     useNativeDriver: false,
  //   }).start();
  // }, [animationDuration, animationEasing, heightValue]);

  const decreaseWidth = useCallback(() => {
    widthValue.setValue(0);
    Animated.timing(widthValue, {
      toValue: 1,
      duration: animationDuration,
      easing: Easing.linear,
      useNativeDriver: false,
    }).start();
  }, [animationDuration, widthValue]);
  // console.log('olddata', oldData);

  useEffect(() => {
    if (showLine) {
      let pp = '';
      if (!lineConfig.curved) {
        for (let i = 0; i < lineData.length; i++) {
          if (i < lineConfig.startIndex || i > lineConfig.endIndex) continue;
          const currentBarWidth =
            (data && data[i] && data[i].barWidth) || props.barWidth || 30;
          pp +=
            'L' +
            (yAxisLabelWidth +
              lineConfig.initialSpacing +
              6 -
              (initialSpacing - currentBarWidth / 2) -
              lineConfig.dataPointsWidth / 2 +
              (currentBarWidth + spacing) * i) +
            ' ' +
            (containerHeight -
              lineConfig.shiftY -
              (lineData[i].value * containerHeight) / maxValue) +
            ' ';
        }
        setPoints(pp.replace('L', 'M'));
      } else {
        let p1Array = [];
        for (let i = 0; i < lineData.length; i++) {
          if (i < lineConfig.startIndex || i > lineConfig.endIndex) continue;
          const currentBarWidth =
            (data && data[i] && data[i].barWidth) || props.barWidth || 30;
          p1Array.push([
            yAxisLabelWidth +
              lineConfig.initialSpacing +
              6 -
              (initialSpacing - currentBarWidth / 2) -
              lineConfig.dataPointsWidth / 2 +
              (currentBarWidth + spacing) * i,
            containerHeight -
              lineConfig.shiftY -
              (lineData[i].value * containerHeight) / maxValue,
          ]);
          let xx = svgPath(p1Array, bezierCommand);
          setPoints(xx);
        }
      }
      if (lineConfig.isAnimated) {
        setTimeout(() => decreaseWidth(), lineConfig.delay || 0);
      }
    }
    // moveBar();
    setTimeout(() => labelsAppear(), animationDuration);
  }, [
    animationDuration,
    containerHeight,
    data,
    lineData,
    decreaseWidth,
    initialSpacing,
    labelsAppear,
    lineConfig.initialSpacing,
    lineConfig.curved,
    lineConfig.dataPointsWidth,
    lineConfig.shiftY,
    lineConfig.isAnimated,
    lineConfig.delay,
    lineConfig.startIndex,
    lineConfig.endIndex,
    maxValue,
    // moveBar,
    props.barWidth,
    showLine,
    spacing,
    yAxisLabelWidth,
  ]);

  const defaultReferenceConfig = {
    thickness: rulesThickness,
    width: horizontal
      ? props.width || totalWidth
      : (props.width || totalWidth) + 11,
    color: 'black',
    type: rulesType,
    dashWidth: dashWidth,
    dashGap: dashGap,
    labelText: '',
    labelTextStyle: null,
  };

  const showReferenceLine1 = props.showReferenceLine1 || false;
  const referenceLine1Position =
    props.referenceLine1Position === 0
      ? 0
      : props.referenceLine1Position || containerHeight / 2;
  const referenceLine1Config = props.referenceLine1Config
    ? {
        thickness: props.referenceLine1Config.thickness || rulesThickness,
        width: horizontal
          ? props.referenceLine1Config.width || props.width || totalWidth
          : (props.referenceLine1Config.width || props.width || totalWidth) +
            11,
        color: props.referenceLine1Config.color || 'black',
        type: props.referenceLine1Config.type || rulesType,
        dashWidth: props.referenceLine1Config.dashWidth || dashWidth,
        dashGap: props.referenceLine1Config.dashGap || dashGap,
        labelText:
          props.referenceLine1Config.labelText ||
          defaultReferenceConfig.labelText,
        labelTextStyle:
          props.referenceLine1Config.labelTextStyle ||
          defaultReferenceConfig.labelTextStyle,
      }
    : defaultReferenceConfig;

  const showReferenceLine2 = props.showReferenceLine2 || false;
  const referenceLine2Position =
    props.referenceLine2Position === 0
      ? 0
      : props.referenceLine2Position || (3 * containerHeight) / 2;
  const referenceLine2Config = props.referenceLine2Config
    ? {
        thickness: props.referenceLine2Config.thickness || rulesThickness,
        width: horizontal
          ? props.referenceLine2Config.width || props.width || totalWidth
          : (props.referenceLine2Config.width || props.width || totalWidth) +
            11,
        color: props.referenceLine2Config.color || 'black',
        type: props.referenceLine2Config.type || rulesType,
        dashWidth: props.referenceLine2Config.dashWidth || dashWidth,
        dashGap: props.referenceLine2Config.dashGap || dashGap,
        labelText:
          props.referenceLine2Config.labelText ||
          defaultReferenceConfig.labelText,
        labelTextStyle:
          props.referenceLine2Config.labelTextStyle ||
          defaultReferenceConfig.labelTextStyle,
      }
    : defaultReferenceConfig;

  const showReferenceLine3 = props.showReferenceLine3 || false;
  const referenceLine3Position =
    props.referenceLine3Position === 0
      ? 0
      : props.referenceLine3Position || containerHeight / 3;
  const referenceLine3Config = props.referenceLine3Config
    ? {
        thickness: props.referenceLine3Config.thickness || rulesThickness,
        width: horizontal
          ? props.referenceLine3Config.width || props.width || totalWidth
          : (props.referenceLine3Config.width || props.width || totalWidth) +
            11,
        color: props.referenceLine3Config.color || 'black',
        type: props.referenceLine3Config.type || rulesType,
        dashWidth: props.referenceLine3Config.dashWidth || dashWidth,
        dashGap: props.referenceLine3Config.dashGap || dashGap,
        labelText:
          props.referenceLine3Config.labelText ||
          defaultReferenceConfig.labelText,
        labelTextStyle:
          props.referenceLine3Config.labelTextStyle ||
          defaultReferenceConfig.labelTextStyle,
      }
    : defaultReferenceConfig;

  horizSections.pop();
  for (let i = 0; i <= noOfSections; i++) {
    let value = maxValue - stepValue * i;
    if (props.showFractionalValues || props.roundToDigits) {
      value = parseFloat(value.toFixed(props.roundToDigits || 1));
    }
    horizSections.push({
      value: props.yAxisLabelTexts
        ? props.yAxisLabelTexts[noOfSections - i] ?? value.toString()
        : value.toString(),
    });
  }
  if (noOfSectionsBelowXAxis) {
    for (let i = 1; i <= noOfSectionsBelowXAxis; i++) {
      let value = stepValue * -i;
      if (props.showFractionalValues || props.roundToDigits) {
        value = parseFloat(value.toFixed(props.roundToDigits || 1));
      }
      horizSectionsBelow.push({
        value: props.yAxisLabelTexts
          ? props.yAxisLabelTexts[noOfSectionsBelowXAxis - i] ??
            value.toString()
          : value.toString(),
      });
    }
  }

  const animatedHeight = heightValue.interpolate({
    inputRange: [0, 1],
    outputRange: ['0%', '100%'],
  });
  const appearingOpacity = opacValue.interpolate({
    inputRange: [0, 1],
    outputRange: [0, 1],
  });

  const animatedWidth = widthValue.interpolate({
    inputRange: [0, 1],
    outputRange: [0, totalWidth],
  });

  const getLabel = (val, index) => {
    let label = '';
    if (
      showFractionalValues ||
      (props.yAxisLabelTexts && props.yAxisLabelTexts[index] !== undefined)
    ) {
      if (val) {
        label = val;
      } else {
        label = '0';
      }
    } else {
      if (val) {
        label = val.toString().split('.')[0];
      } else {
        label = '0';
      }
    }

    return yAxisLabelPrefix + label + yAxisLabelSuffix;
  };

  const renderHorizSections = () => {
    return (
      <>
        {horizSections.map((sectionItems, index) => {
          return (
            <View
              key={index}
              style={[
                styles.horizBar,
                {
                  width: horizontal
                    ? props.width || Math.min(300, totalWidth)
                    : props.width || totalWidth + 11,
                },
                yAxisSide === 'right' && {transform: [{rotateY: '180deg'}]},
                horizontalRulesStyle,
              ]}>
              <View
                style={[
                  styles.leftLabel,
                  {
                    borderRightWidth: yAxisThickness,
                    borderColor: yAxisColor,
                  },
                  horizontal &&
                    !yAxisAtTop && {
                      transform: [
                        {
                          translateX:
                            (props.width || Math.min(300, totalWidth)) +
                            yAxisThickness,
                        },
                      ],
                    },
                  {
                    height:
                      index === noOfSections ? stepHeight / 2 : stepHeight,
                    width: yAxisLabelWidth,
                  },
                  yAxisLabelContainerStyle,
                ]}
              />
              <View
                style={[
                  index === noOfSections
                    ? styles.lastLeftPart
                    : styles.leftPart,
                  {backgroundColor: backgroundColor},
                ]}>
                {index === noOfSections ? (
                  <Rule
                    config={{
                      thickness: xAxisThickness,
                      color: xAxisColor,
                      width: horizontal
                        ? props.width || Math.min(300, totalWidth)
                        : (props.width || totalWidth) + 11,
                      dashWidth: dashWidth,
                      dashGap: dashGap,
                      type: xAxisType,
                    }}
                  />
                ) : hideRules ? null : (
                  <Rule
                    config={{
                      thickness: rulesThickness,
                      color: rulesColor,
                      width: horizontal
                        ? props.width || Math.min(300, totalWidth)
                        : (props.width || totalWidth) + 11,
                      dashWidth: dashWidth,
                      dashGap: dashGap,
                      type: rulesType,
                    }}
                  />
                )}
              </View>
            </View>
          );
        })}

        {
          /***********************************************************************************************/
          /**************************      Render the y axis labels separately      **********************/
          /***********************************************************************************************/
          props.hideAxesAndRules !== true &&
            !hideYAxisText &&
            horizSections.map((sectionItems, index) => {
              let label = getLabel(sectionItems.value, index);
              if (hideOrigin && index === horizSections.length - 1) {
                label = '';
              }
              return (
                <View
                  key={index}
                  style={[
                    styles.horizBar,
                    styles.leftLabel,
                    {
                      position: 'absolute',
                      zIndex: 1,
                      top: stepHeight * index,
                      width: yAxisLabelWidth,
                      height:
                        index === noOfSections ? stepHeight / 2 : stepHeight,
                    },
                    yAxisSide === 'right' && {
                      transform: [
                        {
                          translateX:
                            (props.width ? props.width : totalWidth) - 30,
                        },
                        {rotateY: '180deg'},
                      ],
                    },
                    horizontal &&
                      !yAxisAtTop && {
                        transform: [
                          {
                            translateX:
                              (props.width || Math.min(300, totalWidth)) +
                              yAxisThickness +
                              yAxisLabelWidth,
                          },
                        ],
                      },
                    yAxisLabelContainerStyle,
                  ]}>
                  <Text
                    numberOfLines={yAxisTextNumberOfLines}
                    ellipsizeMode={'clip'}
                    style={[
                      yAxisTextStyle,
                      yAxisSide === 'right' && {
                        transform: [{rotateY: '180deg'}],
                      },
                      index === noOfSections && {
                        marginBottom: stepHeight / -2,
                      },
                    ]}>
                    {label}
                  </Text>
                </View>
              );
            })
          /***********************************************************************************************/
          /***********************************************************************************************/
        }
        {horizSectionsBelow.map((sectionItems, index) => {
          return (
            <View
              key={index}
              style={[
                styles.horizBar,
                {
                  width: horizontal
                    ? props.width || totalWidth
                    : props.width || totalWidth + 11,
                },
                yAxisSide === 'right' && {transform: [{rotateY: '180deg'}]},
                index === 0 && {marginTop: stepHeight / 2},
              ]}>
              <View
                style={[
                  styles.leftLabel,
                  {
                    borderRightWidth: yAxisThickness,
                    borderColor: yAxisColor,
                  },
                  horizontal &&
                    !yAxisAtTop && {
                      transform: [{translateX: totalWidth + yAxisThickness}],
                    },
                  {
                    height: index === 0 ? stepHeight * 1.5 : stepHeight,
                    width: yAxisLabelWidth,
                  },
                  index === 0 && {marginTop: -stepHeight / 2},
                ]}
              />
              <View
                style={[styles.leftPart, {backgroundColor: backgroundColor}]}>
                {hideRules ? null : (
                  <Rule
                    config={{
                      thickness: rulesThickness,
                      color: rulesColor,
                      width: horizontal
                        ? props.width || totalWidth
                        : (props.width || totalWidth) + 11,
                      dashWidth: dashWidth,
                      dashGap: dashGap,
                      type: rulesType,
                    }}
                  />
                )}
              </View>
            </View>
          );
        })}
        {
          /***********************************************************************************************/
          /*************************      Render the y axis labels below origin      *********************/
          /***********************************************************************************************/
          props.hideAxesAndRules !== true &&
            !hideYAxisText &&
            horizSectionsBelow.map((sectionItems, index) => {
              let label = getLabel(
                horizSectionsBelow[horizSectionsBelow.length - 1 - index].value,
                index,
              );
              return (
                <View
                  key={index}
                  style={[
                    styles.horizBar,
                    styles.leftLabel,
                    {
                      position: 'absolute',
                      zIndex: 1,
                      bottom: stepHeight * (index - 1),
                      width: yAxisLabelWidth,
                      height:
                        index === noOfSections ? stepHeight / 2 : stepHeight,
                    },
                    yAxisSide === 'right' && {
                      transform: [
                        {
                          translateX:
                            (props.width ? props.width : totalWidth) - 30,
                        },
                        {rotateY: '180deg'},
                      ],
                    },
                    yAxisLabelContainerStyle,
                  ]}>
                  <Text
                    numberOfLines={yAxisTextNumberOfLines}
                    ellipsizeMode={'clip'}
                    style={[
                      yAxisTextStyle,
                      yAxisSide === 'right' && {
                        transform: [{rotateY: '180deg'}],
                      },
                      index === noOfSections && {
                        marginBottom: stepHeight / -2,
                      },
                    ]}>
                    {label}
                  </Text>
                </View>
              );
            })
          /***********************************************************************************************/
          /***********************************************************************************************/
        }

        {
          /***********************************************************************************************/
          /*************************      Render the reference lines separately      *********************/
          /***********************************************************************************************/
          props.hideAxesAndRules !== true &&
            !hideYAxisText &&
            horizSections.map((sectionItems, index) => {
              let label = getLabel(sectionItems.value, index);
              if (hideOrigin && index === horizSections.length - 1) {
                label = '';
              }
              return (
                <View
                  key={index}
                  style={[
                    styles.horizBar,
                    styles.leftLabel,
                    {
                      position: 'absolute',
                      zIndex: 1,
                      top: stepHeight * index,
                      width: yAxisLabelWidth,
                      height:
                        index === noOfSections ? stepHeight / 2 : stepHeight,
                    },
                    yAxisSide === 'right' && {
                      transform: [
                        {
                          translateX:
                            (props.width ? props.width : totalWidth) - 30,
                        },
                        {rotateY: '180deg'},
                      ],
                    },
                  ]}>
                  {index === noOfSections && showReferenceLine1 ? (
                    <View
                      style={{
                        position: 'absolute',
                        bottom:
                          (referenceLine1Position * containerHeight) / maxValue,
                        left:
                          yAxisSide === 'right'
                            ? yAxisLabelWidth + yAxisThickness
                            : yAxisLabelWidth + yAxisThickness - 5,
                      }}>
                      <Rule config={referenceLine1Config} />
                      {referenceLine1Config.labelText ? (
                        <Text
                          style={[
                            {position: 'absolute'},
                            yAxisSide === 'right' && {
                              transform: [{rotateY: '180deg'}],
                            },
                            referenceLine1Config.labelTextStyle,
                          ]}>
                          {referenceLine1Config.labelText}
                        </Text>
                      ) : null}
                    </View>
                  ) : null}
                  {index === noOfSections && showReferenceLine2 ? (
                    <View
                      style={{
                        position: 'absolute',
                        bottom:
                          (referenceLine2Position * containerHeight) / maxValue,
                        left:
                          yAxisSide === 'right'
                            ? yAxisLabelWidth + yAxisThickness
                            : yAxisLabelWidth + yAxisThickness - 5,
                      }}>
                      <Rule config={referenceLine2Config} />
                      {referenceLine2Config.labelText ? (
                        <Text
                          style={[
                            {position: 'absolute'},
                            yAxisSide === 'right' && {
                              transform: [{rotateY: '180deg'}],
                            },
                            referenceLine2Config.labelTextStyle,
                          ]}>
                          {referenceLine2Config.labelText}
                        </Text>
                      ) : null}
                    </View>
                  ) : null}
                  {index === noOfSections && showReferenceLine3 ? (
                    <View
                      style={{
                        position: 'absolute',
                        bottom:
                          (referenceLine3Position * containerHeight) / maxValue,
                        left:
                          yAxisSide === 'right'
                            ? yAxisLabelWidth + yAxisThickness
                            : yAxisLabelWidth + yAxisThickness - 5,
                      }}>
                      <Rule config={referenceLine3Config} />
                      {referenceLine3Config.labelText ? (
                        <Text
                          style={[
                            {position: 'absolute'},
                            yAxisSide === 'right' && {
                              transform: [{rotateY: '180deg'}],
                            },
                            referenceLine3Config.labelTextStyle,
                          ]}>
                          {referenceLine3Config.labelText}
                        </Text>
                      ) : null}
                    </View>
                  ) : null}
                </View>
              );
            })
          /***********************************************************************************************/
          /***********************************************************************************************/
        }
      </>
    );
  };

  const renderSpecificVerticalLines = (dataForRender: any) => {
    return dataForRender.map((item: any, index: number) => {
      if (item.showVerticalLine) {
        const currentBarWidth = item.barWidth || props.barWidth || 30;
        return (
          <Rect
            x={
              yAxisLabelWidth +
              6 -
              (item.verticalLineThickness || 1) / 2 -
              1 -
              (initialSpacing - currentBarWidth / 2) +
              (currentBarWidth + spacing) * index
            }
            y={
              containerHeight -
              lineConfig.shiftY -
              (item.value * containerHeight) / maxValue +
              9
            }
            width={item.verticalLineThickness || 1}
            height={
              (item.value * containerHeight) / maxValue + lineConfig.shiftY
            }
            fill={item.verticalLineColor || 'lightgray'}
          />
        );
      }
      return null;
    });
  };

  const renderDataPoints = () => {
    return lineData.map((item: any, index: number) => {
      if (index < lineConfig.startIndex || index > lineConfig.endIndex) {
        return null;
      }
      // console.log('comes in');
      const currentBarWidth = item.barWidth || props.barWidth || 30;
      if (lineConfig.dataPointsShape === 'rectangular') {
        return (
          <Fragment key={index}>
            <Rect
              x={
                yAxisLabelWidth +
                lineConfig.initialSpacing +
                6 -
                (initialSpacing - currentBarWidth / 2) -
                lineConfig.dataPointsWidth +
                (currentBarWidth + spacing) * index
              }
              y={
                containerHeight -
                lineConfig.shiftY -
                lineConfig.dataPointsHeight / 2 -
                (item.value * containerHeight) / maxValue
              }
              width={lineConfig.dataPointsWidth}
              height={lineConfig.dataPointsHeight}
              fill={lineConfig.dataPointsColor}
            />
            {item.dataPointText && (
              <CanvasText
                fill={item.textColor || lineConfig.textColor}
                fontSize={item.textFontSize || lineConfig.textFontSize}
                x={
                  yAxisLabelWidth +
                  lineConfig.initialSpacing +
                  6 -
                  (initialSpacing - currentBarWidth / 2) -
                  lineConfig.dataPointsWidth +
                  (currentBarWidth + spacing) * index +
                  (item.textShiftX || lineConfig.textShiftX || 0)
                }
                y={
                  containerHeight -
                  lineConfig.shiftY -
                  lineConfig.dataPointsHeight / 2 -
                  (item.value * containerHeight) / maxValue +
                  (item.textShiftY || lineConfig.textShiftY || 0)
                }>
                {item.dataPointText}
              </CanvasText>
            )}
          </Fragment>
        );
      }
      return (
        <Fragment key={index}>
          <Circle
            cx={
              yAxisLabelWidth +
              lineConfig.initialSpacing +
              6 -
              (initialSpacing - currentBarWidth / 2) -
              lineConfig.dataPointsWidth / 2 +
              (currentBarWidth + spacing) * index
            }
            cy={
              containerHeight -
              lineConfig.shiftY -
              (item.value * containerHeight) / maxValue
            }
            r={lineConfig.dataPointsRadius}
            fill={lineConfig.dataPointsColor}
          />
          {item.dataPointText && (
            <CanvasText
              fill={item.textColor || lineConfig.textColor}
              fontSize={item.textFontSize || lineConfig.textFontSize}
              x={
                yAxisLabelWidth +
                lineConfig.initialSpacing +
                6 -
                (initialSpacing - currentBarWidth / 2) -
                lineConfig.dataPointsWidth +
                (currentBarWidth + spacing) * index +
                (item.textShiftX || lineConfig.textShiftX || 0)
              }
              y={
                containerHeight -
                lineConfig.shiftY -
                lineConfig.dataPointsHeight / 2 -
                (item.value * containerHeight) / maxValue +
                (item.textShiftY || lineConfig.textShiftY || 0)
              }>
              {item.dataPointText}
            </CanvasText>
          )}
        </Fragment>
      );
    });
  };
  const renderSpecificDataPoints = dataForRender => {
    return dataForRender.map((item: any, index: number) => {
      const currentBarWidth = item.barWidth || props.barWidth || 30;
      if (item.showDataPoint) {
        if (item.dataPointShape === 'rectangular') {
          return (
            <Fragment key={index}>
              <Rect
                x={
                  initialSpacing -
                  (item.dataPointWidth || 2) / 2 -
                  1 +
                  (currentBarWidth + spacing) * index
                }
                y={
                  containerHeight -
                  lineConfig.shiftY -
                  (item.dataPointHeight || 2) / 2 +
                  10 -
                  (item.value * containerHeight) / maxValue
                }
                width={item.dataPointWidth || 2}
                height={item.dataPointHeight || 2}
                fill={item.dataPointColor || 'black'}
              />
              {item.dataPointText && (
                <CanvasText
                  fill={item.textColor || 'black'}
                  fontSize={item.textFontSize || 10}
                  x={
                    initialSpacing -
                    (item.dataPointWidth || 2) +
                    spacing * index +
                    (item.textShiftX || lineConfig.textShiftX || 0)
                  }
                  y={
                    containerHeight -
                    lineConfig.shiftY -
                    (item.dataPointHeight || 2) / 2 +
                    10 -
                    (item.value * containerHeight) / maxValue +
                    (item.textShiftY || lineConfig.textShiftY || 0)
                  }>
                  {item.dataPointText}
                </CanvasText>
              )}
            </Fragment>
          );
        } else {
          return (
            <Fragment key={index}>
              <Circle
                cx={
                  initialSpacing -
                  (item.dataPointWidth || 2) / 2 +
                  spacing * index
                }
                cy={
                  containerHeight -
                  lineConfig.shiftY +
                  10 -
                  (item.value * containerHeight) / maxValue
                }
                r={item.dataPointRadius || 3}
                fill={item.dataPointColor || 'black'}
              />
              {item.dataPointText && (
                <CanvasText
                  fill={item.textColor || 'black'}
                  fontSize={item.textFontSize || 10}
                  x={
                    initialSpacing -
                    (item.dataPointWidth || 2) +
                    spacing * index +
                    (item.textShiftX || lineConfig.textShiftX || 0)
                  }
                  y={
                    containerHeight -
                    lineConfig.shiftY -
                    (item.dataPointHeight || 2) / 2 +
                    10 -
                    (item.value * containerHeight) / maxValue +
                    (item.textShiftY || lineConfig.textShiftY || 0)
                  }>
                  {item.dataPointText}
                </CanvasText>
              )}
            </Fragment>
          );
        }
      }
      return null;
    });
  };

  const renderAnimatedLine = () => {
    // console.log('animatedWidth is-------->', animatedWidth);
    return (
      <Animated.View
        style={{
          position: 'absolute',
          height: containerHeight + 10,
          bottom: 60, //stepHeight * -0.5 + xAxisThickness,
          width: animatedWidth,
          zIndex: -1,
          // backgroundColor: 'wheat',
        }}>
        <Svg>
          <Path
            d={points}
            fill="none"
            stroke={lineConfig.color}
            strokeWidth={lineConfig.thickness}
          />

          {renderSpecificVerticalLines(data)}

          {!lineConfig.hideDataPoints
            ? renderDataPoints()
            : renderSpecificDataPoints(data)}
        </Svg>
      </Animated.View>
    );
  };

  const renderLine = () => {
    return (
      <View
        style={{
          position: 'absolute',
          height: containerHeight + 10,
          bottom: 60, //stepHeight * -0.5 + xAxisThickness,
          width: totalWidth,
          zIndex: -1,
          // backgroundColor: 'rgba(200,150,150,0.1)'
        }}>
        <Svg>
          <Path
            d={points}
            fill="none"
            stroke={lineConfig.color}
            strokeWidth={lineConfig.thickness}
          />
          {renderSpecificVerticalLines(data)}

          {!lineConfig.hideDataPoints
            ? renderDataPoints()
            : renderSpecificDataPoints(data)}
        </Svg>
      </View>
    );
  };

  return (
    <View
      style={[
        styles.container,
        {
          height:
            containerHeight +
            horizSectionsBelow.length * stepHeight +
            labelsExtraHeight,
        },
        yAxisSide === 'right' && {marginLeft: yAxisLabelWidth + yAxisThickness},
        props.width && !horizontal && {width: props.width},
        horizontal && {transform: [{rotate: '90deg'}, {translateY: 15}]},
      ]}>
      {props.hideAxesAndRules !== true && renderHorizSections()}
      <ScrollView
        ref={scrollRef}
        onTouchStart={evt => {
          if (props.renderTooltip) {
            setSelectedIndex(-1);
          }
        }}
        onContentSizeChange={() => {
          if (scrollRef.current && scrollToEnd) {
            scrollRef.current.scrollToEnd({animated: scrollAnimation});
          }
        }}
        style={[
          {
            marginLeft:
              yAxisSide === 'right' ? -yAxisLabelWidth + 10 : yAxisLabelWidth,
            position: 'absolute',
            bottom: stepHeight * -0.5 - 60 + xAxisThickness,
          },
          props.width && {width: props.width - 11},
          horizontal && {width: props.width || Math.min(300, totalWidth)},
        ]}
        scrollEnabled={!disableScroll}
        contentContainerStyle={[
          {
            // backgroundColor: 'yellow',
            height:
              containerHeight +
              130 +
              horizSectionsBelow.length * stepHeight +
              labelsExtraHeight,
            paddingLeft: initialSpacing,
            paddingBottom:
              horizSectionsBelow.length * stepHeight + labelsExtraHeight,
            alignItems: 'flex-end',
          },
          !props.width && {width: totalWidth},
        ]}
        showsHorizontalScrollIndicator={showScrollIndicator}
        indicatorStyle={props.indicatorColor}
        horizontal
        // data={props.stackData || data}
        keyExtractor={(item, index) => index.toString()}>
        <Fragment>
          {showVerticalLines &&
            verticalLinesAr.map((item: itemType, index: number) => {
              let totalSpacing = initialSpacing;
              if (verticalLinesSpacing) {
                totalSpacing = verticalLinesSpacing * (index + 1);
              } else {
                if (props.stackData) {
                  totalSpacing +=
                    (props.stackData[0].barWidth || props.barWidth || 30) / 2;
                } else {
                  totalSpacing +=
                    (props.data[0].barWidth || props.barWidth || 30) / 2;
                }
                for (let i = 0; i < index; i++) {
                  let actualSpacing = spacing;
                  if (props.stackData) {
                    if (i >= props.stackData.length - 1) {
                      actualSpacing += (props.barWidth || 30) / 2;
                    } else {
                      if (
                        props.stackData[i].spacing ||
                        props.stackData[i].spacing === 0
                      ) {
                        actualSpacing = props.stackData[i].spacing;
                      }
                      if (props.stackData[i + 1].barWidth) {
                        actualSpacing += props.stackData[i + 1].barWidth;
                      } else {
                        actualSpacing += props.barWidth || 30;
                      }
                    }
                  } else {
                    if (i >= props.data.length - 1) {
                      actualSpacing += (props.barWidth || 30) / 2;
                    } else {
                      if (
                        props.data[i].spacing ||
                        props.data[i].spacing === 0
                      ) {
                        console.log('here for index ' + index + ' and i ' + i);
                        actualSpacing = props.data[i].spacing;
                      }
                      if (props.data[i + 1].barWidth) {
                        actualSpacing += props.data[i + 1].barWidth;
                      } else {
                        actualSpacing += props.barWidth || 30;
                      }
                    }
                  }
                  console.log('i = ' + i + ' actualSpacing ' + actualSpacing);
                  totalSpacing += actualSpacing;
                }
              }

              return (
                <View
                  key={index}
                  style={{
                    position: 'absolute',
                    zIndex: verticalLinesZIndex || -1,
                    marginBottom: xAxisThickness,
                    height:
                      verticalLinesHeight ||
                      containerHeight + 15 - xAxisThickness,
                    width: verticalLinesThickness,
                    backgroundColor: verticalLinesColor,
                    bottom: 60 + labelsExtraHeight,
                    left: totalSpacing,
                  }}
                />
              );
            })}
          {showLine
            ? lineConfig.isAnimated
              ? renderAnimatedLine()
              : renderLine()
            : null}
          {props.stackData
            ? props.stackData.map((item, index) => {
                return (
                  <RenderStackBars
                    key={index}
                    stackData={props.stackData}
                    item={item}
                    index={index}
                    containerHeight={containerHeight}
                    maxValue={maxValue}
                    spacing={item.spacing === 0 ? 0 : item.spacing || spacing}
                    propSpacing={spacing}
                    xAxisThickness={xAxisThickness}
                    barWidth={props.barWidth}
                    opacity={opacity}
                    disablePress={item.disablePress || props.disablePress}
                    rotateLabel={rotateLabel}
                    showXAxisIndices={showXAxisIndices}
                    xAxisIndicesHeight={xAxisIndicesHeight}
                    xAxisIndicesWidth={xAxisIndicesWidth}
                    xAxisIndicesColor={xAxisIndicesColor}
                    horizontal={horizontal}
                    intactTopLabel={intactTopLabel}
                    barBorderRadius={props.barBorderRadius}
                    barBackgroundPattern={props.barBackgroundPattern}
                    patternId={props.patternId}
                    label={
                      item.label ||
                      (props.xAxisLabelTexts && props.xAxisLabelTexts[index]
                        ? props.xAxisLabelTexts[index]
                        : '')
                    }
                    labelTextStyle={
                      item.labelTextStyle || props.xAxisLabelTextStyle
                    }
                    xAxisTextNumberOfLines={xAxisTextNumberOfLines}
                    renderTooltip={props.renderTooltip}
                    initialSpacing={initialSpacing}
                    selectedIndex={selectedIndex}
                    setSelectedIndex={setSelectedIndex}
                    activeOpacity={props.activeOpacity || 0.2}
                  />
                );
              })
            : data.map((item, index) => (
                <RenderBars
                  key={index}
                  item={item}
                  index={index}
                  containerHeight={containerHeight}
                  maxValue={maxValue}
                  spacing={item.spacing === 0 ? 0 : item.spacing || spacing}
                  propSpacing={spacing}
                  side={side}
                  data={data}
                  barWidth={props.barWidth}
                  sideWidth={props.sideWidth}
                  labelWidth={labelWidth}
                  opacity={opacity}
                  isThreeD={isThreeD}
                  isAnimated={isAnimated}
                  animationDuration={animationDuration}
                  rotateLabel={rotateLabel}
                  animatedHeight={animatedHeight}
                  appearingOpacity={appearingOpacity}
                  roundedTop={props.roundedTop}
                  roundedBottom={props.roundedBottom}
                  disablePress={props.disablePress}
                  frontColor={props.frontColor}
                  sideColor={props.sideColor}
                  topColor={props.topColor}
                  showGradient={props.showGradient}
                  gradientColor={props.gradientColor}
                  activeOpacity={props.activeOpacity}
                  cappedBars={props.cappedBars}
                  capThickness={props.capThickness}
                  capColor={props.capColor}
                  capRadius={props.capRadius}
                  showXAxisIndices={showXAxisIndices}
                  xAxisIndicesHeight={xAxisIndicesHeight}
                  xAxisIndicesWidth={xAxisIndicesWidth}
                  xAxisIndicesColor={xAxisIndicesColor}
                  horizontal={horizontal}
                  intactTopLabel={intactTopLabel}
                  barBorderRadius={props.barBorderRadius}
                  autoShiftLabels={autoShiftLabels}
                  barBackgroundPattern={props.barBackgroundPattern}
                  patternId={props.patternId}
                  barMarginBottom={props.barMarginBottom}
                  label={
                    item.label ||
                    (props.xAxisLabelTexts && props.xAxisLabelTexts[index]
                      ? props.xAxisLabelTexts[index]
                      : '')
                  }
                  labelTextStyle={
                    item.labelTextStyle || props.xAxisLabelTextStyle
                  }
                  onPress={props.onPress}
                  xAxisTextNumberOfLines={xAxisTextNumberOfLines}
                  renderTooltip={props.renderTooltip}
                  initialSpacing={initialSpacing}
                  selectedIndex={selectedIndex}
                  setSelectedIndex={setSelectedIndex}
                />
              ))}
        </Fragment>
      </ScrollView>
    </View>
  );
}
Example #25
Source File: DetailsHeader.tsx    From RNChallenge_2 with MIT License 4 votes vote down vote up
DetailsHeader = ({
  headerColor,
  images,
  id,
  shared,
  quandity = 0,
  goToCart,
}: Props) => {
  const {width, height} = useWindowDimensions();
  const navigation = useNavigation();
  const shakeAnim = useRef(new Animated.Value(0)).current;
  useEffect(() => {
    if (quandity > 0) {
      shakeAnimation();
    }
  }, [quandity]);
  const shakeAnimation = () => {
    Animated.sequence([
      Animated.timing(shakeAnim, {
        toValue: 3,
        duration: 100,
        easing: Easing.cubic,
        useNativeDriver: true,
      }),
      Animated.timing(shakeAnim, {
        toValue: -3,
        duration: 100,
        easing: Easing.cubic,
        useNativeDriver: true,
      }),
      Animated.timing(shakeAnim, {
        toValue: 3,
        duration: 100,
        easing: Easing.cubic,
        useNativeDriver: true,
      }),
      Animated.timing(shakeAnim, {
        toValue: 0,
        duration: 100,
        easing: Easing.cubic,
        useNativeDriver: true,
      }),
    ]).start();
  };
  return (
    <View>
      <View
        style={{
          width: width * 0.5,
          height: width * 0.5,
          backgroundColor: headerColor,
          top: -width * 0.1,
          position: 'absolute',
          left: -width * 0.25,
          borderRadius: (width * 0.6) / 2,
          transform: [{scaleX: 2.5}, {scaleY: 2.2}],
        }}
      />

      <View style={[styles.header]}>
        <TouchableOpacity
          onPress={() => {
            navigation.goBack();
          }}>
          <Image
            style={{
              width: 22,
              height: 22,
            }}
            source={require('../../Assets/Icons/back.png')}
          />
        </TouchableOpacity>
        <View
          style={{
            width: 70,
            justifyContent: 'space-between',
            alignItems: 'center',
            flexDirection: 'row',
          }}>
          <TouchableOpacity onPress={() => goToCart()} style={[styles.likeBtn]}>
            <Animated.View
              style={[
                styles.badge,
                {
                  transform: [{translateX: shakeAnim}],
                },
              ]}>
              <Text
                style={{
                  color: 'white',
                  fontSize: 5,
                  textAlign: 'center',
                  fontWeight: 'bold',
                }}>
                {quandity}
              </Text>
            </Animated.View>
            <Image
              style={{
                width: 15,
                height: 15,
              }}
              source={require('../../Assets/Icons/cart.png')}
            />
          </TouchableOpacity>
          <TouchableOpacity style={[styles.likeBtn]}>
            <Image
              style={{
                width: 15,
                height: 15,
              }}
              source={require('../../Assets/Icons/like.png')}
            />
          </TouchableOpacity>
        </View>
      </View>

      <Carousel
        id={id}
        shared={shared}
        activeColor={headerColor}
        backgroundColor={'transparent'}
        offset={75}
        height={height * 0.26}
        images={images}
      />
    </View>
  );
}
Example #26
Source File: DownloadIcon.tsx    From jellyfin-audio-player with MIT License 4 votes vote down vote up
function DownloadIcon({ trackId, size = 16, fill }: DownloadIconProps) {
    // determine styles
    const defaultStyles = useDefaultStyles();
    const iconFill = fill || defaultStyles.textQuarterOpacity.color;

    // Get download icon from state
    const entity = useTypedSelector((state) => state.downloads.entities[trackId]);
    const isQueued = useTypedSelector((state) => state.downloads.queued.includes(trackId));

    // Memoize calculations for radius and circumference of the circle
    const radius = useMemo(() => size / 2, [size]);
    const circumference = useMemo(() => radius * 2 * Math.PI, [radius]);

    // Initialize refs for the circle and the animated value
    const circleRef = useRef<Circle>(null);
    const offsetAnimation = useRef(new Animated.Value(entity?.progress || 0)).current;

    // Whenever the progress changes, trigger the animation
    useEffect(() => {
        Animated.timing(offsetAnimation, {
            toValue: (circumference * (1 - (entity?.progress || 0))),
            duration: 250,
            useNativeDriver: false,
            easing: Easing.ease,
        }).start();
    }, [entity?.progress, offsetAnimation, circumference]);

    // On mount, subscribe to changes in the animation value and then 
    // apply them to the circle using native props
    useEffect(() => {
        const subscription = offsetAnimation.addListener((offset) => {
            // @ts-expect-error undocumented functionality
            const setNativeProps = circleRef.current?.setNativeProps as (props: CircleProps) => void | undefined;
            setNativeProps?.({ strokeDashoffset: offset.value });
        });

        return () => offsetAnimation.removeListener(subscription);
    }, [offsetAnimation]);

    if (!entity && !isQueued) {
        return (
            <CloudIcon width={size} height={size} fill={iconFill} />
        );
    }

    if (entity?.isComplete) {
        return (
            <InternalDriveIcon width={size} height={size} fill={iconFill} />
        );
    }

    if (entity?.isFailed) {
        return (
            <CloudExclamationMarkIcon width={size} height={size} fill={iconFill} />
        );
    }

    if (isQueued || (!entity?.isFailed && !entity?.isComplete)) {
        return (
            <DownloadContainer>
                <Svg width={size} height={size} transform={[{ rotate: '-90deg' }]}>
                    <Circle
                        cx={radius}
                        cy={radius}
                        r={radius - 1}
                        stroke={iconFill}
                        // @ts-expect-error react-native-svg has outdated react-native typings
                        ref={circleRef}
                        strokeWidth={1.5}
                        strokeDasharray={[ circumference, circumference ]}
                        strokeDashoffset={circumference}
                        strokeLinecap='round'
                        fill='transparent'
                    />
                </Svg>
                <IconOverlay>
                    <CloudDownArrow width={size} height={size} fill={iconFill} />
                </IconOverlay>
            </DownloadContainer>
        );
    }

    return null;
}
Example #27
Source File: FlutterwaveCheckout.tsx    From flutterwave-react-native with MIT License 4 votes vote down vote up
FlutterwaveCheckout: React.FC<FlutterwaveCheckoutProps> = function FlutterwaveCheckout(props) {
  const {link, visible, onRedirect, onAbort} = props;
  const [show, setShow] = React.useState<boolean>(false);
  const webviewRef = React.useRef<WebView | null>(null);
  const animation = React.useRef<Animated.Value>(new Animated.Value(0));

  const animateIn = React.useCallback(() => {
    setShow(true);
    Animated.timing(animation.current, {
      toValue: 1,
      duration: 700,
      easing: Easing.in(Easing.elastic(0.72)),
      useNativeDriver: false,
    }).start();
  }, []);

  const animateOut = React.useCallback((): Promise<void> => {
    return new Promise(resolve => {
      Animated.timing(animation.current, {
        toValue: 0,
        duration: 400,
        useNativeDriver: false,
      }).start(() => {
        setShow(false);
        resolve();
      });
    })
  }, []);

  const handleReload = React.useCallback(() => {
    if (webviewRef.current) {
      webviewRef.current.reload();
    }
  }, []);

  const handleAbort = React.useCallback((confirmed: boolean = false) => {
    if (!confirmed) {
      Alert.alert('', 'Are you sure you want to cancel this payment?', [
        {text: 'No'},
        {
          text: 'Yes, Cancel',
          style: 'destructive',
          onPress: () => handleAbort(true),
        },
      ]);
      return;
    }
    // remove tx_ref and dismiss
    animateOut().then(onAbort);
  }, [onAbort, animateOut]);

  const handleNavigationStateChange = React.useCallback((ev: WebViewNavigation): boolean => {
    // cregex to check if redirect has occured on completion/cancel
    const rx = /\/flutterwave\.com\/rn-redirect/;
    // Don't end payment if not redirected back
    if (!rx.test(ev.url)) {
      return true;
    }
    // dismiss modal
    animateOut().then(() => {
      if (onRedirect) {
        onRedirect(getRedirectParams(ev.url))
      }
    });
    return false;
  }, [onRedirect]);

  const doAnimate = React.useCallback(() => {
    if (visible === show) {
      return;
    }
    if (visible) {
      return animateIn();
    }
    animateOut().then(() => {});
  }, [visible, show, animateOut, animateIn]);

  React.useEffect(() => {
    doAnimate();
    return () => {};
  }, [doAnimate]);

  const marginTop = animation.current.interpolate({
    inputRange: [0, 1],
    outputRange: [windowHeight, 0],
  });
  const opacity = animation.current.interpolate({
    inputRange: [0, 0.3, 1],
    outputRange: [0, 1, 1],
  });

  return (
    <Modal
      transparent={true}
      animated={false}
      hardwareAccelerated={false}
      visible={show}>
      <FlutterwaveCheckoutBackdrop onPress={() => handleAbort()} animation={animation.current} />
      <Animated.View
        style={[
          styles.webviewContainer,
          {
            marginTop,
            opacity
          }
        ]}
        testID='flw-checkout-dialog'
      >
        <WebView
          ref={webviewRef}
          source={{uri: link || ''}}
          style={styles.webview}
          startInLoadingState={true}
          scalesPageToFit={true}
          javaScriptEnabled={true}
          onShouldStartLoadWithRequest={handleNavigationStateChange}
          renderError={() => <FlutterwaveCheckoutError hasLink={!!link} onTryAgain={handleReload} />}
          renderLoading={() => <FlutterwaveCheckoutLoader />}
        />
      </Animated.View>
    </Modal>
  )
}
Example #28
Source File: index.tsx    From krmanga with MIT License 4 votes vote down vote up
function MangaView({
                       navigation, dispatch, isLogin, chapterList, bookInfo,
                       book_id, headerHeight, markRoast, chapter_num, episodeList, hasMore, loading,
                       currentChapterNum, pages
                   }: IProps) {

    const [endReached, setEndReached] = useState<boolean>(false);
    let [time, setTime] = useState<NodeJS.Timeout | null>(null);

    let flatListRef: FlatList<IEpisode> | null = null;
    const topPanelValue = useRef(new Animated.Value(0)).current;
    const bottomPanelValue = useRef(new Animated.Value(0)).current;
    const drawerX = useRef(new Animated.Value(-viewportWidth)).current;
    let panelEnable: boolean = true;


    useEffect(() => {
        loadData(true);
        return () => {
            StatusBar.setHidden(false);
            if (isLogin) {
                dispatch({
                    type: "mangaView/addHistory",
                    payload: {
                        book_id
                    }
                });
                dispatch({
                    type: "history/setScreenReload"
                });
                dispatch({
                    type: "downloadManage/setScreenReload"
                });
            }
            dispatch({
                type: "mangaView/setState",
                payload: {
                    ...initialState
                }
            });
        };
    }, []);

    const loadData = (refreshing: boolean, callback?: () => void) => {
        dispatch({
            type: "mangaView/fetchEpisodeList",
            payload: {
                refreshing,
                markRoast,
                chapter_num,
                book_id
            },
            callback
        });
    };

    const onEndReached = () => {
        if (!hasMore || loading) {
            return;
        }

        setEndReached(true);

        dispatch({
            type: "mangaView/fetchEpisodeList",
            payload: {
                book_id,
                chapter_num: currentChapterNum + 1
            },
            callback: () => {
                setEndReached(false);
            }
        });
    };

    const renderItem = ({ item }: ListRenderItemInfo<IEpisode>) => {
        return (
            <Item panelHandle={panelHandle} data={item} />
        );
    };

    const renderFooter = () => {
        if (endReached) {
            return <More />;
        }
        if (!hasMore) {
            return <End />;
        }

        return null;
    };

    const getItemLayout = (data: any, index: number) => {
        if (data[index] === undefined) {
            return { length: 0, offset: 0, index };
        }

        let offset = 0;
        const length = viewportWidth * data[index].multiple;

        for (let i = 0; i < index; i++) {
            offset += viewportWidth * data[i].multiple;
        }

        return { length: length, offset, index };
    };

    const scrollToIndex = (index: number) => {
        dispatch({
            type: "brief/setState",
            payload: {
                markChapterNum: episodeList[index].chapter_num,
                markRoast: episodeList[index].roast
            }
        });
        flatListRef?.scrollToIndex({ viewPosition: 0, index: index });
    };

    const lastChapter = () => {
        if (!loading) {
            dispatch({
                type: "mangaView/fetchEpisodeList",
                payload: {
                    refreshing: true,
                    book_id,
                    chapter_num: currentChapterNum - 1
                }
            });
        }
    };

    const nextChapter = () => {
        if (!loading) {
            dispatch({
                type: "mangaView/fetchEpisodeList",
                payload: {
                    refreshing: true,
                    book_id,
                    chapter_num: currentChapterNum + 1
                }
            });
        }
    };

    const showDrawer = () => {
        Animated.timing(drawerX, {
            toValue: 0,
            duration: 200,
            useNativeDriver: true
        }).start();
    };

    const hideDrawer = () => {
        Animated.timing(drawerX, {
            toValue: -viewportWidth,
            duration: 200,
            useNativeDriver: true
        }).start();
    };

    const hidePanel = () => {
        if (panelEnable) {
            Animated.parallel([
                Animated.timing(
                    topPanelValue,
                    {
                        toValue: -headerHeight - getStatusBarHeight(),
                        duration: 200,
                        easing: Easing.linear,
                        useNativeDriver: true
                    }
                ),
                Animated.timing(
                    bottomPanelValue,
                    {
                        toValue: hp(25),
                        duration: 200,
                        easing: Easing.linear,
                        useNativeDriver: true
                    }
                )
            ]).start(() => {
                StatusBar.setHidden(true);
                panelEnable = !panelEnable;
            });
        }
    };

    const showPanel = () => {
        if (!panelEnable) {
            Animated.parallel([
                Animated.timing(
                    topPanelValue,
                    {
                        toValue: 0,
                        duration: 200,
                        easing: Easing.linear,
                        useNativeDriver: true
                    }
                ),
                Animated.timing(
                    bottomPanelValue,
                    {
                        toValue: 0,
                        duration: 200,
                        easing: Easing.linear,
                        useNativeDriver: true
                    }
                )
            ]).start(() => {
                StatusBar.setHidden(false);
                panelEnable = !panelEnable;
            });
        }
    };

    const panelHandle = useCallback(() => {
        if (panelEnable) {
            hidePanel();
        } else {
            showPanel();
        }
    }, [panelEnable]);

    const debounce = (cb: any, wait = 250) => {
        if (time !== null) {
            clearTimeout(time);
        }

        let tempTime = setTimeout(() => {
            time = null;
            cb && cb();
        }, wait);

        setTime(tempTime);
    };

    const onScrollEndDrag = ({ nativeEvent }: NativeSyntheticEvent<NativeScrollEvent>) => {
        let offset_total = 0;
        let current_episode_total = episodeList[0].episode_total;
        let current_chapter_id = episodeList[0].chapter_id;
        let current_chapter_num = episodeList[0].chapter_num;
        let current_number = episodeList[0].number;
        let current_roast = episodeList[0].roast;
        let current_title = episodeList[0].title;
        for (let i = 0; i < episodeList.length; i++) {
            if (nativeEvent.contentOffset.y >= offset_total) {
                current_episode_total = episodeList[i].episode_total;
                current_chapter_id = episodeList[i].chapter_id;
                current_chapter_num = episodeList[i].chapter_num;
                current_number = episodeList[i].number;
                current_roast = episodeList[i].roast;
                current_title = episodeList[i].title;
            } else {
                break;
            }
            offset_total = offset_total + episodeList[i].multiple * viewportWidth;
        }

        debounce(() => {
            dispatch({
                type: "mangaView/setState",
                payload: {
                    currentEpisodeTotal: current_episode_total,
                    currentChapterId: current_chapter_id,
                    currentChapterNum: current_chapter_num,
                    currentNumber: current_number,
                    showCurrentNumber: current_number,
                    currentRoast: current_roast,
                    currentTitle: current_title
                }
            });
            dispatch({
                type: "brief/setState",
                payload: {
                    markChapterNum: current_chapter_num,
                    markRoast: current_roast
                }
            });
        });

        hidePanel();
    };

    const goMangaChapter = useCallback((item: IChapter) => {
        dispatch({
            type: "mangaView/fetchEpisodeList",
            payload: {
                refreshing: true,
                book_id,
                chapter_num: item.chapter_num,
                callback: () => hideDrawer
            }
        });
    }, []);

    return (
        episodeList.length > 0 ?
            <View>
                <StatusBar barStyle="light-content" />
                <TopCtrPanel
                    book_id={book_id}
                    topPanelValue={topPanelValue}
                    navigation={navigation}
                />
                <BottomCtrPanel
                    bottomPanelValue={bottomPanelValue}
                    scrollToIndex={scrollToIndex}
                    showDrawer={showDrawer}
                    lastChapter={lastChapter}
                    nextChapter={nextChapter}
                />
                <FlatList
                    ref={ref => (flatListRef = ref)}
                    data={episodeList}
                    keyExtractor={(item, key) => `item-${item.id}-key-${key}`}
                    renderItem={renderItem}
                    ListFooterComponent={renderFooter}
                    getItemLayout={getItemLayout}
                    onScrollEndDrag={onScrollEndDrag}
                    initialScrollIndex={pages.episode_offset - 1}
                    onEndReached={onEndReached}
                    onEndReachedThreshold={0.1}
                    extraData={endReached}
                />
                <DarkDrawer
                    chapterList={chapterList}
                    bookInfo={bookInfo}
                    headerHeight={headerHeight}
                    drawerX={drawerX}
                    hideDrawer={hideDrawer}
                    goMangaView={goMangaChapter}
                />
                <BottomStatusBar />
            </View> : null
    );
}
Example #29
Source File: index.tsx    From tiktok-clone with MIT License 4 votes vote down vote up
Feed: React.FC<Props> = ({ play, item }) => {
  const spinValue = new Animated.Value(0);

  Animated.loop(
    Animated.timing(spinValue, {
      toValue: 1,
      duration: 10000,
      easing: Easing.linear,
      useNativeDriver: true,
    }),
  ).start();

  const rotateProp = spinValue.interpolate({
    inputRange: [0, 1],
    outputRange: ['0deg', '360deg'],
  });

  return (
    <>
      <LinearGradient
        colors={['rgba(0,0,0,.3)', 'transparent']}
        style={{
          position: 'absolute',
          left: 0,
          right: 0,
          top: 0,
          height: '70%',
        }}
      />
      <Container>
        <Video
          source={{ uri: item.uri }}
          rate={1.0}
          volume={1.0}
          isMuted={false}
          resizeMode="cover"
          shouldPlay={play}
          isLooping
          style={{
            width: '100%',
            height: '100%',
          }}
        />
      </Container>
      <Details>
        <User>{item.username}</User>
        <Tags>{item.tags}</Tags>
        <MusicBox>
          <FontAwesome name="music" size={15} color="#f5f5f5" />
          <Music>{item.music}</Music>
        </MusicBox>
      </Details>
      <Actions>
        <BoxAction>
          <AntDesign
            style={{ alignSelf: 'center' }}
            name="heart"
            size={35}
            color="#fff"
          />
          <TextAction>{item.likes}</TextAction>
        </BoxAction>
        <BoxAction>
          <FontAwesome
            style={{ alignSelf: 'center' }}
            name="commenting"
            size={35}
            color="#fff"
          />
          <TextAction>{item.comments}</TextAction>
        </BoxAction>
        <BoxAction>
          <FontAwesome
            style={{ alignSelf: 'center' }}
            name="whatsapp"
            size={35}
            color="#06d755"
          />
          <TextAction>Share</TextAction>
        </BoxAction>
        <BoxAction>
          <Animated.View
            style={{
              borderRadius: 50,
              borderWidth: 12,
              borderColor: '#292929',
              transform: [
                {
                  rotate: play ? rotateProp : 0,
                },
              ],
            }}
          >
            <Image
              style={{
                width: 35,
                height: 35,
                borderRadius: 25,
              }}
              source={{
                uri: 'https://avatars3.githubusercontent.com/u/45601574',
              }}
            />
          </Animated.View>

          <Lottie
            source={musicFly}
            progress={play ? spinValue : 0}
            style={{ width: 150, position: 'absolute', bottom: 0, right: 0 }}
          />
        </BoxAction>
      </Actions>
      <LinearGradient
        colors={['transparent', 'rgba(0,0,0,.4)']}
        style={{
          position: 'absolute',
          left: 0,
          right: 0,
          bottom: 0,
          height: '50%',
        }}
      />
    </>
  );
}