@better-auth-ui/heroui 1.6.3 → 1.6.5
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/additional-field.d.ts +4 -0
- package/dist/components/auth/additional-field.js +270 -0
- package/dist/components/auth/auth-provider.d.ts +4 -6
- package/dist/components/auth/auth.d.ts +1 -1
- package/dist/components/auth/auth.js +54 -28
- package/dist/components/{settings/security → auth/delete-user}/danger-zone.d.ts +1 -1
- package/dist/components/{settings/security → auth/delete-user}/danger-zone.js +1 -1
- package/dist/components/auth/delete-user/delete-user.js +95 -0
- package/dist/components/{email → auth/email}/email-changed-email.d.ts +2 -2
- package/dist/components/{email → auth/email}/email-changed-email.js +7 -7
- package/dist/components/{email → auth/email}/email-verification-email.d.ts +2 -2
- package/dist/components/{email → auth/email}/email-verification-email.js +7 -7
- package/dist/components/auth/email/magic-link-email.d.ts +3 -0
- package/dist/components/{email → auth/email}/magic-link-email.js +7 -7
- package/dist/components/auth/email/new-device-email.d.ts +3 -0
- package/dist/components/{email → auth/email}/new-device-email.js +7 -7
- package/dist/components/auth/email/otp-email.d.ts +3 -0
- package/dist/components/{email → auth/email}/otp-email.js +6 -6
- package/dist/components/{email → auth/email}/password-changed-email.d.ts +2 -2
- package/dist/components/{email → auth/email}/password-changed-email.js +7 -7
- package/dist/components/{email → auth/email}/reset-password-email.d.ts +2 -2
- package/dist/components/{email → auth/email}/reset-password-email.js +7 -7
- package/dist/components/auth/forgot-password.d.ts +1 -1
- package/dist/components/auth/forgot-password.js +70 -48
- package/dist/components/auth/magic-link/magic-link-button.d.ts +11 -0
- package/dist/components/auth/magic-link/magic-link-button.js +20 -0
- package/dist/components/auth/magic-link/magic-link.d.ts +16 -0
- package/dist/components/auth/magic-link/magic-link.js +87 -0
- package/dist/components/{settings/account → auth/multi-session}/manage-account.d.ts +2 -6
- package/dist/components/auth/multi-session/manage-account.js +49 -0
- package/dist/components/auth/multi-session/manage-accounts.js +34 -0
- package/dist/components/{user/switch-account-menu.d.ts → auth/multi-session/switch-account-submenu-content.d.ts} +3 -3
- package/dist/components/auth/multi-session/switch-account-submenu-content.js +29 -0
- package/dist/components/{user/switch-account-item.d.ts → auth/multi-session/switch-account-submenu-item.d.ts} +2 -2
- package/dist/components/auth/multi-session/switch-account-submenu-item.js +20 -0
- package/dist/components/auth/multi-session/switch-account-submenu.d.ts +13 -0
- package/dist/components/auth/multi-session/switch-account-submenu.js +24 -0
- package/dist/components/auth/passkey/passkey-button.d.ts +6 -0
- package/dist/components/auth/passkey/passkey-button.js +24 -0
- package/dist/components/auth/passkey/passkey.js +45 -0
- package/dist/components/auth/passkey/passkeys.js +106 -0
- package/dist/components/auth/provider-button.d.ts +6 -8
- package/dist/components/auth/provider-button.js +16 -20
- package/dist/components/auth/provider-buttons.d.ts +3 -4
- package/dist/components/auth/provider-buttons.js +9 -10
- package/dist/components/auth/reset-password.js +110 -107
- package/dist/components/{settings → auth/settings}/account/account-settings.d.ts +5 -2
- package/dist/components/auth/settings/account/account-settings.js +20 -0
- package/dist/components/auth/settings/account/change-avatar.js +89 -0
- package/dist/components/{settings → auth/settings}/account/change-email.js +17 -17
- package/dist/components/{settings → auth/settings}/account/user-profile.d.ts +2 -3
- package/dist/components/auth/settings/account/user-profile.js +86 -0
- package/dist/components/auth/settings/security/active-session.js +59 -0
- package/dist/components/{settings → auth/settings}/security/active-sessions.js +4 -4
- package/dist/components/auth/settings/security/change-password.js +189 -0
- package/dist/components/auth/settings/security/linked-account.js +56 -0
- package/dist/components/{settings → auth/settings}/security/linked-accounts.js +5 -5
- package/dist/components/{settings → auth/settings}/security/security-settings.d.ts +1 -1
- package/dist/components/auth/settings/security/security-settings.js +22 -0
- package/dist/components/auth/settings/settings.js +45 -0
- package/dist/components/auth/sign-in.js +66 -85
- package/dist/components/auth/sign-out.js +11 -11
- package/dist/components/auth/sign-up.js +128 -148
- package/dist/components/{settings/account → auth/theme}/appearance.d.ts +3 -6
- package/dist/components/auth/theme/appearance.js +72 -0
- package/dist/components/auth/theme/theme-toggle-item.d.ts +5 -0
- package/dist/components/auth/theme/theme-toggle-item.js +58 -0
- package/dist/components/auth/user/user-avatar.js +29 -0
- package/dist/components/{user → auth/user}/user-button.d.ts +2 -6
- package/dist/components/auth/user/user-button.js +55 -0
- package/dist/components/auth/user/user-view.js +37 -0
- package/dist/components/auth/username/sign-in-username.d.ts +14 -0
- package/dist/components/auth/username/sign-in-username.js +148 -0
- package/dist/components/auth/username/username-field.d.ts +8 -0
- package/dist/components/auth/username/username-field.js +53 -0
- package/dist/email.d.ts +7 -0
- package/dist/email.js +9 -0
- package/dist/index.d.ts +12 -27
- package/dist/index.js +20 -35
- package/dist/lib/auth/auth-plugin.d.ts +44 -0
- package/dist/lib/auth/delete-user-plugin.d.ts +17 -0
- package/dist/lib/auth/delete-user-plugin.js +10 -0
- package/dist/lib/auth/magic-link-plugin.d.ts +31 -0
- package/dist/lib/auth/magic-link-plugin.js +13 -0
- package/dist/lib/auth/multi-session-plugin.d.ts +18 -0
- package/dist/lib/auth/multi-session-plugin.js +12 -0
- package/dist/lib/auth/passkey-plugin.d.ts +20 -0
- package/dist/lib/auth/passkey-plugin.js +12 -0
- package/dist/lib/auth/theme-plugin.d.ts +68 -0
- package/dist/lib/auth/theme-plugin.js +23 -0
- package/dist/lib/auth/username-plugin.d.ts +63 -0
- package/dist/lib/auth/username-plugin.js +18 -0
- package/dist/plugins.d.ts +20 -0
- package/dist/plugins.js +21 -0
- package/package.json +19 -21
- package/src/components/auth/additional-field.tsx +554 -0
- package/src/components/auth/auth-provider.tsx +5 -6
- package/src/components/auth/auth.tsx +99 -35
- package/src/components/{settings/security → auth/delete-user}/danger-zone.tsx +1 -1
- package/src/components/{settings/security → auth/delete-user}/delete-user.tsx +30 -20
- package/src/components/{email → auth/email}/email-changed-email.tsx +2 -2
- package/src/components/{email → auth/email}/email-verification-email.tsx +2 -2
- package/src/components/{email → auth/email}/magic-link-email.tsx +2 -2
- package/src/components/{email → auth/email}/new-device-email.tsx +2 -2
- package/src/components/{email → auth/email}/otp-email.tsx +2 -2
- package/src/components/{email → auth/email}/password-changed-email.tsx +2 -2
- package/src/components/{email → auth/email}/reset-password-email.tsx +2 -2
- package/src/components/auth/forgot-password.tsx +42 -17
- package/src/components/auth/magic-link/magic-link-button.tsx +61 -0
- package/src/components/auth/{magic-link.tsx → magic-link/magic-link.tsx} +55 -40
- package/src/components/{settings/account → auth/multi-session}/manage-account.tsx +16 -13
- package/src/components/{settings/account → auth/multi-session}/manage-accounts.tsx +14 -5
- package/src/components/{user/switch-account-menu.tsx → auth/multi-session/switch-account-submenu-content.tsx} +18 -11
- package/src/components/{user/switch-account-item.tsx → auth/multi-session/switch-account-submenu-item.tsx} +17 -5
- package/src/components/auth/multi-session/switch-account-submenu.tsx +50 -0
- package/src/components/auth/passkey/passkey-button.tsx +56 -0
- package/src/components/{settings/security → auth/passkey}/passkey.tsx +20 -6
- package/src/components/auth/passkey/passkeys.tsx +196 -0
- package/src/components/auth/provider-button.tsx +27 -29
- package/src/components/auth/provider-buttons.tsx +6 -11
- package/src/components/auth/reset-password.tsx +13 -7
- package/src/components/{settings → auth/settings}/account/account-settings.tsx +15 -13
- package/src/components/{settings → auth/settings}/account/change-avatar.tsx +4 -3
- package/src/components/{settings → auth/settings}/account/change-email.tsx +3 -3
- package/src/components/auth/settings/account/user-profile.tsx +171 -0
- package/src/components/{settings → auth/settings}/security/active-session.tsx +8 -5
- package/src/components/{settings → auth/settings}/security/active-sessions.tsx +3 -3
- package/src/components/{settings → auth/settings}/security/change-password.tsx +14 -9
- package/src/components/{settings → auth/settings}/security/linked-account.tsx +12 -8
- package/src/components/{settings → auth/settings}/security/linked-accounts.tsx +2 -2
- package/src/components/{settings → auth/settings}/security/security-settings.tsx +7 -6
- package/src/components/{settings → auth/settings}/settings.tsx +2 -2
- package/src/components/auth/sign-in.tsx +50 -61
- package/src/components/auth/sign-out.tsx +2 -2
- package/src/components/auth/sign-up.tsx +119 -131
- package/src/components/{settings/account → auth/theme}/appearance.tsx +17 -24
- package/src/components/auth/theme/theme-toggle-item.tsx +110 -0
- package/src/components/{user → auth/user}/user-avatar.tsx +12 -4
- package/src/components/{user → auth/user}/user-button.tsx +15 -88
- package/src/components/{user → auth/user}/user-view.tsx +12 -4
- package/src/components/auth/username/sign-in-username.tsx +299 -0
- package/src/components/auth/username/username-field.tsx +124 -0
- package/src/email.ts +9 -0
- package/src/index.tsx +12 -27
- package/src/lib/auth/auth-plugin.ts +67 -0
- package/src/lib/auth/delete-user-plugin.ts +15 -0
- package/src/lib/auth/magic-link-plugin.ts +26 -0
- package/src/lib/auth/multi-session-plugin.ts +17 -0
- package/src/lib/auth/passkey-plugin.ts +17 -0
- package/src/lib/auth/theme-plugin.ts +86 -0
- package/src/lib/auth/username-plugin.tsx +30 -0
- package/src/plugins.ts +23 -0
- package/dist/components/auth/magic-link-button.d.ts +0 -13
- package/dist/components/auth/magic-link-button.js +0 -16
- package/dist/components/auth/magic-link.d.ts +0 -17
- package/dist/components/auth/magic-link.js +0 -99
- package/dist/components/auth/passkey-button.d.ts +0 -4
- package/dist/components/auth/passkey-button.js +0 -21
- package/dist/components/email/magic-link-email.d.ts +0 -3
- package/dist/components/email/new-device-email.d.ts +0 -3
- package/dist/components/email/otp-email.d.ts +0 -3
- package/dist/components/settings/account/account-settings.js +0 -23
- package/dist/components/settings/account/appearance.js +0 -71
- package/dist/components/settings/account/change-avatar.js +0 -89
- package/dist/components/settings/account/manage-account.js +0 -48
- package/dist/components/settings/account/manage-accounts.js +0 -33
- package/dist/components/settings/account/user-profile.js +0 -103
- package/dist/components/settings/security/active-session.js +0 -59
- package/dist/components/settings/security/change-password.js +0 -189
- package/dist/components/settings/security/delete-user.js +0 -92
- package/dist/components/settings/security/linked-account.js +0 -56
- package/dist/components/settings/security/passkey.js +0 -43
- package/dist/components/settings/security/passkeys.js +0 -53
- package/dist/components/settings/security/security-settings.js +0 -25
- package/dist/components/settings/settings.js +0 -45
- package/dist/components/user/switch-account-item.js +0 -20
- package/dist/components/user/switch-account-menu.js +0 -28
- package/dist/components/user/user-avatar.js +0 -29
- package/dist/components/user/user-button.js +0 -91
- package/dist/components/user/user-view.js +0 -37
- package/dist/core.d.ts +0 -1
- package/dist/core.js +0 -1
- package/dist/react-exports.d.ts +0 -1
- package/dist/react-exports.js +0 -1
- package/src/components/auth/magic-link-button.tsx +0 -43
- package/src/components/auth/passkey-button.tsx +0 -35
- package/src/components/settings/account/user-profile.tsx +0 -217
- package/src/components/settings/security/passkeys.tsx +0 -96
- package/src/core.ts +0 -1
- package/src/react-exports.ts +0 -1
- /package/dist/components/{settings/security → auth/delete-user}/delete-user.d.ts +0 -0
- /package/dist/components/{settings/account → auth/multi-session}/manage-accounts.d.ts +0 -0
- /package/dist/components/{settings/security → auth/passkey}/passkey.d.ts +0 -0
- /package/dist/components/{settings/security → auth/passkey}/passkeys.d.ts +0 -0
- /package/dist/components/{settings → auth/settings}/account/change-avatar.d.ts +0 -0
- /package/dist/components/{settings → auth/settings}/account/change-email.d.ts +0 -0
- /package/dist/components/{settings → auth/settings}/security/active-session.d.ts +0 -0
- /package/dist/components/{settings → auth/settings}/security/active-sessions.d.ts +0 -0
- /package/dist/components/{settings → auth/settings}/security/change-password.d.ts +0 -0
- /package/dist/components/{settings → auth/settings}/security/linked-account.d.ts +0 -0
- /package/dist/components/{settings → auth/settings}/security/linked-accounts.d.ts +0 -0
- /package/dist/components/{settings → auth/settings}/settings.d.ts +0 -0
- /package/dist/components/{user → auth/user}/user-avatar.d.ts +0 -0
- /package/dist/components/{user → auth/user}/user-view.d.ts +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { AuthView } from "@better-auth-ui/core"
|
|
2
2
|
import { useAuth } from "@better-auth-ui/react"
|
|
3
3
|
import type { CardProps } from "@heroui/react"
|
|
4
|
+
import { type ComponentType, useEffect } from "react"
|
|
4
5
|
import { ForgotPassword } from "./forgot-password"
|
|
5
|
-
import { MagicLink } from "./magic-link"
|
|
6
6
|
import type { SocialLayout } from "./provider-buttons"
|
|
7
7
|
import { ResetPassword } from "./reset-password"
|
|
8
8
|
import { SignIn } from "./sign-in"
|
|
@@ -19,6 +19,21 @@ export type AuthProps = {
|
|
|
19
19
|
view?: AuthView
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Built-in views that only make sense when email + password auth is enabled.
|
|
24
|
+
* When it's disabled, the `<Auth>` router redirects these to `signIn` so a
|
|
25
|
+
* plugin's `fallbackViews.auth.signIn` (e.g. magic link) takes over.
|
|
26
|
+
*/
|
|
27
|
+
const PASSWORD_ONLY_VIEWS = ["signUp", "forgotPassword", "resetPassword"]
|
|
28
|
+
|
|
29
|
+
const AUTH_VIEWS: Partial<Record<AuthView, ComponentType<AuthProps>>> = {
|
|
30
|
+
signIn: SignIn,
|
|
31
|
+
signOut: SignOut,
|
|
32
|
+
signUp: SignUp,
|
|
33
|
+
forgotPassword: ForgotPassword,
|
|
34
|
+
resetPassword: ResetPassword
|
|
35
|
+
}
|
|
36
|
+
|
|
22
37
|
/**
|
|
23
38
|
* Render the appropriate authentication view based on the provided `view` or `path`.
|
|
24
39
|
*
|
|
@@ -36,52 +51,101 @@ export function Auth({
|
|
|
36
51
|
view,
|
|
37
52
|
...props
|
|
38
53
|
}: AuthProps & Omit<CardProps, "children">) {
|
|
39
|
-
const { viewPaths } =
|
|
54
|
+
const { basePaths, emailAndPassword, plugins, viewPaths, navigate } =
|
|
55
|
+
useAuth()
|
|
40
56
|
|
|
41
57
|
if (!view && !path) {
|
|
42
58
|
throw new Error("[Better Auth UI] Either `view` or `path` must be provided")
|
|
43
59
|
}
|
|
44
60
|
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
61
|
+
const authView =
|
|
62
|
+
view ||
|
|
63
|
+
(Object.keys(viewPaths.auth) as AuthView[]).find(
|
|
64
|
+
(key) => viewPaths.auth[key] === path
|
|
65
|
+
)
|
|
48
66
|
|
|
49
|
-
|
|
67
|
+
// When email + password auth is disabled, password-only views (signUp,
|
|
68
|
+
// forgotPassword, resetPassword) have no meaning. Redirect them to signIn,
|
|
69
|
+
// where a plugin's `fallbackViews.auth.signIn` (e.g. magic link) takes
|
|
70
|
+
// over as the primary entry point.
|
|
71
|
+
const shouldRedirectToSignIn =
|
|
72
|
+
!emailAndPassword?.enabled &&
|
|
73
|
+
authView &&
|
|
74
|
+
PASSWORD_ONLY_VIEWS.includes(authView)
|
|
50
75
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
if (shouldRedirectToSignIn) {
|
|
78
|
+
navigate({
|
|
79
|
+
to: `${basePaths.auth}/${viewPaths.auth.signIn}`,
|
|
80
|
+
replace: true
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
}, [shouldRedirectToSignIn, navigate, basePaths.auth, viewPaths.auth.signIn])
|
|
84
|
+
|
|
85
|
+
if (shouldRedirectToSignIn) {
|
|
86
|
+
return null
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// 1. Plugin overrides (`views.auth[currentView]`) — first plugin wins,
|
|
90
|
+
// including over built-in views. Resolves the view key from `view`,
|
|
91
|
+
// then `authView` (built-in path match), then plugin-introduced paths
|
|
92
|
+
// (e.g. `magicLink` → `/auth/magic-link`).
|
|
93
|
+
for (const plugin of plugins) {
|
|
94
|
+
const pluginAuthPaths = plugin.viewPaths?.auth
|
|
95
|
+
|
|
96
|
+
const pluginView =
|
|
97
|
+
view ??
|
|
98
|
+
authView ??
|
|
99
|
+
(pluginAuthPaths &&
|
|
100
|
+
Object.keys(pluginAuthPaths).find(
|
|
101
|
+
(key) => pluginAuthPaths[key] === path
|
|
102
|
+
))
|
|
103
|
+
if (!pluginView) continue
|
|
104
|
+
|
|
105
|
+
const PluginView = plugin.views?.auth?.[pluginView]
|
|
106
|
+
if (!PluginView) continue
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<PluginView
|
|
110
|
+
socialLayout={socialLayout}
|
|
111
|
+
socialPosition={socialPosition}
|
|
112
|
+
{...props}
|
|
113
|
+
/>
|
|
114
|
+
)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// 2. Plugin fallbacks — only when the built-in `signIn` isn't viable
|
|
118
|
+
// (password auth is off). Used by `magicLinkPlugin` to render the
|
|
119
|
+
// magic-link form as the primary passwordless sign-in surface.
|
|
120
|
+
if (authView === "signIn" && !emailAndPassword?.enabled) {
|
|
121
|
+
const Fallback = plugins.find(
|
|
122
|
+
(plugin) => plugin.fallbackViews?.auth?.signIn
|
|
123
|
+
)?.fallbackViews?.auth?.signIn
|
|
124
|
+
|
|
125
|
+
if (Fallback) {
|
|
69
126
|
return (
|
|
70
|
-
<
|
|
127
|
+
<Fallback
|
|
71
128
|
socialLayout={socialLayout}
|
|
72
129
|
socialPosition={socialPosition}
|
|
73
130
|
{...props}
|
|
74
131
|
/>
|
|
75
132
|
)
|
|
76
|
-
|
|
77
|
-
return <ForgotPassword {...props} />
|
|
78
|
-
case "resetPassword":
|
|
79
|
-
return <ResetPassword {...props} />
|
|
80
|
-
case "signOut":
|
|
81
|
-
return <SignOut {...props} />
|
|
82
|
-
default:
|
|
83
|
-
throw new Error(
|
|
84
|
-
`[Better Auth UI] Valid views are: ${Object.keys(viewPaths.auth).join(", ")}`
|
|
85
|
-
)
|
|
133
|
+
}
|
|
86
134
|
}
|
|
135
|
+
|
|
136
|
+
const AuthView = authView ? AUTH_VIEWS[authView] : undefined
|
|
137
|
+
|
|
138
|
+
if (!AuthView) {
|
|
139
|
+
throw new Error(
|
|
140
|
+
`[Better Auth UI] Unknown view "${authView}". Valid views are: ${Object.keys(AUTH_VIEWS).join(", ")}`
|
|
141
|
+
)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return (
|
|
145
|
+
<AuthView
|
|
146
|
+
socialLayout={socialLayout}
|
|
147
|
+
socialPosition={socialPosition}
|
|
148
|
+
{...props}
|
|
149
|
+
/>
|
|
150
|
+
)
|
|
87
151
|
}
|
|
@@ -11,7 +11,7 @@ export type DangerZoneProps = {
|
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Renders the danger zone heading and {@link DeleteUser}.
|
|
14
|
-
*
|
|
14
|
+
* Registered as a `securityCard` by `deleteUserPlugin()`; gate by registering the plugin.
|
|
15
15
|
*/
|
|
16
16
|
export function DangerZone({
|
|
17
17
|
className,
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { authQueryKeys } from "@better-auth-ui/core"
|
|
2
|
+
import {
|
|
3
|
+
useAuth,
|
|
4
|
+
useAuthPlugin,
|
|
5
|
+
useDeleteUser,
|
|
6
|
+
useListAccounts
|
|
7
|
+
} from "@better-auth-ui/react"
|
|
2
8
|
import { TriangleExclamation } from "@gravity-ui/icons"
|
|
3
9
|
import {
|
|
4
10
|
AlertDialog,
|
|
@@ -14,8 +20,11 @@ import {
|
|
|
14
20
|
TextField,
|
|
15
21
|
toast
|
|
16
22
|
} from "@heroui/react"
|
|
23
|
+
import { useQueryClient } from "@tanstack/react-query"
|
|
17
24
|
import { type SyntheticEvent, useState } from "react"
|
|
18
25
|
|
|
26
|
+
import { deleteUserPlugin } from "../../../lib/auth/delete-user-plugin"
|
|
27
|
+
|
|
19
28
|
export type DeleteUserProps = {
|
|
20
29
|
className?: string
|
|
21
30
|
variant?: CardProps["variant"]
|
|
@@ -29,15 +38,16 @@ export function DeleteUser({
|
|
|
29
38
|
variant,
|
|
30
39
|
...props
|
|
31
40
|
}: DeleteUserProps & Omit<CardProps, "children">) {
|
|
41
|
+
const { authClient, basePaths, localization, navigate, viewPaths } = useAuth()
|
|
42
|
+
|
|
32
43
|
const {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
} = useAuth()
|
|
44
|
+
localization: deleteUserLocalization,
|
|
45
|
+
sendDeleteAccountVerification
|
|
46
|
+
} = useAuthPlugin(deleteUserPlugin)
|
|
47
|
+
|
|
48
|
+
const { data: accounts } = useListAccounts(authClient)
|
|
39
49
|
|
|
40
|
-
const
|
|
50
|
+
const queryClient = useQueryClient()
|
|
41
51
|
|
|
42
52
|
const [confirmOpen, setConfirmOpen] = useState(false)
|
|
43
53
|
const [password, setPassword] = useState("")
|
|
@@ -45,10 +55,9 @@ export function DeleteUser({
|
|
|
45
55
|
const hasCredentialAccount = accounts?.some(
|
|
46
56
|
(account) => account.providerId === "credential"
|
|
47
57
|
)
|
|
48
|
-
const needsPassword =
|
|
49
|
-
!deleteUserConfig?.sendDeleteAccountVerification && hasCredentialAccount
|
|
58
|
+
const needsPassword = !sendDeleteAccountVerification && hasCredentialAccount
|
|
50
59
|
|
|
51
|
-
const { mutate: deleteUser, isPending } = useDeleteUser()
|
|
60
|
+
const { mutate: deleteUser, isPending } = useDeleteUser(authClient)
|
|
52
61
|
|
|
53
62
|
const handleDialogOpenChange = (open: boolean) => {
|
|
54
63
|
setConfirmOpen(open)
|
|
@@ -67,10 +76,11 @@ export function DeleteUser({
|
|
|
67
76
|
setConfirmOpen(false)
|
|
68
77
|
setPassword("")
|
|
69
78
|
|
|
70
|
-
if (
|
|
71
|
-
toast.success(
|
|
79
|
+
if (sendDeleteAccountVerification) {
|
|
80
|
+
toast.success(deleteUserLocalization.deleteUserVerificationSent)
|
|
72
81
|
} else {
|
|
73
|
-
toast.success(
|
|
82
|
+
toast.success(deleteUserLocalization.deleteUserSuccess)
|
|
83
|
+
queryClient.removeQueries({ queryKey: authQueryKeys.all })
|
|
74
84
|
navigate({
|
|
75
85
|
to: `${basePaths.auth}/${viewPaths.auth.signIn}`,
|
|
76
86
|
replace: true
|
|
@@ -89,11 +99,11 @@ export function DeleteUser({
|
|
|
89
99
|
<Card.Content className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
|
|
90
100
|
<div>
|
|
91
101
|
<p className="text-sm font-medium leading-tight">
|
|
92
|
-
{
|
|
102
|
+
{deleteUserLocalization.deleteUser}
|
|
93
103
|
</p>
|
|
94
104
|
|
|
95
105
|
<p className="text-muted text-xs mt-0.5">
|
|
96
|
-
{
|
|
106
|
+
{deleteUserLocalization.deleteUserDescription}
|
|
97
107
|
</p>
|
|
98
108
|
</div>
|
|
99
109
|
|
|
@@ -104,7 +114,7 @@ export function DeleteUser({
|
|
|
104
114
|
variant="danger"
|
|
105
115
|
onPress={() => setConfirmOpen(true)}
|
|
106
116
|
>
|
|
107
|
-
{
|
|
117
|
+
{deleteUserLocalization.deleteUser}
|
|
108
118
|
</Button>
|
|
109
119
|
|
|
110
120
|
<AlertDialog.Backdrop
|
|
@@ -122,13 +132,13 @@ export function DeleteUser({
|
|
|
122
132
|
</AlertDialog.Icon>
|
|
123
133
|
|
|
124
134
|
<AlertDialog.Heading>
|
|
125
|
-
{
|
|
135
|
+
{deleteUserLocalization.deleteUser}
|
|
126
136
|
</AlertDialog.Heading>
|
|
127
137
|
</AlertDialog.Header>
|
|
128
138
|
|
|
129
139
|
<AlertDialog.Body className="overflow-visible">
|
|
130
140
|
<p className="text-muted text-sm">
|
|
131
|
-
{
|
|
141
|
+
{deleteUserLocalization.deleteUserDescription}
|
|
132
142
|
</p>
|
|
133
143
|
|
|
134
144
|
{needsPassword && (
|
|
@@ -170,7 +180,7 @@ export function DeleteUser({
|
|
|
170
180
|
>
|
|
171
181
|
{isPending && <Spinner color="current" size="sm" />}
|
|
172
182
|
|
|
173
|
-
{
|
|
183
|
+
{deleteUserLocalization.deleteUser}
|
|
174
184
|
</Button>
|
|
175
185
|
</AlertDialog.Footer>
|
|
176
186
|
</Form>
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EmailChangedEmail as EmailChangedEmailPrimitive,
|
|
3
3
|
type EmailChangedEmailProps
|
|
4
|
-
} from "@better-auth-ui/react"
|
|
4
|
+
} from "@better-auth-ui/react/email"
|
|
5
5
|
import { cn } from "@heroui/react"
|
|
6
6
|
|
|
7
|
-
export type { EmailChangedEmailProps } from "@better-auth-ui/react"
|
|
7
|
+
export type { EmailChangedEmailProps } from "@better-auth-ui/react/email"
|
|
8
8
|
|
|
9
9
|
export function EmailChangedEmail({
|
|
10
10
|
colors,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EmailVerificationEmail as EmailVerificationEmailPrimitive,
|
|
3
3
|
type EmailVerificationEmailProps
|
|
4
|
-
} from "@better-auth-ui/react"
|
|
4
|
+
} from "@better-auth-ui/react/email"
|
|
5
5
|
import { cn } from "@heroui/react"
|
|
6
6
|
|
|
7
|
-
export type { EmailVerificationEmailProps } from "@better-auth-ui/react"
|
|
7
|
+
export type { EmailVerificationEmailProps } from "@better-auth-ui/react/email"
|
|
8
8
|
|
|
9
9
|
export function EmailVerificationEmail({
|
|
10
10
|
colors,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MagicLinkEmail as MagicLinkEmailPrimitive,
|
|
3
3
|
type MagicLinkEmailProps
|
|
4
|
-
} from "@better-auth-ui/react"
|
|
4
|
+
} from "@better-auth-ui/react/email"
|
|
5
5
|
import { cn } from "@heroui/react"
|
|
6
6
|
|
|
7
|
-
export type { MagicLinkEmailProps } from "@better-auth-ui/react"
|
|
7
|
+
export type { MagicLinkEmailProps } from "@better-auth-ui/react/email"
|
|
8
8
|
|
|
9
9
|
export function MagicLinkEmail({
|
|
10
10
|
colors,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
NewDeviceEmail as NewDeviceEmailPrimitive,
|
|
3
3
|
type NewDeviceEmailProps
|
|
4
|
-
} from "@better-auth-ui/react"
|
|
4
|
+
} from "@better-auth-ui/react/email"
|
|
5
5
|
import { cn } from "@heroui/react"
|
|
6
6
|
|
|
7
|
-
export type { NewDeviceEmailProps } from "@better-auth-ui/react"
|
|
7
|
+
export type { NewDeviceEmailProps } from "@better-auth-ui/react/email"
|
|
8
8
|
|
|
9
9
|
export function NewDeviceEmail({
|
|
10
10
|
colors,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
OtpEmail as OtpEmailPrimitive,
|
|
3
3
|
type OtpEmailProps
|
|
4
|
-
} from "@better-auth-ui/react"
|
|
4
|
+
} from "@better-auth-ui/react/email"
|
|
5
5
|
import { cn } from "@heroui/react"
|
|
6
6
|
|
|
7
|
-
export type { OtpEmailProps } from "@better-auth-ui/react"
|
|
7
|
+
export type { OtpEmailProps } from "@better-auth-ui/react/email"
|
|
8
8
|
|
|
9
9
|
export function OtpEmail({ colors, classNames, ...props }: OtpEmailProps) {
|
|
10
10
|
return (
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PasswordChangedEmail as PasswordChangedEmailPrimitive,
|
|
3
3
|
type PasswordChangedEmailProps
|
|
4
|
-
} from "@better-auth-ui/react"
|
|
4
|
+
} from "@better-auth-ui/react/email"
|
|
5
5
|
import { cn } from "@heroui/react"
|
|
6
6
|
|
|
7
|
-
export type { PasswordChangedEmailProps } from "@better-auth-ui/react"
|
|
7
|
+
export type { PasswordChangedEmailProps } from "@better-auth-ui/react/email"
|
|
8
8
|
|
|
9
9
|
export function PasswordChangedEmail({
|
|
10
10
|
colors,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ResetPasswordEmail as ResetPasswordEmailPrimitive,
|
|
3
3
|
type ResetPasswordEmailProps
|
|
4
|
-
} from "@better-auth-ui/react"
|
|
4
|
+
} from "@better-auth-ui/react/email"
|
|
5
5
|
import { cn } from "@heroui/react"
|
|
6
6
|
|
|
7
|
-
export type { ResetPasswordEmailProps } from "@better-auth-ui/react"
|
|
7
|
+
export type { ResetPasswordEmailProps } from "@better-auth-ui/react/email"
|
|
8
8
|
|
|
9
9
|
export function ResetPasswordEmail({
|
|
10
10
|
colors,
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
useAuth,
|
|
3
|
+
useFetchOptions,
|
|
4
|
+
useRequestPasswordReset
|
|
5
|
+
} from "@better-auth-ui/react"
|
|
2
6
|
import {
|
|
3
7
|
Button,
|
|
4
8
|
Card,
|
|
@@ -25,7 +29,7 @@ export type ForgotPasswordProps = {
|
|
|
25
29
|
* Render a card-based "Forgot Password" form that sends a password-reset email.
|
|
26
30
|
*
|
|
27
31
|
* The form displays an email input, submit button, and a link back to sign-in.
|
|
28
|
-
* Toasts are displayed on success or error via the `
|
|
32
|
+
* Toasts are displayed on success or error via the `useRequestPasswordReset` hook.
|
|
29
33
|
*
|
|
30
34
|
* @param className - Optional additional CSS class names applied to the card
|
|
31
35
|
* @returns The forgot-password form UI as a JSX element
|
|
@@ -35,25 +39,42 @@ export function ForgotPassword({
|
|
|
35
39
|
variant,
|
|
36
40
|
...props
|
|
37
41
|
}: ForgotPasswordProps & Omit<CardProps, "children">) {
|
|
38
|
-
const { basePaths, localization, viewPaths, navigate } =
|
|
42
|
+
const { authClient, basePaths, localization, viewPaths, navigate, plugins } =
|
|
43
|
+
useAuth()
|
|
44
|
+
|
|
45
|
+
const { fetchOptions, resetFetchOptions } = useFetchOptions()
|
|
39
46
|
|
|
40
|
-
const { mutate: requestPasswordReset, isPending } = useRequestPasswordReset(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
47
|
+
const { mutate: requestPasswordReset, isPending } = useRequestPasswordReset(
|
|
48
|
+
authClient,
|
|
49
|
+
{
|
|
50
|
+
onError: (error) => {
|
|
51
|
+
toast.danger(error.error?.message || error.message)
|
|
52
|
+
resetFetchOptions()
|
|
53
|
+
},
|
|
54
|
+
onSuccess: () => {
|
|
55
|
+
toast.success(localization.auth.passwordResetEmailSent)
|
|
56
|
+
navigate({ to: `${basePaths.auth}/${viewPaths.auth.signIn}` })
|
|
57
|
+
}
|
|
44
58
|
}
|
|
45
|
-
|
|
59
|
+
)
|
|
46
60
|
|
|
47
61
|
function handleSubmit(e: SyntheticEvent<HTMLFormElement>) {
|
|
48
62
|
e.preventDefault()
|
|
49
63
|
|
|
50
64
|
const formData = new FormData(e.currentTarget)
|
|
51
|
-
requestPasswordReset({
|
|
65
|
+
requestPasswordReset({
|
|
66
|
+
email: formData.get("email") as string,
|
|
67
|
+
fetchOptions
|
|
68
|
+
})
|
|
52
69
|
}
|
|
53
70
|
|
|
71
|
+
const Captcha = plugins.find(
|
|
72
|
+
(plugin) => plugin.captchaComponent
|
|
73
|
+
)?.captchaComponent
|
|
74
|
+
|
|
54
75
|
return (
|
|
55
76
|
<Card
|
|
56
|
-
className={cn("w-full max-w-sm
|
|
77
|
+
className={cn("w-full max-w-sm gap-4 md:p-6", className)}
|
|
57
78
|
variant={variant}
|
|
58
79
|
{...props}
|
|
59
80
|
>
|
|
@@ -63,7 +84,7 @@ export function ForgotPassword({
|
|
|
63
84
|
</Card.Title>
|
|
64
85
|
</Card.Header>
|
|
65
86
|
|
|
66
|
-
<Card.Content>
|
|
87
|
+
<Card.Content className="gap-4">
|
|
67
88
|
<Form onSubmit={handleSubmit} className="flex flex-col gap-4">
|
|
68
89
|
<TextField
|
|
69
90
|
name="email"
|
|
@@ -82,20 +103,24 @@ export function ForgotPassword({
|
|
|
82
103
|
<FieldError />
|
|
83
104
|
</TextField>
|
|
84
105
|
|
|
85
|
-
<
|
|
86
|
-
|
|
106
|
+
{Captcha && <div className="flex justify-center">{Captcha}</div>}
|
|
107
|
+
|
|
108
|
+
<div className="flex flex-col gap-3">
|
|
109
|
+
<Button type="submit" className="w-full" isPending={isPending}>
|
|
110
|
+
{isPending && <Spinner color="current" size="sm" />}
|
|
87
111
|
|
|
88
|
-
|
|
89
|
-
|
|
112
|
+
{localization.auth.sendResetLink}
|
|
113
|
+
</Button>
|
|
114
|
+
</div>
|
|
90
115
|
</Form>
|
|
91
116
|
</Card.Content>
|
|
92
117
|
|
|
93
|
-
<Card.Footer className="flex-col">
|
|
118
|
+
<Card.Footer className="flex-col gap-3">
|
|
94
119
|
<Description className="text-sm">
|
|
95
120
|
{localization.auth.rememberYourPassword}{" "}
|
|
96
121
|
<Link
|
|
97
122
|
href={`${basePaths.auth}/${viewPaths.auth.signIn}`}
|
|
98
|
-
className="text-accent
|
|
123
|
+
className="text-accent no-underline hover:underline decoration-accent-hover"
|
|
99
124
|
>
|
|
100
125
|
{localization.auth.signIn}
|
|
101
126
|
</Link>
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type AuthView, authMutationKeys } from "@better-auth-ui/core"
|
|
2
|
+
import { useAuth, useAuthPlugin } from "@better-auth-ui/react"
|
|
3
|
+
import { Envelope, Lock } from "@gravity-ui/icons"
|
|
4
|
+
import { cn, Link } from "@heroui/react"
|
|
5
|
+
import { buttonVariants } from "@heroui/styles"
|
|
6
|
+
import { useIsMutating } from "@tanstack/react-query"
|
|
7
|
+
|
|
8
|
+
import { magicLinkPlugin } from "../../../lib/auth/magic-link-plugin"
|
|
9
|
+
|
|
10
|
+
export type MagicLinkButtonProps = {
|
|
11
|
+
/** @remarks `AuthView` */
|
|
12
|
+
view?: AuthView
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Toggle button between the password sign-in and magic-link routes.
|
|
17
|
+
*
|
|
18
|
+
* @param view - Current auth view. On `"magicLink"` this links back to password sign-in.
|
|
19
|
+
*/
|
|
20
|
+
export function MagicLinkButton({ view }: MagicLinkButtonProps) {
|
|
21
|
+
const { basePaths, emailAndPassword, viewPaths, localization } = useAuth()
|
|
22
|
+
const signInMutating = useIsMutating({
|
|
23
|
+
mutationKey: authMutationKeys.signIn.all
|
|
24
|
+
})
|
|
25
|
+
const signUpMutating = useIsMutating({
|
|
26
|
+
mutationKey: authMutationKeys.signUp.all
|
|
27
|
+
})
|
|
28
|
+
const isPending = signInMutating + signUpMutating > 0
|
|
29
|
+
|
|
30
|
+
const { localization: magicLinkLocalization, viewPaths: magicLinkViewPaths } =
|
|
31
|
+
useAuthPlugin(magicLinkPlugin)
|
|
32
|
+
|
|
33
|
+
const isMagicLinkView = view === "magicLink"
|
|
34
|
+
|
|
35
|
+
// On the magic-link view this button switches back to password sign-in.
|
|
36
|
+
// With password auth disabled there's nowhere to switch to, so hide it.
|
|
37
|
+
// (Other views — e.g. a phone-number plugin's surface — still get a
|
|
38
|
+
// "Continue with Magic Link" link.)
|
|
39
|
+
if (isMagicLinkView && !emailAndPassword?.enabled) return null
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<Link
|
|
43
|
+
href={`${basePaths.auth}/${isMagicLinkView ? viewPaths.auth.signIn : magicLinkViewPaths.auth.magicLink}`}
|
|
44
|
+
isDisabled={isPending}
|
|
45
|
+
className={cn(
|
|
46
|
+
buttonVariants({ variant: "tertiary" }),
|
|
47
|
+
"w-full gap-2",
|
|
48
|
+
isPending && "status-disabled"
|
|
49
|
+
)}
|
|
50
|
+
>
|
|
51
|
+
{isMagicLinkView ? <Lock /> : <Envelope />}
|
|
52
|
+
|
|
53
|
+
{localization.auth.continueWith.replace(
|
|
54
|
+
"{{provider}}",
|
|
55
|
+
isMagicLinkView
|
|
56
|
+
? localization.auth.password
|
|
57
|
+
: magicLinkLocalization.magicLink
|
|
58
|
+
)}
|
|
59
|
+
</Link>
|
|
60
|
+
)
|
|
61
|
+
}
|