{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "auth-verify-email",
  "title": "Auth Verify Email",
  "description": "Email verification status with resend functionality.",
  "registryDependencies": [
    "button",
    "card"
  ],
  "files": [
    {
      "path": "registry/new-york/blocks/auth/auth-verify-email.tsx",
      "content": "\"use client\";\n\nimport {\n  CheckCircle2,\n  Clock,\n  Loader2,\n  Mail,\n  RefreshCw,\n  XCircle,\n} from \"lucide-react\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport { Button } from \"@/registry/new-york/ui/button\";\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardHeader,\n  CardTitle,\n} from \"@/registry/new-york/ui/card\";\n\nexport type VerificationStatus =\n  | \"pending\"\n  | \"verifying\"\n  | \"verified\"\n  | \"expired\"\n  | \"error\";\n\ninterface StatusIconProps {\n  status: VerificationStatus;\n}\n\nfunction StatusIcon({ status }: StatusIconProps) {\n  switch (status) {\n    case \"verified\":\n      return (\n        <div className=\"flex size-16 items-center justify-center rounded-full bg-primary/10\">\n          <CheckCircle2 aria-hidden=\"true\" className=\"size-8 text-primary\" />\n        </div>\n      );\n    case \"verifying\":\n      return (\n        <div className=\"flex size-16 items-center justify-center rounded-full bg-primary/10\">\n          <Loader2\n            aria-hidden=\"true\"\n            className=\"size-8 animate-spin text-primary\"\n          />\n        </div>\n      );\n    case \"expired\":\n    case \"error\":\n      return (\n        <div className=\"flex size-16 items-center justify-center rounded-full bg-destructive/10\">\n          <XCircle aria-hidden=\"true\" className=\"size-8 text-destructive\" />\n        </div>\n      );\n    default:\n      return (\n        <div className=\"flex size-16 items-center justify-center rounded-full bg-muted\">\n          <Mail aria-hidden=\"true\" className=\"size-8 text-muted-foreground\" />\n        </div>\n      );\n  }\n}\n\ninterface StatusHeaderProps {\n  status: VerificationStatus;\n  email?: string;\n  errorMessage?: string;\n}\n\nfunction StatusHeader({ status, email, errorMessage }: StatusHeaderProps) {\n  const getStatusContent = (): { title: string; description: string } => {\n    switch (status) {\n      case \"verified\":\n        return {\n          title: \"Email verified\",\n          description: \"Your email address has been successfully verified.\",\n        };\n      case \"verifying\":\n        return {\n          title: \"Verifying email\",\n          description: \"Please wait while we verify your email address…\",\n        };\n      case \"expired\":\n        return {\n          title: \"Verification link expired\",\n          description:\n            \"The verification link has expired. Please request a new one.\",\n        };\n      case \"error\":\n        return {\n          title: \"Verification failed\",\n          description:\n            errorMessage ||\n            \"Something went wrong. Please try requesting a new verification link.\",\n        };\n      default:\n        return {\n          title: \"Verify your email\",\n          description: email\n            ? `We've sent a verification link to ${email}. Please check your inbox and click the link to verify your email address.`\n            : \"We've sent a verification link to your email address. Please check your inbox and click the link to verify your email address.\",\n        };\n    }\n  };\n\n  const content = getStatusContent();\n\n  return (\n    <>\n      <CardTitle>{content.title}</CardTitle>\n      <CardDescription>{content.description}</CardDescription>\n    </>\n  );\n}\n\nfunction PendingStateHelp() {\n  return (\n    <div className=\"flex items-center gap-2 rounded-lg border bg-muted/50 p-4\">\n      <Clock\n        aria-hidden=\"true\"\n        className=\"size-4 shrink-0 text-muted-foreground\"\n      />\n      <div className=\"flex flex-col gap-1\">\n        <p className=\"font-medium text-sm\">Didn&apos;t receive the email?</p>\n        <p className=\"text-muted-foreground text-xs\">\n          Check your spam folder or try resending the verification link.\n        </p>\n      </div>\n    </div>\n  );\n}\n\ninterface ResendButtonProps {\n  cooldown: number;\n  isResending: boolean;\n  onResend: () => void;\n  variant?: \"default\" | \"outline\";\n  label?: string;\n}\n\nfunction ResendButton({\n  cooldown,\n  isResending,\n  onResend,\n  variant = \"default\",\n  label = \"Resend verification email\",\n}: ResendButtonProps) {\n  return (\n    <Button\n      aria-busy={isResending}\n      className=\"min-h-[44px] w-full touch-manipulation sm:min-h-[32px]\"\n      data-loading={isResending}\n      disabled={cooldown > 0 || isResending}\n      onClick={onResend}\n      type=\"button\"\n      variant={variant}\n    >\n      {isResending ? (\n        <>\n          <Loader2 aria-hidden=\"true\" className=\"size-4 animate-spin\" />\n          Sending…\n        </>\n      ) : cooldown > 0 ? (\n        <>\n          <RefreshCw aria-hidden=\"true\" className=\"size-4\" />\n          Resend in {cooldown}s\n        </>\n      ) : (\n        <>\n          <RefreshCw aria-hidden=\"true\" className=\"size-4\" />\n          {label}\n        </>\n      )}\n    </Button>\n  );\n}\n\ninterface PendingStateProps {\n  onResend?: () => void;\n  cooldown: number;\n  isResending: boolean;\n}\n\nfunction PendingState({ onResend, cooldown, isResending }: PendingStateProps) {\n  return (\n    <div className=\"flex w-full flex-col gap-4\">\n      <PendingStateHelp />\n      {onResend && (\n        <ResendButton\n          cooldown={cooldown}\n          isResending={isResending}\n          onResend={onResend}\n          variant=\"outline\"\n        />\n      )}\n    </div>\n  );\n}\n\ninterface ExpiredErrorStateProps {\n  onResend?: () => void;\n  cooldown: number;\n  isResending: boolean;\n}\n\nfunction ExpiredErrorState({\n  onResend,\n  cooldown,\n  isResending,\n}: ExpiredErrorStateProps) {\n  if (!onResend) return null;\n\n  return (\n    <ResendButton\n      cooldown={cooldown}\n      isResending={isResending}\n      label=\"Request new verification link\"\n      onResend={onResend}\n    />\n  );\n}\n\nfunction VerifiedState() {\n  return (\n    <div className=\"w-full rounded-lg border border-primary/20 bg-primary/5 p-4 text-center\">\n      <p className=\"font-medium text-primary text-sm\">\n        You can now use all features of your account.\n      </p>\n    </div>\n  );\n}\n\nexport interface AuthVerifyEmailProps {\n  email?: string;\n  status?: VerificationStatus;\n  onResend?: () => void;\n  onVerify?: (token: string) => void;\n  className?: string;\n  isLoading?: boolean;\n  errorMessage?: string;\n  resendCooldown?: number;\n}\n\nexport default function AuthVerifyEmail({\n  email,\n  status = \"pending\",\n  onResend,\n  onVerify,\n  className,\n  isLoading = false,\n  errorMessage,\n  resendCooldown = 60,\n}: AuthVerifyEmailProps) {\n  const [cooldown, setCooldown] = useState(0);\n  const [isResending, setIsResending] = useState(false);\n\n  useEffect(() => {\n    if (cooldown > 0) {\n      const timer = setTimeout(() => {\n        setCooldown((prev) => prev - 1);\n      }, 1000);\n      return () => clearTimeout(timer);\n    }\n  }, [cooldown]);\n\n  const handleResend = useCallback(async () => {\n    if (cooldown > 0 || isResending) return;\n    setIsResending(true);\n    try {\n      await onResend?.();\n      setCooldown(resendCooldown);\n    } finally {\n      setIsResending(false);\n    }\n  }, [cooldown, isResending, onResend, resendCooldown]);\n\n  return (\n    <Card className={cn(\"w-full max-w-sm shadow-xs\", className)}>\n      <CardHeader>\n        <StatusHeader\n          email={email}\n          errorMessage={errorMessage}\n          status={status}\n        />\n      </CardHeader>\n      <CardContent>\n        <div className=\"flex flex-col items-center gap-6\">\n          <StatusIcon status={status} />\n\n          {status === \"pending\" && (\n            <PendingState\n              cooldown={cooldown}\n              isResending={isResending}\n              onResend={onResend}\n            />\n          )}\n\n          {(status === \"expired\" || status === \"error\") && (\n            <ExpiredErrorState\n              cooldown={cooldown}\n              isResending={isResending}\n              onResend={onResend}\n            />\n          )}\n\n          {status === \"verified\" && <VerifiedState />}\n        </div>\n      </CardContent>\n    </Card>\n  );\n}\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "block",
    "auth"
  ],
  "type": "registry:ui"
}