@ai-matrx/vault 0.1.36 → 0.1.38
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 +24 -0
- package/dist/index.cjs +415 -305
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +387 -277
- package/dist/index.js.map +1 -1
- package/package.json +2 -23
package/dist/index.cjs
CHANGED
|
@@ -179,7 +179,7 @@ __export(src_exports, {
|
|
|
179
179
|
module.exports = __toCommonJS(src_exports);
|
|
180
180
|
|
|
181
181
|
// src/VaultApp.tsx
|
|
182
|
-
var
|
|
182
|
+
var import_react43 = require("react");
|
|
183
183
|
var import_design_system25 = require("@ai-matrx/design-system");
|
|
184
184
|
var import_controls35 = require("@ai-matrx/design-system/controls");
|
|
185
185
|
var import_confirm_opener14 = require("@ai-matrx/kit/confirm-opener");
|
|
@@ -1362,11 +1362,11 @@ function whenInDay(iso, now = /* @__PURE__ */ new Date()) {
|
|
|
1362
1362
|
if (dayKey(d) === dayKey(now)) return (0, import_format.formatRelativeTime)(iso, { now: now.getTime() });
|
|
1363
1363
|
return d.toLocaleTimeString(void 0, { hour: "numeric", minute: "2-digit" });
|
|
1364
1364
|
}
|
|
1365
|
-
function collapseRuns(rows,
|
|
1365
|
+
function collapseRuns(rows, keyOf2) {
|
|
1366
1366
|
const out = [];
|
|
1367
1367
|
const at = /* @__PURE__ */ new Map();
|
|
1368
1368
|
for (const row of rows) {
|
|
1369
|
-
const k =
|
|
1369
|
+
const k = keyOf2(row);
|
|
1370
1370
|
const seen = at.get(k);
|
|
1371
1371
|
if (seen) seen.times += 1;
|
|
1372
1372
|
else {
|
|
@@ -1889,6 +1889,14 @@ function canDecodeQrLocally() {
|
|
|
1889
1889
|
function hasCamera() {
|
|
1890
1890
|
return typeof navigator !== "undefined" && typeof navigator.mediaDevices?.getUserMedia === "function";
|
|
1891
1891
|
}
|
|
1892
|
+
async function hasCameraDevice() {
|
|
1893
|
+
if (!hasCamera() || typeof navigator.mediaDevices?.enumerateDevices !== "function") return false;
|
|
1894
|
+
try {
|
|
1895
|
+
return (await navigator.mediaDevices.enumerateDevices()).some((d) => d.kind === "videoinput");
|
|
1896
|
+
} catch {
|
|
1897
|
+
return false;
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1892
1900
|
async function decodeQr(source) {
|
|
1893
1901
|
return (0, import_qr.decodeQrFromElement)(source);
|
|
1894
1902
|
}
|
|
@@ -1920,17 +1928,15 @@ function useCanScan() {
|
|
|
1920
1928
|
}, []);
|
|
1921
1929
|
return ok;
|
|
1922
1930
|
}
|
|
1923
|
-
function
|
|
1931
|
+
function QrScanInline({ onResult, onClose }) {
|
|
1924
1932
|
const video = (0, import_react10.useRef)(null);
|
|
1925
1933
|
const [error, setError] = (0, import_react10.useState)(null);
|
|
1926
1934
|
const done = (0, import_react10.useRef)(onResult);
|
|
1927
1935
|
done.current = onResult;
|
|
1928
1936
|
(0, import_react10.useEffect)(() => {
|
|
1929
|
-
if (!open) return;
|
|
1930
1937
|
let stream = null;
|
|
1931
1938
|
let live = true;
|
|
1932
1939
|
let timer2 = null;
|
|
1933
|
-
setError(null);
|
|
1934
1940
|
const stop = () => {
|
|
1935
1941
|
if (timer2) clearTimeout(timer2);
|
|
1936
1942
|
stream?.getTracks().forEach((t) => t.stop());
|
|
@@ -1973,13 +1979,26 @@ function QrScanPanel({ open, onResult, onClose }) {
|
|
|
1973
1979
|
live = false;
|
|
1974
1980
|
stop();
|
|
1975
1981
|
};
|
|
1976
|
-
}, [
|
|
1977
|
-
|
|
1978
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("
|
|
1982
|
+
}, []);
|
|
1983
|
+
if (error) {
|
|
1984
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("p", { className: "flex items-center gap-2 px-1 pt-1 text-xs text-muted-foreground", role: "status", "data-camera-note": "", children: [
|
|
1985
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CameraGlyph, { className: "size-3.5 shrink-0", "aria-hidden": true }),
|
|
1986
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "min-w-0 flex-1 truncate", children: [
|
|
1987
|
+
error,
|
|
1988
|
+
" Paste the setup key or choose a QR image."
|
|
1989
|
+
] }),
|
|
1990
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_controls6.Button, { variant: "quiet", onClick: onClose, children: "Dismiss" })
|
|
1991
|
+
] });
|
|
1992
|
+
}
|
|
1993
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col items-center gap-1.5 pt-2", role: "region", "aria-label": "Scan QR code", "data-camera-preview": "", children: [
|
|
1994
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "relative aspect-square w-full max-w-56 overflow-hidden rounded-xl bg-muted", children: [
|
|
1979
1995
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("video", { ref: video, className: "size-full object-cover", playsInline: true, muted: true, "aria-label": "Camera" }),
|
|
1980
|
-
|
|
1996
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "pointer-events-none absolute inset-[18%] rounded-lg border-2 border-primary", "aria-hidden": true })
|
|
1981
1997
|
] }),
|
|
1982
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.
|
|
1998
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
1999
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-xs text-muted-foreground", children: "Point at the site's QR code" }),
|
|
2000
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_controls6.Button, { variant: "quiet", onClick: onClose, children: "Stop camera" })
|
|
2001
|
+
] })
|
|
1983
2002
|
] });
|
|
1984
2003
|
}
|
|
1985
2004
|
function OtpSetupRow({ value, onChange, label = "Authenticator", placeholder = "Paste setup key or otpauth link", disabled = false, autoFocus = false, onImage, onRecognized, status, autoStartCamera = false }) {
|
|
@@ -1989,8 +2008,15 @@ function OtpSetupRow({ value, onChange, label = "Authenticator", placeholder = "
|
|
|
1989
2008
|
const autoStarted = (0, import_react10.useRef)(false);
|
|
1990
2009
|
(0, import_react10.useEffect)(() => {
|
|
1991
2010
|
if (!autoStartCamera || !canScan || disabled || autoStarted.current || value) return;
|
|
1992
|
-
|
|
1993
|
-
|
|
2011
|
+
let live = true;
|
|
2012
|
+
void hasCameraDevice().then((has) => {
|
|
2013
|
+
if (!live || !has || autoStarted.current) return;
|
|
2014
|
+
autoStarted.current = true;
|
|
2015
|
+
setScanning(true);
|
|
2016
|
+
});
|
|
2017
|
+
return () => {
|
|
2018
|
+
live = false;
|
|
2019
|
+
};
|
|
1994
2020
|
}, [autoStartCamera, canScan, disabled, value]);
|
|
1995
2021
|
const [reading, setReading] = (0, import_react10.useState)(false);
|
|
1996
2022
|
const [imageError, setImageError] = (0, import_react10.useState)(null);
|
|
@@ -2092,10 +2118,9 @@ function OtpSetupRow({ value, onChange, label = "Authenticator", placeholder = "
|
|
|
2092
2118
|
]
|
|
2093
2119
|
}
|
|
2094
2120
|
),
|
|
2095
|
-
canScan ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2096
|
-
|
|
2121
|
+
canScan && scanning ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2122
|
+
QrScanInline,
|
|
2097
2123
|
{
|
|
2098
|
-
open: scanning,
|
|
2099
2124
|
onClose: () => setScanning(false),
|
|
2100
2125
|
onResult: (text) => {
|
|
2101
2126
|
setScanning(false);
|
|
@@ -3206,14 +3231,58 @@ function createVaultKnobs(client, address) {
|
|
|
3206
3231
|
}
|
|
3207
3232
|
var REVEAL_SECONDS_KNOB = "desktop.vault.reveal_hide_seconds";
|
|
3208
3233
|
var BACKUP_PASSPHRASE_MIN_KNOB = "desktop.vault.backup_passphrase_min_length";
|
|
3234
|
+
var ORGANIZATION_SEARCH_AT_KNOB = "vault.organization_search_at";
|
|
3235
|
+
var ORGANIZATION_SEARCH_AT_UNREAD = 8;
|
|
3209
3236
|
function positiveKnob(resolved, key) {
|
|
3210
3237
|
const v = resolved[key];
|
|
3211
3238
|
const n = typeof v === "string" && v.trim() !== "" ? Number(v) : v;
|
|
3212
3239
|
return typeof n === "number" && Number.isFinite(n) && n > 0 ? Math.floor(n) : null;
|
|
3213
3240
|
}
|
|
3214
3241
|
|
|
3215
|
-
// src/
|
|
3242
|
+
// src/organizations.ts
|
|
3243
|
+
var import_record_id_format = require("@ai-matrx/design-system/record-id-format");
|
|
3244
|
+
function orderOrganizations(orgs, items, recentItemIds) {
|
|
3245
|
+
const counts = /* @__PURE__ */ new Map();
|
|
3246
|
+
for (const i of items) if (i.owner.organizationId) counts.set(i.owner.organizationId, (counts.get(i.owner.organizationId) ?? 0) + 1);
|
|
3247
|
+
const byId = new Map(items.map((i) => [i.id, i]));
|
|
3248
|
+
const recent = /* @__PURE__ */ new Map();
|
|
3249
|
+
for (const id of recentItemIds ?? []) {
|
|
3250
|
+
const org = byId.get(id)?.owner.organizationId;
|
|
3251
|
+
if (org && !recent.has(org)) recent.set(org, recent.size);
|
|
3252
|
+
}
|
|
3253
|
+
const group = (o) => recent.has(o.id) ? 0 : (counts.get(o.id) ?? 0) > 0 ? 1 : 2;
|
|
3254
|
+
return [...orgs].sort((a, b) => group(a) - group(b) || (recent.get(a.id) ?? 0) - (recent.get(b.id) ?? 0) || a.name.localeCompare(b.name, void 0, { sensitivity: "base" }) || a.id.localeCompare(b.id));
|
|
3255
|
+
}
|
|
3256
|
+
function organizationHints(orgs) {
|
|
3257
|
+
const seen = /* @__PURE__ */ new Map();
|
|
3258
|
+
for (const o of orgs) seen.set(o.name.trim().toLowerCase(), (seen.get(o.name.trim().toLowerCase()) ?? 0) + 1);
|
|
3259
|
+
return new Map(orgs.filter((o) => (seen.get(o.name.trim().toLowerCase()) ?? 0) > 1).map((o) => [o.id, (0, import_record_id_format.shortUuid)(o.id)]));
|
|
3260
|
+
}
|
|
3261
|
+
|
|
3262
|
+
// src/shown-until-move.ts
|
|
3216
3263
|
var import_react16 = require("react");
|
|
3264
|
+
var keyOf = (loc) => `${String(loc.vault)}|${loc.view}|${loc.itemId ?? ""}|${loc.mode}|${loc.panel ?? ""}|${loc.kind ?? ""}`;
|
|
3265
|
+
function useShownUntilMove(loc) {
|
|
3266
|
+
const [shown, setShown] = (0, import_react16.useState)(null);
|
|
3267
|
+
const home = (0, import_react16.useRef)(null);
|
|
3268
|
+
const key = keyOf(loc);
|
|
3269
|
+
(0, import_react16.useEffect)(() => {
|
|
3270
|
+
if (!shown) {
|
|
3271
|
+
home.current = null;
|
|
3272
|
+
return;
|
|
3273
|
+
}
|
|
3274
|
+
if (home.current?.id !== shown.id) home.current = { id: shown.id, key: null };
|
|
3275
|
+
if (home.current.key === null) {
|
|
3276
|
+
if (loc.itemId === shown.id && loc.mode === "view") home.current.key = key;
|
|
3277
|
+
return;
|
|
3278
|
+
}
|
|
3279
|
+
if (key !== home.current.key) setShown(null);
|
|
3280
|
+
}, [shown, key, loc.itemId, loc.mode]);
|
|
3281
|
+
return [shown, setShown];
|
|
3282
|
+
}
|
|
3283
|
+
|
|
3284
|
+
// src/lock.ts
|
|
3285
|
+
var import_react17 = require("react");
|
|
3217
3286
|
var LOCKED_MESSAGE = "The vault is locked. Unlock it first.";
|
|
3218
3287
|
var VaultLockedError = class extends Error {
|
|
3219
3288
|
code = "vault_locked";
|
|
@@ -3248,12 +3317,12 @@ function guardPort(port, locked) {
|
|
|
3248
3317
|
var NEVER = () => () => void 0;
|
|
3249
3318
|
var UNLOCKED = () => false;
|
|
3250
3319
|
function useLocked(lock) {
|
|
3251
|
-
return (0,
|
|
3320
|
+
return (0, import_react17.useSyncExternalStore)(lock ? lock.subscribe : NEVER, lock ? () => lock.locked() : UNLOCKED, UNLOCKED);
|
|
3252
3321
|
}
|
|
3253
3322
|
|
|
3254
3323
|
// src/io/BackupPanel.tsx
|
|
3255
3324
|
var import_format6 = require("@ai-matrx/kit/format");
|
|
3256
|
-
var
|
|
3325
|
+
var import_react19 = require("react");
|
|
3257
3326
|
var import_controls13 = require("@ai-matrx/design-system/controls");
|
|
3258
3327
|
var import_download = require("@ai-matrx/kit/download");
|
|
3259
3328
|
var import_confirm_opener4 = require("@ai-matrx/kit/confirm-opener");
|
|
@@ -3346,7 +3415,7 @@ function startNewRestoreRun(preview) {
|
|
|
3346
3415
|
}
|
|
3347
3416
|
|
|
3348
3417
|
// src/io/lines.tsx
|
|
3349
|
-
var
|
|
3418
|
+
var import_react18 = require("react");
|
|
3350
3419
|
var import_design_system12 = require("@ai-matrx/design-system");
|
|
3351
3420
|
var import_controls12 = require("@ai-matrx/design-system/controls");
|
|
3352
3421
|
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
@@ -3359,7 +3428,7 @@ function PickLine({ checked, onChange, disabled = false, title, detail, badge, t
|
|
|
3359
3428
|
] });
|
|
3360
3429
|
}
|
|
3361
3430
|
function Windowed({ items, size = 150, render }) {
|
|
3362
|
-
const [all, setAll] = (0,
|
|
3431
|
+
const [all, setAll] = (0, import_react18.useState)(false);
|
|
3363
3432
|
const shown = all ? items : items.slice(0, size);
|
|
3364
3433
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
|
|
3365
3434
|
shown.map(render),
|
|
@@ -3370,7 +3439,7 @@ function Windowed({ items, size = 150, render }) {
|
|
|
3370
3439
|
] });
|
|
3371
3440
|
}
|
|
3372
3441
|
function More({ title = "More", children }) {
|
|
3373
|
-
const [open, setOpen] = (0,
|
|
3442
|
+
const [open, setOpen] = (0, import_react18.useState)(false);
|
|
3374
3443
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
3375
3444
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_controls12.DisclosureHeader, { open, title, onClick: () => setOpen((o) => !o) }),
|
|
3376
3445
|
open ? children : null
|
|
@@ -3410,21 +3479,21 @@ function Omissions({ omissions, accepted, onAccepted, verb }) {
|
|
|
3410
3479
|
function BackupPanel({ port, host, items, onClose, onChanged }) {
|
|
3411
3480
|
const minLength = passphraseMinimum(host.backupPassphraseMinLength);
|
|
3412
3481
|
const confirmed = useConfirmed();
|
|
3413
|
-
const fileInput = (0,
|
|
3414
|
-
const abort = (0,
|
|
3415
|
-
const [mode, setMode] = (0,
|
|
3416
|
-
const [busy, setBusy] = (0,
|
|
3417
|
-
const [error, setError] = (0,
|
|
3418
|
-
const [passphrase, setPassphrase] = (0,
|
|
3419
|
-
const [repeat, setRepeat] = (0,
|
|
3420
|
-
const [accepted, setAccepted] = (0,
|
|
3421
|
-
const [selected, setSelected] = (0,
|
|
3422
|
-
const [backup, setBackup] = (0,
|
|
3423
|
-
const [file, setFile] = (0,
|
|
3424
|
-
const [restorePreview, setRestorePreview] = (0,
|
|
3425
|
-
const [runId, setRunId] = (0,
|
|
3426
|
-
const [result, setResult] = (0,
|
|
3427
|
-
(0,
|
|
3482
|
+
const fileInput = (0, import_react19.useRef)(null);
|
|
3483
|
+
const abort = (0, import_react19.useRef)(null);
|
|
3484
|
+
const [mode, setMode] = (0, import_react19.useState)("backup");
|
|
3485
|
+
const [busy, setBusy] = (0, import_react19.useState)(false);
|
|
3486
|
+
const [error, setError] = (0, import_react19.useState)(null);
|
|
3487
|
+
const [passphrase, setPassphrase] = (0, import_react19.useState)("");
|
|
3488
|
+
const [repeat, setRepeat] = (0, import_react19.useState)("");
|
|
3489
|
+
const [accepted, setAccepted] = (0, import_react19.useState)(false);
|
|
3490
|
+
const [selected, setSelected] = (0, import_react19.useState)(/* @__PURE__ */ new Set());
|
|
3491
|
+
const [backup, setBackup] = (0, import_react19.useState)(null);
|
|
3492
|
+
const [file, setFile] = (0, import_react19.useState)(null);
|
|
3493
|
+
const [restorePreview, setRestorePreview] = (0, import_react19.useState)(null);
|
|
3494
|
+
const [runId, setRunId] = (0, import_react19.useState)(null);
|
|
3495
|
+
const [result, setResult] = (0, import_react19.useState)(null);
|
|
3496
|
+
(0, import_react19.useEffect)(() => () => abort.current?.abort(), []);
|
|
3428
3497
|
const switchMode = (next) => {
|
|
3429
3498
|
abort.current?.abort();
|
|
3430
3499
|
setMode(next);
|
|
@@ -3609,7 +3678,7 @@ function tooShort(passphrase, minLength) {
|
|
|
3609
3678
|
}
|
|
3610
3679
|
|
|
3611
3680
|
// src/io/ExportPanel.tsx
|
|
3612
|
-
var
|
|
3681
|
+
var import_react20 = require("react");
|
|
3613
3682
|
var import_controls14 = require("@ai-matrx/design-system/controls");
|
|
3614
3683
|
var import_download2 = require("@ai-matrx/kit/download");
|
|
3615
3684
|
var import_confirm_opener5 = require("@ai-matrx/kit/confirm-opener");
|
|
@@ -3633,12 +3702,12 @@ function omissionText2(omissions) {
|
|
|
3633
3702
|
}
|
|
3634
3703
|
function ExportPanel({ port, items, onClose }) {
|
|
3635
3704
|
const confirmed = useConfirmed();
|
|
3636
|
-
const logins = (0,
|
|
3637
|
-
const [profile, setProfile] = (0,
|
|
3638
|
-
const [selected, setSelected] = (0,
|
|
3639
|
-
const [preview, setPreview] = (0,
|
|
3640
|
-
const [busy, setBusy] = (0,
|
|
3641
|
-
const [error, setError] = (0,
|
|
3705
|
+
const logins = (0, import_react20.useMemo)(() => items.filter((i) => i.definitionKey === WEBSITE_LOGIN), [items]);
|
|
3706
|
+
const [profile, setProfile] = (0, import_react20.useState)("matrx_login_csv_v1");
|
|
3707
|
+
const [selected, setSelected] = (0, import_react20.useState)(/* @__PURE__ */ new Set());
|
|
3708
|
+
const [preview, setPreview] = (0, import_react20.useState)(null);
|
|
3709
|
+
const [busy, setBusy] = (0, import_react20.useState)(false);
|
|
3710
|
+
const [error, setError] = (0, import_react20.useState)(null);
|
|
3642
3711
|
const format = FORMATS.find((f) => f.value === profile);
|
|
3643
3712
|
const reasons = new Map(preview?.items.map((p) => [p.item_id, p]) ?? []);
|
|
3644
3713
|
const eligible = preview?.items.filter((p) => p.eligible).length ?? 0;
|
|
@@ -3763,7 +3832,7 @@ function ExportPanel({ port, items, onClose }) {
|
|
|
3763
3832
|
}
|
|
3764
3833
|
|
|
3765
3834
|
// src/io/ImportPanel.tsx
|
|
3766
|
-
var
|
|
3835
|
+
var import_react21 = require("react");
|
|
3767
3836
|
var import_controls15 = require("@ai-matrx/design-system/controls");
|
|
3768
3837
|
|
|
3769
3838
|
// src/io/csv-import.ts
|
|
@@ -4625,25 +4694,25 @@ var STATE_BADGE = {
|
|
|
4625
4694
|
var ME = "me";
|
|
4626
4695
|
function ImportPanel({ port, host, items, definitions, organizations, onClose, onChanged, limits }) {
|
|
4627
4696
|
const confirmed = useConfirmed();
|
|
4628
|
-
const [otpFor, setOtpFor] = (0,
|
|
4629
|
-
const fileInput = (0,
|
|
4630
|
-
const abort = (0,
|
|
4631
|
-
const stop = (0,
|
|
4632
|
-
const keys = (0,
|
|
4633
|
-
const [source, setSource] = (0,
|
|
4634
|
-
const [envText, setEnvText] = (0,
|
|
4635
|
-
const [injectSandbox, setInjectSandbox] = (0,
|
|
4636
|
-
const [fileName, setFileName] = (0,
|
|
4637
|
-
const [reading, setReading] = (0,
|
|
4638
|
-
const [draft, setDraft] = (0,
|
|
4639
|
-
const [destination, setDestination] = (0,
|
|
4640
|
-
const [browserFill, setBrowserFill] = (0,
|
|
4641
|
-
const [approvedVisible, setApprovedVisible] = (0,
|
|
4642
|
-
const [selected, setSelected] = (0,
|
|
4643
|
-
const [running, setRunning] = (0,
|
|
4644
|
-
const [done, setDone] = (0,
|
|
4645
|
-
const [error, setError] = (0,
|
|
4646
|
-
(0,
|
|
4697
|
+
const [otpFor, setOtpFor] = (0, import_react21.useState)(null);
|
|
4698
|
+
const fileInput = (0, import_react21.useRef)(null);
|
|
4699
|
+
const abort = (0, import_react21.useRef)(null);
|
|
4700
|
+
const stop = (0, import_react21.useRef)(false);
|
|
4701
|
+
const keys = (0, import_react21.useRef)(/* @__PURE__ */ new Map());
|
|
4702
|
+
const [source, setSource] = (0, import_react21.useState)("auto");
|
|
4703
|
+
const [envText, setEnvText] = (0, import_react21.useState)("");
|
|
4704
|
+
const [injectSandbox, setInjectSandbox] = (0, import_react21.useState)(false);
|
|
4705
|
+
const [fileName, setFileName] = (0, import_react21.useState)(null);
|
|
4706
|
+
const [reading, setReading] = (0, import_react21.useState)(false);
|
|
4707
|
+
const [draft, setDraft] = (0, import_react21.useState)(null);
|
|
4708
|
+
const [destination, setDestination] = (0, import_react21.useState)(ME);
|
|
4709
|
+
const [browserFill, setBrowserFill] = (0, import_react21.useState)(false);
|
|
4710
|
+
const [approvedVisible, setApprovedVisible] = (0, import_react21.useState)(false);
|
|
4711
|
+
const [selected, setSelected] = (0, import_react21.useState)(/* @__PURE__ */ new Set());
|
|
4712
|
+
const [running, setRunning] = (0, import_react21.useState)(null);
|
|
4713
|
+
const [done, setDone] = (0, import_react21.useState)(null);
|
|
4714
|
+
const [error, setError] = (0, import_react21.useState)(null);
|
|
4715
|
+
(0, import_react21.useEffect)(
|
|
4647
4716
|
() => () => {
|
|
4648
4717
|
abort.current?.abort();
|
|
4649
4718
|
stop.current = true;
|
|
@@ -4652,9 +4721,9 @@ function ImportPanel({ port, host, items, definitions, organizations, onClose, o
|
|
|
4652
4721
|
);
|
|
4653
4722
|
const organizationId = destination === ME ? null : destination;
|
|
4654
4723
|
const existingIn = (org) => items.filter((i) => org === null ? i.owner.kind === "me" : i.owner.organizationId === org).map((i) => ({ displayName: i.name, loginUrls: i.loginUrls }));
|
|
4655
|
-
const existing = (0,
|
|
4656
|
-
const destinationOptions = (0,
|
|
4657
|
-
const lines = (0,
|
|
4724
|
+
const existing = (0, import_react21.useMemo)(() => existingIn(organizationId), [items, organizationId]);
|
|
4725
|
+
const destinationOptions = (0, import_react21.useMemo)(() => [{ value: ME, label: "Personal" }, ...organizations.map((o) => ({ value: o.id, label: o.name }))], [organizations]);
|
|
4726
|
+
const lines = (0, import_react21.useMemo)(
|
|
4658
4727
|
() => draft?.kind === "file" ? reviewLines(draft.parsed, { organizationId, browserFill, existing, limits, mapping: draft.mapping }) : [],
|
|
4659
4728
|
[draft, organizationId, browserFill, existing, limits]
|
|
4660
4729
|
);
|
|
@@ -4930,14 +4999,14 @@ function Notices({ draft }) {
|
|
|
4930
4999
|
}
|
|
4931
5000
|
|
|
4932
5001
|
// src/ItemList.tsx
|
|
4933
|
-
var
|
|
5002
|
+
var import_react30 = require("react");
|
|
4934
5003
|
var import_design_system19 = require("@ai-matrx/design-system");
|
|
4935
5004
|
var import_design_system20 = require("@ai-matrx/design-system");
|
|
4936
5005
|
var import_controls23 = require("@ai-matrx/design-system/controls");
|
|
4937
5006
|
var import_icons12 = require("@ai-matrx/design-system/icons");
|
|
4938
5007
|
|
|
4939
5008
|
// src/ItemPane.tsx
|
|
4940
|
-
var
|
|
5009
|
+
var import_react29 = require("react");
|
|
4941
5010
|
var import_design_system17 = require("@ai-matrx/design-system");
|
|
4942
5011
|
var import_design_system18 = require("@ai-matrx/design-system");
|
|
4943
5012
|
var import_controls22 = require("@ai-matrx/design-system/controls");
|
|
@@ -4945,7 +5014,7 @@ var import_confirm_opener10 = require("@ai-matrx/kit/confirm-opener");
|
|
|
4945
5014
|
|
|
4946
5015
|
// src/activity/FilesSection.tsx
|
|
4947
5016
|
var import_format7 = require("@ai-matrx/kit/format");
|
|
4948
|
-
var
|
|
5017
|
+
var import_react22 = require("react");
|
|
4949
5018
|
var import_controls16 = require("@ai-matrx/design-system/controls");
|
|
4950
5019
|
var import_design_system13 = require("@ai-matrx/design-system");
|
|
4951
5020
|
var import_confirm_opener6 = require("@ai-matrx/kit/confirm-opener");
|
|
@@ -4963,11 +5032,11 @@ function FilesSection({ item, port, editing, onChanged }) {
|
|
|
4963
5032
|
const confirmed = useConfirmed();
|
|
4964
5033
|
const canEdit = editing && item.capabilities.canEdit;
|
|
4965
5034
|
const canAdd = item.capabilities.canEdit;
|
|
4966
|
-
const [busy, setBusy] = (0,
|
|
4967
|
-
const [error, setError] = (0,
|
|
4968
|
-
const [pending, setPending] = (0,
|
|
4969
|
-
const [dragging, setDragging] = (0,
|
|
4970
|
-
const picker = (0,
|
|
5035
|
+
const [busy, setBusy] = (0, import_react22.useState)(null);
|
|
5036
|
+
const [error, setError] = (0, import_react22.useState)(null);
|
|
5037
|
+
const [pending, setPending] = (0, import_react22.useState)(null);
|
|
5038
|
+
const [dragging, setDragging] = (0, import_react22.useState)(false);
|
|
5039
|
+
const picker = (0, import_react22.useRef)(null);
|
|
4971
5040
|
if (!canAdd && item.attachments.length === 0) return null;
|
|
4972
5041
|
async function run(key, work, fallback) {
|
|
4973
5042
|
setBusy(key);
|
|
@@ -5044,8 +5113,8 @@ function FilesSection({ item, port, editing, onChanged }) {
|
|
|
5044
5113
|
);
|
|
5045
5114
|
}
|
|
5046
5115
|
function EditableFile({ port, item: it, file: a, busy: b, run: go, onDownload, onTooBig }) {
|
|
5047
|
-
const [open, setOpen] = (0,
|
|
5048
|
-
const replacer = (0,
|
|
5116
|
+
const [open, setOpen] = (0, import_react22.useState)(false);
|
|
5117
|
+
const replacer = (0, import_react22.useRef)(null);
|
|
5049
5118
|
async function remove() {
|
|
5050
5119
|
const yes = await (0, import_confirm_opener6.confirm)({ title: `Delete ${a.label}?`, description: "The encrypted file is removed from this item.", confirmLabel: "Delete", variant: "destructive" });
|
|
5051
5120
|
if (yes) await go(`delete:${a.id}`, () => port.activity.deleteFile(it, a.id), "The file could not be deleted.");
|
|
@@ -5103,9 +5172,9 @@ function Protection({ value, locked, onChange }) {
|
|
|
5103
5172
|
);
|
|
5104
5173
|
}
|
|
5105
5174
|
function NewFile({ file, busy, onAdd, onCancel }) {
|
|
5106
|
-
const [label, setLabel] = (0,
|
|
5107
|
-
const [description, setDescription] = (0,
|
|
5108
|
-
const [handling, setHandling] = (0,
|
|
5175
|
+
const [label, setLabel] = (0, import_react22.useState)(file.name);
|
|
5176
|
+
const [description, setDescription] = (0, import_react22.useState)("");
|
|
5177
|
+
const [handling, setHandling] = (0, import_react22.useState)("revealable");
|
|
5109
5178
|
async function add() {
|
|
5110
5179
|
if (handling === "sealed" && !await confirmSeal(label)) return;
|
|
5111
5180
|
await onAdd({ label: label.trim(), description: description.trim() || null, handling });
|
|
@@ -5125,10 +5194,10 @@ function NewFile({ file, busy, onAdd, onCancel }) {
|
|
|
5125
5194
|
] });
|
|
5126
5195
|
}
|
|
5127
5196
|
function FileDetailsRows({ file, busy, onSave, onCancel }) {
|
|
5128
|
-
const [label, setLabel] = (0,
|
|
5129
|
-
const [description, setDescription] = (0,
|
|
5130
|
-
const [fileName, setFileName] = (0,
|
|
5131
|
-
const [handling, setHandling] = (0,
|
|
5197
|
+
const [label, setLabel] = (0, import_react22.useState)(file.label);
|
|
5198
|
+
const [description, setDescription] = (0, import_react22.useState)(file.description);
|
|
5199
|
+
const [fileName, setFileName] = (0, import_react22.useState)(file.fileName);
|
|
5200
|
+
const [handling, setHandling] = (0, import_react22.useState)(file.handling);
|
|
5132
5201
|
const changed = label !== file.label || description !== file.description || fileName !== file.fileName || handling !== file.handling;
|
|
5133
5202
|
async function save() {
|
|
5134
5203
|
if (handling === "sealed" && file.handling !== "sealed" && !await confirmSeal(label)) return;
|
|
@@ -5154,10 +5223,10 @@ function confirmSeal(label) {
|
|
|
5154
5223
|
});
|
|
5155
5224
|
}
|
|
5156
5225
|
function DraftFilesSection({ files, onFiles }) {
|
|
5157
|
-
const [pending, setPending] = (0,
|
|
5158
|
-
const [error, setError] = (0,
|
|
5159
|
-
const [dragging, setDragging] = (0,
|
|
5160
|
-
const picker = (0,
|
|
5226
|
+
const [pending, setPending] = (0, import_react22.useState)(null);
|
|
5227
|
+
const [error, setError] = (0, import_react22.useState)(null);
|
|
5228
|
+
const [dragging, setDragging] = (0, import_react22.useState)(false);
|
|
5229
|
+
const picker = (0, import_react22.useRef)(null);
|
|
5161
5230
|
const choose = (file) => {
|
|
5162
5231
|
if (!file) return;
|
|
5163
5232
|
if (fileTooBig(file.size)) return setError(TOO_BIG);
|
|
@@ -5206,7 +5275,7 @@ function DraftFilesSection({ files, onFiles }) {
|
|
|
5206
5275
|
}
|
|
5207
5276
|
|
|
5208
5277
|
// src/fields/RecoveryCodesRow.tsx
|
|
5209
|
-
var
|
|
5278
|
+
var import_react23 = require("react");
|
|
5210
5279
|
var import_controls17 = require("@ai-matrx/design-system/controls");
|
|
5211
5280
|
var import_icons9 = require("@ai-matrx/design-system/icons");
|
|
5212
5281
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
@@ -5216,9 +5285,9 @@ function RecoveryCodesRow({ item, field, port, onChanged }) {
|
|
|
5216
5285
|
const confirmed = useConfirmed();
|
|
5217
5286
|
const copyValue2 = useCopy();
|
|
5218
5287
|
const secret = useTransientSecret();
|
|
5219
|
-
const [busy, setBusy] = (0,
|
|
5220
|
-
const [error, setError] = (0,
|
|
5221
|
-
const [draft, setDraft] = (0,
|
|
5288
|
+
const [busy, setBusy] = (0, import_react23.useState)(false);
|
|
5289
|
+
const [error, setError] = (0, import_react23.useState)(null);
|
|
5290
|
+
const [draft, setDraft] = (0, import_react23.useState)(null);
|
|
5222
5291
|
const canEdit = item.capabilities.canEdit;
|
|
5223
5292
|
const run = async (step) => {
|
|
5224
5293
|
setBusy(true);
|
|
@@ -5313,7 +5382,7 @@ function RecoveryCodesRow({ item, field, port, onChanged }) {
|
|
|
5313
5382
|
}
|
|
5314
5383
|
|
|
5315
5384
|
// src/fields/DraftRows.tsx
|
|
5316
|
-
var
|
|
5385
|
+
var import_react24 = require("react");
|
|
5317
5386
|
var import_controls18 = require("@ai-matrx/design-system/controls");
|
|
5318
5387
|
var import_design_system14 = require("@ai-matrx/design-system");
|
|
5319
5388
|
var import_confirm_opener7 = require("@ai-matrx/kit/confirm-opener");
|
|
@@ -5368,7 +5437,7 @@ function FieldSettingsRows({ name, value, defaultHandling = "revealable", onChan
|
|
|
5368
5437
|
var hasSecretSettings = (s) => saysMore(s, "revealable");
|
|
5369
5438
|
var hasDeclaredSettings = (s, defaultHandling) => Boolean(s && saysMore(s, defaultHandling));
|
|
5370
5439
|
function SecretBuilderRow({ field, onChange, onRemove }) {
|
|
5371
|
-
const [open, setOpen] = (0,
|
|
5440
|
+
const [open, setOpen] = (0, import_react24.useState)(hasSecretSettings(field));
|
|
5372
5441
|
const handling = field.handling ?? "revealable";
|
|
5373
5442
|
const name = field.label.trim() || "Secret";
|
|
5374
5443
|
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
@@ -5609,7 +5678,7 @@ function targetLabel(t) {
|
|
|
5609
5678
|
}
|
|
5610
5679
|
|
|
5611
5680
|
// src/extension/UseOnSiteButton.tsx
|
|
5612
|
-
var
|
|
5681
|
+
var import_react25 = require("react");
|
|
5613
5682
|
var import_controls19 = require("@ai-matrx/design-system/controls");
|
|
5614
5683
|
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
5615
5684
|
function canUseOnSite(item, pageUrl) {
|
|
@@ -5617,7 +5686,7 @@ function canUseOnSite(item, pageUrl) {
|
|
|
5617
5686
|
}
|
|
5618
5687
|
function UseOnSiteButton({ port, item, pageUrl, onChanged }) {
|
|
5619
5688
|
const notify = useNotify();
|
|
5620
|
-
const [busy, setBusy] = (0,
|
|
5689
|
+
const [busy, setBusy] = (0, import_react25.useState)(false);
|
|
5621
5690
|
if (!canUseOnSite(item, pageUrl)) return null;
|
|
5622
5691
|
const site = pageSite(pageUrl);
|
|
5623
5692
|
const run = async () => {
|
|
@@ -5636,7 +5705,7 @@ function UseOnSiteButton({ port, item, pageUrl, onChanged }) {
|
|
|
5636
5705
|
}
|
|
5637
5706
|
|
|
5638
5707
|
// src/sharing/SharePanel.tsx
|
|
5639
|
-
var
|
|
5708
|
+
var import_react28 = require("react");
|
|
5640
5709
|
var import_confirm_opener9 = require("@ai-matrx/kit/confirm-opener");
|
|
5641
5710
|
var import_controls21 = require("@ai-matrx/design-system/controls");
|
|
5642
5711
|
var import_design_system16 = require("@ai-matrx/design-system");
|
|
@@ -5659,14 +5728,17 @@ function isEmail(value) {
|
|
|
5659
5728
|
}
|
|
5660
5729
|
var PERSONAL = "personal";
|
|
5661
5730
|
var destinationOf = (key) => key === PERSONAL ? null : key;
|
|
5731
|
+
var orgChoice = (o, hints) => ({ value: o.id, label: o.name, ...hints.has(o.id) ? { hint: hints.get(o.id) } : {} });
|
|
5662
5732
|
function moveDestinations(item, orgs) {
|
|
5663
5733
|
if (item.owner.kind === "shared") return [];
|
|
5664
5734
|
const here = item.owner.organizationId;
|
|
5665
|
-
|
|
5735
|
+
const hints = organizationHints(orgs);
|
|
5736
|
+
return [...here ? [{ value: PERSONAL, label: "Personal" }] : [], ...orgs.filter((o) => o.id !== here).map((o) => orgChoice(o, hints))];
|
|
5666
5737
|
}
|
|
5667
5738
|
function copyDestinations(orgs, item) {
|
|
5668
5739
|
const here = item ? item.owner.kind === "me" ? PERSONAL : item.owner.organizationId : void 0;
|
|
5669
|
-
|
|
5740
|
+
const hints = organizationHints(orgs);
|
|
5741
|
+
return [{ value: PERSONAL, label: "Personal" }, ...orgs.map((o) => orgChoice(o, hints))].filter((d) => d.value !== here);
|
|
5670
5742
|
}
|
|
5671
5743
|
function copyRefusal(message2) {
|
|
5672
5744
|
return /duplicate/i.test(message2) ? "There is already a copy of this item there." : null;
|
|
@@ -5694,7 +5766,7 @@ function shareSummary(grants) {
|
|
|
5694
5766
|
var MEMBER_CHOICE_DEFAULT = "default";
|
|
5695
5767
|
|
|
5696
5768
|
// src/sharing/parts.tsx
|
|
5697
|
-
var
|
|
5769
|
+
var import_react26 = require("react");
|
|
5698
5770
|
var import_design_system15 = require("@ai-matrx/design-system");
|
|
5699
5771
|
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
5700
5772
|
var message = (e, fallback) => {
|
|
@@ -5703,9 +5775,9 @@ var message = (e, fallback) => {
|
|
|
5703
5775
|
};
|
|
5704
5776
|
function useConfirmedChange() {
|
|
5705
5777
|
const confirmed = useConfirmed();
|
|
5706
|
-
const [busy, setBusy] = (0,
|
|
5707
|
-
const [error, setError] = (0,
|
|
5708
|
-
const [notice, setNotice] = (0,
|
|
5778
|
+
const [busy, setBusy] = (0, import_react26.useState)(null);
|
|
5779
|
+
const [error, setError] = (0, import_react26.useState)(null);
|
|
5780
|
+
const [notice, setNotice] = (0, import_react26.useState)(null);
|
|
5709
5781
|
async function run(key, fn, done) {
|
|
5710
5782
|
setBusy(key);
|
|
5711
5783
|
setError(null);
|
|
@@ -5739,18 +5811,20 @@ function StatusLine({ error, notice }) {
|
|
|
5739
5811
|
}
|
|
5740
5812
|
|
|
5741
5813
|
// src/sharing/MovePanel.tsx
|
|
5742
|
-
var
|
|
5814
|
+
var import_react27 = require("react");
|
|
5743
5815
|
var import_confirm_opener8 = require("@ai-matrx/kit/confirm-opener");
|
|
5744
5816
|
var import_controls20 = require("@ai-matrx/design-system/controls");
|
|
5745
5817
|
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
5746
5818
|
var NONE = "__none__";
|
|
5747
|
-
function MovePanel({ item, port, organizations, onClose, onChanged }) {
|
|
5819
|
+
function MovePanel({ item, port, host, organizations, onClose, onChanged, onOpenItem }) {
|
|
5748
5820
|
const { busy, error, notice, run, setNotice } = useConfirmedChange();
|
|
5749
5821
|
const moves = moveDestinations(item, organizations);
|
|
5750
5822
|
const copies = copyDestinations(organizations, item);
|
|
5751
|
-
const [moveTo, setMoveTo] = (0,
|
|
5752
|
-
const [copyTo, setCopyTo] = (0,
|
|
5753
|
-
const [email, setEmail] = (0,
|
|
5823
|
+
const [moveTo, setMoveTo] = (0, import_react27.useState)("");
|
|
5824
|
+
const [copyTo, setCopyTo] = (0, import_react27.useState)("");
|
|
5825
|
+
const [email, setEmail] = (0, import_react27.useState)("");
|
|
5826
|
+
const [made, setMade] = (0, import_react27.useState)(null);
|
|
5827
|
+
const searchAt = host.organizationSearchAt ?? ORGANIZATION_SEARCH_AT_UNREAD;
|
|
5754
5828
|
const passkey = isPasskey(item);
|
|
5755
5829
|
const canMove = item.capabilities.canManage && !passkey && moves.length > 0;
|
|
5756
5830
|
const canGive = item.capabilities.canManage && item.owner.kind === "me" && !passkey;
|
|
@@ -5784,8 +5858,10 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
|
|
|
5784
5858
|
};
|
|
5785
5859
|
const copy = async () => {
|
|
5786
5860
|
if (!copyChoice) return;
|
|
5787
|
-
const
|
|
5788
|
-
if (
|
|
5861
|
+
const copied = await run("copy", () => port.sharing.copy(item, destinationOf(copyChoice.value)), `Copy made in ${copyChoice.label}`);
|
|
5862
|
+
if (!copied) return;
|
|
5863
|
+
setMade(copied);
|
|
5864
|
+
onChanged();
|
|
5789
5865
|
};
|
|
5790
5866
|
const nothing = !canMove && !canGive && !canCopy;
|
|
5791
5867
|
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
@@ -5794,7 +5870,10 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
|
|
|
5794
5870
|
title: "Move or copy",
|
|
5795
5871
|
size: "md",
|
|
5796
5872
|
onClose,
|
|
5797
|
-
footer: /* @__PURE__ */ (0, import_jsx_runtime25.
|
|
5873
|
+
footer: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(PanelFooter, { status: error || notice ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(StatusLine, { error, notice }) : null, children: [
|
|
5874
|
+
made && onOpenItem ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Button, { variant: "outline", onClick: () => onOpenItem(made), children: "Open copy" }) : null,
|
|
5875
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Button, { variant: "primary", onClick: onClose, children: "Done" })
|
|
5876
|
+
] }),
|
|
5798
5877
|
children: nothing ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(VaultSection, { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Empty, { children: passkey ? "A passkey stays where it was created." : "Only the owner can move or give this item." }) }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(VaultSection, { children: [
|
|
5799
5878
|
canMove && moves.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5800
5879
|
VaultRow,
|
|
@@ -5802,7 +5881,7 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
|
|
|
5802
5881
|
label: "Move to",
|
|
5803
5882
|
hint: moveChoice ? itemMoveConsequence(item, destinationOf(moveChoice.value)) : void 0,
|
|
5804
5883
|
actions: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Button, { variant: "outline", disabled: busy !== null || !moveChoice, onClick: () => void move(), children: "Move" }),
|
|
5805
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Select, { className: "w-full", "aria-label": "Move to", value: moveTo || NONE, onValueChange: (v) => setMoveTo(v === NONE ? "" : v), options: [{ value: NONE, label: "Choose where" }, ...moves] })
|
|
5884
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Select, { className: "w-full", "aria-label": "Move to", searchAt, value: moveTo || NONE, onValueChange: (v) => setMoveTo(v === NONE ? "" : v), options: [{ value: NONE, label: "Choose where" }, ...moves] })
|
|
5806
5885
|
}
|
|
5807
5886
|
) : null,
|
|
5808
5887
|
canGive ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(VaultRow, { label: "Give to", hint: "You lose all access; your shares end", actions: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Button, { variant: "danger", disabled: busy !== null || !isEmail(email), onClick: () => void give(), children: "Give" }), children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
@@ -5819,7 +5898,7 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
|
|
|
5819
5898
|
onChange: (e) => setEmail(e.target.value)
|
|
5820
5899
|
}
|
|
5821
5900
|
) }) : null,
|
|
5822
|
-
canCopy && copies.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(VaultRow, { label: "Copy to", hint: "A separate item; edits no longer sync", actions: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Button, { variant: "outline", disabled: busy !== null || !copyChoice, onClick: () => void copy(), children: "Copy" }), children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Select, { className: "w-full", "aria-label": "Copy to", value: copyTo || NONE, onValueChange: (v) => setCopyTo(v === NONE ? "" : v), options: [{ value: NONE, label: "Choose where" }, ...copies] }) }) : null
|
|
5901
|
+
canCopy && copies.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(VaultRow, { label: "Copy to", hint: "A separate item; edits no longer sync", actions: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Button, { variant: "outline", disabled: busy !== null || !copyChoice, onClick: () => void copy(), children: "Copy" }), children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Select, { className: "w-full", "aria-label": "Copy to", searchAt, value: copyTo || NONE, onValueChange: (v) => setCopyTo(v === NONE ? "" : v), options: [{ value: NONE, label: "Choose where" }, ...copies] }) }) : null
|
|
5823
5902
|
] })
|
|
5824
5903
|
}
|
|
5825
5904
|
);
|
|
@@ -5828,11 +5907,11 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
|
|
|
5828
5907
|
// src/sharing/SharePanel.tsx
|
|
5829
5908
|
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
5830
5909
|
function useGrants(port, item) {
|
|
5831
|
-
const [grants, setGrants] = (0,
|
|
5832
|
-
const [loadError, setLoadError] = (0,
|
|
5833
|
-
const [nonce, setNonce] = (0,
|
|
5910
|
+
const [grants, setGrants] = (0, import_react28.useState)(null);
|
|
5911
|
+
const [loadError, setLoadError] = (0, import_react28.useState)(null);
|
|
5912
|
+
const [nonce, setNonce] = (0, import_react28.useState)(0);
|
|
5834
5913
|
const allowed = item.capabilities.canManage;
|
|
5835
|
-
(0,
|
|
5914
|
+
(0, import_react28.useEffect)(() => {
|
|
5836
5915
|
if (!allowed) return;
|
|
5837
5916
|
let live = true;
|
|
5838
5917
|
setLoadError(null);
|
|
@@ -5849,9 +5928,9 @@ function useGrants(port, item) {
|
|
|
5849
5928
|
function SharePanel({ item, port, organizations, onClose, onChanged }) {
|
|
5850
5929
|
const { grants, setGrants, loadError, reload } = useGrants(port, item);
|
|
5851
5930
|
const { busy, error, notice, run } = useConfirmedChange();
|
|
5852
|
-
const [email, setEmail] = (0,
|
|
5853
|
-
const [level, setLevel] = (0,
|
|
5854
|
-
const [more, setMore] = (0,
|
|
5931
|
+
const [email, setEmail] = (0, import_react28.useState)("");
|
|
5932
|
+
const [level, setLevel] = (0, import_react28.useState)("use");
|
|
5933
|
+
const [more, setMore] = (0, import_react28.useState)(false);
|
|
5855
5934
|
const isOrg = item.owner.kind === "organization" && item.owner.organizationId !== null;
|
|
5856
5935
|
const orgName = item.owner.label;
|
|
5857
5936
|
const people = (grants ?? []).filter((g) => g.kind === "person");
|
|
@@ -5970,8 +6049,8 @@ function SharePanel({ item, port, organizations, onClose, onChanged }) {
|
|
|
5970
6049
|
function IntoOrganization({ item, port, organizations, grants, onShared }) {
|
|
5971
6050
|
const { busy, error, notice, run } = useConfirmedChange();
|
|
5972
6051
|
const open = organizations.filter((o) => !grants.some((g) => g.organizationId === o.id));
|
|
5973
|
-
const [target, setTarget] = (0,
|
|
5974
|
-
const [level, setLevel] = (0,
|
|
6052
|
+
const [target, setTarget] = (0, import_react28.useState)("");
|
|
6053
|
+
const [level, setLevel] = (0, import_react28.useState)("use");
|
|
5975
6054
|
const chosen = open.find((o) => o.id === target);
|
|
5976
6055
|
if (item.owner.kind !== "me") return null;
|
|
5977
6056
|
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(VaultSection, { title: "Share into organization", children: open.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
|
|
@@ -6006,10 +6085,10 @@ var CHOICES = [
|
|
|
6006
6085
|
{ value: "editor", label: "Can edit", meta: "See and change" }
|
|
6007
6086
|
];
|
|
6008
6087
|
function MemberAccess({ port, organizationId, organizationName }) {
|
|
6009
|
-
const [list, setList] = (0,
|
|
6010
|
-
const [loadError, setLoadError] = (0,
|
|
6088
|
+
const [list, setList] = (0, import_react28.useState)(null);
|
|
6089
|
+
const [loadError, setLoadError] = (0, import_react28.useState)(null);
|
|
6011
6090
|
const { busy, error, run } = useConfirmedChange();
|
|
6012
|
-
(0,
|
|
6091
|
+
(0, import_react28.useEffect)(() => {
|
|
6013
6092
|
let live = true;
|
|
6014
6093
|
port.sharing.memberAccess(organizationId).then(
|
|
6015
6094
|
(l) => live && setList(l),
|
|
@@ -6041,9 +6120,9 @@ function MemberAccess({ port, organizationId, organizationName }) {
|
|
|
6041
6120
|
] });
|
|
6042
6121
|
}
|
|
6043
6122
|
function SharingSummary({ item, port, className }) {
|
|
6044
|
-
const [text, setText] = (0,
|
|
6123
|
+
const [text, setText] = (0, import_react28.useState)("");
|
|
6045
6124
|
const allowed = item.capabilities.canManage;
|
|
6046
|
-
(0,
|
|
6125
|
+
(0, import_react28.useEffect)(() => {
|
|
6047
6126
|
if (!allowed) return;
|
|
6048
6127
|
let live = true;
|
|
6049
6128
|
port.sharing.grants(item).then(
|
|
@@ -6074,8 +6153,8 @@ function ItemPane(props) {
|
|
|
6074
6153
|
const editing = mode !== "view";
|
|
6075
6154
|
const seedName = seed?.name ?? "";
|
|
6076
6155
|
const seedUrl = seed?.url ?? "";
|
|
6077
|
-
const [loaded, setLoaded] = (0,
|
|
6078
|
-
const base = (0,
|
|
6156
|
+
const [loaded, setLoaded] = (0, import_react29.useState)({});
|
|
6157
|
+
const base = (0, import_react29.useMemo)(() => {
|
|
6079
6158
|
const b = draftOf(item);
|
|
6080
6159
|
if (!item) {
|
|
6081
6160
|
b.name = seedName;
|
|
@@ -6084,28 +6163,28 @@ function ItemPane(props) {
|
|
|
6084
6163
|
b.values = { ...loaded };
|
|
6085
6164
|
return b;
|
|
6086
6165
|
}, [item, seedName, seedUrl, loaded]);
|
|
6087
|
-
const [draft, setDraft] = (0,
|
|
6088
|
-
const [tagsText, setTagsText] = (0,
|
|
6089
|
-
const [showTags, setShowTags] = (0,
|
|
6090
|
-
const [showDescription, setShowDescription] = (0,
|
|
6091
|
-
const [showRecovery, setShowRecovery] = (0,
|
|
6092
|
-
const [settingUpOtp, setSettingUpOtp] = (0,
|
|
6093
|
-
const [owner, setOwner] = (0,
|
|
6094
|
-
const [recipient, setRecipient] = (0,
|
|
6095
|
-
const [generatePrivately, setGeneratePrivately] = (0,
|
|
6096
|
-
const [busy, setBusy] = (0,
|
|
6097
|
-
const [sent, setSent] = (0,
|
|
6098
|
-
const [queuedFiles, setQueuedFiles] = (0,
|
|
6099
|
-
const [showBrowser, setShowBrowser] = (0,
|
|
6100
|
-
const [error, setError] = (0,
|
|
6101
|
-
const [destinations, setDestinations] = (0,
|
|
6102
|
-
const [savedNew, setSavedNew] = (0,
|
|
6166
|
+
const [draft, setDraft] = (0, import_react29.useState)(base);
|
|
6167
|
+
const [tagsText, setTagsText] = (0, import_react29.useState)(base.tags.join(", "));
|
|
6168
|
+
const [showTags, setShowTags] = (0, import_react29.useState)(false);
|
|
6169
|
+
const [showDescription, setShowDescription] = (0, import_react29.useState)(false);
|
|
6170
|
+
const [showRecovery, setShowRecovery] = (0, import_react29.useState)(false);
|
|
6171
|
+
const [settingUpOtp, setSettingUpOtp] = (0, import_react29.useState)(false);
|
|
6172
|
+
const [owner, setOwner] = (0, import_react29.useState)(defaultOwner ?? "me");
|
|
6173
|
+
const [recipient, setRecipient] = (0, import_react29.useState)("");
|
|
6174
|
+
const [generatePrivately, setGeneratePrivately] = (0, import_react29.useState)(false);
|
|
6175
|
+
const [busy, setBusy] = (0, import_react29.useState)(false);
|
|
6176
|
+
const [sent, setSent] = (0, import_react29.useState)(null);
|
|
6177
|
+
const [queuedFiles, setQueuedFiles] = (0, import_react29.useState)([]);
|
|
6178
|
+
const [showBrowser, setShowBrowser] = (0, import_react29.useState)(false);
|
|
6179
|
+
const [error, setError] = (0, import_react29.useState)(null);
|
|
6180
|
+
const [destinations, setDestinations] = (0, import_react29.useState)({});
|
|
6181
|
+
const [savedNew, setSavedNew] = (0, import_react29.useState)(false);
|
|
6103
6182
|
const dirty = editing && !savedNew && isDirty(base, draft);
|
|
6104
6183
|
const declared = definition?.fields ?? [];
|
|
6105
|
-
const prev = (0,
|
|
6106
|
-
const paneRef = (0,
|
|
6184
|
+
const prev = (0, import_react29.useRef)(null);
|
|
6185
|
+
const paneRef = (0, import_react29.useRef)(null);
|
|
6107
6186
|
const room = useRoomOf(paneRef);
|
|
6108
|
-
(0,
|
|
6187
|
+
(0, import_react29.useEffect)(() => {
|
|
6109
6188
|
const was = prev.current;
|
|
6110
6189
|
const id = item?.id ?? null;
|
|
6111
6190
|
if (was && was.id === id && was.mode === mode && editing) {
|
|
@@ -6118,22 +6197,22 @@ function ItemPane(props) {
|
|
|
6118
6197
|
}
|
|
6119
6198
|
prev.current = { base, id, mode };
|
|
6120
6199
|
}, [base, mode, item?.id, editing]);
|
|
6121
|
-
(0,
|
|
6200
|
+
(0, import_react29.useEffect)(() => {
|
|
6122
6201
|
setLoaded({});
|
|
6123
6202
|
setShowTags(false);
|
|
6124
6203
|
setShowDescription(false);
|
|
6125
6204
|
setShowRecovery(false);
|
|
6126
6205
|
setSavedNew(false);
|
|
6127
6206
|
}, [item?.id, mode]);
|
|
6128
|
-
const onDirtyRef = (0,
|
|
6207
|
+
const onDirtyRef = (0, import_react29.useRef)(onDirty);
|
|
6129
6208
|
onDirtyRef.current = onDirty;
|
|
6130
|
-
(0,
|
|
6209
|
+
(0, import_react29.useEffect)(() => onDirtyRef.current(dirty), [dirty]);
|
|
6131
6210
|
const keepKey = draftKey(item?.id ?? null, definition?.key ?? item?.definitionKey ?? null);
|
|
6132
|
-
(0,
|
|
6211
|
+
(0, import_react29.useEffect)(() => {
|
|
6133
6212
|
if (editing && dirty) (0, import_drafts.keepDraft)(keepKey, keptFieldsOf(draft), { basedOn: item?.updatedAt ?? "new" });
|
|
6134
6213
|
else if (!editing) (0, import_drafts.dropKeptDraft)(keepKey);
|
|
6135
6214
|
}, [editing, dirty, draft, keepKey, item?.updatedAt]);
|
|
6136
|
-
(0,
|
|
6215
|
+
(0, import_react29.useEffect)(() => {
|
|
6137
6216
|
if (!editing || !item) return;
|
|
6138
6217
|
let live = true;
|
|
6139
6218
|
for (const f of item.fields) {
|
|
@@ -6258,7 +6337,7 @@ function ItemPane(props) {
|
|
|
6258
6337
|
const turnOnOne = canTurnOn ? (f) => () => turnOn([f]) : () => void 0;
|
|
6259
6338
|
const declaredKeys = new Set(declared.map((f) => f.key));
|
|
6260
6339
|
const hasSecureNote = declaredKeys.has(SECURE_NOTE_KEY) || Boolean(item?.fields.some((f) => f.key === SECURE_NOTE_KEY)) || draft.secrets.some((x) => x.key === SECURE_NOTE_KEY);
|
|
6261
|
-
const [settingsToggled, setSettingsToggled] = (0,
|
|
6340
|
+
const [settingsToggled, setSettingsToggled] = (0, import_react29.useState)(/* @__PURE__ */ new Set());
|
|
6262
6341
|
const settingsOpen = (f) => settingsToggled.has(f.key) !== (definition?.key === ENV_VALUE_KEY || hasDeclaredSettings(draft.fieldSettings?.[f.key], f.handling));
|
|
6263
6342
|
const toggleSettings = (key) => setSettingsToggled((cur) => {
|
|
6264
6343
|
const next = new Set(cur);
|
|
@@ -6413,7 +6492,7 @@ function ItemPane(props) {
|
|
|
6413
6492
|
const hidden = existing && existing.handling !== "visible" && !(f.key in loaded);
|
|
6414
6493
|
const newSecret = mode === "new" && f.storage === "encrypted" && owner !== "person";
|
|
6415
6494
|
const open = newSecret && settingsOpen(f);
|
|
6416
|
-
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
6495
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_react29.Fragment, { children: [
|
|
6417
6496
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6418
6497
|
EditRow,
|
|
6419
6498
|
{
|
|
@@ -6635,8 +6714,8 @@ function ItemList({ title, items, definitions, port, selectedId, onSelect, query
|
|
|
6635
6714
|
const pinned = matchingIds ? items.filter((i) => matchingIds.has(i.id)) : [];
|
|
6636
6715
|
const rest = matchingIds ? items.filter((i) => !matchingIds.has(i.id)) : items;
|
|
6637
6716
|
const ordered = [...pinned, ...rest];
|
|
6638
|
-
const listRef = (0,
|
|
6639
|
-
(0,
|
|
6717
|
+
const listRef = (0, import_react30.useRef)(null);
|
|
6718
|
+
(0, import_react30.useEffect)(() => {
|
|
6640
6719
|
if (selectedId) listRef.current?.querySelector(`[data-item="${selectedId}"]`)?.scrollIntoView({ block: "nearest" });
|
|
6641
6720
|
}, [selectedId, items.length]);
|
|
6642
6721
|
const familyOf2 = (key) => definitions.find((d) => d.key === key)?.family ?? "generic";
|
|
@@ -6699,8 +6778,8 @@ function ListRow({ item, family, port, on, onSelect, withOwner, ownContextMenu,
|
|
|
6699
6778
|
const confirmed = useConfirmed();
|
|
6700
6779
|
const copy = useCopy();
|
|
6701
6780
|
const notify = useNotify();
|
|
6702
|
-
const [busy, setBusy] = (0,
|
|
6703
|
-
const [menuOpen, setMenuOpen] = (0,
|
|
6781
|
+
const [busy, setBusy] = (0, import_react30.useState)(false);
|
|
6782
|
+
const [menuOpen, setMenuOpen] = (0, import_react30.useState)(false);
|
|
6704
6783
|
const canUse = item.capabilities.canUse;
|
|
6705
6784
|
const user = canUse ? item.fields.find((f) => USERNAME_KEYS.test(f.key) && f.handling !== "sealed" && f.active !== false) : void 0;
|
|
6706
6785
|
const secret = canUse && item.capabilities.canReveal ? item.fields.find((f) => f.key === "password" && f.handling === "revealable" && f.active !== false) : void 0;
|
|
@@ -6739,7 +6818,7 @@ function ListRow({ item, family, port, on, onSelect, withOwner, ownContextMenu,
|
|
|
6739
6818
|
...manageEntries(item, onAction),
|
|
6740
6819
|
...hostEntries.map((h) => ({ ...h, kind: h.kind ?? "host" }))
|
|
6741
6820
|
];
|
|
6742
|
-
const entriesRef = (0,
|
|
6821
|
+
const entriesRef = (0, import_react30.useRef)(entries);
|
|
6743
6822
|
entriesRef.current = entries;
|
|
6744
6823
|
const glyphOf = (e) => e.id === "copy:username" ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(UserGlyph, { className: "size-4" }) : e.id === "copy:password" ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(KeyGlyph, { className: "size-4" }) : e.id === "copy:code" ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ClockGlyph, { className: "size-4" }) : e.kind === "favorite" ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(StarGlyph, { className: (0, import_design_system20.cn)("size-4", favorite?.on && "fill-current text-warning") }) : e.kind === "open" ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ChevronRightGlyph, { className: "size-4" }) : e.kind === "host" || e.kind === "manage" ? null : /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_icons12.CopyIcon, { className: "size-4" });
|
|
6745
6824
|
const menuItem = (e) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_design_system19.DropdownMenuItem, { disabled: e.disabled ?? false, onSelect: e.onSelect, children: [
|
|
@@ -6776,10 +6855,11 @@ function ListRow({ item, family, port, on, onSelect, withOwner, ownContextMenu,
|
|
|
6776
6855
|
}
|
|
6777
6856
|
),
|
|
6778
6857
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "absolute right-1.5 top-1/2 flex -translate-y-1/2 items-center gap-0.5", "data-surface": on ? "primary" : void 0, children: [
|
|
6779
|
-
user || secret || favorite ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: (0, import_design_system20.cn)("hidden items-center gap-0.5 rounded-md pl-2 [@media(hover:hover)]:group-hover:flex [@media(hover:hover)]:group-focus-within:flex", on ? "bg-primary" : "bg-accent"), "data-row-quick": "", children: [
|
|
6858
|
+
user || secret || code || favorite ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: (0, import_design_system20.cn)("hidden items-center gap-0.5 rounded-md pl-2 [@media(hover:hover)]:group-hover:flex [@media(hover:hover)]:group-focus-within:flex", on ? "bg-primary" : "bg-accent"), "data-row-quick": "", children: [
|
|
6780
6859
|
favorite ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_controls23.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(StarGlyph, { className: favorite.on ? "fill-current text-warning" : "" }), "aria-label": favorite.on ? "Remove from favorites" : "Add to favorites", "aria-pressed": favorite.on, onClick: favorite.toggle }) : null,
|
|
6781
6860
|
user ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_controls23.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(UserGlyph, {}), "aria-label": `Copy ${user.label}`, disabled: busy, onClick: copyUser }) : null,
|
|
6782
|
-
secret ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_controls23.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(KeyGlyph, {}), "aria-label": "Copy password", disabled: busy, onClick: copyPassword }) : null
|
|
6861
|
+
secret ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_controls23.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(KeyGlyph, {}), "aria-label": "Copy password", disabled: busy, onClick: copyPassword }) : null,
|
|
6862
|
+
code ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_controls23.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ClockGlyph, {}), "aria-label": "Copy one-time code", disabled: busy, onClick: copyCode }) : null
|
|
6783
6863
|
] }) : null,
|
|
6784
6864
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_design_system19.DropdownMenu, { open: menuOpen, onOpenChange: setMenuOpen, children: [
|
|
6785
6865
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_design_system19.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
@@ -6820,7 +6900,7 @@ function manageEntries(item, onAction) {
|
|
|
6820
6900
|
}
|
|
6821
6901
|
|
|
6822
6902
|
// src/lists/TrashView.tsx
|
|
6823
|
-
var
|
|
6903
|
+
var import_react32 = require("react");
|
|
6824
6904
|
var import_controls25 = require("@ai-matrx/design-system/controls");
|
|
6825
6905
|
var import_format9 = require("@ai-matrx/kit/format");
|
|
6826
6906
|
|
|
@@ -6894,7 +6974,7 @@ function refusalText(reason) {
|
|
|
6894
6974
|
}
|
|
6895
6975
|
|
|
6896
6976
|
// src/lists/RestorePanel.tsx
|
|
6897
|
-
var
|
|
6977
|
+
var import_react31 = require("react");
|
|
6898
6978
|
var import_controls24 = require("@ai-matrx/design-system/controls");
|
|
6899
6979
|
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
6900
6980
|
var count = (n, one) => `${n} ${one}${n === 1 ? "" : "s"}`;
|
|
@@ -6905,13 +6985,13 @@ function RestorePanel({
|
|
|
6905
6985
|
turnOn,
|
|
6906
6986
|
onClose
|
|
6907
6987
|
}) {
|
|
6908
|
-
const [preview, setPreview] = (0,
|
|
6909
|
-
const [restored, setRestored] = (0,
|
|
6910
|
-
const [turnedOn, setTurnedOn] = (0,
|
|
6911
|
-
const [error, setError] = (0,
|
|
6912
|
-
const [busy, setBusy] = (0,
|
|
6913
|
-
const [loading, setLoading] = (0,
|
|
6914
|
-
(0,
|
|
6988
|
+
const [preview, setPreview] = (0, import_react31.useState)(null);
|
|
6989
|
+
const [restored, setRestored] = (0, import_react31.useState)(null);
|
|
6990
|
+
const [turnedOn, setTurnedOn] = (0, import_react31.useState)(null);
|
|
6991
|
+
const [error, setError] = (0, import_react31.useState)(null);
|
|
6992
|
+
const [busy, setBusy] = (0, import_react31.useState)(false);
|
|
6993
|
+
const [loading, setLoading] = (0, import_react31.useState)(Boolean(lists.preview));
|
|
6994
|
+
(0, import_react31.useEffect)(() => {
|
|
6915
6995
|
if (!lists.preview) return;
|
|
6916
6996
|
let live = true;
|
|
6917
6997
|
lists.preview(item).then(
|
|
@@ -7015,10 +7095,10 @@ function trashLineOf(item) {
|
|
|
7015
7095
|
}
|
|
7016
7096
|
function TrashView({ port, deleted, query, header, onChanged }) {
|
|
7017
7097
|
const confirmed = useConfirmed();
|
|
7018
|
-
const [busyId, setBusyId] = (0,
|
|
7019
|
-
const [message2, setMessage] = (0,
|
|
7098
|
+
const [busyId, setBusyId] = (0, import_react32.useState)(null);
|
|
7099
|
+
const [message2, setMessage] = (0, import_react32.useState)(null);
|
|
7020
7100
|
const shown = deleted.filter((i) => trashItemMatchesQuery(i, query));
|
|
7021
|
-
const [restoring, setRestoring] = (0,
|
|
7101
|
+
const [restoring, setRestoring] = (0, import_react32.useState)(null);
|
|
7022
7102
|
const restore = async (item, deletionId) => {
|
|
7023
7103
|
setBusyId(item.id);
|
|
7024
7104
|
setMessage(null);
|
|
@@ -7066,15 +7146,15 @@ function TrashView({ port, deleted, query, header, onChanged }) {
|
|
|
7066
7146
|
}
|
|
7067
7147
|
|
|
7068
7148
|
// src/NewItemFlow.tsx
|
|
7069
|
-
var
|
|
7149
|
+
var import_react33 = require("react");
|
|
7070
7150
|
var import_controls26 = require("@ai-matrx/design-system/controls");
|
|
7071
7151
|
var import_icons13 = require("@ai-matrx/design-system/icons");
|
|
7072
7152
|
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
7073
7153
|
function NewItemFlow({ definitions, url, onUrl, onChoose, onCancel }) {
|
|
7074
|
-
const [search, setSearch] = (0,
|
|
7075
|
-
const guess = (0,
|
|
7154
|
+
const [search, setSearch] = (0, import_react33.useState)("");
|
|
7155
|
+
const guess = (0, import_react33.useMemo)(() => inferFromUrl(url, definitions), [url, definitions]);
|
|
7076
7156
|
const common = COMMON_DEFINITION_KEYS.map((k) => definitions.find((d) => d.key === k)).filter((d) => d !== void 0);
|
|
7077
|
-
const matches = (0,
|
|
7157
|
+
const matches = (0, import_react33.useMemo)(() => {
|
|
7078
7158
|
const q = search.trim().toLowerCase();
|
|
7079
7159
|
if (!q) return [];
|
|
7080
7160
|
return definitions.filter((d) => `${d.label} ${d.key} ${d.providerKey ?? ""} ${FAMILY_LABELS[d.family] ?? ""}`.toLowerCase().includes(q)).slice(0, 60);
|
|
@@ -7145,7 +7225,7 @@ function NewItemFlow({ definitions, url, onUrl, onChoose, onCancel }) {
|
|
|
7145
7225
|
}
|
|
7146
7226
|
|
|
7147
7227
|
// src/sharing/SecureLinkPanel.tsx
|
|
7148
|
-
var
|
|
7228
|
+
var import_react34 = require("react");
|
|
7149
7229
|
var import_confirm_opener11 = require("@ai-matrx/kit/confirm-opener");
|
|
7150
7230
|
var import_design_system21 = require("@ai-matrx/design-system");
|
|
7151
7231
|
var import_controls27 = require("@ai-matrx/design-system/controls");
|
|
@@ -7228,20 +7308,20 @@ var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
|
7228
7308
|
function SecureLinkPanel({ item, port, onClose }) {
|
|
7229
7309
|
const sharing = port.sharing;
|
|
7230
7310
|
const { busy, error, notice, run, setNotice } = useConfirmedChange();
|
|
7231
|
-
const [remedy, setRemedy] = (0,
|
|
7232
|
-
const [options, setOptions] = (0,
|
|
7233
|
-
const [optionsError, setOptionsError] = (0,
|
|
7234
|
-
const [sent, setSent] = (0,
|
|
7235
|
-
const [sentError, setSentError] = (0,
|
|
7236
|
-
const [nonce, setNonce] = (0,
|
|
7237
|
-
const [email, setEmail] = (0,
|
|
7238
|
-
const [phone, setPhone] = (0,
|
|
7239
|
-
const [name, setName] = (0,
|
|
7240
|
-
const [linkBy, setLinkBy] = (0,
|
|
7241
|
-
const [fields, setFields] = (0,
|
|
7242
|
-
const [note, setNote] = (0,
|
|
7243
|
-
const [sameChannelSent, setSameChannelSent] = (0,
|
|
7244
|
-
(0,
|
|
7311
|
+
const [remedy, setRemedy] = (0, import_react34.useState)(null);
|
|
7312
|
+
const [options, setOptions] = (0, import_react34.useState)(null);
|
|
7313
|
+
const [optionsError, setOptionsError] = (0, import_react34.useState)(null);
|
|
7314
|
+
const [sent, setSent] = (0, import_react34.useState)(null);
|
|
7315
|
+
const [sentError, setSentError] = (0, import_react34.useState)(null);
|
|
7316
|
+
const [nonce, setNonce] = (0, import_react34.useState)(0);
|
|
7317
|
+
const [email, setEmail] = (0, import_react34.useState)("");
|
|
7318
|
+
const [phone, setPhone] = (0, import_react34.useState)("");
|
|
7319
|
+
const [name, setName] = (0, import_react34.useState)("");
|
|
7320
|
+
const [linkBy, setLinkBy] = (0, import_react34.useState)("email");
|
|
7321
|
+
const [fields, setFields] = (0, import_react34.useState)([]);
|
|
7322
|
+
const [note, setNote] = (0, import_react34.useState)("");
|
|
7323
|
+
const [sameChannelSent, setSameChannelSent] = (0, import_react34.useState)(false);
|
|
7324
|
+
(0, import_react34.useEffect)(() => {
|
|
7245
7325
|
let live = true;
|
|
7246
7326
|
setOptionsError(null);
|
|
7247
7327
|
sharing.secureLinkOptions(item).then(
|
|
@@ -7256,7 +7336,7 @@ function SecureLinkPanel({ item, port, onClose }) {
|
|
|
7256
7336
|
live = false;
|
|
7257
7337
|
};
|
|
7258
7338
|
}, [sharing, item]);
|
|
7259
|
-
(0,
|
|
7339
|
+
(0, import_react34.useEffect)(() => {
|
|
7260
7340
|
const list = sharing.sentSecureLinks;
|
|
7261
7341
|
if (!list) return;
|
|
7262
7342
|
let live = true;
|
|
@@ -7269,9 +7349,9 @@ function SecureLinkPanel({ item, port, onClose }) {
|
|
|
7269
7349
|
live = false;
|
|
7270
7350
|
};
|
|
7271
7351
|
}, [sharing, item, nonce]);
|
|
7272
|
-
const [phoneTyped, setPhoneTyped] = (0,
|
|
7273
|
-
const prefilled = (0,
|
|
7274
|
-
(0,
|
|
7352
|
+
const [phoneTyped, setPhoneTyped] = (0, import_react34.useState)(false);
|
|
7353
|
+
const prefilled = (0, import_react34.useRef)(false);
|
|
7354
|
+
(0, import_react34.useEffect)(() => {
|
|
7275
7355
|
const lookup = sharing.phoneOnFile;
|
|
7276
7356
|
if (!lookup || phoneTyped) return;
|
|
7277
7357
|
const clear = () => {
|
|
@@ -7424,7 +7504,7 @@ function sentMeta(row, options) {
|
|
|
7424
7504
|
}
|
|
7425
7505
|
|
|
7426
7506
|
// src/devices/DevicesPanel.tsx
|
|
7427
|
-
var
|
|
7507
|
+
var import_react35 = require("react");
|
|
7428
7508
|
var import_confirm_opener12 = require("@ai-matrx/kit/confirm-opener");
|
|
7429
7509
|
var import_controls28 = require("@ai-matrx/design-system/controls");
|
|
7430
7510
|
var import_format12 = require("@ai-matrx/kit/format");
|
|
@@ -7515,10 +7595,10 @@ function ErrorLine2({ text }) {
|
|
|
7515
7595
|
function DevicesPanel({ port, onClose }) {
|
|
7516
7596
|
const confirmed = useConfirmed();
|
|
7517
7597
|
const notify = useNotify();
|
|
7518
|
-
const [devices, setDevices] = (0,
|
|
7519
|
-
const [error, setError] = (0,
|
|
7520
|
-
const [busyId, setBusyId] = (0,
|
|
7521
|
-
const load = (0,
|
|
7598
|
+
const [devices, setDevices] = (0, import_react35.useState)(null);
|
|
7599
|
+
const [error, setError] = (0, import_react35.useState)(null);
|
|
7600
|
+
const [busyId, setBusyId] = (0, import_react35.useState)(null);
|
|
7601
|
+
const load = (0, import_react35.useCallback)(async () => {
|
|
7522
7602
|
setError(null);
|
|
7523
7603
|
try {
|
|
7524
7604
|
setDevices(await port.devices.list());
|
|
@@ -7526,7 +7606,7 @@ function DevicesPanel({ port, onClose }) {
|
|
|
7526
7606
|
setError(messageOf3(e, "Your browsers could not be read."));
|
|
7527
7607
|
}
|
|
7528
7608
|
}, [port]);
|
|
7529
|
-
(0,
|
|
7609
|
+
(0, import_react35.useEffect)(() => {
|
|
7530
7610
|
void load();
|
|
7531
7611
|
}, [load]);
|
|
7532
7612
|
const revoke = async (device) => {
|
|
@@ -7584,11 +7664,11 @@ function ApprovePanel({ port, host, onClose, approvalKey, label, kind = "browser
|
|
|
7584
7664
|
const where = isMac ? "the Mac app" : "the extension";
|
|
7585
7665
|
const passkeys = port.devices.passkeys;
|
|
7586
7666
|
const here = passkeys?.available() ?? false;
|
|
7587
|
-
const [methods, setMethods] = (0,
|
|
7588
|
-
const [busy, setBusy] = (0,
|
|
7589
|
-
const [error, setError] = (0,
|
|
7590
|
-
const [approvedUntil, setApprovedUntil] = (0,
|
|
7591
|
-
const load = (0,
|
|
7667
|
+
const [methods, setMethods] = (0, import_react35.useState)(null);
|
|
7668
|
+
const [busy, setBusy] = (0, import_react35.useState)(null);
|
|
7669
|
+
const [error, setError] = (0, import_react35.useState)(null);
|
|
7670
|
+
const [approvedUntil, setApprovedUntil] = (0, import_react35.useState)(null);
|
|
7671
|
+
const load = (0, import_react35.useCallback)(async () => {
|
|
7592
7672
|
setError(null);
|
|
7593
7673
|
try {
|
|
7594
7674
|
setMethods(await port.devices.stepUpMethods());
|
|
@@ -7596,7 +7676,7 @@ function ApprovePanel({ port, host, onClose, approvalKey, label, kind = "browser
|
|
|
7596
7676
|
setError(messageOf3(e, "Your account could not be checked."));
|
|
7597
7677
|
}
|
|
7598
7678
|
}, [port]);
|
|
7599
|
-
(0,
|
|
7679
|
+
(0, import_react35.useEffect)(() => {
|
|
7600
7680
|
if (key && here) void load();
|
|
7601
7681
|
}, [key, here, load]);
|
|
7602
7682
|
const approve = async () => {
|
|
@@ -7684,7 +7764,7 @@ function ApprovePanel({ port, host, onClose, approvalKey, label, kind = "browser
|
|
|
7684
7764
|
}
|
|
7685
7765
|
|
|
7686
7766
|
// src/native/NativeImportPanel.tsx
|
|
7687
|
-
var
|
|
7767
|
+
var import_react37 = require("react");
|
|
7688
7768
|
var import_confirm_opener13 = require("@ai-matrx/kit/confirm-opener");
|
|
7689
7769
|
var import_controls29 = require("@ai-matrx/design-system/controls");
|
|
7690
7770
|
|
|
@@ -7747,19 +7827,19 @@ async function loadFullPreview(bridge, operationId, current) {
|
|
|
7747
7827
|
}
|
|
7748
7828
|
|
|
7749
7829
|
// src/native/use-native-import.ts
|
|
7750
|
-
var
|
|
7830
|
+
var import_react36 = require("react");
|
|
7751
7831
|
var fail = (e, fallback) => e instanceof Error && e.message ? e.message : fallback;
|
|
7752
7832
|
var RESTART = "Your account changed. The import was stopped; start it again.";
|
|
7753
7833
|
function useNativeImport(bridge, stillAllowed, onImported) {
|
|
7754
|
-
const [screen, setScreen] = (0,
|
|
7755
|
-
const [busy, setBusy] = (0,
|
|
7756
|
-
const generation = (0,
|
|
7757
|
-
const mounted = (0,
|
|
7758
|
-
const op = (0,
|
|
7759
|
-
const last = (0,
|
|
7760
|
-
const timer2 = (0,
|
|
7761
|
-
const polls = (0,
|
|
7762
|
-
const refreshRef = (0,
|
|
7834
|
+
const [screen, setScreen] = (0, import_react36.useState)({ kind: "idle", message: null });
|
|
7835
|
+
const [busy, setBusy] = (0, import_react36.useState)(false);
|
|
7836
|
+
const generation = (0, import_react36.useRef)(0);
|
|
7837
|
+
const mounted = (0, import_react36.useRef)(false);
|
|
7838
|
+
const op = (0, import_react36.useRef)(null);
|
|
7839
|
+
const last = (0, import_react36.useRef)(null);
|
|
7840
|
+
const timer2 = (0, import_react36.useRef)(null);
|
|
7841
|
+
const polls = (0, import_react36.useRef)(0);
|
|
7842
|
+
const refreshRef = (0, import_react36.useRef)(async () => void 0);
|
|
7763
7843
|
const current = (g) => mounted.current && g === generation.current;
|
|
7764
7844
|
const stopPolling = () => {
|
|
7765
7845
|
if (timer2.current !== null) clearTimeout(timer2.current);
|
|
@@ -7928,9 +8008,9 @@ function useNativeImport(bridge, stillAllowed, onImported) {
|
|
|
7928
8008
|
setBusy(false);
|
|
7929
8009
|
setScreen({ kind: "idle", message: null });
|
|
7930
8010
|
};
|
|
7931
|
-
const invalidateRef = (0,
|
|
8011
|
+
const invalidateRef = (0, import_react36.useRef)(invalidate);
|
|
7932
8012
|
invalidateRef.current = invalidate;
|
|
7933
|
-
(0,
|
|
8013
|
+
(0, import_react36.useEffect)(() => {
|
|
7934
8014
|
mounted.current = true;
|
|
7935
8015
|
const off = bridge.subscribe?.(() => {
|
|
7936
8016
|
if (op.current) invalidateRef.current(RESTART);
|
|
@@ -7962,14 +8042,14 @@ function NativeImportPanel({ bridge, readLimits, activeOrganizationId, organizat
|
|
|
7962
8042
|
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Importer, { bridge, readLimits, activeOrganizationId, organizations, onClose, onChanged });
|
|
7963
8043
|
}
|
|
7964
8044
|
function Importer({ bridge, readLimits, activeOrganizationId, organizations, onClose, onChanged }) {
|
|
7965
|
-
const options = (0,
|
|
7966
|
-
const [organizationId, setOrganizationId] = (0,
|
|
7967
|
-
const [limits, setLimits] = (0,
|
|
7968
|
-
const [limitError, setLimitError] = (0,
|
|
8045
|
+
const options = (0, import_react37.useMemo)(() => organizations.map((o) => ({ value: o.id, label: o.name })), [organizations]);
|
|
8046
|
+
const [organizationId, setOrganizationId] = (0, import_react37.useState)(() => organizations.some((o) => o.id === activeOrganizationId) ? activeOrganizationId : organizations[0]?.id ?? "");
|
|
8047
|
+
const [limits, setLimits] = (0, import_react37.useState)(null);
|
|
8048
|
+
const [limitError, setLimitError] = (0, import_react37.useState)(null);
|
|
7969
8049
|
const flow = useNativeImport(bridge, (id) => organizations.some((o) => o.id === id), onChanged);
|
|
7970
8050
|
const { screen, busy } = flow;
|
|
7971
8051
|
const orgName = organizations.find((o) => o.id === organizationId)?.name ?? "this organization";
|
|
7972
|
-
(0,
|
|
8052
|
+
(0, import_react37.useEffect)(() => {
|
|
7973
8053
|
if (!readLimits || !organizationId) return;
|
|
7974
8054
|
let live = true;
|
|
7975
8055
|
setLimits(null);
|
|
@@ -8030,21 +8110,21 @@ function Importer({ bridge, readLimits, activeOrganizationId, organizations, onC
|
|
|
8030
8110
|
}
|
|
8031
8111
|
|
|
8032
8112
|
// src/extension/PageView.tsx
|
|
8033
|
-
var
|
|
8113
|
+
var import_react41 = require("react");
|
|
8034
8114
|
var import_design_system23 = require("@ai-matrx/design-system");
|
|
8035
8115
|
var import_controls33 = require("@ai-matrx/design-system/controls");
|
|
8036
8116
|
var import_icons15 = require("@ai-matrx/design-system/icons");
|
|
8037
8117
|
|
|
8038
8118
|
// src/extension/CaptureCard.tsx
|
|
8039
|
-
var
|
|
8119
|
+
var import_react38 = require("react");
|
|
8040
8120
|
var import_controls30 = require("@ai-matrx/design-system/controls");
|
|
8041
8121
|
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
8042
8122
|
var SEARCH_FROM = 4;
|
|
8043
8123
|
function CaptureCard({ capture, onChanged }) {
|
|
8044
|
-
const prompt = (0,
|
|
8124
|
+
const prompt = (0, import_react38.useSyncExternalStore)(capture.subscribe, capture.get, capture.get);
|
|
8045
8125
|
const notify = useNotify();
|
|
8046
|
-
const [busy, setBusy] = (0,
|
|
8047
|
-
const [q, setQ] = (0,
|
|
8126
|
+
const [busy, setBusy] = (0, import_react38.useState)(false);
|
|
8127
|
+
const [q, setQ] = (0, import_react38.useState)("");
|
|
8048
8128
|
if (!prompt) return null;
|
|
8049
8129
|
const decide = async (d) => {
|
|
8050
8130
|
setBusy(true);
|
|
@@ -8100,15 +8180,15 @@ function CaptureCard({ capture, onChanged }) {
|
|
|
8100
8180
|
}
|
|
8101
8181
|
|
|
8102
8182
|
// src/extension/FillSetupCard.tsx
|
|
8103
|
-
var
|
|
8183
|
+
var import_react39 = require("react");
|
|
8104
8184
|
var import_controls31 = require("@ai-matrx/design-system/controls");
|
|
8105
8185
|
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
8106
8186
|
function FillSetupCard({ fillSetup }) {
|
|
8107
8187
|
const notify = useNotify();
|
|
8108
|
-
const state = (0,
|
|
8109
|
-
const box = (0,
|
|
8110
|
-
const [busy, setBusy] = (0,
|
|
8111
|
-
const [error, setError] = (0,
|
|
8188
|
+
const state = (0, import_react39.useSyncExternalStore)(fillSetup.subscribe, fillSetup.get, fillSetup.get);
|
|
8189
|
+
const box = (0, import_react39.useRef)(null);
|
|
8190
|
+
const [busy, setBusy] = (0, import_react39.useState)(false);
|
|
8191
|
+
const [error, setError] = (0, import_react39.useState)(null);
|
|
8112
8192
|
if (state.status !== "off") return null;
|
|
8113
8193
|
const finish = async (run) => {
|
|
8114
8194
|
setBusy(true);
|
|
@@ -8173,7 +8253,7 @@ function FillSetupCard({ fillSetup }) {
|
|
|
8173
8253
|
}
|
|
8174
8254
|
|
|
8175
8255
|
// src/extension/PageGenerator.tsx
|
|
8176
|
-
var
|
|
8256
|
+
var import_react40 = require("react");
|
|
8177
8257
|
var import_design_system22 = require("@ai-matrx/design-system");
|
|
8178
8258
|
var import_controls32 = require("@ai-matrx/design-system/controls");
|
|
8179
8259
|
var import_icons14 = require("@ai-matrx/design-system/icons");
|
|
@@ -8183,10 +8263,10 @@ function PageGenerator({ fields }) {
|
|
|
8183
8263
|
const limits = useGeneratorLimitsSource();
|
|
8184
8264
|
const copy = useCopy();
|
|
8185
8265
|
const held = useTransientSecret(HOLD_MS);
|
|
8186
|
-
const [open, setOpen] = (0,
|
|
8187
|
-
const [busy, setBusy] = (0,
|
|
8188
|
-
const [targets, setTargets] = (0,
|
|
8189
|
-
const [said, setSaid] = (0,
|
|
8266
|
+
const [open, setOpen] = (0, import_react40.useState)(false);
|
|
8267
|
+
const [busy, setBusy] = (0, import_react40.useState)(false);
|
|
8268
|
+
const [targets, setTargets] = (0, import_react40.useState)([]);
|
|
8269
|
+
const [said, setSaid] = (0, import_react40.useState)(null);
|
|
8190
8270
|
if (!limits) return null;
|
|
8191
8271
|
const say3 = setSaid;
|
|
8192
8272
|
const put = async (targetId, value2) => {
|
|
@@ -8250,8 +8330,8 @@ function PageGenerator({ fields }) {
|
|
|
8250
8330
|
// src/extension/PageView.tsx
|
|
8251
8331
|
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
8252
8332
|
function PageView({ port, page, fill, capture, fillSetup, newPasswordFields, items, definitions, onOpen, onNewForPage, onBrowse, onChanged, header }) {
|
|
8253
|
-
const [running, setRunning] = (0,
|
|
8254
|
-
const [said, setSaid] = (0,
|
|
8333
|
+
const [running, setRunning] = (0, import_react41.useState)(null);
|
|
8334
|
+
const [said, setSaid] = (0, import_react41.useState)(null);
|
|
8255
8335
|
const site = pageSite(page.url);
|
|
8256
8336
|
const state = page.matchState ?? { status: "ready" };
|
|
8257
8337
|
const fillable = new Set(page.fillableItemIds ?? page.matchingItemIds);
|
|
@@ -8335,7 +8415,7 @@ function MatchRow({ itemId, item, tag, family, port, busy, running, onOpen, onFi
|
|
|
8335
8415
|
const confirmed = useConfirmed();
|
|
8336
8416
|
const copy = useCopy();
|
|
8337
8417
|
const notify = useNotify();
|
|
8338
|
-
const [reading, setReading] = (0,
|
|
8418
|
+
const [reading, setReading] = (0, import_react41.useState)(false);
|
|
8339
8419
|
const usable = item?.capabilities.canUse ?? false;
|
|
8340
8420
|
const user = usable ? item?.fields.find((f) => USERNAME_KEYS.test(f.key) && f.handling !== "sealed" && f.active) : void 0;
|
|
8341
8421
|
const secret = usable && item?.capabilities.canReveal ? item?.fields.find((f) => f.key === "password" && f.handling === "revealable" && f.active) : void 0;
|
|
@@ -8373,7 +8453,7 @@ function MatchRow({ itemId, item, tag, family, port, busy, running, onOpen, onFi
|
|
|
8373
8453
|
}
|
|
8374
8454
|
|
|
8375
8455
|
// src/Sidebar.tsx
|
|
8376
|
-
var
|
|
8456
|
+
var import_react42 = require("react");
|
|
8377
8457
|
var import_design_system24 = require("@ai-matrx/design-system");
|
|
8378
8458
|
var import_controls34 = require("@ai-matrx/design-system/controls");
|
|
8379
8459
|
var import_icons16 = require("@ai-matrx/design-system/icons");
|
|
@@ -8382,6 +8462,7 @@ var AUTHENTICATOR_LABEL = "Authenticator";
|
|
|
8382
8462
|
function vaultChoices(items, organizations, _current) {
|
|
8383
8463
|
const n = (f) => items.filter(f).length;
|
|
8384
8464
|
const shared = n((i) => i.owner.kind === "shared");
|
|
8465
|
+
const hints = organizationHints(organizations);
|
|
8385
8466
|
return [
|
|
8386
8467
|
{ value: "all", label: "All items", count: items.length },
|
|
8387
8468
|
{ value: "mine", label: "Personal", count: n((i) => i.owner.kind === "me") },
|
|
@@ -8389,11 +8470,11 @@ function vaultChoices(items, organizations, _current) {
|
|
|
8389
8470
|
// Every organization the person belongs to, empty ones too: an empty vault opens on its own
|
|
8390
8471
|
// "Nothing here yet" with New item, so the first credential can go there. (The organization
|
|
8391
8472
|
// list carries no role, so who may add is the server's answer to the save, said in place.)
|
|
8392
|
-
...organizations.map((o) => ({ value: o.id, label: o.name, count: n((i) => i.owner.organizationId === o.id) }))
|
|
8473
|
+
...organizations.map((o) => ({ value: o.id, label: o.name, count: n((i) => i.owner.organizationId === o.id), ...hints.has(o.id) ? { hint: hints.get(o.id) } : {} }))
|
|
8393
8474
|
];
|
|
8394
8475
|
}
|
|
8395
|
-
function VaultSelect({ value, choices, onChange }) {
|
|
8396
|
-
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_controls34.Select, { value, onValueChange: onChange, "aria-label": "Vault", options: choices.map((c) => ({ value: c.value, label: c.label, meta: String(c.count) })) });
|
|
8476
|
+
function VaultSelect({ value, choices, onChange, searchAt = ORGANIZATION_SEARCH_AT_UNREAD }) {
|
|
8477
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_controls34.Select, { value, onValueChange: onChange, "aria-label": "Vault", searchAt, options: choices.map((c) => ({ value: c.value, label: c.label, meta: String(c.count), ...c.hint ? { hint: c.hint } : {} })) });
|
|
8397
8478
|
}
|
|
8398
8479
|
var CATEGORY_GLYPHS = { logins: import_icons16.GlobeIcon, passkeys: ShieldGlyph, api: KeyGlyph, oauth: PlugGlyph, infra: DatabaseGlyph, env: TerminalGlyph, files: FileGlyph, other: NoteGlyph };
|
|
8399
8480
|
var familyOf = (key, definitions) => definitions.find((d) => d.key === key)?.family ?? "generic";
|
|
@@ -8484,12 +8565,12 @@ function Group({ title, children }) {
|
|
|
8484
8565
|
children
|
|
8485
8566
|
] });
|
|
8486
8567
|
}
|
|
8487
|
-
function VaultSidebar({ vault, choices, onVault, view, allCount, deletedCount, views, hasFavorites, hasRecents, onView, onPanel, nativeProvider, hasNativeImport = false, hasPage = false, onLock, onOpenWeb }) {
|
|
8488
|
-
const [tagsOpen, setTagsOpen] = (0,
|
|
8568
|
+
function VaultSidebar({ vault, choices, onVault, organizationSearchAt, view, allCount, deletedCount, views, hasFavorites, hasRecents, onView, onPanel, nativeProvider, hasNativeImport = false, hasPage = false, onLock, onOpenWeb }) {
|
|
8569
|
+
const [tagsOpen, setTagsOpen] = (0, import_react42.useState)(view.startsWith("tag:"));
|
|
8489
8570
|
return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("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: [
|
|
8490
8571
|
/* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex items-center gap-2 px-3 pb-2 pt-3", children: [
|
|
8491
8572
|
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(SafeGlyph, { className: "size-5 shrink-0 text-primary" }),
|
|
8492
|
-
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(VaultSelect, { value: vault, choices, onChange: onVault }) })
|
|
8573
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(VaultSelect, { value: vault, choices, onChange: onVault, searchAt: organizationSearchAt }) })
|
|
8493
8574
|
] }),
|
|
8494
8575
|
/* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex min-h-0 flex-1 flex-col gap-5 overflow-y-auto px-2 pb-3 pt-1", children: [
|
|
8495
8576
|
/* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-col gap-0.5", children: [
|
|
@@ -8566,8 +8647,8 @@ var generatorLimitsFrom = (knobs) => knobs ? async () => {
|
|
|
8566
8647
|
} : void 0;
|
|
8567
8648
|
function ImportWithLimits(props) {
|
|
8568
8649
|
const { knobs, ...rest } = props;
|
|
8569
|
-
const [state, setState] = (0,
|
|
8570
|
-
(0,
|
|
8650
|
+
const [state, setState] = (0, import_react43.useState)(null);
|
|
8651
|
+
(0, import_react43.useEffect)(() => {
|
|
8571
8652
|
if (!knobs) return setState({ error: "Import is not set up for this organization yet." });
|
|
8572
8653
|
knobs().then(
|
|
8573
8654
|
(r) => {
|
|
@@ -8587,18 +8668,18 @@ function VaultApp(given) {
|
|
|
8587
8668
|
const props = { ...given, host: useOrganizationSettings(given.host ?? NO_HOST) };
|
|
8588
8669
|
const lock = props.host?.lock;
|
|
8589
8670
|
const locked = useLocked(lock);
|
|
8590
|
-
const port = (0,
|
|
8671
|
+
const port = (0, import_react43.useMemo)(() => lock ? guardPort(props.port, () => lock.locked()) : props.port, [props.port, lock]);
|
|
8591
8672
|
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system25.LookScope, { look: props.look ?? "web", className: "h-full min-h-0 w-full", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "relative h-full min-h-0 w-full", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(NoticeProvider, { notify: props.notify, children: lock && locked ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(LockedScreen, { lock }) : /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ClipboardProvider, { clipboard: props.host?.clipboard, children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(RevealSecondsProvider, { seconds: props.host?.revealSeconds, children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(IdentityGate, { identity: props.host?.identity, children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(GeneratorLimitsProvider, { resolve: generatorLimitsFrom(props.host?.knobs), children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Workspace, { ...props, port }) }) }) }) }) }) }) });
|
|
8592
8673
|
}
|
|
8593
8674
|
function useOrganizationSettings(host) {
|
|
8594
8675
|
const knobs = host.knobs;
|
|
8595
|
-
const needs = knobs !== void 0 && (host.revealSeconds === void 0 || host.backupPassphraseMinLength === void 0);
|
|
8596
|
-
const [read, setRead] = (0,
|
|
8597
|
-
(0,
|
|
8676
|
+
const needs = knobs !== void 0 && (host.revealSeconds === void 0 || host.backupPassphraseMinLength === void 0 || host.organizationSearchAt === void 0);
|
|
8677
|
+
const [read, setRead] = (0, import_react43.useState)(null);
|
|
8678
|
+
(0, import_react43.useEffect)(() => {
|
|
8598
8679
|
if (!needs || !knobs) return;
|
|
8599
8680
|
let live = true;
|
|
8600
8681
|
knobs().then(
|
|
8601
|
-
(r) => live && setRead({ reveal: positiveKnob(r, REVEAL_SECONDS_KNOB), backupMin: positiveKnob(r, BACKUP_PASSPHRASE_MIN_KNOB) }),
|
|
8682
|
+
(r) => live && setRead({ reveal: positiveKnob(r, REVEAL_SECONDS_KNOB), backupMin: positiveKnob(r, BACKUP_PASSPHRASE_MIN_KNOB), searchAt: positiveKnob(r, ORGANIZATION_SEARCH_AT_KNOB) }),
|
|
8602
8683
|
() => void 0
|
|
8603
8684
|
);
|
|
8604
8685
|
return () => {
|
|
@@ -8609,19 +8690,20 @@ function useOrganizationSettings(host) {
|
|
|
8609
8690
|
return {
|
|
8610
8691
|
...host,
|
|
8611
8692
|
...host.revealSeconds === void 0 && read.reveal !== null ? { revealSeconds: read.reveal } : {},
|
|
8612
|
-
...host.backupPassphraseMinLength === void 0 && read.backupMin !== null ? { backupPassphraseMinLength: read.backupMin } : {}
|
|
8693
|
+
...host.backupPassphraseMinLength === void 0 && read.backupMin !== null ? { backupPassphraseMinLength: read.backupMin } : {},
|
|
8694
|
+
...host.organizationSearchAt === void 0 && read.searchAt !== null ? { organizationSearchAt: read.searchAt } : {}
|
|
8613
8695
|
};
|
|
8614
8696
|
}
|
|
8615
8697
|
var NO_STORE = () => () => void 0;
|
|
8616
8698
|
var NOTHING = () => null;
|
|
8617
8699
|
function useHostPrompts(capture, fillSetup) {
|
|
8618
|
-
const prompt = (0,
|
|
8619
|
-
const setup = (0,
|
|
8700
|
+
const prompt = (0, import_react43.useSyncExternalStore)(capture ? capture.subscribe : NO_STORE, capture ? capture.get : NOTHING, capture ? capture.get : NOTHING);
|
|
8701
|
+
const setup = (0, import_react43.useSyncExternalStore)(fillSetup ? fillSetup.subscribe : NO_STORE, fillSetup ? fillSetup.get : NOTHING, fillSetup ? fillSetup.get : NOTHING);
|
|
8620
8702
|
return prompt !== null || setup?.status === "off";
|
|
8621
8703
|
}
|
|
8622
8704
|
function LockedScreen({ lock }) {
|
|
8623
|
-
const [busy, setBusy] = (0,
|
|
8624
|
-
const [error, setError] = (0,
|
|
8705
|
+
const [busy, setBusy] = (0, import_react43.useState)(false);
|
|
8706
|
+
const [error, setError] = (0, import_react43.useState)(null);
|
|
8625
8707
|
const unlock = async () => {
|
|
8626
8708
|
setBusy(true);
|
|
8627
8709
|
setError(null);
|
|
@@ -8641,29 +8723,29 @@ function LockedScreen({ lock }) {
|
|
|
8641
8723
|
] });
|
|
8642
8724
|
}
|
|
8643
8725
|
function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocationChange, onInventory }) {
|
|
8644
|
-
const rootRef = (0,
|
|
8726
|
+
const rootRef = (0, import_react43.useRef)(null);
|
|
8645
8727
|
const width = useElementWidth(rootRef);
|
|
8646
8728
|
const mode = layout !== "auto" ? layout : width >= FULL_AT ? "full" : width >= SPLIT_AT ? "split" : "stack";
|
|
8647
8729
|
const notify = useNotify();
|
|
8648
|
-
const [snap, setSnap] = (0,
|
|
8649
|
-
const [items, setItems] = (0,
|
|
8650
|
-
const [deleted, setDeleted] = (0,
|
|
8651
|
-
const [favorites, setFavorites] = (0,
|
|
8652
|
-
const [recents, setRecents] = (0,
|
|
8653
|
-
const [error, setError] = (0,
|
|
8654
|
-
const [inner, setInner] = (0,
|
|
8730
|
+
const [snap, setSnap] = (0, import_react43.useState)(null);
|
|
8731
|
+
const [items, setItems] = (0, import_react43.useState)([]);
|
|
8732
|
+
const [deleted, setDeleted] = (0, import_react43.useState)([]);
|
|
8733
|
+
const [favorites, setFavorites] = (0, import_react43.useState)(null);
|
|
8734
|
+
const [recents, setRecents] = (0, import_react43.useState)(null);
|
|
8735
|
+
const [error, setError] = (0, import_react43.useState)(null);
|
|
8736
|
+
const [inner, setInner] = (0, import_react43.useState)(DEFAULT_LOCATION);
|
|
8655
8737
|
const loc = location ?? inner;
|
|
8656
|
-
const dirty = (0,
|
|
8657
|
-
const [notice, setNotice] = (0,
|
|
8658
|
-
const [firstCode, setFirstCode] = (
|
|
8659
|
-
const move = (0,
|
|
8738
|
+
const dirty = (0, import_react43.useRef)(false);
|
|
8739
|
+
const [notice, setNotice] = (0, import_react43.useState)(null);
|
|
8740
|
+
const [firstCode, setFirstCode] = useShownUntilMove(loc);
|
|
8741
|
+
const move = (0, import_react43.useCallback)(
|
|
8660
8742
|
(next, how) => {
|
|
8661
8743
|
if (!location) setInner(next);
|
|
8662
8744
|
onLocationChange?.(next, how);
|
|
8663
8745
|
},
|
|
8664
8746
|
[location, onLocationChange]
|
|
8665
8747
|
);
|
|
8666
|
-
const go = (0,
|
|
8748
|
+
const go = (0, import_react43.useCallback)(
|
|
8667
8749
|
(patch, how = "push") => {
|
|
8668
8750
|
const leaving = patch.itemId !== void 0 || patch.mode !== void 0 || patch.vault !== void 0 || patch.view !== void 0;
|
|
8669
8751
|
const next = { ...loc, ...patch };
|
|
@@ -8682,9 +8764,9 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8682
8764
|
},
|
|
8683
8765
|
[loc, move]
|
|
8684
8766
|
);
|
|
8685
|
-
const keyState = (0,
|
|
8767
|
+
const keyState = (0, import_react43.useRef)({ loc, go });
|
|
8686
8768
|
keyState.current = { loc, go };
|
|
8687
|
-
(0,
|
|
8769
|
+
(0, import_react43.useEffect)(() => {
|
|
8688
8770
|
const onKey = (e) => {
|
|
8689
8771
|
if (e.defaultPrevented || e.metaKey || e.ctrlKey || e.altKey) return;
|
|
8690
8772
|
const root = rootRef.current;
|
|
@@ -8706,8 +8788,8 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8706
8788
|
document.addEventListener("keydown", onKey);
|
|
8707
8789
|
return () => document.removeEventListener("keydown", onKey);
|
|
8708
8790
|
}, []);
|
|
8709
|
-
const keepSearchFocus = (0,
|
|
8710
|
-
(0,
|
|
8791
|
+
const keepSearchFocus = (0, import_react43.useRef)(false);
|
|
8792
|
+
(0, import_react43.useEffect)(() => {
|
|
8711
8793
|
if (!keepSearchFocus.current) return;
|
|
8712
8794
|
keepSearchFocus.current = false;
|
|
8713
8795
|
const search = rootRef.current?.querySelector('input[aria-label^="Search"]');
|
|
@@ -8716,14 +8798,14 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8716
8798
|
search.setSelectionRange(search.value.length, search.value.length);
|
|
8717
8799
|
}, [loc.q]);
|
|
8718
8800
|
const hasPrompts = useHostPrompts(host.capture, host.fillSetup);
|
|
8719
|
-
const knobsRef = (0,
|
|
8801
|
+
const knobsRef = (0, import_react43.useRef)(host.knobs);
|
|
8720
8802
|
knobsRef.current = host.knobs;
|
|
8721
|
-
const [signedOut, setSignedOut] = (0,
|
|
8722
|
-
const [refreshError, setRefreshError] = (0,
|
|
8723
|
-
const [refreshing, setRefreshing] = (0,
|
|
8724
|
-
const loadedAt = (0,
|
|
8725
|
-
const inFlight = (0,
|
|
8726
|
-
const apply = (0,
|
|
8803
|
+
const [signedOut, setSignedOut] = (0, import_react43.useState)(false);
|
|
8804
|
+
const [refreshError, setRefreshError] = (0, import_react43.useState)(null);
|
|
8805
|
+
const [refreshing, setRefreshing] = (0, import_react43.useState)(false);
|
|
8806
|
+
const loadedAt = (0, import_react43.useRef)(0);
|
|
8807
|
+
const inFlight = (0, import_react43.useRef)(false);
|
|
8808
|
+
const apply = (0, import_react43.useCallback)(
|
|
8727
8809
|
(s) => {
|
|
8728
8810
|
loadedAt.current = Date.now();
|
|
8729
8811
|
setSnap(s);
|
|
@@ -8736,7 +8818,7 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8736
8818
|
},
|
|
8737
8819
|
[port]
|
|
8738
8820
|
);
|
|
8739
|
-
const refresh = (0,
|
|
8821
|
+
const refresh = (0, import_react43.useCallback)(() => {
|
|
8740
8822
|
if (inFlight.current) return;
|
|
8741
8823
|
inFlight.current = true;
|
|
8742
8824
|
setRefreshing(true);
|
|
@@ -8750,7 +8832,7 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8750
8832
|
port.lists.favorites?.list().then((ids) => setFavorites(new Set(ids)), () => void 0);
|
|
8751
8833
|
port.lists.recents?.list().then(setRecents, () => void 0);
|
|
8752
8834
|
}, [port, apply]);
|
|
8753
|
-
const load = (0,
|
|
8835
|
+
const load = (0, import_react43.useCallback)(() => {
|
|
8754
8836
|
setError(null);
|
|
8755
8837
|
setRefreshError(null);
|
|
8756
8838
|
let finished = false;
|
|
@@ -8770,11 +8852,11 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8770
8852
|
knobsRef.current?.().catch(() => void 0);
|
|
8771
8853
|
port.lists.recents?.list().then(setRecents, () => void 0);
|
|
8772
8854
|
}, [port, apply]);
|
|
8773
|
-
(0,
|
|
8774
|
-
const quietRef = (0,
|
|
8855
|
+
(0, import_react43.useEffect)(load, [load]);
|
|
8856
|
+
const quietRef = (0, import_react43.useRef)({ loc, ready: false });
|
|
8775
8857
|
quietRef.current = { loc, ready: snap !== null && !error };
|
|
8776
|
-
const [knobSeconds, setKnobSeconds] = (0,
|
|
8777
|
-
(0,
|
|
8858
|
+
const [knobSeconds, setKnobSeconds] = (0, import_react43.useState)(null);
|
|
8859
|
+
(0, import_react43.useEffect)(() => {
|
|
8778
8860
|
if (host.refreshSeconds !== void 0 || !knobsRef.current) return;
|
|
8779
8861
|
let live = true;
|
|
8780
8862
|
knobsRef.current().then(
|
|
@@ -8789,7 +8871,7 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8789
8871
|
};
|
|
8790
8872
|
}, [host.refreshSeconds]);
|
|
8791
8873
|
const everySeconds = host.refreshSeconds ?? knobSeconds;
|
|
8792
|
-
(0,
|
|
8874
|
+
(0, import_react43.useEffect)(() => {
|
|
8793
8875
|
const quietly = (minGapMs) => {
|
|
8794
8876
|
const { loc: here, ready } = quietRef.current;
|
|
8795
8877
|
if (!ready || document.visibilityState === "hidden" || dirty.current || here.mode !== "view") return;
|
|
@@ -8807,22 +8889,22 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8807
8889
|
if (timer2) clearInterval(timer2);
|
|
8808
8890
|
};
|
|
8809
8891
|
}, [refresh, everySeconds]);
|
|
8810
|
-
const inventoryRef = (0,
|
|
8892
|
+
const inventoryRef = (0, import_react43.useRef)(onInventory);
|
|
8811
8893
|
inventoryRef.current = onInventory;
|
|
8812
|
-
(0,
|
|
8894
|
+
(0, import_react43.useEffect)(() => {
|
|
8813
8895
|
if (snap) inventoryRef.current?.({ items, definitions: snap.definitions });
|
|
8814
8896
|
}, [snap, items]);
|
|
8815
|
-
(0,
|
|
8897
|
+
(0, import_react43.useEffect)(() => {
|
|
8816
8898
|
if (!loc.itemId || !port.lists.recents) return;
|
|
8817
8899
|
const id = loc.itemId;
|
|
8818
8900
|
port.lists.recents.record(id).then(() => setRecents((r) => [id, ...(r ?? []).filter((x) => x !== id)]), () => void 0);
|
|
8819
8901
|
}, [loc.itemId, port]);
|
|
8820
|
-
const orgs = snap?.organizations ?? [];
|
|
8902
|
+
const orgs = (0, import_react43.useMemo)(() => orderOrganizations(snap?.organizations ?? [], items, recents), [snap?.organizations, items, recents]);
|
|
8821
8903
|
const definitions = snap?.definitions ?? [];
|
|
8822
|
-
const inThisVault = (0,
|
|
8904
|
+
const inThisVault = (0, import_react43.useMemo)(() => items.filter((i) => inVault(i, loc.vault)), [items, loc.vault]);
|
|
8823
8905
|
const vaultMixesOwners = new Set(inThisVault.map((i) => i.owner.organizationId ?? i.owner.kind)).size > 1;
|
|
8824
|
-
const views = (0,
|
|
8825
|
-
const visible = (0,
|
|
8906
|
+
const views = (0, import_react43.useMemo)(() => buildViews(inThisVault, definitions, favorites, recents), [inThisVault, definitions, favorites, recents]);
|
|
8907
|
+
const visible = (0, import_react43.useMemo)(() => {
|
|
8826
8908
|
const filtered = inThisVault.filter((i) => {
|
|
8827
8909
|
if (!matchesQuery(i, loc.q, familyLabel(itemFamily(i, definitions)))) return false;
|
|
8828
8910
|
if (loc.view === "favorites") return favorites?.has(i.id) ?? false;
|
|
@@ -8834,8 +8916,8 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8834
8916
|
if (loc.view === "recent" && recents) return [...filtered].sort((a, b) => recents.indexOf(a.id) - recents.indexOf(b.id));
|
|
8835
8917
|
return sortItems(filtered, loc.sort, recents);
|
|
8836
8918
|
}, [inThisVault, loc.view, loc.q, loc.sort, favorites, recents, definitions]);
|
|
8837
|
-
const choices = (0,
|
|
8838
|
-
const matchingIds = (0,
|
|
8919
|
+
const choices = (0, import_react43.useMemo)(() => vaultChoices(items, orgs, loc.vault), [items, orgs, loc.vault]);
|
|
8920
|
+
const matchingIds = (0, import_react43.useMemo)(() => host.page ? new Set(host.page.matchingItemIds) : void 0, [host.page]);
|
|
8839
8921
|
const selected = loc.itemId ? items.find((i) => i.id === loc.itemId) ?? null : null;
|
|
8840
8922
|
const replaceItem = (next) => setItems((cur) => cur.some((i) => i.id === next.id) ? cur.map((i) => i.id === next.id ? next : i) : [...cur, next]);
|
|
8841
8923
|
const toggleFavorite = (id) => {
|
|
@@ -8900,7 +8982,7 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8900
8982
|
const hasFavorites = port.lists.favorites !== void 0;
|
|
8901
8983
|
const title = loc.vault === "all" && loc.view === "all" ? "All items" : viewLabel(loc.view, views);
|
|
8902
8984
|
const compactHeader = mode === "full" ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "grid grid-cols-[repeat(auto-fit,minmax(11rem,1fr))] gap-2", "data-vault-compact-header": "", children: [
|
|
8903
|
-
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(VaultSelect, { value: loc.vault, choices, onChange: (vault) => go({ vault, itemId: null, panel: null }) }),
|
|
8985
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(VaultSelect, { value: loc.vault, choices, searchAt: host.organizationSearchAt, onChange: (vault) => go({ vault, itemId: null, panel: null }) }),
|
|
8904
8986
|
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_controls35.Select, { value: loc.view, onValueChange: (view) => go({ view, itemId: null, panel: null }), options: viewOptions(views, inThisVault.length, deleted.length, hasFavorites, port.lists.recents !== void 0, host.page !== void 0, loc.view), "aria-label": "Show" })
|
|
8905
8987
|
] });
|
|
8906
8988
|
const compactActions = mode === "full" ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex shrink-0 items-center gap-2", "data-vault-compact-actions": "", children: [
|
|
@@ -9137,6 +9219,11 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
9137
9219
|
arg: panelArg ?? null,
|
|
9138
9220
|
onClose: closePanel,
|
|
9139
9221
|
onPanel,
|
|
9222
|
+
onOpenItem: (next) => {
|
|
9223
|
+
replaceItem(next);
|
|
9224
|
+
const holds = loc.vault === "all" || loc.vault === "mine" && next.owner.kind === "me" || loc.vault === next.owner.organizationId;
|
|
9225
|
+
go({ ...holds ? {} : { vault: "all" }, itemId: next.id, mode: "view", panel: null });
|
|
9226
|
+
},
|
|
9140
9227
|
onChanged: (next) => {
|
|
9141
9228
|
if (next) replaceItem(next);
|
|
9142
9229
|
else if (next === null) {
|
|
@@ -9176,6 +9263,7 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
9176
9263
|
vault: loc.vault,
|
|
9177
9264
|
choices,
|
|
9178
9265
|
onVault: (vault) => go({ vault, itemId: null, panel: null }),
|
|
9266
|
+
organizationSearchAt: host.organizationSearchAt,
|
|
9179
9267
|
view: loc.view,
|
|
9180
9268
|
allCount: inThisVault.length,
|
|
9181
9269
|
deletedCount: deleted.length,
|
|
@@ -9984,6 +10072,8 @@ function createApiVaultPort(hostApi, options = {}) {
|
|
|
9984
10072
|
const sharedP = retrying(() => account9.sharedWithMe(api));
|
|
9985
10073
|
const quiet = (p) => void p.catch(() => void 0);
|
|
9986
10074
|
[catalogP, authP, userP, sharedP].forEach(quiet);
|
|
10075
|
+
const orgItemsP = retrying(() => account9.organizationItems(api));
|
|
10076
|
+
quiet(orgItemsP);
|
|
9987
10077
|
const raw = {
|
|
9988
10078
|
orgLists: [],
|
|
9989
10079
|
orgsKnown: options.organizations !== void 0,
|
|
@@ -10031,6 +10121,26 @@ function createApiVaultPort(hostApi, options = {}) {
|
|
|
10031
10121
|
raw.orgLists = orgs.map(() => void 0);
|
|
10032
10122
|
raw.orgsKnown = true;
|
|
10033
10123
|
progress();
|
|
10124
|
+
const one = await orgItemsP.then(
|
|
10125
|
+
(r) => r,
|
|
10126
|
+
(e) => {
|
|
10127
|
+
if (e?.status === 404) return null;
|
|
10128
|
+
return "failed";
|
|
10129
|
+
}
|
|
10130
|
+
);
|
|
10131
|
+
if (one) {
|
|
10132
|
+
const byOrg = one === "failed" ? /* @__PURE__ */ new Map() : new Map(one.views.map((v) => [v.organization_id, v.items]));
|
|
10133
|
+
const failed = one === "failed" ? new Set(orgs.map((o) => o.id)) : new Set(one.unavailable);
|
|
10134
|
+
const settled = orgs.map((o, i) => {
|
|
10135
|
+
if (failed.has(o.id)) return Promise.reject(new Error(`${o.name} is unavailable`));
|
|
10136
|
+
const items = byOrg.get(o.id) ?? [];
|
|
10137
|
+
raw.orgLists[i] = { items, count: items.length };
|
|
10138
|
+
return Promise.resolve(raw.orgLists[i]);
|
|
10139
|
+
});
|
|
10140
|
+
settled.forEach(quiet);
|
|
10141
|
+
progress();
|
|
10142
|
+
return settled;
|
|
10143
|
+
}
|
|
10034
10144
|
return orgs.map((o, i) => {
|
|
10035
10145
|
const p = retrying(() => account9.listItems(api, { query: { principal_type: "organization", organization_id: o.id } }, { organizationId: o.id }));
|
|
10036
10146
|
const arrived = p.then((l) => {
|