@satanwagen/reviewkit 0.1.3 → 0.1.4
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 +54 -1
- package/README.md +41 -18
- package/dist/{chunk-NSXRFM75.js → chunk-5MAFDRUI.js} +746 -449
- package/dist/chunk-5MAFDRUI.js.map +1 -0
- package/dist/{chunk-Q7U43PXE.js → chunk-EOX3UJNP.js} +1 -1
- package/dist/client/index.cjs +794 -497
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.js +1 -1
- package/dist/{index-Dl2Fl0qr.d.cts → index-CWGkg1-E.d.cts} +17 -8
- package/dist/{index-BUSmAweg.d.ts → index-DPsjkvaY.d.ts} +17 -8
- package/dist/index.cjs +794 -497
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lazy.cjs +840 -520
- package/dist/lazy.cjs.map +1 -1
- package/dist/lazy.d.cts +1 -1
- package/dist/lazy.d.ts +1 -1
- package/dist/lazy.js +1 -1
- package/dist/next.cjs +840 -520
- package/dist/next.cjs.map +1 -1
- package/dist/next.d.cts +1 -1
- package/dist/next.d.ts +1 -1
- package/dist/next.js +1 -1
- package/package.json +4 -2
- package/dist/chunk-NSXRFM75.js.map +0 -1
- /package/dist/{chunk-Q7U43PXE.js.map → chunk-EOX3UJNP.js.map} +0 -0
|
@@ -340,7 +340,7 @@ function importSessionFile(file) {
|
|
|
340
340
|
}
|
|
341
341
|
|
|
342
342
|
// src/client/ReviewKit.tsx
|
|
343
|
-
import { useEffect as
|
|
343
|
+
import { useEffect as useEffect18, useState as useState14 } from "react";
|
|
344
344
|
import { createPortal } from "react-dom";
|
|
345
345
|
|
|
346
346
|
// src/client/env.ts
|
|
@@ -1234,6 +1234,8 @@ input, textarea, select {
|
|
|
1234
1234
|
.rk-sync-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--rk-fg-faint); }
|
|
1235
1235
|
.rk-sync-online .rk-sync-dot { background: var(--rk-success); }
|
|
1236
1236
|
.rk-sync-connecting .rk-sync-dot { background: var(--rk-warn); }
|
|
1237
|
+
.rk-sync-reason-token-short .rk-sync-dot, .rk-sync-reason-bad-token .rk-sync-dot { background: var(--rk-danger); }
|
|
1238
|
+
.rk-sync[title] { cursor: help; }
|
|
1237
1239
|
/* Automatic Emblema push hint (same quiet language) */
|
|
1238
1240
|
.rk-epush-ok .rk-sync-dot { background: var(--rk-success); }
|
|
1239
1241
|
.rk-epush-sending .rk-sync-dot { background: var(--rk-warn); }
|
|
@@ -2306,7 +2308,8 @@ function reducer(state, action) {
|
|
|
2306
2308
|
panelOpen: false,
|
|
2307
2309
|
confirm: null,
|
|
2308
2310
|
cheatsheetOpen: false,
|
|
2309
|
-
emblemaConnectOpen: false
|
|
2311
|
+
emblemaConnectOpen: false,
|
|
2312
|
+
terminalConnectOpen: false
|
|
2310
2313
|
} : { ...state, hidden: false };
|
|
2311
2314
|
case "SELECT":
|
|
2312
2315
|
return { ...state, selection: action.selection };
|
|
@@ -2416,12 +2419,16 @@ function reducer(state, action) {
|
|
|
2416
2419
|
return { ...state, cheatsheetOpen: action.open };
|
|
2417
2420
|
case "SET_EMBLEMA_CONNECT":
|
|
2418
2421
|
return { ...state, emblemaConnectOpen: action.open };
|
|
2422
|
+
case "SET_TERMINAL_CONNECT":
|
|
2423
|
+
return { ...state, terminalConnectOpen: action.open };
|
|
2419
2424
|
case "SET_COACH":
|
|
2420
2425
|
return { ...state, coachOpen: action.open };
|
|
2421
2426
|
case "SET_CORNER":
|
|
2422
2427
|
return { ...state, badgeCorner: action.corner };
|
|
2423
|
-
case "SYNC_STATUS":
|
|
2424
|
-
|
|
2428
|
+
case "SYNC_STATUS": {
|
|
2429
|
+
const reason = action.reason === void 0 ? action.status === "online" ? null : state.syncReason : action.reason;
|
|
2430
|
+
return state.syncStatus === action.status && state.syncReason === reason ? state : { ...state, syncStatus: action.status, syncReason: reason };
|
|
2431
|
+
}
|
|
2425
2432
|
case "EMBLEMA_PUSH_STATUS":
|
|
2426
2433
|
return state.emblemaPush === action.status ? state : { ...state, emblemaPush: action.status };
|
|
2427
2434
|
/*
|
|
@@ -2550,9 +2557,11 @@ function initialState() {
|
|
|
2550
2557
|
confirm: null,
|
|
2551
2558
|
cheatsheetOpen: false,
|
|
2552
2559
|
emblemaConnectOpen: false,
|
|
2560
|
+
terminalConnectOpen: false,
|
|
2553
2561
|
coachOpen: false,
|
|
2554
2562
|
undoStack: [],
|
|
2555
2563
|
syncStatus: "disabled",
|
|
2564
|
+
syncReason: null,
|
|
2556
2565
|
emblemaPush: "idle",
|
|
2557
2566
|
peers: [],
|
|
2558
2567
|
quick: null,
|
|
@@ -2567,7 +2576,7 @@ function StoreProvider({ config, children }) {
|
|
|
2567
2576
|
const configValue = useMemo(
|
|
2568
2577
|
() => config,
|
|
2569
2578
|
// eslint-disable-next-line react-hooks/exhaustive-deps -- config object identity is per-render; depend on its fields
|
|
2570
|
-
[config.enabled, config.token, config.devAutoOn, config.syncToken, config.syncUrl, config.defaultAuthor, config.fxAssetsUrl, config.position, config.storageKey, config.onSessionChange, config.emblema]
|
|
2579
|
+
[config.enabled, config.token, config.devAutoOn, config.sync, config.syncToken, config.syncUrl, config.defaultAuthor, config.fxAssetsUrl, config.position, config.storageKey, config.onSessionChange, config.emblema]
|
|
2571
2580
|
);
|
|
2572
2581
|
return /* @__PURE__ */ jsx(ConfigContext.Provider, { value: configValue, children: /* @__PURE__ */ jsx(StateContext.Provider, { value: state, children: /* @__PURE__ */ jsx(DispatchContext.Provider, { value: dispatch, children }) }) });
|
|
2573
2582
|
}
|
|
@@ -2596,7 +2605,7 @@ function toast(dispatch, message, tone = "info") {
|
|
|
2596
2605
|
}
|
|
2597
2606
|
|
|
2598
2607
|
// src/client/App.tsx
|
|
2599
|
-
import { useEffect as
|
|
2608
|
+
import { useEffect as useEffect17, useRef as useRef16 } from "react";
|
|
2600
2609
|
|
|
2601
2610
|
// src/client/persist.ts
|
|
2602
2611
|
var DB_NAME = "review-kit";
|
|
@@ -3532,9 +3541,13 @@ function createRkSync(options) {
|
|
|
3532
3541
|
pongTimer = null;
|
|
3533
3542
|
}
|
|
3534
3543
|
break;
|
|
3535
|
-
case "error":
|
|
3544
|
+
case "error": {
|
|
3536
3545
|
log("server error:", msg.code, msg.message);
|
|
3546
|
+
const code = typeof msg.code === "string" ? msg.code : "error";
|
|
3547
|
+
const message = typeof msg.message === "string" ? msg.message : "";
|
|
3548
|
+
safely(() => handlers.onError?.(code, message));
|
|
3537
3549
|
break;
|
|
3550
|
+
}
|
|
3538
3551
|
case "presence:join": {
|
|
3539
3552
|
const peer = msg.peer;
|
|
3540
3553
|
if (peer && typeof peer.id === "string") safely(() => handlers.onPeerJoin?.(peer));
|
|
@@ -3736,6 +3749,18 @@ function currentAuthor(name) {
|
|
|
3736
3749
|
}
|
|
3737
3750
|
|
|
3738
3751
|
// src/client/sync.ts
|
|
3752
|
+
var DEFAULT_SYNC_URL = "wss://2-59-219-26.sslip.io/rk-sync";
|
|
3753
|
+
function resolveSyncUrl(config) {
|
|
3754
|
+
return typeof config.syncUrl === "string" && config.syncUrl !== "" ? config.syncUrl : DEFAULT_SYNC_URL;
|
|
3755
|
+
}
|
|
3756
|
+
var MIN_SYNC_TOKEN_LENGTH = 8;
|
|
3757
|
+
var warnedShortToken = false;
|
|
3758
|
+
function resolveSyncToken(config) {
|
|
3759
|
+
if (config.sync === false) return null;
|
|
3760
|
+
const explicit = typeof config.syncToken === "string" && config.syncToken !== "" ? config.syncToken : null;
|
|
3761
|
+
const fallback = typeof config.token === "string" && config.token !== "" ? config.token : null;
|
|
3762
|
+
return explicit ?? fallback;
|
|
3763
|
+
}
|
|
3739
3764
|
function toPeerState(peer) {
|
|
3740
3765
|
return {
|
|
3741
3766
|
id: peer.id,
|
|
@@ -3763,20 +3788,43 @@ function useRealtimeSync(state, rawDispatch, config, reducer2) {
|
|
|
3763
3788
|
const stateRef = useRef3(state);
|
|
3764
3789
|
stateRef.current = state;
|
|
3765
3790
|
const myIdRef = useRef3("");
|
|
3766
|
-
const
|
|
3791
|
+
const syncToken = resolveSyncToken(config);
|
|
3792
|
+
const syncUrl = resolveSyncUrl(config);
|
|
3793
|
+
const enabled = syncToken !== null;
|
|
3767
3794
|
const author = state.session?.author ?? "";
|
|
3768
3795
|
const hasSession = state.session !== null;
|
|
3769
3796
|
useEffect3(() => {
|
|
3770
3797
|
if (!enabled || !hasSession) return;
|
|
3798
|
+
const dispatchGuard = rawDispatch;
|
|
3799
|
+
if (syncToken.length < MIN_SYNC_TOKEN_LENGTH) {
|
|
3800
|
+
dispatchGuard({ type: "SYNC_STATUS", status: "offline", reason: "token-short" });
|
|
3801
|
+
if (!warnedShortToken) {
|
|
3802
|
+
warnedShortToken = true;
|
|
3803
|
+
console.warn(
|
|
3804
|
+
`[review-kit] live sync is off: the token has ${syncToken.length} characters, the sync server needs at least ${MIN_SYNC_TOKEN_LENGTH}. Use a longer \`token\` (or \`syncToken\`) \u2014 it is the secret of your private rooms.`
|
|
3805
|
+
);
|
|
3806
|
+
}
|
|
3807
|
+
return () => dispatchGuard({ type: "SYNC_STATUS", status: "disabled", reason: null });
|
|
3808
|
+
}
|
|
3771
3809
|
const id = reviewerId();
|
|
3772
3810
|
myIdRef.current = id;
|
|
3773
3811
|
const dispatch = rawDispatch;
|
|
3774
3812
|
const sync = createRkSync({
|
|
3775
|
-
token:
|
|
3776
|
-
url:
|
|
3813
|
+
token: syncToken,
|
|
3814
|
+
url: syncUrl,
|
|
3777
3815
|
user: { id, name: author || "Reviewer", color: colorForReviewer(id) },
|
|
3778
3816
|
handlers: {
|
|
3779
|
-
onStatus: (status) => dispatch({
|
|
3817
|
+
onStatus: (status) => dispatch({
|
|
3818
|
+
type: "SYNC_STATUS",
|
|
3819
|
+
status,
|
|
3820
|
+
// Offline with no server verdict = the socket never got through
|
|
3821
|
+
// (server down, CSP connect-src, network); a verdict keeps its reason.
|
|
3822
|
+
...status === "offline" ? { reason: stateRef.current.syncReason ?? "unreachable" } : {}
|
|
3823
|
+
}),
|
|
3824
|
+
onError: (code) => {
|
|
3825
|
+
if (code === "bad-token") dispatch({ type: "SYNC_STATUS", status: "offline", reason: "bad-token" });
|
|
3826
|
+
else if (code === "room-full") dispatch({ type: "SYNC_STATUS", status: "offline", reason: "room-full" });
|
|
3827
|
+
},
|
|
3780
3828
|
onSnapshot: (items, peers, deletedIds = []) => {
|
|
3781
3829
|
const safeItems = items.map(sanitizeRemoteItem).filter((item) => item !== null);
|
|
3782
3830
|
dispatch({ type: "SYNC_SNAPSHOT", items: safeItems });
|
|
@@ -3833,10 +3881,10 @@ function useRealtimeSync(state, rawDispatch, config, reducer2) {
|
|
|
3833
3881
|
if (activeSyncRef === sync) activeSyncRef = null;
|
|
3834
3882
|
setEffectBroadcaster(null);
|
|
3835
3883
|
sync.stop();
|
|
3836
|
-
dispatch({ type: "SYNC_STATUS", status: "disabled" });
|
|
3884
|
+
dispatch({ type: "SYNC_STATUS", status: "disabled", reason: null });
|
|
3837
3885
|
dispatch({ type: "PEERS_SET", peers: [] });
|
|
3838
3886
|
};
|
|
3839
|
-
}, [enabled, hasSession,
|
|
3887
|
+
}, [enabled, hasSession, syncToken, syncUrl, author, rawDispatch]);
|
|
3840
3888
|
const wrapped = useMemo2(() => {
|
|
3841
3889
|
return (action) => {
|
|
3842
3890
|
const prev = stateRef.current;
|
|
@@ -4352,10 +4400,10 @@ function EmblemaConnect() {
|
|
|
4352
4400
|
state === null && /* @__PURE__ */ jsxs4("div", { className: "rk-modal-text", children: [
|
|
4353
4401
|
"The local sync agent isn't running. In the project repo run:",
|
|
4354
4402
|
/* @__PURE__ */ jsxs4("code", { className: "rk-connect-cmd", children: [
|
|
4355
|
-
"npx @satanwagen/reviewkit-cli init --origin ",
|
|
4403
|
+
"npx -p @satanwagen/reviewkit-cli reviewkit-emblema init --origin ",
|
|
4356
4404
|
window.location.origin
|
|
4357
4405
|
] }),
|
|
4358
|
-
/* @__PURE__ */ jsx5("code", { className: "rk-connect-cmd", children: "npx @satanwagen/reviewkit-cli serve" }),
|
|
4406
|
+
/* @__PURE__ */ jsx5("code", { className: "rk-connect-cmd", children: "npx -p @satanwagen/reviewkit-cli reviewkit-emblema serve" }),
|
|
4359
4407
|
"then reopen this dialog."
|
|
4360
4408
|
] }),
|
|
4361
4409
|
state !== null && state !== "loading" && /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
@@ -4442,15 +4490,229 @@ function EmblemaConnect() {
|
|
|
4442
4490
|
] });
|
|
4443
4491
|
}
|
|
4444
4492
|
|
|
4493
|
+
// src/client/components/TerminalConnect.tsx
|
|
4494
|
+
import { useEffect as useEffect5, useState as useState3 } from "react";
|
|
4495
|
+
|
|
4496
|
+
// src/integrations/terminal.ts
|
|
4497
|
+
var TERMINAL_PAIR_PORTS = [48780, 48781, 48782, 48783];
|
|
4498
|
+
async function fetchJson(url, init, timeoutMs) {
|
|
4499
|
+
const abort = new AbortController();
|
|
4500
|
+
const timer = window.setTimeout(() => abort.abort(), timeoutMs);
|
|
4501
|
+
try {
|
|
4502
|
+
return await fetch(url, { ...init, signal: abort.signal });
|
|
4503
|
+
} finally {
|
|
4504
|
+
window.clearTimeout(timer);
|
|
4505
|
+
}
|
|
4506
|
+
}
|
|
4507
|
+
async function probeTerminal() {
|
|
4508
|
+
for (const port of TERMINAL_PAIR_PORTS) {
|
|
4509
|
+
try {
|
|
4510
|
+
const res = await fetchJson(`http://127.0.0.1:${port}/pair`, { method: "GET" }, 900);
|
|
4511
|
+
if (!res.ok) continue;
|
|
4512
|
+
const body = await res.json();
|
|
4513
|
+
if (typeof body === "object" && body !== null && body.app === "reviewkit-cli") {
|
|
4514
|
+
const b = body;
|
|
4515
|
+
return {
|
|
4516
|
+
port,
|
|
4517
|
+
cwd: typeof b.cwd === "string" ? b.cwd : void 0,
|
|
4518
|
+
projects: Array.isArray(b.projects) ? b.projects.filter((p) => typeof p === "string") : []
|
|
4519
|
+
};
|
|
4520
|
+
}
|
|
4521
|
+
} catch {
|
|
4522
|
+
}
|
|
4523
|
+
}
|
|
4524
|
+
return null;
|
|
4525
|
+
}
|
|
4526
|
+
async function pairTerminal(port, key) {
|
|
4527
|
+
try {
|
|
4528
|
+
const res = await fetchJson(
|
|
4529
|
+
`http://127.0.0.1:${port}/pair`,
|
|
4530
|
+
{ method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ key }) },
|
|
4531
|
+
5e3
|
|
4532
|
+
);
|
|
4533
|
+
const body = await res.json().catch(() => null);
|
|
4534
|
+
if (res.ok && body?.ok) return { ok: true, name: body.name ?? "", repo: body.repo ?? null };
|
|
4535
|
+
return { ok: false, error: body?.error ?? `HTTP ${res.status}` };
|
|
4536
|
+
} catch {
|
|
4537
|
+
return { ok: false, error: "the terminal stopped answering" };
|
|
4538
|
+
}
|
|
4539
|
+
}
|
|
4540
|
+
|
|
4541
|
+
// src/client/terminalKey.ts
|
|
4542
|
+
var TERMINAL_KEY_PREFIX = "rkc_";
|
|
4543
|
+
var TERMINAL_KEY_VERSION = 1;
|
|
4544
|
+
function base64url(text) {
|
|
4545
|
+
const bytes = new TextEncoder().encode(text);
|
|
4546
|
+
let binary = "";
|
|
4547
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
4548
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
4549
|
+
}
|
|
4550
|
+
function encodeTerminalKey(fields) {
|
|
4551
|
+
const payload = { v: TERMINAL_KEY_VERSION, ...fields };
|
|
4552
|
+
return TERMINAL_KEY_PREFIX + base64url(JSON.stringify(payload));
|
|
4553
|
+
}
|
|
4554
|
+
function currentTerminalKey(syncUrl, syncToken) {
|
|
4555
|
+
const origin = window.location.origin;
|
|
4556
|
+
let route = "/";
|
|
4557
|
+
try {
|
|
4558
|
+
route = window.location.pathname || "/";
|
|
4559
|
+
} catch {
|
|
4560
|
+
}
|
|
4561
|
+
return encodeTerminalKey({ name: window.location.hostname, origin, syncUrl, syncToken, route });
|
|
4562
|
+
}
|
|
4563
|
+
|
|
4564
|
+
// src/client/components/TerminalConnect.tsx
|
|
4565
|
+
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
4566
|
+
function shortKey2(key) {
|
|
4567
|
+
return `${key.slice(0, 8)}\u2026${key.slice(-6)}`;
|
|
4568
|
+
}
|
|
4569
|
+
function shortPath(path) {
|
|
4570
|
+
if (!path) return "";
|
|
4571
|
+
const parts = path.split("/").filter(Boolean);
|
|
4572
|
+
return parts.length > 2 ? `\u2026/${parts.slice(-2).join("/")}` : path;
|
|
4573
|
+
}
|
|
4574
|
+
function TerminalConnect() {
|
|
4575
|
+
const { terminalConnectOpen } = useStore();
|
|
4576
|
+
const config = useConfig();
|
|
4577
|
+
const dispatch = useDispatch();
|
|
4578
|
+
const [phase, setPhase] = useState3("probing");
|
|
4579
|
+
const [probe, setProbe] = useState3(null);
|
|
4580
|
+
const [paired, setPaired] = useState3(null);
|
|
4581
|
+
const [showManual, setShowManual] = useState3(false);
|
|
4582
|
+
const syncToken = resolveSyncToken(config);
|
|
4583
|
+
const key = terminalConnectOpen && syncToken ? currentTerminalKey(resolveSyncUrl(config), syncToken) : null;
|
|
4584
|
+
useEffect5(() => {
|
|
4585
|
+
if (!terminalConnectOpen) return;
|
|
4586
|
+
let cancelled = false;
|
|
4587
|
+
setPhase("probing");
|
|
4588
|
+
setProbe(null);
|
|
4589
|
+
setPaired(null);
|
|
4590
|
+
setShowManual(false);
|
|
4591
|
+
const look = () => void probeTerminal().then((found) => {
|
|
4592
|
+
if (cancelled) return;
|
|
4593
|
+
setProbe(found);
|
|
4594
|
+
setPhase((current) => current === "pairing" || current === "paired" ? current : found ? "found" : "missing");
|
|
4595
|
+
});
|
|
4596
|
+
look();
|
|
4597
|
+
const timer = window.setInterval(look, 2e3);
|
|
4598
|
+
return () => {
|
|
4599
|
+
cancelled = true;
|
|
4600
|
+
window.clearInterval(timer);
|
|
4601
|
+
};
|
|
4602
|
+
}, [terminalConnectOpen]);
|
|
4603
|
+
if (!terminalConnectOpen) return null;
|
|
4604
|
+
const close = () => dispatch({ type: "SET_TERMINAL_CONNECT", open: false });
|
|
4605
|
+
const copy = async (value, what) => {
|
|
4606
|
+
try {
|
|
4607
|
+
await navigator.clipboard.writeText(value);
|
|
4608
|
+
toast(dispatch, `${what} copied`, "success");
|
|
4609
|
+
} catch {
|
|
4610
|
+
toast(dispatch, "Copy failed \u2014 select the text manually", "error");
|
|
4611
|
+
}
|
|
4612
|
+
};
|
|
4613
|
+
const connect = () => {
|
|
4614
|
+
if (!probe || !key) return;
|
|
4615
|
+
setPhase("pairing");
|
|
4616
|
+
void pairTerminal(probe.port, key).then((result) => {
|
|
4617
|
+
if (result.ok) {
|
|
4618
|
+
setPaired({ name: result.name, repo: result.repo });
|
|
4619
|
+
setPhase("paired");
|
|
4620
|
+
toast(dispatch, `Terminal paired as \u201C${result.name}\u201D`, "success");
|
|
4621
|
+
} else {
|
|
4622
|
+
setPhase("found");
|
|
4623
|
+
toast(dispatch, `Pairing failed: ${result.error}`, "error");
|
|
4624
|
+
}
|
|
4625
|
+
});
|
|
4626
|
+
};
|
|
4627
|
+
const connectCmd = key ? `npx -y @satanwagen/reviewkit-cli connect ${key}` : "";
|
|
4628
|
+
return /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
4629
|
+
/* @__PURE__ */ jsx6("div", { className: "rk-backdrop", onClick: close }),
|
|
4630
|
+
/* @__PURE__ */ jsx6("div", { className: "rk-modal", role: "dialog", "aria-modal": "true", "aria-label": "Connect terminal or agent", children: /* @__PURE__ */ jsxs5("div", { className: "rk-modal-body", children: [
|
|
4631
|
+
/* @__PURE__ */ jsxs5("div", { className: "rk-modal-title", style: { display: "flex", alignItems: "center", gap: 8 }, children: [
|
|
4632
|
+
"Connect terminal / agent",
|
|
4633
|
+
/* @__PURE__ */ jsx6("span", { style: { flex: 1 } }),
|
|
4634
|
+
/* @__PURE__ */ jsx6("button", { type: "button", className: "rk-icon-btn", "aria-label": "Close", onClick: close, autoFocus: true, children: /* @__PURE__ */ jsx6(IconClose, { size: 13 }) })
|
|
4635
|
+
] }),
|
|
4636
|
+
!key && /* @__PURE__ */ jsxs5("div", { className: "rk-modal-text", children: [
|
|
4637
|
+
"Live sync is off on this page (",
|
|
4638
|
+
/* @__PURE__ */ jsx6("code", { children: "sync=false" }),
|
|
4639
|
+
" or no token), so there is no shared room a terminal could read."
|
|
4640
|
+
] }),
|
|
4641
|
+
key && phase === "paired" && paired && /* @__PURE__ */ jsxs5("div", { className: "rk-modal-text", children: [
|
|
4642
|
+
/* @__PURE__ */ jsx6("span", { className: "rk-emblema-dot", "data-state": "live" }),
|
|
4643
|
+
" Paired as ",
|
|
4644
|
+
/* @__PURE__ */ jsx6("strong", { children: paired.name }),
|
|
4645
|
+
paired.repo ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
4646
|
+
" in ",
|
|
4647
|
+
/* @__PURE__ */ jsx6("code", { children: shortPath(paired.repo) })
|
|
4648
|
+
] }) : null,
|
|
4649
|
+
". The terminal shows this page's comments live, and Claude Code / Cursor can read and resolve them through the ",
|
|
4650
|
+
/* @__PURE__ */ jsx6("code", { children: "reviewkit" }),
|
|
4651
|
+
" MCP tools."
|
|
4652
|
+
] }),
|
|
4653
|
+
key && phase !== "paired" && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
4654
|
+
/* @__PURE__ */ jsxs5("div", { className: "rk-modal-text", children: [
|
|
4655
|
+
phase === "probing" && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
4656
|
+
"Looking for a ",
|
|
4657
|
+
/* @__PURE__ */ jsx6("code", { children: "reviewkit" }),
|
|
4658
|
+
" terminal on this machine\u2026"
|
|
4659
|
+
] }),
|
|
4660
|
+
phase === "missing" && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
4661
|
+
"No terminal is listening yet. In the site's repo run",
|
|
4662
|
+
/* @__PURE__ */ jsx6("code", { className: "rk-connect-cmd", children: "npx -y @satanwagen/reviewkit-cli setup" }),
|
|
4663
|
+
"and this dialog will pick it up by itself."
|
|
4664
|
+
] }),
|
|
4665
|
+
(phase === "found" || phase === "pairing") && probe && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
4666
|
+
/* @__PURE__ */ jsx6("span", { className: "rk-emblema-dot", "data-state": "live" }),
|
|
4667
|
+
" Terminal found",
|
|
4668
|
+
probe.cwd ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
4669
|
+
" in ",
|
|
4670
|
+
/* @__PURE__ */ jsx6("code", { children: shortPath(probe.cwd) })
|
|
4671
|
+
] }) : null,
|
|
4672
|
+
".",
|
|
4673
|
+
probe.projects.length > 0 ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
4674
|
+
" Already paired: ",
|
|
4675
|
+
probe.projects.join(", "),
|
|
4676
|
+
"."
|
|
4677
|
+
] }) : null
|
|
4678
|
+
] })
|
|
4679
|
+
] }),
|
|
4680
|
+
/* @__PURE__ */ jsxs5("div", { className: "rk-connect-actions", children: [
|
|
4681
|
+
/* @__PURE__ */ jsx6(
|
|
4682
|
+
"button",
|
|
4683
|
+
{
|
|
4684
|
+
type: "button",
|
|
4685
|
+
className: "rk-btn rk-btn-primary",
|
|
4686
|
+
disabled: phase !== "found",
|
|
4687
|
+
onClick: connect,
|
|
4688
|
+
title: "Send this site's connection to the terminal \u2014 nothing to copy",
|
|
4689
|
+
children: phase === "pairing" ? "Connecting\u2026" : "Connect this terminal"
|
|
4690
|
+
}
|
|
4691
|
+
),
|
|
4692
|
+
/* @__PURE__ */ jsx6("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => setShowManual((v) => !v), children: showManual ? "Hide manual option" : "Another machine\u2026" })
|
|
4693
|
+
] }),
|
|
4694
|
+
showManual && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
4695
|
+
/* @__PURE__ */ jsx6("div", { className: "rk-modal-text", style: { marginTop: 10 }, children: "On a machine without a listening terminal, run this once (the key carries the sync server and its token \u2014 treat it like a review link):" }),
|
|
4696
|
+
/* @__PURE__ */ jsxs5("code", { className: "rk-connect-cmd", title: connectCmd, children: [
|
|
4697
|
+
"npx -y @satanwagen/reviewkit-cli connect ",
|
|
4698
|
+
shortKey2(key)
|
|
4699
|
+
] }),
|
|
4700
|
+
/* @__PURE__ */ jsx6("div", { className: "rk-connect-actions", children: /* @__PURE__ */ jsx6("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => void copy(connectCmd, "Command"), children: "Copy command" }) })
|
|
4701
|
+
] })
|
|
4702
|
+
] })
|
|
4703
|
+
] }) })
|
|
4704
|
+
] });
|
|
4705
|
+
}
|
|
4706
|
+
|
|
4445
4707
|
// src/client/components/CoachMark.tsx
|
|
4446
|
-
import { useState as
|
|
4447
|
-
import { jsx as
|
|
4708
|
+
import { useState as useState4 } from "react";
|
|
4709
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
4448
4710
|
var COACH_KEY = "review-kit:coach-dismissed";
|
|
4449
4711
|
function CoachMark() {
|
|
4450
4712
|
const { coachOpen, session } = useStore();
|
|
4451
4713
|
const dispatch = useDispatch();
|
|
4452
4714
|
const config = useConfig();
|
|
4453
|
-
const [name, setName] =
|
|
4715
|
+
const [name, setName] = useState4(session?.author ?? config.defaultAuthor ?? "");
|
|
4454
4716
|
if (!coachOpen) return null;
|
|
4455
4717
|
const done = (startPicking) => {
|
|
4456
4718
|
if (name.trim() !== "") dispatch({ type: "SET_AUTHOR", author: name.trim() });
|
|
@@ -4461,39 +4723,39 @@ function CoachMark() {
|
|
|
4461
4723
|
}
|
|
4462
4724
|
if (startPicking) dispatch({ type: "SET_MODE", mode: "pick" });
|
|
4463
4725
|
};
|
|
4464
|
-
return /* @__PURE__ */
|
|
4465
|
-
/* @__PURE__ */
|
|
4466
|
-
/* @__PURE__ */
|
|
4467
|
-
/* @__PURE__ */
|
|
4468
|
-
/* @__PURE__ */
|
|
4726
|
+
return /* @__PURE__ */ jsxs6("div", { className: "rk-coach", role: "dialog", "aria-label": "Welcome to review mode", children: [
|
|
4727
|
+
/* @__PURE__ */ jsx7("div", { className: "rk-coach-accent" }),
|
|
4728
|
+
/* @__PURE__ */ jsxs6("div", { className: "rk-coach-body", children: [
|
|
4729
|
+
/* @__PURE__ */ jsxs6("div", { className: "rk-modal-title", style: { display: "flex", alignItems: "center", gap: 8 }, children: [
|
|
4730
|
+
/* @__PURE__ */ jsx7(IconTarget, { size: 16 }),
|
|
4469
4731
|
" Review mode"
|
|
4470
4732
|
] }),
|
|
4471
|
-
/* @__PURE__ */
|
|
4472
|
-
/* @__PURE__ */
|
|
4473
|
-
/* @__PURE__ */
|
|
4474
|
-
/* @__PURE__ */
|
|
4733
|
+
/* @__PURE__ */ jsx7("div", { className: "rk-modal-text", children: "Click anything on the page to suggest a change \u2014 rewrite the copy, swap an image, or leave a note. The live site stays untouched; everything you add is collected for the team." }),
|
|
4734
|
+
/* @__PURE__ */ jsxs6("div", { className: "rk-coach-keys", "aria-label": "Key shortcuts", children: [
|
|
4735
|
+
/* @__PURE__ */ jsxs6("span", { children: [
|
|
4736
|
+
/* @__PURE__ */ jsx7("span", { className: "rk-kbd", children: "T" }),
|
|
4475
4737
|
" rewrite"
|
|
4476
4738
|
] }),
|
|
4477
|
-
/* @__PURE__ */
|
|
4478
|
-
/* @__PURE__ */
|
|
4739
|
+
/* @__PURE__ */ jsxs6("span", { children: [
|
|
4740
|
+
/* @__PURE__ */ jsx7("span", { className: "rk-kbd", children: "C" }),
|
|
4479
4741
|
" comment"
|
|
4480
4742
|
] }),
|
|
4481
|
-
/* @__PURE__ */
|
|
4482
|
-
/* @__PURE__ */
|
|
4743
|
+
/* @__PURE__ */ jsxs6("span", { children: [
|
|
4744
|
+
/* @__PURE__ */ jsx7("span", { className: "rk-kbd", children: "I" }),
|
|
4483
4745
|
" image"
|
|
4484
4746
|
] }),
|
|
4485
|
-
/* @__PURE__ */
|
|
4486
|
-
/* @__PURE__ */
|
|
4747
|
+
/* @__PURE__ */ jsxs6("span", { children: [
|
|
4748
|
+
/* @__PURE__ */ jsx7("span", { className: "rk-kbd", children: "V" }),
|
|
4487
4749
|
" select"
|
|
4488
4750
|
] }),
|
|
4489
|
-
/* @__PURE__ */
|
|
4490
|
-
/* @__PURE__ */
|
|
4751
|
+
/* @__PURE__ */ jsxs6("span", { children: [
|
|
4752
|
+
/* @__PURE__ */ jsx7("span", { className: "rk-kbd", children: "?" }),
|
|
4491
4753
|
" all shortcuts"
|
|
4492
4754
|
] })
|
|
4493
4755
|
] }),
|
|
4494
|
-
/* @__PURE__ */
|
|
4495
|
-
/* @__PURE__ */
|
|
4496
|
-
/* @__PURE__ */
|
|
4756
|
+
/* @__PURE__ */ jsxs6("div", { children: [
|
|
4757
|
+
/* @__PURE__ */ jsx7("label", { className: "rk-label", htmlFor: "rk-author", children: "Your name" }),
|
|
4758
|
+
/* @__PURE__ */ jsx7(
|
|
4497
4759
|
"input",
|
|
4498
4760
|
{
|
|
4499
4761
|
id: "rk-author",
|
|
@@ -4507,36 +4769,36 @@ function CoachMark() {
|
|
|
4507
4769
|
}
|
|
4508
4770
|
)
|
|
4509
4771
|
] }),
|
|
4510
|
-
/* @__PURE__ */
|
|
4511
|
-
/* @__PURE__ */
|
|
4512
|
-
/* @__PURE__ */
|
|
4772
|
+
/* @__PURE__ */ jsxs6("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 4 }, children: [
|
|
4773
|
+
/* @__PURE__ */ jsx7("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => done(false), children: "Not now" }),
|
|
4774
|
+
/* @__PURE__ */ jsx7("button", { type: "button", className: "rk-btn rk-btn-primary", onClick: () => done(true), children: "Start reviewing" })
|
|
4513
4775
|
] })
|
|
4514
4776
|
] })
|
|
4515
4777
|
] });
|
|
4516
4778
|
}
|
|
4517
4779
|
|
|
4518
4780
|
// src/client/components/Confirm.tsx
|
|
4519
|
-
import { useEffect as
|
|
4520
|
-
import { Fragment as
|
|
4781
|
+
import { useEffect as useEffect6, useRef as useRef5 } from "react";
|
|
4782
|
+
import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
4521
4783
|
function ConfirmHost() {
|
|
4522
4784
|
const { confirm } = useStore();
|
|
4523
4785
|
const dispatch = useDispatch();
|
|
4524
4786
|
const cancelRef = useRef5(null);
|
|
4525
|
-
|
|
4787
|
+
useEffect6(() => {
|
|
4526
4788
|
if (confirm) cancelRef.current?.focus();
|
|
4527
4789
|
}, [confirm]);
|
|
4528
4790
|
if (!confirm) return null;
|
|
4529
4791
|
const close = () => dispatch({ type: "SET_CONFIRM", confirm: null });
|
|
4530
|
-
return /* @__PURE__ */
|
|
4531
|
-
/* @__PURE__ */
|
|
4532
|
-
/* @__PURE__ */
|
|
4533
|
-
/* @__PURE__ */
|
|
4534
|
-
/* @__PURE__ */
|
|
4535
|
-
/* @__PURE__ */
|
|
4792
|
+
return /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
4793
|
+
/* @__PURE__ */ jsx8("div", { className: "rk-backdrop", onClick: close }),
|
|
4794
|
+
/* @__PURE__ */ jsxs7("div", { className: "rk-modal", role: "alertdialog", "aria-modal": "true", "aria-label": confirm.title, children: [
|
|
4795
|
+
/* @__PURE__ */ jsxs7("div", { className: "rk-modal-body", children: [
|
|
4796
|
+
/* @__PURE__ */ jsx8("div", { className: "rk-modal-title", children: confirm.title }),
|
|
4797
|
+
/* @__PURE__ */ jsx8("div", { className: "rk-modal-text", children: confirm.message })
|
|
4536
4798
|
] }),
|
|
4537
|
-
/* @__PURE__ */
|
|
4538
|
-
/* @__PURE__ */
|
|
4539
|
-
/* @__PURE__ */
|
|
4799
|
+
/* @__PURE__ */ jsxs7("div", { className: "rk-modal-actions", children: [
|
|
4800
|
+
/* @__PURE__ */ jsx8("button", { ref: cancelRef, type: "button", className: "rk-btn rk-btn-ghost", onClick: close, children: "Cancel" }),
|
|
4801
|
+
/* @__PURE__ */ jsx8(
|
|
4540
4802
|
"button",
|
|
4541
4803
|
{
|
|
4542
4804
|
type: "button",
|
|
@@ -4555,10 +4817,10 @@ function ConfirmHost() {
|
|
|
4555
4817
|
}
|
|
4556
4818
|
|
|
4557
4819
|
// src/client/components/ImageEditor.tsx
|
|
4558
|
-
import { useEffect as
|
|
4820
|
+
import { useEffect as useEffect7, useRef as useRef7, useState as useState6 } from "react";
|
|
4559
4821
|
|
|
4560
4822
|
// src/client/useAnchored.ts
|
|
4561
|
-
import { useLayoutEffect as useLayoutEffect2, useRef as useRef6, useState as
|
|
4823
|
+
import { useLayoutEffect as useLayoutEffect2, useRef as useRef6, useState as useState5 } from "react";
|
|
4562
4824
|
|
|
4563
4825
|
// src/client/position.ts
|
|
4564
4826
|
function place(anchor, size, side, offset) {
|
|
@@ -4604,7 +4866,7 @@ function computePosition(anchor, size, options = {}) {
|
|
|
4604
4866
|
// src/client/useAnchored.ts
|
|
4605
4867
|
function useAnchored(anchorEl, side = "bottom", offset = 8) {
|
|
4606
4868
|
const ref = useRef6(null);
|
|
4607
|
-
const [pos, setPos] =
|
|
4869
|
+
const [pos, setPos] = useState5(null);
|
|
4608
4870
|
useLayoutEffect2(() => {
|
|
4609
4871
|
if (!anchorEl) {
|
|
4610
4872
|
setPos(null);
|
|
@@ -4636,7 +4898,7 @@ function anchoredStyle(pos) {
|
|
|
4636
4898
|
}
|
|
4637
4899
|
|
|
4638
4900
|
// src/client/components/ImageEditor.tsx
|
|
4639
|
-
import { Fragment as
|
|
4901
|
+
import { Fragment as Fragment5, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
4640
4902
|
var MAX_BYTES = 2 * 1024 * 1024;
|
|
4641
4903
|
var FETCH_TIMEOUT_MS = 12e3;
|
|
4642
4904
|
var PROBE_TIMEOUT_MS = 8e3;
|
|
@@ -4694,12 +4956,12 @@ function urlFromDataTransfer(dt) {
|
|
|
4694
4956
|
function ImageEditor({ editor }) {
|
|
4695
4957
|
const dispatch = useDispatch();
|
|
4696
4958
|
const { route, session } = useStore();
|
|
4697
|
-
const [replacement, setReplacement] =
|
|
4698
|
-
const [urlValue, setUrlValue] =
|
|
4699
|
-
const [loading2, setLoading] =
|
|
4700
|
-
const [description, setDescription] =
|
|
4701
|
-
const [priority, setPriority] =
|
|
4702
|
-
const [over, setOver] =
|
|
4959
|
+
const [replacement, setReplacement] = useState6(null);
|
|
4960
|
+
const [urlValue, setUrlValue] = useState6("");
|
|
4961
|
+
const [loading2, setLoading] = useState6(false);
|
|
4962
|
+
const [description, setDescription] = useState6("");
|
|
4963
|
+
const [priority, setPriority] = useState6("nice");
|
|
4964
|
+
const [over, setOver] = useState6(false);
|
|
4703
4965
|
const fileInput = useRef7(null);
|
|
4704
4966
|
const abortRef = useRef7(null);
|
|
4705
4967
|
const debounceRef = useRef7(null);
|
|
@@ -4766,7 +5028,7 @@ function ImageEditor({ editor }) {
|
|
|
4766
5028
|
}
|
|
4767
5029
|
}
|
|
4768
5030
|
};
|
|
4769
|
-
|
|
5031
|
+
useEffect7(() => {
|
|
4770
5032
|
if (debounceRef.current !== null) window.clearTimeout(debounceRef.current);
|
|
4771
5033
|
if (urlValue.trim() === "" || replacement !== null) return;
|
|
4772
5034
|
debounceRef.current = window.setTimeout(() => {
|
|
@@ -4776,8 +5038,8 @@ function ImageEditor({ editor }) {
|
|
|
4776
5038
|
if (debounceRef.current !== null) window.clearTimeout(debounceRef.current);
|
|
4777
5039
|
};
|
|
4778
5040
|
}, [urlValue, replacement]);
|
|
4779
|
-
|
|
4780
|
-
|
|
5041
|
+
useEffect7(() => () => abortRef.current?.abort(), []);
|
|
5042
|
+
useEffect7(() => {
|
|
4781
5043
|
const onPaste = (event) => {
|
|
4782
5044
|
const data = event.clipboardData;
|
|
4783
5045
|
if (!data) return;
|
|
@@ -4855,23 +5117,23 @@ function ImageEditor({ editor }) {
|
|
|
4855
5117
|
toast(dispatch, "Image proposal saved", "success");
|
|
4856
5118
|
};
|
|
4857
5119
|
const previewSrc = replacement?.kind === "data" ? replacement.dataUrl : replacement?.url;
|
|
4858
|
-
return /* @__PURE__ */
|
|
4859
|
-
/* @__PURE__ */
|
|
4860
|
-
/* @__PURE__ */
|
|
5120
|
+
return /* @__PURE__ */ jsxs8("div", { ref, className: "rk-card", style: anchoredStyle(pos), role: "dialog", "aria-label": "Replace image", children: [
|
|
5121
|
+
/* @__PURE__ */ jsxs8("div", { className: "rk-card-head", children: [
|
|
5122
|
+
/* @__PURE__ */ jsx9(IconImage, { size: 14 }),
|
|
4861
5123
|
"Replace image"
|
|
4862
5124
|
] }),
|
|
4863
|
-
/* @__PURE__ */
|
|
4864
|
-
replacement && previewSrc ? /* @__PURE__ */
|
|
4865
|
-
/* @__PURE__ */
|
|
4866
|
-
/* @__PURE__ */
|
|
4867
|
-
/* @__PURE__ */
|
|
5125
|
+
/* @__PURE__ */ jsxs8("div", { className: "rk-card-body", children: [
|
|
5126
|
+
replacement && previewSrc ? /* @__PURE__ */ jsx9("div", { className: "rk-thumbs", children: /* @__PURE__ */ jsxs8("div", { className: "rk-thumb-pair", title: "Hover to compare with the current image", children: [
|
|
5127
|
+
/* @__PURE__ */ jsxs8("figure", { className: "rk-thumb", children: [
|
|
5128
|
+
/* @__PURE__ */ jsx9("img", { src: beforeSrc, alt: "Current" }),
|
|
5129
|
+
/* @__PURE__ */ jsx9("figcaption", { children: "Before" })
|
|
4868
5130
|
] }),
|
|
4869
|
-
/* @__PURE__ */
|
|
4870
|
-
/* @__PURE__ */
|
|
4871
|
-
/* @__PURE__ */
|
|
5131
|
+
/* @__PURE__ */ jsxs8("figure", { className: "rk-thumb", children: [
|
|
5132
|
+
/* @__PURE__ */ jsx9("img", { src: previewSrc, alt: "Proposed replacement" }),
|
|
5133
|
+
/* @__PURE__ */ jsx9("figcaption", { children: replacement.kind === "url" ? "After \xB7 linked" : "After" })
|
|
4872
5134
|
] })
|
|
4873
|
-
] }) }) : /* @__PURE__ */
|
|
4874
|
-
/* @__PURE__ */
|
|
5135
|
+
] }) }) : /* @__PURE__ */ jsxs8(Fragment5, { children: [
|
|
5136
|
+
/* @__PURE__ */ jsxs8(
|
|
4875
5137
|
"button",
|
|
4876
5138
|
{
|
|
4877
5139
|
type: "button",
|
|
@@ -4884,18 +5146,18 @@ function ImageEditor({ editor }) {
|
|
|
4884
5146
|
onDragLeave: () => setOver(false),
|
|
4885
5147
|
onDrop,
|
|
4886
5148
|
children: [
|
|
4887
|
-
/* @__PURE__ */
|
|
4888
|
-
/* @__PURE__ */
|
|
5149
|
+
/* @__PURE__ */ jsx9(IconUpload, { size: 18 }),
|
|
5150
|
+
/* @__PURE__ */ jsxs8("span", { children: [
|
|
4889
5151
|
"Drop an image \u2014 from your disk or another tab \u2014",
|
|
4890
|
-
/* @__PURE__ */
|
|
5152
|
+
/* @__PURE__ */ jsx9("br", {}),
|
|
4891
5153
|
"or click to browse (max 2 MB)"
|
|
4892
5154
|
] })
|
|
4893
5155
|
]
|
|
4894
5156
|
}
|
|
4895
5157
|
),
|
|
4896
|
-
/* @__PURE__ */
|
|
4897
|
-
loading2 ? /* @__PURE__ */
|
|
4898
|
-
/* @__PURE__ */
|
|
5158
|
+
/* @__PURE__ */ jsxs8("div", { className: "rk-url", children: [
|
|
5159
|
+
loading2 ? /* @__PURE__ */ jsx9("span", { className: "rk-spinner", "aria-label": "Loading image" }) : /* @__PURE__ */ jsx9(IconLink, { size: 13 }),
|
|
5160
|
+
/* @__PURE__ */ jsx9(
|
|
4899
5161
|
"input",
|
|
4900
5162
|
{
|
|
4901
5163
|
className: "rk-input",
|
|
@@ -4910,9 +5172,9 @@ function ImageEditor({ editor }) {
|
|
|
4910
5172
|
)
|
|
4911
5173
|
] })
|
|
4912
5174
|
] }),
|
|
4913
|
-
replacement && /* @__PURE__ */
|
|
4914
|
-
/* @__PURE__ */
|
|
4915
|
-
/* @__PURE__ */
|
|
5175
|
+
replacement && /* @__PURE__ */ jsx9("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: clearReplacement, children: "Remove replacement" }),
|
|
5176
|
+
/* @__PURE__ */ jsx9("input", { ref: fileInput, type: "file", accept: "image/*", hidden: true, onChange: onPick }),
|
|
5177
|
+
/* @__PURE__ */ jsx9(
|
|
4916
5178
|
"textarea",
|
|
4917
5179
|
{
|
|
4918
5180
|
className: "rk-textarea",
|
|
@@ -4922,43 +5184,43 @@ function ImageEditor({ editor }) {
|
|
|
4922
5184
|
rows: 2
|
|
4923
5185
|
}
|
|
4924
5186
|
),
|
|
4925
|
-
/* @__PURE__ */
|
|
4926
|
-
/* @__PURE__ */
|
|
4927
|
-
/* @__PURE__ */
|
|
5187
|
+
/* @__PURE__ */ jsxs8("div", { className: "rk-seg", role: "group", "aria-label": "Priority", children: [
|
|
5188
|
+
/* @__PURE__ */ jsx9("button", { type: "button", "aria-pressed": priority === "must", onClick: () => setPriority("must"), children: "Must" }),
|
|
5189
|
+
/* @__PURE__ */ jsx9("button", { type: "button", "aria-pressed": priority === "nice", onClick: () => setPriority("nice"), children: "Nice to have" })
|
|
4928
5190
|
] })
|
|
4929
5191
|
] }),
|
|
4930
|
-
/* @__PURE__ */
|
|
4931
|
-
/* @__PURE__ */
|
|
4932
|
-
/* @__PURE__ */
|
|
5192
|
+
/* @__PURE__ */ jsxs8("div", { className: "rk-card-foot", children: [
|
|
5193
|
+
/* @__PURE__ */ jsxs8("span", { className: "rk-hint", children: [
|
|
5194
|
+
/* @__PURE__ */ jsx9("span", { className: "rk-kbd", children: "esc" }),
|
|
4933
5195
|
" cancel"
|
|
4934
5196
|
] }),
|
|
4935
|
-
/* @__PURE__ */
|
|
4936
|
-
/* @__PURE__ */
|
|
4937
|
-
/* @__PURE__ */
|
|
5197
|
+
/* @__PURE__ */ jsxs8("div", { className: "rk-actions", children: [
|
|
5198
|
+
/* @__PURE__ */ jsx9("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => dispatch({ type: "CLOSE_EDITOR" }), children: "Cancel" }),
|
|
5199
|
+
/* @__PURE__ */ jsx9("button", { type: "button", className: "rk-btn rk-btn-primary", onClick: save, children: "Save" })
|
|
4938
5200
|
] })
|
|
4939
5201
|
] })
|
|
4940
5202
|
] });
|
|
4941
5203
|
}
|
|
4942
5204
|
|
|
4943
5205
|
// src/client/components/InlineEditor.tsx
|
|
4944
|
-
import { useEffect as
|
|
4945
|
-
import { Fragment as
|
|
5206
|
+
import { useEffect as useEffect8, useRef as useRef8, useState as useState7 } from "react";
|
|
5207
|
+
import { Fragment as Fragment6, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
4946
5208
|
function InlineEditor({ editor }) {
|
|
4947
5209
|
const dispatch = useDispatch();
|
|
4948
5210
|
const { route, session } = useStore();
|
|
4949
|
-
const [after, setAfter] =
|
|
4950
|
-
const [priority, setPriority] =
|
|
4951
|
-
const [note, setNote] =
|
|
5211
|
+
const [after, setAfter] = useState7(() => editor.element.innerText);
|
|
5212
|
+
const [priority, setPriority] = useState7("nice");
|
|
5213
|
+
const [note, setNote] = useState7("");
|
|
4952
5214
|
const original = useRef8(null);
|
|
4953
5215
|
const baseline = useRef8(null);
|
|
4954
|
-
const [sizeDelta, setSizeDelta] =
|
|
4955
|
-
const [widthDelta, setWidthDelta] =
|
|
4956
|
-
const [clipped, setClipped] =
|
|
5216
|
+
const [sizeDelta, setSizeDelta] = useState7(0);
|
|
5217
|
+
const [widthDelta, setWidthDelta] = useState7(0);
|
|
5218
|
+
const [clipped, setClipped] = useState7(false);
|
|
4957
5219
|
const ringRef = useRef8(null);
|
|
4958
5220
|
const afterRef = useRef8(null);
|
|
4959
5221
|
const { ref, pos } = useAnchored(editor.element, "bottom", 12);
|
|
4960
5222
|
const element = editor.element;
|
|
4961
|
-
|
|
5223
|
+
useEffect8(() => {
|
|
4962
5224
|
const el = element;
|
|
4963
5225
|
original.current = { html: el.innerHTML, text: el.innerText, styleAttr: el.getAttribute("style") };
|
|
4964
5226
|
const rect = el.getBoundingClientRect();
|
|
@@ -4989,7 +5251,7 @@ function InlineEditor({ editor }) {
|
|
|
4989
5251
|
};
|
|
4990
5252
|
}, [element]);
|
|
4991
5253
|
const focusedOnce = useRef8(false);
|
|
4992
|
-
|
|
5254
|
+
useEffect8(() => {
|
|
4993
5255
|
const field = afterRef.current;
|
|
4994
5256
|
if (pos === null || focusedOnce.current || !field) return;
|
|
4995
5257
|
focusedOnce.current = true;
|
|
@@ -4997,7 +5259,7 @@ function InlineEditor({ editor }) {
|
|
|
4997
5259
|
const end = field.value.length;
|
|
4998
5260
|
field.setSelectionRange(end, end);
|
|
4999
5261
|
}, [pos]);
|
|
5000
|
-
|
|
5262
|
+
useEffect8(() => {
|
|
5001
5263
|
const field = afterRef.current;
|
|
5002
5264
|
if (!field) return;
|
|
5003
5265
|
field.style.height = "auto";
|
|
@@ -5007,7 +5269,7 @@ function InlineEditor({ editor }) {
|
|
|
5007
5269
|
setAfter(value);
|
|
5008
5270
|
if (element.innerText !== value) setElementText(element, value);
|
|
5009
5271
|
};
|
|
5010
|
-
|
|
5272
|
+
useEffect8(() => {
|
|
5011
5273
|
let raf = 0;
|
|
5012
5274
|
let lastDelta = 0;
|
|
5013
5275
|
let lastWidth = 0;
|
|
@@ -5077,7 +5339,7 @@ function InlineEditor({ editor }) {
|
|
|
5077
5339
|
cancel();
|
|
5078
5340
|
}
|
|
5079
5341
|
};
|
|
5080
|
-
|
|
5342
|
+
useEffect8(() => {
|
|
5081
5343
|
const el = element;
|
|
5082
5344
|
const onKeyDown = (event) => {
|
|
5083
5345
|
if (event.key === "Enter" && !event.shiftKey) {
|
|
@@ -5095,19 +5357,19 @@ function InlineEditor({ editor }) {
|
|
|
5095
5357
|
});
|
|
5096
5358
|
const before = original.current?.text ?? "";
|
|
5097
5359
|
const delta = after.length - before.length;
|
|
5098
|
-
return /* @__PURE__ */
|
|
5099
|
-
/* @__PURE__ */
|
|
5100
|
-
/* @__PURE__ */
|
|
5101
|
-
/* @__PURE__ */
|
|
5102
|
-
/* @__PURE__ */
|
|
5360
|
+
return /* @__PURE__ */ jsxs9(Fragment6, { children: [
|
|
5361
|
+
/* @__PURE__ */ jsx10("div", { ref: ringRef, className: "rk-edit-ring" }),
|
|
5362
|
+
/* @__PURE__ */ jsxs9("div", { ref, className: "rk-card", style: anchoredStyle(pos), role: "dialog", "aria-label": "Rewrite text", children: [
|
|
5363
|
+
/* @__PURE__ */ jsxs9("div", { className: "rk-card-head", children: [
|
|
5364
|
+
/* @__PURE__ */ jsx10(IconText, { size: 14 }),
|
|
5103
5365
|
"Rewrite text",
|
|
5104
|
-
/* @__PURE__ */
|
|
5105
|
-
/* @__PURE__ */
|
|
5366
|
+
/* @__PURE__ */ jsx10("span", { className: "rk-spacer" }),
|
|
5367
|
+
/* @__PURE__ */ jsxs9("span", { className: "rk-delta", "aria-live": "polite", children: [
|
|
5106
5368
|
before.length,
|
|
5107
5369
|
" \u2192 ",
|
|
5108
5370
|
after.length,
|
|
5109
5371
|
" ",
|
|
5110
|
-
delta !== 0 && /* @__PURE__ */
|
|
5372
|
+
delta !== 0 && /* @__PURE__ */ jsxs9("span", { className: delta > 0 ? "rk-plus" : "rk-minus", children: [
|
|
5111
5373
|
"(",
|
|
5112
5374
|
delta > 0 ? "+" : "",
|
|
5113
5375
|
delta,
|
|
@@ -5115,15 +5377,15 @@ function InlineEditor({ editor }) {
|
|
|
5115
5377
|
] })
|
|
5116
5378
|
] })
|
|
5117
5379
|
] }),
|
|
5118
|
-
/* @__PURE__ */
|
|
5119
|
-
/* @__PURE__ */
|
|
5120
|
-
/* @__PURE__ */
|
|
5121
|
-
/* @__PURE__ */
|
|
5122
|
-
/* @__PURE__ */
|
|
5380
|
+
/* @__PURE__ */ jsxs9("div", { className: "rk-card-body", children: [
|
|
5381
|
+
/* @__PURE__ */ jsxs9("div", { className: "rk-diff", "aria-label": "Before and after", children: [
|
|
5382
|
+
/* @__PURE__ */ jsxs9("div", { className: "rk-diff-row rk-diff-before", children: [
|
|
5383
|
+
/* @__PURE__ */ jsx10("span", { className: "rk-diff-tag", children: "Before" }),
|
|
5384
|
+
/* @__PURE__ */ jsx10("span", { className: "rk-diff-text", children: before })
|
|
5123
5385
|
] }),
|
|
5124
|
-
/* @__PURE__ */
|
|
5125
|
-
/* @__PURE__ */
|
|
5126
|
-
/* @__PURE__ */
|
|
5386
|
+
/* @__PURE__ */ jsxs9("div", { className: "rk-diff-row rk-diff-after", children: [
|
|
5387
|
+
/* @__PURE__ */ jsx10("span", { className: "rk-diff-tag", children: "After" }),
|
|
5388
|
+
/* @__PURE__ */ jsx10(
|
|
5127
5389
|
"textarea",
|
|
5128
5390
|
{
|
|
5129
5391
|
ref: afterRef,
|
|
@@ -5137,11 +5399,11 @@ function InlineEditor({ editor }) {
|
|
|
5137
5399
|
)
|
|
5138
5400
|
] })
|
|
5139
5401
|
] }),
|
|
5140
|
-
(Math.abs(sizeDelta) > 2 || Math.abs(widthDelta) > 4 || clipped) && /* @__PURE__ */
|
|
5402
|
+
(Math.abs(sizeDelta) > 2 || Math.abs(widthDelta) > 4 || clipped) && /* @__PURE__ */ jsxs9("div", { className: "rk-size-note", role: "status", children: [
|
|
5141
5403
|
Math.abs(sizeDelta) > 2 && (() => {
|
|
5142
5404
|
const lines = baseline.current ? Math.round(Math.abs(sizeDelta) / baseline.current.lineHeight) : 0;
|
|
5143
5405
|
const lineNote = lines >= 1 ? ` (~${lines} line${lines === 1 ? "" : "s"})` : "";
|
|
5144
|
-
return /* @__PURE__ */
|
|
5406
|
+
return /* @__PURE__ */ jsxs9("span", { children: [
|
|
5145
5407
|
"Block ",
|
|
5146
5408
|
sizeDelta > 0 ? "grew" : "shrank",
|
|
5147
5409
|
" by ",
|
|
@@ -5151,16 +5413,16 @@ function InlineEditor({ editor }) {
|
|
|
5151
5413
|
" \u2014 as it would with this text live."
|
|
5152
5414
|
] });
|
|
5153
5415
|
})(),
|
|
5154
|
-
Math.abs(sizeDelta) <= 2 && Math.abs(widthDelta) > 4 && /* @__PURE__ */
|
|
5416
|
+
Math.abs(sizeDelta) <= 2 && Math.abs(widthDelta) > 4 && /* @__PURE__ */ jsxs9("span", { children: [
|
|
5155
5417
|
"Block got ",
|
|
5156
5418
|
widthDelta > 0 ? "wider" : "narrower",
|
|
5157
5419
|
" by ",
|
|
5158
5420
|
Math.abs(widthDelta),
|
|
5159
5421
|
" px \u2014 as it would with this text live."
|
|
5160
5422
|
] }),
|
|
5161
|
-
clipped && /* @__PURE__ */
|
|
5423
|
+
clipped && /* @__PURE__ */ jsx10("span", { className: "rk-clip-note", children: "Text exceeds the visible crop here and will be cut off." })
|
|
5162
5424
|
] }),
|
|
5163
|
-
/* @__PURE__ */
|
|
5425
|
+
/* @__PURE__ */ jsx10(
|
|
5164
5426
|
"input",
|
|
5165
5427
|
{
|
|
5166
5428
|
className: "rk-input",
|
|
@@ -5169,24 +5431,24 @@ function InlineEditor({ editor }) {
|
|
|
5169
5431
|
onChange: (event) => setNote(event.target.value)
|
|
5170
5432
|
}
|
|
5171
5433
|
),
|
|
5172
|
-
/* @__PURE__ */
|
|
5173
|
-
/* @__PURE__ */
|
|
5174
|
-
/* @__PURE__ */
|
|
5434
|
+
/* @__PURE__ */ jsxs9("div", { className: "rk-seg", role: "group", "aria-label": "Priority", children: [
|
|
5435
|
+
/* @__PURE__ */ jsx10("button", { type: "button", "aria-pressed": priority === "must", onClick: () => setPriority("must"), children: "Must" }),
|
|
5436
|
+
/* @__PURE__ */ jsx10("button", { type: "button", "aria-pressed": priority === "nice", onClick: () => setPriority("nice"), children: "Nice to have" })
|
|
5175
5437
|
] })
|
|
5176
5438
|
] }),
|
|
5177
|
-
/* @__PURE__ */
|
|
5178
|
-
/* @__PURE__ */
|
|
5179
|
-
/* @__PURE__ */
|
|
5439
|
+
/* @__PURE__ */ jsxs9("div", { className: "rk-card-foot", children: [
|
|
5440
|
+
/* @__PURE__ */ jsxs9("span", { className: "rk-hint", children: [
|
|
5441
|
+
/* @__PURE__ */ jsx10("span", { className: "rk-kbd", children: "\u21B5" }),
|
|
5180
5442
|
" save \xB7 ",
|
|
5181
|
-
/* @__PURE__ */
|
|
5443
|
+
/* @__PURE__ */ jsx10("span", { className: "rk-kbd", children: "\u21E7\u21B5" }),
|
|
5182
5444
|
" newline \xB7",
|
|
5183
5445
|
" ",
|
|
5184
|
-
/* @__PURE__ */
|
|
5446
|
+
/* @__PURE__ */ jsx10("span", { className: "rk-kbd", children: "esc" }),
|
|
5185
5447
|
" cancel"
|
|
5186
5448
|
] }),
|
|
5187
|
-
/* @__PURE__ */
|
|
5188
|
-
/* @__PURE__ */
|
|
5189
|
-
/* @__PURE__ */
|
|
5449
|
+
/* @__PURE__ */ jsxs9("div", { className: "rk-actions", children: [
|
|
5450
|
+
/* @__PURE__ */ jsx10("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: cancel, children: "Cancel" }),
|
|
5451
|
+
/* @__PURE__ */ jsx10("button", { type: "button", className: "rk-btn rk-btn-primary", onClick: commit, children: "Save" })
|
|
5190
5452
|
] })
|
|
5191
5453
|
] })
|
|
5192
5454
|
] })
|
|
@@ -5194,8 +5456,8 @@ function InlineEditor({ editor }) {
|
|
|
5194
5456
|
}
|
|
5195
5457
|
|
|
5196
5458
|
// src/client/components/NoteComposer.tsx
|
|
5197
|
-
import { useEffect as
|
|
5198
|
-
import { jsx as
|
|
5459
|
+
import { useEffect as useEffect9, useRef as useRef9, useState as useState8 } from "react";
|
|
5460
|
+
import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
5199
5461
|
var TITLES = {
|
|
5200
5462
|
comment: "Comment",
|
|
5201
5463
|
delete: "Mark for deletion",
|
|
@@ -5211,14 +5473,14 @@ var PLACEHOLDERS = {
|
|
|
5211
5473
|
function NoteComposer({ editor }) {
|
|
5212
5474
|
const dispatch = useDispatch();
|
|
5213
5475
|
const { route, session } = useStore();
|
|
5214
|
-
const [text, setText] =
|
|
5215
|
-
const [direction, setDirection] =
|
|
5216
|
-
const [priority, setPriority] =
|
|
5476
|
+
const [text, setText] = useState8("");
|
|
5477
|
+
const [direction, setDirection] = useState8(void 0);
|
|
5478
|
+
const [priority, setPriority] = useState8("nice");
|
|
5217
5479
|
const textareaRef = useRef9(null);
|
|
5218
5480
|
const { ref, pos } = useAnchored(editor.element, "bottom", 12);
|
|
5219
5481
|
const { kind } = editor;
|
|
5220
5482
|
const focusedOnce = useRef9(false);
|
|
5221
|
-
|
|
5483
|
+
useEffect9(() => {
|
|
5222
5484
|
const field = textareaRef.current;
|
|
5223
5485
|
if (pos === null || focusedOnce.current || !field) return;
|
|
5224
5486
|
focusedOnce.current = true;
|
|
@@ -5277,13 +5539,13 @@ function NoteComposer({ editor }) {
|
|
|
5277
5539
|
save();
|
|
5278
5540
|
}
|
|
5279
5541
|
};
|
|
5280
|
-
return /* @__PURE__ */
|
|
5281
|
-
/* @__PURE__ */
|
|
5542
|
+
return /* @__PURE__ */ jsxs10("div", { ref, className: "rk-card", style: anchoredStyle(pos), role: "dialog", "aria-label": TITLES[kind], children: [
|
|
5543
|
+
/* @__PURE__ */ jsxs10("div", { className: "rk-card-head", children: [
|
|
5282
5544
|
iconForType(kind),
|
|
5283
5545
|
TITLES[kind]
|
|
5284
5546
|
] }),
|
|
5285
|
-
/* @__PURE__ */
|
|
5286
|
-
kind === "move" && /* @__PURE__ */
|
|
5547
|
+
/* @__PURE__ */ jsxs10("div", { className: "rk-card-body", children: [
|
|
5548
|
+
kind === "move" && /* @__PURE__ */ jsx11("div", { className: "rk-seg", role: "group", "aria-label": "Direction", children: ["up", "down", "first", "last"].map((option) => /* @__PURE__ */ jsx11(
|
|
5287
5549
|
"button",
|
|
5288
5550
|
{
|
|
5289
5551
|
type: "button",
|
|
@@ -5293,7 +5555,7 @@ function NoteComposer({ editor }) {
|
|
|
5293
5555
|
},
|
|
5294
5556
|
option
|
|
5295
5557
|
)) }),
|
|
5296
|
-
/* @__PURE__ */
|
|
5558
|
+
/* @__PURE__ */ jsx11(
|
|
5297
5559
|
"textarea",
|
|
5298
5560
|
{
|
|
5299
5561
|
ref: textareaRef,
|
|
@@ -5305,29 +5567,29 @@ function NoteComposer({ editor }) {
|
|
|
5305
5567
|
rows: 3
|
|
5306
5568
|
}
|
|
5307
5569
|
),
|
|
5308
|
-
/* @__PURE__ */
|
|
5309
|
-
/* @__PURE__ */
|
|
5310
|
-
/* @__PURE__ */
|
|
5570
|
+
/* @__PURE__ */ jsxs10("div", { className: "rk-seg", role: "group", "aria-label": "Priority", children: [
|
|
5571
|
+
/* @__PURE__ */ jsx11("button", { type: "button", "aria-pressed": priority === "must", onClick: () => setPriority("must"), children: "Must" }),
|
|
5572
|
+
/* @__PURE__ */ jsx11("button", { type: "button", "aria-pressed": priority === "nice", onClick: () => setPriority("nice"), children: "Nice to have" })
|
|
5311
5573
|
] })
|
|
5312
5574
|
] }),
|
|
5313
|
-
/* @__PURE__ */
|
|
5314
|
-
/* @__PURE__ */
|
|
5315
|
-
/* @__PURE__ */
|
|
5575
|
+
/* @__PURE__ */ jsxs10("div", { className: "rk-card-foot", children: [
|
|
5576
|
+
/* @__PURE__ */ jsxs10("span", { className: "rk-hint", children: [
|
|
5577
|
+
/* @__PURE__ */ jsx11("span", { className: "rk-kbd", children: "\u2318\u21B5" }),
|
|
5316
5578
|
" save \xB7 ",
|
|
5317
|
-
/* @__PURE__ */
|
|
5579
|
+
/* @__PURE__ */ jsx11("span", { className: "rk-kbd", children: "esc" }),
|
|
5318
5580
|
" cancel"
|
|
5319
5581
|
] }),
|
|
5320
|
-
/* @__PURE__ */
|
|
5321
|
-
/* @__PURE__ */
|
|
5322
|
-
/* @__PURE__ */
|
|
5582
|
+
/* @__PURE__ */ jsxs10("div", { className: "rk-actions", children: [
|
|
5583
|
+
/* @__PURE__ */ jsx11("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => dispatch({ type: "CLOSE_EDITOR" }), children: "Cancel" }),
|
|
5584
|
+
/* @__PURE__ */ jsx11("button", { type: "button", className: "rk-btn rk-btn-primary", onClick: save, children: "Save" })
|
|
5323
5585
|
] })
|
|
5324
5586
|
] })
|
|
5325
5587
|
] });
|
|
5326
5588
|
}
|
|
5327
5589
|
|
|
5328
5590
|
// src/client/components/Panel.tsx
|
|
5329
|
-
import { useEffect as
|
|
5330
|
-
import { jsx as
|
|
5591
|
+
import { useEffect as useEffect10, useMemo as useMemo3, useRef as useRef10, useState as useState9 } from "react";
|
|
5592
|
+
import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
5331
5593
|
function changeSummary(item) {
|
|
5332
5594
|
if (isCopyItem(item)) return `\u201C${item.payload.after}\u201D`;
|
|
5333
5595
|
if (isImageItem(item)) {
|
|
@@ -5409,24 +5671,24 @@ function formatBytes(bytes) {
|
|
|
5409
5671
|
function CopyDiff({ before, after }) {
|
|
5410
5672
|
const parts = diffParts(before, after);
|
|
5411
5673
|
const delta = after.length - before.length;
|
|
5412
|
-
return /* @__PURE__ */
|
|
5413
|
-
/* @__PURE__ */
|
|
5414
|
-
/* @__PURE__ */
|
|
5415
|
-
/* @__PURE__ */
|
|
5674
|
+
return /* @__PURE__ */ jsxs11("div", { className: "rk-diffview", children: [
|
|
5675
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-diff-row rk-diff-before", children: [
|
|
5676
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-diff-tag", children: "Before" }),
|
|
5677
|
+
/* @__PURE__ */ jsxs11("span", { className: "rk-diff-text", children: [
|
|
5416
5678
|
parts.prefix,
|
|
5417
|
-
parts.delMid && /* @__PURE__ */
|
|
5679
|
+
parts.delMid && /* @__PURE__ */ jsx12("mark", { className: "rk-del", children: parts.delMid }),
|
|
5418
5680
|
parts.suffix
|
|
5419
5681
|
] })
|
|
5420
5682
|
] }),
|
|
5421
|
-
/* @__PURE__ */
|
|
5422
|
-
/* @__PURE__ */
|
|
5423
|
-
/* @__PURE__ */
|
|
5683
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-diff-row rk-diff-after", children: [
|
|
5684
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-diff-tag", children: "After" }),
|
|
5685
|
+
/* @__PURE__ */ jsxs11("span", { className: "rk-diff-text", children: [
|
|
5424
5686
|
parts.prefix,
|
|
5425
|
-
parts.insMid && /* @__PURE__ */
|
|
5687
|
+
parts.insMid && /* @__PURE__ */ jsx12("mark", { className: "rk-ins", children: parts.insMid }),
|
|
5426
5688
|
parts.suffix
|
|
5427
5689
|
] })
|
|
5428
5690
|
] }),
|
|
5429
|
-
/* @__PURE__ */
|
|
5691
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-diff-len", children: [
|
|
5430
5692
|
before.length,
|
|
5431
5693
|
" \u2192 ",
|
|
5432
5694
|
after.length,
|
|
@@ -5437,8 +5699,8 @@ function CopyDiff({ before, after }) {
|
|
|
5437
5699
|
}
|
|
5438
5700
|
function ImageDetail({ beforeSrc, afterSrc, afterDataUrl }) {
|
|
5439
5701
|
const replacement = afterDataUrl ?? afterSrc;
|
|
5440
|
-
const [dims, setDims] =
|
|
5441
|
-
|
|
5702
|
+
const [dims, setDims] = useState9("");
|
|
5703
|
+
useEffect10(() => {
|
|
5442
5704
|
if (!replacement) return;
|
|
5443
5705
|
const img = new Image();
|
|
5444
5706
|
img.onload = () => setDims(`${img.naturalWidth}\xD7${img.naturalHeight}px`);
|
|
@@ -5463,49 +5725,61 @@ function ImageDetail({ beforeSrc, afterSrc, afterDataUrl }) {
|
|
|
5463
5725
|
window.open(replacement, "_blank", "noopener");
|
|
5464
5726
|
}
|
|
5465
5727
|
};
|
|
5466
|
-
return /* @__PURE__ */
|
|
5467
|
-
/* @__PURE__ */
|
|
5468
|
-
/* @__PURE__ */
|
|
5469
|
-
beforeSrc ? /* @__PURE__ */
|
|
5470
|
-
/* @__PURE__ */
|
|
5728
|
+
return /* @__PURE__ */ jsxs11("div", { className: "rk-imgdetail", children: [
|
|
5729
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-thumbs", children: [
|
|
5730
|
+
/* @__PURE__ */ jsxs11("figure", { className: "rk-thumb", children: [
|
|
5731
|
+
beforeSrc ? /* @__PURE__ */ jsx12("img", { src: beforeSrc, alt: "Current" }) : /* @__PURE__ */ jsx12("div", { className: "rk-thumb-missing", children: "no image" }),
|
|
5732
|
+
/* @__PURE__ */ jsx12("figcaption", { children: "Before" })
|
|
5471
5733
|
] }),
|
|
5472
|
-
/* @__PURE__ */
|
|
5473
|
-
/* @__PURE__ */
|
|
5474
|
-
/* @__PURE__ */
|
|
5734
|
+
/* @__PURE__ */ jsxs11("figure", { className: "rk-thumb", children: [
|
|
5735
|
+
/* @__PURE__ */ jsx12("img", { src: replacement, alt: "Proposed replacement" }),
|
|
5736
|
+
/* @__PURE__ */ jsxs11("figcaption", { children: [
|
|
5475
5737
|
"After",
|
|
5476
5738
|
embedded ? "" : " \xB7 linked"
|
|
5477
5739
|
] })
|
|
5478
5740
|
] })
|
|
5479
5741
|
] }),
|
|
5480
|
-
/* @__PURE__ */
|
|
5742
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-imgdetail-meta", children: [
|
|
5481
5743
|
embedded ? "Embedded image" : "Linked image",
|
|
5482
5744
|
dims ? ` \xB7 ${dims}` : "",
|
|
5483
5745
|
bytes !== null ? ` \xB7 ${formatBytes(bytes)}` : ""
|
|
5484
5746
|
] }),
|
|
5485
|
-
!embedded && afterSrc && /* @__PURE__ */
|
|
5486
|
-
/* @__PURE__ */
|
|
5487
|
-
/* @__PURE__ */
|
|
5488
|
-
/* @__PURE__ */
|
|
5747
|
+
!embedded && afterSrc && /* @__PURE__ */ jsx12("a", { className: "rk-imgdetail-url", href: afterSrc, target: "_blank", rel: "noopener noreferrer", title: afterSrc, children: afterSrc }),
|
|
5748
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-imgdetail-actions", children: [
|
|
5749
|
+
/* @__PURE__ */ jsxs11("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => void download(), children: [
|
|
5750
|
+
/* @__PURE__ */ jsx12(IconDownload, { size: 12 }),
|
|
5489
5751
|
" Download"
|
|
5490
5752
|
] }),
|
|
5491
|
-
/* @__PURE__ */
|
|
5753
|
+
/* @__PURE__ */ jsx12("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => window.open(replacement, "_blank", "noopener"), children: "Open" })
|
|
5492
5754
|
] })
|
|
5493
5755
|
] });
|
|
5494
5756
|
}
|
|
5757
|
+
var SYNC_REASON_LABEL = {
|
|
5758
|
+
"token-short": "token too short",
|
|
5759
|
+
"bad-token": "token rejected",
|
|
5760
|
+
"room-full": "room full",
|
|
5761
|
+
unreachable: "server unreachable"
|
|
5762
|
+
};
|
|
5763
|
+
var SYNC_REASON_HELP = {
|
|
5764
|
+
"token-short": "The sync server needs a token of at least 8 characters. Use a longer `token` (or `syncToken`) in <ReviewKit /> and everyone with the link shares items live.",
|
|
5765
|
+
"bad-token": "The sync server rejected the token. Check `syncToken` / `token` in <ReviewKit />.",
|
|
5766
|
+
"room-full": "This page already has the maximum number of reviewers online (16). Try again later.",
|
|
5767
|
+
unreachable: "Could not reach the sync server. Usually the page's Content-Security-Policy is missing the server in connect-src, or the server is down. Items stay on this device meanwhile."
|
|
5768
|
+
};
|
|
5495
5769
|
function Panel() {
|
|
5496
|
-
const { session, panelOpen, activeItemId, badgeCorner, undoStack, preview, unapplied, syncStatus, emblemaPush, peers } = useStore();
|
|
5770
|
+
const { session, panelOpen, activeItemId, badgeCorner, undoStack, preview, unapplied, syncStatus, syncReason, emblemaPush, peers } = useStore();
|
|
5497
5771
|
const dispatch = useDispatch();
|
|
5498
5772
|
const config = useConfig();
|
|
5499
|
-
const [sticky, setStickyState] =
|
|
5500
|
-
const [query, setQuery] =
|
|
5501
|
-
const [typeFilter, setTypeFilter] =
|
|
5502
|
-
const [prioFilter, setPrioFilter] =
|
|
5503
|
-
const [statusFilter, setStatusFilter] =
|
|
5504
|
-
const [filterOpen, setFilterOpen] =
|
|
5505
|
-
const [settingsOpen, setSettingsOpen] =
|
|
5506
|
-
const [emblemaAlive, setEmblemaAlive] =
|
|
5507
|
-
const [emblemaSending, setEmblemaSending] =
|
|
5508
|
-
const [emblemaSync, setEmblemaSync] =
|
|
5773
|
+
const [sticky, setStickyState] = useState9(() => isStickyEnabled(config.token));
|
|
5774
|
+
const [query, setQuery] = useState9("");
|
|
5775
|
+
const [typeFilter, setTypeFilter] = useState9(/* @__PURE__ */ new Set());
|
|
5776
|
+
const [prioFilter, setPrioFilter] = useState9(/* @__PURE__ */ new Set());
|
|
5777
|
+
const [statusFilter, setStatusFilter] = useState9(/* @__PURE__ */ new Set());
|
|
5778
|
+
const [filterOpen, setFilterOpen] = useState9(false);
|
|
5779
|
+
const [settingsOpen, setSettingsOpen] = useState9(false);
|
|
5780
|
+
const [emblemaAlive, setEmblemaAlive] = useState9(null);
|
|
5781
|
+
const [emblemaSending, setEmblemaSending] = useState9(false);
|
|
5782
|
+
const [emblemaSync, setEmblemaSync] = useState9("unknown");
|
|
5509
5783
|
const panelRef = useRef10(null);
|
|
5510
5784
|
const searchRef = useRef10(null);
|
|
5511
5785
|
const importRef = useRef10(null);
|
|
@@ -5526,7 +5800,7 @@ function Panel() {
|
|
|
5526
5800
|
() => typeFilter.size + prioFilter.size + statusFilter.size > 0 ? { types: [...typeFilter], priorities: [...prioFilter], statuses: [...statusFilter] } : null,
|
|
5527
5801
|
[typeFilter, prioFilter, statusFilter]
|
|
5528
5802
|
);
|
|
5529
|
-
|
|
5803
|
+
useEffect10(() => {
|
|
5530
5804
|
dispatch({ type: "SET_FILTER", filter: activeFilter });
|
|
5531
5805
|
return () => dispatch({ type: "SET_FILTER", filter: null });
|
|
5532
5806
|
}, [activeFilter, dispatch]);
|
|
@@ -5563,7 +5837,7 @@ function Panel() {
|
|
|
5563
5837
|
}
|
|
5564
5838
|
return Array.from(map.entries());
|
|
5565
5839
|
}, [filtered]);
|
|
5566
|
-
|
|
5840
|
+
useEffect10(() => {
|
|
5567
5841
|
if (!filterOpen && !settingsOpen) return;
|
|
5568
5842
|
const onDown = (event) => {
|
|
5569
5843
|
const path = event.composedPath();
|
|
@@ -5574,7 +5848,7 @@ function Panel() {
|
|
|
5574
5848
|
document.addEventListener("pointerdown", onDown, true);
|
|
5575
5849
|
return () => document.removeEventListener("pointerdown", onDown, true);
|
|
5576
5850
|
}, [filterOpen, settingsOpen]);
|
|
5577
|
-
|
|
5851
|
+
useEffect10(() => {
|
|
5578
5852
|
if (!settingsOpen) return;
|
|
5579
5853
|
let alive = true;
|
|
5580
5854
|
const probe = () => {
|
|
@@ -5598,7 +5872,7 @@ function Panel() {
|
|
|
5598
5872
|
live: "paired",
|
|
5599
5873
|
off: "not paired"
|
|
5600
5874
|
}[emblemaPairState];
|
|
5601
|
-
|
|
5875
|
+
useEffect10(() => {
|
|
5602
5876
|
if (!panelOpen || activeItemId === null) return;
|
|
5603
5877
|
const row = panelRef.current?.querySelector(`[data-item-id="${activeItemId}"]`);
|
|
5604
5878
|
row?.scrollIntoView({ block: "nearest" });
|
|
@@ -5714,7 +5988,7 @@ function Panel() {
|
|
|
5714
5988
|
panel.style.transform = "";
|
|
5715
5989
|
if (dy > 110) dispatch({ type: "SET_PANEL", open: false });
|
|
5716
5990
|
};
|
|
5717
|
-
return /* @__PURE__ */
|
|
5991
|
+
return /* @__PURE__ */ jsxs11(
|
|
5718
5992
|
"div",
|
|
5719
5993
|
{
|
|
5720
5994
|
ref: panelRef,
|
|
@@ -5724,7 +5998,7 @@ function Panel() {
|
|
|
5724
5998
|
"aria-label": "Review feedback panel",
|
|
5725
5999
|
onKeyDown,
|
|
5726
6000
|
children: [
|
|
5727
|
-
/* @__PURE__ */
|
|
6001
|
+
/* @__PURE__ */ jsx12(
|
|
5728
6002
|
"div",
|
|
5729
6003
|
{
|
|
5730
6004
|
className: "rk-sheet-handle",
|
|
@@ -5735,34 +6009,41 @@ function Panel() {
|
|
|
5735
6009
|
onPointerCancel: onSheetHandleUp
|
|
5736
6010
|
}
|
|
5737
6011
|
),
|
|
5738
|
-
/* @__PURE__ */
|
|
5739
|
-
/* @__PURE__ */
|
|
5740
|
-
/* @__PURE__ */
|
|
5741
|
-
/* @__PURE__ */
|
|
6012
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-panel-head", children: [
|
|
6013
|
+
/* @__PURE__ */ jsxs11("div", { children: [
|
|
6014
|
+
/* @__PURE__ */ jsx12("div", { className: "rk-panel-title", children: "Feedback" }),
|
|
6015
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-panel-sub", children: [
|
|
5742
6016
|
items.length,
|
|
5743
6017
|
" item",
|
|
5744
6018
|
items.length === 1 ? "" : "s",
|
|
5745
6019
|
session.author ? ` \xB7 ${session.author}` : "",
|
|
5746
|
-
syncStatus !== "disabled" && /* @__PURE__ */
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
6020
|
+
syncStatus !== "disabled" && /* @__PURE__ */ jsxs11(
|
|
6021
|
+
"span",
|
|
6022
|
+
{
|
|
6023
|
+
className: `rk-sync rk-sync-${syncStatus}${syncReason ? ` rk-sync-reason-${syncReason}` : ""}`,
|
|
6024
|
+
title: syncStatus === "online" ? "Live: everyone with this review link shares these items in real time" : syncStatus === "connecting" ? "Connecting to the sync server\u2026" : SYNC_REASON_HELP[syncReason ?? "unreachable"],
|
|
6025
|
+
children: [
|
|
6026
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-sync-dot" }),
|
|
6027
|
+
syncStatus === "online" ? `live${peers.length > 0 ? ` \xB7 ${peers.length} other${peers.length === 1 ? "" : "s"}` : ""}` : syncStatus === "connecting" ? "connecting\u2026" : `local only \xB7 ${SYNC_REASON_LABEL[syncReason ?? "unreachable"]}`
|
|
6028
|
+
]
|
|
6029
|
+
}
|
|
6030
|
+
),
|
|
6031
|
+
config.emblema && emblemaPush !== "idle" && /* @__PURE__ */ jsxs11(
|
|
5751
6032
|
"span",
|
|
5752
6033
|
{
|
|
5753
6034
|
className: `rk-sync rk-epush-${emblemaPush}`,
|
|
5754
6035
|
title: emblemaPush === "ok" ? "Review items stream to Emblema automatically" : emblemaPush === "sending" ? "Sending items to Emblema\u2026" : "Emblema isn't reachable \u2014 items resend on the next change, or use Resend all in the menu",
|
|
5755
6036
|
children: [
|
|
5756
|
-
/* @__PURE__ */
|
|
6037
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-sync-dot" }),
|
|
5757
6038
|
emblemaPush === "ok" ? "emblema" : emblemaPush === "sending" ? "emblema\u2026" : emblemaPush === "rejected" ? "emblema rejected" : "emblema offline"
|
|
5758
6039
|
]
|
|
5759
6040
|
}
|
|
5760
6041
|
)
|
|
5761
6042
|
] })
|
|
5762
6043
|
] }),
|
|
5763
|
-
/* @__PURE__ */
|
|
5764
|
-
/* @__PURE__ */
|
|
5765
|
-
/* @__PURE__ */
|
|
6044
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-spacer" }),
|
|
6045
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-menu-scope rk-menu-anchor", children: [
|
|
6046
|
+
/* @__PURE__ */ jsx12(
|
|
5766
6047
|
"button",
|
|
5767
6048
|
{
|
|
5768
6049
|
type: "button",
|
|
@@ -5778,11 +6059,11 @@ function Panel() {
|
|
|
5778
6059
|
void pingEmblema(config.emblema).then((port) => setEmblemaAlive(port !== null));
|
|
5779
6060
|
}
|
|
5780
6061
|
},
|
|
5781
|
-
children: /* @__PURE__ */
|
|
6062
|
+
children: /* @__PURE__ */ jsx12(IconGear, { size: 15 })
|
|
5782
6063
|
}
|
|
5783
6064
|
),
|
|
5784
|
-
settingsOpen && /* @__PURE__ */
|
|
5785
|
-
config.token && /* @__PURE__ */
|
|
6065
|
+
settingsOpen && /* @__PURE__ */ jsxs11("div", { className: "rk-menu", role: "menu", "aria-label": "Session settings", children: [
|
|
6066
|
+
config.token && /* @__PURE__ */ jsxs11(
|
|
5786
6067
|
"button",
|
|
5787
6068
|
{
|
|
5788
6069
|
type: "button",
|
|
@@ -5797,12 +6078,12 @@ function Panel() {
|
|
|
5797
6078
|
toast(dispatch, next ? "Review stays on in this tab" : "Review active only via the link", "info");
|
|
5798
6079
|
},
|
|
5799
6080
|
children: [
|
|
5800
|
-
/* @__PURE__ */
|
|
6081
|
+
/* @__PURE__ */ jsx12("span", { className: `rk-menu-check${sticky ? " rk-on" : ""}` }),
|
|
5801
6082
|
"Keep review on in this tab"
|
|
5802
6083
|
]
|
|
5803
6084
|
}
|
|
5804
6085
|
),
|
|
5805
|
-
config.emblema && /* @__PURE__ */
|
|
6086
|
+
config.emblema && /* @__PURE__ */ jsxs11(
|
|
5806
6087
|
"button",
|
|
5807
6088
|
{
|
|
5808
6089
|
type: "button",
|
|
@@ -5832,7 +6113,7 @@ function Panel() {
|
|
|
5832
6113
|
}).finally(() => setEmblemaSending(false));
|
|
5833
6114
|
},
|
|
5834
6115
|
children: [
|
|
5835
|
-
/* @__PURE__ */
|
|
6116
|
+
/* @__PURE__ */ jsx12(
|
|
5836
6117
|
"span",
|
|
5837
6118
|
{
|
|
5838
6119
|
className: "rk-emblema-dot",
|
|
@@ -5843,25 +6124,40 @@ function Panel() {
|
|
|
5843
6124
|
]
|
|
5844
6125
|
}
|
|
5845
6126
|
),
|
|
5846
|
-
/* @__PURE__ */
|
|
6127
|
+
/* @__PURE__ */ jsxs11(
|
|
5847
6128
|
"button",
|
|
5848
6129
|
{
|
|
5849
6130
|
type: "button",
|
|
5850
6131
|
role: "menuitem",
|
|
5851
6132
|
className: "rk-menu-item",
|
|
5852
|
-
title: emblemaPairState === "stale" ? "The local sync agent is not answering \u2014 run `npx @satanwagen/reviewkit-cli serve` in the project" : "Pair this project with the Emblema app via a sync key",
|
|
6133
|
+
title: emblemaPairState === "stale" ? "The local sync agent is not answering \u2014 run `npx -p @satanwagen/reviewkit-cli reviewkit-emblema serve` in the project" : "Pair this project with the Emblema app via a sync key",
|
|
5853
6134
|
onClick: () => {
|
|
5854
6135
|
setSettingsOpen(false);
|
|
5855
6136
|
dispatch({ type: "SET_EMBLEMA_CONNECT", open: true });
|
|
5856
6137
|
},
|
|
5857
6138
|
children: [
|
|
5858
|
-
/* @__PURE__ */
|
|
6139
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-emblema-dot", "data-state": emblemaPairState }),
|
|
5859
6140
|
"Connect to Emblema\u2026",
|
|
5860
|
-
/* @__PURE__ */
|
|
6141
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-menu-count", children: emblemaPairLabel })
|
|
5861
6142
|
]
|
|
5862
6143
|
}
|
|
5863
6144
|
),
|
|
5864
|
-
/* @__PURE__ */
|
|
6145
|
+
/* @__PURE__ */ jsx12(
|
|
6146
|
+
"button",
|
|
6147
|
+
{
|
|
6148
|
+
type: "button",
|
|
6149
|
+
role: "menuitem",
|
|
6150
|
+
className: "rk-menu-item",
|
|
6151
|
+
title: resolveSyncToken(config) ? "Pair the reviewkit terminal CLI / Claude Code MCP bridge with this site" : "Needs live sync (sync is off on this page) \u2014 the terminal reads the shared room",
|
|
6152
|
+
disabled: !resolveSyncToken(config),
|
|
6153
|
+
onClick: () => {
|
|
6154
|
+
setSettingsOpen(false);
|
|
6155
|
+
dispatch({ type: "SET_TERMINAL_CONNECT", open: true });
|
|
6156
|
+
},
|
|
6157
|
+
children: "Connect terminal / agent\u2026"
|
|
6158
|
+
}
|
|
6159
|
+
),
|
|
6160
|
+
/* @__PURE__ */ jsx12(
|
|
5865
6161
|
"button",
|
|
5866
6162
|
{
|
|
5867
6163
|
type: "button",
|
|
@@ -5874,31 +6170,31 @@ function Panel() {
|
|
|
5874
6170
|
)
|
|
5875
6171
|
] })
|
|
5876
6172
|
] }),
|
|
5877
|
-
/* @__PURE__ */
|
|
6173
|
+
/* @__PURE__ */ jsx12(
|
|
5878
6174
|
"button",
|
|
5879
6175
|
{
|
|
5880
6176
|
type: "button",
|
|
5881
6177
|
className: "rk-icon-btn",
|
|
5882
6178
|
"aria-label": "Keyboard shortcuts",
|
|
5883
6179
|
onClick: () => dispatch({ type: "SET_CHEATSHEET", open: true }),
|
|
5884
|
-
children: /* @__PURE__ */
|
|
6180
|
+
children: /* @__PURE__ */ jsx12(IconKeyboard, { size: 15 })
|
|
5885
6181
|
}
|
|
5886
6182
|
),
|
|
5887
|
-
/* @__PURE__ */
|
|
6183
|
+
/* @__PURE__ */ jsx12(
|
|
5888
6184
|
"button",
|
|
5889
6185
|
{
|
|
5890
6186
|
type: "button",
|
|
5891
6187
|
className: "rk-icon-btn",
|
|
5892
6188
|
"aria-label": "Close panel",
|
|
5893
6189
|
onClick: () => dispatch({ type: "SET_PANEL", open: false }),
|
|
5894
|
-
children: /* @__PURE__ */
|
|
6190
|
+
children: /* @__PURE__ */ jsx12(IconClose, { size: 14 })
|
|
5895
6191
|
}
|
|
5896
6192
|
)
|
|
5897
6193
|
] }),
|
|
5898
|
-
/* @__PURE__ */
|
|
5899
|
-
/* @__PURE__ */
|
|
5900
|
-
/* @__PURE__ */
|
|
5901
|
-
/* @__PURE__ */
|
|
6194
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-view-row", children: [
|
|
6195
|
+
/* @__PURE__ */ jsx12("div", { className: "rk-view-info", children: /* @__PURE__ */ jsx12("div", { className: "rk-view-title", children: "Page view" }) }),
|
|
6196
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-seg rk-view-toggle", role: "group", "aria-label": "Page view (P to toggle)", children: [
|
|
6197
|
+
/* @__PURE__ */ jsx12(
|
|
5902
6198
|
"button",
|
|
5903
6199
|
{
|
|
5904
6200
|
type: "button",
|
|
@@ -5908,7 +6204,7 @@ function Panel() {
|
|
|
5908
6204
|
children: "Original"
|
|
5909
6205
|
}
|
|
5910
6206
|
),
|
|
5911
|
-
/* @__PURE__ */
|
|
6207
|
+
/* @__PURE__ */ jsx12(
|
|
5912
6208
|
"button",
|
|
5913
6209
|
{
|
|
5914
6210
|
type: "button",
|
|
@@ -5920,8 +6216,8 @@ function Panel() {
|
|
|
5920
6216
|
)
|
|
5921
6217
|
] })
|
|
5922
6218
|
] }),
|
|
5923
|
-
/* @__PURE__ */
|
|
5924
|
-
/* @__PURE__ */
|
|
6219
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-panel-tools", children: [
|
|
6220
|
+
/* @__PURE__ */ jsxs11(
|
|
5925
6221
|
"button",
|
|
5926
6222
|
{
|
|
5927
6223
|
type: "button",
|
|
@@ -5932,15 +6228,15 @@ function Panel() {
|
|
|
5932
6228
|
dispatch({ type: "SET_MODE", mode: "pick" });
|
|
5933
6229
|
},
|
|
5934
6230
|
children: [
|
|
5935
|
-
/* @__PURE__ */
|
|
6231
|
+
/* @__PURE__ */ jsx12(IconTarget, { size: 14 }),
|
|
5936
6232
|
" Pick an element"
|
|
5937
6233
|
]
|
|
5938
6234
|
}
|
|
5939
6235
|
),
|
|
5940
|
-
/* @__PURE__ */
|
|
5941
|
-
/* @__PURE__ */
|
|
5942
|
-
/* @__PURE__ */
|
|
5943
|
-
/* @__PURE__ */
|
|
6236
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-search-row", children: [
|
|
6237
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-search", children: [
|
|
6238
|
+
/* @__PURE__ */ jsx12(IconSearch, { size: 13 }),
|
|
6239
|
+
/* @__PURE__ */ jsx12(
|
|
5944
6240
|
"input",
|
|
5945
6241
|
{
|
|
5946
6242
|
ref: searchRef,
|
|
@@ -5952,8 +6248,8 @@ function Panel() {
|
|
|
5952
6248
|
}
|
|
5953
6249
|
)
|
|
5954
6250
|
] }),
|
|
5955
|
-
/* @__PURE__ */
|
|
5956
|
-
/* @__PURE__ */
|
|
6251
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-menu-scope rk-menu-anchor", children: [
|
|
6252
|
+
/* @__PURE__ */ jsxs11(
|
|
5957
6253
|
"button",
|
|
5958
6254
|
{
|
|
5959
6255
|
type: "button",
|
|
@@ -5965,15 +6261,15 @@ function Panel() {
|
|
|
5965
6261
|
setSettingsOpen(false);
|
|
5966
6262
|
},
|
|
5967
6263
|
children: [
|
|
5968
|
-
/* @__PURE__ */
|
|
6264
|
+
/* @__PURE__ */ jsx12(IconFilter, { size: 13 }),
|
|
5969
6265
|
"Filter",
|
|
5970
|
-
typeFilter.size + prioFilter.size + statusFilter.size > 0 && /* @__PURE__ */
|
|
6266
|
+
typeFilter.size + prioFilter.size + statusFilter.size > 0 && /* @__PURE__ */ jsx12("span", { className: "rk-badge-count", children: typeFilter.size + prioFilter.size + statusFilter.size })
|
|
5971
6267
|
]
|
|
5972
6268
|
}
|
|
5973
6269
|
),
|
|
5974
|
-
filterOpen && /* @__PURE__ */
|
|
5975
|
-
/* @__PURE__ */
|
|
5976
|
-
TYPE_FILTERS.map((type) => /* @__PURE__ */
|
|
6270
|
+
filterOpen && /* @__PURE__ */ jsxs11("div", { className: "rk-menu", role: "menu", "aria-label": "Filter items", children: [
|
|
6271
|
+
/* @__PURE__ */ jsx12("div", { className: "rk-menu-title", children: "Type" }),
|
|
6272
|
+
TYPE_FILTERS.map((type) => /* @__PURE__ */ jsxs11(
|
|
5977
6273
|
"button",
|
|
5978
6274
|
{
|
|
5979
6275
|
type: "button",
|
|
@@ -5987,16 +6283,16 @@ function Panel() {
|
|
|
5987
6283
|
setTypeFilter(next);
|
|
5988
6284
|
},
|
|
5989
6285
|
children: [
|
|
5990
|
-
/* @__PURE__ */
|
|
6286
|
+
/* @__PURE__ */ jsx12("span", { className: `rk-menu-check${typeFilter.has(type) ? " rk-on" : ""}` }),
|
|
5991
6287
|
iconForType(type, 12),
|
|
5992
|
-
/* @__PURE__ */
|
|
5993
|
-
/* @__PURE__ */
|
|
6288
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-menu-label", children: type }),
|
|
6289
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-menu-count", children: typeCounts.get(type) ?? 0 })
|
|
5994
6290
|
]
|
|
5995
6291
|
},
|
|
5996
6292
|
type
|
|
5997
6293
|
)),
|
|
5998
|
-
/* @__PURE__ */
|
|
5999
|
-
PRIORITY_FILTERS.map((priority) => /* @__PURE__ */
|
|
6294
|
+
/* @__PURE__ */ jsx12("div", { className: "rk-menu-title", children: "Priority" }),
|
|
6295
|
+
PRIORITY_FILTERS.map((priority) => /* @__PURE__ */ jsxs11(
|
|
6000
6296
|
"button",
|
|
6001
6297
|
{
|
|
6002
6298
|
type: "button",
|
|
@@ -6010,15 +6306,15 @@ function Panel() {
|
|
|
6010
6306
|
setPrioFilter(next);
|
|
6011
6307
|
},
|
|
6012
6308
|
children: [
|
|
6013
|
-
/* @__PURE__ */
|
|
6014
|
-
/* @__PURE__ */
|
|
6015
|
-
/* @__PURE__ */
|
|
6309
|
+
/* @__PURE__ */ jsx12("span", { className: `rk-menu-check${prioFilter.has(priority) ? " rk-on" : ""}` }),
|
|
6310
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-menu-label", children: PRIORITY_LABELS[priority] }),
|
|
6311
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-menu-count", children: prioCounts.get(priority) ?? 0 })
|
|
6016
6312
|
]
|
|
6017
6313
|
},
|
|
6018
6314
|
priority
|
|
6019
6315
|
)),
|
|
6020
|
-
/* @__PURE__ */
|
|
6021
|
-
STATUSES.map((status) => /* @__PURE__ */
|
|
6316
|
+
/* @__PURE__ */ jsx12("div", { className: "rk-menu-title", children: "Status" }),
|
|
6317
|
+
STATUSES.map((status) => /* @__PURE__ */ jsxs11(
|
|
6022
6318
|
"button",
|
|
6023
6319
|
{
|
|
6024
6320
|
type: "button",
|
|
@@ -6032,15 +6328,15 @@ function Panel() {
|
|
|
6032
6328
|
setStatusFilter(next);
|
|
6033
6329
|
},
|
|
6034
6330
|
children: [
|
|
6035
|
-
/* @__PURE__ */
|
|
6036
|
-
/* @__PURE__ */
|
|
6037
|
-
/* @__PURE__ */
|
|
6038
|
-
/* @__PURE__ */
|
|
6331
|
+
/* @__PURE__ */ jsx12("span", { className: `rk-menu-check${statusFilter.has(status) ? " rk-on" : ""}` }),
|
|
6332
|
+
/* @__PURE__ */ jsx12("span", { className: `rk-status-dot rk-st-${status}` }),
|
|
6333
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-menu-label", children: status }),
|
|
6334
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-menu-count", children: statusCounts.get(status) ?? 0 })
|
|
6039
6335
|
]
|
|
6040
6336
|
},
|
|
6041
6337
|
status
|
|
6042
6338
|
)),
|
|
6043
|
-
/* @__PURE__ */
|
|
6339
|
+
/* @__PURE__ */ jsx12(
|
|
6044
6340
|
"button",
|
|
6045
6341
|
{
|
|
6046
6342
|
type: "button",
|
|
@@ -6060,24 +6356,24 @@ function Panel() {
|
|
|
6060
6356
|
] })
|
|
6061
6357
|
] })
|
|
6062
6358
|
] }),
|
|
6063
|
-
preview && unapplied > 0 && /* @__PURE__ */
|
|
6359
|
+
preview && unapplied > 0 && /* @__PURE__ */ jsxs11("div", { className: "rk-unplaced", role: "status", children: [
|
|
6064
6360
|
unapplied,
|
|
6065
6361
|
" saved change",
|
|
6066
6362
|
unapplied === 1 ? "" : "s",
|
|
6067
6363
|
" couldn\u2019t be placed on the current page \u2014 the page has changed since they were captured."
|
|
6068
6364
|
] }),
|
|
6069
|
-
/* @__PURE__ */
|
|
6070
|
-
/* @__PURE__ */
|
|
6071
|
-
/* @__PURE__ */
|
|
6072
|
-
/* @__PURE__ */
|
|
6073
|
-
] }) : groups.map(([route, entries]) => /* @__PURE__ */
|
|
6074
|
-
/* @__PURE__ */
|
|
6365
|
+
/* @__PURE__ */ jsx12("div", { className: "rk-panel-list", children: filtered.length === 0 ? /* @__PURE__ */ jsxs11("div", { className: "rk-empty", children: [
|
|
6366
|
+
/* @__PURE__ */ jsx12("div", { className: "rk-empty-art", children: /* @__PURE__ */ jsx12(IconTarget, { size: 22 }) }),
|
|
6367
|
+
/* @__PURE__ */ jsx12("div", { className: "rk-empty-title", children: items.length === 0 ? "Nothing here yet" : "No matches" }),
|
|
6368
|
+
/* @__PURE__ */ jsx12("div", { className: "rk-empty-text", children: items.length === 0 ? "Choose \u201CPick an element\u201D, then click anything on the page. Your suggestions collect here, ready to hand off." : "Try a different search, or clear the filters." })
|
|
6369
|
+
] }) : groups.map(([route, entries]) => /* @__PURE__ */ jsxs11("div", { children: [
|
|
6370
|
+
/* @__PURE__ */ jsx12("div", { className: "rk-group-title", children: route }),
|
|
6075
6371
|
entries.map(({ item, number }) => {
|
|
6076
6372
|
const active = item.id === activeItemId;
|
|
6077
6373
|
const orphan = orphanIds.has(item.id);
|
|
6078
6374
|
const hiddenEl = hiddenIds.has(item.id);
|
|
6079
|
-
return /* @__PURE__ */
|
|
6080
|
-
/* @__PURE__ */
|
|
6375
|
+
return /* @__PURE__ */ jsxs11("div", { children: [
|
|
6376
|
+
/* @__PURE__ */ jsxs11(
|
|
6081
6377
|
"div",
|
|
6082
6378
|
{
|
|
6083
6379
|
"data-item-id": item.id,
|
|
@@ -6092,18 +6388,18 @@ function Panel() {
|
|
|
6092
6388
|
}
|
|
6093
6389
|
},
|
|
6094
6390
|
children: [
|
|
6095
|
-
/* @__PURE__ */
|
|
6096
|
-
/* @__PURE__ */
|
|
6097
|
-
/* @__PURE__ */
|
|
6098
|
-
/* @__PURE__ */
|
|
6391
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-item-num", children: number }),
|
|
6392
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-item-icon", children: iconForType(item.type) }),
|
|
6393
|
+
/* @__PURE__ */ jsxs11("span", { className: "rk-item-body", children: [
|
|
6394
|
+
/* @__PURE__ */ jsxs11("span", { className: "rk-item-snippet", children: [
|
|
6099
6395
|
item.target.tagName,
|
|
6100
6396
|
" \xB7 ",
|
|
6101
6397
|
item.target.textSnippet || item.target.selector
|
|
6102
6398
|
] }),
|
|
6103
|
-
/* @__PURE__ */
|
|
6104
|
-
/* @__PURE__ */
|
|
6105
|
-
/* @__PURE__ */
|
|
6106
|
-
/* @__PURE__ */
|
|
6399
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-item-change", children: changeSummary(item) }),
|
|
6400
|
+
/* @__PURE__ */ jsxs11("span", { className: "rk-item-meta", children: [
|
|
6401
|
+
/* @__PURE__ */ jsxs11("span", { className: "rk-author", title: new Date(item.createdAt).toLocaleString(), children: [
|
|
6402
|
+
/* @__PURE__ */ jsx12(
|
|
6107
6403
|
"span",
|
|
6108
6404
|
{
|
|
6109
6405
|
className: "rk-author-dot",
|
|
@@ -6111,15 +6407,15 @@ function Panel() {
|
|
|
6111
6407
|
}
|
|
6112
6408
|
),
|
|
6113
6409
|
item.author?.name ?? "Unknown",
|
|
6114
|
-
/* @__PURE__ */
|
|
6410
|
+
/* @__PURE__ */ jsxs11("span", { className: "rk-time", children: [
|
|
6115
6411
|
" \xB7 ",
|
|
6116
6412
|
timeAgo(item.createdAt)
|
|
6117
6413
|
] })
|
|
6118
6414
|
] }),
|
|
6119
|
-
item.priority === "must" && /* @__PURE__ */
|
|
6120
|
-
item.status !== "open" && /* @__PURE__ */
|
|
6121
|
-
orphan && /* @__PURE__ */
|
|
6122
|
-
hiddenEl && /* @__PURE__ */
|
|
6415
|
+
item.priority === "must" && /* @__PURE__ */ jsx12("span", { className: "rk-badge-mini rk-must", children: "must" }),
|
|
6416
|
+
item.status !== "open" && /* @__PURE__ */ jsx12("span", { className: `rk-badge-mini rk-${item.status}`, children: item.status }),
|
|
6417
|
+
orphan && /* @__PURE__ */ jsx12("span", { className: "rk-badge-mini rk-orphaned", children: "unanchored" }),
|
|
6418
|
+
hiddenEl && /* @__PURE__ */ jsx12(
|
|
6123
6419
|
"span",
|
|
6124
6420
|
{
|
|
6125
6421
|
className: "rk-badge-mini rk-hidden-el",
|
|
@@ -6127,14 +6423,14 @@ function Panel() {
|
|
|
6127
6423
|
children: "hidden"
|
|
6128
6424
|
}
|
|
6129
6425
|
),
|
|
6130
|
-
item.note && /* @__PURE__ */
|
|
6131
|
-
peers.filter((peer) => peer.typingActive && peer.typingItemId === item.id).map((peer) => /* @__PURE__ */
|
|
6426
|
+
item.note && /* @__PURE__ */ jsx12("span", { className: "rk-badge-mini", children: "note" }),
|
|
6427
|
+
peers.filter((peer) => peer.typingActive && peer.typingItemId === item.id).map((peer) => /* @__PURE__ */ jsxs11("span", { className: "rk-badge-mini", style: { color: peer.color }, children: [
|
|
6132
6428
|
peer.name || "peer",
|
|
6133
6429
|
" is writing\u2026"
|
|
6134
6430
|
] }, peer.id))
|
|
6135
6431
|
] })
|
|
6136
6432
|
] }),
|
|
6137
|
-
/* @__PURE__ */
|
|
6433
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-item-actions", children: /* @__PURE__ */ jsx12(
|
|
6138
6434
|
"button",
|
|
6139
6435
|
{
|
|
6140
6436
|
type: "button",
|
|
@@ -6149,15 +6445,15 @@ function Panel() {
|
|
|
6149
6445
|
"info"
|
|
6150
6446
|
);
|
|
6151
6447
|
},
|
|
6152
|
-
children: /* @__PURE__ */
|
|
6448
|
+
children: /* @__PURE__ */ jsx12(IconTrash, { size: 13 })
|
|
6153
6449
|
}
|
|
6154
6450
|
) })
|
|
6155
6451
|
]
|
|
6156
6452
|
}
|
|
6157
6453
|
),
|
|
6158
|
-
active && /* @__PURE__ */
|
|
6159
|
-
/* @__PURE__ */
|
|
6160
|
-
/* @__PURE__ */
|
|
6454
|
+
active && /* @__PURE__ */ jsxs11("div", { className: "rk-item-edit", children: [
|
|
6455
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-detail-byline", title: new Date(item.createdAt).toLocaleString(), children: [
|
|
6456
|
+
/* @__PURE__ */ jsx12(
|
|
6161
6457
|
"span",
|
|
6162
6458
|
{
|
|
6163
6459
|
className: "rk-author-dot",
|
|
@@ -6168,8 +6464,8 @@ function Panel() {
|
|
|
6168
6464
|
" \xB7 ",
|
|
6169
6465
|
timeAgo(item.createdAt)
|
|
6170
6466
|
] }),
|
|
6171
|
-
isCopyItem(item) && /* @__PURE__ */
|
|
6172
|
-
isImageItem(item) && /* @__PURE__ */
|
|
6467
|
+
isCopyItem(item) && /* @__PURE__ */ jsx12(CopyDiff, { before: item.payload.before, after: item.payload.after }),
|
|
6468
|
+
isImageItem(item) && /* @__PURE__ */ jsx12(
|
|
6173
6469
|
ImageDetail,
|
|
6174
6470
|
{
|
|
6175
6471
|
beforeSrc: item.payload.beforeSrc,
|
|
@@ -6177,7 +6473,7 @@ function Panel() {
|
|
|
6177
6473
|
afterDataUrl: item.payload.afterDataUrl
|
|
6178
6474
|
}
|
|
6179
6475
|
),
|
|
6180
|
-
isKnownItemType(item.type) && item.type !== "move" && /* @__PURE__ */
|
|
6476
|
+
isKnownItemType(item.type) && item.type !== "move" && /* @__PURE__ */ jsx12(
|
|
6181
6477
|
"textarea",
|
|
6182
6478
|
{
|
|
6183
6479
|
className: "rk-textarea",
|
|
@@ -6187,7 +6483,7 @@ function Panel() {
|
|
|
6187
6483
|
onChange: (event) => dispatch({ type: "UPDATE_ITEM", id: item.id, patch: withPayloadText(item, event.target.value) })
|
|
6188
6484
|
}
|
|
6189
6485
|
),
|
|
6190
|
-
/* @__PURE__ */
|
|
6486
|
+
/* @__PURE__ */ jsx12(
|
|
6191
6487
|
"input",
|
|
6192
6488
|
{
|
|
6193
6489
|
className: "rk-input",
|
|
@@ -6197,9 +6493,9 @@ function Panel() {
|
|
|
6197
6493
|
onChange: (event) => dispatch({ type: "UPDATE_ITEM", id: item.id, patch: { note: event.target.value } })
|
|
6198
6494
|
}
|
|
6199
6495
|
),
|
|
6200
|
-
/* @__PURE__ */
|
|
6201
|
-
/* @__PURE__ */
|
|
6202
|
-
/* @__PURE__ */
|
|
6496
|
+
/* @__PURE__ */ jsxs11("div", { style: { display: "flex", gap: 8, flexWrap: "wrap" }, children: [
|
|
6497
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-seg", role: "group", "aria-label": "Priority", children: [
|
|
6498
|
+
/* @__PURE__ */ jsx12(
|
|
6203
6499
|
"button",
|
|
6204
6500
|
{
|
|
6205
6501
|
type: "button",
|
|
@@ -6208,7 +6504,7 @@ function Panel() {
|
|
|
6208
6504
|
children: "Must"
|
|
6209
6505
|
}
|
|
6210
6506
|
),
|
|
6211
|
-
/* @__PURE__ */
|
|
6507
|
+
/* @__PURE__ */ jsx12(
|
|
6212
6508
|
"button",
|
|
6213
6509
|
{
|
|
6214
6510
|
type: "button",
|
|
@@ -6218,7 +6514,7 @@ function Panel() {
|
|
|
6218
6514
|
}
|
|
6219
6515
|
)
|
|
6220
6516
|
] }),
|
|
6221
|
-
/* @__PURE__ */
|
|
6517
|
+
/* @__PURE__ */ jsx12("div", { className: "rk-seg", role: "group", "aria-label": "Status", children: STATUSES.map((status) => /* @__PURE__ */ jsx12(
|
|
6222
6518
|
"button",
|
|
6223
6519
|
{
|
|
6224
6520
|
type: "button",
|
|
@@ -6233,22 +6529,22 @@ function Panel() {
|
|
|
6233
6529
|
] }, item.id);
|
|
6234
6530
|
})
|
|
6235
6531
|
] }, route)) }),
|
|
6236
|
-
/* @__PURE__ */
|
|
6237
|
-
/* @__PURE__ */
|
|
6238
|
-
/* @__PURE__ */
|
|
6532
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-panel-foot", children: [
|
|
6533
|
+
/* @__PURE__ */ jsxs11("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: onExport, disabled: items.length === 0, children: [
|
|
6534
|
+
/* @__PURE__ */ jsx12(IconDownload, { size: 13 }),
|
|
6239
6535
|
" Export"
|
|
6240
6536
|
] }),
|
|
6241
|
-
/* @__PURE__ */
|
|
6242
|
-
/* @__PURE__ */
|
|
6537
|
+
/* @__PURE__ */ jsxs11("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => void onCopy(), disabled: items.length === 0, children: [
|
|
6538
|
+
/* @__PURE__ */ jsx12(IconCopyClipboard, { size: 13 }),
|
|
6243
6539
|
" Copy"
|
|
6244
6540
|
] }),
|
|
6245
|
-
/* @__PURE__ */
|
|
6246
|
-
/* @__PURE__ */
|
|
6541
|
+
/* @__PURE__ */ jsxs11("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => importRef.current?.click(), children: [
|
|
6542
|
+
/* @__PURE__ */ jsx12(IconUpload, { size: 13 }),
|
|
6247
6543
|
" Import"
|
|
6248
6544
|
] }),
|
|
6249
|
-
/* @__PURE__ */
|
|
6250
|
-
undoStack.length > 0 && /* @__PURE__ */
|
|
6251
|
-
/* @__PURE__ */
|
|
6545
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-spacer" }),
|
|
6546
|
+
undoStack.length > 0 && /* @__PURE__ */ jsx12("button", { type: "button", className: "rk-icon-btn", "aria-label": "Undo last change (\u2318Z)", onClick: () => dispatch({ type: "UNDO" }), children: /* @__PURE__ */ jsx12(IconUndo, { size: 14 }) }),
|
|
6547
|
+
/* @__PURE__ */ jsx12(
|
|
6252
6548
|
"button",
|
|
6253
6549
|
{
|
|
6254
6550
|
type: "button",
|
|
@@ -6259,7 +6555,7 @@ function Panel() {
|
|
|
6259
6555
|
children: "Clear"
|
|
6260
6556
|
}
|
|
6261
6557
|
),
|
|
6262
|
-
/* @__PURE__ */
|
|
6558
|
+
/* @__PURE__ */ jsx12(
|
|
6263
6559
|
"button",
|
|
6264
6560
|
{
|
|
6265
6561
|
type: "button",
|
|
@@ -6269,7 +6565,7 @@ function Panel() {
|
|
|
6269
6565
|
children: "Exit review"
|
|
6270
6566
|
}
|
|
6271
6567
|
),
|
|
6272
|
-
/* @__PURE__ */
|
|
6568
|
+
/* @__PURE__ */ jsx12(
|
|
6273
6569
|
"input",
|
|
6274
6570
|
{
|
|
6275
6571
|
ref: importRef,
|
|
@@ -6290,8 +6586,8 @@ function Panel() {
|
|
|
6290
6586
|
}
|
|
6291
6587
|
|
|
6292
6588
|
// src/client/components/Presence.tsx
|
|
6293
|
-
import { useEffect as
|
|
6294
|
-
import { Fragment as
|
|
6589
|
+
import { useEffect as useEffect11, useRef as useRef11 } from "react";
|
|
6590
|
+
import { Fragment as Fragment7, jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
6295
6591
|
function initials(name) {
|
|
6296
6592
|
const parts = name.trim().split(/\s+/).filter(Boolean);
|
|
6297
6593
|
if (parts.length === 0) return "\xB7";
|
|
@@ -6301,8 +6597,8 @@ function initials(name) {
|
|
|
6301
6597
|
function PresenceStrip() {
|
|
6302
6598
|
const { peers, syncStatus } = useStore();
|
|
6303
6599
|
if (syncStatus === "disabled" || peers.length === 0) return null;
|
|
6304
|
-
return /* @__PURE__ */
|
|
6305
|
-
peers.slice(0, 5).map((peer) => /* @__PURE__ */
|
|
6600
|
+
return /* @__PURE__ */ jsxs12("div", { className: "rk-presence", "aria-label": `${peers.length} reviewer${peers.length === 1 ? "" : "s"} online`, children: [
|
|
6601
|
+
peers.slice(0, 5).map((peer) => /* @__PURE__ */ jsx13(
|
|
6306
6602
|
"span",
|
|
6307
6603
|
{
|
|
6308
6604
|
className: "rk-avatar",
|
|
@@ -6312,7 +6608,7 @@ function PresenceStrip() {
|
|
|
6312
6608
|
},
|
|
6313
6609
|
peer.id
|
|
6314
6610
|
)),
|
|
6315
|
-
peers.length > 5 && /* @__PURE__ */
|
|
6611
|
+
peers.length > 5 && /* @__PURE__ */ jsxs12("span", { className: "rk-avatar rk-avatar-more", children: [
|
|
6316
6612
|
"+",
|
|
6317
6613
|
peers.length - 5
|
|
6318
6614
|
] })
|
|
@@ -6336,7 +6632,7 @@ function PeerCursors() {
|
|
|
6336
6632
|
}
|
|
6337
6633
|
}
|
|
6338
6634
|
peersRef.current = peers;
|
|
6339
|
-
|
|
6635
|
+
useEffect11(() => {
|
|
6340
6636
|
const reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
6341
6637
|
let raf = 0;
|
|
6342
6638
|
let last = performance.now();
|
|
@@ -6441,8 +6737,8 @@ function PeerCursors() {
|
|
|
6441
6737
|
return () => cancelAnimationFrame(raf);
|
|
6442
6738
|
}, []);
|
|
6443
6739
|
if (peers.length === 0) return null;
|
|
6444
|
-
return /* @__PURE__ */
|
|
6445
|
-
peers.map((peer) => /* @__PURE__ */
|
|
6740
|
+
return /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
6741
|
+
peers.map((peer) => /* @__PURE__ */ jsx13(
|
|
6446
6742
|
"div",
|
|
6447
6743
|
{
|
|
6448
6744
|
ref: (el) => {
|
|
@@ -6454,7 +6750,7 @@ function PeerCursors() {
|
|
|
6454
6750
|
},
|
|
6455
6751
|
`ring-${peer.id}`
|
|
6456
6752
|
)),
|
|
6457
|
-
peers.map((peer, index) => /* @__PURE__ */
|
|
6753
|
+
peers.map((peer, index) => /* @__PURE__ */ jsxs12(
|
|
6458
6754
|
"div",
|
|
6459
6755
|
{
|
|
6460
6756
|
ref: (el) => {
|
|
@@ -6464,8 +6760,8 @@ function PeerCursors() {
|
|
|
6464
6760
|
className: "rk-peer-cursor",
|
|
6465
6761
|
style: { opacity: 0 },
|
|
6466
6762
|
children: [
|
|
6467
|
-
/* @__PURE__ */
|
|
6468
|
-
/* @__PURE__ */
|
|
6763
|
+
/* @__PURE__ */ jsx13("svg", { width: "14", height: "18", viewBox: "0 0 14 18", "aria-hidden": "true", children: /* @__PURE__ */ jsx13("path", { d: "M1 1l12 7.5-5.2 1.2L5 16z", fill: peer.color, stroke: "rgba(0,0,0,0.25)", strokeWidth: "1" }) }),
|
|
6764
|
+
/* @__PURE__ */ jsxs12(
|
|
6469
6765
|
"span",
|
|
6470
6766
|
{
|
|
6471
6767
|
className: "rk-peer-name",
|
|
@@ -6484,19 +6780,19 @@ function PeerCursors() {
|
|
|
6484
6780
|
}
|
|
6485
6781
|
|
|
6486
6782
|
// src/client/components/QuickComment.tsx
|
|
6487
|
-
import { useEffect as
|
|
6488
|
-
import { jsx as
|
|
6783
|
+
import { useEffect as useEffect12, useRef as useRef12, useState as useState10 } from "react";
|
|
6784
|
+
import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
6489
6785
|
function QuickComment() {
|
|
6490
6786
|
const { quick } = useStore();
|
|
6491
6787
|
if (!quick) return null;
|
|
6492
|
-
return /* @__PURE__ */
|
|
6788
|
+
return /* @__PURE__ */ jsx14(QuickComposerCard, { quick }, quick.id);
|
|
6493
6789
|
}
|
|
6494
6790
|
function QuickComposerCard({ quick }) {
|
|
6495
6791
|
const { route, session } = useStore();
|
|
6496
6792
|
const dispatch = useDispatch();
|
|
6497
|
-
const [text, setText] =
|
|
6793
|
+
const [text, setText] = useState10("");
|
|
6498
6794
|
const fieldRef = useRef12(null);
|
|
6499
|
-
|
|
6795
|
+
useEffect12(() => {
|
|
6500
6796
|
const field = fieldRef.current;
|
|
6501
6797
|
if (!field) return;
|
|
6502
6798
|
field.focus();
|
|
@@ -6549,18 +6845,18 @@ function QuickComposerCard({ quick }) {
|
|
|
6549
6845
|
};
|
|
6550
6846
|
const x = Math.min(Math.max(quick.x, 8), window.innerWidth - 288);
|
|
6551
6847
|
const y = Math.min(Math.max(quick.y + 12, 8), window.innerHeight - 108);
|
|
6552
|
-
return /* @__PURE__ */
|
|
6553
|
-
/* @__PURE__ */
|
|
6554
|
-
/* @__PURE__ */
|
|
6555
|
-
/* @__PURE__ */
|
|
6556
|
-
/* @__PURE__ */
|
|
6557
|
-
/* @__PURE__ */
|
|
6848
|
+
return /* @__PURE__ */ jsxs13("div", { className: "rk-quick", style: { transform: `translate3d(${x}px, ${y}px, 0)` }, role: "dialog", "aria-label": "Quick comment", children: [
|
|
6849
|
+
/* @__PURE__ */ jsxs13("div", { className: "rk-quick-head", children: [
|
|
6850
|
+
/* @__PURE__ */ jsx14(IconComment, { size: 12 }),
|
|
6851
|
+
/* @__PURE__ */ jsx14("span", { children: "Comment here" }),
|
|
6852
|
+
/* @__PURE__ */ jsxs13("span", { className: "rk-hint", children: [
|
|
6853
|
+
/* @__PURE__ */ jsx14("span", { className: "rk-kbd", children: "\u21B5" }),
|
|
6558
6854
|
" save \xB7 ",
|
|
6559
|
-
/* @__PURE__ */
|
|
6855
|
+
/* @__PURE__ */ jsx14("span", { className: "rk-kbd", children: "esc" }),
|
|
6560
6856
|
" cancel"
|
|
6561
6857
|
] })
|
|
6562
6858
|
] }),
|
|
6563
|
-
/* @__PURE__ */
|
|
6859
|
+
/* @__PURE__ */ jsx14(
|
|
6564
6860
|
"textarea",
|
|
6565
6861
|
{
|
|
6566
6862
|
ref: fieldRef,
|
|
@@ -6576,8 +6872,8 @@ function QuickComposerCard({ quick }) {
|
|
|
6576
6872
|
}
|
|
6577
6873
|
|
|
6578
6874
|
// src/client/components/PickLayer.tsx
|
|
6579
|
-
import { useEffect as
|
|
6580
|
-
import { Fragment as
|
|
6875
|
+
import { useEffect as useEffect13, useRef as useRef13, useState as useState11 } from "react";
|
|
6876
|
+
import { Fragment as Fragment8, jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
6581
6877
|
function applyRect(el, rect, pad2 = 3) {
|
|
6582
6878
|
if (!el) return;
|
|
6583
6879
|
if (!rect) {
|
|
@@ -6592,14 +6888,14 @@ function applyRect(el, rect, pad2 = 3) {
|
|
|
6592
6888
|
function PickLayer() {
|
|
6593
6889
|
const { mode, selection, tool } = useStore();
|
|
6594
6890
|
const dispatch = useDispatch();
|
|
6595
|
-
const [hovered, setHovered] =
|
|
6891
|
+
const [hovered, setHovered] = useState11(null);
|
|
6596
6892
|
const outlineRef = useRef13(null);
|
|
6597
6893
|
const labelRef = useRef13(null);
|
|
6598
6894
|
const selectRef = useRef13(null);
|
|
6599
6895
|
const hoveredRef = useRef13(null);
|
|
6600
6896
|
hoveredRef.current = hovered;
|
|
6601
6897
|
const picking = mode === "pick";
|
|
6602
|
-
|
|
6898
|
+
useEffect13(() => {
|
|
6603
6899
|
if (!picking) {
|
|
6604
6900
|
setHovered(null);
|
|
6605
6901
|
return;
|
|
@@ -6643,7 +6939,7 @@ function PickLayer() {
|
|
|
6643
6939
|
document.removeEventListener("mousedown", swallow, true);
|
|
6644
6940
|
};
|
|
6645
6941
|
}, [picking, tool, dispatch]);
|
|
6646
|
-
|
|
6942
|
+
useEffect13(() => {
|
|
6647
6943
|
if (!picking) return;
|
|
6648
6944
|
const body = document.body;
|
|
6649
6945
|
const prev = body.style.cursor;
|
|
@@ -6653,7 +6949,7 @@ function PickLayer() {
|
|
|
6653
6949
|
if (body.getAttribute("style") === "") body.removeAttribute("style");
|
|
6654
6950
|
};
|
|
6655
6951
|
}, [picking, tool]);
|
|
6656
|
-
|
|
6952
|
+
useEffect13(() => {
|
|
6657
6953
|
let raf = 0;
|
|
6658
6954
|
const tick = () => {
|
|
6659
6955
|
const hoverEl = hoveredRef.current;
|
|
@@ -6679,21 +6975,21 @@ function PickLayer() {
|
|
|
6679
6975
|
raf = requestAnimationFrame(tick);
|
|
6680
6976
|
return () => cancelAnimationFrame(raf);
|
|
6681
6977
|
}, [picking, selection]);
|
|
6682
|
-
return /* @__PURE__ */
|
|
6683
|
-
picking && /* @__PURE__ */
|
|
6684
|
-
/* @__PURE__ */
|
|
6685
|
-
/* @__PURE__ */
|
|
6686
|
-
/* @__PURE__ */
|
|
6687
|
-
/* @__PURE__ */
|
|
6688
|
-
] }) : /* @__PURE__ */
|
|
6978
|
+
return /* @__PURE__ */ jsxs14(Fragment8, { children: [
|
|
6979
|
+
picking && /* @__PURE__ */ jsxs14(Fragment8, { children: [
|
|
6980
|
+
/* @__PURE__ */ jsx15("div", { ref: outlineRef, className: "rk-outline", style: { opacity: 0 } }),
|
|
6981
|
+
/* @__PURE__ */ jsx15("div", { ref: labelRef, className: "rk-outline-label", style: { opacity: 0 }, children: hovered ? /* @__PURE__ */ jsxs14(Fragment8, { children: [
|
|
6982
|
+
/* @__PURE__ */ jsx15("span", { className: "rk-tag", children: hovered.tagName.toLowerCase() }),
|
|
6983
|
+
/* @__PURE__ */ jsx15("span", { children: describeElement(hovered).replace(/^[a-z0-9]+ · /, "") })
|
|
6984
|
+
] }) : /* @__PURE__ */ jsx15("span", { children: "Pick an element" }) })
|
|
6689
6985
|
] }),
|
|
6690
|
-
selection && /* @__PURE__ */
|
|
6986
|
+
selection && /* @__PURE__ */ jsx15("div", { ref: selectRef, className: "rk-select-ring", style: { opacity: 0 } })
|
|
6691
6987
|
] });
|
|
6692
6988
|
}
|
|
6693
6989
|
|
|
6694
6990
|
// src/client/components/Pins.tsx
|
|
6695
|
-
import { useEffect as
|
|
6696
|
-
import { Fragment as
|
|
6991
|
+
import { useEffect as useEffect14, useMemo as useMemo4, useRef as useRef14, useState as useState12 } from "react";
|
|
6992
|
+
import { Fragment as Fragment9, jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
6697
6993
|
var STATUS_LABELS = {
|
|
6698
6994
|
open: "open",
|
|
6699
6995
|
accepted: "accepted",
|
|
@@ -6705,22 +7001,22 @@ var RERESOLVE_MS = 800;
|
|
|
6705
7001
|
function Pins() {
|
|
6706
7002
|
const { session, route, activeItemId, editor, mode, filter } = useStore();
|
|
6707
7003
|
const dispatch = useDispatch();
|
|
6708
|
-
const [clusters, setClusters] =
|
|
6709
|
-
const [orphanCount, setOrphanCount] =
|
|
7004
|
+
const [clusters, setClusters] = useState12([]);
|
|
7005
|
+
const [orphanCount, setOrphanCount] = useState12(0);
|
|
6710
7006
|
const wrapRefs = useRef14(/* @__PURE__ */ new Map());
|
|
6711
7007
|
const visibleCache = useRef14(/* @__PURE__ */ new Map());
|
|
6712
7008
|
const highlightRef = useRef14(null);
|
|
6713
7009
|
const hoveredItems = useRef14(null);
|
|
6714
7010
|
const elementCache = useRef14(/* @__PURE__ */ new Map());
|
|
6715
7011
|
const lastResolve = useRef14(0);
|
|
6716
|
-
const [newestId, setNewestId] =
|
|
7012
|
+
const [newestId, setNewestId] = useState12(null);
|
|
6717
7013
|
const prevCount = useRef14(0);
|
|
6718
7014
|
const items = useMemo4(() => {
|
|
6719
7015
|
const all = session?.items ?? [];
|
|
6720
7016
|
return all.map((item, index) => ({ item, number: index + 1 })).filter(({ item }) => item.route === route);
|
|
6721
7017
|
}, [session, route]);
|
|
6722
7018
|
const byId = new Map(items.map(({ item }) => [item.id, item]));
|
|
6723
|
-
|
|
7019
|
+
useEffect14(() => {
|
|
6724
7020
|
const count = session?.items.length ?? 0;
|
|
6725
7021
|
if (count > prevCount.current && session && count > 0) {
|
|
6726
7022
|
const id = session.items[count - 1].id;
|
|
@@ -6731,7 +7027,7 @@ function Pins() {
|
|
|
6731
7027
|
}
|
|
6732
7028
|
prevCount.current = count;
|
|
6733
7029
|
}, [session]);
|
|
6734
|
-
|
|
7030
|
+
useEffect14(() => {
|
|
6735
7031
|
let raf = 0;
|
|
6736
7032
|
let lastSignature = "";
|
|
6737
7033
|
const tick = (time) => {
|
|
@@ -6815,8 +7111,8 @@ function Pins() {
|
|
|
6815
7111
|
dispatch({ type: "SET_ACTIVE_ITEM", id });
|
|
6816
7112
|
dispatch({ type: "SET_PANEL", open: true });
|
|
6817
7113
|
};
|
|
6818
|
-
return /* @__PURE__ */
|
|
6819
|
-
/* @__PURE__ */
|
|
7114
|
+
return /* @__PURE__ */ jsxs15(Fragment9, { children: [
|
|
7115
|
+
/* @__PURE__ */ jsx16("div", { ref: highlightRef, className: "rk-hl-ring", style: { opacity: 0 } }),
|
|
6820
7116
|
clusters.map((cluster) => {
|
|
6821
7117
|
const isCluster = cluster.ids.length > 1;
|
|
6822
7118
|
const isActive = activeItemId !== null && cluster.ids.includes(activeItemId);
|
|
@@ -6826,7 +7122,7 @@ function Pins() {
|
|
|
6826
7122
|
const status = statuses.size === 1 ? members[0]?.status : void 0;
|
|
6827
7123
|
const dimmed = filter !== null && members.length > 0 && !members.some((item) => itemMatchesFilter(item, filter));
|
|
6828
7124
|
const statusHint = isCluster ? status ? ` \xB7 all ${STATUS_LABELS[status] ?? status}` : "" : ` \xB7 ${STATUS_LABELS[members[0]?.status ?? "open"] ?? members[0]?.status}`;
|
|
6829
|
-
return /* @__PURE__ */
|
|
7125
|
+
return /* @__PURE__ */ jsx16(
|
|
6830
7126
|
"div",
|
|
6831
7127
|
{
|
|
6832
7128
|
ref: (el) => {
|
|
@@ -6834,7 +7130,7 @@ function Pins() {
|
|
|
6834
7130
|
else wrapRefs.current.delete(cluster.key);
|
|
6835
7131
|
},
|
|
6836
7132
|
className: `rk-pin-wrap${picking ? " rk-pin-ghost" : ""}`,
|
|
6837
|
-
children: /* @__PURE__ */
|
|
7133
|
+
children: /* @__PURE__ */ jsx16(
|
|
6838
7134
|
"button",
|
|
6839
7135
|
{
|
|
6840
7136
|
type: "button",
|
|
@@ -6856,7 +7152,7 @@ function Pins() {
|
|
|
6856
7152
|
cluster.key
|
|
6857
7153
|
);
|
|
6858
7154
|
}),
|
|
6859
|
-
orphanCount > 0 && /* @__PURE__ */
|
|
7155
|
+
orphanCount > 0 && /* @__PURE__ */ jsxs15(
|
|
6860
7156
|
"button",
|
|
6861
7157
|
{
|
|
6862
7158
|
type: "button",
|
|
@@ -6864,7 +7160,7 @@ function Pins() {
|
|
|
6864
7160
|
style: { bottom: 16, left: "50%", transform: "translateX(-50%)" },
|
|
6865
7161
|
onClick: () => dispatch({ type: "SET_PANEL", open: true }),
|
|
6866
7162
|
children: [
|
|
6867
|
-
/* @__PURE__ */
|
|
7163
|
+
/* @__PURE__ */ jsx16(IconUnlink, { size: 13 }),
|
|
6868
7164
|
orphanCount,
|
|
6869
7165
|
" unanchored item",
|
|
6870
7166
|
orphanCount === 1 ? "" : "s"
|
|
@@ -6875,13 +7171,13 @@ function Pins() {
|
|
|
6875
7171
|
}
|
|
6876
7172
|
|
|
6877
7173
|
// src/client/components/Toolbar.tsx
|
|
6878
|
-
import { useEffect as
|
|
6879
|
-
import { Fragment as
|
|
7174
|
+
import { useEffect as useEffect15, useLayoutEffect as useLayoutEffect3, useRef as useRef15, useState as useState13 } from "react";
|
|
7175
|
+
import { Fragment as Fragment10, jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
6880
7176
|
var TOOLS = [
|
|
6881
|
-
{ tool: "select", hintId: "tool-select", label: "Select", icon: (n) => /* @__PURE__ */
|
|
6882
|
-
{ tool: "copy", hintId: "tool-copy", label: "Rewrite text", icon: (n) => /* @__PURE__ */
|
|
6883
|
-
{ tool: "comment", hintId: "tool-comment", label: "Comment", icon: (n) => /* @__PURE__ */
|
|
6884
|
-
{ tool: "image", hintId: "tool-image", label: "Replace image", icon: (n) => /* @__PURE__ */
|
|
7177
|
+
{ tool: "select", hintId: "tool-select", label: "Select", icon: (n) => /* @__PURE__ */ jsx17(IconTarget, { size: n }) },
|
|
7178
|
+
{ tool: "copy", hintId: "tool-copy", label: "Rewrite text", icon: (n) => /* @__PURE__ */ jsx17(IconText, { size: n }) },
|
|
7179
|
+
{ tool: "comment", hintId: "tool-comment", label: "Comment", icon: (n) => /* @__PURE__ */ jsx17(IconComment, { size: n }) },
|
|
7180
|
+
{ tool: "image", hintId: "tool-image", label: "Replace image", icon: (n) => /* @__PURE__ */ jsx17(IconImage, { size: n }) }
|
|
6885
7181
|
];
|
|
6886
7182
|
var POS_KEY2 = "review-kit:toolbar-pos";
|
|
6887
7183
|
var DRAG_THRESHOLD2 = 6;
|
|
@@ -6890,9 +7186,9 @@ function Toolbar() {
|
|
|
6890
7186
|
const hasPeers = syncStatus !== "disabled" && peers.length > 0;
|
|
6891
7187
|
const dispatch = useDispatch();
|
|
6892
7188
|
const ref = useRef15(null);
|
|
6893
|
-
const [pos, setPos] =
|
|
7189
|
+
const [pos, setPos] = useState13(() => readStoredPos(POS_KEY2));
|
|
6894
7190
|
const drag = useRef15(null);
|
|
6895
|
-
const [dragging, setDragging] =
|
|
7191
|
+
const [dragging, setDragging] = useState13(false);
|
|
6896
7192
|
const justDragged = useRef15(false);
|
|
6897
7193
|
const visible = editor === null || selection !== null;
|
|
6898
7194
|
const applyPos = (next, persist) => {
|
|
@@ -6906,7 +7202,7 @@ function Toolbar() {
|
|
|
6906
7202
|
const clamped = clampPos(pos.x, pos.y, el.offsetWidth, el.offsetHeight);
|
|
6907
7203
|
if (clamped.x !== pos.x || clamped.y !== pos.y) applyPos(clamped, true);
|
|
6908
7204
|
}, [pos, selection, hasPeers, visible]);
|
|
6909
|
-
|
|
7205
|
+
useEffect15(() => {
|
|
6910
7206
|
const onResize = () => {
|
|
6911
7207
|
const el = ref.current;
|
|
6912
7208
|
const current = readStoredPos(POS_KEY2);
|
|
@@ -7019,7 +7315,7 @@ function Toolbar() {
|
|
|
7019
7315
|
mode === "pick" && selection === null ? "rk-ghost" : ""
|
|
7020
7316
|
].filter(Boolean).join(" ");
|
|
7021
7317
|
const style = pos !== null ? { left: 0, top: 0, translate: `${pos.x}px ${pos.y}px` } : void 0;
|
|
7022
|
-
return /* @__PURE__ */
|
|
7318
|
+
return /* @__PURE__ */ jsxs16(
|
|
7023
7319
|
"div",
|
|
7024
7320
|
{
|
|
7025
7321
|
ref,
|
|
@@ -7030,7 +7326,7 @@ function Toolbar() {
|
|
|
7030
7326
|
onPointerDown,
|
|
7031
7327
|
onClickCapture,
|
|
7032
7328
|
children: [
|
|
7033
|
-
/* @__PURE__ */
|
|
7329
|
+
/* @__PURE__ */ jsx17(
|
|
7034
7330
|
"button",
|
|
7035
7331
|
{
|
|
7036
7332
|
type: "button",
|
|
@@ -7038,19 +7334,19 @@ function Toolbar() {
|
|
|
7038
7334
|
"aria-label": "Move the toolbar \u2014 drag, or use arrow keys; double-click to reset its position",
|
|
7039
7335
|
onKeyDown: onGripKeyDown,
|
|
7040
7336
|
onDoubleClick: () => applyPos(null, true),
|
|
7041
|
-
children: /* @__PURE__ */
|
|
7042
|
-
/* @__PURE__ */
|
|
7043
|
-
/* @__PURE__ */
|
|
7044
|
-
/* @__PURE__ */
|
|
7045
|
-
/* @__PURE__ */
|
|
7046
|
-
/* @__PURE__ */
|
|
7047
|
-
/* @__PURE__ */
|
|
7337
|
+
children: /* @__PURE__ */ jsxs16("svg", { width: "8", height: "14", viewBox: "0 0 8 14", "aria-hidden": "true", fill: "currentColor", children: [
|
|
7338
|
+
/* @__PURE__ */ jsx17("circle", { cx: "2", cy: "2", r: "1.1" }),
|
|
7339
|
+
/* @__PURE__ */ jsx17("circle", { cx: "6", cy: "2", r: "1.1" }),
|
|
7340
|
+
/* @__PURE__ */ jsx17("circle", { cx: "2", cy: "7", r: "1.1" }),
|
|
7341
|
+
/* @__PURE__ */ jsx17("circle", { cx: "6", cy: "7", r: "1.1" }),
|
|
7342
|
+
/* @__PURE__ */ jsx17("circle", { cx: "2", cy: "12", r: "1.1" }),
|
|
7343
|
+
/* @__PURE__ */ jsx17("circle", { cx: "6", cy: "12", r: "1.1" })
|
|
7048
7344
|
] })
|
|
7049
7345
|
}
|
|
7050
7346
|
),
|
|
7051
|
-
/* @__PURE__ */
|
|
7052
|
-
hasPeers && /* @__PURE__ */
|
|
7053
|
-
/* @__PURE__ */
|
|
7347
|
+
/* @__PURE__ */ jsx17(PresenceStrip, {}),
|
|
7348
|
+
hasPeers && /* @__PURE__ */ jsx17("span", { className: "rk-toolbar-sep" }),
|
|
7349
|
+
/* @__PURE__ */ jsx17("div", { className: "rk-seg rk-tool-seg", role: "group", "aria-label": "Tools", children: TOOLS.map((entry) => /* @__PURE__ */ jsx17(
|
|
7054
7350
|
"button",
|
|
7055
7351
|
{
|
|
7056
7352
|
type: "button",
|
|
@@ -7062,9 +7358,9 @@ function Toolbar() {
|
|
|
7062
7358
|
},
|
|
7063
7359
|
entry.tool
|
|
7064
7360
|
)) }),
|
|
7065
|
-
selection && /* @__PURE__ */
|
|
7066
|
-
selection && /* @__PURE__ */
|
|
7067
|
-
/* @__PURE__ */
|
|
7361
|
+
selection && /* @__PURE__ */ jsx17("span", { className: "rk-toolbar-sep" }),
|
|
7362
|
+
selection && /* @__PURE__ */ jsxs16(Fragment10, { children: [
|
|
7363
|
+
/* @__PURE__ */ jsxs16(
|
|
7068
7364
|
"button",
|
|
7069
7365
|
{
|
|
7070
7366
|
type: "button",
|
|
@@ -7073,12 +7369,12 @@ function Toolbar() {
|
|
|
7073
7369
|
title: `Rewrite text${keyHint("tool-copy")}`,
|
|
7074
7370
|
onClick: () => open("copy"),
|
|
7075
7371
|
children: [
|
|
7076
|
-
/* @__PURE__ */
|
|
7372
|
+
/* @__PURE__ */ jsx17(IconText, { size: 14 }),
|
|
7077
7373
|
" Rewrite"
|
|
7078
7374
|
]
|
|
7079
7375
|
}
|
|
7080
7376
|
),
|
|
7081
|
-
hasImage && /* @__PURE__ */
|
|
7377
|
+
hasImage && /* @__PURE__ */ jsxs16(
|
|
7082
7378
|
"button",
|
|
7083
7379
|
{
|
|
7084
7380
|
type: "button",
|
|
@@ -7087,12 +7383,12 @@ function Toolbar() {
|
|
|
7087
7383
|
title: `Replace image${keyHint("tool-image")}`,
|
|
7088
7384
|
onClick: () => open("image"),
|
|
7089
7385
|
children: [
|
|
7090
|
-
/* @__PURE__ */
|
|
7386
|
+
/* @__PURE__ */ jsx17(IconImage, { size: 14 }),
|
|
7091
7387
|
" Image"
|
|
7092
7388
|
]
|
|
7093
7389
|
}
|
|
7094
7390
|
),
|
|
7095
|
-
/* @__PURE__ */
|
|
7391
|
+
/* @__PURE__ */ jsxs16(
|
|
7096
7392
|
"button",
|
|
7097
7393
|
{
|
|
7098
7394
|
type: "button",
|
|
@@ -7101,32 +7397,32 @@ function Toolbar() {
|
|
|
7101
7397
|
title: `Comment${keyHint("tool-comment")}`,
|
|
7102
7398
|
onClick: () => open("comment"),
|
|
7103
7399
|
children: [
|
|
7104
|
-
/* @__PURE__ */
|
|
7400
|
+
/* @__PURE__ */ jsx17(IconComment, { size: 14 }),
|
|
7105
7401
|
" Comment"
|
|
7106
7402
|
]
|
|
7107
7403
|
}
|
|
7108
7404
|
),
|
|
7109
|
-
/* @__PURE__ */
|
|
7110
|
-
/* @__PURE__ */
|
|
7405
|
+
/* @__PURE__ */ jsxs16("button", { type: "button", role: "menuitem", className: "rk-toolbar-btn", onClick: () => open("style"), children: [
|
|
7406
|
+
/* @__PURE__ */ jsx17(IconStyle, { size: 14 }),
|
|
7111
7407
|
" Style"
|
|
7112
7408
|
] }),
|
|
7113
|
-
/* @__PURE__ */
|
|
7114
|
-
/* @__PURE__ */
|
|
7409
|
+
/* @__PURE__ */ jsxs16("button", { type: "button", role: "menuitem", className: "rk-toolbar-btn", onClick: () => open("move"), children: [
|
|
7410
|
+
/* @__PURE__ */ jsx17(IconMove, { size: 14 }),
|
|
7115
7411
|
" Move"
|
|
7116
7412
|
] }),
|
|
7117
|
-
/* @__PURE__ */
|
|
7118
|
-
/* @__PURE__ */
|
|
7413
|
+
/* @__PURE__ */ jsxs16("button", { type: "button", role: "menuitem", className: "rk-toolbar-btn rk-danger", onClick: () => open("delete"), children: [
|
|
7414
|
+
/* @__PURE__ */ jsx17(IconTrash, { size: 14 }),
|
|
7119
7415
|
" Delete"
|
|
7120
7416
|
] }),
|
|
7121
|
-
/* @__PURE__ */
|
|
7122
|
-
/* @__PURE__ */
|
|
7417
|
+
/* @__PURE__ */ jsx17("span", { className: "rk-toolbar-sep" }),
|
|
7418
|
+
/* @__PURE__ */ jsx17(
|
|
7123
7419
|
"button",
|
|
7124
7420
|
{
|
|
7125
7421
|
type: "button",
|
|
7126
7422
|
className: "rk-icon-btn",
|
|
7127
7423
|
"aria-label": "Deselect",
|
|
7128
7424
|
onClick: () => dispatch({ type: "SELECT", selection: null }),
|
|
7129
|
-
children: /* @__PURE__ */
|
|
7425
|
+
children: /* @__PURE__ */ jsx17(IconClose, { size: 13 })
|
|
7130
7426
|
}
|
|
7131
7427
|
)
|
|
7132
7428
|
] })
|
|
@@ -7136,27 +7432,27 @@ function Toolbar() {
|
|
|
7136
7432
|
}
|
|
7137
7433
|
|
|
7138
7434
|
// src/client/components/Toast.tsx
|
|
7139
|
-
import { useEffect as
|
|
7140
|
-
import { jsx as
|
|
7435
|
+
import { useEffect as useEffect16 } from "react";
|
|
7436
|
+
import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
7141
7437
|
function ToastRow({ toast: toast2 }) {
|
|
7142
7438
|
const dispatch = useDispatch();
|
|
7143
|
-
|
|
7439
|
+
useEffect16(() => {
|
|
7144
7440
|
const timer = window.setTimeout(() => dispatch({ type: "DISMISS_TOAST", id: toast2.id }), 3500);
|
|
7145
7441
|
return () => window.clearTimeout(timer);
|
|
7146
7442
|
}, [toast2.id, dispatch]);
|
|
7147
|
-
return /* @__PURE__ */
|
|
7148
|
-
toast2.tone === "success" ? /* @__PURE__ */
|
|
7443
|
+
return /* @__PURE__ */ jsxs17("div", { className: `rk-toast rk-${toast2.tone}`, role: "status", children: [
|
|
7444
|
+
toast2.tone === "success" ? /* @__PURE__ */ jsx18(IconCheck, { size: 13 }) : toast2.tone === "error" ? /* @__PURE__ */ jsx18(IconWarning, { size: 13 }) : /* @__PURE__ */ jsx18(IconComment, { size: 13 }),
|
|
7149
7445
|
toast2.message
|
|
7150
7446
|
] });
|
|
7151
7447
|
}
|
|
7152
7448
|
function ToastHost() {
|
|
7153
7449
|
const { toasts } = useStore();
|
|
7154
7450
|
if (toasts.length === 0) return null;
|
|
7155
|
-
return /* @__PURE__ */
|
|
7451
|
+
return /* @__PURE__ */ jsx18("div", { className: "rk-toasts", "aria-live": "polite", children: toasts.map((toast2) => /* @__PURE__ */ jsx18(ToastRow, { toast: toast2 }, toast2.id)) });
|
|
7156
7452
|
}
|
|
7157
7453
|
|
|
7158
7454
|
// src/client/App.tsx
|
|
7159
|
-
import { jsx as
|
|
7455
|
+
import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
7160
7456
|
function App() {
|
|
7161
7457
|
const state = useStore();
|
|
7162
7458
|
const rawDispatch = useDispatch();
|
|
@@ -7166,10 +7462,10 @@ function App() {
|
|
|
7166
7462
|
const storageKey = config.storageKey ?? defaultStorageKey();
|
|
7167
7463
|
useAppliedPreview(state, dispatch);
|
|
7168
7464
|
useEmblemaAutoPush(state, dispatch, config);
|
|
7169
|
-
|
|
7465
|
+
useEffect17(() => {
|
|
7170
7466
|
setEffectAssetsUrl(config.fxAssetsUrl);
|
|
7171
7467
|
}, [config.fxAssetsUrl]);
|
|
7172
|
-
|
|
7468
|
+
useEffect17(() => {
|
|
7173
7469
|
let cancelled = false;
|
|
7174
7470
|
void loadSession(storageKey).then((stored) => {
|
|
7175
7471
|
if (cancelled) return;
|
|
@@ -7187,7 +7483,7 @@ function App() {
|
|
|
7187
7483
|
};
|
|
7188
7484
|
}, [storageKey, config.defaultAuthor, dispatch]);
|
|
7189
7485
|
const { session } = state;
|
|
7190
|
-
|
|
7486
|
+
useEffect17(() => {
|
|
7191
7487
|
if (!session) return;
|
|
7192
7488
|
if (saveTimer.current !== null) window.clearTimeout(saveTimer.current);
|
|
7193
7489
|
saveTimer.current = window.setTimeout(() => {
|
|
@@ -7198,9 +7494,9 @@ function App() {
|
|
|
7198
7494
|
if (saveTimer.current !== null) window.clearTimeout(saveTimer.current);
|
|
7199
7495
|
};
|
|
7200
7496
|
}, [session, storageKey, config]);
|
|
7201
|
-
|
|
7497
|
+
useEffect17(() => trackPointer(), []);
|
|
7202
7498
|
const focusHandled = useRef16(false);
|
|
7203
|
-
|
|
7499
|
+
useEffect17(() => {
|
|
7204
7500
|
if (!session || focusHandled.current) return;
|
|
7205
7501
|
focusHandled.current = true;
|
|
7206
7502
|
const id = takeFocusItem();
|
|
@@ -7225,7 +7521,7 @@ function App() {
|
|
|
7225
7521
|
cancelled = true;
|
|
7226
7522
|
};
|
|
7227
7523
|
}, [session, dispatch]);
|
|
7228
|
-
|
|
7524
|
+
useEffect17(() => {
|
|
7229
7525
|
let last = window.location.pathname;
|
|
7230
7526
|
const check = () => {
|
|
7231
7527
|
if (window.location.pathname !== last) {
|
|
@@ -7242,7 +7538,7 @@ function App() {
|
|
|
7242
7538
|
}, [dispatch]);
|
|
7243
7539
|
const stateRef = useRef16(state);
|
|
7244
7540
|
stateRef.current = state;
|
|
7245
|
-
|
|
7541
|
+
useEffect17(() => {
|
|
7246
7542
|
const onKeyDown = (event) => {
|
|
7247
7543
|
const current = stateRef.current;
|
|
7248
7544
|
for (const def of SHORTCUTS) {
|
|
@@ -7257,7 +7553,7 @@ function App() {
|
|
|
7257
7553
|
document.addEventListener("keydown", onKeyDown);
|
|
7258
7554
|
return () => document.removeEventListener("keydown", onKeyDown);
|
|
7259
7555
|
}, [dispatch]);
|
|
7260
|
-
|
|
7556
|
+
useEffect17(() => {
|
|
7261
7557
|
if (!state.editor) return;
|
|
7262
7558
|
const editorEl = state.editor.element;
|
|
7263
7559
|
const onPointerDown = (event) => {
|
|
@@ -7270,32 +7566,33 @@ function App() {
|
|
|
7270
7566
|
}, [state.editor, dispatch]);
|
|
7271
7567
|
if (!session) return null;
|
|
7272
7568
|
if (state.hidden) {
|
|
7273
|
-
return /* @__PURE__ */
|
|
7569
|
+
return /* @__PURE__ */ jsx19(DispatchContext.Provider, { value: dispatch, children: null });
|
|
7274
7570
|
}
|
|
7275
|
-
return /* @__PURE__ */
|
|
7276
|
-
/* @__PURE__ */
|
|
7277
|
-
/* @__PURE__ */
|
|
7278
|
-
/* @__PURE__ */
|
|
7279
|
-
state.editor?.kind === "copy" && /* @__PURE__ */
|
|
7280
|
-
state.editor?.kind === "image" && /* @__PURE__ */
|
|
7281
|
-
state.editor && state.editor.kind !== "copy" && state.editor.kind !== "image" && /* @__PURE__ */
|
|
7282
|
-
/* @__PURE__ */
|
|
7283
|
-
/* @__PURE__ */
|
|
7284
|
-
/* @__PURE__ */
|
|
7285
|
-
/* @__PURE__ */
|
|
7286
|
-
/* @__PURE__ */
|
|
7287
|
-
/* @__PURE__ */
|
|
7288
|
-
/* @__PURE__ */
|
|
7289
|
-
/* @__PURE__ */
|
|
7290
|
-
/* @__PURE__ */
|
|
7571
|
+
return /* @__PURE__ */ jsxs18(DispatchContext.Provider, { value: dispatch, children: [
|
|
7572
|
+
/* @__PURE__ */ jsx19(PickLayer, {}),
|
|
7573
|
+
/* @__PURE__ */ jsx19(PeerCursors, {}),
|
|
7574
|
+
/* @__PURE__ */ jsx19(Toolbar, {}),
|
|
7575
|
+
state.editor?.kind === "copy" && /* @__PURE__ */ jsx19(InlineEditor, { editor: state.editor }),
|
|
7576
|
+
state.editor?.kind === "image" && /* @__PURE__ */ jsx19(ImageEditor, { editor: state.editor }),
|
|
7577
|
+
state.editor && state.editor.kind !== "copy" && state.editor.kind !== "image" && /* @__PURE__ */ jsx19(NoteComposer, { editor: state.editor }),
|
|
7578
|
+
/* @__PURE__ */ jsx19(Pins, {}),
|
|
7579
|
+
/* @__PURE__ */ jsx19(QuickComment, {}),
|
|
7580
|
+
/* @__PURE__ */ jsx19(Panel, {}),
|
|
7581
|
+
/* @__PURE__ */ jsx19(Badge, {}),
|
|
7582
|
+
/* @__PURE__ */ jsx19(CoachMark, {}),
|
|
7583
|
+
/* @__PURE__ */ jsx19(CheatSheet, {}),
|
|
7584
|
+
/* @__PURE__ */ jsx19(EmblemaConnect, {}),
|
|
7585
|
+
/* @__PURE__ */ jsx19(TerminalConnect, {}),
|
|
7586
|
+
/* @__PURE__ */ jsx19(ConfirmHost, {}),
|
|
7587
|
+
/* @__PURE__ */ jsx19(ToastHost, {})
|
|
7291
7588
|
] });
|
|
7292
7589
|
}
|
|
7293
7590
|
|
|
7294
7591
|
// src/client/ReviewKit.tsx
|
|
7295
|
-
import { jsx as
|
|
7592
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
7296
7593
|
function ShadowHost({ config }) {
|
|
7297
|
-
const [mount, setMount] =
|
|
7298
|
-
|
|
7594
|
+
const [mount, setMount] = useState14(null);
|
|
7595
|
+
useEffect18(() => {
|
|
7299
7596
|
const host = document.createElement("div");
|
|
7300
7597
|
host.setAttribute(HOST_ATTR, "");
|
|
7301
7598
|
host.style.position = "fixed";
|
|
@@ -7331,15 +7628,15 @@ function ShadowHost({ config }) {
|
|
|
7331
7628
|
}, []);
|
|
7332
7629
|
if (!mount) return null;
|
|
7333
7630
|
return createPortal(
|
|
7334
|
-
/* @__PURE__ */
|
|
7631
|
+
/* @__PURE__ */ jsx20(StoreProvider, { config, children: /* @__PURE__ */ jsx20(App, {}) }),
|
|
7335
7632
|
mount
|
|
7336
7633
|
);
|
|
7337
7634
|
}
|
|
7338
7635
|
function ReviewKit(props) {
|
|
7339
|
-
const [active, setActive] =
|
|
7636
|
+
const [active, setActive] = useState14(false);
|
|
7340
7637
|
const { enabled, token, allowedHosts, devAutoOn } = props;
|
|
7341
7638
|
const hostsKey = allowedHosts?.join("\0") ?? "";
|
|
7342
|
-
|
|
7639
|
+
useEffect18(() => {
|
|
7343
7640
|
if (enabled === false) {
|
|
7344
7641
|
setActive(false);
|
|
7345
7642
|
return;
|
|
@@ -7350,7 +7647,7 @@ function ReviewKit(props) {
|
|
|
7350
7647
|
return () => window.removeEventListener(DEACTIVATE_EVENT, onDeactivate);
|
|
7351
7648
|
}, [enabled, token, devAutoOn, hostsKey]);
|
|
7352
7649
|
if (enabled === false || !active) return null;
|
|
7353
|
-
return /* @__PURE__ */
|
|
7650
|
+
return /* @__PURE__ */ jsx20(ShadowHost, { config: props });
|
|
7354
7651
|
}
|
|
7355
7652
|
|
|
7356
7653
|
export {
|
|
@@ -7363,4 +7660,4 @@ export {
|
|
|
7363
7660
|
importSessionFile,
|
|
7364
7661
|
ReviewKit
|
|
7365
7662
|
};
|
|
7366
|
-
//# sourceMappingURL=chunk-
|
|
7663
|
+
//# sourceMappingURL=chunk-5MAFDRUI.js.map
|