@ai-matrx/vault 0.1.28 → 0.1.29
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 +12 -0
- package/dist/index.cjs +190 -59
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +46 -5
- package/dist/index.d.ts +46 -5
- package/dist/index.js +204 -73
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -101,8 +101,8 @@ var init_keepass_xml_worker_client = __esm({
|
|
|
101
101
|
});
|
|
102
102
|
|
|
103
103
|
// src/VaultApp.tsx
|
|
104
|
-
import { useCallback as useCallback5, useEffect as useEffect23, useMemo as useMemo6, useRef as useRef19, useState as useState41 } from "react";
|
|
105
|
-
import { DropdownMenu as
|
|
104
|
+
import { useCallback as useCallback5, useEffect as useEffect23, useMemo as useMemo6, useRef as useRef19, useState as useState41, useSyncExternalStore as useSyncExternalStore5 } from "react";
|
|
105
|
+
import { DropdownMenu as DropdownMenu5, DropdownMenuContent as DropdownMenuContent5, DropdownMenuItem as DropdownMenuItem5, DropdownMenuTrigger as DropdownMenuTrigger5, LookScope } from "@ai-matrx/design-system";
|
|
106
106
|
import { Button as Button34, SearchField as SearchField4, Select as Select12 } from "@ai-matrx/design-system/controls";
|
|
107
107
|
import { confirm as confirm14 } from "@ai-matrx/kit/confirm-opener";
|
|
108
108
|
|
|
@@ -119,8 +119,8 @@ async function copyValue(text, label, options, deps) {
|
|
|
119
119
|
const secret = options.secret ?? true;
|
|
120
120
|
if (deps.clipboard) {
|
|
121
121
|
try {
|
|
122
|
-
await deps.clipboard.copy(text, { secret });
|
|
123
|
-
deps.notify(
|
|
122
|
+
const copied = await deps.clipboard.copy(text, { secret });
|
|
123
|
+
deps.notify(copiedLine(label, copied?.clearsAtMs ?? null), "success");
|
|
124
124
|
return true;
|
|
125
125
|
} catch (e) {
|
|
126
126
|
deps.notify(e instanceof Error && e.message ? e.message : `${label} could not be copied`, "error");
|
|
@@ -129,6 +129,11 @@ async function copyValue(text, label, options, deps) {
|
|
|
129
129
|
}
|
|
130
130
|
return copyText(text, { successMessage: `${label} copied`, failureMessage: `${label} could not be copied`, notify: (m, k) => deps.notify(m, k === "error" ? "error" : "success") });
|
|
131
131
|
}
|
|
132
|
+
function copiedLine(label, clearsAtMs) {
|
|
133
|
+
if (clearsAtMs === null || !Number.isFinite(clearsAtMs)) return `${label} copied`;
|
|
134
|
+
const at = new Date(clearsAtMs).toLocaleTimeString(void 0, { hour: "numeric", minute: "2-digit" });
|
|
135
|
+
return `${label} copied. Clears at ${at}`;
|
|
136
|
+
}
|
|
132
137
|
var ClipboardCtx = createContext(void 0);
|
|
133
138
|
function ClipboardProvider({ clipboard, children }) {
|
|
134
139
|
return /* @__PURE__ */ jsx(ClipboardCtx.Provider, { value: clipboard, children });
|
|
@@ -576,6 +581,17 @@ function useElementWidth(ref) {
|
|
|
576
581
|
}, [ref]);
|
|
577
582
|
return width;
|
|
578
583
|
}
|
|
584
|
+
function useDisposable(create, deps) {
|
|
585
|
+
const [held, setHeld] = useState3(null);
|
|
586
|
+
const make = useRef3(create);
|
|
587
|
+
make.current = create;
|
|
588
|
+
useEffect3(() => {
|
|
589
|
+
const made = make.current();
|
|
590
|
+
setHeld(made);
|
|
591
|
+
return () => made.dispose();
|
|
592
|
+
}, deps);
|
|
593
|
+
return held;
|
|
594
|
+
}
|
|
579
595
|
|
|
580
596
|
// src/ui.tsx
|
|
581
597
|
import { createContext as createContext4, useContext as useContext4, useEffect as useEffect4, useState as useState4 } from "react";
|
|
@@ -3126,6 +3142,27 @@ function importLimitsFrom(resolved) {
|
|
|
3126
3142
|
return out;
|
|
3127
3143
|
}
|
|
3128
3144
|
|
|
3145
|
+
// src/knobs.ts
|
|
3146
|
+
import { createKnobReader } from "@ai-matrx/data/knobs";
|
|
3147
|
+
var FRESH_MS = 6e4;
|
|
3148
|
+
function createVaultKnobs(client, address) {
|
|
3149
|
+
const reader = createKnobReader(client);
|
|
3150
|
+
let kept = null;
|
|
3151
|
+
return async () => {
|
|
3152
|
+
if (kept && Date.now() - kept.at < FRESH_MS) return kept.resolved;
|
|
3153
|
+
const snap = await reader.snapshot(address);
|
|
3154
|
+
kept = { at: Date.now(), resolved: snap.resolved };
|
|
3155
|
+
return snap.resolved;
|
|
3156
|
+
};
|
|
3157
|
+
}
|
|
3158
|
+
var REVEAL_SECONDS_KNOB = "desktop.vault.reveal_hide_seconds";
|
|
3159
|
+
var BACKUP_PASSPHRASE_MIN_KNOB = "desktop.vault.backup_passphrase_min_length";
|
|
3160
|
+
function positiveKnob(resolved, key) {
|
|
3161
|
+
const v = resolved[key];
|
|
3162
|
+
const n = typeof v === "string" && v.trim() !== "" ? Number(v) : v;
|
|
3163
|
+
return typeof n === "number" && Number.isFinite(n) && n > 0 ? Math.floor(n) : null;
|
|
3164
|
+
}
|
|
3165
|
+
|
|
3129
3166
|
// src/lock.ts
|
|
3130
3167
|
import { useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
3131
3168
|
var LOCKED_MESSAGE = "The vault is locked. Unlock it first.";
|
|
@@ -3321,7 +3358,8 @@ function Omissions({ omissions, accepted, onAccepted, verb }) {
|
|
|
3321
3358
|
/* @__PURE__ */ jsx17(VaultRow, { label: "Accept", hint: `${verb} without these`, children: /* @__PURE__ */ jsx17(Switch3, { checked: accepted, onCheckedChange: onAccepted, "aria-label": `${verb} without these` }) })
|
|
3322
3359
|
] });
|
|
3323
3360
|
}
|
|
3324
|
-
function BackupPanel({ port, items, onClose, onChanged }) {
|
|
3361
|
+
function BackupPanel({ port, host, items, onClose, onChanged }) {
|
|
3362
|
+
const minLength = passphraseMinimum(host.backupPassphraseMinLength);
|
|
3325
3363
|
const confirmed = useConfirmed();
|
|
3326
3364
|
const fileInput = useRef11(null);
|
|
3327
3365
|
const abort = useRef11(null);
|
|
@@ -3376,7 +3414,7 @@ function BackupPanel({ port, items, onClose, onChanged }) {
|
|
|
3376
3414
|
setAccepted(false);
|
|
3377
3415
|
});
|
|
3378
3416
|
const downloadBackup = () => guarded(async () => {
|
|
3379
|
-
if (!backup) return;
|
|
3417
|
+
if (!backup || tooShort(passphrase, minLength)) return;
|
|
3380
3418
|
const bytes2 = await confirmed(() => port.io.downloadBackup({ itemIds: [...selected], revision: backup.revision, passphrase, acceptOmissions: accepted }));
|
|
3381
3419
|
downloadFile(BACKUP_FILENAME, bytes2, "application/octet-stream");
|
|
3382
3420
|
setPassphrase("");
|
|
@@ -3423,10 +3461,11 @@ function BackupPanel({ port, items, onClose, onChanged }) {
|
|
|
3423
3461
|
};
|
|
3424
3462
|
const retryable = (result?.retryable_failure ?? 0) > 0;
|
|
3425
3463
|
const mismatch = repeat !== "" && repeat !== passphrase;
|
|
3464
|
+
const short = passphrase !== "" && tooShort(passphrase, minLength);
|
|
3426
3465
|
const names = new Map(restorePreview?.records.map((r) => [r.source_item_id, r.display_name]) ?? []);
|
|
3427
3466
|
const footer = mode === "backup" ? /* @__PURE__ */ jsxs16(Fragment10, { children: [
|
|
3428
3467
|
/* @__PURE__ */ jsx17(Button13, { variant: "quiet", onClick: onClose, children: "Close" }),
|
|
3429
|
-
backup ? /* @__PURE__ */ jsx17(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: [
|
|
3468
|
+
backup ? /* @__PURE__ */ jsx17(Button13, { variant: "primary", disabled: busy || !passphrase || short || 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: [
|
|
3430
3469
|
"Review ",
|
|
3431
3470
|
selected.size
|
|
3432
3471
|
] })
|
|
@@ -3473,7 +3512,14 @@ function BackupPanel({ port, items, onClose, onChanged }) {
|
|
|
3473
3512
|
/* @__PURE__ */ jsx17(Summary, { value: backup }),
|
|
3474
3513
|
/* @__PURE__ */ jsx17(Omissions, { omissions: backup.omissions, accepted, onAccepted: setAccepted, verb: "Back up" }),
|
|
3475
3514
|
/* @__PURE__ */ jsxs16(VaultSection, { children: [
|
|
3476
|
-
/* @__PURE__ */ jsx17(VaultRow, { label: "Passphrase", hint: "Not saved. It can't be recovered.", children: /* @__PURE__ */ jsx17(Field6, { type: "password", value: passphrase, autoComplete: "new-password", "aria-label": "Backup passphrase", onChange: (e) => setPassphrase(e.target.value) }) }),
|
|
3515
|
+
/* @__PURE__ */ jsx17(VaultRow, { label: "Passphrase", hint: minLength ? `At least ${minLength} characters. Not saved.` : "Not saved. It can't be recovered.", children: /* @__PURE__ */ jsx17(Field6, { type: "password", value: passphrase, autoComplete: "new-password", "aria-label": "Backup passphrase", "aria-invalid": short || void 0, onChange: (e) => setPassphrase(e.target.value) }) }),
|
|
3516
|
+
short ? /* @__PURE__ */ jsxs16("p", { role: "alert", className: "px-1 text-xs text-destructive", "data-passphrase-too-short": "", children: [
|
|
3517
|
+
"Use at least ",
|
|
3518
|
+
minLength,
|
|
3519
|
+
" characters. This one has ",
|
|
3520
|
+
passphrase.length,
|
|
3521
|
+
"."
|
|
3522
|
+
] }) : null,
|
|
3477
3523
|
/* @__PURE__ */ jsx17(VaultRow, { label: "Repeat", ...mismatch ? { hint: "Doesn't match" } : {}, children: /* @__PURE__ */ jsx17(Field6, { type: "password", value: repeat, autoComplete: "new-password", "aria-label": "Repeat the passphrase", onChange: (e) => setRepeat(e.target.value) }) })
|
|
3478
3524
|
] })
|
|
3479
3525
|
] }) : null
|
|
@@ -3506,6 +3552,12 @@ function BackupPanel({ port, items, onClose, onChanged }) {
|
|
|
3506
3552
|
/* @__PURE__ */ jsx17(ErrorLine, { message: error })
|
|
3507
3553
|
] });
|
|
3508
3554
|
}
|
|
3555
|
+
function passphraseMinimum(given) {
|
|
3556
|
+
return given !== void 0 && Number.isFinite(given) && given > 1 ? Math.floor(given) : null;
|
|
3557
|
+
}
|
|
3558
|
+
function tooShort(passphrase, minLength) {
|
|
3559
|
+
return minLength !== null && [...passphrase].length < minLength;
|
|
3560
|
+
}
|
|
3509
3561
|
|
|
3510
3562
|
// src/io/ExportPanel.tsx
|
|
3511
3563
|
import { useMemo, useState as useState18 } from "react";
|
|
@@ -5963,6 +6015,9 @@ import { Fragment as Fragment18, jsx as jsx27, jsxs as jsxs25 } from "react/jsx-
|
|
|
5963
6015
|
var ENV_VALUE_KEY = "env_value";
|
|
5964
6016
|
var secureNoteDraft = () => ({ key: SECURE_NOTE_KEY, label: "Secure note", value: "", multiline: true, description: "Encrypted notes" });
|
|
5965
6017
|
var USERNAME_KEYS = /^(username|user_name|email|login|username_or_email|account_email)$/;
|
|
6018
|
+
function confirmDelete(item) {
|
|
6019
|
+
return confirm10({ title: `Delete \u201C${item.name}\u201D?`, description: "It moves to Trash. You can restore it from there.", confirmLabel: "Delete", variant: "destructive" });
|
|
6020
|
+
}
|
|
5966
6021
|
function ItemPane(props) {
|
|
5967
6022
|
const { port, item, definition, mode, host, organizations, defaultOwner, seed, onBack, onMode, onSaved, onDeleted, onDirty, onCancelNew, onPanel, onChanged, favorite, notice, refreshKey } = props;
|
|
5968
6023
|
const confirmed = useConfirmed();
|
|
@@ -6115,8 +6170,7 @@ function ItemPane(props) {
|
|
|
6115
6170
|
}
|
|
6116
6171
|
async function remove() {
|
|
6117
6172
|
if (!item) return;
|
|
6118
|
-
|
|
6119
|
-
if (!ok) return;
|
|
6173
|
+
if (!await confirmDelete(item)) return;
|
|
6120
6174
|
setBusy(true);
|
|
6121
6175
|
try {
|
|
6122
6176
|
await port.remove(item);
|
|
@@ -6527,7 +6581,7 @@ function subtitleOf(item, withOwner) {
|
|
|
6527
6581
|
const what = loginSiteOf(item) || item.definitionLabel;
|
|
6528
6582
|
return withOwner ? `${what} \xB7 ${item.owner.label}` : what;
|
|
6529
6583
|
}
|
|
6530
|
-
function ItemList({ title, items, definitions, port, selectedId, onSelect, query, onQuery, sort, onSort, onNew, matchingIds, header, actions, showOwner, canSortViewed = false, onRefresh, refreshing = false, rowContextMenu = "package", rowMenuItems, stillLoading, favorites, onToggleFavorite }) {
|
|
6584
|
+
function ItemList({ title, items, definitions, port, selectedId, onSelect, query, onQuery, sort, onSort, onNew, matchingIds, header, actions, showOwner, canSortViewed = false, onRefresh, refreshing = false, rowContextMenu = "package", rowMenuItems, stillLoading, favorites, onToggleFavorite, onItemAction }) {
|
|
6531
6585
|
const sorts = SORTS2.filter((s) => canSortViewed || s.value !== "viewed");
|
|
6532
6586
|
const pinned = matchingIds ? items.filter((i) => matchingIds.has(i.id)) : [];
|
|
6533
6587
|
const rest = matchingIds ? items.filter((i) => !matchingIds.has(i.id)) : items;
|
|
@@ -6548,7 +6602,7 @@ function ItemList({ title, items, definitions, port, selectedId, onSelect, query
|
|
|
6548
6602
|
}
|
|
6549
6603
|
};
|
|
6550
6604
|
const mixedOwners = showOwner ?? new Set(items.map((i) => i.owner.organizationId ?? i.owner.kind)).size > 1;
|
|
6551
|
-
const row = (i) => /* @__PURE__ */ jsx28(ListRow, { item: i, family: familyOf2(i.definitionKey), port, on: i.id === selectedId, onSelect, withOwner: mixedOwners, ownContextMenu: rowContextMenu === "package", extra: rowMenuItems, favorite: onToggleFavorite ? { on: favorites?.has(i.id) ?? false, toggle: () => onToggleFavorite(i.id) } : void 0 }, i.id);
|
|
6605
|
+
const row = (i) => /* @__PURE__ */ jsx28(ListRow, { item: i, family: familyOf2(i.definitionKey), port, on: i.id === selectedId, onSelect, withOwner: mixedOwners, ownContextMenu: rowContextMenu === "package", extra: rowMenuItems, onAction: onItemAction, favorite: onToggleFavorite ? { on: favorites?.has(i.id) ?? false, toggle: () => onToggleFavorite(i.id) } : void 0 }, i.id);
|
|
6552
6606
|
const sortLabel = sorts.find((s) => s.value === sort)?.label ?? "Name A\u2013Z";
|
|
6553
6607
|
return /* @__PURE__ */ jsxs26("section", { "aria-label": title, className: "flex h-full min-h-0 flex-col border-r border-border bg-background", children: [
|
|
6554
6608
|
/* @__PURE__ */ jsxs26("div", { className: "flex flex-col gap-2 px-3 pb-2 pt-3", children: [
|
|
@@ -6592,7 +6646,7 @@ function ItemList({ title, items, definitions, port, selectedId, onSelect, query
|
|
|
6592
6646
|
] }) })
|
|
6593
6647
|
] });
|
|
6594
6648
|
}
|
|
6595
|
-
function ListRow({ item, family, port, on, onSelect, withOwner, ownContextMenu, extra, favorite }) {
|
|
6649
|
+
function ListRow({ item, family, port, on, onSelect, withOwner, ownContextMenu, extra, onAction, favorite }) {
|
|
6596
6650
|
const confirmed = useConfirmed();
|
|
6597
6651
|
const copy = useCopy();
|
|
6598
6652
|
const notify = useNotify();
|
|
@@ -6633,11 +6687,12 @@ function ListRow({ item, family, port, on, onSelect, withOwner, ownContextMenu,
|
|
|
6633
6687
|
...favoriteEntry ? [favoriteEntry] : [],
|
|
6634
6688
|
{ id: "open", kind: "open", label: "Open", onSelect: () => onSelect(item.id) },
|
|
6635
6689
|
{ id: "copy-name", kind: "copy-name", label: "Copy name", onSelect: copyName },
|
|
6690
|
+
...manageEntries(item, onAction),
|
|
6636
6691
|
...hostEntries.map((h) => ({ ...h, kind: h.kind ?? "host" }))
|
|
6637
6692
|
];
|
|
6638
6693
|
const entriesRef = useRef15(entries);
|
|
6639
6694
|
entriesRef.current = entries;
|
|
6640
|
-
const glyphOf = (e) => e.id === "copy:username" ? /* @__PURE__ */ jsx28(UserGlyph, { className: "size-4" }) : e.id === "copy:password" ? /* @__PURE__ */ jsx28(KeyGlyph, { className: "size-4" }) : e.id === "copy:code" ? /* @__PURE__ */ jsx28(ClockGlyph, { className: "size-4" }) : e.kind === "favorite" ? /* @__PURE__ */ jsx28(StarGlyph, { className: cn13("size-4", favorite?.on && "fill-current text-warning") }) : e.kind === "open" ? /* @__PURE__ */ jsx28(ChevronRightGlyph, { className: "size-4" }) : e.kind === "host" ? null : /* @__PURE__ */ jsx28(CopyIcon7, { className: "size-4" });
|
|
6695
|
+
const glyphOf = (e) => e.id === "copy:username" ? /* @__PURE__ */ jsx28(UserGlyph, { className: "size-4" }) : e.id === "copy:password" ? /* @__PURE__ */ jsx28(KeyGlyph, { className: "size-4" }) : e.id === "copy:code" ? /* @__PURE__ */ jsx28(ClockGlyph, { className: "size-4" }) : e.kind === "favorite" ? /* @__PURE__ */ jsx28(StarGlyph, { className: cn13("size-4", favorite?.on && "fill-current text-warning") }) : e.kind === "open" ? /* @__PURE__ */ jsx28(ChevronRightGlyph, { className: "size-4" }) : e.kind === "host" || e.kind === "manage" ? null : /* @__PURE__ */ jsx28(CopyIcon7, { className: "size-4" });
|
|
6641
6696
|
const menuItem = (e) => /* @__PURE__ */ jsxs26(DropdownMenuItem4, { disabled: e.disabled ?? false, onSelect: e.onSelect, children: [
|
|
6642
6697
|
glyphOf(e),
|
|
6643
6698
|
e.label
|
|
@@ -6691,6 +6746,8 @@ function ListRow({ item, family, port, on, onSelect, withOwner, ownContextMenu,
|
|
|
6691
6746
|
copyEntries.map(menuItem),
|
|
6692
6747
|
copyEntries.length > 0 ? /* @__PURE__ */ jsx28(DropdownMenuSeparator4, {}) : null,
|
|
6693
6748
|
entries.filter((e) => e.kind === "favorite" || e.kind === "open" || e.kind === "copy-name").map(menuItem),
|
|
6749
|
+
entries.some((e) => e.kind === "manage") ? /* @__PURE__ */ jsx28(DropdownMenuSeparator4, {}) : null,
|
|
6750
|
+
entries.filter((e) => e.kind === "manage").map(menuItem),
|
|
6694
6751
|
hostEntries.length > 0 ? /* @__PURE__ */ jsx28(DropdownMenuSeparator4, {}) : null,
|
|
6695
6752
|
entries.filter((e) => e.kind === "host").map(menuItem)
|
|
6696
6753
|
] })
|
|
@@ -6700,6 +6757,17 @@ function ListRow({ item, family, port, on, onSelect, withOwner, ownContextMenu,
|
|
|
6700
6757
|
}
|
|
6701
6758
|
);
|
|
6702
6759
|
}
|
|
6760
|
+
function manageEntries(item, onAction) {
|
|
6761
|
+
if (!onAction) return [];
|
|
6762
|
+
const canManage = item.capabilities.canManage;
|
|
6763
|
+
const offManage = !canManage && manageUnavailableReason(item) !== null;
|
|
6764
|
+
const run = (action) => () => onAction(item, action);
|
|
6765
|
+
return [
|
|
6766
|
+
{ id: "activity", kind: "manage", label: "Activity", onSelect: run("activity") },
|
|
6767
|
+
...canManage || offManage ? [{ id: "share", kind: "manage", label: "Share", onSelect: run("share"), disabled: !canManage }] : [],
|
|
6768
|
+
...canManage || offManage ? [{ id: "delete", kind: "manage", label: "Delete", onSelect: run("delete"), disabled: !canManage }] : []
|
|
6769
|
+
];
|
|
6770
|
+
}
|
|
6703
6771
|
|
|
6704
6772
|
// src/lists/TrashView.tsx
|
|
6705
6773
|
import { useState as useState30 } from "react";
|
|
@@ -7907,7 +7975,7 @@ function Importer({ bridge, readLimits, activeOrganizationId, organizations, onC
|
|
|
7907
7975
|
|
|
7908
7976
|
// src/extension/PageView.tsx
|
|
7909
7977
|
import { useState as useState39 } from "react";
|
|
7910
|
-
import {
|
|
7978
|
+
import { SiteIcon } from "@ai-matrx/design-system";
|
|
7911
7979
|
import { Button as Button33 } from "@ai-matrx/design-system/controls";
|
|
7912
7980
|
import { GlobeIcon as GlobeIcon4 } from "@ai-matrx/design-system/icons";
|
|
7913
7981
|
|
|
@@ -8236,22 +8304,10 @@ function MatchRow({ itemId, item, tag, family, port, busy, running, onOpen, onFi
|
|
|
8236
8304
|
] })
|
|
8237
8305
|
] }),
|
|
8238
8306
|
onFill ? /* @__PURE__ */ jsx38(Button33, { variant: "primary", disabled: busy, "aria-busy": running || void 0, onClick: onFill, "aria-label": `Fill ${item?.name ?? "this login"}`, children: running ? "Filling\u2026" : "Fill" }) : null,
|
|
8307
|
+
onSignIn ? /* @__PURE__ */ jsx38(Button33, { variant: onFill ? "outline" : "primary", icon: /* @__PURE__ */ jsx38(ShieldGlyph, {}), disabled: busy, onClick: onSignIn, "aria-label": `Sign me in with ${item?.name ?? "this login"}`, title: "Sign me in", children: "Sign me in" }) : null,
|
|
8239
8308
|
user && item ? /* @__PURE__ */ jsx38(Button33, { variant: "quiet", icon: /* @__PURE__ */ jsx38(UserGlyph, {}), "aria-label": `Copy ${user.label}`, title: `Copy ${user.label}`, disabled: reading, onClick: () => void read(user.label, () => port.reveal(item, user.key)) }) : null,
|
|
8240
8309
|
secret && item ? /* @__PURE__ */ jsx38(Button33, { variant: "quiet", icon: /* @__PURE__ */ jsx38(KeyGlyph, {}), "aria-label": "Copy password", title: "Copy password", disabled: reading, onClick: () => void read("Password", () => port.reveal(item, secret.key)) }) : null,
|
|
8241
|
-
otp ? /* @__PURE__ */ jsx38(Button33, { variant: "quiet", icon: /* @__PURE__ */ jsx38(ClockGlyph, {}), "aria-label": "Copy one-time code", title: "Copy one-time code", disabled: reading, onClick: () => void read("One-time code", async () => (await port.authenticator.code(otp)).code) }) : null
|
|
8242
|
-
onSignIn ? /* @__PURE__ */ jsxs36(DropdownMenu5, { children: [
|
|
8243
|
-
/* @__PURE__ */ jsx38(DropdownMenuTrigger5, { asChild: true, children: /* @__PURE__ */ jsx38(Button33, { variant: "quiet", icon: /* @__PURE__ */ jsx38(MoreGlyph, {}), "aria-label": "More", disabled: busy }) }),
|
|
8244
|
-
/* @__PURE__ */ jsxs36(DropdownMenuContent5, { align: "end", children: [
|
|
8245
|
-
/* @__PURE__ */ jsxs36(DropdownMenuItem5, { onSelect: onSignIn, children: [
|
|
8246
|
-
/* @__PURE__ */ jsx38(ShieldGlyph, { className: "size-4" }),
|
|
8247
|
-
"Sign me in"
|
|
8248
|
-
] }),
|
|
8249
|
-
/* @__PURE__ */ jsxs36(DropdownMenuItem5, { onSelect: () => onOpen(itemId), children: [
|
|
8250
|
-
/* @__PURE__ */ jsx38(ListGlyph, { className: "size-4" }),
|
|
8251
|
-
"Open item"
|
|
8252
|
-
] })
|
|
8253
|
-
] })
|
|
8254
|
-
] }) : null
|
|
8310
|
+
otp ? /* @__PURE__ */ jsx38(Button33, { variant: "quiet", icon: /* @__PURE__ */ jsx38(ClockGlyph, {}), "aria-label": "Copy one-time code", title: "Copy one-time code", disabled: reading, onClick: () => void read("One-time code", async () => (await port.authenticator.code(otp)).code) }) : null
|
|
8255
8311
|
] });
|
|
8256
8312
|
}
|
|
8257
8313
|
|
|
@@ -8363,7 +8419,7 @@ function Group({ title, children }) {
|
|
|
8363
8419
|
children
|
|
8364
8420
|
] });
|
|
8365
8421
|
}
|
|
8366
|
-
function VaultSidebar({ vault, choices, onVault, view, allCount, deletedCount, views, hasFavorites, hasRecents, onView, onPanel, nativeProvider, hasNativeImport = false, hasPage = false }) {
|
|
8422
|
+
function VaultSidebar({ vault, choices, onVault, view, allCount, deletedCount, views, hasFavorites, hasRecents, onView, onPanel, nativeProvider, hasNativeImport = false, hasPage = false, onLock, onOpenWeb }) {
|
|
8367
8423
|
const [tagsOpen, setTagsOpen] = useState40(view.startsWith("tag:"));
|
|
8368
8424
|
return /* @__PURE__ */ jsxs37("nav", { "aria-label": "Vault", className: "flex h-full min-h-0 flex-col border-r border-sidebar-border bg-sidebar-background text-sidebar-foreground", children: [
|
|
8369
8425
|
/* @__PURE__ */ jsxs37("div", { className: "flex items-center gap-2 px-3 pb-2 pt-3", children: [
|
|
@@ -8402,7 +8458,9 @@ function VaultSidebar({ vault, choices, onVault, view, allCount, deletedCount, v
|
|
|
8402
8458
|
/* @__PURE__ */ jsx39(ShieldGlyph, { className: "size-4 shrink-0" }),
|
|
8403
8459
|
/* @__PURE__ */ jsx39("span", { className: "min-w-0 flex-1 truncate", children: "System AutoFill" }),
|
|
8404
8460
|
/* @__PURE__ */ jsx39("span", { className: cn15("text-xs", nativeProvider.status === "ready" ? "text-success" : "text-warning"), children: nativeProvider.status === "ready" ? "On" : "Set up" })
|
|
8405
|
-
] }) : null
|
|
8461
|
+
] }) : null,
|
|
8462
|
+
onOpenWeb ? /* @__PURE__ */ jsx39(Entry, { on: false, glyph: ExternalGlyph, label: "Open on the web", onClick: onOpenWeb }) : null,
|
|
8463
|
+
onLock ? /* @__PURE__ */ jsx39(Entry, { on: false, glyph: LockGlyph, label: "Lock", onClick: onLock }) : null
|
|
8406
8464
|
] })
|
|
8407
8465
|
] });
|
|
8408
8466
|
}
|
|
@@ -8445,12 +8503,42 @@ function ImportWithLimits(props) {
|
|
|
8445
8503
|
if (state && "limits" in state) return /* @__PURE__ */ jsx40(ImportPanel, { ...rest, limits: state.limits });
|
|
8446
8504
|
return /* @__PURE__ */ jsx40(Panel, { title: "Import", onClose: rest.onClose, children: /* @__PURE__ */ jsx40(Empty, { children: state ? state.error : "Reading this organization\u2019s import settings\u2026" }) });
|
|
8447
8505
|
}
|
|
8448
|
-
function VaultApp(
|
|
8506
|
+
function VaultApp(given) {
|
|
8507
|
+
const props = { ...given, host: useOrganizationSettings(given.host ?? NO_HOST) };
|
|
8449
8508
|
const lock = props.host?.lock;
|
|
8450
8509
|
const locked = useLocked(lock);
|
|
8451
8510
|
const port = useMemo6(() => lock ? guardPort(props.port, () => lock.locked()) : props.port, [props.port, lock]);
|
|
8452
8511
|
return /* @__PURE__ */ jsx40(LookScope, { look: props.look ?? "web", className: "h-full min-h-0 w-full", children: /* @__PURE__ */ jsx40("div", { className: "relative h-full min-h-0 w-full", children: /* @__PURE__ */ jsx40(NoticeProvider, { notify: props.notify, children: lock && locked ? /* @__PURE__ */ jsx40(LockedScreen, { lock }) : /* @__PURE__ */ jsx40(ClipboardProvider, { clipboard: props.host?.clipboard, children: /* @__PURE__ */ jsx40(RevealSecondsProvider, { seconds: props.host?.revealSeconds, children: /* @__PURE__ */ jsx40(IdentityGate, { identity: props.host?.identity, children: /* @__PURE__ */ jsx40(GeneratorLimitsProvider, { resolve: generatorLimitsFrom(props.host?.knobs), children: /* @__PURE__ */ jsx40(Workspace, { ...props, port }) }) }) }) }) }) }) });
|
|
8453
8512
|
}
|
|
8513
|
+
function useOrganizationSettings(host) {
|
|
8514
|
+
const knobs = host.knobs;
|
|
8515
|
+
const needs = knobs !== void 0 && (host.revealSeconds === void 0 || host.backupPassphraseMinLength === void 0);
|
|
8516
|
+
const [read, setRead] = useState41(null);
|
|
8517
|
+
useEffect23(() => {
|
|
8518
|
+
if (!needs || !knobs) return;
|
|
8519
|
+
let live = true;
|
|
8520
|
+
knobs().then(
|
|
8521
|
+
(r) => live && setRead({ reveal: positiveKnob(r, REVEAL_SECONDS_KNOB), backupMin: positiveKnob(r, BACKUP_PASSPHRASE_MIN_KNOB) }),
|
|
8522
|
+
() => void 0
|
|
8523
|
+
);
|
|
8524
|
+
return () => {
|
|
8525
|
+
live = false;
|
|
8526
|
+
};
|
|
8527
|
+
}, [needs, knobs]);
|
|
8528
|
+
if (!read) return host;
|
|
8529
|
+
return {
|
|
8530
|
+
...host,
|
|
8531
|
+
...host.revealSeconds === void 0 && read.reveal !== null ? { revealSeconds: read.reveal } : {},
|
|
8532
|
+
...host.backupPassphraseMinLength === void 0 && read.backupMin !== null ? { backupPassphraseMinLength: read.backupMin } : {}
|
|
8533
|
+
};
|
|
8534
|
+
}
|
|
8535
|
+
var NO_STORE = () => () => void 0;
|
|
8536
|
+
var NOTHING = () => null;
|
|
8537
|
+
function useHostPrompts(capture, fillSetup) {
|
|
8538
|
+
const prompt = useSyncExternalStore5(capture ? capture.subscribe : NO_STORE, capture ? capture.get : NOTHING, capture ? capture.get : NOTHING);
|
|
8539
|
+
const setup = useSyncExternalStore5(fillSetup ? fillSetup.subscribe : NO_STORE, fillSetup ? fillSetup.get : NOTHING, fillSetup ? fillSetup.get : NOTHING);
|
|
8540
|
+
return prompt !== null || setup?.status === "off";
|
|
8541
|
+
}
|
|
8454
8542
|
function LockedScreen({ lock }) {
|
|
8455
8543
|
const [busy, setBusy] = useState41(false);
|
|
8456
8544
|
const [error, setError] = useState41(null);
|
|
@@ -8538,6 +8626,16 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8538
8626
|
document.addEventListener("keydown", onKey);
|
|
8539
8627
|
return () => document.removeEventListener("keydown", onKey);
|
|
8540
8628
|
}, []);
|
|
8629
|
+
const keepSearchFocus = useRef19(false);
|
|
8630
|
+
useEffect23(() => {
|
|
8631
|
+
if (!keepSearchFocus.current) return;
|
|
8632
|
+
keepSearchFocus.current = false;
|
|
8633
|
+
const search = rootRef.current?.querySelector('input[aria-label^="Search"]');
|
|
8634
|
+
if (!search || document.activeElement === search) return;
|
|
8635
|
+
search.focus();
|
|
8636
|
+
search.setSelectionRange(search.value.length, search.value.length);
|
|
8637
|
+
}, [loc.q]);
|
|
8638
|
+
const hasPrompts = useHostPrompts(host.capture, host.fillSetup);
|
|
8541
8639
|
const knobsRef = useRef19(host.knobs);
|
|
8542
8640
|
knobsRef.current = host.knobs;
|
|
8543
8641
|
const [signedOut, setSignedOut] = useState41(false);
|
|
@@ -8680,6 +8778,25 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8680
8778
|
notify(e instanceof Error ? e.message : "Favorites could not be saved.", "error");
|
|
8681
8779
|
});
|
|
8682
8780
|
};
|
|
8781
|
+
const deletedItem = (id) => {
|
|
8782
|
+
setItems((cur) => cur.filter((i) => i.id !== id));
|
|
8783
|
+
dirty.current = false;
|
|
8784
|
+
if (loc.itemId === id) move({ ...loc, itemId: null, mode: "view", panel: null }, "push");
|
|
8785
|
+
notify("Moved to Trash");
|
|
8786
|
+
load();
|
|
8787
|
+
};
|
|
8788
|
+
const rowAction = (item, action) => {
|
|
8789
|
+
if (action !== "delete") return go({ view: loc.view === "page" ? "all" : loc.view, itemId: item.id, mode: "view", panel: action });
|
|
8790
|
+
void confirmDelete(item).then(async (ok) => {
|
|
8791
|
+
if (!ok) return;
|
|
8792
|
+
try {
|
|
8793
|
+
await port.remove(item);
|
|
8794
|
+
deletedItem(item.id);
|
|
8795
|
+
} catch (e) {
|
|
8796
|
+
notify(e instanceof Error && e.message ? e.message : "Deleting failed.", "error");
|
|
8797
|
+
}
|
|
8798
|
+
});
|
|
8799
|
+
};
|
|
8683
8800
|
if (error) {
|
|
8684
8801
|
return /* @__PURE__ */ jsxs38("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: [
|
|
8685
8802
|
/* @__PURE__ */ jsx40(SafeGlyph, { className: "size-8 text-muted-foreground" }),
|
|
@@ -8718,38 +8835,38 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8718
8835
|
onClick: () => go({ view: loc.view === "authenticator" ? "all" : "authenticator", itemId: null, mode: "view", panel: null })
|
|
8719
8836
|
}
|
|
8720
8837
|
),
|
|
8721
|
-
/* @__PURE__ */ jsxs38(
|
|
8722
|
-
/* @__PURE__ */ jsx40(
|
|
8723
|
-
/* @__PURE__ */ jsxs38(
|
|
8724
|
-
/* @__PURE__ */ jsxs38(
|
|
8838
|
+
/* @__PURE__ */ jsxs38(DropdownMenu5, { children: [
|
|
8839
|
+
/* @__PURE__ */ jsx40(DropdownMenuTrigger5, { asChild: true, children: /* @__PURE__ */ jsx40(Button34, { variant: "quiet", icon: /* @__PURE__ */ jsx40(MoreGlyph, {}), "aria-label": "Vault actions" }) }),
|
|
8840
|
+
/* @__PURE__ */ jsxs38(DropdownMenuContent5, { align: "end", children: [
|
|
8841
|
+
/* @__PURE__ */ jsxs38(DropdownMenuItem5, { onSelect: () => go({ panel: "import" }), children: [
|
|
8725
8842
|
/* @__PURE__ */ jsx40(ImportGlyph, { className: "size-4" }),
|
|
8726
8843
|
"Import"
|
|
8727
8844
|
] }),
|
|
8728
|
-
/* @__PURE__ */ jsxs38(
|
|
8845
|
+
/* @__PURE__ */ jsxs38(DropdownMenuItem5, { onSelect: () => go({ panel: "export" }), children: [
|
|
8729
8846
|
/* @__PURE__ */ jsx40(ExportGlyph, { className: "size-4" }),
|
|
8730
8847
|
"Export"
|
|
8731
8848
|
] }),
|
|
8732
|
-
/* @__PURE__ */ jsxs38(
|
|
8849
|
+
/* @__PURE__ */ jsxs38(DropdownMenuItem5, { onSelect: () => go({ panel: "backup" }), children: [
|
|
8733
8850
|
/* @__PURE__ */ jsx40(SafeGlyph, { className: "size-4" }),
|
|
8734
8851
|
"Backup"
|
|
8735
8852
|
] }),
|
|
8736
|
-
/* @__PURE__ */ jsxs38(
|
|
8853
|
+
/* @__PURE__ */ jsxs38(DropdownMenuItem5, { onSelect: () => go({ panel: "devices" }), children: [
|
|
8737
8854
|
/* @__PURE__ */ jsx40(ShieldGlyph, { className: "size-4" }),
|
|
8738
8855
|
"Browsers that fill"
|
|
8739
8856
|
] }),
|
|
8740
|
-
host.nativeImport ? /* @__PURE__ */ jsxs38(
|
|
8857
|
+
host.nativeImport ? /* @__PURE__ */ jsxs38(DropdownMenuItem5, { onSelect: () => go({ panel: "import-passkeys" }), children: [
|
|
8741
8858
|
/* @__PURE__ */ jsx40(ImportGlyph, { className: "size-4" }),
|
|
8742
8859
|
"Import passkeys"
|
|
8743
8860
|
] }) : null,
|
|
8744
|
-
host.nativeProvider && host.nativeProvider.status !== "unavailable" ? /* @__PURE__ */ jsxs38(
|
|
8861
|
+
host.nativeProvider && host.nativeProvider.status !== "unavailable" ? /* @__PURE__ */ jsxs38(DropdownMenuItem5, { onSelect: host.nativeProvider.openSetup, children: [
|
|
8745
8862
|
/* @__PURE__ */ jsx40(ShieldGlyph, { className: "size-4" }),
|
|
8746
8863
|
"System AutoFill"
|
|
8747
8864
|
] }) : null,
|
|
8748
|
-
host.lock?.lock ? /* @__PURE__ */ jsxs38(
|
|
8865
|
+
host.lock?.lock ? /* @__PURE__ */ jsxs38(DropdownMenuItem5, { onSelect: () => void host.lock?.lock?.(), children: [
|
|
8749
8866
|
/* @__PURE__ */ jsx40(LockGlyph, { className: "size-4" }),
|
|
8750
8867
|
"Lock"
|
|
8751
8868
|
] }) : null,
|
|
8752
|
-
host.openWebVault ? /* @__PURE__ */ jsxs38(
|
|
8869
|
+
host.openWebVault ? /* @__PURE__ */ jsxs38(DropdownMenuItem5, { onSelect: host.openWebVault, children: [
|
|
8753
8870
|
/* @__PURE__ */ jsx40(ExternalGlyph, { className: "size-4" }),
|
|
8754
8871
|
"Open on the web"
|
|
8755
8872
|
] }) : null
|
|
@@ -8763,6 +8880,27 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8763
8880
|
compactActions
|
|
8764
8881
|
] })
|
|
8765
8882
|
] });
|
|
8883
|
+
const newItem = () => go({ itemId: null, mode: "new", kind: null, panel: null });
|
|
8884
|
+
const pageHeader = /* @__PURE__ */ jsxs38("div", { className: "flex flex-col gap-2", "data-vault-page-header": "", children: [
|
|
8885
|
+
compactHeader,
|
|
8886
|
+
/* @__PURE__ */ jsxs38("div", { className: "flex items-center gap-2", children: [
|
|
8887
|
+
/* @__PURE__ */ jsx40(
|
|
8888
|
+
SearchField4,
|
|
8889
|
+
{
|
|
8890
|
+
value: loc.q,
|
|
8891
|
+
onChange: (e) => {
|
|
8892
|
+
keepSearchFocus.current = true;
|
|
8893
|
+
go({ q: e.target.value }, "replace");
|
|
8894
|
+
},
|
|
8895
|
+
placeholder: "Search the vault",
|
|
8896
|
+
"aria-label": "Search the vault",
|
|
8897
|
+
className: "min-w-0 flex-1"
|
|
8898
|
+
}
|
|
8899
|
+
),
|
|
8900
|
+
compactActions,
|
|
8901
|
+
/* @__PURE__ */ jsx40(Button34, { variant: "primary", icon: /* @__PURE__ */ jsx40(PlusGlyph, {}), "aria-label": "New item", onClick: newItem })
|
|
8902
|
+
] })
|
|
8903
|
+
] });
|
|
8766
8904
|
const viewProps = { port, host, items: inThisVault, deleted, definitions, query: loc.q, onOpen: (id) => go({ view: "all", itemId: id, mode: "view", panel: null }), onChanged: load, header: viewHeader };
|
|
8767
8905
|
const pageView = loc.view === "page" && host.page && !loc.q ? /* @__PURE__ */ jsx40(
|
|
8768
8906
|
PageView,
|
|
@@ -8770,8 +8908,6 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8770
8908
|
port,
|
|
8771
8909
|
page: host.page,
|
|
8772
8910
|
fill: host.fill,
|
|
8773
|
-
capture: host.capture,
|
|
8774
|
-
fillSetup: host.fillSetup,
|
|
8775
8911
|
newPasswordFields: host.newPasswordFields,
|
|
8776
8912
|
items: inThisVault,
|
|
8777
8913
|
definitions,
|
|
@@ -8779,10 +8915,7 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8779
8915
|
onNewForPage: (url) => go({ mode: "new", kind: null, url, itemId: null, panel: null }),
|
|
8780
8916
|
onBrowse: () => go({ view: "all", itemId: null }),
|
|
8781
8917
|
onChanged: load,
|
|
8782
|
-
|
|
8783
|
-
compactHeader,
|
|
8784
|
-
/* @__PURE__ */ jsx40("div", { className: "flex justify-end", children: compactActions })
|
|
8785
|
-
] }) } : {}
|
|
8918
|
+
header: pageHeader
|
|
8786
8919
|
}
|
|
8787
8920
|
) : null;
|
|
8788
8921
|
const specialView = pageView ?? (loc.view === "authenticator" ? /* @__PURE__ */ jsx40(AuthenticatorView, { ...viewProps }) : loc.view === "trash" ? /* @__PURE__ */ jsx40(TrashView, { ...viewProps }) : null);
|
|
@@ -8797,11 +8930,15 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8797
8930
|
selectedId: loc.itemId,
|
|
8798
8931
|
onSelect: (id) => go({ itemId: id, mode: "view", kind: null, panel: null }),
|
|
8799
8932
|
query: loc.q,
|
|
8800
|
-
onQuery: (q) =>
|
|
8933
|
+
onQuery: (q) => {
|
|
8934
|
+
if (loc.view === "page" && host.page && !q) keepSearchFocus.current = true;
|
|
8935
|
+
go({ q }, "replace");
|
|
8936
|
+
},
|
|
8801
8937
|
sort: loc.sort,
|
|
8802
8938
|
onSort: (sort) => go({ sort }, "replace"),
|
|
8803
8939
|
canSortViewed: port.lists.recents !== void 0,
|
|
8804
|
-
onNew:
|
|
8940
|
+
onNew: newItem,
|
|
8941
|
+
onItemAction: rowAction,
|
|
8805
8942
|
onRefresh: refresh,
|
|
8806
8943
|
refreshing,
|
|
8807
8944
|
...snap.pending && snap.pending.length > 0 ? { stillLoading: snap.pending } : {},
|
|
@@ -8876,13 +9013,7 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8876
9013
|
setNotice(n);
|
|
8877
9014
|
notify("Saved");
|
|
8878
9015
|
},
|
|
8879
|
-
onDeleted:
|
|
8880
|
-
setItems((cur) => cur.filter((i) => i.id !== id));
|
|
8881
|
-
dirty.current = false;
|
|
8882
|
-
move({ ...loc, itemId: null, mode: "view", panel: null }, "push");
|
|
8883
|
-
notify("Moved to Trash");
|
|
8884
|
-
load();
|
|
8885
|
-
},
|
|
9016
|
+
onDeleted: deletedItem,
|
|
8886
9017
|
onDirty: (d) => {
|
|
8887
9018
|
dirty.current = d;
|
|
8888
9019
|
},
|
|
@@ -8943,6 +9074,13 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8943
9074
|
/* @__PURE__ */ jsx40("span", { className: "min-w-0 flex-1 truncate text-warning", title: refreshError, children: "Couldn\u2019t refresh. Showing what was loaded." }),
|
|
8944
9075
|
/* @__PURE__ */ jsx40("button", { type: "button", className: "shrink-0 text-primary hover:underline", onClick: refresh, children: "Try again" })
|
|
8945
9076
|
] }) : null,
|
|
9077
|
+
hasPrompts ? (
|
|
9078
|
+
// "Save this login?" and "Turn on filling" show above the list in every view, not only "This page".
|
|
9079
|
+
/* @__PURE__ */ jsxs38("div", { className: "flex flex-col gap-3 border-b border-border px-3 py-3", "data-vault-host-prompts": "", children: [
|
|
9080
|
+
host.fillSetup ? /* @__PURE__ */ jsx40(FillSetupCard, { fillSetup: host.fillSetup }) : null,
|
|
9081
|
+
host.capture ? /* @__PURE__ */ jsx40(CaptureCard, { capture: host.capture, onChanged: load }) : null
|
|
9082
|
+
] })
|
|
9083
|
+
) : null,
|
|
8946
9084
|
snap.unavailable.length > 0 ? /* @__PURE__ */ jsxs38("div", { role: "status", className: "flex items-center gap-3 border-b border-border bg-muted px-4 py-2 text-sm", children: [
|
|
8947
9085
|
/* @__PURE__ */ jsxs38("span", { className: "min-w-0 flex-1 truncate text-warning", children: [
|
|
8948
9086
|
"Couldn\u2019t load ",
|
|
@@ -8968,7 +9106,9 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8968
9106
|
onPanel: (p) => go({ panel: p }),
|
|
8969
9107
|
nativeProvider: host.nativeProvider,
|
|
8970
9108
|
hasNativeImport: host.nativeImport !== void 0,
|
|
8971
|
-
hasPage: host.page !== void 0
|
|
9109
|
+
hasPage: host.page !== void 0,
|
|
9110
|
+
onLock: host.lock?.lock ? () => void host.lock?.lock?.() : void 0,
|
|
9111
|
+
onOpenWeb: host.openWebVault
|
|
8972
9112
|
}
|
|
8973
9113
|
) : null,
|
|
8974
9114
|
shown.list ? /* @__PURE__ */ jsx40("div", { className: specialView && mode !== "stack" ? "col-span-2 min-h-0" : "min-h-0", children: list }) : null,
|
|
@@ -9941,20 +10081,6 @@ function createApiVaultPort(hostApi, options = {}) {
|
|
|
9941
10081
|
};
|
|
9942
10082
|
}
|
|
9943
10083
|
|
|
9944
|
-
// src/knobs.ts
|
|
9945
|
-
import { createKnobReader } from "@ai-matrx/data/knobs";
|
|
9946
|
-
var FRESH_MS = 6e4;
|
|
9947
|
-
function createVaultKnobs(client, address) {
|
|
9948
|
-
const reader = createKnobReader(client);
|
|
9949
|
-
let kept = null;
|
|
9950
|
-
return async () => {
|
|
9951
|
-
if (kept && Date.now() - kept.at < FRESH_MS) return kept.resolved;
|
|
9952
|
-
const snap = await reader.snapshot(address);
|
|
9953
|
-
kept = { at: Date.now(), resolved: snap.resolved };
|
|
9954
|
-
return snap.resolved;
|
|
9955
|
-
};
|
|
9956
|
-
}
|
|
9957
|
-
|
|
9958
10084
|
// src/agent-context.ts
|
|
9959
10085
|
var hostOf = (url) => {
|
|
9960
10086
|
try {
|
|
@@ -10022,6 +10148,7 @@ function emptyReadAlarm(total, emptyIds, holdings) {
|
|
|
10022
10148
|
return `${staleAlarm(total)} (The check that tells an empty credential from an unreadable one did not answer either: ${holdings.why})`;
|
|
10023
10149
|
}
|
|
10024
10150
|
export {
|
|
10151
|
+
BACKUP_PASSPHRASE_MIN_KNOB,
|
|
10025
10152
|
CATEGORIES,
|
|
10026
10153
|
CONFIRM_RETURN_KEY,
|
|
10027
10154
|
DEFAULT_LOCATION,
|
|
@@ -10030,9 +10157,11 @@ export {
|
|
|
10030
10157
|
HOLDINGS_DOOR_MIGRATION,
|
|
10031
10158
|
IdentityGate,
|
|
10032
10159
|
LOCKED_MESSAGE,
|
|
10160
|
+
REVEAL_SECONDS_KNOB,
|
|
10033
10161
|
VaultApp,
|
|
10034
10162
|
VaultLockedError,
|
|
10035
10163
|
categoryOf,
|
|
10164
|
+
copiedLine,
|
|
10036
10165
|
copyValue,
|
|
10037
10166
|
createApiVaultPort,
|
|
10038
10167
|
createSupabaseIdentity,
|
|
@@ -10049,11 +10178,13 @@ export {
|
|
|
10049
10178
|
matchesQuery,
|
|
10050
10179
|
needsRecentSignIn,
|
|
10051
10180
|
parseDefinitions,
|
|
10181
|
+
positiveKnob,
|
|
10052
10182
|
providerOf,
|
|
10053
10183
|
rowMenuEntriesAt,
|
|
10054
10184
|
siteDomainOf,
|
|
10055
10185
|
sortItems,
|
|
10056
10186
|
useConfirmed,
|
|
10187
|
+
useDisposable,
|
|
10057
10188
|
vaultInventoryScope,
|
|
10058
10189
|
vaultItemFacts,
|
|
10059
10190
|
wasCancelled
|