@ai-matrx/vault 0.1.36 → 0.1.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/dist/index.cjs +393 -305
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +365 -277
- package/dist/index.js.map +1 -1
- package/package.json +2 -23
package/dist/index.js
CHANGED
|
@@ -58,7 +58,7 @@ import {
|
|
|
58
58
|
} from "./chunk-B5TOAIY6.js";
|
|
59
59
|
|
|
60
60
|
// src/VaultApp.tsx
|
|
61
|
-
import { useCallback as useCallback4, useEffect as
|
|
61
|
+
import { useCallback as useCallback4, useEffect as useEffect22, useMemo as useMemo6, useRef as useRef18, useState as useState40, useSyncExternalStore as useSyncExternalStore5 } from "react";
|
|
62
62
|
import { DropdownMenu as DropdownMenu5, DropdownMenuContent as DropdownMenuContent5, DropdownMenuItem as DropdownMenuItem5, DropdownMenuTrigger as DropdownMenuTrigger5, LookScope } from "@ai-matrx/design-system";
|
|
63
63
|
import { Button as Button33, SearchField as SearchField4, Select as Select12 } from "@ai-matrx/design-system/controls";
|
|
64
64
|
import { confirm as confirm14 } from "@ai-matrx/kit/confirm-opener";
|
|
@@ -881,11 +881,11 @@ function whenInDay(iso, now = /* @__PURE__ */ new Date()) {
|
|
|
881
881
|
if (dayKey(d) === dayKey(now)) return formatRelativeTime(iso, { now: now.getTime() });
|
|
882
882
|
return d.toLocaleTimeString(void 0, { hour: "numeric", minute: "2-digit" });
|
|
883
883
|
}
|
|
884
|
-
function collapseRuns(rows,
|
|
884
|
+
function collapseRuns(rows, keyOf2) {
|
|
885
885
|
const out = [];
|
|
886
886
|
const at = /* @__PURE__ */ new Map();
|
|
887
887
|
for (const row of rows) {
|
|
888
|
-
const k =
|
|
888
|
+
const k = keyOf2(row);
|
|
889
889
|
const seen = at.get(k);
|
|
890
890
|
if (seen) seen.times += 1;
|
|
891
891
|
else {
|
|
@@ -1408,6 +1408,14 @@ function canDecodeQrLocally() {
|
|
|
1408
1408
|
function hasCamera() {
|
|
1409
1409
|
return typeof navigator !== "undefined" && typeof navigator.mediaDevices?.getUserMedia === "function";
|
|
1410
1410
|
}
|
|
1411
|
+
async function hasCameraDevice() {
|
|
1412
|
+
if (!hasCamera() || typeof navigator.mediaDevices?.enumerateDevices !== "function") return false;
|
|
1413
|
+
try {
|
|
1414
|
+
return (await navigator.mediaDevices.enumerateDevices()).some((d) => d.kind === "videoinput");
|
|
1415
|
+
} catch {
|
|
1416
|
+
return false;
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1411
1419
|
async function decodeQr(source) {
|
|
1412
1420
|
return decodeQrFromElement(source);
|
|
1413
1421
|
}
|
|
@@ -1439,17 +1447,15 @@ function useCanScan() {
|
|
|
1439
1447
|
}, []);
|
|
1440
1448
|
return ok;
|
|
1441
1449
|
}
|
|
1442
|
-
function
|
|
1450
|
+
function QrScanInline({ onResult, onClose }) {
|
|
1443
1451
|
const video = useRef6(null);
|
|
1444
1452
|
const [error, setError] = useState8(null);
|
|
1445
1453
|
const done = useRef6(onResult);
|
|
1446
1454
|
done.current = onResult;
|
|
1447
1455
|
useEffect8(() => {
|
|
1448
|
-
if (!open) return;
|
|
1449
1456
|
let stream = null;
|
|
1450
1457
|
let live = true;
|
|
1451
1458
|
let timer2 = null;
|
|
1452
|
-
setError(null);
|
|
1453
1459
|
const stop = () => {
|
|
1454
1460
|
if (timer2) clearTimeout(timer2);
|
|
1455
1461
|
stream?.getTracks().forEach((t) => t.stop());
|
|
@@ -1492,13 +1498,26 @@ function QrScanPanel({ open, onResult, onClose }) {
|
|
|
1492
1498
|
live = false;
|
|
1493
1499
|
stop();
|
|
1494
1500
|
};
|
|
1495
|
-
}, [
|
|
1496
|
-
|
|
1497
|
-
/* @__PURE__ */ jsxs6("
|
|
1501
|
+
}, []);
|
|
1502
|
+
if (error) {
|
|
1503
|
+
return /* @__PURE__ */ jsxs6("p", { className: "flex items-center gap-2 px-1 pt-1 text-xs text-muted-foreground", role: "status", "data-camera-note": "", children: [
|
|
1504
|
+
/* @__PURE__ */ jsx7(CameraGlyph, { className: "size-3.5 shrink-0", "aria-hidden": true }),
|
|
1505
|
+
/* @__PURE__ */ jsxs6("span", { className: "min-w-0 flex-1 truncate", children: [
|
|
1506
|
+
error,
|
|
1507
|
+
" Paste the setup key or choose a QR image."
|
|
1508
|
+
] }),
|
|
1509
|
+
/* @__PURE__ */ jsx7(Button5, { variant: "quiet", onClick: onClose, children: "Dismiss" })
|
|
1510
|
+
] });
|
|
1511
|
+
}
|
|
1512
|
+
return /* @__PURE__ */ jsxs6("div", { className: "flex flex-col items-center gap-1.5 pt-2", role: "region", "aria-label": "Scan QR code", "data-camera-preview": "", children: [
|
|
1513
|
+
/* @__PURE__ */ jsxs6("div", { className: "relative aspect-square w-full max-w-56 overflow-hidden rounded-xl bg-muted", children: [
|
|
1498
1514
|
/* @__PURE__ */ jsx7("video", { ref: video, className: "size-full object-cover", playsInline: true, muted: true, "aria-label": "Camera" }),
|
|
1499
|
-
|
|
1515
|
+
/* @__PURE__ */ jsx7("div", { className: "pointer-events-none absolute inset-[18%] rounded-lg border-2 border-primary", "aria-hidden": true })
|
|
1500
1516
|
] }),
|
|
1501
|
-
/* @__PURE__ */
|
|
1517
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
|
|
1518
|
+
/* @__PURE__ */ jsx7("span", { className: "text-xs text-muted-foreground", children: "Point at the site's QR code" }),
|
|
1519
|
+
/* @__PURE__ */ jsx7(Button5, { variant: "quiet", onClick: onClose, children: "Stop camera" })
|
|
1520
|
+
] })
|
|
1502
1521
|
] });
|
|
1503
1522
|
}
|
|
1504
1523
|
function OtpSetupRow({ value, onChange, label = "Authenticator", placeholder = "Paste setup key or otpauth link", disabled = false, autoFocus = false, onImage, onRecognized, status, autoStartCamera = false }) {
|
|
@@ -1508,8 +1527,15 @@ function OtpSetupRow({ value, onChange, label = "Authenticator", placeholder = "
|
|
|
1508
1527
|
const autoStarted = useRef6(false);
|
|
1509
1528
|
useEffect8(() => {
|
|
1510
1529
|
if (!autoStartCamera || !canScan || disabled || autoStarted.current || value) return;
|
|
1511
|
-
|
|
1512
|
-
|
|
1530
|
+
let live = true;
|
|
1531
|
+
void hasCameraDevice().then((has) => {
|
|
1532
|
+
if (!live || !has || autoStarted.current) return;
|
|
1533
|
+
autoStarted.current = true;
|
|
1534
|
+
setScanning(true);
|
|
1535
|
+
});
|
|
1536
|
+
return () => {
|
|
1537
|
+
live = false;
|
|
1538
|
+
};
|
|
1513
1539
|
}, [autoStartCamera, canScan, disabled, value]);
|
|
1514
1540
|
const [reading, setReading] = useState8(false);
|
|
1515
1541
|
const [imageError, setImageError] = useState8(null);
|
|
@@ -1611,10 +1637,9 @@ function OtpSetupRow({ value, onChange, label = "Authenticator", placeholder = "
|
|
|
1611
1637
|
]
|
|
1612
1638
|
}
|
|
1613
1639
|
),
|
|
1614
|
-
canScan ? /* @__PURE__ */ jsx7(
|
|
1615
|
-
|
|
1640
|
+
canScan && scanning ? /* @__PURE__ */ jsx7(
|
|
1641
|
+
QrScanInline,
|
|
1616
1642
|
{
|
|
1617
|
-
open: scanning,
|
|
1618
1643
|
onClose: () => setScanning(false),
|
|
1619
1644
|
onResult: (text) => {
|
|
1620
1645
|
setScanning(false);
|
|
@@ -2728,12 +2753,56 @@ function createVaultKnobs(client, address) {
|
|
|
2728
2753
|
}
|
|
2729
2754
|
var REVEAL_SECONDS_KNOB = "desktop.vault.reveal_hide_seconds";
|
|
2730
2755
|
var BACKUP_PASSPHRASE_MIN_KNOB = "desktop.vault.backup_passphrase_min_length";
|
|
2756
|
+
var ORGANIZATION_SEARCH_AT_KNOB = "vault.organization_search_at";
|
|
2757
|
+
var ORGANIZATION_SEARCH_AT_UNREAD = 8;
|
|
2731
2758
|
function positiveKnob(resolved, key) {
|
|
2732
2759
|
const v = resolved[key];
|
|
2733
2760
|
const n = typeof v === "string" && v.trim() !== "" ? Number(v) : v;
|
|
2734
2761
|
return typeof n === "number" && Number.isFinite(n) && n > 0 ? Math.floor(n) : null;
|
|
2735
2762
|
}
|
|
2736
2763
|
|
|
2764
|
+
// src/organizations.ts
|
|
2765
|
+
import { shortUuid } from "@ai-matrx/design-system/record-id-format";
|
|
2766
|
+
function orderOrganizations(orgs, items, recentItemIds) {
|
|
2767
|
+
const counts = /* @__PURE__ */ new Map();
|
|
2768
|
+
for (const i of items) if (i.owner.organizationId) counts.set(i.owner.organizationId, (counts.get(i.owner.organizationId) ?? 0) + 1);
|
|
2769
|
+
const byId = new Map(items.map((i) => [i.id, i]));
|
|
2770
|
+
const recent = /* @__PURE__ */ new Map();
|
|
2771
|
+
for (const id of recentItemIds ?? []) {
|
|
2772
|
+
const org = byId.get(id)?.owner.organizationId;
|
|
2773
|
+
if (org && !recent.has(org)) recent.set(org, recent.size);
|
|
2774
|
+
}
|
|
2775
|
+
const group = (o) => recent.has(o.id) ? 0 : (counts.get(o.id) ?? 0) > 0 ? 1 : 2;
|
|
2776
|
+
return [...orgs].sort((a, b) => group(a) - group(b) || (recent.get(a.id) ?? 0) - (recent.get(b.id) ?? 0) || a.name.localeCompare(b.name, void 0, { sensitivity: "base" }) || a.id.localeCompare(b.id));
|
|
2777
|
+
}
|
|
2778
|
+
function organizationHints(orgs) {
|
|
2779
|
+
const seen = /* @__PURE__ */ new Map();
|
|
2780
|
+
for (const o of orgs) seen.set(o.name.trim().toLowerCase(), (seen.get(o.name.trim().toLowerCase()) ?? 0) + 1);
|
|
2781
|
+
return new Map(orgs.filter((o) => (seen.get(o.name.trim().toLowerCase()) ?? 0) > 1).map((o) => [o.id, shortUuid(o.id)]));
|
|
2782
|
+
}
|
|
2783
|
+
|
|
2784
|
+
// src/shown-until-move.ts
|
|
2785
|
+
import { useEffect as useEffect11, useRef as useRef9, useState as useState14 } from "react";
|
|
2786
|
+
var keyOf = (loc) => `${String(loc.vault)}|${loc.view}|${loc.itemId ?? ""}|${loc.mode}|${loc.panel ?? ""}|${loc.kind ?? ""}`;
|
|
2787
|
+
function useShownUntilMove(loc) {
|
|
2788
|
+
const [shown, setShown] = useState14(null);
|
|
2789
|
+
const home = useRef9(null);
|
|
2790
|
+
const key = keyOf(loc);
|
|
2791
|
+
useEffect11(() => {
|
|
2792
|
+
if (!shown) {
|
|
2793
|
+
home.current = null;
|
|
2794
|
+
return;
|
|
2795
|
+
}
|
|
2796
|
+
if (home.current?.id !== shown.id) home.current = { id: shown.id, key: null };
|
|
2797
|
+
if (home.current.key === null) {
|
|
2798
|
+
if (loc.itemId === shown.id && loc.mode === "view") home.current.key = key;
|
|
2799
|
+
return;
|
|
2800
|
+
}
|
|
2801
|
+
if (key !== home.current.key) setShown(null);
|
|
2802
|
+
}, [shown, key, loc.itemId, loc.mode]);
|
|
2803
|
+
return [shown, setShown];
|
|
2804
|
+
}
|
|
2805
|
+
|
|
2737
2806
|
// src/lock.ts
|
|
2738
2807
|
import { useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
2739
2808
|
var LOCKED_MESSAGE = "The vault is locked. Unlock it first.";
|
|
@@ -2775,7 +2844,7 @@ function useLocked(lock) {
|
|
|
2775
2844
|
|
|
2776
2845
|
// src/io/BackupPanel.tsx
|
|
2777
2846
|
import { formatFileSize } from "@ai-matrx/kit/format";
|
|
2778
|
-
import { useEffect as
|
|
2847
|
+
import { useEffect as useEffect12, useRef as useRef10, useState as useState16 } from "react";
|
|
2779
2848
|
import { Button as Button12, Field as Field5, SegmentedControl as SegmentedControl3, Switch as Switch3 } from "@ai-matrx/design-system/controls";
|
|
2780
2849
|
import { downloadFile } from "@ai-matrx/kit/download";
|
|
2781
2850
|
import { confirm as confirm4 } from "@ai-matrx/kit/confirm-opener";
|
|
@@ -2868,7 +2937,7 @@ function startNewRestoreRun(preview) {
|
|
|
2868
2937
|
}
|
|
2869
2938
|
|
|
2870
2939
|
// src/io/lines.tsx
|
|
2871
|
-
import { useState as
|
|
2940
|
+
import { useState as useState15 } from "react";
|
|
2872
2941
|
import { Checkbox } from "@ai-matrx/design-system";
|
|
2873
2942
|
import { Badge as Badge4, Button as Button11, DisclosureHeader as DisclosureHeader2 } from "@ai-matrx/design-system/controls";
|
|
2874
2943
|
import { Fragment as Fragment8, jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
@@ -2881,7 +2950,7 @@ function PickLine({ checked, onChange, disabled = false, title, detail, badge, t
|
|
|
2881
2950
|
] });
|
|
2882
2951
|
}
|
|
2883
2952
|
function Windowed({ items, size = 150, render }) {
|
|
2884
|
-
const [all, setAll] =
|
|
2953
|
+
const [all, setAll] = useState15(false);
|
|
2885
2954
|
const shown = all ? items : items.slice(0, size);
|
|
2886
2955
|
return /* @__PURE__ */ jsxs12(Fragment8, { children: [
|
|
2887
2956
|
shown.map(render),
|
|
@@ -2892,7 +2961,7 @@ function Windowed({ items, size = 150, render }) {
|
|
|
2892
2961
|
] });
|
|
2893
2962
|
}
|
|
2894
2963
|
function More({ title = "More", children }) {
|
|
2895
|
-
const [open, setOpen] =
|
|
2964
|
+
const [open, setOpen] = useState15(false);
|
|
2896
2965
|
return /* @__PURE__ */ jsxs12("div", { className: "flex flex-col gap-2", children: [
|
|
2897
2966
|
/* @__PURE__ */ jsx13(DisclosureHeader2, { open, title, onClick: () => setOpen((o) => !o) }),
|
|
2898
2967
|
open ? children : null
|
|
@@ -2932,21 +3001,21 @@ function Omissions({ omissions, accepted, onAccepted, verb }) {
|
|
|
2932
3001
|
function BackupPanel({ port, host, items, onClose, onChanged }) {
|
|
2933
3002
|
const minLength = passphraseMinimum(host.backupPassphraseMinLength);
|
|
2934
3003
|
const confirmed = useConfirmed();
|
|
2935
|
-
const fileInput =
|
|
2936
|
-
const abort =
|
|
2937
|
-
const [mode, setMode] =
|
|
2938
|
-
const [busy, setBusy] =
|
|
2939
|
-
const [error, setError] =
|
|
2940
|
-
const [passphrase, setPassphrase] =
|
|
2941
|
-
const [repeat, setRepeat] =
|
|
2942
|
-
const [accepted, setAccepted] =
|
|
2943
|
-
const [selected, setSelected] =
|
|
2944
|
-
const [backup, setBackup] =
|
|
2945
|
-
const [file, setFile] =
|
|
2946
|
-
const [restorePreview, setRestorePreview] =
|
|
2947
|
-
const [runId, setRunId] =
|
|
2948
|
-
const [result, setResult] =
|
|
2949
|
-
|
|
3004
|
+
const fileInput = useRef10(null);
|
|
3005
|
+
const abort = useRef10(null);
|
|
3006
|
+
const [mode, setMode] = useState16("backup");
|
|
3007
|
+
const [busy, setBusy] = useState16(false);
|
|
3008
|
+
const [error, setError] = useState16(null);
|
|
3009
|
+
const [passphrase, setPassphrase] = useState16("");
|
|
3010
|
+
const [repeat, setRepeat] = useState16("");
|
|
3011
|
+
const [accepted, setAccepted] = useState16(false);
|
|
3012
|
+
const [selected, setSelected] = useState16(/* @__PURE__ */ new Set());
|
|
3013
|
+
const [backup, setBackup] = useState16(null);
|
|
3014
|
+
const [file, setFile] = useState16(null);
|
|
3015
|
+
const [restorePreview, setRestorePreview] = useState16(null);
|
|
3016
|
+
const [runId, setRunId] = useState16(null);
|
|
3017
|
+
const [result, setResult] = useState16(null);
|
|
3018
|
+
useEffect12(() => () => abort.current?.abort(), []);
|
|
2950
3019
|
const switchMode = (next) => {
|
|
2951
3020
|
abort.current?.abort();
|
|
2952
3021
|
setMode(next);
|
|
@@ -3131,7 +3200,7 @@ function tooShort(passphrase, minLength) {
|
|
|
3131
3200
|
}
|
|
3132
3201
|
|
|
3133
3202
|
// src/io/ExportPanel.tsx
|
|
3134
|
-
import { useMemo, useState as
|
|
3203
|
+
import { useMemo, useState as useState17 } from "react";
|
|
3135
3204
|
import { Button as Button13, Select as Select5 } from "@ai-matrx/design-system/controls";
|
|
3136
3205
|
import { downloadFile as downloadFile2 } from "@ai-matrx/kit/download";
|
|
3137
3206
|
import { confirm as confirm5 } from "@ai-matrx/kit/confirm-opener";
|
|
@@ -3156,11 +3225,11 @@ function omissionText2(omissions) {
|
|
|
3156
3225
|
function ExportPanel({ port, items, onClose }) {
|
|
3157
3226
|
const confirmed = useConfirmed();
|
|
3158
3227
|
const logins = useMemo(() => items.filter((i) => i.definitionKey === WEBSITE_LOGIN), [items]);
|
|
3159
|
-
const [profile, setProfile] =
|
|
3160
|
-
const [selected, setSelected] =
|
|
3161
|
-
const [preview, setPreview] =
|
|
3162
|
-
const [busy, setBusy] =
|
|
3163
|
-
const [error, setError] =
|
|
3228
|
+
const [profile, setProfile] = useState17("matrx_login_csv_v1");
|
|
3229
|
+
const [selected, setSelected] = useState17(/* @__PURE__ */ new Set());
|
|
3230
|
+
const [preview, setPreview] = useState17(null);
|
|
3231
|
+
const [busy, setBusy] = useState17(false);
|
|
3232
|
+
const [error, setError] = useState17(null);
|
|
3164
3233
|
const format = FORMATS.find((f) => f.value === profile);
|
|
3165
3234
|
const reasons = new Map(preview?.items.map((p) => [p.item_id, p]) ?? []);
|
|
3166
3235
|
const eligible = preview?.items.filter((p) => p.eligible).length ?? 0;
|
|
@@ -3285,7 +3354,7 @@ function ExportPanel({ port, items, onClose }) {
|
|
|
3285
3354
|
}
|
|
3286
3355
|
|
|
3287
3356
|
// src/io/ImportPanel.tsx
|
|
3288
|
-
import { useEffect as
|
|
3357
|
+
import { useEffect as useEffect13, useMemo as useMemo2, useRef as useRef11, useState as useState18 } from "react";
|
|
3289
3358
|
import { Button as Button14, Select as Select6, Switch as Switch4, Textarea as Textarea2 } from "@ai-matrx/design-system/controls";
|
|
3290
3359
|
|
|
3291
3360
|
// src/io/csv-import.ts
|
|
@@ -4147,25 +4216,25 @@ var STATE_BADGE = {
|
|
|
4147
4216
|
var ME = "me";
|
|
4148
4217
|
function ImportPanel({ port, host, items, definitions, organizations, onClose, onChanged, limits }) {
|
|
4149
4218
|
const confirmed = useConfirmed();
|
|
4150
|
-
const [otpFor, setOtpFor] =
|
|
4151
|
-
const fileInput =
|
|
4152
|
-
const abort =
|
|
4153
|
-
const stop =
|
|
4154
|
-
const keys =
|
|
4155
|
-
const [source, setSource] =
|
|
4156
|
-
const [envText, setEnvText] =
|
|
4157
|
-
const [injectSandbox, setInjectSandbox] =
|
|
4158
|
-
const [fileName, setFileName] =
|
|
4159
|
-
const [reading, setReading] =
|
|
4160
|
-
const [draft, setDraft] =
|
|
4161
|
-
const [destination, setDestination] =
|
|
4162
|
-
const [browserFill, setBrowserFill] =
|
|
4163
|
-
const [approvedVisible, setApprovedVisible] =
|
|
4164
|
-
const [selected, setSelected] =
|
|
4165
|
-
const [running, setRunning] =
|
|
4166
|
-
const [done, setDone] =
|
|
4167
|
-
const [error, setError] =
|
|
4168
|
-
|
|
4219
|
+
const [otpFor, setOtpFor] = useState18(null);
|
|
4220
|
+
const fileInput = useRef11(null);
|
|
4221
|
+
const abort = useRef11(null);
|
|
4222
|
+
const stop = useRef11(false);
|
|
4223
|
+
const keys = useRef11(/* @__PURE__ */ new Map());
|
|
4224
|
+
const [source, setSource] = useState18("auto");
|
|
4225
|
+
const [envText, setEnvText] = useState18("");
|
|
4226
|
+
const [injectSandbox, setInjectSandbox] = useState18(false);
|
|
4227
|
+
const [fileName, setFileName] = useState18(null);
|
|
4228
|
+
const [reading, setReading] = useState18(false);
|
|
4229
|
+
const [draft, setDraft] = useState18(null);
|
|
4230
|
+
const [destination, setDestination] = useState18(ME);
|
|
4231
|
+
const [browserFill, setBrowserFill] = useState18(false);
|
|
4232
|
+
const [approvedVisible, setApprovedVisible] = useState18(false);
|
|
4233
|
+
const [selected, setSelected] = useState18(/* @__PURE__ */ new Set());
|
|
4234
|
+
const [running, setRunning] = useState18(null);
|
|
4235
|
+
const [done, setDone] = useState18(null);
|
|
4236
|
+
const [error, setError] = useState18(null);
|
|
4237
|
+
useEffect13(
|
|
4169
4238
|
() => () => {
|
|
4170
4239
|
abort.current?.abort();
|
|
4171
4240
|
stop.current = true;
|
|
@@ -4452,14 +4521,14 @@ function Notices({ draft }) {
|
|
|
4452
4521
|
}
|
|
4453
4522
|
|
|
4454
4523
|
// src/ItemList.tsx
|
|
4455
|
-
import { useEffect as
|
|
4524
|
+
import { useEffect as useEffect16, useRef as useRef14, useState as useState27 } from "react";
|
|
4456
4525
|
import { DropdownMenu as DropdownMenu4, DropdownMenuContent as DropdownMenuContent4, DropdownMenuItem as DropdownMenuItem4, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator as DropdownMenuSeparator4, DropdownMenuTrigger as DropdownMenuTrigger4 } from "@ai-matrx/design-system";
|
|
4457
4526
|
import { cn as cn11 } from "@ai-matrx/design-system";
|
|
4458
4527
|
import { Button as Button22, SearchField, Tile as Tile3 } from "@ai-matrx/design-system/controls";
|
|
4459
4528
|
import { CopyIcon as CopyIcon7 } from "@ai-matrx/design-system/icons";
|
|
4460
4529
|
|
|
4461
4530
|
// src/ItemPane.tsx
|
|
4462
|
-
import { Fragment as Fragment16, useEffect as
|
|
4531
|
+
import { Fragment as Fragment16, useEffect as useEffect15, useMemo as useMemo3, useRef as useRef13, useState as useState26 } from "react";
|
|
4463
4532
|
import { DropdownMenu as DropdownMenu3, DropdownMenuContent as DropdownMenuContent3, DropdownMenuItem as DropdownMenuItem3, DropdownMenuSeparator as DropdownMenuSeparator3, DropdownMenuTrigger as DropdownMenuTrigger3 } from "@ai-matrx/design-system";
|
|
4464
4533
|
import { cn as cn10 } from "@ai-matrx/design-system";
|
|
4465
4534
|
import { Badge as Badge7, Button as Button21, CONTROLS_CONTAINER_CLASS, OptionCombobox, Switch as Switch6 } from "@ai-matrx/design-system/controls";
|
|
@@ -4467,7 +4536,7 @@ import { confirm as confirm10 } from "@ai-matrx/kit/confirm-opener";
|
|
|
4467
4536
|
|
|
4468
4537
|
// src/activity/FilesSection.tsx
|
|
4469
4538
|
import { formatFileSize as formatFileSize2 } from "@ai-matrx/kit/format";
|
|
4470
|
-
import { useRef as
|
|
4539
|
+
import { useRef as useRef12, useState as useState19 } from "react";
|
|
4471
4540
|
import { Badge as Badge5, Button as Button15, Field as Field6, SegmentedControl as SegmentedControl4 } from "@ai-matrx/design-system/controls";
|
|
4472
4541
|
import { cn as cn7 } from "@ai-matrx/design-system";
|
|
4473
4542
|
import { confirm as confirm6 } from "@ai-matrx/kit/confirm-opener";
|
|
@@ -4485,11 +4554,11 @@ function FilesSection({ item, port, editing, onChanged }) {
|
|
|
4485
4554
|
const confirmed = useConfirmed();
|
|
4486
4555
|
const canEdit = editing && item.capabilities.canEdit;
|
|
4487
4556
|
const canAdd = item.capabilities.canEdit;
|
|
4488
|
-
const [busy, setBusy] =
|
|
4489
|
-
const [error, setError] =
|
|
4490
|
-
const [pending, setPending] =
|
|
4491
|
-
const [dragging, setDragging] =
|
|
4492
|
-
const picker =
|
|
4557
|
+
const [busy, setBusy] = useState19(null);
|
|
4558
|
+
const [error, setError] = useState19(null);
|
|
4559
|
+
const [pending, setPending] = useState19(null);
|
|
4560
|
+
const [dragging, setDragging] = useState19(false);
|
|
4561
|
+
const picker = useRef12(null);
|
|
4493
4562
|
if (!canAdd && item.attachments.length === 0) return null;
|
|
4494
4563
|
async function run(key, work, fallback) {
|
|
4495
4564
|
setBusy(key);
|
|
@@ -4566,8 +4635,8 @@ function FilesSection({ item, port, editing, onChanged }) {
|
|
|
4566
4635
|
);
|
|
4567
4636
|
}
|
|
4568
4637
|
function EditableFile({ port, item: it, file: a, busy: b, run: go, onDownload, onTooBig }) {
|
|
4569
|
-
const [open, setOpen] =
|
|
4570
|
-
const replacer =
|
|
4638
|
+
const [open, setOpen] = useState19(false);
|
|
4639
|
+
const replacer = useRef12(null);
|
|
4571
4640
|
async function remove() {
|
|
4572
4641
|
const yes = await confirm6({ title: `Delete ${a.label}?`, description: "The encrypted file is removed from this item.", confirmLabel: "Delete", variant: "destructive" });
|
|
4573
4642
|
if (yes) await go(`delete:${a.id}`, () => port.activity.deleteFile(it, a.id), "The file could not be deleted.");
|
|
@@ -4625,9 +4694,9 @@ function Protection({ value, locked, onChange }) {
|
|
|
4625
4694
|
);
|
|
4626
4695
|
}
|
|
4627
4696
|
function NewFile({ file, busy, onAdd, onCancel }) {
|
|
4628
|
-
const [label, setLabel] =
|
|
4629
|
-
const [description, setDescription] =
|
|
4630
|
-
const [handling, setHandling] =
|
|
4697
|
+
const [label, setLabel] = useState19(file.name);
|
|
4698
|
+
const [description, setDescription] = useState19("");
|
|
4699
|
+
const [handling, setHandling] = useState19("revealable");
|
|
4631
4700
|
async function add() {
|
|
4632
4701
|
if (handling === "sealed" && !await confirmSeal(label)) return;
|
|
4633
4702
|
await onAdd({ label: label.trim(), description: description.trim() || null, handling });
|
|
@@ -4647,10 +4716,10 @@ function NewFile({ file, busy, onAdd, onCancel }) {
|
|
|
4647
4716
|
] });
|
|
4648
4717
|
}
|
|
4649
4718
|
function FileDetailsRows({ file, busy, onSave, onCancel }) {
|
|
4650
|
-
const [label, setLabel] =
|
|
4651
|
-
const [description, setDescription] =
|
|
4652
|
-
const [fileName, setFileName] =
|
|
4653
|
-
const [handling, setHandling] =
|
|
4719
|
+
const [label, setLabel] = useState19(file.label);
|
|
4720
|
+
const [description, setDescription] = useState19(file.description);
|
|
4721
|
+
const [fileName, setFileName] = useState19(file.fileName);
|
|
4722
|
+
const [handling, setHandling] = useState19(file.handling);
|
|
4654
4723
|
const changed = label !== file.label || description !== file.description || fileName !== file.fileName || handling !== file.handling;
|
|
4655
4724
|
async function save() {
|
|
4656
4725
|
if (handling === "sealed" && file.handling !== "sealed" && !await confirmSeal(label)) return;
|
|
@@ -4676,10 +4745,10 @@ function confirmSeal(label) {
|
|
|
4676
4745
|
});
|
|
4677
4746
|
}
|
|
4678
4747
|
function DraftFilesSection({ files, onFiles }) {
|
|
4679
|
-
const [pending, setPending] =
|
|
4680
|
-
const [error, setError] =
|
|
4681
|
-
const [dragging, setDragging] =
|
|
4682
|
-
const picker =
|
|
4748
|
+
const [pending, setPending] = useState19(null);
|
|
4749
|
+
const [error, setError] = useState19(null);
|
|
4750
|
+
const [dragging, setDragging] = useState19(false);
|
|
4751
|
+
const picker = useRef12(null);
|
|
4683
4752
|
const choose = (file) => {
|
|
4684
4753
|
if (!file) return;
|
|
4685
4754
|
if (fileTooBig(file.size)) return setError(TOO_BIG);
|
|
@@ -4728,7 +4797,7 @@ function DraftFilesSection({ files, onFiles }) {
|
|
|
4728
4797
|
}
|
|
4729
4798
|
|
|
4730
4799
|
// src/fields/RecoveryCodesRow.tsx
|
|
4731
|
-
import { useState as
|
|
4800
|
+
import { useState as useState20 } from "react";
|
|
4732
4801
|
import { Badge as Badge6, Button as Button16, Textarea as Textarea3 } from "@ai-matrx/design-system/controls";
|
|
4733
4802
|
import { CopyIcon as CopyIcon6 } from "@ai-matrx/design-system/icons";
|
|
4734
4803
|
import { Fragment as Fragment13, jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
@@ -4738,9 +4807,9 @@ function RecoveryCodesRow({ item, field, port, onChanged }) {
|
|
|
4738
4807
|
const confirmed = useConfirmed();
|
|
4739
4808
|
const copyValue2 = useCopy();
|
|
4740
4809
|
const secret = useTransientSecret();
|
|
4741
|
-
const [busy, setBusy] =
|
|
4742
|
-
const [error, setError] =
|
|
4743
|
-
const [draft, setDraft] =
|
|
4810
|
+
const [busy, setBusy] = useState20(false);
|
|
4811
|
+
const [error, setError] = useState20(null);
|
|
4812
|
+
const [draft, setDraft] = useState20(null);
|
|
4744
4813
|
const canEdit = item.capabilities.canEdit;
|
|
4745
4814
|
const run = async (step) => {
|
|
4746
4815
|
setBusy(true);
|
|
@@ -4835,7 +4904,7 @@ function RecoveryCodesRow({ item, field, port, onChanged }) {
|
|
|
4835
4904
|
}
|
|
4836
4905
|
|
|
4837
4906
|
// src/fields/DraftRows.tsx
|
|
4838
|
-
import { useState as
|
|
4907
|
+
import { useState as useState21 } from "react";
|
|
4839
4908
|
import { Button as Button17, Field as Field7, SegmentedControl as SegmentedControl5, Select as Select7, Switch as Switch5 } from "@ai-matrx/design-system/controls";
|
|
4840
4909
|
import { RecordId } from "@ai-matrx/design-system";
|
|
4841
4910
|
import { confirm as confirm7 } from "@ai-matrx/kit/confirm-opener";
|
|
@@ -4890,7 +4959,7 @@ function FieldSettingsRows({ name, value, defaultHandling = "revealable", onChan
|
|
|
4890
4959
|
var hasSecretSettings = (s) => saysMore(s, "revealable");
|
|
4891
4960
|
var hasDeclaredSettings = (s, defaultHandling) => Boolean(s && saysMore(s, defaultHandling));
|
|
4892
4961
|
function SecretBuilderRow({ field, onChange, onRemove }) {
|
|
4893
|
-
const [open, setOpen] =
|
|
4962
|
+
const [open, setOpen] = useState21(hasSecretSettings(field));
|
|
4894
4963
|
const handling = field.handling ?? "revealable";
|
|
4895
4964
|
const name = field.label.trim() || "Secret";
|
|
4896
4965
|
return /* @__PURE__ */ jsxs18(Fragment14, { children: [
|
|
@@ -5131,7 +5200,7 @@ function targetLabel(t) {
|
|
|
5131
5200
|
}
|
|
5132
5201
|
|
|
5133
5202
|
// src/extension/UseOnSiteButton.tsx
|
|
5134
|
-
import { useState as
|
|
5203
|
+
import { useState as useState22 } from "react";
|
|
5135
5204
|
import { Button as Button18 } from "@ai-matrx/design-system/controls";
|
|
5136
5205
|
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
5137
5206
|
function canUseOnSite(item, pageUrl) {
|
|
@@ -5139,7 +5208,7 @@ function canUseOnSite(item, pageUrl) {
|
|
|
5139
5208
|
}
|
|
5140
5209
|
function UseOnSiteButton({ port, item, pageUrl, onChanged }) {
|
|
5141
5210
|
const notify = useNotify();
|
|
5142
|
-
const [busy, setBusy] =
|
|
5211
|
+
const [busy, setBusy] = useState22(false);
|
|
5143
5212
|
if (!canUseOnSite(item, pageUrl)) return null;
|
|
5144
5213
|
const site = pageSite(pageUrl);
|
|
5145
5214
|
const run = async () => {
|
|
@@ -5158,7 +5227,7 @@ function UseOnSiteButton({ port, item, pageUrl, onChanged }) {
|
|
|
5158
5227
|
}
|
|
5159
5228
|
|
|
5160
5229
|
// src/sharing/SharePanel.tsx
|
|
5161
|
-
import { useEffect as
|
|
5230
|
+
import { useEffect as useEffect14, useState as useState25 } from "react";
|
|
5162
5231
|
import { confirm as confirm9 } from "@ai-matrx/kit/confirm-opener";
|
|
5163
5232
|
import { Button as Button20, DisclosureHeader as DisclosureHeader3, Field as Field9, RegionSkeleton, Select as Select9 } from "@ai-matrx/design-system/controls";
|
|
5164
5233
|
import { cn as cn9 } from "@ai-matrx/design-system";
|
|
@@ -5181,14 +5250,17 @@ function isEmail(value) {
|
|
|
5181
5250
|
}
|
|
5182
5251
|
var PERSONAL = "personal";
|
|
5183
5252
|
var destinationOf = (key) => key === PERSONAL ? null : key;
|
|
5253
|
+
var orgChoice = (o, hints) => ({ value: o.id, label: o.name, ...hints.has(o.id) ? { hint: hints.get(o.id) } : {} });
|
|
5184
5254
|
function moveDestinations(item, orgs) {
|
|
5185
5255
|
if (item.owner.kind === "shared") return [];
|
|
5186
5256
|
const here = item.owner.organizationId;
|
|
5187
|
-
|
|
5257
|
+
const hints = organizationHints(orgs);
|
|
5258
|
+
return [...here ? [{ value: PERSONAL, label: "Personal" }] : [], ...orgs.filter((o) => o.id !== here).map((o) => orgChoice(o, hints))];
|
|
5188
5259
|
}
|
|
5189
5260
|
function copyDestinations(orgs, item) {
|
|
5190
5261
|
const here = item ? item.owner.kind === "me" ? PERSONAL : item.owner.organizationId : void 0;
|
|
5191
|
-
|
|
5262
|
+
const hints = organizationHints(orgs);
|
|
5263
|
+
return [{ value: PERSONAL, label: "Personal" }, ...orgs.map((o) => orgChoice(o, hints))].filter((d) => d.value !== here);
|
|
5192
5264
|
}
|
|
5193
5265
|
function copyRefusal(message2) {
|
|
5194
5266
|
return /duplicate/i.test(message2) ? "There is already a copy of this item there." : null;
|
|
@@ -5216,7 +5288,7 @@ function shareSummary(grants) {
|
|
|
5216
5288
|
var MEMBER_CHOICE_DEFAULT = "default";
|
|
5217
5289
|
|
|
5218
5290
|
// src/sharing/parts.tsx
|
|
5219
|
-
import { useState as
|
|
5291
|
+
import { useState as useState23 } from "react";
|
|
5220
5292
|
import { cn as cn8 } from "@ai-matrx/design-system";
|
|
5221
5293
|
import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
5222
5294
|
var message = (e, fallback) => {
|
|
@@ -5225,9 +5297,9 @@ var message = (e, fallback) => {
|
|
|
5225
5297
|
};
|
|
5226
5298
|
function useConfirmedChange() {
|
|
5227
5299
|
const confirmed = useConfirmed();
|
|
5228
|
-
const [busy, setBusy] =
|
|
5229
|
-
const [error, setError] =
|
|
5230
|
-
const [notice, setNotice] =
|
|
5300
|
+
const [busy, setBusy] = useState23(null);
|
|
5301
|
+
const [error, setError] = useState23(null);
|
|
5302
|
+
const [notice, setNotice] = useState23(null);
|
|
5231
5303
|
async function run(key, fn, done) {
|
|
5232
5304
|
setBusy(key);
|
|
5233
5305
|
setError(null);
|
|
@@ -5261,18 +5333,20 @@ function StatusLine({ error, notice }) {
|
|
|
5261
5333
|
}
|
|
5262
5334
|
|
|
5263
5335
|
// src/sharing/MovePanel.tsx
|
|
5264
|
-
import { useState as
|
|
5336
|
+
import { useState as useState24 } from "react";
|
|
5265
5337
|
import { confirm as confirm8 } from "@ai-matrx/kit/confirm-opener";
|
|
5266
5338
|
import { Button as Button19, Field as Field8, Select as Select8 } from "@ai-matrx/design-system/controls";
|
|
5267
5339
|
import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
5268
5340
|
var NONE = "__none__";
|
|
5269
|
-
function MovePanel({ item, port, organizations, onClose, onChanged }) {
|
|
5341
|
+
function MovePanel({ item, port, host, organizations, onClose, onChanged, onOpenItem }) {
|
|
5270
5342
|
const { busy, error, notice, run, setNotice } = useConfirmedChange();
|
|
5271
5343
|
const moves = moveDestinations(item, organizations);
|
|
5272
5344
|
const copies = copyDestinations(organizations, item);
|
|
5273
|
-
const [moveTo, setMoveTo] =
|
|
5274
|
-
const [copyTo, setCopyTo] =
|
|
5275
|
-
const [email, setEmail] =
|
|
5345
|
+
const [moveTo, setMoveTo] = useState24("");
|
|
5346
|
+
const [copyTo, setCopyTo] = useState24("");
|
|
5347
|
+
const [email, setEmail] = useState24("");
|
|
5348
|
+
const [made, setMade] = useState24(null);
|
|
5349
|
+
const searchAt = host.organizationSearchAt ?? ORGANIZATION_SEARCH_AT_UNREAD;
|
|
5276
5350
|
const passkey = isPasskey(item);
|
|
5277
5351
|
const canMove = item.capabilities.canManage && !passkey && moves.length > 0;
|
|
5278
5352
|
const canGive = item.capabilities.canManage && item.owner.kind === "me" && !passkey;
|
|
@@ -5306,8 +5380,10 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
|
|
|
5306
5380
|
};
|
|
5307
5381
|
const copy = async () => {
|
|
5308
5382
|
if (!copyChoice) return;
|
|
5309
|
-
const
|
|
5310
|
-
if (
|
|
5383
|
+
const copied = await run("copy", () => port.sharing.copy(item, destinationOf(copyChoice.value)), `Copy made in ${copyChoice.label}`);
|
|
5384
|
+
if (!copied) return;
|
|
5385
|
+
setMade(copied);
|
|
5386
|
+
onChanged();
|
|
5311
5387
|
};
|
|
5312
5388
|
const nothing = !canMove && !canGive && !canCopy;
|
|
5313
5389
|
return /* @__PURE__ */ jsx22(
|
|
@@ -5316,7 +5392,10 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
|
|
|
5316
5392
|
title: "Move or copy",
|
|
5317
5393
|
size: "md",
|
|
5318
5394
|
onClose,
|
|
5319
|
-
footer: /* @__PURE__ */
|
|
5395
|
+
footer: /* @__PURE__ */ jsxs20(PanelFooter, { status: error || notice ? /* @__PURE__ */ jsx22(StatusLine, { error, notice }) : null, children: [
|
|
5396
|
+
made && onOpenItem ? /* @__PURE__ */ jsx22(Button19, { variant: "outline", onClick: () => onOpenItem(made), children: "Open copy" }) : null,
|
|
5397
|
+
/* @__PURE__ */ jsx22(Button19, { variant: "primary", onClick: onClose, children: "Done" })
|
|
5398
|
+
] }),
|
|
5320
5399
|
children: nothing ? /* @__PURE__ */ jsx22(VaultSection, { children: /* @__PURE__ */ jsx22(Empty, { children: passkey ? "A passkey stays where it was created." : "Only the owner can move or give this item." }) }) : /* @__PURE__ */ jsxs20(VaultSection, { children: [
|
|
5321
5400
|
canMove && moves.length > 0 ? /* @__PURE__ */ jsx22(
|
|
5322
5401
|
VaultRow,
|
|
@@ -5324,7 +5403,7 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
|
|
|
5324
5403
|
label: "Move to",
|
|
5325
5404
|
hint: moveChoice ? itemMoveConsequence(item, destinationOf(moveChoice.value)) : void 0,
|
|
5326
5405
|
actions: /* @__PURE__ */ jsx22(Button19, { variant: "outline", disabled: busy !== null || !moveChoice, onClick: () => void move(), children: "Move" }),
|
|
5327
|
-
children: /* @__PURE__ */ jsx22(Select8, { className: "w-full", "aria-label": "Move to", value: moveTo || NONE, onValueChange: (v) => setMoveTo(v === NONE ? "" : v), options: [{ value: NONE, label: "Choose where" }, ...moves] })
|
|
5406
|
+
children: /* @__PURE__ */ jsx22(Select8, { className: "w-full", "aria-label": "Move to", searchAt, value: moveTo || NONE, onValueChange: (v) => setMoveTo(v === NONE ? "" : v), options: [{ value: NONE, label: "Choose where" }, ...moves] })
|
|
5328
5407
|
}
|
|
5329
5408
|
) : null,
|
|
5330
5409
|
canGive ? /* @__PURE__ */ jsx22(VaultRow, { label: "Give to", hint: "You lose all access; your shares end", actions: /* @__PURE__ */ jsx22(Button19, { variant: "danger", disabled: busy !== null || !isEmail(email), onClick: () => void give(), children: "Give" }), children: /* @__PURE__ */ jsx22(
|
|
@@ -5341,7 +5420,7 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
|
|
|
5341
5420
|
onChange: (e) => setEmail(e.target.value)
|
|
5342
5421
|
}
|
|
5343
5422
|
) }) : null,
|
|
5344
|
-
canCopy && copies.length > 0 ? /* @__PURE__ */ jsx22(VaultRow, { label: "Copy to", hint: "A separate item; edits no longer sync", actions: /* @__PURE__ */ jsx22(Button19, { variant: "outline", disabled: busy !== null || !copyChoice, onClick: () => void copy(), children: "Copy" }), children: /* @__PURE__ */ jsx22(Select8, { className: "w-full", "aria-label": "Copy to", value: copyTo || NONE, onValueChange: (v) => setCopyTo(v === NONE ? "" : v), options: [{ value: NONE, label: "Choose where" }, ...copies] }) }) : null
|
|
5423
|
+
canCopy && copies.length > 0 ? /* @__PURE__ */ jsx22(VaultRow, { label: "Copy to", hint: "A separate item; edits no longer sync", actions: /* @__PURE__ */ jsx22(Button19, { variant: "outline", disabled: busy !== null || !copyChoice, onClick: () => void copy(), children: "Copy" }), children: /* @__PURE__ */ jsx22(Select8, { className: "w-full", "aria-label": "Copy to", searchAt, value: copyTo || NONE, onValueChange: (v) => setCopyTo(v === NONE ? "" : v), options: [{ value: NONE, label: "Choose where" }, ...copies] }) }) : null
|
|
5345
5424
|
] })
|
|
5346
5425
|
}
|
|
5347
5426
|
);
|
|
@@ -5350,11 +5429,11 @@ function MovePanel({ item, port, organizations, onClose, onChanged }) {
|
|
|
5350
5429
|
// src/sharing/SharePanel.tsx
|
|
5351
5430
|
import { Fragment as Fragment15, jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
5352
5431
|
function useGrants(port, item) {
|
|
5353
|
-
const [grants, setGrants] =
|
|
5354
|
-
const [loadError, setLoadError] =
|
|
5355
|
-
const [nonce, setNonce] =
|
|
5432
|
+
const [grants, setGrants] = useState25(null);
|
|
5433
|
+
const [loadError, setLoadError] = useState25(null);
|
|
5434
|
+
const [nonce, setNonce] = useState25(0);
|
|
5356
5435
|
const allowed = item.capabilities.canManage;
|
|
5357
|
-
|
|
5436
|
+
useEffect14(() => {
|
|
5358
5437
|
if (!allowed) return;
|
|
5359
5438
|
let live = true;
|
|
5360
5439
|
setLoadError(null);
|
|
@@ -5371,9 +5450,9 @@ function useGrants(port, item) {
|
|
|
5371
5450
|
function SharePanel({ item, port, organizations, onClose, onChanged }) {
|
|
5372
5451
|
const { grants, setGrants, loadError, reload } = useGrants(port, item);
|
|
5373
5452
|
const { busy, error, notice, run } = useConfirmedChange();
|
|
5374
|
-
const [email, setEmail] =
|
|
5375
|
-
const [level, setLevel] =
|
|
5376
|
-
const [more, setMore] =
|
|
5453
|
+
const [email, setEmail] = useState25("");
|
|
5454
|
+
const [level, setLevel] = useState25("use");
|
|
5455
|
+
const [more, setMore] = useState25(false);
|
|
5377
5456
|
const isOrg = item.owner.kind === "organization" && item.owner.organizationId !== null;
|
|
5378
5457
|
const orgName = item.owner.label;
|
|
5379
5458
|
const people = (grants ?? []).filter((g) => g.kind === "person");
|
|
@@ -5492,8 +5571,8 @@ function SharePanel({ item, port, organizations, onClose, onChanged }) {
|
|
|
5492
5571
|
function IntoOrganization({ item, port, organizations, grants, onShared }) {
|
|
5493
5572
|
const { busy, error, notice, run } = useConfirmedChange();
|
|
5494
5573
|
const open = organizations.filter((o) => !grants.some((g) => g.organizationId === o.id));
|
|
5495
|
-
const [target, setTarget] =
|
|
5496
|
-
const [level, setLevel] =
|
|
5574
|
+
const [target, setTarget] = useState25("");
|
|
5575
|
+
const [level, setLevel] = useState25("use");
|
|
5497
5576
|
const chosen = open.find((o) => o.id === target);
|
|
5498
5577
|
if (item.owner.kind !== "me") return null;
|
|
5499
5578
|
return /* @__PURE__ */ jsx23(VaultSection, { title: "Share into organization", children: open.length > 0 ? /* @__PURE__ */ jsxs21(Fragment15, { children: [
|
|
@@ -5528,10 +5607,10 @@ var CHOICES = [
|
|
|
5528
5607
|
{ value: "editor", label: "Can edit", meta: "See and change" }
|
|
5529
5608
|
];
|
|
5530
5609
|
function MemberAccess({ port, organizationId, organizationName }) {
|
|
5531
|
-
const [list, setList] =
|
|
5532
|
-
const [loadError, setLoadError] =
|
|
5610
|
+
const [list, setList] = useState25(null);
|
|
5611
|
+
const [loadError, setLoadError] = useState25(null);
|
|
5533
5612
|
const { busy, error, run } = useConfirmedChange();
|
|
5534
|
-
|
|
5613
|
+
useEffect14(() => {
|
|
5535
5614
|
let live = true;
|
|
5536
5615
|
port.sharing.memberAccess(organizationId).then(
|
|
5537
5616
|
(l) => live && setList(l),
|
|
@@ -5563,9 +5642,9 @@ function MemberAccess({ port, organizationId, organizationName }) {
|
|
|
5563
5642
|
] });
|
|
5564
5643
|
}
|
|
5565
5644
|
function SharingSummary({ item, port, className }) {
|
|
5566
|
-
const [text, setText] =
|
|
5645
|
+
const [text, setText] = useState25("");
|
|
5567
5646
|
const allowed = item.capabilities.canManage;
|
|
5568
|
-
|
|
5647
|
+
useEffect14(() => {
|
|
5569
5648
|
if (!allowed) return;
|
|
5570
5649
|
let live = true;
|
|
5571
5650
|
port.sharing.grants(item).then(
|
|
@@ -5596,7 +5675,7 @@ function ItemPane(props) {
|
|
|
5596
5675
|
const editing = mode !== "view";
|
|
5597
5676
|
const seedName = seed?.name ?? "";
|
|
5598
5677
|
const seedUrl = seed?.url ?? "";
|
|
5599
|
-
const [loaded, setLoaded] =
|
|
5678
|
+
const [loaded, setLoaded] = useState26({});
|
|
5600
5679
|
const base = useMemo3(() => {
|
|
5601
5680
|
const b = draftOf(item);
|
|
5602
5681
|
if (!item) {
|
|
@@ -5606,28 +5685,28 @@ function ItemPane(props) {
|
|
|
5606
5685
|
b.values = { ...loaded };
|
|
5607
5686
|
return b;
|
|
5608
5687
|
}, [item, seedName, seedUrl, loaded]);
|
|
5609
|
-
const [draft, setDraft] =
|
|
5610
|
-
const [tagsText, setTagsText] =
|
|
5611
|
-
const [showTags, setShowTags] =
|
|
5612
|
-
const [showDescription, setShowDescription] =
|
|
5613
|
-
const [showRecovery, setShowRecovery] =
|
|
5614
|
-
const [settingUpOtp, setSettingUpOtp] =
|
|
5615
|
-
const [owner, setOwner] =
|
|
5616
|
-
const [recipient, setRecipient] =
|
|
5617
|
-
const [generatePrivately, setGeneratePrivately] =
|
|
5618
|
-
const [busy, setBusy] =
|
|
5619
|
-
const [sent, setSent] =
|
|
5620
|
-
const [queuedFiles, setQueuedFiles] =
|
|
5621
|
-
const [showBrowser, setShowBrowser] =
|
|
5622
|
-
const [error, setError] =
|
|
5623
|
-
const [destinations, setDestinations] =
|
|
5624
|
-
const [savedNew, setSavedNew] =
|
|
5688
|
+
const [draft, setDraft] = useState26(base);
|
|
5689
|
+
const [tagsText, setTagsText] = useState26(base.tags.join(", "));
|
|
5690
|
+
const [showTags, setShowTags] = useState26(false);
|
|
5691
|
+
const [showDescription, setShowDescription] = useState26(false);
|
|
5692
|
+
const [showRecovery, setShowRecovery] = useState26(false);
|
|
5693
|
+
const [settingUpOtp, setSettingUpOtp] = useState26(false);
|
|
5694
|
+
const [owner, setOwner] = useState26(defaultOwner ?? "me");
|
|
5695
|
+
const [recipient, setRecipient] = useState26("");
|
|
5696
|
+
const [generatePrivately, setGeneratePrivately] = useState26(false);
|
|
5697
|
+
const [busy, setBusy] = useState26(false);
|
|
5698
|
+
const [sent, setSent] = useState26(null);
|
|
5699
|
+
const [queuedFiles, setQueuedFiles] = useState26([]);
|
|
5700
|
+
const [showBrowser, setShowBrowser] = useState26(false);
|
|
5701
|
+
const [error, setError] = useState26(null);
|
|
5702
|
+
const [destinations, setDestinations] = useState26({});
|
|
5703
|
+
const [savedNew, setSavedNew] = useState26(false);
|
|
5625
5704
|
const dirty = editing && !savedNew && isDirty(base, draft);
|
|
5626
5705
|
const declared = definition?.fields ?? [];
|
|
5627
|
-
const prev =
|
|
5628
|
-
const paneRef =
|
|
5706
|
+
const prev = useRef13(null);
|
|
5707
|
+
const paneRef = useRef13(null);
|
|
5629
5708
|
const room = useRoomOf(paneRef);
|
|
5630
|
-
|
|
5709
|
+
useEffect15(() => {
|
|
5631
5710
|
const was = prev.current;
|
|
5632
5711
|
const id = item?.id ?? null;
|
|
5633
5712
|
if (was && was.id === id && was.mode === mode && editing) {
|
|
@@ -5640,22 +5719,22 @@ function ItemPane(props) {
|
|
|
5640
5719
|
}
|
|
5641
5720
|
prev.current = { base, id, mode };
|
|
5642
5721
|
}, [base, mode, item?.id, editing]);
|
|
5643
|
-
|
|
5722
|
+
useEffect15(() => {
|
|
5644
5723
|
setLoaded({});
|
|
5645
5724
|
setShowTags(false);
|
|
5646
5725
|
setShowDescription(false);
|
|
5647
5726
|
setShowRecovery(false);
|
|
5648
5727
|
setSavedNew(false);
|
|
5649
5728
|
}, [item?.id, mode]);
|
|
5650
|
-
const onDirtyRef =
|
|
5729
|
+
const onDirtyRef = useRef13(onDirty);
|
|
5651
5730
|
onDirtyRef.current = onDirty;
|
|
5652
|
-
|
|
5731
|
+
useEffect15(() => onDirtyRef.current(dirty), [dirty]);
|
|
5653
5732
|
const keepKey = draftKey(item?.id ?? null, definition?.key ?? item?.definitionKey ?? null);
|
|
5654
|
-
|
|
5733
|
+
useEffect15(() => {
|
|
5655
5734
|
if (editing && dirty) keepDraft(keepKey, keptFieldsOf(draft), { basedOn: item?.updatedAt ?? "new" });
|
|
5656
5735
|
else if (!editing) dropKeptDraft(keepKey);
|
|
5657
5736
|
}, [editing, dirty, draft, keepKey, item?.updatedAt]);
|
|
5658
|
-
|
|
5737
|
+
useEffect15(() => {
|
|
5659
5738
|
if (!editing || !item) return;
|
|
5660
5739
|
let live = true;
|
|
5661
5740
|
for (const f of item.fields) {
|
|
@@ -5780,7 +5859,7 @@ function ItemPane(props) {
|
|
|
5780
5859
|
const turnOnOne = canTurnOn ? (f) => () => turnOn([f]) : () => void 0;
|
|
5781
5860
|
const declaredKeys = new Set(declared.map((f) => f.key));
|
|
5782
5861
|
const hasSecureNote = declaredKeys.has(SECURE_NOTE_KEY) || Boolean(item?.fields.some((f) => f.key === SECURE_NOTE_KEY)) || draft.secrets.some((x) => x.key === SECURE_NOTE_KEY);
|
|
5783
|
-
const [settingsToggled, setSettingsToggled] =
|
|
5862
|
+
const [settingsToggled, setSettingsToggled] = useState26(/* @__PURE__ */ new Set());
|
|
5784
5863
|
const settingsOpen = (f) => settingsToggled.has(f.key) !== (definition?.key === ENV_VALUE_KEY || hasDeclaredSettings(draft.fieldSettings?.[f.key], f.handling));
|
|
5785
5864
|
const toggleSettings = (key) => setSettingsToggled((cur) => {
|
|
5786
5865
|
const next = new Set(cur);
|
|
@@ -6157,8 +6236,8 @@ function ItemList({ title, items, definitions, port, selectedId, onSelect, query
|
|
|
6157
6236
|
const pinned = matchingIds ? items.filter((i) => matchingIds.has(i.id)) : [];
|
|
6158
6237
|
const rest = matchingIds ? items.filter((i) => !matchingIds.has(i.id)) : items;
|
|
6159
6238
|
const ordered = [...pinned, ...rest];
|
|
6160
|
-
const listRef =
|
|
6161
|
-
|
|
6239
|
+
const listRef = useRef14(null);
|
|
6240
|
+
useEffect16(() => {
|
|
6162
6241
|
if (selectedId) listRef.current?.querySelector(`[data-item="${selectedId}"]`)?.scrollIntoView({ block: "nearest" });
|
|
6163
6242
|
}, [selectedId, items.length]);
|
|
6164
6243
|
const familyOf2 = (key) => definitions.find((d) => d.key === key)?.family ?? "generic";
|
|
@@ -6221,8 +6300,8 @@ function ListRow({ item, family, port, on, onSelect, withOwner, ownContextMenu,
|
|
|
6221
6300
|
const confirmed = useConfirmed();
|
|
6222
6301
|
const copy = useCopy();
|
|
6223
6302
|
const notify = useNotify();
|
|
6224
|
-
const [busy, setBusy] =
|
|
6225
|
-
const [menuOpen, setMenuOpen] =
|
|
6303
|
+
const [busy, setBusy] = useState27(false);
|
|
6304
|
+
const [menuOpen, setMenuOpen] = useState27(false);
|
|
6226
6305
|
const canUse = item.capabilities.canUse;
|
|
6227
6306
|
const user = canUse ? item.fields.find((f) => USERNAME_KEYS.test(f.key) && f.handling !== "sealed" && f.active !== false) : void 0;
|
|
6228
6307
|
const secret = canUse && item.capabilities.canReveal ? item.fields.find((f) => f.key === "password" && f.handling === "revealable" && f.active !== false) : void 0;
|
|
@@ -6261,7 +6340,7 @@ function ListRow({ item, family, port, on, onSelect, withOwner, ownContextMenu,
|
|
|
6261
6340
|
...manageEntries(item, onAction),
|
|
6262
6341
|
...hostEntries.map((h) => ({ ...h, kind: h.kind ?? "host" }))
|
|
6263
6342
|
];
|
|
6264
|
-
const entriesRef =
|
|
6343
|
+
const entriesRef = useRef14(entries);
|
|
6265
6344
|
entriesRef.current = entries;
|
|
6266
6345
|
const glyphOf = (e) => e.id === "copy:username" ? /* @__PURE__ */ jsx25(UserGlyph, { className: "size-4" }) : e.id === "copy:password" ? /* @__PURE__ */ jsx25(KeyGlyph, { className: "size-4" }) : e.id === "copy:code" ? /* @__PURE__ */ jsx25(ClockGlyph, { className: "size-4" }) : e.kind === "favorite" ? /* @__PURE__ */ jsx25(StarGlyph, { className: cn11("size-4", favorite?.on && "fill-current text-warning") }) : e.kind === "open" ? /* @__PURE__ */ jsx25(ChevronRightGlyph, { className: "size-4" }) : e.kind === "host" || e.kind === "manage" ? null : /* @__PURE__ */ jsx25(CopyIcon7, { className: "size-4" });
|
|
6267
6346
|
const menuItem = (e) => /* @__PURE__ */ jsxs23(DropdownMenuItem4, { disabled: e.disabled ?? false, onSelect: e.onSelect, children: [
|
|
@@ -6298,10 +6377,11 @@ function ListRow({ item, family, port, on, onSelect, withOwner, ownContextMenu,
|
|
|
6298
6377
|
}
|
|
6299
6378
|
),
|
|
6300
6379
|
/* @__PURE__ */ jsxs23("div", { className: "absolute right-1.5 top-1/2 flex -translate-y-1/2 items-center gap-0.5", "data-surface": on ? "primary" : void 0, children: [
|
|
6301
|
-
user || secret || favorite ? /* @__PURE__ */ jsxs23("div", { className: cn11("hidden items-center gap-0.5 rounded-md pl-2 [@media(hover:hover)]:group-hover:flex [@media(hover:hover)]:group-focus-within:flex", on ? "bg-primary" : "bg-accent"), "data-row-quick": "", children: [
|
|
6380
|
+
user || secret || code || favorite ? /* @__PURE__ */ jsxs23("div", { className: cn11("hidden items-center gap-0.5 rounded-md pl-2 [@media(hover:hover)]:group-hover:flex [@media(hover:hover)]:group-focus-within:flex", on ? "bg-primary" : "bg-accent"), "data-row-quick": "", children: [
|
|
6302
6381
|
favorite ? /* @__PURE__ */ jsx25(Button22, { variant: "quiet", icon: /* @__PURE__ */ jsx25(StarGlyph, { className: favorite.on ? "fill-current text-warning" : "" }), "aria-label": favorite.on ? "Remove from favorites" : "Add to favorites", "aria-pressed": favorite.on, onClick: favorite.toggle }) : null,
|
|
6303
6382
|
user ? /* @__PURE__ */ jsx25(Button22, { variant: "quiet", icon: /* @__PURE__ */ jsx25(UserGlyph, {}), "aria-label": `Copy ${user.label}`, disabled: busy, onClick: copyUser }) : null,
|
|
6304
|
-
secret ? /* @__PURE__ */ jsx25(Button22, { variant: "quiet", icon: /* @__PURE__ */ jsx25(KeyGlyph, {}), "aria-label": "Copy password", disabled: busy, onClick: copyPassword }) : null
|
|
6383
|
+
secret ? /* @__PURE__ */ jsx25(Button22, { variant: "quiet", icon: /* @__PURE__ */ jsx25(KeyGlyph, {}), "aria-label": "Copy password", disabled: busy, onClick: copyPassword }) : null,
|
|
6384
|
+
code ? /* @__PURE__ */ jsx25(Button22, { variant: "quiet", icon: /* @__PURE__ */ jsx25(ClockGlyph, {}), "aria-label": "Copy one-time code", disabled: busy, onClick: copyCode }) : null
|
|
6305
6385
|
] }) : null,
|
|
6306
6386
|
/* @__PURE__ */ jsxs23(DropdownMenu4, { open: menuOpen, onOpenChange: setMenuOpen, children: [
|
|
6307
6387
|
/* @__PURE__ */ jsx25(DropdownMenuTrigger4, { asChild: true, children: /* @__PURE__ */ jsx25(
|
|
@@ -6342,7 +6422,7 @@ function manageEntries(item, onAction) {
|
|
|
6342
6422
|
}
|
|
6343
6423
|
|
|
6344
6424
|
// src/lists/TrashView.tsx
|
|
6345
|
-
import { useState as
|
|
6425
|
+
import { useState as useState29 } from "react";
|
|
6346
6426
|
import { Button as Button24 } from "@ai-matrx/design-system/controls";
|
|
6347
6427
|
import { formatAbsoluteDate as formatAbsoluteDate4 } from "@ai-matrx/kit/format";
|
|
6348
6428
|
|
|
@@ -6416,7 +6496,7 @@ function refusalText(reason) {
|
|
|
6416
6496
|
}
|
|
6417
6497
|
|
|
6418
6498
|
// src/lists/RestorePanel.tsx
|
|
6419
|
-
import { useEffect as
|
|
6499
|
+
import { useEffect as useEffect17, useState as useState28 } from "react";
|
|
6420
6500
|
import { Button as Button23 } from "@ai-matrx/design-system/controls";
|
|
6421
6501
|
import { Fragment as Fragment18, jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
6422
6502
|
var count = (n, one) => `${n} ${one}${n === 1 ? "" : "s"}`;
|
|
@@ -6427,13 +6507,13 @@ function RestorePanel({
|
|
|
6427
6507
|
turnOn,
|
|
6428
6508
|
onClose
|
|
6429
6509
|
}) {
|
|
6430
|
-
const [preview, setPreview] =
|
|
6431
|
-
const [restored, setRestored] =
|
|
6432
|
-
const [turnedOn, setTurnedOn] =
|
|
6433
|
-
const [error, setError] =
|
|
6434
|
-
const [busy, setBusy] =
|
|
6435
|
-
const [loading, setLoading] =
|
|
6436
|
-
|
|
6510
|
+
const [preview, setPreview] = useState28(null);
|
|
6511
|
+
const [restored, setRestored] = useState28(null);
|
|
6512
|
+
const [turnedOn, setTurnedOn] = useState28(null);
|
|
6513
|
+
const [error, setError] = useState28(null);
|
|
6514
|
+
const [busy, setBusy] = useState28(false);
|
|
6515
|
+
const [loading, setLoading] = useState28(Boolean(lists.preview));
|
|
6516
|
+
useEffect17(() => {
|
|
6437
6517
|
if (!lists.preview) return;
|
|
6438
6518
|
let live = true;
|
|
6439
6519
|
lists.preview(item).then(
|
|
@@ -6537,10 +6617,10 @@ function trashLineOf(item) {
|
|
|
6537
6617
|
}
|
|
6538
6618
|
function TrashView({ port, deleted, query, header, onChanged }) {
|
|
6539
6619
|
const confirmed = useConfirmed();
|
|
6540
|
-
const [busyId, setBusyId] =
|
|
6541
|
-
const [message2, setMessage] =
|
|
6620
|
+
const [busyId, setBusyId] = useState29(null);
|
|
6621
|
+
const [message2, setMessage] = useState29(null);
|
|
6542
6622
|
const shown = deleted.filter((i) => trashItemMatchesQuery(i, query));
|
|
6543
|
-
const [restoring, setRestoring] =
|
|
6623
|
+
const [restoring, setRestoring] = useState29(null);
|
|
6544
6624
|
const restore = async (item, deletionId) => {
|
|
6545
6625
|
setBusyId(item.id);
|
|
6546
6626
|
setMessage(null);
|
|
@@ -6588,12 +6668,12 @@ function TrashView({ port, deleted, query, header, onChanged }) {
|
|
|
6588
6668
|
}
|
|
6589
6669
|
|
|
6590
6670
|
// src/NewItemFlow.tsx
|
|
6591
|
-
import { useMemo as useMemo4, useState as
|
|
6671
|
+
import { useMemo as useMemo4, useState as useState30 } from "react";
|
|
6592
6672
|
import { Button as Button25, Field as Field10, SearchField as SearchField2, Tile as Tile4 } from "@ai-matrx/design-system/controls";
|
|
6593
6673
|
import { GlobeIcon as GlobeIcon2 } from "@ai-matrx/design-system/icons";
|
|
6594
6674
|
import { jsx as jsx28, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
6595
6675
|
function NewItemFlow({ definitions, url, onUrl, onChoose, onCancel }) {
|
|
6596
|
-
const [search, setSearch] =
|
|
6676
|
+
const [search, setSearch] = useState30("");
|
|
6597
6677
|
const guess = useMemo4(() => inferFromUrl(url, definitions), [url, definitions]);
|
|
6598
6678
|
const common = COMMON_DEFINITION_KEYS.map((k) => definitions.find((d) => d.key === k)).filter((d) => d !== void 0);
|
|
6599
6679
|
const matches = useMemo4(() => {
|
|
@@ -6667,7 +6747,7 @@ function NewItemFlow({ definitions, url, onUrl, onChoose, onCancel }) {
|
|
|
6667
6747
|
}
|
|
6668
6748
|
|
|
6669
6749
|
// src/sharing/SecureLinkPanel.tsx
|
|
6670
|
-
import { useEffect as
|
|
6750
|
+
import { useEffect as useEffect18, useRef as useRef15, useState as useState31 } from "react";
|
|
6671
6751
|
import { confirm as confirm11 } from "@ai-matrx/kit/confirm-opener";
|
|
6672
6752
|
import { Checkbox as Checkbox2 } from "@ai-matrx/design-system";
|
|
6673
6753
|
import { Badge as Badge8, Button as Button26, Field as Field11, RegionSkeleton as RegionSkeleton2, SegmentedControl as SegmentedControl6, Textarea as Textarea4 } from "@ai-matrx/design-system/controls";
|
|
@@ -6750,20 +6830,20 @@ import { jsx as jsx29, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
|
6750
6830
|
function SecureLinkPanel({ item, port, onClose }) {
|
|
6751
6831
|
const sharing = port.sharing;
|
|
6752
6832
|
const { busy, error, notice, run, setNotice } = useConfirmedChange();
|
|
6753
|
-
const [remedy, setRemedy] =
|
|
6754
|
-
const [options, setOptions] =
|
|
6755
|
-
const [optionsError, setOptionsError] =
|
|
6756
|
-
const [sent, setSent] =
|
|
6757
|
-
const [sentError, setSentError] =
|
|
6758
|
-
const [nonce, setNonce] =
|
|
6759
|
-
const [email, setEmail] =
|
|
6760
|
-
const [phone, setPhone] =
|
|
6761
|
-
const [name, setName] =
|
|
6762
|
-
const [linkBy, setLinkBy] =
|
|
6763
|
-
const [fields, setFields] =
|
|
6764
|
-
const [note, setNote] =
|
|
6765
|
-
const [sameChannelSent, setSameChannelSent] =
|
|
6766
|
-
|
|
6833
|
+
const [remedy, setRemedy] = useState31(null);
|
|
6834
|
+
const [options, setOptions] = useState31(null);
|
|
6835
|
+
const [optionsError, setOptionsError] = useState31(null);
|
|
6836
|
+
const [sent, setSent] = useState31(null);
|
|
6837
|
+
const [sentError, setSentError] = useState31(null);
|
|
6838
|
+
const [nonce, setNonce] = useState31(0);
|
|
6839
|
+
const [email, setEmail] = useState31("");
|
|
6840
|
+
const [phone, setPhone] = useState31("");
|
|
6841
|
+
const [name, setName] = useState31("");
|
|
6842
|
+
const [linkBy, setLinkBy] = useState31("email");
|
|
6843
|
+
const [fields, setFields] = useState31([]);
|
|
6844
|
+
const [note, setNote] = useState31("");
|
|
6845
|
+
const [sameChannelSent, setSameChannelSent] = useState31(false);
|
|
6846
|
+
useEffect18(() => {
|
|
6767
6847
|
let live = true;
|
|
6768
6848
|
setOptionsError(null);
|
|
6769
6849
|
sharing.secureLinkOptions(item).then(
|
|
@@ -6778,7 +6858,7 @@ function SecureLinkPanel({ item, port, onClose }) {
|
|
|
6778
6858
|
live = false;
|
|
6779
6859
|
};
|
|
6780
6860
|
}, [sharing, item]);
|
|
6781
|
-
|
|
6861
|
+
useEffect18(() => {
|
|
6782
6862
|
const list = sharing.sentSecureLinks;
|
|
6783
6863
|
if (!list) return;
|
|
6784
6864
|
let live = true;
|
|
@@ -6791,9 +6871,9 @@ function SecureLinkPanel({ item, port, onClose }) {
|
|
|
6791
6871
|
live = false;
|
|
6792
6872
|
};
|
|
6793
6873
|
}, [sharing, item, nonce]);
|
|
6794
|
-
const [phoneTyped, setPhoneTyped] =
|
|
6795
|
-
const prefilled =
|
|
6796
|
-
|
|
6874
|
+
const [phoneTyped, setPhoneTyped] = useState31(false);
|
|
6875
|
+
const prefilled = useRef15(false);
|
|
6876
|
+
useEffect18(() => {
|
|
6797
6877
|
const lookup = sharing.phoneOnFile;
|
|
6798
6878
|
if (!lookup || phoneTyped) return;
|
|
6799
6879
|
const clear = () => {
|
|
@@ -6946,7 +7026,7 @@ function sentMeta(row, options) {
|
|
|
6946
7026
|
}
|
|
6947
7027
|
|
|
6948
7028
|
// src/devices/DevicesPanel.tsx
|
|
6949
|
-
import { useCallback as useCallback3, useEffect as
|
|
7029
|
+
import { useCallback as useCallback3, useEffect as useEffect19, useState as useState32 } from "react";
|
|
6950
7030
|
import { confirm as confirm12 } from "@ai-matrx/kit/confirm-opener";
|
|
6951
7031
|
import { Button as Button27, RegionSkeleton as RegionSkeleton3 } from "@ai-matrx/design-system/controls";
|
|
6952
7032
|
import { formatAbsoluteDate as formatAbsoluteDate6 } from "@ai-matrx/kit/format";
|
|
@@ -7037,9 +7117,9 @@ function ErrorLine2({ text }) {
|
|
|
7037
7117
|
function DevicesPanel({ port, onClose }) {
|
|
7038
7118
|
const confirmed = useConfirmed();
|
|
7039
7119
|
const notify = useNotify();
|
|
7040
|
-
const [devices, setDevices] =
|
|
7041
|
-
const [error, setError] =
|
|
7042
|
-
const [busyId, setBusyId] =
|
|
7120
|
+
const [devices, setDevices] = useState32(null);
|
|
7121
|
+
const [error, setError] = useState32(null);
|
|
7122
|
+
const [busyId, setBusyId] = useState32(null);
|
|
7043
7123
|
const load = useCallback3(async () => {
|
|
7044
7124
|
setError(null);
|
|
7045
7125
|
try {
|
|
@@ -7048,7 +7128,7 @@ function DevicesPanel({ port, onClose }) {
|
|
|
7048
7128
|
setError(messageOf3(e, "Your browsers could not be read."));
|
|
7049
7129
|
}
|
|
7050
7130
|
}, [port]);
|
|
7051
|
-
|
|
7131
|
+
useEffect19(() => {
|
|
7052
7132
|
void load();
|
|
7053
7133
|
}, [load]);
|
|
7054
7134
|
const revoke = async (device) => {
|
|
@@ -7106,10 +7186,10 @@ function ApprovePanel({ port, host, onClose, approvalKey, label, kind = "browser
|
|
|
7106
7186
|
const where = isMac ? "the Mac app" : "the extension";
|
|
7107
7187
|
const passkeys = port.devices.passkeys;
|
|
7108
7188
|
const here = passkeys?.available() ?? false;
|
|
7109
|
-
const [methods, setMethods] =
|
|
7110
|
-
const [busy, setBusy] =
|
|
7111
|
-
const [error, setError] =
|
|
7112
|
-
const [approvedUntil, setApprovedUntil] =
|
|
7189
|
+
const [methods, setMethods] = useState32(null);
|
|
7190
|
+
const [busy, setBusy] = useState32(null);
|
|
7191
|
+
const [error, setError] = useState32(null);
|
|
7192
|
+
const [approvedUntil, setApprovedUntil] = useState32(null);
|
|
7113
7193
|
const load = useCallback3(async () => {
|
|
7114
7194
|
setError(null);
|
|
7115
7195
|
try {
|
|
@@ -7118,7 +7198,7 @@ function ApprovePanel({ port, host, onClose, approvalKey, label, kind = "browser
|
|
|
7118
7198
|
setError(messageOf3(e, "Your account could not be checked."));
|
|
7119
7199
|
}
|
|
7120
7200
|
}, [port]);
|
|
7121
|
-
|
|
7201
|
+
useEffect19(() => {
|
|
7122
7202
|
if (key && here) void load();
|
|
7123
7203
|
}, [key, here, load]);
|
|
7124
7204
|
const approve = async () => {
|
|
@@ -7206,7 +7286,7 @@ function ApprovePanel({ port, host, onClose, approvalKey, label, kind = "browser
|
|
|
7206
7286
|
}
|
|
7207
7287
|
|
|
7208
7288
|
// src/native/NativeImportPanel.tsx
|
|
7209
|
-
import { useEffect as
|
|
7289
|
+
import { useEffect as useEffect21, useMemo as useMemo5, useState as useState34 } from "react";
|
|
7210
7290
|
import { confirm as confirm13 } from "@ai-matrx/kit/confirm-opener";
|
|
7211
7291
|
import { Badge as Badge9, Button as Button28, Select as Select10 } from "@ai-matrx/design-system/controls";
|
|
7212
7292
|
|
|
@@ -7269,19 +7349,19 @@ async function loadFullPreview(bridge, operationId, current) {
|
|
|
7269
7349
|
}
|
|
7270
7350
|
|
|
7271
7351
|
// src/native/use-native-import.ts
|
|
7272
|
-
import { useEffect as
|
|
7352
|
+
import { useEffect as useEffect20, useRef as useRef16, useState as useState33 } from "react";
|
|
7273
7353
|
var fail = (e, fallback) => e instanceof Error && e.message ? e.message : fallback;
|
|
7274
7354
|
var RESTART = "Your account changed. The import was stopped; start it again.";
|
|
7275
7355
|
function useNativeImport(bridge, stillAllowed, onImported) {
|
|
7276
|
-
const [screen, setScreen] =
|
|
7277
|
-
const [busy, setBusy] =
|
|
7278
|
-
const generation =
|
|
7279
|
-
const mounted =
|
|
7280
|
-
const op =
|
|
7281
|
-
const last =
|
|
7282
|
-
const timer2 =
|
|
7283
|
-
const polls =
|
|
7284
|
-
const refreshRef =
|
|
7356
|
+
const [screen, setScreen] = useState33({ kind: "idle", message: null });
|
|
7357
|
+
const [busy, setBusy] = useState33(false);
|
|
7358
|
+
const generation = useRef16(0);
|
|
7359
|
+
const mounted = useRef16(false);
|
|
7360
|
+
const op = useRef16(null);
|
|
7361
|
+
const last = useRef16(null);
|
|
7362
|
+
const timer2 = useRef16(null);
|
|
7363
|
+
const polls = useRef16(0);
|
|
7364
|
+
const refreshRef = useRef16(async () => void 0);
|
|
7285
7365
|
const current = (g) => mounted.current && g === generation.current;
|
|
7286
7366
|
const stopPolling = () => {
|
|
7287
7367
|
if (timer2.current !== null) clearTimeout(timer2.current);
|
|
@@ -7450,9 +7530,9 @@ function useNativeImport(bridge, stillAllowed, onImported) {
|
|
|
7450
7530
|
setBusy(false);
|
|
7451
7531
|
setScreen({ kind: "idle", message: null });
|
|
7452
7532
|
};
|
|
7453
|
-
const invalidateRef =
|
|
7533
|
+
const invalidateRef = useRef16(invalidate);
|
|
7454
7534
|
invalidateRef.current = invalidate;
|
|
7455
|
-
|
|
7535
|
+
useEffect20(() => {
|
|
7456
7536
|
mounted.current = true;
|
|
7457
7537
|
const off = bridge.subscribe?.(() => {
|
|
7458
7538
|
if (op.current) invalidateRef.current(RESTART);
|
|
@@ -7485,13 +7565,13 @@ function NativeImportPanel({ bridge, readLimits, activeOrganizationId, organizat
|
|
|
7485
7565
|
}
|
|
7486
7566
|
function Importer({ bridge, readLimits, activeOrganizationId, organizations, onClose, onChanged }) {
|
|
7487
7567
|
const options = useMemo5(() => organizations.map((o) => ({ value: o.id, label: o.name })), [organizations]);
|
|
7488
|
-
const [organizationId, setOrganizationId] =
|
|
7489
|
-
const [limits, setLimits] =
|
|
7490
|
-
const [limitError, setLimitError] =
|
|
7568
|
+
const [organizationId, setOrganizationId] = useState34(() => organizations.some((o) => o.id === activeOrganizationId) ? activeOrganizationId : organizations[0]?.id ?? "");
|
|
7569
|
+
const [limits, setLimits] = useState34(null);
|
|
7570
|
+
const [limitError, setLimitError] = useState34(null);
|
|
7491
7571
|
const flow = useNativeImport(bridge, (id) => organizations.some((o) => o.id === id), onChanged);
|
|
7492
7572
|
const { screen, busy } = flow;
|
|
7493
7573
|
const orgName = organizations.find((o) => o.id === organizationId)?.name ?? "this organization";
|
|
7494
|
-
|
|
7574
|
+
useEffect21(() => {
|
|
7495
7575
|
if (!readLimits || !organizationId) return;
|
|
7496
7576
|
let live = true;
|
|
7497
7577
|
setLimits(null);
|
|
@@ -7552,21 +7632,21 @@ function Importer({ bridge, readLimits, activeOrganizationId, organizations, onC
|
|
|
7552
7632
|
}
|
|
7553
7633
|
|
|
7554
7634
|
// src/extension/PageView.tsx
|
|
7555
|
-
import { useState as
|
|
7635
|
+
import { useState as useState38 } from "react";
|
|
7556
7636
|
import { SiteIcon } from "@ai-matrx/design-system";
|
|
7557
7637
|
import { Button as Button32, Tile as Tile5 } from "@ai-matrx/design-system/controls";
|
|
7558
7638
|
import { GlobeIcon as GlobeIcon3 } from "@ai-matrx/design-system/icons";
|
|
7559
7639
|
|
|
7560
7640
|
// src/extension/CaptureCard.tsx
|
|
7561
|
-
import { useState as
|
|
7641
|
+
import { useState as useState35, useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
7562
7642
|
import { Button as Button29, SearchField as SearchField3 } from "@ai-matrx/design-system/controls";
|
|
7563
7643
|
import { Fragment as Fragment21, jsx as jsx32, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
7564
7644
|
var SEARCH_FROM = 4;
|
|
7565
7645
|
function CaptureCard({ capture, onChanged }) {
|
|
7566
7646
|
const prompt = useSyncExternalStore3(capture.subscribe, capture.get, capture.get);
|
|
7567
7647
|
const notify = useNotify();
|
|
7568
|
-
const [busy, setBusy] =
|
|
7569
|
-
const [q, setQ] =
|
|
7648
|
+
const [busy, setBusy] = useState35(false);
|
|
7649
|
+
const [q, setQ] = useState35("");
|
|
7570
7650
|
if (!prompt) return null;
|
|
7571
7651
|
const decide = async (d) => {
|
|
7572
7652
|
setBusy(true);
|
|
@@ -7622,15 +7702,15 @@ function CaptureCard({ capture, onChanged }) {
|
|
|
7622
7702
|
}
|
|
7623
7703
|
|
|
7624
7704
|
// src/extension/FillSetupCard.tsx
|
|
7625
|
-
import { useRef as
|
|
7705
|
+
import { useRef as useRef17, useState as useState36, useSyncExternalStore as useSyncExternalStore4 } from "react";
|
|
7626
7706
|
import { Button as Button30, Field as Field12 } from "@ai-matrx/design-system/controls";
|
|
7627
7707
|
import { jsx as jsx33, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
7628
7708
|
function FillSetupCard({ fillSetup }) {
|
|
7629
7709
|
const notify = useNotify();
|
|
7630
7710
|
const state = useSyncExternalStore4(fillSetup.subscribe, fillSetup.get, fillSetup.get);
|
|
7631
|
-
const box =
|
|
7632
|
-
const [busy, setBusy] =
|
|
7633
|
-
const [error, setError] =
|
|
7711
|
+
const box = useRef17(null);
|
|
7712
|
+
const [busy, setBusy] = useState36(false);
|
|
7713
|
+
const [error, setError] = useState36(null);
|
|
7634
7714
|
if (state.status !== "off") return null;
|
|
7635
7715
|
const finish = async (run) => {
|
|
7636
7716
|
setBusy(true);
|
|
@@ -7695,7 +7775,7 @@ function FillSetupCard({ fillSetup }) {
|
|
|
7695
7775
|
}
|
|
7696
7776
|
|
|
7697
7777
|
// src/extension/PageGenerator.tsx
|
|
7698
|
-
import { useState as
|
|
7778
|
+
import { useState as useState37 } from "react";
|
|
7699
7779
|
import { Popover as Popover2, PopoverContent as PopoverContent2, PopoverTrigger as PopoverTrigger2 } from "@ai-matrx/design-system";
|
|
7700
7780
|
import { Button as Button31 } from "@ai-matrx/design-system/controls";
|
|
7701
7781
|
import { CopyIcon as CopyIcon8 } from "@ai-matrx/design-system/icons";
|
|
@@ -7705,10 +7785,10 @@ function PageGenerator({ fields }) {
|
|
|
7705
7785
|
const limits = useGeneratorLimitsSource();
|
|
7706
7786
|
const copy = useCopy();
|
|
7707
7787
|
const held = useTransientSecret(HOLD_MS);
|
|
7708
|
-
const [open, setOpen] =
|
|
7709
|
-
const [busy, setBusy] =
|
|
7710
|
-
const [targets, setTargets] =
|
|
7711
|
-
const [said, setSaid] =
|
|
7788
|
+
const [open, setOpen] = useState37(false);
|
|
7789
|
+
const [busy, setBusy] = useState37(false);
|
|
7790
|
+
const [targets, setTargets] = useState37([]);
|
|
7791
|
+
const [said, setSaid] = useState37(null);
|
|
7712
7792
|
if (!limits) return null;
|
|
7713
7793
|
const say3 = setSaid;
|
|
7714
7794
|
const put = async (targetId, value2) => {
|
|
@@ -7772,8 +7852,8 @@ function PageGenerator({ fields }) {
|
|
|
7772
7852
|
// src/extension/PageView.tsx
|
|
7773
7853
|
import { jsx as jsx35, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
7774
7854
|
function PageView({ port, page, fill, capture, fillSetup, newPasswordFields, items, definitions, onOpen, onNewForPage, onBrowse, onChanged, header }) {
|
|
7775
|
-
const [running, setRunning] =
|
|
7776
|
-
const [said, setSaid] =
|
|
7855
|
+
const [running, setRunning] = useState38(null);
|
|
7856
|
+
const [said, setSaid] = useState38(null);
|
|
7777
7857
|
const site = pageSite(page.url);
|
|
7778
7858
|
const state = page.matchState ?? { status: "ready" };
|
|
7779
7859
|
const fillable = new Set(page.fillableItemIds ?? page.matchingItemIds);
|
|
@@ -7857,7 +7937,7 @@ function MatchRow({ itemId, item, tag, family, port, busy, running, onOpen, onFi
|
|
|
7857
7937
|
const confirmed = useConfirmed();
|
|
7858
7938
|
const copy = useCopy();
|
|
7859
7939
|
const notify = useNotify();
|
|
7860
|
-
const [reading, setReading] =
|
|
7940
|
+
const [reading, setReading] = useState38(false);
|
|
7861
7941
|
const usable = item?.capabilities.canUse ?? false;
|
|
7862
7942
|
const user = usable ? item?.fields.find((f) => USERNAME_KEYS.test(f.key) && f.handling !== "sealed" && f.active) : void 0;
|
|
7863
7943
|
const secret = usable && item?.capabilities.canReveal ? item?.fields.find((f) => f.key === "password" && f.handling === "revealable" && f.active) : void 0;
|
|
@@ -7895,7 +7975,7 @@ function MatchRow({ itemId, item, tag, family, port, busy, running, onOpen, onFi
|
|
|
7895
7975
|
}
|
|
7896
7976
|
|
|
7897
7977
|
// src/Sidebar.tsx
|
|
7898
|
-
import { useState as
|
|
7978
|
+
import { useState as useState39 } from "react";
|
|
7899
7979
|
import { cn as cn12, useLook as useLook2 } from "@ai-matrx/design-system";
|
|
7900
7980
|
import { DisclosureHeader as DisclosureHeader4, Select as Select11, Tile as Tile6 } from "@ai-matrx/design-system/controls";
|
|
7901
7981
|
import { GlobeIcon as GlobeIcon4 } from "@ai-matrx/design-system/icons";
|
|
@@ -7904,6 +7984,7 @@ var AUTHENTICATOR_LABEL = "Authenticator";
|
|
|
7904
7984
|
function vaultChoices(items, organizations, _current) {
|
|
7905
7985
|
const n = (f) => items.filter(f).length;
|
|
7906
7986
|
const shared = n((i) => i.owner.kind === "shared");
|
|
7987
|
+
const hints = organizationHints(organizations);
|
|
7907
7988
|
return [
|
|
7908
7989
|
{ value: "all", label: "All items", count: items.length },
|
|
7909
7990
|
{ value: "mine", label: "Personal", count: n((i) => i.owner.kind === "me") },
|
|
@@ -7911,11 +7992,11 @@ function vaultChoices(items, organizations, _current) {
|
|
|
7911
7992
|
// Every organization the person belongs to, empty ones too: an empty vault opens on its own
|
|
7912
7993
|
// "Nothing here yet" with New item, so the first credential can go there. (The organization
|
|
7913
7994
|
// list carries no role, so who may add is the server's answer to the save, said in place.)
|
|
7914
|
-
...organizations.map((o) => ({ value: o.id, label: o.name, count: n((i) => i.owner.organizationId === o.id) }))
|
|
7995
|
+
...organizations.map((o) => ({ value: o.id, label: o.name, count: n((i) => i.owner.organizationId === o.id), ...hints.has(o.id) ? { hint: hints.get(o.id) } : {} }))
|
|
7915
7996
|
];
|
|
7916
7997
|
}
|
|
7917
|
-
function VaultSelect({ value, choices, onChange }) {
|
|
7918
|
-
return /* @__PURE__ */ jsx36(Select11, { value, onValueChange: onChange, "aria-label": "Vault", options: choices.map((c) => ({ value: c.value, label: c.label, meta: String(c.count) })) });
|
|
7998
|
+
function VaultSelect({ value, choices, onChange, searchAt = ORGANIZATION_SEARCH_AT_UNREAD }) {
|
|
7999
|
+
return /* @__PURE__ */ jsx36(Select11, { value, onValueChange: onChange, "aria-label": "Vault", searchAt, options: choices.map((c) => ({ value: c.value, label: c.label, meta: String(c.count), ...c.hint ? { hint: c.hint } : {} })) });
|
|
7919
8000
|
}
|
|
7920
8001
|
var CATEGORY_GLYPHS = { logins: GlobeIcon4, passkeys: ShieldGlyph, api: KeyGlyph, oauth: PlugGlyph, infra: DatabaseGlyph, env: TerminalGlyph, files: FileGlyph, other: NoteGlyph };
|
|
7921
8002
|
var familyOf = (key, definitions) => definitions.find((d) => d.key === key)?.family ?? "generic";
|
|
@@ -8006,12 +8087,12 @@ function Group({ title, children }) {
|
|
|
8006
8087
|
children
|
|
8007
8088
|
] });
|
|
8008
8089
|
}
|
|
8009
|
-
function VaultSidebar({ vault, choices, onVault, view, allCount, deletedCount, views, hasFavorites, hasRecents, onView, onPanel, nativeProvider, hasNativeImport = false, hasPage = false, onLock, onOpenWeb }) {
|
|
8010
|
-
const [tagsOpen, setTagsOpen] =
|
|
8090
|
+
function VaultSidebar({ vault, choices, onVault, organizationSearchAt, view, allCount, deletedCount, views, hasFavorites, hasRecents, onView, onPanel, nativeProvider, hasNativeImport = false, hasPage = false, onLock, onOpenWeb }) {
|
|
8091
|
+
const [tagsOpen, setTagsOpen] = useState39(view.startsWith("tag:"));
|
|
8011
8092
|
return /* @__PURE__ */ jsxs34("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: [
|
|
8012
8093
|
/* @__PURE__ */ jsxs34("div", { className: "flex items-center gap-2 px-3 pb-2 pt-3", children: [
|
|
8013
8094
|
/* @__PURE__ */ jsx36(SafeGlyph, { className: "size-5 shrink-0 text-primary" }),
|
|
8014
|
-
/* @__PURE__ */ jsx36("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx36(VaultSelect, { value: vault, choices, onChange: onVault }) })
|
|
8095
|
+
/* @__PURE__ */ jsx36("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx36(VaultSelect, { value: vault, choices, onChange: onVault, searchAt: organizationSearchAt }) })
|
|
8015
8096
|
] }),
|
|
8016
8097
|
/* @__PURE__ */ jsxs34("div", { className: "flex min-h-0 flex-1 flex-col gap-5 overflow-y-auto px-2 pb-3 pt-1", children: [
|
|
8017
8098
|
/* @__PURE__ */ jsxs34("div", { className: "flex flex-col gap-0.5", children: [
|
|
@@ -8088,8 +8169,8 @@ var generatorLimitsFrom = (knobs) => knobs ? async () => {
|
|
|
8088
8169
|
} : void 0;
|
|
8089
8170
|
function ImportWithLimits(props) {
|
|
8090
8171
|
const { knobs, ...rest } = props;
|
|
8091
|
-
const [state, setState] =
|
|
8092
|
-
|
|
8172
|
+
const [state, setState] = useState40(null);
|
|
8173
|
+
useEffect22(() => {
|
|
8093
8174
|
if (!knobs) return setState({ error: "Import is not set up for this organization yet." });
|
|
8094
8175
|
knobs().then(
|
|
8095
8176
|
(r) => {
|
|
@@ -8114,13 +8195,13 @@ function VaultApp(given) {
|
|
|
8114
8195
|
}
|
|
8115
8196
|
function useOrganizationSettings(host) {
|
|
8116
8197
|
const knobs = host.knobs;
|
|
8117
|
-
const needs = knobs !== void 0 && (host.revealSeconds === void 0 || host.backupPassphraseMinLength === void 0);
|
|
8118
|
-
const [read, setRead] =
|
|
8119
|
-
|
|
8198
|
+
const needs = knobs !== void 0 && (host.revealSeconds === void 0 || host.backupPassphraseMinLength === void 0 || host.organizationSearchAt === void 0);
|
|
8199
|
+
const [read, setRead] = useState40(null);
|
|
8200
|
+
useEffect22(() => {
|
|
8120
8201
|
if (!needs || !knobs) return;
|
|
8121
8202
|
let live = true;
|
|
8122
8203
|
knobs().then(
|
|
8123
|
-
(r) => live && setRead({ reveal: positiveKnob(r, REVEAL_SECONDS_KNOB), backupMin: positiveKnob(r, BACKUP_PASSPHRASE_MIN_KNOB) }),
|
|
8204
|
+
(r) => live && setRead({ reveal: positiveKnob(r, REVEAL_SECONDS_KNOB), backupMin: positiveKnob(r, BACKUP_PASSPHRASE_MIN_KNOB), searchAt: positiveKnob(r, ORGANIZATION_SEARCH_AT_KNOB) }),
|
|
8124
8205
|
() => void 0
|
|
8125
8206
|
);
|
|
8126
8207
|
return () => {
|
|
@@ -8131,7 +8212,8 @@ function useOrganizationSettings(host) {
|
|
|
8131
8212
|
return {
|
|
8132
8213
|
...host,
|
|
8133
8214
|
...host.revealSeconds === void 0 && read.reveal !== null ? { revealSeconds: read.reveal } : {},
|
|
8134
|
-
...host.backupPassphraseMinLength === void 0 && read.backupMin !== null ? { backupPassphraseMinLength: read.backupMin } : {}
|
|
8215
|
+
...host.backupPassphraseMinLength === void 0 && read.backupMin !== null ? { backupPassphraseMinLength: read.backupMin } : {},
|
|
8216
|
+
...host.organizationSearchAt === void 0 && read.searchAt !== null ? { organizationSearchAt: read.searchAt } : {}
|
|
8135
8217
|
};
|
|
8136
8218
|
}
|
|
8137
8219
|
var NO_STORE = () => () => void 0;
|
|
@@ -8142,8 +8224,8 @@ function useHostPrompts(capture, fillSetup) {
|
|
|
8142
8224
|
return prompt !== null || setup?.status === "off";
|
|
8143
8225
|
}
|
|
8144
8226
|
function LockedScreen({ lock }) {
|
|
8145
|
-
const [busy, setBusy] =
|
|
8146
|
-
const [error, setError] =
|
|
8227
|
+
const [busy, setBusy] = useState40(false);
|
|
8228
|
+
const [error, setError] = useState40(null);
|
|
8147
8229
|
const unlock = async () => {
|
|
8148
8230
|
setBusy(true);
|
|
8149
8231
|
setError(null);
|
|
@@ -8163,21 +8245,21 @@ function LockedScreen({ lock }) {
|
|
|
8163
8245
|
] });
|
|
8164
8246
|
}
|
|
8165
8247
|
function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocationChange, onInventory }) {
|
|
8166
|
-
const rootRef =
|
|
8248
|
+
const rootRef = useRef18(null);
|
|
8167
8249
|
const width = useElementWidth(rootRef);
|
|
8168
8250
|
const mode = layout !== "auto" ? layout : width >= FULL_AT ? "full" : width >= SPLIT_AT ? "split" : "stack";
|
|
8169
8251
|
const notify = useNotify();
|
|
8170
|
-
const [snap, setSnap] =
|
|
8171
|
-
const [items, setItems] =
|
|
8172
|
-
const [deleted, setDeleted] =
|
|
8173
|
-
const [favorites, setFavorites] =
|
|
8174
|
-
const [recents, setRecents] =
|
|
8175
|
-
const [error, setError] =
|
|
8176
|
-
const [inner, setInner] =
|
|
8252
|
+
const [snap, setSnap] = useState40(null);
|
|
8253
|
+
const [items, setItems] = useState40([]);
|
|
8254
|
+
const [deleted, setDeleted] = useState40([]);
|
|
8255
|
+
const [favorites, setFavorites] = useState40(null);
|
|
8256
|
+
const [recents, setRecents] = useState40(null);
|
|
8257
|
+
const [error, setError] = useState40(null);
|
|
8258
|
+
const [inner, setInner] = useState40(DEFAULT_LOCATION);
|
|
8177
8259
|
const loc = location ?? inner;
|
|
8178
|
-
const dirty =
|
|
8179
|
-
const [notice, setNotice] =
|
|
8180
|
-
const [firstCode, setFirstCode] =
|
|
8260
|
+
const dirty = useRef18(false);
|
|
8261
|
+
const [notice, setNotice] = useState40(null);
|
|
8262
|
+
const [firstCode, setFirstCode] = useShownUntilMove(loc);
|
|
8181
8263
|
const move = useCallback4(
|
|
8182
8264
|
(next, how) => {
|
|
8183
8265
|
if (!location) setInner(next);
|
|
@@ -8204,9 +8286,9 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8204
8286
|
},
|
|
8205
8287
|
[loc, move]
|
|
8206
8288
|
);
|
|
8207
|
-
const keyState =
|
|
8289
|
+
const keyState = useRef18({ loc, go });
|
|
8208
8290
|
keyState.current = { loc, go };
|
|
8209
|
-
|
|
8291
|
+
useEffect22(() => {
|
|
8210
8292
|
const onKey = (e) => {
|
|
8211
8293
|
if (e.defaultPrevented || e.metaKey || e.ctrlKey || e.altKey) return;
|
|
8212
8294
|
const root = rootRef.current;
|
|
@@ -8228,8 +8310,8 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8228
8310
|
document.addEventListener("keydown", onKey);
|
|
8229
8311
|
return () => document.removeEventListener("keydown", onKey);
|
|
8230
8312
|
}, []);
|
|
8231
|
-
const keepSearchFocus =
|
|
8232
|
-
|
|
8313
|
+
const keepSearchFocus = useRef18(false);
|
|
8314
|
+
useEffect22(() => {
|
|
8233
8315
|
if (!keepSearchFocus.current) return;
|
|
8234
8316
|
keepSearchFocus.current = false;
|
|
8235
8317
|
const search = rootRef.current?.querySelector('input[aria-label^="Search"]');
|
|
@@ -8238,13 +8320,13 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8238
8320
|
search.setSelectionRange(search.value.length, search.value.length);
|
|
8239
8321
|
}, [loc.q]);
|
|
8240
8322
|
const hasPrompts = useHostPrompts(host.capture, host.fillSetup);
|
|
8241
|
-
const knobsRef =
|
|
8323
|
+
const knobsRef = useRef18(host.knobs);
|
|
8242
8324
|
knobsRef.current = host.knobs;
|
|
8243
|
-
const [signedOut, setSignedOut] =
|
|
8244
|
-
const [refreshError, setRefreshError] =
|
|
8245
|
-
const [refreshing, setRefreshing] =
|
|
8246
|
-
const loadedAt =
|
|
8247
|
-
const inFlight =
|
|
8325
|
+
const [signedOut, setSignedOut] = useState40(false);
|
|
8326
|
+
const [refreshError, setRefreshError] = useState40(null);
|
|
8327
|
+
const [refreshing, setRefreshing] = useState40(false);
|
|
8328
|
+
const loadedAt = useRef18(0);
|
|
8329
|
+
const inFlight = useRef18(false);
|
|
8248
8330
|
const apply = useCallback4(
|
|
8249
8331
|
(s) => {
|
|
8250
8332
|
loadedAt.current = Date.now();
|
|
@@ -8292,11 +8374,11 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8292
8374
|
knobsRef.current?.().catch(() => void 0);
|
|
8293
8375
|
port.lists.recents?.list().then(setRecents, () => void 0);
|
|
8294
8376
|
}, [port, apply]);
|
|
8295
|
-
|
|
8296
|
-
const quietRef =
|
|
8377
|
+
useEffect22(load, [load]);
|
|
8378
|
+
const quietRef = useRef18({ loc, ready: false });
|
|
8297
8379
|
quietRef.current = { loc, ready: snap !== null && !error };
|
|
8298
|
-
const [knobSeconds, setKnobSeconds] =
|
|
8299
|
-
|
|
8380
|
+
const [knobSeconds, setKnobSeconds] = useState40(null);
|
|
8381
|
+
useEffect22(() => {
|
|
8300
8382
|
if (host.refreshSeconds !== void 0 || !knobsRef.current) return;
|
|
8301
8383
|
let live = true;
|
|
8302
8384
|
knobsRef.current().then(
|
|
@@ -8311,7 +8393,7 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8311
8393
|
};
|
|
8312
8394
|
}, [host.refreshSeconds]);
|
|
8313
8395
|
const everySeconds = host.refreshSeconds ?? knobSeconds;
|
|
8314
|
-
|
|
8396
|
+
useEffect22(() => {
|
|
8315
8397
|
const quietly = (minGapMs) => {
|
|
8316
8398
|
const { loc: here, ready } = quietRef.current;
|
|
8317
8399
|
if (!ready || document.visibilityState === "hidden" || dirty.current || here.mode !== "view") return;
|
|
@@ -8329,17 +8411,17 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8329
8411
|
if (timer2) clearInterval(timer2);
|
|
8330
8412
|
};
|
|
8331
8413
|
}, [refresh, everySeconds]);
|
|
8332
|
-
const inventoryRef =
|
|
8414
|
+
const inventoryRef = useRef18(onInventory);
|
|
8333
8415
|
inventoryRef.current = onInventory;
|
|
8334
|
-
|
|
8416
|
+
useEffect22(() => {
|
|
8335
8417
|
if (snap) inventoryRef.current?.({ items, definitions: snap.definitions });
|
|
8336
8418
|
}, [snap, items]);
|
|
8337
|
-
|
|
8419
|
+
useEffect22(() => {
|
|
8338
8420
|
if (!loc.itemId || !port.lists.recents) return;
|
|
8339
8421
|
const id = loc.itemId;
|
|
8340
8422
|
port.lists.recents.record(id).then(() => setRecents((r) => [id, ...(r ?? []).filter((x) => x !== id)]), () => void 0);
|
|
8341
8423
|
}, [loc.itemId, port]);
|
|
8342
|
-
const orgs = snap?.organizations ?? [];
|
|
8424
|
+
const orgs = useMemo6(() => orderOrganizations(snap?.organizations ?? [], items, recents), [snap?.organizations, items, recents]);
|
|
8343
8425
|
const definitions = snap?.definitions ?? [];
|
|
8344
8426
|
const inThisVault = useMemo6(() => items.filter((i) => inVault(i, loc.vault)), [items, loc.vault]);
|
|
8345
8427
|
const vaultMixesOwners = new Set(inThisVault.map((i) => i.owner.organizationId ?? i.owner.kind)).size > 1;
|
|
@@ -8422,7 +8504,7 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8422
8504
|
const hasFavorites = port.lists.favorites !== void 0;
|
|
8423
8505
|
const title = loc.vault === "all" && loc.view === "all" ? "All items" : viewLabel(loc.view, views);
|
|
8424
8506
|
const compactHeader = mode === "full" ? void 0 : /* @__PURE__ */ jsxs35("div", { className: "grid grid-cols-[repeat(auto-fit,minmax(11rem,1fr))] gap-2", "data-vault-compact-header": "", children: [
|
|
8425
|
-
/* @__PURE__ */ jsx37(VaultSelect, { value: loc.vault, choices, onChange: (vault) => go({ vault, itemId: null, panel: null }) }),
|
|
8507
|
+
/* @__PURE__ */ jsx37(VaultSelect, { value: loc.vault, choices, searchAt: host.organizationSearchAt, onChange: (vault) => go({ vault, itemId: null, panel: null }) }),
|
|
8426
8508
|
/* @__PURE__ */ jsx37(Select12, { value: loc.view, onValueChange: (view) => go({ view, itemId: null, panel: null }), options: viewOptions(views, inThisVault.length, deleted.length, hasFavorites, port.lists.recents !== void 0, host.page !== void 0, loc.view), "aria-label": "Show" })
|
|
8427
8509
|
] });
|
|
8428
8510
|
const compactActions = mode === "full" ? void 0 : /* @__PURE__ */ jsxs35("div", { className: "flex shrink-0 items-center gap-2", "data-vault-compact-actions": "", children: [
|
|
@@ -8659,6 +8741,11 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8659
8741
|
arg: panelArg ?? null,
|
|
8660
8742
|
onClose: closePanel,
|
|
8661
8743
|
onPanel,
|
|
8744
|
+
onOpenItem: (next) => {
|
|
8745
|
+
replaceItem(next);
|
|
8746
|
+
const holds = loc.vault === "all" || loc.vault === "mine" && next.owner.kind === "me" || loc.vault === next.owner.organizationId;
|
|
8747
|
+
go({ ...holds ? {} : { vault: "all" }, itemId: next.id, mode: "view", panel: null });
|
|
8748
|
+
},
|
|
8662
8749
|
onChanged: (next) => {
|
|
8663
8750
|
if (next) replaceItem(next);
|
|
8664
8751
|
else if (next === null) {
|
|
@@ -8698,6 +8785,7 @@ function Workspace({ port, host = NO_HOST, layout = "auto", location, onLocation
|
|
|
8698
8785
|
vault: loc.vault,
|
|
8699
8786
|
choices,
|
|
8700
8787
|
onVault: (vault) => go({ vault, itemId: null, panel: null }),
|
|
8788
|
+
organizationSearchAt: host.organizationSearchAt,
|
|
8701
8789
|
view: loc.view,
|
|
8702
8790
|
allCount: inThisVault.length,
|
|
8703
8791
|
deletedCount: deleted.length,
|