返回 AiToEarn
list.tsx
1 /**
2 * List - 列表组件
3 * 用于显示列表数据
4 */
5
6 'use client'
7
8 import { cn } from '@/utils/className'
9
10 interface ListItemMetaProps {
11 avatar?: React.ReactNode
12 title?: React.ReactNode
13 description?: React.ReactNode
14 }
15
16 function ListItemMeta({ avatar, title, description }: ListItemMetaProps) {
17 return (
18 <div className="flex gap-3">
19 {avatar && <div className="shrink-0">{avatar}</div>}
20 <div className="flex-1 min-w-0">
21 {title && <div className="font-medium mb-1">{title}</div>}
22 {description && <div className="text-sm text-muted-foreground">{description}</div>}
23 </div>
24 </div>
25 )
26 }
27
28 interface ListItemProps extends React.HTMLAttributes<HTMLDivElement> {
29 children?: React.ReactNode
30 }
31
32 function ListItem({ className, children, ...props }: ListItemProps) {
33 return (
34 <div
35 className={cn('p-4 border rounded-lg mb-2 cursor-pointer transition-all', className)}
36 {...props}
37 >
38 {children}
39 </div>
40 )
41 }
42
43 ListItem.Meta = ListItemMeta
44
45 interface ListProps<T = any> {
46 dataSource?: T[]
47 renderItem?: (item: T, index: number) => React.ReactNode
48 className?: string
49 children?: React.ReactNode
50 }
51
52 function List<T = any>({ dataSource, renderItem, className, children }: ListProps<T>) {
53 if (children) {
54 return <div className={cn('space-y-2', className)}>{children}</div>
55 }
56
57 if (!dataSource || !renderItem) {
58 return null
59 }
60
61 return (
62 <div className={cn('space-y-2', className)}>
63 {dataSource.map((item, index) => (
64 <div key={index}>{renderItem(item, index)}</div>
65 ))}
66 </div>
67 )
68 }
69
70 List.Item = ListItem
71
72 export { List, ListItem, ListItemMeta }
73
73 lines Plain Text