@better-auth-ui/heroui 1.6.9 → 1.6.10
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/additional-field.d.ts +2 -2
- package/dist/components/auth/api-key/api-key.d.ts +1 -1
- package/dist/components/auth/api-key/api-keys.d.ts +1 -1
- package/dist/components/auth/api-key/delete-api-key-dialog.d.ts +1 -1
- package/dist/components/auth/api-key/organization-api-keys.d.ts +1 -1
- package/dist/components/auth/auth-provider.d.ts +1 -1
- package/dist/components/auth/auth.d.ts +3 -3
- package/dist/components/auth/delete-user/danger-zone.d.ts +2 -2
- package/dist/components/auth/delete-user/delete-account.d.ts +1 -1
- package/dist/components/auth/email/email-changed-email.d.ts +2 -2
- package/dist/components/auth/email/email-verification-email.d.ts +2 -2
- package/dist/components/auth/email/magic-link-email.d.ts +2 -2
- package/dist/components/auth/email/new-device-email.d.ts +2 -2
- package/dist/components/auth/email/organization-invitation-email.d.ts +2 -2
- package/dist/components/auth/email/otp-email.d.ts +2 -2
- package/dist/components/auth/email/password-changed-email.d.ts +2 -2
- package/dist/components/auth/email/reset-password-email.d.ts +2 -2
- package/dist/components/auth/field-separator.d.ts +1 -1
- package/dist/components/auth/forgot-password.d.ts +1 -1
- package/dist/components/auth/magic-link/magic-link-button.d.ts +1 -1
- package/dist/components/auth/magic-link/magic-link.d.ts +2 -2
- package/dist/components/auth/multi-session/manage-account.d.ts +1 -1
- package/dist/components/auth/multi-session/manage-accounts.d.ts +1 -1
- package/dist/components/auth/multi-session/switch-account-submenu-item.d.ts +1 -1
- package/dist/components/auth/organization/delete-organization-dialog.d.ts +1 -1
- package/dist/components/auth/organization/leave-organization-dialog.d.ts +1 -1
- package/dist/components/auth/organization/organization-danger-zone.d.ts +2 -2
- package/dist/components/auth/organization/organization-invitation-row.d.ts +1 -1
- package/dist/components/auth/organization/organization-invitations.d.ts +1 -1
- package/dist/components/auth/organization/organization-logo.d.ts +3 -3
- package/dist/components/auth/organization/organization-member-row.d.ts +1 -1
- package/dist/components/auth/organization/organization-members.d.ts +1 -1
- package/dist/components/auth/organization/organization-people.d.ts +1 -1
- package/dist/components/auth/organization/organization-profile.d.ts +1 -1
- package/dist/components/auth/organization/organization-row.d.ts +1 -1
- package/dist/components/auth/organization/organization-settings.d.ts +2 -2
- package/dist/components/auth/organization/organization-switcher.d.ts +3 -3
- package/dist/components/auth/organization/organization-view-skeleton.d.ts +2 -2
- package/dist/components/auth/organization/organization-view.d.ts +3 -3
- package/dist/components/auth/organization/organization.d.ts +3 -3
- package/dist/components/auth/organization/organizations-settings.d.ts +2 -2
- package/dist/components/auth/organization/organizations.d.ts +1 -1
- package/dist/components/auth/organization/remove-member-dialog.d.ts +1 -1
- package/dist/components/auth/organization/slug-field.d.ts +1 -1
- package/dist/components/auth/organization/user-invitation-row.d.ts +1 -1
- package/dist/components/auth/organization/user-invitations.d.ts +1 -1
- package/dist/components/auth/passkey/passkey-button.d.ts +1 -1
- package/dist/components/auth/passkey/passkey.d.ts +1 -1
- package/dist/components/auth/passkey/passkeys.d.ts +1 -1
- package/dist/components/auth/provider-button.d.ts +2 -2
- package/dist/components/auth/reset-password.d.ts +1 -1
- package/dist/components/auth/settings/account/account-settings.d.ts +2 -2
- package/dist/components/auth/settings/account/change-email.d.ts +1 -1
- package/dist/components/auth/settings/account/user-profile.d.ts +1 -1
- package/dist/components/auth/settings/security/active-session.d.ts +1 -1
- package/dist/components/auth/settings/security/active-sessions.d.ts +1 -1
- package/dist/components/auth/settings/security/change-password.d.ts +1 -1
- package/dist/components/auth/settings/security/linked-account.d.ts +1 -1
- package/dist/components/auth/settings/security/linked-accounts.d.ts +1 -1
- package/dist/components/auth/settings/security/security-settings.d.ts +2 -2
- package/dist/components/auth/settings/settings.d.ts +3 -3
- package/dist/components/auth/sign-in.d.ts +2 -2
- package/dist/components/auth/sign-up.d.ts +2 -2
- package/dist/components/auth/theme/appearance.d.ts +1 -1
- package/dist/components/auth/user/user-avatar.d.ts +3 -3
- package/dist/components/auth/user/user-button.d.ts +2 -2
- package/dist/components/auth/user/user-view.d.ts +3 -3
- package/dist/components/auth/username/sign-in-username.d.ts +2 -2
- package/dist/components/auth/username/username-field.d.ts +1 -1
- package/dist/email.d.ts +8 -8
- package/dist/email.js +211 -8
- package/dist/index.d.ts +21 -21
- package/dist/index.js +1682 -21
- package/dist/lib/auth/api-key-plugin.d.ts +3 -3
- package/dist/lib/auth/auth-plugin.d.ts +5 -5
- package/dist/lib/auth/delete-user-plugin.d.ts +2 -2
- package/dist/lib/auth/magic-link-plugin.d.ts +3 -3
- package/dist/lib/auth/multi-session-plugin.d.ts +3 -3
- package/dist/lib/auth/organization-plugin.d.ts +2 -2
- package/dist/lib/auth/passkey-plugin.d.ts +3 -3
- package/dist/lib/auth/theme-plugin.d.ts +3 -3
- package/dist/lib/auth/username-plugin.d.ts +3 -3
- package/dist/plugins.d.ts +46 -46
- package/dist/plugins.js +2824 -47
- package/dist/user-view--47tVtJ3.js +113 -0
- package/package.json +2 -3
- package/dist/components/auth/additional-field.js +0 -137
- package/dist/components/auth/api-key/api-key-skeleton.js +0 -5
- package/dist/components/auth/api-key/api-key.js +0 -17
- package/dist/components/auth/api-key/api-keys-empty.js +0 -9
- package/dist/components/auth/api-key/api-keys.js +0 -22
- package/dist/components/auth/api-key/create-api-key-dialog.js +0 -44
- package/dist/components/auth/api-key/delete-api-key-dialog.js +0 -17
- package/dist/components/auth/api-key/new-api-key-dialog.js +0 -24
- package/dist/components/auth/api-key/organization-api-keys.js +0 -22
- package/dist/components/auth/auth-provider.js +0 -11
- package/dist/components/auth/auth.js +0 -88
- package/dist/components/auth/delete-user/danger-zone.js +0 -12
- package/dist/components/auth/delete-user/delete-account.js +0 -50
- package/dist/components/auth/email/email-changed-email.js +0 -23
- package/dist/components/auth/email/email-verification-email.js +0 -23
- package/dist/components/auth/email/magic-link-email.js +0 -23
- package/dist/components/auth/email/new-device-email.js +0 -23
- package/dist/components/auth/email/organization-invitation-email.js +0 -23
- package/dist/components/auth/email/otp-email.js +0 -22
- package/dist/components/auth/email/password-changed-email.js +0 -23
- package/dist/components/auth/email/reset-password-email.js +0 -23
- package/dist/components/auth/error-toaster.js +0 -33
- package/dist/components/auth/field-separator.js +0 -5
- package/dist/components/auth/forgot-password.js +0 -37
- package/dist/components/auth/magic-link/magic-link-button.js +0 -34
- package/dist/components/auth/magic-link/magic-link.js +0 -40
- package/dist/components/auth/multi-session/manage-account.js +0 -33
- package/dist/components/auth/multi-session/manage-accounts.js +0 -33
- package/dist/components/auth/multi-session/switch-account-submenu-content.js +0 -25
- package/dist/components/auth/multi-session/switch-account-submenu-item.js +0 -17
- package/dist/components/auth/multi-session/switch-account-submenu.js +0 -24
- package/dist/components/auth/organization/change-organization-logo.js +0 -69
- package/dist/components/auth/organization/create-organization-dialog.js +0 -37
- package/dist/components/auth/organization/delete-organization-dialog.js +0 -25
- package/dist/components/auth/organization/delete-organization-skeleton.js +0 -8
- package/dist/components/auth/organization/delete-organization.js +0 -27
- package/dist/components/auth/organization/invite-member-dialog.js +0 -47
- package/dist/components/auth/organization/leave-organization-dialog.js +0 -21
- package/dist/components/auth/organization/leave-organization.js +0 -16
- package/dist/components/auth/organization/organization-danger-zone.js +0 -23
- package/dist/components/auth/organization/organization-invitation-row-skeleton.js +0 -9
- package/dist/components/auth/organization/organization-invitation-row.js +0 -31
- package/dist/components/auth/organization/organization-invitations-empty.js +0 -13
- package/dist/components/auth/organization/organization-invitations.js +0 -66
- package/dist/components/auth/organization/organization-logo.js +0 -14
- package/dist/components/auth/organization/organization-member-row-skeleton.js +0 -9
- package/dist/components/auth/organization/organization-member-row.js +0 -34
- package/dist/components/auth/organization/organization-members.js +0 -67
- package/dist/components/auth/organization/organization-people.js +0 -11
- package/dist/components/auth/organization/organization-profile.js +0 -34
- package/dist/components/auth/organization/organization-row.js +0 -31
- package/dist/components/auth/organization/organization-settings.js +0 -13
- package/dist/components/auth/organization/organization-switcher.js +0 -48
- package/dist/components/auth/organization/organization-view-skeleton.js +0 -9
- package/dist/components/auth/organization/organization-view.js +0 -31
- package/dist/components/auth/organization/organization.js +0 -60
- package/dist/components/auth/organization/organizations-empty.js +0 -9
- package/dist/components/auth/organization/organizations-settings.js +0 -17
- package/dist/components/auth/organization/organizations.js +0 -21
- package/dist/components/auth/organization/remove-member-dialog.js +0 -20
- package/dist/components/auth/organization/slug-field.js +0 -38
- package/dist/components/auth/organization/user-invitation-row-skeleton.js +0 -8
- package/dist/components/auth/organization/user-invitation-row.js +0 -22
- package/dist/components/auth/organization/user-invitations-empty.js +0 -12
- package/dist/components/auth/organization/user-invitations.js +0 -18
- package/dist/components/auth/passkey/add-passkey-dialog.js +0 -22
- package/dist/components/auth/passkey/delete-passkey-dialog.js +0 -14
- package/dist/components/auth/passkey/passkey-button.js +0 -25
- package/dist/components/auth/passkey/passkey-skeleton.js +0 -5
- package/dist/components/auth/passkey/passkey.js +0 -17
- package/dist/components/auth/passkey/passkeys-empty.js +0 -9
- package/dist/components/auth/passkey/passkeys.js +0 -16
- package/dist/components/auth/provider-button.js +0 -29
- package/dist/components/auth/provider-buttons.js +0 -29
- package/dist/components/auth/reset-password.js +0 -57
- package/dist/components/auth/settings/account/account-settings.js +0 -22
- package/dist/components/auth/settings/account/change-avatar.js +0 -54
- package/dist/components/auth/settings/account/change-email.js +0 -28
- package/dist/components/auth/settings/account/user-profile.js +0 -65
- package/dist/components/auth/settings/security/active-session.js +0 -52
- package/dist/components/auth/settings/security/active-sessions.js +0 -23
- package/dist/components/auth/settings/security/change-password.js +0 -79
- package/dist/components/auth/settings/security/linked-account.js +0 -38
- package/dist/components/auth/settings/security/linked-accounts.js +0 -36
- package/dist/components/auth/settings/security/security-settings.js +0 -20
- package/dist/components/auth/settings/settings.js +0 -53
- package/dist/components/auth/sign-in.js +0 -64
- package/dist/components/auth/sign-out.js +0 -33
- package/dist/components/auth/sign-up.js +0 -98
- package/dist/components/auth/theme/appearance.js +0 -24
- package/dist/components/auth/theme/theme-toggle-item.js +0 -57
- package/dist/components/auth/user/user-avatar.js +0 -32
- package/dist/components/auth/user/user-button.js +0 -40
- package/dist/components/auth/user/user-view.js +0 -27
- package/dist/components/auth/username/sign-in-username.js +0 -88
- package/dist/components/auth/username/username-field.js +0 -45
- package/dist/lib/auth/api-key-plugin.js +0 -12
- package/dist/lib/auth/auth-plugin.js +0 -1
- package/dist/lib/auth/delete-user-plugin.js +0 -7
- package/dist/lib/auth/magic-link-plugin.js +0 -18
- package/dist/lib/auth/multi-session-plugin.js +0 -9
- package/dist/lib/auth/organization-plugin.js +0 -19
- package/dist/lib/auth/passkey-plugin.js +0 -9
- package/dist/lib/auth/theme-plugin.js +0 -26
- package/dist/lib/auth/username-plugin.js +0 -19
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { ThemePreviewDark, ThemePreviewLight, ThemePreviewSystem, useAuthPlugin } from "@better-auth-ui/react";
|
|
3
|
-
import { Display, Moon, Sun } from "@gravity-ui/icons";
|
|
4
|
-
import { Card, cn, Label, Radio, RadioGroup, useIsHydrated } from "@heroui/react";
|
|
5
|
-
import { themePlugin } from "../../../lib/auth/theme-plugin";
|
|
6
|
-
/**
|
|
7
|
-
* Renders a theme selector card with visual theme previews.
|
|
8
|
-
*
|
|
9
|
-
* Displays a card containing radio buttons for selecting between system, light,
|
|
10
|
-
* and dark themes. Each option shows a visual preview of the theme. Theme options
|
|
11
|
-
* are conditionally shown based on the `themes` array provided via the theme plugin.
|
|
12
|
-
*/
|
|
13
|
-
export function Appearance({ className, variant, ...props }) {
|
|
14
|
-
const { useTheme, localization } = useAuthPlugin(themePlugin);
|
|
15
|
-
const { theme, setTheme, themes = [] } = useTheme();
|
|
16
|
-
const hydrated = useIsHydrated();
|
|
17
|
-
return (_jsxs("div", { children: [_jsx("h2", { className: cn("text-sm font-semibold mb-3"), children: localization.appearance }), _jsx(Card, { className: cn("p-4 gap-4", className), variant: variant, ...props, children: _jsxs(Card.Content, { children: [_jsx(Label, { children: localization.theme }), _jsx(RadioGroup, { variant: variant === "transparent" ? "secondary" : "primary", value: hydrated ? theme : "", onChange: setTheme, isDisabled: !hydrated || !theme, children: _jsxs("div", { className: "grid gap-3 grid-cols-2 sm:grid-cols-3", children: [themes.includes("system") && (_jsx(Radio, { value: "system", className: cn("mt-0 px-4 pb-4 pt-3 rounded-xl", "border border-transparent data-[selected=true]:border-accent data-[selected=true]:bg-accent/10", "data-[focus-visible=true]:border-accent data-[focus-visible=true]:bg-accent/10", variant === "transparent"
|
|
18
|
-
? "bg-surface"
|
|
19
|
-
: "bg-surface-secondary"), children: _jsxs(Radio.Content, { className: "gap-2", children: [_jsxs("div", { className: "flex gap-2 justify-between", children: [_jsxs(Label, { className: "flex gap-2 items-center", children: [_jsx(Display, { className: "text-muted" }), localization.system] }), _jsx(Radio.Control, { children: _jsx(Radio.Indicator, {}) })] }), _jsx(ThemePreviewSystem, { className: "w-full" })] }) })), themes.includes("light") && (_jsx(Radio, { value: "light", className: cn("mt-0 px-4 pb-4 pt-3 rounded-xl", "border border-transparent data-[selected=true]:border-accent data-[selected=true]:bg-accent/10", "data-[focus-visible=true]:border-accent data-[focus-visible=true]:bg-accent/10", variant === "transparent"
|
|
20
|
-
? "bg-surface"
|
|
21
|
-
: "bg-surface-secondary"), children: _jsxs(Radio.Content, { className: "gap-2", children: [_jsxs("div", { className: "flex gap-2 justify-between", children: [_jsxs(Label, { className: "flex gap-2 items-center", children: [_jsx(Sun, { className: "text-muted" }), localization.light] }), _jsx(Radio.Control, { children: _jsx(Radio.Indicator, {}) })] }), _jsx(ThemePreviewLight, { className: "w-full" })] }) })), themes.includes("dark") && (_jsx(Radio, { value: "dark", className: cn("mt-0 px-4 pb-4 pt-3 rounded-xl", "border border-transparent data-[selected=true]:border-accent data-[selected=true]:bg-accent/10", "data-[focus-visible=true]:border-accent data-[focus-visible=true]:bg-accent/10", variant === "transparent"
|
|
22
|
-
? "bg-surface"
|
|
23
|
-
: "bg-surface-secondary"), children: _jsxs(Radio.Content, { className: "gap-2", children: [_jsxs("div", { className: "flex gap-2 justify-between", children: [_jsxs(Label, { className: "flex gap-2 items-center", children: [_jsx(Moon, { className: "text-muted" }), localization.dark] }), _jsx(Radio.Control, { children: _jsx(Radio.Indicator, {}) })] }), _jsx(ThemePreviewDark, { className: "w-full" })] }) }))] }) })] }) })] }));
|
|
24
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useAuthPlugin } from "@better-auth-ui/react";
|
|
3
|
-
import { Display, Moon, Palette, Sun } from "@gravity-ui/icons";
|
|
4
|
-
import { Dropdown, Label, Tabs } from "@heroui/react";
|
|
5
|
-
import { themePlugin } from "../../../lib/auth/theme-plugin";
|
|
6
|
-
const ACTIVE_TAB_SELECTOR = '[role="tab"][aria-selected="true"]';
|
|
7
|
-
/**
|
|
8
|
-
* Theme toggle dropdown item used inside `UserButton`. Callers are responsible
|
|
9
|
-
* for ensuring theming is configured before rendering this component.
|
|
10
|
-
*/
|
|
11
|
-
export function ThemeToggleItem() {
|
|
12
|
-
const { useTheme, localization } = useAuthPlugin(themePlugin);
|
|
13
|
-
const { theme, setTheme, themes = [] } = useTheme();
|
|
14
|
-
// The Tabs aren't part of the menu's keyboard-navigation list, so arrow-key
|
|
15
|
-
// nav can't reach them on its own. When the wrapper menu item receives focus
|
|
16
|
-
// we delegate focus to the active Tab so the user can switch themes with the
|
|
17
|
-
// Left/Right arrows. React's synthetic `onFocus` bubbles (it's wired to
|
|
18
|
-
// `focusin`), so we must guard against child-originated events: without the
|
|
19
|
-
// `target === currentTarget` check, an arrow-key focus move between tabs
|
|
20
|
-
// bubbles up here and the still-stale `aria-selected="true"` lookup yanks
|
|
21
|
-
// focus back to the previously selected tab.
|
|
22
|
-
const focusActiveTab = (event) => {
|
|
23
|
-
if (event.target !== event.currentTarget)
|
|
24
|
-
return;
|
|
25
|
-
const activeTab = event.currentTarget.querySelector(ACTIVE_TAB_SELECTOR);
|
|
26
|
-
activeTab?.focus({ preventScroll: true });
|
|
27
|
-
};
|
|
28
|
-
// Up/Down on a Tab escapes back to the previous/next sibling menu item so
|
|
29
|
-
// users can keep navigating the menu with the arrow keys after they've
|
|
30
|
-
// entered the Tabs.
|
|
31
|
-
const handleTabsKeyDown = (event) => {
|
|
32
|
-
if (event.key !== "ArrowUp" && event.key !== "ArrowDown")
|
|
33
|
-
return;
|
|
34
|
-
const target = event.target;
|
|
35
|
-
if (target.getAttribute("role") !== "tab")
|
|
36
|
-
return;
|
|
37
|
-
const wrapper = target.closest('[role="menuitem"]');
|
|
38
|
-
const menu = wrapper?.closest('[role="menu"]');
|
|
39
|
-
if (!wrapper || !menu)
|
|
40
|
-
return;
|
|
41
|
-
const items = Array.from(menu.querySelectorAll('[role="menuitem"]:not([data-disabled])'));
|
|
42
|
-
const currentIndex = items.indexOf(wrapper);
|
|
43
|
-
if (currentIndex === -1)
|
|
44
|
-
return;
|
|
45
|
-
const nextIndex = event.key === "ArrowDown" ? currentIndex + 1 : currentIndex - 1;
|
|
46
|
-
const next = items[nextIndex];
|
|
47
|
-
if (!next)
|
|
48
|
-
return;
|
|
49
|
-
event.preventDefault();
|
|
50
|
-
next.focus();
|
|
51
|
-
};
|
|
52
|
-
return (_jsxs(Dropdown.Item, { className: "py-1 pe-2", onFocus: focusActiveTab,
|
|
53
|
-
// Without `shouldCloseOnSelect={false}` the menu auto-closes after the
|
|
54
|
-
// user changes themes, because clicking on a Tab bubbles up as a
|
|
55
|
-
// menu-item activation.
|
|
56
|
-
shouldCloseOnSelect: false, children: [_jsx(Palette, { className: "text-muted" }), _jsx(Label, { children: localization.theme }), _jsx(Tabs, { className: "ml-auto", selectedKey: theme, onSelectionChange: (key) => setTheme(key), children: _jsx(Tabs.ListContainer, { onKeyDown: handleTabsKeyDown, children: _jsxs(Tabs.List, { "aria-label": localization.theme, className: "*:h-5 *:w-5 *:p-0", children: [themes.includes("system") && (_jsxs(Tabs.Tab, { id: "system", "aria-label": localization.system, children: [_jsx(Display, { className: "size-3" }), _jsx(Tabs.Indicator, {})] })), themes.includes("light") && (_jsxs(Tabs.Tab, { id: "light", "aria-label": localization.light, children: [_jsx(Sun, { className: "size-3" }), _jsx(Tabs.Indicator, {})] })), themes.includes("dark") && (_jsxs(Tabs.Tab, { id: "dark", "aria-label": localization.dark, children: [_jsx(Moon, { className: "size-3" }), _jsx(Tabs.Indicator, {})] }))] }) }) })] }));
|
|
57
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useAuth, 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 { authClient } = useAuth();
|
|
17
|
-
const { data: session, isPending: sessionPending } = useSession(authClient, {
|
|
18
|
-
enabled: !user && !isPending
|
|
19
|
-
});
|
|
20
|
-
if ((isPending || sessionPending) && !user) {
|
|
21
|
-
return (_jsx(Skeleton, { className: cn("rounded-full", size === "sm" ? "size-8" : size === "md" ? "size-10" : "size-12", className), style: style }));
|
|
22
|
-
}
|
|
23
|
-
const resolvedUser = user ?? session?.user;
|
|
24
|
-
const initials = (resolvedUser?.username ||
|
|
25
|
-
resolvedUser?.name ||
|
|
26
|
-
resolvedUser?.email)
|
|
27
|
-
?.slice(0, 2)
|
|
28
|
-
.toUpperCase();
|
|
29
|
-
return (_jsxs(Avatar, { size: size, className: cn("rounded-full", className), style: style, ...props, children: [_jsx(Avatar.Image, { alt: resolvedUser?.displayUsername ||
|
|
30
|
-
resolvedUser?.name ||
|
|
31
|
-
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" }) })] }));
|
|
32
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useAuth, useSession } from "@better-auth-ui/react";
|
|
3
|
-
import { ArrowRightFromSquare, ArrowRightToSquare, ChevronsExpandVertical, Gear, PersonPlus } from "@gravity-ui/icons";
|
|
4
|
-
import { Button, cn, Dropdown, Label } from "@heroui/react";
|
|
5
|
-
import { isValidElement } from "react";
|
|
6
|
-
import { UserAvatar } from "./user-avatar";
|
|
7
|
-
import { UserView } from "./user-view";
|
|
8
|
-
function renderUserLink(link, fallbackKey) {
|
|
9
|
-
if (isValidElement(link))
|
|
10
|
-
return link;
|
|
11
|
-
const { label, href, icon, variant } = link;
|
|
12
|
-
return (_jsxs(Dropdown.Item, { href: href, variant: variant, textValue: typeof label === "string" ? label : undefined, children: [icon, _jsx(Label, { children: label })] }, fallbackKey));
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Render a user account dropdown button that shows account actions.
|
|
16
|
-
*
|
|
17
|
-
* @param className - Additional CSS classes applied to the trigger element
|
|
18
|
-
* @param placement - Dropdown popover placement (e.g., "bottom", "top-start", "bottom-end")
|
|
19
|
-
* @param size - "icon" renders an avatar-only trigger; "default" renders a button with label and chevron
|
|
20
|
-
* @param variant - Button visual variant passed to the underlying Button component
|
|
21
|
-
* @param links - Additional menu entries rendered above the built-in items
|
|
22
|
-
* @param hideSettings - Hide the built-in "Settings" link
|
|
23
|
-
* @returns The user button and its dropdown menu as a JSX element
|
|
24
|
-
*/
|
|
25
|
-
export function UserButton({ className, placement, size = "default", variant = "ghost", links, hideSettings, hideSubtitle }) {
|
|
26
|
-
const { authClient, basePaths, viewPaths, localization, plugins } = useAuth();
|
|
27
|
-
const { data: session, isPending: sessionPending } = useSession(authClient);
|
|
28
|
-
const userMenuItems = plugins.flatMap((plugin) => plugin.userMenuItems?.map((Item, index) => (_jsx(Item, { hideSubtitle: hideSubtitle }, `${plugin.id}-${index.toString()}`))) ?? []);
|
|
29
|
-
const userLinks = links?.flatMap((link, index) => {
|
|
30
|
-
if (!isValidElement(link)) {
|
|
31
|
-
const visibility = link.visibility ?? "always";
|
|
32
|
-
if (visibility === "authenticated" && !session)
|
|
33
|
-
return [];
|
|
34
|
-
if (visibility === "unauthenticated" && session)
|
|
35
|
-
return [];
|
|
36
|
-
}
|
|
37
|
-
return [renderUserLink(link, `user-button-link-${index.toString()}`)];
|
|
38
|
-
});
|
|
39
|
-
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-2 py-2 text-left", className), children: [session || sessionPending ? (_jsx(UserView, { isPending: sessionPending, hideSubtitle: hideSubtitle })) : (_jsxs(_Fragment, { children: [_jsx(UserAvatar, {}), _jsx("p", { className: "text-sm font-medium", children: localization.auth.account })] })), _jsx(ChevronsExpandVertical, { className: "ml-auto size-3 text-muted" })] })), _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, { hideSubtitle: hideSubtitle }) })), _jsx(Dropdown.Menu, { children: session ? (_jsxs(_Fragment, { children: [userLinks, !hideSettings && (_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 })] })), userMenuItems, _jsxs(Dropdown.Item, { textValue: localization.auth.signOut, href: `${basePaths.auth}/${viewPaths.auth.signOut}`, variant: "danger", children: [_jsx(ArrowRightFromSquare, { className: "text-danger" }), _jsx(Label, { children: localization.auth.signOut })] })] })) : (_jsxs(_Fragment, { children: [userLinks, _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 })] }), userMenuItems] })) })] })] }));
|
|
40
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useAuth, 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 subtitle (email).
|
|
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 `"md"`
|
|
10
|
-
* @param hideSubtitle - When true, omits the muted subtitle row under the primary label
|
|
11
|
-
* @param user - Optional user to display; when omitted the current session user is used if available
|
|
12
|
-
* @returns A React element containing the user's avatar and text labels
|
|
13
|
-
*/
|
|
14
|
-
export function UserView({ className, isPending, size = "md", hideSubtitle = false, user, ...props }) {
|
|
15
|
-
const { authClient } = useAuth();
|
|
16
|
-
const { data: session, isPending: sessionPending } = useSession(authClient, {
|
|
17
|
-
enabled: !user && !isPending
|
|
18
|
-
});
|
|
19
|
-
const resolvedUser = user ?? session?.user;
|
|
20
|
-
if ((isPending || sessionPending) && !user) {
|
|
21
|
-
return (_jsxs("div", { className: cn("flex items-center gap-2 min-w-0", className), ...props, children: [_jsx(UserAvatar, { isPending: true, className: size === "sm" ? "size-5 [&>span]:text-xs" : undefined, size: size === "lg" ? "md" : "sm" }), _jsxs("div", { className: "flex flex-col gap-1 min-w-0", children: [_jsx(Skeleton, { className: "h-3.5 w-24 rounded-lg" }), !hideSubtitle ? _jsx(Skeleton, { className: "h-3 w-32 rounded-lg" }) : null] })] }));
|
|
22
|
-
}
|
|
23
|
-
return (_jsxs("div", { className: cn("flex items-center gap-2 min-w-0", className), ...props, children: [_jsx(UserAvatar, { className: size === "sm" ? "size-5 [&>span]:text-xs" : undefined, user: resolvedUser, size: size === "lg" ? "md" : "sm" }), _jsxs("div", { className: "flex flex-col min-w-0", children: [_jsx("p", { className: "text-foreground text-sm font-medium leading-tight truncate", children: resolvedUser?.displayUsername ||
|
|
24
|
-
resolvedUser?.name ||
|
|
25
|
-
resolvedUser?.email }), !hideSubtitle &&
|
|
26
|
-
(resolvedUser?.displayUsername || resolvedUser?.name) ? (_jsx("p", { className: "text-muted text-xs leading-tight truncate overflow-x-hidden", children: resolvedUser?.email })) : null] })] }));
|
|
27
|
-
}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { authMutationKeys } from "@better-auth-ui/core";
|
|
3
|
-
import { useAuth, useAuthPlugin, useFetchOptions, useSendVerificationEmail, useSignInEmail, useSignInUsername } from "@better-auth-ui/react";
|
|
4
|
-
import { Button, Card, Checkbox, cn, Description, FieldError, Form, Input, Label, Link, Spinner, TextField, toast } from "@heroui/react";
|
|
5
|
-
import { useIsMutating } from "@tanstack/react-query";
|
|
6
|
-
import { useState } from "react";
|
|
7
|
-
import { usernamePlugin } from "../../../lib/auth/username-plugin";
|
|
8
|
-
import { FieldSeparator } from "../field-separator";
|
|
9
|
-
import { ProviderButtons } from "../provider-buttons";
|
|
10
|
-
/**
|
|
11
|
-
* Render the username-based sign-in UI.
|
|
12
|
-
*
|
|
13
|
-
* @returns The sign-in JSX element containing username/password fields, optional magic-link button, and social provider buttons.
|
|
14
|
-
*/
|
|
15
|
-
export function SignInUsername({ className, socialLayout, socialPosition = "bottom", variant, ...props }) {
|
|
16
|
-
const { authClient, basePaths, baseURL, emailAndPassword, localization, plugins, redirectTo, socialProviders, viewPaths, navigate } = useAuth();
|
|
17
|
-
const { fetchOptions, resetFetchOptions } = useFetchOptions();
|
|
18
|
-
const { localization: usernameLocalization } = useAuthPlugin(usernamePlugin);
|
|
19
|
-
const [password, setPassword] = useState("");
|
|
20
|
-
const { mutate: sendVerificationEmail } = useSendVerificationEmail(authClient, {
|
|
21
|
-
onSuccess: () => toast.success(localization.auth.verificationEmailSent)
|
|
22
|
-
});
|
|
23
|
-
function isEmail(value) {
|
|
24
|
-
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
25
|
-
}
|
|
26
|
-
const { mutate: signInEmail, isPending: isSignInEmailPending } = useSignInEmail(authClient, {
|
|
27
|
-
onError: (error, { email }) => {
|
|
28
|
-
setPassword("");
|
|
29
|
-
if (error.error?.code === "EMAIL_NOT_VERIFIED") {
|
|
30
|
-
toast.danger(error.error?.message || error.message, {
|
|
31
|
-
actionProps: {
|
|
32
|
-
children: localization.auth.resend,
|
|
33
|
-
onClick: () => sendVerificationEmail({
|
|
34
|
-
email,
|
|
35
|
-
callbackURL: `${baseURL}${redirectTo}`
|
|
36
|
-
})
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
toast.danger(error.error?.message || error.message);
|
|
42
|
-
}
|
|
43
|
-
resetFetchOptions();
|
|
44
|
-
},
|
|
45
|
-
onSuccess: () => navigate({ to: redirectTo })
|
|
46
|
-
});
|
|
47
|
-
const { mutate: signInUsername, isPending: isSignInUsernamePending } = useSignInUsername(authClient, {
|
|
48
|
-
onError: (error) => {
|
|
49
|
-
setPassword("");
|
|
50
|
-
toast.danger(error.error?.message || error.message);
|
|
51
|
-
resetFetchOptions();
|
|
52
|
-
},
|
|
53
|
-
onSuccess: () => navigate({ to: redirectTo })
|
|
54
|
-
});
|
|
55
|
-
const handleSubmit = (e) => {
|
|
56
|
-
e.preventDefault();
|
|
57
|
-
const formData = new FormData(e.currentTarget);
|
|
58
|
-
const email = formData.get("email");
|
|
59
|
-
const rememberMe = formData.get("rememberMe") === "on";
|
|
60
|
-
if (isEmail(email)) {
|
|
61
|
-
signInEmail({
|
|
62
|
-
email,
|
|
63
|
-
password,
|
|
64
|
-
...(emailAndPassword?.rememberMe ? { rememberMe } : {}),
|
|
65
|
-
fetchOptions
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
signInUsername({
|
|
70
|
-
username: email,
|
|
71
|
-
password,
|
|
72
|
-
...(emailAndPassword?.rememberMe ? { rememberMe } : {}),
|
|
73
|
-
fetchOptions
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
const signInMutating = useIsMutating({
|
|
78
|
-
mutationKey: authMutationKeys.signIn.all
|
|
79
|
-
});
|
|
80
|
-
const signUpMutating = useIsMutating({
|
|
81
|
-
mutationKey: authMutationKeys.signUp.all
|
|
82
|
-
});
|
|
83
|
-
const isPending = signInMutating + signUpMutating > 0;
|
|
84
|
-
const isSignInPending = isSignInEmailPending || isSignInUsernamePending;
|
|
85
|
-
const Captcha = plugins.find((plugin) => plugin.captchaComponent)?.captchaComponent;
|
|
86
|
-
const showSeparator = emailAndPassword?.enabled && !!socialProviders?.length;
|
|
87
|
-
return (_jsxs(Card, { className: cn("w-full max-w-sm gap-4 md:p-6", className), variant: variant, ...props, children: [_jsx(Card.Header, { children: _jsx(Card.Title, { className: "text-xl font-semibold mb-1", children: localization.auth.signIn }) }), _jsxs(Card.Content, { className: "gap-4", children: [socialPosition === "top" && (_jsxs(_Fragment, { children: [!!socialProviders?.length && (_jsx(ProviderButtons, { socialLayout: socialLayout })), showSeparator && (_jsx(FieldSeparator, { children: localization.auth.or }))] })), emailAndPassword?.enabled && (_jsxs(Form, { onSubmit: handleSubmit, className: "flex flex-col gap-4", children: [_jsxs(TextField, { name: "email", type: "text", autoComplete: "username email", isDisabled: isPending, children: [_jsx(Label, { children: usernameLocalization.username }), _jsx(Input, { placeholder: usernameLocalization.usernameOrEmailPlaceholder, variant: variant === "transparent" ? "primary" : "secondary", required: true }), _jsx(FieldError, {})] }), _jsxs(TextField, { minLength: emailAndPassword?.minPasswordLength, maxLength: emailAndPassword?.maxPasswordLength, name: "password", type: "password", autoComplete: "current-password", isDisabled: isPending, value: password, onChange: setPassword, children: [_jsx(Label, { children: localization.auth.password }), _jsx(Input, { placeholder: localization.auth.passwordPlaceholder, variant: variant === "transparent" ? "primary" : "secondary", required: true }), _jsx(FieldError, {})] }), emailAndPassword?.rememberMe && (_jsxs(Checkbox, { name: "rememberMe", isDisabled: isPending, variant: variant === "transparent" ? "primary" : "secondary", children: [_jsx(Checkbox.Control, { children: _jsx(Checkbox.Indicator, {}) }), _jsx(Checkbox.Content, { children: _jsx(Label, { children: localization.auth.rememberMe }) })] })), Captcha && _jsx("div", { className: "flex justify-center", children: Captcha }), _jsxs("div", { className: "flex flex-col gap-3", children: [_jsxs(Button, { type: "submit", className: "w-full", isPending: isSignInPending || isPending, children: [isSignInPending && _jsx(Spinner, { color: "current", size: "sm" }), localization.auth.signIn] }), plugins.flatMap((plugin) => plugin.authButtons?.map((AuthButton, index) => (_jsx(AuthButton, { view: "signIn" }, `${plugin.id}-${index.toString()}`))))] })] })), socialPosition === "bottom" && (_jsxs(_Fragment, { children: [showSeparator && (_jsx(FieldSeparator, { children: localization.auth.or })), !!socialProviders?.length && (_jsx(ProviderButtons, { socialLayout: socialLayout }))] }))] }), _jsxs(Card.Footer, { className: "flex-col gap-3", children: [emailAndPassword?.forgotPassword && (_jsx(Link, { href: `${basePaths.auth}/${viewPaths.auth.forgotPassword}`, className: "no-underline hover:underline", children: localization.auth.forgotPasswordLink })), emailAndPassword?.enabled && (_jsxs(Description, { className: "text-sm", children: [localization.auth.needToCreateAnAccount, " ", _jsx(Link, { href: `${basePaths.auth}/${viewPaths.auth.signUp}`, className: "text-accent no-underline hover:underline decoration-accent-hover", children: localization.auth.signUp })] }))] })] }));
|
|
88
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useAuth, useAuthPlugin, useIsUsernameAvailable } from "@better-auth-ui/react";
|
|
3
|
-
import { Check, Xmark } from "@gravity-ui/icons";
|
|
4
|
-
import { FieldError, InputGroup, Label, Spinner, TextField } from "@heroui/react";
|
|
5
|
-
import { useDebouncer } from "@tanstack/react-pacer";
|
|
6
|
-
import { useState } from "react";
|
|
7
|
-
import { usernamePlugin } from "../../../lib/auth/username-plugin";
|
|
8
|
-
/**
|
|
9
|
-
* Renderer for the `username` additional field. Owns availability checking,
|
|
10
|
-
* length limits, and visual indicators. `FieldError` automatically surfaces
|
|
11
|
-
* native validation messages. Availability feedback is shown via the icon and
|
|
12
|
-
* aria-label without affecting the field's invalid state.
|
|
13
|
-
*/
|
|
14
|
-
export function UsernameField({ name, field, isPending, variant }) {
|
|
15
|
-
const { authClient } = useAuth();
|
|
16
|
-
const { localization, minUsernameLength, maxUsernameLength, isUsernameAvailable: checkAvailability } = useAuthPlugin(usernamePlugin);
|
|
17
|
-
const currentUsername = String(field.defaultValue ?? "");
|
|
18
|
-
const [value, setValue] = useState(currentUsername);
|
|
19
|
-
const { mutate: requestAvailability, data: availability, error: availabilityError, reset: resetAvailability } = useIsUsernameAvailable(authClient, {
|
|
20
|
-
// Bypass global error toast
|
|
21
|
-
onError: () => { }
|
|
22
|
-
});
|
|
23
|
-
const debouncer = useDebouncer((next) => {
|
|
24
|
-
const trimmed = next.trim();
|
|
25
|
-
// Skip blank input and the user's own current username (profile view).
|
|
26
|
-
if (!trimmed || trimmed === currentUsername) {
|
|
27
|
-
resetAvailability();
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
requestAvailability({ username: trimmed });
|
|
31
|
-
}, { wait: 500 });
|
|
32
|
-
function handleChange(next) {
|
|
33
|
-
setValue(next);
|
|
34
|
-
resetAvailability();
|
|
35
|
-
if (checkAvailability) {
|
|
36
|
-
debouncer.maybeExecute(next);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
const isCheckingAvailability = !!checkAvailability && !!value.trim() && value.trim() !== currentUsername;
|
|
40
|
-
return (_jsxs(TextField, { name: name, type: "text", autoComplete: "username", minLength: minUsernameLength, maxLength: maxUsernameLength, isDisabled: isPending, isReadOnly: field.readOnly, value: value, onChange: handleChange, children: [_jsx(Label, { children: field.label }), _jsxs(InputGroup, { variant: variant === "transparent" ? "primary" : "secondary", children: [_jsx(InputGroup.Input, { placeholder: field.placeholder, required: field.required }), isCheckingAvailability && (_jsx(InputGroup.Suffix, { "aria-label": availability?.available
|
|
41
|
-
? localization.usernameAvailable
|
|
42
|
-
: availability?.available === false
|
|
43
|
-
? localization.usernameTaken
|
|
44
|
-
: undefined, className: "px-2", children: availability?.available ? (_jsx(Check, { className: "text-success" })) : availabilityError || availability?.available === false ? (_jsx(Xmark, { className: "text-danger" })) : (_jsx(Spinner, { size: "sm", color: "current" })) }))] }), _jsx(FieldError, {})] }));
|
|
45
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { createAuthPlugin } from "@better-auth-ui/core";
|
|
2
|
-
import { apiKeyPlugin as coreApiKeyPlugin } from "@better-auth-ui/core/plugins";
|
|
3
|
-
import { ApiKeys } from "../../components/auth/api-key/api-keys";
|
|
4
|
-
import { OrganizationApiKeys } from "../../components/auth/api-key/organization-api-keys";
|
|
5
|
-
export const apiKeyPlugin = createAuthPlugin(coreApiKeyPlugin.id, (options = {}) => {
|
|
6
|
-
const core = coreApiKeyPlugin(options);
|
|
7
|
-
return {
|
|
8
|
-
...core,
|
|
9
|
-
securityCards: [ApiKeys],
|
|
10
|
-
...(core.organization ? { organizationCards: [OrganizationApiKeys] } : {})
|
|
11
|
-
};
|
|
12
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { createAuthPlugin } from "@better-auth-ui/core";
|
|
2
|
-
import { deleteUserPlugin as coreDeleteUserPlugin } from "@better-auth-ui/core/plugins";
|
|
3
|
-
import { DangerZone } from "../../components/auth/delete-user/danger-zone";
|
|
4
|
-
export const deleteUserPlugin = createAuthPlugin(coreDeleteUserPlugin.id, (options = {}) => ({
|
|
5
|
-
...coreDeleteUserPlugin(options),
|
|
6
|
-
securityCards: [DangerZone]
|
|
7
|
-
}));
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { createAuthPlugin } from "@better-auth-ui/core";
|
|
2
|
-
import { magicLinkPlugin as coreMagicLinkPlugin } from "@better-auth-ui/core/plugins";
|
|
3
|
-
import { MagicLink } from "../../components/auth/magic-link/magic-link";
|
|
4
|
-
import { MagicLinkButton } from "../../components/auth/magic-link/magic-link-button";
|
|
5
|
-
export const magicLinkPlugin = createAuthPlugin(coreMagicLinkPlugin.id, (options = {}) => ({
|
|
6
|
-
...coreMagicLinkPlugin(options),
|
|
7
|
-
authButtons: [MagicLinkButton],
|
|
8
|
-
views: {
|
|
9
|
-
auth: { magicLink: MagicLink }
|
|
10
|
-
},
|
|
11
|
-
// Conditional, not an override: when `emailAndPassword.enabled === false`
|
|
12
|
-
// the `<Auth>` router renders this at `/auth/sign-in` instead of the
|
|
13
|
-
// disabled password form. With password auth on, the built-in `SignIn`
|
|
14
|
-
// still wins.
|
|
15
|
-
fallbackViews: {
|
|
16
|
-
auth: { signIn: MagicLink }
|
|
17
|
-
}
|
|
18
|
-
}));
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { createAuthPlugin } from "@better-auth-ui/core";
|
|
2
|
-
import { multiSessionPlugin as coreMultiSessionPlugin } from "@better-auth-ui/core/plugins";
|
|
3
|
-
import { ManageAccounts } from "../../components/auth/multi-session/manage-accounts";
|
|
4
|
-
import { SwitchAccountSubmenu } from "../../components/auth/multi-session/switch-account-submenu";
|
|
5
|
-
export const multiSessionPlugin = createAuthPlugin(coreMultiSessionPlugin.id, (options = {}) => ({
|
|
6
|
-
...coreMultiSessionPlugin(options),
|
|
7
|
-
accountCards: [ManageAccounts],
|
|
8
|
-
userMenuItems: [SwitchAccountSubmenu]
|
|
9
|
-
}));
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { createAuthPlugin } from "@better-auth-ui/core";
|
|
3
|
-
import { organizationPlugin as coreOrganizationPlugin } from "@better-auth-ui/core/plugins";
|
|
4
|
-
import { Briefcase } from "@gravity-ui/icons";
|
|
5
|
-
import { OrganizationsSettings } from "../../components/auth/organization/organizations-settings";
|
|
6
|
-
export const organizationPlugin = createAuthPlugin(coreOrganizationPlugin.id, (options = {}) => {
|
|
7
|
-
const coreOptions = coreOrganizationPlugin(options);
|
|
8
|
-
return {
|
|
9
|
-
...coreOptions,
|
|
10
|
-
localization: coreOptions.localization,
|
|
11
|
-
settingsTabs: [
|
|
12
|
-
{
|
|
13
|
-
view: "organizations",
|
|
14
|
-
label: (_jsxs(_Fragment, { children: [_jsx(Briefcase, { className: "text-muted" }), coreOptions.localization.organizations] })),
|
|
15
|
-
component: OrganizationsSettings
|
|
16
|
-
}
|
|
17
|
-
]
|
|
18
|
-
};
|
|
19
|
-
});
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { createAuthPlugin } from "@better-auth-ui/core";
|
|
2
|
-
import { passkeyPlugin as corePasskeyPlugin } from "@better-auth-ui/core/plugins";
|
|
3
|
-
import { PasskeyButton } from "../../components/auth/passkey/passkey-button";
|
|
4
|
-
import { Passkeys } from "../../components/auth/passkey/passkeys";
|
|
5
|
-
export const passkeyPlugin = createAuthPlugin(corePasskeyPlugin.id, (options = {}) => ({
|
|
6
|
-
...corePasskeyPlugin(options),
|
|
7
|
-
authButtons: [PasskeyButton],
|
|
8
|
-
securityCards: [Passkeys]
|
|
9
|
-
}));
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { createAuthPlugin } from "@better-auth-ui/core";
|
|
2
|
-
import { themePlugin as coreThemePlugin } from "@better-auth-ui/core/plugins";
|
|
3
|
-
import { Appearance } from "../../components/auth/theme/appearance";
|
|
4
|
-
import { ThemeToggleItem } from "../../components/auth/theme/theme-toggle-item";
|
|
5
|
-
export const themePlugin = createAuthPlugin(coreThemePlugin.id, ({ useTheme, ...rest }) => {
|
|
6
|
-
// No-op `setTheme` baseline keeps core's required option satisfied on the
|
|
7
|
-
// hook branch (where the consumer doesn't pass a setter); on the static
|
|
8
|
-
// branch the spread overrides it with the consumer's real setter.
|
|
9
|
-
const base = coreThemePlugin({ setTheme: () => { }, ...rest });
|
|
10
|
-
return {
|
|
11
|
-
...base,
|
|
12
|
-
// Slot components always call `plugin.useTheme()` — invoking the hook
|
|
13
|
-
// inside their render keeps it in scope of any `<ThemeProvider>` the
|
|
14
|
-
// consumer mounts. On the static branch the factory re-runs on every
|
|
15
|
-
// parent render, so the synthesized closure stays in sync with the
|
|
16
|
-
// consumer's `theme` state.
|
|
17
|
-
useTheme: useTheme ??
|
|
18
|
-
(() => ({
|
|
19
|
-
theme: base.theme,
|
|
20
|
-
setTheme: base.setTheme,
|
|
21
|
-
themes: base.themes
|
|
22
|
-
})),
|
|
23
|
-
userMenuItems: [ThemeToggleItem],
|
|
24
|
-
accountCards: [Appearance]
|
|
25
|
-
};
|
|
26
|
-
});
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { createAuthPlugin } from "@better-auth-ui/core";
|
|
2
|
-
import { usernamePlugin as coreUsernamePlugin } from "@better-auth-ui/core/plugins";
|
|
3
|
-
import { SignInUsername } from "../../components/auth/username/sign-in-username";
|
|
4
|
-
import { UsernameField } from "../../components/auth/username/username-field";
|
|
5
|
-
export const usernamePlugin = createAuthPlugin(coreUsernamePlugin.id, (options = {}) => {
|
|
6
|
-
const core = coreUsernamePlugin(options);
|
|
7
|
-
return {
|
|
8
|
-
...core,
|
|
9
|
-
additionalFields: core.additionalFields?.map((field) => field.name === "username"
|
|
10
|
-
? {
|
|
11
|
-
...field,
|
|
12
|
-
render: UsernameField
|
|
13
|
-
}
|
|
14
|
-
: field),
|
|
15
|
-
views: {
|
|
16
|
-
auth: { signIn: SignInUsername }
|
|
17
|
-
}
|
|
18
|
-
};
|
|
19
|
-
});
|