All files / apps/host/src/components/RequestCardDetailSkeleton/skeletons Skeleton.tsx

100% Statements 12/12
100% Branches 3/3
100% Functions 4/4
100% Lines 11/11

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55                                      4x 138x 138x   138x 138x     138x 138x 138x   138x     138x                   138x                    
import React from 'react';
import Animated, {
  interpolate,
  useAnimatedStyle,
  useSharedValue,
  withRepeat,
  withTiming,
} from 'react-native-reanimated';
import { DimensionValue, StyleProp, View, ViewStyle } from 'react-native';
 
import { makeStyles } from '@repo/ui/themes/makeStyles';
 
interface SkeletonProps {
  width: DimensionValue;
  height: DimensionValue;
  radius?: number;
  style?: StyleProp<ViewStyle>;
}
 
export const Skeleton = ({ width, height, radius = 6, style }: SkeletonProps) => {
  const styles = useStyles();
  const progress = useSharedValue(0);
 
  React.useEffect(() => {
    progress.value = withRepeat(withTiming(1, { duration: 1200 }), -1, false);
  }, [progress]);
 
  const animatedStyle = useAnimatedStyle(() => {
    const translationWidth = typeof width === 'number' ? width : 300;
    const translateX = interpolate(progress.value, [0, 1], [-translationWidth, translationWidth]);
 
    return { transform: [{ translateX }] };
  });
 
  return (
    <View
      className="overflow-hidden"
      style={[styles.container, { width, height, borderRadius: radius }, style]}
    >
      <Animated.View className="opacity-50" style={[styles.shimmer, animatedStyle]} />
    </View>
  );
};
 
const useStyles = makeStyles(theme => ({
  container: {
    backgroundColor: theme.colors.skeleton.default,
  },
  shimmer: {
    width: '100%',
    height: '100%',
    backgroundColor: theme.colors.skeleton.active,
  },
}));