import { isValidElement, ReactNode } from "react"; import { ImageURISource, View } from "react-native"; import { useIOTheme } from "../../context"; import { IOColors, IOListItemLogoMargin, IOListItemStyles, IOListItemVisualParams, IOVisualCostants } from "../../core"; import { WithTestID } from "../../utils/types"; import { isImageUri } from "../../utils/url"; import { Avatar } from "../avatar/Avatar"; import { Badge } from "../badge/Badge"; import { LogoPaymentWithFallback } from "../common/LogoPaymentWithFallback"; import { IOIconSizeScale, Icon } from "../icons"; import { HStack, VStack } from "../layout"; import { IOLogoPaymentType } from "../logos"; import { IOSkeleton } from "../skeleton"; import { BodySmall, H6 } from "../typography"; import { PressableBaseProps, PressableListItemBase } from "./PressableListItemBase"; export type ListItemTransactionBadge = { text: string; variant: Badge["variant"]; }; export type ListItemTransactionLogo = | IOLogoPaymentType | ImageURISource | ReactNode; export type ListItemTransaction = WithTestID< PressableBaseProps & { showChevron?: boolean; isLoading?: boolean; loadingAccessibilityLabel?: string; /** * A logo that will be displayed on the left of the list item. * * Must be a {@link IOLogoPaymentType} or an {@link ImageURISource} or an {@link Icon}. */ paymentLogoIcon?: ListItemTransactionLogo; subtitle: string; title: string; /** * The maximum number of lines to display for the title. * @default 2 */ numberOfLines?: number; accessible?: boolean; } & ( | { transaction: { amount: string; amountAccessibilityLabel: string; badge?: never; refund?: boolean; }; } | { transaction: { amount?: string; amountAccessibilityLabel?: string; badge: ListItemTransactionBadge; refund?: never; }; } ) >; const CARD_LOGO_SIZE: IOIconSizeScale = 24; const MUNICIPALITY_LOGO_SIZE = 44; // this is the 's "small" size, // since it is bigger than the card logos, we use // it as a base size for homogeneous sizing via container size. const ListItemTransactionContent = ({ paymentLogoIcon, numberOfLines, title, subtitle, badge, amountAccessibilityLabel, showChevron, amount, refund }: Pick< ListItemTransaction, "paymentLogoIcon" | "numberOfLines" | "title" | "subtitle" | "showChevron" > & { badge: ListItemTransactionBadge | undefined; amount: string | undefined; amountAccessibilityLabel: string | undefined; refund: boolean | undefined; }) => { const theme = useIOTheme(); const interactiveColor: IOColors = theme["interactiveElem-default"]; const amountColor: IOColors = refund ? theme.successText : theme["textBody-default"]; return ( <> {paymentLogoIcon && ( )}
{title}
{subtitle}
{badge ? ( ) : (
{amount}
)} {showChevron && ( )}
); }; const StartComponent = ({ logoIcon }: { logoIcon: ListItemTransactionLogo; }) => { if (isImageUri(logoIcon)) { return ; } if (isValidElement(logoIcon)) { return <>{logoIcon}; } return ( ); }; export const ListItemTransaction = ({ accessibilityLabel, loadingAccessibilityLabel, showChevron = false, isLoading = false, paymentLogoIcon, onPress, subtitle, testID, title, transaction: { amount, amountAccessibilityLabel, badge, refund }, numberOfLines = 2, accessible }: ListItemTransaction) => { if (isLoading) { return ( ); } const contentProps = { paymentLogoIcon, numberOfLines, title, subtitle, badge, amountAccessibilityLabel, showChevron, amount, refund } as const; if (onPress) { return ( ); } else { return ( ); } }; const ListItemTransactionSkeleton = ({ loadingAccessibilityLabel }: Pick) => ( );