import * as React from "react" import { CircleIcon } from "lucide-react" import { cn } from "@/lib/utils" export type TimelineTone = "default" | "success" | "info" | "warning" | "danger" | "muted" export type TimelineOrientation = "vertical" | "horizontal" export type TimelineItem = { key: string title?: React.ReactNode description?: React.ReactNode time?: React.ReactNode icon?: React.ReactNode tone?: TimelineTone content?: React.ReactNode actions?: React.ReactNode hidden?: boolean className?: string } export type TimelineProps = React.ComponentProps<"div"> & { items: TimelineItem[] orientation?: TimelineOrientation pending?: boolean pendingLabel?: React.ReactNode compact?: boolean itemClassName?: string } const dotClassName: Record = { default: "border-primary bg-primary text-primary-foreground", success: "border-emerald-500 bg-emerald-500 text-white", info: "border-blue-500 bg-blue-500 text-white", warning: "border-amber-500 bg-amber-500 text-white", danger: "border-destructive bg-destructive text-destructive-foreground", muted: "border-muted-foreground bg-muted-foreground text-background", } function Timeline({ items, orientation = "vertical", pending = false, pendingLabel = "Pending", compact = false, itemClassName, className, ...props }: TimelineProps) { const visibleItems = items.filter((item) => !item.hidden) if (orientation === "horizontal") { return (
{visibleItems.map((item) => ( ))} {pending && }
) } return (
{visibleItems.map((item, index) => ( ))} {pending && }
) } function TimelineDot({ item }: { item: TimelineItem }) { const tone = item.tone ?? "default" return ( {item.icon ?? } ) } function TimelineVerticalItem({ item, compact, className, isLast }: { item: TimelineItem; compact: boolean; className?: string; isLast?: boolean }) { return (
{!isLast &&
}
{item.title &&
{item.title}
} {item.description &&
{item.description}
}
{item.time &&
{item.time}
}
{item.content &&
{item.content}
} {item.actions &&
{item.actions}
}
) } function TimelineHorizontalItem({ item, compact, className }: { item: TimelineItem; compact: boolean; className?: string }) { return (
{item.time &&
{item.time}
}
{item.title &&
{item.title}
} {item.description &&
{item.description}
} {item.content &&
{item.content}
} {item.actions &&
{item.actions}
}
) } export { Timeline }