import { Image, ImageProps, ImageStyle, StyleProp, TextStyle, View, ViewStyle } from "react-native" import { useTranslation } from "react-i18next" import { useAppTheme } from "@/theme/context" import type { ThemedStyle } from "@/theme/types" import { Button, ButtonProps } from "./Button" import { Text, TextProps } from "./Text" const sadFace = require("@assets/images/sad-face.png") interface EmptyStateProps { /** * An optional prop that specifies the text/image set to use for the empty state. */ preset?: "generic" /** * Style override for the container. */ style?: StyleProp /** * An Image source to be displayed above the heading. */ imageSource?: ImageProps["source"] /** * Style overrides for image. */ imageStyle?: StyleProp /** * Pass any additional props directly to the Image component. */ ImageProps?: Omit /** * The heading text to display if not using `headingTx`. */ heading?: TextProps["text"] /** * Heading text which is looked up via i18n. */ headingTx?: TextProps["tx"] /** * Optional heading options to pass to i18n. Useful for interpolation * as well as explicitly setting locale or translation fallbacks. */ headingTxOptions?: TextProps["txOptions"] /** * Style overrides for heading text. */ headingStyle?: StyleProp /** * Pass any additional props directly to the heading Text component. */ HeadingTextProps?: TextProps /** * The content text to display if not using `contentTx`. */ content?: TextProps["text"] /** * Content text which is looked up via i18n. */ contentTx?: TextProps["tx"] /** * Optional content options to pass to i18n. Useful for interpolation * as well as explicitly setting locale or translation fallbacks. */ contentTxOptions?: TextProps["txOptions"] /** * Style overrides for content text. */ contentStyle?: StyleProp /** * Pass any additional props directly to the content Text component. */ ContentTextProps?: TextProps /** * The button text to display if not using `buttonTx`. */ button?: TextProps["text"] /** * Button text which is looked up via i18n. */ buttonTx?: TextProps["tx"] /** * Optional button options to pass to i18n. Useful for interpolation * as well as explicitly setting locale or translation fallbacks. */ buttonTxOptions?: TextProps["txOptions"] /** * Style overrides for button. */ buttonStyle?: ButtonProps["style"] /** * Style overrides for button text. */ buttonTextStyle?: ButtonProps["textStyle"] /** * Called when the button is pressed. */ buttonOnPress?: ButtonProps["onPress"] /** * Pass any additional props directly to the Button component. */ ButtonProps?: ButtonProps } interface EmptyStatePresetItem { imageSource: ImageProps["source"] heading: TextProps["text"] content: TextProps["text"] button: TextProps["text"] } /** * A component to use when there is no data to display. It can be utilized to direct the user what to do next. * @see [Documentation and Examples]{@link https://docs.infinite.red/ignite-cli/boilerplate/app/components/EmptyState/} * @param {EmptyStateProps} props - The props for the `EmptyState` component. * @returns {JSX.Element} The rendered `EmptyState` component. */ export function EmptyState(props: EmptyStateProps) { const { theme, themed, theme: { spacing }, } = useAppTheme() const { t } = useTranslation() const EmptyStatePresets = { generic: { imageSource: sadFace, heading: t("emptyStateComponent:generic.heading"), content: t("emptyStateComponent:generic.content"), button: t("emptyStateComponent:generic.button"), } as EmptyStatePresetItem, } as const const preset = EmptyStatePresets[props.preset ?? "generic"] const { button = preset.button, buttonTx, buttonOnPress, buttonTxOptions, content = preset.content, contentTx, contentTxOptions, heading = preset.heading, headingTx, headingTxOptions, imageSource = preset.imageSource, style: $containerStyleOverride, buttonStyle: $buttonStyleOverride, buttonTextStyle: $buttonTextStyleOverride, contentStyle: $contentStyleOverride, headingStyle: $headingStyleOverride, imageStyle: $imageStyleOverride, ButtonProps, ContentTextProps, HeadingTextProps, ImageProps, } = props const isImagePresent = !!imageSource const isHeadingPresent = !!(heading || headingTx) const isContentPresent = !!(content || contentTx) const isButtonPresent = !!(button || buttonTx) const $containerStyles = [$containerStyleOverride] const $imageStyles = [ $image, (isHeadingPresent || isContentPresent || isButtonPresent) && { marginBottom: spacing.xxxs }, $imageStyleOverride, ImageProps?.style, ] const $headingStyles = [ themed($heading), isImagePresent && { marginTop: spacing.xxxs }, (isContentPresent || isButtonPresent) && { marginBottom: spacing.xxxs }, $headingStyleOverride, HeadingTextProps?.style, ] const $contentStyles = [ themed($content), (isImagePresent || isHeadingPresent) && { marginTop: spacing.xxxs }, isButtonPresent && { marginBottom: spacing.xxxs }, $contentStyleOverride, ContentTextProps?.style, ] const $buttonStyles = [ (isImagePresent || isHeadingPresent || isContentPresent) && { marginTop: spacing.xl }, $buttonStyleOverride, ButtonProps?.style, ] return ( {isImagePresent && ( )} {isHeadingPresent && ( )} {isContentPresent && ( )} {isButtonPresent && (