cauthy-auth 0.31.0 → 0.32.0

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