@ai-matrx/vault 0.1.9 → 0.1.11

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.js CHANGED
@@ -164,6 +164,7 @@ import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } f
164
164
  import { Button, Field } from "@ai-matrx/design-system/controls";
165
165
 
166
166
  // src/glyphs.tsx
167
+ import { GlobeIcon } from "@ai-matrx/design-system/icons";
167
168
  import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
168
169
  function glyph(paths, air = [1, 1]) {
169
170
  const style = { "--matrx-glyph-air-l": air[0], "--matrx-glyph-air-r": air[1] };
@@ -175,10 +176,6 @@ var KeyGlyph = glyph(/* @__PURE__ */ jsxs2(Fragment, { children: [
175
176
  /* @__PURE__ */ jsx2("circle", { cx: "7.5", cy: "15.5", r: "5.5" }),
176
177
  /* @__PURE__ */ jsx2("path", { d: "m21 2-9.6 9.6M15.5 7.5l3 3" })
177
178
  ] }), [1, 2]);
178
- var GlobeGlyph = glyph(/* @__PURE__ */ jsxs2(Fragment, { children: [
179
- /* @__PURE__ */ jsx2("circle", { cx: "12", cy: "12", r: "10" }),
180
- /* @__PURE__ */ jsx2("path", { d: "M2 12h20M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" })
181
- ] }), [1, 1]);
182
179
  var NoteGlyph = glyph(/* @__PURE__ */ jsxs2(Fragment, { children: [
183
180
  /* @__PURE__ */ jsx2("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }),
184
181
  /* @__PURE__ */ jsx2("path", { d: "M14 2v4a2 2 0 0 0 2 2h4M16 13H8M16 17H8" })
@@ -208,10 +205,6 @@ var FileGlyph = glyph(/* @__PURE__ */ jsxs2(Fragment, { children: [
208
205
  var CodeGlyph = glyph(/* @__PURE__ */ jsx2(Fragment, { children: /* @__PURE__ */ jsx2("path", { d: "m16 18 6-6-6-6M8 6l-6 6 6 6" }) }), [1, 1]);
209
206
  var StarGlyph = glyph(/* @__PURE__ */ jsx2("path", { d: "M12 2l3.1 6.3 6.9 1-5 4.9 1.2 6.8L12 17.8 5.8 21l1.2-6.8-5-4.9 6.9-1z" }), [1, 1]);
210
207
  var PlusGlyph = glyph(/* @__PURE__ */ jsx2("path", { d: "M12 5v14M5 12h14" }), [4, 4]);
211
- var CopyGlyph = glyph(/* @__PURE__ */ jsxs2(Fragment, { children: [
212
- /* @__PURE__ */ jsx2("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }),
213
- /* @__PURE__ */ jsx2("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
214
- ] }), [1, 1]);
215
208
  var EyeGlyph = glyph(/* @__PURE__ */ jsxs2(Fragment, { children: [
216
209
  /* @__PURE__ */ jsx2("path", { d: "M2 12s3.6-7 10-7 10 7 10 7-3.6 7-10 7-10-7-10-7z" }),
217
210
  /* @__PURE__ */ jsx2("circle", { cx: "12", cy: "12", r: "3" })
@@ -236,11 +229,6 @@ var BuildingGlyph = glyph(/* @__PURE__ */ jsxs2(Fragment, { children: [
236
229
  /* @__PURE__ */ jsx2("rect", { x: "4", y: "2", width: "16", height: "20", rx: "2" }),
237
230
  /* @__PURE__ */ jsx2("path", { d: "M9 22v-4h6v4M8 6h.01M16 6h.01M12 6h.01M12 10h.01M12 14h.01M16 10h.01M16 14h.01M8 10h.01M8 14h.01" })
238
231
  ] }), [3, 3]);
239
- var UsersGlyph = glyph(/* @__PURE__ */ jsxs2(Fragment, { children: [
240
- /* @__PURE__ */ jsx2("path", { d: "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" }),
241
- /* @__PURE__ */ jsx2("circle", { cx: "9", cy: "7", r: "4" }),
242
- /* @__PURE__ */ jsx2("path", { d: "M22 21v-2a4 4 0 0 0-3-3.9M16 3.1a4 4 0 0 1 0 7.8" })
243
- ] }), [1, 1]);
244
232
  var ChevronLeftGlyph = glyph(/* @__PURE__ */ jsx2("path", { d: "m15 18-6-6 6-6" }), [8, 8]);
245
233
  var GridGlyph = glyph(/* @__PURE__ */ jsxs2(Fragment, { children: [
246
234
  /* @__PURE__ */ jsx2("rect", { x: "3", y: "3", width: "7", height: "7", rx: "1" }),
@@ -259,7 +247,7 @@ var FAMILY_GLYPHS = {
259
247
  cloud_infrastructure: ServerGlyph
260
248
  };
261
249
  function definitionGlyph(key, family) {
262
- if (key === "username_password" || key === "website_login") return GlobeGlyph;
250
+ if (key === "username_password" || key === "website_login") return GlobeIcon;
263
251
  return FAMILY_GLYPHS[family] ?? KeyGlyph;
264
252
  }
265
253
  var XGlyph = glyph(/* @__PURE__ */ jsx2("path", { d: "M18 6 6 18M6 6l12 12" }), [5, 5]);
@@ -277,15 +265,7 @@ var MoreGlyph = glyph(/* @__PURE__ */ jsxs2(Fragment, { children: [
277
265
  /* @__PURE__ */ jsx2("circle", { cx: "5", cy: "12", r: "1" })
278
266
  ] }), [3, 3]);
279
267
  var ShareGlyph = glyph(/* @__PURE__ */ jsx2(Fragment, { children: /* @__PURE__ */ jsx2("path", { d: "M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8M16 6l-4-4-4 4M12 2v13" }) }), [3, 3]);
280
- var HistoryGlyph = glyph(/* @__PURE__ */ jsxs2(Fragment, { children: [
281
- /* @__PURE__ */ jsx2("path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
282
- /* @__PURE__ */ jsx2("path", { d: "M3 3v5h5M12 7v5l4 2" })
283
- ] }), [2, 2]);
284
268
  var ListGlyph = glyph(/* @__PURE__ */ jsx2("path", { d: "M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01" }), [2, 2]);
285
- var SettingsGlyph = glyph(/* @__PURE__ */ jsxs2(Fragment, { children: [
286
- /* @__PURE__ */ jsx2("path", { d: "M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z" }),
287
- /* @__PURE__ */ jsx2("circle", { cx: "12", cy: "12", r: "3" })
288
- ] }), [2, 2]);
289
269
  var ImportGlyph = glyph(/* @__PURE__ */ jsx2("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3" }), [2, 2]);
290
270
  var ExportGlyph = glyph(/* @__PURE__ */ jsx2("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M17 8l-5-5-5 5M12 3v12" }), [2, 2]);
291
271
  var ChevronDownGlyph = glyph(/* @__PURE__ */ jsx2("path", { d: "m6 9 6 6 6-6" }), [5, 5]);
@@ -326,10 +306,6 @@ var RefreshGlyph = glyph(/* @__PURE__ */ jsxs2(Fragment, { children: [
326
306
  /* @__PURE__ */ jsx2("path", { d: "M21 3v5h-5M3 21v-5h5" })
327
307
  ] }), [2, 2]);
328
308
  var SlidersGlyph = glyph(/* @__PURE__ */ jsx2(Fragment, { children: /* @__PURE__ */ jsx2("path", { d: "M4 21v-7M4 10V3M12 21v-9M12 8V3M20 21v-5M20 12V3M1 14h6M9 8h6M17 16h6" }) }), [0, 0]);
329
- var DownloadGlyph = glyph(/* @__PURE__ */ jsxs2(Fragment, { children: [
330
- /* @__PURE__ */ jsx2("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
331
- /* @__PURE__ */ jsx2("path", { d: "m7 10 5 5 5-5M12 15V3" })
332
- ] }), [2, 2]);
333
309
  var UploadGlyph = glyph(/* @__PURE__ */ jsxs2(Fragment, { children: [
334
310
  /* @__PURE__ */ jsx2("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
335
311
  /* @__PURE__ */ jsx2("path", { d: "m17 8-5-5-5 5M12 3v12" })
@@ -411,7 +387,7 @@ var Ctx2 = createContext2((run) => run());
411
387
  function useConfirmed() {
412
388
  return useContext2(Ctx2);
413
389
  }
414
- var PROVIDER_LABEL = { google: "Google", github: "GitHub", azure: "Microsoft", apple: "Apple", linkedin_oidc: "LinkedIn", slack_oidc: "Slack" };
390
+ var PROVIDER_LABEL = { google: "Google", github: "GitHub", azure: "Microsoft", apple: "Apple", linkedin_oidc: "LinkedIn", slack_oidc: "Slack", browser: "Browser", touch_id: "Touch ID" };
415
391
  var providerLabel = (p) => PROVIDER_LABEL[p] ?? p.charAt(0).toUpperCase() + p.slice(1);
416
392
  function IdentityGate({ identity, children }) {
417
393
  const [asking, setAsking] = useState2(false);
@@ -481,10 +457,21 @@ function ConfirmIdentityDialog({ open, identity, onDone, onCancel }) {
481
457
  ] }),
482
458
  /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-3", children: [
483
459
  identity.dev ? /* @__PURE__ */ jsx3(Button, { variant: "primary", disabled: busy, onClick: () => void attempt(() => identity.dev?.() ?? Promise.resolve()), children: "Sign in again (dev)" }) : null,
484
- account10?.providers.map((p) => /* @__PURE__ */ jsxs3(Button, { variant: identity.dev ? "outline" : "primary", disabled: busy, onClick: () => void attempt(() => identity.withProvider(p), false), children: [
485
- "Continue with ",
486
- providerLabel(p)
487
- ] }, p)),
460
+ account10?.providers.map((p) => /* @__PURE__ */ jsxs3(
461
+ Button,
462
+ {
463
+ variant: identity.dev ? "outline" : "primary",
464
+ disabled: busy,
465
+ onClick: () => void attempt(async () => {
466
+ if (await identity.withProvider(p) === "confirmed") onDone();
467
+ }, false),
468
+ children: [
469
+ "Continue with ",
470
+ providerLabel(p)
471
+ ]
472
+ },
473
+ p
474
+ )),
488
475
  account10?.hasPassword ? /* @__PURE__ */ jsxs3("form", { className: "flex gap-2", onSubmit: (e) => {
489
476
  e.preventDefault();
490
477
  if (password) void attempt(() => identity.withPassword(password));
@@ -511,6 +498,7 @@ function ConfirmIdentityDialog({ open, identity, onDone, onCancel }) {
511
498
  import { useEffect as useEffect5, useState as useState5 } from "react";
512
499
  import { Badge, Button as Button2, Field as Field2, Textarea } from "@ai-matrx/design-system/controls";
513
500
  import { cn as cn3 } from "@ai-matrx/design-system";
501
+ import { CopyIcon } from "@ai-matrx/design-system/icons";
514
502
 
515
503
  // src/hooks.ts
516
504
  import { createContext as createContext3, createElement, useCallback as useCallback2, useContext as useContext3, useEffect as useEffect3, useLayoutEffect, useRef as useRef3, useState as useState3 } from "react";
@@ -579,7 +567,7 @@ function useRoomOf(ref) {
579
567
  return room;
580
568
  }
581
569
  var RoomProvider = Room.Provider;
582
- function Section({ title, actions, children, className }) {
570
+ function VaultSection({ title, actions, children, className }) {
583
571
  const flat = useContext4(InPanel);
584
572
  const desktop = useLook() === "desktop";
585
573
  return /* @__PURE__ */ jsxs4("section", { className: cn2("flex flex-col gap-1.5", className), children: [
@@ -595,7 +583,7 @@ var ROW_GRID = {
595
583
  roomy: "grid-cols-[9rem_minmax(0,1fr)_auto] gap-x-3 px-4",
596
584
  viewport: "grid-cols-[5.75rem_minmax(0,1fr)_auto] gap-x-2 px-3 sm:grid-cols-[9rem_minmax(0,1fr)_auto] sm:gap-x-3 sm:px-4"
597
585
  };
598
- function Row({ label, hint, children, actions, top = false, className }) {
586
+ function VaultRow({ label, hint, children, actions, top = false, className }) {
599
587
  const room = useContext4(Room);
600
588
  return /* @__PURE__ */ jsxs4("div", { className: cn2("grid min-h-11 py-1", ROW_GRID[room ?? "viewport"], top ? "items-start" : "items-center", className), children: [
601
589
  /* @__PURE__ */ jsxs4("div", { className: cn2("flex min-w-0 flex-col text-xs leading-tight text-muted-foreground", top && "pt-2.5"), children: [
@@ -616,11 +604,6 @@ function Panel({ title, open = true, onClose, children, footer, size = "lg" }) {
616
604
  footer ? /* @__PURE__ */ jsx4(DialogFooter, { children: footer }) : null
617
605
  ] }) });
618
606
  }
619
- function formatBytes(n) {
620
- if (n < 1024) return `${n} B`;
621
- if (n < 1024 * 1024) return `${(n / 1024).toFixed(n < 10 * 1024 ? 1 : 0)} KB`;
622
- return `${(n / 1024 / 1024).toFixed(1)} MB`;
623
- }
624
607
  var DAY_FORMAT = { year: "numeric", month: "short", day: "numeric" };
625
608
 
626
609
  // src/FieldRows.tsx
@@ -679,14 +662,14 @@ function SecretRow({ port, item, field, extra }) {
679
662
  const multiline = field.kind === "multiline";
680
663
  const shown = visible ? plain : secret.value;
681
664
  return /* @__PURE__ */ jsx5(
682
- Row,
665
+ VaultRow,
683
666
  {
684
667
  label: field.label,
685
668
  top: multiline && shown !== null,
686
669
  actions: /* @__PURE__ */ jsxs5(Fragment2, { children: [
687
670
  extra,
688
671
  canSee && !visible ? /* @__PURE__ */ jsx5(Button2, { variant: "quiet", icon: secret.value !== null ? /* @__PURE__ */ jsx5(EyeOffGlyph, {}) : /* @__PURE__ */ jsx5(EyeGlyph, {}), "aria-label": secret.value !== null ? `Hide ${field.label}` : `Show ${field.label}`, disabled: busy, onClick: () => void toggle2() }) : null,
689
- canSee ? /* @__PURE__ */ jsx5(Button2, { variant: "quiet", icon: /* @__PURE__ */ jsx5(CopyGlyph, {}), "aria-label": `Copy ${field.label}`, disabled: busy, onClick: () => void copy() }) : null
672
+ canSee ? /* @__PURE__ */ jsx5(Button2, { variant: "quiet", icon: /* @__PURE__ */ jsx5(CopyIcon, {}), "aria-label": `Copy ${field.label}`, disabled: busy, onClick: () => void copy() }) : null
690
673
  ] }),
691
674
  children: sealed ? /* @__PURE__ */ jsx5(Badge, { icon: /* @__PURE__ */ jsx5(LockGlyph, {}), children: "Sealed" }) : off ? /* @__PURE__ */ jsx5("span", { className: "text-muted-foreground", children: "Turned off" }) : error ? /* @__PURE__ */ jsx5("span", { className: "truncate text-destructive", title: error, children: error }) : shown !== null ? visible ? /* @__PURE__ */ jsx5("span", { className: cn3("block", multiline ? "whitespace-pre-wrap break-words" : "truncate"), children: shown || "\u2014" }) : /* @__PURE__ */ jsx5(SecretText, { value: shown, multiline }) : /* @__PURE__ */ jsx5("span", { className: cn3("block truncate text-muted-foreground", !visible && "tracking-widest"), children: visible ? "\u2026" : MASK })
692
675
  }
@@ -696,7 +679,7 @@ function PlainRow({ label, value, hint, openUrl, extra, multiline = false }) {
696
679
  const copyValue2 = useCopy();
697
680
  const isUrl = /^https?:\/\//i.test(value);
698
681
  return /* @__PURE__ */ jsx5(
699
- Row,
682
+ VaultRow,
700
683
  {
701
684
  label,
702
685
  hint,
@@ -704,7 +687,7 @@ function PlainRow({ label, value, hint, openUrl, extra, multiline = false }) {
704
687
  actions: /* @__PURE__ */ jsxs5(Fragment2, { children: [
705
688
  extra,
706
689
  isUrl && openUrl ? /* @__PURE__ */ jsx5(Button2, { variant: "quiet", icon: /* @__PURE__ */ jsx5(ExternalGlyph, {}), "aria-label": `Open ${value}`, onClick: () => openUrl(value) }) : null,
707
- /* @__PURE__ */ jsx5(Button2, { variant: "quiet", icon: /* @__PURE__ */ jsx5(CopyGlyph, {}), "aria-label": `Copy ${typeof label === "string" ? label : "value"}`, onClick: () => void copyValue2(value, typeof label === "string" && label ? label : "Value", { secret: false }) })
690
+ /* @__PURE__ */ jsx5(Button2, { variant: "quiet", icon: /* @__PURE__ */ jsx5(CopyIcon, {}), "aria-label": `Copy ${typeof label === "string" ? label : "value"}`, onClick: () => void copyValue2(value, typeof label === "string" && label ? label : "Value", { secret: false }) })
708
691
  ] }),
709
692
  children: isUrl && openUrl ? (
710
693
  // A real link (right-click, copy link address, open in a new tab); a click goes through the host's opener.
@@ -727,12 +710,12 @@ function PlainRow({ label, value, hint, openUrl, extra, multiline = false }) {
727
710
  );
728
711
  }
729
712
  function AddRow({ label, onAdd, children = "Add" }) {
730
- return /* @__PURE__ */ jsx5(Row, { label, children: onAdd ? /* @__PURE__ */ jsx5("button", { type: "button", className: "text-sm text-muted-foreground hover:text-primary", onClick: onAdd, children }) : /* @__PURE__ */ jsx5("span", { className: "text-disabled-foreground", children: "\u2014" }) });
713
+ return /* @__PURE__ */ jsx5(VaultRow, { label, children: onAdd ? /* @__PURE__ */ jsx5("button", { type: "button", className: "text-sm text-muted-foreground hover:text-primary", onClick: onAdd, children }) : /* @__PURE__ */ jsx5("span", { className: "text-disabled-foreground", children: "\u2014" }) });
731
714
  }
732
715
  function EditRow({ label, hint, value, onChange, placeholder, secret = false, multiline = false, onRemove, removeLabel, actions, autoFocus, onBlur, inputMode }) {
733
716
  const [shown, setShown] = useState5(false);
734
717
  return /* @__PURE__ */ jsx5(
735
- Row,
718
+ VaultRow,
736
719
  {
737
720
  label,
738
721
  hint,
@@ -749,7 +732,7 @@ function EditRow({ label, hint, value, onChange, placeholder, secret = false, mu
749
732
  function CustomEditRow({ label, value, onLabel, onValue, secret, onRemove }) {
750
733
  const [shown, setShown] = useState5(false);
751
734
  return /* @__PURE__ */ jsx5(
752
- Row,
735
+ VaultRow,
753
736
  {
754
737
  label: /* @__PURE__ */ jsx5(Field2, { className: "w-full", value: label, onChange: (e) => onLabel(e.target.value), placeholder: "Name", "aria-label": "Field name" }),
755
738
  actions: /* @__PURE__ */ jsxs5(Fragment2, { children: [
@@ -762,6 +745,7 @@ function CustomEditRow({ label, value, onLabel, onValue, secret, onRemove }) {
762
745
  }
763
746
 
764
747
  // src/activity/HistoryPanel.tsx
748
+ import { CopyIcon as CopyIcon2 } from "@ai-matrx/design-system/icons";
765
749
  import { formatAbsoluteDate as formatAbsoluteDate2 } from "@ai-matrx/kit/format";
766
750
 
767
751
  // src/activity/logic.ts
@@ -814,6 +798,8 @@ function matchesQuery(item, query) {
814
798
  if (!q) return true;
815
799
  return [item.name, item.definitionLabel, ...item.tags, ...item.loginUrls, ...item.custom.map((c) => `${c.label} ${c.value}`)].some((h) => h.toLowerCase().includes(q));
816
800
  }
801
+ var HIDDEN_ITEM_TAG = "matrx:hidden";
802
+ var isHiddenItem = (item) => (item.tags ?? []).includes(HIDDEN_ITEM_TAG);
817
803
  var isAuthenticatorStorage = (key) => key === "totp_seed" || key.startsWith("totp_") || key === "authenticator_last_time_step";
818
804
  function loginSiteOf(item) {
819
805
  const raw = item.loginUrls[0];
@@ -1254,7 +1240,7 @@ function ActivityPanel({ item, port, onClose }) {
1254
1240
  footer: hasMore ? /* @__PURE__ */ jsx6(Button3, { variant: "outline", disabled: loading, onClick: () => setLimit((n) => Math.min(MAX, n * 2)), children: loading ? "Loading\u2026" : "Show more" }) : void 0,
1255
1241
  children: [
1256
1242
  error ? /* @__PURE__ */ jsx6("p", { role: "alert", className: "px-1 text-sm text-destructive", children: error }) : null,
1257
- entries === null ? loading ? /* @__PURE__ */ jsx6(Empty, { children: "Reading activity\u2026" }) : null : entries.length === 0 ? /* @__PURE__ */ jsx6(Empty, { children: "Nothing has happened yet." }) : groupByDay(entries, now).map((day) => /* @__PURE__ */ jsx6(Section, { title: day.label, children: collapseRuns(
1243
+ entries === null ? loading ? /* @__PURE__ */ jsx6(Empty, { children: "Reading activity\u2026" }) : null : entries.length === 0 ? /* @__PURE__ */ jsx6(Empty, { children: "Nothing has happened yet." }) : groupByDay(entries, now).map((day) => /* @__PURE__ */ jsx6(VaultSection, { title: day.label, children: collapseRuns(
1258
1244
  day.entries.map((entry) => ({ entry, s: auditSentence(entry, item, me) })),
1259
1245
  (r) => `${r.s.what}|${r.s.who ?? ""}`
1260
1246
  ).map(({ row: { entry, s }, times }) => {
@@ -1277,7 +1263,7 @@ function ActivityPanel({ item, port, onClose }) {
1277
1263
  import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1278
1264
  var MASK2 = "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
1279
1265
  var messageOf = (e, fallback) => wasCancelled(e) ? null : e instanceof Error ? e.message : fallback;
1280
- function HistoryPanel({ item, port, arg, onClose, onChanged }) {
1266
+ function ItemHistoryPanel({ item, port, arg, onClose, onChanged }) {
1281
1267
  const eligible = historyEligible(item);
1282
1268
  const [page, setPage] = useState7(null);
1283
1269
  const [loading, setLoading] = useState7(eligible);
@@ -1339,7 +1325,7 @@ function HistoryPanel({ item, port, arg, onClose, onChanged }) {
1339
1325
  error ? /* @__PURE__ */ jsx7("p", { role: "alert", className: "px-1 text-sm text-destructive", children: error }) : null,
1340
1326
  notice ? /* @__PURE__ */ jsx7("p", { role: "status", className: "px-1 text-sm text-success", children: notice }) : null,
1341
1327
  page && groups.length === 0 ? /* @__PURE__ */ jsx7(Empty, { children: "No earlier values yet." }) : null,
1342
- page ? groups.map((g) => /* @__PURE__ */ jsx7(Section, { title: g.label, children: g.entries.map((entry) => /* @__PURE__ */ jsx7(HistoryRow, { item, port, page, entry, label: g.label, onRestored: restored, onConflict: conflicted, onError: setError }, `${item.id}:${entry.fieldId}:${entry.revision}`)) }, g.fieldId)) : null,
1328
+ page ? groups.map((g) => /* @__PURE__ */ jsx7(VaultSection, { title: g.label, children: g.entries.map((entry) => /* @__PURE__ */ jsx7(HistoryRow, { item, port, page, entry, label: g.label, onRestored: restored, onConflict: conflicted, onError: setError }, `${item.id}:${entry.fieldId}:${entry.revision}`)) }, g.fieldId)) : null,
1343
1329
  page && (page.captureStartedAt || page.incomplete) ? /* @__PURE__ */ jsxs7("div", { className: "flex flex-wrap gap-x-3 gap-y-1 px-1 text-xs", children: [
1344
1330
  page.captureStartedAt ? /* @__PURE__ */ jsxs7("span", { className: "text-muted-foreground", children: [
1345
1331
  "Kept since ",
@@ -1400,12 +1386,12 @@ function HistoryRow({ item, port, page, entry, label, onRestored, onConflict, on
1400
1386
  }
1401
1387
  }
1402
1388
  return /* @__PURE__ */ jsx7(
1403
- Row,
1389
+ VaultRow,
1404
1390
  {
1405
1391
  label: when,
1406
1392
  actions: entry.available ? /* @__PURE__ */ jsxs7(Fragment3, { children: [
1407
1393
  /* @__PURE__ */ jsx7(Button4, { variant: "quiet", icon: secret.value !== null ? /* @__PURE__ */ jsx7(EyeOffGlyph, {}) : /* @__PURE__ */ jsx7(EyeGlyph, {}), "aria-label": secret.value !== null ? "Hide" : "Show", disabled: busy, onClick: () => void toggle2() }),
1408
- /* @__PURE__ */ jsx7(Button4, { variant: "quiet", icon: /* @__PURE__ */ jsx7(CopyGlyph, {}), "aria-label": "Copy", disabled: busy, onClick: () => void copy() }),
1394
+ /* @__PURE__ */ jsx7(Button4, { variant: "quiet", icon: /* @__PURE__ */ jsx7(CopyIcon2, {}), "aria-label": "Copy", disabled: busy, onClick: () => void copy() }),
1409
1395
  canRestore(page, entry) ? /* @__PURE__ */ jsx7(Button4, { variant: "quiet", icon: /* @__PURE__ */ jsx7(RestoreGlyph, {}), "aria-label": "Restore", disabled: busy, onClick: () => void restore() }) : null
1410
1396
  ] }) : null,
1411
1397
  children: !entry.available ? /* @__PURE__ */ jsx7(Badge2, { children: "Not kept" }) : secret.value !== null ? /* @__PURE__ */ jsx7(SecretText, { value: secret.value, multiline: false }) : /* @__PURE__ */ jsx7("span", { className: "block truncate tracking-widest text-muted-foreground", children: MASK2 })
@@ -1417,6 +1403,7 @@ function HistoryRow({ item, port, page, entry, label, onRestored, onConflict, on
1417
1403
  import { useEffect as useEffect11, useState as useState13 } from "react";
1418
1404
  import { Button as Button9 } from "@ai-matrx/design-system/controls";
1419
1405
  import { cn as cn6, DropdownMenu as DropdownMenu2, DropdownMenuContent as DropdownMenuContent2, DropdownMenuItem as DropdownMenuItem2, DropdownMenuSeparator as DropdownMenuSeparator2, DropdownMenuTrigger as DropdownMenuTrigger2, TextInputDialog } from "@ai-matrx/design-system";
1406
+ import { CopyIcon as CopyIcon4 } from "@ai-matrx/design-system/icons";
1420
1407
 
1421
1408
  // src/authenticator/AddOtpPanel.tsx
1422
1409
  import { useState as useState12 } from "react";
@@ -1426,8 +1413,11 @@ import { Button as Button8, Field as Field4, Select as Select2 } from "@ai-matrx
1426
1413
  import { useEffect as useEffect8, useRef as useRef6, useState as useState8 } from "react";
1427
1414
  import { Button as Button5 } from "@ai-matrx/design-system/controls";
1428
1415
  import { cn as cn5 } from "@ai-matrx/design-system";
1416
+ import { CopyIcon as CopyIcon3 } from "@ai-matrx/design-system/icons";
1417
+ import { groupCode as groupCode2 } from "@ai-matrx/kit/format";
1429
1418
 
1430
1419
  // src/authenticator/otpauth.ts
1420
+ import { groupCode } from "@ai-matrx/kit/format";
1431
1421
  var TOTP_DEFAULT_DIGITS = 6;
1432
1422
  var TOTP_DEFAULT_PERIOD = 30;
1433
1423
  var TOTP_DEFAULT_ALGORITHM = "SHA1";
@@ -1495,12 +1485,6 @@ function describeEnrollment(parsed) {
1495
1485
  const parts = [parsed.issuer, parsed.account].filter((p) => Boolean(p));
1496
1486
  return parts.length ? parts.join(" \xB7 ") : "Setup key";
1497
1487
  }
1498
- function groupCode(code) {
1499
- const c = code.replace(/\s/g, "");
1500
- if (c.length < 6) return c;
1501
- const head = Math.ceil(c.length / 2);
1502
- return `${c.slice(0, head)} ${c.slice(head)}`;
1503
- }
1504
1488
  function maskedCode(digits = TOTP_DEFAULT_DIGITS) {
1505
1489
  return groupCode("\u2022".repeat(Math.max(6, digits)));
1506
1490
  }
@@ -1578,7 +1562,7 @@ function useCopied() {
1578
1562
  }
1579
1563
  function CodeButton({ live, digits, size = "md", label }) {
1580
1564
  const { copied, copy } = useCopied();
1581
- const shown = live.code ? groupCode(live.code) : maskedCode(digits);
1565
+ const shown = live.code ? groupCode2(live.code) : maskedCode(digits);
1582
1566
  return /* @__PURE__ */ jsxs8(
1583
1567
  "button",
1584
1568
  {
@@ -1597,7 +1581,7 @@ function CodeButton({ live, digits, size = "md", label }) {
1597
1581
  }
1598
1582
  function CopyCodeButton({ live, label }) {
1599
1583
  const { copied, copy } = useCopied();
1600
- return /* @__PURE__ */ jsx8(Button5, { variant: "quiet", icon: copied ? /* @__PURE__ */ jsx8(CheckGlyph, {}) : /* @__PURE__ */ jsx8(CopyGlyph, {}), ...copied ? { glyphTone: "success" } : {}, "aria-label": `Copy ${label} code`, disabled: !live.code, onClick: () => live.code && void copy(live.code) });
1584
+ return /* @__PURE__ */ jsx8(Button5, { variant: "quiet", icon: copied ? /* @__PURE__ */ jsx8(CheckGlyph, {}) : /* @__PURE__ */ jsx8(CopyIcon3, {}), ...copied ? { glyphTone: "success" } : {}, "aria-label": `Copy ${label} code`, disabled: !live.code, onClick: () => live.code && void copy(live.code) });
1601
1585
  }
1602
1586
 
1603
1587
  // src/authenticator/live-code.ts
@@ -1869,7 +1853,7 @@ function OtpSetupRow({ value, onChange, label = "One-time password", placeholder
1869
1853
  className: dragging ? "rounded-lg bg-accent" : void 0,
1870
1854
  children: [
1871
1855
  /* @__PURE__ */ jsxs9(
1872
- Row,
1856
+ VaultRow,
1873
1857
  {
1874
1858
  label,
1875
1859
  actions: /* @__PURE__ */ jsxs9(Fragment4, { children: [
@@ -2019,7 +2003,7 @@ function TotpRow({ port, item, onChanged }) {
2019
2003
  ] })
2020
2004
  ] }) : null;
2021
2005
  return /* @__PURE__ */ jsx10(
2022
- Row,
2006
+ VaultRow,
2023
2007
  {
2024
2008
  label: "One-time password",
2025
2009
  actions: /* @__PURE__ */ jsxs10(Fragment5, { children: [
@@ -2078,7 +2062,7 @@ function TwoFactorMethodRow({ port, item, onChanged }) {
2078
2062
  const [busy, setBusy] = useState11(false);
2079
2063
  const [error, setError] = useState11(null);
2080
2064
  const canEdit = item.capabilities.canEdit || item.capabilities.canManage;
2081
- return /* @__PURE__ */ jsx10(Row, { label: "Two-factor", hint: error ? /* @__PURE__ */ jsx10("span", { className: "text-destructive", children: error }) : void 0, children: /* @__PURE__ */ jsx10(
2065
+ return /* @__PURE__ */ jsx10(VaultRow, { label: "Two-factor", hint: error ? /* @__PURE__ */ jsx10("span", { className: "text-destructive", children: error }) : void 0, children: /* @__PURE__ */ jsx10(
2082
2066
  Select,
2083
2067
  {
2084
2068
  value: value ?? "none",
@@ -2193,7 +2177,7 @@ function AddOtpPanel({ port, items, definitions, itemId = null, onClose, onChang
2193
2177
  /* @__PURE__ */ jsx11(Button8, { variant: "primary", disabled: !ready, onClick: () => void save(), children: busy ? "Adding\u2026" : "Add" })
2194
2178
  ] }),
2195
2179
  children: [
2196
- /* @__PURE__ */ jsxs11(Section, { children: [
2180
+ /* @__PURE__ */ jsxs11(VaultSection, { children: [
2197
2181
  /* @__PURE__ */ jsx11(
2198
2182
  OtpSetupRow,
2199
2183
  {
@@ -2215,7 +2199,7 @@ function AddOtpPanel({ port, items, definitions, itemId = null, onClose, onChang
2215
2199
  status: image ? `QR image ready \xB7 ${image.name}` : null
2216
2200
  }
2217
2201
  ),
2218
- /* @__PURE__ */ jsx11(Row, { label: "Add to", children: /* @__PURE__ */ jsx11(
2202
+ /* @__PURE__ */ jsx11(VaultRow, { label: "Add to", children: /* @__PURE__ */ jsx11(
2219
2203
  Select2,
2220
2204
  {
2221
2205
  value: target,
@@ -2229,7 +2213,7 @@ function AddOtpPanel({ port, items, definitions, itemId = null, onClose, onChang
2229
2213
  }
2230
2214
  ) }),
2231
2215
  isNew ? /* @__PURE__ */ jsxs11(Fragment6, { children: [
2232
- /* @__PURE__ */ jsx11(Row, { label: "Name", children: /* @__PURE__ */ jsx11(
2216
+ /* @__PURE__ */ jsx11(VaultRow, { label: "Name", children: /* @__PURE__ */ jsx11(
2233
2217
  Field4,
2234
2218
  {
2235
2219
  className: "w-full",
@@ -2243,7 +2227,7 @@ function AddOtpPanel({ port, items, definitions, itemId = null, onClose, onChang
2243
2227
  "aria-label": "Name"
2244
2228
  }
2245
2229
  ) }),
2246
- /* @__PURE__ */ jsx11(Row, { label: "Website", hint: websiteBad ? /* @__PURE__ */ jsx11("span", { className: "text-destructive", children: "Not a web address" }) : void 0, children: /* @__PURE__ */ jsx11(Field4, { className: "w-full", type: "url", value: website, disabled: busy || created !== null, onChange: (e) => setWebsite(e.target.value), placeholder: "example.com", "aria-label": "Website", "aria-invalid": websiteBad || void 0 }) })
2230
+ /* @__PURE__ */ jsx11(VaultRow, { label: "Website", hint: websiteBad ? /* @__PURE__ */ jsx11("span", { className: "text-destructive", children: "Not a web address" }) : void 0, children: /* @__PURE__ */ jsx11(Field4, { className: "w-full", type: "url", value: website, disabled: busy || created !== null, onChange: (e) => setWebsite(e.target.value), placeholder: "example.com", "aria-label": "Website", "aria-invalid": websiteBad || void 0 }) })
2247
2231
  ] }) : null
2248
2232
  ] }),
2249
2233
  error ? /* @__PURE__ */ jsx11("p", { className: "px-1 text-sm text-destructive", role: "alert", children: error }) : null
@@ -2311,7 +2295,7 @@ function AuthenticatorView({ port, items, definitions, query, onOpen, onChanged,
2311
2295
  /* @__PURE__ */ jsx12("span", { className: "flex size-12 items-center justify-center rounded-full bg-muted text-muted-foreground", children: /* @__PURE__ */ jsx12(ShieldGlyph, { className: "size-6" }) }),
2312
2296
  /* @__PURE__ */ jsx12("p", { className: "text-sm font-medium text-foreground", children: "No one-time passwords yet" }),
2313
2297
  /* @__PURE__ */ jsx12(Button9, { variant: "primary", icon: /* @__PURE__ */ jsx12(PlusGlyph, {}), onClick: () => setAdding(true), children: "Add one-time password" })
2314
- ] }) : groups.length === 0 ? /* @__PURE__ */ jsx12("div", { className: "px-4 py-10 text-center text-sm text-muted-foreground", children: "Nothing matches." }) : /* @__PURE__ */ jsx12("div", { className: "min-h-0 flex-1 overflow-y-auto px-3 pb-6 pt-1 sm:px-4", children: /* @__PURE__ */ jsx12("div", { className: "mx-auto flex w-full max-w-3xl flex-col gap-5", children: groups.map((g) => /* @__PURE__ */ jsx12(Section, { ...groups.length > 1 ? { title: g.label } : {}, className: "[&>div]:px-1", children: g.items.map((item) => /* @__PURE__ */ jsx12(
2298
+ ] }) : groups.length === 0 ? /* @__PURE__ */ jsx12("div", { className: "px-4 py-10 text-center text-sm text-muted-foreground", children: "Nothing matches." }) : /* @__PURE__ */ jsx12("div", { className: "min-h-0 flex-1 overflow-y-auto px-3 pb-6 pt-1 sm:px-4", children: /* @__PURE__ */ jsx12("div", { className: "mx-auto flex w-full max-w-3xl flex-col gap-5", children: groups.map((g) => /* @__PURE__ */ jsx12(VaultSection, { ...groups.length > 1 ? { title: g.label } : {}, className: "[&>div]:px-1", children: g.items.map((item) => /* @__PURE__ */ jsx12(
2315
2299
  OtpListRow,
2316
2300
  {
2317
2301
  port,
@@ -2405,7 +2389,7 @@ function OtpListRow({ port, item, family, entry, onOpen, onRename, onChanged, on
2405
2389
  "Open login"
2406
2390
  ] }),
2407
2391
  live.code ? /* @__PURE__ */ jsxs12(DropdownMenuItem2, { onSelect: () => live.code && void copy(live.code), children: [
2408
- /* @__PURE__ */ jsx12(CopyGlyph, { className: "size-4" }),
2392
+ /* @__PURE__ */ jsx12(CopyIcon4, { className: "size-4" }),
2409
2393
  "Copy code"
2410
2394
  ] }) : null,
2411
2395
  canManage ? /* @__PURE__ */ jsxs12(Fragment7, { children: [
@@ -2432,6 +2416,7 @@ function OtpListRow({ port, item, family, entry, onOpen, onRename, onChanged, on
2432
2416
  import { useRef as useRef9, useState as useState14 } from "react";
2433
2417
  import { Badge as Badge3, Button as Button10, DisclosureHeader, Field as Field5, SegmentedControl, Select as Select3, Switch } from "@ai-matrx/design-system/controls";
2434
2418
  import { confirm as confirm3 } from "@ai-matrx/kit/confirm-opener";
2419
+ import { GlobeIcon as GlobeIcon2 } from "@ai-matrx/design-system/icons";
2435
2420
 
2436
2421
  // src/fields/rules.ts
2437
2422
  var ENV_KEY_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
@@ -2581,7 +2566,7 @@ function FieldSettings({ item, port, field, onClose, onChanged }) {
2581
2566
  const locked = !canEdit || busy !== null;
2582
2567
  return /* @__PURE__ */ jsxs13(Panel, { title: `${field.label} settings`, size: "md", onClose, footer: /* @__PURE__ */ jsx13(Button10, { variant: "primary", onClick: onClose, children: "Done" }), children: [
2583
2568
  !canEdit ? /* @__PURE__ */ jsx13("p", { className: "px-1 text-sm text-muted-foreground", children: "View only: you can\u2019t change these settings." }) : null,
2584
- /* @__PURE__ */ jsx13(Section, { title: "Who can see it", children: /* @__PURE__ */ jsx13(Row, { label: "Value", hint: quietHint(handling.hint), children: field.handling === "sealed" ? /* @__PURE__ */ jsx13(Badge3, { icon: /* @__PURE__ */ jsx13(LockGlyph, {}), children: "Sealed for good" }) : /* @__PURE__ */ jsx13(
2569
+ /* @__PURE__ */ jsx13(VaultSection, { title: "Who can see it", children: /* @__PURE__ */ jsx13(VaultRow, { label: "Value", hint: quietHint(handling.hint), children: field.handling === "sealed" ? /* @__PURE__ */ jsx13(Badge3, { icon: /* @__PURE__ */ jsx13(LockGlyph, {}), children: "Sealed for good" }) : /* @__PURE__ */ jsx13(
2585
2570
  SegmentedControl,
2586
2571
  {
2587
2572
  "aria-label": "Who can see it",
@@ -2590,8 +2575,8 @@ function FieldSettings({ item, port, field, onClose, onChanged }) {
2590
2575
  data: handlingChoices(field.handling).map((h) => ({ value: h, label: HANDLING_WORDS[h].label, title: HANDLING_WORDS[h].hint, disabled: locked }))
2591
2576
  }
2592
2577
  ) }) }),
2593
- /* @__PURE__ */ jsxs13(Section, { title: "Automation", children: [
2594
- /* @__PURE__ */ jsx13(Row, { label: "Env key", hint: envProblem ? quietHint(envProblem, "destructive") : quietHint("The name sandboxes and workflows use"), children: /* @__PURE__ */ jsx13(
2578
+ /* @__PURE__ */ jsxs13(VaultSection, { title: "Automation", children: [
2579
+ /* @__PURE__ */ jsx13(VaultRow, { label: "Env key", hint: envProblem ? quietHint(envProblem, "destructive") : quietHint("The name sandboxes and workflows use"), children: /* @__PURE__ */ jsx13(
2595
2580
  Field5,
2596
2581
  {
2597
2582
  ref: envRef,
@@ -2611,10 +2596,10 @@ function FieldSettings({ item, port, field, onClose, onChanged }) {
2611
2596
  }
2612
2597
  }
2613
2598
  ) }),
2614
- /* @__PURE__ */ jsx13(Row, { label: "Use in sandbox", hint: blocker && !field.injectIntoSandbox ? quietHint(blocker) : quietHint("Sandboxes get it as an env variable"), children: /* @__PURE__ */ jsx13(Switch, { "aria-label": "Use in sandbox", checked: field.injectIntoSandbox, disabled: locked, onCheckedChange: (v) => void setSandbox(v) }) })
2599
+ /* @__PURE__ */ jsx13(VaultRow, { label: "Use in sandbox", hint: blocker && !field.injectIntoSandbox ? quietHint(blocker) : quietHint("Sandboxes get it as an env variable"), children: /* @__PURE__ */ jsx13(Switch, { "aria-label": "Use in sandbox", checked: field.injectIntoSandbox, disabled: locked, onCheckedChange: (v) => void setSandbox(v) }) })
2615
2600
  ] }),
2616
- /* @__PURE__ */ jsxs13(Section, { title: "Field", children: [
2617
- /* @__PURE__ */ jsx13(Row, { label: "Description", children: /* @__PURE__ */ jsx13(
2601
+ /* @__PURE__ */ jsxs13(VaultSection, { title: "Field", children: [
2602
+ /* @__PURE__ */ jsx13(VaultRow, { label: "Description", children: /* @__PURE__ */ jsx13(
2618
2603
  Field5,
2619
2604
  {
2620
2605
  className: "w-full",
@@ -2630,8 +2615,8 @@ function FieldSettings({ item, port, field, onClose, onChanged }) {
2630
2615
  }
2631
2616
  }
2632
2617
  ) }),
2633
- /* @__PURE__ */ jsx13(Row, { label: "Editable", hint: quietHint(field.editable ? "The value can be changed" : "The value is locked"), children: /* @__PURE__ */ jsx13(Switch, { "aria-label": "Editable", checked: field.editable, disabled: locked, onCheckedChange: (v) => void update("editable", { editable: v }) }) }),
2634
- /* @__PURE__ */ jsx13(Row, { label: "Active", hint: quietHint(field.active ? "In use" : "Kept, but nothing uses it"), children: /* @__PURE__ */ jsx13(Switch, { "aria-label": "Active", checked: field.active, disabled: locked, onCheckedChange: (v) => void update("active", { active: v }) }) })
2618
+ /* @__PURE__ */ jsx13(VaultRow, { label: "Editable", hint: quietHint(field.editable ? "The value can be changed" : "The value is locked"), children: /* @__PURE__ */ jsx13(Switch, { "aria-label": "Editable", checked: field.editable, disabled: locked, onCheckedChange: (v) => void update("editable", { editable: v }) }) }),
2619
+ /* @__PURE__ */ jsx13(VaultRow, { label: "Active", hint: quietHint(field.active ? "In use" : "Kept, but nothing uses it"), children: /* @__PURE__ */ jsx13(Switch, { "aria-label": "Active", checked: field.active, disabled: locked, onCheckedChange: (v) => void update("active", { active: v }) }) })
2635
2620
  ] }),
2636
2621
  error ? /* @__PURE__ */ jsx13(Problem, { children: error }) : null
2637
2622
  ] });
@@ -2662,8 +2647,8 @@ function ItemSettingsPanel({ item, port, onClose, onChanged, onPanel }) {
2662
2647
  const fillHint = !hasWebsite ? "Add a website first" : item.browserFillEnabled ? "Offered on matching pages" : "Never filled automatically";
2663
2648
  return /* @__PURE__ */ jsxs13(Panel, { title: "Item settings", size: "md", onClose, footer: /* @__PURE__ */ jsx13(Button10, { variant: "primary", onClick: onClose, children: "Done" }), children: [
2664
2649
  !canEdit ? /* @__PURE__ */ jsx13("p", { className: "px-1 text-sm text-muted-foreground", children: "View only: you can\u2019t change these settings." }) : null,
2665
- /* @__PURE__ */ jsxs13(Section, { title: "In the browser", children: [
2666
- /* @__PURE__ */ jsx13(Row, { label: "Website matching", hint: quietHint(MATCH_WORDS[item.uriMatchMode].hint), children: /* @__PURE__ */ jsx13(
2650
+ /* @__PURE__ */ jsxs13(VaultSection, { title: "In the browser", children: [
2651
+ /* @__PURE__ */ jsx13(VaultRow, { label: "Website matching", hint: quietHint(MATCH_WORDS[item.uriMatchMode].hint), children: /* @__PURE__ */ jsx13(
2667
2652
  Select3,
2668
2653
  {
2669
2654
  "aria-label": "Website matching",
@@ -2673,13 +2658,13 @@ function ItemSettingsPanel({ item, port, onClose, onChanged, onPanel }) {
2673
2658
  onValueChange: (m) => void save("match", () => port.fields.updateItem(item, { uriMatchMode: m }))
2674
2659
  }
2675
2660
  ) }),
2676
- /* @__PURE__ */ jsx13(Row, { label: "Fill in browser", hint: quietHint(fillHint), children: /* @__PURE__ */ jsx13(Switch, { "aria-label": "Fill in browser", checked: hasWebsite && item.browserFillEnabled, disabled: locked || !hasWebsite, onCheckedChange: (v) => void save("fill", () => port.fields.updateItem(item, { browserFillEnabled: v })) }) }),
2661
+ /* @__PURE__ */ jsx13(VaultRow, { label: "Fill in browser", hint: quietHint(fillHint), children: /* @__PURE__ */ jsx13(Switch, { "aria-label": "Fill in browser", checked: hasWebsite && item.browserFillEnabled, disabled: locked || !hasWebsite, onCheckedChange: (v) => void save("fill", () => port.fields.updateItem(item, { browserFillEnabled: v })) }) }),
2677
2662
  promotable.map((f) => /* @__PURE__ */ jsx13(
2678
- Row,
2663
+ VaultRow,
2679
2664
  {
2680
2665
  label: f.label,
2681
2666
  hint: quietHint("Encrypted, so the browser can\u2019t match it"),
2682
- actions: /* @__PURE__ */ jsx13(Button10, { variant: "outline", icon: /* @__PURE__ */ jsx13(GlobeGlyph, {}), disabled: locked, onClick: () => void promote(f), children: "Use as website" }),
2667
+ actions: /* @__PURE__ */ jsx13(Button10, { variant: "outline", icon: /* @__PURE__ */ jsx13(GlobeIcon2, {}), disabled: locked, onClick: () => void promote(f), children: "Use as website" }),
2683
2668
  children: /* @__PURE__ */ jsx13("span", { className: "text-muted-foreground", children: "Not a website yet" })
2684
2669
  },
2685
2670
  f.id
@@ -2687,8 +2672,8 @@ function ItemSettingsPanel({ item, port, onClose, onChanged, onPanel }) {
2687
2672
  ] }),
2688
2673
  /* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-1.5", children: [
2689
2674
  /* @__PURE__ */ jsx13(DisclosureHeader, { open: advanced, title: "Advanced", meta: item.fields.length ? `${item.fields.length} fields` : void 0, onClick: () => setAdvanced((a) => !a) }),
2690
- advanced ? /* @__PURE__ */ jsx13(Section, { children: item.fields.length === 0 ? /* @__PURE__ */ jsx13(Empty, { children: "No encrypted fields." }) : item.fields.map((f) => /* @__PURE__ */ jsx13(
2691
- Row,
2675
+ advanced ? /* @__PURE__ */ jsx13(VaultSection, { children: item.fields.length === 0 ? /* @__PURE__ */ jsx13(Empty, { children: "No encrypted fields." }) : item.fields.map((f) => /* @__PURE__ */ jsx13(
2676
+ VaultRow,
2692
2677
  {
2693
2678
  label: f.label,
2694
2679
  actions: /* @__PURE__ */ jsx13(Button10, { variant: "quiet", icon: /* @__PURE__ */ jsx13(SlidersGlyph, {}), "aria-label": `${f.label} settings`, onClick: () => onPanel(`field:${f.id}`) }),
@@ -2713,6 +2698,7 @@ function ItemSettingsPanel({ item, port, onClose, onChanged, onPanel }) {
2713
2698
  import { createContext as createContext5, useContext as useContext5, useEffect as useEffect12, useRef as useRef10, useState as useState15 } from "react";
2714
2699
  import { Popover, PopoverContent, PopoverTrigger, cn as cn7 } from "@ai-matrx/design-system";
2715
2700
  import { Button as Button11, NumberStepper, SegmentedControl as SegmentedControl2, Select as Select4, Switch as Switch2 } from "@ai-matrx/design-system/controls";
2701
+ import { CopyIcon as CopyIcon5 } from "@ai-matrx/design-system/icons";
2716
2702
 
2717
2703
  // src/generator/generate.ts
2718
2704
  import {
@@ -2870,7 +2856,7 @@ function PasswordGenerator({ limits: source, onUse, useLabel = "Use" }) {
2870
2856
  /* @__PURE__ */ jsxs14("div", { className: "flex min-h-7 items-start gap-1", children: [
2871
2857
  /* @__PURE__ */ jsx14("code", { className: cn7("min-w-0 flex-1 break-all py-1 font-mono text-sm", candidate ? "text-foreground" : "text-muted-foreground"), "data-testid": "generated-value", children: candidate ? revealed ? candidate.value : MASK3 : "\u2014" }),
2872
2858
  /* @__PURE__ */ jsx14(Button11, { variant: "quiet", icon: revealed ? /* @__PURE__ */ jsx14(EyeOffGlyph, {}) : /* @__PURE__ */ jsx14(EyeGlyph, {}), "aria-label": revealed ? "Hide" : "Reveal", disabled: !candidate, onClick: () => setRevealed((r) => !r) }),
2873
- /* @__PURE__ */ jsx14(Button11, { variant: "quiet", icon: /* @__PURE__ */ jsx14(CopyGlyph, {}), "aria-label": "Copy", disabled: !candidate, onClick: () => void copy() }),
2859
+ /* @__PURE__ */ jsx14(Button11, { variant: "quiet", icon: /* @__PURE__ */ jsx14(CopyIcon5, {}), "aria-label": "Copy", disabled: !candidate, onClick: () => void copy() }),
2874
2860
  /* @__PURE__ */ jsx14(Button11, { variant: "quiet", icon: /* @__PURE__ */ jsx14(RefreshGlyph, {}), "aria-label": "Generate another", onClick: () => change(settings) })
2875
2861
  ] }),
2876
2862
  strength && candidate ? /* @__PURE__ */ jsxs14("p", { className: "text-xs", children: [
@@ -2997,6 +2983,7 @@ function useLocked(lock) {
2997
2983
  }
2998
2984
 
2999
2985
  // src/io/BackupPanel.tsx
2986
+ import { formatFileSize } from "@ai-matrx/kit/format";
3000
2987
  import { useEffect as useEffect13, useRef as useRef11, useState as useState17 } from "react";
3001
2988
  import { Button as Button13, Field as Field6, SegmentedControl as SegmentedControl3, Switch as Switch3 } from "@ai-matrx/design-system/controls";
3002
2989
  import { downloadFile } from "@ai-matrx/kit/download";
@@ -3138,17 +3125,17 @@ function omissionText(o) {
3138
3125
  return `${o.count ?? "Some"} ${what}: ${o.reason.replaceAll("_", " ")}`;
3139
3126
  }
3140
3127
  function Summary({ value }) {
3141
- return /* @__PURE__ */ jsxs16(Section, { children: [
3142
- /* @__PURE__ */ jsx16(Row, { label: "Credentials", children: value.record_count }),
3143
- /* @__PURE__ */ jsx16(Row, { label: "Protected fields", children: value.field_count }),
3144
- /* @__PURE__ */ jsx16(Row, { label: "Files", children: value.attachment_count > 0 ? `${value.attachment_count} \xB7 ${formatBytes(value.attachment_bytes)}` : "0" })
3128
+ return /* @__PURE__ */ jsxs16(VaultSection, { children: [
3129
+ /* @__PURE__ */ jsx16(VaultRow, { label: "Credentials", children: value.record_count }),
3130
+ /* @__PURE__ */ jsx16(VaultRow, { label: "Protected fields", children: value.field_count }),
3131
+ /* @__PURE__ */ jsx16(VaultRow, { label: "Files", children: value.attachment_count > 0 ? `${value.attachment_count} \xB7 ${formatFileSize(value.attachment_bytes)}` : "0" })
3145
3132
  ] });
3146
3133
  }
3147
3134
  function Omissions({ omissions, accepted, onAccepted, verb }) {
3148
3135
  if (omissions.length === 0) return null;
3149
- return /* @__PURE__ */ jsxs16(Section, { title: "Left out", children: [
3150
- omissions.map((o, i) => /* @__PURE__ */ jsx16(Row, { label: o.component.replaceAll("_", " "), children: /* @__PURE__ */ jsx16("span", { className: "block truncate text-muted-foreground", title: omissionText(o), children: omissionText(o) }) }, `${o.component}-${o.source_item_id ?? i}`)),
3151
- /* @__PURE__ */ jsx16(Row, { label: "Accept", hint: `${verb} without these`, children: /* @__PURE__ */ jsx16(Switch3, { checked: accepted, onCheckedChange: onAccepted, "aria-label": `${verb} without these` }) })
3136
+ return /* @__PURE__ */ jsxs16(VaultSection, { title: "Left out", children: [
3137
+ omissions.map((o, i) => /* @__PURE__ */ jsx16(VaultRow, { label: o.component.replaceAll("_", " "), children: /* @__PURE__ */ jsx16("span", { className: "block truncate text-muted-foreground", title: omissionText(o), children: omissionText(o) }) }, `${o.component}-${o.source_item_id ?? i}`)),
3138
+ /* @__PURE__ */ jsx16(VaultRow, { label: "Accept", hint: `${verb} without these`, children: /* @__PURE__ */ jsx16(Switch3, { checked: accepted, onCheckedChange: onAccepted, "aria-label": `${verb} without these` }) })
3152
3139
  ] });
3153
3140
  }
3154
3141
  function BackupPanel({ port, items, onClose, onChanged }) {
@@ -3283,7 +3270,7 @@ function BackupPanel({ port, items, onClose, onChanged }) {
3283
3270
  ),
3284
3271
  mode === "backup" ? /* @__PURE__ */ jsxs16(Fragment9, { children: [
3285
3272
  /* @__PURE__ */ jsx16(
3286
- Section,
3273
+ VaultSection,
3287
3274
  {
3288
3275
  title: `${selected.size} of ${plural(items.length, "credential")}`,
3289
3276
  actions: /* @__PURE__ */ jsxs16(Fragment9, { children: [
@@ -3302,13 +3289,13 @@ function BackupPanel({ port, items, onClose, onChanged }) {
3302
3289
  backup ? /* @__PURE__ */ jsxs16(Fragment9, { children: [
3303
3290
  /* @__PURE__ */ jsx16(Summary, { value: backup }),
3304
3291
  /* @__PURE__ */ jsx16(Omissions, { omissions: backup.omissions, accepted, onAccepted: setAccepted, verb: "Back up" }),
3305
- /* @__PURE__ */ jsxs16(Section, { children: [
3306
- /* @__PURE__ */ jsx16(Row, { label: "Passphrase", hint: "Not saved. It can't be recovered.", children: /* @__PURE__ */ jsx16(Field6, { type: "password", value: passphrase, autoComplete: "new-password", "aria-label": "Backup passphrase", onChange: (e) => setPassphrase(e.target.value) }) }),
3307
- /* @__PURE__ */ jsx16(Row, { label: "Repeat", ...mismatch ? { hint: "Doesn't match" } : {}, children: /* @__PURE__ */ jsx16(Field6, { type: "password", value: repeat, autoComplete: "new-password", "aria-label": "Repeat the passphrase", onChange: (e) => setRepeat(e.target.value) }) })
3292
+ /* @__PURE__ */ jsxs16(VaultSection, { children: [
3293
+ /* @__PURE__ */ jsx16(VaultRow, { label: "Passphrase", hint: "Not saved. It can't be recovered.", children: /* @__PURE__ */ jsx16(Field6, { type: "password", value: passphrase, autoComplete: "new-password", "aria-label": "Backup passphrase", onChange: (e) => setPassphrase(e.target.value) }) }),
3294
+ /* @__PURE__ */ jsx16(VaultRow, { label: "Repeat", ...mismatch ? { hint: "Doesn't match" } : {}, children: /* @__PURE__ */ jsx16(Field6, { type: "password", value: repeat, autoComplete: "new-password", "aria-label": "Repeat the passphrase", onChange: (e) => setRepeat(e.target.value) }) })
3308
3295
  ] })
3309
3296
  ] }) : null
3310
- ] }) : /* @__PURE__ */ jsx16(Fragment9, { children: !restorePreview ? /* @__PURE__ */ jsxs16(Section, { children: [
3311
- /* @__PURE__ */ jsxs16(Row, { label: "File", ...file ? { hint: file.name } : {}, children: [
3297
+ ] }) : /* @__PURE__ */ jsx16(Fragment9, { children: !restorePreview ? /* @__PURE__ */ jsxs16(VaultSection, { children: [
3298
+ /* @__PURE__ */ jsxs16(VaultRow, { label: "File", ...file ? { hint: file.name } : {}, children: [
3312
3299
  /* @__PURE__ */ jsx16(Button13, { variant: "outline", disabled: busy, onClick: () => fileInput.current?.click(), children: "Choose a backup" }),
3313
3300
  /* @__PURE__ */ jsx16(
3314
3301
  "input",
@@ -3324,11 +3311,11 @@ function BackupPanel({ port, items, onClose, onChanged }) {
3324
3311
  }
3325
3312
  )
3326
3313
  ] }),
3327
- /* @__PURE__ */ jsx16(Row, { label: "Passphrase", children: /* @__PURE__ */ jsx16(Field6, { type: "password", value: passphrase, autoComplete: "current-password", "aria-label": "Backup passphrase", onChange: (e) => setPassphrase(e.target.value) }) })
3314
+ /* @__PURE__ */ jsx16(VaultRow, { label: "Passphrase", children: /* @__PURE__ */ jsx16(Field6, { type: "password", value: passphrase, autoComplete: "current-password", "aria-label": "Backup passphrase", onChange: (e) => setPassphrase(e.target.value) }) })
3328
3315
  ] }) : /* @__PURE__ */ jsxs16(Fragment9, { children: [
3329
3316
  /* @__PURE__ */ jsx16(Summary, { value: restorePreview }),
3330
3317
  !result ? /* @__PURE__ */ jsx16(Omissions, { omissions: restorePreview.omissions, accepted, onAccepted: setAccepted, verb: "Restore" }) : null,
3331
- !result ? /* @__PURE__ */ jsx16("p", { className: "px-1 text-xs text-muted-foreground", children: "Restored items start disabled and restricted." }) : /* @__PURE__ */ jsx16(Section, { title: `${result.created} restored \xB7 ${result.replayed} already \xB7 ${result.refused} refused \xB7 ${result.retryable_failure} to retry`, children: result.results.map((r) => /* @__PURE__ */ jsx16(Row, { label: names.get(r.source_item_id) ?? "Credential", children: /* @__PURE__ */ jsxs16("span", { className: r.status === "refused" || r.status === "retryable_failure" ? "text-destructive" : "text-foreground", children: [
3318
+ !result ? /* @__PURE__ */ jsx16("p", { className: "px-1 text-xs text-muted-foreground", children: "Restored items start disabled and restricted." }) : /* @__PURE__ */ jsx16(VaultSection, { title: `${result.created} restored \xB7 ${result.replayed} already \xB7 ${result.refused} refused \xB7 ${result.retryable_failure} to retry`, children: result.results.map((r) => /* @__PURE__ */ jsx16(VaultRow, { label: names.get(r.source_item_id) ?? "Credential", children: /* @__PURE__ */ jsxs16("span", { className: r.status === "refused" || r.status === "retryable_failure" ? "text-destructive" : "text-foreground", children: [
3332
3319
  RECORD_STATUS[r.status],
3333
3320
  r.reason === "alias_conflict" ? " \xB7 name in use" : ""
3334
3321
  ] }) }, r.source_item_id)) })
@@ -3433,7 +3420,7 @@ function ExportPanel({ port, items, onClose }) {
3433
3420
  ] })
3434
3421
  ] }),
3435
3422
  children: [
3436
- /* @__PURE__ */ jsx17(Section, { children: /* @__PURE__ */ jsx17(Row, { label: "Format", hint: format?.hint, children: /* @__PURE__ */ jsx17(
3423
+ /* @__PURE__ */ jsx17(VaultSection, { children: /* @__PURE__ */ jsx17(VaultRow, { label: "Format", hint: format?.hint, children: /* @__PURE__ */ jsx17(
3437
3424
  Select5,
3438
3425
  {
3439
3426
  value: profile,
@@ -3446,7 +3433,7 @@ function ExportPanel({ port, items, onClose }) {
3446
3433
  }
3447
3434
  ) }) }),
3448
3435
  /* @__PURE__ */ jsx17(
3449
- Section,
3436
+ VaultSection,
3450
3437
  {
3451
3438
  title: `${selected.size} of ${plural(logins.length, "login")}`,
3452
3439
  actions: /* @__PURE__ */ jsxs17(Fragment10, { children: [
@@ -4517,13 +4504,13 @@ function ImportPanel({ port, host, items, organizations, onClose, onChanged, lim
4517
4504
  /* @__PURE__ */ jsx18(Button15, { variant: "primary", onClick: onClose, children: "Done" })
4518
4505
  ] });
4519
4506
  return /* @__PURE__ */ jsxs18(Panel, { title: "Import", size: "xl", onClose, footer, children: [
4520
- stage === "choose" ? /* @__PURE__ */ jsxs18(Section, { children: [
4521
- /* @__PURE__ */ jsx18(Row, { label: "Source", actions: help && host.openUrl ? /* @__PURE__ */ jsx18(Button15, { variant: "quiet", onClick: () => host.openUrl?.(help), children: "How to export" }) : void 0, children: /* @__PURE__ */ jsx18(Select6, { value: source, options: SOURCE_OPTIONS, "aria-label": "Source", onValueChange: (s) => {
4507
+ stage === "choose" ? /* @__PURE__ */ jsxs18(VaultSection, { children: [
4508
+ /* @__PURE__ */ jsx18(VaultRow, { label: "Source", actions: help && host.openUrl ? /* @__PURE__ */ jsx18(Button15, { variant: "quiet", onClick: () => host.openUrl?.(help), children: "How to export" }) : void 0, children: /* @__PURE__ */ jsx18(Select6, { value: source, options: SOURCE_OPTIONS, "aria-label": "Source", onValueChange: (s) => {
4522
4509
  setSource(s);
4523
4510
  setError(null);
4524
4511
  } }) }),
4525
- source === "env" ? /* @__PURE__ */ jsx18(Row, { label: ".env text", hint: "Same key updates in place", top: true, children: /* @__PURE__ */ jsx18(Textarea2, { mono: true, rows: 7, value: envText, autoComplete: "off", spellCheck: false, "aria-label": ".env text", placeholder: "OPENAI_API_KEY=sk-...\nDATABASE_URL=postgres://...", onChange: (e) => setEnvText(e.target.value) }) }) : null,
4526
- /* @__PURE__ */ jsxs18(Row, { label: "File", hint: fileName ?? void 0, children: [
4512
+ source === "env" ? /* @__PURE__ */ jsx18(VaultRow, { label: ".env text", hint: "Same key updates in place", top: true, children: /* @__PURE__ */ jsx18(Textarea2, { mono: true, rows: 7, value: envText, autoComplete: "off", spellCheck: false, "aria-label": ".env text", placeholder: "OPENAI_API_KEY=sk-...\nDATABASE_URL=postgres://...", onChange: (e) => setEnvText(e.target.value) }) }) : null,
4513
+ /* @__PURE__ */ jsxs18(VaultRow, { label: "File", hint: fileName ?? void 0, children: [
4527
4514
  /* @__PURE__ */ jsx18(Button15, { variant: "outline", disabled: reading, onClick: () => fileInput.current?.click(), children: reading ? "Reading\u2026" : source === "env" ? "Load a file" : "Choose a file" }),
4528
4515
  /* @__PURE__ */ jsx18(
4529
4516
  "input",
@@ -4540,12 +4527,12 @@ function ImportPanel({ port, host, items, organizations, onClose, onChanged, lim
4540
4527
  }
4541
4528
  )
4542
4529
  ] }),
4543
- source === "env" ? /* @__PURE__ */ jsx18(Row, { label: "Sandboxes", hint: "Pass these values to agent sandboxes", children: /* @__PURE__ */ jsx18(Switch4, { checked: injectSandbox, onCheckedChange: setInjectSandbox, "aria-label": "Use in sandboxes" }) }) : null
4530
+ source === "env" ? /* @__PURE__ */ jsx18(VaultRow, { label: "Sandboxes", hint: "Pass these values to agent sandboxes", children: /* @__PURE__ */ jsx18(Switch4, { checked: injectSandbox, onCheckedChange: setInjectSandbox, "aria-label": "Use in sandboxes" }) }) : null
4544
4531
  ] }) : null,
4545
4532
  stage === "review" && draft ? /* @__PURE__ */ jsxs18(Fragment11, { children: [
4546
- organizations.length > 0 ? /* @__PURE__ */ jsx18(Section, { children: /* @__PURE__ */ jsx18(Row, { label: "Save to", children: /* @__PURE__ */ jsx18(Select6, { value: destination, options: destinationOptions, "aria-label": "Save to", onValueChange: (v) => draft.kind === "file" ? restart({ destination: v }) : setDestination(v) }) }) }) : null,
4533
+ organizations.length > 0 ? /* @__PURE__ */ jsx18(VaultSection, { children: /* @__PURE__ */ jsx18(VaultRow, { label: "Save to", children: /* @__PURE__ */ jsx18(Select6, { value: destination, options: destinationOptions, "aria-label": "Save to", onValueChange: (v) => draft.kind === "file" ? restart({ destination: v }) : setDestination(v) }) }) }) : null,
4547
4534
  /* @__PURE__ */ jsx18(
4548
- Section,
4535
+ VaultSection,
4549
4536
  {
4550
4537
  title: draft.kind === "env" ? plural(envKeys.length, "value") : summary(counts, lines.length),
4551
4538
  actions: /* @__PURE__ */ jsxs18(Fragment11, { children: [
@@ -4573,11 +4560,11 @@ function ImportPanel({ port, host, items, organizations, onClose, onChanged, lim
4573
4560
  )
4574
4561
  }
4575
4562
  ),
4576
- draft.kind === "file" && draft.parsed.kind === "structured" ? /* @__PURE__ */ jsx18(Section, { children: /* @__PURE__ */ jsx18(Row, { label: "Visible details", hint: "Approve saving websites and public keys in the clear", children: /* @__PURE__ */ jsx18(Switch4, { checked: approvedVisible, disabled: busy, onCheckedChange: setApprovedVisible, "aria-label": "Approve visible details" }) }) }) : null,
4563
+ draft.kind === "file" && draft.parsed.kind === "structured" ? /* @__PURE__ */ jsx18(VaultSection, { children: /* @__PURE__ */ jsx18(VaultRow, { label: "Visible details", hint: "Approve saving websites and public keys in the clear", children: /* @__PURE__ */ jsx18(Switch4, { checked: approvedVisible, disabled: busy, onCheckedChange: setApprovedVisible, "aria-label": "Approve visible details" }) }) }) : null,
4577
4564
  draft.kind === "file" ? /* @__PURE__ */ jsx18(Notices, { draft }) : null,
4578
- draft.kind === "file" ? /* @__PURE__ */ jsx18(More, { children: /* @__PURE__ */ jsxs18(Section, { children: [
4579
- /* @__PURE__ */ jsx18(Row, { label: "Browser fill", hint: "Needs username, password and an https address", children: /* @__PURE__ */ jsx18(Switch4, { checked: browserFill, disabled: busy, onCheckedChange: (on) => restart({ browserFill: on }), "aria-label": "Browser fill" }) }),
4580
- draft.parsed.kind === "csv" ? draft.parsed.preview.headers.map((header, index) => /* @__PURE__ */ jsx18(Row, { label: header || `Column ${index + 1}`, children: /* @__PURE__ */ jsx18(
4565
+ draft.kind === "file" ? /* @__PURE__ */ jsx18(More, { children: /* @__PURE__ */ jsxs18(VaultSection, { children: [
4566
+ /* @__PURE__ */ jsx18(VaultRow, { label: "Browser fill", hint: "Needs username, password and an https address", children: /* @__PURE__ */ jsx18(Switch4, { checked: browserFill, disabled: busy, onCheckedChange: (on) => restart({ browserFill: on }), "aria-label": "Browser fill" }) }),
4567
+ draft.parsed.kind === "csv" ? draft.parsed.preview.headers.map((header, index) => /* @__PURE__ */ jsx18(VaultRow, { label: header || `Column ${index + 1}`, children: /* @__PURE__ */ jsx18(
4581
4568
  Select6,
4582
4569
  {
4583
4570
  value: draft.mapping[index] ?? "keep",
@@ -4589,16 +4576,16 @@ function ImportPanel({ port, host, items, organizations, onClose, onChanged, lim
4589
4576
  ] }) }) : null,
4590
4577
  ambiguous ? /* @__PURE__ */ jsx18(ErrorLine, { message: "Each of name, username, password, notes and one-time password can be used by one column." }) : null
4591
4578
  ] }) : null,
4592
- stage === "done" && done ? /* @__PURE__ */ jsxs18(Section, { title: "Result", children: [
4593
- /* @__PURE__ */ jsx18(Row, { label: "Created", children: /* @__PURE__ */ jsx18("span", { className: "text-foreground", children: done.created.length }) }),
4594
- /* @__PURE__ */ jsx18(Row, { label: "Skipped", children: /* @__PURE__ */ jsx18("span", { className: "text-foreground", children: done.skipped }) }),
4595
- /* @__PURE__ */ jsx18(Row, { label: "Failed", children: /* @__PURE__ */ jsx18("span", { className: done.failed.length > 0 ? "text-destructive" : "text-foreground", children: done.failed.length }) }),
4596
- done.untried.length > 0 ? /* @__PURE__ */ jsx18(Row, { label: "Not tried", children: /* @__PURE__ */ jsx18("span", { className: "text-foreground", children: done.untried.length }) }) : null,
4597
- done.withOtp > 0 ? /* @__PURE__ */ jsx18(Row, { label: "Codes", children: /* @__PURE__ */ jsxs18("span", { className: "text-muted-foreground", children: [
4579
+ stage === "done" && done ? /* @__PURE__ */ jsxs18(VaultSection, { title: "Result", children: [
4580
+ /* @__PURE__ */ jsx18(VaultRow, { label: "Created", children: /* @__PURE__ */ jsx18("span", { className: "text-foreground", children: done.created.length }) }),
4581
+ /* @__PURE__ */ jsx18(VaultRow, { label: "Skipped", children: /* @__PURE__ */ jsx18("span", { className: "text-foreground", children: done.skipped }) }),
4582
+ /* @__PURE__ */ jsx18(VaultRow, { label: "Failed", children: /* @__PURE__ */ jsx18("span", { className: done.failed.length > 0 ? "text-destructive" : "text-foreground", children: done.failed.length }) }),
4583
+ done.untried.length > 0 ? /* @__PURE__ */ jsx18(VaultRow, { label: "Not tried", children: /* @__PURE__ */ jsx18("span", { className: "text-foreground", children: done.untried.length }) }) : null,
4584
+ done.withOtp > 0 ? /* @__PURE__ */ jsx18(VaultRow, { label: "Codes", children: /* @__PURE__ */ jsxs18("span", { className: "text-muted-foreground", children: [
4598
4585
  plural(done.withOtp, "login"),
4599
4586
  " still need the one-time password added."
4600
4587
  ] }) }) : null,
4601
- done.failed.map((f) => /* @__PURE__ */ jsx18(Row, { label: f.title, children: /* @__PURE__ */ jsx18("span", { className: "block truncate text-destructive", title: f.reason, children: f.reason }) }, f.key))
4588
+ done.failed.map((f) => /* @__PURE__ */ jsx18(VaultRow, { label: f.title, children: /* @__PURE__ */ jsx18("span", { className: "block truncate text-destructive", title: f.reason, children: f.reason }) }, f.key))
4602
4589
  ] }) : null,
4603
4590
  /* @__PURE__ */ jsx18(ErrorLine, { message: error })
4604
4591
  ] });
@@ -4658,11 +4645,13 @@ import { Badge as Badge7, Button as Button21, CONTROLS_CONTAINER_CLASS, OptionCo
4658
4645
  import { confirm as confirm9 } from "@ai-matrx/kit/confirm-opener";
4659
4646
 
4660
4647
  // src/activity/FilesSection.tsx
4648
+ import { formatFileSize as formatFileSize2 } from "@ai-matrx/kit/format";
4661
4649
  import { useRef as useRef13, useState as useState20 } from "react";
4662
4650
  import { Badge as Badge5, Button as Button16, Field as Field7, SegmentedControl as SegmentedControl4 } from "@ai-matrx/design-system/controls";
4663
4651
  import { cn as cn9 } from "@ai-matrx/design-system";
4664
4652
  import { confirm as confirm6 } from "@ai-matrx/kit/confirm-opener";
4665
4653
  import { downloadFile as downloadFile3 } from "@ai-matrx/kit/download";
4654
+ import { DownloadIcon } from "@ai-matrx/design-system/icons";
4666
4655
  import { Fragment as Fragment12, jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
4667
4656
  var messageOf2 = (e, fallback) => wasCancelled(e) ? null : e instanceof Error ? e.message : fallback;
4668
4657
  var TOO_BIG = "Files over 25 MB can't be stored.";
@@ -4721,7 +4710,7 @@ function FilesSection({ item, port, editing, onChanged }) {
4721
4710
  onDragLeave: canEdit ? () => setDragging(false) : void 0,
4722
4711
  onDrop: canEdit ? drop : void 0,
4723
4712
  children: /* @__PURE__ */ jsxs19(
4724
- Section,
4713
+ VaultSection,
4725
4714
  {
4726
4715
  title: "Files",
4727
4716
  actions: canEdit ? /* @__PURE__ */ jsx20(Button16, { variant: "quiet", icon: /* @__PURE__ */ jsx20(PlusGlyph, {}), disabled: busy !== null, onClick: () => picker.current?.click(), children: "Add file" }) : void 0,
@@ -4732,11 +4721,11 @@ function FilesSection({ item, port, editing, onChanged }) {
4732
4721
  } }) : null,
4733
4722
  item.attachments.map(
4734
4723
  (a) => canEdit ? /* @__PURE__ */ jsx20(EditableFile, { port, item, file: a, busy, run, onDownload: () => void download(a), onTooBig: () => setError(TOO_BIG) }, a.id) : /* @__PURE__ */ jsx20(
4735
- Row,
4724
+ VaultRow,
4736
4725
  {
4737
4726
  label: a.label,
4738
4727
  hint: a.description || void 0,
4739
- actions: a.handling === "sealed" ? /* @__PURE__ */ jsx20(Badge5, { icon: /* @__PURE__ */ jsx20(LockGlyph, {}), children: "Sealed" }) : canDownload(item, a) ? /* @__PURE__ */ jsx20(Button16, { variant: "quiet", icon: /* @__PURE__ */ jsx20(DownloadGlyph, {}), "aria-label": `Download ${a.fileName}`, disabled: busy !== null, onClick: () => void download(a) }) : null,
4728
+ actions: a.handling === "sealed" ? /* @__PURE__ */ jsx20(Badge5, { icon: /* @__PURE__ */ jsx20(LockGlyph, {}), children: "Sealed" }) : canDownload(item, a) ? /* @__PURE__ */ jsx20(Button16, { variant: "quiet", icon: /* @__PURE__ */ jsx20(DownloadIcon, {}), "aria-label": `Download ${a.fileName}`, disabled: busy !== null, onClick: () => void download(a) }) : null,
4740
4729
  children: /* @__PURE__ */ jsx20(FileName, { file: a })
4741
4730
  },
4742
4731
  a.id
@@ -4762,12 +4751,12 @@ function EditableFile({ port, item: it, file: a, busy: b, run: go, onDownload, o
4762
4751
  }
4763
4752
  return /* @__PURE__ */ jsxs19(Fragment12, { children: [
4764
4753
  /* @__PURE__ */ jsx20(
4765
- Row,
4754
+ VaultRow,
4766
4755
  {
4767
4756
  label: a.label,
4768
4757
  hint: a.description || void 0,
4769
4758
  actions: /* @__PURE__ */ jsxs19(Fragment12, { children: [
4770
- canDownload(it, a) ? /* @__PURE__ */ jsx20(Button16, { variant: "quiet", icon: /* @__PURE__ */ jsx20(DownloadGlyph, {}), "aria-label": `Download ${a.fileName}`, disabled: b !== null, onClick: onDownload }) : null,
4759
+ canDownload(it, a) ? /* @__PURE__ */ jsx20(Button16, { variant: "quiet", icon: /* @__PURE__ */ jsx20(DownloadIcon, {}), "aria-label": `Download ${a.fileName}`, disabled: b !== null, onClick: onDownload }) : null,
4771
4760
  /* @__PURE__ */ jsx20(Button16, { variant: "quiet", icon: /* @__PURE__ */ jsx20(PencilGlyph, {}), "aria-label": `Edit ${a.label}`, pressed: open, disabled: b !== null, onClick: () => setOpen((o) => !o) }),
4772
4761
  /* @__PURE__ */ jsx20(Button16, { variant: "quiet", icon: /* @__PURE__ */ jsx20(UploadGlyph, {}), "aria-label": `Replace ${a.fileName}`, disabled: b !== null, onClick: () => replacer.current?.click() }),
4773
4762
  /* @__PURE__ */ jsx20(Button16, { variant: "quiet", icon: /* @__PURE__ */ jsx20(TrashGlyph, {}), "aria-label": `Delete ${a.label}`, disabled: b !== null, onClick: () => void remove() }),
@@ -4798,7 +4787,7 @@ function EditableFile({ port, item: it, file: a, busy: b, run: go, onDownload, o
4798
4787
  function FileName({ file }) {
4799
4788
  return /* @__PURE__ */ jsxs19("span", { className: "flex min-w-0 items-center gap-2", children: [
4800
4789
  /* @__PURE__ */ jsx20("span", { className: "truncate", children: file.fileName }),
4801
- /* @__PURE__ */ jsx20("span", { className: "shrink-0 text-xs text-muted-foreground", children: formatBytes(file.sizeBytes) })
4790
+ /* @__PURE__ */ jsx20("span", { className: "shrink-0 text-xs text-muted-foreground", children: formatFileSize2(file.sizeBytes) })
4802
4791
  ] });
4803
4792
  }
4804
4793
  function Protection({ value, locked, onChange }) {
@@ -4821,13 +4810,13 @@ function NewFile({ file, busy, onAdd, onCancel }) {
4821
4810
  await onAdd({ label: label.trim(), description: description.trim() || null, handling });
4822
4811
  }
4823
4812
  return /* @__PURE__ */ jsxs19(Fragment12, { children: [
4824
- /* @__PURE__ */ jsx20(Row, { label: "New file", children: /* @__PURE__ */ jsxs19("span", { className: "flex min-w-0 items-center gap-2", children: [
4813
+ /* @__PURE__ */ jsx20(VaultRow, { label: "New file", children: /* @__PURE__ */ jsxs19("span", { className: "flex min-w-0 items-center gap-2", children: [
4825
4814
  /* @__PURE__ */ jsx20("span", { className: "truncate", children: file.name }),
4826
- /* @__PURE__ */ jsx20("span", { className: "shrink-0 text-xs text-muted-foreground", children: formatBytes(file.size) })
4815
+ /* @__PURE__ */ jsx20("span", { className: "shrink-0 text-xs text-muted-foreground", children: formatFileSize2(file.size) })
4827
4816
  ] }) }),
4828
- /* @__PURE__ */ jsx20(Row, { label: "Name", children: /* @__PURE__ */ jsx20(Field7, { "aria-label": "Name", value: label, onChange: (e) => setLabel(e.target.value) }) }),
4829
- /* @__PURE__ */ jsx20(Row, { label: "Purpose", children: /* @__PURE__ */ jsx20(Field7, { "aria-label": "Purpose", placeholder: "What it is for", value: description, onChange: (e) => setDescription(e.target.value) }) }),
4830
- /* @__PURE__ */ jsx20(Row, { label: "Protection", children: /* @__PURE__ */ jsx20(Protection, { value: handling, locked: false, onChange: setHandling }) }),
4817
+ /* @__PURE__ */ jsx20(VaultRow, { label: "Name", children: /* @__PURE__ */ jsx20(Field7, { "aria-label": "Name", value: label, onChange: (e) => setLabel(e.target.value) }) }),
4818
+ /* @__PURE__ */ jsx20(VaultRow, { label: "Purpose", children: /* @__PURE__ */ jsx20(Field7, { "aria-label": "Purpose", placeholder: "What it is for", value: description, onChange: (e) => setDescription(e.target.value) }) }),
4819
+ /* @__PURE__ */ jsx20(VaultRow, { label: "Protection", children: /* @__PURE__ */ jsx20(Protection, { value: handling, locked: false, onChange: setHandling }) }),
4831
4820
  /* @__PURE__ */ jsxs19("div", { className: "flex justify-end gap-2 px-3 py-1 sm:px-4", children: [
4832
4821
  /* @__PURE__ */ jsx20(Button16, { variant: "quiet", disabled: busy, onClick: onCancel, children: "Cancel" }),
4833
4822
  /* @__PURE__ */ jsx20(Button16, { variant: "primary", disabled: busy || !label.trim(), onClick: () => void add(), children: busy ? "Adding\u2026" : "Add file" })
@@ -4845,10 +4834,10 @@ function FileDetailsRows({ file, busy, onSave, onCancel }) {
4845
4834
  await onSave({ label: label.trim(), description: description.trim() || null, fileName: fileName.trim(), handling });
4846
4835
  }
4847
4836
  return /* @__PURE__ */ jsxs19(Fragment12, { children: [
4848
- /* @__PURE__ */ jsx20(Row, { label: "Name", children: /* @__PURE__ */ jsx20(Field7, { "aria-label": "Name", value: label, onChange: (e) => setLabel(e.target.value) }) }),
4849
- /* @__PURE__ */ jsx20(Row, { label: "Purpose", children: /* @__PURE__ */ jsx20(Field7, { "aria-label": "Purpose", placeholder: "What it is for", value: description, onChange: (e) => setDescription(e.target.value) }) }),
4850
- /* @__PURE__ */ jsx20(Row, { label: "File name", children: /* @__PURE__ */ jsx20(Field7, { "aria-label": "File name", value: fileName, onChange: (e) => setFileName(e.target.value) }) }),
4851
- /* @__PURE__ */ jsx20(Row, { label: "Protection", children: /* @__PURE__ */ jsx20(Protection, { value: handling, locked: file.handling === "sealed", onChange: setHandling }) }),
4837
+ /* @__PURE__ */ jsx20(VaultRow, { label: "Name", children: /* @__PURE__ */ jsx20(Field7, { "aria-label": "Name", value: label, onChange: (e) => setLabel(e.target.value) }) }),
4838
+ /* @__PURE__ */ jsx20(VaultRow, { label: "Purpose", children: /* @__PURE__ */ jsx20(Field7, { "aria-label": "Purpose", placeholder: "What it is for", value: description, onChange: (e) => setDescription(e.target.value) }) }),
4839
+ /* @__PURE__ */ jsx20(VaultRow, { label: "File name", children: /* @__PURE__ */ jsx20(Field7, { "aria-label": "File name", value: fileName, onChange: (e) => setFileName(e.target.value) }) }),
4840
+ /* @__PURE__ */ jsx20(VaultRow, { label: "Protection", children: /* @__PURE__ */ jsx20(Protection, { value: handling, locked: file.handling === "sealed", onChange: setHandling }) }),
4852
4841
  /* @__PURE__ */ jsxs19("div", { className: "flex justify-end gap-2 px-3 py-1 sm:px-4", children: [
4853
4842
  /* @__PURE__ */ jsx20(Button16, { variant: "quiet", disabled: busy, onClick: onCancel, children: "Cancel" }),
4854
4843
  /* @__PURE__ */ jsx20(Button16, { variant: "primary", disabled: busy || !changed || !label.trim() || !fileName.trim(), onClick: () => void save(), children: busy ? "Saving\u2026" : "Save" })
@@ -4867,6 +4856,7 @@ function confirmSeal(label) {
4867
4856
  // src/fields/RecoveryCodesRow.tsx
4868
4857
  import { useState as useState21 } from "react";
4869
4858
  import { Badge as Badge6, Button as Button17, Textarea as Textarea3 } from "@ai-matrx/design-system/controls";
4859
+ import { CopyIcon as CopyIcon6 } from "@ai-matrx/design-system/icons";
4870
4860
  import { Fragment as Fragment13, jsx as jsx21, jsxs as jsxs20 } from "react/jsx-runtime";
4871
4861
  var MASK4 = "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
4872
4862
  var say2 = (e, fallback) => e instanceof Error && e.message ? e.message : fallback;
@@ -4907,7 +4897,7 @@ function RecoveryCodesRow({ item, field, port, onChanged }) {
4907
4897
  };
4908
4898
  if (draft !== null) {
4909
4899
  return /* @__PURE__ */ jsxs20(
4910
- Row,
4900
+ VaultRow,
4911
4901
  {
4912
4902
  label: "Recovery codes",
4913
4903
  top: true,
@@ -4927,7 +4917,7 @@ function RecoveryCodesRow({ item, field, port, onChanged }) {
4927
4917
  }
4928
4918
  if (!field) {
4929
4919
  if (!canEdit) return null;
4930
- return /* @__PURE__ */ jsx21(Row, { label: "Recovery codes", actions: /* @__PURE__ */ jsx21(Button17, { variant: "quiet", icon: /* @__PURE__ */ jsx21(PlusGlyph, {}), "aria-label": "Add recovery codes", onClick: () => setDraft("") }), children: /* @__PURE__ */ jsx21("span", { className: "text-muted-foreground", children: "None" }) });
4920
+ return /* @__PURE__ */ jsx21(VaultRow, { label: "Recovery codes", actions: /* @__PURE__ */ jsx21(Button17, { variant: "quiet", icon: /* @__PURE__ */ jsx21(PlusGlyph, {}), "aria-label": "Add recovery codes", onClick: () => setDraft("") }), children: /* @__PURE__ */ jsx21("span", { className: "text-muted-foreground", children: "None" }) });
4931
4921
  }
4932
4922
  const sealed = field.handling === "sealed";
4933
4923
  const canSee = !sealed && item.capabilities.canReveal;
@@ -4949,7 +4939,7 @@ function RecoveryCodesRow({ item, field, port, onChanged }) {
4949
4939
  });
4950
4940
  };
4951
4941
  return /* @__PURE__ */ jsx21(
4952
- Row,
4942
+ VaultRow,
4953
4943
  {
4954
4944
  label: "Recovery codes",
4955
4945
  top: codes !== null,
@@ -4960,7 +4950,7 @@ function RecoveryCodesRow({ item, field, port, onChanged }) {
4960
4950
  children: sealed ? /* @__PURE__ */ jsx21(Badge6, { icon: /* @__PURE__ */ jsx21(LockGlyph, {}), children: "Sealed" }) : codes ? /* @__PURE__ */ jsxs20("ul", { className: "flex flex-col gap-0.5", "aria-label": "Recovery codes", children: [
4961
4951
  codes.map((code, i) => /* @__PURE__ */ jsxs20("li", { className: "flex min-h-7 items-center gap-1", children: [
4962
4952
  /* @__PURE__ */ jsx21("code", { className: "min-w-0 flex-1 break-all font-mono text-sm text-foreground", children: code }),
4963
- /* @__PURE__ */ jsx21(Button17, { variant: "quiet", icon: /* @__PURE__ */ jsx21(CopyGlyph, {}), "aria-label": `Copy code ${i + 1}`, onClick: () => void copyValue2(code, "Recovery code") }),
4953
+ /* @__PURE__ */ jsx21(Button17, { variant: "quiet", icon: /* @__PURE__ */ jsx21(CopyIcon6, {}), "aria-label": `Copy code ${i + 1}`, onClick: () => void copyValue2(code, "Recovery code") }),
4964
4954
  canEdit ? /* @__PURE__ */ jsx21(Button17, { variant: "quiet", icon: /* @__PURE__ */ jsx21(CheckGlyph, {}), disabled: busy, onClick: () => void markUsed(i), children: "Mark used" }) : null
4965
4955
  ] }, `${i}-${code}`)),
4966
4956
  error ? /* @__PURE__ */ jsx21("li", { role: "alert", className: "text-xs text-destructive", children: error }) : null
@@ -4969,33 +4959,17 @@ function RecoveryCodesRow({ item, field, port, onChanged }) {
4969
4959
  );
4970
4960
  }
4971
4961
 
4962
+ // src/ItemPane.tsx
4963
+ import { HistoryIcon, SettingsIcon, UsersIcon as UsersIcon2 } from "@ai-matrx/design-system/icons";
4964
+ import { dropKeptDraft, keepDraft, readKeptDraft } from "@ai-matrx/kit/drafts";
4965
+
4972
4966
  // src/draft-keep.ts
4973
4967
  var PREFIX = "matrx.vault.draft:";
4974
4968
  function draftKey(itemId, definitionKey) {
4975
4969
  return `${PREFIX}${itemId ?? `new:${definitionKey ?? "custom"}`}`;
4976
4970
  }
4977
- function keepDraft(key, basedOn, d) {
4978
- const kept = { basedOn, draft: { name: d.name, description: d.description, tags: d.tags, loginUrls: d.loginUrls, notes: d.notes, custom: d.custom } };
4979
- try {
4980
- globalThis.sessionStorage?.setItem(key, JSON.stringify(kept));
4981
- } catch {
4982
- }
4983
- }
4984
- function readKeptDraft(key, basedOn) {
4985
- try {
4986
- const raw = globalThis.sessionStorage?.getItem(key);
4987
- if (!raw) return null;
4988
- const kept = JSON.parse(raw);
4989
- return kept.basedOn === basedOn ? kept.draft : null;
4990
- } catch {
4991
- return null;
4992
- }
4993
- }
4994
- function dropKeptDraft(key) {
4995
- try {
4996
- globalThis.sessionStorage?.removeItem(key);
4997
- } catch {
4998
- }
4971
+ function keptFieldsOf(d) {
4972
+ return { name: d.name, description: d.description, tags: d.tags, loginUrls: d.loginUrls, notes: d.notes, custom: d.custom };
4999
4973
  }
5000
4974
 
5001
4975
  // src/extension/page-logic.ts
@@ -5142,6 +5116,7 @@ import { useEffect as useEffect15, useState as useState25 } from "react";
5142
5116
  import { confirm as confirm8 } from "@ai-matrx/kit/confirm-opener";
5143
5117
  import { Button as Button20, DisclosureHeader as DisclosureHeader3, Field as Field9, RegionSkeleton, Select as Select8 } from "@ai-matrx/design-system/controls";
5144
5118
  import { cn as cn11 } from "@ai-matrx/design-system";
5119
+ import { UsersIcon } from "@ai-matrx/design-system/icons";
5145
5120
 
5146
5121
  // src/sharing/logic.ts
5147
5122
  var LEVEL_OPTIONS = [
@@ -5173,7 +5148,7 @@ function copyRefusal(message2) {
5173
5148
  return /duplicate/i.test(message2) ? "There is already a copy of this item there." : null;
5174
5149
  }
5175
5150
  var isPasskey = (item) => item.definitionKey === "native_passkey" || item.definitionKey === "passkey_private";
5176
- function moveConsequence(item, to) {
5151
+ function itemMoveConsequence(item, to) {
5177
5152
  if (item.authenticator) return "One-time password stays behind; set it up again";
5178
5153
  return to ? "Its members get access; people you shared with lose it" : "Only you; organization members lose access";
5179
5154
  }
@@ -5263,7 +5238,7 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
5263
5238
  const to = destinationOf(moveChoice.value);
5264
5239
  const ok = await confirm7({
5265
5240
  title: `Move to ${moveChoice.label}?`,
5266
- description: `"${item.name}" stays the same item, so everything using it keeps working. ${moveConsequence(item, to)}.`,
5241
+ description: `"${item.name}" stays the same item, so everything using it keeps working. ${itemMoveConsequence(item, to)}.`,
5267
5242
  confirmLabel: "Move"
5268
5243
  });
5269
5244
  if (!ok) return;
@@ -5299,17 +5274,17 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
5299
5274
  /* @__PURE__ */ jsx24(StatusLine, { error, notice }),
5300
5275
  /* @__PURE__ */ jsx24(Button19, { variant: "outline", className: "ml-auto", onClick: onClose, children: "Close" })
5301
5276
  ] }),
5302
- children: nothing ? /* @__PURE__ */ jsx24(Section, { children: /* @__PURE__ */ jsx24(Empty, { children: passkey ? "A passkey stays where it was created." : "Only the owner can move or give this item." }) }) : /* @__PURE__ */ jsxs22(Section, { children: [
5277
+ children: nothing ? /* @__PURE__ */ jsx24(VaultSection, { children: /* @__PURE__ */ jsx24(Empty, { children: passkey ? "A passkey stays where it was created." : "Only the owner can move or give this item." }) }) : /* @__PURE__ */ jsxs22(VaultSection, { children: [
5303
5278
  canMove && moves.length > 0 ? /* @__PURE__ */ jsx24(
5304
- Row,
5279
+ VaultRow,
5305
5280
  {
5306
5281
  label: "Move to",
5307
- hint: moveChoice ? moveConsequence(item, destinationOf(moveChoice.value)) : void 0,
5282
+ hint: moveChoice ? itemMoveConsequence(item, destinationOf(moveChoice.value)) : void 0,
5308
5283
  actions: /* @__PURE__ */ jsx24(Button19, { variant: "outline", disabled: busy !== null || !moveChoice, onClick: () => void move(), children: "Move" }),
5309
5284
  children: /* @__PURE__ */ jsx24(Select7, { className: "w-full", "aria-label": "Move to", value: moveTo || NONE, onValueChange: (v) => setMoveTo(v === NONE ? "" : v), options: [{ value: NONE, label: "Choose where" }, ...moves] })
5310
5285
  }
5311
5286
  ) : null,
5312
- canGive ? /* @__PURE__ */ jsx24(Row, { label: "Give to", hint: "You lose all access; your shares end", actions: /* @__PURE__ */ jsx24(Button19, { variant: "danger", disabled: busy !== null || !isEmail(email), onClick: () => void give(), children: "Give" }), children: /* @__PURE__ */ jsx24(
5287
+ canGive ? /* @__PURE__ */ jsx24(VaultRow, { label: "Give to", hint: "You lose all access; your shares end", actions: /* @__PURE__ */ jsx24(Button19, { variant: "danger", disabled: busy !== null || !isEmail(email), onClick: () => void give(), children: "Give" }), children: /* @__PURE__ */ jsx24(
5313
5288
  Field8,
5314
5289
  {
5315
5290
  className: "w-full",
@@ -5323,7 +5298,7 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
5323
5298
  onChange: (e) => setEmail(e.target.value)
5324
5299
  }
5325
5300
  ) }) : null,
5326
- canCopy && copies.length > 0 ? /* @__PURE__ */ jsx24(Row, { label: "Copy to", hint: "A separate item; edits no longer sync", actions: /* @__PURE__ */ jsx24(Button19, { variant: "outline", disabled: busy !== null || !copyChoice, onClick: () => void copy(), children: "Copy" }), children: /* @__PURE__ */ jsx24(Select7, { className: "w-full", "aria-label": "Copy to", value: copyTo || NONE, onValueChange: (v) => setCopyTo(v === NONE ? "" : v), options: [{ value: NONE, label: "Choose where" }, ...copies] }) }) : null
5301
+ canCopy && copies.length > 0 ? /* @__PURE__ */ jsx24(VaultRow, { label: "Copy to", hint: "A separate item; edits no longer sync", actions: /* @__PURE__ */ jsx24(Button19, { variant: "outline", disabled: busy !== null || !copyChoice, onClick: () => void copy(), children: "Copy" }), children: /* @__PURE__ */ jsx24(Select7, { className: "w-full", "aria-label": "Copy to", value: copyTo || NONE, onValueChange: (v) => setCopyTo(v === NONE ? "" : v), options: [{ value: NONE, label: "Choose where" }, ...copies] }) }) : null
5327
5302
  ] })
5328
5303
  }
5329
5304
  );
@@ -5405,7 +5380,7 @@ function SharePanel({ item, port, organizations, onClose, onChanged }) {
5405
5380
  }
5406
5381
  };
5407
5382
  if (!item.capabilities.canManage) {
5408
- return /* @__PURE__ */ jsx25(Panel, { title: "Share", size: "md", onClose, footer: /* @__PURE__ */ jsx25(Button20, { variant: "primary", onClick: onClose, children: "Done" }), children: /* @__PURE__ */ jsx25(Section, { children: /* @__PURE__ */ jsx25(Empty, { children: "Only the owner can change who has access." }) }) });
5383
+ return /* @__PURE__ */ jsx25(Panel, { title: "Share", size: "md", onClose, footer: /* @__PURE__ */ jsx25(Button20, { variant: "primary", onClick: onClose, children: "Done" }), children: /* @__PURE__ */ jsx25(VaultSection, { children: /* @__PURE__ */ jsx25(Empty, { children: "Only the owner can change who has access." }) }) });
5409
5384
  }
5410
5385
  return /* @__PURE__ */ jsxs23(
5411
5386
  Panel,
@@ -5418,9 +5393,9 @@ function SharePanel({ item, port, organizations, onClose, onChanged }) {
5418
5393
  /* @__PURE__ */ jsx25(Button20, { variant: "primary", className: "ml-auto", onClick: onClose, children: "Done" })
5419
5394
  ] }),
5420
5395
  children: [
5421
- /* @__PURE__ */ jsxs23(Section, { title: "Who has access", children: [
5396
+ /* @__PURE__ */ jsxs23(VaultSection, { title: "Who has access", children: [
5422
5397
  isOrg ? /* @__PURE__ */ jsx25(AccessLine, { glyph: BuildingGlyph, who: `${orgName} admins`, children: /* @__PURE__ */ jsx25("span", { className: "px-2 text-sm text-muted-foreground", children: "Full access" }) }) : /* @__PURE__ */ jsx25(AccessLine, { glyph: PersonGlyph, who: "You", meta: "Owner", children: /* @__PURE__ */ jsx25("span", { className: "px-2 text-sm text-muted-foreground", children: "Full access" }) }),
5423
- isOrg ? /* @__PURE__ */ jsx25(AccessLine, { glyph: UsersGlyph, who: `${orgName} members`, children: /* @__PURE__ */ jsx25(
5398
+ isOrg ? /* @__PURE__ */ jsx25(AccessLine, { glyph: UsersIcon, who: `${orgName} members`, children: /* @__PURE__ */ jsx25(
5424
5399
  Select8,
5425
5400
  {
5426
5401
  variant: "inline",
@@ -5481,7 +5456,7 @@ function IntoOrganization({ item, port, organizations, grants, onShared }) {
5481
5456
  const [level, setLevel] = useState25("use");
5482
5457
  const chosen = open.find((o) => o.id === target);
5483
5458
  if (item.owner.kind !== "me") return null;
5484
- return /* @__PURE__ */ jsx25(Section, { title: "Share into organization", children: open.length > 0 ? /* @__PURE__ */ jsxs23(Fragment14, { children: [
5459
+ return /* @__PURE__ */ jsx25(VaultSection, { title: "Share into organization", children: open.length > 0 ? /* @__PURE__ */ jsxs23(Fragment14, { children: [
5485
5460
  /* @__PURE__ */ jsxs23("div", { className: "flex min-h-11 items-center gap-2 px-3 sm:px-4", children: [
5486
5461
  /* @__PURE__ */ jsx25(BuildingGlyph, { className: "size-4 shrink-0 text-muted-foreground" }),
5487
5462
  /* @__PURE__ */ jsx25(Select8, { className: "min-w-0 flex-1", "aria-label": "Organization", value: target || "__none__", onValueChange: (v) => setTarget(v === "__none__" ? "" : v), options: [{ value: "__none__", label: "Choose an organization" }, ...open.map((o) => ({ value: o.id, label: o.name }))] }),
@@ -5531,7 +5506,7 @@ function MemberAccess({ port, organizationId, organizationName }) {
5531
5506
  const effective = await run(userId, () => port.sharing.setMemberAccess(organizationId, userId, access));
5532
5507
  if (effective) setList((l) => l ? { ...l, members: l.members.map((m) => m.userId === userId ? { ...m, access, effective } : m) } : l);
5533
5508
  };
5534
- return /* @__PURE__ */ jsxs23(Section, { title: `${organizationName} vault access`, children: [
5509
+ return /* @__PURE__ */ jsxs23(VaultSection, { title: `${organizationName} vault access`, children: [
5535
5510
  loadError ? /* @__PURE__ */ jsx25(Empty, { children: loadError }) : list === null ? /* @__PURE__ */ jsx25(RegionSkeleton, { shape: "rows", count: 3, "aria-label": "Loading member access", className: "px-3 sm:px-4" }) : list.members.length === 0 ? /* @__PURE__ */ jsx25(Empty, { children: "No members yet." }) : list.members.map((m) => /* @__PURE__ */ jsx25(AccessLine, { glyph: PersonGlyph, who: m.email || m.userId, meta: m.role, children: m.effective === "admin" ? /* @__PURE__ */ jsx25("span", { className: "px-2 text-sm text-muted-foreground", children: MEMBER_ACCESS_LABEL.admin }) : /* @__PURE__ */ jsx25(
5536
5511
  Select8,
5537
5512
  {
@@ -5607,7 +5582,7 @@ function ItemPane(props) {
5607
5582
  if (was && was.id === id && was.mode === mode && editing) {
5608
5583
  setDraft((d) => rebaseDraft(was.base, base, d));
5609
5584
  } else {
5610
- const kept = editing ? readKeptDraft(keepKey, item?.updatedAt ?? "new") : null;
5585
+ const kept = editing ? readKeptDraft(keepKey, { basedOn: item?.updatedAt ?? "new" })?.value ?? null : null;
5611
5586
  setDraft(kept ? { ...base, ...kept } : base);
5612
5587
  setTagsText((kept ?? base).tags.join(", "));
5613
5588
  setError(null);
@@ -5622,7 +5597,7 @@ function ItemPane(props) {
5622
5597
  useEffect16(() => onDirty(dirty), [dirty, onDirty]);
5623
5598
  const keepKey = draftKey(item?.id ?? null, definition?.key ?? item?.definitionKey ?? null);
5624
5599
  useEffect16(() => {
5625
- if (editing && dirty) keepDraft(keepKey, item?.updatedAt ?? "new", draft);
5600
+ if (editing && dirty) keepDraft(keepKey, keptFieldsOf(draft), { basedOn: item?.updatedAt ?? "new" });
5626
5601
  else if (!editing) dropKeptDraft(keepKey);
5627
5602
  }, [editing, dirty, draft, keepKey, item?.updatedAt]);
5628
5603
  useEffect16(() => {
@@ -5709,7 +5684,7 @@ function ItemPane(props) {
5709
5684
  const viewCustom = (item?.custom ?? []).filter((c) => !declaredKeys.has(c.key) && c.key !== MFA_METHOD_KEY && !isAuthenticatorStorage(c.key));
5710
5685
  const isLogin = (item?.definitionKey ?? definition?.key) === "website_login" || (item?.definitionKey ?? definition?.key) === "username_password";
5711
5686
  const typeLabel = definition?.label ?? item?.definitionLabel ?? "";
5712
- const shownOwner = mode === "new" ? owner === "me" ? { label: "Personal", glyph: /* @__PURE__ */ jsx26(PersonGlyph, {}) } : owner === "person" ? { label: "Someone else", glyph: /* @__PURE__ */ jsx26(SendGlyph, {}) } : { label: organizations.find((o) => o.id === owner)?.name ?? "Organization", glyph: /* @__PURE__ */ jsx26(BuildingGlyph, {}) } : item ? { label: item.owner.label, glyph: item.owner.kind === "me" ? /* @__PURE__ */ jsx26(PersonGlyph, {}) : item.owner.kind === "organization" ? /* @__PURE__ */ jsx26(BuildingGlyph, {}) : /* @__PURE__ */ jsx26(UsersGlyph, {}) } : null;
5687
+ const shownOwner = mode === "new" ? owner === "me" ? { label: "Personal", glyph: /* @__PURE__ */ jsx26(PersonGlyph, {}) } : owner === "person" ? { label: "Someone else", glyph: /* @__PURE__ */ jsx26(SendGlyph, {}) } : { label: organizations.find((o) => o.id === owner)?.name ?? "Organization", glyph: /* @__PURE__ */ jsx26(BuildingGlyph, {}) } : item ? { label: item.owner.label, glyph: item.owner.kind === "me" ? /* @__PURE__ */ jsx26(PersonGlyph, {}) : item.owner.kind === "organization" ? /* @__PURE__ */ jsx26(BuildingGlyph, {}) : /* @__PURE__ */ jsx26(UsersIcon2, {}) } : null;
5713
5688
  const tagsVisible = showTags || draft.tags.length > 0 || tagsText !== "";
5714
5689
  const descriptionVisible = showDescription || draft.description !== "";
5715
5690
  const header = /* @__PURE__ */ jsxs24("header", { className: "flex min-h-14 items-center gap-2 border-b border-border px-3 py-2 sm:gap-3 sm:px-5", children: [
@@ -5766,7 +5741,7 @@ function ItemPane(props) {
5766
5741
  "Send securely"
5767
5742
  ] }) : null,
5768
5743
  /* @__PURE__ */ jsxs24(DropdownMenuItem3, { onSelect: () => onPanel("history"), children: [
5769
- /* @__PURE__ */ jsx26(HistoryGlyph, { className: "size-4" }),
5744
+ /* @__PURE__ */ jsx26(HistoryIcon, { className: "size-4" }),
5770
5745
  "Password history"
5771
5746
  ] }),
5772
5747
  /* @__PURE__ */ jsxs24(DropdownMenuItem3, { onSelect: () => onPanel("activity"), children: [
@@ -5774,7 +5749,7 @@ function ItemPane(props) {
5774
5749
  "Activity"
5775
5750
  ] }),
5776
5751
  canEdit ? /* @__PURE__ */ jsxs24(DropdownMenuItem3, { onSelect: () => onPanel("settings"), children: [
5777
- /* @__PURE__ */ jsx26(SettingsGlyph, { className: "size-4" }),
5752
+ /* @__PURE__ */ jsx26(SettingsIcon, { className: "size-4" }),
5778
5753
  "Settings"
5779
5754
  ] }) : null,
5780
5755
  canManage ? /* @__PURE__ */ jsxs24(Fragment15, { children: [
@@ -5794,8 +5769,8 @@ function ItemPane(props) {
5794
5769
  error ? /* @__PURE__ */ jsx26("div", { role: "alert", className: "border-b border-border bg-muted px-5 py-2 text-sm text-destructive", children: error }) : null,
5795
5770
  notice && !editing ? /* @__PURE__ */ jsx26("div", { role: "status", className: "border-b border-border bg-muted px-5 py-2 text-sm text-warning", children: notice }) : null,
5796
5771
  /* @__PURE__ */ jsx26("div", { className: "min-h-0 flex-1 overflow-y-auto", children: /* @__PURE__ */ jsx26("div", { className: "mx-auto flex w-full max-w-3xl flex-col gap-5 px-3 py-4 sm:px-6 sm:py-6", children: editing ? /* @__PURE__ */ jsxs24(Fragment15, { children: [
5797
- /* @__PURE__ */ jsxs24(Section, { children: [
5798
- mode === "new" ? /* @__PURE__ */ jsx26(Row, { label: "Save to", children: /* @__PURE__ */ jsx26(
5772
+ /* @__PURE__ */ jsxs24(VaultSection, { children: [
5773
+ mode === "new" ? /* @__PURE__ */ jsx26(VaultRow, { label: "Save to", children: /* @__PURE__ */ jsx26(
5799
5774
  OptionCombobox,
5800
5775
  {
5801
5776
  value: owner,
@@ -5816,7 +5791,7 @@ function ItemPane(props) {
5816
5791
  /* @__PURE__ */ jsx26(EditRow, { label: "Name", value: draft.name, onChange: (v) => patch({ name: v }), placeholder: "Name", autoFocus: mode === "new" }),
5817
5792
  mode === "new" && owner === "person" ? /* @__PURE__ */ jsxs24(Fragment15, { children: [
5818
5793
  /* @__PURE__ */ jsx26(EditRow, { label: "Their email", value: recipient, placeholder: "name@company.com", inputMode: "email", onChange: setRecipient }),
5819
- declared.some((f) => f.storage === "encrypted" && f.kind === "secret") ? /* @__PURE__ */ jsx26(Row, { label: "Password", hint: "You never see it", children: /* @__PURE__ */ jsx26(Switch5, { checked: generatePrivately, onCheckedChange: setGeneratePrivately, "aria-label": "Generate the password privately" }) }) : null
5794
+ declared.some((f) => f.storage === "encrypted" && f.kind === "secret") ? /* @__PURE__ */ jsx26(VaultRow, { label: "Password", hint: "You never see it", children: /* @__PURE__ */ jsx26(Switch5, { checked: generatePrivately, onCheckedChange: setGeneratePrivately, "aria-label": "Generate the password privately" }) }) : null
5820
5795
  ] }) : null,
5821
5796
  declared.map((f) => {
5822
5797
  const existing = item?.fields.find((x) => x.key === f.key);
@@ -5836,7 +5811,7 @@ function ItemPane(props) {
5836
5811
  actions: /* @__PURE__ */ jsxs24(Fragment15, { children: [
5837
5812
  hidden && existing?.handling === "revealable" && item?.capabilities.canReveal ? /* @__PURE__ */ jsx26(Button21, { variant: "quiet", icon: /* @__PURE__ */ jsx26(EyeGlyph, {}), "aria-label": `Show current ${f.label}`, onClick: () => void loadForEdit(f.key) }) : null,
5838
5813
  secretKind ? /* @__PURE__ */ jsx26(GenerateButton, { onUse: (v) => setValue(f.key, v) }) : null,
5839
- existing ? /* @__PURE__ */ jsx26(Button21, { variant: "quiet", icon: /* @__PURE__ */ jsx26(SettingsGlyph, {}), "aria-label": `${f.label} settings`, onClick: () => onPanel(`field:${existing.id}`) }) : null
5814
+ existing ? /* @__PURE__ */ jsx26(Button21, { variant: "quiet", icon: /* @__PURE__ */ jsx26(SettingsIcon, {}), "aria-label": `${f.label} settings`, onClick: () => onPanel(`field:${existing.id}`) }) : null
5840
5815
  ] })
5841
5816
  },
5842
5817
  f.key
@@ -5854,7 +5829,7 @@ function ItemPane(props) {
5854
5829
  removeLabel: `Delete ${f.label}`,
5855
5830
  actions: /* @__PURE__ */ jsxs24(Fragment15, { children: [
5856
5831
  f.handling === "revealable" && !(f.key in loaded) && item?.capabilities.canReveal ? /* @__PURE__ */ jsx26(Button21, { variant: "quiet", icon: /* @__PURE__ */ jsx26(EyeGlyph, {}), "aria-label": `Show current ${f.label}`, onClick: () => void loadForEdit(f.key) }) : null,
5857
- /* @__PURE__ */ jsx26(Button21, { variant: "quiet", icon: /* @__PURE__ */ jsx26(SettingsGlyph, {}), "aria-label": `${f.label} settings`, onClick: () => onPanel(`field:${f.id}`) })
5832
+ /* @__PURE__ */ jsx26(Button21, { variant: "quiet", icon: /* @__PURE__ */ jsx26(SettingsIcon, {}), "aria-label": `${f.label} settings`, onClick: () => onPanel(`field:${f.id}`) })
5858
5833
  ] })
5859
5834
  },
5860
5835
  f.id
@@ -5887,9 +5862,9 @@ function ItemPane(props) {
5887
5862
  /* @__PURE__ */ jsx26(TotpEditRow, { value: draft.authenticator, onChange: (v) => patch({ authenticator: v }), hasExisting: Boolean(item?.authenticator), item, port, onEnrolled: onChanged }),
5888
5863
  item && isLogin && !item.authenticator ? /* @__PURE__ */ jsx26(TwoFactorMethodRow, { port, item, onChanged }) : null
5889
5864
  ] }),
5890
- /* @__PURE__ */ jsx26(Section, { children: /* @__PURE__ */ jsx26(EditRow, { label: "Notes", value: draft.notes, multiline: true, placeholder: "Anything worth remembering", onChange: (v) => patch({ notes: v }) }) }),
5865
+ /* @__PURE__ */ jsx26(VaultSection, { children: /* @__PURE__ */ jsx26(EditRow, { label: "Notes", value: draft.notes, multiline: true, placeholder: "Anything worth remembering", onChange: (v) => patch({ notes: v }) }) }),
5891
5866
  /* @__PURE__ */ jsxs24(
5892
- Section,
5867
+ VaultSection,
5893
5868
  {
5894
5869
  title: "More",
5895
5870
  actions: /* @__PURE__ */ jsxs24(DropdownMenu3, { children: [
@@ -5923,7 +5898,7 @@ function ItemPane(props) {
5923
5898
  ),
5924
5899
  filesProps ? /* @__PURE__ */ jsx26(FilesSection, { ...filesProps, editing: true }) : null
5925
5900
  ] }) : item ? /* @__PURE__ */ jsxs24(Fragment15, { children: [
5926
- /* @__PURE__ */ jsxs24(Section, { children: [
5901
+ /* @__PURE__ */ jsxs24(VaultSection, { children: [
5927
5902
  declared.map((f) => {
5928
5903
  if (f.storage === "metadata") {
5929
5904
  const v = metaValue(f.key);
@@ -5938,10 +5913,10 @@ function ItemPane(props) {
5938
5913
  item.authenticator ? /* @__PURE__ */ jsx26(TotpRow, { port, item, onChanged }) : /* @__PURE__ */ jsx26(AddRow, { label: "One-time password", onAdd: canEdit ? () => onMode("edit") : null, children: "Set up" }),
5939
5914
  !item.authenticator && item.custom.some((c) => c.key === MFA_METHOD_KEY && c.value) ? /* @__PURE__ */ jsx26(TwoFactorMethodRow, { port, item, onChanged }) : null
5940
5915
  ] }),
5941
- /* @__PURE__ */ jsx26(Section, { children: item.notes ? /* @__PURE__ */ jsx26(PlainRow, { label: "Notes", value: item.notes, multiline: true }) : /* @__PURE__ */ jsx26(AddRow, { label: "Notes", onAdd: canEdit ? () => onMode("edit") : null, children: "Add notes" }) }),
5942
- item.description || item.tags.length > 0 || viewCustom.length > 0 ? /* @__PURE__ */ jsxs24(Section, { title: "More", children: [
5916
+ /* @__PURE__ */ jsx26(VaultSection, { children: item.notes ? /* @__PURE__ */ jsx26(PlainRow, { label: "Notes", value: item.notes, multiline: true }) : /* @__PURE__ */ jsx26(AddRow, { label: "Notes", onAdd: canEdit ? () => onMode("edit") : null, children: "Add notes" }) }),
5917
+ item.description || item.tags.length > 0 || viewCustom.length > 0 ? /* @__PURE__ */ jsxs24(VaultSection, { title: "More", children: [
5943
5918
  item.description ? /* @__PURE__ */ jsx26(PlainRow, { label: "Description", value: item.description }) : null,
5944
- item.tags.length > 0 ? /* @__PURE__ */ jsx26(Row, { label: "Tags", children: /* @__PURE__ */ jsx26("div", { className: "flex flex-wrap gap-1", children: item.tags.map((t) => /* @__PURE__ */ jsx26("span", { className: "rounded-md bg-muted px-1.5 py-0.5 text-xs", children: t }, t)) }) }) : null,
5919
+ item.tags.length > 0 ? /* @__PURE__ */ jsx26(VaultRow, { label: "Tags", children: /* @__PURE__ */ jsx26("div", { className: "flex flex-wrap gap-1", children: item.tags.map((t) => /* @__PURE__ */ jsx26("span", { className: "rounded-md bg-muted px-1.5 py-0.5 text-xs", children: t }, t)) }) }) : null,
5945
5920
  viewCustom.map((c) => /* @__PURE__ */ jsx26(PlainRow, { label: c.label, value: c.value, openUrl: host.openUrl }, c.key))
5946
5921
  ] }) : null,
5947
5922
  filesProps ? /* @__PURE__ */ jsx26(FilesSection, { ...filesProps, editing: false }) : null,
@@ -6189,13 +6164,13 @@ function RestorePanel({ lists, item, restore, onClose }) {
6189
6164
  refused ? null : /* @__PURE__ */ jsx28(Button23, { variant: "primary", icon: /* @__PURE__ */ jsx28(RestoreGlyph, {}), disabled: busy || loading || lists.preview !== void 0 && preview === null, onClick: () => void run(), children: busy ? "Restoring\u2026" : "Restore" })
6190
6165
  ] }),
6191
6166
  children: [
6192
- loading ? /* @__PURE__ */ jsx28(Section, { children: /* @__PURE__ */ jsx28(Empty, { children: "Checking what comes back\u2026" }) }) : preview?.supported ? /* @__PURE__ */ jsxs26(Section, { title: "Comes back", children: [
6193
- /* @__PURE__ */ jsx28(Row, { label: "Fields", children: /* @__PURE__ */ jsx28("span", { className: "text-foreground", children: count(preview.fields, "field") }) }),
6194
- /* @__PURE__ */ jsx28(Row, { label: "Files", children: /* @__PURE__ */ jsx28("span", { className: "text-foreground", children: count(preview.attachments, "file") }) }),
6195
- preview.passkeys === 1 ? /* @__PURE__ */ jsx28(Row, { label: "Passkey", hint: "Not turned on; the site may not accept it", children: /* @__PURE__ */ jsx28("span", { className: "text-foreground", children: "1 passkey" }) }) : null,
6196
- /* @__PURE__ */ jsx28(Row, { label: "Stays off", hint: "Turn each back on yourself", children: /* @__PURE__ */ jsx28("span", { className: "text-muted-foreground", children: "Sharing, browser fill, codes, sandboxes, agents" }) }),
6197
- preview.priorWasDisabled ? /* @__PURE__ */ jsx28(Row, { label: "Before", children: /* @__PURE__ */ jsx28("span", { className: "text-muted-foreground", children: "It was already off before it was deleted." }) }) : null
6198
- ] }) : preview ? /* @__PURE__ */ jsx28(Section, { children: /* @__PURE__ */ jsx28(Empty, { children: refusalText(preview.reason) }) }) : /* @__PURE__ */ jsx28(Section, { children: /* @__PURE__ */ jsx28(Empty, { children: "It comes back turned off: sharing, browser fill, codes and sandbox use stay off." }) }),
6167
+ loading ? /* @__PURE__ */ jsx28(VaultSection, { children: /* @__PURE__ */ jsx28(Empty, { children: "Checking what comes back\u2026" }) }) : preview?.supported ? /* @__PURE__ */ jsxs26(VaultSection, { title: "Comes back", children: [
6168
+ /* @__PURE__ */ jsx28(VaultRow, { label: "Fields", children: /* @__PURE__ */ jsx28("span", { className: "text-foreground", children: count(preview.fields, "field") }) }),
6169
+ /* @__PURE__ */ jsx28(VaultRow, { label: "Files", children: /* @__PURE__ */ jsx28("span", { className: "text-foreground", children: count(preview.attachments, "file") }) }),
6170
+ preview.passkeys === 1 ? /* @__PURE__ */ jsx28(VaultRow, { label: "Passkey", hint: "Not turned on; the site may not accept it", children: /* @__PURE__ */ jsx28("span", { className: "text-foreground", children: "1 passkey" }) }) : null,
6171
+ /* @__PURE__ */ jsx28(VaultRow, { label: "Stays off", hint: "Turn each back on yourself", children: /* @__PURE__ */ jsx28("span", { className: "text-muted-foreground", children: "Sharing, browser fill, codes, sandboxes, agents" }) }),
6172
+ preview.priorWasDisabled ? /* @__PURE__ */ jsx28(VaultRow, { label: "Before", children: /* @__PURE__ */ jsx28("span", { className: "text-muted-foreground", children: "It was already off before it was deleted." }) }) : null
6173
+ ] }) : preview ? /* @__PURE__ */ jsx28(VaultSection, { children: /* @__PURE__ */ jsx28(Empty, { children: refusalText(preview.reason) }) }) : /* @__PURE__ */ jsx28(VaultSection, { children: /* @__PURE__ */ jsx28(Empty, { children: "It comes back turned off: sharing, browser fill, codes and sandbox use stay off." }) }),
6199
6174
  error ? /* @__PURE__ */ jsx28("p", { role: "alert", className: "px-1 text-sm text-destructive", children: error }) : null
6200
6175
  ]
6201
6176
  }
@@ -6227,7 +6202,7 @@ function TrashView({ port, deleted, query, header, onChanged }) {
6227
6202
  };
6228
6203
  return /* @__PURE__ */ jsxs27("div", { className: "flex min-h-0 flex-1 flex-col gap-3 overflow-y-auto p-3", children: [
6229
6204
  header,
6230
- /* @__PURE__ */ jsx29(Section, { title: "Trash", children: shown.length === 0 ? /* @__PURE__ */ jsx29(Empty, { children: deleted.length === 0 ? "The trash is empty." : "Nothing matches." }) : shown.map((item) => (
6205
+ /* @__PURE__ */ jsx29(VaultSection, { title: "Trash", children: shown.length === 0 ? /* @__PURE__ */ jsx29(Empty, { children: deleted.length === 0 ? "The trash is empty." : "Nothing matches." }) : shown.map((item) => (
6231
6206
  // A list row, not a field row: the name gets the whole width (on a phone a label column
6232
6207
  // left "Vau…" for every row), the deletion date sits under it.
6233
6208
  /* @__PURE__ */ jsxs27("div", { className: "flex min-h-12 items-center gap-3 px-3 py-1.5 sm:px-4", children: [
@@ -6247,6 +6222,7 @@ function TrashView({ port, deleted, query, header, onChanged }) {
6247
6222
  import { useMemo as useMemo4, useState as useState30 } from "react";
6248
6223
  import { cn as cn14 } from "@ai-matrx/design-system";
6249
6224
  import { Button as Button25, Field as Field10, SearchField as SearchField2 } from "@ai-matrx/design-system/controls";
6225
+ import { GlobeIcon as GlobeIcon3 } from "@ai-matrx/design-system/icons";
6250
6226
  import { jsx as jsx30, jsxs as jsxs28 } from "react/jsx-runtime";
6251
6227
  function NewItemFlow({ definitions, url, onUrl, onChoose, onCancel }) {
6252
6228
  const [search, setSearch] = useState30("");
@@ -6281,7 +6257,7 @@ function NewItemFlow({ definitions, url, onUrl, onChoose, onCancel }) {
6281
6257
  "aria-label": "Website address",
6282
6258
  inputMode: "url",
6283
6259
  autoFocus: true,
6284
- icon: /* @__PURE__ */ jsx30(GlobeGlyph, {})
6260
+ icon: /* @__PURE__ */ jsx30(GlobeIcon3, {})
6285
6261
  }
6286
6262
  ),
6287
6263
  guess && login ? /* @__PURE__ */ jsxs28("div", { className: "flex flex-col gap-2 rounded-xl border border-border bg-card p-3", children: [
@@ -6531,9 +6507,9 @@ function SecureLinkPanel({ item, port, onClose }) {
6531
6507
  ] }),
6532
6508
  children: [
6533
6509
  remedy ? /* @__PURE__ */ jsx31("p", { className: "px-1 text-xs text-muted-foreground", children: remedy }) : null,
6534
- /* @__PURE__ */ jsxs29(Section, { title: "Recipient", children: [
6535
- /* @__PURE__ */ jsx31(Row, { label: "Email", children: /* @__PURE__ */ jsx31(Field11, { type: "email", autoComplete: "off", placeholder: "name@example.com", "aria-label": "Their email", value: email, onChange: (e) => setEmail(e.target.value), className: "w-full" }) }),
6536
- /* @__PURE__ */ jsx31(Row, { label: "Mobile", hint: "For the code", children: /* @__PURE__ */ jsx31(
6510
+ /* @__PURE__ */ jsxs29(VaultSection, { title: "Recipient", children: [
6511
+ /* @__PURE__ */ jsx31(VaultRow, { label: "Email", children: /* @__PURE__ */ jsx31(Field11, { type: "email", autoComplete: "off", placeholder: "name@example.com", "aria-label": "Their email", value: email, onChange: (e) => setEmail(e.target.value), className: "w-full" }) }),
6512
+ /* @__PURE__ */ jsx31(VaultRow, { label: "Mobile", hint: "For the code", children: /* @__PURE__ */ jsx31(
6537
6513
  Field11,
6538
6514
  {
6539
6515
  type: "tel",
@@ -6549,8 +6525,8 @@ function SecureLinkPanel({ item, port, onClose }) {
6549
6525
  className: "w-full"
6550
6526
  }
6551
6527
  ) }),
6552
- /* @__PURE__ */ jsx31(Row, { label: "Name", hint: "Optional", children: /* @__PURE__ */ jsx31(Field11, { autoComplete: "off", placeholder: "Their name", "aria-label": "Their name", value: name, onChange: (e) => setName(e.target.value), className: "w-full" }) }),
6553
- plan && !plan.same ? /* @__PURE__ */ jsx31(Row, { label: "Link by", children: /* @__PURE__ */ jsx31(
6528
+ /* @__PURE__ */ jsx31(VaultRow, { label: "Name", hint: "Optional", children: /* @__PURE__ */ jsx31(Field11, { autoComplete: "off", placeholder: "Their name", "aria-label": "Their name", value: name, onChange: (e) => setName(e.target.value), className: "w-full" }) }),
6529
+ plan && !plan.same ? /* @__PURE__ */ jsx31(VaultRow, { label: "Link by", children: /* @__PURE__ */ jsx31(
6554
6530
  SegmentedControl5,
6555
6531
  {
6556
6532
  "aria-label": "Send the link by",
@@ -6562,26 +6538,26 @@ function SecureLinkPanel({ item, port, onClose }) {
6562
6538
  ]
6563
6539
  }
6564
6540
  ) }) : null,
6565
- email.trim() ? /* @__PURE__ */ jsx31(Row, { label: "Delivery", children: /* @__PURE__ */ jsx31("span", { className: plan?.same ? "text-warning" : "text-foreground", children: planWords(plan) }) }) : null
6541
+ email.trim() ? /* @__PURE__ */ jsx31(VaultRow, { label: "Delivery", children: /* @__PURE__ */ jsx31("span", { className: plan?.same ? "text-warning" : "text-foreground", children: planWords(plan) }) }) : null
6566
6542
  ] }),
6567
- /* @__PURE__ */ jsx31(Section, { title: "Include", children: optionsError ? /* @__PURE__ */ jsx31(Empty, { children: /* @__PURE__ */ jsx31("span", { className: "text-destructive", children: optionsError }) }) : !options ? /* @__PURE__ */ jsx31(RegionSkeleton2, { shape: "rows", count: 2, "aria-label": "Loading what can be sent", className: "px-3 sm:px-4" }) : options.fields.length === 0 ? /* @__PURE__ */ jsx31(Empty, { children: "Name and details only" }) : options.fields.map((f) => /* @__PURE__ */ jsxs29("label", { className: "flex min-h-11 items-center gap-3 px-3 py-1 sm:px-4", "data-clickable": f.available ? "" : void 0, children: [
6543
+ /* @__PURE__ */ jsx31(VaultSection, { title: "Include", children: optionsError ? /* @__PURE__ */ jsx31(Empty, { children: /* @__PURE__ */ jsx31("span", { className: "text-destructive", children: optionsError }) }) : !options ? /* @__PURE__ */ jsx31(RegionSkeleton2, { shape: "rows", count: 2, "aria-label": "Loading what can be sent", className: "px-3 sm:px-4" }) : options.fields.length === 0 ? /* @__PURE__ */ jsx31(Empty, { children: "Name and details only" }) : options.fields.map((f) => /* @__PURE__ */ jsxs29("label", { className: "flex min-h-11 items-center gap-3 px-3 py-1 sm:px-4", "data-clickable": f.available ? "" : void 0, children: [
6568
6544
  /* @__PURE__ */ jsx31(Checkbox2, { checked: fields.includes(f.key), disabled: !f.available, onCheckedChange: (v) => toggle2(f.key, v === true), "aria-label": f.label }),
6569
6545
  /* @__PURE__ */ jsx31("span", { className: "min-w-0 flex-1 truncate text-sm text-foreground", children: f.label }),
6570
6546
  !f.available && f.reason ? /* @__PURE__ */ jsx31("span", { className: "min-w-0 max-w-[55%] truncate text-xs text-muted-foreground", title: f.reason, children: f.reason }) : null
6571
6547
  ] }, f.key)) }),
6572
- /* @__PURE__ */ jsx31(Section, { title: "Message", children: /* @__PURE__ */ jsx31("div", { className: "px-3 py-1 sm:px-4", children: /* @__PURE__ */ jsx31(Textarea4, { className: "w-full", rows: 2, maxLength: NOTE_MAX, placeholder: "Shown once, with it", "aria-label": "Message", value: note, onChange: (e) => setNote(e.target.value) }) }) }),
6573
- options ? /* @__PURE__ */ jsxs29(Section, { title: "Link", children: [
6574
- /* @__PURE__ */ jsx31(Row, { label: "Opens", children: /* @__PURE__ */ jsx31("span", { className: "text-foreground", children: "Once" }) }),
6575
- /* @__PURE__ */ jsx31(Row, { label: "Link expires", children: /* @__PURE__ */ jsxs29("span", { className: "text-foreground", children: [
6548
+ /* @__PURE__ */ jsx31(VaultSection, { title: "Message", children: /* @__PURE__ */ jsx31("div", { className: "px-3 py-1 sm:px-4", children: /* @__PURE__ */ jsx31(Textarea4, { className: "w-full", rows: 2, maxLength: NOTE_MAX, placeholder: "Shown once, with it", "aria-label": "Message", value: note, onChange: (e) => setNote(e.target.value) }) }) }),
6549
+ options ? /* @__PURE__ */ jsxs29(VaultSection, { title: "Link", children: [
6550
+ /* @__PURE__ */ jsx31(VaultRow, { label: "Opens", children: /* @__PURE__ */ jsx31("span", { className: "text-foreground", children: "Once" }) }),
6551
+ /* @__PURE__ */ jsx31(VaultRow, { label: "Link expires", children: /* @__PURE__ */ jsxs29("span", { className: "text-foreground", children: [
6576
6552
  "After ",
6577
6553
  lifetimeWords(options.linkMinutes)
6578
6554
  ] }) }),
6579
- /* @__PURE__ */ jsx31(Row, { label: "Code expires", children: /* @__PURE__ */ jsxs29("span", { className: "text-foreground", children: [
6555
+ /* @__PURE__ */ jsx31(VaultRow, { label: "Code expires", children: /* @__PURE__ */ jsxs29("span", { className: "text-foreground", children: [
6580
6556
  "After ",
6581
6557
  lifetimeWords(options.codeMinutes)
6582
6558
  ] }) })
6583
6559
  ] }) : null,
6584
- sharing.sentSecureLinks ? /* @__PURE__ */ jsx31(Section, { title: "Sent links", children: sentError ? /* @__PURE__ */ jsx31(Empty, { children: /* @__PURE__ */ jsx31("span", { className: "text-destructive", children: sentError }) }) : !sent ? /* @__PURE__ */ jsx31(RegionSkeleton2, { shape: "rows", count: 2, "aria-label": "Loading sent links", className: "px-3 sm:px-4" }) : sent.length === 0 ? /* @__PURE__ */ jsx31(Empty, { children: "None yet" }) : sent.map((row) => /* @__PURE__ */ jsxs29(AccessLine, { glyph: row.status === "pending" ? ClockGlyph : row.fieldKeys.length ? LockGlyph : ShareGlyph, who: recipientOf(row), meta: sentMeta(row, options), children: [
6560
+ sharing.sentSecureLinks ? /* @__PURE__ */ jsx31(VaultSection, { title: "Sent links", children: sentError ? /* @__PURE__ */ jsx31(Empty, { children: /* @__PURE__ */ jsx31("span", { className: "text-destructive", children: sentError }) }) : !sent ? /* @__PURE__ */ jsx31(RegionSkeleton2, { shape: "rows", count: 2, "aria-label": "Loading sent links", className: "px-3 sm:px-4" }) : sent.length === 0 ? /* @__PURE__ */ jsx31(Empty, { children: "None yet" }) : sent.map((row) => /* @__PURE__ */ jsxs29(AccessLine, { glyph: row.status === "pending" ? ClockGlyph : row.fieldKeys.length ? LockGlyph : ShareGlyph, who: recipientOf(row), meta: sentMeta(row, options), children: [
6585
6561
  /* @__PURE__ */ jsx31(Badge8, { tone: STATUS_TONE[row.status] ?? "neutral", children: statusWord(row.status) }),
6586
6562
  row.status === "pending" ? /* @__PURE__ */ jsx31(Button26, { variant: "quiet", disabled: busy !== null, onClick: () => void turnOff(row), children: "Turn off" }) : null
6587
6563
  ] }, row.id)) }) : null
@@ -6723,10 +6699,10 @@ function DevicesPanel({ port, onClose }) {
6723
6699
  };
6724
6700
  return /* @__PURE__ */ jsxs30(Panel, { title: "Browsers that can fill", onClose, size: "md", children: [
6725
6701
  /* @__PURE__ */ jsx32(ErrorLine2, { text: error }),
6726
- /* @__PURE__ */ jsx32(Section, { children: devices === null ? error ? /* @__PURE__ */ jsx32(Empty, { children: /* @__PURE__ */ jsx32(Button27, { variant: "outline", onClick: () => void load(), children: "Try again" }) }) : /* @__PURE__ */ jsx32(RegionSkeleton3, { shape: "rows", count: 2, "aria-label": "Loading your browsers", className: "px-3 sm:px-4" }) : devices.length === 0 ? /* @__PURE__ */ jsx32(Empty, { children: "No browser can fill yet. Turn it on in the extension." }) : devices.map((device) => {
6702
+ /* @__PURE__ */ jsx32(VaultSection, { children: devices === null ? error ? /* @__PURE__ */ jsx32(Empty, { children: /* @__PURE__ */ jsx32(Button27, { variant: "outline", onClick: () => void load(), children: "Try again" }) }) : /* @__PURE__ */ jsx32(RegionSkeleton3, { shape: "rows", count: 2, "aria-label": "Loading your browsers", className: "px-3 sm:px-4" }) : devices.length === 0 ? /* @__PURE__ */ jsx32(Empty, { children: "No browser can fill yet. Turn it on in the extension." }) : devices.map((device) => {
6727
6703
  const off = isRevoked(device);
6728
6704
  return /* @__PURE__ */ jsx32(
6729
- Row,
6705
+ VaultRow,
6730
6706
  {
6731
6707
  label: off ? "Turned off" : "Can fill",
6732
6708
  hint: off ? formatAbsoluteDate6(device.revokedAt, DAY_FORMAT, "") : void 0,
@@ -6814,18 +6790,18 @@ function ApprovePanel({ port, host, onClose, approvalKey, label, kind = "browser
6814
6790
  /* @__PURE__ */ jsx32(Button27, { variant: "quiet", disabled: busy !== null, onClick: refuse, children: key ? "Refuse" : "Close" }),
6815
6791
  canApprove ? /* @__PURE__ */ jsx32(Button27, { variant: "primary", icon: /* @__PURE__ */ jsx32(FingerprintGlyph, {}), disabled: busy !== null, onClick: () => void approve(), children: busy === "approve" ? "Approving\u2026" : "Approve with passkey" }) : null
6816
6792
  ] });
6817
- return /* @__PURE__ */ jsx32(Panel, { title, onClose: refuse, size: "sm", footer, children: !key ? /* @__PURE__ */ jsx32(Section, { children: /* @__PURE__ */ jsxs30(Empty, { children: [
6793
+ return /* @__PURE__ */ jsx32(Panel, { title, onClose: refuse, size: "sm", footer, children: !key ? /* @__PURE__ */ jsx32(VaultSection, { children: /* @__PURE__ */ jsxs30(Empty, { children: [
6818
6794
  "This link names no key. Start again from ",
6819
6795
  where,
6820
6796
  "."
6821
6797
  ] }) }) : /* @__PURE__ */ jsxs30(Fragment17, { children: [
6822
- /* @__PURE__ */ jsxs30(Section, { title: "What is asking", children: [
6823
- /* @__PURE__ */ jsx32(Row, { label: "Asking", hint: "Approve only if you just asked", children: asker }),
6824
- name ? /* @__PURE__ */ jsx32(Row, { label: "Name", children: /* @__PURE__ */ jsx32("span", { className: "block truncate", children: name }) }) : null,
6825
- /* @__PURE__ */ jsx32(Row, { label: "Code", hint: `Must match ${where}`, children: /* @__PURE__ */ jsx32("span", { className: "font-mono tracking-wider text-foreground", children: shortFingerprint(key) }) })
6798
+ /* @__PURE__ */ jsxs30(VaultSection, { title: "What is asking", children: [
6799
+ /* @__PURE__ */ jsx32(VaultRow, { label: "Asking", hint: "Approve only if you just asked", children: asker }),
6800
+ name ? /* @__PURE__ */ jsx32(VaultRow, { label: "Name", children: /* @__PURE__ */ jsx32("span", { className: "block truncate", children: name }) }) : null,
6801
+ /* @__PURE__ */ jsx32(VaultRow, { label: "Code", hint: `Must match ${where}`, children: /* @__PURE__ */ jsx32("span", { className: "font-mono tracking-wider text-foreground", children: shortFingerprint(key) }) })
6826
6802
  ] }),
6827
6803
  /* @__PURE__ */ jsx32(ErrorLine2, { text: error }),
6828
- /* @__PURE__ */ jsx32(Section, { title: "Confirm it\u2019s you", children: approvedUntil ? /* @__PURE__ */ jsx32(Row, { label: "Approved", actions: /* @__PURE__ */ jsx32(CheckGlyph, { className: "size-4 text-primary" }), children: /* @__PURE__ */ jsxs30("span", { className: "text-foreground", children: [
6804
+ /* @__PURE__ */ jsx32(VaultSection, { title: "Confirm it\u2019s you", children: approvedUntil ? /* @__PURE__ */ jsx32(VaultRow, { label: "Approved", actions: /* @__PURE__ */ jsx32(CheckGlyph, { className: "size-4 text-primary" }), children: /* @__PURE__ */ jsxs30("span", { className: "text-foreground", children: [
6829
6805
  "Return to ",
6830
6806
  where,
6831
6807
  " by ",
@@ -6836,7 +6812,7 @@ function ApprovePanel({ port, host, onClose, approvalKey, label, kind = "browser
6836
6812
  where,
6837
6813
  "."
6838
6814
  ] }) : !here ? /* @__PURE__ */ jsx32(
6839
- Row,
6815
+ VaultRow,
6840
6816
  {
6841
6817
  label: "Passkey",
6842
6818
  hint: `Passkeys work only on ${passkeys.rpId}`,
@@ -6844,14 +6820,14 @@ function ApprovePanel({ port, host, onClose, approvalKey, label, kind = "browser
6844
6820
  children: /* @__PURE__ */ jsx32("span", { className: "text-muted-foreground", children: "Not on this page" })
6845
6821
  }
6846
6822
  ) : methods === null ? error ? /* @__PURE__ */ jsx32(Empty, { children: /* @__PURE__ */ jsx32(Button27, { variant: "outline", onClick: () => void load(), children: "Try again" }) }) : /* @__PURE__ */ jsx32(RegionSkeleton3, { shape: "rows", count: 1, "aria-label": "Checking your account", className: "px-3 sm:px-4" }) : !methods.passkey ? /* @__PURE__ */ jsx32(
6847
- Row,
6823
+ VaultRow,
6848
6824
  {
6849
6825
  label: "Passkey",
6850
6826
  hint: methods.password ? `Or type your password in ${where}` : "Add one to approve",
6851
6827
  actions: /* @__PURE__ */ jsx32(Button27, { variant: "primary", icon: /* @__PURE__ */ jsx32(FingerprintGlyph, {}), disabled: busy !== null, onClick: () => void addPasskey(), children: busy === "add" ? "Adding\u2026" : "Add passkey" }),
6852
6828
  children: /* @__PURE__ */ jsx32("span", { className: "text-muted-foreground", children: methods.password ? "None yet" : "No password or passkey" })
6853
6829
  }
6854
- ) : /* @__PURE__ */ jsx32(Row, { label: "Passkey", hint: "Your device asks for it next", children: /* @__PURE__ */ jsx32("span", { className: "text-foreground", children: "Ready" }) }) })
6830
+ ) : /* @__PURE__ */ jsx32(VaultRow, { label: "Passkey", hint: "Your device asks for it next", children: /* @__PURE__ */ jsx32("span", { className: "text-foreground", children: "Ready" }) }) })
6855
6831
  ] }) });
6856
6832
  }
6857
6833
 
@@ -7129,7 +7105,7 @@ var TONE = {
7129
7105
  };
7130
7106
  function NativeImportPanel({ bridge, readLimits, activeOrganizationId, organizations, onClose, onChanged }) {
7131
7107
  if (!bridge) {
7132
- return /* @__PURE__ */ jsx33(Panel, { title: "Import passkeys", size: "md", onClose, footer: /* @__PURE__ */ jsx33(Button28, { variant: "primary", onClick: onClose, children: "Close" }), children: /* @__PURE__ */ jsx33(Section, { children: /* @__PURE__ */ jsx33(Empty, { children: "Passkey import needs the desktop app." }) }) });
7108
+ return /* @__PURE__ */ jsx33(Panel, { title: "Import passkeys", size: "md", onClose, footer: /* @__PURE__ */ jsx33(Button28, { variant: "primary", onClick: onClose, children: "Close" }), children: /* @__PURE__ */ jsx33(VaultSection, { children: /* @__PURE__ */ jsx33(Empty, { children: "Passkey import needs the desktop app." }) }) });
7133
7109
  }
7134
7110
  return /* @__PURE__ */ jsx33(Importer, { bridge, readLimits, activeOrganizationId, organizations, onClose, onChanged });
7135
7111
  }
@@ -7176,25 +7152,25 @@ function Importer({ bridge, readLimits, activeOrganizationId, organizations, onC
7176
7152
  /* @__PURE__ */ jsx33(Button28, { variant: "primary", onClick: onClose, children: "Done" })
7177
7153
  ] }) : /* @__PURE__ */ jsx33(Button28, { variant: "quiet", onClick: onClose, children: "Close" });
7178
7154
  return /* @__PURE__ */ jsxs31(Panel, { title: "Import passkeys", size: "lg", onClose, footer, children: [
7179
- screen.kind === "idle" ? /* @__PURE__ */ jsxs31(Section, { children: [
7180
- /* @__PURE__ */ jsx33(Row, { label: "Save to", children: /* @__PURE__ */ jsx33(Select9, { value: organizationId, options, "aria-label": "Save to", disabled: busy, onValueChange: setOrganizationId }) }),
7181
- /* @__PURE__ */ jsx33(Row, { label: "File", hint: limits ? `Up to ${plural2(limits.maxItems, "passkey")}` : "A passkey exchange file", children: /* @__PURE__ */ jsx33(Button28, { variant: "outline", icon: /* @__PURE__ */ jsx33(ImportGlyph, { className: "size-4" }), disabled: busy || !organizationId || limitError !== null, onClick: () => void flow.begin(organizationId), children: busy ? "Opening\u2026" : "Choose file" }) }),
7182
- /* @__PURE__ */ jsx33(Row, { label: "Interrupted", hint: "Finish or clear an earlier import", children: /* @__PURE__ */ jsx33(Button28, { variant: "quiet", disabled: busy, onClick: () => void flow.recover(), children: "Recover" }) })
7155
+ screen.kind === "idle" ? /* @__PURE__ */ jsxs31(VaultSection, { children: [
7156
+ /* @__PURE__ */ jsx33(VaultRow, { label: "Save to", children: /* @__PURE__ */ jsx33(Select9, { value: organizationId, options, "aria-label": "Save to", disabled: busy, onValueChange: setOrganizationId }) }),
7157
+ /* @__PURE__ */ jsx33(VaultRow, { label: "File", hint: limits ? `Up to ${plural2(limits.maxItems, "passkey")}` : "A passkey exchange file", children: /* @__PURE__ */ jsx33(Button28, { variant: "outline", icon: /* @__PURE__ */ jsx33(ImportGlyph, { className: "size-4" }), disabled: busy || !organizationId || limitError !== null, onClick: () => void flow.begin(organizationId), children: busy ? "Opening\u2026" : "Choose file" }) }),
7158
+ /* @__PURE__ */ jsx33(VaultRow, { label: "Interrupted", hint: "Finish or clear an earlier import", children: /* @__PURE__ */ jsx33(Button28, { variant: "quiet", disabled: busy, onClick: () => void flow.recover(), children: "Recover" }) })
7183
7159
  ] }) : null,
7184
- preview ? /* @__PURE__ */ jsx33(Section, { title: `${ready} of ${preview.total} ready`, children: /* @__PURE__ */ jsx33(
7160
+ preview ? /* @__PURE__ */ jsx33(VaultSection, { title: `${ready} of ${preview.total} ready`, children: /* @__PURE__ */ jsx33(
7185
7161
  Windowed,
7186
7162
  {
7187
7163
  items: preview.slots,
7188
- render: (slot) => /* @__PURE__ */ jsx33(Row, { label: /* @__PURE__ */ jsx33(Badge9, { tone: TONE[slot.disposition], children: dispositionLabel(slot.disposition) }), hint: void 0, children: /* @__PURE__ */ jsx33("span", { className: "block truncate text-foreground", title: slot.reason ?? void 0, children: slot.title ?? "Unnamed passkey" }) }, slot.slot_id)
7164
+ render: (slot) => /* @__PURE__ */ jsx33(VaultRow, { label: /* @__PURE__ */ jsx33(Badge9, { tone: TONE[slot.disposition], children: dispositionLabel(slot.disposition) }), hint: void 0, children: /* @__PURE__ */ jsx33("span", { className: "block truncate text-foreground", title: slot.reason ?? void 0, children: slot.title ?? "Unnamed passkey" }) }, slot.slot_id)
7189
7165
  }
7190
7166
  ) }) : null,
7191
- status && !preview ? /* @__PURE__ */ jsxs31(Section, { title: `${accounted(status)} of ${status.total} done`, children: [
7192
- /* @__PURE__ */ jsx33(Row, { label: "Imported", children: /* @__PURE__ */ jsx33("span", { className: "text-foreground", children: status.committed }) }),
7193
- /* @__PURE__ */ jsx33(Row, { label: "Already there", children: /* @__PURE__ */ jsx33("span", { className: "text-foreground", children: status.already_present }) }),
7194
- /* @__PURE__ */ jsx33(Row, { label: "Can't import", children: /* @__PURE__ */ jsx33("span", { className: "text-foreground", children: status.unsupported }) }),
7195
- /* @__PURE__ */ jsx33(Row, { label: "Failed", children: /* @__PURE__ */ jsx33("span", { className: status.failed > 0 ? "text-destructive" : "text-foreground", children: status.failed }) }),
7196
- status.uncertain > 0 ? /* @__PURE__ */ jsx33(Row, { label: "Needs recovery", children: /* @__PURE__ */ jsx33("span", { className: "text-foreground", children: status.uncertain }) }) : null,
7197
- status.not_attempted > 0 ? /* @__PURE__ */ jsx33(Row, { label: "Not tried", children: /* @__PURE__ */ jsx33("span", { className: "text-foreground", children: status.not_attempted }) }) : null
7167
+ status && !preview ? /* @__PURE__ */ jsxs31(VaultSection, { title: `${accounted(status)} of ${status.total} done`, children: [
7168
+ /* @__PURE__ */ jsx33(VaultRow, { label: "Imported", children: /* @__PURE__ */ jsx33("span", { className: "text-foreground", children: status.committed }) }),
7169
+ /* @__PURE__ */ jsx33(VaultRow, { label: "Already there", children: /* @__PURE__ */ jsx33("span", { className: "text-foreground", children: status.already_present }) }),
7170
+ /* @__PURE__ */ jsx33(VaultRow, { label: "Can't import", children: /* @__PURE__ */ jsx33("span", { className: "text-foreground", children: status.unsupported }) }),
7171
+ /* @__PURE__ */ jsx33(VaultRow, { label: "Failed", children: /* @__PURE__ */ jsx33("span", { className: status.failed > 0 ? "text-destructive" : "text-foreground", children: status.failed }) }),
7172
+ status.uncertain > 0 ? /* @__PURE__ */ jsx33(VaultRow, { label: "Needs recovery", children: /* @__PURE__ */ jsx33("span", { className: "text-foreground", children: status.uncertain }) }) : null,
7173
+ status.not_attempted > 0 ? /* @__PURE__ */ jsx33(VaultRow, { label: "Not tried", children: /* @__PURE__ */ jsx33("span", { className: "text-foreground", children: status.not_attempted }) }) : null
7198
7174
  ] }) : null,
7199
7175
  screen.message ? /* @__PURE__ */ jsx33("p", { role: "status", className: "px-1 text-sm text-muted-foreground", children: screen.message }) : null,
7200
7176
  /* @__PURE__ */ jsx33(ErrorLine, { message: limitError })
@@ -7205,6 +7181,7 @@ function Importer({ bridge, readLimits, activeOrganizationId, organizations, onC
7205
7181
  import { useState as useState38 } from "react";
7206
7182
  import { DropdownMenu as DropdownMenu5, DropdownMenuContent as DropdownMenuContent5, DropdownMenuItem as DropdownMenuItem4, DropdownMenuTrigger as DropdownMenuTrigger5, SiteIcon } from "@ai-matrx/design-system";
7207
7183
  import { Button as Button32 } from "@ai-matrx/design-system/controls";
7184
+ import { GlobeIcon as GlobeIcon4 } from "@ai-matrx/design-system/icons";
7208
7185
 
7209
7186
  // src/extension/CaptureCard.tsx
7210
7187
  import { useState as useState35, useSyncExternalStore as useSyncExternalStore3 } from "react";
@@ -7347,6 +7324,7 @@ function FillSetupCard({ fillSetup }) {
7347
7324
  import { useState as useState37 } from "react";
7348
7325
  import { Popover as Popover2, PopoverContent as PopoverContent2, PopoverTrigger as PopoverTrigger2 } from "@ai-matrx/design-system";
7349
7326
  import { Button as Button31 } from "@ai-matrx/design-system/controls";
7327
+ import { CopyIcon as CopyIcon7 } from "@ai-matrx/design-system/icons";
7350
7328
  import { Fragment as Fragment20, jsx as jsx36, jsxs as jsxs34 } from "react/jsx-runtime";
7351
7329
  var HOLD_MS = 6e4;
7352
7330
  function PageGenerator({ fields }) {
@@ -7400,11 +7378,11 @@ function PageGenerator({ fields }) {
7400
7378
  const value = held.value;
7401
7379
  return /* @__PURE__ */ jsxs34(Fragment20, { children: [
7402
7380
  /* @__PURE__ */ jsx36(
7403
- Row,
7381
+ VaultRow,
7404
7382
  {
7405
7383
  label: "New password",
7406
7384
  actions: /* @__PURE__ */ jsxs34(Fragment20, { children: [
7407
- value ? /* @__PURE__ */ jsx36(Button31, { variant: "quiet", icon: /* @__PURE__ */ jsx36(CopyGlyph, {}), "aria-label": "Copy password", onClick: () => void copy(value, "Password") }) : null,
7385
+ value ? /* @__PURE__ */ jsx36(Button31, { variant: "quiet", icon: /* @__PURE__ */ jsx36(CopyIcon7, {}), "aria-label": "Copy password", onClick: () => void copy(value, "Password") }) : null,
7408
7386
  /* @__PURE__ */ jsxs34(Popover2, { open, onOpenChange: setOpen, children: [
7409
7387
  /* @__PURE__ */ jsx36(PopoverTrigger2, { asChild: true, children: /* @__PURE__ */ jsx36(Button31, { variant: "outline", icon: /* @__PURE__ */ jsx36(KeyGlyph, {}), disabled: busy, children: "Generate" }) }),
7410
7388
  /* @__PURE__ */ jsx36(PopoverContent2, { sizing: "content", align: "end", children: open ? /* @__PURE__ */ jsx36(PasswordGenerator, { limits, useLabel: "Fill page", onUse: (v) => void onUse(v) }) : null })
@@ -7413,7 +7391,7 @@ function PageGenerator({ fields }) {
7413
7391
  children: said ? /* @__PURE__ */ jsx36("span", { role: "status", className: said.tone === "success" ? "line-clamp-2 text-xs text-foreground" : "line-clamp-2 text-xs text-muted-foreground", children: said.text }) : targets.length > 0 ? /* @__PURE__ */ jsx36("span", { className: "text-xs text-muted-foreground", children: "Choose the boxes to fill." }) : /* @__PURE__ */ jsx36("span", { className: "text-xs text-disabled-foreground", children: "Fills the page\u2019s new-password box" })
7414
7392
  }
7415
7393
  ),
7416
- value && targets.length > 0 ? targets.map((t) => /* @__PURE__ */ jsx36(Row, { label: t.topFrame ? "This page" : "In a frame", actions: /* @__PURE__ */ jsx36(Button31, { variant: "primary", icon: /* @__PURE__ */ jsx36(CheckGlyph, {}), disabled: busy, onClick: () => void put(t.id, value), children: "Fill" }), children: /* @__PURE__ */ jsx36("span", { className: "block truncate text-sm", children: targetLabel(t) }) }, t.id)) : null
7394
+ value && targets.length > 0 ? targets.map((t) => /* @__PURE__ */ jsx36(VaultRow, { label: t.topFrame ? "This page" : "In a frame", actions: /* @__PURE__ */ jsx36(Button31, { variant: "primary", icon: /* @__PURE__ */ jsx36(CheckGlyph, {}), disabled: busy, onClick: () => void put(t.id, value), children: "Fill" }), children: /* @__PURE__ */ jsx36("span", { className: "block truncate text-sm", children: targetLabel(t) }) }, t.id)) : null
7417
7395
  ] });
7418
7396
  }
7419
7397
 
@@ -7475,7 +7453,7 @@ function PageView({ port, page, fill, capture, fillSetup, newPasswordFields, ite
7475
7453
  return /* @__PURE__ */ jsx37("div", { className: "flex h-full min-h-0 flex-col overflow-y-auto bg-background text-foreground", children: /* @__PURE__ */ jsxs35("div", { className: "flex flex-col gap-3 px-3 pb-4 pt-3", children: [
7476
7454
  header,
7477
7455
  /* @__PURE__ */ jsxs35("div", { className: "flex min-h-7 items-center gap-2 px-1", children: [
7478
- /* @__PURE__ */ jsx37(SiteIcon, { site: page.url, fallback: GlobeGlyph, className: "size-4" }),
7456
+ /* @__PURE__ */ jsx37(SiteIcon, { site: page.url, fallback: GlobeIcon4, className: "size-4" }),
7479
7457
  /* @__PURE__ */ jsx37("span", { className: "min-w-0 flex-1 truncate text-sm font-medium", title: page.url, children: site || "No page open" }),
7480
7458
  page.refresh ? /* @__PURE__ */ jsx37(Button32, { variant: "quiet", icon: /* @__PURE__ */ jsx37(RefreshGlyph, {}), "aria-label": "Check again", onClick: page.refresh }) : null,
7481
7459
  onBrowse ? /* @__PURE__ */ jsx37(Button32, { variant: "quiet", icon: /* @__PURE__ */ jsx37(ListGlyph, {}), onClick: onBrowse, children: "All items" }) : null
@@ -7483,7 +7461,7 @@ function PageView({ port, page, fill, capture, fillSetup, newPasswordFields, ite
7483
7461
  fillSetup ? /* @__PURE__ */ jsx37(FillSetupCard, { fillSetup }) : null,
7484
7462
  capture ? /* @__PURE__ */ jsx37(CaptureCard, { capture, onChanged }) : null,
7485
7463
  /* @__PURE__ */ jsx37(
7486
- Section,
7464
+ VaultSection,
7487
7465
  {
7488
7466
  title: "This site",
7489
7467
  actions: canSave ? /* @__PURE__ */ jsx37(Button32, { variant: "quiet", icon: /* @__PURE__ */ jsx37(PlusGlyph, {}), onClick: () => onNewForPage(normalizeLoginUrl2(page.url) ?? page.url), children: "Save a login" }) : null,
@@ -7491,7 +7469,7 @@ function PageView({ port, page, fill, capture, fillSetup, newPasswordFields, ite
7491
7469
  }
7492
7470
  ),
7493
7471
  said ? /* @__PURE__ */ jsx37(Outcome, { said, onDismiss: () => setSaid(null) }) : page.blocked && page.url && state.status === "ready" ? /* @__PURE__ */ jsx37("p", { className: "px-1 text-xs text-muted-foreground", children: BLOCK_WORDS[page.blocked] }) : null,
7494
- newPasswordFields && canSave ? /* @__PURE__ */ jsx37(Section, { children: /* @__PURE__ */ jsx37(PageGenerator, { fields: newPasswordFields }) }) : null
7472
+ newPasswordFields && canSave ? /* @__PURE__ */ jsx37(VaultSection, { children: /* @__PURE__ */ jsx37(PageGenerator, { fields: newPasswordFields }) }) : null
7495
7473
  ] }) });
7496
7474
  }
7497
7475
  function Outcome({ said, onDismiss }) {
@@ -7553,6 +7531,7 @@ function MatchRow({ itemId, item, tag, family, port, busy, running, onOpen, onFi
7553
7531
  import { useState as useState39 } from "react";
7554
7532
  import { cn as cn15, useLook as useLook2 } from "@ai-matrx/design-system";
7555
7533
  import { Select as Select10 } from "@ai-matrx/design-system/controls";
7534
+ import { GlobeIcon as GlobeIcon5 } from "@ai-matrx/design-system/icons";
7556
7535
  import { jsx as jsx38, jsxs as jsxs36 } from "react/jsx-runtime";
7557
7536
  function vaultChoices(items, organizations, current) {
7558
7537
  const n = (f) => items.filter(f).length;
@@ -7568,7 +7547,7 @@ function vaultChoices(items, organizations, current) {
7568
7547
  function VaultSelect({ value, choices, onChange }) {
7569
7548
  return /* @__PURE__ */ jsx38(Select10, { value, onValueChange: onChange, "aria-label": "Vault", options: choices.map((c) => ({ value: c.value, label: c.label, meta: String(c.count) })) });
7570
7549
  }
7571
- var CATEGORY_GLYPHS = { logins: GlobeGlyph, passkeys: ShieldGlyph, api: KeyGlyph, oauth: PlugGlyph, infra: DatabaseGlyph, env: TerminalGlyph, files: FileGlyph, other: NoteGlyph };
7550
+ var CATEGORY_GLYPHS = { logins: GlobeIcon5, passkeys: ShieldGlyph, api: KeyGlyph, oauth: PlugGlyph, infra: DatabaseGlyph, env: TerminalGlyph, files: FileGlyph, other: NoteGlyph };
7572
7551
  var familyOf = (key, definitions) => definitions.find((d) => d.key === key)?.family ?? "generic";
7573
7552
  function itemCategory(item, definitions) {
7574
7553
  return categoryOf(item.definitionKey, familyOf(item.definitionKey, definitions));
@@ -7633,7 +7612,7 @@ function Group({ title, children }) {
7633
7612
  children
7634
7613
  ] });
7635
7614
  }
7636
- function Sidebar({ vault, choices, onVault, view, allCount, deletedCount, views, hasFavorites, hasRecents, onView, onPanel, nativeProvider, hasNativeImport = false, hasPage = false }) {
7615
+ function VaultSidebar({ vault, choices, onVault, view, allCount, deletedCount, views, hasFavorites, hasRecents, onView, onPanel, nativeProvider, hasNativeImport = false, hasPage = false }) {
7637
7616
  const [tagsOpen, setTagsOpen] = useState39(view.startsWith("tag:"));
7638
7617
  return /* @__PURE__ */ jsxs36("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: [
7639
7618
  /* @__PURE__ */ jsxs36("div", { className: "flex items-center gap-2 px-3 pb-2 pt-3", children: [
@@ -7642,7 +7621,7 @@ function Sidebar({ vault, choices, onVault, view, allCount, deletedCount, views,
7642
7621
  ] }),
7643
7622
  /* @__PURE__ */ jsxs36("div", { className: "flex min-h-0 flex-1 flex-col gap-5 overflow-y-auto px-2 pb-3 pt-1", children: [
7644
7623
  /* @__PURE__ */ jsxs36("div", { className: "flex flex-col gap-0.5", children: [
7645
- hasPage ? /* @__PURE__ */ jsx38(Entry, { on: view === "page", glyph: GlobeGlyph, label: "This page", onClick: () => onView("page") }) : null,
7624
+ hasPage ? /* @__PURE__ */ jsx38(Entry, { on: view === "page", glyph: GlobeIcon5, label: "This page", onClick: () => onView("page") }) : null,
7646
7625
  /* @__PURE__ */ jsx38(Entry, { on: view === "all", glyph: GridGlyph, label: "All items", count: allCount, onClick: () => onView("all") }),
7647
7626
  hasFavorites ? /* @__PURE__ */ jsx38(Entry, { on: view === "favorites", glyph: StarGlyph, label: "Favorites", count: views.favorites, onClick: () => onView("favorites") }) : null,
7648
7627
  hasRecents ? /* @__PURE__ */ jsx38(Entry, { on: view === "recent", glyph: ClockGlyph, label: "Recently opened", count: views.recent, onClick: () => onView("recent") }) : null,
@@ -7682,7 +7661,7 @@ var NO_HOST = {};
7682
7661
  var ITEM_PANELS = {
7683
7662
  share: SharePanel,
7684
7663
  move: MovePanel,
7685
- history: HistoryPanel,
7664
+ history: ItemHistoryPanel,
7686
7665
  activity: ActivityPanel,
7687
7666
  settings: ItemSettingsPanel,
7688
7667
  field: FieldSettingsPanel,
@@ -8073,7 +8052,7 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
8073
8052
  ] }) : null,
8074
8053
  /* @__PURE__ */ jsxs37("div", { className: `grid min-h-0 w-full flex-1 ${grid} overflow-hidden`, children: [
8075
8054
  mode === "full" ? /* @__PURE__ */ jsx39(
8076
- Sidebar,
8055
+ VaultSidebar,
8077
8056
  {
8078
8057
  vault: loc.vault,
8079
8058
  choices,
@@ -8814,7 +8793,7 @@ function createApiVaultPort(api, options = {}) {
8814
8793
  lists.forEach((l, i) => {
8815
8794
  const sharedList = i === lists.length - 1;
8816
8795
  for (const w of l.items) {
8817
- if (seen.has(w.id) || deleted.has(w.id)) continue;
8796
+ if (seen.has(w.id) || deleted.has(w.id) || isHiddenItem(w)) continue;
8818
8797
  const owner = sharedList ? orgOf(w.organization_id, null, false) : orgOf(w.organization_id, w.user_id, i === 0);
8819
8798
  const item = itemOf(w, sharedList && !w.organization_id ? { kind: "shared", label: "Shared with me", organizationId: null } : owner, defs, auth);
8820
8799
  (isDeleted(w) ? deleted : seen).set(w.id, item);
@@ -8925,6 +8904,7 @@ export {
8925
8904
  CATEGORIES,
8926
8905
  DEFAULT_LOCATION,
8927
8906
  GenerateButton,
8907
+ HIDDEN_ITEM_TAG,
8928
8908
  LOCKED_MESSAGE,
8929
8909
  VaultApp,
8930
8910
  VaultLockedError,
@@ -8935,6 +8915,7 @@ export {
8935
8915
  createVaultKnobs,
8936
8916
  guardPort,
8937
8917
  inferFromUrl,
8918
+ isHiddenItem,
8938
8919
  locationFromParams,
8939
8920
  locationToParams,
8940
8921
  loginSiteOf,