cauthy-auth 0.32.0 → 0.33.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
@@ -1134,7 +1134,7 @@ var TEXTS = {
1134
1134
  }
1135
1135
  }
1136
1136
  };
1137
- var PlainButton = (p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { ...p });
1137
+ var PlainButton = ({ variant: _variant, loading: _loading, ...p }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { ...p });
1138
1138
  var PlainInput = (p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { ...p });
1139
1139
  var looks = /* @__PURE__ */ new Map();
1140
1140
  var loaded = /* @__PURE__ */ new Set();
@@ -1249,8 +1249,24 @@ function useForm(props) {
1249
1249
  const C = props.components ?? {};
1250
1250
  const Button = C.Button ?? PlainButton;
1251
1251
  const Input = C.Input ?? PlainInput;
1252
- const [error, setError] = (0, import_react.useState)(null);
1253
- const [busy, setBusy] = (0, import_react.useState)(false);
1252
+ const [error, setOnlyError] = (0, import_react.useState)(null);
1253
+ const [problems, setProblems] = (0, import_react.useState)({ list: [], round: 0 });
1254
+ const setError = (0, import_react.useCallback)((e) => {
1255
+ setOnlyError(e);
1256
+ setProblems((p) => p.list.length === 0 ? p : { list: [], round: p.round });
1257
+ }, []);
1258
+ const check = (...found) => {
1259
+ const list = found.filter((e) => Boolean(e));
1260
+ setOnlyError(null);
1261
+ setProblems((p) => ({ list, round: list.length > 0 ? p.round + 1 : p.round }));
1262
+ return list.length === 0;
1263
+ };
1264
+ const fieldError = (name) => problems.list.find((e) => e.field === name) ?? (error?.field === name ? error : null);
1265
+ const firstWrong = (name) => problems.list[0]?.field === name ? problems.round : 0;
1266
+ const [acting, setActing] = (0, import_react.useState)(null);
1267
+ const busy = acting !== null;
1268
+ const setBusy = (0, import_react.useCallback)((on) => setActing(on === false ? null : on === true ? SUBMIT : on), []);
1269
+ const loading = (key = SUBMIT) => acting === key;
1254
1270
  const [policy, setPolicy] = (0, import_react.useState)(void 0);
1255
1271
  const locale = props.locale ?? "en";
1256
1272
  const say = (e) => {
@@ -1263,7 +1279,28 @@ function useForm(props) {
1263
1279
  else window.location.assign(sitePath(to) ?? sameOrigin(props.returnTo) ?? "/");
1264
1280
  };
1265
1281
  const root = useRoot(props);
1266
- return { t, cx, own, C, Button, Input, error, setError, busy, setBusy, say, done, root, policy, setPolicy, passwordRule };
1282
+ return { t, cx, own, C, Button, Input, error, setError, check, fieldError, firstWrong, busy, setBusy, loading, say, done, root, policy, setPolicy, passwordRule };
1283
+ }
1284
+ var SUBMIT = "submit";
1285
+ function Wrap(p) {
1286
+ const { Form: OwnForm } = p.f.C;
1287
+ if (OwnForm) {
1288
+ const own = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1289
+ OwnForm,
1290
+ {
1291
+ as: p.as === "form" ? "form" : "div",
1292
+ onSubmit: p.onSubmit,
1293
+ noValidate: p.noValidate,
1294
+ "aria-busy": p.busy,
1295
+ className: p.slot ? p.f.own(p.slot) : void 0,
1296
+ section: p.section,
1297
+ children: p.children
1298
+ }
1299
+ );
1300
+ return p.root?.["data-cauthy"] !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ...p.root, children: own }) : own;
1301
+ }
1302
+ const Tag2 = p.as;
1303
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tag2, { className: p.slot ? p.f.cx(p.slot) : void 0, ...p.root, onSubmit: p.onSubmit, noValidate: p.noValidate, "aria-busy": p.busy, children: p.children });
1267
1304
  }
1268
1305
  function Note({ f, children, footer }) {
1269
1306
  const { Text } = f.C;
@@ -1344,6 +1381,11 @@ function isPasswordRule(e) {
1344
1381
  if (e.code === "weak_password" || PASSWORD_RULES.includes(e.code)) return true;
1345
1382
  return (e.code === "too_short" || e.code === "too_long") && (e.field === "password" || e.field === "newPassword");
1346
1383
  }
1384
+ function newPasswordProblem(value, policy, field = "password") {
1385
+ const bad = checkNewPassword(value, policy);
1386
+ if (!bad) return null;
1387
+ return { code: bad.code, message: bad.message, field, ...bad.code === "required" ? {} : { reasons: passwordProblems(value, policy) } };
1388
+ }
1347
1389
  function usePasswordPolicy(f, methods) {
1348
1390
  const { setPolicy } = f;
1349
1391
  (0, import_react.useEffect)(() => {
@@ -1353,7 +1395,11 @@ function usePasswordPolicy(f, methods) {
1353
1395
  function Field(p) {
1354
1396
  const id = (0, import_react.useId)();
1355
1397
  const { f } = p;
1356
- const bad = f.error?.field === p.name ? f.error : null;
1398
+ const bad = f.fieldError(p.name);
1399
+ const focus = f.firstWrong(p.name);
1400
+ (0, import_react.useEffect)(() => {
1401
+ if (focus > 0 && typeof document !== "undefined") document.getElementById(id)?.focus();
1402
+ }, [focus, id]);
1357
1403
  const described = [bad ? `${id}-error` : "", p.hint ? `${id}-hint` : ""].filter(Boolean).join(" ");
1358
1404
  const input = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1359
1405
  f.Input,
@@ -1429,7 +1475,7 @@ function SecondStepForm(p) {
1429
1475
  });
1430
1476
  }, []);
1431
1477
  const sendEmail = async () => {
1432
- f.setBusy(true);
1478
+ f.setBusy("email");
1433
1479
  f.setError(null);
1434
1480
  const r = await auth.signIn.mfaSendEmail();
1435
1481
  f.setBusy(false);
@@ -1440,7 +1486,7 @@ function SecondStepForm(p) {
1440
1486
  const pushWait = (0, import_react.useRef)(null);
1441
1487
  (0, import_react.useEffect)(() => () => pushWait.current?.abort(), []);
1442
1488
  const sendPush = async () => {
1443
- f.setBusy(true);
1489
+ f.setBusy("push");
1444
1490
  f.setError(null);
1445
1491
  const r = await auth.signIn.mfaPush();
1446
1492
  f.setBusy(false);
@@ -1456,7 +1502,7 @@ function SecondStepForm(p) {
1456
1502
  f.done();
1457
1503
  };
1458
1504
  const sendCode = async () => {
1459
- f.setBusy(true);
1505
+ f.setBusy("phone");
1460
1506
  f.setError(null);
1461
1507
  const r = await auth.signIn.mfaSendCode();
1462
1508
  f.setBusy(false);
@@ -1474,10 +1520,10 @@ function SecondStepForm(p) {
1474
1520
  };
1475
1521
  const general = f.error && !f.error.field ? f.error : null;
1476
1522
  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: [
1523
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "form", root: f.root, onSubmit: submit, noValidate: true, children: [
1478
1524
  /* @__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
1525
  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 }),
1526
+ phoneWay?.email && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", loading: f.loading("email"), disabled: f.busy, className: f.cx("providerButton"), onClick: () => void sendEmail(), children: f.t.sendEmailAgain }),
1481
1527
  pushNumber > 0 ? f.C.Text ? (
1482
1528
  // The application's text: the number to pick drawn large, by its own rules.
1483
1529
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { role: "status", "aria-live": "polite", children: [
@@ -1489,15 +1535,15 @@ function SecondStepForm(p) {
1489
1535
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: f.t.pushPick.replace("{n}", String(pushNumber)) }),
1490
1536
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: 48, fontWeight: 700, margin: "4px 0", textAlign: "center" }, children: pushNumber }),
1491
1537
  /* @__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) }),
1538
+ ] }) : phoneWay?.push && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", loading: f.loading("push"), disabled: f.busy, className: f.cx("button"), onClick: () => void sendPush(), children: f.t.pushSend }),
1539
+ phoneWay?.phone && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", loading: f.loading("phone"), 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
1540
  /* @__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 })
1541
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.verify })
1496
1542
  ] });
1497
1543
  }
1498
1544
  function ProviderButtons(p) {
1499
1545
  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: [
1546
+ 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", variant: "secondary", className: f.cx("providerButton"), onClick: () => p.onPick(provider.id), children: [
1501
1547
  provider.iconUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: provider.iconUrl, alt: "", width: 18, height: 18, className: f.cx("providerIcon") }),
1502
1548
  f.t.continueWith,
1503
1549
  " ",
@@ -1537,7 +1583,7 @@ function SignIn(props) {
1537
1583
  }, [email, methods]);
1538
1584
  const toCompany = () => {
1539
1585
  autofill.current?.abort();
1540
- f.setBusy(true);
1586
+ f.setBusy("sso");
1541
1587
  auth.signIn.sso({ email }, { returnTo: props.returnTo });
1542
1588
  };
1543
1589
  (0, import_react.useEffect)(() => {
@@ -1579,6 +1625,7 @@ function SignIn(props) {
1579
1625
  if (methods?.magicLink) return sendLink();
1580
1626
  return;
1581
1627
  }
1628
+ if (step === "password" && !f.check(checkEmail(email), checkPassword(password))) return;
1582
1629
  f.setBusy(true);
1583
1630
  f.setError(null);
1584
1631
  const r = step === "sent" ? await auth.signIn.emailCode({ code }) : await auth.signIn.email({ email, password, captchaToken: challenge.token });
@@ -1594,7 +1641,7 @@ function SignIn(props) {
1594
1641
  };
1595
1642
  const usePasskey = async () => {
1596
1643
  autofill.current?.abort();
1597
- f.setBusy(true);
1644
+ f.setBusy("passkey");
1598
1645
  f.setError(null);
1599
1646
  const r = await auth.signIn.passkey({ returnTo: props.returnTo, locale: props.locale, email });
1600
1647
  if (r.ok && r.status === "redirected") return;
@@ -1605,7 +1652,7 @@ function SignIn(props) {
1605
1652
  };
1606
1653
  const sendLink = async () => {
1607
1654
  autofill.current?.abort();
1608
- f.setBusy(true);
1655
+ f.setBusy("link");
1609
1656
  f.setError(null);
1610
1657
  const r = await auth.signIn.magicLink({ email, captchaToken: challenge.token, create: props.createAccounts, returnTo: props.returnTo });
1611
1658
  f.setBusy(false);
@@ -1616,24 +1663,24 @@ function SignIn(props) {
1616
1663
  };
1617
1664
  const general = f.error && !f.error.field ? f.error : null;
1618
1665
  const asksEmail = offers.email;
1619
- if (step === "opening") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: f.cx("form"), ...f.root, "aria-busy": "true" });
1666
+ if (step === "opening") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Wrap, { f, as: "div", slot: "form", root: f.root, busy: true });
1620
1667
  if (step === "sent") {
1621
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
1668
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "form", root: f.root, onSubmit: submit, noValidate: true, children: [
1622
1669
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.signInLinkSent }),
1623
1670
  general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
1624
1671
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.codeFromMail }),
1625
1672
  /* @__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 }),
1626
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.verify })
1673
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.verify })
1627
1674
  ] });
1628
1675
  }
1629
1676
  if (step === "code") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SecondStepForm, { f, auth });
1630
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
1677
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "form", root: f.root, onSubmit: submit, noValidate: true, children: [
1631
1678
  general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
1632
1679
  /* @__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 }),
1680
+ offers.passkey && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", loading: f.loading("passkey"), disabled: f.busy, className: f.cx("providerButton"), onClick: () => void usePasskey(), children: f.t.usePasskey }),
1634
1681
  asksEmail && ((methods?.providers.length ?? 0) > 0 || offers.passkey) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Or, { f, children: f.t.orWithEmail }),
1635
1682
  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 }),
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: [
1683
+ company && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(f.Button, { type: "button", variant: company.enforced ? "primary" : "secondary", loading: f.loading("sso"), disabled: f.busy, className: f.cx(company.enforced ? "button" : "providerButton"), onClick: toCompany, children: [
1637
1684
  f.t.continueWith,
1638
1685
  " ",
1639
1686
  company.name
@@ -1655,10 +1702,10 @@ function SignIn(props) {
1655
1702
  }
1656
1703
  ),
1657
1704
  challenge.node,
1658
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.signIn })
1705
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.signIn })
1659
1706
  ] }),
1660
1707
  !company?.enforced && !passwordOn && methods?.magicLink && challenge.node,
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 }),
1708
+ methods?.magicLink && !company?.enforced && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", loading: f.loading("link"), disabled: f.busy, className: f.cx("providerButton"), onClick: () => void sendLink(), children: f.t.emailMeALink }),
1662
1709
  methods?.signUp !== false && props.links?.signUp && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Note, { f, footer: true, children: [
1663
1710
  f.t.noAccount,
1664
1711
  " ",
@@ -1698,11 +1745,19 @@ function SignUp(props) {
1698
1745
  const [acceptLegal, setAcceptLegal] = (0, import_react.useState)(false);
1699
1746
  const [consents, setConsents] = (0, import_react.useState)({});
1700
1747
  const legal = methods?.legal;
1748
+ const guest = auth.session?.user.isAnonymous === true;
1701
1749
  const submit = async (e) => {
1702
1750
  e.preventDefault();
1751
+ const asksCompany = methods?.organization?.ask === true;
1752
+ if (!f.check(
1753
+ asksCompany && checkOrganization(organization, methods?.organization?.required === true),
1754
+ checkName(name),
1755
+ checkEmail(email),
1756
+ newPasswordProblem(password, f.policy)
1757
+ )) return;
1703
1758
  f.setBusy(true);
1704
1759
  f.setError(null);
1705
- const r = auth.session?.user.isAnonymous === true ? await auth.account.upgrade({ name, email, password }) : await auth.signUp.email({
1760
+ const r = guest ? await auth.account.upgrade({ name, email, password }) : await auth.signUp.email({
1706
1761
  name,
1707
1762
  email,
1708
1763
  password,
@@ -1718,30 +1773,31 @@ function SignUp(props) {
1718
1773
  };
1719
1774
  const general = f.error && !f.error.field ? f.error : null;
1720
1775
  const passwordOn = methods?.passwordSignIn !== false;
1721
- const providers = auth.session?.user.isAnonymous === true || methods?.organization?.required ? [] : methods?.providers ?? [];
1776
+ const providers = guest || methods?.organization?.required ? [] : methods?.providers ?? [];
1722
1777
  if (sent) {
1723
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, children: [
1778
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "div", slot: "form", root: f.root, children: [
1724
1779
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.checkEmail }),
1725
1780
  props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signIn, children: f.t.backToSignIn })
1726
1781
  ] });
1727
1782
  }
1783
+ if (methods === null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Wrap, { f, as: "div", slot: "form", root: f.root, busy: true });
1728
1784
  const footer = props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Note, { f, footer: true, children: [
1729
1785
  f.t.haveAccount,
1730
1786
  " ",
1731
1787
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signIn, children: f.t.signIn })
1732
1788
  ] });
1733
1789
  if (!passwordOn) {
1734
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, children: [
1790
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "div", slot: "form", root: f.root, children: [
1735
1791
  general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
1736
1792
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProviderButtons, { f, providers, onPick: (id) => auth.signIn.social(id, { returnTo: props.returnTo }) }),
1737
1793
  footer
1738
1794
  ] });
1739
1795
  }
1740
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
1796
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "form", root: f.root, onSubmit: submit, noValidate: true, children: [
1741
1797
  general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
1742
1798
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProviderButtons, { f, providers, onPick: (id) => auth.signIn.social(id, { returnTo: props.returnTo }) }),
1743
1799
  providers.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Or, { f, children: f.t.orWithEmail }),
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 }),
1800
+ 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 }),
1745
1801
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "name", type: "text", label: f.t.name, value: name, autoComplete: "name", onChange: setName }),
1746
1802
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: "username", required: true, onChange: setEmail }),
1747
1803
  /* @__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 }),
@@ -1752,7 +1808,7 @@ function SignUp(props) {
1752
1808
  ] }),
1753
1809
  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)),
1754
1810
  challenge.node,
1755
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.signUp }),
1811
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.signUp }),
1756
1812
  footer
1757
1813
  ] });
1758
1814
  }
@@ -1774,16 +1830,16 @@ function ForgotPassword(props) {
1774
1830
  };
1775
1831
  const general = f.error && !f.error.field ? f.error : null;
1776
1832
  if (sent) {
1777
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, children: [
1833
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "div", slot: "form", root: f.root, children: [
1778
1834
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.linkSent }),
1779
1835
  props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signIn, children: f.t.backToSignIn })
1780
1836
  ] });
1781
1837
  }
1782
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
1838
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "form", root: f.root, onSubmit: submit, noValidate: true, children: [
1783
1839
  general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
1784
1840
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: "username", required: true, onChange: setEmail }),
1785
1841
  challenge.node,
1786
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.sendLink }),
1842
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.sendLink }),
1787
1843
  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 }) })
1788
1844
  ] });
1789
1845
  }
@@ -1810,21 +1866,21 @@ function ResetPassword(props) {
1810
1866
  const general = f.error && !f.error.field ? f.error : null;
1811
1867
  const back = props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signIn, children: f.t.backToSignIn });
1812
1868
  if (changed) {
1813
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, children: [
1869
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "div", slot: "form", root: f.root, children: [
1814
1870
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.passwordChanged }),
1815
1871
  back
1816
1872
  ] });
1817
1873
  }
1818
1874
  if (token === "") {
1819
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, children: [
1875
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "div", slot: "form", root: f.root, children: [
1820
1876
  general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
1821
1877
  props.links?.forgotPassword && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.forgotPassword, children: f.t.forgotPassword })
1822
1878
  ] });
1823
1879
  }
1824
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("form"), ...f.root, onSubmit: submit, noValidate: true, children: [
1880
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "form", root: f.root, onSubmit: submit, noValidate: true, children: [
1825
1881
  general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
1826
1882
  /* @__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 }),
1827
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy || token === null, className: f.cx("button"), children: f.t.savePassword })
1883
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy || token === null, className: f.cx("button"), children: f.t.savePassword })
1828
1884
  ] });
1829
1885
  }
1830
1886
  function VerifyEmail(props) {
@@ -1843,7 +1899,7 @@ function VerifyEmail(props) {
1843
1899
  setState("failed");
1844
1900
  });
1845
1901
  });
1846
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, "aria-busy": state === "confirming", children: [
1902
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "div", slot: "form", root: f.root, busy: state === "confirming", children: [
1847
1903
  state === "confirming" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.confirming }),
1848
1904
  state === "confirmed" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.emailConfirmed }),
1849
1905
  state === "failed" && f.error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(f.error) }),
@@ -1887,10 +1943,10 @@ function AcceptInvite(props) {
1887
1943
  const general = f.error && !f.error.field ? f.error : null;
1888
1944
  const back = props.links?.signIn && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: props.links.signIn, children: f.t.backToSignIn });
1889
1945
  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 }) });
1946
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Wrap, { f, as: "div", slot: "form", root: f.root, busy: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.openingInvitation }) });
1891
1947
  }
1892
1948
  if (state === "invalid") {
1893
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, children: [
1949
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "div", slot: "form", root: f.root, children: [
1894
1950
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: general ? f.say(general) : f.t.invitationInvalid }),
1895
1951
  back
1896
1952
  ] });
@@ -1898,13 +1954,13 @@ function AcceptInvite(props) {
1898
1954
  if (state === "code") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SecondStepForm, { f, auth });
1899
1955
  const workspace = invitation?.workspace ?? "";
1900
1956
  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: [
1957
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "form", root: f.root, onSubmit: submit, noValidate: true, children: [
1902
1958
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: heading }),
1903
1959
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.invitedAs.replace("{email}", invitation?.email ?? "") }),
1904
1960
  general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
1905
1961
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "email", name: "username", autoComplete: "username", value: invitation?.email ?? "", readOnly: true, hidden: true }),
1906
1962
  /* @__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 })
1963
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.acceptInvite })
1908
1964
  ] });
1909
1965
  }
1910
1966
  function PendingTerms(props) {
@@ -1924,7 +1980,7 @@ function PendingTerms(props) {
1924
1980
  setOwed([]);
1925
1981
  props.onSuccess?.();
1926
1982
  };
1927
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("form"), ...f.root, children: [
1983
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "div", slot: "form", root: f.root, children: [
1928
1984
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.termsChanged }),
1929
1985
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Note, { f, children: [
1930
1986
  f.t.termsChangedHelp,
@@ -1932,15 +1988,15 @@ function PendingTerms(props) {
1932
1988
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Documents, { f, documents: owed })
1933
1989
  ] }),
1934
1990
  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 })
1991
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), onClick: () => void accept(), children: f.t.acceptTerms })
1936
1992
  ] });
1937
1993
  }
1938
1994
  var ACCOUNT_SECTIONS = ["profile", "email", "password", "linked", "secondStep", "phone", "passkeys", "agents", "sessions"];
1939
1995
  function useSection(props) {
1940
1996
  const f = useForm({ ...props, unstyled: true });
1941
1997
  const [done, setDone] = (0, import_react.useState)(null);
1942
- const run = async (action) => {
1943
- f.setBusy(true);
1998
+ const run = async (action, key = SUBMIT) => {
1999
+ f.setBusy(key);
1944
2000
  f.setError(null);
1945
2001
  setDone(null);
1946
2002
  const r = await action();
@@ -1954,13 +2010,12 @@ function useSection(props) {
1954
2010
  function Account(props) {
1955
2011
  const auth = useAuth();
1956
2012
  const { accountUrl } = useSession();
1957
- const { root } = useForm(props);
1958
- const cx = (slot) => props.classNames?.[slot] ?? `cauthy-${slot}`;
2013
+ const f = useForm(props);
1959
2014
  const [account, setAccount] = (0, import_react.useState)(null);
1960
2015
  (0, import_react.useEffect)(() => {
1961
2016
  void auth.account.get().then(setAccount);
1962
2017
  }, []);
1963
- if (account === null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: cx("account"), ...root, "aria-busy": "true" });
2018
+ if (account === null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Wrap, { f, as: "div", slot: "account", root: f.root, busy: true });
1964
2019
  const when = props.formatDate ?? ((iso) => new Date(iso).toLocaleString());
1965
2020
  const mfa = (mfaEnabled) => setAccount({ ...account, mfaEnabled });
1966
2021
  const part = (section) => {
@@ -1985,7 +2040,7 @@ function Account(props) {
1985
2040
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SessionsPart, { props, when });
1986
2041
  }
1987
2042
  };
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)) });
2043
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Wrap, { f, as: "div", slot: "account", root: f.root, children: (props.sections ?? ACCOUNT_SECTIONS).map((section) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react.Fragment, { children: part(section) }, section)) });
1989
2044
  }
1990
2045
  function AccountProfile(props) {
1991
2046
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Account, { ...props, sections: ["profile"] });
@@ -2058,15 +2113,20 @@ function OrganizationMembers(props) {
2058
2113
  (0, import_react.useEffect)(() => {
2059
2114
  void load();
2060
2115
  }, [id]);
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 }) });
2062
- if (seat === void 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: f.cx("account"), ...root, "aria-busy": "true" });
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 }) });
2116
+ if (gone !== null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Wrap, { f, as: "div", slot: "account", root, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: gone }) });
2117
+ if (seat === void 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Wrap, { f, as: "div", slot: "account", root, busy: true });
2118
+ if (seat === null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Wrap, { f, as: "div", slot: "account", root, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.organizationMissing }) });
2064
2119
  const manage = seat.can.manageMembers;
2065
2120
  const giveable = rolesToGive(seat, roles, props.roles);
2066
- const label = (r) => roles.find((c) => c.role === r)?.name || r;
2121
+ const roleName = (c) => props.roleLabel?.(c) || c.name || c.role;
2122
+ const label = (r) => {
2123
+ const c = roles.find((x) => x.role === r);
2124
+ return c ? roleName(c) : r;
2125
+ };
2067
2126
  const add = async (e) => {
2068
2127
  e.preventDefault();
2069
- const r = await run(() => auth.organizations.add(id, { email, role, locale: props.locale }));
2128
+ if (!f.check(checkEmail(email))) return;
2129
+ const r = await run(() => auth.organizations.add(id, { email, role, locale: props.locale }), "add");
2070
2130
  if (!r.ok) return;
2071
2131
  setEmail("");
2072
2132
  setDone(f.t.memberAdded.replace("{email}", r.member.email));
@@ -2074,28 +2134,28 @@ function OrganizationMembers(props) {
2074
2134
  await load();
2075
2135
  };
2076
2136
  const change = async (m, next) => {
2077
- const r = await run(() => auth.organizations.setRole(id, m.userId, next));
2137
+ const r = await run(() => auth.organizations.setRole(id, m.userId, next), `role:${m.userId}`);
2078
2138
  if (!r.ok) return;
2079
2139
  saved({ kind: "member.role_changed", organizationId: id, userId: m.userId, role: next, previousRole: m.role });
2080
2140
  await load();
2081
2141
  };
2082
2142
  const remove = async (m) => {
2083
2143
  setAsking(null);
2084
- const r = await run(() => auth.organizations.remove(id, m.userId));
2144
+ const r = await run(() => auth.organizations.remove(id, m.userId), `remove:${m.userId}`);
2085
2145
  if (!r.ok) return;
2086
2146
  saved({ kind: m.you ? "member.left" : "member.removed", organizationId: id, userId: m.userId });
2087
2147
  if (m.you) setSeat(null);
2088
2148
  else await load();
2089
2149
  };
2090
2150
  const inviteAgain = async (m) => {
2091
- const r = await run(() => auth.organizations.inviteAgain(id, m.userId, { locale: props.locale }));
2151
+ const r = await run(() => auth.organizations.inviteAgain(id, m.userId, { locale: props.locale }), `invite:${m.userId}`);
2092
2152
  if (!r.ok) return;
2093
2153
  setDone(f.t.memberInvitationSent);
2094
2154
  saved({ kind: "member.invited_again", organizationId: id, userId: m.userId });
2095
2155
  };
2096
2156
  const rename = async (e) => {
2097
2157
  e.preventDefault();
2098
- const r = await run(() => auth.organizations.rename(id, name));
2158
+ const r = await run(() => auth.organizations.rename(id, name), "rename");
2099
2159
  if (!r.ok) return;
2100
2160
  setSeat(r.organization);
2101
2161
  setName(r.organization.name);
@@ -2104,7 +2164,7 @@ function OrganizationMembers(props) {
2104
2164
  };
2105
2165
  const close = async (how) => {
2106
2166
  setAsking(null);
2107
- const r = await run(() => how === "archive" ? auth.organizations.archive(id) : auth.organizations.delete(id));
2167
+ const r = await run(() => how === "archive" ? auth.organizations.archive(id) : auth.organizations.delete(id), how);
2108
2168
  if (!r.ok) return;
2109
2169
  setGone((how === "archive" ? f.t.organizationArchived : f.t.organizationDeleted).replace("{org}", seat.name));
2110
2170
  saved({ kind: how === "archive" ? "organization.archived" : "organization.deleted", organizationId: id });
@@ -2119,8 +2179,8 @@ function OrganizationMembers(props) {
2119
2179
  const confirming = (text2, label2, yes) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { role: "group", "aria-label": label2, children: [
2120
2180
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: text2 }),
2121
2181
  " ",
2122
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: yes, children: f.t.yes }),
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 })
2182
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "danger", disabled: f.busy, className: f.cx("providerButton"), onClick: yes, children: f.t.yes }),
2183
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", disabled: f.busy, className: f.cx("providerButton"), onClick: () => setAsking(null), children: f.t.cancel })
2124
2184
  ] });
2125
2185
  const leaveQuestion = f.t.memberLeaveConfirm.replace("{org}", seat.name);
2126
2186
  const archiveQuestion = f.t.organizationArchiveConfirm.replace("{org}", seat.name);
@@ -2128,8 +2188,8 @@ function OrganizationMembers(props) {
2128
2188
  const archiving = seat.can.archive && !hidden("archive");
2129
2189
  const deleting = seat.can.delete && !hidden("delete");
2130
2190
  const renaming = seat.can.update && !hidden("rename");
2131
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: f.cx("account"), ...root, children: [
2132
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: f.cx("section"), children: [
2191
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "div", slot: "account", root, children: [
2192
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "section", slot: "section", section: "members", children: [
2133
2193
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Heading, { f, children: [
2134
2194
  f.t.members,
2135
2195
  " \xB7 ",
@@ -2142,6 +2202,8 @@ function OrganizationMembers(props) {
2142
2202
  f.Button,
2143
2203
  {
2144
2204
  type: "button",
2205
+ variant: "danger",
2206
+ loading: f.loading(`remove:${auth.session.user.id}`),
2145
2207
  disabled: f.busy,
2146
2208
  className: f.cx("providerButton"),
2147
2209
  onClick: () => ask(auth.session.user.id, f.t.memberLeave, leaveQuestion, () => void remove({ userId: auth.session.user.id, you: true })),
@@ -2176,34 +2238,34 @@ function OrganizationMembers(props) {
2176
2238
  label: `${f.t.memberRole}: ${who}`,
2177
2239
  value: m.role,
2178
2240
  disabled: f.busy,
2179
- options: choices.map((c) => ({ value: c.role, label: c.name || c.role })),
2241
+ options: choices.map((c) => ({ value: c.role, label: roleName(c) })),
2180
2242
  onChange: (next) => void change(m, next)
2181
2243
  }
2182
2244
  ) : 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) }),
2183
2245
  " ",
2184
2246
  asking === m.userId ? confirming(question, action, () => void remove(m)) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
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 }),
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 })
2247
+ may.inviteAgain && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", loading: f.loading(`invite:${m.userId}`), disabled: f.busy, className: f.cx("providerButton"), onClick: () => void inviteAgain(m), children: f.t.memberInviteAgain }),
2248
+ removable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "danger", loading: f.loading(`remove:${m.userId}`), disabled: f.busy, className: f.cx("providerButton"), onClick: () => ask(m.userId, action, question, () => void remove(m)), children: action })
2187
2249
  ] })
2188
2250
  ] }, m.userId);
2189
2251
  }) }),
2190
2252
  done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
2191
2253
  ] }),
2192
- manage && giveable.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: add, noValidate: true, children: [
2254
+ manage && giveable.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "add-member", onSubmit: add, noValidate: true, children: [
2193
2255
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.memberAdd }),
2194
2256
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: "off", required: true, onChange: setEmail }),
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 }),
2196
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.memberAdd })
2257
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AddRole, { f, value: role, options: giveable.map((c) => ({ value: c.role, label: roleName(c) })), onChange: setRole }),
2258
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading("add"), disabled: f.busy, className: f.cx("button"), children: f.t.memberAdd })
2197
2259
  ] }),
2198
- (renaming || archiving || deleting) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: f.cx("section"), children: [
2260
+ (renaming || archiving || deleting) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "section", slot: "section", section: "organization", children: [
2199
2261
  /* @__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: [
2262
+ renaming && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", section: "rename", onSubmit: rename, noValidate: true, children: [
2201
2263
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "name", type: "text", label: f.t.name, value: name, autoComplete: "organization", required: true, onChange: setName }),
2202
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.organizationRename })
2264
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading("rename"), disabled: f.busy, className: f.cx("button"), children: f.t.organizationRename })
2203
2265
  ] }),
2204
2266
  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 })
2267
+ archiving && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "danger", loading: f.loading("archive"), disabled: f.busy, className: f.cx("providerButton"), onClick: () => ask("archive", f.t.organizationArchive, archiveQuestion, () => void close("archive")), children: f.t.organizationArchive }),
2268
+ deleting && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "danger", loading: f.loading("delete"), disabled: f.busy, className: f.cx("providerButton"), onClick: () => ask("delete", f.t.organizationDelete, deleteQuestion, () => void close("delete")), children: f.t.organizationDelete })
2207
2269
  ] })
2208
2270
  ] })
2209
2271
  ] });
@@ -2228,14 +2290,15 @@ function PasskeysPart({ props, account, accountUrl, when }) {
2228
2290
  }, []);
2229
2291
  if (here === null) return null;
2230
2292
  if (!here) {
2231
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: f.cx("section"), children: [
2293
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "section", slot: "section", section: "passkeys", children: [
2232
2294
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.passkeys }),
2233
2295
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: accountUrl, children: f.t.managePasskeys })
2234
2296
  ] });
2235
2297
  }
2236
2298
  const add = async (e, kind = "device") => {
2237
2299
  e?.preventDefault();
2238
- const r = await run(() => auth.account.addPasskey({ name, password, kind }));
2300
+ if (account.hasPassword && !f.check(checkPassword(password))) return;
2301
+ const r = await run(() => auth.account.addPasskey({ name, password, kind }), kind === "security_key" ? "security_key" : SUBMIT);
2239
2302
  if (!r.ok) {
2240
2303
  if (r.error.code === "cancelled") f.setError(null);
2241
2304
  return;
@@ -2247,12 +2310,12 @@ function PasskeysPart({ props, account, accountUrl, when }) {
2247
2310
  props.onSaved?.({ kind: "passkey.added", id: r.passkey.id });
2248
2311
  };
2249
2312
  const remove = async (id) => {
2250
- const r = await run(() => auth.account.removePasskey(id));
2313
+ const r = await run(() => auth.account.removePasskey(id), `remove:${id}`);
2251
2314
  if (!r.ok) return;
2252
2315
  setList(list.filter((p) => p.id !== id));
2253
2316
  props.onSaved?.({ kind: "passkey.removed", id });
2254
2317
  };
2255
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: add, noValidate: true, children: [
2318
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "passkeys", onSubmit: add, noValidate: true, children: [
2256
2319
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.passkeys }),
2257
2320
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.passkeysHelp }),
2258
2321
  general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
@@ -2262,12 +2325,12 @@ function PasskeysPart({ props, account, accountUrl, when }) {
2262
2325
  " \xB7 ",
2263
2326
  when(p.createdAt),
2264
2327
  " ",
2265
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void remove(p.id), children: f.t.removePasskey })
2328
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "danger", loading: f.loading(`remove:${p.id}`), disabled: f.busy, className: f.cx("providerButton"), onClick: () => void remove(p.id), children: f.t.removePasskey })
2266
2329
  ] }, p.id)) }),
2267
2330
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "name", type: "text", label: f.t.passkeyName, value: name, autoComplete: "off", onChange: setName }),
2268
2331
  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 }),
2269
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.addPasskeyDevice }),
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 }),
2332
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.addPasskeyDevice }),
2333
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", loading: f.loading("security_key"), disabled: f.busy, className: f.cx("providerButton"), onClick: () => void add(null, "security_key"), children: f.t.addSecurityKey }),
2271
2334
  done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
2272
2335
  ] });
2273
2336
  }
@@ -2283,12 +2346,12 @@ function ProfilePart({ props, account, onSaved }) {
2283
2346
  setDone(f.t.saved);
2284
2347
  props.onSaved?.({ kind: "profile.saved", name: r.account.name });
2285
2348
  };
2286
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: submit, noValidate: true, children: [
2349
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "profile", onSubmit: submit, noValidate: true, children: [
2287
2350
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.profile }),
2288
2351
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: account.email }),
2289
2352
  general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
2290
2353
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "name", type: "text", label: f.t.name, value: name, autoComplete: "name", onChange: setName }),
2291
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.save }),
2354
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.save }),
2292
2355
  done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
2293
2356
  ] });
2294
2357
  }
@@ -2299,19 +2362,20 @@ function EmailPart({ props, account }) {
2299
2362
  const [password, setPassword] = (0, import_react.useState)("");
2300
2363
  const submit = async (e) => {
2301
2364
  e.preventDefault();
2365
+ if (!f.check(checkEmail(email), account.hasPassword && checkPassword(password))) return;
2302
2366
  const r = await run(() => auth.account.changeEmail({ email, password }));
2303
2367
  if (!r.ok) return;
2304
2368
  setPassword("");
2305
2369
  setDone(f.t.emailSent.replace("{email}", r.email));
2306
2370
  props.onSaved?.({ kind: "email.change_requested", email: r.email });
2307
2371
  };
2308
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: submit, noValidate: true, children: [
2372
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "email", onSubmit: submit, noValidate: true, children: [
2309
2373
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.emailAddress }),
2310
2374
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: account.email }),
2311
2375
  general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
2312
2376
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Field, { f, name: "email", type: "email", label: f.t.newEmail, value: email, autoComplete: "email", required: true, onChange: setEmail }),
2313
2377
  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 }),
2314
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.changeEmail }),
2378
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.changeEmail }),
2315
2379
  done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
2316
2380
  ] });
2317
2381
  }
@@ -2334,13 +2398,13 @@ function LinkedPart({ props }) {
2334
2398
  if (linked === null) return null;
2335
2399
  const name = (id) => offered.find((p) => p.id === id)?.name ?? id;
2336
2400
  const unlink = async (provider) => {
2337
- const r = await run(() => auth.account.unlink(provider));
2401
+ const r = await run(() => auth.account.unlink(provider), `unlink:${provider}`);
2338
2402
  if (!r.ok) return;
2339
2403
  setLinked(linked.filter((x) => x.provider !== provider));
2340
2404
  props.onSaved?.({ kind: "identity.unlinked", provider });
2341
2405
  };
2342
2406
  const here = typeof window === "undefined" ? void 0 : window.location.pathname;
2343
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: f.cx("section"), children: [
2407
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "section", slot: "section", section: "linked", children: [
2344
2408
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.linkedAccounts }),
2345
2409
  came && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: f.t.linked }),
2346
2410
  general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
@@ -2348,9 +2412,9 @@ function LinkedPart({ props }) {
2348
2412
  name(x.provider),
2349
2413
  x.email ? ` \xB7 ${x.email}` : "",
2350
2414
  " ",
2351
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void unlink(x.provider), children: f.t.unlink })
2415
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "danger", loading: f.loading(`unlink:${x.provider}`), disabled: f.busy, className: f.cx("providerButton"), onClick: () => void unlink(x.provider), children: f.t.unlink })
2352
2416
  ] }, x.provider)) }),
2353
- offered.filter((p) => !linked.some((x) => x.provider === p.id)).map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(f.Button, { type: "button", className: f.cx("providerButton"), onClick: () => auth.account.link(p.id, { returnTo: here }), children: [
2417
+ offered.filter((p) => !linked.some((x) => x.provider === p.id)).map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(f.Button, { type: "button", variant: "secondary", className: f.cx("providerButton"), onClick: () => auth.account.link(p.id, { returnTo: here }), children: [
2354
2418
  f.t.linkWith,
2355
2419
  " ",
2356
2420
  p.name
@@ -2365,6 +2429,7 @@ function PasswordPart({ props }) {
2365
2429
  usePasswordPolicy(f, useMethods(auth));
2366
2430
  const submit = async (e) => {
2367
2431
  e.preventDefault();
2432
+ if (!f.check(checkPassword(password), newPasswordProblem(newPassword, f.policy, "newPassword"))) return;
2368
2433
  const r = await run(() => auth.account.changePassword({ password, newPassword }));
2369
2434
  if (!r.ok) return;
2370
2435
  setPassword("");
@@ -2372,12 +2437,12 @@ function PasswordPart({ props }) {
2372
2437
  setDone(f.t.passwordChangedHere);
2373
2438
  props.onSaved?.({ kind: "password.changed" });
2374
2439
  };
2375
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: submit, noValidate: true, children: [
2440
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "password", onSubmit: submit, noValidate: true, children: [
2376
2441
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.changePassword }),
2377
2442
  general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
2378
2443
  /* @__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 }),
2379
2444
  /* @__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 }),
2380
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.changePassword }),
2445
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.changePassword }),
2381
2446
  done && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "success", children: done })
2382
2447
  ] });
2383
2448
  }
@@ -2414,7 +2479,7 @@ function SecondStepPart({ props, account, onChanged }) {
2414
2479
  props.onSaved?.({ kind: "mfa.disabled" });
2415
2480
  };
2416
2481
  const renew = async () => {
2417
- const r = await run(() => auth.account.mfa.recoveryCodes({ password }));
2482
+ const r = await run(() => auth.account.mfa.recoveryCodes({ password }), "codes");
2418
2483
  if (!r.ok) return;
2419
2484
  setCodes(r.recoveryCodes);
2420
2485
  props.onSaved?.({ kind: "recovery_codes.regenerated" });
@@ -2425,24 +2490,24 @@ function SecondStepPart({ props, account, onChanged }) {
2425
2490
  /* @__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)) })
2426
2491
  ] });
2427
2492
  if (setup) {
2428
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: confirm, noValidate: true, children: [
2493
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "secondStep", onSubmit: confirm, noValidate: true, children: [
2429
2494
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.secondStep }),
2430
2495
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.addToApp }),
2431
2496
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { className: f.cx("secret"), children: setup.secret }),
2432
2497
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A, { f, href: setup.otpauthUri, children: f.t.openInApp }),
2433
2498
  general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
2434
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 }),
2435
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.verify })
2500
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.verify })
2436
2501
  ] });
2437
2502
  }
2438
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: account.mfaEnabled ? turnOff : start, noValidate: true, children: [
2503
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "secondStep", onSubmit: account.mfaEnabled ? turnOff : start, noValidate: true, children: [
2439
2504
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.secondStep }),
2440
2505
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: account.mfaEnabled ? f.t.secondStepOn : f.t.secondStepOff }),
2441
2506
  shown,
2442
2507
  general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
2443
2508
  passwordField,
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 }),
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 })
2509
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: account.mfaEnabled ? "danger" : "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: account.mfaEnabled ? f.t.turnOff : f.t.turnOn }),
2510
+ account.mfaEnabled && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "secondary", loading: f.loading("codes"), disabled: f.busy, className: f.cx("providerButton"), onClick: () => void renew(), children: f.t.newRecoveryCodes })
2446
2511
  ] });
2447
2512
  }
2448
2513
  function PhonePart({ props, account, onChanged }) {
@@ -2492,15 +2557,15 @@ function PhonePart({ props, account, onChanged }) {
2492
2557
  };
2493
2558
  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 });
2494
2559
  if (sentTo) {
2495
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: confirm, noValidate: true, children: [
2560
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "phone", onSubmit: confirm, noValidate: true, children: [
2496
2561
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.phone }),
2497
2562
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.codeSent.replace("{to}", sentTo) }),
2498
2563
  general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
2499
2564
  /* @__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 }),
2500
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.verify })
2565
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.verify })
2501
2566
  ] });
2502
2567
  }
2503
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { className: f.cx("section"), onSubmit: ways.phone ? remove : add, noValidate: true, children: [
2568
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "form", slot: "section", section: "phone", onSubmit: ways.phone ? remove : add, noValidate: true, children: [
2504
2569
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.phone }),
2505
2570
  /* @__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}` }),
2506
2571
  codes && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
@@ -2516,7 +2581,7 @@ function PhonePart({ props, account, onChanged }) {
2516
2581
  c === "whatsapp" ? f.t.byWhatsapp : f.t.bySms
2517
2582
  ] }, c)) }),
2518
2583
  passwordField,
2519
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: ways.phone ? f.t.removePhone : f.t.addPhone })
2584
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "submit", variant: ways.phone ? "danger" : "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: ways.phone ? f.t.removePhone : f.t.addPhone })
2520
2585
  ] });
2521
2586
  }
2522
2587
  function AgentsPart({ props, when }) {
@@ -2528,12 +2593,12 @@ function AgentsPart({ props, when }) {
2528
2593
  }, []);
2529
2594
  if (list.length === 0) return null;
2530
2595
  const disconnect = async (id) => {
2531
- const r = await run(() => auth.account.disconnectAgent(id));
2596
+ const r = await run(() => auth.account.disconnectAgent(id), `disconnect:${id}`);
2532
2597
  if (!r.ok) return;
2533
2598
  setList(list.filter((a) => a.id !== id));
2534
2599
  props.onSaved?.({ kind: "agent.disconnected", id });
2535
2600
  };
2536
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: f.cx("section"), children: [
2601
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "section", slot: "section", section: "agents", children: [
2537
2602
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.agents }),
2538
2603
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Note, { f, children: f.t.agentsHelp }),
2539
2604
  general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
@@ -2546,7 +2611,7 @@ function AgentsPart({ props, when }) {
2546
2611
  " \xB7 ",
2547
2612
  when(a.lastUsedAt),
2548
2613
  " ",
2549
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void disconnect(a.id), children: f.t.disconnect })
2614
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "danger", loading: f.loading(`disconnect:${a.id}`), disabled: f.busy, className: f.cx("providerButton"), onClick: () => void disconnect(a.id), children: f.t.disconnect })
2550
2615
  ] }, a.id)) })
2551
2616
  ] });
2552
2617
  }
@@ -2564,7 +2629,7 @@ function SessionsPart({ props, when }) {
2564
2629
  if (props.onSignedOut) props.onSignedOut();
2565
2630
  else window.location.assign("/");
2566
2631
  };
2567
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: f.cx("section"), children: [
2632
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrap, { f, as: "section", slot: "section", section: "sessions", children: [
2568
2633
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Heading, { f, children: f.t.sessions }),
2569
2634
  /* @__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
2635
  s.device || f.t.unknownDevice,
@@ -2574,7 +2639,7 @@ function SessionsPart({ props, when }) {
2574
2639
  when(s.createdAt)
2575
2640
  ] }, i)) }),
2576
2641
  general && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Say, { f, tone: "danger", children: f.say(general) }),
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 })
2642
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(f.Button, { type: "button", variant: "danger", loading: f.loading(), disabled: f.busy, className: f.cx("button"), onClick: () => void end(), children: f.t.signOutEverywhere })
2578
2643
  ] });
2579
2644
  }
2580
2645
  function ChannelPick({ f, value, channels, onChange }) {
@@ -2595,9 +2660,16 @@ function ChannelPick({ f, value, channels, onChange }) {
2595
2660
  // src/react.tsx
2596
2661
  var import_jsx_runtime2 = require("react/jsx-runtime");
2597
2662
  var Ctx = (0, import_react3.createContext)(null);
2663
+ var LocaleCtx = (0, import_react3.createContext)(() => void 0);
2598
2664
  var AHEAD_MS = 6e4;
2599
- function CauthyProvider({ children, basePath = "/api/auth", initialSession }) {
2665
+ function CauthyProvider({ children, basePath = "/api/auth", initialSession, locale }) {
2600
2666
  const base = withoutTrailingSlashes(basePath);
2667
+ const said = (0, import_react3.useRef)(locale);
2668
+ said.current = locale;
2669
+ const readLocale = (0, import_react3.useCallback)(() => {
2670
+ const l = said.current;
2671
+ return typeof l === "function" ? l() : l;
2672
+ }, []);
2601
2673
  const [session, setSession] = (0, import_react3.useState)(initialSession ?? null);
2602
2674
  const [status, setStatus] = (0, import_react3.useState)(
2603
2675
  initialSession === void 0 ? "loading" : initialSession === null ? "unauthenticated" : "authenticated"
@@ -2661,7 +2733,7 @@ function CauthyProvider({ children, basePath = "/api/auth", initialSession }) {
2661
2733
  }),
2662
2734
  [session, status, refresh, base]
2663
2735
  );
2664
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Ctx.Provider, { value, children });
2736
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Ctx.Provider, { value, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(LocaleCtx.Provider, { value: readLocale, children }) });
2665
2737
  }
2666
2738
  function useSession() {
2667
2739
  const ctx = (0, import_react3.useContext)(Ctx);
@@ -2670,8 +2742,9 @@ function useSession() {
2670
2742
  }
2671
2743
  function useAuth() {
2672
2744
  const { session, status, refresh, basePath } = useSession();
2745
+ const locale = (0, import_react3.useContext)(LocaleCtx);
2673
2746
  return (0, import_react3.useMemo)(() => {
2674
- const client = createAuthClient({ basePath });
2747
+ const client = createAuthClient({ basePath, locale });
2675
2748
  const then = async (running) => {
2676
2749
  const r = await running;
2677
2750
  await refresh();
@@ -2708,7 +2781,7 @@ function useAuth() {
2708
2781
  status,
2709
2782
  refresh
2710
2783
  };
2711
- }, [basePath, refresh, session, status]);
2784
+ }, [basePath, locale, refresh, session, status]);
2712
2785
  }
2713
2786
  // Annotate the CommonJS export names for ESM import in node:
2714
2787
  0 && (module.exports = {