Initial commit

This commit is contained in:
Samandar Turgunboyev
2025-08-26 16:26:59 +05:00
commit fd95422447
318 changed files with 38301 additions and 0 deletions

View File

@@ -0,0 +1,150 @@
"use client"
import React, { useEffect, useState, useCallback, useMemo } from "react"
import { type LayoutChangeEvent, View } from "react-native"
import Animated, {
useSharedValue,
useAnimatedStyle,
withRepeat,
withTiming,
Easing,
withSequence,
withDelay,
} from "react-native-reanimated"
import Auto from "svg/Auto"
import Avia from "svg/Avia"
type Props = {
type: "auto" | "avia"
}
const AnimatedIcon = ({ type }: Props) => {
const translateX = useSharedValue(0)
const translateY = useSharedValue(0)
const rotateY = useSharedValue(0)
const direction = useSharedValue(1)
const [containerWidth, setContainerWidth] = useState(0)
const iconSize = 40
const onLayout = useCallback((event: LayoutChangeEvent) => {
const { width } = event.nativeEvent.layout
setContainerWidth(width)
}, []);
const animationConfig = useMemo(() => ({
duration: 4000,
easing: Easing.linear,
rotationDuration: 300,
arcHeight: -30,
}), []);
const createXAnimation = useCallback((maxX: number) => {
return withRepeat(
withSequence(
withTiming(maxX, {
duration: animationConfig.duration,
easing: animationConfig.easing
}, () => {
direction.value = -1;
rotateY.value = withTiming(180, { duration: animationConfig.rotationDuration });
}),
withTiming(0, {
duration: animationConfig.duration,
easing: animationConfig.easing
}, () => {
direction.value = 1;
rotateY.value = withTiming(0, { duration: animationConfig.rotationDuration });
})
),
-1
);
}, [animationConfig, direction, rotateY]);
const createYAnimation = useCallback(() => {
if (type === "avia") {
return withRepeat(
withSequence(
withTiming(animationConfig.arcHeight, {
duration: animationConfig.duration / 2,
easing: Easing.out(Easing.quad),
}),
withTiming(0, {
duration: animationConfig.duration / 2,
easing: Easing.in(Easing.quad),
}),
withTiming(animationConfig.arcHeight, {
duration: animationConfig.duration / 2,
easing: Easing.out(Easing.quad),
}),
withTiming(0, {
duration: animationConfig.duration / 2,
easing: Easing.in(Easing.quad),
})
),
-1
);
}
return withTiming(0, { duration: 100 });
}, [type, animationConfig]);
useEffect(() => {
if (containerWidth === 0) return;
const maxX = containerWidth - iconSize;
translateX.value = createXAnimation(maxX);
translateY.value = createYAnimation();
}, [containerWidth, type, createXAnimation, createYAnimation, translateX, translateY]);
const animatedStyle = useAnimatedStyle(() => {
return {
transform: [
{ translateX: translateX.value },
{ translateY: translateY.value },
{ rotateY: `${rotateY.value}deg` },
],
}
});
const containerStyle = useMemo(() => ({
height: 100,
justifyContent: "center" as const,
backgroundColor: "transparent" as const,
position: "relative" as const,
}), []);
const trackStyle = useMemo(() => ({
height: 2,
backgroundColor: "#28A7E850",
position: "absolute" as const,
top: 25,
left: 0,
right: 0,
}), []);
const iconContainerStyle = useMemo(() => ({
position: "absolute" as const,
top: 0,
height: iconSize,
width: iconSize,
}), [iconSize]);
const renderIcon = useMemo(() => {
if (type === "auto") {
return <Auto color="#28A7E8" width={iconSize} height={iconSize} />;
}
return <Avia color="#28A7E8" width={iconSize} height={iconSize} />;
}, [type, iconSize]);
return (
<View onLayout={onLayout} style={containerStyle}>
<View style={trackStyle} />
<Animated.View style={[iconContainerStyle, animatedStyle]}>
{renderIcon}
</Animated.View>
</View>
)
}
export default AnimatedIcon;