@stackframe/stack 2.5.33 → 2.5.35

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 (126) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/components/credential-sign-in.js +14 -12
  3. package/dist/components/credential-sign-in.js.map +1 -1
  4. package/dist/components/credential-sign-up.js +17 -15
  5. package/dist/components/credential-sign-up.js.map +1 -1
  6. package/dist/components/elements/maybe-full-page.d.mts +2 -2
  7. package/dist/components/elements/maybe-full-page.d.ts +2 -2
  8. package/dist/components/elements/sidebar-layout.d.mts +5 -5
  9. package/dist/components/elements/sidebar-layout.d.ts +5 -5
  10. package/dist/components/magic-link-sign-in.js +11 -9
  11. package/dist/components/magic-link-sign-in.js.map +1 -1
  12. package/dist/components/message-cards/message-card.d.mts +2 -2
  13. package/dist/components/message-cards/message-card.d.ts +2 -2
  14. package/dist/components/oauth-button-group.js.map +1 -1
  15. package/dist/components/oauth-button.js +48 -2
  16. package/dist/components/oauth-button.js.map +1 -1
  17. package/dist/components/profile-image-editor.js +5 -3
  18. package/dist/components/profile-image-editor.js.map +1 -1
  19. package/dist/components/selected-team-switcher.js +8 -5
  20. package/dist/components/selected-team-switcher.js.map +1 -1
  21. package/dist/components/team-icon.js.map +1 -1
  22. package/dist/components/user-button.d.mts +2 -2
  23. package/dist/components/user-button.d.ts +2 -2
  24. package/dist/components/user-button.js +11 -11
  25. package/dist/components/user-button.js.map +1 -1
  26. package/dist/components-page/account-settings.js +79 -66
  27. package/dist/components-page/account-settings.js.map +1 -1
  28. package/dist/components-page/auth-page.js +11 -7
  29. package/dist/components-page/auth-page.js.map +1 -1
  30. package/dist/components-page/email-verification.js +4 -2
  31. package/dist/components-page/email-verification.js.map +1 -1
  32. package/dist/components-page/error-page.js +6 -4
  33. package/dist/components-page/error-page.js.map +1 -1
  34. package/dist/components-page/forgot-password.js +12 -8
  35. package/dist/components-page/forgot-password.js.map +1 -1
  36. package/dist/components-page/magic-link-callback.js +5 -3
  37. package/dist/components-page/magic-link-callback.js.map +1 -1
  38. package/dist/components-page/oauth-callback.js +6 -5
  39. package/dist/components-page/oauth-callback.js.map +1 -1
  40. package/dist/components-page/password-reset.js +25 -22
  41. package/dist/components-page/password-reset.js.map +1 -1
  42. package/dist/components-page/team-creation.js +9 -7
  43. package/dist/components-page/team-creation.js.map +1 -1
  44. package/dist/components-page/team-invitation.js +14 -11
  45. package/dist/components-page/team-invitation.js.map +1 -1
  46. package/dist/esm/components/credential-sign-in.js +14 -12
  47. package/dist/esm/components/credential-sign-in.js.map +1 -1
  48. package/dist/esm/components/credential-sign-up.js +17 -15
  49. package/dist/esm/components/credential-sign-up.js.map +1 -1
  50. package/dist/esm/components/magic-link-sign-in.js +11 -9
  51. package/dist/esm/components/magic-link-sign-in.js.map +1 -1
  52. package/dist/esm/components/oauth-button-group.js.map +1 -1
  53. package/dist/esm/components/oauth-button.js +48 -2
  54. package/dist/esm/components/oauth-button.js.map +1 -1
  55. package/dist/esm/components/profile-image-editor.js +5 -3
  56. package/dist/esm/components/profile-image-editor.js.map +1 -1
  57. package/dist/esm/components/selected-team-switcher.js +8 -5
  58. package/dist/esm/components/selected-team-switcher.js.map +1 -1
  59. package/dist/esm/components/team-icon.js.map +1 -1
  60. package/dist/esm/components/user-button.js +12 -15
  61. package/dist/esm/components/user-button.js.map +1 -1
  62. package/dist/esm/components-page/account-settings.js +79 -66
  63. package/dist/esm/components-page/account-settings.js.map +1 -1
  64. package/dist/esm/components-page/auth-page.js +11 -7
  65. package/dist/esm/components-page/auth-page.js.map +1 -1
  66. package/dist/esm/components-page/email-verification.js +4 -2
  67. package/dist/esm/components-page/email-verification.js.map +1 -1
  68. package/dist/esm/components-page/error-page.js +6 -4
  69. package/dist/esm/components-page/error-page.js.map +1 -1
  70. package/dist/esm/components-page/forgot-password.js +12 -8
  71. package/dist/esm/components-page/forgot-password.js.map +1 -1
  72. package/dist/esm/components-page/magic-link-callback.js +5 -3
  73. package/dist/esm/components-page/magic-link-callback.js.map +1 -1
  74. package/dist/esm/components-page/oauth-callback.js +6 -5
  75. package/dist/esm/components-page/oauth-callback.js.map +1 -1
  76. package/dist/esm/components-page/password-reset.js +25 -22
  77. package/dist/esm/components-page/password-reset.js.map +1 -1
  78. package/dist/esm/components-page/team-creation.js +9 -7
  79. package/dist/esm/components-page/team-creation.js.map +1 -1
  80. package/dist/esm/components-page/team-invitation.js +14 -11
  81. package/dist/esm/components-page/team-invitation.js.map +1 -1
  82. package/dist/esm/generated/quetzal-translations.js +1425 -0
  83. package/dist/esm/generated/quetzal-translations.js.map +1 -0
  84. package/dist/esm/lib/stack-app.js +1 -1
  85. package/dist/esm/lib/translations.js +20 -0
  86. package/dist/esm/lib/translations.js.map +1 -0
  87. package/dist/esm/providers/stack-provider.js +4 -2
  88. package/dist/esm/providers/stack-provider.js.map +1 -1
  89. package/dist/esm/providers/theme-provider.js.map +1 -1
  90. package/dist/esm/providers/translation-provider-client.js +18 -0
  91. package/dist/esm/providers/translation-provider-client.js.map +1 -0
  92. package/dist/esm/providers/translation-provider.js +12 -0
  93. package/dist/esm/providers/translation-provider.js.map +1 -0
  94. package/dist/esm/utils/browser-script.js +38 -6
  95. package/dist/esm/utils/browser-script.js.map +1 -1
  96. package/dist/generated/quetzal-translations.d.mts +4 -0
  97. package/dist/generated/quetzal-translations.d.ts +4 -0
  98. package/dist/generated/quetzal-translations.js +1451 -0
  99. package/dist/generated/quetzal-translations.js.map +1 -0
  100. package/dist/index.d.mts +2 -0
  101. package/dist/index.d.ts +2 -0
  102. package/dist/lib/stack-app.js +1 -1
  103. package/dist/lib/translations.d.mts +5 -0
  104. package/dist/lib/translations.d.ts +5 -0
  105. package/dist/lib/translations.js +55 -0
  106. package/dist/lib/translations.js.map +1 -0
  107. package/dist/providers/stack-provider-client.d.mts +3 -3
  108. package/dist/providers/stack-provider-client.d.ts +3 -3
  109. package/dist/providers/stack-provider.d.mts +6 -3
  110. package/dist/providers/stack-provider.d.ts +6 -3
  111. package/dist/providers/stack-provider.js +4 -2
  112. package/dist/providers/stack-provider.js.map +1 -1
  113. package/dist/providers/theme-provider.d.mts +2 -2
  114. package/dist/providers/theme-provider.d.ts +2 -2
  115. package/dist/providers/theme-provider.js.map +1 -1
  116. package/dist/providers/translation-provider-client.d.mts +14 -0
  117. package/dist/providers/translation-provider-client.d.ts +14 -0
  118. package/dist/providers/translation-provider-client.js +43 -0
  119. package/dist/providers/translation-provider-client.js.map +1 -0
  120. package/dist/providers/translation-provider.d.mts +9 -0
  121. package/dist/providers/translation-provider.d.ts +9 -0
  122. package/dist/providers/translation-provider.js +37 -0
  123. package/dist/providers/translation-provider.js.map +1 -0
  124. package/dist/utils/browser-script.js +38 -6
  125. package/dist/utils/browser-script.js.map +1 -1
  126. package/package.json +20 -12
@@ -23,8 +23,10 @@ import { UserAvatar } from "../components/elements/user-avatar";
23
23
  import { ProfileImageEditor } from "../components/profile-image-editor";
24
24
  import { TeamIcon } from "../components/team-icon";
25
25
  import { MaybeFullPage } from "../components/elements/maybe-full-page";
26
+ import { useTranslation } from "../lib/translations";
26
27
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
27
28
  function AccountSettings(props) {
29
+ const { t } = useTranslation();
28
30
  const user = useUser({ or: "redirect" });
29
31
  const teams = user.useTeams();
30
32
  const stackApp = useStackApp();
@@ -34,14 +36,14 @@ function AccountSettings(props) {
34
36
  {
35
37
  items: [
36
38
  {
37
- title: "My Profile",
39
+ title: t("My Profile"),
38
40
  type: "item",
39
41
  subpath: "/profile",
40
42
  icon: Contact,
41
43
  content: /* @__PURE__ */ jsx(ProfileSection, {})
42
44
  },
43
45
  {
44
- title: "Security",
46
+ title: t("Security"),
45
47
  type: "item",
46
48
  icon: ShieldCheck,
47
49
  subpath: "/security",
@@ -52,7 +54,7 @@ function AccountSettings(props) {
52
54
  ] })
53
55
  },
54
56
  {
55
- title: "Sign Out",
57
+ title: t("Sign Out"),
56
58
  subpath: "/sign-out",
57
59
  type: "item",
58
60
  icon: LogOut,
@@ -66,7 +68,7 @@ function AccountSettings(props) {
66
68
  content: item.content
67
69
  })) || [],
68
70
  ...teams.length > 0 || project.config.clientTeamCreationEnabled ? [{
69
- title: "Teams",
71
+ title: t("Teams"),
70
72
  type: "divider"
71
73
  }] : [],
72
74
  ...teams.map((team) => ({
@@ -85,23 +87,24 @@ function AccountSettings(props) {
85
87
  ] })
86
88
  })),
87
89
  ...project.config.clientTeamCreationEnabled ? [{
88
- title: "Create a team",
90
+ title: t("Create a team"),
89
91
  icon: CirclePlus,
90
92
  type: "item",
91
93
  subpath: "/team-creation",
92
94
  content: /* @__PURE__ */ jsx(TeamCreation, {})
93
95
  }] : []
94
96
  ].filter((p) => p.type === "divider" || p.content),
95
- title: "Account Settings",
97
+ title: t("Account Settings"),
96
98
  basePath: stackApp.urls.accountSettings
97
99
  }
98
100
  ) }) });
99
101
  }
100
102
  function ProfileSection() {
103
+ const { t } = useTranslation();
101
104
  const user = useUser({ or: "redirect" });
102
105
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-8", children: [
103
106
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-start", children: [
104
- /* @__PURE__ */ jsx(Label, { className: "mb-2", children: "Profile image" }),
107
+ /* @__PURE__ */ jsx(Label, { className: "mb-2", children: t("Profile image") }),
105
108
  /* @__PURE__ */ jsx(
106
109
  ProfileImageEditor,
107
110
  {
@@ -113,7 +116,7 @@ function ProfileSection() {
113
116
  )
114
117
  ] }),
115
118
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
116
- /* @__PURE__ */ jsx(Label, { children: "Display name" }),
119
+ /* @__PURE__ */ jsx(Label, { children: t("Display name") }),
117
120
  /* @__PURE__ */ jsx(EditableText, { value: user.displayName || "", onSave: async (newDisplayName) => {
118
121
  await user.update({ displayName: newDisplayName });
119
122
  } })
@@ -121,15 +124,16 @@ function ProfileSection() {
121
124
  ] });
122
125
  }
123
126
  function EmailVerificationSection() {
127
+ const { t } = useTranslation();
124
128
  const user = useUser({ or: "redirect" });
125
129
  const [emailSent, setEmailSent] = useState(false);
126
130
  if (!user.primaryEmail) {
127
131
  return null;
128
132
  }
129
133
  return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs("div", { children: [
130
- /* @__PURE__ */ jsx(Label, { children: "Email Verification" }),
131
- user.primaryEmailVerified ? /* @__PURE__ */ jsx(Typography, { variant: "success", children: "Your email has been verified." }) : /* @__PURE__ */ jsxs(Fragment, { children: [
132
- /* @__PURE__ */ jsx(Typography, { variant: "destructive", children: "Your email has not been verified." }),
134
+ /* @__PURE__ */ jsx(Label, { children: t("Email Verification") }),
135
+ user.primaryEmailVerified ? /* @__PURE__ */ jsx(Typography, { variant: "success", children: t("Your email has been verified.") }) : /* @__PURE__ */ jsxs(Fragment, { children: [
136
+ /* @__PURE__ */ jsx(Typography, { variant: "destructive", children: t("Your email has not been verified.") }),
133
137
  /* @__PURE__ */ jsx("div", { className: "flex mt-4", children: /* @__PURE__ */ jsx(
134
138
  Button,
135
139
  {
@@ -138,28 +142,29 @@ function EmailVerificationSection() {
138
142
  await user.sendVerificationEmail();
139
143
  setEmailSent(true);
140
144
  },
141
- children: emailSent ? "Email sent!" : "Send Verification Email"
145
+ children: emailSent ? t("Email sent!") : t("Send Verification Email")
142
146
  }
143
147
  ) })
144
148
  ] })
145
149
  ] }) });
146
150
  }
147
- var passwordSchema = yupObject({
148
- oldPassword: yupString().required("Please enter your old password"),
149
- newPassword: yupString().required("Please enter your password").test({
150
- name: "is-valid-password",
151
- test: (value, ctx) => {
152
- const error = getPasswordError(value);
153
- if (error) {
154
- return ctx.createError({ message: error.message });
155
- } else {
156
- return true;
157
- }
158
- }
159
- }),
160
- newPasswordRepeat: yupString().nullable().oneOf([yup.ref("newPassword"), "", null], "Passwords do not match").required("Please repeat your password")
161
- });
162
151
  function PasswordSection() {
152
+ const { t } = useTranslation();
153
+ const passwordSchema = yupObject({
154
+ oldPassword: yupString().required(t("Please enter your old password")),
155
+ newPassword: yupString().required(t("Please enter your password")).test({
156
+ name: "is-valid-password",
157
+ test: (value, ctx) => {
158
+ const error = getPasswordError(value);
159
+ if (error) {
160
+ return ctx.createError({ message: error.message });
161
+ } else {
162
+ return true;
163
+ }
164
+ }
165
+ }),
166
+ newPasswordRepeat: yupString().nullable().oneOf([yup.ref("newPassword"), "", null], t("Passwords do not match")).required(t("Please repeat your password"))
167
+ });
163
168
  const user = useUser({ or: "throw" });
164
169
  const [changingPassword, setChangingPassword] = useState(false);
165
170
  const { register, handleSubmit, setError, formState: { errors }, clearErrors, reset } = useForm({
@@ -173,7 +178,7 @@ function PasswordSection() {
173
178
  const { oldPassword, newPassword } = data;
174
179
  const error = await user.updatePassword({ oldPassword, newPassword });
175
180
  if (error) {
176
- setError("oldPassword", { type: "manual", message: "Incorrect password" });
181
+ setError("oldPassword", { type: "manual", message: t("Incorrect password") });
177
182
  } else {
178
183
  reset();
179
184
  setAlreadyReset(true);
@@ -188,15 +193,15 @@ function PasswordSection() {
188
193
  return null;
189
194
  }
190
195
  return /* @__PURE__ */ jsxs("div", { children: [
191
- /* @__PURE__ */ jsx(Label, { children: "Change password" }),
192
- /* @__PURE__ */ jsx("div", { children: alreadyReset ? /* @__PURE__ */ jsx(Typography, { variant: "success", children: "Password changed successfully!" }) : !changingPassword ? /* @__PURE__ */ jsx(
196
+ /* @__PURE__ */ jsx(Label, { children: t("Change password") }),
197
+ /* @__PURE__ */ jsx("div", { children: alreadyReset ? /* @__PURE__ */ jsx(Typography, { variant: "success", children: t("Password changed successfully!") }) : !changingPassword ? /* @__PURE__ */ jsx(
193
198
  Button,
194
199
  {
195
200
  variant: "secondary",
196
201
  onClick: async () => {
197
202
  setChangingPassword(true);
198
203
  },
199
- children: "Change Password"
204
+ children: t("Change Password")
200
205
  }
201
206
  ) : /* @__PURE__ */ jsxs(
202
207
  "form",
@@ -204,7 +209,7 @@ function PasswordSection() {
204
209
  onSubmit: (e) => runAsynchronouslyWithAlert(handleSubmit(onSubmit)(e)),
205
210
  noValidate: true,
206
211
  children: [
207
- /* @__PURE__ */ jsx(Label, { htmlFor: "old-password", className: "mb-1", children: "Old password" }),
212
+ /* @__PURE__ */ jsx(Label, { htmlFor: "old-password", className: "mb-1", children: t("Old password") }),
208
213
  /* @__PURE__ */ jsx(
209
214
  Input,
210
215
  {
@@ -214,7 +219,7 @@ function PasswordSection() {
214
219
  }
215
220
  ),
216
221
  /* @__PURE__ */ jsx(FormWarningText, { text: errors.oldPassword?.message?.toString() }),
217
- /* @__PURE__ */ jsx(Label, { htmlFor: "new-password", className: "mt-4 mb-1", children: "Password" }),
222
+ /* @__PURE__ */ jsx(Label, { htmlFor: "new-password", className: "mt-4 mb-1", children: t("Password") }),
218
223
  /* @__PURE__ */ jsx(
219
224
  PasswordInput,
220
225
  {
@@ -228,7 +233,7 @@ function PasswordSection() {
228
233
  }
229
234
  ),
230
235
  /* @__PURE__ */ jsx(FormWarningText, { text: errors.newPassword?.message?.toString() }),
231
- /* @__PURE__ */ jsx(Label, { htmlFor: "repeat-password", className: "mt-4 mb-1", children: "Repeat password" }),
236
+ /* @__PURE__ */ jsx(Label, { htmlFor: "repeat-password", className: "mt-4 mb-1", children: t("Repeat password") }),
232
237
  /* @__PURE__ */ jsx(
233
238
  PasswordInput,
234
239
  {
@@ -242,13 +247,14 @@ function PasswordSection() {
242
247
  }
243
248
  ),
244
249
  /* @__PURE__ */ jsx(FormWarningText, { text: errors.newPasswordRepeat?.message?.toString() }),
245
- /* @__PURE__ */ jsx(Button, { type: "submit", className: "mt-6", loading, children: "Change Password" })
250
+ /* @__PURE__ */ jsx(Button, { type: "submit", className: "mt-6", loading, children: t("Change Password") })
246
251
  ]
247
252
  }
248
253
  ) })
249
254
  ] });
250
255
  }
251
256
  function MfaSection() {
257
+ const { t } = useTranslation();
252
258
  const project = useStackApp().useProject();
253
259
  const user = useUser({ or: "throw" });
254
260
  const [generatedSecret, setGeneratedSecret] = useState(null);
@@ -274,12 +280,12 @@ function MfaSection() {
274
280
  });
275
281
  }, [mfaCode, generatedSecret, handleSubmit]);
276
282
  return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs("div", { children: [
277
- /* @__PURE__ */ jsx(Label, { children: "Multi-factor Authentication" }),
283
+ /* @__PURE__ */ jsx(Label, { children: t("Multi-factor Authentication") }),
278
284
  /* @__PURE__ */ jsxs("div", { children: [
279
- isEnabled ? /* @__PURE__ */ jsx(Typography, { variant: "success", children: "Multi-factor authentication is currently enabled." }) : generatedSecret ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 items-center", children: [
280
- /* @__PURE__ */ jsx(Typography, { children: "Scan this QR code with your authenticator app:" }),
281
- /* @__PURE__ */ jsx("img", { width: 200, height: 200, src: qrCodeUrl ?? throwErr("TOTP QR code failed to generate"), alt: "TOTP multi-factor authentication QR code" }),
282
- /* @__PURE__ */ jsx(Typography, { children: "Then, enter your six-digit MFA code:" }),
285
+ isEnabled ? /* @__PURE__ */ jsx(Typography, { variant: "success", children: t("Multi-factor authentication is currently enabled.") }) : generatedSecret ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 items-center", children: [
286
+ /* @__PURE__ */ jsx(Typography, { children: t("Scan this QR code with your authenticator app:") }),
287
+ /* @__PURE__ */ jsx("img", { width: 200, height: 200, src: qrCodeUrl ?? throwErr("TOTP QR code failed to generate"), alt: t("TOTP multi-factor authentication QR code") }),
288
+ /* @__PURE__ */ jsx(Typography, { children: t("Then, enter your six-digit MFA code:") }),
283
289
  /* @__PURE__ */ jsx(
284
290
  Input,
285
291
  {
@@ -293,8 +299,8 @@ function MfaSection() {
293
299
  disabled: isLoading
294
300
  }
295
301
  ),
296
- isMaybeWrong && mfaCode.length === 6 && /* @__PURE__ */ jsx(Typography, { variant: "destructive", children: "Incorrect code. Please try again." })
297
- ] }) : /* @__PURE__ */ jsx(Typography, { variant: "destructive", children: "Multi-factor authentication is currently disabled." }),
302
+ isMaybeWrong && mfaCode.length === 6 && /* @__PURE__ */ jsx(Typography, { variant: "destructive", children: t("Incorrect code. Please try again.") })
303
+ ] }) : /* @__PURE__ */ jsx(Typography, { variant: "destructive", children: t("Multi-factor authentication is currently disabled.") }),
298
304
  /* @__PURE__ */ jsx(
299
305
  Button,
300
306
  {
@@ -315,7 +321,7 @@ function MfaSection() {
315
321
  setMfaCode("");
316
322
  }
317
323
  },
318
- children: isEnabled ? "Disable" : generatedSecret ? "Cancel" : "Enable"
324
+ children: isEnabled ? t("Disable") : generatedSecret ? t("Cancel") : t("Enable")
319
325
  }
320
326
  )
321
327
  ] })
@@ -326,17 +332,19 @@ async function generateTotpQrCode(project, user, secret) {
326
332
  return await QRCode.toDataURL(uri);
327
333
  }
328
334
  function SignOutSection() {
335
+ const { t } = useTranslation();
329
336
  const user = useUser({ or: "throw" });
330
337
  return /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
331
338
  Button,
332
339
  {
333
340
  variant: "secondary",
334
341
  onClick: () => user.signOut(),
335
- children: "Sign Out"
342
+ children: t("Sign Out")
336
343
  }
337
344
  ) }) });
338
345
  }
339
346
  function UserSettings(props) {
347
+ const { t } = useTranslation();
340
348
  const user = useUser({ or: "redirect" });
341
349
  const [leaving, setLeaving] = useState(false);
342
350
  return /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: /* @__PURE__ */ jsx("div", { children: !leaving ? /* @__PURE__ */ jsx(
@@ -344,20 +352,21 @@ function UserSettings(props) {
344
352
  {
345
353
  variant: "secondary",
346
354
  onClick: async () => setLeaving(true),
347
- children: "Leave team"
355
+ children: t("Leave team")
348
356
  }
349
357
  ) : /* @__PURE__ */ jsxs("div", { className: "", children: [
350
- /* @__PURE__ */ jsx(Typography, { variant: "destructive", children: "Are you sure you want to leave the team?" }),
358
+ /* @__PURE__ */ jsx(Typography, { variant: "destructive", children: t("Are you sure you want to leave the team?") }),
351
359
  /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
352
360
  /* @__PURE__ */ jsx(Button, { variant: "destructive", onClick: async () => {
353
361
  await user.leaveTeam(props.team);
354
362
  window.location.reload();
355
- }, children: "Leave" }),
356
- /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => setLeaving(false), children: "Cancel" })
363
+ }, children: t("Leave") }),
364
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => setLeaving(false), children: t("Cancel") })
357
365
  ] })
358
366
  ] }) }) });
359
367
  }
360
368
  function ManagementSettings(props) {
369
+ const { t } = useTranslation();
361
370
  const user = useUser({ or: "redirect" });
362
371
  const updateTeamPermission = user.usePermission(props.team, "$update_team");
363
372
  if (!updateTeamPermission) {
@@ -365,7 +374,7 @@ function ManagementSettings(props) {
365
374
  }
366
375
  return /* @__PURE__ */ jsxs(Fragment, { children: [
367
376
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
368
- /* @__PURE__ */ jsx(Label, { children: "Team display name" }),
377
+ /* @__PURE__ */ jsx(Label, { children: t("Team display name") }),
369
378
  /* @__PURE__ */ jsx(
370
379
  ProfileImageEditor,
371
380
  {
@@ -377,7 +386,7 @@ function ManagementSettings(props) {
377
386
  )
378
387
  ] }),
379
388
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
380
- /* @__PURE__ */ jsx(Label, { children: "Team display name" }),
389
+ /* @__PURE__ */ jsx(Label, { children: t("Team display name") }),
381
390
  /* @__PURE__ */ jsx(
382
391
  EditableText,
383
392
  {
@@ -389,11 +398,12 @@ function ManagementSettings(props) {
389
398
  ] });
390
399
  }
391
400
  function ProfileSettings(props) {
401
+ const { t } = useTranslation();
392
402
  const user = useUser({ or: "redirect" });
393
403
  const profile = user.useTeamProfile(props.team);
394
404
  return /* @__PURE__ */ jsx("div", { className: "flex flex-col", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
395
405
  /* @__PURE__ */ jsxs(Label, { className: "flex gap-2", children: [
396
- "User display name ",
406
+ t("User display name"),
397
407
  /* @__PURE__ */ jsx(SimpleTooltip, { tooltip: "This overwrites your user display name in the account setting", type: "info" })
398
408
  ] }),
399
409
  /* @__PURE__ */ jsx(
@@ -407,10 +417,11 @@ function ProfileSettings(props) {
407
417
  )
408
418
  ] }) });
409
419
  }
410
- var invitationSchema = yupObject({
411
- email: yupString().email().required("Please enter an email address")
412
- });
413
420
  function MemberInvitation(props) {
421
+ const { t } = useTranslation();
422
+ const invitationSchema = yupObject({
423
+ email: yupString().email().required(t("Please enter an email address"))
424
+ });
414
425
  const user = useUser({ or: "redirect" });
415
426
  const inviteMemberPermission = user.usePermission(props.team, "$invite_members");
416
427
  if (!inviteMemberPermission) {
@@ -434,7 +445,7 @@ function MemberInvitation(props) {
434
445
  setInvitedEmail(null);
435
446
  }, [watch("email")]);
436
447
  return /* @__PURE__ */ jsxs("div", { children: [
437
- /* @__PURE__ */ jsx(Label, { children: "Invite a user to team" }),
448
+ /* @__PURE__ */ jsx(Label, { children: t("Invite a user to team") }),
438
449
  /* @__PURE__ */ jsxs(
439
450
  "form",
440
451
  {
@@ -445,11 +456,11 @@ function MemberInvitation(props) {
445
456
  /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
446
457
  Input,
447
458
  {
448
- placeholder: "Email",
459
+ placeholder: t("Email"),
449
460
  ...register("email")
450
461
  }
451
462
  ) }),
452
- /* @__PURE__ */ jsx(Button, { type: "submit", loading, children: "Invite User" })
463
+ /* @__PURE__ */ jsx(Button, { type: "submit", loading, children: t("Invite User") })
453
464
  ] }),
454
465
  /* @__PURE__ */ jsx(FormWarningText, { text: errors.email?.message?.toString() }),
455
466
  invitedEmail && /* @__PURE__ */ jsxs(Typography, { type: "label", variant: "secondary", children: [
@@ -462,6 +473,7 @@ function MemberInvitation(props) {
462
473
  ] });
463
474
  }
464
475
  function MembersSettings(props) {
476
+ const { t } = useTranslation();
465
477
  const user = useUser({ or: "redirect" });
466
478
  const readMemberPermission = user.usePermission(props.team, "$read_members");
467
479
  const inviteMemberPermission = user.usePermission(props.team, "$invite_members");
@@ -473,11 +485,11 @@ function MembersSettings(props) {
473
485
  return null;
474
486
  }
475
487
  return /* @__PURE__ */ jsxs("div", { children: [
476
- /* @__PURE__ */ jsx(Label, { children: "Members" }),
488
+ /* @__PURE__ */ jsx(Label, { children: t("Members") }),
477
489
  /* @__PURE__ */ jsxs(Table, { children: [
478
490
  /* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
479
- /* @__PURE__ */ jsx(TableHead, { className: "w-[100px]", children: "User" }),
480
- /* @__PURE__ */ jsx(TableHead, { className: "w-[200px]", children: "Name" })
491
+ /* @__PURE__ */ jsx(TableHead, { className: "w-[100px]", children: t("User") }),
492
+ /* @__PURE__ */ jsx(TableHead, { className: "w-[200px]", children: t("Name") })
481
493
  ] }) }),
482
494
  /* @__PURE__ */ jsx(TableBody, { children: users.map(({ id, teamProfile }, i) => /* @__PURE__ */ jsxs(TableRow, { children: [
483
495
  /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(UserAvatar, { user: teamProfile }) }),
@@ -486,10 +498,11 @@ function MembersSettings(props) {
486
498
  ] })
487
499
  ] });
488
500
  }
489
- var teamCreationSchema = yupObject({
490
- displayName: yupString().required("Please enter a team name")
491
- });
492
501
  function TeamCreation() {
502
+ const { t } = useTranslation();
503
+ const teamCreationSchema = yupObject({
504
+ displayName: yupString().required(t("Please enter a team name"))
505
+ });
493
506
  const { register, handleSubmit, formState: { errors } } = useForm({
494
507
  resolver: yupResolver(teamCreationSchema)
495
508
  });
@@ -498,7 +511,7 @@ function TeamCreation() {
498
511
  const user = useUser({ or: "redirect" });
499
512
  const [loading, setLoading] = useState(false);
500
513
  if (!project.config.clientTeamCreationEnabled) {
501
- return /* @__PURE__ */ jsx(MessageCard, { title: "Team creation is not enabled" });
514
+ return /* @__PURE__ */ jsx(MessageCard, { title: t("Team creation is not enabled") });
502
515
  }
503
516
  const onSubmit = async (data) => {
504
517
  setLoading(true);
@@ -516,7 +529,7 @@ function TeamCreation() {
516
529
  noValidate: true,
517
530
  children: /* @__PURE__ */ jsxs("div", { className: "flex items-end gap-4", children: [
518
531
  /* @__PURE__ */ jsxs("div", { children: [
519
- /* @__PURE__ */ jsx(Label, { htmlFor: "email", className: "mb-1", children: "Display name" }),
532
+ /* @__PURE__ */ jsx(Label, { htmlFor: "email", className: "mb-1", children: t("Display name") }),
520
533
  /* @__PURE__ */ jsx(
521
534
  Input,
522
535
  {
@@ -527,7 +540,7 @@ function TeamCreation() {
527
540
  )
528
541
  ] }),
529
542
  /* @__PURE__ */ jsx(FormWarningText, { text: errors.displayName?.message?.toString() }),
530
- /* @__PURE__ */ jsx(Button, { type: "submit", className: "mt-6", loading, children: "Create" })
543
+ /* @__PURE__ */ jsx(Button, { type: "submit", className: "mt-6", loading, children: t("Create") })
531
544
  ] })
532
545
  }
533
546
  ) }) });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components-page/account-settings.tsx"],"sourcesContent":["'use client';\n\nimport { yupResolver } from \"@hookform/resolvers/yup\";\nimport { getPasswordError } from '@stackframe/stack-shared/dist/helpers/password';\nimport { useAsyncCallback } from '@stackframe/stack-shared/dist/hooks/use-async-callback';\nimport { yupObject, yupString } from '@stackframe/stack-shared/dist/schema-fields';\nimport { generateRandomValues } from '@stackframe/stack-shared/dist/utils/crypto';\nimport { throwErr } from '@stackframe/stack-shared/dist/utils/errors';\nimport { runAsynchronously, runAsynchronouslyWithAlert } from '@stackframe/stack-shared/dist/utils/promises';\nimport { Button, EditableText, Input, Label, PasswordInput, SimpleTooltip, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Typography } from '@stackframe/stack-ui';\nimport { CirclePlus, Contact, LogOut, ShieldCheck, LucideIcon } from 'lucide-react';\nimport { TOTPController, createTOTPKeyURI } from \"oslo/otp\";\nimport * as QRCode from 'qrcode';\nimport { useEffect, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport * as yup from \"yup\";\nimport { CurrentUser, MessageCard, Project, Team, useStackApp, useUser } from '..';\nimport { FormWarningText } from '../components/elements/form-warning';\nimport { SidebarLayout } from '../components/elements/sidebar-layout';\nimport { UserAvatar } from '../components/elements/user-avatar';\nimport { ProfileImageEditor } from \"../components/profile-image-editor\";\nimport { TeamIcon } from '../components/team-icon';\nimport { MaybeFullPage } from \"../components/elements/maybe-full-page\";\n\n\nexport function AccountSettings(props: {\n fullPage?: boolean,\n extraItems?: {\n title: string,\n icon: LucideIcon,\n content: React.ReactNode,\n subpath: string,\n }[],\n}) {\n const user = useUser({ or: 'redirect' });\n const teams = user.useTeams();\n const stackApp = useStackApp();\n const project = stackApp.useProject();\n\n return (\n <MaybeFullPage fullPage={!!props.fullPage}>\n <div style={{ alignSelf: 'stretch', flexGrow: 1 }}>\n <SidebarLayout\n items={([\n {\n title: 'My Profile',\n type: 'item',\n subpath: '/profile',\n icon: Contact,\n content: <ProfileSection/>,\n },\n {\n title: 'Security',\n type: 'item',\n icon: ShieldCheck,\n subpath: '/security',\n content: (\n <div className='flex flex-col gap-8'>\n <EmailVerificationSection />\n <PasswordSection />\n <MfaSection />\n </div>\n ),\n },\n {\n title: 'Sign Out',\n subpath: '/sign-out',\n type: 'item',\n icon: LogOut,\n content: <SignOutSection />,\n },\n ...(props.extraItems?.map(item => ({\n title: item.title,\n type: 'item',\n subpath: item.subpath,\n icon: item.icon,\n content: item.content,\n } as const)) || []),\n ...(teams.length > 0 || project.config.clientTeamCreationEnabled) ? [{\n title: 'Teams',\n type: 'divider',\n }] as const : [],\n ...teams.map(team => ({\n title: <div className='flex gap-2 items-center'>\n <TeamIcon team={team}/>\n {team.displayName}\n </div>,\n type: 'item',\n subpath: `/teams/${team.id}`,\n content: (\n <div className=\"flex flex-col gap-8\">\n <ProfileSettings team={team}/>\n <ManagementSettings team={team}/>\n <MemberInvitation team={team}/>\n <MembersSettings team={team}/>\n <UserSettings team={team}/>\n </div>\n ),\n } as const)),\n ...project.config.clientTeamCreationEnabled ? [{\n title: 'Create a team',\n icon: CirclePlus,\n type: 'item',\n subpath: '/team-creation',\n content: <TeamCreation />,\n }] as const : [],\n ] as const).filter((p) => p.type === 'divider' || (p as any).content )}\n title='Account Settings'\n basePath={stackApp.urls.accountSettings}\n />\n </div>\n </MaybeFullPage>\n );\n}\n\nfunction ProfileSection() {\n const user = useUser({ or: 'redirect' });\n\n return (\n <div className='flex flex-col gap-8'>\n <div className='flex flex-col items-start'>\n <Label className=\"mb-2\">Profile image</Label>\n <ProfileImageEditor\n user={user}\n onProfileImageUrlChange={async (profileImageUrl) => {\n await user.update({ profileImageUrl });\n }}\n />\n </div>\n <div className='flex flex-col'>\n <Label>Display name</Label>\n <EditableText value={user.displayName || ''} onSave={async (newDisplayName) => {\n await user.update({ displayName: newDisplayName });\n }}/>\n </div>\n </div>\n );\n}\n\nfunction EmailVerificationSection() {\n const user = useUser({ or: 'redirect' });\n const [emailSent, setEmailSent] = useState(false);\n\n if (!user.primaryEmail) {\n return null;\n }\n\n return (\n <>\n <div>\n <Label>Email Verification</Label>\n {user.primaryEmailVerified ? (\n <Typography variant='success'>Your email has been verified.</Typography>\n ) : (\n <>\n <Typography variant='destructive'>Your email has not been verified.</Typography>\n <div className='flex mt-4'>\n <Button\n disabled={emailSent}\n onClick={async () => {\n await user.sendVerificationEmail();\n setEmailSent(true);\n }}\n >\n {emailSent ? 'Email sent!' : 'Send Verification Email'}\n </Button>\n </div>\n </>\n )}\n\n </div>\n </>\n );\n}\n\nconst passwordSchema = yupObject({\n oldPassword: yupString().required('Please enter your old password'),\n newPassword: yupString().required('Please enter your password').test({\n name: 'is-valid-password',\n test: (value, ctx) => {\n const error = getPasswordError(value);\n if (error) {\n return ctx.createError({ message: error.message });\n } else {\n return true;\n }\n }\n }),\n newPasswordRepeat: yupString().nullable().oneOf([yup.ref('newPassword'), \"\", null], 'Passwords do not match').required('Please repeat your password')\n});\n\nfunction PasswordSection() {\n const user = useUser({ or: \"throw\" });\n const [changingPassword, setChangingPassword] = useState(false);\n const { register, handleSubmit, setError, formState: { errors }, clearErrors, reset } = useForm({\n resolver: yupResolver(passwordSchema)\n });\n const [alreadyReset, setAlreadyReset] = useState(false);\n const [loading, setLoading] = useState(false);\n\n const onSubmit = async (data: yup.InferType<typeof passwordSchema>) => {\n setLoading(true);\n try {\n const { oldPassword, newPassword } = data;\n const error = await user.updatePassword({ oldPassword, newPassword });\n if (error) {\n setError('oldPassword', { type: 'manual', message: 'Incorrect password' });\n } else {\n reset();\n setAlreadyReset(true);\n }\n } finally {\n setLoading(false);\n }\n };\n\n const registerPassword = register('newPassword');\n const registerPasswordRepeat = register('newPasswordRepeat');\n\n if (!user.hasPassword) {\n return null;\n }\n\n return (\n <div>\n <Label>Change password</Label>\n <div>\n {\n alreadyReset ?\n <Typography variant='success'>Password changed successfully!</Typography> :\n !changingPassword ?\n <Button\n variant='secondary'\n onClick={async () => {\n setChangingPassword(true);\n }}\n >\n Change Password\n </Button> :\n <form\n onSubmit={e => runAsynchronouslyWithAlert(handleSubmit(onSubmit)(e))}\n noValidate\n >\n <Label htmlFor=\"old-password\" className=\"mb-1\">Old password</Label>\n <Input\n id=\"old-password\"\n type=\"password\"\n {...register('oldPassword')}\n />\n <FormWarningText text={errors.oldPassword?.message?.toString()} />\n\n <Label htmlFor=\"new-password\" className=\"mt-4 mb-1\">Password</Label>\n <PasswordInput\n id=\"new-password\"\n {...registerPassword}\n onChange={(e) => {\n clearErrors('newPassword');\n clearErrors('newPasswordRepeat');\n runAsynchronously(registerPassword.onChange(e));\n }}\n />\n <FormWarningText text={errors.newPassword?.message?.toString()} />\n\n <Label htmlFor=\"repeat-password\" className=\"mt-4 mb-1\">Repeat password</Label>\n <PasswordInput\n id=\"repeat-password\"\n {...registerPasswordRepeat}\n onChange={(e) => {\n clearErrors('newPassword');\n clearErrors('newPasswordRepeat');\n runAsynchronously(registerPasswordRepeat.onChange(e));\n }}\n />\n <FormWarningText text={errors.newPasswordRepeat?.message?.toString()} />\n\n <Button type=\"submit\" className=\"mt-6\" loading={loading}>\n Change Password\n </Button>\n </form>\n }\n </div>\n </div>\n );\n}\n\nfunction MfaSection() {\n const project = useStackApp().useProject();\n const user = useUser({ or: \"throw\" });\n const [generatedSecret, setGeneratedSecret] = useState<Uint8Array | null>(null);\n const [qrCodeUrl, setQrCodeUrl] = useState<string | null>(null);\n const [mfaCode, setMfaCode] = useState<string>(\"\");\n const [isMaybeWrong, setIsMaybeWrong] = useState(false);\n const isEnabled = user.isMultiFactorRequired;\n\n const [handleSubmit, isLoading] = useAsyncCallback(async () => {\n await user.update({\n totpMultiFactorSecret: generatedSecret,\n });\n setGeneratedSecret(null);\n setQrCodeUrl(null);\n setMfaCode(\"\");\n }, [generatedSecret, user]);\n\n useEffect(() => {\n setIsMaybeWrong(false);\n runAsynchronouslyWithAlert(async () => {\n if (generatedSecret && await new TOTPController().verify(mfaCode, generatedSecret)) {\n await handleSubmit();\n }\n setIsMaybeWrong(true);\n });\n }, [mfaCode, generatedSecret, handleSubmit]);\n\n return (\n <div>\n <div>\n <Label>Multi-factor Authentication</Label>\n\n <div>\n {isEnabled ? (\n <Typography variant=\"success\">Multi-factor authentication is currently enabled.</Typography>\n ) : (\n generatedSecret ? (\n <div className='flex flex-col gap-4 items-center'>\n <Typography>Scan this QR code with your authenticator app:</Typography>\n <img width={200} height={200} src={qrCodeUrl ?? throwErr(\"TOTP QR code failed to generate\")} alt=\"TOTP multi-factor authentication QR code\" />\n <Typography>Then, enter your six-digit MFA code:</Typography>\n <Input\n value={mfaCode}\n onChange={(e) => {\n setIsMaybeWrong(false);\n setMfaCode(e.target.value);\n }}\n placeholder=\"123456\"\n maxLength={6}\n disabled={isLoading}\n />\n {isMaybeWrong && mfaCode.length === 6 && (\n <Typography variant=\"destructive\">Incorrect code. Please try again.</Typography>\n )}\n </div>\n ) : (\n <Typography variant=\"destructive\">Multi-factor authentication is currently disabled.</Typography>\n )\n )}\n\n <Button\n className=\"mt-4\"\n variant={isEnabled ? 'secondary' : 'default'}\n onClick={async () => {\n if (isEnabled) {\n await user.update({\n totpMultiFactorSecret: null,\n });\n } else if (!generatedSecret) {\n const secret = generateRandomValues(new Uint8Array(20));\n setQrCodeUrl(await generateTotpQrCode(project, user, secret));\n setGeneratedSecret(secret);\n } else {\n setGeneratedSecret(null);\n setQrCodeUrl(null);\n setMfaCode(\"\");\n }\n }}\n >\n {isEnabled ? 'Disable' : (generatedSecret ? 'Cancel' : 'Enable')}\n </Button>\n </div>\n </div>\n </div>\n );\n}\n\nasync function generateTotpQrCode(project: Project, user: CurrentUser, secret: Uint8Array) {\n const uri = createTOTPKeyURI(project.displayName, user.primaryEmail ?? user.id, secret);\n return await QRCode.toDataURL(uri) as any;\n}\n\nfunction SignOutSection() {\n const user = useUser({ or: \"throw\" });\n return (\n <div className='flex flex-col gap-2'>\n <div>\n <Button\n variant='secondary'\n onClick={() => user.signOut()}\n >\n Sign Out\n </Button>\n </div>\n </div>\n );\n}\n\nfunction UserSettings(props: { team: Team }) {\n const user = useUser({ or: 'redirect' });\n const [leaving, setLeaving] = useState(false);\n\n return (\n <div className='flex flex-col gap-2'>\n <div>\n { !leaving ?\n <Button\n variant='secondary'\n onClick={async () => setLeaving(true)}\n >\n Leave team\n </Button> :\n <div className=''>\n <Typography variant='destructive'>Are you sure you want to leave the team?</Typography>\n <div className='flex gap-2'>\n <Button variant='destructive' onClick={async () => {\n await user.leaveTeam(props.team);\n window.location.reload();\n }}>\n Leave\n </Button>\n <Button variant='secondary' onClick={() => setLeaving(false)}>\n Cancel\n </Button>\n </div>\n </div>}\n </div>\n </div>\n );\n}\n\nfunction ManagementSettings(props: { team: Team }) {\n const user = useUser({ or: 'redirect' });\n const updateTeamPermission = user.usePermission(props.team, '$update_team');\n\n if (!updateTeamPermission) {\n return null;\n }\n\n return (\n <>\n <div className='flex flex-col'>\n <Label>Team display name</Label>\n <ProfileImageEditor\n user={props.team}\n onProfileImageUrlChange={async (profileImageUrl) => {\n await props.team.update({ profileImageUrl });\n }}\n />\n </div>\n\n <div className='flex flex-col'>\n <Label>Team display name</Label>\n <EditableText\n value={props.team.displayName}\n onSave={async (newDisplayName) => await props.team.update({ displayName: newDisplayName })}\n />\n </div>\n </>\n );\n}\n\nfunction ProfileSettings(props: { team: Team }) {\n const user = useUser({ or: 'redirect' });\n const profile = user.useTeamProfile(props.team);\n\n return (\n <div className=\"flex flex-col\">\n <div className=\"flex flex-col\">\n <Label className=\"flex gap-2\">User display name <SimpleTooltip tooltip=\"This overwrites your user display name in the account setting\" type='info'/></Label>\n <EditableText\n value={profile.displayName || ''}\n onSave={async (newDisplayName) => {\n await profile.update({ displayName: newDisplayName });\n }}/>\n </div>\n </div>\n );\n}\n\nconst invitationSchema = yupObject({\n email: yupString().email().required('Please enter an email address'),\n});\n\nfunction MemberInvitation(props: { team: Team }) {\n const user = useUser({ or: 'redirect' });\n const inviteMemberPermission = user.usePermission(props.team, '$invite_members');\n\n if (!inviteMemberPermission) {\n return null;\n }\n\n const { register, handleSubmit, formState: { errors }, watch } = useForm({\n resolver: yupResolver(invitationSchema)\n });\n const [loading, setLoading] = useState(false);\n const [invitedEmail, setInvitedEmail] = useState<string | null>(null);\n\n const onSubmit = async (data: yup.InferType<typeof invitationSchema>) => {\n setLoading(true);\n\n try {\n await props.team.inviteUser({ email: data.email });\n setInvitedEmail(data.email);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n setInvitedEmail(null);\n }, [watch('email')]);\n\n return (\n <div>\n <Label>Invite a user to team</Label>\n <form\n onSubmit={e => runAsynchronouslyWithAlert(handleSubmit(onSubmit)(e))}\n noValidate\n >\n <div className=\"flex flex-col gap-4 md:flex-row\">\n <div>\n <Input\n placeholder=\"Email\"\n {...register('email')}\n />\n </div>\n <Button type=\"submit\" loading={loading}>\n Invite User\n </Button>\n </div>\n <FormWarningText text={errors.email?.message?.toString()} />\n {invitedEmail && <Typography type='label' variant='secondary'>Invited {invitedEmail}</Typography>}\n </form>\n </div>\n );\n}\n\n\nfunction MembersSettings(props: { team: Team }) {\n const user = useUser({ or: 'redirect' });\n const readMemberPermission = user.usePermission(props.team, '$read_members');\n const inviteMemberPermission = user.usePermission(props.team, '$invite_members');\n\n if (!readMemberPermission && !inviteMemberPermission) {\n return null;\n }\n\n const users = props.team.useUsers();\n\n if (!readMemberPermission) {\n return null;\n }\n\n return (\n <div>\n <Label>Members</Label>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead className=\"w-[100px]\">User</TableHead>\n <TableHead className=\"w-[200px]\">Name</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {users.map(({ id, teamProfile }, i) => (\n <TableRow key={id}>\n <TableCell>\n <UserAvatar user={teamProfile}/>\n </TableCell>\n <TableCell>\n <Typography>{teamProfile.displayName}</Typography>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n );\n}\n\nconst teamCreationSchema = yupObject({\n displayName: yupString().required('Please enter a team name'),\n});\n\nexport function TeamCreation() {\n const { register, handleSubmit, formState: { errors } } = useForm({\n resolver: yupResolver(teamCreationSchema)\n });\n const app = useStackApp();\n const project = app.useProject();\n const user = useUser({ or: 'redirect' });\n const [loading, setLoading] = useState(false);\n\n if (!project.config.clientTeamCreationEnabled) {\n return <MessageCard title='Team creation is not enabled' />;\n }\n\n const onSubmit = async (data: yup.InferType<typeof teamCreationSchema>) => {\n setLoading(true);\n\n try {\n const team = await user.createTeam({ displayName: data.displayName });\n } finally {\n setLoading(false);\n }\n };\n\n return (\n <div className='stack-scope flex flex-col items-stretch'>\n <div className=\"mb-6\">\n <form\n className=\"flex flex-col items-stretch stack-scope\"\n onSubmit={e => runAsynchronouslyWithAlert(handleSubmit(onSubmit)(e))}\n noValidate\n >\n <div className=\"flex items-end gap-4\">\n <div>\n <Label htmlFor=\"email\" className=\"mb-1\">Display name</Label>\n <Input\n id=\"email\"\n type=\"email\"\n {...register('displayName')}\n />\n </div>\n <FormWarningText text={errors.displayName?.message?.toString()} />\n\n <Button type=\"submit\" className=\"mt-6\" loading={loading}>\n Create\n </Button>\n </div>\n </form>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/components-page/account-settings.tsx"],"sourcesContent":["'use client';\n\nimport { yupResolver } from \"@hookform/resolvers/yup\";\nimport { getPasswordError } from '@stackframe/stack-shared/dist/helpers/password';\nimport { useAsyncCallback } from '@stackframe/stack-shared/dist/hooks/use-async-callback';\nimport { yupObject, yupString } from '@stackframe/stack-shared/dist/schema-fields';\nimport { generateRandomValues } from '@stackframe/stack-shared/dist/utils/crypto';\nimport { throwErr } from '@stackframe/stack-shared/dist/utils/errors';\nimport { runAsynchronously, runAsynchronouslyWithAlert } from '@stackframe/stack-shared/dist/utils/promises';\nimport { Button, EditableText, Input, Label, PasswordInput, SimpleTooltip, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Typography } from '@stackframe/stack-ui';\nimport { CirclePlus, Contact, LogOut, ShieldCheck, LucideIcon } from 'lucide-react';\nimport { TOTPController, createTOTPKeyURI } from \"oslo/otp\";\nimport * as QRCode from 'qrcode';\nimport { useEffect, useState } from 'react';\nimport { useForm } from 'react-hook-form';\nimport * as yup from \"yup\";\nimport { CurrentUser, MessageCard, Project, Team, useStackApp, useUser } from '..';\nimport { FormWarningText } from '../components/elements/form-warning';\nimport { SidebarLayout } from '../components/elements/sidebar-layout';\nimport { UserAvatar } from '../components/elements/user-avatar';\nimport { ProfileImageEditor } from \"../components/profile-image-editor\";\nimport { TeamIcon } from '../components/team-icon';\nimport { MaybeFullPage } from \"../components/elements/maybe-full-page\";\nimport { useTranslation } from \"../lib/translations\";\n\n\nexport function AccountSettings(props: {\n fullPage?: boolean,\n extraItems?: {\n title: string,\n icon: LucideIcon,\n content: React.ReactNode,\n subpath: string,\n }[],\n}) {\n const { t } = useTranslation();\n const user = useUser({ or: 'redirect' });\n const teams = user.useTeams();\n const stackApp = useStackApp();\n const project = stackApp.useProject();\n\n return (\n <MaybeFullPage fullPage={!!props.fullPage}>\n <div style={{ alignSelf: 'stretch', flexGrow: 1 }}>\n <SidebarLayout\n items={([\n {\n title: t('My Profile'),\n type: 'item',\n subpath: '/profile',\n icon: Contact,\n content: <ProfileSection/>,\n },\n {\n title: t('Security'),\n type: 'item',\n icon: ShieldCheck,\n subpath: '/security',\n content: (\n <div className='flex flex-col gap-8'>\n <EmailVerificationSection />\n <PasswordSection />\n <MfaSection />\n </div>\n ),\n },\n {\n title: t('Sign Out'),\n subpath: '/sign-out',\n type: 'item',\n icon: LogOut,\n content: <SignOutSection />,\n },\n ...(props.extraItems?.map(item => ({\n title: item.title,\n type: 'item',\n subpath: item.subpath,\n icon: item.icon,\n content: item.content,\n } as const)) || []),\n ...(teams.length > 0 || project.config.clientTeamCreationEnabled) ? [{\n title: t('Teams'),\n type: 'divider',\n }] as const : [],\n ...teams.map(team => ({\n title: <div className='flex gap-2 items-center'>\n <TeamIcon team={team}/>\n {team.displayName}\n </div>,\n type: 'item',\n subpath: `/teams/${team.id}`,\n content: (\n <div className=\"flex flex-col gap-8\">\n <ProfileSettings team={team}/>\n <ManagementSettings team={team}/>\n <MemberInvitation team={team}/>\n <MembersSettings team={team}/>\n <UserSettings team={team}/>\n </div>\n ),\n } as const)),\n ...project.config.clientTeamCreationEnabled ? [{\n title: t('Create a team'),\n icon: CirclePlus,\n type: 'item',\n subpath: '/team-creation',\n content: <TeamCreation />,\n }] as const : [],\n ] as const).filter((p) => p.type === 'divider' || (p as any).content )}\n title={t(\"Account Settings\")}\n basePath={stackApp.urls.accountSettings}\n />\n </div>\n </MaybeFullPage>\n );\n}\n\nfunction ProfileSection() {\n const { t } = useTranslation();\n const user = useUser({ or: 'redirect' });\n\n return (\n <div className='flex flex-col gap-8'>\n <div className='flex flex-col items-start'>\n <Label className=\"mb-2\">{t(\"Profile image\")}</Label>\n <ProfileImageEditor\n user={user}\n onProfileImageUrlChange={async (profileImageUrl) => {\n await user.update({ profileImageUrl });\n }}\n />\n </div>\n <div className='flex flex-col'>\n <Label>{t(\"Display name\")}</Label>\n <EditableText value={user.displayName || ''} onSave={async (newDisplayName) => {\n await user.update({ displayName: newDisplayName });\n }}/>\n </div>\n </div>\n );\n}\n\nfunction EmailVerificationSection() {\n const { t } = useTranslation();\n const user = useUser({ or: 'redirect' });\n const [emailSent, setEmailSent] = useState(false);\n\n if (!user.primaryEmail) {\n return null;\n }\n\n return (\n <>\n <div>\n <Label>{t(\"Email Verification\")}</Label>\n {user.primaryEmailVerified ? (\n <Typography variant='success'>{t(\"Your email has been verified.\")}</Typography>\n ) : (\n <>\n <Typography variant='destructive'>{t(\"Your email has not been verified.\")}</Typography>\n <div className='flex mt-4'>\n <Button\n disabled={emailSent}\n onClick={async () => {\n await user.sendVerificationEmail();\n setEmailSent(true);\n }}\n >\n {emailSent ? t(\"Email sent!\") : t(\"Send Verification Email\")}\n </Button>\n </div>\n </>\n )}\n\n </div>\n </>\n );\n}\n\nfunction PasswordSection() {\n const { t } = useTranslation();\n\n const passwordSchema = yupObject({\n oldPassword: yupString().required(t('Please enter your old password')),\n newPassword: yupString().required(t('Please enter your password')).test({\n name: 'is-valid-password',\n test: (value, ctx) => {\n const error = getPasswordError(value);\n if (error) {\n return ctx.createError({ message: error.message });\n } else {\n return true;\n }\n }\n }),\n newPasswordRepeat: yupString().nullable().oneOf([yup.ref('newPassword'), \"\", null], t('Passwords do not match')).required(t('Please repeat your password'))\n });\n\n const user = useUser({ or: \"throw\" });\n const [changingPassword, setChangingPassword] = useState(false);\n const { register, handleSubmit, setError, formState: { errors }, clearErrors, reset } = useForm({\n resolver: yupResolver(passwordSchema)\n });\n const [alreadyReset, setAlreadyReset] = useState(false);\n const [loading, setLoading] = useState(false);\n\n const onSubmit = async (data: yup.InferType<typeof passwordSchema>) => {\n setLoading(true);\n try {\n const { oldPassword, newPassword } = data;\n const error = await user.updatePassword({ oldPassword, newPassword });\n if (error) {\n setError('oldPassword', { type: 'manual', message: t('Incorrect password') });\n } else {\n reset();\n setAlreadyReset(true);\n }\n } finally {\n setLoading(false);\n }\n };\n\n const registerPassword = register('newPassword');\n const registerPasswordRepeat = register('newPasswordRepeat');\n\n if (!user.hasPassword) {\n return null;\n }\n\n return (\n <div>\n <Label>{t(\"Change password\")}</Label>\n <div>\n {\n alreadyReset ?\n <Typography variant='success'>{t(\"Password changed successfully!\")}</Typography> :\n !changingPassword ?\n <Button\n variant='secondary'\n onClick={async () => {\n setChangingPassword(true);\n }}\n >{t(\"Change Password\")}</Button> :\n <form\n onSubmit={e => runAsynchronouslyWithAlert(handleSubmit(onSubmit)(e))}\n noValidate\n >\n <Label htmlFor=\"old-password\" className=\"mb-1\">{t(\"Old password\")}</Label>\n <Input\n id=\"old-password\"\n type=\"password\"\n {...register(\"oldPassword\")}\n />\n <FormWarningText text={errors.oldPassword?.message?.toString()} />\n\n <Label htmlFor=\"new-password\" className=\"mt-4 mb-1\">{t(\"Password\")}</Label>\n <PasswordInput\n id=\"new-password\"\n {...registerPassword}\n onChange={(e) => {\n clearErrors('newPassword');\n clearErrors('newPasswordRepeat');\n runAsynchronously(registerPassword.onChange(e));\n }}\n />\n <FormWarningText text={errors.newPassword?.message?.toString()} />\n\n <Label htmlFor=\"repeat-password\" className=\"mt-4 mb-1\">{t(\"Repeat password\")}</Label>\n <PasswordInput\n id=\"repeat-password\"\n {...registerPasswordRepeat}\n onChange={(e) => {\n clearErrors('newPassword');\n clearErrors('newPasswordRepeat');\n runAsynchronously(registerPasswordRepeat.onChange(e));\n }}\n />\n <FormWarningText text={errors.newPasswordRepeat?.message?.toString()} />\n\n <Button type=\"submit\" className=\"mt-6\" loading={loading}>{t(\"Change Password\")}</Button>\n </form>\n }\n </div>\n </div>\n );\n}\n\nfunction MfaSection() {\n const { t } = useTranslation();\n const project = useStackApp().useProject();\n const user = useUser({ or: \"throw\" });\n const [generatedSecret, setGeneratedSecret] = useState<Uint8Array | null>(null);\n const [qrCodeUrl, setQrCodeUrl] = useState<string | null>(null);\n const [mfaCode, setMfaCode] = useState<string>(\"\");\n const [isMaybeWrong, setIsMaybeWrong] = useState(false);\n const isEnabled = user.isMultiFactorRequired;\n\n const [handleSubmit, isLoading] = useAsyncCallback(async () => {\n await user.update({\n totpMultiFactorSecret: generatedSecret,\n });\n setGeneratedSecret(null);\n setQrCodeUrl(null);\n setMfaCode(\"\");\n }, [generatedSecret, user]);\n\n useEffect(() => {\n setIsMaybeWrong(false);\n runAsynchronouslyWithAlert(async () => {\n if (generatedSecret && await new TOTPController().verify(mfaCode, generatedSecret)) {\n await handleSubmit();\n }\n setIsMaybeWrong(true);\n });\n }, [mfaCode, generatedSecret, handleSubmit]);\n\n return (\n <div>\n <div>\n <Label>{t(\"Multi-factor Authentication\")}</Label>\n\n <div>\n {isEnabled ? (\n <Typography variant=\"success\">{t(\"Multi-factor authentication is currently enabled.\")}</Typography>\n ) : (\n generatedSecret ? (\n <div className='flex flex-col gap-4 items-center'>\n <Typography>{t(\"Scan this QR code with your authenticator app:\")}</Typography>\n <img width={200} height={200} src={qrCodeUrl ?? throwErr(\"TOTP QR code failed to generate\")} alt={t(\"TOTP multi-factor authentication QR code\")} />\n <Typography>{t(\"Then, enter your six-digit MFA code:\")}</Typography>\n <Input\n value={mfaCode}\n onChange={(e) => {\n setIsMaybeWrong(false);\n setMfaCode(e.target.value);\n }}\n placeholder=\"123456\"\n maxLength={6}\n disabled={isLoading}\n />\n {isMaybeWrong && mfaCode.length === 6 && (\n <Typography variant=\"destructive\">{t(\"Incorrect code. Please try again.\")}</Typography>\n )}\n </div>\n ) : (\n <Typography variant=\"destructive\">{t(\"Multi-factor authentication is currently disabled.\")}</Typography>\n )\n )}\n\n <Button\n className=\"mt-4\"\n variant={isEnabled ? 'secondary' : 'default'}\n onClick={async () => {\n if (isEnabled) {\n await user.update({\n totpMultiFactorSecret: null,\n });\n } else if (!generatedSecret) {\n const secret = generateRandomValues(new Uint8Array(20));\n setQrCodeUrl(await generateTotpQrCode(project, user, secret));\n setGeneratedSecret(secret);\n } else {\n setGeneratedSecret(null);\n setQrCodeUrl(null);\n setMfaCode(\"\");\n }\n }}\n >\n {isEnabled ? t(\"Disable\") : (generatedSecret ? t(\"Cancel\") : t(\"Enable\"))}\n </Button>\n </div>\n </div>\n </div>\n );\n}\n\nasync function generateTotpQrCode(project: Project, user: CurrentUser, secret: Uint8Array) {\n const uri = createTOTPKeyURI(project.displayName, user.primaryEmail ?? user.id, secret);\n return await QRCode.toDataURL(uri) as any;\n}\n\nfunction SignOutSection() {\n const { t } = useTranslation();\n const user = useUser({ or: \"throw\" });\n return (\n <div className='flex flex-col gap-2'>\n <div>\n <Button\n variant='secondary'\n onClick={() => user.signOut()}\n >{t(\"Sign Out\")}</Button>\n </div>\n </div>\n );\n}\n\nfunction UserSettings(props: { team: Team }) {\n const { t } = useTranslation();\n const user = useUser({ or: 'redirect' });\n const [leaving, setLeaving] = useState(false);\n\n return (\n <div className='flex flex-col gap-2'>\n <div>\n { !leaving ?\n <Button\n variant='secondary'\n onClick={async () => setLeaving(true)}\n >{t(\"Leave team\")}</Button> :\n <div className=''>\n <Typography variant='destructive'>{t(\"Are you sure you want to leave the team?\")}</Typography>\n <div className='flex gap-2'>\n <Button variant='destructive' onClick={async () => {\n await user.leaveTeam(props.team);\n window.location.reload();\n }}>{t(\"Leave\")}</Button>\n <Button variant='secondary' onClick={() => setLeaving(false)}>{t(\"Cancel\")}</Button>\n </div>\n </div>}\n </div>\n </div>\n );\n}\n\nfunction ManagementSettings(props: { team: Team }) {\n const { t } = useTranslation();\n const user = useUser({ or: 'redirect' });\n const updateTeamPermission = user.usePermission(props.team, '$update_team');\n\n if (!updateTeamPermission) {\n return null;\n }\n\n return (\n <>\n <div className='flex flex-col'>\n <Label>{t(\"Team display name\")}</Label>\n <ProfileImageEditor\n user={props.team}\n onProfileImageUrlChange={async (profileImageUrl) => {\n await props.team.update({ profileImageUrl });\n }}\n />\n </div>\n\n <div className='flex flex-col'>\n <Label>{t(\"Team display name\")}</Label>\n <EditableText\n value={props.team.displayName}\n onSave={async (newDisplayName) => await props.team.update({ displayName: newDisplayName })}\n />\n </div>\n </>\n );\n}\n\nfunction ProfileSettings(props: { team: Team }) {\n const { t } = useTranslation();\n const user = useUser({ or: 'redirect' });\n const profile = user.useTeamProfile(props.team);\n\n return (\n <div className=\"flex flex-col\">\n <div className=\"flex flex-col\">\n <Label className=\"flex gap-2\">{t(\"User display name\")}<SimpleTooltip tooltip=\"This overwrites your user display name in the account setting\" type='info'/></Label>\n <EditableText\n value={profile.displayName || ''}\n onSave={async (newDisplayName) => {\n await profile.update({ displayName: newDisplayName });\n }}/>\n </div>\n </div>\n );\n}\n\nfunction MemberInvitation(props: { team: Team }) {\n const { t } = useTranslation();\n\n const invitationSchema = yupObject({\n email: yupString().email().required(t('Please enter an email address')),\n });\n\n const user = useUser({ or: 'redirect' });\n const inviteMemberPermission = user.usePermission(props.team, '$invite_members');\n\n if (!inviteMemberPermission) {\n return null;\n }\n\n const { register, handleSubmit, formState: { errors }, watch } = useForm({\n resolver: yupResolver(invitationSchema)\n });\n const [loading, setLoading] = useState(false);\n const [invitedEmail, setInvitedEmail] = useState<string | null>(null);\n\n const onSubmit = async (data: yup.InferType<typeof invitationSchema>) => {\n setLoading(true);\n\n try {\n await props.team.inviteUser({ email: data.email });\n setInvitedEmail(data.email);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n setInvitedEmail(null);\n }, [watch('email')]);\n\n return (\n <div>\n <Label>{t(\"Invite a user to team\")}</Label>\n <form\n onSubmit={e => runAsynchronouslyWithAlert(handleSubmit(onSubmit)(e))}\n noValidate\n >\n <div className=\"flex flex-col gap-4 md:flex-row\">\n <div>\n <Input\n placeholder={t(\"Email\")}\n {...register(\"email\")}\n />\n </div>\n <Button type=\"submit\" loading={loading}>{t(\"Invite User\")}</Button>\n </div>\n <FormWarningText text={errors.email?.message?.toString()} />\n {invitedEmail && <Typography type='label' variant='secondary'>Invited {invitedEmail}</Typography>}\n </form>\n </div>\n );\n}\n\n\nfunction MembersSettings(props: { team: Team }) {\n const { t } = useTranslation();\n const user = useUser({ or: 'redirect' });\n const readMemberPermission = user.usePermission(props.team, '$read_members');\n const inviteMemberPermission = user.usePermission(props.team, '$invite_members');\n\n if (!readMemberPermission && !inviteMemberPermission) {\n return null;\n }\n\n const users = props.team.useUsers();\n\n if (!readMemberPermission) {\n return null;\n }\n\n return (\n <div>\n <Label>{t(\"Members\")}</Label>\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead className=\"w-[100px]\">{t(\"User\")}</TableHead>\n <TableHead className=\"w-[200px]\">{t(\"Name\")}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {users.map(({ id, teamProfile }, i) => (\n <TableRow key={id}>\n <TableCell>\n <UserAvatar user={teamProfile}/>\n </TableCell>\n <TableCell>\n <Typography>{teamProfile.displayName}</Typography>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n );\n}\n\nexport function TeamCreation() {\n const { t } = useTranslation();\n\n const teamCreationSchema = yupObject({\n displayName: yupString().required(t(\"Please enter a team name\")),\n });\n\n const { register, handleSubmit, formState: { errors } } = useForm({\n resolver: yupResolver(teamCreationSchema)\n });\n const app = useStackApp();\n const project = app.useProject();\n const user = useUser({ or: 'redirect' });\n const [loading, setLoading] = useState(false);\n\n if (!project.config.clientTeamCreationEnabled) {\n return <MessageCard title={t(\"Team creation is not enabled\")} />;\n }\n\n const onSubmit = async (data: yup.InferType<typeof teamCreationSchema>) => {\n setLoading(true);\n\n try {\n const team = await user.createTeam({ displayName: data.displayName });\n } finally {\n setLoading(false);\n }\n };\n\n return (\n <div className='stack-scope flex flex-col items-stretch'>\n <div className=\"mb-6\">\n <form\n className=\"flex flex-col items-stretch stack-scope\"\n onSubmit={e => runAsynchronouslyWithAlert(handleSubmit(onSubmit)(e))}\n noValidate\n >\n <div className=\"flex items-end gap-4\">\n <div>\n <Label htmlFor=\"email\" className=\"mb-1\">{t(\"Display name\")}</Label>\n <Input\n id=\"email\"\n type=\"email\"\n {...register(\"displayName\")}\n />\n </div>\n <FormWarningText text={errors.displayName?.message?.toString()} />\n\n <Button type=\"submit\" className=\"mt-6\" loading={loading}>{t(\"Create\")}</Button>\n </div>\n </form>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}