@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
package/dist/client/index.cjs
CHANGED
|
@@ -906,7 +906,7 @@ __export(client_exports, {
|
|
|
906
906
|
module.exports = __toCommonJS(client_exports);
|
|
907
907
|
|
|
908
908
|
// src/client/ReviewKit.tsx
|
|
909
|
-
var
|
|
909
|
+
var import_react22 = require("react");
|
|
910
910
|
var import_react_dom = require("react-dom");
|
|
911
911
|
|
|
912
912
|
// src/activate.ts
|
|
@@ -1908,6 +1908,8 @@ input, textarea, select {
|
|
|
1908
1908
|
.rk-sync-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--rk-fg-faint); }
|
|
1909
1909
|
.rk-sync-online .rk-sync-dot { background: var(--rk-success); }
|
|
1910
1910
|
.rk-sync-connecting .rk-sync-dot { background: var(--rk-warn); }
|
|
1911
|
+
.rk-sync-reason-token-short .rk-sync-dot, .rk-sync-reason-bad-token .rk-sync-dot { background: var(--rk-danger); }
|
|
1912
|
+
.rk-sync[title] { cursor: help; }
|
|
1911
1913
|
/* Automatic Emblema push hint (same quiet language) */
|
|
1912
1914
|
.rk-epush-ok .rk-sync-dot { background: var(--rk-success); }
|
|
1913
1915
|
.rk-epush-sending .rk-sync-dot { background: var(--rk-warn); }
|
|
@@ -3483,7 +3485,8 @@ function reducer(state, action) {
|
|
|
3483
3485
|
panelOpen: false,
|
|
3484
3486
|
confirm: null,
|
|
3485
3487
|
cheatsheetOpen: false,
|
|
3486
|
-
emblemaConnectOpen: false
|
|
3488
|
+
emblemaConnectOpen: false,
|
|
3489
|
+
terminalConnectOpen: false
|
|
3487
3490
|
} : { ...state, hidden: false };
|
|
3488
3491
|
case "SELECT":
|
|
3489
3492
|
return { ...state, selection: action.selection };
|
|
@@ -3593,12 +3596,16 @@ function reducer(state, action) {
|
|
|
3593
3596
|
return { ...state, cheatsheetOpen: action.open };
|
|
3594
3597
|
case "SET_EMBLEMA_CONNECT":
|
|
3595
3598
|
return { ...state, emblemaConnectOpen: action.open };
|
|
3599
|
+
case "SET_TERMINAL_CONNECT":
|
|
3600
|
+
return { ...state, terminalConnectOpen: action.open };
|
|
3596
3601
|
case "SET_COACH":
|
|
3597
3602
|
return { ...state, coachOpen: action.open };
|
|
3598
3603
|
case "SET_CORNER":
|
|
3599
3604
|
return { ...state, badgeCorner: action.corner };
|
|
3600
|
-
case "SYNC_STATUS":
|
|
3601
|
-
|
|
3605
|
+
case "SYNC_STATUS": {
|
|
3606
|
+
const reason = action.reason === void 0 ? action.status === "online" ? null : state.syncReason : action.reason;
|
|
3607
|
+
return state.syncStatus === action.status && state.syncReason === reason ? state : { ...state, syncStatus: action.status, syncReason: reason };
|
|
3608
|
+
}
|
|
3602
3609
|
case "EMBLEMA_PUSH_STATUS":
|
|
3603
3610
|
return state.emblemaPush === action.status ? state : { ...state, emblemaPush: action.status };
|
|
3604
3611
|
/*
|
|
@@ -3727,9 +3734,11 @@ function initialState() {
|
|
|
3727
3734
|
confirm: null,
|
|
3728
3735
|
cheatsheetOpen: false,
|
|
3729
3736
|
emblemaConnectOpen: false,
|
|
3737
|
+
terminalConnectOpen: false,
|
|
3730
3738
|
coachOpen: false,
|
|
3731
3739
|
undoStack: [],
|
|
3732
3740
|
syncStatus: "disabled",
|
|
3741
|
+
syncReason: null,
|
|
3733
3742
|
emblemaPush: "idle",
|
|
3734
3743
|
peers: [],
|
|
3735
3744
|
quick: null,
|
|
@@ -3744,7 +3753,7 @@ function StoreProvider({ config, children }) {
|
|
|
3744
3753
|
const configValue = (0, import_react.useMemo)(
|
|
3745
3754
|
() => config,
|
|
3746
3755
|
// eslint-disable-next-line react-hooks/exhaustive-deps -- config object identity is per-render; depend on its fields
|
|
3747
|
-
[config.enabled, config.token, config.devAutoOn, config.syncToken, config.syncUrl, config.defaultAuthor, config.fxAssetsUrl, config.position, config.storageKey, config.onSessionChange, config.emblema]
|
|
3756
|
+
[config.enabled, config.token, config.devAutoOn, config.sync, config.syncToken, config.syncUrl, config.defaultAuthor, config.fxAssetsUrl, config.position, config.storageKey, config.onSessionChange, config.emblema]
|
|
3748
3757
|
);
|
|
3749
3758
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ConfigContext.Provider, { value: configValue, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StateContext.Provider, { value: state, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DispatchContext.Provider, { value: dispatch, children }) }) });
|
|
3750
3759
|
}
|
|
@@ -3773,7 +3782,7 @@ function toast(dispatch, message, tone = "info") {
|
|
|
3773
3782
|
}
|
|
3774
3783
|
|
|
3775
3784
|
// src/client/App.tsx
|
|
3776
|
-
var
|
|
3785
|
+
var import_react21 = require("react");
|
|
3777
3786
|
|
|
3778
3787
|
// src/client/persist.ts
|
|
3779
3788
|
var DB_NAME = "review-kit";
|
|
@@ -4757,9 +4766,13 @@ function createRkSync(options) {
|
|
|
4757
4766
|
pongTimer = null;
|
|
4758
4767
|
}
|
|
4759
4768
|
break;
|
|
4760
|
-
case "error":
|
|
4769
|
+
case "error": {
|
|
4761
4770
|
log("server error:", msg.code, msg.message);
|
|
4771
|
+
const code = typeof msg.code === "string" ? msg.code : "error";
|
|
4772
|
+
const message = typeof msg.message === "string" ? msg.message : "";
|
|
4773
|
+
safely(() => handlers.onError?.(code, message));
|
|
4762
4774
|
break;
|
|
4775
|
+
}
|
|
4763
4776
|
case "presence:join": {
|
|
4764
4777
|
const peer = msg.peer;
|
|
4765
4778
|
if (peer && typeof peer.id === "string") safely(() => handlers.onPeerJoin?.(peer));
|
|
@@ -4961,6 +4974,18 @@ function currentAuthor(name) {
|
|
|
4961
4974
|
}
|
|
4962
4975
|
|
|
4963
4976
|
// src/client/sync.ts
|
|
4977
|
+
var DEFAULT_SYNC_URL = "wss://2-59-219-26.sslip.io/rk-sync";
|
|
4978
|
+
function resolveSyncUrl(config) {
|
|
4979
|
+
return typeof config.syncUrl === "string" && config.syncUrl !== "" ? config.syncUrl : DEFAULT_SYNC_URL;
|
|
4980
|
+
}
|
|
4981
|
+
var MIN_SYNC_TOKEN_LENGTH = 8;
|
|
4982
|
+
var warnedShortToken = false;
|
|
4983
|
+
function resolveSyncToken(config) {
|
|
4984
|
+
if (config.sync === false) return null;
|
|
4985
|
+
const explicit = typeof config.syncToken === "string" && config.syncToken !== "" ? config.syncToken : null;
|
|
4986
|
+
const fallback = typeof config.token === "string" && config.token !== "" ? config.token : null;
|
|
4987
|
+
return explicit ?? fallback;
|
|
4988
|
+
}
|
|
4964
4989
|
function toPeerState(peer) {
|
|
4965
4990
|
return {
|
|
4966
4991
|
id: peer.id,
|
|
@@ -4988,20 +5013,43 @@ function useRealtimeSync(state, rawDispatch, config, reducer2) {
|
|
|
4988
5013
|
const stateRef = (0, import_react4.useRef)(state);
|
|
4989
5014
|
stateRef.current = state;
|
|
4990
5015
|
const myIdRef = (0, import_react4.useRef)("");
|
|
4991
|
-
const
|
|
5016
|
+
const syncToken = resolveSyncToken(config);
|
|
5017
|
+
const syncUrl = resolveSyncUrl(config);
|
|
5018
|
+
const enabled = syncToken !== null;
|
|
4992
5019
|
const author = state.session?.author ?? "";
|
|
4993
5020
|
const hasSession = state.session !== null;
|
|
4994
5021
|
(0, import_react4.useEffect)(() => {
|
|
4995
5022
|
if (!enabled || !hasSession) return;
|
|
5023
|
+
const dispatchGuard = rawDispatch;
|
|
5024
|
+
if (syncToken.length < MIN_SYNC_TOKEN_LENGTH) {
|
|
5025
|
+
dispatchGuard({ type: "SYNC_STATUS", status: "offline", reason: "token-short" });
|
|
5026
|
+
if (!warnedShortToken) {
|
|
5027
|
+
warnedShortToken = true;
|
|
5028
|
+
console.warn(
|
|
5029
|
+
`[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.`
|
|
5030
|
+
);
|
|
5031
|
+
}
|
|
5032
|
+
return () => dispatchGuard({ type: "SYNC_STATUS", status: "disabled", reason: null });
|
|
5033
|
+
}
|
|
4996
5034
|
const id = reviewerId();
|
|
4997
5035
|
myIdRef.current = id;
|
|
4998
5036
|
const dispatch = rawDispatch;
|
|
4999
5037
|
const sync = createRkSync({
|
|
5000
|
-
token:
|
|
5001
|
-
url:
|
|
5038
|
+
token: syncToken,
|
|
5039
|
+
url: syncUrl,
|
|
5002
5040
|
user: { id, name: author || "Reviewer", color: colorForReviewer(id) },
|
|
5003
5041
|
handlers: {
|
|
5004
|
-
onStatus: (status) => dispatch({
|
|
5042
|
+
onStatus: (status) => dispatch({
|
|
5043
|
+
type: "SYNC_STATUS",
|
|
5044
|
+
status,
|
|
5045
|
+
// Offline with no server verdict = the socket never got through
|
|
5046
|
+
// (server down, CSP connect-src, network); a verdict keeps its reason.
|
|
5047
|
+
...status === "offline" ? { reason: stateRef.current.syncReason ?? "unreachable" } : {}
|
|
5048
|
+
}),
|
|
5049
|
+
onError: (code) => {
|
|
5050
|
+
if (code === "bad-token") dispatch({ type: "SYNC_STATUS", status: "offline", reason: "bad-token" });
|
|
5051
|
+
else if (code === "room-full") dispatch({ type: "SYNC_STATUS", status: "offline", reason: "room-full" });
|
|
5052
|
+
},
|
|
5005
5053
|
onSnapshot: (items, peers, deletedIds = []) => {
|
|
5006
5054
|
const safeItems = items.map(sanitizeRemoteItem).filter((item) => item !== null);
|
|
5007
5055
|
dispatch({ type: "SYNC_SNAPSHOT", items: safeItems });
|
|
@@ -5058,10 +5106,10 @@ function useRealtimeSync(state, rawDispatch, config, reducer2) {
|
|
|
5058
5106
|
if (activeSyncRef === sync) activeSyncRef = null;
|
|
5059
5107
|
setEffectBroadcaster2(null);
|
|
5060
5108
|
sync.stop();
|
|
5061
|
-
dispatch({ type: "SYNC_STATUS", status: "disabled" });
|
|
5109
|
+
dispatch({ type: "SYNC_STATUS", status: "disabled", reason: null });
|
|
5062
5110
|
dispatch({ type: "PEERS_SET", peers: [] });
|
|
5063
5111
|
};
|
|
5064
|
-
}, [enabled, hasSession,
|
|
5112
|
+
}, [enabled, hasSession, syncToken, syncUrl, author, rawDispatch]);
|
|
5065
5113
|
const wrapped = (0, import_react4.useMemo)(() => {
|
|
5066
5114
|
return (action) => {
|
|
5067
5115
|
const prev = stateRef.current;
|
|
@@ -5577,10 +5625,10 @@ function EmblemaConnect() {
|
|
|
5577
5625
|
state === null && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "rk-modal-text", children: [
|
|
5578
5626
|
"The local sync agent isn't running. In the project repo run:",
|
|
5579
5627
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("code", { className: "rk-connect-cmd", children: [
|
|
5580
|
-
"npx @satanwagen/reviewkit-cli init --origin ",
|
|
5628
|
+
"npx -p @satanwagen/reviewkit-cli reviewkit-emblema init --origin ",
|
|
5581
5629
|
window.location.origin
|
|
5582
5630
|
] }),
|
|
5583
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("code", { className: "rk-connect-cmd", children: "npx @satanwagen/reviewkit-cli serve" }),
|
|
5631
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("code", { className: "rk-connect-cmd", children: "npx -p @satanwagen/reviewkit-cli reviewkit-emblema serve" }),
|
|
5584
5632
|
"then reopen this dialog."
|
|
5585
5633
|
] }),
|
|
5586
5634
|
state !== null && state !== "loading" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
@@ -5667,15 +5715,229 @@ function EmblemaConnect() {
|
|
|
5667
5715
|
] });
|
|
5668
5716
|
}
|
|
5669
5717
|
|
|
5670
|
-
// src/client/components/
|
|
5718
|
+
// src/client/components/TerminalConnect.tsx
|
|
5671
5719
|
var import_react7 = require("react");
|
|
5720
|
+
|
|
5721
|
+
// src/integrations/terminal.ts
|
|
5722
|
+
var TERMINAL_PAIR_PORTS = [48780, 48781, 48782, 48783];
|
|
5723
|
+
async function fetchJson2(url, init, timeoutMs) {
|
|
5724
|
+
const abort = new AbortController();
|
|
5725
|
+
const timer = window.setTimeout(() => abort.abort(), timeoutMs);
|
|
5726
|
+
try {
|
|
5727
|
+
return await fetch(url, { ...init, signal: abort.signal });
|
|
5728
|
+
} finally {
|
|
5729
|
+
window.clearTimeout(timer);
|
|
5730
|
+
}
|
|
5731
|
+
}
|
|
5732
|
+
async function probeTerminal() {
|
|
5733
|
+
for (const port of TERMINAL_PAIR_PORTS) {
|
|
5734
|
+
try {
|
|
5735
|
+
const res = await fetchJson2(`http://127.0.0.1:${port}/pair`, { method: "GET" }, 900);
|
|
5736
|
+
if (!res.ok) continue;
|
|
5737
|
+
const body = await res.json();
|
|
5738
|
+
if (typeof body === "object" && body !== null && body.app === "reviewkit-cli") {
|
|
5739
|
+
const b = body;
|
|
5740
|
+
return {
|
|
5741
|
+
port,
|
|
5742
|
+
cwd: typeof b.cwd === "string" ? b.cwd : void 0,
|
|
5743
|
+
projects: Array.isArray(b.projects) ? b.projects.filter((p) => typeof p === "string") : []
|
|
5744
|
+
};
|
|
5745
|
+
}
|
|
5746
|
+
} catch {
|
|
5747
|
+
}
|
|
5748
|
+
}
|
|
5749
|
+
return null;
|
|
5750
|
+
}
|
|
5751
|
+
async function pairTerminal(port, key) {
|
|
5752
|
+
try {
|
|
5753
|
+
const res = await fetchJson2(
|
|
5754
|
+
`http://127.0.0.1:${port}/pair`,
|
|
5755
|
+
{ method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ key }) },
|
|
5756
|
+
5e3
|
|
5757
|
+
);
|
|
5758
|
+
const body = await res.json().catch(() => null);
|
|
5759
|
+
if (res.ok && body?.ok) return { ok: true, name: body.name ?? "", repo: body.repo ?? null };
|
|
5760
|
+
return { ok: false, error: body?.error ?? `HTTP ${res.status}` };
|
|
5761
|
+
} catch {
|
|
5762
|
+
return { ok: false, error: "the terminal stopped answering" };
|
|
5763
|
+
}
|
|
5764
|
+
}
|
|
5765
|
+
|
|
5766
|
+
// src/client/terminalKey.ts
|
|
5767
|
+
var TERMINAL_KEY_PREFIX = "rkc_";
|
|
5768
|
+
var TERMINAL_KEY_VERSION = 1;
|
|
5769
|
+
function base64url(text) {
|
|
5770
|
+
const bytes = new TextEncoder().encode(text);
|
|
5771
|
+
let binary = "";
|
|
5772
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
5773
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
5774
|
+
}
|
|
5775
|
+
function encodeTerminalKey(fields) {
|
|
5776
|
+
const payload = { v: TERMINAL_KEY_VERSION, ...fields };
|
|
5777
|
+
return TERMINAL_KEY_PREFIX + base64url(JSON.stringify(payload));
|
|
5778
|
+
}
|
|
5779
|
+
function currentTerminalKey(syncUrl, syncToken) {
|
|
5780
|
+
const origin = window.location.origin;
|
|
5781
|
+
let route = "/";
|
|
5782
|
+
try {
|
|
5783
|
+
route = window.location.pathname || "/";
|
|
5784
|
+
} catch {
|
|
5785
|
+
}
|
|
5786
|
+
return encodeTerminalKey({ name: window.location.hostname, origin, syncUrl, syncToken, route });
|
|
5787
|
+
}
|
|
5788
|
+
|
|
5789
|
+
// src/client/components/TerminalConnect.tsx
|
|
5672
5790
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
5791
|
+
function shortKey2(key) {
|
|
5792
|
+
return `${key.slice(0, 8)}\u2026${key.slice(-6)}`;
|
|
5793
|
+
}
|
|
5794
|
+
function shortPath(path) {
|
|
5795
|
+
if (!path) return "";
|
|
5796
|
+
const parts = path.split("/").filter(Boolean);
|
|
5797
|
+
return parts.length > 2 ? `\u2026/${parts.slice(-2).join("/")}` : path;
|
|
5798
|
+
}
|
|
5799
|
+
function TerminalConnect() {
|
|
5800
|
+
const { terminalConnectOpen } = useStore();
|
|
5801
|
+
const config = useConfig();
|
|
5802
|
+
const dispatch = useDispatch();
|
|
5803
|
+
const [phase, setPhase] = (0, import_react7.useState)("probing");
|
|
5804
|
+
const [probe, setProbe] = (0, import_react7.useState)(null);
|
|
5805
|
+
const [paired, setPaired] = (0, import_react7.useState)(null);
|
|
5806
|
+
const [showManual, setShowManual] = (0, import_react7.useState)(false);
|
|
5807
|
+
const syncToken = resolveSyncToken(config);
|
|
5808
|
+
const key = terminalConnectOpen && syncToken ? currentTerminalKey(resolveSyncUrl(config), syncToken) : null;
|
|
5809
|
+
(0, import_react7.useEffect)(() => {
|
|
5810
|
+
if (!terminalConnectOpen) return;
|
|
5811
|
+
let cancelled = false;
|
|
5812
|
+
setPhase("probing");
|
|
5813
|
+
setProbe(null);
|
|
5814
|
+
setPaired(null);
|
|
5815
|
+
setShowManual(false);
|
|
5816
|
+
const look = () => void probeTerminal().then((found) => {
|
|
5817
|
+
if (cancelled) return;
|
|
5818
|
+
setProbe(found);
|
|
5819
|
+
setPhase((current) => current === "pairing" || current === "paired" ? current : found ? "found" : "missing");
|
|
5820
|
+
});
|
|
5821
|
+
look();
|
|
5822
|
+
const timer = window.setInterval(look, 2e3);
|
|
5823
|
+
return () => {
|
|
5824
|
+
cancelled = true;
|
|
5825
|
+
window.clearInterval(timer);
|
|
5826
|
+
};
|
|
5827
|
+
}, [terminalConnectOpen]);
|
|
5828
|
+
if (!terminalConnectOpen) return null;
|
|
5829
|
+
const close = () => dispatch({ type: "SET_TERMINAL_CONNECT", open: false });
|
|
5830
|
+
const copy = async (value, what) => {
|
|
5831
|
+
try {
|
|
5832
|
+
await navigator.clipboard.writeText(value);
|
|
5833
|
+
toast(dispatch, `${what} copied`, "success");
|
|
5834
|
+
} catch {
|
|
5835
|
+
toast(dispatch, "Copy failed \u2014 select the text manually", "error");
|
|
5836
|
+
}
|
|
5837
|
+
};
|
|
5838
|
+
const connect = () => {
|
|
5839
|
+
if (!probe || !key) return;
|
|
5840
|
+
setPhase("pairing");
|
|
5841
|
+
void pairTerminal(probe.port, key).then((result) => {
|
|
5842
|
+
if (result.ok) {
|
|
5843
|
+
setPaired({ name: result.name, repo: result.repo });
|
|
5844
|
+
setPhase("paired");
|
|
5845
|
+
toast(dispatch, `Terminal paired as \u201C${result.name}\u201D`, "success");
|
|
5846
|
+
} else {
|
|
5847
|
+
setPhase("found");
|
|
5848
|
+
toast(dispatch, `Pairing failed: ${result.error}`, "error");
|
|
5849
|
+
}
|
|
5850
|
+
});
|
|
5851
|
+
};
|
|
5852
|
+
const connectCmd = key ? `npx -y @satanwagen/reviewkit-cli connect ${key}` : "";
|
|
5853
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
5854
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "rk-backdrop", onClick: close }),
|
|
5855
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "rk-modal", role: "dialog", "aria-modal": "true", "aria-label": "Connect terminal or agent", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "rk-modal-body", children: [
|
|
5856
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "rk-modal-title", style: { display: "flex", alignItems: "center", gap: 8 }, children: [
|
|
5857
|
+
"Connect terminal / agent",
|
|
5858
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { flex: 1 } }),
|
|
5859
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "rk-icon-btn", "aria-label": "Close", onClick: close, autoFocus: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(IconClose, { size: 13 }) })
|
|
5860
|
+
] }),
|
|
5861
|
+
!key && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "rk-modal-text", children: [
|
|
5862
|
+
"Live sync is off on this page (",
|
|
5863
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("code", { children: "sync=false" }),
|
|
5864
|
+
" or no token), so there is no shared room a terminal could read."
|
|
5865
|
+
] }),
|
|
5866
|
+
key && phase === "paired" && paired && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "rk-modal-text", children: [
|
|
5867
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "rk-emblema-dot", "data-state": "live" }),
|
|
5868
|
+
" Paired as ",
|
|
5869
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { children: paired.name }),
|
|
5870
|
+
paired.repo ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
5871
|
+
" in ",
|
|
5872
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("code", { children: shortPath(paired.repo) })
|
|
5873
|
+
] }) : null,
|
|
5874
|
+
". The terminal shows this page's comments live, and Claude Code / Cursor can read and resolve them through the ",
|
|
5875
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("code", { children: "reviewkit" }),
|
|
5876
|
+
" MCP tools."
|
|
5877
|
+
] }),
|
|
5878
|
+
key && phase !== "paired" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
5879
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "rk-modal-text", children: [
|
|
5880
|
+
phase === "probing" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
5881
|
+
"Looking for a ",
|
|
5882
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("code", { children: "reviewkit" }),
|
|
5883
|
+
" terminal on this machine\u2026"
|
|
5884
|
+
] }),
|
|
5885
|
+
phase === "missing" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
5886
|
+
"No terminal is listening yet. In the site's repo run",
|
|
5887
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("code", { className: "rk-connect-cmd", children: "npx -y @satanwagen/reviewkit-cli setup" }),
|
|
5888
|
+
"and this dialog will pick it up by itself."
|
|
5889
|
+
] }),
|
|
5890
|
+
(phase === "found" || phase === "pairing") && probe && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
5891
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "rk-emblema-dot", "data-state": "live" }),
|
|
5892
|
+
" Terminal found",
|
|
5893
|
+
probe.cwd ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
5894
|
+
" in ",
|
|
5895
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("code", { children: shortPath(probe.cwd) })
|
|
5896
|
+
] }) : null,
|
|
5897
|
+
".",
|
|
5898
|
+
probe.projects.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
5899
|
+
" Already paired: ",
|
|
5900
|
+
probe.projects.join(", "),
|
|
5901
|
+
"."
|
|
5902
|
+
] }) : null
|
|
5903
|
+
] })
|
|
5904
|
+
] }),
|
|
5905
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "rk-connect-actions", children: [
|
|
5906
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
5907
|
+
"button",
|
|
5908
|
+
{
|
|
5909
|
+
type: "button",
|
|
5910
|
+
className: "rk-btn rk-btn-primary",
|
|
5911
|
+
disabled: phase !== "found",
|
|
5912
|
+
onClick: connect,
|
|
5913
|
+
title: "Send this site's connection to the terminal \u2014 nothing to copy",
|
|
5914
|
+
children: phase === "pairing" ? "Connecting\u2026" : "Connect this terminal"
|
|
5915
|
+
}
|
|
5916
|
+
),
|
|
5917
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => setShowManual((v) => !v), children: showManual ? "Hide manual option" : "Another machine\u2026" })
|
|
5918
|
+
] }),
|
|
5919
|
+
showManual && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
5920
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("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):" }),
|
|
5921
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("code", { className: "rk-connect-cmd", title: connectCmd, children: [
|
|
5922
|
+
"npx -y @satanwagen/reviewkit-cli connect ",
|
|
5923
|
+
shortKey2(key)
|
|
5924
|
+
] }),
|
|
5925
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "rk-connect-actions", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => void copy(connectCmd, "Command"), children: "Copy command" }) })
|
|
5926
|
+
] })
|
|
5927
|
+
] })
|
|
5928
|
+
] }) })
|
|
5929
|
+
] });
|
|
5930
|
+
}
|
|
5931
|
+
|
|
5932
|
+
// src/client/components/CoachMark.tsx
|
|
5933
|
+
var import_react8 = require("react");
|
|
5934
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
5673
5935
|
var COACH_KEY = "review-kit:coach-dismissed";
|
|
5674
5936
|
function CoachMark() {
|
|
5675
5937
|
const { coachOpen, session } = useStore();
|
|
5676
5938
|
const dispatch = useDispatch();
|
|
5677
5939
|
const config = useConfig();
|
|
5678
|
-
const [name, setName] = (0,
|
|
5940
|
+
const [name, setName] = (0, import_react8.useState)(session?.author ?? config.defaultAuthor ?? "");
|
|
5679
5941
|
if (!coachOpen) return null;
|
|
5680
5942
|
const done = (startPicking) => {
|
|
5681
5943
|
if (name.trim() !== "") dispatch({ type: "SET_AUTHOR", author: name.trim() });
|
|
@@ -5686,39 +5948,39 @@ function CoachMark() {
|
|
|
5686
5948
|
}
|
|
5687
5949
|
if (startPicking) dispatch({ type: "SET_MODE", mode: "pick" });
|
|
5688
5950
|
};
|
|
5689
|
-
return /* @__PURE__ */ (0,
|
|
5690
|
-
/* @__PURE__ */ (0,
|
|
5691
|
-
/* @__PURE__ */ (0,
|
|
5692
|
-
/* @__PURE__ */ (0,
|
|
5693
|
-
/* @__PURE__ */ (0,
|
|
5951
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "rk-coach", role: "dialog", "aria-label": "Welcome to review mode", children: [
|
|
5952
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "rk-coach-accent" }),
|
|
5953
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "rk-coach-body", children: [
|
|
5954
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "rk-modal-title", style: { display: "flex", alignItems: "center", gap: 8 }, children: [
|
|
5955
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconTarget, { size: 16 }),
|
|
5694
5956
|
" Review mode"
|
|
5695
5957
|
] }),
|
|
5696
|
-
/* @__PURE__ */ (0,
|
|
5697
|
-
/* @__PURE__ */ (0,
|
|
5698
|
-
/* @__PURE__ */ (0,
|
|
5699
|
-
/* @__PURE__ */ (0,
|
|
5958
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("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." }),
|
|
5959
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "rk-coach-keys", "aria-label": "Key shortcuts", children: [
|
|
5960
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
|
|
5961
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "rk-kbd", children: "T" }),
|
|
5700
5962
|
" rewrite"
|
|
5701
5963
|
] }),
|
|
5702
|
-
/* @__PURE__ */ (0,
|
|
5703
|
-
/* @__PURE__ */ (0,
|
|
5964
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
|
|
5965
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "rk-kbd", children: "C" }),
|
|
5704
5966
|
" comment"
|
|
5705
5967
|
] }),
|
|
5706
|
-
/* @__PURE__ */ (0,
|
|
5707
|
-
/* @__PURE__ */ (0,
|
|
5968
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
|
|
5969
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "rk-kbd", children: "I" }),
|
|
5708
5970
|
" image"
|
|
5709
5971
|
] }),
|
|
5710
|
-
/* @__PURE__ */ (0,
|
|
5711
|
-
/* @__PURE__ */ (0,
|
|
5972
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
|
|
5973
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "rk-kbd", children: "V" }),
|
|
5712
5974
|
" select"
|
|
5713
5975
|
] }),
|
|
5714
|
-
/* @__PURE__ */ (0,
|
|
5715
|
-
/* @__PURE__ */ (0,
|
|
5976
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
|
|
5977
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "rk-kbd", children: "?" }),
|
|
5716
5978
|
" all shortcuts"
|
|
5717
5979
|
] })
|
|
5718
5980
|
] }),
|
|
5719
|
-
/* @__PURE__ */ (0,
|
|
5720
|
-
/* @__PURE__ */ (0,
|
|
5721
|
-
/* @__PURE__ */ (0,
|
|
5981
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
|
|
5982
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { className: "rk-label", htmlFor: "rk-author", children: "Your name" }),
|
|
5983
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
5722
5984
|
"input",
|
|
5723
5985
|
{
|
|
5724
5986
|
id: "rk-author",
|
|
@@ -5732,36 +5994,36 @@ function CoachMark() {
|
|
|
5732
5994
|
}
|
|
5733
5995
|
)
|
|
5734
5996
|
] }),
|
|
5735
|
-
/* @__PURE__ */ (0,
|
|
5736
|
-
/* @__PURE__ */ (0,
|
|
5737
|
-
/* @__PURE__ */ (0,
|
|
5997
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 4 }, children: [
|
|
5998
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => done(false), children: "Not now" }),
|
|
5999
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: "rk-btn rk-btn-primary", onClick: () => done(true), children: "Start reviewing" })
|
|
5738
6000
|
] })
|
|
5739
6001
|
] })
|
|
5740
6002
|
] });
|
|
5741
6003
|
}
|
|
5742
6004
|
|
|
5743
6005
|
// src/client/components/Confirm.tsx
|
|
5744
|
-
var
|
|
5745
|
-
var
|
|
6006
|
+
var import_react9 = require("react");
|
|
6007
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
5746
6008
|
function ConfirmHost() {
|
|
5747
6009
|
const { confirm } = useStore();
|
|
5748
6010
|
const dispatch = useDispatch();
|
|
5749
|
-
const cancelRef = (0,
|
|
5750
|
-
(0,
|
|
6011
|
+
const cancelRef = (0, import_react9.useRef)(null);
|
|
6012
|
+
(0, import_react9.useEffect)(() => {
|
|
5751
6013
|
if (confirm) cancelRef.current?.focus();
|
|
5752
6014
|
}, [confirm]);
|
|
5753
6015
|
if (!confirm) return null;
|
|
5754
6016
|
const close = () => dispatch({ type: "SET_CONFIRM", confirm: null });
|
|
5755
|
-
return /* @__PURE__ */ (0,
|
|
5756
|
-
/* @__PURE__ */ (0,
|
|
5757
|
-
/* @__PURE__ */ (0,
|
|
5758
|
-
/* @__PURE__ */ (0,
|
|
5759
|
-
/* @__PURE__ */ (0,
|
|
5760
|
-
/* @__PURE__ */ (0,
|
|
6017
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
6018
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "rk-backdrop", onClick: close }),
|
|
6019
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "rk-modal", role: "alertdialog", "aria-modal": "true", "aria-label": confirm.title, children: [
|
|
6020
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "rk-modal-body", children: [
|
|
6021
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "rk-modal-title", children: confirm.title }),
|
|
6022
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "rk-modal-text", children: confirm.message })
|
|
5761
6023
|
] }),
|
|
5762
|
-
/* @__PURE__ */ (0,
|
|
5763
|
-
/* @__PURE__ */ (0,
|
|
5764
|
-
/* @__PURE__ */ (0,
|
|
6024
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "rk-modal-actions", children: [
|
|
6025
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { ref: cancelRef, type: "button", className: "rk-btn rk-btn-ghost", onClick: close, children: "Cancel" }),
|
|
6026
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
5765
6027
|
"button",
|
|
5766
6028
|
{
|
|
5767
6029
|
type: "button",
|
|
@@ -5780,10 +6042,10 @@ function ConfirmHost() {
|
|
|
5780
6042
|
}
|
|
5781
6043
|
|
|
5782
6044
|
// src/client/components/ImageEditor.tsx
|
|
5783
|
-
var
|
|
6045
|
+
var import_react11 = require("react");
|
|
5784
6046
|
|
|
5785
6047
|
// src/client/useAnchored.ts
|
|
5786
|
-
var
|
|
6048
|
+
var import_react10 = require("react");
|
|
5787
6049
|
|
|
5788
6050
|
// src/client/position.ts
|
|
5789
6051
|
function place(anchor, size, side, offset) {
|
|
@@ -5828,9 +6090,9 @@ function computePosition(anchor, size, options = {}) {
|
|
|
5828
6090
|
|
|
5829
6091
|
// src/client/useAnchored.ts
|
|
5830
6092
|
function useAnchored(anchorEl, side = "bottom", offset = 8) {
|
|
5831
|
-
const ref = (0,
|
|
5832
|
-
const [pos, setPos] = (0,
|
|
5833
|
-
(0,
|
|
6093
|
+
const ref = (0, import_react10.useRef)(null);
|
|
6094
|
+
const [pos, setPos] = (0, import_react10.useState)(null);
|
|
6095
|
+
(0, import_react10.useLayoutEffect)(() => {
|
|
5834
6096
|
if (!anchorEl) {
|
|
5835
6097
|
setPos(null);
|
|
5836
6098
|
return;
|
|
@@ -5861,7 +6123,7 @@ function anchoredStyle(pos) {
|
|
|
5861
6123
|
}
|
|
5862
6124
|
|
|
5863
6125
|
// src/client/components/ImageEditor.tsx
|
|
5864
|
-
var
|
|
6126
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
5865
6127
|
var MAX_BYTES = 2 * 1024 * 1024;
|
|
5866
6128
|
var FETCH_TIMEOUT_MS = 12e3;
|
|
5867
6129
|
var PROBE_TIMEOUT_MS = 8e3;
|
|
@@ -5919,15 +6181,15 @@ function urlFromDataTransfer(dt) {
|
|
|
5919
6181
|
function ImageEditor({ editor }) {
|
|
5920
6182
|
const dispatch = useDispatch();
|
|
5921
6183
|
const { route, session } = useStore();
|
|
5922
|
-
const [replacement, setReplacement] = (0,
|
|
5923
|
-
const [urlValue, setUrlValue] = (0,
|
|
5924
|
-
const [loading2, setLoading] = (0,
|
|
5925
|
-
const [description, setDescription] = (0,
|
|
5926
|
-
const [priority, setPriority] = (0,
|
|
5927
|
-
const [over, setOver] = (0,
|
|
5928
|
-
const fileInput = (0,
|
|
5929
|
-
const abortRef = (0,
|
|
5930
|
-
const debounceRef = (0,
|
|
6184
|
+
const [replacement, setReplacement] = (0, import_react11.useState)(null);
|
|
6185
|
+
const [urlValue, setUrlValue] = (0, import_react11.useState)("");
|
|
6186
|
+
const [loading2, setLoading] = (0, import_react11.useState)(false);
|
|
6187
|
+
const [description, setDescription] = (0, import_react11.useState)("");
|
|
6188
|
+
const [priority, setPriority] = (0, import_react11.useState)("nice");
|
|
6189
|
+
const [over, setOver] = (0, import_react11.useState)(false);
|
|
6190
|
+
const fileInput = (0, import_react11.useRef)(null);
|
|
6191
|
+
const abortRef = (0, import_react11.useRef)(null);
|
|
6192
|
+
const debounceRef = (0, import_react11.useRef)(null);
|
|
5931
6193
|
const { ref, pos } = useAnchored(editor.element, "bottom", 12);
|
|
5932
6194
|
const image = findImage(editor.element);
|
|
5933
6195
|
const beforeSrc = image?.currentSrc || image?.src || "";
|
|
@@ -5991,7 +6253,7 @@ function ImageEditor({ editor }) {
|
|
|
5991
6253
|
}
|
|
5992
6254
|
}
|
|
5993
6255
|
};
|
|
5994
|
-
(0,
|
|
6256
|
+
(0, import_react11.useEffect)(() => {
|
|
5995
6257
|
if (debounceRef.current !== null) window.clearTimeout(debounceRef.current);
|
|
5996
6258
|
if (urlValue.trim() === "" || replacement !== null) return;
|
|
5997
6259
|
debounceRef.current = window.setTimeout(() => {
|
|
@@ -6001,8 +6263,8 @@ function ImageEditor({ editor }) {
|
|
|
6001
6263
|
if (debounceRef.current !== null) window.clearTimeout(debounceRef.current);
|
|
6002
6264
|
};
|
|
6003
6265
|
}, [urlValue, replacement]);
|
|
6004
|
-
(0,
|
|
6005
|
-
(0,
|
|
6266
|
+
(0, import_react11.useEffect)(() => () => abortRef.current?.abort(), []);
|
|
6267
|
+
(0, import_react11.useEffect)(() => {
|
|
6006
6268
|
const onPaste = (event) => {
|
|
6007
6269
|
const data = event.clipboardData;
|
|
6008
6270
|
if (!data) return;
|
|
@@ -6080,23 +6342,23 @@ function ImageEditor({ editor }) {
|
|
|
6080
6342
|
toast(dispatch, "Image proposal saved", "success");
|
|
6081
6343
|
};
|
|
6082
6344
|
const previewSrc = replacement?.kind === "data" ? replacement.dataUrl : replacement?.url;
|
|
6083
|
-
return /* @__PURE__ */ (0,
|
|
6084
|
-
/* @__PURE__ */ (0,
|
|
6085
|
-
/* @__PURE__ */ (0,
|
|
6345
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { ref, className: "rk-card", style: anchoredStyle(pos), role: "dialog", "aria-label": "Replace image", children: [
|
|
6346
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "rk-card-head", children: [
|
|
6347
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconImage, { size: 14 }),
|
|
6086
6348
|
"Replace image"
|
|
6087
6349
|
] }),
|
|
6088
|
-
/* @__PURE__ */ (0,
|
|
6089
|
-
replacement && previewSrc ? /* @__PURE__ */ (0,
|
|
6090
|
-
/* @__PURE__ */ (0,
|
|
6091
|
-
/* @__PURE__ */ (0,
|
|
6092
|
-
/* @__PURE__ */ (0,
|
|
6350
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "rk-card-body", children: [
|
|
6351
|
+
replacement && previewSrc ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "rk-thumbs", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "rk-thumb-pair", title: "Hover to compare with the current image", children: [
|
|
6352
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("figure", { className: "rk-thumb", children: [
|
|
6353
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("img", { src: beforeSrc, alt: "Current" }),
|
|
6354
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("figcaption", { children: "Before" })
|
|
6093
6355
|
] }),
|
|
6094
|
-
/* @__PURE__ */ (0,
|
|
6095
|
-
/* @__PURE__ */ (0,
|
|
6096
|
-
/* @__PURE__ */ (0,
|
|
6356
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("figure", { className: "rk-thumb", children: [
|
|
6357
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("img", { src: previewSrc, alt: "Proposed replacement" }),
|
|
6358
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("figcaption", { children: replacement.kind === "url" ? "After \xB7 linked" : "After" })
|
|
6097
6359
|
] })
|
|
6098
|
-
] }) }) : /* @__PURE__ */ (0,
|
|
6099
|
-
/* @__PURE__ */ (0,
|
|
6360
|
+
] }) }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
6361
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
6100
6362
|
"button",
|
|
6101
6363
|
{
|
|
6102
6364
|
type: "button",
|
|
@@ -6109,18 +6371,18 @@ function ImageEditor({ editor }) {
|
|
|
6109
6371
|
onDragLeave: () => setOver(false),
|
|
6110
6372
|
onDrop,
|
|
6111
6373
|
children: [
|
|
6112
|
-
/* @__PURE__ */ (0,
|
|
6113
|
-
/* @__PURE__ */ (0,
|
|
6374
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconUpload, { size: 18 }),
|
|
6375
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { children: [
|
|
6114
6376
|
"Drop an image \u2014 from your disk or another tab \u2014",
|
|
6115
|
-
/* @__PURE__ */ (0,
|
|
6377
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("br", {}),
|
|
6116
6378
|
"or click to browse (max 2 MB)"
|
|
6117
6379
|
] })
|
|
6118
6380
|
]
|
|
6119
6381
|
}
|
|
6120
6382
|
),
|
|
6121
|
-
/* @__PURE__ */ (0,
|
|
6122
|
-
loading2 ? /* @__PURE__ */ (0,
|
|
6123
|
-
/* @__PURE__ */ (0,
|
|
6383
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "rk-url", children: [
|
|
6384
|
+
loading2 ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "rk-spinner", "aria-label": "Loading image" }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconLink, { size: 13 }),
|
|
6385
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
6124
6386
|
"input",
|
|
6125
6387
|
{
|
|
6126
6388
|
className: "rk-input",
|
|
@@ -6135,9 +6397,9 @@ function ImageEditor({ editor }) {
|
|
|
6135
6397
|
)
|
|
6136
6398
|
] })
|
|
6137
6399
|
] }),
|
|
6138
|
-
replacement && /* @__PURE__ */ (0,
|
|
6139
|
-
/* @__PURE__ */ (0,
|
|
6140
|
-
/* @__PURE__ */ (0,
|
|
6400
|
+
replacement && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: clearReplacement, children: "Remove replacement" }),
|
|
6401
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("input", { ref: fileInput, type: "file", accept: "image/*", hidden: true, onChange: onPick }),
|
|
6402
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
6141
6403
|
"textarea",
|
|
6142
6404
|
{
|
|
6143
6405
|
className: "rk-textarea",
|
|
@@ -6147,43 +6409,43 @@ function ImageEditor({ editor }) {
|
|
|
6147
6409
|
rows: 2
|
|
6148
6410
|
}
|
|
6149
6411
|
),
|
|
6150
|
-
/* @__PURE__ */ (0,
|
|
6151
|
-
/* @__PURE__ */ (0,
|
|
6152
|
-
/* @__PURE__ */ (0,
|
|
6412
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "rk-seg", role: "group", "aria-label": "Priority", children: [
|
|
6413
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", "aria-pressed": priority === "must", onClick: () => setPriority("must"), children: "Must" }),
|
|
6414
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", "aria-pressed": priority === "nice", onClick: () => setPriority("nice"), children: "Nice to have" })
|
|
6153
6415
|
] })
|
|
6154
6416
|
] }),
|
|
6155
|
-
/* @__PURE__ */ (0,
|
|
6156
|
-
/* @__PURE__ */ (0,
|
|
6157
|
-
/* @__PURE__ */ (0,
|
|
6417
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "rk-card-foot", children: [
|
|
6418
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "rk-hint", children: [
|
|
6419
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "rk-kbd", children: "esc" }),
|
|
6158
6420
|
" cancel"
|
|
6159
6421
|
] }),
|
|
6160
|
-
/* @__PURE__ */ (0,
|
|
6161
|
-
/* @__PURE__ */ (0,
|
|
6162
|
-
/* @__PURE__ */ (0,
|
|
6422
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "rk-actions", children: [
|
|
6423
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => dispatch({ type: "CLOSE_EDITOR" }), children: "Cancel" }),
|
|
6424
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: "rk-btn rk-btn-primary", onClick: save, children: "Save" })
|
|
6163
6425
|
] })
|
|
6164
6426
|
] })
|
|
6165
6427
|
] });
|
|
6166
6428
|
}
|
|
6167
6429
|
|
|
6168
6430
|
// src/client/components/InlineEditor.tsx
|
|
6169
|
-
var
|
|
6170
|
-
var
|
|
6431
|
+
var import_react12 = require("react");
|
|
6432
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
6171
6433
|
function InlineEditor({ editor }) {
|
|
6172
6434
|
const dispatch = useDispatch();
|
|
6173
6435
|
const { route, session } = useStore();
|
|
6174
|
-
const [after, setAfter] = (0,
|
|
6175
|
-
const [priority, setPriority] = (0,
|
|
6176
|
-
const [note, setNote] = (0,
|
|
6177
|
-
const original = (0,
|
|
6178
|
-
const baseline = (0,
|
|
6179
|
-
const [sizeDelta, setSizeDelta] = (0,
|
|
6180
|
-
const [widthDelta, setWidthDelta] = (0,
|
|
6181
|
-
const [clipped, setClipped] = (0,
|
|
6182
|
-
const ringRef = (0,
|
|
6183
|
-
const afterRef = (0,
|
|
6436
|
+
const [after, setAfter] = (0, import_react12.useState)(() => editor.element.innerText);
|
|
6437
|
+
const [priority, setPriority] = (0, import_react12.useState)("nice");
|
|
6438
|
+
const [note, setNote] = (0, import_react12.useState)("");
|
|
6439
|
+
const original = (0, import_react12.useRef)(null);
|
|
6440
|
+
const baseline = (0, import_react12.useRef)(null);
|
|
6441
|
+
const [sizeDelta, setSizeDelta] = (0, import_react12.useState)(0);
|
|
6442
|
+
const [widthDelta, setWidthDelta] = (0, import_react12.useState)(0);
|
|
6443
|
+
const [clipped, setClipped] = (0, import_react12.useState)(false);
|
|
6444
|
+
const ringRef = (0, import_react12.useRef)(null);
|
|
6445
|
+
const afterRef = (0, import_react12.useRef)(null);
|
|
6184
6446
|
const { ref, pos } = useAnchored(editor.element, "bottom", 12);
|
|
6185
6447
|
const element = editor.element;
|
|
6186
|
-
(0,
|
|
6448
|
+
(0, import_react12.useEffect)(() => {
|
|
6187
6449
|
const el = element;
|
|
6188
6450
|
original.current = { html: el.innerHTML, text: el.innerText, styleAttr: el.getAttribute("style") };
|
|
6189
6451
|
const rect = el.getBoundingClientRect();
|
|
@@ -6213,8 +6475,8 @@ function InlineEditor({ editor }) {
|
|
|
6213
6475
|
}
|
|
6214
6476
|
};
|
|
6215
6477
|
}, [element]);
|
|
6216
|
-
const focusedOnce = (0,
|
|
6217
|
-
(0,
|
|
6478
|
+
const focusedOnce = (0, import_react12.useRef)(false);
|
|
6479
|
+
(0, import_react12.useEffect)(() => {
|
|
6218
6480
|
const field = afterRef.current;
|
|
6219
6481
|
if (pos === null || focusedOnce.current || !field) return;
|
|
6220
6482
|
focusedOnce.current = true;
|
|
@@ -6222,7 +6484,7 @@ function InlineEditor({ editor }) {
|
|
|
6222
6484
|
const end = field.value.length;
|
|
6223
6485
|
field.setSelectionRange(end, end);
|
|
6224
6486
|
}, [pos]);
|
|
6225
|
-
(0,
|
|
6487
|
+
(0, import_react12.useEffect)(() => {
|
|
6226
6488
|
const field = afterRef.current;
|
|
6227
6489
|
if (!field) return;
|
|
6228
6490
|
field.style.height = "auto";
|
|
@@ -6232,7 +6494,7 @@ function InlineEditor({ editor }) {
|
|
|
6232
6494
|
setAfter(value);
|
|
6233
6495
|
if (element.innerText !== value) setElementText(element, value);
|
|
6234
6496
|
};
|
|
6235
|
-
(0,
|
|
6497
|
+
(0, import_react12.useEffect)(() => {
|
|
6236
6498
|
let raf = 0;
|
|
6237
6499
|
let lastDelta = 0;
|
|
6238
6500
|
let lastWidth = 0;
|
|
@@ -6302,7 +6564,7 @@ function InlineEditor({ editor }) {
|
|
|
6302
6564
|
cancel();
|
|
6303
6565
|
}
|
|
6304
6566
|
};
|
|
6305
|
-
(0,
|
|
6567
|
+
(0, import_react12.useEffect)(() => {
|
|
6306
6568
|
const el = element;
|
|
6307
6569
|
const onKeyDown = (event) => {
|
|
6308
6570
|
if (event.key === "Enter" && !event.shiftKey) {
|
|
@@ -6320,19 +6582,19 @@ function InlineEditor({ editor }) {
|
|
|
6320
6582
|
});
|
|
6321
6583
|
const before = original.current?.text ?? "";
|
|
6322
6584
|
const delta = after.length - before.length;
|
|
6323
|
-
return /* @__PURE__ */ (0,
|
|
6324
|
-
/* @__PURE__ */ (0,
|
|
6325
|
-
/* @__PURE__ */ (0,
|
|
6326
|
-
/* @__PURE__ */ (0,
|
|
6327
|
-
/* @__PURE__ */ (0,
|
|
6585
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
6586
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { ref: ringRef, className: "rk-edit-ring" }),
|
|
6587
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { ref, className: "rk-card", style: anchoredStyle(pos), role: "dialog", "aria-label": "Rewrite text", children: [
|
|
6588
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "rk-card-head", children: [
|
|
6589
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconText, { size: 14 }),
|
|
6328
6590
|
"Rewrite text",
|
|
6329
|
-
/* @__PURE__ */ (0,
|
|
6330
|
-
/* @__PURE__ */ (0,
|
|
6591
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "rk-spacer" }),
|
|
6592
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "rk-delta", "aria-live": "polite", children: [
|
|
6331
6593
|
before.length,
|
|
6332
6594
|
" \u2192 ",
|
|
6333
6595
|
after.length,
|
|
6334
6596
|
" ",
|
|
6335
|
-
delta !== 0 && /* @__PURE__ */ (0,
|
|
6597
|
+
delta !== 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: delta > 0 ? "rk-plus" : "rk-minus", children: [
|
|
6336
6598
|
"(",
|
|
6337
6599
|
delta > 0 ? "+" : "",
|
|
6338
6600
|
delta,
|
|
@@ -6340,15 +6602,15 @@ function InlineEditor({ editor }) {
|
|
|
6340
6602
|
] })
|
|
6341
6603
|
] })
|
|
6342
6604
|
] }),
|
|
6343
|
-
/* @__PURE__ */ (0,
|
|
6344
|
-
/* @__PURE__ */ (0,
|
|
6345
|
-
/* @__PURE__ */ (0,
|
|
6346
|
-
/* @__PURE__ */ (0,
|
|
6347
|
-
/* @__PURE__ */ (0,
|
|
6605
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "rk-card-body", children: [
|
|
6606
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "rk-diff", "aria-label": "Before and after", children: [
|
|
6607
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "rk-diff-row rk-diff-before", children: [
|
|
6608
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "rk-diff-tag", children: "Before" }),
|
|
6609
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "rk-diff-text", children: before })
|
|
6348
6610
|
] }),
|
|
6349
|
-
/* @__PURE__ */ (0,
|
|
6350
|
-
/* @__PURE__ */ (0,
|
|
6351
|
-
/* @__PURE__ */ (0,
|
|
6611
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "rk-diff-row rk-diff-after", children: [
|
|
6612
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "rk-diff-tag", children: "After" }),
|
|
6613
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
6352
6614
|
"textarea",
|
|
6353
6615
|
{
|
|
6354
6616
|
ref: afterRef,
|
|
@@ -6362,11 +6624,11 @@ function InlineEditor({ editor }) {
|
|
|
6362
6624
|
)
|
|
6363
6625
|
] })
|
|
6364
6626
|
] }),
|
|
6365
|
-
(Math.abs(sizeDelta) > 2 || Math.abs(widthDelta) > 4 || clipped) && /* @__PURE__ */ (0,
|
|
6627
|
+
(Math.abs(sizeDelta) > 2 || Math.abs(widthDelta) > 4 || clipped) && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "rk-size-note", role: "status", children: [
|
|
6366
6628
|
Math.abs(sizeDelta) > 2 && (() => {
|
|
6367
6629
|
const lines = baseline.current ? Math.round(Math.abs(sizeDelta) / baseline.current.lineHeight) : 0;
|
|
6368
6630
|
const lineNote = lines >= 1 ? ` (~${lines} line${lines === 1 ? "" : "s"})` : "";
|
|
6369
|
-
return /* @__PURE__ */ (0,
|
|
6631
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { children: [
|
|
6370
6632
|
"Block ",
|
|
6371
6633
|
sizeDelta > 0 ? "grew" : "shrank",
|
|
6372
6634
|
" by ",
|
|
@@ -6376,16 +6638,16 @@ function InlineEditor({ editor }) {
|
|
|
6376
6638
|
" \u2014 as it would with this text live."
|
|
6377
6639
|
] });
|
|
6378
6640
|
})(),
|
|
6379
|
-
Math.abs(sizeDelta) <= 2 && Math.abs(widthDelta) > 4 && /* @__PURE__ */ (0,
|
|
6641
|
+
Math.abs(sizeDelta) <= 2 && Math.abs(widthDelta) > 4 && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { children: [
|
|
6380
6642
|
"Block got ",
|
|
6381
6643
|
widthDelta > 0 ? "wider" : "narrower",
|
|
6382
6644
|
" by ",
|
|
6383
6645
|
Math.abs(widthDelta),
|
|
6384
6646
|
" px \u2014 as it would with this text live."
|
|
6385
6647
|
] }),
|
|
6386
|
-
clipped && /* @__PURE__ */ (0,
|
|
6648
|
+
clipped && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "rk-clip-note", children: "Text exceeds the visible crop here and will be cut off." })
|
|
6387
6649
|
] }),
|
|
6388
|
-
/* @__PURE__ */ (0,
|
|
6650
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
6389
6651
|
"input",
|
|
6390
6652
|
{
|
|
6391
6653
|
className: "rk-input",
|
|
@@ -6394,24 +6656,24 @@ function InlineEditor({ editor }) {
|
|
|
6394
6656
|
onChange: (event) => setNote(event.target.value)
|
|
6395
6657
|
}
|
|
6396
6658
|
),
|
|
6397
|
-
/* @__PURE__ */ (0,
|
|
6398
|
-
/* @__PURE__ */ (0,
|
|
6399
|
-
/* @__PURE__ */ (0,
|
|
6659
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "rk-seg", role: "group", "aria-label": "Priority", children: [
|
|
6660
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", "aria-pressed": priority === "must", onClick: () => setPriority("must"), children: "Must" }),
|
|
6661
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", "aria-pressed": priority === "nice", onClick: () => setPriority("nice"), children: "Nice to have" })
|
|
6400
6662
|
] })
|
|
6401
6663
|
] }),
|
|
6402
|
-
/* @__PURE__ */ (0,
|
|
6403
|
-
/* @__PURE__ */ (0,
|
|
6404
|
-
/* @__PURE__ */ (0,
|
|
6664
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "rk-card-foot", children: [
|
|
6665
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "rk-hint", children: [
|
|
6666
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "rk-kbd", children: "\u21B5" }),
|
|
6405
6667
|
" save \xB7 ",
|
|
6406
|
-
/* @__PURE__ */ (0,
|
|
6668
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "rk-kbd", children: "\u21E7\u21B5" }),
|
|
6407
6669
|
" newline \xB7",
|
|
6408
6670
|
" ",
|
|
6409
|
-
/* @__PURE__ */ (0,
|
|
6671
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "rk-kbd", children: "esc" }),
|
|
6410
6672
|
" cancel"
|
|
6411
6673
|
] }),
|
|
6412
|
-
/* @__PURE__ */ (0,
|
|
6413
|
-
/* @__PURE__ */ (0,
|
|
6414
|
-
/* @__PURE__ */ (0,
|
|
6674
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "rk-actions", children: [
|
|
6675
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: cancel, children: "Cancel" }),
|
|
6676
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", className: "rk-btn rk-btn-primary", onClick: commit, children: "Save" })
|
|
6415
6677
|
] })
|
|
6416
6678
|
] })
|
|
6417
6679
|
] })
|
|
@@ -6419,8 +6681,8 @@ function InlineEditor({ editor }) {
|
|
|
6419
6681
|
}
|
|
6420
6682
|
|
|
6421
6683
|
// src/client/components/NoteComposer.tsx
|
|
6422
|
-
var
|
|
6423
|
-
var
|
|
6684
|
+
var import_react13 = require("react");
|
|
6685
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
6424
6686
|
var TITLES = {
|
|
6425
6687
|
comment: "Comment",
|
|
6426
6688
|
delete: "Mark for deletion",
|
|
@@ -6436,14 +6698,14 @@ var PLACEHOLDERS = {
|
|
|
6436
6698
|
function NoteComposer({ editor }) {
|
|
6437
6699
|
const dispatch = useDispatch();
|
|
6438
6700
|
const { route, session } = useStore();
|
|
6439
|
-
const [text, setText] = (0,
|
|
6440
|
-
const [direction, setDirection] = (0,
|
|
6441
|
-
const [priority, setPriority] = (0,
|
|
6442
|
-
const textareaRef = (0,
|
|
6701
|
+
const [text, setText] = (0, import_react13.useState)("");
|
|
6702
|
+
const [direction, setDirection] = (0, import_react13.useState)(void 0);
|
|
6703
|
+
const [priority, setPriority] = (0, import_react13.useState)("nice");
|
|
6704
|
+
const textareaRef = (0, import_react13.useRef)(null);
|
|
6443
6705
|
const { ref, pos } = useAnchored(editor.element, "bottom", 12);
|
|
6444
6706
|
const { kind } = editor;
|
|
6445
|
-
const focusedOnce = (0,
|
|
6446
|
-
(0,
|
|
6707
|
+
const focusedOnce = (0, import_react13.useRef)(false);
|
|
6708
|
+
(0, import_react13.useEffect)(() => {
|
|
6447
6709
|
const field = textareaRef.current;
|
|
6448
6710
|
if (pos === null || focusedOnce.current || !field) return;
|
|
6449
6711
|
focusedOnce.current = true;
|
|
@@ -6502,13 +6764,13 @@ function NoteComposer({ editor }) {
|
|
|
6502
6764
|
save();
|
|
6503
6765
|
}
|
|
6504
6766
|
};
|
|
6505
|
-
return /* @__PURE__ */ (0,
|
|
6506
|
-
/* @__PURE__ */ (0,
|
|
6767
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { ref, className: "rk-card", style: anchoredStyle(pos), role: "dialog", "aria-label": TITLES[kind], children: [
|
|
6768
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "rk-card-head", children: [
|
|
6507
6769
|
iconForType(kind),
|
|
6508
6770
|
TITLES[kind]
|
|
6509
6771
|
] }),
|
|
6510
|
-
/* @__PURE__ */ (0,
|
|
6511
|
-
kind === "move" && /* @__PURE__ */ (0,
|
|
6772
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "rk-card-body", children: [
|
|
6773
|
+
kind === "move" && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "rk-seg", role: "group", "aria-label": "Direction", children: ["up", "down", "first", "last"].map((option) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
6512
6774
|
"button",
|
|
6513
6775
|
{
|
|
6514
6776
|
type: "button",
|
|
@@ -6518,7 +6780,7 @@ function NoteComposer({ editor }) {
|
|
|
6518
6780
|
},
|
|
6519
6781
|
option
|
|
6520
6782
|
)) }),
|
|
6521
|
-
/* @__PURE__ */ (0,
|
|
6783
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
6522
6784
|
"textarea",
|
|
6523
6785
|
{
|
|
6524
6786
|
ref: textareaRef,
|
|
@@ -6530,29 +6792,29 @@ function NoteComposer({ editor }) {
|
|
|
6530
6792
|
rows: 3
|
|
6531
6793
|
}
|
|
6532
6794
|
),
|
|
6533
|
-
/* @__PURE__ */ (0,
|
|
6534
|
-
/* @__PURE__ */ (0,
|
|
6535
|
-
/* @__PURE__ */ (0,
|
|
6795
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "rk-seg", role: "group", "aria-label": "Priority", children: [
|
|
6796
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", "aria-pressed": priority === "must", onClick: () => setPriority("must"), children: "Must" }),
|
|
6797
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", "aria-pressed": priority === "nice", onClick: () => setPriority("nice"), children: "Nice to have" })
|
|
6536
6798
|
] })
|
|
6537
6799
|
] }),
|
|
6538
|
-
/* @__PURE__ */ (0,
|
|
6539
|
-
/* @__PURE__ */ (0,
|
|
6540
|
-
/* @__PURE__ */ (0,
|
|
6800
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "rk-card-foot", children: [
|
|
6801
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "rk-hint", children: [
|
|
6802
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "rk-kbd", children: "\u2318\u21B5" }),
|
|
6541
6803
|
" save \xB7 ",
|
|
6542
|
-
/* @__PURE__ */ (0,
|
|
6804
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "rk-kbd", children: "esc" }),
|
|
6543
6805
|
" cancel"
|
|
6544
6806
|
] }),
|
|
6545
|
-
/* @__PURE__ */ (0,
|
|
6546
|
-
/* @__PURE__ */ (0,
|
|
6547
|
-
/* @__PURE__ */ (0,
|
|
6807
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "rk-actions", children: [
|
|
6808
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => dispatch({ type: "CLOSE_EDITOR" }), children: "Cancel" }),
|
|
6809
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", className: "rk-btn rk-btn-primary", onClick: save, children: "Save" })
|
|
6548
6810
|
] })
|
|
6549
6811
|
] })
|
|
6550
6812
|
] });
|
|
6551
6813
|
}
|
|
6552
6814
|
|
|
6553
6815
|
// src/client/components/Panel.tsx
|
|
6554
|
-
var
|
|
6555
|
-
var
|
|
6816
|
+
var import_react14 = require("react");
|
|
6817
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
6556
6818
|
function changeSummary(item) {
|
|
6557
6819
|
if (isCopyItem(item)) return `\u201C${item.payload.after}\u201D`;
|
|
6558
6820
|
if (isImageItem(item)) {
|
|
@@ -6634,24 +6896,24 @@ function formatBytes(bytes) {
|
|
|
6634
6896
|
function CopyDiff({ before, after }) {
|
|
6635
6897
|
const parts = diffParts(before, after);
|
|
6636
6898
|
const delta = after.length - before.length;
|
|
6637
|
-
return /* @__PURE__ */ (0,
|
|
6638
|
-
/* @__PURE__ */ (0,
|
|
6639
|
-
/* @__PURE__ */ (0,
|
|
6640
|
-
/* @__PURE__ */ (0,
|
|
6899
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rk-diffview", children: [
|
|
6900
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rk-diff-row rk-diff-before", children: [
|
|
6901
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rk-diff-tag", children: "Before" }),
|
|
6902
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "rk-diff-text", children: [
|
|
6641
6903
|
parts.prefix,
|
|
6642
|
-
parts.delMid && /* @__PURE__ */ (0,
|
|
6904
|
+
parts.delMid && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("mark", { className: "rk-del", children: parts.delMid }),
|
|
6643
6905
|
parts.suffix
|
|
6644
6906
|
] })
|
|
6645
6907
|
] }),
|
|
6646
|
-
/* @__PURE__ */ (0,
|
|
6647
|
-
/* @__PURE__ */ (0,
|
|
6648
|
-
/* @__PURE__ */ (0,
|
|
6908
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rk-diff-row rk-diff-after", children: [
|
|
6909
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rk-diff-tag", children: "After" }),
|
|
6910
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "rk-diff-text", children: [
|
|
6649
6911
|
parts.prefix,
|
|
6650
|
-
parts.insMid && /* @__PURE__ */ (0,
|
|
6912
|
+
parts.insMid && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("mark", { className: "rk-ins", children: parts.insMid }),
|
|
6651
6913
|
parts.suffix
|
|
6652
6914
|
] })
|
|
6653
6915
|
] }),
|
|
6654
|
-
/* @__PURE__ */ (0,
|
|
6916
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rk-diff-len", children: [
|
|
6655
6917
|
before.length,
|
|
6656
6918
|
" \u2192 ",
|
|
6657
6919
|
after.length,
|
|
@@ -6662,8 +6924,8 @@ function CopyDiff({ before, after }) {
|
|
|
6662
6924
|
}
|
|
6663
6925
|
function ImageDetail({ beforeSrc, afterSrc, afterDataUrl }) {
|
|
6664
6926
|
const replacement = afterDataUrl ?? afterSrc;
|
|
6665
|
-
const [dims, setDims] = (0,
|
|
6666
|
-
(0,
|
|
6927
|
+
const [dims, setDims] = (0, import_react14.useState)("");
|
|
6928
|
+
(0, import_react14.useEffect)(() => {
|
|
6667
6929
|
if (!replacement) return;
|
|
6668
6930
|
const img = new Image();
|
|
6669
6931
|
img.onload = () => setDims(`${img.naturalWidth}\xD7${img.naturalHeight}px`);
|
|
@@ -6688,55 +6950,67 @@ function ImageDetail({ beforeSrc, afterSrc, afterDataUrl }) {
|
|
|
6688
6950
|
window.open(replacement, "_blank", "noopener");
|
|
6689
6951
|
}
|
|
6690
6952
|
};
|
|
6691
|
-
return /* @__PURE__ */ (0,
|
|
6692
|
-
/* @__PURE__ */ (0,
|
|
6693
|
-
/* @__PURE__ */ (0,
|
|
6694
|
-
beforeSrc ? /* @__PURE__ */ (0,
|
|
6695
|
-
/* @__PURE__ */ (0,
|
|
6953
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rk-imgdetail", children: [
|
|
6954
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rk-thumbs", children: [
|
|
6955
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("figure", { className: "rk-thumb", children: [
|
|
6956
|
+
beforeSrc ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("img", { src: beforeSrc, alt: "Current" }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "rk-thumb-missing", children: "no image" }),
|
|
6957
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("figcaption", { children: "Before" })
|
|
6696
6958
|
] }),
|
|
6697
|
-
/* @__PURE__ */ (0,
|
|
6698
|
-
/* @__PURE__ */ (0,
|
|
6699
|
-
/* @__PURE__ */ (0,
|
|
6959
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("figure", { className: "rk-thumb", children: [
|
|
6960
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("img", { src: replacement, alt: "Proposed replacement" }),
|
|
6961
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("figcaption", { children: [
|
|
6700
6962
|
"After",
|
|
6701
6963
|
embedded ? "" : " \xB7 linked"
|
|
6702
6964
|
] })
|
|
6703
6965
|
] })
|
|
6704
6966
|
] }),
|
|
6705
|
-
/* @__PURE__ */ (0,
|
|
6967
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rk-imgdetail-meta", children: [
|
|
6706
6968
|
embedded ? "Embedded image" : "Linked image",
|
|
6707
6969
|
dims ? ` \xB7 ${dims}` : "",
|
|
6708
6970
|
bytes !== null ? ` \xB7 ${formatBytes(bytes)}` : ""
|
|
6709
6971
|
] }),
|
|
6710
|
-
!embedded && afterSrc && /* @__PURE__ */ (0,
|
|
6711
|
-
/* @__PURE__ */ (0,
|
|
6712
|
-
/* @__PURE__ */ (0,
|
|
6713
|
-
/* @__PURE__ */ (0,
|
|
6972
|
+
!embedded && afterSrc && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("a", { className: "rk-imgdetail-url", href: afterSrc, target: "_blank", rel: "noopener noreferrer", title: afterSrc, children: afterSrc }),
|
|
6973
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rk-imgdetail-actions", children: [
|
|
6974
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => void download(), children: [
|
|
6975
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconDownload, { size: 12 }),
|
|
6714
6976
|
" Download"
|
|
6715
6977
|
] }),
|
|
6716
|
-
/* @__PURE__ */ (0,
|
|
6978
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => window.open(replacement, "_blank", "noopener"), children: "Open" })
|
|
6717
6979
|
] })
|
|
6718
6980
|
] });
|
|
6719
6981
|
}
|
|
6982
|
+
var SYNC_REASON_LABEL = {
|
|
6983
|
+
"token-short": "token too short",
|
|
6984
|
+
"bad-token": "token rejected",
|
|
6985
|
+
"room-full": "room full",
|
|
6986
|
+
unreachable: "server unreachable"
|
|
6987
|
+
};
|
|
6988
|
+
var SYNC_REASON_HELP = {
|
|
6989
|
+
"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.",
|
|
6990
|
+
"bad-token": "The sync server rejected the token. Check `syncToken` / `token` in <ReviewKit />.",
|
|
6991
|
+
"room-full": "This page already has the maximum number of reviewers online (16). Try again later.",
|
|
6992
|
+
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."
|
|
6993
|
+
};
|
|
6720
6994
|
function Panel() {
|
|
6721
|
-
const { session, panelOpen, activeItemId, badgeCorner, undoStack, preview, unapplied, syncStatus, emblemaPush, peers } = useStore();
|
|
6995
|
+
const { session, panelOpen, activeItemId, badgeCorner, undoStack, preview, unapplied, syncStatus, syncReason, emblemaPush, peers } = useStore();
|
|
6722
6996
|
const dispatch = useDispatch();
|
|
6723
6997
|
const config = useConfig();
|
|
6724
|
-
const [sticky, setStickyState] = (0,
|
|
6725
|
-
const [query, setQuery] = (0,
|
|
6726
|
-
const [typeFilter, setTypeFilter] = (0,
|
|
6727
|
-
const [prioFilter, setPrioFilter] = (0,
|
|
6728
|
-
const [statusFilter, setStatusFilter] = (0,
|
|
6729
|
-
const [filterOpen, setFilterOpen] = (0,
|
|
6730
|
-
const [settingsOpen, setSettingsOpen] = (0,
|
|
6731
|
-
const [emblemaAlive, setEmblemaAlive] = (0,
|
|
6732
|
-
const [emblemaSending, setEmblemaSending] = (0,
|
|
6733
|
-
const [emblemaSync, setEmblemaSync] = (0,
|
|
6734
|
-
const panelRef = (0,
|
|
6735
|
-
const searchRef = (0,
|
|
6736
|
-
const importRef = (0,
|
|
6737
|
-
const sheetDrag = (0,
|
|
6738
|
-
const items = (0,
|
|
6739
|
-
const { orphanIds, hiddenIds } = (0,
|
|
6998
|
+
const [sticky, setStickyState] = (0, import_react14.useState)(() => isStickyEnabled(config.token));
|
|
6999
|
+
const [query, setQuery] = (0, import_react14.useState)("");
|
|
7000
|
+
const [typeFilter, setTypeFilter] = (0, import_react14.useState)(/* @__PURE__ */ new Set());
|
|
7001
|
+
const [prioFilter, setPrioFilter] = (0, import_react14.useState)(/* @__PURE__ */ new Set());
|
|
7002
|
+
const [statusFilter, setStatusFilter] = (0, import_react14.useState)(/* @__PURE__ */ new Set());
|
|
7003
|
+
const [filterOpen, setFilterOpen] = (0, import_react14.useState)(false);
|
|
7004
|
+
const [settingsOpen, setSettingsOpen] = (0, import_react14.useState)(false);
|
|
7005
|
+
const [emblemaAlive, setEmblemaAlive] = (0, import_react14.useState)(null);
|
|
7006
|
+
const [emblemaSending, setEmblemaSending] = (0, import_react14.useState)(false);
|
|
7007
|
+
const [emblemaSync, setEmblemaSync] = (0, import_react14.useState)("unknown");
|
|
7008
|
+
const panelRef = (0, import_react14.useRef)(null);
|
|
7009
|
+
const searchRef = (0, import_react14.useRef)(null);
|
|
7010
|
+
const importRef = (0, import_react14.useRef)(null);
|
|
7011
|
+
const sheetDrag = (0, import_react14.useRef)(null);
|
|
7012
|
+
const items = (0, import_react14.useMemo)(() => session?.items ?? [], [session]);
|
|
7013
|
+
const { orphanIds, hiddenIds } = (0, import_react14.useMemo)(() => {
|
|
6740
7014
|
const orphans = /* @__PURE__ */ new Set();
|
|
6741
7015
|
const hiddens = /* @__PURE__ */ new Set();
|
|
6742
7016
|
for (const item of items) {
|
|
@@ -6747,15 +7021,15 @@ function Panel() {
|
|
|
6747
7021
|
}
|
|
6748
7022
|
return { orphanIds: orphans, hiddenIds: hiddens };
|
|
6749
7023
|
}, [items, panelOpen]);
|
|
6750
|
-
const activeFilter = (0,
|
|
7024
|
+
const activeFilter = (0, import_react14.useMemo)(
|
|
6751
7025
|
() => typeFilter.size + prioFilter.size + statusFilter.size > 0 ? { types: [...typeFilter], priorities: [...prioFilter], statuses: [...statusFilter] } : null,
|
|
6752
7026
|
[typeFilter, prioFilter, statusFilter]
|
|
6753
7027
|
);
|
|
6754
|
-
(0,
|
|
7028
|
+
(0, import_react14.useEffect)(() => {
|
|
6755
7029
|
dispatch({ type: "SET_FILTER", filter: activeFilter });
|
|
6756
7030
|
return () => dispatch({ type: "SET_FILTER", filter: null });
|
|
6757
7031
|
}, [activeFilter, dispatch]);
|
|
6758
|
-
const filtered = (0,
|
|
7032
|
+
const filtered = (0, import_react14.useMemo)(() => {
|
|
6759
7033
|
const q = query.trim().toLowerCase();
|
|
6760
7034
|
return items.map((item, index) => ({ item, number: index + 1 })).filter(({ item }) => {
|
|
6761
7035
|
if (!itemMatchesFilter(item, activeFilter)) return false;
|
|
@@ -6764,22 +7038,22 @@ function Panel() {
|
|
|
6764
7038
|
return haystack.includes(q);
|
|
6765
7039
|
});
|
|
6766
7040
|
}, [items, query, activeFilter]);
|
|
6767
|
-
const typeCounts = (0,
|
|
7041
|
+
const typeCounts = (0, import_react14.useMemo)(() => {
|
|
6768
7042
|
const counts = /* @__PURE__ */ new Map();
|
|
6769
7043
|
for (const item of items) counts.set(item.type, (counts.get(item.type) ?? 0) + 1);
|
|
6770
7044
|
return counts;
|
|
6771
7045
|
}, [items]);
|
|
6772
|
-
const prioCounts = (0,
|
|
7046
|
+
const prioCounts = (0, import_react14.useMemo)(() => {
|
|
6773
7047
|
const counts = /* @__PURE__ */ new Map();
|
|
6774
7048
|
for (const item of items) counts.set(item.priority, (counts.get(item.priority) ?? 0) + 1);
|
|
6775
7049
|
return counts;
|
|
6776
7050
|
}, [items]);
|
|
6777
|
-
const statusCounts = (0,
|
|
7051
|
+
const statusCounts = (0, import_react14.useMemo)(() => {
|
|
6778
7052
|
const counts = /* @__PURE__ */ new Map();
|
|
6779
7053
|
for (const item of items) counts.set(item.status, (counts.get(item.status) ?? 0) + 1);
|
|
6780
7054
|
return counts;
|
|
6781
7055
|
}, [items]);
|
|
6782
|
-
const groups = (0,
|
|
7056
|
+
const groups = (0, import_react14.useMemo)(() => {
|
|
6783
7057
|
const map = /* @__PURE__ */ new Map();
|
|
6784
7058
|
for (const entry of filtered) {
|
|
6785
7059
|
const list = map.get(entry.item.route) ?? [];
|
|
@@ -6788,7 +7062,7 @@ function Panel() {
|
|
|
6788
7062
|
}
|
|
6789
7063
|
return Array.from(map.entries());
|
|
6790
7064
|
}, [filtered]);
|
|
6791
|
-
(0,
|
|
7065
|
+
(0, import_react14.useEffect)(() => {
|
|
6792
7066
|
if (!filterOpen && !settingsOpen) return;
|
|
6793
7067
|
const onDown = (event) => {
|
|
6794
7068
|
const path = event.composedPath();
|
|
@@ -6799,7 +7073,7 @@ function Panel() {
|
|
|
6799
7073
|
document.addEventListener("pointerdown", onDown, true);
|
|
6800
7074
|
return () => document.removeEventListener("pointerdown", onDown, true);
|
|
6801
7075
|
}, [filterOpen, settingsOpen]);
|
|
6802
|
-
(0,
|
|
7076
|
+
(0, import_react14.useEffect)(() => {
|
|
6803
7077
|
if (!settingsOpen) return;
|
|
6804
7078
|
let alive = true;
|
|
6805
7079
|
const probe = () => {
|
|
@@ -6823,7 +7097,7 @@ function Panel() {
|
|
|
6823
7097
|
live: "paired",
|
|
6824
7098
|
off: "not paired"
|
|
6825
7099
|
}[emblemaPairState];
|
|
6826
|
-
(0,
|
|
7100
|
+
(0, import_react14.useEffect)(() => {
|
|
6827
7101
|
if (!panelOpen || activeItemId === null) return;
|
|
6828
7102
|
const row = panelRef.current?.querySelector(`[data-item-id="${activeItemId}"]`);
|
|
6829
7103
|
row?.scrollIntoView({ block: "nearest" });
|
|
@@ -6939,7 +7213,7 @@ function Panel() {
|
|
|
6939
7213
|
panel.style.transform = "";
|
|
6940
7214
|
if (dy > 110) dispatch({ type: "SET_PANEL", open: false });
|
|
6941
7215
|
};
|
|
6942
|
-
return /* @__PURE__ */ (0,
|
|
7216
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
6943
7217
|
"div",
|
|
6944
7218
|
{
|
|
6945
7219
|
ref: panelRef,
|
|
@@ -6949,7 +7223,7 @@ function Panel() {
|
|
|
6949
7223
|
"aria-label": "Review feedback panel",
|
|
6950
7224
|
onKeyDown,
|
|
6951
7225
|
children: [
|
|
6952
|
-
/* @__PURE__ */ (0,
|
|
7226
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
6953
7227
|
"div",
|
|
6954
7228
|
{
|
|
6955
7229
|
className: "rk-sheet-handle",
|
|
@@ -6960,34 +7234,41 @@ function Panel() {
|
|
|
6960
7234
|
onPointerCancel: onSheetHandleUp
|
|
6961
7235
|
}
|
|
6962
7236
|
),
|
|
6963
|
-
/* @__PURE__ */ (0,
|
|
6964
|
-
/* @__PURE__ */ (0,
|
|
6965
|
-
/* @__PURE__ */ (0,
|
|
6966
|
-
/* @__PURE__ */ (0,
|
|
7237
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rk-panel-head", children: [
|
|
7238
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
|
|
7239
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "rk-panel-title", children: "Feedback" }),
|
|
7240
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rk-panel-sub", children: [
|
|
6967
7241
|
items.length,
|
|
6968
7242
|
" item",
|
|
6969
7243
|
items.length === 1 ? "" : "s",
|
|
6970
7244
|
session.author ? ` \xB7 ${session.author}` : "",
|
|
6971
|
-
syncStatus !== "disabled" && /* @__PURE__ */ (0,
|
|
6972
|
-
|
|
6973
|
-
|
|
6974
|
-
|
|
6975
|
-
|
|
7245
|
+
syncStatus !== "disabled" && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
7246
|
+
"span",
|
|
7247
|
+
{
|
|
7248
|
+
className: `rk-sync rk-sync-${syncStatus}${syncReason ? ` rk-sync-reason-${syncReason}` : ""}`,
|
|
7249
|
+
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"],
|
|
7250
|
+
children: [
|
|
7251
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rk-sync-dot" }),
|
|
7252
|
+
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"]}`
|
|
7253
|
+
]
|
|
7254
|
+
}
|
|
7255
|
+
),
|
|
7256
|
+
config.emblema && emblemaPush !== "idle" && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
6976
7257
|
"span",
|
|
6977
7258
|
{
|
|
6978
7259
|
className: `rk-sync rk-epush-${emblemaPush}`,
|
|
6979
7260
|
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",
|
|
6980
7261
|
children: [
|
|
6981
|
-
/* @__PURE__ */ (0,
|
|
7262
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rk-sync-dot" }),
|
|
6982
7263
|
emblemaPush === "ok" ? "emblema" : emblemaPush === "sending" ? "emblema\u2026" : emblemaPush === "rejected" ? "emblema rejected" : "emblema offline"
|
|
6983
7264
|
]
|
|
6984
7265
|
}
|
|
6985
7266
|
)
|
|
6986
7267
|
] })
|
|
6987
7268
|
] }),
|
|
6988
|
-
/* @__PURE__ */ (0,
|
|
6989
|
-
/* @__PURE__ */ (0,
|
|
6990
|
-
/* @__PURE__ */ (0,
|
|
7269
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rk-spacer" }),
|
|
7270
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rk-menu-scope rk-menu-anchor", children: [
|
|
7271
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
6991
7272
|
"button",
|
|
6992
7273
|
{
|
|
6993
7274
|
type: "button",
|
|
@@ -7003,11 +7284,11 @@ function Panel() {
|
|
|
7003
7284
|
void pingEmblema(config.emblema).then((port) => setEmblemaAlive(port !== null));
|
|
7004
7285
|
}
|
|
7005
7286
|
},
|
|
7006
|
-
children: /* @__PURE__ */ (0,
|
|
7287
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconGear, { size: 15 })
|
|
7007
7288
|
}
|
|
7008
7289
|
),
|
|
7009
|
-
settingsOpen && /* @__PURE__ */ (0,
|
|
7010
|
-
config.token && /* @__PURE__ */ (0,
|
|
7290
|
+
settingsOpen && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rk-menu", role: "menu", "aria-label": "Session settings", children: [
|
|
7291
|
+
config.token && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
7011
7292
|
"button",
|
|
7012
7293
|
{
|
|
7013
7294
|
type: "button",
|
|
@@ -7022,12 +7303,12 @@ function Panel() {
|
|
|
7022
7303
|
toast(dispatch, next ? "Review stays on in this tab" : "Review active only via the link", "info");
|
|
7023
7304
|
},
|
|
7024
7305
|
children: [
|
|
7025
|
-
/* @__PURE__ */ (0,
|
|
7306
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: `rk-menu-check${sticky ? " rk-on" : ""}` }),
|
|
7026
7307
|
"Keep review on in this tab"
|
|
7027
7308
|
]
|
|
7028
7309
|
}
|
|
7029
7310
|
),
|
|
7030
|
-
config.emblema && /* @__PURE__ */ (0,
|
|
7311
|
+
config.emblema && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
7031
7312
|
"button",
|
|
7032
7313
|
{
|
|
7033
7314
|
type: "button",
|
|
@@ -7057,7 +7338,7 @@ function Panel() {
|
|
|
7057
7338
|
}).finally(() => setEmblemaSending(false));
|
|
7058
7339
|
},
|
|
7059
7340
|
children: [
|
|
7060
|
-
/* @__PURE__ */ (0,
|
|
7341
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
7061
7342
|
"span",
|
|
7062
7343
|
{
|
|
7063
7344
|
className: "rk-emblema-dot",
|
|
@@ -7068,25 +7349,40 @@ function Panel() {
|
|
|
7068
7349
|
]
|
|
7069
7350
|
}
|
|
7070
7351
|
),
|
|
7071
|
-
/* @__PURE__ */ (0,
|
|
7352
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
7072
7353
|
"button",
|
|
7073
7354
|
{
|
|
7074
7355
|
type: "button",
|
|
7075
7356
|
role: "menuitem",
|
|
7076
7357
|
className: "rk-menu-item",
|
|
7077
|
-
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",
|
|
7358
|
+
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",
|
|
7078
7359
|
onClick: () => {
|
|
7079
7360
|
setSettingsOpen(false);
|
|
7080
7361
|
dispatch({ type: "SET_EMBLEMA_CONNECT", open: true });
|
|
7081
7362
|
},
|
|
7082
7363
|
children: [
|
|
7083
|
-
/* @__PURE__ */ (0,
|
|
7364
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rk-emblema-dot", "data-state": emblemaPairState }),
|
|
7084
7365
|
"Connect to Emblema\u2026",
|
|
7085
|
-
/* @__PURE__ */ (0,
|
|
7366
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rk-menu-count", children: emblemaPairLabel })
|
|
7086
7367
|
]
|
|
7087
7368
|
}
|
|
7088
7369
|
),
|
|
7089
|
-
/* @__PURE__ */ (0,
|
|
7370
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
7371
|
+
"button",
|
|
7372
|
+
{
|
|
7373
|
+
type: "button",
|
|
7374
|
+
role: "menuitem",
|
|
7375
|
+
className: "rk-menu-item",
|
|
7376
|
+
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",
|
|
7377
|
+
disabled: !resolveSyncToken(config),
|
|
7378
|
+
onClick: () => {
|
|
7379
|
+
setSettingsOpen(false);
|
|
7380
|
+
dispatch({ type: "SET_TERMINAL_CONNECT", open: true });
|
|
7381
|
+
},
|
|
7382
|
+
children: "Connect terminal / agent\u2026"
|
|
7383
|
+
}
|
|
7384
|
+
),
|
|
7385
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
7090
7386
|
"button",
|
|
7091
7387
|
{
|
|
7092
7388
|
type: "button",
|
|
@@ -7099,31 +7395,31 @@ function Panel() {
|
|
|
7099
7395
|
)
|
|
7100
7396
|
] })
|
|
7101
7397
|
] }),
|
|
7102
|
-
/* @__PURE__ */ (0,
|
|
7398
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
7103
7399
|
"button",
|
|
7104
7400
|
{
|
|
7105
7401
|
type: "button",
|
|
7106
7402
|
className: "rk-icon-btn",
|
|
7107
7403
|
"aria-label": "Keyboard shortcuts",
|
|
7108
7404
|
onClick: () => dispatch({ type: "SET_CHEATSHEET", open: true }),
|
|
7109
|
-
children: /* @__PURE__ */ (0,
|
|
7405
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconKeyboard, { size: 15 })
|
|
7110
7406
|
}
|
|
7111
7407
|
),
|
|
7112
|
-
/* @__PURE__ */ (0,
|
|
7408
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
7113
7409
|
"button",
|
|
7114
7410
|
{
|
|
7115
7411
|
type: "button",
|
|
7116
7412
|
className: "rk-icon-btn",
|
|
7117
7413
|
"aria-label": "Close panel",
|
|
7118
7414
|
onClick: () => dispatch({ type: "SET_PANEL", open: false }),
|
|
7119
|
-
children: /* @__PURE__ */ (0,
|
|
7415
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconClose, { size: 14 })
|
|
7120
7416
|
}
|
|
7121
7417
|
)
|
|
7122
7418
|
] }),
|
|
7123
|
-
/* @__PURE__ */ (0,
|
|
7124
|
-
/* @__PURE__ */ (0,
|
|
7125
|
-
/* @__PURE__ */ (0,
|
|
7126
|
-
/* @__PURE__ */ (0,
|
|
7419
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rk-view-row", children: [
|
|
7420
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "rk-view-info", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "rk-view-title", children: "Page view" }) }),
|
|
7421
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rk-seg rk-view-toggle", role: "group", "aria-label": "Page view (P to toggle)", children: [
|
|
7422
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
7127
7423
|
"button",
|
|
7128
7424
|
{
|
|
7129
7425
|
type: "button",
|
|
@@ -7133,7 +7429,7 @@ function Panel() {
|
|
|
7133
7429
|
children: "Original"
|
|
7134
7430
|
}
|
|
7135
7431
|
),
|
|
7136
|
-
/* @__PURE__ */ (0,
|
|
7432
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
7137
7433
|
"button",
|
|
7138
7434
|
{
|
|
7139
7435
|
type: "button",
|
|
@@ -7145,8 +7441,8 @@ function Panel() {
|
|
|
7145
7441
|
)
|
|
7146
7442
|
] })
|
|
7147
7443
|
] }),
|
|
7148
|
-
/* @__PURE__ */ (0,
|
|
7149
|
-
/* @__PURE__ */ (0,
|
|
7444
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rk-panel-tools", children: [
|
|
7445
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
7150
7446
|
"button",
|
|
7151
7447
|
{
|
|
7152
7448
|
type: "button",
|
|
@@ -7157,15 +7453,15 @@ function Panel() {
|
|
|
7157
7453
|
dispatch({ type: "SET_MODE", mode: "pick" });
|
|
7158
7454
|
},
|
|
7159
7455
|
children: [
|
|
7160
|
-
/* @__PURE__ */ (0,
|
|
7456
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconTarget, { size: 14 }),
|
|
7161
7457
|
" Pick an element"
|
|
7162
7458
|
]
|
|
7163
7459
|
}
|
|
7164
7460
|
),
|
|
7165
|
-
/* @__PURE__ */ (0,
|
|
7166
|
-
/* @__PURE__ */ (0,
|
|
7167
|
-
/* @__PURE__ */ (0,
|
|
7168
|
-
/* @__PURE__ */ (0,
|
|
7461
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rk-search-row", children: [
|
|
7462
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rk-search", children: [
|
|
7463
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconSearch, { size: 13 }),
|
|
7464
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
7169
7465
|
"input",
|
|
7170
7466
|
{
|
|
7171
7467
|
ref: searchRef,
|
|
@@ -7177,8 +7473,8 @@ function Panel() {
|
|
|
7177
7473
|
}
|
|
7178
7474
|
)
|
|
7179
7475
|
] }),
|
|
7180
|
-
/* @__PURE__ */ (0,
|
|
7181
|
-
/* @__PURE__ */ (0,
|
|
7476
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rk-menu-scope rk-menu-anchor", children: [
|
|
7477
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
7182
7478
|
"button",
|
|
7183
7479
|
{
|
|
7184
7480
|
type: "button",
|
|
@@ -7190,15 +7486,15 @@ function Panel() {
|
|
|
7190
7486
|
setSettingsOpen(false);
|
|
7191
7487
|
},
|
|
7192
7488
|
children: [
|
|
7193
|
-
/* @__PURE__ */ (0,
|
|
7489
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconFilter, { size: 13 }),
|
|
7194
7490
|
"Filter",
|
|
7195
|
-
typeFilter.size + prioFilter.size + statusFilter.size > 0 && /* @__PURE__ */ (0,
|
|
7491
|
+
typeFilter.size + prioFilter.size + statusFilter.size > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rk-badge-count", children: typeFilter.size + prioFilter.size + statusFilter.size })
|
|
7196
7492
|
]
|
|
7197
7493
|
}
|
|
7198
7494
|
),
|
|
7199
|
-
filterOpen && /* @__PURE__ */ (0,
|
|
7200
|
-
/* @__PURE__ */ (0,
|
|
7201
|
-
TYPE_FILTERS.map((type) => /* @__PURE__ */ (0,
|
|
7495
|
+
filterOpen && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rk-menu", role: "menu", "aria-label": "Filter items", children: [
|
|
7496
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "rk-menu-title", children: "Type" }),
|
|
7497
|
+
TYPE_FILTERS.map((type) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
7202
7498
|
"button",
|
|
7203
7499
|
{
|
|
7204
7500
|
type: "button",
|
|
@@ -7212,16 +7508,16 @@ function Panel() {
|
|
|
7212
7508
|
setTypeFilter(next);
|
|
7213
7509
|
},
|
|
7214
7510
|
children: [
|
|
7215
|
-
/* @__PURE__ */ (0,
|
|
7511
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: `rk-menu-check${typeFilter.has(type) ? " rk-on" : ""}` }),
|
|
7216
7512
|
iconForType(type, 12),
|
|
7217
|
-
/* @__PURE__ */ (0,
|
|
7218
|
-
/* @__PURE__ */ (0,
|
|
7513
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rk-menu-label", children: type }),
|
|
7514
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rk-menu-count", children: typeCounts.get(type) ?? 0 })
|
|
7219
7515
|
]
|
|
7220
7516
|
},
|
|
7221
7517
|
type
|
|
7222
7518
|
)),
|
|
7223
|
-
/* @__PURE__ */ (0,
|
|
7224
|
-
PRIORITY_FILTERS.map((priority) => /* @__PURE__ */ (0,
|
|
7519
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "rk-menu-title", children: "Priority" }),
|
|
7520
|
+
PRIORITY_FILTERS.map((priority) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
7225
7521
|
"button",
|
|
7226
7522
|
{
|
|
7227
7523
|
type: "button",
|
|
@@ -7235,15 +7531,15 @@ function Panel() {
|
|
|
7235
7531
|
setPrioFilter(next);
|
|
7236
7532
|
},
|
|
7237
7533
|
children: [
|
|
7238
|
-
/* @__PURE__ */ (0,
|
|
7239
|
-
/* @__PURE__ */ (0,
|
|
7240
|
-
/* @__PURE__ */ (0,
|
|
7534
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: `rk-menu-check${prioFilter.has(priority) ? " rk-on" : ""}` }),
|
|
7535
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rk-menu-label", children: PRIORITY_LABELS[priority] }),
|
|
7536
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rk-menu-count", children: prioCounts.get(priority) ?? 0 })
|
|
7241
7537
|
]
|
|
7242
7538
|
},
|
|
7243
7539
|
priority
|
|
7244
7540
|
)),
|
|
7245
|
-
/* @__PURE__ */ (0,
|
|
7246
|
-
STATUSES.map((status) => /* @__PURE__ */ (0,
|
|
7541
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "rk-menu-title", children: "Status" }),
|
|
7542
|
+
STATUSES.map((status) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
7247
7543
|
"button",
|
|
7248
7544
|
{
|
|
7249
7545
|
type: "button",
|
|
@@ -7257,15 +7553,15 @@ function Panel() {
|
|
|
7257
7553
|
setStatusFilter(next);
|
|
7258
7554
|
},
|
|
7259
7555
|
children: [
|
|
7260
|
-
/* @__PURE__ */ (0,
|
|
7261
|
-
/* @__PURE__ */ (0,
|
|
7262
|
-
/* @__PURE__ */ (0,
|
|
7263
|
-
/* @__PURE__ */ (0,
|
|
7556
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: `rk-menu-check${statusFilter.has(status) ? " rk-on" : ""}` }),
|
|
7557
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: `rk-status-dot rk-st-${status}` }),
|
|
7558
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rk-menu-label", children: status }),
|
|
7559
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rk-menu-count", children: statusCounts.get(status) ?? 0 })
|
|
7264
7560
|
]
|
|
7265
7561
|
},
|
|
7266
7562
|
status
|
|
7267
7563
|
)),
|
|
7268
|
-
/* @__PURE__ */ (0,
|
|
7564
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
7269
7565
|
"button",
|
|
7270
7566
|
{
|
|
7271
7567
|
type: "button",
|
|
@@ -7285,24 +7581,24 @@ function Panel() {
|
|
|
7285
7581
|
] })
|
|
7286
7582
|
] })
|
|
7287
7583
|
] }),
|
|
7288
|
-
preview && unapplied > 0 && /* @__PURE__ */ (0,
|
|
7584
|
+
preview && unapplied > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rk-unplaced", role: "status", children: [
|
|
7289
7585
|
unapplied,
|
|
7290
7586
|
" saved change",
|
|
7291
7587
|
unapplied === 1 ? "" : "s",
|
|
7292
7588
|
" couldn\u2019t be placed on the current page \u2014 the page has changed since they were captured."
|
|
7293
7589
|
] }),
|
|
7294
|
-
/* @__PURE__ */ (0,
|
|
7295
|
-
/* @__PURE__ */ (0,
|
|
7296
|
-
/* @__PURE__ */ (0,
|
|
7297
|
-
/* @__PURE__ */ (0,
|
|
7298
|
-
] }) : groups.map(([route, entries]) => /* @__PURE__ */ (0,
|
|
7299
|
-
/* @__PURE__ */ (0,
|
|
7590
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "rk-panel-list", children: filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rk-empty", children: [
|
|
7591
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "rk-empty-art", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconTarget, { size: 22 }) }),
|
|
7592
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "rk-empty-title", children: items.length === 0 ? "Nothing here yet" : "No matches" }),
|
|
7593
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("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." })
|
|
7594
|
+
] }) : groups.map(([route, entries]) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
|
|
7595
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "rk-group-title", children: route }),
|
|
7300
7596
|
entries.map(({ item, number }) => {
|
|
7301
7597
|
const active2 = item.id === activeItemId;
|
|
7302
7598
|
const orphan = orphanIds.has(item.id);
|
|
7303
7599
|
const hiddenEl = hiddenIds.has(item.id);
|
|
7304
|
-
return /* @__PURE__ */ (0,
|
|
7305
|
-
/* @__PURE__ */ (0,
|
|
7600
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
|
|
7601
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
7306
7602
|
"div",
|
|
7307
7603
|
{
|
|
7308
7604
|
"data-item-id": item.id,
|
|
@@ -7317,18 +7613,18 @@ function Panel() {
|
|
|
7317
7613
|
}
|
|
7318
7614
|
},
|
|
7319
7615
|
children: [
|
|
7320
|
-
/* @__PURE__ */ (0,
|
|
7321
|
-
/* @__PURE__ */ (0,
|
|
7322
|
-
/* @__PURE__ */ (0,
|
|
7323
|
-
/* @__PURE__ */ (0,
|
|
7616
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rk-item-num", children: number }),
|
|
7617
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rk-item-icon", children: iconForType(item.type) }),
|
|
7618
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "rk-item-body", children: [
|
|
7619
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "rk-item-snippet", children: [
|
|
7324
7620
|
item.target.tagName,
|
|
7325
7621
|
" \xB7 ",
|
|
7326
7622
|
item.target.textSnippet || item.target.selector
|
|
7327
7623
|
] }),
|
|
7328
|
-
/* @__PURE__ */ (0,
|
|
7329
|
-
/* @__PURE__ */ (0,
|
|
7330
|
-
/* @__PURE__ */ (0,
|
|
7331
|
-
/* @__PURE__ */ (0,
|
|
7624
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rk-item-change", children: changeSummary(item) }),
|
|
7625
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "rk-item-meta", children: [
|
|
7626
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "rk-author", title: new Date(item.createdAt).toLocaleString(), children: [
|
|
7627
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
7332
7628
|
"span",
|
|
7333
7629
|
{
|
|
7334
7630
|
className: "rk-author-dot",
|
|
@@ -7336,15 +7632,15 @@ function Panel() {
|
|
|
7336
7632
|
}
|
|
7337
7633
|
),
|
|
7338
7634
|
item.author?.name ?? "Unknown",
|
|
7339
|
-
/* @__PURE__ */ (0,
|
|
7635
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "rk-time", children: [
|
|
7340
7636
|
" \xB7 ",
|
|
7341
7637
|
timeAgo(item.createdAt)
|
|
7342
7638
|
] })
|
|
7343
7639
|
] }),
|
|
7344
|
-
item.priority === "must" && /* @__PURE__ */ (0,
|
|
7345
|
-
item.status !== "open" && /* @__PURE__ */ (0,
|
|
7346
|
-
orphan && /* @__PURE__ */ (0,
|
|
7347
|
-
hiddenEl && /* @__PURE__ */ (0,
|
|
7640
|
+
item.priority === "must" && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rk-badge-mini rk-must", children: "must" }),
|
|
7641
|
+
item.status !== "open" && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: `rk-badge-mini rk-${item.status}`, children: item.status }),
|
|
7642
|
+
orphan && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rk-badge-mini rk-orphaned", children: "unanchored" }),
|
|
7643
|
+
hiddenEl && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
7348
7644
|
"span",
|
|
7349
7645
|
{
|
|
7350
7646
|
className: "rk-badge-mini rk-hidden-el",
|
|
@@ -7352,14 +7648,14 @@ function Panel() {
|
|
|
7352
7648
|
children: "hidden"
|
|
7353
7649
|
}
|
|
7354
7650
|
),
|
|
7355
|
-
item.note && /* @__PURE__ */ (0,
|
|
7356
|
-
peers.filter((peer) => peer.typingActive && peer.typingItemId === item.id).map((peer) => /* @__PURE__ */ (0,
|
|
7651
|
+
item.note && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rk-badge-mini", children: "note" }),
|
|
7652
|
+
peers.filter((peer) => peer.typingActive && peer.typingItemId === item.id).map((peer) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "rk-badge-mini", style: { color: peer.color }, children: [
|
|
7357
7653
|
peer.name || "peer",
|
|
7358
7654
|
" is writing\u2026"
|
|
7359
7655
|
] }, peer.id))
|
|
7360
7656
|
] })
|
|
7361
7657
|
] }),
|
|
7362
|
-
/* @__PURE__ */ (0,
|
|
7658
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rk-item-actions", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
7363
7659
|
"button",
|
|
7364
7660
|
{
|
|
7365
7661
|
type: "button",
|
|
@@ -7374,15 +7670,15 @@ function Panel() {
|
|
|
7374
7670
|
"info"
|
|
7375
7671
|
);
|
|
7376
7672
|
},
|
|
7377
|
-
children: /* @__PURE__ */ (0,
|
|
7673
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconTrash, { size: 13 })
|
|
7378
7674
|
}
|
|
7379
7675
|
) })
|
|
7380
7676
|
]
|
|
7381
7677
|
}
|
|
7382
7678
|
),
|
|
7383
|
-
active2 && /* @__PURE__ */ (0,
|
|
7384
|
-
/* @__PURE__ */ (0,
|
|
7385
|
-
/* @__PURE__ */ (0,
|
|
7679
|
+
active2 && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rk-item-edit", children: [
|
|
7680
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rk-detail-byline", title: new Date(item.createdAt).toLocaleString(), children: [
|
|
7681
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
7386
7682
|
"span",
|
|
7387
7683
|
{
|
|
7388
7684
|
className: "rk-author-dot",
|
|
@@ -7393,8 +7689,8 @@ function Panel() {
|
|
|
7393
7689
|
" \xB7 ",
|
|
7394
7690
|
timeAgo(item.createdAt)
|
|
7395
7691
|
] }),
|
|
7396
|
-
isCopyItem(item) && /* @__PURE__ */ (0,
|
|
7397
|
-
isImageItem(item) && /* @__PURE__ */ (0,
|
|
7692
|
+
isCopyItem(item) && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CopyDiff, { before: item.payload.before, after: item.payload.after }),
|
|
7693
|
+
isImageItem(item) && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
7398
7694
|
ImageDetail,
|
|
7399
7695
|
{
|
|
7400
7696
|
beforeSrc: item.payload.beforeSrc,
|
|
@@ -7402,7 +7698,7 @@ function Panel() {
|
|
|
7402
7698
|
afterDataUrl: item.payload.afterDataUrl
|
|
7403
7699
|
}
|
|
7404
7700
|
),
|
|
7405
|
-
isKnownItemType(item.type) && item.type !== "move" && /* @__PURE__ */ (0,
|
|
7701
|
+
isKnownItemType(item.type) && item.type !== "move" && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
7406
7702
|
"textarea",
|
|
7407
7703
|
{
|
|
7408
7704
|
className: "rk-textarea",
|
|
@@ -7412,7 +7708,7 @@ function Panel() {
|
|
|
7412
7708
|
onChange: (event) => dispatch({ type: "UPDATE_ITEM", id: item.id, patch: withPayloadText(item, event.target.value) })
|
|
7413
7709
|
}
|
|
7414
7710
|
),
|
|
7415
|
-
/* @__PURE__ */ (0,
|
|
7711
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
7416
7712
|
"input",
|
|
7417
7713
|
{
|
|
7418
7714
|
className: "rk-input",
|
|
@@ -7422,9 +7718,9 @@ function Panel() {
|
|
|
7422
7718
|
onChange: (event) => dispatch({ type: "UPDATE_ITEM", id: item.id, patch: { note: event.target.value } })
|
|
7423
7719
|
}
|
|
7424
7720
|
),
|
|
7425
|
-
/* @__PURE__ */ (0,
|
|
7426
|
-
/* @__PURE__ */ (0,
|
|
7427
|
-
/* @__PURE__ */ (0,
|
|
7721
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { display: "flex", gap: 8, flexWrap: "wrap" }, children: [
|
|
7722
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rk-seg", role: "group", "aria-label": "Priority", children: [
|
|
7723
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
7428
7724
|
"button",
|
|
7429
7725
|
{
|
|
7430
7726
|
type: "button",
|
|
@@ -7433,7 +7729,7 @@ function Panel() {
|
|
|
7433
7729
|
children: "Must"
|
|
7434
7730
|
}
|
|
7435
7731
|
),
|
|
7436
|
-
/* @__PURE__ */ (0,
|
|
7732
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
7437
7733
|
"button",
|
|
7438
7734
|
{
|
|
7439
7735
|
type: "button",
|
|
@@ -7443,7 +7739,7 @@ function Panel() {
|
|
|
7443
7739
|
}
|
|
7444
7740
|
)
|
|
7445
7741
|
] }),
|
|
7446
|
-
/* @__PURE__ */ (0,
|
|
7742
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "rk-seg", role: "group", "aria-label": "Status", children: STATUSES.map((status) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
7447
7743
|
"button",
|
|
7448
7744
|
{
|
|
7449
7745
|
type: "button",
|
|
@@ -7458,22 +7754,22 @@ function Panel() {
|
|
|
7458
7754
|
] }, item.id);
|
|
7459
7755
|
})
|
|
7460
7756
|
] }, route)) }),
|
|
7461
|
-
/* @__PURE__ */ (0,
|
|
7462
|
-
/* @__PURE__ */ (0,
|
|
7463
|
-
/* @__PURE__ */ (0,
|
|
7757
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rk-panel-foot", children: [
|
|
7758
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: onExport, disabled: items.length === 0, children: [
|
|
7759
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconDownload, { size: 13 }),
|
|
7464
7760
|
" Export"
|
|
7465
7761
|
] }),
|
|
7466
|
-
/* @__PURE__ */ (0,
|
|
7467
|
-
/* @__PURE__ */ (0,
|
|
7762
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => void onCopy(), disabled: items.length === 0, children: [
|
|
7763
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconCopyClipboard, { size: 13 }),
|
|
7468
7764
|
" Copy"
|
|
7469
7765
|
] }),
|
|
7470
|
-
/* @__PURE__ */ (0,
|
|
7471
|
-
/* @__PURE__ */ (0,
|
|
7766
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => importRef.current?.click(), children: [
|
|
7767
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconUpload, { size: 13 }),
|
|
7472
7768
|
" Import"
|
|
7473
7769
|
] }),
|
|
7474
|
-
/* @__PURE__ */ (0,
|
|
7475
|
-
undoStack.length > 0 && /* @__PURE__ */ (0,
|
|
7476
|
-
/* @__PURE__ */ (0,
|
|
7770
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rk-spacer" }),
|
|
7771
|
+
undoStack.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", className: "rk-icon-btn", "aria-label": "Undo last change (\u2318Z)", onClick: () => dispatch({ type: "UNDO" }), children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconUndo, { size: 14 }) }),
|
|
7772
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
7477
7773
|
"button",
|
|
7478
7774
|
{
|
|
7479
7775
|
type: "button",
|
|
@@ -7484,7 +7780,7 @@ function Panel() {
|
|
|
7484
7780
|
children: "Clear"
|
|
7485
7781
|
}
|
|
7486
7782
|
),
|
|
7487
|
-
/* @__PURE__ */ (0,
|
|
7783
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
7488
7784
|
"button",
|
|
7489
7785
|
{
|
|
7490
7786
|
type: "button",
|
|
@@ -7494,7 +7790,7 @@ function Panel() {
|
|
|
7494
7790
|
children: "Exit review"
|
|
7495
7791
|
}
|
|
7496
7792
|
),
|
|
7497
|
-
/* @__PURE__ */ (0,
|
|
7793
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
7498
7794
|
"input",
|
|
7499
7795
|
{
|
|
7500
7796
|
ref: importRef,
|
|
@@ -7515,8 +7811,8 @@ function Panel() {
|
|
|
7515
7811
|
}
|
|
7516
7812
|
|
|
7517
7813
|
// src/client/components/Presence.tsx
|
|
7518
|
-
var
|
|
7519
|
-
var
|
|
7814
|
+
var import_react15 = require("react");
|
|
7815
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
7520
7816
|
function initials(name) {
|
|
7521
7817
|
const parts = name.trim().split(/\s+/).filter(Boolean);
|
|
7522
7818
|
if (parts.length === 0) return "\xB7";
|
|
@@ -7526,8 +7822,8 @@ function initials(name) {
|
|
|
7526
7822
|
function PresenceStrip() {
|
|
7527
7823
|
const { peers, syncStatus } = useStore();
|
|
7528
7824
|
if (syncStatus === "disabled" || peers.length === 0) return null;
|
|
7529
|
-
return /* @__PURE__ */ (0,
|
|
7530
|
-
peers.slice(0, 5).map((peer) => /* @__PURE__ */ (0,
|
|
7825
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "rk-presence", "aria-label": `${peers.length} reviewer${peers.length === 1 ? "" : "s"} online`, children: [
|
|
7826
|
+
peers.slice(0, 5).map((peer) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
7531
7827
|
"span",
|
|
7532
7828
|
{
|
|
7533
7829
|
className: "rk-avatar",
|
|
@@ -7537,7 +7833,7 @@ function PresenceStrip() {
|
|
|
7537
7833
|
},
|
|
7538
7834
|
peer.id
|
|
7539
7835
|
)),
|
|
7540
|
-
peers.length > 5 && /* @__PURE__ */ (0,
|
|
7836
|
+
peers.length > 5 && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "rk-avatar rk-avatar-more", children: [
|
|
7541
7837
|
"+",
|
|
7542
7838
|
peers.length - 5
|
|
7543
7839
|
] })
|
|
@@ -7545,13 +7841,13 @@ function PresenceStrip() {
|
|
|
7545
7841
|
}
|
|
7546
7842
|
function PeerCursors() {
|
|
7547
7843
|
const { peers } = useStore();
|
|
7548
|
-
const ringRefs = (0,
|
|
7549
|
-
const cursorRefs = (0,
|
|
7550
|
-
const motion = (0,
|
|
7844
|
+
const ringRefs = (0, import_react15.useRef)(/* @__PURE__ */ new Map());
|
|
7845
|
+
const cursorRefs = (0, import_react15.useRef)(/* @__PURE__ */ new Map());
|
|
7846
|
+
const motion = (0, import_react15.useRef)(
|
|
7551
7847
|
/* @__PURE__ */ new Map()
|
|
7552
7848
|
);
|
|
7553
|
-
const peersRef = (0,
|
|
7554
|
-
const seen = (0,
|
|
7849
|
+
const peersRef = (0, import_react15.useRef)(peers);
|
|
7850
|
+
const seen = (0, import_react15.useRef)(/* @__PURE__ */ new Map());
|
|
7555
7851
|
for (const peer of peers) {
|
|
7556
7852
|
const sig = peer.cursor ? `${peer.cursor.x},${peer.cursor.y},${peer.cursor.ox},${peer.cursor.oy}` : "";
|
|
7557
7853
|
if (seen.current.get(peer.id) !== sig) {
|
|
@@ -7561,7 +7857,7 @@ function PeerCursors() {
|
|
|
7561
7857
|
}
|
|
7562
7858
|
}
|
|
7563
7859
|
peersRef.current = peers;
|
|
7564
|
-
(0,
|
|
7860
|
+
(0, import_react15.useEffect)(() => {
|
|
7565
7861
|
const reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
7566
7862
|
let raf = 0;
|
|
7567
7863
|
let last = performance.now();
|
|
@@ -7666,8 +7962,8 @@ function PeerCursors() {
|
|
|
7666
7962
|
return () => cancelAnimationFrame(raf);
|
|
7667
7963
|
}, []);
|
|
7668
7964
|
if (peers.length === 0) return null;
|
|
7669
|
-
return /* @__PURE__ */ (0,
|
|
7670
|
-
peers.map((peer) => /* @__PURE__ */ (0,
|
|
7965
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
|
|
7966
|
+
peers.map((peer) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
7671
7967
|
"div",
|
|
7672
7968
|
{
|
|
7673
7969
|
ref: (el) => {
|
|
@@ -7679,7 +7975,7 @@ function PeerCursors() {
|
|
|
7679
7975
|
},
|
|
7680
7976
|
`ring-${peer.id}`
|
|
7681
7977
|
)),
|
|
7682
|
-
peers.map((peer, index) => /* @__PURE__ */ (0,
|
|
7978
|
+
peers.map((peer, index) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
7683
7979
|
"div",
|
|
7684
7980
|
{
|
|
7685
7981
|
ref: (el) => {
|
|
@@ -7689,8 +7985,8 @@ function PeerCursors() {
|
|
|
7689
7985
|
className: "rk-peer-cursor",
|
|
7690
7986
|
style: { opacity: 0 },
|
|
7691
7987
|
children: [
|
|
7692
|
-
/* @__PURE__ */ (0,
|
|
7693
|
-
/* @__PURE__ */ (0,
|
|
7988
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("svg", { width: "14", height: "18", viewBox: "0 0 14 18", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: "M1 1l12 7.5-5.2 1.2L5 16z", fill: peer.color, stroke: "rgba(0,0,0,0.25)", strokeWidth: "1" }) }),
|
|
7989
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
7694
7990
|
"span",
|
|
7695
7991
|
{
|
|
7696
7992
|
className: "rk-peer-name",
|
|
@@ -7709,19 +8005,19 @@ function PeerCursors() {
|
|
|
7709
8005
|
}
|
|
7710
8006
|
|
|
7711
8007
|
// src/client/components/QuickComment.tsx
|
|
7712
|
-
var
|
|
7713
|
-
var
|
|
8008
|
+
var import_react16 = require("react");
|
|
8009
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
7714
8010
|
function QuickComment() {
|
|
7715
8011
|
const { quick } = useStore();
|
|
7716
8012
|
if (!quick) return null;
|
|
7717
|
-
return /* @__PURE__ */ (0,
|
|
8013
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(QuickComposerCard, { quick }, quick.id);
|
|
7718
8014
|
}
|
|
7719
8015
|
function QuickComposerCard({ quick }) {
|
|
7720
8016
|
const { route, session } = useStore();
|
|
7721
8017
|
const dispatch = useDispatch();
|
|
7722
|
-
const [text, setText] = (0,
|
|
7723
|
-
const fieldRef = (0,
|
|
7724
|
-
(0,
|
|
8018
|
+
const [text, setText] = (0, import_react16.useState)("");
|
|
8019
|
+
const fieldRef = (0, import_react16.useRef)(null);
|
|
8020
|
+
(0, import_react16.useEffect)(() => {
|
|
7725
8021
|
const field = fieldRef.current;
|
|
7726
8022
|
if (!field) return;
|
|
7727
8023
|
field.focus();
|
|
@@ -7774,18 +8070,18 @@ function QuickComposerCard({ quick }) {
|
|
|
7774
8070
|
};
|
|
7775
8071
|
const x = Math.min(Math.max(quick.x, 8), window.innerWidth - 288);
|
|
7776
8072
|
const y = Math.min(Math.max(quick.y + 12, 8), window.innerHeight - 108);
|
|
7777
|
-
return /* @__PURE__ */ (0,
|
|
7778
|
-
/* @__PURE__ */ (0,
|
|
7779
|
-
/* @__PURE__ */ (0,
|
|
7780
|
-
/* @__PURE__ */ (0,
|
|
7781
|
-
/* @__PURE__ */ (0,
|
|
7782
|
-
/* @__PURE__ */ (0,
|
|
8073
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "rk-quick", style: { transform: `translate3d(${x}px, ${y}px, 0)` }, role: "dialog", "aria-label": "Quick comment", children: [
|
|
8074
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "rk-quick-head", children: [
|
|
8075
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(IconComment, { size: 12 }),
|
|
8076
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: "Comment here" }),
|
|
8077
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "rk-hint", children: [
|
|
8078
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "rk-kbd", children: "\u21B5" }),
|
|
7783
8079
|
" save \xB7 ",
|
|
7784
|
-
/* @__PURE__ */ (0,
|
|
8080
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "rk-kbd", children: "esc" }),
|
|
7785
8081
|
" cancel"
|
|
7786
8082
|
] })
|
|
7787
8083
|
] }),
|
|
7788
|
-
/* @__PURE__ */ (0,
|
|
8084
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
7789
8085
|
"textarea",
|
|
7790
8086
|
{
|
|
7791
8087
|
ref: fieldRef,
|
|
@@ -7801,8 +8097,8 @@ function QuickComposerCard({ quick }) {
|
|
|
7801
8097
|
}
|
|
7802
8098
|
|
|
7803
8099
|
// src/client/components/PickLayer.tsx
|
|
7804
|
-
var
|
|
7805
|
-
var
|
|
8100
|
+
var import_react17 = require("react");
|
|
8101
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
7806
8102
|
function applyRect(el, rect, pad2 = 3) {
|
|
7807
8103
|
if (!el) return;
|
|
7808
8104
|
if (!rect) {
|
|
@@ -7817,14 +8113,14 @@ function applyRect(el, rect, pad2 = 3) {
|
|
|
7817
8113
|
function PickLayer() {
|
|
7818
8114
|
const { mode, selection, tool } = useStore();
|
|
7819
8115
|
const dispatch = useDispatch();
|
|
7820
|
-
const [hovered, setHovered] = (0,
|
|
7821
|
-
const outlineRef = (0,
|
|
7822
|
-
const labelRef = (0,
|
|
7823
|
-
const selectRef = (0,
|
|
7824
|
-
const hoveredRef = (0,
|
|
8116
|
+
const [hovered, setHovered] = (0, import_react17.useState)(null);
|
|
8117
|
+
const outlineRef = (0, import_react17.useRef)(null);
|
|
8118
|
+
const labelRef = (0, import_react17.useRef)(null);
|
|
8119
|
+
const selectRef = (0, import_react17.useRef)(null);
|
|
8120
|
+
const hoveredRef = (0, import_react17.useRef)(null);
|
|
7825
8121
|
hoveredRef.current = hovered;
|
|
7826
8122
|
const picking = mode === "pick";
|
|
7827
|
-
(0,
|
|
8123
|
+
(0, import_react17.useEffect)(() => {
|
|
7828
8124
|
if (!picking) {
|
|
7829
8125
|
setHovered(null);
|
|
7830
8126
|
return;
|
|
@@ -7868,7 +8164,7 @@ function PickLayer() {
|
|
|
7868
8164
|
document.removeEventListener("mousedown", swallow, true);
|
|
7869
8165
|
};
|
|
7870
8166
|
}, [picking, tool, dispatch]);
|
|
7871
|
-
(0,
|
|
8167
|
+
(0, import_react17.useEffect)(() => {
|
|
7872
8168
|
if (!picking) return;
|
|
7873
8169
|
const body = document.body;
|
|
7874
8170
|
const prev = body.style.cursor;
|
|
@@ -7878,7 +8174,7 @@ function PickLayer() {
|
|
|
7878
8174
|
if (body.getAttribute("style") === "") body.removeAttribute("style");
|
|
7879
8175
|
};
|
|
7880
8176
|
}, [picking, tool]);
|
|
7881
|
-
(0,
|
|
8177
|
+
(0, import_react17.useEffect)(() => {
|
|
7882
8178
|
let raf = 0;
|
|
7883
8179
|
const tick = () => {
|
|
7884
8180
|
const hoverEl = hoveredRef.current;
|
|
@@ -7904,21 +8200,21 @@ function PickLayer() {
|
|
|
7904
8200
|
raf = requestAnimationFrame(tick);
|
|
7905
8201
|
return () => cancelAnimationFrame(raf);
|
|
7906
8202
|
}, [picking, selection]);
|
|
7907
|
-
return /* @__PURE__ */ (0,
|
|
7908
|
-
picking && /* @__PURE__ */ (0,
|
|
7909
|
-
/* @__PURE__ */ (0,
|
|
7910
|
-
/* @__PURE__ */ (0,
|
|
7911
|
-
/* @__PURE__ */ (0,
|
|
7912
|
-
/* @__PURE__ */ (0,
|
|
7913
|
-
] }) : /* @__PURE__ */ (0,
|
|
8203
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
8204
|
+
picking && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
8205
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { ref: outlineRef, className: "rk-outline", style: { opacity: 0 } }),
|
|
8206
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { ref: labelRef, className: "rk-outline-label", style: { opacity: 0 }, children: hovered ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
8207
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "rk-tag", children: hovered.tagName.toLowerCase() }),
|
|
8208
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: describeElement(hovered).replace(/^[a-z0-9]+ · /, "") })
|
|
8209
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: "Pick an element" }) })
|
|
7914
8210
|
] }),
|
|
7915
|
-
selection && /* @__PURE__ */ (0,
|
|
8211
|
+
selection && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { ref: selectRef, className: "rk-select-ring", style: { opacity: 0 } })
|
|
7916
8212
|
] });
|
|
7917
8213
|
}
|
|
7918
8214
|
|
|
7919
8215
|
// src/client/components/Pins.tsx
|
|
7920
|
-
var
|
|
7921
|
-
var
|
|
8216
|
+
var import_react18 = require("react");
|
|
8217
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
7922
8218
|
var STATUS_LABELS = {
|
|
7923
8219
|
open: "open",
|
|
7924
8220
|
accepted: "accepted",
|
|
@@ -7930,22 +8226,22 @@ var RERESOLVE_MS = 800;
|
|
|
7930
8226
|
function Pins() {
|
|
7931
8227
|
const { session, route, activeItemId, editor, mode, filter } = useStore();
|
|
7932
8228
|
const dispatch = useDispatch();
|
|
7933
|
-
const [clusters, setClusters] = (0,
|
|
7934
|
-
const [orphanCount, setOrphanCount] = (0,
|
|
7935
|
-
const wrapRefs = (0,
|
|
7936
|
-
const visibleCache = (0,
|
|
7937
|
-
const highlightRef = (0,
|
|
7938
|
-
const hoveredItems = (0,
|
|
7939
|
-
const elementCache = (0,
|
|
7940
|
-
const lastResolve = (0,
|
|
7941
|
-
const [newestId, setNewestId] = (0,
|
|
7942
|
-
const prevCount = (0,
|
|
7943
|
-
const items = (0,
|
|
8229
|
+
const [clusters, setClusters] = (0, import_react18.useState)([]);
|
|
8230
|
+
const [orphanCount, setOrphanCount] = (0, import_react18.useState)(0);
|
|
8231
|
+
const wrapRefs = (0, import_react18.useRef)(/* @__PURE__ */ new Map());
|
|
8232
|
+
const visibleCache = (0, import_react18.useRef)(/* @__PURE__ */ new Map());
|
|
8233
|
+
const highlightRef = (0, import_react18.useRef)(null);
|
|
8234
|
+
const hoveredItems = (0, import_react18.useRef)(null);
|
|
8235
|
+
const elementCache = (0, import_react18.useRef)(/* @__PURE__ */ new Map());
|
|
8236
|
+
const lastResolve = (0, import_react18.useRef)(0);
|
|
8237
|
+
const [newestId, setNewestId] = (0, import_react18.useState)(null);
|
|
8238
|
+
const prevCount = (0, import_react18.useRef)(0);
|
|
8239
|
+
const items = (0, import_react18.useMemo)(() => {
|
|
7944
8240
|
const all = session?.items ?? [];
|
|
7945
8241
|
return all.map((item, index) => ({ item, number: index + 1 })).filter(({ item }) => item.route === route);
|
|
7946
8242
|
}, [session, route]);
|
|
7947
8243
|
const byId = new Map(items.map(({ item }) => [item.id, item]));
|
|
7948
|
-
(0,
|
|
8244
|
+
(0, import_react18.useEffect)(() => {
|
|
7949
8245
|
const count = session?.items.length ?? 0;
|
|
7950
8246
|
if (count > prevCount.current && session && count > 0) {
|
|
7951
8247
|
const id = session.items[count - 1].id;
|
|
@@ -7956,7 +8252,7 @@ function Pins() {
|
|
|
7956
8252
|
}
|
|
7957
8253
|
prevCount.current = count;
|
|
7958
8254
|
}, [session]);
|
|
7959
|
-
(0,
|
|
8255
|
+
(0, import_react18.useEffect)(() => {
|
|
7960
8256
|
let raf = 0;
|
|
7961
8257
|
let lastSignature = "";
|
|
7962
8258
|
const tick = (time) => {
|
|
@@ -8040,8 +8336,8 @@ function Pins() {
|
|
|
8040
8336
|
dispatch({ type: "SET_ACTIVE_ITEM", id });
|
|
8041
8337
|
dispatch({ type: "SET_PANEL", open: true });
|
|
8042
8338
|
};
|
|
8043
|
-
return /* @__PURE__ */ (0,
|
|
8044
|
-
/* @__PURE__ */ (0,
|
|
8339
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
|
|
8340
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { ref: highlightRef, className: "rk-hl-ring", style: { opacity: 0 } }),
|
|
8045
8341
|
clusters.map((cluster) => {
|
|
8046
8342
|
const isCluster = cluster.ids.length > 1;
|
|
8047
8343
|
const isActive = activeItemId !== null && cluster.ids.includes(activeItemId);
|
|
@@ -8051,7 +8347,7 @@ function Pins() {
|
|
|
8051
8347
|
const status = statuses.size === 1 ? members[0]?.status : void 0;
|
|
8052
8348
|
const dimmed = filter !== null && members.length > 0 && !members.some((item) => itemMatchesFilter(item, filter));
|
|
8053
8349
|
const statusHint = isCluster ? status ? ` \xB7 all ${STATUS_LABELS[status] ?? status}` : "" : ` \xB7 ${STATUS_LABELS[members[0]?.status ?? "open"] ?? members[0]?.status}`;
|
|
8054
|
-
return /* @__PURE__ */ (0,
|
|
8350
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
8055
8351
|
"div",
|
|
8056
8352
|
{
|
|
8057
8353
|
ref: (el) => {
|
|
@@ -8059,7 +8355,7 @@ function Pins() {
|
|
|
8059
8355
|
else wrapRefs.current.delete(cluster.key);
|
|
8060
8356
|
},
|
|
8061
8357
|
className: `rk-pin-wrap${picking ? " rk-pin-ghost" : ""}`,
|
|
8062
|
-
children: /* @__PURE__ */ (0,
|
|
8358
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
8063
8359
|
"button",
|
|
8064
8360
|
{
|
|
8065
8361
|
type: "button",
|
|
@@ -8081,7 +8377,7 @@ function Pins() {
|
|
|
8081
8377
|
cluster.key
|
|
8082
8378
|
);
|
|
8083
8379
|
}),
|
|
8084
|
-
orphanCount > 0 && /* @__PURE__ */ (0,
|
|
8380
|
+
orphanCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
8085
8381
|
"button",
|
|
8086
8382
|
{
|
|
8087
8383
|
type: "button",
|
|
@@ -8089,7 +8385,7 @@ function Pins() {
|
|
|
8089
8385
|
style: { bottom: 16, left: "50%", transform: "translateX(-50%)" },
|
|
8090
8386
|
onClick: () => dispatch({ type: "SET_PANEL", open: true }),
|
|
8091
8387
|
children: [
|
|
8092
|
-
/* @__PURE__ */ (0,
|
|
8388
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(IconUnlink, { size: 13 }),
|
|
8093
8389
|
orphanCount,
|
|
8094
8390
|
" unanchored item",
|
|
8095
8391
|
orphanCount === 1 ? "" : "s"
|
|
@@ -8100,13 +8396,13 @@ function Pins() {
|
|
|
8100
8396
|
}
|
|
8101
8397
|
|
|
8102
8398
|
// src/client/components/Toolbar.tsx
|
|
8103
|
-
var
|
|
8104
|
-
var
|
|
8399
|
+
var import_react19 = require("react");
|
|
8400
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
8105
8401
|
var TOOLS = [
|
|
8106
|
-
{ tool: "select", hintId: "tool-select", label: "Select", icon: (n) => /* @__PURE__ */ (0,
|
|
8107
|
-
{ tool: "copy", hintId: "tool-copy", label: "Rewrite text", icon: (n) => /* @__PURE__ */ (0,
|
|
8108
|
-
{ tool: "comment", hintId: "tool-comment", label: "Comment", icon: (n) => /* @__PURE__ */ (0,
|
|
8109
|
-
{ tool: "image", hintId: "tool-image", label: "Replace image", icon: (n) => /* @__PURE__ */ (0,
|
|
8402
|
+
{ tool: "select", hintId: "tool-select", label: "Select", icon: (n) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(IconTarget, { size: n }) },
|
|
8403
|
+
{ tool: "copy", hintId: "tool-copy", label: "Rewrite text", icon: (n) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(IconText, { size: n }) },
|
|
8404
|
+
{ tool: "comment", hintId: "tool-comment", label: "Comment", icon: (n) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(IconComment, { size: n }) },
|
|
8405
|
+
{ tool: "image", hintId: "tool-image", label: "Replace image", icon: (n) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(IconImage, { size: n }) }
|
|
8110
8406
|
];
|
|
8111
8407
|
var POS_KEY2 = "review-kit:toolbar-pos";
|
|
8112
8408
|
var DRAG_THRESHOLD2 = 6;
|
|
@@ -8114,24 +8410,24 @@ function Toolbar() {
|
|
|
8114
8410
|
const { selection, editor, peers, syncStatus, mode, tool } = useStore();
|
|
8115
8411
|
const hasPeers = syncStatus !== "disabled" && peers.length > 0;
|
|
8116
8412
|
const dispatch = useDispatch();
|
|
8117
|
-
const ref = (0,
|
|
8118
|
-
const [pos, setPos] = (0,
|
|
8119
|
-
const drag = (0,
|
|
8120
|
-
const [dragging, setDragging] = (0,
|
|
8121
|
-
const justDragged = (0,
|
|
8413
|
+
const ref = (0, import_react19.useRef)(null);
|
|
8414
|
+
const [pos, setPos] = (0, import_react19.useState)(() => readStoredPos(POS_KEY2));
|
|
8415
|
+
const drag = (0, import_react19.useRef)(null);
|
|
8416
|
+
const [dragging, setDragging] = (0, import_react19.useState)(false);
|
|
8417
|
+
const justDragged = (0, import_react19.useRef)(false);
|
|
8122
8418
|
const visible = editor === null || selection !== null;
|
|
8123
8419
|
const applyPos = (next, persist) => {
|
|
8124
8420
|
if (next === null && ref.current) ref.current.style.bottom = "";
|
|
8125
8421
|
setPos(next);
|
|
8126
8422
|
if (persist) storePos(POS_KEY2, next);
|
|
8127
8423
|
};
|
|
8128
|
-
(0,
|
|
8424
|
+
(0, import_react19.useLayoutEffect)(() => {
|
|
8129
8425
|
const el = ref.current;
|
|
8130
8426
|
if (!el || pos === null) return;
|
|
8131
8427
|
const clamped = clampPos(pos.x, pos.y, el.offsetWidth, el.offsetHeight);
|
|
8132
8428
|
if (clamped.x !== pos.x || clamped.y !== pos.y) applyPos(clamped, true);
|
|
8133
8429
|
}, [pos, selection, hasPeers, visible]);
|
|
8134
|
-
(0,
|
|
8430
|
+
(0, import_react19.useEffect)(() => {
|
|
8135
8431
|
const onResize = () => {
|
|
8136
8432
|
const el = ref.current;
|
|
8137
8433
|
const current = readStoredPos(POS_KEY2);
|
|
@@ -8244,7 +8540,7 @@ function Toolbar() {
|
|
|
8244
8540
|
mode === "pick" && selection === null ? "rk-ghost" : ""
|
|
8245
8541
|
].filter(Boolean).join(" ");
|
|
8246
8542
|
const style = pos !== null ? { left: 0, top: 0, translate: `${pos.x}px ${pos.y}px` } : void 0;
|
|
8247
|
-
return /* @__PURE__ */ (0,
|
|
8543
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
8248
8544
|
"div",
|
|
8249
8545
|
{
|
|
8250
8546
|
ref,
|
|
@@ -8255,7 +8551,7 @@ function Toolbar() {
|
|
|
8255
8551
|
onPointerDown,
|
|
8256
8552
|
onClickCapture,
|
|
8257
8553
|
children: [
|
|
8258
|
-
/* @__PURE__ */ (0,
|
|
8554
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
8259
8555
|
"button",
|
|
8260
8556
|
{
|
|
8261
8557
|
type: "button",
|
|
@@ -8263,19 +8559,19 @@ function Toolbar() {
|
|
|
8263
8559
|
"aria-label": "Move the toolbar \u2014 drag, or use arrow keys; double-click to reset its position",
|
|
8264
8560
|
onKeyDown: onGripKeyDown,
|
|
8265
8561
|
onDoubleClick: () => applyPos(null, true),
|
|
8266
|
-
children: /* @__PURE__ */ (0,
|
|
8267
|
-
/* @__PURE__ */ (0,
|
|
8268
|
-
/* @__PURE__ */ (0,
|
|
8269
|
-
/* @__PURE__ */ (0,
|
|
8270
|
-
/* @__PURE__ */ (0,
|
|
8271
|
-
/* @__PURE__ */ (0,
|
|
8272
|
-
/* @__PURE__ */ (0,
|
|
8562
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("svg", { width: "8", height: "14", viewBox: "0 0 8 14", "aria-hidden": "true", fill: "currentColor", children: [
|
|
8563
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("circle", { cx: "2", cy: "2", r: "1.1" }),
|
|
8564
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("circle", { cx: "6", cy: "2", r: "1.1" }),
|
|
8565
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("circle", { cx: "2", cy: "7", r: "1.1" }),
|
|
8566
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("circle", { cx: "6", cy: "7", r: "1.1" }),
|
|
8567
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("circle", { cx: "2", cy: "12", r: "1.1" }),
|
|
8568
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("circle", { cx: "6", cy: "12", r: "1.1" })
|
|
8273
8569
|
] })
|
|
8274
8570
|
}
|
|
8275
8571
|
),
|
|
8276
|
-
/* @__PURE__ */ (0,
|
|
8277
|
-
hasPeers && /* @__PURE__ */ (0,
|
|
8278
|
-
/* @__PURE__ */ (0,
|
|
8572
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(PresenceStrip, {}),
|
|
8573
|
+
hasPeers && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "rk-toolbar-sep" }),
|
|
8574
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "rk-seg rk-tool-seg", role: "group", "aria-label": "Tools", children: TOOLS.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
8279
8575
|
"button",
|
|
8280
8576
|
{
|
|
8281
8577
|
type: "button",
|
|
@@ -8287,9 +8583,9 @@ function Toolbar() {
|
|
|
8287
8583
|
},
|
|
8288
8584
|
entry.tool
|
|
8289
8585
|
)) }),
|
|
8290
|
-
selection && /* @__PURE__ */ (0,
|
|
8291
|
-
selection && /* @__PURE__ */ (0,
|
|
8292
|
-
/* @__PURE__ */ (0,
|
|
8586
|
+
selection && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "rk-toolbar-sep" }),
|
|
8587
|
+
selection && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
8588
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
8293
8589
|
"button",
|
|
8294
8590
|
{
|
|
8295
8591
|
type: "button",
|
|
@@ -8298,12 +8594,12 @@ function Toolbar() {
|
|
|
8298
8594
|
title: `Rewrite text${keyHint("tool-copy")}`,
|
|
8299
8595
|
onClick: () => open("copy"),
|
|
8300
8596
|
children: [
|
|
8301
|
-
/* @__PURE__ */ (0,
|
|
8597
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(IconText, { size: 14 }),
|
|
8302
8598
|
" Rewrite"
|
|
8303
8599
|
]
|
|
8304
8600
|
}
|
|
8305
8601
|
),
|
|
8306
|
-
hasImage && /* @__PURE__ */ (0,
|
|
8602
|
+
hasImage && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
8307
8603
|
"button",
|
|
8308
8604
|
{
|
|
8309
8605
|
type: "button",
|
|
@@ -8312,12 +8608,12 @@ function Toolbar() {
|
|
|
8312
8608
|
title: `Replace image${keyHint("tool-image")}`,
|
|
8313
8609
|
onClick: () => open("image"),
|
|
8314
8610
|
children: [
|
|
8315
|
-
/* @__PURE__ */ (0,
|
|
8611
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(IconImage, { size: 14 }),
|
|
8316
8612
|
" Image"
|
|
8317
8613
|
]
|
|
8318
8614
|
}
|
|
8319
8615
|
),
|
|
8320
|
-
/* @__PURE__ */ (0,
|
|
8616
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
8321
8617
|
"button",
|
|
8322
8618
|
{
|
|
8323
8619
|
type: "button",
|
|
@@ -8326,32 +8622,32 @@ function Toolbar() {
|
|
|
8326
8622
|
title: `Comment${keyHint("tool-comment")}`,
|
|
8327
8623
|
onClick: () => open("comment"),
|
|
8328
8624
|
children: [
|
|
8329
|
-
/* @__PURE__ */ (0,
|
|
8625
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(IconComment, { size: 14 }),
|
|
8330
8626
|
" Comment"
|
|
8331
8627
|
]
|
|
8332
8628
|
}
|
|
8333
8629
|
),
|
|
8334
|
-
/* @__PURE__ */ (0,
|
|
8335
|
-
/* @__PURE__ */ (0,
|
|
8630
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("button", { type: "button", role: "menuitem", className: "rk-toolbar-btn", onClick: () => open("style"), children: [
|
|
8631
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(IconStyle, { size: 14 }),
|
|
8336
8632
|
" Style"
|
|
8337
8633
|
] }),
|
|
8338
|
-
/* @__PURE__ */ (0,
|
|
8339
|
-
/* @__PURE__ */ (0,
|
|
8634
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("button", { type: "button", role: "menuitem", className: "rk-toolbar-btn", onClick: () => open("move"), children: [
|
|
8635
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(IconMove, { size: 14 }),
|
|
8340
8636
|
" Move"
|
|
8341
8637
|
] }),
|
|
8342
|
-
/* @__PURE__ */ (0,
|
|
8343
|
-
/* @__PURE__ */ (0,
|
|
8638
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("button", { type: "button", role: "menuitem", className: "rk-toolbar-btn rk-danger", onClick: () => open("delete"), children: [
|
|
8639
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(IconTrash, { size: 14 }),
|
|
8344
8640
|
" Delete"
|
|
8345
8641
|
] }),
|
|
8346
|
-
/* @__PURE__ */ (0,
|
|
8347
|
-
/* @__PURE__ */ (0,
|
|
8642
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "rk-toolbar-sep" }),
|
|
8643
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
8348
8644
|
"button",
|
|
8349
8645
|
{
|
|
8350
8646
|
type: "button",
|
|
8351
8647
|
className: "rk-icon-btn",
|
|
8352
8648
|
"aria-label": "Deselect",
|
|
8353
8649
|
onClick: () => dispatch({ type: "SELECT", selection: null }),
|
|
8354
|
-
children: /* @__PURE__ */ (0,
|
|
8650
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(IconClose, { size: 13 })
|
|
8355
8651
|
}
|
|
8356
8652
|
)
|
|
8357
8653
|
] })
|
|
@@ -8361,40 +8657,40 @@ function Toolbar() {
|
|
|
8361
8657
|
}
|
|
8362
8658
|
|
|
8363
8659
|
// src/client/components/Toast.tsx
|
|
8364
|
-
var
|
|
8365
|
-
var
|
|
8660
|
+
var import_react20 = require("react");
|
|
8661
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
8366
8662
|
function ToastRow({ toast: toast2 }) {
|
|
8367
8663
|
const dispatch = useDispatch();
|
|
8368
|
-
(0,
|
|
8664
|
+
(0, import_react20.useEffect)(() => {
|
|
8369
8665
|
const timer = window.setTimeout(() => dispatch({ type: "DISMISS_TOAST", id: toast2.id }), 3500);
|
|
8370
8666
|
return () => window.clearTimeout(timer);
|
|
8371
8667
|
}, [toast2.id, dispatch]);
|
|
8372
|
-
return /* @__PURE__ */ (0,
|
|
8373
|
-
toast2.tone === "success" ? /* @__PURE__ */ (0,
|
|
8668
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: `rk-toast rk-${toast2.tone}`, role: "status", children: [
|
|
8669
|
+
toast2.tone === "success" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(IconCheck, { size: 13 }) : toast2.tone === "error" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(IconWarning, { size: 13 }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(IconComment, { size: 13 }),
|
|
8374
8670
|
toast2.message
|
|
8375
8671
|
] });
|
|
8376
8672
|
}
|
|
8377
8673
|
function ToastHost() {
|
|
8378
8674
|
const { toasts } = useStore();
|
|
8379
8675
|
if (toasts.length === 0) return null;
|
|
8380
|
-
return /* @__PURE__ */ (0,
|
|
8676
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "rk-toasts", "aria-live": "polite", children: toasts.map((toast2) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ToastRow, { toast: toast2 }, toast2.id)) });
|
|
8381
8677
|
}
|
|
8382
8678
|
|
|
8383
8679
|
// src/client/App.tsx
|
|
8384
|
-
var
|
|
8680
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
8385
8681
|
function App() {
|
|
8386
8682
|
const state = useStore();
|
|
8387
8683
|
const rawDispatch = useDispatch();
|
|
8388
8684
|
const config = useConfig();
|
|
8389
8685
|
const dispatch = useRealtimeSync(state, rawDispatch, config, reducer);
|
|
8390
|
-
const saveTimer = (0,
|
|
8686
|
+
const saveTimer = (0, import_react21.useRef)(null);
|
|
8391
8687
|
const storageKey = config.storageKey ?? defaultStorageKey();
|
|
8392
8688
|
useAppliedPreview(state, dispatch);
|
|
8393
8689
|
useEmblemaAutoPush(state, dispatch, config);
|
|
8394
|
-
(0,
|
|
8690
|
+
(0, import_react21.useEffect)(() => {
|
|
8395
8691
|
setEffectAssetsUrl(config.fxAssetsUrl);
|
|
8396
8692
|
}, [config.fxAssetsUrl]);
|
|
8397
|
-
(0,
|
|
8693
|
+
(0, import_react21.useEffect)(() => {
|
|
8398
8694
|
let cancelled = false;
|
|
8399
8695
|
void loadSession(storageKey).then((stored) => {
|
|
8400
8696
|
if (cancelled) return;
|
|
@@ -8412,7 +8708,7 @@ function App() {
|
|
|
8412
8708
|
};
|
|
8413
8709
|
}, [storageKey, config.defaultAuthor, dispatch]);
|
|
8414
8710
|
const { session } = state;
|
|
8415
|
-
(0,
|
|
8711
|
+
(0, import_react21.useEffect)(() => {
|
|
8416
8712
|
if (!session) return;
|
|
8417
8713
|
if (saveTimer.current !== null) window.clearTimeout(saveTimer.current);
|
|
8418
8714
|
saveTimer.current = window.setTimeout(() => {
|
|
@@ -8423,9 +8719,9 @@ function App() {
|
|
|
8423
8719
|
if (saveTimer.current !== null) window.clearTimeout(saveTimer.current);
|
|
8424
8720
|
};
|
|
8425
8721
|
}, [session, storageKey, config]);
|
|
8426
|
-
(0,
|
|
8427
|
-
const focusHandled = (0,
|
|
8428
|
-
(0,
|
|
8722
|
+
(0, import_react21.useEffect)(() => trackPointer(), []);
|
|
8723
|
+
const focusHandled = (0, import_react21.useRef)(false);
|
|
8724
|
+
(0, import_react21.useEffect)(() => {
|
|
8429
8725
|
if (!session || focusHandled.current) return;
|
|
8430
8726
|
focusHandled.current = true;
|
|
8431
8727
|
const id = takeFocusItem();
|
|
@@ -8450,7 +8746,7 @@ function App() {
|
|
|
8450
8746
|
cancelled = true;
|
|
8451
8747
|
};
|
|
8452
8748
|
}, [session, dispatch]);
|
|
8453
|
-
(0,
|
|
8749
|
+
(0, import_react21.useEffect)(() => {
|
|
8454
8750
|
let last = window.location.pathname;
|
|
8455
8751
|
const check = () => {
|
|
8456
8752
|
if (window.location.pathname !== last) {
|
|
@@ -8465,9 +8761,9 @@ function App() {
|
|
|
8465
8761
|
window.removeEventListener("popstate", check);
|
|
8466
8762
|
};
|
|
8467
8763
|
}, [dispatch]);
|
|
8468
|
-
const stateRef = (0,
|
|
8764
|
+
const stateRef = (0, import_react21.useRef)(state);
|
|
8469
8765
|
stateRef.current = state;
|
|
8470
|
-
(0,
|
|
8766
|
+
(0, import_react21.useEffect)(() => {
|
|
8471
8767
|
const onKeyDown = (event) => {
|
|
8472
8768
|
const current = stateRef.current;
|
|
8473
8769
|
for (const def of SHORTCUTS) {
|
|
@@ -8482,7 +8778,7 @@ function App() {
|
|
|
8482
8778
|
document.addEventListener("keydown", onKeyDown);
|
|
8483
8779
|
return () => document.removeEventListener("keydown", onKeyDown);
|
|
8484
8780
|
}, [dispatch]);
|
|
8485
|
-
(0,
|
|
8781
|
+
(0, import_react21.useEffect)(() => {
|
|
8486
8782
|
if (!state.editor) return;
|
|
8487
8783
|
const editorEl = state.editor.element;
|
|
8488
8784
|
const onPointerDown = (event) => {
|
|
@@ -8495,32 +8791,33 @@ function App() {
|
|
|
8495
8791
|
}, [state.editor, dispatch]);
|
|
8496
8792
|
if (!session) return null;
|
|
8497
8793
|
if (state.hidden) {
|
|
8498
|
-
return /* @__PURE__ */ (0,
|
|
8794
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DispatchContext.Provider, { value: dispatch, children: null });
|
|
8499
8795
|
}
|
|
8500
|
-
return /* @__PURE__ */ (0,
|
|
8501
|
-
/* @__PURE__ */ (0,
|
|
8502
|
-
/* @__PURE__ */ (0,
|
|
8503
|
-
/* @__PURE__ */ (0,
|
|
8504
|
-
state.editor?.kind === "copy" && /* @__PURE__ */ (0,
|
|
8505
|
-
state.editor?.kind === "image" && /* @__PURE__ */ (0,
|
|
8506
|
-
state.editor && state.editor.kind !== "copy" && state.editor.kind !== "image" && /* @__PURE__ */ (0,
|
|
8507
|
-
/* @__PURE__ */ (0,
|
|
8508
|
-
/* @__PURE__ */ (0,
|
|
8509
|
-
/* @__PURE__ */ (0,
|
|
8510
|
-
/* @__PURE__ */ (0,
|
|
8511
|
-
/* @__PURE__ */ (0,
|
|
8512
|
-
/* @__PURE__ */ (0,
|
|
8513
|
-
/* @__PURE__ */ (0,
|
|
8514
|
-
/* @__PURE__ */ (0,
|
|
8515
|
-
/* @__PURE__ */ (0,
|
|
8796
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(DispatchContext.Provider, { value: dispatch, children: [
|
|
8797
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(PickLayer, {}),
|
|
8798
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(PeerCursors, {}),
|
|
8799
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Toolbar, {}),
|
|
8800
|
+
state.editor?.kind === "copy" && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(InlineEditor, { editor: state.editor }),
|
|
8801
|
+
state.editor?.kind === "image" && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ImageEditor, { editor: state.editor }),
|
|
8802
|
+
state.editor && state.editor.kind !== "copy" && state.editor.kind !== "image" && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(NoteComposer, { editor: state.editor }),
|
|
8803
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Pins, {}),
|
|
8804
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(QuickComment, {}),
|
|
8805
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Panel, {}),
|
|
8806
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Badge, {}),
|
|
8807
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(CoachMark, {}),
|
|
8808
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(CheatSheet, {}),
|
|
8809
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(EmblemaConnect, {}),
|
|
8810
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(TerminalConnect, {}),
|
|
8811
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ConfirmHost, {}),
|
|
8812
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ToastHost, {})
|
|
8516
8813
|
] });
|
|
8517
8814
|
}
|
|
8518
8815
|
|
|
8519
8816
|
// src/client/ReviewKit.tsx
|
|
8520
|
-
var
|
|
8817
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
8521
8818
|
function ShadowHost({ config }) {
|
|
8522
|
-
const [mount, setMount] = (0,
|
|
8523
|
-
(0,
|
|
8819
|
+
const [mount, setMount] = (0, import_react22.useState)(null);
|
|
8820
|
+
(0, import_react22.useEffect)(() => {
|
|
8524
8821
|
const host = document.createElement("div");
|
|
8525
8822
|
host.setAttribute(HOST_ATTR, "");
|
|
8526
8823
|
host.style.position = "fixed";
|
|
@@ -8556,15 +8853,15 @@ function ShadowHost({ config }) {
|
|
|
8556
8853
|
}, []);
|
|
8557
8854
|
if (!mount) return null;
|
|
8558
8855
|
return (0, import_react_dom.createPortal)(
|
|
8559
|
-
/* @__PURE__ */ (0,
|
|
8856
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(StoreProvider, { config, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(App, {}) }),
|
|
8560
8857
|
mount
|
|
8561
8858
|
);
|
|
8562
8859
|
}
|
|
8563
8860
|
function ReviewKit(props) {
|
|
8564
|
-
const [active2, setActive] = (0,
|
|
8861
|
+
const [active2, setActive] = (0, import_react22.useState)(false);
|
|
8565
8862
|
const { enabled, token, allowedHosts, devAutoOn } = props;
|
|
8566
8863
|
const hostsKey = allowedHosts?.join("\0") ?? "";
|
|
8567
|
-
(0,
|
|
8864
|
+
(0, import_react22.useEffect)(() => {
|
|
8568
8865
|
if (enabled === false) {
|
|
8569
8866
|
setActive(false);
|
|
8570
8867
|
return;
|
|
@@ -8575,7 +8872,7 @@ function ReviewKit(props) {
|
|
|
8575
8872
|
return () => window.removeEventListener(DEACTIVATE_EVENT, onDeactivate);
|
|
8576
8873
|
}, [enabled, token, devAutoOn, hostsKey]);
|
|
8577
8874
|
if (enabled === false || !active2) return null;
|
|
8578
|
-
return /* @__PURE__ */ (0,
|
|
8875
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ShadowHost, { config: props });
|
|
8579
8876
|
}
|
|
8580
8877
|
// Annotate the CommonJS export names for ESM import in node:
|
|
8581
8878
|
0 && (module.exports = {
|