47 lines
1.0 KiB
TypeScript
47 lines
1.0 KiB
TypeScript
import { useEffect } from 'react';
|
|
import { Image, ImageStyle, StyleProp } from 'react-native';
|
|
import Animated, {
|
|
Easing,
|
|
useAnimatedStyle,
|
|
useSharedValue,
|
|
withRepeat,
|
|
withTiming,
|
|
} from 'react-native-reanimated';
|
|
|
|
const SIZES = {
|
|
small: 24,
|
|
large: 48,
|
|
} as const;
|
|
|
|
type Props = {
|
|
size?: keyof typeof SIZES | number;
|
|
style?: StyleProp<ImageStyle>;
|
|
};
|
|
|
|
export function LoadingSpinner({ size = 'large', style }: Props) {
|
|
const dimension = typeof size === 'number' ? size : SIZES[size];
|
|
const rotation = useSharedValue(0);
|
|
|
|
useEffect(() => {
|
|
rotation.value = withRepeat(
|
|
withTiming(360, { duration: 1000, easing: Easing.linear }),
|
|
-1,
|
|
false,
|
|
);
|
|
}, [rotation]);
|
|
|
|
const animatedStyle = useAnimatedStyle(() => ({
|
|
transform: [{ rotate: `${rotation.value}deg` }],
|
|
}));
|
|
|
|
return (
|
|
<Animated.View style={animatedStyle}>
|
|
<Image
|
|
source={require('@/assets/icons/logo.png')}
|
|
style={[{ width: dimension, height: dimension }, style]}
|
|
resizeMode="contain"
|
|
/>
|
|
</Animated.View>
|
|
);
|
|
}
|