@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,79 +1,192 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useAuth, useChangePassword, useListAccounts, useRequestPasswordReset, useSession } from "@better-auth-ui/react";
3
- import { Eye, EyeSlash } from "@gravity-ui/icons";
4
- import { Button, Card, cn, FieldError, Fieldset, Form, Input, InputGroup, Label, Skeleton, Spinner, TextField, toast } from "@heroui/react";
5
- import { useState } from "react";
6
- /**
7
- * Render a card form for changing the authenticated user's password.
8
- *
9
- * When the user has a credential account, displays fields for current password,
10
- * new password, and optionally confirm password. When the user only has social
11
- * accounts, displays a prompt to set a password via the reset flow.
12
- *
13
- * @returns A JSX element containing the change-password or set-password card
14
- */
15
- export function ChangePassword({ className, variant, ...props }) {
16
- const { emailAndPassword, localization } = useAuth();
17
- const { data: session } = useSession();
18
- const { data: accounts, isPending: isAccountsPending } = useListAccounts();
19
- const hasCredentialAccount = accounts?.some((account) => account.providerId === "credential");
20
- if (!isAccountsPending && !hasCredentialAccount) {
21
- return _jsx(SetPassword, { className: className, variant: variant, ...props });
22
- }
23
- return (_jsx(ChangePasswordForm, { className: className, variant: variant, emailAndPassword: emailAndPassword, localization: localization, session: isAccountsPending ? undefined : session, ...props }));
1
+ import { useAuth as e, useChangePassword as t, useListAccounts as n, useRequestPasswordReset as r, useSession as i } from "@better-auth-ui/react";
2
+ import { Button as a, Card as o, FieldError as s, Fieldset as c, Form as l, Input as u, InputGroup as d, Label as f, Skeleton as p, Spinner as m, TextField as h, cn as g, toast as _ } from "@heroui/react";
3
+ import { jsx as v, jsxs as y } from "react/jsx-runtime";
4
+ import { useState as b } from "react";
5
+ import { Eye as x, EyeSlash as S } from "@gravity-ui/icons";
6
+ //#region src/components/settings/security/change-password.tsx
7
+ function C({ className: t, variant: r, ...a }) {
8
+ let { emailAndPassword: o, localization: s } = e(), { data: c } = i(), { data: l, isPending: u } = n(), d = l?.some((e) => e.providerId === "credential");
9
+ return !u && !d ? /* @__PURE__ */ v(w, {
10
+ className: t,
11
+ variant: r,
12
+ ...a
13
+ }) : /* @__PURE__ */ v(T, {
14
+ className: t,
15
+ variant: r,
16
+ emailAndPassword: o,
17
+ localization: s,
18
+ session: u ? void 0 : c,
19
+ ...a
20
+ });
24
21
  }
25
- function SetPassword({ className, variant, ...props }) {
26
- const { localization } = useAuth();
27
- const { data: session } = useSession();
28
- const { mutate: requestPasswordReset, isPending } = useRequestPasswordReset({
29
- onError: (error) => toast.danger(error.error?.message || error.message),
30
- onSuccess: () => toast.success(localization.auth.passwordResetEmailSent)
31
- });
32
- const handleSetPassword = () => {
33
- if (!session?.user.email)
34
- return;
35
- requestPasswordReset({ email: session.user.email });
36
- };
37
- return (_jsxs("div", { children: [_jsx("h2", { className: cn("text-sm font-semibold mb-3"), children: localization.settings.changePassword }), _jsx(Card, { className: cn(className), variant: variant, ...props, children: _jsxs(Card.Content, { 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.setPassword }), _jsx("p", { className: "text-muted text-xs mt-0.5", children: localization.settings.setPasswordDescription })] }), _jsxs(Button, { size: "sm", isPending: isPending, isDisabled: !session, onPress: handleSetPassword, children: [isPending && _jsx(Spinner, { color: "current", size: "sm" }), localization.auth.sendResetLink] })] }) })] }));
22
+ function w({ className: t, variant: n, ...s }) {
23
+ let { localization: c } = e(), { data: l } = i(), { mutate: u, isPending: d } = r({
24
+ onError: (e) => _.danger(e.error?.message || e.message),
25
+ onSuccess: () => _.success(c.auth.passwordResetEmailSent)
26
+ }), f = () => {
27
+ l?.user.email && u({ email: l.user.email });
28
+ };
29
+ return /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("h2", {
30
+ className: g("text-sm font-semibold mb-3"),
31
+ children: c.settings.changePassword
32
+ }), /* @__PURE__ */ v(o, {
33
+ className: g(t),
34
+ variant: n,
35
+ ...s,
36
+ children: /* @__PURE__ */ y(o.Content, {
37
+ className: "flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between",
38
+ children: [/* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("p", {
39
+ className: "text-sm font-medium leading-tight",
40
+ children: c.settings.setPassword
41
+ }), /* @__PURE__ */ v("p", {
42
+ className: "text-muted text-xs mt-0.5",
43
+ children: c.settings.setPasswordDescription
44
+ })] }), /* @__PURE__ */ y(a, {
45
+ size: "sm",
46
+ isPending: d,
47
+ isDisabled: !l,
48
+ onPress: f,
49
+ children: [d && /* @__PURE__ */ v(m, {
50
+ color: "current",
51
+ size: "sm"
52
+ }), c.auth.sendResetLink]
53
+ })]
54
+ })
55
+ })] });
38
56
  }
39
- function ChangePasswordForm({ className, variant, emailAndPassword, localization, session, ...props }) {
40
- const [currentPassword, setCurrentPassword] = useState("");
41
- const [newPassword, setNewPassword] = useState("");
42
- const [confirmPassword, setConfirmPassword] = useState("");
43
- const { mutate: changePassword, isPending } = useChangePassword({
44
- onError: (error) => {
45
- setCurrentPassword("");
46
- setNewPassword("");
47
- setConfirmPassword("");
48
- toast.danger(error.error?.message || error.message);
49
- },
50
- onSuccess: () => {
51
- setCurrentPassword("");
52
- setNewPassword("");
53
- setConfirmPassword("");
54
- toast.success(localization.settings.changePasswordSuccess);
55
- }
56
- });
57
- const [isNewPasswordVisible, setIsNewPasswordVisible] = useState(false);
58
- const [isConfirmPasswordVisible, setIsConfirmPasswordVisible] = useState(false);
59
- const handleSubmit = (e) => {
60
- e.preventDefault();
61
- if (emailAndPassword?.confirmPassword && newPassword !== confirmPassword) {
62
- setCurrentPassword("");
63
- setNewPassword("");
64
- setConfirmPassword("");
65
- toast.danger(localization.auth.passwordsDoNotMatch);
66
- return;
67
- }
68
- changePassword({
69
- currentPassword,
70
- newPassword,
71
- revokeOtherSessions: true
72
- });
73
- };
74
- return (_jsxs("div", { children: [_jsx("h2", { className: cn("text-sm font-semibold mb-3"), children: localization.settings.changePassword }), _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: [_jsxs(Fieldset.Group, { children: [_jsxs(TextField, { name: "currentPassword", type: "password", isDisabled: isPending || !session, defaultValue: "", value: currentPassword, onChange: setCurrentPassword, children: [_jsx(Label, { children: localization.settings.currentPassword }), _jsx(Input, { className: cn(!session && "hidden"), autoComplete: "current-password", placeholder: localization.settings.currentPasswordPlaceholder, required: true, variant: variant === "transparent" ? "primary" : "secondary" }), !session && (_jsx(Skeleton, { className: "h-10 md:h-9 w-full rounded-xl" })), _jsx(FieldError, {})] }), _jsxs(TextField, { minLength: emailAndPassword?.minPasswordLength, maxLength: emailAndPassword?.maxPasswordLength, isDisabled: isPending || !session, value: newPassword, onChange: setNewPassword, children: [_jsx(Label, { children: localization.auth.newPassword }), _jsxs(InputGroup, { className: cn(!session && "hidden"), variant: variant === "transparent" ? "primary" : "secondary", children: [_jsx(InputGroup.Input, { name: "newPassword", type: isNewPasswordVisible ? "text" : "password", autoComplete: "new-password", placeholder: localization.auth.newPasswordPlaceholder, required: true }), _jsx(InputGroup.Suffix, { className: "px-0", children: _jsx(Button, { isIconOnly: true, "aria-label": isNewPasswordVisible
75
- ? localization.auth.hidePassword
76
- : localization.auth.showPassword, size: "sm", variant: "ghost", onPress: () => setIsNewPasswordVisible(!isNewPasswordVisible), isDisabled: isPending, children: isNewPasswordVisible ? _jsx(EyeSlash, {}) : _jsx(Eye, {}) }) })] }), !session && (_jsx(Skeleton, { className: "h-10 md:h-9 w-full rounded-xl" })), _jsx(FieldError, {})] }), emailAndPassword?.confirmPassword && (_jsxs(TextField, { minLength: emailAndPassword?.minPasswordLength, maxLength: emailAndPassword?.maxPasswordLength, isDisabled: isPending || !session, isRequired: true, value: confirmPassword, onChange: setConfirmPassword, children: [_jsx(Label, { children: localization.auth.confirmPassword }), _jsxs(InputGroup, { className: cn(!session && "hidden"), variant: variant === "transparent" ? "primary" : "secondary", children: [_jsx(InputGroup.Input, { name: "confirmPassword", type: isConfirmPasswordVisible ? "text" : "password", autoComplete: "new-password", placeholder: localization.auth.confirmPasswordPlaceholder, required: true }), _jsx(InputGroup.Suffix, { className: "px-0", children: _jsx(Button, { isIconOnly: true, "aria-label": isConfirmPasswordVisible
77
- ? localization.auth.hidePassword
78
- : localization.auth.showPassword, size: "sm", variant: "ghost", onPress: () => setIsConfirmPasswordVisible(!isConfirmPasswordVisible), isDisabled: isPending, children: isConfirmPasswordVisible ? _jsx(EyeSlash, {}) : _jsx(Eye, {}) }) })] }), !session && (_jsx(Skeleton, { className: "h-10 md:h-9 w-full rounded-xl" })), _jsx(FieldError, {})] }))] }), _jsx(Fieldset.Actions, { children: _jsxs(Button, { type: "submit", isPending: isPending, isDisabled: !session, size: "sm", children: [isPending && _jsx(Spinner, { color: "current", size: "sm" }), localization.settings.updatePassword] }) })] }) }) }) })] }));
57
+ function T({ className: e, variant: n, emailAndPassword: r, localization: i, session: C, ...w }) {
58
+ let [T, E] = b(""), [D, O] = b(""), [k, A] = b(""), { mutate: j, isPending: M } = t({
59
+ onError: (e) => {
60
+ E(""), O(""), A(""), _.danger(e.error?.message || e.message);
61
+ },
62
+ onSuccess: () => {
63
+ E(""), O(""), A(""), _.success(i.settings.changePasswordSuccess);
64
+ }
65
+ }), [N, P] = b(!1), [F, I] = b(!1), L = (e) => {
66
+ if (e.preventDefault(), r?.confirmPassword && D !== k) {
67
+ E(""), O(""), A(""), _.danger(i.auth.passwordsDoNotMatch);
68
+ return;
69
+ }
70
+ j({
71
+ currentPassword: T,
72
+ newPassword: D,
73
+ revokeOtherSessions: !0
74
+ });
75
+ };
76
+ return /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("h2", {
77
+ className: g("text-sm font-semibold mb-3"),
78
+ children: i.settings.changePassword
79
+ }), /* @__PURE__ */ v(o, {
80
+ className: g("p-4 gap-4", e),
81
+ variant: n,
82
+ ...w,
83
+ children: /* @__PURE__ */ v(o.Content, { children: /* @__PURE__ */ v(l, {
84
+ onSubmit: L,
85
+ children: /* @__PURE__ */ y(c, {
86
+ className: "w-full gap-4",
87
+ children: [/* @__PURE__ */ y(c.Group, { children: [
88
+ /* @__PURE__ */ y(h, {
89
+ name: "currentPassword",
90
+ type: "password",
91
+ isDisabled: M || !C,
92
+ defaultValue: "",
93
+ value: T,
94
+ onChange: E,
95
+ children: [
96
+ /* @__PURE__ */ v(f, { children: i.settings.currentPassword }),
97
+ /* @__PURE__ */ v(u, {
98
+ className: g(!C && "hidden"),
99
+ autoComplete: "current-password",
100
+ placeholder: i.settings.currentPasswordPlaceholder,
101
+ required: !0,
102
+ variant: n === "transparent" ? "primary" : "secondary"
103
+ }),
104
+ !C && /* @__PURE__ */ v(p, { className: "h-10 md:h-9 w-full rounded-xl" }),
105
+ /* @__PURE__ */ v(s, {})
106
+ ]
107
+ }),
108
+ /* @__PURE__ */ y(h, {
109
+ minLength: r?.minPasswordLength,
110
+ maxLength: r?.maxPasswordLength,
111
+ isDisabled: M || !C,
112
+ value: D,
113
+ onChange: O,
114
+ children: [
115
+ /* @__PURE__ */ v(f, { children: i.auth.newPassword }),
116
+ /* @__PURE__ */ y(d, {
117
+ className: g(!C && "hidden"),
118
+ variant: n === "transparent" ? "primary" : "secondary",
119
+ children: [/* @__PURE__ */ v(d.Input, {
120
+ name: "newPassword",
121
+ type: N ? "text" : "password",
122
+ autoComplete: "new-password",
123
+ placeholder: i.auth.newPasswordPlaceholder,
124
+ required: !0
125
+ }), /* @__PURE__ */ v(d.Suffix, {
126
+ className: "px-0",
127
+ children: /* @__PURE__ */ v(a, {
128
+ isIconOnly: !0,
129
+ "aria-label": N ? i.auth.hidePassword : i.auth.showPassword,
130
+ size: "sm",
131
+ variant: "ghost",
132
+ onPress: () => P(!N),
133
+ isDisabled: M,
134
+ children: v(N ? S : x, {})
135
+ })
136
+ })]
137
+ }),
138
+ !C && /* @__PURE__ */ v(p, { className: "h-10 md:h-9 w-full rounded-xl" }),
139
+ /* @__PURE__ */ v(s, {})
140
+ ]
141
+ }),
142
+ r?.confirmPassword && /* @__PURE__ */ y(h, {
143
+ minLength: r?.minPasswordLength,
144
+ maxLength: r?.maxPasswordLength,
145
+ isDisabled: M || !C,
146
+ isRequired: !0,
147
+ value: k,
148
+ onChange: A,
149
+ children: [
150
+ /* @__PURE__ */ v(f, { children: i.auth.confirmPassword }),
151
+ /* @__PURE__ */ y(d, {
152
+ className: g(!C && "hidden"),
153
+ variant: n === "transparent" ? "primary" : "secondary",
154
+ children: [/* @__PURE__ */ v(d.Input, {
155
+ name: "confirmPassword",
156
+ type: F ? "text" : "password",
157
+ autoComplete: "new-password",
158
+ placeholder: i.auth.confirmPasswordPlaceholder,
159
+ required: !0
160
+ }), /* @__PURE__ */ v(d.Suffix, {
161
+ className: "px-0",
162
+ children: /* @__PURE__ */ v(a, {
163
+ isIconOnly: !0,
164
+ "aria-label": F ? i.auth.hidePassword : i.auth.showPassword,
165
+ size: "sm",
166
+ variant: "ghost",
167
+ onPress: () => I(!F),
168
+ isDisabled: M,
169
+ children: v(F ? S : x, {})
170
+ })
171
+ })]
172
+ }),
173
+ !C && /* @__PURE__ */ v(p, { className: "h-10 md:h-9 w-full rounded-xl" }),
174
+ /* @__PURE__ */ v(s, {})
175
+ ]
176
+ })
177
+ ] }), /* @__PURE__ */ v(c.Actions, { children: /* @__PURE__ */ y(a, {
178
+ type: "submit",
179
+ isPending: M,
180
+ isDisabled: !C,
181
+ size: "sm",
182
+ children: [M && /* @__PURE__ */ v(m, {
183
+ color: "current",
184
+ size: "sm"
185
+ }), i.settings.updatePassword]
186
+ }) })]
187
+ })
188
+ }) })
189
+ })] });
79
190
  }
191
+ //#endregion
192
+ export { C as ChangePassword };
@@ -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 DangerZoneProps = {
4
4
  className?: string;
5
5
  variant?: CardProps["variant"];
@@ -1,12 +1,18 @@
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 { DeleteUser } from "./delete-user";
5
- /**
6
- * Renders the danger zone heading and {@link DeleteUser}.
7
- * Gate with `deleteUser.enabled` at the call site (e.g. {@link SecuritySettings}).
8
- */
9
- export function DangerZone({ className, variant, ...props }) {
10
- const { localization } = useAuth();
11
- return (_jsxs("div", { className: cn("flex w-full flex-col", className), ...props, children: [_jsx("h2", { className: cn("text-sm font-semibold mb-3"), children: localization.settings.dangerZone }), _jsx(DeleteUser, { variant: variant })] }));
1
+ import { DeleteUser as e } from "./delete-user.js";
2
+ import { useAuth as t } from "@better-auth-ui/react";
3
+ import { cn as n } from "@heroui/react";
4
+ import { jsx as r, jsxs as i } from "react/jsx-runtime";
5
+ //#region src/components/settings/security/danger-zone.tsx
6
+ function a({ className: a, variant: o, ...s }) {
7
+ let { localization: c } = t();
8
+ return /* @__PURE__ */ i("div", {
9
+ className: n("flex w-full flex-col", a),
10
+ ...s,
11
+ children: [/* @__PURE__ */ r("h2", {
12
+ className: n("text-sm font-semibold mb-3"),
13
+ children: c.settings.dangerZone
14
+ }), /* @__PURE__ */ r(e, { variant: o })]
15
+ });
12
16
  }
17
+ //#endregion
18
+ export { a as DangerZone };
@@ -1,4 +1,4 @@
1
- import { type CardProps } from "@heroui/react";
1
+ import { CardProps } from '@heroui/react';
2
2
  export type DeleteUserProps = {
3
3
  className?: string;
4
4
  variant?: CardProps["variant"];
@@ -1,47 +1,97 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useAuth, useDeleteUser, useListAccounts } from "@better-auth-ui/react";
3
- import { TriangleExclamation } from "@gravity-ui/icons";
4
- import { AlertDialog, Button, Card, cn, FieldError, Form, Input, Label, Spinner, TextField, toast } from "@heroui/react";
5
- import { useState } from "react";
6
- /**
7
- * Danger-zone card to delete the authenticated account, with a confirmation dialog and toasts.
8
- */
9
- export function DeleteUser({ className, variant, ...props }) {
10
- const { basePaths, deleteUser: deleteUserConfig, localization, navigate, viewPaths } = useAuth();
11
- const { data: accounts } = useListAccounts();
12
- const [confirmOpen, setConfirmOpen] = useState(false);
13
- const [password, setPassword] = useState("");
14
- const hasCredentialAccount = accounts?.some((account) => account.providerId === "credential");
15
- const needsPassword = !deleteUserConfig?.sendDeleteAccountVerification && hasCredentialAccount;
16
- const { mutate: deleteUser, isPending } = useDeleteUser();
17
- const handleDialogOpenChange = (open) => {
18
- setConfirmOpen(open);
19
- setPassword("");
20
- };
21
- const handleSubmit = async (e) => {
22
- e.preventDefault();
23
- const params = {
24
- ...(needsPassword ? { password } : {})
25
- };
26
- deleteUser(params, {
27
- onSuccess: () => {
28
- setConfirmOpen(false);
29
- setPassword("");
30
- if (deleteUserConfig?.sendDeleteAccountVerification) {
31
- toast.success(localization.settings.deleteUserVerificationSent);
32
- }
33
- else {
34
- toast.success(localization.settings.deleteUserSuccess);
35
- navigate({
36
- to: `${basePaths.auth}/${viewPaths.auth.signIn}`,
37
- replace: true
38
- });
39
- }
40
- },
41
- onError: (error) => {
42
- toast.danger(error.error?.message || error.message);
43
- }
44
- });
45
- };
46
- return (_jsx(Card, { className: cn("border border-danger", className), variant: variant, ...props, children: _jsxs(Card.Content, { 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.deleteUser }), _jsx("p", { className: "text-muted text-xs mt-0.5", children: localization.settings.deleteUserDescription })] }), _jsxs(AlertDialog, { children: [_jsx(Button, { isDisabled: !accounts, size: "sm", variant: "danger", onPress: () => setConfirmOpen(true), children: localization.settings.deleteUser }), _jsx(AlertDialog.Backdrop, { isOpen: confirmOpen, onOpenChange: handleDialogOpenChange, children: _jsx(AlertDialog.Container, { children: _jsx(AlertDialog.Dialog, { children: _jsxs(Form, { onSubmit: handleSubmit, children: [_jsx(AlertDialog.CloseTrigger, {}), _jsxs(AlertDialog.Header, { children: [_jsx(AlertDialog.Icon, { status: "danger", children: _jsx(TriangleExclamation, {}) }), _jsx(AlertDialog.Heading, { children: localization.settings.deleteUser })] }), _jsxs(AlertDialog.Body, { className: "overflow-visible", children: [_jsx("p", { className: "text-muted text-sm", children: localization.settings.deleteUserDescription }), needsPassword && (_jsxs(TextField, { className: "mt-4", name: "password", type: "password", isDisabled: isPending, value: password, onChange: setPassword, children: [_jsx(Label, { children: localization.auth.password }), _jsx(Input, { autoComplete: "current-password", placeholder: localization.auth.passwordPlaceholder, required: true, variant: "secondary" }), _jsx(FieldError, {})] }))] }), _jsxs(AlertDialog.Footer, { children: [_jsx(Button, { slot: "close", variant: "tertiary", isDisabled: isPending, children: localization.settings.cancel }), _jsxs(Button, { type: "submit", variant: "danger", isPending: isPending, children: [isPending && _jsx(Spinner, { color: "current", size: "sm" }), localization.settings.deleteUser] })] })] }) }) }) })] })] }) }));
1
+ import { useAuth as e, useDeleteUser as t, useListAccounts as n } from "@better-auth-ui/react";
2
+ import { AlertDialog as r, Button as i, Card as a, FieldError as o, Form as s, Input as c, Label as l, Spinner as u, TextField as d, cn as f, toast as p } from "@heroui/react";
3
+ import { jsx as m, jsxs as h } from "react/jsx-runtime";
4
+ import { useState as g } from "react";
5
+ import { TriangleExclamation as _ } from "@gravity-ui/icons";
6
+ //#region src/components/settings/security/delete-user.tsx
7
+ function v({ className: v, variant: y, ...b }) {
8
+ let { basePaths: x, deleteUser: S, localization: C, navigate: w, viewPaths: T } = e(), { data: E } = n(), [D, O] = g(!1), [k, A] = g(""), j = E?.some((e) => e.providerId === "credential"), M = !S?.sendDeleteAccountVerification && j, { mutate: N, isPending: P } = t(), F = (e) => {
9
+ O(e), A("");
10
+ }, I = async (e) => {
11
+ e.preventDefault(), N({ ...M ? { password: k } : {} }, {
12
+ onSuccess: () => {
13
+ O(!1), A(""), S?.sendDeleteAccountVerification ? p.success(C.settings.deleteUserVerificationSent) : (p.success(C.settings.deleteUserSuccess), w({
14
+ to: `${x.auth}/${T.auth.signIn}`,
15
+ replace: !0
16
+ }));
17
+ },
18
+ onError: (e) => {
19
+ p.danger(e.error?.message || e.message);
20
+ }
21
+ });
22
+ };
23
+ return /* @__PURE__ */ m(a, {
24
+ className: f("border border-danger", v),
25
+ variant: y,
26
+ ...b,
27
+ children: /* @__PURE__ */ h(a.Content, {
28
+ className: "flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between",
29
+ children: [/* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("p", {
30
+ className: "text-sm font-medium leading-tight",
31
+ children: C.settings.deleteUser
32
+ }), /* @__PURE__ */ m("p", {
33
+ className: "text-muted text-xs mt-0.5",
34
+ children: C.settings.deleteUserDescription
35
+ })] }), /* @__PURE__ */ h(r, { children: [/* @__PURE__ */ m(i, {
36
+ isDisabled: !E,
37
+ size: "sm",
38
+ variant: "danger",
39
+ onPress: () => O(!0),
40
+ children: C.settings.deleteUser
41
+ }), /* @__PURE__ */ m(r.Backdrop, {
42
+ isOpen: D,
43
+ onOpenChange: F,
44
+ children: /* @__PURE__ */ m(r.Container, { children: /* @__PURE__ */ m(r.Dialog, { children: /* @__PURE__ */ h(s, {
45
+ onSubmit: I,
46
+ children: [
47
+ /* @__PURE__ */ m(r.CloseTrigger, {}),
48
+ /* @__PURE__ */ h(r.Header, { children: [/* @__PURE__ */ m(r.Icon, {
49
+ status: "danger",
50
+ children: /* @__PURE__ */ m(_, {})
51
+ }), /* @__PURE__ */ m(r.Heading, { children: C.settings.deleteUser })] }),
52
+ /* @__PURE__ */ h(r.Body, {
53
+ className: "overflow-visible",
54
+ children: [/* @__PURE__ */ m("p", {
55
+ className: "text-muted text-sm",
56
+ children: C.settings.deleteUserDescription
57
+ }), M && /* @__PURE__ */ h(d, {
58
+ className: "mt-4",
59
+ name: "password",
60
+ type: "password",
61
+ isDisabled: P,
62
+ value: k,
63
+ onChange: A,
64
+ children: [
65
+ /* @__PURE__ */ m(l, { children: C.auth.password }),
66
+ /* @__PURE__ */ m(c, {
67
+ autoComplete: "current-password",
68
+ placeholder: C.auth.passwordPlaceholder,
69
+ required: !0,
70
+ variant: "secondary"
71
+ }),
72
+ /* @__PURE__ */ m(o, {})
73
+ ]
74
+ })]
75
+ }),
76
+ /* @__PURE__ */ h(r.Footer, { children: [/* @__PURE__ */ m(i, {
77
+ slot: "close",
78
+ variant: "tertiary",
79
+ isDisabled: P,
80
+ children: C.settings.cancel
81
+ }), /* @__PURE__ */ h(i, {
82
+ type: "submit",
83
+ variant: "danger",
84
+ isPending: P,
85
+ children: [P && /* @__PURE__ */ m(u, {
86
+ color: "current",
87
+ size: "sm"
88
+ }), C.settings.deleteUser]
89
+ })] })
90
+ ]
91
+ }) }) })
92
+ })] })]
93
+ })
94
+ });
47
95
  }
96
+ //#endregion
97
+ export { v as DeleteUser };
@@ -1,4 +1,4 @@
1
- import type { Account, SocialProvider } from "better-auth";
1
+ import { Account, SocialProvider } from 'better-auth';
2
2
  export type LinkedAccountProps = {
3
3
  account?: Account;
4
4
  provider: SocialProvider;
@@ -1,48 +1,62 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { getProviderName } from "@better-auth-ui/core";
3
- import { providerIcons, useAccountInfo, useAuth, useLinkSocial, useUnlinkAccount } from "@better-auth-ui/react";
4
- import { Link, LinkSlash, PlugConnection } from "@gravity-ui/icons";
5
- import { Button, cn, Skeleton, Spinner, toast } from "@heroui/react";
6
- /**
7
- * Render a single linked social account row with provider info and link/unlink control.
8
- *
9
- * Fetches additional account information from the provider using the accountInfo API
10
- * and displays the provider name, account details, and a link/unlink button.
11
- *
12
- * @param account - The account object containing id, accountId, and providerId
13
- * @param provider - The provider id
14
- * @returns A JSX element containing the linked account row
15
- */
16
- export function LinkedAccount({ account, provider }) {
17
- const { baseURL, localization } = useAuth();
18
- const { data: accountInfo, isPending: isLoadingInfo } = useAccountInfo(account?.accountId, {
19
- enabled: !!account,
20
- throwOnError: (error) => {
21
- if (error.error)
22
- toast.danger(error.error.message);
23
- return false;
24
- }
25
- });
26
- const { mutate: linkSocial, isPending: isLinking } = useLinkSocial({
27
- onError: (error) => toast.danger(error.error?.message || error.message)
28
- });
29
- const { mutate: unlinkAccount, isPending: isUnlinking } = useUnlinkAccount({
30
- onError: (error) => toast.danger(error.error?.message || error.message),
31
- onSuccess: () => toast.success(localization.settings.accountUnlinked)
32
- });
33
- const ProviderIcon = providerIcons[provider];
34
- const providerName = getProviderName(provider);
35
- const displayName = accountInfo?.data?.login ||
36
- accountInfo?.data?.username ||
37
- accountInfo?.user?.email ||
38
- accountInfo?.user?.name ||
39
- account?.accountId;
40
- return (_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: cn("flex size-10 shrink-0 items-center justify-center rounded-xl bg-surface-secondary"), children: ProviderIcon ? (_jsx(ProviderIcon, { className: cn("size-4.5", !account && "opacity-50") })) : (_jsx(PlugConnection, { className: cn("size-4.5", !account && "opacity-50") })) }), _jsxs("div", { className: "flex flex-col min-w-0", children: [_jsx("span", { className: "text-sm font-medium leading-tight", children: providerName }), account && isLoadingInfo ? (_jsx(Skeleton, { className: "h-3 w-24 my-0.5 rounded-lg" })) : (_jsx("span", { className: "text-xs text-muted truncate", children: account
41
- ? displayName
42
- : localization.settings.linkProvider.replace("{{provider}}", providerName) }))] }), account ? (_jsxs(Button, { className: "ml-auto shrink-0", variant: "outline", size: "sm", onPress: () => unlinkAccount({ providerId: account.providerId }), isPending: isUnlinking, "aria-label": localization.settings.unlinkProvider.replace("{{provider}}", providerName), children: [isUnlinking ? _jsx(Spinner, { color: "current", size: "sm" }) : _jsx(LinkSlash, {}), localization.settings.unlinkProvider
43
- .replace("{{provider}}", "")
44
- .trim()] })) : (_jsxs(Button, { className: "ml-auto shrink-0", variant: "outline", size: "sm", onPress: () => linkSocial({
45
- provider,
46
- callbackURL: `${baseURL}${window.location.pathname}`
47
- }), isPending: isLinking, "aria-label": localization.settings.linkProvider.replace("{{provider}}", providerName), children: [isLinking ? _jsx(Spinner, { color: "current", size: "sm" }) : _jsx(Link, {}), localization.settings.link] }))] }));
1
+ import { providerIcons as e, useAccountInfo as t, useAuth as n, useLinkSocial as r, useUnlinkAccount as i } from "@better-auth-ui/react";
2
+ import { Button as a, Skeleton as o, Spinner as s, cn as c, toast as l } from "@heroui/react";
3
+ import { jsx as u, jsxs as d } from "react/jsx-runtime";
4
+ import { Link as f, LinkSlash as p, PlugConnection as m } from "@gravity-ui/icons";
5
+ import { getProviderName as h } from "@better-auth-ui/core";
6
+ //#region src/components/settings/security/linked-account.tsx
7
+ function g({ account: g, provider: _ }) {
8
+ let { baseURL: v, localization: y } = n(), { data: b, isPending: x } = t(g?.accountId, {
9
+ enabled: !!g,
10
+ throwOnError: (e) => (e.error && l.danger(e.error.message), !1)
11
+ }), { mutate: S, isPending: C } = r({ onError: (e) => l.danger(e.error?.message || e.message) }), { mutate: w, isPending: T } = i({
12
+ onError: (e) => l.danger(e.error?.message || e.message),
13
+ onSuccess: () => l.success(y.settings.accountUnlinked)
14
+ }), E = e[_], D = h(_), O = b?.data?.login || b?.data?.username || b?.user?.email || b?.user?.name || g?.accountId;
15
+ return /* @__PURE__ */ d("div", {
16
+ className: "flex items-center gap-3",
17
+ children: [
18
+ /* @__PURE__ */ u("div", {
19
+ className: c("flex size-10 shrink-0 items-center justify-center rounded-xl bg-surface-secondary"),
20
+ children: u(E || m, { className: c("size-4.5", !g && "opacity-50") })
21
+ }),
22
+ /* @__PURE__ */ d("div", {
23
+ className: "flex flex-col min-w-0",
24
+ children: [/* @__PURE__ */ u("span", {
25
+ className: "text-sm font-medium leading-tight",
26
+ children: D
27
+ }), g && x ? /* @__PURE__ */ u(o, { className: "h-3 w-24 my-0.5 rounded-lg" }) : /* @__PURE__ */ u("span", {
28
+ className: "text-xs text-muted truncate",
29
+ children: g ? O : y.settings.linkProvider.replace("{{provider}}", D)
30
+ })]
31
+ }),
32
+ g ? /* @__PURE__ */ d(a, {
33
+ className: "ml-auto shrink-0",
34
+ variant: "outline",
35
+ size: "sm",
36
+ onPress: () => w({ providerId: g.providerId }),
37
+ isPending: T,
38
+ "aria-label": y.settings.unlinkProvider.replace("{{provider}}", D),
39
+ children: [T ? /* @__PURE__ */ u(s, {
40
+ color: "current",
41
+ size: "sm"
42
+ }) : /* @__PURE__ */ u(p, {}), y.settings.unlinkProvider.replace("{{provider}}", "").trim()]
43
+ }) : /* @__PURE__ */ d(a, {
44
+ className: "ml-auto shrink-0",
45
+ variant: "outline",
46
+ size: "sm",
47
+ onPress: () => S({
48
+ provider: _,
49
+ callbackURL: `${v}${window.location.pathname}`
50
+ }),
51
+ isPending: C,
52
+ "aria-label": y.settings.linkProvider.replace("{{provider}}", D),
53
+ children: [C ? /* @__PURE__ */ u(s, {
54
+ color: "current",
55
+ size: "sm"
56
+ }) : /* @__PURE__ */ u(f, {}), y.settings.link]
57
+ })
58
+ ]
59
+ });
48
60
  }
61
+ //#endregion
62
+ export { g as LinkedAccount };
@@ -1,4 +1,4 @@
1
- import { type CardProps } from "@heroui/react";
1
+ import { CardProps } from '@heroui/react';
2
2
  export type LinkedAccountsProps = {
3
3
  className?: string;
4
4
  variant?: CardProps["variant"];