diff --git a/example/src/pages/Selection.tsx b/example/src/pages/Selection.tsx index 358ea3aa..dbccadca 100644 --- a/example/src/pages/Selection.tsx +++ b/example/src/pages/Selection.tsx @@ -147,11 +147,18 @@ const renderListItemCheckbox = () => ( const mockRadioItems = (): ReadonlyArray> => [ { - icon: "coggle", + startImage: { icon: "coggle" }, value: "Let's try with a basic title", description: "Ti contatteranno solo i servizi che hanno qualcosa di importante da dirti. Potrai sempre disattivare le comunicazioni che non ti interessano.", - id: "example-1" + id: "example-icon" + }, + { + startImage: { paymentLogo: "myBank" }, + value: "Let's try with a basic title", + description: + "Ti contatteranno solo i servizi che hanno qualcosa di importante da dirti. Potrai sempre disattivare le comunicazioni che non ti interessano.", + id: "example-paymentLogo" }, { value: "Let's try with a basic title", @@ -169,6 +176,51 @@ const mockRadioItems = (): ReadonlyArray> => [ "Ti contatteranno solo i servizi che hanno qualcosa di importante da dirti.", id: "example-disabled", disabled: true + }, + { + value: "Let's try with a disabled item", + description: + "Ti contatteranno solo i servizi che hanno qualcosa di importante da dirti.", + id: "example-loading", + disabled: true, + loadingProps: { + state: true, + skeletonIcon: false + } + }, + { + value: "Let's try with a disabled item", + description: + "Ti contatteranno solo i servizi che hanno qualcosa di importante da dirti.", + id: "example-loading-withIcon", + disabled: true, + loadingProps: { + state: true, + skeletonIcon: true + } + }, + { + value: "Let's try with a disabled item", + description: + "Ti contatteranno solo i servizi che hanno qualcosa di importante da dirti.", + id: "example-loading-withDescription", + disabled: true, + loadingProps: { + state: true, + skeletonDescription: true + } + }, + { + value: "Let's try with a disabled item", + description: + "Ti contatteranno solo i servizi che hanno qualcosa di importante da dirti.", + id: "example-loading-withIcon-withDescription", + disabled: true, + loadingProps: { + state: true, + skeletonDescription: true, + skeletonIcon: true + } } ]; diff --git a/src/components/listitems/ListItemRadio.tsx b/src/components/listitems/ListItemRadio.tsx index ae5b89bd..6d418fa8 100644 --- a/src/components/listitems/ListItemRadio.tsx +++ b/src/components/listitems/ListItemRadio.tsx @@ -11,6 +11,7 @@ import Animated, { useSharedValue, withSpring } from "react-native-reanimated"; +import Placeholder from "rn-placeholder"; import { IOColors, IOScaleValues, @@ -26,13 +27,31 @@ import { IOIcons, Icon } from "../icons"; import { HSpacer, VSpacer } from "../spacer"; import { H6, LabelSmall } from "../typography"; import { AnimatedRadio } from "../radio/AnimatedRadio"; +import { IOLogoPaymentType, LogoPayment } from "../logos"; + +type ListItemRadioGraphicProps = + | { icon?: never; paymentLogo: IOLogoPaymentType } + | { icon: IOIcons; paymentLogo?: never }; + +type ListItemRadioLoadingProps = + | { + state: true; + skeletonDescription?: boolean; + skeletonIcon?: boolean; + } + | { + state?: false; + skeletonDescription?: never; + skeletonIcon?: never; + }; type Props = WithTestID<{ value: string; description?: string; - icon?: IOIcons; selected: boolean; onValueChange?: (newValue: boolean) => void; + startImage?: ListItemRadioGraphicProps; + loadingProps?: ListItemRadioLoadingProps; }>; const DISABLED_OPACITY = 0.5; @@ -46,7 +65,7 @@ type OwnProps = Props & >; /** - * with the automatic state management that uses a {@link AnimatedCheckBox} + * `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 @@ -55,16 +74,16 @@ type OwnProps = Props & export const ListItemRadio = ({ value, description, - icon, + startImage, selected, disabled, onValueChange, + loadingProps, testID }: OwnProps) => { const [toggleValue, setToggleValue] = useState(selected ?? false); // Animations const isPressed: Animated.SharedValue = useSharedValue(0); - // Scaling transformation applied when the button is pressed const animationScaleValue = IOScaleValues?.basicButton?.pressedState; @@ -123,7 +142,66 @@ export const ListItemRadio = ({ } }; - return ( + const disabledStyle = { opacity: disabled ? DISABLED_OPACITY : 1 }; + + const SkeletonDescriptionLines = () => ( + <> + + + + + + + + ); + + const SkeletonIcon = () => ( + + + + ); + + const SkeletonComponent = () => ( + + + + + {loadingProps?.skeletonIcon && } + + + + + + + + + {loadingProps?.skeletonDescription && } + + ); + + return loadingProps?.state ? ( + + ) : ( - {icon && ( + {startImage && ( - + {/* icon or paymentLogo props are mutually exclusive */} + {startImage.icon && ( + + )} + {startImage.paymentLogo && ( + + )} )} diff --git a/src/components/radio/RadioGroup.tsx b/src/components/radio/RadioGroup.tsx index ddbb8bd2..c7401f8a 100644 --- a/src/components/radio/RadioGroup.tsx +++ b/src/components/radio/RadioGroup.tsx @@ -1,15 +1,15 @@ -import React from "react"; +import React, { ComponentProps } from "react"; import { View } from "react-native"; import { Divider } from "../divider"; -import { IOIcons } from "../icons"; import { ListItemRadio } from "../listitems/ListItemRadio"; export type RadioItem = { id: T; value: string; description?: string; - icon?: IOIcons; disabled?: boolean; + startImage?: ComponentProps["startImage"]; + loadingProps?: ComponentProps["loadingProps"]; }; type Props = { @@ -31,8 +31,9 @@ export const RadioGroup = ({ items, selectedItem, onPress }: Props) => ( testID={`RadioItemTestID_${item.id}`} value={item.value} description={item.description} - icon={item.icon} + startImage={item.startImage} disabled={item.disabled} + loadingProps={item.loadingProps} onValueChange={() => onPress(item.id)} selected={selectedItem === item.id} />