import React from "react"; import { StyleSheet, View, ImageSourcePropType, StyleProp, ViewStyle, TextStyle, Pressable, } from "react-native"; import Image from "./Image"; import Surface from "./Surface"; import Icon from "./Icon"; import { Title, Subtitle, Caption } from "./Typography"; import { withTheme } from "../core/theming"; import type { Theme } from "../styles/DefaultTheme"; import Config from "./Config"; import { COMPONENT_TYPES, createElevationType, createTextProp, createImageProp, createIconProp, createAspectRatioProp, createActionProp, createBoolProp, createTextStyle, } from "../core/component-types"; const ICON_SIZE = Config.cardIconSize; const ICON_CONTAINER_SIZE = Config.cardIconSize * 2; const ICON_CONTAINER_PADDING = Config.cardIconSize / 2 - 1; const ICON_ELEVATION = Config.cardIconElevation; export const TopRightCircleIcon = withTheme( ({ icon, theme, onPress, IconOverride, }: { icon: string; theme: Theme; onPress?: () => void; IconOverride: typeof Icon; }) => { return ( { return [ { opacity: pressed ? 0.8 : 1, }, ]; }} > ); } ); type Props = { image?: string | ImageSourcePropType; title?: string; subtitle?: string; description?: string; textCentered: boolean; icon?: string; aspectRatio?: number; elevation?: number; numColumns?: number; theme: Theme; titleStyle?: StyleProp; subtitleStyle?: StyleProp; descriptionStyle?: StyleProp; style?: StyleProp; onPress?: () => void; onPressIcon?: () => void; children?: React.ReactNode; IconOverride?: typeof Icon; }; const Card: React.FC = ({ image = Config.cardImageUrl, title, subtitle, description, textCentered, icon, aspectRatio = 1.5, elevation = 2, style, onPress, onPressIcon, titleStyle, subtitleStyle, descriptionStyle, theme, children, IconOverride = null, }) => { // Necessary to inject web-renderable Icons in buider. const SelectedIcon = IconOverride || Icon; const { backgroundColor: bgColor, padding, ...styles } = StyleSheet.flatten( style || {} ); const backgroundColor = bgColor ? bgColor : theme.colors.surface; const innerPadding = padding ? padding : 12; return ( { return [ { opacity: pressed ? 0.8 : 1, }, ]; }} > {title || (title && title !== "") ? ( ) : null} {subtitle || (subtitle && subtitle !== "") ? ( <Subtitle text={subtitle} style={subtitleStyle} /> ) : null} {description || (description && description !== "") ? ( <View style={{ marginTop: 4 }}> <Caption text={description} style={descriptionStyle} /> </View> ) : null} {children} </View> </View> {icon ? ( <TopRightCircleIcon IconOverride={SelectedIcon} icon={icon} onPress={onPressIcon} /> ) : null} </Pressable> </Surface> ); }; export default withTheme(Card); export const SEED_DATA = { name: "Card", tag: "Card", description: "A card you can customize however you'd like", category: COMPONENT_TYPES.card, props: { elevation: createElevationType(3), image: createImageProp(), onPress: createActionProp(), onPressIcon: createActionProp(), title: createTextProp({ label: "Title", description: "Large title text", // defaultValue: "Title", defaultValue: null, }), titleStyle: createTextStyle({ label: "Title Style", }), subtitle: createTextProp({ label: "Subtitle", description: "Text underneath the title", defaultValue: null, // defaultValue: "Edit me in the props panel on the right", }), subtitleStyle: createTextStyle({ label: "Subtitle Style", }), description: createTextProp({ label: "Description", description: "Smallest text underneath subtitle", // defaultValue: // "This bottom text is optional, but shows up to make your life a little easier!", defaultValue: null, }), descriptionStyle: createTextStyle({ label: "Description Style", }), icon: createIconProp(), aspectRatio: createAspectRatioProp({ defaultValue: 1.5, }), textCentered: createBoolProp({ label: "Centered Text", description: "Places your title and subtitle in the center", }), }, };