@stackframe/stack 2.5.17 → 2.5.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/dist/components/credential-sign-in.js +4 -1
- package/dist/components/credential-sign-in.js.map +1 -1
- package/dist/components/elements/sidebar-layout.d.mts +21 -0
- package/dist/components/elements/sidebar-layout.d.ts +21 -0
- package/dist/components/elements/sidebar-layout.js +125 -0
- package/dist/components/elements/sidebar-layout.js.map +1 -0
- package/dist/components/elements/user-avatar.d.mts +5 -11
- package/dist/components/elements/user-avatar.d.ts +5 -11
- package/dist/components/elements/user-avatar.js.map +1 -1
- package/dist/components/message-cards/predefined-message-card.d.mts +1 -1
- package/dist/components/message-cards/predefined-message-card.d.ts +1 -1
- package/dist/components/message-cards/predefined-message-card.js +8 -0
- package/dist/components/message-cards/predefined-message-card.js.map +1 -1
- package/dist/components/selected-team-switcher.d.mts +1 -0
- package/dist/components/selected-team-switcher.d.ts +1 -0
- package/dist/components/selected-team-switcher.js +35 -5
- package/dist/components/selected-team-switcher.js.map +1 -1
- package/dist/components-page/account-settings.js +123 -31
- package/dist/components-page/account-settings.js.map +1 -1
- package/dist/components-page/auth-page.d.mts +1 -0
- package/dist/components-page/auth-page.d.ts +1 -0
- package/dist/components-page/auth-page.js +4 -1
- package/dist/components-page/auth-page.js.map +1 -1
- package/dist/components-page/forgot-password.d.mts +4 -1
- package/dist/components-page/forgot-password.d.ts +4 -1
- package/dist/components-page/forgot-password.js +55 -7
- package/dist/components-page/forgot-password.js.map +1 -1
- package/dist/components-page/password-reset.d.mts +6 -2
- package/dist/components-page/password-reset.d.ts +6 -2
- package/dist/components-page/password-reset.js +100 -8
- package/dist/components-page/password-reset.js.map +1 -1
- package/dist/components-page/stack-handler.d.mts +1 -0
- package/dist/components-page/stack-handler.d.ts +1 -0
- package/dist/components-page/stack-handler.js +32 -6
- package/dist/components-page/stack-handler.js.map +1 -1
- package/dist/{components/password-reset-form.d.mts → components-page/team-creation.d.mts} +2 -3
- package/dist/{components/password-reset-form.d.ts → components-page/team-creation.d.ts} +2 -3
- package/dist/components-page/team-creation.js +92 -0
- package/dist/components-page/team-creation.js.map +1 -0
- package/dist/components-page/team-invitation.d.mts +8 -0
- package/dist/components-page/team-invitation.d.ts +8 -0
- package/dist/components-page/team-invitation.js +141 -0
- package/dist/components-page/team-invitation.js.map +1 -0
- package/dist/components-page/team-settings.d.mts +8 -0
- package/dist/components-page/team-settings.d.ts +8 -0
- package/dist/components-page/team-settings.js +139 -0
- package/dist/components-page/team-settings.js.map +1 -0
- package/dist/esm/components/credential-sign-in.js +4 -1
- package/dist/esm/components/credential-sign-in.js.map +1 -1
- package/dist/esm/components/elements/sidebar-layout.js +90 -0
- package/dist/esm/components/elements/sidebar-layout.js.map +1 -0
- package/dist/esm/components/elements/user-avatar.js.map +1 -1
- package/dist/esm/components/message-cards/predefined-message-card.js +8 -0
- package/dist/esm/components/message-cards/predefined-message-card.js.map +1 -1
- package/dist/esm/components/selected-team-switcher.js +39 -7
- package/dist/esm/components/selected-team-switcher.js.map +1 -1
- package/dist/esm/components-page/account-settings.js +114 -32
- package/dist/esm/components-page/account-settings.js.map +1 -1
- package/dist/esm/components-page/auth-page.js +4 -1
- package/dist/esm/components-page/auth-page.js.map +1 -1
- package/dist/esm/components-page/forgot-password.js +52 -5
- package/dist/esm/components-page/forgot-password.js.map +1 -1
- package/dist/esm/components-page/password-reset.js +101 -9
- package/dist/esm/components-page/password-reset.js.map +1 -1
- package/dist/esm/components-page/stack-handler.js +32 -6
- package/dist/esm/components-page/stack-handler.js.map +1 -1
- package/dist/esm/components-page/team-creation.js +68 -0
- package/dist/esm/components-page/team-creation.js.map +1 -0
- package/dist/esm/components-page/team-invitation.js +107 -0
- package/dist/esm/components-page/team-invitation.js.map +1 -0
- package/dist/esm/components-page/team-settings.js +115 -0
- package/dist/esm/components-page/team-settings.js.map +1 -0
- 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 +5 -1
- package/dist/esm/lib/auth.js.map +1 -1
- package/dist/esm/lib/stack-app.js +272 -25
- package/dist/esm/lib/stack-app.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/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/lib/auth.js +5 -1
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/hooks.d.mts +1 -0
- package/dist/lib/hooks.d.ts +1 -0
- package/dist/lib/stack-app.d.mts +64 -5
- package/dist/lib/stack-app.d.ts +64 -5
- package/dist/lib/stack-app.js +272 -25
- package/dist/lib/stack-app.js.map +1 -1
- package/dist/providers/stack-provider-client.d.mts +1 -0
- package/dist/providers/stack-provider-client.d.ts +1 -0
- package/dist/providers/stack-provider.d.mts +1 -0
- package/dist/providers/stack-provider.d.ts +1 -0
- package/package.json +10 -6
- package/dist/components/forgot-password-form.d.mts +0 -7
- package/dist/components/forgot-password-form.d.ts +0 -7
- package/dist/components/forgot-password-form.js +0 -83
- package/dist/components/forgot-password-form.js.map +0 -1
- package/dist/components/password-reset-form.js +0 -135
- package/dist/components/password-reset-form.js.map +0 -1
- package/dist/esm/components/forgot-password-form.js +0 -59
- package/dist/esm/components/forgot-password-form.js.map +0 -1
- package/dist/esm/components/password-reset-form.js +0 -105
- package/dist/esm/components/password-reset-form.js.map +0 -1
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
"use client";
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
|
+
|
|
22
|
+
// src/components-page/team-settings.tsx
|
|
23
|
+
var team_settings_exports = {};
|
|
24
|
+
__export(team_settings_exports, {
|
|
25
|
+
TeamSettings: () => TeamSettings
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(team_settings_exports);
|
|
28
|
+
var import_stack_ui = require("@stackframe/stack-ui");
|
|
29
|
+
var import_lucide_react = require("lucide-react");
|
|
30
|
+
var import_react = require("react");
|
|
31
|
+
var import__ = require("..");
|
|
32
|
+
var import_sidebar_layout = require("../components/elements/sidebar-layout");
|
|
33
|
+
var import_user_avatar = require("../components/elements/user-avatar");
|
|
34
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
35
|
+
function TeamSettings(props) {
|
|
36
|
+
const user = (0, import__.useUser)({ or: "redirect" });
|
|
37
|
+
const team = user.useTeam(props.teamId);
|
|
38
|
+
if (!team) {
|
|
39
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import__.MessageCard, { title: "Team not found" });
|
|
40
|
+
}
|
|
41
|
+
const inner = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
42
|
+
import_sidebar_layout.SidebarLayout,
|
|
43
|
+
{
|
|
44
|
+
items: [
|
|
45
|
+
{ title: "My Profile", content: profileSettings({ team }), icon: import_lucide_react.Contact, description: `Your profile in the team "${team.displayName}"` },
|
|
46
|
+
{ title: "Members", content: membersSettings({ team }), icon: import_lucide_react.Users },
|
|
47
|
+
{ title: "Team Info", content: managementSettings({ team }), icon: import_lucide_react.Info }
|
|
48
|
+
// { title: 'Settings', content: userSettings({ team }), icon: Settings },
|
|
49
|
+
].filter(({ content }) => content),
|
|
50
|
+
title: "Team Settings"
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
if (props.fullPage) {
|
|
54
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Container, { size: 800, className: "stack-scope", children: inner });
|
|
55
|
+
} else {
|
|
56
|
+
return inner;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function managementSettings(props) {
|
|
60
|
+
const user = (0, import__.useUser)({ or: "redirect" });
|
|
61
|
+
const updateTeamPermission = user.usePermission(props.team, "$update_team");
|
|
62
|
+
if (!updateTeamPermission) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
66
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { children: "Team display name" }),
|
|
67
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.EditableText, { value: props.team.displayName, onSave: () => {
|
|
68
|
+
} })
|
|
69
|
+
] }) });
|
|
70
|
+
}
|
|
71
|
+
function profileSettings(props) {
|
|
72
|
+
const user = (0, import__.useUser)({ or: "redirect" });
|
|
73
|
+
const profile = user.useTeamProfile(props.team);
|
|
74
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-col", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col", children: [
|
|
75
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_stack_ui.Label, { className: "flex gap-2", children: [
|
|
76
|
+
"Display name ",
|
|
77
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.SimpleTooltip, { tooltip: "This overwrites your user display name in the account setting", type: "info" })
|
|
78
|
+
] }),
|
|
79
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
80
|
+
import_stack_ui.EditableText,
|
|
81
|
+
{
|
|
82
|
+
value: profile.displayName || "",
|
|
83
|
+
onSave: async (newDisplayName) => {
|
|
84
|
+
await profile.update({ displayName: newDisplayName });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
)
|
|
88
|
+
] }) });
|
|
89
|
+
}
|
|
90
|
+
function membersSettings(props) {
|
|
91
|
+
const [removeModalOpen, setRemoveModalOpen] = (0, import_react.useState)(false);
|
|
92
|
+
const user = (0, import__.useUser)({ or: "redirect" });
|
|
93
|
+
const removeMemberPermission = user.usePermission(props.team, "$remove_members");
|
|
94
|
+
const readMemberPermission = user.usePermission(props.team, "$read_members");
|
|
95
|
+
const inviteMemberPermission = user.usePermission(props.team, "$invite_members");
|
|
96
|
+
const [email, setEmail] = (0, import_react.useState)("");
|
|
97
|
+
const [invited, setInvited] = (0, import_react.useState)(false);
|
|
98
|
+
if (!readMemberPermission && !inviteMemberPermission) {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
const users = props.team.useUsers();
|
|
102
|
+
(0, import_react.useEffect)(() => {
|
|
103
|
+
if (invited && email) {
|
|
104
|
+
setInvited(false);
|
|
105
|
+
}
|
|
106
|
+
}, [email]);
|
|
107
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col gap-8", children: [
|
|
108
|
+
inviteMemberPermission && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
109
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { children: "Invite a user to team" }),
|
|
110
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col gap-2 md:flex-row", children: [
|
|
111
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Input, { placeholder: "Email", value: email, onChange: (e) => setEmail(e.target.value) }),
|
|
112
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Button, { onClick: async () => {
|
|
113
|
+
await props.team.inviteUser({ email });
|
|
114
|
+
setEmail("");
|
|
115
|
+
setInvited(true);
|
|
116
|
+
}, children: "Invite" })
|
|
117
|
+
] }),
|
|
118
|
+
invited && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { type: "label", variant: "secondary", children: "User invited." })
|
|
119
|
+
] }),
|
|
120
|
+
readMemberPermission && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
121
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { children: "Members" }),
|
|
122
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_stack_ui.Table, { children: [
|
|
123
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_stack_ui.TableRow, { children: [
|
|
124
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableHead, { className: "w-[100px]", children: "User" }),
|
|
125
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableHead, { className: "w-[200px]", children: "Name" })
|
|
126
|
+
] }) }),
|
|
127
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableBody, { children: users.map(({ id, teamProfile }, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_stack_ui.TableRow, { children: [
|
|
128
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableCell, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_user_avatar.UserAvatar, { user: teamProfile }) }),
|
|
129
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableCell, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { children: teamProfile.displayName }) })
|
|
130
|
+
] }, id)) })
|
|
131
|
+
] })
|
|
132
|
+
] })
|
|
133
|
+
] }) });
|
|
134
|
+
}
|
|
135
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
136
|
+
0 && (module.exports = {
|
|
137
|
+
TeamSettings
|
|
138
|
+
});
|
|
139
|
+
//# sourceMappingURL=team-settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components-page/team-settings.tsx"],"sourcesContent":["'use client';\n\nimport { ActionCell, ActionDialog, Button, Container, EditableText, Input, Label, SimpleTooltip, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Typography } from \"@stackframe/stack-ui\";\nimport { Contact, Info, Settings, Users } from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\nimport { MessageCard, Team, useStackApp, useUser } from \"..\";\nimport { SidebarLayout } from \"../components/elements/sidebar-layout\";\nimport { UserAvatar } from \"../components/elements/user-avatar\";\n\nexport function TeamSettings(props: { fullPage?: boolean, teamId: string }) {\n const user = useUser({ or: 'redirect' });\n const team = user.useTeam(props.teamId);\n\n if (!team) {\n return <MessageCard title='Team not found' />;\n }\n\n\n const inner = <SidebarLayout\n items={[\n { title: 'My Profile', content: profileSettings({ team }), icon: Contact, description: `Your profile in the team \"${team.displayName}\"` },\n { title: 'Members', content: membersSettings({ team }), icon: Users },\n { title: 'Team Info', content: managementSettings({ team }), icon: Info },\n // { title: 'Settings', content: userSettings({ team }), icon: Settings },\n ].filter(({ content }) => content as any)}\n title='Team Settings'\n />;\n\n if (props.fullPage) {\n return (\n <Container size={800} className='stack-scope'>\n {inner}\n </Container>\n );\n } else {\n return inner;\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 value={props.team.displayName} onSave={() => {}}/>\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\">Display name <SimpleTooltip tooltip=\"This overwrites your user display name in the account setting\" type='info'/></Label>\n <EditableText\n value={profile.displayName || ''}\n onSave={async (newDisplayName) => {\n await profile.update({ displayName: newDisplayName });\n }}/>\n </div>\n </div>\n );\n}\n\nfunction userSettings(props: { team: Team }) {\n const app = useStackApp();\n const user = useUser({ or: 'redirect' });\n\n return (\n <div>\n <div>\n <Button\n variant='secondary'\n onClick={async () => {\n await user.leaveTeam(props.team);\n await app.redirectToHome();\n }}\n >\n Leave team\n </Button>\n </div>\n </div>\n );\n}\n\nfunction RemoveMemberDialog(props: {\n open?: boolean,\n onOpenChange?: (open: boolean) => void,\n}) {\n return (\n <ActionDialog\n open={props.open}\n onOpenChange={props.onOpenChange}\n title=\"Delete domain\"\n danger\n okButton={{\n label: \"Delete\",\n onClick: async () => {\n }\n }}\n cancelButton\n >\n <Typography>\n Do you really want to remove from the team?\n </Typography>\n </ActionDialog>\n );\n}\n\nfunction membersSettings(props: { team: Team }) {\n const [removeModalOpen, setRemoveModalOpen] = useState(false);\n const user = useUser({ or: 'redirect' });\n const removeMemberPermission = user.usePermission(props.team, '$remove_members');\n const readMemberPermission = user.usePermission(props.team, '$read_members');\n const inviteMemberPermission = user.usePermission(props.team, '$invite_members');\n const [email, setEmail] = useState('');\n const [invited, setInvited] = useState(false);\n\n if (!readMemberPermission && !inviteMemberPermission) {\n return null;\n }\n\n const users = props.team.useUsers();\n\n useEffect(() => {\n if (invited && email) {\n setInvited(false);\n }\n }, [email]);\n\n return (\n <>\n <div className=\"flex flex-col gap-8\">\n {inviteMemberPermission &&\n <div>\n <Label>Invite a user to team</Label>\n <div className=\"flex flex-col gap-2 md:flex-row\">\n <Input placeholder=\"Email\" value={email} onChange={e => setEmail(e.target.value)}/>\n <Button onClick={async () => {\n await props.team.inviteUser({ email });\n setEmail('');\n setInvited(true);\n }}>Invite</Button>\n </div>\n {invited && <Typography type='label' variant='secondary'>User invited.</Typography>}\n </div>}\n {readMemberPermission &&\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 {/* {removeMemberPermission && <TableHead className=\"w-[100px]\">Actions</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 {/* {removeMemberPermission && <TableCell>\n <ActionCell items={[\n { item: 'Remove', onClick: () => setRemoveModalOpen(true), danger: true },\n ]}/>\n <RemoveMemberDialog open={removeModalOpen} onOpenChange={setRemoveModalOpen} />\n </TableCell>} */}\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>}\n </div>\n </>\n );\n}"],"mappings":"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","names":[]}
|
|
@@ -25,7 +25,10 @@ function CredentialSignIn() {
|
|
|
25
25
|
setLoading(true);
|
|
26
26
|
try {
|
|
27
27
|
const { email, password } = data;
|
|
28
|
-
const error = await app.signInWithCredential({
|
|
28
|
+
const error = await app.signInWithCredential({
|
|
29
|
+
email,
|
|
30
|
+
password
|
|
31
|
+
});
|
|
29
32
|
setError("email", { type: "manual", message: error?.message });
|
|
30
33
|
} finally {
|
|
31
34
|
setLoading(false);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/credential-sign-in.tsx"],"sourcesContent":["'use client';\n\nimport { useForm } from \"react-hook-form\";\nimport { yupResolver } from \"@hookform/resolvers/yup\";\nimport * as yup from \"yup\";\nimport { FormWarningText } from \"./elements/form-warning\";\nimport { useStackApp } from \"..\";\nimport { runAsynchronouslyWithAlert } from \"@stackframe/stack-shared/dist/utils/promises\";\nimport { Button, Input, Label, PasswordInput, StyledLink } from \"@stackframe/stack-ui\";\nimport { useState } from \"react\";\nimport { yupObject, yupString, yupNumber, yupBoolean, yupArray, yupMixed } from \"@stackframe/stack-shared/dist/schema-fields\";\n\nconst schema = yupObject({\n email: yupString().email('Please enter a valid email').required('Please enter your email'),\n password: yupString().required('Please enter your password')\n});\n\nexport function CredentialSignIn() {\n const { register, handleSubmit, setError, formState: { errors } } = useForm({\n resolver: yupResolver(schema)\n });\n const app = useStackApp();\n const [loading, setLoading] = useState(false);\n\n const onSubmit = async (data: yup.InferType<typeof schema>) => {\n setLoading(true);\n\n try {\n const { email, password } = data;\n const error = await app.signInWithCredential({
|
|
1
|
+
{"version":3,"sources":["../../../src/components/credential-sign-in.tsx"],"sourcesContent":["'use client';\n\nimport { useForm } from \"react-hook-form\";\nimport { yupResolver } from \"@hookform/resolvers/yup\";\nimport * as yup from \"yup\";\nimport { FormWarningText } from \"./elements/form-warning\";\nimport { useStackApp } from \"..\";\nimport { runAsynchronouslyWithAlert } from \"@stackframe/stack-shared/dist/utils/promises\";\nimport { Button, Input, Label, PasswordInput, StyledLink } from \"@stackframe/stack-ui\";\nimport { useState } from \"react\";\nimport { yupObject, yupString, yupNumber, yupBoolean, yupArray, yupMixed } from \"@stackframe/stack-shared/dist/schema-fields\";\nimport { KnownErrors } from \"@stackframe/stack-shared\";\n\nconst schema = yupObject({\n email: yupString().email('Please enter a valid email').required('Please enter your email'),\n password: yupString().required('Please enter your password')\n});\n\nexport function CredentialSignIn() {\n const { register, handleSubmit, setError, formState: { errors } } = useForm({\n resolver: yupResolver(schema)\n });\n const app = useStackApp();\n const [loading, setLoading] = useState(false);\n\n const onSubmit = async (data: yup.InferType<typeof schema>) => {\n setLoading(true);\n\n try {\n const { email, password } = data;\n const error = await app.signInWithCredential({\n email,\n password,\n });\n setError('email', { type: 'manual', message: error?.message });\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\">Email</Label>\n <Input\n id=\"email\"\n type=\"email\"\n {...register('email')}\n />\n <FormWarningText text={errors.email?.message?.toString()} />\n\n <Label htmlFor=\"password\" className=\"mt-4 mb-1\">Password</Label>\n <PasswordInput\n id=\"password\"\n {...register('password')}\n />\n <FormWarningText text={errors.password?.message?.toString()} />\n\n <StyledLink href={app.urls.forgotPassword} className=\"mt-1 text-sm\">\n Forgot password?\n </StyledLink>\n\n <Button type=\"submit\" className=\"mt-6\" loading={loading}>\n Sign In\n </Button>\n </form>\n );\n}\n"],"mappings":";;;AAEA,SAAS,eAAe;AACxB,SAAS,mBAAmB;AAE5B,SAAS,uBAAuB;AAChC,SAAS,mBAAmB;AAC5B,SAAS,kCAAkC;AAC3C,SAAS,QAAQ,OAAO,OAAO,eAAe,kBAAkB;AAChE,SAAS,gBAAgB;AACzB,SAAS,WAAW,iBAA4D;AA+B5E,SAKE,KALF;AA5BJ,IAAM,SAAS,UAAU;AAAA,EACvB,OAAO,UAAU,EAAE,MAAM,4BAA4B,EAAE,SAAS,yBAAyB;AAAA,EACzF,UAAU,UAAU,EAAE,SAAS,4BAA4B;AAC7D,CAAC;AAEM,SAAS,mBAAmB;AACjC,QAAM,EAAE,UAAU,cAAc,UAAU,WAAW,EAAE,OAAO,EAAE,IAAI,QAAQ;AAAA,IAC1E,UAAU,YAAY,MAAM;AAAA,EAC9B,CAAC;AACD,QAAM,MAAM,YAAY;AACxB,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAE5C,QAAM,WAAW,OAAO,SAAuC;AAC7D,eAAW,IAAI;AAEf,QAAI;AACF,YAAM,EAAE,OAAO,SAAS,IAAI;AAC5B,YAAM,QAAQ,MAAM,IAAI,qBAAqB;AAAA,QAC3C;AAAA,QACA;AAAA,MACF,CAAC;AACD,eAAS,SAAS,EAAE,MAAM,UAAU,SAAS,OAAO,QAAQ,CAAC;AAAA,IAC/D,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,mBAAK;AAAA,QAC7C;AAAA,UAAC;AAAA;AAAA,YACC,IAAG;AAAA,YACH,MAAK;AAAA,YACJ,GAAG,SAAS,OAAO;AAAA;AAAA,QACtB;AAAA,QACA,oBAAC,mBAAgB,MAAM,OAAO,OAAO,SAAS,SAAS,GAAG;AAAA,QAE1D,oBAAC,SAAM,SAAQ,YAAW,WAAU,aAAY,sBAAQ;AAAA,QACxD;AAAA,UAAC;AAAA;AAAA,YACC,IAAG;AAAA,YACF,GAAG,SAAS,UAAU;AAAA;AAAA,QACzB;AAAA,QACA,oBAAC,mBAAgB,MAAM,OAAO,UAAU,SAAS,SAAS,GAAG;AAAA,QAE7D,oBAAC,cAAW,MAAM,IAAI,KAAK,gBAAgB,WAAU,gBAAe,8BAEpE;AAAA,QAEA,oBAAC,UAAO,MAAK,UAAS,WAAU,QAAO,SAAkB,qBAEzD;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use client";
|
|
3
|
+
|
|
4
|
+
// src/components/elements/sidebar-layout.tsx
|
|
5
|
+
import { Button, Typography, cn } from "@stackframe/stack-ui";
|
|
6
|
+
import { XIcon } from "lucide-react";
|
|
7
|
+
import React from "react";
|
|
8
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
function SidebarNavItem(props) {
|
|
10
|
+
return /* @__PURE__ */ jsxs(
|
|
11
|
+
Button,
|
|
12
|
+
{
|
|
13
|
+
variant: "ghost",
|
|
14
|
+
size: "sm",
|
|
15
|
+
className: cn(
|
|
16
|
+
props.selected && "bg-muted",
|
|
17
|
+
"justify-start text-md text-zinc-800 dark:text-zinc-300 px-2"
|
|
18
|
+
),
|
|
19
|
+
onClick: props.onClick,
|
|
20
|
+
children: [
|
|
21
|
+
props.item.icon && /* @__PURE__ */ jsx(props.item.icon, { className: "mr-2 h-4 w-4" }),
|
|
22
|
+
props.item.title
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
function SidebarLayout(props) {
|
|
28
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
29
|
+
/* @__PURE__ */ jsx("div", { className: "hidden sm:flex", children: /* @__PURE__ */ jsx(DesktopLayout, { items: props.items, title: props.title }) }),
|
|
30
|
+
/* @__PURE__ */ jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsx(MobileLayout, { items: props.items, title: props.title }) })
|
|
31
|
+
] });
|
|
32
|
+
}
|
|
33
|
+
function DesktopLayout(props) {
|
|
34
|
+
const [selectedIndex, setSelectedIndex] = React.useState(0);
|
|
35
|
+
const currentItem = props.items[selectedIndex];
|
|
36
|
+
return /* @__PURE__ */ jsxs("div", { className: "stack-scope flex p-2 w-full", children: [
|
|
37
|
+
/* @__PURE__ */ jsxs("div", { className: "flex w-[200px] border-r flex-col items-stretch gap-2 p-2", children: [
|
|
38
|
+
props.title && /* @__PURE__ */ jsx("div", { className: "mb-2 ml-2", children: /* @__PURE__ */ jsx(Typography, { type: "h2", className: "text-lg font-semibold text-zinc-800 dark:text-zinc-300", children: props.title }) }),
|
|
39
|
+
props.items.map((item, index) => /* @__PURE__ */ jsx(
|
|
40
|
+
SidebarNavItem,
|
|
41
|
+
{
|
|
42
|
+
item,
|
|
43
|
+
onClick: () => setSelectedIndex(index),
|
|
44
|
+
selected: index === selectedIndex
|
|
45
|
+
},
|
|
46
|
+
index
|
|
47
|
+
))
|
|
48
|
+
] }),
|
|
49
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col gap-4 py-2 px-4", children: [
|
|
50
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
51
|
+
/* @__PURE__ */ jsx(Typography, { type: "h4", children: currentItem.title }),
|
|
52
|
+
currentItem.description && /* @__PURE__ */ jsx(Typography, { variant: "secondary", type: "label", children: currentItem.description })
|
|
53
|
+
] }),
|
|
54
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1", children: currentItem.content })
|
|
55
|
+
] })
|
|
56
|
+
] });
|
|
57
|
+
}
|
|
58
|
+
function MobileLayout(props) {
|
|
59
|
+
const [selectedIndex, setSelectedIndex] = React.useState(null);
|
|
60
|
+
if (selectedIndex === null) {
|
|
61
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 p-2", children: [
|
|
62
|
+
props.title && /* @__PURE__ */ jsx("div", { className: "mb-2 ml-2", children: /* @__PURE__ */ jsx(Typography, { type: "h2", className: "text-lg font-semibold text-zinc-800 dark:text-zinc-300", children: props.title }) }),
|
|
63
|
+
props.items.map((item, index) => /* @__PURE__ */ jsx(
|
|
64
|
+
SidebarNavItem,
|
|
65
|
+
{
|
|
66
|
+
item,
|
|
67
|
+
onClick: () => setSelectedIndex(index),
|
|
68
|
+
selected: false
|
|
69
|
+
},
|
|
70
|
+
index
|
|
71
|
+
))
|
|
72
|
+
] });
|
|
73
|
+
} else {
|
|
74
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col gap-4 py-2 px-4", children: [
|
|
75
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
76
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
|
|
77
|
+
/* @__PURE__ */ jsx(Typography, { type: "h4", children: props.items[selectedIndex].title }),
|
|
78
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon", onClick: () => setSelectedIndex(null), children: /* @__PURE__ */ jsx(XIcon, { className: "h-5 w-5" }) })
|
|
79
|
+
] }),
|
|
80
|
+
props.items[selectedIndex].description && /* @__PURE__ */ jsx(Typography, { variant: "secondary", type: "label", children: props.items[selectedIndex].description })
|
|
81
|
+
] }),
|
|
82
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1", children: props.items[selectedIndex].content })
|
|
83
|
+
] });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
export {
|
|
87
|
+
SidebarLayout,
|
|
88
|
+
SidebarNavItem
|
|
89
|
+
};
|
|
90
|
+
//# sourceMappingURL=sidebar-layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/elements/sidebar-layout.tsx"],"sourcesContent":["'use client';\n\nimport { Button, Typography, cn } from '@stackframe/stack-ui';\nimport { ArrowLeft, LucideIcon, XIcon } from 'lucide-react';\nimport React, { ReactNode } from 'react';\n\ntype Item = {\n title: React.ReactNode,\n description?: React.ReactNode,\n icon?: LucideIcon,\n content: React.ReactNode,\n}\n\nexport function SidebarNavItem(props: { item: Item, selected: boolean, onClick: () => void }) {\n return (\n <Button\n variant='ghost'\n size='sm'\n className={cn(\n props.selected && \"bg-muted\",\n \"justify-start text-md text-zinc-800 dark:text-zinc-300 px-2\",\n )}\n onClick={props.onClick}\n >\n {props.item.icon && <props.item.icon className=\"mr-2 h-4 w-4\" />}\n {props.item.title}\n </Button>\n );\n}\n\nexport function SidebarLayout(props: { items: Item[], title?: ReactNode }) {\n return (\n <>\n <div className=\"hidden sm:flex\">\n <DesktopLayout items={props.items} title={props.title} />\n </div>\n <div className=\"sm:hidden\">\n <MobileLayout items={props.items} title={props.title} />\n </div>\n </>\n );\n}\n\nfunction DesktopLayout(props: { items: Item[], title?: ReactNode }) {\n const [selectedIndex, setSelectedIndex] = React.useState(0);\n const currentItem = props.items[selectedIndex];\n\n return (\n <div className=\"stack-scope flex p-2 w-full\">\n <div className=\"flex w-[200px] border-r flex-col items-stretch gap-2 p-2\">\n {props.title && <div className='mb-2 ml-2'>\n <Typography type='h2' className=\"text-lg font-semibold text-zinc-800 dark:text-zinc-300\">{props.title}</Typography>\n </div>}\n\n {props.items.map((item, index) => (\n <SidebarNavItem\n key={index}\n item={item}\n onClick={() => setSelectedIndex(index)}\n selected={index === selectedIndex}\n />\n ))}\n </div>\n <div className=\"flex-1 flex flex-col gap-4 py-2 px-4\">\n <div className='mb-4'>\n <Typography type='h4'>{currentItem.title}</Typography>\n {currentItem.description && <Typography variant='secondary' type='label'>{currentItem.description}</Typography>}\n </div>\n <div className='flex-1'>\n {currentItem.content}\n </div>\n </div>\n </div>\n );\n}\n\nfunction MobileLayout(props: { items: Item[], title?: ReactNode }) {\n const [selectedIndex, setSelectedIndex] = React.useState<number | null>(null);\n\n if (selectedIndex === null) {\n return (\n <div className=\"flex flex-col gap-2 p-2\">\n {props.title && <div className='mb-2 ml-2'>\n <Typography type='h2' className=\"text-lg font-semibold text-zinc-800 dark:text-zinc-300\">{props.title}</Typography>\n </div>}\n\n {props.items.map((item, index) => (\n <SidebarNavItem\n key={index}\n item={item}\n onClick={() => setSelectedIndex(index)}\n selected={false}\n />\n ))}\n </div>\n );\n } else {\n return (\n <div className=\"flex-1 flex flex-col gap-4 py-2 px-4\">\n <div className='flex flex-col'>\n <div className='flex justify-between'>\n <Typography type='h4'>{props.items[selectedIndex].title}</Typography>\n <Button variant='ghost' size='icon' onClick={() => setSelectedIndex(null)}>\n <XIcon className='h-5 w-5' />\n </Button>\n </div>\n {props.items[selectedIndex].description && <Typography variant='secondary' type='label'>{props.items[selectedIndex].description}</Typography>}\n </div>\n <div className='flex-1'>\n {props.items[selectedIndex].content}\n </div>\n </div>\n );\n }\n}"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/elements/user-avatar.tsx"],"sourcesContent":["import { UserRound } from \"lucide-react\";\nimport { User } from \"../../lib/stack-app\";\nimport { Avatar, AvatarFallback, AvatarImage } from \"@stackframe/stack-ui\";\n\nexport function UserAvatar(props: {
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/elements/user-avatar.tsx"],"sourcesContent":["import { UserRound } from \"lucide-react\";\nimport { User } from \"../../lib/stack-app\";\nimport { Avatar, AvatarFallback, AvatarImage } from \"@stackframe/stack-ui\";\n\nexport function UserAvatar(props: {\n size?: number,\n user?: {\n profileImageUrl?: string | null,\n displayName?: string | null,\n primaryEmail?: string | null,\n } | null,\n}) {\n const user = props.user;\n return (\n <Avatar style={{ height: props.size || '34px', width: props.size || '34px' }}>\n <AvatarImage src={user?.profileImageUrl || ''} />\n <AvatarFallback>\n {user ?\n <div className='font-medium'>\n {(user.displayName || user.primaryEmail)?.slice(0, 2).toUpperCase()}\n </div> :\n <UserRound className=\"h-5 w-5 text-zinc-500\" />}\n </AvatarFallback>\n </Avatar>\n );\n}\n"],"mappings":";AAAA,SAAS,iBAAiB;AAE1B,SAAS,QAAQ,gBAAgB,mBAAmB;AAYhD,SACE,KADF;AAVG,SAAS,WAAW,OAOxB;AACD,QAAM,OAAO,MAAM;AACnB,SACE,qBAAC,UAAO,OAAO,EAAE,QAAQ,MAAM,QAAQ,QAAQ,OAAO,MAAM,QAAQ,OAAO,GACzE;AAAA,wBAAC,eAAY,KAAK,MAAM,mBAAmB,IAAI;AAAA,IAC/C,oBAAC,kBACE,iBACC,oBAAC,SAAI,WAAU,eACX,gBAAK,eAAe,KAAK,eAAe,MAAM,GAAG,CAAC,EAAE,YAAY,GACpE,IACA,oBAAC,aAAU,WAAU,yBAAwB,GACjD;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -32,6 +32,14 @@ function PredefinedMessageCard({
|
|
|
32
32
|
primaryButton = "Sign in";
|
|
33
33
|
break;
|
|
34
34
|
}
|
|
35
|
+
case "signUpDisabled": {
|
|
36
|
+
title = "Sign up for new users is not enabled at the moment.";
|
|
37
|
+
primaryAction = () => stackApp.redirectToHome();
|
|
38
|
+
secondaryAction = () => stackApp.redirectToSignIn();
|
|
39
|
+
primaryButton = "Go to home";
|
|
40
|
+
secondaryButton = "Sign in";
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
35
43
|
case "emailSent": {
|
|
36
44
|
title = "Email sent!";
|
|
37
45
|
message = "If the user with this e-mail address exists, an e-mail was sent to your inbox. Make sure to check your spam folder.";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/message-cards/predefined-message-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { Typography } from \"@stackframe/stack-ui\";\nimport { useStackApp } from \"../..\";\nimport { MessageCard } from \"./message-card\";\n\nexport function PredefinedMessageCard({\n type,\n fullPage=false,\n}: {\n type: 'signedIn' | 'signedOut' | 'emailSent' | 'passwordReset' | 'emailVerified' | 'unknownError',\n fullPage?: boolean,\n}) {\n const stackApp = useStackApp();\n\n let title: string;\n let message: string | null = null;\n let primaryButton: string | null = null;\n let secondaryButton: string | null = null;\n let primaryAction: (() => Promise<void> | void) | null = null;\n let secondaryAction: (() => Promise<void> | void) | null = null;\n\n switch (type) {\n case 'signedIn': {\n title = \"You are already signed in\";\n primaryAction = () => stackApp.redirectToHome();\n secondaryAction = () => stackApp.redirectToSignOut();\n primaryButton = \"Go to home\";\n secondaryButton = \"Sign out\";\n break;\n }\n case 'signedOut': {\n title = \"You are not currently signed in.\";\n primaryAction = () => stackApp.redirectToSignIn();\n primaryButton = \"Sign in\";\n break;\n }\n case 'emailSent': {\n title = \"Email sent!\";\n message = 'If the user with this e-mail address exists, an e-mail was sent to your inbox. Make sure to check your spam folder.';\n primaryAction = () => stackApp.redirectToHome();\n primaryButton = \"Go to home\";\n break;\n }\n case 'passwordReset': {\n title = \"Password reset successfully!\";\n message = 'Your password has been reset. You can now sign in with your new password.';\n primaryAction = () => stackApp.redirectToSignIn({ noRedirectBack: true });\n primaryButton = \"Sign in\";\n break;\n }\n case 'emailVerified': {\n title = \"Email verified!\";\n message = 'Your have successfully verified your email.';\n primaryAction = () => stackApp.redirectToSignIn({ noRedirectBack: true });\n primaryButton = \"Sign in\";\n break;\n }\n case 'unknownError': {\n title = \"An unknown error occurred\";\n message = 'Please try again and if the problem persists, contact support.';\n primaryAction = () => stackApp.redirectToHome();\n primaryButton = \"Go to home\";\n break;\n }\n }\n\n return (\n <MessageCard\n title={title}\n fullPage={fullPage}\n primaryButtonText={primaryButton}\n primaryAction={primaryAction}\n secondaryButtonText={secondaryButton || undefined}\n secondaryAction={secondaryAction || undefined}\n >\n {message && <Typography>{message}</Typography>}\n </MessageCard>\n );\n}\n"],"mappings":";;;AAEA,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,mBAAmB;
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/message-cards/predefined-message-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { Typography } from \"@stackframe/stack-ui\";\nimport { useStackApp } from \"../..\";\nimport { MessageCard } from \"./message-card\";\n\nexport function PredefinedMessageCard({\n type,\n fullPage=false,\n}: {\n type: 'signedIn' | 'signedOut' | 'emailSent' | 'passwordReset' | 'emailVerified' | 'unknownError' | 'signUpDisabled',\n fullPage?: boolean,\n}) {\n const stackApp = useStackApp();\n\n let title: string;\n let message: string | null = null;\n let primaryButton: string | null = null;\n let secondaryButton: string | null = null;\n let primaryAction: (() => Promise<void> | void) | null = null;\n let secondaryAction: (() => Promise<void> | void) | null = null;\n\n switch (type) {\n case 'signedIn': {\n title = \"You are already signed in\";\n primaryAction = () => stackApp.redirectToHome();\n secondaryAction = () => stackApp.redirectToSignOut();\n primaryButton = \"Go to home\";\n secondaryButton = \"Sign out\";\n break;\n }\n case 'signedOut': {\n title = \"You are not currently signed in.\";\n primaryAction = () => stackApp.redirectToSignIn();\n primaryButton = \"Sign in\";\n break;\n }\n case 'signUpDisabled': {\n title = \"Sign up for new users is not enabled at the moment.\";\n primaryAction = () => stackApp.redirectToHome();\n secondaryAction = () => stackApp.redirectToSignIn();\n primaryButton = \"Go to home\";\n secondaryButton = \"Sign in\";\n break;\n }\n case 'emailSent': {\n title = \"Email sent!\";\n message = 'If the user with this e-mail address exists, an e-mail was sent to your inbox. Make sure to check your spam folder.';\n primaryAction = () => stackApp.redirectToHome();\n primaryButton = \"Go to home\";\n break;\n }\n case 'passwordReset': {\n title = \"Password reset successfully!\";\n message = 'Your password has been reset. You can now sign in with your new password.';\n primaryAction = () => stackApp.redirectToSignIn({ noRedirectBack: true });\n primaryButton = \"Sign in\";\n break;\n }\n case 'emailVerified': {\n title = \"Email verified!\";\n message = 'Your have successfully verified your email.';\n primaryAction = () => stackApp.redirectToSignIn({ noRedirectBack: true });\n primaryButton = \"Sign in\";\n break;\n }\n case 'unknownError': {\n title = \"An unknown error occurred\";\n message = 'Please try again and if the problem persists, contact support.';\n primaryAction = () => stackApp.redirectToHome();\n primaryButton = \"Go to home\";\n break;\n }\n }\n\n return (\n <MessageCard\n title={title}\n fullPage={fullPage}\n primaryButtonText={primaryButton}\n primaryAction={primaryAction}\n secondaryButtonText={secondaryButton || undefined}\n secondaryAction={secondaryAction || undefined}\n >\n {message && <Typography>{message}</Typography>}\n </MessageCard>\n );\n}\n"],"mappings":";;;AAEA,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,mBAAmB;AAgFV;AA9EX,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA,WAAS;AACX,GAGG;AACD,QAAM,WAAW,YAAY;AAE7B,MAAI;AACJ,MAAI,UAAyB;AAC7B,MAAI,gBAA+B;AACnC,MAAI,kBAAiC;AACrC,MAAI,gBAAqD;AACzD,MAAI,kBAAuD;AAE3D,UAAQ,MAAM;AAAA,IACZ,KAAK,YAAY;AACf,cAAQ;AACR,sBAAgB,MAAM,SAAS,eAAe;AAC9C,wBAAkB,MAAM,SAAS,kBAAkB;AACnD,sBAAgB;AAChB,wBAAkB;AAClB;AAAA,IACF;AAAA,IACA,KAAK,aAAa;AAChB,cAAQ;AACR,sBAAgB,MAAM,SAAS,iBAAiB;AAChD,sBAAgB;AAChB;AAAA,IACF;AAAA,IACA,KAAK,kBAAkB;AACrB,cAAQ;AACR,sBAAgB,MAAM,SAAS,eAAe;AAC9C,wBAAkB,MAAM,SAAS,iBAAiB;AAClD,sBAAgB;AAChB,wBAAkB;AAClB;AAAA,IACF;AAAA,IACA,KAAK,aAAa;AAChB,cAAQ;AACR,gBAAU;AACV,sBAAgB,MAAM,SAAS,eAAe;AAC9C,sBAAgB;AAChB;AAAA,IACF;AAAA,IACA,KAAK,iBAAiB;AACpB,cAAQ;AACR,gBAAU;AACV,sBAAgB,MAAM,SAAS,iBAAiB,EAAE,gBAAgB,KAAK,CAAC;AACxE,sBAAgB;AAChB;AAAA,IACF;AAAA,IACA,KAAK,iBAAiB;AACpB,cAAQ;AACR,gBAAU;AACV,sBAAgB,MAAM,SAAS,iBAAiB,EAAE,gBAAgB,KAAK,CAAC;AACxE,sBAAgB;AAChB;AAAA,IACF;AAAA,IACA,KAAK,gBAAgB;AACnB,cAAQ;AACR,gBAAU;AACV,sBAAgB,MAAM,SAAS,eAAe;AAC9C,sBAAgB;AAChB;AAAA,IACF;AAAA,EACF;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,mBAAmB;AAAA,MACnB;AAAA,MACA,qBAAqB,mBAAmB;AAAA,MACxC,iBAAiB,mBAAmB;AAAA,MAEnC,qBAAW,oBAAC,cAAY,mBAAQ;AAAA;AAAA,EACnC;AAEJ;","names":[]}
|
|
@@ -4,20 +4,23 @@
|
|
|
4
4
|
// src/components/selected-team-switcher.tsx
|
|
5
5
|
import { runAsynchronouslyWithAlert } from "@stackframe/stack-shared/dist/utils/promises";
|
|
6
6
|
import {
|
|
7
|
+
Button,
|
|
7
8
|
Select,
|
|
8
9
|
SelectContent,
|
|
9
10
|
SelectGroup,
|
|
10
11
|
SelectItem,
|
|
11
12
|
SelectLabel,
|
|
13
|
+
SelectSeparator,
|
|
12
14
|
SelectTrigger,
|
|
13
15
|
SelectValue,
|
|
14
16
|
Typography
|
|
15
17
|
} from "@stackframe/stack-ui";
|
|
16
18
|
import { useRouter } from "next/navigation";
|
|
17
19
|
import { useEffect, useMemo } from "react";
|
|
18
|
-
import { useUser } from "..";
|
|
20
|
+
import { useStackApp, useUser } from "..";
|
|
19
21
|
import Image from "next/image";
|
|
20
|
-
import {
|
|
22
|
+
import { PlusCircle, Settings } from "lucide-react";
|
|
23
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
21
24
|
function TeamIcon(props) {
|
|
22
25
|
if (props.team.profileImageUrl) {
|
|
23
26
|
return /* @__PURE__ */ jsx("div", { className: "w-6 h-6 mr-2 rounded bg-gray-200 overflow-hidden", children: /* @__PURE__ */ jsx(Image, { src: props.team.profileImageUrl, alt: props.team.displayName, className: "w-6 h-6" }) });
|
|
@@ -26,7 +29,9 @@ function TeamIcon(props) {
|
|
|
26
29
|
}
|
|
27
30
|
}
|
|
28
31
|
function SelectedTeamSwitcher(props) {
|
|
32
|
+
const app = useStackApp();
|
|
29
33
|
const user = useUser();
|
|
34
|
+
const project = app.useProject();
|
|
30
35
|
const router = useRouter();
|
|
31
36
|
const selectedTeam = user?.selectedTeam || props.selectedTeam;
|
|
32
37
|
const rawTeams = user?.useTeams();
|
|
@@ -57,11 +62,38 @@ function SelectedTeamSwitcher(props) {
|
|
|
57
62
|
children: [
|
|
58
63
|
/* @__PURE__ */ jsx(SelectTrigger, { className: "stack-scope", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select team" }) }),
|
|
59
64
|
/* @__PURE__ */ jsxs(SelectContent, { className: "stack-scope", children: [
|
|
60
|
-
|
|
61
|
-
/* @__PURE__ */ jsx(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
user?.selectedTeam ? /* @__PURE__ */ jsxs(SelectGroup, { children: [
|
|
66
|
+
/* @__PURE__ */ jsx(SelectLabel, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
67
|
+
"Current team",
|
|
68
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon", className: "h-6 w-6", onClick: () => router.push(`${app.urls.handler}/team-settings/${user.selectedTeam?.id}`), children: /* @__PURE__ */ jsx(Settings, { className: "h-4 w-4" }) })
|
|
69
|
+
] }) }),
|
|
70
|
+
/* @__PURE__ */ jsx(SelectItem, { value: user.selectedTeam.id, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
|
|
71
|
+
/* @__PURE__ */ jsx(TeamIcon, { team: user.selectedTeam }),
|
|
72
|
+
/* @__PURE__ */ jsx(Typography, { children: user.selectedTeam.displayName })
|
|
73
|
+
] }) })
|
|
74
|
+
] }) : void 0,
|
|
75
|
+
teams?.length ? /* @__PURE__ */ jsxs(SelectGroup, { children: [
|
|
76
|
+
/* @__PURE__ */ jsx(SelectLabel, { children: "Other teams" }),
|
|
77
|
+
teams.filter((team) => team.id !== user?.selectedTeam?.id).map((team) => /* @__PURE__ */ jsx(SelectItem, { value: team.id, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
|
|
78
|
+
/* @__PURE__ */ jsx(TeamIcon, { team }),
|
|
79
|
+
/* @__PURE__ */ jsx(Typography, { children: team.displayName })
|
|
80
|
+
] }) }, team.id))
|
|
81
|
+
] }) : /* @__PURE__ */ jsx(SelectGroup, { children: /* @__PURE__ */ jsx(SelectLabel, { children: "No teams yet" }) }),
|
|
82
|
+
project.config.clientTeamCreationEnabled && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
83
|
+
/* @__PURE__ */ jsx(SelectSeparator, {}),
|
|
84
|
+
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(
|
|
85
|
+
Button,
|
|
86
|
+
{
|
|
87
|
+
onClick: () => router.push(app.urls.teamCreation),
|
|
88
|
+
className: "w-full",
|
|
89
|
+
variant: "ghost",
|
|
90
|
+
children: [
|
|
91
|
+
/* @__PURE__ */ jsx(PlusCircle, { className: "mr-2 h-4 w-4" }),
|
|
92
|
+
" Create a team"
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
) })
|
|
96
|
+
] })
|
|
65
97
|
] })
|
|
66
98
|
]
|
|
67
99
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/selected-team-switcher.tsx"],"sourcesContent":["'use client';\nimport { runAsynchronouslyWithAlert } from \"@stackframe/stack-shared/dist/utils/promises\";\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectTrigger,\n SelectValue,\n Typography\n} from \"@stackframe/stack-ui\";\nimport { useRouter } from \"next/navigation\";\nimport { useEffect, useMemo } from \"react\";\nimport { Team, useUser } from \"..\";\nimport Image from \"next/image\";\n\ntype SelectedTeamSwitcherProps = {\n urlMap?: (team: Team) => string,\n selectedTeam?: Team,\n noUpdateSelectedTeam?: boolean,\n};\n\nfunction TeamIcon(props: { team: Team }) {\n if (props.team.profileImageUrl) {\n return (\n <div className=\"w-6 h-6 mr-2 rounded bg-gray-200 overflow-hidden\">\n <Image src={props.team.profileImageUrl} alt={props.team.displayName} className=\"w-6 h-6\" />\n </div>\n );\n } else {\n return (\n <div className=\"flex items-center justify-center w-6 h-6 mr-2 rounded bg-gray-200\">\n <Typography>{props.team.displayName.slice(0, 1).toUpperCase()}</Typography>\n </div>\n );\n }\n}\n\nexport function SelectedTeamSwitcher(props: SelectedTeamSwitcherProps) {\n const user = useUser();\n const router = useRouter();\n const selectedTeam = user?.selectedTeam || props.selectedTeam;\n const rawTeams = user?.useTeams();\n const teams = useMemo(() => rawTeams?.sort((a, b) => b.id === selectedTeam?.id ? 1 : -1), [rawTeams, selectedTeam]);\n\n useEffect(() => {\n if (!props.noUpdateSelectedTeam && props.selectedTeam) {\n runAsynchronouslyWithAlert(user?.setSelectedTeam(props.selectedTeam));\n }\n }, [props.noUpdateSelectedTeam, props.selectedTeam]);\n\n return (\n <Select\n value={selectedTeam?.id}\n onValueChange={(value) => {\n runAsynchronouslyWithAlert(async () => {\n const team = teams?.find(team => team.id === value);\n if (!team) {\n throw new Error('Team not found, this should not happen');\n }\n\n if (!props.noUpdateSelectedTeam) {\n await user?.setSelectedTeam(team);\n }\n if (props.urlMap) {\n router.push(props.urlMap(team));\n }\n });\n }}\n >\n <SelectTrigger className=\"stack-scope\">\n <SelectValue placeholder=\"Select team\"/>\n </SelectTrigger>\n <SelectContent className=\"stack-scope\">\n {
|
|
1
|
+
{"version":3,"sources":["../../../src/components/selected-team-switcher.tsx"],"sourcesContent":["'use client';\nimport { runAsynchronouslyWithAlert } from \"@stackframe/stack-shared/dist/utils/promises\";\nimport {\n Button,\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n Typography\n} from \"@stackframe/stack-ui\";\nimport { useRouter } from \"next/navigation\";\nimport { useEffect, useMemo } from \"react\";\nimport { Team, useStackApp, useUser } from \"..\";\nimport Image from \"next/image\";\nimport { PlusCircle, Settings } from \"lucide-react\";\n\ntype SelectedTeamSwitcherProps = {\n urlMap?: (team: Team) => string,\n selectedTeam?: Team,\n noUpdateSelectedTeam?: boolean,\n};\n\nfunction TeamIcon(props: { team: Team }) {\n if (props.team.profileImageUrl) {\n return (\n <div className=\"w-6 h-6 mr-2 rounded bg-gray-200 overflow-hidden\">\n <Image src={props.team.profileImageUrl} alt={props.team.displayName} className=\"w-6 h-6\" />\n </div>\n );\n } else {\n return (\n <div className=\"flex items-center justify-center w-6 h-6 mr-2 rounded bg-gray-200\">\n <Typography>{props.team.displayName.slice(0, 1).toUpperCase()}</Typography>\n </div>\n );\n }\n}\n\nexport function SelectedTeamSwitcher(props: SelectedTeamSwitcherProps) {\n const app = useStackApp();\n const user = useUser();\n const project = app.useProject();\n const router = useRouter();\n const selectedTeam = user?.selectedTeam || props.selectedTeam;\n const rawTeams = user?.useTeams();\n const teams = useMemo(() => rawTeams?.sort((a, b) => b.id === selectedTeam?.id ? 1 : -1), [rawTeams, selectedTeam]);\n\n useEffect(() => {\n if (!props.noUpdateSelectedTeam && props.selectedTeam) {\n runAsynchronouslyWithAlert(user?.setSelectedTeam(props.selectedTeam));\n }\n }, [props.noUpdateSelectedTeam, props.selectedTeam]);\n\n return (\n <Select\n value={selectedTeam?.id}\n onValueChange={(value) => {\n runAsynchronouslyWithAlert(async () => {\n const team = teams?.find(team => team.id === value);\n if (!team) {\n throw new Error('Team not found, this should not happen');\n }\n\n if (!props.noUpdateSelectedTeam) {\n await user?.setSelectedTeam(team);\n }\n if (props.urlMap) {\n router.push(props.urlMap(team));\n }\n });\n }}\n >\n <SelectTrigger className=\"stack-scope\">\n <SelectValue placeholder=\"Select team\"/>\n </SelectTrigger>\n <SelectContent className=\"stack-scope\">\n {user?.selectedTeam ? <SelectGroup>\n <SelectLabel>\n <div className=\"flex items-center justify-between\">\n Current team\n <Button variant='ghost' size='icon' className=\"h-6 w-6\" onClick={() => router.push(`${app.urls.handler}/team-settings/${user.selectedTeam?.id}`)}>\n <Settings className=\"h-4 w-4\"/>\n </Button>\n </div>\n </SelectLabel>\n <SelectItem value={user.selectedTeam.id}>\n <div className=\"flex items-center\">\n <TeamIcon team={user.selectedTeam} />\n <Typography>{user.selectedTeam.displayName}</Typography>\n </div>\n </SelectItem>\n </SelectGroup> : undefined}\n\n {teams?.length ?\n <SelectGroup>\n <SelectLabel>Other teams</SelectLabel>\n {teams.filter(team => team.id !== user?.selectedTeam?.id)\n .map(team => (\n <SelectItem value={team.id} key={team.id}>\n <div className=\"flex items-center\">\n <TeamIcon team={team} />\n <Typography>{team.displayName}</Typography>\n </div>\n </SelectItem>\n ))}\n </SelectGroup> :\n <SelectGroup>\n <SelectLabel>No teams yet</SelectLabel>\n </SelectGroup>}\n\n {project.config.clientTeamCreationEnabled && <>\n <SelectSeparator/>\n <div>\n <Button\n onClick={() => router.push(app.urls.teamCreation)}\n className=\"w-full\"\n variant='ghost'\n >\n <PlusCircle className=\"mr-2 h-4 w-4\"/> Create a team\n </Button>\n </div>\n </>}\n </SelectContent>\n </Select>\n );\n}\n"],"mappings":"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","names":["team"]}
|