{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"copy-button","type":"registry:ui","title":"Copy Button","description":"An icon button that copies text. The copy icon pops into a check, then back.","dependencies":["@radix-ui/react-slot@^1.3.3","@untitledui/icons@^0.0.23","class-variance-authority@^0.7.1","motion@^14.0.0"],"files":[{"path":"components/ui/copy-button.tsx","type":"registry:ui","content":"\"use client\";\n\nimport { Check, Copy01 } from \"@untitledui/icons\";\nimport { AnimatePresence, motion } from \"motion/react\";\nimport { useState } from \"react\";\nimport { Button } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\n\nfunction CopyButton({ value, label, className }: { value: string; label: string; className?: string }) {\n  const [copied, setCopied] = useState(false);\n\n  return (\n    <Button\n      variant=\"ghost\"\n      size=\"icon\"\n      className={cn(\"text-muted-foreground size-7 shrink-0\", className)}\n      aria-label={copied ? \"Copied\" : label}\n      onClick={() => {\n        void navigator.clipboard\n          ?.writeText(value)\n          .then(() => {\n            setCopied(true);\n            setTimeout(() => setCopied(false), 1500);\n          })\n          .catch(() => undefined);\n      }}\n    >\n      <AnimatePresence mode=\"wait\" initial={false}>\n        <motion.span\n          key={copied ? \"copied\" : \"copy\"}\n          initial={{ opacity: 0, scale: 0.6 }}\n          animate={{ opacity: 1, scale: 1 }}\n          exit={{ opacity: 0, scale: 0.6 }}\n          transition={{ duration: 0.15 }}\n        >\n          {copied ? <Check className=\"text-foreground\" /> : <Copy01 />}\n        </motion.span>\n      </AnimatePresence>\n    </Button>\n  );\n}\n\nexport { CopyButton };\n"},{"path":"components/ui/button.tsx","type":"registry:ui","content":"import { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { type HTMLMotionProps, motion } from \"motion/react\";\nimport * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nconst buttonVariants = cva(\n  \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-lg text-sm font-medium transition-[color,background-color,border-color,box-shadow,opacity] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-solid focus-visible:outline-foreground aria-invalid:focus-visible:outline-destructive aria-invalid:border-destructive\",\n  {\n    variants: {\n      variant: {\n        default:\n          \"bg-primary text-primary-foreground bg-[linear-gradient(to_bottom,rgb(255_255_255/0.12),transparent)] shadow-[inset_0_1px_0_rgb(255_255_255/0.18),0_1px_2px_rgb(0_0_0/0.2),0_0_0_1px_var(--primary)] hover:bg-primary/90\",\n        destructive:\n          \"bg-destructive text-white bg-[linear-gradient(to_bottom,rgb(255_255_255/0.14),transparent)] shadow-[inset_0_1px_0_rgb(255_255_255/0.2),0_1px_2px_rgb(0_0_0/0.2),0_0_0_1px_var(--destructive)] hover:bg-destructive/90\",\n        outline:\n          \"border bg-background shadow-[0_1px_2px_rgb(0_0_0/0.05),inset_0_-1px_0_rgb(0_0_0/0.05)] hover:bg-accent/60 hover:border-foreground/20 dark:bg-input/30 dark:border-input dark:shadow-[inset_0_1px_0_rgb(255_255_255/0.05)] dark:hover:bg-input/50\",\n        secondary: \"bg-secondary text-secondary-foreground hover:bg-secondary/70\",\n        ghost: \"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50\",\n        link: \"text-foreground underline underline-offset-4 decoration-foreground/30 hover:decoration-foreground\",\n      },\n      size: {\n        default: \"h-9 px-4 py-2 has-[>svg]:px-3\",\n        sm: \"h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5\",\n        lg: \"h-10 px-6 has-[>svg]:px-4\",\n        icon: \"size-9\",\n      },\n    },\n    defaultVariants: {\n      variant: \"default\",\n      size: \"default\",\n    },\n  },\n);\n\nfunction Button({\n  className,\n  variant,\n  size,\n  asChild = false,\n  ...props\n}: React.ComponentProps<\"button\"> &\n  VariantProps<typeof buttonVariants> & {\n    asChild?: boolean;\n  }) {\n  const classes = cn(buttonVariants({ variant, size, className }));\n\n  if (asChild) {\n    return <Slot data-slot=\"button\" className={classes} {...props} />;\n  }\n\n  return (\n    <motion.button\n      data-slot=\"button\"\n      whileTap={{ scale: 0.97 }}\n      transition={{ type: \"spring\", stiffness: 600, damping: 30 }}\n      className={classes}\n      {...(props as HTMLMotionProps<\"button\">)}\n    />\n  );\n}\n\nexport { Button, buttonVariants };\n"}]}