@stackframe/stack 2.5.35 → 2.5.37
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.
- package/CHANGELOG.md +20 -0
- package/dist/components/elements/sidebar-layout.js +15 -7
- package/dist/components/elements/sidebar-layout.js.map +1 -1
- package/dist/components/elements/user-avatar.js +1 -1
- package/dist/components/elements/user-avatar.js.map +1 -1
- package/dist/components/oauth-button.js +19 -21
- package/dist/components/oauth-button.js.map +1 -1
- package/dist/components/profile-image-editor.js +2 -2
- package/dist/components/profile-image-editor.js.map +1 -1
- package/dist/components/selected-team-switcher.js +1 -1
- package/dist/components/selected-team-switcher.js.map +1 -1
- package/dist/components-page/account-settings.d.mts +4 -2
- package/dist/components-page/account-settings.d.ts +4 -2
- package/dist/components-page/account-settings.js +356 -184
- package/dist/components-page/account-settings.js.map +1 -1
- package/dist/components-page/oauth-callback.js +1 -1
- package/dist/components-page/oauth-callback.js.map +1 -1
- package/dist/components-page/stack-handler.d.mts +1 -0
- package/dist/components-page/stack-handler.d.ts +1 -0
- package/dist/esm/components/elements/sidebar-layout.js +15 -7
- package/dist/esm/components/elements/sidebar-layout.js.map +1 -1
- package/dist/esm/components/elements/user-avatar.js +1 -1
- package/dist/esm/components/elements/user-avatar.js.map +1 -1
- package/dist/esm/components/oauth-button.js +19 -21
- package/dist/esm/components/oauth-button.js.map +1 -1
- package/dist/esm/components/profile-image-editor.js +2 -2
- package/dist/esm/components/profile-image-editor.js.map +1 -1
- package/dist/esm/components/selected-team-switcher.js +1 -1
- package/dist/esm/components/selected-team-switcher.js.map +1 -1
- package/dist/esm/components-page/account-settings.js +356 -185
- package/dist/esm/components-page/account-settings.js.map +1 -1
- package/dist/esm/components-page/oauth-callback.js +1 -1
- package/dist/esm/components-page/oauth-callback.js.map +1 -1
- package/dist/esm/generated/global-css.js +1 -1
- package/dist/esm/generated/global-css.js.map +1 -1
- package/dist/esm/generated/quetzal-translations.js +1555 -1351
- package/dist/esm/generated/quetzal-translations.js.map +1 -1
- package/dist/esm/lib/stack-app.js +8 -1
- package/dist/esm/lib/stack-app.js.map +1 -1
- package/dist/esm/utils/browser-script.js +10 -7
- package/dist/esm/utils/browser-script.js.map +1 -1
- package/dist/generated/global-css.d.mts +1 -1
- package/dist/generated/global-css.d.ts +1 -1
- package/dist/generated/global-css.js +1 -1
- package/dist/generated/global-css.js.map +1 -1
- package/dist/generated/quetzal-translations.d.mts +2 -2
- package/dist/generated/quetzal-translations.d.ts +2 -2
- package/dist/generated/quetzal-translations.js +1555 -1351
- package/dist/generated/quetzal-translations.js.map +1 -1
- package/dist/lib/stack-app.d.mts +4 -1
- package/dist/lib/stack-app.d.ts +4 -1
- package/dist/lib/stack-app.js +8 -1
- package/dist/lib/stack-app.js.map +1 -1
- package/dist/utils/browser-script.js +10 -7
- package/dist/utils/browser-script.js.map +1 -1
- package/package.json +4 -4
|
@@ -33,7 +33,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
33
33
|
var account_settings_exports = {};
|
|
34
34
|
__export(account_settings_exports, {
|
|
35
35
|
AccountSettings: () => AccountSettings,
|
|
36
|
-
TeamCreation: () => TeamCreation
|
|
36
|
+
TeamCreation: () => TeamCreation,
|
|
37
|
+
useDeleteAccountSection: () => useDeleteAccountSection
|
|
37
38
|
});
|
|
38
39
|
module.exports = __toCommonJS(account_settings_exports);
|
|
39
40
|
var import_yup = require("@hookform/resolvers/yup");
|
|
@@ -47,16 +48,16 @@ var import_stack_ui = require("@stackframe/stack-ui");
|
|
|
47
48
|
var import_lucide_react = require("lucide-react");
|
|
48
49
|
var import_otp = require("oslo/otp");
|
|
49
50
|
var QRCode = __toESM(require("qrcode"));
|
|
50
|
-
var import_react = require("react");
|
|
51
|
+
var import_react = __toESM(require("react"));
|
|
51
52
|
var import_react_hook_form = require("react-hook-form");
|
|
52
53
|
var yup = __toESM(require("yup"));
|
|
53
54
|
var import__ = require("..");
|
|
54
55
|
var import_form_warning = require("../components/elements/form-warning");
|
|
56
|
+
var import_maybe_full_page = require("../components/elements/maybe-full-page");
|
|
55
57
|
var import_sidebar_layout = require("../components/elements/sidebar-layout");
|
|
56
58
|
var import_user_avatar = require("../components/elements/user-avatar");
|
|
57
59
|
var import_profile_image_editor = require("../components/profile-image-editor");
|
|
58
60
|
var import_team_icon = require("../components/team-icon");
|
|
59
|
-
var import_maybe_full_page = require("../components/elements/maybe-full-page");
|
|
60
61
|
var import_translations = require("../lib/translations");
|
|
61
62
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
62
63
|
function AccountSettings(props) {
|
|
@@ -74,25 +75,21 @@ function AccountSettings(props) {
|
|
|
74
75
|
type: "item",
|
|
75
76
|
subpath: "/profile",
|
|
76
77
|
icon: import_lucide_react.Contact,
|
|
77
|
-
content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
78
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProfilePage, {})
|
|
78
79
|
},
|
|
79
80
|
{
|
|
80
81
|
title: t("Security"),
|
|
81
82
|
type: "item",
|
|
82
|
-
icon: import_lucide_react.ShieldCheck,
|
|
83
83
|
subpath: "/security",
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(PasswordSection, {}),
|
|
87
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MfaSection, {})
|
|
88
|
-
] })
|
|
84
|
+
icon: import_lucide_react.ShieldCheck,
|
|
85
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SecurityPage, {})
|
|
89
86
|
},
|
|
90
87
|
{
|
|
91
|
-
title: t("
|
|
92
|
-
subpath: "/sign-out",
|
|
88
|
+
title: t("Settings"),
|
|
93
89
|
type: "item",
|
|
94
|
-
|
|
95
|
-
|
|
90
|
+
subpath: "/settings",
|
|
91
|
+
icon: import_lucide_react.Settings,
|
|
92
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SettingsPage, {})
|
|
96
93
|
},
|
|
97
94
|
...props.extraItems?.map((item) => ({
|
|
98
95
|
title: item.title,
|
|
@@ -112,13 +109,7 @@ function AccountSettings(props) {
|
|
|
112
109
|
] }),
|
|
113
110
|
type: "item",
|
|
114
111
|
subpath: `/teams/${team.id}`,
|
|
115
|
-
content: /* @__PURE__ */ (0, import_jsx_runtime.
|
|
116
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProfileSettings, { team }),
|
|
117
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ManagementSettings, { team }),
|
|
118
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MemberInvitation, { team }),
|
|
119
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MembersSettings, { team }),
|
|
120
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(UserSettings, { team })
|
|
121
|
-
] })
|
|
112
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TeamPage, { team })
|
|
122
113
|
})),
|
|
123
114
|
...project.config.clientTeamCreationEnabled ? [{
|
|
124
115
|
title: t("Create a team"),
|
|
@@ -133,42 +124,93 @@ function AccountSettings(props) {
|
|
|
133
124
|
}
|
|
134
125
|
) }) });
|
|
135
126
|
}
|
|
136
|
-
function
|
|
127
|
+
function Section(props) {
|
|
128
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex", children: [
|
|
129
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex-1 flex flex-col justify-center", children: [
|
|
130
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { className: "font-medium", children: props.title }),
|
|
131
|
+
props.description && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "secondary", type: "footnote", children: props.description })
|
|
132
|
+
] }),
|
|
133
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex-1 flex flex-col gap-2", children: props.children })
|
|
134
|
+
] });
|
|
135
|
+
}
|
|
136
|
+
function PageLayout(props) {
|
|
137
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col gap-6", children: [
|
|
138
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Separator, {}),
|
|
139
|
+
import_react.default.Children.map(props.children, (child) => child && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
140
|
+
child,
|
|
141
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Separator, {})
|
|
142
|
+
] }))
|
|
143
|
+
] });
|
|
144
|
+
}
|
|
145
|
+
function ProfilePage() {
|
|
137
146
|
const { t } = (0, import_translations.useTranslation)();
|
|
138
147
|
const user = (0, import__.useUser)({ or: "redirect" });
|
|
139
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
140
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(PageLayout, { children: [
|
|
149
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
150
|
+
Section,
|
|
151
|
+
{
|
|
152
|
+
title: t("User name"),
|
|
153
|
+
description: t("This is a display name and is not used for authentication"),
|
|
154
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
155
|
+
import_stack_ui.EditableText,
|
|
156
|
+
{
|
|
157
|
+
value: user.displayName || "",
|
|
158
|
+
onSave: async (newDisplayName) => {
|
|
159
|
+
await user.update({ displayName: newDisplayName });
|
|
160
|
+
}
|
|
148
161
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
162
|
+
)
|
|
163
|
+
}
|
|
164
|
+
),
|
|
165
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
166
|
+
Section,
|
|
167
|
+
{
|
|
168
|
+
title: t("Profile image"),
|
|
169
|
+
description: t("Upload your own image as your avatar"),
|
|
170
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
171
|
+
import_profile_image_editor.ProfileImageEditor,
|
|
172
|
+
{
|
|
173
|
+
user,
|
|
174
|
+
onProfileImageUrlChange: async (profileImageUrl) => {
|
|
175
|
+
await user.update({ profileImageUrl });
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
)
|
|
179
|
+
}
|
|
180
|
+
)
|
|
158
181
|
] });
|
|
159
182
|
}
|
|
160
|
-
function
|
|
183
|
+
function SecurityPage() {
|
|
184
|
+
const emailVerificationSection = useEmailVerificationSection();
|
|
185
|
+
const passwordSection = usePasswordSection();
|
|
186
|
+
const mfaSection = useMfaSection();
|
|
187
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(PageLayout, { children: [
|
|
188
|
+
emailVerificationSection,
|
|
189
|
+
passwordSection,
|
|
190
|
+
mfaSection
|
|
191
|
+
] });
|
|
192
|
+
}
|
|
193
|
+
function SettingsPage() {
|
|
194
|
+
const deleteAccountSection = useDeleteAccountSection();
|
|
195
|
+
const signOutSection = useSignOutSection();
|
|
196
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(PageLayout, { children: [
|
|
197
|
+
deleteAccountSection,
|
|
198
|
+
signOutSection
|
|
199
|
+
] });
|
|
200
|
+
}
|
|
201
|
+
function useEmailVerificationSection() {
|
|
161
202
|
const { t } = (0, import_translations.useTranslation)();
|
|
162
203
|
const user = (0, import__.useUser)({ or: "redirect" });
|
|
163
204
|
const [emailSent, setEmailSent] = (0, import_react.useState)(false);
|
|
164
205
|
if (!user.primaryEmail) {
|
|
165
206
|
return null;
|
|
166
207
|
}
|
|
167
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
208
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
209
|
+
Section,
|
|
210
|
+
{
|
|
211
|
+
title: t("Email Verification"),
|
|
212
|
+
description: t("Verify your email address to secure your account"),
|
|
213
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: user.primaryEmailVerified ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "success", children: t("Your email has been verified.") }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
172
214
|
import_stack_ui.Button,
|
|
173
215
|
{
|
|
174
216
|
disabled: emailSent,
|
|
@@ -178,11 +220,11 @@ function EmailVerificationSection() {
|
|
|
178
220
|
},
|
|
179
221
|
children: emailSent ? t("Email sent!") : t("Send Verification Email")
|
|
180
222
|
}
|
|
181
|
-
) })
|
|
182
|
-
|
|
183
|
-
|
|
223
|
+
) }) })
|
|
224
|
+
}
|
|
225
|
+
);
|
|
184
226
|
}
|
|
185
|
-
function
|
|
227
|
+
function usePasswordSection() {
|
|
186
228
|
const { t } = (0, import_translations.useTranslation)();
|
|
187
229
|
const passwordSchema = (0, import_schema_fields.yupObject)({
|
|
188
230
|
oldPassword: (0, import_schema_fields.yupString)().required(t("Please enter your old password")),
|
|
@@ -287,7 +329,7 @@ function PasswordSection() {
|
|
|
287
329
|
) })
|
|
288
330
|
] });
|
|
289
331
|
}
|
|
290
|
-
function
|
|
332
|
+
function useMfaSection() {
|
|
291
333
|
const { t } = (0, import_translations.useTranslation)();
|
|
292
334
|
const project = (0, import__.useStackApp)().useProject();
|
|
293
335
|
const user = (0, import__.useUser)({ or: "throw" });
|
|
@@ -313,103 +355,165 @@ function MfaSection() {
|
|
|
313
355
|
setIsMaybeWrong(true);
|
|
314
356
|
});
|
|
315
357
|
}, [mfaCode, generatedSecret, handleSubmit]);
|
|
316
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
323
|
-
|
|
324
|
-
|
|
358
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
359
|
+
Section,
|
|
360
|
+
{
|
|
361
|
+
title: t("Multi-factor Authentication"),
|
|
362
|
+
description: isEnabled ? t("Multi-factor authentication is currently enabled.") : t("Multi-factor authentication is currently disabled."),
|
|
363
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col gap-4", children: [
|
|
364
|
+
!isEnabled && generatedSecret && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
365
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { children: t("Scan this QR code with your authenticator app:") }),
|
|
366
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { width: 200, height: 200, src: qrCodeUrl ?? (0, import_errors.throwErr)("TOTP QR code failed to generate"), alt: t("TOTP multi-factor authentication QR code") }),
|
|
367
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { children: t("Then, enter your six-digit MFA code:") }),
|
|
368
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
369
|
+
import_stack_ui.Input,
|
|
370
|
+
{
|
|
371
|
+
value: mfaCode,
|
|
372
|
+
onChange: (e) => {
|
|
373
|
+
setIsMaybeWrong(false);
|
|
374
|
+
setMfaCode(e.target.value);
|
|
375
|
+
},
|
|
376
|
+
placeholder: "123456",
|
|
377
|
+
maxLength: 6,
|
|
378
|
+
disabled: isLoading
|
|
379
|
+
}
|
|
380
|
+
),
|
|
381
|
+
isMaybeWrong && mfaCode.length === 6 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "destructive", children: t("Incorrect code. Please try again.") }),
|
|
382
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
383
|
+
import_stack_ui.Button,
|
|
384
|
+
{
|
|
385
|
+
variant: "secondary",
|
|
386
|
+
onClick: () => {
|
|
387
|
+
setGeneratedSecret(null);
|
|
388
|
+
setQrCodeUrl(null);
|
|
389
|
+
setMfaCode("");
|
|
390
|
+
},
|
|
391
|
+
children: t("Cancel")
|
|
392
|
+
}
|
|
393
|
+
) })
|
|
394
|
+
] }),
|
|
395
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex gap-2", children: isEnabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
396
|
+
import_stack_ui.Button,
|
|
325
397
|
{
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
setIsMaybeWrong(false);
|
|
329
|
-
setMfaCode(e.target.value);
|
|
330
|
-
},
|
|
331
|
-
placeholder: "123456",
|
|
332
|
-
maxLength: 6,
|
|
333
|
-
disabled: isLoading
|
|
334
|
-
}
|
|
335
|
-
),
|
|
336
|
-
isMaybeWrong && mfaCode.length === 6 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "destructive", children: t("Incorrect code. Please try again.") })
|
|
337
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "destructive", children: t("Multi-factor authentication is currently disabled.") }),
|
|
338
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
339
|
-
import_stack_ui.Button,
|
|
340
|
-
{
|
|
341
|
-
className: "mt-4",
|
|
342
|
-
variant: isEnabled ? "secondary" : "default",
|
|
343
|
-
onClick: async () => {
|
|
344
|
-
if (isEnabled) {
|
|
398
|
+
variant: "secondary",
|
|
399
|
+
onClick: async () => {
|
|
345
400
|
await user.update({
|
|
346
401
|
totpMultiFactorSecret: null
|
|
347
402
|
});
|
|
348
|
-
}
|
|
403
|
+
},
|
|
404
|
+
children: t("Disable")
|
|
405
|
+
}
|
|
406
|
+
) : !generatedSecret && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
407
|
+
import_stack_ui.Button,
|
|
408
|
+
{
|
|
409
|
+
variant: "default",
|
|
410
|
+
onClick: async () => {
|
|
349
411
|
const secret = (0, import_crypto.generateRandomValues)(new Uint8Array(20));
|
|
350
412
|
setQrCodeUrl(await generateTotpQrCode(project, user, secret));
|
|
351
413
|
setGeneratedSecret(secret);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
}
|
|
360
|
-
)
|
|
361
|
-
] })
|
|
362
|
-
] }) });
|
|
414
|
+
},
|
|
415
|
+
children: t("Enable")
|
|
416
|
+
}
|
|
417
|
+
) })
|
|
418
|
+
] })
|
|
419
|
+
}
|
|
420
|
+
);
|
|
363
421
|
}
|
|
364
422
|
async function generateTotpQrCode(project, user, secret) {
|
|
365
423
|
const uri = (0, import_otp.createTOTPKeyURI)(project.displayName, user.primaryEmail ?? user.id, secret);
|
|
366
424
|
return await QRCode.toDataURL(uri);
|
|
367
425
|
}
|
|
368
|
-
function
|
|
426
|
+
function useSignOutSection() {
|
|
369
427
|
const { t } = (0, import_translations.useTranslation)();
|
|
370
428
|
const user = (0, import__.useUser)({ or: "throw" });
|
|
371
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
372
|
-
|
|
429
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
430
|
+
Section,
|
|
373
431
|
{
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
children:
|
|
432
|
+
title: t("Sign out"),
|
|
433
|
+
description: t("End your current session"),
|
|
434
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
435
|
+
import_stack_ui.Button,
|
|
436
|
+
{
|
|
437
|
+
variant: "secondary",
|
|
438
|
+
onClick: () => user.signOut(),
|
|
439
|
+
children: t("Sign out")
|
|
440
|
+
}
|
|
441
|
+
) })
|
|
377
442
|
}
|
|
378
|
-
)
|
|
443
|
+
);
|
|
379
444
|
}
|
|
380
|
-
function
|
|
445
|
+
function TeamPage(props) {
|
|
446
|
+
const teamUserProfileSection = useTeamUserProfileSection(props);
|
|
447
|
+
const teamProfileImageSection = useTeamProfileImageSection(props);
|
|
448
|
+
const teamDisplayNameSection = useTeamDisplayNameSection(props);
|
|
449
|
+
const leaveTeamSection = useLeaveTeamSection(props);
|
|
450
|
+
const memberInvitationSection = useMemberInvitationSection(props);
|
|
451
|
+
const memberListSection = useMemberListSection(props);
|
|
452
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(PageLayout, { children: [
|
|
453
|
+
teamUserProfileSection,
|
|
454
|
+
memberInvitationSection,
|
|
455
|
+
memberListSection,
|
|
456
|
+
teamProfileImageSection,
|
|
457
|
+
teamDisplayNameSection,
|
|
458
|
+
leaveTeamSection
|
|
459
|
+
] });
|
|
460
|
+
}
|
|
461
|
+
function useLeaveTeamSection(props) {
|
|
381
462
|
const { t } = (0, import_translations.useTranslation)();
|
|
382
463
|
const user = (0, import__.useUser)({ or: "redirect" });
|
|
383
464
|
const [leaving, setLeaving] = (0, import_react.useState)(false);
|
|
384
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
385
|
-
|
|
465
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
466
|
+
Section,
|
|
386
467
|
{
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
children:
|
|
468
|
+
title: t("Leave Team"),
|
|
469
|
+
description: t("leave this team and remove your team profile"),
|
|
470
|
+
children: !leaving ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
471
|
+
import_stack_ui.Button,
|
|
472
|
+
{
|
|
473
|
+
variant: "secondary",
|
|
474
|
+
onClick: () => setLeaving(true),
|
|
475
|
+
children: t("Leave team")
|
|
476
|
+
}
|
|
477
|
+
) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
478
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "destructive", children: t("Are you sure you want to leave the team?") }),
|
|
479
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex gap-2", children: [
|
|
480
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
481
|
+
import_stack_ui.Button,
|
|
482
|
+
{
|
|
483
|
+
variant: "destructive",
|
|
484
|
+
onClick: async () => {
|
|
485
|
+
await user.leaveTeam(props.team);
|
|
486
|
+
window.location.reload();
|
|
487
|
+
},
|
|
488
|
+
children: t("Leave")
|
|
489
|
+
}
|
|
490
|
+
),
|
|
491
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
492
|
+
import_stack_ui.Button,
|
|
493
|
+
{
|
|
494
|
+
variant: "secondary",
|
|
495
|
+
onClick: () => setLeaving(false),
|
|
496
|
+
children: t("Cancel")
|
|
497
|
+
}
|
|
498
|
+
)
|
|
499
|
+
] })
|
|
500
|
+
] })
|
|
390
501
|
}
|
|
391
|
-
)
|
|
392
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "destructive", children: t("Are you sure you want to leave the team?") }),
|
|
393
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex gap-2", children: [
|
|
394
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Button, { variant: "destructive", onClick: async () => {
|
|
395
|
-
await user.leaveTeam(props.team);
|
|
396
|
-
window.location.reload();
|
|
397
|
-
}, children: t("Leave") }),
|
|
398
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Button, { variant: "secondary", onClick: () => setLeaving(false), children: t("Cancel") })
|
|
399
|
-
] })
|
|
400
|
-
] }) }) });
|
|
502
|
+
);
|
|
401
503
|
}
|
|
402
|
-
function
|
|
504
|
+
function useTeamProfileImageSection(props) {
|
|
403
505
|
const { t } = (0, import_translations.useTranslation)();
|
|
404
506
|
const user = (0, import__.useUser)({ or: "redirect" });
|
|
405
507
|
const updateTeamPermission = user.usePermission(props.team, "$update_team");
|
|
406
508
|
if (!updateTeamPermission) {
|
|
407
509
|
return null;
|
|
408
510
|
}
|
|
409
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
511
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
512
|
+
Section,
|
|
513
|
+
{
|
|
514
|
+
title: t("Team profile image"),
|
|
515
|
+
description: t("Upload an image for your team"),
|
|
516
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
413
517
|
import_profile_image_editor.ProfileImageEditor,
|
|
414
518
|
{
|
|
415
519
|
user: props.team,
|
|
@@ -418,40 +522,53 @@ function ManagementSettings(props) {
|
|
|
418
522
|
}
|
|
419
523
|
}
|
|
420
524
|
)
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
525
|
+
}
|
|
526
|
+
);
|
|
527
|
+
}
|
|
528
|
+
function useTeamDisplayNameSection(props) {
|
|
529
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
530
|
+
const user = (0, import__.useUser)({ or: "redirect" });
|
|
531
|
+
const updateTeamPermission = user.usePermission(props.team, "$update_team");
|
|
532
|
+
if (!updateTeamPermission) {
|
|
533
|
+
return null;
|
|
534
|
+
}
|
|
535
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
536
|
+
Section,
|
|
537
|
+
{
|
|
538
|
+
title: t("Team display name"),
|
|
539
|
+
description: t("Change the display name of your team"),
|
|
540
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
425
541
|
import_stack_ui.EditableText,
|
|
426
542
|
{
|
|
427
543
|
value: props.team.displayName,
|
|
428
544
|
onSave: async (newDisplayName) => await props.team.update({ displayName: newDisplayName })
|
|
429
545
|
}
|
|
430
546
|
)
|
|
431
|
-
|
|
432
|
-
|
|
547
|
+
}
|
|
548
|
+
);
|
|
433
549
|
}
|
|
434
|
-
function
|
|
550
|
+
function useTeamUserProfileSection(props) {
|
|
435
551
|
const { t } = (0, import_translations.useTranslation)();
|
|
436
552
|
const user = (0, import__.useUser)({ or: "redirect" });
|
|
437
553
|
const profile = user.useTeamProfile(props.team);
|
|
438
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
554
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
555
|
+
Section,
|
|
556
|
+
{
|
|
557
|
+
title: t("Team user name"),
|
|
558
|
+
description: t("Overwrite your user display name in this team"),
|
|
559
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
560
|
+
import_stack_ui.EditableText,
|
|
561
|
+
{
|
|
562
|
+
value: profile.displayName || "",
|
|
563
|
+
onSave: async (newDisplayName) => {
|
|
564
|
+
await profile.update({ displayName: newDisplayName });
|
|
565
|
+
}
|
|
449
566
|
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
567
|
+
)
|
|
568
|
+
}
|
|
569
|
+
);
|
|
453
570
|
}
|
|
454
|
-
function
|
|
571
|
+
function useMemberInvitationSection(props) {
|
|
455
572
|
const { t } = (0, import_translations.useTranslation)();
|
|
456
573
|
const invitationSchema = (0, import_schema_fields.yupObject)({
|
|
457
574
|
email: (0, import_schema_fields.yupString)().email().required(t("Please enter an email address"))
|
|
@@ -478,35 +595,39 @@ function MemberInvitation(props) {
|
|
|
478
595
|
(0, import_react.useEffect)(() => {
|
|
479
596
|
setInvitedEmail(null);
|
|
480
597
|
}, [watch("email")]);
|
|
481
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
"
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
598
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
599
|
+
Section,
|
|
600
|
+
{
|
|
601
|
+
title: t("Invite member"),
|
|
602
|
+
description: t("Invite a user to your team through email"),
|
|
603
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
604
|
+
"form",
|
|
605
|
+
{
|
|
606
|
+
onSubmit: (e) => (0, import_promises.runAsynchronouslyWithAlert)(handleSubmit(onSubmit)(e)),
|
|
607
|
+
noValidate: true,
|
|
608
|
+
children: [
|
|
609
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col gap-4 md:flex-row", children: [
|
|
610
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
611
|
+
import_stack_ui.Input,
|
|
612
|
+
{
|
|
613
|
+
placeholder: t("Email"),
|
|
614
|
+
...register("email")
|
|
615
|
+
}
|
|
616
|
+
),
|
|
617
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Button, { type: "submit", loading, children: t("Invite User") })
|
|
618
|
+
] }),
|
|
619
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_form_warning.FormWarningText, { text: errors.email?.message?.toString() }),
|
|
620
|
+
invitedEmail && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_stack_ui.Typography, { type: "label", variant: "secondary", children: [
|
|
621
|
+
"Invited ",
|
|
622
|
+
invitedEmail
|
|
623
|
+
] })
|
|
624
|
+
]
|
|
625
|
+
}
|
|
626
|
+
)
|
|
627
|
+
}
|
|
628
|
+
);
|
|
508
629
|
}
|
|
509
|
-
function
|
|
630
|
+
function useMemberListSection(props) {
|
|
510
631
|
const { t } = (0, import_translations.useTranslation)();
|
|
511
632
|
const user = (0, import__.useUser)({ or: "redirect" });
|
|
512
633
|
const readMemberPermission = user.usePermission(props.team, "$read_members");
|
|
@@ -519,8 +640,8 @@ function MembersSettings(props) {
|
|
|
519
640
|
return null;
|
|
520
641
|
}
|
|
521
642
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
522
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.
|
|
523
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_stack_ui.Table, { children: [
|
|
643
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { className: "font-medium mb-2", children: t("Members") }),
|
|
644
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "border rounded-md", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_stack_ui.Table, { children: [
|
|
524
645
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_stack_ui.TableRow, { children: [
|
|
525
646
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableHead, { className: "w-[100px]", children: t("User") }),
|
|
526
647
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableHead, { className: "w-[200px]", children: t("Name") })
|
|
@@ -529,7 +650,7 @@ function MembersSettings(props) {
|
|
|
529
650
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableCell, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_user_avatar.UserAvatar, { user: teamProfile }) }),
|
|
530
651
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableCell, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { children: teamProfile.displayName }) })
|
|
531
652
|
] }, id)) })
|
|
532
|
-
] })
|
|
653
|
+
] }) })
|
|
533
654
|
] });
|
|
534
655
|
}
|
|
535
656
|
function TeamCreation() {
|
|
@@ -555,33 +676,84 @@ function TeamCreation() {
|
|
|
555
676
|
setLoading(false);
|
|
556
677
|
}
|
|
557
678
|
};
|
|
558
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
679
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PageLayout, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Section, { title: t("Create a Team"), description: t("Enter a display name for your new team"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
559
680
|
"form",
|
|
560
681
|
{
|
|
561
|
-
className: "flex flex-col items-stretch stack-scope",
|
|
562
682
|
onSubmit: (e) => (0, import_promises.runAsynchronouslyWithAlert)(handleSubmit(onSubmit)(e)),
|
|
563
683
|
noValidate: true,
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
684
|
+
className: "flex gap-2",
|
|
685
|
+
children: [
|
|
686
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col flex-1", children: [
|
|
567
687
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
568
688
|
import_stack_ui.Input,
|
|
569
689
|
{
|
|
570
|
-
id: "
|
|
571
|
-
type: "
|
|
690
|
+
id: "displayName",
|
|
691
|
+
type: "text",
|
|
572
692
|
...register("displayName")
|
|
573
693
|
}
|
|
574
|
-
)
|
|
694
|
+
),
|
|
695
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_form_warning.FormWarningText, { text: errors.displayName?.message?.toString() })
|
|
575
696
|
] }),
|
|
576
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
577
|
-
|
|
578
|
-
] })
|
|
697
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Button, { type: "submit", loading, children: t("Create") })
|
|
698
|
+
]
|
|
579
699
|
}
|
|
580
700
|
) }) });
|
|
581
701
|
}
|
|
702
|
+
function useDeleteAccountSection() {
|
|
703
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
704
|
+
const user = (0, import__.useUser)({ or: "redirect" });
|
|
705
|
+
const app = (0, import__.useStackApp)();
|
|
706
|
+
const project = app.useProject();
|
|
707
|
+
const [deleting, setDeleting] = (0, import_react.useState)(false);
|
|
708
|
+
if (!project.config.clientUserDeletionEnabled) {
|
|
709
|
+
return null;
|
|
710
|
+
}
|
|
711
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
712
|
+
Section,
|
|
713
|
+
{
|
|
714
|
+
title: t("Delete Account"),
|
|
715
|
+
description: t("Permanently remove your account and all associated data"),
|
|
716
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "stack-scope flex flex-col items-stretch", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Accordion, { type: "single", collapsible: true, className: "w-full", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_stack_ui.AccordionItem, { value: "item-1", children: [
|
|
717
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.AccordionTrigger, { children: t("Danger zone") }),
|
|
718
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.AccordionContent, { children: !deleting ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
719
|
+
import_stack_ui.Button,
|
|
720
|
+
{
|
|
721
|
+
variant: "destructive",
|
|
722
|
+
onClick: () => setDeleting(true),
|
|
723
|
+
children: t("Delete account")
|
|
724
|
+
}
|
|
725
|
+
) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
726
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "destructive", children: t("Are you sure you want to delete your account? This action is IRREVERSIBLE and will delete ALL associated data.") }),
|
|
727
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex gap-2", children: [
|
|
728
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
729
|
+
import_stack_ui.Button,
|
|
730
|
+
{
|
|
731
|
+
variant: "destructive",
|
|
732
|
+
onClick: async () => {
|
|
733
|
+
await user.delete();
|
|
734
|
+
await app.redirectToHome();
|
|
735
|
+
},
|
|
736
|
+
children: t("Delete Account")
|
|
737
|
+
}
|
|
738
|
+
),
|
|
739
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
740
|
+
import_stack_ui.Button,
|
|
741
|
+
{
|
|
742
|
+
variant: "secondary",
|
|
743
|
+
onClick: () => setDeleting(false),
|
|
744
|
+
children: t("Cancel")
|
|
745
|
+
}
|
|
746
|
+
)
|
|
747
|
+
] })
|
|
748
|
+
] }) })
|
|
749
|
+
] }) }) })
|
|
750
|
+
}
|
|
751
|
+
);
|
|
752
|
+
}
|
|
582
753
|
// Annotate the CommonJS export names for ESM import in node:
|
|
583
754
|
0 && (module.exports = {
|
|
584
755
|
AccountSettings,
|
|
585
|
-
TeamCreation
|
|
756
|
+
TeamCreation,
|
|
757
|
+
useDeleteAccountSection
|
|
586
758
|
});
|
|
587
759
|
//# sourceMappingURL=account-settings.js.map
|