@better-auth-ui/react 1.6.4 → 1.6.6

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.
@@ -1,43 +1,44 @@
1
1
  "use client";
2
- import { deepmerge as e, defaultAuthConfig as t } from "@better-auth-ui/core";
3
- import { QueryClient as n, QueryClientContext as r, QueryClientProvider as i } from "@tanstack/react-query";
4
- import { createContext as a, useContext as o } from "react";
5
- import { jsx as s } from "react/jsx-runtime";
2
+ import { FetchOptionsProvider as e } from "./fetch-options-provider.js";
3
+ import { deepmerge as t, defaultAuthConfig as n } from "@better-auth-ui/core";
4
+ import { QueryClient as r, QueryClientContext as i, QueryClientProvider as a } from "@tanstack/react-query";
5
+ import { createContext as o, useContext as s } from "react";
6
+ import { jsx as c } from "react/jsx-runtime";
6
7
  //#region src/components/auth/auth-provider.tsx
7
- var c = a(void 0), l = new n({ defaultOptions: { queries: { staleTime: 5e3 } } });
8
- function u({ children: n, queryClient: a, ...u }) {
9
- let d = e(t, {
10
- ...u,
8
+ var l = o(void 0), u = new r({ defaultOptions: { queries: { staleTime: 5e3 } } });
9
+ function d({ children: r, queryClient: o, ...d }) {
10
+ let f = t(n, {
11
+ ...d,
11
12
  viewPaths: {
12
13
  auth: {
13
- ...t.viewPaths.auth,
14
- ...u.viewPaths?.auth
14
+ ...n.viewPaths.auth,
15
+ ...d.viewPaths?.auth
15
16
  },
16
17
  settings: {
17
- ...t.viewPaths.settings,
18
- ...u.viewPaths?.settings
18
+ ...n.viewPaths.settings,
19
+ ...d.viewPaths?.settings
19
20
  }
20
21
  }
21
22
  });
22
- d.redirectTo = typeof window < "u" && new URLSearchParams(window.location.search).get("redirectTo")?.trim() || d.redirectTo;
23
- let f = /* @__PURE__ */ new Map();
24
- for (let e of d.plugins ?? []) for (let t of e.additionalFields ?? []) f.set(t.name, t);
25
- for (let e of d.additionalFields ?? []) f.set(e.name, e);
26
- return d.additionalFields = Array.from(f.values()), o(r) ? /* @__PURE__ */ s(c.Provider, {
27
- value: d,
28
- children: n
29
- }) : /* @__PURE__ */ s(i, {
30
- client: a || l,
31
- children: /* @__PURE__ */ s(c.Provider, {
32
- value: d,
33
- children: n
23
+ f.redirectTo = typeof window < "u" && new URLSearchParams(window.location.search).get("redirectTo")?.trim() || f.redirectTo;
24
+ let p = /* @__PURE__ */ new Map();
25
+ for (let e of f.plugins ?? []) for (let t of e.additionalFields ?? []) p.set(t.name, t);
26
+ for (let e of f.additionalFields ?? []) p.set(e.name, e);
27
+ return f.additionalFields = Array.from(p.values()), s(i) ? /* @__PURE__ */ c(l.Provider, {
28
+ value: f,
29
+ children: /* @__PURE__ */ c(e, { children: r })
30
+ }) : /* @__PURE__ */ c(a, {
31
+ client: o || u,
32
+ children: /* @__PURE__ */ c(l.Provider, {
33
+ value: f,
34
+ children: /* @__PURE__ */ c(e, { children: r })
34
35
  })
35
36
  });
36
37
  }
37
- function d() {
38
- let e = o(c);
38
+ function f() {
39
+ let e = s(l);
39
40
  if (!e) throw Error("[Better Auth UI] AuthProvider is required");
40
41
  return e;
41
42
  }
42
43
  //#endregion
43
- export { u as AuthProvider, d as useAuth };
44
+ export { d as AuthProvider, f as useAuth };
@@ -0,0 +1,19 @@
1
+ import { PropsWithChildren } from 'react';
2
+ /** Subset of BetterFetchOptions we expose. Add fields as use-cases arise. */
3
+ export type FetchOptions = {
4
+ headers?: Record<string, string>;
5
+ body?: Record<string, unknown>;
6
+ };
7
+ type FetchOptionsContextValue = {
8
+ /** Current fetchOptions, or `undefined` when none are set. */
9
+ fetchOptions: FetchOptions | undefined;
10
+ /** OVERRIDES the entire fetchOptions object. Pass `undefined` to clear. */
11
+ setFetchOptions: (fetchOptions: FetchOptions | undefined) => void;
12
+ /** Clears `fetchOptions` and runs the registered reset (e.g. captcha widget). Call from form `onError`. */
13
+ resetFetchOptions: () => void;
14
+ /** Register a reset handler. Used by `captchaPlugin`. Pass `null` to clear. */
15
+ registerReset: (reset: (() => void) | null) => void;
16
+ };
17
+ export declare function FetchOptionsProvider({ children }: PropsWithChildren): import("react/jsx-runtime").JSX.Element;
18
+ export declare function useFetchOptions(): FetchOptionsContextValue;
19
+ export {};
@@ -0,0 +1,30 @@
1
+ "use client";
2
+ import { createContext as e, useCallback as t, useContext as n, useRef as r, useState as i } from "react";
3
+ import { jsx as a } from "react/jsx-runtime";
4
+ //#region src/components/auth/fetch-options-provider.tsx
5
+ var o = e(void 0);
6
+ function s({ children: e }) {
7
+ let [n, s] = i(void 0), c = r(null), l = t((e) => {
8
+ s(e);
9
+ }, []), u = t((e) => {
10
+ c.current = e;
11
+ }, []), d = t(() => {
12
+ s(void 0), c.current?.();
13
+ }, []);
14
+ return /* @__PURE__ */ a(o.Provider, {
15
+ value: {
16
+ fetchOptions: n,
17
+ setFetchOptions: l,
18
+ resetFetchOptions: d,
19
+ registerReset: u
20
+ },
21
+ children: e
22
+ });
23
+ }
24
+ function c() {
25
+ let e = n(o);
26
+ if (!e) throw Error("[Better Auth UI] useFetchOptions must be used within FetchOptionsProvider");
27
+ return e;
28
+ }
29
+ //#endregion
30
+ export { s as FetchOptionsProvider, c as useFetchOptions };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from './components/auth/auth-provider';
2
+ export * from './components/auth/fetch-options-provider';
2
3
  export * from './components/icons';
3
4
  export * from './components/settings/account/theme-preview';
4
5
  export * from './hooks/auth/use-authenticate';
package/dist/index.js CHANGED
@@ -1,76 +1,77 @@
1
1
  "use client";
2
- import { AuthProvider as e, useAuth as t } from "./components/auth/auth-provider.js";
3
- import { Apple as n } from "./components/icons/apple.js";
4
- import { Atlassian as r } from "./components/icons/atlassian.js";
5
- import { Cognito as i } from "./components/icons/cognito.js";
6
- import { Discord as a } from "./components/icons/discord.js";
7
- import { Dropbox as o } from "./components/icons/dropbox.js";
8
- import { Facebook as s } from "./components/icons/facebook.js";
9
- import { Figma as c } from "./components/icons/figma.js";
10
- import { GitHub as l } from "./components/icons/github.js";
11
- import { GitLab as u } from "./components/icons/gitlab.js";
12
- import { Google as d } from "./components/icons/google.js";
13
- import { HuggingFace as f } from "./components/icons/huggingface.js";
14
- import { Kakao as p } from "./components/icons/kakao.js";
15
- import { Kick as m } from "./components/icons/kick.js";
16
- import { Line as h } from "./components/icons/line.js";
17
- import { Linear as g } from "./components/icons/linear.js";
18
- import { LinkedIn as _ } from "./components/icons/linkedin.js";
19
- import { Microsoft as v } from "./components/icons/microsoft.js";
20
- import { Naver as y } from "./components/icons/naver.js";
21
- import { Notion as b } from "./components/icons/notion.js";
22
- import { Paybin as x } from "./components/icons/paybin.js";
23
- import { PayPal as S } from "./components/icons/paypal.js";
24
- import { Polar as C } from "./components/icons/polar.js";
25
- import { Railway as w } from "./components/icons/railway.js";
26
- import { Reddit as T } from "./components/icons/reddit.js";
27
- import { Roblox as E } from "./components/icons/roblox.js";
28
- import { Salesforce as D } from "./components/icons/salesforce.js";
29
- import { Slack as O } from "./components/icons/slack.js";
30
- import { Spotify as k } from "./components/icons/spotify.js";
31
- import { TikTok as A } from "./components/icons/tiktok.js";
32
- import { Twitch as j } from "./components/icons/twitch.js";
33
- import { Vercel as M } from "./components/icons/vercel.js";
34
- import { VK as N } from "./components/icons/vk.js";
35
- import { WeChat as P } from "./components/icons/wechat.js";
36
- import { X as F } from "./components/icons/x.js";
37
- import { Zoom as I } from "./components/icons/zoom.js";
2
+ import { FetchOptionsProvider as e, useFetchOptions as t } from "./components/auth/fetch-options-provider.js";
3
+ import { AuthProvider as n, useAuth as r } from "./components/auth/auth-provider.js";
4
+ import { Apple as i } from "./components/icons/apple.js";
5
+ import { Atlassian as a } from "./components/icons/atlassian.js";
6
+ import { Cognito as o } from "./components/icons/cognito.js";
7
+ import { Discord as s } from "./components/icons/discord.js";
8
+ import { Dropbox as c } from "./components/icons/dropbox.js";
9
+ import { Facebook as l } from "./components/icons/facebook.js";
10
+ import { Figma as u } from "./components/icons/figma.js";
11
+ import { GitHub as d } from "./components/icons/github.js";
12
+ import { GitLab as f } from "./components/icons/gitlab.js";
13
+ import { Google as p } from "./components/icons/google.js";
14
+ import { HuggingFace as m } from "./components/icons/huggingface.js";
15
+ import { Kakao as h } from "./components/icons/kakao.js";
16
+ import { Kick as g } from "./components/icons/kick.js";
17
+ import { Line as _ } from "./components/icons/line.js";
18
+ import { Linear as v } from "./components/icons/linear.js";
19
+ import { LinkedIn as y } from "./components/icons/linkedin.js";
20
+ import { Microsoft as b } from "./components/icons/microsoft.js";
21
+ import { Naver as x } from "./components/icons/naver.js";
22
+ import { Notion as S } from "./components/icons/notion.js";
23
+ import { Paybin as C } from "./components/icons/paybin.js";
24
+ import { PayPal as w } from "./components/icons/paypal.js";
25
+ import { Polar as T } from "./components/icons/polar.js";
26
+ import { Railway as E } from "./components/icons/railway.js";
27
+ import { Reddit as D } from "./components/icons/reddit.js";
28
+ import { Roblox as O } from "./components/icons/roblox.js";
29
+ import { Salesforce as k } from "./components/icons/salesforce.js";
30
+ import { Slack as A } from "./components/icons/slack.js";
31
+ import { Spotify as j } from "./components/icons/spotify.js";
32
+ import { TikTok as M } from "./components/icons/tiktok.js";
33
+ import { Twitch as N } from "./components/icons/twitch.js";
34
+ import { Vercel as P } from "./components/icons/vercel.js";
35
+ import { VK as F } from "./components/icons/vk.js";
36
+ import { WeChat as I } from "./components/icons/wechat.js";
37
+ import { X as L } from "./components/icons/x.js";
38
+ import { Zoom as R } from "./components/icons/zoom.js";
38
39
  import "./components/icons/index.js";
39
- import { ThemePreviewDark as L, ThemePreviewLight as R, ThemePreviewSystem as z } from "./components/settings/account/theme-preview.js";
40
- import { ensureSession as B, fetchSession as V, prefetchSession as H, sessionOptions as U, useSession as W } from "./queries/auth/session-query.js";
41
- import { useAuthenticate as G } from "./hooks/auth/use-authenticate.js";
42
- import { useUser as K } from "./hooks/auth/use-user.js";
43
- import { authMutationOptions as q } from "./mutations/auth-mutation-options.js";
44
- import { useAuthMutation as J } from "./hooks/use-auth-mutation.js";
45
- import { useAuthPlugin as Y } from "./hooks/use-auth-plugin.js";
46
- import { authQueryOptions as X } from "./queries/auth-query-options.js";
47
- import { useAuthQuery as Z } from "./hooks/use-auth-query.js";
48
- import { providerIcons as Q } from "./lib/provider-icons.js";
49
- import { requestPasswordResetOptions as $, useRequestPasswordReset as ee } from "./mutations/auth/request-password-reset-mutation.js";
50
- import { resetPasswordOptions as te, useResetPassword as ne } from "./mutations/auth/reset-password-mutation.js";
51
- import { sendVerificationEmailOptions as re, useSendVerificationEmail as ie } from "./mutations/auth/send-verification-email-mutation.js";
52
- import { signInEmailOptions as ae, useSignInEmail as oe } from "./mutations/auth/sign-in-email-mutation.js";
53
- import { signInSocialOptions as se, useSignInSocial as ce } from "./mutations/auth/sign-in-social-mutation.js";
54
- import { signOutOptions as le, useSignOut as ue } from "./mutations/auth/sign-out-mutation.js";
55
- import { signUpEmailOptions as de, useSignUpEmail as fe } from "./mutations/auth/sign-up-email-mutation.js";
56
- import { signInMagicLinkOptions as pe, useSignInMagicLink as me } from "./mutations/magic-link/sign-in-magic-link-mutation.js";
57
- import { ensureListDeviceSessions as he, fetchListDeviceSessions as ge, listDeviceSessionsOptions as _e, prefetchListDeviceSessions as ve, useListDeviceSessions as ye } from "./queries/multi-session/list-device-sessions-query.js";
58
- import { revokeMultiSessionOptions as be, useRevokeMultiSession as xe } from "./mutations/multi-session/revoke-multi-session-mutation.js";
59
- import { setActiveSessionOptions as Se, useSetActiveSession as Ce } from "./mutations/multi-session/set-active-session-mutation.js";
60
- import { ensureListPasskeys as we, fetchListPasskeys as Te, listPasskeysOptions as Ee, prefetchListPasskeys as De, useListPasskeys as Oe } from "./queries/passkey/list-passkeys-query.js";
61
- import { addPasskeyOptions as ke, useAddPasskey as Ae } from "./mutations/passkey/add-passkey-mutation.js";
62
- import { deletePasskeyOptions as je, useDeletePasskey as Me } from "./mutations/passkey/delete-passkey-mutation.js";
63
- import { signInPasskeyOptions as Ne, useSignInPasskey as Pe } from "./mutations/passkey/sign-in-passkey-mutation.js";
64
- import { changeEmailOptions as Fe, useChangeEmail as Ie } from "./mutations/settings/change-email-mutation.js";
65
- import { changePasswordOptions as Le, useChangePassword as Re } from "./mutations/settings/change-password-mutation.js";
66
- import { deleteUserOptions as ze, useDeleteUser as Be } from "./mutations/settings/delete-user-mutation.js";
67
- import { linkSocialOptions as Ve, useLinkSocial as He } from "./mutations/settings/link-social-mutation.js";
68
- import { ensureListSessions as Ue, fetchListSessions as We, listSessionsOptions as Ge, prefetchListSessions as Ke, useListSessions as qe } from "./queries/settings/list-sessions-query.js";
69
- import { revokeSessionOptions as Je, useRevokeSession as Ye } from "./mutations/settings/revoke-session-mutation.js";
70
- import { ensureListAccounts as Xe, fetchListAccounts as Ze, listAccountsOptions as Qe, prefetchListAccounts as $e, useListAccounts as et } from "./queries/settings/list-accounts-query.js";
71
- import { unlinkAccountOptions as tt, useUnlinkAccount as nt } from "./mutations/settings/unlink-account-mutation.js";
72
- import { updateUserOptions as rt, useUpdateUser as it } from "./mutations/settings/update-user-mutation.js";
73
- import { isUsernameAvailableOptions as at, useIsUsernameAvailable as ot } from "./mutations/username/is-username-available-mutation.js";
74
- import { signInUsernameOptions as st, useSignInUsername as ct } from "./mutations/username/sign-in-username-mutation.js";
75
- import { accountInfoOptions as lt, ensureAccountInfo as ut, fetchAccountInfo as dt, prefetchAccountInfo as ft, useAccountInfo as pt } from "./queries/settings/account-info-query.js";
76
- export { n as Apple, r as Atlassian, e as AuthProvider, i as Cognito, a as Discord, o as Dropbox, s as Facebook, c as Figma, l as GitHub, u as GitLab, d as Google, f as HuggingFace, p as Kakao, m as Kick, h as Line, g as Linear, _ as LinkedIn, v as Microsoft, y as Naver, b as Notion, S as PayPal, x as Paybin, C as Polar, w as Railway, T as Reddit, E as Roblox, D as Salesforce, O as Slack, k as Spotify, L as ThemePreviewDark, R as ThemePreviewLight, z as ThemePreviewSystem, A as TikTok, j as Twitch, N as VK, M as Vercel, P as WeChat, F as X, I as Zoom, lt as accountInfoOptions, ke as addPasskeyOptions, q as authMutationOptions, X as authQueryOptions, Fe as changeEmailOptions, Le as changePasswordOptions, je as deletePasskeyOptions, ze as deleteUserOptions, ut as ensureAccountInfo, Xe as ensureListAccounts, he as ensureListDeviceSessions, we as ensureListPasskeys, Ue as ensureListSessions, B as ensureSession, dt as fetchAccountInfo, Ze as fetchListAccounts, ge as fetchListDeviceSessions, Te as fetchListPasskeys, We as fetchListSessions, V as fetchSession, at as isUsernameAvailableOptions, Ve as linkSocialOptions, Qe as listAccountsOptions, _e as listDeviceSessionsOptions, Ee as listPasskeysOptions, Ge as listSessionsOptions, ft as prefetchAccountInfo, $e as prefetchListAccounts, ve as prefetchListDeviceSessions, De as prefetchListPasskeys, Ke as prefetchListSessions, H as prefetchSession, Q as providerIcons, $ as requestPasswordResetOptions, te as resetPasswordOptions, be as revokeMultiSessionOptions, Je as revokeSessionOptions, re as sendVerificationEmailOptions, U as sessionOptions, Se as setActiveSessionOptions, ae as signInEmailOptions, pe as signInMagicLinkOptions, Ne as signInPasskeyOptions, se as signInSocialOptions, st as signInUsernameOptions, le as signOutOptions, de as signUpEmailOptions, tt as unlinkAccountOptions, rt as updateUserOptions, pt as useAccountInfo, Ae as useAddPasskey, t as useAuth, J as useAuthMutation, Y as useAuthPlugin, Z as useAuthQuery, G as useAuthenticate, Ie as useChangeEmail, Re as useChangePassword, Me as useDeletePasskey, Be as useDeleteUser, ot as useIsUsernameAvailable, He as useLinkSocial, et as useListAccounts, ye as useListDeviceSessions, Oe as useListPasskeys, qe as useListSessions, ee as useRequestPasswordReset, ne as useResetPassword, xe as useRevokeMultiSession, Ye as useRevokeSession, ie as useSendVerificationEmail, W as useSession, Ce as useSetActiveSession, oe as useSignInEmail, me as useSignInMagicLink, Pe as useSignInPasskey, ce as useSignInSocial, ct as useSignInUsername, ue as useSignOut, fe as useSignUpEmail, nt as useUnlinkAccount, it as useUpdateUser, K as useUser };
40
+ import { ThemePreviewDark as z, ThemePreviewLight as B, ThemePreviewSystem as V } from "./components/settings/account/theme-preview.js";
41
+ import { ensureSession as H, fetchSession as U, prefetchSession as W, sessionOptions as G, useSession as K } from "./queries/auth/session-query.js";
42
+ import { useAuthenticate as q } from "./hooks/auth/use-authenticate.js";
43
+ import { useUser as J } from "./hooks/auth/use-user.js";
44
+ import { authMutationOptions as Y } from "./mutations/auth-mutation-options.js";
45
+ import { useAuthMutation as X } from "./hooks/use-auth-mutation.js";
46
+ import { useAuthPlugin as Z } from "./hooks/use-auth-plugin.js";
47
+ import { authQueryOptions as Q } from "./queries/auth-query-options.js";
48
+ import { useAuthQuery as $ } from "./hooks/use-auth-query.js";
49
+ import { providerIcons as ee } from "./lib/provider-icons.js";
50
+ import { requestPasswordResetOptions as te, useRequestPasswordReset as ne } from "./mutations/auth/request-password-reset-mutation.js";
51
+ import { resetPasswordOptions as re, useResetPassword as ie } from "./mutations/auth/reset-password-mutation.js";
52
+ import { sendVerificationEmailOptions as ae, useSendVerificationEmail as oe } from "./mutations/auth/send-verification-email-mutation.js";
53
+ import { signInEmailOptions as se, useSignInEmail as ce } from "./mutations/auth/sign-in-email-mutation.js";
54
+ import { signInSocialOptions as le, useSignInSocial as ue } from "./mutations/auth/sign-in-social-mutation.js";
55
+ import { signOutOptions as de, useSignOut as fe } from "./mutations/auth/sign-out-mutation.js";
56
+ import { signUpEmailOptions as pe, useSignUpEmail as me } from "./mutations/auth/sign-up-email-mutation.js";
57
+ import { signInMagicLinkOptions as he, useSignInMagicLink as ge } from "./mutations/magic-link/sign-in-magic-link-mutation.js";
58
+ import { ensureListDeviceSessions as _e, fetchListDeviceSessions as ve, listDeviceSessionsOptions as ye, prefetchListDeviceSessions as be, useListDeviceSessions as xe } from "./queries/multi-session/list-device-sessions-query.js";
59
+ import { revokeMultiSessionOptions as Se, useRevokeMultiSession as Ce } from "./mutations/multi-session/revoke-multi-session-mutation.js";
60
+ import { setActiveSessionOptions as we, useSetActiveSession as Te } from "./mutations/multi-session/set-active-session-mutation.js";
61
+ import { ensureListPasskeys as Ee, fetchListPasskeys as De, listPasskeysOptions as Oe, prefetchListPasskeys as ke, useListPasskeys as Ae } from "./queries/passkey/list-passkeys-query.js";
62
+ import { addPasskeyOptions as je, useAddPasskey as Me } from "./mutations/passkey/add-passkey-mutation.js";
63
+ import { deletePasskeyOptions as Ne, useDeletePasskey as Pe } from "./mutations/passkey/delete-passkey-mutation.js";
64
+ import { signInPasskeyOptions as Fe, useSignInPasskey as Ie } from "./mutations/passkey/sign-in-passkey-mutation.js";
65
+ import { changeEmailOptions as Le, useChangeEmail as Re } from "./mutations/settings/change-email-mutation.js";
66
+ import { changePasswordOptions as ze, useChangePassword as Be } from "./mutations/settings/change-password-mutation.js";
67
+ import { deleteUserOptions as Ve, useDeleteUser as He } from "./mutations/settings/delete-user-mutation.js";
68
+ import { linkSocialOptions as Ue, useLinkSocial as We } from "./mutations/settings/link-social-mutation.js";
69
+ import { ensureListSessions as Ge, fetchListSessions as Ke, listSessionsOptions as qe, prefetchListSessions as Je, useListSessions as Ye } from "./queries/settings/list-sessions-query.js";
70
+ import { revokeSessionOptions as Xe, useRevokeSession as Ze } from "./mutations/settings/revoke-session-mutation.js";
71
+ import { ensureListAccounts as Qe, fetchListAccounts as $e, listAccountsOptions as et, prefetchListAccounts as tt, useListAccounts as nt } from "./queries/settings/list-accounts-query.js";
72
+ import { unlinkAccountOptions as rt, useUnlinkAccount as it } from "./mutations/settings/unlink-account-mutation.js";
73
+ import { updateUserOptions as at, useUpdateUser as ot } from "./mutations/settings/update-user-mutation.js";
74
+ import { isUsernameAvailableOptions as st, useIsUsernameAvailable as ct } from "./mutations/username/is-username-available-mutation.js";
75
+ import { signInUsernameOptions as lt, useSignInUsername as ut } from "./mutations/username/sign-in-username-mutation.js";
76
+ import { accountInfoOptions as dt, ensureAccountInfo as ft, fetchAccountInfo as pt, prefetchAccountInfo as mt, useAccountInfo as ht } from "./queries/settings/account-info-query.js";
77
+ export { i as Apple, a as Atlassian, n as AuthProvider, o as Cognito, s as Discord, c as Dropbox, l as Facebook, e as FetchOptionsProvider, u as Figma, d as GitHub, f as GitLab, p as Google, m as HuggingFace, h as Kakao, g as Kick, _ as Line, v as Linear, y as LinkedIn, b as Microsoft, x as Naver, S as Notion, w as PayPal, C as Paybin, T as Polar, E as Railway, D as Reddit, O as Roblox, k as Salesforce, A as Slack, j as Spotify, z as ThemePreviewDark, B as ThemePreviewLight, V as ThemePreviewSystem, M as TikTok, N as Twitch, F as VK, P as Vercel, I as WeChat, L as X, R as Zoom, dt as accountInfoOptions, je as addPasskeyOptions, Y as authMutationOptions, Q as authQueryOptions, Le as changeEmailOptions, ze as changePasswordOptions, Ne as deletePasskeyOptions, Ve as deleteUserOptions, ft as ensureAccountInfo, Qe as ensureListAccounts, _e as ensureListDeviceSessions, Ee as ensureListPasskeys, Ge as ensureListSessions, H as ensureSession, pt as fetchAccountInfo, $e as fetchListAccounts, ve as fetchListDeviceSessions, De as fetchListPasskeys, Ke as fetchListSessions, U as fetchSession, st as isUsernameAvailableOptions, Ue as linkSocialOptions, et as listAccountsOptions, ye as listDeviceSessionsOptions, Oe as listPasskeysOptions, qe as listSessionsOptions, mt as prefetchAccountInfo, tt as prefetchListAccounts, be as prefetchListDeviceSessions, ke as prefetchListPasskeys, Je as prefetchListSessions, W as prefetchSession, ee as providerIcons, te as requestPasswordResetOptions, re as resetPasswordOptions, Se as revokeMultiSessionOptions, Xe as revokeSessionOptions, ae as sendVerificationEmailOptions, G as sessionOptions, we as setActiveSessionOptions, se as signInEmailOptions, he as signInMagicLinkOptions, Fe as signInPasskeyOptions, le as signInSocialOptions, lt as signInUsernameOptions, de as signOutOptions, pe as signUpEmailOptions, rt as unlinkAccountOptions, at as updateUserOptions, ht as useAccountInfo, Me as useAddPasskey, r as useAuth, X as useAuthMutation, Z as useAuthPlugin, $ as useAuthQuery, q as useAuthenticate, Re as useChangeEmail, Be as useChangePassword, Pe as useDeletePasskey, He as useDeleteUser, t as useFetchOptions, ct as useIsUsernameAvailable, We as useLinkSocial, nt as useListAccounts, xe as useListDeviceSessions, Ae as useListPasskeys, Ye as useListSessions, ne as useRequestPasswordReset, ie as useResetPassword, Ce as useRevokeMultiSession, Ze as useRevokeSession, oe as useSendVerificationEmail, K as useSession, Te as useSetActiveSession, ce as useSignInEmail, ge as useSignInMagicLink, Ie as useSignInPasskey, ue as useSignInSocial, ut as useSignInUsername, fe as useSignOut, me as useSignUpEmail, it as useUnlinkAccount, ot as useUpdateUser, J as useUser };
@@ -26,6 +26,8 @@ export type UserMenuItemProps = {
26
26
  export type AuthPluginComponents = {
27
27
  /** Rendered below the submit button in auth forms. */
28
28
  authButtons?: ComponentType<AuthButtonProps>[];
29
+ /** Captcha widget rendered above the submit button, below additionalFields. Singular — only one captcha can be active at a time. */
30
+ captchaComponent?: ReactNode;
29
31
  /** Rendered as cards inside security settings. */
30
32
  securityCards?: ComponentType<SecurityCardProps>[];
31
33
  /** Rendered as cards inside account settings. */
@@ -0,0 +1,29 @@
1
+ import { ComponentType } from 'react';
2
+ /** Props passed to the consumer's `render` component. */
3
+ export type CaptchaRenderProps = {
4
+ /** Call once the user solves the captcha. */
5
+ setToken: (token: string) => void;
6
+ /** Call on error/expire to clear the token. */
7
+ clearToken: () => void;
8
+ /**
9
+ * Register your widget's `reset()`. Forms call it after a failed
10
+ * submission since captcha tokens are single-use. Pass `null` on unmount.
11
+ */
12
+ setReset: (reset: (() => void) | null) => void;
13
+ };
14
+ export type CaptchaPluginOptions = {
15
+ /** Renders the captcha widget. Wire `setToken`, `clearToken`, `setReset`. */
16
+ render: ComponentType<CaptchaRenderProps>;
17
+ };
18
+ /**
19
+ * Provider-agnostic captcha plugin. Forwards the resolved token via the
20
+ * `x-captcha-response` header on Better Auth requests.
21
+ */
22
+ export declare const captchaPlugin: ((args_0: CaptchaPluginOptions) => Omit<{
23
+ render: ComponentType<CaptchaRenderProps>;
24
+ captchaComponent: import("react/jsx-runtime").JSX.Element;
25
+ }, "id"> & {
26
+ id: "captcha";
27
+ }) & {
28
+ id: "captcha";
29
+ };
@@ -0,0 +1,29 @@
1
+ "use client";
2
+ import { useFetchOptions as e } from "../components/auth/fetch-options-provider.js";
3
+ import { useAuthPlugin as t } from "../hooks/use-auth-plugin.js";
4
+ import { createAuthPlugin as n } from "@better-auth-ui/core";
5
+ import { useCallback as r, useEffect as i } from "react";
6
+ import { jsx as a } from "react/jsx-runtime";
7
+ //#region src/plugins/captcha-plugin.tsx
8
+ function o() {
9
+ let { render: n } = t(s), { setFetchOptions: o, registerReset: c } = e(), l = r((e) => {
10
+ o({ headers: { "x-captcha-response": e } });
11
+ }, [o]), u = r(() => {
12
+ o(void 0);
13
+ }, [o]), d = r((e) => {
14
+ c(e);
15
+ }, [c]);
16
+ return i(() => () => {
17
+ o(void 0), c(null);
18
+ }, [o, c]), /* @__PURE__ */ a(n, {
19
+ setToken: l,
20
+ clearToken: u,
21
+ setReset: d
22
+ });
23
+ }
24
+ var s = n("captcha", ({ render: e }) => ({
25
+ render: e,
26
+ captchaComponent: /* @__PURE__ */ a(o, {})
27
+ }));
28
+ //#endregion
29
+ export { s as captchaPlugin };
@@ -0,0 +1 @@
1
+ export * from './plugins/captcha-plugin';
@@ -0,0 +1,3 @@
1
+ "use client";
2
+ import { captchaPlugin as e } from "./plugins/captcha-plugin.js";
3
+ export { e as captchaPlugin };
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@better-auth-ui/react",
3
- "version": "1.6.4",
3
+ "version": "1.6.6",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "build": "vite build",
7
- "dev": "vite build --watch",
7
+ "dev": "tsc --watch",
8
8
  "email": "email dev --dir src/components/auth/email -p 9000",
9
9
  "test": "vitest"
10
10
  },
@@ -26,13 +26,17 @@
26
26
  "./server": {
27
27
  "types": "./dist/server.d.ts",
28
28
  "import": "./dist/server.js"
29
+ },
30
+ "./plugins": {
31
+ "types": "./dist/plugins.d.ts",
32
+ "import": "./dist/plugins.js"
29
33
  }
30
34
  },
31
35
  "devDependencies": {
32
36
  "@better-auth/passkey": "^1.6.9",
33
37
  "@react-email/components": "^1.0.12",
34
38
  "@react-email/preview-server": "^5.2.10",
35
- "@tanstack/react-query": "^5.100.8",
39
+ "@tanstack/react-query": "^5.100.9",
36
40
  "@testing-library/react": "^16.3.2",
37
41
  "@testing-library/user-event": "^14.5.2",
38
42
  "@types/react": "^19.2.14",
@@ -41,26 +45,26 @@
41
45
  "better-auth": "^1.6.9",
42
46
  "clsx": "^2.1.1",
43
47
  "playwright": "^1.59.1",
44
- "react": "^19.2.5",
45
- "react-dom": "^19.2.5",
46
- "react-email": "^6.0.5",
48
+ "react": "^19.2.6",
49
+ "react-dom": "^19.2.6",
50
+ "react-email": "^6.1.1",
47
51
  "tailwind-merge": "^3.5.0",
48
- "tailwindcss": "^4.2.4",
52
+ "tailwindcss": "^4.3.0",
49
53
  "vitest": "^4.1.5",
50
- "zod": "^4.4.2"
54
+ "zod": "^4.4.3"
51
55
  },
52
56
  "peerDependencies": {
53
57
  "@better-auth-ui/core": "*",
54
58
  "@better-auth/passkey": ">=1.6.9",
55
59
  "@react-email/components": ">=1.0.12",
56
- "@tanstack/react-query": ">=5.100.8",
60
+ "@tanstack/react-query": ">=5.100.9",
57
61
  "better-auth": ">=1.6.9",
58
62
  "clsx": ">=2.0.0",
59
- "react": ">=19.2.5",
60
- "react-dom": ">=19.2.5",
63
+ "react": ">=19.2.6",
64
+ "react-dom": ">=19.2.6",
61
65
  "tailwind-merge": ">=3.5.0",
62
- "tailwindcss": ">=4.2.4",
63
- "zod": ">=4.4.2"
66
+ "tailwindcss": ">=4.3.0",
67
+ "zod": ">=4.4.3"
64
68
  },
65
69
  "repository": {
66
70
  "type": "git",
@@ -18,8 +18,8 @@ import {
18
18
  type ReactNode,
19
19
  useContext
20
20
  } from "react"
21
-
22
21
  import type { AuthClient } from "../../lib/auth-client"
22
+ import { FetchOptionsProvider } from "./fetch-options-provider"
23
23
 
24
24
  const AuthContext = createContext<AuthConfig | undefined>(undefined)
25
25
 
@@ -108,7 +108,7 @@ export function AuthProvider({
108
108
  if (contextQueryClient) {
109
109
  return (
110
110
  <AuthContext.Provider value={mergedConfig}>
111
- {children}
111
+ <FetchOptionsProvider>{children}</FetchOptionsProvider>
112
112
  </AuthContext.Provider>
113
113
  )
114
114
  }
@@ -116,7 +116,7 @@ export function AuthProvider({
116
116
  return (
117
117
  <QueryClientProvider client={queryClient || fallbackQueryClient}>
118
118
  <AuthContext.Provider value={mergedConfig}>
119
- {children}
119
+ <FetchOptionsProvider>{children}</FetchOptionsProvider>
120
120
  </AuthContext.Provider>
121
121
  </QueryClientProvider>
122
122
  )
@@ -0,0 +1,77 @@
1
+ "use client"
2
+
3
+ import {
4
+ createContext,
5
+ type PropsWithChildren,
6
+ useCallback,
7
+ useContext,
8
+ useRef,
9
+ useState
10
+ } from "react"
11
+
12
+ /** Subset of BetterFetchOptions we expose. Add fields as use-cases arise. */
13
+ export type FetchOptions = {
14
+ headers?: Record<string, string>
15
+ body?: Record<string, unknown>
16
+ }
17
+
18
+ type FetchOptionsContextValue = {
19
+ /** Current fetchOptions, or `undefined` when none are set. */
20
+ fetchOptions: FetchOptions | undefined
21
+ /** OVERRIDES the entire fetchOptions object. Pass `undefined` to clear. */
22
+ setFetchOptions: (fetchOptions: FetchOptions | undefined) => void
23
+ /** Clears `fetchOptions` and runs the registered reset (e.g. captcha widget). Call from form `onError`. */
24
+ resetFetchOptions: () => void
25
+ /** Register a reset handler. Used by `captchaPlugin`. Pass `null` to clear. */
26
+ registerReset: (reset: (() => void) | null) => void
27
+ }
28
+
29
+ const FetchOptionsContext = createContext<FetchOptionsContextValue | undefined>(
30
+ undefined
31
+ )
32
+
33
+ export function FetchOptionsProvider({ children }: PropsWithChildren) {
34
+ const [current, setCurrent] = useState<FetchOptions | undefined>(undefined)
35
+ const resetRef = useRef<(() => void) | null>(null)
36
+
37
+ const setFetchOptions = useCallback(
38
+ (fetchOptions: FetchOptions | undefined) => {
39
+ setCurrent(fetchOptions)
40
+ },
41
+ []
42
+ )
43
+
44
+ const registerReset = useCallback((reset: (() => void) | null) => {
45
+ resetRef.current = reset
46
+ }, [])
47
+
48
+ const resetFetchOptions = useCallback(() => {
49
+ setCurrent(undefined)
50
+ resetRef.current?.()
51
+ }, [])
52
+
53
+ return (
54
+ <FetchOptionsContext.Provider
55
+ value={{
56
+ fetchOptions: current,
57
+ setFetchOptions,
58
+ resetFetchOptions,
59
+ registerReset
60
+ }}
61
+ >
62
+ {children}
63
+ </FetchOptionsContext.Provider>
64
+ )
65
+ }
66
+
67
+ export function useFetchOptions(): FetchOptionsContextValue {
68
+ const ctx = useContext(FetchOptionsContext)
69
+
70
+ if (!ctx) {
71
+ throw new Error(
72
+ "[Better Auth UI] useFetchOptions must be used within FetchOptionsProvider"
73
+ )
74
+ }
75
+
76
+ return ctx
77
+ }
package/src/index.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  "use client"
2
2
 
3
3
  export * from "./components/auth/auth-provider"
4
+ export * from "./components/auth/fetch-options-provider"
4
5
  export * from "./components/icons"
5
6
  export * from "./components/settings/account/theme-preview"
6
7
  export * from "./hooks/auth/use-authenticate"
@@ -32,6 +32,8 @@ export type UserMenuItemProps = {
32
32
  export type AuthPluginComponents = {
33
33
  /** Rendered below the submit button in auth forms. */
34
34
  authButtons?: ComponentType<AuthButtonProps>[]
35
+ /** Captcha widget rendered above the submit button, below additionalFields. Singular — only one captcha can be active at a time. */
36
+ captchaComponent?: ReactNode
35
37
  /** Rendered as cards inside security settings. */
36
38
  securityCards?: ComponentType<SecurityCardProps>[]
37
39
  /** Rendered as cards inside account settings. */
@@ -0,0 +1,75 @@
1
+ "use client"
2
+
3
+ import { createAuthPlugin } from "@better-auth-ui/core"
4
+ import {
5
+ type ComponentType,
6
+ type ReactNode,
7
+ useCallback,
8
+ useEffect
9
+ } from "react"
10
+ import { useFetchOptions } from "../components/auth/fetch-options-provider"
11
+ import { useAuthPlugin } from "../hooks/use-auth-plugin"
12
+
13
+ /** Props passed to the consumer's `render` component. */
14
+ export type CaptchaRenderProps = {
15
+ /** Call once the user solves the captcha. */
16
+ setToken: (token: string) => void
17
+ /** Call on error/expire to clear the token. */
18
+ clearToken: () => void
19
+ /**
20
+ * Register your widget's `reset()`. Forms call it after a failed
21
+ * submission since captcha tokens are single-use. Pass `null` on unmount.
22
+ */
23
+ setReset: (reset: (() => void) | null) => void
24
+ }
25
+
26
+ export type CaptchaPluginOptions = {
27
+ /** Renders the captcha widget. Wire `setToken`, `clearToken`, `setReset`. */
28
+ render: ComponentType<CaptchaRenderProps>
29
+ }
30
+
31
+ function CaptchaWidget(): ReactNode {
32
+ const { render: Render } = useAuthPlugin(captchaPlugin)
33
+ const { setFetchOptions, registerReset } = useFetchOptions()
34
+
35
+ const setToken = useCallback(
36
+ (token: string) => {
37
+ setFetchOptions({ headers: { "x-captcha-response": token } })
38
+ },
39
+ [setFetchOptions]
40
+ )
41
+
42
+ const clearToken = useCallback(() => {
43
+ setFetchOptions(undefined)
44
+ }, [setFetchOptions])
45
+
46
+ const setReset = useCallback(
47
+ (reset: (() => void) | null) => {
48
+ registerReset(reset)
49
+ },
50
+ [registerReset]
51
+ )
52
+
53
+ useEffect(() => {
54
+ return () => {
55
+ setFetchOptions(undefined)
56
+ registerReset(null)
57
+ }
58
+ }, [setFetchOptions, registerReset])
59
+
60
+ return (
61
+ <Render setToken={setToken} clearToken={clearToken} setReset={setReset} />
62
+ )
63
+ }
64
+
65
+ /**
66
+ * Provider-agnostic captcha plugin. Forwards the resolved token via the
67
+ * `x-captcha-response` header on Better Auth requests.
68
+ */
69
+ export const captchaPlugin = createAuthPlugin(
70
+ "captcha",
71
+ ({ render }: CaptchaPluginOptions) => ({
72
+ render,
73
+ captchaComponent: <CaptchaWidget />
74
+ })
75
+ )
package/src/plugins.ts ADDED
@@ -0,0 +1,3 @@
1
+ "use client"
2
+
3
+ export * from "./plugins/captcha-plugin"