cauthy-auth 0.31.0 → 0.33.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 +59 -2
- package/dist/react.d.mts +329 -30
- package/dist/react.d.ts +329 -30
- package/dist/react.js +617 -290
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +615 -298
- package/dist/react.mjs.map +1 -1
- package/package.json +2 -1
package/dist/react.js
CHANGED
|
@@ -23,10 +23,20 @@ var react_exports = {};
|
|
|
23
23
|
__export(react_exports, {
|
|
24
24
|
AcceptInvite: () => AcceptInvite,
|
|
25
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,
|
|
26
35
|
CauthyProvider: () => CauthyProvider,
|
|
27
36
|
ForgotPassword: () => ForgotPassword,
|
|
28
37
|
GoogleOneTap: () => GoogleOneTap,
|
|
29
38
|
OrganizationMembers: () => OrganizationMembers,
|
|
39
|
+
PendingTerms: () => PendingTerms,
|
|
30
40
|
ResetPassword: () => ResetPassword,
|
|
31
41
|
SignIn: () => SignIn,
|
|
32
42
|
SignUp: () => SignUp,
|
|
@@ -802,6 +812,7 @@ var TEXTS = {
|
|
|
802
812
|
removePhone: "Remove phone",
|
|
803
813
|
bySms: "SMS",
|
|
804
814
|
byWhatsapp: "WhatsApp",
|
|
815
|
+
channel: "Send codes by",
|
|
805
816
|
checkEmail: "Almost there: open the link we sent to confirm your address \u2014 it signs you in.",
|
|
806
817
|
backToSignIn: "Back to sign in",
|
|
807
818
|
emailMeALink: "Email me a sign-in link",
|
|
@@ -891,6 +902,9 @@ var TEXTS = {
|
|
|
891
902
|
organizationDeleted: "{org} was deleted.",
|
|
892
903
|
yes: "Yes",
|
|
893
904
|
cancel: "Cancel",
|
|
905
|
+
termsChanged: "Our terms changed",
|
|
906
|
+
termsChangedHelp: "To go on, read and accept",
|
|
907
|
+
acceptTerms: "Accept",
|
|
894
908
|
errors: {
|
|
895
909
|
not_allowed: "Your role in this organization does not allow that.",
|
|
896
910
|
last_manager: "Somebody else must manage the members first: give that role to another member.",
|
|
@@ -978,6 +992,7 @@ var TEXTS = {
|
|
|
978
992
|
removePhone: "Quitar tel\xE9fono",
|
|
979
993
|
bySms: "SMS",
|
|
980
994
|
byWhatsapp: "WhatsApp",
|
|
995
|
+
channel: "Enviar los c\xF3digos por",
|
|
981
996
|
checkEmail: "Casi listo: abre el enlace que te enviamos para confirmar tu correo; te deja adentro.",
|
|
982
997
|
backToSignIn: "Volver a entrar",
|
|
983
998
|
emailMeALink: "Env\xEDame un enlace para entrar",
|
|
@@ -1067,6 +1082,9 @@ var TEXTS = {
|
|
|
1067
1082
|
organizationDeleted: "{org} qued\xF3 eliminada.",
|
|
1068
1083
|
yes: "S\xED",
|
|
1069
1084
|
cancel: "Cancelar",
|
|
1085
|
+
termsChanged: "Nuestros t\xE9rminos cambiaron",
|
|
1086
|
+
termsChangedHelp: "Para seguir, lee y acepta",
|
|
1087
|
+
acceptTerms: "Aceptar",
|
|
1070
1088
|
errors: {
|
|
1071
1089
|
not_allowed: "Tu rol en esta organizaci\xF3n no permite eso.",
|
|
1072
1090
|
last_manager: "Primero alguien m\xE1s debe administrar los miembros: dale ese rol a otro miembro.",
|
|
@@ -1116,7 +1134,7 @@ var TEXTS = {
|
|
|
1116
1134
|
}
|
|
1117
1135
|
}
|
|
1118
1136
|
};
|
|
1119
|
-
var PlainButton = (p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { ...p });
|
|
1137
|
+
var PlainButton = ({ variant: _variant, loading: _loading, ...p }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { ...p });
|
|
1120
1138
|
var PlainInput = (p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { ...p });
|
|
1121
1139
|
var looks = /* @__PURE__ */ new Map();
|
|
1122
1140
|
var loaded = /* @__PURE__ */ new Set();
|
|
@@ -1227,10 +1245,28 @@ function sameOrigin(to) {
|
|
|
1227
1245
|
function useForm(props) {
|
|
1228
1246
|
const t = { ...TEXTS[props.locale ?? "en"], ...props.texts, errors: { ...TEXTS[props.locale ?? "en"].errors, ...props.texts?.errors } };
|
|
1229
1247
|
const cx = (slot) => props.classNames?.[slot] ?? `cauthy-${slot}`;
|
|
1230
|
-
const
|
|
1231
|
-
const
|
|
1232
|
-
const
|
|
1233
|
-
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;
|
|
1252
|
+
const [error, setOnlyError] = (0, import_react.useState)(null);
|
|
1253
|
+
const [problems, setProblems] = (0, import_react.useState)({ list: [], round: 0 });
|
|
1254
|
+
const setError = (0, import_react.useCallback)((e) => {
|
|
1255
|
+
setOnlyError(e);
|
|
1256
|
+
setProblems((p) => p.list.length === 0 ? p : { list: [], round: p.round });
|
|
1257
|
+
}, []);
|
|
1258
|
+
const check = (...found) => {
|
|
1259
|
+
const list = found.filter((e) => Boolean(e));
|
|
1260
|
+
setOnlyError(null);
|
|
1261
|
+
setProblems((p) => ({ list, round: list.length > 0 ? p.round + 1 : p.round }));
|
|
1262
|
+
return list.length === 0;
|
|
1263
|
+
};
|
|
1264
|
+
const fieldError = (name) => problems.list.find((e) => e.field === name) ?? (error?.field === name ? error : null);
|
|
1265
|
+
const firstWrong = (name) => problems.list[0]?.field === name ? problems.round : 0;
|
|
1266
|
+
const [acting, setActing] = (0, import_react.useState)(null);
|
|
1267
|
+
const busy = acting !== null;
|
|
1268
|
+
const setBusy = (0, import_react.useCallback)((on) => setActing(on === false ? null : on === true ? SUBMIT : on), []);
|
|
1269
|
+
const loading = (key = SUBMIT) => acting === key;
|
|
1234
1270
|
const [policy, setPolicy] = (0, import_react.useState)(void 0);
|
|
1235
1271
|
const locale = props.locale ?? "en";
|
|
1236
1272
|
const say = (e) => {
|
|
@@ -1243,13 +1279,113 @@ function useForm(props) {
|
|
|
1243
1279
|
else window.location.assign(sitePath(to) ?? sameOrigin(props.returnTo) ?? "/");
|
|
1244
1280
|
};
|
|
1245
1281
|
const root = useRoot(props);
|
|
1246
|
-
return { t, cx, Button, Input, error, setError, busy, setBusy, say, done, root, policy, setPolicy, passwordRule };
|
|
1282
|
+
return { t, cx, own, C, Button, Input, error, setError, check, fieldError, firstWrong, busy, setBusy, loading, say, done, root, policy, setPolicy, passwordRule };
|
|
1283
|
+
}
|
|
1284
|
+
var SUBMIT = "submit";
|
|
1285
|
+
function Wrap(p) {
|
|
1286
|
+
const { Form: OwnForm } = p.f.C;
|
|
1287
|
+
if (OwnForm) {
|
|
1288
|
+
const own = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1289
|
+
OwnForm,
|
|
1290
|
+
{
|
|
1291
|
+
as: p.as === "form" ? "form" : "div",
|
|
1292
|
+
onSubmit: p.onSubmit,
|
|
1293
|
+
noValidate: p.noValidate,
|
|
1294
|
+
"aria-busy": p.busy,
|
|
1295
|
+
className: p.slot ? p.f.own(p.slot) : void 0,
|
|
1296
|
+
section: p.section,
|
|
1297
|
+
children: p.children
|
|
1298
|
+
}
|
|
1299
|
+
);
|
|
1300
|
+
return p.root?.["data-cauthy"] !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ...p.root, children: own }) : own;
|
|
1301
|
+
}
|
|
1302
|
+
const Tag2 = p.as;
|
|
1303
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tag2, { className: p.slot ? p.f.cx(p.slot) : void 0, ...p.root, onSubmit: p.onSubmit, noValidate: p.noValidate, "aria-busy": p.busy, children: p.children });
|
|
1304
|
+
}
|
|
1305
|
+
function Note({ f, children, footer }) {
|
|
1306
|
+
const { Text } = f.C;
|
|
1307
|
+
if (Text) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { as: "p", tone: "muted", size: footer ? "sm" : "md", children });
|
|
1308
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: f.cx(footer ? "footer" : "notice"), children });
|
|
1309
|
+
}
|
|
1310
|
+
function Heading({ f, children }) {
|
|
1311
|
+
const { Text } = f.C;
|
|
1312
|
+
if (Text) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { as: "h2", size: "lg", children });
|
|
1313
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: f.cx("heading"), children });
|
|
1314
|
+
}
|
|
1315
|
+
function Say({ f, tone, children }) {
|
|
1316
|
+
const { Alert } = f.C;
|
|
1317
|
+
if (Alert) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Alert, { tone, children });
|
|
1318
|
+
if (tone === "danger") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "alert", className: f.cx("error"), children });
|
|
1319
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "status", className: f.cx("notice"), children });
|
|
1320
|
+
}
|
|
1321
|
+
function Or({ f, children }) {
|
|
1322
|
+
const { Divider } = f.C;
|
|
1323
|
+
if (Divider) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Divider, { label: children });
|
|
1324
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: f.cx("separator"), children });
|
|
1325
|
+
}
|
|
1326
|
+
function A({ f, href, newTab, children }) {
|
|
1327
|
+
const { Link } = f.C;
|
|
1328
|
+
if (Link) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Link, { href, newTab, children });
|
|
1329
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { className: f.cx("link"), href, target: newTab ? "_blank" : void 0, rel: newTab ? "noopener" : void 0, children });
|
|
1330
|
+
}
|
|
1331
|
+
function Tag({ f, tone, children, plain }) {
|
|
1332
|
+
const { Badge } = f.C;
|
|
1333
|
+
if (Badge) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1334
|
+
" ",
|
|
1335
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { tone, children })
|
|
1336
|
+
] });
|
|
1337
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: plain });
|
|
1338
|
+
}
|
|
1339
|
+
function Check(p) {
|
|
1340
|
+
const id = (0, import_react.useId)();
|
|
1341
|
+
const { f } = p;
|
|
1342
|
+
const { Checkbox } = f.C;
|
|
1343
|
+
if (Checkbox) {
|
|
1344
|
+
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 });
|
|
1345
|
+
}
|
|
1346
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: f.cx("check"), children: [
|
|
1347
|
+
/* @__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) }),
|
|
1348
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: p.children })
|
|
1349
|
+
] });
|
|
1350
|
+
}
|
|
1351
|
+
function Pick(p) {
|
|
1352
|
+
const made = (0, import_react.useId)();
|
|
1353
|
+
const id = p.id ?? made;
|
|
1354
|
+
const { f } = p;
|
|
1355
|
+
const { Select } = f.C;
|
|
1356
|
+
if (Select) {
|
|
1357
|
+
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 });
|
|
1358
|
+
}
|
|
1359
|
+
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)) });
|
|
1360
|
+
}
|
|
1361
|
+
function Labelled({ f, id, label, children }) {
|
|
1362
|
+
const { Field: OwnField } = f.C;
|
|
1363
|
+
if (OwnField) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(OwnField, { id, label, className: f.own("field"), children });
|
|
1364
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: f.cx("field"), children: [
|
|
1365
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: f.cx("label"), children: label }),
|
|
1366
|
+
children
|
|
1367
|
+
] });
|
|
1368
|
+
}
|
|
1369
|
+
function Documents({ f, documents }) {
|
|
1370
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: documents.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
1371
|
+
i > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1372
|
+
f.t.and,
|
|
1373
|
+
" "
|
|
1374
|
+
] }),
|
|
1375
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: d.url, newTab: true, children: d.kind === "terms" ? f.t.termsOfService : f.t.privacyPolicy }),
|
|
1376
|
+
" "
|
|
1377
|
+
] }, d.kind)) });
|
|
1247
1378
|
}
|
|
1248
1379
|
var PASSWORD_RULES = ["needs_lowercase", "needs_uppercase", "needs_digit", "needs_symbol", "needs_classes", "breached"];
|
|
1249
1380
|
function isPasswordRule(e) {
|
|
1250
1381
|
if (e.code === "weak_password" || PASSWORD_RULES.includes(e.code)) return true;
|
|
1251
1382
|
return (e.code === "too_short" || e.code === "too_long") && (e.field === "password" || e.field === "newPassword");
|
|
1252
1383
|
}
|
|
1384
|
+
function newPasswordProblem(value, policy, field = "password") {
|
|
1385
|
+
const bad = checkNewPassword(value, policy);
|
|
1386
|
+
if (!bad) return null;
|
|
1387
|
+
return { code: bad.code, message: bad.message, field, ...bad.code === "required" ? {} : { reasons: passwordProblems(value, policy) } };
|
|
1388
|
+
}
|
|
1253
1389
|
function usePasswordPolicy(f, methods) {
|
|
1254
1390
|
const { setPolicy } = f;
|
|
1255
1391
|
(0, import_react.useEffect)(() => {
|
|
@@ -1259,28 +1395,49 @@ function usePasswordPolicy(f, methods) {
|
|
|
1259
1395
|
function Field(p) {
|
|
1260
1396
|
const id = (0, import_react.useId)();
|
|
1261
1397
|
const { f } = p;
|
|
1262
|
-
const bad = f.
|
|
1398
|
+
const bad = f.fieldError(p.name);
|
|
1399
|
+
const focus = f.firstWrong(p.name);
|
|
1400
|
+
(0, import_react.useEffect)(() => {
|
|
1401
|
+
if (focus > 0 && typeof document !== "undefined") document.getElementById(id)?.focus();
|
|
1402
|
+
}, [focus, id]);
|
|
1263
1403
|
const described = [bad ? `${id}-error` : "", p.hint ? `${id}-hint` : ""].filter(Boolean).join(" ");
|
|
1404
|
+
const input = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1405
|
+
f.Input,
|
|
1406
|
+
{
|
|
1407
|
+
id,
|
|
1408
|
+
name: p.name,
|
|
1409
|
+
type: p.type,
|
|
1410
|
+
value: p.value,
|
|
1411
|
+
autoComplete: p.autoComplete,
|
|
1412
|
+
required: p.required,
|
|
1413
|
+
className: f.cx("input"),
|
|
1414
|
+
"aria-invalid": bad ? true : void 0,
|
|
1415
|
+
"aria-describedby": described || void 0,
|
|
1416
|
+
onChange: (e) => p.onChange(e.target.value)
|
|
1417
|
+
}
|
|
1418
|
+
);
|
|
1419
|
+
const { Field: OwnField } = f.C;
|
|
1420
|
+
if (OwnField) {
|
|
1421
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1422
|
+
OwnField,
|
|
1423
|
+
{
|
|
1424
|
+
id,
|
|
1425
|
+
label: p.label,
|
|
1426
|
+
aside: p.aside,
|
|
1427
|
+
help: p.hint && !bad ? p.hint : void 0,
|
|
1428
|
+
error: bad ? f.say(bad) : void 0,
|
|
1429
|
+
required: p.required,
|
|
1430
|
+
className: f.own("field"),
|
|
1431
|
+
children: input
|
|
1432
|
+
}
|
|
1433
|
+
);
|
|
1434
|
+
}
|
|
1264
1435
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("field"), children: [
|
|
1265
1436
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: f.cx("label"), htmlFor: id, children: [
|
|
1266
1437
|
p.label,
|
|
1267
1438
|
p.aside
|
|
1268
1439
|
] }),
|
|
1269
|
-
|
|
1270
|
-
f.Input,
|
|
1271
|
-
{
|
|
1272
|
-
id,
|
|
1273
|
-
name: p.name,
|
|
1274
|
-
type: p.type,
|
|
1275
|
-
value: p.value,
|
|
1276
|
-
autoComplete: p.autoComplete,
|
|
1277
|
-
required: p.required,
|
|
1278
|
-
className: f.cx("input"),
|
|
1279
|
-
"aria-invalid": bad ? true : void 0,
|
|
1280
|
-
"aria-describedby": described || void 0,
|
|
1281
|
-
onChange: (e) => p.onChange(e.target.value)
|
|
1282
|
-
}
|
|
1283
|
-
),
|
|
1440
|
+
input,
|
|
1284
1441
|
p.hint && !bad && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { id: `${id}-hint`, className: f.cx("hint"), children: p.hint }),
|
|
1285
1442
|
bad && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { id: `${id}-error`, role: "alert", className: f.cx("fieldError"), children: f.say(bad) })
|
|
1286
1443
|
] });
|
|
@@ -1318,7 +1475,7 @@ function SecondStepForm(p) {
|
|
|
1318
1475
|
});
|
|
1319
1476
|
}, []);
|
|
1320
1477
|
const sendEmail = async () => {
|
|
1321
|
-
f.setBusy(
|
|
1478
|
+
f.setBusy("email");
|
|
1322
1479
|
f.setError(null);
|
|
1323
1480
|
const r = await auth.signIn.mfaSendEmail();
|
|
1324
1481
|
f.setBusy(false);
|
|
@@ -1329,7 +1486,7 @@ function SecondStepForm(p) {
|
|
|
1329
1486
|
const pushWait = (0, import_react.useRef)(null);
|
|
1330
1487
|
(0, import_react.useEffect)(() => () => pushWait.current?.abort(), []);
|
|
1331
1488
|
const sendPush = async () => {
|
|
1332
|
-
f.setBusy(
|
|
1489
|
+
f.setBusy("push");
|
|
1333
1490
|
f.setError(null);
|
|
1334
1491
|
const r = await auth.signIn.mfaPush();
|
|
1335
1492
|
f.setBusy(false);
|
|
@@ -1345,7 +1502,7 @@ function SecondStepForm(p) {
|
|
|
1345
1502
|
f.done();
|
|
1346
1503
|
};
|
|
1347
1504
|
const sendCode = async () => {
|
|
1348
|
-
f.setBusy(
|
|
1505
|
+
f.setBusy("phone");
|
|
1349
1506
|
f.setError(null);
|
|
1350
1507
|
const r = await auth.signIn.mfaSendCode();
|
|
1351
1508
|
f.setBusy(false);
|
|
@@ -1363,23 +1520,30 @@ function SecondStepForm(p) {
|
|
|
1363
1520
|
};
|
|
1364
1521
|
const general = f.error && !f.error.field ? f.error : null;
|
|
1365
1522
|
const to = phoneWay?.phone?.number ?? "";
|
|
1366
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form",
|
|
1367
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1368
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1369
|
-
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 }),
|
|
1370
|
-
pushNumber > 0 ?
|
|
1523
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "form", root: f.root, onSubmit: submit, noValidate: true, children: [
|
|
1524
|
+
/* @__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 }),
|
|
1525
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1526
|
+
phoneWay?.email && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", loading: f.loading("email"), disabled: f.busy, className: f.cx("providerButton"), onClick: () => void sendEmail(), children: f.t.sendEmailAgain }),
|
|
1527
|
+
pushNumber > 0 ? f.C.Text ? (
|
|
1528
|
+
// The application's text: the number to pick drawn large, by its own rules.
|
|
1529
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { role: "status", "aria-live": "polite", children: [
|
|
1530
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.C.Text, { as: "p", children: f.t.pushPick.replace("{n}", String(pushNumber)) }),
|
|
1531
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.C.Text, { as: "p", size: "lg", children: pushNumber }),
|
|
1532
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.C.Text, { as: "p", tone: "muted", children: f.t.pushWaiting })
|
|
1533
|
+
] })
|
|
1534
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("notice"), role: "status", "aria-live": "polite", children: [
|
|
1371
1535
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: f.t.pushPick.replace("{n}", String(pushNumber)) }),
|
|
1372
1536
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: 48, fontWeight: 700, margin: "4px 0", textAlign: "center" }, children: pushNumber }),
|
|
1373
1537
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: f.t.pushWaiting })
|
|
1374
|
-
] }) : 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 }),
|
|
1375
|
-
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) }),
|
|
1538
|
+
] }) : phoneWay?.push && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", loading: f.loading("push"), disabled: f.busy, className: f.cx("button"), onClick: () => void sendPush(), children: f.t.pushSend }),
|
|
1539
|
+
phoneWay?.phone && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", loading: f.loading("phone"), disabled: f.busy, className: f.cx("providerButton"), onClick: () => void sendCode(), children: (phoneWay.phone.channel === "whatsapp" ? f.t.sendCodeWhatsapp : f.t.sendCodeSms).replace("{to}", to) }),
|
|
1376
1540
|
/* @__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 }),
|
|
1377
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.verify })
|
|
1541
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.verify })
|
|
1378
1542
|
] });
|
|
1379
1543
|
}
|
|
1380
1544
|
function ProviderButtons(p) {
|
|
1381
1545
|
const { f } = p;
|
|
1382
|
-
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: [
|
|
1546
|
+
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", variant: "secondary", className: f.cx("providerButton"), onClick: () => p.onPick(provider.id), children: [
|
|
1383
1547
|
provider.iconUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: provider.iconUrl, alt: "", width: 18, height: 18, className: f.cx("providerIcon") }),
|
|
1384
1548
|
f.t.continueWith,
|
|
1385
1549
|
" ",
|
|
@@ -1419,7 +1583,7 @@ function SignIn(props) {
|
|
|
1419
1583
|
}, [email, methods]);
|
|
1420
1584
|
const toCompany = () => {
|
|
1421
1585
|
autofill.current?.abort();
|
|
1422
|
-
f.setBusy(
|
|
1586
|
+
f.setBusy("sso");
|
|
1423
1587
|
auth.signIn.sso({ email }, { returnTo: props.returnTo });
|
|
1424
1588
|
};
|
|
1425
1589
|
(0, import_react.useEffect)(() => {
|
|
@@ -1461,6 +1625,7 @@ function SignIn(props) {
|
|
|
1461
1625
|
if (methods?.magicLink) return sendLink();
|
|
1462
1626
|
return;
|
|
1463
1627
|
}
|
|
1628
|
+
if (step === "password" && !f.check(checkEmail(email), checkPassword(password))) return;
|
|
1464
1629
|
f.setBusy(true);
|
|
1465
1630
|
f.setError(null);
|
|
1466
1631
|
const r = step === "sent" ? await auth.signIn.emailCode({ code }) : await auth.signIn.email({ email, password, captchaToken: challenge.token });
|
|
@@ -1476,7 +1641,7 @@ function SignIn(props) {
|
|
|
1476
1641
|
};
|
|
1477
1642
|
const usePasskey = async () => {
|
|
1478
1643
|
autofill.current?.abort();
|
|
1479
|
-
f.setBusy(
|
|
1644
|
+
f.setBusy("passkey");
|
|
1480
1645
|
f.setError(null);
|
|
1481
1646
|
const r = await auth.signIn.passkey({ returnTo: props.returnTo, locale: props.locale, email });
|
|
1482
1647
|
if (r.ok && r.status === "redirected") return;
|
|
@@ -1487,7 +1652,7 @@ function SignIn(props) {
|
|
|
1487
1652
|
};
|
|
1488
1653
|
const sendLink = async () => {
|
|
1489
1654
|
autofill.current?.abort();
|
|
1490
|
-
f.setBusy(
|
|
1655
|
+
f.setBusy("link");
|
|
1491
1656
|
f.setError(null);
|
|
1492
1657
|
const r = await auth.signIn.magicLink({ email, captchaToken: challenge.token, create: props.createAccounts, returnTo: props.returnTo });
|
|
1493
1658
|
f.setBusy(false);
|
|
@@ -1498,29 +1663,29 @@ function SignIn(props) {
|
|
|
1498
1663
|
};
|
|
1499
1664
|
const general = f.error && !f.error.field ? f.error : null;
|
|
1500
1665
|
const asksEmail = offers.email;
|
|
1501
|
-
if (step === "opening") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div",
|
|
1666
|
+
if (step === "opening") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Wrap, { f, as: "div", slot: "form", root: f.root, busy: true });
|
|
1502
1667
|
if (step === "sent") {
|
|
1503
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form",
|
|
1504
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1505
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1506
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1668
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "form", root: f.root, onSubmit: submit, noValidate: true, children: [
|
|
1669
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.signInLinkSent }),
|
|
1670
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1671
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.codeFromMail }),
|
|
1507
1672
|
/* @__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 }),
|
|
1508
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.verify })
|
|
1673
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.verify })
|
|
1509
1674
|
] });
|
|
1510
1675
|
}
|
|
1511
1676
|
if (step === "code") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SecondStepForm, { f, auth });
|
|
1512
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form",
|
|
1513
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1677
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "form", root: f.root, onSubmit: submit, noValidate: true, children: [
|
|
1678
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1514
1679
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProviderButtons, { f, providers: methods?.providers ?? [], onPick: (id) => auth.signIn.social(id, { returnTo: props.returnTo }) }),
|
|
1515
|
-
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 }),
|
|
1516
|
-
asksEmail && ((methods?.providers.length ?? 0) > 0 || offers.passkey) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1680
|
+
offers.passkey && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", loading: f.loading("passkey"), disabled: f.busy, className: f.cx("providerButton"), onClick: () => void usePasskey(), children: f.t.usePasskey }),
|
|
1681
|
+
asksEmail && ((methods?.providers.length ?? 0) > 0 || offers.passkey) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Or, { f, children: f.t.orWithEmail }),
|
|
1517
1682
|
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 }),
|
|
1518
|
-
company && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(f.Button, { type: "button", disabled: f.busy, className: f.cx(company.enforced ? "button" : "providerButton"), onClick: toCompany, children: [
|
|
1683
|
+
company && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(f.Button, { type: "button", variant: company.enforced ? "primary" : "secondary", loading: f.loading("sso"), disabled: f.busy, className: f.cx(company.enforced ? "button" : "providerButton"), onClick: toCompany, children: [
|
|
1519
1684
|
f.t.continueWith,
|
|
1520
1685
|
" ",
|
|
1521
1686
|
company.name
|
|
1522
1687
|
] }),
|
|
1523
|
-
company?.enforced && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1688
|
+
company?.enforced && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.ssoOnly }),
|
|
1524
1689
|
!company?.enforced && passwordOn && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1525
1690
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1526
1691
|
Field,
|
|
@@ -1533,18 +1698,18 @@ function SignIn(props) {
|
|
|
1533
1698
|
autoComplete: "current-password",
|
|
1534
1699
|
required: true,
|
|
1535
1700
|
onChange: setPassword,
|
|
1536
|
-
aside: props.links?.forgotPassword ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1701
|
+
aside: props.links?.forgotPassword ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.forgotPassword, children: f.t.forgotPassword }) : void 0
|
|
1537
1702
|
}
|
|
1538
1703
|
),
|
|
1539
1704
|
challenge.node,
|
|
1540
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.signIn })
|
|
1705
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.signIn })
|
|
1541
1706
|
] }),
|
|
1542
1707
|
!company?.enforced && !passwordOn && methods?.magicLink && challenge.node,
|
|
1543
|
-
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 }),
|
|
1544
|
-
methods?.signUp !== false && props.links?.signUp && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1708
|
+
methods?.magicLink && !company?.enforced && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", loading: f.loading("link"), disabled: f.busy, className: f.cx("providerButton"), onClick: () => void sendLink(), children: f.t.emailMeALink }),
|
|
1709
|
+
methods?.signUp !== false && props.links?.signUp && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Note, { f, footer: true, children: [
|
|
1545
1710
|
f.t.noAccount,
|
|
1546
1711
|
" ",
|
|
1547
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1712
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signUp, children: f.t.createAccount })
|
|
1548
1713
|
] })
|
|
1549
1714
|
] });
|
|
1550
1715
|
}
|
|
@@ -1580,11 +1745,19 @@ function SignUp(props) {
|
|
|
1580
1745
|
const [acceptLegal, setAcceptLegal] = (0, import_react.useState)(false);
|
|
1581
1746
|
const [consents, setConsents] = (0, import_react.useState)({});
|
|
1582
1747
|
const legal = methods?.legal;
|
|
1748
|
+
const guest = auth.session?.user.isAnonymous === true;
|
|
1583
1749
|
const submit = async (e) => {
|
|
1584
1750
|
e.preventDefault();
|
|
1751
|
+
const asksCompany = methods?.organization?.ask === true;
|
|
1752
|
+
if (!f.check(
|
|
1753
|
+
asksCompany && checkOrganization(organization, methods?.organization?.required === true),
|
|
1754
|
+
checkName(name),
|
|
1755
|
+
checkEmail(email),
|
|
1756
|
+
newPasswordProblem(password, f.policy)
|
|
1757
|
+
)) return;
|
|
1585
1758
|
f.setBusy(true);
|
|
1586
1759
|
f.setError(null);
|
|
1587
|
-
const r =
|
|
1760
|
+
const r = guest ? await auth.account.upgrade({ name, email, password }) : await auth.signUp.email({
|
|
1588
1761
|
name,
|
|
1589
1762
|
email,
|
|
1590
1763
|
password,
|
|
@@ -1600,54 +1773,42 @@ function SignUp(props) {
|
|
|
1600
1773
|
};
|
|
1601
1774
|
const general = f.error && !f.error.field ? f.error : null;
|
|
1602
1775
|
const passwordOn = methods?.passwordSignIn !== false;
|
|
1603
|
-
const providers =
|
|
1776
|
+
const providers = guest || methods?.organization?.required ? [] : methods?.providers ?? [];
|
|
1604
1777
|
if (sent) {
|
|
1605
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div",
|
|
1606
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1607
|
-
props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1778
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "div", slot: "form", root: f.root, children: [
|
|
1779
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.checkEmail }),
|
|
1780
|
+
props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signIn, children: f.t.backToSignIn })
|
|
1608
1781
|
] });
|
|
1609
1782
|
}
|
|
1610
|
-
|
|
1783
|
+
if (methods === null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Wrap, { f, as: "div", slot: "form", root: f.root, busy: true });
|
|
1784
|
+
const footer = props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Note, { f, footer: true, children: [
|
|
1611
1785
|
f.t.haveAccount,
|
|
1612
1786
|
" ",
|
|
1613
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1787
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signIn, children: f.t.signIn })
|
|
1614
1788
|
] });
|
|
1615
1789
|
if (!passwordOn) {
|
|
1616
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div",
|
|
1617
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1790
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "div", slot: "form", root: f.root, children: [
|
|
1791
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1618
1792
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProviderButtons, { f, providers, onPick: (id) => auth.signIn.social(id, { returnTo: props.returnTo }) }),
|
|
1619
1793
|
footer
|
|
1620
1794
|
] });
|
|
1621
1795
|
}
|
|
1622
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form",
|
|
1623
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1796
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "form", root: f.root, onSubmit: submit, noValidate: true, children: [
|
|
1797
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1624
1798
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProviderButtons, { f, providers, onPick: (id) => auth.signIn.social(id, { returnTo: props.returnTo }) }),
|
|
1625
|
-
providers.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1626
|
-
methods
|
|
1799
|
+
providers.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Or, { f, children: f.t.orWithEmail }),
|
|
1800
|
+
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 }),
|
|
1627
1801
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "name", type: "text", label: f.t.name, value: name, autoComplete: "name", onChange: setName }),
|
|
1628
1802
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: "username", required: true, onChange: setEmail }),
|
|
1629
1803
|
/* @__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 }),
|
|
1630
|
-
legal && legal.documents.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
" ",
|
|
1635
|
-
legal.documents.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
1636
|
-
i > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1637
|
-
f.t.and,
|
|
1638
|
-
" "
|
|
1639
|
-
] }),
|
|
1640
|
-
/* @__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 }),
|
|
1641
|
-
" "
|
|
1642
|
-
] }, d.kind))
|
|
1643
|
-
] })
|
|
1804
|
+
legal && legal.documents.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Check, { f, name: "acceptLegal", checked: acceptLegal, required: true, onChange: setAcceptLegal, children: [
|
|
1805
|
+
f.t.iAccept,
|
|
1806
|
+
" ",
|
|
1807
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Documents, { f, documents: legal.documents })
|
|
1644
1808
|
] }),
|
|
1645
|
-
legal?.consentPurposes.map((p) => /* @__PURE__ */ (0, import_jsx_runtime.
|
|
1646
|
-
/* @__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 }) }),
|
|
1647
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: p.label })
|
|
1648
|
-
] }, p.key)),
|
|
1809
|
+
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)),
|
|
1649
1810
|
challenge.node,
|
|
1650
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.signUp }),
|
|
1811
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.signUp }),
|
|
1651
1812
|
footer
|
|
1652
1813
|
] });
|
|
1653
1814
|
}
|
|
@@ -1669,17 +1830,17 @@ function ForgotPassword(props) {
|
|
|
1669
1830
|
};
|
|
1670
1831
|
const general = f.error && !f.error.field ? f.error : null;
|
|
1671
1832
|
if (sent) {
|
|
1672
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div",
|
|
1673
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1674
|
-
props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1833
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "div", slot: "form", root: f.root, children: [
|
|
1834
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.linkSent }),
|
|
1835
|
+
props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signIn, children: f.t.backToSignIn })
|
|
1675
1836
|
] });
|
|
1676
1837
|
}
|
|
1677
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form",
|
|
1678
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1838
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "form", root: f.root, onSubmit: submit, noValidate: true, children: [
|
|
1839
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1679
1840
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: "username", required: true, onChange: setEmail }),
|
|
1680
1841
|
challenge.node,
|
|
1681
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.sendLink }),
|
|
1682
|
-
props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1842
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.sendLink }),
|
|
1843
|
+
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 }) })
|
|
1683
1844
|
] });
|
|
1684
1845
|
}
|
|
1685
1846
|
function ResetPassword(props) {
|
|
@@ -1703,23 +1864,23 @@ function ResetPassword(props) {
|
|
|
1703
1864
|
setChanged(true);
|
|
1704
1865
|
};
|
|
1705
1866
|
const general = f.error && !f.error.field ? f.error : null;
|
|
1706
|
-
const back = props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1867
|
+
const back = props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signIn, children: f.t.backToSignIn });
|
|
1707
1868
|
if (changed) {
|
|
1708
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div",
|
|
1709
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1869
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "div", slot: "form", root: f.root, children: [
|
|
1870
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.passwordChanged }),
|
|
1710
1871
|
back
|
|
1711
1872
|
] });
|
|
1712
1873
|
}
|
|
1713
1874
|
if (token === "") {
|
|
1714
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div",
|
|
1715
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1716
|
-
props.links?.forgotPassword && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1875
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "div", slot: "form", root: f.root, children: [
|
|
1876
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1877
|
+
props.links?.forgotPassword && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.forgotPassword, children: f.t.forgotPassword })
|
|
1717
1878
|
] });
|
|
1718
1879
|
}
|
|
1719
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form",
|
|
1720
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1880
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "form", root: f.root, onSubmit: submit, noValidate: true, children: [
|
|
1881
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1721
1882
|
/* @__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 }),
|
|
1722
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy || token === null, className: f.cx("button"), children: f.t.savePassword })
|
|
1883
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy || token === null, className: f.cx("button"), children: f.t.savePassword })
|
|
1723
1884
|
] });
|
|
1724
1885
|
}
|
|
1725
1886
|
function VerifyEmail(props) {
|
|
@@ -1738,11 +1899,11 @@ function VerifyEmail(props) {
|
|
|
1738
1899
|
setState("failed");
|
|
1739
1900
|
});
|
|
1740
1901
|
});
|
|
1741
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div",
|
|
1742
|
-
state === "confirming" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1743
|
-
state === "confirmed" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1744
|
-
state === "failed" && f.error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1745
|
-
state !== "confirming" && props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1902
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "div", slot: "form", root: f.root, busy: state === "confirming", children: [
|
|
1903
|
+
state === "confirming" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.confirming }),
|
|
1904
|
+
state === "confirmed" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.emailConfirmed }),
|
|
1905
|
+
state === "failed" && f.error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(f.error) }),
|
|
1906
|
+
state !== "confirming" && props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signIn, children: f.t.backToSignIn })
|
|
1746
1907
|
] });
|
|
1747
1908
|
}
|
|
1748
1909
|
function AcceptInvite(props) {
|
|
@@ -1775,37 +1936,67 @@ function AcceptInvite(props) {
|
|
|
1775
1936
|
if (r.error.code === "invalid_token") return setState("invalid");
|
|
1776
1937
|
return f.setError(r.error);
|
|
1777
1938
|
}
|
|
1939
|
+
props.onSaved?.({ kind: "invitation.accepted", email: invitation?.email ?? "", ...invitation?.organization ? { organization: invitation.organization } : {} });
|
|
1778
1940
|
if (r.status === "mfa_required") return setState("code");
|
|
1779
1941
|
f.done();
|
|
1780
1942
|
};
|
|
1781
1943
|
const general = f.error && !f.error.field ? f.error : null;
|
|
1782
|
-
const back = props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1944
|
+
const back = props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signIn, children: f.t.backToSignIn });
|
|
1783
1945
|
if (state === "opening") {
|
|
1784
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div",
|
|
1946
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Wrap, { f, as: "div", slot: "form", root: f.root, busy: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.openingInvitation }) });
|
|
1785
1947
|
}
|
|
1786
1948
|
if (state === "invalid") {
|
|
1787
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div",
|
|
1788
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1949
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "div", slot: "form", root: f.root, children: [
|
|
1950
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: general ? f.say(general) : f.t.invitationInvalid }),
|
|
1789
1951
|
back
|
|
1790
1952
|
] });
|
|
1791
1953
|
}
|
|
1792
1954
|
if (state === "code") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SecondStepForm, { f, auth });
|
|
1793
1955
|
const workspace = invitation?.workspace ?? "";
|
|
1794
1956
|
const heading = invitation?.organization ? f.t.invitedToOrganization.replace("{organization}", invitation.organization).replace("{workspace}", workspace) : f.t.invitedTo.replace("{workspace}", workspace);
|
|
1795
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form",
|
|
1796
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1797
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1798
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1957
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "form", root: f.root, onSubmit: submit, noValidate: true, children: [
|
|
1958
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: heading }),
|
|
1959
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.invitedAs.replace("{email}", invitation?.email ?? "") }),
|
|
1960
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1799
1961
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "email", name: "username", autoComplete: "username", value: invitation?.email ?? "", readOnly: true, hidden: true }),
|
|
1800
1962
|
/* @__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 }),
|
|
1801
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.acceptInvite })
|
|
1963
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.acceptInvite })
|
|
1964
|
+
] });
|
|
1965
|
+
}
|
|
1966
|
+
function PendingTerms(props) {
|
|
1967
|
+
const auth = useAuth();
|
|
1968
|
+
const f = useForm(props);
|
|
1969
|
+
const [owed, setOwed] = (0, import_react.useState)(null);
|
|
1970
|
+
(0, import_react.useEffect)(() => {
|
|
1971
|
+
void auth.account.legal().then((r) => setOwed(r.ok ? r.pending : []));
|
|
1972
|
+
}, []);
|
|
1973
|
+
if (!owed || owed.length === 0) return null;
|
|
1974
|
+
const accept = async () => {
|
|
1975
|
+
f.setBusy(true);
|
|
1976
|
+
f.setError(null);
|
|
1977
|
+
const r = await auth.account.acceptLegal({ kinds: owed.map((d) => d.kind) });
|
|
1978
|
+
f.setBusy(false);
|
|
1979
|
+
if (!r.ok) return f.setError(r.error);
|
|
1980
|
+
setOwed([]);
|
|
1981
|
+
props.onSuccess?.();
|
|
1982
|
+
};
|
|
1983
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "div", slot: "form", root: f.root, children: [
|
|
1984
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.termsChanged }),
|
|
1985
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Note, { f, children: [
|
|
1986
|
+
f.t.termsChangedHelp,
|
|
1987
|
+
" ",
|
|
1988
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Documents, { f, documents: owed })
|
|
1989
|
+
] }),
|
|
1990
|
+
f.error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(f.error) }),
|
|
1991
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), onClick: () => void accept(), children: f.t.acceptTerms })
|
|
1802
1992
|
] });
|
|
1803
1993
|
}
|
|
1994
|
+
var ACCOUNT_SECTIONS = ["profile", "email", "password", "linked", "secondStep", "phone", "passkeys", "agents", "sessions"];
|
|
1804
1995
|
function useSection(props) {
|
|
1805
1996
|
const f = useForm({ ...props, unstyled: true });
|
|
1806
1997
|
const [done, setDone] = (0, import_react.useState)(null);
|
|
1807
|
-
const run = async (action) => {
|
|
1808
|
-
f.setBusy(
|
|
1998
|
+
const run = async (action, key = SUBMIT) => {
|
|
1999
|
+
f.setBusy(key);
|
|
1809
2000
|
f.setError(null);
|
|
1810
2001
|
setDone(null);
|
|
1811
2002
|
const r = await action();
|
|
@@ -1819,37 +2010,64 @@ function useSection(props) {
|
|
|
1819
2010
|
function Account(props) {
|
|
1820
2011
|
const auth = useAuth();
|
|
1821
2012
|
const { accountUrl } = useSession();
|
|
1822
|
-
const
|
|
1823
|
-
const cx = (slot) => props.classNames?.[slot] ?? `cauthy-${slot}`;
|
|
2013
|
+
const f = useForm(props);
|
|
1824
2014
|
const [account, setAccount] = (0, import_react.useState)(null);
|
|
1825
|
-
const [sessions, setSessions] = (0, import_react.useState)([]);
|
|
1826
2015
|
(0, import_react.useEffect)(() => {
|
|
1827
2016
|
void auth.account.get().then(setAccount);
|
|
1828
|
-
void auth.account.sessions().then(setSessions);
|
|
1829
2017
|
}, []);
|
|
1830
|
-
if (account === null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div",
|
|
2018
|
+
if (account === null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Wrap, { f, as: "div", slot: "account", root: f.root, busy: true });
|
|
1831
2019
|
const when = props.formatDate ?? ((iso) => new Date(iso).toLocaleString());
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
2020
|
+
const mfa = (mfaEnabled) => setAccount({ ...account, mfaEnabled });
|
|
2021
|
+
const part = (section) => {
|
|
2022
|
+
switch (section) {
|
|
2023
|
+
case "profile":
|
|
2024
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProfilePart, { props, account, onSaved: setAccount });
|
|
2025
|
+
case "email":
|
|
2026
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EmailPart, { props, account });
|
|
2027
|
+
case "password":
|
|
2028
|
+
return account.hasPassword ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PasswordPart, { props }) : null;
|
|
2029
|
+
case "linked":
|
|
2030
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LinkedPart, { props });
|
|
2031
|
+
case "secondStep":
|
|
2032
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SecondStepPart, { props, account, onChanged: mfa });
|
|
2033
|
+
case "phone":
|
|
2034
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PhonePart, { props, account, onChanged: mfa });
|
|
2035
|
+
case "passkeys":
|
|
2036
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PasskeysPart, { props, account, accountUrl: accountUrl(), when });
|
|
2037
|
+
case "agents":
|
|
2038
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AgentsPart, { props, when });
|
|
2039
|
+
case "sessions":
|
|
2040
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SessionsPart, { props, when });
|
|
2041
|
+
}
|
|
2042
|
+
};
|
|
2043
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Wrap, { f, as: "div", slot: "account", root: f.root, children: (props.sections ?? ACCOUNT_SECTIONS).map((section) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react.Fragment, { children: part(section) }, section)) });
|
|
2044
|
+
}
|
|
2045
|
+
function AccountProfile(props) {
|
|
2046
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["profile"] });
|
|
2047
|
+
}
|
|
2048
|
+
function AccountEmail(props) {
|
|
2049
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["email"] });
|
|
2050
|
+
}
|
|
2051
|
+
function AccountPassword(props) {
|
|
2052
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["password"] });
|
|
2053
|
+
}
|
|
2054
|
+
function AccountLinked(props) {
|
|
2055
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["linked"] });
|
|
2056
|
+
}
|
|
2057
|
+
function AccountSecondStep(props) {
|
|
2058
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["secondStep"] });
|
|
2059
|
+
}
|
|
2060
|
+
function AccountPhone(props) {
|
|
2061
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["phone"] });
|
|
2062
|
+
}
|
|
2063
|
+
function AccountPasskeys(props) {
|
|
2064
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["passkeys"] });
|
|
2065
|
+
}
|
|
2066
|
+
function AccountAgents(props) {
|
|
2067
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["agents"] });
|
|
2068
|
+
}
|
|
2069
|
+
function AccountSessions(props) {
|
|
2070
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["sessions"] });
|
|
1853
2071
|
}
|
|
1854
2072
|
var OWNER = "owner";
|
|
1855
2073
|
function memberActions(seat, m) {
|
|
@@ -1861,8 +2079,9 @@ function memberActions(seat, m) {
|
|
|
1861
2079
|
inviteAgain: seat.can.manageMembers && m.invited
|
|
1862
2080
|
};
|
|
1863
2081
|
}
|
|
1864
|
-
function rolesToGive(seat, roles) {
|
|
1865
|
-
|
|
2082
|
+
function rolesToGive(seat, roles, only) {
|
|
2083
|
+
const mine = seat.role === OWNER ? roles : roles.filter((c) => c.role !== OWNER);
|
|
2084
|
+
return only ? mine.filter((c) => only(c.role, c)) : mine;
|
|
1866
2085
|
}
|
|
1867
2086
|
function OrganizationMembers(props) {
|
|
1868
2087
|
const auth = useAuth();
|
|
@@ -1879,6 +2098,8 @@ function OrganizationMembers(props) {
|
|
|
1879
2098
|
const [gone, setGone] = (0, import_react.useState)(null);
|
|
1880
2099
|
const id = props.organizationId;
|
|
1881
2100
|
const when = props.formatDate ?? ((iso) => new Date(iso).toLocaleDateString());
|
|
2101
|
+
const hidden = (action) => props.hide?.includes(action) === true;
|
|
2102
|
+
const saved = (event) => props.onSaved?.(event);
|
|
1882
2103
|
const load = async () => {
|
|
1883
2104
|
const [list, people, choices] = await Promise.all([auth.organizations.list(), auth.organizations.members(id), auth.organizations.roles(id)]);
|
|
1884
2105
|
const mine = list.find((o) => o.id === id) ?? null;
|
|
@@ -1886,135 +2107,173 @@ function OrganizationMembers(props) {
|
|
|
1886
2107
|
if (mine) setName(mine.name);
|
|
1887
2108
|
setMembers(people);
|
|
1888
2109
|
setRoles(choices ?? []);
|
|
1889
|
-
const offered = mine ? rolesToGive(mine, choices ?? []) : [];
|
|
2110
|
+
const offered = mine ? rolesToGive(mine, choices ?? [], props.roles) : [];
|
|
1890
2111
|
if (offered.length > 0 && !offered.some((c) => c.role === role)) setRole(offered[0].role);
|
|
1891
2112
|
};
|
|
1892
2113
|
(0, import_react.useEffect)(() => {
|
|
1893
2114
|
void load();
|
|
1894
2115
|
}, [id]);
|
|
1895
|
-
if (gone !== null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div",
|
|
1896
|
-
if (seat === void 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div",
|
|
1897
|
-
if (seat === null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div",
|
|
2116
|
+
if (gone !== null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Wrap, { f, as: "div", slot: "account", root, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: gone }) });
|
|
2117
|
+
if (seat === void 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Wrap, { f, as: "div", slot: "account", root, busy: true });
|
|
2118
|
+
if (seat === null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Wrap, { f, as: "div", slot: "account", root, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.organizationMissing }) });
|
|
1898
2119
|
const manage = seat.can.manageMembers;
|
|
1899
|
-
const giveable = rolesToGive(seat, roles);
|
|
1900
|
-
const
|
|
2120
|
+
const giveable = rolesToGive(seat, roles, props.roles);
|
|
2121
|
+
const roleName = (c) => props.roleLabel?.(c) || c.name || c.role;
|
|
2122
|
+
const label = (r) => {
|
|
2123
|
+
const c = roles.find((x) => x.role === r);
|
|
2124
|
+
return c ? roleName(c) : r;
|
|
2125
|
+
};
|
|
1901
2126
|
const add = async (e) => {
|
|
1902
2127
|
e.preventDefault();
|
|
1903
|
-
|
|
2128
|
+
if (!f.check(checkEmail(email))) return;
|
|
2129
|
+
const r = await run(() => auth.organizations.add(id, { email, role, locale: props.locale }), "add");
|
|
1904
2130
|
if (!r.ok) return;
|
|
1905
2131
|
setEmail("");
|
|
1906
2132
|
setDone(f.t.memberAdded.replace("{email}", r.member.email));
|
|
2133
|
+
saved({ kind: "member.added", organizationId: id, userId: r.member.userId, email: r.member.email, role: r.member.role || role });
|
|
1907
2134
|
await load();
|
|
1908
2135
|
};
|
|
1909
2136
|
const change = async (m, next) => {
|
|
1910
|
-
const r = await run(() => auth.organizations.setRole(id, m.userId, next));
|
|
1911
|
-
if (r.ok)
|
|
2137
|
+
const r = await run(() => auth.organizations.setRole(id, m.userId, next), `role:${m.userId}`);
|
|
2138
|
+
if (!r.ok) return;
|
|
2139
|
+
saved({ kind: "member.role_changed", organizationId: id, userId: m.userId, role: next, previousRole: m.role });
|
|
2140
|
+
await load();
|
|
1912
2141
|
};
|
|
1913
2142
|
const remove = async (m) => {
|
|
1914
2143
|
setAsking(null);
|
|
1915
|
-
const r = await run(() => auth.organizations.remove(id, m.userId));
|
|
2144
|
+
const r = await run(() => auth.organizations.remove(id, m.userId), `remove:${m.userId}`);
|
|
1916
2145
|
if (!r.ok) return;
|
|
2146
|
+
saved({ kind: m.you ? "member.left" : "member.removed", organizationId: id, userId: m.userId });
|
|
1917
2147
|
if (m.you) setSeat(null);
|
|
1918
2148
|
else await load();
|
|
1919
2149
|
};
|
|
1920
2150
|
const inviteAgain = async (m) => {
|
|
1921
|
-
const r = await run(() => auth.organizations.inviteAgain(id, m.userId, { locale: props.locale }));
|
|
1922
|
-
if (r.ok)
|
|
2151
|
+
const r = await run(() => auth.organizations.inviteAgain(id, m.userId, { locale: props.locale }), `invite:${m.userId}`);
|
|
2152
|
+
if (!r.ok) return;
|
|
2153
|
+
setDone(f.t.memberInvitationSent);
|
|
2154
|
+
saved({ kind: "member.invited_again", organizationId: id, userId: m.userId });
|
|
1923
2155
|
};
|
|
1924
2156
|
const rename = async (e) => {
|
|
1925
2157
|
e.preventDefault();
|
|
1926
|
-
const r = await run(() => auth.organizations.rename(id, name));
|
|
2158
|
+
const r = await run(() => auth.organizations.rename(id, name), "rename");
|
|
1927
2159
|
if (!r.ok) return;
|
|
1928
2160
|
setSeat(r.organization);
|
|
1929
2161
|
setName(r.organization.name);
|
|
1930
2162
|
setDone(f.t.organizationRenamed.replace("{name}", r.organization.name));
|
|
2163
|
+
saved({ kind: "organization.renamed", organizationId: id, name: r.organization.name });
|
|
1931
2164
|
};
|
|
1932
2165
|
const close = async (how) => {
|
|
1933
2166
|
setAsking(null);
|
|
1934
|
-
const r = await run(() => how === "archive" ? auth.organizations.archive(id) : auth.organizations.delete(id));
|
|
1935
|
-
if (r.ok)
|
|
2167
|
+
const r = await run(() => how === "archive" ? auth.organizations.archive(id) : auth.organizations.delete(id), how);
|
|
2168
|
+
if (!r.ok) return;
|
|
2169
|
+
setGone((how === "archive" ? f.t.organizationArchived : f.t.organizationDeleted).replace("{org}", seat.name));
|
|
2170
|
+
saved({ kind: how === "archive" ? "organization.archived" : "organization.deleted", organizationId: id });
|
|
2171
|
+
};
|
|
2172
|
+
const ask = (key, title, question, yes) => {
|
|
2173
|
+
const { Confirm } = f.C;
|
|
2174
|
+
if (!Confirm) return setAsking(key);
|
|
2175
|
+
void Confirm({ title, body: question, confirmLabel: title, cancelLabel: f.t.cancel, danger: true }).then((ok) => {
|
|
2176
|
+
if (ok) yes();
|
|
2177
|
+
});
|
|
1936
2178
|
};
|
|
1937
2179
|
const confirming = (text2, label2, yes) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { role: "group", "aria-label": label2, children: [
|
|
1938
2180
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: text2 }),
|
|
1939
2181
|
" ",
|
|
1940
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: yes, children: f.t.yes }),
|
|
1941
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => setAsking(null), children: f.t.cancel })
|
|
2182
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "danger", disabled: f.busy, className: f.cx("providerButton"), onClick: yes, children: f.t.yes }),
|
|
2183
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", disabled: f.busy, className: f.cx("providerButton"), onClick: () => setAsking(null), children: f.t.cancel })
|
|
1942
2184
|
] });
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
2185
|
+
const leaveQuestion = f.t.memberLeaveConfirm.replace("{org}", seat.name);
|
|
2186
|
+
const archiveQuestion = f.t.organizationArchiveConfirm.replace("{org}", seat.name);
|
|
2187
|
+
const deleteQuestion = f.t.organizationDeleteConfirm.replace("{org}", seat.name);
|
|
2188
|
+
const archiving = seat.can.archive && !hidden("archive");
|
|
2189
|
+
const deleting = seat.can.delete && !hidden("delete");
|
|
2190
|
+
const renaming = seat.can.update && !hidden("rename");
|
|
2191
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "div", slot: "account", root, children: [
|
|
2192
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "section", slot: "section", section: "members", children: [
|
|
2193
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Heading, { f, children: [
|
|
1946
2194
|
f.t.members,
|
|
1947
2195
|
" \xB7 ",
|
|
1948
2196
|
seat.name
|
|
1949
2197
|
] }),
|
|
1950
|
-
problem && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2198
|
+
problem && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(problem) }),
|
|
1951
2199
|
members === null ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1952
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1953
|
-
auth.session && (asking === auth.session.user.id ? confirming(
|
|
1954
|
-
f.
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
2200
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.membersHidden }),
|
|
2201
|
+
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)(
|
|
2202
|
+
f.Button,
|
|
2203
|
+
{
|
|
2204
|
+
type: "button",
|
|
2205
|
+
variant: "danger",
|
|
2206
|
+
loading: f.loading(`remove:${auth.session.user.id}`),
|
|
2207
|
+
disabled: f.busy,
|
|
2208
|
+
className: f.cx("providerButton"),
|
|
2209
|
+
onClick: () => ask(auth.session.user.id, f.t.memberLeave, leaveQuestion, () => void remove({ userId: auth.session.user.id, you: true })),
|
|
2210
|
+
children: f.t.memberLeave
|
|
2211
|
+
}
|
|
2212
|
+
))
|
|
1958
2213
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: f.cx("sessions"), children: members.map((m) => {
|
|
1959
2214
|
const who = m.name || m.email;
|
|
1960
2215
|
const may = memberActions(seat, m);
|
|
2216
|
+
const removable = may.remove && !(m.you && hidden("leave"));
|
|
2217
|
+
const question = m.you ? leaveQuestion : f.t.memberRemoveConfirm.replace("{who}", who);
|
|
2218
|
+
const action = m.you ? f.t.memberLeave : f.t.memberRemove;
|
|
2219
|
+
const choices = giveable.some((c) => c.role === m.role) ? giveable : [...roles.filter((c) => c.role === m.role), ...giveable];
|
|
1961
2220
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: f.cx("session"), children: [
|
|
1962
2221
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
1963
2222
|
who,
|
|
1964
2223
|
m.name ? ` \xB7 ${m.email}` : "",
|
|
1965
|
-
m.you
|
|
1966
|
-
|
|
1967
|
-
|
|
2224
|
+
m.you && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tag, { f, plain: ` (${f.t.memberYou})`, children: f.t.memberYou }),
|
|
2225
|
+
f.C.Badge ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
2226
|
+
m.invited && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tag, { f, tone: "warning", plain: "", children: f.t.memberInvited }),
|
|
2227
|
+
m.manager && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tag, { f, tone: "success", plain: "", children: f.t.memberManager })
|
|
2228
|
+
] }) : `${m.invited ? ` \xB7 ${f.t.memberInvited}` : ""}${m.manager ? ` \xB7 ${f.t.memberManager}` : ""}`,
|
|
1968
2229
|
" \xB7 ",
|
|
1969
2230
|
when(m.since)
|
|
1970
2231
|
] }),
|
|
1971
2232
|
" ",
|
|
1972
2233
|
may.changeRole && giveable.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1973
|
-
|
|
2234
|
+
Pick,
|
|
1974
2235
|
{
|
|
1975
|
-
|
|
1976
|
-
|
|
2236
|
+
f,
|
|
2237
|
+
name: `role_${m.userId}`,
|
|
2238
|
+
label: `${f.t.memberRole}: ${who}`,
|
|
1977
2239
|
value: m.role,
|
|
1978
2240
|
disabled: f.busy,
|
|
1979
|
-
|
|
1980
|
-
|
|
2241
|
+
options: choices.map((c) => ({ value: c.role, label: roleName(c) })),
|
|
2242
|
+
onChange: (next) => void change(m, next)
|
|
1981
2243
|
}
|
|
1982
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: label(m.role) }),
|
|
2244
|
+
) : 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) }),
|
|
1983
2245
|
" ",
|
|
1984
|
-
asking === m.userId ? confirming(
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
() => void remove(m)
|
|
1988
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1989
|
-
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 }),
|
|
1990
|
-
may.remove && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => setAsking(m.userId), children: m.you ? f.t.memberLeave : f.t.memberRemove })
|
|
2246
|
+
asking === m.userId ? confirming(question, action, () => void remove(m)) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
2247
|
+
may.inviteAgain && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", loading: f.loading(`invite:${m.userId}`), disabled: f.busy, className: f.cx("providerButton"), onClick: () => void inviteAgain(m), children: f.t.memberInviteAgain }),
|
|
2248
|
+
removable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "danger", loading: f.loading(`remove:${m.userId}`), disabled: f.busy, className: f.cx("providerButton"), onClick: () => ask(m.userId, action, question, () => void remove(m)), children: action })
|
|
1991
2249
|
] })
|
|
1992
2250
|
] }, m.userId);
|
|
1993
2251
|
}) }),
|
|
1994
|
-
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2252
|
+
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
|
|
1995
2253
|
] }),
|
|
1996
|
-
manage && giveable.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form",
|
|
1997
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2254
|
+
manage && giveable.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "add-member", onSubmit: add, noValidate: true, children: [
|
|
2255
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.memberAdd }),
|
|
1998
2256
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: "off", required: true, onChange: setEmail }),
|
|
1999
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
2000
|
-
|
|
2001
|
-
/* @__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)) })
|
|
2002
|
-
] }),
|
|
2003
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.memberAdd })
|
|
2257
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AddRole, { f, value: role, options: giveable.map((c) => ({ value: c.role, label: roleName(c) })), onChange: setRole }),
|
|
2258
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading("add"), disabled: f.busy, className: f.cx("button"), children: f.t.memberAdd })
|
|
2004
2259
|
] }),
|
|
2005
|
-
(
|
|
2006
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2007
|
-
|
|
2260
|
+
(renaming || archiving || deleting) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "section", slot: "section", section: "organization", children: [
|
|
2261
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.organization }),
|
|
2262
|
+
renaming && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", section: "rename", onSubmit: rename, noValidate: true, children: [
|
|
2008
2263
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "name", type: "text", label: f.t.name, value: name, autoComplete: "organization", required: true, onChange: setName }),
|
|
2009
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.organizationRename })
|
|
2264
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading("rename"), disabled: f.busy, className: f.cx("button"), children: f.t.organizationRename })
|
|
2010
2265
|
] }),
|
|
2011
|
-
asking === "archive" ? confirming(
|
|
2012
|
-
|
|
2013
|
-
|
|
2266
|
+
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: [
|
|
2267
|
+
archiving && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "danger", loading: f.loading("archive"), disabled: f.busy, className: f.cx("providerButton"), onClick: () => ask("archive", f.t.organizationArchive, archiveQuestion, () => void close("archive")), children: f.t.organizationArchive }),
|
|
2268
|
+
deleting && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "danger", loading: f.loading("delete"), disabled: f.busy, className: f.cx("providerButton"), onClick: () => ask("delete", f.t.organizationDelete, deleteQuestion, () => void close("delete")), children: f.t.organizationDelete })
|
|
2014
2269
|
] })
|
|
2015
2270
|
] })
|
|
2016
2271
|
] });
|
|
2017
2272
|
}
|
|
2273
|
+
function AddRole({ f, value, options, onChange }) {
|
|
2274
|
+
const id = (0, import_react.useId)();
|
|
2275
|
+
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 }) });
|
|
2276
|
+
}
|
|
2018
2277
|
function PasskeysPart({ props, account, accountUrl, when }) {
|
|
2019
2278
|
const auth = useAuth();
|
|
2020
2279
|
const { f, done, setDone, run, general } = useSection(props);
|
|
@@ -2031,14 +2290,15 @@ function PasskeysPart({ props, account, accountUrl, when }) {
|
|
|
2031
2290
|
}, []);
|
|
2032
2291
|
if (here === null) return null;
|
|
2033
2292
|
if (!here) {
|
|
2034
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section",
|
|
2035
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2036
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2293
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "section", slot: "section", section: "passkeys", children: [
|
|
2294
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.passkeys }),
|
|
2295
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: accountUrl, children: f.t.managePasskeys })
|
|
2037
2296
|
] });
|
|
2038
2297
|
}
|
|
2039
2298
|
const add = async (e, kind = "device") => {
|
|
2040
2299
|
e?.preventDefault();
|
|
2041
|
-
|
|
2300
|
+
if (account.hasPassword && !f.check(checkPassword(password))) return;
|
|
2301
|
+
const r = await run(() => auth.account.addPasskey({ name, password, kind }), kind === "security_key" ? "security_key" : SUBMIT);
|
|
2042
2302
|
if (!r.ok) {
|
|
2043
2303
|
if (r.error.code === "cancelled") f.setError(null);
|
|
2044
2304
|
return;
|
|
@@ -2047,28 +2307,31 @@ function PasskeysPart({ props, account, accountUrl, when }) {
|
|
|
2047
2307
|
setName("");
|
|
2048
2308
|
setPassword("");
|
|
2049
2309
|
setDone(f.t.passkeyAdded);
|
|
2310
|
+
props.onSaved?.({ kind: "passkey.added", id: r.passkey.id });
|
|
2050
2311
|
};
|
|
2051
2312
|
const remove = async (id) => {
|
|
2052
|
-
const r = await run(() => auth.account.removePasskey(id));
|
|
2053
|
-
if (r.ok)
|
|
2313
|
+
const r = await run(() => auth.account.removePasskey(id), `remove:${id}`);
|
|
2314
|
+
if (!r.ok) return;
|
|
2315
|
+
setList(list.filter((p) => p.id !== id));
|
|
2316
|
+
props.onSaved?.({ kind: "passkey.removed", id });
|
|
2054
2317
|
};
|
|
2055
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form",
|
|
2056
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2057
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2058
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2059
|
-
list.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2318
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "passkeys", onSubmit: add, noValidate: true, children: [
|
|
2319
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.passkeys }),
|
|
2320
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.passkeysHelp }),
|
|
2321
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2322
|
+
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: [
|
|
2060
2323
|
p.name || f.t.passkeyUnnamed,
|
|
2061
|
-
p.kind !== "unknown"
|
|
2324
|
+
p.kind !== "unknown" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tag, { f, plain: ` \xB7 ${f.t.passkeyKinds[p.kind]}`, children: f.t.passkeyKinds[p.kind] }),
|
|
2062
2325
|
" \xB7 ",
|
|
2063
2326
|
when(p.createdAt),
|
|
2064
2327
|
" ",
|
|
2065
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void remove(p.id), children: f.t.removePasskey })
|
|
2328
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "danger", loading: f.loading(`remove:${p.id}`), disabled: f.busy, className: f.cx("providerButton"), onClick: () => void remove(p.id), children: f.t.removePasskey })
|
|
2066
2329
|
] }, p.id)) }),
|
|
2067
2330
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "name", type: "text", label: f.t.passkeyName, value: name, autoComplete: "off", onChange: setName }),
|
|
2068
2331
|
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 }),
|
|
2069
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.addPasskeyDevice }),
|
|
2070
|
-
/* @__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 }),
|
|
2071
|
-
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2332
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.addPasskeyDevice }),
|
|
2333
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", loading: f.loading("security_key"), disabled: f.busy, className: f.cx("providerButton"), onClick: () => void add(null, "security_key"), children: f.t.addSecurityKey }),
|
|
2334
|
+
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
|
|
2072
2335
|
] });
|
|
2073
2336
|
}
|
|
2074
2337
|
function ProfilePart({ props, account, onSaved }) {
|
|
@@ -2081,14 +2344,15 @@ function ProfilePart({ props, account, onSaved }) {
|
|
|
2081
2344
|
if (!r.ok) return;
|
|
2082
2345
|
onSaved(r.account);
|
|
2083
2346
|
setDone(f.t.saved);
|
|
2347
|
+
props.onSaved?.({ kind: "profile.saved", name: r.account.name });
|
|
2084
2348
|
};
|
|
2085
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form",
|
|
2086
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2087
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2088
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2349
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "profile", onSubmit: submit, noValidate: true, children: [
|
|
2350
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.profile }),
|
|
2351
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: account.email }),
|
|
2352
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2089
2353
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "name", type: "text", label: f.t.name, value: name, autoComplete: "name", onChange: setName }),
|
|
2090
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.save }),
|
|
2091
|
-
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2354
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.save }),
|
|
2355
|
+
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
|
|
2092
2356
|
] });
|
|
2093
2357
|
}
|
|
2094
2358
|
function EmailPart({ props, account }) {
|
|
@@ -2098,19 +2362,21 @@ function EmailPart({ props, account }) {
|
|
|
2098
2362
|
const [password, setPassword] = (0, import_react.useState)("");
|
|
2099
2363
|
const submit = async (e) => {
|
|
2100
2364
|
e.preventDefault();
|
|
2365
|
+
if (!f.check(checkEmail(email), account.hasPassword && checkPassword(password))) return;
|
|
2101
2366
|
const r = await run(() => auth.account.changeEmail({ email, password }));
|
|
2102
2367
|
if (!r.ok) return;
|
|
2103
2368
|
setPassword("");
|
|
2104
2369
|
setDone(f.t.emailSent.replace("{email}", r.email));
|
|
2370
|
+
props.onSaved?.({ kind: "email.change_requested", email: r.email });
|
|
2105
2371
|
};
|
|
2106
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form",
|
|
2107
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2108
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2109
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2372
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "email", onSubmit: submit, noValidate: true, children: [
|
|
2373
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.emailAddress }),
|
|
2374
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: account.email }),
|
|
2375
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2110
2376
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.newEmail, value: email, autoComplete: "email", required: true, onChange: setEmail }),
|
|
2111
2377
|
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 }),
|
|
2112
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.changeEmail }),
|
|
2113
|
-
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2378
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.changeEmail }),
|
|
2379
|
+
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
|
|
2114
2380
|
] });
|
|
2115
2381
|
}
|
|
2116
2382
|
function LinkedPart({ props }) {
|
|
@@ -2123,27 +2389,32 @@ function LinkedPart({ props }) {
|
|
|
2123
2389
|
void auth.account.identities().then(setLinked);
|
|
2124
2390
|
void auth.methods().then((m) => setOffered(m.providers));
|
|
2125
2391
|
const back = typeof window === "undefined" ? null : new URLSearchParams(window.location.search);
|
|
2126
|
-
|
|
2127
|
-
|
|
2392
|
+
const provider = back?.get("linked");
|
|
2393
|
+
if (provider) {
|
|
2394
|
+
setCame(provider);
|
|
2395
|
+
props.onSaved?.({ kind: "identity.linked", provider });
|
|
2396
|
+
} else if (back?.get("auth_error")) f.setError({ code: back.get("auth_error"), message: "That account could not be linked. Try again." });
|
|
2128
2397
|
}, []);
|
|
2129
2398
|
if (linked === null) return null;
|
|
2130
2399
|
const name = (id) => offered.find((p) => p.id === id)?.name ?? id;
|
|
2131
2400
|
const unlink = async (provider) => {
|
|
2132
|
-
const r = await run(() => auth.account.unlink(provider));
|
|
2133
|
-
if (r.ok)
|
|
2401
|
+
const r = await run(() => auth.account.unlink(provider), `unlink:${provider}`);
|
|
2402
|
+
if (!r.ok) return;
|
|
2403
|
+
setLinked(linked.filter((x) => x.provider !== provider));
|
|
2404
|
+
props.onSaved?.({ kind: "identity.unlinked", provider });
|
|
2134
2405
|
};
|
|
2135
2406
|
const here = typeof window === "undefined" ? void 0 : window.location.pathname;
|
|
2136
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section",
|
|
2137
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2138
|
-
came && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2139
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2140
|
-
linked.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2407
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "section", slot: "section", section: "linked", children: [
|
|
2408
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.linkedAccounts }),
|
|
2409
|
+
came && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: f.t.linked }),
|
|
2410
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2411
|
+
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: [
|
|
2141
2412
|
name(x.provider),
|
|
2142
2413
|
x.email ? ` \xB7 ${x.email}` : "",
|
|
2143
2414
|
" ",
|
|
2144
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void unlink(x.provider), children: f.t.unlink })
|
|
2415
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "danger", loading: f.loading(`unlink:${x.provider}`), disabled: f.busy, className: f.cx("providerButton"), onClick: () => void unlink(x.provider), children: f.t.unlink })
|
|
2145
2416
|
] }, x.provider)) }),
|
|
2146
|
-
offered.filter((p) => !linked.some((x) => x.provider === p.id)).map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(f.Button, { type: "button", className: f.cx("providerButton"), onClick: () => auth.account.link(p.id, { returnTo: here }), children: [
|
|
2417
|
+
offered.filter((p) => !linked.some((x) => x.provider === p.id)).map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(f.Button, { type: "button", variant: "secondary", className: f.cx("providerButton"), onClick: () => auth.account.link(p.id, { returnTo: here }), children: [
|
|
2147
2418
|
f.t.linkWith,
|
|
2148
2419
|
" ",
|
|
2149
2420
|
p.name
|
|
@@ -2158,19 +2429,21 @@ function PasswordPart({ props }) {
|
|
|
2158
2429
|
usePasswordPolicy(f, useMethods(auth));
|
|
2159
2430
|
const submit = async (e) => {
|
|
2160
2431
|
e.preventDefault();
|
|
2432
|
+
if (!f.check(checkPassword(password), newPasswordProblem(newPassword, f.policy, "newPassword"))) return;
|
|
2161
2433
|
const r = await run(() => auth.account.changePassword({ password, newPassword }));
|
|
2162
2434
|
if (!r.ok) return;
|
|
2163
2435
|
setPassword("");
|
|
2164
2436
|
setNewPassword("");
|
|
2165
2437
|
setDone(f.t.passwordChangedHere);
|
|
2438
|
+
props.onSaved?.({ kind: "password.changed" });
|
|
2166
2439
|
};
|
|
2167
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form",
|
|
2168
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2169
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2440
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "password", onSubmit: submit, noValidate: true, children: [
|
|
2441
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.changePassword }),
|
|
2442
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2170
2443
|
/* @__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 }),
|
|
2171
2444
|
/* @__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 }),
|
|
2172
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.changePassword }),
|
|
2173
|
-
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2445
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.changePassword }),
|
|
2446
|
+
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
|
|
2174
2447
|
] });
|
|
2175
2448
|
}
|
|
2176
2449
|
function SecondStepPart({ props, account, onChanged }) {
|
|
@@ -2194,6 +2467,7 @@ function SecondStepPart({ props, account, onChanged }) {
|
|
|
2194
2467
|
setPassword("");
|
|
2195
2468
|
setCodes(r.recoveryCodes);
|
|
2196
2469
|
onChanged(true);
|
|
2470
|
+
props.onSaved?.({ kind: "mfa.enabled" });
|
|
2197
2471
|
};
|
|
2198
2472
|
const turnOff = async (e) => {
|
|
2199
2473
|
e.preventDefault();
|
|
@@ -2202,35 +2476,38 @@ function SecondStepPart({ props, account, onChanged }) {
|
|
|
2202
2476
|
setPassword("");
|
|
2203
2477
|
setCodes(null);
|
|
2204
2478
|
onChanged(false);
|
|
2479
|
+
props.onSaved?.({ kind: "mfa.disabled" });
|
|
2205
2480
|
};
|
|
2206
2481
|
const renew = async () => {
|
|
2207
|
-
const r = await run(() => auth.account.mfa.recoveryCodes({ password }));
|
|
2208
|
-
if (r.ok)
|
|
2482
|
+
const r = await run(() => auth.account.mfa.recoveryCodes({ password }), "codes");
|
|
2483
|
+
if (!r.ok) return;
|
|
2484
|
+
setCodes(r.recoveryCodes);
|
|
2485
|
+
props.onSaved?.({ kind: "recovery_codes.regenerated" });
|
|
2209
2486
|
};
|
|
2210
2487
|
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 });
|
|
2211
2488
|
const shown = codes && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
2212
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2489
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.keepCodes }),
|
|
2213
2490
|
/* @__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)) })
|
|
2214
2491
|
] });
|
|
2215
2492
|
if (setup) {
|
|
2216
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form",
|
|
2217
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2218
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2493
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "secondStep", onSubmit: confirm, noValidate: true, children: [
|
|
2494
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.secondStep }),
|
|
2495
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.addToApp }),
|
|
2219
2496
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { className: f.cx("secret"), children: setup.secret }),
|
|
2220
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2221
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2497
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: setup.otpauthUri, children: f.t.openInApp }),
|
|
2498
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2222
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 }),
|
|
2223
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.verify })
|
|
2500
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.verify })
|
|
2224
2501
|
] });
|
|
2225
2502
|
}
|
|
2226
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form",
|
|
2227
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2228
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2503
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "secondStep", onSubmit: account.mfaEnabled ? turnOff : start, noValidate: true, children: [
|
|
2504
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.secondStep }),
|
|
2505
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: account.mfaEnabled ? f.t.secondStepOn : f.t.secondStepOff }),
|
|
2229
2506
|
shown,
|
|
2230
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2507
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2231
2508
|
passwordField,
|
|
2232
|
-
/* @__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 }),
|
|
2233
|
-
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 })
|
|
2509
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: account.mfaEnabled ? "danger" : "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: account.mfaEnabled ? f.t.turnOff : f.t.turnOn }),
|
|
2510
|
+
account.mfaEnabled && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", loading: f.loading("codes"), disabled: f.busy, className: f.cx("providerButton"), onClick: () => void renew(), children: f.t.newRecoveryCodes })
|
|
2234
2511
|
] });
|
|
2235
2512
|
}
|
|
2236
2513
|
function PhonePart({ props, account, onChanged }) {
|
|
@@ -2265,6 +2542,7 @@ function PhonePart({ props, account, onChanged }) {
|
|
|
2265
2542
|
setPassword("");
|
|
2266
2543
|
if (r.recoveryCodes.length > 0) setCodes(r.recoveryCodes);
|
|
2267
2544
|
onChanged(true);
|
|
2545
|
+
props.onSaved?.({ kind: "phone.added", channel });
|
|
2268
2546
|
await load();
|
|
2269
2547
|
};
|
|
2270
2548
|
const remove = async (e) => {
|
|
@@ -2275,33 +2553,35 @@ function PhonePart({ props, account, onChanged }) {
|
|
|
2275
2553
|
await load();
|
|
2276
2554
|
const left = await auth.account.mfa.factors();
|
|
2277
2555
|
onChanged(Boolean(left?.totp));
|
|
2556
|
+
props.onSaved?.({ kind: "phone.removed" });
|
|
2278
2557
|
};
|
|
2279
2558
|
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 });
|
|
2280
2559
|
if (sentTo) {
|
|
2281
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form",
|
|
2282
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2283
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2284
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2560
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "phone", onSubmit: confirm, noValidate: true, children: [
|
|
2561
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.phone }),
|
|
2562
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.codeSent.replace("{to}", sentTo) }),
|
|
2563
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2285
2564
|
/* @__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 }),
|
|
2286
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.verify })
|
|
2565
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.verify })
|
|
2287
2566
|
] });
|
|
2288
2567
|
}
|
|
2289
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form",
|
|
2290
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2291
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2568
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "phone", onSubmit: ways.phone ? remove : add, noValidate: true, children: [
|
|
2569
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.phone }),
|
|
2570
|
+
/* @__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}` }),
|
|
2292
2571
|
codes && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
2293
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2572
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.keepCodes }),
|
|
2294
2573
|
/* @__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)) })
|
|
2295
2574
|
] }),
|
|
2296
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2575
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2297
2576
|
!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 }),
|
|
2298
|
-
!ways.phone && ways.phoneChannels.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2577
|
+
!ways.phone && ways.phoneChannels.length > 1 && f.C.Select && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChannelPick, { f, value: channel, channels: ways.phoneChannels, onChange: setChannel }),
|
|
2578
|
+
!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: [
|
|
2299
2579
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "radio", name: "channel", value: c, checked: channel === c, onChange: () => setChannel(c) }),
|
|
2300
2580
|
" ",
|
|
2301
2581
|
c === "whatsapp" ? f.t.byWhatsapp : f.t.bySms
|
|
2302
2582
|
] }, c)) }),
|
|
2303
2583
|
passwordField,
|
|
2304
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: ways.phone ? f.t.removePhone : f.t.addPhone })
|
|
2584
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: ways.phone ? "danger" : "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: ways.phone ? f.t.removePhone : f.t.addPhone })
|
|
2305
2585
|
] });
|
|
2306
2586
|
}
|
|
2307
2587
|
function AgentsPart({ props, when }) {
|
|
@@ -2313,13 +2593,15 @@ function AgentsPart({ props, when }) {
|
|
|
2313
2593
|
}, []);
|
|
2314
2594
|
if (list.length === 0) return null;
|
|
2315
2595
|
const disconnect = async (id) => {
|
|
2316
|
-
const r = await run(() => auth.account.disconnectAgent(id));
|
|
2317
|
-
if (r.ok)
|
|
2596
|
+
const r = await run(() => auth.account.disconnectAgent(id), `disconnect:${id}`);
|
|
2597
|
+
if (!r.ok) return;
|
|
2598
|
+
setList(list.filter((a) => a.id !== id));
|
|
2599
|
+
props.onSaved?.({ kind: "agent.disconnected", id });
|
|
2318
2600
|
};
|
|
2319
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section",
|
|
2320
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2321
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2322
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2601
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "section", slot: "section", section: "agents", children: [
|
|
2602
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.agents }),
|
|
2603
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.agentsHelp }),
|
|
2604
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2323
2605
|
/* @__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: [
|
|
2324
2606
|
a.name || f.t.anAgent,
|
|
2325
2607
|
a.redirectHost ? ` (${a.redirectHost})` : "",
|
|
@@ -2329,31 +2611,65 @@ function AgentsPart({ props, when }) {
|
|
|
2329
2611
|
" \xB7 ",
|
|
2330
2612
|
when(a.lastUsedAt),
|
|
2331
2613
|
" ",
|
|
2332
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void disconnect(a.id), children: f.t.disconnect })
|
|
2614
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "danger", loading: f.loading(`disconnect:${a.id}`), disabled: f.busy, className: f.cx("providerButton"), onClick: () => void disconnect(a.id), children: f.t.disconnect })
|
|
2333
2615
|
] }, a.id)) })
|
|
2334
2616
|
] });
|
|
2335
2617
|
}
|
|
2336
|
-
function
|
|
2618
|
+
function SessionsPart({ props, when }) {
|
|
2337
2619
|
const auth = useAuth();
|
|
2338
2620
|
const { f, run, general } = useSection(props);
|
|
2621
|
+
const [sessions, setSessions] = (0, import_react.useState)([]);
|
|
2622
|
+
(0, import_react.useEffect)(() => {
|
|
2623
|
+
void auth.account.sessions().then(setSessions);
|
|
2624
|
+
}, []);
|
|
2339
2625
|
const end = async () => {
|
|
2340
2626
|
const r = await run(() => auth.account.signOutEverywhere());
|
|
2341
2627
|
if (!r.ok) return;
|
|
2628
|
+
props.onSaved?.({ kind: "sessions.ended" });
|
|
2342
2629
|
if (props.onSignedOut) props.onSignedOut();
|
|
2343
2630
|
else window.location.assign("/");
|
|
2344
2631
|
};
|
|
2345
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
2346
|
-
|
|
2347
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2632
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "section", slot: "section", section: "sessions", children: [
|
|
2633
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.sessions }),
|
|
2634
|
+
/* @__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: [
|
|
2635
|
+
s.device || f.t.unknownDevice,
|
|
2636
|
+
" \xB7 ",
|
|
2637
|
+
s.ip,
|
|
2638
|
+
" \xB7 ",
|
|
2639
|
+
when(s.createdAt)
|
|
2640
|
+
] }, i)) }),
|
|
2641
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2642
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "danger", loading: f.loading(), disabled: f.busy, className: f.cx("button"), onClick: () => void end(), children: f.t.signOutEverywhere })
|
|
2348
2643
|
] });
|
|
2349
2644
|
}
|
|
2645
|
+
function ChannelPick({ f, value, channels, onChange }) {
|
|
2646
|
+
const id = (0, import_react.useId)();
|
|
2647
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Labelled, { f, id, label: f.t.channel, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2648
|
+
Pick,
|
|
2649
|
+
{
|
|
2650
|
+
f,
|
|
2651
|
+
id,
|
|
2652
|
+
name: "channel",
|
|
2653
|
+
value,
|
|
2654
|
+
options: channels.map((c) => ({ value: c, label: c === "whatsapp" ? f.t.byWhatsapp : f.t.bySms })),
|
|
2655
|
+
onChange: (c) => onChange(c)
|
|
2656
|
+
}
|
|
2657
|
+
) });
|
|
2658
|
+
}
|
|
2350
2659
|
|
|
2351
2660
|
// src/react.tsx
|
|
2352
2661
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
2353
2662
|
var Ctx = (0, import_react3.createContext)(null);
|
|
2663
|
+
var LocaleCtx = (0, import_react3.createContext)(() => void 0);
|
|
2354
2664
|
var AHEAD_MS = 6e4;
|
|
2355
|
-
function CauthyProvider({ children, basePath = "/api/auth", initialSession }) {
|
|
2665
|
+
function CauthyProvider({ children, basePath = "/api/auth", initialSession, locale }) {
|
|
2356
2666
|
const base = withoutTrailingSlashes(basePath);
|
|
2667
|
+
const said = (0, import_react3.useRef)(locale);
|
|
2668
|
+
said.current = locale;
|
|
2669
|
+
const readLocale = (0, import_react3.useCallback)(() => {
|
|
2670
|
+
const l = said.current;
|
|
2671
|
+
return typeof l === "function" ? l() : l;
|
|
2672
|
+
}, []);
|
|
2357
2673
|
const [session, setSession] = (0, import_react3.useState)(initialSession ?? null);
|
|
2358
2674
|
const [status, setStatus] = (0, import_react3.useState)(
|
|
2359
2675
|
initialSession === void 0 ? "loading" : initialSession === null ? "unauthenticated" : "authenticated"
|
|
@@ -2417,7 +2733,7 @@ function CauthyProvider({ children, basePath = "/api/auth", initialSession }) {
|
|
|
2417
2733
|
}),
|
|
2418
2734
|
[session, status, refresh, base]
|
|
2419
2735
|
);
|
|
2420
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Ctx.Provider, { value, children });
|
|
2736
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Ctx.Provider, { value, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(LocaleCtx.Provider, { value: readLocale, children }) });
|
|
2421
2737
|
}
|
|
2422
2738
|
function useSession() {
|
|
2423
2739
|
const ctx = (0, import_react3.useContext)(Ctx);
|
|
@@ -2426,8 +2742,9 @@ function useSession() {
|
|
|
2426
2742
|
}
|
|
2427
2743
|
function useAuth() {
|
|
2428
2744
|
const { session, status, refresh, basePath } = useSession();
|
|
2745
|
+
const locale = (0, import_react3.useContext)(LocaleCtx);
|
|
2429
2746
|
return (0, import_react3.useMemo)(() => {
|
|
2430
|
-
const client = createAuthClient({ basePath });
|
|
2747
|
+
const client = createAuthClient({ basePath, locale });
|
|
2431
2748
|
const then = async (running) => {
|
|
2432
2749
|
const r = await running;
|
|
2433
2750
|
await refresh();
|
|
@@ -2464,16 +2781,26 @@ function useAuth() {
|
|
|
2464
2781
|
status,
|
|
2465
2782
|
refresh
|
|
2466
2783
|
};
|
|
2467
|
-
}, [basePath, refresh, session, status]);
|
|
2784
|
+
}, [basePath, locale, refresh, session, status]);
|
|
2468
2785
|
}
|
|
2469
2786
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2470
2787
|
0 && (module.exports = {
|
|
2471
2788
|
AcceptInvite,
|
|
2472
2789
|
Account,
|
|
2790
|
+
AccountAgents,
|
|
2791
|
+
AccountEmail,
|
|
2792
|
+
AccountLinked,
|
|
2793
|
+
AccountPasskeys,
|
|
2794
|
+
AccountPassword,
|
|
2795
|
+
AccountPhone,
|
|
2796
|
+
AccountProfile,
|
|
2797
|
+
AccountSecondStep,
|
|
2798
|
+
AccountSessions,
|
|
2473
2799
|
CauthyProvider,
|
|
2474
2800
|
ForgotPassword,
|
|
2475
2801
|
GoogleOneTap,
|
|
2476
2802
|
OrganizationMembers,
|
|
2803
|
+
PendingTerms,
|
|
2477
2804
|
ResetPassword,
|
|
2478
2805
|
SignIn,
|
|
2479
2806
|
SignUp,
|