import * as React from 'react' import { motion } from 'framer-motion' import { cva, type VariantProps } from 'class-variance-authority' import { cn } from '@/lib/utils' import { CloseLargeLine } from './icons-inline' const tagVariants = cva( 'inline-flex items-center justify-center gap-1.5 rounded-md border px-2.5 py-0.5 text-xs font-medium transition-colors whitespace-nowrap cursor-pointer group', { variants: { appearance: { filled: '', outline: 'bg-transparent' }, color: { primary: '', success: '', error: '', warning: '', info: '', link: '', pink: '', purple: '', yellow: '', orange: '', teal: '', blue: '', mauve: '', slate: '', lavender: '', sage: '', }, }, compoundVariants: [ { appearance: 'filled', color: 'primary', className: 'border-transparent bg-primary text-text-on-primary hover:bg-primary-hover' }, { appearance: 'filled', color: 'success', className: 'border-transparent bg-success-bg text-success border-success-border hover:bg-success-bg-hover' }, { appearance: 'filled', color: 'error', className: 'border-transparent bg-error-bg text-error border-error-border hover:bg-error-bg-hover' }, { appearance: 'filled', color: 'warning', className: 'border-transparent bg-warning-bg text-warning border-warning-border hover:bg-warning-bg-hover' }, { appearance: 'filled', color: 'info', className: 'border-transparent bg-info-bg text-info border-info-border hover:bg-info-bg-hover' }, { appearance: 'filled', color: 'link', className: 'border-transparent bg-transparent text-link underline-offset-4 hover:underline hover:text-link' }, { appearance: 'filled', color: 'pink', className: 'border-transparent bg-pink-bg text-pink hover:bg-pink-bg-hover' }, { appearance: 'filled', color: 'purple', className: 'border-transparent bg-purple-bg text-purple hover:bg-purple-bg-hover' }, { appearance: 'filled', color: 'yellow', className: 'border-transparent bg-yellow-bg text-yellow hover:bg-yellow-bg-hover' }, { appearance: 'filled', color: 'orange', className: 'border-transparent bg-orange-bg text-orange hover:bg-orange-bg-hover' }, { appearance: 'filled', color: 'teal', className: 'border-transparent bg-teal-bg text-teal hover:bg-teal-bg-hover' }, { appearance: 'filled', color: 'blue', className: 'border-transparent bg-blue-bg text-blue hover:bg-blue-bg-hover' }, { appearance: 'filled', color: 'mauve', className: 'border-transparent bg-mauve-bg text-mauve hover:bg-mauve-bg-hover' }, { appearance: 'filled', color: 'slate', className: 'border-transparent bg-slate-bg text-slate hover:bg-slate-bg-hover' }, { appearance: 'filled', color: 'lavender', className: 'border-transparent bg-lavender-bg text-lavender hover:bg-lavender-bg-hover' }, { appearance: 'filled', color: 'sage', className: 'border-transparent bg-sage-bg text-sage hover:bg-sage-bg-hover' }, { appearance: 'outline', color: 'primary', className: 'border-primary-border text-primary hover:bg-primary-bg' }, { appearance: 'outline', color: 'success', className: 'border-success-border text-success hover:bg-success-bg' }, { appearance: 'outline', color: 'error', className: 'border-error-border text-error hover:bg-error-bg' }, { appearance: 'outline', color: 'warning', className: 'border-warning-border text-warning hover:bg-warning-bg' }, { appearance: 'outline', color: 'info', className: 'border-info-border text-info hover:bg-info-bg' }, { appearance: 'outline', color: 'link', className: 'border-transparent text-link underline-offset-4 hover:underline hover:text-link' }, { appearance: 'outline', color: 'pink', className: 'border-pink text-pink hover:bg-pink-bg' }, { appearance: 'outline', color: 'purple', className: 'border-purple text-purple hover:bg-purple-bg' }, { appearance: 'outline', color: 'yellow', className: 'border-yellow text-yellow hover:bg-yellow-bg' }, { appearance: 'outline', color: 'orange', className: 'border-orange text-orange hover:bg-orange-bg' }, { appearance: 'outline', color: 'teal', className: 'border-teal text-teal hover:bg-teal-bg' }, { appearance: 'outline', color: 'blue', className: 'border-blue text-blue hover:bg-blue-bg' }, { appearance: 'outline', color: 'mauve', className: 'border-mauve text-mauve hover:bg-mauve-bg' }, { appearance: 'outline', color: 'slate', className: 'border-slate text-slate hover:bg-slate-bg' }, { appearance: 'outline', color: 'lavender', className: 'border-lavender text-lavender hover:bg-lavender-bg' }, { appearance: 'outline', color: 'sage', className: 'border-sage text-sage hover:bg-sage-bg' }, ], defaultVariants: { appearance: 'filled', color: 'primary' }, } ) export interface TagProps extends Omit, 'color'>, VariantProps { closable?: boolean onClose?: (event: React.MouseEvent | React.KeyboardEvent) => void closeAriaLabel?: string closeIcon?: React.ReactNode } const Tag = React.forwardRef( ( { className, appearance = 'filled', color = 'primary', closable = false, onClose, closeAriaLabel = 'Close tag', closeIcon, children, onMouseEnter: onMouseEnterProp, onMouseLeave: onMouseLeaveProp, ...props }, ref ) => { const [isHovered, setIsHovered] = React.useState(false) const [isCloseFocused, setIsCloseFocused] = React.useState(false) const showClose = closable && typeof onClose === 'function' const showCloseControl = isHovered || isCloseFocused const handleMouseEnter = (e: React.MouseEvent) => { if (showClose) setIsHovered(true) onMouseEnterProp?.(e) } const handleMouseLeave = (e: React.MouseEvent) => { if (showClose) setIsHovered(false) onMouseLeaveProp?.(e) } const handleCloseClick = (e: React.MouseEvent) => { e.preventDefault() e.stopPropagation() onClose?.(e) } const handleCloseKeyDown = (e: React.KeyboardEvent) => { if (e.key !== 'Enter' && e.key !== ' ') return e.preventDefault() e.stopPropagation() onClose?.(e) } return ( {children} {showClose && ( )} ) } ) Tag.displayName = 'Tag' export { Tag, tagVariants }