cauthy-auth 0.31.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 +59 -2
- package/dist/react.d.mts +329 -30
- package/dist/react.d.ts +329 -30
- package/dist/react.js +617 -290
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +615 -298
- package/dist/react.mjs.map +1 -1
- package/package.json +2 -1
package/dist/react.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
// src/react.tsx
|
|
4
|
-
import { createContext, useCallback, useContext, useEffect as useEffect2, useMemo, useRef as useRef2, useState as useState2 } from "react";
|
|
4
|
+
import { createContext, useCallback as useCallback2, useContext, useEffect as useEffect2, useMemo, useRef as useRef2, useState as useState2 } from "react";
|
|
5
5
|
|
|
6
6
|
// src/passkey.ts
|
|
7
7
|
function canUsePasskeys() {
|
|
@@ -721,8 +721,8 @@ function definePolicy(given) {
|
|
|
721
721
|
}
|
|
722
722
|
|
|
723
723
|
// src/components.tsx
|
|
724
|
-
import { useEffect, useId, useRef, useState } from "react";
|
|
725
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
724
|
+
import { Fragment, useCallback, useEffect, useId, useRef, useState } from "react";
|
|
725
|
+
import { Fragment as Fragment2, jsx, jsxs } from "react/jsx-runtime";
|
|
726
726
|
var TEXTS = {
|
|
727
727
|
en: {
|
|
728
728
|
email: "Email",
|
|
@@ -763,6 +763,7 @@ var TEXTS = {
|
|
|
763
763
|
removePhone: "Remove phone",
|
|
764
764
|
bySms: "SMS",
|
|
765
765
|
byWhatsapp: "WhatsApp",
|
|
766
|
+
channel: "Send codes by",
|
|
766
767
|
checkEmail: "Almost there: open the link we sent to confirm your address \u2014 it signs you in.",
|
|
767
768
|
backToSignIn: "Back to sign in",
|
|
768
769
|
emailMeALink: "Email me a sign-in link",
|
|
@@ -852,6 +853,9 @@ var TEXTS = {
|
|
|
852
853
|
organizationDeleted: "{org} was deleted.",
|
|
853
854
|
yes: "Yes",
|
|
854
855
|
cancel: "Cancel",
|
|
856
|
+
termsChanged: "Our terms changed",
|
|
857
|
+
termsChangedHelp: "To go on, read and accept",
|
|
858
|
+
acceptTerms: "Accept",
|
|
855
859
|
errors: {
|
|
856
860
|
not_allowed: "Your role in this organization does not allow that.",
|
|
857
861
|
last_manager: "Somebody else must manage the members first: give that role to another member.",
|
|
@@ -939,6 +943,7 @@ var TEXTS = {
|
|
|
939
943
|
removePhone: "Quitar tel\xE9fono",
|
|
940
944
|
bySms: "SMS",
|
|
941
945
|
byWhatsapp: "WhatsApp",
|
|
946
|
+
channel: "Enviar los c\xF3digos por",
|
|
942
947
|
checkEmail: "Casi listo: abre el enlace que te enviamos para confirmar tu correo; te deja adentro.",
|
|
943
948
|
backToSignIn: "Volver a entrar",
|
|
944
949
|
emailMeALink: "Env\xEDame un enlace para entrar",
|
|
@@ -1028,6 +1033,9 @@ var TEXTS = {
|
|
|
1028
1033
|
organizationDeleted: "{org} qued\xF3 eliminada.",
|
|
1029
1034
|
yes: "S\xED",
|
|
1030
1035
|
cancel: "Cancelar",
|
|
1036
|
+
termsChanged: "Nuestros t\xE9rminos cambiaron",
|
|
1037
|
+
termsChangedHelp: "Para seguir, lee y acepta",
|
|
1038
|
+
acceptTerms: "Aceptar",
|
|
1031
1039
|
errors: {
|
|
1032
1040
|
not_allowed: "Tu rol en esta organizaci\xF3n no permite eso.",
|
|
1033
1041
|
last_manager: "Primero alguien m\xE1s debe administrar los miembros: dale ese rol a otro miembro.",
|
|
@@ -1077,7 +1085,7 @@ var TEXTS = {
|
|
|
1077
1085
|
}
|
|
1078
1086
|
}
|
|
1079
1087
|
};
|
|
1080
|
-
var PlainButton = (p) => /* @__PURE__ */ jsx("button", { ...p });
|
|
1088
|
+
var PlainButton = ({ variant: _variant, loading: _loading, ...p }) => /* @__PURE__ */ jsx("button", { ...p });
|
|
1081
1089
|
var PlainInput = (p) => /* @__PURE__ */ jsx("input", { ...p });
|
|
1082
1090
|
var looks = /* @__PURE__ */ new Map();
|
|
1083
1091
|
var loaded = /* @__PURE__ */ new Set();
|
|
@@ -1188,10 +1196,28 @@ function sameOrigin(to) {
|
|
|
1188
1196
|
function useForm(props) {
|
|
1189
1197
|
const t = { ...TEXTS[props.locale ?? "en"], ...props.texts, errors: { ...TEXTS[props.locale ?? "en"].errors, ...props.texts?.errors } };
|
|
1190
1198
|
const cx = (slot) => props.classNames?.[slot] ?? `cauthy-${slot}`;
|
|
1191
|
-
const
|
|
1192
|
-
const
|
|
1193
|
-
const
|
|
1194
|
-
const
|
|
1199
|
+
const own = (slot) => props.classNames?.[slot];
|
|
1200
|
+
const C = props.components ?? {};
|
|
1201
|
+
const Button = C.Button ?? PlainButton;
|
|
1202
|
+
const Input = C.Input ?? PlainInput;
|
|
1203
|
+
const [error, setOnlyError] = useState(null);
|
|
1204
|
+
const [problems, setProblems] = useState({ list: [], round: 0 });
|
|
1205
|
+
const setError = useCallback((e) => {
|
|
1206
|
+
setOnlyError(e);
|
|
1207
|
+
setProblems((p) => p.list.length === 0 ? p : { list: [], round: p.round });
|
|
1208
|
+
}, []);
|
|
1209
|
+
const check = (...found) => {
|
|
1210
|
+
const list = found.filter((e) => Boolean(e));
|
|
1211
|
+
setOnlyError(null);
|
|
1212
|
+
setProblems((p) => ({ list, round: list.length > 0 ? p.round + 1 : p.round }));
|
|
1213
|
+
return list.length === 0;
|
|
1214
|
+
};
|
|
1215
|
+
const fieldError = (name) => problems.list.find((e) => e.field === name) ?? (error?.field === name ? error : null);
|
|
1216
|
+
const firstWrong = (name) => problems.list[0]?.field === name ? problems.round : 0;
|
|
1217
|
+
const [acting, setActing] = useState(null);
|
|
1218
|
+
const busy = acting !== null;
|
|
1219
|
+
const setBusy = useCallback((on) => setActing(on === false ? null : on === true ? SUBMIT : on), []);
|
|
1220
|
+
const loading = (key = SUBMIT) => acting === key;
|
|
1195
1221
|
const [policy, setPolicy] = useState(void 0);
|
|
1196
1222
|
const locale = props.locale ?? "en";
|
|
1197
1223
|
const say = (e) => {
|
|
@@ -1204,13 +1230,113 @@ function useForm(props) {
|
|
|
1204
1230
|
else window.location.assign(sitePath(to) ?? sameOrigin(props.returnTo) ?? "/");
|
|
1205
1231
|
};
|
|
1206
1232
|
const root = useRoot(props);
|
|
1207
|
-
return { t, cx, Button, Input, error, setError, busy, setBusy, say, done, root, policy, setPolicy, passwordRule };
|
|
1233
|
+
return { t, cx, own, C, Button, Input, error, setError, check, fieldError, firstWrong, busy, setBusy, loading, say, done, root, policy, setPolicy, passwordRule };
|
|
1234
|
+
}
|
|
1235
|
+
var SUBMIT = "submit";
|
|
1236
|
+
function Wrap(p) {
|
|
1237
|
+
const { Form: OwnForm } = p.f.C;
|
|
1238
|
+
if (OwnForm) {
|
|
1239
|
+
const own = /* @__PURE__ */ jsx(
|
|
1240
|
+
OwnForm,
|
|
1241
|
+
{
|
|
1242
|
+
as: p.as === "form" ? "form" : "div",
|
|
1243
|
+
onSubmit: p.onSubmit,
|
|
1244
|
+
noValidate: p.noValidate,
|
|
1245
|
+
"aria-busy": p.busy,
|
|
1246
|
+
className: p.slot ? p.f.own(p.slot) : void 0,
|
|
1247
|
+
section: p.section,
|
|
1248
|
+
children: p.children
|
|
1249
|
+
}
|
|
1250
|
+
);
|
|
1251
|
+
return p.root?.["data-cauthy"] !== void 0 ? /* @__PURE__ */ jsx("div", { ...p.root, children: own }) : own;
|
|
1252
|
+
}
|
|
1253
|
+
const Tag2 = p.as;
|
|
1254
|
+
return /* @__PURE__ */ 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 });
|
|
1255
|
+
}
|
|
1256
|
+
function Note({ f, children, footer }) {
|
|
1257
|
+
const { Text } = f.C;
|
|
1258
|
+
if (Text) return /* @__PURE__ */ jsx(Text, { as: "p", tone: "muted", size: footer ? "sm" : "md", children });
|
|
1259
|
+
return /* @__PURE__ */ jsx("p", { className: f.cx(footer ? "footer" : "notice"), children });
|
|
1260
|
+
}
|
|
1261
|
+
function Heading({ f, children }) {
|
|
1262
|
+
const { Text } = f.C;
|
|
1263
|
+
if (Text) return /* @__PURE__ */ jsx(Text, { as: "h2", size: "lg", children });
|
|
1264
|
+
return /* @__PURE__ */ jsx("h2", { className: f.cx("heading"), children });
|
|
1265
|
+
}
|
|
1266
|
+
function Say({ f, tone, children }) {
|
|
1267
|
+
const { Alert } = f.C;
|
|
1268
|
+
if (Alert) return /* @__PURE__ */ jsx(Alert, { tone, children });
|
|
1269
|
+
if (tone === "danger") return /* @__PURE__ */ jsx("p", { role: "alert", className: f.cx("error"), children });
|
|
1270
|
+
return /* @__PURE__ */ jsx("p", { role: "status", className: f.cx("notice"), children });
|
|
1271
|
+
}
|
|
1272
|
+
function Or({ f, children }) {
|
|
1273
|
+
const { Divider } = f.C;
|
|
1274
|
+
if (Divider) return /* @__PURE__ */ jsx(Divider, { label: children });
|
|
1275
|
+
return /* @__PURE__ */ jsx("p", { className: f.cx("separator"), children });
|
|
1276
|
+
}
|
|
1277
|
+
function A({ f, href, newTab, children }) {
|
|
1278
|
+
const { Link } = f.C;
|
|
1279
|
+
if (Link) return /* @__PURE__ */ jsx(Link, { href, newTab, children });
|
|
1280
|
+
return /* @__PURE__ */ jsx("a", { className: f.cx("link"), href, target: newTab ? "_blank" : void 0, rel: newTab ? "noopener" : void 0, children });
|
|
1281
|
+
}
|
|
1282
|
+
function Tag({ f, tone, children, plain }) {
|
|
1283
|
+
const { Badge } = f.C;
|
|
1284
|
+
if (Badge) return /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
1285
|
+
" ",
|
|
1286
|
+
/* @__PURE__ */ jsx(Badge, { tone, children })
|
|
1287
|
+
] });
|
|
1288
|
+
return /* @__PURE__ */ jsx(Fragment2, { children: plain });
|
|
1289
|
+
}
|
|
1290
|
+
function Check(p) {
|
|
1291
|
+
const id = useId();
|
|
1292
|
+
const { f } = p;
|
|
1293
|
+
const { Checkbox } = f.C;
|
|
1294
|
+
if (Checkbox) {
|
|
1295
|
+
return /* @__PURE__ */ jsx(Checkbox, { id, name: p.name, checked: p.checked, required: p.required, className: f.own("check"), onChange: p.onChange, children: p.children });
|
|
1296
|
+
}
|
|
1297
|
+
return /* @__PURE__ */ jsxs("label", { className: f.cx("check"), children: [
|
|
1298
|
+
/* @__PURE__ */ jsx("input", { type: "checkbox", name: p.name, checked: p.checked, required: p.required, onChange: (e) => p.onChange(e.target.checked) }),
|
|
1299
|
+
/* @__PURE__ */ jsx("span", { children: p.children })
|
|
1300
|
+
] });
|
|
1301
|
+
}
|
|
1302
|
+
function Pick(p) {
|
|
1303
|
+
const made = useId();
|
|
1304
|
+
const id = p.id ?? made;
|
|
1305
|
+
const { f } = p;
|
|
1306
|
+
const { Select } = f.C;
|
|
1307
|
+
if (Select) {
|
|
1308
|
+
return /* @__PURE__ */ jsx(Select, { id, name: p.name, value: p.value, options: p.options, disabled: p.disabled, "aria-label": p.label, className: f.own("input"), onChange: p.onChange });
|
|
1309
|
+
}
|
|
1310
|
+
return /* @__PURE__ */ jsx("select", { id, name: p.name, "aria-label": p.label, className: f.cx("input"), value: p.value, disabled: p.disabled, onChange: (e) => p.onChange(e.target.value), children: p.options.map((o) => /* @__PURE__ */ jsx("option", { value: o.value, children: o.label }, o.value)) });
|
|
1311
|
+
}
|
|
1312
|
+
function Labelled({ f, id, label, children }) {
|
|
1313
|
+
const { Field: OwnField } = f.C;
|
|
1314
|
+
if (OwnField) return /* @__PURE__ */ jsx(OwnField, { id, label, className: f.own("field"), children });
|
|
1315
|
+
return /* @__PURE__ */ jsxs("label", { className: f.cx("field"), children: [
|
|
1316
|
+
/* @__PURE__ */ jsx("span", { className: f.cx("label"), children: label }),
|
|
1317
|
+
children
|
|
1318
|
+
] });
|
|
1319
|
+
}
|
|
1320
|
+
function Documents({ f, documents }) {
|
|
1321
|
+
return /* @__PURE__ */ jsx(Fragment2, { children: documents.map((d, i) => /* @__PURE__ */ jsxs("span", { children: [
|
|
1322
|
+
i > 0 && /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
1323
|
+
f.t.and,
|
|
1324
|
+
" "
|
|
1325
|
+
] }),
|
|
1326
|
+
/* @__PURE__ */ jsx(A, { f, href: d.url, newTab: true, children: d.kind === "terms" ? f.t.termsOfService : f.t.privacyPolicy }),
|
|
1327
|
+
" "
|
|
1328
|
+
] }, d.kind)) });
|
|
1208
1329
|
}
|
|
1209
1330
|
var PASSWORD_RULES = ["needs_lowercase", "needs_uppercase", "needs_digit", "needs_symbol", "needs_classes", "breached"];
|
|
1210
1331
|
function isPasswordRule(e) {
|
|
1211
1332
|
if (e.code === "weak_password" || PASSWORD_RULES.includes(e.code)) return true;
|
|
1212
1333
|
return (e.code === "too_short" || e.code === "too_long") && (e.field === "password" || e.field === "newPassword");
|
|
1213
1334
|
}
|
|
1335
|
+
function newPasswordProblem(value, policy, field = "password") {
|
|
1336
|
+
const bad = checkNewPassword(value, policy);
|
|
1337
|
+
if (!bad) return null;
|
|
1338
|
+
return { code: bad.code, message: bad.message, field, ...bad.code === "required" ? {} : { reasons: passwordProblems(value, policy) } };
|
|
1339
|
+
}
|
|
1214
1340
|
function usePasswordPolicy(f, methods) {
|
|
1215
1341
|
const { setPolicy } = f;
|
|
1216
1342
|
useEffect(() => {
|
|
@@ -1220,28 +1346,49 @@ function usePasswordPolicy(f, methods) {
|
|
|
1220
1346
|
function Field(p) {
|
|
1221
1347
|
const id = useId();
|
|
1222
1348
|
const { f } = p;
|
|
1223
|
-
const bad = f.
|
|
1349
|
+
const bad = f.fieldError(p.name);
|
|
1350
|
+
const focus = f.firstWrong(p.name);
|
|
1351
|
+
useEffect(() => {
|
|
1352
|
+
if (focus > 0 && typeof document !== "undefined") document.getElementById(id)?.focus();
|
|
1353
|
+
}, [focus, id]);
|
|
1224
1354
|
const described = [bad ? `${id}-error` : "", p.hint ? `${id}-hint` : ""].filter(Boolean).join(" ");
|
|
1355
|
+
const input = /* @__PURE__ */ jsx(
|
|
1356
|
+
f.Input,
|
|
1357
|
+
{
|
|
1358
|
+
id,
|
|
1359
|
+
name: p.name,
|
|
1360
|
+
type: p.type,
|
|
1361
|
+
value: p.value,
|
|
1362
|
+
autoComplete: p.autoComplete,
|
|
1363
|
+
required: p.required,
|
|
1364
|
+
className: f.cx("input"),
|
|
1365
|
+
"aria-invalid": bad ? true : void 0,
|
|
1366
|
+
"aria-describedby": described || void 0,
|
|
1367
|
+
onChange: (e) => p.onChange(e.target.value)
|
|
1368
|
+
}
|
|
1369
|
+
);
|
|
1370
|
+
const { Field: OwnField } = f.C;
|
|
1371
|
+
if (OwnField) {
|
|
1372
|
+
return /* @__PURE__ */ jsx(
|
|
1373
|
+
OwnField,
|
|
1374
|
+
{
|
|
1375
|
+
id,
|
|
1376
|
+
label: p.label,
|
|
1377
|
+
aside: p.aside,
|
|
1378
|
+
help: p.hint && !bad ? p.hint : void 0,
|
|
1379
|
+
error: bad ? f.say(bad) : void 0,
|
|
1380
|
+
required: p.required,
|
|
1381
|
+
className: f.own("field"),
|
|
1382
|
+
children: input
|
|
1383
|
+
}
|
|
1384
|
+
);
|
|
1385
|
+
}
|
|
1225
1386
|
return /* @__PURE__ */ jsxs("div", { className: f.cx("field"), children: [
|
|
1226
1387
|
/* @__PURE__ */ jsxs("label", { className: f.cx("label"), htmlFor: id, children: [
|
|
1227
1388
|
p.label,
|
|
1228
1389
|
p.aside
|
|
1229
1390
|
] }),
|
|
1230
|
-
|
|
1231
|
-
f.Input,
|
|
1232
|
-
{
|
|
1233
|
-
id,
|
|
1234
|
-
name: p.name,
|
|
1235
|
-
type: p.type,
|
|
1236
|
-
value: p.value,
|
|
1237
|
-
autoComplete: p.autoComplete,
|
|
1238
|
-
required: p.required,
|
|
1239
|
-
className: f.cx("input"),
|
|
1240
|
-
"aria-invalid": bad ? true : void 0,
|
|
1241
|
-
"aria-describedby": described || void 0,
|
|
1242
|
-
onChange: (e) => p.onChange(e.target.value)
|
|
1243
|
-
}
|
|
1244
|
-
),
|
|
1391
|
+
input,
|
|
1245
1392
|
p.hint && !bad && /* @__PURE__ */ jsx("span", { id: `${id}-hint`, className: f.cx("hint"), children: p.hint }),
|
|
1246
1393
|
bad && /* @__PURE__ */ jsx("span", { id: `${id}-error`, role: "alert", className: f.cx("fieldError"), children: f.say(bad) })
|
|
1247
1394
|
] });
|
|
@@ -1279,7 +1426,7 @@ function SecondStepForm(p) {
|
|
|
1279
1426
|
});
|
|
1280
1427
|
}, []);
|
|
1281
1428
|
const sendEmail = async () => {
|
|
1282
|
-
f.setBusy(
|
|
1429
|
+
f.setBusy("email");
|
|
1283
1430
|
f.setError(null);
|
|
1284
1431
|
const r = await auth.signIn.mfaSendEmail();
|
|
1285
1432
|
f.setBusy(false);
|
|
@@ -1290,7 +1437,7 @@ function SecondStepForm(p) {
|
|
|
1290
1437
|
const pushWait = useRef(null);
|
|
1291
1438
|
useEffect(() => () => pushWait.current?.abort(), []);
|
|
1292
1439
|
const sendPush = async () => {
|
|
1293
|
-
f.setBusy(
|
|
1440
|
+
f.setBusy("push");
|
|
1294
1441
|
f.setError(null);
|
|
1295
1442
|
const r = await auth.signIn.mfaPush();
|
|
1296
1443
|
f.setBusy(false);
|
|
@@ -1306,7 +1453,7 @@ function SecondStepForm(p) {
|
|
|
1306
1453
|
f.done();
|
|
1307
1454
|
};
|
|
1308
1455
|
const sendCode = async () => {
|
|
1309
|
-
f.setBusy(
|
|
1456
|
+
f.setBusy("phone");
|
|
1310
1457
|
f.setError(null);
|
|
1311
1458
|
const r = await auth.signIn.mfaSendCode();
|
|
1312
1459
|
f.setBusy(false);
|
|
@@ -1324,23 +1471,30 @@ function SecondStepForm(p) {
|
|
|
1324
1471
|
};
|
|
1325
1472
|
const general = f.error && !f.error.field ? f.error : null;
|
|
1326
1473
|
const to = phoneWay?.phone?.number ?? "";
|
|
1327
|
-
return /* @__PURE__ */ jsxs("form",
|
|
1328
|
-
/* @__PURE__ */ jsx(
|
|
1329
|
-
general && /* @__PURE__ */ jsx(
|
|
1330
|
-
phoneWay?.email && /* @__PURE__ */ jsx(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void sendEmail(), children: f.t.sendEmailAgain }),
|
|
1331
|
-
pushNumber > 0 ?
|
|
1474
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "form", slot: "form", root: f.root, onSubmit: submit, noValidate: true, children: [
|
|
1475
|
+
/* @__PURE__ */ 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 }),
|
|
1476
|
+
general && /* @__PURE__ */ jsx(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1477
|
+
phoneWay?.email && /* @__PURE__ */ 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 }),
|
|
1478
|
+
pushNumber > 0 ? f.C.Text ? (
|
|
1479
|
+
// The application's text: the number to pick drawn large, by its own rules.
|
|
1480
|
+
/* @__PURE__ */ jsxs("div", { role: "status", "aria-live": "polite", children: [
|
|
1481
|
+
/* @__PURE__ */ jsx(f.C.Text, { as: "p", children: f.t.pushPick.replace("{n}", String(pushNumber)) }),
|
|
1482
|
+
/* @__PURE__ */ jsx(f.C.Text, { as: "p", size: "lg", children: pushNumber }),
|
|
1483
|
+
/* @__PURE__ */ jsx(f.C.Text, { as: "p", tone: "muted", children: f.t.pushWaiting })
|
|
1484
|
+
] })
|
|
1485
|
+
) : /* @__PURE__ */ jsxs("div", { className: f.cx("notice"), role: "status", "aria-live": "polite", children: [
|
|
1332
1486
|
/* @__PURE__ */ jsx("p", { children: f.t.pushPick.replace("{n}", String(pushNumber)) }),
|
|
1333
1487
|
/* @__PURE__ */ jsx("p", { style: { fontSize: 48, fontWeight: 700, margin: "4px 0", textAlign: "center" }, children: pushNumber }),
|
|
1334
1488
|
/* @__PURE__ */ jsx("p", { children: f.t.pushWaiting })
|
|
1335
|
-
] }) : phoneWay?.push && /* @__PURE__ */ jsx(f.Button, { type: "button", disabled: f.busy, className: f.cx("button"), onClick: () => void sendPush(), children: f.t.pushSend }),
|
|
1336
|
-
phoneWay?.phone && /* @__PURE__ */ 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) }),
|
|
1489
|
+
] }) : phoneWay?.push && /* @__PURE__ */ 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 }),
|
|
1490
|
+
phoneWay?.phone && /* @__PURE__ */ 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) }),
|
|
1337
1491
|
/* @__PURE__ */ jsx(Field, { f, name: "code", type: "text", label: f.t.code, value: code, autoComplete: "one-time-code", required: true, onChange: setCode }),
|
|
1338
|
-
/* @__PURE__ */ jsx(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.verify })
|
|
1492
|
+
/* @__PURE__ */ jsx(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.verify })
|
|
1339
1493
|
] });
|
|
1340
1494
|
}
|
|
1341
1495
|
function ProviderButtons(p) {
|
|
1342
1496
|
const { f } = p;
|
|
1343
|
-
return /* @__PURE__ */ jsx(
|
|
1497
|
+
return /* @__PURE__ */ jsx(Fragment2, { children: p.providers.map((provider) => /* @__PURE__ */ jsxs(f.Button, { type: "button", variant: "secondary", className: f.cx("providerButton"), onClick: () => p.onPick(provider.id), children: [
|
|
1344
1498
|
provider.iconUrl && /* @__PURE__ */ jsx("img", { src: provider.iconUrl, alt: "", width: 18, height: 18, className: f.cx("providerIcon") }),
|
|
1345
1499
|
f.t.continueWith,
|
|
1346
1500
|
" ",
|
|
@@ -1380,7 +1534,7 @@ function SignIn(props) {
|
|
|
1380
1534
|
}, [email, methods]);
|
|
1381
1535
|
const toCompany = () => {
|
|
1382
1536
|
autofill.current?.abort();
|
|
1383
|
-
f.setBusy(
|
|
1537
|
+
f.setBusy("sso");
|
|
1384
1538
|
auth.signIn.sso({ email }, { returnTo: props.returnTo });
|
|
1385
1539
|
};
|
|
1386
1540
|
useEffect(() => {
|
|
@@ -1422,6 +1576,7 @@ function SignIn(props) {
|
|
|
1422
1576
|
if (methods?.magicLink) return sendLink();
|
|
1423
1577
|
return;
|
|
1424
1578
|
}
|
|
1579
|
+
if (step === "password" && !f.check(checkEmail(email), checkPassword(password))) return;
|
|
1425
1580
|
f.setBusy(true);
|
|
1426
1581
|
f.setError(null);
|
|
1427
1582
|
const r = step === "sent" ? await auth.signIn.emailCode({ code }) : await auth.signIn.email({ email, password, captchaToken: challenge.token });
|
|
@@ -1437,7 +1592,7 @@ function SignIn(props) {
|
|
|
1437
1592
|
};
|
|
1438
1593
|
const usePasskey = async () => {
|
|
1439
1594
|
autofill.current?.abort();
|
|
1440
|
-
f.setBusy(
|
|
1595
|
+
f.setBusy("passkey");
|
|
1441
1596
|
f.setError(null);
|
|
1442
1597
|
const r = await auth.signIn.passkey({ returnTo: props.returnTo, locale: props.locale, email });
|
|
1443
1598
|
if (r.ok && r.status === "redirected") return;
|
|
@@ -1448,7 +1603,7 @@ function SignIn(props) {
|
|
|
1448
1603
|
};
|
|
1449
1604
|
const sendLink = async () => {
|
|
1450
1605
|
autofill.current?.abort();
|
|
1451
|
-
f.setBusy(
|
|
1606
|
+
f.setBusy("link");
|
|
1452
1607
|
f.setError(null);
|
|
1453
1608
|
const r = await auth.signIn.magicLink({ email, captchaToken: challenge.token, create: props.createAccounts, returnTo: props.returnTo });
|
|
1454
1609
|
f.setBusy(false);
|
|
@@ -1459,30 +1614,30 @@ function SignIn(props) {
|
|
|
1459
1614
|
};
|
|
1460
1615
|
const general = f.error && !f.error.field ? f.error : null;
|
|
1461
1616
|
const asksEmail = offers.email;
|
|
1462
|
-
if (step === "opening") return /* @__PURE__ */ jsx("div",
|
|
1617
|
+
if (step === "opening") return /* @__PURE__ */ jsx(Wrap, { f, as: "div", slot: "form", root: f.root, busy: true });
|
|
1463
1618
|
if (step === "sent") {
|
|
1464
|
-
return /* @__PURE__ */ jsxs("form",
|
|
1465
|
-
/* @__PURE__ */ jsx(
|
|
1466
|
-
general && /* @__PURE__ */ jsx(
|
|
1467
|
-
/* @__PURE__ */ jsx(
|
|
1619
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "form", slot: "form", root: f.root, onSubmit: submit, noValidate: true, children: [
|
|
1620
|
+
/* @__PURE__ */ jsx(Note, { f, children: f.t.signInLinkSent }),
|
|
1621
|
+
general && /* @__PURE__ */ jsx(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1622
|
+
/* @__PURE__ */ jsx(Note, { f, children: f.t.codeFromMail }),
|
|
1468
1623
|
/* @__PURE__ */ jsx(Field, { f, name: "code", type: "text", label: f.t.code, value: code, autoComplete: "one-time-code", required: true, onChange: setCode }),
|
|
1469
|
-
/* @__PURE__ */ jsx(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.verify })
|
|
1624
|
+
/* @__PURE__ */ jsx(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.verify })
|
|
1470
1625
|
] });
|
|
1471
1626
|
}
|
|
1472
1627
|
if (step === "code") return /* @__PURE__ */ jsx(SecondStepForm, { f, auth });
|
|
1473
|
-
return /* @__PURE__ */ jsxs("form",
|
|
1474
|
-
general && /* @__PURE__ */ jsx(
|
|
1628
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "form", slot: "form", root: f.root, onSubmit: submit, noValidate: true, children: [
|
|
1629
|
+
general && /* @__PURE__ */ jsx(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1475
1630
|
/* @__PURE__ */ jsx(ProviderButtons, { f, providers: methods?.providers ?? [], onPick: (id) => auth.signIn.social(id, { returnTo: props.returnTo }) }),
|
|
1476
|
-
offers.passkey && /* @__PURE__ */ jsx(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void usePasskey(), children: f.t.usePasskey }),
|
|
1477
|
-
asksEmail && ((methods?.providers.length ?? 0) > 0 || offers.passkey) && /* @__PURE__ */ jsx(
|
|
1631
|
+
offers.passkey && /* @__PURE__ */ 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 }),
|
|
1632
|
+
asksEmail && ((methods?.providers.length ?? 0) > 0 || offers.passkey) && /* @__PURE__ */ jsx(Or, { f, children: f.t.orWithEmail }),
|
|
1478
1633
|
asksEmail && /* @__PURE__ */ jsx(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: methods?.passkeyHere ? "username webauthn" : "username", required: true, onChange: setEmail }),
|
|
1479
|
-
company && /* @__PURE__ */ jsxs(f.Button, { type: "button", disabled: f.busy, className: f.cx(company.enforced ? "button" : "providerButton"), onClick: toCompany, children: [
|
|
1634
|
+
company && /* @__PURE__ */ 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: [
|
|
1480
1635
|
f.t.continueWith,
|
|
1481
1636
|
" ",
|
|
1482
1637
|
company.name
|
|
1483
1638
|
] }),
|
|
1484
|
-
company?.enforced && /* @__PURE__ */ jsx(
|
|
1485
|
-
!company?.enforced && passwordOn && /* @__PURE__ */ jsxs(
|
|
1639
|
+
company?.enforced && /* @__PURE__ */ jsx(Note, { f, children: f.t.ssoOnly }),
|
|
1640
|
+
!company?.enforced && passwordOn && /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
1486
1641
|
/* @__PURE__ */ jsx(
|
|
1487
1642
|
Field,
|
|
1488
1643
|
{
|
|
@@ -1494,18 +1649,18 @@ function SignIn(props) {
|
|
|
1494
1649
|
autoComplete: "current-password",
|
|
1495
1650
|
required: true,
|
|
1496
1651
|
onChange: setPassword,
|
|
1497
|
-
aside: props.links?.forgotPassword ? /* @__PURE__ */ jsx(
|
|
1652
|
+
aside: props.links?.forgotPassword ? /* @__PURE__ */ jsx(A, { f, href: props.links.forgotPassword, children: f.t.forgotPassword }) : void 0
|
|
1498
1653
|
}
|
|
1499
1654
|
),
|
|
1500
1655
|
challenge.node,
|
|
1501
|
-
/* @__PURE__ */ jsx(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.signIn })
|
|
1656
|
+
/* @__PURE__ */ jsx(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.signIn })
|
|
1502
1657
|
] }),
|
|
1503
1658
|
!company?.enforced && !passwordOn && methods?.magicLink && challenge.node,
|
|
1504
|
-
methods?.magicLink && !company?.enforced && /* @__PURE__ */ jsx(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void sendLink(), children: f.t.emailMeALink }),
|
|
1505
|
-
methods?.signUp !== false && props.links?.signUp && /* @__PURE__ */ jsxs(
|
|
1659
|
+
methods?.magicLink && !company?.enforced && /* @__PURE__ */ 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 }),
|
|
1660
|
+
methods?.signUp !== false && props.links?.signUp && /* @__PURE__ */ jsxs(Note, { f, footer: true, children: [
|
|
1506
1661
|
f.t.noAccount,
|
|
1507
1662
|
" ",
|
|
1508
|
-
/* @__PURE__ */ jsx(
|
|
1663
|
+
/* @__PURE__ */ jsx(A, { f, href: props.links.signUp, children: f.t.createAccount })
|
|
1509
1664
|
] })
|
|
1510
1665
|
] });
|
|
1511
1666
|
}
|
|
@@ -1541,11 +1696,19 @@ function SignUp(props) {
|
|
|
1541
1696
|
const [acceptLegal, setAcceptLegal] = useState(false);
|
|
1542
1697
|
const [consents, setConsents] = useState({});
|
|
1543
1698
|
const legal = methods?.legal;
|
|
1699
|
+
const guest = auth.session?.user.isAnonymous === true;
|
|
1544
1700
|
const submit = async (e) => {
|
|
1545
1701
|
e.preventDefault();
|
|
1702
|
+
const asksCompany = methods?.organization?.ask === true;
|
|
1703
|
+
if (!f.check(
|
|
1704
|
+
asksCompany && checkOrganization(organization, methods?.organization?.required === true),
|
|
1705
|
+
checkName(name),
|
|
1706
|
+
checkEmail(email),
|
|
1707
|
+
newPasswordProblem(password, f.policy)
|
|
1708
|
+
)) return;
|
|
1546
1709
|
f.setBusy(true);
|
|
1547
1710
|
f.setError(null);
|
|
1548
|
-
const r =
|
|
1711
|
+
const r = guest ? await auth.account.upgrade({ name, email, password }) : await auth.signUp.email({
|
|
1549
1712
|
name,
|
|
1550
1713
|
email,
|
|
1551
1714
|
password,
|
|
@@ -1561,54 +1724,42 @@ function SignUp(props) {
|
|
|
1561
1724
|
};
|
|
1562
1725
|
const general = f.error && !f.error.field ? f.error : null;
|
|
1563
1726
|
const passwordOn = methods?.passwordSignIn !== false;
|
|
1564
|
-
const providers =
|
|
1727
|
+
const providers = guest || methods?.organization?.required ? [] : methods?.providers ?? [];
|
|
1565
1728
|
if (sent) {
|
|
1566
|
-
return /* @__PURE__ */ jsxs("div",
|
|
1567
|
-
/* @__PURE__ */ jsx(
|
|
1568
|
-
props.links?.signIn && /* @__PURE__ */ jsx(
|
|
1729
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "div", slot: "form", root: f.root, children: [
|
|
1730
|
+
/* @__PURE__ */ jsx(Note, { f, children: f.t.checkEmail }),
|
|
1731
|
+
props.links?.signIn && /* @__PURE__ */ jsx(A, { f, href: props.links.signIn, children: f.t.backToSignIn })
|
|
1569
1732
|
] });
|
|
1570
1733
|
}
|
|
1571
|
-
|
|
1734
|
+
if (methods === null) return /* @__PURE__ */ jsx(Wrap, { f, as: "div", slot: "form", root: f.root, busy: true });
|
|
1735
|
+
const footer = props.links?.signIn && /* @__PURE__ */ jsxs(Note, { f, footer: true, children: [
|
|
1572
1736
|
f.t.haveAccount,
|
|
1573
1737
|
" ",
|
|
1574
|
-
/* @__PURE__ */ jsx(
|
|
1738
|
+
/* @__PURE__ */ jsx(A, { f, href: props.links.signIn, children: f.t.signIn })
|
|
1575
1739
|
] });
|
|
1576
1740
|
if (!passwordOn) {
|
|
1577
|
-
return /* @__PURE__ */ jsxs("div",
|
|
1578
|
-
general && /* @__PURE__ */ jsx(
|
|
1741
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "div", slot: "form", root: f.root, children: [
|
|
1742
|
+
general && /* @__PURE__ */ jsx(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1579
1743
|
/* @__PURE__ */ jsx(ProviderButtons, { f, providers, onPick: (id) => auth.signIn.social(id, { returnTo: props.returnTo }) }),
|
|
1580
1744
|
footer
|
|
1581
1745
|
] });
|
|
1582
1746
|
}
|
|
1583
|
-
return /* @__PURE__ */ jsxs("form",
|
|
1584
|
-
general && /* @__PURE__ */ jsx(
|
|
1747
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "form", slot: "form", root: f.root, onSubmit: submit, noValidate: true, children: [
|
|
1748
|
+
general && /* @__PURE__ */ jsx(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1585
1749
|
/* @__PURE__ */ jsx(ProviderButtons, { f, providers, onPick: (id) => auth.signIn.social(id, { returnTo: props.returnTo }) }),
|
|
1586
|
-
providers.length > 0 && /* @__PURE__ */ jsx(
|
|
1587
|
-
methods
|
|
1750
|
+
providers.length > 0 && /* @__PURE__ */ jsx(Or, { f, children: f.t.orWithEmail }),
|
|
1751
|
+
methods.organization?.ask && /* @__PURE__ */ jsx(Field, { f, name: "organization", type: "text", label: f.t.company, value: organization, autoComplete: "organization", required: methods.organization.required, onChange: setOrganization }),
|
|
1588
1752
|
/* @__PURE__ */ jsx(Field, { f, name: "name", type: "text", label: f.t.name, value: name, autoComplete: "name", onChange: setName }),
|
|
1589
1753
|
/* @__PURE__ */ jsx(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: "username", required: true, onChange: setEmail }),
|
|
1590
1754
|
/* @__PURE__ */ jsx(Field, { f, name: "password", type: "password", label: f.t.password, value: password, autoComplete: "new-password", required: true, onChange: setPassword, hint: f.passwordRule }),
|
|
1591
|
-
legal && legal.documents.length > 0 && /* @__PURE__ */ jsxs(
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
" ",
|
|
1596
|
-
legal.documents.map((d, i) => /* @__PURE__ */ jsxs("span", { children: [
|
|
1597
|
-
i > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1598
|
-
f.t.and,
|
|
1599
|
-
" "
|
|
1600
|
-
] }),
|
|
1601
|
-
/* @__PURE__ */ jsx("a", { className: f.cx("link"), href: d.url, target: "_blank", rel: "noopener", children: d.kind === "terms" ? f.t.termsOfService : f.t.privacyPolicy }),
|
|
1602
|
-
" "
|
|
1603
|
-
] }, d.kind))
|
|
1604
|
-
] })
|
|
1755
|
+
legal && legal.documents.length > 0 && /* @__PURE__ */ jsxs(Check, { f, name: "acceptLegal", checked: acceptLegal, required: true, onChange: setAcceptLegal, children: [
|
|
1756
|
+
f.t.iAccept,
|
|
1757
|
+
" ",
|
|
1758
|
+
/* @__PURE__ */ jsx(Documents, { f, documents: legal.documents })
|
|
1605
1759
|
] }),
|
|
1606
|
-
legal?.consentPurposes.map((p) => /* @__PURE__ */
|
|
1607
|
-
/* @__PURE__ */ jsx("input", { type: "checkbox", name: `consent_${p.key}`, checked: consents[p.key] === true, required: p.required, onChange: (e) => setConsents({ ...consents, [p.key]: e.target.checked }) }),
|
|
1608
|
-
/* @__PURE__ */ jsx("span", { children: p.label })
|
|
1609
|
-
] }, p.key)),
|
|
1760
|
+
legal?.consentPurposes.map((p) => /* @__PURE__ */ 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)),
|
|
1610
1761
|
challenge.node,
|
|
1611
|
-
/* @__PURE__ */ jsx(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.signUp }),
|
|
1762
|
+
/* @__PURE__ */ jsx(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.signUp }),
|
|
1612
1763
|
footer
|
|
1613
1764
|
] });
|
|
1614
1765
|
}
|
|
@@ -1630,17 +1781,17 @@ function ForgotPassword(props) {
|
|
|
1630
1781
|
};
|
|
1631
1782
|
const general = f.error && !f.error.field ? f.error : null;
|
|
1632
1783
|
if (sent) {
|
|
1633
|
-
return /* @__PURE__ */ jsxs("div",
|
|
1634
|
-
/* @__PURE__ */ jsx(
|
|
1635
|
-
props.links?.signIn && /* @__PURE__ */ jsx(
|
|
1784
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "div", slot: "form", root: f.root, children: [
|
|
1785
|
+
/* @__PURE__ */ jsx(Note, { f, children: f.t.linkSent }),
|
|
1786
|
+
props.links?.signIn && /* @__PURE__ */ jsx(A, { f, href: props.links.signIn, children: f.t.backToSignIn })
|
|
1636
1787
|
] });
|
|
1637
1788
|
}
|
|
1638
|
-
return /* @__PURE__ */ jsxs("form",
|
|
1639
|
-
general && /* @__PURE__ */ jsx(
|
|
1789
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "form", slot: "form", root: f.root, onSubmit: submit, noValidate: true, children: [
|
|
1790
|
+
general && /* @__PURE__ */ jsx(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1640
1791
|
/* @__PURE__ */ jsx(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: "username", required: true, onChange: setEmail }),
|
|
1641
1792
|
challenge.node,
|
|
1642
|
-
/* @__PURE__ */ jsx(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.sendLink }),
|
|
1643
|
-
props.links?.signIn && /* @__PURE__ */ jsx(
|
|
1793
|
+
/* @__PURE__ */ jsx(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.sendLink }),
|
|
1794
|
+
props.links?.signIn && /* @__PURE__ */ jsx(Note, { f, footer: true, children: /* @__PURE__ */ jsx(A, { f, href: props.links.signIn, children: f.t.backToSignIn }) })
|
|
1644
1795
|
] });
|
|
1645
1796
|
}
|
|
1646
1797
|
function ResetPassword(props) {
|
|
@@ -1664,23 +1815,23 @@ function ResetPassword(props) {
|
|
|
1664
1815
|
setChanged(true);
|
|
1665
1816
|
};
|
|
1666
1817
|
const general = f.error && !f.error.field ? f.error : null;
|
|
1667
|
-
const back = props.links?.signIn && /* @__PURE__ */ jsx(
|
|
1818
|
+
const back = props.links?.signIn && /* @__PURE__ */ jsx(A, { f, href: props.links.signIn, children: f.t.backToSignIn });
|
|
1668
1819
|
if (changed) {
|
|
1669
|
-
return /* @__PURE__ */ jsxs("div",
|
|
1670
|
-
/* @__PURE__ */ jsx(
|
|
1820
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "div", slot: "form", root: f.root, children: [
|
|
1821
|
+
/* @__PURE__ */ jsx(Note, { f, children: f.t.passwordChanged }),
|
|
1671
1822
|
back
|
|
1672
1823
|
] });
|
|
1673
1824
|
}
|
|
1674
1825
|
if (token === "") {
|
|
1675
|
-
return /* @__PURE__ */ jsxs("div",
|
|
1676
|
-
general && /* @__PURE__ */ jsx(
|
|
1677
|
-
props.links?.forgotPassword && /* @__PURE__ */ jsx(
|
|
1826
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "div", slot: "form", root: f.root, children: [
|
|
1827
|
+
general && /* @__PURE__ */ jsx(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1828
|
+
props.links?.forgotPassword && /* @__PURE__ */ jsx(A, { f, href: props.links.forgotPassword, children: f.t.forgotPassword })
|
|
1678
1829
|
] });
|
|
1679
1830
|
}
|
|
1680
|
-
return /* @__PURE__ */ jsxs("form",
|
|
1681
|
-
general && /* @__PURE__ */ jsx(
|
|
1831
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "form", slot: "form", root: f.root, onSubmit: submit, noValidate: true, children: [
|
|
1832
|
+
general && /* @__PURE__ */ jsx(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1682
1833
|
/* @__PURE__ */ jsx(Field, { f, name: "password", type: "password", label: f.t.newPassword, value: password, autoComplete: "new-password", required: true, onChange: setPassword, hint: f.passwordRule }),
|
|
1683
|
-
/* @__PURE__ */ jsx(f.Button, { type: "submit", disabled: f.busy || token === null, className: f.cx("button"), children: f.t.savePassword })
|
|
1834
|
+
/* @__PURE__ */ jsx(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy || token === null, className: f.cx("button"), children: f.t.savePassword })
|
|
1684
1835
|
] });
|
|
1685
1836
|
}
|
|
1686
1837
|
function VerifyEmail(props) {
|
|
@@ -1699,11 +1850,11 @@ function VerifyEmail(props) {
|
|
|
1699
1850
|
setState("failed");
|
|
1700
1851
|
});
|
|
1701
1852
|
});
|
|
1702
|
-
return /* @__PURE__ */ jsxs("div",
|
|
1703
|
-
state === "confirming" && /* @__PURE__ */ jsx(
|
|
1704
|
-
state === "confirmed" && /* @__PURE__ */ jsx(
|
|
1705
|
-
state === "failed" && f.error && /* @__PURE__ */ jsx(
|
|
1706
|
-
state !== "confirming" && props.links?.signIn && /* @__PURE__ */ jsx(
|
|
1853
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "div", slot: "form", root: f.root, busy: state === "confirming", children: [
|
|
1854
|
+
state === "confirming" && /* @__PURE__ */ jsx(Note, { f, children: f.t.confirming }),
|
|
1855
|
+
state === "confirmed" && /* @__PURE__ */ jsx(Note, { f, children: f.t.emailConfirmed }),
|
|
1856
|
+
state === "failed" && f.error && /* @__PURE__ */ jsx(Say, { f, tone: "danger", children: f.say(f.error) }),
|
|
1857
|
+
state !== "confirming" && props.links?.signIn && /* @__PURE__ */ jsx(A, { f, href: props.links.signIn, children: f.t.backToSignIn })
|
|
1707
1858
|
] });
|
|
1708
1859
|
}
|
|
1709
1860
|
function AcceptInvite(props) {
|
|
@@ -1736,37 +1887,67 @@ function AcceptInvite(props) {
|
|
|
1736
1887
|
if (r.error.code === "invalid_token") return setState("invalid");
|
|
1737
1888
|
return f.setError(r.error);
|
|
1738
1889
|
}
|
|
1890
|
+
props.onSaved?.({ kind: "invitation.accepted", email: invitation?.email ?? "", ...invitation?.organization ? { organization: invitation.organization } : {} });
|
|
1739
1891
|
if (r.status === "mfa_required") return setState("code");
|
|
1740
1892
|
f.done();
|
|
1741
1893
|
};
|
|
1742
1894
|
const general = f.error && !f.error.field ? f.error : null;
|
|
1743
|
-
const back = props.links?.signIn && /* @__PURE__ */ jsx(
|
|
1895
|
+
const back = props.links?.signIn && /* @__PURE__ */ jsx(A, { f, href: props.links.signIn, children: f.t.backToSignIn });
|
|
1744
1896
|
if (state === "opening") {
|
|
1745
|
-
return /* @__PURE__ */ jsx("div",
|
|
1897
|
+
return /* @__PURE__ */ jsx(Wrap, { f, as: "div", slot: "form", root: f.root, busy: true, children: /* @__PURE__ */ jsx(Note, { f, children: f.t.openingInvitation }) });
|
|
1746
1898
|
}
|
|
1747
1899
|
if (state === "invalid") {
|
|
1748
|
-
return /* @__PURE__ */ jsxs("div",
|
|
1749
|
-
/* @__PURE__ */ jsx(
|
|
1900
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "div", slot: "form", root: f.root, children: [
|
|
1901
|
+
/* @__PURE__ */ jsx(Say, { f, tone: "danger", children: general ? f.say(general) : f.t.invitationInvalid }),
|
|
1750
1902
|
back
|
|
1751
1903
|
] });
|
|
1752
1904
|
}
|
|
1753
1905
|
if (state === "code") return /* @__PURE__ */ jsx(SecondStepForm, { f, auth });
|
|
1754
1906
|
const workspace = invitation?.workspace ?? "";
|
|
1755
1907
|
const heading = invitation?.organization ? f.t.invitedToOrganization.replace("{organization}", invitation.organization).replace("{workspace}", workspace) : f.t.invitedTo.replace("{workspace}", workspace);
|
|
1756
|
-
return /* @__PURE__ */ jsxs("form",
|
|
1757
|
-
/* @__PURE__ */ jsx(
|
|
1758
|
-
/* @__PURE__ */ jsx(
|
|
1759
|
-
general && /* @__PURE__ */ jsx(
|
|
1908
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "form", slot: "form", root: f.root, onSubmit: submit, noValidate: true, children: [
|
|
1909
|
+
/* @__PURE__ */ jsx(Heading, { f, children: heading }),
|
|
1910
|
+
/* @__PURE__ */ jsx(Note, { f, children: f.t.invitedAs.replace("{email}", invitation?.email ?? "") }),
|
|
1911
|
+
general && /* @__PURE__ */ jsx(Say, { f, tone: "danger", children: f.say(general) }),
|
|
1760
1912
|
/* @__PURE__ */ jsx("input", { type: "email", name: "username", autoComplete: "username", value: invitation?.email ?? "", readOnly: true, hidden: true }),
|
|
1761
1913
|
/* @__PURE__ */ jsx(Field, { f, name: "password", type: "password", label: f.t.choosePassword, value: password, autoComplete: "new-password", required: true, onChange: setPassword, hint: f.passwordRule }),
|
|
1762
|
-
/* @__PURE__ */ jsx(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.acceptInvite })
|
|
1914
|
+
/* @__PURE__ */ jsx(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.acceptInvite })
|
|
1915
|
+
] });
|
|
1916
|
+
}
|
|
1917
|
+
function PendingTerms(props) {
|
|
1918
|
+
const auth = useAuth();
|
|
1919
|
+
const f = useForm(props);
|
|
1920
|
+
const [owed, setOwed] = useState(null);
|
|
1921
|
+
useEffect(() => {
|
|
1922
|
+
void auth.account.legal().then((r) => setOwed(r.ok ? r.pending : []));
|
|
1923
|
+
}, []);
|
|
1924
|
+
if (!owed || owed.length === 0) return null;
|
|
1925
|
+
const accept = async () => {
|
|
1926
|
+
f.setBusy(true);
|
|
1927
|
+
f.setError(null);
|
|
1928
|
+
const r = await auth.account.acceptLegal({ kinds: owed.map((d) => d.kind) });
|
|
1929
|
+
f.setBusy(false);
|
|
1930
|
+
if (!r.ok) return f.setError(r.error);
|
|
1931
|
+
setOwed([]);
|
|
1932
|
+
props.onSuccess?.();
|
|
1933
|
+
};
|
|
1934
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "div", slot: "form", root: f.root, children: [
|
|
1935
|
+
/* @__PURE__ */ jsx(Heading, { f, children: f.t.termsChanged }),
|
|
1936
|
+
/* @__PURE__ */ jsxs(Note, { f, children: [
|
|
1937
|
+
f.t.termsChangedHelp,
|
|
1938
|
+
" ",
|
|
1939
|
+
/* @__PURE__ */ jsx(Documents, { f, documents: owed })
|
|
1940
|
+
] }),
|
|
1941
|
+
f.error && /* @__PURE__ */ jsx(Say, { f, tone: "danger", children: f.say(f.error) }),
|
|
1942
|
+
/* @__PURE__ */ jsx(f.Button, { type: "button", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), onClick: () => void accept(), children: f.t.acceptTerms })
|
|
1763
1943
|
] });
|
|
1764
1944
|
}
|
|
1945
|
+
var ACCOUNT_SECTIONS = ["profile", "email", "password", "linked", "secondStep", "phone", "passkeys", "agents", "sessions"];
|
|
1765
1946
|
function useSection(props) {
|
|
1766
1947
|
const f = useForm({ ...props, unstyled: true });
|
|
1767
1948
|
const [done, setDone] = useState(null);
|
|
1768
|
-
const run = async (action) => {
|
|
1769
|
-
f.setBusy(
|
|
1949
|
+
const run = async (action, key = SUBMIT) => {
|
|
1950
|
+
f.setBusy(key);
|
|
1770
1951
|
f.setError(null);
|
|
1771
1952
|
setDone(null);
|
|
1772
1953
|
const r = await action();
|
|
@@ -1780,37 +1961,64 @@ function useSection(props) {
|
|
|
1780
1961
|
function Account(props) {
|
|
1781
1962
|
const auth = useAuth();
|
|
1782
1963
|
const { accountUrl } = useSession();
|
|
1783
|
-
const
|
|
1784
|
-
const cx = (slot) => props.classNames?.[slot] ?? `cauthy-${slot}`;
|
|
1964
|
+
const f = useForm(props);
|
|
1785
1965
|
const [account, setAccount] = useState(null);
|
|
1786
|
-
const [sessions, setSessions] = useState([]);
|
|
1787
1966
|
useEffect(() => {
|
|
1788
1967
|
void auth.account.get().then(setAccount);
|
|
1789
|
-
void auth.account.sessions().then(setSessions);
|
|
1790
1968
|
}, []);
|
|
1791
|
-
if (account === null) return /* @__PURE__ */ jsx("div",
|
|
1969
|
+
if (account === null) return /* @__PURE__ */ jsx(Wrap, { f, as: "div", slot: "account", root: f.root, busy: true });
|
|
1792
1970
|
const when = props.formatDate ?? ((iso) => new Date(iso).toLocaleString());
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1971
|
+
const mfa = (mfaEnabled) => setAccount({ ...account, mfaEnabled });
|
|
1972
|
+
const part = (section) => {
|
|
1973
|
+
switch (section) {
|
|
1974
|
+
case "profile":
|
|
1975
|
+
return /* @__PURE__ */ jsx(ProfilePart, { props, account, onSaved: setAccount });
|
|
1976
|
+
case "email":
|
|
1977
|
+
return /* @__PURE__ */ jsx(EmailPart, { props, account });
|
|
1978
|
+
case "password":
|
|
1979
|
+
return account.hasPassword ? /* @__PURE__ */ jsx(PasswordPart, { props }) : null;
|
|
1980
|
+
case "linked":
|
|
1981
|
+
return /* @__PURE__ */ jsx(LinkedPart, { props });
|
|
1982
|
+
case "secondStep":
|
|
1983
|
+
return /* @__PURE__ */ jsx(SecondStepPart, { props, account, onChanged: mfa });
|
|
1984
|
+
case "phone":
|
|
1985
|
+
return /* @__PURE__ */ jsx(PhonePart, { props, account, onChanged: mfa });
|
|
1986
|
+
case "passkeys":
|
|
1987
|
+
return /* @__PURE__ */ jsx(PasskeysPart, { props, account, accountUrl: accountUrl(), when });
|
|
1988
|
+
case "agents":
|
|
1989
|
+
return /* @__PURE__ */ jsx(AgentsPart, { props, when });
|
|
1990
|
+
case "sessions":
|
|
1991
|
+
return /* @__PURE__ */ jsx(SessionsPart, { props, when });
|
|
1992
|
+
}
|
|
1993
|
+
};
|
|
1994
|
+
return /* @__PURE__ */ jsx(Wrap, { f, as: "div", slot: "account", root: f.root, children: (props.sections ?? ACCOUNT_SECTIONS).map((section) => /* @__PURE__ */ jsx(Fragment, { children: part(section) }, section)) });
|
|
1995
|
+
}
|
|
1996
|
+
function AccountProfile(props) {
|
|
1997
|
+
return /* @__PURE__ */ jsx(Account, { ...props, sections: ["profile"] });
|
|
1998
|
+
}
|
|
1999
|
+
function AccountEmail(props) {
|
|
2000
|
+
return /* @__PURE__ */ jsx(Account, { ...props, sections: ["email"] });
|
|
2001
|
+
}
|
|
2002
|
+
function AccountPassword(props) {
|
|
2003
|
+
return /* @__PURE__ */ jsx(Account, { ...props, sections: ["password"] });
|
|
2004
|
+
}
|
|
2005
|
+
function AccountLinked(props) {
|
|
2006
|
+
return /* @__PURE__ */ jsx(Account, { ...props, sections: ["linked"] });
|
|
2007
|
+
}
|
|
2008
|
+
function AccountSecondStep(props) {
|
|
2009
|
+
return /* @__PURE__ */ jsx(Account, { ...props, sections: ["secondStep"] });
|
|
2010
|
+
}
|
|
2011
|
+
function AccountPhone(props) {
|
|
2012
|
+
return /* @__PURE__ */ jsx(Account, { ...props, sections: ["phone"] });
|
|
2013
|
+
}
|
|
2014
|
+
function AccountPasskeys(props) {
|
|
2015
|
+
return /* @__PURE__ */ jsx(Account, { ...props, sections: ["passkeys"] });
|
|
2016
|
+
}
|
|
2017
|
+
function AccountAgents(props) {
|
|
2018
|
+
return /* @__PURE__ */ jsx(Account, { ...props, sections: ["agents"] });
|
|
2019
|
+
}
|
|
2020
|
+
function AccountSessions(props) {
|
|
2021
|
+
return /* @__PURE__ */ jsx(Account, { ...props, sections: ["sessions"] });
|
|
1814
2022
|
}
|
|
1815
2023
|
var OWNER = "owner";
|
|
1816
2024
|
function memberActions(seat, m) {
|
|
@@ -1822,8 +2030,9 @@ function memberActions(seat, m) {
|
|
|
1822
2030
|
inviteAgain: seat.can.manageMembers && m.invited
|
|
1823
2031
|
};
|
|
1824
2032
|
}
|
|
1825
|
-
function rolesToGive(seat, roles) {
|
|
1826
|
-
|
|
2033
|
+
function rolesToGive(seat, roles, only) {
|
|
2034
|
+
const mine = seat.role === OWNER ? roles : roles.filter((c) => c.role !== OWNER);
|
|
2035
|
+
return only ? mine.filter((c) => only(c.role, c)) : mine;
|
|
1827
2036
|
}
|
|
1828
2037
|
function OrganizationMembers(props) {
|
|
1829
2038
|
const auth = useAuth();
|
|
@@ -1840,6 +2049,8 @@ function OrganizationMembers(props) {
|
|
|
1840
2049
|
const [gone, setGone] = useState(null);
|
|
1841
2050
|
const id = props.organizationId;
|
|
1842
2051
|
const when = props.formatDate ?? ((iso) => new Date(iso).toLocaleDateString());
|
|
2052
|
+
const hidden = (action) => props.hide?.includes(action) === true;
|
|
2053
|
+
const saved = (event) => props.onSaved?.(event);
|
|
1843
2054
|
const load = async () => {
|
|
1844
2055
|
const [list, people, choices] = await Promise.all([auth.organizations.list(), auth.organizations.members(id), auth.organizations.roles(id)]);
|
|
1845
2056
|
const mine = list.find((o) => o.id === id) ?? null;
|
|
@@ -1847,135 +2058,173 @@ function OrganizationMembers(props) {
|
|
|
1847
2058
|
if (mine) setName(mine.name);
|
|
1848
2059
|
setMembers(people);
|
|
1849
2060
|
setRoles(choices ?? []);
|
|
1850
|
-
const offered = mine ? rolesToGive(mine, choices ?? []) : [];
|
|
2061
|
+
const offered = mine ? rolesToGive(mine, choices ?? [], props.roles) : [];
|
|
1851
2062
|
if (offered.length > 0 && !offered.some((c) => c.role === role)) setRole(offered[0].role);
|
|
1852
2063
|
};
|
|
1853
2064
|
useEffect(() => {
|
|
1854
2065
|
void load();
|
|
1855
2066
|
}, [id]);
|
|
1856
|
-
if (gone !== null) return /* @__PURE__ */ jsx("div",
|
|
1857
|
-
if (seat === void 0) return /* @__PURE__ */ jsx("div",
|
|
1858
|
-
if (seat === null) return /* @__PURE__ */ jsx("div",
|
|
2067
|
+
if (gone !== null) return /* @__PURE__ */ jsx(Wrap, { f, as: "div", slot: "account", root, children: /* @__PURE__ */ jsx(Say, { f, tone: "success", children: gone }) });
|
|
2068
|
+
if (seat === void 0) return /* @__PURE__ */ jsx(Wrap, { f, as: "div", slot: "account", root, busy: true });
|
|
2069
|
+
if (seat === null) return /* @__PURE__ */ jsx(Wrap, { f, as: "div", slot: "account", root, children: /* @__PURE__ */ jsx(Note, { f, children: f.t.organizationMissing }) });
|
|
1859
2070
|
const manage = seat.can.manageMembers;
|
|
1860
|
-
const giveable = rolesToGive(seat, roles);
|
|
1861
|
-
const
|
|
2071
|
+
const giveable = rolesToGive(seat, roles, props.roles);
|
|
2072
|
+
const roleName = (c) => props.roleLabel?.(c) || c.name || c.role;
|
|
2073
|
+
const label = (r) => {
|
|
2074
|
+
const c = roles.find((x) => x.role === r);
|
|
2075
|
+
return c ? roleName(c) : r;
|
|
2076
|
+
};
|
|
1862
2077
|
const add = async (e) => {
|
|
1863
2078
|
e.preventDefault();
|
|
1864
|
-
|
|
2079
|
+
if (!f.check(checkEmail(email))) return;
|
|
2080
|
+
const r = await run(() => auth.organizations.add(id, { email, role, locale: props.locale }), "add");
|
|
1865
2081
|
if (!r.ok) return;
|
|
1866
2082
|
setEmail("");
|
|
1867
2083
|
setDone(f.t.memberAdded.replace("{email}", r.member.email));
|
|
2084
|
+
saved({ kind: "member.added", organizationId: id, userId: r.member.userId, email: r.member.email, role: r.member.role || role });
|
|
1868
2085
|
await load();
|
|
1869
2086
|
};
|
|
1870
2087
|
const change = async (m, next) => {
|
|
1871
|
-
const r = await run(() => auth.organizations.setRole(id, m.userId, next));
|
|
1872
|
-
if (r.ok)
|
|
2088
|
+
const r = await run(() => auth.organizations.setRole(id, m.userId, next), `role:${m.userId}`);
|
|
2089
|
+
if (!r.ok) return;
|
|
2090
|
+
saved({ kind: "member.role_changed", organizationId: id, userId: m.userId, role: next, previousRole: m.role });
|
|
2091
|
+
await load();
|
|
1873
2092
|
};
|
|
1874
2093
|
const remove = async (m) => {
|
|
1875
2094
|
setAsking(null);
|
|
1876
|
-
const r = await run(() => auth.organizations.remove(id, m.userId));
|
|
2095
|
+
const r = await run(() => auth.organizations.remove(id, m.userId), `remove:${m.userId}`);
|
|
1877
2096
|
if (!r.ok) return;
|
|
2097
|
+
saved({ kind: m.you ? "member.left" : "member.removed", organizationId: id, userId: m.userId });
|
|
1878
2098
|
if (m.you) setSeat(null);
|
|
1879
2099
|
else await load();
|
|
1880
2100
|
};
|
|
1881
2101
|
const inviteAgain = async (m) => {
|
|
1882
|
-
const r = await run(() => auth.organizations.inviteAgain(id, m.userId, { locale: props.locale }));
|
|
1883
|
-
if (r.ok)
|
|
2102
|
+
const r = await run(() => auth.organizations.inviteAgain(id, m.userId, { locale: props.locale }), `invite:${m.userId}`);
|
|
2103
|
+
if (!r.ok) return;
|
|
2104
|
+
setDone(f.t.memberInvitationSent);
|
|
2105
|
+
saved({ kind: "member.invited_again", organizationId: id, userId: m.userId });
|
|
1884
2106
|
};
|
|
1885
2107
|
const rename = async (e) => {
|
|
1886
2108
|
e.preventDefault();
|
|
1887
|
-
const r = await run(() => auth.organizations.rename(id, name));
|
|
2109
|
+
const r = await run(() => auth.organizations.rename(id, name), "rename");
|
|
1888
2110
|
if (!r.ok) return;
|
|
1889
2111
|
setSeat(r.organization);
|
|
1890
2112
|
setName(r.organization.name);
|
|
1891
2113
|
setDone(f.t.organizationRenamed.replace("{name}", r.organization.name));
|
|
2114
|
+
saved({ kind: "organization.renamed", organizationId: id, name: r.organization.name });
|
|
1892
2115
|
};
|
|
1893
2116
|
const close = async (how) => {
|
|
1894
2117
|
setAsking(null);
|
|
1895
|
-
const r = await run(() => how === "archive" ? auth.organizations.archive(id) : auth.organizations.delete(id));
|
|
1896
|
-
if (r.ok)
|
|
2118
|
+
const r = await run(() => how === "archive" ? auth.organizations.archive(id) : auth.organizations.delete(id), how);
|
|
2119
|
+
if (!r.ok) return;
|
|
2120
|
+
setGone((how === "archive" ? f.t.organizationArchived : f.t.organizationDeleted).replace("{org}", seat.name));
|
|
2121
|
+
saved({ kind: how === "archive" ? "organization.archived" : "organization.deleted", organizationId: id });
|
|
2122
|
+
};
|
|
2123
|
+
const ask = (key, title, question, yes) => {
|
|
2124
|
+
const { Confirm } = f.C;
|
|
2125
|
+
if (!Confirm) return setAsking(key);
|
|
2126
|
+
void Confirm({ title, body: question, confirmLabel: title, cancelLabel: f.t.cancel, danger: true }).then((ok) => {
|
|
2127
|
+
if (ok) yes();
|
|
2128
|
+
});
|
|
1897
2129
|
};
|
|
1898
2130
|
const confirming = (text2, label2, yes) => /* @__PURE__ */ jsxs("span", { role: "group", "aria-label": label2, children: [
|
|
1899
2131
|
/* @__PURE__ */ jsx("span", { children: text2 }),
|
|
1900
2132
|
" ",
|
|
1901
|
-
/* @__PURE__ */ jsx(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: yes, children: f.t.yes }),
|
|
1902
|
-
/* @__PURE__ */ jsx(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => setAsking(null), children: f.t.cancel })
|
|
2133
|
+
/* @__PURE__ */ jsx(f.Button, { type: "button", variant: "danger", disabled: f.busy, className: f.cx("providerButton"), onClick: yes, children: f.t.yes }),
|
|
2134
|
+
/* @__PURE__ */ jsx(f.Button, { type: "button", variant: "secondary", disabled: f.busy, className: f.cx("providerButton"), onClick: () => setAsking(null), children: f.t.cancel })
|
|
1903
2135
|
] });
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
2136
|
+
const leaveQuestion = f.t.memberLeaveConfirm.replace("{org}", seat.name);
|
|
2137
|
+
const archiveQuestion = f.t.organizationArchiveConfirm.replace("{org}", seat.name);
|
|
2138
|
+
const deleteQuestion = f.t.organizationDeleteConfirm.replace("{org}", seat.name);
|
|
2139
|
+
const archiving = seat.can.archive && !hidden("archive");
|
|
2140
|
+
const deleting = seat.can.delete && !hidden("delete");
|
|
2141
|
+
const renaming = seat.can.update && !hidden("rename");
|
|
2142
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "div", slot: "account", root, children: [
|
|
2143
|
+
/* @__PURE__ */ jsxs(Wrap, { f, as: "section", slot: "section", section: "members", children: [
|
|
2144
|
+
/* @__PURE__ */ jsxs(Heading, { f, children: [
|
|
1907
2145
|
f.t.members,
|
|
1908
2146
|
" \xB7 ",
|
|
1909
2147
|
seat.name
|
|
1910
2148
|
] }),
|
|
1911
|
-
problem && /* @__PURE__ */ jsx(
|
|
1912
|
-
members === null ? /* @__PURE__ */ jsxs(
|
|
1913
|
-
/* @__PURE__ */ jsx(
|
|
1914
|
-
auth.session && (asking === auth.session.user.id ? confirming(
|
|
1915
|
-
f.
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
2149
|
+
problem && /* @__PURE__ */ jsx(Say, { f, tone: "danger", children: f.say(problem) }),
|
|
2150
|
+
members === null ? /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
2151
|
+
/* @__PURE__ */ jsx(Note, { f, children: f.t.membersHidden }),
|
|
2152
|
+
auth.session && !hidden("leave") && (asking === auth.session.user.id ? confirming(leaveQuestion, f.t.memberLeave, () => void remove({ userId: auth.session.user.id, you: true })) : /* @__PURE__ */ jsx(
|
|
2153
|
+
f.Button,
|
|
2154
|
+
{
|
|
2155
|
+
type: "button",
|
|
2156
|
+
variant: "danger",
|
|
2157
|
+
loading: f.loading(`remove:${auth.session.user.id}`),
|
|
2158
|
+
disabled: f.busy,
|
|
2159
|
+
className: f.cx("providerButton"),
|
|
2160
|
+
onClick: () => ask(auth.session.user.id, f.t.memberLeave, leaveQuestion, () => void remove({ userId: auth.session.user.id, you: true })),
|
|
2161
|
+
children: f.t.memberLeave
|
|
2162
|
+
}
|
|
2163
|
+
))
|
|
1919
2164
|
] }) : /* @__PURE__ */ jsx("ul", { className: f.cx("sessions"), children: members.map((m) => {
|
|
1920
2165
|
const who = m.name || m.email;
|
|
1921
2166
|
const may = memberActions(seat, m);
|
|
2167
|
+
const removable = may.remove && !(m.you && hidden("leave"));
|
|
2168
|
+
const question = m.you ? leaveQuestion : f.t.memberRemoveConfirm.replace("{who}", who);
|
|
2169
|
+
const action = m.you ? f.t.memberLeave : f.t.memberRemove;
|
|
2170
|
+
const choices = giveable.some((c) => c.role === m.role) ? giveable : [...roles.filter((c) => c.role === m.role), ...giveable];
|
|
1922
2171
|
return /* @__PURE__ */ jsxs("li", { className: f.cx("session"), children: [
|
|
1923
2172
|
/* @__PURE__ */ jsxs("span", { children: [
|
|
1924
2173
|
who,
|
|
1925
2174
|
m.name ? ` \xB7 ${m.email}` : "",
|
|
1926
|
-
m.you
|
|
1927
|
-
|
|
1928
|
-
|
|
2175
|
+
m.you && /* @__PURE__ */ jsx(Tag, { f, plain: ` (${f.t.memberYou})`, children: f.t.memberYou }),
|
|
2176
|
+
f.C.Badge ? /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
2177
|
+
m.invited && /* @__PURE__ */ jsx(Tag, { f, tone: "warning", plain: "", children: f.t.memberInvited }),
|
|
2178
|
+
m.manager && /* @__PURE__ */ jsx(Tag, { f, tone: "success", plain: "", children: f.t.memberManager })
|
|
2179
|
+
] }) : `${m.invited ? ` \xB7 ${f.t.memberInvited}` : ""}${m.manager ? ` \xB7 ${f.t.memberManager}` : ""}`,
|
|
1929
2180
|
" \xB7 ",
|
|
1930
2181
|
when(m.since)
|
|
1931
2182
|
] }),
|
|
1932
2183
|
" ",
|
|
1933
2184
|
may.changeRole && giveable.length > 0 ? /* @__PURE__ */ jsx(
|
|
1934
|
-
|
|
2185
|
+
Pick,
|
|
1935
2186
|
{
|
|
1936
|
-
|
|
1937
|
-
|
|
2187
|
+
f,
|
|
2188
|
+
name: `role_${m.userId}`,
|
|
2189
|
+
label: `${f.t.memberRole}: ${who}`,
|
|
1938
2190
|
value: m.role,
|
|
1939
2191
|
disabled: f.busy,
|
|
1940
|
-
|
|
1941
|
-
|
|
2192
|
+
options: choices.map((c) => ({ value: c.role, label: roleName(c) })),
|
|
2193
|
+
onChange: (next) => void change(m, next)
|
|
1942
2194
|
}
|
|
1943
|
-
) : /* @__PURE__ */ jsx("span", { children: label(m.role) }),
|
|
2195
|
+
) : f.C.Badge ? /* @__PURE__ */ jsx(f.C.Badge, { tone: "neutral", children: label(m.role) }) : /* @__PURE__ */ jsx("span", { children: label(m.role) }),
|
|
1944
2196
|
" ",
|
|
1945
|
-
asking === m.userId ? confirming(
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
() => void remove(m)
|
|
1949
|
-
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1950
|
-
may.inviteAgain && /* @__PURE__ */ jsx(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void inviteAgain(m), children: f.t.memberInviteAgain }),
|
|
1951
|
-
may.remove && /* @__PURE__ */ jsx(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => setAsking(m.userId), children: m.you ? f.t.memberLeave : f.t.memberRemove })
|
|
2197
|
+
asking === m.userId ? confirming(question, action, () => void remove(m)) : /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
2198
|
+
may.inviteAgain && /* @__PURE__ */ 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 }),
|
|
2199
|
+
removable && /* @__PURE__ */ 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 })
|
|
1952
2200
|
] })
|
|
1953
2201
|
] }, m.userId);
|
|
1954
2202
|
}) }),
|
|
1955
|
-
done && /* @__PURE__ */ jsx(
|
|
2203
|
+
done && /* @__PURE__ */ jsx(Say, { f, tone: "success", children: done })
|
|
1956
2204
|
] }),
|
|
1957
|
-
manage && giveable.length > 0 && /* @__PURE__ */ jsxs("form",
|
|
1958
|
-
/* @__PURE__ */ jsx(
|
|
2205
|
+
manage && giveable.length > 0 && /* @__PURE__ */ jsxs(Wrap, { f, as: "form", slot: "section", section: "add-member", onSubmit: add, noValidate: true, children: [
|
|
2206
|
+
/* @__PURE__ */ jsx(Heading, { f, children: f.t.memberAdd }),
|
|
1959
2207
|
/* @__PURE__ */ jsx(Field, { f, name: "email", type: "email", label: f.t.email, value: email, autoComplete: "off", required: true, onChange: setEmail }),
|
|
1960
|
-
/* @__PURE__ */
|
|
1961
|
-
|
|
1962
|
-
/* @__PURE__ */ jsx("select", { name: "role", className: f.cx("input"), value: role, onChange: (e) => setRole(e.target.value), children: giveable.map((c) => /* @__PURE__ */ jsx("option", { value: c.role, children: c.name || c.role }, c.role)) })
|
|
1963
|
-
] }),
|
|
1964
|
-
/* @__PURE__ */ jsx(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.memberAdd })
|
|
2208
|
+
/* @__PURE__ */ jsx(AddRole, { f, value: role, options: giveable.map((c) => ({ value: c.role, label: roleName(c) })), onChange: setRole }),
|
|
2209
|
+
/* @__PURE__ */ jsx(f.Button, { type: "submit", variant: "primary", loading: f.loading("add"), disabled: f.busy, className: f.cx("button"), children: f.t.memberAdd })
|
|
1965
2210
|
] }),
|
|
1966
|
-
(
|
|
1967
|
-
/* @__PURE__ */ jsx(
|
|
1968
|
-
|
|
2211
|
+
(renaming || archiving || deleting) && /* @__PURE__ */ jsxs(Wrap, { f, as: "section", slot: "section", section: "organization", children: [
|
|
2212
|
+
/* @__PURE__ */ jsx(Heading, { f, children: f.t.organization }),
|
|
2213
|
+
renaming && /* @__PURE__ */ jsxs(Wrap, { f, as: "form", section: "rename", onSubmit: rename, noValidate: true, children: [
|
|
1969
2214
|
/* @__PURE__ */ jsx(Field, { f, name: "name", type: "text", label: f.t.name, value: name, autoComplete: "organization", required: true, onChange: setName }),
|
|
1970
|
-
/* @__PURE__ */ jsx(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.organizationRename })
|
|
2215
|
+
/* @__PURE__ */ jsx(f.Button, { type: "submit", variant: "primary", loading: f.loading("rename"), disabled: f.busy, className: f.cx("button"), children: f.t.organizationRename })
|
|
1971
2216
|
] }),
|
|
1972
|
-
asking === "archive" ? confirming(
|
|
1973
|
-
|
|
1974
|
-
|
|
2217
|
+
asking === "archive" ? confirming(archiveQuestion, f.t.organizationArchive, () => void close("archive")) : asking === "delete" ? confirming(deleteQuestion, f.t.organizationDelete, () => void close("delete")) : /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
2218
|
+
archiving && /* @__PURE__ */ 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 }),
|
|
2219
|
+
deleting && /* @__PURE__ */ 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 })
|
|
1975
2220
|
] })
|
|
1976
2221
|
] })
|
|
1977
2222
|
] });
|
|
1978
2223
|
}
|
|
2224
|
+
function AddRole({ f, value, options, onChange }) {
|
|
2225
|
+
const id = useId();
|
|
2226
|
+
return /* @__PURE__ */ jsx(Labelled, { f, id, label: f.t.memberRole, children: /* @__PURE__ */ jsx(Pick, { f, id, name: "role", value, options, onChange }) });
|
|
2227
|
+
}
|
|
1979
2228
|
function PasskeysPart({ props, account, accountUrl, when }) {
|
|
1980
2229
|
const auth = useAuth();
|
|
1981
2230
|
const { f, done, setDone, run, general } = useSection(props);
|
|
@@ -1992,14 +2241,15 @@ function PasskeysPart({ props, account, accountUrl, when }) {
|
|
|
1992
2241
|
}, []);
|
|
1993
2242
|
if (here === null) return null;
|
|
1994
2243
|
if (!here) {
|
|
1995
|
-
return /* @__PURE__ */ jsxs("section",
|
|
1996
|
-
/* @__PURE__ */ jsx(
|
|
1997
|
-
/* @__PURE__ */ jsx(
|
|
2244
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "section", slot: "section", section: "passkeys", children: [
|
|
2245
|
+
/* @__PURE__ */ jsx(Heading, { f, children: f.t.passkeys }),
|
|
2246
|
+
/* @__PURE__ */ jsx(A, { f, href: accountUrl, children: f.t.managePasskeys })
|
|
1998
2247
|
] });
|
|
1999
2248
|
}
|
|
2000
2249
|
const add = async (e, kind = "device") => {
|
|
2001
2250
|
e?.preventDefault();
|
|
2002
|
-
|
|
2251
|
+
if (account.hasPassword && !f.check(checkPassword(password))) return;
|
|
2252
|
+
const r = await run(() => auth.account.addPasskey({ name, password, kind }), kind === "security_key" ? "security_key" : SUBMIT);
|
|
2003
2253
|
if (!r.ok) {
|
|
2004
2254
|
if (r.error.code === "cancelled") f.setError(null);
|
|
2005
2255
|
return;
|
|
@@ -2008,28 +2258,31 @@ function PasskeysPart({ props, account, accountUrl, when }) {
|
|
|
2008
2258
|
setName("");
|
|
2009
2259
|
setPassword("");
|
|
2010
2260
|
setDone(f.t.passkeyAdded);
|
|
2261
|
+
props.onSaved?.({ kind: "passkey.added", id: r.passkey.id });
|
|
2011
2262
|
};
|
|
2012
2263
|
const remove = async (id) => {
|
|
2013
|
-
const r = await run(() => auth.account.removePasskey(id));
|
|
2014
|
-
if (r.ok)
|
|
2264
|
+
const r = await run(() => auth.account.removePasskey(id), `remove:${id}`);
|
|
2265
|
+
if (!r.ok) return;
|
|
2266
|
+
setList(list.filter((p) => p.id !== id));
|
|
2267
|
+
props.onSaved?.({ kind: "passkey.removed", id });
|
|
2015
2268
|
};
|
|
2016
|
-
return /* @__PURE__ */ jsxs("form",
|
|
2017
|
-
/* @__PURE__ */ jsx(
|
|
2018
|
-
/* @__PURE__ */ jsx(
|
|
2019
|
-
general && /* @__PURE__ */ jsx(
|
|
2020
|
-
list.length === 0 ? /* @__PURE__ */ jsx(
|
|
2269
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "form", slot: "section", section: "passkeys", onSubmit: add, noValidate: true, children: [
|
|
2270
|
+
/* @__PURE__ */ jsx(Heading, { f, children: f.t.passkeys }),
|
|
2271
|
+
/* @__PURE__ */ jsx(Note, { f, children: f.t.passkeysHelp }),
|
|
2272
|
+
general && /* @__PURE__ */ jsx(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2273
|
+
list.length === 0 ? /* @__PURE__ */ jsx(Note, { f, children: f.t.noPasskeys }) : /* @__PURE__ */ jsx("ul", { className: f.cx("sessions"), children: list.map((p) => /* @__PURE__ */ jsxs("li", { className: f.cx("session"), children: [
|
|
2021
2274
|
p.name || f.t.passkeyUnnamed,
|
|
2022
|
-
p.kind !== "unknown"
|
|
2275
|
+
p.kind !== "unknown" && /* @__PURE__ */ jsx(Tag, { f, plain: ` \xB7 ${f.t.passkeyKinds[p.kind]}`, children: f.t.passkeyKinds[p.kind] }),
|
|
2023
2276
|
" \xB7 ",
|
|
2024
2277
|
when(p.createdAt),
|
|
2025
2278
|
" ",
|
|
2026
|
-
/* @__PURE__ */ jsx(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void remove(p.id), children: f.t.removePasskey })
|
|
2279
|
+
/* @__PURE__ */ 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 })
|
|
2027
2280
|
] }, p.id)) }),
|
|
2028
2281
|
/* @__PURE__ */ jsx(Field, { f, name: "name", type: "text", label: f.t.passkeyName, value: name, autoComplete: "off", onChange: setName }),
|
|
2029
2282
|
account.hasPassword && /* @__PURE__ */ jsx(Field, { f, name: "password", type: "password", label: f.t.currentPassword, value: password, autoComplete: "current-password", required: true, onChange: setPassword }),
|
|
2030
|
-
/* @__PURE__ */ jsx(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.addPasskeyDevice }),
|
|
2031
|
-
/* @__PURE__ */ jsx(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void add(null, "security_key"), children: f.t.addSecurityKey }),
|
|
2032
|
-
done && /* @__PURE__ */ jsx(
|
|
2283
|
+
/* @__PURE__ */ jsx(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.addPasskeyDevice }),
|
|
2284
|
+
/* @__PURE__ */ 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 }),
|
|
2285
|
+
done && /* @__PURE__ */ jsx(Say, { f, tone: "success", children: done })
|
|
2033
2286
|
] });
|
|
2034
2287
|
}
|
|
2035
2288
|
function ProfilePart({ props, account, onSaved }) {
|
|
@@ -2042,14 +2295,15 @@ function ProfilePart({ props, account, onSaved }) {
|
|
|
2042
2295
|
if (!r.ok) return;
|
|
2043
2296
|
onSaved(r.account);
|
|
2044
2297
|
setDone(f.t.saved);
|
|
2298
|
+
props.onSaved?.({ kind: "profile.saved", name: r.account.name });
|
|
2045
2299
|
};
|
|
2046
|
-
return /* @__PURE__ */ jsxs("form",
|
|
2047
|
-
/* @__PURE__ */ jsx(
|
|
2048
|
-
/* @__PURE__ */ jsx(
|
|
2049
|
-
general && /* @__PURE__ */ jsx(
|
|
2300
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "form", slot: "section", section: "profile", onSubmit: submit, noValidate: true, children: [
|
|
2301
|
+
/* @__PURE__ */ jsx(Heading, { f, children: f.t.profile }),
|
|
2302
|
+
/* @__PURE__ */ jsx(Note, { f, children: account.email }),
|
|
2303
|
+
general && /* @__PURE__ */ jsx(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2050
2304
|
/* @__PURE__ */ jsx(Field, { f, name: "name", type: "text", label: f.t.name, value: name, autoComplete: "name", onChange: setName }),
|
|
2051
|
-
/* @__PURE__ */ jsx(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.save }),
|
|
2052
|
-
done && /* @__PURE__ */ jsx(
|
|
2305
|
+
/* @__PURE__ */ jsx(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.save }),
|
|
2306
|
+
done && /* @__PURE__ */ jsx(Say, { f, tone: "success", children: done })
|
|
2053
2307
|
] });
|
|
2054
2308
|
}
|
|
2055
2309
|
function EmailPart({ props, account }) {
|
|
@@ -2059,19 +2313,21 @@ function EmailPart({ props, account }) {
|
|
|
2059
2313
|
const [password, setPassword] = useState("");
|
|
2060
2314
|
const submit = async (e) => {
|
|
2061
2315
|
e.preventDefault();
|
|
2316
|
+
if (!f.check(checkEmail(email), account.hasPassword && checkPassword(password))) return;
|
|
2062
2317
|
const r = await run(() => auth.account.changeEmail({ email, password }));
|
|
2063
2318
|
if (!r.ok) return;
|
|
2064
2319
|
setPassword("");
|
|
2065
2320
|
setDone(f.t.emailSent.replace("{email}", r.email));
|
|
2321
|
+
props.onSaved?.({ kind: "email.change_requested", email: r.email });
|
|
2066
2322
|
};
|
|
2067
|
-
return /* @__PURE__ */ jsxs("form",
|
|
2068
|
-
/* @__PURE__ */ jsx(
|
|
2069
|
-
/* @__PURE__ */ jsx(
|
|
2070
|
-
general && /* @__PURE__ */ jsx(
|
|
2323
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "form", slot: "section", section: "email", onSubmit: submit, noValidate: true, children: [
|
|
2324
|
+
/* @__PURE__ */ jsx(Heading, { f, children: f.t.emailAddress }),
|
|
2325
|
+
/* @__PURE__ */ jsx(Note, { f, children: account.email }),
|
|
2326
|
+
general && /* @__PURE__ */ jsx(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2071
2327
|
/* @__PURE__ */ jsx(Field, { f, name: "email", type: "email", label: f.t.newEmail, value: email, autoComplete: "email", required: true, onChange: setEmail }),
|
|
2072
2328
|
account.hasPassword && /* @__PURE__ */ jsx(Field, { f, name: "password", type: "password", label: f.t.currentPassword, value: password, autoComplete: "current-password", required: true, onChange: setPassword }),
|
|
2073
|
-
/* @__PURE__ */ jsx(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.changeEmail }),
|
|
2074
|
-
done && /* @__PURE__ */ jsx(
|
|
2329
|
+
/* @__PURE__ */ jsx(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.changeEmail }),
|
|
2330
|
+
done && /* @__PURE__ */ jsx(Say, { f, tone: "success", children: done })
|
|
2075
2331
|
] });
|
|
2076
2332
|
}
|
|
2077
2333
|
function LinkedPart({ props }) {
|
|
@@ -2084,27 +2340,32 @@ function LinkedPart({ props }) {
|
|
|
2084
2340
|
void auth.account.identities().then(setLinked);
|
|
2085
2341
|
void auth.methods().then((m) => setOffered(m.providers));
|
|
2086
2342
|
const back = typeof window === "undefined" ? null : new URLSearchParams(window.location.search);
|
|
2087
|
-
|
|
2088
|
-
|
|
2343
|
+
const provider = back?.get("linked");
|
|
2344
|
+
if (provider) {
|
|
2345
|
+
setCame(provider);
|
|
2346
|
+
props.onSaved?.({ kind: "identity.linked", provider });
|
|
2347
|
+
} else if (back?.get("auth_error")) f.setError({ code: back.get("auth_error"), message: "That account could not be linked. Try again." });
|
|
2089
2348
|
}, []);
|
|
2090
2349
|
if (linked === null) return null;
|
|
2091
2350
|
const name = (id) => offered.find((p) => p.id === id)?.name ?? id;
|
|
2092
2351
|
const unlink = async (provider) => {
|
|
2093
|
-
const r = await run(() => auth.account.unlink(provider));
|
|
2094
|
-
if (r.ok)
|
|
2352
|
+
const r = await run(() => auth.account.unlink(provider), `unlink:${provider}`);
|
|
2353
|
+
if (!r.ok) return;
|
|
2354
|
+
setLinked(linked.filter((x) => x.provider !== provider));
|
|
2355
|
+
props.onSaved?.({ kind: "identity.unlinked", provider });
|
|
2095
2356
|
};
|
|
2096
2357
|
const here = typeof window === "undefined" ? void 0 : window.location.pathname;
|
|
2097
|
-
return /* @__PURE__ */ jsxs("section",
|
|
2098
|
-
/* @__PURE__ */ jsx(
|
|
2099
|
-
came && /* @__PURE__ */ jsx(
|
|
2100
|
-
general && /* @__PURE__ */ jsx(
|
|
2101
|
-
linked.length === 0 ? /* @__PURE__ */ jsx(
|
|
2358
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "section", slot: "section", section: "linked", children: [
|
|
2359
|
+
/* @__PURE__ */ jsx(Heading, { f, children: f.t.linkedAccounts }),
|
|
2360
|
+
came && /* @__PURE__ */ jsx(Say, { f, tone: "success", children: f.t.linked }),
|
|
2361
|
+
general && /* @__PURE__ */ jsx(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2362
|
+
linked.length === 0 ? /* @__PURE__ */ jsx(Note, { f, children: f.t.noLinkedAccounts }) : /* @__PURE__ */ jsx("ul", { className: f.cx("sessions"), children: linked.map((x) => /* @__PURE__ */ jsxs("li", { className: f.cx("session"), children: [
|
|
2102
2363
|
name(x.provider),
|
|
2103
2364
|
x.email ? ` \xB7 ${x.email}` : "",
|
|
2104
2365
|
" ",
|
|
2105
|
-
/* @__PURE__ */ jsx(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void unlink(x.provider), children: f.t.unlink })
|
|
2366
|
+
/* @__PURE__ */ 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 })
|
|
2106
2367
|
] }, x.provider)) }),
|
|
2107
|
-
offered.filter((p) => !linked.some((x) => x.provider === p.id)).map((p) => /* @__PURE__ */ jsxs(f.Button, { type: "button", className: f.cx("providerButton"), onClick: () => auth.account.link(p.id, { returnTo: here }), children: [
|
|
2368
|
+
offered.filter((p) => !linked.some((x) => x.provider === p.id)).map((p) => /* @__PURE__ */ jsxs(f.Button, { type: "button", variant: "secondary", className: f.cx("providerButton"), onClick: () => auth.account.link(p.id, { returnTo: here }), children: [
|
|
2108
2369
|
f.t.linkWith,
|
|
2109
2370
|
" ",
|
|
2110
2371
|
p.name
|
|
@@ -2119,19 +2380,21 @@ function PasswordPart({ props }) {
|
|
|
2119
2380
|
usePasswordPolicy(f, useMethods(auth));
|
|
2120
2381
|
const submit = async (e) => {
|
|
2121
2382
|
e.preventDefault();
|
|
2383
|
+
if (!f.check(checkPassword(password), newPasswordProblem(newPassword, f.policy, "newPassword"))) return;
|
|
2122
2384
|
const r = await run(() => auth.account.changePassword({ password, newPassword }));
|
|
2123
2385
|
if (!r.ok) return;
|
|
2124
2386
|
setPassword("");
|
|
2125
2387
|
setNewPassword("");
|
|
2126
2388
|
setDone(f.t.passwordChangedHere);
|
|
2389
|
+
props.onSaved?.({ kind: "password.changed" });
|
|
2127
2390
|
};
|
|
2128
|
-
return /* @__PURE__ */ jsxs("form",
|
|
2129
|
-
/* @__PURE__ */ jsx(
|
|
2130
|
-
general && /* @__PURE__ */ jsx(
|
|
2391
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "form", slot: "section", section: "password", onSubmit: submit, noValidate: true, children: [
|
|
2392
|
+
/* @__PURE__ */ jsx(Heading, { f, children: f.t.changePassword }),
|
|
2393
|
+
general && /* @__PURE__ */ jsx(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2131
2394
|
/* @__PURE__ */ jsx(Field, { f, name: "password", type: "password", label: f.t.currentPassword, value: password, autoComplete: "current-password", required: true, onChange: setPassword }),
|
|
2132
2395
|
/* @__PURE__ */ jsx(Field, { f, name: "newPassword", type: "password", label: f.t.newPassword, value: newPassword, autoComplete: "new-password", required: true, onChange: setNewPassword, hint: f.passwordRule }),
|
|
2133
|
-
/* @__PURE__ */ jsx(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.changePassword }),
|
|
2134
|
-
done && /* @__PURE__ */ jsx(
|
|
2396
|
+
/* @__PURE__ */ jsx(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.changePassword }),
|
|
2397
|
+
done && /* @__PURE__ */ jsx(Say, { f, tone: "success", children: done })
|
|
2135
2398
|
] });
|
|
2136
2399
|
}
|
|
2137
2400
|
function SecondStepPart({ props, account, onChanged }) {
|
|
@@ -2155,6 +2418,7 @@ function SecondStepPart({ props, account, onChanged }) {
|
|
|
2155
2418
|
setPassword("");
|
|
2156
2419
|
setCodes(r.recoveryCodes);
|
|
2157
2420
|
onChanged(true);
|
|
2421
|
+
props.onSaved?.({ kind: "mfa.enabled" });
|
|
2158
2422
|
};
|
|
2159
2423
|
const turnOff = async (e) => {
|
|
2160
2424
|
e.preventDefault();
|
|
@@ -2163,35 +2427,38 @@ function SecondStepPart({ props, account, onChanged }) {
|
|
|
2163
2427
|
setPassword("");
|
|
2164
2428
|
setCodes(null);
|
|
2165
2429
|
onChanged(false);
|
|
2430
|
+
props.onSaved?.({ kind: "mfa.disabled" });
|
|
2166
2431
|
};
|
|
2167
2432
|
const renew = async () => {
|
|
2168
|
-
const r = await run(() => auth.account.mfa.recoveryCodes({ password }));
|
|
2169
|
-
if (r.ok)
|
|
2433
|
+
const r = await run(() => auth.account.mfa.recoveryCodes({ password }), "codes");
|
|
2434
|
+
if (!r.ok) return;
|
|
2435
|
+
setCodes(r.recoveryCodes);
|
|
2436
|
+
props.onSaved?.({ kind: "recovery_codes.regenerated" });
|
|
2170
2437
|
};
|
|
2171
2438
|
const passwordField = account.hasPassword && /* @__PURE__ */ jsx(Field, { f, name: "password", type: "password", label: f.t.currentPassword, value: password, autoComplete: "current-password", required: true, onChange: setPassword });
|
|
2172
|
-
const shown = codes && /* @__PURE__ */ jsxs(
|
|
2173
|
-
/* @__PURE__ */ jsx(
|
|
2439
|
+
const shown = codes && /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
2440
|
+
/* @__PURE__ */ jsx(Note, { f, children: f.t.keepCodes }),
|
|
2174
2441
|
/* @__PURE__ */ jsx("ul", { className: f.cx("codes"), children: codes.map((c) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("code", { children: c }) }, c)) })
|
|
2175
2442
|
] });
|
|
2176
2443
|
if (setup) {
|
|
2177
|
-
return /* @__PURE__ */ jsxs("form",
|
|
2178
|
-
/* @__PURE__ */ jsx(
|
|
2179
|
-
/* @__PURE__ */ jsx(
|
|
2444
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "form", slot: "section", section: "secondStep", onSubmit: confirm, noValidate: true, children: [
|
|
2445
|
+
/* @__PURE__ */ jsx(Heading, { f, children: f.t.secondStep }),
|
|
2446
|
+
/* @__PURE__ */ jsx(Note, { f, children: f.t.addToApp }),
|
|
2180
2447
|
/* @__PURE__ */ jsx("code", { className: f.cx("secret"), children: setup.secret }),
|
|
2181
|
-
/* @__PURE__ */ jsx(
|
|
2182
|
-
general && /* @__PURE__ */ jsx(
|
|
2448
|
+
/* @__PURE__ */ jsx(A, { f, href: setup.otpauthUri, children: f.t.openInApp }),
|
|
2449
|
+
general && /* @__PURE__ */ jsx(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2183
2450
|
/* @__PURE__ */ jsx(Field, { f, name: "code", type: "text", label: f.t.code, value: code, autoComplete: "one-time-code", required: true, onChange: setCode }),
|
|
2184
|
-
/* @__PURE__ */ jsx(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.verify })
|
|
2451
|
+
/* @__PURE__ */ jsx(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.verify })
|
|
2185
2452
|
] });
|
|
2186
2453
|
}
|
|
2187
|
-
return /* @__PURE__ */ jsxs("form",
|
|
2188
|
-
/* @__PURE__ */ jsx(
|
|
2189
|
-
/* @__PURE__ */ jsx(
|
|
2454
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "form", slot: "section", section: "secondStep", onSubmit: account.mfaEnabled ? turnOff : start, noValidate: true, children: [
|
|
2455
|
+
/* @__PURE__ */ jsx(Heading, { f, children: f.t.secondStep }),
|
|
2456
|
+
/* @__PURE__ */ jsx(Note, { f, children: account.mfaEnabled ? f.t.secondStepOn : f.t.secondStepOff }),
|
|
2190
2457
|
shown,
|
|
2191
|
-
general && /* @__PURE__ */ jsx(
|
|
2458
|
+
general && /* @__PURE__ */ jsx(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2192
2459
|
passwordField,
|
|
2193
|
-
/* @__PURE__ */ jsx(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: account.mfaEnabled ? f.t.turnOff : f.t.turnOn }),
|
|
2194
|
-
account.mfaEnabled && /* @__PURE__ */ jsx(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void renew(), children: f.t.newRecoveryCodes })
|
|
2460
|
+
/* @__PURE__ */ 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 }),
|
|
2461
|
+
account.mfaEnabled && /* @__PURE__ */ 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 })
|
|
2195
2462
|
] });
|
|
2196
2463
|
}
|
|
2197
2464
|
function PhonePart({ props, account, onChanged }) {
|
|
@@ -2226,6 +2493,7 @@ function PhonePart({ props, account, onChanged }) {
|
|
|
2226
2493
|
setPassword("");
|
|
2227
2494
|
if (r.recoveryCodes.length > 0) setCodes(r.recoveryCodes);
|
|
2228
2495
|
onChanged(true);
|
|
2496
|
+
props.onSaved?.({ kind: "phone.added", channel });
|
|
2229
2497
|
await load();
|
|
2230
2498
|
};
|
|
2231
2499
|
const remove = async (e) => {
|
|
@@ -2236,33 +2504,35 @@ function PhonePart({ props, account, onChanged }) {
|
|
|
2236
2504
|
await load();
|
|
2237
2505
|
const left = await auth.account.mfa.factors();
|
|
2238
2506
|
onChanged(Boolean(left?.totp));
|
|
2507
|
+
props.onSaved?.({ kind: "phone.removed" });
|
|
2239
2508
|
};
|
|
2240
2509
|
const passwordField = account.hasPassword && /* @__PURE__ */ jsx(Field, { f, name: "password", type: "password", label: f.t.currentPassword, value: password, autoComplete: "current-password", required: true, onChange: setPassword });
|
|
2241
2510
|
if (sentTo) {
|
|
2242
|
-
return /* @__PURE__ */ jsxs("form",
|
|
2243
|
-
/* @__PURE__ */ jsx(
|
|
2244
|
-
/* @__PURE__ */ jsx(
|
|
2245
|
-
general && /* @__PURE__ */ jsx(
|
|
2511
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "form", slot: "section", section: "phone", onSubmit: confirm, noValidate: true, children: [
|
|
2512
|
+
/* @__PURE__ */ jsx(Heading, { f, children: f.t.phone }),
|
|
2513
|
+
/* @__PURE__ */ jsx(Note, { f, children: f.t.codeSent.replace("{to}", sentTo) }),
|
|
2514
|
+
general && /* @__PURE__ */ jsx(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2246
2515
|
/* @__PURE__ */ jsx(Field, { f, name: "code", type: "text", label: f.t.code, value: code, autoComplete: "one-time-code", required: true, onChange: setCode }),
|
|
2247
|
-
/* @__PURE__ */ jsx(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: f.t.verify })
|
|
2516
|
+
/* @__PURE__ */ jsx(f.Button, { type: "submit", variant: "primary", loading: f.loading(), disabled: f.busy, className: f.cx("button"), children: f.t.verify })
|
|
2248
2517
|
] });
|
|
2249
2518
|
}
|
|
2250
|
-
return /* @__PURE__ */ jsxs("form",
|
|
2251
|
-
/* @__PURE__ */ jsx(
|
|
2252
|
-
/* @__PURE__ */ jsx(
|
|
2253
|
-
codes && /* @__PURE__ */ jsxs(
|
|
2254
|
-
/* @__PURE__ */ jsx(
|
|
2519
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "form", slot: "section", section: "phone", onSubmit: ways.phone ? remove : add, noValidate: true, children: [
|
|
2520
|
+
/* @__PURE__ */ jsx(Heading, { f, children: f.t.phone }),
|
|
2521
|
+
/* @__PURE__ */ jsx(Note, { f, children: ways.phone ? f.t.phoneOn.replace("{to}", ways.phone.number) : `${f.t.phoneOff} ${f.t.phoneHelp}` }),
|
|
2522
|
+
codes && /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
2523
|
+
/* @__PURE__ */ jsx(Note, { f, children: f.t.keepCodes }),
|
|
2255
2524
|
/* @__PURE__ */ jsx("ul", { className: f.cx("codes"), children: codes.map((c) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("code", { children: c }) }, c)) })
|
|
2256
2525
|
] }),
|
|
2257
|
-
general && /* @__PURE__ */ jsx(
|
|
2526
|
+
general && /* @__PURE__ */ jsx(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2258
2527
|
!ways.phone && /* @__PURE__ */ jsx(Field, { f, name: "phone", type: "tel", label: f.t.phone, value: number, autoComplete: "tel", required: true, onChange: setNumber }),
|
|
2259
|
-
!ways.phone && ways.phoneChannels.length > 1 && /* @__PURE__ */ jsx(
|
|
2528
|
+
!ways.phone && ways.phoneChannels.length > 1 && f.C.Select && /* @__PURE__ */ jsx(ChannelPick, { f, value: channel, channels: ways.phoneChannels, onChange: setChannel }),
|
|
2529
|
+
!ways.phone && ways.phoneChannels.length > 1 && !f.C.Select && /* @__PURE__ */ jsx("div", { className: f.cx("field"), role: "radiogroup", children: ways.phoneChannels.map((c) => /* @__PURE__ */ jsxs("label", { className: f.cx("label"), children: [
|
|
2260
2530
|
/* @__PURE__ */ jsx("input", { type: "radio", name: "channel", value: c, checked: channel === c, onChange: () => setChannel(c) }),
|
|
2261
2531
|
" ",
|
|
2262
2532
|
c === "whatsapp" ? f.t.byWhatsapp : f.t.bySms
|
|
2263
2533
|
] }, c)) }),
|
|
2264
2534
|
passwordField,
|
|
2265
|
-
/* @__PURE__ */ jsx(f.Button, { type: "submit", disabled: f.busy, className: f.cx("button"), children: ways.phone ? f.t.removePhone : f.t.addPhone })
|
|
2535
|
+
/* @__PURE__ */ 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 })
|
|
2266
2536
|
] });
|
|
2267
2537
|
}
|
|
2268
2538
|
function AgentsPart({ props, when }) {
|
|
@@ -2274,13 +2544,15 @@ function AgentsPart({ props, when }) {
|
|
|
2274
2544
|
}, []);
|
|
2275
2545
|
if (list.length === 0) return null;
|
|
2276
2546
|
const disconnect = async (id) => {
|
|
2277
|
-
const r = await run(() => auth.account.disconnectAgent(id));
|
|
2278
|
-
if (r.ok)
|
|
2547
|
+
const r = await run(() => auth.account.disconnectAgent(id), `disconnect:${id}`);
|
|
2548
|
+
if (!r.ok) return;
|
|
2549
|
+
setList(list.filter((a) => a.id !== id));
|
|
2550
|
+
props.onSaved?.({ kind: "agent.disconnected", id });
|
|
2279
2551
|
};
|
|
2280
|
-
return /* @__PURE__ */ jsxs("section",
|
|
2281
|
-
/* @__PURE__ */ jsx(
|
|
2282
|
-
/* @__PURE__ */ jsx(
|
|
2283
|
-
general && /* @__PURE__ */ jsx(
|
|
2552
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "section", slot: "section", section: "agents", children: [
|
|
2553
|
+
/* @__PURE__ */ jsx(Heading, { f, children: f.t.agents }),
|
|
2554
|
+
/* @__PURE__ */ jsx(Note, { f, children: f.t.agentsHelp }),
|
|
2555
|
+
general && /* @__PURE__ */ jsx(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2284
2556
|
/* @__PURE__ */ jsx("ul", { className: f.cx("sessions"), children: list.map((a) => /* @__PURE__ */ jsxs("li", { className: f.cx("session"), children: [
|
|
2285
2557
|
a.name || f.t.anAgent,
|
|
2286
2558
|
a.redirectHost ? ` (${a.redirectHost})` : "",
|
|
@@ -2290,37 +2562,71 @@ function AgentsPart({ props, when }) {
|
|
|
2290
2562
|
" \xB7 ",
|
|
2291
2563
|
when(a.lastUsedAt),
|
|
2292
2564
|
" ",
|
|
2293
|
-
/* @__PURE__ */ jsx(f.Button, { type: "button", disabled: f.busy, className: f.cx("providerButton"), onClick: () => void disconnect(a.id), children: f.t.disconnect })
|
|
2565
|
+
/* @__PURE__ */ 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 })
|
|
2294
2566
|
] }, a.id)) })
|
|
2295
2567
|
] });
|
|
2296
2568
|
}
|
|
2297
|
-
function
|
|
2569
|
+
function SessionsPart({ props, when }) {
|
|
2298
2570
|
const auth = useAuth();
|
|
2299
2571
|
const { f, run, general } = useSection(props);
|
|
2572
|
+
const [sessions, setSessions] = useState([]);
|
|
2573
|
+
useEffect(() => {
|
|
2574
|
+
void auth.account.sessions().then(setSessions);
|
|
2575
|
+
}, []);
|
|
2300
2576
|
const end = async () => {
|
|
2301
2577
|
const r = await run(() => auth.account.signOutEverywhere());
|
|
2302
2578
|
if (!r.ok) return;
|
|
2579
|
+
props.onSaved?.({ kind: "sessions.ended" });
|
|
2303
2580
|
if (props.onSignedOut) props.onSignedOut();
|
|
2304
2581
|
else window.location.assign("/");
|
|
2305
2582
|
};
|
|
2306
|
-
return /* @__PURE__ */ jsxs(
|
|
2307
|
-
|
|
2308
|
-
/* @__PURE__ */ jsx(
|
|
2583
|
+
return /* @__PURE__ */ jsxs(Wrap, { f, as: "section", slot: "section", section: "sessions", children: [
|
|
2584
|
+
/* @__PURE__ */ jsx(Heading, { f, children: f.t.sessions }),
|
|
2585
|
+
/* @__PURE__ */ jsx("ul", { className: f.cx("sessions"), children: sessions.map((s, i) => /* @__PURE__ */ jsxs("li", { className: f.cx("session"), children: [
|
|
2586
|
+
s.device || f.t.unknownDevice,
|
|
2587
|
+
" \xB7 ",
|
|
2588
|
+
s.ip,
|
|
2589
|
+
" \xB7 ",
|
|
2590
|
+
when(s.createdAt)
|
|
2591
|
+
] }, i)) }),
|
|
2592
|
+
general && /* @__PURE__ */ jsx(Say, { f, tone: "danger", children: f.say(general) }),
|
|
2593
|
+
/* @__PURE__ */ jsx(f.Button, { type: "button", variant: "danger", loading: f.loading(), disabled: f.busy, className: f.cx("button"), onClick: () => void end(), children: f.t.signOutEverywhere })
|
|
2309
2594
|
] });
|
|
2310
2595
|
}
|
|
2596
|
+
function ChannelPick({ f, value, channels, onChange }) {
|
|
2597
|
+
const id = useId();
|
|
2598
|
+
return /* @__PURE__ */ jsx(Labelled, { f, id, label: f.t.channel, children: /* @__PURE__ */ jsx(
|
|
2599
|
+
Pick,
|
|
2600
|
+
{
|
|
2601
|
+
f,
|
|
2602
|
+
id,
|
|
2603
|
+
name: "channel",
|
|
2604
|
+
value,
|
|
2605
|
+
options: channels.map((c) => ({ value: c, label: c === "whatsapp" ? f.t.byWhatsapp : f.t.bySms })),
|
|
2606
|
+
onChange: (c) => onChange(c)
|
|
2607
|
+
}
|
|
2608
|
+
) });
|
|
2609
|
+
}
|
|
2311
2610
|
|
|
2312
2611
|
// src/react.tsx
|
|
2313
2612
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
2314
2613
|
var Ctx = createContext(null);
|
|
2614
|
+
var LocaleCtx = createContext(() => void 0);
|
|
2315
2615
|
var AHEAD_MS = 6e4;
|
|
2316
|
-
function CauthyProvider({ children, basePath = "/api/auth", initialSession }) {
|
|
2616
|
+
function CauthyProvider({ children, basePath = "/api/auth", initialSession, locale }) {
|
|
2317
2617
|
const base = withoutTrailingSlashes(basePath);
|
|
2618
|
+
const said = useRef2(locale);
|
|
2619
|
+
said.current = locale;
|
|
2620
|
+
const readLocale = useCallback2(() => {
|
|
2621
|
+
const l = said.current;
|
|
2622
|
+
return typeof l === "function" ? l() : l;
|
|
2623
|
+
}, []);
|
|
2318
2624
|
const [session, setSession] = useState2(initialSession ?? null);
|
|
2319
2625
|
const [status, setStatus] = useState2(
|
|
2320
2626
|
initialSession === void 0 ? "loading" : initialSession === null ? "unauthenticated" : "authenticated"
|
|
2321
2627
|
);
|
|
2322
2628
|
const asking = useRef2(null);
|
|
2323
|
-
const refresh =
|
|
2629
|
+
const refresh = useCallback2(() => {
|
|
2324
2630
|
asking.current ??= (async () => {
|
|
2325
2631
|
try {
|
|
2326
2632
|
const res = await fetch(`${base}/session`, { credentials: "same-origin", headers: { accept: "application/json" } });
|
|
@@ -2378,7 +2684,7 @@ function CauthyProvider({ children, basePath = "/api/auth", initialSession }) {
|
|
|
2378
2684
|
}),
|
|
2379
2685
|
[session, status, refresh, base]
|
|
2380
2686
|
);
|
|
2381
|
-
return /* @__PURE__ */ jsx2(Ctx.Provider, { value, children });
|
|
2687
|
+
return /* @__PURE__ */ jsx2(Ctx.Provider, { value, children: /* @__PURE__ */ jsx2(LocaleCtx.Provider, { value: readLocale, children }) });
|
|
2382
2688
|
}
|
|
2383
2689
|
function useSession() {
|
|
2384
2690
|
const ctx = useContext(Ctx);
|
|
@@ -2387,8 +2693,9 @@ function useSession() {
|
|
|
2387
2693
|
}
|
|
2388
2694
|
function useAuth() {
|
|
2389
2695
|
const { session, status, refresh, basePath } = useSession();
|
|
2696
|
+
const locale = useContext(LocaleCtx);
|
|
2390
2697
|
return useMemo(() => {
|
|
2391
|
-
const client = createAuthClient({ basePath });
|
|
2698
|
+
const client = createAuthClient({ basePath, locale });
|
|
2392
2699
|
const then = async (running) => {
|
|
2393
2700
|
const r = await running;
|
|
2394
2701
|
await refresh();
|
|
@@ -2425,15 +2732,25 @@ function useAuth() {
|
|
|
2425
2732
|
status,
|
|
2426
2733
|
refresh
|
|
2427
2734
|
};
|
|
2428
|
-
}, [basePath, refresh, session, status]);
|
|
2735
|
+
}, [basePath, locale, refresh, session, status]);
|
|
2429
2736
|
}
|
|
2430
2737
|
export {
|
|
2431
2738
|
AcceptInvite,
|
|
2432
2739
|
Account,
|
|
2740
|
+
AccountAgents,
|
|
2741
|
+
AccountEmail,
|
|
2742
|
+
AccountLinked,
|
|
2743
|
+
AccountPasskeys,
|
|
2744
|
+
AccountPassword,
|
|
2745
|
+
AccountPhone,
|
|
2746
|
+
AccountProfile,
|
|
2747
|
+
AccountSecondStep,
|
|
2748
|
+
AccountSessions,
|
|
2433
2749
|
CauthyProvider,
|
|
2434
2750
|
ForgotPassword,
|
|
2435
2751
|
GoogleOneTap,
|
|
2436
2752
|
OrganizationMembers,
|
|
2753
|
+
PendingTerms,
|
|
2437
2754
|
ResetPassword,
|
|
2438
2755
|
SignIn,
|
|
2439
2756
|
SignUp,
|