import * as React from "react" import { Slot } from "@radix-ui/react-slot" import { cva, type VariantProps } from "class-variance-authority" import { cn } from "@/lib/utils" // Loading 图标组件 export const LoadingIcon = ({ className }: { className?: string }) => ( ) const buttonVariants = cva( "inline-flex items-center justify-center gap-2 whitespace-nowrap transition-all disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive cursor-pointer", { variants: { variant: { primary: "bg-primary-gradient-normal disabled:bg-none disabled:bg-primary-variant-disabled disabled:text-txt-primary-disabled disabled:backdrop-blur-lg text-txt-primary-specialmap-normal shadow-xs hover:bg-primary-gradient-hover active:bg-primary-gradient-press", secondary: "border border-solid border-primary-variant-normal text-primary-variant-normal disabled:border-primary-variant-disabled disabled:text-txt-primary-disabled hover:border-primary-variant-hover hover:text-primary-variant-hover active:border-primary-variant-press active:text-primary-variant-press", tertiary: "bg-surface-element-normal text-txt-primary-normal disabled:bg-surface-element-disabled disabled:text-txt-primary-disabled hover:bg-surface-element-hover active:bg-surface-element-press", tertiaryDark: "bg-surface-element-dark-normal text-txt-primary-normal disabled:bg-surface-element-dark-disabled disabled:text-txt-primary-disabled hover:bg-surface-element-dark-hover active:bg-surface-element-dark-press", destructive: "bg-important-normal text-txt-primary-normal disabled:bg-important-disabled disabled:text-txt-primary-disabled disabled:backdrop-blur-lg hover:bg-important-hover active:bg-important-press", ghost: "bg-transparent text-primary-variant-normal disabled:text-txt-primary-disabled hover:bg-surface-element-hover hover:backdrop-blur-[16px] active:bg-surface-element-press", vip: "bg-gradient-secondary-normal text-black" }, size: { large: "min-w-[128px] h-12 rounded-full px-8 has-[>svg]:px-6 txt-label-l", small: "min-w-[80px] h-8 rounded-full px-4 has-[>svg]:px-2 txt-label-s", icon: "size-9", }, block: { true: "w-full", false: "", }, loading: { true: "cursor-not-allowed backdrop-blur backdrop-filter", false: "", }, }, defaultVariants: { variant: "primary", size: "large", block: false, loading: false, }, } ) const iconButtonVariants = cva( "inline-flex items-center justify-center transition-all disabled:pointer-events-none [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none rounded-full cursor-pointer", { variants: { variant: { default: "bg-primary-gradient-normal text-txt-primary-normal disabled:bg-primary-gradient-disabled disabled:bg-none disabled:text-txt-primary-disabled hover:bg-primary-gradient-hover active:bg-primary-gradient-press", primary: "bg-primary-normal text-txt-primary-normal disabled:bg-primary-disabled disabled:text-txt-primary-disabled hover:bg-primary-hover active:bg-primary-press", tertiary: "bg-surface-element-normal text-txt-primary-normal disabled:bg-surface-element-disabled disabled:text-txt-primary-disabled hover:bg-surface-element-hover active:bg-surface-element-press", tertiaryDark: "bg-surface-element-dark-normal text-txt-primary-normal disabled:bg-surface-element-dark-disabled disabled:text-txt-primary-specialmap-disable hover:bg-surface-element-dark-hover active:bg-surface-element-dark-press", contrast: "bg-surface-element-light-normal text-txt-primary-normal disabled:bg-surface-element-light-disabled disabled:text-txt-primary-disabled hover:bg-surface-element-light-hover active:bg-surface-element-light-press", ghost: "bg-transparent text-txt-primary-normal disabled:text-txt-primary-disabled hover:bg-surface-element-hover hover:backdrop-blur-[16px] active:bg-surface-element-press", destructive: "bg-important-normal text-txt-primary-normal disabled:bg-important-disabled disabled:text-txt-primary-disabled disabled:backdrop-blur-lg hover:bg-important-hover active:bg-important-press", }, size: { large: "size-12 [&_svg:not([class*='size-'])]:size-6 [&_i]:!text-[24px]", small: "size-8 [&_svg:not([class*='size-'])]:size-4 [&_i]:!text-[16px]", xs: "size-6 [&_svg:not([class*='size-'])]:size-3 [&_i]:!text-[12px]", mini: "size-4 [&_svg:not([class*='size-'])]:size-2 [&_i]:!text-[8px]", }, loading: { true: "cursor-not-allowed backdrop-blur backdrop-filter", false: "", }, }, defaultVariants: { variant: "default", size: "large", loading: false, }, } ) function Button({ className, variant, size, block, loading = false, children, asChild = false, disabled, ...props }: React.ComponentProps<"button"> & VariantProps & { asChild?: boolean, block?: boolean, loading?: boolean }) { const Comp = asChild ? Slot : "button" // 当 loading 为 true 时,自动禁用按钮 const isDisabled = disabled || loading return ( {loading && ( )} {/* 当 loading 时,如果有 children 则显示,否则只显示 loading 图标 */} {!loading ? children : null} ) } function IconButton({ className, variant, iconfont, size, loading = false, children, asChild = false, disabled, ...props }: React.ComponentProps<"button"> & VariantProps & { iconfont?: string, asChild?: boolean, loading?: boolean }) { const Comp = asChild ? Slot : "button" // 当 loading 为 true 时,自动禁用按钮 const isDisabled = disabled || loading return ( {loading ? ( ) : ( <> {iconfont && } {children} )} ) } export { Button, IconButton, buttonVariants, iconButtonVariants }