@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,23 +1,30 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { PasswordChangedEmail as PasswordChangedEmailPrimitive } from "@better-auth-ui/react";
3
- import { cn } from "@heroui/react";
4
- export function PasswordChangedEmail({ colors, classNames, ...props }) {
5
- return (_jsx(PasswordChangedEmailPrimitive, { colors: {
6
- light: {
7
- background: "#F5F5F5",
8
- primary: "#0285F7",
9
- primaryForeground: "#FCFCFC",
10
- ...colors?.light
11
- },
12
- dark: {
13
- background: "#060607",
14
- primary: "#0584F6",
15
- primaryForeground: "#FCFCFC",
16
- ...colors?.dark
17
- }
18
- }, classNames: {
19
- ...classNames,
20
- card: cn("border-none rounded-3xl", classNames?.card),
21
- button: cn("rounded-full", classNames?.button)
22
- }, ...props }));
1
+ import { PasswordChangedEmail as e } from "@better-auth-ui/react";
2
+ import { cn as t } from "@heroui/react";
3
+ import { jsx as n } from "react/jsx-runtime";
4
+ //#region src/components/email/password-changed-email.tsx
5
+ function r({ colors: r, classNames: i, ...a }) {
6
+ return /* @__PURE__ */ n(e, {
7
+ colors: {
8
+ light: {
9
+ background: "#F5F5F5",
10
+ primary: "#0285F7",
11
+ primaryForeground: "#FCFCFC",
12
+ ...r?.light
13
+ },
14
+ dark: {
15
+ background: "#060607",
16
+ primary: "#0584F6",
17
+ primaryForeground: "#FCFCFC",
18
+ ...r?.dark
19
+ }
20
+ },
21
+ classNames: {
22
+ ...i,
23
+ card: t("border-none rounded-3xl", i?.card),
24
+ button: t("rounded-full", i?.button)
25
+ },
26
+ ...a
27
+ });
23
28
  }
29
+ //#endregion
30
+ export { r as PasswordChangedEmail };
@@ -1,3 +1,3 @@
1
- import { type ResetPasswordEmailProps } from "@better-auth-ui/react";
2
- export type { ResetPasswordEmailProps } from "@better-auth-ui/react";
1
+ import { ResetPasswordEmailProps } from '@better-auth-ui/react';
2
+ export type { ResetPasswordEmailProps } from '@better-auth-ui/react';
3
3
  export declare function ResetPasswordEmail({ colors, classNames, ...props }: ResetPasswordEmailProps): import("react/jsx-runtime").JSX.Element;
@@ -1,23 +1,30 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { ResetPasswordEmail as ResetPasswordEmailPrimitive } from "@better-auth-ui/react";
3
- import { cn } from "@heroui/react";
4
- export function ResetPasswordEmail({ colors, classNames, ...props }) {
5
- return (_jsx(ResetPasswordEmailPrimitive, { colors: {
6
- light: {
7
- background: "#F5F5F5",
8
- primary: "#0285F7",
9
- primaryForeground: "#FCFCFC",
10
- ...colors?.light
11
- },
12
- dark: {
13
- background: "#060607",
14
- primary: "#0584F6",
15
- primaryForeground: "#FCFCFC",
16
- ...colors?.dark
17
- }
18
- }, classNames: {
19
- ...classNames,
20
- card: cn("border-none rounded-3xl", classNames?.card),
21
- button: cn("rounded-full", classNames?.button)
22
- }, ...props }));
1
+ import { ResetPasswordEmail as e } from "@better-auth-ui/react";
2
+ import { cn as t } from "@heroui/react";
3
+ import { jsx as n } from "react/jsx-runtime";
4
+ //#region src/components/email/reset-password-email.tsx
5
+ function r({ colors: r, classNames: i, ...a }) {
6
+ return /* @__PURE__ */ n(e, {
7
+ colors: {
8
+ light: {
9
+ background: "#F5F5F5",
10
+ primary: "#0285F7",
11
+ primaryForeground: "#FCFCFC",
12
+ ...r?.light
13
+ },
14
+ dark: {
15
+ background: "#060607",
16
+ primary: "#0584F6",
17
+ primaryForeground: "#FCFCFC",
18
+ ...r?.dark
19
+ }
20
+ },
21
+ classNames: {
22
+ ...i,
23
+ card: t("border-none rounded-3xl", i?.card),
24
+ button: t("rounded-full", i?.button)
25
+ },
26
+ ...a
27
+ });
23
28
  }
29
+ //#endregion
30
+ export { r as ResetPasswordEmail };
@@ -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 AccountSettingsProps = {
4
4
  className?: string;
5
5
  variant?: CardProps["variant"];
@@ -1,20 +1,23 @@
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 { Appearance } from "./appearance";
5
- import { ChangeEmail } from "./change-email";
6
- import { ManageAccounts } from "./manage-accounts";
7
- import { UserProfile } from "./user-profile";
8
- /**
9
- * Renders the account settings layout including user profile, change email, appearance, and accounts management.
10
- *
11
- * UserProfile, ChangeEmail, and Appearance are always rendered; Accounts is rendered when `multiSession` is enabled.
12
- *
13
- * @param className - Optional additional CSS class names for the outer container.
14
- * @param variant - Card variant forwarded to each account settings card.
15
- * @returns The account settings container as a JSX element.
16
- */
17
- export function AccountSettings({ className, variant, ...props }) {
18
- const { multiSession, emailAndPassword, magicLink, appearance: { setTheme } } = useAuth();
19
- return (_jsxs("div", { className: cn("flex w-full flex-col gap-4 md:gap-6", className), ...props, children: [_jsx(UserProfile, { variant: variant }), (emailAndPassword?.enabled || magicLink) && (_jsx(ChangeEmail, { variant: variant })), setTheme && _jsx(Appearance, { variant: variant }), multiSession && _jsx(ManageAccounts, { variant: variant })] }));
1
+ import { Appearance as e } from "./appearance.js";
2
+ import { ChangeEmail as t } from "./change-email.js";
3
+ import { ManageAccounts as n } from "./manage-accounts.js";
4
+ import { UserProfile as r } from "./user-profile.js";
5
+ import { useAuth as i } from "@better-auth-ui/react";
6
+ import { cn as a } from "@heroui/react";
7
+ import { jsx as o, jsxs as s } from "react/jsx-runtime";
8
+ //#region src/components/settings/account/account-settings.tsx
9
+ function c({ className: c, variant: l, ...u }) {
10
+ let { multiSession: d, emailAndPassword: f, magicLink: p, appearance: { setTheme: m } } = i();
11
+ return /* @__PURE__ */ s("div", {
12
+ className: a("flex w-full flex-col gap-4 md:gap-6", c),
13
+ ...u,
14
+ children: [
15
+ /* @__PURE__ */ o(r, { variant: l }),
16
+ (f?.enabled || p) && /* @__PURE__ */ o(t, { variant: l }),
17
+ m && /* @__PURE__ */ o(e, { variant: l }),
18
+ d && /* @__PURE__ */ o(n, { variant: l })
19
+ ]
20
+ });
20
21
  }
22
+ //#endregion
23
+ export { c as AccountSettings };
@@ -1,4 +1,4 @@
1
- import { type CardProps } from "@heroui/react";
1
+ import { CardProps } from '@heroui/react';
2
2
  export type AppearanceProps = {
3
3
  className?: string;
4
4
  variant?: CardProps["variant"];
@@ -1,28 +1,71 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { ThemePreviewDark, ThemePreviewLight, ThemePreviewSystem, useAuth, useSession } from "@better-auth-ui/react";
3
- import { Display, Moon, Sun } from "@gravity-ui/icons";
4
- import { Card, cn, Label, Radio, RadioGroup } from "@heroui/react";
5
- /**
6
- * Renders a theme selector card with visual theme previews.
7
- *
8
- * Displays a card containing radio buttons for selecting between system, light,
9
- * and dark themes. Each option shows a visual preview of the theme. Only renders
10
- * if theme settings are configured (theme, setTheme, and themes are provided).
11
- *
12
- * @param className - Optional additional CSS class names for the card container.
13
- * @returns A JSX element containing the theme selector card, or null if theme settings are not configured.
14
- */
15
- export function Appearance({ className, variant, ...props }) {
16
- const { localization, appearance: { theme, setTheme, themes } } = useAuth();
17
- const { data: session } = useSession();
18
- if (!setTheme || !themes?.length) {
19
- return null;
20
- }
21
- return (_jsxs("div", { children: [_jsx("h2", { className: cn("text-sm font-semibold mb-3"), children: localization.settings.appearance }), _jsx(Card, { className: cn("p-4 gap-4", className), variant: variant, ...props, children: _jsxs(Card.Content, { children: [_jsx(Label, { children: localization.settings.theme }), _jsx(RadioGroup, { variant: variant === "transparent" ? "secondary" : "primary", value: session ? theme : "", onChange: setTheme, isDisabled: !session || !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"
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(Display, { className: "text-muted" }), localization.settings.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"
24
- ? "bg-surface"
25
- : "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.settings.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"
26
- ? "bg-surface"
27
- : "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.settings.dark] }), _jsx(Radio.Control, { children: _jsx(Radio.Indicator, {}) })] }), _jsx(ThemePreviewDark, { className: "w-full" })] }) }))] }) })] }) })] }));
1
+ import { ThemePreviewDark as e, ThemePreviewLight as t, ThemePreviewSystem as n, useAuth as r, useSession as i } from "@better-auth-ui/react";
2
+ import { Card as a, Label as o, Radio as s, RadioGroup as c, cn as l } from "@heroui/react";
3
+ import { jsx as u, jsxs as d } from "react/jsx-runtime";
4
+ import { Display as f, Moon as p, Sun as m } from "@gravity-ui/icons";
5
+ //#region src/components/settings/account/appearance.tsx
6
+ function h({ className: h, variant: g, ..._ }) {
7
+ let { localization: v, appearance: { theme: y, setTheme: b, themes: x } } = r(), { data: S } = i();
8
+ return !b || !x?.length ? null : /* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("h2", {
9
+ className: l("text-sm font-semibold mb-3"),
10
+ children: v.settings.appearance
11
+ }), /* @__PURE__ */ u(a, {
12
+ className: l("p-4 gap-4", h),
13
+ variant: g,
14
+ ..._,
15
+ children: /* @__PURE__ */ d(a.Content, { children: [/* @__PURE__ */ u(o, { children: v.settings.theme }), /* @__PURE__ */ u(c, {
16
+ variant: g === "transparent" ? "secondary" : "primary",
17
+ value: S ? y : "",
18
+ onChange: b,
19
+ isDisabled: !S || !y,
20
+ children: /* @__PURE__ */ d("div", {
21
+ className: "grid gap-3 grid-cols-2 sm:grid-cols-3",
22
+ children: [
23
+ x.includes("system") && /* @__PURE__ */ u(s, {
24
+ value: "system",
25
+ className: l("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", g === "transparent" ? "bg-surface" : "bg-surface-secondary"),
26
+ children: /* @__PURE__ */ d(s.Content, {
27
+ className: "gap-2",
28
+ children: [/* @__PURE__ */ d("div", {
29
+ className: "flex gap-2 justify-between",
30
+ children: [/* @__PURE__ */ d(o, {
31
+ className: "flex gap-2 items-center",
32
+ children: [/* @__PURE__ */ u(f, { className: "text-muted" }), v.settings.system]
33
+ }), /* @__PURE__ */ u(s.Control, { children: /* @__PURE__ */ u(s.Indicator, {}) })]
34
+ }), /* @__PURE__ */ u(n, { className: "w-full" })]
35
+ })
36
+ }),
37
+ x.includes("light") && /* @__PURE__ */ u(s, {
38
+ value: "light",
39
+ className: l("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", g === "transparent" ? "bg-surface" : "bg-surface-secondary"),
40
+ children: /* @__PURE__ */ d(s.Content, {
41
+ className: "gap-2",
42
+ children: [/* @__PURE__ */ d("div", {
43
+ className: "flex gap-2 justify-between",
44
+ children: [/* @__PURE__ */ d(o, {
45
+ className: "flex gap-2 items-center",
46
+ children: [/* @__PURE__ */ u(m, { className: "text-muted" }), v.settings.light]
47
+ }), /* @__PURE__ */ u(s.Control, { children: /* @__PURE__ */ u(s.Indicator, {}) })]
48
+ }), /* @__PURE__ */ u(t, { className: "w-full" })]
49
+ })
50
+ }),
51
+ x.includes("dark") && /* @__PURE__ */ u(s, {
52
+ value: "dark",
53
+ className: l("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", g === "transparent" ? "bg-surface" : "bg-surface-secondary"),
54
+ children: /* @__PURE__ */ d(s.Content, {
55
+ className: "gap-2",
56
+ children: [/* @__PURE__ */ d("div", {
57
+ className: "flex gap-2 justify-between",
58
+ children: [/* @__PURE__ */ d(o, {
59
+ className: "flex gap-2 items-center",
60
+ children: [/* @__PURE__ */ u(p, { className: "text-muted" }), v.settings.dark]
61
+ }), /* @__PURE__ */ u(s.Control, { children: /* @__PURE__ */ u(s.Indicator, {}) })]
62
+ }), /* @__PURE__ */ u(e, { className: "w-full" })]
63
+ })
64
+ })
65
+ ]
66
+ })
67
+ })] })
68
+ })] });
28
69
  }
70
+ //#endregion
71
+ export { h as Appearance };
@@ -1,56 +1,89 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { fileToBase64 } from "@better-auth-ui/core";
3
- import { useAuth, useSession, useUpdateUser } from "@better-auth-ui/react";
4
- import { CloudArrowUpIn, TrashBin } from "@gravity-ui/icons";
5
- import { Button, cn, Dropdown, Label, Spinner, toast } from "@heroui/react";
6
- import { useRef, useState } from "react";
7
- import { UserAvatar } from "../../user/user-avatar";
8
- export function ChangeAvatar({ className }) {
9
- const { localization, avatar } = useAuth();
10
- const { data: session } = useSession();
11
- const { mutate: updateUser, isPending: updatePending } = useUpdateUser({
12
- onError: (error) => toast.danger(error.error?.message || error.message)
13
- });
14
- const fileInputRef = useRef(null);
15
- const [isUploading, setIsUploading] = useState(false);
16
- const [isDeleting, setIsDeleting] = useState(false);
17
- const isPending = updatePending || isUploading || isDeleting;
18
- async function handleFileChange(e) {
19
- const file = e.target.files?.[0];
20
- if (!file)
21
- return;
22
- e.target.value = "";
23
- setIsUploading(true);
24
- try {
25
- const resized = (await avatar.resize?.(file, avatar.size, avatar.extension)) || file;
26
- const image = (await avatar.upload?.(resized)) || (await fileToBase64(resized));
27
- updateUser({ image }, {
28
- onSuccess: () => toast.success(localization.settings.avatarChangedSuccess)
29
- });
30
- }
31
- catch (error) {
32
- if (error instanceof Error) {
33
- toast.danger(error.message);
34
- }
35
- }
36
- setIsUploading(false);
37
- }
38
- async function handleDelete() {
39
- const currentImage = session?.user.image;
40
- updateUser({ image: null }, {
41
- onSuccess: async () => {
42
- if (currentImage) {
43
- setIsDeleting(true);
44
- try {
45
- await avatar.delete?.(currentImage);
46
- }
47
- finally {
48
- setIsDeleting(false);
49
- }
50
- }
51
- toast.success(localization.settings.avatarDeletedSuccess);
52
- }
53
- });
54
- }
55
- return (_jsxs("div", { className: cn("flex flex-col gap-1", className), children: [_jsx(Label, { isDisabled: !session, children: localization.settings.avatar }), _jsx("input", { ref: fileInputRef, type: "file", accept: "image/*", className: "hidden", onChange: handleFileChange }), _jsxs("div", { className: "flex items-center gap-4", children: [_jsx(Button, { type: "button", isIconOnly: true, variant: "ghost", className: "p-0 h-auto w-auto rounded-full", isDisabled: !session || isPending, onPress: () => fileInputRef.current?.click(), children: _jsx(UserAvatar, { size: "lg", isPending: isPending }) }), _jsxs(Dropdown, { children: [_jsxs(Button, { isDisabled: !session || isPending, size: "sm", variant: "secondary", children: [isPending && _jsx(Spinner, { size: "sm" }), localization.settings.changeAvatar] }), _jsx(Dropdown.Popover, { className: "min-w-fit", children: _jsxs(Dropdown.Menu, { children: [_jsxs(Dropdown.Item, { textValue: localization.settings.uploadAvatar, onAction: () => fileInputRef.current?.click(), children: [_jsx(CloudArrowUpIn, { className: "text-muted" }), _jsx(Label, { children: localization.settings.uploadAvatar })] }), _jsxs(Dropdown.Item, { textValue: localization.settings.deleteAvatar, isDisabled: !session?.user.image, onAction: handleDelete, variant: "danger", children: [_jsx(TrashBin, { className: "text-danger" }), _jsx(Label, { children: localization.settings.deleteAvatar })] })] }) })] })] })] }));
1
+ import { UserAvatar as e } from "../../user/user-avatar.js";
2
+ import { useAuth as t, useSession as n, useUpdateUser as r } from "@better-auth-ui/react";
3
+ import { Button as i, Dropdown as a, Label as o, Spinner as s, cn as c, toast as l } from "@heroui/react";
4
+ import { jsx as u, jsxs as d } from "react/jsx-runtime";
5
+ import { useRef as f, useState as p } from "react";
6
+ import { CloudArrowUpIn as m, TrashBin as h } from "@gravity-ui/icons";
7
+ import { fileToBase64 as g } from "@better-auth-ui/core";
8
+ //#region src/components/settings/account/change-avatar.tsx
9
+ function _({ className: _ }) {
10
+ let { localization: v, avatar: y } = t(), { data: b } = n(), { mutate: x, isPending: S } = r({ onError: (e) => l.danger(e.error?.message || e.message) }), C = f(null), [w, T] = p(!1), [E, D] = p(!1), O = S || w || E;
11
+ async function k(e) {
12
+ let t = e.target.files?.[0];
13
+ if (t) {
14
+ e.target.value = "", T(!0);
15
+ try {
16
+ let e = await y.resize?.(t, y.size, y.extension) || t;
17
+ x({ image: await y.upload?.(e) || await g(e) }, { onSuccess: () => l.success(v.settings.avatarChangedSuccess) });
18
+ } catch (e) {
19
+ e instanceof Error && l.danger(e.message);
20
+ }
21
+ T(!1);
22
+ }
23
+ }
24
+ async function A() {
25
+ let e = b?.user.image;
26
+ x({ image: null }, { onSuccess: async () => {
27
+ if (e) {
28
+ D(!0);
29
+ try {
30
+ await y.delete?.(e);
31
+ } finally {
32
+ D(!1);
33
+ }
34
+ }
35
+ l.success(v.settings.avatarDeletedSuccess);
36
+ } });
37
+ }
38
+ return /* @__PURE__ */ d("div", {
39
+ className: c("flex flex-col gap-1", _),
40
+ children: [
41
+ /* @__PURE__ */ u(o, {
42
+ isDisabled: !b,
43
+ children: v.settings.avatar
44
+ }),
45
+ /* @__PURE__ */ u("input", {
46
+ ref: C,
47
+ type: "file",
48
+ accept: "image/*",
49
+ className: "hidden",
50
+ onChange: k
51
+ }),
52
+ /* @__PURE__ */ d("div", {
53
+ className: "flex items-center gap-4",
54
+ children: [/* @__PURE__ */ u(i, {
55
+ type: "button",
56
+ isIconOnly: !0,
57
+ variant: "ghost",
58
+ className: "p-0 h-auto w-auto rounded-full",
59
+ isDisabled: !b || O,
60
+ onPress: () => C.current?.click(),
61
+ children: /* @__PURE__ */ u(e, {
62
+ size: "lg",
63
+ isPending: O
64
+ })
65
+ }), /* @__PURE__ */ d(a, { children: [/* @__PURE__ */ d(i, {
66
+ isDisabled: !b || O,
67
+ size: "sm",
68
+ variant: "secondary",
69
+ children: [O && /* @__PURE__ */ u(s, { size: "sm" }), v.settings.changeAvatar]
70
+ }), /* @__PURE__ */ u(a.Popover, {
71
+ className: "min-w-fit",
72
+ children: /* @__PURE__ */ d(a.Menu, { children: [/* @__PURE__ */ d(a.Item, {
73
+ textValue: v.settings.uploadAvatar,
74
+ onAction: () => C.current?.click(),
75
+ children: [/* @__PURE__ */ u(m, { className: "text-muted" }), /* @__PURE__ */ u(o, { children: v.settings.uploadAvatar })]
76
+ }), /* @__PURE__ */ d(a.Item, {
77
+ textValue: v.settings.deleteAvatar,
78
+ isDisabled: !b?.user.image,
79
+ onAction: A,
80
+ variant: "danger",
81
+ children: [/* @__PURE__ */ u(h, { className: "text-danger" }), /* @__PURE__ */ u(o, { children: v.settings.deleteAvatar })]
82
+ })] })
83
+ })] })]
84
+ })
85
+ ]
86
+ });
56
87
  }
88
+ //#endregion
89
+ export { _ as ChangeAvatar };
@@ -1,4 +1,4 @@
1
- import { type CardProps } from "@heroui/react";
1
+ import { CardProps } from '@heroui/react';
2
2
  export type ChangeEmailProps = {
3
3
  className?: string;
4
4
  variant?: CardProps["variant"];
@@ -1,29 +1,57 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useAuth, useChangeEmail, useSession } from "@better-auth-ui/react";
3
- import { Button, Card, cn, FieldError, Fieldset, Form, Input, Label, Skeleton, Spinner, TextField, toast } from "@heroui/react";
4
- /**
5
- * Render a card containing a form to view and update the authenticated user's email.
6
- *
7
- * Shows a loading skeleton until session data is available, displays the current
8
- * email as the form's default value, and sends a verification email to the
9
- * new address upon successful submission.
10
- *
11
- * @returns A JSX element rendering the change-email card and form
12
- */
13
- export function ChangeEmail({ className, variant, ...props }) {
14
- const { localization, baseURL, viewPaths } = useAuth();
15
- const { data: session } = useSession();
16
- const { mutate: changeEmail, isPending } = useChangeEmail({
17
- onSuccess: () => toast.success(localization.settings.changeEmailSuccess),
18
- onError: (error) => toast.danger(error.error?.message || error.message)
19
- });
20
- function handleSubmit(e) {
21
- e.preventDefault();
22
- const formData = new FormData(e.currentTarget);
23
- changeEmail({
24
- newEmail: formData.get("email"),
25
- callbackURL: `${baseURL}/${viewPaths.settings.account}`
26
- });
27
- }
28
- return (_jsxs("div", { children: [_jsx("h2", { className: cn("text-sm font-semibold mb-3"), children: localization.settings.changeEmail }), _jsx(Card, { className: cn("p-4 gap-4", className), variant: variant, ...props, children: _jsx(Card.Content, { children: _jsx(Form, { onSubmit: handleSubmit, children: _jsxs(Fieldset, { className: "w-full gap-4", children: [_jsx(Fieldset.Group, { children: _jsxs(TextField, { name: "email", type: "email", defaultValue: session?.user.email, isDisabled: isPending || !session, children: [_jsx(Label, { children: localization.auth.email }), session ? (_jsx(Input, { required: true, variant: variant === "transparent" ? "primary" : "secondary", autoComplete: "email", placeholder: localization.auth.emailPlaceholder })) : (_jsx(Skeleton, { className: "h-10 md:h-9 w-full rounded-xl" })), _jsx(FieldError, {})] }, session?.user.email) }), _jsx(Fieldset.Actions, { children: _jsxs(Button, { type: "submit", isPending: isPending, isDisabled: !session, size: "sm", children: [isPending && _jsx(Spinner, { color: "current", size: "sm" }), localization.settings.updateEmail] }) })] }) }) }) })] }));
1
+ import { useAuth as e, useChangeEmail as t, useSession as n } from "@better-auth-ui/react";
2
+ import { Button as r, Card as i, FieldError as a, Fieldset as o, Form as s, Input as c, Label as l, Skeleton as u, Spinner as d, TextField as f, cn as p, toast as m } from "@heroui/react";
3
+ import { jsx as h, jsxs as g } from "react/jsx-runtime";
4
+ //#region src/components/settings/account/change-email.tsx
5
+ function _({ className: _, variant: v, ...y }) {
6
+ let { localization: b, baseURL: x, viewPaths: S } = e(), { data: C } = n(), { mutate: w, isPending: T } = t({
7
+ onSuccess: () => m.success(b.settings.changeEmailSuccess),
8
+ onError: (e) => m.danger(e.error?.message || e.message)
9
+ });
10
+ function E(e) {
11
+ e.preventDefault(), w({
12
+ newEmail: new FormData(e.currentTarget).get("email"),
13
+ callbackURL: `${x}/${S.settings.account}`
14
+ });
15
+ }
16
+ return /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("h2", {
17
+ className: p("text-sm font-semibold mb-3"),
18
+ children: b.settings.changeEmail
19
+ }), /* @__PURE__ */ h(i, {
20
+ className: p("p-4 gap-4", _),
21
+ variant: v,
22
+ ...y,
23
+ children: /* @__PURE__ */ h(i.Content, { children: /* @__PURE__ */ h(s, {
24
+ onSubmit: E,
25
+ children: /* @__PURE__ */ g(o, {
26
+ className: "w-full gap-4",
27
+ children: [/* @__PURE__ */ h(o.Group, { children: /* @__PURE__ */ g(f, {
28
+ name: "email",
29
+ type: "email",
30
+ defaultValue: C?.user.email,
31
+ isDisabled: T || !C,
32
+ children: [
33
+ /* @__PURE__ */ h(l, { children: b.auth.email }),
34
+ C ? /* @__PURE__ */ h(c, {
35
+ required: !0,
36
+ variant: v === "transparent" ? "primary" : "secondary",
37
+ autoComplete: "email",
38
+ placeholder: b.auth.emailPlaceholder
39
+ }) : /* @__PURE__ */ h(u, { className: "h-10 md:h-9 w-full rounded-xl" }),
40
+ /* @__PURE__ */ h(a, {})
41
+ ]
42
+ }, C?.user.email) }), /* @__PURE__ */ h(o.Actions, { children: /* @__PURE__ */ g(r, {
43
+ type: "submit",
44
+ isPending: T,
45
+ isDisabled: !C,
46
+ size: "sm",
47
+ children: [T && /* @__PURE__ */ h(d, {
48
+ color: "current",
49
+ size: "sm"
50
+ }), b.settings.updateEmail]
51
+ }) })]
52
+ })
53
+ }) })
54
+ })] });
29
55
  }
56
+ //#endregion
57
+ export { _ as ChangeEmail };
@@ -1,4 +1,4 @@
1
- import type { Session, User } from "better-auth";
1
+ import { Session, User } from 'better-auth';
2
2
  export type DeviceSession = {
3
3
  session: Session;
4
4
  user: User;