@ai-matrx/vault 0.1.11 → 0.1.12
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/CHANGELOG.md +19 -1
- package/dist/index.cjs +210 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +58 -4
- package/dist/index.d.ts +58 -4
- package/dist/index.js +273 -113
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -324,9 +324,20 @@ var FingerprintGlyph = glyph(/* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
|
324
324
|
var SendGlyph = glyph(/* @__PURE__ */ jsx2("path", { d: "M14.5 21.7a.5.5 0 0 0 .9 0L22 3a.5.5 0 0 0-.6-.6L2.3 9.1a.5.5 0 0 0 0 .9l7.9 3.2a2 2 0 0 1 1.1 1.1zM21.9 2.1 10.9 13.1" }), [1, 1]);
|
|
325
325
|
|
|
326
326
|
// src/auth/identity.ts
|
|
327
|
+
var CONFIRM_RETURN_KEY = "matrx-vault:confirming-as";
|
|
328
|
+
var RETURN_WINDOW_MS = 15 * 6e4;
|
|
327
329
|
var SAME_PERSON = "That signed in a different account. Use the account this vault belongs to.";
|
|
328
330
|
function createSupabaseIdentity(auth, options = {}) {
|
|
329
331
|
let me = null;
|
|
332
|
+
const now = options.now ?? Date.now;
|
|
333
|
+
const store = () => {
|
|
334
|
+
if (options.store) return options.store;
|
|
335
|
+
try {
|
|
336
|
+
return globalThis.sessionStorage ?? null;
|
|
337
|
+
} catch {
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
340
|
+
};
|
|
330
341
|
const who = async () => {
|
|
331
342
|
const { data } = await auth.getUser();
|
|
332
343
|
if (!data.user) throw new Error("You are signed out. Sign in again.");
|
|
@@ -343,10 +354,35 @@ function createSupabaseIdentity(auth, options = {}) {
|
|
|
343
354
|
return { email: u.email ?? null, providers: [...names].filter((p) => p !== "email" && p !== "phone"), hasPassword: names.has("email") };
|
|
344
355
|
},
|
|
345
356
|
async withProvider(provider) {
|
|
346
|
-
await who();
|
|
357
|
+
const u = await who();
|
|
358
|
+
store()?.setItem(CONFIRM_RETURN_KEY, JSON.stringify({ id: u.id, email: u.email ?? null, at: now() }));
|
|
347
359
|
const redirectTo = options.redirectTo?.() ?? globalThis.location?.href;
|
|
348
360
|
const { error } = await auth.signInWithOAuth({ provider, ...redirectTo ? { options: { redirectTo } } : {} });
|
|
349
|
-
if (error)
|
|
361
|
+
if (error) {
|
|
362
|
+
store()?.removeItem(CONFIRM_RETURN_KEY);
|
|
363
|
+
throw new Error(error.message);
|
|
364
|
+
}
|
|
365
|
+
},
|
|
366
|
+
async checkReturn() {
|
|
367
|
+
const s = store();
|
|
368
|
+
const raw = s?.getItem(CONFIRM_RETURN_KEY) ?? null;
|
|
369
|
+
if (!s || raw === null) return null;
|
|
370
|
+
s.removeItem(CONFIRM_RETURN_KEY);
|
|
371
|
+
let expected;
|
|
372
|
+
try {
|
|
373
|
+
expected = JSON.parse(raw);
|
|
374
|
+
} catch {
|
|
375
|
+
return null;
|
|
376
|
+
}
|
|
377
|
+
if (typeof expected.id !== "string" || typeof expected.at !== "number" || now() - expected.at > RETURN_WINDOW_MS) return null;
|
|
378
|
+
const { data } = await auth.getUser();
|
|
379
|
+
if (!data.user || data.user.id === expected.id) return null;
|
|
380
|
+
const email = typeof expected.email === "string" && expected.email ? expected.email : null;
|
|
381
|
+
const message2 = `That signed in a different account, so it was signed out here.${email ? ` Sign in again as ${email}.` : " Sign in again."}`;
|
|
382
|
+
me = null;
|
|
383
|
+
if (options.onDifferentPerson) await options.onDifferentPerson(message2);
|
|
384
|
+
else await auth.signOut?.({ scope: "local" });
|
|
385
|
+
return message2;
|
|
350
386
|
},
|
|
351
387
|
async withPassword(password) {
|
|
352
388
|
const u = await who();
|
|
@@ -392,6 +428,18 @@ var providerLabel = (p) => PROVIDER_LABEL[p] ?? p.charAt(0).toUpperCase() + p.sl
|
|
|
392
428
|
function IdentityGate({ identity, children }) {
|
|
393
429
|
const [asking, setAsking] = useState2(false);
|
|
394
430
|
const waiters = useRef2([]);
|
|
431
|
+
const [returnProblem, setReturnProblem] = useState2(null);
|
|
432
|
+
useEffect2(() => {
|
|
433
|
+
if (!identity?.checkReturn) return;
|
|
434
|
+
let live = true;
|
|
435
|
+
identity.checkReturn().then(
|
|
436
|
+
(problem) => live && problem && setReturnProblem(problem),
|
|
437
|
+
(e) => live && setReturnProblem(e instanceof Error ? e.message : "The account that came back could not be checked.")
|
|
438
|
+
);
|
|
439
|
+
return () => {
|
|
440
|
+
live = false;
|
|
441
|
+
};
|
|
442
|
+
}, [identity]);
|
|
395
443
|
const confirmed = async (run) => {
|
|
396
444
|
try {
|
|
397
445
|
return await run();
|
|
@@ -412,7 +460,14 @@ function IdentityGate({ identity, children }) {
|
|
|
412
460
|
};
|
|
413
461
|
return /* @__PURE__ */ jsxs3(Ctx2.Provider, { value: confirmed, children: [
|
|
414
462
|
children,
|
|
415
|
-
identity ? /* @__PURE__ */ jsx3(ConfirmIdentityDialog, { open: asking, identity, onDone: () => settle(true), onCancel: () => settle(false) }) : null
|
|
463
|
+
identity ? /* @__PURE__ */ jsx3(ConfirmIdentityDialog, { open: asking, identity, onDone: () => settle(true), onCancel: () => settle(false) }) : null,
|
|
464
|
+
/* @__PURE__ */ jsx3(Dialog, { open: returnProblem !== null, onOpenChange: (o) => o ? void 0 : setReturnProblem(null), children: /* @__PURE__ */ jsxs3(DialogContent, { size: "sm", children: [
|
|
465
|
+
/* @__PURE__ */ jsxs3(DialogHeader, { children: [
|
|
466
|
+
/* @__PURE__ */ jsx3(DialogTitle, { children: "Different account" }),
|
|
467
|
+
/* @__PURE__ */ jsx3(DialogDescription, { children: returnProblem })
|
|
468
|
+
] }),
|
|
469
|
+
/* @__PURE__ */ jsx3("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx3(Button, { variant: "primary", onClick: () => setReturnProblem(null), children: "OK" }) })
|
|
470
|
+
] }) })
|
|
416
471
|
] });
|
|
417
472
|
}
|
|
418
473
|
var wasCancelled = (e) => e instanceof Error && e.message === CANCELLED;
|
|
@@ -476,7 +531,7 @@ function ConfirmIdentityDialog({ open, identity, onDone, onCancel }) {
|
|
|
476
531
|
e.preventDefault();
|
|
477
532
|
if (password) void attempt(() => identity.withPassword(password));
|
|
478
533
|
}, children: [
|
|
479
|
-
/* @__PURE__ */ jsx3(Field, { className: "min-w-0 flex-1", type: "password", autoComplete: "current-password", placeholder: "Your password", "aria-label": "Your password", value: password, onChange: (e) => setPassword(e.target.value) }),
|
|
534
|
+
/* @__PURE__ */ jsx3(Field, { className: "min-w-0 flex-1", type: "password", autoComplete: "current-password", placeholder: "Your password", "aria-label": "Your password", value: password, onChange: (e) => setPassword(e.target.value), autoFocus: true }),
|
|
480
535
|
/* @__PURE__ */ jsx3(Button, { variant: "outline", type: "submit", disabled: busy || !password, children: "Confirm" })
|
|
481
536
|
] }) : null,
|
|
482
537
|
account10?.email ? codeSent ? /* @__PURE__ */ jsxs3("form", { className: "flex gap-2", onSubmit: (e) => {
|
|
@@ -604,6 +659,12 @@ function Panel({ title, open = true, onClose, children, footer, size = "lg" }) {
|
|
|
604
659
|
footer ? /* @__PURE__ */ jsx4(DialogFooter, { children: footer }) : null
|
|
605
660
|
] }) });
|
|
606
661
|
}
|
|
662
|
+
function PanelFooter({ status, children }) {
|
|
663
|
+
return /* @__PURE__ */ jsxs4("div", { className: "flex w-full flex-wrap items-center justify-end gap-2", children: [
|
|
664
|
+
status ? /* @__PURE__ */ jsx4("div", { className: "min-w-0 flex-1 basis-full sm:basis-0", children: status }) : null,
|
|
665
|
+
children
|
|
666
|
+
] });
|
|
667
|
+
}
|
|
607
668
|
var DAY_FORMAT = { year: "numeric", month: "short", day: "numeric" };
|
|
608
669
|
|
|
609
670
|
// src/FieldRows.tsx
|
|
@@ -614,7 +675,7 @@ function SecretText({ value, multiline }) {
|
|
|
614
675
|
return /* @__PURE__ */ jsx5("span", { className: "break-all font-mono text-sm tracking-wide", children: [...value].map((ch, i) => /* @__PURE__ */ jsx5("span", { className: /[0-9]/.test(ch) ? "text-primary" : /[^A-Za-z0-9]/.test(ch) ? "text-warning" : void 0, children: ch }, i)) });
|
|
615
676
|
}
|
|
616
677
|
var quietError = (e, fallback) => wasCancelled(e) ? null : e instanceof Error ? e.message : fallback;
|
|
617
|
-
function SecretRow({ port, item, field, extra }) {
|
|
678
|
+
function SecretRow({ port, item, field, extra, onTurnOn }) {
|
|
618
679
|
const confirmed = useConfirmed();
|
|
619
680
|
const copyValue2 = useCopy();
|
|
620
681
|
const secret = useTransientSecret();
|
|
@@ -668,10 +729,27 @@ function SecretRow({ port, item, field, extra }) {
|
|
|
668
729
|
top: multiline && shown !== null,
|
|
669
730
|
actions: /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
670
731
|
extra,
|
|
732
|
+
off && onTurnOn ? /* @__PURE__ */ jsx5(TurnOnButton, { label: field.label, onTurnOn }) : null,
|
|
671
733
|
canSee && !visible ? /* @__PURE__ */ jsx5(Button2, { variant: "quiet", icon: secret.value !== null ? /* @__PURE__ */ jsx5(EyeOffGlyph, {}) : /* @__PURE__ */ jsx5(EyeGlyph, {}), "aria-label": secret.value !== null ? `Hide ${field.label}` : `Show ${field.label}`, disabled: busy, onClick: () => void toggle2() }) : null,
|
|
672
734
|
canSee ? /* @__PURE__ */ jsx5(Button2, { variant: "quiet", icon: /* @__PURE__ */ jsx5(CopyIcon, {}), "aria-label": `Copy ${field.label}`, disabled: busy, onClick: () => void copy() }) : null
|
|
673
735
|
] }),
|
|
674
|
-
children: sealed ? /* @__PURE__ */ jsx5(Badge, { icon: /* @__PURE__ */ jsx5(LockGlyph, {}), children: "
|
|
736
|
+
children: sealed ? /* @__PURE__ */ jsx5(Badge, { icon: /* @__PURE__ */ jsx5(LockGlyph, {}), children: "Never shown" }) : off ? /* @__PURE__ */ jsx5("span", { className: "text-muted-foreground", children: "Turned off" }) : error ? /* @__PURE__ */ jsx5("span", { className: "truncate text-destructive", title: error, children: error }) : shown !== null ? visible ? /* @__PURE__ */ jsx5("span", { className: cn3("block", multiline ? "whitespace-pre-wrap break-words" : "truncate"), children: shown || "\u2014" }) : /* @__PURE__ */ jsx5(SecretText, { value: shown, multiline }) : /* @__PURE__ */ jsx5("span", { className: cn3("block truncate text-muted-foreground", !visible && "tracking-widest"), children: visible ? "\u2026" : MASK })
|
|
737
|
+
}
|
|
738
|
+
);
|
|
739
|
+
}
|
|
740
|
+
function TurnOnButton({ label, onTurnOn }) {
|
|
741
|
+
const [busy, setBusy] = useState5(false);
|
|
742
|
+
return /* @__PURE__ */ jsx5(
|
|
743
|
+
Button2,
|
|
744
|
+
{
|
|
745
|
+
variant: "outline",
|
|
746
|
+
"aria-label": `Turn on ${label}`,
|
|
747
|
+
disabled: busy,
|
|
748
|
+
onClick: () => {
|
|
749
|
+
setBusy(true);
|
|
750
|
+
void onTurnOn().finally(() => setBusy(false));
|
|
751
|
+
},
|
|
752
|
+
children: "Turn on"
|
|
675
753
|
}
|
|
676
754
|
);
|
|
677
755
|
}
|
|
@@ -810,14 +888,27 @@ function loginSiteOf(item) {
|
|
|
810
888
|
return raw.replace(/^https?:\/\//, "").replace(/^www\./, "").split("/")[0] ?? "";
|
|
811
889
|
}
|
|
812
890
|
}
|
|
891
|
+
var TWO_PART_SUFFIX = /* @__PURE__ */ new Set(["co", "com", "org", "net", "gov", "edu", "ac", "ne", "or"]);
|
|
892
|
+
function siteDomainOf(host) {
|
|
893
|
+
const h = host.toLowerCase().replace(/\.$/, "");
|
|
894
|
+
if (!h || /^[\d.]+$/.test(h) || h.includes(":")) return h;
|
|
895
|
+
const labels = h.split(".").filter(Boolean);
|
|
896
|
+
if (labels.length <= 2) return labels.join(".");
|
|
897
|
+
const sld = labels[labels.length - 2] ?? "";
|
|
898
|
+
const tld = labels[labels.length - 1] ?? "";
|
|
899
|
+
const keep = TWO_PART_SUFFIX.has(sld) && tld.length <= 3 ? 3 : 2;
|
|
900
|
+
return labels.slice(-keep).join(".");
|
|
901
|
+
}
|
|
813
902
|
function sortItems(items, sort) {
|
|
814
903
|
const out = [...items];
|
|
815
904
|
const byName = (a, b) => a.name.localeCompare(b.name, void 0, { sensitivity: "base" });
|
|
816
905
|
if (sort === "name") return out.sort(byName);
|
|
817
|
-
if (sort === "website")
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
906
|
+
if (sort === "website")
|
|
907
|
+
return out.sort((a, b) => {
|
|
908
|
+
const x = loginSiteOf(a), y = loginSiteOf(b);
|
|
909
|
+
if (!x || !y) return x ? -1 : y ? 1 : byName(a, b);
|
|
910
|
+
return siteDomainOf(x).localeCompare(siteDomainOf(y)) || x.localeCompare(y) || byName(a, b);
|
|
911
|
+
});
|
|
821
912
|
if (sort === "updated") return out.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
|
|
822
913
|
return out.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
|
|
823
914
|
}
|
|
@@ -1208,7 +1299,7 @@ import { useEffect as useEffect6, useRef as useRef4, useState as useState6 } fro
|
|
|
1208
1299
|
import { Button as Button3 } from "@ai-matrx/design-system/controls";
|
|
1209
1300
|
import { cn as cn4 } from "@ai-matrx/design-system";
|
|
1210
1301
|
import { formatAbsoluteDate } from "@ai-matrx/kit/format";
|
|
1211
|
-
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1302
|
+
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1212
1303
|
var PAGE = 50;
|
|
1213
1304
|
var MAX = 500;
|
|
1214
1305
|
function ActivityPanel({ item, port, onClose }) {
|
|
@@ -1237,7 +1328,10 @@ function ActivityPanel({ item, port, onClose }) {
|
|
|
1237
1328
|
{
|
|
1238
1329
|
title: "Activity",
|
|
1239
1330
|
onClose,
|
|
1240
|
-
footer:
|
|
1331
|
+
footer: /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
1332
|
+
hasMore ? /* @__PURE__ */ jsx6(Button3, { variant: "outline", disabled: loading, onClick: () => setLimit((n) => Math.min(MAX, n * 2)), children: loading ? "Loading\u2026" : "Show more" }) : null,
|
|
1333
|
+
/* @__PURE__ */ jsx6(Button3, { variant: "primary", onClick: onClose, children: "Done" })
|
|
1334
|
+
] }),
|
|
1241
1335
|
children: [
|
|
1242
1336
|
error ? /* @__PURE__ */ jsx6("p", { role: "alert", className: "px-1 text-sm text-destructive", children: error }) : null,
|
|
1243
1337
|
entries === null ? loading ? /* @__PURE__ */ jsx6(Empty, { children: "Reading activity\u2026" }) : null : entries.length === 0 ? /* @__PURE__ */ jsx6(Empty, { children: "Nothing has happened yet." }) : groupByDay(entries, now).map((day) => /* @__PURE__ */ jsx6(VaultSection, { title: day.label, children: collapseRuns(
|
|
@@ -1260,7 +1354,7 @@ function ActivityPanel({ item, port, onClose }) {
|
|
|
1260
1354
|
}
|
|
1261
1355
|
|
|
1262
1356
|
// src/activity/HistoryPanel.tsx
|
|
1263
|
-
import { Fragment as
|
|
1357
|
+
import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1264
1358
|
var MASK2 = "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
|
|
1265
1359
|
var messageOf = (e, fallback) => wasCancelled(e) ? null : e instanceof Error ? e.message : fallback;
|
|
1266
1360
|
function ItemHistoryPanel({ item, port, arg, onClose, onChanged }) {
|
|
@@ -1320,8 +1414,11 @@ function ItemHistoryPanel({ item, port, arg, onClose, onChanged }) {
|
|
|
1320
1414
|
{
|
|
1321
1415
|
title: "Password history",
|
|
1322
1416
|
onClose,
|
|
1323
|
-
footer:
|
|
1324
|
-
|
|
1417
|
+
footer: /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
1418
|
+
page?.nextBefore ? /* @__PURE__ */ jsx7(Button4, { variant: "outline", disabled: more, onClick: () => void loadMore(), children: more ? "Loading\u2026" : "Show earlier" }) : null,
|
|
1419
|
+
/* @__PURE__ */ jsx7(Button4, { variant: "primary", onClick: onClose, children: "Done" })
|
|
1420
|
+
] }),
|
|
1421
|
+
children: !eligible ? /* @__PURE__ */ jsx7(Empty, { children: "History is kept only for your own items." }) : loading && !page ? /* @__PURE__ */ jsx7(Empty, { children: "Reading history\u2026" }) : /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
1325
1422
|
error ? /* @__PURE__ */ jsx7("p", { role: "alert", className: "px-1 text-sm text-destructive", children: error }) : null,
|
|
1326
1423
|
notice ? /* @__PURE__ */ jsx7("p", { role: "status", className: "px-1 text-sm text-success", children: notice }) : null,
|
|
1327
1424
|
page && groups.length === 0 ? /* @__PURE__ */ jsx7(Empty, { children: "No earlier values yet." }) : null,
|
|
@@ -1389,7 +1486,7 @@ function HistoryRow({ item, port, page, entry, label, onRestored, onConflict, on
|
|
|
1389
1486
|
VaultRow,
|
|
1390
1487
|
{
|
|
1391
1488
|
label: when,
|
|
1392
|
-
actions: entry.available ? /* @__PURE__ */ jsxs7(
|
|
1489
|
+
actions: entry.available ? /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
1393
1490
|
/* @__PURE__ */ jsx7(Button4, { variant: "quiet", icon: secret.value !== null ? /* @__PURE__ */ jsx7(EyeOffGlyph, {}) : /* @__PURE__ */ jsx7(EyeGlyph, {}), "aria-label": secret.value !== null ? "Hide" : "Show", disabled: busy, onClick: () => void toggle2() }),
|
|
1394
1491
|
/* @__PURE__ */ jsx7(Button4, { variant: "quiet", icon: /* @__PURE__ */ jsx7(CopyIcon2, {}), "aria-label": "Copy", disabled: busy, onClick: () => void copy() }),
|
|
1395
1492
|
canRestore(page, entry) ? /* @__PURE__ */ jsx7(Button4, { variant: "quiet", icon: /* @__PURE__ */ jsx7(RestoreGlyph, {}), "aria-label": "Restore", disabled: busy, onClick: () => void restore() }) : null
|
|
@@ -1723,7 +1820,7 @@ function imageFrom(data) {
|
|
|
1723
1820
|
}
|
|
1724
1821
|
|
|
1725
1822
|
// src/authenticator/Setup.tsx
|
|
1726
|
-
import { Fragment as
|
|
1823
|
+
import { Fragment as Fragment5, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1727
1824
|
function useCanScan() {
|
|
1728
1825
|
const [ok, setOk] = useState10(false);
|
|
1729
1826
|
useEffect10(() => {
|
|
@@ -1856,7 +1953,7 @@ function OtpSetupRow({ value, onChange, label = "One-time password", placeholder
|
|
|
1856
1953
|
VaultRow,
|
|
1857
1954
|
{
|
|
1858
1955
|
label,
|
|
1859
|
-
actions: /* @__PURE__ */ jsxs9(
|
|
1956
|
+
actions: /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
1860
1957
|
/* @__PURE__ */ jsx9(Button6, { variant: "quiet", icon: /* @__PURE__ */ jsx9(QrGlyph, {}), "aria-label": "Choose QR image", title: "Choose or drop a QR image", disabled: disabled || reading, onClick: () => file.current?.click() }),
|
|
1861
1958
|
canScan ? /* @__PURE__ */ jsx9(Button6, { variant: "quiet", icon: /* @__PURE__ */ jsx9(CameraGlyph, {}), "aria-label": "Scan with camera", title: "Scan with camera", disabled, onClick: () => setScanning(true) }) : null
|
|
1862
1959
|
] }),
|
|
@@ -1925,13 +2022,14 @@ import { confirm as confirm2 } from "@ai-matrx/kit/confirm-opener";
|
|
|
1925
2022
|
|
|
1926
2023
|
// src/authenticator/port.ts
|
|
1927
2024
|
var MFA_METHOD_KEY = "mfa_method";
|
|
2025
|
+
var OTP_SEED_KEY = "totp_seed";
|
|
1928
2026
|
function mfaMethodOf(item) {
|
|
1929
2027
|
const v = item.custom.find((c) => c.key === MFA_METHOD_KEY)?.value;
|
|
1930
2028
|
return v === "sms" ? "sms" : v ? "push_or_other" : null;
|
|
1931
2029
|
}
|
|
1932
2030
|
|
|
1933
2031
|
// src/authenticator/TotpRows.tsx
|
|
1934
|
-
import { Fragment as
|
|
2032
|
+
import { Fragment as Fragment6, jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1935
2033
|
function otpActionError(e, what) {
|
|
1936
2034
|
const status = e?.status;
|
|
1937
2035
|
if (status === 404) return "There is no one-time password here.";
|
|
@@ -2006,7 +2104,7 @@ function TotpRow({ port, item, onChanged }) {
|
|
|
2006
2104
|
VaultRow,
|
|
2007
2105
|
{
|
|
2008
2106
|
label: "One-time password",
|
|
2009
|
-
actions: /* @__PURE__ */ jsxs10(
|
|
2107
|
+
actions: /* @__PURE__ */ jsxs10(Fragment6, { children: [
|
|
2010
2108
|
a.enabled ? /* @__PURE__ */ jsx10(CopyCodeButton, { live, label: item.name }) : null,
|
|
2011
2109
|
menu
|
|
2012
2110
|
] }),
|
|
@@ -2089,7 +2187,7 @@ function TwoFactorMethodRow({ port, item, onChanged }) {
|
|
|
2089
2187
|
}
|
|
2090
2188
|
|
|
2091
2189
|
// src/authenticator/AddOtpPanel.tsx
|
|
2092
|
-
import { Fragment as
|
|
2190
|
+
import { Fragment as Fragment7, jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2093
2191
|
var NEW = "__new__";
|
|
2094
2192
|
var LOGIN_KEYS = ["website_login", "username_password"];
|
|
2095
2193
|
function normalizeWebsite(raw) {
|
|
@@ -2172,7 +2270,7 @@ function AddOtpPanel({ port, items, definitions, itemId = null, onClose, onChang
|
|
|
2172
2270
|
title: "Add one-time password",
|
|
2173
2271
|
size: "md",
|
|
2174
2272
|
onClose,
|
|
2175
|
-
footer: /* @__PURE__ */ jsxs11(
|
|
2273
|
+
footer: /* @__PURE__ */ jsxs11(Fragment7, { children: [
|
|
2176
2274
|
/* @__PURE__ */ jsx11(Button8, { variant: "quiet", onClick: onClose, disabled: busy, children: "Cancel" }),
|
|
2177
2275
|
/* @__PURE__ */ jsx11(Button8, { variant: "primary", disabled: !ready, onClick: () => void save(), children: busy ? "Adding\u2026" : "Add" })
|
|
2178
2276
|
] }),
|
|
@@ -2212,7 +2310,7 @@ function AddOtpPanel({ port, items, definitions, itemId = null, onClose, onChang
|
|
|
2212
2310
|
}
|
|
2213
2311
|
}
|
|
2214
2312
|
) }),
|
|
2215
|
-
isNew ? /* @__PURE__ */ jsxs11(
|
|
2313
|
+
isNew ? /* @__PURE__ */ jsxs11(Fragment7, { children: [
|
|
2216
2314
|
/* @__PURE__ */ jsx11(VaultRow, { label: "Name", children: /* @__PURE__ */ jsx11(
|
|
2217
2315
|
Field4,
|
|
2218
2316
|
{
|
|
@@ -2244,7 +2342,7 @@ function AddedPanel({ port, item, onClose, onDone }) {
|
|
|
2244
2342
|
}
|
|
2245
2343
|
|
|
2246
2344
|
// src/authenticator/AuthenticatorView.tsx
|
|
2247
|
-
import { Fragment as
|
|
2345
|
+
import { Fragment as Fragment8, jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2248
2346
|
function matchesEntry(entry, q) {
|
|
2249
2347
|
if (!entry || !q) return false;
|
|
2250
2348
|
return [entry.issuer, entry.account].some((v) => v?.toLowerCase().includes(q));
|
|
@@ -2283,7 +2381,7 @@ function AuthenticatorView({ port, items, definitions, query, onOpen, onChanged,
|
|
|
2283
2381
|
const total = items.filter((i) => i.authenticator && !i.deletion && !hidden.has(i.id)).length;
|
|
2284
2382
|
const familyOf2 = (key) => definitions.find((d) => d.key === key)?.family ?? "generic";
|
|
2285
2383
|
return /* @__PURE__ */ jsxs12("section", { "aria-label": "One-time passwords", className: "flex h-full min-h-0 flex-col bg-background", children: [
|
|
2286
|
-
header,
|
|
2384
|
+
header ? /* @__PURE__ */ jsx12("div", { className: "mx-auto w-full max-w-3xl px-3 pt-3 sm:px-4", children: header }) : null,
|
|
2287
2385
|
/* @__PURE__ */ jsxs12("div", { className: "flex min-h-12 items-center justify-between gap-2 px-4 pb-1 pt-3", children: [
|
|
2288
2386
|
/* @__PURE__ */ jsxs12("div", { className: "flex min-w-0 items-baseline gap-2", children: [
|
|
2289
2387
|
/* @__PURE__ */ jsx12("h2", { className: "truncate text-sm font-semibold text-foreground", children: "One-time passwords" }),
|
|
@@ -2295,7 +2393,7 @@ function AuthenticatorView({ port, items, definitions, query, onOpen, onChanged,
|
|
|
2295
2393
|
/* @__PURE__ */ jsx12("span", { className: "flex size-12 items-center justify-center rounded-full bg-muted text-muted-foreground", children: /* @__PURE__ */ jsx12(ShieldGlyph, { className: "size-6" }) }),
|
|
2296
2394
|
/* @__PURE__ */ jsx12("p", { className: "text-sm font-medium text-foreground", children: "No one-time passwords yet" }),
|
|
2297
2395
|
/* @__PURE__ */ jsx12(Button9, { variant: "primary", icon: /* @__PURE__ */ jsx12(PlusGlyph, {}), onClick: () => setAdding(true), children: "Add one-time password" })
|
|
2298
|
-
] }) : groups.length === 0 ? /* @__PURE__ */ jsx12("div", { className: "px-4 py-10 text-center text-sm text-muted-foreground", children: "Nothing matches." }) : /* @__PURE__ */ jsx12("div", { className: "min-h-0 flex-1 overflow-y-auto px-3 pb-6 pt-1 sm:px-4", children: /* @__PURE__ */ jsx12("div", { className: "mx-auto flex w-full max-w-3xl flex-col gap-5", children: groups.map((g) => /* @__PURE__ */ jsx12(VaultSection, {
|
|
2396
|
+
] }) : groups.length === 0 ? /* @__PURE__ */ jsx12("div", { className: "px-4 py-10 text-center text-sm text-muted-foreground", children: "Nothing matches." }) : /* @__PURE__ */ jsx12("div", { className: "min-h-0 flex-1 overflow-y-auto px-3 pb-6 pt-1 sm:px-4", children: /* @__PURE__ */ jsx12("div", { className: "mx-auto flex w-full max-w-3xl flex-col gap-5", children: groups.map((g) => /* @__PURE__ */ jsx12(VaultSection, { title: g.label, className: "[&>div]:px-1", children: g.items.map((item) => /* @__PURE__ */ jsx12(
|
|
2299
2397
|
OtpListRow,
|
|
2300
2398
|
{
|
|
2301
2399
|
port,
|
|
@@ -2392,7 +2490,7 @@ function OtpListRow({ port, item, family, entry, onOpen, onRename, onChanged, on
|
|
|
2392
2490
|
/* @__PURE__ */ jsx12(CopyIcon4, { className: "size-4" }),
|
|
2393
2491
|
"Copy code"
|
|
2394
2492
|
] }) : null,
|
|
2395
|
-
canManage ? /* @__PURE__ */ jsxs12(
|
|
2493
|
+
canManage ? /* @__PURE__ */ jsxs12(Fragment8, { children: [
|
|
2396
2494
|
/* @__PURE__ */ jsxs12(DropdownMenuItem2, { onSelect: onRename, children: [
|
|
2397
2495
|
/* @__PURE__ */ jsx12(PencilGlyph, { className: "size-4" }),
|
|
2398
2496
|
"Rename"
|
|
@@ -2432,9 +2530,9 @@ function sandboxBlocker(envKeyDraft, savedEnvKey) {
|
|
|
2432
2530
|
return null;
|
|
2433
2531
|
}
|
|
2434
2532
|
var HANDLING_WORDS = {
|
|
2435
|
-
visible: { label: "
|
|
2436
|
-
revealable: { label: "
|
|
2437
|
-
sealed: { label: "
|
|
2533
|
+
visible: { label: "Always shown", hint: "Anyone who can use it can show or copy it" },
|
|
2534
|
+
revealable: { label: "Hidden", hint: "Showing or copying it needs reveal access" },
|
|
2535
|
+
sealed: { label: "Never shown", hint: "No one can see it. Automation can still use it." }
|
|
2438
2536
|
};
|
|
2439
2537
|
function handlingChoices(current) {
|
|
2440
2538
|
return current === "sealed" ? ["sealed"] : ["visible", "revealable", "sealed"];
|
|
@@ -2616,7 +2714,7 @@ function FieldSettings({ item, port, field, onClose, onChanged }) {
|
|
|
2616
2714
|
}
|
|
2617
2715
|
) }),
|
|
2618
2716
|
/* @__PURE__ */ jsx13(VaultRow, { label: "Editable", hint: quietHint(field.editable ? "The value can be changed" : "The value is locked"), children: /* @__PURE__ */ jsx13(Switch, { "aria-label": "Editable", checked: field.editable, disabled: locked, onCheckedChange: (v) => void update("editable", { editable: v }) }) }),
|
|
2619
|
-
/* @__PURE__ */ jsx13(VaultRow, { label: "
|
|
2717
|
+
/* @__PURE__ */ jsx13(VaultRow, { label: "Turned on", hint: quietHint(field.active ? "In use" : "Kept, but nothing uses it"), children: /* @__PURE__ */ jsx13(Switch, { "aria-label": "Turned on", checked: field.active, disabled: locked, onCheckedChange: (v) => void update("active", { active: v }) }) })
|
|
2620
2718
|
] }),
|
|
2621
2719
|
error ? /* @__PURE__ */ jsx13(Problem, { children: error }) : null
|
|
2622
2720
|
] });
|
|
@@ -2684,7 +2782,7 @@ function ItemSettingsPanel({ item, port, onClose, onChanged, onPanel }) {
|
|
|
2684
2782
|
f.envKey
|
|
2685
2783
|
] }) : null,
|
|
2686
2784
|
f.injectIntoSandbox ? /* @__PURE__ */ jsx13("span", { className: "text-muted-foreground", children: " \xB7 Sandbox" }) : null,
|
|
2687
|
-
!f.active ? /* @__PURE__ */ jsx13("span", { className: "text-
|
|
2785
|
+
!f.active ? /* @__PURE__ */ jsx13("span", { className: "text-warning", children: " \xB7 Turned off" }) : null
|
|
2688
2786
|
] })
|
|
2689
2787
|
},
|
|
2690
2788
|
f.id
|
|
@@ -3080,7 +3178,7 @@ function startNewRestoreRun(preview) {
|
|
|
3080
3178
|
import { useState as useState16 } from "react";
|
|
3081
3179
|
import { Checkbox } from "@ai-matrx/design-system";
|
|
3082
3180
|
import { Badge as Badge4, Button as Button12, DisclosureHeader as DisclosureHeader2 } from "@ai-matrx/design-system/controls";
|
|
3083
|
-
import { Fragment as
|
|
3181
|
+
import { Fragment as Fragment9, jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
3084
3182
|
function PickLine({ checked, onChange, disabled = false, title, detail, badge, tone }) {
|
|
3085
3183
|
return /* @__PURE__ */ jsxs15("label", { className: "flex min-h-11 items-center gap-3 px-4 py-1", "data-clickable": disabled ? void 0 : "", children: [
|
|
3086
3184
|
/* @__PURE__ */ jsx15(Checkbox, { checked, disabled, onCheckedChange: (v) => onChange(v === true), "aria-label": title }),
|
|
@@ -3092,7 +3190,7 @@ function PickLine({ checked, onChange, disabled = false, title, detail, badge, t
|
|
|
3092
3190
|
function Windowed({ items, size = 150, render }) {
|
|
3093
3191
|
const [all, setAll] = useState16(false);
|
|
3094
3192
|
const shown = all ? items : items.slice(0, size);
|
|
3095
|
-
return /* @__PURE__ */ jsxs15(
|
|
3193
|
+
return /* @__PURE__ */ jsxs15(Fragment9, { children: [
|
|
3096
3194
|
shown.map(render),
|
|
3097
3195
|
items.length > shown.length ? /* @__PURE__ */ jsx15("div", { className: "px-4 py-2", children: /* @__PURE__ */ jsxs15(Button12, { variant: "quiet", onClick: () => setAll(true), children: [
|
|
3098
3196
|
"Show all ",
|
|
@@ -3113,7 +3211,7 @@ function ErrorLine({ message: message2 }) {
|
|
|
3113
3211
|
var plural = (n, one, many = `${one}s`) => `${n} ${n === 1 ? one : many}`;
|
|
3114
3212
|
|
|
3115
3213
|
// src/io/BackupPanel.tsx
|
|
3116
|
-
import { Fragment as
|
|
3214
|
+
import { Fragment as Fragment10, jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
3117
3215
|
var RECORD_STATUS = {
|
|
3118
3216
|
created: "Restored",
|
|
3119
3217
|
replayed: "Already restored",
|
|
@@ -3241,13 +3339,13 @@ function BackupPanel({ port, items, onClose, onChanged }) {
|
|
|
3241
3339
|
const retryable = (result?.retryable_failure ?? 0) > 0;
|
|
3242
3340
|
const mismatch = repeat !== "" && repeat !== passphrase;
|
|
3243
3341
|
const names = new Map(restorePreview?.records.map((r) => [r.source_item_id, r.display_name]) ?? []);
|
|
3244
|
-
const footer = mode === "backup" ? /* @__PURE__ */ jsxs16(
|
|
3342
|
+
const footer = mode === "backup" ? /* @__PURE__ */ jsxs16(Fragment10, { children: [
|
|
3245
3343
|
/* @__PURE__ */ jsx16(Button13, { variant: "quiet", onClick: onClose, children: "Close" }),
|
|
3246
3344
|
backup ? /* @__PURE__ */ jsx16(Button13, { variant: "primary", disabled: busy || !passphrase || passphrase !== repeat || backup.omissions.length > 0 && !accepted, onClick: () => void downloadBackup(), children: "Encrypt and download" }) : /* @__PURE__ */ jsxs16(Button13, { variant: "primary", disabled: busy || selected.size === 0, onClick: () => void reviewBackup(), children: [
|
|
3247
3345
|
"Review ",
|
|
3248
3346
|
selected.size
|
|
3249
3347
|
] })
|
|
3250
|
-
] }) : /* @__PURE__ */ jsxs16(
|
|
3348
|
+
] }) : /* @__PURE__ */ jsxs16(Fragment10, { children: [
|
|
3251
3349
|
/* @__PURE__ */ jsx16(Button13, { variant: "quiet", onClick: onClose, children: result && !retryable ? "Done" : "Close" }),
|
|
3252
3350
|
result ? retryable ? /* @__PURE__ */ jsx16(Button13, { variant: "primary", disabled: busy, onClick: () => void restore(), children: "Try again" }) : /* @__PURE__ */ jsx16(Button13, { variant: "outline", disabled: busy, onClick: () => void again(), children: "Restore again" }) : restorePreview ? /* @__PURE__ */ jsxs16(Button13, { variant: "primary", disabled: busy || restorePreview.omissions.length > 0 && !accepted, onClick: () => void restore(), children: [
|
|
3253
3351
|
"Restore ",
|
|
@@ -3268,12 +3366,12 @@ function BackupPanel({ port, items, onClose, onChanged }) {
|
|
|
3268
3366
|
]
|
|
3269
3367
|
}
|
|
3270
3368
|
),
|
|
3271
|
-
mode === "backup" ? /* @__PURE__ */ jsxs16(
|
|
3369
|
+
mode === "backup" ? /* @__PURE__ */ jsxs16(Fragment10, { children: [
|
|
3272
3370
|
/* @__PURE__ */ jsx16(
|
|
3273
3371
|
VaultSection,
|
|
3274
3372
|
{
|
|
3275
3373
|
title: `${selected.size} of ${plural(items.length, "credential")}`,
|
|
3276
|
-
actions: /* @__PURE__ */ jsxs16(
|
|
3374
|
+
actions: /* @__PURE__ */ jsxs16(Fragment10, { children: [
|
|
3277
3375
|
/* @__PURE__ */ jsx16(Button13, { variant: "quiet", disabled: busy || items.length === 0, onClick: () => {
|
|
3278
3376
|
setBackup(null);
|
|
3279
3377
|
setSelected(new Set(items.map((i) => i.id)));
|
|
@@ -3286,7 +3384,7 @@ function BackupPanel({ port, items, onClose, onChanged }) {
|
|
|
3286
3384
|
children: items.length === 0 ? /* @__PURE__ */ jsx16(Empty, { children: "Nothing to back up yet." }) : /* @__PURE__ */ jsx16(Windowed, { items, render: (i) => /* @__PURE__ */ jsx16(PickLine, { title: i.name, detail: i.definitionLabel, checked: selected.has(i.id), disabled: busy, onChange: (on) => pick(i.id, on) }, i.id) })
|
|
3287
3385
|
}
|
|
3288
3386
|
),
|
|
3289
|
-
backup ? /* @__PURE__ */ jsxs16(
|
|
3387
|
+
backup ? /* @__PURE__ */ jsxs16(Fragment10, { children: [
|
|
3290
3388
|
/* @__PURE__ */ jsx16(Summary, { value: backup }),
|
|
3291
3389
|
/* @__PURE__ */ jsx16(Omissions, { omissions: backup.omissions, accepted, onAccepted: setAccepted, verb: "Back up" }),
|
|
3292
3390
|
/* @__PURE__ */ jsxs16(VaultSection, { children: [
|
|
@@ -3294,7 +3392,7 @@ function BackupPanel({ port, items, onClose, onChanged }) {
|
|
|
3294
3392
|
/* @__PURE__ */ jsx16(VaultRow, { label: "Repeat", ...mismatch ? { hint: "Doesn't match" } : {}, children: /* @__PURE__ */ jsx16(Field6, { type: "password", value: repeat, autoComplete: "new-password", "aria-label": "Repeat the passphrase", onChange: (e) => setRepeat(e.target.value) }) })
|
|
3295
3393
|
] })
|
|
3296
3394
|
] }) : null
|
|
3297
|
-
] }) : /* @__PURE__ */ jsx16(
|
|
3395
|
+
] }) : /* @__PURE__ */ jsx16(Fragment10, { children: !restorePreview ? /* @__PURE__ */ jsxs16(VaultSection, { children: [
|
|
3298
3396
|
/* @__PURE__ */ jsxs16(VaultRow, { label: "File", ...file ? { hint: file.name } : {}, children: [
|
|
3299
3397
|
/* @__PURE__ */ jsx16(Button13, { variant: "outline", disabled: busy, onClick: () => fileInput.current?.click(), children: "Choose a backup" }),
|
|
3300
3398
|
/* @__PURE__ */ jsx16(
|
|
@@ -3312,7 +3410,7 @@ function BackupPanel({ port, items, onClose, onChanged }) {
|
|
|
3312
3410
|
)
|
|
3313
3411
|
] }),
|
|
3314
3412
|
/* @__PURE__ */ jsx16(VaultRow, { label: "Passphrase", children: /* @__PURE__ */ jsx16(Field6, { type: "password", value: passphrase, autoComplete: "current-password", "aria-label": "Backup passphrase", onChange: (e) => setPassphrase(e.target.value) }) })
|
|
3315
|
-
] }) : /* @__PURE__ */ jsxs16(
|
|
3413
|
+
] }) : /* @__PURE__ */ jsxs16(Fragment10, { children: [
|
|
3316
3414
|
/* @__PURE__ */ jsx16(Summary, { value: restorePreview }),
|
|
3317
3415
|
!result ? /* @__PURE__ */ jsx16(Omissions, { omissions: restorePreview.omissions, accepted, onAccepted: setAccepted, verb: "Restore" }) : null,
|
|
3318
3416
|
!result ? /* @__PURE__ */ jsx16("p", { className: "px-1 text-xs text-muted-foreground", children: "Restored items start disabled and restricted." }) : /* @__PURE__ */ jsx16(VaultSection, { title: `${result.created} restored \xB7 ${result.replayed} already \xB7 ${result.refused} refused \xB7 ${result.retryable_failure} to retry`, children: result.results.map((r) => /* @__PURE__ */ jsx16(VaultRow, { label: names.get(r.source_item_id) ?? "Credential", children: /* @__PURE__ */ jsxs16("span", { className: r.status === "refused" || r.status === "retryable_failure" ? "text-destructive" : "text-foreground", children: [
|
|
@@ -3329,7 +3427,7 @@ import { useMemo, useState as useState18 } from "react";
|
|
|
3329
3427
|
import { Button as Button14, Select as Select5 } from "@ai-matrx/design-system/controls";
|
|
3330
3428
|
import { downloadFile as downloadFile2 } from "@ai-matrx/kit/download";
|
|
3331
3429
|
import { confirm as confirm5 } from "@ai-matrx/kit/confirm-opener";
|
|
3332
|
-
import { Fragment as
|
|
3430
|
+
import { Fragment as Fragment11, jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
3333
3431
|
var FORMATS = [
|
|
3334
3432
|
{ value: "matrx_login_csv_v1", label: "Matrx", hint: "Website logins, all common fields" },
|
|
3335
3433
|
{ value: "firefox_csv_v1", label: "Firefox", hint: "Address, username and password" },
|
|
@@ -3409,7 +3507,7 @@ function ExportPanel({ port, items, onClose }) {
|
|
|
3409
3507
|
title: "Export logins",
|
|
3410
3508
|
size: "lg",
|
|
3411
3509
|
onClose,
|
|
3412
|
-
footer: /* @__PURE__ */ jsxs17(
|
|
3510
|
+
footer: /* @__PURE__ */ jsxs17(Fragment11, { children: [
|
|
3413
3511
|
/* @__PURE__ */ jsx17(Button14, { variant: "quiet", onClick: onClose, children: "Close" }),
|
|
3414
3512
|
preview ? /* @__PURE__ */ jsxs17(Button14, { variant: "primary", icon: /* @__PURE__ */ jsx17(ExportGlyph, { className: "size-4" }), disabled: busy || eligible === 0, onClick: () => void download(), children: [
|
|
3415
3513
|
"Download ",
|
|
@@ -3436,7 +3534,7 @@ function ExportPanel({ port, items, onClose }) {
|
|
|
3436
3534
|
VaultSection,
|
|
3437
3535
|
{
|
|
3438
3536
|
title: `${selected.size} of ${plural(logins.length, "login")}`,
|
|
3439
|
-
actions: /* @__PURE__ */ jsxs17(
|
|
3537
|
+
actions: /* @__PURE__ */ jsxs17(Fragment11, { children: [
|
|
3440
3538
|
/* @__PURE__ */ jsx17(Button14, { variant: "quiet", disabled: busy || logins.length === 0, onClick: () => {
|
|
3441
3539
|
changed();
|
|
3442
3540
|
setSelected(new Set(logins.map((l) => l.id)));
|
|
@@ -4318,7 +4416,7 @@ async function parseImportFile(source, file, limits, signal) {
|
|
|
4318
4416
|
}
|
|
4319
4417
|
|
|
4320
4418
|
// src/io/ImportPanel.tsx
|
|
4321
|
-
import { Fragment as
|
|
4419
|
+
import { Fragment as Fragment12, jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
4322
4420
|
var ROLE_OPTIONS = [
|
|
4323
4421
|
{ value: "keep", label: "Keep encrypted" },
|
|
4324
4422
|
{ value: "title", label: "Name" },
|
|
@@ -4493,13 +4591,13 @@ function ImportPanel({ port, host, items, organizations, onClose, onChanged, lim
|
|
|
4493
4591
|
const help = EXPORT_HELP[source];
|
|
4494
4592
|
const stage = done ? "done" : draft ? "review" : "choose";
|
|
4495
4593
|
const busy = running !== null || reading;
|
|
4496
|
-
const footer = stage === "choose" ? /* @__PURE__ */ jsxs18(
|
|
4594
|
+
const footer = stage === "choose" ? /* @__PURE__ */ jsxs18(Fragment12, { children: [
|
|
4497
4595
|
/* @__PURE__ */ jsx18(Button15, { variant: "quiet", onClick: onClose, children: "Close" }),
|
|
4498
4596
|
source === "env" ? /* @__PURE__ */ jsx18(Button15, { variant: "primary", icon: /* @__PURE__ */ jsx18(ImportGlyph, { className: "size-4" }), disabled: !envText.trim(), onClick: () => reviewEnv(envText), children: "Review" }) : null
|
|
4499
|
-
] }) : stage === "review" ? /* @__PURE__ */ jsxs18(
|
|
4597
|
+
] }) : stage === "review" ? /* @__PURE__ */ jsxs18(Fragment12, { children: [
|
|
4500
4598
|
running ? /* @__PURE__ */ jsx18(Button15, { variant: "outline", onClick: () => stop.current = true, children: "Stop" }) : /* @__PURE__ */ jsx18(Button15, { variant: "quiet", onClick: reset, children: "Back" }),
|
|
4501
4599
|
/* @__PURE__ */ jsx18(Button15, { variant: "primary", icon: /* @__PURE__ */ jsx18(ImportGlyph, { className: "size-4" }), disabled: busy || chosen === 0 || ambiguous === true || needsApproval, onClick: start, children: running ? `Importing ${running.done} of ${running.total}` : `Import ${chosen}` })
|
|
4502
|
-
] }) : /* @__PURE__ */ jsxs18(
|
|
4600
|
+
] }) : /* @__PURE__ */ jsxs18(Fragment12, { children: [
|
|
4503
4601
|
done && done.failed.length + done.untried.length > 0 ? /* @__PURE__ */ jsx18(Button15, { variant: "outline", disabled: busy, onClick: retry, children: running ? `Importing ${running.done} of ${running.total}` : `Try ${done.failed.length + done.untried.length} again` }) : null,
|
|
4504
4602
|
/* @__PURE__ */ jsx18(Button15, { variant: "primary", onClick: onClose, children: "Done" })
|
|
4505
4603
|
] });
|
|
@@ -4529,13 +4627,13 @@ function ImportPanel({ port, host, items, organizations, onClose, onChanged, lim
|
|
|
4529
4627
|
] }),
|
|
4530
4628
|
source === "env" ? /* @__PURE__ */ jsx18(VaultRow, { label: "Sandboxes", hint: "Pass these values to agent sandboxes", children: /* @__PURE__ */ jsx18(Switch4, { checked: injectSandbox, onCheckedChange: setInjectSandbox, "aria-label": "Use in sandboxes" }) }) : null
|
|
4531
4629
|
] }) : null,
|
|
4532
|
-
stage === "review" && draft ? /* @__PURE__ */ jsxs18(
|
|
4630
|
+
stage === "review" && draft ? /* @__PURE__ */ jsxs18(Fragment12, { children: [
|
|
4533
4631
|
organizations.length > 0 ? /* @__PURE__ */ jsx18(VaultSection, { children: /* @__PURE__ */ jsx18(VaultRow, { label: "Save to", children: /* @__PURE__ */ jsx18(Select6, { value: destination, options: destinationOptions, "aria-label": "Save to", onValueChange: (v) => draft.kind === "file" ? restart({ destination: v }) : setDestination(v) }) }) }) : null,
|
|
4534
4632
|
/* @__PURE__ */ jsx18(
|
|
4535
4633
|
VaultSection,
|
|
4536
4634
|
{
|
|
4537
4635
|
title: draft.kind === "env" ? plural(envKeys.length, "value") : summary(counts, lines.length),
|
|
4538
|
-
actions: /* @__PURE__ */ jsxs18(
|
|
4636
|
+
actions: /* @__PURE__ */ jsxs18(Fragment12, { children: [
|
|
4539
4637
|
/* @__PURE__ */ jsx18(Button15, { variant: "quiet", disabled: busy, onClick: () => setSelected(draft.kind === "env" ? new Set(envKeys.map((e) => e.key + e.text)) : defaultSelection(lines)), children: "Reset" }),
|
|
4540
4638
|
/* @__PURE__ */ jsx18(Button15, { variant: "quiet", disabled: busy, onClick: () => setSelected(/* @__PURE__ */ new Set()), children: "None" })
|
|
4541
4639
|
] }),
|
|
@@ -4629,7 +4727,7 @@ import { jsx as jsx19 } from "react/jsx-runtime";
|
|
|
4629
4727
|
function ItemIcon({ definitionKey, family, site, size = "md", inverted = false }) {
|
|
4630
4728
|
const box = size === "lg" ? "size-10 rounded-xl text-base" : size === "md" ? "size-8 rounded-lg text-sm" : "size-6 rounded-md text-xs";
|
|
4631
4729
|
const tone = inverted ? "bg-primary-foreground text-primary" : "bg-muted text-foreground";
|
|
4632
|
-
const initial = site
|
|
4730
|
+
const initial = siteDomainOf(site).charAt(0).toUpperCase();
|
|
4633
4731
|
if (initial && /[A-Z0-9]/.test(initial)) {
|
|
4634
4732
|
return /* @__PURE__ */ jsx19("span", { "aria-hidden": true, className: cn8("flex shrink-0 items-center justify-center font-semibold", box, tone), children: initial });
|
|
4635
4733
|
}
|
|
@@ -4652,13 +4750,13 @@ import { cn as cn9 } from "@ai-matrx/design-system";
|
|
|
4652
4750
|
import { confirm as confirm6 } from "@ai-matrx/kit/confirm-opener";
|
|
4653
4751
|
import { downloadFile as downloadFile3 } from "@ai-matrx/kit/download";
|
|
4654
4752
|
import { DownloadIcon } from "@ai-matrx/design-system/icons";
|
|
4655
|
-
import { Fragment as
|
|
4753
|
+
import { Fragment as Fragment13, jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
4656
4754
|
var messageOf2 = (e, fallback) => wasCancelled(e) ? null : e instanceof Error ? e.message : fallback;
|
|
4657
4755
|
var TOO_BIG = "Files over 25 MB can't be stored.";
|
|
4658
4756
|
var PROTECTION = [
|
|
4659
4757
|
{ value: "visible", label: "Open", title: "Anyone who can use the item can download it" },
|
|
4660
4758
|
{ value: "revealable", label: "Protected", title: "Downloading needs a recent sign-in" },
|
|
4661
|
-
{ value: "sealed", label: "
|
|
4759
|
+
{ value: "sealed", label: "Never shown", title: "Only automation can use it, never a person" }
|
|
4662
4760
|
];
|
|
4663
4761
|
function FilesSection({ item, port, editing, onChanged }) {
|
|
4664
4762
|
const confirmed = useConfirmed();
|
|
@@ -4725,7 +4823,7 @@ function FilesSection({ item, port, editing, onChanged }) {
|
|
|
4725
4823
|
{
|
|
4726
4824
|
label: a.label,
|
|
4727
4825
|
hint: a.description || void 0,
|
|
4728
|
-
actions: a.handling === "sealed" ? /* @__PURE__ */ jsx20(Badge5, { icon: /* @__PURE__ */ jsx20(LockGlyph, {}), children: "
|
|
4826
|
+
actions: a.handling === "sealed" ? /* @__PURE__ */ jsx20(Badge5, { icon: /* @__PURE__ */ jsx20(LockGlyph, {}), children: "Never shown" }) : canDownload(item, a) ? /* @__PURE__ */ jsx20(Button16, { variant: "quiet", icon: /* @__PURE__ */ jsx20(DownloadIcon, {}), "aria-label": `Download ${a.fileName}`, disabled: busy !== null, onClick: () => void download(a) }) : null,
|
|
4729
4827
|
children: /* @__PURE__ */ jsx20(FileName, { file: a })
|
|
4730
4828
|
},
|
|
4731
4829
|
a.id
|
|
@@ -4749,13 +4847,13 @@ function EditableFile({ port, item: it, file: a, busy: b, run: go, onDownload, o
|
|
|
4749
4847
|
const yes = await confirm6({ title: `Delete ${a.label}?`, description: "The encrypted file is removed from this item.", confirmLabel: "Delete", variant: "destructive" });
|
|
4750
4848
|
if (yes) await go(`delete:${a.id}`, () => port.activity.deleteFile(it, a.id), "The file could not be deleted.");
|
|
4751
4849
|
}
|
|
4752
|
-
return /* @__PURE__ */ jsxs19(
|
|
4850
|
+
return /* @__PURE__ */ jsxs19(Fragment13, { children: [
|
|
4753
4851
|
/* @__PURE__ */ jsx20(
|
|
4754
4852
|
VaultRow,
|
|
4755
4853
|
{
|
|
4756
4854
|
label: a.label,
|
|
4757
4855
|
hint: a.description || void 0,
|
|
4758
|
-
actions: /* @__PURE__ */ jsxs19(
|
|
4856
|
+
actions: /* @__PURE__ */ jsxs19(Fragment13, { children: [
|
|
4759
4857
|
canDownload(it, a) ? /* @__PURE__ */ jsx20(Button16, { variant: "quiet", icon: /* @__PURE__ */ jsx20(DownloadIcon, {}), "aria-label": `Download ${a.fileName}`, disabled: b !== null, onClick: onDownload }) : null,
|
|
4760
4858
|
/* @__PURE__ */ jsx20(Button16, { variant: "quiet", icon: /* @__PURE__ */ jsx20(PencilGlyph, {}), "aria-label": `Edit ${a.label}`, pressed: open, disabled: b !== null, onClick: () => setOpen((o) => !o) }),
|
|
4761
4859
|
/* @__PURE__ */ jsx20(Button16, { variant: "quiet", icon: /* @__PURE__ */ jsx20(UploadGlyph, {}), "aria-label": `Replace ${a.fileName}`, disabled: b !== null, onClick: () => replacer.current?.click() }),
|
|
@@ -4809,7 +4907,7 @@ function NewFile({ file, busy, onAdd, onCancel }) {
|
|
|
4809
4907
|
if (handling === "sealed" && !await confirmSeal(label)) return;
|
|
4810
4908
|
await onAdd({ label: label.trim(), description: description.trim() || null, handling });
|
|
4811
4909
|
}
|
|
4812
|
-
return /* @__PURE__ */ jsxs19(
|
|
4910
|
+
return /* @__PURE__ */ jsxs19(Fragment13, { children: [
|
|
4813
4911
|
/* @__PURE__ */ jsx20(VaultRow, { label: "New file", children: /* @__PURE__ */ jsxs19("span", { className: "flex min-w-0 items-center gap-2", children: [
|
|
4814
4912
|
/* @__PURE__ */ jsx20("span", { className: "truncate", children: file.name }),
|
|
4815
4913
|
/* @__PURE__ */ jsx20("span", { className: "shrink-0 text-xs text-muted-foreground", children: formatFileSize2(file.size) })
|
|
@@ -4833,7 +4931,7 @@ function FileDetailsRows({ file, busy, onSave, onCancel }) {
|
|
|
4833
4931
|
if (handling === "sealed" && file.handling !== "sealed" && !await confirmSeal(label)) return;
|
|
4834
4932
|
await onSave({ label: label.trim(), description: description.trim() || null, fileName: fileName.trim(), handling });
|
|
4835
4933
|
}
|
|
4836
|
-
return /* @__PURE__ */ jsxs19(
|
|
4934
|
+
return /* @__PURE__ */ jsxs19(Fragment13, { children: [
|
|
4837
4935
|
/* @__PURE__ */ jsx20(VaultRow, { label: "Name", children: /* @__PURE__ */ jsx20(Field7, { "aria-label": "Name", value: label, onChange: (e) => setLabel(e.target.value) }) }),
|
|
4838
4936
|
/* @__PURE__ */ jsx20(VaultRow, { label: "Purpose", children: /* @__PURE__ */ jsx20(Field7, { "aria-label": "Purpose", placeholder: "What it is for", value: description, onChange: (e) => setDescription(e.target.value) }) }),
|
|
4839
4937
|
/* @__PURE__ */ jsx20(VaultRow, { label: "File name", children: /* @__PURE__ */ jsx20(Field7, { "aria-label": "File name", value: fileName, onChange: (e) => setFileName(e.target.value) }) }),
|
|
@@ -4857,7 +4955,7 @@ function confirmSeal(label) {
|
|
|
4857
4955
|
import { useState as useState21 } from "react";
|
|
4858
4956
|
import { Badge as Badge6, Button as Button17, Textarea as Textarea3 } from "@ai-matrx/design-system/controls";
|
|
4859
4957
|
import { CopyIcon as CopyIcon6 } from "@ai-matrx/design-system/icons";
|
|
4860
|
-
import { Fragment as
|
|
4958
|
+
import { Fragment as Fragment14, jsx as jsx21, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
4861
4959
|
var MASK4 = "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
|
|
4862
4960
|
var say2 = (e, fallback) => e instanceof Error && e.message ? e.message : fallback;
|
|
4863
4961
|
function RecoveryCodesRow({ item, field, port, onChanged }) {
|
|
@@ -4901,7 +4999,7 @@ function RecoveryCodesRow({ item, field, port, onChanged }) {
|
|
|
4901
4999
|
{
|
|
4902
5000
|
label: "Recovery codes",
|
|
4903
5001
|
top: true,
|
|
4904
|
-
actions: /* @__PURE__ */ jsxs20(
|
|
5002
|
+
actions: /* @__PURE__ */ jsxs20(Fragment14, { children: [
|
|
4905
5003
|
/* @__PURE__ */ jsx21(Button17, { variant: "quiet", icon: /* @__PURE__ */ jsx21(CheckGlyph, {}), "aria-label": "Save codes", disabled: busy || !draft.trim(), onClick: () => void saveDraft() }),
|
|
4906
5004
|
/* @__PURE__ */ jsx21(Button17, { variant: "quiet", removes: true, icon: /* @__PURE__ */ jsx21(XGlyph, {}), "aria-label": "Cancel", disabled: busy, onClick: () => {
|
|
4907
5005
|
setDraft(null);
|
|
@@ -4943,11 +5041,11 @@ function RecoveryCodesRow({ item, field, port, onChanged }) {
|
|
|
4943
5041
|
{
|
|
4944
5042
|
label: "Recovery codes",
|
|
4945
5043
|
top: codes !== null,
|
|
4946
|
-
actions: /* @__PURE__ */ jsxs20(
|
|
5044
|
+
actions: /* @__PURE__ */ jsxs20(Fragment14, { children: [
|
|
4947
5045
|
canSee ? /* @__PURE__ */ jsx21(Button17, { variant: "quiet", icon: codes ? /* @__PURE__ */ jsx21(EyeOffGlyph, {}) : /* @__PURE__ */ jsx21(EyeGlyph, {}), "aria-label": codes ? "Hide codes" : "Show codes", disabled: busy, onClick: () => void toggle2() }) : null,
|
|
4948
5046
|
canEdit && !sealed ? /* @__PURE__ */ jsx21(Button17, { variant: "quiet", icon: /* @__PURE__ */ jsx21(PencilGlyph, {}), "aria-label": "Replace all codes", disabled: busy, onClick: () => setDraft("") }) : null
|
|
4949
5047
|
] }),
|
|
4950
|
-
children: sealed ? /* @__PURE__ */ jsx21(Badge6, { icon: /* @__PURE__ */ jsx21(LockGlyph, {}), children: "
|
|
5048
|
+
children: sealed ? /* @__PURE__ */ jsx21(Badge6, { icon: /* @__PURE__ */ jsx21(LockGlyph, {}), children: "Never shown" }) : codes ? /* @__PURE__ */ jsxs20("ul", { className: "flex flex-col gap-0.5", "aria-label": "Recovery codes", children: [
|
|
4951
5049
|
codes.map((code, i) => /* @__PURE__ */ jsxs20("li", { className: "flex min-h-7 items-center gap-1", children: [
|
|
4952
5050
|
/* @__PURE__ */ jsx21("code", { className: "min-w-0 flex-1 break-all font-mono text-sm text-foreground", children: code }),
|
|
4953
5051
|
/* @__PURE__ */ jsx21(Button17, { variant: "quiet", icon: /* @__PURE__ */ jsx21(CopyIcon6, {}), "aria-label": `Copy code ${i + 1}`, onClick: () => void copyValue2(code, "Recovery code") }),
|
|
@@ -5270,10 +5368,7 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
|
|
|
5270
5368
|
title: "Move or copy",
|
|
5271
5369
|
size: "md",
|
|
5272
5370
|
onClose,
|
|
5273
|
-
footer: /* @__PURE__ */
|
|
5274
|
-
/* @__PURE__ */ jsx24(StatusLine, { error, notice }),
|
|
5275
|
-
/* @__PURE__ */ jsx24(Button19, { variant: "outline", className: "ml-auto", onClick: onClose, children: "Close" })
|
|
5276
|
-
] }),
|
|
5371
|
+
footer: /* @__PURE__ */ jsx24(PanelFooter, { status: error || notice ? /* @__PURE__ */ jsx24(StatusLine, { error, notice }) : null, children: /* @__PURE__ */ jsx24(Button19, { variant: "primary", onClick: onClose, children: "Done" }) }),
|
|
5277
5372
|
children: nothing ? /* @__PURE__ */ jsx24(VaultSection, { children: /* @__PURE__ */ jsx24(Empty, { children: passkey ? "A passkey stays where it was created." : "Only the owner can move or give this item." }) }) : /* @__PURE__ */ jsxs22(VaultSection, { children: [
|
|
5278
5373
|
canMove && moves.length > 0 ? /* @__PURE__ */ jsx24(
|
|
5279
5374
|
VaultRow,
|
|
@@ -5305,7 +5400,7 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
|
|
|
5305
5400
|
}
|
|
5306
5401
|
|
|
5307
5402
|
// src/sharing/SharePanel.tsx
|
|
5308
|
-
import { Fragment as
|
|
5403
|
+
import { Fragment as Fragment15, jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
5309
5404
|
function useGrants(port, item) {
|
|
5310
5405
|
const [grants, setGrants] = useState25(null);
|
|
5311
5406
|
const [loadError, setLoadError] = useState25(null);
|
|
@@ -5388,10 +5483,7 @@ function SharePanel({ item, port, organizations, onClose, onChanged }) {
|
|
|
5388
5483
|
title: "Share",
|
|
5389
5484
|
size: "md",
|
|
5390
5485
|
onClose,
|
|
5391
|
-
footer: /* @__PURE__ */
|
|
5392
|
-
/* @__PURE__ */ jsx25(StatusLine, { error, notice }),
|
|
5393
|
-
/* @__PURE__ */ jsx25(Button20, { variant: "primary", className: "ml-auto", onClick: onClose, children: "Done" })
|
|
5394
|
-
] }),
|
|
5486
|
+
footer: /* @__PURE__ */ jsx25(PanelFooter, { status: error || notice ? /* @__PURE__ */ jsx25(StatusLine, { error, notice }) : null, children: /* @__PURE__ */ jsx25(Button20, { variant: "primary", onClick: onClose, children: "Done" }) }),
|
|
5395
5487
|
children: [
|
|
5396
5488
|
/* @__PURE__ */ jsxs23(VaultSection, { title: "Who has access", children: [
|
|
5397
5489
|
isOrg ? /* @__PURE__ */ jsx25(AccessLine, { glyph: BuildingGlyph, who: `${orgName} admins`, children: /* @__PURE__ */ jsx25("span", { className: "px-2 text-sm text-muted-foreground", children: "Full access" }) }) : /* @__PURE__ */ jsx25(AccessLine, { glyph: PersonGlyph, who: "You", meta: "Owner", children: /* @__PURE__ */ jsx25("span", { className: "px-2 text-sm text-muted-foreground", children: "Full access" }) }),
|
|
@@ -5456,7 +5548,7 @@ function IntoOrganization({ item, port, organizations, grants, onShared }) {
|
|
|
5456
5548
|
const [level, setLevel] = useState25("use");
|
|
5457
5549
|
const chosen = open.find((o) => o.id === target);
|
|
5458
5550
|
if (item.owner.kind !== "me") return null;
|
|
5459
|
-
return /* @__PURE__ */ jsx25(VaultSection, { title: "Share into organization", children: open.length > 0 ? /* @__PURE__ */ jsxs23(
|
|
5551
|
+
return /* @__PURE__ */ jsx25(VaultSection, { title: "Share into organization", children: open.length > 0 ? /* @__PURE__ */ jsxs23(Fragment15, { children: [
|
|
5460
5552
|
/* @__PURE__ */ jsxs23("div", { className: "flex min-h-11 items-center gap-2 px-3 sm:px-4", children: [
|
|
5461
5553
|
/* @__PURE__ */ jsx25(BuildingGlyph, { className: "size-4 shrink-0 text-muted-foreground" }),
|
|
5462
5554
|
/* @__PURE__ */ jsx25(Select8, { className: "min-w-0 flex-1", "aria-label": "Organization", value: target || "__none__", onValueChange: (v) => setTarget(v === "__none__" ? "" : v), options: [{ value: "__none__", label: "Choose an organization" }, ...open.map((o) => ({ value: o.id, label: o.name }))] }),
|
|
@@ -5542,7 +5634,7 @@ function SharingSummary({ item, port, className }) {
|
|
|
5542
5634
|
|
|
5543
5635
|
// src/ItemPane.tsx
|
|
5544
5636
|
import { formatAbsoluteDate as formatAbsoluteDate3 } from "@ai-matrx/kit/format";
|
|
5545
|
-
import { Fragment as
|
|
5637
|
+
import { Fragment as Fragment16, jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
5546
5638
|
var USERNAME_KEYS = /^(username|user_name|email|login|username_or_email|account_email)$/;
|
|
5547
5639
|
function ItemPane(props) {
|
|
5548
5640
|
const { port, item, definition, mode, host, organizations, defaultOwner, seed, onBack, onMode, onSaved, onDeleted, onDirty, onCancelNew, onPanel, onChanged, favorite, notice, refreshKey } = props;
|
|
@@ -5677,6 +5769,21 @@ function ItemPane(props) {
|
|
|
5677
5769
|
if (!wasCancelled(e)) setError(e instanceof Error ? e.message : "The value could not be read.");
|
|
5678
5770
|
}
|
|
5679
5771
|
}
|
|
5772
|
+
const offFields = item ? item.fields.filter((f) => !f.active) : [];
|
|
5773
|
+
const seedField = item?.fields.find((f) => f.key === OTP_SEED_KEY) ?? null;
|
|
5774
|
+
const canTurnOn = Boolean(item && canEdit);
|
|
5775
|
+
async function turnOn(fields) {
|
|
5776
|
+
if (!item || fields.length === 0) return;
|
|
5777
|
+
setError(null);
|
|
5778
|
+
try {
|
|
5779
|
+
for (const f of fields) await confirmed(() => port.fields.updateField(item, f.id, { active: true }));
|
|
5780
|
+
onChanged();
|
|
5781
|
+
} catch (e) {
|
|
5782
|
+
if (!wasCancelled(e)) setError(e instanceof Error ? e.message : "It could not be turned on.");
|
|
5783
|
+
onChanged();
|
|
5784
|
+
}
|
|
5785
|
+
}
|
|
5786
|
+
const turnOnOne = canTurnOn ? (f) => () => turnOn([f]) : () => void 0;
|
|
5680
5787
|
const declaredKeys = new Set(declared.map((f) => f.key));
|
|
5681
5788
|
const extraFields = (item?.fields ?? []).filter((f) => !declaredKeys.has(f.key) && !draft.removed.includes(f.id) && !isAuthenticatorStorage(f.key));
|
|
5682
5789
|
const metaValue = (key) => draft.values[key] ?? item?.custom.find((c) => c.key === key)?.value ?? "";
|
|
@@ -5685,6 +5792,10 @@ function ItemPane(props) {
|
|
|
5685
5792
|
const isLogin = (item?.definitionKey ?? definition?.key) === "website_login" || (item?.definitionKey ?? definition?.key) === "username_password";
|
|
5686
5793
|
const typeLabel = definition?.label ?? item?.definitionLabel ?? "";
|
|
5687
5794
|
const shownOwner = mode === "new" ? owner === "me" ? { label: "Personal", glyph: /* @__PURE__ */ jsx26(PersonGlyph, {}) } : owner === "person" ? { label: "Someone else", glyph: /* @__PURE__ */ jsx26(SendGlyph, {}) } : { label: organizations.find((o) => o.id === owner)?.name ?? "Organization", glyph: /* @__PURE__ */ jsx26(BuildingGlyph, {}) } : item ? { label: item.owner.label, glyph: item.owner.kind === "me" ? /* @__PURE__ */ jsx26(PersonGlyph, {}) : item.owner.kind === "organization" ? /* @__PURE__ */ jsx26(BuildingGlyph, {}) : /* @__PURE__ */ jsx26(UsersIcon2, {}) } : null;
|
|
5795
|
+
const sameNamed = (id) => {
|
|
5796
|
+
const name = organizations.find((o) => o.id === id)?.name.trim().toLowerCase();
|
|
5797
|
+
return Boolean(name) && organizations.filter((o) => o.name.trim().toLowerCase() === name).length > 1;
|
|
5798
|
+
};
|
|
5688
5799
|
const tagsVisible = showTags || draft.tags.length > 0 || tagsText !== "";
|
|
5689
5800
|
const descriptionVisible = showDescription || draft.description !== "";
|
|
5690
5801
|
const header = /* @__PURE__ */ jsxs24("header", { className: "flex min-h-14 items-center gap-2 border-b border-border px-3 py-2 sm:gap-3 sm:px-5", children: [
|
|
@@ -5752,7 +5863,7 @@ function ItemPane(props) {
|
|
|
5752
5863
|
/* @__PURE__ */ jsx26(SettingsIcon, { className: "size-4" }),
|
|
5753
5864
|
"Settings"
|
|
5754
5865
|
] }) : null,
|
|
5755
|
-
canManage ? /* @__PURE__ */ jsxs24(
|
|
5866
|
+
canManage ? /* @__PURE__ */ jsxs24(Fragment16, { children: [
|
|
5756
5867
|
/* @__PURE__ */ jsx26(DropdownMenuSeparator3, {}),
|
|
5757
5868
|
/* @__PURE__ */ jsxs24(DropdownMenuItem3, { className: "text-destructive", disabled: busy, onSelect: () => void remove(), children: [
|
|
5758
5869
|
/* @__PURE__ */ jsx26(TrashGlyph, { className: "size-4" }),
|
|
@@ -5768,7 +5879,11 @@ function ItemPane(props) {
|
|
|
5768
5879
|
header,
|
|
5769
5880
|
error ? /* @__PURE__ */ jsx26("div", { role: "alert", className: "border-b border-border bg-muted px-5 py-2 text-sm text-destructive", children: error }) : null,
|
|
5770
5881
|
notice && !editing ? /* @__PURE__ */ jsx26("div", { role: "status", className: "border-b border-border bg-muted px-5 py-2 text-sm text-warning", children: notice }) : null,
|
|
5771
|
-
|
|
5882
|
+
item && !editing && offFields.length > 0 ? /* @__PURE__ */ jsxs24("div", { role: "status", className: "flex items-center gap-3 border-b border-border bg-muted px-5 py-2 text-sm", children: [
|
|
5883
|
+
/* @__PURE__ */ jsx26("span", { className: "min-w-0 flex-1 truncate text-warning", children: offFields.length === 1 ? "1 field is turned off" : `${offFields.length} fields are turned off` }),
|
|
5884
|
+
canTurnOn ? /* @__PURE__ */ jsx26(TurnOnButton, { label: "all fields", onTurnOn: () => turnOn(offFields) }) : null
|
|
5885
|
+
] }) : null,
|
|
5886
|
+
/* @__PURE__ */ jsx26("div", { className: "min-h-0 flex-1 overflow-y-auto", children: /* @__PURE__ */ jsx26("div", { className: "mx-auto flex w-full max-w-3xl flex-col gap-5 px-3 py-4 sm:px-6 sm:py-6", children: editing ? /* @__PURE__ */ jsxs24(Fragment16, { children: [
|
|
5772
5887
|
/* @__PURE__ */ jsxs24(VaultSection, { children: [
|
|
5773
5888
|
mode === "new" ? /* @__PURE__ */ jsx26(VaultRow, { label: "Save to", children: /* @__PURE__ */ jsx26(
|
|
5774
5889
|
OptionCombobox,
|
|
@@ -5780,16 +5895,16 @@ function ItemPane(props) {
|
|
|
5780
5895
|
searchPlaceholder: "Find an organization",
|
|
5781
5896
|
groups: [
|
|
5782
5897
|
{ heading: "Just you", options: ["me"] },
|
|
5783
|
-
...organizations.length > 0 ? [{ heading: "Organizations", options: organizations.map((o) => o.id) }] : [],
|
|
5898
|
+
...organizations.length > 0 ? [{ heading: "Organizations", options: [...organizations].sort((a, b) => a.name.localeCompare(b.name, void 0, { sensitivity: "base" }) || a.id.localeCompare(b.id)).map((o) => o.id) }] : [],
|
|
5784
5899
|
{ heading: "Send", options: ["person"] }
|
|
5785
5900
|
],
|
|
5786
5901
|
getLabel: (v) => v === "me" ? "Personal" : v === "person" ? "Someone else" : organizations.find((o) => o.id === v)?.name ?? v,
|
|
5787
|
-
getHint: (v) => v === "me" ? "Only you" : v === "person" ? "Sent by email" : null,
|
|
5902
|
+
getHint: (v) => v === "me" ? "Only you" : v === "person" ? "Sent by email" : sameNamed(v) ? `ID ${v.slice(0, 8)}` : null,
|
|
5788
5903
|
renderIcon: (v) => v === "me" ? /* @__PURE__ */ jsx26(PersonGlyph, { className: "size-4" }) : v === "person" ? /* @__PURE__ */ jsx26(SendGlyph, { className: "size-4" }) : /* @__PURE__ */ jsx26(BuildingGlyph, { className: "size-4" })
|
|
5789
5904
|
}
|
|
5790
5905
|
) }) : null,
|
|
5791
5906
|
/* @__PURE__ */ jsx26(EditRow, { label: "Name", value: draft.name, onChange: (v) => patch({ name: v }), placeholder: "Name", autoFocus: mode === "new" }),
|
|
5792
|
-
mode === "new" && owner === "person" ? /* @__PURE__ */ jsxs24(
|
|
5907
|
+
mode === "new" && owner === "person" ? /* @__PURE__ */ jsxs24(Fragment16, { children: [
|
|
5793
5908
|
/* @__PURE__ */ jsx26(EditRow, { label: "Their email", value: recipient, placeholder: "name@company.com", inputMode: "email", onChange: setRecipient }),
|
|
5794
5909
|
declared.some((f) => f.storage === "encrypted" && f.kind === "secret") ? /* @__PURE__ */ jsx26(VaultRow, { label: "Password", hint: "You never see it", children: /* @__PURE__ */ jsx26(Switch5, { checked: generatePrivately, onCheckedChange: setGeneratePrivately, "aria-label": "Generate the password privately" }) }) : null
|
|
5795
5910
|
] }) : null,
|
|
@@ -5808,7 +5923,7 @@ function ItemPane(props) {
|
|
|
5808
5923
|
multiline: f.kind === "multiline",
|
|
5809
5924
|
inputMode: f.kind === "url" ? "url" : USERNAME_KEYS.test(f.key) ? "email" : "text",
|
|
5810
5925
|
onChange: (v) => setValue(f.key, v),
|
|
5811
|
-
actions: /* @__PURE__ */ jsxs24(
|
|
5926
|
+
actions: /* @__PURE__ */ jsxs24(Fragment16, { children: [
|
|
5812
5927
|
hidden && existing?.handling === "revealable" && item?.capabilities.canReveal ? /* @__PURE__ */ jsx26(Button21, { variant: "quiet", icon: /* @__PURE__ */ jsx26(EyeGlyph, {}), "aria-label": `Show current ${f.label}`, onClick: () => void loadForEdit(f.key) }) : null,
|
|
5813
5928
|
secretKind ? /* @__PURE__ */ jsx26(GenerateButton, { onUse: (v) => setValue(f.key, v) }) : null,
|
|
5814
5929
|
existing ? /* @__PURE__ */ jsx26(Button21, { variant: "quiet", icon: /* @__PURE__ */ jsx26(SettingsIcon, {}), "aria-label": `${f.label} settings`, onClick: () => onPanel(`field:${existing.id}`) }) : null
|
|
@@ -5827,7 +5942,7 @@ function ItemPane(props) {
|
|
|
5827
5942
|
onChange: (v) => setValue(f.key, v),
|
|
5828
5943
|
onRemove: () => patch({ removed: [...draft.removed, f.id] }),
|
|
5829
5944
|
removeLabel: `Delete ${f.label}`,
|
|
5830
|
-
actions: /* @__PURE__ */ jsxs24(
|
|
5945
|
+
actions: /* @__PURE__ */ jsxs24(Fragment16, { children: [
|
|
5831
5946
|
f.handling === "revealable" && !(f.key in loaded) && item?.capabilities.canReveal ? /* @__PURE__ */ jsx26(Button21, { variant: "quiet", icon: /* @__PURE__ */ jsx26(EyeGlyph, {}), "aria-label": `Show current ${f.label}`, onClick: () => void loadForEdit(f.key) }) : null,
|
|
5832
5947
|
/* @__PURE__ */ jsx26(Button21, { variant: "quiet", icon: /* @__PURE__ */ jsx26(SettingsIcon, {}), "aria-label": `${f.label} settings`, onClick: () => onPanel(`field:${f.id}`) })
|
|
5833
5948
|
] })
|
|
@@ -5859,7 +5974,7 @@ function ItemPane(props) {
|
|
|
5859
5974
|
i
|
|
5860
5975
|
)),
|
|
5861
5976
|
/* @__PURE__ */ jsx26(AddRow, { label: draft.loginUrls.length === 0 ? "Website" : "", onAdd: () => patch({ loginUrls: [...draft.loginUrls, ""] }), children: draft.loginUrls.length === 0 ? "Add website" : "Add another website" }),
|
|
5862
|
-
/* @__PURE__ */ jsx26(TotpEditRow, { value: draft.authenticator, onChange: (v) => patch({ authenticator: v }), hasExisting: Boolean(item?.authenticator), item, port, onEnrolled: onChanged }),
|
|
5977
|
+
/* @__PURE__ */ jsx26(TotpEditRow, { value: draft.authenticator, onChange: (v) => patch({ authenticator: v }), hasExisting: Boolean(item?.authenticator || seedField), item, port, onEnrolled: onChanged }),
|
|
5863
5978
|
item && isLogin && !item.authenticator ? /* @__PURE__ */ jsx26(TwoFactorMethodRow, { port, item, onChanged }) : null
|
|
5864
5979
|
] }),
|
|
5865
5980
|
/* @__PURE__ */ jsx26(VaultSection, { children: /* @__PURE__ */ jsx26(EditRow, { label: "Notes", value: draft.notes, multiline: true, placeholder: "Anything worth remembering", onChange: (v) => patch({ notes: v }) }) }),
|
|
@@ -5892,12 +6007,12 @@ function ItemPane(props) {
|
|
|
5892
6007
|
) : null,
|
|
5893
6008
|
draft.secrets.map((s, i) => /* @__PURE__ */ jsx26(CustomEditRow, { label: s.label, value: s.value, secret: true, onLabel: (v) => patch({ secrets: draft.secrets.map((x, j) => j === i ? { ...x, label: v } : x) }), onValue: (v) => patch({ secrets: draft.secrets.map((x, j) => j === i ? { ...x, value: v } : x) }), onRemove: () => patch({ secrets: draft.secrets.filter((_, j) => j !== i) }) }, `s${i}`)),
|
|
5894
6009
|
extraCustom.map((c) => /* @__PURE__ */ jsx26(CustomEditRow, { label: c.label, value: c.value, secret: false, onLabel: (v) => patch({ custom: draft.custom.map((x) => x.key === c.key ? { ...x, label: v } : x) }), onValue: (v) => patch({ custom: draft.custom.map((x) => x.key === c.key ? { ...x, value: v } : x) }), onRemove: () => patch({ custom: draft.custom.filter((x) => x.key !== c.key) }) }, c.key)),
|
|
5895
|
-
!descriptionVisible && !tagsVisible && draft.secrets.length === 0 && extraCustom.length === 0 ? /* @__PURE__ */ jsx26(AddRow, { label: "
|
|
6010
|
+
!descriptionVisible && !tagsVisible && draft.secrets.length === 0 && extraCustom.length === 0 ? /* @__PURE__ */ jsx26(AddRow, { label: "Tags", onAdd: () => setShowTags(true), children: "Add tags" }) : null
|
|
5896
6011
|
]
|
|
5897
6012
|
}
|
|
5898
6013
|
),
|
|
5899
6014
|
filesProps ? /* @__PURE__ */ jsx26(FilesSection, { ...filesProps, editing: true }) : null
|
|
5900
|
-
] }) : item ? /* @__PURE__ */ jsxs24(
|
|
6015
|
+
] }) : item ? /* @__PURE__ */ jsxs24(Fragment16, { children: [
|
|
5901
6016
|
/* @__PURE__ */ jsxs24(VaultSection, { children: [
|
|
5902
6017
|
declared.map((f) => {
|
|
5903
6018
|
if (f.storage === "metadata") {
|
|
@@ -5906,11 +6021,15 @@ function ItemPane(props) {
|
|
|
5906
6021
|
}
|
|
5907
6022
|
const field = item.fields.find((x) => x.key === f.key);
|
|
5908
6023
|
if (isRecoveryCodesField(f)) return /* @__PURE__ */ jsx26(RecoveryCodesRow, { item, field, port, onChanged }, f.key);
|
|
5909
|
-
return field ? /* @__PURE__ */ jsx26(SecretRow, { port, item, field }, field.id) : null;
|
|
6024
|
+
return field ? /* @__PURE__ */ jsx26(SecretRow, { port, item, field, onTurnOn: turnOnOne(field) }, field.id) : null;
|
|
5910
6025
|
}),
|
|
5911
|
-
extraFields.map((f) => isRecoveryCodesField(f) ? /* @__PURE__ */ jsx26(RecoveryCodesRow, { item, field: f, port, onChanged }, f.id) : /* @__PURE__ */ jsx26(SecretRow, { port, item, field: f }, f.id)),
|
|
6026
|
+
extraFields.map((f) => isRecoveryCodesField(f) ? /* @__PURE__ */ jsx26(RecoveryCodesRow, { item, field: f, port, onChanged }, f.id) : /* @__PURE__ */ jsx26(SecretRow, { port, item, field: f, onTurnOn: turnOnOne(f) }, f.id)),
|
|
5912
6027
|
item.loginUrls.length > 0 ? item.loginUrls.map((u, i) => /* @__PURE__ */ jsx26(PlainRow, { label: i === 0 ? "Website" : `Website ${i + 1}`, value: u, openUrl: host.openUrl }, `${u}-${i}`)) : /* @__PURE__ */ jsx26(AddRow, { label: "Website", onAdd: canEdit ? () => onMode("edit") : null, children: "Add website" }),
|
|
5913
|
-
item.authenticator ? /* @__PURE__ */ jsx26(TotpRow, { port, item, onChanged }) :
|
|
6028
|
+
item.authenticator ? /* @__PURE__ */ jsx26(TotpRow, { port, item, onChanged }) : seedField && !seedField.active ? (
|
|
6029
|
+
// The secret is still there, only off: turning it on brings the codes back. Never "Set up",
|
|
6030
|
+
// which would invite replacing a working two-factor secret.
|
|
6031
|
+
/* @__PURE__ */ jsx26(VaultRow, { label: "One-time password", actions: canTurnOn ? /* @__PURE__ */ jsx26(TurnOnButton, { label: "One-time password", onTurnOn: () => turnOn([seedField]) }) : null, children: /* @__PURE__ */ jsx26("span", { className: "text-muted-foreground", children: "Turned off" }) })
|
|
6032
|
+
) : /* @__PURE__ */ jsx26(AddRow, { label: "One-time password", onAdd: canEdit ? () => onMode("edit") : null, children: "Set up" }),
|
|
5914
6033
|
!item.authenticator && item.custom.some((c) => c.key === MFA_METHOD_KEY && c.value) ? /* @__PURE__ */ jsx26(TwoFactorMethodRow, { port, item, onChanged }) : null
|
|
5915
6034
|
] }),
|
|
5916
6035
|
/* @__PURE__ */ jsx26(VaultSection, { children: item.notes ? /* @__PURE__ */ jsx26(PlainRow, { label: "Notes", value: item.notes, multiline: true }) : /* @__PURE__ */ jsx26(AddRow, { label: "Notes", onAdd: canEdit ? () => onMode("edit") : null, children: "Add notes" }) }),
|
|
@@ -5942,7 +6061,7 @@ function subtitleOf(item, withOwner) {
|
|
|
5942
6061
|
const what = loginSiteOf(item) || item.definitionLabel;
|
|
5943
6062
|
return withOwner ? `${what} \xB7 ${item.owner.label}` : what;
|
|
5944
6063
|
}
|
|
5945
|
-
function ItemList({ title, items, definitions, port, selectedId, onSelect, query, onQuery, sort, onSort, onNew, matchingIds, header }) {
|
|
6064
|
+
function ItemList({ title, items, definitions, port, selectedId, onSelect, query, onQuery, sort, onSort, onNew, matchingIds, header, showOwner }) {
|
|
5946
6065
|
const pinned = matchingIds ? items.filter((i) => matchingIds.has(i.id)) : [];
|
|
5947
6066
|
const rest = matchingIds ? items.filter((i) => !matchingIds.has(i.id)) : items;
|
|
5948
6067
|
const ordered = [...pinned, ...rest];
|
|
@@ -5961,7 +6080,7 @@ function ItemList({ title, items, definitions, port, selectedId, onSelect, query
|
|
|
5961
6080
|
listRef.current?.querySelector(`[data-item="${next.id}"]`)?.scrollIntoView({ block: "nearest" });
|
|
5962
6081
|
}
|
|
5963
6082
|
};
|
|
5964
|
-
const mixedOwners = new Set(items.map((i) => i.owner.organizationId ?? i.owner.kind)).size > 1;
|
|
6083
|
+
const mixedOwners = showOwner ?? new Set(items.map((i) => i.owner.organizationId ?? i.owner.kind)).size > 1;
|
|
5965
6084
|
const row = (i) => /* @__PURE__ */ jsx27(ListRow, { item: i, family: familyOf2(i.definitionKey), port, on: i.id === selectedId, onSelect, withOwner: mixedOwners }, i.id);
|
|
5966
6085
|
const sortLabel = SORTS2.find((s) => s.value === sort)?.label ?? "Name";
|
|
5967
6086
|
return /* @__PURE__ */ jsxs25("section", { "aria-label": title, className: "flex h-full min-h-0 flex-col border-r border-border bg-background", children: [
|
|
@@ -6114,7 +6233,7 @@ function refusalText(reason) {
|
|
|
6114
6233
|
// src/lists/RestorePanel.tsx
|
|
6115
6234
|
import { useEffect as useEffect18, useState as useState28 } from "react";
|
|
6116
6235
|
import { Button as Button23 } from "@ai-matrx/design-system/controls";
|
|
6117
|
-
import { Fragment as
|
|
6236
|
+
import { Fragment as Fragment17, jsx as jsx28, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
6118
6237
|
var count = (n, one) => `${n} ${one}${n === 1 ? "" : "s"}`;
|
|
6119
6238
|
function RestorePanel({ lists, item, restore, onClose }) {
|
|
6120
6239
|
const [preview, setPreview] = useState28(null);
|
|
@@ -6159,7 +6278,7 @@ function RestorePanel({ lists, item, restore, onClose }) {
|
|
|
6159
6278
|
title: `Restore "${item.name}"`,
|
|
6160
6279
|
size: "md",
|
|
6161
6280
|
onClose,
|
|
6162
|
-
footer: /* @__PURE__ */ jsxs26(
|
|
6281
|
+
footer: /* @__PURE__ */ jsxs26(Fragment17, { children: [
|
|
6163
6282
|
/* @__PURE__ */ jsx28(Button23, { variant: "quiet", onClick: onClose, children: refused ? "Close" : "Cancel" }),
|
|
6164
6283
|
refused ? null : /* @__PURE__ */ jsx28(Button23, { variant: "primary", icon: /* @__PURE__ */ jsx28(RestoreGlyph, {}), disabled: busy || loading || lists.preview !== void 0 && preview === null, onClick: () => void run(), children: busy ? "Restoring\u2026" : "Restore" })
|
|
6165
6284
|
] }),
|
|
@@ -6179,6 +6298,9 @@ function RestorePanel({ lists, item, restore, onClose }) {
|
|
|
6179
6298
|
|
|
6180
6299
|
// src/lists/TrashView.tsx
|
|
6181
6300
|
import { jsx as jsx29, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
6301
|
+
function trashLineOf(item) {
|
|
6302
|
+
return [item.definitionLabel || null, item.owner.label, item.deletion?.deletedAt ? `Deleted ${formatAbsoluteDate4(item.deletion.deletedAt, DAY_FORMAT, "")}` : null].filter(Boolean).join(" \xB7 ");
|
|
6303
|
+
}
|
|
6182
6304
|
function TrashView({ port, deleted, query, header, onChanged }) {
|
|
6183
6305
|
const confirmed = useConfirmed();
|
|
6184
6306
|
const [busyId, setBusyId] = useState29(null);
|
|
@@ -6190,7 +6312,7 @@ function TrashView({ port, deleted, query, header, onChanged }) {
|
|
|
6190
6312
|
setMessage(null);
|
|
6191
6313
|
try {
|
|
6192
6314
|
const r = await confirmed(() => port.lists.restore(item, deletionId));
|
|
6193
|
-
setMessage({ tone: "ok", text: r.alreadyRestored ? `"${item.name}" was already restored.` : `Restored "${item.name}" with ${r.restoredFields} fields and ${r.restoredAttachments} files.
|
|
6315
|
+
setMessage({ tone: "ok", text: r.alreadyRestored ? `"${item.name}" was already restored.` : `Restored "${item.name}" with ${r.restoredFields} fields and ${r.restoredAttachments} files. Turn its fields on from the item.` });
|
|
6194
6316
|
onChanged();
|
|
6195
6317
|
return r;
|
|
6196
6318
|
} catch (e) {
|
|
@@ -6208,7 +6330,7 @@ function TrashView({ port, deleted, query, header, onChanged }) {
|
|
|
6208
6330
|
/* @__PURE__ */ jsxs27("div", { className: "flex min-h-12 items-center gap-3 px-3 py-1.5 sm:px-4", children: [
|
|
6209
6331
|
/* @__PURE__ */ jsxs27("span", { className: "flex min-w-0 flex-1 flex-col leading-tight", children: [
|
|
6210
6332
|
/* @__PURE__ */ jsx29("span", { className: "truncate text-sm text-foreground", children: item.name }),
|
|
6211
|
-
/* @__PURE__ */ jsx29("span", { className: "truncate text-xs text-muted-foreground", children:
|
|
6333
|
+
/* @__PURE__ */ jsx29("span", { className: "truncate text-xs text-muted-foreground", children: trashLineOf(item) })
|
|
6212
6334
|
] }),
|
|
6213
6335
|
/* @__PURE__ */ jsx29(Button24, { variant: "outline", icon: /* @__PURE__ */ jsx29(RestoreGlyph, {}), disabled: busyId !== null || !item.deletion, onClick: () => setRestoring(item), children: "Restore" })
|
|
6214
6336
|
] }, item.id)
|
|
@@ -6499,10 +6621,9 @@ function SecureLinkPanel({ item, port, onClose }) {
|
|
|
6499
6621
|
title: "Send securely",
|
|
6500
6622
|
size: "md",
|
|
6501
6623
|
onClose,
|
|
6502
|
-
footer: /* @__PURE__ */ jsxs29(
|
|
6503
|
-
/* @__PURE__ */ jsx31("div", { className: "w-full sm:w-auto sm:min-w-0 sm:flex-1", children: /* @__PURE__ */ jsx31(StatusLine, { error, notice }) }),
|
|
6624
|
+
footer: /* @__PURE__ */ jsxs29(PanelFooter, { status: error || notice ? /* @__PURE__ */ jsx31(StatusLine, { error, notice }) : null, children: [
|
|
6504
6625
|
sameChannelSent && !error ? /* @__PURE__ */ jsx31(Badge8, { tone: "warning", children: "Both by email" }) : null,
|
|
6505
|
-
/* @__PURE__ */ jsx31(Button26, { variant: "quiet",
|
|
6626
|
+
/* @__PURE__ */ jsx31(Button26, { variant: "quiet", onClick: onClose, children: "Close" }),
|
|
6506
6627
|
/* @__PURE__ */ jsx31(Button26, { variant: "primary", disabled: !canSend, onClick: () => void send(), children: busy === "send" ? "Sending\u2026" : "Send link" })
|
|
6507
6628
|
] }),
|
|
6508
6629
|
children: [
|
|
@@ -6655,7 +6776,7 @@ function addPasskeyFailure(message2) {
|
|
|
6655
6776
|
var isRevoked = (d) => d.revokedAt !== null;
|
|
6656
6777
|
|
|
6657
6778
|
// src/devices/DevicesPanel.tsx
|
|
6658
|
-
import { Fragment as
|
|
6779
|
+
import { Fragment as Fragment18, jsx as jsx32, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
6659
6780
|
var messageOf3 = (e, fallback) => e instanceof Error && e.message ? e.message : fallback;
|
|
6660
6781
|
function ErrorLine2({ text }) {
|
|
6661
6782
|
return text ? /* @__PURE__ */ jsx32("p", { role: "alert", className: "px-1 text-sm text-destructive", children: text }) : null;
|
|
@@ -6786,7 +6907,7 @@ function ApprovePanel({ port, host, onClose, approvalKey, label, kind = "browser
|
|
|
6786
6907
|
};
|
|
6787
6908
|
const canApprove = Boolean(key && passkeys && here && methods?.passkey && !approvedUntil);
|
|
6788
6909
|
const title = isMac ? "Approve this Mac" : name ? `Approve ${name}` : "Approve this browser";
|
|
6789
|
-
const footer = approvedUntil ? /* @__PURE__ */ jsx32(Button27, { variant: "primary", onClick: onClose, children: "Done" }) : /* @__PURE__ */ jsxs30(
|
|
6910
|
+
const footer = approvedUntil ? /* @__PURE__ */ jsx32(Button27, { variant: "primary", onClick: onClose, children: "Done" }) : /* @__PURE__ */ jsxs30(Fragment18, { children: [
|
|
6790
6911
|
/* @__PURE__ */ jsx32(Button27, { variant: "quiet", disabled: busy !== null, onClick: refuse, children: key ? "Refuse" : "Close" }),
|
|
6791
6912
|
canApprove ? /* @__PURE__ */ jsx32(Button27, { variant: "primary", icon: /* @__PURE__ */ jsx32(FingerprintGlyph, {}), disabled: busy !== null, onClick: () => void approve(), children: busy === "approve" ? "Approving\u2026" : "Approve with passkey" }) : null
|
|
6792
6913
|
] });
|
|
@@ -6794,7 +6915,7 @@ function ApprovePanel({ port, host, onClose, approvalKey, label, kind = "browser
|
|
|
6794
6915
|
"This link names no key. Start again from ",
|
|
6795
6916
|
where,
|
|
6796
6917
|
"."
|
|
6797
|
-
] }) }) : /* @__PURE__ */ jsxs30(
|
|
6918
|
+
] }) }) : /* @__PURE__ */ jsxs30(Fragment18, { children: [
|
|
6798
6919
|
/* @__PURE__ */ jsxs30(VaultSection, { title: "What is asking", children: [
|
|
6799
6920
|
/* @__PURE__ */ jsx32(VaultRow, { label: "Asking", hint: "Approve only if you just asked", children: asker }),
|
|
6800
6921
|
name ? /* @__PURE__ */ jsx32(VaultRow, { label: "Name", children: /* @__PURE__ */ jsx32("span", { className: "block truncate", children: name }) }) : null,
|
|
@@ -7094,7 +7215,7 @@ function useNativeImport(bridge, stillAllowed, onImported) {
|
|
|
7094
7215
|
}
|
|
7095
7216
|
|
|
7096
7217
|
// src/native/NativeImportPanel.tsx
|
|
7097
|
-
import { Fragment as
|
|
7218
|
+
import { Fragment as Fragment19, jsx as jsx33, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
7098
7219
|
var TONE = {
|
|
7099
7220
|
eligible: "success",
|
|
7100
7221
|
committed: "success",
|
|
@@ -7138,16 +7259,16 @@ function Importer({ bridge, readLimits, activeOrganizationId, organizations, onC
|
|
|
7138
7259
|
const yes = await confirm12({ title: `Add ${plural2(ready, "passkey")} to ${orgName}?`, description: "Passkeys already there are skipped.", confirmLabel: "Import" });
|
|
7139
7260
|
if (yes) await flow.confirm();
|
|
7140
7261
|
};
|
|
7141
|
-
const footer = preview ? /* @__PURE__ */ jsxs31(
|
|
7262
|
+
const footer = preview ? /* @__PURE__ */ jsxs31(Fragment19, { children: [
|
|
7142
7263
|
/* @__PURE__ */ jsx33(Button28, { variant: "quiet", disabled: busy, onClick: () => void flow.cancel(), children: "Cancel" }),
|
|
7143
7264
|
/* @__PURE__ */ jsxs31(Button28, { variant: "primary", icon: /* @__PURE__ */ jsx33(ImportGlyph, { className: "size-4" }), disabled: busy || ready === 0, onClick: () => void importNow(), children: [
|
|
7144
7265
|
"Import ",
|
|
7145
7266
|
ready
|
|
7146
7267
|
] })
|
|
7147
|
-
] }) : status ? active ? /* @__PURE__ */ jsxs31(
|
|
7268
|
+
] }) : status ? active ? /* @__PURE__ */ jsxs31(Fragment19, { children: [
|
|
7148
7269
|
/* @__PURE__ */ jsx33(Button28, { variant: "outline", disabled: busy, onClick: () => void flow.refresh(), children: "Refresh" }),
|
|
7149
7270
|
/* @__PURE__ */ jsx33(Button28, { variant: "outline", disabled: busy, onClick: () => void flow.cancel(), children: "Cancel import" })
|
|
7150
|
-
] }) : /* @__PURE__ */ jsxs31(
|
|
7271
|
+
] }) : /* @__PURE__ */ jsxs31(Fragment19, { children: [
|
|
7151
7272
|
/* @__PURE__ */ jsx33(Button28, { variant: "quiet", onClick: flow.reset, children: "New file" }),
|
|
7152
7273
|
/* @__PURE__ */ jsx33(Button28, { variant: "primary", onClick: onClose, children: "Done" })
|
|
7153
7274
|
] }) : /* @__PURE__ */ jsx33(Button28, { variant: "quiet", onClick: onClose, children: "Close" });
|
|
@@ -7186,7 +7307,7 @@ import { GlobeIcon as GlobeIcon4 } from "@ai-matrx/design-system/icons";
|
|
|
7186
7307
|
// src/extension/CaptureCard.tsx
|
|
7187
7308
|
import { useState as useState35, useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
7188
7309
|
import { Button as Button29, SearchField as SearchField3 } from "@ai-matrx/design-system/controls";
|
|
7189
|
-
import { Fragment as
|
|
7310
|
+
import { Fragment as Fragment20, jsx as jsx34, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
7190
7311
|
var SEARCH_FROM = 4;
|
|
7191
7312
|
function CaptureCard({ capture, onChanged }) {
|
|
7192
7313
|
const prompt = useSyncExternalStore3(capture.subscribe, capture.get, capture.get);
|
|
@@ -7219,7 +7340,7 @@ function CaptureCard({ capture, onChanged }) {
|
|
|
7219
7340
|
] }),
|
|
7220
7341
|
/* @__PURE__ */ jsx34(Button29, { variant: "quiet", icon: /* @__PURE__ */ jsx34(XGlyph, {}), "aria-label": "Not now", disabled: busy, onClick: () => void decide({ action: "dismiss" }) })
|
|
7221
7342
|
] }),
|
|
7222
|
-
prompt.unavailable ? /* @__PURE__ */ jsx34("p", { className: "text-xs text-muted-foreground", children: "Save it by hand with Save a login." }) : /* @__PURE__ */ jsxs32(
|
|
7343
|
+
prompt.unavailable ? /* @__PURE__ */ jsx34("p", { className: "text-xs text-muted-foreground", children: "Save it by hand with Save a login." }) : /* @__PURE__ */ jsxs32(Fragment20, { children: [
|
|
7223
7344
|
existing.length > 0 ? /* @__PURE__ */ jsxs32("div", { className: "flex flex-col gap-1", children: [
|
|
7224
7345
|
existing.length >= SEARCH_FROM ? /* @__PURE__ */ jsx34(SearchField3, { value: q, onChange: (e) => setQ(e.target.value), placeholder: "Search logins", "aria-label": "Search logins to update" }) : null,
|
|
7225
7346
|
/* @__PURE__ */ jsxs32("ul", { className: "flex max-h-36 flex-col gap-px overflow-y-auto", children: [
|
|
@@ -7325,7 +7446,7 @@ import { useState as useState37 } from "react";
|
|
|
7325
7446
|
import { Popover as Popover2, PopoverContent as PopoverContent2, PopoverTrigger as PopoverTrigger2 } from "@ai-matrx/design-system";
|
|
7326
7447
|
import { Button as Button31 } from "@ai-matrx/design-system/controls";
|
|
7327
7448
|
import { CopyIcon as CopyIcon7 } from "@ai-matrx/design-system/icons";
|
|
7328
|
-
import { Fragment as
|
|
7449
|
+
import { Fragment as Fragment21, jsx as jsx36, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
7329
7450
|
var HOLD_MS = 6e4;
|
|
7330
7451
|
function PageGenerator({ fields }) {
|
|
7331
7452
|
const limits = useGeneratorLimitsSource();
|
|
@@ -7376,12 +7497,12 @@ function PageGenerator({ fields }) {
|
|
|
7376
7497
|
}
|
|
7377
7498
|
};
|
|
7378
7499
|
const value = held.value;
|
|
7379
|
-
return /* @__PURE__ */ jsxs34(
|
|
7500
|
+
return /* @__PURE__ */ jsxs34(Fragment21, { children: [
|
|
7380
7501
|
/* @__PURE__ */ jsx36(
|
|
7381
7502
|
VaultRow,
|
|
7382
7503
|
{
|
|
7383
7504
|
label: "New password",
|
|
7384
|
-
actions: /* @__PURE__ */ jsxs34(
|
|
7505
|
+
actions: /* @__PURE__ */ jsxs34(Fragment21, { children: [
|
|
7385
7506
|
value ? /* @__PURE__ */ jsx36(Button31, { variant: "quiet", icon: /* @__PURE__ */ jsx36(CopyIcon7, {}), "aria-label": "Copy password", onClick: () => void copy(value, "Password") }) : null,
|
|
7386
7507
|
/* @__PURE__ */ jsxs34(Popover2, { open, onOpenChange: setOpen, children: [
|
|
7387
7508
|
/* @__PURE__ */ jsx36(PopoverTrigger2, { asChild: true, children: /* @__PURE__ */ jsx36(Button31, { variant: "outline", icon: /* @__PURE__ */ jsx36(KeyGlyph, {}), disabled: busy, children: "Generate" }) }),
|
|
@@ -7758,8 +7879,33 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
7758
7879
|
},
|
|
7759
7880
|
[loc, move]
|
|
7760
7881
|
);
|
|
7882
|
+
const keyState = useRef19({ loc, go });
|
|
7883
|
+
keyState.current = { loc, go };
|
|
7884
|
+
useEffect23(() => {
|
|
7885
|
+
const onKey = (e) => {
|
|
7886
|
+
if (e.defaultPrevented || e.metaKey || e.ctrlKey || e.altKey) return;
|
|
7887
|
+
const root = rootRef.current;
|
|
7888
|
+
const at = document.activeElement;
|
|
7889
|
+
if (!root || at && at !== document.body && !root.contains(at)) return;
|
|
7890
|
+
if (at instanceof HTMLElement && (at.isContentEditable || /^(INPUT|TEXTAREA|SELECT)$/.test(at.tagName))) return;
|
|
7891
|
+
if (document.querySelector('[role="dialog"], [role="alertdialog"]')) return;
|
|
7892
|
+
const { loc: here, go: to } = keyState.current;
|
|
7893
|
+
if (e.key === "/") {
|
|
7894
|
+
const search = root.querySelector('input[aria-label^="Search"]');
|
|
7895
|
+
if (!search) return;
|
|
7896
|
+
e.preventDefault();
|
|
7897
|
+
search.focus();
|
|
7898
|
+
} else if (e.key === "Escape" && here.itemId && here.mode === "view" && !here.panel) {
|
|
7899
|
+
e.preventDefault();
|
|
7900
|
+
to({ itemId: null, mode: "view", panel: null });
|
|
7901
|
+
}
|
|
7902
|
+
};
|
|
7903
|
+
document.addEventListener("keydown", onKey);
|
|
7904
|
+
return () => document.removeEventListener("keydown", onKey);
|
|
7905
|
+
}, []);
|
|
7761
7906
|
const knobsRef = useRef19(host.knobs);
|
|
7762
7907
|
knobsRef.current = host.knobs;
|
|
7908
|
+
const [signedOut, setSignedOut] = useState40(false);
|
|
7763
7909
|
const load = useCallback5(() => {
|
|
7764
7910
|
setError(null);
|
|
7765
7911
|
port.load().then((s) => {
|
|
@@ -7770,7 +7916,10 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
7770
7916
|
(rows) => setDeleted([...s.deleted, ...rows.filter((r) => !s.deleted.some((d) => d.id === r.id))]),
|
|
7771
7917
|
() => void 0
|
|
7772
7918
|
);
|
|
7773
|
-
}).catch((e) =>
|
|
7919
|
+
}).catch((e) => {
|
|
7920
|
+
setSignedOut(e?.status === 401);
|
|
7921
|
+
setError(e instanceof Error ? e.message : "The vault could not be loaded.");
|
|
7922
|
+
});
|
|
7774
7923
|
port.lists.favorites?.list().then((ids) => setFavorites(new Set(ids)), () => void 0);
|
|
7775
7924
|
knobsRef.current?.().catch(() => void 0);
|
|
7776
7925
|
port.lists.recents?.list().then(setRecents, () => void 0);
|
|
@@ -7784,6 +7933,7 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
7784
7933
|
const orgs = snap?.organizations ?? [];
|
|
7785
7934
|
const definitions = snap?.definitions ?? [];
|
|
7786
7935
|
const inThisVault = useMemo6(() => items.filter((i) => inVault(i, loc.vault)), [items, loc.vault]);
|
|
7936
|
+
const vaultMixesOwners = new Set(inThisVault.map((i) => i.owner.organizationId ?? i.owner.kind)).size > 1;
|
|
7787
7937
|
const views = useMemo6(() => buildViews(inThisVault, definitions, favorites, recents), [inThisVault, definitions, favorites, recents]);
|
|
7788
7938
|
const visible = useMemo6(() => {
|
|
7789
7939
|
const filtered = inThisVault.filter((i) => {
|
|
@@ -7824,8 +7974,11 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
7824
7974
|
return /* @__PURE__ */ jsxs37("div", { ref: rootRef, role: "alert", className: "flex h-full flex-col items-center justify-center gap-3 bg-background p-6 text-center text-sm", children: [
|
|
7825
7975
|
/* @__PURE__ */ jsx39(SafeGlyph, { className: "size-8 text-muted-foreground" }),
|
|
7826
7976
|
/* @__PURE__ */ jsx39("div", { className: "font-medium", children: "The vault couldn\u2019t open" }),
|
|
7827
|
-
/* @__PURE__ */ jsx39("div", { className: "max-w-xs text-muted-foreground", children: plainLoadError(error) }),
|
|
7828
|
-
/* @__PURE__ */
|
|
7977
|
+
/* @__PURE__ */ jsx39("div", { className: "max-w-xs text-muted-foreground", children: signedOut ? "You\u2019ve been signed out." : plainLoadError(error) }),
|
|
7978
|
+
/* @__PURE__ */ jsxs37("div", { className: "flex gap-2", children: [
|
|
7979
|
+
signedOut && host.signIn ? /* @__PURE__ */ jsx39(Button33, { variant: "primary", onClick: host.signIn, children: "Sign in" }) : null,
|
|
7980
|
+
/* @__PURE__ */ jsx39(Button33, { variant: signedOut && host.signIn ? "outline" : "primary", onClick: load, children: "Try again" })
|
|
7981
|
+
] })
|
|
7829
7982
|
] });
|
|
7830
7983
|
}
|
|
7831
7984
|
if (!snap) {
|
|
@@ -7905,6 +8058,7 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
7905
8058
|
{
|
|
7906
8059
|
title,
|
|
7907
8060
|
items: visible,
|
|
8061
|
+
showOwner: vaultMixesOwners,
|
|
7908
8062
|
definitions,
|
|
7909
8063
|
port,
|
|
7910
8064
|
selectedId: loc.itemId,
|
|
@@ -8677,6 +8831,7 @@ async function readNativeImportLimits(api, organizationId) {
|
|
|
8677
8831
|
var recoveryOf = (w) => w.lifecycle?.vault_recovery;
|
|
8678
8832
|
var isDeleted = (w) => recoveryOf(w)?.state === "deleted";
|
|
8679
8833
|
var MATCH_MODES2 = ["host", "domain", "exact", "never"];
|
|
8834
|
+
var FIELD_WORDS = { totp_seed: "One-time password key", authenticator_last_time_step: "Last code used" };
|
|
8680
8835
|
var handlingOf = (v) => v === "visible" || v === "sealed" ? v : "revealable";
|
|
8681
8836
|
function fieldOf(w, def) {
|
|
8682
8837
|
const declared = def?.fields.find((f) => f.key === w.field_key);
|
|
@@ -8684,7 +8839,7 @@ function fieldOf(w, def) {
|
|
|
8684
8839
|
return {
|
|
8685
8840
|
id: w.id,
|
|
8686
8841
|
key: w.field_key,
|
|
8687
|
-
label: declared?.label ?? humanize(w.field_key),
|
|
8842
|
+
label: declared?.label ?? FIELD_WORDS[w.field_key] ?? humanize(w.field_key),
|
|
8688
8843
|
kind: declared?.kind ?? (handling === "visible" ? "text" : "secret"),
|
|
8689
8844
|
handling,
|
|
8690
8845
|
editable: w.editable ?? true,
|
|
@@ -8902,9 +9057,11 @@ function createVaultKnobs(client, address) {
|
|
|
8902
9057
|
}
|
|
8903
9058
|
export {
|
|
8904
9059
|
CATEGORIES,
|
|
9060
|
+
CONFIRM_RETURN_KEY,
|
|
8905
9061
|
DEFAULT_LOCATION,
|
|
8906
9062
|
GenerateButton,
|
|
8907
9063
|
HIDDEN_ITEM_TAG,
|
|
9064
|
+
IdentityGate,
|
|
8908
9065
|
LOCKED_MESSAGE,
|
|
8909
9066
|
VaultApp,
|
|
8910
9067
|
VaultLockedError,
|
|
@@ -8922,6 +9079,9 @@ export {
|
|
|
8922
9079
|
matchesQuery,
|
|
8923
9080
|
needsRecentSignIn,
|
|
8924
9081
|
parseDefinitions,
|
|
8925
|
-
|
|
9082
|
+
siteDomainOf,
|
|
9083
|
+
sortItems,
|
|
9084
|
+
useConfirmed,
|
|
9085
|
+
wasCancelled
|
|
8926
9086
|
};
|
|
8927
9087
|
//# sourceMappingURL=index.js.map
|