import React, { useCallback, useState } from 'react'; import { Animated, Image as ImageNative, ImageLoadEventData, NativeSyntheticEvent, StyleSheet, View, Text } from 'react-native'; import { Ripple } from '../Ripple'; import { Skeleton } from '../Skeleton'; import { ImageProps } from './types'; import createSxStyle from '../../lib/sx'; import useTheme from '../../context/theme/useTheme'; export const Image: React.FC = ({ onPress, onLongPress, source, src, Component = onPress || onLongPress ? Ripple : View, placeholderStyle, placeholderContent, errorContent, containerStyle, persisRatioWithImageFailed = true, childrenContainerStyle = null, style = {}, ImageComponent = ImageNative, onLoad, children, transition, height, width = '100%', transitionDuration = 200, ...props }) => { const theme = useTheme(); const [error, setError] = useState(false); const placeholderOpacity = React.useRef(new Animated.Value(1)); const onLoadHandler = useCallback( (event: NativeSyntheticEvent) => { Animated.timing(placeholderOpacity.current, { toValue: 0, duration: transitionDuration, useNativeDriver: true }).start(); onLoad?.(event); }, [transitionDuration, onLoad] ); const onLoadError = useCallback(() => { setError(true); }, []); const hasImage = Boolean(source || src); const sourceResolve = typeof source === 'string' ? { uri: source } : source; return ( {/* Transition placeholder */} {!error ? ( {React.isValidElement(placeholderContent) ? placeholderContent : placeholderContent && {placeholderContent}} ) : ( {React.isValidElement(errorContent) ? errorContent : errorContent && {errorContent}} )} {/* Children for Image */} {children && ( {children} )} ); }; const styles = StyleSheet.create({ container: { backgroundColor: 'transparent', position: 'relative', overflow: 'hidden' } }); Image.displayName = 'Image';