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