@better-auth-ui/heroui 1.6.2 → 1.6.4
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-provider.js +12 -11
- 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 +3 -4
- package/dist/components/{settings/security → auth/delete-user}/danger-zone.js +1 -1
- package/dist/components/{settings/security → auth/delete-user}/delete-user.d.ts +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/error-toaster.d.ts +1 -0
- package/dist/components/auth/error-toaster.js +17 -0
- package/dist/components/auth/forgot-password.d.ts +2 -2
- package/dist/components/auth/forgot-password.js +42 -42
- 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/{settings/account → auth/multi-session}/manage-accounts.d.ts +1 -1
- 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/{settings/security → auth/passkey}/passkeys.d.ts +1 -1
- package/dist/components/auth/passkey/passkeys.js +106 -0
- package/dist/components/auth/provider-button.d.ts +13 -0
- package/dist/components/auth/provider-button.js +25 -0
- package/dist/components/auth/provider-buttons.d.ts +3 -10
- package/dist/components/auth/provider-buttons.js +14 -22
- package/dist/components/auth/reset-password.d.ts +1 -1
- package/dist/components/auth/reset-password.js +110 -110
- 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.d.ts +1 -1
- package/dist/components/{settings → auth/settings}/account/change-email.js +17 -20
- package/dist/components/{settings → auth/settings}/account/user-profile.d.ts +3 -4
- 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.d.ts +1 -1
- package/dist/components/auth/settings/security/active-sessions.js +34 -0
- package/dist/components/{settings → auth/settings}/security/change-password.d.ts +1 -1
- 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.d.ts +1 -1
- package/dist/components/auth/settings/security/linked-accounts.js +45 -0
- 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.d.ts +1 -1
- package/dist/components/auth/sign-in.js +64 -100
- package/dist/components/auth/sign-out.js +11 -11
- package/dist/components/auth/sign-up.d.ts +1 -1
- package/dist/components/auth/sign-up.js +123 -157
- 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 +142 -0
- package/dist/components/auth/username/username-field.d.ts +8 -0
- package/dist/components/auth/username/username-field.js +51 -0
- package/dist/email.d.ts +7 -0
- package/dist/email.js +9 -0
- package/dist/index.d.ts +13 -27
- package/dist/index.js +22 -36
- 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 +22 -22
- package/src/components/auth/additional-field.tsx +554 -0
- package/src/components/auth/auth-provider.tsx +8 -5
- package/src/components/auth/auth.tsx +100 -36
- package/src/components/{settings/security → auth/delete-user}/danger-zone.tsx +3 -10
- package/src/components/{settings/security → auth/delete-user}/delete-user.tsx +31 -24
- 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/error-toaster.tsx +25 -0
- package/src/components/auth/forgot-password.tsx +15 -13
- package/src/components/auth/magic-link/magic-link-button.tsx +61 -0
- package/src/components/auth/{magic-link.tsx → magic-link/magic-link.tsx} +52 -57
- package/src/components/{settings/account → auth/multi-session}/manage-account.tsx +15 -15
- package/src/components/{settings/account → auth/multi-session}/manage-accounts.tsx +16 -12
- package/src/components/{user/switch-account-menu.tsx → auth/multi-session/switch-account-submenu-content.tsx} +19 -17
- package/src/components/{user/switch-account-item.tsx → auth/multi-session/switch-account-submenu-item.tsx} +18 -8
- 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 +21 -9
- package/src/components/auth/passkey/passkeys.tsx +196 -0
- package/src/components/auth/provider-button.tsx +65 -0
- package/src/components/auth/provider-buttons.tsx +23 -45
- package/src/components/auth/reset-password.tsx +14 -9
- package/src/components/{settings → auth/settings}/account/account-settings.tsx +15 -13
- package/src/components/{settings → auth/settings}/account/change-avatar.tsx +4 -5
- package/src/components/{settings → auth/settings}/account/change-email.tsx +5 -6
- package/src/components/auth/settings/account/user-profile.tsx +171 -0
- package/src/components/{settings → auth/settings}/security/active-session.tsx +8 -6
- package/src/components/{settings → auth/settings}/security/active-sessions.tsx +5 -10
- package/src/components/{settings → auth/settings}/security/change-password.tsx +22 -14
- package/src/components/{settings → auth/settings}/security/linked-account.tsx +10 -16
- package/src/components/{settings → auth/settings}/security/linked-accounts.tsx +4 -9
- 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 +39 -80
- package/src/components/auth/sign-out.tsx +2 -2
- package/src/components/auth/sign-up.tsx +110 -147
- package/src/components/{settings/account → auth/theme}/appearance.tsx +18 -25
- 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 +283 -0
- package/src/components/auth/username/username-field.tsx +122 -0
- package/src/email.ts +9 -0
- package/src/index.tsx +13 -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 -111
- package/dist/components/auth/passkey-button.d.ts +0 -4
- package/dist/components/auth/passkey-button.js +0 -24
- 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 -51
- package/dist/components/settings/account/manage-accounts.js +0 -33
- package/dist/components/settings/account/user-profile.js +0 -106
- package/dist/components/settings/security/active-session.js +0 -62
- package/dist/components/settings/security/active-sessions.js +0 -34
- package/dist/components/settings/security/change-password.js +0 -192
- package/dist/components/settings/security/delete-user.js +0 -97
- package/dist/components/settings/security/linked-account.js +0 -62
- package/dist/components/settings/security/linked-accounts.js +0 -45
- 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 -36
- package/src/components/settings/account/user-profile.tsx +0 -218
- package/src/components/settings/security/passkeys.tsx +0 -104
- package/src/core.ts +0 -1
- package/src/react-exports.ts +0 -1
- /package/dist/components/{settings/security → auth/passkey}/passkey.d.ts +0 -0
- /package/dist/components/{settings → auth/settings}/account/change-avatar.d.ts +0 -0
- /package/dist/components/{settings → auth/settings}/security/active-session.d.ts +0 -0
- /package/dist/components/{settings → auth/settings}/security/linked-account.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
|
*
|
|
@@ -35,53 +50,102 @@ export function Auth({
|
|
|
35
50
|
socialPosition,
|
|
36
51
|
view,
|
|
37
52
|
...props
|
|
38
|
-
}: AuthProps & CardProps) {
|
|
39
|
-
const { viewPaths } =
|
|
53
|
+
}: AuthProps & Omit<CardProps, "children">) {
|
|
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
|
}
|
|
@@ -1,23 +1,16 @@
|
|
|
1
1
|
import { useAuth } from "@better-auth-ui/react"
|
|
2
2
|
import { type CardProps, cn } from "@heroui/react"
|
|
3
3
|
import type { ComponentProps } from "react"
|
|
4
|
-
|
|
5
4
|
import { DeleteUser } from "./delete-user"
|
|
6
|
-
|
|
7
|
-
export type DangerZoneProps = {
|
|
8
|
-
className?: string
|
|
5
|
+
export type DangerZoneProps = Omit<ComponentProps<"div">, "children"> & {
|
|
9
6
|
variant?: CardProps["variant"]
|
|
10
7
|
}
|
|
11
8
|
|
|
12
9
|
/**
|
|
13
10
|
* Renders the danger zone heading and {@link DeleteUser}.
|
|
14
|
-
*
|
|
11
|
+
* Registered as a `securityCard` by `deleteUserPlugin()`; gate by registering the plugin.
|
|
15
12
|
*/
|
|
16
|
-
export function DangerZone({
|
|
17
|
-
className,
|
|
18
|
-
variant,
|
|
19
|
-
...props
|
|
20
|
-
}: DangerZoneProps & ComponentProps<"div">) {
|
|
13
|
+
export function DangerZone({ className, variant, ...props }: DangerZoneProps) {
|
|
21
14
|
const { localization } = useAuth()
|
|
22
15
|
|
|
23
16
|
return (
|
|
@@ -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"]
|
|
@@ -28,16 +37,17 @@ export function DeleteUser({
|
|
|
28
37
|
className,
|
|
29
38
|
variant,
|
|
30
39
|
...props
|
|
31
|
-
}: DeleteUserProps & CardProps) {
|
|
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,18 +76,16 @@ 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
|
|
77
87
|
})
|
|
78
88
|
}
|
|
79
|
-
},
|
|
80
|
-
onError: (error) => {
|
|
81
|
-
toast.danger(error.error?.message || error.message)
|
|
82
89
|
}
|
|
83
90
|
})
|
|
84
91
|
}
|
|
@@ -92,11 +99,11 @@ export function DeleteUser({
|
|
|
92
99
|
<Card.Content className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
|
|
93
100
|
<div>
|
|
94
101
|
<p className="text-sm font-medium leading-tight">
|
|
95
|
-
{
|
|
102
|
+
{deleteUserLocalization.deleteUser}
|
|
96
103
|
</p>
|
|
97
104
|
|
|
98
105
|
<p className="text-muted text-xs mt-0.5">
|
|
99
|
-
{
|
|
106
|
+
{deleteUserLocalization.deleteUserDescription}
|
|
100
107
|
</p>
|
|
101
108
|
</div>
|
|
102
109
|
|
|
@@ -107,7 +114,7 @@ export function DeleteUser({
|
|
|
107
114
|
variant="danger"
|
|
108
115
|
onPress={() => setConfirmOpen(true)}
|
|
109
116
|
>
|
|
110
|
-
{
|
|
117
|
+
{deleteUserLocalization.deleteUser}
|
|
111
118
|
</Button>
|
|
112
119
|
|
|
113
120
|
<AlertDialog.Backdrop
|
|
@@ -125,13 +132,13 @@ export function DeleteUser({
|
|
|
125
132
|
</AlertDialog.Icon>
|
|
126
133
|
|
|
127
134
|
<AlertDialog.Heading>
|
|
128
|
-
{
|
|
135
|
+
{deleteUserLocalization.deleteUser}
|
|
129
136
|
</AlertDialog.Heading>
|
|
130
137
|
</AlertDialog.Header>
|
|
131
138
|
|
|
132
139
|
<AlertDialog.Body className="overflow-visible">
|
|
133
140
|
<p className="text-muted text-sm">
|
|
134
|
-
{
|
|
141
|
+
{deleteUserLocalization.deleteUserDescription}
|
|
135
142
|
</p>
|
|
136
143
|
|
|
137
144
|
{needsPassword && (
|
|
@@ -173,7 +180,7 @@ export function DeleteUser({
|
|
|
173
180
|
>
|
|
174
181
|
{isPending && <Spinner color="current" size="sm" />}
|
|
175
182
|
|
|
176
|
-
{
|
|
183
|
+
{deleteUserLocalization.deleteUser}
|
|
177
184
|
</Button>
|
|
178
185
|
</AlertDialog.Footer>
|
|
179
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,
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { toast } from "@heroui/react"
|
|
2
|
+
import { useQueryClient } from "@tanstack/react-query"
|
|
3
|
+
import type { BetterFetchError } from "better-auth/react"
|
|
4
|
+
import { useEffect } from "react"
|
|
5
|
+
|
|
6
|
+
export function ErrorToaster() {
|
|
7
|
+
const queryClient = useQueryClient()
|
|
8
|
+
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
queryClient.getQueryCache().config.onError = (error) => {
|
|
11
|
+
const err = error as BetterFetchError
|
|
12
|
+
if (err?.error) toast.danger(err.error.message)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
queryClient.setMutationDefaults([], {
|
|
16
|
+
onError: (error) => {
|
|
17
|
+
toast.danger(
|
|
18
|
+
(error as BetterFetchError)?.error?.message || error.message
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
})
|
|
22
|
+
}, [queryClient])
|
|
23
|
+
|
|
24
|
+
return null
|
|
25
|
+
}
|
|
@@ -25,7 +25,7 @@ export type ForgotPasswordProps = {
|
|
|
25
25
|
* Render a card-based "Forgot Password" form that sends a password-reset email.
|
|
26
26
|
*
|
|
27
27
|
* 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 `
|
|
28
|
+
* Toasts are displayed on success or error via the `useRequestPasswordReset` hook.
|
|
29
29
|
*
|
|
30
30
|
* @param className - Optional additional CSS class names applied to the card
|
|
31
31
|
* @returns The forgot-password form UI as a JSX element
|
|
@@ -34,16 +34,18 @@ export function ForgotPassword({
|
|
|
34
34
|
className,
|
|
35
35
|
variant,
|
|
36
36
|
...props
|
|
37
|
-
}: ForgotPasswordProps & CardProps) {
|
|
38
|
-
const { basePaths, localization, viewPaths, navigate } = useAuth()
|
|
37
|
+
}: ForgotPasswordProps & Omit<CardProps, "children">) {
|
|
38
|
+
const { authClient, basePaths, localization, viewPaths, navigate } = useAuth()
|
|
39
39
|
|
|
40
|
-
const { mutate: requestPasswordReset, isPending } = useRequestPasswordReset(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
const { mutate: requestPasswordReset, isPending } = useRequestPasswordReset(
|
|
41
|
+
authClient,
|
|
42
|
+
{
|
|
43
|
+
onSuccess: () => {
|
|
44
|
+
toast.success(localization.auth.passwordResetEmailSent)
|
|
45
|
+
navigate({ to: `${basePaths.auth}/${viewPaths.auth.signIn}` })
|
|
46
|
+
}
|
|
45
47
|
}
|
|
46
|
-
|
|
48
|
+
)
|
|
47
49
|
|
|
48
50
|
function handleSubmit(e: SyntheticEvent<HTMLFormElement>) {
|
|
49
51
|
e.preventDefault()
|
|
@@ -54,7 +56,7 @@ export function ForgotPassword({
|
|
|
54
56
|
|
|
55
57
|
return (
|
|
56
58
|
<Card
|
|
57
|
-
className={cn("w-full max-w-sm
|
|
59
|
+
className={cn("w-full max-w-sm gap-4 md:p-6", className)}
|
|
58
60
|
variant={variant}
|
|
59
61
|
{...props}
|
|
60
62
|
>
|
|
@@ -64,7 +66,7 @@ export function ForgotPassword({
|
|
|
64
66
|
</Card.Title>
|
|
65
67
|
</Card.Header>
|
|
66
68
|
|
|
67
|
-
<Card.Content>
|
|
69
|
+
<Card.Content className="gap-4">
|
|
68
70
|
<Form onSubmit={handleSubmit} className="flex flex-col gap-4">
|
|
69
71
|
<TextField
|
|
70
72
|
name="email"
|
|
@@ -91,12 +93,12 @@ export function ForgotPassword({
|
|
|
91
93
|
</Form>
|
|
92
94
|
</Card.Content>
|
|
93
95
|
|
|
94
|
-
<Card.Footer className="flex-col">
|
|
96
|
+
<Card.Footer className="flex-col gap-3">
|
|
95
97
|
<Description className="text-sm">
|
|
96
98
|
{localization.auth.rememberYourPassword}{" "}
|
|
97
99
|
<Link
|
|
98
100
|
href={`${basePaths.auth}/${viewPaths.auth.signIn}`}
|
|
99
|
-
className="text-accent
|
|
101
|
+
className="text-accent no-underline hover:underline decoration-accent-hover"
|
|
100
102
|
>
|
|
101
103
|
{localization.auth.signIn}
|
|
102
104
|
</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
|
+
}
|