import { Slot } from '@radix-ui/react-slot'; import { cva, type VariantProps } from 'class-variance-authority'; import * as React from 'react'; import { cn } from '@/lib/classMerge'; import { CircleSpinnerLoader } from '../loaders/CircleSpinnerLoader'; export const buttonTypeClasses = { default: 'bg-background border hover:bg-item-hover disabled:bg-disabled disabled:text-gray-light active:bg-item-active data-[selected=true]:bg-item-select', black: 'bg-black text-white hover:bg-foreground-hover disabled:bg-black/60', outlined: 'bg-transparent border border-border text-gray-dark hover:bg-item-hover disabled:bg-transparent disabled:text-gray-light active:bg-item-active data-[selected=true]:bg-item-select', primary: 'bg-primary disabled:bg-disabled text-white hover:bg-primary-light disabled:text-gray-light active:bg-primary-dark data-[selected=true]:bg-primary-dark', ghost: 'bg-transparent text-gray-dark shadow-none hover:bg-item-hover hover:text-foreground disabled:bg-transparent disabled:text-gray-light active:bg-item-active data-[selected=true]:bg-item-select', link: 'bg-transparent text-gray-dark shadow-none hover:text-foreground disabled:bg-transparent disabled:text-gray-light', danger: 'bg-danger-background text-danger-foreground hover:bg-danger-background-hover active:bg-danger-background-hover data-[selected=true]:bg-danger-background-hover', warning: 'bg-warning-background text-warning-foreground hover:bg-warning-background-hover active:bg-warning-background-hover data-[selected=true]:bg-warning-background-hover', success: 'bg-success-background text-success-foreground hover:bg-success-background-hover active:bg-success-background-hover data-[selected=true]:bg-success-background-hover' }; const roundingVariants = { default: 'rounded', full: 'rounded-full', large: 'rounded-lg', small: 'rounded-sm', none: 'rounded-none' }; const sizeVariants = { default: 'h-6 min-h-6 max-h-6', tall: 'h-7 min-h-7 max-h-7', small: 'h-5 min-h-5 max-h-5' }; export const buttonVariants = cva( 'inline-flex whitespace-nowrap items-center overflow-hidden text-base justify-center gap-1.5 shadow rounded transition-all duration-300 focus-visible:outline-none disabled:pointer-events-none disabled:cursor-not-allowed data-[loading=true]:cursor-progress', { variants: { variant: buttonTypeClasses, size: sizeVariants, iconButton: { true: '', false: 'px-2.5' }, rounding: roundingVariants, block: { true: 'w-full', false: '' } }, compoundVariants: [ { iconButton: true, size: 'default', className: 'w-6 min-w-6 max-w-6' }, { iconButton: true, size: 'tall', className: 'w-7 min-w-7 max-w-7' }, { iconButton: true, size: 'small', className: 'w-5 min-w-5 max-w-5' } ], defaultVariants: { variant: 'default', size: 'default', iconButton: false, block: false } } ); export const buttonIconVariants = cva('', { variants: { variant: { default: 'text-icon-color', black: 'text-white!', outlined: 'text-icon-color', primary: 'text-white', ghost: 'text-icon-color', link: 'text-icon-color', danger: 'text-danger-foreground', warning: 'text-warning-foreground', success: 'text-success-foreground' }, size: { default: 'text-icon-size!', tall: 'text-icon-size-lg!', small: 'text-icon-size-sm!' }, disabled: { true: 'text-gray-light', false: '' } }, compoundVariants: [ { variant: 'black', disabled: true, className: 'text-white' }, { variant: 'outlined', size: 'tall', className: 'text-icon-size!' } ] }); const loadingSizeVariants = { default: 'w-[var(--text-icon-size)] h-[var(--text-icon-size)]', tall: 'w-[var(--text-icon-size-lg)] h-[var(--text-icon-size-lg)]', small: 'w-[var(--text-icon-size-sm)] h-[var(--text-icon-size-sm)]' }; export interface ButtonProps extends Omit, 'prefix'>, VariantProps { asChild?: boolean; prefix?: React.ReactNode; suffix?: React.ReactNode; loading?: boolean; selected?: boolean; prefixClassName?: string; suffixClassName?: string; block?: boolean; } export const Button = React.forwardRef( ( { className = '', variant = 'default', size = 'default', asChild = false, prefix, suffix, children, loading = false, selected = false, disabled = false, prefixClassName, suffixClassName, rounding = 'default', block = false, onClick, ...props }, ref ) => { const Comp = asChild ? Slot : 'button'; const hasChildren = !!children; const iconButton = !hasChildren && (!prefix || !suffix); return ( {loading ? ( ) : ( prefix && ( {prefix} ) )} {hasChildren && {children}} {suffix && ( {suffix} )} ); } ); Button.displayName = 'Button'; export const LoadingIcon: React.FC<{ variant: ButtonProps['variant']; size: ButtonProps['size']; }> = ({ variant = 'default', size = 'default' }) => { return (
); };