import color from "color"; import * as React from "react"; import { StyleProp, StyleSheet, TextStyle, View, ViewStyle, } from "react-native"; import TouchableRipple from "../TouchableRipple/TouchableRipple"; import Text from "../Text"; import { $RemoveChildren, EllipsizeProp } from "../types"; import { DefaultTheme, ThemeContext } from "styled-components"; type Description = | React.ReactNode | ((props: { selectable: boolean; ellipsizeMode: EllipsizeProp | undefined; color: string; fontSize: number; }) => React.ReactNode); type Props = $RemoveChildren & { /** * Title text for the list item. */ title?: React.ReactNode; /** * Description text for the list item or callback which returns a React element to display the description. */ description?: Description | null; /** * Callback which returns a React element to display on the left side. */ left?: (props: { color: string; style: { marginLeft: number; marginRight: number; marginVertical?: number; }; }) => React.ReactNode; /** * Callback which returns a React element to display on the right side. */ right?: (props: { color: string; style?: { marginRight: number; marginVertical?: number; }; }) => React.ReactNode; /** * Callback which returns a React element to display on the right side. */ content?: (props: { color: string; style?: { marginRight?: number; marginVertical?: number; }; }) => React.ReactNode; /** * Function to execute on press. */ onPress?: () => void; /** * @optional */ theme?: DefaultTheme; /** * Style that is passed to the wrapping TouchableRipple element. */ style?: StyleProp; focusedStyle?: StyleProp; hoveredStyle?: StyleProp; pressedStyle?: StyleProp; /** * Style that is passed to wrap content. */ rowStyle?: StyleProp; /** * Style that is passed to wrap content. */ contentStyle?: StyleProp; /** * Style that is passed to Title element. */ titleStyle?: StyleProp; /** * Style that is passed to Description element. */ descriptionStyle?: StyleProp; /** * Truncate Title text such that the total number of lines does not * exceed this number. */ titleNumberOfLines?: number; /** * Truncate Description text such that the total number of lines does not * exceed this number. */ descriptionNumberOfLines?: number; /** * Ellipsize Mode for the Title. One of `'head'`, `'middle'`, `'tail'`, `'clip'`. * * See [`ellipsizeMode`](https://reactnative.dev/docs/text#ellipsizemode) */ titleEllipsizeMode?: EllipsizeProp; /** * Ellipsize Mode for the Description. One of `'head'`, `'middle'`, `'tail'`, `'clip'`. * * See [`ellipsizeMode`](https://reactnative.dev/docs/text#ellipsizemode) */ descriptionEllipsizeMode?: EllipsizeProp; }; /** * A component to show tiles inside a List. * *
* * * *
* * ## Usage * ```js * import * as React from 'react'; * import { ListItem } from 'react-native-simple-elements/components/ListItem'; * * const MyComponent = () => ( * } * /> * ); * * export default MyComponent; * ``` * */ const FlexItem = ({ left, right, content, title, description, onPress, style, focusedStyle, hoveredStyle, pressedStyle, rowStyle, contentStyle, titleStyle, titleNumberOfLines = 1, descriptionNumberOfLines = 2, titleEllipsizeMode, descriptionEllipsizeMode, descriptionStyle, ...rest }: Props) => { const theme = React.useContext(ThemeContext); const renderDescription = ( descriptionColor: string, description?: Description | null ) => { return typeof description === "function" ? ( description({ selectable: false, ellipsizeMode: descriptionEllipsizeMode, color: descriptionColor, fontSize: styles.description.fontSize, }) ) : ( {description} ); }; const titleColor = color(theme.colors.text).alpha(0.87).rgb().string(); const descriptionColor = color(theme.colors.text).alpha(0.54).rgb().string(); return ( {left ? left({ color: descriptionColor, style: description ? styles.iconMarginLeft : { ...styles.iconMarginLeft, ...styles.marginVerticalNone, }, }) : null} {content ? content({ color: titleColor, style: { } }) : ( <> {title} {description ? renderDescription(descriptionColor, description) : null} ) } {right ? right({ color: descriptionColor, style: description ? styles.iconMarginRight : { ...styles.iconMarginRight, ...styles.marginVerticalNone, }, }) : null} ); }; FlexItem.displayName = "Flex.Item"; const styles = StyleSheet.create({ container: { padding: 8, }, row: { flexDirection: "row", }, title: { fontSize: 16, }, description: { fontSize: 14, }, marginVerticalNone: { marginVertical: 0 }, iconMarginLeft: { marginLeft: 0, marginRight: 16 }, iconMarginRight: { marginRight: 0 }, item: { marginVertical: 6, paddingLeft: 8, }, content: { flex: 1, justifyContent: "center", }, }); export default FlexItem;