@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.
Files changed (74) hide show
  1. package/dist/components/auth/auth-provider.js +12 -11
  2. package/dist/components/auth/auth.d.ts +1 -1
  3. package/dist/components/auth/error-toaster.d.ts +1 -0
  4. package/dist/components/auth/error-toaster.js +17 -0
  5. package/dist/components/auth/forgot-password.d.ts +1 -1
  6. package/dist/components/auth/forgot-password.js +3 -6
  7. package/dist/components/auth/magic-link.d.ts +1 -1
  8. package/dist/components/auth/magic-link.js +52 -64
  9. package/dist/components/auth/passkey-button.js +12 -15
  10. package/dist/components/auth/provider-button.d.ts +15 -0
  11. package/dist/components/auth/provider-button.js +29 -0
  12. package/dist/components/auth/provider-buttons.d.ts +4 -10
  13. package/dist/components/auth/provider-buttons.js +16 -23
  14. package/dist/components/auth/reset-password.d.ts +1 -1
  15. package/dist/components/auth/reset-password.js +3 -6
  16. package/dist/components/auth/sign-in.d.ts +1 -1
  17. package/dist/components/auth/sign-in.js +81 -93
  18. package/dist/components/auth/sign-up.d.ts +1 -1
  19. package/dist/components/auth/sign-up.js +99 -108
  20. package/dist/components/settings/account/appearance.d.ts +1 -1
  21. package/dist/components/settings/account/change-avatar.js +1 -1
  22. package/dist/components/settings/account/change-email.d.ts +1 -1
  23. package/dist/components/settings/account/change-email.js +1 -4
  24. package/dist/components/settings/account/manage-account.js +1 -4
  25. package/dist/components/settings/account/manage-accounts.d.ts +1 -1
  26. package/dist/components/settings/account/manage-accounts.js +16 -16
  27. package/dist/components/settings/account/user-profile.d.ts +1 -1
  28. package/dist/components/settings/account/user-profile.js +1 -4
  29. package/dist/components/settings/security/active-session.js +1 -4
  30. package/dist/components/settings/security/active-sessions.d.ts +1 -1
  31. package/dist/components/settings/security/active-sessions.js +17 -17
  32. package/dist/components/settings/security/change-password.d.ts +1 -1
  33. package/dist/components/settings/security/change-password.js +1 -4
  34. package/dist/components/settings/security/delete-user.d.ts +1 -1
  35. package/dist/components/settings/security/delete-user.js +6 -11
  36. package/dist/components/settings/security/linked-account.js +1 -7
  37. package/dist/components/settings/security/linked-accounts.d.ts +1 -1
  38. package/dist/components/settings/security/linked-accounts.js +18 -18
  39. package/dist/components/settings/security/passkey.js +19 -19
  40. package/dist/components/settings/security/passkeys.d.ts +1 -1
  41. package/dist/components/settings/security/passkeys.js +28 -28
  42. package/dist/components/user/switch-account-item.js +9 -9
  43. package/dist/components/user/switch-account-menu.js +16 -16
  44. package/dist/index.d.ts +1 -0
  45. package/dist/index.js +34 -33
  46. package/package.json +6 -4
  47. package/src/components/auth/auth-provider.tsx +4 -0
  48. package/src/components/auth/auth.tsx +1 -1
  49. package/src/components/auth/error-toaster.tsx +25 -0
  50. package/src/components/auth/forgot-password.tsx +1 -2
  51. package/src/components/auth/magic-link.tsx +3 -23
  52. package/src/components/auth/passkey-button.tsx +1 -2
  53. package/src/components/auth/provider-button.tsx +67 -0
  54. package/src/components/auth/provider-buttons.tsx +26 -43
  55. package/src/components/auth/reset-password.tsx +1 -2
  56. package/src/components/auth/sign-in.tsx +2 -20
  57. package/src/components/auth/sign-up.tsx +5 -20
  58. package/src/components/settings/account/appearance.tsx +1 -1
  59. package/src/components/settings/account/change-avatar.tsx +1 -3
  60. package/src/components/settings/account/change-email.tsx +2 -3
  61. package/src/components/settings/account/manage-account.tsx +1 -4
  62. package/src/components/settings/account/manage-accounts.tsx +3 -8
  63. package/src/components/settings/account/user-profile.tsx +1 -2
  64. package/src/components/settings/security/active-session.tsx +0 -1
  65. package/src/components/settings/security/active-sessions.tsx +3 -8
  66. package/src/components/settings/security/change-password.tsx +7 -4
  67. package/src/components/settings/security/delete-user.tsx +1 -4
  68. package/src/components/settings/security/linked-account.tsx +4 -14
  69. package/src/components/settings/security/linked-accounts.tsx +3 -8
  70. package/src/components/settings/security/passkey.tsx +2 -4
  71. package/src/components/settings/security/passkeys.tsx +4 -12
  72. package/src/components/user/switch-account-item.tsx +2 -4
  73. package/src/components/user/switch-account-menu.tsx +2 -7
  74. 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 { ProviderButtons as r } from "./components/auth/provider-buttons.js";
6
- import { MagicLink as i } from "./components/auth/magic-link.js";
7
- import { ResetPassword as a } from "./components/auth/reset-password.js";
8
- import { SignIn as o } from "./components/auth/sign-in.js";
9
- import { SignOut as s } from "./components/auth/sign-out.js";
10
- import { SignUp as c } from "./components/auth/sign-up.js";
11
- import { Auth as l } from "./components/auth/auth.js";
12
- import { AuthProvider as u } from "./components/auth/auth-provider.js";
13
- import { EmailChangedEmail as d } from "./components/email/email-changed-email.js";
14
- import { EmailVerificationEmail as f } from "./components/email/email-verification-email.js";
15
- import { MagicLinkEmail as p } from "./components/email/magic-link-email.js";
16
- import { NewDeviceEmail as m } from "./components/email/new-device-email.js";
17
- import { OtpEmail as h } from "./components/email/otp-email.js";
18
- import { PasswordChangedEmail as g } from "./components/email/password-changed-email.js";
19
- import { ResetPasswordEmail as _ } from "./components/email/reset-password-email.js";
20
- import { Appearance as v } from "./components/settings/account/appearance.js";
21
- import { ChangeEmail as y } from "./components/settings/account/change-email.js";
22
- import { UserAvatar as b } from "./components/user/user-avatar.js";
23
- import { UserView as x } from "./components/user/user-view.js";
24
- import { ManageAccount as S } from "./components/settings/account/manage-account.js";
25
- import { ManageAccounts as C } from "./components/settings/account/manage-accounts.js";
26
- import { UserProfile as w } from "./components/settings/account/user-profile.js";
27
- import { AccountSettings as T } from "./components/settings/account/account-settings.js";
28
- import { ActiveSessions as E } from "./components/settings/security/active-sessions.js";
29
- import { ChangePassword as D } from "./components/settings/security/change-password.js";
30
- import { DeleteUser as O } from "./components/settings/security/delete-user.js";
31
- import { DangerZone as k } from "./components/settings/security/danger-zone.js";
32
- import { LinkedAccounts as A } from "./components/settings/security/linked-accounts.js";
33
- import { Passkeys as j } from "./components/settings/security/passkeys.js";
34
- import { SecuritySettings as M } from "./components/settings/security/security-settings.js";
35
- import { Settings as N } from "./components/settings/settings.js";
36
- import { UserButton as P } from "./components/user/user-button.js";
37
- export { T as AccountSettings, E as ActiveSessions, v as Appearance, l as Auth, u as AuthProvider, y as ChangeEmail, D as ChangePassword, k as DangerZone, O as DeleteUser, d as EmailChangedEmail, f as EmailVerificationEmail, e as ForgotPassword, A as LinkedAccounts, i as MagicLink, t as MagicLinkButton, p as MagicLinkEmail, S as ManageAccount, C as ManageAccounts, m as NewDeviceEmail, h as OtpEmail, n as PasskeyButton, j as Passkeys, g as PasswordChangedEmail, r as ProviderButtons, a as ResetPassword, _ as ResetPasswordEmail, M as SecuritySettings, N as Settings, o as SignIn, s as SignOut, c as SignUp, b as UserAvatar, P as UserButton, w as UserProfile, x as UserView };
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.2",
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.21.1",
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.21.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
  )
@@ -35,7 +35,7 @@ export function Auth({
35
35
  socialPosition,
36
36
  view,
37
37
  ...props
38
- }: AuthProps & CardProps) {
38
+ }: AuthProps & Omit<CardProps, "children">) {
39
39
  const { viewPaths } = useAuth()
40
40
 
41
41
  if (!view && !path) {
@@ -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 [socialRedirecting, setSocialRedirecting] = useState(false)
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, toast } from "@heroui/react"
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 { getProviderName } from "@better-auth-ui/core"
2
- import { providerIcons, useAuth } from "@better-auth-ui/react"
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: boolean
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 and handle initiation and pending state.
15
+ * Render social provider sign-in buttons. Each button owns its own sign-in mutation.
20
16
  *
21
- * @param isPending - Disables all provider buttons when true.
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 { baseURL, localization, redirectTo, socialProviders } = useAuth()
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
- const ProviderIcon = providerIcons[provider]
58
-
59
- return (
60
- <Button
61
- key={provider}
62
- className={cn(
63
- "w-full",
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
- ? getProviderName(provider)
79
- : null}
80
- </Button>
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 signInPending = signInEmailPending || signInUsernamePending
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 || socialPending || socialRedirecting
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
  )}
@@ -34,7 +34,7 @@ export function Appearance({
34
34
  className,
35
35
  variant,
36
36
  ...props
37
- }: AppearanceProps & CardProps) {
37
+ }: AppearanceProps & Omit<CardProps, "children">) {
38
38
  const {
39
39
  localization,
40
40
  appearance: { theme, setTheme, themes }
@@ -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