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/README.md +22 -3
- package/dist/react.d.mts +54 -7
- package/dist/react.d.ts +54 -7
- package/dist/react.js +186 -113
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +189 -116
- package/dist/react.mjs.map +1 -1
- package/package.json +1 -1
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,
|
|
1253
|
-
const [
|
|
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.
|
|
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(
|
|
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(
|
|
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(
|
|
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",
|
|
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(
|
|
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(
|
|
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(
|
|
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",
|
|
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",
|
|
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",
|
|
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 =
|
|
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 =
|
|
1776
|
+
const providers = guest || methods?.organization?.required ? [] : methods?.providers ?? [];
|
|
1722
1777
|
if (sent) {
|
|
1723
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div",
|
|
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",
|
|
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",
|
|
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
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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(
|
|
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
|
|
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",
|
|
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",
|
|
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",
|
|
2062
|
-
if (seat === void 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div",
|
|
2063
|
-
if (seat === null) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div",
|
|
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
|
|
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
|
-
|
|
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",
|
|
2132
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section",
|
|
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
|
|
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",
|
|
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
|
|
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",
|
|
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",
|
|
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",
|
|
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
|
-
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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",
|
|
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 = {
|