import React, { ReactNode, forwardRef, ForwardRefRenderFunction, useImperativeHandle, isValidElement, } from 'react'; import { StyleSheet, StyleProp, ViewStyle, TouchableOpacity, Text, View, TextStyle, } from 'react-native'; import { isString, isFunction, isBoolean } from 'lodash'; import { mergeProps } from '../../core/helpers'; import ShouldRender from '../ShouldRender'; import { Align } from './enum'; import { IconXRightsmall1 } from '../../icons'; import createStyle from './styles/list-item.style'; import { useTheme } from '../Theme/Theme'; export interface ListItemProps { /** * 是否禁用 */ disabled?: boolean; /** * 容器元素垂直对齐方式,默认垂直居中 */ align?: Align; /** * 左侧区域元素垂直对齐方式,默认垂直居中 */ leftAlign?: Align; /** * 右侧区域元素垂直对齐方式,默认垂直居中 */ rightAlign?: Align; /** * 右侧区域的箭头 */ arrow?: boolean | ReactNode; /** * 右侧区域的箭头颜色 * @default #999999 */ arrowFill?: string; /** * 左侧区域的前缀 */ prefix?: ReactNode; /** * 右侧区域的后缀 */ extra?: ReactNode; /** * 灰色的描述信息 */ description?: ReactNode; children?: ReactNode; /** * 点击事件 */ onPress?: () => void; /** * 容器样式 */ style?: StyleProp; /** * 标题容器样式,children为string类型时生效 */ titleStyle?: StyleProp; /** * 标题可显示文字行数,children为string类型时生效 */ titleLines?: number; /** * 描述容器样式,description为string类型时生效 */ descriptionStyle?: StyleProp; /** * 描述可显示文字行数,description为string类型时生效 */ descriptionLines?: number; /** * 左侧区域样式 */ leftStyle?: StyleProp; /** * 右侧区域样式 */ rightStyle?: StyleProp; /** * 左侧内容区样式 */ leftContentSyle?: StyleProp; /** * 右侧内容区样式 */ rightContentStyle?: StyleProp; /** * 右侧区域箭头样式,arrow为true时生效或者onPress属性为函数时生效 */ arrowStyle?: StyleProp; /** * 右侧区域箭头容器样式,arrow为true时生效或者onPress属性为函数时生效 */ arrowContainerStyle?: StyleProp; /** * 屏幕阅读器标签 */ accessibilityLabel?: string; /** * 不可操作点击回调 */ onDisabledPress?: () => void; } export interface ListItemRef {} const ListItem: ForwardRefRenderFunction = ( p, ref ) => { const token = useTheme(); const styles = createStyle(token); const defaultProps = { align: Align.middle, leftAlign: Align.middle, rightAlign: Align.middle, }; const props: ListItemProps = mergeProps(defaultProps, p); // 左侧区域、右侧区域元素垂直对齐方式,默认垂直居中 const getVerticalAlign = () => { return { alignItems: props.align, }; }; // 左侧区域各个元素垂直对齐方式 const leftVerticalAlign = () => { return { alignItems: props.leftAlign, }; }; // 右侧区域各个元素垂直对齐方式 const rightVerticalAlign = () => { return { alignItems: props.rightAlign, }; }; // 是否渲染右侧区域向右的箭头 const hasArrow = () => { // 如果是布尔值 if (isBoolean(props.arrow)) { return props.arrow; } // 如果是自定义节点 if (isValidElement(props.arrow)) { return false; } // 如果onPress属性为函数,则默认值为true return isFunction(props.onPress); }; // 控制右侧区域箭头的左边距 // const arrowIconMarginLeft = () => { // return { // marginLeft: isValidElement(props.extra) ? 2 : 0, // }; // }; // 控制左侧区域的左边距 const leftContentMarginLeft = () => { return { marginLeft: isValidElement(props.prefix) ? token['--spacing-2'] : 0, }; }; // 控制左侧区域的右边距 const leftMarginRight = () => { return { marginRight: isValidElement(props.extra) || hasArrow() || isValidElement(props.arrow) ? token['--spacing-2'] : 0, }; }; // 左侧prefix区域 const prefix = ( <> {/* 左边区域的左侧区域 */} {props.prefix} ); // 左侧内容区 const leftContent = ( <> {/* 左侧内容区 */} {/* 主信息为字符串类型 */} {props.children} {/* 主信息为节点类型 */} {props.children} {/* 描述信息为字符串类型 */} {props.description} {/* 描述信息为节点类型 */} {props.description} ); // 左侧区域 const leftArea = ( <> {/* 左边区域 */} {prefix} {leftContent} ); // 右侧剪头区域 const arrow = ( <> {/* 右侧区域向右的箭头 */} {/* 右侧箭头区域自定义 */} {props.arrow} ); // 右侧extra const extra = ( <> {/* 右侧区域的箭头的左侧区域,即右侧内容区 */} {props.extra} ); // 右侧区域 const rightArea = ( <> {/* 右边区域 */} {extra} {arrow} ); const handlePress = () => { if (props.disabled && isFunction(props.onDisabledPress)) { props.onDisabledPress?.(); return; } // 之前逻辑保持不动 if (!isFunction(props.onPress)) { return; } props.onPress(); }; // 预留向外界暴露的对象 useImperativeHandle(ref, () => ({})); const disableFinal = !( isFunction(props.onPress) || (props.disabled && isFunction(props.onDisabledPress)) ); return ( {leftArea} {rightArea} ); }; export default forwardRef(ListItem);