cauthy-auth 0.36.0 → 0.37.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 +6 -2
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +6 -0
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.mts +12 -0
- package/dist/react.d.ts +12 -0
- package/dist/react.js +277 -45
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +277 -45
- package/dist/react.mjs.map +1 -1
- package/package.json +1 -1
package/dist/react.d.mts
CHANGED
|
@@ -1225,6 +1225,18 @@ interface AuthTexts {
|
|
|
1225
1225
|
recoveryCodes: string;
|
|
1226
1226
|
newRecoveryCodes: string;
|
|
1227
1227
|
keepCodes: string;
|
|
1228
|
+
/** Beside recovery codes just made: copy them all, or save them as a text file. */
|
|
1229
|
+
copyCodes: string;
|
|
1230
|
+
downloadCodes: string;
|
|
1231
|
+
codesCopied: string;
|
|
1232
|
+
/** Said when the browser would not copy: the codes stay on screen to select. */
|
|
1233
|
+
codesNotCopied: string;
|
|
1234
|
+
/** The action that opens the form of a part already set (the name). */
|
|
1235
|
+
change: string;
|
|
1236
|
+
/** The password part, when the account has one. */
|
|
1237
|
+
passwordSet: string;
|
|
1238
|
+
/** Opens the form that adds another passkey, once the account has one. */
|
|
1239
|
+
addAnotherPasskey: string;
|
|
1228
1240
|
passkeys: string;
|
|
1229
1241
|
managePasskeys: string;
|
|
1230
1242
|
passkeysHelp: string;
|
package/dist/react.d.ts
CHANGED
|
@@ -1225,6 +1225,18 @@ interface AuthTexts {
|
|
|
1225
1225
|
recoveryCodes: string;
|
|
1226
1226
|
newRecoveryCodes: string;
|
|
1227
1227
|
keepCodes: string;
|
|
1228
|
+
/** Beside recovery codes just made: copy them all, or save them as a text file. */
|
|
1229
|
+
copyCodes: string;
|
|
1230
|
+
downloadCodes: string;
|
|
1231
|
+
codesCopied: string;
|
|
1232
|
+
/** Said when the browser would not copy: the codes stay on screen to select. */
|
|
1233
|
+
codesNotCopied: string;
|
|
1234
|
+
/** The action that opens the form of a part already set (the name). */
|
|
1235
|
+
change: string;
|
|
1236
|
+
/** The password part, when the account has one. */
|
|
1237
|
+
passwordSet: string;
|
|
1238
|
+
/** Opens the form that adds another passkey, once the account has one. */
|
|
1239
|
+
addAnotherPasskey: string;
|
|
1228
1240
|
passkeys: string;
|
|
1229
1241
|
managePasskeys: string;
|
|
1230
1242
|
passkeysHelp: string;
|
package/dist/react.js
CHANGED
|
@@ -850,6 +850,13 @@ var TEXTS = {
|
|
|
850
850
|
recoveryCodes: "Recovery codes",
|
|
851
851
|
newRecoveryCodes: "New recovery codes",
|
|
852
852
|
keepCodes: "Keep these codes somewhere safe. Each works once, and they are not shown again.",
|
|
853
|
+
copyCodes: "Copy all",
|
|
854
|
+
downloadCodes: "Download .txt",
|
|
855
|
+
codesCopied: "The codes were copied.",
|
|
856
|
+
codesNotCopied: "The codes could not be copied. Select them and copy them by hand.",
|
|
857
|
+
change: "Change",
|
|
858
|
+
passwordSet: "Your account has a password.",
|
|
859
|
+
addAnotherPasskey: "Add a passkey",
|
|
853
860
|
passkeys: "Passkeys",
|
|
854
861
|
managePasskeys: "Add or remove a passkey",
|
|
855
862
|
passkeysHelp: "Sign in with your fingerprint, your face or your device's lock, without a password.",
|
|
@@ -1034,6 +1041,13 @@ var TEXTS = {
|
|
|
1034
1041
|
recoveryCodes: "C\xF3digos de recuperaci\xF3n",
|
|
1035
1042
|
newRecoveryCodes: "Nuevos c\xF3digos de recuperaci\xF3n",
|
|
1036
1043
|
keepCodes: "Guarda estos c\xF3digos en un lugar seguro. Cada uno sirve una vez y no se vuelven a mostrar.",
|
|
1044
|
+
copyCodes: "Copiar todos",
|
|
1045
|
+
downloadCodes: "Descargar .txt",
|
|
1046
|
+
codesCopied: "Los c\xF3digos quedaron copiados.",
|
|
1047
|
+
codesNotCopied: "No se pudieron copiar los c\xF3digos. Selecci\xF3nalos y c\xF3pialos a mano.",
|
|
1048
|
+
change: "Cambiar",
|
|
1049
|
+
passwordSet: "Tu cuenta tiene contrase\xF1a.",
|
|
1050
|
+
addAnotherPasskey: "Agregar una llave de acceso",
|
|
1037
1051
|
passkeys: "Llaves de acceso",
|
|
1038
1052
|
managePasskeys: "Agregar o quitar una llave de acceso",
|
|
1039
1053
|
passkeysHelp: "Entra con tu huella, tu rostro o el bloqueo de tu dispositivo, sin contrase\xF1a.",
|
|
@@ -2209,6 +2223,8 @@ function OrganizationMembers(props) {
|
|
|
2209
2223
|
const [role, setRole] = (0, import_react.useState)("");
|
|
2210
2224
|
const [name, setName] = (0, import_react.useState)("");
|
|
2211
2225
|
const [asking, setAsking] = (0, import_react.useState)(null);
|
|
2226
|
+
const [adding, setAdding] = (0, import_react.useState)(false);
|
|
2227
|
+
const [renamingOpen, setRenamingOpen] = (0, import_react.useState)(false);
|
|
2212
2228
|
const [gone, setGone] = (0, import_react.useState)(null);
|
|
2213
2229
|
const id = props.organizationId;
|
|
2214
2230
|
const when = props.formatDate ?? ((iso) => new Date(iso).toLocaleDateString());
|
|
@@ -2243,6 +2259,7 @@ function OrganizationMembers(props) {
|
|
|
2243
2259
|
const r = await run(() => auth.organizations.add(id, { email, role, locale: props.locale }), "add");
|
|
2244
2260
|
if (!r.ok) return;
|
|
2245
2261
|
setEmail("");
|
|
2262
|
+
setAdding(false);
|
|
2246
2263
|
setDone(f.t.memberAdded.replace("{email}", r.member.email));
|
|
2247
2264
|
saved({ kind: "member.added", organizationId: id, userId: r.member.userId, email: r.member.email, role: r.member.role || role });
|
|
2248
2265
|
await load();
|
|
@@ -2273,6 +2290,7 @@ function OrganizationMembers(props) {
|
|
|
2273
2290
|
if (!r.ok) return;
|
|
2274
2291
|
setSeat(r.organization);
|
|
2275
2292
|
setName(r.organization.name);
|
|
2293
|
+
setRenamingOpen(false);
|
|
2276
2294
|
setDone(f.t.organizationRenamed.replace("{name}", r.organization.name));
|
|
2277
2295
|
saved({ kind: "organization.renamed", organizationId: id, name: r.organization.name });
|
|
2278
2296
|
};
|
|
@@ -2302,6 +2320,24 @@ function OrganizationMembers(props) {
|
|
|
2302
2320
|
const archiving = seat.can.archive && !hidden("archive");
|
|
2303
2321
|
const deleting = seat.can.delete && !hidden("delete");
|
|
2304
2322
|
const renaming = seat.can.update && !hidden("rename");
|
|
2323
|
+
const alone = members !== null && members.every((m) => m.you);
|
|
2324
|
+
const addOpen = adding || alone;
|
|
2325
|
+
const open = (form) => {
|
|
2326
|
+
setDone(null);
|
|
2327
|
+
f.setError(null);
|
|
2328
|
+
if (form === "add") setAdding(true);
|
|
2329
|
+
else setRenamingOpen(true);
|
|
2330
|
+
};
|
|
2331
|
+
const cancelAdd = () => {
|
|
2332
|
+
setEmail("");
|
|
2333
|
+
f.setError(null);
|
|
2334
|
+
setAdding(false);
|
|
2335
|
+
};
|
|
2336
|
+
const cancelRename = () => {
|
|
2337
|
+
setName(seat.name);
|
|
2338
|
+
f.setError(null);
|
|
2339
|
+
setRenamingOpen(false);
|
|
2340
|
+
};
|
|
2305
2341
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "div", slot: "account", root, children: [
|
|
2306
2342
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "section", slot: "section", section: "members", children: [
|
|
2307
2343
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Heading, { f, children: [
|
|
@@ -2365,18 +2401,23 @@ function OrganizationMembers(props) {
|
|
|
2365
2401
|
}) }),
|
|
2366
2402
|
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
|
|
2367
2403
|
] }),
|
|
2368
|
-
manage && giveable.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "add-member", onSubmit: add, noValidate: true, children: [
|
|
2404
|
+
manage && giveable.length > 0 && (addOpen ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "add-member", onSubmit: add, noValidate: true, children: [
|
|
2369
2405
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.memberAdd }),
|
|
2370
2406
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: "off", required: true, onChange: setEmail }),
|
|
2371
2407
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AddRole, { f, value: role, options: giveable.map((c) => ({ value: c.role, label: roleName(c) })), onChange: setRole }),
|
|
2372
|
-
/* @__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 })
|
|
2373
|
-
|
|
2408
|
+
/* @__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 }),
|
|
2409
|
+
!alone && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Cancel, { f, onClick: cancelAdd })
|
|
2410
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Wrap, { f, as: "div", slot: "section", section: "add-member", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", disabled: f.busy, className: f.cx("providerButton"), onClick: () => open("add"), children: f.t.memberAdd }) })),
|
|
2374
2411
|
(renaming || archiving || deleting) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "section", slot: "section", section: "organization", children: [
|
|
2375
2412
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.organization }),
|
|
2376
|
-
renaming && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", section: "rename", onSubmit: rename, noValidate: true, children: [
|
|
2413
|
+
renaming && (renamingOpen ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", section: "rename", onSubmit: rename, noValidate: true, children: [
|
|
2377
2414
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "name", type: "text", label: f.t.name, value: name, autoComplete: "organization", required: true, onChange: setName }),
|
|
2378
|
-
/* @__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 })
|
|
2379
|
-
|
|
2415
|
+
/* @__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 }),
|
|
2416
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Cancel, { f, onClick: cancelRename })
|
|
2417
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
2418
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: seat.name }),
|
|
2419
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", disabled: f.busy, className: f.cx("providerButton"), onClick: () => open("rename"), children: f.t.organizationRename })
|
|
2420
|
+
] })),
|
|
2380
2421
|
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: [
|
|
2381
2422
|
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 }),
|
|
2382
2423
|
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 })
|
|
@@ -2395,6 +2436,7 @@ function PasskeysPart({ props, account, accountUrl, when }) {
|
|
|
2395
2436
|
const [list, setList] = (0, import_react.useState)([]);
|
|
2396
2437
|
const [name, setName] = (0, import_react.useState)("");
|
|
2397
2438
|
const [password, setPassword] = (0, import_react.useState)("");
|
|
2439
|
+
const [adding, setAdding] = (0, import_react.useState)(false);
|
|
2398
2440
|
(0, import_react.useEffect)(() => {
|
|
2399
2441
|
void auth.methods().then((m) => {
|
|
2400
2442
|
const can2 = m.passkeyHere && canUsePasskeys();
|
|
@@ -2420,6 +2462,7 @@ function PasskeysPart({ props, account, accountUrl, when }) {
|
|
|
2420
2462
|
setList([...list, r.passkey]);
|
|
2421
2463
|
setName("");
|
|
2422
2464
|
setPassword("");
|
|
2465
|
+
setAdding(false);
|
|
2423
2466
|
setDone(f.t.passkeyAdded);
|
|
2424
2467
|
props.onSaved?.({ kind: "passkey.added", id: r.passkey.id });
|
|
2425
2468
|
};
|
|
@@ -2429,43 +2472,123 @@ function PasskeysPart({ props, account, accountUrl, when }) {
|
|
|
2429
2472
|
setList(list.filter((p) => p.id !== id));
|
|
2430
2473
|
props.onSaved?.({ kind: "passkey.removed", id });
|
|
2431
2474
|
};
|
|
2475
|
+
const cancel = () => {
|
|
2476
|
+
setName("");
|
|
2477
|
+
setPassword("");
|
|
2478
|
+
f.setError(null);
|
|
2479
|
+
setAdding(false);
|
|
2480
|
+
};
|
|
2481
|
+
const listed = 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: [
|
|
2482
|
+
p.name || f.t.passkeyUnnamed,
|
|
2483
|
+
p.kind !== "unknown" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tag, { f, plain: ` \xB7 ${f.t.passkeyKinds[p.kind]}`, children: f.t.passkeyKinds[p.kind] }),
|
|
2484
|
+
" \xB7 ",
|
|
2485
|
+
when(p.createdAt),
|
|
2486
|
+
" ",
|
|
2487
|
+
/* @__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 })
|
|
2488
|
+
] }, p.id)) });
|
|
2489
|
+
if (list.length > 0 && !adding) {
|
|
2490
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "div", slot: "section", section: "passkeys", children: [
|
|
2491
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.passkeys }),
|
|
2492
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.passkeysHelp }),
|
|
2493
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2494
|
+
listed,
|
|
2495
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", disabled: f.busy, className: f.cx("providerButton"), onClick: () => {
|
|
2496
|
+
setDone(null);
|
|
2497
|
+
f.setError(null);
|
|
2498
|
+
setAdding(true);
|
|
2499
|
+
}, children: f.t.addAnotherPasskey }),
|
|
2500
|
+
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
|
|
2501
|
+
] });
|
|
2502
|
+
}
|
|
2432
2503
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "passkeys", onSubmit: add, noValidate: true, children: [
|
|
2433
2504
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.passkeys }),
|
|
2434
2505
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.passkeysHelp }),
|
|
2435
2506
|
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2436
|
-
|
|
2437
|
-
p.name || f.t.passkeyUnnamed,
|
|
2438
|
-
p.kind !== "unknown" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tag, { f, plain: ` \xB7 ${f.t.passkeyKinds[p.kind]}`, children: f.t.passkeyKinds[p.kind] }),
|
|
2439
|
-
" \xB7 ",
|
|
2440
|
-
when(p.createdAt),
|
|
2441
|
-
" ",
|
|
2442
|
-
/* @__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 })
|
|
2443
|
-
] }, p.id)) }),
|
|
2507
|
+
listed,
|
|
2444
2508
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "name", type: "text", label: f.t.passkeyName, value: name, autoComplete: "off", onChange: setName }),
|
|
2445
2509
|
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 }),
|
|
2446
2510
|
/* @__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 }),
|
|
2447
2511
|
/* @__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 }),
|
|
2512
|
+
list.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Cancel, { f, onClick: cancel }),
|
|
2448
2513
|
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
|
|
2449
2514
|
] });
|
|
2450
2515
|
}
|
|
2516
|
+
function Cancel({ f, onClick }) {
|
|
2517
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", disabled: f.busy, className: f.cx("providerButton"), onClick, children: f.t.cancel });
|
|
2518
|
+
}
|
|
2519
|
+
function RecoveryCodes({ f, codes }) {
|
|
2520
|
+
const [copied, setCopied] = (0, import_react.useState)(null);
|
|
2521
|
+
(0, import_react.useEffect)(() => setCopied(null), [codes]);
|
|
2522
|
+
const copy = async () => {
|
|
2523
|
+
try {
|
|
2524
|
+
await navigator.clipboard.writeText(codes.join("\n"));
|
|
2525
|
+
setCopied(true);
|
|
2526
|
+
} catch {
|
|
2527
|
+
setCopied(false);
|
|
2528
|
+
}
|
|
2529
|
+
};
|
|
2530
|
+
const download = () => {
|
|
2531
|
+
const file = new Blob([`${f.t.recoveryCodes}
|
|
2532
|
+
|
|
2533
|
+
${codes.join("\n")}
|
|
2534
|
+
`], { type: "text/plain;charset=utf-8" });
|
|
2535
|
+
const url = URL.createObjectURL(file);
|
|
2536
|
+
const a = document.createElement("a");
|
|
2537
|
+
a.href = url;
|
|
2538
|
+
a.download = "recovery-codes.txt";
|
|
2539
|
+
document.body.appendChild(a);
|
|
2540
|
+
a.click();
|
|
2541
|
+
a.remove();
|
|
2542
|
+
setTimeout(() => URL.revokeObjectURL(url), 0);
|
|
2543
|
+
};
|
|
2544
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
2545
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.keepCodes }),
|
|
2546
|
+
/* @__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)) }),
|
|
2547
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", className: f.cx("providerButton"), onClick: () => void copy(), children: f.t.copyCodes }),
|
|
2548
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", className: f.cx("providerButton"), onClick: download, children: f.t.downloadCodes }),
|
|
2549
|
+
copied === true && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: f.t.codesCopied }),
|
|
2550
|
+
copied === false && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.t.codesNotCopied })
|
|
2551
|
+
] });
|
|
2552
|
+
}
|
|
2451
2553
|
function ProfilePart({ props, account, onSaved }) {
|
|
2452
2554
|
const auth = useAuth();
|
|
2453
2555
|
const { f, done, setDone, run, general } = useSection(props);
|
|
2454
2556
|
const [name, setName] = (0, import_react.useState)(account.name);
|
|
2557
|
+
const [editing, setEditing] = (0, import_react.useState)(account.name.trim() === "");
|
|
2455
2558
|
const submit = async (e) => {
|
|
2456
2559
|
e.preventDefault();
|
|
2457
2560
|
const r = await run(() => auth.account.update({ name }));
|
|
2458
2561
|
if (!r.ok) return;
|
|
2459
2562
|
onSaved(r.account);
|
|
2563
|
+
setName(r.account.name);
|
|
2564
|
+
setEditing(r.account.name.trim() === "");
|
|
2460
2565
|
setDone(f.t.saved);
|
|
2461
2566
|
props.onSaved?.({ kind: "profile.saved", name: r.account.name });
|
|
2462
2567
|
};
|
|
2568
|
+
const cancel = () => {
|
|
2569
|
+
setName(account.name);
|
|
2570
|
+
f.setError(null);
|
|
2571
|
+
setEditing(false);
|
|
2572
|
+
};
|
|
2573
|
+
if (!editing) {
|
|
2574
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "div", slot: "section", section: "profile", children: [
|
|
2575
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.profile }),
|
|
2576
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: account.name }),
|
|
2577
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: account.email }),
|
|
2578
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", disabled: f.busy, className: f.cx("providerButton"), onClick: () => {
|
|
2579
|
+
setDone(null);
|
|
2580
|
+
setEditing(true);
|
|
2581
|
+
}, children: f.t.change }),
|
|
2582
|
+
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
|
|
2583
|
+
] });
|
|
2584
|
+
}
|
|
2463
2585
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "profile", onSubmit: submit, noValidate: true, children: [
|
|
2464
2586
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.profile }),
|
|
2465
2587
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: account.email }),
|
|
2466
2588
|
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2467
2589
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "name", type: "text", label: f.t.name, value: name, autoComplete: "name", onChange: setName }),
|
|
2468
2590
|
/* @__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 }),
|
|
2591
|
+
account.name.trim() !== "" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Cancel, { f, onClick: cancel }),
|
|
2469
2592
|
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
|
|
2470
2593
|
] });
|
|
2471
2594
|
}
|
|
@@ -2474,15 +2597,35 @@ function EmailPart({ props, account }) {
|
|
|
2474
2597
|
const { f, done, setDone, run, general } = useSection(props);
|
|
2475
2598
|
const [email, setEmail] = (0, import_react.useState)("");
|
|
2476
2599
|
const [password, setPassword] = (0, import_react.useState)("");
|
|
2600
|
+
const [editing, setEditing] = (0, import_react.useState)(false);
|
|
2477
2601
|
const submit = async (e) => {
|
|
2478
2602
|
e.preventDefault();
|
|
2479
2603
|
if (!f.check(checkEmail(email), account.hasPassword && checkPassword(password))) return;
|
|
2480
2604
|
const r = await run(() => auth.account.changeEmail({ email, password }));
|
|
2481
2605
|
if (!r.ok) return;
|
|
2606
|
+
setEmail("");
|
|
2482
2607
|
setPassword("");
|
|
2608
|
+
setEditing(false);
|
|
2483
2609
|
setDone(f.t.emailSent.replace("{email}", r.email));
|
|
2484
2610
|
props.onSaved?.({ kind: "email.change_requested", email: r.email });
|
|
2485
2611
|
};
|
|
2612
|
+
const cancel = () => {
|
|
2613
|
+
setEmail("");
|
|
2614
|
+
setPassword("");
|
|
2615
|
+
f.setError(null);
|
|
2616
|
+
setEditing(false);
|
|
2617
|
+
};
|
|
2618
|
+
if (!editing) {
|
|
2619
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "div", slot: "section", section: "email", children: [
|
|
2620
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.emailAddress }),
|
|
2621
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: account.email }),
|
|
2622
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", disabled: f.busy, className: f.cx("providerButton"), onClick: () => {
|
|
2623
|
+
setDone(null);
|
|
2624
|
+
setEditing(true);
|
|
2625
|
+
}, children: f.t.changeEmail }),
|
|
2626
|
+
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
|
|
2627
|
+
] });
|
|
2628
|
+
}
|
|
2486
2629
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "email", onSubmit: submit, noValidate: true, children: [
|
|
2487
2630
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.emailAddress }),
|
|
2488
2631
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: account.email }),
|
|
@@ -2490,7 +2633,7 @@ function EmailPart({ props, account }) {
|
|
|
2490
2633
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.newEmail, value: email, autoComplete: "email", required: true, onChange: setEmail }),
|
|
2491
2634
|
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 }),
|
|
2492
2635
|
/* @__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 }),
|
|
2493
|
-
|
|
2636
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Cancel, { f, onClick: cancel })
|
|
2494
2637
|
] });
|
|
2495
2638
|
}
|
|
2496
2639
|
function LinkedPart({ props }) {
|
|
@@ -2555,6 +2698,7 @@ function PasswordPart({ props }) {
|
|
|
2555
2698
|
const { f, done, setDone, run, general } = useSection(props);
|
|
2556
2699
|
const [password, setPassword] = (0, import_react.useState)("");
|
|
2557
2700
|
const [newPassword, setNewPassword] = (0, import_react.useState)("");
|
|
2701
|
+
const [editing, setEditing] = (0, import_react.useState)(false);
|
|
2558
2702
|
usePasswordPolicy(f, useMethods(auth));
|
|
2559
2703
|
const submit = async (e) => {
|
|
2560
2704
|
e.preventDefault();
|
|
@@ -2563,16 +2707,34 @@ function PasswordPart({ props }) {
|
|
|
2563
2707
|
if (!r.ok) return;
|
|
2564
2708
|
setPassword("");
|
|
2565
2709
|
setNewPassword("");
|
|
2710
|
+
setEditing(false);
|
|
2566
2711
|
setDone(f.t.passwordChangedHere);
|
|
2567
2712
|
props.onSaved?.({ kind: "password.changed" });
|
|
2568
2713
|
};
|
|
2714
|
+
const cancel = () => {
|
|
2715
|
+
setPassword("");
|
|
2716
|
+
setNewPassword("");
|
|
2717
|
+
f.setError(null);
|
|
2718
|
+
setEditing(false);
|
|
2719
|
+
};
|
|
2720
|
+
if (!editing) {
|
|
2721
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "div", slot: "section", section: "password", children: [
|
|
2722
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.password }),
|
|
2723
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.passwordSet }),
|
|
2724
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", disabled: f.busy, className: f.cx("providerButton"), onClick: () => {
|
|
2725
|
+
setDone(null);
|
|
2726
|
+
setEditing(true);
|
|
2727
|
+
}, children: f.t.changePassword }),
|
|
2728
|
+
done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
|
|
2729
|
+
] });
|
|
2730
|
+
}
|
|
2569
2731
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "password", onSubmit: submit, noValidate: true, children: [
|
|
2570
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.
|
|
2732
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.password }),
|
|
2571
2733
|
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2572
2734
|
/* @__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 }),
|
|
2573
2735
|
/* @__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 }),
|
|
2574
2736
|
/* @__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 }),
|
|
2575
|
-
|
|
2737
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Cancel, { f, onClick: cancel })
|
|
2576
2738
|
] });
|
|
2577
2739
|
}
|
|
2578
2740
|
function SecondStepPart({ props, account, onChanged }) {
|
|
@@ -2582,6 +2744,7 @@ function SecondStepPart({ props, account, onChanged }) {
|
|
|
2582
2744
|
const [code, setCode] = (0, import_react.useState)("");
|
|
2583
2745
|
const [setup, setSetup] = (0, import_react.useState)(null);
|
|
2584
2746
|
const [codes, setCodes] = (0, import_react.useState)(null);
|
|
2747
|
+
const [asking, setAsking] = (0, import_react.useState)(null);
|
|
2585
2748
|
const start = async (e) => {
|
|
2586
2749
|
e.preventDefault();
|
|
2587
2750
|
const r = await run(() => auth.account.mfa.setup({ password }));
|
|
@@ -2598,26 +2761,36 @@ function SecondStepPart({ props, account, onChanged }) {
|
|
|
2598
2761
|
onChanged(true);
|
|
2599
2762
|
props.onSaved?.({ kind: "mfa.enabled" });
|
|
2600
2763
|
};
|
|
2601
|
-
const turnOff = async (
|
|
2602
|
-
|
|
2603
|
-
const r = await run(() => auth.account.mfa.disable({ password }));
|
|
2764
|
+
const turnOff = async (key) => {
|
|
2765
|
+
const r = await run(() => auth.account.mfa.disable({ password }), key);
|
|
2604
2766
|
if (!r.ok) return;
|
|
2605
2767
|
setPassword("");
|
|
2768
|
+
setAsking(null);
|
|
2606
2769
|
setCodes(null);
|
|
2607
2770
|
onChanged(false);
|
|
2608
2771
|
props.onSaved?.({ kind: "mfa.disabled" });
|
|
2609
2772
|
};
|
|
2610
|
-
const renew = async () => {
|
|
2611
|
-
const r = await run(() => auth.account.mfa.recoveryCodes({ password }),
|
|
2773
|
+
const renew = async (key) => {
|
|
2774
|
+
const r = await run(() => auth.account.mfa.recoveryCodes({ password }), key);
|
|
2612
2775
|
if (!r.ok) return;
|
|
2776
|
+
setPassword("");
|
|
2777
|
+
setAsking(null);
|
|
2613
2778
|
setCodes(r.recoveryCodes);
|
|
2614
2779
|
props.onSaved?.({ kind: "recovery_codes.regenerated" });
|
|
2615
2780
|
};
|
|
2781
|
+
const press = (what) => {
|
|
2782
|
+
f.setError(null);
|
|
2783
|
+
if (!account.hasPassword) return void (what === "off" ? turnOff(what) : renew(what));
|
|
2784
|
+
setPassword("");
|
|
2785
|
+
setCodes(null);
|
|
2786
|
+
setAsking(what);
|
|
2787
|
+
};
|
|
2788
|
+
const cancel = () => {
|
|
2789
|
+
setPassword("");
|
|
2790
|
+
f.setError(null);
|
|
2791
|
+
setAsking(null);
|
|
2792
|
+
};
|
|
2616
2793
|
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 });
|
|
2617
|
-
const shown = codes && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
2618
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.keepCodes }),
|
|
2619
|
-
/* @__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)) })
|
|
2620
|
-
] });
|
|
2621
2794
|
if (setup) {
|
|
2622
2795
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "secondStep", onSubmit: confirm, noValidate: true, children: [
|
|
2623
2796
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.secondStep }),
|
|
@@ -2629,14 +2802,36 @@ function SecondStepPart({ props, account, onChanged }) {
|
|
|
2629
2802
|
/* @__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 })
|
|
2630
2803
|
] });
|
|
2631
2804
|
}
|
|
2632
|
-
|
|
2805
|
+
if (!account.mfaEnabled) {
|
|
2806
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "secondStep", onSubmit: start, noValidate: true, children: [
|
|
2807
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.secondStep }),
|
|
2808
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.secondStepOff }),
|
|
2809
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2810
|
+
passwordField,
|
|
2811
|
+
/* @__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.turnOn })
|
|
2812
|
+
] });
|
|
2813
|
+
}
|
|
2814
|
+
if (asking) {
|
|
2815
|
+
const submit = (e) => {
|
|
2816
|
+
e.preventDefault();
|
|
2817
|
+
void (asking === "off" ? turnOff(SUBMIT) : renew(SUBMIT));
|
|
2818
|
+
};
|
|
2819
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "secondStep", onSubmit: submit, noValidate: true, children: [
|
|
2820
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.secondStep }),
|
|
2821
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.secondStepOn }),
|
|
2822
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2823
|
+
passwordField,
|
|
2824
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: asking === "off" ? "danger" : "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: asking === "off" ? f.t.turnOff : f.t.newRecoveryCodes }),
|
|
2825
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Cancel, { f, onClick: cancel })
|
|
2826
|
+
] });
|
|
2827
|
+
}
|
|
2828
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "div", slot: "section", section: "secondStep", children: [
|
|
2633
2829
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.secondStep }),
|
|
2634
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children:
|
|
2635
|
-
|
|
2830
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.secondStepOn }),
|
|
2831
|
+
codes && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RecoveryCodes, { f, codes }),
|
|
2636
2832
|
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2637
|
-
|
|
2638
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "
|
|
2639
|
-
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 })
|
|
2833
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "danger", loading: f.loading("off"), disabled: f.busy, className: f.cx("button"), onClick: () => press("off"), children: f.t.turnOff }),
|
|
2834
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", loading: f.loading("codes"), disabled: f.busy, className: f.cx("providerButton"), onClick: () => press("codes"), children: f.t.newRecoveryCodes })
|
|
2640
2835
|
] });
|
|
2641
2836
|
}
|
|
2642
2837
|
function PhonePart({ props, account, onChanged }) {
|
|
@@ -2649,6 +2844,7 @@ function PhonePart({ props, account, onChanged }) {
|
|
|
2649
2844
|
const [code, setCode] = (0, import_react.useState)("");
|
|
2650
2845
|
const [sentTo, setSentTo] = (0, import_react.useState)("");
|
|
2651
2846
|
const [codes, setCodes] = (0, import_react.useState)(null);
|
|
2847
|
+
const [removing, setRemoving] = (0, import_react.useState)(false);
|
|
2652
2848
|
const load = () => auth.account.mfa.factors().then((w) => {
|
|
2653
2849
|
setWays(w);
|
|
2654
2850
|
if (w && w.phoneChannels.length > 0 && !w.phoneChannels.includes(channel)) setChannel(w.phoneChannels[0]);
|
|
@@ -2669,21 +2865,34 @@ function PhonePart({ props, account, onChanged }) {
|
|
|
2669
2865
|
setSentTo("");
|
|
2670
2866
|
setCode("");
|
|
2671
2867
|
setPassword("");
|
|
2868
|
+
setNumber("");
|
|
2672
2869
|
if (r.recoveryCodes.length > 0) setCodes(r.recoveryCodes);
|
|
2673
2870
|
onChanged(true);
|
|
2674
2871
|
props.onSaved?.({ kind: "phone.added", channel });
|
|
2675
2872
|
await load();
|
|
2676
2873
|
};
|
|
2677
|
-
const remove = async (
|
|
2678
|
-
|
|
2679
|
-
const r = await run(() => auth.account.mfa.removePhone({ password }));
|
|
2874
|
+
const remove = async (key) => {
|
|
2875
|
+
const r = await run(() => auth.account.mfa.removePhone({ password }), key);
|
|
2680
2876
|
if (!r.ok) return;
|
|
2681
2877
|
setPassword("");
|
|
2878
|
+
setRemoving(false);
|
|
2879
|
+
setCodes(null);
|
|
2682
2880
|
await load();
|
|
2683
2881
|
const left = await auth.account.mfa.factors();
|
|
2684
2882
|
onChanged(Boolean(left?.totp));
|
|
2685
2883
|
props.onSaved?.({ kind: "phone.removed" });
|
|
2686
2884
|
};
|
|
2885
|
+
const press = () => {
|
|
2886
|
+
f.setError(null);
|
|
2887
|
+
if (!account.hasPassword) return void remove("remove");
|
|
2888
|
+
setPassword("");
|
|
2889
|
+
setRemoving(true);
|
|
2890
|
+
};
|
|
2891
|
+
const cancel = () => {
|
|
2892
|
+
setPassword("");
|
|
2893
|
+
f.setError(null);
|
|
2894
|
+
setRemoving(false);
|
|
2895
|
+
};
|
|
2687
2896
|
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 });
|
|
2688
2897
|
if (sentTo) {
|
|
2689
2898
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "phone", onSubmit: confirm, noValidate: true, children: [
|
|
@@ -2694,23 +2903,46 @@ function PhonePart({ props, account, onChanged }) {
|
|
|
2694
2903
|
/* @__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 })
|
|
2695
2904
|
] });
|
|
2696
2905
|
}
|
|
2697
|
-
|
|
2906
|
+
if (ways.phone) {
|
|
2907
|
+
const by = ways.phone.channel === "whatsapp" ? f.t.byWhatsapp : ways.phone.channel === "sms" ? f.t.bySms : "";
|
|
2908
|
+
const on = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Note, { f, children: [
|
|
2909
|
+
f.t.phoneOn.replace("{to}", ways.phone.number),
|
|
2910
|
+
by && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tag, { f, plain: ` \xB7 ${by}`, children: by })
|
|
2911
|
+
] });
|
|
2912
|
+
if (removing) {
|
|
2913
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "phone", onSubmit: (e) => {
|
|
2914
|
+
e.preventDefault();
|
|
2915
|
+
void remove(SUBMIT);
|
|
2916
|
+
}, noValidate: true, children: [
|
|
2917
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.phone }),
|
|
2918
|
+
on,
|
|
2919
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2920
|
+
passwordField,
|
|
2921
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "danger", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.removePhone }),
|
|
2922
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Cancel, { f, onClick: cancel })
|
|
2923
|
+
] });
|
|
2924
|
+
}
|
|
2925
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "div", slot: "section", section: "phone", children: [
|
|
2926
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.phone }),
|
|
2927
|
+
on,
|
|
2928
|
+
codes && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RecoveryCodes, { f, codes }),
|
|
2929
|
+
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2930
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "danger", loading: f.loading("remove"), disabled: f.busy, className: f.cx("button"), onClick: press, children: f.t.removePhone })
|
|
2931
|
+
] });
|
|
2932
|
+
}
|
|
2933
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "phone", onSubmit: add, noValidate: true, children: [
|
|
2698
2934
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.phone }),
|
|
2699
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children:
|
|
2700
|
-
codes && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
2701
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.keepCodes }),
|
|
2702
|
-
/* @__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)) })
|
|
2703
|
-
] }),
|
|
2935
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: `${f.t.phoneOff} ${f.t.phoneHelp}` }),
|
|
2704
2936
|
general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2937
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "phone", type: "tel", label: f.t.phone, value: number, autoComplete: "tel", required: true, onChange: setNumber }),
|
|
2938
|
+
ways.phoneChannels.length > 1 && f.C.Select && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChannelPick, { f, value: channel, channels: ways.phoneChannels, onChange: setChannel }),
|
|
2939
|
+
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: [
|
|
2708
2940
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "radio", name: "channel", value: c, checked: channel === c, disabled: f.busy, onChange: () => setChannel(c) }),
|
|
2709
2941
|
" ",
|
|
2710
2942
|
c === "whatsapp" ? f.t.byWhatsapp : f.t.bySms
|
|
2711
2943
|
] }, c)) }),
|
|
2712
2944
|
passwordField,
|
|
2713
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant:
|
|
2945
|
+
/* @__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.addPhone })
|
|
2714
2946
|
] });
|
|
2715
2947
|
}
|
|
2716
2948
|
function AgentsPart({ props, when }) {
|