@better-auth-ui/heroui 1.6.2 → 1.6.3
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.js +12 -11
- package/dist/components/auth/auth.d.ts +1 -1
- 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 +1 -1
- package/dist/components/auth/forgot-password.js +3 -6
- package/dist/components/auth/magic-link.d.ts +1 -1
- package/dist/components/auth/magic-link.js +52 -64
- package/dist/components/auth/passkey-button.js +12 -15
- package/dist/components/auth/provider-button.d.ts +15 -0
- package/dist/components/auth/provider-button.js +29 -0
- package/dist/components/auth/provider-buttons.d.ts +4 -10
- package/dist/components/auth/provider-buttons.js +16 -23
- package/dist/components/auth/reset-password.d.ts +1 -1
- package/dist/components/auth/reset-password.js +3 -6
- package/dist/components/auth/sign-in.d.ts +1 -1
- package/dist/components/auth/sign-in.js +81 -93
- package/dist/components/auth/sign-up.d.ts +1 -1
- package/dist/components/auth/sign-up.js +99 -108
- package/dist/components/settings/account/appearance.d.ts +1 -1
- package/dist/components/settings/account/change-avatar.js +1 -1
- package/dist/components/settings/account/change-email.d.ts +1 -1
- package/dist/components/settings/account/change-email.js +1 -4
- package/dist/components/settings/account/manage-account.js +1 -4
- package/dist/components/settings/account/manage-accounts.d.ts +1 -1
- package/dist/components/settings/account/manage-accounts.js +16 -16
- package/dist/components/settings/account/user-profile.d.ts +1 -1
- package/dist/components/settings/account/user-profile.js +1 -4
- package/dist/components/settings/security/active-session.js +1 -4
- package/dist/components/settings/security/active-sessions.d.ts +1 -1
- package/dist/components/settings/security/active-sessions.js +17 -17
- package/dist/components/settings/security/change-password.d.ts +1 -1
- package/dist/components/settings/security/change-password.js +1 -4
- package/dist/components/settings/security/delete-user.d.ts +1 -1
- package/dist/components/settings/security/delete-user.js +6 -11
- package/dist/components/settings/security/linked-account.js +1 -7
- package/dist/components/settings/security/linked-accounts.d.ts +1 -1
- package/dist/components/settings/security/linked-accounts.js +18 -18
- package/dist/components/settings/security/passkey.js +19 -19
- package/dist/components/settings/security/passkeys.d.ts +1 -1
- package/dist/components/settings/security/passkeys.js +28 -28
- package/dist/components/user/switch-account-item.js +9 -9
- package/dist/components/user/switch-account-menu.js +16 -16
- package/dist/index.d.ts +1 -0
- package/dist/index.js +34 -33
- package/package.json +6 -4
- package/src/components/auth/auth-provider.tsx +4 -0
- package/src/components/auth/auth.tsx +1 -1
- package/src/components/auth/error-toaster.tsx +25 -0
- package/src/components/auth/forgot-password.tsx +1 -2
- package/src/components/auth/magic-link.tsx +3 -23
- package/src/components/auth/passkey-button.tsx +1 -2
- package/src/components/auth/provider-button.tsx +67 -0
- package/src/components/auth/provider-buttons.tsx +26 -43
- package/src/components/auth/reset-password.tsx +1 -2
- package/src/components/auth/sign-in.tsx +2 -20
- package/src/components/auth/sign-up.tsx +5 -20
- package/src/components/settings/account/appearance.tsx +1 -1
- package/src/components/settings/account/change-avatar.tsx +1 -3
- package/src/components/settings/account/change-email.tsx +2 -3
- package/src/components/settings/account/manage-account.tsx +1 -4
- package/src/components/settings/account/manage-accounts.tsx +3 -8
- package/src/components/settings/account/user-profile.tsx +1 -2
- package/src/components/settings/security/active-session.tsx +0 -1
- package/src/components/settings/security/active-sessions.tsx +3 -8
- package/src/components/settings/security/change-password.tsx +7 -4
- package/src/components/settings/security/delete-user.tsx +1 -4
- package/src/components/settings/security/linked-account.tsx +4 -14
- package/src/components/settings/security/linked-accounts.tsx +3 -8
- package/src/components/settings/security/passkey.tsx +2 -4
- package/src/components/settings/security/passkeys.tsx +4 -12
- package/src/components/user/switch-account-item.tsx +2 -4
- package/src/components/user/switch-account-menu.tsx +2 -7
- package/src/index.tsx +1 -0
package/dist/index.js
CHANGED
|
@@ -2,36 +2,37 @@
|
|
|
2
2
|
import { ForgotPassword as e } from "./components/auth/forgot-password.js";
|
|
3
3
|
import { MagicLinkButton as t } from "./components/auth/magic-link-button.js";
|
|
4
4
|
import { PasskeyButton as n } from "./components/auth/passkey-button.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
|
|
5
|
+
import { ProviderButton as r } from "./components/auth/provider-button.js";
|
|
6
|
+
import { ProviderButtons as i } from "./components/auth/provider-buttons.js";
|
|
7
|
+
import { MagicLink as a } from "./components/auth/magic-link.js";
|
|
8
|
+
import { ResetPassword as o } from "./components/auth/reset-password.js";
|
|
9
|
+
import { SignIn as s } from "./components/auth/sign-in.js";
|
|
10
|
+
import { SignOut as c } from "./components/auth/sign-out.js";
|
|
11
|
+
import { SignUp as l } from "./components/auth/sign-up.js";
|
|
12
|
+
import { Auth as u } from "./components/auth/auth.js";
|
|
13
|
+
import { AuthProvider as d } from "./components/auth/auth-provider.js";
|
|
14
|
+
import { EmailChangedEmail as f } from "./components/email/email-changed-email.js";
|
|
15
|
+
import { EmailVerificationEmail as p } from "./components/email/email-verification-email.js";
|
|
16
|
+
import { MagicLinkEmail as m } from "./components/email/magic-link-email.js";
|
|
17
|
+
import { NewDeviceEmail as h } from "./components/email/new-device-email.js";
|
|
18
|
+
import { OtpEmail as g } from "./components/email/otp-email.js";
|
|
19
|
+
import { PasswordChangedEmail as _ } from "./components/email/password-changed-email.js";
|
|
20
|
+
import { ResetPasswordEmail as v } from "./components/email/reset-password-email.js";
|
|
21
|
+
import { Appearance as y } from "./components/settings/account/appearance.js";
|
|
22
|
+
import { ChangeEmail as b } from "./components/settings/account/change-email.js";
|
|
23
|
+
import { UserAvatar as x } from "./components/user/user-avatar.js";
|
|
24
|
+
import { UserView as S } from "./components/user/user-view.js";
|
|
25
|
+
import { ManageAccount as C } from "./components/settings/account/manage-account.js";
|
|
26
|
+
import { ManageAccounts as w } from "./components/settings/account/manage-accounts.js";
|
|
27
|
+
import { UserProfile as T } from "./components/settings/account/user-profile.js";
|
|
28
|
+
import { AccountSettings as E } from "./components/settings/account/account-settings.js";
|
|
29
|
+
import { ActiveSessions as D } from "./components/settings/security/active-sessions.js";
|
|
30
|
+
import { ChangePassword as O } from "./components/settings/security/change-password.js";
|
|
31
|
+
import { DeleteUser as k } from "./components/settings/security/delete-user.js";
|
|
32
|
+
import { DangerZone as A } from "./components/settings/security/danger-zone.js";
|
|
33
|
+
import { LinkedAccounts as j } from "./components/settings/security/linked-accounts.js";
|
|
34
|
+
import { Passkeys as M } from "./components/settings/security/passkeys.js";
|
|
35
|
+
import { SecuritySettings as N } from "./components/settings/security/security-settings.js";
|
|
36
|
+
import { Settings as P } from "./components/settings/settings.js";
|
|
37
|
+
import { UserButton as F } from "./components/user/user-button.js";
|
|
38
|
+
export { E as AccountSettings, D as ActiveSessions, y as Appearance, u as Auth, d as AuthProvider, b as ChangeEmail, O as ChangePassword, A as DangerZone, k as DeleteUser, f as EmailChangedEmail, p as EmailVerificationEmail, e as ForgotPassword, j as LinkedAccounts, a as MagicLink, t as MagicLinkButton, m as MagicLinkEmail, C as ManageAccount, w as ManageAccounts, h as NewDeviceEmail, g as OtpEmail, n as PasskeyButton, M as Passkeys, _ as PasswordChangedEmail, r as ProviderButton, i as ProviderButtons, o as ResetPassword, v as ResetPasswordEmail, N as SecuritySettings, P as Settings, s as SignIn, c as SignOut, l as SignUp, x as UserAvatar, F as UserButton, T as UserProfile, S as UserView };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@better-auth-ui/heroui",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "vite build && bun styles",
|
|
@@ -31,18 +31,19 @@
|
|
|
31
31
|
"@gravity-ui/icons": "^2.18.0",
|
|
32
32
|
"@heroui/react": "^3.0.2",
|
|
33
33
|
"@heroui/styles": "^3.0.2",
|
|
34
|
-
"@tanstack/react-pacer": "^0.
|
|
34
|
+
"@tanstack/react-pacer": "^0.22.0",
|
|
35
|
+
"@tanstack/react-query": "^5.99.0",
|
|
35
36
|
"@testing-library/react": "^16.3.2",
|
|
36
37
|
"@testing-library/user-event": "^14.5.2",
|
|
37
38
|
"@types/react": "^19.2.14",
|
|
38
39
|
"@vitejs/plugin-react": "^6.0.1",
|
|
39
40
|
"@vitest/browser-playwright": "^4.1.4",
|
|
40
41
|
"better-auth": "^1.6.5",
|
|
42
|
+
"bowser": "^2.11.0",
|
|
41
43
|
"cpy-cli": "^7.0.0",
|
|
42
44
|
"playwright": "^1.59.1",
|
|
43
45
|
"react": "^19.2.5",
|
|
44
46
|
"react-dom": "^19.2.5",
|
|
45
|
-
"bowser": "^2.11.0",
|
|
46
47
|
"vitest": "^4.1.4"
|
|
47
48
|
},
|
|
48
49
|
"dependencies": {
|
|
@@ -53,7 +54,8 @@
|
|
|
53
54
|
"@gravity-ui/icons": ">=2.18.0",
|
|
54
55
|
"@heroui/react": ">=3.0.2",
|
|
55
56
|
"@heroui/styles": ">=3.0.2",
|
|
56
|
-
"@tanstack/react-pacer": ">=0.
|
|
57
|
+
"@tanstack/react-pacer": ">=0.22.0",
|
|
58
|
+
"@tanstack/react-query": ">=5.99.0",
|
|
57
59
|
"better-auth": ">=1.6.5",
|
|
58
60
|
"react": ">=19.2.5",
|
|
59
61
|
"react-dom": ">=19.2.5",
|
|
@@ -4,6 +4,8 @@ import {
|
|
|
4
4
|
} from "@better-auth-ui/react"
|
|
5
5
|
import { RouterProvider } from "@heroui/react"
|
|
6
6
|
|
|
7
|
+
import { ErrorToaster } from "./error-toaster"
|
|
8
|
+
|
|
7
9
|
export type AuthProviderProps = Omit<AuthProviderPropsPrimitive, "Link">
|
|
8
10
|
|
|
9
11
|
/**
|
|
@@ -21,6 +23,8 @@ export function AuthProvider({
|
|
|
21
23
|
<AuthProviderPrimitive navigate={navigate} {...config}>
|
|
22
24
|
<RouterProvider navigate={(path) => navigate({ to: path })}>
|
|
23
25
|
{children}
|
|
26
|
+
|
|
27
|
+
<ErrorToaster />
|
|
24
28
|
</RouterProvider>
|
|
25
29
|
</AuthProviderPrimitive>
|
|
26
30
|
)
|
|
@@ -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
|
+
}
|
|
@@ -34,11 +34,10 @@ export function ForgotPassword({
|
|
|
34
34
|
className,
|
|
35
35
|
variant,
|
|
36
36
|
...props
|
|
37
|
-
}: ForgotPasswordProps & CardProps) {
|
|
37
|
+
}: ForgotPasswordProps & Omit<CardProps, "children">) {
|
|
38
38
|
const { basePaths, localization, viewPaths, navigate } = useAuth()
|
|
39
39
|
|
|
40
40
|
const { mutate: requestPasswordReset, isPending } = useRequestPasswordReset({
|
|
41
|
-
onError: (error) => toast.danger(error.error?.message || error.message),
|
|
42
41
|
onSuccess: () => {
|
|
43
42
|
toast.success(localization.auth.passwordResetEmailSent)
|
|
44
43
|
navigate({ to: `${basePaths.auth}/${viewPaths.auth.signIn}` })
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
useAuth,
|
|
3
|
-
useSignInMagicLink,
|
|
4
|
-
useSignInSocial
|
|
5
|
-
} from "@better-auth-ui/react"
|
|
1
|
+
import { useAuth, useSignInMagicLink } from "@better-auth-ui/react"
|
|
6
2
|
import {
|
|
7
3
|
Button,
|
|
8
4
|
Card,
|
|
@@ -46,7 +42,7 @@ export function MagicLink({
|
|
|
46
42
|
socialPosition = "bottom",
|
|
47
43
|
variant,
|
|
48
44
|
...props
|
|
49
|
-
}: MagicLinkProps & CardProps) {
|
|
45
|
+
}: MagicLinkProps & Omit<CardProps, "children">) {
|
|
50
46
|
const {
|
|
51
47
|
basePaths,
|
|
52
48
|
baseURL,
|
|
@@ -61,27 +57,13 @@ export function MagicLink({
|
|
|
61
57
|
|
|
62
58
|
const { mutate: signInMagicLink, isPending: magicLinkPending } =
|
|
63
59
|
useSignInMagicLink({
|
|
64
|
-
onError: (error) => toast.danger(error.error?.message || error.message),
|
|
65
60
|
onSuccess: () => {
|
|
66
61
|
setEmail("")
|
|
67
62
|
toast.success(localization.auth.magicLinkSent)
|
|
68
63
|
}
|
|
69
64
|
})
|
|
70
65
|
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
const { mutate: signInSocial, isPending: socialPending } = useSignInSocial({
|
|
74
|
-
onError: (error) => toast.danger(error.error?.message || error.message),
|
|
75
|
-
onSuccess: () => {
|
|
76
|
-
setSocialRedirecting(true)
|
|
77
|
-
|
|
78
|
-
setTimeout(() => {
|
|
79
|
-
setSocialRedirecting(false)
|
|
80
|
-
}, 5000)
|
|
81
|
-
}
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
const isPending = magicLinkPending || socialPending || socialRedirecting
|
|
66
|
+
const isPending = magicLinkPending
|
|
85
67
|
|
|
86
68
|
const handleSubmit = (e: SyntheticEvent<HTMLFormElement>) => {
|
|
87
69
|
e.preventDefault()
|
|
@@ -108,7 +90,6 @@ export function MagicLink({
|
|
|
108
90
|
{!!socialProviders?.length && (
|
|
109
91
|
<ProviderButtons
|
|
110
92
|
socialLayout={socialLayout}
|
|
111
|
-
signInSocial={signInSocial}
|
|
112
93
|
isPending={isPending}
|
|
113
94
|
/>
|
|
114
95
|
)}
|
|
@@ -161,7 +142,6 @@ export function MagicLink({
|
|
|
161
142
|
{!!socialProviders?.length && (
|
|
162
143
|
<ProviderButtons
|
|
163
144
|
socialLayout={socialLayout}
|
|
164
|
-
signInSocial={signInSocial}
|
|
165
145
|
isPending={isPending}
|
|
166
146
|
/>
|
|
167
147
|
)}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useAuth, useSignInPasskey } from "@better-auth-ui/react"
|
|
2
2
|
import { Fingerprint } from "@gravity-ui/icons"
|
|
3
|
-
import { Button, Spinner
|
|
3
|
+
import { Button, Spinner } from "@heroui/react"
|
|
4
4
|
|
|
5
5
|
export type PasskeyButtonProps = {
|
|
6
6
|
isPending: boolean
|
|
@@ -11,7 +11,6 @@ export function PasskeyButton({ isPending }: PasskeyButtonProps) {
|
|
|
11
11
|
|
|
12
12
|
const { mutate: signInPasskey, isPending: passkeyPending } = useSignInPasskey(
|
|
13
13
|
{
|
|
14
|
-
onError: (error) => toast.danger(error.error?.message || error.message),
|
|
15
14
|
onSuccess: () => navigate({ to: redirectTo })
|
|
16
15
|
}
|
|
17
16
|
)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { getProviderName } from "@better-auth-ui/core"
|
|
2
|
+
import { providerIcons, useAuth, useSignInSocial } from "@better-auth-ui/react"
|
|
3
|
+
import { Button, type ButtonProps, Spinner } from "@heroui/react"
|
|
4
|
+
import type { SocialProvider } from "better-auth/social-providers"
|
|
5
|
+
import { useState } from "react"
|
|
6
|
+
|
|
7
|
+
export type ProviderButtonProps = {
|
|
8
|
+
provider: SocialProvider
|
|
9
|
+
label?: "continueWith" | "providerName" | "none"
|
|
10
|
+
isDisabled?: boolean
|
|
11
|
+
} & Omit<ButtonProps, "children" | "onPress" | "isPending">
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Render a single social provider sign-in button with its own mutation and pending state.
|
|
15
|
+
*
|
|
16
|
+
* @param provider - The social provider this button signs in with.
|
|
17
|
+
* @param label - Label style: `"continueWith"` (e.g. "Continue with Google"), `"providerName"` (e.g. "Google"), or `"none"` (icon only).
|
|
18
|
+
* @param isDisabled - External disabled state (e.g. a sibling provider is mid-redirect).
|
|
19
|
+
*/
|
|
20
|
+
export function ProviderButton({
|
|
21
|
+
provider,
|
|
22
|
+
label = "continueWith",
|
|
23
|
+
isDisabled,
|
|
24
|
+
variant = "tertiary",
|
|
25
|
+
...props
|
|
26
|
+
}: ProviderButtonProps) {
|
|
27
|
+
const { baseURL, localization, redirectTo } = useAuth()
|
|
28
|
+
|
|
29
|
+
const callbackURL = `${baseURL}${redirectTo}`
|
|
30
|
+
|
|
31
|
+
const [redirecting, setRedirecting] = useState(false)
|
|
32
|
+
|
|
33
|
+
const { mutate: signInSocial, isPending } = useSignInSocial({
|
|
34
|
+
onSuccess: () => {
|
|
35
|
+
setRedirecting(true)
|
|
36
|
+
|
|
37
|
+
setTimeout(() => {
|
|
38
|
+
setRedirecting(false)
|
|
39
|
+
}, 5000)
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
const ProviderIcon = providerIcons[provider]
|
|
44
|
+
|
|
45
|
+
const pending = isPending || redirecting
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<Button
|
|
49
|
+
variant={variant}
|
|
50
|
+
isDisabled={isDisabled}
|
|
51
|
+
isPending={pending}
|
|
52
|
+
onPress={() => signInSocial({ provider, callbackURL })}
|
|
53
|
+
{...props}
|
|
54
|
+
>
|
|
55
|
+
{pending ? <Spinner color="current" size="sm" /> : <ProviderIcon />}
|
|
56
|
+
|
|
57
|
+
{label === "continueWith"
|
|
58
|
+
? localization.auth.continueWith.replace(
|
|
59
|
+
"{{provider}}",
|
|
60
|
+
getProviderName(provider)
|
|
61
|
+
)
|
|
62
|
+
: label === "providerName"
|
|
63
|
+
? getProviderName(provider)
|
|
64
|
+
: null}
|
|
65
|
+
</Button>
|
|
66
|
+
)
|
|
67
|
+
}
|
|
@@ -1,36 +1,28 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { Button, cn } from "@heroui/react"
|
|
4
|
-
import type { SocialProvider } from "better-auth/social-providers"
|
|
1
|
+
import { useAuth } from "@better-auth-ui/react"
|
|
2
|
+
import { cn } from "@heroui/react"
|
|
5
3
|
import { useMemo } from "react"
|
|
6
4
|
|
|
5
|
+
import { ProviderButton } from "./provider-button"
|
|
6
|
+
|
|
7
7
|
export type ProviderButtonsProps = {
|
|
8
|
-
isPending
|
|
8
|
+
isPending?: boolean
|
|
9
9
|
socialLayout?: SocialLayout
|
|
10
|
-
signInSocial: (params: {
|
|
11
|
-
provider: SocialProvider
|
|
12
|
-
callbackURL: string
|
|
13
|
-
}) => void
|
|
14
10
|
}
|
|
15
11
|
|
|
16
12
|
export type SocialLayout = "auto" | "horizontal" | "vertical" | "grid"
|
|
17
13
|
|
|
18
14
|
/**
|
|
19
|
-
* Render social provider sign-in buttons
|
|
15
|
+
* Render social provider sign-in buttons. Each button owns its own sign-in mutation.
|
|
20
16
|
*
|
|
21
|
-
* @param isPending -
|
|
17
|
+
* @param isPending - External pending state (e.g. parent form submitting) that disables all buttons.
|
|
22
18
|
* @param socialLayout - Preferred layout for the buttons; `"auto"` picks `"horizontal"` when there are four or more providers, otherwise `"vertical"`.
|
|
23
|
-
* @param signInSocial - Callback invoked with the provider and callbackURL when a button is clicked.
|
|
24
19
|
* @returns The JSX element that renders the configured social provider buttons.
|
|
25
20
|
*/
|
|
26
21
|
export function ProviderButtons({
|
|
27
22
|
isPending,
|
|
28
|
-
socialLayout = "auto"
|
|
29
|
-
signInSocial
|
|
23
|
+
socialLayout = "auto"
|
|
30
24
|
}: ProviderButtonsProps) {
|
|
31
|
-
const {
|
|
32
|
-
|
|
33
|
-
const callbackURL = `${baseURL}${redirectTo}`
|
|
25
|
+
const { socialProviders } = useAuth()
|
|
34
26
|
|
|
35
27
|
const resolvedSocialLayout = useMemo(() => {
|
|
36
28
|
if (socialLayout === "auto") {
|
|
@@ -53,33 +45,24 @@ export function ProviderButtons({
|
|
|
53
45
|
resolvedSocialLayout === "horizontal" && "flex flex-wrap"
|
|
54
46
|
)}
|
|
55
47
|
>
|
|
56
|
-
{socialProviders?.map((provider) =>
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
"
|
|
64
|
-
resolvedSocialLayout === "horizontal" && "flex-1"
|
|
65
|
-
)}
|
|
66
|
-
variant="tertiary"
|
|
67
|
-
isPending={isPending}
|
|
68
|
-
onPress={() => signInSocial({ provider, callbackURL })}
|
|
69
|
-
>
|
|
70
|
-
<ProviderIcon />
|
|
71
|
-
|
|
72
|
-
{resolvedSocialLayout === "vertical"
|
|
73
|
-
? localization.auth.continueWith.replace(
|
|
74
|
-
"{{provider}}",
|
|
75
|
-
getProviderName(provider)
|
|
76
|
-
)
|
|
48
|
+
{socialProviders?.map((provider) => (
|
|
49
|
+
<ProviderButton
|
|
50
|
+
key={provider}
|
|
51
|
+
provider={provider}
|
|
52
|
+
isDisabled={isPending}
|
|
53
|
+
label={
|
|
54
|
+
resolvedSocialLayout === "vertical"
|
|
55
|
+
? "continueWith"
|
|
77
56
|
: resolvedSocialLayout === "grid"
|
|
78
|
-
?
|
|
79
|
-
:
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
57
|
+
? "providerName"
|
|
58
|
+
: "none"
|
|
59
|
+
}
|
|
60
|
+
className={cn(
|
|
61
|
+
"w-full",
|
|
62
|
+
resolvedSocialLayout === "horizontal" && "flex-1"
|
|
63
|
+
)}
|
|
64
|
+
/>
|
|
65
|
+
))}
|
|
83
66
|
</div>
|
|
84
67
|
)
|
|
85
68
|
}
|
|
@@ -31,12 +31,11 @@ export function ResetPassword({
|
|
|
31
31
|
className,
|
|
32
32
|
variant,
|
|
33
33
|
...props
|
|
34
|
-
}: ResetPasswordProps & CardProps) {
|
|
34
|
+
}: ResetPasswordProps & Omit<CardProps, "children">) {
|
|
35
35
|
const { basePaths, emailAndPassword, localization, viewPaths, navigate } =
|
|
36
36
|
useAuth()
|
|
37
37
|
|
|
38
38
|
const { mutate: resetPassword, isPending } = useResetPassword({
|
|
39
|
-
onError: (error) => toast.danger(error.error?.message || error.message),
|
|
40
39
|
onSuccess: () => {
|
|
41
40
|
toast.success(localization.auth.passwordResetSuccess)
|
|
42
41
|
navigate({ to: `${basePaths.auth}/${viewPaths.auth.signIn}` })
|
|
@@ -2,7 +2,6 @@ import {
|
|
|
2
2
|
useAuth,
|
|
3
3
|
useSendVerificationEmail,
|
|
4
4
|
useSignInEmail,
|
|
5
|
-
useSignInSocial,
|
|
6
5
|
useSignInUsername
|
|
7
6
|
} from "@better-auth-ui/react"
|
|
8
7
|
import {
|
|
@@ -50,7 +49,7 @@ export function SignIn({
|
|
|
50
49
|
socialPosition = "bottom",
|
|
51
50
|
variant,
|
|
52
51
|
...props
|
|
53
|
-
}: SignInProps & CardProps) {
|
|
52
|
+
}: SignInProps & Omit<CardProps, "children">) {
|
|
54
53
|
const {
|
|
55
54
|
basePaths,
|
|
56
55
|
baseURL,
|
|
@@ -68,7 +67,6 @@ export function SignIn({
|
|
|
68
67
|
const [password, setPassword] = useState("")
|
|
69
68
|
|
|
70
69
|
const { mutate: sendVerificationEmail } = useSendVerificationEmail({
|
|
71
|
-
onError: (error) => toast.danger(error.error?.message || error.message),
|
|
72
70
|
onSuccess: () => toast.success(localization.auth.verificationEmailSent)
|
|
73
71
|
})
|
|
74
72
|
|
|
@@ -105,19 +103,6 @@ export function SignIn({
|
|
|
105
103
|
onSuccess: () => navigate({ to: redirectTo })
|
|
106
104
|
})
|
|
107
105
|
|
|
108
|
-
const [socialRedirecting, setSocialRedirecting] = useState(false)
|
|
109
|
-
|
|
110
|
-
const { mutate: signInSocial, isPending: socialPending } = useSignInSocial({
|
|
111
|
-
onError: (error) => toast.danger(error.error?.message || error.message),
|
|
112
|
-
onSuccess: () => {
|
|
113
|
-
setSocialRedirecting(true)
|
|
114
|
-
|
|
115
|
-
setTimeout(() => {
|
|
116
|
-
setSocialRedirecting(false)
|
|
117
|
-
}, 5000)
|
|
118
|
-
}
|
|
119
|
-
})
|
|
120
|
-
|
|
121
106
|
const handleSubmit = (e: SyntheticEvent<HTMLFormElement>) => {
|
|
122
107
|
e.preventDefault()
|
|
123
108
|
|
|
@@ -139,8 +124,7 @@ export function SignIn({
|
|
|
139
124
|
}
|
|
140
125
|
}
|
|
141
126
|
|
|
142
|
-
const
|
|
143
|
-
const isPending = signInPending || socialPending || socialRedirecting
|
|
127
|
+
const isPending = signInEmailPending || signInUsernamePending
|
|
144
128
|
|
|
145
129
|
const showSeparator = emailAndPassword?.enabled && !!socialProviders?.length
|
|
146
130
|
|
|
@@ -162,7 +146,6 @@ export function SignIn({
|
|
|
162
146
|
{!!socialProviders?.length && (
|
|
163
147
|
<ProviderButtons
|
|
164
148
|
socialLayout={socialLayout}
|
|
165
|
-
signInSocial={signInSocial}
|
|
166
149
|
isPending={isPending}
|
|
167
150
|
/>
|
|
168
151
|
)}
|
|
@@ -262,7 +245,6 @@ export function SignIn({
|
|
|
262
245
|
{!!socialProviders?.length && (
|
|
263
246
|
<ProviderButtons
|
|
264
247
|
socialLayout={socialLayout}
|
|
265
|
-
signInSocial={signInSocial}
|
|
266
248
|
isPending={isPending}
|
|
267
249
|
/>
|
|
268
250
|
)}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
useAuth,
|
|
3
3
|
useIsUsernameAvailable,
|
|
4
|
-
useSignInSocial,
|
|
5
4
|
useSignUpEmail
|
|
6
5
|
} from "@better-auth-ui/react"
|
|
7
6
|
import { Check, Eye, EyeSlash, Xmark } from "@gravity-ui/icons"
|
|
@@ -51,7 +50,7 @@ export function SignUp({
|
|
|
51
50
|
socialPosition = "bottom",
|
|
52
51
|
variant,
|
|
53
52
|
...props
|
|
54
|
-
}: SignUpProps & CardProps) {
|
|
53
|
+
}: SignUpProps & Omit<CardProps, "children">) {
|
|
55
54
|
const {
|
|
56
55
|
basePaths,
|
|
57
56
|
emailAndPassword,
|
|
@@ -112,24 +111,11 @@ export function SignUp({
|
|
|
112
111
|
}
|
|
113
112
|
})
|
|
114
113
|
|
|
115
|
-
const [socialRedirecting, setSocialRedirecting] = useState(false)
|
|
116
|
-
|
|
117
|
-
const { mutate: signInSocial, isPending: socialPending } = useSignInSocial({
|
|
118
|
-
onError: (error) => toast.danger(error.error?.message || error.message),
|
|
119
|
-
onSuccess: () => {
|
|
120
|
-
setSocialRedirecting(true)
|
|
121
|
-
|
|
122
|
-
setTimeout(() => {
|
|
123
|
-
setSocialRedirecting(false)
|
|
124
|
-
}, 5000)
|
|
125
|
-
}
|
|
126
|
-
})
|
|
127
|
-
|
|
128
114
|
const [isPasswordVisible, setIsPasswordVisible] = useState(false)
|
|
129
115
|
const [isConfirmPasswordVisible, setIsConfirmPasswordVisible] =
|
|
130
116
|
useState(false)
|
|
131
117
|
|
|
132
|
-
const isPending = signUpPending
|
|
118
|
+
const isPending = signUpPending
|
|
133
119
|
|
|
134
120
|
const handleSubmit = (e: SyntheticEvent<HTMLFormElement>) => {
|
|
135
121
|
e.preventDefault()
|
|
@@ -181,7 +167,6 @@ export function SignUp({
|
|
|
181
167
|
<ProviderButtons
|
|
182
168
|
isPending={isPending}
|
|
183
169
|
socialLayout={socialLayout}
|
|
184
|
-
signInSocial={signInSocial}
|
|
185
170
|
/>
|
|
186
171
|
)}
|
|
187
172
|
|
|
@@ -250,8 +235,9 @@ export function SignUp({
|
|
|
250
235
|
<FieldError>
|
|
251
236
|
{usernameError?.error?.message ||
|
|
252
237
|
usernameError?.message ||
|
|
253
|
-
(usernameData?.available === false
|
|
254
|
-
localization.auth.usernameTaken
|
|
238
|
+
(usernameData?.available === false
|
|
239
|
+
? localization.auth.usernameTaken
|
|
240
|
+
: null)}
|
|
255
241
|
</FieldError>
|
|
256
242
|
</TextField>
|
|
257
243
|
)}
|
|
@@ -384,7 +370,6 @@ export function SignUp({
|
|
|
384
370
|
{!!socialProviders?.length && (
|
|
385
371
|
<ProviderButtons
|
|
386
372
|
socialLayout={socialLayout}
|
|
387
|
-
signInSocial={signInSocial}
|
|
388
373
|
isPending={isPending}
|
|
389
374
|
/>
|
|
390
375
|
)}
|
|
@@ -14,9 +14,7 @@ export function ChangeAvatar({ className }: ChangeAvatarProps) {
|
|
|
14
14
|
const { localization, avatar } = useAuth()
|
|
15
15
|
const { data: session } = useSession()
|
|
16
16
|
|
|
17
|
-
const { mutate: updateUser, isPending: updatePending } = useUpdateUser(
|
|
18
|
-
onError: (error) => toast.danger(error.error?.message || error.message)
|
|
19
|
-
})
|
|
17
|
+
const { mutate: updateUser, isPending: updatePending } = useUpdateUser()
|
|
20
18
|
|
|
21
19
|
const fileInputRef = useRef<HTMLInputElement>(null)
|
|
22
20
|
const [isUploading, setIsUploading] = useState(false)
|
|
@@ -34,13 +34,12 @@ export function ChangeEmail({
|
|
|
34
34
|
className,
|
|
35
35
|
variant,
|
|
36
36
|
...props
|
|
37
|
-
}: ChangeEmailProps & CardProps) {
|
|
37
|
+
}: ChangeEmailProps & Omit<CardProps, "children">) {
|
|
38
38
|
const { localization, baseURL, viewPaths } = useAuth()
|
|
39
39
|
const { data: session } = useSession()
|
|
40
40
|
|
|
41
41
|
const { mutate: changeEmail, isPending } = useChangeEmail({
|
|
42
|
-
onSuccess: () => toast.success(localization.settings.changeEmailSuccess)
|
|
43
|
-
onError: (error) => toast.danger(error.error?.message || error.message)
|
|
42
|
+
onSuccess: () => toast.success(localization.settings.changeEmailSuccess)
|
|
44
43
|
})
|
|
45
44
|
|
|
46
45
|
function handleSubmit(e: SyntheticEvent<HTMLFormElement>) {
|
|
@@ -41,13 +41,10 @@ export function ManageAccount({
|
|
|
41
41
|
const { data: user } = useUser()
|
|
42
42
|
|
|
43
43
|
const { mutate: setActiveSession, isPending: isSwitching } =
|
|
44
|
-
useSetActiveSession(
|
|
45
|
-
onError: (error) => toast.danger(error.error?.message || error.message)
|
|
46
|
-
})
|
|
44
|
+
useSetActiveSession()
|
|
47
45
|
|
|
48
46
|
const { mutate: revokeSession, isPending: isRevoking } =
|
|
49
47
|
useRevokeMultiSession({
|
|
50
|
-
onError: (error) => toast.danger(error.error?.message || error.message),
|
|
51
48
|
onSuccess: () => toast.success(localization.settings.revokeSessionSuccess)
|
|
52
49
|
})
|
|
53
50
|
|