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