import { Redo2, RotateCcw, Undo2 } from "lucide-react" import { Shimmer } from "@/components/ai-elements/shimmer" import { useVersionsContext, type VersionItem, } from "@/components/canvas/versions-context" import { useDictionary } from "@/hooks/use-dictionary" import { formatMessage } from "@/lib/i18n/utils" import { cn } from "@/lib/utils" import { describeChangeSummary, describeTotals } from "@/lib/version-text" import { useUiStore } from "@/stores/ui-store" /** Picture of a version (SVG data URL), or what stands in for it */ export function VersionThumb({ svg, dimmed, className, }: { /** undefined or null: still being made; "": none could be made */ svg: string | null | undefined dimmed?: boolean className?: string }) { const t = useDictionary().versions if (svg) { return ( // biome-ignore lint/performance/noImgElement: data URL thumbnail ) } if (svg === "") { return {t.noPreview} } return ( {t.rendering} ) } interface VersionCardProps extends React.ComponentProps<"div"> { version: VersionItem /** The newest version shows its picture; older ones fold into one row */ isLatest: boolean /** What happened ("Drew the diagram"); an undone change says so instead */ label: string /** Goes after the summary text (the chat adds its "Show XML" link) */ afterSummary?: React.ReactNode /** Panel below the card (the chat shows the AI's XML there) */ children?: React.ReactNode } /** * Card for one diagram version: picture, number, label, what changed, and * the action (undo or redo on the latest, restore on older ones). The * picture opens Compare. Other attributes go on the card's element. */ export function VersionCard({ version, isLatest, label, afterSummary, children, className, ...rest }: VersionCardProps) { const t = useDictionary().versions const source = useVersionsContext() const openCompare = useUiStore((s) => s.openCompare) const isUndone = source.undoneId === version.id const isOnCanvas = source.onCanvasId === version.id const title = isUndone ? t.undone : label const summary = version.fromScratch ? describeTotals(version.summary, t) : describeChangeSummary(version.summary, t) const badge = ( v{version.number} ) const actionClass = "inline-flex h-7 shrink-0 items-center gap-1 rounded-lg px-2 text-xs text-muted-foreground hover:bg-accent hover:text-foreground disabled:opacity-40" const restoreButton = ( ) const summaryLine = (
{summary} {afterSummary}
) if (!isLatest) { return (
{badge}
{title}
{summaryLine}
{restoreButton}
{children}
) } // Undo and redo belong to the newest change while it is (or was) on // the canvas; after an older version was restored, this one is // restored too const canUndo = source.canUndo || source.canRedo return (
{/* Title row with the action; the summary runs under both */}
{badge}
{title}
{canUndo ? ( ) : ( restoreButton )}
{summaryLine}
{children}
) }