{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "change-email-confirmation-email",
  "title": "Change Email Confirmation Email",
  "description": "Email template component for approving an email address change from the current address.",
  "dependencies": [
    "@better-auth-ui/react@latest",
    "@better-auth-ui/core@latest",
    "react-email"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "../../packages/react/src/components/auth/email/change-email-confirmation.tsx",
      "content": "import type { ReactNode } from \"react\"\nimport {\n  Body,\n  Button,\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 changeEmailConfirmationEmailLocalization = {\n  CONFIRM_EMAIL_CHANGE: \"Confirm your email change\",\n  LOGO: \"Logo\",\n  EMAIL_CHANGE_REQUESTED:\n    \"Someone requested to change the email address for your {appName} account.\",\n  CURRENT_EMAIL: \"Current email:\",\n  NEW_EMAIL: \"New email:\",\n  APPROVE_EMAIL_CHANGE: \"Approve email change\",\n  OR_COPY_AND_PASTE_URL: \"Or copy and paste this URL into your browser:\",\n  THIS_LINK_EXPIRES_IN_MINUTES:\n    \"This link expires in {expirationMinutes} minutes.\",\n  EMAIL_SENT_BY: \"Email sent by {appName}.\",\n  IF_YOU_DIDNT_REQUEST_EMAIL_CHANGE:\n    \"If you didn't request this change, you can safely ignore this email. Your email address will stay the same.\",\n  POWERED_BY_BETTER_AUTH: \"Powered by {betterAuth}\"\n}\n\n/**\n * Localization strings for the ChangeEmailConfirmationEmail component.\n */\nexport type ChangeEmailConfirmationEmailLocalization =\n  typeof changeEmailConfirmationEmailLocalization\n\n/**\n * Props for the ChangeEmailConfirmationEmail component.\n */\nexport interface ChangeEmailConfirmationEmailProps {\n  /** Confirmation URL sent by Better Auth to the user's current email address */\n  url: string\n  /** User's current email address */\n  currentEmail?: string\n  /** Requested new email address */\n  newEmail?: string\n  /** Name of the application sending the email */\n  appName?: string\n  /** Number of minutes until the confirmation link 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 `ChangeEmailConfirmationEmailLocalization`\n   */\n  localization?: Partial<ChangeEmailConfirmationEmailLocalization>\n}\n\n/**\n * Email template for approving an email change from the current address.\n *\n * Use this template with Better Auth's\n * `user.changeEmail.sendChangeEmailConfirmation` callback. The email is sent\n * before the address changes, so it is separate from `EmailChangedEmail`.\n *\n * @example\n * ```tsx\n * <ChangeEmailConfirmationEmail\n *   url=\"https://example.com/api/auth/change-email/verify?token=abc123\"\n *   currentEmail=\"current@example.com\"\n *   newEmail=\"new@example.com\"\n *   appName=\"My App\"\n *   expirationMinutes={60}\n * />\n * ```\n */\nexport const ChangeEmailConfirmationEmail = ({\n  url,\n  currentEmail,\n  newEmail,\n  appName,\n  expirationMinutes = 60,\n  logoURL,\n  colors,\n  classNames,\n  darkMode = true,\n  poweredBy,\n  head,\n  ...props\n}: ChangeEmailConfirmationEmailProps) => {\n  const localization = {\n    ...ChangeEmailConfirmationEmail.localization,\n    ...props.localization\n  }\n\n  const requestText = localization.EMAIL_CHANGE_REQUESTED.replace(\n    \"{appName}\",\n    appName || \"\"\n  )\n    .replace(/\\s{2,}/g, \" \")\n    .replace(\" .\", \".\")\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>{localization.CONFIRM_EMAIL_CHANGE}</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                \"rounded-none border border-border bg-card p-8 text-card-foreground\",\n                classNames?.card\n              )}\n            >\n              {logoURL &&\n                (typeof logoURL === \"string\" ? (\n                  <Img\n                    alt={appName || localization.LOGO}\n                    className={cn(\"mx-auto mb-8\", classNames?.logo)}\n                    height={48}\n                    src={logoURL}\n                    width={48}\n                  />\n                ) : (\n                  <>\n                    <Img\n                      alt={appName || localization.LOGO}\n                      className={cn(\n                        \"logo-light mx-auto mb-8\",\n                        classNames?.logo\n                      )}\n                      height={48}\n                      src={logoURL.light}\n                      width={48}\n                    />\n                    <Img\n                      alt={appName || localization.LOGO}\n                      className={cn(\n                        \"logo-dark hidden mx-auto mb-8\",\n                        classNames?.logo\n                      )}\n                      height={48}\n                      src={logoURL.dark}\n                      width={48}\n                    />\n                  </>\n                ))}\n\n              <Heading\n                className={cn(\n                  \"m-0 mb-5 text-2xl font-semibold\",\n                  classNames?.title\n                )}\n              >\n                {localization.CONFIRM_EMAIL_CHANGE}\n              </Heading>\n\n              <Text className={cn(\"text-sm\", classNames?.content)}>\n                {requestText}\n              </Text>\n\n              {(currentEmail || newEmail) && (\n                <Section\n                  className={cn(\n                    \"my-6 border border-border bg-muted p-4\",\n                    classNames?.codeBlock\n                  )}\n                >\n                  {currentEmail && (\n                    <>\n                      <Text\n                        className={cn(\n                          \"m-0 mb-2 text-xs text-muted-foreground\",\n                          classNames?.description\n                        )}\n                      >\n                        {localization.CURRENT_EMAIL}\n                      </Text>\n                      <Text\n                        className={cn(\n                          \"m-0 text-sm font-semibold\",\n                          newEmail && \"mb-4\",\n                          classNames?.content\n                        )}\n                      >\n                        {currentEmail}\n                      </Text>\n                    </>\n                  )}\n\n                  {newEmail && (\n                    <>\n                      <Text\n                        className={cn(\n                          \"m-0 mb-2 text-xs text-muted-foreground\",\n                          classNames?.description\n                        )}\n                      >\n                        {localization.NEW_EMAIL}\n                      </Text>\n                      <Text\n                        className={cn(\n                          \"m-0 text-sm font-semibold text-primary\",\n                          classNames?.content\n                        )}\n                      >\n                        {newEmail}\n                      </Text>\n                    </>\n                  )}\n                </Section>\n              )}\n\n              <Section className=\"my-6\">\n                <Button\n                  className={cn(\n                    \"inline-block whitespace-nowrap rounded-none bg-primary px-6 py-2.5 text-sm font-medium text-primary-foreground no-underline\",\n                    classNames?.button\n                  )}\n                  href={url}\n                >\n                  {localization.APPROVE_EMAIL_CHANGE}\n                </Button>\n              </Section>\n\n              <Text\n                className={cn(\n                  \"m-0 mb-3 text-xs text-muted-foreground\",\n                  classNames?.description\n                )}\n              >\n                {localization.OR_COPY_AND_PASTE_URL}\n              </Text>\n\n              <Link\n                className={cn(\n                  \"break-all text-xs text-primary\",\n                  classNames?.link\n                )}\n                href={url}\n              >\n                {url}\n              </Link>\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                  \"m-0 mb-3 text-xs text-muted-foreground\",\n                  classNames?.description\n                )}\n              >\n                {localization.THIS_LINK_EXPIRES_IN_MINUTES.replace(\n                  \"{expirationMinutes}\",\n                  expirationMinutes.toString()\n                )}\n                {appName &&\n                  ` ${localization.EMAIL_SENT_BY.replace(\"{appName}\", appName)}`}\n              </Text>\n\n              <Text\n                className={cn(\n                  \"m-0 text-xs text-muted-foreground\",\n                  classNames?.description\n                )}\n              >\n                {localization.IF_YOU_DIDNT_REQUEST_EMAIL_CHANGE}\n              </Text>\n\n              {poweredBy && (\n                <Text\n                  className={cn(\n                    \"m-0 mt-4 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                          className={cn(\n                            \"text-primary underline\",\n                            classNames?.link\n                          )}\n                          href=\"https://better-auth.com\"\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\nChangeEmailConfirmationEmail.localization =\n  changeEmailConfirmationEmailLocalization\n\nChangeEmailConfirmationEmail.PreviewProps = {\n  url: \"https://better-auth-ui.com/api/auth/change-email/verify?token=example-token\",\n  currentEmail: \"current@example.com\",\n  newEmail: \"new@example.com\",\n  appName: \"Better Auth\",\n  poweredBy: true,\n  darkMode: true\n} as ChangeEmailConfirmationEmailProps\n\nexport default ChangeEmailConfirmationEmail\n",
      "type": "registry:component",
      "target": "@components/auth/email/change-email-confirmation.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"
}