@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,42 +1,45 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useAuth, useListAccounts } from "@better-auth-ui/react";
3
- import { Card, cn, Skeleton, toast } from "@heroui/react";
4
- import { LinkedAccount } from "./linked-account";
5
- /**
6
- * Render a card showing linked social accounts and available social providers to link.
7
- *
8
- * Linked accounts (excluding the "credential" provider) are shown with an unlink control;
9
- * available providers are shown with a link control. Button states and labels reflect
10
- * ongoing link/unlink activity and use localization for provider-specific text.
11
- *
12
- * @returns A JSX element containing the linked accounts card
13
- */
14
- export function LinkedAccounts({ className, variant, ...props }) {
15
- const { localization, socialProviders } = useAuth();
16
- const { data: accounts, isPending } = useListAccounts({
17
- throwOnError: (error) => {
18
- if (error.error)
19
- toast.danger(error.error.message);
20
- return false;
21
- }
22
- });
23
- const linkedAccounts = accounts?.filter((account) => account.providerId !== "credential");
24
- const allRows = [
25
- ...(linkedAccounts?.map((account) => ({
26
- key: account.id,
27
- account,
28
- provider: account.providerId
29
- })) ?? []),
30
- ...(socialProviders?.map((provider) => ({
31
- key: provider,
32
- account: undefined,
33
- provider
34
- })) ?? [])
35
- ];
36
- return (_jsxs("div", { children: [_jsx("h2", { className: cn("text-sm font-semibold mb-3"), children: localization.settings.linkedAccounts }), _jsx(Card, { className: cn(className), variant: variant, ...props, children: _jsx(Card.Content, { className: "gap-0", children: isPending
37
- ? socialProviders?.map((provider, index) => (_jsxs("div", { children: [index > 0 && (_jsx("div", { className: "border-b border-dashed -mx-4 md:-mx-6 my-4" })), _jsx(AccountRowSkeleton, {})] }, provider)))
38
- : allRows.map((row, index) => (_jsxs("div", { children: [index > 0 && (_jsx("div", { className: "border-b border-dashed -mx-4 md:-mx-6 my-4" })), _jsx(LinkedAccount, { account: row.account, provider: row.provider })] }, row.key))) }) })] }));
1
+ import { LinkedAccount as e } from "./linked-account.js";
2
+ import { useAuth as t, useListAccounts as n } from "@better-auth-ui/react";
3
+ import { Card as r, Skeleton as i, cn as a, toast as o } from "@heroui/react";
4
+ import { jsx as s, jsxs as c } from "react/jsx-runtime";
5
+ //#region src/components/settings/security/linked-accounts.tsx
6
+ function l({ className: i, variant: l, ...d }) {
7
+ let { localization: f, socialProviders: p } = t(), { data: m, isPending: h } = n({ throwOnError: (e) => (e.error && o.danger(e.error.message), !1) }), g = [...(m?.filter((e) => e.providerId !== "credential"))?.map((e) => ({
8
+ key: e.id,
9
+ account: e,
10
+ provider: e.providerId
11
+ })) ?? [], ...p?.map((e) => ({
12
+ key: e,
13
+ account: void 0,
14
+ provider: e
15
+ })) ?? []];
16
+ return /* @__PURE__ */ c("div", { children: [/* @__PURE__ */ s("h2", {
17
+ className: a("text-sm font-semibold mb-3"),
18
+ children: f.settings.linkedAccounts
19
+ }), /* @__PURE__ */ s(r, {
20
+ className: a(i),
21
+ variant: l,
22
+ ...d,
23
+ children: /* @__PURE__ */ s(r.Content, {
24
+ className: "gap-0",
25
+ children: h ? p?.map((e, t) => /* @__PURE__ */ c("div", { children: [t > 0 && /* @__PURE__ */ s("div", { className: "border-b border-dashed -mx-4 md:-mx-6 my-4" }), /* @__PURE__ */ s(u, {})] }, e)) : g.map((t, n) => /* @__PURE__ */ c("div", { children: [n > 0 && /* @__PURE__ */ s("div", { className: "border-b border-dashed -mx-4 md:-mx-6 my-4" }), /* @__PURE__ */ s(e, {
26
+ account: t.account,
27
+ provider: t.provider
28
+ })] }, t.key))
29
+ })
30
+ })] });
39
31
  }
40
- function AccountRowSkeleton() {
41
- return (_jsx("div", { className: "flex items-center justify-between", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Skeleton, { className: "size-10 rounded-xl" }), _jsxs("div", { className: "flex flex-col gap-1", children: [_jsx(Skeleton, { className: "h-4 w-20 rounded-lg" }), _jsx(Skeleton, { className: "h-3 w-32 rounded-lg" })] })] }) }));
32
+ function u() {
33
+ return /* @__PURE__ */ s("div", {
34
+ className: "flex items-center justify-between",
35
+ children: /* @__PURE__ */ c("div", {
36
+ className: "flex items-center gap-3",
37
+ children: [/* @__PURE__ */ s(i, { className: "size-10 rounded-xl" }), /* @__PURE__ */ c("div", {
38
+ className: "flex flex-col gap-1",
39
+ children: [/* @__PURE__ */ s(i, { className: "h-4 w-20 rounded-lg" }), /* @__PURE__ */ s(i, { className: "h-3 w-32 rounded-lg" })]
40
+ })]
41
+ })
42
+ });
42
43
  }
44
+ //#endregion
45
+ export { l as LinkedAccounts };
@@ -1,14 +1,43 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useAuth, useDeletePasskey } from "@better-auth-ui/react";
3
- import { Fingerprint, Xmark } from "@gravity-ui/icons";
4
- import { Button, Spinner, toast } from "@heroui/react";
5
- export function Passkey({ passkey }) {
6
- const { localization } = useAuth();
7
- const { mutate: deletePasskey, isPending } = useDeletePasskey({
8
- onError: (error) => toast.danger(error.error?.message || error.message)
9
- });
10
- return (_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "flex size-10 shrink-0 items-center justify-center rounded-xl bg-surface-secondary", children: _jsx(Fingerprint, { className: "size-4.5" }) }), _jsxs("div", { className: "flex flex-col min-w-0", children: [_jsx("span", { className: "text-sm font-medium leading-tight", children: passkey.name || localization.auth.passkey }), _jsx("span", { className: "text-xs text-muted", children: new Date(passkey.createdAt).toLocaleString(undefined, {
11
- dateStyle: "medium",
12
- timeStyle: "short"
13
- }) })] }), _jsxs(Button, { className: "ml-auto shrink-0", variant: "outline", size: "sm", isPending: isPending, onPress: () => deletePasskey({ id: passkey.id }), children: [isPending ? _jsx(Spinner, { color: "current", size: "sm" }) : _jsx(Xmark, {}), localization.settings.delete] })] }));
1
+ import { useAuth as e, useDeletePasskey as t } from "@better-auth-ui/react";
2
+ import { Button as n, Spinner as r, toast as i } from "@heroui/react";
3
+ import { jsx as a, jsxs as o } from "react/jsx-runtime";
4
+ import { Fingerprint as s, Xmark as c } from "@gravity-ui/icons";
5
+ //#region src/components/settings/security/passkey.tsx
6
+ function l({ passkey: l }) {
7
+ let { localization: u } = e(), { mutate: d, isPending: f } = t({ onError: (e) => i.danger(e.error?.message || e.message) });
8
+ return /* @__PURE__ */ o("div", {
9
+ className: "flex items-center gap-3",
10
+ children: [
11
+ /* @__PURE__ */ a("div", {
12
+ className: "flex size-10 shrink-0 items-center justify-center rounded-xl bg-surface-secondary",
13
+ children: /* @__PURE__ */ a(s, { className: "size-4.5" })
14
+ }),
15
+ /* @__PURE__ */ o("div", {
16
+ className: "flex flex-col min-w-0",
17
+ children: [/* @__PURE__ */ a("span", {
18
+ className: "text-sm font-medium leading-tight",
19
+ children: l.name || u.auth.passkey
20
+ }), /* @__PURE__ */ a("span", {
21
+ className: "text-xs text-muted",
22
+ children: new Date(l.createdAt).toLocaleString(void 0, {
23
+ dateStyle: "medium",
24
+ timeStyle: "short"
25
+ })
26
+ })]
27
+ }),
28
+ /* @__PURE__ */ o(n, {
29
+ className: "ml-auto shrink-0",
30
+ variant: "outline",
31
+ size: "sm",
32
+ isPending: f,
33
+ onPress: () => d({ id: l.id }),
34
+ children: [f ? /* @__PURE__ */ a(r, {
35
+ color: "current",
36
+ size: "sm"
37
+ }) : /* @__PURE__ */ a(c, {}), u.settings.delete]
38
+ })
39
+ ]
40
+ });
14
41
  }
42
+ //#endregion
43
+ export { l as Passkey };
@@ -1,4 +1,4 @@
1
- import { type CardProps } from "@heroui/react";
1
+ import { CardProps } from '@heroui/react';
2
2
  export type PasskeysProps = {
3
3
  className?: string;
4
4
  variant?: CardProps["variant"];
@@ -1,21 +1,53 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useAddPasskey, useAuth, useListUserPasskeys } from "@better-auth-ui/react";
3
- import { Button, Card, cn, Skeleton, Spinner, toast } from "@heroui/react";
4
- import { Passkey } from "./passkey";
5
- export function Passkeys({ className, variant, ...props }) {
6
- const { localization } = useAuth();
7
- const { data: passkeys, isPending } = useListUserPasskeys({
8
- throwOnError: (error) => {
9
- if (error.error)
10
- toast.danger(error.error.message);
11
- return false;
12
- }
13
- });
14
- const { mutate: addPasskey, isPending: isAdding } = useAddPasskey({
15
- onError: (error) => toast.danger(error.error?.message || error.message)
16
- });
17
- return (_jsxs("div", { children: [_jsx("h2", { className: cn("text-sm font-semibold mb-3"), children: localization.settings.passkeys }), _jsx(Card, { className: cn(className), variant: variant, ...props, children: _jsxs(Card.Content, { className: "gap-0", children: [_jsxs("div", { className: "flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between", children: [_jsxs("div", { children: [_jsx("p", { className: "text-sm font-medium leading-tight", children: localization.settings.passkeysDescription }), _jsx("p", { className: "text-muted text-xs mt-0.5", children: localization.settings.passkeysInstructions })] }), _jsxs(Button, { className: "shrink-0", size: "sm", isPending: isAdding, isDisabled: isPending, onPress: () => addPasskey(), children: [isAdding && _jsx(Spinner, { color: "current", size: "sm" }), localization.settings.addPasskey] })] }), isPending ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "border-b border-dashed -mx-4 md:-mx-6 my-4" }), _jsx(PasskeySkeleton, {})] })) : (passkeys?.map((passkey) => (_jsxs("div", { children: [_jsx("div", { className: "border-b border-dashed -mx-4 md:-mx-6 my-4" }), _jsx(Passkey, { passkey: passkey })] }, passkey.id))))] }) })] }));
1
+ import { Passkey as e } from "./passkey.js";
2
+ import { useAddPasskey as t, useAuth as n, useListUserPasskeys as r } from "@better-auth-ui/react";
3
+ import { Button as i, Card as a, Skeleton as o, Spinner as s, cn as c, toast as l } from "@heroui/react";
4
+ import { Fragment as u, jsx as d, jsxs as f } from "react/jsx-runtime";
5
+ //#region src/components/settings/security/passkeys.tsx
6
+ function p({ className: o, variant: p, ...h }) {
7
+ let { localization: g } = n(), { data: _, isPending: v } = r({ throwOnError: (e) => (e.error && l.danger(e.error.message), !1) }), { mutate: y, isPending: b } = t({ onError: (e) => l.danger(e.error?.message || e.message) });
8
+ return /* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("h2", {
9
+ className: c("text-sm font-semibold mb-3"),
10
+ children: g.settings.passkeys
11
+ }), /* @__PURE__ */ d(a, {
12
+ className: c(o),
13
+ variant: p,
14
+ ...h,
15
+ children: /* @__PURE__ */ f(a.Content, {
16
+ className: "gap-0",
17
+ children: [/* @__PURE__ */ f("div", {
18
+ className: "flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between",
19
+ children: [/* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("p", {
20
+ className: "text-sm font-medium leading-tight",
21
+ children: g.settings.passkeysDescription
22
+ }), /* @__PURE__ */ d("p", {
23
+ className: "text-muted text-xs mt-0.5",
24
+ children: g.settings.passkeysInstructions
25
+ })] }), /* @__PURE__ */ f(i, {
26
+ className: "shrink-0",
27
+ size: "sm",
28
+ isPending: b,
29
+ isDisabled: v,
30
+ onPress: () => y(),
31
+ children: [b && /* @__PURE__ */ d(s, {
32
+ color: "current",
33
+ size: "sm"
34
+ }), g.settings.addPasskey]
35
+ })]
36
+ }), v ? /* @__PURE__ */ f(u, { children: [/* @__PURE__ */ d("div", { className: "border-b border-dashed -mx-4 md:-mx-6 my-4" }), /* @__PURE__ */ d(m, {})] }) : _?.map((t) => /* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("div", { className: "border-b border-dashed -mx-4 md:-mx-6 my-4" }), /* @__PURE__ */ d(e, { passkey: t })] }, t.id))]
37
+ })
38
+ })] });
18
39
  }
19
- function PasskeySkeleton() {
20
- return (_jsx("div", { className: "flex items-center justify-between", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Skeleton, { className: "size-10 rounded-xl" }), _jsxs("div", { className: "flex flex-col gap-1", children: [_jsx(Skeleton, { className: "h-4 w-24 rounded-lg" }), _jsx(Skeleton, { className: "h-3 w-20 rounded-lg" })] })] }) }));
40
+ function m() {
41
+ return /* @__PURE__ */ d("div", {
42
+ className: "flex items-center justify-between",
43
+ children: /* @__PURE__ */ f("div", {
44
+ className: "flex items-center gap-3",
45
+ children: [/* @__PURE__ */ d(o, { className: "size-10 rounded-xl" }), /* @__PURE__ */ f("div", {
46
+ className: "flex flex-col gap-1",
47
+ children: [/* @__PURE__ */ d(o, { className: "h-4 w-24 rounded-lg" }), /* @__PURE__ */ d(o, { className: "h-3 w-20 rounded-lg" })]
48
+ })]
49
+ })
50
+ });
21
51
  }
52
+ //#endregion
53
+ export { p as Passkeys };
@@ -1,5 +1,5 @@
1
- import { type CardProps } from "@heroui/react";
2
- import type { ComponentProps } from "react";
1
+ import { CardProps } from '@heroui/react';
2
+ import { ComponentProps } from 'react';
3
3
  export type SecuritySettingsProps = {
4
4
  className?: string;
5
5
  variant?: CardProps["variant"];
@@ -1,22 +1,25 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useAuth } from "@better-auth-ui/react";
3
- import { cn } from "@heroui/react";
4
- import { ActiveSessions } from "./active-sessions";
5
- import { ChangePassword } from "./change-password";
6
- import { DangerZone } from "./danger-zone";
7
- import { LinkedAccounts } from "./linked-accounts";
8
- import { Passkeys } from "./passkeys";
9
- /**
10
- * Renders the security settings layout including password management, linked accounts, and active sessions.
11
- *
12
- * ChangePassword is rendered when password authentication is enabled; LinkedAccounts is rendered when social providers are present.
13
- * DangerZone is rendered when `deleteUser.enabled` is true in auth config.
14
- *
15
- * @param className - Optional additional CSS class names for the outer container.
16
- * @param variant - Card variant forwarded to each security settings card.
17
- * @returns The security settings container as a JSX element.
18
- */
19
- export function SecuritySettings({ className, variant, ...props }) {
20
- const { deleteUser, emailAndPassword, passkey, socialProviders } = useAuth();
21
- return (_jsxs("div", { className: cn("flex w-full flex-col gap-4 md:gap-6", className), ...props, children: [emailAndPassword?.enabled && _jsx(ChangePassword, { variant: variant }), !!socialProviders?.length && _jsx(LinkedAccounts, { variant: variant }), passkey && _jsx(Passkeys, { variant: variant }), _jsx(ActiveSessions, { variant: variant }), deleteUser?.enabled && _jsx(DangerZone, { variant: variant })] }));
1
+ import { ActiveSessions as e } from "./active-sessions.js";
2
+ import { ChangePassword as t } from "./change-password.js";
3
+ import { DangerZone as n } from "./danger-zone.js";
4
+ import { LinkedAccounts as r } from "./linked-accounts.js";
5
+ import { Passkeys as i } from "./passkeys.js";
6
+ import { useAuth as a } from "@better-auth-ui/react";
7
+ import { cn as o } from "@heroui/react";
8
+ import { jsx as s, jsxs as c } from "react/jsx-runtime";
9
+ //#region src/components/settings/security/security-settings.tsx
10
+ function l({ className: l, variant: u, ...d }) {
11
+ let { deleteUser: f, emailAndPassword: p, passkey: m, socialProviders: h } = a();
12
+ return /* @__PURE__ */ c("div", {
13
+ className: o("flex w-full flex-col gap-4 md:gap-6", l),
14
+ ...d,
15
+ children: [
16
+ p?.enabled && /* @__PURE__ */ s(t, { variant: u }),
17
+ !!h?.length && /* @__PURE__ */ s(r, { variant: u }),
18
+ m && /* @__PURE__ */ s(i, { variant: u }),
19
+ /* @__PURE__ */ s(e, { variant: u }),
20
+ f?.enabled && /* @__PURE__ */ s(n, { variant: u })
21
+ ]
22
+ });
22
23
  }
24
+ //#endregion
25
+ export { l as SecuritySettings };
@@ -1,6 +1,6 @@
1
- import type { SettingsView } from "@better-auth-ui/react/core";
2
- import { type CardProps } from "@heroui/react";
3
- import { type ComponentProps } from "react";
1
+ import { SettingsView } from '@better-auth-ui/core';
2
+ import { CardProps } from '@heroui/react';
3
+ import { ComponentProps } from 'react';
4
4
  export type SettingsProps = {
5
5
  className?: string;
6
6
  hideNav?: boolean;
@@ -1,28 +1,45 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useAuth, useAuthenticate } from "@better-auth-ui/react";
3
- import { cn, Tabs } from "@heroui/react";
4
- import { useMemo } from "react";
5
- import { AccountSettings } from "./account/account-settings";
6
- import { SecuritySettings } from "./security/security-settings";
7
- /**
8
- * Renders the settings UI and activates the appropriate settings view based on `view` or `path`.
9
- *
10
- * @param className - Additional CSS class names applied to the root container
11
- * @param path - Route path used to resolve which settings view to activate when `view` is not provided
12
- * @param view - Explicit settings view to activate, e.g. `"account"` or `"security"`
13
- * @param hideNav - When `true`, hide the navigation tabs
14
- * @param variant - Card variant forwarded to each settings section card
15
- * @returns A DOM tree containing the responsive settings tabs and the currently selected settings panel
16
- *
17
- * @throws Error if neither `view` nor `path` is provided
18
- */
19
- export function Settings({ className, hideNav, path, variant, view, ...props }) {
20
- const { basePaths, localization, viewPaths } = useAuth();
21
- useAuthenticate();
22
- if (!view && !path) {
23
- throw new Error("[Better Auth UI] Either `view` or `path` must be provided");
24
- }
25
- const settingsPathViews = useMemo(() => Object.fromEntries(Object.entries(viewPaths.settings).map(([k, v]) => [v, k])), [viewPaths.settings]);
26
- const currentView = view || (path ? settingsPathViews[path] : undefined);
27
- return (_jsxs(Tabs, { className: cn(className), orientation: "horizontal", selectedKey: currentView, ...props, children: [_jsx(Tabs.ListContainer, { children: _jsxs(Tabs.List, { "aria-label": localization.settings.settings, className: "overflow-auto w-fit", children: [_jsxs(Tabs.Tab, { id: "account", href: `${basePaths.settings}/${viewPaths.settings.account}`, children: [localization.settings.account, _jsx(Tabs.Indicator, {})] }), _jsxs(Tabs.Tab, { id: "security", href: `${basePaths.settings}/${viewPaths.settings.security}`, children: [localization.settings.security, _jsx(Tabs.Indicator, {})] })] }) }), _jsx(Tabs.Panel, { id: "account", className: "px-0", children: _jsx(AccountSettings, { variant: variant }) }), _jsx(Tabs.Panel, { id: "security", className: "px-0", children: _jsx(SecuritySettings, { variant: variant }) })] }));
1
+ import { AccountSettings as e } from "./account/account-settings.js";
2
+ import { SecuritySettings as t } from "./security/security-settings.js";
3
+ import { useAuth as n, useAuthenticate as r } from "@better-auth-ui/react";
4
+ import { Tabs as i, cn as a } from "@heroui/react";
5
+ import { jsx as o, jsxs as s } from "react/jsx-runtime";
6
+ import { useMemo as c } from "react";
7
+ //#region src/components/settings/settings.tsx
8
+ function l({ className: l, hideNav: u, path: d, variant: f, view: p, ...m }) {
9
+ let { basePaths: h, localization: g, viewPaths: _ } = n();
10
+ if (r(), !p && !d) throw Error("[Better Auth UI] Either `view` or `path` must be provided");
11
+ let v = c(() => Object.fromEntries(Object.entries(_.settings).map(([e, t]) => [t, e])), [_.settings]), y = p || (d ? v[d] : void 0);
12
+ return /* @__PURE__ */ s(i, {
13
+ className: a(l),
14
+ orientation: "horizontal",
15
+ selectedKey: y,
16
+ ...m,
17
+ children: [
18
+ /* @__PURE__ */ o(i.ListContainer, { children: /* @__PURE__ */ s(i.List, {
19
+ "aria-label": g.settings.settings,
20
+ className: "overflow-auto w-fit",
21
+ children: [/* @__PURE__ */ s(i.Tab, {
22
+ id: "account",
23
+ href: `${h.settings}/${_.settings.account}`,
24
+ children: [g.settings.account, /* @__PURE__ */ o(i.Indicator, {})]
25
+ }), /* @__PURE__ */ s(i.Tab, {
26
+ id: "security",
27
+ href: `${h.settings}/${_.settings.security}`,
28
+ children: [g.settings.security, /* @__PURE__ */ o(i.Indicator, {})]
29
+ })]
30
+ }) }),
31
+ /* @__PURE__ */ o(i.Panel, {
32
+ id: "account",
33
+ className: "px-0",
34
+ children: /* @__PURE__ */ o(e, { variant: f })
35
+ }),
36
+ /* @__PURE__ */ o(i.Panel, {
37
+ id: "security",
38
+ className: "px-0",
39
+ children: /* @__PURE__ */ o(t, { variant: f })
40
+ })
41
+ ]
42
+ });
28
43
  }
44
+ //#endregion
45
+ export { l as Settings };
@@ -1,4 +1,4 @@
1
- import type { Session, User } from "better-auth";
1
+ import { Session, User } from 'better-auth';
2
2
  type DeviceSession = {
3
3
  session: Session;
4
4
  user: User;
@@ -1,16 +1,20 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useSetActiveSession } from "@better-auth-ui/react";
3
- import { Dropdown, Spinner, toast } from "@heroui/react";
4
- import { UserView } from "./user-view";
5
- /**
6
- * Render a dropdown item for switching to a different authenticated session.
7
- *
8
- * @param deviceSession - The device session to display and switch to when pressed
9
- * @returns The switch account dropdown item as a JSX element
10
- */
11
- export function SwitchAccountItem({ deviceSession }) {
12
- const { mutate: setActiveSession, isPending } = useSetActiveSession({
13
- onError: (error) => toast.danger(error.error?.message || error.message)
14
- });
15
- return (_jsxs(Dropdown.Item, { className: "px-2", isDisabled: isPending, onPress: () => setActiveSession({ sessionToken: deviceSession.session.token }), children: [_jsx(UserView, { user: deviceSession.user }), isPending && _jsx(Spinner, { color: "current", size: "sm", className: "ml-auto" })] }));
1
+ import { UserView as e } from "./user-view.js";
2
+ import { useSetActiveSession as t } from "@better-auth-ui/react";
3
+ import { Dropdown as n, Spinner as r, toast as i } from "@heroui/react";
4
+ import { jsx as a, jsxs as o } from "react/jsx-runtime";
5
+ //#region src/components/user/switch-account-item.tsx
6
+ function s({ deviceSession: s }) {
7
+ let { mutate: c, isPending: l } = t({ onError: (e) => i.danger(e.error?.message || e.message) });
8
+ return /* @__PURE__ */ o(n.Item, {
9
+ className: "px-2",
10
+ isDisabled: l,
11
+ onPress: () => c({ sessionToken: s.session.token }),
12
+ children: [/* @__PURE__ */ a(e, { user: s.user }), l && /* @__PURE__ */ a(r, {
13
+ color: "current",
14
+ size: "sm",
15
+ className: "ml-auto"
16
+ })]
17
+ });
16
18
  }
19
+ //#endregion
20
+ export { s as SwitchAccountItem };
@@ -1,29 +1,28 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useAuth, useListDeviceSessions, useSession } from "@better-auth-ui/react";
3
- import { Check, CirclePlus } from "@gravity-ui/icons";
4
- import { Dropdown, Label, Separator, toast } from "@heroui/react";
5
- import { SwitchAccountItem } from "./switch-account-item";
6
- import { UserView } from "./user-view";
7
- /**
8
- * Render the menu content for switching between multiple authenticated sessions.
9
- *
10
- * Shows the current session with a checkmark, lists other device sessions that can be activated,
11
- * and provides an option to add a new account. This component should be rendered inside a
12
- * Dropdown.SubmenuTrigger to defer the useListDeviceSessions query until the submenu is opened.
13
- *
14
- * @returns The switch account menu content as a JSX element
15
- */
16
- export function SwitchAccountMenu() {
17
- const { basePaths, viewPaths, localization } = useAuth();
18
- const { data: session } = useSession();
19
- const { data: deviceSessions, isPending } = useListDeviceSessions({
20
- throwOnError: (error) => {
21
- if (error.error)
22
- toast.danger(error.error.message);
23
- return false;
24
- }
25
- });
26
- 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, { isPending: isPending }), !isPending && _jsx(Check, { className: "ml-auto" })] }), deviceSessions
27
- ?.filter((deviceSession) => deviceSession.session.id !== session?.session?.id)
28
- .map((deviceSession) => (_jsx(SwitchAccountItem, { deviceSession: deviceSession }, deviceSession.session.id))), _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 })] })] }) }));
1
+ import { UserView as e } from "./user-view.js";
2
+ import { SwitchAccountItem as t } from "./switch-account-item.js";
3
+ import { useAuth as n, useListDeviceSessions as r, useSession as i } from "@better-auth-ui/react";
4
+ import { Dropdown as a, Label as o, Separator as s, toast as c } from "@heroui/react";
5
+ import { jsx as l, jsxs as u } from "react/jsx-runtime";
6
+ import { Check as d, CirclePlus as f } from "@gravity-ui/icons";
7
+ //#region src/components/user/switch-account-menu.tsx
8
+ function p() {
9
+ let { basePaths: p, viewPaths: m, localization: h } = n(), { data: g } = i(), { data: _, isPending: v } = r({ throwOnError: (e) => (e.error && c.danger(e.error.message), !1) });
10
+ return /* @__PURE__ */ l(a.Popover, {
11
+ className: "min-w-40 md:min-w-56 max-w-[48svw]",
12
+ children: /* @__PURE__ */ u(a.Menu, { children: [
13
+ /* @__PURE__ */ u(a.Item, {
14
+ className: "px-2",
15
+ children: [/* @__PURE__ */ l(e, { isPending: v }), !v && /* @__PURE__ */ l(d, { className: "ml-auto" })]
16
+ }),
17
+ _?.filter((e) => e.session.id !== g?.session?.id).map((e) => /* @__PURE__ */ l(t, { deviceSession: e }, e.session.id)),
18
+ /* @__PURE__ */ l(s, {}),
19
+ /* @__PURE__ */ u(a.Item, {
20
+ textValue: h.auth.addAccount,
21
+ href: `${p.auth}/${m.auth.signIn}`,
22
+ children: [/* @__PURE__ */ l(f, { className: "text-muted" }), /* @__PURE__ */ l(o, { children: h.auth.addAccount })]
23
+ })
24
+ ] })
25
+ });
29
26
  }
27
+ //#endregion
28
+ export { p as SwitchAccountMenu };
@@ -1,6 +1,6 @@
1
- import { type AvatarProps } from "@heroui/react";
2
- import type { User } from "better-auth";
3
- import type { ReactNode } from "react";
1
+ import { AvatarProps } from '@heroui/react';
2
+ import { User } from 'better-auth';
3
+ import { ReactNode } from 'react';
4
4
  export type UserAvatarProps = {
5
5
  className?: string;
6
6
  fallback?: ReactNode;
@@ -1,31 +1,29 @@
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" }) })] }));
1
+ import { useSession as e } from "@better-auth-ui/react";
2
+ import { Avatar as t, Skeleton as n, cn as r } from "@heroui/react";
3
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
4
+ import { Person as o } from "@gravity-ui/icons";
5
+ //#region src/components/user/user-avatar.tsx
6
+ function s({ className: s, fallback: c, isPending: l, user: u, size: d = "sm", style: f, ...p }) {
7
+ let { data: m, isPending: h } = e({ enabled: !u && !l });
8
+ if ((l || h) && !u) return /* @__PURE__ */ i(n, {
9
+ className: r("rounded-full", d === "sm" ? "size-8" : d === "md" ? "size-10" : "size-12", s),
10
+ style: f
11
+ });
12
+ let g = u ?? m?.user, _ = (g?.username || g?.name || g?.email)?.slice(0, 2).toUpperCase();
13
+ return /* @__PURE__ */ a(t, {
14
+ size: d,
15
+ className: r("rounded-full", s),
16
+ style: f,
17
+ ...p,
18
+ children: [/* @__PURE__ */ i(t.Image, {
19
+ alt: g?.displayUsername || g?.name || g?.email,
20
+ src: g?.image ?? void 0
21
+ }), /* @__PURE__ */ i(t.Fallback, {
22
+ className: r(d === "lg" ? "text-xl" : d === "md" ? "text-base" : "text-sm"),
23
+ delayMs: g?.image ? 600 : void 0,
24
+ children: c || _ || /* @__PURE__ */ i(o, { className: "size-4" })
25
+ })]
26
+ });
31
27
  }
28
+ //#endregion
29
+ export { s as UserAvatar };
@@ -1,4 +1,4 @@
1
- import { type ButtonProps, type DropdownPopoverProps } from "@heroui/react";
1
+ import { ButtonProps, DropdownPopoverProps } from '@heroui/react';
2
2
  export type UserButtonProps = {
3
3
  className?: string;
4
4
  size?: "default" | "icon";