@satanwagen/reviewkit 0.1.2 → 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 +158 -0
- package/README.md +158 -64
- package/dist/activate.cjs +150 -0
- package/dist/activate.cjs.map +1 -0
- package/dist/activate.d.cts +59 -0
- package/dist/activate.d.ts +59 -0
- package/dist/activate.js +21 -0
- package/dist/activate.js.map +1 -0
- package/dist/{chunk-YWBFAV57.js → chunk-5MAFDRUI.js} +1161 -1555
- package/dist/chunk-5MAFDRUI.js.map +1 -0
- package/dist/{chunk-4YNLMSCK.js → chunk-DG6O5XIC.js} +36 -10
- package/dist/chunk-DG6O5XIC.js.map +1 -0
- package/dist/chunk-EOX3UJNP.js +36 -0
- package/dist/chunk-EOX3UJNP.js.map +1 -0
- package/dist/chunk-ETAGGIDN.js +119 -0
- package/dist/chunk-ETAGGIDN.js.map +1 -0
- package/dist/client/index.cjs +4834 -4244
- 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 +49 -3
- package/dist/client/index.js.map +1 -1
- package/dist/effects-EWKHKUDP.js +851 -0
- package/dist/effects-EWKHKUDP.js.map +1 -0
- package/dist/index-CWGkg1-E.d.cts +86 -0
- package/dist/index-DPsjkvaY.d.ts +86 -0
- package/dist/index.cjs +4852 -4267
- 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 +35 -3
- package/dist/index.js.map +1 -1
- package/dist/lazy.cjs +9308 -0
- package/dist/lazy.cjs.map +1 -0
- package/dist/lazy.d.cts +7 -0
- package/dist/lazy.d.ts +7 -0
- package/dist/lazy.js +8 -0
- package/dist/lazy.js.map +1 -0
- package/dist/next.cjs +9309 -0
- package/dist/next.cjs.map +1 -0
- package/dist/next.d.cts +4 -0
- package/dist/next.d.ts +4 -0
- package/dist/next.js +9 -0
- package/dist/next.js.map +1 -0
- package/dist/schema.cjs +53 -16
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +20 -5
- package/dist/schema.d.ts +20 -5
- package/dist/schema.js +30 -2
- package/dist/schema.js.map +1 -1
- package/package.json +23 -8
- package/cli/emblema-sync.mjs +0 -675
- package/dist/chunk-4YNLMSCK.js.map +0 -1
- package/dist/chunk-YWBFAV57.js.map +0 -1
- package/dist/index-BbucFgZi.d.ts +0 -49
- package/dist/index-CBlJrKkm.d.cts +0 -49
|
@@ -1,7 +1,30 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import {
|
|
2
|
+
ITEM_STATUSES,
|
|
3
|
+
SCHEMA_VERSION,
|
|
4
|
+
fetchSyncKey,
|
|
5
|
+
fetchSyncState,
|
|
6
|
+
generateSyncKey,
|
|
7
|
+
isCommentItem,
|
|
8
|
+
isCopyItem,
|
|
9
|
+
isDeleteItem,
|
|
10
|
+
isImageItem,
|
|
11
|
+
isKnownItemType,
|
|
12
|
+
isMoveItem,
|
|
13
|
+
isStyleItem,
|
|
14
|
+
parseSession,
|
|
15
|
+
parseSessionJson,
|
|
16
|
+
pingEmblema,
|
|
17
|
+
revokeSyncKey,
|
|
18
|
+
sendToEmblema
|
|
19
|
+
} from "./chunk-DG6O5XIC.js";
|
|
20
|
+
import {
|
|
21
|
+
clearSticky,
|
|
22
|
+
isLocalHost,
|
|
23
|
+
isStickyEnabled,
|
|
24
|
+
reviewParam,
|
|
25
|
+
setSticky,
|
|
26
|
+
shouldActivate
|
|
27
|
+
} from "./chunk-ETAGGIDN.js";
|
|
5
28
|
|
|
6
29
|
// src/client/target.ts
|
|
7
30
|
var HOST_ATTR = "data-review-kit-host";
|
|
@@ -316,19 +339,14 @@ function importSessionFile(file) {
|
|
|
316
339
|
});
|
|
317
340
|
}
|
|
318
341
|
|
|
342
|
+
// src/client/ReviewKit.tsx
|
|
343
|
+
import { useEffect as useEffect18, useState as useState14 } from "react";
|
|
344
|
+
import { createPortal } from "react-dom";
|
|
345
|
+
|
|
319
346
|
// src/client/env.ts
|
|
320
|
-
var STICKY_KEY = "review-kit:sticky";
|
|
321
347
|
var LEGACY_SESSION_KEY = "review-kit:active";
|
|
322
348
|
var LEGACY_LOCAL_FLAG = "reviewkit";
|
|
323
|
-
var STICKY_TTL_MS = 4 * 60 * 60 * 1e3;
|
|
324
349
|
var DEACTIVATE_EVENT = "review-kit:deactivate";
|
|
325
|
-
function isDevBuild() {
|
|
326
|
-
try {
|
|
327
|
-
return process.env.NODE_ENV === "development";
|
|
328
|
-
} catch {
|
|
329
|
-
return false;
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
350
|
function safeRemove(storage, key) {
|
|
333
351
|
try {
|
|
334
352
|
storage().removeItem(key);
|
|
@@ -339,40 +357,8 @@ function clearLegacyKeys() {
|
|
|
339
357
|
safeRemove(() => window.sessionStorage, LEGACY_SESSION_KEY);
|
|
340
358
|
safeRemove(() => window.localStorage, LEGACY_LOCAL_FLAG);
|
|
341
359
|
}
|
|
342
|
-
function readSticky() {
|
|
343
|
-
try {
|
|
344
|
-
const raw = window.sessionStorage.getItem(STICKY_KEY);
|
|
345
|
-
if (!raw) return null;
|
|
346
|
-
const parsed = JSON.parse(raw);
|
|
347
|
-
if (typeof parsed === "object" && parsed !== null && typeof parsed.token === "string" && typeof parsed.until === "number") {
|
|
348
|
-
return parsed;
|
|
349
|
-
}
|
|
350
|
-
} catch {
|
|
351
|
-
}
|
|
352
|
-
return null;
|
|
353
|
-
}
|
|
354
|
-
function isStickyEnabled(token) {
|
|
355
|
-
const sticky = readSticky();
|
|
356
|
-
if (!sticky) return false;
|
|
357
|
-
if (sticky.until < Date.now() || sticky.token !== (token ?? "")) {
|
|
358
|
-
safeRemove(() => window.sessionStorage, STICKY_KEY);
|
|
359
|
-
return false;
|
|
360
|
-
}
|
|
361
|
-
return true;
|
|
362
|
-
}
|
|
363
|
-
function setSticky(token, on) {
|
|
364
|
-
try {
|
|
365
|
-
if (on) {
|
|
366
|
-
const value = { token: token ?? "", until: Date.now() + STICKY_TTL_MS };
|
|
367
|
-
window.sessionStorage.setItem(STICKY_KEY, JSON.stringify(value));
|
|
368
|
-
} else {
|
|
369
|
-
window.sessionStorage.removeItem(STICKY_KEY);
|
|
370
|
-
}
|
|
371
|
-
} catch {
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
360
|
function deactivateReview() {
|
|
375
|
-
|
|
361
|
+
clearSticky();
|
|
376
362
|
clearLegacyKeys();
|
|
377
363
|
try {
|
|
378
364
|
const url = new URL(window.location.href);
|
|
@@ -387,67 +373,24 @@ function deactivateReview() {
|
|
|
387
373
|
} catch {
|
|
388
374
|
}
|
|
389
375
|
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
let host = "";
|
|
393
|
-
try {
|
|
394
|
-
host = window.location.hostname.toLowerCase();
|
|
395
|
-
} catch {
|
|
396
|
-
return false;
|
|
397
|
-
}
|
|
398
|
-
return allowedHosts.some((pattern) => {
|
|
399
|
-
const regex = new RegExp(
|
|
400
|
-
"^" + pattern.toLowerCase().split("*").map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join(".*") + "$"
|
|
401
|
-
);
|
|
402
|
-
return regex.test(host);
|
|
403
|
-
});
|
|
404
|
-
}
|
|
405
|
-
function resolveActivation(token) {
|
|
376
|
+
var warnedNoAllowlist = false;
|
|
377
|
+
function resolveActivation(options) {
|
|
406
378
|
if (typeof window === "undefined") return false;
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
if (tokenConfigured) {
|
|
420
|
-
if (param !== null && param !== "") {
|
|
421
|
-
if (param === token) {
|
|
422
|
-
setSticky(token, true);
|
|
423
|
-
return true;
|
|
424
|
-
}
|
|
425
|
-
console.warn("[review-kit] `?review` token does not match the configured token; staying inactive.");
|
|
426
|
-
return false;
|
|
427
|
-
}
|
|
428
|
-
if (isStickyEnabled(token)) {
|
|
429
|
-
setSticky(token, true);
|
|
430
|
-
return true;
|
|
379
|
+
clearLegacyKeys();
|
|
380
|
+
const active = shouldActivate(options);
|
|
381
|
+
if (!active) return false;
|
|
382
|
+
const token = options.token;
|
|
383
|
+
const param = reviewParam();
|
|
384
|
+
if (token !== void 0 && token !== "" && (param === token || isStickyEnabled(token))) {
|
|
385
|
+
setSticky(token, true);
|
|
386
|
+
if (param === token && !options.allowedHosts?.length && !isLocalHost() && !warnedNoAllowlist) {
|
|
387
|
+
warnedNoAllowlist = true;
|
|
388
|
+
console.warn(
|
|
389
|
+
"[review-kit] Review mode activated by URL token on a public hostname with no `allowedHosts`. For production pass `allowedHosts` next to `token` so the layer cannot be opened on hosts you did not intend."
|
|
390
|
+
);
|
|
431
391
|
}
|
|
432
|
-
clearLegacyKeys();
|
|
433
|
-
return false;
|
|
434
|
-
}
|
|
435
|
-
if (param !== null && param !== "") {
|
|
436
|
-
console.warn(
|
|
437
|
-
"[review-kit] Activated via `?review` with no token configured. Pass a `token` prop to <ReviewKit /> to restrict who can open review mode."
|
|
438
|
-
);
|
|
439
|
-
setSticky(void 0, true);
|
|
440
|
-
return true;
|
|
441
|
-
}
|
|
442
|
-
if (isStickyEnabled(void 0)) {
|
|
443
|
-
setSticky(void 0, true);
|
|
444
|
-
return true;
|
|
445
|
-
}
|
|
446
|
-
try {
|
|
447
|
-
if (window.localStorage.getItem(LEGACY_LOCAL_FLAG) !== null) return true;
|
|
448
|
-
} catch {
|
|
449
392
|
}
|
|
450
|
-
return
|
|
393
|
+
return true;
|
|
451
394
|
}
|
|
452
395
|
var FOCUS_KEY = "review-kit:focus";
|
|
453
396
|
function rememberFocusItem(id) {
|
|
@@ -1291,10 +1234,13 @@ input, textarea, select {
|
|
|
1291
1234
|
.rk-sync-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--rk-fg-faint); }
|
|
1292
1235
|
.rk-sync-online .rk-sync-dot { background: var(--rk-success); }
|
|
1293
1236
|
.rk-sync-connecting .rk-sync-dot { background: var(--rk-warn); }
|
|
1237
|
+
.rk-sync-reason-token-short .rk-sync-dot, .rk-sync-reason-bad-token .rk-sync-dot { background: var(--rk-danger); }
|
|
1238
|
+
.rk-sync[title] { cursor: help; }
|
|
1294
1239
|
/* Automatic Emblema push hint (same quiet language) */
|
|
1295
1240
|
.rk-epush-ok .rk-sync-dot { background: var(--rk-success); }
|
|
1296
1241
|
.rk-epush-sending .rk-sync-dot { background: var(--rk-warn); }
|
|
1297
1242
|
.rk-epush-offline .rk-sync-dot { background: var(--rk-fg-faint); }
|
|
1243
|
+
.rk-epush-rejected .rk-sync-dot { background: var(--rk-danger, #d33); }
|
|
1298
1244
|
|
|
1299
1245
|
/* ---------------------------------------------------------------- */
|
|
1300
1246
|
/* Floating editor cards */
|
|
@@ -2280,6 +2226,9 @@ input, textarea, select {
|
|
|
2280
2226
|
`;
|
|
2281
2227
|
}
|
|
2282
2228
|
|
|
2229
|
+
// src/client/store.tsx
|
|
2230
|
+
import { createContext, useContext, useMemo, useReducer } from "react";
|
|
2231
|
+
|
|
2283
2232
|
// src/client/id.ts
|
|
2284
2233
|
function rkId() {
|
|
2285
2234
|
const time = Date.now().toString(36);
|
|
@@ -2295,6 +2244,9 @@ function rkId() {
|
|
|
2295
2244
|
}
|
|
2296
2245
|
return `rk-${time}-${rand}`;
|
|
2297
2246
|
}
|
|
2247
|
+
|
|
2248
|
+
// src/client/store.tsx
|
|
2249
|
+
import { jsx } from "react/jsx-runtime";
|
|
2298
2250
|
function itemMatchesFilter(item, filter) {
|
|
2299
2251
|
if (!filter) return true;
|
|
2300
2252
|
if (filter.types.length > 0 && !filter.types.includes(item.type)) return false;
|
|
@@ -2356,7 +2308,8 @@ function reducer(state, action) {
|
|
|
2356
2308
|
panelOpen: false,
|
|
2357
2309
|
confirm: null,
|
|
2358
2310
|
cheatsheetOpen: false,
|
|
2359
|
-
emblemaConnectOpen: false
|
|
2311
|
+
emblemaConnectOpen: false,
|
|
2312
|
+
terminalConnectOpen: false
|
|
2360
2313
|
} : { ...state, hidden: false };
|
|
2361
2314
|
case "SELECT":
|
|
2362
2315
|
return { ...state, selection: action.selection };
|
|
@@ -2466,12 +2419,16 @@ function reducer(state, action) {
|
|
|
2466
2419
|
return { ...state, cheatsheetOpen: action.open };
|
|
2467
2420
|
case "SET_EMBLEMA_CONNECT":
|
|
2468
2421
|
return { ...state, emblemaConnectOpen: action.open };
|
|
2422
|
+
case "SET_TERMINAL_CONNECT":
|
|
2423
|
+
return { ...state, terminalConnectOpen: action.open };
|
|
2469
2424
|
case "SET_COACH":
|
|
2470
2425
|
return { ...state, coachOpen: action.open };
|
|
2471
2426
|
case "SET_CORNER":
|
|
2472
2427
|
return { ...state, badgeCorner: action.corner };
|
|
2473
|
-
case "SYNC_STATUS":
|
|
2474
|
-
|
|
2428
|
+
case "SYNC_STATUS": {
|
|
2429
|
+
const reason = action.reason === void 0 ? action.status === "online" ? null : state.syncReason : action.reason;
|
|
2430
|
+
return state.syncStatus === action.status && state.syncReason === reason ? state : { ...state, syncStatus: action.status, syncReason: reason };
|
|
2431
|
+
}
|
|
2475
2432
|
case "EMBLEMA_PUSH_STATUS":
|
|
2476
2433
|
return state.emblemaPush === action.status ? state : { ...state, emblemaPush: action.status };
|
|
2477
2434
|
/*
|
|
@@ -2600,9 +2557,11 @@ function initialState() {
|
|
|
2600
2557
|
confirm: null,
|
|
2601
2558
|
cheatsheetOpen: false,
|
|
2602
2559
|
emblemaConnectOpen: false,
|
|
2560
|
+
terminalConnectOpen: false,
|
|
2603
2561
|
coachOpen: false,
|
|
2604
2562
|
undoStack: [],
|
|
2605
2563
|
syncStatus: "disabled",
|
|
2564
|
+
syncReason: null,
|
|
2606
2565
|
emblemaPush: "idle",
|
|
2607
2566
|
peers: [],
|
|
2608
2567
|
quick: null,
|
|
@@ -2617,7 +2576,7 @@ function StoreProvider({ config, children }) {
|
|
|
2617
2576
|
const configValue = useMemo(
|
|
2618
2577
|
() => config,
|
|
2619
2578
|
// eslint-disable-next-line react-hooks/exhaustive-deps -- config object identity is per-render; depend on its fields
|
|
2620
|
-
[config.token, config.syncToken, config.syncUrl, config.defaultAuthor, config.position, config.storageKey, config.onSessionChange, config.emblema]
|
|
2579
|
+
[config.enabled, config.token, config.devAutoOn, config.sync, config.syncToken, config.syncUrl, config.defaultAuthor, config.fxAssetsUrl, config.position, config.storageKey, config.onSessionChange, config.emblema]
|
|
2621
2580
|
);
|
|
2622
2581
|
return /* @__PURE__ */ jsx(ConfigContext.Provider, { value: configValue, children: /* @__PURE__ */ jsx(StateContext.Provider, { value: state, children: /* @__PURE__ */ jsx(DispatchContext.Provider, { value: dispatch, children }) }) });
|
|
2623
2582
|
}
|
|
@@ -2645,6 +2604,9 @@ function toast(dispatch, message, tone = "info") {
|
|
|
2645
2604
|
dispatch({ type: "PUSH_TOAST", toast: { id: rkId(), message, tone } });
|
|
2646
2605
|
}
|
|
2647
2606
|
|
|
2607
|
+
// src/client/App.tsx
|
|
2608
|
+
import { useEffect as useEffect17, useRef as useRef16 } from "react";
|
|
2609
|
+
|
|
2648
2610
|
// src/client/persist.ts
|
|
2649
2611
|
var DB_NAME = "review-kit";
|
|
2650
2612
|
var STORE = "sessions";
|
|
@@ -2771,6 +2733,9 @@ async function revealTarget(target) {
|
|
|
2771
2733
|
const el = resolveTarget(target)?.element ?? null;
|
|
2772
2734
|
return el && isElementVisible(el) ? "revealed" : "failed";
|
|
2773
2735
|
}
|
|
2736
|
+
|
|
2737
|
+
// src/client/preview.ts
|
|
2738
|
+
import { useEffect, useRef } from "react";
|
|
2774
2739
|
var EDITED_ATTR = "data-rk-edited";
|
|
2775
2740
|
var STYLE_ID = "rk-preview-style";
|
|
2776
2741
|
var RESCHEDULE_MS = 180;
|
|
@@ -2989,836 +2954,91 @@ function useAppliedPreview(state, dispatch) {
|
|
|
2989
2954
|
}, []);
|
|
2990
2955
|
}
|
|
2991
2956
|
|
|
2992
|
-
// src/client/
|
|
2993
|
-
var
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
particle.textContent = spec.glyphs[i % spec.glyphs.length];
|
|
3023
|
-
const delay = i / count * duration * 0.4;
|
|
3024
|
-
const life = duration * (0.45 + 0.35 * (i * 7 % 10) / 10);
|
|
3025
|
-
particle.style.fontSize = `${14 + i * 13 % 18}px`;
|
|
3026
|
-
if (spec.kind === "rain") {
|
|
3027
|
-
const x = i * 61 % 100 / 100 * vw;
|
|
3028
|
-
const sway = i * 31 % 60 - 30 | 0;
|
|
3029
|
-
particle.style.setProperty("--fx-x0", `${x}px`);
|
|
3030
|
-
particle.style.setProperty("--fx-x1", `${x + sway}px`);
|
|
3031
|
-
particle.style.setProperty("--fx-y0", `-40px`);
|
|
3032
|
-
particle.style.setProperty("--fx-y1", `${vh + 40}px`);
|
|
3033
|
-
} else {
|
|
3034
|
-
const angle = i / count * Math.PI * 2;
|
|
3035
|
-
const radius = 120 + i * 47 % 240;
|
|
3036
|
-
particle.style.setProperty("--fx-x0", `${vw / 2}px`);
|
|
3037
|
-
particle.style.setProperty("--fx-y0", `${vh / 2}px`);
|
|
3038
|
-
particle.style.setProperty("--fx-x1", `${vw / 2 + Math.cos(angle) * radius}px`);
|
|
3039
|
-
particle.style.setProperty("--fx-y1", `${vh / 2 + Math.sin(angle) * radius + vh * 0.4}px`);
|
|
3040
|
-
}
|
|
3041
|
-
particle.style.animation = `rk-fx-fall ${reduced ? life * 0.8 : life}ms linear ${delay}ms both`;
|
|
3042
|
-
layer.appendChild(particle);
|
|
3043
|
-
}
|
|
3044
|
-
}
|
|
3045
|
-
function runShake() {
|
|
3046
|
-
const prev = document.body.style.animation;
|
|
3047
|
-
let styleTag = document.getElementById("rk-fx-shake-style");
|
|
3048
|
-
if (!styleTag) {
|
|
3049
|
-
styleTag = document.createElement("style");
|
|
3050
|
-
styleTag.id = "rk-fx-shake-style";
|
|
3051
|
-
styleTag.textContent = "@keyframes rk-fx-shake { 0%,100% { transform: translate(0,0); } 25% { transform: translate(-5px,3px); } 50% { transform: translate(4px,-4px); } 75% { transform: translate(-3px,-2px); } }";
|
|
3052
|
-
document.head.appendChild(styleTag);
|
|
3053
|
-
}
|
|
3054
|
-
document.body.style.animation = "rk-fx-shake 260ms ease-in-out 6";
|
|
3055
|
-
let done = false;
|
|
3056
|
-
const restore2 = () => {
|
|
3057
|
-
if (done) return;
|
|
3058
|
-
done = true;
|
|
3059
|
-
document.body.style.animation = prev;
|
|
3060
|
-
if (document.body.getAttribute("style") === "") document.body.removeAttribute("style");
|
|
3061
|
-
};
|
|
3062
|
-
window.setTimeout(restore2, 1700);
|
|
3063
|
-
return restore2;
|
|
3064
|
-
}
|
|
3065
|
-
function startOndro({ layer, reduced }) {
|
|
3066
|
-
const cleanups = [];
|
|
3067
|
-
const timers = [];
|
|
3068
|
-
const intervals = [];
|
|
3069
|
-
const later = (fn, ms) => timers.push(window.setTimeout(fn, ms));
|
|
3070
|
-
const every = (fn, ms) => intervals.push(window.setInterval(fn, ms));
|
|
3071
|
-
cleanups.push(() => {
|
|
3072
|
-
timers.forEach((t) => window.clearTimeout(t));
|
|
3073
|
-
intervals.forEach((t) => window.clearInterval(t));
|
|
3074
|
-
});
|
|
3075
|
-
const addStyle = (css) => {
|
|
3076
|
-
const style = document.createElement("style");
|
|
3077
|
-
style.setAttribute("data-rk-fx", "ondro");
|
|
3078
|
-
style.textContent = css;
|
|
3079
|
-
document.head.appendChild(style);
|
|
3080
|
-
cleanups.push(() => style.remove());
|
|
3081
|
-
return style;
|
|
3082
|
-
};
|
|
3083
|
-
const wave = (spec) => {
|
|
3084
|
-
const sub = document.createElement("div");
|
|
3085
|
-
sub.className = "rk-fx-layer";
|
|
3086
|
-
layer.appendChild(sub);
|
|
3087
|
-
spawnParticles(sub, spec, reduced, spec.durationMs);
|
|
3088
|
-
const t = window.setTimeout(() => sub.remove(), spec.durationMs + 1600);
|
|
3089
|
-
timers.push(t);
|
|
3090
|
-
cleanups.push(() => sub.remove());
|
|
3091
|
-
};
|
|
3092
|
-
if (reduced) {
|
|
3093
|
-
addStyle(`@keyframes rk-ondro { 0% { filter: none; } 50% { filter: hue-rotate(40deg) saturate(1.15); } 100% { filter: none; } }
|
|
3094
|
-
${CHAOS_SEL} { animation: rk-ondro 8s ease-in-out infinite; }`);
|
|
3095
|
-
wave({ kind: "rain", glyphs: ["\u{1F92A}", "\u{1F4A5}", "\u{1F300}"], count: 8, durationMs: 8e3 });
|
|
3096
|
-
every(() => wave({ kind: "rain", glyphs: ["\u{1F92A}", "\u{1F300}"], count: 6, durationMs: 8e3 }), 15e3);
|
|
3097
|
-
} else {
|
|
3098
|
-
const scrollX = window.scrollX;
|
|
3099
|
-
const scrollY = window.scrollY;
|
|
3100
|
-
const htmlOverflow = document.documentElement.style.overflow;
|
|
3101
|
-
document.documentElement.style.overflow = "hidden";
|
|
3102
|
-
cleanups.push(() => {
|
|
3103
|
-
document.documentElement.style.overflow = htmlOverflow;
|
|
3104
|
-
if (document.documentElement.getAttribute("style") === "") document.documentElement.removeAttribute("style");
|
|
3105
|
-
window.scrollTo(scrollX, scrollY);
|
|
3106
|
-
});
|
|
3107
|
-
const originY = scrollY + window.innerHeight / 2;
|
|
3108
|
-
addStyle(`${CHAOS_SEL} { transform-origin: 50vw ${originY}px; }`);
|
|
3109
|
-
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
3110
|
-
svg.setAttribute("data-rk-fx", "ondro");
|
|
3111
|
-
svg.setAttribute("width", "0");
|
|
3112
|
-
svg.setAttribute("height", "0");
|
|
3113
|
-
svg.style.position = "absolute";
|
|
3114
|
-
svg.innerHTML = `<defs>
|
|
3115
|
-
<filter id="rk-ondro-warp" x="-10%" y="-10%" width="120%" height="120%">
|
|
3116
|
-
<feTurbulence type="turbulence" baseFrequency="0.004 0.017" numOctaves="2" result="n" seed="7">
|
|
3117
|
-
<animate attributeName="baseFrequency" dur="5.2s" values="0.004 0.017;0.013 0.005;0.004 0.017" repeatCount="indefinite"/>
|
|
3118
|
-
</feTurbulence>
|
|
3119
|
-
<feDisplacementMap in="SourceGraphic" in2="n" scale="14" xChannelSelector="R" yChannelSelector="G">
|
|
3120
|
-
<animate attributeName="scale" dur="4.4s" values="6;26;6" repeatCount="indefinite"/>
|
|
3121
|
-
</feDisplacementMap>
|
|
3122
|
-
</filter>
|
|
3123
|
-
<filter id="rk-ondro-ca" x="-5%" y="-5%" width="110%" height="110%">
|
|
3124
|
-
<feColorMatrix in="SourceGraphic" type="matrix" values="1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" result="r"/>
|
|
3125
|
-
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0" result="g"/>
|
|
3126
|
-
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0" result="b"/>
|
|
3127
|
-
<feOffset in="r" dx="4" dy="0" result="ro"><animate attributeName="dx" dur="2.9s" values="1;6;1" repeatCount="indefinite"/></feOffset>
|
|
3128
|
-
<feOffset in="b" dx="-4" dy="1" result="bo"><animate attributeName="dx" dur="3.3s" values="-1;-6;-1" repeatCount="indefinite"/></feOffset>
|
|
3129
|
-
<feBlend in="ro" in2="g" mode="screen" result="rg"/>
|
|
3130
|
-
<feBlend in="rg" in2="bo" mode="screen"/>
|
|
3131
|
-
</filter>
|
|
3132
|
-
</defs>`;
|
|
3133
|
-
document.body.appendChild(svg);
|
|
3134
|
-
cleanups.push(() => svg.remove());
|
|
3135
|
-
addStyle(`@keyframes rk-ondro1 {
|
|
3136
|
-
0% { filter: none; transform: scale(1.22); }
|
|
3137
|
-
25% { filter: hue-rotate(120deg) saturate(1.9) blur(1.6px); transform: scale(1.238) rotate(1.4deg) translateX(6px); }
|
|
3138
|
-
50% { filter: hue-rotate(230deg) saturate(0.6) contrast(1.12) blur(0.6px); transform: scale(1.202) rotate(-1.2deg) translateY(5px); }
|
|
3139
|
-
75% { filter: hue-rotate(310deg) saturate(2.1) blur(2.6px); transform: scale(1.22) skewX(1.1deg) translateX(-7px); }
|
|
3140
|
-
100% { filter: hue-rotate(360deg); transform: scale(1.22); }
|
|
3141
|
-
}
|
|
3142
|
-
${CHAOS_SEL} { animation: rk-ondro1 2.6s ease-in-out infinite; }`);
|
|
3143
|
-
later(() => {
|
|
3144
|
-
addStyle(`@keyframes rk-ondro2 {
|
|
3145
|
-
0% { filter: url(#rk-ondro-warp) hue-rotate(0deg) saturate(1.3); transform: scale(1.22); }
|
|
3146
|
-
20% { filter: url(#rk-ondro-ca) hue-rotate(100deg) saturate(2.3) blur(3.4px); transform: scale(1.256) rotate(2.4deg) translate(12px, -6px); }
|
|
3147
|
-
45% { filter: url(#rk-ondro-warp) hue-rotate(190deg) saturate(0.45) contrast(1.2) blur(1.4px); transform: scale(1.19) rotate(-2.2deg) translate(-13px, 8px) skewY(1.2deg); }
|
|
3148
|
-
70% { filter: url(#rk-ondro-ca) hue-rotate(280deg) saturate(2.4) blur(4.6px); transform: scale(1.244) skewX(-1.8deg) translateY(-10px); }
|
|
3149
|
-
100% { filter: url(#rk-ondro-warp) hue-rotate(360deg) saturate(1.3); transform: scale(1.22); }
|
|
3150
|
-
}
|
|
3151
|
-
${CHAOS_SEL} { animation: rk-ondro2 2.2s ease-in-out infinite; }
|
|
3152
|
-
@keyframes rk-ondro-shake { 0%,100% { transform: translate(0,0); } 20% { transform: translate(-6px,4px); } 40% { transform: translate(5px,-5px); } 60% { transform: translate(-4px,-3px); } 80% { transform: translate(6px,3px); } }
|
|
3153
|
-
@keyframes rk-ondro-text {
|
|
3154
|
-
0%,100% { letter-spacing: normal; word-spacing: normal; text-shadow: none; }
|
|
3155
|
-
30% { letter-spacing: 0.12em; word-spacing: 0.3em; text-shadow: 4px 0 rgba(255,0,90,0.6), -4px 1px rgba(0,190,255,0.6); }
|
|
3156
|
-
60% { letter-spacing: -0.05em; word-spacing: -0.1em; text-shadow: -6px 0 rgba(255,0,90,0.55), 6px 2px rgba(0,190,255,0.55), 0 3px rgba(120,255,0,0.4); }
|
|
3157
|
-
80% { letter-spacing: 0.2em; text-shadow: 2px -2px rgba(255,0,90,0.65), -2px 2px rgba(0,190,255,0.65); }
|
|
3158
|
-
}
|
|
3159
|
-
h1, h2, h3, h4, p, a, li, button, span { animation: rk-ondro-text 3.1s ease-in-out infinite; }`);
|
|
3160
|
-
startTextDecay(cleanups, every);
|
|
3161
|
-
spawnGlitchBands(layer, cleanups);
|
|
3162
|
-
wave({ kind: "burst", glyphs: ["\u{1F4A5}", "\u{1F9E8}", "\u{1F525}", "\u{1F300}"], count: 34, durationMs: 5e3 });
|
|
3163
|
-
}, 6e3);
|
|
3164
|
-
later(() => {
|
|
3165
|
-
addStyle(`@keyframes rk-ondro3 {
|
|
3166
|
-
0% { filter: url(#rk-ondro-warp) hue-rotate(0deg) saturate(1.6) invert(0); transform: scale(1.22); }
|
|
3167
|
-
18% { filter: url(#rk-ondro-ca) hue-rotate(140deg) saturate(2.5) blur(6px) invert(0.35); transform: scale(1.27) rotate(3.2deg) translate(20px, -12px); }
|
|
3168
|
-
38% { filter: url(#rk-ondro-warp) hue-rotate(220deg) saturate(0.4) blur(2px) invert(0.75); transform: scale(1.18) rotate(-3deg) translate(-22px, 12px) skewY(2deg); }
|
|
3169
|
-
58% { filter: url(#rk-ondro-ca) hue-rotate(300deg) saturate(2.2) blur(7px) invert(0.3); transform: scale(1.25) skewX(2.4deg) translateY(-16px); }
|
|
3170
|
-
80% { filter: url(#rk-ondro-warp) hue-rotate(340deg) saturate(1.8) blur(3px) invert(0.05); transform: scale(1.23) rotate(1.6deg) translate(14px, 6px); }
|
|
3171
|
-
100% { filter: url(#rk-ondro-warp) hue-rotate(360deg) saturate(1.6) invert(0); transform: scale(1.22); }
|
|
3172
|
-
}
|
|
3173
|
-
${CHAOS_SEL} { animation: rk-ondro3 4s ease-in-out infinite; }
|
|
3174
|
-
@keyframes rk-ondro-shake3 { 0%,100% { transform: translate(0,0) rotate(0); } 25% { transform: translate(-9px,6px) rotate(-0.4deg); } 50% { transform: translate(8px,-8px) rotate(0.5deg); } 75% { transform: translate(-7px,-5px) rotate(-0.3deg); } }
|
|
3175
|
-
body { animation: rk-ondro-shake3 620ms ease-in-out infinite; }`);
|
|
3176
|
-
wave({ kind: "rain", glyphs: ["\u{1F92F}", "\u{1F480}", "\u{1F9E0}", "\u26A1\uFE0F", "\u{1FAE0}", "\u{1F529}"], count: 60, durationMs: 7e3 });
|
|
3177
|
-
}, 13e3);
|
|
3178
|
-
wave({ kind: "rain", glyphs: ["\u{1F92A}", "\u{1F4A5}", "\u{1F300}", "\u{1F9E0}", "\u26A1\uFE0F"], count: 40, durationMs: 12e3 });
|
|
3179
|
-
every(() => wave({ kind: "rain", glyphs: ["\u{1F92A}", "\u{1F4A5}", "\u{1F300}", "\u{1F9E0}", "\u26A1\uFE0F", "\u{1F355}", "\u{1F4C0}"], count: 30, durationMs: 9e3 }), 9500);
|
|
3180
|
-
every(() => spawnFallingLetters(layer), 12e3);
|
|
3181
|
-
later(() => spawnFallingLetters(layer), 7e3);
|
|
3182
|
-
}
|
|
3183
|
-
const audio = new Audio(`${FX_SOUND_BASE}/rick.mp3`);
|
|
3184
|
-
audio.volume = 0.8;
|
|
3185
|
-
audio.loop = true;
|
|
3186
|
-
cleanups.push(() => {
|
|
3187
|
-
audio.pause();
|
|
3188
|
-
audio.src = "";
|
|
3189
|
-
});
|
|
3190
|
-
audio.play().catch(() => {
|
|
3191
|
-
const chip = document.createElement("button");
|
|
3192
|
-
chip.className = "rk-fx-sound";
|
|
3193
|
-
chip.type = "button";
|
|
3194
|
-
chip.textContent = "\u{1F50A} klikni pre zvuk";
|
|
3195
|
-
chip.addEventListener("click", () => {
|
|
3196
|
-
audio.play().catch(() => void 0);
|
|
3197
|
-
chip.remove();
|
|
3198
|
-
});
|
|
3199
|
-
layer.appendChild(chip);
|
|
3200
|
-
cleanups.push(() => chip.remove());
|
|
3201
|
-
});
|
|
3202
|
-
installKillWord(cleanups);
|
|
3203
|
-
return () => {
|
|
3204
|
-
for (const fn of cleanups) fn();
|
|
3205
|
-
};
|
|
2957
|
+
// src/client/effectCatalog.ts
|
|
2958
|
+
var EFFECT_NAMES = [
|
|
2959
|
+
"ondro",
|
|
2960
|
+
"lava",
|
|
2961
|
+
"sklo",
|
|
2962
|
+
"vir",
|
|
2963
|
+
"crt",
|
|
2964
|
+
"hovno",
|
|
2965
|
+
"konfety",
|
|
2966
|
+
"srdiecka",
|
|
2967
|
+
"sneh",
|
|
2968
|
+
"zemetrasenie",
|
|
2969
|
+
"69",
|
|
2970
|
+
"kokot",
|
|
2971
|
+
"vrtule",
|
|
2972
|
+
"muchy",
|
|
2973
|
+
"pes",
|
|
2974
|
+
"pivo",
|
|
2975
|
+
"nikotin",
|
|
2976
|
+
"matrix",
|
|
2977
|
+
"disko",
|
|
2978
|
+
"zrkadlo",
|
|
2979
|
+
"pohreb",
|
|
2980
|
+
"laser",
|
|
2981
|
+
"kura",
|
|
2982
|
+
"spam"
|
|
2983
|
+
];
|
|
2984
|
+
var NAME_SET = new Set(EFFECT_NAMES);
|
|
2985
|
+
function isEffectCommand(name) {
|
|
2986
|
+
return name === "stop" || NAME_SET.has(name);
|
|
3206
2987
|
}
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
}
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
}
|
|
3227
|
-
function bigEffect(build) {
|
|
3228
|
-
return function start({ layer, reduced }) {
|
|
3229
|
-
const cleanups = [];
|
|
3230
|
-
const timers = [];
|
|
3231
|
-
const intervals = [];
|
|
3232
|
-
const later = (fn, ms) => timers.push(window.setTimeout(fn, ms));
|
|
3233
|
-
const every = (fn, ms) => intervals.push(window.setInterval(fn, ms));
|
|
3234
|
-
cleanups.push(() => {
|
|
3235
|
-
timers.forEach((t) => window.clearTimeout(t));
|
|
3236
|
-
intervals.forEach((t) => window.clearInterval(t));
|
|
3237
|
-
});
|
|
3238
|
-
const addStyle = (css) => {
|
|
3239
|
-
const style = document.createElement("style");
|
|
3240
|
-
style.setAttribute("data-rk-fx", "");
|
|
3241
|
-
style.textContent = css;
|
|
3242
|
-
document.head.appendChild(style);
|
|
3243
|
-
cleanups.push(() => style.remove());
|
|
3244
|
-
};
|
|
3245
|
-
const wave = (spec) => {
|
|
3246
|
-
const sub = document.createElement("div");
|
|
3247
|
-
sub.className = "rk-fx-layer";
|
|
3248
|
-
layer.appendChild(sub);
|
|
3249
|
-
spawnParticles(sub, spec, reduced, spec.durationMs);
|
|
3250
|
-
timers.push(window.setTimeout(() => sub.remove(), spec.durationMs + 1600));
|
|
3251
|
-
cleanups.push(() => sub.remove());
|
|
3252
|
-
};
|
|
3253
|
-
if (!reduced) {
|
|
3254
|
-
const scrollX = window.scrollX;
|
|
3255
|
-
const scrollY = window.scrollY;
|
|
3256
|
-
const htmlOverflow = document.documentElement.style.overflow;
|
|
3257
|
-
document.documentElement.style.overflow = "hidden";
|
|
3258
|
-
cleanups.push(() => {
|
|
3259
|
-
document.documentElement.style.overflow = htmlOverflow;
|
|
3260
|
-
if (document.documentElement.getAttribute("style") === "") document.documentElement.removeAttribute("style");
|
|
3261
|
-
window.scrollTo(scrollX, scrollY);
|
|
3262
|
-
});
|
|
3263
|
-
const originY = scrollY + window.innerHeight / 2;
|
|
3264
|
-
addStyle(`${CHAOS_SEL} { transform-origin: 50vw ${originY}px; }`);
|
|
3265
|
-
}
|
|
3266
|
-
build({
|
|
3267
|
-
layer,
|
|
3268
|
-
reduced,
|
|
3269
|
-
addStyle,
|
|
3270
|
-
later,
|
|
3271
|
-
every,
|
|
3272
|
-
wave,
|
|
3273
|
-
decayText: () => startTextDecay(cleanups, every),
|
|
3274
|
-
cleanups
|
|
2988
|
+
|
|
2989
|
+
// src/client/effectsLazy.ts
|
|
2990
|
+
var loaded = null;
|
|
2991
|
+
var loading = null;
|
|
2992
|
+
var broadcaster = null;
|
|
2993
|
+
var assetsUrl = null;
|
|
2994
|
+
var queued = 0;
|
|
2995
|
+
function load() {
|
|
2996
|
+
if (loaded) return Promise.resolve(loaded);
|
|
2997
|
+
if (!loading) {
|
|
2998
|
+
loading = import("./effects-EWKHKUDP.js").then((mod) => {
|
|
2999
|
+
loaded = mod;
|
|
3000
|
+
mod.setEffectBroadcaster(broadcaster);
|
|
3001
|
+
mod.setFxAssetsUrl(assetsUrl);
|
|
3002
|
+
return mod;
|
|
3003
|
+
}).catch((error) => {
|
|
3004
|
+
loading = null;
|
|
3005
|
+
queued = 0;
|
|
3006
|
+
throw error;
|
|
3275
3007
|
});
|
|
3276
|
-
installKillWord(cleanups);
|
|
3277
|
-
return () => {
|
|
3278
|
-
for (const fn of cleanups) fn();
|
|
3279
|
-
};
|
|
3280
|
-
};
|
|
3281
|
-
}
|
|
3282
|
-
function startTextDecay(cleanups, every) {
|
|
3283
|
-
const GLYPHS = "\u2593\u2592\u2591#@%&$?!\xD7\xD8\u2206\xA7";
|
|
3284
|
-
const originals = /* @__PURE__ */ new Map();
|
|
3285
|
-
const nodes = [];
|
|
3286
|
-
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
|
|
3287
|
-
let node;
|
|
3288
|
-
while ((node = walker.nextNode()) && nodes.length < 120) {
|
|
3289
|
-
const text = node;
|
|
3290
|
-
const value = text.nodeValue ?? "";
|
|
3291
|
-
if (value.trim().length < 4) continue;
|
|
3292
|
-
const parent = text.parentElement;
|
|
3293
|
-
if (!parent || parent.closest("[data-review-kit-host], script, style, [data-rk-edited]")) continue;
|
|
3294
|
-
nodes.push(text);
|
|
3295
|
-
}
|
|
3296
|
-
every(() => {
|
|
3297
|
-
for (let i = 0; i < 22; i++) {
|
|
3298
|
-
const text = nodes[Math.random() * nodes.length | 0];
|
|
3299
|
-
if (!text || !text.isConnected) continue;
|
|
3300
|
-
if (!originals.has(text)) originals.set(text, text.nodeValue ?? "");
|
|
3301
|
-
const original = originals.get(text) ?? "";
|
|
3302
|
-
if (Math.random() < 0.3) {
|
|
3303
|
-
text.nodeValue = original;
|
|
3304
|
-
continue;
|
|
3305
|
-
}
|
|
3306
|
-
const chars = [...original];
|
|
3307
|
-
const swaps = 1 + (Math.random() * 3 | 0);
|
|
3308
|
-
for (let k = 0; k < swaps; k++) {
|
|
3309
|
-
const idx = Math.random() * chars.length | 0;
|
|
3310
|
-
if (chars[idx] !== " ") chars[idx] = GLYPHS[Math.random() * GLYPHS.length | 0];
|
|
3311
|
-
}
|
|
3312
|
-
text.nodeValue = chars.join("");
|
|
3313
|
-
}
|
|
3314
|
-
}, 260);
|
|
3315
|
-
cleanups.push(() => {
|
|
3316
|
-
for (const [text, value] of originals) {
|
|
3317
|
-
if (text.isConnected && text.nodeValue !== value) text.nodeValue = value;
|
|
3318
|
-
}
|
|
3319
|
-
originals.clear();
|
|
3320
|
-
});
|
|
3321
|
-
}
|
|
3322
|
-
function spawnFallingLetters(layer) {
|
|
3323
|
-
const sub = document.createElement("div");
|
|
3324
|
-
sub.className = "rk-fx-layer";
|
|
3325
|
-
layer.appendChild(sub);
|
|
3326
|
-
const headings = [...document.querySelectorAll("h1, h2, h3")].filter((el) => {
|
|
3327
|
-
const r = el.getBoundingClientRect();
|
|
3328
|
-
return r.width > 0 && r.top < window.innerHeight && r.bottom > 0 && !el.closest("[data-review-kit-host]");
|
|
3329
|
-
});
|
|
3330
|
-
let spawned = 0;
|
|
3331
|
-
for (const heading of headings.slice(0, 3)) {
|
|
3332
|
-
const textNode = [...heading.childNodes].find((n) => n.nodeType === 3 && (n.nodeValue ?? "").trim().length > 3);
|
|
3333
|
-
const source = textNode ?? heading.firstChild;
|
|
3334
|
-
if (!source || source.nodeType !== 3) continue;
|
|
3335
|
-
const value = source.nodeValue ?? "";
|
|
3336
|
-
const range = document.createRange();
|
|
3337
|
-
for (let i = 0; i < value.length && spawned < 26; i++) {
|
|
3338
|
-
if (value[i] === " " || Math.random() < 0.55) continue;
|
|
3339
|
-
range.setStart(source, i);
|
|
3340
|
-
range.setEnd(source, i + 1);
|
|
3341
|
-
const rect = range.getBoundingClientRect();
|
|
3342
|
-
if (rect.width === 0) continue;
|
|
3343
|
-
const span = document.createElement("span");
|
|
3344
|
-
span.className = "rk-fx-letter";
|
|
3345
|
-
span.textContent = value[i];
|
|
3346
|
-
span.style.left = `${rect.left}px`;
|
|
3347
|
-
span.style.top = `${rect.top}px`;
|
|
3348
|
-
span.style.fontSize = `${rect.height}px`;
|
|
3349
|
-
span.style.animationDelay = `${Math.random() * 900 | 0}ms`;
|
|
3350
|
-
span.style.setProperty("--fx-drift", `${(Math.random() * 120 | 0) - 60}px`);
|
|
3351
|
-
sub.appendChild(span);
|
|
3352
|
-
spawned++;
|
|
3353
|
-
}
|
|
3354
|
-
}
|
|
3355
|
-
window.setTimeout(() => sub.remove(), 4600);
|
|
3356
|
-
}
|
|
3357
|
-
function spawnGlitchBands(layer, cleanups) {
|
|
3358
|
-
for (let i = 0; i < 3; i++) {
|
|
3359
|
-
const band = document.createElement("div");
|
|
3360
|
-
band.className = "rk-fx-band";
|
|
3361
|
-
band.style.height = `${34 + i * 16}px`;
|
|
3362
|
-
band.style.animationDuration = `${2.8 + i * 0.7}s`;
|
|
3363
|
-
band.style.animationDelay = `${i * 0.9}s`;
|
|
3364
|
-
layer.appendChild(band);
|
|
3365
|
-
cleanups.push(() => band.remove());
|
|
3366
3008
|
}
|
|
3009
|
+
return loading;
|
|
3367
3010
|
}
|
|
3368
|
-
|
|
3369
|
-
if (
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
every(() => wave({ kind: "rain", glyphs: ["\u{1FAE0}", "\u{1F4A7}"], count: 6, durationMs: 9e3 }), 14e3);
|
|
3374
|
-
return;
|
|
3375
|
-
}
|
|
3376
|
-
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
3377
|
-
svg.setAttribute("data-rk-fx", "");
|
|
3378
|
-
svg.setAttribute("width", "0");
|
|
3379
|
-
svg.setAttribute("height", "0");
|
|
3380
|
-
svg.style.position = "absolute";
|
|
3381
|
-
svg.innerHTML = `<defs><filter id="rk-lava-warp" x="-10%" y="-10%" width="120%" height="130%">
|
|
3382
|
-
<feTurbulence type="fractalNoise" baseFrequency="0.008 0.003" numOctaves="2" result="n" seed="4">
|
|
3383
|
-
<animate attributeName="baseFrequency" dur="7s" values="0.008 0.003;0.014 0.006;0.008 0.003" repeatCount="indefinite"/>
|
|
3384
|
-
</feTurbulence>
|
|
3385
|
-
<feDisplacementMap in="SourceGraphic" in2="n" scale="10" xChannelSelector="R" yChannelSelector="G">
|
|
3386
|
-
<animate attributeName="scale" dur="6s" values="4;24;4" repeatCount="indefinite"/>
|
|
3387
|
-
</feDisplacementMap>
|
|
3388
|
-
</filter></defs>`;
|
|
3389
|
-
document.body.appendChild(svg);
|
|
3390
|
-
cleanups.push(() => svg.remove());
|
|
3391
|
-
addStyle(`@keyframes rk-lava1 {
|
|
3392
|
-
0% { filter: none; transform: scale(1.22); }
|
|
3393
|
-
35% { filter: sepia(0.4) hue-rotate(-24deg) saturate(1.8) blur(0.8px); transform: scale(1.235) skewY(0.5deg) translateY(6px); }
|
|
3394
|
-
70% { filter: sepia(0.6) hue-rotate(-38deg) saturate(2.2) contrast(1.1) blur(1.6px); transform: scale(1.22) scaleY(1.03) translateY(14px) skewX(-0.6deg); }
|
|
3395
|
-
100% { filter: none; transform: scale(1.22); }
|
|
3396
|
-
}
|
|
3397
|
-
${CHAOS_SEL} { animation: rk-lava1 7s ease-in-out infinite; }`);
|
|
3398
|
-
later(() => {
|
|
3399
|
-
addStyle(`@keyframes rk-lava2 {
|
|
3400
|
-
0% { filter: url(#rk-lava-warp) sepia(0.5) hue-rotate(-30deg) saturate(2); transform: scale(1.22) translateY(10px); }
|
|
3401
|
-
40% { filter: url(#rk-lava-warp) sepia(0.8) hue-rotate(-48deg) saturate(2.8) contrast(1.18) blur(2.4px); transform: scale(1.2) scaleY(1.1) translateY(46px) skewX(1deg); }
|
|
3402
|
-
70% { filter: url(#rk-lava-warp) sepia(0.7) hue-rotate(-40deg) saturate(2.4) blur(1.2px); transform: scale(1.23) scaleY(1.06) translateY(28px) skewY(-0.8deg); }
|
|
3403
|
-
100% { filter: url(#rk-lava-warp) sepia(0.5) hue-rotate(-30deg) saturate(2); transform: scale(1.22) translateY(10px); }
|
|
3404
|
-
}
|
|
3405
|
-
${CHAOS_SEL} { animation: rk-lava2 6.5s ease-in-out infinite; }
|
|
3406
|
-
@keyframes rk-lava-text { 0%,100% { letter-spacing: normal; } 50% { letter-spacing: 0.1em; word-spacing: 0.25em; text-shadow: 0 6px 6px rgba(255,80,0,0.5); } }
|
|
3407
|
-
h1, h2, h3, p, a, li, button { animation: rk-lava-text 5s ease-in-out infinite; }`);
|
|
3408
|
-
decayText();
|
|
3409
|
-
}, 1e4);
|
|
3410
|
-
const drips = document.createElement("div");
|
|
3411
|
-
drips.className = "rk-fx-layer";
|
|
3412
|
-
layer.appendChild(drips);
|
|
3413
|
-
cleanups.push(() => drips.remove());
|
|
3414
|
-
every(() => {
|
|
3415
|
-
const d = document.createElement("div");
|
|
3416
|
-
d.className = "rk-fx-drip";
|
|
3417
|
-
d.style.left = `${(Math.random() * 96 + 2).toFixed(1)}vw`;
|
|
3418
|
-
d.style.animationDuration = `${(3.5 + Math.random() * 3).toFixed(2)}s`;
|
|
3419
|
-
d.style.background = `linear-gradient(180deg, transparent, hsl(${Math.random() * 30 + 8 | 0}, 95%, 55%))`;
|
|
3420
|
-
drips.appendChild(d);
|
|
3421
|
-
window.setTimeout(() => d.remove(), 7e3);
|
|
3422
|
-
}, 700);
|
|
3423
|
-
wave({ kind: "rain", glyphs: ["\u{1F525}", "\u{1FAE0}", "\u{1F321}\uFE0F", "\u{1F4A7}"], count: 30, durationMs: 1e4 });
|
|
3424
|
-
every(() => wave({ kind: "rain", glyphs: ["\u{1F525}", "\u{1FAE0}", "\u{1F4A7}"], count: 22, durationMs: 9e3 }), 9500);
|
|
3425
|
-
});
|
|
3426
|
-
var startSklo = bigEffect(({ layer, reduced, addStyle, every, wave, decayText, cleanups }) => {
|
|
3427
|
-
if (reduced) {
|
|
3428
|
-
addStyle(`@keyframes rk-sklo-soft { 0%,100% { filter: none; } 50% { filter: saturate(0.7) brightness(1.06); } }
|
|
3429
|
-
${CHAOS_SEL} { animation: rk-sklo-soft 8s ease-in-out infinite; }`);
|
|
3430
|
-
wave({ kind: "burst", glyphs: ["\u2727", "\u2756", "\u{1F4A0}"], count: 10, durationMs: 8e3 });
|
|
3431
|
-
return;
|
|
3432
|
-
}
|
|
3433
|
-
addStyle(`@keyframes rk-sklo-base {
|
|
3434
|
-
0%,10% { transform: scale(1.12); filter: none; }
|
|
3435
|
-
16% { transform: scale(1.125) rotate(0.4deg); filter: brightness(1.12) contrast(1.06); }
|
|
3436
|
-
50% { transform: scale(1.1) rotate(-0.5deg); filter: saturate(0.65) brightness(1.05) blur(0.5px); }
|
|
3437
|
-
72% { transform: scale(1.12); filter: none; }
|
|
3438
|
-
100% { transform: scale(1.12); filter: none; }
|
|
3439
|
-
}
|
|
3440
|
-
${CHAOS_SEL} { animation: rk-sklo-base 11s ease-in-out infinite; }
|
|
3441
|
-
@keyframes rk-sklo-fly {
|
|
3442
|
-
0%, 12% { transform: translate(0, 0) rotate(0); opacity: 1; }
|
|
3443
|
-
30% { transform: translate(var(--rk-gx), var(--rk-gy)) rotate(var(--rk-gr)); opacity: 0.92; }
|
|
3444
|
-
52% { transform: translate(calc(var(--rk-gx) * 1.18), calc(var(--rk-gy) * 1.18)) rotate(calc(var(--rk-gr) * 1.25)); opacity: 0.85; }
|
|
3445
|
-
74% { transform: translate(0, 0) rotate(0); opacity: 1; }
|
|
3446
|
-
100% { transform: translate(0, 0) rotate(0); opacity: 1; }
|
|
3447
|
-
}
|
|
3448
|
-
[data-rk-shard] { animation: rk-sklo-fly 11s cubic-bezier(0.55, 0, 0.3, 1) infinite; }`);
|
|
3449
|
-
const shards = [...document.querySelectorAll("h1, h2, h3, h4, p, li, img, button, a")].filter((el) => {
|
|
3450
|
-
if (el.closest("[data-review-kit-host]")) return false;
|
|
3451
|
-
const r = el.getBoundingClientRect();
|
|
3452
|
-
return r.width > 8 && r.height > 8 && r.bottom > -200 && r.top < window.innerHeight + 200;
|
|
3453
|
-
}).slice(0, 90);
|
|
3454
|
-
const rules = [];
|
|
3455
|
-
shards.forEach((el, i) => {
|
|
3456
|
-
const angle = i * 137.5 * Math.PI / 180;
|
|
3457
|
-
const dist = 18 + i * 29 % 46;
|
|
3458
|
-
rules.push(
|
|
3459
|
-
`[data-rk-shard="${i}"] { --rk-gx: ${(Math.cos(angle) * dist).toFixed(1)}vw; --rk-gy: ${(Math.sin(angle) * dist).toFixed(1)}vh; --rk-gr: ${i * 97 % 640 - 320}deg; }`
|
|
3460
|
-
);
|
|
3461
|
-
el.setAttribute("data-rk-shard", String(i));
|
|
3462
|
-
});
|
|
3463
|
-
addStyle(rules.join("\n"));
|
|
3464
|
-
cleanups.push(() => {
|
|
3465
|
-
for (const el of shards) el.removeAttribute("data-rk-shard");
|
|
3466
|
-
});
|
|
3467
|
-
const cracks = document.createElement("div");
|
|
3468
|
-
cracks.className = "rk-fx-cracks";
|
|
3469
|
-
cracks.innerHTML = Array.from({ length: 9 }, (_, i) => {
|
|
3470
|
-
const angle = i * 40 + i % 3 * 7;
|
|
3471
|
-
return `<span style="transform: rotate(${angle}deg); animation-delay: ${(i * 0.05).toFixed(2)}s"></span>`;
|
|
3472
|
-
}).join("");
|
|
3473
|
-
layer.appendChild(cracks);
|
|
3474
|
-
cleanups.push(() => cracks.remove());
|
|
3475
|
-
decayText();
|
|
3476
|
-
every(() => wave({ kind: "burst", glyphs: ["\u2727", "\u2756", "\u{1F4A0}", "\u{1F9CA}"], count: 26, durationMs: 5e3 }), 11e3);
|
|
3477
|
-
wave({ kind: "burst", glyphs: ["\u2727", "\u2756", "\u{1F4A0}"], count: 26, durationMs: 5e3 });
|
|
3478
|
-
});
|
|
3479
|
-
var startVir = bigEffect(({ layer, reduced, addStyle, later, wave, decayText, cleanups }) => {
|
|
3480
|
-
if (reduced) {
|
|
3481
|
-
addStyle(`@keyframes rk-vir-soft { 0%,100% { filter: none; } 50% { filter: hue-rotate(50deg); } }
|
|
3482
|
-
${CHAOS_SEL} { animation: rk-vir-soft 9s ease-in-out infinite; }`);
|
|
3483
|
-
wave({ kind: "burst", glyphs: ["\u{1F300}"], count: 8, durationMs: 8e3 });
|
|
3484
|
-
return;
|
|
3485
|
-
}
|
|
3486
|
-
addStyle(`@keyframes rk-vir1 {
|
|
3487
|
-
0% { transform: scale(1.25) rotate(0deg); filter: none; }
|
|
3488
|
-
30% { transform: scale(1.31) rotate(4deg); filter: hue-rotate(50deg) saturate(1.3) blur(0.5px); }
|
|
3489
|
-
60% { transform: scale(1.28) rotate(-3.4deg); filter: hue-rotate(140deg) saturate(0.8) blur(1px); }
|
|
3490
|
-
100% { transform: scale(1.25) rotate(0deg); filter: none; }
|
|
3491
|
-
}
|
|
3492
|
-
${CHAOS_SEL} { animation: rk-vir1 6.5s ease-in-out infinite; }`);
|
|
3493
|
-
later(() => {
|
|
3494
|
-
addStyle(`@keyframes rk-vir2 {
|
|
3495
|
-
0% { transform: scale(1.25) rotate(0deg); filter: hue-rotate(0deg) saturate(1.4); }
|
|
3496
|
-
25% { transform: scale(1.42) rotate(9deg); filter: hue-rotate(90deg) saturate(1.9) blur(1.6px); }
|
|
3497
|
-
50% { transform: scale(1.55) rotate(-7deg); filter: hue-rotate(200deg) saturate(0.6) contrast(1.15) blur(2.6px); }
|
|
3498
|
-
75% { transform: scale(1.38) rotate(10deg); filter: hue-rotate(300deg) saturate(1.8) blur(1.2px); }
|
|
3499
|
-
100% { transform: scale(1.25) rotate(0deg); filter: hue-rotate(360deg) saturate(1.4); }
|
|
3500
|
-
}
|
|
3501
|
-
${CHAOS_SEL} { animation: rk-vir2 5.5s ease-in-out infinite; }
|
|
3502
|
-
@keyframes rk-vir-text { 0%,100% { letter-spacing: normal; } 50% { letter-spacing: 0.16em; text-shadow: 3px 0 rgba(0,180,255,0.5), -3px 0 rgba(255,60,160,0.5); } }
|
|
3503
|
-
h1, h2, h3, p, a, li, button { animation: rk-vir-text 4.5s ease-in-out infinite; }`);
|
|
3504
|
-
decayText();
|
|
3505
|
-
}, 12e3);
|
|
3506
|
-
const GLYPHS = ["\u{1F300}", "\u2728", "\u{1F343}", "\u{1F4C4}", "\u2604\uFE0F"];
|
|
3507
|
-
const bits = [];
|
|
3508
|
-
const cx = () => window.innerWidth / 2;
|
|
3509
|
-
const cy = () => window.innerHeight / 2;
|
|
3510
|
-
const maxR = () => Math.hypot(window.innerWidth, window.innerHeight) / 2 + 60;
|
|
3511
|
-
for (let i = 0; i < 36; i++) {
|
|
3512
|
-
const el = document.createElement("span");
|
|
3513
|
-
el.className = "rk-fx-particle";
|
|
3514
|
-
el.textContent = GLYPHS[i % GLYPHS.length];
|
|
3515
|
-
el.style.fontSize = `${13 + i * 11 % 16}px`;
|
|
3516
|
-
layer.appendChild(el);
|
|
3517
|
-
bits.push({ el, r: maxR() * ((i + 1) / 36), a: i * 0.7, v: 0.6 + i % 5 * 0.16 });
|
|
3518
|
-
}
|
|
3519
|
-
let raf = 0;
|
|
3520
|
-
const tick = () => {
|
|
3521
|
-
raf = requestAnimationFrame(tick);
|
|
3522
|
-
for (const bit of bits) {
|
|
3523
|
-
bit.a += 0.014 * bit.v * (1 + 140 / Math.max(bit.r, 40));
|
|
3524
|
-
bit.r -= 0.55 * bit.v;
|
|
3525
|
-
if (bit.r < 16) bit.r = maxR();
|
|
3526
|
-
bit.el.style.transform = `translate3d(${cx() + Math.cos(bit.a) * bit.r}px, ${cy() + Math.sin(bit.a) * bit.r}px, 0) rotate(${bit.a}rad)`;
|
|
3527
|
-
bit.el.style.opacity = `${Math.min(1, bit.r / 120)}`;
|
|
3528
|
-
}
|
|
3529
|
-
};
|
|
3530
|
-
raf = requestAnimationFrame(tick);
|
|
3531
|
-
cleanups.push(() => {
|
|
3532
|
-
cancelAnimationFrame(raf);
|
|
3533
|
-
bits.forEach((bit) => bit.el.remove());
|
|
3534
|
-
});
|
|
3535
|
-
});
|
|
3536
|
-
var startCrt = bigEffect(({ layer, reduced, addStyle, every, wave, decayText, cleanups }) => {
|
|
3537
|
-
if (reduced) {
|
|
3538
|
-
addStyle(`${CHAOS_SEL} { filter: sepia(0.7) hue-rotate(55deg) saturate(1.6) contrast(1.05); transition: filter 2s ease; }`);
|
|
3539
|
-
return;
|
|
3011
|
+
function cancelWhenReady() {
|
|
3012
|
+
if (loaded) return loaded.cancelEffects();
|
|
3013
|
+
if (loading && queued > 0) {
|
|
3014
|
+
loading.then((mod) => mod.cancelEffects()).catch(() => void 0);
|
|
3015
|
+
return true;
|
|
3540
3016
|
}
|
|
3541
|
-
|
|
3542
|
-
svg.setAttribute("data-rk-fx", "");
|
|
3543
|
-
svg.setAttribute("width", "0");
|
|
3544
|
-
svg.setAttribute("height", "0");
|
|
3545
|
-
svg.style.position = "absolute";
|
|
3546
|
-
svg.innerHTML = `<defs><filter id="rk-crt-tear" x="-10%" y="-10%" width="120%" height="120%">
|
|
3547
|
-
<feTurbulence type="turbulence" baseFrequency="0.002 0.09" numOctaves="1" result="n" seed="11">
|
|
3548
|
-
<animate attributeName="seed" dur="3s" values="11;37;11" repeatCount="indefinite"/>
|
|
3549
|
-
</feTurbulence>
|
|
3550
|
-
<feDisplacementMap in="SourceGraphic" in2="n" scale="0" xChannelSelector="R" yChannelSelector="G">
|
|
3551
|
-
<animate attributeName="scale" dur="8s" values="0;0;26;4;0;0" keyTimes="0;0.55;0.62;0.7;0.78;1" repeatCount="indefinite"/>
|
|
3552
|
-
</feDisplacementMap>
|
|
3553
|
-
</filter></defs>`;
|
|
3554
|
-
document.body.appendChild(svg);
|
|
3555
|
-
cleanups.push(() => svg.remove());
|
|
3556
|
-
addStyle(`@keyframes rk-crt-hold {
|
|
3557
|
-
0%, 60% { transform: scale(1.16) translate(0, 0); }
|
|
3558
|
-
64% { transform: scale(1.16) translate(-3px, 14px) skewX(-0.8deg); }
|
|
3559
|
-
68% { transform: scale(1.16) translate(2px, -8px); }
|
|
3560
|
-
74%, 100% { transform: scale(1.16) translate(0, 0); }
|
|
3561
|
-
}
|
|
3562
|
-
${CHAOS_SEL} {
|
|
3563
|
-
filter: url(#rk-crt-tear) sepia(1) hue-rotate(55deg) saturate(2.6) contrast(1.22) brightness(0.92);
|
|
3564
|
-
animation: rk-crt-hold 8s linear infinite;
|
|
3565
|
-
}
|
|
3566
|
-
@keyframes rk-crt-text { 0%,100% { text-shadow: 1px 0 rgba(0,255,120,0.5); } 50% { text-shadow: -2px 0 rgba(0,255,120,0.7), 2px 0 rgba(0,120,60,0.5); letter-spacing: 0.06em; } }
|
|
3567
|
-
h1, h2, h3, p, a, li, button { animation: rk-crt-text 5s ease-in-out infinite; }`);
|
|
3568
|
-
const overlay = document.createElement("div");
|
|
3569
|
-
overlay.className = "rk-fx-crt";
|
|
3570
|
-
overlay.innerHTML = '<div class="rk-fx-crt-scan"></div><div class="rk-fx-crt-roll"></div><div class="rk-fx-crt-vignette"></div><div class="rk-fx-crt-osd">KAN\xC1L 69 \xB7 SLAB\xDD SIGN\xC1L</div>';
|
|
3571
|
-
layer.appendChild(overlay);
|
|
3572
|
-
cleanups.push(() => overlay.remove());
|
|
3573
|
-
decayText();
|
|
3574
|
-
every(() => wave({ kind: "rain", glyphs: ["\u{1F4FA}", "\u{1F4E1}", "\u{1D34D}"], count: 10, durationMs: 7e3 }), 16e3);
|
|
3575
|
-
});
|
|
3576
|
-
function startBanner({ layer, reduced }) {
|
|
3577
|
-
const banner = document.createElement("div");
|
|
3578
|
-
banner.className = "rk-fx-banner";
|
|
3579
|
-
banner.textContent = "\u{1F6A8} KOKOT ALERT \u{1F6A8} KOKOT ALERT \u{1F6A8} KOKOT ALERT \u{1F6A8}";
|
|
3580
|
-
if (reduced) banner.classList.add("rk-fx-banner-still");
|
|
3581
|
-
layer.appendChild(banner);
|
|
3582
|
-
return () => banner.remove();
|
|
3583
|
-
}
|
|
3584
|
-
function startVrtule({ reduced }) {
|
|
3585
|
-
const style = document.createElement("style");
|
|
3586
|
-
style.setAttribute("data-rk-fx", "vrtule");
|
|
3587
|
-
style.textContent = reduced ? `@keyframes rk-vrtula { 0%,100% { transform: rotate(0); } 50% { transform: rotate(3deg); } }
|
|
3588
|
-
img { animation: rk-vrtula 4s ease-in-out infinite; }` : `@keyframes rk-vrtula { from { transform: rotate(0) scale(1); } 50% { transform: rotate(180deg) scale(0.9); } to { transform: rotate(360deg) scale(1); } }
|
|
3589
|
-
img { animation: rk-vrtula 3.6s ease-in-out infinite; }`;
|
|
3590
|
-
document.head.appendChild(style);
|
|
3591
|
-
return () => style.remove();
|
|
3592
|
-
}
|
|
3593
|
-
function makeChase(options) {
|
|
3594
|
-
return function startChase({ layer, reduced }) {
|
|
3595
|
-
const critters = [];
|
|
3596
|
-
const count = reduced ? Math.min(4, options.count) : options.count;
|
|
3597
|
-
for (let i = 0; i < count; i++) {
|
|
3598
|
-
const el = document.createElement("span");
|
|
3599
|
-
el.className = "rk-fx-particle";
|
|
3600
|
-
el.textContent = options.glyphs[i % options.glyphs.length];
|
|
3601
|
-
el.style.fontSize = `${options.sizePx(i)}px`;
|
|
3602
|
-
layer.appendChild(el);
|
|
3603
|
-
critters.push({ el, x: window.innerWidth / 2, y: window.innerHeight / 2, seed: i * 137 });
|
|
3604
|
-
}
|
|
3605
|
-
const wobble = options.wobbleT ?? 400;
|
|
3606
|
-
let raf = 0;
|
|
3607
|
-
const tick = (t) => {
|
|
3608
|
-
raf = requestAnimationFrame(tick);
|
|
3609
|
-
const root = layer.getRootNode();
|
|
3610
|
-
const chips = [...root.querySelectorAll(".rk-peer-cursor")].filter((c) => c.style.opacity !== "0").map((c) => {
|
|
3611
|
-
const m = /translate3d\(([-\d.]+)px, ([-\d.]+)px/.exec(c.style.transform);
|
|
3612
|
-
return m ? { x: parseFloat(m[1]), y: parseFloat(m[2]) } : null;
|
|
3613
|
-
}).filter((p) => p !== null);
|
|
3614
|
-
chips.push({ x: lastPointerFallback.x, y: lastPointerFallback.y });
|
|
3615
|
-
for (const critter of critters) {
|
|
3616
|
-
const target = chips[critter.seed % chips.length];
|
|
3617
|
-
const orbit = reduced ? 14 : options.orbit(critter.seed);
|
|
3618
|
-
const wx = target.x + Math.cos(t / wobble + critter.seed) * orbit;
|
|
3619
|
-
const wy = target.y + Math.sin(t / (wobble * 0.82) + critter.seed) * orbit;
|
|
3620
|
-
const prevX = critter.x;
|
|
3621
|
-
critter.x += (wx - critter.x) * options.lag;
|
|
3622
|
-
critter.y += (wy - critter.y) * options.lag;
|
|
3623
|
-
const face = options.flip && critter.x < prevX ? " scaleX(-1)" : "";
|
|
3624
|
-
critter.el.style.transform = `translate3d(${critter.x}px, ${critter.y}px, 0)${face}`;
|
|
3625
|
-
}
|
|
3626
|
-
};
|
|
3627
|
-
raf = requestAnimationFrame(tick);
|
|
3628
|
-
const onMove = (event) => {
|
|
3629
|
-
lastPointerFallback.x = event.clientX;
|
|
3630
|
-
lastPointerFallback.y = event.clientY;
|
|
3631
|
-
};
|
|
3632
|
-
document.addEventListener("pointermove", onMove, { passive: true });
|
|
3633
|
-
return () => {
|
|
3634
|
-
cancelAnimationFrame(raf);
|
|
3635
|
-
document.removeEventListener("pointermove", onMove);
|
|
3636
|
-
for (const critter of critters) critter.el.remove();
|
|
3637
|
-
};
|
|
3638
|
-
};
|
|
3017
|
+
return false;
|
|
3639
3018
|
}
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
style.setAttribute("data-rk-fx", "");
|
|
3644
|
-
style.textContent = css;
|
|
3645
|
-
document.head.appendChild(style);
|
|
3646
|
-
return () => style.remove();
|
|
3647
|
-
}
|
|
3648
|
-
var PAGE_SEL = "body > :not([data-review-kit-host]):not(script):not(style)";
|
|
3649
|
-
function startDisko({ layer, reduced }) {
|
|
3650
|
-
const remove = styleEffect(
|
|
3651
|
-
reduced ? `@keyframes rk-disko { 0%,100% { filter: none; } 50% { filter: hue-rotate(60deg) saturate(1.2); } }
|
|
3652
|
-
${PAGE_SEL} { animation: rk-disko 8s ease-in-out infinite; }` : `@keyframes rk-disko { from { filter: hue-rotate(0deg) saturate(1.35); } to { filter: hue-rotate(360deg) saturate(1.35); } }
|
|
3653
|
-
${PAGE_SEL} { animation: rk-disko 4s linear infinite; }`
|
|
3654
|
-
);
|
|
3655
|
-
spawnParticles(layer, { kind: "rain", glyphs: ["\u2728", "\u{1FAA9}", "\u{1F483}", "\u{1F57A}"], count: 26}, reduced, 15e3);
|
|
3656
|
-
return remove;
|
|
3019
|
+
function setEffectBroadcaster(fn) {
|
|
3020
|
+
broadcaster = fn;
|
|
3021
|
+
loaded?.setEffectBroadcaster(fn);
|
|
3657
3022
|
}
|
|
3658
|
-
function
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
}
|
|
3662
|
-
return styleEffect(`@keyframes rk-zrkadlo {
|
|
3663
|
-
0%, 100% { transform: perspective(1400px) rotateY(0); }
|
|
3664
|
-
35%, 65% { transform: perspective(1400px) rotateY(180deg); }
|
|
3665
|
-
}
|
|
3666
|
-
${PAGE_SEL} { animation: rk-zrkadlo 12s ease-in-out both; transform-origin: 50% 50%; }`);
|
|
3667
|
-
}
|
|
3668
|
-
function startPohreb({ layer, reduced }) {
|
|
3669
|
-
const remove = styleEffect(`@keyframes rk-pohreb { from { filter: none; } to { filter: grayscale(1) brightness(0.82) sepia(0.15); } }
|
|
3670
|
-
${PAGE_SEL} { animation: rk-pohreb 5s ease-out both; }`);
|
|
3671
|
-
spawnParticles(layer, { kind: "rain", glyphs: ["\u{1F940}", "\u26B0\uFE0F", "\u{1F56F}\uFE0F", "\u{1F5A4}"], count: reduced ? 8 : 22}, reduced, 14e3);
|
|
3672
|
-
return remove;
|
|
3673
|
-
}
|
|
3674
|
-
function startLaser({ layer, reduced }) {
|
|
3675
|
-
const beams = [];
|
|
3676
|
-
const count = reduced ? 2 : 5;
|
|
3677
|
-
const hues = [330, 190, 120, 45, 265];
|
|
3678
|
-
for (let i = 0; i < count; i++) {
|
|
3679
|
-
const beam = document.createElement("div");
|
|
3680
|
-
beam.className = "rk-fx-laser";
|
|
3681
|
-
beam.style.background = `linear-gradient(90deg, transparent, hsla(${hues[i % hues.length]}, 100%, 60%, 0.55), transparent)`;
|
|
3682
|
-
beam.style.left = `${i % 2 * 100}%`;
|
|
3683
|
-
beam.style.animationDuration = `${3.4 + i * 0.6}s`;
|
|
3684
|
-
beam.style.animationDelay = `${i * 0.45}s`;
|
|
3685
|
-
if (i % 2) beam.style.animationDirection = "reverse";
|
|
3686
|
-
layer.appendChild(beam);
|
|
3687
|
-
beams.push(beam);
|
|
3688
|
-
}
|
|
3689
|
-
return () => beams.forEach((b) => b.remove());
|
|
3690
|
-
}
|
|
3691
|
-
function startKura({ layer, reduced }) {
|
|
3692
|
-
const hen = document.createElement("span");
|
|
3693
|
-
hen.className = "rk-fx-kura";
|
|
3694
|
-
hen.textContent = "\u{1F414}";
|
|
3695
|
-
layer.appendChild(hen);
|
|
3696
|
-
const props = [hen];
|
|
3697
|
-
const timers = [];
|
|
3698
|
-
const walkMs = reduced ? 16e3 : 11e3;
|
|
3699
|
-
hen.style.animationDuration = `${walkMs}ms`;
|
|
3700
|
-
if (!reduced) {
|
|
3701
|
-
for (let i = 1; i <= 5; i++) {
|
|
3702
|
-
timers.push(
|
|
3703
|
-
window.setTimeout(() => {
|
|
3704
|
-
const egg = document.createElement("span");
|
|
3705
|
-
egg.className = "rk-fx-egg";
|
|
3706
|
-
egg.textContent = "\u{1F95A}";
|
|
3707
|
-
egg.style.left = `${i / 6 * 100}%`;
|
|
3708
|
-
layer.appendChild(egg);
|
|
3709
|
-
props.push(egg);
|
|
3710
|
-
timers.push(
|
|
3711
|
-
window.setTimeout(() => {
|
|
3712
|
-
egg.textContent = "\u{1F423}";
|
|
3713
|
-
}, 2600 + i * 400)
|
|
3714
|
-
);
|
|
3715
|
-
}, walkMs * i / 6)
|
|
3716
|
-
);
|
|
3717
|
-
}
|
|
3718
|
-
}
|
|
3719
|
-
return () => {
|
|
3720
|
-
timers.forEach((t) => window.clearTimeout(t));
|
|
3721
|
-
props.forEach((p) => p.remove());
|
|
3722
|
-
};
|
|
3023
|
+
function setEffectAssetsUrl(url) {
|
|
3024
|
+
assetsUrl = url ?? null;
|
|
3025
|
+
loaded?.setFxAssetsUrl(assetsUrl);
|
|
3723
3026
|
}
|
|
3724
|
-
function
|
|
3725
|
-
|
|
3726
|
-
"\u26A0\uFE0F Kritick\xE1 chyba: str\xE1nka je pr\xEDli\u0161 pekn\xE1",
|
|
3727
|
-
"\u{1F525} 69 \u013Eud\xED pr\xE1ve pozer\xE1 tento button",
|
|
3728
|
-
"\u{1F4BE} Uklad\xE1m tvoje hriechy\u2026",
|
|
3729
|
-
"\u{1F4C8} Konverzia st\xFApla o 420 %",
|
|
3730
|
-
"\u{1F9E0} AI navrhuje: prerob to cel\xE9",
|
|
3731
|
-
"\u{1F36A} T\xE1to str\xE1nka \u017Eerie kol\xE1\u010Diky",
|
|
3732
|
-
"\u{1F4DE} Vol\xE1 ti klient. Zdvihni.",
|
|
3733
|
-
"\u{1F4B8} Fakt\xFAra po splatnosti (odjak\u017Eiva)",
|
|
3734
|
-
"\u{1F6F8} Zisten\xE1 mimozemsk\xE1 aktivita v p\xE4ti\u010Dke",
|
|
3735
|
-
"\u2705 Ni\u010D sa nepodarilo \xFAspe\u0161ne"
|
|
3736
|
-
];
|
|
3737
|
-
const toasts = [];
|
|
3738
|
-
const timers = [];
|
|
3739
|
-
const total = reduced ? 4 : MESSAGES.length;
|
|
3740
|
-
for (let i = 0; i < total; i++) {
|
|
3741
|
-
timers.push(
|
|
3742
|
-
window.setTimeout(() => {
|
|
3743
|
-
const toast2 = document.createElement("div");
|
|
3744
|
-
toast2.className = "rk-fx-toast";
|
|
3745
|
-
toast2.textContent = MESSAGES[i % MESSAGES.length];
|
|
3746
|
-
toast2.style.top = `${14 + i % 5 * 58}px`;
|
|
3747
|
-
layer.appendChild(toast2);
|
|
3748
|
-
toasts.push(toast2);
|
|
3749
|
-
timers.push(window.setTimeout(() => toast2.remove(), 5200));
|
|
3750
|
-
}, i * (reduced ? 1800 : 950))
|
|
3751
|
-
);
|
|
3752
|
-
}
|
|
3753
|
-
return () => {
|
|
3754
|
-
timers.forEach((t) => window.clearTimeout(t));
|
|
3755
|
-
toasts.forEach((t) => t.remove());
|
|
3756
|
-
};
|
|
3027
|
+
function cancelEffects() {
|
|
3028
|
+
return cancelWhenReady();
|
|
3757
3029
|
}
|
|
3758
|
-
var EFFECTS = {
|
|
3759
|
-
ondro: { kind: "custom", durationMs: ONDRO_MS, start: startOndro },
|
|
3760
|
-
lava: { kind: "custom", durationMs: BIG_MS, start: startLava },
|
|
3761
|
-
sklo: { kind: "custom", durationMs: BIG_MS, start: startSklo },
|
|
3762
|
-
vir: { kind: "custom", durationMs: BIG_MS, start: startVir },
|
|
3763
|
-
crt: { kind: "custom", durationMs: BIG_MS, start: startCrt },
|
|
3764
|
-
hovno: { kind: "rain", glyphs: ["\u{1F4A9}"], count: 44, durationMs: 4200 },
|
|
3765
|
-
konfety: { kind: "burst", glyphs: ["\u{1F389}", "\u{1F38A}", "\u2728"], count: 56, durationMs: 3600 },
|
|
3766
|
-
srdiecka: { kind: "rain", glyphs: ["\u2764\uFE0F", "\u{1F49A}", "\u{1F49B}"], count: 40, durationMs: 4200 },
|
|
3767
|
-
sneh: { kind: "rain", glyphs: ["\u2744\uFE0F", "\u{1F328}\uFE0F"], count: 48, durationMs: 5200 },
|
|
3768
|
-
zemetrasenie: { kind: "rain", glyphs: ["\u{1FAA8}", "\u{1F9F1}"], count: 18, durationMs: 2400, shake: true },
|
|
3769
|
-
"69": { kind: "burst", glyphs: ["\u{1F346}", "\u{1F351}", "\u{1F4A6}"], count: 69, durationMs: NICE_MS },
|
|
3770
|
-
kokot: { kind: "custom", durationMs: 14500, start: startBanner },
|
|
3771
|
-
vrtule: { kind: "custom", durationMs: NICE_MS, start: startVrtule },
|
|
3772
|
-
muchy: {
|
|
3773
|
-
kind: "custom",
|
|
3774
|
-
durationMs: NICE_MS,
|
|
3775
|
-
start: makeChase({ glyphs: ["\u{1FAB0}"], count: 14, sizePx: (i) => 12 + i % 3 * 4, orbit: (s) => 26 + s % 20, lag: 0.12, wobbleT: 400 })
|
|
3776
|
-
},
|
|
3777
|
-
pes: {
|
|
3778
|
-
kind: "custom",
|
|
3779
|
-
durationMs: 12e3,
|
|
3780
|
-
start: makeChase({ glyphs: ["\u{1F415}", "\u{1F429}", "\u{1F9AE}"], count: 3, sizePx: (i) => 26 + i % 2 * 6, orbit: (s) => 46 + s % 30, lag: 0.055, wobbleT: 900, flip: true })
|
|
3781
|
-
},
|
|
3782
|
-
pivo: { kind: "rain", glyphs: ["\u{1F37A}", "\u{1F37B}", "\u{1F37E}"], count: 42, durationMs: 8e3 },
|
|
3783
|
-
nikotin: { kind: "rain", glyphs: ["\u{1F6AC}", "\u{1F4A8}", "\u{1F62E}\u200D\u{1F4A8}"], count: 20, durationMs: 13e3 },
|
|
3784
|
-
matrix: { kind: "rain", glyphs: [..."\u30A2\u30AB\u30B5\u30BF\u30CA0169\uFF8A\uFF8F\uFF94\uFF97\uFF66"], count: 64, durationMs: 12e3, className: "rk-fx-matrix" },
|
|
3785
|
-
disko: { kind: "custom", durationMs: 15e3, start: startDisko },
|
|
3786
|
-
zrkadlo: { kind: "custom", durationMs: 12e3, start: startZrkadlo },
|
|
3787
|
-
pohreb: { kind: "custom", durationMs: 14e3, start: startPohreb },
|
|
3788
|
-
laser: { kind: "custom", durationMs: 12e3, start: startLaser },
|
|
3789
|
-
kura: { kind: "custom", durationMs: 11500, start: startKura },
|
|
3790
|
-
spam: { kind: "custom", durationMs: 11e3, start: startSpam }
|
|
3791
|
-
};
|
|
3792
3030
|
function runEffect(name, layerHost) {
|
|
3031
|
+
if (!isEffectCommand(name)) return false;
|
|
3793
3032
|
if (name === "stop") {
|
|
3794
|
-
|
|
3033
|
+
cancelWhenReady();
|
|
3795
3034
|
return true;
|
|
3796
3035
|
}
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
layerHost.appendChild(layer);
|
|
3804
|
-
let customCleanup = null;
|
|
3805
|
-
let shakeCleanup = null;
|
|
3806
|
-
if (spec.kind === "custom") {
|
|
3807
|
-
customCleanup = spec.start({ layer, reduced });
|
|
3808
|
-
} else {
|
|
3809
|
-
spawnParticles(layer, spec, reduced, duration);
|
|
3810
|
-
if (spec.shake && !reduced) shakeCleanup = runShake();
|
|
3811
|
-
}
|
|
3812
|
-
let timer = 0;
|
|
3813
|
-
const cancel = () => {
|
|
3814
|
-
window.clearTimeout(timer);
|
|
3815
|
-
customCleanup?.();
|
|
3816
|
-
shakeCleanup?.();
|
|
3817
|
-
layer.remove();
|
|
3818
|
-
active.delete(cancel);
|
|
3819
|
-
};
|
|
3820
|
-
timer = window.setTimeout(cancel, duration + 1200);
|
|
3821
|
-
active.add(cancel);
|
|
3036
|
+
queued += 1;
|
|
3037
|
+
void load().then((mod) => {
|
|
3038
|
+
queued = Math.max(0, queued - 1);
|
|
3039
|
+
mod.runEffect(name, layerHost);
|
|
3040
|
+
}).catch(() => {
|
|
3041
|
+
});
|
|
3822
3042
|
return true;
|
|
3823
3043
|
}
|
|
3824
3044
|
|
|
@@ -4118,21 +3338,24 @@ var SHORTCUTS = [
|
|
|
4118
3338
|
}
|
|
4119
3339
|
}
|
|
4120
3340
|
];
|
|
3341
|
+
|
|
3342
|
+
// src/client/emblemaPush.ts
|
|
3343
|
+
import { useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
4121
3344
|
var AUTO_PUSH_DEBOUNCE_MS = 500;
|
|
4122
3345
|
function useEmblemaAutoPush(state, dispatch, config) {
|
|
4123
3346
|
const emblema = config.emblema;
|
|
4124
|
-
const sessionRef =
|
|
3347
|
+
const sessionRef = useRef2(state.session);
|
|
4125
3348
|
sessionRef.current = state.session;
|
|
4126
|
-
const lastSent =
|
|
4127
|
-
const inFlight =
|
|
4128
|
-
const alive =
|
|
4129
|
-
|
|
3349
|
+
const lastSent = useRef2(/* @__PURE__ */ new Map());
|
|
3350
|
+
const inFlight = useRef2(false);
|
|
3351
|
+
const alive = useRef2(true);
|
|
3352
|
+
useEffect2(() => {
|
|
4130
3353
|
alive.current = true;
|
|
4131
3354
|
return () => {
|
|
4132
3355
|
alive.current = false;
|
|
4133
3356
|
};
|
|
4134
3357
|
}, []);
|
|
4135
|
-
const flushRef =
|
|
3358
|
+
const flushRef = useRef2(() => {
|
|
4136
3359
|
});
|
|
4137
3360
|
flushRef.current = () => {
|
|
4138
3361
|
if (!alive.current || !emblema) return;
|
|
@@ -4154,12 +3377,12 @@ function useEmblemaAutoPush(state, dispatch, config) {
|
|
|
4154
3377
|
for (const item of changed) lastSent.current.set(item.id, item);
|
|
4155
3378
|
if (alive.current) dispatch({ type: "EMBLEMA_PUSH_STATUS", status: "ok" });
|
|
4156
3379
|
} else if (alive.current) {
|
|
4157
|
-
dispatch({ type: "EMBLEMA_PUSH_STATUS", status: "offline" });
|
|
3380
|
+
dispatch({ type: "EMBLEMA_PUSH_STATUS", status: result.reason === "rejected" ? "rejected" : "offline" });
|
|
4158
3381
|
}
|
|
4159
3382
|
});
|
|
4160
3383
|
};
|
|
4161
3384
|
const items = state.session?.items;
|
|
4162
|
-
|
|
3385
|
+
useEffect2(() => {
|
|
4163
3386
|
if (!emblema || !items) return;
|
|
4164
3387
|
for (const id of [...lastSent.current.keys()]) {
|
|
4165
3388
|
if (!items.some((item) => item.id === id)) lastSent.current.delete(id);
|
|
@@ -4173,6 +3396,9 @@ function useEmblemaAutoPush(state, dispatch, config) {
|
|
|
4173
3396
|
}, [items, emblema]);
|
|
4174
3397
|
}
|
|
4175
3398
|
|
|
3399
|
+
// src/client/sync.ts
|
|
3400
|
+
import { useEffect as useEffect3, useMemo as useMemo2, useRef as useRef3 } from "react";
|
|
3401
|
+
|
|
4176
3402
|
// realtime/client/rkSync.ts
|
|
4177
3403
|
var RK_SYNC_PROTOCOL_VERSION = 1;
|
|
4178
3404
|
var BACKOFF_BASE_MS = 1e3;
|
|
@@ -4303,8 +3529,8 @@ function createRkSync(options) {
|
|
|
4303
3529
|
log(`welcome: ${items.length} items, ${peers.length} peers, ${deleted.length} tombstones, flushing ${queue.length}`);
|
|
4304
3530
|
safely(() => handlers.onSnapshot?.(items, peers, deleted));
|
|
4305
3531
|
while (queue.length > 0) {
|
|
4306
|
-
const
|
|
4307
|
-
if (!rawSend(
|
|
3532
|
+
const queued2 = queue[0];
|
|
3533
|
+
if (!rawSend(queued2)) break;
|
|
4308
3534
|
queue.shift();
|
|
4309
3535
|
}
|
|
4310
3536
|
break;
|
|
@@ -4315,9 +3541,13 @@ function createRkSync(options) {
|
|
|
4315
3541
|
pongTimer = null;
|
|
4316
3542
|
}
|
|
4317
3543
|
break;
|
|
4318
|
-
case "error":
|
|
3544
|
+
case "error": {
|
|
4319
3545
|
log("server error:", msg.code, msg.message);
|
|
3546
|
+
const code = typeof msg.code === "string" ? msg.code : "error";
|
|
3547
|
+
const message = typeof msg.message === "string" ? msg.message : "";
|
|
3548
|
+
safely(() => handlers.onError?.(code, message));
|
|
4320
3549
|
break;
|
|
3550
|
+
}
|
|
4321
3551
|
case "presence:join": {
|
|
4322
3552
|
const peer = msg.peer;
|
|
4323
3553
|
if (peer && typeof peer.id === "string") safely(() => handlers.onPeerJoin?.(peer));
|
|
@@ -4356,8 +3586,8 @@ function createRkSync(options) {
|
|
|
4356
3586
|
if (typeof msg.peerId === "string") {
|
|
4357
3587
|
const peerId = msg.peerId;
|
|
4358
3588
|
const itemId = typeof msg.itemId === "string" ? msg.itemId : null;
|
|
4359
|
-
const
|
|
4360
|
-
safely(() => handlers.onPeerTyping?.(peerId, itemId,
|
|
3589
|
+
const active = msg.active === true;
|
|
3590
|
+
safely(() => handlers.onPeerTyping?.(peerId, itemId, active));
|
|
4361
3591
|
}
|
|
4362
3592
|
break;
|
|
4363
3593
|
case "item:add": {
|
|
@@ -4388,6 +3618,8 @@ function createRkSync(options) {
|
|
|
4388
3618
|
safely(() => handlers.onItemDelete?.(id, authorId));
|
|
4389
3619
|
}
|
|
4390
3620
|
break;
|
|
3621
|
+
default:
|
|
3622
|
+
break;
|
|
4391
3623
|
}
|
|
4392
3624
|
};
|
|
4393
3625
|
const connect = () => {
|
|
@@ -4471,8 +3703,8 @@ function createRkSync(options) {
|
|
|
4471
3703
|
sendSelecting(selector) {
|
|
4472
3704
|
sendEphemeral({ t: "selecting", selector });
|
|
4473
3705
|
},
|
|
4474
|
-
sendTyping(itemId,
|
|
4475
|
-
sendEphemeral({ t: "typing", itemId, active
|
|
3706
|
+
sendTyping(itemId, active) {
|
|
3707
|
+
sendEphemeral({ t: "typing", itemId, active });
|
|
4476
3708
|
},
|
|
4477
3709
|
sendEffect(name) {
|
|
4478
3710
|
sendEphemeral({ t: "fx", name });
|
|
@@ -4517,7 +3749,18 @@ function currentAuthor(name) {
|
|
|
4517
3749
|
}
|
|
4518
3750
|
|
|
4519
3751
|
// src/client/sync.ts
|
|
4520
|
-
var DEFAULT_SYNC_URL = "wss://
|
|
3752
|
+
var DEFAULT_SYNC_URL = "wss://2-59-219-26.sslip.io/rk-sync";
|
|
3753
|
+
function resolveSyncUrl(config) {
|
|
3754
|
+
return typeof config.syncUrl === "string" && config.syncUrl !== "" ? config.syncUrl : DEFAULT_SYNC_URL;
|
|
3755
|
+
}
|
|
3756
|
+
var MIN_SYNC_TOKEN_LENGTH = 8;
|
|
3757
|
+
var warnedShortToken = false;
|
|
3758
|
+
function resolveSyncToken(config) {
|
|
3759
|
+
if (config.sync === false) return null;
|
|
3760
|
+
const explicit = typeof config.syncToken === "string" && config.syncToken !== "" ? config.syncToken : null;
|
|
3761
|
+
const fallback = typeof config.token === "string" && config.token !== "" ? config.token : null;
|
|
3762
|
+
return explicit ?? fallback;
|
|
3763
|
+
}
|
|
4521
3764
|
function toPeerState(peer) {
|
|
4522
3765
|
return {
|
|
4523
3766
|
id: peer.id,
|
|
@@ -4541,24 +3784,47 @@ function sanitizeRemoteItem(raw) {
|
|
|
4541
3784
|
return { ...raw, target };
|
|
4542
3785
|
}
|
|
4543
3786
|
function useRealtimeSync(state, rawDispatch, config, reducer2) {
|
|
4544
|
-
const syncRef =
|
|
4545
|
-
const stateRef =
|
|
3787
|
+
const syncRef = useRef3(null);
|
|
3788
|
+
const stateRef = useRef3(state);
|
|
4546
3789
|
stateRef.current = state;
|
|
4547
|
-
const myIdRef =
|
|
4548
|
-
const
|
|
3790
|
+
const myIdRef = useRef3("");
|
|
3791
|
+
const syncToken = resolveSyncToken(config);
|
|
3792
|
+
const syncUrl = resolveSyncUrl(config);
|
|
3793
|
+
const enabled = syncToken !== null;
|
|
4549
3794
|
const author = state.session?.author ?? "";
|
|
4550
3795
|
const hasSession = state.session !== null;
|
|
4551
|
-
|
|
3796
|
+
useEffect3(() => {
|
|
4552
3797
|
if (!enabled || !hasSession) return;
|
|
3798
|
+
const dispatchGuard = rawDispatch;
|
|
3799
|
+
if (syncToken.length < MIN_SYNC_TOKEN_LENGTH) {
|
|
3800
|
+
dispatchGuard({ type: "SYNC_STATUS", status: "offline", reason: "token-short" });
|
|
3801
|
+
if (!warnedShortToken) {
|
|
3802
|
+
warnedShortToken = true;
|
|
3803
|
+
console.warn(
|
|
3804
|
+
`[review-kit] live sync is off: the token has ${syncToken.length} characters, the sync server needs at least ${MIN_SYNC_TOKEN_LENGTH}. Use a longer \`token\` (or \`syncToken\`) \u2014 it is the secret of your private rooms.`
|
|
3805
|
+
);
|
|
3806
|
+
}
|
|
3807
|
+
return () => dispatchGuard({ type: "SYNC_STATUS", status: "disabled", reason: null });
|
|
3808
|
+
}
|
|
4553
3809
|
const id = reviewerId();
|
|
4554
3810
|
myIdRef.current = id;
|
|
4555
3811
|
const dispatch = rawDispatch;
|
|
4556
3812
|
const sync = createRkSync({
|
|
4557
|
-
token:
|
|
4558
|
-
url:
|
|
3813
|
+
token: syncToken,
|
|
3814
|
+
url: syncUrl,
|
|
4559
3815
|
user: { id, name: author || "Reviewer", color: colorForReviewer(id) },
|
|
4560
3816
|
handlers: {
|
|
4561
|
-
onStatus: (status) => dispatch({
|
|
3817
|
+
onStatus: (status) => dispatch({
|
|
3818
|
+
type: "SYNC_STATUS",
|
|
3819
|
+
status,
|
|
3820
|
+
// Offline with no server verdict = the socket never got through
|
|
3821
|
+
// (server down, CSP connect-src, network); a verdict keeps its reason.
|
|
3822
|
+
...status === "offline" ? { reason: stateRef.current.syncReason ?? "unreachable" } : {}
|
|
3823
|
+
}),
|
|
3824
|
+
onError: (code) => {
|
|
3825
|
+
if (code === "bad-token") dispatch({ type: "SYNC_STATUS", status: "offline", reason: "bad-token" });
|
|
3826
|
+
else if (code === "room-full") dispatch({ type: "SYNC_STATUS", status: "offline", reason: "room-full" });
|
|
3827
|
+
},
|
|
4562
3828
|
onSnapshot: (items, peers, deletedIds = []) => {
|
|
4563
3829
|
const safeItems = items.map(sanitizeRemoteItem).filter((item) => item !== null);
|
|
4564
3830
|
dispatch({ type: "SYNC_SNAPSHOT", items: safeItems });
|
|
@@ -4580,7 +3846,7 @@ function useRealtimeSync(state, rawDispatch, config, reducer2) {
|
|
|
4580
3846
|
runEffect(name, layerRoot);
|
|
4581
3847
|
},
|
|
4582
3848
|
onPeerSelecting: (peerId, selector) => dispatch({ type: "PEER_SELECTING", peerId, selector }),
|
|
4583
|
-
onPeerTyping: (peerId, itemId,
|
|
3849
|
+
onPeerTyping: (peerId, itemId, active) => dispatch({ type: "PEER_TYPING", peerId, itemId, active }),
|
|
4584
3850
|
onItemAdd: (item, authorId) => {
|
|
4585
3851
|
const safeItem = sanitizeRemoteItem(item);
|
|
4586
3852
|
if (!safeItem) return;
|
|
@@ -4615,11 +3881,11 @@ function useRealtimeSync(state, rawDispatch, config, reducer2) {
|
|
|
4615
3881
|
if (activeSyncRef === sync) activeSyncRef = null;
|
|
4616
3882
|
setEffectBroadcaster(null);
|
|
4617
3883
|
sync.stop();
|
|
4618
|
-
dispatch({ type: "SYNC_STATUS", status: "disabled" });
|
|
3884
|
+
dispatch({ type: "SYNC_STATUS", status: "disabled", reason: null });
|
|
4619
3885
|
dispatch({ type: "PEERS_SET", peers: [] });
|
|
4620
3886
|
};
|
|
4621
|
-
}, [enabled, hasSession,
|
|
4622
|
-
const wrapped =
|
|
3887
|
+
}, [enabled, hasSession, syncToken, syncUrl, author, rawDispatch]);
|
|
3888
|
+
const wrapped = useMemo2(() => {
|
|
4623
3889
|
return (action) => {
|
|
4624
3890
|
const prev = stateRef.current;
|
|
4625
3891
|
rawDispatch(action);
|
|
@@ -4641,7 +3907,7 @@ function useRealtimeSync(state, rawDispatch, config, reducer2) {
|
|
|
4641
3907
|
}
|
|
4642
3908
|
};
|
|
4643
3909
|
}, [rawDispatch, reducer2]);
|
|
4644
|
-
|
|
3910
|
+
useEffect3(() => {
|
|
4645
3911
|
if (!enabled) return;
|
|
4646
3912
|
let lastEl = null;
|
|
4647
3913
|
let lastSel = null;
|
|
@@ -4670,18 +3936,21 @@ function useRealtimeSync(state, rawDispatch, config, reducer2) {
|
|
|
4670
3936
|
return () => document.removeEventListener("pointermove", onPointerMove);
|
|
4671
3937
|
}, [enabled]);
|
|
4672
3938
|
const selectingSelector = state.editor?.target.selector ?? state.selection?.target.selector ?? null;
|
|
4673
|
-
|
|
3939
|
+
useEffect3(() => {
|
|
4674
3940
|
if (!enabled) return;
|
|
4675
3941
|
syncRef.current?.sendSelecting(selectingSelector);
|
|
4676
3942
|
}, [enabled, selectingSelector]);
|
|
4677
3943
|
const editorOpen = state.editor !== null;
|
|
4678
|
-
|
|
3944
|
+
useEffect3(() => {
|
|
4679
3945
|
if (!enabled) return;
|
|
4680
3946
|
syncRef.current?.sendTyping(null, editorOpen);
|
|
4681
3947
|
}, [enabled, editorOpen]);
|
|
4682
3948
|
return enabled ? wrapped : rawDispatch;
|
|
4683
3949
|
}
|
|
4684
3950
|
|
|
3951
|
+
// src/client/components/Badge.tsx
|
|
3952
|
+
import { useLayoutEffect, useRef as useRef4, useState } from "react";
|
|
3953
|
+
|
|
4685
3954
|
// src/client/dragPosition.ts
|
|
4686
3955
|
var MARGIN = 8;
|
|
4687
3956
|
var SNAP = 14;
|
|
@@ -4723,6 +3992,9 @@ function snapClampPos(x, y, width, height) {
|
|
|
4723
3992
|
if (y > vh - height - 16 - SNAP) y = vh - height - 16;
|
|
4724
3993
|
return clampPos(x, y, width, height);
|
|
4725
3994
|
}
|
|
3995
|
+
|
|
3996
|
+
// src/client/components/Badge.tsx
|
|
3997
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
4726
3998
|
var POS_KEY = "review-kit:badge-pos";
|
|
4727
3999
|
var DRAG_THRESHOLD = 6;
|
|
4728
4000
|
function defaultPos(corner, width, height) {
|
|
@@ -4745,16 +4017,16 @@ function Badge() {
|
|
|
4745
4017
|
const { session, mode, panelOpen } = useStore();
|
|
4746
4018
|
const dispatch = useDispatch();
|
|
4747
4019
|
const config = useConfig();
|
|
4748
|
-
const ref =
|
|
4749
|
-
const clickTimer =
|
|
4750
|
-
const lastClickAt =
|
|
4020
|
+
const ref = useRef4(null);
|
|
4021
|
+
const clickTimer = useRef4(null);
|
|
4022
|
+
const lastClickAt = useRef4(0);
|
|
4751
4023
|
const [pos, setPos] = useState(() => readStoredPos(POS_KEY));
|
|
4752
4024
|
const [dragging, setDragging] = useState(false);
|
|
4753
|
-
const drag =
|
|
4025
|
+
const drag = useRef4(null);
|
|
4754
4026
|
const openCount = session?.items.filter((item) => item.status === "open").length ?? 0;
|
|
4755
4027
|
const applyPos = (next, persist) => {
|
|
4756
4028
|
setPos(next);
|
|
4757
|
-
storePos(POS_KEY, next);
|
|
4029
|
+
if (persist) storePos(POS_KEY, next);
|
|
4758
4030
|
const el = ref.current;
|
|
4759
4031
|
if (el) {
|
|
4760
4032
|
const effective = next ?? defaultPos(config.position ?? "bottom-right", el.offsetWidth, el.offsetHeight);
|
|
@@ -4828,7 +4100,7 @@ function Badge() {
|
|
|
4828
4100
|
if (clickTimer.current !== null) window.clearTimeout(clickTimer.current);
|
|
4829
4101
|
clickTimer.current = null;
|
|
4830
4102
|
lastClickAt.current = 0;
|
|
4831
|
-
applyPos(null);
|
|
4103
|
+
applyPos(null, true);
|
|
4832
4104
|
return;
|
|
4833
4105
|
}
|
|
4834
4106
|
lastClickAt.current = now;
|
|
@@ -4846,7 +4118,7 @@ function Badge() {
|
|
|
4846
4118
|
node.offsetHeight
|
|
4847
4119
|
);
|
|
4848
4120
|
node.style.translate = `${snapped.x}px ${snapped.y}px`;
|
|
4849
|
-
applyPos(snapped);
|
|
4121
|
+
applyPos(snapped, true);
|
|
4850
4122
|
};
|
|
4851
4123
|
window.addEventListener("pointermove", onMove, { passive: false });
|
|
4852
4124
|
window.addEventListener("pointerup", onUp);
|
|
@@ -4865,15 +4137,18 @@ function Badge() {
|
|
|
4865
4137
|
"aria-expanded": panelOpen,
|
|
4866
4138
|
onPointerDown,
|
|
4867
4139
|
children: [
|
|
4868
|
-
/* @__PURE__ */
|
|
4140
|
+
/* @__PURE__ */ jsx2("span", { className: "rk-badge-dot" }),
|
|
4869
4141
|
"Review",
|
|
4870
|
-
openCount > 0 && /* @__PURE__ */
|
|
4142
|
+
openCount > 0 && /* @__PURE__ */ jsx2("span", { className: "rk-badge-count", children: openCount })
|
|
4871
4143
|
]
|
|
4872
4144
|
}
|
|
4873
4145
|
);
|
|
4874
4146
|
}
|
|
4147
|
+
|
|
4148
|
+
// src/client/components/icons.tsx
|
|
4149
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
4875
4150
|
function Base({ size = 16, children, ...rest }) {
|
|
4876
|
-
return /* @__PURE__ */
|
|
4151
|
+
return /* @__PURE__ */ jsx3(
|
|
4877
4152
|
"svg",
|
|
4878
4153
|
{
|
|
4879
4154
|
width: size,
|
|
@@ -4892,170 +4167,177 @@ function Base({ size = 16, children, ...rest }) {
|
|
|
4892
4167
|
);
|
|
4893
4168
|
}
|
|
4894
4169
|
function IconText(props) {
|
|
4895
|
-
return /* @__PURE__ */
|
|
4896
|
-
/* @__PURE__ */
|
|
4897
|
-
/* @__PURE__ */
|
|
4898
|
-
/* @__PURE__ */
|
|
4170
|
+
return /* @__PURE__ */ jsxs2(Base, { ...props, children: [
|
|
4171
|
+
/* @__PURE__ */ jsx3("path", { d: "M3.5 4.5V3h9v1.5" }),
|
|
4172
|
+
/* @__PURE__ */ jsx3("path", { d: "M8 3v10" }),
|
|
4173
|
+
/* @__PURE__ */ jsx3("path", { d: "M6 13h4" })
|
|
4899
4174
|
] });
|
|
4900
4175
|
}
|
|
4901
4176
|
function IconImage(props) {
|
|
4902
|
-
return /* @__PURE__ */
|
|
4903
|
-
/* @__PURE__ */
|
|
4904
|
-
/* @__PURE__ */
|
|
4905
|
-
/* @__PURE__ */
|
|
4177
|
+
return /* @__PURE__ */ jsxs2(Base, { ...props, children: [
|
|
4178
|
+
/* @__PURE__ */ jsx3("rect", { x: "2.25", y: "3.25", width: "11.5", height: "9.5", rx: "1.5" }),
|
|
4179
|
+
/* @__PURE__ */ jsx3("circle", { cx: "5.75", cy: "6.5", r: "1", fill: "currentColor", stroke: "none" }),
|
|
4180
|
+
/* @__PURE__ */ jsx3("path", { d: "M2.5 11l3.2-3.2a1 1 0 0 1 1.4 0L10 10.7l1.4-1.4a1 1 0 0 1 1.4 0l.95.95" })
|
|
4906
4181
|
] });
|
|
4907
4182
|
}
|
|
4908
4183
|
function IconComment(props) {
|
|
4909
|
-
return /* @__PURE__ */
|
|
4184
|
+
return /* @__PURE__ */ jsx3(Base, { ...props, children: /* @__PURE__ */ jsx3("path", { d: "M13.5 7.6c0 2.7-2.46 4.6-5.5 4.6-.6 0-1.18-.07-1.72-.2L3.5 13.5l.55-2.2C3.06 10.45 2.5 9.1 2.5 7.6 2.5 4.9 4.96 3 8 3s5.5 1.9 5.5 4.6Z" }) });
|
|
4910
4185
|
}
|
|
4911
4186
|
function IconTrash(props) {
|
|
4912
|
-
return /* @__PURE__ */
|
|
4913
|
-
/* @__PURE__ */
|
|
4914
|
-
/* @__PURE__ */
|
|
4915
|
-
/* @__PURE__ */
|
|
4916
|
-
/* @__PURE__ */
|
|
4187
|
+
return /* @__PURE__ */ jsxs2(Base, { ...props, children: [
|
|
4188
|
+
/* @__PURE__ */ jsx3("path", { d: "M2.75 4.25h10.5" }),
|
|
4189
|
+
/* @__PURE__ */ jsx3("path", { d: "M5.5 4.25V3.4c0-.63.51-1.15 1.15-1.15h2.7c.64 0 1.15.52 1.15 1.15v.85" }),
|
|
4190
|
+
/* @__PURE__ */ jsx3("path", { d: "M4.25 4.5l.55 8.05c.04.62.56 1.1 1.18 1.1h4.04c.62 0 1.14-.48 1.18-1.1l.55-8.05" }),
|
|
4191
|
+
/* @__PURE__ */ jsx3("path", { d: "M6.6 7v3.8M9.4 7v3.8" })
|
|
4917
4192
|
] });
|
|
4918
4193
|
}
|
|
4919
4194
|
function IconMove(props) {
|
|
4920
|
-
return /* @__PURE__ */
|
|
4921
|
-
/* @__PURE__ */
|
|
4922
|
-
/* @__PURE__ */
|
|
4923
|
-
/* @__PURE__ */
|
|
4195
|
+
return /* @__PURE__ */ jsxs2(Base, { ...props, children: [
|
|
4196
|
+
/* @__PURE__ */ jsx3("path", { d: "M8 2.5v11" }),
|
|
4197
|
+
/* @__PURE__ */ jsx3("path", { d: "M5.25 5.25 8 2.5l2.75 2.75" }),
|
|
4198
|
+
/* @__PURE__ */ jsx3("path", { d: "M5.25 10.75 8 13.5l2.75-2.75" })
|
|
4924
4199
|
] });
|
|
4925
4200
|
}
|
|
4926
4201
|
function IconStyle(props) {
|
|
4927
|
-
return /* @__PURE__ */
|
|
4928
|
-
/* @__PURE__ */
|
|
4929
|
-
/* @__PURE__ */
|
|
4202
|
+
return /* @__PURE__ */ jsxs2(Base, { ...props, children: [
|
|
4203
|
+
/* @__PURE__ */ jsx3("path", { d: "M11.2 2.6a1.6 1.6 0 0 1 2.26 2.26L7.1 11.2l-3.1.85.84-3.1 6.36-6.35Z" }),
|
|
4204
|
+
/* @__PURE__ */ jsx3("path", { d: "M9.6 4.2l2.2 2.2" })
|
|
4930
4205
|
] });
|
|
4931
4206
|
}
|
|
4932
4207
|
function IconClose(props) {
|
|
4933
|
-
return /* @__PURE__ */
|
|
4208
|
+
return /* @__PURE__ */ jsx3(Base, { ...props, children: /* @__PURE__ */ jsx3("path", { d: "M4 4l8 8M12 4l-8 8" }) });
|
|
4934
4209
|
}
|
|
4935
4210
|
function IconSearch(props) {
|
|
4936
|
-
return /* @__PURE__ */
|
|
4937
|
-
/* @__PURE__ */
|
|
4938
|
-
/* @__PURE__ */
|
|
4211
|
+
return /* @__PURE__ */ jsxs2(Base, { ...props, children: [
|
|
4212
|
+
/* @__PURE__ */ jsx3("circle", { cx: "7", cy: "7", r: "4.25" }),
|
|
4213
|
+
/* @__PURE__ */ jsx3("path", { d: "M10.3 10.3 13.5 13.5" })
|
|
4939
4214
|
] });
|
|
4940
4215
|
}
|
|
4941
4216
|
function IconDownload(props) {
|
|
4942
|
-
return /* @__PURE__ */
|
|
4943
|
-
/* @__PURE__ */
|
|
4944
|
-
/* @__PURE__ */
|
|
4945
|
-
/* @__PURE__ */
|
|
4217
|
+
return /* @__PURE__ */ jsxs2(Base, { ...props, children: [
|
|
4218
|
+
/* @__PURE__ */ jsx3("path", { d: "M8 2.5v7.5" }),
|
|
4219
|
+
/* @__PURE__ */ jsx3("path", { d: "M5.25 7.5 8 10.25 10.75 7.5" }),
|
|
4220
|
+
/* @__PURE__ */ jsx3("path", { d: "M3 11.5v1a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-1" })
|
|
4946
4221
|
] });
|
|
4947
4222
|
}
|
|
4948
4223
|
function IconUpload(props) {
|
|
4949
|
-
return /* @__PURE__ */
|
|
4950
|
-
/* @__PURE__ */
|
|
4951
|
-
/* @__PURE__ */
|
|
4952
|
-
/* @__PURE__ */
|
|
4224
|
+
return /* @__PURE__ */ jsxs2(Base, { ...props, children: [
|
|
4225
|
+
/* @__PURE__ */ jsx3("path", { d: "M8 10V2.75" }),
|
|
4226
|
+
/* @__PURE__ */ jsx3("path", { d: "M5.25 5.25 8 2.5l2.75 2.75" }),
|
|
4227
|
+
/* @__PURE__ */ jsx3("path", { d: "M3 11.5v1a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-1" })
|
|
4953
4228
|
] });
|
|
4954
4229
|
}
|
|
4955
4230
|
function IconCopyClipboard(props) {
|
|
4956
|
-
return /* @__PURE__ */
|
|
4957
|
-
/* @__PURE__ */
|
|
4958
|
-
/* @__PURE__ */
|
|
4231
|
+
return /* @__PURE__ */ jsxs2(Base, { ...props, children: [
|
|
4232
|
+
/* @__PURE__ */ jsx3("rect", { x: "5.5", y: "5.5", width: "8", height: "8", rx: "1.5" }),
|
|
4233
|
+
/* @__PURE__ */ jsx3("path", { d: "M10.5 5.5v-2a1 1 0 0 0-1-1h-6a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2" })
|
|
4959
4234
|
] });
|
|
4960
4235
|
}
|
|
4961
4236
|
function IconUndo(props) {
|
|
4962
|
-
return /* @__PURE__ */
|
|
4963
|
-
/* @__PURE__ */
|
|
4964
|
-
/* @__PURE__ */
|
|
4237
|
+
return /* @__PURE__ */ jsxs2(Base, { ...props, children: [
|
|
4238
|
+
/* @__PURE__ */ jsx3("path", { d: "M3 6.5h6.5a3.5 3.5 0 0 1 0 7H6" }),
|
|
4239
|
+
/* @__PURE__ */ jsx3("path", { d: "M5.5 4 3 6.5 5.5 9" })
|
|
4965
4240
|
] });
|
|
4966
4241
|
}
|
|
4967
4242
|
function IconCheck(props) {
|
|
4968
|
-
return /* @__PURE__ */
|
|
4243
|
+
return /* @__PURE__ */ jsx3(Base, { ...props, children: /* @__PURE__ */ jsx3("path", { d: "M3 8.5 6.5 12 13 4.5" }) });
|
|
4969
4244
|
}
|
|
4970
4245
|
function IconWarning(props) {
|
|
4971
|
-
return /* @__PURE__ */
|
|
4972
|
-
/* @__PURE__ */
|
|
4973
|
-
/* @__PURE__ */
|
|
4974
|
-
/* @__PURE__ */
|
|
4246
|
+
return /* @__PURE__ */ jsxs2(Base, { ...props, children: [
|
|
4247
|
+
/* @__PURE__ */ jsx3("path", { d: "M8 2.75 14.5 13.5h-13L8 2.75Z" }),
|
|
4248
|
+
/* @__PURE__ */ jsx3("path", { d: "M8 7v3" }),
|
|
4249
|
+
/* @__PURE__ */ jsx3("circle", { cx: "8", cy: "11.9", r: "0.55", fill: "currentColor", stroke: "none" })
|
|
4975
4250
|
] });
|
|
4976
4251
|
}
|
|
4977
4252
|
function IconTarget(props) {
|
|
4978
|
-
return /* @__PURE__ */
|
|
4979
|
-
/* @__PURE__ */
|
|
4980
|
-
/* @__PURE__ */
|
|
4981
|
-
/* @__PURE__ */
|
|
4253
|
+
return /* @__PURE__ */ jsxs2(Base, { ...props, children: [
|
|
4254
|
+
/* @__PURE__ */ jsx3("circle", { cx: "8", cy: "8", r: "5.5" }),
|
|
4255
|
+
/* @__PURE__ */ jsx3("circle", { cx: "8", cy: "8", r: "1", fill: "currentColor", stroke: "none" }),
|
|
4256
|
+
/* @__PURE__ */ jsx3("path", { d: "M8 1.5v2M8 12.5v2M1.5 8h2M12.5 8h2" })
|
|
4982
4257
|
] });
|
|
4983
4258
|
}
|
|
4984
4259
|
function IconKeyboard(props) {
|
|
4985
|
-
return /* @__PURE__ */
|
|
4986
|
-
/* @__PURE__ */
|
|
4987
|
-
/* @__PURE__ */
|
|
4260
|
+
return /* @__PURE__ */ jsxs2(Base, { ...props, children: [
|
|
4261
|
+
/* @__PURE__ */ jsx3("rect", { x: "2", y: "4.5", width: "12", height: "7.5", rx: "1.5" }),
|
|
4262
|
+
/* @__PURE__ */ jsx3("path", { d: "M4.5 7h.01M7 7h.01M9.5 7h.01M12 7h.01M5 9.5h6" })
|
|
4988
4263
|
] });
|
|
4989
4264
|
}
|
|
4990
4265
|
function IconGear(props) {
|
|
4991
|
-
return /* @__PURE__ */
|
|
4992
|
-
/* @__PURE__ */
|
|
4993
|
-
/* @__PURE__ */
|
|
4266
|
+
return /* @__PURE__ */ jsxs2(Base, { ...props, children: [
|
|
4267
|
+
/* @__PURE__ */ jsx3("circle", { cx: "8", cy: "8", r: "2.1" }),
|
|
4268
|
+
/* @__PURE__ */ jsx3("path", { d: "M8 1.8v2M8 12.2v2M1.8 8h2M12.2 8h2M3.6 3.6l1.4 1.4M11 11l1.4 1.4M12.4 3.6 11 5M5 11l-1.4 1.4" })
|
|
4994
4269
|
] });
|
|
4995
4270
|
}
|
|
4996
4271
|
function IconFilter(props) {
|
|
4997
|
-
return /* @__PURE__ */
|
|
4272
|
+
return /* @__PURE__ */ jsx3(Base, { ...props, children: /* @__PURE__ */ jsx3("path", { d: "M2.5 4h11M4.5 8h7M6.5 12h3" }) });
|
|
4998
4273
|
}
|
|
4999
4274
|
function IconLink(props) {
|
|
5000
|
-
return /* @__PURE__ */
|
|
5001
|
-
/* @__PURE__ */
|
|
5002
|
-
/* @__PURE__ */
|
|
5003
|
-
/* @__PURE__ */
|
|
4275
|
+
return /* @__PURE__ */ jsxs2(Base, { ...props, children: [
|
|
4276
|
+
/* @__PURE__ */ jsx3("path", { d: "M6.5 9.5 9.5 6.5" }),
|
|
4277
|
+
/* @__PURE__ */ jsx3("path", { d: "M7.25 4.9 8.4 3.75a2.4 2.4 0 0 1 3.4 0 2.4 2.4 0 0 1 0 3.4L10.65 8.3" }),
|
|
4278
|
+
/* @__PURE__ */ jsx3("path", { d: "M8.75 11.1 7.6 12.25a2.4 2.4 0 0 1-3.4 0 2.4 2.4 0 0 1 0-3.4L5.35 7.7" })
|
|
5004
4279
|
] });
|
|
5005
4280
|
}
|
|
5006
4281
|
function IconUnlink(props) {
|
|
5007
|
-
return /* @__PURE__ */
|
|
5008
|
-
/* @__PURE__ */
|
|
5009
|
-
/* @__PURE__ */
|
|
4282
|
+
return /* @__PURE__ */ jsxs2(Base, { ...props, children: [
|
|
4283
|
+
/* @__PURE__ */ jsx3("path", { d: "M6.5 4.5v-2M9.5 13.5v-2M4.5 6.5h-2M13.5 9.5h-2" }),
|
|
4284
|
+
/* @__PURE__ */ jsx3("path", { d: "M6 10 3.5 12.5M10 6l2.5-2.5" })
|
|
5010
4285
|
] });
|
|
5011
4286
|
}
|
|
5012
4287
|
function iconForType(type, size = 14) {
|
|
5013
4288
|
switch (type) {
|
|
5014
4289
|
case "copy":
|
|
5015
|
-
return /* @__PURE__ */
|
|
4290
|
+
return /* @__PURE__ */ jsx3(IconText, { size });
|
|
5016
4291
|
case "image":
|
|
5017
|
-
return /* @__PURE__ */
|
|
4292
|
+
return /* @__PURE__ */ jsx3(IconImage, { size });
|
|
5018
4293
|
case "comment":
|
|
5019
|
-
return /* @__PURE__ */
|
|
4294
|
+
return /* @__PURE__ */ jsx3(IconComment, { size });
|
|
5020
4295
|
case "delete":
|
|
5021
|
-
return /* @__PURE__ */
|
|
4296
|
+
return /* @__PURE__ */ jsx3(IconTrash, { size });
|
|
5022
4297
|
case "move":
|
|
5023
|
-
return /* @__PURE__ */
|
|
4298
|
+
return /* @__PURE__ */ jsx3(IconMove, { size });
|
|
5024
4299
|
case "style":
|
|
5025
|
-
return /* @__PURE__ */
|
|
4300
|
+
return /* @__PURE__ */ jsx3(IconStyle, { size });
|
|
5026
4301
|
default:
|
|
5027
|
-
return /* @__PURE__ */
|
|
4302
|
+
return /* @__PURE__ */ jsx3(IconTarget, { size });
|
|
5028
4303
|
}
|
|
5029
4304
|
}
|
|
4305
|
+
|
|
4306
|
+
// src/client/components/CheatSheet.tsx
|
|
4307
|
+
import { Fragment, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
5030
4308
|
var GROUPS = ["Tools", "View", "Items", "Session"];
|
|
5031
4309
|
function CheatSheet() {
|
|
5032
4310
|
const { cheatsheetOpen } = useStore();
|
|
5033
4311
|
const dispatch = useDispatch();
|
|
5034
4312
|
if (!cheatsheetOpen) return null;
|
|
5035
4313
|
const close = () => dispatch({ type: "SET_CHEATSHEET", open: false });
|
|
5036
|
-
return /* @__PURE__ */
|
|
5037
|
-
/* @__PURE__ */
|
|
5038
|
-
/* @__PURE__ */
|
|
5039
|
-
/* @__PURE__ */
|
|
5040
|
-
/* @__PURE__ */
|
|
5041
|
-
/* @__PURE__ */
|
|
5042
|
-
/* @__PURE__ */
|
|
5043
|
-
/* @__PURE__ */
|
|
4314
|
+
return /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
4315
|
+
/* @__PURE__ */ jsx4("div", { className: "rk-backdrop", onClick: close }),
|
|
4316
|
+
/* @__PURE__ */ jsxs3("div", { className: "rk-modal rk-cheatsheet", role: "dialog", "aria-modal": "true", "aria-label": "Keyboard shortcuts", children: [
|
|
4317
|
+
/* @__PURE__ */ jsxs3("div", { className: "rk-cheat-head", children: [
|
|
4318
|
+
/* @__PURE__ */ jsx4("span", { className: "rk-cheat-head-icon", children: /* @__PURE__ */ jsx4(IconKeyboard, { size: 15 }) }),
|
|
4319
|
+
/* @__PURE__ */ jsx4("span", { className: "rk-cheat-title", children: "Keyboard shortcuts" }),
|
|
4320
|
+
/* @__PURE__ */ jsx4("span", { style: { flex: 1 } }),
|
|
4321
|
+
/* @__PURE__ */ jsx4("button", { type: "button", className: "rk-icon-btn", "aria-label": "Close", onClick: close, autoFocus: true, children: /* @__PURE__ */ jsx4(IconClose, { size: 13 }) })
|
|
5044
4322
|
] }),
|
|
5045
|
-
/* @__PURE__ */
|
|
5046
|
-
/* @__PURE__ */
|
|
5047
|
-
SHORTCUTS.filter((def) => def.group === group).map((def) => /* @__PURE__ */
|
|
5048
|
-
/* @__PURE__ */
|
|
5049
|
-
/* @__PURE__ */
|
|
5050
|
-
/* @__PURE__ */
|
|
4323
|
+
/* @__PURE__ */ jsx4("div", { className: "rk-cheat-grid", children: GROUPS.map((group) => /* @__PURE__ */ jsxs3("section", { className: "rk-cheat-group", children: [
|
|
4324
|
+
/* @__PURE__ */ jsx4("h3", { className: "rk-cheat-group-title", children: group }),
|
|
4325
|
+
SHORTCUTS.filter((def) => def.group === group).map((def) => /* @__PURE__ */ jsxs3("div", { className: "rk-shortcut-row", children: [
|
|
4326
|
+
/* @__PURE__ */ jsxs3("span", { className: "rk-shortcut-text", children: [
|
|
4327
|
+
/* @__PURE__ */ jsx4("span", { className: "rk-shortcut-title", children: def.title }),
|
|
4328
|
+
/* @__PURE__ */ jsx4("span", { className: "rk-shortcut-desc", children: def.description })
|
|
5051
4329
|
] }),
|
|
5052
|
-
/* @__PURE__ */
|
|
4330
|
+
/* @__PURE__ */ jsx4("span", { className: "rk-keys", children: displayKeys(def, IS_MAC).map((key) => /* @__PURE__ */ jsx4("span", { className: "rk-kbd", children: key }, key)) })
|
|
5053
4331
|
] }, def.id))
|
|
5054
4332
|
] }, group)) }),
|
|
5055
|
-
/* @__PURE__ */
|
|
4333
|
+
/* @__PURE__ */ jsx4("div", { className: "rk-egg", children: "Psst \u2014 the \u201C/\u201D box knows a few tricks it won\u2019t tell you about." })
|
|
5056
4334
|
] })
|
|
5057
4335
|
] });
|
|
5058
4336
|
}
|
|
4337
|
+
|
|
4338
|
+
// src/client/components/EmblemaConnect.tsx
|
|
4339
|
+
import { useEffect as useEffect4, useState as useState2 } from "react";
|
|
4340
|
+
import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
5059
4341
|
function shortKey(key) {
|
|
5060
4342
|
return `${key.slice(0, 4)}\u2026${key.slice(-4)}`;
|
|
5061
4343
|
}
|
|
@@ -5070,14 +4352,14 @@ function ago(iso) {
|
|
|
5070
4352
|
function EmblemaConnect() {
|
|
5071
4353
|
const { emblemaConnectOpen } = useStore();
|
|
5072
4354
|
const dispatch = useDispatch();
|
|
5073
|
-
const [state, setState] =
|
|
5074
|
-
const [key, setKey] =
|
|
5075
|
-
const [busy, setBusy] =
|
|
4355
|
+
const [state, setState] = useState2("loading");
|
|
4356
|
+
const [key, setKey] = useState2(null);
|
|
4357
|
+
const [busy, setBusy] = useState2(false);
|
|
5076
4358
|
const refresh = () => {
|
|
5077
4359
|
setState("loading");
|
|
5078
4360
|
void fetchSyncState().then(setState);
|
|
5079
4361
|
};
|
|
5080
|
-
|
|
4362
|
+
useEffect4(() => {
|
|
5081
4363
|
if (emblemaConnectOpen) {
|
|
5082
4364
|
setKey(null);
|
|
5083
4365
|
refresh();
|
|
@@ -5106,48 +4388,48 @@ function EmblemaConnect() {
|
|
|
5106
4388
|
refresh();
|
|
5107
4389
|
}).finally(() => setBusy(false));
|
|
5108
4390
|
};
|
|
5109
|
-
return /* @__PURE__ */
|
|
5110
|
-
/* @__PURE__ */
|
|
5111
|
-
/* @__PURE__ */
|
|
5112
|
-
/* @__PURE__ */
|
|
4391
|
+
return /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
4392
|
+
/* @__PURE__ */ jsx5("div", { className: "rk-backdrop", onClick: close }),
|
|
4393
|
+
/* @__PURE__ */ jsx5("div", { className: "rk-modal", role: "dialog", "aria-modal": "true", "aria-label": "Connect to Emblema", children: /* @__PURE__ */ jsxs4("div", { className: "rk-modal-body", children: [
|
|
4394
|
+
/* @__PURE__ */ jsxs4("div", { className: "rk-modal-title", style: { display: "flex", alignItems: "center", gap: 8 }, children: [
|
|
5113
4395
|
"Connect to Emblema",
|
|
5114
|
-
/* @__PURE__ */
|
|
5115
|
-
/* @__PURE__ */
|
|
4396
|
+
/* @__PURE__ */ jsx5("span", { style: { flex: 1 } }),
|
|
4397
|
+
/* @__PURE__ */ jsx5("button", { type: "button", className: "rk-icon-btn", "aria-label": "Close", onClick: close, autoFocus: true, children: /* @__PURE__ */ jsx5(IconClose, { size: 13 }) })
|
|
5116
4398
|
] }),
|
|
5117
|
-
state === "loading" && /* @__PURE__ */
|
|
5118
|
-
state === null && /* @__PURE__ */
|
|
4399
|
+
state === "loading" && /* @__PURE__ */ jsx5("div", { className: "rk-modal-text", children: "Looking for the local sync agent\u2026" }),
|
|
4400
|
+
state === null && /* @__PURE__ */ jsxs4("div", { className: "rk-modal-text", children: [
|
|
5119
4401
|
"The local sync agent isn't running. In the project repo run:",
|
|
5120
|
-
/* @__PURE__ */
|
|
5121
|
-
"npx reviewkit-emblema init --origin ",
|
|
4402
|
+
/* @__PURE__ */ jsxs4("code", { className: "rk-connect-cmd", children: [
|
|
4403
|
+
"npx -p @satanwagen/reviewkit-cli reviewkit-emblema init --origin ",
|
|
5122
4404
|
window.location.origin
|
|
5123
4405
|
] }),
|
|
5124
|
-
/* @__PURE__ */
|
|
4406
|
+
/* @__PURE__ */ jsx5("code", { className: "rk-connect-cmd", children: "npx -p @satanwagen/reviewkit-cli reviewkit-emblema serve" }),
|
|
5125
4407
|
"then reopen this dialog."
|
|
5126
4408
|
] }),
|
|
5127
|
-
state !== null && state !== "loading" && /* @__PURE__ */
|
|
5128
|
-
/* @__PURE__ */
|
|
4409
|
+
state !== null && state !== "loading" && /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
4410
|
+
/* @__PURE__ */ jsxs4("div", { className: "rk-modal-text", children: [
|
|
5129
4411
|
"Project ",
|
|
5130
|
-
/* @__PURE__ */
|
|
4412
|
+
/* @__PURE__ */ jsx5("strong", { children: state.name }),
|
|
5131
4413
|
" ",
|
|
5132
|
-
/* @__PURE__ */
|
|
4414
|
+
/* @__PURE__ */ jsxs4("span", { className: "rk-connect-id", children: [
|
|
5133
4415
|
"(",
|
|
5134
4416
|
state.id,
|
|
5135
4417
|
")"
|
|
5136
4418
|
] }),
|
|
5137
|
-
/* @__PURE__ */
|
|
4419
|
+
/* @__PURE__ */ jsx5("br", {}),
|
|
5138
4420
|
"Status:",
|
|
5139
4421
|
" ",
|
|
5140
|
-
state.revoked ? /* @__PURE__ */
|
|
5141
|
-
/* @__PURE__ */
|
|
4422
|
+
state.revoked ? /* @__PURE__ */ jsx5("span", { className: "rk-connect-bad", children: "revoked \u2014 generate a new key to reconnect" }) : /* @__PURE__ */ jsx5(Fragment2, { children: "paired key active" }),
|
|
4423
|
+
/* @__PURE__ */ jsx5("br", {}),
|
|
5142
4424
|
"Last confirmed by Emblema: ",
|
|
5143
|
-
/* @__PURE__ */
|
|
4425
|
+
/* @__PURE__ */ jsx5("strong", { children: ago(state.lastAck) }),
|
|
5144
4426
|
" \xB7 ",
|
|
5145
4427
|
state.findings,
|
|
5146
4428
|
" finding",
|
|
5147
4429
|
state.findings === 1 ? "" : "s",
|
|
5148
4430
|
" tracked"
|
|
5149
4431
|
] }),
|
|
5150
|
-
key && /* @__PURE__ */
|
|
4432
|
+
key && /* @__PURE__ */ jsx5(
|
|
5151
4433
|
"code",
|
|
5152
4434
|
{
|
|
5153
4435
|
className: "rk-connect-key",
|
|
@@ -5155,8 +4437,8 @@ function EmblemaConnect() {
|
|
|
5155
4437
|
children: shortKey(key)
|
|
5156
4438
|
}
|
|
5157
4439
|
),
|
|
5158
|
-
/* @__PURE__ */
|
|
5159
|
-
/* @__PURE__ */
|
|
4440
|
+
/* @__PURE__ */ jsxs4("div", { className: "rk-connect-actions", children: [
|
|
4441
|
+
/* @__PURE__ */ jsx5(
|
|
5160
4442
|
"button",
|
|
5161
4443
|
{
|
|
5162
4444
|
type: "button",
|
|
@@ -5167,7 +4449,7 @@ function EmblemaConnect() {
|
|
|
5167
4449
|
children: state.revoked ? "Generate new key" : "New key (rotate)"
|
|
5168
4450
|
}
|
|
5169
4451
|
),
|
|
5170
|
-
/* @__PURE__ */
|
|
4452
|
+
/* @__PURE__ */ jsx5(
|
|
5171
4453
|
"button",
|
|
5172
4454
|
{
|
|
5173
4455
|
type: "button",
|
|
@@ -5184,8 +4466,8 @@ function EmblemaConnect() {
|
|
|
5184
4466
|
children: "Copy key"
|
|
5185
4467
|
}
|
|
5186
4468
|
),
|
|
5187
|
-
/* @__PURE__ */
|
|
5188
|
-
/* @__PURE__ */
|
|
4469
|
+
/* @__PURE__ */ jsx5("span", { style: { flex: 1 } }),
|
|
4470
|
+
/* @__PURE__ */ jsx5(
|
|
5189
4471
|
"button",
|
|
5190
4472
|
{
|
|
5191
4473
|
type: "button",
|
|
@@ -5207,12 +4489,230 @@ function EmblemaConnect() {
|
|
|
5207
4489
|
] }) })
|
|
5208
4490
|
] });
|
|
5209
4491
|
}
|
|
4492
|
+
|
|
4493
|
+
// src/client/components/TerminalConnect.tsx
|
|
4494
|
+
import { useEffect as useEffect5, useState as useState3 } from "react";
|
|
4495
|
+
|
|
4496
|
+
// src/integrations/terminal.ts
|
|
4497
|
+
var TERMINAL_PAIR_PORTS = [48780, 48781, 48782, 48783];
|
|
4498
|
+
async function fetchJson(url, init, timeoutMs) {
|
|
4499
|
+
const abort = new AbortController();
|
|
4500
|
+
const timer = window.setTimeout(() => abort.abort(), timeoutMs);
|
|
4501
|
+
try {
|
|
4502
|
+
return await fetch(url, { ...init, signal: abort.signal });
|
|
4503
|
+
} finally {
|
|
4504
|
+
window.clearTimeout(timer);
|
|
4505
|
+
}
|
|
4506
|
+
}
|
|
4507
|
+
async function probeTerminal() {
|
|
4508
|
+
for (const port of TERMINAL_PAIR_PORTS) {
|
|
4509
|
+
try {
|
|
4510
|
+
const res = await fetchJson(`http://127.0.0.1:${port}/pair`, { method: "GET" }, 900);
|
|
4511
|
+
if (!res.ok) continue;
|
|
4512
|
+
const body = await res.json();
|
|
4513
|
+
if (typeof body === "object" && body !== null && body.app === "reviewkit-cli") {
|
|
4514
|
+
const b = body;
|
|
4515
|
+
return {
|
|
4516
|
+
port,
|
|
4517
|
+
cwd: typeof b.cwd === "string" ? b.cwd : void 0,
|
|
4518
|
+
projects: Array.isArray(b.projects) ? b.projects.filter((p) => typeof p === "string") : []
|
|
4519
|
+
};
|
|
4520
|
+
}
|
|
4521
|
+
} catch {
|
|
4522
|
+
}
|
|
4523
|
+
}
|
|
4524
|
+
return null;
|
|
4525
|
+
}
|
|
4526
|
+
async function pairTerminal(port, key) {
|
|
4527
|
+
try {
|
|
4528
|
+
const res = await fetchJson(
|
|
4529
|
+
`http://127.0.0.1:${port}/pair`,
|
|
4530
|
+
{ method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ key }) },
|
|
4531
|
+
5e3
|
|
4532
|
+
);
|
|
4533
|
+
const body = await res.json().catch(() => null);
|
|
4534
|
+
if (res.ok && body?.ok) return { ok: true, name: body.name ?? "", repo: body.repo ?? null };
|
|
4535
|
+
return { ok: false, error: body?.error ?? `HTTP ${res.status}` };
|
|
4536
|
+
} catch {
|
|
4537
|
+
return { ok: false, error: "the terminal stopped answering" };
|
|
4538
|
+
}
|
|
4539
|
+
}
|
|
4540
|
+
|
|
4541
|
+
// src/client/terminalKey.ts
|
|
4542
|
+
var TERMINAL_KEY_PREFIX = "rkc_";
|
|
4543
|
+
var TERMINAL_KEY_VERSION = 1;
|
|
4544
|
+
function base64url(text) {
|
|
4545
|
+
const bytes = new TextEncoder().encode(text);
|
|
4546
|
+
let binary = "";
|
|
4547
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
4548
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
4549
|
+
}
|
|
4550
|
+
function encodeTerminalKey(fields) {
|
|
4551
|
+
const payload = { v: TERMINAL_KEY_VERSION, ...fields };
|
|
4552
|
+
return TERMINAL_KEY_PREFIX + base64url(JSON.stringify(payload));
|
|
4553
|
+
}
|
|
4554
|
+
function currentTerminalKey(syncUrl, syncToken) {
|
|
4555
|
+
const origin = window.location.origin;
|
|
4556
|
+
let route = "/";
|
|
4557
|
+
try {
|
|
4558
|
+
route = window.location.pathname || "/";
|
|
4559
|
+
} catch {
|
|
4560
|
+
}
|
|
4561
|
+
return encodeTerminalKey({ name: window.location.hostname, origin, syncUrl, syncToken, route });
|
|
4562
|
+
}
|
|
4563
|
+
|
|
4564
|
+
// src/client/components/TerminalConnect.tsx
|
|
4565
|
+
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
4566
|
+
function shortKey2(key) {
|
|
4567
|
+
return `${key.slice(0, 8)}\u2026${key.slice(-6)}`;
|
|
4568
|
+
}
|
|
4569
|
+
function shortPath(path) {
|
|
4570
|
+
if (!path) return "";
|
|
4571
|
+
const parts = path.split("/").filter(Boolean);
|
|
4572
|
+
return parts.length > 2 ? `\u2026/${parts.slice(-2).join("/")}` : path;
|
|
4573
|
+
}
|
|
4574
|
+
function TerminalConnect() {
|
|
4575
|
+
const { terminalConnectOpen } = useStore();
|
|
4576
|
+
const config = useConfig();
|
|
4577
|
+
const dispatch = useDispatch();
|
|
4578
|
+
const [phase, setPhase] = useState3("probing");
|
|
4579
|
+
const [probe, setProbe] = useState3(null);
|
|
4580
|
+
const [paired, setPaired] = useState3(null);
|
|
4581
|
+
const [showManual, setShowManual] = useState3(false);
|
|
4582
|
+
const syncToken = resolveSyncToken(config);
|
|
4583
|
+
const key = terminalConnectOpen && syncToken ? currentTerminalKey(resolveSyncUrl(config), syncToken) : null;
|
|
4584
|
+
useEffect5(() => {
|
|
4585
|
+
if (!terminalConnectOpen) return;
|
|
4586
|
+
let cancelled = false;
|
|
4587
|
+
setPhase("probing");
|
|
4588
|
+
setProbe(null);
|
|
4589
|
+
setPaired(null);
|
|
4590
|
+
setShowManual(false);
|
|
4591
|
+
const look = () => void probeTerminal().then((found) => {
|
|
4592
|
+
if (cancelled) return;
|
|
4593
|
+
setProbe(found);
|
|
4594
|
+
setPhase((current) => current === "pairing" || current === "paired" ? current : found ? "found" : "missing");
|
|
4595
|
+
});
|
|
4596
|
+
look();
|
|
4597
|
+
const timer = window.setInterval(look, 2e3);
|
|
4598
|
+
return () => {
|
|
4599
|
+
cancelled = true;
|
|
4600
|
+
window.clearInterval(timer);
|
|
4601
|
+
};
|
|
4602
|
+
}, [terminalConnectOpen]);
|
|
4603
|
+
if (!terminalConnectOpen) return null;
|
|
4604
|
+
const close = () => dispatch({ type: "SET_TERMINAL_CONNECT", open: false });
|
|
4605
|
+
const copy = async (value, what) => {
|
|
4606
|
+
try {
|
|
4607
|
+
await navigator.clipboard.writeText(value);
|
|
4608
|
+
toast(dispatch, `${what} copied`, "success");
|
|
4609
|
+
} catch {
|
|
4610
|
+
toast(dispatch, "Copy failed \u2014 select the text manually", "error");
|
|
4611
|
+
}
|
|
4612
|
+
};
|
|
4613
|
+
const connect = () => {
|
|
4614
|
+
if (!probe || !key) return;
|
|
4615
|
+
setPhase("pairing");
|
|
4616
|
+
void pairTerminal(probe.port, key).then((result) => {
|
|
4617
|
+
if (result.ok) {
|
|
4618
|
+
setPaired({ name: result.name, repo: result.repo });
|
|
4619
|
+
setPhase("paired");
|
|
4620
|
+
toast(dispatch, `Terminal paired as \u201C${result.name}\u201D`, "success");
|
|
4621
|
+
} else {
|
|
4622
|
+
setPhase("found");
|
|
4623
|
+
toast(dispatch, `Pairing failed: ${result.error}`, "error");
|
|
4624
|
+
}
|
|
4625
|
+
});
|
|
4626
|
+
};
|
|
4627
|
+
const connectCmd = key ? `npx -y @satanwagen/reviewkit-cli connect ${key}` : "";
|
|
4628
|
+
return /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
4629
|
+
/* @__PURE__ */ jsx6("div", { className: "rk-backdrop", onClick: close }),
|
|
4630
|
+
/* @__PURE__ */ jsx6("div", { className: "rk-modal", role: "dialog", "aria-modal": "true", "aria-label": "Connect terminal or agent", children: /* @__PURE__ */ jsxs5("div", { className: "rk-modal-body", children: [
|
|
4631
|
+
/* @__PURE__ */ jsxs5("div", { className: "rk-modal-title", style: { display: "flex", alignItems: "center", gap: 8 }, children: [
|
|
4632
|
+
"Connect terminal / agent",
|
|
4633
|
+
/* @__PURE__ */ jsx6("span", { style: { flex: 1 } }),
|
|
4634
|
+
/* @__PURE__ */ jsx6("button", { type: "button", className: "rk-icon-btn", "aria-label": "Close", onClick: close, autoFocus: true, children: /* @__PURE__ */ jsx6(IconClose, { size: 13 }) })
|
|
4635
|
+
] }),
|
|
4636
|
+
!key && /* @__PURE__ */ jsxs5("div", { className: "rk-modal-text", children: [
|
|
4637
|
+
"Live sync is off on this page (",
|
|
4638
|
+
/* @__PURE__ */ jsx6("code", { children: "sync=false" }),
|
|
4639
|
+
" or no token), so there is no shared room a terminal could read."
|
|
4640
|
+
] }),
|
|
4641
|
+
key && phase === "paired" && paired && /* @__PURE__ */ jsxs5("div", { className: "rk-modal-text", children: [
|
|
4642
|
+
/* @__PURE__ */ jsx6("span", { className: "rk-emblema-dot", "data-state": "live" }),
|
|
4643
|
+
" Paired as ",
|
|
4644
|
+
/* @__PURE__ */ jsx6("strong", { children: paired.name }),
|
|
4645
|
+
paired.repo ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
4646
|
+
" in ",
|
|
4647
|
+
/* @__PURE__ */ jsx6("code", { children: shortPath(paired.repo) })
|
|
4648
|
+
] }) : null,
|
|
4649
|
+
". The terminal shows this page's comments live, and Claude Code / Cursor can read and resolve them through the ",
|
|
4650
|
+
/* @__PURE__ */ jsx6("code", { children: "reviewkit" }),
|
|
4651
|
+
" MCP tools."
|
|
4652
|
+
] }),
|
|
4653
|
+
key && phase !== "paired" && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
4654
|
+
/* @__PURE__ */ jsxs5("div", { className: "rk-modal-text", children: [
|
|
4655
|
+
phase === "probing" && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
4656
|
+
"Looking for a ",
|
|
4657
|
+
/* @__PURE__ */ jsx6("code", { children: "reviewkit" }),
|
|
4658
|
+
" terminal on this machine\u2026"
|
|
4659
|
+
] }),
|
|
4660
|
+
phase === "missing" && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
4661
|
+
"No terminal is listening yet. In the site's repo run",
|
|
4662
|
+
/* @__PURE__ */ jsx6("code", { className: "rk-connect-cmd", children: "npx -y @satanwagen/reviewkit-cli setup" }),
|
|
4663
|
+
"and this dialog will pick it up by itself."
|
|
4664
|
+
] }),
|
|
4665
|
+
(phase === "found" || phase === "pairing") && probe && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
4666
|
+
/* @__PURE__ */ jsx6("span", { className: "rk-emblema-dot", "data-state": "live" }),
|
|
4667
|
+
" Terminal found",
|
|
4668
|
+
probe.cwd ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
4669
|
+
" in ",
|
|
4670
|
+
/* @__PURE__ */ jsx6("code", { children: shortPath(probe.cwd) })
|
|
4671
|
+
] }) : null,
|
|
4672
|
+
".",
|
|
4673
|
+
probe.projects.length > 0 ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
4674
|
+
" Already paired: ",
|
|
4675
|
+
probe.projects.join(", "),
|
|
4676
|
+
"."
|
|
4677
|
+
] }) : null
|
|
4678
|
+
] })
|
|
4679
|
+
] }),
|
|
4680
|
+
/* @__PURE__ */ jsxs5("div", { className: "rk-connect-actions", children: [
|
|
4681
|
+
/* @__PURE__ */ jsx6(
|
|
4682
|
+
"button",
|
|
4683
|
+
{
|
|
4684
|
+
type: "button",
|
|
4685
|
+
className: "rk-btn rk-btn-primary",
|
|
4686
|
+
disabled: phase !== "found",
|
|
4687
|
+
onClick: connect,
|
|
4688
|
+
title: "Send this site's connection to the terminal \u2014 nothing to copy",
|
|
4689
|
+
children: phase === "pairing" ? "Connecting\u2026" : "Connect this terminal"
|
|
4690
|
+
}
|
|
4691
|
+
),
|
|
4692
|
+
/* @__PURE__ */ jsx6("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => setShowManual((v) => !v), children: showManual ? "Hide manual option" : "Another machine\u2026" })
|
|
4693
|
+
] }),
|
|
4694
|
+
showManual && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
4695
|
+
/* @__PURE__ */ jsx6("div", { className: "rk-modal-text", style: { marginTop: 10 }, children: "On a machine without a listening terminal, run this once (the key carries the sync server and its token \u2014 treat it like a review link):" }),
|
|
4696
|
+
/* @__PURE__ */ jsxs5("code", { className: "rk-connect-cmd", title: connectCmd, children: [
|
|
4697
|
+
"npx -y @satanwagen/reviewkit-cli connect ",
|
|
4698
|
+
shortKey2(key)
|
|
4699
|
+
] }),
|
|
4700
|
+
/* @__PURE__ */ jsx6("div", { className: "rk-connect-actions", children: /* @__PURE__ */ jsx6("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => void copy(connectCmd, "Command"), children: "Copy command" }) })
|
|
4701
|
+
] })
|
|
4702
|
+
] })
|
|
4703
|
+
] }) })
|
|
4704
|
+
] });
|
|
4705
|
+
}
|
|
4706
|
+
|
|
4707
|
+
// src/client/components/CoachMark.tsx
|
|
4708
|
+
import { useState as useState4 } from "react";
|
|
4709
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
5210
4710
|
var COACH_KEY = "review-kit:coach-dismissed";
|
|
5211
4711
|
function CoachMark() {
|
|
5212
4712
|
const { coachOpen, session } = useStore();
|
|
5213
4713
|
const dispatch = useDispatch();
|
|
5214
4714
|
const config = useConfig();
|
|
5215
|
-
const [name, setName] =
|
|
4715
|
+
const [name, setName] = useState4(session?.author ?? config.defaultAuthor ?? "");
|
|
5216
4716
|
if (!coachOpen) return null;
|
|
5217
4717
|
const done = (startPicking) => {
|
|
5218
4718
|
if (name.trim() !== "") dispatch({ type: "SET_AUTHOR", author: name.trim() });
|
|
@@ -5223,39 +4723,39 @@ function CoachMark() {
|
|
|
5223
4723
|
}
|
|
5224
4724
|
if (startPicking) dispatch({ type: "SET_MODE", mode: "pick" });
|
|
5225
4725
|
};
|
|
5226
|
-
return /* @__PURE__ */
|
|
5227
|
-
/* @__PURE__ */
|
|
5228
|
-
/* @__PURE__ */
|
|
5229
|
-
/* @__PURE__ */
|
|
5230
|
-
/* @__PURE__ */
|
|
4726
|
+
return /* @__PURE__ */ jsxs6("div", { className: "rk-coach", role: "dialog", "aria-label": "Welcome to review mode", children: [
|
|
4727
|
+
/* @__PURE__ */ jsx7("div", { className: "rk-coach-accent" }),
|
|
4728
|
+
/* @__PURE__ */ jsxs6("div", { className: "rk-coach-body", children: [
|
|
4729
|
+
/* @__PURE__ */ jsxs6("div", { className: "rk-modal-title", style: { display: "flex", alignItems: "center", gap: 8 }, children: [
|
|
4730
|
+
/* @__PURE__ */ jsx7(IconTarget, { size: 16 }),
|
|
5231
4731
|
" Review mode"
|
|
5232
4732
|
] }),
|
|
5233
|
-
/* @__PURE__ */
|
|
5234
|
-
/* @__PURE__ */
|
|
5235
|
-
/* @__PURE__ */
|
|
5236
|
-
/* @__PURE__ */
|
|
4733
|
+
/* @__PURE__ */ jsx7("div", { className: "rk-modal-text", children: "Click anything on the page to suggest a change \u2014 rewrite the copy, swap an image, or leave a note. The live site stays untouched; everything you add is collected for the team." }),
|
|
4734
|
+
/* @__PURE__ */ jsxs6("div", { className: "rk-coach-keys", "aria-label": "Key shortcuts", children: [
|
|
4735
|
+
/* @__PURE__ */ jsxs6("span", { children: [
|
|
4736
|
+
/* @__PURE__ */ jsx7("span", { className: "rk-kbd", children: "T" }),
|
|
5237
4737
|
" rewrite"
|
|
5238
4738
|
] }),
|
|
5239
|
-
/* @__PURE__ */
|
|
5240
|
-
/* @__PURE__ */
|
|
4739
|
+
/* @__PURE__ */ jsxs6("span", { children: [
|
|
4740
|
+
/* @__PURE__ */ jsx7("span", { className: "rk-kbd", children: "C" }),
|
|
5241
4741
|
" comment"
|
|
5242
4742
|
] }),
|
|
5243
|
-
/* @__PURE__ */
|
|
5244
|
-
/* @__PURE__ */
|
|
4743
|
+
/* @__PURE__ */ jsxs6("span", { children: [
|
|
4744
|
+
/* @__PURE__ */ jsx7("span", { className: "rk-kbd", children: "I" }),
|
|
5245
4745
|
" image"
|
|
5246
4746
|
] }),
|
|
5247
|
-
/* @__PURE__ */
|
|
5248
|
-
/* @__PURE__ */
|
|
4747
|
+
/* @__PURE__ */ jsxs6("span", { children: [
|
|
4748
|
+
/* @__PURE__ */ jsx7("span", { className: "rk-kbd", children: "V" }),
|
|
5249
4749
|
" select"
|
|
5250
4750
|
] }),
|
|
5251
|
-
/* @__PURE__ */
|
|
5252
|
-
/* @__PURE__ */
|
|
4751
|
+
/* @__PURE__ */ jsxs6("span", { children: [
|
|
4752
|
+
/* @__PURE__ */ jsx7("span", { className: "rk-kbd", children: "?" }),
|
|
5253
4753
|
" all shortcuts"
|
|
5254
4754
|
] })
|
|
5255
4755
|
] }),
|
|
5256
|
-
/* @__PURE__ */
|
|
5257
|
-
/* @__PURE__ */
|
|
5258
|
-
/* @__PURE__ */
|
|
4756
|
+
/* @__PURE__ */ jsxs6("div", { children: [
|
|
4757
|
+
/* @__PURE__ */ jsx7("label", { className: "rk-label", htmlFor: "rk-author", children: "Your name" }),
|
|
4758
|
+
/* @__PURE__ */ jsx7(
|
|
5259
4759
|
"input",
|
|
5260
4760
|
{
|
|
5261
4761
|
id: "rk-author",
|
|
@@ -5269,32 +4769,36 @@ function CoachMark() {
|
|
|
5269
4769
|
}
|
|
5270
4770
|
)
|
|
5271
4771
|
] }),
|
|
5272
|
-
/* @__PURE__ */
|
|
5273
|
-
/* @__PURE__ */
|
|
5274
|
-
/* @__PURE__ */
|
|
4772
|
+
/* @__PURE__ */ jsxs6("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 4 }, children: [
|
|
4773
|
+
/* @__PURE__ */ jsx7("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => done(false), children: "Not now" }),
|
|
4774
|
+
/* @__PURE__ */ jsx7("button", { type: "button", className: "rk-btn rk-btn-primary", onClick: () => done(true), children: "Start reviewing" })
|
|
5275
4775
|
] })
|
|
5276
4776
|
] })
|
|
5277
4777
|
] });
|
|
5278
4778
|
}
|
|
4779
|
+
|
|
4780
|
+
// src/client/components/Confirm.tsx
|
|
4781
|
+
import { useEffect as useEffect6, useRef as useRef5 } from "react";
|
|
4782
|
+
import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
5279
4783
|
function ConfirmHost() {
|
|
5280
4784
|
const { confirm } = useStore();
|
|
5281
4785
|
const dispatch = useDispatch();
|
|
5282
|
-
const cancelRef =
|
|
5283
|
-
|
|
4786
|
+
const cancelRef = useRef5(null);
|
|
4787
|
+
useEffect6(() => {
|
|
5284
4788
|
if (confirm) cancelRef.current?.focus();
|
|
5285
4789
|
}, [confirm]);
|
|
5286
4790
|
if (!confirm) return null;
|
|
5287
4791
|
const close = () => dispatch({ type: "SET_CONFIRM", confirm: null });
|
|
5288
|
-
return /* @__PURE__ */
|
|
5289
|
-
/* @__PURE__ */
|
|
5290
|
-
/* @__PURE__ */
|
|
5291
|
-
/* @__PURE__ */
|
|
5292
|
-
/* @__PURE__ */
|
|
5293
|
-
/* @__PURE__ */
|
|
4792
|
+
return /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
4793
|
+
/* @__PURE__ */ jsx8("div", { className: "rk-backdrop", onClick: close }),
|
|
4794
|
+
/* @__PURE__ */ jsxs7("div", { className: "rk-modal", role: "alertdialog", "aria-modal": "true", "aria-label": confirm.title, children: [
|
|
4795
|
+
/* @__PURE__ */ jsxs7("div", { className: "rk-modal-body", children: [
|
|
4796
|
+
/* @__PURE__ */ jsx8("div", { className: "rk-modal-title", children: confirm.title }),
|
|
4797
|
+
/* @__PURE__ */ jsx8("div", { className: "rk-modal-text", children: confirm.message })
|
|
5294
4798
|
] }),
|
|
5295
|
-
/* @__PURE__ */
|
|
5296
|
-
/* @__PURE__ */
|
|
5297
|
-
/* @__PURE__ */
|
|
4799
|
+
/* @__PURE__ */ jsxs7("div", { className: "rk-modal-actions", children: [
|
|
4800
|
+
/* @__PURE__ */ jsx8("button", { ref: cancelRef, type: "button", className: "rk-btn rk-btn-ghost", onClick: close, children: "Cancel" }),
|
|
4801
|
+
/* @__PURE__ */ jsx8(
|
|
5298
4802
|
"button",
|
|
5299
4803
|
{
|
|
5300
4804
|
type: "button",
|
|
@@ -5312,6 +4816,12 @@ function ConfirmHost() {
|
|
|
5312
4816
|
] });
|
|
5313
4817
|
}
|
|
5314
4818
|
|
|
4819
|
+
// src/client/components/ImageEditor.tsx
|
|
4820
|
+
import { useEffect as useEffect7, useRef as useRef7, useState as useState6 } from "react";
|
|
4821
|
+
|
|
4822
|
+
// src/client/useAnchored.ts
|
|
4823
|
+
import { useLayoutEffect as useLayoutEffect2, useRef as useRef6, useState as useState5 } from "react";
|
|
4824
|
+
|
|
5315
4825
|
// src/client/position.ts
|
|
5316
4826
|
function place(anchor, size, side, offset) {
|
|
5317
4827
|
switch (side) {
|
|
@@ -5355,9 +4865,9 @@ function computePosition(anchor, size, options = {}) {
|
|
|
5355
4865
|
|
|
5356
4866
|
// src/client/useAnchored.ts
|
|
5357
4867
|
function useAnchored(anchorEl, side = "bottom", offset = 8) {
|
|
5358
|
-
const ref =
|
|
5359
|
-
const [pos, setPos] =
|
|
5360
|
-
|
|
4868
|
+
const ref = useRef6(null);
|
|
4869
|
+
const [pos, setPos] = useState5(null);
|
|
4870
|
+
useLayoutEffect2(() => {
|
|
5361
4871
|
if (!anchorEl) {
|
|
5362
4872
|
setPos(null);
|
|
5363
4873
|
return;
|
|
@@ -5386,6 +4896,9 @@ function anchoredStyle(pos) {
|
|
|
5386
4896
|
if (!pos) return { visibility: "hidden", transform: "translate3d(-9999px, -9999px, 0)" };
|
|
5387
4897
|
return { transform: `translate3d(${pos.x}px, ${pos.y}px, 0)`, top: 0, left: 0 };
|
|
5388
4898
|
}
|
|
4899
|
+
|
|
4900
|
+
// src/client/components/ImageEditor.tsx
|
|
4901
|
+
import { Fragment as Fragment5, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
5389
4902
|
var MAX_BYTES = 2 * 1024 * 1024;
|
|
5390
4903
|
var FETCH_TIMEOUT_MS = 12e3;
|
|
5391
4904
|
var PROBE_TIMEOUT_MS = 8e3;
|
|
@@ -5443,15 +4956,15 @@ function urlFromDataTransfer(dt) {
|
|
|
5443
4956
|
function ImageEditor({ editor }) {
|
|
5444
4957
|
const dispatch = useDispatch();
|
|
5445
4958
|
const { route, session } = useStore();
|
|
5446
|
-
const [replacement, setReplacement] =
|
|
5447
|
-
const [urlValue, setUrlValue] =
|
|
5448
|
-
const [
|
|
5449
|
-
const [description, setDescription] =
|
|
5450
|
-
const [priority, setPriority] =
|
|
5451
|
-
const [over, setOver] =
|
|
5452
|
-
const fileInput =
|
|
5453
|
-
const abortRef =
|
|
5454
|
-
const debounceRef =
|
|
4959
|
+
const [replacement, setReplacement] = useState6(null);
|
|
4960
|
+
const [urlValue, setUrlValue] = useState6("");
|
|
4961
|
+
const [loading2, setLoading] = useState6(false);
|
|
4962
|
+
const [description, setDescription] = useState6("");
|
|
4963
|
+
const [priority, setPriority] = useState6("nice");
|
|
4964
|
+
const [over, setOver] = useState6(false);
|
|
4965
|
+
const fileInput = useRef7(null);
|
|
4966
|
+
const abortRef = useRef7(null);
|
|
4967
|
+
const debounceRef = useRef7(null);
|
|
5455
4968
|
const { ref, pos } = useAnchored(editor.element, "bottom", 12);
|
|
5456
4969
|
const image = findImage(editor.element);
|
|
5457
4970
|
const beforeSrc = image?.currentSrc || image?.src || "";
|
|
@@ -5515,7 +5028,7 @@ function ImageEditor({ editor }) {
|
|
|
5515
5028
|
}
|
|
5516
5029
|
}
|
|
5517
5030
|
};
|
|
5518
|
-
|
|
5031
|
+
useEffect7(() => {
|
|
5519
5032
|
if (debounceRef.current !== null) window.clearTimeout(debounceRef.current);
|
|
5520
5033
|
if (urlValue.trim() === "" || replacement !== null) return;
|
|
5521
5034
|
debounceRef.current = window.setTimeout(() => {
|
|
@@ -5525,8 +5038,8 @@ function ImageEditor({ editor }) {
|
|
|
5525
5038
|
if (debounceRef.current !== null) window.clearTimeout(debounceRef.current);
|
|
5526
5039
|
};
|
|
5527
5040
|
}, [urlValue, replacement]);
|
|
5528
|
-
|
|
5529
|
-
|
|
5041
|
+
useEffect7(() => () => abortRef.current?.abort(), []);
|
|
5042
|
+
useEffect7(() => {
|
|
5530
5043
|
const onPaste = (event) => {
|
|
5531
5044
|
const data = event.clipboardData;
|
|
5532
5045
|
if (!data) return;
|
|
@@ -5604,23 +5117,23 @@ function ImageEditor({ editor }) {
|
|
|
5604
5117
|
toast(dispatch, "Image proposal saved", "success");
|
|
5605
5118
|
};
|
|
5606
5119
|
const previewSrc = replacement?.kind === "data" ? replacement.dataUrl : replacement?.url;
|
|
5607
|
-
return /* @__PURE__ */
|
|
5608
|
-
/* @__PURE__ */
|
|
5609
|
-
/* @__PURE__ */
|
|
5120
|
+
return /* @__PURE__ */ jsxs8("div", { ref, className: "rk-card", style: anchoredStyle(pos), role: "dialog", "aria-label": "Replace image", children: [
|
|
5121
|
+
/* @__PURE__ */ jsxs8("div", { className: "rk-card-head", children: [
|
|
5122
|
+
/* @__PURE__ */ jsx9(IconImage, { size: 14 }),
|
|
5610
5123
|
"Replace image"
|
|
5611
5124
|
] }),
|
|
5612
|
-
/* @__PURE__ */
|
|
5613
|
-
replacement && previewSrc ? /* @__PURE__ */
|
|
5614
|
-
/* @__PURE__ */
|
|
5615
|
-
/* @__PURE__ */
|
|
5616
|
-
/* @__PURE__ */
|
|
5125
|
+
/* @__PURE__ */ jsxs8("div", { className: "rk-card-body", children: [
|
|
5126
|
+
replacement && previewSrc ? /* @__PURE__ */ jsx9("div", { className: "rk-thumbs", children: /* @__PURE__ */ jsxs8("div", { className: "rk-thumb-pair", title: "Hover to compare with the current image", children: [
|
|
5127
|
+
/* @__PURE__ */ jsxs8("figure", { className: "rk-thumb", children: [
|
|
5128
|
+
/* @__PURE__ */ jsx9("img", { src: beforeSrc, alt: "Current" }),
|
|
5129
|
+
/* @__PURE__ */ jsx9("figcaption", { children: "Before" })
|
|
5617
5130
|
] }),
|
|
5618
|
-
/* @__PURE__ */
|
|
5619
|
-
/* @__PURE__ */
|
|
5620
|
-
/* @__PURE__ */
|
|
5131
|
+
/* @__PURE__ */ jsxs8("figure", { className: "rk-thumb", children: [
|
|
5132
|
+
/* @__PURE__ */ jsx9("img", { src: previewSrc, alt: "Proposed replacement" }),
|
|
5133
|
+
/* @__PURE__ */ jsx9("figcaption", { children: replacement.kind === "url" ? "After \xB7 linked" : "After" })
|
|
5621
5134
|
] })
|
|
5622
|
-
] }) }) : /* @__PURE__ */
|
|
5623
|
-
/* @__PURE__ */
|
|
5135
|
+
] }) }) : /* @__PURE__ */ jsxs8(Fragment5, { children: [
|
|
5136
|
+
/* @__PURE__ */ jsxs8(
|
|
5624
5137
|
"button",
|
|
5625
5138
|
{
|
|
5626
5139
|
type: "button",
|
|
@@ -5633,18 +5146,18 @@ function ImageEditor({ editor }) {
|
|
|
5633
5146
|
onDragLeave: () => setOver(false),
|
|
5634
5147
|
onDrop,
|
|
5635
5148
|
children: [
|
|
5636
|
-
/* @__PURE__ */
|
|
5637
|
-
/* @__PURE__ */
|
|
5149
|
+
/* @__PURE__ */ jsx9(IconUpload, { size: 18 }),
|
|
5150
|
+
/* @__PURE__ */ jsxs8("span", { children: [
|
|
5638
5151
|
"Drop an image \u2014 from your disk or another tab \u2014",
|
|
5639
|
-
/* @__PURE__ */
|
|
5152
|
+
/* @__PURE__ */ jsx9("br", {}),
|
|
5640
5153
|
"or click to browse (max 2 MB)"
|
|
5641
5154
|
] })
|
|
5642
5155
|
]
|
|
5643
5156
|
}
|
|
5644
5157
|
),
|
|
5645
|
-
/* @__PURE__ */
|
|
5646
|
-
|
|
5647
|
-
/* @__PURE__ */
|
|
5158
|
+
/* @__PURE__ */ jsxs8("div", { className: "rk-url", children: [
|
|
5159
|
+
loading2 ? /* @__PURE__ */ jsx9("span", { className: "rk-spinner", "aria-label": "Loading image" }) : /* @__PURE__ */ jsx9(IconLink, { size: 13 }),
|
|
5160
|
+
/* @__PURE__ */ jsx9(
|
|
5648
5161
|
"input",
|
|
5649
5162
|
{
|
|
5650
5163
|
className: "rk-input",
|
|
@@ -5659,9 +5172,9 @@ function ImageEditor({ editor }) {
|
|
|
5659
5172
|
)
|
|
5660
5173
|
] })
|
|
5661
5174
|
] }),
|
|
5662
|
-
replacement && /* @__PURE__ */
|
|
5663
|
-
/* @__PURE__ */
|
|
5664
|
-
/* @__PURE__ */
|
|
5175
|
+
replacement && /* @__PURE__ */ jsx9("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: clearReplacement, children: "Remove replacement" }),
|
|
5176
|
+
/* @__PURE__ */ jsx9("input", { ref: fileInput, type: "file", accept: "image/*", hidden: true, onChange: onPick }),
|
|
5177
|
+
/* @__PURE__ */ jsx9(
|
|
5665
5178
|
"textarea",
|
|
5666
5179
|
{
|
|
5667
5180
|
className: "rk-textarea",
|
|
@@ -5671,39 +5184,43 @@ function ImageEditor({ editor }) {
|
|
|
5671
5184
|
rows: 2
|
|
5672
5185
|
}
|
|
5673
5186
|
),
|
|
5674
|
-
/* @__PURE__ */
|
|
5675
|
-
/* @__PURE__ */
|
|
5676
|
-
/* @__PURE__ */
|
|
5187
|
+
/* @__PURE__ */ jsxs8("div", { className: "rk-seg", role: "group", "aria-label": "Priority", children: [
|
|
5188
|
+
/* @__PURE__ */ jsx9("button", { type: "button", "aria-pressed": priority === "must", onClick: () => setPriority("must"), children: "Must" }),
|
|
5189
|
+
/* @__PURE__ */ jsx9("button", { type: "button", "aria-pressed": priority === "nice", onClick: () => setPriority("nice"), children: "Nice to have" })
|
|
5677
5190
|
] })
|
|
5678
5191
|
] }),
|
|
5679
|
-
/* @__PURE__ */
|
|
5680
|
-
/* @__PURE__ */
|
|
5681
|
-
/* @__PURE__ */
|
|
5192
|
+
/* @__PURE__ */ jsxs8("div", { className: "rk-card-foot", children: [
|
|
5193
|
+
/* @__PURE__ */ jsxs8("span", { className: "rk-hint", children: [
|
|
5194
|
+
/* @__PURE__ */ jsx9("span", { className: "rk-kbd", children: "esc" }),
|
|
5682
5195
|
" cancel"
|
|
5683
5196
|
] }),
|
|
5684
|
-
/* @__PURE__ */
|
|
5685
|
-
/* @__PURE__ */
|
|
5686
|
-
/* @__PURE__ */
|
|
5197
|
+
/* @__PURE__ */ jsxs8("div", { className: "rk-actions", children: [
|
|
5198
|
+
/* @__PURE__ */ jsx9("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => dispatch({ type: "CLOSE_EDITOR" }), children: "Cancel" }),
|
|
5199
|
+
/* @__PURE__ */ jsx9("button", { type: "button", className: "rk-btn rk-btn-primary", onClick: save, children: "Save" })
|
|
5687
5200
|
] })
|
|
5688
5201
|
] })
|
|
5689
5202
|
] });
|
|
5690
5203
|
}
|
|
5204
|
+
|
|
5205
|
+
// src/client/components/InlineEditor.tsx
|
|
5206
|
+
import { useEffect as useEffect8, useRef as useRef8, useState as useState7 } from "react";
|
|
5207
|
+
import { Fragment as Fragment6, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
5691
5208
|
function InlineEditor({ editor }) {
|
|
5692
5209
|
const dispatch = useDispatch();
|
|
5693
5210
|
const { route, session } = useStore();
|
|
5694
|
-
const [after, setAfter] =
|
|
5695
|
-
const [priority, setPriority] =
|
|
5696
|
-
const [note, setNote] =
|
|
5697
|
-
const original =
|
|
5698
|
-
const baseline =
|
|
5699
|
-
const [sizeDelta, setSizeDelta] =
|
|
5700
|
-
const [widthDelta, setWidthDelta] =
|
|
5701
|
-
const [clipped, setClipped] =
|
|
5702
|
-
const ringRef =
|
|
5703
|
-
const afterRef =
|
|
5211
|
+
const [after, setAfter] = useState7(() => editor.element.innerText);
|
|
5212
|
+
const [priority, setPriority] = useState7("nice");
|
|
5213
|
+
const [note, setNote] = useState7("");
|
|
5214
|
+
const original = useRef8(null);
|
|
5215
|
+
const baseline = useRef8(null);
|
|
5216
|
+
const [sizeDelta, setSizeDelta] = useState7(0);
|
|
5217
|
+
const [widthDelta, setWidthDelta] = useState7(0);
|
|
5218
|
+
const [clipped, setClipped] = useState7(false);
|
|
5219
|
+
const ringRef = useRef8(null);
|
|
5220
|
+
const afterRef = useRef8(null);
|
|
5704
5221
|
const { ref, pos } = useAnchored(editor.element, "bottom", 12);
|
|
5705
5222
|
const element = editor.element;
|
|
5706
|
-
|
|
5223
|
+
useEffect8(() => {
|
|
5707
5224
|
const el = element;
|
|
5708
5225
|
original.current = { html: el.innerHTML, text: el.innerText, styleAttr: el.getAttribute("style") };
|
|
5709
5226
|
const rect = el.getBoundingClientRect();
|
|
@@ -5733,8 +5250,8 @@ function InlineEditor({ editor }) {
|
|
|
5733
5250
|
}
|
|
5734
5251
|
};
|
|
5735
5252
|
}, [element]);
|
|
5736
|
-
const focusedOnce =
|
|
5737
|
-
|
|
5253
|
+
const focusedOnce = useRef8(false);
|
|
5254
|
+
useEffect8(() => {
|
|
5738
5255
|
const field = afterRef.current;
|
|
5739
5256
|
if (pos === null || focusedOnce.current || !field) return;
|
|
5740
5257
|
focusedOnce.current = true;
|
|
@@ -5742,7 +5259,7 @@ function InlineEditor({ editor }) {
|
|
|
5742
5259
|
const end = field.value.length;
|
|
5743
5260
|
field.setSelectionRange(end, end);
|
|
5744
5261
|
}, [pos]);
|
|
5745
|
-
|
|
5262
|
+
useEffect8(() => {
|
|
5746
5263
|
const field = afterRef.current;
|
|
5747
5264
|
if (!field) return;
|
|
5748
5265
|
field.style.height = "auto";
|
|
@@ -5752,7 +5269,7 @@ function InlineEditor({ editor }) {
|
|
|
5752
5269
|
setAfter(value);
|
|
5753
5270
|
if (element.innerText !== value) setElementText(element, value);
|
|
5754
5271
|
};
|
|
5755
|
-
|
|
5272
|
+
useEffect8(() => {
|
|
5756
5273
|
let raf = 0;
|
|
5757
5274
|
let lastDelta = 0;
|
|
5758
5275
|
let lastWidth = 0;
|
|
@@ -5822,7 +5339,7 @@ function InlineEditor({ editor }) {
|
|
|
5822
5339
|
cancel();
|
|
5823
5340
|
}
|
|
5824
5341
|
};
|
|
5825
|
-
|
|
5342
|
+
useEffect8(() => {
|
|
5826
5343
|
const el = element;
|
|
5827
5344
|
const onKeyDown = (event) => {
|
|
5828
5345
|
if (event.key === "Enter" && !event.shiftKey) {
|
|
@@ -5840,19 +5357,19 @@ function InlineEditor({ editor }) {
|
|
|
5840
5357
|
});
|
|
5841
5358
|
const before = original.current?.text ?? "";
|
|
5842
5359
|
const delta = after.length - before.length;
|
|
5843
|
-
return /* @__PURE__ */
|
|
5844
|
-
/* @__PURE__ */
|
|
5845
|
-
/* @__PURE__ */
|
|
5846
|
-
/* @__PURE__ */
|
|
5847
|
-
/* @__PURE__ */
|
|
5360
|
+
return /* @__PURE__ */ jsxs9(Fragment6, { children: [
|
|
5361
|
+
/* @__PURE__ */ jsx10("div", { ref: ringRef, className: "rk-edit-ring" }),
|
|
5362
|
+
/* @__PURE__ */ jsxs9("div", { ref, className: "rk-card", style: anchoredStyle(pos), role: "dialog", "aria-label": "Rewrite text", children: [
|
|
5363
|
+
/* @__PURE__ */ jsxs9("div", { className: "rk-card-head", children: [
|
|
5364
|
+
/* @__PURE__ */ jsx10(IconText, { size: 14 }),
|
|
5848
5365
|
"Rewrite text",
|
|
5849
|
-
/* @__PURE__ */
|
|
5850
|
-
/* @__PURE__ */
|
|
5366
|
+
/* @__PURE__ */ jsx10("span", { className: "rk-spacer" }),
|
|
5367
|
+
/* @__PURE__ */ jsxs9("span", { className: "rk-delta", "aria-live": "polite", children: [
|
|
5851
5368
|
before.length,
|
|
5852
5369
|
" \u2192 ",
|
|
5853
5370
|
after.length,
|
|
5854
5371
|
" ",
|
|
5855
|
-
delta !== 0 && /* @__PURE__ */
|
|
5372
|
+
delta !== 0 && /* @__PURE__ */ jsxs9("span", { className: delta > 0 ? "rk-plus" : "rk-minus", children: [
|
|
5856
5373
|
"(",
|
|
5857
5374
|
delta > 0 ? "+" : "",
|
|
5858
5375
|
delta,
|
|
@@ -5860,15 +5377,15 @@ function InlineEditor({ editor }) {
|
|
|
5860
5377
|
] })
|
|
5861
5378
|
] })
|
|
5862
5379
|
] }),
|
|
5863
|
-
/* @__PURE__ */
|
|
5864
|
-
/* @__PURE__ */
|
|
5865
|
-
/* @__PURE__ */
|
|
5866
|
-
/* @__PURE__ */
|
|
5867
|
-
/* @__PURE__ */
|
|
5380
|
+
/* @__PURE__ */ jsxs9("div", { className: "rk-card-body", children: [
|
|
5381
|
+
/* @__PURE__ */ jsxs9("div", { className: "rk-diff", "aria-label": "Before and after", children: [
|
|
5382
|
+
/* @__PURE__ */ jsxs9("div", { className: "rk-diff-row rk-diff-before", children: [
|
|
5383
|
+
/* @__PURE__ */ jsx10("span", { className: "rk-diff-tag", children: "Before" }),
|
|
5384
|
+
/* @__PURE__ */ jsx10("span", { className: "rk-diff-text", children: before })
|
|
5868
5385
|
] }),
|
|
5869
|
-
/* @__PURE__ */
|
|
5870
|
-
/* @__PURE__ */
|
|
5871
|
-
/* @__PURE__ */
|
|
5386
|
+
/* @__PURE__ */ jsxs9("div", { className: "rk-diff-row rk-diff-after", children: [
|
|
5387
|
+
/* @__PURE__ */ jsx10("span", { className: "rk-diff-tag", children: "After" }),
|
|
5388
|
+
/* @__PURE__ */ jsx10(
|
|
5872
5389
|
"textarea",
|
|
5873
5390
|
{
|
|
5874
5391
|
ref: afterRef,
|
|
@@ -5882,11 +5399,11 @@ function InlineEditor({ editor }) {
|
|
|
5882
5399
|
)
|
|
5883
5400
|
] })
|
|
5884
5401
|
] }),
|
|
5885
|
-
(Math.abs(sizeDelta) > 2 || Math.abs(widthDelta) > 4 || clipped) && /* @__PURE__ */
|
|
5402
|
+
(Math.abs(sizeDelta) > 2 || Math.abs(widthDelta) > 4 || clipped) && /* @__PURE__ */ jsxs9("div", { className: "rk-size-note", role: "status", children: [
|
|
5886
5403
|
Math.abs(sizeDelta) > 2 && (() => {
|
|
5887
5404
|
const lines = baseline.current ? Math.round(Math.abs(sizeDelta) / baseline.current.lineHeight) : 0;
|
|
5888
5405
|
const lineNote = lines >= 1 ? ` (~${lines} line${lines === 1 ? "" : "s"})` : "";
|
|
5889
|
-
return /* @__PURE__ */
|
|
5406
|
+
return /* @__PURE__ */ jsxs9("span", { children: [
|
|
5890
5407
|
"Block ",
|
|
5891
5408
|
sizeDelta > 0 ? "grew" : "shrank",
|
|
5892
5409
|
" by ",
|
|
@@ -5896,16 +5413,16 @@ function InlineEditor({ editor }) {
|
|
|
5896
5413
|
" \u2014 as it would with this text live."
|
|
5897
5414
|
] });
|
|
5898
5415
|
})(),
|
|
5899
|
-
Math.abs(sizeDelta) <= 2 && Math.abs(widthDelta) > 4 && /* @__PURE__ */
|
|
5416
|
+
Math.abs(sizeDelta) <= 2 && Math.abs(widthDelta) > 4 && /* @__PURE__ */ jsxs9("span", { children: [
|
|
5900
5417
|
"Block got ",
|
|
5901
5418
|
widthDelta > 0 ? "wider" : "narrower",
|
|
5902
5419
|
" by ",
|
|
5903
5420
|
Math.abs(widthDelta),
|
|
5904
5421
|
" px \u2014 as it would with this text live."
|
|
5905
5422
|
] }),
|
|
5906
|
-
clipped && /* @__PURE__ */
|
|
5423
|
+
clipped && /* @__PURE__ */ jsx10("span", { className: "rk-clip-note", children: "Text exceeds the visible crop here and will be cut off." })
|
|
5907
5424
|
] }),
|
|
5908
|
-
/* @__PURE__ */
|
|
5425
|
+
/* @__PURE__ */ jsx10(
|
|
5909
5426
|
"input",
|
|
5910
5427
|
{
|
|
5911
5428
|
className: "rk-input",
|
|
@@ -5914,29 +5431,33 @@ function InlineEditor({ editor }) {
|
|
|
5914
5431
|
onChange: (event) => setNote(event.target.value)
|
|
5915
5432
|
}
|
|
5916
5433
|
),
|
|
5917
|
-
/* @__PURE__ */
|
|
5918
|
-
/* @__PURE__ */
|
|
5919
|
-
/* @__PURE__ */
|
|
5434
|
+
/* @__PURE__ */ jsxs9("div", { className: "rk-seg", role: "group", "aria-label": "Priority", children: [
|
|
5435
|
+
/* @__PURE__ */ jsx10("button", { type: "button", "aria-pressed": priority === "must", onClick: () => setPriority("must"), children: "Must" }),
|
|
5436
|
+
/* @__PURE__ */ jsx10("button", { type: "button", "aria-pressed": priority === "nice", onClick: () => setPriority("nice"), children: "Nice to have" })
|
|
5920
5437
|
] })
|
|
5921
5438
|
] }),
|
|
5922
|
-
/* @__PURE__ */
|
|
5923
|
-
/* @__PURE__ */
|
|
5924
|
-
/* @__PURE__ */
|
|
5439
|
+
/* @__PURE__ */ jsxs9("div", { className: "rk-card-foot", children: [
|
|
5440
|
+
/* @__PURE__ */ jsxs9("span", { className: "rk-hint", children: [
|
|
5441
|
+
/* @__PURE__ */ jsx10("span", { className: "rk-kbd", children: "\u21B5" }),
|
|
5925
5442
|
" save \xB7 ",
|
|
5926
|
-
/* @__PURE__ */
|
|
5443
|
+
/* @__PURE__ */ jsx10("span", { className: "rk-kbd", children: "\u21E7\u21B5" }),
|
|
5927
5444
|
" newline \xB7",
|
|
5928
5445
|
" ",
|
|
5929
|
-
/* @__PURE__ */
|
|
5446
|
+
/* @__PURE__ */ jsx10("span", { className: "rk-kbd", children: "esc" }),
|
|
5930
5447
|
" cancel"
|
|
5931
5448
|
] }),
|
|
5932
|
-
/* @__PURE__ */
|
|
5933
|
-
/* @__PURE__ */
|
|
5934
|
-
/* @__PURE__ */
|
|
5449
|
+
/* @__PURE__ */ jsxs9("div", { className: "rk-actions", children: [
|
|
5450
|
+
/* @__PURE__ */ jsx10("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: cancel, children: "Cancel" }),
|
|
5451
|
+
/* @__PURE__ */ jsx10("button", { type: "button", className: "rk-btn rk-btn-primary", onClick: commit, children: "Save" })
|
|
5935
5452
|
] })
|
|
5936
5453
|
] })
|
|
5937
5454
|
] })
|
|
5938
5455
|
] });
|
|
5939
5456
|
}
|
|
5457
|
+
|
|
5458
|
+
// src/client/components/NoteComposer.tsx
|
|
5459
|
+
import { useEffect as useEffect9, useRef as useRef9, useState as useState8 } from "react";
|
|
5460
|
+
import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
5940
5461
|
var TITLES = {
|
|
5941
5462
|
comment: "Comment",
|
|
5942
5463
|
delete: "Mark for deletion",
|
|
@@ -5952,14 +5473,14 @@ var PLACEHOLDERS = {
|
|
|
5952
5473
|
function NoteComposer({ editor }) {
|
|
5953
5474
|
const dispatch = useDispatch();
|
|
5954
5475
|
const { route, session } = useStore();
|
|
5955
|
-
const [text, setText] =
|
|
5956
|
-
const [direction, setDirection] =
|
|
5957
|
-
const [priority, setPriority] =
|
|
5958
|
-
const textareaRef =
|
|
5476
|
+
const [text, setText] = useState8("");
|
|
5477
|
+
const [direction, setDirection] = useState8(void 0);
|
|
5478
|
+
const [priority, setPriority] = useState8("nice");
|
|
5479
|
+
const textareaRef = useRef9(null);
|
|
5959
5480
|
const { ref, pos } = useAnchored(editor.element, "bottom", 12);
|
|
5960
5481
|
const { kind } = editor;
|
|
5961
|
-
const focusedOnce =
|
|
5962
|
-
|
|
5482
|
+
const focusedOnce = useRef9(false);
|
|
5483
|
+
useEffect9(() => {
|
|
5963
5484
|
const field = textareaRef.current;
|
|
5964
5485
|
if (pos === null || focusedOnce.current || !field) return;
|
|
5965
5486
|
focusedOnce.current = true;
|
|
@@ -6018,13 +5539,13 @@ function NoteComposer({ editor }) {
|
|
|
6018
5539
|
save();
|
|
6019
5540
|
}
|
|
6020
5541
|
};
|
|
6021
|
-
return /* @__PURE__ */
|
|
6022
|
-
/* @__PURE__ */
|
|
5542
|
+
return /* @__PURE__ */ jsxs10("div", { ref, className: "rk-card", style: anchoredStyle(pos), role: "dialog", "aria-label": TITLES[kind], children: [
|
|
5543
|
+
/* @__PURE__ */ jsxs10("div", { className: "rk-card-head", children: [
|
|
6023
5544
|
iconForType(kind),
|
|
6024
5545
|
TITLES[kind]
|
|
6025
5546
|
] }),
|
|
6026
|
-
/* @__PURE__ */
|
|
6027
|
-
kind === "move" && /* @__PURE__ */
|
|
5547
|
+
/* @__PURE__ */ jsxs10("div", { className: "rk-card-body", children: [
|
|
5548
|
+
kind === "move" && /* @__PURE__ */ jsx11("div", { className: "rk-seg", role: "group", "aria-label": "Direction", children: ["up", "down", "first", "last"].map((option) => /* @__PURE__ */ jsx11(
|
|
6028
5549
|
"button",
|
|
6029
5550
|
{
|
|
6030
5551
|
type: "button",
|
|
@@ -6034,7 +5555,7 @@ function NoteComposer({ editor }) {
|
|
|
6034
5555
|
},
|
|
6035
5556
|
option
|
|
6036
5557
|
)) }),
|
|
6037
|
-
/* @__PURE__ */
|
|
5558
|
+
/* @__PURE__ */ jsx11(
|
|
6038
5559
|
"textarea",
|
|
6039
5560
|
{
|
|
6040
5561
|
ref: textareaRef,
|
|
@@ -6046,25 +5567,29 @@ function NoteComposer({ editor }) {
|
|
|
6046
5567
|
rows: 3
|
|
6047
5568
|
}
|
|
6048
5569
|
),
|
|
6049
|
-
/* @__PURE__ */
|
|
6050
|
-
/* @__PURE__ */
|
|
6051
|
-
/* @__PURE__ */
|
|
5570
|
+
/* @__PURE__ */ jsxs10("div", { className: "rk-seg", role: "group", "aria-label": "Priority", children: [
|
|
5571
|
+
/* @__PURE__ */ jsx11("button", { type: "button", "aria-pressed": priority === "must", onClick: () => setPriority("must"), children: "Must" }),
|
|
5572
|
+
/* @__PURE__ */ jsx11("button", { type: "button", "aria-pressed": priority === "nice", onClick: () => setPriority("nice"), children: "Nice to have" })
|
|
6052
5573
|
] })
|
|
6053
5574
|
] }),
|
|
6054
|
-
/* @__PURE__ */
|
|
6055
|
-
/* @__PURE__ */
|
|
6056
|
-
/* @__PURE__ */
|
|
5575
|
+
/* @__PURE__ */ jsxs10("div", { className: "rk-card-foot", children: [
|
|
5576
|
+
/* @__PURE__ */ jsxs10("span", { className: "rk-hint", children: [
|
|
5577
|
+
/* @__PURE__ */ jsx11("span", { className: "rk-kbd", children: "\u2318\u21B5" }),
|
|
6057
5578
|
" save \xB7 ",
|
|
6058
|
-
/* @__PURE__ */
|
|
5579
|
+
/* @__PURE__ */ jsx11("span", { className: "rk-kbd", children: "esc" }),
|
|
6059
5580
|
" cancel"
|
|
6060
5581
|
] }),
|
|
6061
|
-
/* @__PURE__ */
|
|
6062
|
-
/* @__PURE__ */
|
|
6063
|
-
/* @__PURE__ */
|
|
5582
|
+
/* @__PURE__ */ jsxs10("div", { className: "rk-actions", children: [
|
|
5583
|
+
/* @__PURE__ */ jsx11("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => dispatch({ type: "CLOSE_EDITOR" }), children: "Cancel" }),
|
|
5584
|
+
/* @__PURE__ */ jsx11("button", { type: "button", className: "rk-btn rk-btn-primary", onClick: save, children: "Save" })
|
|
6064
5585
|
] })
|
|
6065
5586
|
] })
|
|
6066
5587
|
] });
|
|
6067
5588
|
}
|
|
5589
|
+
|
|
5590
|
+
// src/client/components/Panel.tsx
|
|
5591
|
+
import { useEffect as useEffect10, useMemo as useMemo3, useRef as useRef10, useState as useState9 } from "react";
|
|
5592
|
+
import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
6068
5593
|
function changeSummary(item) {
|
|
6069
5594
|
if (isCopyItem(item)) return `\u201C${item.payload.after}\u201D`;
|
|
6070
5595
|
if (isImageItem(item)) {
|
|
@@ -6146,24 +5671,24 @@ function formatBytes(bytes) {
|
|
|
6146
5671
|
function CopyDiff({ before, after }) {
|
|
6147
5672
|
const parts = diffParts(before, after);
|
|
6148
5673
|
const delta = after.length - before.length;
|
|
6149
|
-
return /* @__PURE__ */
|
|
6150
|
-
/* @__PURE__ */
|
|
6151
|
-
/* @__PURE__ */
|
|
6152
|
-
/* @__PURE__ */
|
|
5674
|
+
return /* @__PURE__ */ jsxs11("div", { className: "rk-diffview", children: [
|
|
5675
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-diff-row rk-diff-before", children: [
|
|
5676
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-diff-tag", children: "Before" }),
|
|
5677
|
+
/* @__PURE__ */ jsxs11("span", { className: "rk-diff-text", children: [
|
|
6153
5678
|
parts.prefix,
|
|
6154
|
-
parts.delMid && /* @__PURE__ */
|
|
5679
|
+
parts.delMid && /* @__PURE__ */ jsx12("mark", { className: "rk-del", children: parts.delMid }),
|
|
6155
5680
|
parts.suffix
|
|
6156
5681
|
] })
|
|
6157
5682
|
] }),
|
|
6158
|
-
/* @__PURE__ */
|
|
6159
|
-
/* @__PURE__ */
|
|
6160
|
-
/* @__PURE__ */
|
|
5683
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-diff-row rk-diff-after", children: [
|
|
5684
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-diff-tag", children: "After" }),
|
|
5685
|
+
/* @__PURE__ */ jsxs11("span", { className: "rk-diff-text", children: [
|
|
6161
5686
|
parts.prefix,
|
|
6162
|
-
parts.insMid && /* @__PURE__ */
|
|
5687
|
+
parts.insMid && /* @__PURE__ */ jsx12("mark", { className: "rk-ins", children: parts.insMid }),
|
|
6163
5688
|
parts.suffix
|
|
6164
5689
|
] })
|
|
6165
5690
|
] }),
|
|
6166
|
-
/* @__PURE__ */
|
|
5691
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-diff-len", children: [
|
|
6167
5692
|
before.length,
|
|
6168
5693
|
" \u2192 ",
|
|
6169
5694
|
after.length,
|
|
@@ -6174,8 +5699,8 @@ function CopyDiff({ before, after }) {
|
|
|
6174
5699
|
}
|
|
6175
5700
|
function ImageDetail({ beforeSrc, afterSrc, afterDataUrl }) {
|
|
6176
5701
|
const replacement = afterDataUrl ?? afterSrc;
|
|
6177
|
-
const [dims, setDims] =
|
|
6178
|
-
|
|
5702
|
+
const [dims, setDims] = useState9("");
|
|
5703
|
+
useEffect10(() => {
|
|
6179
5704
|
if (!replacement) return;
|
|
6180
5705
|
const img = new Image();
|
|
6181
5706
|
img.onload = () => setDims(`${img.naturalWidth}\xD7${img.naturalHeight}px`);
|
|
@@ -6200,55 +5725,67 @@ function ImageDetail({ beforeSrc, afterSrc, afterDataUrl }) {
|
|
|
6200
5725
|
window.open(replacement, "_blank", "noopener");
|
|
6201
5726
|
}
|
|
6202
5727
|
};
|
|
6203
|
-
return /* @__PURE__ */
|
|
6204
|
-
/* @__PURE__ */
|
|
6205
|
-
/* @__PURE__ */
|
|
6206
|
-
beforeSrc ? /* @__PURE__ */
|
|
6207
|
-
/* @__PURE__ */
|
|
5728
|
+
return /* @__PURE__ */ jsxs11("div", { className: "rk-imgdetail", children: [
|
|
5729
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-thumbs", children: [
|
|
5730
|
+
/* @__PURE__ */ jsxs11("figure", { className: "rk-thumb", children: [
|
|
5731
|
+
beforeSrc ? /* @__PURE__ */ jsx12("img", { src: beforeSrc, alt: "Current" }) : /* @__PURE__ */ jsx12("div", { className: "rk-thumb-missing", children: "no image" }),
|
|
5732
|
+
/* @__PURE__ */ jsx12("figcaption", { children: "Before" })
|
|
6208
5733
|
] }),
|
|
6209
|
-
/* @__PURE__ */
|
|
6210
|
-
/* @__PURE__ */
|
|
6211
|
-
/* @__PURE__ */
|
|
5734
|
+
/* @__PURE__ */ jsxs11("figure", { className: "rk-thumb", children: [
|
|
5735
|
+
/* @__PURE__ */ jsx12("img", { src: replacement, alt: "Proposed replacement" }),
|
|
5736
|
+
/* @__PURE__ */ jsxs11("figcaption", { children: [
|
|
6212
5737
|
"After",
|
|
6213
5738
|
embedded ? "" : " \xB7 linked"
|
|
6214
5739
|
] })
|
|
6215
5740
|
] })
|
|
6216
5741
|
] }),
|
|
6217
|
-
/* @__PURE__ */
|
|
5742
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-imgdetail-meta", children: [
|
|
6218
5743
|
embedded ? "Embedded image" : "Linked image",
|
|
6219
5744
|
dims ? ` \xB7 ${dims}` : "",
|
|
6220
5745
|
bytes !== null ? ` \xB7 ${formatBytes(bytes)}` : ""
|
|
6221
5746
|
] }),
|
|
6222
|
-
!embedded && afterSrc && /* @__PURE__ */
|
|
6223
|
-
/* @__PURE__ */
|
|
6224
|
-
/* @__PURE__ */
|
|
6225
|
-
/* @__PURE__ */
|
|
5747
|
+
!embedded && afterSrc && /* @__PURE__ */ jsx12("a", { className: "rk-imgdetail-url", href: afterSrc, target: "_blank", rel: "noopener noreferrer", title: afterSrc, children: afterSrc }),
|
|
5748
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-imgdetail-actions", children: [
|
|
5749
|
+
/* @__PURE__ */ jsxs11("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => void download(), children: [
|
|
5750
|
+
/* @__PURE__ */ jsx12(IconDownload, { size: 12 }),
|
|
6226
5751
|
" Download"
|
|
6227
5752
|
] }),
|
|
6228
|
-
/* @__PURE__ */
|
|
5753
|
+
/* @__PURE__ */ jsx12("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => window.open(replacement, "_blank", "noopener"), children: "Open" })
|
|
6229
5754
|
] })
|
|
6230
5755
|
] });
|
|
6231
5756
|
}
|
|
5757
|
+
var SYNC_REASON_LABEL = {
|
|
5758
|
+
"token-short": "token too short",
|
|
5759
|
+
"bad-token": "token rejected",
|
|
5760
|
+
"room-full": "room full",
|
|
5761
|
+
unreachable: "server unreachable"
|
|
5762
|
+
};
|
|
5763
|
+
var SYNC_REASON_HELP = {
|
|
5764
|
+
"token-short": "The sync server needs a token of at least 8 characters. Use a longer `token` (or `syncToken`) in <ReviewKit /> and everyone with the link shares items live.",
|
|
5765
|
+
"bad-token": "The sync server rejected the token. Check `syncToken` / `token` in <ReviewKit />.",
|
|
5766
|
+
"room-full": "This page already has the maximum number of reviewers online (16). Try again later.",
|
|
5767
|
+
unreachable: "Could not reach the sync server. Usually the page's Content-Security-Policy is missing the server in connect-src, or the server is down. Items stay on this device meanwhile."
|
|
5768
|
+
};
|
|
6232
5769
|
function Panel() {
|
|
6233
|
-
const { session, panelOpen, activeItemId, badgeCorner, undoStack, preview, unapplied, syncStatus, emblemaPush, peers } = useStore();
|
|
5770
|
+
const { session, panelOpen, activeItemId, badgeCorner, undoStack, preview, unapplied, syncStatus, syncReason, emblemaPush, peers } = useStore();
|
|
6234
5771
|
const dispatch = useDispatch();
|
|
6235
5772
|
const config = useConfig();
|
|
6236
|
-
const [sticky, setStickyState] =
|
|
6237
|
-
const [query, setQuery] =
|
|
6238
|
-
const [typeFilter, setTypeFilter] =
|
|
6239
|
-
const [prioFilter, setPrioFilter] =
|
|
6240
|
-
const [statusFilter, setStatusFilter] =
|
|
6241
|
-
const [filterOpen, setFilterOpen] =
|
|
6242
|
-
const [settingsOpen, setSettingsOpen] =
|
|
6243
|
-
const [emblemaAlive, setEmblemaAlive] =
|
|
6244
|
-
const [emblemaSending, setEmblemaSending] =
|
|
6245
|
-
const [emblemaSync, setEmblemaSync] =
|
|
6246
|
-
const panelRef =
|
|
6247
|
-
const searchRef =
|
|
6248
|
-
const importRef =
|
|
6249
|
-
const sheetDrag =
|
|
6250
|
-
const items =
|
|
6251
|
-
const { orphanIds, hiddenIds } =
|
|
5773
|
+
const [sticky, setStickyState] = useState9(() => isStickyEnabled(config.token));
|
|
5774
|
+
const [query, setQuery] = useState9("");
|
|
5775
|
+
const [typeFilter, setTypeFilter] = useState9(/* @__PURE__ */ new Set());
|
|
5776
|
+
const [prioFilter, setPrioFilter] = useState9(/* @__PURE__ */ new Set());
|
|
5777
|
+
const [statusFilter, setStatusFilter] = useState9(/* @__PURE__ */ new Set());
|
|
5778
|
+
const [filterOpen, setFilterOpen] = useState9(false);
|
|
5779
|
+
const [settingsOpen, setSettingsOpen] = useState9(false);
|
|
5780
|
+
const [emblemaAlive, setEmblemaAlive] = useState9(null);
|
|
5781
|
+
const [emblemaSending, setEmblemaSending] = useState9(false);
|
|
5782
|
+
const [emblemaSync, setEmblemaSync] = useState9("unknown");
|
|
5783
|
+
const panelRef = useRef10(null);
|
|
5784
|
+
const searchRef = useRef10(null);
|
|
5785
|
+
const importRef = useRef10(null);
|
|
5786
|
+
const sheetDrag = useRef10(null);
|
|
5787
|
+
const items = useMemo3(() => session?.items ?? [], [session]);
|
|
5788
|
+
const { orphanIds, hiddenIds } = useMemo3(() => {
|
|
6252
5789
|
const orphans = /* @__PURE__ */ new Set();
|
|
6253
5790
|
const hiddens = /* @__PURE__ */ new Set();
|
|
6254
5791
|
for (const item of items) {
|
|
@@ -6259,15 +5796,15 @@ function Panel() {
|
|
|
6259
5796
|
}
|
|
6260
5797
|
return { orphanIds: orphans, hiddenIds: hiddens };
|
|
6261
5798
|
}, [items, panelOpen]);
|
|
6262
|
-
const activeFilter =
|
|
5799
|
+
const activeFilter = useMemo3(
|
|
6263
5800
|
() => typeFilter.size + prioFilter.size + statusFilter.size > 0 ? { types: [...typeFilter], priorities: [...prioFilter], statuses: [...statusFilter] } : null,
|
|
6264
5801
|
[typeFilter, prioFilter, statusFilter]
|
|
6265
5802
|
);
|
|
6266
|
-
|
|
5803
|
+
useEffect10(() => {
|
|
6267
5804
|
dispatch({ type: "SET_FILTER", filter: activeFilter });
|
|
6268
5805
|
return () => dispatch({ type: "SET_FILTER", filter: null });
|
|
6269
5806
|
}, [activeFilter, dispatch]);
|
|
6270
|
-
const filtered =
|
|
5807
|
+
const filtered = useMemo3(() => {
|
|
6271
5808
|
const q = query.trim().toLowerCase();
|
|
6272
5809
|
return items.map((item, index) => ({ item, number: index + 1 })).filter(({ item }) => {
|
|
6273
5810
|
if (!itemMatchesFilter(item, activeFilter)) return false;
|
|
@@ -6276,22 +5813,22 @@ function Panel() {
|
|
|
6276
5813
|
return haystack.includes(q);
|
|
6277
5814
|
});
|
|
6278
5815
|
}, [items, query, activeFilter]);
|
|
6279
|
-
const typeCounts =
|
|
5816
|
+
const typeCounts = useMemo3(() => {
|
|
6280
5817
|
const counts = /* @__PURE__ */ new Map();
|
|
6281
5818
|
for (const item of items) counts.set(item.type, (counts.get(item.type) ?? 0) + 1);
|
|
6282
5819
|
return counts;
|
|
6283
5820
|
}, [items]);
|
|
6284
|
-
const prioCounts =
|
|
5821
|
+
const prioCounts = useMemo3(() => {
|
|
6285
5822
|
const counts = /* @__PURE__ */ new Map();
|
|
6286
5823
|
for (const item of items) counts.set(item.priority, (counts.get(item.priority) ?? 0) + 1);
|
|
6287
5824
|
return counts;
|
|
6288
5825
|
}, [items]);
|
|
6289
|
-
const statusCounts =
|
|
5826
|
+
const statusCounts = useMemo3(() => {
|
|
6290
5827
|
const counts = /* @__PURE__ */ new Map();
|
|
6291
5828
|
for (const item of items) counts.set(item.status, (counts.get(item.status) ?? 0) + 1);
|
|
6292
5829
|
return counts;
|
|
6293
5830
|
}, [items]);
|
|
6294
|
-
const groups =
|
|
5831
|
+
const groups = useMemo3(() => {
|
|
6295
5832
|
const map = /* @__PURE__ */ new Map();
|
|
6296
5833
|
for (const entry of filtered) {
|
|
6297
5834
|
const list = map.get(entry.item.route) ?? [];
|
|
@@ -6300,7 +5837,7 @@ function Panel() {
|
|
|
6300
5837
|
}
|
|
6301
5838
|
return Array.from(map.entries());
|
|
6302
5839
|
}, [filtered]);
|
|
6303
|
-
|
|
5840
|
+
useEffect10(() => {
|
|
6304
5841
|
if (!filterOpen && !settingsOpen) return;
|
|
6305
5842
|
const onDown = (event) => {
|
|
6306
5843
|
const path = event.composedPath();
|
|
@@ -6311,7 +5848,7 @@ function Panel() {
|
|
|
6311
5848
|
document.addEventListener("pointerdown", onDown, true);
|
|
6312
5849
|
return () => document.removeEventListener("pointerdown", onDown, true);
|
|
6313
5850
|
}, [filterOpen, settingsOpen]);
|
|
6314
|
-
|
|
5851
|
+
useEffect10(() => {
|
|
6315
5852
|
if (!settingsOpen) return;
|
|
6316
5853
|
let alive = true;
|
|
6317
5854
|
const probe = () => {
|
|
@@ -6335,7 +5872,7 @@ function Panel() {
|
|
|
6335
5872
|
live: "paired",
|
|
6336
5873
|
off: "not paired"
|
|
6337
5874
|
}[emblemaPairState];
|
|
6338
|
-
|
|
5875
|
+
useEffect10(() => {
|
|
6339
5876
|
if (!panelOpen || activeItemId === null) return;
|
|
6340
5877
|
const row = panelRef.current?.querySelector(`[data-item-id="${activeItemId}"]`);
|
|
6341
5878
|
row?.scrollIntoView({ block: "nearest" });
|
|
@@ -6366,11 +5903,11 @@ function Panel() {
|
|
|
6366
5903
|
if (focusable.length === 0) return;
|
|
6367
5904
|
const first = focusable[0];
|
|
6368
5905
|
const last = focusable[focusable.length - 1];
|
|
6369
|
-
const
|
|
6370
|
-
if (event.shiftKey &&
|
|
5906
|
+
const active = panel.getRootNode() instanceof ShadowRoot ? panel.getRootNode().activeElement : document.activeElement;
|
|
5907
|
+
if (event.shiftKey && active === first) {
|
|
6371
5908
|
event.preventDefault();
|
|
6372
5909
|
last.focus();
|
|
6373
|
-
} else if (!event.shiftKey &&
|
|
5910
|
+
} else if (!event.shiftKey && active === last) {
|
|
6374
5911
|
event.preventDefault();
|
|
6375
5912
|
first.focus();
|
|
6376
5913
|
}
|
|
@@ -6451,7 +5988,7 @@ function Panel() {
|
|
|
6451
5988
|
panel.style.transform = "";
|
|
6452
5989
|
if (dy > 110) dispatch({ type: "SET_PANEL", open: false });
|
|
6453
5990
|
};
|
|
6454
|
-
return /* @__PURE__ */
|
|
5991
|
+
return /* @__PURE__ */ jsxs11(
|
|
6455
5992
|
"div",
|
|
6456
5993
|
{
|
|
6457
5994
|
ref: panelRef,
|
|
@@ -6461,7 +5998,7 @@ function Panel() {
|
|
|
6461
5998
|
"aria-label": "Review feedback panel",
|
|
6462
5999
|
onKeyDown,
|
|
6463
6000
|
children: [
|
|
6464
|
-
/* @__PURE__ */
|
|
6001
|
+
/* @__PURE__ */ jsx12(
|
|
6465
6002
|
"div",
|
|
6466
6003
|
{
|
|
6467
6004
|
className: "rk-sheet-handle",
|
|
@@ -6472,34 +6009,41 @@ function Panel() {
|
|
|
6472
6009
|
onPointerCancel: onSheetHandleUp
|
|
6473
6010
|
}
|
|
6474
6011
|
),
|
|
6475
|
-
/* @__PURE__ */
|
|
6476
|
-
/* @__PURE__ */
|
|
6477
|
-
/* @__PURE__ */
|
|
6478
|
-
/* @__PURE__ */
|
|
6012
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-panel-head", children: [
|
|
6013
|
+
/* @__PURE__ */ jsxs11("div", { children: [
|
|
6014
|
+
/* @__PURE__ */ jsx12("div", { className: "rk-panel-title", children: "Feedback" }),
|
|
6015
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-panel-sub", children: [
|
|
6479
6016
|
items.length,
|
|
6480
6017
|
" item",
|
|
6481
6018
|
items.length === 1 ? "" : "s",
|
|
6482
6019
|
session.author ? ` \xB7 ${session.author}` : "",
|
|
6483
|
-
syncStatus !== "disabled" && /* @__PURE__ */
|
|
6484
|
-
|
|
6485
|
-
|
|
6486
|
-
|
|
6487
|
-
|
|
6020
|
+
syncStatus !== "disabled" && /* @__PURE__ */ jsxs11(
|
|
6021
|
+
"span",
|
|
6022
|
+
{
|
|
6023
|
+
className: `rk-sync rk-sync-${syncStatus}${syncReason ? ` rk-sync-reason-${syncReason}` : ""}`,
|
|
6024
|
+
title: syncStatus === "online" ? "Live: everyone with this review link shares these items in real time" : syncStatus === "connecting" ? "Connecting to the sync server\u2026" : SYNC_REASON_HELP[syncReason ?? "unreachable"],
|
|
6025
|
+
children: [
|
|
6026
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-sync-dot" }),
|
|
6027
|
+
syncStatus === "online" ? `live${peers.length > 0 ? ` \xB7 ${peers.length} other${peers.length === 1 ? "" : "s"}` : ""}` : syncStatus === "connecting" ? "connecting\u2026" : `local only \xB7 ${SYNC_REASON_LABEL[syncReason ?? "unreachable"]}`
|
|
6028
|
+
]
|
|
6029
|
+
}
|
|
6030
|
+
),
|
|
6031
|
+
config.emblema && emblemaPush !== "idle" && /* @__PURE__ */ jsxs11(
|
|
6488
6032
|
"span",
|
|
6489
6033
|
{
|
|
6490
6034
|
className: `rk-sync rk-epush-${emblemaPush}`,
|
|
6491
6035
|
title: emblemaPush === "ok" ? "Review items stream to Emblema automatically" : emblemaPush === "sending" ? "Sending items to Emblema\u2026" : "Emblema isn't reachable \u2014 items resend on the next change, or use Resend all in the menu",
|
|
6492
6036
|
children: [
|
|
6493
|
-
/* @__PURE__ */
|
|
6494
|
-
emblemaPush === "ok" ? "emblema" : emblemaPush === "sending" ? "emblema\u2026" : "emblema offline"
|
|
6037
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-sync-dot" }),
|
|
6038
|
+
emblemaPush === "ok" ? "emblema" : emblemaPush === "sending" ? "emblema\u2026" : emblemaPush === "rejected" ? "emblema rejected" : "emblema offline"
|
|
6495
6039
|
]
|
|
6496
6040
|
}
|
|
6497
6041
|
)
|
|
6498
6042
|
] })
|
|
6499
6043
|
] }),
|
|
6500
|
-
/* @__PURE__ */
|
|
6501
|
-
/* @__PURE__ */
|
|
6502
|
-
/* @__PURE__ */
|
|
6044
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-spacer" }),
|
|
6045
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-menu-scope rk-menu-anchor", children: [
|
|
6046
|
+
/* @__PURE__ */ jsx12(
|
|
6503
6047
|
"button",
|
|
6504
6048
|
{
|
|
6505
6049
|
type: "button",
|
|
@@ -6515,11 +6059,11 @@ function Panel() {
|
|
|
6515
6059
|
void pingEmblema(config.emblema).then((port) => setEmblemaAlive(port !== null));
|
|
6516
6060
|
}
|
|
6517
6061
|
},
|
|
6518
|
-
children: /* @__PURE__ */
|
|
6062
|
+
children: /* @__PURE__ */ jsx12(IconGear, { size: 15 })
|
|
6519
6063
|
}
|
|
6520
6064
|
),
|
|
6521
|
-
settingsOpen && /* @__PURE__ */
|
|
6522
|
-
/* @__PURE__ */
|
|
6065
|
+
settingsOpen && /* @__PURE__ */ jsxs11("div", { className: "rk-menu", role: "menu", "aria-label": "Session settings", children: [
|
|
6066
|
+
config.token && /* @__PURE__ */ jsxs11(
|
|
6523
6067
|
"button",
|
|
6524
6068
|
{
|
|
6525
6069
|
type: "button",
|
|
@@ -6534,12 +6078,12 @@ function Panel() {
|
|
|
6534
6078
|
toast(dispatch, next ? "Review stays on in this tab" : "Review active only via the link", "info");
|
|
6535
6079
|
},
|
|
6536
6080
|
children: [
|
|
6537
|
-
/* @__PURE__ */
|
|
6081
|
+
/* @__PURE__ */ jsx12("span", { className: `rk-menu-check${sticky ? " rk-on" : ""}` }),
|
|
6538
6082
|
"Keep review on in this tab"
|
|
6539
6083
|
]
|
|
6540
6084
|
}
|
|
6541
6085
|
),
|
|
6542
|
-
config.emblema && /* @__PURE__ */
|
|
6086
|
+
config.emblema && /* @__PURE__ */ jsxs11(
|
|
6543
6087
|
"button",
|
|
6544
6088
|
{
|
|
6545
6089
|
type: "button",
|
|
@@ -6569,7 +6113,7 @@ function Panel() {
|
|
|
6569
6113
|
}).finally(() => setEmblemaSending(false));
|
|
6570
6114
|
},
|
|
6571
6115
|
children: [
|
|
6572
|
-
/* @__PURE__ */
|
|
6116
|
+
/* @__PURE__ */ jsx12(
|
|
6573
6117
|
"span",
|
|
6574
6118
|
{
|
|
6575
6119
|
className: "rk-emblema-dot",
|
|
@@ -6580,25 +6124,40 @@ function Panel() {
|
|
|
6580
6124
|
]
|
|
6581
6125
|
}
|
|
6582
6126
|
),
|
|
6583
|
-
/* @__PURE__ */
|
|
6127
|
+
/* @__PURE__ */ jsxs11(
|
|
6584
6128
|
"button",
|
|
6585
6129
|
{
|
|
6586
6130
|
type: "button",
|
|
6587
6131
|
role: "menuitem",
|
|
6588
6132
|
className: "rk-menu-item",
|
|
6589
|
-
title: emblemaPairState === "stale" ? "The local sync agent is not answering \u2014 run `npx reviewkit-emblema serve` in the project" : "Pair this project with the Emblema app via a sync key",
|
|
6133
|
+
title: emblemaPairState === "stale" ? "The local sync agent is not answering \u2014 run `npx -p @satanwagen/reviewkit-cli reviewkit-emblema serve` in the project" : "Pair this project with the Emblema app via a sync key",
|
|
6590
6134
|
onClick: () => {
|
|
6591
6135
|
setSettingsOpen(false);
|
|
6592
6136
|
dispatch({ type: "SET_EMBLEMA_CONNECT", open: true });
|
|
6593
6137
|
},
|
|
6594
6138
|
children: [
|
|
6595
|
-
/* @__PURE__ */
|
|
6139
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-emblema-dot", "data-state": emblemaPairState }),
|
|
6596
6140
|
"Connect to Emblema\u2026",
|
|
6597
|
-
/* @__PURE__ */
|
|
6141
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-menu-count", children: emblemaPairLabel })
|
|
6598
6142
|
]
|
|
6599
6143
|
}
|
|
6600
6144
|
),
|
|
6601
|
-
/* @__PURE__ */
|
|
6145
|
+
/* @__PURE__ */ jsx12(
|
|
6146
|
+
"button",
|
|
6147
|
+
{
|
|
6148
|
+
type: "button",
|
|
6149
|
+
role: "menuitem",
|
|
6150
|
+
className: "rk-menu-item",
|
|
6151
|
+
title: resolveSyncToken(config) ? "Pair the reviewkit terminal CLI / Claude Code MCP bridge with this site" : "Needs live sync (sync is off on this page) \u2014 the terminal reads the shared room",
|
|
6152
|
+
disabled: !resolveSyncToken(config),
|
|
6153
|
+
onClick: () => {
|
|
6154
|
+
setSettingsOpen(false);
|
|
6155
|
+
dispatch({ type: "SET_TERMINAL_CONNECT", open: true });
|
|
6156
|
+
},
|
|
6157
|
+
children: "Connect terminal / agent\u2026"
|
|
6158
|
+
}
|
|
6159
|
+
),
|
|
6160
|
+
/* @__PURE__ */ jsx12(
|
|
6602
6161
|
"button",
|
|
6603
6162
|
{
|
|
6604
6163
|
type: "button",
|
|
@@ -6611,31 +6170,31 @@ function Panel() {
|
|
|
6611
6170
|
)
|
|
6612
6171
|
] })
|
|
6613
6172
|
] }),
|
|
6614
|
-
/* @__PURE__ */
|
|
6173
|
+
/* @__PURE__ */ jsx12(
|
|
6615
6174
|
"button",
|
|
6616
6175
|
{
|
|
6617
6176
|
type: "button",
|
|
6618
6177
|
className: "rk-icon-btn",
|
|
6619
6178
|
"aria-label": "Keyboard shortcuts",
|
|
6620
6179
|
onClick: () => dispatch({ type: "SET_CHEATSHEET", open: true }),
|
|
6621
|
-
children: /* @__PURE__ */
|
|
6180
|
+
children: /* @__PURE__ */ jsx12(IconKeyboard, { size: 15 })
|
|
6622
6181
|
}
|
|
6623
6182
|
),
|
|
6624
|
-
/* @__PURE__ */
|
|
6183
|
+
/* @__PURE__ */ jsx12(
|
|
6625
6184
|
"button",
|
|
6626
6185
|
{
|
|
6627
6186
|
type: "button",
|
|
6628
6187
|
className: "rk-icon-btn",
|
|
6629
6188
|
"aria-label": "Close panel",
|
|
6630
6189
|
onClick: () => dispatch({ type: "SET_PANEL", open: false }),
|
|
6631
|
-
children: /* @__PURE__ */
|
|
6190
|
+
children: /* @__PURE__ */ jsx12(IconClose, { size: 14 })
|
|
6632
6191
|
}
|
|
6633
6192
|
)
|
|
6634
6193
|
] }),
|
|
6635
|
-
/* @__PURE__ */
|
|
6636
|
-
/* @__PURE__ */
|
|
6637
|
-
/* @__PURE__ */
|
|
6638
|
-
/* @__PURE__ */
|
|
6194
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-view-row", children: [
|
|
6195
|
+
/* @__PURE__ */ jsx12("div", { className: "rk-view-info", children: /* @__PURE__ */ jsx12("div", { className: "rk-view-title", children: "Page view" }) }),
|
|
6196
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-seg rk-view-toggle", role: "group", "aria-label": "Page view (P to toggle)", children: [
|
|
6197
|
+
/* @__PURE__ */ jsx12(
|
|
6639
6198
|
"button",
|
|
6640
6199
|
{
|
|
6641
6200
|
type: "button",
|
|
@@ -6645,7 +6204,7 @@ function Panel() {
|
|
|
6645
6204
|
children: "Original"
|
|
6646
6205
|
}
|
|
6647
6206
|
),
|
|
6648
|
-
/* @__PURE__ */
|
|
6207
|
+
/* @__PURE__ */ jsx12(
|
|
6649
6208
|
"button",
|
|
6650
6209
|
{
|
|
6651
6210
|
type: "button",
|
|
@@ -6657,8 +6216,8 @@ function Panel() {
|
|
|
6657
6216
|
)
|
|
6658
6217
|
] })
|
|
6659
6218
|
] }),
|
|
6660
|
-
/* @__PURE__ */
|
|
6661
|
-
/* @__PURE__ */
|
|
6219
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-panel-tools", children: [
|
|
6220
|
+
/* @__PURE__ */ jsxs11(
|
|
6662
6221
|
"button",
|
|
6663
6222
|
{
|
|
6664
6223
|
type: "button",
|
|
@@ -6669,15 +6228,15 @@ function Panel() {
|
|
|
6669
6228
|
dispatch({ type: "SET_MODE", mode: "pick" });
|
|
6670
6229
|
},
|
|
6671
6230
|
children: [
|
|
6672
|
-
/* @__PURE__ */
|
|
6231
|
+
/* @__PURE__ */ jsx12(IconTarget, { size: 14 }),
|
|
6673
6232
|
" Pick an element"
|
|
6674
6233
|
]
|
|
6675
6234
|
}
|
|
6676
6235
|
),
|
|
6677
|
-
/* @__PURE__ */
|
|
6678
|
-
/* @__PURE__ */
|
|
6679
|
-
/* @__PURE__ */
|
|
6680
|
-
/* @__PURE__ */
|
|
6236
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-search-row", children: [
|
|
6237
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-search", children: [
|
|
6238
|
+
/* @__PURE__ */ jsx12(IconSearch, { size: 13 }),
|
|
6239
|
+
/* @__PURE__ */ jsx12(
|
|
6681
6240
|
"input",
|
|
6682
6241
|
{
|
|
6683
6242
|
ref: searchRef,
|
|
@@ -6689,8 +6248,8 @@ function Panel() {
|
|
|
6689
6248
|
}
|
|
6690
6249
|
)
|
|
6691
6250
|
] }),
|
|
6692
|
-
/* @__PURE__ */
|
|
6693
|
-
/* @__PURE__ */
|
|
6251
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-menu-scope rk-menu-anchor", children: [
|
|
6252
|
+
/* @__PURE__ */ jsxs11(
|
|
6694
6253
|
"button",
|
|
6695
6254
|
{
|
|
6696
6255
|
type: "button",
|
|
@@ -6702,15 +6261,15 @@ function Panel() {
|
|
|
6702
6261
|
setSettingsOpen(false);
|
|
6703
6262
|
},
|
|
6704
6263
|
children: [
|
|
6705
|
-
/* @__PURE__ */
|
|
6264
|
+
/* @__PURE__ */ jsx12(IconFilter, { size: 13 }),
|
|
6706
6265
|
"Filter",
|
|
6707
|
-
typeFilter.size + prioFilter.size + statusFilter.size > 0 && /* @__PURE__ */
|
|
6266
|
+
typeFilter.size + prioFilter.size + statusFilter.size > 0 && /* @__PURE__ */ jsx12("span", { className: "rk-badge-count", children: typeFilter.size + prioFilter.size + statusFilter.size })
|
|
6708
6267
|
]
|
|
6709
6268
|
}
|
|
6710
6269
|
),
|
|
6711
|
-
filterOpen && /* @__PURE__ */
|
|
6712
|
-
/* @__PURE__ */
|
|
6713
|
-
TYPE_FILTERS.map((type) => /* @__PURE__ */
|
|
6270
|
+
filterOpen && /* @__PURE__ */ jsxs11("div", { className: "rk-menu", role: "menu", "aria-label": "Filter items", children: [
|
|
6271
|
+
/* @__PURE__ */ jsx12("div", { className: "rk-menu-title", children: "Type" }),
|
|
6272
|
+
TYPE_FILTERS.map((type) => /* @__PURE__ */ jsxs11(
|
|
6714
6273
|
"button",
|
|
6715
6274
|
{
|
|
6716
6275
|
type: "button",
|
|
@@ -6724,16 +6283,16 @@ function Panel() {
|
|
|
6724
6283
|
setTypeFilter(next);
|
|
6725
6284
|
},
|
|
6726
6285
|
children: [
|
|
6727
|
-
/* @__PURE__ */
|
|
6286
|
+
/* @__PURE__ */ jsx12("span", { className: `rk-menu-check${typeFilter.has(type) ? " rk-on" : ""}` }),
|
|
6728
6287
|
iconForType(type, 12),
|
|
6729
|
-
/* @__PURE__ */
|
|
6730
|
-
/* @__PURE__ */
|
|
6288
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-menu-label", children: type }),
|
|
6289
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-menu-count", children: typeCounts.get(type) ?? 0 })
|
|
6731
6290
|
]
|
|
6732
6291
|
},
|
|
6733
6292
|
type
|
|
6734
6293
|
)),
|
|
6735
|
-
/* @__PURE__ */
|
|
6736
|
-
PRIORITY_FILTERS.map((priority) => /* @__PURE__ */
|
|
6294
|
+
/* @__PURE__ */ jsx12("div", { className: "rk-menu-title", children: "Priority" }),
|
|
6295
|
+
PRIORITY_FILTERS.map((priority) => /* @__PURE__ */ jsxs11(
|
|
6737
6296
|
"button",
|
|
6738
6297
|
{
|
|
6739
6298
|
type: "button",
|
|
@@ -6747,15 +6306,15 @@ function Panel() {
|
|
|
6747
6306
|
setPrioFilter(next);
|
|
6748
6307
|
},
|
|
6749
6308
|
children: [
|
|
6750
|
-
/* @__PURE__ */
|
|
6751
|
-
/* @__PURE__ */
|
|
6752
|
-
/* @__PURE__ */
|
|
6309
|
+
/* @__PURE__ */ jsx12("span", { className: `rk-menu-check${prioFilter.has(priority) ? " rk-on" : ""}` }),
|
|
6310
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-menu-label", children: PRIORITY_LABELS[priority] }),
|
|
6311
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-menu-count", children: prioCounts.get(priority) ?? 0 })
|
|
6753
6312
|
]
|
|
6754
6313
|
},
|
|
6755
6314
|
priority
|
|
6756
6315
|
)),
|
|
6757
|
-
/* @__PURE__ */
|
|
6758
|
-
STATUSES.map((status) => /* @__PURE__ */
|
|
6316
|
+
/* @__PURE__ */ jsx12("div", { className: "rk-menu-title", children: "Status" }),
|
|
6317
|
+
STATUSES.map((status) => /* @__PURE__ */ jsxs11(
|
|
6759
6318
|
"button",
|
|
6760
6319
|
{
|
|
6761
6320
|
type: "button",
|
|
@@ -6769,15 +6328,15 @@ function Panel() {
|
|
|
6769
6328
|
setStatusFilter(next);
|
|
6770
6329
|
},
|
|
6771
6330
|
children: [
|
|
6772
|
-
/* @__PURE__ */
|
|
6773
|
-
/* @__PURE__ */
|
|
6774
|
-
/* @__PURE__ */
|
|
6775
|
-
/* @__PURE__ */
|
|
6331
|
+
/* @__PURE__ */ jsx12("span", { className: `rk-menu-check${statusFilter.has(status) ? " rk-on" : ""}` }),
|
|
6332
|
+
/* @__PURE__ */ jsx12("span", { className: `rk-status-dot rk-st-${status}` }),
|
|
6333
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-menu-label", children: status }),
|
|
6334
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-menu-count", children: statusCounts.get(status) ?? 0 })
|
|
6776
6335
|
]
|
|
6777
6336
|
},
|
|
6778
6337
|
status
|
|
6779
6338
|
)),
|
|
6780
|
-
/* @__PURE__ */
|
|
6339
|
+
/* @__PURE__ */ jsx12(
|
|
6781
6340
|
"button",
|
|
6782
6341
|
{
|
|
6783
6342
|
type: "button",
|
|
@@ -6797,28 +6356,28 @@ function Panel() {
|
|
|
6797
6356
|
] })
|
|
6798
6357
|
] })
|
|
6799
6358
|
] }),
|
|
6800
|
-
preview && unapplied > 0 && /* @__PURE__ */
|
|
6359
|
+
preview && unapplied > 0 && /* @__PURE__ */ jsxs11("div", { className: "rk-unplaced", role: "status", children: [
|
|
6801
6360
|
unapplied,
|
|
6802
6361
|
" saved change",
|
|
6803
6362
|
unapplied === 1 ? "" : "s",
|
|
6804
6363
|
" couldn\u2019t be placed on the current page \u2014 the page has changed since they were captured."
|
|
6805
6364
|
] }),
|
|
6806
|
-
/* @__PURE__ */
|
|
6807
|
-
/* @__PURE__ */
|
|
6808
|
-
/* @__PURE__ */
|
|
6809
|
-
/* @__PURE__ */
|
|
6810
|
-
] }) : groups.map(([route, entries]) => /* @__PURE__ */
|
|
6811
|
-
/* @__PURE__ */
|
|
6365
|
+
/* @__PURE__ */ jsx12("div", { className: "rk-panel-list", children: filtered.length === 0 ? /* @__PURE__ */ jsxs11("div", { className: "rk-empty", children: [
|
|
6366
|
+
/* @__PURE__ */ jsx12("div", { className: "rk-empty-art", children: /* @__PURE__ */ jsx12(IconTarget, { size: 22 }) }),
|
|
6367
|
+
/* @__PURE__ */ jsx12("div", { className: "rk-empty-title", children: items.length === 0 ? "Nothing here yet" : "No matches" }),
|
|
6368
|
+
/* @__PURE__ */ jsx12("div", { className: "rk-empty-text", children: items.length === 0 ? "Choose \u201CPick an element\u201D, then click anything on the page. Your suggestions collect here, ready to hand off." : "Try a different search, or clear the filters." })
|
|
6369
|
+
] }) : groups.map(([route, entries]) => /* @__PURE__ */ jsxs11("div", { children: [
|
|
6370
|
+
/* @__PURE__ */ jsx12("div", { className: "rk-group-title", children: route }),
|
|
6812
6371
|
entries.map(({ item, number }) => {
|
|
6813
|
-
const
|
|
6372
|
+
const active = item.id === activeItemId;
|
|
6814
6373
|
const orphan = orphanIds.has(item.id);
|
|
6815
6374
|
const hiddenEl = hiddenIds.has(item.id);
|
|
6816
|
-
return /* @__PURE__ */
|
|
6817
|
-
/* @__PURE__ */
|
|
6375
|
+
return /* @__PURE__ */ jsxs11("div", { children: [
|
|
6376
|
+
/* @__PURE__ */ jsxs11(
|
|
6818
6377
|
"div",
|
|
6819
6378
|
{
|
|
6820
6379
|
"data-item-id": item.id,
|
|
6821
|
-
className: `rk-item${
|
|
6380
|
+
className: `rk-item${active ? " rk-active" : ""}${orphan ? " rk-orphan" : ""}`,
|
|
6822
6381
|
role: "button",
|
|
6823
6382
|
tabIndex: 0,
|
|
6824
6383
|
onClick: () => jumpTo(item),
|
|
@@ -6829,18 +6388,18 @@ function Panel() {
|
|
|
6829
6388
|
}
|
|
6830
6389
|
},
|
|
6831
6390
|
children: [
|
|
6832
|
-
/* @__PURE__ */
|
|
6833
|
-
/* @__PURE__ */
|
|
6834
|
-
/* @__PURE__ */
|
|
6835
|
-
/* @__PURE__ */
|
|
6391
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-item-num", children: number }),
|
|
6392
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-item-icon", children: iconForType(item.type) }),
|
|
6393
|
+
/* @__PURE__ */ jsxs11("span", { className: "rk-item-body", children: [
|
|
6394
|
+
/* @__PURE__ */ jsxs11("span", { className: "rk-item-snippet", children: [
|
|
6836
6395
|
item.target.tagName,
|
|
6837
6396
|
" \xB7 ",
|
|
6838
6397
|
item.target.textSnippet || item.target.selector
|
|
6839
6398
|
] }),
|
|
6840
|
-
/* @__PURE__ */
|
|
6841
|
-
/* @__PURE__ */
|
|
6842
|
-
/* @__PURE__ */
|
|
6843
|
-
/* @__PURE__ */
|
|
6399
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-item-change", children: changeSummary(item) }),
|
|
6400
|
+
/* @__PURE__ */ jsxs11("span", { className: "rk-item-meta", children: [
|
|
6401
|
+
/* @__PURE__ */ jsxs11("span", { className: "rk-author", title: new Date(item.createdAt).toLocaleString(), children: [
|
|
6402
|
+
/* @__PURE__ */ jsx12(
|
|
6844
6403
|
"span",
|
|
6845
6404
|
{
|
|
6846
6405
|
className: "rk-author-dot",
|
|
@@ -6848,15 +6407,15 @@ function Panel() {
|
|
|
6848
6407
|
}
|
|
6849
6408
|
),
|
|
6850
6409
|
item.author?.name ?? "Unknown",
|
|
6851
|
-
/* @__PURE__ */
|
|
6410
|
+
/* @__PURE__ */ jsxs11("span", { className: "rk-time", children: [
|
|
6852
6411
|
" \xB7 ",
|
|
6853
6412
|
timeAgo(item.createdAt)
|
|
6854
6413
|
] })
|
|
6855
6414
|
] }),
|
|
6856
|
-
item.priority === "must" && /* @__PURE__ */
|
|
6857
|
-
item.status !== "open" && /* @__PURE__ */
|
|
6858
|
-
orphan && /* @__PURE__ */
|
|
6859
|
-
hiddenEl && /* @__PURE__ */
|
|
6415
|
+
item.priority === "must" && /* @__PURE__ */ jsx12("span", { className: "rk-badge-mini rk-must", children: "must" }),
|
|
6416
|
+
item.status !== "open" && /* @__PURE__ */ jsx12("span", { className: `rk-badge-mini rk-${item.status}`, children: item.status }),
|
|
6417
|
+
orphan && /* @__PURE__ */ jsx12("span", { className: "rk-badge-mini rk-orphaned", children: "unanchored" }),
|
|
6418
|
+
hiddenEl && /* @__PURE__ */ jsx12(
|
|
6860
6419
|
"span",
|
|
6861
6420
|
{
|
|
6862
6421
|
className: "rk-badge-mini rk-hidden-el",
|
|
@@ -6864,14 +6423,14 @@ function Panel() {
|
|
|
6864
6423
|
children: "hidden"
|
|
6865
6424
|
}
|
|
6866
6425
|
),
|
|
6867
|
-
item.note && /* @__PURE__ */
|
|
6868
|
-
peers.filter((peer) => peer.typingActive && peer.typingItemId === item.id).map((peer) => /* @__PURE__ */
|
|
6426
|
+
item.note && /* @__PURE__ */ jsx12("span", { className: "rk-badge-mini", children: "note" }),
|
|
6427
|
+
peers.filter((peer) => peer.typingActive && peer.typingItemId === item.id).map((peer) => /* @__PURE__ */ jsxs11("span", { className: "rk-badge-mini", style: { color: peer.color }, children: [
|
|
6869
6428
|
peer.name || "peer",
|
|
6870
6429
|
" is writing\u2026"
|
|
6871
6430
|
] }, peer.id))
|
|
6872
6431
|
] })
|
|
6873
6432
|
] }),
|
|
6874
|
-
/* @__PURE__ */
|
|
6433
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-item-actions", children: /* @__PURE__ */ jsx12(
|
|
6875
6434
|
"button",
|
|
6876
6435
|
{
|
|
6877
6436
|
type: "button",
|
|
@@ -6886,15 +6445,15 @@ function Panel() {
|
|
|
6886
6445
|
"info"
|
|
6887
6446
|
);
|
|
6888
6447
|
},
|
|
6889
|
-
children: /* @__PURE__ */
|
|
6448
|
+
children: /* @__PURE__ */ jsx12(IconTrash, { size: 13 })
|
|
6890
6449
|
}
|
|
6891
6450
|
) })
|
|
6892
6451
|
]
|
|
6893
6452
|
}
|
|
6894
6453
|
),
|
|
6895
|
-
|
|
6896
|
-
/* @__PURE__ */
|
|
6897
|
-
/* @__PURE__ */
|
|
6454
|
+
active && /* @__PURE__ */ jsxs11("div", { className: "rk-item-edit", children: [
|
|
6455
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-detail-byline", title: new Date(item.createdAt).toLocaleString(), children: [
|
|
6456
|
+
/* @__PURE__ */ jsx12(
|
|
6898
6457
|
"span",
|
|
6899
6458
|
{
|
|
6900
6459
|
className: "rk-author-dot",
|
|
@@ -6905,8 +6464,8 @@ function Panel() {
|
|
|
6905
6464
|
" \xB7 ",
|
|
6906
6465
|
timeAgo(item.createdAt)
|
|
6907
6466
|
] }),
|
|
6908
|
-
isCopyItem(item) && /* @__PURE__ */
|
|
6909
|
-
isImageItem(item) && /* @__PURE__ */
|
|
6467
|
+
isCopyItem(item) && /* @__PURE__ */ jsx12(CopyDiff, { before: item.payload.before, after: item.payload.after }),
|
|
6468
|
+
isImageItem(item) && /* @__PURE__ */ jsx12(
|
|
6910
6469
|
ImageDetail,
|
|
6911
6470
|
{
|
|
6912
6471
|
beforeSrc: item.payload.beforeSrc,
|
|
@@ -6914,7 +6473,7 @@ function Panel() {
|
|
|
6914
6473
|
afterDataUrl: item.payload.afterDataUrl
|
|
6915
6474
|
}
|
|
6916
6475
|
),
|
|
6917
|
-
isKnownItemType(item.type) && item.type !== "move" && /* @__PURE__ */
|
|
6476
|
+
isKnownItemType(item.type) && item.type !== "move" && /* @__PURE__ */ jsx12(
|
|
6918
6477
|
"textarea",
|
|
6919
6478
|
{
|
|
6920
6479
|
className: "rk-textarea",
|
|
@@ -6924,7 +6483,7 @@ function Panel() {
|
|
|
6924
6483
|
onChange: (event) => dispatch({ type: "UPDATE_ITEM", id: item.id, patch: withPayloadText(item, event.target.value) })
|
|
6925
6484
|
}
|
|
6926
6485
|
),
|
|
6927
|
-
/* @__PURE__ */
|
|
6486
|
+
/* @__PURE__ */ jsx12(
|
|
6928
6487
|
"input",
|
|
6929
6488
|
{
|
|
6930
6489
|
className: "rk-input",
|
|
@@ -6934,9 +6493,9 @@ function Panel() {
|
|
|
6934
6493
|
onChange: (event) => dispatch({ type: "UPDATE_ITEM", id: item.id, patch: { note: event.target.value } })
|
|
6935
6494
|
}
|
|
6936
6495
|
),
|
|
6937
|
-
/* @__PURE__ */
|
|
6938
|
-
/* @__PURE__ */
|
|
6939
|
-
/* @__PURE__ */
|
|
6496
|
+
/* @__PURE__ */ jsxs11("div", { style: { display: "flex", gap: 8, flexWrap: "wrap" }, children: [
|
|
6497
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-seg", role: "group", "aria-label": "Priority", children: [
|
|
6498
|
+
/* @__PURE__ */ jsx12(
|
|
6940
6499
|
"button",
|
|
6941
6500
|
{
|
|
6942
6501
|
type: "button",
|
|
@@ -6945,7 +6504,7 @@ function Panel() {
|
|
|
6945
6504
|
children: "Must"
|
|
6946
6505
|
}
|
|
6947
6506
|
),
|
|
6948
|
-
/* @__PURE__ */
|
|
6507
|
+
/* @__PURE__ */ jsx12(
|
|
6949
6508
|
"button",
|
|
6950
6509
|
{
|
|
6951
6510
|
type: "button",
|
|
@@ -6955,7 +6514,7 @@ function Panel() {
|
|
|
6955
6514
|
}
|
|
6956
6515
|
)
|
|
6957
6516
|
] }),
|
|
6958
|
-
/* @__PURE__ */
|
|
6517
|
+
/* @__PURE__ */ jsx12("div", { className: "rk-seg", role: "group", "aria-label": "Status", children: STATUSES.map((status) => /* @__PURE__ */ jsx12(
|
|
6959
6518
|
"button",
|
|
6960
6519
|
{
|
|
6961
6520
|
type: "button",
|
|
@@ -6970,22 +6529,22 @@ function Panel() {
|
|
|
6970
6529
|
] }, item.id);
|
|
6971
6530
|
})
|
|
6972
6531
|
] }, route)) }),
|
|
6973
|
-
/* @__PURE__ */
|
|
6974
|
-
/* @__PURE__ */
|
|
6975
|
-
/* @__PURE__ */
|
|
6532
|
+
/* @__PURE__ */ jsxs11("div", { className: "rk-panel-foot", children: [
|
|
6533
|
+
/* @__PURE__ */ jsxs11("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: onExport, disabled: items.length === 0, children: [
|
|
6534
|
+
/* @__PURE__ */ jsx12(IconDownload, { size: 13 }),
|
|
6976
6535
|
" Export"
|
|
6977
6536
|
] }),
|
|
6978
|
-
/* @__PURE__ */
|
|
6979
|
-
/* @__PURE__ */
|
|
6537
|
+
/* @__PURE__ */ jsxs11("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => void onCopy(), disabled: items.length === 0, children: [
|
|
6538
|
+
/* @__PURE__ */ jsx12(IconCopyClipboard, { size: 13 }),
|
|
6980
6539
|
" Copy"
|
|
6981
6540
|
] }),
|
|
6982
|
-
/* @__PURE__ */
|
|
6983
|
-
/* @__PURE__ */
|
|
6541
|
+
/* @__PURE__ */ jsxs11("button", { type: "button", className: "rk-btn rk-btn-ghost", onClick: () => importRef.current?.click(), children: [
|
|
6542
|
+
/* @__PURE__ */ jsx12(IconUpload, { size: 13 }),
|
|
6984
6543
|
" Import"
|
|
6985
6544
|
] }),
|
|
6986
|
-
/* @__PURE__ */
|
|
6987
|
-
undoStack.length > 0 && /* @__PURE__ */
|
|
6988
|
-
/* @__PURE__ */
|
|
6545
|
+
/* @__PURE__ */ jsx12("span", { className: "rk-spacer" }),
|
|
6546
|
+
undoStack.length > 0 && /* @__PURE__ */ jsx12("button", { type: "button", className: "rk-icon-btn", "aria-label": "Undo last change (\u2318Z)", onClick: () => dispatch({ type: "UNDO" }), children: /* @__PURE__ */ jsx12(IconUndo, { size: 14 }) }),
|
|
6547
|
+
/* @__PURE__ */ jsx12(
|
|
6989
6548
|
"button",
|
|
6990
6549
|
{
|
|
6991
6550
|
type: "button",
|
|
@@ -6996,7 +6555,7 @@ function Panel() {
|
|
|
6996
6555
|
children: "Clear"
|
|
6997
6556
|
}
|
|
6998
6557
|
),
|
|
6999
|
-
/* @__PURE__ */
|
|
6558
|
+
/* @__PURE__ */ jsx12(
|
|
7000
6559
|
"button",
|
|
7001
6560
|
{
|
|
7002
6561
|
type: "button",
|
|
@@ -7006,7 +6565,7 @@ function Panel() {
|
|
|
7006
6565
|
children: "Exit review"
|
|
7007
6566
|
}
|
|
7008
6567
|
),
|
|
7009
|
-
/* @__PURE__ */
|
|
6568
|
+
/* @__PURE__ */ jsx12(
|
|
7010
6569
|
"input",
|
|
7011
6570
|
{
|
|
7012
6571
|
ref: importRef,
|
|
@@ -7025,6 +6584,10 @@ function Panel() {
|
|
|
7025
6584
|
}
|
|
7026
6585
|
);
|
|
7027
6586
|
}
|
|
6587
|
+
|
|
6588
|
+
// src/client/components/Presence.tsx
|
|
6589
|
+
import { useEffect as useEffect11, useRef as useRef11 } from "react";
|
|
6590
|
+
import { Fragment as Fragment7, jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
7028
6591
|
function initials(name) {
|
|
7029
6592
|
const parts = name.trim().split(/\s+/).filter(Boolean);
|
|
7030
6593
|
if (parts.length === 0) return "\xB7";
|
|
@@ -7034,8 +6597,8 @@ function initials(name) {
|
|
|
7034
6597
|
function PresenceStrip() {
|
|
7035
6598
|
const { peers, syncStatus } = useStore();
|
|
7036
6599
|
if (syncStatus === "disabled" || peers.length === 0) return null;
|
|
7037
|
-
return /* @__PURE__ */
|
|
7038
|
-
peers.slice(0, 5).map((peer) => /* @__PURE__ */
|
|
6600
|
+
return /* @__PURE__ */ jsxs12("div", { className: "rk-presence", "aria-label": `${peers.length} reviewer${peers.length === 1 ? "" : "s"} online`, children: [
|
|
6601
|
+
peers.slice(0, 5).map((peer) => /* @__PURE__ */ jsx13(
|
|
7039
6602
|
"span",
|
|
7040
6603
|
{
|
|
7041
6604
|
className: "rk-avatar",
|
|
@@ -7045,7 +6608,7 @@ function PresenceStrip() {
|
|
|
7045
6608
|
},
|
|
7046
6609
|
peer.id
|
|
7047
6610
|
)),
|
|
7048
|
-
peers.length > 5 && /* @__PURE__ */
|
|
6611
|
+
peers.length > 5 && /* @__PURE__ */ jsxs12("span", { className: "rk-avatar rk-avatar-more", children: [
|
|
7049
6612
|
"+",
|
|
7050
6613
|
peers.length - 5
|
|
7051
6614
|
] })
|
|
@@ -7053,13 +6616,13 @@ function PresenceStrip() {
|
|
|
7053
6616
|
}
|
|
7054
6617
|
function PeerCursors() {
|
|
7055
6618
|
const { peers } = useStore();
|
|
7056
|
-
const ringRefs =
|
|
7057
|
-
const cursorRefs =
|
|
7058
|
-
const motion =
|
|
6619
|
+
const ringRefs = useRef11(/* @__PURE__ */ new Map());
|
|
6620
|
+
const cursorRefs = useRef11(/* @__PURE__ */ new Map());
|
|
6621
|
+
const motion = useRef11(
|
|
7059
6622
|
/* @__PURE__ */ new Map()
|
|
7060
6623
|
);
|
|
7061
|
-
const peersRef =
|
|
7062
|
-
const seen =
|
|
6624
|
+
const peersRef = useRef11(peers);
|
|
6625
|
+
const seen = useRef11(/* @__PURE__ */ new Map());
|
|
7063
6626
|
for (const peer of peers) {
|
|
7064
6627
|
const sig = peer.cursor ? `${peer.cursor.x},${peer.cursor.y},${peer.cursor.ox},${peer.cursor.oy}` : "";
|
|
7065
6628
|
if (seen.current.get(peer.id) !== sig) {
|
|
@@ -7069,7 +6632,7 @@ function PeerCursors() {
|
|
|
7069
6632
|
}
|
|
7070
6633
|
}
|
|
7071
6634
|
peersRef.current = peers;
|
|
7072
|
-
|
|
6635
|
+
useEffect11(() => {
|
|
7073
6636
|
const reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
7074
6637
|
let raf = 0;
|
|
7075
6638
|
let last = performance.now();
|
|
@@ -7174,8 +6737,8 @@ function PeerCursors() {
|
|
|
7174
6737
|
return () => cancelAnimationFrame(raf);
|
|
7175
6738
|
}, []);
|
|
7176
6739
|
if (peers.length === 0) return null;
|
|
7177
|
-
return /* @__PURE__ */
|
|
7178
|
-
peers.map((peer) => /* @__PURE__ */
|
|
6740
|
+
return /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
6741
|
+
peers.map((peer) => /* @__PURE__ */ jsx13(
|
|
7179
6742
|
"div",
|
|
7180
6743
|
{
|
|
7181
6744
|
ref: (el) => {
|
|
@@ -7187,7 +6750,7 @@ function PeerCursors() {
|
|
|
7187
6750
|
},
|
|
7188
6751
|
`ring-${peer.id}`
|
|
7189
6752
|
)),
|
|
7190
|
-
peers.map((peer, index) => /* @__PURE__ */
|
|
6753
|
+
peers.map((peer, index) => /* @__PURE__ */ jsxs12(
|
|
7191
6754
|
"div",
|
|
7192
6755
|
{
|
|
7193
6756
|
ref: (el) => {
|
|
@@ -7197,8 +6760,8 @@ function PeerCursors() {
|
|
|
7197
6760
|
className: "rk-peer-cursor",
|
|
7198
6761
|
style: { opacity: 0 },
|
|
7199
6762
|
children: [
|
|
7200
|
-
/* @__PURE__ */
|
|
7201
|
-
/* @__PURE__ */
|
|
6763
|
+
/* @__PURE__ */ jsx13("svg", { width: "14", height: "18", viewBox: "0 0 14 18", "aria-hidden": "true", children: /* @__PURE__ */ jsx13("path", { d: "M1 1l12 7.5-5.2 1.2L5 16z", fill: peer.color, stroke: "rgba(0,0,0,0.25)", strokeWidth: "1" }) }),
|
|
6764
|
+
/* @__PURE__ */ jsxs12(
|
|
7202
6765
|
"span",
|
|
7203
6766
|
{
|
|
7204
6767
|
className: "rk-peer-name",
|
|
@@ -7215,17 +6778,21 @@ function PeerCursors() {
|
|
|
7215
6778
|
))
|
|
7216
6779
|
] });
|
|
7217
6780
|
}
|
|
6781
|
+
|
|
6782
|
+
// src/client/components/QuickComment.tsx
|
|
6783
|
+
import { useEffect as useEffect12, useRef as useRef12, useState as useState10 } from "react";
|
|
6784
|
+
import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
7218
6785
|
function QuickComment() {
|
|
7219
6786
|
const { quick } = useStore();
|
|
7220
6787
|
if (!quick) return null;
|
|
7221
|
-
return /* @__PURE__ */
|
|
6788
|
+
return /* @__PURE__ */ jsx14(QuickComposerCard, { quick }, quick.id);
|
|
7222
6789
|
}
|
|
7223
6790
|
function QuickComposerCard({ quick }) {
|
|
7224
6791
|
const { route, session } = useStore();
|
|
7225
6792
|
const dispatch = useDispatch();
|
|
7226
|
-
const [text, setText] =
|
|
7227
|
-
const fieldRef =
|
|
7228
|
-
|
|
6793
|
+
const [text, setText] = useState10("");
|
|
6794
|
+
const fieldRef = useRef12(null);
|
|
6795
|
+
useEffect12(() => {
|
|
7229
6796
|
const field = fieldRef.current;
|
|
7230
6797
|
if (!field) return;
|
|
7231
6798
|
field.focus();
|
|
@@ -7242,7 +6809,7 @@ function QuickComposerCard({ quick }) {
|
|
|
7242
6809
|
return;
|
|
7243
6810
|
}
|
|
7244
6811
|
const command = /^\/(\S+)$/.exec(trimmed);
|
|
7245
|
-
if (command &&
|
|
6812
|
+
if (command && isEffectCommand(command[1])) {
|
|
7246
6813
|
try {
|
|
7247
6814
|
runEffect(command[1], layerRoot);
|
|
7248
6815
|
sendEffectToRoom(command[1]);
|
|
@@ -7278,18 +6845,18 @@ function QuickComposerCard({ quick }) {
|
|
|
7278
6845
|
};
|
|
7279
6846
|
const x = Math.min(Math.max(quick.x, 8), window.innerWidth - 288);
|
|
7280
6847
|
const y = Math.min(Math.max(quick.y + 12, 8), window.innerHeight - 108);
|
|
7281
|
-
return /* @__PURE__ */
|
|
7282
|
-
/* @__PURE__ */
|
|
7283
|
-
/* @__PURE__ */
|
|
7284
|
-
/* @__PURE__ */
|
|
7285
|
-
/* @__PURE__ */
|
|
7286
|
-
/* @__PURE__ */
|
|
6848
|
+
return /* @__PURE__ */ jsxs13("div", { className: "rk-quick", style: { transform: `translate3d(${x}px, ${y}px, 0)` }, role: "dialog", "aria-label": "Quick comment", children: [
|
|
6849
|
+
/* @__PURE__ */ jsxs13("div", { className: "rk-quick-head", children: [
|
|
6850
|
+
/* @__PURE__ */ jsx14(IconComment, { size: 12 }),
|
|
6851
|
+
/* @__PURE__ */ jsx14("span", { children: "Comment here" }),
|
|
6852
|
+
/* @__PURE__ */ jsxs13("span", { className: "rk-hint", children: [
|
|
6853
|
+
/* @__PURE__ */ jsx14("span", { className: "rk-kbd", children: "\u21B5" }),
|
|
7287
6854
|
" save \xB7 ",
|
|
7288
|
-
/* @__PURE__ */
|
|
6855
|
+
/* @__PURE__ */ jsx14("span", { className: "rk-kbd", children: "esc" }),
|
|
7289
6856
|
" cancel"
|
|
7290
6857
|
] })
|
|
7291
6858
|
] }),
|
|
7292
|
-
/* @__PURE__ */
|
|
6859
|
+
/* @__PURE__ */ jsx14(
|
|
7293
6860
|
"textarea",
|
|
7294
6861
|
{
|
|
7295
6862
|
ref: fieldRef,
|
|
@@ -7303,6 +6870,10 @@ function QuickComposerCard({ quick }) {
|
|
|
7303
6870
|
)
|
|
7304
6871
|
] });
|
|
7305
6872
|
}
|
|
6873
|
+
|
|
6874
|
+
// src/client/components/PickLayer.tsx
|
|
6875
|
+
import { useEffect as useEffect13, useRef as useRef13, useState as useState11 } from "react";
|
|
6876
|
+
import { Fragment as Fragment8, jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
7306
6877
|
function applyRect(el, rect, pad2 = 3) {
|
|
7307
6878
|
if (!el) return;
|
|
7308
6879
|
if (!rect) {
|
|
@@ -7317,14 +6888,14 @@ function applyRect(el, rect, pad2 = 3) {
|
|
|
7317
6888
|
function PickLayer() {
|
|
7318
6889
|
const { mode, selection, tool } = useStore();
|
|
7319
6890
|
const dispatch = useDispatch();
|
|
7320
|
-
const [hovered, setHovered] =
|
|
7321
|
-
const outlineRef =
|
|
7322
|
-
const labelRef =
|
|
7323
|
-
const selectRef =
|
|
7324
|
-
const hoveredRef =
|
|
6891
|
+
const [hovered, setHovered] = useState11(null);
|
|
6892
|
+
const outlineRef = useRef13(null);
|
|
6893
|
+
const labelRef = useRef13(null);
|
|
6894
|
+
const selectRef = useRef13(null);
|
|
6895
|
+
const hoveredRef = useRef13(null);
|
|
7325
6896
|
hoveredRef.current = hovered;
|
|
7326
6897
|
const picking = mode === "pick";
|
|
7327
|
-
|
|
6898
|
+
useEffect13(() => {
|
|
7328
6899
|
if (!picking) {
|
|
7329
6900
|
setHovered(null);
|
|
7330
6901
|
return;
|
|
@@ -7368,7 +6939,7 @@ function PickLayer() {
|
|
|
7368
6939
|
document.removeEventListener("mousedown", swallow, true);
|
|
7369
6940
|
};
|
|
7370
6941
|
}, [picking, tool, dispatch]);
|
|
7371
|
-
|
|
6942
|
+
useEffect13(() => {
|
|
7372
6943
|
if (!picking) return;
|
|
7373
6944
|
const body = document.body;
|
|
7374
6945
|
const prev = body.style.cursor;
|
|
@@ -7378,7 +6949,7 @@ function PickLayer() {
|
|
|
7378
6949
|
if (body.getAttribute("style") === "") body.removeAttribute("style");
|
|
7379
6950
|
};
|
|
7380
6951
|
}, [picking, tool]);
|
|
7381
|
-
|
|
6952
|
+
useEffect13(() => {
|
|
7382
6953
|
let raf = 0;
|
|
7383
6954
|
const tick = () => {
|
|
7384
6955
|
const hoverEl = hoveredRef.current;
|
|
@@ -7404,17 +6975,21 @@ function PickLayer() {
|
|
|
7404
6975
|
raf = requestAnimationFrame(tick);
|
|
7405
6976
|
return () => cancelAnimationFrame(raf);
|
|
7406
6977
|
}, [picking, selection]);
|
|
7407
|
-
return /* @__PURE__ */
|
|
7408
|
-
picking && /* @__PURE__ */
|
|
7409
|
-
/* @__PURE__ */
|
|
7410
|
-
/* @__PURE__ */
|
|
7411
|
-
/* @__PURE__ */
|
|
7412
|
-
/* @__PURE__ */
|
|
7413
|
-
] }) : /* @__PURE__ */
|
|
6978
|
+
return /* @__PURE__ */ jsxs14(Fragment8, { children: [
|
|
6979
|
+
picking && /* @__PURE__ */ jsxs14(Fragment8, { children: [
|
|
6980
|
+
/* @__PURE__ */ jsx15("div", { ref: outlineRef, className: "rk-outline", style: { opacity: 0 } }),
|
|
6981
|
+
/* @__PURE__ */ jsx15("div", { ref: labelRef, className: "rk-outline-label", style: { opacity: 0 }, children: hovered ? /* @__PURE__ */ jsxs14(Fragment8, { children: [
|
|
6982
|
+
/* @__PURE__ */ jsx15("span", { className: "rk-tag", children: hovered.tagName.toLowerCase() }),
|
|
6983
|
+
/* @__PURE__ */ jsx15("span", { children: describeElement(hovered).replace(/^[a-z0-9]+ · /, "") })
|
|
6984
|
+
] }) : /* @__PURE__ */ jsx15("span", { children: "Pick an element" }) })
|
|
7414
6985
|
] }),
|
|
7415
|
-
selection && /* @__PURE__ */
|
|
6986
|
+
selection && /* @__PURE__ */ jsx15("div", { ref: selectRef, className: "rk-select-ring", style: { opacity: 0 } })
|
|
7416
6987
|
] });
|
|
7417
6988
|
}
|
|
6989
|
+
|
|
6990
|
+
// src/client/components/Pins.tsx
|
|
6991
|
+
import { useEffect as useEffect14, useMemo as useMemo4, useRef as useRef14, useState as useState12 } from "react";
|
|
6992
|
+
import { Fragment as Fragment9, jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
7418
6993
|
var STATUS_LABELS = {
|
|
7419
6994
|
open: "open",
|
|
7420
6995
|
accepted: "accepted",
|
|
@@ -7426,22 +7001,22 @@ var RERESOLVE_MS = 800;
|
|
|
7426
7001
|
function Pins() {
|
|
7427
7002
|
const { session, route, activeItemId, editor, mode, filter } = useStore();
|
|
7428
7003
|
const dispatch = useDispatch();
|
|
7429
|
-
const [clusters, setClusters] =
|
|
7430
|
-
const [orphanCount, setOrphanCount] =
|
|
7431
|
-
const wrapRefs =
|
|
7432
|
-
const visibleCache =
|
|
7433
|
-
const highlightRef =
|
|
7434
|
-
const hoveredItems =
|
|
7435
|
-
const elementCache =
|
|
7436
|
-
const lastResolve =
|
|
7437
|
-
const [newestId, setNewestId] =
|
|
7438
|
-
const prevCount =
|
|
7439
|
-
const items =
|
|
7004
|
+
const [clusters, setClusters] = useState12([]);
|
|
7005
|
+
const [orphanCount, setOrphanCount] = useState12(0);
|
|
7006
|
+
const wrapRefs = useRef14(/* @__PURE__ */ new Map());
|
|
7007
|
+
const visibleCache = useRef14(/* @__PURE__ */ new Map());
|
|
7008
|
+
const highlightRef = useRef14(null);
|
|
7009
|
+
const hoveredItems = useRef14(null);
|
|
7010
|
+
const elementCache = useRef14(/* @__PURE__ */ new Map());
|
|
7011
|
+
const lastResolve = useRef14(0);
|
|
7012
|
+
const [newestId, setNewestId] = useState12(null);
|
|
7013
|
+
const prevCount = useRef14(0);
|
|
7014
|
+
const items = useMemo4(() => {
|
|
7440
7015
|
const all = session?.items ?? [];
|
|
7441
7016
|
return all.map((item, index) => ({ item, number: index + 1 })).filter(({ item }) => item.route === route);
|
|
7442
7017
|
}, [session, route]);
|
|
7443
7018
|
const byId = new Map(items.map(({ item }) => [item.id, item]));
|
|
7444
|
-
|
|
7019
|
+
useEffect14(() => {
|
|
7445
7020
|
const count = session?.items.length ?? 0;
|
|
7446
7021
|
if (count > prevCount.current && session && count > 0) {
|
|
7447
7022
|
const id = session.items[count - 1].id;
|
|
@@ -7452,7 +7027,7 @@ function Pins() {
|
|
|
7452
7027
|
}
|
|
7453
7028
|
prevCount.current = count;
|
|
7454
7029
|
}, [session]);
|
|
7455
|
-
|
|
7030
|
+
useEffect14(() => {
|
|
7456
7031
|
let raf = 0;
|
|
7457
7032
|
let lastSignature = "";
|
|
7458
7033
|
const tick = (time) => {
|
|
@@ -7536,8 +7111,8 @@ function Pins() {
|
|
|
7536
7111
|
dispatch({ type: "SET_ACTIVE_ITEM", id });
|
|
7537
7112
|
dispatch({ type: "SET_PANEL", open: true });
|
|
7538
7113
|
};
|
|
7539
|
-
return /* @__PURE__ */
|
|
7540
|
-
/* @__PURE__ */
|
|
7114
|
+
return /* @__PURE__ */ jsxs15(Fragment9, { children: [
|
|
7115
|
+
/* @__PURE__ */ jsx16("div", { ref: highlightRef, className: "rk-hl-ring", style: { opacity: 0 } }),
|
|
7541
7116
|
clusters.map((cluster) => {
|
|
7542
7117
|
const isCluster = cluster.ids.length > 1;
|
|
7543
7118
|
const isActive = activeItemId !== null && cluster.ids.includes(activeItemId);
|
|
@@ -7547,7 +7122,7 @@ function Pins() {
|
|
|
7547
7122
|
const status = statuses.size === 1 ? members[0]?.status : void 0;
|
|
7548
7123
|
const dimmed = filter !== null && members.length > 0 && !members.some((item) => itemMatchesFilter(item, filter));
|
|
7549
7124
|
const statusHint = isCluster ? status ? ` \xB7 all ${STATUS_LABELS[status] ?? status}` : "" : ` \xB7 ${STATUS_LABELS[members[0]?.status ?? "open"] ?? members[0]?.status}`;
|
|
7550
|
-
return /* @__PURE__ */
|
|
7125
|
+
return /* @__PURE__ */ jsx16(
|
|
7551
7126
|
"div",
|
|
7552
7127
|
{
|
|
7553
7128
|
ref: (el) => {
|
|
@@ -7555,7 +7130,7 @@ function Pins() {
|
|
|
7555
7130
|
else wrapRefs.current.delete(cluster.key);
|
|
7556
7131
|
},
|
|
7557
7132
|
className: `rk-pin-wrap${picking ? " rk-pin-ghost" : ""}`,
|
|
7558
|
-
children: /* @__PURE__ */
|
|
7133
|
+
children: /* @__PURE__ */ jsx16(
|
|
7559
7134
|
"button",
|
|
7560
7135
|
{
|
|
7561
7136
|
type: "button",
|
|
@@ -7577,7 +7152,7 @@ function Pins() {
|
|
|
7577
7152
|
cluster.key
|
|
7578
7153
|
);
|
|
7579
7154
|
}),
|
|
7580
|
-
orphanCount > 0 && /* @__PURE__ */
|
|
7155
|
+
orphanCount > 0 && /* @__PURE__ */ jsxs15(
|
|
7581
7156
|
"button",
|
|
7582
7157
|
{
|
|
7583
7158
|
type: "button",
|
|
@@ -7585,7 +7160,7 @@ function Pins() {
|
|
|
7585
7160
|
style: { bottom: 16, left: "50%", transform: "translateX(-50%)" },
|
|
7586
7161
|
onClick: () => dispatch({ type: "SET_PANEL", open: true }),
|
|
7587
7162
|
children: [
|
|
7588
|
-
/* @__PURE__ */
|
|
7163
|
+
/* @__PURE__ */ jsx16(IconUnlink, { size: 13 }),
|
|
7589
7164
|
orphanCount,
|
|
7590
7165
|
" unanchored item",
|
|
7591
7166
|
orphanCount === 1 ? "" : "s"
|
|
@@ -7594,11 +7169,15 @@ function Pins() {
|
|
|
7594
7169
|
)
|
|
7595
7170
|
] });
|
|
7596
7171
|
}
|
|
7172
|
+
|
|
7173
|
+
// src/client/components/Toolbar.tsx
|
|
7174
|
+
import { useEffect as useEffect15, useLayoutEffect as useLayoutEffect3, useRef as useRef15, useState as useState13 } from "react";
|
|
7175
|
+
import { Fragment as Fragment10, jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
7597
7176
|
var TOOLS = [
|
|
7598
|
-
{ tool: "select", hintId: "tool-select", label: "Select", icon: (n) => /* @__PURE__ */
|
|
7599
|
-
{ tool: "copy", hintId: "tool-copy", label: "Rewrite text", icon: (n) => /* @__PURE__ */
|
|
7600
|
-
{ tool: "comment", hintId: "tool-comment", label: "Comment", icon: (n) => /* @__PURE__ */
|
|
7601
|
-
{ tool: "image", hintId: "tool-image", label: "Replace image", icon: (n) => /* @__PURE__ */
|
|
7177
|
+
{ tool: "select", hintId: "tool-select", label: "Select", icon: (n) => /* @__PURE__ */ jsx17(IconTarget, { size: n }) },
|
|
7178
|
+
{ tool: "copy", hintId: "tool-copy", label: "Rewrite text", icon: (n) => /* @__PURE__ */ jsx17(IconText, { size: n }) },
|
|
7179
|
+
{ tool: "comment", hintId: "tool-comment", label: "Comment", icon: (n) => /* @__PURE__ */ jsx17(IconComment, { size: n }) },
|
|
7180
|
+
{ tool: "image", hintId: "tool-image", label: "Replace image", icon: (n) => /* @__PURE__ */ jsx17(IconImage, { size: n }) }
|
|
7602
7181
|
];
|
|
7603
7182
|
var POS_KEY2 = "review-kit:toolbar-pos";
|
|
7604
7183
|
var DRAG_THRESHOLD2 = 6;
|
|
@@ -7606,30 +7185,30 @@ function Toolbar() {
|
|
|
7606
7185
|
const { selection, editor, peers, syncStatus, mode, tool } = useStore();
|
|
7607
7186
|
const hasPeers = syncStatus !== "disabled" && peers.length > 0;
|
|
7608
7187
|
const dispatch = useDispatch();
|
|
7609
|
-
const ref =
|
|
7610
|
-
const [pos, setPos] =
|
|
7611
|
-
const drag =
|
|
7612
|
-
const [dragging, setDragging] =
|
|
7613
|
-
const justDragged =
|
|
7188
|
+
const ref = useRef15(null);
|
|
7189
|
+
const [pos, setPos] = useState13(() => readStoredPos(POS_KEY2));
|
|
7190
|
+
const drag = useRef15(null);
|
|
7191
|
+
const [dragging, setDragging] = useState13(false);
|
|
7192
|
+
const justDragged = useRef15(false);
|
|
7614
7193
|
const visible = editor === null || selection !== null;
|
|
7615
7194
|
const applyPos = (next, persist) => {
|
|
7616
7195
|
if (next === null && ref.current) ref.current.style.bottom = "";
|
|
7617
7196
|
setPos(next);
|
|
7618
|
-
storePos(POS_KEY2, next);
|
|
7197
|
+
if (persist) storePos(POS_KEY2, next);
|
|
7619
7198
|
};
|
|
7620
|
-
|
|
7199
|
+
useLayoutEffect3(() => {
|
|
7621
7200
|
const el = ref.current;
|
|
7622
7201
|
if (!el || pos === null) return;
|
|
7623
7202
|
const clamped = clampPos(pos.x, pos.y, el.offsetWidth, el.offsetHeight);
|
|
7624
|
-
if (clamped.x !== pos.x || clamped.y !== pos.y) applyPos(clamped);
|
|
7203
|
+
if (clamped.x !== pos.x || clamped.y !== pos.y) applyPos(clamped, true);
|
|
7625
7204
|
}, [pos, selection, hasPeers, visible]);
|
|
7626
|
-
|
|
7205
|
+
useEffect15(() => {
|
|
7627
7206
|
const onResize = () => {
|
|
7628
7207
|
const el = ref.current;
|
|
7629
7208
|
const current = readStoredPos(POS_KEY2);
|
|
7630
7209
|
if (!el || !current) return;
|
|
7631
7210
|
const clamped = clampPos(current.x, current.y, el.offsetWidth, el.offsetHeight);
|
|
7632
|
-
if (clamped.x !== current.x || clamped.y !== current.y) applyPos(clamped);
|
|
7211
|
+
if (clamped.x !== current.x || clamped.y !== current.y) applyPos(clamped, true);
|
|
7633
7212
|
};
|
|
7634
7213
|
window.addEventListener("resize", onResize);
|
|
7635
7214
|
return () => window.removeEventListener("resize", onResize);
|
|
@@ -7694,7 +7273,7 @@ function Toolbar() {
|
|
|
7694
7273
|
node.style.left = "0px";
|
|
7695
7274
|
node.style.top = "0px";
|
|
7696
7275
|
node.style.translate = `${snapped.x}px ${snapped.y}px`;
|
|
7697
|
-
applyPos(snapped);
|
|
7276
|
+
applyPos(snapped, true);
|
|
7698
7277
|
};
|
|
7699
7278
|
window.addEventListener("pointermove", onMove, { passive: false });
|
|
7700
7279
|
window.addEventListener("pointerup", onUp);
|
|
@@ -7721,7 +7300,7 @@ function Toolbar() {
|
|
|
7721
7300
|
else if (event.key === "ArrowDown") dy = stepSize;
|
|
7722
7301
|
else return;
|
|
7723
7302
|
event.preventDefault();
|
|
7724
|
-
applyPos(clampPos(rect.left + dx, rect.top + dy, el.offsetWidth, el.offsetHeight));
|
|
7303
|
+
applyPos(clampPos(rect.left + dx, rect.top + dy, el.offsetWidth, el.offsetHeight), true);
|
|
7725
7304
|
};
|
|
7726
7305
|
const open = (kind) => {
|
|
7727
7306
|
if (!selection) return;
|
|
@@ -7736,7 +7315,7 @@ function Toolbar() {
|
|
|
7736
7315
|
mode === "pick" && selection === null ? "rk-ghost" : ""
|
|
7737
7316
|
].filter(Boolean).join(" ");
|
|
7738
7317
|
const style = pos !== null ? { left: 0, top: 0, translate: `${pos.x}px ${pos.y}px` } : void 0;
|
|
7739
|
-
return /* @__PURE__ */
|
|
7318
|
+
return /* @__PURE__ */ jsxs16(
|
|
7740
7319
|
"div",
|
|
7741
7320
|
{
|
|
7742
7321
|
ref,
|
|
@@ -7747,27 +7326,27 @@ function Toolbar() {
|
|
|
7747
7326
|
onPointerDown,
|
|
7748
7327
|
onClickCapture,
|
|
7749
7328
|
children: [
|
|
7750
|
-
/* @__PURE__ */
|
|
7329
|
+
/* @__PURE__ */ jsx17(
|
|
7751
7330
|
"button",
|
|
7752
7331
|
{
|
|
7753
7332
|
type: "button",
|
|
7754
7333
|
className: "rk-toolbar-grip",
|
|
7755
7334
|
"aria-label": "Move the toolbar \u2014 drag, or use arrow keys; double-click to reset its position",
|
|
7756
7335
|
onKeyDown: onGripKeyDown,
|
|
7757
|
-
onDoubleClick: () => applyPos(null),
|
|
7758
|
-
children: /* @__PURE__ */
|
|
7759
|
-
/* @__PURE__ */
|
|
7760
|
-
/* @__PURE__ */
|
|
7761
|
-
/* @__PURE__ */
|
|
7762
|
-
/* @__PURE__ */
|
|
7763
|
-
/* @__PURE__ */
|
|
7764
|
-
/* @__PURE__ */
|
|
7336
|
+
onDoubleClick: () => applyPos(null, true),
|
|
7337
|
+
children: /* @__PURE__ */ jsxs16("svg", { width: "8", height: "14", viewBox: "0 0 8 14", "aria-hidden": "true", fill: "currentColor", children: [
|
|
7338
|
+
/* @__PURE__ */ jsx17("circle", { cx: "2", cy: "2", r: "1.1" }),
|
|
7339
|
+
/* @__PURE__ */ jsx17("circle", { cx: "6", cy: "2", r: "1.1" }),
|
|
7340
|
+
/* @__PURE__ */ jsx17("circle", { cx: "2", cy: "7", r: "1.1" }),
|
|
7341
|
+
/* @__PURE__ */ jsx17("circle", { cx: "6", cy: "7", r: "1.1" }),
|
|
7342
|
+
/* @__PURE__ */ jsx17("circle", { cx: "2", cy: "12", r: "1.1" }),
|
|
7343
|
+
/* @__PURE__ */ jsx17("circle", { cx: "6", cy: "12", r: "1.1" })
|
|
7765
7344
|
] })
|
|
7766
7345
|
}
|
|
7767
7346
|
),
|
|
7768
|
-
/* @__PURE__ */
|
|
7769
|
-
hasPeers && /* @__PURE__ */
|
|
7770
|
-
/* @__PURE__ */
|
|
7347
|
+
/* @__PURE__ */ jsx17(PresenceStrip, {}),
|
|
7348
|
+
hasPeers && /* @__PURE__ */ jsx17("span", { className: "rk-toolbar-sep" }),
|
|
7349
|
+
/* @__PURE__ */ jsx17("div", { className: "rk-seg rk-tool-seg", role: "group", "aria-label": "Tools", children: TOOLS.map((entry) => /* @__PURE__ */ jsx17(
|
|
7771
7350
|
"button",
|
|
7772
7351
|
{
|
|
7773
7352
|
type: "button",
|
|
@@ -7779,9 +7358,9 @@ function Toolbar() {
|
|
|
7779
7358
|
},
|
|
7780
7359
|
entry.tool
|
|
7781
7360
|
)) }),
|
|
7782
|
-
selection && /* @__PURE__ */
|
|
7783
|
-
selection && /* @__PURE__ */
|
|
7784
|
-
/* @__PURE__ */
|
|
7361
|
+
selection && /* @__PURE__ */ jsx17("span", { className: "rk-toolbar-sep" }),
|
|
7362
|
+
selection && /* @__PURE__ */ jsxs16(Fragment10, { children: [
|
|
7363
|
+
/* @__PURE__ */ jsxs16(
|
|
7785
7364
|
"button",
|
|
7786
7365
|
{
|
|
7787
7366
|
type: "button",
|
|
@@ -7790,12 +7369,12 @@ function Toolbar() {
|
|
|
7790
7369
|
title: `Rewrite text${keyHint("tool-copy")}`,
|
|
7791
7370
|
onClick: () => open("copy"),
|
|
7792
7371
|
children: [
|
|
7793
|
-
/* @__PURE__ */
|
|
7372
|
+
/* @__PURE__ */ jsx17(IconText, { size: 14 }),
|
|
7794
7373
|
" Rewrite"
|
|
7795
7374
|
]
|
|
7796
7375
|
}
|
|
7797
7376
|
),
|
|
7798
|
-
hasImage && /* @__PURE__ */
|
|
7377
|
+
hasImage && /* @__PURE__ */ jsxs16(
|
|
7799
7378
|
"button",
|
|
7800
7379
|
{
|
|
7801
7380
|
type: "button",
|
|
@@ -7804,12 +7383,12 @@ function Toolbar() {
|
|
|
7804
7383
|
title: `Replace image${keyHint("tool-image")}`,
|
|
7805
7384
|
onClick: () => open("image"),
|
|
7806
7385
|
children: [
|
|
7807
|
-
/* @__PURE__ */
|
|
7386
|
+
/* @__PURE__ */ jsx17(IconImage, { size: 14 }),
|
|
7808
7387
|
" Image"
|
|
7809
7388
|
]
|
|
7810
7389
|
}
|
|
7811
7390
|
),
|
|
7812
|
-
/* @__PURE__ */
|
|
7391
|
+
/* @__PURE__ */ jsxs16(
|
|
7813
7392
|
"button",
|
|
7814
7393
|
{
|
|
7815
7394
|
type: "button",
|
|
@@ -7818,32 +7397,32 @@ function Toolbar() {
|
|
|
7818
7397
|
title: `Comment${keyHint("tool-comment")}`,
|
|
7819
7398
|
onClick: () => open("comment"),
|
|
7820
7399
|
children: [
|
|
7821
|
-
/* @__PURE__ */
|
|
7400
|
+
/* @__PURE__ */ jsx17(IconComment, { size: 14 }),
|
|
7822
7401
|
" Comment"
|
|
7823
7402
|
]
|
|
7824
7403
|
}
|
|
7825
7404
|
),
|
|
7826
|
-
/* @__PURE__ */
|
|
7827
|
-
/* @__PURE__ */
|
|
7405
|
+
/* @__PURE__ */ jsxs16("button", { type: "button", role: "menuitem", className: "rk-toolbar-btn", onClick: () => open("style"), children: [
|
|
7406
|
+
/* @__PURE__ */ jsx17(IconStyle, { size: 14 }),
|
|
7828
7407
|
" Style"
|
|
7829
7408
|
] }),
|
|
7830
|
-
/* @__PURE__ */
|
|
7831
|
-
/* @__PURE__ */
|
|
7409
|
+
/* @__PURE__ */ jsxs16("button", { type: "button", role: "menuitem", className: "rk-toolbar-btn", onClick: () => open("move"), children: [
|
|
7410
|
+
/* @__PURE__ */ jsx17(IconMove, { size: 14 }),
|
|
7832
7411
|
" Move"
|
|
7833
7412
|
] }),
|
|
7834
|
-
/* @__PURE__ */
|
|
7835
|
-
/* @__PURE__ */
|
|
7413
|
+
/* @__PURE__ */ jsxs16("button", { type: "button", role: "menuitem", className: "rk-toolbar-btn rk-danger", onClick: () => open("delete"), children: [
|
|
7414
|
+
/* @__PURE__ */ jsx17(IconTrash, { size: 14 }),
|
|
7836
7415
|
" Delete"
|
|
7837
7416
|
] }),
|
|
7838
|
-
/* @__PURE__ */
|
|
7839
|
-
/* @__PURE__ */
|
|
7417
|
+
/* @__PURE__ */ jsx17("span", { className: "rk-toolbar-sep" }),
|
|
7418
|
+
/* @__PURE__ */ jsx17(
|
|
7840
7419
|
"button",
|
|
7841
7420
|
{
|
|
7842
7421
|
type: "button",
|
|
7843
7422
|
className: "rk-icon-btn",
|
|
7844
7423
|
"aria-label": "Deselect",
|
|
7845
7424
|
onClick: () => dispatch({ type: "SELECT", selection: null }),
|
|
7846
|
-
children: /* @__PURE__ */
|
|
7425
|
+
children: /* @__PURE__ */ jsx17(IconClose, { size: 13 })
|
|
7847
7426
|
}
|
|
7848
7427
|
)
|
|
7849
7428
|
] })
|
|
@@ -7851,32 +7430,42 @@ function Toolbar() {
|
|
|
7851
7430
|
}
|
|
7852
7431
|
);
|
|
7853
7432
|
}
|
|
7433
|
+
|
|
7434
|
+
// src/client/components/Toast.tsx
|
|
7435
|
+
import { useEffect as useEffect16 } from "react";
|
|
7436
|
+
import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
7854
7437
|
function ToastRow({ toast: toast2 }) {
|
|
7855
7438
|
const dispatch = useDispatch();
|
|
7856
|
-
|
|
7439
|
+
useEffect16(() => {
|
|
7857
7440
|
const timer = window.setTimeout(() => dispatch({ type: "DISMISS_TOAST", id: toast2.id }), 3500);
|
|
7858
7441
|
return () => window.clearTimeout(timer);
|
|
7859
7442
|
}, [toast2.id, dispatch]);
|
|
7860
|
-
return /* @__PURE__ */
|
|
7861
|
-
toast2.tone === "success" ? /* @__PURE__ */
|
|
7443
|
+
return /* @__PURE__ */ jsxs17("div", { className: `rk-toast rk-${toast2.tone}`, role: "status", children: [
|
|
7444
|
+
toast2.tone === "success" ? /* @__PURE__ */ jsx18(IconCheck, { size: 13 }) : toast2.tone === "error" ? /* @__PURE__ */ jsx18(IconWarning, { size: 13 }) : /* @__PURE__ */ jsx18(IconComment, { size: 13 }),
|
|
7862
7445
|
toast2.message
|
|
7863
7446
|
] });
|
|
7864
7447
|
}
|
|
7865
7448
|
function ToastHost() {
|
|
7866
7449
|
const { toasts } = useStore();
|
|
7867
7450
|
if (toasts.length === 0) return null;
|
|
7868
|
-
return /* @__PURE__ */
|
|
7451
|
+
return /* @__PURE__ */ jsx18("div", { className: "rk-toasts", "aria-live": "polite", children: toasts.map((toast2) => /* @__PURE__ */ jsx18(ToastRow, { toast: toast2 }, toast2.id)) });
|
|
7869
7452
|
}
|
|
7453
|
+
|
|
7454
|
+
// src/client/App.tsx
|
|
7455
|
+
import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
7870
7456
|
function App() {
|
|
7871
7457
|
const state = useStore();
|
|
7872
7458
|
const rawDispatch = useDispatch();
|
|
7873
7459
|
const config = useConfig();
|
|
7874
7460
|
const dispatch = useRealtimeSync(state, rawDispatch, config, reducer);
|
|
7875
|
-
const saveTimer =
|
|
7461
|
+
const saveTimer = useRef16(null);
|
|
7876
7462
|
const storageKey = config.storageKey ?? defaultStorageKey();
|
|
7877
7463
|
useAppliedPreview(state, dispatch);
|
|
7878
7464
|
useEmblemaAutoPush(state, dispatch, config);
|
|
7879
|
-
|
|
7465
|
+
useEffect17(() => {
|
|
7466
|
+
setEffectAssetsUrl(config.fxAssetsUrl);
|
|
7467
|
+
}, [config.fxAssetsUrl]);
|
|
7468
|
+
useEffect17(() => {
|
|
7880
7469
|
let cancelled = false;
|
|
7881
7470
|
void loadSession(storageKey).then((stored) => {
|
|
7882
7471
|
if (cancelled) return;
|
|
@@ -7894,7 +7483,7 @@ function App() {
|
|
|
7894
7483
|
};
|
|
7895
7484
|
}, [storageKey, config.defaultAuthor, dispatch]);
|
|
7896
7485
|
const { session } = state;
|
|
7897
|
-
|
|
7486
|
+
useEffect17(() => {
|
|
7898
7487
|
if (!session) return;
|
|
7899
7488
|
if (saveTimer.current !== null) window.clearTimeout(saveTimer.current);
|
|
7900
7489
|
saveTimer.current = window.setTimeout(() => {
|
|
@@ -7905,9 +7494,9 @@ function App() {
|
|
|
7905
7494
|
if (saveTimer.current !== null) window.clearTimeout(saveTimer.current);
|
|
7906
7495
|
};
|
|
7907
7496
|
}, [session, storageKey, config]);
|
|
7908
|
-
|
|
7909
|
-
const focusHandled =
|
|
7910
|
-
|
|
7497
|
+
useEffect17(() => trackPointer(), []);
|
|
7498
|
+
const focusHandled = useRef16(false);
|
|
7499
|
+
useEffect17(() => {
|
|
7911
7500
|
if (!session || focusHandled.current) return;
|
|
7912
7501
|
focusHandled.current = true;
|
|
7913
7502
|
const id = takeFocusItem();
|
|
@@ -7932,7 +7521,7 @@ function App() {
|
|
|
7932
7521
|
cancelled = true;
|
|
7933
7522
|
};
|
|
7934
7523
|
}, [session, dispatch]);
|
|
7935
|
-
|
|
7524
|
+
useEffect17(() => {
|
|
7936
7525
|
let last = window.location.pathname;
|
|
7937
7526
|
const check = () => {
|
|
7938
7527
|
if (window.location.pathname !== last) {
|
|
@@ -7947,9 +7536,9 @@ function App() {
|
|
|
7947
7536
|
window.removeEventListener("popstate", check);
|
|
7948
7537
|
};
|
|
7949
7538
|
}, [dispatch]);
|
|
7950
|
-
const stateRef =
|
|
7539
|
+
const stateRef = useRef16(state);
|
|
7951
7540
|
stateRef.current = state;
|
|
7952
|
-
|
|
7541
|
+
useEffect17(() => {
|
|
7953
7542
|
const onKeyDown = (event) => {
|
|
7954
7543
|
const current = stateRef.current;
|
|
7955
7544
|
for (const def of SHORTCUTS) {
|
|
@@ -7964,7 +7553,7 @@ function App() {
|
|
|
7964
7553
|
document.addEventListener("keydown", onKeyDown);
|
|
7965
7554
|
return () => document.removeEventListener("keydown", onKeyDown);
|
|
7966
7555
|
}, [dispatch]);
|
|
7967
|
-
|
|
7556
|
+
useEffect17(() => {
|
|
7968
7557
|
if (!state.editor) return;
|
|
7969
7558
|
const editorEl = state.editor.element;
|
|
7970
7559
|
const onPointerDown = (event) => {
|
|
@@ -7977,29 +7566,33 @@ function App() {
|
|
|
7977
7566
|
}, [state.editor, dispatch]);
|
|
7978
7567
|
if (!session) return null;
|
|
7979
7568
|
if (state.hidden) {
|
|
7980
|
-
return /* @__PURE__ */
|
|
7569
|
+
return /* @__PURE__ */ jsx19(DispatchContext.Provider, { value: dispatch, children: null });
|
|
7981
7570
|
}
|
|
7982
|
-
return /* @__PURE__ */
|
|
7983
|
-
/* @__PURE__ */
|
|
7984
|
-
/* @__PURE__ */
|
|
7985
|
-
/* @__PURE__ */
|
|
7986
|
-
state.editor?.kind === "copy" && /* @__PURE__ */
|
|
7987
|
-
state.editor?.kind === "image" && /* @__PURE__ */
|
|
7988
|
-
state.editor && state.editor.kind !== "copy" && state.editor.kind !== "image" && /* @__PURE__ */
|
|
7989
|
-
/* @__PURE__ */
|
|
7990
|
-
/* @__PURE__ */
|
|
7991
|
-
/* @__PURE__ */
|
|
7992
|
-
/* @__PURE__ */
|
|
7993
|
-
/* @__PURE__ */
|
|
7994
|
-
/* @__PURE__ */
|
|
7995
|
-
/* @__PURE__ */
|
|
7996
|
-
/* @__PURE__ */
|
|
7997
|
-
/* @__PURE__ */
|
|
7571
|
+
return /* @__PURE__ */ jsxs18(DispatchContext.Provider, { value: dispatch, children: [
|
|
7572
|
+
/* @__PURE__ */ jsx19(PickLayer, {}),
|
|
7573
|
+
/* @__PURE__ */ jsx19(PeerCursors, {}),
|
|
7574
|
+
/* @__PURE__ */ jsx19(Toolbar, {}),
|
|
7575
|
+
state.editor?.kind === "copy" && /* @__PURE__ */ jsx19(InlineEditor, { editor: state.editor }),
|
|
7576
|
+
state.editor?.kind === "image" && /* @__PURE__ */ jsx19(ImageEditor, { editor: state.editor }),
|
|
7577
|
+
state.editor && state.editor.kind !== "copy" && state.editor.kind !== "image" && /* @__PURE__ */ jsx19(NoteComposer, { editor: state.editor }),
|
|
7578
|
+
/* @__PURE__ */ jsx19(Pins, {}),
|
|
7579
|
+
/* @__PURE__ */ jsx19(QuickComment, {}),
|
|
7580
|
+
/* @__PURE__ */ jsx19(Panel, {}),
|
|
7581
|
+
/* @__PURE__ */ jsx19(Badge, {}),
|
|
7582
|
+
/* @__PURE__ */ jsx19(CoachMark, {}),
|
|
7583
|
+
/* @__PURE__ */ jsx19(CheatSheet, {}),
|
|
7584
|
+
/* @__PURE__ */ jsx19(EmblemaConnect, {}),
|
|
7585
|
+
/* @__PURE__ */ jsx19(TerminalConnect, {}),
|
|
7586
|
+
/* @__PURE__ */ jsx19(ConfirmHost, {}),
|
|
7587
|
+
/* @__PURE__ */ jsx19(ToastHost, {})
|
|
7998
7588
|
] });
|
|
7999
7589
|
}
|
|
7590
|
+
|
|
7591
|
+
// src/client/ReviewKit.tsx
|
|
7592
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
8000
7593
|
function ShadowHost({ config }) {
|
|
8001
|
-
const [mount, setMount] =
|
|
8002
|
-
|
|
7594
|
+
const [mount, setMount] = useState14(null);
|
|
7595
|
+
useEffect18(() => {
|
|
8003
7596
|
const host = document.createElement("div");
|
|
8004
7597
|
host.setAttribute(HOST_ATTR, "");
|
|
8005
7598
|
host.style.position = "fixed";
|
|
@@ -8035,23 +7628,36 @@ function ShadowHost({ config }) {
|
|
|
8035
7628
|
}, []);
|
|
8036
7629
|
if (!mount) return null;
|
|
8037
7630
|
return createPortal(
|
|
8038
|
-
/* @__PURE__ */
|
|
7631
|
+
/* @__PURE__ */ jsx20(StoreProvider, { config, children: /* @__PURE__ */ jsx20(App, {}) }),
|
|
8039
7632
|
mount
|
|
8040
7633
|
);
|
|
8041
7634
|
}
|
|
8042
7635
|
function ReviewKit(props) {
|
|
8043
|
-
const [
|
|
8044
|
-
|
|
8045
|
-
|
|
8046
|
-
|
|
7636
|
+
const [active, setActive] = useState14(false);
|
|
7637
|
+
const { enabled, token, allowedHosts, devAutoOn } = props;
|
|
7638
|
+
const hostsKey = allowedHosts?.join("\0") ?? "";
|
|
7639
|
+
useEffect18(() => {
|
|
7640
|
+
if (enabled === false) {
|
|
7641
|
+
setActive(false);
|
|
7642
|
+
return;
|
|
7643
|
+
}
|
|
7644
|
+
setActive(resolveActivation({ token, allowedHosts, devAutoOn, enabled }));
|
|
8047
7645
|
const onDeactivate = () => setActive(false);
|
|
8048
7646
|
window.addEventListener(DEACTIVATE_EVENT, onDeactivate);
|
|
8049
7647
|
return () => window.removeEventListener(DEACTIVATE_EVENT, onDeactivate);
|
|
8050
|
-
}, [
|
|
8051
|
-
if (!
|
|
8052
|
-
return /* @__PURE__ */
|
|
7648
|
+
}, [enabled, token, devAutoOn, hostsKey]);
|
|
7649
|
+
if (enabled === false || !active) return null;
|
|
7650
|
+
return /* @__PURE__ */ jsx20(ShadowHost, { config: props });
|
|
8053
7651
|
}
|
|
8054
7652
|
|
|
8055
|
-
export {
|
|
8056
|
-
|
|
8057
|
-
|
|
7653
|
+
export {
|
|
7654
|
+
captureTarget,
|
|
7655
|
+
resolveTarget,
|
|
7656
|
+
exportFilename,
|
|
7657
|
+
sessionToJson,
|
|
7658
|
+
downloadSession,
|
|
7659
|
+
copySessionToClipboard,
|
|
7660
|
+
importSessionFile,
|
|
7661
|
+
ReviewKit
|
|
7662
|
+
};
|
|
7663
|
+
//# sourceMappingURL=chunk-5MAFDRUI.js.map
|