import { Image, type ImageProps, type ImageSource } from "expo-image"; import { type ReactNode } from "react"; import { StyleSheet, View, type StyleProp, type ViewStyle } from "react-native"; import { GestureDetector } from "react-native-gesture-handler"; import { useDerivedValue } from "react-native-reanimated"; import { BeforeClip } from "./BeforeClip"; import { Handle } from "./Handle"; import { Label } from "./Label"; import { useComparisonSlider } from "./useComparisonSlider"; type PassThroughImageProps = Omit; /** Props for {@link ImageComparisonSlider}. */ export interface ImageComparisonSliderProps { /** Revealed image */ before: ImageSource | number; /** Background image */ after: ImageSource | number; /** Split ratio, 0–1 */ initialPosition?: number; /** Comparison UI and gestures */ enabled?: boolean; /** Both images */ contentFit?: ImageProps["contentFit"]; /** Image stack corners */ borderRadius?: number; /** Root container */ style?: StyleProp; /** Knob children */ knobContent?: ReactNode; /** Divider line */ renderLine?: ReactNode; /** before (expo-image, minus source / style / contentFit) */ beforeImageProps?: PassThroughImageProps; /** after */ afterImageProps?: PassThroughImageProps; /** Label on the before image */ beforeLabel?: string; /** Label on the after image */ afterLabel?: string; } /** * Before/after image comparison slider for React Native and Expo. * * @see {@link ImageComparisonSliderProps} */ export function ImageComparisonSlider({ before, after, initialPosition = 0.5, enabled = true, contentFit = "cover", borderRadius, style, knobContent, renderLine, beforeImageProps, afterImageProps, beforeLabel, afterLabel, }: ImageComparisonSliderProps) { const { measuredWidth, containerWidth, splitPercent, splitRatio, pan, onLayoutWidth, onAccessibilityAction, } = useComparisonSlider(initialPosition, enabled); const splitPx = useDerivedValue(() => splitRatio.get() * containerWidth.get()); return ( onLayoutWidth(e.nativeEvent.layout.width)}> {afterLabel && enabled && {enabled && } ); } const styles = StyleSheet.create({ root: { width: "100%", }, media: { ...StyleSheet.absoluteFill, overflow: "hidden", }, fullImage: { ...StyleSheet.absoluteFill, width: "100%", height: "100%", }, });