cauthy-auth 0.30.0 → 0.32.0

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