@better-auth-ui/heroui 1.6.1 → 1.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/dist/components/auth/auth-provider.d.ts +1 -1
  2. package/dist/components/auth/auth-provider.js +15 -11
  3. package/dist/components/auth/auth.d.ts +3 -3
  4. package/dist/components/auth/auth.js +36 -41
  5. package/dist/components/auth/field-separator.d.ts +1 -1
  6. package/dist/components/auth/field-separator.js +17 -4
  7. package/dist/components/auth/forgot-password.d.ts +1 -1
  8. package/dist/components/auth/forgot-password.js +69 -27
  9. package/dist/components/auth/magic-link-button.d.ts +1 -1
  10. package/dist/components/auth/magic-link-button.js +15 -18
  11. package/dist/components/auth/magic-link.d.ts +2 -2
  12. package/dist/components/auth/magic-link.js +110 -43
  13. package/dist/components/auth/passkey-button.js +23 -12
  14. package/dist/components/auth/provider-buttons.d.ts +1 -1
  15. package/dist/components/auth/provider-buttons.js +26 -33
  16. package/dist/components/auth/reset-password.d.ts +1 -1
  17. package/dist/components/auth/reset-password.js +146 -57
  18. package/dist/components/auth/sign-in.d.ts +2 -2
  19. package/dist/components/auth/sign-in.js +163 -64
  20. package/dist/components/auth/sign-out.js +26 -32
  21. package/dist/components/auth/sign-up.d.ts +2 -2
  22. package/dist/components/auth/sign-up.js +240 -70
  23. package/dist/components/email/email-changed-email.d.ts +2 -2
  24. package/dist/components/email/email-changed-email.js +29 -22
  25. package/dist/components/email/email-verification-email.d.ts +2 -2
  26. package/dist/components/email/email-verification-email.js +29 -22
  27. package/dist/components/email/magic-link-email.d.ts +2 -2
  28. package/dist/components/email/magic-link-email.js +29 -22
  29. package/dist/components/email/new-device-email.d.ts +2 -2
  30. package/dist/components/email/new-device-email.js +29 -22
  31. package/dist/components/email/otp-email.d.ts +2 -2
  32. package/dist/components/email/otp-email.js +28 -21
  33. package/dist/components/email/password-changed-email.d.ts +2 -2
  34. package/dist/components/email/password-changed-email.js +29 -22
  35. package/dist/components/email/reset-password-email.d.ts +2 -2
  36. package/dist/components/email/reset-password-email.js +29 -22
  37. package/dist/components/settings/account/account-settings.d.ts +2 -2
  38. package/dist/components/settings/account/account-settings.js +22 -19
  39. package/dist/components/settings/account/appearance.d.ts +1 -1
  40. package/dist/components/settings/account/appearance.js +70 -27
  41. package/dist/components/settings/account/change-avatar.js +88 -55
  42. package/dist/components/settings/account/change-email.d.ts +1 -1
  43. package/dist/components/settings/account/change-email.js +56 -28
  44. package/dist/components/settings/account/manage-account.d.ts +1 -1
  45. package/dist/components/settings/account/manage-account.js +50 -31
  46. package/dist/components/settings/account/manage-accounts.d.ts +1 -1
  47. package/dist/components/settings/account/manage-accounts.js +32 -36
  48. package/dist/components/settings/account/user-profile.d.ts +3 -3
  49. package/dist/components/settings/account/user-profile.js +105 -22
  50. package/dist/components/settings/security/active-session.d.ts +1 -1
  51. package/dist/components/settings/security/active-session.js +60 -51
  52. package/dist/components/settings/security/active-sessions.d.ts +1 -1
  53. package/dist/components/settings/security/active-sessions.js +32 -26
  54. package/dist/components/settings/security/change-password.d.ts +1 -1
  55. package/dist/components/settings/security/change-password.js +189 -76
  56. package/dist/components/settings/security/danger-zone.d.ts +2 -2
  57. package/dist/components/settings/security/danger-zone.js +17 -11
  58. package/dist/components/settings/security/delete-user.d.ts +1 -1
  59. package/dist/components/settings/security/delete-user.js +96 -46
  60. package/dist/components/settings/security/linked-account.d.ts +1 -1
  61. package/dist/components/settings/security/linked-account.js +61 -47
  62. package/dist/components/settings/security/linked-accounts.d.ts +1 -1
  63. package/dist/components/settings/security/linked-accounts.js +43 -40
  64. package/dist/components/settings/security/passkey.js +42 -13
  65. package/dist/components/settings/security/passkeys.d.ts +1 -1
  66. package/dist/components/settings/security/passkeys.js +51 -19
  67. package/dist/components/settings/security/security-settings.d.ts +2 -2
  68. package/dist/components/settings/security/security-settings.js +24 -21
  69. package/dist/components/settings/settings.d.ts +3 -3
  70. package/dist/components/settings/settings.js +44 -27
  71. package/dist/components/user/switch-account-item.d.ts +1 -1
  72. package/dist/components/user/switch-account-item.js +19 -15
  73. package/dist/components/user/switch-account-menu.js +27 -28
  74. package/dist/components/user/user-avatar.d.ts +3 -3
  75. package/dist/components/user/user-avatar.js +28 -30
  76. package/dist/components/user/user-button.d.ts +1 -1
  77. package/dist/components/user/user-button.js +90 -23
  78. package/dist/components/user/user-view.d.ts +3 -3
  79. package/dist/components/user/user-view.js +36 -23
  80. package/dist/core.d.ts +1 -1
  81. package/dist/index.d.ts +35 -35
  82. package/dist/index.js +36 -35
  83. package/dist/react-exports.d.ts +1 -1
  84. package/package.json +12 -10
  85. package/src/components/auth/auth.tsx +1 -1
  86. package/src/components/auth/sign-in.tsx +63 -30
  87. package/src/components/auth/sign-up.tsx +97 -3
  88. package/src/components/settings/account/user-profile.tsx +121 -6
  89. package/src/components/settings/settings.tsx +1 -1
@@ -1,24 +1,91 @@
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 })] })] })) })] })] }));
1
+ import { UserAvatar as e } from "./user-avatar.js";
2
+ import { UserView as t } from "./user-view.js";
3
+ import { SwitchAccountMenu as n } from "./switch-account-menu.js";
4
+ import { useAuth as r, useSession as i } from "@better-auth-ui/react";
5
+ import { Button as a, Dropdown as o, Label as s, Separator as c, Tabs as l, cn as u } from "@heroui/react";
6
+ import { Fragment as d, jsx as f, jsxs as p } from "react/jsx-runtime";
7
+ import { ArrowRightFromSquare as m, ArrowRightToSquare as h, ChevronsExpandVertical as g, Display as _, Gear as v, Moon as y, PersonPlus as b, Persons as x, Sun as S } from "@gravity-ui/icons";
8
+ //#region src/components/user/user-button.tsx
9
+ function C({ className: C, placement: w = "bottom", size: T = "default", variant: E = "ghost", themeToggle: D = !0 }) {
10
+ let { basePaths: O, viewPaths: k, localization: A, multiSession: j, appearance: { theme: M, setTheme: N, themes: P } } = r(), { data: F, isPending: I } = i();
11
+ return /* @__PURE__ */ p(o, { children: [T === "icon" ? /* @__PURE__ */ f(o.Trigger, {
12
+ className: u("rounded-full", C),
13
+ children: /* @__PURE__ */ f(e, {})
14
+ }) : /* @__PURE__ */ p(a, {
15
+ variant: E,
16
+ className: u("h-auto font-normal justify-start px-3 py-2 text-left", C),
17
+ children: [F || I ? /* @__PURE__ */ f(t, { isPending: I }) : /* @__PURE__ */ p(d, { children: [/* @__PURE__ */ f(e, {}), /* @__PURE__ */ f("p", {
18
+ className: "text-sm font-medium",
19
+ children: A.auth.account
20
+ })] }), /* @__PURE__ */ f(g, { className: "ml-auto size-3.5" })]
21
+ }), /* @__PURE__ */ p(o.Popover, {
22
+ placement: w,
23
+ className: "min-w-40 md:min-w-56 max-w-[48svw]",
24
+ children: [F && /* @__PURE__ */ f("div", {
25
+ className: "px-3 pt-3 pb-1",
26
+ children: /* @__PURE__ */ f(t, {})
27
+ }), /* @__PURE__ */ f(o.Menu, { children: F ? /* @__PURE__ */ p(d, { children: [
28
+ /* @__PURE__ */ p(o.Item, {
29
+ textValue: A.settings.settings,
30
+ href: `${O.settings}/${k.settings.account}`,
31
+ children: [/* @__PURE__ */ f(v, { className: "text-muted" }), /* @__PURE__ */ f(s, { children: A.settings.settings })]
32
+ }),
33
+ j && /* @__PURE__ */ p(o.SubmenuTrigger, { children: [/* @__PURE__ */ p(o.Item, {
34
+ textValue: A.auth.switchAccount,
35
+ children: [
36
+ /* @__PURE__ */ f(x, { className: "text-muted" }),
37
+ /* @__PURE__ */ f(s, { children: A.auth.switchAccount }),
38
+ /* @__PURE__ */ f(o.SubmenuIndicator, {})
39
+ ]
40
+ }), /* @__PURE__ */ f(o.Popover, {
41
+ className: "min-w-40 md:min-w-56 max-w-[48svw]",
42
+ children: /* @__PURE__ */ f(n, {})
43
+ })] }),
44
+ D && M && N && !!P?.length && /* @__PURE__ */ p(o.Item, {
45
+ className: "py-1 pe-2",
46
+ children: [/* @__PURE__ */ f(s, { children: A.settings.theme }), /* @__PURE__ */ f(l, {
47
+ className: "ml-auto",
48
+ selectedKey: M,
49
+ onSelectionChange: (e) => N(e),
50
+ children: /* @__PURE__ */ f(l.ListContainer, { children: /* @__PURE__ */ p(l.List, {
51
+ "aria-label": A.settings.theme,
52
+ className: "*:h-5 *:w-5 *:p-0",
53
+ children: [
54
+ P.includes("system") && /* @__PURE__ */ p(l.Tab, {
55
+ id: "system",
56
+ "aria-label": A.settings.system,
57
+ children: [/* @__PURE__ */ f(_, { className: "size-3" }), /* @__PURE__ */ f(l.Indicator, {})]
58
+ }),
59
+ P.includes("light") && /* @__PURE__ */ p(l.Tab, {
60
+ id: "light",
61
+ "aria-label": A.settings.light,
62
+ children: [/* @__PURE__ */ f(S, { className: "size-3" }), /* @__PURE__ */ f(l.Indicator, {})]
63
+ }),
64
+ P.includes("dark") && /* @__PURE__ */ p(l.Tab, {
65
+ id: "dark",
66
+ "aria-label": A.settings.dark,
67
+ children: [/* @__PURE__ */ f(y, { className: "size-3" }), /* @__PURE__ */ f(l.Indicator, {})]
68
+ })
69
+ ]
70
+ }) })
71
+ })]
72
+ }),
73
+ /* @__PURE__ */ f(c, {}),
74
+ /* @__PURE__ */ p(o.Item, {
75
+ textValue: A.auth.signOut,
76
+ href: `${O.auth}/${k.auth.signOut}`,
77
+ children: [/* @__PURE__ */ f(m, { className: "text-muted" }), /* @__PURE__ */ f(s, { children: A.auth.signOut })]
78
+ })
79
+ ] }) : /* @__PURE__ */ p(d, { children: [/* @__PURE__ */ p(o.Item, {
80
+ textValue: A.auth.signIn,
81
+ href: `${O.auth}/${k.auth.signIn}`,
82
+ children: [/* @__PURE__ */ f(h, { className: "text-muted" }), /* @__PURE__ */ f(s, { children: A.auth.signIn })]
83
+ }), /* @__PURE__ */ p(o.Item, {
84
+ textValue: A.auth.signUp,
85
+ href: `${O.auth}/${k.auth.signUp}`,
86
+ children: [/* @__PURE__ */ f(b, { className: "text-muted" }), /* @__PURE__ */ f(s, { children: A.auth.signUp })]
87
+ })] }) })]
88
+ })] });
24
89
  }
90
+ //#endregion
91
+ export { C as UserButton };
@@ -1,6 +1,6 @@
1
- import { type AvatarProps } from "@heroui/react";
2
- import type { User } from "better-auth";
3
- import type { ComponentProps } from "react";
1
+ import { AvatarProps } from '@heroui/react';
2
+ import { User } from 'better-auth';
3
+ import { ComponentProps } from 'react';
4
4
  export type UserViewProps = {
5
5
  className?: string;
6
6
  isPending?: boolean;
@@ -1,24 +1,37 @@
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 }))] })] }));
1
+ import { UserAvatar as e } from "./user-avatar.js";
2
+ import { useSession as t } from "@better-auth-ui/react";
3
+ import { Skeleton as n, cn as r } from "@heroui/react";
4
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
5
+ //#region src/components/user/user-view.tsx
6
+ function o({ className: o, isPending: s, size: c = "sm", user: l, ...u }) {
7
+ let { data: d, isPending: f } = t({ enabled: !l && !s }), p = l ?? d?.user;
8
+ return (s || f) && !l ? /* @__PURE__ */ a("div", {
9
+ className: r("flex items-center gap-2 min-w-0", o),
10
+ ...u,
11
+ children: [/* @__PURE__ */ i(e, {
12
+ isPending: !0,
13
+ size: c
14
+ }), /* @__PURE__ */ a("div", {
15
+ className: "flex flex-col gap-1 min-w-0",
16
+ children: [/* @__PURE__ */ i(n, { className: "h-3.5 w-24 rounded-lg" }), /* @__PURE__ */ i(n, { className: "h-3 w-32 rounded-lg" })]
17
+ })]
18
+ }) : /* @__PURE__ */ a("div", {
19
+ className: r("flex items-center gap-2 min-w-0", o),
20
+ ...u,
21
+ children: [/* @__PURE__ */ i(e, {
22
+ user: p,
23
+ size: c
24
+ }), /* @__PURE__ */ a("div", {
25
+ className: "min-w-0",
26
+ children: [/* @__PURE__ */ i("p", {
27
+ className: "text-sm font-medium truncate leading-tight",
28
+ children: p?.displayUsername || p?.name || p?.email
29
+ }), (p?.displayUsername || p?.name) && /* @__PURE__ */ i("p", {
30
+ className: "text-muted text-xs mb-0.5 truncate overflow-x-hidden",
31
+ children: p?.email
32
+ })]
33
+ })]
34
+ });
24
35
  }
36
+ //#endregion
37
+ export { o as UserView };
package/dist/core.d.ts CHANGED
@@ -1 +1 @@
1
- export * from "@better-auth-ui/react/core";
1
+ export * from '@better-auth-ui/react/core';
package/dist/index.d.ts CHANGED
@@ -1,35 +1,35 @@
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/passkey-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/passkeys";
31
- export * from "./components/settings/security/security-settings";
32
- export * from "./components/settings/settings";
33
- export * from "./components/user/user-avatar";
34
- export * from "./components/user/user-button";
35
- export * from "./components/user/user-view";
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/passkey-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/passkeys';
31
+ export * from './components/settings/security/security-settings';
32
+ export * from './components/settings/settings';
33
+ export * from './components/user/user-avatar';
34
+ export * from './components/user/user-button';
35
+ export * from './components/user/user-view';
package/dist/index.js CHANGED
@@ -1,36 +1,37 @@
1
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/passkey-button";
8
- export * from "./components/auth/provider-buttons";
9
- export * from "./components/auth/reset-password";
10
- export * from "./components/auth/sign-in";
11
- export * from "./components/auth/sign-out";
12
- export * from "./components/auth/sign-up";
13
- export * from "./components/email/email-changed-email";
14
- export * from "./components/email/email-verification-email";
15
- export * from "./components/email/magic-link-email";
16
- export * from "./components/email/new-device-email";
17
- export * from "./components/email/otp-email";
18
- export * from "./components/email/password-changed-email";
19
- export * from "./components/email/reset-password-email";
20
- export * from "./components/settings/account/account-settings";
21
- export * from "./components/settings/account/appearance";
22
- export * from "./components/settings/account/change-email";
23
- export * from "./components/settings/account/manage-account";
24
- export * from "./components/settings/account/manage-accounts";
25
- export * from "./components/settings/account/user-profile";
26
- export * from "./components/settings/security/active-sessions";
27
- export * from "./components/settings/security/change-password";
28
- export * from "./components/settings/security/danger-zone";
29
- export * from "./components/settings/security/delete-user";
30
- export * from "./components/settings/security/linked-accounts";
31
- export * from "./components/settings/security/passkeys";
32
- export * from "./components/settings/security/security-settings";
33
- export * from "./components/settings/settings";
34
- export * from "./components/user/user-avatar";
35
- export * from "./components/user/user-button";
36
- export * from "./components/user/user-view";
2
+ import { ForgotPassword as e } from "./components/auth/forgot-password.js";
3
+ import { MagicLinkButton as t } from "./components/auth/magic-link-button.js";
4
+ import { PasskeyButton as n } from "./components/auth/passkey-button.js";
5
+ import { ProviderButtons as r } from "./components/auth/provider-buttons.js";
6
+ import { MagicLink as i } from "./components/auth/magic-link.js";
7
+ import { ResetPassword as a } from "./components/auth/reset-password.js";
8
+ import { SignIn as o } from "./components/auth/sign-in.js";
9
+ import { SignOut as s } from "./components/auth/sign-out.js";
10
+ import { SignUp as c } from "./components/auth/sign-up.js";
11
+ import { Auth as l } from "./components/auth/auth.js";
12
+ import { AuthProvider as u } from "./components/auth/auth-provider.js";
13
+ import { EmailChangedEmail as d } from "./components/email/email-changed-email.js";
14
+ import { EmailVerificationEmail as f } from "./components/email/email-verification-email.js";
15
+ import { MagicLinkEmail as p } from "./components/email/magic-link-email.js";
16
+ import { NewDeviceEmail as m } from "./components/email/new-device-email.js";
17
+ import { OtpEmail as h } from "./components/email/otp-email.js";
18
+ import { PasswordChangedEmail as g } from "./components/email/password-changed-email.js";
19
+ import { ResetPasswordEmail as _ } from "./components/email/reset-password-email.js";
20
+ import { Appearance as v } from "./components/settings/account/appearance.js";
21
+ import { ChangeEmail as y } from "./components/settings/account/change-email.js";
22
+ import { UserAvatar as b } from "./components/user/user-avatar.js";
23
+ import { UserView as x } from "./components/user/user-view.js";
24
+ import { ManageAccount as S } from "./components/settings/account/manage-account.js";
25
+ import { ManageAccounts as C } from "./components/settings/account/manage-accounts.js";
26
+ import { UserProfile as w } from "./components/settings/account/user-profile.js";
27
+ import { AccountSettings as T } from "./components/settings/account/account-settings.js";
28
+ import { ActiveSessions as E } from "./components/settings/security/active-sessions.js";
29
+ import { ChangePassword as D } from "./components/settings/security/change-password.js";
30
+ import { DeleteUser as O } from "./components/settings/security/delete-user.js";
31
+ import { DangerZone as k } from "./components/settings/security/danger-zone.js";
32
+ import { LinkedAccounts as A } from "./components/settings/security/linked-accounts.js";
33
+ import { Passkeys as j } from "./components/settings/security/passkeys.js";
34
+ import { SecuritySettings as M } from "./components/settings/security/security-settings.js";
35
+ import { Settings as N } from "./components/settings/settings.js";
36
+ import { UserButton as P } from "./components/user/user-button.js";
37
+ export { T as AccountSettings, E as ActiveSessions, v as Appearance, l as Auth, u as AuthProvider, y as ChangeEmail, D as ChangePassword, k as DangerZone, O as DeleteUser, d as EmailChangedEmail, f as EmailVerificationEmail, e as ForgotPassword, A as LinkedAccounts, i as MagicLink, t as MagicLinkButton, p as MagicLinkEmail, S as ManageAccount, C as ManageAccounts, m as NewDeviceEmail, h as OtpEmail, n as PasskeyButton, j as Passkeys, g as PasswordChangedEmail, r as ProviderButtons, a as ResetPassword, _ as ResetPasswordEmail, M as SecuritySettings, N as Settings, o as SignIn, s as SignOut, c as SignUp, b as UserAvatar, P as UserButton, w as UserProfile, x as UserView };
@@ -1 +1 @@
1
- export * from "@better-auth-ui/react";
1
+ export * from '@better-auth-ui/react';
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@better-auth-ui/heroui",
3
- "version": "1.6.1",
3
+ "version": "1.6.2",
4
4
  "type": "module",
5
5
  "scripts": {
6
- "build": "tsc && bun styles",
6
+ "build": "vite build && bun styles",
7
7
  "dev": "bun styles && tsc --watch",
8
8
  "styles": "cpy src/styles.css dist/ --flat",
9
9
  "test": "vitest"
@@ -14,16 +14,16 @@
14
14
  ],
15
15
  "exports": {
16
16
  ".": {
17
- "import": "./dist/index.js",
18
- "types": "./dist/index.d.ts"
17
+ "types": "./dist/index.d.ts",
18
+ "import": "./dist/index.js"
19
19
  },
20
20
  "./core": {
21
- "import": "./dist/core.js",
22
- "types": "./dist/core.d.ts"
21
+ "types": "./dist/core.d.ts",
22
+ "import": "./dist/core.js"
23
23
  },
24
24
  "./react": {
25
- "import": "./dist/react-exports.js",
26
- "types": "./dist/react-exports.d.ts"
25
+ "types": "./dist/react-exports.d.ts",
26
+ "import": "./dist/react-exports.js"
27
27
  },
28
28
  "./styles": "./dist/styles.css"
29
29
  },
@@ -31,12 +31,13 @@
31
31
  "@gravity-ui/icons": "^2.18.0",
32
32
  "@heroui/react": "^3.0.2",
33
33
  "@heroui/styles": "^3.0.2",
34
+ "@tanstack/react-pacer": "^0.21.1",
34
35
  "@testing-library/react": "^16.3.2",
35
36
  "@testing-library/user-event": "^14.5.2",
36
37
  "@types/react": "^19.2.14",
37
38
  "@vitejs/plugin-react": "^6.0.1",
38
39
  "@vitest/browser-playwright": "^4.1.4",
39
- "better-auth": "^1.6.4",
40
+ "better-auth": "^1.6.5",
40
41
  "cpy-cli": "^7.0.0",
41
42
  "playwright": "^1.59.1",
42
43
  "react": "^19.2.5",
@@ -52,7 +53,8 @@
52
53
  "@gravity-ui/icons": ">=2.18.0",
53
54
  "@heroui/react": ">=3.0.2",
54
55
  "@heroui/styles": ">=3.0.2",
55
- "better-auth": ">=1.6.4",
56
+ "@tanstack/react-pacer": ">=0.21.0",
57
+ "better-auth": ">=1.6.5",
56
58
  "react": ">=19.2.5",
57
59
  "react-dom": ">=19.2.5",
58
60
  "bowser": ">=2.11.0"
@@ -1,5 +1,5 @@
1
+ import type { AuthView } from "@better-auth-ui/core"
1
2
  import { useAuth } from "@better-auth-ui/react"
2
- import type { AuthView } from "@better-auth-ui/react/core"
3
3
  import type { CardProps } from "@heroui/react"
4
4
  import { ForgotPassword } from "./forgot-password"
5
5
  import { MagicLink } from "./magic-link"
@@ -2,7 +2,8 @@ import {
2
2
  useAuth,
3
3
  useSendVerificationEmail,
4
4
  useSignInEmail,
5
- useSignInSocial
5
+ useSignInSocial,
6
+ useSignInUsername
6
7
  } from "@better-auth-ui/react"
7
8
  import {
8
9
  Button,
@@ -34,6 +35,10 @@ export interface SignInProps {
34
35
  variant?: CardProps["variant"]
35
36
  }
36
37
 
38
+ function isEmail(value: string): boolean {
39
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)
40
+ }
41
+
37
42
  /**
38
43
  * Render the sign-in UI using auth context for configuration and localization.
39
44
  *
@@ -55,6 +60,7 @@ export function SignIn({
55
60
  passkey,
56
61
  redirectTo,
57
62
  socialProviders,
63
+ username: usernameConfig,
58
64
  viewPaths,
59
65
  navigate
60
66
  } = useAuth()
@@ -66,27 +72,38 @@ export function SignIn({
66
72
  onSuccess: () => toast.success(localization.auth.verificationEmailSent)
67
73
  })
68
74
 
69
- const { mutate: signInEmail, isPending: signInPending } = useSignInEmail({
70
- onError: (error, { email }) => {
71
- setPassword("")
72
-
73
- if (error.error?.code === "EMAIL_NOT_VERIFIED") {
74
- toast.danger(error.error?.message || error.message, {
75
- actionProps: {
76
- children: localization.auth.resend,
77
- onClick: () =>
78
- sendVerificationEmail({
79
- email,
80
- callbackURL: `${baseURL}${redirectTo}`
81
- })
82
- }
83
- })
84
- } else {
75
+ const { mutate: signInEmail, isPending: signInEmailPending } = useSignInEmail(
76
+ {
77
+ onError: (error, { email }) => {
78
+ setPassword("")
79
+
80
+ if (error.error?.code === "EMAIL_NOT_VERIFIED") {
81
+ toast.danger(error.error?.message || error.message, {
82
+ actionProps: {
83
+ children: localization.auth.resend,
84
+ onClick: () =>
85
+ sendVerificationEmail({
86
+ email,
87
+ callbackURL: `${baseURL}${redirectTo}`
88
+ })
89
+ }
90
+ })
91
+ } else {
92
+ toast.danger(error.error?.message || error.message)
93
+ }
94
+ },
95
+ onSuccess: () => navigate({ to: redirectTo })
96
+ }
97
+ )
98
+
99
+ const { mutate: signInUsername, isPending: signInUsernamePending } =
100
+ useSignInUsername({
101
+ onError: (error) => {
102
+ setPassword("")
85
103
  toast.danger(error.error?.message || error.message)
86
- }
87
- },
88
- onSuccess: () => navigate({ to: redirectTo })
89
- })
104
+ },
105
+ onSuccess: () => navigate({ to: redirectTo })
106
+ })
90
107
 
91
108
  const [socialRedirecting, setSocialRedirecting] = useState(false)
92
109
 
@@ -108,13 +125,21 @@ export function SignIn({
108
125
  const email = formData.get("email") as string
109
126
  const rememberMe = formData.get("rememberMe") === "on"
110
127
 
111
- signInEmail({
112
- email,
113
- password,
114
- ...(emailAndPassword?.rememberMe ? { rememberMe } : {})
115
- })
128
+ if (usernameConfig?.enabled && !isEmail(email)) {
129
+ signInUsername({
130
+ username: email,
131
+ password
132
+ })
133
+ } else {
134
+ signInEmail({
135
+ email,
136
+ password,
137
+ ...(emailAndPassword?.rememberMe ? { rememberMe } : {})
138
+ })
139
+ }
116
140
  }
117
141
 
142
+ const signInPending = signInEmailPending || signInUsernamePending
118
143
  const isPending = signInPending || socialPending || socialRedirecting
119
144
 
120
145
  const showSeparator = emailAndPassword?.enabled && !!socialProviders?.length
@@ -152,14 +177,22 @@ export function SignIn({
152
177
  <Form onSubmit={handleSubmit} className="flex flex-col gap-4">
153
178
  <TextField
154
179
  name="email"
155
- type="email"
156
- autoComplete="email"
180
+ type={usernameConfig?.enabled ? "text" : "email"}
181
+ autoComplete={usernameConfig?.enabled ? "username" : "email"}
157
182
  isDisabled={isPending}
158
183
  >
159
- <Label>{localization.auth.email}</Label>
184
+ <Label>
185
+ {usernameConfig?.enabled
186
+ ? localization.auth.username
187
+ : localization.auth.email}
188
+ </Label>
160
189
 
161
190
  <Input
162
- placeholder={localization.auth.emailPlaceholder}
191
+ placeholder={
192
+ usernameConfig?.enabled
193
+ ? localization.auth.usernameOrEmailPlaceholder
194
+ : localization.auth.emailPlaceholder
195
+ }
163
196
  variant={variant === "transparent" ? "primary" : "secondary"}
164
197
  required
165
198
  />