@ai-matrx/vault 0.1.35 → 0.1.37
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 +15 -1
- package/dist/index.cjs +416 -323
- 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 +389 -296
- package/dist/index.js.map +1 -1
- package/package.json +8 -29
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 {
|
|
@@ -1774,14 +1774,12 @@ function CodeButton({ live, digits, size = "md", label }) {
|
|
|
1774
1774
|
disabled: !live.code,
|
|
1775
1775
|
onClick: () => live.code && void copy(live.code),
|
|
1776
1776
|
"aria-label": live.code ? `Copy ${label} code` : `Getting ${label} code`,
|
|
1777
|
+
...live.code ? { tooltip: "Copy code" } : {},
|
|
1777
1778
|
variant: "quiet",
|
|
1778
1779
|
layout: "row",
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
copied ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "inline-flex size-6 items-center justify-center text-success", role: "status", "aria-label": "Copied", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckGlyph, { className: "size-4" }) }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CountdownRing, { remaining: live.remaining, period: live.period, loading: !live.code })
|
|
1783
|
-
] }),
|
|
1784
|
-
className: "max-w-full shrink-0"
|
|
1780
|
+
fit: true,
|
|
1781
|
+
title: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: (0, import_design_system8.cn)("whitespace-nowrap font-mono font-medium tabular-nums tracking-[0.08em]", size === "lg" ? "text-2xl" : "text-[1.0625rem]", live.code ? "text-foreground" : "text-disabled-foreground"), children: shown }),
|
|
1782
|
+
end: copied ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "inline-flex size-6 items-center justify-center text-success", role: "status", "aria-label": "Copied", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckGlyph, { className: "size-4" }) }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CountdownRing, { remaining: live.remaining, period: live.period, loading: !live.code })
|
|
1785
1783
|
}
|
|
1786
1784
|
);
|
|
1787
1785
|
}
|
|
@@ -1891,6 +1889,14 @@ function canDecodeQrLocally() {
|
|
|
1891
1889
|
function hasCamera() {
|
|
1892
1890
|
return typeof navigator !== "undefined" && typeof navigator.mediaDevices?.getUserMedia === "function";
|
|
1893
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
|
+
}
|
|
1894
1900
|
async function decodeQr(source) {
|
|
1895
1901
|
return (0, import_qr.decodeQrFromElement)(source);
|
|
1896
1902
|
}
|
|
@@ -1922,17 +1928,15 @@ function useCanScan() {
|
|
|
1922
1928
|
}, []);
|
|
1923
1929
|
return ok;
|
|
1924
1930
|
}
|
|
1925
|
-
function
|
|
1931
|
+
function QrScanInline({ onResult, onClose }) {
|
|
1926
1932
|
const video = (0, import_react10.useRef)(null);
|
|
1927
1933
|
const [error, setError] = (0, import_react10.useState)(null);
|
|
1928
1934
|
const done = (0, import_react10.useRef)(onResult);
|
|
1929
1935
|
done.current = onResult;
|
|
1930
1936
|
(0, import_react10.useEffect)(() => {
|
|
1931
|
-
if (!open) return;
|
|
1932
1937
|
let stream = null;
|
|
1933
1938
|
let live = true;
|
|
1934
1939
|
let timer2 = null;
|
|
1935
|
-
setError(null);
|
|
1936
1940
|
const stop = () => {
|
|
1937
1941
|
if (timer2) clearTimeout(timer2);
|
|
1938
1942
|
stream?.getTracks().forEach((t) => t.stop());
|
|
@@ -1975,13 +1979,26 @@ function QrScanPanel({ open, onResult, onClose }) {
|
|
|
1975
1979
|
live = false;
|
|
1976
1980
|
stop();
|
|
1977
1981
|
};
|
|
1978
|
-
}, [
|
|
1979
|
-
|
|
1980
|
-
/* @__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: [
|
|
1981
1995
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("video", { ref: video, className: "size-full object-cover", playsInline: true, muted: true, "aria-label": "Camera" }),
|
|
1982
|
-
|
|
1996
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "pointer-events-none absolute inset-[18%] rounded-lg border-2 border-primary", "aria-hidden": true })
|
|
1983
1997
|
] }),
|
|
1984
|
-
/* @__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
|
+
] })
|
|
1985
2002
|
] });
|
|
1986
2003
|
}
|
|
1987
2004
|
function OtpSetupRow({ value, onChange, label = "Authenticator", placeholder = "Paste setup key or otpauth link", disabled = false, autoFocus = false, onImage, onRecognized, status, autoStartCamera = false }) {
|
|
@@ -1991,8 +2008,15 @@ function OtpSetupRow({ value, onChange, label = "Authenticator", placeholder = "
|
|
|
1991
2008
|
const autoStarted = (0, import_react10.useRef)(false);
|
|
1992
2009
|
(0, import_react10.useEffect)(() => {
|
|
1993
2010
|
if (!autoStartCamera || !canScan || disabled || autoStarted.current || value) return;
|
|
1994
|
-
|
|
1995
|
-
|
|
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
|
+
};
|
|
1996
2020
|
}, [autoStartCamera, canScan, disabled, value]);
|
|
1997
2021
|
const [reading, setReading] = (0, import_react10.useState)(false);
|
|
1998
2022
|
const [imageError, setImageError] = (0, import_react10.useState)(null);
|
|
@@ -2094,10 +2118,9 @@ function OtpSetupRow({ value, onChange, label = "Authenticator", placeholder = "
|
|
|
2094
2118
|
]
|
|
2095
2119
|
}
|
|
2096
2120
|
),
|
|
2097
|
-
canScan ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2098
|
-
|
|
2121
|
+
canScan && scanning ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2122
|
+
QrScanInline,
|
|
2099
2123
|
{
|
|
2100
|
-
open: scanning,
|
|
2101
2124
|
onClose: () => setScanning(false),
|
|
2102
2125
|
onResult: (text) => {
|
|
2103
2126
|
setScanning(false);
|
|
@@ -2583,7 +2606,7 @@ function OtpListRow({ port, item, family, entry, onOpen, onOpenInNewTab, onRenam
|
|
|
2583
2606
|
const canManage = item.capabilities.canManage || item.capabilities.canEdit;
|
|
2584
2607
|
if (a.removed) return null;
|
|
2585
2608
|
const sub = a.error ?? [entry?.account, loginSiteOf(item) || entry?.issuer].filter((v, i, all) => Boolean(v) && all.indexOf(v) === i).join(" \xB7 ");
|
|
2586
|
-
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "grid min-h-14 grid-cols-[2rem_minmax(0,1fr)_auto_auto] items-center gap-x-
|
|
2609
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "grid min-h-14 grid-cols-[2rem_minmax(0,1fr)_auto_auto] items-center gap-x-1 rounded-lg px-2 py-1.5 transition-colors hover:bg-accent/50", children: [
|
|
2587
2610
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2588
2611
|
import_controls9.Button,
|
|
2589
2612
|
{
|
|
@@ -2604,6 +2627,7 @@ function OtpListRow({ port, item, family, entry, onOpen, onOpenInNewTab, onRenam
|
|
|
2604
2627
|
onClick: onOpen,
|
|
2605
2628
|
title: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: a.enabled ? "text-foreground" : "text-muted-foreground", children: item.name }),
|
|
2606
2629
|
line: sub ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: a.error ? "text-destructive" : "text-muted-foreground", title: sub, children: sub }) : void 0,
|
|
2630
|
+
oneLine: true,
|
|
2607
2631
|
className: "min-w-0"
|
|
2608
2632
|
}
|
|
2609
2633
|
),
|
|
@@ -3207,14 +3231,58 @@ function createVaultKnobs(client, address) {
|
|
|
3207
3231
|
}
|
|
3208
3232
|
var REVEAL_SECONDS_KNOB = "desktop.vault.reveal_hide_seconds";
|
|
3209
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;
|
|
3210
3236
|
function positiveKnob(resolved, key) {
|
|
3211
3237
|
const v = resolved[key];
|
|
3212
3238
|
const n = typeof v === "string" && v.trim() !== "" ? Number(v) : v;
|
|
3213
3239
|
return typeof n === "number" && Number.isFinite(n) && n > 0 ? Math.floor(n) : null;
|
|
3214
3240
|
}
|
|
3215
3241
|
|
|
3216
|
-
// 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
|
|
3217
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");
|
|
3218
3286
|
var LOCKED_MESSAGE = "The vault is locked. Unlock it first.";
|
|
3219
3287
|
var VaultLockedError = class extends Error {
|
|
3220
3288
|
code = "vault_locked";
|
|
@@ -3249,12 +3317,12 @@ function guardPort(port, locked) {
|
|
|
3249
3317
|
var NEVER = () => () => void 0;
|
|
3250
3318
|
var UNLOCKED = () => false;
|
|
3251
3319
|
function useLocked(lock) {
|
|
3252
|
-
return (0,
|
|
3320
|
+
return (0, import_react17.useSyncExternalStore)(lock ? lock.subscribe : NEVER, lock ? () => lock.locked() : UNLOCKED, UNLOCKED);
|
|
3253
3321
|
}
|
|
3254
3322
|
|
|
3255
3323
|
// src/io/BackupPanel.tsx
|
|
3256
3324
|
var import_format6 = require("@ai-matrx/kit/format");
|
|
3257
|
-
var
|
|
3325
|
+
var import_react19 = require("react");
|
|
3258
3326
|
var import_controls13 = require("@ai-matrx/design-system/controls");
|
|
3259
3327
|
var import_download = require("@ai-matrx/kit/download");
|
|
3260
3328
|
var import_confirm_opener4 = require("@ai-matrx/kit/confirm-opener");
|
|
@@ -3347,7 +3415,7 @@ function startNewRestoreRun(preview) {
|
|
|
3347
3415
|
}
|
|
3348
3416
|
|
|
3349
3417
|
// src/io/lines.tsx
|
|
3350
|
-
var
|
|
3418
|
+
var import_react18 = require("react");
|
|
3351
3419
|
var import_design_system12 = require("@ai-matrx/design-system");
|
|
3352
3420
|
var import_controls12 = require("@ai-matrx/design-system/controls");
|
|
3353
3421
|
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
@@ -3360,7 +3428,7 @@ function PickLine({ checked, onChange, disabled = false, title, detail, badge, t
|
|
|
3360
3428
|
] });
|
|
3361
3429
|
}
|
|
3362
3430
|
function Windowed({ items, size = 150, render }) {
|
|
3363
|
-
const [all, setAll] = (0,
|
|
3431
|
+
const [all, setAll] = (0, import_react18.useState)(false);
|
|
3364
3432
|
const shown = all ? items : items.slice(0, size);
|
|
3365
3433
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
|
|
3366
3434
|
shown.map(render),
|
|
@@ -3371,7 +3439,7 @@ function Windowed({ items, size = 150, render }) {
|
|
|
3371
3439
|
] });
|
|
3372
3440
|
}
|
|
3373
3441
|
function More({ title = "More", children }) {
|
|
3374
|
-
const [open, setOpen] = (0,
|
|
3442
|
+
const [open, setOpen] = (0, import_react18.useState)(false);
|
|
3375
3443
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
3376
3444
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_controls12.DisclosureHeader, { open, title, onClick: () => setOpen((o) => !o) }),
|
|
3377
3445
|
open ? children : null
|
|
@@ -3411,21 +3479,21 @@ function Omissions({ omissions, accepted, onAccepted, verb }) {
|
|
|
3411
3479
|
function BackupPanel({ port, host, items, onClose, onChanged }) {
|
|
3412
3480
|
const minLength = passphraseMinimum(host.backupPassphraseMinLength);
|
|
3413
3481
|
const confirmed = useConfirmed();
|
|
3414
|
-
const fileInput = (0,
|
|
3415
|
-
const abort = (0,
|
|
3416
|
-
const [mode, setMode] = (0,
|
|
3417
|
-
const [busy, setBusy] = (0,
|
|
3418
|
-
const [error, setError] = (0,
|
|
3419
|
-
const [passphrase, setPassphrase] = (0,
|
|
3420
|
-
const [repeat, setRepeat] = (0,
|
|
3421
|
-
const [accepted, setAccepted] = (0,
|
|
3422
|
-
const [selected, setSelected] = (0,
|
|
3423
|
-
const [backup, setBackup] = (0,
|
|
3424
|
-
const [file, setFile] = (0,
|
|
3425
|
-
const [restorePreview, setRestorePreview] = (0,
|
|
3426
|
-
const [runId, setRunId] = (0,
|
|
3427
|
-
const [result, setResult] = (0,
|
|
3428
|
-
(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(), []);
|
|
3429
3497
|
const switchMode = (next) => {
|
|
3430
3498
|
abort.current?.abort();
|
|
3431
3499
|
setMode(next);
|
|
@@ -3562,7 +3630,7 @@ function BackupPanel({ port, host, items, onClose, onChanged }) {
|
|
|
3562
3630
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Summary, { value: backup }),
|
|
3563
3631
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Omissions, { omissions: backup.omissions, accepted, onAccepted: setAccepted, verb: "Back up" }),
|
|
3564
3632
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(VaultSection, { children: [
|
|
3565
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(VaultRow, { label: "Passphrase", hint: minLength ? `At least ${minLength} characters. Not saved.` : "Not saved. It can't be recovered.", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_controls13.Field, { type: "password", value: passphrase, autoComplete: "new-password", "aria-label": "Backup passphrase", "aria-invalid": short || void 0, onChange: (e) => setPassphrase(e.target.value) }) }),
|
|
3633
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(VaultRow, { label: "Passphrase", hint: minLength ? `At least ${minLength} characters. Not saved. It can't be recovered.` : "Not saved. It can't be recovered.", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_controls13.Field, { type: "password", value: passphrase, autoComplete: "new-password", "aria-label": "Backup passphrase", "aria-invalid": short || void 0, onChange: (e) => setPassphrase(e.target.value) }) }),
|
|
3566
3634
|
short ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("p", { role: "alert", className: "px-1 text-xs text-destructive", "data-passphrase-too-short": "", children: [
|
|
3567
3635
|
"Use at least ",
|
|
3568
3636
|
minLength,
|
|
@@ -3610,7 +3678,7 @@ function tooShort(passphrase, minLength) {
|
|
|
3610
3678
|
}
|
|
3611
3679
|
|
|
3612
3680
|
// src/io/ExportPanel.tsx
|
|
3613
|
-
var
|
|
3681
|
+
var import_react20 = require("react");
|
|
3614
3682
|
var import_controls14 = require("@ai-matrx/design-system/controls");
|
|
3615
3683
|
var import_download2 = require("@ai-matrx/kit/download");
|
|
3616
3684
|
var import_confirm_opener5 = require("@ai-matrx/kit/confirm-opener");
|
|
@@ -3634,12 +3702,12 @@ function omissionText2(omissions) {
|
|
|
3634
3702
|
}
|
|
3635
3703
|
function ExportPanel({ port, items, onClose }) {
|
|
3636
3704
|
const confirmed = useConfirmed();
|
|
3637
|
-
const logins = (0,
|
|
3638
|
-
const [profile, setProfile] = (0,
|
|
3639
|
-
const [selected, setSelected] = (0,
|
|
3640
|
-
const [preview, setPreview] = (0,
|
|
3641
|
-
const [busy, setBusy] = (0,
|
|
3642
|
-
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);
|
|
3643
3711
|
const format = FORMATS.find((f) => f.value === profile);
|
|
3644
3712
|
const reasons = new Map(preview?.items.map((p) => [p.item_id, p]) ?? []);
|
|
3645
3713
|
const eligible = preview?.items.filter((p) => p.eligible).length ?? 0;
|
|
@@ -3764,7 +3832,7 @@ function ExportPanel({ port, items, onClose }) {
|
|
|
3764
3832
|
}
|
|
3765
3833
|
|
|
3766
3834
|
// src/io/ImportPanel.tsx
|
|
3767
|
-
var
|
|
3835
|
+
var import_react21 = require("react");
|
|
3768
3836
|
var import_controls15 = require("@ai-matrx/design-system/controls");
|
|
3769
3837
|
|
|
3770
3838
|
// src/io/csv-import.ts
|
|
@@ -4626,25 +4694,25 @@ var STATE_BADGE = {
|
|
|
4626
4694
|
var ME = "me";
|
|
4627
4695
|
function ImportPanel({ port, host, items, definitions, organizations, onClose, onChanged, limits }) {
|
|
4628
4696
|
const confirmed = useConfirmed();
|
|
4629
|
-
const [otpFor, setOtpFor] = (0,
|
|
4630
|
-
const fileInput = (0,
|
|
4631
|
-
const abort = (0,
|
|
4632
|
-
const stop = (0,
|
|
4633
|
-
const keys = (0,
|
|
4634
|
-
const [source, setSource] = (0,
|
|
4635
|
-
const [envText, setEnvText] = (0,
|
|
4636
|
-
const [injectSandbox, setInjectSandbox] = (0,
|
|
4637
|
-
const [fileName, setFileName] = (0,
|
|
4638
|
-
const [reading, setReading] = (0,
|
|
4639
|
-
const [draft, setDraft] = (0,
|
|
4640
|
-
const [destination, setDestination] = (0,
|
|
4641
|
-
const [browserFill, setBrowserFill] = (0,
|
|
4642
|
-
const [approvedVisible, setApprovedVisible] = (0,
|
|
4643
|
-
const [selected, setSelected] = (0,
|
|
4644
|
-
const [running, setRunning] = (0,
|
|
4645
|
-
const [done, setDone] = (0,
|
|
4646
|
-
const [error, setError] = (0,
|
|
4647
|
-
(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)(
|
|
4648
4716
|
() => () => {
|
|
4649
4717
|
abort.current?.abort();
|
|
4650
4718
|
stop.current = true;
|
|
@@ -4653,9 +4721,9 @@ function ImportPanel({ port, host, items, definitions, organizations, onClose, o
|
|
|
4653
4721
|
);
|
|
4654
4722
|
const organizationId = destination === ME ? null : destination;
|
|
4655
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 }));
|
|
4656
|
-
const existing = (0,
|
|
4657
|
-
const destinationOptions = (0,
|
|
4658
|
-
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)(
|
|
4659
4727
|
() => draft?.kind === "file" ? reviewLines(draft.parsed, { organizationId, browserFill, existing, limits, mapping: draft.mapping }) : [],
|
|
4660
4728
|
[draft, organizationId, browserFill, existing, limits]
|
|
4661
4729
|
);
|
|
@@ -4931,14 +4999,14 @@ function Notices({ draft }) {
|
|
|
4931
4999
|
}
|
|
4932
5000
|
|
|
4933
5001
|
// src/ItemList.tsx
|
|
4934
|
-
var
|
|
5002
|
+
var import_react30 = require("react");
|
|
4935
5003
|
var import_design_system19 = require("@ai-matrx/design-system");
|
|
4936
5004
|
var import_design_system20 = require("@ai-matrx/design-system");
|
|
4937
5005
|
var import_controls23 = require("@ai-matrx/design-system/controls");
|
|
4938
5006
|
var import_icons12 = require("@ai-matrx/design-system/icons");
|
|
4939
5007
|
|
|
4940
5008
|
// src/ItemPane.tsx
|
|
4941
|
-
var
|
|
5009
|
+
var import_react29 = require("react");
|
|
4942
5010
|
var import_design_system17 = require("@ai-matrx/design-system");
|
|
4943
5011
|
var import_design_system18 = require("@ai-matrx/design-system");
|
|
4944
5012
|
var import_controls22 = require("@ai-matrx/design-system/controls");
|
|
@@ -4946,7 +5014,7 @@ var import_confirm_opener10 = require("@ai-matrx/kit/confirm-opener");
|
|
|
4946
5014
|
|
|
4947
5015
|
// src/activity/FilesSection.tsx
|
|
4948
5016
|
var import_format7 = require("@ai-matrx/kit/format");
|
|
4949
|
-
var
|
|
5017
|
+
var import_react22 = require("react");
|
|
4950
5018
|
var import_controls16 = require("@ai-matrx/design-system/controls");
|
|
4951
5019
|
var import_design_system13 = require("@ai-matrx/design-system");
|
|
4952
5020
|
var import_confirm_opener6 = require("@ai-matrx/kit/confirm-opener");
|
|
@@ -4964,11 +5032,11 @@ function FilesSection({ item, port, editing, onChanged }) {
|
|
|
4964
5032
|
const confirmed = useConfirmed();
|
|
4965
5033
|
const canEdit = editing && item.capabilities.canEdit;
|
|
4966
5034
|
const canAdd = item.capabilities.canEdit;
|
|
4967
|
-
const [busy, setBusy] = (0,
|
|
4968
|
-
const [error, setError] = (0,
|
|
4969
|
-
const [pending, setPending] = (0,
|
|
4970
|
-
const [dragging, setDragging] = (0,
|
|
4971
|
-
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);
|
|
4972
5040
|
if (!canAdd && item.attachments.length === 0) return null;
|
|
4973
5041
|
async function run(key, work, fallback) {
|
|
4974
5042
|
setBusy(key);
|
|
@@ -5045,8 +5113,8 @@ function FilesSection({ item, port, editing, onChanged }) {
|
|
|
5045
5113
|
);
|
|
5046
5114
|
}
|
|
5047
5115
|
function EditableFile({ port, item: it, file: a, busy: b, run: go, onDownload, onTooBig }) {
|
|
5048
|
-
const [open, setOpen] = (0,
|
|
5049
|
-
const replacer = (0,
|
|
5116
|
+
const [open, setOpen] = (0, import_react22.useState)(false);
|
|
5117
|
+
const replacer = (0, import_react22.useRef)(null);
|
|
5050
5118
|
async function remove() {
|
|
5051
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" });
|
|
5052
5120
|
if (yes) await go(`delete:${a.id}`, () => port.activity.deleteFile(it, a.id), "The file could not be deleted.");
|
|
@@ -5104,9 +5172,9 @@ function Protection({ value, locked, onChange }) {
|
|
|
5104
5172
|
);
|
|
5105
5173
|
}
|
|
5106
5174
|
function NewFile({ file, busy, onAdd, onCancel }) {
|
|
5107
|
-
const [label, setLabel] = (0,
|
|
5108
|
-
const [description, setDescription] = (0,
|
|
5109
|
-
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");
|
|
5110
5178
|
async function add() {
|
|
5111
5179
|
if (handling === "sealed" && !await confirmSeal(label)) return;
|
|
5112
5180
|
await onAdd({ label: label.trim(), description: description.trim() || null, handling });
|
|
@@ -5126,10 +5194,10 @@ function NewFile({ file, busy, onAdd, onCancel }) {
|
|
|
5126
5194
|
] });
|
|
5127
5195
|
}
|
|
5128
5196
|
function FileDetailsRows({ file, busy, onSave, onCancel }) {
|
|
5129
|
-
const [label, setLabel] = (0,
|
|
5130
|
-
const [description, setDescription] = (0,
|
|
5131
|
-
const [fileName, setFileName] = (0,
|
|
5132
|
-
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);
|
|
5133
5201
|
const changed = label !== file.label || description !== file.description || fileName !== file.fileName || handling !== file.handling;
|
|
5134
5202
|
async function save() {
|
|
5135
5203
|
if (handling === "sealed" && file.handling !== "sealed" && !await confirmSeal(label)) return;
|
|
@@ -5155,10 +5223,10 @@ function confirmSeal(label) {
|
|
|
5155
5223
|
});
|
|
5156
5224
|
}
|
|
5157
5225
|
function DraftFilesSection({ files, onFiles }) {
|
|
5158
|
-
const [pending, setPending] = (0,
|
|
5159
|
-
const [error, setError] = (0,
|
|
5160
|
-
const [dragging, setDragging] = (0,
|
|
5161
|
-
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);
|
|
5162
5230
|
const choose = (file) => {
|
|
5163
5231
|
if (!file) return;
|
|
5164
5232
|
if (fileTooBig(file.size)) return setError(TOO_BIG);
|
|
@@ -5207,7 +5275,7 @@ function DraftFilesSection({ files, onFiles }) {
|
|
|
5207
5275
|
}
|
|
5208
5276
|
|
|
5209
5277
|
// src/fields/RecoveryCodesRow.tsx
|
|
5210
|
-
var
|
|
5278
|
+
var import_react23 = require("react");
|
|
5211
5279
|
var import_controls17 = require("@ai-matrx/design-system/controls");
|
|
5212
5280
|
var import_icons9 = require("@ai-matrx/design-system/icons");
|
|
5213
5281
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
@@ -5217,9 +5285,9 @@ function RecoveryCodesRow({ item, field, port, onChanged }) {
|
|
|
5217
5285
|
const confirmed = useConfirmed();
|
|
5218
5286
|
const copyValue2 = useCopy();
|
|
5219
5287
|
const secret = useTransientSecret();
|
|
5220
|
-
const [busy, setBusy] = (0,
|
|
5221
|
-
const [error, setError] = (0,
|
|
5222
|
-
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);
|
|
5223
5291
|
const canEdit = item.capabilities.canEdit;
|
|
5224
5292
|
const run = async (step) => {
|
|
5225
5293
|
setBusy(true);
|
|
@@ -5314,7 +5382,7 @@ function RecoveryCodesRow({ item, field, port, onChanged }) {
|
|
|
5314
5382
|
}
|
|
5315
5383
|
|
|
5316
5384
|
// src/fields/DraftRows.tsx
|
|
5317
|
-
var
|
|
5385
|
+
var import_react24 = require("react");
|
|
5318
5386
|
var import_controls18 = require("@ai-matrx/design-system/controls");
|
|
5319
5387
|
var import_design_system14 = require("@ai-matrx/design-system");
|
|
5320
5388
|
var import_confirm_opener7 = require("@ai-matrx/kit/confirm-opener");
|
|
@@ -5369,7 +5437,7 @@ function FieldSettingsRows({ name, value, defaultHandling = "revealable", onChan
|
|
|
5369
5437
|
var hasSecretSettings = (s) => saysMore(s, "revealable");
|
|
5370
5438
|
var hasDeclaredSettings = (s, defaultHandling) => Boolean(s && saysMore(s, defaultHandling));
|
|
5371
5439
|
function SecretBuilderRow({ field, onChange, onRemove }) {
|
|
5372
|
-
const [open, setOpen] = (0,
|
|
5440
|
+
const [open, setOpen] = (0, import_react24.useState)(hasSecretSettings(field));
|
|
5373
5441
|
const handling = field.handling ?? "revealable";
|
|
5374
5442
|
const name = field.label.trim() || "Secret";
|
|
5375
5443
|
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
@@ -5610,7 +5678,7 @@ function targetLabel(t) {
|
|
|
5610
5678
|
}
|
|
5611
5679
|
|
|
5612
5680
|
// src/extension/UseOnSiteButton.tsx
|
|
5613
|
-
var
|
|
5681
|
+
var import_react25 = require("react");
|
|
5614
5682
|
var import_controls19 = require("@ai-matrx/design-system/controls");
|
|
5615
5683
|
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
5616
5684
|
function canUseOnSite(item, pageUrl) {
|
|
@@ -5618,7 +5686,7 @@ function canUseOnSite(item, pageUrl) {
|
|
|
5618
5686
|
}
|
|
5619
5687
|
function UseOnSiteButton({ port, item, pageUrl, onChanged }) {
|
|
5620
5688
|
const notify = useNotify();
|
|
5621
|
-
const [busy, setBusy] = (0,
|
|
5689
|
+
const [busy, setBusy] = (0, import_react25.useState)(false);
|
|
5622
5690
|
if (!canUseOnSite(item, pageUrl)) return null;
|
|
5623
5691
|
const site = pageSite(pageUrl);
|
|
5624
5692
|
const run = async () => {
|
|
@@ -5637,7 +5705,7 @@ function UseOnSiteButton({ port, item, pageUrl, onChanged }) {
|
|
|
5637
5705
|
}
|
|
5638
5706
|
|
|
5639
5707
|
// src/sharing/SharePanel.tsx
|
|
5640
|
-
var
|
|
5708
|
+
var import_react28 = require("react");
|
|
5641
5709
|
var import_confirm_opener9 = require("@ai-matrx/kit/confirm-opener");
|
|
5642
5710
|
var import_controls21 = require("@ai-matrx/design-system/controls");
|
|
5643
5711
|
var import_design_system16 = require("@ai-matrx/design-system");
|
|
@@ -5660,14 +5728,17 @@ function isEmail(value) {
|
|
|
5660
5728
|
}
|
|
5661
5729
|
var PERSONAL = "personal";
|
|
5662
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) } : {} });
|
|
5663
5732
|
function moveDestinations(item, orgs) {
|
|
5664
5733
|
if (item.owner.kind === "shared") return [];
|
|
5665
5734
|
const here = item.owner.organizationId;
|
|
5666
|
-
|
|
5735
|
+
const hints = organizationHints(orgs);
|
|
5736
|
+
return [...here ? [{ value: PERSONAL, label: "Personal" }] : [], ...orgs.filter((o) => o.id !== here).map((o) => orgChoice(o, hints))];
|
|
5667
5737
|
}
|
|
5668
5738
|
function copyDestinations(orgs, item) {
|
|
5669
5739
|
const here = item ? item.owner.kind === "me" ? PERSONAL : item.owner.organizationId : void 0;
|
|
5670
|
-
|
|
5740
|
+
const hints = organizationHints(orgs);
|
|
5741
|
+
return [{ value: PERSONAL, label: "Personal" }, ...orgs.map((o) => orgChoice(o, hints))].filter((d) => d.value !== here);
|
|
5671
5742
|
}
|
|
5672
5743
|
function copyRefusal(message2) {
|
|
5673
5744
|
return /duplicate/i.test(message2) ? "There is already a copy of this item there." : null;
|
|
@@ -5695,7 +5766,7 @@ function shareSummary(grants) {
|
|
|
5695
5766
|
var MEMBER_CHOICE_DEFAULT = "default";
|
|
5696
5767
|
|
|
5697
5768
|
// src/sharing/parts.tsx
|
|
5698
|
-
var
|
|
5769
|
+
var import_react26 = require("react");
|
|
5699
5770
|
var import_design_system15 = require("@ai-matrx/design-system");
|
|
5700
5771
|
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
5701
5772
|
var message = (e, fallback) => {
|
|
@@ -5704,9 +5775,9 @@ var message = (e, fallback) => {
|
|
|
5704
5775
|
};
|
|
5705
5776
|
function useConfirmedChange() {
|
|
5706
5777
|
const confirmed = useConfirmed();
|
|
5707
|
-
const [busy, setBusy] = (0,
|
|
5708
|
-
const [error, setError] = (0,
|
|
5709
|
-
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);
|
|
5710
5781
|
async function run(key, fn, done) {
|
|
5711
5782
|
setBusy(key);
|
|
5712
5783
|
setError(null);
|
|
@@ -5740,18 +5811,20 @@ function StatusLine({ error, notice }) {
|
|
|
5740
5811
|
}
|
|
5741
5812
|
|
|
5742
5813
|
// src/sharing/MovePanel.tsx
|
|
5743
|
-
var
|
|
5814
|
+
var import_react27 = require("react");
|
|
5744
5815
|
var import_confirm_opener8 = require("@ai-matrx/kit/confirm-opener");
|
|
5745
5816
|
var import_controls20 = require("@ai-matrx/design-system/controls");
|
|
5746
5817
|
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
5747
5818
|
var NONE = "__none__";
|
|
5748
|
-
function MovePanel({ item, port, organizations, onClose, onChanged }) {
|
|
5819
|
+
function MovePanel({ item, port, host, organizations, onClose, onChanged, onOpenItem }) {
|
|
5749
5820
|
const { busy, error, notice, run, setNotice } = useConfirmedChange();
|
|
5750
5821
|
const moves = moveDestinations(item, organizations);
|
|
5751
5822
|
const copies = copyDestinations(organizations, item);
|
|
5752
|
-
const [moveTo, setMoveTo] = (0,
|
|
5753
|
-
const [copyTo, setCopyTo] = (0,
|
|
5754
|
-
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;
|
|
5755
5828
|
const passkey = isPasskey(item);
|
|
5756
5829
|
const canMove = item.capabilities.canManage && !passkey && moves.length > 0;
|
|
5757
5830
|
const canGive = item.capabilities.canManage && item.owner.kind === "me" && !passkey;
|
|
@@ -5785,8 +5858,10 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
|
|
|
5785
5858
|
};
|
|
5786
5859
|
const copy = async () => {
|
|
5787
5860
|
if (!copyChoice) return;
|
|
5788
|
-
const
|
|
5789
|
-
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();
|
|
5790
5865
|
};
|
|
5791
5866
|
const nothing = !canMove && !canGive && !canCopy;
|
|
5792
5867
|
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
@@ -5795,7 +5870,10 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
|
|
|
5795
5870
|
title: "Move or copy",
|
|
5796
5871
|
size: "md",
|
|
5797
5872
|
onClose,
|
|
5798
|
-
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
|
+
] }),
|
|
5799
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: [
|
|
5800
5878
|
canMove && moves.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5801
5879
|
VaultRow,
|
|
@@ -5803,7 +5881,7 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
|
|
|
5803
5881
|
label: "Move to",
|
|
5804
5882
|
hint: moveChoice ? itemMoveConsequence(item, destinationOf(moveChoice.value)) : void 0,
|
|
5805
5883
|
actions: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Button, { variant: "outline", disabled: busy !== null || !moveChoice, onClick: () => void move(), children: "Move" }),
|
|
5806
|
-
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] })
|
|
5807
5885
|
}
|
|
5808
5886
|
) : null,
|
|
5809
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)(
|
|
@@ -5820,7 +5898,7 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
|
|
|
5820
5898
|
onChange: (e) => setEmail(e.target.value)
|
|
5821
5899
|
}
|
|
5822
5900
|
) }) : null,
|
|
5823
|
-
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
|
|
5824
5902
|
] })
|
|
5825
5903
|
}
|
|
5826
5904
|
);
|
|
@@ -5829,11 +5907,11 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
|
|
|
5829
5907
|
// src/sharing/SharePanel.tsx
|
|
5830
5908
|
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
5831
5909
|
function useGrants(port, item) {
|
|
5832
|
-
const [grants, setGrants] = (0,
|
|
5833
|
-
const [loadError, setLoadError] = (0,
|
|
5834
|
-
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);
|
|
5835
5913
|
const allowed = item.capabilities.canManage;
|
|
5836
|
-
(0,
|
|
5914
|
+
(0, import_react28.useEffect)(() => {
|
|
5837
5915
|
if (!allowed) return;
|
|
5838
5916
|
let live = true;
|
|
5839
5917
|
setLoadError(null);
|
|
@@ -5850,9 +5928,9 @@ function useGrants(port, item) {
|
|
|
5850
5928
|
function SharePanel({ item, port, organizations, onClose, onChanged }) {
|
|
5851
5929
|
const { grants, setGrants, loadError, reload } = useGrants(port, item);
|
|
5852
5930
|
const { busy, error, notice, run } = useConfirmedChange();
|
|
5853
|
-
const [email, setEmail] = (0,
|
|
5854
|
-
const [level, setLevel] = (0,
|
|
5855
|
-
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);
|
|
5856
5934
|
const isOrg = item.owner.kind === "organization" && item.owner.organizationId !== null;
|
|
5857
5935
|
const orgName = item.owner.label;
|
|
5858
5936
|
const people = (grants ?? []).filter((g) => g.kind === "person");
|
|
@@ -5971,8 +6049,8 @@ function SharePanel({ item, port, organizations, onClose, onChanged }) {
|
|
|
5971
6049
|
function IntoOrganization({ item, port, organizations, grants, onShared }) {
|
|
5972
6050
|
const { busy, error, notice, run } = useConfirmedChange();
|
|
5973
6051
|
const open = organizations.filter((o) => !grants.some((g) => g.organizationId === o.id));
|
|
5974
|
-
const [target, setTarget] = (0,
|
|
5975
|
-
const [level, setLevel] = (0,
|
|
6052
|
+
const [target, setTarget] = (0, import_react28.useState)("");
|
|
6053
|
+
const [level, setLevel] = (0, import_react28.useState)("use");
|
|
5976
6054
|
const chosen = open.find((o) => o.id === target);
|
|
5977
6055
|
if (item.owner.kind !== "me") return null;
|
|
5978
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: [
|
|
@@ -6007,10 +6085,10 @@ var CHOICES = [
|
|
|
6007
6085
|
{ value: "editor", label: "Can edit", meta: "See and change" }
|
|
6008
6086
|
];
|
|
6009
6087
|
function MemberAccess({ port, organizationId, organizationName }) {
|
|
6010
|
-
const [list, setList] = (0,
|
|
6011
|
-
const [loadError, setLoadError] = (0,
|
|
6088
|
+
const [list, setList] = (0, import_react28.useState)(null);
|
|
6089
|
+
const [loadError, setLoadError] = (0, import_react28.useState)(null);
|
|
6012
6090
|
const { busy, error, run } = useConfirmedChange();
|
|
6013
|
-
(0,
|
|
6091
|
+
(0, import_react28.useEffect)(() => {
|
|
6014
6092
|
let live = true;
|
|
6015
6093
|
port.sharing.memberAccess(organizationId).then(
|
|
6016
6094
|
(l) => live && setList(l),
|
|
@@ -6042,9 +6120,9 @@ function MemberAccess({ port, organizationId, organizationName }) {
|
|
|
6042
6120
|
] });
|
|
6043
6121
|
}
|
|
6044
6122
|
function SharingSummary({ item, port, className }) {
|
|
6045
|
-
const [text, setText] = (0,
|
|
6123
|
+
const [text, setText] = (0, import_react28.useState)("");
|
|
6046
6124
|
const allowed = item.capabilities.canManage;
|
|
6047
|
-
(0,
|
|
6125
|
+
(0, import_react28.useEffect)(() => {
|
|
6048
6126
|
if (!allowed) return;
|
|
6049
6127
|
let live = true;
|
|
6050
6128
|
port.sharing.grants(item).then(
|
|
@@ -6075,8 +6153,8 @@ function ItemPane(props) {
|
|
|
6075
6153
|
const editing = mode !== "view";
|
|
6076
6154
|
const seedName = seed?.name ?? "";
|
|
6077
6155
|
const seedUrl = seed?.url ?? "";
|
|
6078
|
-
const [loaded, setLoaded] = (0,
|
|
6079
|
-
const base = (0,
|
|
6156
|
+
const [loaded, setLoaded] = (0, import_react29.useState)({});
|
|
6157
|
+
const base = (0, import_react29.useMemo)(() => {
|
|
6080
6158
|
const b = draftOf(item);
|
|
6081
6159
|
if (!item) {
|
|
6082
6160
|
b.name = seedName;
|
|
@@ -6085,28 +6163,28 @@ function ItemPane(props) {
|
|
|
6085
6163
|
b.values = { ...loaded };
|
|
6086
6164
|
return b;
|
|
6087
6165
|
}, [item, seedName, seedUrl, loaded]);
|
|
6088
|
-
const [draft, setDraft] = (0,
|
|
6089
|
-
const [tagsText, setTagsText] = (0,
|
|
6090
|
-
const [showTags, setShowTags] = (0,
|
|
6091
|
-
const [showDescription, setShowDescription] = (0,
|
|
6092
|
-
const [showRecovery, setShowRecovery] = (0,
|
|
6093
|
-
const [settingUpOtp, setSettingUpOtp] = (0,
|
|
6094
|
-
const [owner, setOwner] = (0,
|
|
6095
|
-
const [recipient, setRecipient] = (0,
|
|
6096
|
-
const [generatePrivately, setGeneratePrivately] = (0,
|
|
6097
|
-
const [busy, setBusy] = (0,
|
|
6098
|
-
const [sent, setSent] = (0,
|
|
6099
|
-
const [queuedFiles, setQueuedFiles] = (0,
|
|
6100
|
-
const [showBrowser, setShowBrowser] = (0,
|
|
6101
|
-
const [error, setError] = (0,
|
|
6102
|
-
const [destinations, setDestinations] = (0,
|
|
6103
|
-
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);
|
|
6104
6182
|
const dirty = editing && !savedNew && isDirty(base, draft);
|
|
6105
6183
|
const declared = definition?.fields ?? [];
|
|
6106
|
-
const prev = (0,
|
|
6107
|
-
const paneRef = (0,
|
|
6184
|
+
const prev = (0, import_react29.useRef)(null);
|
|
6185
|
+
const paneRef = (0, import_react29.useRef)(null);
|
|
6108
6186
|
const room = useRoomOf(paneRef);
|
|
6109
|
-
(0,
|
|
6187
|
+
(0, import_react29.useEffect)(() => {
|
|
6110
6188
|
const was = prev.current;
|
|
6111
6189
|
const id = item?.id ?? null;
|
|
6112
6190
|
if (was && was.id === id && was.mode === mode && editing) {
|
|
@@ -6119,22 +6197,22 @@ function ItemPane(props) {
|
|
|
6119
6197
|
}
|
|
6120
6198
|
prev.current = { base, id, mode };
|
|
6121
6199
|
}, [base, mode, item?.id, editing]);
|
|
6122
|
-
(0,
|
|
6200
|
+
(0, import_react29.useEffect)(() => {
|
|
6123
6201
|
setLoaded({});
|
|
6124
6202
|
setShowTags(false);
|
|
6125
6203
|
setShowDescription(false);
|
|
6126
6204
|
setShowRecovery(false);
|
|
6127
6205
|
setSavedNew(false);
|
|
6128
6206
|
}, [item?.id, mode]);
|
|
6129
|
-
const onDirtyRef = (0,
|
|
6207
|
+
const onDirtyRef = (0, import_react29.useRef)(onDirty);
|
|
6130
6208
|
onDirtyRef.current = onDirty;
|
|
6131
|
-
(0,
|
|
6209
|
+
(0, import_react29.useEffect)(() => onDirtyRef.current(dirty), [dirty]);
|
|
6132
6210
|
const keepKey = draftKey(item?.id ?? null, definition?.key ?? item?.definitionKey ?? null);
|
|
6133
|
-
(0,
|
|
6211
|
+
(0, import_react29.useEffect)(() => {
|
|
6134
6212
|
if (editing && dirty) (0, import_drafts.keepDraft)(keepKey, keptFieldsOf(draft), { basedOn: item?.updatedAt ?? "new" });
|
|
6135
6213
|
else if (!editing) (0, import_drafts.dropKeptDraft)(keepKey);
|
|
6136
6214
|
}, [editing, dirty, draft, keepKey, item?.updatedAt]);
|
|
6137
|
-
(0,
|
|
6215
|
+
(0, import_react29.useEffect)(() => {
|
|
6138
6216
|
if (!editing || !item) return;
|
|
6139
6217
|
let live = true;
|
|
6140
6218
|
for (const f of item.fields) {
|
|
@@ -6259,7 +6337,7 @@ function ItemPane(props) {
|
|
|
6259
6337
|
const turnOnOne = canTurnOn ? (f) => () => turnOn([f]) : () => void 0;
|
|
6260
6338
|
const declaredKeys = new Set(declared.map((f) => f.key));
|
|
6261
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);
|
|
6262
|
-
const [settingsToggled, setSettingsToggled] = (0,
|
|
6340
|
+
const [settingsToggled, setSettingsToggled] = (0, import_react29.useState)(/* @__PURE__ */ new Set());
|
|
6263
6341
|
const settingsOpen = (f) => settingsToggled.has(f.key) !== (definition?.key === ENV_VALUE_KEY || hasDeclaredSettings(draft.fieldSettings?.[f.key], f.handling));
|
|
6264
6342
|
const toggleSettings = (key) => setSettingsToggled((cur) => {
|
|
6265
6343
|
const next = new Set(cur);
|
|
@@ -6414,7 +6492,7 @@ function ItemPane(props) {
|
|
|
6414
6492
|
const hidden = existing && existing.handling !== "visible" && !(f.key in loaded);
|
|
6415
6493
|
const newSecret = mode === "new" && f.storage === "encrypted" && owner !== "person";
|
|
6416
6494
|
const open = newSecret && settingsOpen(f);
|
|
6417
|
-
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
6495
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_react29.Fragment, { children: [
|
|
6418
6496
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
6419
6497
|
EditRow,
|
|
6420
6498
|
{
|
|
@@ -6636,8 +6714,8 @@ function ItemList({ title, items, definitions, port, selectedId, onSelect, query
|
|
|
6636
6714
|
const pinned = matchingIds ? items.filter((i) => matchingIds.has(i.id)) : [];
|
|
6637
6715
|
const rest = matchingIds ? items.filter((i) => !matchingIds.has(i.id)) : items;
|
|
6638
6716
|
const ordered = [...pinned, ...rest];
|
|
6639
|
-
const listRef = (0,
|
|
6640
|
-
(0,
|
|
6717
|
+
const listRef = (0, import_react30.useRef)(null);
|
|
6718
|
+
(0, import_react30.useEffect)(() => {
|
|
6641
6719
|
if (selectedId) listRef.current?.querySelector(`[data-item="${selectedId}"]`)?.scrollIntoView({ block: "nearest" });
|
|
6642
6720
|
}, [selectedId, items.length]);
|
|
6643
6721
|
const familyOf2 = (key) => definitions.find((d) => d.key === key)?.family ?? "generic";
|
|
@@ -6700,8 +6778,8 @@ function ListRow({ item, family, port, on, onSelect, withOwner, ownContextMenu,
|
|
|
6700
6778
|
const confirmed = useConfirmed();
|
|
6701
6779
|
const copy = useCopy();
|
|
6702
6780
|
const notify = useNotify();
|
|
6703
|
-
const [busy, setBusy] = (0,
|
|
6704
|
-
const [menuOpen, setMenuOpen] = (0,
|
|
6781
|
+
const [busy, setBusy] = (0, import_react30.useState)(false);
|
|
6782
|
+
const [menuOpen, setMenuOpen] = (0, import_react30.useState)(false);
|
|
6705
6783
|
const canUse = item.capabilities.canUse;
|
|
6706
6784
|
const user = canUse ? item.fields.find((f) => USERNAME_KEYS.test(f.key) && f.handling !== "sealed" && f.active !== false) : void 0;
|
|
6707
6785
|
const secret = canUse && item.capabilities.canReveal ? item.fields.find((f) => f.key === "password" && f.handling === "revealable" && f.active !== false) : void 0;
|
|
@@ -6740,7 +6818,7 @@ function ListRow({ item, family, port, on, onSelect, withOwner, ownContextMenu,
|
|
|
6740
6818
|
...manageEntries(item, onAction),
|
|
6741
6819
|
...hostEntries.map((h) => ({ ...h, kind: h.kind ?? "host" }))
|
|
6742
6820
|
];
|
|
6743
|
-
const entriesRef = (0,
|
|
6821
|
+
const entriesRef = (0, import_react30.useRef)(entries);
|
|
6744
6822
|
entriesRef.current = entries;
|
|
6745
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" });
|
|
6746
6824
|
const menuItem = (e) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_design_system19.DropdownMenuItem, { disabled: e.disabled ?? false, onSelect: e.onSelect, children: [
|
|
@@ -6763,21 +6841,25 @@ function ListRow({ item, family, port, on, onSelect, withOwner, ownContextMenu,
|
|
|
6763
6841
|
{
|
|
6764
6842
|
type: "button",
|
|
6765
6843
|
"aria-current": on ? "true" : void 0,
|
|
6766
|
-
|
|
6844
|
+
selected: on,
|
|
6845
|
+
selectedStyle: "primary",
|
|
6767
6846
|
onClick: () => onSelect(item.id),
|
|
6768
6847
|
layout: "row",
|
|
6769
6848
|
variant: "quiet",
|
|
6849
|
+
endInset: "control",
|
|
6850
|
+
oneLine: true,
|
|
6770
6851
|
icon: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ItemIcon, { definitionKey: item.definitionKey, family, site: loginSiteOf(item), inverted: on }),
|
|
6771
6852
|
title: item.name,
|
|
6772
6853
|
line: subtitleOf(item, withOwner),
|
|
6773
|
-
className: "w-full
|
|
6854
|
+
className: "w-full"
|
|
6774
6855
|
}
|
|
6775
6856
|
),
|
|
6776
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: [
|
|
6777
|
-
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: [
|
|
6778
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,
|
|
6779
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,
|
|
6780
|
-
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
|
|
6781
6863
|
] }) : null,
|
|
6782
6864
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_design_system19.DropdownMenu, { open: menuOpen, onOpenChange: setMenuOpen, children: [
|
|
6783
6865
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_design_system19.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
@@ -6818,7 +6900,7 @@ function manageEntries(item, onAction) {
|
|
|
6818
6900
|
}
|
|
6819
6901
|
|
|
6820
6902
|
// src/lists/TrashView.tsx
|
|
6821
|
-
var
|
|
6903
|
+
var import_react32 = require("react");
|
|
6822
6904
|
var import_controls25 = require("@ai-matrx/design-system/controls");
|
|
6823
6905
|
var import_format9 = require("@ai-matrx/kit/format");
|
|
6824
6906
|
|
|
@@ -6892,7 +6974,7 @@ function refusalText(reason) {
|
|
|
6892
6974
|
}
|
|
6893
6975
|
|
|
6894
6976
|
// src/lists/RestorePanel.tsx
|
|
6895
|
-
var
|
|
6977
|
+
var import_react31 = require("react");
|
|
6896
6978
|
var import_controls24 = require("@ai-matrx/design-system/controls");
|
|
6897
6979
|
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
6898
6980
|
var count = (n, one) => `${n} ${one}${n === 1 ? "" : "s"}`;
|
|
@@ -6903,13 +6985,13 @@ function RestorePanel({
|
|
|
6903
6985
|
turnOn,
|
|
6904
6986
|
onClose
|
|
6905
6987
|
}) {
|
|
6906
|
-
const [preview, setPreview] = (0,
|
|
6907
|
-
const [restored, setRestored] = (0,
|
|
6908
|
-
const [turnedOn, setTurnedOn] = (0,
|
|
6909
|
-
const [error, setError] = (0,
|
|
6910
|
-
const [busy, setBusy] = (0,
|
|
6911
|
-
const [loading, setLoading] = (0,
|
|
6912
|
-
(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)(() => {
|
|
6913
6995
|
if (!lists.preview) return;
|
|
6914
6996
|
let live = true;
|
|
6915
6997
|
lists.preview(item).then(
|
|
@@ -7013,10 +7095,10 @@ function trashLineOf(item) {
|
|
|
7013
7095
|
}
|
|
7014
7096
|
function TrashView({ port, deleted, query, header, onChanged }) {
|
|
7015
7097
|
const confirmed = useConfirmed();
|
|
7016
|
-
const [busyId, setBusyId] = (0,
|
|
7017
|
-
const [message2, setMessage] = (0,
|
|
7098
|
+
const [busyId, setBusyId] = (0, import_react32.useState)(null);
|
|
7099
|
+
const [message2, setMessage] = (0, import_react32.useState)(null);
|
|
7018
7100
|
const shown = deleted.filter((i) => trashItemMatchesQuery(i, query));
|
|
7019
|
-
const [restoring, setRestoring] = (0,
|
|
7101
|
+
const [restoring, setRestoring] = (0, import_react32.useState)(null);
|
|
7020
7102
|
const restore = async (item, deletionId) => {
|
|
7021
7103
|
setBusyId(item.id);
|
|
7022
7104
|
setMessage(null);
|
|
@@ -7064,15 +7146,15 @@ function TrashView({ port, deleted, query, header, onChanged }) {
|
|
|
7064
7146
|
}
|
|
7065
7147
|
|
|
7066
7148
|
// src/NewItemFlow.tsx
|
|
7067
|
-
var
|
|
7149
|
+
var import_react33 = require("react");
|
|
7068
7150
|
var import_controls26 = require("@ai-matrx/design-system/controls");
|
|
7069
7151
|
var import_icons13 = require("@ai-matrx/design-system/icons");
|
|
7070
7152
|
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
7071
7153
|
function NewItemFlow({ definitions, url, onUrl, onChoose, onCancel }) {
|
|
7072
|
-
const [search, setSearch] = (0,
|
|
7073
|
-
const guess = (0,
|
|
7154
|
+
const [search, setSearch] = (0, import_react33.useState)("");
|
|
7155
|
+
const guess = (0, import_react33.useMemo)(() => inferFromUrl(url, definitions), [url, definitions]);
|
|
7074
7156
|
const common = COMMON_DEFINITION_KEYS.map((k) => definitions.find((d) => d.key === k)).filter((d) => d !== void 0);
|
|
7075
|
-
const matches = (0,
|
|
7157
|
+
const matches = (0, import_react33.useMemo)(() => {
|
|
7076
7158
|
const q = search.trim().toLowerCase();
|
|
7077
7159
|
if (!q) return [];
|
|
7078
7160
|
return definitions.filter((d) => `${d.label} ${d.key} ${d.providerKey ?? ""} ${FAMILY_LABELS[d.family] ?? ""}`.toLowerCase().includes(q)).slice(0, 60);
|
|
@@ -7143,7 +7225,7 @@ function NewItemFlow({ definitions, url, onUrl, onChoose, onCancel }) {
|
|
|
7143
7225
|
}
|
|
7144
7226
|
|
|
7145
7227
|
// src/sharing/SecureLinkPanel.tsx
|
|
7146
|
-
var
|
|
7228
|
+
var import_react34 = require("react");
|
|
7147
7229
|
var import_confirm_opener11 = require("@ai-matrx/kit/confirm-opener");
|
|
7148
7230
|
var import_design_system21 = require("@ai-matrx/design-system");
|
|
7149
7231
|
var import_controls27 = require("@ai-matrx/design-system/controls");
|
|
@@ -7226,20 +7308,20 @@ var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
|
7226
7308
|
function SecureLinkPanel({ item, port, onClose }) {
|
|
7227
7309
|
const sharing = port.sharing;
|
|
7228
7310
|
const { busy, error, notice, run, setNotice } = useConfirmedChange();
|
|
7229
|
-
const [remedy, setRemedy] = (0,
|
|
7230
|
-
const [options, setOptions] = (0,
|
|
7231
|
-
const [optionsError, setOptionsError] = (0,
|
|
7232
|
-
const [sent, setSent] = (0,
|
|
7233
|
-
const [sentError, setSentError] = (0,
|
|
7234
|
-
const [nonce, setNonce] = (0,
|
|
7235
|
-
const [email, setEmail] = (0,
|
|
7236
|
-
const [phone, setPhone] = (0,
|
|
7237
|
-
const [name, setName] = (0,
|
|
7238
|
-
const [linkBy, setLinkBy] = (0,
|
|
7239
|
-
const [fields, setFields] = (0,
|
|
7240
|
-
const [note, setNote] = (0,
|
|
7241
|
-
const [sameChannelSent, setSameChannelSent] = (0,
|
|
7242
|
-
(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)(() => {
|
|
7243
7325
|
let live = true;
|
|
7244
7326
|
setOptionsError(null);
|
|
7245
7327
|
sharing.secureLinkOptions(item).then(
|
|
@@ -7254,7 +7336,7 @@ function SecureLinkPanel({ item, port, onClose }) {
|
|
|
7254
7336
|
live = false;
|
|
7255
7337
|
};
|
|
7256
7338
|
}, [sharing, item]);
|
|
7257
|
-
(0,
|
|
7339
|
+
(0, import_react34.useEffect)(() => {
|
|
7258
7340
|
const list = sharing.sentSecureLinks;
|
|
7259
7341
|
if (!list) return;
|
|
7260
7342
|
let live = true;
|
|
@@ -7267,9 +7349,9 @@ function SecureLinkPanel({ item, port, onClose }) {
|
|
|
7267
7349
|
live = false;
|
|
7268
7350
|
};
|
|
7269
7351
|
}, [sharing, item, nonce]);
|
|
7270
|
-
const [phoneTyped, setPhoneTyped] = (0,
|
|
7271
|
-
const prefilled = (0,
|
|
7272
|
-
(0,
|
|
7352
|
+
const [phoneTyped, setPhoneTyped] = (0, import_react34.useState)(false);
|
|
7353
|
+
const prefilled = (0, import_react34.useRef)(false);
|
|
7354
|
+
(0, import_react34.useEffect)(() => {
|
|
7273
7355
|
const lookup = sharing.phoneOnFile;
|
|
7274
7356
|
if (!lookup || phoneTyped) return;
|
|
7275
7357
|
const clear = () => {
|
|
@@ -7422,7 +7504,7 @@ function sentMeta(row, options) {
|
|
|
7422
7504
|
}
|
|
7423
7505
|
|
|
7424
7506
|
// src/devices/DevicesPanel.tsx
|
|
7425
|
-
var
|
|
7507
|
+
var import_react35 = require("react");
|
|
7426
7508
|
var import_confirm_opener12 = require("@ai-matrx/kit/confirm-opener");
|
|
7427
7509
|
var import_controls28 = require("@ai-matrx/design-system/controls");
|
|
7428
7510
|
var import_format12 = require("@ai-matrx/kit/format");
|
|
@@ -7513,10 +7595,10 @@ function ErrorLine2({ text }) {
|
|
|
7513
7595
|
function DevicesPanel({ port, onClose }) {
|
|
7514
7596
|
const confirmed = useConfirmed();
|
|
7515
7597
|
const notify = useNotify();
|
|
7516
|
-
const [devices, setDevices] = (0,
|
|
7517
|
-
const [error, setError] = (0,
|
|
7518
|
-
const [busyId, setBusyId] = (0,
|
|
7519
|
-
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 () => {
|
|
7520
7602
|
setError(null);
|
|
7521
7603
|
try {
|
|
7522
7604
|
setDevices(await port.devices.list());
|
|
@@ -7524,7 +7606,7 @@ function DevicesPanel({ port, onClose }) {
|
|
|
7524
7606
|
setError(messageOf3(e, "Your browsers could not be read."));
|
|
7525
7607
|
}
|
|
7526
7608
|
}, [port]);
|
|
7527
|
-
(0,
|
|
7609
|
+
(0, import_react35.useEffect)(() => {
|
|
7528
7610
|
void load();
|
|
7529
7611
|
}, [load]);
|
|
7530
7612
|
const revoke = async (device) => {
|
|
@@ -7582,11 +7664,11 @@ function ApprovePanel({ port, host, onClose, approvalKey, label, kind = "browser
|
|
|
7582
7664
|
const where = isMac ? "the Mac app" : "the extension";
|
|
7583
7665
|
const passkeys = port.devices.passkeys;
|
|
7584
7666
|
const here = passkeys?.available() ?? false;
|
|
7585
|
-
const [methods, setMethods] = (0,
|
|
7586
|
-
const [busy, setBusy] = (0,
|
|
7587
|
-
const [error, setError] = (0,
|
|
7588
|
-
const [approvedUntil, setApprovedUntil] = (0,
|
|
7589
|
-
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 () => {
|
|
7590
7672
|
setError(null);
|
|
7591
7673
|
try {
|
|
7592
7674
|
setMethods(await port.devices.stepUpMethods());
|
|
@@ -7594,7 +7676,7 @@ function ApprovePanel({ port, host, onClose, approvalKey, label, kind = "browser
|
|
|
7594
7676
|
setError(messageOf3(e, "Your account could not be checked."));
|
|
7595
7677
|
}
|
|
7596
7678
|
}, [port]);
|
|
7597
|
-
(0,
|
|
7679
|
+
(0, import_react35.useEffect)(() => {
|
|
7598
7680
|
if (key && here) void load();
|
|
7599
7681
|
}, [key, here, load]);
|
|
7600
7682
|
const approve = async () => {
|
|
@@ -7682,7 +7764,7 @@ function ApprovePanel({ port, host, onClose, approvalKey, label, kind = "browser
|
|
|
7682
7764
|
}
|
|
7683
7765
|
|
|
7684
7766
|
// src/native/NativeImportPanel.tsx
|
|
7685
|
-
var
|
|
7767
|
+
var import_react37 = require("react");
|
|
7686
7768
|
var import_confirm_opener13 = require("@ai-matrx/kit/confirm-opener");
|
|
7687
7769
|
var import_controls29 = require("@ai-matrx/design-system/controls");
|
|
7688
7770
|
|
|
@@ -7745,19 +7827,19 @@ async function loadFullPreview(bridge, operationId, current) {
|
|
|
7745
7827
|
}
|
|
7746
7828
|
|
|
7747
7829
|
// src/native/use-native-import.ts
|
|
7748
|
-
var
|
|
7830
|
+
var import_react36 = require("react");
|
|
7749
7831
|
var fail = (e, fallback) => e instanceof Error && e.message ? e.message : fallback;
|
|
7750
7832
|
var RESTART = "Your account changed. The import was stopped; start it again.";
|
|
7751
7833
|
function useNativeImport(bridge, stillAllowed, onImported) {
|
|
7752
|
-
const [screen, setScreen] = (0,
|
|
7753
|
-
const [busy, setBusy] = (0,
|
|
7754
|
-
const generation = (0,
|
|
7755
|
-
const mounted = (0,
|
|
7756
|
-
const op = (0,
|
|
7757
|
-
const last = (0,
|
|
7758
|
-
const timer2 = (0,
|
|
7759
|
-
const polls = (0,
|
|
7760
|
-
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);
|
|
7761
7843
|
const current = (g) => mounted.current && g === generation.current;
|
|
7762
7844
|
const stopPolling = () => {
|
|
7763
7845
|
if (timer2.current !== null) clearTimeout(timer2.current);
|
|
@@ -7926,9 +8008,9 @@ function useNativeImport(bridge, stillAllowed, onImported) {
|
|
|
7926
8008
|
setBusy(false);
|
|
7927
8009
|
setScreen({ kind: "idle", message: null });
|
|
7928
8010
|
};
|
|
7929
|
-
const invalidateRef = (0,
|
|
8011
|
+
const invalidateRef = (0, import_react36.useRef)(invalidate);
|
|
7930
8012
|
invalidateRef.current = invalidate;
|
|
7931
|
-
(0,
|
|
8013
|
+
(0, import_react36.useEffect)(() => {
|
|
7932
8014
|
mounted.current = true;
|
|
7933
8015
|
const off = bridge.subscribe?.(() => {
|
|
7934
8016
|
if (op.current) invalidateRef.current(RESTART);
|
|
@@ -7960,14 +8042,14 @@ function NativeImportPanel({ bridge, readLimits, activeOrganizationId, organizat
|
|
|
7960
8042
|
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Importer, { bridge, readLimits, activeOrganizationId, organizations, onClose, onChanged });
|
|
7961
8043
|
}
|
|
7962
8044
|
function Importer({ bridge, readLimits, activeOrganizationId, organizations, onClose, onChanged }) {
|
|
7963
|
-
const options = (0,
|
|
7964
|
-
const [organizationId, setOrganizationId] = (0,
|
|
7965
|
-
const [limits, setLimits] = (0,
|
|
7966
|
-
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);
|
|
7967
8049
|
const flow = useNativeImport(bridge, (id) => organizations.some((o) => o.id === id), onChanged);
|
|
7968
8050
|
const { screen, busy } = flow;
|
|
7969
8051
|
const orgName = organizations.find((o) => o.id === organizationId)?.name ?? "this organization";
|
|
7970
|
-
(0,
|
|
8052
|
+
(0, import_react37.useEffect)(() => {
|
|
7971
8053
|
if (!readLimits || !organizationId) return;
|
|
7972
8054
|
let live = true;
|
|
7973
8055
|
setLimits(null);
|
|
@@ -8028,21 +8110,21 @@ function Importer({ bridge, readLimits, activeOrganizationId, organizations, onC
|
|
|
8028
8110
|
}
|
|
8029
8111
|
|
|
8030
8112
|
// src/extension/PageView.tsx
|
|
8031
|
-
var
|
|
8113
|
+
var import_react41 = require("react");
|
|
8032
8114
|
var import_design_system23 = require("@ai-matrx/design-system");
|
|
8033
8115
|
var import_controls33 = require("@ai-matrx/design-system/controls");
|
|
8034
8116
|
var import_icons15 = require("@ai-matrx/design-system/icons");
|
|
8035
8117
|
|
|
8036
8118
|
// src/extension/CaptureCard.tsx
|
|
8037
|
-
var
|
|
8119
|
+
var import_react38 = require("react");
|
|
8038
8120
|
var import_controls30 = require("@ai-matrx/design-system/controls");
|
|
8039
8121
|
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
8040
8122
|
var SEARCH_FROM = 4;
|
|
8041
8123
|
function CaptureCard({ capture, onChanged }) {
|
|
8042
|
-
const prompt = (0,
|
|
8124
|
+
const prompt = (0, import_react38.useSyncExternalStore)(capture.subscribe, capture.get, capture.get);
|
|
8043
8125
|
const notify = useNotify();
|
|
8044
|
-
const [busy, setBusy] = (0,
|
|
8045
|
-
const [q, setQ] = (0,
|
|
8126
|
+
const [busy, setBusy] = (0, import_react38.useState)(false);
|
|
8127
|
+
const [q, setQ] = (0, import_react38.useState)("");
|
|
8046
8128
|
if (!prompt) return null;
|
|
8047
8129
|
const decide = async (d) => {
|
|
8048
8130
|
setBusy(true);
|
|
@@ -8098,15 +8180,15 @@ function CaptureCard({ capture, onChanged }) {
|
|
|
8098
8180
|
}
|
|
8099
8181
|
|
|
8100
8182
|
// src/extension/FillSetupCard.tsx
|
|
8101
|
-
var
|
|
8183
|
+
var import_react39 = require("react");
|
|
8102
8184
|
var import_controls31 = require("@ai-matrx/design-system/controls");
|
|
8103
8185
|
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
8104
8186
|
function FillSetupCard({ fillSetup }) {
|
|
8105
8187
|
const notify = useNotify();
|
|
8106
|
-
const state = (0,
|
|
8107
|
-
const box = (0,
|
|
8108
|
-
const [busy, setBusy] = (0,
|
|
8109
|
-
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);
|
|
8110
8192
|
if (state.status !== "off") return null;
|
|
8111
8193
|
const finish = async (run) => {
|
|
8112
8194
|
setBusy(true);
|
|
@@ -8171,7 +8253,7 @@ function FillSetupCard({ fillSetup }) {
|
|
|
8171
8253
|
}
|
|
8172
8254
|
|
|
8173
8255
|
// src/extension/PageGenerator.tsx
|
|
8174
|
-
var
|
|
8256
|
+
var import_react40 = require("react");
|
|
8175
8257
|
var import_design_system22 = require("@ai-matrx/design-system");
|
|
8176
8258
|
var import_controls32 = require("@ai-matrx/design-system/controls");
|
|
8177
8259
|
var import_icons14 = require("@ai-matrx/design-system/icons");
|
|
@@ -8181,10 +8263,10 @@ function PageGenerator({ fields }) {
|
|
|
8181
8263
|
const limits = useGeneratorLimitsSource();
|
|
8182
8264
|
const copy = useCopy();
|
|
8183
8265
|
const held = useTransientSecret(HOLD_MS);
|
|
8184
|
-
const [open, setOpen] = (0,
|
|
8185
|
-
const [busy, setBusy] = (0,
|
|
8186
|
-
const [targets, setTargets] = (0,
|
|
8187
|
-
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);
|
|
8188
8270
|
if (!limits) return null;
|
|
8189
8271
|
const say3 = setSaid;
|
|
8190
8272
|
const put = async (targetId, value2) => {
|
|
@@ -8248,8 +8330,8 @@ function PageGenerator({ fields }) {
|
|
|
8248
8330
|
// src/extension/PageView.tsx
|
|
8249
8331
|
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
8250
8332
|
function PageView({ port, page, fill, capture, fillSetup, newPasswordFields, items, definitions, onOpen, onNewForPage, onBrowse, onChanged, header }) {
|
|
8251
|
-
const [running, setRunning] = (0,
|
|
8252
|
-
const [said, setSaid] = (0,
|
|
8333
|
+
const [running, setRunning] = (0, import_react41.useState)(null);
|
|
8334
|
+
const [said, setSaid] = (0, import_react41.useState)(null);
|
|
8253
8335
|
const site = pageSite(page.url);
|
|
8254
8336
|
const state = page.matchState ?? { status: "ready" };
|
|
8255
8337
|
const fillable = new Set(page.fillableItemIds ?? page.matchingItemIds);
|
|
@@ -8258,8 +8340,8 @@ function PageView({ port, page, fill, capture, fillSetup, newPasswordFields, ite
|
|
|
8258
8340
|
const familyOf2 = (key) => definitions.find((d) => d.key === key)?.family ?? "generic";
|
|
8259
8341
|
const canSave = isFillablePage(page.url);
|
|
8260
8342
|
const signIn = page.signIn;
|
|
8261
|
-
const act = async (itemId, run, failed) => {
|
|
8262
|
-
setRunning(itemId);
|
|
8343
|
+
const act = async (itemId, action, run, failed) => {
|
|
8344
|
+
setRunning({ itemId, action });
|
|
8263
8345
|
setSaid(null);
|
|
8264
8346
|
try {
|
|
8265
8347
|
setSaid(await run());
|
|
@@ -8292,10 +8374,10 @@ function PageView({ port, page, fill, capture, fillSetup, newPasswordFields, ite
|
|
|
8292
8374
|
family: item ? familyOf2(item.definitionKey) : "generic",
|
|
8293
8375
|
port,
|
|
8294
8376
|
busy: running !== null,
|
|
8295
|
-
running: running === itemId,
|
|
8377
|
+
running: running?.itemId === itemId ? running.action : null,
|
|
8296
8378
|
onOpen,
|
|
8297
|
-
onFill: fill && !page.blocked && fillable.has(itemId) && item?.capabilities.canUse !== false ? () => void act(itemId, async () => FILL_WORDS[await fill(itemId)], FILL_WORDS.unavailable) : null,
|
|
8298
|
-
onSignIn: signIn ? () => void act(itemId, async () => SIGN_IN_WORDS[await signIn(itemId)], SIGN_IN_WORDS.unknown) : null
|
|
8379
|
+
onFill: fill && !page.blocked && fillable.has(itemId) && item?.capabilities.canUse !== false ? () => void act(itemId, "fill", async () => FILL_WORDS[await fill(itemId)], FILL_WORDS.unavailable) : null,
|
|
8380
|
+
onSignIn: signIn ? () => void act(itemId, "signIn", async () => SIGN_IN_WORDS[await signIn(itemId)], SIGN_IN_WORDS.unknown) : null
|
|
8299
8381
|
},
|
|
8300
8382
|
itemId
|
|
8301
8383
|
)) });
|
|
@@ -8333,7 +8415,7 @@ function MatchRow({ itemId, item, tag, family, port, busy, running, onOpen, onFi
|
|
|
8333
8415
|
const confirmed = useConfirmed();
|
|
8334
8416
|
const copy = useCopy();
|
|
8335
8417
|
const notify = useNotify();
|
|
8336
|
-
const [reading, setReading] = (0,
|
|
8418
|
+
const [reading, setReading] = (0, import_react41.useState)(false);
|
|
8337
8419
|
const usable = item?.capabilities.canUse ?? false;
|
|
8338
8420
|
const user = usable ? item?.fields.find((f) => USERNAME_KEYS.test(f.key) && f.handling !== "sealed" && f.active) : void 0;
|
|
8339
8421
|
const secret = usable && item?.capabilities.canReveal ? item?.fields.find((f) => f.key === "password" && f.handling === "revealable" && f.active) : void 0;
|
|
@@ -8362,8 +8444,8 @@ function MatchRow({ itemId, item, tag, family, port, busy, running, onOpen, onFi
|
|
|
8362
8444
|
className: "min-w-0 flex-1"
|
|
8363
8445
|
}
|
|
8364
8446
|
),
|
|
8365
|
-
onFill ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_controls33.Button, { variant: "primary", disabled: busy, "aria-busy": running || void 0, onClick: onFill, "aria-label": `Fill ${item?.name ?? "this login"}`, children: running ? "Filling\u2026" : "Fill" }) : null,
|
|
8366
|
-
onSignIn ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_controls33.Button, { variant: onFill ? "outline" : "primary", icon: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ShieldGlyph, {}), disabled: busy, onClick: onSignIn, "aria-label": `Sign me in with ${item?.name ?? "this login"}`, title: "Sign me in", children: "Sign me in" }) : null,
|
|
8447
|
+
onFill ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_controls33.Button, { variant: "primary", disabled: busy, "aria-busy": running === "fill" || void 0, onClick: onFill, "aria-label": `Fill ${item?.name ?? "this login"}`, children: running === "fill" ? "Filling\u2026" : "Fill" }) : null,
|
|
8448
|
+
onSignIn ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_controls33.Button, { variant: onFill ? "outline" : "primary", icon: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ShieldGlyph, {}), disabled: busy, "aria-busy": running === "signIn" || void 0, onClick: onSignIn, "aria-label": `Sign me in with ${item?.name ?? "this login"}`, title: "Sign me in", children: running === "signIn" ? "Signing in\u2026" : "Sign me in" }) : null,
|
|
8367
8449
|
user && item ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_controls33.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(UserGlyph, {}), "aria-label": `Copy ${user.label}`, title: `Copy ${user.label}`, disabled: reading, onClick: () => void read(user.label, () => port.reveal(item, user.key)) }) : null,
|
|
8368
8450
|
secret && item ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_controls33.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(KeyGlyph, {}), "aria-label": "Copy password", title: "Copy password", disabled: reading, onClick: () => void read("Password", () => port.reveal(item, secret.key)) }) : null,
|
|
8369
8451
|
otp ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_controls33.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ClockGlyph, {}), "aria-label": "Copy one-time code", title: "Copy one-time code", disabled: reading, onClick: () => void read("One-time code", async () => (await port.authenticator.code(otp)).code) }) : null
|
|
@@ -8371,7 +8453,7 @@ function MatchRow({ itemId, item, tag, family, port, busy, running, onOpen, onFi
|
|
|
8371
8453
|
}
|
|
8372
8454
|
|
|
8373
8455
|
// src/Sidebar.tsx
|
|
8374
|
-
var
|
|
8456
|
+
var import_react42 = require("react");
|
|
8375
8457
|
var import_design_system24 = require("@ai-matrx/design-system");
|
|
8376
8458
|
var import_controls34 = require("@ai-matrx/design-system/controls");
|
|
8377
8459
|
var import_icons16 = require("@ai-matrx/design-system/icons");
|
|
@@ -8380,6 +8462,7 @@ var AUTHENTICATOR_LABEL = "Authenticator";
|
|
|
8380
8462
|
function vaultChoices(items, organizations, _current) {
|
|
8381
8463
|
const n = (f) => items.filter(f).length;
|
|
8382
8464
|
const shared = n((i) => i.owner.kind === "shared");
|
|
8465
|
+
const hints = organizationHints(organizations);
|
|
8383
8466
|
return [
|
|
8384
8467
|
{ value: "all", label: "All items", count: items.length },
|
|
8385
8468
|
{ value: "mine", label: "Personal", count: n((i) => i.owner.kind === "me") },
|
|
@@ -8387,11 +8470,11 @@ function vaultChoices(items, organizations, _current) {
|
|
|
8387
8470
|
// Every organization the person belongs to, empty ones too: an empty vault opens on its own
|
|
8388
8471
|
// "Nothing here yet" with New item, so the first credential can go there. (The organization
|
|
8389
8472
|
// list carries no role, so who may add is the server's answer to the save, said in place.)
|
|
8390
|
-
...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) } : {} }))
|
|
8391
8474
|
];
|
|
8392
8475
|
}
|
|
8393
|
-
function VaultSelect({ value, choices, onChange }) {
|
|
8394
|
-
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 } : {} })) });
|
|
8395
8478
|
}
|
|
8396
8479
|
var CATEGORY_GLYPHS = { logins: import_icons16.GlobeIcon, passkeys: ShieldGlyph, api: KeyGlyph, oauth: PlugGlyph, infra: DatabaseGlyph, env: TerminalGlyph, files: FileGlyph, other: NoteGlyph };
|
|
8397
8480
|
var familyOf = (key, definitions) => definitions.find((d) => d.key === key)?.family ?? "generic";
|
|
@@ -8455,12 +8538,14 @@ function viewOptions(views, allCount, deletedCount, hasFavorites, hasRecents, ha
|
|
|
8455
8538
|
];
|
|
8456
8539
|
}
|
|
8457
8540
|
function Entry({ on, glyph: Icon, label, count: count2, onClick, nested = false }) {
|
|
8541
|
+
const desktop = (0, import_design_system24.useLook)() === "desktop";
|
|
8458
8542
|
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
8459
8543
|
import_controls34.Tile,
|
|
8460
8544
|
{
|
|
8461
8545
|
type: "button",
|
|
8462
8546
|
"aria-current": on ? "page" : void 0,
|
|
8463
8547
|
selected: on,
|
|
8548
|
+
...desktop ? { selectedStyle: "fill" } : {},
|
|
8464
8549
|
onClick,
|
|
8465
8550
|
layout: "row",
|
|
8466
8551
|
variant: "quiet",
|
|
@@ -8468,8 +8553,9 @@ function Entry({ on, glyph: Icon, label, count: count2, onClick, nested = false
|
|
|
8468
8553
|
icon: nested ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Icon, { className: "size-4 shrink-0" }),
|
|
8469
8554
|
title: label,
|
|
8470
8555
|
...count2 !== void 0 ? { end: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "text-xs tabular-nums text-muted-foreground", children: count2 }) } : {},
|
|
8556
|
+
...nested ? { level: 1 } : {},
|
|
8471
8557
|
"data-nested": nested ? "" : void 0,
|
|
8472
|
-
className:
|
|
8558
|
+
className: "w-full"
|
|
8473
8559
|
}
|
|
8474
8560
|
);
|
|
8475
8561
|
}
|
|
@@ -8479,12 +8565,12 @@ function Group({ title, children }) {
|
|
|
8479
8565
|
children
|
|
8480
8566
|
] });
|
|
8481
8567
|
}
|
|
8482
|
-
function VaultSidebar({ vault, choices, onVault, view, allCount, deletedCount, views, hasFavorites, hasRecents, onView, onPanel, nativeProvider, hasNativeImport = false, hasPage = false, onLock, onOpenWeb }) {
|
|
8483
|
-
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:"));
|
|
8484
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: [
|
|
8485
8571
|
/* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex items-center gap-2 px-3 pb-2 pt-3", children: [
|
|
8486
8572
|
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(SafeGlyph, { className: "size-5 shrink-0 text-primary" }),
|
|
8487
|
-
/* @__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 }) })
|
|
8488
8574
|
] }),
|
|
8489
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: [
|
|
8490
8576
|
/* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-col gap-0.5", children: [
|
|
@@ -8561,8 +8647,8 @@ var generatorLimitsFrom = (knobs) => knobs ? async () => {
|
|
|
8561
8647
|
} : void 0;
|
|
8562
8648
|
function ImportWithLimits(props) {
|
|
8563
8649
|
const { knobs, ...rest } = props;
|
|
8564
|
-
const [state, setState] = (0,
|
|
8565
|
-
(0,
|
|
8650
|
+
const [state, setState] = (0, import_react43.useState)(null);
|
|
8651
|
+
(0, import_react43.useEffect)(() => {
|
|
8566
8652
|
if (!knobs) return setState({ error: "Import is not set up for this organization yet." });
|
|
8567
8653
|
knobs().then(
|
|
8568
8654
|
(r) => {
|
|
@@ -8582,18 +8668,18 @@ function VaultApp(given) {
|
|
|
8582
8668
|
const props = { ...given, host: useOrganizationSettings(given.host ?? NO_HOST) };
|
|
8583
8669
|
const lock = props.host?.lock;
|
|
8584
8670
|
const locked = useLocked(lock);
|
|
8585
|
-
const port = (0,
|
|
8671
|
+
const port = (0, import_react43.useMemo)(() => lock ? guardPort(props.port, () => lock.locked()) : props.port, [props.port, lock]);
|
|
8586
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 }) }) }) }) }) }) }) });
|
|
8587
8673
|
}
|
|
8588
8674
|
function useOrganizationSettings(host) {
|
|
8589
8675
|
const knobs = host.knobs;
|
|
8590
|
-
const needs = knobs !== void 0 && (host.revealSeconds === void 0 || host.backupPassphraseMinLength === void 0);
|
|
8591
|
-
const [read, setRead] = (0,
|
|
8592
|
-
(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)(() => {
|
|
8593
8679
|
if (!needs || !knobs) return;
|
|
8594
8680
|
let live = true;
|
|
8595
8681
|
knobs().then(
|
|
8596
|
-
(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) }),
|
|
8597
8683
|
() => void 0
|
|
8598
8684
|
);
|
|
8599
8685
|
return () => {
|
|
@@ -8604,19 +8690,20 @@ function useOrganizationSettings(host) {
|
|
|
8604
8690
|
return {
|
|
8605
8691
|
...host,
|
|
8606
8692
|
...host.revealSeconds === void 0 && read.reveal !== null ? { revealSeconds: read.reveal } : {},
|
|
8607
|
-
...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 } : {}
|
|
8608
8695
|
};
|
|
8609
8696
|
}
|
|
8610
8697
|
var NO_STORE = () => () => void 0;
|
|
8611
8698
|
var NOTHING = () => null;
|
|
8612
8699
|
function useHostPrompts(capture, fillSetup) {
|
|
8613
|
-
const prompt = (0,
|
|
8614
|
-
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);
|
|
8615
8702
|
return prompt !== null || setup?.status === "off";
|
|
8616
8703
|
}
|
|
8617
8704
|
function LockedScreen({ lock }) {
|
|
8618
|
-
const [busy, setBusy] = (0,
|
|
8619
|
-
const [error, setError] = (0,
|
|
8705
|
+
const [busy, setBusy] = (0, import_react43.useState)(false);
|
|
8706
|
+
const [error, setError] = (0, import_react43.useState)(null);
|
|
8620
8707
|
const unlock = async () => {
|
|
8621
8708
|
setBusy(true);
|
|
8622
8709
|
setError(null);
|
|
@@ -8636,29 +8723,29 @@ function LockedScreen({ lock }) {
|
|
|
8636
8723
|
] });
|
|
8637
8724
|
}
|
|
8638
8725
|
function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocationChange, onInventory }) {
|
|
8639
|
-
const rootRef = (0,
|
|
8726
|
+
const rootRef = (0, import_react43.useRef)(null);
|
|
8640
8727
|
const width = useElementWidth(rootRef);
|
|
8641
8728
|
const mode = layout !== "auto" ? layout : width >= FULL_AT ? "full" : width >= SPLIT_AT ? "split" : "stack";
|
|
8642
8729
|
const notify = useNotify();
|
|
8643
|
-
const [snap, setSnap] = (0,
|
|
8644
|
-
const [items, setItems] = (0,
|
|
8645
|
-
const [deleted, setDeleted] = (0,
|
|
8646
|
-
const [favorites, setFavorites] = (0,
|
|
8647
|
-
const [recents, setRecents] = (0,
|
|
8648
|
-
const [error, setError] = (0,
|
|
8649
|
-
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);
|
|
8650
8737
|
const loc = location ?? inner;
|
|
8651
|
-
const dirty = (0,
|
|
8652
|
-
const [notice, setNotice] = (0,
|
|
8653
|
-
const [firstCode, setFirstCode] = (
|
|
8654
|
-
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)(
|
|
8655
8742
|
(next, how) => {
|
|
8656
8743
|
if (!location) setInner(next);
|
|
8657
8744
|
onLocationChange?.(next, how);
|
|
8658
8745
|
},
|
|
8659
8746
|
[location, onLocationChange]
|
|
8660
8747
|
);
|
|
8661
|
-
const go = (0,
|
|
8748
|
+
const go = (0, import_react43.useCallback)(
|
|
8662
8749
|
(patch, how = "push") => {
|
|
8663
8750
|
const leaving = patch.itemId !== void 0 || patch.mode !== void 0 || patch.vault !== void 0 || patch.view !== void 0;
|
|
8664
8751
|
const next = { ...loc, ...patch };
|
|
@@ -8677,9 +8764,9 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8677
8764
|
},
|
|
8678
8765
|
[loc, move]
|
|
8679
8766
|
);
|
|
8680
|
-
const keyState = (0,
|
|
8767
|
+
const keyState = (0, import_react43.useRef)({ loc, go });
|
|
8681
8768
|
keyState.current = { loc, go };
|
|
8682
|
-
(0,
|
|
8769
|
+
(0, import_react43.useEffect)(() => {
|
|
8683
8770
|
const onKey = (e) => {
|
|
8684
8771
|
if (e.defaultPrevented || e.metaKey || e.ctrlKey || e.altKey) return;
|
|
8685
8772
|
const root = rootRef.current;
|
|
@@ -8701,8 +8788,8 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8701
8788
|
document.addEventListener("keydown", onKey);
|
|
8702
8789
|
return () => document.removeEventListener("keydown", onKey);
|
|
8703
8790
|
}, []);
|
|
8704
|
-
const keepSearchFocus = (0,
|
|
8705
|
-
(0,
|
|
8791
|
+
const keepSearchFocus = (0, import_react43.useRef)(false);
|
|
8792
|
+
(0, import_react43.useEffect)(() => {
|
|
8706
8793
|
if (!keepSearchFocus.current) return;
|
|
8707
8794
|
keepSearchFocus.current = false;
|
|
8708
8795
|
const search = rootRef.current?.querySelector('input[aria-label^="Search"]');
|
|
@@ -8711,14 +8798,14 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8711
8798
|
search.setSelectionRange(search.value.length, search.value.length);
|
|
8712
8799
|
}, [loc.q]);
|
|
8713
8800
|
const hasPrompts = useHostPrompts(host.capture, host.fillSetup);
|
|
8714
|
-
const knobsRef = (0,
|
|
8801
|
+
const knobsRef = (0, import_react43.useRef)(host.knobs);
|
|
8715
8802
|
knobsRef.current = host.knobs;
|
|
8716
|
-
const [signedOut, setSignedOut] = (0,
|
|
8717
|
-
const [refreshError, setRefreshError] = (0,
|
|
8718
|
-
const [refreshing, setRefreshing] = (0,
|
|
8719
|
-
const loadedAt = (0,
|
|
8720
|
-
const inFlight = (0,
|
|
8721
|
-
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)(
|
|
8722
8809
|
(s) => {
|
|
8723
8810
|
loadedAt.current = Date.now();
|
|
8724
8811
|
setSnap(s);
|
|
@@ -8731,7 +8818,7 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8731
8818
|
},
|
|
8732
8819
|
[port]
|
|
8733
8820
|
);
|
|
8734
|
-
const refresh = (0,
|
|
8821
|
+
const refresh = (0, import_react43.useCallback)(() => {
|
|
8735
8822
|
if (inFlight.current) return;
|
|
8736
8823
|
inFlight.current = true;
|
|
8737
8824
|
setRefreshing(true);
|
|
@@ -8745,7 +8832,7 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8745
8832
|
port.lists.favorites?.list().then((ids) => setFavorites(new Set(ids)), () => void 0);
|
|
8746
8833
|
port.lists.recents?.list().then(setRecents, () => void 0);
|
|
8747
8834
|
}, [port, apply]);
|
|
8748
|
-
const load = (0,
|
|
8835
|
+
const load = (0, import_react43.useCallback)(() => {
|
|
8749
8836
|
setError(null);
|
|
8750
8837
|
setRefreshError(null);
|
|
8751
8838
|
let finished = false;
|
|
@@ -8765,11 +8852,11 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8765
8852
|
knobsRef.current?.().catch(() => void 0);
|
|
8766
8853
|
port.lists.recents?.list().then(setRecents, () => void 0);
|
|
8767
8854
|
}, [port, apply]);
|
|
8768
|
-
(0,
|
|
8769
|
-
const quietRef = (0,
|
|
8855
|
+
(0, import_react43.useEffect)(load, [load]);
|
|
8856
|
+
const quietRef = (0, import_react43.useRef)({ loc, ready: false });
|
|
8770
8857
|
quietRef.current = { loc, ready: snap !== null && !error };
|
|
8771
|
-
const [knobSeconds, setKnobSeconds] = (0,
|
|
8772
|
-
(0,
|
|
8858
|
+
const [knobSeconds, setKnobSeconds] = (0, import_react43.useState)(null);
|
|
8859
|
+
(0, import_react43.useEffect)(() => {
|
|
8773
8860
|
if (host.refreshSeconds !== void 0 || !knobsRef.current) return;
|
|
8774
8861
|
let live = true;
|
|
8775
8862
|
knobsRef.current().then(
|
|
@@ -8784,7 +8871,7 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8784
8871
|
};
|
|
8785
8872
|
}, [host.refreshSeconds]);
|
|
8786
8873
|
const everySeconds = host.refreshSeconds ?? knobSeconds;
|
|
8787
|
-
(0,
|
|
8874
|
+
(0, import_react43.useEffect)(() => {
|
|
8788
8875
|
const quietly = (minGapMs) => {
|
|
8789
8876
|
const { loc: here, ready } = quietRef.current;
|
|
8790
8877
|
if (!ready || document.visibilityState === "hidden" || dirty.current || here.mode !== "view") return;
|
|
@@ -8802,22 +8889,22 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8802
8889
|
if (timer2) clearInterval(timer2);
|
|
8803
8890
|
};
|
|
8804
8891
|
}, [refresh, everySeconds]);
|
|
8805
|
-
const inventoryRef = (0,
|
|
8892
|
+
const inventoryRef = (0, import_react43.useRef)(onInventory);
|
|
8806
8893
|
inventoryRef.current = onInventory;
|
|
8807
|
-
(0,
|
|
8894
|
+
(0, import_react43.useEffect)(() => {
|
|
8808
8895
|
if (snap) inventoryRef.current?.({ items, definitions: snap.definitions });
|
|
8809
8896
|
}, [snap, items]);
|
|
8810
|
-
(0,
|
|
8897
|
+
(0, import_react43.useEffect)(() => {
|
|
8811
8898
|
if (!loc.itemId || !port.lists.recents) return;
|
|
8812
8899
|
const id = loc.itemId;
|
|
8813
8900
|
port.lists.recents.record(id).then(() => setRecents((r) => [id, ...(r ?? []).filter((x) => x !== id)]), () => void 0);
|
|
8814
8901
|
}, [loc.itemId, port]);
|
|
8815
|
-
const orgs = snap?.organizations ?? [];
|
|
8902
|
+
const orgs = (0, import_react43.useMemo)(() => orderOrganizations(snap?.organizations ?? [], items, recents), [snap?.organizations, items, recents]);
|
|
8816
8903
|
const definitions = snap?.definitions ?? [];
|
|
8817
|
-
const inThisVault = (0,
|
|
8904
|
+
const inThisVault = (0, import_react43.useMemo)(() => items.filter((i) => inVault(i, loc.vault)), [items, loc.vault]);
|
|
8818
8905
|
const vaultMixesOwners = new Set(inThisVault.map((i) => i.owner.organizationId ?? i.owner.kind)).size > 1;
|
|
8819
|
-
const views = (0,
|
|
8820
|
-
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)(() => {
|
|
8821
8908
|
const filtered = inThisVault.filter((i) => {
|
|
8822
8909
|
if (!matchesQuery(i, loc.q, familyLabel(itemFamily(i, definitions)))) return false;
|
|
8823
8910
|
if (loc.view === "favorites") return favorites?.has(i.id) ?? false;
|
|
@@ -8829,8 +8916,8 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8829
8916
|
if (loc.view === "recent" && recents) return [...filtered].sort((a, b) => recents.indexOf(a.id) - recents.indexOf(b.id));
|
|
8830
8917
|
return sortItems(filtered, loc.sort, recents);
|
|
8831
8918
|
}, [inThisVault, loc.view, loc.q, loc.sort, favorites, recents, definitions]);
|
|
8832
|
-
const choices = (0,
|
|
8833
|
-
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]);
|
|
8834
8921
|
const selected = loc.itemId ? items.find((i) => i.id === loc.itemId) ?? null : null;
|
|
8835
8922
|
const replaceItem = (next) => setItems((cur) => cur.some((i) => i.id === next.id) ? cur.map((i) => i.id === next.id ? next : i) : [...cur, next]);
|
|
8836
8923
|
const toggleFavorite = (id) => {
|
|
@@ -8895,7 +8982,7 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8895
8982
|
const hasFavorites = port.lists.favorites !== void 0;
|
|
8896
8983
|
const title = loc.vault === "all" && loc.view === "all" ? "All items" : viewLabel(loc.view, views);
|
|
8897
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: [
|
|
8898
|
-
/* @__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 }) }),
|
|
8899
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" })
|
|
8900
8987
|
] });
|
|
8901
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: [
|
|
@@ -9132,6 +9219,11 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
9132
9219
|
arg: panelArg ?? null,
|
|
9133
9220
|
onClose: closePanel,
|
|
9134
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
|
+
},
|
|
9135
9227
|
onChanged: (next) => {
|
|
9136
9228
|
if (next) replaceItem(next);
|
|
9137
9229
|
else if (next === null) {
|
|
@@ -9171,6 +9263,7 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
9171
9263
|
vault: loc.vault,
|
|
9172
9264
|
choices,
|
|
9173
9265
|
onVault: (vault) => go({ vault, itemId: null, panel: null }),
|
|
9266
|
+
organizationSearchAt: host.organizationSearchAt,
|
|
9174
9267
|
view: loc.view,
|
|
9175
9268
|
allCount: inThisVault.length,
|
|
9176
9269
|
deletedCount: deleted.length,
|