import { cva } from "class-variance-authority"; import React, { ReactNode } from "react"; import { Button, Card, CardProps, Spinner, Tooltip, } from "@sparkle/components/"; import { ImagePreview } from "@sparkle/components/ImagePreview"; import { XMarkIcon } from "@sparkle/icons/app"; import { cn } from "@sparkle/lib/utils"; const citationVariants = cva( "s-relative s-flex s-min-w-24 s-flex-none s-flex-col s-overflow-hidden", { variants: { hasImage: { // Use min() to maintain aspect ratio in grid mode (8% of width) while capping // padding at 3 (0.75rem) for list mode to prevent excessive top padding on wide items. false: "s-pt-[min(8%,theme(spacing.3))]", true: "s-border-0 s-p-0", }, }, defaultVariants: { hasImage: false, }, } ); type CitationProps = CardProps & { children: React.ReactNode; isLoading?: boolean; tooltip?: string; }; const Citation = React.forwardRef( ( { children, variant = "secondary", isLoading, className, tooltip, ...props }, ref ) => { const { hasDescription, hasImage } = React.useMemo(() => { const childrenArray = React.Children.toArray(children); return { hasDescription: childrenArray.some( (child) => React.isValidElement(child) && child.type === CitationDescription ), hasImage: childrenArray.some( (child) => React.isValidElement(child) && child.type === CitationImage ), }; }, [children]); // IMPORTANT: The order of elements is crucial for event handling. // The CitationDescription must always come after other elements to ensure // proper event propagation (especially for the close button's click events). // If auto-inserting a description, it must be appended after children. // Skip auto-insertion for CitationImage children since they're self-contained. const contentWithDescription = ( <> {children} {!hasDescription && !hasImage && (   )} ); const cardButton = ( {contentWithDescription} {isLoading && } ); if (tooltip) { return ; } return cardButton; } ); Citation.displayName = "Citation"; const CitationIndex = React.forwardRef< HTMLDivElement, React.HTMLAttributes >(({ children, className, ...props }, ref) => { return (
{children}
); }); CitationIndex.displayName = "CitationIndex"; const CITATION_GRID_VARIANTS = ["grid", "list"] as const; type CitationGridVariantType = (typeof CITATION_GRID_VARIANTS)[number]; const citationGridVariants = cva("s-grid s-gap-2", { variants: { variant: { grid: "s-grid-cols-2 @xxs:s-grid-cols-3 @xs:s-grid-cols-4 @md:s-grid-cols-5 @lg:s-grid-cols-6", list: "s-grid-cols-1", }, }, defaultVariants: { variant: "grid", }, }); interface CitationGridProps extends React.HTMLAttributes { variant?: CitationGridVariantType; } const CitationGrid = React.forwardRef( ({ children, className, variant, ...props }, ref) => { return (
{children}
); } ); CitationGrid.displayName = "CitationGrid"; interface CitationCloseProps extends React.ButtonHTMLAttributes { className?: string; onClick?: (e: React.MouseEvent) => void; } const CitationClose = React.forwardRef( ({ className, onClick, ...props }, ref) => { return (