This commit is contained in:
oneao committed 2025-11-20 17:30:28 +08:00
1 parent 63b168affc
commit 069b4506e4
29 files changed
+1077 -1116

No files matched your search

@@ -0,0 +1,105 @@
import type { icons } from 'lucide-react-native'
import type { ReactElement, ReactNode } from 'react'
import type { ViewStyle } from 'react-native'
import { Children, cloneElement, isValidElement } from 'react'
import { Text, TouchableOpacity, View } from 'react-native'
import LucideIcon from './LucideIcon'
/* ================= Cell ================= */
export interface CellProps {
left?: ReactNode
right?: ReactNode
title?: string
leftIcon?: keyof typeof icons
rightIcon?: keyof typeof icons
rightText?: string
isLink?: boolean
className?: string
style?: ViewStyle
showDivider?: boolean // 由 CellGroup 注入
onPress?: () => void
}
export function Cell({
left,
right,
title,
leftIcon,
rightIcon = 'ChevronRight',
rightText,
isLink = false,
className,
style,
showDivider = false,
onPress,
}: CellProps) {
return (
<View>
<TouchableOpacity
activeOpacity={isLink ? 0.5 : 1}
className={`flex flex-row items-center justify-between px-4 py-3 ${className}`}
style={style}
onPress={onPress}
>
{left || (
<View className="flex flex-row items-center space-x-2">
{leftIcon && <LucideIcon icon={leftIcon} size={18} />}
{title && <Text className="text-base text-gray-900 ml-2">{title}</Text>}
</View>
)}
{right || (
<View className="flex flex-row items-center ">
{rightText && <Text className="text-gray-500 text-base mr-2">{rightText}</Text>}
{isLink && rightIcon && (
<LucideIcon icon={rightIcon} size={16} color="#9ca3af" />
)}
</View>
)}
</TouchableOpacity>
{showDivider && (
<View
className="bg-gray-100"
style={{ marginLeft: 16, marginRight: 16, height: 1 }}
/>
)}
</View>
)
}
/* ================= CellGroup ================= */
export interface CellGroupProps {
className?: string
style?: ViewStyle
children?: ReactNode
showDivider?: boolean // 整组是否显示下划线
}
export function CellGroup({
className,
style,
children,
showDivider = true,
}: CellGroupProps) {
const elements = Children.toArray(children)
return (
<View className={`bg-white ${className}`} style={style}>
{elements.map((child, index) => {
if (!isValidElement<CellProps>(child))
return child
const isLast = index === elements.length - 1
return cloneElement<CellProps>(child as ReactElement<CellProps>, {
showDivider: showDivider && !isLast,
})
})}
</View>
)
}