@ai-matrx/vault 0.1.8 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -222,6 +222,7 @@ var import_design_system2 = require("@ai-matrx/design-system");
222
222
  var import_controls = require("@ai-matrx/design-system/controls");
223
223
 
224
224
  // src/glyphs.tsx
225
+ var import_icons = require("@ai-matrx/design-system/icons");
225
226
  var import_jsx_runtime2 = require("react/jsx-runtime");
226
227
  function glyph(paths, air = [1, 1]) {
227
228
  const style = { "--matrx-glyph-air-l": air[0], "--matrx-glyph-air-r": air[1] };
@@ -233,10 +234,6 @@ var KeyGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_ru
233
234
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "7.5", cy: "15.5", r: "5.5" }),
234
235
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "m21 2-9.6 9.6M15.5 7.5l3 3" })
235
236
  ] }), [1, 2]);
236
- var GlobeGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
237
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
238
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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" })
239
- ] }), [1, 1]);
240
237
  var NoteGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
241
238
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }),
242
239
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M14 2v4a2 2 0 0 0 2 2h4M16 13H8M16 17H8" })
@@ -266,10 +263,6 @@ var FileGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_r
266
263
  var CodeGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "m16 18 6-6-6-6M8 6l-6 6 6 6" }) }), [1, 1]);
267
264
  var StarGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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]);
268
265
  var PlusGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M12 5v14M5 12h14" }), [4, 4]);
269
- var CopyGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
270
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }),
271
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
272
- ] }), [1, 1]);
273
266
  var EyeGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
274
267
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M2 12s3.6-7 10-7 10 7 10 7-3.6 7-10 7-10-7-10-7z" }),
275
268
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "12", cy: "12", r: "3" })
@@ -294,11 +287,6 @@ var BuildingGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_j
294
287
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "4", y: "2", width: "16", height: "20", rx: "2" }),
295
288
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M9 22v-4h6v4M8 6h.01M16 6h.01M12 6h.01M12 10h.01M12 14h.01M16 10h.01M16 14h.01M8 10h.01M8 14h.01" })
296
289
  ] }), [3, 3]);
297
- var UsersGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
298
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" }),
299
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "9", cy: "7", r: "4" }),
300
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M22 21v-2a4 4 0 0 0-3-3.9M16 3.1a4 4 0 0 1 0 7.8" })
301
- ] }), [1, 1]);
302
290
  var ChevronLeftGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "m15 18-6-6 6-6" }), [8, 8]);
303
291
  var GridGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
304
292
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "3", y: "3", width: "7", height: "7", rx: "1" }),
@@ -317,7 +305,7 @@ var FAMILY_GLYPHS = {
317
305
  cloud_infrastructure: ServerGlyph
318
306
  };
319
307
  function definitionGlyph(key, family) {
320
- if (key === "username_password" || key === "website_login") return GlobeGlyph;
308
+ if (key === "username_password" || key === "website_login") return import_icons.GlobeIcon;
321
309
  return FAMILY_GLYPHS[family] ?? KeyGlyph;
322
310
  }
323
311
  var XGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M18 6 6 18M6 6l12 12" }), [5, 5]);
@@ -335,15 +323,7 @@ var MoreGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_r
335
323
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "5", cy: "12", r: "1" })
336
324
  ] }), [3, 3]);
337
325
  var ShareGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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]);
338
- var HistoryGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
339
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
340
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M3 3v5h5M12 7v5l4 2" })
341
- ] }), [2, 2]);
342
326
  var ListGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01" }), [2, 2]);
343
- var SettingsGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
344
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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" }),
345
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "12", cy: "12", r: "3" })
346
- ] }), [2, 2]);
347
327
  var ImportGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3" }), [2, 2]);
348
328
  var ExportGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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]);
349
329
  var ChevronDownGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "m6 9 6 6 6-6" }), [5, 5]);
@@ -384,10 +364,6 @@ var RefreshGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_js
384
364
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M21 3v5h-5M3 21v-5h5" })
385
365
  ] }), [2, 2]);
386
366
  var SlidersGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M4 21v-7M4 10V3M12 21v-9M12 8V3M20 21v-5M20 12V3M1 14h6M9 8h6M17 16h6" }) }), [0, 0]);
387
- var DownloadGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
388
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
389
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "m7 10 5 5 5-5M12 15V3" })
390
- ] }), [2, 2]);
391
367
  var UploadGlyph = glyph(/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
392
368
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
393
369
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "m17 8-5-5-5 5M12 3v12" })
@@ -469,7 +445,7 @@ var Ctx2 = (0, import_react2.createContext)((run) => run());
469
445
  function useConfirmed() {
470
446
  return (0, import_react2.useContext)(Ctx2);
471
447
  }
472
- var PROVIDER_LABEL = { google: "Google", github: "GitHub", azure: "Microsoft", apple: "Apple", linkedin_oidc: "LinkedIn", slack_oidc: "Slack" };
448
+ var PROVIDER_LABEL = { google: "Google", github: "GitHub", azure: "Microsoft", apple: "Apple", linkedin_oidc: "LinkedIn", slack_oidc: "Slack", browser: "Browser", touch_id: "Touch ID" };
473
449
  var providerLabel = (p) => PROVIDER_LABEL[p] ?? p.charAt(0).toUpperCase() + p.slice(1);
474
450
  function IdentityGate({ identity, children }) {
475
451
  const [asking, setAsking] = (0, import_react2.useState)(false);
@@ -539,10 +515,21 @@ function ConfirmIdentityDialog({ open, identity, onDone, onCancel }) {
539
515
  ] }),
540
516
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex flex-col gap-3", children: [
541
517
  identity.dev ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_controls.Button, { variant: "primary", disabled: busy, onClick: () => void attempt(() => identity.dev?.() ?? Promise.resolve()), children: "Sign in again (dev)" }) : null,
542
- account10?.providers.map((p) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_controls.Button, { variant: identity.dev ? "outline" : "primary", disabled: busy, onClick: () => void attempt(() => identity.withProvider(p), false), children: [
543
- "Continue with ",
544
- providerLabel(p)
545
- ] }, p)),
518
+ account10?.providers.map((p) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
519
+ import_controls.Button,
520
+ {
521
+ variant: identity.dev ? "outline" : "primary",
522
+ disabled: busy,
523
+ onClick: () => void attempt(async () => {
524
+ if (await identity.withProvider(p) === "confirmed") onDone();
525
+ }, false),
526
+ children: [
527
+ "Continue with ",
528
+ providerLabel(p)
529
+ ]
530
+ },
531
+ p
532
+ )),
546
533
  account10?.hasPassword ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("form", { className: "flex gap-2", onSubmit: (e) => {
547
534
  e.preventDefault();
548
535
  if (password) void attempt(() => identity.withPassword(password));
@@ -569,6 +556,7 @@ function ConfirmIdentityDialog({ open, identity, onDone, onCancel }) {
569
556
  var import_react5 = require("react");
570
557
  var import_controls2 = require("@ai-matrx/design-system/controls");
571
558
  var import_design_system5 = require("@ai-matrx/design-system");
559
+ var import_icons2 = require("@ai-matrx/design-system/icons");
572
560
 
573
561
  // src/hooks.ts
574
562
  var import_react3 = require("react");
@@ -637,14 +625,15 @@ function useRoomOf(ref) {
637
625
  return room;
638
626
  }
639
627
  var RoomProvider = Room.Provider;
640
- function Section({ title, actions, children, className }) {
628
+ function VaultSection({ title, actions, children, className }) {
641
629
  const flat = (0, import_react4.useContext)(InPanel);
630
+ const desktop = (0, import_design_system4.useLook)() === "desktop";
642
631
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: (0, import_design_system4.cn)("flex flex-col gap-1.5", className), children: [
643
632
  title || actions ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex min-h-7 items-center justify-between gap-2 px-1", children: [
644
- title ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { className: "text-xs font-medium text-muted-foreground", children: title }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", {}),
633
+ title ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { className: desktop ? "text-sm font-semibold text-foreground" : "text-xs font-medium text-muted-foreground", children: title }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", {}),
645
634
  actions ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "flex items-center gap-1", children: actions }) : null
646
635
  ] }) : null,
647
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: flat ? "-mx-3 flex flex-col sm:-mx-4" : "flex flex-col rounded-xl border border-border bg-card py-1", children })
636
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: flat ? "-mx-3 flex flex-col sm:-mx-4" : desktop ? "flex flex-col divide-y divide-border rounded-xl bg-card" : "flex flex-col rounded-xl border border-border bg-card py-1", children })
648
637
  ] });
649
638
  }
650
639
  var ROW_GRID = {
@@ -652,7 +641,7 @@ var ROW_GRID = {
652
641
  roomy: "grid-cols-[9rem_minmax(0,1fr)_auto] gap-x-3 px-4",
653
642
  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"
654
643
  };
655
- function Row({ label, hint, children, actions, top = false, className }) {
644
+ function VaultRow({ label, hint, children, actions, top = false, className }) {
656
645
  const room = (0, import_react4.useContext)(Room);
657
646
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: (0, import_design_system4.cn)("grid min-h-11 py-1", ROW_GRID[room ?? "viewport"], top ? "items-start" : "items-center", className), children: [
658
647
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: (0, import_design_system4.cn)("flex min-w-0 flex-col text-xs leading-tight text-muted-foreground", top && "pt-2.5"), children: [
@@ -673,11 +662,6 @@ function Panel({ title, open = true, onClose, children, footer, size = "lg" }) {
673
662
  footer ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system3.DialogFooter, { children: footer }) : null
674
663
  ] }) });
675
664
  }
676
- function formatBytes(n) {
677
- if (n < 1024) return `${n} B`;
678
- if (n < 1024 * 1024) return `${(n / 1024).toFixed(n < 10 * 1024 ? 1 : 0)} KB`;
679
- return `${(n / 1024 / 1024).toFixed(1)} MB`;
680
- }
681
665
  var DAY_FORMAT = { year: "numeric", month: "short", day: "numeric" };
682
666
 
683
667
  // src/FieldRows.tsx
@@ -736,14 +720,14 @@ function SecretRow({ port, item, field, extra }) {
736
720
  const multiline = field.kind === "multiline";
737
721
  const shown = visible ? plain : secret.value;
738
722
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
739
- Row,
723
+ VaultRow,
740
724
  {
741
725
  label: field.label,
742
726
  top: multiline && shown !== null,
743
727
  actions: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
744
728
  extra,
745
729
  canSee && !visible ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_controls2.Button, { variant: "quiet", icon: secret.value !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(EyeOffGlyph, {}) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(EyeGlyph, {}), "aria-label": secret.value !== null ? `Hide ${field.label}` : `Show ${field.label}`, disabled: busy, onClick: () => void toggle2() }) : null,
746
- canSee ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_controls2.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CopyGlyph, {}), "aria-label": `Copy ${field.label}`, disabled: busy, onClick: () => void copy() }) : null
730
+ canSee ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_controls2.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_icons2.CopyIcon, {}), "aria-label": `Copy ${field.label}`, disabled: busy, onClick: () => void copy() }) : null
747
731
  ] }),
748
732
  children: sealed ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_controls2.Badge, { icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(LockGlyph, {}), children: "Sealed" }) : off ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-muted-foreground", children: "Turned off" }) : error ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "truncate text-destructive", title: error, children: error }) : shown !== null ? visible ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: (0, import_design_system5.cn)("block", multiline ? "whitespace-pre-wrap break-words" : "truncate"), children: shown || "\u2014" }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SecretText, { value: shown, multiline }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: (0, import_design_system5.cn)("block truncate text-muted-foreground", !visible && "tracking-widest"), children: visible ? "\u2026" : MASK })
749
733
  }
@@ -753,7 +737,7 @@ function PlainRow({ label, value, hint, openUrl, extra, multiline = false }) {
753
737
  const copyValue2 = useCopy();
754
738
  const isUrl = /^https?:\/\//i.test(value);
755
739
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
756
- Row,
740
+ VaultRow,
757
741
  {
758
742
  label,
759
743
  hint,
@@ -761,7 +745,7 @@ function PlainRow({ label, value, hint, openUrl, extra, multiline = false }) {
761
745
  actions: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
762
746
  extra,
763
747
  isUrl && openUrl ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_controls2.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ExternalGlyph, {}), "aria-label": `Open ${value}`, onClick: () => openUrl(value) }) : null,
764
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_controls2.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CopyGlyph, {}), "aria-label": `Copy ${typeof label === "string" ? label : "value"}`, onClick: () => void copyValue2(value, typeof label === "string" && label ? label : "Value", { secret: false }) })
748
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_controls2.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_icons2.CopyIcon, {}), "aria-label": `Copy ${typeof label === "string" ? label : "value"}`, onClick: () => void copyValue2(value, typeof label === "string" && label ? label : "Value", { secret: false }) })
765
749
  ] }),
766
750
  children: isUrl && openUrl ? (
767
751
  // A real link (right-click, copy link address, open in a new tab); a click goes through the host's opener.
@@ -784,12 +768,12 @@ function PlainRow({ label, value, hint, openUrl, extra, multiline = false }) {
784
768
  );
785
769
  }
786
770
  function AddRow({ label, onAdd, children = "Add" }) {
787
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Row, { label, children: onAdd ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "text-sm text-muted-foreground hover:text-primary", onClick: onAdd, children }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-disabled-foreground", children: "\u2014" }) });
771
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(VaultRow, { label, children: onAdd ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "text-sm text-muted-foreground hover:text-primary", onClick: onAdd, children }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-disabled-foreground", children: "\u2014" }) });
788
772
  }
789
773
  function EditRow({ label, hint, value, onChange, placeholder, secret = false, multiline = false, onRemove, removeLabel, actions, autoFocus, onBlur, inputMode }) {
790
774
  const [shown, setShown] = (0, import_react5.useState)(false);
791
775
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
792
- Row,
776
+ VaultRow,
793
777
  {
794
778
  label,
795
779
  hint,
@@ -806,7 +790,7 @@ function EditRow({ label, hint, value, onChange, placeholder, secret = false, mu
806
790
  function CustomEditRow({ label, value, onLabel, onValue, secret, onRemove }) {
807
791
  const [shown, setShown] = (0, import_react5.useState)(false);
808
792
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
809
- Row,
793
+ VaultRow,
810
794
  {
811
795
  label: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_controls2.Field, { className: "w-full", value: label, onChange: (e) => onLabel(e.target.value), placeholder: "Name", "aria-label": "Field name" }),
812
796
  actions: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
@@ -819,6 +803,7 @@ function CustomEditRow({ label, value, onLabel, onValue, secret, onRemove }) {
819
803
  }
820
804
 
821
805
  // src/activity/HistoryPanel.tsx
806
+ var import_icons3 = require("@ai-matrx/design-system/icons");
822
807
  var import_format3 = require("@ai-matrx/kit/format");
823
808
 
824
809
  // src/activity/logic.ts
@@ -1311,7 +1296,7 @@ function ActivityPanel({ item, port, onClose }) {
1311
1296
  footer: hasMore ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_controls3.Button, { variant: "outline", disabled: loading, onClick: () => setLimit((n) => Math.min(MAX, n * 2)), children: loading ? "Loading\u2026" : "Show more" }) : void 0,
1312
1297
  children: [
1313
1298
  error ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { role: "alert", className: "px-1 text-sm text-destructive", children: error }) : null,
1314
- entries === null ? loading ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Empty, { children: "Reading activity\u2026" }) : null : entries.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Empty, { children: "Nothing has happened yet." }) : groupByDay(entries, now).map((day) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Section, { title: day.label, children: collapseRuns(
1299
+ entries === null ? loading ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Empty, { children: "Reading activity\u2026" }) : null : entries.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Empty, { children: "Nothing has happened yet." }) : groupByDay(entries, now).map((day) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(VaultSection, { title: day.label, children: collapseRuns(
1315
1300
  day.entries.map((entry) => ({ entry, s: auditSentence(entry, item, me) })),
1316
1301
  (r) => `${r.s.what}|${r.s.who ?? ""}`
1317
1302
  ).map(({ row: { entry, s }, times }) => {
@@ -1334,7 +1319,7 @@ function ActivityPanel({ item, port, onClose }) {
1334
1319
  var import_jsx_runtime7 = require("react/jsx-runtime");
1335
1320
  var MASK2 = "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
1336
1321
  var messageOf = (e, fallback) => wasCancelled(e) ? null : e instanceof Error ? e.message : fallback;
1337
- function HistoryPanel({ item, port, arg, onClose, onChanged }) {
1322
+ function ItemHistoryPanel({ item, port, arg, onClose, onChanged }) {
1338
1323
  const eligible = historyEligible(item);
1339
1324
  const [page, setPage] = (0, import_react7.useState)(null);
1340
1325
  const [loading, setLoading] = (0, import_react7.useState)(eligible);
@@ -1396,7 +1381,7 @@ function HistoryPanel({ item, port, arg, onClose, onChanged }) {
1396
1381
  error ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { role: "alert", className: "px-1 text-sm text-destructive", children: error }) : null,
1397
1382
  notice ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { role: "status", className: "px-1 text-sm text-success", children: notice }) : null,
1398
1383
  page && groups.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Empty, { children: "No earlier values yet." }) : null,
1399
- page ? groups.map((g) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Section, { title: g.label, children: g.entries.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HistoryRow, { item, port, page, entry, label: g.label, onRestored: restored, onConflict: conflicted, onError: setError }, `${item.id}:${entry.fieldId}:${entry.revision}`)) }, g.fieldId)) : null,
1384
+ page ? groups.map((g) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(VaultSection, { title: g.label, children: g.entries.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HistoryRow, { item, port, page, entry, label: g.label, onRestored: restored, onConflict: conflicted, onError: setError }, `${item.id}:${entry.fieldId}:${entry.revision}`)) }, g.fieldId)) : null,
1400
1385
  page && (page.captureStartedAt || page.incomplete) ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-wrap gap-x-3 gap-y-1 px-1 text-xs", children: [
1401
1386
  page.captureStartedAt ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "text-muted-foreground", children: [
1402
1387
  "Kept since ",
@@ -1457,12 +1442,12 @@ function HistoryRow({ item, port, page, entry, label, onRestored, onConflict, on
1457
1442
  }
1458
1443
  }
1459
1444
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1460
- Row,
1445
+ VaultRow,
1461
1446
  {
1462
1447
  label: when,
1463
1448
  actions: entry.available ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
1464
1449
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_controls4.Button, { variant: "quiet", icon: secret.value !== null ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(EyeOffGlyph, {}) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(EyeGlyph, {}), "aria-label": secret.value !== null ? "Hide" : "Show", disabled: busy, onClick: () => void toggle2() }),
1465
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_controls4.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CopyGlyph, {}), "aria-label": "Copy", disabled: busy, onClick: () => void copy() }),
1450
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_controls4.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_icons3.CopyIcon, {}), "aria-label": "Copy", disabled: busy, onClick: () => void copy() }),
1466
1451
  canRestore(page, entry) ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_controls4.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(RestoreGlyph, {}), "aria-label": "Restore", disabled: busy, onClick: () => void restore() }) : null
1467
1452
  ] }) : null,
1468
1453
  children: !entry.available ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_controls4.Badge, { children: "Not kept" }) : secret.value !== null ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SecretText, { value: secret.value, multiline: false }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "block truncate tracking-widest text-muted-foreground", children: MASK2 })
@@ -1474,6 +1459,7 @@ function HistoryRow({ item, port, page, entry, label, onRestored, onConflict, on
1474
1459
  var import_react13 = require("react");
1475
1460
  var import_controls9 = require("@ai-matrx/design-system/controls");
1476
1461
  var import_design_system9 = require("@ai-matrx/design-system");
1462
+ var import_icons5 = require("@ai-matrx/design-system/icons");
1477
1463
 
1478
1464
  // src/authenticator/AddOtpPanel.tsx
1479
1465
  var import_react12 = require("react");
@@ -1483,8 +1469,11 @@ var import_controls8 = require("@ai-matrx/design-system/controls");
1483
1469
  var import_react8 = require("react");
1484
1470
  var import_controls5 = require("@ai-matrx/design-system/controls");
1485
1471
  var import_design_system7 = require("@ai-matrx/design-system");
1472
+ var import_icons4 = require("@ai-matrx/design-system/icons");
1473
+ var import_format5 = require("@ai-matrx/kit/format");
1486
1474
 
1487
1475
  // src/authenticator/otpauth.ts
1476
+ var import_format4 = require("@ai-matrx/kit/format");
1488
1477
  var TOTP_DEFAULT_DIGITS = 6;
1489
1478
  var TOTP_DEFAULT_PERIOD = 30;
1490
1479
  var TOTP_DEFAULT_ALGORITHM = "SHA1";
@@ -1552,14 +1541,8 @@ function describeEnrollment(parsed) {
1552
1541
  const parts = [parsed.issuer, parsed.account].filter((p) => Boolean(p));
1553
1542
  return parts.length ? parts.join(" \xB7 ") : "Setup key";
1554
1543
  }
1555
- function groupCode(code) {
1556
- const c = code.replace(/\s/g, "");
1557
- if (c.length < 6) return c;
1558
- const head = Math.ceil(c.length / 2);
1559
- return `${c.slice(0, head)} ${c.slice(head)}`;
1560
- }
1561
1544
  function maskedCode(digits = TOTP_DEFAULT_DIGITS) {
1562
- return groupCode("\u2022".repeat(Math.max(6, digits)));
1545
+ return (0, import_format4.groupCode)("\u2022".repeat(Math.max(6, digits)));
1563
1546
  }
1564
1547
  function accountOfLabel(label, issuer) {
1565
1548
  const l = label?.trim();
@@ -1635,7 +1618,7 @@ function useCopied() {
1635
1618
  }
1636
1619
  function CodeButton({ live, digits, size = "md", label }) {
1637
1620
  const { copied, copy } = useCopied();
1638
- const shown = live.code ? groupCode(live.code) : maskedCode(digits);
1621
+ const shown = live.code ? (0, import_format5.groupCode)(live.code) : maskedCode(digits);
1639
1622
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1640
1623
  "button",
1641
1624
  {
@@ -1654,7 +1637,7 @@ function CodeButton({ live, digits, size = "md", label }) {
1654
1637
  }
1655
1638
  function CopyCodeButton({ live, label }) {
1656
1639
  const { copied, copy } = useCopied();
1657
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_controls5.Button, { variant: "quiet", icon: copied ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckGlyph, {}) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CopyGlyph, {}), ...copied ? { glyphTone: "success" } : {}, "aria-label": `Copy ${label} code`, disabled: !live.code, onClick: () => live.code && void copy(live.code) });
1640
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_controls5.Button, { variant: "quiet", icon: copied ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CheckGlyph, {}) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_icons4.CopyIcon, {}), ...copied ? { glyphTone: "success" } : {}, "aria-label": `Copy ${label} code`, disabled: !live.code, onClick: () => live.code && void copy(live.code) });
1658
1641
  }
1659
1642
 
1660
1643
  // src/authenticator/live-code.ts
@@ -1926,7 +1909,7 @@ function OtpSetupRow({ value, onChange, label = "One-time password", placeholder
1926
1909
  className: dragging ? "rounded-lg bg-accent" : void 0,
1927
1910
  children: [
1928
1911
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
1929
- Row,
1912
+ VaultRow,
1930
1913
  {
1931
1914
  label,
1932
1915
  actions: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
@@ -2076,7 +2059,7 @@ function TotpRow({ port, item, onChanged }) {
2076
2059
  ] })
2077
2060
  ] }) : null;
2078
2061
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2079
- Row,
2062
+ VaultRow,
2080
2063
  {
2081
2064
  label: "One-time password",
2082
2065
  actions: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
@@ -2135,7 +2118,7 @@ function TwoFactorMethodRow({ port, item, onChanged }) {
2135
2118
  const [busy, setBusy] = (0, import_react11.useState)(false);
2136
2119
  const [error, setError] = (0, import_react11.useState)(null);
2137
2120
  const canEdit = item.capabilities.canEdit || item.capabilities.canManage;
2138
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Row, { label: "Two-factor", hint: error ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-destructive", children: error }) : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2121
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(VaultRow, { label: "Two-factor", hint: error ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-destructive", children: error }) : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2139
2122
  import_controls7.Select,
2140
2123
  {
2141
2124
  value: value ?? "none",
@@ -2250,7 +2233,7 @@ function AddOtpPanel({ port, items, definitions, itemId = null, onClose, onChang
2250
2233
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_controls8.Button, { variant: "primary", disabled: !ready, onClick: () => void save(), children: busy ? "Adding\u2026" : "Add" })
2251
2234
  ] }),
2252
2235
  children: [
2253
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Section, { children: [
2236
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(VaultSection, { children: [
2254
2237
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2255
2238
  OtpSetupRow,
2256
2239
  {
@@ -2272,7 +2255,7 @@ function AddOtpPanel({ port, items, definitions, itemId = null, onClose, onChang
2272
2255
  status: image ? `QR image ready \xB7 ${image.name}` : null
2273
2256
  }
2274
2257
  ),
2275
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Row, { label: "Add to", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2258
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(VaultRow, { label: "Add to", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2276
2259
  import_controls8.Select,
2277
2260
  {
2278
2261
  value: target,
@@ -2286,7 +2269,7 @@ function AddOtpPanel({ port, items, definitions, itemId = null, onClose, onChang
2286
2269
  }
2287
2270
  ) }),
2288
2271
  isNew ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
2289
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Row, { label: "Name", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2272
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(VaultRow, { label: "Name", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2290
2273
  import_controls8.Field,
2291
2274
  {
2292
2275
  className: "w-full",
@@ -2300,7 +2283,7 @@ function AddOtpPanel({ port, items, definitions, itemId = null, onClose, onChang
2300
2283
  "aria-label": "Name"
2301
2284
  }
2302
2285
  ) }),
2303
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Row, { label: "Website", hint: websiteBad ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "text-destructive", children: "Not a web address" }) : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_controls8.Field, { 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 }) })
2286
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(VaultRow, { label: "Website", hint: websiteBad ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "text-destructive", children: "Not a web address" }) : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_controls8.Field, { 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 }) })
2304
2287
  ] }) : null
2305
2288
  ] }),
2306
2289
  error ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "px-1 text-sm text-destructive", role: "alert", children: error }) : null
@@ -2368,7 +2351,7 @@ function AuthenticatorView({ port, items, definitions, query, onOpen, onChanged,
2368
2351
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "flex size-12 items-center justify-center rounded-full bg-muted text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ShieldGlyph, { className: "size-6" }) }),
2369
2352
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm font-medium text-foreground", children: "No one-time passwords yet" }),
2370
2353
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_controls9.Button, { variant: "primary", icon: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PlusGlyph, {}), onClick: () => setAdding(true), children: "Add one-time password" })
2371
- ] }) : groups.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "px-4 py-10 text-center text-sm text-muted-foreground", children: "Nothing matches." }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "min-h-0 flex-1 overflow-y-auto px-3 pb-6 pt-1 sm:px-4", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "mx-auto flex w-full max-w-3xl flex-col gap-5", children: groups.map((g) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Section, { ...groups.length > 1 ? { title: g.label } : {}, className: "[&>div]:px-1", children: g.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2354
+ ] }) : groups.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "px-4 py-10 text-center text-sm text-muted-foreground", children: "Nothing matches." }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "min-h-0 flex-1 overflow-y-auto px-3 pb-6 pt-1 sm:px-4", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "mx-auto flex w-full max-w-3xl flex-col gap-5", children: groups.map((g) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(VaultSection, { ...groups.length > 1 ? { title: g.label } : {}, className: "[&>div]:px-1", children: g.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2372
2355
  OtpListRow,
2373
2356
  {
2374
2357
  port,
@@ -2462,7 +2445,7 @@ function OtpListRow({ port, item, family, entry, onOpen, onRename, onChanged, on
2462
2445
  "Open login"
2463
2446
  ] }),
2464
2447
  live.code ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_design_system9.DropdownMenuItem, { onSelect: () => live.code && void copy(live.code), children: [
2465
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CopyGlyph, { className: "size-4" }),
2448
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_icons5.CopyIcon, { className: "size-4" }),
2466
2449
  "Copy code"
2467
2450
  ] }) : null,
2468
2451
  canManage ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
@@ -2489,6 +2472,7 @@ function OtpListRow({ port, item, family, entry, onOpen, onRename, onChanged, on
2489
2472
  var import_react14 = require("react");
2490
2473
  var import_controls10 = require("@ai-matrx/design-system/controls");
2491
2474
  var import_confirm_opener3 = require("@ai-matrx/kit/confirm-opener");
2475
+ var import_icons6 = require("@ai-matrx/design-system/icons");
2492
2476
 
2493
2477
  // src/fields/rules.ts
2494
2478
  var ENV_KEY_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
@@ -2638,7 +2622,7 @@ function FieldSettings({ item, port, field, onClose, onChanged }) {
2638
2622
  const locked = !canEdit || busy !== null;
2639
2623
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Panel, { title: `${field.label} settings`, size: "md", onClose, footer: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_controls10.Button, { variant: "primary", onClick: onClose, children: "Done" }), children: [
2640
2624
  !canEdit ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "px-1 text-sm text-muted-foreground", children: "View only: you can\u2019t change these settings." }) : null,
2641
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Section, { title: "Who can see it", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Row, { label: "Value", hint: quietHint(handling.hint), children: field.handling === "sealed" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_controls10.Badge, { icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(LockGlyph, {}), children: "Sealed for good" }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2625
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(VaultSection, { title: "Who can see it", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(VaultRow, { label: "Value", hint: quietHint(handling.hint), children: field.handling === "sealed" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_controls10.Badge, { icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(LockGlyph, {}), children: "Sealed for good" }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2642
2626
  import_controls10.SegmentedControl,
2643
2627
  {
2644
2628
  "aria-label": "Who can see it",
@@ -2647,8 +2631,8 @@ function FieldSettings({ item, port, field, onClose, onChanged }) {
2647
2631
  data: handlingChoices(field.handling).map((h) => ({ value: h, label: HANDLING_WORDS[h].label, title: HANDLING_WORDS[h].hint, disabled: locked }))
2648
2632
  }
2649
2633
  ) }) }),
2650
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Section, { title: "Automation", children: [
2651
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Row, { label: "Env key", hint: envProblem ? quietHint(envProblem, "destructive") : quietHint("The name sandboxes and workflows use"), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2634
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(VaultSection, { title: "Automation", children: [
2635
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(VaultRow, { label: "Env key", hint: envProblem ? quietHint(envProblem, "destructive") : quietHint("The name sandboxes and workflows use"), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2652
2636
  import_controls10.Field,
2653
2637
  {
2654
2638
  ref: envRef,
@@ -2668,10 +2652,10 @@ function FieldSettings({ item, port, field, onClose, onChanged }) {
2668
2652
  }
2669
2653
  }
2670
2654
  ) }),
2671
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Row, { label: "Use in sandbox", hint: blocker && !field.injectIntoSandbox ? quietHint(blocker) : quietHint("Sandboxes get it as an env variable"), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_controls10.Switch, { "aria-label": "Use in sandbox", checked: field.injectIntoSandbox, disabled: locked, onCheckedChange: (v) => void setSandbox(v) }) })
2655
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(VaultRow, { label: "Use in sandbox", hint: blocker && !field.injectIntoSandbox ? quietHint(blocker) : quietHint("Sandboxes get it as an env variable"), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_controls10.Switch, { "aria-label": "Use in sandbox", checked: field.injectIntoSandbox, disabled: locked, onCheckedChange: (v) => void setSandbox(v) }) })
2672
2656
  ] }),
2673
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Section, { title: "Field", children: [
2674
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Row, { label: "Description", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2657
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(VaultSection, { title: "Field", children: [
2658
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(VaultRow, { label: "Description", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2675
2659
  import_controls10.Field,
2676
2660
  {
2677
2661
  className: "w-full",
@@ -2687,8 +2671,8 @@ function FieldSettings({ item, port, field, onClose, onChanged }) {
2687
2671
  }
2688
2672
  }
2689
2673
  ) }),
2690
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Row, { label: "Editable", hint: quietHint(field.editable ? "The value can be changed" : "The value is locked"), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_controls10.Switch, { "aria-label": "Editable", checked: field.editable, disabled: locked, onCheckedChange: (v) => void update("editable", { editable: v }) }) }),
2691
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Row, { label: "Active", hint: quietHint(field.active ? "In use" : "Kept, but nothing uses it"), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_controls10.Switch, { "aria-label": "Active", checked: field.active, disabled: locked, onCheckedChange: (v) => void update("active", { active: v }) }) })
2674
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(VaultRow, { label: "Editable", hint: quietHint(field.editable ? "The value can be changed" : "The value is locked"), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_controls10.Switch, { "aria-label": "Editable", checked: field.editable, disabled: locked, onCheckedChange: (v) => void update("editable", { editable: v }) }) }),
2675
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(VaultRow, { label: "Active", hint: quietHint(field.active ? "In use" : "Kept, but nothing uses it"), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_controls10.Switch, { "aria-label": "Active", checked: field.active, disabled: locked, onCheckedChange: (v) => void update("active", { active: v }) }) })
2692
2676
  ] }),
2693
2677
  error ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Problem, { children: error }) : null
2694
2678
  ] });
@@ -2719,8 +2703,8 @@ function ItemSettingsPanel({ item, port, onClose, onChanged, onPanel }) {
2719
2703
  const fillHint = !hasWebsite ? "Add a website first" : item.browserFillEnabled ? "Offered on matching pages" : "Never filled automatically";
2720
2704
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Panel, { title: "Item settings", size: "md", onClose, footer: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_controls10.Button, { variant: "primary", onClick: onClose, children: "Done" }), children: [
2721
2705
  !canEdit ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "px-1 text-sm text-muted-foreground", children: "View only: you can\u2019t change these settings." }) : null,
2722
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Section, { title: "In the browser", children: [
2723
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Row, { label: "Website matching", hint: quietHint(MATCH_WORDS[item.uriMatchMode].hint), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2706
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(VaultSection, { title: "In the browser", children: [
2707
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(VaultRow, { label: "Website matching", hint: quietHint(MATCH_WORDS[item.uriMatchMode].hint), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2724
2708
  import_controls10.Select,
2725
2709
  {
2726
2710
  "aria-label": "Website matching",
@@ -2730,13 +2714,13 @@ function ItemSettingsPanel({ item, port, onClose, onChanged, onPanel }) {
2730
2714
  onValueChange: (m) => void save("match", () => port.fields.updateItem(item, { uriMatchMode: m }))
2731
2715
  }
2732
2716
  ) }),
2733
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Row, { label: "Fill in browser", hint: quietHint(fillHint), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_controls10.Switch, { "aria-label": "Fill in browser", checked: hasWebsite && item.browserFillEnabled, disabled: locked || !hasWebsite, onCheckedChange: (v) => void save("fill", () => port.fields.updateItem(item, { browserFillEnabled: v })) }) }),
2717
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(VaultRow, { label: "Fill in browser", hint: quietHint(fillHint), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_controls10.Switch, { "aria-label": "Fill in browser", checked: hasWebsite && item.browserFillEnabled, disabled: locked || !hasWebsite, onCheckedChange: (v) => void save("fill", () => port.fields.updateItem(item, { browserFillEnabled: v })) }) }),
2734
2718
  promotable.map((f) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2735
- Row,
2719
+ VaultRow,
2736
2720
  {
2737
2721
  label: f.label,
2738
2722
  hint: quietHint("Encrypted, so the browser can\u2019t match it"),
2739
- actions: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_controls10.Button, { variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(GlobeGlyph, {}), disabled: locked, onClick: () => void promote(f), children: "Use as website" }),
2723
+ actions: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_controls10.Button, { variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons6.GlobeIcon, {}), disabled: locked, onClick: () => void promote(f), children: "Use as website" }),
2740
2724
  children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-muted-foreground", children: "Not a website yet" })
2741
2725
  },
2742
2726
  f.id
@@ -2744,8 +2728,8 @@ function ItemSettingsPanel({ item, port, onClose, onChanged, onPanel }) {
2744
2728
  ] }),
2745
2729
  /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
2746
2730
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_controls10.DisclosureHeader, { open: advanced, title: "Advanced", meta: item.fields.length ? `${item.fields.length} fields` : void 0, onClick: () => setAdvanced((a) => !a) }),
2747
- advanced ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Section, { children: item.fields.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Empty, { children: "No encrypted fields." }) : item.fields.map((f) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2748
- Row,
2731
+ advanced ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(VaultSection, { children: item.fields.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Empty, { children: "No encrypted fields." }) : item.fields.map((f) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2732
+ VaultRow,
2749
2733
  {
2750
2734
  label: f.label,
2751
2735
  actions: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_controls10.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SlidersGlyph, {}), "aria-label": `${f.label} settings`, onClick: () => onPanel(`field:${f.id}`) }),
@@ -2770,6 +2754,7 @@ function ItemSettingsPanel({ item, port, onClose, onChanged, onPanel }) {
2770
2754
  var import_react15 = require("react");
2771
2755
  var import_design_system10 = require("@ai-matrx/design-system");
2772
2756
  var import_controls11 = require("@ai-matrx/design-system/controls");
2757
+ var import_icons7 = require("@ai-matrx/design-system/icons");
2773
2758
 
2774
2759
  // src/generator/generate.ts
2775
2760
  var import_credential_generator = require("@ai-matrx/kit/credential-generator");
@@ -2924,7 +2909,7 @@ function PasswordGenerator({ limits: source, onUse, useLabel = "Use" }) {
2924
2909
  /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex min-h-7 items-start gap-1", children: [
2925
2910
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("code", { className: (0, import_design_system10.cn)("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" }),
2926
2911
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_controls11.Button, { variant: "quiet", icon: revealed ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(EyeOffGlyph, {}) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(EyeGlyph, {}), "aria-label": revealed ? "Hide" : "Reveal", disabled: !candidate, onClick: () => setRevealed((r) => !r) }),
2927
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_controls11.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(CopyGlyph, {}), "aria-label": "Copy", disabled: !candidate, onClick: () => void copy() }),
2912
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_controls11.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_icons7.CopyIcon, {}), "aria-label": "Copy", disabled: !candidate, onClick: () => void copy() }),
2928
2913
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_controls11.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(RefreshGlyph, {}), "aria-label": "Generate another", onClick: () => change(settings) })
2929
2914
  ] }),
2930
2915
  strength && candidate ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("p", { className: "text-xs", children: [
@@ -3051,6 +3036,7 @@ function useLocked(lock) {
3051
3036
  }
3052
3037
 
3053
3038
  // src/io/BackupPanel.tsx
3039
+ var import_format6 = require("@ai-matrx/kit/format");
3054
3040
  var import_react18 = require("react");
3055
3041
  var import_controls13 = require("@ai-matrx/design-system/controls");
3056
3042
  var import_download = require("@ai-matrx/kit/download");
@@ -3192,17 +3178,17 @@ function omissionText(o) {
3192
3178
  return `${o.count ?? "Some"} ${what}: ${o.reason.replaceAll("_", " ")}`;
3193
3179
  }
3194
3180
  function Summary({ value }) {
3195
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Section, { children: [
3196
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Row, { label: "Credentials", children: value.record_count }),
3197
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Row, { label: "Protected fields", children: value.field_count }),
3198
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Row, { label: "Files", children: value.attachment_count > 0 ? `${value.attachment_count} \xB7 ${formatBytes(value.attachment_bytes)}` : "0" })
3181
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(VaultSection, { children: [
3182
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(VaultRow, { label: "Credentials", children: value.record_count }),
3183
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(VaultRow, { label: "Protected fields", children: value.field_count }),
3184
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(VaultRow, { label: "Files", children: value.attachment_count > 0 ? `${value.attachment_count} \xB7 ${(0, import_format6.formatFileSize)(value.attachment_bytes)}` : "0" })
3199
3185
  ] });
3200
3186
  }
3201
3187
  function Omissions({ omissions, accepted, onAccepted, verb }) {
3202
3188
  if (omissions.length === 0) return null;
3203
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Section, { title: "Left out", children: [
3204
- omissions.map((o, i) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Row, { label: o.component.replaceAll("_", " "), children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "block truncate text-muted-foreground", title: omissionText(o), children: omissionText(o) }) }, `${o.component}-${o.source_item_id ?? i}`)),
3205
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Row, { label: "Accept", hint: `${verb} without these`, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_controls13.Switch, { checked: accepted, onCheckedChange: onAccepted, "aria-label": `${verb} without these` }) })
3189
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(VaultSection, { title: "Left out", children: [
3190
+ omissions.map((o, i) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(VaultRow, { label: o.component.replaceAll("_", " "), children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "block truncate text-muted-foreground", title: omissionText(o), children: omissionText(o) }) }, `${o.component}-${o.source_item_id ?? i}`)),
3191
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(VaultRow, { label: "Accept", hint: `${verb} without these`, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_controls13.Switch, { checked: accepted, onCheckedChange: onAccepted, "aria-label": `${verb} without these` }) })
3206
3192
  ] });
3207
3193
  }
3208
3194
  function BackupPanel({ port, items, onClose, onChanged }) {
@@ -3337,7 +3323,7 @@ function BackupPanel({ port, items, onClose, onChanged }) {
3337
3323
  ),
3338
3324
  mode === "backup" ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
3339
3325
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3340
- Section,
3326
+ VaultSection,
3341
3327
  {
3342
3328
  title: `${selected.size} of ${plural(items.length, "credential")}`,
3343
3329
  actions: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
@@ -3356,13 +3342,13 @@ function BackupPanel({ port, items, onClose, onChanged }) {
3356
3342
  backup ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
3357
3343
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Summary, { value: backup }),
3358
3344
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Omissions, { omissions: backup.omissions, accepted, onAccepted: setAccepted, verb: "Back up" }),
3359
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Section, { children: [
3360
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Row, { label: "Passphrase", hint: "Not saved. It can't be recovered.", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_controls13.Field, { type: "password", value: passphrase, autoComplete: "new-password", "aria-label": "Backup passphrase", onChange: (e) => setPassphrase(e.target.value) }) }),
3361
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Row, { label: "Repeat", ...mismatch ? { hint: "Doesn't match" } : {}, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_controls13.Field, { type: "password", value: repeat, autoComplete: "new-password", "aria-label": "Repeat the passphrase", onChange: (e) => setRepeat(e.target.value) }) })
3345
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(VaultSection, { children: [
3346
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(VaultRow, { label: "Passphrase", hint: "Not saved. It can't be recovered.", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_controls13.Field, { type: "password", value: passphrase, autoComplete: "new-password", "aria-label": "Backup passphrase", onChange: (e) => setPassphrase(e.target.value) }) }),
3347
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(VaultRow, { label: "Repeat", ...mismatch ? { hint: "Doesn't match" } : {}, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_controls13.Field, { type: "password", value: repeat, autoComplete: "new-password", "aria-label": "Repeat the passphrase", onChange: (e) => setRepeat(e.target.value) }) })
3362
3348
  ] })
3363
3349
  ] }) : null
3364
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children: !restorePreview ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Section, { children: [
3365
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Row, { label: "File", ...file ? { hint: file.name } : {}, children: [
3350
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children: !restorePreview ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(VaultSection, { children: [
3351
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(VaultRow, { label: "File", ...file ? { hint: file.name } : {}, children: [
3366
3352
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_controls13.Button, { variant: "outline", disabled: busy, onClick: () => fileInput.current?.click(), children: "Choose a backup" }),
3367
3353
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3368
3354
  "input",
@@ -3378,11 +3364,11 @@ function BackupPanel({ port, items, onClose, onChanged }) {
3378
3364
  }
3379
3365
  )
3380
3366
  ] }),
3381
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Row, { label: "Passphrase", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_controls13.Field, { type: "password", value: passphrase, autoComplete: "current-password", "aria-label": "Backup passphrase", onChange: (e) => setPassphrase(e.target.value) }) })
3367
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(VaultRow, { label: "Passphrase", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_controls13.Field, { type: "password", value: passphrase, autoComplete: "current-password", "aria-label": "Backup passphrase", onChange: (e) => setPassphrase(e.target.value) }) })
3382
3368
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
3383
3369
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Summary, { value: restorePreview }),
3384
3370
  !result ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Omissions, { omissions: restorePreview.omissions, accepted, onAccepted: setAccepted, verb: "Restore" }) : null,
3385
- !result ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "px-1 text-xs text-muted-foreground", children: "Restored items start disabled and restricted." }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(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__ */ (0, import_jsx_runtime16.jsx)(Row, { label: names.get(r.source_item_id) ?? "Credential", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("span", { className: r.status === "refused" || r.status === "retryable_failure" ? "text-destructive" : "text-foreground", children: [
3371
+ !result ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "px-1 text-xs text-muted-foreground", children: "Restored items start disabled and restricted." }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(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__ */ (0, import_jsx_runtime16.jsx)(VaultRow, { label: names.get(r.source_item_id) ?? "Credential", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("span", { className: r.status === "refused" || r.status === "retryable_failure" ? "text-destructive" : "text-foreground", children: [
3386
3372
  RECORD_STATUS[r.status],
3387
3373
  r.reason === "alias_conflict" ? " \xB7 name in use" : ""
3388
3374
  ] }) }, r.source_item_id)) })
@@ -3487,7 +3473,7 @@ function ExportPanel({ port, items, onClose }) {
3487
3473
  ] })
3488
3474
  ] }),
3489
3475
  children: [
3490
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Section, { children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Row, { label: "Format", hint: format?.hint, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3476
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(VaultSection, { children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(VaultRow, { label: "Format", hint: format?.hint, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3491
3477
  import_controls14.Select,
3492
3478
  {
3493
3479
  value: profile,
@@ -3500,7 +3486,7 @@ function ExportPanel({ port, items, onClose }) {
3500
3486
  }
3501
3487
  ) }) }),
3502
3488
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
3503
- Section,
3489
+ VaultSection,
3504
3490
  {
3505
3491
  title: `${selected.size} of ${plural(logins.length, "login")}`,
3506
3492
  actions: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
@@ -4571,13 +4557,13 @@ function ImportPanel({ port, host, items, organizations, onClose, onChanged, lim
4571
4557
  /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_controls15.Button, { variant: "primary", onClick: onClose, children: "Done" })
4572
4558
  ] });
4573
4559
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Panel, { title: "Import", size: "xl", onClose, footer, children: [
4574
- stage === "choose" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Section, { children: [
4575
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Row, { label: "Source", actions: help && host.openUrl ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_controls15.Button, { variant: "quiet", onClick: () => host.openUrl?.(help), children: "How to export" }) : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_controls15.Select, { value: source, options: SOURCE_OPTIONS, "aria-label": "Source", onValueChange: (s) => {
4560
+ stage === "choose" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(VaultSection, { children: [
4561
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VaultRow, { label: "Source", actions: help && host.openUrl ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_controls15.Button, { variant: "quiet", onClick: () => host.openUrl?.(help), children: "How to export" }) : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_controls15.Select, { value: source, options: SOURCE_OPTIONS, "aria-label": "Source", onValueChange: (s) => {
4576
4562
  setSource(s);
4577
4563
  setError(null);
4578
4564
  } }) }),
4579
- source === "env" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Row, { label: ".env text", hint: "Same key updates in place", top: true, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_controls15.Textarea, { 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,
4580
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Row, { label: "File", hint: fileName ?? void 0, children: [
4565
+ source === "env" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VaultRow, { label: ".env text", hint: "Same key updates in place", top: true, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_controls15.Textarea, { 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,
4566
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(VaultRow, { label: "File", hint: fileName ?? void 0, children: [
4581
4567
  /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_controls15.Button, { variant: "outline", disabled: reading, onClick: () => fileInput.current?.click(), children: reading ? "Reading\u2026" : source === "env" ? "Load a file" : "Choose a file" }),
4582
4568
  /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4583
4569
  "input",
@@ -4594,12 +4580,12 @@ function ImportPanel({ port, host, items, organizations, onClose, onChanged, lim
4594
4580
  }
4595
4581
  )
4596
4582
  ] }),
4597
- source === "env" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Row, { label: "Sandboxes", hint: "Pass these values to agent sandboxes", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_controls15.Switch, { checked: injectSandbox, onCheckedChange: setInjectSandbox, "aria-label": "Use in sandboxes" }) }) : null
4583
+ source === "env" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VaultRow, { label: "Sandboxes", hint: "Pass these values to agent sandboxes", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_controls15.Switch, { checked: injectSandbox, onCheckedChange: setInjectSandbox, "aria-label": "Use in sandboxes" }) }) : null
4598
4584
  ] }) : null,
4599
4585
  stage === "review" && draft ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
4600
- organizations.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Section, { children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Row, { label: "Save to", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_controls15.Select, { value: destination, options: destinationOptions, "aria-label": "Save to", onValueChange: (v) => draft.kind === "file" ? restart({ destination: v }) : setDestination(v) }) }) }) : null,
4586
+ organizations.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VaultSection, { children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VaultRow, { label: "Save to", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_controls15.Select, { value: destination, options: destinationOptions, "aria-label": "Save to", onValueChange: (v) => draft.kind === "file" ? restart({ destination: v }) : setDestination(v) }) }) }) : null,
4601
4587
  /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4602
- Section,
4588
+ VaultSection,
4603
4589
  {
4604
4590
  title: draft.kind === "env" ? plural(envKeys.length, "value") : summary(counts, lines.length),
4605
4591
  actions: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
@@ -4627,11 +4613,11 @@ function ImportPanel({ port, host, items, organizations, onClose, onChanged, lim
4627
4613
  )
4628
4614
  }
4629
4615
  ),
4630
- draft.kind === "file" && draft.parsed.kind === "structured" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Section, { children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Row, { label: "Visible details", hint: "Approve saving websites and public keys in the clear", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_controls15.Switch, { checked: approvedVisible, disabled: busy, onCheckedChange: setApprovedVisible, "aria-label": "Approve visible details" }) }) }) : null,
4616
+ draft.kind === "file" && draft.parsed.kind === "structured" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VaultSection, { children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VaultRow, { label: "Visible details", hint: "Approve saving websites and public keys in the clear", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_controls15.Switch, { checked: approvedVisible, disabled: busy, onCheckedChange: setApprovedVisible, "aria-label": "Approve visible details" }) }) }) : null,
4631
4617
  draft.kind === "file" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Notices, { draft }) : null,
4632
- draft.kind === "file" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(More, { children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Section, { children: [
4633
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Row, { label: "Browser fill", hint: "Needs username, password and an https address", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_controls15.Switch, { checked: browserFill, disabled: busy, onCheckedChange: (on) => restart({ browserFill: on }), "aria-label": "Browser fill" }) }),
4634
- draft.parsed.kind === "csv" ? draft.parsed.preview.headers.map((header, index) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Row, { label: header || `Column ${index + 1}`, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4618
+ draft.kind === "file" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(More, { children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(VaultSection, { children: [
4619
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VaultRow, { label: "Browser fill", hint: "Needs username, password and an https address", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_controls15.Switch, { checked: browserFill, disabled: busy, onCheckedChange: (on) => restart({ browserFill: on }), "aria-label": "Browser fill" }) }),
4620
+ draft.parsed.kind === "csv" ? draft.parsed.preview.headers.map((header, index) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VaultRow, { label: header || `Column ${index + 1}`, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
4635
4621
  import_controls15.Select,
4636
4622
  {
4637
4623
  value: draft.mapping[index] ?? "keep",
@@ -4643,16 +4629,16 @@ function ImportPanel({ port, host, items, organizations, onClose, onChanged, lim
4643
4629
  ] }) }) : null,
4644
4630
  ambiguous ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ErrorLine, { message: "Each of name, username, password, notes and one-time password can be used by one column." }) : null
4645
4631
  ] }) : null,
4646
- stage === "done" && done ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Section, { title: "Result", children: [
4647
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Row, { label: "Created", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-foreground", children: done.created.length }) }),
4648
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Row, { label: "Skipped", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-foreground", children: done.skipped }) }),
4649
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Row, { label: "Failed", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: done.failed.length > 0 ? "text-destructive" : "text-foreground", children: done.failed.length }) }),
4650
- done.untried.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Row, { label: "Not tried", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-foreground", children: done.untried.length }) }) : null,
4651
- done.withOtp > 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Row, { label: "Codes", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: "text-muted-foreground", children: [
4632
+ stage === "done" && done ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(VaultSection, { title: "Result", children: [
4633
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VaultRow, { label: "Created", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-foreground", children: done.created.length }) }),
4634
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VaultRow, { label: "Skipped", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-foreground", children: done.skipped }) }),
4635
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VaultRow, { label: "Failed", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: done.failed.length > 0 ? "text-destructive" : "text-foreground", children: done.failed.length }) }),
4636
+ done.untried.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VaultRow, { label: "Not tried", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-foreground", children: done.untried.length }) }) : null,
4637
+ done.withOtp > 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VaultRow, { label: "Codes", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: "text-muted-foreground", children: [
4652
4638
  plural(done.withOtp, "login"),
4653
4639
  " still need the one-time password added."
4654
4640
  ] }) }) : null,
4655
- done.failed.map((f) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Row, { label: f.title, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "block truncate text-destructive", title: f.reason, children: f.reason }) }, f.key))
4641
+ done.failed.map((f) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VaultRow, { label: f.title, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "block truncate text-destructive", title: f.reason, children: f.reason }) }, f.key))
4656
4642
  ] }) : null,
4657
4643
  /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ErrorLine, { message: error })
4658
4644
  ] });
@@ -4712,11 +4698,13 @@ var import_controls21 = require("@ai-matrx/design-system/controls");
4712
4698
  var import_confirm_opener9 = require("@ai-matrx/kit/confirm-opener");
4713
4699
 
4714
4700
  // src/activity/FilesSection.tsx
4701
+ var import_format7 = require("@ai-matrx/kit/format");
4715
4702
  var import_react21 = require("react");
4716
4703
  var import_controls16 = require("@ai-matrx/design-system/controls");
4717
4704
  var import_design_system13 = require("@ai-matrx/design-system");
4718
4705
  var import_confirm_opener6 = require("@ai-matrx/kit/confirm-opener");
4719
4706
  var import_download3 = require("@ai-matrx/kit/download");
4707
+ var import_icons8 = require("@ai-matrx/design-system/icons");
4720
4708
  var import_jsx_runtime20 = require("react/jsx-runtime");
4721
4709
  var messageOf2 = (e, fallback) => wasCancelled(e) ? null : e instanceof Error ? e.message : fallback;
4722
4710
  var TOO_BIG = "Files over 25 MB can't be stored.";
@@ -4775,7 +4763,7 @@ function FilesSection({ item, port, editing, onChanged }) {
4775
4763
  onDragLeave: canEdit ? () => setDragging(false) : void 0,
4776
4764
  onDrop: canEdit ? drop : void 0,
4777
4765
  children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
4778
- Section,
4766
+ VaultSection,
4779
4767
  {
4780
4768
  title: "Files",
4781
4769
  actions: canEdit ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(PlusGlyph, {}), disabled: busy !== null, onClick: () => picker.current?.click(), children: "Add file" }) : void 0,
@@ -4786,11 +4774,11 @@ function FilesSection({ item, port, editing, onChanged }) {
4786
4774
  } }) : null,
4787
4775
  item.attachments.map(
4788
4776
  (a) => canEdit ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(EditableFile, { port, item, file: a, busy, run, onDownload: () => void download(a), onTooBig: () => setError(TOO_BIG) }, a.id) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4789
- Row,
4777
+ VaultRow,
4790
4778
  {
4791
4779
  label: a.label,
4792
4780
  hint: a.description || void 0,
4793
- actions: a.handling === "sealed" ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Badge, { icon: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(LockGlyph, {}), children: "Sealed" }) : canDownload(item, a) ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DownloadGlyph, {}), "aria-label": `Download ${a.fileName}`, disabled: busy !== null, onClick: () => void download(a) }) : null,
4781
+ actions: a.handling === "sealed" ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Badge, { icon: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(LockGlyph, {}), children: "Sealed" }) : canDownload(item, a) ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_icons8.DownloadIcon, {}), "aria-label": `Download ${a.fileName}`, disabled: busy !== null, onClick: () => void download(a) }) : null,
4794
4782
  children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(FileName, { file: a })
4795
4783
  },
4796
4784
  a.id
@@ -4816,12 +4804,12 @@ function EditableFile({ port, item: it, file: a, busy: b, run: go, onDownload, o
4816
4804
  }
4817
4805
  return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
4818
4806
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4819
- Row,
4807
+ VaultRow,
4820
4808
  {
4821
4809
  label: a.label,
4822
4810
  hint: a.description || void 0,
4823
4811
  actions: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
4824
- canDownload(it, a) ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DownloadGlyph, {}), "aria-label": `Download ${a.fileName}`, disabled: b !== null, onClick: onDownload }) : null,
4812
+ canDownload(it, a) ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_icons8.DownloadIcon, {}), "aria-label": `Download ${a.fileName}`, disabled: b !== null, onClick: onDownload }) : null,
4825
4813
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(PencilGlyph, {}), "aria-label": `Edit ${a.label}`, pressed: open, disabled: b !== null, onClick: () => setOpen((o) => !o) }),
4826
4814
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(UploadGlyph, {}), "aria-label": `Replace ${a.fileName}`, disabled: b !== null, onClick: () => replacer.current?.click() }),
4827
4815
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TrashGlyph, {}), "aria-label": `Delete ${a.label}`, disabled: b !== null, onClick: () => void remove() }),
@@ -4852,7 +4840,7 @@ function EditableFile({ port, item: it, file: a, busy: b, run: go, onDownload, o
4852
4840
  function FileName({ file }) {
4853
4841
  return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "flex min-w-0 items-center gap-2", children: [
4854
4842
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "truncate", children: file.fileName }),
4855
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground", children: formatBytes(file.sizeBytes) })
4843
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground", children: (0, import_format7.formatFileSize)(file.sizeBytes) })
4856
4844
  ] });
4857
4845
  }
4858
4846
  function Protection({ value, locked, onChange }) {
@@ -4875,13 +4863,13 @@ function NewFile({ file, busy, onAdd, onCancel }) {
4875
4863
  await onAdd({ label: label.trim(), description: description.trim() || null, handling });
4876
4864
  }
4877
4865
  return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
4878
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Row, { label: "New file", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "flex min-w-0 items-center gap-2", children: [
4866
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(VaultRow, { label: "New file", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "flex min-w-0 items-center gap-2", children: [
4879
4867
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "truncate", children: file.name }),
4880
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground", children: formatBytes(file.size) })
4868
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground", children: (0, import_format7.formatFileSize)(file.size) })
4881
4869
  ] }) }),
4882
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Row, { label: "Name", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Field, { "aria-label": "Name", value: label, onChange: (e) => setLabel(e.target.value) }) }),
4883
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Row, { label: "Purpose", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Field, { "aria-label": "Purpose", placeholder: "What it is for", value: description, onChange: (e) => setDescription(e.target.value) }) }),
4884
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Row, { label: "Protection", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Protection, { value: handling, locked: false, onChange: setHandling }) }),
4870
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(VaultRow, { label: "Name", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Field, { "aria-label": "Name", value: label, onChange: (e) => setLabel(e.target.value) }) }),
4871
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(VaultRow, { label: "Purpose", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Field, { "aria-label": "Purpose", placeholder: "What it is for", value: description, onChange: (e) => setDescription(e.target.value) }) }),
4872
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(VaultRow, { label: "Protection", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Protection, { value: handling, locked: false, onChange: setHandling }) }),
4885
4873
  /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex justify-end gap-2 px-3 py-1 sm:px-4", children: [
4886
4874
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Button, { variant: "quiet", disabled: busy, onClick: onCancel, children: "Cancel" }),
4887
4875
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Button, { variant: "primary", disabled: busy || !label.trim(), onClick: () => void add(), children: busy ? "Adding\u2026" : "Add file" })
@@ -4899,10 +4887,10 @@ function FileDetailsRows({ file, busy, onSave, onCancel }) {
4899
4887
  await onSave({ label: label.trim(), description: description.trim() || null, fileName: fileName.trim(), handling });
4900
4888
  }
4901
4889
  return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
4902
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Row, { label: "Name", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Field, { "aria-label": "Name", value: label, onChange: (e) => setLabel(e.target.value) }) }),
4903
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Row, { label: "Purpose", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Field, { "aria-label": "Purpose", placeholder: "What it is for", value: description, onChange: (e) => setDescription(e.target.value) }) }),
4904
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Row, { label: "File name", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Field, { "aria-label": "File name", value: fileName, onChange: (e) => setFileName(e.target.value) }) }),
4905
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Row, { label: "Protection", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Protection, { value: handling, locked: file.handling === "sealed", onChange: setHandling }) }),
4890
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(VaultRow, { label: "Name", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Field, { "aria-label": "Name", value: label, onChange: (e) => setLabel(e.target.value) }) }),
4891
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(VaultRow, { label: "Purpose", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Field, { "aria-label": "Purpose", placeholder: "What it is for", value: description, onChange: (e) => setDescription(e.target.value) }) }),
4892
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(VaultRow, { label: "File name", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Field, { "aria-label": "File name", value: fileName, onChange: (e) => setFileName(e.target.value) }) }),
4893
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(VaultRow, { label: "Protection", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Protection, { value: handling, locked: file.handling === "sealed", onChange: setHandling }) }),
4906
4894
  /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex justify-end gap-2 px-3 py-1 sm:px-4", children: [
4907
4895
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Button, { variant: "quiet", disabled: busy, onClick: onCancel, children: "Cancel" }),
4908
4896
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Button, { variant: "primary", disabled: busy || !changed || !label.trim() || !fileName.trim(), onClick: () => void save(), children: busy ? "Saving\u2026" : "Save" })
@@ -4921,6 +4909,7 @@ function confirmSeal(label) {
4921
4909
  // src/fields/RecoveryCodesRow.tsx
4922
4910
  var import_react22 = require("react");
4923
4911
  var import_controls17 = require("@ai-matrx/design-system/controls");
4912
+ var import_icons9 = require("@ai-matrx/design-system/icons");
4924
4913
  var import_jsx_runtime21 = require("react/jsx-runtime");
4925
4914
  var MASK4 = "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
4926
4915
  var say2 = (e, fallback) => e instanceof Error && e.message ? e.message : fallback;
@@ -4961,7 +4950,7 @@ function RecoveryCodesRow({ item, field, port, onChanged }) {
4961
4950
  };
4962
4951
  if (draft !== null) {
4963
4952
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
4964
- Row,
4953
+ VaultRow,
4965
4954
  {
4966
4955
  label: "Recovery codes",
4967
4956
  top: true,
@@ -4981,7 +4970,7 @@ function RecoveryCodesRow({ item, field, port, onChanged }) {
4981
4970
  }
4982
4971
  if (!field) {
4983
4972
  if (!canEdit) return null;
4984
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Row, { label: "Recovery codes", actions: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_controls17.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PlusGlyph, {}), "aria-label": "Add recovery codes", onClick: () => setDraft("") }), children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-muted-foreground", children: "None" }) });
4973
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(VaultRow, { label: "Recovery codes", actions: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_controls17.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(PlusGlyph, {}), "aria-label": "Add recovery codes", onClick: () => setDraft("") }), children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-muted-foreground", children: "None" }) });
4985
4974
  }
4986
4975
  const sealed = field.handling === "sealed";
4987
4976
  const canSee = !sealed && item.capabilities.canReveal;
@@ -5003,7 +4992,7 @@ function RecoveryCodesRow({ item, field, port, onChanged }) {
5003
4992
  });
5004
4993
  };
5005
4994
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
5006
- Row,
4995
+ VaultRow,
5007
4996
  {
5008
4997
  label: "Recovery codes",
5009
4998
  top: codes !== null,
@@ -5014,7 +5003,7 @@ function RecoveryCodesRow({ item, field, port, onChanged }) {
5014
5003
  children: sealed ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_controls17.Badge, { icon: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LockGlyph, {}), children: "Sealed" }) : codes ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("ul", { className: "flex flex-col gap-0.5", "aria-label": "Recovery codes", children: [
5015
5004
  codes.map((code, i) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("li", { className: "flex min-h-7 items-center gap-1", children: [
5016
5005
  /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("code", { className: "min-w-0 flex-1 break-all font-mono text-sm text-foreground", children: code }),
5017
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_controls17.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CopyGlyph, {}), "aria-label": `Copy code ${i + 1}`, onClick: () => void copyValue2(code, "Recovery code") }),
5006
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_controls17.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_icons9.CopyIcon, {}), "aria-label": `Copy code ${i + 1}`, onClick: () => void copyValue2(code, "Recovery code") }),
5018
5007
  canEdit ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_controls17.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CheckGlyph, {}), disabled: busy, onClick: () => void markUsed(i), children: "Mark used" }) : null
5019
5008
  ] }, `${i}-${code}`)),
5020
5009
  error ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("li", { role: "alert", className: "text-xs text-destructive", children: error }) : null
@@ -5023,33 +5012,17 @@ function RecoveryCodesRow({ item, field, port, onChanged }) {
5023
5012
  );
5024
5013
  }
5025
5014
 
5015
+ // src/ItemPane.tsx
5016
+ var import_icons11 = require("@ai-matrx/design-system/icons");
5017
+ var import_drafts = require("@ai-matrx/kit/drafts");
5018
+
5026
5019
  // src/draft-keep.ts
5027
5020
  var PREFIX = "matrx.vault.draft:";
5028
5021
  function draftKey(itemId, definitionKey) {
5029
5022
  return `${PREFIX}${itemId ?? `new:${definitionKey ?? "custom"}`}`;
5030
5023
  }
5031
- function keepDraft(key, basedOn, d) {
5032
- const kept = { basedOn, draft: { name: d.name, description: d.description, tags: d.tags, loginUrls: d.loginUrls, notes: d.notes, custom: d.custom } };
5033
- try {
5034
- globalThis.sessionStorage?.setItem(key, JSON.stringify(kept));
5035
- } catch {
5036
- }
5037
- }
5038
- function readKeptDraft(key, basedOn) {
5039
- try {
5040
- const raw = globalThis.sessionStorage?.getItem(key);
5041
- if (!raw) return null;
5042
- const kept = JSON.parse(raw);
5043
- return kept.basedOn === basedOn ? kept.draft : null;
5044
- } catch {
5045
- return null;
5046
- }
5047
- }
5048
- function dropKeptDraft(key) {
5049
- try {
5050
- globalThis.sessionStorage?.removeItem(key);
5051
- } catch {
5052
- }
5024
+ function keptFieldsOf(d) {
5025
+ return { name: d.name, description: d.description, tags: d.tags, loginUrls: d.loginUrls, notes: d.notes, custom: d.custom };
5053
5026
  }
5054
5027
 
5055
5028
  // src/extension/page-logic.ts
@@ -5196,6 +5169,7 @@ var import_react26 = require("react");
5196
5169
  var import_confirm_opener8 = require("@ai-matrx/kit/confirm-opener");
5197
5170
  var import_controls20 = require("@ai-matrx/design-system/controls");
5198
5171
  var import_design_system15 = require("@ai-matrx/design-system");
5172
+ var import_icons10 = require("@ai-matrx/design-system/icons");
5199
5173
 
5200
5174
  // src/sharing/logic.ts
5201
5175
  var LEVEL_OPTIONS = [
@@ -5227,7 +5201,7 @@ function copyRefusal(message2) {
5227
5201
  return /duplicate/i.test(message2) ? "There is already a copy of this item there." : null;
5228
5202
  }
5229
5203
  var isPasskey = (item) => item.definitionKey === "native_passkey" || item.definitionKey === "passkey_private";
5230
- function moveConsequence(item, to) {
5204
+ function itemMoveConsequence(item, to) {
5231
5205
  if (item.authenticator) return "One-time password stays behind; set it up again";
5232
5206
  return to ? "Its members get access; people you shared with lose it" : "Only you; organization members lose access";
5233
5207
  }
@@ -5317,7 +5291,7 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
5317
5291
  const to = destinationOf(moveChoice.value);
5318
5292
  const ok = await (0, import_confirm_opener7.confirm)({
5319
5293
  title: `Move to ${moveChoice.label}?`,
5320
- description: `"${item.name}" stays the same item, so everything using it keeps working. ${moveConsequence(item, to)}.`,
5294
+ description: `"${item.name}" stays the same item, so everything using it keeps working. ${itemMoveConsequence(item, to)}.`,
5321
5295
  confirmLabel: "Move"
5322
5296
  });
5323
5297
  if (!ok) return;
@@ -5353,17 +5327,17 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
5353
5327
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(StatusLine, { error, notice }),
5354
5328
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_controls19.Button, { variant: "outline", className: "ml-auto", onClick: onClose, children: "Close" })
5355
5329
  ] }),
5356
- children: nothing ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Section, { children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Empty, { children: passkey ? "A passkey stays where it was created." : "Only the owner can move or give this item." }) }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(Section, { children: [
5330
+ children: nothing ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(VaultSection, { children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Empty, { children: passkey ? "A passkey stays where it was created." : "Only the owner can move or give this item." }) }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(VaultSection, { children: [
5357
5331
  canMove && moves.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5358
- Row,
5332
+ VaultRow,
5359
5333
  {
5360
5334
  label: "Move to",
5361
- hint: moveChoice ? moveConsequence(item, destinationOf(moveChoice.value)) : void 0,
5335
+ hint: moveChoice ? itemMoveConsequence(item, destinationOf(moveChoice.value)) : void 0,
5362
5336
  actions: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_controls19.Button, { variant: "outline", disabled: busy !== null || !moveChoice, onClick: () => void move(), children: "Move" }),
5363
5337
  children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_controls19.Select, { className: "w-full", "aria-label": "Move to", value: moveTo || NONE, onValueChange: (v) => setMoveTo(v === NONE ? "" : v), options: [{ value: NONE, label: "Choose where" }, ...moves] })
5364
5338
  }
5365
5339
  ) : null,
5366
- canGive ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Row, { label: "Give to", hint: "You lose all access; your shares end", actions: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_controls19.Button, { variant: "danger", disabled: busy !== null || !isEmail(email), onClick: () => void give(), children: "Give" }), children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5340
+ canGive ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(VaultRow, { label: "Give to", hint: "You lose all access; your shares end", actions: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_controls19.Button, { variant: "danger", disabled: busy !== null || !isEmail(email), onClick: () => void give(), children: "Give" }), children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5367
5341
  import_controls19.Field,
5368
5342
  {
5369
5343
  className: "w-full",
@@ -5377,7 +5351,7 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
5377
5351
  onChange: (e) => setEmail(e.target.value)
5378
5352
  }
5379
5353
  ) }) : null,
5380
- canCopy && copies.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Row, { label: "Copy to", hint: "A separate item; edits no longer sync", actions: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_controls19.Button, { variant: "outline", disabled: busy !== null || !copyChoice, onClick: () => void copy(), children: "Copy" }), children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_controls19.Select, { className: "w-full", "aria-label": "Copy to", value: copyTo || NONE, onValueChange: (v) => setCopyTo(v === NONE ? "" : v), options: [{ value: NONE, label: "Choose where" }, ...copies] }) }) : null
5354
+ canCopy && copies.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(VaultRow, { label: "Copy to", hint: "A separate item; edits no longer sync", actions: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_controls19.Button, { variant: "outline", disabled: busy !== null || !copyChoice, onClick: () => void copy(), children: "Copy" }), children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_controls19.Select, { className: "w-full", "aria-label": "Copy to", value: copyTo || NONE, onValueChange: (v) => setCopyTo(v === NONE ? "" : v), options: [{ value: NONE, label: "Choose where" }, ...copies] }) }) : null
5381
5355
  ] })
5382
5356
  }
5383
5357
  );
@@ -5459,7 +5433,7 @@ function SharePanel({ item, port, organizations, onClose, onChanged }) {
5459
5433
  }
5460
5434
  };
5461
5435
  if (!item.capabilities.canManage) {
5462
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Panel, { title: "Share", size: "md", onClose, footer: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Button, { variant: "primary", onClick: onClose, children: "Done" }), children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Section, { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Empty, { children: "Only the owner can change who has access." }) }) });
5436
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Panel, { title: "Share", size: "md", onClose, footer: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Button, { variant: "primary", onClick: onClose, children: "Done" }), children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(VaultSection, { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Empty, { children: "Only the owner can change who has access." }) }) });
5463
5437
  }
5464
5438
  return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
5465
5439
  Panel,
@@ -5472,9 +5446,9 @@ function SharePanel({ item, port, organizations, onClose, onChanged }) {
5472
5446
  /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Button, { variant: "primary", className: "ml-auto", onClick: onClose, children: "Done" })
5473
5447
  ] }),
5474
5448
  children: [
5475
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Section, { title: "Who has access", children: [
5449
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(VaultSection, { title: "Who has access", children: [
5476
5450
  isOrg ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(AccessLine, { glyph: BuildingGlyph, who: `${orgName} admins`, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "px-2 text-sm text-muted-foreground", children: "Full access" }) }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(AccessLine, { glyph: PersonGlyph, who: "You", meta: "Owner", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "px-2 text-sm text-muted-foreground", children: "Full access" }) }),
5477
- isOrg ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(AccessLine, { glyph: UsersGlyph, who: `${orgName} members`, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5451
+ isOrg ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(AccessLine, { glyph: import_icons10.UsersIcon, who: `${orgName} members`, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5478
5452
  import_controls20.Select,
5479
5453
  {
5480
5454
  variant: "inline",
@@ -5535,7 +5509,7 @@ function IntoOrganization({ item, port, organizations, grants, onShared }) {
5535
5509
  const [level, setLevel] = (0, import_react26.useState)("use");
5536
5510
  const chosen = open.find((o) => o.id === target);
5537
5511
  if (item.owner.kind !== "me") return null;
5538
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Section, { title: "Share into organization", children: open.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
5512
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(VaultSection, { title: "Share into organization", children: open.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
5539
5513
  /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex min-h-11 items-center gap-2 px-3 sm:px-4", children: [
5540
5514
  /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(BuildingGlyph, { className: "size-4 shrink-0 text-muted-foreground" }),
5541
5515
  /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Select, { 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 }))] }),
@@ -5585,7 +5559,7 @@ function MemberAccess({ port, organizationId, organizationName }) {
5585
5559
  const effective = await run(userId, () => port.sharing.setMemberAccess(organizationId, userId, access));
5586
5560
  if (effective) setList((l) => l ? { ...l, members: l.members.map((m) => m.userId === userId ? { ...m, access, effective } : m) } : l);
5587
5561
  };
5588
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Section, { title: `${organizationName} vault access`, children: [
5562
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(VaultSection, { title: `${organizationName} vault access`, children: [
5589
5563
  loadError ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Empty, { children: loadError }) : list === null ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.RegionSkeleton, { shape: "rows", count: 3, "aria-label": "Loading member access", className: "px-3 sm:px-4" }) : list.members.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Empty, { children: "No members yet." }) : list.members.map((m) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(AccessLine, { glyph: PersonGlyph, who: m.email || m.userId, meta: m.role, children: m.effective === "admin" ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "px-2 text-sm text-muted-foreground", children: MEMBER_ACCESS_LABEL.admin }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5590
5564
  import_controls20.Select,
5591
5565
  {
@@ -5620,7 +5594,7 @@ function SharingSummary({ item, port, className }) {
5620
5594
  }
5621
5595
 
5622
5596
  // src/ItemPane.tsx
5623
- var import_format4 = require("@ai-matrx/kit/format");
5597
+ var import_format8 = require("@ai-matrx/kit/format");
5624
5598
  var import_jsx_runtime26 = require("react/jsx-runtime");
5625
5599
  var USERNAME_KEYS = /^(username|user_name|email|login|username_or_email|account_email)$/;
5626
5600
  function ItemPane(props) {
@@ -5661,7 +5635,7 @@ function ItemPane(props) {
5661
5635
  if (was && was.id === id && was.mode === mode && editing) {
5662
5636
  setDraft((d) => rebaseDraft(was.base, base, d));
5663
5637
  } else {
5664
- const kept = editing ? readKeptDraft(keepKey, item?.updatedAt ?? "new") : null;
5638
+ const kept = editing ? (0, import_drafts.readKeptDraft)(keepKey, { basedOn: item?.updatedAt ?? "new" })?.value ?? null : null;
5665
5639
  setDraft(kept ? { ...base, ...kept } : base);
5666
5640
  setTagsText((kept ?? base).tags.join(", "));
5667
5641
  setError(null);
@@ -5676,8 +5650,8 @@ function ItemPane(props) {
5676
5650
  (0, import_react27.useEffect)(() => onDirty(dirty), [dirty, onDirty]);
5677
5651
  const keepKey = draftKey(item?.id ?? null, definition?.key ?? item?.definitionKey ?? null);
5678
5652
  (0, import_react27.useEffect)(() => {
5679
- if (editing && dirty) keepDraft(keepKey, item?.updatedAt ?? "new", draft);
5680
- else if (!editing) dropKeptDraft(keepKey);
5653
+ if (editing && dirty) (0, import_drafts.keepDraft)(keepKey, keptFieldsOf(draft), { basedOn: item?.updatedAt ?? "new" });
5654
+ else if (!editing) (0, import_drafts.dropKeptDraft)(keepKey);
5681
5655
  }, [editing, dirty, draft, keepKey, item?.updatedAt]);
5682
5656
  (0, import_react27.useEffect)(() => {
5683
5657
  if (!editing || !item) return;
@@ -5714,7 +5688,7 @@ function ItemPane(props) {
5714
5688
  if (item) {
5715
5689
  const r = await port.save(item, definition, out);
5716
5690
  const [next, n] = await withOtp(r.item, r.notice);
5717
- dropKeptDraft(keepKey);
5691
+ (0, import_drafts.dropKeptDraft)(keepKey);
5718
5692
  onSaved(next, false, n);
5719
5693
  } else if (definition && owner === "person") {
5720
5694
  const secretKey = declared.find((f) => f.storage === "encrypted" && f.kind === "secret")?.key ?? null;
@@ -5724,7 +5698,7 @@ function ItemPane(props) {
5724
5698
  } else if (definition) {
5725
5699
  const r = await port.create(definition, owner === "me" ? null : owner, out);
5726
5700
  const [next, n] = await withOtp(r.item, r.notice);
5727
- dropKeptDraft(keepKey);
5701
+ (0, import_drafts.dropKeptDraft)(keepKey);
5728
5702
  onSaved(next, true, n);
5729
5703
  }
5730
5704
  } catch (e) {
@@ -5763,7 +5737,7 @@ function ItemPane(props) {
5763
5737
  const viewCustom = (item?.custom ?? []).filter((c) => !declaredKeys.has(c.key) && c.key !== MFA_METHOD_KEY && !isAuthenticatorStorage(c.key));
5764
5738
  const isLogin = (item?.definitionKey ?? definition?.key) === "website_login" || (item?.definitionKey ?? definition?.key) === "username_password";
5765
5739
  const typeLabel = definition?.label ?? item?.definitionLabel ?? "";
5766
- const shownOwner = mode === "new" ? owner === "me" ? { label: "Personal", glyph: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PersonGlyph, {}) } : owner === "person" ? { label: "Someone else", glyph: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(SendGlyph, {}) } : { label: organizations.find((o) => o.id === owner)?.name ?? "Organization", glyph: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(BuildingGlyph, {}) } : item ? { label: item.owner.label, glyph: item.owner.kind === "me" ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PersonGlyph, {}) : item.owner.kind === "organization" ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(BuildingGlyph, {}) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(UsersGlyph, {}) } : null;
5740
+ const shownOwner = mode === "new" ? owner === "me" ? { label: "Personal", glyph: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PersonGlyph, {}) } : owner === "person" ? { label: "Someone else", glyph: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(SendGlyph, {}) } : { label: organizations.find((o) => o.id === owner)?.name ?? "Organization", glyph: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(BuildingGlyph, {}) } : item ? { label: item.owner.label, glyph: item.owner.kind === "me" ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PersonGlyph, {}) : item.owner.kind === "organization" ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(BuildingGlyph, {}) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_icons11.UsersIcon, {}) } : null;
5767
5741
  const tagsVisible = showTags || draft.tags.length > 0 || tagsText !== "";
5768
5742
  const descriptionVisible = showDescription || draft.description !== "";
5769
5743
  const header = /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("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: [
@@ -5820,7 +5794,7 @@ function ItemPane(props) {
5820
5794
  "Send securely"
5821
5795
  ] }) : null,
5822
5796
  /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_design_system16.DropdownMenuItem, { onSelect: () => onPanel("history"), children: [
5823
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(HistoryGlyph, { className: "size-4" }),
5797
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_icons11.HistoryIcon, { className: "size-4" }),
5824
5798
  "Password history"
5825
5799
  ] }),
5826
5800
  /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_design_system16.DropdownMenuItem, { onSelect: () => onPanel("activity"), children: [
@@ -5828,7 +5802,7 @@ function ItemPane(props) {
5828
5802
  "Activity"
5829
5803
  ] }),
5830
5804
  canEdit ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_design_system16.DropdownMenuItem, { onSelect: () => onPanel("settings"), children: [
5831
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(SettingsGlyph, { className: "size-4" }),
5805
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_icons11.SettingsIcon, { className: "size-4" }),
5832
5806
  "Settings"
5833
5807
  ] }) : null,
5834
5808
  canManage ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
@@ -5848,8 +5822,8 @@ function ItemPane(props) {
5848
5822
  error ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { role: "alert", className: "border-b border-border bg-muted px-5 py-2 text-sm text-destructive", children: error }) : null,
5849
5823
  notice && !editing ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { role: "status", className: "border-b border-border bg-muted px-5 py-2 text-sm text-warning", children: notice }) : null,
5850
5824
  /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "min-h-0 flex-1 overflow-y-auto", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("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__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
5851
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Section, { children: [
5852
- mode === "new" ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Row, { label: "Save to", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5825
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(VaultSection, { children: [
5826
+ mode === "new" ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(VaultRow, { label: "Save to", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5853
5827
  import_controls21.OptionCombobox,
5854
5828
  {
5855
5829
  value: owner,
@@ -5870,7 +5844,7 @@ function ItemPane(props) {
5870
5844
  /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(EditRow, { label: "Name", value: draft.name, onChange: (v) => patch({ name: v }), placeholder: "Name", autoFocus: mode === "new" }),
5871
5845
  mode === "new" && owner === "person" ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
5872
5846
  /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(EditRow, { label: "Their email", value: recipient, placeholder: "name@company.com", inputMode: "email", onChange: setRecipient }),
5873
- declared.some((f) => f.storage === "encrypted" && f.kind === "secret") ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Row, { label: "Password", hint: "You never see it", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.Switch, { checked: generatePrivately, onCheckedChange: setGeneratePrivately, "aria-label": "Generate the password privately" }) }) : null
5847
+ declared.some((f) => f.storage === "encrypted" && f.kind === "secret") ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(VaultRow, { label: "Password", hint: "You never see it", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.Switch, { checked: generatePrivately, onCheckedChange: setGeneratePrivately, "aria-label": "Generate the password privately" }) }) : null
5874
5848
  ] }) : null,
5875
5849
  declared.map((f) => {
5876
5850
  const existing = item?.fields.find((x) => x.key === f.key);
@@ -5890,7 +5864,7 @@ function ItemPane(props) {
5890
5864
  actions: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
5891
5865
  hidden && existing?.handling === "revealable" && item?.capabilities.canReveal ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(EyeGlyph, {}), "aria-label": `Show current ${f.label}`, onClick: () => void loadForEdit(f.key) }) : null,
5892
5866
  secretKind ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(GenerateButton, { onUse: (v) => setValue(f.key, v) }) : null,
5893
- existing ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(SettingsGlyph, {}), "aria-label": `${f.label} settings`, onClick: () => onPanel(`field:${existing.id}`) }) : null
5867
+ existing ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_icons11.SettingsIcon, {}), "aria-label": `${f.label} settings`, onClick: () => onPanel(`field:${existing.id}`) }) : null
5894
5868
  ] })
5895
5869
  },
5896
5870
  f.key
@@ -5908,7 +5882,7 @@ function ItemPane(props) {
5908
5882
  removeLabel: `Delete ${f.label}`,
5909
5883
  actions: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
5910
5884
  f.handling === "revealable" && !(f.key in loaded) && item?.capabilities.canReveal ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(EyeGlyph, {}), "aria-label": `Show current ${f.label}`, onClick: () => void loadForEdit(f.key) }) : null,
5911
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(SettingsGlyph, {}), "aria-label": `${f.label} settings`, onClick: () => onPanel(`field:${f.id}`) })
5885
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_icons11.SettingsIcon, {}), "aria-label": `${f.label} settings`, onClick: () => onPanel(`field:${f.id}`) })
5912
5886
  ] })
5913
5887
  },
5914
5888
  f.id
@@ -5941,9 +5915,9 @@ function ItemPane(props) {
5941
5915
  /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TotpEditRow, { value: draft.authenticator, onChange: (v) => patch({ authenticator: v }), hasExisting: Boolean(item?.authenticator), item, port, onEnrolled: onChanged }),
5942
5916
  item && isLogin && !item.authenticator ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TwoFactorMethodRow, { port, item, onChanged }) : null
5943
5917
  ] }),
5944
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Section, { children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(EditRow, { label: "Notes", value: draft.notes, multiline: true, placeholder: "Anything worth remembering", onChange: (v) => patch({ notes: v }) }) }),
5918
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(VaultSection, { children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(EditRow, { label: "Notes", value: draft.notes, multiline: true, placeholder: "Anything worth remembering", onChange: (v) => patch({ notes: v }) }) }),
5945
5919
  /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
5946
- Section,
5920
+ VaultSection,
5947
5921
  {
5948
5922
  title: "More",
5949
5923
  actions: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_design_system16.DropdownMenu, { children: [
@@ -5977,7 +5951,7 @@ function ItemPane(props) {
5977
5951
  ),
5978
5952
  filesProps ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(FilesSection, { ...filesProps, editing: true }) : null
5979
5953
  ] }) : item ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
5980
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Section, { children: [
5954
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(VaultSection, { children: [
5981
5955
  declared.map((f) => {
5982
5956
  if (f.storage === "metadata") {
5983
5957
  const v = metaValue(f.key);
@@ -5992,18 +5966,18 @@ function ItemPane(props) {
5992
5966
  item.authenticator ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TotpRow, { port, item, onChanged }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AddRow, { label: "One-time password", onAdd: canEdit ? () => onMode("edit") : null, children: "Set up" }),
5993
5967
  !item.authenticator && item.custom.some((c) => c.key === MFA_METHOD_KEY && c.value) ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TwoFactorMethodRow, { port, item, onChanged }) : null
5994
5968
  ] }),
5995
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Section, { children: item.notes ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PlainRow, { label: "Notes", value: item.notes, multiline: true }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AddRow, { label: "Notes", onAdd: canEdit ? () => onMode("edit") : null, children: "Add notes" }) }),
5996
- item.description || item.tags.length > 0 || viewCustom.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Section, { title: "More", children: [
5969
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(VaultSection, { children: item.notes ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PlainRow, { label: "Notes", value: item.notes, multiline: true }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AddRow, { label: "Notes", onAdd: canEdit ? () => onMode("edit") : null, children: "Add notes" }) }),
5970
+ item.description || item.tags.length > 0 || viewCustom.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(VaultSection, { title: "More", children: [
5997
5971
  item.description ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PlainRow, { label: "Description", value: item.description }) : null,
5998
- item.tags.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Row, { label: "Tags", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "flex flex-wrap gap-1", children: item.tags.map((t) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "rounded-md bg-muted px-1.5 py-0.5 text-xs", children: t }, t)) }) }) : null,
5972
+ item.tags.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(VaultRow, { label: "Tags", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "flex flex-wrap gap-1", children: item.tags.map((t) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "rounded-md bg-muted px-1.5 py-0.5 text-xs", children: t }, t)) }) }) : null,
5999
5973
  viewCustom.map((c) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PlainRow, { label: c.label, value: c.value, openUrl: host.openUrl }, c.key))
6000
5974
  ] }) : null,
6001
5975
  filesProps ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(FilesSection, { ...filesProps, editing: false }) : null,
6002
5976
  /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("p", { className: (0, import_design_system17.cn)("px-1 text-xs text-muted-foreground"), children: [
6003
5977
  "Modified ",
6004
- (0, import_format4.formatAbsoluteDate)(item.updatedAt, DAY_FORMAT, ""),
5978
+ (0, import_format8.formatAbsoluteDate)(item.updatedAt, DAY_FORMAT, ""),
6005
5979
  " \xB7 Created ",
6006
- (0, import_format4.formatAbsoluteDate)(item.createdAt, DAY_FORMAT, "")
5980
+ (0, import_format8.formatAbsoluteDate)(item.createdAt, DAY_FORMAT, "")
6007
5981
  ] })
6008
5982
  ] }) : null }) })
6009
5983
  ] }) });
@@ -6119,7 +6093,7 @@ function ListRow({ item, family, port, on, onSelect, withOwner }) {
6119
6093
  // src/lists/TrashView.tsx
6120
6094
  var import_react30 = require("react");
6121
6095
  var import_controls24 = require("@ai-matrx/design-system/controls");
6122
- var import_format5 = require("@ai-matrx/kit/format");
6096
+ var import_format9 = require("@ai-matrx/kit/format");
6123
6097
 
6124
6098
  // src/lists/logic.ts
6125
6099
  var ENTITY_TYPE = "credential_item";
@@ -6243,13 +6217,13 @@ function RestorePanel({ lists, item, restore, onClose }) {
6243
6217
  refused ? null : /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_controls23.Button, { variant: "primary", icon: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(RestoreGlyph, {}), disabled: busy || loading || lists.preview !== void 0 && preview === null, onClick: () => void run(), children: busy ? "Restoring\u2026" : "Restore" })
6244
6218
  ] }),
6245
6219
  children: [
6246
- loading ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Section, { children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Empty, { children: "Checking what comes back\u2026" }) }) : preview?.supported ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(Section, { title: "Comes back", children: [
6247
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Row, { label: "Fields", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "text-foreground", children: count(preview.fields, "field") }) }),
6248
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Row, { label: "Files", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "text-foreground", children: count(preview.attachments, "file") }) }),
6249
- preview.passkeys === 1 ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Row, { label: "Passkey", hint: "Not turned on; the site may not accept it", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "text-foreground", children: "1 passkey" }) }) : null,
6250
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Row, { label: "Stays off", hint: "Turn each back on yourself", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "text-muted-foreground", children: "Sharing, browser fill, codes, sandboxes, agents" }) }),
6251
- preview.priorWasDisabled ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Row, { label: "Before", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "text-muted-foreground", children: "It was already off before it was deleted." }) }) : null
6252
- ] }) : preview ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Section, { children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Empty, { children: refusalText(preview.reason) }) }) : /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Section, { children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Empty, { children: "It comes back turned off: sharing, browser fill, codes and sandbox use stay off." }) }),
6220
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(VaultSection, { children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Empty, { children: "Checking what comes back\u2026" }) }) : preview?.supported ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(VaultSection, { title: "Comes back", children: [
6221
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(VaultRow, { label: "Fields", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "text-foreground", children: count(preview.fields, "field") }) }),
6222
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(VaultRow, { label: "Files", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "text-foreground", children: count(preview.attachments, "file") }) }),
6223
+ preview.passkeys === 1 ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(VaultRow, { label: "Passkey", hint: "Not turned on; the site may not accept it", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "text-foreground", children: "1 passkey" }) }) : null,
6224
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(VaultRow, { label: "Stays off", hint: "Turn each back on yourself", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "text-muted-foreground", children: "Sharing, browser fill, codes, sandboxes, agents" }) }),
6225
+ preview.priorWasDisabled ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(VaultRow, { label: "Before", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "text-muted-foreground", children: "It was already off before it was deleted." }) }) : null
6226
+ ] }) : preview ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(VaultSection, { children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Empty, { children: refusalText(preview.reason) }) }) : /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(VaultSection, { children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Empty, { children: "It comes back turned off: sharing, browser fill, codes and sandbox use stay off." }) }),
6253
6227
  error ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { role: "alert", className: "px-1 text-sm text-destructive", children: error }) : null
6254
6228
  ]
6255
6229
  }
@@ -6281,13 +6255,13 @@ function TrashView({ port, deleted, query, header, onChanged }) {
6281
6255
  };
6282
6256
  return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex min-h-0 flex-1 flex-col gap-3 overflow-y-auto p-3", children: [
6283
6257
  header,
6284
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(Section, { title: "Trash", children: shown.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(Empty, { children: deleted.length === 0 ? "The trash is empty." : "Nothing matches." }) : shown.map((item) => (
6258
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(VaultSection, { title: "Trash", children: shown.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(Empty, { children: deleted.length === 0 ? "The trash is empty." : "Nothing matches." }) : shown.map((item) => (
6285
6259
  // A list row, not a field row: the name gets the whole width (on a phone a label column
6286
6260
  // left "Vau…" for every row), the deletion date sits under it.
6287
6261
  /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex min-h-12 items-center gap-3 px-3 py-1.5 sm:px-4", children: [
6288
6262
  /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("span", { className: "flex min-w-0 flex-1 flex-col leading-tight", children: [
6289
6263
  /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "truncate text-sm text-foreground", children: item.name }),
6290
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "truncate text-xs text-muted-foreground", children: [item.deletion?.deletedAt ? `Deleted ${(0, import_format5.formatAbsoluteDate)(item.deletion.deletedAt, DAY_FORMAT, "")}` : null, item.owner.kind !== "me" ? item.owner.label : null].filter(Boolean).join(" \xB7 ") })
6264
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "truncate text-xs text-muted-foreground", children: [item.deletion?.deletedAt ? `Deleted ${(0, import_format9.formatAbsoluteDate)(item.deletion.deletedAt, DAY_FORMAT, "")}` : null, item.owner.kind !== "me" ? item.owner.label : null].filter(Boolean).join(" \xB7 ") })
6291
6265
  ] }),
6292
6266
  /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_controls24.Button, { variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(RestoreGlyph, {}), disabled: busyId !== null || !item.deletion, onClick: () => setRestoring(item), children: "Restore" })
6293
6267
  ] }, item.id)
@@ -6301,6 +6275,7 @@ function TrashView({ port, deleted, query, header, onChanged }) {
6301
6275
  var import_react31 = require("react");
6302
6276
  var import_design_system20 = require("@ai-matrx/design-system");
6303
6277
  var import_controls25 = require("@ai-matrx/design-system/controls");
6278
+ var import_icons12 = require("@ai-matrx/design-system/icons");
6304
6279
  var import_jsx_runtime30 = require("react/jsx-runtime");
6305
6280
  function NewItemFlow({ definitions, url, onUrl, onChoose, onCancel }) {
6306
6281
  const [search, setSearch] = (0, import_react31.useState)("");
@@ -6335,7 +6310,7 @@ function NewItemFlow({ definitions, url, onUrl, onChoose, onCancel }) {
6335
6310
  "aria-label": "Website address",
6336
6311
  inputMode: "url",
6337
6312
  autoFocus: true,
6338
- icon: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(GlobeGlyph, {})
6313
+ icon: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_icons12.GlobeIcon, {})
6339
6314
  }
6340
6315
  ),
6341
6316
  guess && login ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-2 rounded-xl border border-border bg-card p-3", children: [
@@ -6374,10 +6349,10 @@ var import_react32 = require("react");
6374
6349
  var import_confirm_opener10 = require("@ai-matrx/kit/confirm-opener");
6375
6350
  var import_design_system21 = require("@ai-matrx/design-system");
6376
6351
  var import_controls26 = require("@ai-matrx/design-system/controls");
6377
- var import_format7 = require("@ai-matrx/kit/format");
6352
+ var import_format11 = require("@ai-matrx/kit/format");
6378
6353
 
6379
6354
  // src/sharing/secure-link-logic.ts
6380
- var import_format6 = require("@ai-matrx/kit/format");
6355
+ var import_format10 = require("@ai-matrx/kit/format");
6381
6356
  var SECURE_RESOURCE_TYPE = "credential_item";
6382
6357
  var NOTE_MAX = 1e3;
6383
6358
  var CHANNEL_WORD = { email: "email", sms: "text" };
@@ -6415,7 +6390,7 @@ function carriedWords(keys, fields) {
6415
6390
  const known = new Map(fields.map((f) => [f.key, f.label]));
6416
6391
  return keys.map((k) => known.get(k) ?? fieldNames([k])).join(", ");
6417
6392
  }
6418
- var lifetimeWords = (minutes) => (0, import_format6.formatDurationMinutes)(minutes, { style: "long" });
6393
+ var lifetimeWords = (minutes) => (0, import_format10.formatDurationMinutes)(minutes, { style: "long" });
6419
6394
  function remedyOf(e) {
6420
6395
  const body = e?.serverDetail;
6421
6396
  if (!body || typeof body !== "object") return null;
@@ -6585,9 +6560,9 @@ function SecureLinkPanel({ item, port, onClose }) {
6585
6560
  ] }),
6586
6561
  children: [
6587
6562
  remedy ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "px-1 text-xs text-muted-foreground", children: remedy }) : null,
6588
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(Section, { title: "Recipient", children: [
6589
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Row, { label: "Email", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_controls26.Field, { type: "email", autoComplete: "off", placeholder: "name@example.com", "aria-label": "Their email", value: email, onChange: (e) => setEmail(e.target.value), className: "w-full" }) }),
6590
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Row, { label: "Mobile", hint: "For the code", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6563
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(VaultSection, { title: "Recipient", children: [
6564
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(VaultRow, { label: "Email", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_controls26.Field, { type: "email", autoComplete: "off", placeholder: "name@example.com", "aria-label": "Their email", value: email, onChange: (e) => setEmail(e.target.value), className: "w-full" }) }),
6565
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(VaultRow, { label: "Mobile", hint: "For the code", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6591
6566
  import_controls26.Field,
6592
6567
  {
6593
6568
  type: "tel",
@@ -6603,8 +6578,8 @@ function SecureLinkPanel({ item, port, onClose }) {
6603
6578
  className: "w-full"
6604
6579
  }
6605
6580
  ) }),
6606
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Row, { label: "Name", hint: "Optional", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_controls26.Field, { autoComplete: "off", placeholder: "Their name", "aria-label": "Their name", value: name, onChange: (e) => setName(e.target.value), className: "w-full" }) }),
6607
- plan && !plan.same ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Row, { label: "Link by", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6581
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(VaultRow, { label: "Name", hint: "Optional", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_controls26.Field, { autoComplete: "off", placeholder: "Their name", "aria-label": "Their name", value: name, onChange: (e) => setName(e.target.value), className: "w-full" }) }),
6582
+ plan && !plan.same ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(VaultRow, { label: "Link by", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6608
6583
  import_controls26.SegmentedControl,
6609
6584
  {
6610
6585
  "aria-label": "Send the link by",
@@ -6616,26 +6591,26 @@ function SecureLinkPanel({ item, port, onClose }) {
6616
6591
  ]
6617
6592
  }
6618
6593
  ) }) : null,
6619
- email.trim() ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Row, { label: "Delivery", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: plan?.same ? "text-warning" : "text-foreground", children: planWords(plan) }) }) : null
6594
+ email.trim() ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(VaultRow, { label: "Delivery", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: plan?.same ? "text-warning" : "text-foreground", children: planWords(plan) }) }) : null
6620
6595
  ] }),
6621
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Section, { title: "Include", children: optionsError ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Empty, { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-destructive", children: optionsError }) }) : !options ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_controls26.RegionSkeleton, { shape: "rows", count: 2, "aria-label": "Loading what can be sent", className: "px-3 sm:px-4" }) : options.fields.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Empty, { children: "Name and details only" }) : options.fields.map((f) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("label", { className: "flex min-h-11 items-center gap-3 px-3 py-1 sm:px-4", "data-clickable": f.available ? "" : void 0, children: [
6596
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(VaultSection, { title: "Include", children: optionsError ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Empty, { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-destructive", children: optionsError }) }) : !options ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_controls26.RegionSkeleton, { shape: "rows", count: 2, "aria-label": "Loading what can be sent", className: "px-3 sm:px-4" }) : options.fields.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Empty, { children: "Name and details only" }) : options.fields.map((f) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("label", { className: "flex min-h-11 items-center gap-3 px-3 py-1 sm:px-4", "data-clickable": f.available ? "" : void 0, children: [
6622
6597
  /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_design_system21.Checkbox, { checked: fields.includes(f.key), disabled: !f.available, onCheckedChange: (v) => toggle2(f.key, v === true), "aria-label": f.label }),
6623
6598
  /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm text-foreground", children: f.label }),
6624
6599
  !f.available && f.reason ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "min-w-0 max-w-[55%] truncate text-xs text-muted-foreground", title: f.reason, children: f.reason }) : null
6625
6600
  ] }, f.key)) }),
6626
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Section, { title: "Message", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "px-3 py-1 sm:px-4", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_controls26.Textarea, { className: "w-full", rows: 2, maxLength: NOTE_MAX, placeholder: "Shown once, with it", "aria-label": "Message", value: note, onChange: (e) => setNote(e.target.value) }) }) }),
6627
- options ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(Section, { title: "Link", children: [
6628
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Row, { label: "Opens", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-foreground", children: "Once" }) }),
6629
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Row, { label: "Link expires", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("span", { className: "text-foreground", children: [
6601
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(VaultSection, { title: "Message", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "px-3 py-1 sm:px-4", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_controls26.Textarea, { className: "w-full", rows: 2, maxLength: NOTE_MAX, placeholder: "Shown once, with it", "aria-label": "Message", value: note, onChange: (e) => setNote(e.target.value) }) }) }),
6602
+ options ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(VaultSection, { title: "Link", children: [
6603
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(VaultRow, { label: "Opens", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-foreground", children: "Once" }) }),
6604
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(VaultRow, { label: "Link expires", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("span", { className: "text-foreground", children: [
6630
6605
  "After ",
6631
6606
  lifetimeWords(options.linkMinutes)
6632
6607
  ] }) }),
6633
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Row, { label: "Code expires", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("span", { className: "text-foreground", children: [
6608
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(VaultRow, { label: "Code expires", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("span", { className: "text-foreground", children: [
6634
6609
  "After ",
6635
6610
  lifetimeWords(options.codeMinutes)
6636
6611
  ] }) })
6637
6612
  ] }) : null,
6638
- sharing.sentSecureLinks ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Section, { title: "Sent links", children: sentError ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Empty, { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-destructive", children: sentError }) }) : !sent ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_controls26.RegionSkeleton, { shape: "rows", count: 2, "aria-label": "Loading sent links", className: "px-3 sm:px-4" }) : sent.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Empty, { children: "None yet" }) : sent.map((row) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(AccessLine, { glyph: row.status === "pending" ? ClockGlyph : row.fieldKeys.length ? LockGlyph : ShareGlyph, who: recipientOf(row), meta: sentMeta(row, options), children: [
6613
+ sharing.sentSecureLinks ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(VaultSection, { title: "Sent links", children: sentError ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Empty, { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-destructive", children: sentError }) }) : !sent ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_controls26.RegionSkeleton, { shape: "rows", count: 2, "aria-label": "Loading sent links", className: "px-3 sm:px-4" }) : sent.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Empty, { children: "None yet" }) : sent.map((row) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(AccessLine, { glyph: row.status === "pending" ? ClockGlyph : row.fieldKeys.length ? LockGlyph : ShareGlyph, who: recipientOf(row), meta: sentMeta(row, options), children: [
6639
6614
  /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_controls26.Badge, { tone: STATUS_TONE[row.status] ?? "neutral", children: statusWord(row.status) }),
6640
6615
  row.status === "pending" ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_controls26.Button, { variant: "quiet", disabled: busy !== null, onClick: () => void turnOff(row), children: "Turn off" }) : null
6641
6616
  ] }, row.id)) }) : null
@@ -6644,7 +6619,7 @@ function SecureLinkPanel({ item, port, onClose }) {
6644
6619
  );
6645
6620
  }
6646
6621
  function sentMeta(row, options) {
6647
- const when = row.status === "pending" ? `Until ${(0, import_format7.formatAbsoluteDate)(row.expiresAt, void 0, "")}` : row.status === "viewed" && row.viewedAt ? (0, import_format7.formatAbsoluteDate)(row.viewedAt, void 0, "") : (0, import_format7.formatAbsoluteDate)(row.createdAt, DAY_FORMAT, "");
6622
+ const when = row.status === "pending" ? `Until ${(0, import_format11.formatAbsoluteDate)(row.expiresAt, void 0, "")}` : row.status === "viewed" && row.viewedAt ? (0, import_format11.formatAbsoluteDate)(row.viewedAt, void 0, "") : (0, import_format11.formatAbsoluteDate)(row.createdAt, DAY_FORMAT, "");
6648
6623
  const carried = row.fieldKeys.length ? carriedWords(row.fieldKeys, options?.fields ?? []) : "";
6649
6624
  return [when, carried].filter(Boolean).join(" \xB7 ");
6650
6625
  }
@@ -6653,7 +6628,7 @@ function sentMeta(row, options) {
6653
6628
  var import_react33 = require("react");
6654
6629
  var import_confirm_opener11 = require("@ai-matrx/kit/confirm-opener");
6655
6630
  var import_controls27 = require("@ai-matrx/design-system/controls");
6656
- var import_format8 = require("@ai-matrx/kit/format");
6631
+ var import_format12 = require("@ai-matrx/kit/format");
6657
6632
 
6658
6633
  // src/devices/logic.ts
6659
6634
  var PASSKEY_RP_ID = "aimatrx.com";
@@ -6777,19 +6752,19 @@ function DevicesPanel({ port, onClose }) {
6777
6752
  };
6778
6753
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Panel, { title: "Browsers that can fill", onClose, size: "md", children: [
6779
6754
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ErrorLine2, { text: error }),
6780
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Section, { children: devices === null ? error ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Empty, { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_controls27.Button, { variant: "outline", onClick: () => void load(), children: "Try again" }) }) : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_controls27.RegionSkeleton, { shape: "rows", count: 2, "aria-label": "Loading your browsers", className: "px-3 sm:px-4" }) : devices.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Empty, { children: "No browser can fill yet. Turn it on in the extension." }) : devices.map((device) => {
6755
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(VaultSection, { children: devices === null ? error ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Empty, { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_controls27.Button, { variant: "outline", onClick: () => void load(), children: "Try again" }) }) : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_controls27.RegionSkeleton, { shape: "rows", count: 2, "aria-label": "Loading your browsers", className: "px-3 sm:px-4" }) : devices.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Empty, { children: "No browser can fill yet. Turn it on in the extension." }) : devices.map((device) => {
6781
6756
  const off = isRevoked(device);
6782
6757
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6783
- Row,
6758
+ VaultRow,
6784
6759
  {
6785
6760
  label: off ? "Turned off" : "Can fill",
6786
- hint: off ? (0, import_format8.formatAbsoluteDate)(device.revokedAt, DAY_FORMAT, "") : void 0,
6761
+ hint: off ? (0, import_format12.formatAbsoluteDate)(device.revokedAt, DAY_FORMAT, "") : void 0,
6787
6762
  actions: off ? null : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_controls27.Button, { variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(PowerGlyph, {}), disabled: busyId !== null, onClick: () => void revoke(device), children: "Revoke" }),
6788
6763
  children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "flex min-w-0 flex-col", children: [
6789
6764
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: off ? "truncate text-muted-foreground" : "truncate text-foreground", children: device.label }),
6790
6765
  /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "truncate text-xs text-muted-foreground", children: [
6791
- device.lastUsedAt ? `Last used ${(0, import_format8.formatAbsoluteDate)(device.lastUsedAt, void 0, "")}` : "Never used",
6792
- device.addedAt ? ` \xB7 added ${(0, import_format8.formatAbsoluteDate)(device.addedAt, DAY_FORMAT, "")}` : ""
6766
+ device.lastUsedAt ? `Last used ${(0, import_format12.formatAbsoluteDate)(device.lastUsedAt, void 0, "")}` : "Never used",
6767
+ device.addedAt ? ` \xB7 added ${(0, import_format12.formatAbsoluteDate)(device.addedAt, DAY_FORMAT, "")}` : ""
6793
6768
  ] })
6794
6769
  ] })
6795
6770
  },
@@ -6868,29 +6843,29 @@ function ApprovePanel({ port, host, onClose, approvalKey, label, kind = "browser
6868
6843
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_controls27.Button, { variant: "quiet", disabled: busy !== null, onClick: refuse, children: key ? "Refuse" : "Close" }),
6869
6844
  canApprove ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_controls27.Button, { variant: "primary", icon: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(FingerprintGlyph, {}), disabled: busy !== null, onClick: () => void approve(), children: busy === "approve" ? "Approving\u2026" : "Approve with passkey" }) : null
6870
6845
  ] });
6871
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Panel, { title, onClose: refuse, size: "sm", footer, children: !key ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Section, { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Empty, { children: [
6846
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Panel, { title, onClose: refuse, size: "sm", footer, children: !key ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(VaultSection, { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Empty, { children: [
6872
6847
  "This link names no key. Start again from ",
6873
6848
  where,
6874
6849
  "."
6875
6850
  ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
6876
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Section, { title: "What is asking", children: [
6877
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Row, { label: "Asking", hint: "Approve only if you just asked", children: asker }),
6878
- name ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Row, { label: "Name", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "block truncate", children: name }) }) : null,
6879
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Row, { label: "Code", hint: `Must match ${where}`, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "font-mono tracking-wider text-foreground", children: shortFingerprint(key) }) })
6851
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(VaultSection, { title: "What is asking", children: [
6852
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(VaultRow, { label: "Asking", hint: "Approve only if you just asked", children: asker }),
6853
+ name ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(VaultRow, { label: "Name", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "block truncate", children: name }) }) : null,
6854
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(VaultRow, { label: "Code", hint: `Must match ${where}`, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "font-mono tracking-wider text-foreground", children: shortFingerprint(key) }) })
6880
6855
  ] }),
6881
6856
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ErrorLine2, { text: error }),
6882
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Section, { title: "Confirm it\u2019s you", children: approvedUntil ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Row, { label: "Approved", actions: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(CheckGlyph, { className: "size-4 text-primary" }), children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "text-foreground", children: [
6857
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(VaultSection, { title: "Confirm it\u2019s you", children: approvedUntil ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(VaultRow, { label: "Approved", actions: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(CheckGlyph, { className: "size-4 text-primary" }), children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "text-foreground", children: [
6883
6858
  "Return to ",
6884
6859
  where,
6885
6860
  " by ",
6886
- (0, import_format8.formatAbsoluteDate)(approvedUntil, void 0, ""),
6861
+ (0, import_format12.formatAbsoluteDate)(approvedUntil, void 0, ""),
6887
6862
  "."
6888
6863
  ] }) }) : !passkeys ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Empty, { children: [
6889
6864
  "Approve with your password in ",
6890
6865
  where,
6891
6866
  "."
6892
6867
  ] }) : !here ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6893
- Row,
6868
+ VaultRow,
6894
6869
  {
6895
6870
  label: "Passkey",
6896
6871
  hint: `Passkeys work only on ${passkeys.rpId}`,
@@ -6898,14 +6873,14 @@ function ApprovePanel({ port, host, onClose, approvalKey, label, kind = "browser
6898
6873
  children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-muted-foreground", children: "Not on this page" })
6899
6874
  }
6900
6875
  ) : methods === null ? error ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Empty, { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_controls27.Button, { variant: "outline", onClick: () => void load(), children: "Try again" }) }) : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_controls27.RegionSkeleton, { shape: "rows", count: 1, "aria-label": "Checking your account", className: "px-3 sm:px-4" }) : !methods.passkey ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6901
- Row,
6876
+ VaultRow,
6902
6877
  {
6903
6878
  label: "Passkey",
6904
6879
  hint: methods.password ? `Or type your password in ${where}` : "Add one to approve",
6905
6880
  actions: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_controls27.Button, { variant: "primary", icon: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(FingerprintGlyph, {}), disabled: busy !== null, onClick: () => void addPasskey(), children: busy === "add" ? "Adding\u2026" : "Add passkey" }),
6906
6881
  children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-muted-foreground", children: methods.password ? "None yet" : "No password or passkey" })
6907
6882
  }
6908
- ) : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Row, { label: "Passkey", hint: "Your device asks for it next", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-foreground", children: "Ready" }) }) })
6883
+ ) : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(VaultRow, { label: "Passkey", hint: "Your device asks for it next", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-foreground", children: "Ready" }) }) })
6909
6884
  ] }) });
6910
6885
  }
6911
6886
 
@@ -7183,7 +7158,7 @@ var TONE = {
7183
7158
  };
7184
7159
  function NativeImportPanel({ bridge, readLimits, activeOrganizationId, organizations, onClose, onChanged }) {
7185
7160
  if (!bridge) {
7186
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Panel, { title: "Import passkeys", size: "md", onClose, footer: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Button, { variant: "primary", onClick: onClose, children: "Close" }), children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Section, { children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Empty, { children: "Passkey import needs the desktop app." }) }) });
7161
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Panel, { title: "Import passkeys", size: "md", onClose, footer: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Button, { variant: "primary", onClick: onClose, children: "Close" }), children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(VaultSection, { children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Empty, { children: "Passkey import needs the desktop app." }) }) });
7187
7162
  }
7188
7163
  return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Importer, { bridge, readLimits, activeOrganizationId, organizations, onClose, onChanged });
7189
7164
  }
@@ -7230,25 +7205,25 @@ function Importer({ bridge, readLimits, activeOrganizationId, organizations, onC
7230
7205
  /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Button, { variant: "primary", onClick: onClose, children: "Done" })
7231
7206
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Button, { variant: "quiet", onClick: onClose, children: "Close" });
7232
7207
  return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(Panel, { title: "Import passkeys", size: "lg", onClose, footer, children: [
7233
- screen.kind === "idle" ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(Section, { children: [
7234
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Row, { label: "Save to", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Select, { value: organizationId, options, "aria-label": "Save to", disabled: busy, onValueChange: setOrganizationId }) }),
7235
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Row, { label: "File", hint: limits ? `Up to ${plural2(limits.maxItems, "passkey")}` : "A passkey exchange file", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Button, { variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ImportGlyph, { className: "size-4" }), disabled: busy || !organizationId || limitError !== null, onClick: () => void flow.begin(organizationId), children: busy ? "Opening\u2026" : "Choose file" }) }),
7236
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Row, { label: "Interrupted", hint: "Finish or clear an earlier import", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Button, { variant: "quiet", disabled: busy, onClick: () => void flow.recover(), children: "Recover" }) })
7208
+ screen.kind === "idle" ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(VaultSection, { children: [
7209
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(VaultRow, { label: "Save to", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Select, { value: organizationId, options, "aria-label": "Save to", disabled: busy, onValueChange: setOrganizationId }) }),
7210
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(VaultRow, { label: "File", hint: limits ? `Up to ${plural2(limits.maxItems, "passkey")}` : "A passkey exchange file", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Button, { variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ImportGlyph, { className: "size-4" }), disabled: busy || !organizationId || limitError !== null, onClick: () => void flow.begin(organizationId), children: busy ? "Opening\u2026" : "Choose file" }) }),
7211
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(VaultRow, { label: "Interrupted", hint: "Finish or clear an earlier import", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Button, { variant: "quiet", disabled: busy, onClick: () => void flow.recover(), children: "Recover" }) })
7237
7212
  ] }) : null,
7238
- preview ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Section, { title: `${ready} of ${preview.total} ready`, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7213
+ preview ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(VaultSection, { title: `${ready} of ${preview.total} ready`, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7239
7214
  Windowed,
7240
7215
  {
7241
7216
  items: preview.slots,
7242
- render: (slot) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Row, { label: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Badge, { tone: TONE[slot.disposition], children: dispositionLabel(slot.disposition) }), hint: void 0, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "block truncate text-foreground", title: slot.reason ?? void 0, children: slot.title ?? "Unnamed passkey" }) }, slot.slot_id)
7217
+ render: (slot) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(VaultRow, { label: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Badge, { tone: TONE[slot.disposition], children: dispositionLabel(slot.disposition) }), hint: void 0, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "block truncate text-foreground", title: slot.reason ?? void 0, children: slot.title ?? "Unnamed passkey" }) }, slot.slot_id)
7243
7218
  }
7244
7219
  ) }) : null,
7245
- status && !preview ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(Section, { title: `${accounted(status)} of ${status.total} done`, children: [
7246
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Row, { label: "Imported", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-foreground", children: status.committed }) }),
7247
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Row, { label: "Already there", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-foreground", children: status.already_present }) }),
7248
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Row, { label: "Can't import", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-foreground", children: status.unsupported }) }),
7249
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Row, { label: "Failed", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: status.failed > 0 ? "text-destructive" : "text-foreground", children: status.failed }) }),
7250
- status.uncertain > 0 ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Row, { label: "Needs recovery", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-foreground", children: status.uncertain }) }) : null,
7251
- status.not_attempted > 0 ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Row, { label: "Not tried", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-foreground", children: status.not_attempted }) }) : null
7220
+ status && !preview ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(VaultSection, { title: `${accounted(status)} of ${status.total} done`, children: [
7221
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(VaultRow, { label: "Imported", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-foreground", children: status.committed }) }),
7222
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(VaultRow, { label: "Already there", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-foreground", children: status.already_present }) }),
7223
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(VaultRow, { label: "Can't import", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-foreground", children: status.unsupported }) }),
7224
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(VaultRow, { label: "Failed", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: status.failed > 0 ? "text-destructive" : "text-foreground", children: status.failed }) }),
7225
+ status.uncertain > 0 ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(VaultRow, { label: "Needs recovery", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-foreground", children: status.uncertain }) }) : null,
7226
+ status.not_attempted > 0 ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(VaultRow, { label: "Not tried", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-foreground", children: status.not_attempted }) }) : null
7252
7227
  ] }) : null,
7253
7228
  screen.message ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { role: "status", className: "px-1 text-sm text-muted-foreground", children: screen.message }) : null,
7254
7229
  /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ErrorLine, { message: limitError })
@@ -7259,6 +7234,7 @@ function Importer({ bridge, readLimits, activeOrganizationId, organizations, onC
7259
7234
  var import_react39 = require("react");
7260
7235
  var import_design_system23 = require("@ai-matrx/design-system");
7261
7236
  var import_controls32 = require("@ai-matrx/design-system/controls");
7237
+ var import_icons14 = require("@ai-matrx/design-system/icons");
7262
7238
 
7263
7239
  // src/extension/CaptureCard.tsx
7264
7240
  var import_react36 = require("react");
@@ -7401,6 +7377,7 @@ function FillSetupCard({ fillSetup }) {
7401
7377
  var import_react38 = require("react");
7402
7378
  var import_design_system22 = require("@ai-matrx/design-system");
7403
7379
  var import_controls31 = require("@ai-matrx/design-system/controls");
7380
+ var import_icons13 = require("@ai-matrx/design-system/icons");
7404
7381
  var import_jsx_runtime36 = require("react/jsx-runtime");
7405
7382
  var HOLD_MS = 6e4;
7406
7383
  function PageGenerator({ fields }) {
@@ -7454,11 +7431,11 @@ function PageGenerator({ fields }) {
7454
7431
  const value = held.value;
7455
7432
  return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
7456
7433
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7457
- Row,
7434
+ VaultRow,
7458
7435
  {
7459
7436
  label: "New password",
7460
7437
  actions: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
7461
- value ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_controls31.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(CopyGlyph, {}), "aria-label": "Copy password", onClick: () => void copy(value, "Password") }) : null,
7438
+ value ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_controls31.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_icons13.CopyIcon, {}), "aria-label": "Copy password", onClick: () => void copy(value, "Password") }) : null,
7462
7439
  /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_design_system22.Popover, { open, onOpenChange: setOpen, children: [
7463
7440
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system22.PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_controls31.Button, { variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(KeyGlyph, {}), disabled: busy, children: "Generate" }) }),
7464
7441
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_design_system22.PopoverContent, { sizing: "content", align: "end", children: open ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(PasswordGenerator, { limits, useLabel: "Fill page", onUse: (v) => void onUse(v) }) : null })
@@ -7467,7 +7444,7 @@ function PageGenerator({ fields }) {
7467
7444
  children: said ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("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__ */ (0, import_jsx_runtime36.jsx)("span", { className: "text-xs text-muted-foreground", children: "Choose the boxes to fill." }) : /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "text-xs text-disabled-foreground", children: "Fills the page\u2019s new-password box" })
7468
7445
  }
7469
7446
  ),
7470
- value && targets.length > 0 ? targets.map((t) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Row, { label: t.topFrame ? "This page" : "In a frame", actions: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_controls31.Button, { variant: "primary", icon: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(CheckGlyph, {}), disabled: busy, onClick: () => void put(t.id, value), children: "Fill" }), children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "block truncate text-sm", children: targetLabel(t) }) }, t.id)) : null
7447
+ value && targets.length > 0 ? targets.map((t) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(VaultRow, { label: t.topFrame ? "This page" : "In a frame", actions: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_controls31.Button, { variant: "primary", icon: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(CheckGlyph, {}), disabled: busy, onClick: () => void put(t.id, value), children: "Fill" }), children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "block truncate text-sm", children: targetLabel(t) }) }, t.id)) : null
7471
7448
  ] });
7472
7449
  }
7473
7450
 
@@ -7529,7 +7506,7 @@ function PageView({ port, page, fill, capture, fillSetup, newPasswordFields, ite
7529
7506
  return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "flex h-full min-h-0 flex-col overflow-y-auto bg-background text-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex flex-col gap-3 px-3 pb-4 pt-3", children: [
7530
7507
  header,
7531
7508
  /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex min-h-7 items-center gap-2 px-1", children: [
7532
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_design_system23.SiteIcon, { site: page.url, fallback: GlobeGlyph, className: "size-4" }),
7509
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_design_system23.SiteIcon, { site: page.url, fallback: import_icons14.GlobeIcon, className: "size-4" }),
7533
7510
  /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm font-medium", title: page.url, children: site || "No page open" }),
7534
7511
  page.refresh ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_controls32.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(RefreshGlyph, {}), "aria-label": "Check again", onClick: page.refresh }) : null,
7535
7512
  onBrowse ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_controls32.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ListGlyph, {}), onClick: onBrowse, children: "All items" }) : null
@@ -7537,7 +7514,7 @@ function PageView({ port, page, fill, capture, fillSetup, newPasswordFields, ite
7537
7514
  fillSetup ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(FillSetupCard, { fillSetup }) : null,
7538
7515
  capture ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(CaptureCard, { capture, onChanged }) : null,
7539
7516
  /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
7540
- Section,
7517
+ VaultSection,
7541
7518
  {
7542
7519
  title: "This site",
7543
7520
  actions: canSave ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_controls32.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(PlusGlyph, {}), onClick: () => onNewForPage(normalizeLoginUrl2(page.url) ?? page.url), children: "Save a login" }) : null,
@@ -7545,7 +7522,7 @@ function PageView({ port, page, fill, capture, fillSetup, newPasswordFields, ite
7545
7522
  }
7546
7523
  ),
7547
7524
  said ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Outcome, { said, onDismiss: () => setSaid(null) }) : page.blocked && page.url && state.status === "ready" ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "px-1 text-xs text-muted-foreground", children: BLOCK_WORDS[page.blocked] }) : null,
7548
- newPasswordFields && canSave ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Section, { children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(PageGenerator, { fields: newPasswordFields }) }) : null
7525
+ newPasswordFields && canSave ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(VaultSection, { children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(PageGenerator, { fields: newPasswordFields }) }) : null
7549
7526
  ] }) });
7550
7527
  }
7551
7528
  function Outcome({ said, onDismiss }) {
@@ -7607,6 +7584,7 @@ function MatchRow({ itemId, item, tag, family, port, busy, running, onOpen, onFi
7607
7584
  var import_react40 = require("react");
7608
7585
  var import_design_system24 = require("@ai-matrx/design-system");
7609
7586
  var import_controls33 = require("@ai-matrx/design-system/controls");
7587
+ var import_icons15 = require("@ai-matrx/design-system/icons");
7610
7588
  var import_jsx_runtime38 = require("react/jsx-runtime");
7611
7589
  function vaultChoices(items, organizations, current) {
7612
7590
  const n = (f) => items.filter(f).length;
@@ -7622,7 +7600,7 @@ function vaultChoices(items, organizations, current) {
7622
7600
  function VaultSelect({ value, choices, onChange }) {
7623
7601
  return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_controls33.Select, { value, onValueChange: onChange, "aria-label": "Vault", options: choices.map((c) => ({ value: c.value, label: c.label, meta: String(c.count) })) });
7624
7602
  }
7625
- var CATEGORY_GLYPHS = { logins: GlobeGlyph, passkeys: ShieldGlyph, api: KeyGlyph, oauth: PlugGlyph, infra: DatabaseGlyph, env: TerminalGlyph, files: FileGlyph, other: NoteGlyph };
7603
+ var CATEGORY_GLYPHS = { logins: import_icons15.GlobeIcon, passkeys: ShieldGlyph, api: KeyGlyph, oauth: PlugGlyph, infra: DatabaseGlyph, env: TerminalGlyph, files: FileGlyph, other: NoteGlyph };
7626
7604
  var familyOf = (key, definitions) => definitions.find((d) => d.key === key)?.family ?? "generic";
7627
7605
  function itemCategory(item, definitions) {
7628
7606
  return categoryOf(item.definitionKey, familyOf(item.definitionKey, definitions));
@@ -7665,13 +7643,14 @@ function viewOptions(views, allCount, deletedCount, hasFavorites, hasRecents, ha
7665
7643
  ];
7666
7644
  }
7667
7645
  function Entry({ on, glyph: Icon, label, count: count2, onClick }) {
7646
+ const desktop = (0, import_design_system24.useLook)() === "desktop";
7668
7647
  return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
7669
7648
  "button",
7670
7649
  {
7671
7650
  type: "button",
7672
7651
  "aria-current": on ? "page" : void 0,
7673
7652
  onClick,
7674
- className: (0, import_design_system24.cn)("flex h-8 w-full items-center gap-2.5 rounded-lg px-2.5 text-left text-sm", on ? "bg-sidebar-accent font-medium text-sidebar-accent-foreground" : "text-sidebar-foreground hover:bg-sidebar-accent"),
7653
+ className: (0, import_design_system24.cn)("flex h-8 w-full items-center gap-2.5 rounded-lg px-2.5 text-left text-sm", on ? desktop ? "bg-sidebar-accent text-primary" : "bg-sidebar-accent font-medium text-sidebar-accent-foreground" : "text-sidebar-foreground hover:bg-sidebar-accent"),
7675
7654
  children: [
7676
7655
  /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Icon, { className: "size-4 shrink-0" }),
7677
7656
  /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "min-w-0 flex-1 truncate", children: label }),
@@ -7686,7 +7665,7 @@ function Group({ title, children }) {
7686
7665
  children
7687
7666
  ] });
7688
7667
  }
7689
- function Sidebar({ vault, choices, onVault, view, allCount, deletedCount, views, hasFavorites, hasRecents, onView, onPanel, nativeProvider, hasNativeImport = false, hasPage = false }) {
7668
+ function VaultSidebar({ vault, choices, onVault, view, allCount, deletedCount, views, hasFavorites, hasRecents, onView, onPanel, nativeProvider, hasNativeImport = false, hasPage = false }) {
7690
7669
  const [tagsOpen, setTagsOpen] = (0, import_react40.useState)(view.startsWith("tag:"));
7691
7670
  return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("nav", { "aria-label": "Vault", className: "flex h-full min-h-0 flex-col border-r border-sidebar-border bg-sidebar-background text-sidebar-foreground", children: [
7692
7671
  /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex items-center gap-2 px-3 pb-2 pt-3", children: [
@@ -7695,7 +7674,7 @@ function Sidebar({ vault, choices, onVault, view, allCount, deletedCount, views,
7695
7674
  ] }),
7696
7675
  /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex min-h-0 flex-1 flex-col gap-5 overflow-y-auto px-2 pb-3 pt-1", children: [
7697
7676
  /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex flex-col gap-0.5", children: [
7698
- hasPage ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Entry, { on: view === "page", glyph: GlobeGlyph, label: "This page", onClick: () => onView("page") }) : null,
7677
+ hasPage ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Entry, { on: view === "page", glyph: import_icons15.GlobeIcon, label: "This page", onClick: () => onView("page") }) : null,
7699
7678
  /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Entry, { on: view === "all", glyph: GridGlyph, label: "All items", count: allCount, onClick: () => onView("all") }),
7700
7679
  hasFavorites ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Entry, { on: view === "favorites", glyph: StarGlyph, label: "Favorites", count: views.favorites, onClick: () => onView("favorites") }) : null,
7701
7680
  hasRecents ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Entry, { on: view === "recent", glyph: ClockGlyph, label: "Recently opened", count: views.recent, onClick: () => onView("recent") }) : null,
@@ -7735,7 +7714,7 @@ var NO_HOST = {};
7735
7714
  var ITEM_PANELS = {
7736
7715
  share: SharePanel,
7737
7716
  move: MovePanel,
7738
- history: HistoryPanel,
7717
+ history: ItemHistoryPanel,
7739
7718
  activity: ActivityPanel,
7740
7719
  settings: ItemSettingsPanel,
7741
7720
  field: FieldSettingsPanel,
@@ -7768,7 +7747,7 @@ function VaultApp(props) {
7768
7747
  const lock = props.host?.lock;
7769
7748
  const locked = useLocked(lock);
7770
7749
  const port = (0, import_react41.useMemo)(() => lock ? guardPort(props.port, () => lock.locked()) : props.port, [props.port, lock]);
7771
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "relative h-full min-h-0 w-full", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(NoticeProvider, { notify: props.notify, children: lock && locked ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(LockedScreen, { lock }) : /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ClipboardProvider, { clipboard: props.host?.clipboard, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(RevealSecondsProvider, { seconds: props.host?.revealSeconds, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(IdentityGate, { identity: props.host?.identity, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(GeneratorLimitsProvider, { resolve: generatorLimitsFrom(props.host?.knobs), children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Workspace, { ...props, port }) }) }) }) }) }) });
7750
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_design_system25.LookScope, { look: props.look ?? "web", className: "h-full min-h-0 w-full", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "relative h-full min-h-0 w-full", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(NoticeProvider, { notify: props.notify, children: lock && locked ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(LockedScreen, { lock }) : /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ClipboardProvider, { clipboard: props.host?.clipboard, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(RevealSecondsProvider, { seconds: props.host?.revealSeconds, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(IdentityGate, { identity: props.host?.identity, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(GeneratorLimitsProvider, { resolve: generatorLimitsFrom(props.host?.knobs), children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Workspace, { ...props, port }) }) }) }) }) }) }) });
7772
7751
  }
7773
7752
  function LockedScreen({ lock }) {
7774
7753
  const [busy, setBusy] = (0, import_react41.useState)(false);
@@ -8126,7 +8105,7 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
8126
8105
  ] }) : null,
8127
8106
  /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: `grid min-h-0 w-full flex-1 ${grid} overflow-hidden`, children: [
8128
8107
  mode === "full" ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8129
- Sidebar,
8108
+ VaultSidebar,
8130
8109
  {
8131
8110
  vault: loc.vault,
8132
8111
  choices,