cauthy-auth 0.30.0 → 0.32.0
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/README.md +50 -5
- package/dist/{cauthy-BXgsZ-Um.d.mts → cauthy-2jtP2LVQ.d.mts} +1 -1
- package/dist/{cauthy-CHENs452.d.ts → cauthy-CKfvvv_i.d.ts} +1 -1
- package/dist/cli.js +8 -5
- package/dist/client.d.mts +47 -6
- package/dist/client.d.ts +47 -6
- package/dist/client.js +16 -2
- package/dist/client.js.map +1 -1
- package/dist/client.mjs +16 -2
- package/dist/client.mjs.map +1 -1
- package/dist/express.d.mts +2 -2
- package/dist/express.d.ts +2 -2
- package/dist/fastify.d.mts +2 -2
- package/dist/fastify.d.ts +2 -2
- package/dist/hono.d.mts +2 -2
- package/dist/hono.d.ts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +64 -21
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +64 -21
- package/dist/index.mjs.map +1 -1
- package/dist/next.d.mts +2 -2
- package/dist/next.d.ts +2 -2
- package/dist/react.d.mts +339 -31
- package/dist/react.d.ts +339 -31
- package/dist/react.js +616 -225
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +610 -230
- package/dist/react.mjs.map +1 -1
- package/dist/styles.css +8 -0
- package/dist/svelte.d.mts +2 -2
- package/dist/svelte.d.ts +2 -2
- package/dist/svelte.js +16 -2
- package/dist/svelte.js.map +1 -1
- package/dist/svelte.mjs +16 -2
- package/dist/svelte.mjs.map +1 -1
- package/dist/{system-0mHrdAgO.d.mts → system-BrrJsrFW.d.mts} +14 -0
- package/dist/{system-BIYbS7h2.d.ts → system-BvvoNs2y.d.ts} +14 -0
- package/dist/vue.d.mts +2 -2
- package/dist/vue.d.ts +2 -2
- package/dist/vue.js +16 -2
- package/dist/vue.js.map +1 -1
- package/dist/vue.mjs +16 -2
- package/dist/vue.mjs.map +1 -1
- package/package.json +2 -1
package/dist/react.js
CHANGED
|
@@ -21,11 +21,22 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
// src/react.tsx
|
|
22
22
|
var react_exports = {};
|
|
23
23
|
__export(react_exports, {
|
|
24
|
+
AcceptInvite: () => AcceptInvite,
|
|
24
25
|
Account: () => Account,
|
|
26
|
+
AccountAgents: () => AccountAgents,
|
|
27
|
+
AccountEmail: () => AccountEmail,
|
|
28
|
+
AccountLinked: () => AccountLinked,
|
|
29
|
+
AccountPasskeys: () => AccountPasskeys,
|
|
30
|
+
AccountPassword: () => AccountPassword,
|
|
31
|
+
AccountPhone: () => AccountPhone,
|
|
32
|
+
AccountProfile: () => AccountProfile,
|
|
33
|
+
AccountSecondStep: () => AccountSecondStep,
|
|
34
|
+
AccountSessions: () => AccountSessions,
|
|
25
35
|
CauthyProvider: () => CauthyProvider,
|
|
26
36
|
ForgotPassword: () => ForgotPassword,
|
|
27
37
|
GoogleOneTap: () => GoogleOneTap,
|
|
28
38
|
OrganizationMembers: () => OrganizationMembers,
|
|
39
|
+
PendingTerms: () => PendingTerms,
|
|
29
40
|
ResetPassword: () => ResetPassword,
|
|
30
41
|
SignIn: () => SignIn,
|
|
31
42
|
SignUp: () => SignUp,
|
|
@@ -411,11 +422,11 @@ function createAuthClient(options = {}) {
|
|
|
411
422
|
if (res.ok) {
|
|
412
423
|
const m = await res.json();
|
|
413
424
|
if (m.password) policy = passwordPolicyOf(m.password);
|
|
414
|
-
return { providers: [], signUp: true, magicLink: false, passkey: false, ...m, ...policy ? { password: policy } : {}, passkeyHere: m.passkeyHere === true, passkeyOnCauthy: m.passkeyOnCauthy ?? m.passkey === true, sso: m.sso === true };
|
|
425
|
+
return { providers: [], signUp: true, magicLink: false, passkey: false, ...m, ...policy ? { password: policy } : {}, passwordSignIn: m.passwordSignIn !== false, passkeyHere: m.passkeyHere === true, passkeyOnCauthy: m.passkeyOnCauthy ?? m.passkey === true, sso: m.sso === true };
|
|
415
426
|
}
|
|
416
427
|
} catch {
|
|
417
428
|
}
|
|
418
|
-
return { providers: [], signUp: true, magicLink: false, passkey: false, passkeyHere: false, passkeyOnCauthy: false, sso: false };
|
|
429
|
+
return { providers: [], signUp: true, passwordSignIn: true, magicLink: false, passkey: false, passkeyHere: false, passkeyOnCauthy: false, sso: false };
|
|
419
430
|
}
|
|
420
431
|
async function ceremony(begin, finish, form, run, more = {}) {
|
|
421
432
|
const begun = await post(begin, form, null);
|
|
@@ -562,6 +573,20 @@ function createAuthClient(options = {}) {
|
|
|
562
573
|
forgotPassword: (f) => post("/forgot-password", { email: f.email }, checkEmail(f.email), f.captchaToken),
|
|
563
574
|
resetPassword: (f) => post("/reset-password", { token: f.token, password: f.password }, checkNewPassword(f.password, policy)),
|
|
564
575
|
verifyEmail: (f) => post("/verify-email", { token: f.token }, null),
|
|
576
|
+
async invitation(token) {
|
|
577
|
+
const bad = { ok: false, error: { code: "invalid_token", message: "This invitation is not valid, or it has expired." } };
|
|
578
|
+
if (typeof token !== "string" || token.trim() === "") return bad;
|
|
579
|
+
try {
|
|
580
|
+
const res = await doFetch(`${base}/invitation?token=${encodeURIComponent(token.trim())}`, { credentials: "same-origin", headers: { accept: "application/json" } });
|
|
581
|
+
const body = await res.json().catch(() => null);
|
|
582
|
+
if (res.ok && body?.invitation) return { ok: true, status: "ok", invitation: body.invitation };
|
|
583
|
+
const e = body?.error;
|
|
584
|
+
return { ok: false, error: e && typeof e.code === "string" ? { code: e.code, message: String(e.message ?? "") } : UNAVAILABLE };
|
|
585
|
+
} catch {
|
|
586
|
+
return { ok: false, error: UNAVAILABLE };
|
|
587
|
+
}
|
|
588
|
+
},
|
|
589
|
+
acceptInvitation: (token, password) => post("/invitation/accept", { token, password }, checkNewPassword(password, policy)),
|
|
565
590
|
signOut: () => post("/sign-out", {}, null),
|
|
566
591
|
organizations: {
|
|
567
592
|
async list(system) {
|
|
@@ -787,6 +812,7 @@ var TEXTS = {
|
|
|
787
812
|
removePhone: "Remove phone",
|
|
788
813
|
bySms: "SMS",
|
|
789
814
|
byWhatsapp: "WhatsApp",
|
|
815
|
+
channel: "Send codes by",
|
|
790
816
|
checkEmail: "Almost there: open the link we sent to confirm your address \u2014 it signs you in.",
|
|
791
817
|
backToSignIn: "Back to sign in",
|
|
792
818
|
emailMeALink: "Email me a sign-in link",
|
|
@@ -798,6 +824,13 @@ var TEXTS = {
|
|
|
798
824
|
passwordChanged: "Your password was changed. You can sign in with it now.",
|
|
799
825
|
confirming: "Confirming your address\u2026",
|
|
800
826
|
emailConfirmed: "Your address is confirmed. You can sign in now.",
|
|
827
|
+
invitedTo: "You've been invited to {workspace}",
|
|
828
|
+
invitedToOrganization: "You've been invited to {organization} on {workspace}",
|
|
829
|
+
invitedAs: "You will sign in as {email}.",
|
|
830
|
+
choosePassword: "Choose a password",
|
|
831
|
+
acceptInvite: "Accept and sign in",
|
|
832
|
+
openingInvitation: "Opening your invitation\u2026",
|
|
833
|
+
invitationInvalid: "This invitation is not valid: it was already used, or it has expired. Ask whoever invited you to send it again.",
|
|
801
834
|
profile: "Profile",
|
|
802
835
|
save: "Save",
|
|
803
836
|
saved: "Saved.",
|
|
@@ -869,6 +902,9 @@ var TEXTS = {
|
|
|
869
902
|
organizationDeleted: "{org} was deleted.",
|
|
870
903
|
yes: "Yes",
|
|
871
904
|
cancel: "Cancel",
|
|
905
|
+
termsChanged: "Our terms changed",
|
|
906
|
+
termsChangedHelp: "To go on, read and accept",
|
|
907
|
+
acceptTerms: "Accept",
|
|
872
908
|
errors: {
|
|
873
909
|
not_allowed: "Your role in this organization does not allow that.",
|
|
874
910
|
last_manager: "Somebody else must manage the members first: give that role to another member.",
|
|
@@ -912,7 +948,9 @@ var TEXTS = {
|
|
|
912
948
|
invalid_assertion: "Your company's answer could not be checked. Try again.",
|
|
913
949
|
provisioning_disabled: "Your company's sign-in worked, but this workspace has no account for you. Ask its admin to add you.",
|
|
914
950
|
connection_inactive: "Your company's sign-in is turned off for this workspace.",
|
|
915
|
-
invalid_grant: "That sign-in expired. Try again."
|
|
951
|
+
invalid_grant: "That sign-in expired. Try again.",
|
|
952
|
+
password_disabled: "This workspace does not sign in with a password. Use one of the other ways.",
|
|
953
|
+
passkeys_disabled: "Passkeys are turned off for this workspace."
|
|
916
954
|
}
|
|
917
955
|
},
|
|
918
956
|
es: {
|
|
@@ -954,6 +992,7 @@ var TEXTS = {
|
|
|
954
992
|
removePhone: "Quitar tel\xE9fono",
|
|
955
993
|
bySms: "SMS",
|
|
956
994
|
byWhatsapp: "WhatsApp",
|
|
995
|
+
channel: "Enviar los c\xF3digos por",
|
|
957
996
|
checkEmail: "Casi listo: abre el enlace que te enviamos para confirmar tu correo; te deja adentro.",
|
|
958
997
|
backToSignIn: "Volver a entrar",
|
|
959
998
|
emailMeALink: "Env\xEDame un enlace para entrar",
|
|
@@ -965,6 +1004,13 @@ var TEXTS = {
|
|
|
965
1004
|
passwordChanged: "Tu contrase\xF1a se cambi\xF3. Ya puedes entrar con ella.",
|
|
966
1005
|
confirming: "Confirmando tu correo\u2026",
|
|
967
1006
|
emailConfirmed: "Tu correo qued\xF3 confirmado. Ya puedes entrar.",
|
|
1007
|
+
invitedTo: "Te invitaron a {workspace}",
|
|
1008
|
+
invitedToOrganization: "Te invitaron a {organization} en {workspace}",
|
|
1009
|
+
invitedAs: "Vas a entrar como {email}.",
|
|
1010
|
+
choosePassword: "Elige una contrase\xF1a",
|
|
1011
|
+
acceptInvite: "Aceptar y entrar",
|
|
1012
|
+
openingInvitation: "Abriendo tu invitaci\xF3n\u2026",
|
|
1013
|
+
invitationInvalid: "Esta invitaci\xF3n no es v\xE1lida: ya se us\xF3 o venci\xF3. P\xEDdele a quien te invit\xF3 que te la env\xEDe de nuevo.",
|
|
968
1014
|
profile: "Perfil",
|
|
969
1015
|
save: "Guardar",
|
|
970
1016
|
saved: "Guardado.",
|
|
@@ -1036,6 +1082,9 @@ var TEXTS = {
|
|
|
1036
1082
|
organizationDeleted: "{org} qued\xF3 eliminada.",
|
|
1037
1083
|
yes: "S\xED",
|
|
1038
1084
|
cancel: "Cancelar",
|
|
1085
|
+
termsChanged: "Nuestros t\xE9rminos cambiaron",
|
|
1086
|
+
termsChangedHelp: "Para seguir, lee y acepta",
|
|
1087
|
+
acceptTerms: "Aceptar",
|
|
1039
1088
|
errors: {
|
|
1040
1089
|
not_allowed: "Tu rol en esta organizaci\xF3n no permite eso.",
|
|
1041
1090
|
last_manager: "Primero alguien m\xE1s debe administrar los miembros: dale ese rol a otro miembro.",
|
|
@@ -1079,7 +1128,9 @@ var TEXTS = {
|
|
|
1079
1128
|
invalid_assertion: "No se pudo verificar la respuesta de tu empresa. Intenta de nuevo.",
|
|
1080
1129
|
provisioning_disabled: "El ingreso con tu empresa funcion\xF3, pero este workspace no tiene una cuenta para ti. P\xEDdele a su admin que te agregue.",
|
|
1081
1130
|
connection_inactive: "El inicio de sesi\xF3n de tu empresa est\xE1 apagado en este workspace.",
|
|
1082
|
-
invalid_grant: "Ese ingreso venci\xF3. Intenta de nuevo."
|
|
1131
|
+
invalid_grant: "Ese ingreso venci\xF3. Intenta de nuevo.",
|
|
1132
|
+
password_disabled: "En este workspace no se entra con contrase\xF1a. Usa una de las otras formas.",
|
|
1133
|
+
passkeys_disabled: "Las llaves de acceso est\xE1n desactivadas en este workspace."
|
|
1083
1134
|
}
|
|
1084
1135
|
}
|
|
1085
1136
|
};
|
|
@@ -1194,8 +1245,10 @@ function sameOrigin(to) {
|
|
|
1194
1245
|
function useForm(props) {
|
|
1195
1246
|
const t = { ...TEXTS[props.locale ?? "en"], ...props.texts, errors: { ...TEXTS[props.locale ?? "en"].errors, ...props.texts?.errors } };
|
|
1196
1247
|
const cx = (slot) => props.classNames?.[slot] ?? `cauthy-${slot}`;
|
|
1197
|
-
const
|
|
1198
|
-
const
|
|
1248
|
+
const own = (slot) => props.classNames?.[slot];
|
|
1249
|
+
const C = props.components ?? {};
|
|
1250
|
+
const Button = C.Button ?? PlainButton;
|
|
1251
|
+
const Input = C.Input ?? PlainInput;
|
|
1199
1252
|
const [error, setError] = (0, import_react.useState)(null);
|
|
1200
1253
|
const [busy, setBusy] = (0, import_react.useState)(false);
|
|
1201
1254
|
const [policy, setPolicy] = (0, import_react.useState)(void 0);
|
|
@@ -1210,7 +1263,81 @@ function useForm(props) {
|
|
|
1210
1263
|
else window.location.assign(sitePath(to) ?? sameOrigin(props.returnTo) ?? "/");
|
|
1211
1264
|
};
|
|
1212
1265
|
const root = useRoot(props);
|
|
1213
|
-
return { t, cx, Button, Input, error, setError, busy, setBusy, say, done, root, policy, setPolicy, passwordRule };
|
|
1266
|
+
return { t, cx, own, C, Button, Input, error, setError, busy, setBusy, say, done, root, policy, setPolicy, passwordRule };
|
|
1267
|
+
}
|
|
1268
|
+
function Note({ f, children, footer }) {
|
|
1269
|
+
const { Text } = f.C;
|
|
1270
|
+
if (Text) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { as: "p", tone: "muted", size: footer ? "sm" : "md", children });
|
|
1271
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: f.cx(footer ? "footer" : "notice"), children });
|
|
1272
|
+
}
|
|
1273
|
+
function Heading({ f, children }) {
|
|
1274
|
+
const { Text } = f.C;
|
|
1275
|
+
if (Text) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { as: "h2", size: "lg", children });
|
|
1276
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: f.cx("heading"), children });
|
|
1277
|
+
}
|
|
1278
|
+
function Say({ f, tone, children }) {
|
|
1279
|
+
const { Alert } = f.C;
|
|
1280
|
+
if (Alert) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Alert, { tone, children });
|
|
1281
|
+
if (tone === "danger") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "alert", className: f.cx("error"), children });
|
|
1282
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "status", className: f.cx("notice"), children });
|
|
1283
|
+
}
|
|
1284
|
+
function Or({ f, children }) {
|
|
1285
|
+
const { Divider } = f.C;
|
|
1286
|
+
if (Divider) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Divider, { label: children });
|
|
1287
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: f.cx("separator"), children });
|
|
1288
|
+
}
|
|
1289
|
+
function A({ f, href, newTab, children }) {
|
|
1290
|
+
const { Link } = f.C;
|
|
1291
|
+
if (Link) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Link, { href, newTab, children });
|
|
1292
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { className: f.cx("link"), href, target: newTab ? "_blank" : void 0, rel: newTab ? "noopener" : void 0, children });
|
|
1293
|
+
}
|
|
1294
|
+
function Tag({ f, tone, children, plain }) {
|
|
1295
|
+
const { Badge } = f.C;
|
|
1296
|
+
if (Badge) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1297
|
+
" ",
|
|
1298
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { tone, children })
|
|
1299
|
+
] });
|
|
1300
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: plain });
|
|
1301
|
+
}
|
|
1302
|
+
function Check(p) {
|
|
1303
|
+
const id = (0, import_react.useId)();
|
|
1304
|
+
const { f } = p;
|
|
1305
|
+
const { Checkbox } = f.C;
|
|
1306
|
+
if (Checkbox) {
|
|
1307
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Checkbox, { id, name: p.name, checked: p.checked, required: p.required, className: f.own("check"), onChange: p.onChange, children: p.children });
|
|
1308
|
+
}
|
|
1309
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: f.cx("check"), children: [
|
|
1310
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", name: p.name, checked: p.checked, required: p.required, onChange: (e) => p.onChange(e.target.checked) }),
|
|
1311
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: p.children })
|
|
1312
|
+
] });
|
|
1313
|
+
}
|
|
1314
|
+
function Pick(p) {
|
|
1315
|
+
const made = (0, import_react.useId)();
|
|
1316
|
+
const id = p.id ?? made;
|
|
1317
|
+
const { f } = p;
|
|
1318
|
+
const { Select } = f.C;
|
|
1319
|
+
if (Select) {
|
|
1320
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Select, { id, name: p.name, value: p.value, options: p.options, disabled: p.disabled, "aria-label": p.label, className: f.own("input"), onChange: p.onChange });
|
|
1321
|
+
}
|
|
1322
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("select", { id, name: p.name, "aria-label": p.label, className: f.cx("input"), value: p.value, disabled: p.disabled, onChange: (e) => p.onChange(e.target.value), children: p.options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: o.value, children: o.label }, o.value)) });
|
|
1323
|
+
}
|
|
1324
|
+
function Labelled({ f, id, label, children }) {
|
|
1325
|
+
const { Field: OwnField } = f.C;
|
|
1326
|
+
if (OwnField) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(OwnField, { id, label, className: f.own("field"), children });
|
|
1327
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: f.cx("field"), children: [
|
|
1328
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: f.cx("label"), children: label }),
|
|
1329
|
+
children
|
|
1330
|
+
] });
|
|
1331
|
+
}
|
|
1332
|
+
function Documents({ f, documents }) {
|
|
1333
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: documents.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
1334
|
+
i > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1335
|
+
f.t.and,
|
|
1336
|
+
" "
|
|
1337
|
+
] }),
|
|
1338
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: d.url, newTab: true, children: d.kind === "terms" ? f.t.termsOfService : f.t.privacyPolicy }),
|
|
1339
|
+
" "
|
|
1340
|
+
] }, d.kind)) });
|
|
1214
1341
|
}
|
|
1215
1342
|
var PASSWORD_RULES = ["needs_lowercase", "needs_uppercase", "needs_digit", "needs_symbol", "needs_classes", "breached"];
|
|
1216
1343
|
function isPasswordRule(e) {
|
|
@@ -1228,26 +1355,43 @@ function Field(p) {
|
|
|
1228
1355
|
const { f } = p;
|
|
1229
1356
|
const bad = f.error?.field === p.name ? f.error : null;
|
|
1230
1357
|
const described = [bad ? `${id}-error` : "", p.hint ? `${id}-hint` : ""].filter(Boolean).join(" ");
|
|
1358
|
+
const input = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1359
|
+
f.Input,
|
|
1360
|
+
{
|
|
1361
|
+
id,
|
|
1362
|
+
name: p.name,
|
|
1363
|
+
type: p.type,
|
|
1364
|
+
value: p.value,
|
|
1365
|
+
autoComplete: p.autoComplete,
|
|
1366
|
+
required: p.required,
|
|
1367
|
+
className: f.cx("input"),
|
|
1368
|
+
"aria-invalid": bad ? true : void 0,
|
|
1369
|
+
"aria-describedby": described || void 0,
|
|
1370
|
+
onChange: (e) => p.onChange(e.target.value)
|
|
1371
|
+
}
|
|
1372
|
+
);
|
|
1373
|
+
const { Field: OwnField } = f.C;
|
|
1374
|
+
if (OwnField) {
|
|
1375
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1376
|
+
OwnField,
|
|
1377
|
+
{
|
|
1378
|
+
id,
|
|
1379
|
+
label: p.label,
|
|
1380
|
+
aside: p.aside,
|
|
1381
|
+
help: p.hint && !bad ? p.hint : void 0,
|
|
1382
|
+
error: bad ? f.say(bad) : void 0,
|
|
1383
|
+
required: p.required,
|
|
1384
|
+
className: f.own("field"),
|
|
1385
|
+
children: input
|
|
1386
|
+
}
|
|
1387
|
+
);
|
|
1388
|
+
}
|
|
1231
1389
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("field"), children: [
|
|
1232
1390
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: f.cx("label"), htmlFor: id, children: [
|
|
1233
1391
|
p.label,
|
|
1234
1392
|
p.aside
|
|
1235
1393
|
] }),
|
|
1236
|
-
|
|
1237
|
-
f.Input,
|
|
1238
|
-
{
|
|
1239
|
-
id,
|
|
1240
|
-
name: p.name,
|
|
1241
|
-
type: p.type,
|
|
1242
|
-
value: p.value,
|
|
1243
|
-
autoComplete: p.autoComplete,
|
|
1244
|
-
required: p.required,
|
|
1245
|
-
className: f.cx("input"),
|
|
1246
|
-
"aria-invalid": bad ? true : void 0,
|
|
1247
|
-
"aria-describedby": described || void 0,
|
|
1248
|
-
onChange: (e) => p.onChange(e.target.value)
|
|
1249
|
-
}
|
|
1250
|
-
),
|
|
1394
|
+
input,
|
|
1251
1395
|
p.hint && !bad && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { id: `${id}-hint`, className: f.cx("hint"), children: p.hint }),
|
|
1252
1396
|
bad && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { id: `${id}-error`, role: "alert", className: f.cx("fieldError"), children: f.say(bad) })
|
|
1253
1397
|
] });
|
|
@@ -1274,23 +1418,16 @@ function useMailedToken(name, open) {
|
|
|
1274
1418
|
open(takeToken(name));
|
|
1275
1419
|
}, []);
|
|
1276
1420
|
}
|
|
1277
|
-
function
|
|
1278
|
-
const auth =
|
|
1279
|
-
const f = useForm(props);
|
|
1280
|
-
const [methods, setMethods] = (0, import_react.useState)(null);
|
|
1281
|
-
const [email, setEmail] = (0, import_react.useState)("");
|
|
1282
|
-
const [password, setPassword] = (0, import_react.useState)("");
|
|
1421
|
+
function SecondStepForm(p) {
|
|
1422
|
+
const { f, auth } = p;
|
|
1283
1423
|
const [code, setCode] = (0, import_react.useState)("");
|
|
1284
|
-
const [step, setStep] = (0, import_react.useState)("password");
|
|
1285
|
-
const challenge = useChallenge(methods?.captchaSiteKey, props.locale);
|
|
1286
1424
|
const [phoneWay, setPhoneWay] = (0, import_react.useState)(null);
|
|
1287
1425
|
const [phoneSent, setPhoneSent] = (0, import_react.useState)("");
|
|
1288
1426
|
(0, import_react.useEffect)(() => {
|
|
1289
|
-
if (step !== "code") return;
|
|
1290
1427
|
void auth.signIn.mfaMethods().then((r) => {
|
|
1291
1428
|
if (r.ok) setPhoneWay({ totp: r.totp, phone: r.phone, push: r.push, email: r.email });
|
|
1292
1429
|
});
|
|
1293
|
-
}, [
|
|
1430
|
+
}, []);
|
|
1294
1431
|
const sendEmail = async () => {
|
|
1295
1432
|
f.setBusy(true);
|
|
1296
1433
|
f.setError(null);
|
|
@@ -1326,6 +1463,62 @@ function SignIn(props) {
|
|
|
1326
1463
|
if (!r.ok) return f.setError(r.error);
|
|
1327
1464
|
setPhoneSent(r.sentTo);
|
|
1328
1465
|
};
|
|
1466
|
+
const submit = async (e) => {
|
|
1467
|
+
e.preventDefault();
|
|
1468
|
+
f.setBusy(true);
|
|
1469
|
+
f.setError(null);
|
|
1470
|
+
const r = await auth.signIn.mfa({ code });
|
|
1471
|
+
f.setBusy(false);
|
|
1472
|
+
if (!r.ok) return f.setError(r.error);
|
|
1473
|
+
f.done();
|
|
1474
|
+
};
|
|
1475
|
+
const general = f.error && !f.error.field ? f.error : null;
|
|
1476
|
+
const to = phoneWay?.phone?.number ?? "";
|
|
1477
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
|
|
1478
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: phoneSent ? f.t.codeSent.replace("{to}", phoneSent) : phoneWay?.email ? f.t.codeHelpEmail.replace("{to}", phoneWay.email.to) : phoneWay?.phone && !phoneWay.totp ? f.t.codeHelpPhone : f.t.codeHelp }),
|
|
1479
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1480
|
+
phoneWay?.email && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void sendEmail(), children: f.t.sendEmailAgain }),
|
|
1481
|
+
pushNumber > 0 ? f.C.Text ? (
|
|
1482
|
+
// The application's text: the number to pick drawn large, by its own rules.
|
|
1483
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { role: "status", "aria-live": "polite", children: [
|
|
1484
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.C.Text, { as: "p", children: f.t.pushPick.replace("{n}", String(pushNumber)) }),
|
|
1485
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.C.Text, { as: "p", size: "lg", children: pushNumber }),
|
|
1486
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.C.Text, { as: "p", tone: "muted", children: f.t.pushWaiting })
|
|
1487
|
+
] })
|
|
1488
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("notice"), role: "status", "aria-live": "polite", children: [
|
|
1489
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: f.t.pushPick.replace("{n}", String(pushNumber)) }),
|
|
1490
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: 48, fontWeight: 700, margin: "4px 0", textAlign: "center" }, children: pushNumber }),
|
|
1491
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: f.t.pushWaiting })
|
|
1492
|
+
] }) : phoneWay?.push && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("button"), onClick: () => void sendPush(), children: f.t.pushSend }),
|
|
1493
|
+
phoneWay?.phone && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void sendCode(), children: (phoneWay.phone.channel === "whatsapp" ? f.t.sendCodeWhatsapp : f.t.sendCodeSms).replace("{to}", to) }),
|
|
1494
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "code", type: "text", label: f.t.code, value: code, autoComplete: "one-time-code", required: true, onChange: setCode }),
|
|
1495
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.verify })
|
|
1496
|
+
] });
|
|
1497
|
+
}
|
|
1498
|
+
function ProviderButtons(p) {
|
|
1499
|
+
const { f } = p;
|
|
1500
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: p.providers.map((provider) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(f.Button, { type: "button", className: f.cx("providerButton"), onClick: () => p.onPick(provider.id), children: [
|
|
1501
|
+
provider.iconUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: provider.iconUrl, alt: "", width: 18, height: 18, className: f.cx("providerIcon") }),
|
|
1502
|
+
f.t.continueWith,
|
|
1503
|
+
" ",
|
|
1504
|
+
provider.name
|
|
1505
|
+
] }, provider.id)) });
|
|
1506
|
+
}
|
|
1507
|
+
function signInOffers(methods) {
|
|
1508
|
+
const password = methods?.passwordSignIn !== false;
|
|
1509
|
+
return { password, email: password || methods?.magicLink === true || methods?.sso === true, passkey: methods?.passkey === true };
|
|
1510
|
+
}
|
|
1511
|
+
function SignIn(props) {
|
|
1512
|
+
const auth = useAuth();
|
|
1513
|
+
const f = useForm(props);
|
|
1514
|
+
const [methods, setMethods] = (0, import_react.useState)(null);
|
|
1515
|
+
const [email, setEmail] = (0, import_react.useState)("");
|
|
1516
|
+
const [password, setPassword] = (0, import_react.useState)("");
|
|
1517
|
+
const [code, setCode] = (0, import_react.useState)("");
|
|
1518
|
+
const [step, setStep] = (0, import_react.useState)("password");
|
|
1519
|
+
const challenge = useChallenge(methods?.captchaSiteKey, props.locale);
|
|
1520
|
+
const offers = signInOffers(methods);
|
|
1521
|
+
const passwordOn = offers.password;
|
|
1329
1522
|
const autofill = (0, import_react.useRef)(null);
|
|
1330
1523
|
const [offer, setOffer] = (0, import_react.useState)(0);
|
|
1331
1524
|
const [company, setCompany] = (0, import_react.useState)(null);
|
|
@@ -1377,10 +1570,18 @@ function SignIn(props) {
|
|
|
1377
1570
|
const submit = async (e) => {
|
|
1378
1571
|
e.preventDefault();
|
|
1379
1572
|
autofill.current?.abort();
|
|
1573
|
+
if (step === "password" && company?.enforced) {
|
|
1574
|
+
f.setError(null);
|
|
1575
|
+
return toCompany();
|
|
1576
|
+
}
|
|
1577
|
+
if (step === "password" && !passwordOn) {
|
|
1578
|
+
if (company) return toCompany();
|
|
1579
|
+
if (methods?.magicLink) return sendLink();
|
|
1580
|
+
return;
|
|
1581
|
+
}
|
|
1380
1582
|
f.setBusy(true);
|
|
1381
1583
|
f.setError(null);
|
|
1382
|
-
|
|
1383
|
-
const r = step === "code" ? await auth.signIn.mfa({ code }) : step === "sent" ? await auth.signIn.emailCode({ code }) : await auth.signIn.email({ email, password, captchaToken: challenge.token });
|
|
1584
|
+
const r = step === "sent" ? await auth.signIn.emailCode({ code }) : await auth.signIn.email({ email, password, captchaToken: challenge.token });
|
|
1384
1585
|
f.setBusy(false);
|
|
1385
1586
|
if (step === "password") challenge.renew();
|
|
1386
1587
|
if (!r.ok && r.error.code === "sso_required") return toCompany();
|
|
@@ -1414,49 +1615,31 @@ function SignIn(props) {
|
|
|
1414
1615
|
setStep("sent");
|
|
1415
1616
|
};
|
|
1416
1617
|
const general = f.error && !f.error.field ? f.error : null;
|
|
1618
|
+
const asksEmail = offers.email;
|
|
1417
1619
|
if (step === "opening") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: f.cx("form"), ...f.root, "aria-busy": "true" });
|
|
1418
1620
|
if (step === "sent") {
|
|
1419
1621
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
|
|
1420
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1421
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1422
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1423
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "code", type: "text", label: f.t.code, value: code, autoComplete: "one-time-code", required: true, onChange: setCode }),
|
|
1424
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.verify })
|
|
1425
|
-
] });
|
|
1426
|
-
}
|
|
1427
|
-
if (step === "code") {
|
|
1428
|
-
const to = phoneWay?.phone?.number ?? "";
|
|
1429
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
|
|
1430
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: f.cx("notice"), children: phoneSent ? f.t.codeSent.replace("{to}", phoneSent) : phoneWay?.email ? f.t.codeHelpEmail.replace("{to}", phoneWay.email.to) : phoneWay?.phone && !phoneWay.totp ? f.t.codeHelpPhone : f.t.codeHelp }),
|
|
1431
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "alert", className: f.cx("error"), children: f.say(general) }),
|
|
1432
|
-
phoneWay?.email && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void sendEmail(), children: f.t.sendEmailAgain }),
|
|
1433
|
-
pushNumber > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("notice"), role: "status", "aria-live": "polite", children: [
|
|
1434
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: f.t.pushPick.replace("{n}", String(pushNumber)) }),
|
|
1435
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: 48, fontWeight: 700, margin: "4px 0", textAlign: "center" }, children: pushNumber }),
|
|
1436
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: f.t.pushWaiting })
|
|
1437
|
-
] }) : phoneWay?.push && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("button"), onClick: () => void sendPush(), children: f.t.pushSend }),
|
|
1438
|
-
phoneWay?.phone && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void sendCode(), children: (phoneWay.phone.channel === "whatsapp" ? f.t.sendCodeWhatsapp : f.t.sendCodeSms).replace("{to}", to) }),
|
|
1622
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.signInLinkSent }),
|
|
1623
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1624
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.codeFromMail }),
|
|
1439
1625
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "code", type: "text", label: f.t.code, value: code, autoComplete: "one-time-code", required: true, onChange: setCode }),
|
|
1440
1626
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.verify })
|
|
1441
1627
|
] });
|
|
1442
1628
|
}
|
|
1629
|
+
if (step === "code") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SecondStepForm, { f, auth });
|
|
1443
1630
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
|
|
1444
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
] }, p.id)),
|
|
1450
|
-
methods?.passkey && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void usePasskey(), children: f.t.usePasskey }),
|
|
1451
|
-
((methods?.providers.length ?? 0) > 0 || methods?.passkey) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: f.cx("separator"), children: f.t.orWithEmail }),
|
|
1452
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: methods?.passkeyHere ? "username webauthn" : "username", required: true, onChange: setEmail }),
|
|
1631
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1632
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProviderButtons, { f, providers: methods?.providers ?? [], onPick: (id) => auth.signIn.social(id, { returnTo: props.returnTo }) }),
|
|
1633
|
+
offers.passkey && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void usePasskey(), children: f.t.usePasskey }),
|
|
1634
|
+
asksEmail && ((methods?.providers.length ?? 0) > 0 || offers.passkey) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Or, { f, children: f.t.orWithEmail }),
|
|
1635
|
+
asksEmail && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: methods?.passkeyHere ? "username webauthn" : "username", required: true, onChange: setEmail }),
|
|
1453
1636
|
company && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(f.Button, { type: "button", disabled: f.busy, className: f.cx(company.enforced ? "button" : "providerButton"), onClick: toCompany, children: [
|
|
1454
1637
|
f.t.continueWith,
|
|
1455
1638
|
" ",
|
|
1456
1639
|
company.name
|
|
1457
1640
|
] }),
|
|
1458
|
-
company?.enforced && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1459
|
-
!company?.enforced && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1641
|
+
company?.enforced && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.ssoOnly }),
|
|
1642
|
+
!company?.enforced && passwordOn && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1460
1643
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1461
1644
|
Field,
|
|
1462
1645
|
{
|
|
@@ -1468,17 +1651,18 @@ function SignIn(props) {
|
|
|
1468
1651
|
autoComplete: "current-password",
|
|
1469
1652
|
required: true,
|
|
1470
1653
|
onChange: setPassword,
|
|
1471
|
-
aside: props.links?.forgotPassword ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1654
|
+
aside: props.links?.forgotPassword ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.forgotPassword, children: f.t.forgotPassword }) : void 0
|
|
1472
1655
|
}
|
|
1473
1656
|
),
|
|
1474
1657
|
challenge.node,
|
|
1475
1658
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.signIn })
|
|
1476
1659
|
] }),
|
|
1660
|
+
!company?.enforced && !passwordOn && methods?.magicLink && challenge.node,
|
|
1477
1661
|
methods?.magicLink && !company?.enforced && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void sendLink(), children: f.t.emailMeALink }),
|
|
1478
|
-
methods?.signUp !== false && props.links?.signUp && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1662
|
+
methods?.signUp !== false && props.links?.signUp && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Note, { f, footer: true, children: [
|
|
1479
1663
|
f.t.noAccount,
|
|
1480
1664
|
" ",
|
|
1481
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1665
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signUp, children: f.t.createAccount })
|
|
1482
1666
|
] })
|
|
1483
1667
|
] });
|
|
1484
1668
|
}
|
|
@@ -1533,44 +1717,43 @@ function SignUp(props) {
|
|
|
1533
1717
|
f.done();
|
|
1534
1718
|
};
|
|
1535
1719
|
const general = f.error && !f.error.field ? f.error : null;
|
|
1720
|
+
const passwordOn = methods?.passwordSignIn !== false;
|
|
1721
|
+
const providers = auth.session?.user.isAnonymous === true || methods?.organization?.required ? [] : methods?.providers ?? [];
|
|
1536
1722
|
if (sent) {
|
|
1537
1723
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, children: [
|
|
1538
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1539
|
-
props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1724
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.checkEmail }),
|
|
1725
|
+
props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signIn, children: f.t.backToSignIn })
|
|
1726
|
+
] });
|
|
1727
|
+
}
|
|
1728
|
+
const footer = props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Note, { f, footer: true, children: [
|
|
1729
|
+
f.t.haveAccount,
|
|
1730
|
+
" ",
|
|
1731
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signIn, children: f.t.signIn })
|
|
1732
|
+
] });
|
|
1733
|
+
if (!passwordOn) {
|
|
1734
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, children: [
|
|
1735
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1736
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProviderButtons, { f, providers, onPick: (id) => auth.signIn.social(id, { returnTo: props.returnTo }) }),
|
|
1737
|
+
footer
|
|
1540
1738
|
] });
|
|
1541
1739
|
}
|
|
1542
1740
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
|
|
1543
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1741
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1742
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProviderButtons, { f, providers, onPick: (id) => auth.signIn.social(id, { returnTo: props.returnTo }) }),
|
|
1743
|
+
providers.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Or, { f, children: f.t.orWithEmail }),
|
|
1544
1744
|
methods?.organization?.ask && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "organization", type: "text", label: f.t.company, value: organization, autoComplete: "organization", required: methods.organization.required, onChange: setOrganization }),
|
|
1545
1745
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "name", type: "text", label: f.t.name, value: name, autoComplete: "name", onChange: setName }),
|
|
1546
1746
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: "username", required: true, onChange: setEmail }),
|
|
1547
1747
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "password", type: "password", label: f.t.password, value: password, autoComplete: "new-password", required: true, onChange: setPassword, hint: f.passwordRule }),
|
|
1548
|
-
legal && legal.documents.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
" ",
|
|
1553
|
-
legal.documents.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
1554
|
-
i > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1555
|
-
f.t.and,
|
|
1556
|
-
" "
|
|
1557
|
-
] }),
|
|
1558
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { className: f.cx("link"), href: d.url, target: "_blank", rel: "noopener", children: d.kind === "terms" ? f.t.termsOfService : f.t.privacyPolicy }),
|
|
1559
|
-
" "
|
|
1560
|
-
] }, d.kind))
|
|
1561
|
-
] })
|
|
1748
|
+
legal && legal.documents.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Check, { f, name: "acceptLegal", checked: acceptLegal, required: true, onChange: setAcceptLegal, children: [
|
|
1749
|
+
f.t.iAccept,
|
|
1750
|
+
" ",
|
|
1751
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Documents, { f, documents: legal.documents })
|
|
1562
1752
|
] }),
|
|
1563
|
-
legal?.consentPurposes.map((p) => /* @__PURE__ */ (0, import_jsx_runtime.
|
|
1564
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", name: `consent_${p.key}`, checked: consents[p.key] === true, required: p.required, onChange: (e) => setConsents({ ...consents, [p.key]: e.target.checked }) }),
|
|
1565
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: p.label })
|
|
1566
|
-
] }, p.key)),
|
|
1753
|
+
legal?.consentPurposes.map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Check, { f, name: `consent_${p.key}`, checked: consents[p.key] === true, required: p.required, onChange: (on) => setConsents({ ...consents, [p.key]: on }), children: p.label }, p.key)),
|
|
1567
1754
|
challenge.node,
|
|
1568
1755
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.signUp }),
|
|
1569
|
-
|
|
1570
|
-
f.t.haveAccount,
|
|
1571
|
-
" ",
|
|
1572
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { className: f.cx("link"), href: props.links.signIn, children: f.t.signIn })
|
|
1573
|
-
] })
|
|
1756
|
+
footer
|
|
1574
1757
|
] });
|
|
1575
1758
|
}
|
|
1576
1759
|
function ForgotPassword(props) {
|
|
@@ -1592,16 +1775,16 @@ function ForgotPassword(props) {
|
|
|
1592
1775
|
const general = f.error && !f.error.field ? f.error : null;
|
|
1593
1776
|
if (sent) {
|
|
1594
1777
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, children: [
|
|
1595
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1596
|
-
props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1778
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.linkSent }),
|
|
1779
|
+
props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signIn, children: f.t.backToSignIn })
|
|
1597
1780
|
] });
|
|
1598
1781
|
}
|
|
1599
1782
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
|
|
1600
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1783
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1601
1784
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: "username", required: true, onChange: setEmail }),
|
|
1602
1785
|
challenge.node,
|
|
1603
1786
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.sendLink }),
|
|
1604
|
-
props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1787
|
+
props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, footer: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signIn, children: f.t.backToSignIn }) })
|
|
1605
1788
|
] });
|
|
1606
1789
|
}
|
|
1607
1790
|
function ResetPassword(props) {
|
|
@@ -1625,21 +1808,21 @@ function ResetPassword(props) {
|
|
|
1625
1808
|
setChanged(true);
|
|
1626
1809
|
};
|
|
1627
1810
|
const general = f.error && !f.error.field ? f.error : null;
|
|
1628
|
-
const back = props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1811
|
+
const back = props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signIn, children: f.t.backToSignIn });
|
|
1629
1812
|
if (changed) {
|
|
1630
1813
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, children: [
|
|
1631
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1814
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.passwordChanged }),
|
|
1632
1815
|
back
|
|
1633
1816
|
] });
|
|
1634
1817
|
}
|
|
1635
1818
|
if (token === "") {
|
|
1636
1819
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, children: [
|
|
1637
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1638
|
-
props.links?.forgotPassword && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1820
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1821
|
+
props.links?.forgotPassword && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.forgotPassword, children: f.t.forgotPassword })
|
|
1639
1822
|
] });
|
|
1640
1823
|
}
|
|
1641
1824
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
|
|
1642
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1825
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1643
1826
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "password", type: "password", label: f.t.newPassword, value: password, autoComplete: "new-password", required: true, onChange: setPassword, hint: f.passwordRule }),
|
|
1644
1827
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy || token === null, className: f.cx("button"), children: f.t.savePassword })
|
|
1645
1828
|
] });
|
|
@@ -1661,12 +1844,98 @@ function VerifyEmail(props) {
|
|
|
1661
1844
|
});
|
|
1662
1845
|
});
|
|
1663
1846
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, "aria-busy": state === "confirming", children: [
|
|
1664
|
-
state === "confirming" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1665
|
-
state === "confirmed" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1666
|
-
state === "failed" && f.error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1667
|
-
state !== "confirming" && props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1847
|
+
state === "confirming" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.confirming }),
|
|
1848
|
+
state === "confirmed" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.emailConfirmed }),
|
|
1849
|
+
state === "failed" && f.error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(f.error) }),
|
|
1850
|
+
state !== "confirming" && props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signIn, children: f.t.backToSignIn })
|
|
1668
1851
|
] });
|
|
1669
1852
|
}
|
|
1853
|
+
function AcceptInvite(props) {
|
|
1854
|
+
const auth = useAuth();
|
|
1855
|
+
const f = useForm(props);
|
|
1856
|
+
const [token, setToken] = (0, import_react.useState)("");
|
|
1857
|
+
const [invitation, setInvitation] = (0, import_react.useState)(null);
|
|
1858
|
+
const [state, setState] = (0, import_react.useState)("opening");
|
|
1859
|
+
const [password, setPassword] = (0, import_react.useState)("");
|
|
1860
|
+
usePasswordPolicy(f, useMethods(auth));
|
|
1861
|
+
useMailedToken("token", (t) => {
|
|
1862
|
+
if (!t) return setState("invalid");
|
|
1863
|
+
setToken(t);
|
|
1864
|
+
void auth.invitation(t).then((r) => {
|
|
1865
|
+
if (r.ok) {
|
|
1866
|
+
setInvitation(r.invitation);
|
|
1867
|
+
return setState("ready");
|
|
1868
|
+
}
|
|
1869
|
+
if (r.error.code !== "invalid_token") f.setError(r.error);
|
|
1870
|
+
setState("invalid");
|
|
1871
|
+
});
|
|
1872
|
+
});
|
|
1873
|
+
const submit = async (e) => {
|
|
1874
|
+
e.preventDefault();
|
|
1875
|
+
f.setBusy(true);
|
|
1876
|
+
f.setError(null);
|
|
1877
|
+
const r = await auth.acceptInvitation(token, password);
|
|
1878
|
+
f.setBusy(false);
|
|
1879
|
+
if (!r.ok) {
|
|
1880
|
+
if (r.error.code === "invalid_token") return setState("invalid");
|
|
1881
|
+
return f.setError(r.error);
|
|
1882
|
+
}
|
|
1883
|
+
props.onSaved?.({ kind: "invitation.accepted", email: invitation?.email ?? "", ...invitation?.organization ? { organization: invitation.organization } : {} });
|
|
1884
|
+
if (r.status === "mfa_required") return setState("code");
|
|
1885
|
+
f.done();
|
|
1886
|
+
};
|
|
1887
|
+
const general = f.error && !f.error.field ? f.error : null;
|
|
1888
|
+
const back = props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signIn, children: f.t.backToSignIn });
|
|
1889
|
+
if (state === "opening") {
|
|
1890
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: f.cx("form"), ...f.root, "aria-busy": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.openingInvitation }) });
|
|
1891
|
+
}
|
|
1892
|
+
if (state === "invalid") {
|
|
1893
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, children: [
|
|
1894
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: general ? f.say(general) : f.t.invitationInvalid }),
|
|
1895
|
+
back
|
|
1896
|
+
] });
|
|
1897
|
+
}
|
|
1898
|
+
if (state === "code") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SecondStepForm, { f, auth });
|
|
1899
|
+
const workspace = invitation?.workspace ?? "";
|
|
1900
|
+
const heading = invitation?.organization ? f.t.invitedToOrganization.replace("{organization}", invitation.organization).replace("{workspace}", workspace) : f.t.invitedTo.replace("{workspace}", workspace);
|
|
1901
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
|
|
1902
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: heading }),
|
|
1903
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.invitedAs.replace("{email}", invitation?.email ?? "") }),
|
|
1904
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1905
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "email", name: "username", autoComplete: "username", value: invitation?.email ?? "", readOnly: true, hidden: true }),
|
|
1906
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "password", type: "password", label: f.t.choosePassword, value: password, autoComplete: "new-password", required: true, onChange: setPassword, hint: f.passwordRule }),
|
|
1907
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.acceptInvite })
|
|
1908
|
+
] });
|
|
1909
|
+
}
|
|
1910
|
+
function PendingTerms(props) {
|
|
1911
|
+
const auth = useAuth();
|
|
1912
|
+
const f = useForm(props);
|
|
1913
|
+
const [owed, setOwed] = (0, import_react.useState)(null);
|
|
1914
|
+
(0, import_react.useEffect)(() => {
|
|
1915
|
+
void auth.account.legal().then((r) => setOwed(r.ok ? r.pending : []));
|
|
1916
|
+
}, []);
|
|
1917
|
+
if (!owed || owed.length === 0) return null;
|
|
1918
|
+
const accept = async () => {
|
|
1919
|
+
f.setBusy(true);
|
|
1920
|
+
f.setError(null);
|
|
1921
|
+
const r = await auth.account.acceptLegal({ kinds: owed.map((d) => d.kind) });
|
|
1922
|
+
f.setBusy(false);
|
|
1923
|
+
if (!r.ok) return f.setError(r.error);
|
|
1924
|
+
setOwed([]);
|
|
1925
|
+
props.onSuccess?.();
|
|
1926
|
+
};
|
|
1927
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, children: [
|
|
1928
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.termsChanged }),
|
|
1929
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Note, { f, children: [
|
|
1930
|
+
f.t.termsChangedHelp,
|
|
1931
|
+
" ",
|
|
1932
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Documents, { f, documents: owed })
|
|
1933
|
+
] }),
|
|
1934
|
+
f.error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(f.error) }),
|
|
1935
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("button"), onClick: () => void accept(), children: f.t.acceptTerms })
|
|
1936
|
+
] });
|
|
1937
|
+
}
|
|
1938
|
+
var ACCOUNT_SECTIONS = ["profile", "email", "password", "linked", "secondStep", "phone", "passkeys", "agents", "sessions"];
|
|
1670
1939
|
function useSection(props) {
|
|
1671
1940
|
const f = useForm({ ...props, unstyled: true });
|
|
1672
1941
|
const [done, setDone] = (0, import_react.useState)(null);
|
|
@@ -1685,37 +1954,65 @@ function useSection(props) {
|
|
|
1685
1954
|
function Account(props) {
|
|
1686
1955
|
const auth = useAuth();
|
|
1687
1956
|
const { accountUrl } = useSession();
|
|
1688
|
-
const {
|
|
1957
|
+
const { root } = useForm(props);
|
|
1689
1958
|
const cx = (slot) => props.classNames?.[slot] ?? `cauthy-${slot}`;
|
|
1690
1959
|
const [account, setAccount] = (0, import_react.useState)(null);
|
|
1691
|
-
const [sessions, setSessions] = (0, import_react.useState)([]);
|
|
1692
1960
|
(0, import_react.useEffect)(() => {
|
|
1693
1961
|
void auth.account.get().then(setAccount);
|
|
1694
|
-
void auth.account.sessions().then(setSessions);
|
|
1695
1962
|
}, []);
|
|
1696
1963
|
if (account === null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cx("account"), ...root, "aria-busy": "true" });
|
|
1697
1964
|
const when = props.formatDate ?? ((iso) => new Date(iso).toLocaleString());
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1965
|
+
const mfa = (mfaEnabled) => setAccount({ ...account, mfaEnabled });
|
|
1966
|
+
const part = (section) => {
|
|
1967
|
+
switch (section) {
|
|
1968
|
+
case "profile":
|
|
1969
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProfilePart, { props, account, onSaved: setAccount });
|
|
1970
|
+
case "email":
|
|
1971
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EmailPart, { props, account });
|
|
1972
|
+
case "password":
|
|
1973
|
+
return account.hasPassword ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PasswordPart, { props }) : null;
|
|
1974
|
+
case "linked":
|
|
1975
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LinkedPart, { props });
|
|
1976
|
+
case "secondStep":
|
|
1977
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SecondStepPart, { props, account, onChanged: mfa });
|
|
1978
|
+
case "phone":
|
|
1979
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PhonePart, { props, account, onChanged: mfa });
|
|
1980
|
+
case "passkeys":
|
|
1981
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PasskeysPart, { props, account, accountUrl: accountUrl(), when });
|
|
1982
|
+
case "agents":
|
|
1983
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AgentsPart, { props, when });
|
|
1984
|
+
case "sessions":
|
|
1985
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SessionsPart, { props, when });
|
|
1986
|
+
}
|
|
1987
|
+
};
|
|
1988
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cx("account"), ...root, children: (props.sections ?? ACCOUNT_SECTIONS).map((section) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react.Fragment, { children: part(section) }, section)) });
|
|
1989
|
+
}
|
|
1990
|
+
function AccountProfile(props) {
|
|
1991
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["profile"] });
|
|
1992
|
+
}
|
|
1993
|
+
function AccountEmail(props) {
|
|
1994
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["email"] });
|
|
1995
|
+
}
|
|
1996
|
+
function AccountPassword(props) {
|
|
1997
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["password"] });
|
|
1998
|
+
}
|
|
1999
|
+
function AccountLinked(props) {
|
|
2000
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["linked"] });
|
|
2001
|
+
}
|
|
2002
|
+
function AccountSecondStep(props) {
|
|
2003
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["secondStep"] });
|
|
2004
|
+
}
|
|
2005
|
+
function AccountPhone(props) {
|
|
2006
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["phone"] });
|
|
2007
|
+
}
|
|
2008
|
+
function AccountPasskeys(props) {
|
|
2009
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["passkeys"] });
|
|
2010
|
+
}
|
|
2011
|
+
function AccountAgents(props) {
|
|
2012
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["agents"] });
|
|
2013
|
+
}
|
|
2014
|
+
function AccountSessions(props) {
|
|
2015
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["sessions"] });
|
|
1719
2016
|
}
|
|
1720
2017
|
var OWNER = "owner";
|
|
1721
2018
|
function memberActions(seat, m) {
|
|
@@ -1727,8 +2024,9 @@ function memberActions(seat, m) {
|
|
|
1727
2024
|
inviteAgain: seat.can.manageMembers && m.invited
|
|
1728
2025
|
};
|
|
1729
2026
|
}
|
|
1730
|
-
function rolesToGive(seat, roles) {
|
|
1731
|
-
|
|
2027
|
+
function rolesToGive(seat, roles, only) {
|
|
2028
|
+
const mine = seat.role === OWNER ? roles : roles.filter((c) => c.role !== OWNER);
|
|
2029
|
+
return only ? mine.filter((c) => only(c.role, c)) : mine;
|
|
1732
2030
|
}
|
|
1733
2031
|
function OrganizationMembers(props) {
|
|
1734
2032
|
const auth = useAuth();
|
|
@@ -1745,6 +2043,8 @@ function OrganizationMembers(props) {
|
|
|
1745
2043
|
const [gone, setGone] = (0, import_react.useState)(null);
|
|
1746
2044
|
const id = props.organizationId;
|
|
1747
2045
|
const when = props.formatDate ?? ((iso) => new Date(iso).toLocaleDateString());
|
|
2046
|
+
const hidden = (action) => props.hide?.includes(action) === true;
|
|
2047
|
+
const saved = (event) => props.onSaved?.(event);
|
|
1748
2048
|
const load = async () => {
|
|
1749
2049
|
const [list, people, choices] = await Promise.all([auth.organizations.list(), auth.organizations.members(id), auth.organizations.roles(id)]);
|
|
1750
2050
|
const mine = list.find((o) => o.id === id) ?? null;
|
|
@@ -1752,17 +2052,17 @@ function OrganizationMembers(props) {
|
|
|
1752
2052
|
if (mine) setName(mine.name);
|
|
1753
2053
|
setMembers(people);
|
|
1754
2054
|
setRoles(choices ?? []);
|
|
1755
|
-
const offered = mine ? rolesToGive(mine, choices ?? []) : [];
|
|
2055
|
+
const offered = mine ? rolesToGive(mine, choices ?? [], props.roles) : [];
|
|
1756
2056
|
if (offered.length > 0 && !offered.some((c) => c.role === role)) setRole(offered[0].role);
|
|
1757
2057
|
};
|
|
1758
2058
|
(0, import_react.useEffect)(() => {
|
|
1759
2059
|
void load();
|
|
1760
2060
|
}, [id]);
|
|
1761
|
-
if (gone !== null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: f.cx("account"), ...root, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2061
|
+
if (gone !== null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: f.cx("account"), ...root, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: gone }) });
|
|
1762
2062
|
if (seat === void 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: f.cx("account"), ...root, "aria-busy": "true" });
|
|
1763
|
-
if (seat === null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: f.cx("account"), ...root, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2063
|
+
if (seat === null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: f.cx("account"), ...root, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.organizationMissing }) });
|
|
1764
2064
|
const manage = seat.can.manageMembers;
|
|
1765
|
-
const giveable = rolesToGive(seat, roles);
|
|
2065
|
+
const giveable = rolesToGive(seat, roles, props.roles);
|
|
1766
2066
|
const label = (r) => roles.find((c) => c.role === r)?.name || r;
|
|
1767
2067
|
const add = async (e) => {
|
|
1768
2068
|
e.preventDefault();
|
|
@@ -1770,22 +2070,28 @@ function OrganizationMembers(props) {
|
|
|
1770
2070
|
if (!r.ok) return;
|
|
1771
2071
|
setEmail("");
|
|
1772
2072
|
setDone(f.t.memberAdded.replace("{email}", r.member.email));
|
|
2073
|
+
saved({ kind: "member.added", organizationId: id, userId: r.member.userId, email: r.member.email, role: r.member.role || role });
|
|
1773
2074
|
await load();
|
|
1774
2075
|
};
|
|
1775
2076
|
const change = async (m, next) => {
|
|
1776
2077
|
const r = await run(() => auth.organizations.setRole(id, m.userId, next));
|
|
1777
|
-
if (r.ok)
|
|
2078
|
+
if (!r.ok) return;
|
|
2079
|
+
saved({ kind: "member.role_changed", organizationId: id, userId: m.userId, role: next, previousRole: m.role });
|
|
2080
|
+
await load();
|
|
1778
2081
|
};
|
|
1779
2082
|
const remove = async (m) => {
|
|
1780
2083
|
setAsking(null);
|
|
1781
2084
|
const r = await run(() => auth.organizations.remove(id, m.userId));
|
|
1782
2085
|
if (!r.ok) return;
|
|
2086
|
+
saved({ kind: m.you ? "member.left" : "member.removed", organizationId: id, userId: m.userId });
|
|
1783
2087
|
if (m.you) setSeat(null);
|
|
1784
2088
|
else await load();
|
|
1785
2089
|
};
|
|
1786
2090
|
const inviteAgain = async (m) => {
|
|
1787
2091
|
const r = await run(() => auth.organizations.inviteAgain(id, m.userId, { locale: props.locale }));
|
|
1788
|
-
if (r.ok)
|
|
2092
|
+
if (!r.ok) return;
|
|
2093
|
+
setDone(f.t.memberInvitationSent);
|
|
2094
|
+
saved({ kind: "member.invited_again", organizationId: id, userId: m.userId });
|
|
1789
2095
|
};
|
|
1790
2096
|
const rename = async (e) => {
|
|
1791
2097
|
e.preventDefault();
|
|
@@ -1794,11 +2100,21 @@ function OrganizationMembers(props) {
|
|
|
1794
2100
|
setSeat(r.organization);
|
|
1795
2101
|
setName(r.organization.name);
|
|
1796
2102
|
setDone(f.t.organizationRenamed.replace("{name}", r.organization.name));
|
|
2103
|
+
saved({ kind: "organization.renamed", organizationId: id, name: r.organization.name });
|
|
1797
2104
|
};
|
|
1798
2105
|
const close = async (how) => {
|
|
1799
2106
|
setAsking(null);
|
|
1800
2107
|
const r = await run(() => how === "archive" ? auth.organizations.archive(id) : auth.organizations.delete(id));
|
|
1801
|
-
if (r.ok)
|
|
2108
|
+
if (!r.ok) return;
|
|
2109
|
+
setGone((how === "archive" ? f.t.organizationArchived : f.t.organizationDeleted).replace("{org}", seat.name));
|
|
2110
|
+
saved({ kind: how === "archive" ? "organization.archived" : "organization.deleted", organizationId: id });
|
|
2111
|
+
};
|
|
2112
|
+
const ask = (key, title, question, yes) => {
|
|
2113
|
+
const { Confirm } = f.C;
|
|
2114
|
+
if (!Confirm) return setAsking(key);
|
|
2115
|
+
void Confirm({ title, body: question, confirmLabel: title, cancelLabel: f.t.cancel, danger: true }).then((ok) => {
|
|
2116
|
+
if (ok) yes();
|
|
2117
|
+
});
|
|
1802
2118
|
};
|
|
1803
2119
|
const confirming = (text2, label2, yes) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { role: "group", "aria-label": label2, children: [
|
|
1804
2120
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: text2 }),
|
|
@@ -1806,81 +2122,96 @@ function OrganizationMembers(props) {
|
|
|
1806
2122
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: yes, children: f.t.yes }),
|
|
1807
2123
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => setAsking(null), children: f.t.cancel })
|
|
1808
2124
|
] });
|
|
2125
|
+
const leaveQuestion = f.t.memberLeaveConfirm.replace("{org}", seat.name);
|
|
2126
|
+
const archiveQuestion = f.t.organizationArchiveConfirm.replace("{org}", seat.name);
|
|
2127
|
+
const deleteQuestion = f.t.organizationDeleteConfirm.replace("{org}", seat.name);
|
|
2128
|
+
const archiving = seat.can.archive && !hidden("archive");
|
|
2129
|
+
const deleting = seat.can.delete && !hidden("delete");
|
|
2130
|
+
const renaming = seat.can.update && !hidden("rename");
|
|
1809
2131
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("account"), ...root, children: [
|
|
1810
2132
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: f.cx("section"), children: [
|
|
1811
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
2133
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Heading, { f, children: [
|
|
1812
2134
|
f.t.members,
|
|
1813
2135
|
" \xB7 ",
|
|
1814
2136
|
seat.name
|
|
1815
2137
|
] }),
|
|
1816
|
-
problem && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2138
|
+
problem && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(problem) }),
|
|
1817
2139
|
members === null ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1818
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1819
|
-
auth.session && (asking === auth.session.user.id ? confirming(
|
|
1820
|
-
f.
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
2140
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.membersHidden }),
|
|
2141
|
+
auth.session && !hidden("leave") && (asking === auth.session.user.id ? confirming(leaveQuestion, f.t.memberLeave, () => void remove({ userId: auth.session.user.id, you: true })) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2142
|
+
f.Button,
|
|
2143
|
+
{
|
|
2144
|
+
type: "button",
|
|
2145
|
+
disabled: f.busy,
|
|
2146
|
+
className: f.cx("providerButton"),
|
|
2147
|
+
onClick: () => ask(auth.session.user.id, f.t.memberLeave, leaveQuestion, () => void remove({ userId: auth.session.user.id, you: true })),
|
|
2148
|
+
children: f.t.memberLeave
|
|
2149
|
+
}
|
|
2150
|
+
))
|
|
1824
2151
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: f.cx("sessions"), children: members.map((m) => {
|
|
1825
2152
|
const who = m.name || m.email;
|
|
1826
2153
|
const may = memberActions(seat, m);
|
|
2154
|
+
const removable = may.remove && !(m.you && hidden("leave"));
|
|
2155
|
+
const question = m.you ? leaveQuestion : f.t.memberRemoveConfirm.replace("{who}", who);
|
|
2156
|
+
const action = m.you ? f.t.memberLeave : f.t.memberRemove;
|
|
2157
|
+
const choices = giveable.some((c) => c.role === m.role) ? giveable : [...roles.filter((c) => c.role === m.role), ...giveable];
|
|
1827
2158
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: f.cx("session"), children: [
|
|
1828
2159
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
1829
2160
|
who,
|
|
1830
2161
|
m.name ? ` \xB7 ${m.email}` : "",
|
|
1831
|
-
m.you
|
|
1832
|
-
|
|
1833
|
-
|
|
2162
|
+
m.you && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tag, { f, plain: ` (${f.t.memberYou})`, children: f.t.memberYou }),
|
|
2163
|
+
f.C.Badge ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
2164
|
+
m.invited && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tag, { f, tone: "warning", plain: "", children: f.t.memberInvited }),
|
|
2165
|
+
m.manager && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tag, { f, tone: "success", plain: "", children: f.t.memberManager })
|
|
2166
|
+
] }) : `${m.invited ? ` \xB7 ${f.t.memberInvited}` : ""}${m.manager ? ` \xB7 ${f.t.memberManager}` : ""}`,
|
|
1834
2167
|
" \xB7 ",
|
|
1835
2168
|
when(m.since)
|
|
1836
2169
|
] }),
|
|
1837
2170
|
" ",
|
|
1838
2171
|
may.changeRole && giveable.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1839
|
-
|
|
2172
|
+
Pick,
|
|
1840
2173
|
{
|
|
1841
|
-
|
|
1842
|
-
|
|
2174
|
+
f,
|
|
2175
|
+
name: `role_${m.userId}`,
|
|
2176
|
+
label: `${f.t.memberRole}: ${who}`,
|
|
1843
2177
|
value: m.role,
|
|
1844
2178
|
disabled: f.busy,
|
|
1845
|
-
|
|
1846
|
-
|
|
2179
|
+
options: choices.map((c) => ({ value: c.role, label: c.name || c.role })),
|
|
2180
|
+
onChange: (next) => void change(m, next)
|
|
1847
2181
|
}
|
|
1848
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: label(m.role) }),
|
|
2182
|
+
) : f.C.Badge ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.C.Badge, { tone: "neutral", children: label(m.role) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: label(m.role) }),
|
|
1849
2183
|
" ",
|
|
1850
|
-
asking === m.userId ? confirming(
|
|
1851
|
-
m.you ? f.t.memberLeaveConfirm.replace("{org}", seat.name) : f.t.memberRemoveConfirm.replace("{who}", who),
|
|
1852
|
-
m.you ? f.t.memberLeave : f.t.memberRemove,
|
|
1853
|
-
() => void remove(m)
|
|
1854
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
2184
|
+
asking === m.userId ? confirming(question, action, () => void remove(m)) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1855
2185
|
may.inviteAgain && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void inviteAgain(m), children: f.t.memberInviteAgain }),
|
|
1856
|
-
|
|
2186
|
+
removable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => ask(m.userId, action, question, () => void remove(m)), children: action })
|
|
1857
2187
|
] })
|
|
1858
2188
|
] }, m.userId);
|
|
1859
2189
|
}) }),
|
|
1860
|
-
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2190
|
+
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
|
|
1861
2191
|
] }),
|
|
1862
2192
|
manage && giveable.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: add, noValidate: true, children: [
|
|
1863
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2193
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.memberAdd }),
|
|
1864
2194
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: "off", required: true, onChange: setEmail }),
|
|
1865
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
1866
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: f.cx("label"), children: f.t.memberRole }),
|
|
1867
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("select", { name: "role", className: f.cx("input"), value: role, onChange: (e) => setRole(e.target.value), children: giveable.map((c) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: c.role, children: c.name || c.role }, c.role)) })
|
|
1868
|
-
] }),
|
|
2195
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AddRole, { f, value: role, options: giveable.map((c) => ({ value: c.role, label: c.name || c.role })), onChange: setRole }),
|
|
1869
2196
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.memberAdd })
|
|
1870
2197
|
] }),
|
|
1871
|
-
(
|
|
1872
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1873
|
-
|
|
2198
|
+
(renaming || archiving || deleting) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: f.cx("section"), children: [
|
|
2199
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.organization }),
|
|
2200
|
+
renaming && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { onSubmit: rename, noValidate: true, children: [
|
|
1874
2201
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "name", type: "text", label: f.t.name, value: name, autoComplete: "organization", required: true, onChange: setName }),
|
|
1875
2202
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.organizationRename })
|
|
1876
2203
|
] }),
|
|
1877
|
-
asking === "archive" ? confirming(
|
|
1878
|
-
|
|
1879
|
-
|
|
2204
|
+
asking === "archive" ? confirming(archiveQuestion, f.t.organizationArchive, () => void close("archive")) : asking === "delete" ? confirming(deleteQuestion, f.t.organizationDelete, () => void close("delete")) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
2205
|
+
archiving && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => ask("archive", f.t.organizationArchive, archiveQuestion, () => void close("archive")), children: f.t.organizationArchive }),
|
|
2206
|
+
deleting && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => ask("delete", f.t.organizationDelete, deleteQuestion, () => void close("delete")), children: f.t.organizationDelete })
|
|
1880
2207
|
] })
|
|
1881
2208
|
] })
|
|
1882
2209
|
] });
|
|
1883
2210
|
}
|
|
2211
|
+
function AddRole({ f, value, options, onChange }) {
|
|
2212
|
+
const id = (0, import_react.useId)();
|
|
2213
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Labelled, { f, id, label: f.t.memberRole, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Pick, { f, id, name: "role", value, options, onChange }) });
|
|
2214
|
+
}
|
|
1884
2215
|
function PasskeysPart({ props, account, accountUrl, when }) {
|
|
1885
2216
|
const auth = useAuth();
|
|
1886
2217
|
const { f, done, setDone, run, general } = useSection(props);
|
|
@@ -1898,8 +2229,8 @@ function PasskeysPart({ props, account, accountUrl, when }) {
|
|
|
1898
2229
|
if (here === null) return null;
|
|
1899
2230
|
if (!here) {
|
|
1900
2231
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: f.cx("section"), children: [
|
|
1901
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1902
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2232
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.passkeys }),
|
|
2233
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: accountUrl, children: f.t.managePasskeys })
|
|
1903
2234
|
] });
|
|
1904
2235
|
}
|
|
1905
2236
|
const add = async (e, kind = "device") => {
|
|
@@ -1913,18 +2244,21 @@ function PasskeysPart({ props, account, accountUrl, when }) {
|
|
|
1913
2244
|
setName("");
|
|
1914
2245
|
setPassword("");
|
|
1915
2246
|
setDone(f.t.passkeyAdded);
|
|
2247
|
+
props.onSaved?.({ kind: "passkey.added", id: r.passkey.id });
|
|
1916
2248
|
};
|
|
1917
2249
|
const remove = async (id) => {
|
|
1918
2250
|
const r = await run(() => auth.account.removePasskey(id));
|
|
1919
|
-
if (r.ok)
|
|
2251
|
+
if (!r.ok) return;
|
|
2252
|
+
setList(list.filter((p) => p.id !== id));
|
|
2253
|
+
props.onSaved?.({ kind: "passkey.removed", id });
|
|
1920
2254
|
};
|
|
1921
2255
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: add, noValidate: true, children: [
|
|
1922
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1923
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1924
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1925
|
-
list.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2256
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.passkeys }),
|
|
2257
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.passkeysHelp }),
|
|
2258
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2259
|
+
list.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.noPasskeys }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: f.cx("sessions"), children: list.map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: f.cx("session"), children: [
|
|
1926
2260
|
p.name || f.t.passkeyUnnamed,
|
|
1927
|
-
p.kind !== "unknown"
|
|
2261
|
+
p.kind !== "unknown" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tag, { f, plain: ` \xB7 ${f.t.passkeyKinds[p.kind]}`, children: f.t.passkeyKinds[p.kind] }),
|
|
1928
2262
|
" \xB7 ",
|
|
1929
2263
|
when(p.createdAt),
|
|
1930
2264
|
" ",
|
|
@@ -1934,7 +2268,7 @@ function PasskeysPart({ props, account, accountUrl, when }) {
|
|
|
1934
2268
|
account.hasPassword && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "password", type: "password", label: f.t.currentPassword, value: password, autoComplete: "current-password", required: true, onChange: setPassword }),
|
|
1935
2269
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.addPasskeyDevice }),
|
|
1936
2270
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void add(null, "security_key"), children: f.t.addSecurityKey }),
|
|
1937
|
-
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2271
|
+
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
|
|
1938
2272
|
] });
|
|
1939
2273
|
}
|
|
1940
2274
|
function ProfilePart({ props, account, onSaved }) {
|
|
@@ -1947,14 +2281,15 @@ function ProfilePart({ props, account, onSaved }) {
|
|
|
1947
2281
|
if (!r.ok) return;
|
|
1948
2282
|
onSaved(r.account);
|
|
1949
2283
|
setDone(f.t.saved);
|
|
2284
|
+
props.onSaved?.({ kind: "profile.saved", name: r.account.name });
|
|
1950
2285
|
};
|
|
1951
2286
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: submit, noValidate: true, children: [
|
|
1952
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1953
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1954
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2287
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.profile }),
|
|
2288
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: account.email }),
|
|
2289
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1955
2290
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "name", type: "text", label: f.t.name, value: name, autoComplete: "name", onChange: setName }),
|
|
1956
2291
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.save }),
|
|
1957
|
-
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2292
|
+
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
|
|
1958
2293
|
] });
|
|
1959
2294
|
}
|
|
1960
2295
|
function EmailPart({ props, account }) {
|
|
@@ -1968,15 +2303,16 @@ function EmailPart({ props, account }) {
|
|
|
1968
2303
|
if (!r.ok) return;
|
|
1969
2304
|
setPassword("");
|
|
1970
2305
|
setDone(f.t.emailSent.replace("{email}", r.email));
|
|
2306
|
+
props.onSaved?.({ kind: "email.change_requested", email: r.email });
|
|
1971
2307
|
};
|
|
1972
2308
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: submit, noValidate: true, children: [
|
|
1973
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1974
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1975
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2309
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.emailAddress }),
|
|
2310
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: account.email }),
|
|
2311
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1976
2312
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.newEmail, value: email, autoComplete: "email", required: true, onChange: setEmail }),
|
|
1977
2313
|
account.hasPassword && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "password", type: "password", label: f.t.currentPassword, value: password, autoComplete: "current-password", required: true, onChange: setPassword }),
|
|
1978
2314
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.changeEmail }),
|
|
1979
|
-
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2315
|
+
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
|
|
1980
2316
|
] });
|
|
1981
2317
|
}
|
|
1982
2318
|
function LinkedPart({ props }) {
|
|
@@ -1989,21 +2325,26 @@ function LinkedPart({ props }) {
|
|
|
1989
2325
|
void auth.account.identities().then(setLinked);
|
|
1990
2326
|
void auth.methods().then((m) => setOffered(m.providers));
|
|
1991
2327
|
const back = typeof window === "undefined" ? null : new URLSearchParams(window.location.search);
|
|
1992
|
-
|
|
1993
|
-
|
|
2328
|
+
const provider = back?.get("linked");
|
|
2329
|
+
if (provider) {
|
|
2330
|
+
setCame(provider);
|
|
2331
|
+
props.onSaved?.({ kind: "identity.linked", provider });
|
|
2332
|
+
} else if (back?.get("auth_error")) f.setError({ code: back.get("auth_error"), message: "That account could not be linked. Try again." });
|
|
1994
2333
|
}, []);
|
|
1995
2334
|
if (linked === null) return null;
|
|
1996
2335
|
const name = (id) => offered.find((p) => p.id === id)?.name ?? id;
|
|
1997
2336
|
const unlink = async (provider) => {
|
|
1998
2337
|
const r = await run(() => auth.account.unlink(provider));
|
|
1999
|
-
if (r.ok)
|
|
2338
|
+
if (!r.ok) return;
|
|
2339
|
+
setLinked(linked.filter((x) => x.provider !== provider));
|
|
2340
|
+
props.onSaved?.({ kind: "identity.unlinked", provider });
|
|
2000
2341
|
};
|
|
2001
2342
|
const here = typeof window === "undefined" ? void 0 : window.location.pathname;
|
|
2002
2343
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: f.cx("section"), children: [
|
|
2003
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2004
|
-
came && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2005
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2006
|
-
linked.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2344
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.linkedAccounts }),
|
|
2345
|
+
came && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: f.t.linked }),
|
|
2346
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2347
|
+
linked.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.noLinkedAccounts }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: f.cx("sessions"), children: linked.map((x) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: f.cx("session"), children: [
|
|
2007
2348
|
name(x.provider),
|
|
2008
2349
|
x.email ? ` \xB7 ${x.email}` : "",
|
|
2009
2350
|
" ",
|
|
@@ -2029,14 +2370,15 @@ function PasswordPart({ props }) {
|
|
|
2029
2370
|
setPassword("");
|
|
2030
2371
|
setNewPassword("");
|
|
2031
2372
|
setDone(f.t.passwordChangedHere);
|
|
2373
|
+
props.onSaved?.({ kind: "password.changed" });
|
|
2032
2374
|
};
|
|
2033
2375
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: submit, noValidate: true, children: [
|
|
2034
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2035
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2376
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.changePassword }),
|
|
2377
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2036
2378
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "password", type: "password", label: f.t.currentPassword, value: password, autoComplete: "current-password", required: true, onChange: setPassword }),
|
|
2037
2379
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "newPassword", type: "password", label: f.t.newPassword, value: newPassword, autoComplete: "new-password", required: true, onChange: setNewPassword, hint: f.passwordRule }),
|
|
2038
2380
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.changePassword }),
|
|
2039
|
-
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2381
|
+
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
|
|
2040
2382
|
] });
|
|
2041
2383
|
}
|
|
2042
2384
|
function SecondStepPart({ props, account, onChanged }) {
|
|
@@ -2060,6 +2402,7 @@ function SecondStepPart({ props, account, onChanged }) {
|
|
|
2060
2402
|
setPassword("");
|
|
2061
2403
|
setCodes(r.recoveryCodes);
|
|
2062
2404
|
onChanged(true);
|
|
2405
|
+
props.onSaved?.({ kind: "mfa.enabled" });
|
|
2063
2406
|
};
|
|
2064
2407
|
const turnOff = async (e) => {
|
|
2065
2408
|
e.preventDefault();
|
|
@@ -2068,32 +2411,35 @@ function SecondStepPart({ props, account, onChanged }) {
|
|
|
2068
2411
|
setPassword("");
|
|
2069
2412
|
setCodes(null);
|
|
2070
2413
|
onChanged(false);
|
|
2414
|
+
props.onSaved?.({ kind: "mfa.disabled" });
|
|
2071
2415
|
};
|
|
2072
2416
|
const renew = async () => {
|
|
2073
2417
|
const r = await run(() => auth.account.mfa.recoveryCodes({ password }));
|
|
2074
|
-
if (r.ok)
|
|
2418
|
+
if (!r.ok) return;
|
|
2419
|
+
setCodes(r.recoveryCodes);
|
|
2420
|
+
props.onSaved?.({ kind: "recovery_codes.regenerated" });
|
|
2075
2421
|
};
|
|
2076
2422
|
const passwordField = account.hasPassword && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "password", type: "password", label: f.t.currentPassword, value: password, autoComplete: "current-password", required: true, onChange: setPassword });
|
|
2077
2423
|
const shown = codes && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
2078
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2424
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.keepCodes }),
|
|
2079
2425
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: f.cx("codes"), children: codes.map((c) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: c }) }, c)) })
|
|
2080
2426
|
] });
|
|
2081
2427
|
if (setup) {
|
|
2082
2428
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: confirm, noValidate: true, children: [
|
|
2083
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2084
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2429
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.secondStep }),
|
|
2430
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.addToApp }),
|
|
2085
2431
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { className: f.cx("secret"), children: setup.secret }),
|
|
2086
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2087
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2432
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: setup.otpauthUri, children: f.t.openInApp }),
|
|
2433
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2088
2434
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "code", type: "text", label: f.t.code, value: code, autoComplete: "one-time-code", required: true, onChange: setCode }),
|
|
2089
2435
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.verify })
|
|
2090
2436
|
] });
|
|
2091
2437
|
}
|
|
2092
2438
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: account.mfaEnabled ? turnOff : start, noValidate: true, children: [
|
|
2093
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2094
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2439
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.secondStep }),
|
|
2440
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: account.mfaEnabled ? f.t.secondStepOn : f.t.secondStepOff }),
|
|
2095
2441
|
shown,
|
|
2096
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2442
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2097
2443
|
passwordField,
|
|
2098
2444
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: account.mfaEnabled ? f.t.turnOff : f.t.turnOn }),
|
|
2099
2445
|
account.mfaEnabled && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void renew(), children: f.t.newRecoveryCodes })
|
|
@@ -2131,6 +2477,7 @@ function PhonePart({ props, account, onChanged }) {
|
|
|
2131
2477
|
setPassword("");
|
|
2132
2478
|
if (r.recoveryCodes.length > 0) setCodes(r.recoveryCodes);
|
|
2133
2479
|
onChanged(true);
|
|
2480
|
+
props.onSaved?.({ kind: "phone.added", channel });
|
|
2134
2481
|
await load();
|
|
2135
2482
|
};
|
|
2136
2483
|
const remove = async (e) => {
|
|
@@ -2141,27 +2488,29 @@ function PhonePart({ props, account, onChanged }) {
|
|
|
2141
2488
|
await load();
|
|
2142
2489
|
const left = await auth.account.mfa.factors();
|
|
2143
2490
|
onChanged(Boolean(left?.totp));
|
|
2491
|
+
props.onSaved?.({ kind: "phone.removed" });
|
|
2144
2492
|
};
|
|
2145
2493
|
const passwordField = account.hasPassword && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "password", type: "password", label: f.t.currentPassword, value: password, autoComplete: "current-password", required: true, onChange: setPassword });
|
|
2146
2494
|
if (sentTo) {
|
|
2147
2495
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: confirm, noValidate: true, children: [
|
|
2148
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2149
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2150
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2496
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.phone }),
|
|
2497
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.codeSent.replace("{to}", sentTo) }),
|
|
2498
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2151
2499
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "code", type: "text", label: f.t.code, value: code, autoComplete: "one-time-code", required: true, onChange: setCode }),
|
|
2152
2500
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.verify })
|
|
2153
2501
|
] });
|
|
2154
2502
|
}
|
|
2155
2503
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: ways.phone ? remove : add, noValidate: true, children: [
|
|
2156
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2157
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2504
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.phone }),
|
|
2505
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: ways.phone ? f.t.phoneOn.replace("{to}", ways.phone.number) : `${f.t.phoneOff} ${f.t.phoneHelp}` }),
|
|
2158
2506
|
codes && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
2159
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2507
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.keepCodes }),
|
|
2160
2508
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: f.cx("codes"), children: codes.map((c) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: c }) }, c)) })
|
|
2161
2509
|
] }),
|
|
2162
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2510
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2163
2511
|
!ways.phone && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "phone", type: "tel", label: f.t.phone, value: number, autoComplete: "tel", required: true, onChange: setNumber }),
|
|
2164
|
-
!ways.phone && ways.phoneChannels.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2512
|
+
!ways.phone && ways.phoneChannels.length > 1 && f.C.Select && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChannelPick, { f, value: channel, channels: ways.phoneChannels, onChange: setChannel }),
|
|
2513
|
+
!ways.phone && ways.phoneChannels.length > 1 && !f.C.Select && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: f.cx("field"), role: "radiogroup", children: ways.phoneChannels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: f.cx("label"), children: [
|
|
2165
2514
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "radio", name: "channel", value: c, checked: channel === c, onChange: () => setChannel(c) }),
|
|
2166
2515
|
" ",
|
|
2167
2516
|
c === "whatsapp" ? f.t.byWhatsapp : f.t.bySms
|
|
@@ -2180,12 +2529,14 @@ function AgentsPart({ props, when }) {
|
|
|
2180
2529
|
if (list.length === 0) return null;
|
|
2181
2530
|
const disconnect = async (id) => {
|
|
2182
2531
|
const r = await run(() => auth.account.disconnectAgent(id));
|
|
2183
|
-
if (r.ok)
|
|
2532
|
+
if (!r.ok) return;
|
|
2533
|
+
setList(list.filter((a) => a.id !== id));
|
|
2534
|
+
props.onSaved?.({ kind: "agent.disconnected", id });
|
|
2184
2535
|
};
|
|
2185
2536
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: f.cx("section"), children: [
|
|
2186
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2187
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2188
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2537
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.agents }),
|
|
2538
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.agentsHelp }),
|
|
2539
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2189
2540
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: f.cx("sessions"), children: list.map((a) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: f.cx("session"), children: [
|
|
2190
2541
|
a.name || f.t.anAgent,
|
|
2191
2542
|
a.redirectHost ? ` (${a.redirectHost})` : "",
|
|
@@ -2199,20 +2550,47 @@ function AgentsPart({ props, when }) {
|
|
|
2199
2550
|
] }, a.id)) })
|
|
2200
2551
|
] });
|
|
2201
2552
|
}
|
|
2202
|
-
function
|
|
2553
|
+
function SessionsPart({ props, when }) {
|
|
2203
2554
|
const auth = useAuth();
|
|
2204
2555
|
const { f, run, general } = useSection(props);
|
|
2556
|
+
const [sessions, setSessions] = (0, import_react.useState)([]);
|
|
2557
|
+
(0, import_react.useEffect)(() => {
|
|
2558
|
+
void auth.account.sessions().then(setSessions);
|
|
2559
|
+
}, []);
|
|
2205
2560
|
const end = async () => {
|
|
2206
2561
|
const r = await run(() => auth.account.signOutEverywhere());
|
|
2207
2562
|
if (!r.ok) return;
|
|
2563
|
+
props.onSaved?.({ kind: "sessions.ended" });
|
|
2208
2564
|
if (props.onSignedOut) props.onSignedOut();
|
|
2209
2565
|
else window.location.assign("/");
|
|
2210
2566
|
};
|
|
2211
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
2212
|
-
|
|
2567
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: f.cx("section"), children: [
|
|
2568
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.sessions }),
|
|
2569
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: f.cx("sessions"), children: sessions.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: f.cx("session"), children: [
|
|
2570
|
+
s.device || f.t.unknownDevice,
|
|
2571
|
+
" \xB7 ",
|
|
2572
|
+
s.ip,
|
|
2573
|
+
" \xB7 ",
|
|
2574
|
+
when(s.createdAt)
|
|
2575
|
+
] }, i)) }),
|
|
2576
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2213
2577
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("button"), onClick: () => void end(), children: f.t.signOutEverywhere })
|
|
2214
2578
|
] });
|
|
2215
2579
|
}
|
|
2580
|
+
function ChannelPick({ f, value, channels, onChange }) {
|
|
2581
|
+
const id = (0, import_react.useId)();
|
|
2582
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Labelled, { f, id, label: f.t.channel, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2583
|
+
Pick,
|
|
2584
|
+
{
|
|
2585
|
+
f,
|
|
2586
|
+
id,
|
|
2587
|
+
name: "channel",
|
|
2588
|
+
value,
|
|
2589
|
+
options: channels.map((c) => ({ value: c, label: c === "whatsapp" ? f.t.byWhatsapp : f.t.bySms })),
|
|
2590
|
+
onChange: (c) => onChange(c)
|
|
2591
|
+
}
|
|
2592
|
+
) });
|
|
2593
|
+
}
|
|
2216
2594
|
|
|
2217
2595
|
// src/react.tsx
|
|
2218
2596
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
@@ -2314,6 +2692,8 @@ function useAuth() {
|
|
|
2314
2692
|
googleOneTap: (o) => then(client.signIn.googleOneTap(o))
|
|
2315
2693
|
},
|
|
2316
2694
|
signUp: { email: (f) => then(client.signUp.email(f)) },
|
|
2695
|
+
// The invited person is signed in once they accept.
|
|
2696
|
+
acceptInvitation: (token, password) => then(client.acceptInvitation(token, password)),
|
|
2317
2697
|
signOut: () => then(client.signOut()),
|
|
2318
2698
|
account: {
|
|
2319
2699
|
...client.account,
|
|
@@ -2332,11 +2712,22 @@ function useAuth() {
|
|
|
2332
2712
|
}
|
|
2333
2713
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2334
2714
|
0 && (module.exports = {
|
|
2715
|
+
AcceptInvite,
|
|
2335
2716
|
Account,
|
|
2717
|
+
AccountAgents,
|
|
2718
|
+
AccountEmail,
|
|
2719
|
+
AccountLinked,
|
|
2720
|
+
AccountPasskeys,
|
|
2721
|
+
AccountPassword,
|
|
2722
|
+
AccountPhone,
|
|
2723
|
+
AccountProfile,
|
|
2724
|
+
AccountSecondStep,
|
|
2725
|
+
AccountSessions,
|
|
2336
2726
|
CauthyProvider,
|
|
2337
2727
|
ForgotPassword,
|
|
2338
2728
|
GoogleOneTap,
|
|
2339
2729
|
OrganizationMembers,
|
|
2730
|
+
PendingTerms,
|
|
2340
2731
|
ResetPassword,
|
|
2341
2732
|
SignIn,
|
|
2342
2733
|
SignUp,
|