@better-auth-ui/react 1.6.4 → 1.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/auth/auth-provider.js +28 -27
- package/dist/components/auth/fetch-options-provider.d.ts +19 -0
- package/dist/components/auth/fetch-options-provider.js +30 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +75 -74
- package/dist/lib/auth-plugin.d.ts +2 -0
- package/dist/plugins/captcha-plugin.d.ts +29 -0
- package/dist/plugins/captcha-plugin.js +29 -0
- package/dist/plugins.d.ts +1 -0
- package/dist/plugins.js +3 -0
- package/package.json +5 -1
- package/src/components/auth/auth-provider.tsx +3 -3
- package/src/components/auth/fetch-options-provider.tsx +77 -0
- package/src/index.ts +1 -0
- package/src/lib/auth-plugin.ts +2 -0
- package/src/plugins/captcha-plugin.tsx +75 -0
- package/src/plugins.ts +3 -0
|
@@ -1,43 +1,44 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
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
|
|
8
|
-
function
|
|
9
|
-
let
|
|
10
|
-
...
|
|
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
|
-
...
|
|
14
|
-
...
|
|
14
|
+
...n.viewPaths.auth,
|
|
15
|
+
...d.viewPaths?.auth
|
|
15
16
|
},
|
|
16
17
|
settings: {
|
|
17
|
-
...
|
|
18
|
-
...
|
|
18
|
+
...n.viewPaths.settings,
|
|
19
|
+
...d.viewPaths?.settings
|
|
19
20
|
}
|
|
20
21
|
}
|
|
21
22
|
});
|
|
22
|
-
|
|
23
|
-
let
|
|
24
|
-
for (let e of
|
|
25
|
-
for (let e of
|
|
26
|
-
return
|
|
27
|
-
value:
|
|
28
|
-
children:
|
|
29
|
-
}) : /* @__PURE__ */
|
|
30
|
-
client:
|
|
31
|
-
children: /* @__PURE__ */
|
|
32
|
-
value:
|
|
33
|
-
children:
|
|
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
|
|
38
|
-
let e =
|
|
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 {
|
|
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
package/dist/index.js
CHANGED
|
@@ -1,76 +1,77 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
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
|
-
import {
|
|
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
|
|
40
|
-
import { ensureSession as
|
|
41
|
-
import { useAuthenticate as
|
|
42
|
-
import { useUser as
|
|
43
|
-
import { authMutationOptions as
|
|
44
|
-
import { useAuthMutation as
|
|
45
|
-
import { useAuthPlugin as
|
|
46
|
-
import { authQueryOptions as
|
|
47
|
-
import { useAuthQuery as
|
|
48
|
-
import { providerIcons as
|
|
49
|
-
import { requestPasswordResetOptions as
|
|
50
|
-
import { resetPasswordOptions as
|
|
51
|
-
import { sendVerificationEmailOptions as
|
|
52
|
-
import { signInEmailOptions as
|
|
53
|
-
import { signInSocialOptions as
|
|
54
|
-
import { signOutOptions as
|
|
55
|
-
import { signUpEmailOptions as
|
|
56
|
-
import { signInMagicLinkOptions as
|
|
57
|
-
import { ensureListDeviceSessions as
|
|
58
|
-
import { revokeMultiSessionOptions as
|
|
59
|
-
import { setActiveSessionOptions as
|
|
60
|
-
import { ensureListPasskeys as
|
|
61
|
-
import { addPasskeyOptions as
|
|
62
|
-
import { deletePasskeyOptions as
|
|
63
|
-
import { signInPasskeyOptions as
|
|
64
|
-
import { changeEmailOptions as
|
|
65
|
-
import { changePasswordOptions as
|
|
66
|
-
import { deleteUserOptions as
|
|
67
|
-
import { linkSocialOptions as
|
|
68
|
-
import { ensureListSessions as
|
|
69
|
-
import { revokeSessionOptions as
|
|
70
|
-
import { ensureListAccounts as
|
|
71
|
-
import { unlinkAccountOptions as
|
|
72
|
-
import { updateUserOptions as
|
|
73
|
-
import { isUsernameAvailableOptions as
|
|
74
|
-
import { signInUsernameOptions as
|
|
75
|
-
import { accountInfoOptions as
|
|
76
|
-
export {
|
|
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';
|
package/dist/plugins.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@better-auth-ui/react",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "vite build",
|
|
@@ -26,6 +26,10 @@
|
|
|
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": {
|
|
@@ -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"
|
package/src/lib/auth-plugin.ts
CHANGED
|
@@ -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