import { ComponentProps, ReactNode, useState } from "react"; import { Image, Pressable, StyleSheet, View } from "react-native"; import ReactNativeHapticFeedback from "react-native-haptic-feedback"; import Animated from "react-native-reanimated"; import { useIOTheme } from "../../context"; import { IOSelectionListItemStyles, IOSelectionListItemVisualParams, IOSelectionTickVisualParams } from "../../core"; import { useListItemAnimation } from "../../hooks"; import { useIOFontDynamicScale } from "../../utils/accessibility"; import { WithTestID } from "../../utils/types"; import { IOIcons, Icon } from "../icons"; import { HSpacer, VSpacer, VStack } from "../layout"; import { IOLogoPaymentType, LogoPayment } from "../logos"; import { AnimatedRadio } from "../radio/AnimatedRadio"; import { IOSkeleton } from "../skeleton"; import { BodySmall, H6 } from "../typography"; type ListItemRadioGraphicProps = | { icon?: never; paymentLogo: IOLogoPaymentType; uri?: never } | { icon?: never; paymentLogo?: never; uri: string } | { icon: IOIcons; paymentLogo?: never; uri?: never }; type ListItemRadioLoadingProps = | { state: true; skeletonDescription?: boolean; skeletonIcon?: boolean; loadingAccessibilityLabel?: string; } | { state?: false; skeletonDescription?: never; skeletonIcon?: never; loadingAccessibilityLabel?: never; }; type Props = WithTestID<{ value: string; description?: string | ReactNode; selected: boolean; onValueChange?: (newValue: boolean) => void; startImage?: ListItemRadioGraphicProps; loadingProps?: ListItemRadioLoadingProps; }>; const DISABLED_OPACITY = 0.5; type ListItemRadioProps = Props & Pick< ComponentProps, "onPress" | "accessibilityLabel" | "accessibilityHint" | "disabled" >; const styles = StyleSheet.create({ imageSize: { width: IOSelectionListItemVisualParams.iconSize, height: IOSelectionListItemVisualParams.iconSize, resizeMode: "contain" } }); /** * `ListItemRadio` component with the automatic state management that uses a {@link AnimatedCheckBox} * The toggleValue change when a `onPress` event is received and dispatch the `onValueChange`. * * @param props * @constructor */ export const ListItemRadio = ({ value, description, startImage, selected, disabled, onValueChange, accessibilityLabel, accessibilityHint, loadingProps, testID }: ListItemRadioProps) => { const [toggleValue, setToggleValue] = useState(selected ?? false); const { dynamicFontScale, spacingScaleMultiplier, hugeFontEnabled } = useIOFontDynamicScale(); const { onPressIn, onPressOut, scaleAnimatedStyle, backgroundAnimatedStyle } = useListItemAnimation(); const theme = useIOTheme(); const toggleRadioItem = () => { ReactNativeHapticFeedback.trigger("impactLight"); setToggleValue(!toggleValue); if (onValueChange !== undefined) { onValueChange(!toggleValue); } }; const disabledStyle = { opacity: disabled ? DISABLED_OPACITY : 1 }; const SkeletonDescriptionLines = () => ( ); const SkeletonIcon = () => ( ); const ListItemRadioSkeleton = ({ loadingAccessibilityLabel }: Pick) => ( {loadingProps?.skeletonIcon && } {loadingProps?.skeletonDescription && } ); return loadingProps?.state ? ( ) : ( {startImage?.icon && !hugeFontEnabled && ( )} {startImage?.uri && ( )} {startImage?.paymentLogo && ( )}
{value}
{description && ( {description} )}
); };