import { ComponentProps, ReactNode } from "react"; import { GestureResponderEvent, Image, Pressable, View } from "react-native"; import Animated from "react-native-reanimated"; import { useIOTheme } from "../../context"; import { IOColors, IOListItemStyles, IOListItemVisualParams, IOSelectionListItemVisualParams, IOSpacer, IOVisualCostants } from "../../core"; import { useListItemAnimation } from "../../hooks"; import { useIOFontDynamicScale } from "../../utils/accessibility"; import { WithTestID } from "../../utils/types"; import { Avatar } from "../avatar"; import { Badge } from "../badge"; import { IOIcons, Icon } from "../icons"; import { HSpacer, VSpacer } from "../layout"; import { LoadingSpinner } from "../loadingSpinner"; import { BodySmall, Caption, H6 } from "../typography"; type ListItemTopElementProps = | { badgeProps: ComponentProps; dateValue?: never; } | { badgeProps?: never; dateValue: string; }; type ListItemNavPartialProps = WithTestID< { value: string | ReactNode; /** * The maximum number of lines to display for the value. */ numberOfLines?: number; description?: string | ReactNode; loading?: boolean; onPress: (event: GestureResponderEvent) => void; hideChevron?: boolean; topElement?: ListItemTopElementProps; } & Pick< ComponentProps, "accessibilityLabel" | "accessibilityHint" > >; export type ListItemNavGraphicProps = | { avatarProps: Omit, "size">; icon?: never; iconColor?: never; paymentLogoUri?: never; } | { avatarProps?: never; icon?: never; iconColor?: never; paymentLogoUri: string; } | { avatarProps?: never; icon: IOIcons; iconColor?: IOColors; paymentLogoUri?: never; } | { avatarProps?: never; icon?: never; iconColor?: never; paymentLogoUri?: never; }; export type ListItemNav = ListItemNavPartialProps & ListItemNavGraphicProps; export const ListItemNav = ({ value, description, onPress, icon, iconColor, avatarProps: avatar, paymentLogoUri, accessibilityLabel, accessibilityHint, testID, hideChevron = false, topElement, loading, numberOfLines }: ListItemNav) => { const { onPressIn, onPressOut, scaleAnimatedStyle, backgroundAnimatedStyle } = useListItemAnimation(); const theme = useIOTheme(); const defaultIconColor = iconColor ?? theme["icon-decorative"]; const interactiveColor = theme["interactiveElem-default"]; const { dynamicFontScale, hugeFontEnabled } = useIOFontDynamicScale(); const listItemNavContent = ( <> {topElement && ( <> {topElement.badgeProps && ( <> )} {topElement.dateValue && ( <> {topElement.dateValue} )} )} {/* Let developer using a custom component (e.g: skeleton) */} {typeof value === "string" ? (
{value}
) : ( value )} {description && ( <> {typeof description === "string" ? ( {description} ) : ( description )} )} ); const handleOnPress = (event: GestureResponderEvent) => { if (!loading) { onPress(event); } }; return ( {/* Possibile graphical assets - Icon - Image URL (for payment logos) - Avatar */} {icon && !hugeFontEnabled && ( <> )} {paymentLogoUri && ( <> )} {avatar && ( <> )} {listItemNavContent} {loading && } {!loading && !hideChevron && ( )} ); };