xref: /MusicFree/src/components/base/listItem.tsx (revision 740e39476f71e0e17304d812ac0a4c4cdc183ed1)
11119c2eaS猫头猫import React, {ReactNode} from 'react';
21119c2eaS猫头猫import {
31119c2eaS猫头猫    StyleProp,
41119c2eaS猫头猫    StyleSheet,
51119c2eaS猫头猫    TextProps,
61119c2eaS猫头猫    TextStyle,
71119c2eaS猫头猫    TouchableHighlight,
81119c2eaS猫头猫    TouchableOpacity,
91119c2eaS猫头猫    View,
101119c2eaS猫头猫    ViewStyle,
111119c2eaS猫头猫} from 'react-native';
1219dc08ecS猫头猫import rpx from '@/utils/rpx';
131119c2eaS猫头猫import useColors from '@/hooks/useColors';
141119c2eaS猫头猫import ThemeText from './themeText';
151119c2eaS猫头猫import {
161119c2eaS猫头猫    fontSizeConst,
171119c2eaS猫头猫    fontWeightConst,
181119c2eaS猫头猫    iconSizeConst,
191119c2eaS猫头猫} from '@/constants/uiConst';
201119c2eaS猫头猫import FastImage from './fastImage';
211119c2eaS猫头猫import {ImageStyle} from 'react-native-fast-image';
225589cdf3S猫头猫import Icon, {IIconName} from '@/components/base/icon.tsx';
2319dc08ecS猫头猫
241119c2eaS猫头猫interface IListItemProps {
251119c2eaS猫头猫    // 是否有左右边距
265589cdf3S猫头猫    withHorizontalPadding?: boolean;
271119c2eaS猫头猫    // 左边距
281119c2eaS猫头猫    leftPadding?: number;
291119c2eaS猫头猫    // 右边距
301119c2eaS猫头猫    rightPadding?: number;
311119c2eaS猫头猫    // height:
321119c2eaS猫头猫    style?: StyleProp<ViewStyle>;
331119c2eaS猫头猫    // 高度类型
34e01046d9S猫头猫    heightType?: 'big' | 'small' | 'smallest' | 'normal' | 'none';
351119c2eaS猫头猫    children?: ReactNode;
361119c2eaS猫头猫    onPress?: () => void;
371119c2eaS猫头猫    onLongPress?: () => void;
381119c2eaS猫头猫}
391119c2eaS猫头猫
401119c2eaS猫头猫const defaultPadding = rpx(24);
411119c2eaS猫头猫const defaultActionWidth = rpx(80);
421119c2eaS猫头猫
431119c2eaS猫头猫const Size = {
441119c2eaS猫头猫    big: rpx(120),
451119c2eaS猫头猫    normal: rpx(108),
461119c2eaS猫头猫    small: rpx(96),
47e01046d9S猫头猫    smallest: rpx(72),
481119c2eaS猫头猫    none: undefined,
491119c2eaS猫头猫};
501119c2eaS猫头猫
511119c2eaS猫头猫function ListItem(props: IListItemProps) {
521119c2eaS猫头猫    const {
535589cdf3S猫头猫        withHorizontalPadding,
541119c2eaS猫头猫        leftPadding = defaultPadding,
551119c2eaS猫头猫        rightPadding = defaultPadding,
561119c2eaS猫头猫        style,
571119c2eaS猫头猫        heightType = 'normal',
581119c2eaS猫头猫        children,
591119c2eaS猫头猫        onPress,
601119c2eaS猫头猫        onLongPress,
611119c2eaS猫头猫    } = props;
621119c2eaS猫头猫
631119c2eaS猫头猫    const defaultStyle: StyleProp<ViewStyle> = {
645589cdf3S猫头猫        paddingLeft: withHorizontalPadding ? leftPadding : 0,
655589cdf3S猫头猫        paddingRight: withHorizontalPadding ? rightPadding : 0,
661119c2eaS猫头猫        height: Size[heightType],
671119c2eaS猫头猫    };
681119c2eaS猫头猫
691119c2eaS猫头猫    const colors = useColors();
701119c2eaS猫头猫
711119c2eaS猫头猫    return (
721119c2eaS猫头猫        <TouchableHighlight
731119c2eaS猫头猫            style={styles.container}
741119c2eaS猫头猫            underlayColor={colors.listActive}
751119c2eaS猫头猫            onPress={onPress}
761119c2eaS猫头猫            onLongPress={onLongPress}>
771119c2eaS猫头猫            <View style={[styles.container, defaultStyle, style]}>
781119c2eaS猫头猫                {children}
791119c2eaS猫头猫            </View>
801119c2eaS猫头猫        </TouchableHighlight>
811119c2eaS猫头猫    );
821119c2eaS猫头猫}
831119c2eaS猫头猫
841119c2eaS猫头猫interface IListItemTextProps {
851119c2eaS猫头猫    children?: number | string;
861119c2eaS猫头猫    fontSize?: keyof typeof fontSizeConst;
871119c2eaS猫头猫    fontWeight?: keyof typeof fontWeightConst;
881119c2eaS猫头猫    width?: number;
891119c2eaS猫头猫    position?: 'left' | 'right' | 'none';
901119c2eaS猫头猫    fixedWidth?: boolean;
911119c2eaS猫头猫    containerStyle?: StyleProp<ViewStyle>;
921119c2eaS猫头猫    contentStyle?: StyleProp<TextStyle>;
931119c2eaS猫头猫    contentProps?: TextProps;
941119c2eaS猫头猫}
951119c2eaS猫头猫
961119c2eaS猫头猫function ListItemText(props: IListItemTextProps) {
971119c2eaS猫头猫    const {
981119c2eaS猫头猫        children,
991119c2eaS猫头猫        fontSize,
1001119c2eaS猫头猫        fontWeight,
1011119c2eaS猫头猫        position = 'left',
1021119c2eaS猫头猫        fixedWidth,
1031119c2eaS猫头猫        width,
1041119c2eaS猫头猫        containerStyle,
1051119c2eaS猫头猫        contentStyle,
1061119c2eaS猫头猫        contentProps = {},
1071119c2eaS猫头猫    } = props;
1081119c2eaS猫头猫
1091119c2eaS猫头猫    const defaultStyle: StyleProp<ViewStyle> = {
1101119c2eaS猫头猫        marginRight: position === 'left' ? defaultPadding : 0,
1111119c2eaS猫头猫        marginLeft: position === 'right' ? defaultPadding : 0,
1121119c2eaS猫头猫        width: fixedWidth ? width ?? defaultActionWidth : undefined,
1131119c2eaS猫头猫        flexBasis: fixedWidth ? width ?? defaultActionWidth : undefined,
1141119c2eaS猫头猫    };
1151119c2eaS猫头猫
1161119c2eaS猫头猫    return (
1171119c2eaS猫头猫        <View style={[styles.actionBase, defaultStyle, containerStyle]}>
1181119c2eaS猫头猫            <ThemeText
1191119c2eaS猫头猫                fontSize={fontSize}
1201119c2eaS猫头猫                style={contentStyle}
1211119c2eaS猫头猫                fontWeight={fontWeight}
1221119c2eaS猫头猫                {...contentProps}>
1231119c2eaS猫头猫                {children}
1241119c2eaS猫头猫            </ThemeText>
1251119c2eaS猫头猫        </View>
1261119c2eaS猫头猫    );
1271119c2eaS猫头猫}
1281119c2eaS猫头猫
1291119c2eaS猫头猫interface IListItemIconProps {
1305589cdf3S猫头猫    icon: IIconName;
1311119c2eaS猫头猫    iconSize?: number;
1321119c2eaS猫头猫    width?: number;
1331119c2eaS猫头猫    position?: 'left' | 'right' | 'none';
1341119c2eaS猫头猫    fixedWidth?: boolean;
1351119c2eaS猫头猫    containerStyle?: StyleProp<ViewStyle>;
1361119c2eaS猫头猫    contentStyle?: StyleProp<TextStyle>;
1371119c2eaS猫头猫    onPress?: () => void;
138*740e3947S猫头猫    color?: string;
1391119c2eaS猫头猫}
1401119c2eaS猫头猫
1411119c2eaS猫头猫function ListItemIcon(props: IListItemIconProps) {
1421119c2eaS猫头猫    const {
1431119c2eaS猫头猫        icon,
1441119c2eaS猫头猫        iconSize = iconSizeConst.normal,
1451119c2eaS猫头猫        position = 'left',
1461119c2eaS猫头猫        fixedWidth,
1471119c2eaS猫头猫        width,
1481119c2eaS猫头猫        containerStyle,
1491119c2eaS猫头猫        contentStyle,
1501119c2eaS猫头猫        onPress,
151*740e3947S猫头猫        color,
1521119c2eaS猫头猫    } = props;
1531119c2eaS猫头猫
1546cfecf1cS猫头猫    const colors = useColors();
1556cfecf1cS猫头猫
1561119c2eaS猫头猫    const defaultStyle: StyleProp<ViewStyle> = {
1571119c2eaS猫头猫        marginRight: position === 'left' ? defaultPadding : 0,
1581119c2eaS猫头猫        marginLeft: position === 'right' ? defaultPadding : 0,
1591119c2eaS猫头猫        width: fixedWidth ? width ?? defaultActionWidth : undefined,
1601119c2eaS猫头猫        flexBasis: fixedWidth ? width ?? defaultActionWidth : undefined,
1611119c2eaS猫头猫    };
1621119c2eaS猫头猫
1631119c2eaS猫头猫    const innerContent = (
1641119c2eaS猫头猫        <View style={[styles.actionBase, defaultStyle, containerStyle]}>
1656cfecf1cS猫头猫            <Icon
1666cfecf1cS猫头猫                name={icon}
1676cfecf1cS猫头猫                size={iconSize}
1686cfecf1cS猫头猫                style={contentStyle}
169*740e3947S猫头猫                color={color || colors.text}
1706cfecf1cS猫头猫            />
1711119c2eaS猫头猫        </View>
1721119c2eaS猫头猫    );
1731119c2eaS猫头猫
1741119c2eaS猫头猫    return onPress ? (
1751119c2eaS猫头猫        <TouchableOpacity onPress={onPress}>{innerContent}</TouchableOpacity>
1761119c2eaS猫头猫    ) : (
1771119c2eaS猫头猫        innerContent
1781119c2eaS猫头猫    );
1791119c2eaS猫头猫}
1801119c2eaS猫头猫
1811119c2eaS猫头猫interface IListItemImageProps {
1821119c2eaS猫头猫    uri?: string;
1831119c2eaS猫头猫    fallbackImg?: number;
1841119c2eaS猫头猫    imageSize?: number;
1851119c2eaS猫头猫    width?: number;
1861119c2eaS猫头猫    position?: 'left' | 'right';
1871119c2eaS猫头猫    fixedWidth?: boolean;
1881119c2eaS猫头猫    containerStyle?: StyleProp<ViewStyle>;
1891119c2eaS猫头猫    contentStyle?: StyleProp<ImageStyle>;
1905589cdf3S猫头猫    maskIcon?: IIconName | null;
1911119c2eaS猫头猫}
1921119c2eaS猫头猫
1931119c2eaS猫头猫function ListItemImage(props: IListItemImageProps) {
1941119c2eaS猫头猫    const {
1951119c2eaS猫头猫        uri,
1961119c2eaS猫头猫        fallbackImg,
1971119c2eaS猫头猫        position = 'left',
1981119c2eaS猫头猫        fixedWidth,
1991119c2eaS猫头猫        width,
2001119c2eaS猫头猫        containerStyle,
2011119c2eaS猫头猫        contentStyle,
2027aed04d4S猫头猫        maskIcon,
2031119c2eaS猫头猫    } = props;
2041119c2eaS猫头猫
2051119c2eaS猫头猫    const defaultStyle: StyleProp<ViewStyle> = {
2061119c2eaS猫头猫        marginRight: position === 'left' ? defaultPadding : 0,
2071119c2eaS猫头猫        marginLeft: position === 'right' ? defaultPadding : 0,
2081119c2eaS猫头猫        width: fixedWidth ? width ?? defaultActionWidth : undefined,
2091119c2eaS猫头猫        flexBasis: fixedWidth ? width ?? defaultActionWidth : undefined,
2101119c2eaS猫头猫    };
2111119c2eaS猫头猫
2121119c2eaS猫头猫    return (
2131119c2eaS猫头猫        <View style={[styles.actionBase, defaultStyle, containerStyle]}>
2141119c2eaS猫头猫            <FastImage
2151119c2eaS猫头猫                style={[styles.leftImage, contentStyle]}
2161119c2eaS猫头猫                uri={uri}
2171119c2eaS猫头猫                emptySrc={fallbackImg}
2181119c2eaS猫头猫            />
2197aed04d4S猫头猫            {maskIcon ? (
2207aed04d4S猫头猫                <View style={[styles.leftImage, styles.imageMask]}>
2217aed04d4S猫头猫                    <Icon
2227aed04d4S猫头猫                        name={maskIcon}
2237aed04d4S猫头猫                        size={iconSizeConst.normal}
2247aed04d4S猫头猫                        color="red"
2257aed04d4S猫头猫                    />
2267aed04d4S猫头猫                </View>
2277aed04d4S猫头猫            ) : null}
2281119c2eaS猫头猫        </View>
2291119c2eaS猫头猫    );
2301119c2eaS猫头猫}
2311119c2eaS猫头猫
2321119c2eaS猫头猫interface IContentProps {
2331119c2eaS猫头猫    title?: ReactNode;
2346cfecf1cS猫头猫    children?: ReactNode;
2351119c2eaS猫头猫    description?: ReactNode;
2361119c2eaS猫头猫    containerStyle?: StyleProp<ViewStyle>;
2371119c2eaS猫头猫}
2381119c2eaS猫头猫
2391119c2eaS猫头猫function Content(props: IContentProps) {
2406cfecf1cS猫头猫    const {
2416cfecf1cS猫头猫        children,
2426cfecf1cS猫头猫        title = children,
2436cfecf1cS猫头猫        description = null,
2446cfecf1cS猫头猫        containerStyle,
2456cfecf1cS猫头猫    } = props;
2461119c2eaS猫头猫
2471119c2eaS猫头猫    let realTitle;
2481119c2eaS猫头猫    let realDescription;
2491119c2eaS猫头猫
2501119c2eaS猫头猫    if (typeof title === 'string' || typeof title === 'number') {
2511119c2eaS猫头猫        realTitle = <ThemeText numberOfLines={1}>{title}</ThemeText>;
2521119c2eaS猫头猫    } else {
2531119c2eaS猫头猫        realTitle = title;
2541119c2eaS猫头猫    }
2551119c2eaS猫头猫
2561119c2eaS猫头猫    if (typeof description === 'string' || typeof description === 'number') {
2571119c2eaS猫头猫        realDescription = (
2581119c2eaS猫头猫            <ThemeText
2591119c2eaS猫头猫                numberOfLines={1}
2601119c2eaS猫头猫                fontSize="description"
261277c5280S猫头猫                fontColor="textSecondary"
2621119c2eaS猫头猫                style={styles.contentDesc}>
2631119c2eaS猫头猫                {description}
2641119c2eaS猫头猫            </ThemeText>
2651119c2eaS猫头猫        );
2661119c2eaS猫头猫    } else {
2671119c2eaS猫头猫        realDescription = description;
2681119c2eaS猫头猫    }
2691119c2eaS猫头猫
2701119c2eaS猫头猫    return (
2711119c2eaS猫头猫        <View style={[styles.itemContentContainer, containerStyle]}>
2721119c2eaS猫头猫            {realTitle}
2731119c2eaS猫头猫            {realDescription}
2741119c2eaS猫头猫        </View>
2751119c2eaS猫头猫    );
27619dc08ecS猫头猫}
277e650bfb3S猫头猫
278e01046d9S猫头猫export function ListItemHeader(props: {children?: ReactNode}) {
279e01046d9S猫头猫    const {children} = props;
280e01046d9S猫头猫    return (
281e01046d9S猫头猫        <ListItem
2825589cdf3S猫头猫            withHorizontalPadding
283e01046d9S猫头猫            heightType="smallest"
284e01046d9S猫头猫            style={styles.listItemHeader}>
285e01046d9S猫头猫            {typeof children === 'string' ? (
286e01046d9S猫头猫                <ThemeText
287e01046d9S猫头猫                    fontSize="subTitle"
288e01046d9S猫头猫                    fontColor="textSecondary"
289e01046d9S猫头猫                    fontWeight="bold">
290e01046d9S猫头猫                    {children}
291e01046d9S猫头猫                </ThemeText>
292e01046d9S猫头猫            ) : (
293e01046d9S猫头猫                children
294e01046d9S猫头猫            )}
295e01046d9S猫头猫        </ListItem>
296e01046d9S猫头猫    );
297e01046d9S猫头猫}
298e01046d9S猫头猫
299e650bfb3S猫头猫const styles = StyleSheet.create({
3001119c2eaS猫头猫    /** listitem */
3011119c2eaS猫头猫    container: {
3021119c2eaS猫头猫        width: '100%',
3031119c2eaS猫头猫        flexDirection: 'row',
3041119c2eaS猫头猫        alignItems: 'center',
3051119c2eaS猫头猫    },
3061119c2eaS猫头猫    /** left */
3071119c2eaS猫头猫    actionBase: {
3081119c2eaS猫头猫        height: '100%',
3091119c2eaS猫头猫        flexShrink: 0,
3101119c2eaS猫头猫        flexGrow: 0,
3111119c2eaS猫头猫        flexBasis: 0,
3121119c2eaS猫头猫        flexDirection: 'row',
3131119c2eaS猫头猫        justifyContent: 'center',
3141119c2eaS猫头猫        alignItems: 'center',
3151119c2eaS猫头猫    },
3161119c2eaS猫头猫
3171119c2eaS猫头猫    leftImage: {
3181119c2eaS猫头猫        width: rpx(80),
3191119c2eaS猫头猫        height: rpx(80),
3201119c2eaS猫头猫        borderRadius: rpx(16),
3211119c2eaS猫头猫    },
3227aed04d4S猫头猫    imageMask: {
3237aed04d4S猫头猫        position: 'absolute',
3247aed04d4S猫头猫        alignItems: 'center',
3257aed04d4S猫头猫        justifyContent: 'center',
3267aed04d4S猫头猫        backgroundColor: '#00000022',
3277aed04d4S猫头猫    },
3281119c2eaS猫头猫    itemContentContainer: {
3291119c2eaS猫头猫        flex: 1,
3301119c2eaS猫头猫        height: '100%',
3311119c2eaS猫头猫        justifyContent: 'center',
3321119c2eaS猫头猫    },
3331119c2eaS猫头猫    contentDesc: {
3341119c2eaS猫头猫        marginTop: rpx(16),
33519dc08ecS猫头猫    },
336e01046d9S猫头猫
337e01046d9S猫头猫    listItemHeader: {
338e01046d9S猫头猫        marginTop: rpx(20),
339e01046d9S猫头猫    },
34019dc08ecS猫头猫});
3411119c2eaS猫头猫
3421119c2eaS猫头猫ListItem.Size = Size;
3431119c2eaS猫头猫ListItem.ListItemIcon = ListItemIcon;
3441119c2eaS猫头猫ListItem.ListItemImage = ListItemImage;
3451119c2eaS猫头猫ListItem.ListItemText = ListItemText;
3461119c2eaS猫头猫ListItem.Content = Content;
3471119c2eaS猫头猫
3481119c2eaS猫头猫export default ListItem;
349