All files / components/ui OptimizedImage.tsx

100% Statements 6/6
100% Branches 10/10
100% Functions 3/3
100% Lines 6/6

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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83                                          7x 7x   7x                                       2x                                             2x                   4x          
import { StyleSheet } from 'react-native';
import { Image, type ImageProps, type ImageSource } from 'expo-image';
 
import { neutralScale } from '@/src/design-system/tokens';
 
interface OptimizedImageProps extends Omit<ImageProps, 'source'> {
  source: string | ImageSource;
  blurhash?: string;
  cachePolicy?: 'none' | 'disk' | 'memory' | 'memory-disk';
  transitionDuration?: number;
}
 
export function OptimizedImage({
  source,
  blurhash,
  style,
  cachePolicy = 'memory-disk',
  transitionDuration = 200,
  contentFit = 'cover',
  ...props
}: OptimizedImageProps) {
  const imageSource: ImageSource = typeof source === 'string' ? { uri: source } : source;
  const placeholder = blurhash ? { blurhash } : undefined;
 
  return (
    <Image
      source={imageSource}
      style={[styles.image, style]}
      contentFit={contentFit}
      transition={transitionDuration}
      cachePolicy={cachePolicy}
      placeholder={placeholder}
      placeholderContentFit={contentFit}
      {...props}
    />
  );
}
 
interface AvatarImageProps extends Omit<OptimizedImageProps, 'style'> {
  size?: number;
  style?: ImageProps['style'];
}
 
export function AvatarImage({ source, size = 50, style, ...props }: AvatarImageProps) {
  return (
    <OptimizedImage
      source={source}
      style={[{ width: size, height: size, borderRadius: size / 2 }, style]}
      contentFit="cover"
      {...props}
    />
  );
}
 
interface ProductImageProps extends Omit<OptimizedImageProps, 'style'> {
  aspectRatio?: number;
  borderRadius?: number;
  style?: ImageProps['style'];
}
 
export function ProductImage({
  source,
  aspectRatio = 1,
  borderRadius = 12,
  style,
  ...props
}: ProductImageProps) {
  return (
    <OptimizedImage
      source={source}
      style={[{ aspectRatio, borderRadius }, style]}
      contentFit="cover"
      {...props}
    />
  );
}
 
const styles = StyleSheet.create({
  image: {
    backgroundColor: neutralScale.neutral2,
  },
});