@better-auth-ui/react 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/auth/auth-provider.d.ts +32 -0
- package/dist/components/auth/auth-provider.js +44 -0
- package/dist/components/email/email-changed.d.ts +97 -0
- package/dist/components/email/email-changed.js +70 -0
- package/dist/components/email/email-localization.d.ts +61 -0
- package/dist/components/email/email-localization.js +24 -0
- package/dist/components/email/email-styles.d.ts +89 -0
- package/dist/components/email/email-styles.js +129 -0
- package/dist/components/email/email-verification.d.ts +97 -0
- package/dist/components/email/email-verification.js +75 -0
- package/dist/components/email/index.d.ts +9 -0
- package/dist/components/email/index.js +9 -0
- package/dist/components/email/magic-link.d.ts +93 -0
- package/dist/components/email/magic-link.js +72 -0
- package/dist/components/email/new-device.d.ts +123 -0
- package/dist/components/email/new-device.js +90 -0
- package/dist/components/email/otp-email.d.ts +88 -0
- package/dist/components/email/otp-email.js +65 -0
- package/dist/components/email/password-changed.d.ts +96 -0
- package/dist/components/email/password-changed.js +76 -0
- package/dist/components/email/reset-password.d.ts +90 -0
- package/dist/components/email/reset-password.js +68 -0
- package/dist/components/icons/apple.d.ts +8 -0
- package/dist/components/icons/apple.js +10 -0
- package/dist/components/icons/atlassian.d.ts +10 -0
- package/dist/components/icons/atlassian.js +14 -0
- package/dist/components/icons/cognito.d.ts +8 -0
- package/dist/components/icons/cognito.js +10 -0
- package/dist/components/icons/discord.d.ts +8 -0
- package/dist/components/icons/discord.js +10 -0
- package/dist/components/icons/dropbox.d.ts +8 -0
- package/dist/components/icons/dropbox.js +10 -0
- package/dist/components/icons/facebook.d.ts +10 -0
- package/dist/components/icons/facebook.js +12 -0
- package/dist/components/icons/figma.d.ts +11 -0
- package/dist/components/icons/figma.js +13 -0
- package/dist/components/icons/github.d.ts +10 -0
- package/dist/components/icons/github.js +12 -0
- package/dist/components/icons/gitlab.d.ts +8 -0
- package/dist/components/icons/gitlab.js +10 -0
- package/dist/components/icons/google.d.ts +8 -0
- package/dist/components/icons/google.js +10 -0
- package/dist/components/icons/huggingface.d.ts +8 -0
- package/dist/components/icons/huggingface.js +10 -0
- package/dist/components/icons/index.d.ts +35 -0
- package/dist/components/icons/index.js +35 -0
- package/dist/components/icons/kakao.d.ts +10 -0
- package/dist/components/icons/kakao.js +12 -0
- package/dist/components/icons/kick.d.ts +10 -0
- package/dist/components/icons/kick.js +12 -0
- package/dist/components/icons/line.d.ts +8 -0
- package/dist/components/icons/line.js +10 -0
- package/dist/components/icons/linear.d.ts +8 -0
- package/dist/components/icons/linear.js +10 -0
- package/dist/components/icons/linkedin.d.ts +8 -0
- package/dist/components/icons/linkedin.js +10 -0
- package/dist/components/icons/microsoft.d.ts +8 -0
- package/dist/components/icons/microsoft.js +10 -0
- package/dist/components/icons/naver.d.ts +8 -0
- package/dist/components/icons/naver.js +10 -0
- package/dist/components/icons/notion.d.ts +8 -0
- package/dist/components/icons/notion.js +10 -0
- package/dist/components/icons/paybin.d.ts +7 -0
- package/dist/components/icons/paybin.js +9 -0
- package/dist/components/icons/paypal.d.ts +8 -0
- package/dist/components/icons/paypal.js +10 -0
- package/dist/components/icons/polar.d.ts +8 -0
- package/dist/components/icons/polar.js +10 -0
- package/dist/components/icons/railway.d.ts +8 -0
- package/dist/components/icons/railway.js +10 -0
- package/dist/components/icons/reddit.d.ts +8 -0
- package/dist/components/icons/reddit.js +10 -0
- package/dist/components/icons/roblox.d.ts +11 -0
- package/dist/components/icons/roblox.js +13 -0
- package/dist/components/icons/salesforce.d.ts +8 -0
- package/dist/components/icons/salesforce.js +10 -0
- package/dist/components/icons/slack.d.ts +8 -0
- package/dist/components/icons/slack.js +10 -0
- package/dist/components/icons/spotify.d.ts +8 -0
- package/dist/components/icons/spotify.js +10 -0
- package/dist/components/icons/tiktok.d.ts +9 -0
- package/dist/components/icons/tiktok.js +11 -0
- package/dist/components/icons/twitch.d.ts +8 -0
- package/dist/components/icons/twitch.js +13 -0
- package/dist/components/icons/vercel.d.ts +8 -0
- package/dist/components/icons/vercel.js +10 -0
- package/dist/components/icons/vk.d.ts +8 -0
- package/dist/components/icons/vk.js +10 -0
- package/dist/components/icons/wechat.d.ts +8 -0
- package/dist/components/icons/wechat.js +10 -0
- package/dist/components/icons/x.d.ts +8 -0
- package/dist/components/icons/x.js +10 -0
- package/dist/components/icons/zoom.d.ts +8 -0
- package/dist/components/icons/zoom.js +12 -0
- package/dist/components/settings/account/theme-preview.d.ts +3 -0
- package/dist/components/settings/account/theme-preview.js +10 -0
- package/dist/core.d.ts +1 -0
- package/dist/core.js +1 -0
- package/dist/hooks/auth/use-auth-mutation.d.ts +18 -0
- package/dist/hooks/auth/use-auth-mutation.js +10 -0
- package/dist/hooks/auth/use-auth-query.d.ts +24 -0
- package/dist/hooks/auth/use-auth-query.js +10 -0
- package/dist/hooks/auth/use-authenticate.d.ts +9 -0
- package/dist/hooks/auth/use-authenticate.js +28 -0
- package/dist/hooks/auth/use-forgot-password.d.ts +20 -0
- package/dist/hooks/auth/use-forgot-password.js +14 -0
- package/dist/hooks/auth/use-request-password-reset.d.ts +26 -0
- package/dist/hooks/auth/use-request-password-reset.js +14 -0
- package/dist/hooks/auth/use-reset-password.d.ts +40 -0
- package/dist/hooks/auth/use-reset-password.js +13 -0
- package/dist/hooks/auth/use-send-verification-email.d.ts +24 -0
- package/dist/hooks/auth/use-send-verification-email.js +13 -0
- package/dist/hooks/auth/use-session.d.ts +9 -0
- package/dist/hooks/auth/use-session.js +18 -0
- package/dist/hooks/auth/use-sign-in-email.d.ts +53 -0
- package/dist/hooks/auth/use-sign-in-email.js +24 -0
- package/dist/hooks/auth/use-sign-in-magic-link.d.ts +32 -0
- package/dist/hooks/auth/use-sign-in-magic-link.js +13 -0
- package/dist/hooks/auth/use-sign-in-social.d.ts +93 -0
- package/dist/hooks/auth/use-sign-in-social.js +13 -0
- package/dist/hooks/auth/use-sign-out.d.ts +19 -0
- package/dist/hooks/auth/use-sign-out.js +24 -0
- package/dist/hooks/auth/use-sign-up-email.d.ts +526 -0
- package/dist/hooks/auth/use-sign-up-email.js +24 -0
- package/dist/hooks/auth/use-user.d.ts +513 -0
- package/dist/hooks/auth/use-user.js +14 -0
- package/dist/hooks/settings/use-account-info.d.ts +17 -0
- package/dist/hooks/settings/use-account-info.js +25 -0
- package/dist/hooks/settings/use-change-email.d.ts +24 -0
- package/dist/hooks/settings/use-change-email.js +23 -0
- package/dist/hooks/settings/use-change-password.d.ts +54 -0
- package/dist/hooks/settings/use-change-password.js +11 -0
- package/dist/hooks/settings/use-delete-user.d.ts +42 -0
- package/dist/hooks/settings/use-delete-user.js +11 -0
- package/dist/hooks/settings/use-link-social.d.ts +46 -0
- package/dist/hooks/settings/use-link-social.js +10 -0
- package/dist/hooks/settings/use-list-accounts.d.ts +20 -0
- package/dist/hooks/settings/use-list-accounts.js +23 -0
- package/dist/hooks/settings/use-list-device-sessions.d.ts +11 -0
- package/dist/hooks/settings/use-list-device-sessions.js +22 -0
- package/dist/hooks/settings/use-list-sessions.d.ts +20 -0
- package/dist/hooks/settings/use-list-sessions.js +22 -0
- package/dist/hooks/settings/use-revoke-multi-session.d.ts +19 -0
- package/dist/hooks/settings/use-revoke-multi-session.js +20 -0
- package/dist/hooks/settings/use-revoke-session.d.ts +19 -0
- package/dist/hooks/settings/use-revoke-session.js +21 -0
- package/dist/hooks/settings/use-set-active-session.d.ts +37 -0
- package/dist/hooks/settings/use-set-active-session.js +28 -0
- package/dist/hooks/settings/use-unlink-account.d.ts +21 -0
- package/dist/hooks/settings/use-unlink-account.js +21 -0
- package/dist/hooks/settings/use-update-user.d.ts +11 -0
- package/dist/hooks/settings/use-update-user.js +29 -0
- package/dist/hooks/use-hydrated.d.ts +6 -0
- package/dist/hooks/use-hydrated.js +18 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +33 -0
- package/dist/lib/auth-client.d.ts +1979 -0
- package/dist/lib/auth-client.js +5 -0
- package/dist/lib/auth-config.d.ts +43 -0
- package/dist/lib/auth-config.js +1 -0
- package/dist/lib/auth-context.d.ts +2 -0
- package/dist/lib/auth-context.js +3 -0
- package/dist/lib/auth-hook-options.d.ts +8 -0
- package/dist/lib/auth-hook-options.js +1 -0
- package/dist/lib/provider-icons.d.ts +13 -0
- package/dist/lib/provider-icons.js +48 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/lib/utils.js +5 -0
- package/package.json +64 -0
- package/src/components/auth/auth-provider.tsx +82 -0
- package/src/components/email/email-changed.tsx +381 -0
- package/src/components/email/email-localization.tsx +33 -0
- package/src/components/email/email-styles.tsx +175 -0
- package/src/components/email/email-verification.tsx +350 -0
- package/src/components/email/index.ts +9 -0
- package/src/components/email/magic-link.tsx +349 -0
- package/src/components/email/new-device.tsx +452 -0
- package/src/components/email/otp-email.tsx +321 -0
- package/src/components/email/password-changed.tsx +380 -0
- package/src/components/email/reset-password.tsx +343 -0
- package/src/components/icons/apple.tsx +24 -0
- package/src/components/icons/atlassian.tsx +43 -0
- package/src/components/icons/cognito.tsx +25 -0
- package/src/components/icons/discord.tsx +24 -0
- package/src/components/icons/dropbox.tsx +24 -0
- package/src/components/icons/facebook.tsx +30 -0
- package/src/components/icons/figma.tsx +43 -0
- package/src/components/icons/github.tsx +26 -0
- package/src/components/icons/gitlab.tsx +36 -0
- package/src/components/icons/google.tsx +42 -0
- package/src/components/icons/huggingface.tsx +44 -0
- package/src/components/icons/index.ts +35 -0
- package/src/components/icons/kakao.tsx +26 -0
- package/src/components/icons/kick.tsx +30 -0
- package/src/components/icons/line.tsx +24 -0
- package/src/components/icons/linear.tsx +24 -0
- package/src/components/icons/linkedin.tsx +28 -0
- package/src/components/icons/microsoft.tsx +24 -0
- package/src/components/icons/naver.tsx +24 -0
- package/src/components/icons/notion.tsx +25 -0
- package/src/components/icons/paybin.tsx +37 -0
- package/src/components/icons/paypal.tsx +36 -0
- package/src/components/icons/polar.tsx +31 -0
- package/src/components/icons/railway.tsx +24 -0
- package/src/components/icons/reddit.tsx +25 -0
- package/src/components/icons/roblox.tsx +28 -0
- package/src/components/icons/salesforce.tsx +24 -0
- package/src/components/icons/slack.tsx +36 -0
- package/src/components/icons/spotify.tsx +24 -0
- package/src/components/icons/tiktok.tsx +32 -0
- package/src/components/icons/twitch.tsx +50 -0
- package/src/components/icons/vercel.tsx +21 -0
- package/src/components/icons/vk.tsx +24 -0
- package/src/components/icons/wechat.tsx +24 -0
- package/src/components/icons/x.tsx +24 -0
- package/src/components/icons/zoom.tsx +48 -0
- package/src/components/settings/account/theme-preview.tsx +271 -0
- package/src/core.ts +1 -0
- package/src/hooks/auth/use-auth-mutation.ts +56 -0
- package/src/hooks/auth/use-auth-query.ts +50 -0
- package/src/hooks/auth/use-authenticate.ts +35 -0
- package/src/hooks/auth/use-request-password-reset.ts +24 -0
- package/src/hooks/auth/use-reset-password.ts +23 -0
- package/src/hooks/auth/use-send-verification-email.ts +23 -0
- package/src/hooks/auth/use-session.ts +26 -0
- package/src/hooks/auth/use-sign-in-email.ts +35 -0
- package/src/hooks/auth/use-sign-in-magic-link.ts +23 -0
- package/src/hooks/auth/use-sign-in-social.ts +23 -0
- package/src/hooks/auth/use-sign-out.ts +34 -0
- package/src/hooks/auth/use-sign-up-email.ts +35 -0
- package/src/hooks/auth/use-user.ts +21 -0
- package/src/hooks/settings/use-account-info.ts +30 -0
- package/src/hooks/settings/use-change-email.ts +33 -0
- package/src/hooks/settings/use-change-password.ts +21 -0
- package/src/hooks/settings/use-delete-user.ts +21 -0
- package/src/hooks/settings/use-link-social.ts +19 -0
- package/src/hooks/settings/use-list-accounts.ts +27 -0
- package/src/hooks/settings/use-list-device-sessions.ts +32 -0
- package/src/hooks/settings/use-list-sessions.ts +26 -0
- package/src/hooks/settings/use-revoke-multi-session.ts +30 -0
- package/src/hooks/settings/use-revoke-session.ts +31 -0
- package/src/hooks/settings/use-set-active-session.ts +46 -0
- package/src/hooks/settings/use-unlink-account.ts +31 -0
- package/src/hooks/settings/use-update-user.ts +44 -0
- package/src/index.ts +34 -0
- package/src/lib/auth-client.ts +37 -0
- package/src/lib/auth-config.ts +48 -0
- package/src/lib/auth-context.ts +6 -0
- package/src/lib/provider-icons.ts +90 -0
- package/src/lib/utils.ts +6 -0
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Body,
|
|
3
|
+
Button,
|
|
4
|
+
Container,
|
|
5
|
+
Head,
|
|
6
|
+
Heading,
|
|
7
|
+
Hr,
|
|
8
|
+
Html,
|
|
9
|
+
Img,
|
|
10
|
+
Link,
|
|
11
|
+
Preview,
|
|
12
|
+
pixelBasedPreset,
|
|
13
|
+
Section,
|
|
14
|
+
Tailwind,
|
|
15
|
+
Text
|
|
16
|
+
} from "@react-email/components"
|
|
17
|
+
import type { ReactNode } from "react"
|
|
18
|
+
|
|
19
|
+
import { cn } from "../../lib/utils"
|
|
20
|
+
import {
|
|
21
|
+
type EmailClassNames,
|
|
22
|
+
type EmailColors,
|
|
23
|
+
EmailStyles
|
|
24
|
+
} from "./email-styles"
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Device information displayed in the new device email notification.
|
|
28
|
+
*/
|
|
29
|
+
export interface DeviceInfo {
|
|
30
|
+
/** Browser name and version */
|
|
31
|
+
browser?: string
|
|
32
|
+
/** Operating system name and version */
|
|
33
|
+
os?: string
|
|
34
|
+
/** Geographic location of the sign-in */
|
|
35
|
+
location?: string
|
|
36
|
+
/** IP address of the device */
|
|
37
|
+
ipAddress?: string
|
|
38
|
+
/** Timestamp of the sign-in event */
|
|
39
|
+
timestamp?: string
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const newDeviceEmailLocalization = {
|
|
43
|
+
NEW_SIGN_IN_DETECTED: "New sign-in detected",
|
|
44
|
+
LOGO: "Logo",
|
|
45
|
+
NEW_SIGN_IN_TO_YOUR_ACCOUNT:
|
|
46
|
+
"We detected a new sign-in to your {appName} account {userEmail} from a device we don't recognize.",
|
|
47
|
+
DEVICE_DETAILS: "Device details",
|
|
48
|
+
BROWSER: "Browser",
|
|
49
|
+
OPERATING_SYSTEM: "Operating System",
|
|
50
|
+
LOCATION: "Location",
|
|
51
|
+
IP_ADDRESS: "IP Address",
|
|
52
|
+
TIME: "Time",
|
|
53
|
+
IF_THIS_WAS_YOU:
|
|
54
|
+
"If this was you, you can safely ignore this email. If you don't recognize this activity, please secure your account immediately.",
|
|
55
|
+
SECURE_MY_ACCOUNT: "Secure my account",
|
|
56
|
+
EMAIL_SENT_BY: "Email sent by {appName}.",
|
|
57
|
+
IF_YOU_DIDNT_SIGN_IN:
|
|
58
|
+
"If you didn't sign in, please contact support immediately {supportEmail} to secure your account.",
|
|
59
|
+
POWERED_BY_BETTER_AUTH: "Powered by {betterAuth}"
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Localization strings for the NewDeviceEmail component.
|
|
64
|
+
*
|
|
65
|
+
* Contains all text content used in the new device detection email template.
|
|
66
|
+
*/
|
|
67
|
+
export type NewDeviceEmailLocalization = typeof newDeviceEmailLocalization
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Props for the NewDeviceEmail component.
|
|
71
|
+
*/
|
|
72
|
+
export interface NewDeviceEmailProps {
|
|
73
|
+
/** Email address of the user account */
|
|
74
|
+
userEmail?: string
|
|
75
|
+
/** Information about the device that signed in */
|
|
76
|
+
deviceInfo?: DeviceInfo
|
|
77
|
+
/** URL to secure the account if unauthorized access is suspected */
|
|
78
|
+
secureAccountLink?: string
|
|
79
|
+
/** Name of the application sending the email */
|
|
80
|
+
appName?: string
|
|
81
|
+
/** Support email address for security concerns */
|
|
82
|
+
supportEmail?: string
|
|
83
|
+
/** Logo URL(s) - a single string or light/dark variants. If omitted, no logo is shown. */
|
|
84
|
+
logoURL?: string | { light: string; dark: string }
|
|
85
|
+
/** Custom CSS class names for styling specific parts of the email */
|
|
86
|
+
classNames?: EmailClassNames
|
|
87
|
+
/** Custom color scheme for light and dark modes */
|
|
88
|
+
colors?: EmailColors
|
|
89
|
+
/** Whether to show the "Powered by better-auth" footer */
|
|
90
|
+
poweredBy?: boolean
|
|
91
|
+
/** Whether to enable dark mode support */
|
|
92
|
+
darkMode?: boolean
|
|
93
|
+
/** Additional React nodes to inject into the email head */
|
|
94
|
+
head?: ReactNode
|
|
95
|
+
/**
|
|
96
|
+
* Localization overrides for customizing email text
|
|
97
|
+
* @remarks `NewDeviceEmailLocalization`
|
|
98
|
+
*/
|
|
99
|
+
localization?: Partial<NewDeviceEmailLocalization>
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Email template component that notifies users when a new device signs into their account.
|
|
104
|
+
*
|
|
105
|
+
* This email includes:
|
|
106
|
+
* - Device information display (browser, OS, location, IP, timestamp)
|
|
107
|
+
* - Secure account action button
|
|
108
|
+
* - Security warnings and support contact information
|
|
109
|
+
* - Customizable branding and styling
|
|
110
|
+
* - Support for light/dark mode themes
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```tsx
|
|
114
|
+
* <NewDeviceEmail
|
|
115
|
+
* userEmail="user@example.com"
|
|
116
|
+
* deviceInfo={{
|
|
117
|
+
* browser: "Chrome on macOS",
|
|
118
|
+
* os: "macOS 14.0",
|
|
119
|
+
* location: "San Francisco, CA",
|
|
120
|
+
* ipAddress: "192.168.1.1",
|
|
121
|
+
* timestamp: "February 10, 2025 at 4:20 PM UTC"
|
|
122
|
+
* }}
|
|
123
|
+
* secureAccountLink="https://example.com/secure-account"
|
|
124
|
+
* appName="My App"
|
|
125
|
+
* supportEmail="support@example.com"
|
|
126
|
+
* darkMode={true}
|
|
127
|
+
* />
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
export const NewDeviceEmail = ({
|
|
131
|
+
userEmail,
|
|
132
|
+
deviceInfo,
|
|
133
|
+
secureAccountLink,
|
|
134
|
+
appName,
|
|
135
|
+
supportEmail,
|
|
136
|
+
logoURL,
|
|
137
|
+
colors,
|
|
138
|
+
classNames,
|
|
139
|
+
darkMode = true,
|
|
140
|
+
poweredBy,
|
|
141
|
+
head,
|
|
142
|
+
...props
|
|
143
|
+
}: NewDeviceEmailProps) => {
|
|
144
|
+
const localization = {
|
|
145
|
+
...NewDeviceEmail.localization,
|
|
146
|
+
...props.localization
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const previewText = localization.NEW_SIGN_IN_DETECTED
|
|
150
|
+
|
|
151
|
+
return (
|
|
152
|
+
<Html>
|
|
153
|
+
<Head>
|
|
154
|
+
<meta content="light dark" name="color-scheme" />
|
|
155
|
+
<meta content="light dark" name="supported-color-schemes" />
|
|
156
|
+
|
|
157
|
+
<EmailStyles colors={colors} darkMode={darkMode} />
|
|
158
|
+
|
|
159
|
+
{head}
|
|
160
|
+
</Head>
|
|
161
|
+
|
|
162
|
+
<Preview>{previewText}</Preview>
|
|
163
|
+
|
|
164
|
+
<Tailwind config={{ presets: [pixelBasedPreset] }}>
|
|
165
|
+
<Body className={cn("bg-background font-sans", classNames?.body)}>
|
|
166
|
+
<Container
|
|
167
|
+
className={cn(
|
|
168
|
+
"mx-auto my-auto max-w-xl px-2 py-10",
|
|
169
|
+
classNames?.container
|
|
170
|
+
)}
|
|
171
|
+
>
|
|
172
|
+
<Section
|
|
173
|
+
className={cn(
|
|
174
|
+
"bg-card text-card-foreground rounded-none border border-border p-8",
|
|
175
|
+
classNames?.card
|
|
176
|
+
)}
|
|
177
|
+
>
|
|
178
|
+
{logoURL &&
|
|
179
|
+
(typeof logoURL === "string" ? (
|
|
180
|
+
<Img
|
|
181
|
+
src={logoURL}
|
|
182
|
+
width={48}
|
|
183
|
+
height={48}
|
|
184
|
+
alt={appName || localization.LOGO}
|
|
185
|
+
className={cn("mx-auto mb-8", classNames?.logo)}
|
|
186
|
+
/>
|
|
187
|
+
) : (
|
|
188
|
+
<>
|
|
189
|
+
<Img
|
|
190
|
+
src={logoURL.light}
|
|
191
|
+
width={48}
|
|
192
|
+
height={48}
|
|
193
|
+
alt={appName || localization.LOGO}
|
|
194
|
+
className={cn(
|
|
195
|
+
"mx-auto mb-8 logo-light",
|
|
196
|
+
classNames?.logo
|
|
197
|
+
)}
|
|
198
|
+
/>
|
|
199
|
+
<Img
|
|
200
|
+
src={logoURL.dark}
|
|
201
|
+
width={48}
|
|
202
|
+
height={48}
|
|
203
|
+
alt={appName || localization.LOGO}
|
|
204
|
+
className={cn(
|
|
205
|
+
"hidden mx-auto mb-8 logo-dark",
|
|
206
|
+
classNames?.logo
|
|
207
|
+
)}
|
|
208
|
+
/>
|
|
209
|
+
</>
|
|
210
|
+
))}
|
|
211
|
+
|
|
212
|
+
<Heading
|
|
213
|
+
className={cn(
|
|
214
|
+
"m-0 mb-5 text-2xl font-semibold",
|
|
215
|
+
classNames?.title
|
|
216
|
+
)}
|
|
217
|
+
>
|
|
218
|
+
{localization.NEW_SIGN_IN_DETECTED}
|
|
219
|
+
</Heading>
|
|
220
|
+
|
|
221
|
+
<Text className={cn("text-sm font-normal", classNames?.content)}>
|
|
222
|
+
{(() => {
|
|
223
|
+
const textWithAppName =
|
|
224
|
+
localization.NEW_SIGN_IN_TO_YOUR_ACCOUNT.replace(
|
|
225
|
+
"{appName}",
|
|
226
|
+
appName || ""
|
|
227
|
+
)
|
|
228
|
+
.replace(/\s{2,}/g, " ")
|
|
229
|
+
.replace(" .", ".")
|
|
230
|
+
|
|
231
|
+
const [beforeUserEmail, afterUserEmail] =
|
|
232
|
+
textWithAppName.split("{userEmail}")
|
|
233
|
+
|
|
234
|
+
return userEmail ? (
|
|
235
|
+
<>
|
|
236
|
+
{beforeUserEmail}
|
|
237
|
+
|
|
238
|
+
<Link
|
|
239
|
+
href={`mailto:${userEmail}`}
|
|
240
|
+
className="text-primary font-medium"
|
|
241
|
+
>
|
|
242
|
+
{userEmail}
|
|
243
|
+
</Link>
|
|
244
|
+
|
|
245
|
+
{afterUserEmail}
|
|
246
|
+
</>
|
|
247
|
+
) : (
|
|
248
|
+
textWithAppName
|
|
249
|
+
.replace("{userEmail}", "")
|
|
250
|
+
.replace(/\s{2,}/g, " ")
|
|
251
|
+
.replace(" .", ".")
|
|
252
|
+
)
|
|
253
|
+
})()}
|
|
254
|
+
</Text>
|
|
255
|
+
|
|
256
|
+
{deviceInfo && (
|
|
257
|
+
<Section
|
|
258
|
+
className={cn(
|
|
259
|
+
"my-6 border border-border bg-muted p-4",
|
|
260
|
+
classNames?.codeBlock
|
|
261
|
+
)}
|
|
262
|
+
>
|
|
263
|
+
<Text
|
|
264
|
+
className={cn(
|
|
265
|
+
"m-0 mb-3 text-xs text-muted-foreground",
|
|
266
|
+
classNames?.description
|
|
267
|
+
)}
|
|
268
|
+
>
|
|
269
|
+
{localization.DEVICE_DETAILS}:
|
|
270
|
+
</Text>
|
|
271
|
+
|
|
272
|
+
{deviceInfo.browser && (
|
|
273
|
+
<Text
|
|
274
|
+
className={cn("m-0 mb-2 text-sm", classNames?.content)}
|
|
275
|
+
>
|
|
276
|
+
<span className="font-semibold">
|
|
277
|
+
{localization.BROWSER}:
|
|
278
|
+
</span>{" "}
|
|
279
|
+
{deviceInfo.browser}
|
|
280
|
+
</Text>
|
|
281
|
+
)}
|
|
282
|
+
|
|
283
|
+
{deviceInfo.os && (
|
|
284
|
+
<Text
|
|
285
|
+
className={cn("m-0 mb-2 text-sm", classNames?.content)}
|
|
286
|
+
>
|
|
287
|
+
<span className="font-semibold">
|
|
288
|
+
{localization.OPERATING_SYSTEM}:
|
|
289
|
+
</span>{" "}
|
|
290
|
+
{deviceInfo.os}
|
|
291
|
+
</Text>
|
|
292
|
+
)}
|
|
293
|
+
|
|
294
|
+
{deviceInfo.location && (
|
|
295
|
+
<Text
|
|
296
|
+
className={cn("m-0 mb-2 text-sm", classNames?.content)}
|
|
297
|
+
>
|
|
298
|
+
<span className="font-semibold">
|
|
299
|
+
{localization.LOCATION}:
|
|
300
|
+
</span>{" "}
|
|
301
|
+
{deviceInfo.location}
|
|
302
|
+
</Text>
|
|
303
|
+
)}
|
|
304
|
+
|
|
305
|
+
{deviceInfo.ipAddress && (
|
|
306
|
+
<Text
|
|
307
|
+
className={cn("m-0 mb-2 text-sm", classNames?.content)}
|
|
308
|
+
>
|
|
309
|
+
<span className="font-semibold">
|
|
310
|
+
{localization.IP_ADDRESS}:
|
|
311
|
+
</span>{" "}
|
|
312
|
+
{deviceInfo.ipAddress}
|
|
313
|
+
</Text>
|
|
314
|
+
)}
|
|
315
|
+
|
|
316
|
+
{deviceInfo.timestamp && (
|
|
317
|
+
<Text className={cn("m-0 text-sm", classNames?.content)}>
|
|
318
|
+
<span className="font-semibold">
|
|
319
|
+
{localization.TIME}:
|
|
320
|
+
</span>{" "}
|
|
321
|
+
{deviceInfo.timestamp}
|
|
322
|
+
</Text>
|
|
323
|
+
)}
|
|
324
|
+
</Section>
|
|
325
|
+
)}
|
|
326
|
+
|
|
327
|
+
<Text className={cn("text-sm font-normal", classNames?.content)}>
|
|
328
|
+
{localization.IF_THIS_WAS_YOU}
|
|
329
|
+
</Text>
|
|
330
|
+
|
|
331
|
+
{secureAccountLink && (
|
|
332
|
+
<Section className="mt-6">
|
|
333
|
+
<Button
|
|
334
|
+
href={secureAccountLink}
|
|
335
|
+
className={cn(
|
|
336
|
+
"inline-block whitespace-nowrap rounded-none text-sm font-medium py-2.5 px-6 bg-primary text-primary-foreground no-underline",
|
|
337
|
+
classNames?.button
|
|
338
|
+
)}
|
|
339
|
+
>
|
|
340
|
+
{localization.SECURE_MY_ACCOUNT}
|
|
341
|
+
</Button>
|
|
342
|
+
</Section>
|
|
343
|
+
)}
|
|
344
|
+
|
|
345
|
+
<Hr
|
|
346
|
+
className={cn(
|
|
347
|
+
"my-6 w-full border border-solid border-border",
|
|
348
|
+
classNames?.separator
|
|
349
|
+
)}
|
|
350
|
+
/>
|
|
351
|
+
|
|
352
|
+
{appName && (
|
|
353
|
+
<Text
|
|
354
|
+
className={cn(
|
|
355
|
+
"mb-3 text-xs text-muted-foreground",
|
|
356
|
+
classNames?.description
|
|
357
|
+
)}
|
|
358
|
+
>
|
|
359
|
+
{localization.EMAIL_SENT_BY.replace("{appName}", appName)}
|
|
360
|
+
</Text>
|
|
361
|
+
)}
|
|
362
|
+
|
|
363
|
+
<Text
|
|
364
|
+
className={cn(
|
|
365
|
+
"mt-3 text-xs text-muted-foreground",
|
|
366
|
+
classNames?.description
|
|
367
|
+
)}
|
|
368
|
+
>
|
|
369
|
+
{(() => {
|
|
370
|
+
const [beforeSupportEmail, afterSupportEmail] =
|
|
371
|
+
localization.IF_YOU_DIDNT_SIGN_IN.split("{supportEmail}")
|
|
372
|
+
|
|
373
|
+
return supportEmail ? (
|
|
374
|
+
<>
|
|
375
|
+
{beforeSupportEmail}
|
|
376
|
+
<Link
|
|
377
|
+
href={`mailto:${supportEmail}`}
|
|
378
|
+
className={cn(
|
|
379
|
+
"text-primary underline",
|
|
380
|
+
classNames?.link
|
|
381
|
+
)}
|
|
382
|
+
>
|
|
383
|
+
{supportEmail}
|
|
384
|
+
</Link>
|
|
385
|
+
{afterSupportEmail}
|
|
386
|
+
</>
|
|
387
|
+
) : (
|
|
388
|
+
localization.IF_YOU_DIDNT_SIGN_IN.replace(
|
|
389
|
+
"{supportEmail}",
|
|
390
|
+
""
|
|
391
|
+
)
|
|
392
|
+
.replace(/\s{2,}/g, " ")
|
|
393
|
+
.replace(" .", ".")
|
|
394
|
+
)
|
|
395
|
+
})()}
|
|
396
|
+
</Text>
|
|
397
|
+
|
|
398
|
+
{poweredBy && (
|
|
399
|
+
<Text
|
|
400
|
+
className={cn(
|
|
401
|
+
"mt-4 mb-0 text-center text-[11px] text-muted-foreground",
|
|
402
|
+
classNames?.poweredBy
|
|
403
|
+
)}
|
|
404
|
+
>
|
|
405
|
+
{(() => {
|
|
406
|
+
const [beforeBetterAuth, afterBetterAuth] =
|
|
407
|
+
localization.POWERED_BY_BETTER_AUTH.split("{betterAuth}")
|
|
408
|
+
|
|
409
|
+
return (
|
|
410
|
+
<>
|
|
411
|
+
{beforeBetterAuth}
|
|
412
|
+
<Link
|
|
413
|
+
href="https://better-auth.com"
|
|
414
|
+
className={cn(
|
|
415
|
+
"text-primary underline",
|
|
416
|
+
classNames?.link
|
|
417
|
+
)}
|
|
418
|
+
>
|
|
419
|
+
better-auth
|
|
420
|
+
</Link>
|
|
421
|
+
{afterBetterAuth}
|
|
422
|
+
</>
|
|
423
|
+
)
|
|
424
|
+
})()}
|
|
425
|
+
</Text>
|
|
426
|
+
)}
|
|
427
|
+
</Section>
|
|
428
|
+
</Container>
|
|
429
|
+
</Body>
|
|
430
|
+
</Tailwind>
|
|
431
|
+
</Html>
|
|
432
|
+
)
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
NewDeviceEmail.localization = newDeviceEmailLocalization
|
|
436
|
+
|
|
437
|
+
NewDeviceEmail.PreviewProps = {
|
|
438
|
+
userEmail: "m@example.com",
|
|
439
|
+
deviceInfo: {
|
|
440
|
+
browser: "Chrome on macOS",
|
|
441
|
+
os: "macOS 26.2",
|
|
442
|
+
location: "San Francisco, CA, United States",
|
|
443
|
+
ipAddress: "127.0.0.1",
|
|
444
|
+
timestamp: "February 10, 2025 at 4:20 PM UTC"
|
|
445
|
+
},
|
|
446
|
+
secureAccountLink: "https://better-auth-ui.com/auth/secure-account",
|
|
447
|
+
appName: "Better Auth",
|
|
448
|
+
supportEmail: "support@example.com",
|
|
449
|
+
darkMode: true
|
|
450
|
+
} as NewDeviceEmailProps
|
|
451
|
+
|
|
452
|
+
export default NewDeviceEmail
|