cauthy-auth 0.31.0 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -2
- package/dist/react.d.mts +280 -28
- package/dist/react.d.ts +280 -28
- package/dist/react.js +447 -193
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +444 -200
- 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.",
|
|
@@ -1227,8 +1245,10 @@ 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
|
|
1248
|
+
const own = (slot) => props.classNames?.[slot];
|
|
1249
|
+
const C = props.components ?? {};
|
|
1250
|
+
const Button = C.Button ?? PlainButton;
|
|
1251
|
+
const Input = C.Input ?? PlainInput;
|
|
1232
1252
|
const [error, setError] = (0, import_react.useState)(null);
|
|
1233
1253
|
const [busy, setBusy] = (0, import_react.useState)(false);
|
|
1234
1254
|
const [policy, setPolicy] = (0, import_react.useState)(void 0);
|
|
@@ -1243,7 +1263,81 @@ function useForm(props) {
|
|
|
1243
1263
|
else window.location.assign(sitePath(to) ?? sameOrigin(props.returnTo) ?? "/");
|
|
1244
1264
|
};
|
|
1245
1265
|
const root = useRoot(props);
|
|
1246
|
-
return { t, cx, Button, Input, error, setError, busy, setBusy, say, done, root, policy, setPolicy, passwordRule };
|
|
1266
|
+
return { t, cx, own, C, Button, Input, error, setError, busy, setBusy, say, done, root, policy, setPolicy, passwordRule };
|
|
1267
|
+
}
|
|
1268
|
+
function Note({ f, children, footer }) {
|
|
1269
|
+
const { Text } = f.C;
|
|
1270
|
+
if (Text) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { as: "p", tone: "muted", size: footer ? "sm" : "md", children });
|
|
1271
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: f.cx(footer ? "footer" : "notice"), children });
|
|
1272
|
+
}
|
|
1273
|
+
function Heading({ f, children }) {
|
|
1274
|
+
const { Text } = f.C;
|
|
1275
|
+
if (Text) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { as: "h2", size: "lg", children });
|
|
1276
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: f.cx("heading"), children });
|
|
1277
|
+
}
|
|
1278
|
+
function Say({ f, tone, children }) {
|
|
1279
|
+
const { Alert } = f.C;
|
|
1280
|
+
if (Alert) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Alert, { tone, children });
|
|
1281
|
+
if (tone === "danger") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "alert", className: f.cx("error"), children });
|
|
1282
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "status", className: f.cx("notice"), children });
|
|
1283
|
+
}
|
|
1284
|
+
function Or({ f, children }) {
|
|
1285
|
+
const { Divider } = f.C;
|
|
1286
|
+
if (Divider) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Divider, { label: children });
|
|
1287
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: f.cx("separator"), children });
|
|
1288
|
+
}
|
|
1289
|
+
function A({ f, href, newTab, children }) {
|
|
1290
|
+
const { Link } = f.C;
|
|
1291
|
+
if (Link) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Link, { href, newTab, children });
|
|
1292
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { className: f.cx("link"), href, target: newTab ? "_blank" : void 0, rel: newTab ? "noopener" : void 0, children });
|
|
1293
|
+
}
|
|
1294
|
+
function Tag({ f, tone, children, plain }) {
|
|
1295
|
+
const { Badge } = f.C;
|
|
1296
|
+
if (Badge) return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1297
|
+
" ",
|
|
1298
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, { tone, children })
|
|
1299
|
+
] });
|
|
1300
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: plain });
|
|
1301
|
+
}
|
|
1302
|
+
function Check(p) {
|
|
1303
|
+
const id = (0, import_react.useId)();
|
|
1304
|
+
const { f } = p;
|
|
1305
|
+
const { Checkbox } = f.C;
|
|
1306
|
+
if (Checkbox) {
|
|
1307
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Checkbox, { id, name: p.name, checked: p.checked, required: p.required, className: f.own("check"), onChange: p.onChange, children: p.children });
|
|
1308
|
+
}
|
|
1309
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: f.cx("check"), children: [
|
|
1310
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", name: p.name, checked: p.checked, required: p.required, onChange: (e) => p.onChange(e.target.checked) }),
|
|
1311
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: p.children })
|
|
1312
|
+
] });
|
|
1313
|
+
}
|
|
1314
|
+
function Pick(p) {
|
|
1315
|
+
const made = (0, import_react.useId)();
|
|
1316
|
+
const id = p.id ?? made;
|
|
1317
|
+
const { f } = p;
|
|
1318
|
+
const { Select } = f.C;
|
|
1319
|
+
if (Select) {
|
|
1320
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Select, { id, name: p.name, value: p.value, options: p.options, disabled: p.disabled, "aria-label": p.label, className: f.own("input"), onChange: p.onChange });
|
|
1321
|
+
}
|
|
1322
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("select", { id, name: p.name, "aria-label": p.label, className: f.cx("input"), value: p.value, disabled: p.disabled, onChange: (e) => p.onChange(e.target.value), children: p.options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: o.value, children: o.label }, o.value)) });
|
|
1323
|
+
}
|
|
1324
|
+
function Labelled({ f, id, label, children }) {
|
|
1325
|
+
const { Field: OwnField } = f.C;
|
|
1326
|
+
if (OwnField) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(OwnField, { id, label, className: f.own("field"), children });
|
|
1327
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: f.cx("field"), children: [
|
|
1328
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: f.cx("label"), children: label }),
|
|
1329
|
+
children
|
|
1330
|
+
] });
|
|
1331
|
+
}
|
|
1332
|
+
function Documents({ f, documents }) {
|
|
1333
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: documents.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
1334
|
+
i > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1335
|
+
f.t.and,
|
|
1336
|
+
" "
|
|
1337
|
+
] }),
|
|
1338
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: d.url, newTab: true, children: d.kind === "terms" ? f.t.termsOfService : f.t.privacyPolicy }),
|
|
1339
|
+
" "
|
|
1340
|
+
] }, d.kind)) });
|
|
1247
1341
|
}
|
|
1248
1342
|
var PASSWORD_RULES = ["needs_lowercase", "needs_uppercase", "needs_digit", "needs_symbol", "needs_classes", "breached"];
|
|
1249
1343
|
function isPasswordRule(e) {
|
|
@@ -1261,26 +1355,43 @@ function Field(p) {
|
|
|
1261
1355
|
const { f } = p;
|
|
1262
1356
|
const bad = f.error?.field === p.name ? f.error : null;
|
|
1263
1357
|
const described = [bad ? `${id}-error` : "", p.hint ? `${id}-hint` : ""].filter(Boolean).join(" ");
|
|
1358
|
+
const input = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1359
|
+
f.Input,
|
|
1360
|
+
{
|
|
1361
|
+
id,
|
|
1362
|
+
name: p.name,
|
|
1363
|
+
type: p.type,
|
|
1364
|
+
value: p.value,
|
|
1365
|
+
autoComplete: p.autoComplete,
|
|
1366
|
+
required: p.required,
|
|
1367
|
+
className: f.cx("input"),
|
|
1368
|
+
"aria-invalid": bad ? true : void 0,
|
|
1369
|
+
"aria-describedby": described || void 0,
|
|
1370
|
+
onChange: (e) => p.onChange(e.target.value)
|
|
1371
|
+
}
|
|
1372
|
+
);
|
|
1373
|
+
const { Field: OwnField } = f.C;
|
|
1374
|
+
if (OwnField) {
|
|
1375
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1376
|
+
OwnField,
|
|
1377
|
+
{
|
|
1378
|
+
id,
|
|
1379
|
+
label: p.label,
|
|
1380
|
+
aside: p.aside,
|
|
1381
|
+
help: p.hint && !bad ? p.hint : void 0,
|
|
1382
|
+
error: bad ? f.say(bad) : void 0,
|
|
1383
|
+
required: p.required,
|
|
1384
|
+
className: f.own("field"),
|
|
1385
|
+
children: input
|
|
1386
|
+
}
|
|
1387
|
+
);
|
|
1388
|
+
}
|
|
1264
1389
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("field"), children: [
|
|
1265
1390
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: f.cx("label"), htmlFor: id, children: [
|
|
1266
1391
|
p.label,
|
|
1267
1392
|
p.aside
|
|
1268
1393
|
] }),
|
|
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
|
-
),
|
|
1394
|
+
input,
|
|
1284
1395
|
p.hint && !bad && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { id: `${id}-hint`, className: f.cx("hint"), children: p.hint }),
|
|
1285
1396
|
bad && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { id: `${id}-error`, role: "alert", className: f.cx("fieldError"), children: f.say(bad) })
|
|
1286
1397
|
] });
|
|
@@ -1364,10 +1475,17 @@ function SecondStepForm(p) {
|
|
|
1364
1475
|
const general = f.error && !f.error.field ? f.error : null;
|
|
1365
1476
|
const to = phoneWay?.phone?.number ?? "";
|
|
1366
1477
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
|
|
1367
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1368
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1478
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: phoneSent ? f.t.codeSent.replace("{to}", phoneSent) : phoneWay?.email ? f.t.codeHelpEmail.replace("{to}", phoneWay.email.to) : phoneWay?.phone && !phoneWay.totp ? f.t.codeHelpPhone : f.t.codeHelp }),
|
|
1479
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1369
1480
|
phoneWay?.email && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void sendEmail(), children: f.t.sendEmailAgain }),
|
|
1370
|
-
pushNumber > 0 ?
|
|
1481
|
+
pushNumber > 0 ? f.C.Text ? (
|
|
1482
|
+
// The application's text: the number to pick drawn large, by its own rules.
|
|
1483
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { role: "status", "aria-live": "polite", children: [
|
|
1484
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.C.Text, { as: "p", children: f.t.pushPick.replace("{n}", String(pushNumber)) }),
|
|
1485
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.C.Text, { as: "p", size: "lg", children: pushNumber }),
|
|
1486
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.C.Text, { as: "p", tone: "muted", children: f.t.pushWaiting })
|
|
1487
|
+
] })
|
|
1488
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("notice"), role: "status", "aria-live": "polite", children: [
|
|
1371
1489
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: f.t.pushPick.replace("{n}", String(pushNumber)) }),
|
|
1372
1490
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: 48, fontWeight: 700, margin: "4px 0", textAlign: "center" }, children: pushNumber }),
|
|
1373
1491
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: f.t.pushWaiting })
|
|
@@ -1501,26 +1619,26 @@ function SignIn(props) {
|
|
|
1501
1619
|
if (step === "opening") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: f.cx("form"), ...f.root, "aria-busy": "true" });
|
|
1502
1620
|
if (step === "sent") {
|
|
1503
1621
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
|
|
1504
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1505
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1506
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1622
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.signInLinkSent }),
|
|
1623
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1624
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.codeFromMail }),
|
|
1507
1625
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "code", type: "text", label: f.t.code, value: code, autoComplete: "one-time-code", required: true, onChange: setCode }),
|
|
1508
1626
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.verify })
|
|
1509
1627
|
] });
|
|
1510
1628
|
}
|
|
1511
1629
|
if (step === "code") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SecondStepForm, { f, auth });
|
|
1512
1630
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
|
|
1513
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1631
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1514
1632
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProviderButtons, { f, providers: methods?.providers ?? [], onPick: (id) => auth.signIn.social(id, { returnTo: props.returnTo }) }),
|
|
1515
1633
|
offers.passkey && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void usePasskey(), children: f.t.usePasskey }),
|
|
1516
|
-
asksEmail && ((methods?.providers.length ?? 0) > 0 || offers.passkey) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1634
|
+
asksEmail && ((methods?.providers.length ?? 0) > 0 || offers.passkey) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Or, { f, children: f.t.orWithEmail }),
|
|
1517
1635
|
asksEmail && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: methods?.passkeyHere ? "username webauthn" : "username", required: true, onChange: setEmail }),
|
|
1518
1636
|
company && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(f.Button, { type: "button", disabled: f.busy, className: f.cx(company.enforced ? "button" : "providerButton"), onClick: toCompany, children: [
|
|
1519
1637
|
f.t.continueWith,
|
|
1520
1638
|
" ",
|
|
1521
1639
|
company.name
|
|
1522
1640
|
] }),
|
|
1523
|
-
company?.enforced && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1641
|
+
company?.enforced && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.ssoOnly }),
|
|
1524
1642
|
!company?.enforced && passwordOn && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1525
1643
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1526
1644
|
Field,
|
|
@@ -1533,7 +1651,7 @@ function SignIn(props) {
|
|
|
1533
1651
|
autoComplete: "current-password",
|
|
1534
1652
|
required: true,
|
|
1535
1653
|
onChange: setPassword,
|
|
1536
|
-
aside: props.links?.forgotPassword ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1654
|
+
aside: props.links?.forgotPassword ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.forgotPassword, children: f.t.forgotPassword }) : void 0
|
|
1537
1655
|
}
|
|
1538
1656
|
),
|
|
1539
1657
|
challenge.node,
|
|
@@ -1541,10 +1659,10 @@ function SignIn(props) {
|
|
|
1541
1659
|
] }),
|
|
1542
1660
|
!company?.enforced && !passwordOn && methods?.magicLink && challenge.node,
|
|
1543
1661
|
methods?.magicLink && !company?.enforced && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void sendLink(), children: f.t.emailMeALink }),
|
|
1544
|
-
methods?.signUp !== false && props.links?.signUp && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1662
|
+
methods?.signUp !== false && props.links?.signUp && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Note, { f, footer: true, children: [
|
|
1545
1663
|
f.t.noAccount,
|
|
1546
1664
|
" ",
|
|
1547
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1665
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signUp, children: f.t.createAccount })
|
|
1548
1666
|
] })
|
|
1549
1667
|
] });
|
|
1550
1668
|
}
|
|
@@ -1603,49 +1721,36 @@ function SignUp(props) {
|
|
|
1603
1721
|
const providers = auth.session?.user.isAnonymous === true || methods?.organization?.required ? [] : methods?.providers ?? [];
|
|
1604
1722
|
if (sent) {
|
|
1605
1723
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, children: [
|
|
1606
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1607
|
-
props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1724
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.checkEmail }),
|
|
1725
|
+
props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signIn, children: f.t.backToSignIn })
|
|
1608
1726
|
] });
|
|
1609
1727
|
}
|
|
1610
|
-
const footer = props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1728
|
+
const footer = props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Note, { f, footer: true, children: [
|
|
1611
1729
|
f.t.haveAccount,
|
|
1612
1730
|
" ",
|
|
1613
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1731
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signIn, children: f.t.signIn })
|
|
1614
1732
|
] });
|
|
1615
1733
|
if (!passwordOn) {
|
|
1616
1734
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, children: [
|
|
1617
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1735
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1618
1736
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProviderButtons, { f, providers, onPick: (id) => auth.signIn.social(id, { returnTo: props.returnTo }) }),
|
|
1619
1737
|
footer
|
|
1620
1738
|
] });
|
|
1621
1739
|
}
|
|
1622
1740
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
|
|
1623
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1741
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1624
1742
|
/* @__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)(
|
|
1743
|
+
providers.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Or, { f, children: f.t.orWithEmail }),
|
|
1626
1744
|
methods?.organization?.ask && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "organization", type: "text", label: f.t.company, value: organization, autoComplete: "organization", required: methods.organization.required, onChange: setOrganization }),
|
|
1627
1745
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "name", type: "text", label: f.t.name, value: name, autoComplete: "name", onChange: setName }),
|
|
1628
1746
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: "username", required: true, onChange: setEmail }),
|
|
1629
1747
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "password", type: "password", label: f.t.password, value: password, autoComplete: "new-password", required: true, onChange: setPassword, hint: f.passwordRule }),
|
|
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
|
-
] })
|
|
1748
|
+
legal && legal.documents.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Check, { f, name: "acceptLegal", checked: acceptLegal, required: true, onChange: setAcceptLegal, children: [
|
|
1749
|
+
f.t.iAccept,
|
|
1750
|
+
" ",
|
|
1751
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Documents, { f, documents: legal.documents })
|
|
1644
1752
|
] }),
|
|
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)),
|
|
1753
|
+
legal?.consentPurposes.map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Check, { f, name: `consent_${p.key}`, checked: consents[p.key] === true, required: p.required, onChange: (on) => setConsents({ ...consents, [p.key]: on }), children: p.label }, p.key)),
|
|
1649
1754
|
challenge.node,
|
|
1650
1755
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.signUp }),
|
|
1651
1756
|
footer
|
|
@@ -1670,16 +1775,16 @@ function ForgotPassword(props) {
|
|
|
1670
1775
|
const general = f.error && !f.error.field ? f.error : null;
|
|
1671
1776
|
if (sent) {
|
|
1672
1777
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, children: [
|
|
1673
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1674
|
-
props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1778
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.linkSent }),
|
|
1779
|
+
props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signIn, children: f.t.backToSignIn })
|
|
1675
1780
|
] });
|
|
1676
1781
|
}
|
|
1677
1782
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
|
|
1678
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1783
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1679
1784
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: "username", required: true, onChange: setEmail }),
|
|
1680
1785
|
challenge.node,
|
|
1681
1786
|
/* @__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)(
|
|
1787
|
+
props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, footer: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signIn, children: f.t.backToSignIn }) })
|
|
1683
1788
|
] });
|
|
1684
1789
|
}
|
|
1685
1790
|
function ResetPassword(props) {
|
|
@@ -1703,21 +1808,21 @@ function ResetPassword(props) {
|
|
|
1703
1808
|
setChanged(true);
|
|
1704
1809
|
};
|
|
1705
1810
|
const general = f.error && !f.error.field ? f.error : null;
|
|
1706
|
-
const back = props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1811
|
+
const back = props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signIn, children: f.t.backToSignIn });
|
|
1707
1812
|
if (changed) {
|
|
1708
1813
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, children: [
|
|
1709
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1814
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.passwordChanged }),
|
|
1710
1815
|
back
|
|
1711
1816
|
] });
|
|
1712
1817
|
}
|
|
1713
1818
|
if (token === "") {
|
|
1714
1819
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, children: [
|
|
1715
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1716
|
-
props.links?.forgotPassword && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1820
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1821
|
+
props.links?.forgotPassword && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.forgotPassword, children: f.t.forgotPassword })
|
|
1717
1822
|
] });
|
|
1718
1823
|
}
|
|
1719
1824
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
|
|
1720
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1825
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1721
1826
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "password", type: "password", label: f.t.newPassword, value: password, autoComplete: "new-password", required: true, onChange: setPassword, hint: f.passwordRule }),
|
|
1722
1827
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy || token === null, className: f.cx("button"), children: f.t.savePassword })
|
|
1723
1828
|
] });
|
|
@@ -1739,10 +1844,10 @@ function VerifyEmail(props) {
|
|
|
1739
1844
|
});
|
|
1740
1845
|
});
|
|
1741
1846
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, "aria-busy": state === "confirming", children: [
|
|
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)(
|
|
1847
|
+
state === "confirming" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.confirming }),
|
|
1848
|
+
state === "confirmed" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.emailConfirmed }),
|
|
1849
|
+
state === "failed" && f.error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(f.error) }),
|
|
1850
|
+
state !== "confirming" && props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signIn, children: f.t.backToSignIn })
|
|
1746
1851
|
] });
|
|
1747
1852
|
}
|
|
1748
1853
|
function AcceptInvite(props) {
|
|
@@ -1775,17 +1880,18 @@ function AcceptInvite(props) {
|
|
|
1775
1880
|
if (r.error.code === "invalid_token") return setState("invalid");
|
|
1776
1881
|
return f.setError(r.error);
|
|
1777
1882
|
}
|
|
1883
|
+
props.onSaved?.({ kind: "invitation.accepted", email: invitation?.email ?? "", ...invitation?.organization ? { organization: invitation.organization } : {} });
|
|
1778
1884
|
if (r.status === "mfa_required") return setState("code");
|
|
1779
1885
|
f.done();
|
|
1780
1886
|
};
|
|
1781
1887
|
const general = f.error && !f.error.field ? f.error : null;
|
|
1782
|
-
const back = props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1888
|
+
const back = props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signIn, children: f.t.backToSignIn });
|
|
1783
1889
|
if (state === "opening") {
|
|
1784
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: f.cx("form"), ...f.root, "aria-busy": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1890
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: f.cx("form"), ...f.root, "aria-busy": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.openingInvitation }) });
|
|
1785
1891
|
}
|
|
1786
1892
|
if (state === "invalid") {
|
|
1787
1893
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, children: [
|
|
1788
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1894
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: general ? f.say(general) : f.t.invitationInvalid }),
|
|
1789
1895
|
back
|
|
1790
1896
|
] });
|
|
1791
1897
|
}
|
|
@@ -1793,14 +1899,43 @@ function AcceptInvite(props) {
|
|
|
1793
1899
|
const workspace = invitation?.workspace ?? "";
|
|
1794
1900
|
const heading = invitation?.organization ? f.t.invitedToOrganization.replace("{organization}", invitation.organization).replace("{workspace}", workspace) : f.t.invitedTo.replace("{workspace}", workspace);
|
|
1795
1901
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
|
|
1796
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1797
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1798
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1902
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: heading }),
|
|
1903
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.invitedAs.replace("{email}", invitation?.email ?? "") }),
|
|
1904
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1799
1905
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "email", name: "username", autoComplete: "username", value: invitation?.email ?? "", readOnly: true, hidden: true }),
|
|
1800
1906
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "password", type: "password", label: f.t.choosePassword, value: password, autoComplete: "new-password", required: true, onChange: setPassword, hint: f.passwordRule }),
|
|
1801
1907
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.acceptInvite })
|
|
1802
1908
|
] });
|
|
1803
1909
|
}
|
|
1910
|
+
function PendingTerms(props) {
|
|
1911
|
+
const auth = useAuth();
|
|
1912
|
+
const f = useForm(props);
|
|
1913
|
+
const [owed, setOwed] = (0, import_react.useState)(null);
|
|
1914
|
+
(0, import_react.useEffect)(() => {
|
|
1915
|
+
void auth.account.legal().then((r) => setOwed(r.ok ? r.pending : []));
|
|
1916
|
+
}, []);
|
|
1917
|
+
if (!owed || owed.length === 0) return null;
|
|
1918
|
+
const accept = async () => {
|
|
1919
|
+
f.setBusy(true);
|
|
1920
|
+
f.setError(null);
|
|
1921
|
+
const r = await auth.account.acceptLegal({ kinds: owed.map((d) => d.kind) });
|
|
1922
|
+
f.setBusy(false);
|
|
1923
|
+
if (!r.ok) return f.setError(r.error);
|
|
1924
|
+
setOwed([]);
|
|
1925
|
+
props.onSuccess?.();
|
|
1926
|
+
};
|
|
1927
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, children: [
|
|
1928
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.termsChanged }),
|
|
1929
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Note, { f, children: [
|
|
1930
|
+
f.t.termsChangedHelp,
|
|
1931
|
+
" ",
|
|
1932
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Documents, { f, documents: owed })
|
|
1933
|
+
] }),
|
|
1934
|
+
f.error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(f.error) }),
|
|
1935
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("button"), onClick: () => void accept(), children: f.t.acceptTerms })
|
|
1936
|
+
] });
|
|
1937
|
+
}
|
|
1938
|
+
var ACCOUNT_SECTIONS = ["profile", "email", "password", "linked", "secondStep", "phone", "passkeys", "agents", "sessions"];
|
|
1804
1939
|
function useSection(props) {
|
|
1805
1940
|
const f = useForm({ ...props, unstyled: true });
|
|
1806
1941
|
const [done, setDone] = (0, import_react.useState)(null);
|
|
@@ -1819,37 +1954,65 @@ function useSection(props) {
|
|
|
1819
1954
|
function Account(props) {
|
|
1820
1955
|
const auth = useAuth();
|
|
1821
1956
|
const { accountUrl } = useSession();
|
|
1822
|
-
const {
|
|
1957
|
+
const { root } = useForm(props);
|
|
1823
1958
|
const cx = (slot) => props.classNames?.[slot] ?? `cauthy-${slot}`;
|
|
1824
1959
|
const [account, setAccount] = (0, import_react.useState)(null);
|
|
1825
|
-
const [sessions, setSessions] = (0, import_react.useState)([]);
|
|
1826
1960
|
(0, import_react.useEffect)(() => {
|
|
1827
1961
|
void auth.account.get().then(setAccount);
|
|
1828
|
-
void auth.account.sessions().then(setSessions);
|
|
1829
1962
|
}, []);
|
|
1830
1963
|
if (account === null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cx("account"), ...root, "aria-busy": "true" });
|
|
1831
1964
|
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
|
-
|
|
1965
|
+
const mfa = (mfaEnabled) => setAccount({ ...account, mfaEnabled });
|
|
1966
|
+
const part = (section) => {
|
|
1967
|
+
switch (section) {
|
|
1968
|
+
case "profile":
|
|
1969
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProfilePart, { props, account, onSaved: setAccount });
|
|
1970
|
+
case "email":
|
|
1971
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EmailPart, { props, account });
|
|
1972
|
+
case "password":
|
|
1973
|
+
return account.hasPassword ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PasswordPart, { props }) : null;
|
|
1974
|
+
case "linked":
|
|
1975
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LinkedPart, { props });
|
|
1976
|
+
case "secondStep":
|
|
1977
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SecondStepPart, { props, account, onChanged: mfa });
|
|
1978
|
+
case "phone":
|
|
1979
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PhonePart, { props, account, onChanged: mfa });
|
|
1980
|
+
case "passkeys":
|
|
1981
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PasskeysPart, { props, account, accountUrl: accountUrl(), when });
|
|
1982
|
+
case "agents":
|
|
1983
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AgentsPart, { props, when });
|
|
1984
|
+
case "sessions":
|
|
1985
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SessionsPart, { props, when });
|
|
1986
|
+
}
|
|
1987
|
+
};
|
|
1988
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cx("account"), ...root, children: (props.sections ?? ACCOUNT_SECTIONS).map((section) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react.Fragment, { children: part(section) }, section)) });
|
|
1989
|
+
}
|
|
1990
|
+
function AccountProfile(props) {
|
|
1991
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["profile"] });
|
|
1992
|
+
}
|
|
1993
|
+
function AccountEmail(props) {
|
|
1994
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["email"] });
|
|
1995
|
+
}
|
|
1996
|
+
function AccountPassword(props) {
|
|
1997
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["password"] });
|
|
1998
|
+
}
|
|
1999
|
+
function AccountLinked(props) {
|
|
2000
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["linked"] });
|
|
2001
|
+
}
|
|
2002
|
+
function AccountSecondStep(props) {
|
|
2003
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["secondStep"] });
|
|
2004
|
+
}
|
|
2005
|
+
function AccountPhone(props) {
|
|
2006
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["phone"] });
|
|
2007
|
+
}
|
|
2008
|
+
function AccountPasskeys(props) {
|
|
2009
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["passkeys"] });
|
|
2010
|
+
}
|
|
2011
|
+
function AccountAgents(props) {
|
|
2012
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["agents"] });
|
|
2013
|
+
}
|
|
2014
|
+
function AccountSessions(props) {
|
|
2015
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["sessions"] });
|
|
1853
2016
|
}
|
|
1854
2017
|
var OWNER = "owner";
|
|
1855
2018
|
function memberActions(seat, m) {
|
|
@@ -1861,8 +2024,9 @@ function memberActions(seat, m) {
|
|
|
1861
2024
|
inviteAgain: seat.can.manageMembers && m.invited
|
|
1862
2025
|
};
|
|
1863
2026
|
}
|
|
1864
|
-
function rolesToGive(seat, roles) {
|
|
1865
|
-
|
|
2027
|
+
function rolesToGive(seat, roles, only) {
|
|
2028
|
+
const mine = seat.role === OWNER ? roles : roles.filter((c) => c.role !== OWNER);
|
|
2029
|
+
return only ? mine.filter((c) => only(c.role, c)) : mine;
|
|
1866
2030
|
}
|
|
1867
2031
|
function OrganizationMembers(props) {
|
|
1868
2032
|
const auth = useAuth();
|
|
@@ -1879,6 +2043,8 @@ function OrganizationMembers(props) {
|
|
|
1879
2043
|
const [gone, setGone] = (0, import_react.useState)(null);
|
|
1880
2044
|
const id = props.organizationId;
|
|
1881
2045
|
const when = props.formatDate ?? ((iso) => new Date(iso).toLocaleDateString());
|
|
2046
|
+
const hidden = (action) => props.hide?.includes(action) === true;
|
|
2047
|
+
const saved = (event) => props.onSaved?.(event);
|
|
1882
2048
|
const load = async () => {
|
|
1883
2049
|
const [list, people, choices] = await Promise.all([auth.organizations.list(), auth.organizations.members(id), auth.organizations.roles(id)]);
|
|
1884
2050
|
const mine = list.find((o) => o.id === id) ?? null;
|
|
@@ -1886,17 +2052,17 @@ function OrganizationMembers(props) {
|
|
|
1886
2052
|
if (mine) setName(mine.name);
|
|
1887
2053
|
setMembers(people);
|
|
1888
2054
|
setRoles(choices ?? []);
|
|
1889
|
-
const offered = mine ? rolesToGive(mine, choices ?? []) : [];
|
|
2055
|
+
const offered = mine ? rolesToGive(mine, choices ?? [], props.roles) : [];
|
|
1890
2056
|
if (offered.length > 0 && !offered.some((c) => c.role === role)) setRole(offered[0].role);
|
|
1891
2057
|
};
|
|
1892
2058
|
(0, import_react.useEffect)(() => {
|
|
1893
2059
|
void load();
|
|
1894
2060
|
}, [id]);
|
|
1895
|
-
if (gone !== null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: f.cx("account"), ...root, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2061
|
+
if (gone !== null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: f.cx("account"), ...root, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: gone }) });
|
|
1896
2062
|
if (seat === void 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: f.cx("account"), ...root, "aria-busy": "true" });
|
|
1897
|
-
if (seat === null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: f.cx("account"), ...root, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2063
|
+
if (seat === null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: f.cx("account"), ...root, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.organizationMissing }) });
|
|
1898
2064
|
const manage = seat.can.manageMembers;
|
|
1899
|
-
const giveable = rolesToGive(seat, roles);
|
|
2065
|
+
const giveable = rolesToGive(seat, roles, props.roles);
|
|
1900
2066
|
const label = (r) => roles.find((c) => c.role === r)?.name || r;
|
|
1901
2067
|
const add = async (e) => {
|
|
1902
2068
|
e.preventDefault();
|
|
@@ -1904,22 +2070,28 @@ function OrganizationMembers(props) {
|
|
|
1904
2070
|
if (!r.ok) return;
|
|
1905
2071
|
setEmail("");
|
|
1906
2072
|
setDone(f.t.memberAdded.replace("{email}", r.member.email));
|
|
2073
|
+
saved({ kind: "member.added", organizationId: id, userId: r.member.userId, email: r.member.email, role: r.member.role || role });
|
|
1907
2074
|
await load();
|
|
1908
2075
|
};
|
|
1909
2076
|
const change = async (m, next) => {
|
|
1910
2077
|
const r = await run(() => auth.organizations.setRole(id, m.userId, next));
|
|
1911
|
-
if (r.ok)
|
|
2078
|
+
if (!r.ok) return;
|
|
2079
|
+
saved({ kind: "member.role_changed", organizationId: id, userId: m.userId, role: next, previousRole: m.role });
|
|
2080
|
+
await load();
|
|
1912
2081
|
};
|
|
1913
2082
|
const remove = async (m) => {
|
|
1914
2083
|
setAsking(null);
|
|
1915
2084
|
const r = await run(() => auth.organizations.remove(id, m.userId));
|
|
1916
2085
|
if (!r.ok) return;
|
|
2086
|
+
saved({ kind: m.you ? "member.left" : "member.removed", organizationId: id, userId: m.userId });
|
|
1917
2087
|
if (m.you) setSeat(null);
|
|
1918
2088
|
else await load();
|
|
1919
2089
|
};
|
|
1920
2090
|
const inviteAgain = async (m) => {
|
|
1921
2091
|
const r = await run(() => auth.organizations.inviteAgain(id, m.userId, { locale: props.locale }));
|
|
1922
|
-
if (r.ok)
|
|
2092
|
+
if (!r.ok) return;
|
|
2093
|
+
setDone(f.t.memberInvitationSent);
|
|
2094
|
+
saved({ kind: "member.invited_again", organizationId: id, userId: m.userId });
|
|
1923
2095
|
};
|
|
1924
2096
|
const rename = async (e) => {
|
|
1925
2097
|
e.preventDefault();
|
|
@@ -1928,11 +2100,21 @@ function OrganizationMembers(props) {
|
|
|
1928
2100
|
setSeat(r.organization);
|
|
1929
2101
|
setName(r.organization.name);
|
|
1930
2102
|
setDone(f.t.organizationRenamed.replace("{name}", r.organization.name));
|
|
2103
|
+
saved({ kind: "organization.renamed", organizationId: id, name: r.organization.name });
|
|
1931
2104
|
};
|
|
1932
2105
|
const close = async (how) => {
|
|
1933
2106
|
setAsking(null);
|
|
1934
2107
|
const r = await run(() => how === "archive" ? auth.organizations.archive(id) : auth.organizations.delete(id));
|
|
1935
|
-
if (r.ok)
|
|
2108
|
+
if (!r.ok) return;
|
|
2109
|
+
setGone((how === "archive" ? f.t.organizationArchived : f.t.organizationDeleted).replace("{org}", seat.name));
|
|
2110
|
+
saved({ kind: how === "archive" ? "organization.archived" : "organization.deleted", organizationId: id });
|
|
2111
|
+
};
|
|
2112
|
+
const ask = (key, title, question, yes) => {
|
|
2113
|
+
const { Confirm } = f.C;
|
|
2114
|
+
if (!Confirm) return setAsking(key);
|
|
2115
|
+
void Confirm({ title, body: question, confirmLabel: title, cancelLabel: f.t.cancel, danger: true }).then((ok) => {
|
|
2116
|
+
if (ok) yes();
|
|
2117
|
+
});
|
|
1936
2118
|
};
|
|
1937
2119
|
const confirming = (text2, label2, yes) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { role: "group", "aria-label": label2, children: [
|
|
1938
2120
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: text2 }),
|
|
@@ -1940,81 +2122,96 @@ function OrganizationMembers(props) {
|
|
|
1940
2122
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: yes, children: f.t.yes }),
|
|
1941
2123
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => setAsking(null), children: f.t.cancel })
|
|
1942
2124
|
] });
|
|
2125
|
+
const leaveQuestion = f.t.memberLeaveConfirm.replace("{org}", seat.name);
|
|
2126
|
+
const archiveQuestion = f.t.organizationArchiveConfirm.replace("{org}", seat.name);
|
|
2127
|
+
const deleteQuestion = f.t.organizationDeleteConfirm.replace("{org}", seat.name);
|
|
2128
|
+
const archiving = seat.can.archive && !hidden("archive");
|
|
2129
|
+
const deleting = seat.can.delete && !hidden("delete");
|
|
2130
|
+
const renaming = seat.can.update && !hidden("rename");
|
|
1943
2131
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("account"), ...root, children: [
|
|
1944
2132
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: f.cx("section"), children: [
|
|
1945
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
2133
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Heading, { f, children: [
|
|
1946
2134
|
f.t.members,
|
|
1947
2135
|
" \xB7 ",
|
|
1948
2136
|
seat.name
|
|
1949
2137
|
] }),
|
|
1950
|
-
problem && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2138
|
+
problem && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(problem) }),
|
|
1951
2139
|
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
|
-
|
|
2140
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.membersHidden }),
|
|
2141
|
+
auth.session && !hidden("leave") && (asking === auth.session.user.id ? confirming(leaveQuestion, f.t.memberLeave, () => void remove({ userId: auth.session.user.id, you: true })) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2142
|
+
f.Button,
|
|
2143
|
+
{
|
|
2144
|
+
type: "button",
|
|
2145
|
+
disabled: f.busy,
|
|
2146
|
+
className: f.cx("providerButton"),
|
|
2147
|
+
onClick: () => ask(auth.session.user.id, f.t.memberLeave, leaveQuestion, () => void remove({ userId: auth.session.user.id, you: true })),
|
|
2148
|
+
children: f.t.memberLeave
|
|
2149
|
+
}
|
|
2150
|
+
))
|
|
1958
2151
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: f.cx("sessions"), children: members.map((m) => {
|
|
1959
2152
|
const who = m.name || m.email;
|
|
1960
2153
|
const may = memberActions(seat, m);
|
|
2154
|
+
const removable = may.remove && !(m.you && hidden("leave"));
|
|
2155
|
+
const question = m.you ? leaveQuestion : f.t.memberRemoveConfirm.replace("{who}", who);
|
|
2156
|
+
const action = m.you ? f.t.memberLeave : f.t.memberRemove;
|
|
2157
|
+
const choices = giveable.some((c) => c.role === m.role) ? giveable : [...roles.filter((c) => c.role === m.role), ...giveable];
|
|
1961
2158
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: f.cx("session"), children: [
|
|
1962
2159
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
1963
2160
|
who,
|
|
1964
2161
|
m.name ? ` \xB7 ${m.email}` : "",
|
|
1965
|
-
m.you
|
|
1966
|
-
|
|
1967
|
-
|
|
2162
|
+
m.you && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tag, { f, plain: ` (${f.t.memberYou})`, children: f.t.memberYou }),
|
|
2163
|
+
f.C.Badge ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
2164
|
+
m.invited && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tag, { f, tone: "warning", plain: "", children: f.t.memberInvited }),
|
|
2165
|
+
m.manager && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tag, { f, tone: "success", plain: "", children: f.t.memberManager })
|
|
2166
|
+
] }) : `${m.invited ? ` \xB7 ${f.t.memberInvited}` : ""}${m.manager ? ` \xB7 ${f.t.memberManager}` : ""}`,
|
|
1968
2167
|
" \xB7 ",
|
|
1969
2168
|
when(m.since)
|
|
1970
2169
|
] }),
|
|
1971
2170
|
" ",
|
|
1972
2171
|
may.changeRole && giveable.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1973
|
-
|
|
2172
|
+
Pick,
|
|
1974
2173
|
{
|
|
1975
|
-
|
|
1976
|
-
|
|
2174
|
+
f,
|
|
2175
|
+
name: `role_${m.userId}`,
|
|
2176
|
+
label: `${f.t.memberRole}: ${who}`,
|
|
1977
2177
|
value: m.role,
|
|
1978
2178
|
disabled: f.busy,
|
|
1979
|
-
|
|
1980
|
-
|
|
2179
|
+
options: choices.map((c) => ({ value: c.role, label: c.name || c.role })),
|
|
2180
|
+
onChange: (next) => void change(m, next)
|
|
1981
2181
|
}
|
|
1982
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: label(m.role) }),
|
|
2182
|
+
) : f.C.Badge ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.C.Badge, { tone: "neutral", children: label(m.role) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: label(m.role) }),
|
|
1983
2183
|
" ",
|
|
1984
|
-
asking === m.userId ? confirming(
|
|
1985
|
-
m.you ? f.t.memberLeaveConfirm.replace("{org}", seat.name) : f.t.memberRemoveConfirm.replace("{who}", who),
|
|
1986
|
-
m.you ? f.t.memberLeave : f.t.memberRemove,
|
|
1987
|
-
() => void remove(m)
|
|
1988
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
2184
|
+
asking === m.userId ? confirming(question, action, () => void remove(m)) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1989
2185
|
may.inviteAgain && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void inviteAgain(m), children: f.t.memberInviteAgain }),
|
|
1990
|
-
|
|
2186
|
+
removable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => ask(m.userId, action, question, () => void remove(m)), children: action })
|
|
1991
2187
|
] })
|
|
1992
2188
|
] }, m.userId);
|
|
1993
2189
|
}) }),
|
|
1994
|
-
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2190
|
+
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
|
|
1995
2191
|
] }),
|
|
1996
2192
|
manage && giveable.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: add, noValidate: true, children: [
|
|
1997
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2193
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.memberAdd }),
|
|
1998
2194
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: "off", required: true, onChange: setEmail }),
|
|
1999
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
2000
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: f.cx("label"), children: f.t.memberRole }),
|
|
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
|
-
] }),
|
|
2195
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AddRole, { f, value: role, options: giveable.map((c) => ({ value: c.role, label: c.name || c.role })), onChange: setRole }),
|
|
2003
2196
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.memberAdd })
|
|
2004
2197
|
] }),
|
|
2005
|
-
(
|
|
2006
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2007
|
-
|
|
2198
|
+
(renaming || archiving || deleting) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: f.cx("section"), children: [
|
|
2199
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.organization }),
|
|
2200
|
+
renaming && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { onSubmit: rename, noValidate: true, children: [
|
|
2008
2201
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "name", type: "text", label: f.t.name, value: name, autoComplete: "organization", required: true, onChange: setName }),
|
|
2009
2202
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.organizationRename })
|
|
2010
2203
|
] }),
|
|
2011
|
-
asking === "archive" ? confirming(
|
|
2012
|
-
|
|
2013
|
-
|
|
2204
|
+
asking === "archive" ? confirming(archiveQuestion, f.t.organizationArchive, () => void close("archive")) : asking === "delete" ? confirming(deleteQuestion, f.t.organizationDelete, () => void close("delete")) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
2205
|
+
archiving && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => ask("archive", f.t.organizationArchive, archiveQuestion, () => void close("archive")), children: f.t.organizationArchive }),
|
|
2206
|
+
deleting && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => ask("delete", f.t.organizationDelete, deleteQuestion, () => void close("delete")), children: f.t.organizationDelete })
|
|
2014
2207
|
] })
|
|
2015
2208
|
] })
|
|
2016
2209
|
] });
|
|
2017
2210
|
}
|
|
2211
|
+
function AddRole({ f, value, options, onChange }) {
|
|
2212
|
+
const id = (0, import_react.useId)();
|
|
2213
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Labelled, { f, id, label: f.t.memberRole, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Pick, { f, id, name: "role", value, options, onChange }) });
|
|
2214
|
+
}
|
|
2018
2215
|
function PasskeysPart({ props, account, accountUrl, when }) {
|
|
2019
2216
|
const auth = useAuth();
|
|
2020
2217
|
const { f, done, setDone, run, general } = useSection(props);
|
|
@@ -2032,8 +2229,8 @@ function PasskeysPart({ props, account, accountUrl, when }) {
|
|
|
2032
2229
|
if (here === null) return null;
|
|
2033
2230
|
if (!here) {
|
|
2034
2231
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: f.cx("section"), children: [
|
|
2035
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2036
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2232
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.passkeys }),
|
|
2233
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: accountUrl, children: f.t.managePasskeys })
|
|
2037
2234
|
] });
|
|
2038
2235
|
}
|
|
2039
2236
|
const add = async (e, kind = "device") => {
|
|
@@ -2047,18 +2244,21 @@ function PasskeysPart({ props, account, accountUrl, when }) {
|
|
|
2047
2244
|
setName("");
|
|
2048
2245
|
setPassword("");
|
|
2049
2246
|
setDone(f.t.passkeyAdded);
|
|
2247
|
+
props.onSaved?.({ kind: "passkey.added", id: r.passkey.id });
|
|
2050
2248
|
};
|
|
2051
2249
|
const remove = async (id) => {
|
|
2052
2250
|
const r = await run(() => auth.account.removePasskey(id));
|
|
2053
|
-
if (r.ok)
|
|
2251
|
+
if (!r.ok) return;
|
|
2252
|
+
setList(list.filter((p) => p.id !== id));
|
|
2253
|
+
props.onSaved?.({ kind: "passkey.removed", id });
|
|
2054
2254
|
};
|
|
2055
2255
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: add, noValidate: true, children: [
|
|
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)(
|
|
2256
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.passkeys }),
|
|
2257
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.passkeysHelp }),
|
|
2258
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2259
|
+
list.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.noPasskeys }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: f.cx("sessions"), children: list.map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: f.cx("session"), children: [
|
|
2060
2260
|
p.name || f.t.passkeyUnnamed,
|
|
2061
|
-
p.kind !== "unknown"
|
|
2261
|
+
p.kind !== "unknown" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tag, { f, plain: ` \xB7 ${f.t.passkeyKinds[p.kind]}`, children: f.t.passkeyKinds[p.kind] }),
|
|
2062
2262
|
" \xB7 ",
|
|
2063
2263
|
when(p.createdAt),
|
|
2064
2264
|
" ",
|
|
@@ -2068,7 +2268,7 @@ function PasskeysPart({ props, account, accountUrl, when }) {
|
|
|
2068
2268
|
account.hasPassword && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "password", type: "password", label: f.t.currentPassword, value: password, autoComplete: "current-password", required: true, onChange: setPassword }),
|
|
2069
2269
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.addPasskeyDevice }),
|
|
2070
2270
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void add(null, "security_key"), children: f.t.addSecurityKey }),
|
|
2071
|
-
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2271
|
+
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
|
|
2072
2272
|
] });
|
|
2073
2273
|
}
|
|
2074
2274
|
function ProfilePart({ props, account, onSaved }) {
|
|
@@ -2081,14 +2281,15 @@ function ProfilePart({ props, account, onSaved }) {
|
|
|
2081
2281
|
if (!r.ok) return;
|
|
2082
2282
|
onSaved(r.account);
|
|
2083
2283
|
setDone(f.t.saved);
|
|
2284
|
+
props.onSaved?.({ kind: "profile.saved", name: r.account.name });
|
|
2084
2285
|
};
|
|
2085
2286
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: submit, noValidate: true, children: [
|
|
2086
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2087
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2088
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2287
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.profile }),
|
|
2288
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: account.email }),
|
|
2289
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2089
2290
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "name", type: "text", label: f.t.name, value: name, autoComplete: "name", onChange: setName }),
|
|
2090
2291
|
/* @__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)(
|
|
2292
|
+
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
|
|
2092
2293
|
] });
|
|
2093
2294
|
}
|
|
2094
2295
|
function EmailPart({ props, account }) {
|
|
@@ -2102,15 +2303,16 @@ function EmailPart({ props, account }) {
|
|
|
2102
2303
|
if (!r.ok) return;
|
|
2103
2304
|
setPassword("");
|
|
2104
2305
|
setDone(f.t.emailSent.replace("{email}", r.email));
|
|
2306
|
+
props.onSaved?.({ kind: "email.change_requested", email: r.email });
|
|
2105
2307
|
};
|
|
2106
2308
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: submit, noValidate: true, children: [
|
|
2107
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2108
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2109
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2309
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.emailAddress }),
|
|
2310
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: account.email }),
|
|
2311
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2110
2312
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.newEmail, value: email, autoComplete: "email", required: true, onChange: setEmail }),
|
|
2111
2313
|
account.hasPassword && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "password", type: "password", label: f.t.currentPassword, value: password, autoComplete: "current-password", required: true, onChange: setPassword }),
|
|
2112
2314
|
/* @__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)(
|
|
2315
|
+
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
|
|
2114
2316
|
] });
|
|
2115
2317
|
}
|
|
2116
2318
|
function LinkedPart({ props }) {
|
|
@@ -2123,21 +2325,26 @@ function LinkedPart({ props }) {
|
|
|
2123
2325
|
void auth.account.identities().then(setLinked);
|
|
2124
2326
|
void auth.methods().then((m) => setOffered(m.providers));
|
|
2125
2327
|
const back = typeof window === "undefined" ? null : new URLSearchParams(window.location.search);
|
|
2126
|
-
|
|
2127
|
-
|
|
2328
|
+
const provider = back?.get("linked");
|
|
2329
|
+
if (provider) {
|
|
2330
|
+
setCame(provider);
|
|
2331
|
+
props.onSaved?.({ kind: "identity.linked", provider });
|
|
2332
|
+
} else if (back?.get("auth_error")) f.setError({ code: back.get("auth_error"), message: "That account could not be linked. Try again." });
|
|
2128
2333
|
}, []);
|
|
2129
2334
|
if (linked === null) return null;
|
|
2130
2335
|
const name = (id) => offered.find((p) => p.id === id)?.name ?? id;
|
|
2131
2336
|
const unlink = async (provider) => {
|
|
2132
2337
|
const r = await run(() => auth.account.unlink(provider));
|
|
2133
|
-
if (r.ok)
|
|
2338
|
+
if (!r.ok) return;
|
|
2339
|
+
setLinked(linked.filter((x) => x.provider !== provider));
|
|
2340
|
+
props.onSaved?.({ kind: "identity.unlinked", provider });
|
|
2134
2341
|
};
|
|
2135
2342
|
const here = typeof window === "undefined" ? void 0 : window.location.pathname;
|
|
2136
2343
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: f.cx("section"), children: [
|
|
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)(
|
|
2344
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.linkedAccounts }),
|
|
2345
|
+
came && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: f.t.linked }),
|
|
2346
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2347
|
+
linked.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.noLinkedAccounts }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: f.cx("sessions"), children: linked.map((x) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: f.cx("session"), children: [
|
|
2141
2348
|
name(x.provider),
|
|
2142
2349
|
x.email ? ` \xB7 ${x.email}` : "",
|
|
2143
2350
|
" ",
|
|
@@ -2163,14 +2370,15 @@ function PasswordPart({ props }) {
|
|
|
2163
2370
|
setPassword("");
|
|
2164
2371
|
setNewPassword("");
|
|
2165
2372
|
setDone(f.t.passwordChangedHere);
|
|
2373
|
+
props.onSaved?.({ kind: "password.changed" });
|
|
2166
2374
|
};
|
|
2167
2375
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: submit, noValidate: true, children: [
|
|
2168
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2169
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2376
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.changePassword }),
|
|
2377
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2170
2378
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "password", type: "password", label: f.t.currentPassword, value: password, autoComplete: "current-password", required: true, onChange: setPassword }),
|
|
2171
2379
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "newPassword", type: "password", label: f.t.newPassword, value: newPassword, autoComplete: "new-password", required: true, onChange: setNewPassword, hint: f.passwordRule }),
|
|
2172
2380
|
/* @__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)(
|
|
2381
|
+
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
|
|
2174
2382
|
] });
|
|
2175
2383
|
}
|
|
2176
2384
|
function SecondStepPart({ props, account, onChanged }) {
|
|
@@ -2194,6 +2402,7 @@ function SecondStepPart({ props, account, onChanged }) {
|
|
|
2194
2402
|
setPassword("");
|
|
2195
2403
|
setCodes(r.recoveryCodes);
|
|
2196
2404
|
onChanged(true);
|
|
2405
|
+
props.onSaved?.({ kind: "mfa.enabled" });
|
|
2197
2406
|
};
|
|
2198
2407
|
const turnOff = async (e) => {
|
|
2199
2408
|
e.preventDefault();
|
|
@@ -2202,32 +2411,35 @@ function SecondStepPart({ props, account, onChanged }) {
|
|
|
2202
2411
|
setPassword("");
|
|
2203
2412
|
setCodes(null);
|
|
2204
2413
|
onChanged(false);
|
|
2414
|
+
props.onSaved?.({ kind: "mfa.disabled" });
|
|
2205
2415
|
};
|
|
2206
2416
|
const renew = async () => {
|
|
2207
2417
|
const r = await run(() => auth.account.mfa.recoveryCodes({ password }));
|
|
2208
|
-
if (r.ok)
|
|
2418
|
+
if (!r.ok) return;
|
|
2419
|
+
setCodes(r.recoveryCodes);
|
|
2420
|
+
props.onSaved?.({ kind: "recovery_codes.regenerated" });
|
|
2209
2421
|
};
|
|
2210
2422
|
const passwordField = account.hasPassword && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "password", type: "password", label: f.t.currentPassword, value: password, autoComplete: "current-password", required: true, onChange: setPassword });
|
|
2211
2423
|
const shown = codes && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
2212
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2424
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.keepCodes }),
|
|
2213
2425
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: f.cx("codes"), children: codes.map((c) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: c }) }, c)) })
|
|
2214
2426
|
] });
|
|
2215
2427
|
if (setup) {
|
|
2216
2428
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: confirm, noValidate: true, children: [
|
|
2217
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2218
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2429
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.secondStep }),
|
|
2430
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.addToApp }),
|
|
2219
2431
|
/* @__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)(
|
|
2432
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: setup.otpauthUri, children: f.t.openInApp }),
|
|
2433
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2222
2434
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "code", type: "text", label: f.t.code, value: code, autoComplete: "one-time-code", required: true, onChange: setCode }),
|
|
2223
2435
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.verify })
|
|
2224
2436
|
] });
|
|
2225
2437
|
}
|
|
2226
2438
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: account.mfaEnabled ? turnOff : start, noValidate: true, children: [
|
|
2227
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2228
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2439
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.secondStep }),
|
|
2440
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: account.mfaEnabled ? f.t.secondStepOn : f.t.secondStepOff }),
|
|
2229
2441
|
shown,
|
|
2230
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2442
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2231
2443
|
passwordField,
|
|
2232
2444
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: account.mfaEnabled ? f.t.turnOff : f.t.turnOn }),
|
|
2233
2445
|
account.mfaEnabled && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void renew(), children: f.t.newRecoveryCodes })
|
|
@@ -2265,6 +2477,7 @@ function PhonePart({ props, account, onChanged }) {
|
|
|
2265
2477
|
setPassword("");
|
|
2266
2478
|
if (r.recoveryCodes.length > 0) setCodes(r.recoveryCodes);
|
|
2267
2479
|
onChanged(true);
|
|
2480
|
+
props.onSaved?.({ kind: "phone.added", channel });
|
|
2268
2481
|
await load();
|
|
2269
2482
|
};
|
|
2270
2483
|
const remove = async (e) => {
|
|
@@ -2275,27 +2488,29 @@ function PhonePart({ props, account, onChanged }) {
|
|
|
2275
2488
|
await load();
|
|
2276
2489
|
const left = await auth.account.mfa.factors();
|
|
2277
2490
|
onChanged(Boolean(left?.totp));
|
|
2491
|
+
props.onSaved?.({ kind: "phone.removed" });
|
|
2278
2492
|
};
|
|
2279
2493
|
const passwordField = account.hasPassword && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "password", type: "password", label: f.t.currentPassword, value: password, autoComplete: "current-password", required: true, onChange: setPassword });
|
|
2280
2494
|
if (sentTo) {
|
|
2281
2495
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: confirm, noValidate: true, children: [
|
|
2282
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2283
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2284
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2496
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.phone }),
|
|
2497
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.codeSent.replace("{to}", sentTo) }),
|
|
2498
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2285
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 }),
|
|
2286
2500
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.verify })
|
|
2287
2501
|
] });
|
|
2288
2502
|
}
|
|
2289
2503
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: ways.phone ? remove : add, noValidate: true, children: [
|
|
2290
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2291
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2504
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.phone }),
|
|
2505
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: ways.phone ? f.t.phoneOn.replace("{to}", ways.phone.number) : `${f.t.phoneOff} ${f.t.phoneHelp}` }),
|
|
2292
2506
|
codes && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
2293
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2507
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.keepCodes }),
|
|
2294
2508
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: f.cx("codes"), children: codes.map((c) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: c }) }, c)) })
|
|
2295
2509
|
] }),
|
|
2296
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2510
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2297
2511
|
!ways.phone && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "phone", type: "tel", label: f.t.phone, value: number, autoComplete: "tel", required: true, onChange: setNumber }),
|
|
2298
|
-
!ways.phone && ways.phoneChannels.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2512
|
+
!ways.phone && ways.phoneChannels.length > 1 && f.C.Select && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChannelPick, { f, value: channel, channels: ways.phoneChannels, onChange: setChannel }),
|
|
2513
|
+
!ways.phone && ways.phoneChannels.length > 1 && !f.C.Select && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: f.cx("field"), role: "radiogroup", children: ways.phoneChannels.map((c) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: f.cx("label"), children: [
|
|
2299
2514
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "radio", name: "channel", value: c, checked: channel === c, onChange: () => setChannel(c) }),
|
|
2300
2515
|
" ",
|
|
2301
2516
|
c === "whatsapp" ? f.t.byWhatsapp : f.t.bySms
|
|
@@ -2314,12 +2529,14 @@ function AgentsPart({ props, when }) {
|
|
|
2314
2529
|
if (list.length === 0) return null;
|
|
2315
2530
|
const disconnect = async (id) => {
|
|
2316
2531
|
const r = await run(() => auth.account.disconnectAgent(id));
|
|
2317
|
-
if (r.ok)
|
|
2532
|
+
if (!r.ok) return;
|
|
2533
|
+
setList(list.filter((a) => a.id !== id));
|
|
2534
|
+
props.onSaved?.({ kind: "agent.disconnected", id });
|
|
2318
2535
|
};
|
|
2319
2536
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: f.cx("section"), children: [
|
|
2320
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2321
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2322
|
-
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2537
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.agents }),
|
|
2538
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.agentsHelp }),
|
|
2539
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2323
2540
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: f.cx("sessions"), children: list.map((a) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: f.cx("session"), children: [
|
|
2324
2541
|
a.name || f.t.anAgent,
|
|
2325
2542
|
a.redirectHost ? ` (${a.redirectHost})` : "",
|
|
@@ -2333,20 +2550,47 @@ function AgentsPart({ props, when }) {
|
|
|
2333
2550
|
] }, a.id)) })
|
|
2334
2551
|
] });
|
|
2335
2552
|
}
|
|
2336
|
-
function
|
|
2553
|
+
function SessionsPart({ props, when }) {
|
|
2337
2554
|
const auth = useAuth();
|
|
2338
2555
|
const { f, run, general } = useSection(props);
|
|
2556
|
+
const [sessions, setSessions] = (0, import_react.useState)([]);
|
|
2557
|
+
(0, import_react.useEffect)(() => {
|
|
2558
|
+
void auth.account.sessions().then(setSessions);
|
|
2559
|
+
}, []);
|
|
2339
2560
|
const end = async () => {
|
|
2340
2561
|
const r = await run(() => auth.account.signOutEverywhere());
|
|
2341
2562
|
if (!r.ok) return;
|
|
2563
|
+
props.onSaved?.({ kind: "sessions.ended" });
|
|
2342
2564
|
if (props.onSignedOut) props.onSignedOut();
|
|
2343
2565
|
else window.location.assign("/");
|
|
2344
2566
|
};
|
|
2345
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
2346
|
-
|
|
2567
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: f.cx("section"), children: [
|
|
2568
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.sessions }),
|
|
2569
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: f.cx("sessions"), children: sessions.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: f.cx("session"), children: [
|
|
2570
|
+
s.device || f.t.unknownDevice,
|
|
2571
|
+
" \xB7 ",
|
|
2572
|
+
s.ip,
|
|
2573
|
+
" \xB7 ",
|
|
2574
|
+
when(s.createdAt)
|
|
2575
|
+
] }, i)) }),
|
|
2576
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2347
2577
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("button"), onClick: () => void end(), children: f.t.signOutEverywhere })
|
|
2348
2578
|
] });
|
|
2349
2579
|
}
|
|
2580
|
+
function ChannelPick({ f, value, channels, onChange }) {
|
|
2581
|
+
const id = (0, import_react.useId)();
|
|
2582
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Labelled, { f, id, label: f.t.channel, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2583
|
+
Pick,
|
|
2584
|
+
{
|
|
2585
|
+
f,
|
|
2586
|
+
id,
|
|
2587
|
+
name: "channel",
|
|
2588
|
+
value,
|
|
2589
|
+
options: channels.map((c) => ({ value: c, label: c === "whatsapp" ? f.t.byWhatsapp : f.t.bySms })),
|
|
2590
|
+
onChange: (c) => onChange(c)
|
|
2591
|
+
}
|
|
2592
|
+
) });
|
|
2593
|
+
}
|
|
2350
2594
|
|
|
2351
2595
|
// src/react.tsx
|
|
2352
2596
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
@@ -2470,10 +2714,20 @@ function useAuth() {
|
|
|
2470
2714
|
0 && (module.exports = {
|
|
2471
2715
|
AcceptInvite,
|
|
2472
2716
|
Account,
|
|
2717
|
+
AccountAgents,
|
|
2718
|
+
AccountEmail,
|
|
2719
|
+
AccountLinked,
|
|
2720
|
+
AccountPasskeys,
|
|
2721
|
+
AccountPassword,
|
|
2722
|
+
AccountPhone,
|
|
2723
|
+
AccountProfile,
|
|
2724
|
+
AccountSecondStep,
|
|
2725
|
+
AccountSessions,
|
|
2473
2726
|
CauthyProvider,
|
|
2474
2727
|
ForgotPassword,
|
|
2475
2728
|
GoogleOneTap,
|
|
2476
2729
|
OrganizationMembers,
|
|
2730
|
+
PendingTerms,
|
|
2477
2731
|
ResetPassword,
|
|
2478
2732
|
SignIn,
|
|
2479
2733
|
SignUp,
|