@ai-matrx/vault 0.1.15 → 0.1.17

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
@@ -152,24 +152,28 @@ __export(src_exports, {
152
152
  guardPort: () => guardPort,
153
153
  inferFromUrl: () => inferFromUrl,
154
154
  isHiddenItem: () => isHiddenItem,
155
+ itemIdAt: () => itemIdAt,
155
156
  locationFromParams: () => locationFromParams,
156
157
  locationToParams: () => locationToParams,
157
158
  loginSiteOf: () => loginSiteOf,
158
159
  matchesQuery: () => matchesQuery,
159
160
  needsRecentSignIn: () => needsRecentSignIn,
160
161
  parseDefinitions: () => parseDefinitions,
162
+ providerOf: () => providerOf,
161
163
  siteDomainOf: () => siteDomainOf,
162
164
  sortItems: () => sortItems,
163
165
  useConfirmed: () => useConfirmed,
166
+ vaultInventoryScope: () => vaultInventoryScope,
167
+ vaultItemFacts: () => vaultItemFacts,
164
168
  wasCancelled: () => wasCancelled
165
169
  });
166
170
  module.exports = __toCommonJS(src_exports);
167
171
 
168
172
  // src/VaultApp.tsx
169
- var import_react41 = require("react");
170
- var import_design_system25 = require("@ai-matrx/design-system");
171
- var import_controls34 = require("@ai-matrx/design-system/controls");
172
- var import_confirm_opener13 = require("@ai-matrx/kit/confirm-opener");
173
+ var import_react42 = require("react");
174
+ var import_design_system26 = require("@ai-matrx/design-system");
175
+ var import_controls35 = require("@ai-matrx/design-system/controls");
176
+ var import_confirm_opener14 = require("@ai-matrx/kit/confirm-opener");
173
177
 
174
178
  // src/notice.tsx
175
179
  var import_react = require("react");
@@ -703,12 +707,12 @@ var ROW_GRID = {
703
707
  roomy: "grid-cols-[9rem_minmax(0,1fr)_auto] gap-x-3 px-4",
704
708
  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"
705
709
  };
706
- function VaultRow({ label, hint, children, actions, top = false, className }) {
710
+ function VaultRow({ label, hint: hint2, children, actions, top = false, className }) {
707
711
  const room = (0, import_react4.useContext)(Room);
708
712
  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: [
709
713
  /* @__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: [
710
714
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: room === "roomy" ? "truncate" : room === "compact" ? "line-clamp-2 break-words" : "line-clamp-2 break-words sm:truncate", children: label }),
711
- hint ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "line-clamp-2 break-words text-xs text-disabled-foreground", children: hint }) : null
715
+ hint2 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "line-clamp-2 break-words text-xs text-disabled-foreground", children: hint2 }) : null
712
716
  ] }),
713
717
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: (0, import_design_system4.cn)("min-w-0 text-sm", top && "py-1.5"), children }),
714
718
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: (0, import_design_system4.cn)("flex items-center gap-0.5", top && "pt-1"), children: actions })
@@ -818,14 +822,14 @@ function TurnOnButton({ label, onTurnOn }) {
818
822
  }
819
823
  );
820
824
  }
821
- function PlainRow({ label, value, hint, openUrl, extra, multiline = false }) {
825
+ function PlainRow({ label, value, hint: hint2, openUrl, extra, multiline = false }) {
822
826
  const copyValue2 = useCopy();
823
827
  const isUrl = /^https?:\/\//i.test(value);
824
828
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
825
829
  VaultRow,
826
830
  {
827
831
  label,
828
- hint,
832
+ hint: hint2,
829
833
  top: multiline,
830
834
  actions: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
831
835
  extra,
@@ -855,13 +859,13 @@ function PlainRow({ label, value, hint, openUrl, extra, multiline = false }) {
855
859
  function AddRow({ label, onAdd, children = "Add" }) {
856
860
  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" }) });
857
861
  }
858
- function EditRow({ label, hint, value, onChange, placeholder, secret = false, multiline = false, onRemove, removeLabel, actions, autoFocus, onBlur, inputMode }) {
862
+ function EditRow({ label, hint: hint2, value, onChange, placeholder, secret = false, multiline = false, onRemove, removeLabel, actions, autoFocus, onBlur, inputMode }) {
859
863
  const [shown, setShown] = (0, import_react5.useState)(false);
860
864
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
861
865
  VaultRow,
862
866
  {
863
867
  label,
864
- hint,
868
+ hint: hint2,
865
869
  top: multiline,
866
870
  actions: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
867
871
  secret && value ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_controls2.Button, { variant: "quiet", icon: shown ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(EyeOffGlyph, {}) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(EyeGlyph, {}), "aria-label": shown ? "Hide" : "Show", onClick: () => setShown((s) => !s) }) : null,
@@ -872,7 +876,7 @@ function EditRow({ label, hint, value, onChange, placeholder, secret = false, mu
872
876
  }
873
877
  );
874
878
  }
875
- function CustomEditRow({ label, value, onLabel, onValue, secret, onRemove }) {
879
+ function CustomEditRow({ label, value, onLabel, onValue, secret, onRemove, extra, onPasteValue }) {
876
880
  const [shown, setShown] = (0, import_react5.useState)(false);
877
881
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
878
882
  VaultRow,
@@ -880,9 +884,25 @@ function CustomEditRow({ label, value, onLabel, onValue, secret, onRemove }) {
880
884
  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" }),
881
885
  actions: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
882
886
  secret && value ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_controls2.Button, { variant: "quiet", icon: shown ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(EyeOffGlyph, {}) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(EyeGlyph, {}), "aria-label": shown ? "Hide" : "Show", onClick: () => setShown((x) => !x) }) : null,
887
+ extra,
883
888
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_controls2.Button, { variant: "quiet", removes: true, icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(XGlyph, {}), "aria-label": "Remove field", onClick: onRemove })
884
889
  ] }),
885
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_controls2.Field, { className: "w-full", value, onChange: (e) => onValue(e.target.value), type: secret && !shown ? "password" : "text", placeholder: secret ? "Secret value" : "Value", autoComplete: "off", spellCheck: false, "aria-label": "Field value" })
890
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
891
+ import_controls2.Field,
892
+ {
893
+ className: "w-full",
894
+ value,
895
+ onChange: (e) => onValue(e.target.value),
896
+ onPaste: onPasteValue ? (e) => {
897
+ if (onPasteValue(e.clipboardData.getData("text"))) e.preventDefault();
898
+ } : void 0,
899
+ type: secret && !shown ? "password" : "text",
900
+ placeholder: secret ? "Secret value" : "Value",
901
+ autoComplete: "off",
902
+ spellCheck: false,
903
+ "aria-label": label ? `${label} value` : "Field value"
904
+ }
905
+ )
886
906
  }
887
907
  );
888
908
  }
@@ -896,7 +916,7 @@ var import_format = require("@ai-matrx/kit/format");
896
916
 
897
917
  // src/model.ts
898
918
  var DEFAULT_LOCATION = { vault: "all", view: "all", q: "", sort: "name", itemId: null, mode: "view", kind: null, url: "", panel: null };
899
- var SORTS = ["name", "website", "updated", "created"];
919
+ var SORTS = ["name", "name-desc", "website", "updated", "created", "viewed"];
900
920
  function locationFromParams(params, itemId = params.get("item")) {
901
921
  const sort = params.get("sort");
902
922
  const mode = params.get("mode");
@@ -966,10 +986,15 @@ function siteDomainOf(host) {
966
986
  const keep = TWO_PART_SUFFIX.has(sld) && tld.length <= 3 ? 3 : 2;
967
987
  return labels.slice(-keep).join(".");
968
988
  }
969
- function sortItems(items, sort) {
989
+ function sortItems(items, sort, recents) {
970
990
  const out = [...items];
971
- const byName = (a, b) => a.name.localeCompare(b.name, void 0, { sensitivity: "base" });
991
+ const byName = (a, b) => a.name.localeCompare(b.name, void 0, { sensitivity: "base", numeric: true });
972
992
  if (sort === "name") return out.sort(byName);
993
+ if (sort === "name-desc") return out.sort((a, b) => byName(b, a));
994
+ if (sort === "viewed") {
995
+ const at = new Map((recents ?? []).map((id, i) => [id, i]));
996
+ return out.sort((a, b) => (at.get(a.id) ?? Infinity) - (at.get(b.id) ?? Infinity) || byName(a, b));
997
+ }
973
998
  if (sort === "website")
974
999
  return out.sort((a, b) => {
975
1000
  const x = loginSiteOf(a), y = loginSiteOf(b);
@@ -2205,7 +2230,7 @@ function TotpEditRow({ value, onChange, hasExisting, item, port, onEnrolled, onR
2205
2230
  setStatus(null);
2206
2231
  onChange(v);
2207
2232
  },
2208
- placeholder: hasExisting ? "Paste a new key to replace" : "Setup key or otpauth link",
2233
+ placeholder: hasExisting ? "Paste a new key to replace" : "Paste setup key or otpauth link",
2209
2234
  status,
2210
2235
  ...uploadImage ? { onImage: (f) => void uploadImage(f) } : {},
2211
2236
  ...onRecognized ? { onRecognized } : {}
@@ -2661,6 +2686,18 @@ function withoutCode(codes, index) {
2661
2686
  const left = codes.filter((_, i) => i !== index);
2662
2687
  return left.length ? left.join("\n") : null;
2663
2688
  }
2689
+ function parseEnvAssignment(text) {
2690
+ const m = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=(.*)$/s.exec(text.trim());
2691
+ if (!m || /\n/.test(m[2] ?? "")) return null;
2692
+ let value = (m[2] ?? "").trim();
2693
+ const q = value[0];
2694
+ if ((q === '"' || q === "'") && value.length >= 2 && value.endsWith(q)) value = value.slice(1, -1);
2695
+ return value ? { key: m[1] ?? "", value } : null;
2696
+ }
2697
+ function labelFromEnvKey(key) {
2698
+ const words = key.toLowerCase().split(/[_\s]+/).filter(Boolean).join(" ");
2699
+ return words ? words.charAt(0).toUpperCase() + words.slice(1) : key;
2700
+ }
2664
2701
 
2665
2702
  // src/fields/SettingsPanels.tsx
2666
2703
  var import_jsx_runtime14 = require("react/jsx-runtime");
@@ -3055,11 +3092,11 @@ function PasswordGenerator({ limits: source, onUse, useLabel = "Use" }) {
3055
3092
  /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_controls11.Button, { variant: "primary", disabled: !candidate, onClick: use, children: useLabel })
3056
3093
  ] });
3057
3094
  }
3058
- function OptionLine({ label, hint, children }) {
3095
+ function OptionLine({ label, hint: hint2, children }) {
3059
3096
  return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex min-h-9 items-center justify-between gap-3", children: [
3060
3097
  /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex min-w-0 flex-col", children: [
3061
3098
  /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "truncate text-sm text-foreground", children: label }),
3062
- hint ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "truncate text-xs text-muted-foreground", children: hint }) : null
3099
+ hint2 ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "truncate text-xs text-muted-foreground", children: hint2 }) : null
3063
3100
  ] }),
3064
3101
  /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "flex shrink-0 items-center", children })
3065
3102
  ] });
@@ -4782,17 +4819,18 @@ function Notices({ draft }) {
4782
4819
  }
4783
4820
 
4784
4821
  // src/ItemList.tsx
4785
- var import_react28 = require("react");
4786
- var import_design_system18 = require("@ai-matrx/design-system");
4822
+ var import_react29 = require("react");
4787
4823
  var import_design_system19 = require("@ai-matrx/design-system");
4788
- var import_controls22 = require("@ai-matrx/design-system/controls");
4824
+ var import_design_system20 = require("@ai-matrx/design-system");
4825
+ var import_controls23 = require("@ai-matrx/design-system/controls");
4826
+ var import_icons12 = require("@ai-matrx/design-system/icons");
4789
4827
 
4790
4828
  // src/ItemPane.tsx
4791
- var import_react27 = require("react");
4792
- var import_design_system16 = require("@ai-matrx/design-system");
4829
+ var import_react28 = require("react");
4793
4830
  var import_design_system17 = require("@ai-matrx/design-system");
4794
- var import_controls21 = require("@ai-matrx/design-system/controls");
4795
- var import_confirm_opener9 = require("@ai-matrx/kit/confirm-opener");
4831
+ var import_design_system18 = require("@ai-matrx/design-system");
4832
+ var import_controls22 = require("@ai-matrx/design-system/controls");
4833
+ var import_confirm_opener10 = require("@ai-matrx/kit/confirm-opener");
4796
4834
 
4797
4835
  // src/activity/FilesSection.tsx
4798
4836
  var import_format7 = require("@ai-matrx/kit/format");
@@ -4813,12 +4851,13 @@ var PROTECTION = [
4813
4851
  function FilesSection({ item, port, editing, onChanged }) {
4814
4852
  const confirmed = useConfirmed();
4815
4853
  const canEdit = editing && item.capabilities.canEdit;
4854
+ const canAdd = item.capabilities.canEdit;
4816
4855
  const [busy, setBusy] = (0, import_react21.useState)(null);
4817
4856
  const [error, setError] = (0, import_react21.useState)(null);
4818
4857
  const [pending, setPending] = (0, import_react21.useState)(null);
4819
4858
  const [dragging, setDragging] = (0, import_react21.useState)(false);
4820
4859
  const picker = (0, import_react21.useRef)(null);
4821
- if (!canEdit && item.attachments.length === 0) return null;
4860
+ if (!canAdd && item.attachments.length === 0) return null;
4822
4861
  async function run(key, work, fallback) {
4823
4862
  setBusy(key);
4824
4863
  setError(null);
@@ -4840,7 +4879,7 @@ function FilesSection({ item, port, editing, onChanged }) {
4840
4879
  setPending(file);
4841
4880
  }
4842
4881
  function drop(e) {
4843
- if (!canEdit) return;
4882
+ if (!canAdd) return;
4844
4883
  e.preventDefault();
4845
4884
  setDragging(false);
4846
4885
  choose(e.dataTransfer.files[0]);
@@ -4853,22 +4892,23 @@ function FilesSection({ item, port, editing, onChanged }) {
4853
4892
  "div",
4854
4893
  {
4855
4894
  className: (0, import_design_system13.cn)("rounded-xl", dragging && "outline outline-2 outline-primary"),
4856
- onDragOver: canEdit ? (e) => {
4895
+ onDragOver: canAdd ? (e) => {
4857
4896
  e.preventDefault();
4858
4897
  setDragging(true);
4859
4898
  } : void 0,
4860
- onDragLeave: canEdit ? () => setDragging(false) : void 0,
4861
- onDrop: canEdit ? drop : void 0,
4899
+ onDragLeave: canAdd ? () => setDragging(false) : void 0,
4900
+ onDrop: canAdd ? drop : void 0,
4862
4901
  children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
4863
4902
  VaultSection,
4864
4903
  {
4865
- title: "Files",
4866
- 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,
4904
+ title: editing || item.attachments.length > 0 || pending ? "Files" : void 0,
4905
+ actions: canAdd && (editing || item.attachments.length > 0) ? /* @__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,
4867
4906
  children: [
4868
- canEdit ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("input", { ref: picker, type: "file", hidden: true, onChange: (e) => {
4907
+ canAdd ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("input", { ref: picker, type: "file", hidden: true, "aria-label": "Choose a file", onChange: (e) => {
4869
4908
  choose(e.target.files?.[0]);
4870
4909
  e.target.value = "";
4871
4910
  } }) : null,
4911
+ !editing && canAdd && item.attachments.length === 0 && !pending ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(AddRow, { label: "Files", onAdd: () => picker.current?.click(), children: "Add file" }) : null,
4872
4912
  item.attachments.map(
4873
4913
  (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)(
4874
4914
  VaultRow,
@@ -4881,7 +4921,7 @@ function FilesSection({ item, port, editing, onChanged }) {
4881
4921
  a.id
4882
4922
  )
4883
4923
  ),
4884
- canEdit && pending ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(NewFile, { file: pending, busy: busy === "add", onCancel: () => setPending(null), onAdd: async (details) => {
4924
+ canAdd && pending ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(NewFile, { file: pending, busy: busy === "add", onCancel: () => setPending(null), onAdd: async (details) => {
4885
4925
  if (await run("add", () => port.activity.addFile(item, pending, details), "The file could not be added.")) setPending(null);
4886
4926
  } }) : null,
4887
4927
  canEdit && item.attachments.length === 0 && !pending ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "px-4 py-3 text-sm text-muted-foreground", children: "Drop a file here or choose Add file" }) : null,
@@ -5002,6 +5042,57 @@ function confirmSeal(label) {
5002
5042
  variant: "destructive"
5003
5043
  });
5004
5044
  }
5045
+ function DraftFilesSection({ files, onFiles }) {
5046
+ const [pending, setPending] = (0, import_react21.useState)(null);
5047
+ const [error, setError] = (0, import_react21.useState)(null);
5048
+ const [dragging, setDragging] = (0, import_react21.useState)(false);
5049
+ const picker = (0, import_react21.useRef)(null);
5050
+ const choose = (file) => {
5051
+ if (!file) return;
5052
+ if (fileTooBig(file.size)) return setError(TOO_BIG);
5053
+ setError(null);
5054
+ setPending(file);
5055
+ };
5056
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5057
+ "div",
5058
+ {
5059
+ className: (0, import_design_system13.cn)("rounded-xl", dragging && "outline outline-2 outline-primary"),
5060
+ onDragOver: (e) => {
5061
+ e.preventDefault();
5062
+ setDragging(true);
5063
+ },
5064
+ onDragLeave: () => setDragging(false),
5065
+ onDrop: (e) => {
5066
+ e.preventDefault();
5067
+ setDragging(false);
5068
+ choose(e.dataTransfer.files[0]);
5069
+ },
5070
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(VaultSection, { title: files.length > 0 || pending ? "Files" : void 0, actions: files.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(PlusGlyph, {}), onClick: () => picker.current?.click(), children: "Add file" }) : void 0, children: [
5071
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("input", { ref: picker, type: "file", hidden: true, "aria-label": "Choose a file", onChange: (e) => {
5072
+ choose(e.target.files?.[0]);
5073
+ e.target.value = "";
5074
+ } }),
5075
+ files.map((f, i) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(VaultRow, { label: f.label, hint: f.description ?? void 0, actions: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_controls16.Button, { variant: "quiet", removes: true, icon: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(XGlyph, {}), "aria-label": `Remove ${f.label}`, onClick: () => onFiles(files.filter((_, j) => j !== i)) }), children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "flex min-w-0 items-center gap-2", children: [
5076
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "truncate", children: f.file.name }),
5077
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground", children: (0, import_format7.formatFileSize)(f.file.size) })
5078
+ ] }) }, `${f.file.name}-${i}`)),
5079
+ pending ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5080
+ NewFile,
5081
+ {
5082
+ file: pending,
5083
+ busy: false,
5084
+ onCancel: () => setPending(null),
5085
+ onAdd: async (d) => {
5086
+ onFiles([...files, { file: pending, ...d }]);
5087
+ setPending(null);
5088
+ }
5089
+ }
5090
+ ) : files.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(AddRow, { label: "Files", onAdd: () => picker.current?.click(), children: "Add file" }) : null,
5091
+ error ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { role: "alert", className: "px-4 py-2 text-sm text-destructive", children: error }) : null
5092
+ ] })
5093
+ }
5094
+ );
5095
+ }
5005
5096
 
5006
5097
  // src/fields/RecoveryCodesRow.tsx
5007
5098
  var import_react22 = require("react");
@@ -5109,6 +5200,134 @@ function RecoveryCodesRow({ item, field, port, onChanged }) {
5109
5200
  );
5110
5201
  }
5111
5202
 
5203
+ // src/fields/DraftRows.tsx
5204
+ var import_react23 = require("react");
5205
+ var import_controls18 = require("@ai-matrx/design-system/controls");
5206
+ var import_design_system14 = require("@ai-matrx/design-system");
5207
+ var import_confirm_opener7 = require("@ai-matrx/kit/confirm-opener");
5208
+ var import_jsx_runtime22 = require("react/jsx-runtime");
5209
+ var HANDLINGS = ["visible", "revealable", "sealed"];
5210
+ var hint = (text, tone = "muted") => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: tone === "destructive" ? "text-destructive" : void 0, title: text, children: text });
5211
+ var hasSecretSettings = (s) => Boolean(s.envKey?.trim() || s.injectIntoSandbox || s.handling && s.handling !== "revealable");
5212
+ function SecretBuilderRow({ field, onChange, onRemove }) {
5213
+ const [open, setOpen] = (0, import_react23.useState)(hasSecretSettings(field));
5214
+ const env = field.envKey ?? "";
5215
+ const envProblem = envKeyProblem(env);
5216
+ const envOk = env.trim() !== "" && !envProblem;
5217
+ const handling = field.handling ?? "revealable";
5218
+ const name = field.label.trim() || "Secret";
5219
+ const chooseHandling = async (next) => {
5220
+ if (next === handling) return;
5221
+ if (next === "sealed") {
5222
+ const ok = await (0, import_confirm_opener7.confirm)({
5223
+ title: `Seal ${name} permanently?`,
5224
+ description: "Once saved, no person can see or copy it again; only automation can use it.",
5225
+ confirmLabel: "Seal",
5226
+ variant: "destructive"
5227
+ });
5228
+ if (!ok) return;
5229
+ }
5230
+ onChange({ handling: next });
5231
+ };
5232
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
5233
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
5234
+ CustomEditRow,
5235
+ {
5236
+ label: field.label,
5237
+ value: field.value,
5238
+ secret: true,
5239
+ onLabel: (v) => onChange({ label: v }),
5240
+ onValue: (v) => onChange({ value: v }),
5241
+ onRemove,
5242
+ onPasteValue: (text) => {
5243
+ const a = parseEnvAssignment(text);
5244
+ if (!a) return false;
5245
+ onChange({ envKey: a.key, value: a.value, ...field.label.trim() ? {} : { label: labelFromEnvKey(a.key) } });
5246
+ setOpen(true);
5247
+ return true;
5248
+ },
5249
+ extra: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
5250
+ handling !== "sealed" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(GenerateButton, { onUse: (v) => onChange({ value: v }) }) : null,
5251
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_controls18.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SlidersGlyph, {}), "aria-label": `${name} settings`, pressed: open, onClick: () => setOpen((o) => !o) })
5252
+ ] })
5253
+ }
5254
+ ),
5255
+ open ? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
5256
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(VaultRow, { label: "Env key", hint: envProblem ? hint(envProblem, "destructive") : hint("The name sandboxes and workflows use"), children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
5257
+ import_controls18.Field,
5258
+ {
5259
+ className: "w-full font-mono",
5260
+ "aria-label": `${name} env key`,
5261
+ "aria-invalid": Boolean(envProblem),
5262
+ placeholder: "e.g. GITHUB_TOKEN",
5263
+ autoComplete: "off",
5264
+ spellCheck: false,
5265
+ value: env,
5266
+ onChange: (e) => onChange({ envKey: e.target.value, ...e.target.value.trim() ? {} : { injectIntoSandbox: false } })
5267
+ }
5268
+ ) }),
5269
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(VaultRow, { label: "Who can see it", hint: hint(HANDLING_WORDS[handling].hint), children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
5270
+ import_controls18.SegmentedControl,
5271
+ {
5272
+ "aria-label": `Who can see ${name}`,
5273
+ value: handling,
5274
+ onValueChange: (v) => void chooseHandling(v),
5275
+ data: HANDLINGS.map((h) => ({ value: h, label: HANDLING_WORDS[h].label, title: HANDLING_WORDS[h].hint }))
5276
+ }
5277
+ ) }),
5278
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(VaultRow, { label: "Use in sandbox", hint: envOk ? hint("Sandboxes get it as an env variable") : hint("Needs an env key"), children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_controls18.Switch, { "aria-label": `Use ${name} in sandbox`, checked: envOk && field.injectIntoSandbox === true, disabled: !envOk, onCheckedChange: (v) => onChange({ injectIntoSandbox: v }) }) })
5279
+ ] }) : null
5280
+ ] });
5281
+ }
5282
+ function withMfaMethod(custom, v) {
5283
+ const rest = custom.filter((c) => c.key !== MFA_METHOD_KEY);
5284
+ return v === "sms" || v === "push_or_other" ? [...rest, { key: MFA_METHOD_KEY, label: "Two-factor method", value: v }] : rest;
5285
+ }
5286
+ function DraftTwoFactorRow({ custom, onCustom }) {
5287
+ const value = custom.find((c) => c.key === MFA_METHOD_KEY)?.value || "none";
5288
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(VaultRow, { label: "Two-factor", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
5289
+ import_controls18.Select,
5290
+ {
5291
+ value: value === "sms" || value === "push_or_other" ? value : "none",
5292
+ "aria-label": "Two-factor method",
5293
+ options: MFA_OPTIONS.map((o) => ({ value: o.value, label: o.label })),
5294
+ onValueChange: (v) => onCustom(withMfaMethod(custom, v))
5295
+ }
5296
+ ) });
5297
+ }
5298
+ var defaultBrowserSettings = (hasWebsite) => ({ uriMatchMode: "host", browserFillEnabled: hasWebsite });
5299
+ function DraftBrowserRows({ value, hasWebsite, onChange }) {
5300
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
5301
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(VaultRow, { label: "Website matching", hint: hint(MATCH_WORDS[value.uriMatchMode].hint), children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
5302
+ import_controls18.Select,
5303
+ {
5304
+ "aria-label": "Website matching",
5305
+ value: value.uriMatchMode,
5306
+ options: MATCH_MODES.map((m) => ({ value: m, label: MATCH_WORDS[m].label })),
5307
+ onValueChange: (m) => onChange({ ...value, uriMatchMode: m })
5308
+ }
5309
+ ) }),
5310
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(VaultRow, { label: "Fill in browser", hint: hint(hasWebsite ? value.browserFillEnabled ? "Offered on matching pages" : "Never filled automatically" : "Add a website first"), children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_controls18.Switch, { "aria-label": "Fill in browser", checked: hasWebsite && value.browserFillEnabled, disabled: !hasWebsite, onCheckedChange: (v) => onChange({ ...value, browserFillEnabled: v }) }) })
5311
+ ] });
5312
+ }
5313
+ function AssignResult({ sent, onAnother, onDone }) {
5314
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "mx-auto flex w-full max-w-3xl flex-col gap-5 px-3 py-4 sm:px-6 sm:py-6", role: "status", children: [
5315
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(VaultSection, { title: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { className: "flex items-center gap-1.5", children: [
5316
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CheckGlyph, { className: "size-4 text-success" }),
5317
+ "Sent to ",
5318
+ sent.recipientEmail
5319
+ ] }), children: [
5320
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(VaultRow, { label: "Name", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "block truncate", children: sent.name }) }),
5321
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(VaultRow, { label: "Item ID", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_design_system14.RecordId, { value: sent.id, label: "Item" }) }),
5322
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(VaultRow, { label: "Password", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "block truncate text-muted-foreground", children: sent.generated ? "Generated privately, never shown to you" : "Theirs now; you keep no access" }) })
5323
+ ] }),
5324
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex justify-end gap-2", children: [
5325
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_controls18.Button, { variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(PlusGlyph, {}), onClick: onAnother, children: "Create another" }),
5326
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_controls18.Button, { variant: "primary", onClick: onDone, children: "Done" })
5327
+ ] })
5328
+ ] });
5329
+ }
5330
+
5112
5331
  // src/ItemPane.tsx
5113
5332
  var import_icons11 = require("@ai-matrx/design-system/icons");
5114
5333
  var import_drafts = require("@ai-matrx/kit/drafts");
@@ -5235,15 +5454,15 @@ function targetLabel(t) {
5235
5454
  }
5236
5455
 
5237
5456
  // src/extension/UseOnSiteButton.tsx
5238
- var import_react23 = require("react");
5239
- var import_controls18 = require("@ai-matrx/design-system/controls");
5240
- var import_jsx_runtime22 = require("react/jsx-runtime");
5457
+ var import_react24 = require("react");
5458
+ var import_controls19 = require("@ai-matrx/design-system/controls");
5459
+ var import_jsx_runtime23 = require("react/jsx-runtime");
5241
5460
  function canUseOnSite(item, pageUrl) {
5242
5461
  return item.capabilities.canEdit && isFillablePage(pageUrl) && !coversPage(item.loginUrls, item.uriMatchMode, pageUrl);
5243
5462
  }
5244
5463
  function UseOnSiteButton({ port, item, pageUrl, onChanged }) {
5245
5464
  const notify = useNotify();
5246
- const [busy, setBusy] = (0, import_react23.useState)(false);
5465
+ const [busy, setBusy] = (0, import_react24.useState)(false);
5247
5466
  if (!canUseOnSite(item, pageUrl)) return null;
5248
5467
  const site = pageSite(pageUrl);
5249
5468
  const run = async () => {
@@ -5258,14 +5477,14 @@ function UseOnSiteButton({ port, item, pageUrl, onChanged }) {
5258
5477
  setBusy(false);
5259
5478
  }
5260
5479
  };
5261
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_controls18.Button, { variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(PlusGlyph, {}), disabled: busy, onClick: () => void run(), title: `Fill this login on ${site}`, children: "Use here" });
5480
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_controls19.Button, { variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PlusGlyph, {}), disabled: busy, onClick: () => void run(), title: `Fill this login on ${site}`, children: "Use here" });
5262
5481
  }
5263
5482
 
5264
5483
  // src/sharing/SharePanel.tsx
5265
- var import_react26 = require("react");
5266
- var import_confirm_opener8 = require("@ai-matrx/kit/confirm-opener");
5267
- var import_controls20 = require("@ai-matrx/design-system/controls");
5268
- var import_design_system15 = require("@ai-matrx/design-system");
5484
+ var import_react27 = require("react");
5485
+ var import_confirm_opener9 = require("@ai-matrx/kit/confirm-opener");
5486
+ var import_controls21 = require("@ai-matrx/design-system/controls");
5487
+ var import_design_system16 = require("@ai-matrx/design-system");
5269
5488
  var import_icons10 = require("@ai-matrx/design-system/icons");
5270
5489
 
5271
5490
  // src/sharing/logic.ts
@@ -5320,18 +5539,18 @@ function shareSummary(grants) {
5320
5539
  var MEMBER_CHOICE_DEFAULT = "default";
5321
5540
 
5322
5541
  // src/sharing/parts.tsx
5323
- var import_react24 = require("react");
5324
- var import_design_system14 = require("@ai-matrx/design-system");
5325
- var import_jsx_runtime23 = require("react/jsx-runtime");
5542
+ var import_react25 = require("react");
5543
+ var import_design_system15 = require("@ai-matrx/design-system");
5544
+ var import_jsx_runtime24 = require("react/jsx-runtime");
5326
5545
  var message = (e, fallback) => {
5327
5546
  const m = e instanceof Error && e.message ? e.message : fallback;
5328
5547
  return copyRefusal(m) ?? m;
5329
5548
  };
5330
5549
  function useConfirmedChange() {
5331
5550
  const confirmed = useConfirmed();
5332
- const [busy, setBusy] = (0, import_react24.useState)(null);
5333
- const [error, setError] = (0, import_react24.useState)(null);
5334
- const [notice, setNotice] = (0, import_react24.useState)(null);
5551
+ const [busy, setBusy] = (0, import_react25.useState)(null);
5552
+ const [error, setError] = (0, import_react25.useState)(null);
5553
+ const [notice, setNotice] = (0, import_react25.useState)(null);
5335
5554
  async function run(key, fn, done) {
5336
5555
  setBusy(key);
5337
5556
  setError(null);
@@ -5350,33 +5569,33 @@ function useConfirmedChange() {
5350
5569
  return { busy, error, notice, run, setNotice };
5351
5570
  }
5352
5571
  function AccessLine({ glyph: G, who, meta, children }) {
5353
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex min-h-11 items-center gap-2 px-3 sm:px-4", children: [
5354
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(G, { className: "size-4 shrink-0 text-muted-foreground" }),
5355
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex min-w-0 flex-1 items-baseline gap-2", children: [
5356
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "truncate text-sm text-foreground", children: who }),
5357
- meta ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground", children: meta }) : null
5572
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex min-h-11 items-center gap-2 px-3 sm:px-4", children: [
5573
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(G, { className: "size-4 shrink-0 text-muted-foreground" }),
5574
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex min-w-0 flex-1 items-baseline gap-2", children: [
5575
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "truncate text-sm text-foreground", children: who }),
5576
+ meta ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground", children: meta }) : null
5358
5577
  ] }),
5359
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex shrink-0 items-center gap-0.5", children })
5578
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex shrink-0 items-center gap-0.5", children })
5360
5579
  ] });
5361
5580
  }
5362
5581
  function StatusLine({ error, notice }) {
5363
5582
  if (!error && !notice) return null;
5364
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: (0, import_design_system14.cn)("min-w-0 flex-1 line-clamp-2 text-sm", error ? "text-destructive" : "text-success"), title: error ?? notice ?? void 0, children: error ?? notice });
5583
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: (0, import_design_system15.cn)("min-w-0 flex-1 line-clamp-2 text-sm", error ? "text-destructive" : "text-success"), title: error ?? notice ?? void 0, children: error ?? notice });
5365
5584
  }
5366
5585
 
5367
5586
  // src/sharing/MovePanel.tsx
5368
- var import_react25 = require("react");
5369
- var import_confirm_opener7 = require("@ai-matrx/kit/confirm-opener");
5370
- var import_controls19 = require("@ai-matrx/design-system/controls");
5371
- var import_jsx_runtime24 = require("react/jsx-runtime");
5587
+ var import_react26 = require("react");
5588
+ var import_confirm_opener8 = require("@ai-matrx/kit/confirm-opener");
5589
+ var import_controls20 = require("@ai-matrx/design-system/controls");
5590
+ var import_jsx_runtime25 = require("react/jsx-runtime");
5372
5591
  var NONE = "__none__";
5373
5592
  function MovePanel({ item, port, organizations, onClose, onChanged }) {
5374
5593
  const { busy, error, notice, run, setNotice } = useConfirmedChange();
5375
5594
  const moves = moveDestinations(item, organizations);
5376
5595
  const copies = copyDestinations(organizations, item);
5377
- const [moveTo, setMoveTo] = (0, import_react25.useState)("");
5378
- const [copyTo, setCopyTo] = (0, import_react25.useState)("");
5379
- const [email, setEmail] = (0, import_react25.useState)("");
5596
+ const [moveTo, setMoveTo] = (0, import_react26.useState)("");
5597
+ const [copyTo, setCopyTo] = (0, import_react26.useState)("");
5598
+ const [email, setEmail] = (0, import_react26.useState)("");
5380
5599
  const passkey = isPasskey(item);
5381
5600
  const canMove = item.capabilities.canManage && !passkey && moves.length > 0;
5382
5601
  const canGive = item.capabilities.canManage && item.owner.kind === "me" && !passkey;
@@ -5386,7 +5605,7 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
5386
5605
  const move = async () => {
5387
5606
  if (!moveChoice) return;
5388
5607
  const to = destinationOf(moveChoice.value);
5389
- const ok = await (0, import_confirm_opener7.confirm)({
5608
+ const ok = await (0, import_confirm_opener8.confirm)({
5390
5609
  title: `Move to ${moveChoice.label}?`,
5391
5610
  description: `"${item.name}" stays the same item, so everything using it keeps working. ${itemMoveConsequence(item, to)}.`,
5392
5611
  confirmLabel: "Move"
@@ -5401,7 +5620,7 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
5401
5620
  const give = async () => {
5402
5621
  const to = email.trim();
5403
5622
  if (!isEmail(to)) return;
5404
- const ok = await (0, import_confirm_opener7.confirm)({ title: "Give ownership away?", description: giveDescription(item, to), confirmLabel: "Give ownership", variant: "destructive" });
5623
+ const ok = await (0, import_confirm_opener8.confirm)({ title: "Give ownership away?", description: giveDescription(item, to), confirmLabel: "Give ownership", variant: "destructive" });
5405
5624
  if (!ok) return;
5406
5625
  const out = await run("give", () => port.sharing.giveOwnership(item, to));
5407
5626
  if (!out) return;
@@ -5414,25 +5633,25 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
5414
5633
  if (made) onChanged();
5415
5634
  };
5416
5635
  const nothing = !canMove && !canGive && !canCopy;
5417
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5636
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5418
5637
  Panel,
5419
5638
  {
5420
5639
  title: "Move or copy",
5421
5640
  size: "md",
5422
5641
  onClose,
5423
- footer: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(PanelFooter, { status: error || notice ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(StatusLine, { error, notice }) : null, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_controls19.Button, { variant: "primary", onClick: onClose, children: "Done" }) }),
5424
- 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: [
5425
- canMove && moves.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5642
+ footer: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(PanelFooter, { status: error || notice ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(StatusLine, { error, notice }) : null, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Button, { variant: "primary", onClick: onClose, children: "Done" }) }),
5643
+ children: nothing ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(VaultSection, { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Empty, { children: passkey ? "A passkey stays where it was created." : "Only the owner can move or give this item." }) }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(VaultSection, { children: [
5644
+ canMove && moves.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5426
5645
  VaultRow,
5427
5646
  {
5428
5647
  label: "Move to",
5429
5648
  hint: moveChoice ? itemMoveConsequence(item, destinationOf(moveChoice.value)) : void 0,
5430
- actions: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_controls19.Button, { variant: "outline", disabled: busy !== null || !moveChoice, onClick: () => void move(), children: "Move" }),
5431
- 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] })
5649
+ actions: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Button, { variant: "outline", disabled: busy !== null || !moveChoice, onClick: () => void move(), children: "Move" }),
5650
+ children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Select, { className: "w-full", "aria-label": "Move to", value: moveTo || NONE, onValueChange: (v) => setMoveTo(v === NONE ? "" : v), options: [{ value: NONE, label: "Choose where" }, ...moves] })
5432
5651
  }
5433
5652
  ) : null,
5434
- 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)(
5435
- import_controls19.Field,
5653
+ canGive ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(VaultRow, { label: "Give to", hint: "You lose all access; your shares end", actions: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Button, { variant: "danger", disabled: busy !== null || !isEmail(email), onClick: () => void give(), children: "Give" }), children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5654
+ import_controls20.Field,
5436
5655
  {
5437
5656
  className: "w-full",
5438
5657
  type: "email",
@@ -5445,20 +5664,20 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
5445
5664
  onChange: (e) => setEmail(e.target.value)
5446
5665
  }
5447
5666
  ) }) : null,
5448
- 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
5667
+ canCopy && copies.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(VaultRow, { label: "Copy to", hint: "A separate item; edits no longer sync", actions: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Button, { variant: "outline", disabled: busy !== null || !copyChoice, onClick: () => void copy(), children: "Copy" }), children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Select, { className: "w-full", "aria-label": "Copy to", value: copyTo || NONE, onValueChange: (v) => setCopyTo(v === NONE ? "" : v), options: [{ value: NONE, label: "Choose where" }, ...copies] }) }) : null
5449
5668
  ] })
5450
5669
  }
5451
5670
  );
5452
5671
  }
5453
5672
 
5454
5673
  // src/sharing/SharePanel.tsx
5455
- var import_jsx_runtime25 = require("react/jsx-runtime");
5674
+ var import_jsx_runtime26 = require("react/jsx-runtime");
5456
5675
  function useGrants(port, item) {
5457
- const [grants, setGrants] = (0, import_react26.useState)(null);
5458
- const [loadError, setLoadError] = (0, import_react26.useState)(null);
5459
- const [nonce, setNonce] = (0, import_react26.useState)(0);
5676
+ const [grants, setGrants] = (0, import_react27.useState)(null);
5677
+ const [loadError, setLoadError] = (0, import_react27.useState)(null);
5678
+ const [nonce, setNonce] = (0, import_react27.useState)(0);
5460
5679
  const allowed = item.capabilities.canManage;
5461
- (0, import_react26.useEffect)(() => {
5680
+ (0, import_react27.useEffect)(() => {
5462
5681
  if (!allowed) return;
5463
5682
  let live = true;
5464
5683
  setLoadError(null);
@@ -5475,9 +5694,9 @@ function useGrants(port, item) {
5475
5694
  function SharePanel({ item, port, organizations, onClose, onChanged }) {
5476
5695
  const { grants, setGrants, loadError, reload } = useGrants(port, item);
5477
5696
  const { busy, error, notice, run } = useConfirmedChange();
5478
- const [email, setEmail] = (0, import_react26.useState)("");
5479
- const [level, setLevel] = (0, import_react26.useState)("use");
5480
- const [more, setMore] = (0, import_react26.useState)(false);
5697
+ const [email, setEmail] = (0, import_react27.useState)("");
5698
+ const [level, setLevel] = (0, import_react27.useState)("use");
5699
+ const [more, setMore] = (0, import_react27.useState)(false);
5481
5700
  const isOrg = item.owner.kind === "organization" && item.owner.organizationId !== null;
5482
5701
  const orgName = item.owner.label;
5483
5702
  const people = (grants ?? []).filter((g) => g.kind === "person");
@@ -5496,7 +5715,7 @@ function SharePanel({ item, port, organizations, onClose, onChanged }) {
5496
5715
  if (updated) setGrants((all) => (all ?? []).map((x) => x.id === g.id ? { ...updated, label: updated.label || g.label } : x));
5497
5716
  };
5498
5717
  const revoke = async (g) => {
5499
- const ok = await (0, import_confirm_opener8.confirm)({
5718
+ const ok = await (0, import_confirm_opener9.confirm)({
5500
5719
  title: g.kind === "organization" ? `Remove from ${g.label}?` : "Remove access?",
5501
5720
  description: g.kind === "organization" ? `${g.label} members can no longer use "${item.name}". It stays in your vault.` : `${g.label} can no longer use "${item.name}". This takes effect at once.`,
5502
5721
  confirmLabel: "Remove",
@@ -5512,7 +5731,7 @@ function SharePanel({ item, port, organizations, onClose, onChanged }) {
5512
5731
  const setMode = async (mode) => {
5513
5732
  if (mode === (item.accessMode === "restricted" ? "restricted" : "all_members")) return;
5514
5733
  if (mode === "all_members" && people.length > 0) {
5515
- const ok = await (0, import_confirm_opener8.confirm)({
5734
+ const ok = await (0, import_confirm_opener9.confirm)({
5516
5735
  title: "Open to every member?",
5517
5736
  description: `Every member of ${orgName} gets it at their own vault access. The ${people.length === 1 ? "person" : `${people.length} people`} listed here lose their own access.`,
5518
5737
  confirmLabel: "Open to members",
@@ -5527,20 +5746,20 @@ function SharePanel({ item, port, organizations, onClose, onChanged }) {
5527
5746
  }
5528
5747
  };
5529
5748
  if (!item.capabilities.canManage) {
5530
- 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." }) }) });
5749
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Panel, { title: "Share", size: "md", onClose, footer: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.Button, { variant: "primary", onClick: onClose, children: "Done" }), children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(VaultSection, { children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Empty, { children: "Only the owner can change who has access." }) }) });
5531
5750
  }
5532
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
5751
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
5533
5752
  Panel,
5534
5753
  {
5535
5754
  title: "Share",
5536
5755
  size: "md",
5537
5756
  onClose,
5538
- footer: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(PanelFooter, { status: error || notice ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(StatusLine, { error, notice }) : null, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Button, { variant: "primary", onClick: onClose, children: "Done" }) }),
5757
+ footer: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PanelFooter, { status: error || notice ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(StatusLine, { error, notice }) : null, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.Button, { variant: "primary", onClick: onClose, children: "Done" }) }),
5539
5758
  children: [
5540
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(VaultSection, { title: "Who has access", children: [
5541
- 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" }) }),
5542
- isOrg ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(AccessLine, { glyph: import_icons10.UsersIcon, who: `${orgName} members`, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5543
- import_controls20.Select,
5759
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(VaultSection, { title: "Who has access", children: [
5760
+ isOrg ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AccessLine, { glyph: BuildingGlyph, who: `${orgName} admins`, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "px-2 text-sm text-muted-foreground", children: "Full access" }) }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AccessLine, { glyph: PersonGlyph, who: "You", meta: "Owner", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "px-2 text-sm text-muted-foreground", children: "Full access" }) }),
5761
+ isOrg ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AccessLine, { glyph: import_icons10.UsersIcon, who: `${orgName} members`, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5762
+ import_controls21.Select,
5544
5763
  {
5545
5764
  variant: "inline",
5546
5765
  align: "end",
@@ -5554,14 +5773,14 @@ function SharePanel({ item, port, organizations, onClose, onChanged }) {
5554
5773
  ]
5555
5774
  }
5556
5775
  ) }) : null,
5557
- loadError ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(AccessLine, { glyph: XGlyph, who: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "text-destructive", children: loadError }), children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Button, { variant: "quiet", onClick: reload, children: "Retry" }) }) : grants === null ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.RegionSkeleton, { shape: "rows", count: 2, "aria-label": "Loading who has access", className: "px-3 sm:px-4" }) : grants.map((g) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(AccessLine, { glyph: g.kind === "organization" ? BuildingGlyph : PersonGlyph, who: g.label, ...g.kind === "organization" ? { meta: "Organization vault" } : {}, children: [
5558
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Select, { variant: "inline", align: "end", "aria-label": `What ${g.label} can do`, disabled: busy !== null, value: g.level, onValueChange: (v) => void change(g, v), options: LEVEL_OPTIONS }),
5559
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Button, { variant: "quiet", removes: true, icon: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(XGlyph, {}), "aria-label": `Remove ${g.label}`, disabled: busy !== null, onClick: () => void revoke(g) })
5776
+ loadError ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AccessLine, { glyph: XGlyph, who: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-destructive", children: loadError }), children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.Button, { variant: "quiet", onClick: reload, children: "Retry" }) }) : grants === null ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.RegionSkeleton, { shape: "rows", count: 2, "aria-label": "Loading who has access", className: "px-3 sm:px-4" }) : grants.map((g) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(AccessLine, { glyph: g.kind === "organization" ? BuildingGlyph : PersonGlyph, who: g.label, ...g.kind === "organization" ? { meta: "Organization vault" } : {}, children: [
5777
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.Select, { variant: "inline", align: "end", "aria-label": `What ${g.label} can do`, disabled: busy !== null, value: g.level, onValueChange: (v) => void change(g, v), options: LEVEL_OPTIONS }),
5778
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.Button, { variant: "quiet", removes: true, icon: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(XGlyph, {}), "aria-label": `Remove ${g.label}`, disabled: busy !== null, onClick: () => void revoke(g) })
5560
5779
  ] }, g.id)),
5561
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex min-h-11 items-center gap-2 px-3 sm:px-4", children: [
5562
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(PersonGlyph, { className: "size-4 shrink-0 text-muted-foreground" }),
5563
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5564
- import_controls20.Field,
5780
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex min-h-11 items-center gap-2 px-3 sm:px-4", children: [
5781
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PersonGlyph, { className: "size-4 shrink-0 text-muted-foreground" }),
5782
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5783
+ import_controls21.Field,
5565
5784
  {
5566
5785
  className: "min-w-0 flex-1",
5567
5786
  type: "email",
@@ -5581,13 +5800,13 @@ function SharePanel({ item, port, organizations, onClose, onChanged }) {
5581
5800
  }
5582
5801
  }
5583
5802
  ),
5584
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Select, { variant: "inline", align: "end", "aria-label": "What they can do", value: level, onValueChange: setLevel, options: LEVEL_OPTIONS }),
5585
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Button, { variant: "primary", disabled: busy !== null || !isEmail(email), onClick: () => void add(), children: "Share" })
5803
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.Select, { variant: "inline", align: "end", "aria-label": "What they can do", value: level, onValueChange: setLevel, options: LEVEL_OPTIONS }),
5804
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.Button, { variant: "primary", disabled: busy !== null || !isEmail(email), onClick: () => void add(), children: "Share" })
5586
5805
  ] })
5587
5806
  ] }),
5588
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-3", children: [
5589
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.DisclosureHeader, { open: more, title: "More options", onClick: () => setMore((o) => !o) }),
5590
- more ? isOrg && item.owner.organizationId ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(MemberAccess, { port, organizationId: item.owner.organizationId, organizationName: orgName }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(IntoOrganization, { item, port, organizations, grants: grants ?? [], onShared: (g) => setGrants((all) => [...(all ?? []).filter((x) => x.id !== g.id), g]) }) : null
5807
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-col gap-3", children: [
5808
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.DisclosureHeader, { open: more, title: "More options", onClick: () => setMore((o) => !o) }),
5809
+ more ? isOrg && item.owner.organizationId ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(MemberAccess, { port, organizationId: item.owner.organizationId, organizationName: orgName }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(IntoOrganization, { item, port, organizations, grants: grants ?? [], onShared: (g) => setGrants((all) => [...(all ?? []).filter((x) => x.id !== g.id), g]) }) : null
5591
5810
  ] })
5592
5811
  ]
5593
5812
  }
@@ -5596,17 +5815,17 @@ function SharePanel({ item, port, organizations, onClose, onChanged }) {
5596
5815
  function IntoOrganization({ item, port, organizations, grants, onShared }) {
5597
5816
  const { busy, error, notice, run } = useConfirmedChange();
5598
5817
  const open = organizations.filter((o) => !grants.some((g) => g.organizationId === o.id));
5599
- const [target, setTarget] = (0, import_react26.useState)("");
5600
- const [level, setLevel] = (0, import_react26.useState)("use");
5818
+ const [target, setTarget] = (0, import_react27.useState)("");
5819
+ const [level, setLevel] = (0, import_react27.useState)("use");
5601
5820
  const chosen = open.find((o) => o.id === target);
5602
5821
  if (item.owner.kind !== "me") return null;
5603
- 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: [
5604
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex min-h-11 items-center gap-2 px-3 sm:px-4", children: [
5605
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(BuildingGlyph, { className: "size-4 shrink-0 text-muted-foreground" }),
5606
- /* @__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 }))] }),
5607
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_controls20.Select, { variant: "inline", align: "end", "aria-label": "What its members can do", value: level, onValueChange: setLevel, options: LEVEL_OPTIONS }),
5608
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5609
- import_controls20.Button,
5822
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(VaultSection, { title: "Share into organization", children: open.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
5823
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex min-h-11 items-center gap-2 px-3 sm:px-4", children: [
5824
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(BuildingGlyph, { className: "size-4 shrink-0 text-muted-foreground" }),
5825
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.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 }))] }),
5826
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.Select, { variant: "inline", align: "end", "aria-label": "What its members can do", value: level, onValueChange: setLevel, options: LEVEL_OPTIONS }),
5827
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5828
+ import_controls21.Button,
5610
5829
  {
5611
5830
  variant: "outline",
5612
5831
  disabled: busy !== null || !chosen,
@@ -5622,8 +5841,8 @@ function IntoOrganization({ item, port, organizations, grants, onShared }) {
5622
5841
  }
5623
5842
  )
5624
5843
  ] }),
5625
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { className: "truncate px-3 pb-1 text-xs text-muted-foreground sm:px-4", children: error ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "text-destructive", children: error }) : notice ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "text-success", children: notice }) : "It stays yours; its members can use it too" })
5626
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Empty, { children: organizations.length ? "Already in every organization you belong to." : "You are not in any organization." }) });
5844
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "truncate px-3 pb-1 text-xs text-muted-foreground sm:px-4", children: error ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-destructive", children: error }) : notice ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-success", children: notice }) : "It stays yours; its members can use it too" })
5845
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Empty, { children: organizations.length ? "Already in every organization you belong to." : "You are not in any organization." }) });
5627
5846
  }
5628
5847
  var CHOICES = [
5629
5848
  { value: MEMBER_CHOICE_DEFAULT, label: "Default" },
@@ -5632,10 +5851,10 @@ var CHOICES = [
5632
5851
  { value: "editor", label: "Can edit", meta: "See and change" }
5633
5852
  ];
5634
5853
  function MemberAccess({ port, organizationId, organizationName }) {
5635
- const [list, setList] = (0, import_react26.useState)(null);
5636
- const [loadError, setLoadError] = (0, import_react26.useState)(null);
5854
+ const [list, setList] = (0, import_react27.useState)(null);
5855
+ const [loadError, setLoadError] = (0, import_react27.useState)(null);
5637
5856
  const { busy, error, run } = useConfirmedChange();
5638
- (0, import_react26.useEffect)(() => {
5857
+ (0, import_react27.useEffect)(() => {
5639
5858
  let live = true;
5640
5859
  port.sharing.memberAccess(organizationId).then(
5641
5860
  (l) => live && setList(l),
@@ -5650,9 +5869,9 @@ function MemberAccess({ port, organizationId, organizationName }) {
5650
5869
  const effective = await run(userId, () => port.sharing.setMemberAccess(organizationId, userId, access));
5651
5870
  if (effective) setList((l) => l ? { ...l, members: l.members.map((m) => m.userId === userId ? { ...m, access, effective } : m) } : l);
5652
5871
  };
5653
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(VaultSection, { title: `${organizationName} vault access`, children: [
5654
- 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)(
5655
- import_controls20.Select,
5872
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(VaultSection, { title: `${organizationName} vault access`, children: [
5873
+ loadError ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Empty, { children: loadError }) : list === null ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.RegionSkeleton, { shape: "rows", count: 3, "aria-label": "Loading member access", className: "px-3 sm:px-4" }) : list.members.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Empty, { children: "No members yet." }) : list.members.map((m) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AccessLine, { glyph: PersonGlyph, who: m.email || m.userId, meta: m.role, children: m.effective === "admin" ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "px-2 text-sm text-muted-foreground", children: MEMBER_ACCESS_LABEL.admin }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5874
+ import_controls21.Select,
5656
5875
  {
5657
5876
  variant: "inline",
5658
5877
  align: "end",
@@ -5663,13 +5882,13 @@ function MemberAccess({ port, organizationId, organizationName }) {
5663
5882
  options: CHOICES.map((c) => c.value === MEMBER_CHOICE_DEFAULT ? { value: c.value, label: `Default (${MEMBER_ACCESS_LABEL[list.defaultAccess]})` } : c.meta ? { value: c.value, label: c.label, meta: c.meta } : { value: c.value, label: c.label })
5664
5883
  }
5665
5884
  ) }, m.userId)),
5666
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { className: "truncate px-3 pb-1 text-xs text-muted-foreground sm:px-4", children: error ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "text-destructive", children: error }) : "Applies to every item in this organization" })
5885
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "truncate px-3 pb-1 text-xs text-muted-foreground sm:px-4", children: error ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-destructive", children: error }) : "Applies to every item in this organization" })
5667
5886
  ] });
5668
5887
  }
5669
5888
  function SharingSummary({ item, port, className }) {
5670
- const [text, setText] = (0, import_react26.useState)("");
5889
+ const [text, setText] = (0, import_react27.useState)("");
5671
5890
  const allowed = item.capabilities.canManage;
5672
- (0, import_react26.useEffect)(() => {
5891
+ (0, import_react27.useEffect)(() => {
5673
5892
  if (!allowed) return;
5674
5893
  let live = true;
5675
5894
  port.sharing.grants(item).then(
@@ -5681,12 +5900,12 @@ function SharingSummary({ item, port, className }) {
5681
5900
  };
5682
5901
  }, [port, item, allowed]);
5683
5902
  if (!allowed || !text) return null;
5684
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: (0, import_design_system15.cn)("truncate text-xs text-muted-foreground", className), children: text });
5903
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: (0, import_design_system16.cn)("truncate text-xs text-muted-foreground", className), children: text });
5685
5904
  }
5686
5905
 
5687
5906
  // src/ItemPane.tsx
5688
5907
  var import_format8 = require("@ai-matrx/kit/format");
5689
- var import_jsx_runtime26 = require("react/jsx-runtime");
5908
+ var import_jsx_runtime27 = require("react/jsx-runtime");
5690
5909
  var USERNAME_KEYS = /^(username|user_name|email|login|username_or_email|account_email)$/;
5691
5910
  function ItemPane(props) {
5692
5911
  const { port, item, definition, mode, host, organizations, defaultOwner, seed, onBack, onMode, onSaved, onDeleted, onDirty, onCancelNew, onPanel, onChanged, favorite, notice, refreshKey } = props;
@@ -5695,8 +5914,8 @@ function ItemPane(props) {
5695
5914
  const editing = mode !== "view";
5696
5915
  const seedName = seed?.name ?? "";
5697
5916
  const seedUrl = seed?.url ?? "";
5698
- const [loaded, setLoaded] = (0, import_react27.useState)({});
5699
- const base = (0, import_react27.useMemo)(() => {
5917
+ const [loaded, setLoaded] = (0, import_react28.useState)({});
5918
+ const base = (0, import_react28.useMemo)(() => {
5700
5919
  const b = draftOf(item);
5701
5920
  if (!item) {
5702
5921
  b.name = seedName;
@@ -5705,24 +5924,27 @@ function ItemPane(props) {
5705
5924
  b.values = { ...loaded };
5706
5925
  return b;
5707
5926
  }, [item, seedName, seedUrl, loaded]);
5708
- const [draft, setDraft] = (0, import_react27.useState)(base);
5709
- const [tagsText, setTagsText] = (0, import_react27.useState)(base.tags.join(", "));
5710
- const [showTags, setShowTags] = (0, import_react27.useState)(false);
5711
- const [showDescription, setShowDescription] = (0, import_react27.useState)(false);
5712
- const [showRecovery, setShowRecovery] = (0, import_react27.useState)(false);
5713
- const [settingUpOtp, setSettingUpOtp] = (0, import_react27.useState)(false);
5714
- const [owner, setOwner] = (0, import_react27.useState)(defaultOwner ?? "me");
5715
- const [recipient, setRecipient] = (0, import_react27.useState)("");
5716
- const [generatePrivately, setGeneratePrivately] = (0, import_react27.useState)(false);
5717
- const [busy, setBusy] = (0, import_react27.useState)(false);
5718
- const [error, setError] = (0, import_react27.useState)(null);
5719
- const [destinations, setDestinations] = (0, import_react27.useState)({});
5927
+ const [draft, setDraft] = (0, import_react28.useState)(base);
5928
+ const [tagsText, setTagsText] = (0, import_react28.useState)(base.tags.join(", "));
5929
+ const [showTags, setShowTags] = (0, import_react28.useState)(false);
5930
+ const [showDescription, setShowDescription] = (0, import_react28.useState)(false);
5931
+ const [showRecovery, setShowRecovery] = (0, import_react28.useState)(false);
5932
+ const [settingUpOtp, setSettingUpOtp] = (0, import_react28.useState)(false);
5933
+ const [owner, setOwner] = (0, import_react28.useState)(defaultOwner ?? "me");
5934
+ const [recipient, setRecipient] = (0, import_react28.useState)("");
5935
+ const [generatePrivately, setGeneratePrivately] = (0, import_react28.useState)(false);
5936
+ const [busy, setBusy] = (0, import_react28.useState)(false);
5937
+ const [sent, setSent] = (0, import_react28.useState)(null);
5938
+ const [queuedFiles, setQueuedFiles] = (0, import_react28.useState)([]);
5939
+ const [showBrowser, setShowBrowser] = (0, import_react28.useState)(false);
5940
+ const [error, setError] = (0, import_react28.useState)(null);
5941
+ const [destinations, setDestinations] = (0, import_react28.useState)({});
5720
5942
  const dirty = editing && isDirty(base, draft);
5721
5943
  const declared = definition?.fields ?? [];
5722
- const prev = (0, import_react27.useRef)(null);
5723
- const paneRef = (0, import_react27.useRef)(null);
5944
+ const prev = (0, import_react28.useRef)(null);
5945
+ const paneRef = (0, import_react28.useRef)(null);
5724
5946
  const room = useRoomOf(paneRef);
5725
- (0, import_react27.useEffect)(() => {
5947
+ (0, import_react28.useEffect)(() => {
5726
5948
  const was = prev.current;
5727
5949
  const id = item?.id ?? null;
5728
5950
  if (was && was.id === id && was.mode === mode && editing) {
@@ -5735,19 +5957,19 @@ function ItemPane(props) {
5735
5957
  }
5736
5958
  prev.current = { base, id, mode };
5737
5959
  }, [base, mode, item?.id, editing]);
5738
- (0, import_react27.useEffect)(() => {
5960
+ (0, import_react28.useEffect)(() => {
5739
5961
  setLoaded({});
5740
5962
  setShowTags(false);
5741
5963
  setShowDescription(false);
5742
5964
  setShowRecovery(false);
5743
5965
  }, [item?.id, mode]);
5744
- (0, import_react27.useEffect)(() => onDirty(dirty), [dirty, onDirty]);
5966
+ (0, import_react28.useEffect)(() => onDirty(dirty), [dirty, onDirty]);
5745
5967
  const keepKey = draftKey(item?.id ?? null, definition?.key ?? item?.definitionKey ?? null);
5746
- (0, import_react27.useEffect)(() => {
5968
+ (0, import_react28.useEffect)(() => {
5747
5969
  if (editing && dirty) (0, import_drafts.keepDraft)(keepKey, keptFieldsOf(draft), { basedOn: item?.updatedAt ?? "new" });
5748
5970
  else if (!editing) (0, import_drafts.dropKeptDraft)(keepKey);
5749
5971
  }, [editing, dirty, draft, keepKey, item?.updatedAt]);
5750
- (0, import_react27.useEffect)(() => {
5972
+ (0, import_react28.useEffect)(() => {
5751
5973
  if (!editing || !item) return;
5752
5974
  let live = true;
5753
5975
  for (const f of item.fields) {
@@ -5789,10 +6011,13 @@ function ItemPane(props) {
5789
6011
  const secretKey = declared.find((f) => f.storage === "encrypted" && f.kind === "secret")?.key ?? null;
5790
6012
  const r = await port.sharing.assign({ recipientEmail: recipient.trim(), definition, draft: out, generateFieldKey: generatePrivately ? secretKey : null });
5791
6013
  notify(`Sent to ${r.recipientEmail}`);
5792
- onCancelNew();
6014
+ (0, import_drafts.dropKeptDraft)(keepKey);
6015
+ onDirty(false);
6016
+ setSent(r);
5793
6017
  } else if (definition) {
5794
6018
  const r = await port.create(definition, owner === "me" ? null : owner, out);
5795
- const [next, n, enrolled] = await withOtp(r.item, r.notice);
6019
+ const [withCode, n0, enrolled] = await withOtp(r.item, r.notice);
6020
+ const [next, n] = await storeQueuedFiles(withCode, n0);
5796
6021
  (0, import_drafts.dropKeptDraft)(keepKey);
5797
6022
  onSaved(next, true, n, enrolled);
5798
6023
  }
@@ -5802,9 +6027,32 @@ function ItemPane(props) {
5802
6027
  setBusy(false);
5803
6028
  }
5804
6029
  }
6030
+ async function storeQueuedFiles(saved, notice2) {
6031
+ let next = saved;
6032
+ const failed = [];
6033
+ for (const q of queuedFiles) {
6034
+ try {
6035
+ next = await confirmed(() => port.activity.addFile(next, q.file, { label: q.label, description: q.description, handling: q.handling }));
6036
+ } catch {
6037
+ failed.push(q.label);
6038
+ }
6039
+ }
6040
+ setQueuedFiles([]);
6041
+ if (failed.length === 0) return [next, notice2];
6042
+ const said = `Saved, but ${failed.length === 1 ? `the file ${failed[0]} was` : `${failed.length} files were`} not stored. Add ${failed.length === 1 ? "it" : "them"} with Add file.`;
6043
+ return [next, notice2 ? `${notice2} ${said}` : said];
6044
+ }
6045
+ function createAnother() {
6046
+ setSent(null);
6047
+ setDraft(base);
6048
+ setTagsText(base.tags.join(", "));
6049
+ setQueuedFiles([]);
6050
+ setShowBrowser(false);
6051
+ setError(null);
6052
+ }
5805
6053
  async function remove() {
5806
6054
  if (!item) return;
5807
- const ok = await (0, import_confirm_opener9.confirm)({ title: `Delete \u201C${item.name}\u201D?`, description: "It moves to Trash. You can restore it from there.", confirmLabel: "Delete", variant: "destructive" });
6055
+ const ok = await (0, import_confirm_opener10.confirm)({ title: `Delete \u201C${item.name}\u201D?`, description: "It moves to Trash. You can restore it from there.", confirmLabel: "Delete", variant: "destructive" });
5808
6056
  if (!ok) return;
5809
6057
  setBusy(true);
5810
6058
  try {
@@ -5845,6 +6093,7 @@ function ItemPane(props) {
5845
6093
  onChanged();
5846
6094
  }
5847
6095
  }
6096
+ const fieldSettings = (f) => canEdit ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_controls22.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(SlidersGlyph, {}), "aria-label": `${f.label} settings`, title: `${f.label} settings`, onClick: () => onPanel(`field:${f.id}`) }) : null;
5848
6097
  const turnOnOne = canTurnOn ? (f) => () => turnOn([f]) : () => void 0;
5849
6098
  const declaredKeys = new Set(declared.map((f) => f.key));
5850
6099
  const extraFields = (item?.fields ?? []).filter((f) => !declaredKeys.has(f.key) && !draft.removed.includes(f.id) && !isAuthenticatorStorage(f.key));
@@ -5857,35 +6106,35 @@ function ItemPane(props) {
5857
6106
  const recoveryExtra = extraFields.some(isRecoveryCodesField);
5858
6107
  const offerRecovery = isLogin || Boolean(item?.authenticator) || draft.authenticator.trim() !== "";
5859
6108
  const recoveryEditing = !recoveryDeclared && !recoveryExtra && (showRecovery || (draft.values[RECOVERY_CODES_KEY] ?? "") !== "");
5860
- 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;
6109
+ const shownOwner = mode === "new" ? owner === "me" ? { label: "Personal", glyph: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(PersonGlyph, {}) } : owner === "person" ? { label: "Someone else", glyph: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(SendGlyph, {}) } : { label: organizations.find((o) => o.id === owner)?.name ?? "Organization", glyph: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(BuildingGlyph, {}) } : item ? { label: item.owner.label, glyph: item.owner.kind === "me" ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(PersonGlyph, {}) : item.owner.kind === "organization" ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(BuildingGlyph, {}) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_icons11.UsersIcon, {}) } : null;
5861
6110
  const sameNamed = (id) => {
5862
6111
  const name = organizations.find((o) => o.id === id)?.name.trim().toLowerCase();
5863
6112
  return Boolean(name) && organizations.filter((o) => o.name.trim().toLowerCase() === name).length > 1;
5864
6113
  };
5865
6114
  const tagsVisible = showTags || draft.tags.length > 0 || tagsText !== "";
5866
6115
  const descriptionVisible = showDescription || draft.description !== "";
5867
- 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: [
5868
- onBack ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ChevronLeftGlyph, {}), "aria-label": "Back", onClick: mode === "new" ? onCancelNew : onBack }) : null,
5869
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ItemIcon, { definitionKey: definition?.key ?? item?.definitionKey ?? "custom", family: definition?.family ?? "generic", site: item ? loginSiteOf(item) : loginSiteOf({ loginUrls: draft.loginUrls }), size: "lg" }),
5870
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col", children: [
5871
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h2", { className: "truncate text-base font-semibold leading-tight", children: editing ? draft.name || (mode === "new" ? `New ${typeLabel.toLowerCase()}` : item?.name) : item?.name }),
5872
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "flex min-w-0 items-center gap-1 text-xs text-muted-foreground", children: [
5873
- typeLabel ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "truncate", children: typeLabel }) : null,
5874
- shownOwner ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.Badge, { className: "shrink-0", icon: shownOwner.glyph, "aria-label": `Saved in ${shownOwner.label}`, children: shownOwner.label }) : null,
5875
- item && !editing ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(SharingSummary, { item, port, className: "hidden truncate before:mr-1 before:content-['\xB7'] sm:inline" }, `${item.updatedAt}-${refreshKey ?? ""}`) : null
6116
+ const header = /* @__PURE__ */ (0, import_jsx_runtime27.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: [
6117
+ onBack ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_controls22.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ChevronLeftGlyph, {}), "aria-label": "Back", onClick: mode === "new" ? onCancelNew : onBack }) : null,
6118
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ItemIcon, { definitionKey: definition?.key ?? item?.definitionKey ?? "custom", family: definition?.family ?? "generic", site: item ? loginSiteOf(item) : loginSiteOf({ loginUrls: draft.loginUrls }), size: "lg" }),
6119
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col", children: [
6120
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("h2", { className: "truncate text-base font-semibold leading-tight", children: editing ? draft.name || (mode === "new" ? `New ${typeLabel.toLowerCase()}` : item?.name) : item?.name }),
6121
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "flex min-w-0 items-center gap-1 text-xs text-muted-foreground", children: [
6122
+ typeLabel ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "truncate", children: typeLabel }) : null,
6123
+ shownOwner ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_controls22.Badge, { className: "shrink-0", icon: shownOwner.glyph, "aria-label": `Saved in ${shownOwner.label}`, children: shownOwner.label }) : null,
6124
+ item && !editing ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(SharingSummary, { item, port, className: "hidden truncate before:mr-1 before:content-['\xB7'] sm:inline" }, `${item.updatedAt}-${refreshKey ?? ""}`) : null
5876
6125
  ] })
5877
6126
  ] }),
5878
- editing ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex shrink-0 items-center gap-2", children: [
5879
- dirty ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "hidden items-center gap-1.5 text-xs text-muted-foreground sm:flex", role: "status", children: [
5880
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "size-1.5 rounded-full bg-warning", "aria-hidden": true }),
6127
+ editing ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex shrink-0 items-center gap-2", children: [
6128
+ dirty ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "hidden items-center gap-1.5 text-xs text-muted-foreground sm:flex", role: "status", children: [
6129
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "size-1.5 rounded-full bg-warning", "aria-hidden": true }),
5881
6130
  "Unsaved"
5882
6131
  ] }) : null,
5883
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.Button, { variant: "quiet", disabled: busy, onClick: () => mode === "new" ? onCancelNew() : onMode("view"), children: dirty ? "Discard" : "Cancel" }),
5884
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.Button, { variant: "primary", disabled: busy || draft.name.trim() === "" || mode === "edit" && !dirty || mode === "new" && owner === "person" && !/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(recipient.trim()), onClick: () => void save(), children: mode === "new" && owner === "person" ? "Send" : "Save" })
5885
- ] }) : item ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex shrink-0 items-center gap-1", children: [
5886
- host.page && canUseOnSite(item, host.page.url) ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(UseOnSiteButton, { port, item, pageUrl: host.page.url, onChanged: (next) => onChanged(next) }) : null,
5887
- host.fill && item.capabilities.canUse ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5888
- import_controls21.Button,
6132
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_controls22.Button, { variant: "quiet", disabled: busy, onClick: () => mode === "new" ? onCancelNew() : onMode("view"), children: dirty ? "Discard" : "Cancel" }),
6133
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_controls22.Button, { variant: "primary", disabled: busy || sent !== null || draft.name.trim() === "" || mode === "edit" && !dirty || mode === "new" && owner === "person" && !/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(recipient.trim()), onClick: () => void save(), children: mode === "new" && owner === "person" ? "Send" : "Save" })
6134
+ ] }) : item ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex shrink-0 items-center gap-1", children: [
6135
+ host.page && canUseOnSite(item, host.page.url) ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(UseOnSiteButton, { port, item, pageUrl: host.page.url, onChanged: (next) => onChanged(next) }) : null,
6136
+ host.fill && item.capabilities.canUse ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6137
+ import_controls22.Button,
5889
6138
  {
5890
6139
  variant: "primary",
5891
6140
  onClick: () => void host.fill?.(item.id).then((outcome) => {
@@ -5895,44 +6144,44 @@ function ItemPane(props) {
5895
6144
  children: "Fill"
5896
6145
  }
5897
6146
  ) : null,
5898
- favorite ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "hidden sm:contents", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(StarGlyph, { className: favorite.on ? "fill-current text-warning" : "size-4" }), "aria-label": favorite.on ? "Remove from favorites" : "Add to favorites", pressed: favorite.on, onClick: favorite.toggle }) }) : null,
5899
- canManage ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "hidden sm:contents", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ShareGlyph, {}), "aria-label": "Share", onClick: () => onPanel("share") }) }) : null,
5900
- canEdit ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.Button, { variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PencilGlyph, {}), collapse: "container", "aria-label": "Edit", onClick: () => onMode("edit"), children: "Edit" }) : null,
5901
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_design_system16.DropdownMenu, { children: [
5902
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_design_system16.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(MoreGlyph, {}), "aria-label": "More actions" }) }),
5903
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_design_system16.DropdownMenuContent, { align: "end", children: [
5904
- favorite ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_design_system16.DropdownMenuItem, { onSelect: favorite.toggle, children: [
5905
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(StarGlyph, { className: "size-4" }),
6147
+ favorite ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "hidden sm:contents", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_controls22.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(StarGlyph, { className: favorite.on ? "fill-current text-warning" : "size-4" }), "aria-label": favorite.on ? "Remove from favorites" : "Add to favorites", pressed: favorite.on, onClick: favorite.toggle }) }) : null,
6148
+ canManage ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "hidden sm:contents", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_controls22.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ShareGlyph, {}), "aria-label": "Share", onClick: () => onPanel("share") }) }) : null,
6149
+ canEdit ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_controls22.Button, { variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(PencilGlyph, {}), collapse: "container", "aria-label": "Edit", onClick: () => onMode("edit"), children: "Edit" }) : null,
6150
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_design_system17.DropdownMenu, { children: [
6151
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_design_system17.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_controls22.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(MoreGlyph, {}), "aria-label": "More actions" }) }),
6152
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_design_system17.DropdownMenuContent, { align: "end", children: [
6153
+ favorite ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_design_system17.DropdownMenuItem, { onSelect: favorite.toggle, children: [
6154
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(StarGlyph, { className: "size-4" }),
5906
6155
  favorite.on ? "Remove from favorites" : "Add to favorites"
5907
6156
  ] }) : null,
5908
- canManage ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_design_system16.DropdownMenuItem, { onSelect: () => onPanel("share"), children: [
5909
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ShareGlyph, { className: "size-4" }),
6157
+ canManage ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_design_system17.DropdownMenuItem, { onSelect: () => onPanel("share"), children: [
6158
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ShareGlyph, { className: "size-4" }),
5910
6159
  "Share"
5911
6160
  ] }) : null,
5912
- canManage ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_design_system16.DropdownMenuItem, { onSelect: () => onPanel("move"), children: [
5913
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(MoveGlyph, { className: "size-4" }),
6161
+ canManage ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_design_system17.DropdownMenuItem, { onSelect: () => onPanel("move"), children: [
6162
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(MoveGlyph, { className: "size-4" }),
5914
6163
  "Move or copy"
5915
6164
  ] }) : null,
5916
- item.capabilities.canReveal ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_design_system16.DropdownMenuItem, { onSelect: () => onPanel("send"), children: [
5917
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(SendGlyph, { className: "size-4" }),
6165
+ item.capabilities.canReveal ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_design_system17.DropdownMenuItem, { onSelect: () => onPanel("send"), children: [
6166
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(SendGlyph, { className: "size-4" }),
5918
6167
  "Send securely"
5919
6168
  ] }) : null,
5920
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_design_system16.DropdownMenuItem, { onSelect: () => onPanel("history"), children: [
5921
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_icons11.HistoryIcon, { className: "size-4" }),
6169
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_design_system17.DropdownMenuItem, { onSelect: () => onPanel("history"), children: [
6170
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_icons11.HistoryIcon, { className: "size-4" }),
5922
6171
  "Password history"
5923
6172
  ] }),
5924
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_design_system16.DropdownMenuItem, { onSelect: () => onPanel("activity"), children: [
5925
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ListGlyph, { className: "size-4" }),
6173
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_design_system17.DropdownMenuItem, { onSelect: () => onPanel("activity"), children: [
6174
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ListGlyph, { className: "size-4" }),
5926
6175
  "Activity"
5927
6176
  ] }),
5928
- canEdit ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_design_system16.DropdownMenuItem, { onSelect: () => onPanel("settings"), children: [
5929
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_icons11.SettingsIcon, { className: "size-4" }),
6177
+ canEdit ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_design_system17.DropdownMenuItem, { onSelect: () => onPanel("settings"), children: [
6178
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_icons11.SettingsIcon, { className: "size-4" }),
5930
6179
  "Settings"
5931
6180
  ] }) : null,
5932
- canManage ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
5933
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_design_system16.DropdownMenuSeparator, {}),
5934
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_design_system16.DropdownMenuItem, { className: "text-destructive", disabled: busy, onSelect: () => void remove(), children: [
5935
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TrashGlyph, { className: "size-4" }),
6181
+ canManage ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
6182
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_design_system17.DropdownMenuSeparator, {}),
6183
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_design_system17.DropdownMenuItem, { className: "text-destructive", disabled: busy, onSelect: () => void remove(), children: [
6184
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TrashGlyph, { className: "size-4" }),
5936
6185
  "Delete"
5937
6186
  ] })
5938
6187
  ] }) : null
@@ -5941,18 +6190,18 @@ function ItemPane(props) {
5941
6190
  ] }) : null
5942
6191
  ] });
5943
6192
  const filesProps = item ? { item, port, host, definition, organizations, arg: null, onClose: () => void 0, onChanged, onPanel } : null;
5944
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(RoomProvider, { value: room, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("article", { ref: paneRef, "aria-label": item?.name ?? "New item", className: (0, import_design_system17.cn)(import_controls21.CONTROLS_CONTAINER_CLASS, "flex h-full min-h-0 flex-col bg-background"), children: [
6193
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(RoomProvider, { value: room, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("article", { ref: paneRef, "aria-label": item?.name ?? "New item", className: (0, import_design_system18.cn)(import_controls22.CONTROLS_CONTAINER_CLASS, "flex h-full min-h-0 flex-col bg-background"), children: [
5945
6194
  header,
5946
- 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,
5947
- 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,
5948
- item && !editing && (itemOff || offFields.length > 0) ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { role: "status", className: "flex items-center gap-3 border-b border-border bg-muted px-5 py-2 text-sm", children: [
5949
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "min-w-0 flex-1 truncate text-warning", children: offFields.length === 0 ? "This item is turned off" : offFields.length === 1 ? "1 field is turned off" : `${offFields.length} fields are turned off` }),
5950
- canTurnOn ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TurnOnButton, { label: "all fields", onTurnOn: () => turnOn(offFields) }) : null
6195
+ error ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { role: "alert", className: "border-b border-border bg-muted px-5 py-2 text-sm text-destructive", children: error }) : null,
6196
+ notice && !editing ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { role: "status", className: "border-b border-border bg-muted px-5 py-2 text-sm text-warning", children: notice }) : null,
6197
+ item && !editing && (itemOff || offFields.length > 0) ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { role: "status", className: "flex items-center gap-3 border-b border-border bg-muted px-5 py-2 text-sm", children: [
6198
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "min-w-0 flex-1 truncate text-warning", children: offFields.length === 0 ? "This item is turned off" : offFields.length === 1 ? "1 field is turned off" : `${offFields.length} fields are turned off` }),
6199
+ canTurnOn ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TurnOnButton, { label: "all fields", onTurnOn: () => turnOn(offFields) }) : null
5951
6200
  ] }) : null,
5952
- /* @__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: [
5953
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(VaultSection, { children: [
5954
- mode === "new" ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(VaultRow, { label: "Save to", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5955
- import_controls21.OptionCombobox,
6201
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "min-h-0 flex-1 overflow-y-auto", children: sent ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(AssignResult, { sent, onAnother: createAnother, onDone: onCancelNew }) : /* @__PURE__ */ (0, import_jsx_runtime27.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_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
6202
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(VaultSection, { children: [
6203
+ mode === "new" ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(VaultRow, { label: "Save to", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6204
+ import_controls22.OptionCombobox,
5956
6205
  {
5957
6206
  value: owner,
5958
6207
  onChange: setOwner,
@@ -5966,39 +6215,39 @@ function ItemPane(props) {
5966
6215
  ],
5967
6216
  getLabel: (v) => v === "me" ? "Personal" : v === "person" ? "Someone else" : organizations.find((o) => o.id === v)?.name ?? v,
5968
6217
  getHint: (v) => v === "me" ? "Only you" : v === "person" ? "Sent by email" : sameNamed(v) ? `ID ${v.slice(0, 8)}` : null,
5969
- renderIcon: (v) => v === "me" ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PersonGlyph, { className: "size-4" }) : v === "person" ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(SendGlyph, { className: "size-4" }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(BuildingGlyph, { className: "size-4" })
6218
+ renderIcon: (v) => v === "me" ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(PersonGlyph, { className: "size-4" }) : v === "person" ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(SendGlyph, { className: "size-4" }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(BuildingGlyph, { className: "size-4" })
5970
6219
  }
5971
6220
  ) }) : null,
5972
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(EditRow, { label: "Name", value: draft.name, onChange: (v) => patch({ name: v }), placeholder: "Name", autoFocus: mode === "new" }),
5973
- mode === "new" && owner === "person" ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
5974
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(EditRow, { label: "Their email", value: recipient, placeholder: "name@company.com", inputMode: "email", onChange: setRecipient }),
5975
- 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
6221
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(EditRow, { label: "Name", value: draft.name, onChange: (v) => patch({ name: v }), placeholder: "Name", autoFocus: mode === "new" }),
6222
+ mode === "new" && owner === "person" ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
6223
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(EditRow, { label: "Their email", value: recipient, placeholder: "name@company.com", inputMode: "email", onChange: setRecipient }),
6224
+ declared.some((f) => f.storage === "encrypted" && f.kind === "secret") ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(VaultRow, { label: "Password", hint: "You never see it", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_controls22.Switch, { checked: generatePrivately, onCheckedChange: setGeneratePrivately, "aria-label": "Generate the password privately" }) }) : null
5976
6225
  ] }) : null,
5977
6226
  declared.map((f) => {
5978
6227
  const existing = item?.fields.find((x) => x.key === f.key);
5979
6228
  const secretKind = f.storage === "encrypted" && f.kind === "secret";
5980
6229
  const value = f.storage === "metadata" ? metaValue(f.key) : draft.values[f.key] ?? "";
5981
6230
  const hidden = existing && existing.handling !== "visible" && !(f.key in loaded);
5982
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6231
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5983
6232
  EditRow,
5984
6233
  {
5985
6234
  label: f.label,
5986
6235
  value,
5987
- placeholder: hidden ? "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" : f.required ? "Required" : "",
6236
+ placeholder: hidden ? "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" : f.required ? "Required" : isRecoveryCodesField(f) ? "Backup codes, one per line" : "",
5988
6237
  secret: secretKind,
5989
6238
  multiline: f.kind === "multiline",
5990
6239
  inputMode: f.kind === "url" ? "url" : USERNAME_KEYS.test(f.key) ? "email" : "text",
5991
6240
  onChange: (v) => setValue(f.key, v),
5992
- actions: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
5993
- 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,
5994
- secretKind ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(GenerateButton, { onUse: (v) => setValue(f.key, v) }) : null,
5995
- 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
6241
+ actions: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
6242
+ hidden && existing?.handling === "revealable" && item?.capabilities.canReveal ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_controls22.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(EyeGlyph, {}), "aria-label": `Show current ${f.label}`, onClick: () => void loadForEdit(f.key) }) : null,
6243
+ secretKind ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(GenerateButton, { onUse: (v) => setValue(f.key, v) }) : null,
6244
+ existing ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_controls22.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_icons11.SettingsIcon, {}), "aria-label": `${f.label} settings`, onClick: () => onPanel(`field:${existing.id}`) }) : null
5996
6245
  ] })
5997
6246
  },
5998
6247
  f.key
5999
6248
  );
6000
6249
  }),
6001
- extraFields.map((f) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6250
+ extraFields.map((f) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6002
6251
  EditRow,
6003
6252
  {
6004
6253
  label: f.label,
@@ -6009,18 +6258,18 @@ function ItemPane(props) {
6009
6258
  onChange: (v) => setValue(f.key, v),
6010
6259
  onRemove: () => patch({ removed: [...draft.removed, f.id] }),
6011
6260
  removeLabel: `Delete ${f.label}`,
6012
- actions: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
6013
- 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,
6014
- /* @__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}`) })
6261
+ actions: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
6262
+ f.handling === "revealable" && !(f.key in loaded) && item?.capabilities.canReveal ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_controls22.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(EyeGlyph, {}), "aria-label": `Show current ${f.label}`, onClick: () => void loadForEdit(f.key) }) : null,
6263
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_controls22.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_icons11.SettingsIcon, {}), "aria-label": `${f.label} settings`, onClick: () => onPanel(`field:${f.id}`) })
6015
6264
  ] })
6016
6265
  },
6017
6266
  f.id
6018
6267
  )),
6019
- draft.loginUrls.map((u, i) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6268
+ draft.loginUrls.map((u, i) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6020
6269
  EditRow,
6021
6270
  {
6022
6271
  label: i === 0 ? "Website" : `Website ${i + 1}`,
6023
- hint: destinations[i] && destinations[i].tone !== "success" ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: destinations[i].tone === "destructive" ? "text-destructive" : "text-warning", children: destinations[i].message }) : void 0,
6272
+ hint: destinations[i] && destinations[i].tone !== "success" ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: destinations[i].tone === "destructive" ? "text-destructive" : "text-warning", children: destinations[i].message }) : void 0,
6024
6273
  value: u,
6025
6274
  autoFocus: i > 0 && u === "" && i === draft.loginUrls.length - 1,
6026
6275
  placeholder: "https://",
@@ -6040,10 +6289,11 @@ function ItemPane(props) {
6040
6289
  },
6041
6290
  i
6042
6291
  )),
6043
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AddRow, { label: draft.loginUrls.length === 0 ? "Website" : "", onAdd: () => patch({ loginUrls: [...draft.loginUrls, ""] }), children: draft.loginUrls.length === 0 ? "Add website" : "Add another website" }),
6044
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TotpEditRow, { value: draft.authenticator, onChange: (v) => patch({ authenticator: v }), hasExisting: Boolean(item?.authenticator || seedField), item, port, onEnrolled: onChanged }),
6045
- item && isLogin && !item.authenticator ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TwoFactorMethodRow, { port, item, onChanged }) : null,
6046
- recoveryEditing ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6292
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(AddRow, { label: draft.loginUrls.length === 0 ? "Website" : "", onAdd: () => patch({ loginUrls: [...draft.loginUrls, ""] }), children: draft.loginUrls.length === 0 ? "Add website" : "Add another website" }),
6293
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TotpEditRow, { value: draft.authenticator, onChange: (v) => patch({ authenticator: v }), hasExisting: Boolean(item?.authenticator || seedField), item, port, onEnrolled: onChanged }),
6294
+ item && isLogin && !item.authenticator ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TwoFactorMethodRow, { port, item, onChanged }) : null,
6295
+ !item && isLogin && draft.authenticator.trim() === "" ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(DraftTwoFactorRow, { custom: draft.custom, onCustom: (custom) => patch({ custom }) }) : null,
6296
+ recoveryEditing ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6047
6297
  EditRow,
6048
6298
  {
6049
6299
  label: "Recovery codes",
@@ -6062,26 +6312,30 @@ function ItemPane(props) {
6062
6312
  },
6063
6313
  removeLabel: "Remove recovery codes"
6064
6314
  }
6065
- ) : !recoveryDeclared && !recoveryExtra && offerRecovery ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AddRow, { label: "Recovery codes", onAdd: () => setShowRecovery(true), children: "Add backup codes" }) : null
6315
+ ) : !recoveryDeclared && !recoveryExtra && offerRecovery ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(AddRow, { label: "Recovery codes", onAdd: () => setShowRecovery(true), children: "Add backup codes" }) : null
6066
6316
  ] }),
6067
- /* @__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 }) }) }),
6068
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
6317
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(VaultSection, { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(EditRow, { label: "Notes", value: draft.notes, multiline: true, placeholder: "Anything worth remembering", onChange: (v) => patch({ notes: v }) }) }),
6318
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
6069
6319
  VaultSection,
6070
6320
  {
6071
6321
  title: "More",
6072
- actions: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_design_system16.DropdownMenu, { children: [
6073
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_design_system16.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_controls21.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PlusGlyph, {}), children: "Add" }) }),
6074
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_design_system16.DropdownMenuContent, { align: "end", children: [
6075
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_design_system16.DropdownMenuItem, { onSelect: () => patch({ secrets: [...draft.secrets, { key: "", label: "", value: "" }] }), children: "Secret field" }),
6076
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_design_system16.DropdownMenuItem, { onSelect: () => patch({ custom: [...draft.custom, { key: `custom_${draft.custom.length + 1}_${Date.now() % 1e5}`, label: "", value: "" }] }), children: "Text field" }),
6077
- !tagsVisible ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_design_system16.DropdownMenuItem, { onSelect: () => setShowTags(true), children: "Tags" }) : null,
6078
- !descriptionVisible ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_design_system16.DropdownMenuItem, { onSelect: () => setShowDescription(true), children: "Description" }) : null,
6079
- !recoveryDeclared && !recoveryExtra && !recoveryEditing ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_design_system16.DropdownMenuItem, { onSelect: () => setShowRecovery(true), children: "Recovery codes" }) : null
6322
+ actions: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_design_system17.DropdownMenu, { children: [
6323
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_design_system17.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_controls22.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(PlusGlyph, {}), children: "Add" }) }),
6324
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_design_system17.DropdownMenuContent, { align: "end", children: [
6325
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_design_system17.DropdownMenuItem, { onSelect: () => patch({ secrets: [...draft.secrets, { key: "", label: "", value: "" }] }), children: "Secret field" }),
6326
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_design_system17.DropdownMenuItem, { onSelect: () => patch({ custom: [...draft.custom, { key: `custom_${draft.custom.length + 1}_${Date.now() % 1e5}`, label: "", value: "" }] }), children: "Text field" }),
6327
+ !tagsVisible ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_design_system17.DropdownMenuItem, { onSelect: () => setShowTags(true), children: "Tags" }) : null,
6328
+ !descriptionVisible ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_design_system17.DropdownMenuItem, { onSelect: () => setShowDescription(true), children: "Description" }) : null,
6329
+ mode === "new" && !showBrowser ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_design_system17.DropdownMenuItem, { onSelect: () => {
6330
+ setShowBrowser(true);
6331
+ if (!draft.browser) patch({ browser: defaultBrowserSettings(draft.loginUrls.some((u) => u.trim() !== "")) });
6332
+ }, children: "Browser settings" }) : null,
6333
+ !recoveryDeclared && !recoveryExtra && !recoveryEditing ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_design_system17.DropdownMenuItem, { onSelect: () => setShowRecovery(true), children: "Recovery codes" }) : null
6080
6334
  ] })
6081
6335
  ] }),
6082
6336
  children: [
6083
- descriptionVisible ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(EditRow, { label: "Description", value: draft.description, placeholder: "What this is for", onChange: (v) => patch({ description: v }) }) : null,
6084
- tagsVisible ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6337
+ descriptionVisible ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(EditRow, { label: "Description", value: draft.description, placeholder: "What this is for", onChange: (v) => patch({ description: v }) }) : null,
6338
+ tagsVisible ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6085
6339
  EditRow,
6086
6340
  {
6087
6341
  label: "Tags",
@@ -6093,49 +6347,50 @@ function ItemPane(props) {
6093
6347
  }
6094
6348
  }
6095
6349
  ) : null,
6096
- draft.secrets.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(CustomEditRow, { label: s.label, value: s.value, secret: true, onLabel: (v) => patch({ secrets: draft.secrets.map((x, j) => j === i ? { ...x, label: v } : x) }), onValue: (v) => patch({ secrets: draft.secrets.map((x, j) => j === i ? { ...x, value: v } : x) }), onRemove: () => patch({ secrets: draft.secrets.filter((_, j) => j !== i) }) }, `s${i}`)),
6097
- extraCustom.map((c) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(CustomEditRow, { label: c.label, value: c.value, secret: false, onLabel: (v) => patch({ custom: draft.custom.map((x) => x.key === c.key ? { ...x, label: v } : x) }), onValue: (v) => patch({ custom: draft.custom.map((x) => x.key === c.key ? { ...x, value: v } : x) }), onRemove: () => patch({ custom: draft.custom.filter((x) => x.key !== c.key) }) }, c.key)),
6098
- !descriptionVisible && !tagsVisible && draft.secrets.length === 0 && extraCustom.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AddRow, { label: "Tags", onAdd: () => setShowTags(true), children: "Add tags" }) : null
6350
+ mode === "new" && showBrowser && draft.browser ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(DraftBrowserRows, { value: draft.browser, hasWebsite: draft.loginUrls.some((u) => u.trim() !== ""), onChange: (browser) => patch({ browser }) }) : null,
6351
+ draft.secrets.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(SecretBuilderRow, { field: s, onChange: (p) => setDraft((d) => ({ ...d, secrets: d.secrets.map((x, j) => j === i ? { ...x, ...p } : x) })), onRemove: () => patch({ secrets: draft.secrets.filter((_, j) => j !== i) }) }, `s${i}`)),
6352
+ extraCustom.map((c) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(CustomEditRow, { label: c.label, value: c.value, secret: false, onLabel: (v) => patch({ custom: draft.custom.map((x) => x.key === c.key ? { ...x, label: v } : x) }), onValue: (v) => patch({ custom: draft.custom.map((x) => x.key === c.key ? { ...x, value: v } : x) }), onRemove: () => patch({ custom: draft.custom.filter((x) => x.key !== c.key) }) }, c.key)),
6353
+ !descriptionVisible && !tagsVisible && draft.secrets.length === 0 && extraCustom.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(AddRow, { label: "Tags", onAdd: () => setShowTags(true), children: "Add tags" }) : null
6099
6354
  ]
6100
6355
  }
6101
6356
  ),
6102
- filesProps ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(FilesSection, { ...filesProps, editing: true }) : null
6103
- ] }) : item ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
6104
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(VaultSection, { children: [
6357
+ filesProps ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(FilesSection, { ...filesProps, editing: true }) : mode === "new" && owner !== "person" ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(DraftFilesSection, { files: queuedFiles, onFiles: setQueuedFiles }) : null
6358
+ ] }) : item ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
6359
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(VaultSection, { children: [
6105
6360
  declared.map((f) => {
6106
6361
  if (f.storage === "metadata") {
6107
6362
  const v = metaValue(f.key);
6108
- return v ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PlainRow, { label: f.label, value: v, openUrl: host.openUrl }, f.key) : null;
6363
+ return v ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(PlainRow, { label: f.label, value: v, openUrl: host.openUrl }, f.key) : null;
6109
6364
  }
6110
6365
  const field = item.fields.find((x) => x.key === f.key);
6111
- if (isRecoveryCodesField(f)) return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(RecoveryCodesRow, { item, field, port, onChanged }, f.key);
6112
- return field ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(SecretRow, { port, item, field, onTurnOn: turnOnOne(field) }, field.id) : null;
6366
+ if (isRecoveryCodesField(f)) return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(RecoveryCodesRow, { item, field, port, onChanged }, f.key);
6367
+ return field ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(SecretRow, { port, item, field, onTurnOn: turnOnOne(field), extra: fieldSettings(field) }, field.id) : null;
6113
6368
  }),
6114
- extraFields.map((f) => isRecoveryCodesField(f) ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(RecoveryCodesRow, { item, field: f, port, onChanged }, f.id) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(SecretRow, { port, item, field: f, onTurnOn: turnOnOne(f) }, f.id)),
6115
- item.loginUrls.length > 0 ? item.loginUrls.map((u, i) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PlainRow, { label: i === 0 ? "Website" : `Website ${i + 1}`, value: u, openUrl: host.openUrl }, `${u}-${i}`)) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AddRow, { label: "Website", onAdd: canEdit ? () => onMode("edit") : null, children: "Add website" }),
6116
- item.authenticator ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TotpRow, { port, item, onChanged }) : seedField && !seedField.active ? (
6369
+ extraFields.map((f) => isRecoveryCodesField(f) ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(RecoveryCodesRow, { item, field: f, port, onChanged }, f.id) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(SecretRow, { port, item, field: f, onTurnOn: turnOnOne(f), extra: fieldSettings(f) }, f.id)),
6370
+ item.loginUrls.length > 0 ? item.loginUrls.map((u, i) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(PlainRow, { label: i === 0 ? "Website" : `Website ${i + 1}`, value: u, openUrl: host.openUrl }, `${u}-${i}`)) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(AddRow, { label: "Website", onAdd: canEdit ? () => onMode("edit") : null, children: "Add website" }),
6371
+ item.authenticator ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TotpRow, { port, item, onChanged }) : seedField && !seedField.active ? (
6117
6372
  // The secret is still there, only off: turning it on brings the codes back. Never "Set up",
6118
6373
  // which would invite replacing a working two-factor secret.
6119
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(VaultRow, { label: "Authenticator", actions: canTurnOn ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TurnOnButton, { label: "Authenticator", onTurnOn: () => turnOn([seedField]) }) : null, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-muted-foreground", children: "Turned off" }) })
6120
- ) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AddRow, { label: "Authenticator", onAdd: canEdit ? () => setSettingUpOtp(true) : null, children: "Set up" }),
6121
- !recoveryDeclared && !recoveryExtra && offerRecovery ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(RecoveryCodesRow, { item, field: null, port, onChanged }) : null,
6122
- !item.authenticator && item.custom.some((c) => c.key === MFA_METHOD_KEY && c.value) ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TwoFactorMethodRow, { port, item, onChanged }) : null
6374
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(VaultRow, { label: "Authenticator", actions: canTurnOn ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TurnOnButton, { label: "Authenticator", onTurnOn: () => turnOn([seedField]) }) : null, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-muted-foreground", children: "Turned off" }) })
6375
+ ) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(AddRow, { label: "Authenticator", onAdd: canEdit ? () => setSettingUpOtp(true) : null, children: "Set up" }),
6376
+ !recoveryDeclared && !recoveryExtra && offerRecovery ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(RecoveryCodesRow, { item, field: null, port, onChanged }) : null,
6377
+ !item.authenticator && item.custom.some((c) => c.key === MFA_METHOD_KEY && c.value) ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TwoFactorMethodRow, { port, item, onChanged }) : null
6123
6378
  ] }),
6124
- /* @__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" }) }),
6125
- item.description || item.tags.length > 0 || viewCustom.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(VaultSection, { title: "More", children: [
6126
- item.description ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PlainRow, { label: "Description", value: item.description }) : null,
6127
- 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,
6128
- viewCustom.map((c) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PlainRow, { label: c.label, value: c.value, openUrl: host.openUrl }, c.key))
6379
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(VaultSection, { children: item.notes ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(PlainRow, { label: "Notes", value: item.notes, multiline: true }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(AddRow, { label: "Notes", onAdd: canEdit ? () => onMode("edit") : null, children: "Add notes" }) }),
6380
+ item.description || item.tags.length > 0 || viewCustom.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(VaultSection, { title: "More", children: [
6381
+ item.description ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(PlainRow, { label: "Description", value: item.description }) : null,
6382
+ item.tags.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(VaultRow, { label: "Tags", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "flex flex-wrap gap-1", children: item.tags.map((t) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "rounded-md bg-muted px-1.5 py-0.5 text-xs", children: t }, t)) }) }) : null,
6383
+ viewCustom.map((c) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(PlainRow, { label: c.label, value: c.value, openUrl: host.openUrl }, c.key))
6129
6384
  ] }) : null,
6130
- filesProps ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(FilesSection, { ...filesProps, editing: false }) : null,
6131
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("p", { className: (0, import_design_system17.cn)("px-1 text-xs text-muted-foreground"), children: [
6385
+ filesProps ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(FilesSection, { ...filesProps, editing: false }) : null,
6386
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("p", { className: (0, import_design_system18.cn)("px-1 text-xs text-muted-foreground"), children: [
6132
6387
  "Modified ",
6133
6388
  (0, import_format8.formatAbsoluteDate)(item.updatedAt, DAY_FORMAT, ""),
6134
6389
  " \xB7 Created ",
6135
6390
  (0, import_format8.formatAbsoluteDate)(item.createdAt, DAY_FORMAT, "")
6136
6391
  ] })
6137
6392
  ] }) : null }) }),
6138
- settingUpOtp && item ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6393
+ settingUpOtp && item ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6139
6394
  AddOtpPanel,
6140
6395
  {
6141
6396
  port,
@@ -6154,23 +6409,26 @@ function ItemPane(props) {
6154
6409
  }
6155
6410
 
6156
6411
  // src/ItemList.tsx
6157
- var import_jsx_runtime27 = require("react/jsx-runtime");
6412
+ var import_jsx_runtime28 = require("react/jsx-runtime");
6158
6413
  var SORTS2 = [
6159
- { value: "name", label: "Name" },
6414
+ { value: "name", label: "Name A\u2013Z" },
6415
+ { value: "name-desc", label: "Name Z\u2013A" },
6160
6416
  { value: "website", label: "Website" },
6161
6417
  { value: "updated", label: "Recently changed" },
6162
- { value: "created", label: "Recently added" }
6418
+ { value: "created", label: "Recently added" },
6419
+ { value: "viewed", label: "Recently viewed" }
6163
6420
  ];
6164
6421
  function subtitleOf(item, withOwner) {
6165
6422
  const what = loginSiteOf(item) || item.definitionLabel;
6166
6423
  return withOwner ? `${what} \xB7 ${item.owner.label}` : what;
6167
6424
  }
6168
- function ItemList({ title, items, definitions, port, selectedId, onSelect, query, onQuery, sort, onSort, onNew, matchingIds, header, showOwner }) {
6425
+ function ItemList({ title, items, definitions, port, selectedId, onSelect, query, onQuery, sort, onSort, onNew, matchingIds, header, showOwner, canSortViewed = false }) {
6426
+ const sorts = SORTS2.filter((s) => canSortViewed || s.value !== "viewed");
6169
6427
  const pinned = matchingIds ? items.filter((i) => matchingIds.has(i.id)) : [];
6170
6428
  const rest = matchingIds ? items.filter((i) => !matchingIds.has(i.id)) : items;
6171
6429
  const ordered = [...pinned, ...rest];
6172
- const listRef = (0, import_react28.useRef)(null);
6173
- (0, import_react28.useEffect)(() => {
6430
+ const listRef = (0, import_react29.useRef)(null);
6431
+ (0, import_react29.useEffect)(() => {
6174
6432
  if (selectedId) listRef.current?.querySelector(`[data-item="${selectedId}"]`)?.scrollIntoView({ block: "nearest" });
6175
6433
  }, [selectedId, items.length]);
6176
6434
  const familyOf2 = (key) => definitions.find((d) => d.key === key)?.family ?? "generic";
@@ -6185,34 +6443,34 @@ function ItemList({ title, items, definitions, port, selectedId, onSelect, query
6185
6443
  }
6186
6444
  };
6187
6445
  const mixedOwners = showOwner ?? new Set(items.map((i) => i.owner.organizationId ?? i.owner.kind)).size > 1;
6188
- const row = (i) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ListRow, { item: i, family: familyOf2(i.definitionKey), port, on: i.id === selectedId, onSelect, withOwner: mixedOwners }, i.id);
6189
- const sortLabel = SORTS2.find((s) => s.value === sort)?.label ?? "Name";
6190
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("section", { "aria-label": title, className: "flex h-full min-h-0 flex-col border-r border-border bg-background", children: [
6191
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col gap-2 px-3 pb-2 pt-3", children: [
6446
+ const row = (i) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ListRow, { item: i, family: familyOf2(i.definitionKey), port, on: i.id === selectedId, onSelect, withOwner: mixedOwners }, i.id);
6447
+ const sortLabel = sorts.find((s) => s.value === sort)?.label ?? "Name A\u2013Z";
6448
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("section", { "aria-label": title, className: "flex h-full min-h-0 flex-col border-r border-border bg-background", children: [
6449
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-col gap-2 px-3 pb-2 pt-3", children: [
6192
6450
  header,
6193
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center gap-2", children: [
6194
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_controls22.SearchField, { value: query, onChange: (e) => onQuery(e.target.value), onKeyDown, placeholder: `Search ${title}`, className: "min-w-0 flex-1", "aria-label": "Search the vault" }),
6195
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_controls22.Button, { variant: "primary", icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(PlusGlyph, {}), "aria-label": "New item", onClick: onNew })
6451
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex items-center gap-2", children: [
6452
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_controls23.SearchField, { value: query, onChange: (e) => onQuery(e.target.value), onKeyDown, placeholder: `Search ${title}`, className: "min-w-0 flex-1", "aria-label": "Search the vault" }),
6453
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_controls23.Button, { variant: "primary", icon: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(PlusGlyph, {}), "aria-label": "New item", onClick: onNew })
6196
6454
  ] }),
6197
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center justify-between gap-2 px-1", children: [
6198
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "truncate text-xs text-muted-foreground", children: [
6455
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex items-center justify-between gap-2 px-1", children: [
6456
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: "truncate text-xs text-muted-foreground", children: [
6199
6457
  items.length,
6200
6458
  " ",
6201
6459
  items.length === 1 ? "item" : "items"
6202
6460
  ] }),
6203
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_design_system18.DropdownMenu, { children: [
6204
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_design_system18.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_controls22.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(SortGlyph, {}), "aria-label": `Sort: ${sortLabel}`, children: sortLabel }) }),
6205
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_design_system18.DropdownMenuContent, { align: "end", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_design_system18.DropdownMenuRadioGroup, { value: sort, onValueChange: (v) => onSort(SORTS2.find((s) => s.value === v)?.value ?? "name"), children: SORTS2.map((s) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_design_system18.DropdownMenuRadioItem, { value: s.value, children: s.label }, s.value)) }) })
6461
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_design_system19.DropdownMenu, { children: [
6462
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_design_system19.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_controls23.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(SortGlyph, {}), "aria-label": `Sort: ${sortLabel}`, children: sortLabel }) }),
6463
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_design_system19.DropdownMenuContent, { align: "end", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_design_system19.DropdownMenuRadioGroup, { value: sort, onValueChange: (v) => onSort(sorts.find((s) => s.value === v)?.value ?? "name"), children: sorts.map((s) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_design_system19.DropdownMenuRadioItem, { value: s.value, children: s.label }, s.value)) }) })
6206
6464
  ] })
6207
6465
  ] })
6208
6466
  ] }),
6209
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "min-h-0 flex-1 overflow-y-auto px-2 pb-3", onKeyDown, children: items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col items-center gap-3 px-4 py-12 text-center", children: [
6210
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-sm text-muted-foreground", children: query ? `Nothing matches \u201C${query}\u201D.` : "Nothing here yet." }),
6211
- query ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_controls22.Button, { variant: "outline", onClick: () => onQuery(""), children: "Clear search" }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_controls22.Button, { variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(PlusGlyph, {}), onClick: onNew, children: "New item" })
6212
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("ul", { ref: listRef, className: "flex flex-col gap-px", children: [
6213
- pinned.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("li", { className: "px-2 pb-1 pt-1 text-xs font-medium text-muted-foreground", children: "This page" }) : null,
6467
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "min-h-0 flex-1 overflow-y-auto px-2 pb-3", onKeyDown, children: items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-col items-center gap-3 px-4 py-12 text-center", children: [
6468
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "text-sm text-muted-foreground", children: query ? `Nothing matches \u201C${query}\u201D.` : "Nothing here yet." }),
6469
+ query ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_controls23.Button, { variant: "outline", onClick: () => onQuery(""), children: "Clear search" }) : /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_controls23.Button, { variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(PlusGlyph, {}), onClick: onNew, children: "New item" })
6470
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("ul", { ref: listRef, className: "flex flex-col gap-px", children: [
6471
+ pinned.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("li", { className: "px-2 pb-1 pt-1 text-xs font-medium text-muted-foreground", children: "This page" }) : null,
6214
6472
  pinned.map(row),
6215
- pinned.length > 0 && rest.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("li", { className: "px-2 pb-1 pt-3 text-xs font-medium text-muted-foreground", children: "Everything else" }) : null,
6473
+ pinned.length > 0 && rest.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("li", { className: "px-2 pb-1 pt-3 text-xs font-medium text-muted-foreground", children: "Everything else" }) : null,
6216
6474
  rest.map(row)
6217
6475
  ] }) })
6218
6476
  ] });
@@ -6221,48 +6479,93 @@ function ListRow({ item, family, port, on, onSelect, withOwner }) {
6221
6479
  const confirmed = useConfirmed();
6222
6480
  const copy = useCopy();
6223
6481
  const notify = useNotify();
6224
- const [busy, setBusy] = (0, import_react28.useState)(false);
6225
- const user = item.fields.find((f) => USERNAME_KEYS.test(f.key) && f.handling !== "sealed");
6226
- const secret = item.fields.find((f) => f.key === "password" && f.handling === "revealable");
6227
- const quick = async (key, label) => {
6482
+ const [busy, setBusy] = (0, import_react29.useState)(false);
6483
+ const [menuOpen, setMenuOpen] = (0, import_react29.useState)(false);
6484
+ const canUse = item.capabilities.canUse;
6485
+ const user = canUse ? item.fields.find((f) => USERNAME_KEYS.test(f.key) && f.handling !== "sealed" && f.active !== false) : void 0;
6486
+ const secret = canUse && item.capabilities.canReveal ? item.fields.find((f) => f.key === "password" && f.handling === "revealable" && f.active !== false) : void 0;
6487
+ const code = canUse && item.authenticator?.enabled ? item.authenticator : null;
6488
+ const run = async (label, read, isSecret) => {
6228
6489
  setBusy(true);
6229
6490
  try {
6230
- const v = await confirmed(() => port.reveal(item, key));
6231
- await copy(v, label, { secret: key !== user?.key || user.handling !== "visible" });
6491
+ const v = await confirmed(read);
6492
+ await copy(v, label, { secret: isSecret });
6232
6493
  } catch (e) {
6233
6494
  if (!wasCancelled(e)) notify(e instanceof Error ? e.message : `${label} could not be read`, "error");
6234
6495
  } finally {
6235
6496
  setBusy(false);
6236
6497
  }
6237
6498
  };
6238
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("li", { className: "group relative", "data-item": item.id, children: [
6239
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
6499
+ const copyUser = () => user && void run(user.label, () => port.reveal(item, user.key), user.handling !== "visible");
6500
+ const copyPassword = () => secret && void run("Password", () => port.reveal(item, secret.key), true);
6501
+ const copyCode = () => code && void run("One-time code", async () => (await port.authenticator.code(item)).code, true);
6502
+ const copyName = () => void copy(item.name, "Name", { secret: false });
6503
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("li", { className: "group relative", "data-item": item.id, children: [
6504
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
6240
6505
  "button",
6241
6506
  {
6242
6507
  type: "button",
6243
6508
  "aria-current": on ? "true" : void 0,
6244
6509
  "data-surface": on ? "primary" : void 0,
6245
6510
  onClick: () => onSelect(item.id),
6246
- className: (0, import_design_system19.cn)("flex h-12 w-full items-center gap-3 rounded-lg px-2 text-left", on ? "bg-primary text-primary-foreground" : "hover:bg-accent"),
6511
+ className: (0, import_design_system20.cn)("flex h-12 w-full items-center gap-3 rounded-lg px-2 pr-10 text-left", on ? "bg-primary text-primary-foreground" : "hover:bg-accent"),
6247
6512
  children: [
6248
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ItemIcon, { definitionKey: item.definitionKey, family, site: loginSiteOf(item), inverted: on }),
6249
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "flex min-w-0 flex-1 flex-col leading-tight", children: [
6250
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "truncate text-sm font-medium", children: item.name }),
6251
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "truncate text-xs text-muted-foreground", children: subtitleOf(item, withOwner) })
6513
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ItemIcon, { definitionKey: item.definitionKey, family, site: loginSiteOf(item), inverted: on }),
6514
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: "flex min-w-0 flex-1 flex-col leading-tight", children: [
6515
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "truncate text-sm font-medium", children: item.name }),
6516
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "truncate text-xs text-muted-foreground", children: subtitleOf(item, withOwner) })
6252
6517
  ] })
6253
6518
  ]
6254
6519
  }
6255
6520
  ),
6256
- item.capabilities.canUse && (user || secret && item.capabilities.canReveal) ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: (0, import_design_system19.cn)("absolute right-1.5 top-1/2 hidden -translate-y-1/2 items-center gap-0.5 rounded-md pl-2 group-hover:flex", on ? "bg-primary" : "bg-accent"), "data-surface": on ? "primary" : void 0, children: [
6257
- user ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_controls22.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(UserGlyph, {}), "aria-label": `Copy ${user.label}`, disabled: busy, onClick: () => void quick(user.key, user.label) }) : null,
6258
- secret && item.capabilities.canReveal ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_controls22.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(KeyGlyph, {}), "aria-label": "Copy password", disabled: busy, onClick: () => void quick(secret.key, "Password") }) : null
6259
- ] }) : null
6521
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "absolute right-1.5 top-1/2 flex -translate-y-1/2 items-center gap-0.5", "data-surface": on ? "primary" : void 0, children: [
6522
+ user || secret ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: (0, import_design_system20.cn)("hidden items-center gap-0.5 rounded-md pl-2 [@media(hover:hover)]:group-hover:flex [@media(hover:hover)]:group-focus-within:flex", on ? "bg-primary" : "bg-accent"), "data-row-quick": "", children: [
6523
+ user ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_controls23.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(UserGlyph, {}), "aria-label": `Copy ${user.label}`, disabled: busy, onClick: copyUser }) : null,
6524
+ secret ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_controls23.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(KeyGlyph, {}), "aria-label": "Copy password", disabled: busy, onClick: copyPassword }) : null
6525
+ ] }) : null,
6526
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_design_system19.DropdownMenu, { open: menuOpen, onOpenChange: setMenuOpen, children: [
6527
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_design_system19.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
6528
+ import_controls23.Button,
6529
+ {
6530
+ variant: "quiet",
6531
+ icon: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(MoreGlyph, {}),
6532
+ "aria-label": `Actions for ${item.name}`,
6533
+ disabled: busy,
6534
+ className: (0, import_design_system20.cn)("[@media(hover:hover)]:invisible [@media(hover:hover)]:group-hover:visible [@media(hover:hover)]:group-focus-within:visible", menuOpen && "[@media(hover:hover)]:visible")
6535
+ }
6536
+ ) }),
6537
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_design_system19.DropdownMenuContent, { align: "end", children: [
6538
+ user ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_design_system19.DropdownMenuItem, { onSelect: copyUser, children: [
6539
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(UserGlyph, { className: "size-4" }),
6540
+ "Copy ",
6541
+ user.label.toLowerCase()
6542
+ ] }) : null,
6543
+ secret ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_design_system19.DropdownMenuItem, { onSelect: copyPassword, children: [
6544
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(KeyGlyph, { className: "size-4" }),
6545
+ "Copy password"
6546
+ ] }) : null,
6547
+ code ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_design_system19.DropdownMenuItem, { onSelect: copyCode, children: [
6548
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ClockGlyph, { className: "size-4" }),
6549
+ "Copy one-time code"
6550
+ ] }) : null,
6551
+ user || secret || code ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_design_system19.DropdownMenuSeparator, {}) : null,
6552
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_design_system19.DropdownMenuItem, { onSelect: () => onSelect(item.id), children: [
6553
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ChevronRightGlyph, { className: "size-4" }),
6554
+ "Open"
6555
+ ] }),
6556
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_design_system19.DropdownMenuItem, { onSelect: copyName, children: [
6557
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_icons12.CopyIcon, { className: "size-4" }),
6558
+ "Copy name"
6559
+ ] })
6560
+ ] })
6561
+ ] })
6562
+ ] })
6260
6563
  ] });
6261
6564
  }
6262
6565
 
6263
6566
  // src/lists/TrashView.tsx
6264
- var import_react30 = require("react");
6265
- var import_controls24 = require("@ai-matrx/design-system/controls");
6567
+ var import_react31 = require("react");
6568
+ var import_controls25 = require("@ai-matrx/design-system/controls");
6266
6569
  var import_format9 = require("@ai-matrx/kit/format");
6267
6570
 
6268
6571
  // src/lists/logic.ts
@@ -6335,16 +6638,16 @@ function refusalText(reason) {
6335
6638
  }
6336
6639
 
6337
6640
  // src/lists/RestorePanel.tsx
6338
- var import_react29 = require("react");
6339
- var import_controls23 = require("@ai-matrx/design-system/controls");
6340
- var import_jsx_runtime28 = require("react/jsx-runtime");
6641
+ var import_react30 = require("react");
6642
+ var import_controls24 = require("@ai-matrx/design-system/controls");
6643
+ var import_jsx_runtime29 = require("react/jsx-runtime");
6341
6644
  var count = (n, one) => `${n} ${one}${n === 1 ? "" : "s"}`;
6342
6645
  function RestorePanel({ lists, item, restore, onClose }) {
6343
- const [preview, setPreview] = (0, import_react29.useState)(null);
6344
- const [error, setError] = (0, import_react29.useState)(null);
6345
- const [busy, setBusy] = (0, import_react29.useState)(false);
6346
- const [loading, setLoading] = (0, import_react29.useState)(Boolean(lists.preview));
6347
- (0, import_react29.useEffect)(() => {
6646
+ const [preview, setPreview] = (0, import_react30.useState)(null);
6647
+ const [error, setError] = (0, import_react30.useState)(null);
6648
+ const [busy, setBusy] = (0, import_react30.useState)(false);
6649
+ const [loading, setLoading] = (0, import_react30.useState)(Boolean(lists.preview));
6650
+ (0, import_react30.useEffect)(() => {
6348
6651
  if (!lists.preview) return;
6349
6652
  let live = true;
6350
6653
  lists.preview(item).then(
@@ -6376,41 +6679,41 @@ function RestorePanel({ lists, item, restore, onClose }) {
6376
6679
  setBusy(false);
6377
6680
  }
6378
6681
  };
6379
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
6682
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
6380
6683
  Panel,
6381
6684
  {
6382
6685
  title: `Restore "${item.name}"`,
6383
6686
  size: "md",
6384
6687
  onClose,
6385
- footer: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
6386
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_controls23.Button, { variant: "quiet", onClick: onClose, children: refused ? "Close" : "Cancel" }),
6387
- 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" })
6688
+ footer: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_jsx_runtime29.Fragment, { children: [
6689
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_controls24.Button, { variant: "quiet", onClick: onClose, children: refused ? "Close" : "Cancel" }),
6690
+ refused ? null : /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_controls24.Button, { variant: "primary", icon: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(RestoreGlyph, {}), disabled: busy || loading || lists.preview !== void 0 && preview === null, onClick: () => void run(), children: busy ? "Restoring\u2026" : "Restore" })
6388
6691
  ] }),
6389
6692
  children: [
6390
- 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: [
6391
- /* @__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") }) }),
6392
- /* @__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") }) }),
6393
- 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,
6394
- /* @__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" }) }),
6395
- 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
6396
- ] }) : 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." }) }),
6397
- error ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { role: "alert", className: "px-1 text-sm text-destructive", children: error }) : null
6693
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(VaultSection, { children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(Empty, { children: "Checking what comes back\u2026" }) }) : preview?.supported ? /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(VaultSection, { title: "Comes back", children: [
6694
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(VaultRow, { label: "Fields", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-foreground", children: count(preview.fields, "field") }) }),
6695
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(VaultRow, { label: "Files", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-foreground", children: count(preview.attachments, "file") }) }),
6696
+ preview.passkeys === 1 ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(VaultRow, { label: "Passkey", hint: "Not turned on; the site may not accept it", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-foreground", children: "1 passkey" }) }) : null,
6697
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(VaultRow, { label: "Stays off", hint: "Turn each back on yourself", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-muted-foreground", children: "Sharing, browser fill, codes, sandboxes, agents" }) }),
6698
+ preview.priorWasDisabled ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(VaultRow, { label: "Before", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-muted-foreground", children: "It was already off before it was deleted." }) }) : null
6699
+ ] }) : preview ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(VaultSection, { children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(Empty, { children: refusalText(preview.reason) }) }) : /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(VaultSection, { children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(Empty, { children: "It comes back turned off: sharing, browser fill, codes and sandbox use stay off." }) }),
6700
+ error ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { role: "alert", className: "px-1 text-sm text-destructive", children: error }) : null
6398
6701
  ]
6399
6702
  }
6400
6703
  );
6401
6704
  }
6402
6705
 
6403
6706
  // src/lists/TrashView.tsx
6404
- var import_jsx_runtime29 = require("react/jsx-runtime");
6707
+ var import_jsx_runtime30 = require("react/jsx-runtime");
6405
6708
  function trashLineOf(item) {
6406
6709
  return [item.definitionLabel || null, item.owner.label, item.deletion?.deletedAt ? `Deleted ${(0, import_format9.formatAbsoluteDate)(item.deletion.deletedAt, DAY_FORMAT, "")}` : null].filter(Boolean).join(" \xB7 ");
6407
6710
  }
6408
6711
  function TrashView({ port, deleted, query, header, onChanged }) {
6409
6712
  const confirmed = useConfirmed();
6410
- const [busyId, setBusyId] = (0, import_react30.useState)(null);
6411
- const [message2, setMessage] = (0, import_react30.useState)(null);
6713
+ const [busyId, setBusyId] = (0, import_react31.useState)(null);
6714
+ const [message2, setMessage] = (0, import_react31.useState)(null);
6412
6715
  const shown = deleted.filter((i) => trashItemMatchesQuery(i, query));
6413
- const [restoring, setRestoring] = (0, import_react30.useState)(null);
6716
+ const [restoring, setRestoring] = (0, import_react31.useState)(null);
6414
6717
  const restore = async (item, deletionId) => {
6415
6718
  setBusyId(item.id);
6416
6719
  setMessage(null);
@@ -6426,35 +6729,35 @@ function TrashView({ port, deleted, query, header, onChanged }) {
6426
6729
  setBusyId(null);
6427
6730
  }
6428
6731
  };
6429
- 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: [
6732
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex min-h-0 flex-1 flex-col gap-3 overflow-y-auto p-3", children: [
6430
6733
  header,
6431
- /* @__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) => (
6734
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(VaultSection, { title: "Trash", children: shown.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Empty, { children: deleted.length === 0 ? "The trash is empty." : "Nothing matches." }) : shown.map((item) => (
6432
6735
  // A list row, not a field row: the name gets the whole width (on a phone a label column
6433
6736
  // left "Vau…" for every row), the deletion date sits under it.
6434
- /* @__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: [
6435
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("span", { className: "flex min-w-0 flex-1 flex-col leading-tight", children: [
6436
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "truncate text-sm text-foreground", children: item.name }),
6437
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "truncate text-xs text-muted-foreground", children: trashLineOf(item) })
6737
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex min-h-12 items-center gap-3 px-3 py-1.5 sm:px-4", children: [
6738
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "flex min-w-0 flex-1 flex-col leading-tight", children: [
6739
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "truncate text-sm text-foreground", children: item.name }),
6740
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "truncate text-xs text-muted-foreground", children: trashLineOf(item) })
6438
6741
  ] }),
6439
- /* @__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" })
6742
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_controls25.Button, { variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(RestoreGlyph, {}), disabled: busyId !== null || !item.deletion, onClick: () => setRestoring(item), children: "Restore" })
6440
6743
  ] }, item.id)
6441
6744
  )) }),
6442
- restoring ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(RestorePanel, { lists: port.lists, item: restoring, restore: (deletionId) => restore(restoring, deletionId), onClose: () => setRestoring(null) }) : null,
6443
- message2 ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { role: "status", className: message2.tone === "error" ? "px-1 text-sm text-destructive" : "px-1 text-sm text-muted-foreground", children: message2.text }) : null
6745
+ restoring ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(RestorePanel, { lists: port.lists, item: restoring, restore: (deletionId) => restore(restoring, deletionId), onClose: () => setRestoring(null) }) : null,
6746
+ message2 ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { role: "status", className: message2.tone === "error" ? "px-1 text-sm text-destructive" : "px-1 text-sm text-muted-foreground", children: message2.text }) : null
6444
6747
  ] });
6445
6748
  }
6446
6749
 
6447
6750
  // src/NewItemFlow.tsx
6448
- var import_react31 = require("react");
6449
- var import_design_system20 = require("@ai-matrx/design-system");
6450
- var import_controls25 = require("@ai-matrx/design-system/controls");
6451
- var import_icons12 = require("@ai-matrx/design-system/icons");
6452
- var import_jsx_runtime30 = require("react/jsx-runtime");
6751
+ var import_react32 = require("react");
6752
+ var import_design_system21 = require("@ai-matrx/design-system");
6753
+ var import_controls26 = require("@ai-matrx/design-system/controls");
6754
+ var import_icons13 = require("@ai-matrx/design-system/icons");
6755
+ var import_jsx_runtime31 = require("react/jsx-runtime");
6453
6756
  function NewItemFlow({ definitions, url, onUrl, onChoose, onCancel }) {
6454
- const [search, setSearch] = (0, import_react31.useState)("");
6455
- const guess = (0, import_react31.useMemo)(() => inferFromUrl(url, definitions), [url, definitions]);
6757
+ const [search, setSearch] = (0, import_react32.useState)("");
6758
+ const guess = (0, import_react32.useMemo)(() => inferFromUrl(url, definitions), [url, definitions]);
6456
6759
  const common = COMMON_DEFINITION_KEYS.map((k) => definitions.find((d) => d.key === k)).filter((d) => d !== void 0);
6457
- const matches = (0, import_react31.useMemo)(() => {
6760
+ const matches = (0, import_react32.useMemo)(() => {
6458
6761
  const q = search.trim().toLowerCase();
6459
6762
  if (!q) return [];
6460
6763
  return definitions.filter((d) => `${d.label} ${d.key} ${d.providerKey ?? ""} ${FAMILY_LABELS[d.family] ?? ""}`.toLowerCase().includes(q)).slice(0, 60);
@@ -6463,15 +6766,15 @@ function NewItemFlow({ definitions, url, onUrl, onChoose, onCancel }) {
6463
6766
  const alternatives = (guess?.alternatives ?? []).map((k) => definitions.find((d) => d.key === k)).filter((d) => d !== void 0).slice(0, 4);
6464
6767
  const use = (d) => onChoose(d.key, guess?.name ?? "", guess?.url ?? url.trim());
6465
6768
  const shown = search.trim() ? matches : common;
6466
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex h-full min-h-0 flex-col bg-background", children: [
6467
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("header", { className: "flex min-h-14 items-center gap-2 border-b border-border px-3 sm:px-5", children: [
6468
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_controls25.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ChevronLeftGlyph, {}), "aria-label": "Cancel", onClick: onCancel }),
6469
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("h2", { className: "text-base font-semibold", children: "New item" })
6769
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex h-full min-h-0 flex-col bg-background", children: [
6770
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("header", { className: "flex min-h-14 items-center gap-2 border-b border-border px-3 sm:px-5", children: [
6771
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_controls26.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(ChevronLeftGlyph, {}), "aria-label": "Cancel", onClick: onCancel }),
6772
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("h2", { className: "text-base font-semibold", children: "New item" })
6470
6773
  ] }),
6471
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "min-h-0 flex-1 overflow-y-auto", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "mx-auto flex w-full max-w-2xl flex-col gap-8 px-4 py-8 sm:px-6 sm:py-12", children: [
6472
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-3", children: [
6473
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6474
- import_controls25.Field,
6774
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "min-h-0 flex-1 overflow-y-auto", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "mx-auto flex w-full max-w-2xl flex-col gap-8 px-4 py-8 sm:px-6 sm:py-12", children: [
6775
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex flex-col gap-3", children: [
6776
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6777
+ import_controls26.Field,
6475
6778
  {
6476
6779
  hero: true,
6477
6780
  value: url,
@@ -6483,45 +6786,45 @@ function NewItemFlow({ definitions, url, onUrl, onChoose, onCancel }) {
6483
6786
  "aria-label": "Website address",
6484
6787
  inputMode: "url",
6485
6788
  autoFocus: true,
6486
- icon: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_icons12.GlobeIcon, {})
6789
+ icon: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_icons13.GlobeIcon, {})
6487
6790
  }
6488
6791
  ),
6489
- 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: [
6490
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center gap-3", children: [
6491
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { "aria-hidden": true, className: "flex size-9 shrink-0 items-center justify-center rounded-lg bg-muted text-sm font-semibold", children: guess.name.charAt(0).toUpperCase() }),
6492
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col", children: [
6493
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "truncate text-sm font-medium", children: guess.name }),
6494
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "truncate text-xs text-muted-foreground", children: guess.url.replace(/^https?:\/\//, "") })
6792
+ guess && login ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex flex-col gap-2 rounded-xl border border-border bg-card p-3", children: [
6793
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex items-center gap-3", children: [
6794
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { "aria-hidden": true, className: "flex size-9 shrink-0 items-center justify-center rounded-lg bg-muted text-sm font-semibold", children: guess.name.charAt(0).toUpperCase() }),
6795
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col", children: [
6796
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "truncate text-sm font-medium", children: guess.name }),
6797
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "truncate text-xs text-muted-foreground", children: guess.url.replace(/^https?:\/\//, "") })
6495
6798
  ] }),
6496
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_controls25.Button, { variant: "primary", onClick: () => use(login), children: "Save login" })
6799
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_controls26.Button, { variant: "primary", onClick: () => use(login), children: "Save login" })
6497
6800
  ] }),
6498
- alternatives.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-wrap items-center gap-1.5 pl-12", children: [
6499
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "text-xs text-muted-foreground", children: "Or" }),
6500
- alternatives.map((d) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_controls25.Button, { variant: "outline", onClick: () => use(d), children: d.label }, d.key))
6801
+ alternatives.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex flex-wrap items-center gap-1.5 pl-12", children: [
6802
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-xs text-muted-foreground", children: "Or" }),
6803
+ alternatives.map((d) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_controls26.Button, { variant: "outline", onClick: () => use(d), children: d.label }, d.key))
6501
6804
  ] }) : null
6502
- ] }) : url.trim() ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { className: "px-1 text-sm text-muted-foreground", children: "Not a website address. Pick a type below; it is kept." }) : null
6805
+ ] }) : url.trim() ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "px-1 text-sm text-muted-foreground", children: "Not a website address. Pick a type below; it is kept." }) : null
6503
6806
  ] }),
6504
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-3", children: [
6505
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "flex items-center justify-between gap-3", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("h3", { className: "text-xs font-medium text-muted-foreground", children: search.trim() ? "Matching types" : "Or choose a type" }) }),
6506
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("ul", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: shown.map((d) => {
6807
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex flex-col gap-3", children: [
6808
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "flex items-center justify-between gap-3", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("h3", { className: "text-xs font-medium text-muted-foreground", children: search.trim() ? "Matching types" : "Or choose a type" }) }),
6809
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("ul", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: shown.map((d) => {
6507
6810
  const Icon = definitionGlyph(d.key, d.family);
6508
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("button", { type: "button", onClick: () => use(d), className: (0, import_design_system20.cn)("flex h-12 w-full items-center gap-3 rounded-xl border border-border bg-card px-3 text-left hover:bg-accent"), children: [
6509
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "flex size-8 shrink-0 items-center justify-center rounded-lg bg-muted", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Icon, { className: "size-4" }) }),
6510
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm font-medium", children: d.label })
6811
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("button", { type: "button", onClick: () => use(d), className: (0, import_design_system21.cn)("flex h-12 w-full items-center gap-3 rounded-xl border border-border bg-card px-3 text-left hover:bg-accent"), children: [
6812
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "flex size-8 shrink-0 items-center justify-center rounded-lg bg-muted", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(Icon, { className: "size-4" }) }),
6813
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm font-medium", children: d.label })
6511
6814
  ] }) }, d.key);
6512
6815
  }) }),
6513
- search.trim() && matches.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { className: "px-1 text-sm text-muted-foreground", children: "No type matches." }) : null,
6514
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_controls25.SearchField, { value: search, onChange: (e) => setSearch(e.target.value), placeholder: `Search all ${definitions.length} types`, "aria-label": "Search types" })
6816
+ search.trim() && matches.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "px-1 text-sm text-muted-foreground", children: "No type matches." }) : null,
6817
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_controls26.SearchField, { value: search, onChange: (e) => setSearch(e.target.value), placeholder: `Search all ${definitions.length} types`, "aria-label": "Search types" })
6515
6818
  ] })
6516
6819
  ] }) })
6517
6820
  ] });
6518
6821
  }
6519
6822
 
6520
6823
  // src/sharing/SecureLinkPanel.tsx
6521
- var import_react32 = require("react");
6522
- var import_confirm_opener10 = require("@ai-matrx/kit/confirm-opener");
6523
- var import_design_system21 = require("@ai-matrx/design-system");
6524
- var import_controls26 = require("@ai-matrx/design-system/controls");
6824
+ var import_react33 = require("react");
6825
+ var import_confirm_opener11 = require("@ai-matrx/kit/confirm-opener");
6826
+ var import_design_system22 = require("@ai-matrx/design-system");
6827
+ var import_controls27 = require("@ai-matrx/design-system/controls");
6525
6828
  var import_format11 = require("@ai-matrx/kit/format");
6526
6829
 
6527
6830
  // src/sharing/secure-link-logic.ts
@@ -6597,24 +6900,24 @@ function sortSent(rows) {
6597
6900
  }
6598
6901
 
6599
6902
  // src/sharing/SecureLinkPanel.tsx
6600
- var import_jsx_runtime31 = require("react/jsx-runtime");
6903
+ var import_jsx_runtime32 = require("react/jsx-runtime");
6601
6904
  function SecureLinkPanel({ item, port, onClose }) {
6602
6905
  const sharing = port.sharing;
6603
6906
  const { busy, error, notice, run, setNotice } = useConfirmedChange();
6604
- const [remedy, setRemedy] = (0, import_react32.useState)(null);
6605
- const [options, setOptions] = (0, import_react32.useState)(null);
6606
- const [optionsError, setOptionsError] = (0, import_react32.useState)(null);
6607
- const [sent, setSent] = (0, import_react32.useState)(null);
6608
- const [sentError, setSentError] = (0, import_react32.useState)(null);
6609
- const [nonce, setNonce] = (0, import_react32.useState)(0);
6610
- const [email, setEmail] = (0, import_react32.useState)("");
6611
- const [phone, setPhone] = (0, import_react32.useState)("");
6612
- const [name, setName] = (0, import_react32.useState)("");
6613
- const [linkBy, setLinkBy] = (0, import_react32.useState)("email");
6614
- const [fields, setFields] = (0, import_react32.useState)([]);
6615
- const [note, setNote] = (0, import_react32.useState)("");
6616
- const [sameChannelSent, setSameChannelSent] = (0, import_react32.useState)(false);
6617
- (0, import_react32.useEffect)(() => {
6907
+ const [remedy, setRemedy] = (0, import_react33.useState)(null);
6908
+ const [options, setOptions] = (0, import_react33.useState)(null);
6909
+ const [optionsError, setOptionsError] = (0, import_react33.useState)(null);
6910
+ const [sent, setSent] = (0, import_react33.useState)(null);
6911
+ const [sentError, setSentError] = (0, import_react33.useState)(null);
6912
+ const [nonce, setNonce] = (0, import_react33.useState)(0);
6913
+ const [email, setEmail] = (0, import_react33.useState)("");
6914
+ const [phone, setPhone] = (0, import_react33.useState)("");
6915
+ const [name, setName] = (0, import_react33.useState)("");
6916
+ const [linkBy, setLinkBy] = (0, import_react33.useState)("email");
6917
+ const [fields, setFields] = (0, import_react33.useState)([]);
6918
+ const [note, setNote] = (0, import_react33.useState)("");
6919
+ const [sameChannelSent, setSameChannelSent] = (0, import_react33.useState)(false);
6920
+ (0, import_react33.useEffect)(() => {
6618
6921
  let live = true;
6619
6922
  setOptionsError(null);
6620
6923
  sharing.secureLinkOptions(item).then(
@@ -6629,7 +6932,7 @@ function SecureLinkPanel({ item, port, onClose }) {
6629
6932
  live = false;
6630
6933
  };
6631
6934
  }, [sharing, item]);
6632
- (0, import_react32.useEffect)(() => {
6935
+ (0, import_react33.useEffect)(() => {
6633
6936
  const list = sharing.sentSecureLinks;
6634
6937
  if (!list) return;
6635
6938
  let live = true;
@@ -6642,9 +6945,9 @@ function SecureLinkPanel({ item, port, onClose }) {
6642
6945
  live = false;
6643
6946
  };
6644
6947
  }, [sharing, item, nonce]);
6645
- const [phoneTyped, setPhoneTyped] = (0, import_react32.useState)(false);
6646
- const prefilled = (0, import_react32.useRef)(false);
6647
- (0, import_react32.useEffect)(() => {
6948
+ const [phoneTyped, setPhoneTyped] = (0, import_react33.useState)(false);
6949
+ const prefilled = (0, import_react33.useRef)(false);
6950
+ (0, import_react33.useEffect)(() => {
6648
6951
  const lookup = sharing.phoneOnFile;
6649
6952
  if (!lookup || phoneTyped) return;
6650
6953
  const clear = () => {
@@ -6706,7 +7009,7 @@ function SecureLinkPanel({ item, port, onClose }) {
6706
7009
  setNonce((n) => n + 1);
6707
7010
  };
6708
7011
  const turnOff = async (row) => {
6709
- const ok = await (0, import_confirm_opener10.confirm)({
7012
+ const ok = await (0, import_confirm_opener11.confirm)({
6710
7013
  title: "Turn off this link?",
6711
7014
  description: `The link to ${recipientOf(row)} stops working at once and what it carries is deleted. They will need a new one.`,
6712
7015
  confirmLabel: "Turn off",
@@ -6719,23 +7022,23 @@ function SecureLinkPanel({ item, port, onClose }) {
6719
7022
  setNonce((n) => n + 1);
6720
7023
  };
6721
7024
  const toggle2 = (key, on) => setFields((cur) => on ? [...cur.filter((k) => k !== key), key] : cur.filter((k) => k !== key));
6722
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
7025
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
6723
7026
  Panel,
6724
7027
  {
6725
7028
  title: "Send securely",
6726
7029
  size: "md",
6727
7030
  onClose,
6728
- footer: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(PanelFooter, { status: error || notice ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(StatusLine, { error, notice }) : null, children: [
6729
- sameChannelSent && !error ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_controls26.Badge, { tone: "warning", children: "Both by email" }) : null,
6730
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_controls26.Button, { variant: "quiet", onClick: onClose, children: "Close" }),
6731
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_controls26.Button, { variant: "primary", disabled: !canSend, onClick: () => void send(), children: busy === "send" ? "Sending\u2026" : "Send link" })
7031
+ footer: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(PanelFooter, { status: error || notice ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(StatusLine, { error, notice }) : null, children: [
7032
+ sameChannelSent && !error ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_controls27.Badge, { tone: "warning", children: "Both by email" }) : null,
7033
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_controls27.Button, { variant: "quiet", onClick: onClose, children: "Close" }),
7034
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_controls27.Button, { variant: "primary", disabled: !canSend, onClick: () => void send(), children: busy === "send" ? "Sending\u2026" : "Send link" })
6732
7035
  ] }),
6733
7036
  children: [
6734
- remedy ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "px-1 text-xs text-muted-foreground", children: remedy }) : null,
6735
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(VaultSection, { title: "Recipient", children: [
6736
- /* @__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" }) }),
6737
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(VaultRow, { label: "Mobile", hint: "For the code", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6738
- import_controls26.Field,
7037
+ remedy ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("p", { className: "px-1 text-xs text-muted-foreground", children: remedy }) : null,
7038
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(VaultSection, { title: "Recipient", children: [
7039
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(VaultRow, { label: "Email", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_controls27.Field, { type: "email", autoComplete: "off", placeholder: "name@example.com", "aria-label": "Their email", value: email, onChange: (e) => setEmail(e.target.value), className: "w-full" }) }),
7040
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(VaultRow, { label: "Mobile", hint: "For the code", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7041
+ import_controls27.Field,
6739
7042
  {
6740
7043
  type: "tel",
6741
7044
  autoComplete: "off",
@@ -6750,9 +7053,9 @@ function SecureLinkPanel({ item, port, onClose }) {
6750
7053
  className: "w-full"
6751
7054
  }
6752
7055
  ) }),
6753
- /* @__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" }) }),
6754
- plan && !plan.same ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(VaultRow, { label: "Link by", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6755
- import_controls26.SegmentedControl,
7056
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(VaultRow, { label: "Name", hint: "Optional", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_controls27.Field, { autoComplete: "off", placeholder: "Their name", "aria-label": "Their name", value: name, onChange: (e) => setName(e.target.value), className: "w-full" }) }),
7057
+ plan && !plan.same ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(VaultRow, { label: "Link by", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7058
+ import_controls27.SegmentedControl,
6756
7059
  {
6757
7060
  "aria-label": "Send the link by",
6758
7061
  value: linkBy,
@@ -6763,28 +7066,28 @@ function SecureLinkPanel({ item, port, onClose }) {
6763
7066
  ]
6764
7067
  }
6765
7068
  ) }) : null,
6766
- 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
7069
+ email.trim() ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(VaultRow, { label: "Delivery", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: plan?.same ? "text-warning" : "text-foreground", children: planWords(plan) }) }) : null
6767
7070
  ] }),
6768
- /* @__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: [
6769
- /* @__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 }),
6770
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm text-foreground", children: f.label }),
6771
- !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
7071
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(VaultSection, { title: "Include", children: optionsError ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Empty, { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-destructive", children: optionsError }) }) : !options ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_controls27.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_runtime32.jsx)(Empty, { children: "Name and details only" }) : options.fields.map((f) => /* @__PURE__ */ (0, import_jsx_runtime32.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: [
7072
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_design_system22.Checkbox, { checked: fields.includes(f.key), disabled: !f.available, onCheckedChange: (v) => toggle2(f.key, v === true), "aria-label": f.label }),
7073
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm text-foreground", children: f.label }),
7074
+ !f.available && f.reason ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "min-w-0 max-w-[55%] truncate text-xs text-muted-foreground", title: f.reason, children: f.reason }) : null
6772
7075
  ] }, f.key)) }),
6773
- /* @__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) }) }) }),
6774
- options ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(VaultSection, { title: "Link", children: [
6775
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(VaultRow, { label: "Opens", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-foreground", children: "Once" }) }),
6776
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(VaultRow, { label: "Link expires", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("span", { className: "text-foreground", children: [
7076
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(VaultSection, { title: "Message", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "px-3 py-1 sm:px-4", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_controls27.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) }) }) }),
7077
+ options ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(VaultSection, { title: "Link", children: [
7078
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(VaultRow, { label: "Opens", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-foreground", children: "Once" }) }),
7079
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(VaultRow, { label: "Link expires", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "text-foreground", children: [
6777
7080
  "After ",
6778
7081
  lifetimeWords(options.linkMinutes)
6779
7082
  ] }) }),
6780
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(VaultRow, { label: "Code expires", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("span", { className: "text-foreground", children: [
7083
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(VaultRow, { label: "Code expires", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "text-foreground", children: [
6781
7084
  "After ",
6782
7085
  lifetimeWords(options.codeMinutes)
6783
7086
  ] }) })
6784
7087
  ] }) : null,
6785
- 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: [
6786
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_controls26.Badge, { tone: STATUS_TONE[row.status] ?? "neutral", children: statusWord(row.status) }),
6787
- 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
7088
+ sharing.sentSecureLinks ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(VaultSection, { title: "Sent links", children: sentError ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Empty, { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-destructive", children: sentError }) }) : !sent ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_controls27.RegionSkeleton, { shape: "rows", count: 2, "aria-label": "Loading sent links", className: "px-3 sm:px-4" }) : sent.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Empty, { children: "None yet" }) : sent.map((row) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(AccessLine, { glyph: row.status === "pending" ? ClockGlyph : row.fieldKeys.length ? LockGlyph : ShareGlyph, who: recipientOf(row), meta: sentMeta(row, options), children: [
7089
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_controls27.Badge, { tone: STATUS_TONE[row.status] ?? "neutral", children: statusWord(row.status) }),
7090
+ row.status === "pending" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_controls27.Button, { variant: "quiet", disabled: busy !== null, onClick: () => void turnOff(row), children: "Turn off" }) : null
6788
7091
  ] }, row.id)) }) : null
6789
7092
  ]
6790
7093
  }
@@ -6797,9 +7100,9 @@ function sentMeta(row, options) {
6797
7100
  }
6798
7101
 
6799
7102
  // src/devices/DevicesPanel.tsx
6800
- var import_react33 = require("react");
6801
- var import_confirm_opener11 = require("@ai-matrx/kit/confirm-opener");
6802
- var import_controls27 = require("@ai-matrx/design-system/controls");
7103
+ var import_react34 = require("react");
7104
+ var import_confirm_opener12 = require("@ai-matrx/kit/confirm-opener");
7105
+ var import_controls28 = require("@ai-matrx/design-system/controls");
6803
7106
  var import_format12 = require("@ai-matrx/kit/format");
6804
7107
 
6805
7108
  // src/devices/logic.ts
@@ -6880,18 +7183,18 @@ function addPasskeyFailure(message2) {
6880
7183
  var isRevoked = (d) => d.revokedAt !== null;
6881
7184
 
6882
7185
  // src/devices/DevicesPanel.tsx
6883
- var import_jsx_runtime32 = require("react/jsx-runtime");
7186
+ var import_jsx_runtime33 = require("react/jsx-runtime");
6884
7187
  var messageOf3 = (e, fallback) => e instanceof Error && e.message ? e.message : fallback;
6885
7188
  function ErrorLine2({ text }) {
6886
- return text ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("p", { role: "alert", className: "px-1 text-sm text-destructive", children: text }) : null;
7189
+ return text ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { role: "alert", className: "px-1 text-sm text-destructive", children: text }) : null;
6887
7190
  }
6888
7191
  function DevicesPanel({ port, onClose }) {
6889
7192
  const confirmed = useConfirmed();
6890
7193
  const notify = useNotify();
6891
- const [devices, setDevices] = (0, import_react33.useState)(null);
6892
- const [error, setError] = (0, import_react33.useState)(null);
6893
- const [busyId, setBusyId] = (0, import_react33.useState)(null);
6894
- const load = (0, import_react33.useCallback)(async () => {
7194
+ const [devices, setDevices] = (0, import_react34.useState)(null);
7195
+ const [error, setError] = (0, import_react34.useState)(null);
7196
+ const [busyId, setBusyId] = (0, import_react34.useState)(null);
7197
+ const load = (0, import_react34.useCallback)(async () => {
6895
7198
  setError(null);
6896
7199
  try {
6897
7200
  setDevices(await port.devices.list());
@@ -6899,11 +7202,11 @@ function DevicesPanel({ port, onClose }) {
6899
7202
  setError(messageOf3(e, "Your browsers could not be read."));
6900
7203
  }
6901
7204
  }, [port]);
6902
- (0, import_react33.useEffect)(() => {
7205
+ (0, import_react34.useEffect)(() => {
6903
7206
  void load();
6904
7207
  }, [load]);
6905
7208
  const revoke = async (device) => {
6906
- const yes = await (0, import_confirm_opener11.confirm)({
7209
+ const yes = await (0, import_confirm_opener12.confirm)({
6907
7210
  title: `Revoke ${device.label}?`,
6908
7211
  description: "It stops filling now and the extension there signs out. It fills again only after you sign in there and confirm.",
6909
7212
  confirmLabel: "Revoke",
@@ -6922,19 +7225,19 @@ function DevicesPanel({ port, onClose }) {
6922
7225
  setBusyId(null);
6923
7226
  }
6924
7227
  };
6925
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Panel, { title: "Browsers that can fill", onClose, size: "md", children: [
6926
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ErrorLine2, { text: error }),
6927
- /* @__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) => {
7228
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(Panel, { title: "Browsers that can fill", onClose, size: "md", children: [
7229
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ErrorLine2, { text: error }),
7230
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(VaultSection, { children: devices === null ? error ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Empty, { children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Button, { variant: "outline", onClick: () => void load(), children: "Try again" }) }) : /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.RegionSkeleton, { shape: "rows", count: 2, "aria-label": "Loading your browsers", className: "px-3 sm:px-4" }) : devices.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Empty, { children: "No browser can fill yet. Turn it on in the extension." }) : devices.map((device) => {
6928
7231
  const off = isRevoked(device);
6929
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7232
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
6930
7233
  VaultRow,
6931
7234
  {
6932
7235
  label: off ? "Turned off" : "Can fill",
6933
7236
  hint: off ? (0, import_format12.formatAbsoluteDate)(device.revokedAt, DAY_FORMAT, "") : void 0,
6934
- 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" }),
6935
- children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "flex min-w-0 flex-col", children: [
6936
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: off ? "truncate text-muted-foreground" : "truncate text-foreground", children: device.label }),
6937
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "truncate text-xs text-muted-foreground", children: [
7237
+ actions: off ? null : /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Button, { variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(PowerGlyph, {}), disabled: busyId !== null, onClick: () => void revoke(device), children: "Revoke" }),
7238
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: "flex min-w-0 flex-col", children: [
7239
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: off ? "truncate text-muted-foreground" : "truncate text-foreground", children: device.label }),
7240
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: "truncate text-xs text-muted-foreground", children: [
6938
7241
  device.lastUsedAt ? `Last used ${(0, import_format12.formatAbsoluteDate)(device.lastUsedAt, void 0, "")}` : "Never used",
6939
7242
  device.addedAt ? ` \xB7 added ${(0, import_format12.formatAbsoluteDate)(device.addedAt, DAY_FORMAT, "")}` : ""
6940
7243
  ] })
@@ -6957,11 +7260,11 @@ function ApprovePanel({ port, host, onClose, approvalKey, label, kind = "browser
6957
7260
  const where = isMac ? "the Mac app" : "the extension";
6958
7261
  const passkeys = port.devices.passkeys;
6959
7262
  const here = passkeys?.available() ?? false;
6960
- const [methods, setMethods] = (0, import_react33.useState)(null);
6961
- const [busy, setBusy] = (0, import_react33.useState)(null);
6962
- const [error, setError] = (0, import_react33.useState)(null);
6963
- const [approvedUntil, setApprovedUntil] = (0, import_react33.useState)(null);
6964
- const load = (0, import_react33.useCallback)(async () => {
7263
+ const [methods, setMethods] = (0, import_react34.useState)(null);
7264
+ const [busy, setBusy] = (0, import_react34.useState)(null);
7265
+ const [error, setError] = (0, import_react34.useState)(null);
7266
+ const [approvedUntil, setApprovedUntil] = (0, import_react34.useState)(null);
7267
+ const load = (0, import_react34.useCallback)(async () => {
6965
7268
  setError(null);
6966
7269
  try {
6967
7270
  setMethods(await port.devices.stepUpMethods());
@@ -6969,7 +7272,7 @@ function ApprovePanel({ port, host, onClose, approvalKey, label, kind = "browser
6969
7272
  setError(messageOf3(e, "Your account could not be checked."));
6970
7273
  }
6971
7274
  }, [port]);
6972
- (0, import_react33.useEffect)(() => {
7275
+ (0, import_react34.useEffect)(() => {
6973
7276
  if (key && here) void load();
6974
7277
  }, [key, here, load]);
6975
7278
  const approve = async () => {
@@ -7011,55 +7314,55 @@ function ApprovePanel({ port, host, onClose, approvalKey, label, kind = "browser
7011
7314
  };
7012
7315
  const canApprove = Boolean(key && passkeys && here && methods?.passkey && !approvedUntil);
7013
7316
  const title = isMac ? "Approve this Mac" : name ? `Approve ${name}` : "Approve this browser";
7014
- const footer = approvedUntil ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_controls27.Button, { variant: "primary", onClick: onClose, children: "Done" }) : /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
7015
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_controls27.Button, { variant: "quiet", disabled: busy !== null, onClick: refuse, children: key ? "Refuse" : "Close" }),
7016
- 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
7317
+ const footer = approvedUntil ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Button, { variant: "primary", onClick: onClose, children: "Done" }) : /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
7318
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Button, { variant: "quiet", disabled: busy !== null, onClick: refuse, children: key ? "Refuse" : "Close" }),
7319
+ canApprove ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Button, { variant: "primary", icon: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(FingerprintGlyph, {}), disabled: busy !== null, onClick: () => void approve(), children: busy === "approve" ? "Approving\u2026" : "Approve with passkey" }) : null
7017
7320
  ] });
7018
- 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: [
7321
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Panel, { title, onClose: refuse, size: "sm", footer, children: !key ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(VaultSection, { children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(Empty, { children: [
7019
7322
  "This link names no key. Start again from ",
7020
7323
  where,
7021
7324
  "."
7022
- ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
7023
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(VaultSection, { title: "What is asking", children: [
7024
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(VaultRow, { label: "Asking", hint: "Approve only if you just asked", children: asker }),
7025
- name ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(VaultRow, { label: "Name", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "block truncate", children: name }) }) : null,
7026
- /* @__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) }) })
7325
+ ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
7326
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(VaultSection, { title: "What is asking", children: [
7327
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(VaultRow, { label: "Asking", hint: "Approve only if you just asked", children: asker }),
7328
+ name ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(VaultRow, { label: "Name", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "block truncate", children: name }) }) : null,
7329
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(VaultRow, { label: "Code", hint: `Must match ${where}`, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "font-mono tracking-wider text-foreground", children: shortFingerprint(key) }) })
7027
7330
  ] }),
7028
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ErrorLine2, { text: error }),
7029
- /* @__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: [
7331
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ErrorLine2, { text: error }),
7332
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(VaultSection, { title: "Confirm it\u2019s you", children: approvedUntil ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(VaultRow, { label: "Approved", actions: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(CheckGlyph, { className: "size-4 text-primary" }), children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: "text-foreground", children: [
7030
7333
  "Return to ",
7031
7334
  where,
7032
7335
  " by ",
7033
7336
  (0, import_format12.formatAbsoluteDate)(approvedUntil, void 0, ""),
7034
7337
  "."
7035
- ] }) }) : !passkeys ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Empty, { children: [
7338
+ ] }) }) : !passkeys ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(Empty, { children: [
7036
7339
  "Approve with your password in ",
7037
7340
  where,
7038
7341
  "."
7039
- ] }) : !here ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7342
+ ] }) : !here ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7040
7343
  VaultRow,
7041
7344
  {
7042
7345
  label: "Passkey",
7043
7346
  hint: `Passkeys work only on ${passkeys.rpId}`,
7044
- actions: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_controls27.Button, { variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ExternalGlyph, {}), onClick: openOnDomain, children: "Open there" }),
7045
- children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-muted-foreground", children: "Not on this page" })
7347
+ actions: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Button, { variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ExternalGlyph, {}), onClick: openOnDomain, children: "Open there" }),
7348
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-muted-foreground", children: "Not on this page" })
7046
7349
  }
7047
- ) : 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)(
7350
+ ) : methods === null ? error ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Empty, { children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Button, { variant: "outline", onClick: () => void load(), children: "Try again" }) }) : /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.RegionSkeleton, { shape: "rows", count: 1, "aria-label": "Checking your account", className: "px-3 sm:px-4" }) : !methods.passkey ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7048
7351
  VaultRow,
7049
7352
  {
7050
7353
  label: "Passkey",
7051
7354
  hint: methods.password ? `Or type your password in ${where}` : "Add one to approve",
7052
- 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" }),
7053
- children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-muted-foreground", children: methods.password ? "None yet" : "No password or passkey" })
7355
+ actions: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Button, { variant: "primary", icon: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(FingerprintGlyph, {}), disabled: busy !== null, onClick: () => void addPasskey(), children: busy === "add" ? "Adding\u2026" : "Add passkey" }),
7356
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-muted-foreground", children: methods.password ? "None yet" : "No password or passkey" })
7054
7357
  }
7055
- ) : /* @__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" }) }) })
7358
+ ) : /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(VaultRow, { label: "Passkey", hint: "Your device asks for it next", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-foreground", children: "Ready" }) }) })
7056
7359
  ] }) });
7057
7360
  }
7058
7361
 
7059
7362
  // src/native/NativeImportPanel.tsx
7060
- var import_react35 = require("react");
7061
- var import_confirm_opener12 = require("@ai-matrx/kit/confirm-opener");
7062
- var import_controls28 = require("@ai-matrx/design-system/controls");
7363
+ var import_react36 = require("react");
7364
+ var import_confirm_opener13 = require("@ai-matrx/kit/confirm-opener");
7365
+ var import_controls29 = require("@ai-matrx/design-system/controls");
7063
7366
 
7064
7367
  // src/native/logic.ts
7065
7368
  var ACTIVE_PHASES = /* @__PURE__ */ new Set(["authorizing", "importing"]);
@@ -7120,19 +7423,19 @@ async function loadFullPreview(bridge, operationId, current) {
7120
7423
  }
7121
7424
 
7122
7425
  // src/native/use-native-import.ts
7123
- var import_react34 = require("react");
7426
+ var import_react35 = require("react");
7124
7427
  var fail = (e, fallback) => e instanceof Error && e.message ? e.message : fallback;
7125
7428
  var RESTART = "Your account changed. The import was stopped; start it again.";
7126
7429
  function useNativeImport(bridge, stillAllowed, onImported) {
7127
- const [screen, setScreen] = (0, import_react34.useState)({ kind: "idle", message: null });
7128
- const [busy, setBusy] = (0, import_react34.useState)(false);
7129
- const generation = (0, import_react34.useRef)(0);
7130
- const mounted = (0, import_react34.useRef)(false);
7131
- const op = (0, import_react34.useRef)(null);
7132
- const last = (0, import_react34.useRef)(null);
7133
- const timer2 = (0, import_react34.useRef)(null);
7134
- const polls = (0, import_react34.useRef)(0);
7135
- const refreshRef = (0, import_react34.useRef)(async () => void 0);
7430
+ const [screen, setScreen] = (0, import_react35.useState)({ kind: "idle", message: null });
7431
+ const [busy, setBusy] = (0, import_react35.useState)(false);
7432
+ const generation = (0, import_react35.useRef)(0);
7433
+ const mounted = (0, import_react35.useRef)(false);
7434
+ const op = (0, import_react35.useRef)(null);
7435
+ const last = (0, import_react35.useRef)(null);
7436
+ const timer2 = (0, import_react35.useRef)(null);
7437
+ const polls = (0, import_react35.useRef)(0);
7438
+ const refreshRef = (0, import_react35.useRef)(async () => void 0);
7136
7439
  const current = (g) => mounted.current && g === generation.current;
7137
7440
  const stopPolling = () => {
7138
7441
  if (timer2.current !== null) clearTimeout(timer2.current);
@@ -7233,7 +7536,7 @@ function useNativeImport(bridge, stillAllowed, onImported) {
7233
7536
  }
7234
7537
  };
7235
7538
  refreshRef.current = refresh;
7236
- const confirm14 = async () => {
7539
+ const confirm15 = async () => {
7237
7540
  if (screen.kind !== "preview") return;
7238
7541
  const active = op.current;
7239
7542
  if (!active?.organizationId || active.id !== screen.preview.operation_id) return;
@@ -7301,9 +7604,9 @@ function useNativeImport(bridge, stillAllowed, onImported) {
7301
7604
  setBusy(false);
7302
7605
  setScreen({ kind: "idle", message: null });
7303
7606
  };
7304
- const invalidateRef = (0, import_react34.useRef)(invalidate);
7607
+ const invalidateRef = (0, import_react35.useRef)(invalidate);
7305
7608
  invalidateRef.current = invalidate;
7306
- (0, import_react34.useEffect)(() => {
7609
+ (0, import_react35.useEffect)(() => {
7307
7610
  mounted.current = true;
7308
7611
  const off = bridge.subscribe?.(() => {
7309
7612
  if (op.current) invalidateRef.current(RESTART);
@@ -7315,11 +7618,11 @@ function useNativeImport(bridge, stillAllowed, onImported) {
7315
7618
  off?.();
7316
7619
  };
7317
7620
  }, [bridge]);
7318
- return { screen, busy, begin, refresh: () => refresh(false), confirm: confirm14, cancel, recover, reset };
7621
+ return { screen, busy, begin, refresh: () => refresh(false), confirm: confirm15, cancel, recover, reset };
7319
7622
  }
7320
7623
 
7321
7624
  // src/native/NativeImportPanel.tsx
7322
- var import_jsx_runtime33 = require("react/jsx-runtime");
7625
+ var import_jsx_runtime34 = require("react/jsx-runtime");
7323
7626
  var TONE = {
7324
7627
  eligible: "success",
7325
7628
  committed: "success",
@@ -7330,19 +7633,19 @@ var TONE = {
7330
7633
  };
7331
7634
  function NativeImportPanel({ bridge, readLimits, activeOrganizationId, organizations, onClose, onChanged }) {
7332
7635
  if (!bridge) {
7333
- 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." }) }) });
7636
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Panel, { title: "Import passkeys", size: "md", onClose, footer: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_controls29.Button, { variant: "primary", onClick: onClose, children: "Close" }), children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(VaultSection, { children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Empty, { children: "Passkey import needs the desktop app." }) }) });
7334
7637
  }
7335
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Importer, { bridge, readLimits, activeOrganizationId, organizations, onClose, onChanged });
7638
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(Importer, { bridge, readLimits, activeOrganizationId, organizations, onClose, onChanged });
7336
7639
  }
7337
7640
  function Importer({ bridge, readLimits, activeOrganizationId, organizations, onClose, onChanged }) {
7338
- const options = (0, import_react35.useMemo)(() => organizations.map((o) => ({ value: o.id, label: o.name })), [organizations]);
7339
- const [organizationId, setOrganizationId] = (0, import_react35.useState)(() => organizations.some((o) => o.id === activeOrganizationId) ? activeOrganizationId : organizations[0]?.id ?? "");
7340
- const [limits, setLimits] = (0, import_react35.useState)(null);
7341
- const [limitError, setLimitError] = (0, import_react35.useState)(null);
7641
+ const options = (0, import_react36.useMemo)(() => organizations.map((o) => ({ value: o.id, label: o.name })), [organizations]);
7642
+ const [organizationId, setOrganizationId] = (0, import_react36.useState)(() => organizations.some((o) => o.id === activeOrganizationId) ? activeOrganizationId : organizations[0]?.id ?? "");
7643
+ const [limits, setLimits] = (0, import_react36.useState)(null);
7644
+ const [limitError, setLimitError] = (0, import_react36.useState)(null);
7342
7645
  const flow = useNativeImport(bridge, (id) => organizations.some((o) => o.id === id), onChanged);
7343
7646
  const { screen, busy } = flow;
7344
7647
  const orgName = organizations.find((o) => o.id === organizationId)?.name ?? "this organization";
7345
- (0, import_react35.useEffect)(() => {
7648
+ (0, import_react36.useEffect)(() => {
7346
7649
  if (!readLimits || !organizationId) return;
7347
7650
  let live = true;
7348
7651
  setLimits(null);
@@ -7360,64 +7663,64 @@ function Importer({ bridge, readLimits, activeOrganizationId, organizations, onC
7360
7663
  const active = status !== null && !TERMINAL_PHASES.has(status.phase);
7361
7664
  const ready = preview?.slots.filter((s) => s.disposition === "eligible").length ?? 0;
7362
7665
  const importNow = async () => {
7363
- const yes = await (0, import_confirm_opener12.confirm)({ title: `Add ${plural2(ready, "passkey")} to ${orgName}?`, description: "Passkeys already there are skipped.", confirmLabel: "Import" });
7666
+ const yes = await (0, import_confirm_opener13.confirm)({ title: `Add ${plural2(ready, "passkey")} to ${orgName}?`, description: "Passkeys already there are skipped.", confirmLabel: "Import" });
7364
7667
  if (yes) await flow.confirm();
7365
7668
  };
7366
- const footer = preview ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
7367
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Button, { variant: "quiet", disabled: busy, onClick: () => void flow.cancel(), children: "Cancel" }),
7368
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_controls28.Button, { variant: "primary", icon: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ImportGlyph, { className: "size-4" }), disabled: busy || ready === 0, onClick: () => void importNow(), children: [
7669
+ const footer = preview ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
7670
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_controls29.Button, { variant: "quiet", disabled: busy, onClick: () => void flow.cancel(), children: "Cancel" }),
7671
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_controls29.Button, { variant: "primary", icon: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ImportGlyph, { className: "size-4" }), disabled: busy || ready === 0, onClick: () => void importNow(), children: [
7369
7672
  "Import ",
7370
7673
  ready
7371
7674
  ] })
7372
- ] }) : status ? active ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
7373
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Button, { variant: "outline", disabled: busy, onClick: () => void flow.refresh(), children: "Refresh" }),
7374
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Button, { variant: "outline", disabled: busy, onClick: () => void flow.cancel(), children: "Cancel import" })
7375
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
7376
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Button, { variant: "quiet", onClick: flow.reset, children: "New file" }),
7377
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Button, { variant: "primary", onClick: onClose, children: "Done" })
7378
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_controls28.Button, { variant: "quiet", onClick: onClose, children: "Close" });
7379
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(Panel, { title: "Import passkeys", size: "lg", onClose, footer, children: [
7380
- screen.kind === "idle" ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(VaultSection, { children: [
7381
- /* @__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 }) }),
7382
- /* @__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" }) }),
7383
- /* @__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" }) })
7675
+ ] }) : status ? active ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
7676
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_controls29.Button, { variant: "outline", disabled: busy, onClick: () => void flow.refresh(), children: "Refresh" }),
7677
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_controls29.Button, { variant: "outline", disabled: busy, onClick: () => void flow.cancel(), children: "Cancel import" })
7678
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
7679
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_controls29.Button, { variant: "quiet", onClick: flow.reset, children: "New file" }),
7680
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_controls29.Button, { variant: "primary", onClick: onClose, children: "Done" })
7681
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_controls29.Button, { variant: "quiet", onClick: onClose, children: "Close" });
7682
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(Panel, { title: "Import passkeys", size: "lg", onClose, footer, children: [
7683
+ screen.kind === "idle" ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(VaultSection, { children: [
7684
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(VaultRow, { label: "Save to", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_controls29.Select, { value: organizationId, options, "aria-label": "Save to", disabled: busy, onValueChange: setOrganizationId }) }),
7685
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(VaultRow, { label: "File", hint: limits ? `Up to ${plural2(limits.maxItems, "passkey")}` : "A passkey exchange file", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_controls29.Button, { variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ImportGlyph, { className: "size-4" }), disabled: busy || !organizationId || limitError !== null, onClick: () => void flow.begin(organizationId), children: busy ? "Opening\u2026" : "Choose file" }) }),
7686
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(VaultRow, { label: "Interrupted", hint: "Finish or clear an earlier import", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_controls29.Button, { variant: "quiet", disabled: busy, onClick: () => void flow.recover(), children: "Recover" }) })
7384
7687
  ] }) : null,
7385
- preview ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(VaultSection, { title: `${ready} of ${preview.total} ready`, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7688
+ preview ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(VaultSection, { title: `${ready} of ${preview.total} ready`, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7386
7689
  Windowed,
7387
7690
  {
7388
7691
  items: preview.slots,
7389
- 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)
7692
+ render: (slot) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(VaultRow, { label: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_controls29.Badge, { tone: TONE[slot.disposition], children: dispositionLabel(slot.disposition) }), hint: void 0, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "block truncate text-foreground", title: slot.reason ?? void 0, children: slot.title ?? "Unnamed passkey" }) }, slot.slot_id)
7390
7693
  }
7391
7694
  ) }) : null,
7392
- status && !preview ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(VaultSection, { title: `${accounted(status)} of ${status.total} done`, children: [
7393
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(VaultRow, { label: "Imported", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-foreground", children: status.committed }) }),
7394
- /* @__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 }) }),
7395
- /* @__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 }) }),
7396
- /* @__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 }) }),
7397
- 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,
7398
- 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
7695
+ status && !preview ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(VaultSection, { title: `${accounted(status)} of ${status.total} done`, children: [
7696
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(VaultRow, { label: "Imported", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "text-foreground", children: status.committed }) }),
7697
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(VaultRow, { label: "Already there", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "text-foreground", children: status.already_present }) }),
7698
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(VaultRow, { label: "Can't import", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "text-foreground", children: status.unsupported }) }),
7699
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(VaultRow, { label: "Failed", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: status.failed > 0 ? "text-destructive" : "text-foreground", children: status.failed }) }),
7700
+ status.uncertain > 0 ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(VaultRow, { label: "Needs recovery", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "text-foreground", children: status.uncertain }) }) : null,
7701
+ status.not_attempted > 0 ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(VaultRow, { label: "Not tried", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "text-foreground", children: status.not_attempted }) }) : null
7399
7702
  ] }) : null,
7400
- screen.message ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { role: "status", className: "px-1 text-sm text-muted-foreground", children: screen.message }) : null,
7401
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ErrorLine, { message: limitError })
7703
+ screen.message ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { role: "status", className: "px-1 text-sm text-muted-foreground", children: screen.message }) : null,
7704
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ErrorLine, { message: limitError })
7402
7705
  ] });
7403
7706
  }
7404
7707
 
7405
7708
  // src/extension/PageView.tsx
7406
- var import_react39 = require("react");
7407
- var import_design_system23 = require("@ai-matrx/design-system");
7408
- var import_controls32 = require("@ai-matrx/design-system/controls");
7409
- var import_icons14 = require("@ai-matrx/design-system/icons");
7709
+ var import_react40 = require("react");
7710
+ var import_design_system24 = require("@ai-matrx/design-system");
7711
+ var import_controls33 = require("@ai-matrx/design-system/controls");
7712
+ var import_icons15 = require("@ai-matrx/design-system/icons");
7410
7713
 
7411
7714
  // src/extension/CaptureCard.tsx
7412
- var import_react36 = require("react");
7413
- var import_controls29 = require("@ai-matrx/design-system/controls");
7414
- var import_jsx_runtime34 = require("react/jsx-runtime");
7715
+ var import_react37 = require("react");
7716
+ var import_controls30 = require("@ai-matrx/design-system/controls");
7717
+ var import_jsx_runtime35 = require("react/jsx-runtime");
7415
7718
  var SEARCH_FROM = 4;
7416
7719
  function CaptureCard({ capture, onChanged }) {
7417
- const prompt = (0, import_react36.useSyncExternalStore)(capture.subscribe, capture.get, capture.get);
7720
+ const prompt = (0, import_react37.useSyncExternalStore)(capture.subscribe, capture.get, capture.get);
7418
7721
  const notify = useNotify();
7419
- const [busy, setBusy] = (0, import_react36.useState)(false);
7420
- const [q, setQ] = (0, import_react36.useState)("");
7722
+ const [busy, setBusy] = (0, import_react37.useState)(false);
7723
+ const [q, setQ] = (0, import_react37.useState)("");
7421
7724
  if (!prompt) return null;
7422
7725
  const decide = async (d) => {
7423
7726
  setBusy(true);
@@ -7435,53 +7738,53 @@ function CaptureCard({ capture, onChanged }) {
7435
7738
  const existing = prompt.existing;
7436
7739
  const needle = q.trim().toLocaleLowerCase();
7437
7740
  const shown = needle ? existing.filter((x) => x.name.toLocaleLowerCase().includes(needle)) : existing;
7438
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("section", { "aria-label": "Save this login", className: "flex flex-col gap-2 rounded-xl border border-border bg-card px-3 py-2.5", children: [
7439
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex items-center gap-2.5", children: [
7440
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ShieldGlyph, { className: "size-5 shrink-0 text-primary" }),
7441
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col leading-tight", children: [
7442
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "truncate text-sm font-medium", children: prompt.unavailable ? "Couldn\u2019t hold this login" : "Save this login?" }),
7443
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "truncate text-xs text-muted-foreground", children: prompt.username ? `${prompt.host} \xB7 ${prompt.username}` : prompt.host })
7741
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("section", { "aria-label": "Save this login", className: "flex flex-col gap-2 rounded-xl border border-border bg-card px-3 py-2.5", children: [
7742
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "flex items-center gap-2.5", children: [
7743
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ShieldGlyph, { className: "size-5 shrink-0 text-primary" }),
7744
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col leading-tight", children: [
7745
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "truncate text-sm font-medium", children: prompt.unavailable ? "Couldn\u2019t hold this login" : "Save this login?" }),
7746
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "truncate text-xs text-muted-foreground", children: prompt.username ? `${prompt.host} \xB7 ${prompt.username}` : prompt.host })
7444
7747
  ] }),
7445
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_controls29.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(XGlyph, {}), "aria-label": "Not now", disabled: busy, onClick: () => void decide({ action: "dismiss" }) })
7748
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_controls30.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(XGlyph, {}), "aria-label": "Not now", disabled: busy, onClick: () => void decide({ action: "dismiss" }) })
7446
7749
  ] }),
7447
- prompt.unavailable ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { className: "text-xs text-muted-foreground", children: "Save it by hand with Save a login." }) : /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
7448
- existing.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex flex-col gap-1", children: [
7449
- existing.length >= SEARCH_FROM ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_controls29.SearchField, { value: q, onChange: (e) => setQ(e.target.value), placeholder: "Search logins", "aria-label": "Search logins to update" }) : null,
7450
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("ul", { className: "flex max-h-36 flex-col gap-px overflow-y-auto", children: [
7750
+ prompt.unavailable ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { className: "text-xs text-muted-foreground", children: "Save it by hand with Save a login." }) : /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_jsx_runtime35.Fragment, { children: [
7751
+ existing.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "flex flex-col gap-1", children: [
7752
+ existing.length >= SEARCH_FROM ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_controls30.SearchField, { value: q, onChange: (e) => setQ(e.target.value), placeholder: "Search logins", "aria-label": "Search logins to update" }) : null,
7753
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("ul", { className: "flex max-h-36 flex-col gap-px overflow-y-auto", children: [
7451
7754
  shown.map((x) => {
7452
7755
  const tag = distinguish(x, existing);
7453
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("li", { className: "flex h-9 items-center gap-2 px-1", children: [
7454
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("span", { className: "min-w-0 flex-1 truncate text-sm", children: [
7756
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("li", { className: "flex h-9 items-center gap-2 px-1", children: [
7757
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "min-w-0 flex-1 truncate text-sm", children: [
7455
7758
  x.name,
7456
- tag ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("span", { className: "text-muted-foreground", children: [
7759
+ tag ? /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "text-muted-foreground", children: [
7457
7760
  " \xB7 ",
7458
7761
  tag
7459
7762
  ] }) : null
7460
7763
  ] }),
7461
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_controls29.Button, { variant: "primary", disabled: busy, onClick: () => void decide({ action: "update", itemId: x.itemId }), "aria-label": `Update ${x.name}`, children: "Update" })
7764
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_controls30.Button, { variant: "primary", disabled: busy, onClick: () => void decide({ action: "update", itemId: x.itemId }), "aria-label": `Update ${x.name}`, children: "Update" })
7462
7765
  ] }, x.itemId);
7463
7766
  }),
7464
- shown.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("li", { className: "px-1 py-2 text-xs text-muted-foreground", children: "No saved login matches." }) : null
7767
+ shown.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("li", { className: "px-1 py-2 text-xs text-muted-foreground", children: "No saved login matches." }) : null
7465
7768
  ] })
7466
7769
  ] }) : null,
7467
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
7468
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_controls29.Button, { variant: existing.length > 0 ? "outline" : "primary", disabled: busy, onClick: () => void decide({ action: "save" }), children: existing.length > 0 ? "Save as new" : "Save" }),
7469
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_controls29.Button, { variant: "quiet", disabled: busy, onClick: () => void decide({ action: "never" }), children: "Never here" })
7770
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
7771
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_controls30.Button, { variant: existing.length > 0 ? "outline" : "primary", disabled: busy, onClick: () => void decide({ action: "save" }), children: existing.length > 0 ? "Save as new" : "Save" }),
7772
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_controls30.Button, { variant: "quiet", disabled: busy, onClick: () => void decide({ action: "never" }), children: "Never here" })
7470
7773
  ] })
7471
7774
  ] })
7472
7775
  ] });
7473
7776
  }
7474
7777
 
7475
7778
  // src/extension/FillSetupCard.tsx
7476
- var import_react37 = require("react");
7477
- var import_controls30 = require("@ai-matrx/design-system/controls");
7478
- var import_jsx_runtime35 = require("react/jsx-runtime");
7779
+ var import_react38 = require("react");
7780
+ var import_controls31 = require("@ai-matrx/design-system/controls");
7781
+ var import_jsx_runtime36 = require("react/jsx-runtime");
7479
7782
  function FillSetupCard({ fillSetup }) {
7480
7783
  const notify = useNotify();
7481
- const state = (0, import_react37.useSyncExternalStore)(fillSetup.subscribe, fillSetup.get, fillSetup.get);
7482
- const box = (0, import_react37.useRef)(null);
7483
- const [busy, setBusy] = (0, import_react37.useState)(false);
7484
- const [error, setError] = (0, import_react37.useState)(null);
7784
+ const state = (0, import_react38.useSyncExternalStore)(fillSetup.subscribe, fillSetup.get, fillSetup.get);
7785
+ const box = (0, import_react38.useRef)(null);
7786
+ const [busy, setBusy] = (0, import_react38.useState)(false);
7787
+ const [error, setError] = (0, import_react38.useState)(null);
7485
7788
  if (state.status !== "off") return null;
7486
7789
  const finish = async (run) => {
7487
7790
  setBusy(true);
@@ -7507,15 +7810,15 @@ function FillSetupCard({ fillSetup }) {
7507
7810
  const neither = m !== null && !m.password && !m.passkey;
7508
7811
  const showPassword = !neither && (m === null || m.password);
7509
7812
  const showPasskey = state.passkey !== null && (neither || m === null || m.passkey);
7510
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("section", { "aria-label": "Turn on filling", "data-testid": "fill-setup", className: "flex flex-col gap-2 rounded-xl border border-border bg-card px-3 py-2.5", children: [
7511
- /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "flex items-center gap-2.5", children: [
7512
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(KeyGlyph, { className: "size-5 shrink-0 text-primary" }),
7513
- /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col leading-tight", children: [
7514
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "truncate text-sm font-medium", children: "Turn on filling" }),
7515
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "truncate text-xs text-muted-foreground", children: neither ? "Add a passkey on the web first." : "Confirm it\u2019s you once in this browser." })
7813
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("section", { "aria-label": "Turn on filling", "data-testid": "fill-setup", className: "flex flex-col gap-2 rounded-xl border border-border bg-card px-3 py-2.5", children: [
7814
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex items-center gap-2.5", children: [
7815
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(KeyGlyph, { className: "size-5 shrink-0 text-primary" }),
7816
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col leading-tight", children: [
7817
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "truncate text-sm font-medium", children: "Turn on filling" }),
7818
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "truncate text-xs text-muted-foreground", children: neither ? "Add a passkey on the web first." : "Confirm it\u2019s you once in this browser." })
7516
7819
  ] })
7517
7820
  ] }),
7518
- showPassword ? /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
7821
+ showPassword ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
7519
7822
  "form",
7520
7823
  {
7521
7824
  className: "flex items-center gap-2",
@@ -7524,42 +7827,42 @@ function FillSetupCard({ fillSetup }) {
7524
7827
  withPassword();
7525
7828
  },
7526
7829
  children: [
7527
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_controls30.Field, { ref: box, className: "min-w-0 flex-1", type: "password", autoComplete: "current-password", placeholder: "AI Matrx password", "aria-label": "Your AI Matrx password", disabled: busy }),
7528
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_controls30.Button, { variant: "primary", type: "submit", disabled: busy, children: "Turn on" })
7830
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_controls31.Field, { ref: box, className: "min-w-0 flex-1", type: "password", autoComplete: "current-password", placeholder: "AI Matrx password", "aria-label": "Your AI Matrx password", disabled: busy }),
7831
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_controls31.Button, { variant: "primary", type: "submit", disabled: busy, children: "Turn on" })
7529
7832
  ]
7530
7833
  }
7531
7834
  ) : null,
7532
- showPasskey ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_controls30.Button, { variant: "outline", iconEnd: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ExternalGlyph, {}), disabled: busy, onClick: () => {
7835
+ showPasskey ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_controls31.Button, { variant: "outline", iconEnd: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ExternalGlyph, {}), disabled: busy, onClick: () => {
7533
7836
  setError(null);
7534
7837
  fillSetup.openPasskey();
7535
7838
  }, children: neither ? "Add a passkey" : "Use a passkey" }) : null,
7536
- showPasskey && state.awaitingPasskey && state.passkey ? /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "flex items-center gap-2", "data-testid": "fill-setup-waiting", children: [
7537
- /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "min-w-0 flex-1 text-xs text-muted-foreground", children: [
7839
+ showPasskey && state.awaitingPasskey && state.passkey ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex items-center gap-2", "data-testid": "fill-setup-waiting", children: [
7840
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { className: "min-w-0 flex-1 text-xs text-muted-foreground", children: [
7538
7841
  "Approve code ",
7539
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "font-mono text-foreground", children: state.passkey.code }),
7842
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "font-mono text-foreground", children: state.passkey.code }),
7540
7843
  " on that page."
7541
7844
  ] }),
7542
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_controls30.Button, { variant: "primary", disabled: busy, onClick: () => void finish(() => fillSetup.finishPasskey()), children: "I approved" })
7845
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_controls31.Button, { variant: "primary", disabled: busy, onClick: () => void finish(() => fillSetup.finishPasskey()), children: "I approved" })
7543
7846
  ] }) : null,
7544
- error ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { role: "alert", className: "text-xs text-destructive", children: error }) : null
7847
+ error ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { role: "alert", className: "text-xs text-destructive", children: error }) : null
7545
7848
  ] });
7546
7849
  }
7547
7850
 
7548
7851
  // src/extension/PageGenerator.tsx
7549
- var import_react38 = require("react");
7550
- var import_design_system22 = require("@ai-matrx/design-system");
7551
- var import_controls31 = require("@ai-matrx/design-system/controls");
7552
- var import_icons13 = require("@ai-matrx/design-system/icons");
7553
- var import_jsx_runtime36 = require("react/jsx-runtime");
7852
+ var import_react39 = require("react");
7853
+ var import_design_system23 = require("@ai-matrx/design-system");
7854
+ var import_controls32 = require("@ai-matrx/design-system/controls");
7855
+ var import_icons14 = require("@ai-matrx/design-system/icons");
7856
+ var import_jsx_runtime37 = require("react/jsx-runtime");
7554
7857
  var HOLD_MS = 6e4;
7555
7858
  function PageGenerator({ fields }) {
7556
7859
  const limits = useGeneratorLimitsSource();
7557
7860
  const copy = useCopy();
7558
7861
  const held = useTransientSecret(HOLD_MS);
7559
- const [open, setOpen] = (0, import_react38.useState)(false);
7560
- const [busy, setBusy] = (0, import_react38.useState)(false);
7561
- const [targets, setTargets] = (0, import_react38.useState)([]);
7562
- const [said, setSaid] = (0, import_react38.useState)(null);
7862
+ const [open, setOpen] = (0, import_react39.useState)(false);
7863
+ const [busy, setBusy] = (0, import_react39.useState)(false);
7864
+ const [targets, setTargets] = (0, import_react39.useState)([]);
7865
+ const [said, setSaid] = (0, import_react39.useState)(null);
7563
7866
  if (!limits) return null;
7564
7867
  const say3 = setSaid;
7565
7868
  const put = async (targetId, value2) => {
@@ -7601,30 +7904,30 @@ function PageGenerator({ fields }) {
7601
7904
  }
7602
7905
  };
7603
7906
  const value = held.value;
7604
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
7605
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7907
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_jsx_runtime37.Fragment, { children: [
7908
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
7606
7909
  VaultRow,
7607
7910
  {
7608
7911
  label: "New password",
7609
- actions: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
7610
- 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,
7611
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_design_system22.Popover, { open, onOpenChange: setOpen, children: [
7612
- /* @__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" }) }),
7613
- /* @__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 })
7912
+ actions: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_jsx_runtime37.Fragment, { children: [
7913
+ value ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_controls32.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_icons14.CopyIcon, {}), "aria-label": "Copy password", onClick: () => void copy(value, "Password") }) : null,
7914
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_design_system23.Popover, { open, onOpenChange: setOpen, children: [
7915
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_design_system23.PopoverTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_controls32.Button, { variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(KeyGlyph, {}), disabled: busy, children: "Generate" }) }),
7916
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_design_system23.PopoverContent, { sizing: "content", align: "end", children: open ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(PasswordGenerator, { limits, useLabel: "Fill page", onUse: (v) => void onUse(v) }) : null })
7614
7917
  ] })
7615
7918
  ] }),
7616
- 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" })
7919
+ children: said ? /* @__PURE__ */ (0, import_jsx_runtime37.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_runtime37.jsx)("span", { className: "text-xs text-muted-foreground", children: "Choose the boxes to fill." }) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "text-xs text-disabled-foreground", children: "Fills the page\u2019s new-password box" })
7617
7920
  }
7618
7921
  ),
7619
- 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
7922
+ value && targets.length > 0 ? targets.map((t) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(VaultRow, { label: t.topFrame ? "This page" : "In a frame", actions: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_controls32.Button, { variant: "primary", icon: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(CheckGlyph, {}), disabled: busy, onClick: () => void put(t.id, value), children: "Fill" }), children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "block truncate text-sm", children: targetLabel(t) }) }, t.id)) : null
7620
7923
  ] });
7621
7924
  }
7622
7925
 
7623
7926
  // src/extension/PageView.tsx
7624
- var import_jsx_runtime37 = require("react/jsx-runtime");
7927
+ var import_jsx_runtime38 = require("react/jsx-runtime");
7625
7928
  function PageView({ port, page, fill, capture, fillSetup, newPasswordFields, items, definitions, onOpen, onNewForPage, onBrowse, onChanged, header }) {
7626
- const [running, setRunning] = (0, import_react39.useState)(null);
7627
- const [said, setSaid] = (0, import_react39.useState)(null);
7929
+ const [running, setRunning] = (0, import_react40.useState)(null);
7930
+ const [said, setSaid] = (0, import_react40.useState)(null);
7628
7931
  const site = pageSite(page.url);
7629
7932
  const state = page.matchState ?? { status: "ready" };
7630
7933
  const fillable = new Set(page.fillableItemIds ?? page.matchingItemIds);
@@ -7645,20 +7948,20 @@ function PageView({ port, page, fill, capture, fillSetup, newPasswordFields, ite
7645
7948
  }
7646
7949
  };
7647
7950
  let body;
7648
- if (!page.url) body = /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Empty, { children: "No page is open in this tab." });
7951
+ if (!page.url) body = /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Empty, { children: "No page is open in this tab." });
7649
7952
  else if (state.status === "error") {
7650
- body = /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex items-center gap-2 px-3 py-2 sm:px-4", children: [
7651
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { role: "alert", className: "min-w-0 flex-1 text-sm text-muted-foreground", children: MATCH_ERROR_WORDS[state.reason] }),
7652
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_controls32.Button, { variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(RefreshGlyph, {}), onClick: state.retry, children: "Retry" })
7953
+ body = /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex items-center gap-2 px-3 py-2 sm:px-4", children: [
7954
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { role: "alert", className: "min-w-0 flex-1 text-sm text-muted-foreground", children: MATCH_ERROR_WORDS[state.reason] }),
7955
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_controls33.Button, { variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(RefreshGlyph, {}), onClick: state.retry, children: "Retry" })
7653
7956
  ] });
7654
7957
  } else if (state.status === "loading") {
7655
- body = /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { "aria-busy": "true", "aria-label": "Checking saved logins", className: "flex flex-col", children: [0, 1].map((n) => /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex h-12 items-center gap-3 px-3", children: [
7656
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "size-8 animate-pulse rounded-lg bg-muted" }),
7657
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "h-3 w-1/2 animate-pulse rounded bg-muted" })
7958
+ body = /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { "aria-busy": "true", "aria-label": "Checking saved logins", className: "flex flex-col", children: [0, 1].map((n) => /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex h-12 items-center gap-3 px-3", children: [
7959
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "size-8 animate-pulse rounded-lg bg-muted" }),
7960
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "h-3 w-1/2 animate-pulse rounded bg-muted" })
7658
7961
  ] }, n)) });
7659
- } else if (matches.length === 0) body = /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(Empty, { children: "No saved login for this site." });
7962
+ } else if (matches.length === 0) body = /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Empty, { children: "No saved login for this site." });
7660
7963
  else {
7661
- body = /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("ul", { className: "flex flex-col", children: matches.map(({ itemId, item }) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
7964
+ body = /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("ul", { className: "flex flex-col", children: matches.map(({ itemId, item }) => /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
7662
7965
  MatchRow,
7663
7966
  {
7664
7967
  itemId,
@@ -7675,40 +7978,40 @@ function PageView({ port, page, fill, capture, fillSetup, newPasswordFields, ite
7675
7978
  itemId
7676
7979
  )) });
7677
7980
  }
7678
- 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: [
7981
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "flex h-full min-h-0 flex-col overflow-y-auto bg-background text-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex flex-col gap-3 px-3 pb-4 pt-3", children: [
7679
7982
  header,
7680
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex min-h-7 items-center gap-2 px-1", children: [
7681
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_design_system23.SiteIcon, { site: page.url, fallback: import_icons14.GlobeIcon, className: "size-4" }),
7682
- /* @__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" }),
7683
- 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,
7684
- 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
7983
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex min-h-7 items-center gap-2 px-1", children: [
7984
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_design_system24.SiteIcon, { site: page.url, fallback: import_icons15.GlobeIcon, className: "size-4" }),
7985
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm font-medium", title: page.url, children: site || "No page open" }),
7986
+ page.refresh ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_controls33.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(RefreshGlyph, {}), "aria-label": "Check again", onClick: page.refresh }) : null,
7987
+ onBrowse ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_controls33.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ListGlyph, {}), onClick: onBrowse, children: "All items" }) : null
7685
7988
  ] }),
7686
- fillSetup ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(FillSetupCard, { fillSetup }) : null,
7687
- capture ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(CaptureCard, { capture, onChanged }) : null,
7688
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
7989
+ fillSetup ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(FillSetupCard, { fillSetup }) : null,
7990
+ capture ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(CaptureCard, { capture, onChanged }) : null,
7991
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
7689
7992
  VaultSection,
7690
7993
  {
7691
7994
  title: "This site",
7692
- 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,
7995
+ actions: canSave ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_controls33.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(PlusGlyph, {}), onClick: () => onNewForPage(normalizeLoginUrl2(page.url) ?? page.url), children: "Save a login" }) : null,
7693
7996
  children: body
7694
7997
  }
7695
7998
  ),
7696
- 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,
7697
- newPasswordFields && canSave ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(VaultSection, { children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(PageGenerator, { fields: newPasswordFields }) }) : null
7999
+ said ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Outcome, { said, onDismiss: () => setSaid(null) }) : page.blocked && page.url && state.status === "ready" ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { className: "px-1 text-xs text-muted-foreground", children: BLOCK_WORDS[page.blocked] }) : null,
8000
+ newPasswordFields && canSave ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(VaultSection, { children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(PageGenerator, { fields: newPasswordFields }) }) : null
7698
8001
  ] }) });
7699
8002
  }
7700
8003
  function Outcome({ said, onDismiss }) {
7701
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { role: "status", className: "flex items-center gap-2 px-1", children: [
7702
- said.tone === "success" ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(CheckGlyph, { className: "size-4 shrink-0 text-primary" }) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ShieldGlyph, { className: "size-4 shrink-0 text-destructive" }),
7703
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "min-w-0 flex-1 text-xs text-foreground", children: said.text }),
7704
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_controls32.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(XGlyph, {}), "aria-label": "Dismiss", onClick: onDismiss })
8004
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { role: "status", className: "flex items-center gap-2 px-1", children: [
8005
+ said.tone === "success" ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(CheckGlyph, { className: "size-4 shrink-0 text-primary" }) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ShieldGlyph, { className: "size-4 shrink-0 text-destructive" }),
8006
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "min-w-0 flex-1 text-xs text-foreground", children: said.text }),
8007
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_controls33.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(XGlyph, {}), "aria-label": "Dismiss", onClick: onDismiss })
7705
8008
  ] });
7706
8009
  }
7707
8010
  function MatchRow({ itemId, item, tag, family, port, busy, running, onOpen, onFill, onSignIn }) {
7708
8011
  const confirmed = useConfirmed();
7709
8012
  const copy = useCopy();
7710
8013
  const notify = useNotify();
7711
- const [reading, setReading] = (0, import_react39.useState)(false);
8014
+ const [reading, setReading] = (0, import_react40.useState)(false);
7712
8015
  const usable = item?.capabilities.canUse ?? false;
7713
8016
  const user = usable ? item?.fields.find((f) => USERNAME_KEYS.test(f.key) && f.handling !== "sealed" && f.active) : void 0;
7714
8017
  const secret = usable && item?.capabilities.canReveal ? item?.fields.find((f) => f.key === "password" && f.handling === "revealable" && f.active) : void 0;
@@ -7724,27 +8027,27 @@ function MatchRow({ itemId, item, tag, family, port, busy, running, onOpen, onFi
7724
8027
  }
7725
8028
  };
7726
8029
  const subtitle = [item ? loginSiteOf(item) || item.definitionLabel : "", tag].filter(Boolean).join(" \xB7 ");
7727
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("li", { className: "flex h-12 items-center gap-1 pl-1 pr-2", "data-item": itemId, children: [
7728
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("button", { type: "button", onClick: () => onOpen(itemId), className: "flex h-11 min-w-0 flex-1 items-center gap-3 rounded-lg px-2 text-left hover:bg-accent", children: [
7729
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ItemIcon, { definitionKey: item?.definitionKey ?? "website_login", family, site: item ? loginSiteOf(item) : "" }),
7730
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { className: "flex min-w-0 flex-1 flex-col leading-tight", children: [
7731
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "truncate text-sm font-medium", children: item?.name ?? "Saved login" }),
7732
- subtitle ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "truncate text-xs text-muted-foreground", children: subtitle }) : null
8030
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("li", { className: "flex h-12 items-center gap-1 pl-1 pr-2", "data-item": itemId, children: [
8031
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("button", { type: "button", onClick: () => onOpen(itemId), className: "flex h-11 min-w-0 flex-1 items-center gap-3 rounded-lg px-2 text-left hover:bg-accent", children: [
8032
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ItemIcon, { definitionKey: item?.definitionKey ?? "website_login", family, site: item ? loginSiteOf(item) : "" }),
8033
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("span", { className: "flex min-w-0 flex-1 flex-col leading-tight", children: [
8034
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "truncate text-sm font-medium", children: item?.name ?? "Saved login" }),
8035
+ subtitle ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "truncate text-xs text-muted-foreground", children: subtitle }) : null
7733
8036
  ] })
7734
8037
  ] }),
7735
- onFill ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_controls32.Button, { variant: "primary", disabled: busy, "aria-busy": running || void 0, onClick: onFill, "aria-label": `Fill ${item?.name ?? "this login"}`, children: running ? "Filling\u2026" : "Fill" }) : null,
7736
- user && item ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_controls32.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(UserGlyph, {}), "aria-label": `Copy ${user.label}`, title: `Copy ${user.label}`, disabled: reading, onClick: () => void read(user.label, () => port.reveal(item, user.key)) }) : null,
7737
- secret && item ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_controls32.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(KeyGlyph, {}), "aria-label": "Copy password", title: "Copy password", disabled: reading, onClick: () => void read("Password", () => port.reveal(item, secret.key)) }) : null,
7738
- otp ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_controls32.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ClockGlyph, {}), "aria-label": "Copy one-time code", title: "Copy one-time code", disabled: reading, onClick: () => void read("One-time code", async () => (await port.authenticator.code(otp)).code) }) : null,
7739
- onSignIn ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_design_system23.DropdownMenu, { children: [
7740
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_design_system23.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_controls32.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(MoreGlyph, {}), "aria-label": "More", disabled: busy }) }),
7741
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_design_system23.DropdownMenuContent, { align: "end", children: [
7742
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_design_system23.DropdownMenuItem, { onSelect: onSignIn, children: [
7743
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ShieldGlyph, { className: "size-4" }),
8038
+ onFill ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_controls33.Button, { variant: "primary", disabled: busy, "aria-busy": running || void 0, onClick: onFill, "aria-label": `Fill ${item?.name ?? "this login"}`, children: running ? "Filling\u2026" : "Fill" }) : null,
8039
+ user && item ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_controls33.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(UserGlyph, {}), "aria-label": `Copy ${user.label}`, title: `Copy ${user.label}`, disabled: reading, onClick: () => void read(user.label, () => port.reveal(item, user.key)) }) : null,
8040
+ secret && item ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_controls33.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(KeyGlyph, {}), "aria-label": "Copy password", title: "Copy password", disabled: reading, onClick: () => void read("Password", () => port.reveal(item, secret.key)) }) : null,
8041
+ otp ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_controls33.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ClockGlyph, {}), "aria-label": "Copy one-time code", title: "Copy one-time code", disabled: reading, onClick: () => void read("One-time code", async () => (await port.authenticator.code(otp)).code) }) : null,
8042
+ onSignIn ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_design_system24.DropdownMenu, { children: [
8043
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_design_system24.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_controls33.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(MoreGlyph, {}), "aria-label": "More", disabled: busy }) }),
8044
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_design_system24.DropdownMenuContent, { align: "end", children: [
8045
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_design_system24.DropdownMenuItem, { onSelect: onSignIn, children: [
8046
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ShieldGlyph, { className: "size-4" }),
7744
8047
  "Sign me in"
7745
8048
  ] }),
7746
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_design_system23.DropdownMenuItem, { onSelect: () => onOpen(itemId), children: [
7747
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ListGlyph, { className: "size-4" }),
8049
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_design_system24.DropdownMenuItem, { onSelect: () => onOpen(itemId), children: [
8050
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ListGlyph, { className: "size-4" }),
7748
8051
  "Open item"
7749
8052
  ] })
7750
8053
  ] })
@@ -7753,11 +8056,11 @@ function MatchRow({ itemId, item, tag, family, port, busy, running, onOpen, onFi
7753
8056
  }
7754
8057
 
7755
8058
  // src/Sidebar.tsx
7756
- var import_react40 = require("react");
7757
- var import_design_system24 = require("@ai-matrx/design-system");
7758
- var import_controls33 = require("@ai-matrx/design-system/controls");
7759
- var import_icons15 = require("@ai-matrx/design-system/icons");
7760
- var import_jsx_runtime38 = require("react/jsx-runtime");
8059
+ var import_react41 = require("react");
8060
+ var import_design_system25 = require("@ai-matrx/design-system");
8061
+ var import_controls34 = require("@ai-matrx/design-system/controls");
8062
+ var import_icons16 = require("@ai-matrx/design-system/icons");
8063
+ var import_jsx_runtime39 = require("react/jsx-runtime");
7761
8064
  var AUTHENTICATOR_LABEL = "Authenticator";
7762
8065
  function vaultChoices(items, organizations, current) {
7763
8066
  const n = (f) => items.filter(f).length;
@@ -7771,9 +8074,9 @@ function vaultChoices(items, organizations, current) {
7771
8074
  ];
7772
8075
  }
7773
8076
  function VaultSelect({ value, choices, onChange }) {
7774
- 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) })) });
8077
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_controls34.Select, { value, onValueChange: onChange, "aria-label": "Vault", options: choices.map((c) => ({ value: c.value, label: c.label, meta: String(c.count) })) });
7775
8078
  }
7776
- var CATEGORY_GLYPHS = { logins: import_icons15.GlobeIcon, passkeys: ShieldGlyph, api: KeyGlyph, oauth: PlugGlyph, infra: DatabaseGlyph, env: TerminalGlyph, files: FileGlyph, other: NoteGlyph };
8079
+ var CATEGORY_GLYPHS = { logins: import_icons16.GlobeIcon, passkeys: ShieldGlyph, api: KeyGlyph, oauth: PlugGlyph, infra: DatabaseGlyph, env: TerminalGlyph, files: FileGlyph, other: NoteGlyph };
7777
8080
  var familyOf = (key, definitions) => definitions.find((d) => d.key === key)?.family ?? "generic";
7778
8081
  function itemCategory(item, definitions) {
7779
8082
  return categoryOf(item.definitionKey, familyOf(item.definitionKey, definitions));
@@ -7816,71 +8119,71 @@ function viewOptions(views, allCount, deletedCount, hasFavorites, hasRecents, ha
7816
8119
  ];
7817
8120
  }
7818
8121
  function Entry({ on, glyph: Icon, label, count: count2, onClick }) {
7819
- const desktop = (0, import_design_system24.useLook)() === "desktop";
7820
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
8122
+ const desktop = (0, import_design_system25.useLook)() === "desktop";
8123
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
7821
8124
  "button",
7822
8125
  {
7823
8126
  type: "button",
7824
8127
  "aria-current": on ? "page" : void 0,
7825
8128
  onClick,
7826
- 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"),
8129
+ className: (0, import_design_system25.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"),
7827
8130
  children: [
7828
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Icon, { className: "size-4 shrink-0" }),
7829
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "min-w-0 flex-1 truncate", children: label }),
7830
- count2 !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "text-xs tabular-nums text-muted-foreground", children: count2 }) : null
8131
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Icon, { className: "size-4 shrink-0" }),
8132
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "min-w-0 flex-1 truncate", children: label }),
8133
+ count2 !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "text-xs tabular-nums text-muted-foreground", children: count2 }) : null
7831
8134
  ]
7832
8135
  }
7833
8136
  );
7834
8137
  }
7835
8138
  function Group({ title, children }) {
7836
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex flex-col gap-0.5", children: [
7837
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "px-2.5 pb-1 text-xs font-medium text-muted-foreground", children: title }),
8139
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-col gap-0.5", children: [
8140
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "px-2.5 pb-1 text-xs font-medium text-muted-foreground", children: title }),
7838
8141
  children
7839
8142
  ] });
7840
8143
  }
7841
8144
  function VaultSidebar({ vault, choices, onVault, view, allCount, deletedCount, views, hasFavorites, hasRecents, onView, onPanel, nativeProvider, hasNativeImport = false, hasPage = false }) {
7842
- const [tagsOpen, setTagsOpen] = (0, import_react40.useState)(view.startsWith("tag:"));
7843
- 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: [
7844
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex items-center gap-2 px-3 pb-2 pt-3", children: [
7845
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(SafeGlyph, { className: "size-5 shrink-0 text-primary" }),
7846
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(VaultSelect, { value: vault, choices, onChange: onVault }) })
8145
+ const [tagsOpen, setTagsOpen] = (0, import_react41.useState)(view.startsWith("tag:"));
8146
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("nav", { "aria-label": "Vault", className: "flex h-full min-h-0 flex-col border-r border-sidebar-border bg-sidebar-background text-sidebar-foreground", children: [
8147
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex items-center gap-2 px-3 pb-2 pt-3", children: [
8148
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(SafeGlyph, { className: "size-5 shrink-0 text-primary" }),
8149
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(VaultSelect, { value: vault, choices, onChange: onVault }) })
7847
8150
  ] }),
7848
- /* @__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: [
7849
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex flex-col gap-0.5", children: [
7850
- hasPage ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Entry, { on: view === "page", glyph: import_icons15.GlobeIcon, label: "This page", onClick: () => onView("page") }) : null,
7851
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Entry, { on: view === "all", glyph: GridGlyph, label: "All items", count: allCount, onClick: () => onView("all") }),
7852
- hasFavorites ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Entry, { on: view === "favorites", glyph: StarGlyph, label: "Favorites", count: views.favorites, onClick: () => onView("favorites") }) : null,
7853
- hasRecents ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Entry, { on: view === "recent", glyph: ClockGlyph, label: "Recently opened", count: views.recent, onClick: () => onView("recent") }) : null,
7854
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Entry, { on: view === "authenticator", glyph: LockGlyph, label: AUTHENTICATOR_LABEL, count: views.authenticator, onClick: () => onView("authenticator") })
8151
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex min-h-0 flex-1 flex-col gap-5 overflow-y-auto px-2 pb-3 pt-1", children: [
8152
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-col gap-0.5", children: [
8153
+ hasPage ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Entry, { on: view === "page", glyph: import_icons16.GlobeIcon, label: "This page", onClick: () => onView("page") }) : null,
8154
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Entry, { on: view === "all", glyph: GridGlyph, label: "All items", count: allCount, onClick: () => onView("all") }),
8155
+ hasFavorites ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Entry, { on: view === "favorites", glyph: StarGlyph, label: "Favorites", count: views.favorites, onClick: () => onView("favorites") }) : null,
8156
+ hasRecents ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Entry, { on: view === "recent", glyph: ClockGlyph, label: "Recently opened", count: views.recent, onClick: () => onView("recent") }) : null,
8157
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Entry, { on: view === "authenticator", glyph: LockGlyph, label: AUTHENTICATOR_LABEL, count: views.authenticator, onClick: () => onView("authenticator") })
7855
8158
  ] }),
7856
- views.categories.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Group, { title: "Categories", children: views.categories.map((e) => /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Entry, { on: view === e.view, glyph: e.glyph, label: e.label, count: e.count, onClick: () => onView(e.view) }, e.view)) }) : null,
7857
- views.tags.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex flex-col gap-0.5", children: [
7858
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("button", { type: "button", "aria-expanded": tagsOpen, onClick: () => setTagsOpen((o) => !o), className: "flex h-7 items-center gap-1 rounded-md px-2.5 text-left text-xs font-medium text-muted-foreground hover:text-foreground", children: [
7859
- tagsOpen ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ChevronDownGlyph, { className: "size-3.5" }) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ChevronRightGlyph, { className: "size-3.5" }),
8159
+ views.categories.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Group, { title: "Categories", children: views.categories.map((e) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Entry, { on: view === e.view, glyph: e.glyph, label: e.label, count: e.count, onClick: () => onView(e.view) }, e.view)) }) : null,
8160
+ views.tags.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-col gap-0.5", children: [
8161
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("button", { type: "button", "aria-expanded": tagsOpen, onClick: () => setTagsOpen((o) => !o), className: "flex h-7 items-center gap-1 rounded-md px-2.5 text-left text-xs font-medium text-muted-foreground hover:text-foreground", children: [
8162
+ tagsOpen ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ChevronDownGlyph, { className: "size-3.5" }) : /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ChevronRightGlyph, { className: "size-3.5" }),
7860
8163
  "Tags",
7861
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "ml-auto tabular-nums", children: views.tags.length })
8164
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "ml-auto tabular-nums", children: views.tags.length })
7862
8165
  ] }),
7863
- tagsOpen ? views.tags.map((e) => /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Entry, { on: view === e.view, glyph: e.glyph, label: e.label, count: e.count, onClick: () => onView(e.view) }, e.view)) : null
8166
+ tagsOpen ? views.tags.map((e) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Entry, { on: view === e.view, glyph: e.glyph, label: e.label, count: e.count, onClick: () => onView(e.view) }, e.view)) : null
7864
8167
  ] }) : null
7865
8168
  ] }),
7866
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex flex-col gap-0.5 border-t border-sidebar-border p-2", children: [
7867
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Entry, { on: view === "trash", glyph: TrashGlyph, label: "Trash", count: deletedCount, onClick: () => onView("trash") }),
7868
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Entry, { on: false, glyph: ImportGlyph, label: "Import", onClick: () => onPanel("import") }),
7869
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Entry, { on: false, glyph: ExportGlyph, label: "Export", onClick: () => onPanel("export") }),
7870
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Entry, { on: false, glyph: SafeGlyph, label: "Backup", onClick: () => onPanel("backup") }),
7871
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Entry, { on: false, glyph: ShieldGlyph, label: "Browsers that fill", onClick: () => onPanel("devices") }),
7872
- hasNativeImport ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Entry, { on: false, glyph: ImportGlyph, label: "Import passkeys", onClick: () => onPanel("import-passkeys") }) : null,
7873
- nativeProvider && nativeProvider.status !== "unavailable" ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("button", { type: "button", onClick: nativeProvider.openSetup, className: "flex h-8 w-full items-center gap-2.5 rounded-lg px-2.5 text-left text-sm hover:bg-sidebar-accent", children: [
7874
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ShieldGlyph, { className: "size-4 shrink-0" }),
7875
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "min-w-0 flex-1 truncate", children: "System AutoFill" }),
7876
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: (0, import_design_system24.cn)("text-xs", nativeProvider.status === "ready" ? "text-success" : "text-warning"), children: nativeProvider.status === "ready" ? "On" : "Set up" })
8169
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-col gap-0.5 border-t border-sidebar-border p-2", children: [
8170
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Entry, { on: view === "trash", glyph: TrashGlyph, label: "Trash", count: deletedCount, onClick: () => onView("trash") }),
8171
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Entry, { on: false, glyph: ImportGlyph, label: "Import", onClick: () => onPanel("import") }),
8172
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Entry, { on: false, glyph: ExportGlyph, label: "Export", onClick: () => onPanel("export") }),
8173
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Entry, { on: false, glyph: SafeGlyph, label: "Backup", onClick: () => onPanel("backup") }),
8174
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Entry, { on: false, glyph: ShieldGlyph, label: "Browsers that fill", onClick: () => onPanel("devices") }),
8175
+ hasNativeImport ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Entry, { on: false, glyph: ImportGlyph, label: "Import passkeys", onClick: () => onPanel("import-passkeys") }) : null,
8176
+ nativeProvider && nativeProvider.status !== "unavailable" ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("button", { type: "button", onClick: nativeProvider.openSetup, className: "flex h-8 w-full items-center gap-2.5 rounded-lg px-2.5 text-left text-sm hover:bg-sidebar-accent", children: [
8177
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ShieldGlyph, { className: "size-4 shrink-0" }),
8178
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "min-w-0 flex-1 truncate", children: "System AutoFill" }),
8179
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: (0, import_design_system25.cn)("text-xs", nativeProvider.status === "ready" ? "text-success" : "text-warning"), children: nativeProvider.status === "ready" ? "On" : "Set up" })
7877
8180
  ] }) : null
7878
8181
  ] })
7879
8182
  ] });
7880
8183
  }
7881
8184
 
7882
8185
  // src/VaultApp.tsx
7883
- var import_jsx_runtime39 = require("react/jsx-runtime");
8186
+ var import_jsx_runtime40 = require("react/jsx-runtime");
7884
8187
  var FULL_AT = 1120;
7885
8188
  var SPLIT_AT = 640;
7886
8189
  var NO_HOST = {};
@@ -7899,8 +8202,8 @@ var generatorLimitsFrom = (knobs) => knobs ? async () => {
7899
8202
  } : void 0;
7900
8203
  function ImportWithLimits(props) {
7901
8204
  const { knobs, ...rest } = props;
7902
- const [state, setState] = (0, import_react41.useState)(null);
7903
- (0, import_react41.useEffect)(() => {
8205
+ const [state, setState] = (0, import_react42.useState)(null);
8206
+ (0, import_react42.useEffect)(() => {
7904
8207
  if (!knobs) return setState({ error: "Import is not set up for this organization yet." });
7905
8208
  knobs().then(
7906
8209
  (r) => {
@@ -7913,18 +8216,18 @@ function ImportWithLimits(props) {
7913
8216
  (e) => setState({ error: e instanceof Error ? e.message : "The import settings could not be read." })
7914
8217
  );
7915
8218
  }, [knobs]);
7916
- if (state && "limits" in state) return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ImportPanel, { ...rest, limits: state.limits });
7917
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Panel, { title: "Import", onClose: rest.onClose, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Empty, { children: state ? state.error : "Reading this organization\u2019s import settings\u2026" }) });
8219
+ if (state && "limits" in state) return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ImportPanel, { ...rest, limits: state.limits });
8220
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Panel, { title: "Import", onClose: rest.onClose, children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Empty, { children: state ? state.error : "Reading this organization\u2019s import settings\u2026" }) });
7918
8221
  }
7919
8222
  function VaultApp(props) {
7920
8223
  const lock = props.host?.lock;
7921
8224
  const locked = useLocked(lock);
7922
- const port = (0, import_react41.useMemo)(() => lock ? guardPort(props.port, () => lock.locked()) : props.port, [props.port, lock]);
7923
- 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 }) }) }) }) }) }) }) });
8225
+ const port = (0, import_react42.useMemo)(() => lock ? guardPort(props.port, () => lock.locked()) : props.port, [props.port, lock]);
8226
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system26.LookScope, { look: props.look ?? "web", className: "h-full min-h-0 w-full", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "relative h-full min-h-0 w-full", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(NoticeProvider, { notify: props.notify, children: lock && locked ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(LockedScreen, { lock }) : /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ClipboardProvider, { clipboard: props.host?.clipboard, children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(RevealSecondsProvider, { seconds: props.host?.revealSeconds, children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(IdentityGate, { identity: props.host?.identity, children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(GeneratorLimitsProvider, { resolve: generatorLimitsFrom(props.host?.knobs), children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Workspace, { ...props, port }) }) }) }) }) }) }) });
7924
8227
  }
7925
8228
  function LockedScreen({ lock }) {
7926
- const [busy, setBusy] = (0, import_react41.useState)(false);
7927
- const [error, setError] = (0, import_react41.useState)(null);
8229
+ const [busy, setBusy] = (0, import_react42.useState)(false);
8230
+ const [error, setError] = (0, import_react42.useState)(null);
7928
8231
  const unlock = async () => {
7929
8232
  setBusy(true);
7930
8233
  setError(null);
@@ -7936,37 +8239,37 @@ function LockedScreen({ lock }) {
7936
8239
  setBusy(false);
7937
8240
  }
7938
8241
  };
7939
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { role: "region", "aria-label": "Vault locked", className: "flex h-full min-h-0 flex-col items-center justify-center gap-3 p-6 text-center", children: [
7940
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(LockGlyph, { className: "size-8 text-muted-foreground" }),
7941
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "text-base font-medium text-foreground", children: "Vault locked" }),
7942
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_controls34.Button, { variant: "primary", disabled: busy, onClick: () => void unlock(), children: lock.unlockLabel ?? "Unlock" }),
7943
- error ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { role: "alert", className: "max-w-sm text-sm text-destructive", children: error }) : null
8242
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { role: "region", "aria-label": "Vault locked", className: "flex h-full min-h-0 flex-col items-center justify-center gap-3 p-6 text-center", children: [
8243
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(LockGlyph, { className: "size-8 text-muted-foreground" }),
8244
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "text-base font-medium text-foreground", children: "Vault locked" }),
8245
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_controls35.Button, { variant: "primary", disabled: busy, onClick: () => void unlock(), children: lock.unlockLabel ?? "Unlock" }),
8246
+ error ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { role: "alert", className: "max-w-sm text-sm text-destructive", children: error }) : null
7944
8247
  ] });
7945
8248
  }
7946
- function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocationChange }) {
7947
- const rootRef = (0, import_react41.useRef)(null);
8249
+ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocationChange, onInventory }) {
8250
+ const rootRef = (0, import_react42.useRef)(null);
7948
8251
  const width = useElementWidth(rootRef);
7949
8252
  const mode = layout !== "auto" ? layout : width >= FULL_AT ? "full" : width >= SPLIT_AT ? "split" : "stack";
7950
8253
  const notify = useNotify();
7951
- const [snap, setSnap] = (0, import_react41.useState)(null);
7952
- const [items, setItems] = (0, import_react41.useState)([]);
7953
- const [deleted, setDeleted] = (0, import_react41.useState)([]);
7954
- const [favorites, setFavorites] = (0, import_react41.useState)(null);
7955
- const [recents, setRecents] = (0, import_react41.useState)(null);
7956
- const [error, setError] = (0, import_react41.useState)(null);
7957
- const [inner, setInner] = (0, import_react41.useState)(DEFAULT_LOCATION);
8254
+ const [snap, setSnap] = (0, import_react42.useState)(null);
8255
+ const [items, setItems] = (0, import_react42.useState)([]);
8256
+ const [deleted, setDeleted] = (0, import_react42.useState)([]);
8257
+ const [favorites, setFavorites] = (0, import_react42.useState)(null);
8258
+ const [recents, setRecents] = (0, import_react42.useState)(null);
8259
+ const [error, setError] = (0, import_react42.useState)(null);
8260
+ const [inner, setInner] = (0, import_react42.useState)(DEFAULT_LOCATION);
7958
8261
  const loc = location ?? inner;
7959
- const dirty = (0, import_react41.useRef)(false);
7960
- const [notice, setNotice] = (0, import_react41.useState)(null);
7961
- const [firstCode, setFirstCode] = (0, import_react41.useState)(null);
7962
- const move = (0, import_react41.useCallback)(
8262
+ const dirty = (0, import_react42.useRef)(false);
8263
+ const [notice, setNotice] = (0, import_react42.useState)(null);
8264
+ const [firstCode, setFirstCode] = (0, import_react42.useState)(null);
8265
+ const move = (0, import_react42.useCallback)(
7963
8266
  (next, how) => {
7964
8267
  if (!location) setInner(next);
7965
8268
  onLocationChange?.(next, how);
7966
8269
  },
7967
8270
  [location, onLocationChange]
7968
8271
  );
7969
- const go = (0, import_react41.useCallback)(
8272
+ const go = (0, import_react42.useCallback)(
7970
8273
  (patch, how = "push") => {
7971
8274
  const leaving = patch.itemId !== void 0 || patch.mode !== void 0 || patch.vault !== void 0 || patch.view !== void 0;
7972
8275
  const next = { ...loc, ...patch };
@@ -7978,16 +8281,16 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
7978
8281
  move(next, how);
7979
8282
  };
7980
8283
  if (leaving && dirty.current) {
7981
- void (0, import_confirm_opener13.confirm)({ title: "Discard your changes?", description: "What you changed in this item is not saved.", confirmLabel: "Discard", cancelLabel: "Keep editing", variant: "destructive" }).then((ok) => ok && proceed());
8284
+ void (0, import_confirm_opener14.confirm)({ title: "Discard your changes?", description: "What you changed in this item is not saved.", confirmLabel: "Discard", cancelLabel: "Keep editing", variant: "destructive" }).then((ok) => ok && proceed());
7982
8285
  return;
7983
8286
  }
7984
8287
  proceed();
7985
8288
  },
7986
8289
  [loc, move]
7987
8290
  );
7988
- const keyState = (0, import_react41.useRef)({ loc, go });
8291
+ const keyState = (0, import_react42.useRef)({ loc, go });
7989
8292
  keyState.current = { loc, go };
7990
- (0, import_react41.useEffect)(() => {
8293
+ (0, import_react42.useEffect)(() => {
7991
8294
  const onKey = (e) => {
7992
8295
  if (e.defaultPrevented || e.metaKey || e.ctrlKey || e.altKey) return;
7993
8296
  const root = rootRef.current;
@@ -8009,10 +8312,10 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
8009
8312
  document.addEventListener("keydown", onKey);
8010
8313
  return () => document.removeEventListener("keydown", onKey);
8011
8314
  }, []);
8012
- const knobsRef = (0, import_react41.useRef)(host.knobs);
8315
+ const knobsRef = (0, import_react42.useRef)(host.knobs);
8013
8316
  knobsRef.current = host.knobs;
8014
- const [signedOut, setSignedOut] = (0, import_react41.useState)(false);
8015
- const load = (0, import_react41.useCallback)(() => {
8317
+ const [signedOut, setSignedOut] = (0, import_react42.useState)(false);
8318
+ const load = (0, import_react42.useCallback)(() => {
8016
8319
  setError(null);
8017
8320
  port.load().then((s) => {
8018
8321
  setSnap(s);
@@ -8030,18 +8333,23 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
8030
8333
  knobsRef.current?.().catch(() => void 0);
8031
8334
  port.lists.recents?.list().then(setRecents, () => void 0);
8032
8335
  }, [port]);
8033
- (0, import_react41.useEffect)(load, [load]);
8034
- (0, import_react41.useEffect)(() => {
8336
+ (0, import_react42.useEffect)(load, [load]);
8337
+ const inventoryRef = (0, import_react42.useRef)(onInventory);
8338
+ inventoryRef.current = onInventory;
8339
+ (0, import_react42.useEffect)(() => {
8340
+ if (snap) inventoryRef.current?.({ items, definitions: snap.definitions });
8341
+ }, [snap, items]);
8342
+ (0, import_react42.useEffect)(() => {
8035
8343
  if (!loc.itemId || !port.lists.recents) return;
8036
8344
  const id = loc.itemId;
8037
8345
  port.lists.recents.record(id).then(() => setRecents((r) => [id, ...(r ?? []).filter((x) => x !== id)]), () => void 0);
8038
8346
  }, [loc.itemId, port]);
8039
8347
  const orgs = snap?.organizations ?? [];
8040
8348
  const definitions = snap?.definitions ?? [];
8041
- const inThisVault = (0, import_react41.useMemo)(() => items.filter((i) => inVault(i, loc.vault)), [items, loc.vault]);
8349
+ const inThisVault = (0, import_react42.useMemo)(() => items.filter((i) => inVault(i, loc.vault)), [items, loc.vault]);
8042
8350
  const vaultMixesOwners = new Set(inThisVault.map((i) => i.owner.organizationId ?? i.owner.kind)).size > 1;
8043
- const views = (0, import_react41.useMemo)(() => buildViews(inThisVault, definitions, favorites, recents), [inThisVault, definitions, favorites, recents]);
8044
- const visible = (0, import_react41.useMemo)(() => {
8351
+ const views = (0, import_react42.useMemo)(() => buildViews(inThisVault, definitions, favorites, recents), [inThisVault, definitions, favorites, recents]);
8352
+ const visible = (0, import_react42.useMemo)(() => {
8045
8353
  const filtered = inThisVault.filter((i) => {
8046
8354
  if (!matchesQuery(i, loc.q)) return false;
8047
8355
  if (loc.view === "favorites") return favorites?.has(i.id) ?? false;
@@ -8050,10 +8358,10 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
8050
8358
  return inView(i, loc.view);
8051
8359
  });
8052
8360
  if (loc.view === "recent" && recents) return [...filtered].sort((a, b) => recents.indexOf(a.id) - recents.indexOf(b.id));
8053
- return sortItems(filtered, loc.sort);
8361
+ return sortItems(filtered, loc.sort, recents);
8054
8362
  }, [inThisVault, loc.view, loc.q, loc.sort, favorites, recents, definitions]);
8055
- const choices = (0, import_react41.useMemo)(() => vaultChoices(items, orgs, loc.vault), [items, orgs, loc.vault]);
8056
- const matchingIds = (0, import_react41.useMemo)(() => host.page ? new Set(host.page.matchingItemIds) : void 0, [host.page]);
8363
+ const choices = (0, import_react42.useMemo)(() => vaultChoices(items, orgs, loc.vault), [items, orgs, loc.vault]);
8364
+ const matchingIds = (0, import_react42.useMemo)(() => host.page ? new Set(host.page.matchingItemIds) : void 0, [host.page]);
8057
8365
  const selected = loc.itemId ? items.find((i) => i.id === loc.itemId) ?? null : null;
8058
8366
  const replaceItem = (next) => setItems((cur) => cur.some((i) => i.id === next.id) ? cur.map((i) => i.id === next.id ? next : i) : [...cur, next]);
8059
8367
  const toggleFavorite = (id) => {
@@ -8077,35 +8385,35 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
8077
8385
  });
8078
8386
  };
8079
8387
  if (error) {
8080
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { ref: rootRef, role: "alert", className: "flex h-full flex-col items-center justify-center gap-3 bg-background p-6 text-center text-sm", children: [
8081
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(SafeGlyph, { className: "size-8 text-muted-foreground" }),
8082
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "font-medium", children: "The vault couldn\u2019t open" }),
8083
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "max-w-xs text-muted-foreground", children: signedOut ? "You\u2019ve been signed out." : plainLoadError(error) }),
8084
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex gap-2", children: [
8085
- signedOut && host.signIn ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_controls34.Button, { variant: "primary", onClick: host.signIn, children: "Sign in" }) : null,
8086
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_controls34.Button, { variant: signedOut && host.signIn ? "outline" : "primary", onClick: load, children: "Try again" })
8388
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { ref: rootRef, role: "alert", className: "flex h-full flex-col items-center justify-center gap-3 bg-background p-6 text-center text-sm", children: [
8389
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(SafeGlyph, { className: "size-8 text-muted-foreground" }),
8390
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "font-medium", children: "The vault couldn\u2019t open" }),
8391
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "max-w-xs text-muted-foreground", children: signedOut ? "You\u2019ve been signed out." : plainLoadError(error) }),
8392
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex gap-2", children: [
8393
+ signedOut && host.signIn ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_controls35.Button, { variant: "primary", onClick: host.signIn, children: "Sign in" }) : null,
8394
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_controls35.Button, { variant: signedOut && host.signIn ? "outline" : "primary", onClick: load, children: "Try again" })
8087
8395
  ] })
8088
8396
  ] });
8089
8397
  }
8090
8398
  if (!snap) {
8091
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { ref: rootRef, className: "flex h-full bg-background", "aria-busy": "true", "aria-label": "Opening the vault", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "flex w-full max-w-sm flex-col gap-1 p-3", children: [0, 1, 2, 3, 4, 5, 6].map((n) => /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex h-12 items-center gap-3 px-2", children: [
8092
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "size-8 animate-pulse rounded-lg bg-muted" }),
8093
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-1 flex-col gap-1.5", children: [
8094
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "h-3 w-2/3 animate-pulse rounded bg-muted" }),
8095
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "h-2.5 w-1/3 animate-pulse rounded bg-muted" })
8399
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { ref: rootRef, className: "flex h-full bg-background", "aria-busy": "true", "aria-label": "Opening the vault", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "flex w-full max-w-sm flex-col gap-1 p-3", children: [0, 1, 2, 3, 4, 5, 6].map((n) => /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex h-12 items-center gap-3 px-2", children: [
8400
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "size-8 animate-pulse rounded-lg bg-muted" }),
8401
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex flex-1 flex-col gap-1.5", children: [
8402
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "h-3 w-2/3 animate-pulse rounded bg-muted" }),
8403
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "h-2.5 w-1/3 animate-pulse rounded bg-muted" })
8096
8404
  ] })
8097
8405
  ] }, n)) }) });
8098
8406
  }
8099
8407
  const hasFavorites = port.lists.favorites !== void 0;
8100
8408
  const title = loc.vault === "all" && loc.view === "all" ? "All items" : viewLabel(loc.view, views);
8101
- const compactHeader = mode === "full" ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_auto_auto] gap-2", children: [
8102
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(VaultSelect, { value: loc.vault, choices, onChange: (vault) => go({ vault, itemId: null, panel: null }) }),
8103
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_controls34.Select, { value: loc.view, onValueChange: (view) => go({ view, itemId: null, panel: null }), options: viewOptions(views, inThisVault.length, deleted.length, hasFavorites, port.lists.recents !== void 0, host.page !== void 0), "aria-label": "Show" }),
8104
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8105
- import_controls34.Button,
8409
+ const compactHeader = mode === "full" ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)_auto_auto] gap-2", children: [
8410
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(VaultSelect, { value: loc.vault, choices, onChange: (vault) => go({ vault, itemId: null, panel: null }) }),
8411
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_controls35.Select, { value: loc.view, onValueChange: (view) => go({ view, itemId: null, panel: null }), options: viewOptions(views, inThisVault.length, deleted.length, hasFavorites, port.lists.recents !== void 0, host.page !== void 0), "aria-label": "Show" }),
8412
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8413
+ import_controls35.Button,
8106
8414
  {
8107
8415
  variant: loc.view === "authenticator" ? "outline" : "quiet",
8108
- icon: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(LockGlyph, {}),
8416
+ icon: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(LockGlyph, {}),
8109
8417
  "aria-label": AUTHENTICATOR_LABEL,
8110
8418
  "aria-pressed": loc.view === "authenticator",
8111
8419
  title: AUTHENTICATOR_LABEL,
@@ -8113,46 +8421,50 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
8113
8421
  children: mode === "split" ? AUTHENTICATOR_LABEL : null
8114
8422
  }
8115
8423
  ),
8116
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_design_system25.DropdownMenu, { children: [
8117
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_design_system25.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_controls34.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(MoreGlyph, {}), "aria-label": "Vault actions" }) }),
8118
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_design_system25.DropdownMenuContent, { align: "end", children: [
8119
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_design_system25.DropdownMenuItem, { onSelect: () => go({ panel: "import" }), children: [
8120
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ImportGlyph, { className: "size-4" }),
8424
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_design_system26.DropdownMenu, { children: [
8425
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_design_system26.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_controls35.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(MoreGlyph, {}), "aria-label": "Vault actions" }) }),
8426
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_design_system26.DropdownMenuContent, { align: "end", children: [
8427
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_design_system26.DropdownMenuItem, { onSelect: () => go({ panel: "import" }), children: [
8428
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ImportGlyph, { className: "size-4" }),
8121
8429
  "Import"
8122
8430
  ] }),
8123
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_design_system25.DropdownMenuItem, { onSelect: () => go({ panel: "export" }), children: [
8124
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ExportGlyph, { className: "size-4" }),
8431
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_design_system26.DropdownMenuItem, { onSelect: () => go({ panel: "export" }), children: [
8432
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ExportGlyph, { className: "size-4" }),
8125
8433
  "Export"
8126
8434
  ] }),
8127
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_design_system25.DropdownMenuItem, { onSelect: () => go({ panel: "backup" }), children: [
8128
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(SafeGlyph, { className: "size-4" }),
8435
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_design_system26.DropdownMenuItem, { onSelect: () => go({ panel: "backup" }), children: [
8436
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(SafeGlyph, { className: "size-4" }),
8129
8437
  "Backup"
8130
8438
  ] }),
8131
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_design_system25.DropdownMenuItem, { onSelect: () => go({ panel: "devices" }), children: [
8132
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ShieldGlyph, { className: "size-4" }),
8439
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_design_system26.DropdownMenuItem, { onSelect: () => go({ panel: "devices" }), children: [
8440
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ShieldGlyph, { className: "size-4" }),
8133
8441
  "Browsers that fill"
8134
8442
  ] }),
8135
- host.nativeImport ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_design_system25.DropdownMenuItem, { onSelect: () => go({ panel: "import-passkeys" }), children: [
8136
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ImportGlyph, { className: "size-4" }),
8443
+ host.nativeImport ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_design_system26.DropdownMenuItem, { onSelect: () => go({ panel: "import-passkeys" }), children: [
8444
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ImportGlyph, { className: "size-4" }),
8137
8445
  "Import passkeys"
8138
8446
  ] }) : null,
8139
- host.nativeProvider && host.nativeProvider.status !== "unavailable" ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_design_system25.DropdownMenuItem, { onSelect: host.nativeProvider.openSetup, children: [
8140
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ShieldGlyph, { className: "size-4" }),
8447
+ host.nativeProvider && host.nativeProvider.status !== "unavailable" ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_design_system26.DropdownMenuItem, { onSelect: host.nativeProvider.openSetup, children: [
8448
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ShieldGlyph, { className: "size-4" }),
8141
8449
  "System AutoFill"
8142
8450
  ] }) : null,
8143
- host.lock?.lock ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_design_system25.DropdownMenuItem, { onSelect: () => void host.lock?.lock?.(), children: [
8144
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(LockGlyph, { className: "size-4" }),
8451
+ host.lock?.lock ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_design_system26.DropdownMenuItem, { onSelect: () => void host.lock?.lock?.(), children: [
8452
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(LockGlyph, { className: "size-4" }),
8145
8453
  "Lock"
8454
+ ] }) : null,
8455
+ host.openWebVault ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_design_system26.DropdownMenuItem, { onSelect: host.openWebVault, children: [
8456
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ExternalGlyph, { className: "size-4" }),
8457
+ "Open on the web"
8146
8458
  ] }) : null
8147
8459
  ] })
8148
8460
  ] })
8149
8461
  ] });
8150
- const viewHeader = /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-col gap-2", children: [
8462
+ const viewHeader = /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex flex-col gap-2", children: [
8151
8463
  compactHeader,
8152
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_controls34.SearchField, { value: loc.q, onChange: (e) => go({ q: e.target.value }, "replace"), placeholder: `Search ${viewLabel(loc.view, views)}`, "aria-label": `Search ${viewLabel(loc.view, views)}` })
8464
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_controls35.SearchField, { value: loc.q, onChange: (e) => go({ q: e.target.value }, "replace"), placeholder: `Search ${viewLabel(loc.view, views)}`, "aria-label": `Search ${viewLabel(loc.view, views)}` })
8153
8465
  ] });
8154
8466
  const viewProps = { port, host, items: inThisVault, deleted, definitions, query: loc.q, onOpen: (id) => go({ view: "all", itemId: id, mode: "view", panel: null }), onChanged: load, header: viewHeader };
8155
- const pageView = loc.view === "page" && host.page && !loc.q ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8467
+ const pageView = loc.view === "page" && host.page && !loc.q ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8156
8468
  PageView,
8157
8469
  {
8158
8470
  port,
@@ -8170,8 +8482,8 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
8170
8482
  ...compactHeader ? { header: compactHeader } : {}
8171
8483
  }
8172
8484
  ) : null;
8173
- const specialView = pageView ?? (loc.view === "authenticator" ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(AuthenticatorView, { ...viewProps }) : loc.view === "trash" ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(TrashView, { ...viewProps }) : null);
8174
- const list = specialView ?? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8485
+ const specialView = pageView ?? (loc.view === "authenticator" ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(AuthenticatorView, { ...viewProps }) : loc.view === "trash" ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(TrashView, { ...viewProps }) : null);
8486
+ const list = specialView ?? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8175
8487
  ItemList,
8176
8488
  {
8177
8489
  title,
@@ -8185,6 +8497,7 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
8185
8497
  onQuery: (q) => go({ q }, "replace"),
8186
8498
  sort: loc.sort,
8187
8499
  onSort: (sort) => go({ sort }, "replace"),
8500
+ canSortViewed: port.lists.recents !== void 0,
8188
8501
  onNew: () => go({ itemId: null, mode: "new", kind: null, panel: null }),
8189
8502
  ...matchingIds ? { matchingIds } : {},
8190
8503
  ...compactHeader ? { header: compactHeader } : {}
@@ -8198,9 +8511,9 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
8198
8511
  const onPanel = (panel2) => go({ panel: panel2 }, "push");
8199
8512
  let detail;
8200
8513
  if (loc.mode === "new" && !kindDefinition) {
8201
- detail = /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(NewItemFlow, { definitions, url: loc.url, onUrl: (url) => go({ url }, "replace"), onChoose: (kind, _name, url) => go({ kind, url }, "push"), onCancel: () => go({ mode: "view", kind: null, url: "", itemId: null }) });
8514
+ detail = /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(NewItemFlow, { definitions, url: loc.url, onUrl: (url) => go({ url }, "replace"), onChoose: (kind, _name, url) => go({ kind, url }, "push"), onCancel: () => go({ mode: "view", kind: null, url: "", itemId: null }) });
8202
8515
  } else if (loc.mode === "new" && kindDefinition) {
8203
- detail = /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8516
+ detail = /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8204
8517
  ItemPane,
8205
8518
  {
8206
8519
  port,
@@ -8232,7 +8545,7 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
8232
8545
  `new-${kindDefinition.key}`
8233
8546
  );
8234
8547
  } else if (selected) {
8235
- detail = /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8548
+ detail = /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8236
8549
  ItemPane,
8237
8550
  {
8238
8551
  port,
@@ -8276,23 +8589,23 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
8276
8589
  selected.id
8277
8590
  );
8278
8591
  } else if (loc.itemId) {
8279
- detail = /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Blank, { children: "This item is not in your vault, or you cannot see it." });
8592
+ detail = /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Blank, { children: "This item is not in your vault, or you cannot see it." });
8280
8593
  } else {
8281
- detail = /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Blank, { children: visible.length === 0 ? "" : "Select an item" });
8594
+ detail = /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Blank, { children: visible.length === 0 ? "" : "Select an item" });
8282
8595
  }
8283
8596
  const [panelName, panelArg] = (loc.panel ?? "").split(/:(.*)/s);
8284
8597
  const closePanel = () => go({ panel: null }, "push");
8285
8598
  const vaultPanelProps = { port, host, items, definitions, organizations: orgs, onClose: closePanel, onChanged: load };
8286
8599
  let panel = null;
8287
- if (panelName === "import") panel = /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ImportWithLimits, { ...vaultPanelProps, knobs: host.knobs });
8288
- else if (panelName === "devices") panel = /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(DevicesPanel, { ...vaultPanelProps });
8289
- else if (panelName === "approve" && panelArg) panel = /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ApprovePanel, { ...vaultPanelProps, ...approvalFromParams(panelArg, new URLSearchParams(globalThis.location?.search ?? "")) });
8290
- else if (panelName === "import-passkeys" && host.nativeImport) panel = /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(NativeImportPanel, { ...vaultPanelProps, bridge: host.nativeImport, readLimits: port.native.limits, activeOrganizationId: orgs[0]?.id ?? null });
8291
- else if (panelName === "export") panel = /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ExportPanel, { ...vaultPanelProps });
8292
- else if (panelName === "backup") panel = /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(BackupPanel, { ...vaultPanelProps });
8600
+ if (panelName === "import") panel = /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ImportWithLimits, { ...vaultPanelProps, knobs: host.knobs });
8601
+ else if (panelName === "devices") panel = /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(DevicesPanel, { ...vaultPanelProps });
8602
+ else if (panelName === "approve" && panelArg) panel = /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ApprovePanel, { ...vaultPanelProps, ...approvalFromParams(panelArg, new URLSearchParams(globalThis.location?.search ?? "")) });
8603
+ else if (panelName === "import-passkeys" && host.nativeImport) panel = /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(NativeImportPanel, { ...vaultPanelProps, bridge: host.nativeImport, readLimits: port.native.limits, activeOrganizationId: orgs[0]?.id ?? null });
8604
+ else if (panelName === "export") panel = /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ExportPanel, { ...vaultPanelProps });
8605
+ else if (panelName === "backup") panel = /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(BackupPanel, { ...vaultPanelProps });
8293
8606
  else if (panelName && selected && ITEM_PANELS[panelName]) {
8294
8607
  const P = ITEM_PANELS[panelName];
8295
- panel = /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8608
+ panel = /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8296
8609
  P,
8297
8610
  {
8298
8611
  item: selected,
@@ -8315,17 +8628,17 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
8315
8628
  }
8316
8629
  const grid = mode === "full" ? "grid-cols-[15rem_21rem_minmax(0,1fr)]" : mode === "split" ? "grid-cols-[19rem_minmax(0,1fr)]" : "grid-cols-1";
8317
8630
  const shown = panesShown(mode, specialView !== null, showingDetail);
8318
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { ref: rootRef, className: "flex h-full min-h-0 w-full flex-col bg-background text-foreground", children: [
8319
- snap.unavailable.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { role: "status", className: "flex items-center gap-3 border-b border-border bg-muted px-4 py-2 text-sm", children: [
8320
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "min-w-0 flex-1 truncate text-warning", children: [
8631
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { ref: rootRef, className: "flex h-full min-h-0 w-full flex-col bg-background text-foreground", children: [
8632
+ snap.unavailable.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { role: "status", className: "flex items-center gap-3 border-b border-border bg-muted px-4 py-2 text-sm", children: [
8633
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "min-w-0 flex-1 truncate text-warning", children: [
8321
8634
  "Couldn\u2019t load ",
8322
8635
  snap.unavailable.join(", "),
8323
8636
  ". Showing the rest."
8324
8637
  ] }),
8325
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("button", { type: "button", className: "shrink-0 text-primary hover:underline", onClick: load, children: "Try again" })
8638
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("button", { type: "button", className: "shrink-0 text-primary hover:underline", onClick: load, children: "Try again" })
8326
8639
  ] }) : null,
8327
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: `grid min-h-0 w-full flex-1 ${grid} overflow-hidden`, children: [
8328
- mode === "full" ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8640
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: `grid min-h-0 w-full flex-1 ${grid} overflow-hidden`, children: [
8641
+ mode === "full" ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8329
8642
  VaultSidebar,
8330
8643
  {
8331
8644
  vault: loc.vault,
@@ -8344,10 +8657,10 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
8344
8657
  hasPage: host.page !== void 0
8345
8658
  }
8346
8659
  ) : null,
8347
- shown.list ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: specialView && mode !== "stack" ? "col-span-2 min-h-0" : "min-h-0", children: list }) : null,
8660
+ shown.list ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: specialView && mode !== "stack" ? "col-span-2 min-h-0" : "min-h-0", children: list }) : null,
8348
8661
  shown.detail ? detail : null,
8349
8662
  panel,
8350
- firstCode ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(FirstCodePanel, { port, item: firstCode, onClose: () => setFirstCode(null), onDone: () => setFirstCode(null) }) : null
8663
+ firstCode ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(FirstCodePanel, { port, item: firstCode, onClose: () => setFirstCode(null), onDone: () => setFirstCode(null) }) : null
8351
8664
  ] })
8352
8665
  ] });
8353
8666
  }
@@ -8355,8 +8668,8 @@ function plainLoadError(message2) {
8355
8668
  return /load failed|failed to fetch|network|timed? ?out/i.test(message2) ? "The connection dropped. Check you\u2019re online, then try again." : message2;
8356
8669
  }
8357
8670
  function Blank({ children }) {
8358
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex h-full flex-col items-center justify-center gap-3 bg-background text-sm text-muted-foreground", children: [
8359
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(SafeGlyph, { className: "size-10 text-disabled-foreground" }),
8671
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex h-full flex-col items-center justify-center gap-3 bg-background text-sm text-muted-foreground", children: [
8672
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(SafeGlyph, { className: "size-10 text-disabled-foreground" }),
8360
8673
  children
8361
8674
  ] });
8362
8675
  }
@@ -8726,6 +9039,20 @@ function createListsPort(ctx, door) {
8726
9039
 
8727
9040
  // src/sharing/api.ts
8728
9041
  var account6 = __toESM(require("@ai-matrx/api/account"), 1);
9042
+
9043
+ // src/secret-field-in.ts
9044
+ function secretFieldIn(s) {
9045
+ const envKey = s.envKey?.trim() || null;
9046
+ return {
9047
+ field_key: fieldKeyOf(s.label),
9048
+ value: s.value,
9049
+ handling: s.handling ?? "revealable",
9050
+ ...envKey ? { env_key: envKey } : {},
9051
+ ...envKey && s.injectIntoSandbox ? { inject_into_sandbox: true } : {}
9052
+ };
9053
+ }
9054
+
9055
+ // src/sharing/api.ts
8729
9056
  function grantOf(w) {
8730
9057
  const org = Boolean(w.organization_id);
8731
9058
  return {
@@ -8825,7 +9152,7 @@ function createSharingPort(ctx, options = {}) {
8825
9152
  non_secret_fields: [...meta.map((f) => ({ key: f.key, label: f.label, value: draft.values[f.key] ?? "" })), ...draft.custom.filter((c) => c.label.trim() !== "").map((c) => ({ key: c.key || fieldKeyOf(c.label), label: c.label, value: c.value }))],
8826
9153
  fields: [
8827
9154
  ...encrypted.map((f) => ({ field_key: f.key, value: draft.values[f.key] ?? "", handling: f.handling })),
8828
- ...draft.secrets.filter((s) => s.label.trim() !== "" && s.value !== "").map((s) => ({ field_key: fieldKeyOf(s.label), value: s.value, handling: "revealable" }))
9155
+ ...draft.secrets.filter((s) => s.label.trim() !== "" && s.value !== "").map(secretFieldIn)
8829
9156
  ]
8830
9157
  }
8831
9158
  });
@@ -9111,14 +9438,14 @@ function createApiVaultPort(api, options = {}) {
9111
9438
  login_urls: draft.loginUrls,
9112
9439
  // A login a person saves with its website is offered on that website (the server's own
9113
9440
  // default is off, which made "Save a login" on a page answer "No saved login" there).
9114
- ...draft.loginUrls.length > 0 ? { browser_fill_enabled: true } : {},
9441
+ ...draft.browser ? { uri_match_mode: draft.browser.uriMatchMode, browser_fill_enabled: draft.browser.browserFillEnabled } : draft.loginUrls.length > 0 ? { browser_fill_enabled: true } : {},
9115
9442
  notes: draft.notes || null,
9116
9443
  principal: organizationId ? { type: "organization", organization_id: organizationId } : { type: "user" },
9117
9444
  initiation: "user",
9118
9445
  non_secret_fields: [...meta.map((f) => ({ key: f.key, label: f.label, value: draft.values[f.key] ?? "" })), ...draft.custom.filter((c) => c.label.trim() !== "").map((c) => ({ key: c.key || fieldKeyOf(c.label), label: c.label, value: c.value }))],
9119
9446
  fields: [
9120
9447
  ...encrypted.map((f) => ({ field_key: f.key, value: draft.values[f.key] ?? "", handling: f.handling })),
9121
- ...draft.secrets.filter((s) => s.label.trim() !== "" && s.value !== "").map((s) => ({ field_key: fieldKeyOf(s.label), value: s.value, handling: "revealable" })),
9448
+ ...draft.secrets.filter((s) => s.label.trim() !== "" && s.value !== "").map(secretFieldIn),
9122
9449
  // Backup codes on a type that does not declare them (a website login): their own encrypted field.
9123
9450
  ...!declared.some((f) => f.key === RECOVERY_CODES_KEY) && (draft.values[RECOVERY_CODES_KEY] ?? "").trim() !== "" ? [{ field_key: RECOVERY_CODES_KEY, value: parseRecoveryCodes(draft.values[RECOVERY_CODES_KEY] ?? "").join("\n"), handling: "revealable", description: "One-time account recovery codes" }] : []
9124
9451
  ]
@@ -9158,7 +9485,7 @@ function createApiVaultPort(api, options = {}) {
9158
9485
  }
9159
9486
  for (const s of draft.secrets) {
9160
9487
  if (s.label.trim() === "" || s.value === "") continue;
9161
- await account9.addField(api, { path: { item_id: item.id }, body: { field_key: fieldKeyOf(s.label), value: s.value, handling: "revealable" } }, opts);
9488
+ await account9.addField(api, { path: { item_id: item.id }, body: secretFieldIn(s) }, opts);
9162
9489
  }
9163
9490
  for (const id of draft.removed) await account9.deleteField(api, { path: { item_id: item.id, field_id: id } }, opts);
9164
9491
  return { item: await refetch(item.id, item.owner), notice: null };
@@ -9183,4 +9510,42 @@ function createVaultKnobs(client, address) {
9183
9510
  return snap.resolved;
9184
9511
  };
9185
9512
  }
9513
+
9514
+ // src/agent-context.ts
9515
+ var hostOf = (url) => {
9516
+ try {
9517
+ return new URL(/^[a-z][a-z0-9+.-]*:\/\//i.test(url) ? url : `https://${url}`).host || null;
9518
+ } catch {
9519
+ return null;
9520
+ }
9521
+ };
9522
+ function providerOf(item, definitions) {
9523
+ return definitions.find((d) => d.key === item.definitionKey)?.providerKey ?? null;
9524
+ }
9525
+ function vaultItemFacts(item, definitions) {
9526
+ const provider = providerOf(item, definitions);
9527
+ const hosts = item.loginUrls.map(hostOf).filter((h) => Boolean(h));
9528
+ const keys = item.fields.map((f) => f.key).filter((k) => !isAuthenticatorStorage(k));
9529
+ return [
9530
+ `Name: ${item.name}`,
9531
+ ...item.definitionLabel ? [`Type: ${item.definitionLabel}`] : [],
9532
+ ...provider ? [`Provider: ${provider}`] : [],
9533
+ ...hosts.length ? [`Sites: ${hosts.join(", ")}`] : [],
9534
+ `Owner: ${item.owner.label}`,
9535
+ `Status: ${item.turnedOff ? "turned off" : "active"}`,
9536
+ ...item.accessMode ? [`Access: ${item.accessMode}`] : [],
9537
+ ...item.tags.length ? [`Tags: ${item.tags.join(", ")}`] : [],
9538
+ ...keys.length ? [`Fields: ${keys.join(", ")}`] : [],
9539
+ ...item.authenticator ? ["Has a one-time password"] : []
9540
+ ];
9541
+ }
9542
+ function vaultInventoryScope(inventory, clicked = null) {
9543
+ const { items, definitions } = inventory;
9544
+ const providers = [...new Set(items.map((i) => providerOf(i, definitions)).filter((p) => Boolean(p)))];
9545
+ const content = clicked ? vaultItemFacts(clicked, definitions) : [`Vault \u2014 ${items.length} ${items.length === 1 ? "item" : "items"}`, ...items.map((i) => `\u2022 ${i.name}${i.definitionLabel ? ` \u2014 ${i.definitionLabel}` : ""}`)];
9546
+ return { content: content.join("\n"), credential_count: items.length, credential_labels: items.map((i) => i.name), credential_providers: providers };
9547
+ }
9548
+ function itemIdAt(target) {
9549
+ return target?.closest("[data-item]")?.getAttribute("data-item") ?? null;
9550
+ }
9186
9551
  //# sourceMappingURL=index.cjs.map