@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,43 @@
|
|
|
1
|
+
import type { AuthConfig as BaseAuthConfig } from "@better-auth-ui/react/core";
|
|
2
|
+
import type { ComponentType, PropsWithChildren } from "react";
|
|
3
|
+
import type { AnyAuthClient, AuthClient } from "./auth-client";
|
|
4
|
+
/**
|
|
5
|
+
* Extends the base AuthConfig with React-specific requirements including
|
|
6
|
+
* an authClient instance and a Link component for navigation.
|
|
7
|
+
*
|
|
8
|
+
* Users can augment this interface to provide their own auth client type:
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* declare module "@better-auth-ui/react" {
|
|
12
|
+
* interface AuthConfig {
|
|
13
|
+
* AuthClient: typeof authClient
|
|
14
|
+
* }
|
|
15
|
+
* }
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export interface AuthConfig extends BaseAuthConfig {
|
|
19
|
+
authClient: AuthClient;
|
|
20
|
+
/**
|
|
21
|
+
* React component for rendering links
|
|
22
|
+
* @remarks `LinkComponent`
|
|
23
|
+
*/
|
|
24
|
+
Link: ComponentType<PropsWithChildren<{
|
|
25
|
+
className?: string;
|
|
26
|
+
href: string;
|
|
27
|
+
to?: string;
|
|
28
|
+
}>>;
|
|
29
|
+
}
|
|
30
|
+
type DeepPartial<T> = T extends (...args: any[]) => any ? T : T extends object ? {
|
|
31
|
+
[P in keyof T]?: DeepPartial<T[P]>;
|
|
32
|
+
} : T;
|
|
33
|
+
/**
|
|
34
|
+
* Partial AuthConfig with any Better Auth client instance.
|
|
35
|
+
*/
|
|
36
|
+
export type AnyAuthConfig = DeepPartial<Omit<AuthConfig, "authClient">> & {
|
|
37
|
+
/**
|
|
38
|
+
* Better Auth client instance
|
|
39
|
+
* @remarks `AuthClient`
|
|
40
|
+
*/
|
|
41
|
+
authClient?: AnyAuthClient;
|
|
42
|
+
};
|
|
43
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { SocialProvider } from "better-auth/social-providers";
|
|
2
|
+
import type { ComponentPropsWithRef, ComponentType } from "react";
|
|
3
|
+
/**
|
|
4
|
+
* Mapping of social authentication provider names to their corresponding icon components.
|
|
5
|
+
*
|
|
6
|
+
* Provides React SVG icon components for all supported social authentication providers.
|
|
7
|
+
* Each icon is a React component that accepts standard SVG props and can be customized
|
|
8
|
+
* with className, size, color, etc.
|
|
9
|
+
*
|
|
10
|
+
* Supported providers include: Apple, Google, GitHub, Microsoft, Discord, Facebook,
|
|
11
|
+
* Twitter/X, and many others.
|
|
12
|
+
*/
|
|
13
|
+
export declare const providerIcons: Record<SocialProvider, ComponentType<ComponentPropsWithRef<"svg">>>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Apple, Atlassian, Cognito, Discord, Dropbox, Facebook, Figma, GitHub, GitLab, Google, HuggingFace, Kakao, Kick, Line, Linear, LinkedIn, Microsoft, Naver, Notion, Paybin, PayPal, Polar, Railway, Reddit, Roblox, Salesforce, Slack, Spotify, TikTok, Twitch, Vercel, VK, WeChat, X, Zoom } from "../components/icons";
|
|
2
|
+
/**
|
|
3
|
+
* Mapping of social authentication provider names to their corresponding icon components.
|
|
4
|
+
*
|
|
5
|
+
* Provides React SVG icon components for all supported social authentication providers.
|
|
6
|
+
* Each icon is a React component that accepts standard SVG props and can be customized
|
|
7
|
+
* with className, size, color, etc.
|
|
8
|
+
*
|
|
9
|
+
* Supported providers include: Apple, Google, GitHub, Microsoft, Discord, Facebook,
|
|
10
|
+
* Twitter/X, and many others.
|
|
11
|
+
*/
|
|
12
|
+
export const providerIcons = {
|
|
13
|
+
apple: Apple,
|
|
14
|
+
atlassian: Atlassian,
|
|
15
|
+
cognito: Cognito,
|
|
16
|
+
discord: Discord,
|
|
17
|
+
dropbox: Dropbox,
|
|
18
|
+
facebook: Facebook,
|
|
19
|
+
figma: Figma,
|
|
20
|
+
github: GitHub,
|
|
21
|
+
gitlab: GitLab,
|
|
22
|
+
google: Google,
|
|
23
|
+
huggingface: HuggingFace,
|
|
24
|
+
kakao: Kakao,
|
|
25
|
+
kick: Kick,
|
|
26
|
+
line: Line,
|
|
27
|
+
linear: Linear,
|
|
28
|
+
linkedin: LinkedIn,
|
|
29
|
+
microsoft: Microsoft,
|
|
30
|
+
naver: Naver,
|
|
31
|
+
notion: Notion,
|
|
32
|
+
paybin: Paybin,
|
|
33
|
+
paypal: PayPal,
|
|
34
|
+
polar: Polar,
|
|
35
|
+
railway: Railway,
|
|
36
|
+
reddit: Reddit,
|
|
37
|
+
roblox: Roblox,
|
|
38
|
+
salesforce: Salesforce,
|
|
39
|
+
slack: Slack,
|
|
40
|
+
spotify: Spotify,
|
|
41
|
+
tiktok: TikTok,
|
|
42
|
+
twitch: Twitch,
|
|
43
|
+
twitter: X,
|
|
44
|
+
vercel: Vercel,
|
|
45
|
+
vk: VK,
|
|
46
|
+
wechat: WeChat,
|
|
47
|
+
zoom: Zoom
|
|
48
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@better-auth-ui/react",
|
|
3
|
+
"version": "1.6.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "tsc",
|
|
7
|
+
"dev": "tsc --watch",
|
|
8
|
+
"email": "email dev --dir src/components/email -p 9000",
|
|
9
|
+
"test": "vitest"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"src",
|
|
13
|
+
"dist"
|
|
14
|
+
],
|
|
15
|
+
"main": "./dist/index.js",
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"import": "./dist/index.js",
|
|
20
|
+
"types": "./dist/index.d.ts"
|
|
21
|
+
},
|
|
22
|
+
"./core": {
|
|
23
|
+
"import": "./dist/core.js",
|
|
24
|
+
"types": "./dist/core.d.ts"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@react-email/components": "^1.0.12",
|
|
29
|
+
"@react-email/preview-server": "^5.2.10",
|
|
30
|
+
"@tanstack/react-query": "^5.99.0",
|
|
31
|
+
"@testing-library/react": "^16.3.2",
|
|
32
|
+
"@testing-library/user-event": "^14.5.2",
|
|
33
|
+
"@types/react": "^19.2.14",
|
|
34
|
+
"@vitejs/plugin-react": "^6.0.1",
|
|
35
|
+
"@vitest/browser-playwright": "^4.1.4",
|
|
36
|
+
"better-auth": "^1.6.4",
|
|
37
|
+
"clsx": "^2.1.1",
|
|
38
|
+
"playwright": "^1.59.1",
|
|
39
|
+
"react": "^19.2.5",
|
|
40
|
+
"react-dom": "^19.2.5",
|
|
41
|
+
"react-email": "^5.2.10",
|
|
42
|
+
"tailwind-merge": "^3.5.0",
|
|
43
|
+
"tailwindcss": "^4.2.2",
|
|
44
|
+
"vitest": "^4.1.4",
|
|
45
|
+
"zod": "^4.3.6"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@better-auth-ui/core": "*"
|
|
49
|
+
},
|
|
50
|
+
"peerDependencies": {
|
|
51
|
+
"@react-email/components": ">=1.0.12",
|
|
52
|
+
"@tanstack/react-query": ">=5.99.0",
|
|
53
|
+
"better-auth": ">=1.6.4",
|
|
54
|
+
"clsx": ">=2.0.0",
|
|
55
|
+
"react": ">=19.2.5",
|
|
56
|
+
"react-dom": ">=19.2.5",
|
|
57
|
+
"tailwind-merge": ">=3.5.0",
|
|
58
|
+
"tailwindcss": ">=4.2.2",
|
|
59
|
+
"zod": ">=4.3.0"
|
|
60
|
+
},
|
|
61
|
+
"publishConfig": {
|
|
62
|
+
"access": "public"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { deepmerge, defaultAuthConfig } from "@better-auth-ui/core"
|
|
4
|
+
import {
|
|
5
|
+
type AnyAuthClient,
|
|
6
|
+
type AnyAuthConfig,
|
|
7
|
+
type AuthConfig,
|
|
8
|
+
AuthContext
|
|
9
|
+
} from "@better-auth-ui/react"
|
|
10
|
+
import {
|
|
11
|
+
QueryClient,
|
|
12
|
+
QueryClientContext,
|
|
13
|
+
QueryClientProvider
|
|
14
|
+
} from "@tanstack/react-query"
|
|
15
|
+
import { type PropsWithChildren, useContext } from "react"
|
|
16
|
+
|
|
17
|
+
const fallbackQueryClient = new QueryClient()
|
|
18
|
+
|
|
19
|
+
const baseAuthConfig: AnyAuthConfig = {
|
|
20
|
+
...defaultAuthConfig,
|
|
21
|
+
Link: (props) => <a {...props} />
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type AuthProviderProps = PropsWithChildren<AnyAuthConfig> & {
|
|
25
|
+
authClient: AnyAuthClient
|
|
26
|
+
navigate: (options: { to: string; replace?: boolean }) => void
|
|
27
|
+
/**
|
|
28
|
+
* TanStack QueryClient to use for your application's queries
|
|
29
|
+
*/
|
|
30
|
+
queryClient?: QueryClient
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Provides merged authentication configuration and a resolved React Query client to descendant components.
|
|
35
|
+
*
|
|
36
|
+
* The component merges the provided auth config with the library defaults, updates `redirectTo` from the
|
|
37
|
+
* current URL when the app is hydrated, wires a QueryClient (prop, context, or fallback) and installs an
|
|
38
|
+
* error handler that surfaces query errors via the configured toast. It then supplies the merged config
|
|
39
|
+
* via AuthContext and wraps children with QueryClientProvider.
|
|
40
|
+
*
|
|
41
|
+
* @returns The children wrapped with AuthContext.Provider and QueryClientProvider configured for auth.
|
|
42
|
+
*/
|
|
43
|
+
export function AuthProvider({
|
|
44
|
+
children,
|
|
45
|
+
queryClient,
|
|
46
|
+
...config
|
|
47
|
+
}: AuthProviderProps) {
|
|
48
|
+
const contextQueryClient = useContext(QueryClientContext)
|
|
49
|
+
const resolvedQueryClient =
|
|
50
|
+
queryClient || contextQueryClient || fallbackQueryClient
|
|
51
|
+
|
|
52
|
+
const mergedConfig = deepmerge(baseAuthConfig, config) as AuthConfig
|
|
53
|
+
|
|
54
|
+
mergedConfig.redirectTo =
|
|
55
|
+
(typeof window !== "undefined" &&
|
|
56
|
+
new URLSearchParams(window.location.search).get("redirectTo")?.trim()) ||
|
|
57
|
+
mergedConfig.redirectTo
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<AuthContext.Provider value={mergedConfig}>
|
|
61
|
+
<QueryClientProvider client={resolvedQueryClient}>
|
|
62
|
+
{children}
|
|
63
|
+
</QueryClientProvider>
|
|
64
|
+
</AuthContext.Provider>
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Accesses the current authentication configuration from AuthContext.
|
|
70
|
+
*
|
|
71
|
+
* @returns The merged authentication configuration provided by AuthProvider.
|
|
72
|
+
* @throws If no AuthProvider is present in the component tree.
|
|
73
|
+
*/
|
|
74
|
+
export function useAuth() {
|
|
75
|
+
const context = useContext(AuthContext)
|
|
76
|
+
|
|
77
|
+
if (!context) {
|
|
78
|
+
throw new Error("[Better Auth UI] AuthProvider is required")
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return context
|
|
82
|
+
}
|
|
@@ -0,0 +1,381 @@
|
|
|
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
|
+
const emailChangedEmailLocalization = {
|
|
27
|
+
YOUR_EMAIL_ADDRESS_HAS_BEEN_CHANGED: "Your email address has been changed",
|
|
28
|
+
LOGO: "Logo",
|
|
29
|
+
EMAIL_ADDRESS_CHANGED: "Email address changed",
|
|
30
|
+
EMAIL_ADDRESS_FOR_YOUR_ACCOUNT_CHANGED:
|
|
31
|
+
"The email address for your {appName} account has been changed.",
|
|
32
|
+
PREVIOUS_EMAIL: "Previous email:",
|
|
33
|
+
NEW_EMAIL: "New email:",
|
|
34
|
+
IF_YOU_MADE_THIS_CHANGE:
|
|
35
|
+
"If you made this change, you can safely ignore this email.",
|
|
36
|
+
I_DIDNT_MAKE_THIS_CHANGE: "I didn't make this change",
|
|
37
|
+
EMAIL_SENT_BY: "Email sent by {appName}.",
|
|
38
|
+
IF_YOU_DIDNT_AUTHORIZE_THIS_CHANGE:
|
|
39
|
+
"If you didn't authorize this change, please contact support immediately {supportEmail} to secure your account.",
|
|
40
|
+
POWERED_BY_BETTER_AUTH: "Powered by {betterAuth}"
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Localization strings for the EmailChangedEmail component.
|
|
45
|
+
*
|
|
46
|
+
* Contains all text content used in the email changed notification email template.
|
|
47
|
+
*/
|
|
48
|
+
export type EmailChangedEmailLocalization = typeof emailChangedEmailLocalization
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Props for the EmailChangedEmail component.
|
|
52
|
+
*/
|
|
53
|
+
export interface EmailChangedEmailProps {
|
|
54
|
+
/** The previous email address that was changed */
|
|
55
|
+
oldEmail?: string
|
|
56
|
+
/** The new email address */
|
|
57
|
+
newEmail?: string
|
|
58
|
+
/** URL to revert the email change if unauthorized */
|
|
59
|
+
revertURL?: string
|
|
60
|
+
/** Name of the application sending the email */
|
|
61
|
+
appName?: string
|
|
62
|
+
/** Support email address for security concerns */
|
|
63
|
+
supportEmail?: string
|
|
64
|
+
/** Logo URL(s) - a single string or light/dark variants. If omitted, no logo is shown. */
|
|
65
|
+
logoURL?: string | { light: string; dark: string }
|
|
66
|
+
/** Custom CSS class names for styling specific parts of the email */
|
|
67
|
+
classNames?: EmailClassNames
|
|
68
|
+
/** Custom color scheme for light and dark modes */
|
|
69
|
+
colors?: EmailColors
|
|
70
|
+
/** Whether to show the "Powered by better-auth" footer */
|
|
71
|
+
poweredBy?: boolean
|
|
72
|
+
/** Whether to enable dark mode support */
|
|
73
|
+
darkMode?: boolean
|
|
74
|
+
/** Additional React nodes to inject into the email head */
|
|
75
|
+
head?: ReactNode
|
|
76
|
+
/**
|
|
77
|
+
* Localization overrides for customizing email text
|
|
78
|
+
* @remarks `EmailChangedEmailLocalization`
|
|
79
|
+
*/
|
|
80
|
+
localization?: Partial<EmailChangedEmailLocalization>
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Email template component that notifies users when their email address has been changed.
|
|
85
|
+
*
|
|
86
|
+
* This email includes:
|
|
87
|
+
* - Display of both old and new email addresses
|
|
88
|
+
* - Revert action button if unauthorized change occurred
|
|
89
|
+
* - Security information and support contact details
|
|
90
|
+
* - Customizable branding and styling
|
|
91
|
+
* - Support for light/dark mode themes
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```tsx
|
|
95
|
+
* <EmailChangedEmail
|
|
96
|
+
* oldEmail="old@example.com"
|
|
97
|
+
* newEmail="new@example.com"
|
|
98
|
+
* revertURL="https://example.com/revert?token=abc123"
|
|
99
|
+
* appName="My App"
|
|
100
|
+
* supportEmail="support@example.com"
|
|
101
|
+
* logoURL="https://example.com/logo.png"
|
|
102
|
+
* darkMode={true}
|
|
103
|
+
* />
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
export const EmailChangedEmail = ({
|
|
107
|
+
oldEmail,
|
|
108
|
+
newEmail,
|
|
109
|
+
revertURL,
|
|
110
|
+
appName,
|
|
111
|
+
supportEmail,
|
|
112
|
+
logoURL,
|
|
113
|
+
colors,
|
|
114
|
+
classNames,
|
|
115
|
+
darkMode = true,
|
|
116
|
+
poweredBy,
|
|
117
|
+
head,
|
|
118
|
+
...props
|
|
119
|
+
}: EmailChangedEmailProps) => {
|
|
120
|
+
const localization = {
|
|
121
|
+
...EmailChangedEmail.localization,
|
|
122
|
+
...props.localization
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const previewText = localization.YOUR_EMAIL_ADDRESS_HAS_BEEN_CHANGED
|
|
126
|
+
|
|
127
|
+
return (
|
|
128
|
+
<Html>
|
|
129
|
+
<Head>
|
|
130
|
+
<meta content="light dark" name="color-scheme" />
|
|
131
|
+
<meta content="light dark" name="supported-color-schemes" />
|
|
132
|
+
|
|
133
|
+
<EmailStyles colors={colors} darkMode={darkMode} />
|
|
134
|
+
|
|
135
|
+
{head}
|
|
136
|
+
</Head>
|
|
137
|
+
|
|
138
|
+
<Preview>{previewText}</Preview>
|
|
139
|
+
|
|
140
|
+
<Tailwind config={{ presets: [pixelBasedPreset] }}>
|
|
141
|
+
<Body className={cn("bg-background font-sans", classNames?.body)}>
|
|
142
|
+
<Container
|
|
143
|
+
className={cn(
|
|
144
|
+
"mx-auto my-auto max-w-xl px-2 py-10",
|
|
145
|
+
classNames?.container
|
|
146
|
+
)}
|
|
147
|
+
>
|
|
148
|
+
<Section
|
|
149
|
+
className={cn(
|
|
150
|
+
"bg-card text-card-foreground rounded-none border border-border p-8",
|
|
151
|
+
classNames?.card
|
|
152
|
+
)}
|
|
153
|
+
>
|
|
154
|
+
{logoURL &&
|
|
155
|
+
(typeof logoURL === "string" ? (
|
|
156
|
+
<Img
|
|
157
|
+
src={logoURL}
|
|
158
|
+
width={48}
|
|
159
|
+
height={48}
|
|
160
|
+
alt={appName || localization.LOGO}
|
|
161
|
+
className={cn("mx-auto mb-8", classNames?.logo)}
|
|
162
|
+
/>
|
|
163
|
+
) : (
|
|
164
|
+
<>
|
|
165
|
+
<Img
|
|
166
|
+
src={logoURL.light}
|
|
167
|
+
width={48}
|
|
168
|
+
height={48}
|
|
169
|
+
alt={appName || localization.LOGO}
|
|
170
|
+
className={cn(
|
|
171
|
+
"mx-auto mb-8 logo-light",
|
|
172
|
+
classNames?.logo
|
|
173
|
+
)}
|
|
174
|
+
/>
|
|
175
|
+
<Img
|
|
176
|
+
src={logoURL.dark}
|
|
177
|
+
width={48}
|
|
178
|
+
height={48}
|
|
179
|
+
alt={appName || localization.LOGO}
|
|
180
|
+
className={cn(
|
|
181
|
+
"hidden mx-auto mb-8 logo-dark",
|
|
182
|
+
classNames?.logo
|
|
183
|
+
)}
|
|
184
|
+
/>
|
|
185
|
+
</>
|
|
186
|
+
))}
|
|
187
|
+
|
|
188
|
+
<Heading
|
|
189
|
+
className={cn(
|
|
190
|
+
"m-0 mb-5 text-2xl font-semibold",
|
|
191
|
+
classNames?.title
|
|
192
|
+
)}
|
|
193
|
+
>
|
|
194
|
+
{localization.EMAIL_ADDRESS_CHANGED}
|
|
195
|
+
</Heading>
|
|
196
|
+
|
|
197
|
+
<Text className={cn("text-sm font-normal", classNames?.content)}>
|
|
198
|
+
{localization.EMAIL_ADDRESS_FOR_YOUR_ACCOUNT_CHANGED.replace(
|
|
199
|
+
"{appName}",
|
|
200
|
+
appName || ""
|
|
201
|
+
)
|
|
202
|
+
.replace(/\s{2,}/g, " ")
|
|
203
|
+
.replace(" .", ".")}
|
|
204
|
+
</Text>
|
|
205
|
+
|
|
206
|
+
{(oldEmail || newEmail) && (
|
|
207
|
+
<Section
|
|
208
|
+
className={cn(
|
|
209
|
+
"my-6 border border-border bg-muted p-4",
|
|
210
|
+
classNames?.codeBlock
|
|
211
|
+
)}
|
|
212
|
+
>
|
|
213
|
+
{oldEmail && (
|
|
214
|
+
<>
|
|
215
|
+
<Text
|
|
216
|
+
className={cn(
|
|
217
|
+
"m-0 mb-2 text-xs text-muted-foreground",
|
|
218
|
+
classNames?.description
|
|
219
|
+
)}
|
|
220
|
+
>
|
|
221
|
+
{localization.PREVIOUS_EMAIL}
|
|
222
|
+
</Text>
|
|
223
|
+
|
|
224
|
+
<Text
|
|
225
|
+
className={cn(
|
|
226
|
+
"m-0 mb-4 text-sm font-semibold",
|
|
227
|
+
classNames?.content
|
|
228
|
+
)}
|
|
229
|
+
>
|
|
230
|
+
{oldEmail}
|
|
231
|
+
</Text>
|
|
232
|
+
</>
|
|
233
|
+
)}
|
|
234
|
+
|
|
235
|
+
{newEmail && (
|
|
236
|
+
<>
|
|
237
|
+
<Text
|
|
238
|
+
className={cn(
|
|
239
|
+
"m-0 mb-2 text-xs text-muted-foreground",
|
|
240
|
+
classNames?.description
|
|
241
|
+
)}
|
|
242
|
+
>
|
|
243
|
+
{localization.NEW_EMAIL}
|
|
244
|
+
</Text>
|
|
245
|
+
|
|
246
|
+
<Text
|
|
247
|
+
className={cn(
|
|
248
|
+
"m-0 text-sm font-semibold text-primary",
|
|
249
|
+
classNames?.content
|
|
250
|
+
)}
|
|
251
|
+
>
|
|
252
|
+
{newEmail}
|
|
253
|
+
</Text>
|
|
254
|
+
</>
|
|
255
|
+
)}
|
|
256
|
+
</Section>
|
|
257
|
+
)}
|
|
258
|
+
|
|
259
|
+
<Text className={cn("text-sm font-normal", classNames?.content)}>
|
|
260
|
+
{localization.IF_YOU_MADE_THIS_CHANGE}
|
|
261
|
+
</Text>
|
|
262
|
+
|
|
263
|
+
{revertURL && (
|
|
264
|
+
<Section className="my-6">
|
|
265
|
+
<Button
|
|
266
|
+
href={revertURL}
|
|
267
|
+
className={cn(
|
|
268
|
+
"inline-block whitespace-nowrap rounded-none text-sm font-medium py-2.5 px-6 bg-primary text-primary-foreground no-underline",
|
|
269
|
+
classNames?.button
|
|
270
|
+
)}
|
|
271
|
+
>
|
|
272
|
+
{localization.I_DIDNT_MAKE_THIS_CHANGE}
|
|
273
|
+
</Button>
|
|
274
|
+
</Section>
|
|
275
|
+
)}
|
|
276
|
+
|
|
277
|
+
<Hr
|
|
278
|
+
className={cn(
|
|
279
|
+
"my-6 w-full border border-solid border-border",
|
|
280
|
+
classNames?.separator
|
|
281
|
+
)}
|
|
282
|
+
/>
|
|
283
|
+
|
|
284
|
+
{appName && (
|
|
285
|
+
<Text
|
|
286
|
+
className={cn(
|
|
287
|
+
"mb-3 text-xs text-muted-foreground",
|
|
288
|
+
classNames?.description
|
|
289
|
+
)}
|
|
290
|
+
>
|
|
291
|
+
{localization.EMAIL_SENT_BY.replace("{appName}", appName)}
|
|
292
|
+
</Text>
|
|
293
|
+
)}
|
|
294
|
+
|
|
295
|
+
<Text
|
|
296
|
+
className={cn(
|
|
297
|
+
"mt-3 text-xs text-muted-foreground",
|
|
298
|
+
classNames?.description
|
|
299
|
+
)}
|
|
300
|
+
>
|
|
301
|
+
{(() => {
|
|
302
|
+
const [beforeSupportEmail, afterSupportEmail] =
|
|
303
|
+
localization.IF_YOU_DIDNT_AUTHORIZE_THIS_CHANGE.split(
|
|
304
|
+
"{supportEmail}"
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
return supportEmail ? (
|
|
308
|
+
<>
|
|
309
|
+
{beforeSupportEmail}
|
|
310
|
+
<Link
|
|
311
|
+
href={`mailto:${supportEmail}`}
|
|
312
|
+
className={cn(
|
|
313
|
+
"text-primary underline",
|
|
314
|
+
classNames?.link
|
|
315
|
+
)}
|
|
316
|
+
>
|
|
317
|
+
{supportEmail}
|
|
318
|
+
</Link>
|
|
319
|
+
{afterSupportEmail}
|
|
320
|
+
</>
|
|
321
|
+
) : (
|
|
322
|
+
localization.IF_YOU_DIDNT_AUTHORIZE_THIS_CHANGE.replace(
|
|
323
|
+
"{supportEmail}",
|
|
324
|
+
""
|
|
325
|
+
)
|
|
326
|
+
.replace(/\s{2,}/g, " ")
|
|
327
|
+
.replace(" .", ".")
|
|
328
|
+
)
|
|
329
|
+
})()}
|
|
330
|
+
</Text>
|
|
331
|
+
|
|
332
|
+
{poweredBy && (
|
|
333
|
+
<Text
|
|
334
|
+
className={cn(
|
|
335
|
+
"mt-4 mb-0 text-center text-[11px] text-muted-foreground",
|
|
336
|
+
classNames?.poweredBy
|
|
337
|
+
)}
|
|
338
|
+
>
|
|
339
|
+
{(() => {
|
|
340
|
+
const [beforeBetterAuth, afterBetterAuth] =
|
|
341
|
+
localization.POWERED_BY_BETTER_AUTH.split("{betterAuth}")
|
|
342
|
+
|
|
343
|
+
return (
|
|
344
|
+
<>
|
|
345
|
+
{beforeBetterAuth}
|
|
346
|
+
<Link
|
|
347
|
+
href="https://better-auth.com"
|
|
348
|
+
className={cn(
|
|
349
|
+
"text-primary underline",
|
|
350
|
+
classNames?.link
|
|
351
|
+
)}
|
|
352
|
+
>
|
|
353
|
+
better-auth
|
|
354
|
+
</Link>
|
|
355
|
+
{afterBetterAuth}
|
|
356
|
+
</>
|
|
357
|
+
)
|
|
358
|
+
})()}
|
|
359
|
+
</Text>
|
|
360
|
+
)}
|
|
361
|
+
</Section>
|
|
362
|
+
</Container>
|
|
363
|
+
</Body>
|
|
364
|
+
</Tailwind>
|
|
365
|
+
</Html>
|
|
366
|
+
)
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
EmailChangedEmail.localization = emailChangedEmailLocalization
|
|
370
|
+
|
|
371
|
+
EmailChangedEmail.PreviewProps = {
|
|
372
|
+
oldEmail: "old@example.com",
|
|
373
|
+
newEmail: "new@example.com",
|
|
374
|
+
supportEmail: "support@example.com",
|
|
375
|
+
revertURL: "https://better-auth-ui.com/auth/revert-email?token=example-token",
|
|
376
|
+
appName: "Better Auth",
|
|
377
|
+
poweredBy: true,
|
|
378
|
+
darkMode: true
|
|
379
|
+
} as EmailChangedEmailProps
|
|
380
|
+
|
|
381
|
+
export default EmailChangedEmail
|