@stackframe/stack 2.5.25 → 2.5.28
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 +30 -0
- package/dist/components/elements/maybe-full-page.d.mts +2 -3
- package/dist/components/elements/maybe-full-page.d.ts +2 -3
- package/dist/components/elements/maybe-full-page.js +5 -9
- package/dist/components/elements/maybe-full-page.js.map +1 -1
- package/dist/components/elements/user-avatar.d.mts +1 -0
- package/dist/components/elements/user-avatar.d.ts +1 -0
- package/dist/components/elements/user-avatar.js +4 -3
- package/dist/components/elements/user-avatar.js.map +1 -1
- package/dist/components/message-cards/message-card.js +1 -1
- package/dist/components/message-cards/message-card.js.map +1 -1
- package/dist/components/profile-image-editor.d.mts +11 -0
- package/dist/components/profile-image-editor.d.ts +11 -0
- package/dist/components/profile-image-editor.js +160 -0
- package/dist/components/profile-image-editor.js.map +1 -0
- package/dist/components/team-icon.js +2 -13
- package/dist/components/team-icon.js.map +1 -1
- package/dist/components-page/account-settings.js +48 -19
- package/dist/components-page/account-settings.js.map +1 -1
- package/dist/components-page/auth-page.js +1 -1
- package/dist/components-page/auth-page.js.map +1 -1
- package/dist/components-page/forgot-password.js +1 -1
- package/dist/components-page/forgot-password.js.map +1 -1
- package/dist/components-page/password-reset.js +1 -1
- package/dist/components-page/password-reset.js.map +1 -1
- package/dist/components-page/stack-handler.js +5 -1
- package/dist/components-page/stack-handler.js.map +1 -1
- package/dist/components-page/team-creation.js +1 -1
- package/dist/components-page/team-creation.js.map +1 -1
- package/dist/esm/components/elements/maybe-full-page.js +5 -9
- package/dist/esm/components/elements/maybe-full-page.js.map +1 -1
- package/dist/esm/components/elements/user-avatar.js +4 -3
- package/dist/esm/components/elements/user-avatar.js.map +1 -1
- package/dist/esm/components/message-cards/message-card.js +1 -1
- package/dist/esm/components/message-cards/message-card.js.map +1 -1
- package/dist/esm/components/profile-image-editor.js +124 -0
- package/dist/esm/components/profile-image-editor.js.map +1 -0
- package/dist/esm/components/team-icon.js +3 -4
- package/dist/esm/components/team-icon.js.map +1 -1
- package/dist/esm/components-page/account-settings.js +48 -19
- package/dist/esm/components-page/account-settings.js.map +1 -1
- package/dist/esm/components-page/auth-page.js +1 -1
- package/dist/esm/components-page/auth-page.js.map +1 -1
- package/dist/esm/components-page/forgot-password.js +1 -1
- package/dist/esm/components-page/forgot-password.js.map +1 -1
- package/dist/esm/components-page/password-reset.js +1 -1
- package/dist/esm/components-page/password-reset.js.map +1 -1
- package/dist/esm/components-page/stack-handler.js +5 -1
- package/dist/esm/components-page/stack-handler.js.map +1 -1
- package/dist/esm/components-page/team-creation.js +1 -1
- package/dist/esm/components-page/team-creation.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/lib/auth.js +26 -15
- package/dist/esm/lib/auth.js.map +1 -1
- package/dist/esm/lib/cookie.js +10 -8
- package/dist/esm/lib/cookie.js.map +1 -1
- package/dist/esm/lib/stack-app.js +15 -4
- package/dist/esm/lib/stack-app.js.map +1 -1
- package/dist/esm/utils/constants.js +1 -1
- package/dist/esm/utils/constants.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/lib/auth.js +24 -13
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/cookie.d.mts +4 -5
- package/dist/lib/cookie.d.ts +4 -5
- package/dist/lib/cookie.js +11 -9
- package/dist/lib/cookie.js.map +1 -1
- package/dist/lib/stack-app.d.mts +4 -0
- package/dist/lib/stack-app.d.ts +4 -0
- package/dist/lib/stack-app.js +15 -4
- package/dist/lib/stack-app.js.map +1 -1
- package/dist/utils/constants.d.mts +1 -1
- package/dist/utils/constants.d.ts +1 -1
- package/dist/utils/constants.js +1 -1
- package/dist/utils/constants.js.map +1 -1
- package/package.json +9 -6
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// src/components/profile-image-editor.tsx
|
|
2
|
+
import { fileToBase64 } from "@stackframe/stack-shared/dist/utils/base64";
|
|
3
|
+
import { Button, Slider, Typography } from "@stackframe/stack-ui";
|
|
4
|
+
import imageCompression from "browser-image-compression";
|
|
5
|
+
import { Upload } from "lucide-react";
|
|
6
|
+
import { useRef, useState } from "react";
|
|
7
|
+
import AvatarEditor from "react-avatar-editor";
|
|
8
|
+
import { UserAvatar } from "./elements/user-avatar";
|
|
9
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
async function checkImageUrl(url) {
|
|
11
|
+
try {
|
|
12
|
+
const res = await fetch(url, { method: "HEAD" });
|
|
13
|
+
const buff = await res.blob();
|
|
14
|
+
return buff.type.startsWith("image/");
|
|
15
|
+
} catch (e) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function ProfileImageEditor(props) {
|
|
20
|
+
const cropRef = useRef(null);
|
|
21
|
+
const [slideValue, setSlideValue] = useState(1);
|
|
22
|
+
const [rawUrl, setRawUrl] = useState(null);
|
|
23
|
+
const [error, setError] = useState(null);
|
|
24
|
+
function reset() {
|
|
25
|
+
setSlideValue(1);
|
|
26
|
+
setRawUrl(null);
|
|
27
|
+
setError(null);
|
|
28
|
+
}
|
|
29
|
+
function upload() {
|
|
30
|
+
const input = document.createElement("input");
|
|
31
|
+
input.type = "file";
|
|
32
|
+
input.onchange = (e) => {
|
|
33
|
+
const file = e.target.files?.[0];
|
|
34
|
+
if (!file) return;
|
|
35
|
+
fileToBase64(file).then(async (rawUrl2) => {
|
|
36
|
+
if (await checkImageUrl(rawUrl2)) {
|
|
37
|
+
setRawUrl(rawUrl2);
|
|
38
|
+
setError(null);
|
|
39
|
+
} else {
|
|
40
|
+
setError("Invalid image");
|
|
41
|
+
}
|
|
42
|
+
}).then(() => input.remove()).catch(console.error);
|
|
43
|
+
};
|
|
44
|
+
input.click();
|
|
45
|
+
}
|
|
46
|
+
if (!rawUrl) {
|
|
47
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
48
|
+
/* @__PURE__ */ jsxs("div", { className: "cursor-pointer relative", onClick: upload, children: [
|
|
49
|
+
/* @__PURE__ */ jsx(
|
|
50
|
+
UserAvatar,
|
|
51
|
+
{
|
|
52
|
+
size: 100,
|
|
53
|
+
user: props.user,
|
|
54
|
+
border: true
|
|
55
|
+
}
|
|
56
|
+
),
|
|
57
|
+
/* @__PURE__ */ jsx("div", { className: "absolute top-0 left-0 h-[100px] w-[100px] bg-gray-500/20 backdrop-blur-sm items-center justify-center rounded-full flex opacity-0 hover:opacity-100 transition-opacity", children: /* @__PURE__ */ jsx("div", { className: "bg-background p-2 rounded-full", children: /* @__PURE__ */ jsx(Upload, { className: "h-5 w-5" }) }) })
|
|
58
|
+
] }),
|
|
59
|
+
error && /* @__PURE__ */ jsx(Typography, { variant: "destructive", type: "label", children: error })
|
|
60
|
+
] });
|
|
61
|
+
}
|
|
62
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-4", children: [
|
|
63
|
+
/* @__PURE__ */ jsx(
|
|
64
|
+
AvatarEditor,
|
|
65
|
+
{
|
|
66
|
+
ref: cropRef,
|
|
67
|
+
image: rawUrl || props.user.profileImageUrl || "",
|
|
68
|
+
borderRadius: 1e3,
|
|
69
|
+
color: [0, 0, 0, 0.72],
|
|
70
|
+
scale: slideValue,
|
|
71
|
+
rotate: 0,
|
|
72
|
+
border: 20,
|
|
73
|
+
className: "border"
|
|
74
|
+
}
|
|
75
|
+
),
|
|
76
|
+
/* @__PURE__ */ jsx(
|
|
77
|
+
Slider,
|
|
78
|
+
{
|
|
79
|
+
min: 1,
|
|
80
|
+
max: 5,
|
|
81
|
+
step: 0.1,
|
|
82
|
+
defaultValue: [slideValue],
|
|
83
|
+
value: [slideValue],
|
|
84
|
+
onValueChange: (v) => setSlideValue(v[0])
|
|
85
|
+
}
|
|
86
|
+
),
|
|
87
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-row gap-2", children: [
|
|
88
|
+
/* @__PURE__ */ jsx(
|
|
89
|
+
Button,
|
|
90
|
+
{
|
|
91
|
+
onClick: async () => {
|
|
92
|
+
if (cropRef.current && rawUrl) {
|
|
93
|
+
const croppedUrl = cropRef.current.getImage().toDataURL("image/jpeg");
|
|
94
|
+
const compressedFile = await imageCompression(
|
|
95
|
+
await imageCompression.getFilefromDataUrl(croppedUrl, "profile-image"),
|
|
96
|
+
{
|
|
97
|
+
maxSizeMB: 0.1,
|
|
98
|
+
fileType: "image/jpeg"
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
const compressedUrl = await imageCompression.getDataUrlFromFile(compressedFile);
|
|
102
|
+
await props.onProfileImageUrlChange(compressedUrl);
|
|
103
|
+
reset();
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
children: "Save"
|
|
107
|
+
}
|
|
108
|
+
),
|
|
109
|
+
/* @__PURE__ */ jsx(
|
|
110
|
+
Button,
|
|
111
|
+
{
|
|
112
|
+
variant: "secondary",
|
|
113
|
+
onClick: reset,
|
|
114
|
+
children: "Cancel"
|
|
115
|
+
}
|
|
116
|
+
)
|
|
117
|
+
] })
|
|
118
|
+
] });
|
|
119
|
+
}
|
|
120
|
+
export {
|
|
121
|
+
ProfileImageEditor,
|
|
122
|
+
checkImageUrl
|
|
123
|
+
};
|
|
124
|
+
//# sourceMappingURL=profile-image-editor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/profile-image-editor.tsx"],"sourcesContent":["import { fileToBase64 } from '@stackframe/stack-shared/dist/utils/base64';\nimport { Button, Slider, Typography } from '@stackframe/stack-ui';\nimport imageCompression from 'browser-image-compression';\nimport { Upload } from 'lucide-react';\nimport { ComponentProps, useRef, useState } from 'react';\nimport AvatarEditor from 'react-avatar-editor';\nimport { UserAvatar } from './elements/user-avatar';\n\nexport async function checkImageUrl(url: string){\n try {\n const res = await fetch(url, { method: 'HEAD' });\n const buff = await res.blob();\n return buff.type.startsWith('image/');\n } catch (e) {\n return false;\n }\n}\n\nexport function ProfileImageEditor(props: {\n user: NonNullable<ComponentProps<typeof UserAvatar>['user']>,\n onProfileImageUrlChange: (profileImageUrl: string | null) => void | Promise<void>,\n}) {\n const cropRef = useRef<AvatarEditor>(null);\n const [slideValue, setSlideValue] = useState(1);\n const [rawUrl, setRawUrl] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n function reset() {\n setSlideValue(1);\n setRawUrl(null);\n setError(null);\n }\n\n function upload() {\n const input = document.createElement('input');\n input.type = 'file';\n input.onchange = (e) => {\n const file = (e.target as HTMLInputElement).files?.[0];\n if (!file) return;\n fileToBase64(file)\n .then(async (rawUrl) => {\n if (await checkImageUrl(rawUrl)) {\n setRawUrl(rawUrl);\n setError(null);\n } else {\n setError('Invalid image');\n }\n })\n .then(() => input.remove())\n .catch(console.error);\n };\n input.click();\n }\n\n if (!rawUrl) {\n return <div className='flex flex-col'>\n <div className='cursor-pointer relative' onClick={upload}>\n <UserAvatar\n size={100}\n user={props.user}\n border\n />\n <div className='absolute top-0 left-0 h-[100px] w-[100px] bg-gray-500/20 backdrop-blur-sm items-center justify-center rounded-full flex opacity-0 hover:opacity-100 transition-opacity'>\n <div className='bg-background p-2 rounded-full'>\n <Upload className='h-5 w-5' />\n </div>\n </div>\n </div>\n {error && <Typography variant='destructive' type='label'>{error}</Typography>}\n </div>;\n }\n\n return (\n <div className='flex flex-col items-center gap-4'>\n <AvatarEditor\n ref={cropRef}\n image={rawUrl || props.user.profileImageUrl || \"\"}\n borderRadius={1000}\n color={[0, 0, 0, 0.72]}\n scale={slideValue}\n rotate={0}\n border={20}\n className='border'\n />\n <Slider\n min={1}\n max={5}\n step={0.1}\n defaultValue={[slideValue]}\n value={[slideValue]}\n onValueChange={(v) => setSlideValue(v[0])}\n />\n\n <div className='flex flex-row gap-2'>\n <Button\n onClick={async () => {\n if (cropRef.current && rawUrl) {\n const croppedUrl = cropRef.current.getImage().toDataURL('image/jpeg');\n const compressedFile = await imageCompression(\n await imageCompression.getFilefromDataUrl(croppedUrl, 'profile-image'),\n {\n maxSizeMB: 0.1,\n fileType: \"image/jpeg\",\n }\n );\n const compressedUrl = await imageCompression.getDataUrlFromFile(compressedFile);\n await props.onProfileImageUrlChange(compressedUrl);\n reset();\n }\n }}\n >\n Save\n </Button>\n <Button\n variant=\"secondary\"\n onClick={reset}\n >\n Cancel\n </Button>\n </div>\n </div>\n );\n}"],"mappings":"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","names":["rawUrl"]}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
// src/components/team-icon.tsx
|
|
2
|
-
import
|
|
3
|
-
import { Typography } from "@stackframe/stack-ui";
|
|
2
|
+
import { Avatar, AvatarImage, Typography } from "@stackframe/stack-ui";
|
|
4
3
|
import { jsx } from "react/jsx-runtime";
|
|
5
4
|
function TeamIcon(props) {
|
|
6
5
|
if (props.team.profileImageUrl) {
|
|
7
|
-
return /* @__PURE__ */ jsx(
|
|
6
|
+
return /* @__PURE__ */ jsx(Avatar, { className: "w-6 h-6 rounded", children: /* @__PURE__ */ jsx(AvatarImage, { src: props.team.profileImageUrl, alt: props.team.displayName }) });
|
|
8
7
|
} else {
|
|
9
|
-
return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center w-6 h-6 rounded bg-
|
|
8
|
+
return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center w-6 h-6 rounded bg-zinc-200", children: /* @__PURE__ */ jsx(Typography, { className: "text-zinc-800 dark:text-zinc-800", children: props.team.displayName.slice(0, 1).toUpperCase() }) });
|
|
10
9
|
}
|
|
11
10
|
}
|
|
12
11
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/team-icon.tsx"],"sourcesContent":["import Image from \"next/image\";\nimport { Team } from \"..\";\nimport { Typography } from \"@stackframe/stack-ui\";\n\nexport function TeamIcon(props: { team: Team }) {\n if (props.team.profileImageUrl) {\n return (\n <
|
|
1
|
+
{"version":3,"sources":["../../../src/components/team-icon.tsx"],"sourcesContent":["import Image from \"next/image\";\nimport { Team } from \"..\";\nimport { Avatar, AvatarImage, Typography } from \"@stackframe/stack-ui\";\n\nexport function TeamIcon(props: { team: Team }) {\n if (props.team.profileImageUrl) {\n return (\n <Avatar className=\"w-6 h-6 rounded\">\n <AvatarImage src={props.team.profileImageUrl} alt={props.team.displayName} />\n </Avatar>\n );\n } else {\n return (\n <div className=\"flex items-center justify-center w-6 h-6 rounded bg-zinc-200\">\n <Typography className=\"text-zinc-800 dark:text-zinc-800\">{props.team.displayName.slice(0, 1).toUpperCase()}</Typography>\n </div>\n );\n }\n}"],"mappings":";AAEA,SAAS,QAAQ,aAAa,kBAAkB;AAMxC;AAJD,SAAS,SAAS,OAAuB;AAC9C,MAAI,MAAM,KAAK,iBAAiB;AAC9B,WACE,oBAAC,UAAO,WAAU,mBAChB,8BAAC,eAAY,KAAK,MAAM,KAAK,iBAAiB,KAAK,MAAM,KAAK,aAAa,GAC7E;AAAA,EAEJ,OAAO;AACL,WACE,oBAAC,SAAI,WAAU,gEACb,8BAAC,cAAW,WAAU,oCAAoC,gBAAM,KAAK,YAAY,MAAM,GAAG,CAAC,EAAE,YAAY,GAAE,GAC7G;AAAA,EAEJ;AACF;","names":[]}
|
|
@@ -20,14 +20,16 @@ import { MessageCard, useStackApp, useUser } from "..";
|
|
|
20
20
|
import { FormWarningText } from "../components/elements/form-warning";
|
|
21
21
|
import { SidebarLayout } from "../components/elements/sidebar-layout";
|
|
22
22
|
import { UserAvatar } from "../components/elements/user-avatar";
|
|
23
|
+
import { ProfileImageEditor } from "../components/profile-image-editor";
|
|
23
24
|
import { TeamIcon } from "../components/team-icon";
|
|
25
|
+
import { MaybeFullPage } from "../components/elements/maybe-full-page";
|
|
24
26
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
25
27
|
function AccountSettings({ fullPage = false }) {
|
|
26
28
|
const user = useUser({ or: "redirect" });
|
|
27
29
|
const teams = user.useTeams();
|
|
28
30
|
const stackApp = useStackApp();
|
|
29
31
|
const project = stackApp.useProject();
|
|
30
|
-
return /* @__PURE__ */ jsx(
|
|
32
|
+
return /* @__PURE__ */ jsx(MaybeFullPage, { fullPage, children: /* @__PURE__ */ jsx("div", { style: { alignSelf: "stretch", flexGrow: 1 }, children: /* @__PURE__ */ jsx(
|
|
31
33
|
SidebarLayout,
|
|
32
34
|
{
|
|
33
35
|
items: [
|
|
@@ -86,16 +88,30 @@ function AccountSettings({ fullPage = false }) {
|
|
|
86
88
|
title: "Account Settings",
|
|
87
89
|
basePath: stackApp.urls.accountSettings
|
|
88
90
|
}
|
|
89
|
-
);
|
|
91
|
+
) }) });
|
|
90
92
|
}
|
|
91
93
|
function ProfileSection() {
|
|
92
94
|
const user = useUser({ or: "redirect" });
|
|
93
|
-
return /* @__PURE__ */
|
|
94
|
-
/* @__PURE__ */
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
95
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-8", children: [
|
|
96
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-start", children: [
|
|
97
|
+
/* @__PURE__ */ jsx(Label, { className: "mb-2", children: "Profile image" }),
|
|
98
|
+
/* @__PURE__ */ jsx(
|
|
99
|
+
ProfileImageEditor,
|
|
100
|
+
{
|
|
101
|
+
user,
|
|
102
|
+
onProfileImageUrlChange: async (profileImageUrl) => {
|
|
103
|
+
await user.update({ profileImageUrl });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
)
|
|
107
|
+
] }),
|
|
108
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
109
|
+
/* @__PURE__ */ jsx(Label, { children: "Display name" }),
|
|
110
|
+
/* @__PURE__ */ jsx(EditableText, { value: user.displayName || "", onSave: async (newDisplayName) => {
|
|
111
|
+
await user.update({ displayName: newDisplayName });
|
|
112
|
+
} })
|
|
113
|
+
] })
|
|
114
|
+
] });
|
|
99
115
|
}
|
|
100
116
|
function EmailVerificationSection() {
|
|
101
117
|
const user = useUser({ or: "redirect" });
|
|
@@ -314,7 +330,6 @@ function SignOutSection() {
|
|
|
314
330
|
) }) });
|
|
315
331
|
}
|
|
316
332
|
function UserSettings(props) {
|
|
317
|
-
const app = useStackApp();
|
|
318
333
|
const user = useUser({ or: "redirect" });
|
|
319
334
|
const [leaving, setLeaving] = useState(false);
|
|
320
335
|
return /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: /* @__PURE__ */ jsx("div", { children: !leaving ? /* @__PURE__ */ jsx(
|
|
@@ -341,16 +356,30 @@ function ManagementSettings(props) {
|
|
|
341
356
|
if (!updateTeamPermission) {
|
|
342
357
|
return null;
|
|
343
358
|
}
|
|
344
|
-
return /* @__PURE__ */
|
|
345
|
-
/* @__PURE__ */
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
359
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
360
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
361
|
+
/* @__PURE__ */ jsx(Label, { children: "Team display name" }),
|
|
362
|
+
/* @__PURE__ */ jsx(
|
|
363
|
+
ProfileImageEditor,
|
|
364
|
+
{
|
|
365
|
+
user: props.team,
|
|
366
|
+
onProfileImageUrlChange: async (profileImageUrl) => {
|
|
367
|
+
await props.team.update({ profileImageUrl });
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
)
|
|
371
|
+
] }),
|
|
372
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
373
|
+
/* @__PURE__ */ jsx(Label, { children: "Team display name" }),
|
|
374
|
+
/* @__PURE__ */ jsx(
|
|
375
|
+
EditableText,
|
|
376
|
+
{
|
|
377
|
+
value: props.team.displayName,
|
|
378
|
+
onSave: async (newDisplayName) => await props.team.update({ displayName: newDisplayName })
|
|
379
|
+
}
|
|
380
|
+
)
|
|
381
|
+
] })
|
|
382
|
+
] });
|
|
354
383
|
}
|
|
355
384
|
function ProfileSettings(props) {
|
|
356
385
|
const user = useUser({ or: "redirect" });
|
|
@@ -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 } 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 { MaybeFullPage } from \"../components/elements/maybe-full-page\";\nimport { SidebarLayout } from '../components/elements/sidebar-layout';\nimport { UserAvatar } from '../components/elements/user-avatar';\nimport { TeamIcon } from '../components/team-icon';\n\n\nexport function AccountSettings({ fullPage=false }: { fullPage?: boolean }) {\n const user = useUser({ or: 'redirect' });\n const teams = user.useTeams();\n const stackApp = useStackApp();\n const project = stackApp.useProject();\n\n return (\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 ...(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 );\n}\n\nfunction ProfileSection() {\n const user = useUser({ or: 'redirect' });\n\n return (\n <div>\n <div>\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 app = useStackApp();\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>\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}"],"mappings":";;;AAEA,SAAS,mBAAmB;AAC5B,SAAS,wBAAwB;AACjC,SAAS,wBAAwB;AACjC,SAAS,WAAW,iBAAiB;AACrC,SAAS,4BAA4B;AACrC,SAAS,gBAAgB;AACzB,SAAS,mBAAmB,kCAAkC;AAC9D,SAAS,QAAQ,cAAc,OAAO,OAAO,eAAe,eAAe,OAAO,WAAW,WAAW,WAAW,aAAa,UAAU,kBAAkB;AAC5J,SAAS,YAAY,SAAS,QAAQ,mBAAmB;AACzD,SAAS,gBAAgB,wBAAwB;AACjD,YAAY,YAAY;AACxB,SAAS,WAAW,gBAAgB;AACpC,SAAS,eAAe;AACxB,YAAY,SAAS;AACrB,SAAsB,aAA4B,aAAa,eAAe;AAC9E,SAAS,uBAAuB;AAEhC,SAAS,qBAAqB;AAC9B,SAAS,kBAAkB;AAC3B,SAAS,gBAAgB;AAiBN,SAuFT,UAvFS,KAQP,YARO;AAdZ,SAAS,gBAAgB,EAAE,WAAS,MAAM,GAA2B;AAC1E,QAAM,OAAO,QAAQ,EAAE,IAAI,WAAW,CAAC;AACvC,QAAM,QAAQ,KAAK,SAAS;AAC5B,QAAM,WAAW,YAAY;AAC7B,QAAM,UAAU,SAAS,WAAW;AAEpC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAQ;AAAA,QACN;AAAA,UACE,OAAO;AAAA,UACP,MAAM;AAAA,UACN,SAAS;AAAA,UACT,MAAM;AAAA,UACN,SAAS,oBAAC,kBAAc;AAAA,QAC1B;AAAA,QACA;AAAA,UACE,OAAO;AAAA,UACP,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS;AAAA,UACT,SACE,qBAAC,SAAI,WAAU,uBACb;AAAA,gCAAC,4BAAyB;AAAA,YAC1B,oBAAC,mBAAgB;AAAA,YACjB,oBAAC,cAAW;AAAA,aACd;AAAA,QAEJ;AAAA,QACA;AAAA,UACE,OAAO;AAAA,UACP,SAAS;AAAA,UACT,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS,oBAAC,kBAAe;AAAA,QAC3B;AAAA,QACA,GAAI,MAAM,SAAS,KAAK,QAAQ,OAAO,4BAA6B,CAAC;AAAA,UACnE,OAAO;AAAA,UACP,MAAM;AAAA,QACR,CAAC,IAAa,CAAC;AAAA,QACf,GAAG,MAAM,IAAI,WAAS;AAAA,UACpB,OAAO,qBAAC,SAAI,WAAU,2BACpB;AAAA,gCAAC,YAAS,MAAW;AAAA,YACpB,KAAK;AAAA,aACR;AAAA,UACA,MAAM;AAAA,UACN,SAAS,UAAU,KAAK,EAAE;AAAA,UAC1B,SACE,qBAAC,SAAI,WAAU,uBACb;AAAA,gCAAC,mBAAgB,MAAW;AAAA,YAC5B,oBAAC,sBAAmB,MAAW;AAAA,YAC/B,oBAAC,oBAAiB,MAAW;AAAA,YAC7B,oBAAC,mBAAgB,MAAW;AAAA,YAC5B,oBAAC,gBAAa,MAAW;AAAA,aAC3B;AAAA,QAEJ,EAAW;AAAA,QACX,GAAG,QAAQ,OAAO,4BAA4B,CAAC;AAAA,UAC7C,OAAO;AAAA,UACP,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS;AAAA,UACT,SAAS,oBAAC,gBAAa;AAAA,QACzB,CAAC,IAAa,CAAC;AAAA,MACjB,EAAY,OAAO,CAAC,MAAM,EAAE,SAAS,aAAc,EAAU,OAAQ;AAAA,MACrE,OAAM;AAAA,MACN,UAAU,SAAS,KAAK;AAAA;AAAA,EAC1B;AAEJ;AAEA,SAAS,iBAAiB;AACxB,QAAM,OAAO,QAAQ,EAAE,IAAI,WAAW,CAAC;AAEvC,SACE,oBAAC,SACC,+BAAC,SACC;AAAA,wBAAC,SAAM,0BAAY;AAAA,IACnB,oBAAC,gBAAa,OAAO,KAAK,eAAe,IAAI,QAAQ,OAAO,mBAAmB;AAC7E,YAAM,KAAK,OAAO,EAAE,aAAa,eAAe,CAAC;AAAA,IACnD,GAAE;AAAA,KACJ,GACF;AAEJ;AAEA,SAAS,2BAA2B;AAClC,QAAM,OAAO,QAAQ,EAAE,IAAI,WAAW,CAAC;AACvC,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAEhD,MAAI,CAAC,KAAK,cAAc;AACtB,WAAO;AAAA,EACT;AAEA,SACE,gCACE,+BAAC,SACC;AAAA,wBAAC,SAAM,gCAAkB;AAAA,IACxB,KAAK,uBACJ,oBAAC,cAAW,SAAQ,WAAU,2CAA6B,IAE3D,iCACE;AAAA,0BAAC,cAAW,SAAQ,eAAc,+CAAiC;AAAA,MACnE,oBAAC,SAAI,WAAU,aACb;AAAA,QAAC;AAAA;AAAA,UACC,UAAU;AAAA,UACV,SAAS,YAAY;AACnB,kBAAM,KAAK,sBAAsB;AACjC,yBAAa,IAAI;AAAA,UACnB;AAAA,UAEC,sBAAY,gBAAgB;AAAA;AAAA,MAC/B,GACF;AAAA,OACF;AAAA,KAGJ,GACF;AAEJ;AAEA,IAAM,iBAAiB,UAAU;AAAA,EAC/B,aAAa,UAAU,EAAE,SAAS,gCAAgC;AAAA,EAClE,aAAa,UAAU,EAAE,SAAS,4BAA4B,EAAE,KAAK;AAAA,IACnE,MAAM;AAAA,IACN,MAAM,CAAC,OAAO,QAAQ;AACpB,YAAM,QAAQ,iBAAiB,KAAK;AACpC,UAAI,OAAO;AACT,eAAO,IAAI,YAAY,EAAE,SAAS,MAAM,QAAQ,CAAC;AAAA,MACnD,OAAO;AACL,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF,CAAC;AAAA,EACD,mBAAmB,UAAU,EAAE,SAAS,EAAE,MAAM,CAAK,QAAI,aAAa,GAAG,IAAI,IAAI,GAAG,wBAAwB,EAAE,SAAS,6BAA6B;AACtJ,CAAC;AAED,SAAS,kBAAkB;AACzB,QAAM,OAAO,QAAQ,EAAE,IAAI,QAAQ,CAAC;AACpC,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,SAAS,KAAK;AAC9D,QAAM,EAAE,UAAU,cAAc,UAAU,WAAW,EAAE,OAAO,GAAG,aAAa,MAAM,IAAI,QAAQ;AAAA,IAC9F,UAAU,YAAY,cAAc;AAAA,EACtC,CAAC;AACD,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,KAAK;AACtD,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAE5C,QAAM,WAAW,OAAO,SAA+C;AACrE,eAAW,IAAI;AACf,QAAI;AACF,YAAM,EAAE,aAAa,YAAY,IAAI;AACrC,YAAM,QAAQ,MAAM,KAAK,eAAe,EAAE,aAAa,YAAY,CAAC;AACpE,UAAI,OAAO;AACT,iBAAS,eAAe,EAAE,MAAM,UAAU,SAAS,qBAAqB,CAAC;AAAA,MAC3E,OAAO;AACL,cAAM;AACN,wBAAgB,IAAI;AAAA,MACtB;AAAA,IACF,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF;AAEA,QAAM,mBAAmB,SAAS,aAAa;AAC/C,QAAM,yBAAyB,SAAS,mBAAmB;AAE3D,MAAI,CAAC,KAAK,aAAa;AACrB,WAAO;AAAA,EACT;AAEA,SACE,qBAAC,SACC;AAAA,wBAAC,SAAM,6BAAe;AAAA,IACtB,oBAAC,SAEG,yBACE,oBAAC,cAAW,SAAQ,WAAU,4CAA8B,IAC5D,CAAC,mBACC;AAAA,MAAC;AAAA;AAAA,QACC,SAAQ;AAAA,QACR,SAAS,YAAY;AACnB,8BAAoB,IAAI;AAAA,QAC1B;AAAA,QACD;AAAA;AAAA,IAED,IACA;AAAA,MAAC;AAAA;AAAA,QACC,UAAU,OAAK,2BAA2B,aAAa,QAAQ,EAAE,CAAC,CAAC;AAAA,QACnE,YAAU;AAAA,QAEV;AAAA,8BAAC,SAAM,SAAQ,gBAAe,WAAU,QAAO,0BAAY;AAAA,UAC3D;AAAA,YAAC;AAAA;AAAA,cACC,IAAG;AAAA,cACH,MAAK;AAAA,cACJ,GAAG,SAAS,aAAa;AAAA;AAAA,UAC5B;AAAA,UACA,oBAAC,mBAAgB,MAAM,OAAO,aAAa,SAAS,SAAS,GAAG;AAAA,UAEhE,oBAAC,SAAM,SAAQ,gBAAe,WAAU,aAAY,sBAAQ;AAAA,UAC5D;AAAA,YAAC;AAAA;AAAA,cACC,IAAG;AAAA,cACF,GAAG;AAAA,cACJ,UAAU,CAAC,MAAM;AACf,4BAAY,aAAa;AACzB,4BAAY,mBAAmB;AAC/B,kCAAkB,iBAAiB,SAAS,CAAC,CAAC;AAAA,cAChD;AAAA;AAAA,UACF;AAAA,UACA,oBAAC,mBAAgB,MAAM,OAAO,aAAa,SAAS,SAAS,GAAG;AAAA,UAEhE,oBAAC,SAAM,SAAQ,mBAAkB,WAAU,aAAY,6BAAe;AAAA,UACtE;AAAA,YAAC;AAAA;AAAA,cACC,IAAG;AAAA,cACF,GAAG;AAAA,cACJ,UAAU,CAAC,MAAM;AACf,4BAAY,aAAa;AACzB,4BAAY,mBAAmB;AAC/B,kCAAkB,uBAAuB,SAAS,CAAC,CAAC;AAAA,cACtD;AAAA;AAAA,UACF;AAAA,UACA,oBAAC,mBAAgB,MAAM,OAAO,mBAAmB,SAAS,SAAS,GAAG;AAAA,UAEtE,oBAAC,UAAO,MAAK,UAAS,WAAU,QAAO,SAAkB,6BAEzD;AAAA;AAAA;AAAA,IACF,GAER;AAAA,KACF;AAEJ;AAEA,SAAS,aAAa;AACpB,QAAM,UAAU,YAAY,EAAE,WAAW;AACzC,QAAM,OAAO,QAAQ,EAAE,IAAI,QAAQ,CAAC;AACpC,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAA4B,IAAI;AAC9E,QAAM,CAAC,WAAW,YAAY,IAAI,SAAwB,IAAI;AAC9D,QAAM,CAAC,SAAS,UAAU,IAAI,SAAiB,EAAE;AACjD,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,KAAK;AACtD,QAAM,YAAY,KAAK;AAEvB,QAAM,CAAC,cAAc,SAAS,IAAI,iBAAiB,YAAY;AAC7D,UAAM,KAAK,OAAO;AAAA,MAChB,uBAAuB;AAAA,IACzB,CAAC;AACD,uBAAmB,IAAI;AACvB,iBAAa,IAAI;AACjB,eAAW,EAAE;AAAA,EACf,GAAG,CAAC,iBAAiB,IAAI,CAAC;AAE1B,YAAU,MAAM;AACd,oBAAgB,KAAK;AACrB,+BAA2B,YAAY;AACrC,UAAI,mBAAmB,MAAM,IAAI,eAAe,EAAE,OAAO,SAAS,eAAe,GAAG;AAClF,cAAM,aAAa;AAAA,MACrB;AACA,sBAAgB,IAAI;AAAA,IACtB,CAAC;AAAA,EACH,GAAG,CAAC,SAAS,iBAAiB,YAAY,CAAC;AAE3C,SACE,oBAAC,SACC,+BAAC,SACC;AAAA,wBAAC,SAAM,yCAA2B;AAAA,IAElC,qBAAC,SACE;AAAA,kBACC,oBAAC,cAAW,SAAQ,WAAU,+DAAiD,IAE/E,kBACE,qBAAC,SAAI,WAAU,oCACb;AAAA,4BAAC,cAAW,4DAA8C;AAAA,QAC1D,oBAAC,SAAI,OAAO,KAAK,QAAQ,KAAK,KAAK,aAAa,SAAS,iCAAiC,GAAG,KAAI,4CAA2C;AAAA,QAC5I,oBAAC,cAAW,kDAAoC;AAAA,QAChD;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,YACP,UAAU,CAAC,MAAM;AACnB,8BAAgB,KAAK;AACrB,yBAAW,EAAE,OAAO,KAAK;AAAA,YACvB;AAAA,YACA,aAAY;AAAA,YACZ,WAAW;AAAA,YACX,UAAU;AAAA;AAAA,QACZ;AAAA,QACC,gBAAgB,QAAQ,WAAW,KAClC,oBAAC,cAAW,SAAQ,eAAc,+CAAiC;AAAA,SAEvE,IAEA,oBAAC,cAAW,SAAQ,eAAc,gEAAkD;AAAA,MAIxF;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,SAAS,YAAY,cAAc;AAAA,UACnC,SAAS,YAAY;AACnB,gBAAI,WAAW;AACb,oBAAM,KAAK,OAAO;AAAA,gBAChB,uBAAuB;AAAA,cACzB,CAAC;AAAA,YACH,WAAW,CAAC,iBAAiB;AAC3B,oBAAM,SAAS,qBAAqB,IAAI,WAAW,EAAE,CAAC;AACtD,2BAAa,MAAM,mBAAmB,SAAS,MAAM,MAAM,CAAC;AAC5D,iCAAmB,MAAM;AAAA,YAC3B,OAAO;AACL,iCAAmB,IAAI;AACvB,2BAAa,IAAI;AACjB,yBAAW,EAAE;AAAA,YACf;AAAA,UACF;AAAA,UAEC,sBAAY,YAAa,kBAAkB,WAAW;AAAA;AAAA,MACzD;AAAA,OACF;AAAA,KACF,GACF;AAEJ;AAEA,eAAe,mBAAmB,SAAkB,MAAmB,QAAoB;AACzF,QAAM,MAAM,iBAAiB,QAAQ,aAAa,KAAK,gBAAgB,KAAK,IAAI,MAAM;AACtF,SAAO,MAAa,iBAAU,GAAG;AACnC;AAEA,SAAS,iBAAiB;AACxB,QAAM,OAAO,QAAQ,EAAE,IAAI,QAAQ,CAAC;AACpC,SACE,oBAAC,SAAI,WAAU,uBACb,8BAAC,SACC;AAAA,IAAC;AAAA;AAAA,MACC,SAAQ;AAAA,MACR,SAAS,MAAM,KAAK,QAAQ;AAAA,MAC7B;AAAA;AAAA,EAED,GACF,GACF;AAEJ;AAEA,SAAS,aAAa,OAAuB;AAC3C,QAAM,MAAM,YAAY;AACxB,QAAM,OAAO,QAAQ,EAAE,IAAI,WAAW,CAAC;AACvC,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAE5C,SACE,oBAAC,SAAI,WAAU,uBACb,8BAAC,SACG,WAAC,UACD;AAAA,IAAC;AAAA;AAAA,MACC,SAAQ;AAAA,MACR,SAAS,YAAY,WAAW,IAAI;AAAA,MACrC;AAAA;AAAA,EAED,IACA,qBAAC,SAAI,WAAU,IACb;AAAA,wBAAC,cAAW,SAAQ,eAAc,sDAAwC;AAAA,IAC1E,qBAAC,SAAI,WAAU,cACb;AAAA,0BAAC,UAAO,SAAQ,eAAc,SAAS,YAAY;AACjD,cAAM,KAAK,UAAU,MAAM,IAAI;AAC/B,eAAO,SAAS,OAAO;AAAA,MACzB,GAAG,mBAEH;AAAA,MACA,oBAAC,UAAO,SAAQ,aAAY,SAAS,MAAM,WAAW,KAAK,GAAG,oBAE9D;AAAA,OACF;AAAA,KACF,GACJ,GACF;AAEJ;AAEA,SAAS,mBAAmB,OAAuB;AACjD,QAAM,OAAO,QAAQ,EAAE,IAAI,WAAW,CAAC;AACvC,QAAM,uBAAuB,KAAK,cAAc,MAAM,MAAM,cAAc;AAE1E,MAAI,CAAC,sBAAsB;AACzB,WAAO;AAAA,EACT;AAEA,SACE,gCACE,+BAAC,SACC;AAAA,wBAAC,SAAM,+BAAiB;AAAA,IACxB;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,MAAM,KAAK;AAAA,QAClB,QAAQ,OAAO,mBAAmB,MAAM,MAAM,KAAK,OAAO,EAAE,aAAa,eAAe,CAAC;AAAA;AAAA,IAC3F;AAAA,KACF,GACF;AAEJ;AAEA,SAAS,gBAAgB,OAAuB;AAC9C,QAAM,OAAO,QAAQ,EAAE,IAAI,WAAW,CAAC;AACvC,QAAM,UAAU,KAAK,eAAe,MAAM,IAAI;AAE9C,SACE,oBAAC,SAAI,WAAU,iBACb,+BAAC,SAAI,WAAU,iBACb;AAAA,yBAAC,SAAM,WAAU,cAAa;AAAA;AAAA,MAAkB,oBAAC,iBAAc,SAAQ,iEAAgE,MAAK,QAAM;AAAA,OAAE;AAAA,IACpJ;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,QAAQ,eAAe;AAAA,QAC9B,QAAQ,OAAO,mBAAmB;AAChC,gBAAM,QAAQ,OAAO,EAAE,aAAa,eAAe,CAAC;AAAA,QACtD;AAAA;AAAA,IAAE;AAAA,KACN,GACF;AAEJ;AAEA,IAAM,mBAAmB,UAAU;AAAA,EACjC,OAAO,UAAU,EAAE,MAAM,EAAE,SAAS,+BAA+B;AACrE,CAAC;AAED,SAAS,iBAAiB,OAAuB;AAC/C,QAAM,OAAO,QAAQ,EAAE,IAAI,WAAW,CAAC;AACvC,QAAM,yBAAyB,KAAK,cAAc,MAAM,MAAM,iBAAiB;AAE/E,MAAI,CAAC,wBAAwB;AAC3B,WAAO;AAAA,EACT;AAEA,QAAM,EAAE,UAAU,cAAc,WAAW,EAAE,OAAO,GAAG,MAAM,IAAI,QAAQ;AAAA,IACvE,UAAU,YAAY,gBAAgB;AAAA,EACxC,CAAC;AACD,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAC5C,QAAM,CAAC,cAAc,eAAe,IAAI,SAAwB,IAAI;AAEpE,QAAM,WAAW,OAAO,SAAiD;AACvE,eAAW,IAAI;AAEf,QAAI;AACF,YAAM,MAAM,KAAK,WAAW,EAAE,OAAO,KAAK,MAAM,CAAC;AACjD,sBAAgB,KAAK,KAAK;AAAA,IAC5B,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF;AAEA,YAAU,MAAM;AACd,oBAAgB,IAAI;AAAA,EACtB,GAAG,CAAC,MAAM,OAAO,CAAC,CAAC;AAEnB,SACE,qBAAC,SACC;AAAA,wBAAC,SAAM,mCAAqB;AAAA,IAC5B;AAAA,MAAC;AAAA;AAAA,QACC,UAAU,OAAK,2BAA2B,aAAa,QAAQ,EAAE,CAAC,CAAC;AAAA,QACnE,YAAU;AAAA,QAEV;AAAA,+BAAC,SAAI,WAAU,mCACb;AAAA,gCAAC,SACC;AAAA,cAAC;AAAA;AAAA,gBACC,aAAY;AAAA,gBACX,GAAG,SAAS,OAAO;AAAA;AAAA,YACtB,GACF;AAAA,YACA,oBAAC,UAAO,MAAK,UAAS,SAAkB,yBAExC;AAAA,aACF;AAAA,UACA,oBAAC,mBAAgB,MAAM,OAAO,OAAO,SAAS,SAAS,GAAG;AAAA,UACzD,gBAAgB,qBAAC,cAAW,MAAK,SAAQ,SAAQ,aAAY;AAAA;AAAA,YAAS;AAAA,aAAa;AAAA;AAAA;AAAA,IACtF;AAAA,KACF;AAEJ;AAGA,SAAS,gBAAgB,OAAuB;AAC9C,QAAM,OAAO,QAAQ,EAAE,IAAI,WAAW,CAAC;AACvC,QAAM,uBAAuB,KAAK,cAAc,MAAM,MAAM,eAAe;AAC3E,QAAM,yBAAyB,KAAK,cAAc,MAAM,MAAM,iBAAiB;AAE/E,MAAI,CAAC,wBAAwB,CAAC,wBAAwB;AACpD,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,MAAM,KAAK,SAAS;AAElC,MAAI,CAAC,sBAAsB;AACzB,WAAO;AAAA,EACT;AAEA,SACE,qBAAC,SACC;AAAA,wBAAC,SAAM,qBAAO;AAAA,IACd,qBAAC,SACC;AAAA,0BAAC,eACC,+BAAC,YACC;AAAA,4BAAC,aAAU,WAAU,aAAY,kBAAI;AAAA,QACrC,oBAAC,aAAU,WAAU,aAAY,kBAAI;AAAA,SACvC,GACF;AAAA,MACA,oBAAC,aACE,gBAAM,IAAI,CAAC,EAAE,IAAI,YAAY,GAAG,MAC/B,qBAAC,YACC;AAAA,4BAAC,aACC,8BAAC,cAAW,MAAM,aAAY,GAChC;AAAA,QACA,oBAAC,aACC,8BAAC,cAAY,sBAAY,aAAY,GACvC;AAAA,WANa,EAOf,CACD,GACH;AAAA,OACF;AAAA,KACF;AAEJ;AAEA,IAAM,qBAAqB,UAAU;AAAA,EACnC,aAAa,UAAU,EAAE,SAAS,0BAA0B;AAC9D,CAAC;AAEM,SAAS,eAAe;AAC7B,QAAM,EAAE,UAAU,cAAc,WAAW,EAAE,OAAO,EAAE,IAAI,QAAQ;AAAA,IAChE,UAAU,YAAY,kBAAkB;AAAA,EAC1C,CAAC;AACD,QAAM,MAAM,YAAY;AACxB,QAAM,UAAU,IAAI,WAAW;AAC/B,QAAM,OAAO,QAAQ,EAAE,IAAI,WAAW,CAAC;AACvC,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAE5C,MAAI,CAAC,QAAQ,OAAO,2BAA2B;AAC7C,WAAO,oBAAC,eAAY,OAAM,gCAA+B;AAAA,EAC3D;AAEA,QAAM,WAAW,OAAO,SAAmD;AACzE,eAAW,IAAI;AAEf,QAAI;AACF,YAAM,OAAO,MAAM,KAAK,WAAW,EAAE,aAAa,KAAK,YAAY,CAAC;AAAA,IACtE,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF;AAEA,SACE,oBAAC,SAAI,WAAU,2CACb,8BAAC,SAAI,WAAU,QACb;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,UAAU,OAAK,2BAA2B,aAAa,QAAQ,EAAE,CAAC,CAAC;AAAA,MACnE,YAAU;AAAA,MAEV,+BAAC,SAAI,WAAU,wBACb;AAAA,6BAAC,SACC;AAAA,8BAAC,SAAM,SAAQ,SAAQ,WAAU,QAAO,0BAAY;AAAA,UACpD;AAAA,YAAC;AAAA;AAAA,cACC,IAAG;AAAA,cACH,MAAK;AAAA,cACJ,GAAG,SAAS,aAAa;AAAA;AAAA,UAC5B;AAAA,WACF;AAAA,QACA,oBAAC,mBAAgB,MAAM,OAAO,aAAa,SAAS,SAAS,GAAG;AAAA,QAEhE,oBAAC,UAAO,MAAK,UAAS,WAAU,QAAO,SAAkB,oBAEzD;AAAA,SACF;AAAA;AAAA,EACF,GACF,GACF;AAEJ;","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 } 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({ fullPage=false }: { fullPage?: boolean }) {\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={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 ...(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":[]}
|
|
@@ -38,7 +38,7 @@ function AuthPage({
|
|
|
38
38
|
return /* @__PURE__ */ jsx(PredefinedMessageCard, { type: "signUpDisabled", fullPage });
|
|
39
39
|
}
|
|
40
40
|
const enableSeparator = (project.config.credentialEnabled || project.config.magicLinkEnabled) && project.config.oauthProviders.length > 0;
|
|
41
|
-
return /* @__PURE__ */ jsx(MaybeFullPage, { fullPage, children: /* @__PURE__ */ jsxs("div", { className: "stack-scope flex flex-col items-stretch", children: [
|
|
41
|
+
return /* @__PURE__ */ jsx(MaybeFullPage, { fullPage, children: /* @__PURE__ */ jsxs("div", { className: "stack-scope flex flex-col items-stretch", style: { width: "380px", padding: fullPage ? "1rem" : 0 }, children: [
|
|
42
42
|
/* @__PURE__ */ jsxs("div", { className: "text-center mb-6", children: [
|
|
43
43
|
/* @__PURE__ */ jsx(Typography, { type: "h2", children: type === "sign-in" ? "Sign in to your account" : "Create a new account" }),
|
|
44
44
|
type === "sign-in" ? project.config.signUpEnabled && /* @__PURE__ */ jsxs(Typography, { children: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components-page/auth-page.tsx"],"sourcesContent":["'use client';\n\nimport { CredentialSignIn } from '../components/credential-sign-in';\nimport { SeparatorWithText } from '../components/elements/separator-with-text';\nimport { OAuthButtonGroup } from '../components/oauth-button-group';\nimport { MaybeFullPage } from '../components/elements/maybe-full-page';\nimport { useUser, useStackApp } from '..';\nimport { PredefinedMessageCard } from '../components/message-cards/predefined-message-card';\nimport { MagicLinkSignIn } from '../components/magic-link-sign-in';\nimport { CredentialSignUp } from '../components/credential-sign-up';\nimport { StyledLink, Tabs, TabsContent, TabsList, TabsTrigger, Typography } from '@stackframe/stack-ui';\nimport { Project } from '../lib/stack-app';\nimport { runAsynchronously } from '@stackframe/stack-shared/dist/utils/promises';\nimport { useEffect } from 'react';\n\nexport function AuthPage({\n fullPage=false,\n type,\n automaticRedirect,\n mockProject,\n}: {\n fullPage?: boolean,\n type: 'sign-in' | 'sign-up',\n automaticRedirect?: boolean,\n mockProject?: {\n config: {\n signUpEnabled: boolean,\n credentialEnabled: boolean,\n magicLinkEnabled: boolean,\n oauthProviders: {\n id: string,\n }[],\n },\n },\n}) {\n const stackApp = useStackApp();\n const user = useUser();\n const projectFromHook = stackApp.useProject();\n const project = mockProject || projectFromHook;\n\n useEffect(() => {\n if (automaticRedirect) {\n if (user && !mockProject) {\n runAsynchronously(type === 'sign-in' ? stackApp.redirectToAfterSignIn() : stackApp.redirectToAfterSignUp());\n }\n }\n }, [user, mockProject, stackApp, automaticRedirect]);\n\n if (user && !mockProject) {\n return <PredefinedMessageCard type='signedIn' fullPage={fullPage} />;\n }\n\n if (type === 'sign-up' && !project.config.signUpEnabled) {\n return <PredefinedMessageCard type='signUpDisabled' fullPage={fullPage} />;\n }\n\n const enableSeparator = (project.config.credentialEnabled || project.config.magicLinkEnabled) && project.config.oauthProviders.length > 0;\n\n return (\n <MaybeFullPage fullPage={fullPage}>\n <div className='stack-scope flex flex-col items-stretch'>\n <div className=\"text-center mb-6\">\n <Typography type='h2'>\n {type === 'sign-in' ? 'Sign in to your account' : 'Create a new account'}\n </Typography>\n {type === 'sign-in' ? (\n project.config.signUpEnabled && (\n <Typography>\n {\"Don't have an account? \"}\n <StyledLink href={stackApp.urls.signUp} onClick={(e) => {\n runAsynchronously(stackApp.redirectToSignUp());\n e.preventDefault();\n }}>\n Sign up\n </StyledLink>\n </Typography>\n )\n ) : (\n <Typography>\n {\"Already have an account? \"}\n <StyledLink href={stackApp.urls.signIn} onClick={(e) => {\n runAsynchronously(stackApp.redirectToSignIn());\n e.preventDefault();\n }}>\n Sign in\n </StyledLink>\n </Typography>\n )}\n </div>\n <OAuthButtonGroup type={type} mockProject={mockProject} />\n {enableSeparator && <SeparatorWithText text={'Or continue with'} />}\n {project.config.credentialEnabled && project.config.magicLinkEnabled ? (\n <Tabs defaultValue='magic-link'>\n <TabsList className='w-full mb-2'>\n <TabsTrigger value='magic-link' className='flex-1'>Magic Link</TabsTrigger>\n <TabsTrigger value='password' className='flex-1'>Password</TabsTrigger>\n </TabsList>\n <TabsContent value='magic-link'>\n <MagicLinkSignIn/>\n </TabsContent>\n <TabsContent value='password'>\n {type === 'sign-up' ? <CredentialSignUp/> : <CredentialSignIn/>}\n </TabsContent>\n </Tabs>\n ) : project.config.credentialEnabled ? (\n type === 'sign-up' ? <CredentialSignUp/> : <CredentialSignIn/>\n ) : project.config.magicLinkEnabled ? (\n <MagicLinkSignIn/>\n ) : null}\n </div>\n </MaybeFullPage>\n );\n}\n"],"mappings":";;;AAEA,SAAS,wBAAwB;AACjC,SAAS,yBAAyB;AAClC,SAAS,wBAAwB;AACjC,SAAS,qBAAqB;AAC9B,SAAS,SAAS,mBAAmB;AACrC,SAAS,6BAA6B;AACtC,SAAS,uBAAuB;AAChC,SAAS,wBAAwB;AACjC,SAAS,YAAY,MAAM,aAAa,UAAU,aAAa,kBAAkB;AAEjF,SAAS,yBAAyB;AAClC,SAAS,iBAAiB;AAoCf,cAkBG,YAlBH;AAlCJ,SAAS,SAAS;AAAA,EACvB,WAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AACF,GAcG;AACD,QAAM,WAAW,YAAY;AAC7B,QAAM,OAAO,QAAQ;AACrB,QAAM,kBAAkB,SAAS,WAAW;AAC5C,QAAM,UAAU,eAAe;AAE/B,YAAU,MAAM;AACd,QAAI,mBAAmB;AACrB,UAAI,QAAQ,CAAC,aAAa;AACxB,0BAAkB,SAAS,YAAY,SAAS,sBAAsB,IAAI,SAAS,sBAAsB,CAAC;AAAA,MAC5G;AAAA,IACF;AAAA,EACF,GAAG,CAAC,MAAM,aAAa,UAAU,iBAAiB,CAAC;AAEnD,MAAI,QAAQ,CAAC,aAAa;AACxB,WAAO,oBAAC,yBAAsB,MAAK,YAAW,UAAoB;AAAA,EACpE;AAEA,MAAI,SAAS,aAAa,CAAC,QAAQ,OAAO,eAAe;AACvD,WAAO,oBAAC,yBAAsB,MAAK,kBAAiB,UAAoB;AAAA,EAC1E;AAEA,QAAM,mBAAmB,QAAQ,OAAO,qBAAqB,QAAQ,OAAO,qBAAqB,QAAQ,OAAO,eAAe,SAAS;AAExI,SACE,oBAAC,iBAAc,UACb,+BAAC,SAAI,WAAU,
|
|
1
|
+
{"version":3,"sources":["../../../src/components-page/auth-page.tsx"],"sourcesContent":["'use client';\n\nimport { CredentialSignIn } from '../components/credential-sign-in';\nimport { SeparatorWithText } from '../components/elements/separator-with-text';\nimport { OAuthButtonGroup } from '../components/oauth-button-group';\nimport { MaybeFullPage } from '../components/elements/maybe-full-page';\nimport { useUser, useStackApp } from '..';\nimport { PredefinedMessageCard } from '../components/message-cards/predefined-message-card';\nimport { MagicLinkSignIn } from '../components/magic-link-sign-in';\nimport { CredentialSignUp } from '../components/credential-sign-up';\nimport { StyledLink, Tabs, TabsContent, TabsList, TabsTrigger, Typography } from '@stackframe/stack-ui';\nimport { Project } from '../lib/stack-app';\nimport { runAsynchronously } from '@stackframe/stack-shared/dist/utils/promises';\nimport { useEffect } from 'react';\n\nexport function AuthPage({\n fullPage=false,\n type,\n automaticRedirect,\n mockProject,\n}: {\n fullPage?: boolean,\n type: 'sign-in' | 'sign-up',\n automaticRedirect?: boolean,\n mockProject?: {\n config: {\n signUpEnabled: boolean,\n credentialEnabled: boolean,\n magicLinkEnabled: boolean,\n oauthProviders: {\n id: string,\n }[],\n },\n },\n}) {\n const stackApp = useStackApp();\n const user = useUser();\n const projectFromHook = stackApp.useProject();\n const project = mockProject || projectFromHook;\n\n useEffect(() => {\n if (automaticRedirect) {\n if (user && !mockProject) {\n runAsynchronously(type === 'sign-in' ? stackApp.redirectToAfterSignIn() : stackApp.redirectToAfterSignUp());\n }\n }\n }, [user, mockProject, stackApp, automaticRedirect]);\n\n if (user && !mockProject) {\n return <PredefinedMessageCard type='signedIn' fullPage={fullPage} />;\n }\n\n if (type === 'sign-up' && !project.config.signUpEnabled) {\n return <PredefinedMessageCard type='signUpDisabled' fullPage={fullPage} />;\n }\n\n const enableSeparator = (project.config.credentialEnabled || project.config.magicLinkEnabled) && project.config.oauthProviders.length > 0;\n\n return (\n <MaybeFullPage fullPage={fullPage}>\n <div className='stack-scope flex flex-col items-stretch' style={{ width: '380px', padding: fullPage ? '1rem' : 0 }}>\n <div className=\"text-center mb-6\">\n <Typography type='h2'>\n {type === 'sign-in' ? 'Sign in to your account' : 'Create a new account'}\n </Typography>\n {type === 'sign-in' ? (\n project.config.signUpEnabled && (\n <Typography>\n {\"Don't have an account? \"}\n <StyledLink href={stackApp.urls.signUp} onClick={(e) => {\n runAsynchronously(stackApp.redirectToSignUp());\n e.preventDefault();\n }}>\n Sign up\n </StyledLink>\n </Typography>\n )\n ) : (\n <Typography>\n {\"Already have an account? \"}\n <StyledLink href={stackApp.urls.signIn} onClick={(e) => {\n runAsynchronously(stackApp.redirectToSignIn());\n e.preventDefault();\n }}>\n Sign in\n </StyledLink>\n </Typography>\n )}\n </div>\n <OAuthButtonGroup type={type} mockProject={mockProject} />\n {enableSeparator && <SeparatorWithText text={'Or continue with'} />}\n {project.config.credentialEnabled && project.config.magicLinkEnabled ? (\n <Tabs defaultValue='magic-link'>\n <TabsList className='w-full mb-2'>\n <TabsTrigger value='magic-link' className='flex-1'>Magic Link</TabsTrigger>\n <TabsTrigger value='password' className='flex-1'>Password</TabsTrigger>\n </TabsList>\n <TabsContent value='magic-link'>\n <MagicLinkSignIn/>\n </TabsContent>\n <TabsContent value='password'>\n {type === 'sign-up' ? <CredentialSignUp/> : <CredentialSignIn/>}\n </TabsContent>\n </Tabs>\n ) : project.config.credentialEnabled ? (\n type === 'sign-up' ? <CredentialSignUp/> : <CredentialSignIn/>\n ) : project.config.magicLinkEnabled ? (\n <MagicLinkSignIn/>\n ) : null}\n </div>\n </MaybeFullPage>\n );\n}\n"],"mappings":";;;AAEA,SAAS,wBAAwB;AACjC,SAAS,yBAAyB;AAClC,SAAS,wBAAwB;AACjC,SAAS,qBAAqB;AAC9B,SAAS,SAAS,mBAAmB;AACrC,SAAS,6BAA6B;AACtC,SAAS,uBAAuB;AAChC,SAAS,wBAAwB;AACjC,SAAS,YAAY,MAAM,aAAa,UAAU,aAAa,kBAAkB;AAEjF,SAAS,yBAAyB;AAClC,SAAS,iBAAiB;AAoCf,cAkBG,YAlBH;AAlCJ,SAAS,SAAS;AAAA,EACvB,WAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AACF,GAcG;AACD,QAAM,WAAW,YAAY;AAC7B,QAAM,OAAO,QAAQ;AACrB,QAAM,kBAAkB,SAAS,WAAW;AAC5C,QAAM,UAAU,eAAe;AAE/B,YAAU,MAAM;AACd,QAAI,mBAAmB;AACrB,UAAI,QAAQ,CAAC,aAAa;AACxB,0BAAkB,SAAS,YAAY,SAAS,sBAAsB,IAAI,SAAS,sBAAsB,CAAC;AAAA,MAC5G;AAAA,IACF;AAAA,EACF,GAAG,CAAC,MAAM,aAAa,UAAU,iBAAiB,CAAC;AAEnD,MAAI,QAAQ,CAAC,aAAa;AACxB,WAAO,oBAAC,yBAAsB,MAAK,YAAW,UAAoB;AAAA,EACpE;AAEA,MAAI,SAAS,aAAa,CAAC,QAAQ,OAAO,eAAe;AACvD,WAAO,oBAAC,yBAAsB,MAAK,kBAAiB,UAAoB;AAAA,EAC1E;AAEA,QAAM,mBAAmB,QAAQ,OAAO,qBAAqB,QAAQ,OAAO,qBAAqB,QAAQ,OAAO,eAAe,SAAS;AAExI,SACE,oBAAC,iBAAc,UACb,+BAAC,SAAI,WAAU,2CAA0C,OAAO,EAAE,OAAO,SAAS,SAAS,WAAW,SAAS,EAAE,GAC/G;AAAA,yBAAC,SAAI,WAAU,oBACb;AAAA,0BAAC,cAAW,MAAK,MACd,mBAAS,YAAY,4BAA4B,wBACpD;AAAA,MACC,SAAS,YACR,QAAQ,OAAO,iBACb,qBAAC,cACE;AAAA;AAAA,QACD,oBAAC,cAAW,MAAM,SAAS,KAAK,QAAQ,SAAS,CAAC,MAAM;AACtD,4BAAkB,SAAS,iBAAiB,CAAC;AAC7C,YAAE,eAAe;AAAA,QACnB,GAAG,qBAEH;AAAA,SACF,IAGF,qBAAC,cACE;AAAA;AAAA,QACD,oBAAC,cAAW,MAAM,SAAS,KAAK,QAAQ,SAAS,CAAC,MAAM;AACtD,4BAAkB,SAAS,iBAAiB,CAAC;AAC7C,YAAE,eAAe;AAAA,QACnB,GAAG,qBAEH;AAAA,SACF;AAAA,OAEJ;AAAA,IACA,oBAAC,oBAAiB,MAAY,aAA0B;AAAA,IACvD,mBAAmB,oBAAC,qBAAkB,MAAM,oBAAoB;AAAA,IAChE,QAAQ,OAAO,qBAAqB,QAAQ,OAAO,mBAClD,qBAAC,QAAK,cAAa,cACjB;AAAA,2BAAC,YAAS,WAAU,eAClB;AAAA,4BAAC,eAAY,OAAM,cAAa,WAAU,UAAS,wBAAU;AAAA,QAC7D,oBAAC,eAAY,OAAM,YAAW,WAAU,UAAS,sBAAQ;AAAA,SAC3D;AAAA,MACA,oBAAC,eAAY,OAAM,cACjB,8BAAC,mBAAe,GAClB;AAAA,MACA,oBAAC,eAAY,OAAM,YAChB,mBAAS,YAAY,oBAAC,oBAAgB,IAAK,oBAAC,oBAAgB,GAC/D;AAAA,OACF,IACE,QAAQ,OAAO,oBACjB,SAAS,YAAY,oBAAC,oBAAgB,IAAK,oBAAC,oBAAgB,IAC1D,QAAQ,OAAO,mBACjB,oBAAC,mBAAe,IACd;AAAA,KACN,GACF;AAEJ;","names":[]}
|
|
@@ -66,7 +66,7 @@ function ForgotPassword({ fullPage = false }) {
|
|
|
66
66
|
return /* @__PURE__ */ jsx(PredefinedMessageCard, { type: "emailSent", fullPage });
|
|
67
67
|
}
|
|
68
68
|
return /* @__PURE__ */ jsxs(MaybeFullPage, { fullPage, children: [
|
|
69
|
-
/* @__PURE__ */ jsxs("div", { className: "text-center mb-6 stack-scope", children: [
|
|
69
|
+
/* @__PURE__ */ jsxs("div", { className: "text-center mb-6 stack-scope", style: { width: "380px", padding: fullPage ? "1rem" : 0 }, children: [
|
|
70
70
|
/* @__PURE__ */ jsx(Typography, { type: "h2", children: "Reset Your Password" }),
|
|
71
71
|
/* @__PURE__ */ jsxs(Typography, { children: [
|
|
72
72
|
"Don't need to reset? ",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components-page/forgot-password.tsx"],"sourcesContent":["'use client';\n\nimport { yupResolver } from \"@hookform/resolvers/yup\";\nimport { yupObject, yupString } from \"@stackframe/stack-shared/dist/schema-fields\";\nimport { runAsynchronouslyWithAlert } from \"@stackframe/stack-shared/dist/utils/promises\";\nimport { Button, Input, Label, StyledLink, Typography } from \"@stackframe/stack-ui\";\nimport { useState } from \"react\";\nimport { useForm } from \"react-hook-form\";\nimport * as yup from \"yup\";\nimport { useStackApp, useUser } from \"..\";\nimport { FormWarningText } from \"../components/elements/form-warning\";\nimport { MaybeFullPage } from \"../components/elements/maybe-full-page\";\nimport { PredefinedMessageCard } from \"../components/message-cards/predefined-message-card\";\n\nconst schema = yupObject({\n email: yupString().email('Please enter a valid email').required('Please enter your email')\n});\n\nexport function ForgotPasswordForm({ onSent }: { onSent?: () => void }) {\n const { register, handleSubmit, formState: { errors }, clearErrors } = useForm({\n resolver: yupResolver(schema)\n });\n const stackApp = useStackApp();\n const [loading, setLoading] = useState(false);\n\n const onSubmit = async (data: yup.InferType<typeof schema>) => {\n setLoading(true);\n try {\n const { email } = data;\n await stackApp.sendForgotPasswordEmail(email);\n onSent?.();\n } finally {\n setLoading(false);\n }\n };\n\n return (\n <form\n className=\"flex flex-col items-stretch stack-scope\"\n onSubmit={e => runAsynchronouslyWithAlert(handleSubmit(onSubmit)(e))}\n noValidate\n >\n <Label htmlFor=\"email\" className=\"mb-1\">Your Email</Label>\n <Input\n id=\"email\"\n type=\"email\"\n {...register('email')}\n onChange={() => clearErrors('email')}\n />\n <FormWarningText text={errors.email?.message?.toString()} />\n\n <Button type=\"submit\" className=\"mt-6\" loading={loading}>\n Send Email\n </Button>\n </form>\n );\n}\n\n\nexport function ForgotPassword({ fullPage=false }: { fullPage?: boolean }) {\n const stackApp = useStackApp();\n const user = useUser();\n const [sent, setSent] = useState(false);\n\n if (user) {\n return <PredefinedMessageCard type='signedIn' fullPage={fullPage} />;\n }\n\n if (sent) {\n return <PredefinedMessageCard type='emailSent' fullPage={fullPage} />;\n }\n\n return (\n <MaybeFullPage fullPage={fullPage}>\n <div className=\"text-center mb-6 stack-scope\">\n <Typography type='h2'>Reset Your Password</Typography>\n <Typography>\n {\"Don't need to reset? \"}\n <StyledLink href={stackApp.urls['signUp']}>\n Sign in\n </StyledLink>\n </Typography>\n </div>\n <ForgotPasswordForm onSent={() => setSent(true)} />\n </MaybeFullPage>\n );\n};\n"],"mappings":";;;AAEA,SAAS,mBAAmB;AAC5B,SAAS,WAAW,iBAAiB;AACrC,SAAS,kCAAkC;AAC3C,SAAS,QAAQ,OAAO,OAAO,YAAY,kBAAkB;AAC7D,SAAS,gBAAgB;AACzB,SAAS,eAAe;AAExB,SAAS,aAAa,eAAe;AACrC,SAAS,uBAAuB;AAChC,SAAS,qBAAqB;AAC9B,SAAS,6BAA6B;AAyBlC,SAKE,KALF;AAvBJ,IAAM,SAAS,UAAU;AAAA,EACvB,OAAO,UAAU,EAAE,MAAM,4BAA4B,EAAE,SAAS,yBAAyB;AAC3F,CAAC;AAEM,SAAS,mBAAmB,EAAE,OAAO,GAA4B;AACtE,QAAM,EAAE,UAAU,cAAc,WAAW,EAAE,OAAO,GAAG,YAAY,IAAI,QAAQ;AAAA,IAC7E,UAAU,YAAY,MAAM;AAAA,EAC9B,CAAC;AACD,QAAM,WAAW,YAAY;AAC7B,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAE5C,QAAM,WAAW,OAAO,SAAuC;AAC7D,eAAW,IAAI;AACf,QAAI;AACF,YAAM,EAAE,MAAM,IAAI;AAClB,YAAM,SAAS,wBAAwB,KAAK;AAC9C,eAAS;AAAA,IACT,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,UAAU,OAAK,2BAA2B,aAAa,QAAQ,EAAE,CAAC,CAAC;AAAA,MACnE,YAAU;AAAA,MAEV;AAAA,4BAAC,SAAM,SAAQ,SAAQ,WAAU,QAAO,wBAAU;AAAA,QAClD;AAAA,UAAC;AAAA;AAAA,YACC,IAAG;AAAA,YACH,MAAK;AAAA,YACJ,GAAG,SAAS,OAAO;AAAA,YACpB,UAAU,MAAM,YAAY,OAAO;AAAA;AAAA,QACrC;AAAA,QACA,oBAAC,mBAAgB,MAAM,OAAO,OAAO,SAAS,SAAS,GAAG;AAAA,QAE1D,oBAAC,UAAO,MAAK,UAAS,WAAU,QAAO,SAAkB,wBAEzD;AAAA;AAAA;AAAA,EACF;AAEJ;AAGO,SAAS,eAAe,EAAE,WAAS,MAAM,GAA2B;AACzE,QAAM,WAAW,YAAY;AAC7B,QAAM,OAAO,QAAQ;AACrB,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AAEtC,MAAI,MAAM;AACR,WAAO,oBAAC,yBAAsB,MAAK,YAAW,UAAoB;AAAA,EACpE;AAEA,MAAI,MAAM;AACR,WAAO,oBAAC,yBAAsB,MAAK,aAAY,UAAoB;AAAA,EACrE;AAEA,SACE,qBAAC,iBAAc,UACb;AAAA,yBAAC,SAAI,WAAU,
|
|
1
|
+
{"version":3,"sources":["../../../src/components-page/forgot-password.tsx"],"sourcesContent":["'use client';\n\nimport { yupResolver } from \"@hookform/resolvers/yup\";\nimport { yupObject, yupString } from \"@stackframe/stack-shared/dist/schema-fields\";\nimport { runAsynchronouslyWithAlert } from \"@stackframe/stack-shared/dist/utils/promises\";\nimport { Button, Input, Label, StyledLink, Typography } from \"@stackframe/stack-ui\";\nimport { useState } from \"react\";\nimport { useForm } from \"react-hook-form\";\nimport * as yup from \"yup\";\nimport { useStackApp, useUser } from \"..\";\nimport { FormWarningText } from \"../components/elements/form-warning\";\nimport { MaybeFullPage } from \"../components/elements/maybe-full-page\";\nimport { PredefinedMessageCard } from \"../components/message-cards/predefined-message-card\";\n\nconst schema = yupObject({\n email: yupString().email('Please enter a valid email').required('Please enter your email')\n});\n\nexport function ForgotPasswordForm({ onSent }: { onSent?: () => void }) {\n const { register, handleSubmit, formState: { errors }, clearErrors } = useForm({\n resolver: yupResolver(schema)\n });\n const stackApp = useStackApp();\n const [loading, setLoading] = useState(false);\n\n const onSubmit = async (data: yup.InferType<typeof schema>) => {\n setLoading(true);\n try {\n const { email } = data;\n await stackApp.sendForgotPasswordEmail(email);\n onSent?.();\n } finally {\n setLoading(false);\n }\n };\n\n return (\n <form\n className=\"flex flex-col items-stretch stack-scope\"\n onSubmit={e => runAsynchronouslyWithAlert(handleSubmit(onSubmit)(e))}\n noValidate\n >\n <Label htmlFor=\"email\" className=\"mb-1\">Your Email</Label>\n <Input\n id=\"email\"\n type=\"email\"\n {...register('email')}\n onChange={() => clearErrors('email')}\n />\n <FormWarningText text={errors.email?.message?.toString()} />\n\n <Button type=\"submit\" className=\"mt-6\" loading={loading}>\n Send Email\n </Button>\n </form>\n );\n}\n\n\nexport function ForgotPassword({ fullPage=false }: { fullPage?: boolean }) {\n const stackApp = useStackApp();\n const user = useUser();\n const [sent, setSent] = useState(false);\n\n if (user) {\n return <PredefinedMessageCard type='signedIn' fullPage={fullPage} />;\n }\n\n if (sent) {\n return <PredefinedMessageCard type='emailSent' fullPage={fullPage} />;\n }\n\n return (\n <MaybeFullPage fullPage={fullPage}>\n <div className=\"text-center mb-6 stack-scope\" style={{ width: '380px', padding: fullPage ? '1rem' : 0 }}>\n <Typography type='h2'>Reset Your Password</Typography>\n <Typography>\n {\"Don't need to reset? \"}\n <StyledLink href={stackApp.urls['signUp']}>\n Sign in\n </StyledLink>\n </Typography>\n </div>\n <ForgotPasswordForm onSent={() => setSent(true)} />\n </MaybeFullPage>\n );\n};\n"],"mappings":";;;AAEA,SAAS,mBAAmB;AAC5B,SAAS,WAAW,iBAAiB;AACrC,SAAS,kCAAkC;AAC3C,SAAS,QAAQ,OAAO,OAAO,YAAY,kBAAkB;AAC7D,SAAS,gBAAgB;AACzB,SAAS,eAAe;AAExB,SAAS,aAAa,eAAe;AACrC,SAAS,uBAAuB;AAChC,SAAS,qBAAqB;AAC9B,SAAS,6BAA6B;AAyBlC,SAKE,KALF;AAvBJ,IAAM,SAAS,UAAU;AAAA,EACvB,OAAO,UAAU,EAAE,MAAM,4BAA4B,EAAE,SAAS,yBAAyB;AAC3F,CAAC;AAEM,SAAS,mBAAmB,EAAE,OAAO,GAA4B;AACtE,QAAM,EAAE,UAAU,cAAc,WAAW,EAAE,OAAO,GAAG,YAAY,IAAI,QAAQ;AAAA,IAC7E,UAAU,YAAY,MAAM;AAAA,EAC9B,CAAC;AACD,QAAM,WAAW,YAAY;AAC7B,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAE5C,QAAM,WAAW,OAAO,SAAuC;AAC7D,eAAW,IAAI;AACf,QAAI;AACF,YAAM,EAAE,MAAM,IAAI;AAClB,YAAM,SAAS,wBAAwB,KAAK;AAC9C,eAAS;AAAA,IACT,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,UAAU,OAAK,2BAA2B,aAAa,QAAQ,EAAE,CAAC,CAAC;AAAA,MACnE,YAAU;AAAA,MAEV;AAAA,4BAAC,SAAM,SAAQ,SAAQ,WAAU,QAAO,wBAAU;AAAA,QAClD;AAAA,UAAC;AAAA;AAAA,YACC,IAAG;AAAA,YACH,MAAK;AAAA,YACJ,GAAG,SAAS,OAAO;AAAA,YACpB,UAAU,MAAM,YAAY,OAAO;AAAA;AAAA,QACrC;AAAA,QACA,oBAAC,mBAAgB,MAAM,OAAO,OAAO,SAAS,SAAS,GAAG;AAAA,QAE1D,oBAAC,UAAO,MAAK,UAAS,WAAU,QAAO,SAAkB,wBAEzD;AAAA;AAAA;AAAA,EACF;AAEJ;AAGO,SAAS,eAAe,EAAE,WAAS,MAAM,GAA2B;AACzE,QAAM,WAAW,YAAY;AAC7B,QAAM,OAAO,QAAQ;AACrB,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AAEtC,MAAI,MAAM;AACR,WAAO,oBAAC,yBAAsB,MAAK,YAAW,UAAoB;AAAA,EACpE;AAEA,MAAI,MAAM;AACR,WAAO,oBAAC,yBAAsB,MAAK,aAAY,UAAoB;AAAA,EACrE;AAEA,SACE,qBAAC,iBAAc,UACb;AAAA,yBAAC,SAAI,WAAU,gCAA+B,OAAO,EAAE,OAAO,SAAS,SAAS,WAAW,SAAS,EAAE,GACpG;AAAA,0BAAC,cAAW,MAAK,MAAK,iCAAmB;AAAA,MACzC,qBAAC,cACE;AAAA;AAAA,QACD,oBAAC,cAAW,MAAM,SAAS,KAAK,QAAQ,GAAG,qBAE3C;AAAA,SACF;AAAA,OACF;AAAA,IACA,oBAAC,sBAAmB,QAAQ,MAAM,QAAQ,IAAI,GAAG;AAAA,KACnD;AAEJ;","names":[]}
|
|
@@ -61,7 +61,7 @@ function PasswordResetForm({ code, fullPage = false }) {
|
|
|
61
61
|
return /* @__PURE__ */ jsx(MessageCard, { title: "Failed to reset password", fullPage, children: "Failed to reset password. Please request a new password reset link" });
|
|
62
62
|
}
|
|
63
63
|
return /* @__PURE__ */ jsxs(MaybeFullPage, { fullPage, children: [
|
|
64
|
-
/* @__PURE__ */ jsx("div", { className: "text-center mb-6", children: /* @__PURE__ */ jsx(Typography, { type: "h2", children: "Reset Your Password" }) }),
|
|
64
|
+
/* @__PURE__ */ jsx("div", { className: "text-center mb-6", style: { width: "380px", padding: fullPage ? "1rem" : 0 }, children: /* @__PURE__ */ jsx(Typography, { type: "h2", children: "Reset Your Password" }) }),
|
|
65
65
|
/* @__PURE__ */ jsxs(
|
|
66
66
|
"form",
|
|
67
67
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components-page/password-reset.tsx"],"sourcesContent":["'use client';\n\nimport { yupResolver } from \"@hookform/resolvers/yup\";\nimport { KnownErrors } from \"@stackframe/stack-shared\";\nimport { getPasswordError } from \"@stackframe/stack-shared/dist/helpers/password\";\nimport { yupObject, yupString } from \"@stackframe/stack-shared/dist/schema-fields\";\nimport { cacheFunction } from \"@stackframe/stack-shared/dist/utils/caches\";\nimport { runAsynchronouslyWithAlert } from \"@stackframe/stack-shared/dist/utils/promises\";\nimport { Button, Label, PasswordInput, Typography } from \"@stackframe/stack-ui\";\nimport React, { useState } from \"react\";\nimport { useForm } from \"react-hook-form\";\nimport * as yup from \"yup\";\nimport { StackClientApp, useStackApp } from \"..\";\nimport { FormWarningText } from \"../components/elements/form-warning\";\nimport { MaybeFullPage } from \"../components/elements/maybe-full-page\";\nimport { MessageCard } from \"../components/message-cards/message-card\";\nimport { PredefinedMessageCard } from \"../components/message-cards/predefined-message-card\";\n\nconst schema = yupObject({\n password: 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 passwordRepeat: yupString().nullable().oneOf([yup.ref('password'), null], 'Passwords do not match').required('Please repeat your password')\n});\n\nexport default function PasswordResetForm(\n { code, fullPage = false }:\n { code: string, fullPage?: boolean }\n) {\n const { register, handleSubmit, formState: { errors }, clearErrors } = useForm({\n resolver: yupResolver(schema)\n });\n const stackApp = useStackApp();\n const [finished, setFinished] = useState(false);\n const [resetError, setResetError] = useState(false);\n const [loading, setLoading] = useState(false);\n\n const onSubmit = async (data: yup.InferType<typeof schema>) => {\n setLoading(true);\n try {\n const { password } = data;\n const errorCode = await stackApp.resetPassword({ password, code });\n if (errorCode) {\n setResetError(true);\n return;\n }\n\n setFinished(true);\n } finally {\n setLoading(false);\n }\n };\n\n if (finished) {\n return <PredefinedMessageCard type='passwordReset' fullPage={fullPage} />;\n }\n\n if (resetError) {\n return (\n <MessageCard title=\"Failed to reset password\" fullPage={fullPage}>\n Failed to reset password. Please request a new password reset link\n </MessageCard>\n );\n }\n\n return (\n <MaybeFullPage fullPage={fullPage}>\n <div className=\"text-center mb-6\">\n <Typography type='h2'>Reset Your Password</Typography>\n </div>\n\n <form\n style={{ display: 'flex', flexDirection: 'column', alignItems: 'stretch' }}\n onSubmit={e => runAsynchronouslyWithAlert(handleSubmit(onSubmit)(e))}\n noValidate\n >\n <Label htmlFor=\"password\" className=\"mb-1\">New Password</Label>\n <PasswordInput\n id=\"password\"\n {...register('password')}\n onChange={() => {\n clearErrors('password');\n clearErrors('passwordRepeat');\n }}\n />\n <FormWarningText text={errors.password?.message?.toString()} />\n\n <Label htmlFor=\"repeat-password\" className=\"mt-4 mb-1\">Repeat New Password</Label>\n <PasswordInput\n id=\"repeat-password\"\n {...register('passwordRepeat')}\n onChange={() => {\n clearErrors('password');\n clearErrors('passwordRepeat');\n }}\n />\n <FormWarningText text={errors.passwordRepeat?.message?.toString()} />\n\n <Button type=\"submit\" className=\"mt-6\" loading={loading}>\n Reset Password\n </Button>\n </form>\n </MaybeFullPage>\n );\n}\n\n\nconst cachedVerifyPasswordResetCode = cacheFunction(async (stackApp: StackClientApp<true>, code: string) => {\n return await stackApp.verifyPasswordResetCode(code);\n});\n\nexport function PasswordReset({\n searchParams,\n fullPage = false,\n}: {\n searchParams: Record<string, string>,\n fullPage?: boolean,\n}) {\n const stackApp = useStackApp();\n\n const invalidJsx = (\n <MessageCard title=\"Invalid Password Reset Link\" fullPage={fullPage}>\n <Typography>Please double check if you have the correct password reset link.</Typography>\n </MessageCard>\n );\n\n const expiredJsx = (\n <MessageCard title=\"Expired Password Reset Link\" fullPage={fullPage}>\n <Typography>Your password reset link has expired. Please request a new password reset link from the login page.</Typography>\n </MessageCard>\n );\n\n const usedJsx = (\n <MessageCard title=\"Used Password Reset Link\" fullPage={fullPage}>\n <Typography>This password reset link has already been used. If you need to reset your password again, please request a new password reset link from the login page.</Typography>\n </MessageCard>\n );\n\n const code = searchParams.code;\n if (!code) {\n return invalidJsx;\n }\n\n const error = React.use(cachedVerifyPasswordResetCode(stackApp, code));\n\n if (error instanceof KnownErrors.VerificationCodeNotFound) {\n return invalidJsx;\n } else if (error instanceof KnownErrors.VerificationCodeExpired) {\n return expiredJsx;\n } else if (error instanceof KnownErrors.VerificationCodeAlreadyUsed) {\n return usedJsx;\n } else if (error) {\n throw error;\n }\n\n return <PasswordResetForm code={code} fullPage={fullPage} />;\n}\n"],"mappings":";;;AAEA,SAAS,mBAAmB;AAC5B,SAAS,mBAAmB;AAC5B,SAAS,wBAAwB;AACjC,SAAS,WAAW,iBAAiB;AACrC,SAAS,qBAAqB;AAC9B,SAAS,kCAAkC;AAC3C,SAAS,QAAQ,OAAO,eAAe,kBAAkB;AACzD,OAAO,SAAS,gBAAgB;AAChC,SAAS,eAAe;AACxB,YAAY,SAAS;AACrB,SAAyB,mBAAmB;AAC5C,SAAS,uBAAuB;AAChC,SAAS,qBAAqB;AAC9B,SAAS,mBAAmB;AAC5B,SAAS,6BAA6B;AA8C3B,cAiBL,YAjBK;AA5CX,IAAM,SAAS,UAAU;AAAA,EACvB,UAAU,UAAU,EAAE,SAAS,4BAA4B,EAAE,KAAK;AAAA,IAChE,MAAM;AAAA,IACN,MAAM,CAAC,OAAO,QAAQ;AACpB,YAAM,QAAQ,iBAAiB,KAAK;AACpC,UAAI,OAAO;AACT,eAAO,IAAI,YAAY,EAAE,SAAS,MAAM,QAAQ,CAAC;AAAA,MACnD,OAAO;AACL,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF,CAAC;AAAA,EACD,gBAAgB,UAAU,EAAE,SAAS,EAAE,MAAM,CAAK,QAAI,UAAU,GAAG,IAAI,GAAG,wBAAwB,EAAE,SAAS,6BAA6B;AAC5I,CAAC;AAEc,SAAR,kBACL,EAAE,MAAM,WAAW,MAAM,GAEzB;AACA,QAAM,EAAE,UAAU,cAAc,WAAW,EAAE,OAAO,GAAG,YAAY,IAAI,QAAQ;AAAA,IAC7E,UAAU,YAAY,MAAM;AAAA,EAC9B,CAAC;AACD,QAAM,WAAW,YAAY;AAC7B,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAC9C,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAClD,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAE5C,QAAM,WAAW,OAAO,SAAuC;AAC7D,eAAW,IAAI;AACf,QAAI;AACF,YAAM,EAAE,SAAS,IAAI;AACrB,YAAM,YAAY,MAAM,SAAS,cAAc,EAAE,UAAU,KAAK,CAAC;AACjE,UAAI,WAAW;AACb,sBAAc,IAAI;AAClB;AAAA,MACF;AAEA,kBAAY,IAAI;AAAA,IAClB,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF;AAEA,MAAI,UAAU;AACZ,WAAO,oBAAC,yBAAsB,MAAK,iBAAgB,UAAoB;AAAA,EACzE;AAEA,MAAI,YAAY;AACd,WACE,oBAAC,eAAY,OAAM,4BAA2B,UAAoB,gFAElE;AAAA,EAEJ;AAEA,SACE,qBAAC,iBAAc,UACb;AAAA,wBAAC,SAAI,WAAU,
|
|
1
|
+
{"version":3,"sources":["../../../src/components-page/password-reset.tsx"],"sourcesContent":["'use client';\n\nimport { yupResolver } from \"@hookform/resolvers/yup\";\nimport { KnownErrors } from \"@stackframe/stack-shared\";\nimport { getPasswordError } from \"@stackframe/stack-shared/dist/helpers/password\";\nimport { yupObject, yupString } from \"@stackframe/stack-shared/dist/schema-fields\";\nimport { cacheFunction } from \"@stackframe/stack-shared/dist/utils/caches\";\nimport { runAsynchronouslyWithAlert } from \"@stackframe/stack-shared/dist/utils/promises\";\nimport { Button, Label, PasswordInput, Typography } from \"@stackframe/stack-ui\";\nimport React, { useState } from \"react\";\nimport { useForm } from \"react-hook-form\";\nimport * as yup from \"yup\";\nimport { StackClientApp, useStackApp } from \"..\";\nimport { FormWarningText } from \"../components/elements/form-warning\";\nimport { MaybeFullPage } from \"../components/elements/maybe-full-page\";\nimport { MessageCard } from \"../components/message-cards/message-card\";\nimport { PredefinedMessageCard } from \"../components/message-cards/predefined-message-card\";\n\nconst schema = yupObject({\n password: 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 passwordRepeat: yupString().nullable().oneOf([yup.ref('password'), null], 'Passwords do not match').required('Please repeat your password')\n});\n\nexport default function PasswordResetForm(\n { code, fullPage = false }:\n { code: string, fullPage?: boolean }\n) {\n const { register, handleSubmit, formState: { errors }, clearErrors } = useForm({\n resolver: yupResolver(schema)\n });\n const stackApp = useStackApp();\n const [finished, setFinished] = useState(false);\n const [resetError, setResetError] = useState(false);\n const [loading, setLoading] = useState(false);\n\n const onSubmit = async (data: yup.InferType<typeof schema>) => {\n setLoading(true);\n try {\n const { password } = data;\n const errorCode = await stackApp.resetPassword({ password, code });\n if (errorCode) {\n setResetError(true);\n return;\n }\n\n setFinished(true);\n } finally {\n setLoading(false);\n }\n };\n\n if (finished) {\n return <PredefinedMessageCard type='passwordReset' fullPage={fullPage} />;\n }\n\n if (resetError) {\n return (\n <MessageCard title=\"Failed to reset password\" fullPage={fullPage}>\n Failed to reset password. Please request a new password reset link\n </MessageCard>\n );\n }\n\n return (\n <MaybeFullPage fullPage={fullPage}>\n <div className=\"text-center mb-6\" style={{ width: '380px', padding: fullPage ? '1rem' : 0 }}>\n <Typography type='h2'>Reset Your Password</Typography>\n </div>\n\n <form\n style={{ display: 'flex', flexDirection: 'column', alignItems: 'stretch' }}\n onSubmit={e => runAsynchronouslyWithAlert(handleSubmit(onSubmit)(e))}\n noValidate\n >\n <Label htmlFor=\"password\" className=\"mb-1\">New Password</Label>\n <PasswordInput\n id=\"password\"\n {...register('password')}\n onChange={() => {\n clearErrors('password');\n clearErrors('passwordRepeat');\n }}\n />\n <FormWarningText text={errors.password?.message?.toString()} />\n\n <Label htmlFor=\"repeat-password\" className=\"mt-4 mb-1\">Repeat New Password</Label>\n <PasswordInput\n id=\"repeat-password\"\n {...register('passwordRepeat')}\n onChange={() => {\n clearErrors('password');\n clearErrors('passwordRepeat');\n }}\n />\n <FormWarningText text={errors.passwordRepeat?.message?.toString()} />\n\n <Button type=\"submit\" className=\"mt-6\" loading={loading}>\n Reset Password\n </Button>\n </form>\n </MaybeFullPage>\n );\n}\n\n\nconst cachedVerifyPasswordResetCode = cacheFunction(async (stackApp: StackClientApp<true>, code: string) => {\n return await stackApp.verifyPasswordResetCode(code);\n});\n\nexport function PasswordReset({\n searchParams,\n fullPage = false,\n}: {\n searchParams: Record<string, string>,\n fullPage?: boolean,\n}) {\n const stackApp = useStackApp();\n\n const invalidJsx = (\n <MessageCard title=\"Invalid Password Reset Link\" fullPage={fullPage}>\n <Typography>Please double check if you have the correct password reset link.</Typography>\n </MessageCard>\n );\n\n const expiredJsx = (\n <MessageCard title=\"Expired Password Reset Link\" fullPage={fullPage}>\n <Typography>Your password reset link has expired. Please request a new password reset link from the login page.</Typography>\n </MessageCard>\n );\n\n const usedJsx = (\n <MessageCard title=\"Used Password Reset Link\" fullPage={fullPage}>\n <Typography>This password reset link has already been used. If you need to reset your password again, please request a new password reset link from the login page.</Typography>\n </MessageCard>\n );\n\n const code = searchParams.code;\n if (!code) {\n return invalidJsx;\n }\n\n const error = React.use(cachedVerifyPasswordResetCode(stackApp, code));\n\n if (error instanceof KnownErrors.VerificationCodeNotFound) {\n return invalidJsx;\n } else if (error instanceof KnownErrors.VerificationCodeExpired) {\n return expiredJsx;\n } else if (error instanceof KnownErrors.VerificationCodeAlreadyUsed) {\n return usedJsx;\n } else if (error) {\n throw error;\n }\n\n return <PasswordResetForm code={code} fullPage={fullPage} />;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -17,8 +17,12 @@ async function StackHandler({
|
|
|
17
17
|
app,
|
|
18
18
|
params: { stack } = {},
|
|
19
19
|
searchParams = {},
|
|
20
|
-
fullPage
|
|
20
|
+
fullPage
|
|
21
21
|
}) {
|
|
22
|
+
if (fullPage === void 0) {
|
|
23
|
+
console.warn("Not specifying `fullPage` in the StackHandler options is deprecated; the default value will change to `false` in the next major version. Please specify `fullPage={true}` in your `app/[...stack]/handler/page.tsx` file to retain the current behavior.");
|
|
24
|
+
fullPage = true;
|
|
25
|
+
}
|
|
22
26
|
if (!stack) {
|
|
23
27
|
return /* @__PURE__ */ jsx(MessageCard, { title: "Invalid Stack Handler Setup", fullPage, children: /* @__PURE__ */ jsx("p", { children: "Can't use Stack handler at this location. Make sure that the file is in a folder called [...stack]." }) });
|
|
24
28
|
}
|