import * as React from "react" import { ChevronRightIcon } from "lucide-react" import { cn } from "@/lib/utils" export type ListItem = { key: string title: React.ReactNode description?: React.ReactNode avatar?: React.ReactNode extra?: React.ReactNode href?: string disabled?: boolean onClick?: () => void } export type ListProps = React.ComponentProps<"div"> & { items?: ListItem[] bordered?: boolean split?: boolean size?: "sm" | "md" | "lg" renderItem?: (item: ListItem, index: number) => React.ReactNode } const itemPadding = { sm: "px-3 py-2", md: "px-4 py-3", lg: "px-5 py-4", } function List({ items, bordered = true, split = true, size = "md", renderItem, className, children, ...props }: ListProps) { return (
{items?.map((item, index) => renderItem?.(item, index) ?? )} {children}
) } export type ListRowProps = React.ComponentProps<"div"> & { item: ListItem split?: boolean size?: "sm" | "md" | "lg" } function ListRow({ item, split = true, size = "md", className, ...props }: ListRowProps) { const clickable = Boolean(item.href || item.onClick) const content = ( <> {item.avatar &&
{item.avatar}
}
{item.title}
{item.description &&
{item.description}
}
{item.extra &&
{item.extra}
} {clickable && } ) const rowClassName = cn( "flex items-center gap-3 bg-card transition-colors", itemPadding[size], split && "border-b last:border-b-0", clickable && !item.disabled && "cursor-pointer hover:bg-muted/50", item.disabled && "pointer-events-none opacity-55", className ) if (item.href) { return ( )} > {content} ) } return (
)} > {content}
) } export { List, ListRow }