| import React, { useEffect } from 'react'; | |
| import { View, StyleSheet, ViewStyle, DimensionValue } from 'react-native'; | |
| import Animated, { | |
| useSharedValue, | |
| useAnimatedStyle, | |
| withRepeat, | |
| withTiming, | |
| withSequence | |
| } from 'react-native-reanimated'; | |
| interface SkeletonProps { | |
| width?: DimensionValue; | |
| height?: DimensionValue; | |
| style?: ViewStyle; | |
| borderRadius?: number; | |
| } | |
| export const Skeleton: React.FC<SkeletonProps> = ({ | |
| width = '100%', | |
| height = 20, | |
| style, | |
| borderRadius = 4 | |
| }) => { | |
| const opacity = useSharedValue(0.3); | |
| useEffect(() => { | |
| opacity.value = withRepeat( | |
| withSequence( | |
| withTiming(0.3, { duration: 1000 }), | |
| withTiming(0.7, { duration: 1000 }) | |
| ), | |
| -1, | |
| true | |
| ); | |
| }, []); | |
| const animatedStyle = useAnimatedStyle(() => ({ | |
| opacity: opacity.value, | |
| })); | |
| return ( | |
| <Animated.View | |
| style={[ | |
| styles.skeleton, | |
| { width, height, borderRadius }, | |
| style, | |
| animatedStyle, | |
| ]} | |
| /> | |
| ); | |
| }; | |
| const styles = StyleSheet.create({ | |
| skeleton: { | |
| backgroundColor: '#E1E9EE', | |
| }, | |
| }); | |