@better-auth-ui/heroui 1.6.0
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/account/account.d.ts +18 -0
- package/dist/components/account/account.js +24 -0
- package/dist/components/account/settings/account-settings.d.ts +5 -0
- package/dist/components/account/settings/account-settings.js +6 -0
- package/dist/components/account/settings/settings.d.ts +5 -0
- package/dist/components/account/settings/settings.js +5 -0
- package/dist/components/account/settings/user-profile.d.ts +5 -0
- package/dist/components/account/settings/user-profile.js +20 -0
- package/dist/components/auth/auth-provider.d.ts +9 -0
- package/dist/components/auth/auth-provider.js +12 -0
- package/dist/components/auth/auth.d.ts +23 -0
- package/dist/components/auth/auth.js +42 -0
- package/dist/components/auth/field-separator.d.ts +4 -0
- package/dist/components/auth/field-separator.js +5 -0
- package/dist/components/auth/forgot-password.d.ts +15 -0
- package/dist/components/auth/forgot-password.js +28 -0
- package/dist/components/auth/magic-link-button.d.ts +13 -0
- package/dist/components/auth/magic-link-button.js +19 -0
- package/dist/components/auth/magic-link.d.ts +17 -0
- package/dist/components/auth/magic-link.js +43 -0
- package/dist/components/auth/provider-buttons.d.ts +19 -0
- package/dist/components/auth/provider-buttons.js +34 -0
- package/dist/components/auth/reset-password.d.ts +11 -0
- package/dist/components/auth/reset-password.js +58 -0
- package/dist/components/auth/sign-in.d.ts +14 -0
- package/dist/components/auth/sign-in.js +64 -0
- package/dist/components/auth/sign-out.d.ts +9 -0
- package/dist/components/auth/sign-out.js +33 -0
- package/dist/components/auth/sign-up.d.ts +19 -0
- package/dist/components/auth/sign-up.js +71 -0
- package/dist/components/email/email-changed-email.d.ts +3 -0
- package/dist/components/email/email-changed-email.js +23 -0
- package/dist/components/email/email-verification-email.d.ts +3 -0
- package/dist/components/email/email-verification-email.js +23 -0
- package/dist/components/email/magic-link-email.d.ts +3 -0
- package/dist/components/email/magic-link-email.js +23 -0
- package/dist/components/email/new-device-email.d.ts +3 -0
- package/dist/components/email/new-device-email.js +23 -0
- package/dist/components/email/otp-email.d.ts +3 -0
- package/dist/components/email/otp-email.js +22 -0
- package/dist/components/email/password-changed-email.d.ts +3 -0
- package/dist/components/email/password-changed-email.js +23 -0
- package/dist/components/email/reset-password-email.d.ts +3 -0
- package/dist/components/email/reset-password-email.js +23 -0
- package/dist/components/settings/account/account-settings.d.ts +16 -0
- package/dist/components/settings/account/account-settings.js +20 -0
- package/dist/components/settings/account/accounts.d.ts +14 -0
- package/dist/components/settings/account/accounts.js +26 -0
- package/dist/components/settings/account/appearance.d.ts +16 -0
- package/dist/components/settings/account/appearance.js +28 -0
- package/dist/components/settings/account/change-avatar.d.ts +4 -0
- package/dist/components/settings/account/change-avatar.js +56 -0
- package/dist/components/settings/account/change-email.d.ts +15 -0
- package/dist/components/settings/account/change-email.js +29 -0
- package/dist/components/settings/account/manage-account.d.ts +19 -0
- package/dist/components/settings/account/manage-account.js +32 -0
- package/dist/components/settings/account/manage-accounts.d.ts +14 -0
- package/dist/components/settings/account/manage-accounts.js +37 -0
- package/dist/components/settings/account/theme-selector.d.ts +16 -0
- package/dist/components/settings/account/theme-selector.js +33 -0
- package/dist/components/settings/account/theme-settings.d.ts +16 -0
- package/dist/components/settings/account/theme-settings.js +31 -0
- package/dist/components/settings/account/user-profile.d.ts +11 -0
- package/dist/components/settings/account/user-profile.js +23 -0
- package/dist/components/settings/account-settings.d.ts +5 -0
- package/dist/components/settings/account-settings.js +6 -0
- package/dist/components/settings/account.d.ts +18 -0
- package/dist/components/settings/account.js +24 -0
- package/dist/components/settings/security/active-session.d.ts +14 -0
- package/dist/components/settings/security/active-session.js +53 -0
- package/dist/components/settings/security/active-sessions.d.ts +14 -0
- package/dist/components/settings/security/active-sessions.js +28 -0
- package/dist/components/settings/security/change-password.d.ts +15 -0
- package/dist/components/settings/security/change-password.js +79 -0
- package/dist/components/settings/security/connected-account.d.ts +16 -0
- package/dist/components/settings/security/connected-account.js +46 -0
- package/dist/components/settings/security/connected-accounts.d.ts +15 -0
- package/dist/components/settings/security/connected-accounts.js +31 -0
- package/dist/components/settings/security/danger-zone.d.ts +11 -0
- package/dist/components/settings/security/danger-zone.js +12 -0
- package/dist/components/settings/security/delete-user.d.ts +9 -0
- package/dist/components/settings/security/delete-user.js +47 -0
- package/dist/components/settings/security/linked-account.d.ts +16 -0
- package/dist/components/settings/security/linked-account.js +48 -0
- package/dist/components/settings/security/linked-accounts.d.ts +15 -0
- package/dist/components/settings/security/linked-accounts.js +42 -0
- package/dist/components/settings/security/security-settings.d.ts +17 -0
- package/dist/components/settings/security/security-settings.js +21 -0
- package/dist/components/settings/security/sessions.d.ts +14 -0
- package/dist/components/settings/security/sessions.js +40 -0
- package/dist/components/settings/settings/account-settings.d.ts +5 -0
- package/dist/components/settings/settings/account-settings.js +6 -0
- package/dist/components/settings/settings/user-profile.d.ts +5 -0
- package/dist/components/settings/settings/user-profile.js +20 -0
- package/dist/components/settings/settings.d.ts +24 -0
- package/dist/components/settings/settings.js +28 -0
- package/dist/components/settings/user-profile.d.ts +5 -0
- package/dist/components/settings/user-profile.js +20 -0
- package/dist/components/user/switch-account-item.d.ts +16 -0
- package/dist/components/user/switch-account-item.js +16 -0
- package/dist/components/user/switch-account-menu.d.ts +10 -0
- package/dist/components/user/switch-account-menu.js +29 -0
- package/dist/components/user/switch-account-popover.d.ts +10 -0
- package/dist/components/user/switch-account-popover.js +25 -0
- package/dist/components/user/switch-account-submenu.d.ts +10 -0
- package/dist/components/user/switch-account-submenu.js +25 -0
- package/dist/components/user/user-avatar.d.ts +25 -0
- package/dist/components/user/user-avatar.js +31 -0
- package/dist/components/user/user-button.d.ts +25 -0
- package/dist/components/user/user-button.js +24 -0
- package/dist/components/user/user-view.d.ts +22 -0
- package/dist/components/user/user-view.js +24 -0
- package/dist/core.d.ts +1 -0
- package/dist/core.js +1 -0
- package/dist/hooks/use-auth.d.ts +2 -0
- package/dist/hooks/use-auth.js +8 -0
- package/dist/hooks/use-redirect-to.d.ts +8 -0
- package/dist/hooks/use-redirect-to.js +19 -0
- package/dist/hooks/use-sign-in.d.ts +8 -0
- package/dist/hooks/use-sign-in.js +53 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +34 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/lib/utils.js +5 -0
- package/dist/react-exports.d.ts +1 -0
- package/dist/react-exports.js +1 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +1 -0
- package/dist/src/components/auth/auth-provider.d.ts +8 -0
- package/dist/src/components/auth/auth-provider.js +13 -0
- package/dist/src/components/auth/auth.d.ts +22 -0
- package/dist/src/components/auth/auth.js +42 -0
- package/dist/src/components/auth/field-separator.d.ts +4 -0
- package/dist/src/components/auth/field-separator.js +5 -0
- package/dist/src/components/auth/forgot-password.d.ts +15 -0
- package/dist/src/components/auth/forgot-password.js +29 -0
- package/dist/src/components/auth/magic-link-button.d.ts +13 -0
- package/dist/src/components/auth/magic-link-button.js +20 -0
- package/dist/src/components/auth/magic-link.d.ts +17 -0
- package/dist/src/components/auth/magic-link.js +37 -0
- package/dist/src/components/auth/provider-buttons.d.ts +19 -0
- package/dist/src/components/auth/provider-buttons.js +35 -0
- package/dist/src/components/auth/reset-password.d.ts +11 -0
- package/dist/src/components/auth/reset-password.js +59 -0
- package/dist/src/components/auth/sign-in.d.ts +14 -0
- package/dist/src/components/auth/sign-in.js +58 -0
- package/dist/src/components/auth/sign-out.d.ts +11 -0
- package/dist/src/components/auth/sign-out.js +34 -0
- package/dist/src/components/auth/sign-up.d.ts +19 -0
- package/dist/src/components/auth/sign-up.js +65 -0
- package/dist/src/components/email/email-changed-email.d.ts +3 -0
- package/dist/src/components/email/email-changed-email.js +23 -0
- package/dist/src/components/email/email-verification-email.d.ts +3 -0
- package/dist/src/components/email/email-verification-email.js +23 -0
- package/dist/src/components/email/magic-link-email.d.ts +3 -0
- package/dist/src/components/email/magic-link-email.js +23 -0
- package/dist/src/components/email/new-device-email.d.ts +3 -0
- package/dist/src/components/email/new-device-email.js +23 -0
- package/dist/src/components/email/otp-email.d.ts +3 -0
- package/dist/src/components/email/otp-email.js +22 -0
- package/dist/src/components/email/password-changed-email.d.ts +3 -0
- package/dist/src/components/email/password-changed-email.js +23 -0
- package/dist/src/components/email/reset-password-email.d.ts +3 -0
- package/dist/src/components/email/reset-password-email.js +23 -0
- package/dist/src/components/settings/account/account-settings.d.ts +13 -0
- package/dist/src/components/settings/account/account-settings.js +19 -0
- package/dist/src/components/settings/account/appearance.d.ts +16 -0
- package/dist/src/components/settings/account/appearance.js +28 -0
- package/dist/src/components/settings/account/change-email.d.ts +15 -0
- package/dist/src/components/settings/account/change-email.js +35 -0
- package/dist/src/components/settings/account/manage-account.d.ts +19 -0
- package/dist/src/components/settings/account/manage-account.js +27 -0
- package/dist/src/components/settings/account/manage-accounts.d.ts +14 -0
- package/dist/src/components/settings/account/manage-accounts.js +27 -0
- package/dist/src/components/settings/account/user-profile.d.ts +13 -0
- package/dist/src/components/settings/account/user-profile.js +29 -0
- package/dist/src/components/settings/security/active-session.d.ts +14 -0
- package/dist/src/components/settings/security/active-session.js +35 -0
- package/dist/src/components/settings/security/active-sessions.d.ts +14 -0
- package/dist/src/components/settings/security/active-sessions.js +29 -0
- package/dist/src/components/settings/security/change-password.d.ts +15 -0
- package/dist/src/components/settings/security/change-password.js +57 -0
- package/dist/src/components/settings/security/linked-account.d.ts +16 -0
- package/dist/src/components/settings/security/linked-account.js +46 -0
- package/dist/src/components/settings/security/linked-accounts.d.ts +15 -0
- package/dist/src/components/settings/security/linked-accounts.js +31 -0
- package/dist/src/components/settings/security/security-settings.d.ts +15 -0
- package/dist/src/components/settings/security/security-settings.js +18 -0
- package/dist/src/components/settings/settings.d.ts +29 -0
- package/dist/src/components/settings/settings.js +39 -0
- package/dist/src/components/user/switch-account-item.d.ts +16 -0
- package/dist/src/components/user/switch-account-item.js +14 -0
- package/dist/src/components/user/switch-account-menu.d.ts +10 -0
- package/dist/src/components/user/switch-account-menu.js +23 -0
- package/dist/src/components/user/user-avatar.d.ts +24 -0
- package/dist/src/components/user/user-avatar.js +31 -0
- package/dist/src/components/user/user-button.d.ts +21 -0
- package/dist/src/components/user/user-button.js +24 -0
- package/dist/src/components/user/user-view.d.ts +21 -0
- package/dist/src/components/user/user-view.js +24 -0
- package/dist/src/core.d.ts +1 -0
- package/dist/src/core.js +1 -0
- package/dist/src/index.d.ts +31 -0
- package/dist/src/index.js +32 -0
- package/dist/src/lib/utils.d.ts +2 -0
- package/dist/src/lib/utils.js +5 -0
- package/dist/src/react-exports.d.ts +1 -0
- package/dist/src/react-exports.js +1 -0
- package/dist/styles.css +1 -0
- package/package.json +63 -0
- package/src/components/auth/auth-provider.tsx +27 -0
- package/src/components/auth/auth.tsx +87 -0
- package/src/components/auth/field-separator.tsx +14 -0
- package/src/components/auth/forgot-password.tsx +107 -0
- package/src/components/auth/magic-link-button.tsx +43 -0
- package/src/components/auth/magic-link.tsx +181 -0
- package/src/components/auth/provider-buttons.tsx +85 -0
- package/src/components/auth/reset-password.tsx +210 -0
- package/src/components/auth/sign-in.tsx +260 -0
- package/src/components/auth/sign-out.tsx +44 -0
- package/src/components/auth/sign-up.tsx +314 -0
- package/src/components/email/email-changed-email.tsx +38 -0
- package/src/components/email/email-verification-email.tsx +38 -0
- package/src/components/email/magic-link-email.tsx +38 -0
- package/src/components/email/new-device-email.tsx +38 -0
- package/src/components/email/otp-email.tsx +33 -0
- package/src/components/email/password-changed-email.tsx +38 -0
- package/src/components/email/reset-password-email.tsx +38 -0
- package/src/components/settings/account/account-settings.tsx +48 -0
- package/src/components/settings/account/appearance.tsx +157 -0
- package/src/components/settings/account/change-avatar.tsx +142 -0
- package/src/components/settings/account/change-email.tsx +111 -0
- package/src/components/settings/account/manage-account.tsx +123 -0
- package/src/components/settings/account/manage-accounts.tsx +78 -0
- package/src/components/settings/account/user-profile.tsx +103 -0
- package/src/components/settings/security/active-session.tsx +123 -0
- package/src/components/settings/security/active-sessions.tsx +77 -0
- package/src/components/settings/security/change-password.tsx +335 -0
- package/src/components/settings/security/danger-zone.tsx +32 -0
- package/src/components/settings/security/delete-user.tsx +187 -0
- package/src/components/settings/security/linked-account.tsx +136 -0
- package/src/components/settings/security/linked-accounts.tsx +98 -0
- package/src/components/settings/security/security-settings.tsx +43 -0
- package/src/components/settings/settings.tsx +96 -0
- package/src/components/user/switch-account-item.tsx +39 -0
- package/src/components/user/switch-account-menu.tsx +64 -0
- package/src/components/user/user-avatar.tsx +88 -0
- package/src/components/user/user-button.tsx +221 -0
- package/src/components/user/user-view.tsx +74 -0
- package/src/core.ts +1 -0
- package/src/index.tsx +35 -0
- package/src/react-exports.ts +1 -0
- package/src/styles.css +1 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useAuth, useListDeviceSessions, useSession, useSetActiveSession } from "@better-auth-ui/react";
|
|
3
|
+
import { Check, CirclePlus } from "@gravity-ui/icons";
|
|
4
|
+
import { Dropdown, Label, Separator } from "@heroui/react";
|
|
5
|
+
import { UserView } from "./user-view";
|
|
6
|
+
/**
|
|
7
|
+
* Render the popover content for switching between multiple authenticated sessions.
|
|
8
|
+
*
|
|
9
|
+
* Shows the current session with a checkmark, lists other device sessions that can be activated,
|
|
10
|
+
* and provides an option to add a new account. This component should be rendered inside a
|
|
11
|
+
* Dropdown.SubmenuTrigger to defer the useListDeviceSessions query until the submenu is opened.
|
|
12
|
+
*
|
|
13
|
+
* @returns The switch account submenu popover content as a JSX element
|
|
14
|
+
*/
|
|
15
|
+
export function SwitchAccountSubmenu() {
|
|
16
|
+
const { basePaths, viewPaths, localization } = useAuth();
|
|
17
|
+
const { settingActiveSession, setActiveSession } = useSetActiveSession();
|
|
18
|
+
const { data: sessionData } = useSession();
|
|
19
|
+
const { data: deviceSessions } = useListDeviceSessions();
|
|
20
|
+
return (_jsx(Dropdown.Popover, { className: "min-w-40 md:min-w-56 max-w-[48svw]", children: _jsxs(Dropdown.Menu, { children: [_jsxs(Dropdown.Item, { className: "px-2", children: [_jsx(UserView, {}), _jsx(Check, { className: "ml-auto" })] }), deviceSessions
|
|
21
|
+
?.filter((deviceSession) => deviceSession.session.id !== sessionData?.session?.id)
|
|
22
|
+
.map((deviceSession) => {
|
|
23
|
+
return (_jsx(Dropdown.Item, { className: "px-2", isDisabled: !!settingActiveSession, onPress: () => setActiveSession(deviceSession.session.token), children: _jsx(UserView, { user: deviceSession.user }) }, deviceSession.session.id));
|
|
24
|
+
}), _jsx(Separator, {}), _jsxs(Dropdown.Item, { textValue: localization.auth.addAccount, href: `${basePaths.auth}/${viewPaths.auth.signIn}`, children: [_jsx(CirclePlus, { className: "text-muted" }), _jsx(Label, { children: localization.auth.addAccount })] })] }) }));
|
|
25
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type AvatarProps } from "@heroui/react";
|
|
2
|
+
import type { User } from "better-auth";
|
|
3
|
+
import type { ReactNode } from "react";
|
|
4
|
+
export type UserAvatarProps = {
|
|
5
|
+
className?: string;
|
|
6
|
+
fallback?: ReactNode;
|
|
7
|
+
isPending?: boolean;
|
|
8
|
+
/** @remarks `User` */
|
|
9
|
+
user?: User & {
|
|
10
|
+
username?: string | null;
|
|
11
|
+
displayUsername?: string | null;
|
|
12
|
+
};
|
|
13
|
+
size?: AvatarProps["size"];
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Render a user avatar that shows the user's image, initials, or a custom fallback; displays a circular skeleton while the session (or explicit pending flag) is pending.
|
|
17
|
+
*
|
|
18
|
+
* @param className - Additional CSS classes applied to the outer avatar container
|
|
19
|
+
* @param fallback - Custom fallback content to render when no image or initials are available
|
|
20
|
+
* @param isPending - When true, force rendering of the loading skeleton (unless an explicit `user` prop is provided)
|
|
21
|
+
* @param user - Optional user object to display; when omitted the current session user is used if available
|
|
22
|
+
* @param size - Visual size of the avatar; one of `"sm"`, `"md"`, or `"lg"` (default: `"sm"`)
|
|
23
|
+
* @returns A React element that displays the user's avatar image, initials, or the provided fallback; renders a circular skeleton while loading
|
|
24
|
+
*/
|
|
25
|
+
export declare function UserAvatar({ className, fallback, isPending, user, size, style, ...props }: UserAvatarProps & AvatarProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useSession } from "@better-auth-ui/react";
|
|
3
|
+
import { Person } from "@gravity-ui/icons";
|
|
4
|
+
import { Avatar, cn, Skeleton } from "@heroui/react";
|
|
5
|
+
/**
|
|
6
|
+
* Render a user avatar that shows the user's image, initials, or a custom fallback; displays a circular skeleton while the session (or explicit pending flag) is pending.
|
|
7
|
+
*
|
|
8
|
+
* @param className - Additional CSS classes applied to the outer avatar container
|
|
9
|
+
* @param fallback - Custom fallback content to render when no image or initials are available
|
|
10
|
+
* @param isPending - When true, force rendering of the loading skeleton (unless an explicit `user` prop is provided)
|
|
11
|
+
* @param user - Optional user object to display; when omitted the current session user is used if available
|
|
12
|
+
* @param size - Visual size of the avatar; one of `"sm"`, `"md"`, or `"lg"` (default: `"sm"`)
|
|
13
|
+
* @returns A React element that displays the user's avatar image, initials, or the provided fallback; renders a circular skeleton while loading
|
|
14
|
+
*/
|
|
15
|
+
export function UserAvatar({ className, fallback, isPending, user, size = "sm", style, ...props }) {
|
|
16
|
+
const { data: session, isPending: sessionPending } = useSession({
|
|
17
|
+
enabled: !user && !isPending
|
|
18
|
+
});
|
|
19
|
+
if ((isPending || sessionPending) && !user) {
|
|
20
|
+
return (_jsx(Skeleton, { className: cn("rounded-full", size === "sm" ? "size-8" : size === "md" ? "size-10" : "size-12", className), style: style }));
|
|
21
|
+
}
|
|
22
|
+
const resolvedUser = user ?? session?.user;
|
|
23
|
+
const initials = (resolvedUser?.username ||
|
|
24
|
+
resolvedUser?.name ||
|
|
25
|
+
resolvedUser?.email)
|
|
26
|
+
?.slice(0, 2)
|
|
27
|
+
.toUpperCase();
|
|
28
|
+
return (_jsxs(Avatar, { size: size, className: cn("rounded-full", className), style: style, ...props, children: [_jsx(Avatar.Image, { alt: resolvedUser?.displayUsername ||
|
|
29
|
+
resolvedUser?.name ||
|
|
30
|
+
resolvedUser?.email, src: resolvedUser?.image ?? undefined }), _jsx(Avatar.Fallback, { className: cn(size === "lg" ? "text-xl" : size === "md" ? "text-base" : "text-sm"), delayMs: resolvedUser?.image ? 600 : undefined, children: fallback || initials || _jsx(Person, { className: "size-4" }) })] }));
|
|
31
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type ButtonProps, type DropdownPopoverProps } from "@heroui/react";
|
|
2
|
+
export type UserButtonProps = {
|
|
3
|
+
className?: string;
|
|
4
|
+
size?: "default" | "icon";
|
|
5
|
+
/**
|
|
6
|
+
* The placement of the element with respect to its anchor element.
|
|
7
|
+
* @default "bottom"
|
|
8
|
+
*/
|
|
9
|
+
placement?: DropdownPopoverProps["placement"];
|
|
10
|
+
themeToggle?: boolean;
|
|
11
|
+
variant?: ButtonProps["variant"];
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Render a user account dropdown button that shows account actions, session switching, and theme controls.
|
|
15
|
+
*
|
|
16
|
+
* Renders either an icon-only trigger or a full button showing the current user state; its dropdown contains account settings, multi-session switching (when enabled), theme selection (when enabled), and sign-in/sign-out flows depending on authentication state.
|
|
17
|
+
*
|
|
18
|
+
* @param className - Additional CSS classes applied to the trigger element
|
|
19
|
+
* @param placement - Dropdown popover placement (e.g., "bottom", "top-start", "bottom-end")
|
|
20
|
+
* @param size - "icon" renders an avatar-only trigger; "default" renders a button with label and chevron
|
|
21
|
+
* @param variant - Button visual variant passed to the underlying Button component
|
|
22
|
+
* @param themeToggle - When true and theming is available, show theme selection controls in the menu
|
|
23
|
+
* @returns The user button and its dropdown menu as a JSX element
|
|
24
|
+
*/
|
|
25
|
+
export declare function UserButton({ className, placement, size, variant, themeToggle }: UserButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useAuth, useSession } from "@better-auth-ui/react";
|
|
3
|
+
import { ArrowRightFromSquare, ArrowRightToSquare, ChevronsExpandVertical, Display, Gear, Moon, PersonPlus, Persons, Sun } from "@gravity-ui/icons";
|
|
4
|
+
import { Button, cn, Dropdown, Label, Separator, Tabs } from "@heroui/react";
|
|
5
|
+
import { SwitchAccountMenu } from "./switch-account-menu";
|
|
6
|
+
import { UserAvatar } from "./user-avatar";
|
|
7
|
+
import { UserView } from "./user-view";
|
|
8
|
+
/**
|
|
9
|
+
* Render a user account dropdown button that shows account actions, session switching, and theme controls.
|
|
10
|
+
*
|
|
11
|
+
* Renders either an icon-only trigger or a full button showing the current user state; its dropdown contains account settings, multi-session switching (when enabled), theme selection (when enabled), and sign-in/sign-out flows depending on authentication state.
|
|
12
|
+
*
|
|
13
|
+
* @param className - Additional CSS classes applied to the trigger element
|
|
14
|
+
* @param placement - Dropdown popover placement (e.g., "bottom", "top-start", "bottom-end")
|
|
15
|
+
* @param size - "icon" renders an avatar-only trigger; "default" renders a button with label and chevron
|
|
16
|
+
* @param variant - Button visual variant passed to the underlying Button component
|
|
17
|
+
* @param themeToggle - When true and theming is available, show theme selection controls in the menu
|
|
18
|
+
* @returns The user button and its dropdown menu as a JSX element
|
|
19
|
+
*/
|
|
20
|
+
export function UserButton({ className, placement = "bottom", size = "default", variant = "ghost", themeToggle = true }) {
|
|
21
|
+
const { basePaths, viewPaths, localization, multiSession, appearance: { theme, setTheme, themes } } = useAuth();
|
|
22
|
+
const { data: session, isPending: sessionPending } = useSession();
|
|
23
|
+
return (_jsxs(Dropdown, { children: [size === "icon" ? (_jsx(Dropdown.Trigger, { className: cn("rounded-full", className), children: _jsx(UserAvatar, {}) })) : (_jsxs(Button, { variant: variant, className: cn("h-auto font-normal justify-start px-3 py-2 text-left", className), children: [session || sessionPending ? (_jsx(UserView, { isPending: sessionPending })) : (_jsxs(_Fragment, { children: [_jsx(UserAvatar, {}), _jsx("p", { className: "text-sm font-medium", children: localization.auth.account })] })), _jsx(ChevronsExpandVertical, { className: "ml-auto size-3.5" })] })), _jsxs(Dropdown.Popover, { placement: placement, className: "min-w-40 md:min-w-56 max-w-[48svw]", children: [session && (_jsx("div", { className: "px-3 pt-3 pb-1", children: _jsx(UserView, {}) })), _jsx(Dropdown.Menu, { children: session ? (_jsxs(_Fragment, { children: [_jsxs(Dropdown.Item, { textValue: localization.settings.settings, href: `${basePaths.settings}/${viewPaths.settings.account}`, children: [_jsx(Gear, { className: "text-muted" }), _jsx(Label, { children: localization.settings.settings })] }), multiSession && (_jsxs(Dropdown.SubmenuTrigger, { children: [_jsxs(Dropdown.Item, { textValue: localization.auth.switchAccount, children: [_jsx(Persons, { className: "text-muted" }), _jsx(Label, { children: localization.auth.switchAccount }), _jsx(Dropdown.SubmenuIndicator, {})] }), _jsx(Dropdown.Popover, { className: "min-w-40 md:min-w-56 max-w-[48svw]", children: _jsx(SwitchAccountMenu, {}) })] })), themeToggle && theme && setTheme && !!themes?.length && (_jsxs(Dropdown.Item, { className: "py-1 pe-2", children: [_jsx(Label, { children: localization.settings.theme }), _jsx(Tabs, { className: "ml-auto", selectedKey: theme, onSelectionChange: (key) => setTheme(key), children: _jsx(Tabs.ListContainer, { children: _jsxs(Tabs.List, { "aria-label": localization.settings.theme, className: "*:h-5 *:w-5 *:p-0", children: [themes.includes("system") && (_jsxs(Tabs.Tab, { id: "system", "aria-label": localization.settings.system, children: [_jsx(Display, { className: "size-3" }), _jsx(Tabs.Indicator, {})] })), themes.includes("light") && (_jsxs(Tabs.Tab, { id: "light", "aria-label": localization.settings.light, children: [_jsx(Sun, { className: "size-3" }), _jsx(Tabs.Indicator, {})] })), themes.includes("dark") && (_jsxs(Tabs.Tab, { id: "dark", "aria-label": localization.settings.dark, children: [_jsx(Moon, { className: "size-3" }), _jsx(Tabs.Indicator, {})] }))] }) }) })] })), _jsx(Separator, {}), _jsxs(Dropdown.Item, { textValue: localization.auth.signOut, href: `${basePaths.auth}/${viewPaths.auth.signOut}`, children: [_jsx(ArrowRightFromSquare, { className: "text-muted" }), _jsx(Label, { children: localization.auth.signOut })] })] })) : (_jsxs(_Fragment, { children: [_jsxs(Dropdown.Item, { textValue: localization.auth.signIn, href: `${basePaths.auth}/${viewPaths.auth.signIn}`, children: [_jsx(ArrowRightToSquare, { className: "text-muted" }), _jsx(Label, { children: localization.auth.signIn })] }), _jsxs(Dropdown.Item, { textValue: localization.auth.signUp, href: `${basePaths.auth}/${viewPaths.auth.signUp}`, children: [_jsx(PersonPlus, { className: "text-muted" }), _jsx(Label, { children: localization.auth.signUp })] })] })) })] })] }));
|
|
24
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type AvatarProps } from "@heroui/react";
|
|
2
|
+
import type { User } from "better-auth";
|
|
3
|
+
import type { ComponentProps } from "react";
|
|
4
|
+
export type UserViewProps = {
|
|
5
|
+
className?: string;
|
|
6
|
+
isPending?: boolean;
|
|
7
|
+
size?: AvatarProps["size"];
|
|
8
|
+
/** @remarks `User` */
|
|
9
|
+
user?: User & {
|
|
10
|
+
username?: string | null;
|
|
11
|
+
displayUsername?: string | null;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Render a compact user item with an avatar, a primary label (display username, name, or email), and an optional secondary email line.
|
|
16
|
+
*
|
|
17
|
+
* @param isPending - If true and no `user` prop is provided, renders a loading skeleton instead of user details
|
|
18
|
+
* @param size - Avatar size variant; defaults to `"sm"`
|
|
19
|
+
* @param user - Optional user to display; when omitted the current session user is used if available
|
|
20
|
+
* @returns A React element containing the user's avatar and text labels
|
|
21
|
+
*/
|
|
22
|
+
export declare function UserView({ className, isPending, size, user, ...props }: UserViewProps & ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useSession } from "@better-auth-ui/react";
|
|
3
|
+
import { cn, Skeleton } from "@heroui/react";
|
|
4
|
+
import { UserAvatar } from "./user-avatar";
|
|
5
|
+
/**
|
|
6
|
+
* Render a compact user item with an avatar, a primary label (display username, name, or email), and an optional secondary email line.
|
|
7
|
+
*
|
|
8
|
+
* @param isPending - If true and no `user` prop is provided, renders a loading skeleton instead of user details
|
|
9
|
+
* @param size - Avatar size variant; defaults to `"sm"`
|
|
10
|
+
* @param user - Optional user to display; when omitted the current session user is used if available
|
|
11
|
+
* @returns A React element containing the user's avatar and text labels
|
|
12
|
+
*/
|
|
13
|
+
export function UserView({ className, isPending, size = "sm", user, ...props }) {
|
|
14
|
+
const { data: session, isPending: sessionPending } = useSession({
|
|
15
|
+
enabled: !user && !isPending
|
|
16
|
+
});
|
|
17
|
+
const resolvedUser = user ?? session?.user;
|
|
18
|
+
if ((isPending || sessionPending) && !user) {
|
|
19
|
+
return (_jsxs("div", { className: cn("flex items-center gap-2 min-w-0", className), ...props, children: [_jsx(UserAvatar, { isPending: true, size: size }), _jsxs("div", { className: "flex flex-col gap-1 min-w-0", children: [_jsx(Skeleton, { className: "h-3.5 w-24 rounded-lg" }), _jsx(Skeleton, { className: "h-3 w-32 rounded-lg" })] })] }));
|
|
20
|
+
}
|
|
21
|
+
return (_jsxs("div", { className: cn("flex items-center gap-2 min-w-0", className), ...props, children: [_jsx(UserAvatar, { user: resolvedUser, size: size }), _jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "text-sm font-medium truncate leading-tight", children: resolvedUser?.displayUsername ||
|
|
22
|
+
resolvedUser?.name ||
|
|
23
|
+
resolvedUser?.email }), (resolvedUser?.displayUsername || resolvedUser?.name) && (_jsx("p", { className: "text-muted text-xs mb-0.5 truncate overflow-x-hidden", children: resolvedUser?.email }))] })] }));
|
|
24
|
+
}
|
package/dist/core.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@better-auth-ui/react/core";
|
package/dist/core.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@better-auth-ui/react/core";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AnyAuthConfig } from "@better-auth-ui/react";
|
|
2
|
+
/**
|
|
3
|
+
* Redirects unauthenticated users to the sign-in page, preserving the current URL as a redirectTo query parameter.
|
|
4
|
+
*
|
|
5
|
+
* @param config - Optional partial AuthConfig used to customize auth behavior
|
|
6
|
+
* @param shouldRedirect - Condition to check before redirecting (default: when user is not authenticated and not loading)
|
|
7
|
+
*/
|
|
8
|
+
export declare function useRedirectTo(config?: AnyAuthConfig, shouldRedirect?: boolean): void;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useEffect } from "react";
|
|
2
|
+
import { useAuth } from "./use-auth";
|
|
3
|
+
/**
|
|
4
|
+
* Redirects unauthenticated users to the sign-in page, preserving the current URL as a redirectTo query parameter.
|
|
5
|
+
*
|
|
6
|
+
* @param config - Optional partial AuthConfig used to customize auth behavior
|
|
7
|
+
* @param shouldRedirect - Condition to check before redirecting (default: when user is not authenticated and not loading)
|
|
8
|
+
*/
|
|
9
|
+
export function useRedirectTo(config, shouldRedirect) {
|
|
10
|
+
const { basePaths, viewPaths, replace } = useAuth(config);
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
if (shouldRedirect === false)
|
|
13
|
+
return;
|
|
14
|
+
const currentURL = window.location.pathname + window.location.search;
|
|
15
|
+
const redirectTo = encodeURIComponent(currentURL);
|
|
16
|
+
const signInPath = `${basePaths.auth}/${viewPaths.auth.signIn}?redirectTo=${redirectTo}`;
|
|
17
|
+
replace(signInPath);
|
|
18
|
+
}, [basePaths.auth, viewPaths.auth.signIn, replace, shouldRedirect]);
|
|
19
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AuthConfig } from "@better-auth-ui/react";
|
|
2
|
+
export declare function useSignIn(config: AuthConfig<{
|
|
3
|
+
RESEND: string;
|
|
4
|
+
VERIFICATION_EMAIL_SENT: string;
|
|
5
|
+
}>): [state: {
|
|
6
|
+
email: string;
|
|
7
|
+
password: string;
|
|
8
|
+
}, dispatch: (payload: FormData) => void, isPending: boolean];
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useActionState } from "react";
|
|
3
|
+
export function useSignIn(config) {
|
|
4
|
+
const { authClient, baseURL, emailAndPassword, localization, redirectTo, navigate, toast } = config;
|
|
5
|
+
const { refetch } = authClient.useSession();
|
|
6
|
+
const signInAction = async (_, formData) => {
|
|
7
|
+
const email = formData.get("email");
|
|
8
|
+
const password = formData.get("password");
|
|
9
|
+
const rememberMe = formData.get("rememberMe") === "on";
|
|
10
|
+
const { error } = await authClient.signIn.email({
|
|
11
|
+
email,
|
|
12
|
+
password,
|
|
13
|
+
...(emailAndPassword?.rememberMe ? { rememberMe } : {})
|
|
14
|
+
}, { disableSignal: true });
|
|
15
|
+
if (error) {
|
|
16
|
+
if (error.code === "EMAIL_NOT_VERIFIED") {
|
|
17
|
+
const toastId = toast.error(error.message, {
|
|
18
|
+
action: {
|
|
19
|
+
label: localization.RESEND,
|
|
20
|
+
onClick: async () => {
|
|
21
|
+
const callbackURL = `${baseURL ?? ""}${redirectTo}`;
|
|
22
|
+
toast.dismiss?.(toastId);
|
|
23
|
+
const { error } = await authClient.sendVerificationEmail({
|
|
24
|
+
email,
|
|
25
|
+
callbackURL
|
|
26
|
+
});
|
|
27
|
+
if (error) {
|
|
28
|
+
toast.error(error.message);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
toast.success(localization.VERIFICATION_EMAIL_SENT);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
toast.error(error.message);
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
email,
|
|
42
|
+
password: ""
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
await refetch();
|
|
46
|
+
navigate(redirectTo);
|
|
47
|
+
return { email, password };
|
|
48
|
+
};
|
|
49
|
+
return useActionState(signInAction, {
|
|
50
|
+
email: "",
|
|
51
|
+
password: ""
|
|
52
|
+
});
|
|
53
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export * from "./components/auth/auth";
|
|
2
|
+
export * from "./components/auth/auth-provider";
|
|
3
|
+
export * from "./components/auth/forgot-password";
|
|
4
|
+
export * from "./components/auth/magic-link";
|
|
5
|
+
export * from "./components/auth/magic-link-button";
|
|
6
|
+
export * from "./components/auth/provider-buttons";
|
|
7
|
+
export * from "./components/auth/reset-password";
|
|
8
|
+
export * from "./components/auth/sign-in";
|
|
9
|
+
export * from "./components/auth/sign-out";
|
|
10
|
+
export * from "./components/auth/sign-up";
|
|
11
|
+
export * from "./components/email/email-changed-email";
|
|
12
|
+
export * from "./components/email/email-verification-email";
|
|
13
|
+
export * from "./components/email/magic-link-email";
|
|
14
|
+
export * from "./components/email/new-device-email";
|
|
15
|
+
export * from "./components/email/otp-email";
|
|
16
|
+
export * from "./components/email/password-changed-email";
|
|
17
|
+
export * from "./components/email/reset-password-email";
|
|
18
|
+
export * from "./components/settings/account/account-settings";
|
|
19
|
+
export * from "./components/settings/account/appearance";
|
|
20
|
+
export * from "./components/settings/account/change-email";
|
|
21
|
+
export * from "./components/settings/account/manage-account";
|
|
22
|
+
export * from "./components/settings/account/manage-accounts";
|
|
23
|
+
export * from "./components/settings/account/user-profile";
|
|
24
|
+
export * from "./components/settings/security/active-sessions";
|
|
25
|
+
export * from "./components/settings/security/change-password";
|
|
26
|
+
export * from "./components/settings/security/danger-zone";
|
|
27
|
+
export * from "./components/settings/security/delete-user";
|
|
28
|
+
export * from "./components/settings/security/linked-accounts";
|
|
29
|
+
export * from "./components/settings/security/security-settings";
|
|
30
|
+
export * from "./components/settings/settings";
|
|
31
|
+
export * from "./components/user/user-avatar";
|
|
32
|
+
export * from "./components/user/user-button";
|
|
33
|
+
export * from "./components/user/user-view";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
export * from "./components/auth/auth";
|
|
3
|
+
export * from "./components/auth/auth-provider";
|
|
4
|
+
export * from "./components/auth/forgot-password";
|
|
5
|
+
export * from "./components/auth/magic-link";
|
|
6
|
+
export * from "./components/auth/magic-link-button";
|
|
7
|
+
export * from "./components/auth/provider-buttons";
|
|
8
|
+
export * from "./components/auth/reset-password";
|
|
9
|
+
export * from "./components/auth/sign-in";
|
|
10
|
+
export * from "./components/auth/sign-out";
|
|
11
|
+
export * from "./components/auth/sign-up";
|
|
12
|
+
export * from "./components/email/email-changed-email";
|
|
13
|
+
export * from "./components/email/email-verification-email";
|
|
14
|
+
export * from "./components/email/magic-link-email";
|
|
15
|
+
export * from "./components/email/new-device-email";
|
|
16
|
+
export * from "./components/email/otp-email";
|
|
17
|
+
export * from "./components/email/password-changed-email";
|
|
18
|
+
export * from "./components/email/reset-password-email";
|
|
19
|
+
export * from "./components/settings/account/account-settings";
|
|
20
|
+
export * from "./components/settings/account/appearance";
|
|
21
|
+
export * from "./components/settings/account/change-email";
|
|
22
|
+
export * from "./components/settings/account/manage-account";
|
|
23
|
+
export * from "./components/settings/account/manage-accounts";
|
|
24
|
+
export * from "./components/settings/account/user-profile";
|
|
25
|
+
export * from "./components/settings/security/active-sessions";
|
|
26
|
+
export * from "./components/settings/security/change-password";
|
|
27
|
+
export * from "./components/settings/security/danger-zone";
|
|
28
|
+
export * from "./components/settings/security/delete-user";
|
|
29
|
+
export * from "./components/settings/security/linked-accounts";
|
|
30
|
+
export * from "./components/settings/security/security-settings";
|
|
31
|
+
export * from "./components/settings/settings";
|
|
32
|
+
export * from "./components/user/user-avatar";
|
|
33
|
+
export * from "./components/user/user-button";
|
|
34
|
+
export * from "./components/user/user-view";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@better-auth-ui/react";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@better-auth-ui/react";
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@better-auth-ui/react/server";
|
package/dist/server.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@better-auth-ui/react/server";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type AuthProviderProps } from "@better-auth-ui/react";
|
|
2
|
+
/**
|
|
3
|
+
* Provides an authentication context by rendering an auth provider with the sonner toast handler injected, forwarding remaining configuration and rendering `children` inside it.
|
|
4
|
+
*
|
|
5
|
+
* @param children - React nodes to render inside the authentication provider
|
|
6
|
+
* @returns A React element that renders an authentication provider configured with the provided props and toast handler
|
|
7
|
+
*/
|
|
8
|
+
export declare function AuthProvider({ children, navigate, ...config }: AuthProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { AuthProvider as AuthProviderPrimitive } from "@better-auth-ui/react";
|
|
3
|
+
import { RouterProvider } from "@heroui/react";
|
|
4
|
+
import { toast } from "sonner";
|
|
5
|
+
/**
|
|
6
|
+
* Provides an authentication context by rendering an auth provider with the sonner toast handler injected, forwarding remaining configuration and rendering `children` inside it.
|
|
7
|
+
*
|
|
8
|
+
* @param children - React nodes to render inside the authentication provider
|
|
9
|
+
* @returns A React element that renders an authentication provider configured with the provided props and toast handler
|
|
10
|
+
*/
|
|
11
|
+
export function AuthProvider({ children, navigate, ...config }) {
|
|
12
|
+
return (_jsx(AuthProviderPrimitive, { toast: toast, navigate: navigate, ...config, children: _jsx(RouterProvider, { navigate: (path) => navigate({ to: path }), children: children }) }));
|
|
13
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { AuthView } from "@better-auth-ui/react/core";
|
|
2
|
+
import type { CardProps } from "@heroui/react";
|
|
3
|
+
import type { SocialLayout } from "./provider-buttons";
|
|
4
|
+
export type AuthProps = {
|
|
5
|
+
className?: string;
|
|
6
|
+
path?: string;
|
|
7
|
+
socialLayout?: SocialLayout;
|
|
8
|
+
socialPosition?: "top" | "bottom";
|
|
9
|
+
variant?: CardProps["variant"];
|
|
10
|
+
view?: AuthView;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Render the appropriate authentication view based on the provided `view` or `path`.
|
|
14
|
+
*
|
|
15
|
+
* @param path - Route path used to resolve an auth view when `view` is not provided
|
|
16
|
+
* @param socialLayout - Social layout to apply to sign-in/sign-up/magic-link views
|
|
17
|
+
* @param socialPosition - Position for social buttons ("top" or "bottom")
|
|
18
|
+
* @param variant - Variant to apply to the card
|
|
19
|
+
* @param view - Explicit auth view to render (e.g., "signIn", "signUp")
|
|
20
|
+
* @returns The React element for the resolved authentication view
|
|
21
|
+
*/
|
|
22
|
+
export declare function Auth({ path, socialLayout, socialPosition, view, ...props }: AuthProps & CardProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useAuth } from "@better-auth-ui/react";
|
|
3
|
+
import { ForgotPassword } from "./forgot-password";
|
|
4
|
+
import { MagicLink } from "./magic-link";
|
|
5
|
+
import { ResetPassword } from "./reset-password";
|
|
6
|
+
import { SignIn } from "./sign-in";
|
|
7
|
+
import { SignOut } from "./sign-out";
|
|
8
|
+
import { SignUp } from "./sign-up";
|
|
9
|
+
/**
|
|
10
|
+
* Render the appropriate authentication view based on the provided `view` or `path`.
|
|
11
|
+
*
|
|
12
|
+
* @param path - Route path used to resolve an auth view when `view` is not provided
|
|
13
|
+
* @param socialLayout - Social layout to apply to sign-in/sign-up/magic-link views
|
|
14
|
+
* @param socialPosition - Position for social buttons ("top" or "bottom")
|
|
15
|
+
* @param variant - Variant to apply to the card
|
|
16
|
+
* @param view - Explicit auth view to render (e.g., "signIn", "signUp")
|
|
17
|
+
* @returns The React element for the resolved authentication view
|
|
18
|
+
*/
|
|
19
|
+
export function Auth({ path, socialLayout, socialPosition, view, ...props }) {
|
|
20
|
+
const { viewPaths } = useAuth();
|
|
21
|
+
if (!view && !path) {
|
|
22
|
+
throw new Error("[Better Auth UI] Either `view` or `path` must be provided");
|
|
23
|
+
}
|
|
24
|
+
const authPathViews = Object.fromEntries(Object.entries(viewPaths.auth).map(([k, v]) => [v, k]));
|
|
25
|
+
const currentView = view || (path ? authPathViews[path] : undefined);
|
|
26
|
+
switch (currentView) {
|
|
27
|
+
case "signIn":
|
|
28
|
+
return (_jsx(SignIn, { socialLayout: socialLayout, socialPosition: socialPosition, ...props }));
|
|
29
|
+
case "signUp":
|
|
30
|
+
return (_jsx(SignUp, { socialLayout: socialLayout, socialPosition: socialPosition, ...props }));
|
|
31
|
+
case "magicLink":
|
|
32
|
+
return (_jsx(MagicLink, { socialLayout: socialLayout, socialPosition: socialPosition, ...props }));
|
|
33
|
+
case "forgotPassword":
|
|
34
|
+
return _jsx(ForgotPassword, { ...props });
|
|
35
|
+
case "resetPassword":
|
|
36
|
+
return _jsx(ResetPassword, { ...props });
|
|
37
|
+
case "signOut":
|
|
38
|
+
return _jsx(SignOut, { ...props });
|
|
39
|
+
default:
|
|
40
|
+
throw new Error(`[Better Auth UI] Valid views are: ${Object.keys(viewPaths.auth).join(", ")}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Separator } from "@heroui/react";
|
|
3
|
+
export function FieldSeparator({ children }) {
|
|
4
|
+
return (_jsxs("div", { className: "flex items-center gap-4", children: [_jsx(Separator, { className: "flex-1" }), _jsx("p", { className: "text-xs text-muted shrink-0", children: children }), _jsx(Separator, { className: "flex-1" })] }));
|
|
5
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type CardProps } from "@heroui/react";
|
|
2
|
+
export type ForgotPasswordProps = {
|
|
3
|
+
className?: string;
|
|
4
|
+
variant?: CardProps["variant"];
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Render a card-based "Forgot Password" form that sends a password-reset email.
|
|
8
|
+
*
|
|
9
|
+
* The form displays an email input, submit button, and a link back to sign-in.
|
|
10
|
+
* Toasts are displayed on success or error via the `useForgotPassword` hook.
|
|
11
|
+
*
|
|
12
|
+
* @param className - Optional additional CSS class names applied to the card
|
|
13
|
+
* @returns The forgot-password form UI as a JSX element
|
|
14
|
+
*/
|
|
15
|
+
export declare function ForgotPassword({ className, variant, ...props }: ForgotPasswordProps & CardProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useAuth, useRequestPasswordReset } from "@better-auth-ui/react";
|
|
3
|
+
import { Button, Card, Description, FieldError, Fieldset, Form, Input, Label, Link, Spinner, TextField, toast } from "@heroui/react";
|
|
4
|
+
import { cn } from "../../lib/utils";
|
|
5
|
+
/**
|
|
6
|
+
* Render a card-based "Forgot Password" form that sends a password-reset email.
|
|
7
|
+
*
|
|
8
|
+
* The form displays an email input, submit button, and a link back to sign-in.
|
|
9
|
+
* Toasts are displayed on success or error via the `useForgotPassword` hook.
|
|
10
|
+
*
|
|
11
|
+
* @param className - Optional additional CSS class names applied to the card
|
|
12
|
+
* @returns The forgot-password form UI as a JSX element
|
|
13
|
+
*/
|
|
14
|
+
export function ForgotPassword({ className, variant, ...props }) {
|
|
15
|
+
const { basePaths, localization, viewPaths, navigate } = useAuth();
|
|
16
|
+
const { mutate: requestPasswordReset, isPending } = useRequestPasswordReset({
|
|
17
|
+
onError: (error) => toast.danger(error.error?.message || error.message),
|
|
18
|
+
onSuccess: () => {
|
|
19
|
+
toast.success(localization.auth.passwordResetEmailSent);
|
|
20
|
+
navigate({ to: `${basePaths.auth}/${viewPaths.auth.signIn}` });
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
function handleSubmit(e) {
|
|
24
|
+
e.preventDefault();
|
|
25
|
+
const formData = new FormData(e.currentTarget);
|
|
26
|
+
requestPasswordReset({ email: formData.get("email") });
|
|
27
|
+
}
|
|
28
|
+
return (_jsx(Card, { className: cn("w-full max-w-sm p-4 md:p-6", className), variant: variant, ...props, children: _jsx(Card.Content, { children: _jsx(Form, { onSubmit: handleSubmit, children: _jsxs(Fieldset, { className: "gap-4", children: [_jsx(Label, { className: "text-xl", children: localization.auth.forgotPassword }), _jsxs(TextField, { name: "email", type: "email", autoComplete: "email", isDisabled: isPending, children: [_jsx(Label, { children: localization.auth.email }), _jsx(Input, { placeholder: localization.auth.emailPlaceholder, required: true, variant: variant === "transparent" ? "primary" : "secondary" }), _jsx(FieldError, { className: "text-wrap" })] }), _jsx(Fieldset.Actions, { children: _jsxs(Button, { type: "submit", className: "w-full", isPending: isPending, children: [isPending && _jsx(Spinner, { color: "current", size: "sm" }), localization.auth.sendResetLink] }) }), _jsxs(Description, { className: "text-center text-sm", children: [localization.auth.rememberYourPassword, " ", _jsx(Link, { href: `${basePaths.auth}/${viewPaths.auth.signIn}`, className: "text-accent decoration-accent no-underline hover:underline", children: localization.auth.signIn })] })] }) }) }) }));
|
|
29
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AuthView } from "@better-auth-ui/core";
|
|
2
|
+
export type MagicLinkButtonProps = {
|
|
3
|
+
isPending: boolean;
|
|
4
|
+
view?: AuthView;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Renders a full-width tertiary link-style button that navigates to either the magic-link or sign-in route.
|
|
8
|
+
*
|
|
9
|
+
* @param isPending - If true, applies disabled styling and prevents interaction
|
|
10
|
+
* @param view - Current auth view; when `"magicLink"`, the button targets the sign-in/password variant
|
|
11
|
+
* @returns The rendered Link element with the appropriate href, icon, and label
|
|
12
|
+
*/
|
|
13
|
+
export declare function MagicLinkButton({ isPending, view }: MagicLinkButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useAuth } from "@better-auth-ui/react";
|
|
3
|
+
import { Envelope, Lock } from "@gravity-ui/icons";
|
|
4
|
+
import { Link } from "@heroui/react";
|
|
5
|
+
import { buttonVariants } from "@heroui/styles";
|
|
6
|
+
import { cn } from "../../lib/utils";
|
|
7
|
+
/**
|
|
8
|
+
* Renders a full-width tertiary link-style button that navigates to either the magic-link or sign-in route.
|
|
9
|
+
*
|
|
10
|
+
* @param isPending - If true, applies disabled styling and prevents interaction
|
|
11
|
+
* @param view - Current auth view; when `"magicLink"`, the button targets the sign-in/password variant
|
|
12
|
+
* @returns The rendered Link element with the appropriate href, icon, and label
|
|
13
|
+
*/
|
|
14
|
+
export function MagicLinkButton({ isPending, view }) {
|
|
15
|
+
const { basePaths, viewPaths, localization } = useAuth();
|
|
16
|
+
const isMagicLinkView = view === "magicLink";
|
|
17
|
+
return (_jsxs(Link, { href: `${basePaths.auth}/${isMagicLinkView ? viewPaths.auth.signIn : viewPaths.auth.magicLink}`, className: cn(buttonVariants({ variant: "tertiary" }), "w-full gap-2", isPending && "status-disabled pointer-events-none"), children: [isMagicLinkView ? _jsx(Lock, {}) : _jsx(Envelope, {}), localization.auth.continueWith.replace("{{provider}}", isMagicLinkView
|
|
18
|
+
? localization.auth.password
|
|
19
|
+
: localization.auth.magicLink)] }));
|
|
20
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type CardProps } from "@heroui/react";
|
|
2
|
+
import { type SocialLayout } from "./provider-buttons";
|
|
3
|
+
export type MagicLinkProps = {
|
|
4
|
+
className?: string;
|
|
5
|
+
socialLayout?: SocialLayout;
|
|
6
|
+
socialPosition?: "top" | "bottom";
|
|
7
|
+
variant?: CardProps["variant"];
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Render a card-based sign-in form that sends an email magic link and optionally shows social provider buttons.
|
|
11
|
+
*
|
|
12
|
+
* @param className - Additional CSS class names applied to the card container
|
|
13
|
+
* @param socialLayout - Layout style for social provider buttons
|
|
14
|
+
* @param socialPosition - Position of social provider buttons; `"top"` or `"bottom"`. Defaults to `"bottom"`.
|
|
15
|
+
* @returns The magic-link sign-in UI as a JSX element
|
|
16
|
+
*/
|
|
17
|
+
export declare function MagicLink({ className, socialLayout, socialPosition, variant, ...props }: MagicLinkProps & CardProps): import("react/jsx-runtime").JSX.Element;
|