{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "otp-email",
  "title": "OTP Email",
  "description": "Email template component that sends one-time password (OTP) verification codes to users.",
  "dependencies": [
    "@better-auth-ui/react@latest",
    "@better-auth-ui/core@latest",
    "react-email"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "../../packages/react/src/components/auth/email/otp-email.tsx",
      "content": "import type { ReactNode } from \"react\"\nimport {\n  Body,\n  Container,\n  Head,\n  Heading,\n  Hr,\n  Html,\n  Img,\n  Link,\n  Preview,\n  pixelBasedPreset,\n  Section,\n  Tailwind,\n  Text\n} from \"react-email\"\n\nimport { cn } from \"../../../lib/utils\"\nimport {\n  type EmailClassNames,\n  type EmailColors,\n  EmailStyles\n} from \"./email-styles\"\n\nconst otpEmailLocalization = {\n  YOUR_VERIFICATION_CODE_IS_CODE:\n    \"Your verification code is {verificationCode}\",\n  LOGO: \"Logo\",\n  VERIFY_YOUR_EMAIL: \"Verify your email\",\n  WE_NEED_TO_VERIFY_YOUR_EMAIL_ADDRESS:\n    \"We need to verify your email address {email} before you can access your {appName} account. Enter the code below in your open browser window.\",\n  THIS_CODE_EXPIRES_IN_MINUTES:\n    \"This code expires in {expirationMinutes} minutes.\",\n  EMAIL_SENT_BY: \"Email sent by {appName}.\",\n  IF_YOU_DIDNT_REQUEST_THIS_EMAIL:\n    \"If you didn't request this email, you can safely ignore it. Someone else might have typed your email address by mistake.\",\n  POWERED_BY_BETTER_AUTH: \"Powered by {betterAuth}\"\n}\n\n/**\n * Localization strings for the OtpEmail component.\n *\n * Contains all text content used in the OTP (One-Time Password) email template.\n */\nexport type OtpEmailEmailLocalization = typeof otpEmailLocalization\n\n/**\n * Props for the OtpEmail component.\n */\nexport interface OtpEmailProps {\n  /** The one-time verification code to display */\n  verificationCode: string\n  /** Email address being verified */\n  email?: string\n  /** Name of the application sending the email */\n  appName?: string\n  /** Number of minutes until the verification code expires */\n  expirationMinutes?: number\n  /** Logo URL(s) - a single string or light/dark variants. If omitted, no logo is shown. */\n  logoURL?: string | { light: string; dark: string }\n  /** Custom CSS class names for styling specific parts of the email */\n  classNames?: EmailClassNames\n  /** Custom color scheme for light and dark modes */\n  colors?: EmailColors\n  /** Whether to show the \"Powered by better-auth\" footer */\n  poweredBy?: boolean\n  /** Whether to enable dark mode support */\n  darkMode?: boolean\n  /** Additional React nodes to inject into the email head */\n  head?: ReactNode\n  /**\n   * Localization overrides for customizing email text\n   * @remarks `OtpEmailEmailLocalization`\n   */\n  localization?: Partial<OtpEmailEmailLocalization>\n}\n\n/**\n * Email template component that sends one-time password (OTP) verification codes to users.\n *\n * This email includes:\n * - Large, prominently displayed verification code\n * - Expiration time information\n * - Security notice for unauthorized requests\n * - Customizable branding and styling\n * - Support for light/dark mode themes\n *\n * @example\n * ```tsx\n * <OtpEmail\n *   verificationCode=\"069420\"\n *   email=\"user@example.com\"\n *   appName=\"My App\"\n *   expirationMinutes={10}\n *   logoURL=\"https://example.com/logo.png\"\n *   darkMode={true}\n * />\n * ```\n */\nexport const OtpEmail = ({\n  verificationCode,\n  email,\n  appName,\n  expirationMinutes = 10,\n  logoURL,\n  colors,\n  classNames,\n  darkMode = true,\n  poweredBy,\n  head,\n  ...props\n}: OtpEmailProps) => {\n  const localization = {\n    ...OtpEmail.localization,\n    ...props.localization\n  }\n\n  const previewText = localization.YOUR_VERIFICATION_CODE_IS_CODE.replace(\n    \"{verificationCode}\",\n    verificationCode\n  )\n\n  return (\n    <Html>\n      <Head>\n        <meta content=\"light dark\" name=\"color-scheme\" />\n        <meta content=\"light dark\" name=\"supported-color-schemes\" />\n\n        <EmailStyles colors={colors} darkMode={darkMode} />\n\n        {head}\n      </Head>\n\n      <Preview>{previewText}</Preview>\n\n      <Tailwind config={{ presets: [pixelBasedPreset] }}>\n        <Body className={cn(\"bg-background font-sans\", classNames?.body)}>\n          <Container\n            className={cn(\n              \"mx-auto my-auto max-w-xl px-2 py-10\",\n              classNames?.container\n            )}\n          >\n            <Section\n              className={cn(\n                \"bg-card text-card-foreground rounded-none border border-border p-8\",\n                classNames?.card\n              )}\n            >\n              {logoURL &&\n                (typeof logoURL === \"string\" ? (\n                  <Img\n                    src={logoURL}\n                    width={48}\n                    height={48}\n                    alt={appName || localization.LOGO}\n                    className={cn(\"mx-auto mb-8\", classNames?.logo)}\n                  />\n                ) : (\n                  <>\n                    <Img\n                      src={logoURL.light}\n                      width={48}\n                      height={48}\n                      alt={appName || localization.LOGO}\n                      className={cn(\n                        \"mx-auto mb-8 logo-light\",\n                        classNames?.logo\n                      )}\n                    />\n                    <Img\n                      src={logoURL.dark}\n                      width={48}\n                      height={48}\n                      alt={appName || localization.LOGO}\n                      className={cn(\n                        \"hidden mx-auto mb-8 logo-dark\",\n                        classNames?.logo\n                      )}\n                    />\n                  </>\n                ))}\n\n              <Heading\n                className={cn(\"mb-5 text-2xl font-semibold\", classNames?.title)}\n              >\n                {localization.VERIFY_YOUR_EMAIL}\n              </Heading>\n\n              <Text className={cn(\"text-sm font-normal\", classNames?.content)}>\n                {(() => {\n                  const textWithAppName =\n                    localization.WE_NEED_TO_VERIFY_YOUR_EMAIL_ADDRESS.replace(\n                      \"{appName}\",\n                      appName || \"\"\n                    )\n                      .replace(/\\s{2,}/g, \" \")\n                      .replace(\" .\", \".\")\n\n                  const [beforeEmail, afterEmail] =\n                    textWithAppName.split(\"{email}\")\n\n                  return email ? (\n                    <>\n                      {beforeEmail}\n\n                      <Link\n                        href={`mailto:${email}`}\n                        className=\"text-primary font-medium\"\n                      >\n                        {email}\n                      </Link>\n\n                      {afterEmail}\n                    </>\n                  ) : (\n                    textWithAppName\n                      .replace(\"{email}\", \"\")\n                      .replace(/\\s{2,}/g, \" \")\n                      .replace(\" .\", \".\")\n                  )\n                })()}\n              </Text>\n\n              <Section\n                className={cn(\n                  \"my-6 border border-border bg-muted p-6\",\n                  classNames?.codeBlock\n                )}\n              >\n                <Text\n                  className={cn(\n                    \"m-0 text-center text-4xl font-semibold tracking-widest\",\n                    classNames?.title\n                  )}\n                >\n                  {verificationCode}\n                </Text>\n              </Section>\n\n              <Hr\n                className={cn(\n                  \"my-6 w-full border border-solid border-border\",\n                  classNames?.separator\n                )}\n              />\n\n              <Text\n                className={cn(\n                  \"mb-3 text-xs text-muted-foreground\",\n                  classNames?.description\n                )}\n              >\n                {localization.THIS_CODE_EXPIRES_IN_MINUTES.replace(\n                  \"{expirationMinutes}\",\n                  expirationMinutes.toString()\n                )}\n                {appName && (\n                  <>\n                    {\" \"}\n                    {localization.EMAIL_SENT_BY.replace(\"{appName}\", appName)}\n                  </>\n                )}\n              </Text>\n\n              <Text\n                className={cn(\n                  \"mt-3 text-xs text-muted-foreground\",\n                  classNames?.description\n                )}\n              >\n                {localization.IF_YOU_DIDNT_REQUEST_THIS_EMAIL}\n              </Text>\n\n              {poweredBy && (\n                <Text\n                  className={cn(\n                    \"mt-4 mb-0 text-center text-[11px] text-muted-foreground\",\n                    classNames?.poweredBy\n                  )}\n                >\n                  {(() => {\n                    const [beforeBetterAuth, afterBetterAuth] =\n                      localization.POWERED_BY_BETTER_AUTH.split(\"{betterAuth}\")\n\n                    return (\n                      <>\n                        {beforeBetterAuth}\n                        <Link\n                          href=\"https://better-auth.com\"\n                          className={cn(\n                            \"text-primary underline\",\n                            classNames?.link\n                          )}\n                        >\n                          better-auth\n                        </Link>\n                        {afterBetterAuth}\n                      </>\n                    )\n                  })()}\n                </Text>\n              )}\n            </Section>\n          </Container>\n        </Body>\n      </Tailwind>\n    </Html>\n  )\n}\n\nOtpEmail.localization = otpEmailLocalization\n\nOtpEmail.PreviewProps = {\n  verificationCode: \"069420\",\n  email: \"m@example.com\",\n  appName: \"Better Auth\",\n  darkMode: true\n} as OtpEmailProps\n\nexport default OtpEmail\n",
      "type": "registry:component",
      "target": "@components/auth/email/otp-email.tsx"
    },
    {
      "path": "../../packages/react/src/components/auth/email/email-styles.tsx",
      "content": "/**\n * Default color scheme for email templates in light and dark modes.\n *\n * Provides a consistent color palette that can be customized via the EmailColors type.\n */\nexport const defaultColors = {\n  light: {\n    background: \"#F5F5F5\",\n    border: \"#E5E5E5\",\n    card: \"#FFFFFF\",\n    cardForeground: \"#0A0A0A\",\n    foreground: \"#262626\",\n    muted: \"#F5F5F5\",\n    mutedForeground: \"#737373\",\n    primary: \"#171717\",\n    primaryForeground: \"#FAFAFA\"\n  },\n  dark: {\n    background: \"#0A0A0A\",\n    border: \"#2E2E2E\",\n    card: \"#171717\",\n    cardForeground: \"#FAFAFA\",\n    foreground: \"#D4D4D4\",\n    muted: \"#212121\",\n    mutedForeground: \"#A1A1A1\",\n    primary: \"#E5E5E5\",\n    primaryForeground: \"#171717\"\n  }\n}\n\n/**\n * Custom CSS class names for styling different parts of email templates.\n *\n * Allows fine-grained control over the appearance of email components.\n */\nexport type EmailClassNames = {\n  body?: string\n  container?: string\n  card?: string\n  logo?: string\n  title?: string\n  content?: string\n  button?: string\n  description?: string\n  separator?: string\n  link?: string\n  poweredBy?: string\n  codeBlock?: string\n}\n\n/**\n * Custom color scheme configuration for email templates.\n *\n * Supports separate color definitions for light and dark modes.\n * Any color not specified will fall back to the defaultColors values.\n */\nexport type EmailColors = {\n  light?: Partial<typeof defaultColors.light>\n  dark?: Partial<typeof defaultColors.dark>\n}\n\n/**\n * Props for the EmailStyles component.\n */\ninterface EmailStylesProps {\n  /** Custom color scheme for light and dark modes */\n  colors?: EmailColors\n  /** Whether to enable dark mode support */\n  darkMode?: boolean\n}\n\n/**\n * Component that injects CSS styles for email templates with support for light and dark modes.\n *\n * Generates inline styles that adapt to the user's color scheme preference and applies\n * custom colors if provided. Handles logo visibility switching between light and dark modes.\n *\n * @param props - Style configuration options\n * @returns A style element containing CSS for email template theming\n *\n * @example\n * ```tsx\n * <EmailStyles\n *   colors={{\n *     light: { primary: \"#000000\" },\n *     dark: { primary: \"#FFFFFF\" }\n *   }}\n *   darkMode={true}\n * />\n * ```\n */\nexport const EmailStyles = ({ colors, darkMode = true }: EmailStylesProps) => {\n  return (\n    <style type=\"text/css\">{`\n      .bg-background {\n        background-color: ${colors?.light?.background || defaultColors.light.background} !important;\n      }\n      .bg-card {\n        background-color: ${colors?.light?.card || defaultColors.light.card} !important;\n      }\n      .bg-primary {\n        background-color: ${colors?.light?.primary || defaultColors.light.primary} !important;\n      }\n      .bg-muted {\n        background-color: ${colors?.light?.muted || defaultColors.light.muted} !important;\n      }\n      .border-border {\n        border-color: ${colors?.light?.border || defaultColors.light.border} !important;\n      }\n      .text-card-foreground {\n        color: ${colors?.light?.cardForeground || defaultColors.light.cardForeground} !important;\n      }\n      .text-muted-foreground {\n        color: ${colors?.light?.mutedForeground || defaultColors.light.mutedForeground} !important;\n      }\n      .text-primary {\n        color: ${colors?.light?.primary || defaultColors.light.primary} !important;\n      }\n      .text-primary-foreground {\n        color: ${colors?.light?.primaryForeground || defaultColors.light.primaryForeground} !important;\n      }\n      .logo-dark {\n        display: none !important;\n      }\n      .logo-light {\n        display: block !important;\n      }\n\n      ${\n        darkMode\n          ? `@media (prefers-color-scheme: dark) {\n        .bg-background {\n          background-color: ${colors?.dark?.background || defaultColors.dark.background} !important;\n        }\n        .bg-card {\n          background-color: ${colors?.dark?.card || defaultColors.dark.card} !important;\n        }\n        .bg-primary {\n          background-color: ${colors?.dark?.primary || defaultColors.dark.primary} !important;\n        }\n        .bg-muted {\n          background-color: ${colors?.dark?.muted || defaultColors.dark.muted} !important;\n        }\n        .border-border {\n          border-color: ${colors?.dark?.border || defaultColors.dark.border} !important;\n        }\n        .text-card-foreground {\n          color: ${colors?.dark?.cardForeground || defaultColors.dark.cardForeground} !important;\n        }\n        .text-muted-foreground {\n          color: ${colors?.dark?.mutedForeground || defaultColors.dark.mutedForeground} !important;\n        }\n        .text-primary {\n          color: ${colors?.dark?.primary || defaultColors.dark.primary} !important;\n        }\n        .text-primary-foreground {\n          color: ${colors?.dark?.primaryForeground || defaultColors.dark.primaryForeground} !important;\n        }\n        .logo-dark {\n          display: block !important;\n        }\n        .logo-light {\n          display: none !important;\n        }\n        * {\n          box-shadow: none !important;\n        }\n      }`\n          : \"\"\n      }\n    `}</style>\n  )\n}\n\nexport default EmailStyles\n",
      "type": "registry:component",
      "target": "@components/auth/email/email-styles.tsx"
    }
  ],
  "type": "registry:component"
}