@ai-matrx/vault 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/README.md +1 -1
- package/dist/index.cjs +378 -277
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +63 -6
- package/dist/index.d.ts +63 -6
- package/dist/index.js +166 -65
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -138,24 +138,28 @@ __export(src_exports, {
|
|
|
138
138
|
CATEGORIES: () => CATEGORIES,
|
|
139
139
|
DEFAULT_LOCATION: () => DEFAULT_LOCATION,
|
|
140
140
|
GenerateButton: () => GenerateButton,
|
|
141
|
+
LOCKED_MESSAGE: () => LOCKED_MESSAGE,
|
|
141
142
|
VaultApp: () => VaultApp,
|
|
143
|
+
VaultLockedError: () => VaultLockedError,
|
|
142
144
|
categoryOf: () => categoryOf,
|
|
145
|
+
copyValue: () => copyValue,
|
|
143
146
|
createApiVaultPort: () => createApiVaultPort,
|
|
144
147
|
createSupabaseIdentity: () => createSupabaseIdentity,
|
|
145
148
|
createVaultKnobs: () => createVaultKnobs,
|
|
149
|
+
guardPort: () => guardPort,
|
|
146
150
|
inferFromUrl: () => inferFromUrl,
|
|
147
151
|
locationFromParams: () => locationFromParams,
|
|
148
152
|
locationToParams: () => locationToParams,
|
|
153
|
+
loginSiteOf: () => loginSiteOf,
|
|
149
154
|
matchesQuery: () => matchesQuery,
|
|
150
155
|
needsRecentSignIn: () => needsRecentSignIn,
|
|
151
156
|
parseDefinitions: () => parseDefinitions,
|
|
152
|
-
siteOf: () => siteOf,
|
|
153
157
|
sortItems: () => sortItems
|
|
154
158
|
});
|
|
155
159
|
module.exports = __toCommonJS(src_exports);
|
|
156
160
|
|
|
157
161
|
// src/VaultApp.tsx
|
|
158
|
-
var
|
|
162
|
+
var import_react41 = require("react");
|
|
159
163
|
var import_design_system25 = require("@ai-matrx/design-system");
|
|
160
164
|
var import_controls34 = require("@ai-matrx/design-system/controls");
|
|
161
165
|
var import_confirm_opener13 = require("@ai-matrx/kit/confirm-opener");
|
|
@@ -169,9 +173,28 @@ var Ctx = (0, import_react.createContext)(() => void 0);
|
|
|
169
173
|
function useNotify() {
|
|
170
174
|
return (0, import_react.useContext)(Ctx);
|
|
171
175
|
}
|
|
176
|
+
async function copyValue(text, label, options, deps) {
|
|
177
|
+
const secret = options.secret ?? true;
|
|
178
|
+
if (deps.clipboard) {
|
|
179
|
+
try {
|
|
180
|
+
await deps.clipboard.copy(text, { secret });
|
|
181
|
+
deps.notify(`${label} copied`, "success");
|
|
182
|
+
return true;
|
|
183
|
+
} catch (e) {
|
|
184
|
+
deps.notify(e instanceof Error && e.message ? e.message : `${label} could not be copied`, "error");
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return (0, import_clipboard.copyText)(text, { successMessage: `${label} copied`, failureMessage: `${label} could not be copied`, notify: (m, k) => deps.notify(m, k === "error" ? "error" : "success") });
|
|
189
|
+
}
|
|
190
|
+
var ClipboardCtx = (0, import_react.createContext)(void 0);
|
|
191
|
+
function ClipboardProvider({ clipboard, children }) {
|
|
192
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ClipboardCtx.Provider, { value: clipboard, children });
|
|
193
|
+
}
|
|
172
194
|
function useCopy() {
|
|
173
195
|
const notify = useNotify();
|
|
174
|
-
|
|
196
|
+
const clipboard = (0, import_react.useContext)(ClipboardCtx);
|
|
197
|
+
return (0, import_react.useCallback)((text, label, options = {}) => copyValue(text, label, options, { clipboard, notify }), [notify, clipboard]);
|
|
175
198
|
}
|
|
176
199
|
function NoticeProvider({ notify, children }) {
|
|
177
200
|
const [shown, setShown] = (0, import_react.useState)(null);
|
|
@@ -549,7 +572,15 @@ var import_design_system5 = require("@ai-matrx/design-system");
|
|
|
549
572
|
|
|
550
573
|
// src/hooks.ts
|
|
551
574
|
var import_react3 = require("react");
|
|
552
|
-
|
|
575
|
+
var DEFAULT_REVEAL_MS = 2e4;
|
|
576
|
+
var RevealMs = (0, import_react3.createContext)(DEFAULT_REVEAL_MS);
|
|
577
|
+
function RevealSecondsProvider({ seconds, children }) {
|
|
578
|
+
const ms = seconds !== void 0 && Number.isFinite(seconds) && seconds > 0 ? seconds * 1e3 : DEFAULT_REVEAL_MS;
|
|
579
|
+
return (0, import_react3.createElement)(RevealMs.Provider, { value: ms }, children);
|
|
580
|
+
}
|
|
581
|
+
function useTransientSecret(given) {
|
|
582
|
+
const fromHost = (0, import_react3.useContext)(RevealMs);
|
|
583
|
+
const ms = given ?? fromHost;
|
|
553
584
|
const [value, setValue] = (0, import_react3.useState)(null);
|
|
554
585
|
const timer2 = (0, import_react3.useRef)(null);
|
|
555
586
|
const clear = (0, import_react3.useCallback)(() => {
|
|
@@ -647,12 +678,7 @@ function formatBytes(n) {
|
|
|
647
678
|
if (n < 1024 * 1024) return `${(n / 1024).toFixed(n < 10 * 1024 ? 1 : 0)} KB`;
|
|
648
679
|
return `${(n / 1024 / 1024).toFixed(1)} MB`;
|
|
649
680
|
}
|
|
650
|
-
|
|
651
|
-
if (!iso) return "";
|
|
652
|
-
const d = new Date(iso);
|
|
653
|
-
if (Number.isNaN(d.getTime())) return iso;
|
|
654
|
-
return d.toLocaleString(void 0, withTime ? { year: "numeric", month: "short", day: "numeric", hour: "numeric", minute: "2-digit" } : { year: "numeric", month: "short", day: "numeric" });
|
|
655
|
-
}
|
|
681
|
+
var DAY_FORMAT = { year: "numeric", month: "short", day: "numeric" };
|
|
656
682
|
|
|
657
683
|
// src/FieldRows.tsx
|
|
658
684
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
@@ -664,7 +690,7 @@ function SecretText({ value, multiline }) {
|
|
|
664
690
|
var quietError = (e, fallback) => wasCancelled(e) ? null : e instanceof Error ? e.message : fallback;
|
|
665
691
|
function SecretRow({ port, item, field, extra }) {
|
|
666
692
|
const confirmed = useConfirmed();
|
|
667
|
-
const
|
|
693
|
+
const copyValue2 = useCopy();
|
|
668
694
|
const secret = useTransientSecret();
|
|
669
695
|
const [plain, setPlain] = (0, import_react5.useState)(null);
|
|
670
696
|
const [busy, setBusy] = (0, import_react5.useState)(false);
|
|
@@ -705,7 +731,7 @@ function SecretRow({ port, item, field, extra }) {
|
|
|
705
731
|
}
|
|
706
732
|
async function copy() {
|
|
707
733
|
const v = await fetchValue();
|
|
708
|
-
if (v !== null) await
|
|
734
|
+
if (v !== null) await copyValue2(v, field.label, { secret: !visible });
|
|
709
735
|
}
|
|
710
736
|
const multiline = field.kind === "multiline";
|
|
711
737
|
const shown = visible ? plain : secret.value;
|
|
@@ -724,7 +750,7 @@ function SecretRow({ port, item, field, extra }) {
|
|
|
724
750
|
);
|
|
725
751
|
}
|
|
726
752
|
function PlainRow({ label, value, hint, openUrl, extra, multiline = false }) {
|
|
727
|
-
const
|
|
753
|
+
const copyValue2 = useCopy();
|
|
728
754
|
const isUrl = /^https?:\/\//i.test(value);
|
|
729
755
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
730
756
|
Row,
|
|
@@ -735,7 +761,7 @@ function PlainRow({ label, value, hint, openUrl, extra, multiline = false }) {
|
|
|
735
761
|
actions: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
736
762
|
extra,
|
|
737
763
|
isUrl && openUrl ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_controls2.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ExternalGlyph, {}), "aria-label": `Open ${value}`, onClick: () => openUrl(value) }) : null,
|
|
738
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_controls2.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CopyGlyph, {}), "aria-label": `Copy ${typeof label === "string" ? label : "value"}`, onClick: () => void
|
|
764
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_controls2.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CopyGlyph, {}), "aria-label": `Copy ${typeof label === "string" ? label : "value"}`, onClick: () => void copyValue2(value, typeof label === "string" && label ? label : "Value", { secret: false }) })
|
|
739
765
|
] }),
|
|
740
766
|
children: isUrl && openUrl ? (
|
|
741
767
|
// A real link (right-click, copy link address, open in a new tab); a click goes through the host's opener.
|
|
@@ -792,6 +818,9 @@ function CustomEditRow({ label, value, onLabel, onValue, secret, onRemove }) {
|
|
|
792
818
|
);
|
|
793
819
|
}
|
|
794
820
|
|
|
821
|
+
// src/activity/HistoryPanel.tsx
|
|
822
|
+
var import_format3 = require("@ai-matrx/kit/format");
|
|
823
|
+
|
|
795
824
|
// src/activity/logic.ts
|
|
796
825
|
var import_format = require("@ai-matrx/kit/format");
|
|
797
826
|
|
|
@@ -843,7 +872,7 @@ function matchesQuery(item, query) {
|
|
|
843
872
|
return [item.name, item.definitionLabel, ...item.tags, ...item.loginUrls, ...item.custom.map((c) => `${c.label} ${c.value}`)].some((h) => h.toLowerCase().includes(q));
|
|
844
873
|
}
|
|
845
874
|
var isAuthenticatorStorage = (key) => key === "totp_seed" || key.startsWith("totp_") || key === "authenticator_last_time_step";
|
|
846
|
-
function
|
|
875
|
+
function loginSiteOf(item) {
|
|
847
876
|
const raw = item.loginUrls[0];
|
|
848
877
|
if (!raw) return "";
|
|
849
878
|
try {
|
|
@@ -857,7 +886,7 @@ function sortItems(items, sort) {
|
|
|
857
886
|
const byName = (a, b) => a.name.localeCompare(b.name, void 0, { sensitivity: "base" });
|
|
858
887
|
if (sort === "name") return out.sort(byName);
|
|
859
888
|
if (sort === "website") return out.sort((a, b) => {
|
|
860
|
-
const x =
|
|
889
|
+
const x = loginSiteOf(a), y = loginSiteOf(b);
|
|
861
890
|
return x && y ? x.localeCompare(y) || byName(a, b) : x ? -1 : y ? 1 : byName(a, b);
|
|
862
891
|
});
|
|
863
892
|
if (sort === "updated") return out.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
|
|
@@ -1249,6 +1278,7 @@ var HistoryChangedError = class extends Error {
|
|
|
1249
1278
|
var import_react6 = require("react");
|
|
1250
1279
|
var import_controls3 = require("@ai-matrx/design-system/controls");
|
|
1251
1280
|
var import_design_system6 = require("@ai-matrx/design-system");
|
|
1281
|
+
var import_format2 = require("@ai-matrx/kit/format");
|
|
1252
1282
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1253
1283
|
var PAGE = 50;
|
|
1254
1284
|
var MAX = 500;
|
|
@@ -1285,7 +1315,7 @@ function ActivityPanel({ item, port, onClose }) {
|
|
|
1285
1315
|
day.entries.map((entry) => ({ entry, s: auditSentence(entry, item, me) })),
|
|
1286
1316
|
(r) => `${r.s.what}|${r.s.who ?? ""}`
|
|
1287
1317
|
).map(({ row: { entry, s }, times }) => {
|
|
1288
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex min-h-9 items-center gap-1.5 px-3 text-sm sm:px-4", title:
|
|
1318
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex min-h-9 items-center gap-1.5 px-3 text-sm sm:px-4", title: (0, import_format2.formatAbsoluteDate)(entry.at, void 0, ""), children: [
|
|
1289
1319
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: (0, import_design_system6.cn)("truncate", s.refused ? "text-destructive" : "text-foreground"), children: s.what }),
|
|
1290
1320
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "shrink-0 text-muted-foreground", children: [
|
|
1291
1321
|
times > 1 ? ` \xB7 ${times} times` : "",
|
|
@@ -1370,7 +1400,7 @@ function HistoryPanel({ item, port, arg, onClose, onChanged }) {
|
|
|
1370
1400
|
page && (page.captureStartedAt || page.incomplete) ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-wrap gap-x-3 gap-y-1 px-1 text-xs", children: [
|
|
1371
1401
|
page.captureStartedAt ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "text-muted-foreground", children: [
|
|
1372
1402
|
"Kept since ",
|
|
1373
|
-
|
|
1403
|
+
(0, import_format3.formatAbsoluteDate)(page.captureStartedAt, void 0, "")
|
|
1374
1404
|
] }) : null,
|
|
1375
1405
|
page.incomplete ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-warning", children: "Some changes could not be read" }) : null
|
|
1376
1406
|
] }) : null
|
|
@@ -1381,9 +1411,9 @@ function HistoryPanel({ item, port, arg, onClose, onChanged }) {
|
|
|
1381
1411
|
function HistoryRow({ item, port, page, entry, label, onRestored, onConflict, onError }) {
|
|
1382
1412
|
const confirmed = useConfirmed();
|
|
1383
1413
|
const secret = useTransientSecret();
|
|
1384
|
-
const
|
|
1414
|
+
const copyValue2 = useCopy();
|
|
1385
1415
|
const [busy, setBusy] = (0, import_react7.useState)(false);
|
|
1386
|
-
const when =
|
|
1416
|
+
const when = (0, import_format3.formatAbsoluteDate)(entry.recordedAt, void 0, "");
|
|
1387
1417
|
async function read() {
|
|
1388
1418
|
if (secret.value !== null) return secret.value;
|
|
1389
1419
|
setBusy(true);
|
|
@@ -1404,7 +1434,7 @@ function HistoryRow({ item, port, page, entry, label, onRestored, onConflict, on
|
|
|
1404
1434
|
}
|
|
1405
1435
|
async function copy() {
|
|
1406
1436
|
const v = await read();
|
|
1407
|
-
if (v !== null) await
|
|
1437
|
+
if (v !== null) await copyValue2(v, `Earlier ${label.toLowerCase()}`);
|
|
1408
1438
|
}
|
|
1409
1439
|
async function restore() {
|
|
1410
1440
|
const yes = await (0, import_confirm_opener.confirm)({
|
|
@@ -1545,11 +1575,11 @@ function authenticatorName(current, parsed) {
|
|
|
1545
1575
|
if (name && !PLACEHOLDER_NAMES.includes(name.toLowerCase())) return name;
|
|
1546
1576
|
return parsed.issuer || parsed.account || name || "One-time password";
|
|
1547
1577
|
}
|
|
1548
|
-
function matchIssuerToSite(issuer, candidates,
|
|
1578
|
+
function matchIssuerToSite(issuer, candidates, siteOf) {
|
|
1549
1579
|
const key = (issuer ?? "").toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
1550
1580
|
if (key.length < 2) return null;
|
|
1551
1581
|
for (const c of candidates) {
|
|
1552
|
-
const host =
|
|
1582
|
+
const host = siteOf(c).toLowerCase();
|
|
1553
1583
|
if (!host) continue;
|
|
1554
1584
|
const labels = host.split(".");
|
|
1555
1585
|
if (labels.some((l) => l.replace(/[^a-z0-9]/g, "") === key)) return c;
|
|
@@ -1589,13 +1619,13 @@ function CountdownRing({ remaining, period, loading = false, className }) {
|
|
|
1589
1619
|
}
|
|
1590
1620
|
function useCopied() {
|
|
1591
1621
|
const [copied, setCopied] = (0, import_react8.useState)(false);
|
|
1592
|
-
const
|
|
1622
|
+
const copyValue2 = useCopy();
|
|
1593
1623
|
const t = (0, import_react8.useRef)(null);
|
|
1594
1624
|
(0, import_react8.useEffect)(() => () => void (t.current && clearTimeout(t.current)), []);
|
|
1595
1625
|
return {
|
|
1596
1626
|
copied,
|
|
1597
1627
|
copy: async (code) => {
|
|
1598
|
-
const ok = await
|
|
1628
|
+
const ok = await copyValue2(code, "One-time code");
|
|
1599
1629
|
if (!ok) return;
|
|
1600
1630
|
setCopied(true);
|
|
1601
1631
|
if (t.current) clearTimeout(t.current);
|
|
@@ -2170,7 +2200,7 @@ function AddOtpPanel({ port, items, definitions, itemId = null, onClose, onChang
|
|
|
2170
2200
|
const recognise = (p) => {
|
|
2171
2201
|
if (!nameTouched) setName((n) => authenticatorName(n, p));
|
|
2172
2202
|
if (!targetChosen) {
|
|
2173
|
-
const match = matchIssuerToSite(p.issuer, candidates,
|
|
2203
|
+
const match = matchIssuerToSite(p.issuer, candidates, loginSiteOf);
|
|
2174
2204
|
setTarget(match ? match.id : NEW);
|
|
2175
2205
|
}
|
|
2176
2206
|
};
|
|
@@ -2248,7 +2278,7 @@ function AddOtpPanel({ port, items, definitions, itemId = null, onClose, onChang
|
|
|
2248
2278
|
value: target,
|
|
2249
2279
|
disabled: busy || created !== null,
|
|
2250
2280
|
"aria-label": "Add to",
|
|
2251
|
-
options: [{ value: NEW, label: "New login" }, ...candidates.map((c) => ({ value: c.id, label:
|
|
2281
|
+
options: [{ value: NEW, label: "New login" }, ...candidates.map((c) => ({ value: c.id, label: loginSiteOf(c) ? `${c.name} \xB7 ${loginSiteOf(c)}` : c.name }))],
|
|
2252
2282
|
onValueChange: (v) => {
|
|
2253
2283
|
setTarget(v);
|
|
2254
2284
|
setTargetChosen(true);
|
|
@@ -2410,7 +2440,7 @@ function OtpListRow({ port, item, family, entry, onOpen, onRename, onChanged, on
|
|
|
2410
2440
|
const Icon = definitionGlyph(item.definitionKey, family);
|
|
2411
2441
|
const canManage = item.capabilities.canManage || item.capabilities.canEdit;
|
|
2412
2442
|
if (a.removed) return null;
|
|
2413
|
-
const sub = a.error ?? [entry?.account,
|
|
2443
|
+
const sub = a.error ?? [entry?.account, loginSiteOf(item) || entry?.issuer].filter((v, i, all) => Boolean(v) && all.indexOf(v) === i).join(" \xB7 ");
|
|
2414
2444
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "grid min-h-14 grid-cols-[2rem_minmax(0,1fr)_auto_auto] items-center gap-x-3 rounded-lg px-2 py-1.5 transition-colors hover:bg-accent/50", children: [
|
|
2415
2445
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", onClick: onOpen, "aria-label": `Open ${item.name}`, tabIndex: -1, className: (0, import_design_system9.cn)("flex size-8 items-center justify-center rounded-lg bg-muted", a.enabled ? "text-foreground" : "text-disabled-foreground"), children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Icon, { className: "size-4" }) }),
|
|
2416
2446
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("button", { type: "button", onClick: onOpen, className: "flex min-w-0 flex-col items-start rounded-md text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: [
|
|
@@ -2810,7 +2840,7 @@ function PasswordGenerator({ limits: source, onUse, useLabel = "Use" }) {
|
|
|
2810
2840
|
const [candidate, setCandidate] = (0, import_react15.useState)(null);
|
|
2811
2841
|
const [revealed, setRevealed] = (0, import_react15.useState)(false);
|
|
2812
2842
|
const [note, setNote] = (0, import_react15.useState)(null);
|
|
2813
|
-
const
|
|
2843
|
+
const copyValue2 = useCopy();
|
|
2814
2844
|
const expiry = (0, import_react15.useRef)(null);
|
|
2815
2845
|
const drop = () => {
|
|
2816
2846
|
if (expiry.current) clearTimeout(expiry.current);
|
|
@@ -2870,7 +2900,7 @@ function PasswordGenerator({ limits: source, onUse, useLabel = "Use" }) {
|
|
|
2870
2900
|
const strength = candidate ? strengthOf(candidate.bits) : null;
|
|
2871
2901
|
const copy = async () => {
|
|
2872
2902
|
if (!candidate) return;
|
|
2873
|
-
const ok = await
|
|
2903
|
+
const ok = await copyValue2(candidate.value, "Generated password");
|
|
2874
2904
|
setNote(ok ? { tone: "success", text: "Copied. Your clipboard keeps it." } : { tone: "destructive", text: "Couldn\u2019t copy. Reveal it and copy by hand." });
|
|
2875
2905
|
};
|
|
2876
2906
|
const use = () => {
|
|
@@ -2981,8 +3011,47 @@ function importLimitsFrom(resolved) {
|
|
|
2981
3011
|
return out;
|
|
2982
3012
|
}
|
|
2983
3013
|
|
|
3014
|
+
// src/lock.ts
|
|
3015
|
+
var import_react16 = require("react");
|
|
3016
|
+
var LOCKED_MESSAGE = "The vault is locked. Unlock it first.";
|
|
3017
|
+
var VaultLockedError = class extends Error {
|
|
3018
|
+
code = "vault_locked";
|
|
3019
|
+
constructor() {
|
|
3020
|
+
super(LOCKED_MESSAGE);
|
|
3021
|
+
this.name = "VaultLockedError";
|
|
3022
|
+
}
|
|
3023
|
+
};
|
|
3024
|
+
function guardPort(port, locked) {
|
|
3025
|
+
const cache = /* @__PURE__ */ new WeakMap();
|
|
3026
|
+
const wrap = (target) => {
|
|
3027
|
+
const hit = cache.get(target);
|
|
3028
|
+
if (hit) return hit;
|
|
3029
|
+
const proxy = new Proxy(target, {
|
|
3030
|
+
get(obj2, key, receiver) {
|
|
3031
|
+
const value = Reflect.get(obj2, key, receiver);
|
|
3032
|
+
if (typeof value === "function") {
|
|
3033
|
+
return (...args) => {
|
|
3034
|
+
if (locked()) return Promise.reject(new VaultLockedError());
|
|
3035
|
+
return value.apply(obj2, args);
|
|
3036
|
+
};
|
|
3037
|
+
}
|
|
3038
|
+
if (value && typeof value === "object") return wrap(value);
|
|
3039
|
+
return value;
|
|
3040
|
+
}
|
|
3041
|
+
});
|
|
3042
|
+
cache.set(target, proxy);
|
|
3043
|
+
return proxy;
|
|
3044
|
+
};
|
|
3045
|
+
return wrap(port);
|
|
3046
|
+
}
|
|
3047
|
+
var NEVER = () => () => void 0;
|
|
3048
|
+
var UNLOCKED = () => false;
|
|
3049
|
+
function useLocked(lock) {
|
|
3050
|
+
return (0, import_react16.useSyncExternalStore)(lock ? lock.subscribe : NEVER, lock ? () => lock.locked() : UNLOCKED, UNLOCKED);
|
|
3051
|
+
}
|
|
3052
|
+
|
|
2984
3053
|
// src/io/BackupPanel.tsx
|
|
2985
|
-
var
|
|
3054
|
+
var import_react18 = require("react");
|
|
2986
3055
|
var import_controls13 = require("@ai-matrx/design-system/controls");
|
|
2987
3056
|
var import_download = require("@ai-matrx/kit/download");
|
|
2988
3057
|
var import_confirm_opener4 = require("@ai-matrx/kit/confirm-opener");
|
|
@@ -3075,7 +3144,7 @@ function startNewRestoreRun(preview) {
|
|
|
3075
3144
|
}
|
|
3076
3145
|
|
|
3077
3146
|
// src/io/lines.tsx
|
|
3078
|
-
var
|
|
3147
|
+
var import_react17 = require("react");
|
|
3079
3148
|
var import_design_system11 = require("@ai-matrx/design-system");
|
|
3080
3149
|
var import_controls12 = require("@ai-matrx/design-system/controls");
|
|
3081
3150
|
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
@@ -3088,7 +3157,7 @@ function PickLine({ checked, onChange, disabled = false, title, detail, badge, t
|
|
|
3088
3157
|
] });
|
|
3089
3158
|
}
|
|
3090
3159
|
function Windowed({ items, size = 150, render }) {
|
|
3091
|
-
const [all, setAll] = (0,
|
|
3160
|
+
const [all, setAll] = (0, import_react17.useState)(false);
|
|
3092
3161
|
const shown = all ? items : items.slice(0, size);
|
|
3093
3162
|
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
3094
3163
|
shown.map(render),
|
|
@@ -3099,7 +3168,7 @@ function Windowed({ items, size = 150, render }) {
|
|
|
3099
3168
|
] });
|
|
3100
3169
|
}
|
|
3101
3170
|
function More({ title = "More", children }) {
|
|
3102
|
-
const [open, setOpen] = (0,
|
|
3171
|
+
const [open, setOpen] = (0, import_react17.useState)(false);
|
|
3103
3172
|
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
3104
3173
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_controls12.DisclosureHeader, { open, title, onClick: () => setOpen((o) => !o) }),
|
|
3105
3174
|
open ? children : null
|
|
@@ -3138,21 +3207,21 @@ function Omissions({ omissions, accepted, onAccepted, verb }) {
|
|
|
3138
3207
|
}
|
|
3139
3208
|
function BackupPanel({ port, items, onClose, onChanged }) {
|
|
3140
3209
|
const confirmed = useConfirmed();
|
|
3141
|
-
const fileInput = (0,
|
|
3142
|
-
const abort = (0,
|
|
3143
|
-
const [mode, setMode] = (0,
|
|
3144
|
-
const [busy, setBusy] = (0,
|
|
3145
|
-
const [error, setError] = (0,
|
|
3146
|
-
const [passphrase, setPassphrase] = (0,
|
|
3147
|
-
const [repeat, setRepeat] = (0,
|
|
3148
|
-
const [accepted, setAccepted] = (0,
|
|
3149
|
-
const [selected, setSelected] = (0,
|
|
3150
|
-
const [backup, setBackup] = (0,
|
|
3151
|
-
const [file, setFile] = (0,
|
|
3152
|
-
const [restorePreview, setRestorePreview] = (0,
|
|
3153
|
-
const [runId, setRunId] = (0,
|
|
3154
|
-
const [result, setResult] = (0,
|
|
3155
|
-
(0,
|
|
3210
|
+
const fileInput = (0, import_react18.useRef)(null);
|
|
3211
|
+
const abort = (0, import_react18.useRef)(null);
|
|
3212
|
+
const [mode, setMode] = (0, import_react18.useState)("backup");
|
|
3213
|
+
const [busy, setBusy] = (0, import_react18.useState)(false);
|
|
3214
|
+
const [error, setError] = (0, import_react18.useState)(null);
|
|
3215
|
+
const [passphrase, setPassphrase] = (0, import_react18.useState)("");
|
|
3216
|
+
const [repeat, setRepeat] = (0, import_react18.useState)("");
|
|
3217
|
+
const [accepted, setAccepted] = (0, import_react18.useState)(false);
|
|
3218
|
+
const [selected, setSelected] = (0, import_react18.useState)(/* @__PURE__ */ new Set());
|
|
3219
|
+
const [backup, setBackup] = (0, import_react18.useState)(null);
|
|
3220
|
+
const [file, setFile] = (0, import_react18.useState)(null);
|
|
3221
|
+
const [restorePreview, setRestorePreview] = (0, import_react18.useState)(null);
|
|
3222
|
+
const [runId, setRunId] = (0, import_react18.useState)(null);
|
|
3223
|
+
const [result, setResult] = (0, import_react18.useState)(null);
|
|
3224
|
+
(0, import_react18.useEffect)(() => () => abort.current?.abort(), []);
|
|
3156
3225
|
const switchMode = (next) => {
|
|
3157
3226
|
abort.current?.abort();
|
|
3158
3227
|
setMode(next);
|
|
@@ -3323,7 +3392,7 @@ function BackupPanel({ port, items, onClose, onChanged }) {
|
|
|
3323
3392
|
}
|
|
3324
3393
|
|
|
3325
3394
|
// src/io/ExportPanel.tsx
|
|
3326
|
-
var
|
|
3395
|
+
var import_react19 = require("react");
|
|
3327
3396
|
var import_controls14 = require("@ai-matrx/design-system/controls");
|
|
3328
3397
|
var import_download2 = require("@ai-matrx/kit/download");
|
|
3329
3398
|
var import_confirm_opener5 = require("@ai-matrx/kit/confirm-opener");
|
|
@@ -3347,12 +3416,12 @@ function omissionText2(omissions) {
|
|
|
3347
3416
|
}
|
|
3348
3417
|
function ExportPanel({ port, items, onClose }) {
|
|
3349
3418
|
const confirmed = useConfirmed();
|
|
3350
|
-
const logins = (0,
|
|
3351
|
-
const [profile, setProfile] = (0,
|
|
3352
|
-
const [selected, setSelected] = (0,
|
|
3353
|
-
const [preview, setPreview] = (0,
|
|
3354
|
-
const [busy, setBusy] = (0,
|
|
3355
|
-
const [error, setError] = (0,
|
|
3419
|
+
const logins = (0, import_react19.useMemo)(() => items.filter((i) => i.definitionKey === WEBSITE_LOGIN), [items]);
|
|
3420
|
+
const [profile, setProfile] = (0, import_react19.useState)("matrx_login_csv_v1");
|
|
3421
|
+
const [selected, setSelected] = (0, import_react19.useState)(/* @__PURE__ */ new Set());
|
|
3422
|
+
const [preview, setPreview] = (0, import_react19.useState)(null);
|
|
3423
|
+
const [busy, setBusy] = (0, import_react19.useState)(false);
|
|
3424
|
+
const [error, setError] = (0, import_react19.useState)(null);
|
|
3356
3425
|
const format = FORMATS.find((f) => f.value === profile);
|
|
3357
3426
|
const reasons = new Map(preview?.items.map((p) => [p.item_id, p]) ?? []);
|
|
3358
3427
|
const eligible = preview?.items.filter((p) => p.eligible).length ?? 0;
|
|
@@ -3477,7 +3546,7 @@ function ExportPanel({ port, items, onClose }) {
|
|
|
3477
3546
|
}
|
|
3478
3547
|
|
|
3479
3548
|
// src/io/ImportPanel.tsx
|
|
3480
|
-
var
|
|
3549
|
+
var import_react20 = require("react");
|
|
3481
3550
|
var import_controls15 = require("@ai-matrx/design-system/controls");
|
|
3482
3551
|
|
|
3483
3552
|
// src/io/csv-import.ts
|
|
@@ -4336,24 +4405,24 @@ var STATE_BADGE = {
|
|
|
4336
4405
|
var ME = "me";
|
|
4337
4406
|
function ImportPanel({ port, host, items, organizations, onClose, onChanged, limits }) {
|
|
4338
4407
|
const confirmed = useConfirmed();
|
|
4339
|
-
const fileInput = (0,
|
|
4340
|
-
const abort = (0,
|
|
4341
|
-
const stop = (0,
|
|
4342
|
-
const keys = (0,
|
|
4343
|
-
const [source, setSource] = (0,
|
|
4344
|
-
const [envText, setEnvText] = (0,
|
|
4345
|
-
const [injectSandbox, setInjectSandbox] = (0,
|
|
4346
|
-
const [fileName, setFileName] = (0,
|
|
4347
|
-
const [reading, setReading] = (0,
|
|
4348
|
-
const [draft, setDraft] = (0,
|
|
4349
|
-
const [destination, setDestination] = (0,
|
|
4350
|
-
const [browserFill, setBrowserFill] = (0,
|
|
4351
|
-
const [approvedVisible, setApprovedVisible] = (0,
|
|
4352
|
-
const [selected, setSelected] = (0,
|
|
4353
|
-
const [running, setRunning] = (0,
|
|
4354
|
-
const [done, setDone] = (0,
|
|
4355
|
-
const [error, setError] = (0,
|
|
4356
|
-
(0,
|
|
4408
|
+
const fileInput = (0, import_react20.useRef)(null);
|
|
4409
|
+
const abort = (0, import_react20.useRef)(null);
|
|
4410
|
+
const stop = (0, import_react20.useRef)(false);
|
|
4411
|
+
const keys = (0, import_react20.useRef)(/* @__PURE__ */ new Map());
|
|
4412
|
+
const [source, setSource] = (0, import_react20.useState)("auto");
|
|
4413
|
+
const [envText, setEnvText] = (0, import_react20.useState)("");
|
|
4414
|
+
const [injectSandbox, setInjectSandbox] = (0, import_react20.useState)(false);
|
|
4415
|
+
const [fileName, setFileName] = (0, import_react20.useState)(null);
|
|
4416
|
+
const [reading, setReading] = (0, import_react20.useState)(false);
|
|
4417
|
+
const [draft, setDraft] = (0, import_react20.useState)(null);
|
|
4418
|
+
const [destination, setDestination] = (0, import_react20.useState)(ME);
|
|
4419
|
+
const [browserFill, setBrowserFill] = (0, import_react20.useState)(false);
|
|
4420
|
+
const [approvedVisible, setApprovedVisible] = (0, import_react20.useState)(false);
|
|
4421
|
+
const [selected, setSelected] = (0, import_react20.useState)(/* @__PURE__ */ new Set());
|
|
4422
|
+
const [running, setRunning] = (0, import_react20.useState)(null);
|
|
4423
|
+
const [done, setDone] = (0, import_react20.useState)(null);
|
|
4424
|
+
const [error, setError] = (0, import_react20.useState)(null);
|
|
4425
|
+
(0, import_react20.useEffect)(
|
|
4357
4426
|
() => () => {
|
|
4358
4427
|
abort.current?.abort();
|
|
4359
4428
|
stop.current = true;
|
|
@@ -4362,9 +4431,9 @@ function ImportPanel({ port, host, items, organizations, onClose, onChanged, lim
|
|
|
4362
4431
|
);
|
|
4363
4432
|
const organizationId = destination === ME ? null : destination;
|
|
4364
4433
|
const existingIn = (org) => items.filter((i) => org === null ? i.owner.kind === "me" : i.owner.organizationId === org).map((i) => ({ displayName: i.name, loginUrls: i.loginUrls }));
|
|
4365
|
-
const existing = (0,
|
|
4366
|
-
const destinationOptions = (0,
|
|
4367
|
-
const lines = (0,
|
|
4434
|
+
const existing = (0, import_react20.useMemo)(() => existingIn(organizationId), [items, organizationId]);
|
|
4435
|
+
const destinationOptions = (0, import_react20.useMemo)(() => [{ value: ME, label: "Personal" }, ...organizations.map((o) => ({ value: o.id, label: o.name }))], [organizations]);
|
|
4436
|
+
const lines = (0, import_react20.useMemo)(
|
|
4368
4437
|
() => draft?.kind === "file" ? reviewLines(draft.parsed, { organizationId, browserFill, existing, limits, mapping: draft.mapping }) : [],
|
|
4369
4438
|
[draft, organizationId, browserFill, existing, limits]
|
|
4370
4439
|
);
|
|
@@ -4616,7 +4685,7 @@ function Notices({ draft }) {
|
|
|
4616
4685
|
}
|
|
4617
4686
|
|
|
4618
4687
|
// src/ItemList.tsx
|
|
4619
|
-
var
|
|
4688
|
+
var import_react28 = require("react");
|
|
4620
4689
|
var import_design_system18 = require("@ai-matrx/design-system");
|
|
4621
4690
|
var import_design_system19 = require("@ai-matrx/design-system");
|
|
4622
4691
|
var import_controls22 = require("@ai-matrx/design-system/controls");
|
|
@@ -4636,14 +4705,14 @@ function ItemIcon({ definitionKey, family, site, size = "md", inverted = false }
|
|
|
4636
4705
|
}
|
|
4637
4706
|
|
|
4638
4707
|
// src/ItemPane.tsx
|
|
4639
|
-
var
|
|
4708
|
+
var import_react27 = require("react");
|
|
4640
4709
|
var import_design_system16 = require("@ai-matrx/design-system");
|
|
4641
4710
|
var import_design_system17 = require("@ai-matrx/design-system");
|
|
4642
4711
|
var import_controls21 = require("@ai-matrx/design-system/controls");
|
|
4643
4712
|
var import_confirm_opener9 = require("@ai-matrx/kit/confirm-opener");
|
|
4644
4713
|
|
|
4645
4714
|
// src/activity/FilesSection.tsx
|
|
4646
|
-
var
|
|
4715
|
+
var import_react21 = require("react");
|
|
4647
4716
|
var import_controls16 = require("@ai-matrx/design-system/controls");
|
|
4648
4717
|
var import_design_system13 = require("@ai-matrx/design-system");
|
|
4649
4718
|
var import_confirm_opener6 = require("@ai-matrx/kit/confirm-opener");
|
|
@@ -4659,11 +4728,11 @@ var PROTECTION = [
|
|
|
4659
4728
|
function FilesSection({ item, port, editing, onChanged }) {
|
|
4660
4729
|
const confirmed = useConfirmed();
|
|
4661
4730
|
const canEdit = editing && item.capabilities.canEdit;
|
|
4662
|
-
const [busy, setBusy] = (0,
|
|
4663
|
-
const [error, setError] = (0,
|
|
4664
|
-
const [pending, setPending] = (0,
|
|
4665
|
-
const [dragging, setDragging] = (0,
|
|
4666
|
-
const picker = (0,
|
|
4731
|
+
const [busy, setBusy] = (0, import_react21.useState)(null);
|
|
4732
|
+
const [error, setError] = (0, import_react21.useState)(null);
|
|
4733
|
+
const [pending, setPending] = (0, import_react21.useState)(null);
|
|
4734
|
+
const [dragging, setDragging] = (0, import_react21.useState)(false);
|
|
4735
|
+
const picker = (0, import_react21.useRef)(null);
|
|
4667
4736
|
if (!canEdit && item.attachments.length === 0) return null;
|
|
4668
4737
|
async function run(key, work, fallback) {
|
|
4669
4738
|
setBusy(key);
|
|
@@ -4739,8 +4808,8 @@ function FilesSection({ item, port, editing, onChanged }) {
|
|
|
4739
4808
|
);
|
|
4740
4809
|
}
|
|
4741
4810
|
function EditableFile({ port, item: it, file: a, busy: b, run: go, onDownload, onTooBig }) {
|
|
4742
|
-
const [open, setOpen] = (0,
|
|
4743
|
-
const replacer = (0,
|
|
4811
|
+
const [open, setOpen] = (0, import_react21.useState)(false);
|
|
4812
|
+
const replacer = (0, import_react21.useRef)(null);
|
|
4744
4813
|
async function remove() {
|
|
4745
4814
|
const yes = await (0, import_confirm_opener6.confirm)({ title: `Delete ${a.label}?`, description: "The encrypted file is removed from this item.", confirmLabel: "Delete", variant: "destructive" });
|
|
4746
4815
|
if (yes) await go(`delete:${a.id}`, () => port.activity.deleteFile(it, a.id), "The file could not be deleted.");
|
|
@@ -4798,9 +4867,9 @@ function Protection({ value, locked, onChange }) {
|
|
|
4798
4867
|
);
|
|
4799
4868
|
}
|
|
4800
4869
|
function NewFile({ file, busy, onAdd, onCancel }) {
|
|
4801
|
-
const [label, setLabel] = (0,
|
|
4802
|
-
const [description, setDescription] = (0,
|
|
4803
|
-
const [handling, setHandling] = (0,
|
|
4870
|
+
const [label, setLabel] = (0, import_react21.useState)(file.name);
|
|
4871
|
+
const [description, setDescription] = (0, import_react21.useState)("");
|
|
4872
|
+
const [handling, setHandling] = (0, import_react21.useState)("revealable");
|
|
4804
4873
|
async function add() {
|
|
4805
4874
|
if (handling === "sealed" && !await confirmSeal(label)) return;
|
|
4806
4875
|
await onAdd({ label: label.trim(), description: description.trim() || null, handling });
|
|
@@ -4820,10 +4889,10 @@ function NewFile({ file, busy, onAdd, onCancel }) {
|
|
|
4820
4889
|
] });
|
|
4821
4890
|
}
|
|
4822
4891
|
function FileDetailsRows({ file, busy, onSave, onCancel }) {
|
|
4823
|
-
const [label, setLabel] = (0,
|
|
4824
|
-
const [description, setDescription] = (0,
|
|
4825
|
-
const [fileName, setFileName] = (0,
|
|
4826
|
-
const [handling, setHandling] = (0,
|
|
4892
|
+
const [label, setLabel] = (0, import_react21.useState)(file.label);
|
|
4893
|
+
const [description, setDescription] = (0, import_react21.useState)(file.description);
|
|
4894
|
+
const [fileName, setFileName] = (0, import_react21.useState)(file.fileName);
|
|
4895
|
+
const [handling, setHandling] = (0, import_react21.useState)(file.handling);
|
|
4827
4896
|
const changed = label !== file.label || description !== file.description || fileName !== file.fileName || handling !== file.handling;
|
|
4828
4897
|
async function save() {
|
|
4829
4898
|
if (handling === "sealed" && file.handling !== "sealed" && !await confirmSeal(label)) return;
|
|
@@ -4850,18 +4919,18 @@ function confirmSeal(label) {
|
|
|
4850
4919
|
}
|
|
4851
4920
|
|
|
4852
4921
|
// src/fields/RecoveryCodesRow.tsx
|
|
4853
|
-
var
|
|
4922
|
+
var import_react22 = require("react");
|
|
4854
4923
|
var import_controls17 = require("@ai-matrx/design-system/controls");
|
|
4855
4924
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
4856
4925
|
var MASK4 = "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
|
|
4857
4926
|
var say2 = (e, fallback) => e instanceof Error && e.message ? e.message : fallback;
|
|
4858
4927
|
function RecoveryCodesRow({ item, field, port, onChanged }) {
|
|
4859
4928
|
const confirmed = useConfirmed();
|
|
4860
|
-
const
|
|
4929
|
+
const copyValue2 = useCopy();
|
|
4861
4930
|
const secret = useTransientSecret();
|
|
4862
|
-
const [busy, setBusy] = (0,
|
|
4863
|
-
const [error, setError] = (0,
|
|
4864
|
-
const [draft, setDraft] = (0,
|
|
4931
|
+
const [busy, setBusy] = (0, import_react22.useState)(false);
|
|
4932
|
+
const [error, setError] = (0, import_react22.useState)(null);
|
|
4933
|
+
const [draft, setDraft] = (0, import_react22.useState)(null);
|
|
4865
4934
|
const canEdit = item.capabilities.canEdit;
|
|
4866
4935
|
const run = async (step) => {
|
|
4867
4936
|
setBusy(true);
|
|
@@ -4945,7 +5014,7 @@ function RecoveryCodesRow({ item, field, port, onChanged }) {
|
|
|
4945
5014
|
children: sealed ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_controls17.Badge, { icon: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LockGlyph, {}), children: "Sealed" }) : codes ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("ul", { className: "flex flex-col gap-0.5", "aria-label": "Recovery codes", children: [
|
|
4946
5015
|
codes.map((code, i) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("li", { className: "flex min-h-7 items-center gap-1", children: [
|
|
4947
5016
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("code", { className: "min-w-0 flex-1 break-all font-mono text-sm text-foreground", children: code }),
|
|
4948
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_controls17.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CopyGlyph, {}), "aria-label": `Copy code ${i + 1}`, onClick: () => void
|
|
5017
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_controls17.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CopyGlyph, {}), "aria-label": `Copy code ${i + 1}`, onClick: () => void copyValue2(code, "Recovery code") }),
|
|
4949
5018
|
canEdit ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_controls17.Button, { variant: "quiet", icon: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CheckGlyph, {}), disabled: busy, onClick: () => void markUsed(i), children: "Mark used" }) : null
|
|
4950
5019
|
] }, `${i}-${code}`)),
|
|
4951
5020
|
error ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("li", { role: "alert", className: "text-xs text-destructive", children: error }) : null
|
|
@@ -5096,7 +5165,7 @@ function targetLabel(t) {
|
|
|
5096
5165
|
}
|
|
5097
5166
|
|
|
5098
5167
|
// src/extension/UseOnSiteButton.tsx
|
|
5099
|
-
var
|
|
5168
|
+
var import_react23 = require("react");
|
|
5100
5169
|
var import_controls18 = require("@ai-matrx/design-system/controls");
|
|
5101
5170
|
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
5102
5171
|
function canUseOnSite(item, pageUrl) {
|
|
@@ -5104,7 +5173,7 @@ function canUseOnSite(item, pageUrl) {
|
|
|
5104
5173
|
}
|
|
5105
5174
|
function UseOnSiteButton({ port, item, pageUrl, onChanged }) {
|
|
5106
5175
|
const notify = useNotify();
|
|
5107
|
-
const [busy, setBusy] = (0,
|
|
5176
|
+
const [busy, setBusy] = (0, import_react23.useState)(false);
|
|
5108
5177
|
if (!canUseOnSite(item, pageUrl)) return null;
|
|
5109
5178
|
const site = pageSite(pageUrl);
|
|
5110
5179
|
const run = async () => {
|
|
@@ -5123,7 +5192,7 @@ function UseOnSiteButton({ port, item, pageUrl, onChanged }) {
|
|
|
5123
5192
|
}
|
|
5124
5193
|
|
|
5125
5194
|
// src/sharing/SharePanel.tsx
|
|
5126
|
-
var
|
|
5195
|
+
var import_react26 = require("react");
|
|
5127
5196
|
var import_confirm_opener8 = require("@ai-matrx/kit/confirm-opener");
|
|
5128
5197
|
var import_controls20 = require("@ai-matrx/design-system/controls");
|
|
5129
5198
|
var import_design_system15 = require("@ai-matrx/design-system");
|
|
@@ -5137,7 +5206,7 @@ var MEMBER_ACCESS_LABEL = { none: "No access", use: "Can use", editor: "Can edit
|
|
|
5137
5206
|
function levelOf(flags) {
|
|
5138
5207
|
return flags.can_manage ? "edit" : "use";
|
|
5139
5208
|
}
|
|
5140
|
-
function
|
|
5209
|
+
function shareFlagsOf(level) {
|
|
5141
5210
|
return { can_use: true, can_manage: level === "edit" };
|
|
5142
5211
|
}
|
|
5143
5212
|
function isEmail(value) {
|
|
@@ -5180,7 +5249,7 @@ function shareSummary(grants) {
|
|
|
5180
5249
|
var MEMBER_CHOICE_DEFAULT = "default";
|
|
5181
5250
|
|
|
5182
5251
|
// src/sharing/parts.tsx
|
|
5183
|
-
var
|
|
5252
|
+
var import_react24 = require("react");
|
|
5184
5253
|
var import_design_system14 = require("@ai-matrx/design-system");
|
|
5185
5254
|
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
5186
5255
|
var message = (e, fallback) => {
|
|
@@ -5189,9 +5258,9 @@ var message = (e, fallback) => {
|
|
|
5189
5258
|
};
|
|
5190
5259
|
function useAction() {
|
|
5191
5260
|
const confirmed = useConfirmed();
|
|
5192
|
-
const [busy, setBusy] = (0,
|
|
5193
|
-
const [error, setError] = (0,
|
|
5194
|
-
const [notice, setNotice] = (0,
|
|
5261
|
+
const [busy, setBusy] = (0, import_react24.useState)(null);
|
|
5262
|
+
const [error, setError] = (0, import_react24.useState)(null);
|
|
5263
|
+
const [notice, setNotice] = (0, import_react24.useState)(null);
|
|
5195
5264
|
async function run(key, fn, done) {
|
|
5196
5265
|
setBusy(key);
|
|
5197
5266
|
setError(null);
|
|
@@ -5225,7 +5294,7 @@ function StatusLine({ error, notice }) {
|
|
|
5225
5294
|
}
|
|
5226
5295
|
|
|
5227
5296
|
// src/sharing/MovePanel.tsx
|
|
5228
|
-
var
|
|
5297
|
+
var import_react25 = require("react");
|
|
5229
5298
|
var import_confirm_opener7 = require("@ai-matrx/kit/confirm-opener");
|
|
5230
5299
|
var import_controls19 = require("@ai-matrx/design-system/controls");
|
|
5231
5300
|
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
@@ -5234,9 +5303,9 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
|
|
|
5234
5303
|
const { busy, error, notice, run, setNotice } = useAction();
|
|
5235
5304
|
const moves = moveDestinations(item, organizations);
|
|
5236
5305
|
const copies = copyDestinations(organizations, item);
|
|
5237
|
-
const [moveTo, setMoveTo] = (0,
|
|
5238
|
-
const [copyTo, setCopyTo] = (0,
|
|
5239
|
-
const [email, setEmail] = (0,
|
|
5306
|
+
const [moveTo, setMoveTo] = (0, import_react25.useState)("");
|
|
5307
|
+
const [copyTo, setCopyTo] = (0, import_react25.useState)("");
|
|
5308
|
+
const [email, setEmail] = (0, import_react25.useState)("");
|
|
5240
5309
|
const passkey = isPasskey(item);
|
|
5241
5310
|
const canMove = item.capabilities.canManage && !passkey && moves.length > 0;
|
|
5242
5311
|
const canGive = item.capabilities.canManage && item.owner.kind === "me" && !passkey;
|
|
@@ -5317,11 +5386,11 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
|
|
|
5317
5386
|
// src/sharing/SharePanel.tsx
|
|
5318
5387
|
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
5319
5388
|
function useGrants(port, item) {
|
|
5320
|
-
const [grants, setGrants] = (0,
|
|
5321
|
-
const [loadError, setLoadError] = (0,
|
|
5322
|
-
const [nonce, setNonce] = (0,
|
|
5389
|
+
const [grants, setGrants] = (0, import_react26.useState)(null);
|
|
5390
|
+
const [loadError, setLoadError] = (0, import_react26.useState)(null);
|
|
5391
|
+
const [nonce, setNonce] = (0, import_react26.useState)(0);
|
|
5323
5392
|
const allowed = item.capabilities.canManage;
|
|
5324
|
-
(0,
|
|
5393
|
+
(0, import_react26.useEffect)(() => {
|
|
5325
5394
|
if (!allowed) return;
|
|
5326
5395
|
let live = true;
|
|
5327
5396
|
setLoadError(null);
|
|
@@ -5338,9 +5407,9 @@ function useGrants(port, item) {
|
|
|
5338
5407
|
function SharePanel({ item, port, organizations, onClose, onChanged }) {
|
|
5339
5408
|
const { grants, setGrants, loadError, reload } = useGrants(port, item);
|
|
5340
5409
|
const { busy, error, notice, run } = useAction();
|
|
5341
|
-
const [email, setEmail] = (0,
|
|
5342
|
-
const [level, setLevel] = (0,
|
|
5343
|
-
const [more, setMore] = (0,
|
|
5410
|
+
const [email, setEmail] = (0, import_react26.useState)("");
|
|
5411
|
+
const [level, setLevel] = (0, import_react26.useState)("use");
|
|
5412
|
+
const [more, setMore] = (0, import_react26.useState)(false);
|
|
5344
5413
|
const isOrg = item.owner.kind === "organization" && item.owner.organizationId !== null;
|
|
5345
5414
|
const orgName = item.owner.label;
|
|
5346
5415
|
const people = (grants ?? []).filter((g) => g.kind === "person");
|
|
@@ -5462,8 +5531,8 @@ function SharePanel({ item, port, organizations, onClose, onChanged }) {
|
|
|
5462
5531
|
function IntoOrganization({ item, port, organizations, grants, onShared }) {
|
|
5463
5532
|
const { busy, error, notice, run } = useAction();
|
|
5464
5533
|
const open = organizations.filter((o) => !grants.some((g) => g.organizationId === o.id));
|
|
5465
|
-
const [target, setTarget] = (0,
|
|
5466
|
-
const [level, setLevel] = (0,
|
|
5534
|
+
const [target, setTarget] = (0, import_react26.useState)("");
|
|
5535
|
+
const [level, setLevel] = (0, import_react26.useState)("use");
|
|
5467
5536
|
const chosen = open.find((o) => o.id === target);
|
|
5468
5537
|
if (item.owner.kind !== "me") return null;
|
|
5469
5538
|
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Section, { title: "Share into organization", children: open.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
@@ -5498,10 +5567,10 @@ var CHOICES = [
|
|
|
5498
5567
|
{ value: "editor", label: "Can edit", meta: "See and change" }
|
|
5499
5568
|
];
|
|
5500
5569
|
function MemberAccess({ port, organizationId, organizationName }) {
|
|
5501
|
-
const [list, setList] = (0,
|
|
5502
|
-
const [loadError, setLoadError] = (0,
|
|
5570
|
+
const [list, setList] = (0, import_react26.useState)(null);
|
|
5571
|
+
const [loadError, setLoadError] = (0, import_react26.useState)(null);
|
|
5503
5572
|
const { busy, error, run } = useAction();
|
|
5504
|
-
(0,
|
|
5573
|
+
(0, import_react26.useEffect)(() => {
|
|
5505
5574
|
let live = true;
|
|
5506
5575
|
port.sharing.memberAccess(organizationId).then(
|
|
5507
5576
|
(l) => live && setList(l),
|
|
@@ -5533,9 +5602,9 @@ function MemberAccess({ port, organizationId, organizationName }) {
|
|
|
5533
5602
|
] });
|
|
5534
5603
|
}
|
|
5535
5604
|
function SharingSummary({ item, port, className }) {
|
|
5536
|
-
const [text, setText] = (0,
|
|
5605
|
+
const [text, setText] = (0, import_react26.useState)("");
|
|
5537
5606
|
const allowed = item.capabilities.canManage;
|
|
5538
|
-
(0,
|
|
5607
|
+
(0, import_react26.useEffect)(() => {
|
|
5539
5608
|
if (!allowed) return;
|
|
5540
5609
|
let live = true;
|
|
5541
5610
|
port.sharing.grants(item).then(
|
|
@@ -5551,6 +5620,7 @@ function SharingSummary({ item, port, className }) {
|
|
|
5551
5620
|
}
|
|
5552
5621
|
|
|
5553
5622
|
// src/ItemPane.tsx
|
|
5623
|
+
var import_format4 = require("@ai-matrx/kit/format");
|
|
5554
5624
|
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
5555
5625
|
var USERNAME_KEYS = /^(username|user_name|email|login|username_or_email|account_email)$/;
|
|
5556
5626
|
function ItemPane(props) {
|
|
@@ -5560,8 +5630,8 @@ function ItemPane(props) {
|
|
|
5560
5630
|
const editing = mode !== "view";
|
|
5561
5631
|
const seedName = seed?.name ?? "";
|
|
5562
5632
|
const seedUrl = seed?.url ?? "";
|
|
5563
|
-
const [loaded, setLoaded] = (0,
|
|
5564
|
-
const base = (0,
|
|
5633
|
+
const [loaded, setLoaded] = (0, import_react27.useState)({});
|
|
5634
|
+
const base = (0, import_react27.useMemo)(() => {
|
|
5565
5635
|
const b = draftOf(item);
|
|
5566
5636
|
if (!item) {
|
|
5567
5637
|
b.name = seedName;
|
|
@@ -5570,22 +5640,22 @@ function ItemPane(props) {
|
|
|
5570
5640
|
b.values = { ...loaded };
|
|
5571
5641
|
return b;
|
|
5572
5642
|
}, [item, seedName, seedUrl, loaded]);
|
|
5573
|
-
const [draft, setDraft] = (0,
|
|
5574
|
-
const [tagsText, setTagsText] = (0,
|
|
5575
|
-
const [showTags, setShowTags] = (0,
|
|
5576
|
-
const [showDescription, setShowDescription] = (0,
|
|
5577
|
-
const [owner, setOwner] = (0,
|
|
5578
|
-
const [recipient, setRecipient] = (0,
|
|
5579
|
-
const [generatePrivately, setGeneratePrivately] = (0,
|
|
5580
|
-
const [busy, setBusy] = (0,
|
|
5581
|
-
const [error, setError] = (0,
|
|
5582
|
-
const [destinations, setDestinations] = (0,
|
|
5643
|
+
const [draft, setDraft] = (0, import_react27.useState)(base);
|
|
5644
|
+
const [tagsText, setTagsText] = (0, import_react27.useState)(base.tags.join(", "));
|
|
5645
|
+
const [showTags, setShowTags] = (0, import_react27.useState)(false);
|
|
5646
|
+
const [showDescription, setShowDescription] = (0, import_react27.useState)(false);
|
|
5647
|
+
const [owner, setOwner] = (0, import_react27.useState)(defaultOwner ?? "me");
|
|
5648
|
+
const [recipient, setRecipient] = (0, import_react27.useState)("");
|
|
5649
|
+
const [generatePrivately, setGeneratePrivately] = (0, import_react27.useState)(false);
|
|
5650
|
+
const [busy, setBusy] = (0, import_react27.useState)(false);
|
|
5651
|
+
const [error, setError] = (0, import_react27.useState)(null);
|
|
5652
|
+
const [destinations, setDestinations] = (0, import_react27.useState)({});
|
|
5583
5653
|
const dirty = editing && isDirty(base, draft);
|
|
5584
5654
|
const declared = definition?.fields ?? [];
|
|
5585
|
-
const prev = (0,
|
|
5586
|
-
const paneRef = (0,
|
|
5655
|
+
const prev = (0, import_react27.useRef)(null);
|
|
5656
|
+
const paneRef = (0, import_react27.useRef)(null);
|
|
5587
5657
|
const room = useRoomOf(paneRef);
|
|
5588
|
-
(0,
|
|
5658
|
+
(0, import_react27.useEffect)(() => {
|
|
5589
5659
|
const was = prev.current;
|
|
5590
5660
|
const id = item?.id ?? null;
|
|
5591
5661
|
if (was && was.id === id && was.mode === mode && editing) {
|
|
@@ -5598,18 +5668,18 @@ function ItemPane(props) {
|
|
|
5598
5668
|
}
|
|
5599
5669
|
prev.current = { base, id, mode };
|
|
5600
5670
|
}, [base, mode, item?.id, editing]);
|
|
5601
|
-
(0,
|
|
5671
|
+
(0, import_react27.useEffect)(() => {
|
|
5602
5672
|
setLoaded({});
|
|
5603
5673
|
setShowTags(false);
|
|
5604
5674
|
setShowDescription(false);
|
|
5605
5675
|
}, [item?.id, mode]);
|
|
5606
|
-
(0,
|
|
5676
|
+
(0, import_react27.useEffect)(() => onDirty(dirty), [dirty, onDirty]);
|
|
5607
5677
|
const keepKey = draftKey(item?.id ?? null, definition?.key ?? item?.definitionKey ?? null);
|
|
5608
|
-
(0,
|
|
5678
|
+
(0, import_react27.useEffect)(() => {
|
|
5609
5679
|
if (editing && dirty) keepDraft(keepKey, item?.updatedAt ?? "new", draft);
|
|
5610
5680
|
else if (!editing) dropKeptDraft(keepKey);
|
|
5611
5681
|
}, [editing, dirty, draft, keepKey, item?.updatedAt]);
|
|
5612
|
-
(0,
|
|
5682
|
+
(0, import_react27.useEffect)(() => {
|
|
5613
5683
|
if (!editing || !item) return;
|
|
5614
5684
|
let live = true;
|
|
5615
5685
|
for (const f of item.fields) {
|
|
@@ -5698,7 +5768,7 @@ function ItemPane(props) {
|
|
|
5698
5768
|
const descriptionVisible = showDescription || draft.description !== "";
|
|
5699
5769
|
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: [
|
|
5700
5770
|
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,
|
|
5701
|
-
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ItemIcon, { definitionKey: definition?.key ?? item?.definitionKey ?? "custom", family: definition?.family ?? "generic", site: item ?
|
|
5771
|
+
/* @__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" }),
|
|
5702
5772
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col", children: [
|
|
5703
5773
|
/* @__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 }),
|
|
5704
5774
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "flex min-w-0 items-center gap-1 text-xs text-muted-foreground", children: [
|
|
@@ -5931,9 +6001,9 @@ function ItemPane(props) {
|
|
|
5931
6001
|
filesProps ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(FilesSection, { ...filesProps, editing: false }) : null,
|
|
5932
6002
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("p", { className: (0, import_design_system17.cn)("px-1 text-xs text-muted-foreground"), children: [
|
|
5933
6003
|
"Modified ",
|
|
5934
|
-
|
|
6004
|
+
(0, import_format4.formatAbsoluteDate)(item.updatedAt, DAY_FORMAT, ""),
|
|
5935
6005
|
" \xB7 Created ",
|
|
5936
|
-
|
|
6006
|
+
(0, import_format4.formatAbsoluteDate)(item.createdAt, DAY_FORMAT, "")
|
|
5937
6007
|
] })
|
|
5938
6008
|
] }) : null }) })
|
|
5939
6009
|
] }) });
|
|
@@ -5948,15 +6018,15 @@ var SORTS2 = [
|
|
|
5948
6018
|
{ value: "created", label: "Recently added" }
|
|
5949
6019
|
];
|
|
5950
6020
|
function subtitleOf(item, withOwner) {
|
|
5951
|
-
const what =
|
|
6021
|
+
const what = loginSiteOf(item) || item.definitionLabel;
|
|
5952
6022
|
return withOwner ? `${what} \xB7 ${item.owner.label}` : what;
|
|
5953
6023
|
}
|
|
5954
6024
|
function ItemList({ title, items, definitions, port, selectedId, onSelect, query, onQuery, sort, onSort, onNew, matchingIds, header }) {
|
|
5955
6025
|
const pinned = matchingIds ? items.filter((i) => matchingIds.has(i.id)) : [];
|
|
5956
6026
|
const rest = matchingIds ? items.filter((i) => !matchingIds.has(i.id)) : items;
|
|
5957
6027
|
const ordered = [...pinned, ...rest];
|
|
5958
|
-
const listRef = (0,
|
|
5959
|
-
(0,
|
|
6028
|
+
const listRef = (0, import_react28.useRef)(null);
|
|
6029
|
+
(0, import_react28.useEffect)(() => {
|
|
5960
6030
|
if (selectedId) listRef.current?.querySelector(`[data-item="${selectedId}"]`)?.scrollIntoView({ block: "nearest" });
|
|
5961
6031
|
}, [selectedId, items.length]);
|
|
5962
6032
|
const familyOf2 = (key) => definitions.find((d) => d.key === key)?.family ?? "generic";
|
|
@@ -6007,14 +6077,14 @@ function ListRow({ item, family, port, on, onSelect, withOwner }) {
|
|
|
6007
6077
|
const confirmed = useConfirmed();
|
|
6008
6078
|
const copy = useCopy();
|
|
6009
6079
|
const notify = useNotify();
|
|
6010
|
-
const [busy, setBusy] = (0,
|
|
6080
|
+
const [busy, setBusy] = (0, import_react28.useState)(false);
|
|
6011
6081
|
const user = item.fields.find((f) => USERNAME_KEYS.test(f.key) && f.handling !== "sealed");
|
|
6012
6082
|
const secret = item.fields.find((f) => f.key === "password" && f.handling === "revealable");
|
|
6013
6083
|
const quick = async (key, label) => {
|
|
6014
6084
|
setBusy(true);
|
|
6015
6085
|
try {
|
|
6016
6086
|
const v = await confirmed(() => port.reveal(item, key));
|
|
6017
|
-
await copy(v, label);
|
|
6087
|
+
await copy(v, label, { secret: key !== user?.key || user.handling !== "visible" });
|
|
6018
6088
|
} catch (e) {
|
|
6019
6089
|
if (!wasCancelled(e)) notify(e instanceof Error ? e.message : `${label} could not be read`, "error");
|
|
6020
6090
|
} finally {
|
|
@@ -6031,7 +6101,7 @@ function ListRow({ item, family, port, on, onSelect, withOwner }) {
|
|
|
6031
6101
|
onClick: () => onSelect(item.id),
|
|
6032
6102
|
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"),
|
|
6033
6103
|
children: [
|
|
6034
|
-
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ItemIcon, { definitionKey: item.definitionKey, family, site:
|
|
6104
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ItemIcon, { definitionKey: item.definitionKey, family, site: loginSiteOf(item), inverted: on }),
|
|
6035
6105
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "flex min-w-0 flex-1 flex-col leading-tight", children: [
|
|
6036
6106
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "truncate text-sm font-medium", children: item.name }),
|
|
6037
6107
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "truncate text-xs text-muted-foreground", children: subtitleOf(item, withOwner) })
|
|
@@ -6047,8 +6117,9 @@ function ListRow({ item, family, port, on, onSelect, withOwner }) {
|
|
|
6047
6117
|
}
|
|
6048
6118
|
|
|
6049
6119
|
// src/lists/TrashView.tsx
|
|
6050
|
-
var
|
|
6120
|
+
var import_react30 = require("react");
|
|
6051
6121
|
var import_controls24 = require("@ai-matrx/design-system/controls");
|
|
6122
|
+
var import_format5 = require("@ai-matrx/kit/format");
|
|
6052
6123
|
|
|
6053
6124
|
// src/lists/logic.ts
|
|
6054
6125
|
var ENTITY_TYPE = "credential_item";
|
|
@@ -6059,7 +6130,7 @@ function favoriteIds(data) {
|
|
|
6059
6130
|
function recentIds(data, limit = 50) {
|
|
6060
6131
|
return rowsOf(data).filter((r) => typeof r.last_viewed_at === "string" && r.last_viewed_at !== "").sort((a, b) => Date.parse(b.last_viewed_at) - Date.parse(a.last_viewed_at)).slice(0, limit).map((r) => r.entity_id);
|
|
6061
6132
|
}
|
|
6062
|
-
function
|
|
6133
|
+
function trashItemMatchesQuery(item, query) {
|
|
6063
6134
|
const q = query.trim().toLowerCase();
|
|
6064
6135
|
if (!q) return true;
|
|
6065
6136
|
return [item.name, item.definitionLabel, item.owner.label, ...item.tags].some((s) => s.toLowerCase().includes(q));
|
|
@@ -6120,16 +6191,16 @@ function refusalText(reason) {
|
|
|
6120
6191
|
}
|
|
6121
6192
|
|
|
6122
6193
|
// src/lists/RestorePanel.tsx
|
|
6123
|
-
var
|
|
6194
|
+
var import_react29 = require("react");
|
|
6124
6195
|
var import_controls23 = require("@ai-matrx/design-system/controls");
|
|
6125
6196
|
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
6126
6197
|
var count = (n, one) => `${n} ${one}${n === 1 ? "" : "s"}`;
|
|
6127
6198
|
function RestorePanel({ lists, item, restore, onClose }) {
|
|
6128
|
-
const [preview, setPreview] = (0,
|
|
6129
|
-
const [error, setError] = (0,
|
|
6130
|
-
const [busy, setBusy] = (0,
|
|
6131
|
-
const [loading, setLoading] = (0,
|
|
6132
|
-
(0,
|
|
6199
|
+
const [preview, setPreview] = (0, import_react29.useState)(null);
|
|
6200
|
+
const [error, setError] = (0, import_react29.useState)(null);
|
|
6201
|
+
const [busy, setBusy] = (0, import_react29.useState)(false);
|
|
6202
|
+
const [loading, setLoading] = (0, import_react29.useState)(Boolean(lists.preview));
|
|
6203
|
+
(0, import_react29.useEffect)(() => {
|
|
6133
6204
|
if (!lists.preview) return;
|
|
6134
6205
|
let live = true;
|
|
6135
6206
|
lists.preview(item).then(
|
|
@@ -6189,10 +6260,10 @@ function RestorePanel({ lists, item, restore, onClose }) {
|
|
|
6189
6260
|
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
6190
6261
|
function TrashView({ port, deleted, query, header, onChanged }) {
|
|
6191
6262
|
const confirmed = useConfirmed();
|
|
6192
|
-
const [busyId, setBusyId] = (0,
|
|
6193
|
-
const [message2, setMessage] = (0,
|
|
6194
|
-
const shown = deleted.filter((i) =>
|
|
6195
|
-
const [restoring, setRestoring] = (0,
|
|
6263
|
+
const [busyId, setBusyId] = (0, import_react30.useState)(null);
|
|
6264
|
+
const [message2, setMessage] = (0, import_react30.useState)(null);
|
|
6265
|
+
const shown = deleted.filter((i) => trashItemMatchesQuery(i, query));
|
|
6266
|
+
const [restoring, setRestoring] = (0, import_react30.useState)(null);
|
|
6196
6267
|
const restore = async (item, deletionId) => {
|
|
6197
6268
|
setBusyId(item.id);
|
|
6198
6269
|
setMessage(null);
|
|
@@ -6216,7 +6287,7 @@ function TrashView({ port, deleted, query, header, onChanged }) {
|
|
|
6216
6287
|
/* @__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: [
|
|
6217
6288
|
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("span", { className: "flex min-w-0 flex-1 flex-col leading-tight", children: [
|
|
6218
6289
|
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "truncate text-sm text-foreground", children: item.name }),
|
|
6219
|
-
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "truncate text-xs text-muted-foreground", children: [item.deletion?.deletedAt ? `Deleted ${
|
|
6290
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "truncate text-xs text-muted-foreground", children: [item.deletion?.deletedAt ? `Deleted ${(0, import_format5.formatAbsoluteDate)(item.deletion.deletedAt, DAY_FORMAT, "")}` : null, item.owner.kind !== "me" ? item.owner.label : null].filter(Boolean).join(" \xB7 ") })
|
|
6220
6291
|
] }),
|
|
6221
6292
|
/* @__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" })
|
|
6222
6293
|
] }, item.id)
|
|
@@ -6227,15 +6298,15 @@ function TrashView({ port, deleted, query, header, onChanged }) {
|
|
|
6227
6298
|
}
|
|
6228
6299
|
|
|
6229
6300
|
// src/NewItemFlow.tsx
|
|
6230
|
-
var
|
|
6301
|
+
var import_react31 = require("react");
|
|
6231
6302
|
var import_design_system20 = require("@ai-matrx/design-system");
|
|
6232
6303
|
var import_controls25 = require("@ai-matrx/design-system/controls");
|
|
6233
6304
|
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
6234
6305
|
function NewItemFlow({ definitions, url, onUrl, onChoose, onCancel }) {
|
|
6235
|
-
const [search, setSearch] = (0,
|
|
6236
|
-
const guess = (0,
|
|
6306
|
+
const [search, setSearch] = (0, import_react31.useState)("");
|
|
6307
|
+
const guess = (0, import_react31.useMemo)(() => inferFromUrl(url, definitions), [url, definitions]);
|
|
6237
6308
|
const common = COMMON_DEFINITION_KEYS.map((k) => definitions.find((d) => d.key === k)).filter((d) => d !== void 0);
|
|
6238
|
-
const matches = (0,
|
|
6309
|
+
const matches = (0, import_react31.useMemo)(() => {
|
|
6239
6310
|
const q = search.trim().toLowerCase();
|
|
6240
6311
|
if (!q) return [];
|
|
6241
6312
|
return definitions.filter((d) => `${d.label} ${d.key} ${d.providerKey ?? ""} ${FAMILY_LABELS[d.family] ?? ""}`.toLowerCase().includes(q)).slice(0, 60);
|
|
@@ -6299,13 +6370,14 @@ function NewItemFlow({ definitions, url, onUrl, onChoose, onCancel }) {
|
|
|
6299
6370
|
}
|
|
6300
6371
|
|
|
6301
6372
|
// src/sharing/SecureLinkPanel.tsx
|
|
6302
|
-
var
|
|
6373
|
+
var import_react32 = require("react");
|
|
6303
6374
|
var import_confirm_opener10 = require("@ai-matrx/kit/confirm-opener");
|
|
6304
6375
|
var import_design_system21 = require("@ai-matrx/design-system");
|
|
6305
6376
|
var import_controls26 = require("@ai-matrx/design-system/controls");
|
|
6377
|
+
var import_format7 = require("@ai-matrx/kit/format");
|
|
6306
6378
|
|
|
6307
6379
|
// src/sharing/secure-link-logic.ts
|
|
6308
|
-
var
|
|
6380
|
+
var import_format6 = require("@ai-matrx/kit/format");
|
|
6309
6381
|
var SECURE_RESOURCE_TYPE = "credential_item";
|
|
6310
6382
|
var NOTE_MAX = 1e3;
|
|
6311
6383
|
var CHANNEL_WORD = { email: "email", sms: "text" };
|
|
@@ -6343,7 +6415,7 @@ function carriedWords(keys, fields) {
|
|
|
6343
6415
|
const known = new Map(fields.map((f) => [f.key, f.label]));
|
|
6344
6416
|
return keys.map((k) => known.get(k) ?? fieldNames([k])).join(", ");
|
|
6345
6417
|
}
|
|
6346
|
-
var lifetimeWords = (minutes) => (0,
|
|
6418
|
+
var lifetimeWords = (minutes) => (0, import_format6.formatDurationMinutes)(minutes, { style: "long" });
|
|
6347
6419
|
function remedyOf(e) {
|
|
6348
6420
|
const body = e?.serverDetail;
|
|
6349
6421
|
if (!body || typeof body !== "object") return null;
|
|
@@ -6381,20 +6453,20 @@ var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
|
6381
6453
|
function SecureLinkPanel({ item, port, onClose }) {
|
|
6382
6454
|
const sharing = port.sharing;
|
|
6383
6455
|
const { busy, error, notice, run, setNotice } = useAction();
|
|
6384
|
-
const [remedy, setRemedy] = (0,
|
|
6385
|
-
const [options, setOptions] = (0,
|
|
6386
|
-
const [optionsError, setOptionsError] = (0,
|
|
6387
|
-
const [sent, setSent] = (0,
|
|
6388
|
-
const [sentError, setSentError] = (0,
|
|
6389
|
-
const [nonce, setNonce] = (0,
|
|
6390
|
-
const [email, setEmail] = (0,
|
|
6391
|
-
const [phone, setPhone] = (0,
|
|
6392
|
-
const [name, setName] = (0,
|
|
6393
|
-
const [linkBy, setLinkBy] = (0,
|
|
6394
|
-
const [fields, setFields] = (0,
|
|
6395
|
-
const [note, setNote] = (0,
|
|
6396
|
-
const [sameChannelSent, setSameChannelSent] = (0,
|
|
6397
|
-
(0,
|
|
6456
|
+
const [remedy, setRemedy] = (0, import_react32.useState)(null);
|
|
6457
|
+
const [options, setOptions] = (0, import_react32.useState)(null);
|
|
6458
|
+
const [optionsError, setOptionsError] = (0, import_react32.useState)(null);
|
|
6459
|
+
const [sent, setSent] = (0, import_react32.useState)(null);
|
|
6460
|
+
const [sentError, setSentError] = (0, import_react32.useState)(null);
|
|
6461
|
+
const [nonce, setNonce] = (0, import_react32.useState)(0);
|
|
6462
|
+
const [email, setEmail] = (0, import_react32.useState)("");
|
|
6463
|
+
const [phone, setPhone] = (0, import_react32.useState)("");
|
|
6464
|
+
const [name, setName] = (0, import_react32.useState)("");
|
|
6465
|
+
const [linkBy, setLinkBy] = (0, import_react32.useState)("email");
|
|
6466
|
+
const [fields, setFields] = (0, import_react32.useState)([]);
|
|
6467
|
+
const [note, setNote] = (0, import_react32.useState)("");
|
|
6468
|
+
const [sameChannelSent, setSameChannelSent] = (0, import_react32.useState)(false);
|
|
6469
|
+
(0, import_react32.useEffect)(() => {
|
|
6398
6470
|
let live = true;
|
|
6399
6471
|
setOptionsError(null);
|
|
6400
6472
|
sharing.secureLinkOptions(item).then(
|
|
@@ -6409,7 +6481,7 @@ function SecureLinkPanel({ item, port, onClose }) {
|
|
|
6409
6481
|
live = false;
|
|
6410
6482
|
};
|
|
6411
6483
|
}, [sharing, item]);
|
|
6412
|
-
(0,
|
|
6484
|
+
(0, import_react32.useEffect)(() => {
|
|
6413
6485
|
const list = sharing.sentSecureLinks;
|
|
6414
6486
|
if (!list) return;
|
|
6415
6487
|
let live = true;
|
|
@@ -6422,9 +6494,9 @@ function SecureLinkPanel({ item, port, onClose }) {
|
|
|
6422
6494
|
live = false;
|
|
6423
6495
|
};
|
|
6424
6496
|
}, [sharing, item, nonce]);
|
|
6425
|
-
const [phoneTyped, setPhoneTyped] = (0,
|
|
6426
|
-
const prefilled = (0,
|
|
6427
|
-
(0,
|
|
6497
|
+
const [phoneTyped, setPhoneTyped] = (0, import_react32.useState)(false);
|
|
6498
|
+
const prefilled = (0, import_react32.useRef)(false);
|
|
6499
|
+
(0, import_react32.useEffect)(() => {
|
|
6428
6500
|
const lookup = sharing.phoneOnFile;
|
|
6429
6501
|
if (!lookup || phoneTyped) return;
|
|
6430
6502
|
const clear = () => {
|
|
@@ -6572,15 +6644,16 @@ function SecureLinkPanel({ item, port, onClose }) {
|
|
|
6572
6644
|
);
|
|
6573
6645
|
}
|
|
6574
6646
|
function sentMeta(row, options) {
|
|
6575
|
-
const when = row.status === "pending" ? `Until ${
|
|
6647
|
+
const when = row.status === "pending" ? `Until ${(0, import_format7.formatAbsoluteDate)(row.expiresAt, void 0, "")}` : row.status === "viewed" && row.viewedAt ? (0, import_format7.formatAbsoluteDate)(row.viewedAt, void 0, "") : (0, import_format7.formatAbsoluteDate)(row.createdAt, DAY_FORMAT, "");
|
|
6576
6648
|
const carried = row.fieldKeys.length ? carriedWords(row.fieldKeys, options?.fields ?? []) : "";
|
|
6577
6649
|
return [when, carried].filter(Boolean).join(" \xB7 ");
|
|
6578
6650
|
}
|
|
6579
6651
|
|
|
6580
6652
|
// src/devices/DevicesPanel.tsx
|
|
6581
|
-
var
|
|
6653
|
+
var import_react33 = require("react");
|
|
6582
6654
|
var import_confirm_opener11 = require("@ai-matrx/kit/confirm-opener");
|
|
6583
6655
|
var import_controls27 = require("@ai-matrx/design-system/controls");
|
|
6656
|
+
var import_format8 = require("@ai-matrx/kit/format");
|
|
6584
6657
|
|
|
6585
6658
|
// src/devices/logic.ts
|
|
6586
6659
|
var PASSKEY_RP_ID = "aimatrx.com";
|
|
@@ -6668,10 +6741,10 @@ function ErrorLine2({ text }) {
|
|
|
6668
6741
|
function DevicesPanel({ port, onClose }) {
|
|
6669
6742
|
const confirmed = useConfirmed();
|
|
6670
6743
|
const notify = useNotify();
|
|
6671
|
-
const [devices, setDevices] = (0,
|
|
6672
|
-
const [error, setError] = (0,
|
|
6673
|
-
const [busyId, setBusyId] = (0,
|
|
6674
|
-
const load = (0,
|
|
6744
|
+
const [devices, setDevices] = (0, import_react33.useState)(null);
|
|
6745
|
+
const [error, setError] = (0, import_react33.useState)(null);
|
|
6746
|
+
const [busyId, setBusyId] = (0, import_react33.useState)(null);
|
|
6747
|
+
const load = (0, import_react33.useCallback)(async () => {
|
|
6675
6748
|
setError(null);
|
|
6676
6749
|
try {
|
|
6677
6750
|
setDevices(await port.devices.list());
|
|
@@ -6679,7 +6752,7 @@ function DevicesPanel({ port, onClose }) {
|
|
|
6679
6752
|
setError(messageOf3(e, "Your browsers could not be read."));
|
|
6680
6753
|
}
|
|
6681
6754
|
}, [port]);
|
|
6682
|
-
(0,
|
|
6755
|
+
(0, import_react33.useEffect)(() => {
|
|
6683
6756
|
void load();
|
|
6684
6757
|
}, [load]);
|
|
6685
6758
|
const revoke = async (device) => {
|
|
@@ -6710,13 +6783,13 @@ function DevicesPanel({ port, onClose }) {
|
|
|
6710
6783
|
Row,
|
|
6711
6784
|
{
|
|
6712
6785
|
label: off ? "Turned off" : "Can fill",
|
|
6713
|
-
hint: off ?
|
|
6786
|
+
hint: off ? (0, import_format8.formatAbsoluteDate)(device.revokedAt, DAY_FORMAT, "") : void 0,
|
|
6714
6787
|
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" }),
|
|
6715
6788
|
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "flex min-w-0 flex-col", children: [
|
|
6716
6789
|
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: off ? "truncate text-muted-foreground" : "truncate text-foreground", children: device.label }),
|
|
6717
6790
|
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "truncate text-xs text-muted-foreground", children: [
|
|
6718
|
-
device.lastUsedAt ? `Last used ${
|
|
6719
|
-
device.addedAt ? ` \xB7 added ${
|
|
6791
|
+
device.lastUsedAt ? `Last used ${(0, import_format8.formatAbsoluteDate)(device.lastUsedAt, void 0, "")}` : "Never used",
|
|
6792
|
+
device.addedAt ? ` \xB7 added ${(0, import_format8.formatAbsoluteDate)(device.addedAt, DAY_FORMAT, "")}` : ""
|
|
6720
6793
|
] })
|
|
6721
6794
|
] })
|
|
6722
6795
|
},
|
|
@@ -6737,11 +6810,11 @@ function ApprovePanel({ port, host, onClose, approvalKey, label, kind = "browser
|
|
|
6737
6810
|
const where = isMac ? "the Mac app" : "the extension";
|
|
6738
6811
|
const passkeys = port.devices.passkeys;
|
|
6739
6812
|
const here = passkeys?.available() ?? false;
|
|
6740
|
-
const [methods, setMethods] = (0,
|
|
6741
|
-
const [busy, setBusy] = (0,
|
|
6742
|
-
const [error, setError] = (0,
|
|
6743
|
-
const [approvedUntil, setApprovedUntil] = (0,
|
|
6744
|
-
const load = (0,
|
|
6813
|
+
const [methods, setMethods] = (0, import_react33.useState)(null);
|
|
6814
|
+
const [busy, setBusy] = (0, import_react33.useState)(null);
|
|
6815
|
+
const [error, setError] = (0, import_react33.useState)(null);
|
|
6816
|
+
const [approvedUntil, setApprovedUntil] = (0, import_react33.useState)(null);
|
|
6817
|
+
const load = (0, import_react33.useCallback)(async () => {
|
|
6745
6818
|
setError(null);
|
|
6746
6819
|
try {
|
|
6747
6820
|
setMethods(await port.devices.stepUpMethods());
|
|
@@ -6749,7 +6822,7 @@ function ApprovePanel({ port, host, onClose, approvalKey, label, kind = "browser
|
|
|
6749
6822
|
setError(messageOf3(e, "Your account could not be checked."));
|
|
6750
6823
|
}
|
|
6751
6824
|
}, [port]);
|
|
6752
|
-
(0,
|
|
6825
|
+
(0, import_react33.useEffect)(() => {
|
|
6753
6826
|
if (key && here) void load();
|
|
6754
6827
|
}, [key, here, load]);
|
|
6755
6828
|
const approve = async () => {
|
|
@@ -6810,7 +6883,7 @@ function ApprovePanel({ port, host, onClose, approvalKey, label, kind = "browser
|
|
|
6810
6883
|
"Return to ",
|
|
6811
6884
|
where,
|
|
6812
6885
|
" by ",
|
|
6813
|
-
|
|
6886
|
+
(0, import_format8.formatAbsoluteDate)(approvedUntil, void 0, ""),
|
|
6814
6887
|
"."
|
|
6815
6888
|
] }) }) : !passkeys ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(Empty, { children: [
|
|
6816
6889
|
"Approve with your password in ",
|
|
@@ -6837,7 +6910,7 @@ function ApprovePanel({ port, host, onClose, approvalKey, label, kind = "browser
|
|
|
6837
6910
|
}
|
|
6838
6911
|
|
|
6839
6912
|
// src/native/NativeImportPanel.tsx
|
|
6840
|
-
var
|
|
6913
|
+
var import_react35 = require("react");
|
|
6841
6914
|
var import_confirm_opener12 = require("@ai-matrx/kit/confirm-opener");
|
|
6842
6915
|
var import_controls28 = require("@ai-matrx/design-system/controls");
|
|
6843
6916
|
|
|
@@ -6900,19 +6973,19 @@ async function loadFullPreview(bridge, operationId, current) {
|
|
|
6900
6973
|
}
|
|
6901
6974
|
|
|
6902
6975
|
// src/native/use-native-import.ts
|
|
6903
|
-
var
|
|
6976
|
+
var import_react34 = require("react");
|
|
6904
6977
|
var fail = (e, fallback) => e instanceof Error && e.message ? e.message : fallback;
|
|
6905
6978
|
var RESTART = "Your account changed. The import was stopped; start it again.";
|
|
6906
6979
|
function useNativeImport(bridge, stillAllowed, onImported) {
|
|
6907
|
-
const [screen, setScreen] = (0,
|
|
6908
|
-
const [busy, setBusy] = (0,
|
|
6909
|
-
const generation = (0,
|
|
6910
|
-
const mounted = (0,
|
|
6911
|
-
const op = (0,
|
|
6912
|
-
const last = (0,
|
|
6913
|
-
const timer2 = (0,
|
|
6914
|
-
const polls = (0,
|
|
6915
|
-
const refreshRef = (0,
|
|
6980
|
+
const [screen, setScreen] = (0, import_react34.useState)({ kind: "idle", message: null });
|
|
6981
|
+
const [busy, setBusy] = (0, import_react34.useState)(false);
|
|
6982
|
+
const generation = (0, import_react34.useRef)(0);
|
|
6983
|
+
const mounted = (0, import_react34.useRef)(false);
|
|
6984
|
+
const op = (0, import_react34.useRef)(null);
|
|
6985
|
+
const last = (0, import_react34.useRef)(null);
|
|
6986
|
+
const timer2 = (0, import_react34.useRef)(null);
|
|
6987
|
+
const polls = (0, import_react34.useRef)(0);
|
|
6988
|
+
const refreshRef = (0, import_react34.useRef)(async () => void 0);
|
|
6916
6989
|
const current = (g) => mounted.current && g === generation.current;
|
|
6917
6990
|
const stopPolling = () => {
|
|
6918
6991
|
if (timer2.current !== null) clearTimeout(timer2.current);
|
|
@@ -7081,9 +7154,9 @@ function useNativeImport(bridge, stillAllowed, onImported) {
|
|
|
7081
7154
|
setBusy(false);
|
|
7082
7155
|
setScreen({ kind: "idle", message: null });
|
|
7083
7156
|
};
|
|
7084
|
-
const invalidateRef = (0,
|
|
7157
|
+
const invalidateRef = (0, import_react34.useRef)(invalidate);
|
|
7085
7158
|
invalidateRef.current = invalidate;
|
|
7086
|
-
(0,
|
|
7159
|
+
(0, import_react34.useEffect)(() => {
|
|
7087
7160
|
mounted.current = true;
|
|
7088
7161
|
const off = bridge.subscribe?.(() => {
|
|
7089
7162
|
if (op.current) invalidateRef.current(RESTART);
|
|
@@ -7115,14 +7188,14 @@ function NativeImportPanel({ bridge, readLimits, activeOrganizationId, organizat
|
|
|
7115
7188
|
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Importer, { bridge, readLimits, activeOrganizationId, organizations, onClose, onChanged });
|
|
7116
7189
|
}
|
|
7117
7190
|
function Importer({ bridge, readLimits, activeOrganizationId, organizations, onClose, onChanged }) {
|
|
7118
|
-
const options = (0,
|
|
7119
|
-
const [organizationId, setOrganizationId] = (0,
|
|
7120
|
-
const [limits, setLimits] = (0,
|
|
7121
|
-
const [limitError, setLimitError] = (0,
|
|
7191
|
+
const options = (0, import_react35.useMemo)(() => organizations.map((o) => ({ value: o.id, label: o.name })), [organizations]);
|
|
7192
|
+
const [organizationId, setOrganizationId] = (0, import_react35.useState)(() => organizations.some((o) => o.id === activeOrganizationId) ? activeOrganizationId : organizations[0]?.id ?? "");
|
|
7193
|
+
const [limits, setLimits] = (0, import_react35.useState)(null);
|
|
7194
|
+
const [limitError, setLimitError] = (0, import_react35.useState)(null);
|
|
7122
7195
|
const flow = useNativeImport(bridge, (id) => organizations.some((o) => o.id === id), onChanged);
|
|
7123
7196
|
const { screen, busy } = flow;
|
|
7124
7197
|
const orgName = organizations.find((o) => o.id === organizationId)?.name ?? "this organization";
|
|
7125
|
-
(0,
|
|
7198
|
+
(0, import_react35.useEffect)(() => {
|
|
7126
7199
|
if (!readLimits || !organizationId) return;
|
|
7127
7200
|
let live = true;
|
|
7128
7201
|
setLimits(null);
|
|
@@ -7183,20 +7256,20 @@ function Importer({ bridge, readLimits, activeOrganizationId, organizations, onC
|
|
|
7183
7256
|
}
|
|
7184
7257
|
|
|
7185
7258
|
// src/extension/PageView.tsx
|
|
7186
|
-
var
|
|
7259
|
+
var import_react39 = require("react");
|
|
7187
7260
|
var import_design_system23 = require("@ai-matrx/design-system");
|
|
7188
7261
|
var import_controls32 = require("@ai-matrx/design-system/controls");
|
|
7189
7262
|
|
|
7190
7263
|
// src/extension/CaptureCard.tsx
|
|
7191
|
-
var
|
|
7264
|
+
var import_react36 = require("react");
|
|
7192
7265
|
var import_controls29 = require("@ai-matrx/design-system/controls");
|
|
7193
7266
|
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
7194
7267
|
var SEARCH_FROM = 4;
|
|
7195
7268
|
function CaptureCard({ capture, onChanged }) {
|
|
7196
|
-
const prompt = (0,
|
|
7269
|
+
const prompt = (0, import_react36.useSyncExternalStore)(capture.subscribe, capture.get, capture.get);
|
|
7197
7270
|
const notify = useNotify();
|
|
7198
|
-
const [busy, setBusy] = (0,
|
|
7199
|
-
const [q, setQ] = (0,
|
|
7271
|
+
const [busy, setBusy] = (0, import_react36.useState)(false);
|
|
7272
|
+
const [q, setQ] = (0, import_react36.useState)("");
|
|
7200
7273
|
if (!prompt) return null;
|
|
7201
7274
|
const decide = async (d) => {
|
|
7202
7275
|
setBusy(true);
|
|
@@ -7252,15 +7325,15 @@ function CaptureCard({ capture, onChanged }) {
|
|
|
7252
7325
|
}
|
|
7253
7326
|
|
|
7254
7327
|
// src/extension/FillSetupCard.tsx
|
|
7255
|
-
var
|
|
7328
|
+
var import_react37 = require("react");
|
|
7256
7329
|
var import_controls30 = require("@ai-matrx/design-system/controls");
|
|
7257
7330
|
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
7258
7331
|
function FillSetupCard({ fillSetup }) {
|
|
7259
7332
|
const notify = useNotify();
|
|
7260
|
-
const state = (0,
|
|
7261
|
-
const box = (0,
|
|
7262
|
-
const [busy, setBusy] = (0,
|
|
7263
|
-
const [error, setError] = (0,
|
|
7333
|
+
const state = (0, import_react37.useSyncExternalStore)(fillSetup.subscribe, fillSetup.get, fillSetup.get);
|
|
7334
|
+
const box = (0, import_react37.useRef)(null);
|
|
7335
|
+
const [busy, setBusy] = (0, import_react37.useState)(false);
|
|
7336
|
+
const [error, setError] = (0, import_react37.useState)(null);
|
|
7264
7337
|
if (state.status !== "off") return null;
|
|
7265
7338
|
const finish = async (run) => {
|
|
7266
7339
|
setBusy(true);
|
|
@@ -7325,7 +7398,7 @@ function FillSetupCard({ fillSetup }) {
|
|
|
7325
7398
|
}
|
|
7326
7399
|
|
|
7327
7400
|
// src/extension/PageGenerator.tsx
|
|
7328
|
-
var
|
|
7401
|
+
var import_react38 = require("react");
|
|
7329
7402
|
var import_design_system22 = require("@ai-matrx/design-system");
|
|
7330
7403
|
var import_controls31 = require("@ai-matrx/design-system/controls");
|
|
7331
7404
|
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
@@ -7334,10 +7407,10 @@ function PageGenerator({ fields }) {
|
|
|
7334
7407
|
const limits = useGeneratorLimitsSource();
|
|
7335
7408
|
const copy = useCopy();
|
|
7336
7409
|
const held = useTransientSecret(HOLD_MS);
|
|
7337
|
-
const [open, setOpen] = (0,
|
|
7338
|
-
const [busy, setBusy] = (0,
|
|
7339
|
-
const [targets, setTargets] = (0,
|
|
7340
|
-
const [said, setSaid] = (0,
|
|
7410
|
+
const [open, setOpen] = (0, import_react38.useState)(false);
|
|
7411
|
+
const [busy, setBusy] = (0, import_react38.useState)(false);
|
|
7412
|
+
const [targets, setTargets] = (0, import_react38.useState)([]);
|
|
7413
|
+
const [said, setSaid] = (0, import_react38.useState)(null);
|
|
7341
7414
|
if (!limits) return null;
|
|
7342
7415
|
const say3 = setSaid;
|
|
7343
7416
|
const put = async (targetId, value2) => {
|
|
@@ -7401,8 +7474,8 @@ function PageGenerator({ fields }) {
|
|
|
7401
7474
|
// src/extension/PageView.tsx
|
|
7402
7475
|
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
7403
7476
|
function PageView({ port, page, fill, capture, fillSetup, newPasswordFields, items, definitions, onOpen, onNewForPage, onBrowse, onChanged, header }) {
|
|
7404
|
-
const [running, setRunning] = (0,
|
|
7405
|
-
const [said, setSaid] = (0,
|
|
7477
|
+
const [running, setRunning] = (0, import_react39.useState)(null);
|
|
7478
|
+
const [said, setSaid] = (0, import_react39.useState)(null);
|
|
7406
7479
|
const site = pageSite(page.url);
|
|
7407
7480
|
const state = page.matchState ?? { status: "ready" };
|
|
7408
7481
|
const fillable = new Set(page.fillableItemIds ?? page.matchingItemIds);
|
|
@@ -7486,7 +7559,7 @@ function MatchRow({ itemId, item, tag, family, port, busy, running, onOpen, onFi
|
|
|
7486
7559
|
const confirmed = useConfirmed();
|
|
7487
7560
|
const copy = useCopy();
|
|
7488
7561
|
const notify = useNotify();
|
|
7489
|
-
const [reading, setReading] = (0,
|
|
7562
|
+
const [reading, setReading] = (0, import_react39.useState)(false);
|
|
7490
7563
|
const usable = item?.capabilities.canUse ?? false;
|
|
7491
7564
|
const user = usable ? item?.fields.find((f) => USERNAME_KEYS.test(f.key) && f.handling !== "sealed" && f.active) : void 0;
|
|
7492
7565
|
const secret = usable && item?.capabilities.canReveal ? item?.fields.find((f) => f.key === "password" && f.handling === "revealable" && f.active) : void 0;
|
|
@@ -7501,10 +7574,10 @@ function MatchRow({ itemId, item, tag, family, port, busy, running, onOpen, onFi
|
|
|
7501
7574
|
setReading(false);
|
|
7502
7575
|
}
|
|
7503
7576
|
};
|
|
7504
|
-
const subtitle = [item ?
|
|
7577
|
+
const subtitle = [item ? loginSiteOf(item) || item.definitionLabel : "", tag].filter(Boolean).join(" \xB7 ");
|
|
7505
7578
|
return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("li", { className: "flex h-12 items-center gap-1 pl-1 pr-2", "data-item": itemId, children: [
|
|
7506
7579
|
/* @__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: [
|
|
7507
|
-
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ItemIcon, { definitionKey: item?.definitionKey ?? "website_login", family, site: item ?
|
|
7580
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(ItemIcon, { definitionKey: item?.definitionKey ?? "website_login", family, site: item ? loginSiteOf(item) : "" }),
|
|
7508
7581
|
/* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { className: "flex min-w-0 flex-1 flex-col leading-tight", children: [
|
|
7509
7582
|
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "truncate text-sm font-medium", children: item?.name ?? "Saved login" }),
|
|
7510
7583
|
subtitle ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "truncate text-xs text-muted-foreground", children: subtitle }) : null
|
|
@@ -7531,7 +7604,7 @@ function MatchRow({ itemId, item, tag, family, port, busy, running, onOpen, onFi
|
|
|
7531
7604
|
}
|
|
7532
7605
|
|
|
7533
7606
|
// src/Sidebar.tsx
|
|
7534
|
-
var
|
|
7607
|
+
var import_react40 = require("react");
|
|
7535
7608
|
var import_design_system24 = require("@ai-matrx/design-system");
|
|
7536
7609
|
var import_controls33 = require("@ai-matrx/design-system/controls");
|
|
7537
7610
|
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
@@ -7614,7 +7687,7 @@ function Group({ title, children }) {
|
|
|
7614
7687
|
] });
|
|
7615
7688
|
}
|
|
7616
7689
|
function Sidebar({ vault, choices, onVault, view, allCount, deletedCount, views, hasFavorites, hasRecents, onView, onPanel, nativeProvider, hasNativeImport = false, hasPage = false }) {
|
|
7617
|
-
const [tagsOpen, setTagsOpen] = (0,
|
|
7690
|
+
const [tagsOpen, setTagsOpen] = (0, import_react40.useState)(view.startsWith("tag:"));
|
|
7618
7691
|
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: [
|
|
7619
7692
|
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex items-center gap-2 px-3 pb-2 pt-3", children: [
|
|
7620
7693
|
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(SafeGlyph, { className: "size-5 shrink-0 text-primary" }),
|
|
@@ -7674,8 +7747,8 @@ var generatorLimitsFrom = (knobs) => knobs ? async () => {
|
|
|
7674
7747
|
} : void 0;
|
|
7675
7748
|
function ImportWithLimits(props) {
|
|
7676
7749
|
const { knobs, ...rest } = props;
|
|
7677
|
-
const [state, setState] = (0,
|
|
7678
|
-
(0,
|
|
7750
|
+
const [state, setState] = (0, import_react41.useState)(null);
|
|
7751
|
+
(0, import_react41.useEffect)(() => {
|
|
7679
7752
|
if (!knobs) return setState({ error: "Import is not set up for this organization yet." });
|
|
7680
7753
|
knobs().then(
|
|
7681
7754
|
(r) => {
|
|
@@ -7692,31 +7765,55 @@ function ImportWithLimits(props) {
|
|
|
7692
7765
|
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" }) });
|
|
7693
7766
|
}
|
|
7694
7767
|
function VaultApp(props) {
|
|
7695
|
-
|
|
7768
|
+
const lock = props.host?.lock;
|
|
7769
|
+
const locked = useLocked(lock);
|
|
7770
|
+
const port = (0, import_react41.useMemo)(() => lock ? guardPort(props.port, () => lock.locked()) : props.port, [props.port, lock]);
|
|
7771
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "relative h-full min-h-0 w-full", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(NoticeProvider, { notify: props.notify, children: lock && locked ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(LockedScreen, { lock }) : /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ClipboardProvider, { clipboard: props.host?.clipboard, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(RevealSecondsProvider, { seconds: props.host?.revealSeconds, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(IdentityGate, { identity: props.host?.identity, children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(GeneratorLimitsProvider, { resolve: generatorLimitsFrom(props.host?.knobs), children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Workspace, { ...props, port }) }) }) }) }) }) });
|
|
7772
|
+
}
|
|
7773
|
+
function LockedScreen({ lock }) {
|
|
7774
|
+
const [busy, setBusy] = (0, import_react41.useState)(false);
|
|
7775
|
+
const [error, setError] = (0, import_react41.useState)(null);
|
|
7776
|
+
const unlock = async () => {
|
|
7777
|
+
setBusy(true);
|
|
7778
|
+
setError(null);
|
|
7779
|
+
try {
|
|
7780
|
+
await lock.unlock();
|
|
7781
|
+
} catch (e) {
|
|
7782
|
+
setError(e instanceof Error && e.message ? e.message : "The vault stayed locked.");
|
|
7783
|
+
} finally {
|
|
7784
|
+
setBusy(false);
|
|
7785
|
+
}
|
|
7786
|
+
};
|
|
7787
|
+
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: [
|
|
7788
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(LockGlyph, { className: "size-8 text-muted-foreground" }),
|
|
7789
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "text-base font-medium text-foreground", children: "Vault locked" }),
|
|
7790
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_controls34.Button, { variant: "primary", disabled: busy, onClick: () => void unlock(), children: lock.unlockLabel ?? "Unlock" }),
|
|
7791
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { role: "alert", className: "max-w-sm text-sm text-destructive", children: error }) : null
|
|
7792
|
+
] });
|
|
7696
7793
|
}
|
|
7697
7794
|
function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocationChange }) {
|
|
7698
|
-
const rootRef = (0,
|
|
7795
|
+
const rootRef = (0, import_react41.useRef)(null);
|
|
7699
7796
|
const width = useElementWidth(rootRef);
|
|
7700
7797
|
const mode = layout !== "auto" ? layout : width >= FULL_AT ? "full" : width >= SPLIT_AT ? "split" : "stack";
|
|
7701
7798
|
const notify = useNotify();
|
|
7702
|
-
const [snap, setSnap] = (0,
|
|
7703
|
-
const [items, setItems] = (0,
|
|
7704
|
-
const [deleted, setDeleted] = (0,
|
|
7705
|
-
const [favorites, setFavorites] = (0,
|
|
7706
|
-
const [recents, setRecents] = (0,
|
|
7707
|
-
const [error, setError] = (0,
|
|
7708
|
-
const [inner, setInner] = (0,
|
|
7799
|
+
const [snap, setSnap] = (0, import_react41.useState)(null);
|
|
7800
|
+
const [items, setItems] = (0, import_react41.useState)([]);
|
|
7801
|
+
const [deleted, setDeleted] = (0, import_react41.useState)([]);
|
|
7802
|
+
const [favorites, setFavorites] = (0, import_react41.useState)(null);
|
|
7803
|
+
const [recents, setRecents] = (0, import_react41.useState)(null);
|
|
7804
|
+
const [error, setError] = (0, import_react41.useState)(null);
|
|
7805
|
+
const [inner, setInner] = (0, import_react41.useState)(DEFAULT_LOCATION);
|
|
7709
7806
|
const loc = location ?? inner;
|
|
7710
|
-
const dirty = (0,
|
|
7711
|
-
const [notice, setNotice] = (0,
|
|
7712
|
-
const move = (0,
|
|
7807
|
+
const dirty = (0, import_react41.useRef)(false);
|
|
7808
|
+
const [notice, setNotice] = (0, import_react41.useState)(null);
|
|
7809
|
+
const move = (0, import_react41.useCallback)(
|
|
7713
7810
|
(next, how) => {
|
|
7714
7811
|
if (!location) setInner(next);
|
|
7715
7812
|
onLocationChange?.(next, how);
|
|
7716
7813
|
},
|
|
7717
7814
|
[location, onLocationChange]
|
|
7718
7815
|
);
|
|
7719
|
-
const go = (0,
|
|
7816
|
+
const go = (0, import_react41.useCallback)(
|
|
7720
7817
|
(patch, how = "push") => {
|
|
7721
7818
|
const leaving = patch.itemId !== void 0 || patch.mode !== void 0 || patch.vault !== void 0 || patch.view !== void 0;
|
|
7722
7819
|
const next = { ...loc, ...patch };
|
|
@@ -7735,9 +7832,9 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
7735
7832
|
},
|
|
7736
7833
|
[loc, move]
|
|
7737
7834
|
);
|
|
7738
|
-
const knobsRef = (0,
|
|
7835
|
+
const knobsRef = (0, import_react41.useRef)(host.knobs);
|
|
7739
7836
|
knobsRef.current = host.knobs;
|
|
7740
|
-
const load = (0,
|
|
7837
|
+
const load = (0, import_react41.useCallback)(() => {
|
|
7741
7838
|
setError(null);
|
|
7742
7839
|
port.load().then((s) => {
|
|
7743
7840
|
setSnap(s);
|
|
@@ -7752,17 +7849,17 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
7752
7849
|
knobsRef.current?.().catch(() => void 0);
|
|
7753
7850
|
port.lists.recents?.list().then(setRecents, () => void 0);
|
|
7754
7851
|
}, [port]);
|
|
7755
|
-
(0,
|
|
7756
|
-
(0,
|
|
7852
|
+
(0, import_react41.useEffect)(load, [load]);
|
|
7853
|
+
(0, import_react41.useEffect)(() => {
|
|
7757
7854
|
if (!loc.itemId || !port.lists.recents) return;
|
|
7758
7855
|
const id = loc.itemId;
|
|
7759
7856
|
port.lists.recents.record(id).then(() => setRecents((r) => [id, ...(r ?? []).filter((x) => x !== id)]), () => void 0);
|
|
7760
7857
|
}, [loc.itemId, port]);
|
|
7761
7858
|
const orgs = snap?.organizations ?? [];
|
|
7762
7859
|
const definitions = snap?.definitions ?? [];
|
|
7763
|
-
const inThisVault = (0,
|
|
7764
|
-
const views = (0,
|
|
7765
|
-
const visible = (0,
|
|
7860
|
+
const inThisVault = (0, import_react41.useMemo)(() => items.filter((i) => inVault(i, loc.vault)), [items, loc.vault]);
|
|
7861
|
+
const views = (0, import_react41.useMemo)(() => buildViews(inThisVault, definitions, favorites, recents), [inThisVault, definitions, favorites, recents]);
|
|
7862
|
+
const visible = (0, import_react41.useMemo)(() => {
|
|
7766
7863
|
const filtered = inThisVault.filter((i) => {
|
|
7767
7864
|
if (!matchesQuery(i, loc.q)) return false;
|
|
7768
7865
|
if (loc.view === "favorites") return favorites?.has(i.id) ?? false;
|
|
@@ -7773,8 +7870,8 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
7773
7870
|
if (loc.view === "recent" && recents) return [...filtered].sort((a, b) => recents.indexOf(a.id) - recents.indexOf(b.id));
|
|
7774
7871
|
return sortItems(filtered, loc.sort);
|
|
7775
7872
|
}, [inThisVault, loc.view, loc.q, loc.sort, favorites, recents, definitions]);
|
|
7776
|
-
const choices = (0,
|
|
7777
|
-
const matchingIds = (0,
|
|
7873
|
+
const choices = (0, import_react41.useMemo)(() => vaultChoices(items, orgs, loc.vault), [items, orgs, loc.vault]);
|
|
7874
|
+
const matchingIds = (0, import_react41.useMemo)(() => host.page ? new Set(host.page.matchingItemIds) : void 0, [host.page]);
|
|
7778
7875
|
const selected = loc.itemId ? items.find((i) => i.id === loc.itemId) ?? null : null;
|
|
7779
7876
|
const replaceItem = (next) => setItems((cur) => cur.some((i) => i.id === next.id) ? cur.map((i) => i.id === next.id ? next : i) : [...cur, next]);
|
|
7780
7877
|
const toggleFavorite = (id) => {
|
|
@@ -7845,6 +7942,10 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
7845
7942
|
host.nativeProvider && host.nativeProvider.status !== "unavailable" ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_design_system25.DropdownMenuItem, { onSelect: host.nativeProvider.openSetup, children: [
|
|
7846
7943
|
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ShieldGlyph, { className: "size-4" }),
|
|
7847
7944
|
"System AutoFill"
|
|
7945
|
+
] }) : null,
|
|
7946
|
+
host.lock?.lock ? /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_design_system25.DropdownMenuItem, { onSelect: () => void host.lock?.lock?.(), children: [
|
|
7947
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(LockGlyph, { className: "size-4" }),
|
|
7948
|
+
"Lock"
|
|
7848
7949
|
] }) : null
|
|
7849
7950
|
] })
|
|
7850
7951
|
] })
|
|
@@ -8459,7 +8560,7 @@ function createSharingPort(ctx, options = {}) {
|
|
|
8459
8560
|
return r.grants.map(grantOf);
|
|
8460
8561
|
},
|
|
8461
8562
|
async addPerson(item, email, level) {
|
|
8462
|
-
const w = await account6.addGrant(api, { path: { item_id: item.id }, body: { recipient_email: email.trim(), ...
|
|
8563
|
+
const w = await account6.addGrant(api, { path: { item_id: item.id }, body: { recipient_email: email.trim(), ...shareFlagsOf(level), initiation: "user" } }, ctx.optsFor(item));
|
|
8463
8564
|
return grantOf(w);
|
|
8464
8565
|
},
|
|
8465
8566
|
async addOrganization(item, organizationId, level) {
|
|
@@ -8467,14 +8568,14 @@ function createSharingPort(ctx, options = {}) {
|
|
|
8467
8568
|
return grantOf(w);
|
|
8468
8569
|
},
|
|
8469
8570
|
async setLevel(item, grant, level) {
|
|
8470
|
-
const w = await account6.updateGrant(api, { path: { item_id: item.id, grant_id: grant.id }, body: { ...
|
|
8571
|
+
const w = await account6.updateGrant(api, { path: { item_id: item.id, grant_id: grant.id }, body: { ...shareFlagsOf(level), initiation: "user" } }, ctx.optsFor(item));
|
|
8471
8572
|
return grantOf(w);
|
|
8472
8573
|
},
|
|
8473
8574
|
async revoke(item, grant) {
|
|
8474
8575
|
await account6.removeGrant(api, { path: { item_id: item.id, grant_id: grant.id } }, ctx.optsFor(item));
|
|
8475
8576
|
},
|
|
8476
8577
|
async setAccessMode(item, mode, people) {
|
|
8477
|
-
const grantees = mode === "restricted" ? people.filter((g) => g.kind === "person" && g.userId).map((g) => ({ user_id: g.userId, ...
|
|
8578
|
+
const grantees = mode === "restricted" ? people.filter((g) => g.kind === "person" && g.userId).map((g) => ({ user_id: g.userId, ...shareFlagsOf(g.level) })) : [];
|
|
8478
8579
|
await account6.share(api, { path: { item_id: item.id }, body: { access_mode: mode, grantees, initiation: "user" } }, ctx.optsFor(item));
|
|
8479
8580
|
return ctx.refetch(item.id, item.owner);
|
|
8480
8581
|
},
|