@designfever/web-review-kit 0.2.0 → 0.3.0

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.
@@ -39,7 +39,7 @@ __export(react_shell_exports, {
39
39
  mountReviewShell: () => mountReviewShell
40
40
  });
41
41
  module.exports = __toCommonJS(react_shell_exports);
42
- var import_react17 = __toESM(require("react"), 1);
42
+ var import_react18 = __toESM(require("react"), 1);
43
43
  var import_client = require("react-dom/client");
44
44
 
45
45
  // src/react-shell/style.ts
@@ -161,17 +161,20 @@ function ensureReviewShellStyle() {
161
161
  --df-review-color-scrollbar-border: rgba(15, 18, 24, 0.92);
162
162
  --df-review-color-backdrop: rgba(2, 6, 12, 0.62);
163
163
  --df-review-color-ruler-surface: transparent;
164
- --df-review-color-ruler-label: transparent;
165
- --df-review-color-ruler-label-text: #e1d8ff;
166
- --df-review-color-ruler-tick-major: rgba(179, 149, 255, 0.75);
164
+ --df-review-color-ruler-label: rgba(15, 18, 24, 0.9);
165
+ --df-review-color-ruler-label-text: #f4efff;
166
+ --df-review-color-ruler-tick-major: rgba(201, 184, 255, 0.9);
167
167
  --df-review-color-ruler-tick-minor: rgba(237, 243, 251, 0.2);
168
- --df-review-color-ruler-guide: rgba(255, 255, 255, 0.74);
168
+ --df-review-color-ruler-guide: rgba(255, 255, 255, 0.86);
169
169
  --df-review-color-ruler-measure-border: #c9b8ff;
170
- --df-review-color-ruler-measure-bg: rgba(179, 149, 255, 0.16);
171
- --df-review-color-ruler-measure-shadow: rgba(20, 12, 40, 0.38);
172
- --df-review-color-ruler-popover-border: rgba(237, 243, 251, 0.22);
173
- --df-review-color-ruler-popover-bg: transparent;
174
- --df-review-color-ruler-popover-shadow: transparent;
170
+ --df-review-color-ruler-measure-bg: rgba(179, 149, 255, 0.18);
171
+ --df-review-color-ruler-measure-shadow: rgba(20, 12, 40, 0.52);
172
+ --df-review-color-ruler-popover-border: rgba(255, 255, 255, 0.34);
173
+ --df-review-color-ruler-popover-bg: rgba(15, 18, 24, 0.94);
174
+ --df-review-color-ruler-popover-text: #ffffff;
175
+ --df-review-color-ruler-popover-shadow: rgba(0, 0, 0, 0.42);
176
+ --df-review-color-ruler-coord-bg: #d7c9ff;
177
+ --df-review-color-ruler-coord-text: #14111f;
175
178
  --df-review-focus-ring: rgba(124, 199, 255, 0.58);
176
179
  --df-review-shadow-card: 0 14px 36px rgba(0, 0, 0, 0.34);
177
180
  --df-review-shadow-control: inset 0 1px 0 rgba(255, 255, 255, 0.04);
@@ -253,17 +256,20 @@ function ensureReviewShellStyle() {
253
256
  --df-review-color-scrollbar-border: rgba(244, 246, 249, 0.92);
254
257
  --df-review-color-backdrop: rgba(15, 23, 42, 0.32);
255
258
  --df-review-color-ruler-surface: transparent;
256
- --df-review-color-ruler-label: transparent;
257
- --df-review-color-ruler-label-text: #6543b8;
258
- --df-review-color-ruler-tick-major: rgba(101, 67, 184, 0.58);
259
- --df-review-color-ruler-tick-minor: rgba(23, 32, 44, 0.24);
260
- --df-review-color-ruler-guide: rgba(101, 67, 184, 0.58);
261
- --df-review-color-ruler-measure-border: #6543b8;
262
- --df-review-color-ruler-measure-bg: rgba(101, 67, 184, 0.1);
263
- --df-review-color-ruler-measure-shadow: rgba(101, 67, 184, 0.22);
264
- --df-review-color-ruler-popover-border: rgba(23, 32, 44, 0.16);
265
- --df-review-color-ruler-popover-bg: transparent;
266
- --df-review-color-ruler-popover-shadow: transparent;
259
+ --df-review-color-ruler-label: rgba(255, 255, 255, 0.94);
260
+ --df-review-color-ruler-label-text: #3b247e;
261
+ --df-review-color-ruler-tick-major: rgba(0, 95, 204, 0.92);
262
+ --df-review-color-ruler-tick-minor: rgba(23, 32, 44, 0.3);
263
+ --df-review-color-ruler-guide: rgba(0, 102, 255, 0.96);
264
+ --df-review-color-ruler-measure-border: #0066ff;
265
+ --df-review-color-ruler-measure-bg: rgba(0, 102, 255, 0.16);
266
+ --df-review-color-ruler-measure-shadow: rgba(0, 43, 120, 0.56);
267
+ --df-review-color-ruler-popover-border: rgba(255, 255, 255, 0.34);
268
+ --df-review-color-ruler-popover-bg: rgba(15, 18, 24, 0.94);
269
+ --df-review-color-ruler-popover-text: #ffffff;
270
+ --df-review-color-ruler-popover-shadow: rgba(0, 0, 0, 0.42);
271
+ --df-review-color-ruler-coord-bg: #005be8;
272
+ --df-review-color-ruler-coord-text: #ffffff;
267
273
  --df-review-focus-ring: rgba(23, 105, 170, 0.42);
268
274
  --df-review-shadow-card: 0 14px 36px rgba(15, 23, 42, 0.14);
269
275
  --df-review-shadow-control: inset 0 1px 0 rgba(255, 255, 255, 0.72);
@@ -374,6 +380,7 @@ function ensureReviewShellStyle() {
374
380
  .df-review-prompt-block-header button:hover,
375
381
  .df-review-item-actions button:hover,
376
382
  .df-review-item-visibility:hover,
383
+ .df-review-item-source-open:hover,
377
384
  .df-review-item-prompt-copy:hover,
378
385
  .df-review-item-delete:hover,
379
386
  .df-review-presets button.is-active,
@@ -937,6 +944,59 @@ function ensureReviewShellStyle() {
937
944
  color: var(--df-review-accent);
938
945
  }
939
946
 
947
+ .df-review-edit-modal {
948
+ position: fixed;
949
+ inset: 0;
950
+ z-index: 1003;
951
+ display: grid;
952
+ place-items: center;
953
+ padding: 24px;
954
+ }
955
+
956
+ .df-review-edit-dialog {
957
+ position: relative;
958
+ z-index: 1;
959
+ display: grid;
960
+ width: min(460px, calc(100vw - 48px));
961
+ overflow: hidden;
962
+ border: 1px solid var(--df-review-line);
963
+ border-radius: var(--df-review-radius-lg);
964
+ background: var(--df-review-panel);
965
+ box-shadow: var(--df-review-shadow-modal);
966
+ }
967
+
968
+ .df-review-edit-textarea {
969
+ min-height: 160px;
970
+ }
971
+
972
+ .df-review-edit-textarea textarea {
973
+ width: 100%;
974
+ min-height: 160px;
975
+ border: 0;
976
+ padding: 10px;
977
+ outline: 0;
978
+ background: transparent;
979
+ color: var(--df-review-text);
980
+ resize: vertical;
981
+ font-size: var(--df-review-font-size-md);
982
+ line-height: 1.5;
983
+ }
984
+
985
+ .df-review-edit-textarea textarea:focus {
986
+ outline: 0;
987
+ }
988
+
989
+ .df-review-edit-error {
990
+ margin: 0;
991
+ color: var(--df-review-danger);
992
+ font-size: var(--df-review-font-size-sm);
993
+ font-weight: 800;
994
+ }
995
+
996
+ .df-review-edit-actions {
997
+ grid-template-columns: minmax(0, 1fr) auto auto;
998
+ }
999
+
940
1000
  .df-review-prompt-modal {
941
1001
  position: fixed;
942
1002
  inset: 0;
@@ -1939,7 +1999,9 @@ function ensureReviewShellStyle() {
1939
1999
  }
1940
2000
 
1941
2001
  .df-review-item-delete,
2002
+ .df-review-item-edit,
1942
2003
  .df-review-item-prompt-copy,
2004
+ .df-review-item-source-open,
1943
2005
  .df-review-item-visibility {
1944
2006
  display: inline-grid;
1945
2007
  place-items: center;
@@ -1950,10 +2012,13 @@ function ensureReviewShellStyle() {
1950
2012
  padding: 0;
1951
2013
  color: var(--df-review-muted);
1952
2014
  background: transparent;
2015
+ text-decoration: none;
1953
2016
  transition: border-color 140ms ease, background 140ms ease, color 140ms ease;
1954
2017
  }
1955
2018
 
1956
2019
  .df-review-item-visibility:hover,
2020
+ .df-review-item-edit:hover,
2021
+ .df-review-item-source-open:hover,
1957
2022
  .df-review-item-prompt-copy:hover {
1958
2023
  border-color: rgba(124, 199, 255, 0.34);
1959
2024
  color: var(--df-review-accent);
@@ -1980,7 +2045,9 @@ function ensureReviewShellStyle() {
1980
2045
  }
1981
2046
 
1982
2047
  .df-review-item-delete svg,
2048
+ .df-review-item-edit svg,
1983
2049
  .df-review-item-prompt-copy svg,
2050
+ .df-review-item-source-open svg,
1984
2051
  .df-review-item-visibility svg {
1985
2052
  width: 14px;
1986
2053
  height: 14px;
@@ -2226,37 +2293,42 @@ function ensureReviewShellStyle() {
2226
2293
  display: flex;
2227
2294
  align-items: center;
2228
2295
  gap: 6px;
2229
- padding: 3px 7px;
2230
- border-radius: 5px;
2296
+ padding: 4px 8px;
2297
+ border: 1px solid var(--df-review-color-ruler-popover-border);
2298
+ border-radius: var(--df-review-radius-sm);
2231
2299
  background: var(--df-review-color-ruler-label);
2232
2300
  line-height: 1;
2233
2301
  white-space: nowrap;
2302
+ box-shadow: 0 6px 18px var(--df-review-color-ruler-popover-shadow);
2234
2303
  }
2235
2304
 
2236
2305
  .df-review-ruler-frame-label strong {
2237
2306
  color: var(--df-review-color-ruler-label-text);
2238
- font-size: var(--df-review-font-size-2xs);
2307
+ font-size: var(--df-review-font-size-xs);
2239
2308
  font-weight: 900;
2240
2309
  }
2241
2310
 
2242
2311
  .df-review-ruler-frame-label span {
2243
- color: var(--df-review-muted);
2244
- font-size: var(--df-review-font-size-2xs);
2312
+ color: var(--df-review-color-ruler-label-text);
2313
+ font-size: var(--df-review-font-size-xs);
2245
2314
  font-weight: 900;
2315
+ opacity: 0.78;
2246
2316
  }
2247
2317
 
2248
2318
  .df-review-ruler-coord {
2249
2319
  position: absolute;
2250
2320
  z-index: 7;
2251
- padding: 2px 4px;
2252
- border-radius: 4px;
2253
- background: #b395ff;
2254
- color: #14111f;
2255
- font-size: var(--df-review-font-size-3xs);
2321
+ padding: 4px 6px;
2322
+ border: 1px solid var(--df-review-color-ruler-popover-border);
2323
+ border-radius: var(--df-review-radius-xs);
2324
+ background: var(--df-review-color-ruler-coord-bg);
2325
+ color: var(--df-review-color-ruler-coord-text);
2326
+ font-size: var(--df-review-font-size-xs);
2256
2327
  font-weight: 900;
2257
2328
  line-height: 1;
2258
2329
  white-space: nowrap;
2259
2330
  pointer-events: none;
2331
+ box-shadow: 0 6px 18px var(--df-review-color-ruler-popover-shadow);
2260
2332
  }
2261
2333
 
2262
2334
  .df-review-ruler-coord.is-x {
@@ -2291,47 +2363,53 @@ function ensureReviewShellStyle() {
2291
2363
  z-index: 2;
2292
2364
  pointer-events: none;
2293
2365
  background: var(--df-review-color-ruler-guide);
2294
- box-shadow: 0 0 0 1px rgba(87, 55, 166, 0.45);
2366
+ box-shadow: 0 0 0 1px var(--df-review-color-ruler-measure-shadow);
2295
2367
  }
2296
2368
 
2297
2369
  .df-review-ruler-guide.is-x {
2298
2370
  left: 0;
2299
2371
  right: 0;
2300
- height: 1px;
2372
+ height: 2px;
2301
2373
  }
2302
2374
 
2303
2375
  .df-review-ruler-guide.is-y {
2304
2376
  top: 0;
2305
2377
  bottom: 0;
2306
- width: 1px;
2378
+ width: 2px;
2307
2379
  }
2308
2380
 
2309
2381
  .df-review-ruler-selection {
2310
2382
  position: absolute;
2311
2383
  z-index: 3;
2312
2384
  pointer-events: none;
2313
- border: 1px solid var(--df-review-color-ruler-measure-border);
2385
+ border: 3px solid var(--df-review-color-ruler-measure-border);
2314
2386
  background: var(--df-review-color-ruler-measure-bg);
2315
2387
  box-shadow:
2316
2388
  inset 0 0 0 1px var(--df-review-color-ruler-measure-shadow),
2317
- 0 0 0 1px var(--df-review-color-ruler-measure-shadow);
2389
+ 0 0 0 1px rgba(255, 255, 255, 0.96),
2390
+ 0 0 0 4px var(--df-review-color-ruler-measure-shadow);
2318
2391
  }
2319
2392
 
2320
2393
  .df-review-ruler-label {
2321
2394
  position: absolute;
2322
2395
  z-index: 4;
2323
2396
  pointer-events: none;
2324
- min-width: 156px;
2325
- padding: 7px 8px;
2397
+ min-width: 124px;
2398
+ padding: 9px 11px;
2326
2399
  border: 1px solid var(--df-review-color-ruler-popover-border);
2327
- border-radius: var(--df-review-radius-sm);
2400
+ border-radius: var(--df-review-radius-md);
2328
2401
  background: var(--df-review-color-ruler-popover-bg);
2329
- color: var(--df-review-text);
2330
- font-size: var(--df-review-font-size-xs);
2402
+ color: var(--df-review-color-ruler-popover-text);
2403
+ font-family: var(--df-review-font-mono);
2404
+ font-size: var(--df-review-font-size-lg);
2331
2405
  font-weight: 900;
2332
2406
  line-height: 1;
2333
2407
  white-space: nowrap;
2334
- box-shadow: 0 8px 22px var(--df-review-color-ruler-popover-shadow);
2408
+ letter-spacing: -0.02em;
2409
+ text-align: center;
2410
+ box-shadow:
2411
+ 0 10px 26px var(--df-review-color-ruler-popover-shadow),
2412
+ inset 0 1px 0 rgba(255, 255, 255, 0.18);
2335
2413
  }
2336
2414
 
2337
2415
  @media (max-width: 860px) {
@@ -2391,7 +2469,7 @@ function ensureReviewShellStyle() {
2391
2469
  }
2392
2470
 
2393
2471
  // src/react-shell/review/shell.tsx
2394
- var import_react16 = require("react");
2472
+ var import_react17 = require("react");
2395
2473
 
2396
2474
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/createLucideIcon.mjs
2397
2475
  var import_react3 = require("react");
@@ -2554,8 +2632,23 @@ var __iconNode5 = [
2554
2632
  ];
2555
2633
  var Eye = createLucideIcon("eye", __iconNode5);
2556
2634
 
2557
- // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/grip-vertical.mjs
2635
+ // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/file-code-corner.mjs
2558
2636
  var __iconNode6 = [
2637
+ [
2638
+ "path",
2639
+ {
2640
+ d: "M4 12.15V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.706.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2h-3.35",
2641
+ key: "1wthlu"
2642
+ }
2643
+ ],
2644
+ ["path", { d: "M14 2v5a1 1 0 0 0 1 1h5", key: "wfsgrz" }],
2645
+ ["path", { d: "m5 16-3 3 3 3", key: "331omg" }],
2646
+ ["path", { d: "m9 22 3-3-3-3", key: "lsp7cz" }]
2647
+ ];
2648
+ var FileCodeCorner = createLucideIcon("file-code-corner", __iconNode6);
2649
+
2650
+ // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/grip-vertical.mjs
2651
+ var __iconNode7 = [
2559
2652
  ["circle", { cx: "9", cy: "12", r: "1", key: "1vctgf" }],
2560
2653
  ["circle", { cx: "9", cy: "5", r: "1", key: "hp0tcf" }],
2561
2654
  ["circle", { cx: "9", cy: "19", r: "1", key: "fkjjf6" }],
@@ -2563,35 +2656,35 @@ var __iconNode6 = [
2563
2656
  ["circle", { cx: "15", cy: "5", r: "1", key: "19l28e" }],
2564
2657
  ["circle", { cx: "15", cy: "19", r: "1", key: "f4zoj3" }]
2565
2658
  ];
2566
- var GripVertical = createLucideIcon("grip-vertical", __iconNode6);
2659
+ var GripVertical = createLucideIcon("grip-vertical", __iconNode7);
2567
2660
 
2568
2661
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/image.mjs
2569
- var __iconNode7 = [
2662
+ var __iconNode8 = [
2570
2663
  ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2", key: "1m3agn" }],
2571
2664
  ["circle", { cx: "9", cy: "9", r: "2", key: "af1f0g" }],
2572
2665
  ["path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21", key: "1xmnt7" }]
2573
2666
  ];
2574
- var Image = createLucideIcon("image", __iconNode7);
2667
+ var Image = createLucideIcon("image", __iconNode8);
2575
2668
 
2576
2669
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/layout-grid.mjs
2577
- var __iconNode8 = [
2670
+ var __iconNode9 = [
2578
2671
  ["rect", { width: "7", height: "7", x: "3", y: "3", rx: "1", key: "1g98yp" }],
2579
2672
  ["rect", { width: "7", height: "7", x: "14", y: "3", rx: "1", key: "6d4xhi" }],
2580
2673
  ["rect", { width: "7", height: "7", x: "14", y: "14", rx: "1", key: "nxv5o0" }],
2581
2674
  ["rect", { width: "7", height: "7", x: "3", y: "14", rx: "1", key: "1bb6yr" }]
2582
2675
  ];
2583
- var LayoutGrid = createLucideIcon("layout-grid", __iconNode8);
2676
+ var LayoutGrid = createLucideIcon("layout-grid", __iconNode9);
2584
2677
 
2585
2678
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/list-filter.mjs
2586
- var __iconNode9 = [
2679
+ var __iconNode10 = [
2587
2680
  ["path", { d: "M2 5h20", key: "1fs1ex" }],
2588
2681
  ["path", { d: "M6 12h12", key: "8npq4p" }],
2589
2682
  ["path", { d: "M9 19h6", key: "456am0" }]
2590
2683
  ];
2591
- var ListFilter = createLucideIcon("list-filter", __iconNode9);
2684
+ var ListFilter = createLucideIcon("list-filter", __iconNode10);
2592
2685
 
2593
2686
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/map.mjs
2594
- var __iconNode10 = [
2687
+ var __iconNode11 = [
2595
2688
  [
2596
2689
  "path",
2597
2690
  {
@@ -2602,42 +2695,55 @@ var __iconNode10 = [
2602
2695
  ["path", { d: "M15 5.764v15", key: "1pn4in" }],
2603
2696
  ["path", { d: "M9 3.236v15", key: "1uimfh" }]
2604
2697
  ];
2605
- var Map2 = createLucideIcon("map", __iconNode10);
2698
+ var Map2 = createLucideIcon("map", __iconNode11);
2606
2699
 
2607
2700
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/maximize-2.mjs
2608
- var __iconNode11 = [
2701
+ var __iconNode12 = [
2609
2702
  ["path", { d: "M15 3h6v6", key: "1q9fwt" }],
2610
2703
  ["path", { d: "m21 3-7 7", key: "1l2asr" }],
2611
2704
  ["path", { d: "m3 21 7-7", key: "tjx5ai" }],
2612
2705
  ["path", { d: "M9 21H3v-6", key: "wtvkvv" }]
2613
2706
  ];
2614
- var Maximize2 = createLucideIcon("maximize-2", __iconNode11);
2707
+ var Maximize2 = createLucideIcon("maximize-2", __iconNode12);
2615
2708
 
2616
2709
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/monitor.mjs
2617
- var __iconNode12 = [
2710
+ var __iconNode13 = [
2618
2711
  ["rect", { width: "20", height: "14", x: "2", y: "3", rx: "2", key: "48i651" }],
2619
2712
  ["line", { x1: "8", x2: "16", y1: "21", y2: "21", key: "1svkeh" }],
2620
2713
  ["line", { x1: "12", x2: "12", y1: "17", y2: "21", key: "vw1qmm" }]
2621
2714
  ];
2622
- var Monitor = createLucideIcon("monitor", __iconNode12);
2715
+ var Monitor = createLucideIcon("monitor", __iconNode13);
2716
+
2717
+ // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/pencil.mjs
2718
+ var __iconNode14 = [
2719
+ [
2720
+ "path",
2721
+ {
2722
+ d: "M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z",
2723
+ key: "1a8usu"
2724
+ }
2725
+ ],
2726
+ ["path", { d: "m15 5 4 4", key: "1mk7zo" }]
2727
+ ];
2728
+ var Pencil = createLucideIcon("pencil", __iconNode14);
2623
2729
 
2624
2730
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/rectangle-horizontal.mjs
2625
- var __iconNode13 = [
2731
+ var __iconNode15 = [
2626
2732
  ["rect", { width: "20", height: "12", x: "2", y: "6", rx: "2", key: "9lu3g6" }]
2627
2733
  ];
2628
- var RectangleHorizontal = createLucideIcon("rectangle-horizontal", __iconNode13);
2734
+ var RectangleHorizontal = createLucideIcon("rectangle-horizontal", __iconNode15);
2629
2735
 
2630
2736
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/refresh-cw.mjs
2631
- var __iconNode14 = [
2737
+ var __iconNode16 = [
2632
2738
  ["path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8", key: "v9h5vc" }],
2633
2739
  ["path", { d: "M21 3v5h-5", key: "1q7to0" }],
2634
2740
  ["path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16", key: "3uifl3" }],
2635
2741
  ["path", { d: "M8 16H3v5", key: "1cv678" }]
2636
2742
  ];
2637
- var RefreshCw = createLucideIcon("refresh-cw", __iconNode14);
2743
+ var RefreshCw = createLucideIcon("refresh-cw", __iconNode16);
2638
2744
 
2639
2745
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/ruler.mjs
2640
- var __iconNode15 = [
2746
+ var __iconNode17 = [
2641
2747
  [
2642
2748
  "path",
2643
2749
  {
@@ -2650,19 +2756,19 @@ var __iconNode15 = [
2650
2756
  ["path", { d: "m8.5 6.5 2-2", key: "vc6u1g" }],
2651
2757
  ["path", { d: "m17.5 15.5 2-2", key: "wo5hmg" }]
2652
2758
  ];
2653
- var Ruler = createLucideIcon("ruler", __iconNode15);
2759
+ var Ruler = createLucideIcon("ruler", __iconNode17);
2654
2760
 
2655
2761
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/scan.mjs
2656
- var __iconNode16 = [
2762
+ var __iconNode18 = [
2657
2763
  ["path", { d: "M3 7V5a2 2 0 0 1 2-2h2", key: "aa7l1z" }],
2658
2764
  ["path", { d: "M17 3h2a2 2 0 0 1 2 2v2", key: "4qcy5o" }],
2659
2765
  ["path", { d: "M21 17v2a2 2 0 0 1-2 2h-2", key: "6vwrx8" }],
2660
2766
  ["path", { d: "M7 21H5a2 2 0 0 1-2-2v-2", key: "ioqczr" }]
2661
2767
  ];
2662
- var Scan = createLucideIcon("scan", __iconNode16);
2768
+ var Scan = createLucideIcon("scan", __iconNode18);
2663
2769
 
2664
2770
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/settings.mjs
2665
- var __iconNode17 = [
2771
+ var __iconNode19 = [
2666
2772
  [
2667
2773
  "path",
2668
2774
  {
@@ -2672,17 +2778,17 @@ var __iconNode17 = [
2672
2778
  ],
2673
2779
  ["circle", { cx: "12", cy: "12", r: "3", key: "1v7zrd" }]
2674
2780
  ];
2675
- var Settings = createLucideIcon("settings", __iconNode17);
2781
+ var Settings = createLucideIcon("settings", __iconNode19);
2676
2782
 
2677
2783
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/smartphone.mjs
2678
- var __iconNode18 = [
2784
+ var __iconNode20 = [
2679
2785
  ["rect", { width: "14", height: "20", x: "5", y: "2", rx: "2", ry: "2", key: "1yt0o3" }],
2680
2786
  ["path", { d: "M12 18h.01", key: "mhygvu" }]
2681
2787
  ];
2682
- var Smartphone = createLucideIcon("smartphone", __iconNode18);
2788
+ var Smartphone = createLucideIcon("smartphone", __iconNode20);
2683
2789
 
2684
2790
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/square-mouse-pointer.mjs
2685
- var __iconNode19 = [
2791
+ var __iconNode21 = [
2686
2792
  [
2687
2793
  "path",
2688
2794
  {
@@ -2692,10 +2798,10 @@ var __iconNode19 = [
2692
2798
  ],
2693
2799
  ["path", { d: "M21 11V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h6", key: "14rsvq" }]
2694
2800
  ];
2695
- var SquareMousePointer = createLucideIcon("square-mouse-pointer", __iconNode19);
2801
+ var SquareMousePointer = createLucideIcon("square-mouse-pointer", __iconNode21);
2696
2802
 
2697
2803
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/sticky-note.mjs
2698
- var __iconNode20 = [
2804
+ var __iconNode22 = [
2699
2805
  [
2700
2806
  "path",
2701
2807
  {
@@ -2705,31 +2811,31 @@ var __iconNode20 = [
2705
2811
  ],
2706
2812
  ["path", { d: "M15 3v5a1 1 0 0 0 1 1h5", key: "6s6qgf" }]
2707
2813
  ];
2708
- var StickyNote = createLucideIcon("sticky-note", __iconNode20);
2814
+ var StickyNote = createLucideIcon("sticky-note", __iconNode22);
2709
2815
 
2710
2816
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/upload.mjs
2711
- var __iconNode21 = [
2817
+ var __iconNode23 = [
2712
2818
  ["path", { d: "M12 3v12", key: "1x0j5s" }],
2713
2819
  ["path", { d: "m17 8-5-5-5 5", key: "7q97r8" }],
2714
2820
  ["path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4", key: "ih7n3h" }]
2715
2821
  ];
2716
- var Upload = createLucideIcon("upload", __iconNode21);
2822
+ var Upload = createLucideIcon("upload", __iconNode23);
2717
2823
 
2718
2824
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/users.mjs
2719
- var __iconNode22 = [
2825
+ var __iconNode24 = [
2720
2826
  ["path", { d: "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2", key: "1yyitq" }],
2721
2827
  ["path", { d: "M16 3.128a4 4 0 0 1 0 7.744", key: "16gr8j" }],
2722
2828
  ["path", { d: "M22 21v-2a4 4 0 0 0-3-3.87", key: "kshegd" }],
2723
2829
  ["circle", { cx: "9", cy: "7", r: "4", key: "nufk8" }]
2724
2830
  ];
2725
- var Users = createLucideIcon("users", __iconNode22);
2831
+ var Users = createLucideIcon("users", __iconNode24);
2726
2832
 
2727
2833
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/x.mjs
2728
- var __iconNode23 = [
2834
+ var __iconNode25 = [
2729
2835
  ["path", { d: "M18 6 6 18", key: "1bl5f8" }],
2730
2836
  ["path", { d: "m6 6 12 12", key: "d8bk6v" }]
2731
2837
  ];
2732
- var X = createLucideIcon("x", __iconNode23);
2838
+ var X = createLucideIcon("x", __iconNode25);
2733
2839
 
2734
2840
  // src/react-shell/constants.ts
2735
2841
  var REVIEW_QA_FILTERS = [
@@ -2949,6 +3055,8 @@ var formatPromptSourceHint = (item) => {
2949
3055
  return [
2950
3056
  `Component: ${source.component ?? "(unknown)"}`,
2951
3057
  `File: ${source.file ?? "(unknown)"}`,
3058
+ `Line: ${source.line ?? "(unknown)"}`,
3059
+ `Column: ${source.column ?? "(unknown)"}`,
2952
3060
  `Section index: ${source.sectionIndex ?? "(unknown)"}`,
2953
3061
  `Section id: ${source.sectionId ?? "(none)"}`
2954
3062
  ].join("\n");
@@ -3611,8 +3719,122 @@ var SitemapModal = ({
3611
3719
  );
3612
3720
  };
3613
3721
 
3614
- // src/react-shell/qa/item.remote.actions.tsx
3722
+ // src/react-shell/qa/item.edit.modal.tsx
3723
+ var import_react4 = require("react");
3615
3724
  var import_jsx_runtime4 = require("react/jsx-runtime");
3725
+ var QaItemEditModal = ({
3726
+ item,
3727
+ onClose,
3728
+ onSave
3729
+ }) => {
3730
+ const [commentDraft, setCommentDraft] = (0, import_react4.useState)(item.comment);
3731
+ const [error, setError] = (0, import_react4.useState)("");
3732
+ const [isSaving, setIsSaving] = (0, import_react4.useState)(false);
3733
+ (0, import_react4.useEffect)(() => {
3734
+ setCommentDraft(item.comment);
3735
+ setError("");
3736
+ setIsSaving(false);
3737
+ }, [item.id, item.comment]);
3738
+ const saveComment = async () => {
3739
+ const nextComment = commentDraft.trim();
3740
+ if (!nextComment) {
3741
+ setError("Comment is required.");
3742
+ return;
3743
+ }
3744
+ setError("");
3745
+ setIsSaving(true);
3746
+ try {
3747
+ await onSave(item, nextComment);
3748
+ } catch (error2) {
3749
+ setError(
3750
+ error2 instanceof Error ? error2.message : "Failed to update QA comment."
3751
+ );
3752
+ setIsSaving(false);
3753
+ }
3754
+ };
3755
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3756
+ "div",
3757
+ {
3758
+ "aria-modal": "true",
3759
+ className: "df-review-edit-modal",
3760
+ role: "dialog",
3761
+ "aria-labelledby": "df-review-edit-title",
3762
+ children: [
3763
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3764
+ "button",
3765
+ {
3766
+ "aria-label": "Close edit dialog",
3767
+ className: "df-review-settings-backdrop",
3768
+ type: "button",
3769
+ onClick: onClose
3770
+ }
3771
+ ),
3772
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3773
+ "form",
3774
+ {
3775
+ className: "df-review-edit-dialog",
3776
+ onSubmit: (event) => {
3777
+ event.preventDefault();
3778
+ void saveComment();
3779
+ },
3780
+ children: [
3781
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("header", { className: "df-review-settings-header", children: [
3782
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "df-review-settings-title", children: [
3783
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { id: "df-review-edit-title", children: "Edit QA comment" }),
3784
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Update the text shown on this QA item." })
3785
+ ] }),
3786
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "df-review-settings-header-actions", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3787
+ "button",
3788
+ {
3789
+ "aria-label": "Close edit dialog",
3790
+ type: "button",
3791
+ onClick: onClose,
3792
+ children: "x"
3793
+ }
3794
+ ) })
3795
+ ] }),
3796
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "df-review-settings-body df-review-edit-body", children: [
3797
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "df-review-settings-field", children: [
3798
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Comment" }),
3799
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "df-review-settings-text-input df-review-edit-textarea", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3800
+ "textarea",
3801
+ {
3802
+ autoFocus: true,
3803
+ value: commentDraft,
3804
+ onChange: (event) => {
3805
+ setCommentDraft(event.target.value);
3806
+ if (error) setError("");
3807
+ },
3808
+ onKeyDown: (event) => {
3809
+ if (event.key === "Escape") {
3810
+ event.preventDefault();
3811
+ onClose();
3812
+ }
3813
+ if ((event.metaKey || event.ctrlKey) && event.key === "Enter") {
3814
+ event.preventDefault();
3815
+ void saveComment();
3816
+ }
3817
+ }
3818
+ }
3819
+ ) })
3820
+ ] }),
3821
+ error && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "df-review-edit-error", children: error }),
3822
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("footer", { className: "df-review-settings-actions df-review-edit-actions", children: [
3823
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", {}),
3824
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { disabled: isSaving, type: "button", onClick: onClose, children: "Cancel" }),
3825
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { disabled: isSaving, type: "submit", children: isSaving ? "Saving\u2026" : "Save" })
3826
+ ] })
3827
+ ] })
3828
+ ]
3829
+ }
3830
+ )
3831
+ ]
3832
+ }
3833
+ );
3834
+ };
3835
+
3836
+ // src/react-shell/qa/item.remote.actions.tsx
3837
+ var import_jsx_runtime5 = require("react/jsx-runtime");
3616
3838
  var QaItemRemoteActions = ({
3617
3839
  isRemoteSource,
3618
3840
  isSubmitted,
@@ -3626,13 +3848,13 @@ var QaItemRemoteActions = ({
3626
3848
  const canOpenRemoteIssue = !isRemoteSource && Boolean(item.externalIssueUrl);
3627
3849
  const hasRemoteActions = canSubmitToRemote || canOpenRemoteIssue;
3628
3850
  if (!hasRemoteActions) return null;
3629
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3851
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3630
3852
  "div",
3631
3853
  {
3632
3854
  className: "df-review-item-remote-actions",
3633
3855
  onClick: (event) => event.stopPropagation(),
3634
3856
  children: [
3635
- canSubmitToRemote && remoteAdapterEntry && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
3857
+ canSubmitToRemote && remoteAdapterEntry && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3636
3858
  "button",
3637
3859
  {
3638
3860
  "aria-label": "Submit to remote",
@@ -3641,12 +3863,12 @@ var QaItemRemoteActions = ({
3641
3863
  type: "button",
3642
3864
  onClick: () => void onSubmitItem(numberedItem),
3643
3865
  children: [
3644
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Upload, { "aria-hidden": "true" }),
3645
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: isSubmitted ? "Submitted" : isSubmitting ? "Submitting" : "Submit" })
3866
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Upload, { "aria-hidden": "true" }),
3867
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: isSubmitted ? "Submitted" : isSubmitting ? "Submitting" : "Submit" })
3646
3868
  ]
3647
3869
  }
3648
3870
  ),
3649
- canOpenRemoteIssue && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
3871
+ canOpenRemoteIssue && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3650
3872
  "a",
3651
3873
  {
3652
3874
  "aria-label": "Open remote issue",
@@ -3654,7 +3876,7 @@ var QaItemRemoteActions = ({
3654
3876
  href: item.externalIssueUrl,
3655
3877
  rel: "noreferrer",
3656
3878
  target: "_blank",
3657
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ExternalLink, { "aria-hidden": "true" })
3879
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ExternalLink, { "aria-hidden": "true" })
3658
3880
  }
3659
3881
  )
3660
3882
  ]
@@ -3680,7 +3902,7 @@ function matchesReviewItemStatus(itemStatus, queryStatus) {
3680
3902
  }
3681
3903
 
3682
3904
  // src/react-shell/qa/item.status.actions.tsx
3683
- var import_jsx_runtime5 = require("react/jsx-runtime");
3905
+ var import_jsx_runtime6 = require("react/jsx-runtime");
3684
3906
  var getStatusOption = (status, statusOptions) => {
3685
3907
  const normalizedStatus = normalizeReviewItemStatus(status);
3686
3908
  return statusOptions.find((statusOption) => statusOption.value === status) ?? statusOptions.find(
@@ -3698,12 +3920,12 @@ var QaItemStatusActions = ({
3698
3920
  const statusClassName = `is-status-${normalizeReviewItemStatus(
3699
3921
  currentStatusOption.value
3700
3922
  )}`;
3701
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3923
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3702
3924
  "div",
3703
3925
  {
3704
3926
  className: "df-review-item-status-actions",
3705
3927
  onClick: (event) => event.stopPropagation(),
3706
- children: canUpdateStatus ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3928
+ children: canUpdateStatus ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3707
3929
  "select",
3708
3930
  {
3709
3931
  "aria-label": "QA status",
@@ -3713,9 +3935,9 @@ var QaItemStatusActions = ({
3713
3935
  item,
3714
3936
  event.currentTarget.value
3715
3937
  ),
3716
- children: statusOptions.map((statusOption) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: statusOption.value, children: statusOption.label }, statusOption.value))
3938
+ children: statusOptions.map((statusOption) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: statusOption.value, children: statusOption.label }, statusOption.value))
3717
3939
  }
3718
- ) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: `df-review-item-status-badge ${statusClassName}`, children: currentStatusOption.label })
3940
+ ) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: `df-review-item-status-badge ${statusClassName}`, children: currentStatusOption.label })
3719
3941
  }
3720
3942
  );
3721
3943
  };
@@ -3859,25 +4081,107 @@ var isScrollableReviewAnchorElement = (element) => {
3859
4081
  };
3860
4082
 
3861
4083
  // src/react-shell/review/item.icons.tsx
3862
- var import_jsx_runtime6 = require("react/jsx-runtime");
4084
+ var import_jsx_runtime7 = require("react/jsx-runtime");
3863
4085
  var ReviewScopeIcon = ({ scope }) => {
3864
- if (scope === "mobile") return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Smartphone, { "aria-hidden": "true" });
3865
- if (scope === "tablet") return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(RectangleHorizontal, { "aria-hidden": "true" });
3866
- if (scope === "wide") return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Maximize2, { "aria-hidden": "true" });
3867
- if (scope === "dom") return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SquareMousePointer, { "aria-hidden": "true" });
3868
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Monitor, { "aria-hidden": "true" });
4086
+ if (scope === "mobile") return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Smartphone, { "aria-hidden": "true" });
4087
+ if (scope === "tablet") return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(RectangleHorizontal, { "aria-hidden": "true" });
4088
+ if (scope === "wide") return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Maximize2, { "aria-hidden": "true" });
4089
+ if (scope === "dom") return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SquareMousePointer, { "aria-hidden": "true" });
4090
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Monitor, { "aria-hidden": "true" });
3869
4091
  };
3870
4092
  var getReviewItemMode = (item) => isAnchorRestorableReviewItem(item) ? "dom" : item.kind;
3871
4093
  var ReviewItemModeIcon = ({
3872
4094
  mode
3873
4095
  }) => {
3874
- if (mode === "area") return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Scan, { "aria-hidden": "true" });
3875
- if (mode === "dom") return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SquareMousePointer, { "aria-hidden": "true" });
3876
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(StickyNote, { "aria-hidden": "true" });
4096
+ if (mode === "area") return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Scan, { "aria-hidden": "true" });
4097
+ if (mode === "dom") return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SquareMousePointer, { "aria-hidden": "true" });
4098
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(StickyNote, { "aria-hidden": "true" });
4099
+ };
4100
+
4101
+ // src/react-shell/source.open.ts
4102
+ var SOURCE_SELECTOR = [
4103
+ "[data-wrk-source-file]",
4104
+ "[data-wrk-source-component]",
4105
+ "[data-wrk-source-line]",
4106
+ "[data-wrk-source-column]",
4107
+ "[data-file]",
4108
+ "[data-component]",
4109
+ "[data-section-index]",
4110
+ "[data-section-id]"
4111
+ ].join(", ");
4112
+ var getSourceHintElement = (target) => {
4113
+ return getEventElement(target)?.closest(SOURCE_SELECTOR) ?? null;
4114
+ };
4115
+ var getElementSourceHint = (target) => {
4116
+ const sourceElement = getSourceHintElement(target);
4117
+ if (!sourceElement) return void 0;
4118
+ const source = {
4119
+ component: getSourceAttribute(
4120
+ sourceElement,
4121
+ "data-wrk-source-component",
4122
+ "data-component"
4123
+ ),
4124
+ file: getSourceAttribute(sourceElement, "data-wrk-source-file", "data-file"),
4125
+ line: getSourceAttribute(sourceElement, "data-wrk-source-line"),
4126
+ column: getSourceAttribute(sourceElement, "data-wrk-source-column"),
4127
+ sectionId: getSourceAttribute(sourceElement, "data-section-id"),
4128
+ sectionIndex: getSourceAttribute(sourceElement, "data-section-index")
4129
+ };
4130
+ return Object.values(source).some(Boolean) ? source : void 0;
4131
+ };
4132
+ var getSourceOpenUrl = (source, sourceRoot) => {
4133
+ const file = source?.file?.trim();
4134
+ if (!file) return null;
4135
+ const sourcePath = getSourcePath(file, sourceRoot);
4136
+ if (!sourcePath) return null;
4137
+ const line = getSourcePosition(source?.line);
4138
+ const column = getSourcePosition(source?.column);
4139
+ const encodedPath = encodeURI(sourcePath).replace(
4140
+ /[#?]/g,
4141
+ (match) => match === "#" ? "%23" : "%3F"
4142
+ );
4143
+ return `vscode://file/${encodedPath}:${line}:${column}`;
4144
+ };
4145
+ var openSourceInEditor = (source, sourceRoot) => {
4146
+ const url = getSourceOpenUrl(source, sourceRoot);
4147
+ if (!url) return false;
4148
+ window.open(url, "_blank", "noreferrer");
4149
+ return true;
3877
4150
  };
4151
+ function getSourceAttribute(element, ...names) {
4152
+ for (const name of names) {
4153
+ const value = element.getAttribute(name)?.trim();
4154
+ if (value) return value;
4155
+ }
4156
+ return void 0;
4157
+ }
4158
+ function getEventElement(target) {
4159
+ if (!target || typeof target !== "object") return null;
4160
+ const node = target;
4161
+ if (node.nodeType === 1 && typeof node.closest === "function") {
4162
+ return node;
4163
+ }
4164
+ if (node.parentElement && typeof node.parentElement.closest === "function") {
4165
+ return node.parentElement;
4166
+ }
4167
+ return null;
4168
+ }
4169
+ function getSourcePath(file, sourceRoot) {
4170
+ const normalizedFile = file.replace(/\\/g, "/");
4171
+ if (normalizedFile.startsWith("/") || /^[a-zA-Z]:\//.test(normalizedFile)) {
4172
+ return normalizedFile;
4173
+ }
4174
+ const normalizedRoot = sourceRoot?.trim().replace(/\\/g, "/").replace(/\/+$/, "");
4175
+ if (!normalizedRoot) return null;
4176
+ return `${normalizedRoot}/${normalizedFile.replace(/^\/+/, "")}`;
4177
+ }
4178
+ function getSourcePosition(value) {
4179
+ const position = Number(value);
4180
+ return Number.isInteger(position) && position > 0 ? position : 1;
4181
+ }
3878
4182
 
3879
4183
  // src/react-shell/qa/item.card.tsx
3880
- var import_jsx_runtime7 = require("react/jsx-runtime");
4184
+ var import_jsx_runtime8 = require("react/jsx-runtime");
3881
4185
  var formatItemCardDate = (value) => {
3882
4186
  const date = new Date(value);
3883
4187
  if (Number.isNaN(date.getTime())) return value;
@@ -3898,10 +4202,12 @@ var QaItemCard = ({
3898
4202
  remoteAdapterEntry,
3899
4203
  copiedPromptKey,
3900
4204
  selectedItemId,
4205
+ sourceRoot,
3901
4206
  onChangeItemStatus,
3902
4207
  onClearSelectedItem,
3903
4208
  onRemoveItem,
3904
4209
  onCopyItemPrompt,
4210
+ onEditItem,
3905
4211
  onRestoreReviewItem,
3906
4212
  onSubmitItem,
3907
4213
  onToggleItemOverlayVisibility
@@ -3918,8 +4224,10 @@ var QaItemCard = ({
3918
4224
  const statusOptions = activeAdapterEntry.statusOptions;
3919
4225
  const isActive = item.id === selectedItemId;
3920
4226
  const canUpdateStatus = Boolean(activeAdapterEntry.updateStatus) && statusOptions.length > 0 && !isSubmitting;
4227
+ const canEditItem = activeAdapterEntry.canUpdate && !isSubmitting;
3921
4228
  const itemMeta = [formatItemCardDate(item.createdAt), itemAuthor].filter(Boolean).join(" | ");
3922
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
4229
+ const sourceOpenUrl = getSourceOpenUrl(item.anchor?.source, sourceRoot);
4230
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
3923
4231
  "article",
3924
4232
  {
3925
4233
  className: `df-review-item-card${isActive ? " is-active" : ""}${getItemPresetScope(item) !== currentPresetScope ? " is-dim" : ""}${isOverlayVisible ? "" : " is-overlay-hidden"}`,
@@ -3931,46 +4239,58 @@ var QaItemCard = ({
3931
4239
  onRestoreReviewItem(item);
3932
4240
  },
3933
4241
  children: [
3934
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "df-review-item-header", children: [
3935
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "df-review-item-main", children: [
3936
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "df-review-item-badges", children: [
3937
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "df-review-item-id", children: numberedItem.displayLabel }),
3938
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
4242
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "df-review-item-header", children: [
4243
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "df-review-item-main", children: [
4244
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "df-review-item-badges", children: [
4245
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "df-review-item-id", children: numberedItem.displayLabel }),
4246
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
3939
4247
  "span",
3940
4248
  {
3941
4249
  className: `df-review-item-scope is-scope-${numberedItem.scope}`,
3942
4250
  children: [
3943
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ReviewScopeIcon, { scope: numberedItem.scope }),
4251
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ReviewScopeIcon, { scope: numberedItem.scope }),
3944
4252
  numberedItem.label
3945
4253
  ]
3946
4254
  }
3947
4255
  ),
3948
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: `df-review-item-mode is-mode-${itemMode}`, children: [
3949
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ReviewItemModeIcon, { mode: itemMode }),
4256
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: `df-review-item-mode is-mode-${itemMode}`, children: [
4257
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ReviewItemModeIcon, { mode: itemMode }),
3950
4258
  itemMode
3951
4259
  ] })
3952
4260
  ] }),
3953
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("strong", { className: "df-review-item-comment", children: itemComment }),
3954
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("small", { className: "df-review-item-meta", children: itemMeta }),
3955
- item.submitError && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("small", { className: "df-review-item-error", children: item.submitError })
4261
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("strong", { className: "df-review-item-comment", children: itemComment }),
4262
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("small", { className: "df-review-item-meta", children: itemMeta }),
4263
+ item.submitError && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("small", { className: "df-review-item-error", children: item.submitError })
3956
4264
  ] }),
3957
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
4265
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
3958
4266
  "div",
3959
4267
  {
3960
4268
  className: "df-review-item-header-actions",
3961
4269
  onClick: (event) => event.stopPropagation(),
3962
4270
  children: [
3963
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4271
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3964
4272
  "button",
3965
4273
  {
3966
4274
  "aria-label": isOverlayVisible ? "Hide QA overlay" : "Show QA overlay",
3967
4275
  className: `df-review-item-visibility${isOverlayVisible ? " is-visible" : " is-hidden"}`,
3968
4276
  type: "button",
3969
4277
  onClick: () => onToggleItemOverlayVisibility(item.id),
3970
- children: isOverlayVisible ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Eye, { "aria-hidden": "true" }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(EyeOff, { "aria-hidden": "true" })
4278
+ children: isOverlayVisible ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Eye, { "aria-hidden": "true" }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(EyeOff, { "aria-hidden": "true" })
3971
4279
  }
3972
4280
  ),
3973
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4281
+ sourceOpenUrl && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4282
+ "a",
4283
+ {
4284
+ "aria-label": "Open source in VS Code",
4285
+ className: "df-review-item-source-open",
4286
+ href: sourceOpenUrl,
4287
+ rel: "noreferrer",
4288
+ target: "_blank",
4289
+ title: "Open source in VS Code",
4290
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(FileCodeCorner, { "aria-hidden": "true" })
4291
+ }
4292
+ ),
4293
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3974
4294
  "button",
3975
4295
  {
3976
4296
  "aria-label": isPromptCopied ? "Copied QA prompt" : "Copy QA prompt",
@@ -3978,25 +4298,36 @@ var QaItemCard = ({
3978
4298
  title: isPromptCopied ? "Copied QA prompt" : "Copy QA prompt",
3979
4299
  type: "button",
3980
4300
  onClick: () => onCopyItemPrompt(numberedItem),
3981
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Copy, { "aria-hidden": "true" })
4301
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Copy, { "aria-hidden": "true" })
4302
+ }
4303
+ ),
4304
+ canEditItem && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4305
+ "button",
4306
+ {
4307
+ "aria-label": "Edit QA comment",
4308
+ className: "df-review-item-edit",
4309
+ title: "Edit QA comment",
4310
+ type: "button",
4311
+ onClick: () => onEditItem(item),
4312
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Pencil, { "aria-hidden": "true" })
3982
4313
  }
3983
4314
  ),
3984
- canRemoveItem && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4315
+ canRemoveItem && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3985
4316
  "button",
3986
4317
  {
3987
4318
  "aria-label": "Delete QA",
3988
4319
  className: "df-review-item-delete",
3989
4320
  type: "button",
3990
4321
  onClick: () => void onRemoveItem(item),
3991
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(X, { "aria-hidden": "true" })
4322
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(X, { "aria-hidden": "true" })
3992
4323
  }
3993
4324
  )
3994
4325
  ]
3995
4326
  }
3996
4327
  )
3997
4328
  ] }),
3998
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "df-review-item-actions", children: [
3999
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4329
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "df-review-item-actions", children: [
4330
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4000
4331
  QaItemStatusActions,
4001
4332
  {
4002
4333
  canUpdateStatus,
@@ -4005,7 +4336,7 @@ var QaItemCard = ({
4005
4336
  onChangeItemStatus
4006
4337
  }
4007
4338
  ),
4008
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4339
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4009
4340
  QaItemRemoteActions,
4010
4341
  {
4011
4342
  isRemoteSource,
@@ -4024,19 +4355,19 @@ var QaItemCard = ({
4024
4355
  };
4025
4356
 
4026
4357
  // src/react-shell/presence/row.tsx
4027
- var import_jsx_runtime8 = require("react/jsx-runtime");
4358
+ var import_jsx_runtime9 = require("react/jsx-runtime");
4028
4359
  var PresenceRow = ({
4029
4360
  presenceSessionId,
4030
4361
  users
4031
4362
  }) => {
4032
4363
  if (users.length === 0) return null;
4033
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { "aria-label": "Review presence", className: "df-review-presence-row", children: [
4034
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "df-review-presence-label", children: [
4035
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Users, { "aria-hidden": "true" }),
4364
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { "aria-label": "Review presence", className: "df-review-presence-row", children: [
4365
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "df-review-presence-label", children: [
4366
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Users, { "aria-hidden": "true" }),
4036
4367
  "online ",
4037
4368
  users.length
4038
4369
  ] }),
4039
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "df-review-presence-list", children: users.map((user) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
4370
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "df-review-presence-list", children: users.map((user) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
4040
4371
  "span",
4041
4372
  {
4042
4373
  className: `df-review-presence-chip${user.sessionId === presenceSessionId ? " is-self" : ""}`,
@@ -4044,8 +4375,8 @@ var PresenceRow = ({
4044
4375
  "--df-review-presence-color": user.color
4045
4376
  },
4046
4377
  children: [
4047
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "df-review-presence-dot", "aria-hidden": "true" }),
4048
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "df-review-presence-name", children: user.userId })
4378
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "df-review-presence-dot", "aria-hidden": "true" }),
4379
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "df-review-presence-name", children: user.userId })
4049
4380
  ]
4050
4381
  },
4051
4382
  user.sessionId
@@ -4054,7 +4385,7 @@ var PresenceRow = ({
4054
4385
  };
4055
4386
 
4056
4387
  // src/react-shell/qa/panel.header.tsx
4057
- var import_jsx_runtime9 = require("react/jsx-runtime");
4388
+ var import_jsx_runtime10 = require("react/jsx-runtime");
4058
4389
  var QaPanelHeader = ({
4059
4390
  activeItemCount,
4060
4391
  currentPagePresenceUsers,
@@ -4070,34 +4401,34 @@ var QaPanelHeader = ({
4070
4401
  onQaFilterChange,
4071
4402
  onRefreshReviewData
4072
4403
  }) => {
4073
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "df-review-list-header", children: [
4074
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "df-review-list-toolbar", children: [
4075
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "df-review-list-controls", children: [
4076
- showSourceSelect && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4404
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "df-review-list-header", children: [
4405
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "df-review-list-toolbar", children: [
4406
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "df-review-list-controls", children: [
4407
+ showSourceSelect && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4077
4408
  "select",
4078
4409
  {
4079
4410
  "aria-label": "QA source",
4080
4411
  className: "df-review-source-select",
4081
4412
  value: source,
4082
4413
  onChange: (event) => onChangeReviewSource(event.currentTarget.value),
4083
- children: sourceEntries.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("option", { value: entry.label, children: entry.label }, entry.label))
4414
+ children: sourceEntries.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: entry.label, children: entry.label }, entry.label))
4084
4415
  }
4085
4416
  ),
4086
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4417
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4087
4418
  "button",
4088
4419
  {
4089
4420
  "aria-label": "Refresh QA",
4090
4421
  className: "df-review-source-refresh",
4091
4422
  type: "button",
4092
4423
  onClick: () => void onRefreshReviewData(),
4093
- children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(RefreshCw, { "aria-hidden": "true" })
4424
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(RefreshCw, { "aria-hidden": "true" })
4094
4425
  }
4095
4426
  )
4096
4427
  ] }),
4097
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "df-review-filter-tabs", "aria-label": "QA filters", children: REVIEW_QA_FILTERS.map((filter) => {
4428
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "df-review-filter-tabs", "aria-label": "QA filters", children: REVIEW_QA_FILTERS.map((filter) => {
4098
4429
  const count = qaFilterCounts.get(filter.key) ?? 0;
4099
4430
  const isActive = qaFilter === filter.key;
4100
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4431
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4101
4432
  "button",
4102
4433
  {
4103
4434
  "aria-label": `${filter.label} QA (${count})`,
@@ -4105,23 +4436,23 @@ var QaPanelHeader = ({
4105
4436
  className: `df-review-filter-tab${isActive ? " is-active" : ""}`,
4106
4437
  type: "button",
4107
4438
  onClick: () => onQaFilterChange(filter.key),
4108
- children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "df-review-filter-icon", children: filter.scope ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ReviewScopeIcon, { scope: filter.scope }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ListFilter, { "aria-hidden": "true" }) })
4439
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "df-review-filter-icon", children: filter.scope ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ReviewScopeIcon, { scope: filter.scope }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ListFilter, { "aria-hidden": "true" }) })
4109
4440
  },
4110
4441
  filter.key
4111
4442
  );
4112
4443
  }) })
4113
4444
  ] }),
4114
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "df-review-list-title", children: [
4115
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { children: [
4445
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "df-review-list-title", children: [
4446
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { children: [
4116
4447
  label,
4117
4448
  " QA"
4118
4449
  ] }),
4119
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("strong", { children: [
4450
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("strong", { children: [
4120
4451
  filteredItemCount,
4121
4452
  qaFilter === "all" ? "" : `/${activeItemCount}`
4122
4453
  ] })
4123
4454
  ] }),
4124
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4455
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4125
4456
  PresenceRow,
4126
4457
  {
4127
4458
  presenceSessionId,
@@ -4132,7 +4463,7 @@ var QaPanelHeader = ({
4132
4463
  };
4133
4464
 
4134
4465
  // src/react-shell/qa/panel.tsx
4135
- var import_jsx_runtime10 = require("react/jsx-runtime");
4466
+ var import_jsx_runtime11 = require("react/jsx-runtime");
4136
4467
  var ReviewQaPanel = ({
4137
4468
  activeAdapterEntry,
4138
4469
  activeItems,
@@ -4150,12 +4481,14 @@ var ReviewQaPanel = ({
4150
4481
  remoteAdapterEntry,
4151
4482
  selectedItemId,
4152
4483
  showSourceSelect,
4484
+ sourceRoot,
4153
4485
  source,
4154
4486
  sourceEntries,
4155
4487
  onChangeItemStatus,
4156
4488
  onClearSelectedItem,
4157
4489
  onChangeReviewSource,
4158
4490
  onCopyItemPrompt,
4491
+ onEditItem,
4159
4492
  onQaFilterChange,
4160
4493
  onRefreshReviewData,
4161
4494
  onRemoveItem,
@@ -4163,8 +4496,8 @@ var ReviewQaPanel = ({
4163
4496
  onSubmitItem,
4164
4497
  onToggleItemOverlayVisibility
4165
4498
  }) => {
4166
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("aside", { className: "df-review-qa-panel", "aria-hidden": !isListVisible, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "df-review-panel-body", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("section", { className: "df-review-item-list", children: [
4167
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4499
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("aside", { className: "df-review-qa-panel", "aria-hidden": !isListVisible, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "df-review-panel-body", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("section", { className: "df-review-item-list", children: [
4500
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
4168
4501
  QaPanelHeader,
4169
4502
  {
4170
4503
  activeItemCount: activeItems.length,
@@ -4182,7 +4515,7 @@ var ReviewQaPanel = ({
4182
4515
  onRefreshReviewData
4183
4516
  }
4184
4517
  ),
4185
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
4518
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
4186
4519
  "div",
4187
4520
  {
4188
4521
  className: "df-review-list-scroll",
@@ -4192,11 +4525,11 @@ var ReviewQaPanel = ({
4192
4525
  }
4193
4526
  },
4194
4527
  children: [
4195
- activeItems.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "df-review-empty", children: isRemoteSource ? `No ${activeAdapterEntry.label} QA on this page.` : "No QA on this page." }),
4196
- activeItems.length > 0 && filteredNumberedActiveItems.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "df-review-empty", children: "No QA in this filter." }),
4528
+ activeItems.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "df-review-empty", children: isRemoteSource ? `No ${activeAdapterEntry.label} QA on this page.` : "No QA on this page." }),
4529
+ activeItems.length > 0 && filteredNumberedActiveItems.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "df-review-empty", children: "No QA in this filter." }),
4197
4530
  filteredNumberedActiveItems.map((numberedItem) => {
4198
4531
  const { item } = numberedItem;
4199
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4532
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
4200
4533
  QaItemCard,
4201
4534
  {
4202
4535
  activeAdapterEntry,
@@ -4208,9 +4541,11 @@ var ReviewQaPanel = ({
4208
4541
  remoteAdapterEntry,
4209
4542
  copiedPromptKey,
4210
4543
  selectedItemId,
4544
+ sourceRoot,
4211
4545
  onChangeItemStatus,
4212
4546
  onClearSelectedItem,
4213
4547
  onCopyItemPrompt,
4548
+ onEditItem,
4214
4549
  onRemoveItem,
4215
4550
  onRestoreReviewItem,
4216
4551
  onSubmitItem,
@@ -4226,53 +4561,41 @@ var ReviewQaPanel = ({
4226
4561
  };
4227
4562
 
4228
4563
  // src/react-shell/review/mode.toolbar.tsx
4229
- var import_jsx_runtime11 = require("react/jsx-runtime");
4564
+ var import_jsx_runtime12 = require("react/jsx-runtime");
4230
4565
  var ReviewModeToolbar = ({
4231
- canWriteAny,
4232
4566
  canWriteArea,
4233
4567
  canWriteDom,
4234
- canWriteNote,
4235
4568
  mode,
4236
4569
  onSetReviewMode
4237
4570
  }) => {
4238
- if (!canWriteAny) return null;
4239
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "df-review-mode", "aria-label": "Add QA", children: [
4240
- canWriteDom && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
4571
+ if (!canWriteDom && !canWriteArea) return null;
4572
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "df-review-mode", "aria-label": "Add QA", children: [
4573
+ canWriteDom && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4241
4574
  "button",
4242
4575
  {
4243
4576
  "aria-label": "Element",
4244
4577
  className: `df-review-mode-button is-element${mode === "element" ? " is-active" : ""}`,
4245
4578
  type: "button",
4246
4579
  onClick: () => onSetReviewMode("element"),
4247
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SquareMousePointer, { "aria-hidden": "true" })
4580
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SquareMousePointer, { "aria-hidden": "true" })
4248
4581
  }
4249
4582
  ),
4250
- canWriteDom && (canWriteNote || canWriteArea) && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "df-review-mode-divider", "aria-hidden": "true", children: "|" }),
4251
- canWriteNote && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
4252
- "button",
4253
- {
4254
- "aria-label": "Note",
4255
- className: `df-review-mode-button is-note${mode === "note" ? " is-active" : ""}`,
4256
- type: "button",
4257
- onClick: () => onSetReviewMode("note"),
4258
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(StickyNote, { "aria-hidden": "true" })
4259
- }
4260
- ),
4261
- canWriteArea && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
4583
+ canWriteDom && canWriteArea && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "df-review-mode-divider", "aria-hidden": "true", children: "|" }),
4584
+ canWriteArea && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4262
4585
  "button",
4263
4586
  {
4264
4587
  "aria-label": "Area",
4265
4588
  className: `df-review-mode-button is-area${mode === "area" ? " is-active" : ""}`,
4266
4589
  type: "button",
4267
4590
  onClick: () => onSetReviewMode("area"),
4268
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Scan, { "aria-hidden": "true" })
4591
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Scan, { "aria-hidden": "true" })
4269
4592
  }
4270
4593
  )
4271
4594
  ] });
4272
4595
  };
4273
4596
 
4274
4597
  // src/react-shell/ruler/gutters.tsx
4275
- var import_jsx_runtime12 = require("react/jsx-runtime");
4598
+ var import_jsx_runtime13 = require("react/jsx-runtime");
4276
4599
  var RulerGutters = ({
4277
4600
  rulerHover,
4278
4601
  rulerScaleX,
@@ -4280,9 +4603,9 @@ var RulerGutters = ({
4280
4603
  rulerUnit,
4281
4604
  size
4282
4605
  }) => {
4283
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
4284
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "df-review-ruler-corner", "aria-hidden": "true" }),
4285
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
4606
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
4607
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "df-review-ruler-corner", "aria-hidden": "true" }),
4608
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
4286
4609
  "div",
4287
4610
  {
4288
4611
  className: "df-review-ruler-gutter is-x",
@@ -4290,15 +4613,15 @@ var RulerGutters = ({
4290
4613
  "--df-review-ruler-step-x": `${rulerScaleX * 20}px`
4291
4614
  },
4292
4615
  children: [
4293
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "df-review-ruler-frame-label", children: [
4294
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("strong", { children: size.label }),
4295
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
4616
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "df-review-ruler-frame-label", children: [
4617
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("strong", { children: size.label }),
4618
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { children: [
4296
4619
  size.designWidth,
4297
4620
  size.designHeight ? `x${size.designHeight}` : "",
4298
4621
  rulerUnit
4299
4622
  ] })
4300
4623
  ] }),
4301
- rulerHover && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4624
+ rulerHover && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4302
4625
  "div",
4303
4626
  {
4304
4627
  className: "df-review-ruler-coord is-x",
@@ -4309,14 +4632,14 @@ var RulerGutters = ({
4309
4632
  ]
4310
4633
  }
4311
4634
  ),
4312
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4635
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4313
4636
  "div",
4314
4637
  {
4315
4638
  className: "df-review-ruler-gutter is-y",
4316
4639
  style: {
4317
4640
  "--df-review-ruler-step-y": `${rulerScaleY * 20}px`
4318
4641
  },
4319
- children: rulerHover && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4642
+ children: rulerHover && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4320
4643
  "div",
4321
4644
  {
4322
4645
  className: "df-review-ruler-coord is-y",
@@ -4330,7 +4653,7 @@ var RulerGutters = ({
4330
4653
  };
4331
4654
 
4332
4655
  // src/react-shell/ruler/overlay.tsx
4333
- var import_jsx_runtime13 = require("react/jsx-runtime");
4656
+ var import_jsx_runtime14 = require("react/jsx-runtime");
4334
4657
  var RulerOverlay = ({
4335
4658
  iframeRef,
4336
4659
  isRulerDragging,
@@ -4340,7 +4663,7 @@ var RulerOverlay = ({
4340
4663
  rulerOverlayRef,
4341
4664
  size
4342
4665
  }) => {
4343
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
4666
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
4344
4667
  "div",
4345
4668
  {
4346
4669
  ref: rulerOverlayRef,
@@ -4354,8 +4677,8 @@ var RulerOverlay = ({
4354
4677
  );
4355
4678
  },
4356
4679
  children: [
4357
- rulerHover && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
4358
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4680
+ rulerHover && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
4681
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4359
4682
  "div",
4360
4683
  {
4361
4684
  className: "df-review-ruler-guide is-x",
@@ -4363,7 +4686,7 @@ var RulerOverlay = ({
4363
4686
  style: { top: `${rulerHover.y}px` }
4364
4687
  }
4365
4688
  ),
4366
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4689
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4367
4690
  "div",
4368
4691
  {
4369
4692
  className: "df-review-ruler-guide is-y",
@@ -4372,8 +4695,8 @@ var RulerOverlay = ({
4372
4695
  }
4373
4696
  )
4374
4697
  ] }),
4375
- rulerMeasure && (rulerMeasure.width > 0 || rulerMeasure.height > 0) && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
4376
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4698
+ rulerMeasure && (rulerMeasure.width > 0 || rulerMeasure.height > 0) && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
4699
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4377
4700
  "div",
4378
4701
  {
4379
4702
  className: "df-review-ruler-selection",
@@ -4386,7 +4709,7 @@ var RulerOverlay = ({
4386
4709
  }
4387
4710
  }
4388
4711
  ),
4389
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4712
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4390
4713
  "div",
4391
4714
  {
4392
4715
  className: "df-review-ruler-label",
@@ -4410,12 +4733,10 @@ var RulerOverlay = ({
4410
4733
  };
4411
4734
 
4412
4735
  // src/react-shell/target/frame.tsx
4413
- var import_jsx_runtime14 = require("react/jsx-runtime");
4736
+ var import_jsx_runtime15 = require("react/jsx-runtime");
4414
4737
  var ReviewTargetFrame = ({
4415
- canWriteAny,
4416
4738
  canWriteArea,
4417
4739
  canWriteDom,
4418
- canWriteNote,
4419
4740
  frameScrollRef,
4420
4741
  iframeRef,
4421
4742
  isRulerAvailable,
@@ -4435,13 +4756,13 @@ var ReviewTargetFrame = ({
4435
4756
  onSetReviewMode
4436
4757
  }) => {
4437
4758
  const showRuler = isRulerVisible && isRulerAvailable;
4438
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("main", { className: "df-review-stage", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "df-review-frame", children: [
4439
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "df-review-frame-scroll", ref: frameScrollRef, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "df-review-frame-canvas", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
4759
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("main", { className: "df-review-stage", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "df-review-frame", children: [
4760
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "df-review-frame-scroll", ref: frameScrollRef, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "df-review-frame-canvas", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
4440
4761
  "div",
4441
4762
  {
4442
4763
  className: `df-review-device-frame${showRuler ? " is-ruler" : ""}`,
4443
4764
  children: [
4444
- showRuler && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4765
+ showRuler && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4445
4766
  RulerGutters,
4446
4767
  {
4447
4768
  rulerHover,
@@ -4451,7 +4772,7 @@ var ReviewTargetFrame = ({
4451
4772
  size
4452
4773
  }
4453
4774
  ),
4454
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
4775
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
4455
4776
  "div",
4456
4777
  {
4457
4778
  className: "df-review-device",
@@ -4462,7 +4783,7 @@ var ReviewTargetFrame = ({
4462
4783
  minHeight: `${size.height}px`
4463
4784
  },
4464
4785
  children: [
4465
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4786
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4466
4787
  "iframe",
4467
4788
  {
4468
4789
  ref: iframeRef,
@@ -4474,7 +4795,7 @@ var ReviewTargetFrame = ({
4474
4795
  },
4475
4796
  targetSrc
4476
4797
  ),
4477
- showRuler && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4798
+ showRuler && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4478
4799
  RulerOverlay,
4479
4800
  {
4480
4801
  iframeRef,
@@ -4492,13 +4813,11 @@ var ReviewTargetFrame = ({
4492
4813
  ]
4493
4814
  }
4494
4815
  ) }) }),
4495
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "df-review-frame-actions", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4816
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "df-review-frame-actions", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4496
4817
  ReviewModeToolbar,
4497
4818
  {
4498
- canWriteAny,
4499
4819
  canWriteArea,
4500
4820
  canWriteDom,
4501
- canWriteNote,
4502
4821
  mode,
4503
4822
  onSetReviewMode
4504
4823
  }
@@ -4507,18 +4826,18 @@ var ReviewTargetFrame = ({
4507
4826
  };
4508
4827
 
4509
4828
  // src/react-shell/topbar.tsx
4510
- var import_jsx_runtime15 = require("react/jsx-runtime");
4829
+ var import_jsx_runtime16 = require("react/jsx-runtime");
4511
4830
  var ReviewScopeIcon2 = ({ scope }) => {
4512
- if (scope === "mobile") return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Smartphone, { "aria-hidden": "true" });
4513
- if (scope === "tablet") return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(RectangleHorizontal, { "aria-hidden": "true" });
4514
- if (scope === "wide") return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Maximize2, { "aria-hidden": "true" });
4515
- if (scope === "dom") return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(SquareMousePointer, { "aria-hidden": "true" });
4516
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Monitor, { "aria-hidden": "true" });
4831
+ if (scope === "mobile") return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Smartphone, { "aria-hidden": "true" });
4832
+ if (scope === "tablet") return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(RectangleHorizontal, { "aria-hidden": "true" });
4833
+ if (scope === "wide") return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Maximize2, { "aria-hidden": "true" });
4834
+ if (scope === "dom") return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(SquareMousePointer, { "aria-hidden": "true" });
4835
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Monitor, { "aria-hidden": "true" });
4517
4836
  };
4518
4837
  var ViewportPresetIcon = ({
4519
4838
  preset
4520
4839
  }) => {
4521
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ReviewScopeIcon2, { scope: getViewportPresetKind(preset) });
4840
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ReviewScopeIcon2, { scope: getViewportPresetKind(preset) });
4522
4841
  };
4523
4842
  var ReviewTopbar = ({
4524
4843
  draftTarget,
@@ -4540,8 +4859,8 @@ var ReviewTopbar = ({
4540
4859
  onOpenInitialPrompt,
4541
4860
  onOpenSettings
4542
4861
  }) => {
4543
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("header", { className: "df-review-topbar", children: [
4544
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
4862
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("header", { className: "df-review-topbar", children: [
4863
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
4545
4864
  "form",
4546
4865
  {
4547
4866
  className: "df-review-address",
@@ -4550,17 +4869,17 @@ var ReviewTopbar = ({
4550
4869
  onApplyTarget();
4551
4870
  },
4552
4871
  children: [
4553
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4872
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4554
4873
  "button",
4555
4874
  {
4556
4875
  "aria-label": "Open sitemap",
4557
4876
  className: "df-review-sitemap-button",
4558
4877
  type: "button",
4559
4878
  onClick: onOpenSitemap,
4560
- children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Map2, { "aria-hidden": "true" })
4879
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Map2, { "aria-hidden": "true" })
4561
4880
  }
4562
4881
  ),
4563
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4882
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4564
4883
  "input",
4565
4884
  {
4566
4885
  "aria-label": "Path",
@@ -4568,56 +4887,56 @@ var ReviewTopbar = ({
4568
4887
  onChange: (event) => onDraftTargetChange(event.target.value)
4569
4888
  }
4570
4889
  ),
4571
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "submit", children: "Load" }),
4572
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", onClick: onCopyCurrentUrl, children: copyLabel })
4890
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { type: "submit", children: "Load" }),
4891
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { type: "button", onClick: onCopyCurrentUrl, children: copyLabel })
4573
4892
  ]
4574
4893
  }
4575
4894
  ),
4576
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "df-review-tools", children: [
4577
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "df-review-tool-controls", children: [
4578
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "df-review-presets", "aria-label": "Viewport presets", children: viewportPresets.map((preset) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
4895
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "df-review-tools", children: [
4896
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "df-review-tool-controls", children: [
4897
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "df-review-presets", "aria-label": "Viewport presets", children: viewportPresets.map((preset) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
4579
4898
  "button",
4580
4899
  {
4581
4900
  className: preset.label === size.label ? "is-active" : "",
4582
4901
  type: "button",
4583
4902
  onClick: () => onSizeChange(preset),
4584
4903
  children: [
4585
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ViewportPresetIcon, { preset }),
4586
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "df-review-preset-copy", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("strong", { children: preset.label }) }),
4587
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "df-review-preset-count", children: presetScopeCounts.get(getViewportPresetKind(preset)) ?? 0 })
4904
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ViewportPresetIcon, { preset }),
4905
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "df-review-preset-copy", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("strong", { children: preset.label }) }),
4906
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "df-review-preset-count", children: presetScopeCounts.get(getViewportPresetKind(preset)) ?? 0 })
4588
4907
  ]
4589
4908
  },
4590
4909
  preset.label
4591
4910
  )) }),
4592
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "df-review-tool-divider", "aria-hidden": "true", children: "|" }),
4593
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { className: "df-review-active-size", children: [
4911
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "df-review-tool-divider", "aria-hidden": "true", children: "|" }),
4912
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("span", { className: "df-review-active-size", children: [
4594
4913
  size.width,
4595
4914
  "x",
4596
4915
  size.height
4597
4916
  ] })
4598
4917
  ] }),
4599
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "df-review-overlays", "aria-label": "Target overlays", children: [
4600
- isRulerAvailable && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4918
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "df-review-overlays", "aria-label": "Target overlays", children: [
4919
+ isRulerAvailable && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4601
4920
  "button",
4602
4921
  {
4603
4922
  "aria-label": "Toggle ruler",
4604
4923
  className: `df-review-overlay-button is-ruler${isRulerVisible ? " is-active" : ""}`,
4605
4924
  type: "button",
4606
4925
  onClick: onToggleRuler,
4607
- children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Ruler, { "aria-hidden": "true" })
4926
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Ruler, { "aria-hidden": "true" })
4608
4927
  }
4609
4928
  ),
4610
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4929
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4611
4930
  "button",
4612
4931
  {
4613
4932
  "aria-label": "Toggle grid overlay",
4614
4933
  className: `df-review-overlay-button is-grid${targetOverlayState.grid ? " is-active" : ""}`,
4615
4934
  type: "button",
4616
4935
  onClick: () => onToggleTargetOverlay("grid"),
4617
- children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(LayoutGrid, { "aria-hidden": "true" })
4936
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(LayoutGrid, { "aria-hidden": "true" })
4618
4937
  }
4619
4938
  ),
4620
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4939
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4621
4940
  "button",
4622
4941
  {
4623
4942
  "aria-disabled": !isFigmaOverlayAvailable,
@@ -4625,28 +4944,28 @@ var ReviewTopbar = ({
4625
4944
  className: `df-review-overlay-button is-figma${targetOverlayState.figma ? " is-active" : ""}${isFigmaOverlayAvailable ? "" : " is-disabled"}`,
4626
4945
  type: "button",
4627
4946
  onClick: () => onToggleTargetOverlay("figma"),
4628
- children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Image, { "aria-hidden": "true" })
4947
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Image, { "aria-hidden": "true" })
4629
4948
  }
4630
4949
  ),
4631
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "df-review-tool-divider", "aria-hidden": "true", children: "|" }),
4632
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4950
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "df-review-tool-divider", "aria-hidden": "true", children: "|" }),
4951
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4633
4952
  "button",
4634
4953
  {
4635
4954
  "aria-label": "Open initial prompt",
4636
4955
  className: "df-review-overlay-button is-prompt",
4637
4956
  type: "button",
4638
4957
  onClick: onOpenInitialPrompt,
4639
- children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(CircleQuestionMark, { "aria-hidden": "true" })
4958
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(CircleQuestionMark, { "aria-hidden": "true" })
4640
4959
  }
4641
4960
  ),
4642
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4961
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
4643
4962
  "button",
4644
4963
  {
4645
4964
  "aria-label": "Open settings",
4646
4965
  className: "df-review-overlay-button is-settings",
4647
4966
  type: "button",
4648
4967
  onClick: onOpenSettings,
4649
- children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Settings, { "aria-hidden": "true" })
4968
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Settings, { "aria-hidden": "true" })
4650
4969
  }
4651
4970
  )
4652
4971
  ] })
@@ -4655,10 +4974,10 @@ var ReviewTopbar = ({
4655
4974
  };
4656
4975
 
4657
4976
  // src/react-shell/hooks/use.review.controller.ts
4658
- var import_react8 = require("react");
4977
+ var import_react9 = require("react");
4659
4978
 
4660
4979
  // src/react-shell/hooks/use.review.item.restore.ts
4661
- var import_react4 = require("react");
4980
+ var import_react5 = require("react");
4662
4981
  function runWithAutoScrollBehavior(targetDocument, callback) {
4663
4982
  const elements = [
4664
4983
  targetDocument?.documentElement,
@@ -4694,7 +5013,7 @@ var useReviewItemRestore = ({
4694
5013
  onSyncTargetViewport,
4695
5014
  onTargetChange
4696
5015
  }) => {
4697
- const clearSelectedItem = (0, import_react4.useCallback)(() => {
5016
+ const clearSelectedItem = (0, import_react5.useCallback)(() => {
4698
5017
  pendingRestoreRef.current = null;
4699
5018
  selectedItemIdRef.current = null;
4700
5019
  onSelectedItemIdChange(null);
@@ -4705,7 +5024,7 @@ var useReviewItemRestore = ({
4705
5024
  pendingRestoreRef,
4706
5025
  selectedItemIdRef
4707
5026
  ]);
4708
- const applyItemScroll = (0, import_react4.useCallback)(
5027
+ const applyItemScroll = (0, import_react5.useCallback)(
4709
5028
  (item) => {
4710
5029
  if (selectedItemIdRef.current !== item.id) return;
4711
5030
  const targetWindow = iframeRef.current?.contentWindow;
@@ -4730,13 +5049,13 @@ var useReviewItemRestore = ({
4730
5049
  },
4731
5050
  [controllerRef, iframeRef, onSyncTargetViewport, selectedItemIdRef]
4732
5051
  );
4733
- const applyPendingRestore = (0, import_react4.useCallback)(() => {
5052
+ const applyPendingRestore = (0, import_react5.useCallback)(() => {
4734
5053
  const item = pendingRestoreRef.current;
4735
5054
  if (!item) return;
4736
5055
  applyItemScroll(item);
4737
5056
  pendingRestoreRef.current = null;
4738
5057
  }, [applyItemScroll, pendingRestoreRef]);
4739
- const restoreReviewItem = (0, import_react4.useCallback)(
5058
+ const restoreReviewItem = (0, import_react5.useCallback)(
4740
5059
  (item) => {
4741
5060
  const nextTarget = getItemTarget(item, reviewPathPrefix);
4742
5061
  const nextSize = getRestoredSize(item, viewportPresets);
@@ -4768,7 +5087,7 @@ var useReviewItemRestore = ({
4768
5087
  viewportPresets
4769
5088
  ]
4770
5089
  );
4771
- const restoreInitialItem = (0, import_react4.useCallback)(async () => {
5090
+ const restoreInitialItem = (0, import_react5.useCallback)(async () => {
4772
5091
  const itemId = pendingInitialItemIdRef.current;
4773
5092
  if (!itemId) return;
4774
5093
  pendingInitialItemIdRef.current = null;
@@ -4786,7 +5105,7 @@ var useReviewItemRestore = ({
4786
5105
  };
4787
5106
 
4788
5107
  // src/react-shell/hooks/use.review.kit.lifecycle.ts
4789
- var import_react5 = require("react");
5108
+ var import_react6 = require("react");
4790
5109
 
4791
5110
  // src/route.ts
4792
5111
  function getItemRouteKey(item) {
@@ -5237,18 +5556,39 @@ function decodeHtmlEntities(value) {
5237
5556
  }
5238
5557
  function getDomSourceHint(target) {
5239
5558
  const sourceElement = target.closest(
5240
- "[data-file], [data-component], [data-section-index], [data-section-id]"
5559
+ [
5560
+ "[data-wrk-source-file]",
5561
+ "[data-wrk-source-component]",
5562
+ "[data-wrk-source-line]",
5563
+ "[data-wrk-source-column]",
5564
+ "[data-file]",
5565
+ "[data-component]",
5566
+ "[data-section-index]",
5567
+ "[data-section-id]"
5568
+ ].join(", ")
5241
5569
  );
5242
5570
  if (!sourceElement) return void 0;
5243
- const dataset = sourceElement.dataset;
5244
5571
  const source = {
5245
- component: dataset.component,
5246
- file: dataset.file,
5247
- sectionId: dataset.sectionId,
5248
- sectionIndex: dataset.sectionIndex
5572
+ component: getSourceAttribute2(
5573
+ sourceElement,
5574
+ "data-wrk-source-component",
5575
+ "data-component"
5576
+ ),
5577
+ file: getSourceAttribute2(sourceElement, "data-wrk-source-file", "data-file"),
5578
+ line: getSourceAttribute2(sourceElement, "data-wrk-source-line"),
5579
+ column: getSourceAttribute2(sourceElement, "data-wrk-source-column"),
5580
+ sectionId: getSourceAttribute2(sourceElement, "data-section-id"),
5581
+ sectionIndex: getSourceAttribute2(sourceElement, "data-section-index")
5249
5582
  };
5250
5583
  return Object.values(source).some(Boolean) ? source : void 0;
5251
5584
  }
5585
+ function getSourceAttribute2(element, ...names) {
5586
+ for (const name of names) {
5587
+ const value = element.getAttribute(name)?.trim();
5588
+ if (value) return value;
5589
+ }
5590
+ return void 0;
5591
+ }
5252
5592
  function dedupeAnchorCandidates(candidates) {
5253
5593
  const seen = /* @__PURE__ */ new Set();
5254
5594
  return candidates.filter((candidate) => {
@@ -7289,6 +7629,13 @@ ${formatItemMeta(item)}`;
7289
7629
 
7290
7630
  // src/core/web.review.kit.app.ts
7291
7631
  var ROOT_ID = "df-web-review-kit-root";
7632
+ function isEditableEventTarget(event) {
7633
+ const path = event.composedPath?.() ?? [];
7634
+ const element = path[0] ?? event.target;
7635
+ if (!element || typeof element.tagName !== "string") return false;
7636
+ const tag = element.tagName;
7637
+ return tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT" || element.isContentEditable === true;
7638
+ }
7292
7639
  function createWebReviewKit(options) {
7293
7640
  if (typeof window === "undefined" || typeof document === "undefined") {
7294
7641
  return createNoopController();
@@ -7321,7 +7668,7 @@ var WebReviewKitApp = class {
7321
7668
  event.stopPropagation();
7322
7669
  return;
7323
7670
  }
7324
- if (!isHotkey(event, this.hotkey)) return;
7671
+ if (isEditableEventTarget(event) || !isHotkey(event, this.hotkey)) return;
7325
7672
  event.preventDefault();
7326
7673
  event.stopPropagation();
7327
7674
  this.toggle();
@@ -7757,7 +8104,7 @@ var setTargetScrollbarHidden = (targetDocument, hidden) => {
7757
8104
  existing?.remove();
7758
8105
  }
7759
8106
  };
7760
- var isEditableEventTarget = (event) => {
8107
+ var isEditableEventTarget2 = (event) => {
7761
8108
  const path = event.composedPath?.() ?? [];
7762
8109
  const element = path[0] ?? event.target;
7763
8110
  if (!element || typeof element.tagName !== "string") return false;
@@ -7914,13 +8261,13 @@ var useReviewKitLifecycle = ({
7914
8261
  onSyncShellTarget,
7915
8262
  onSyncTargetViewport
7916
8263
  }) => {
7917
- const destroyReviewKit = (0, import_react5.useCallback)(() => {
8264
+ const destroyReviewKit = (0, import_react6.useCallback)(() => {
7918
8265
  cleanupTargetRef.current?.();
7919
8266
  cleanupTargetRef.current = null;
7920
8267
  controllerRef.current?.destroy();
7921
8268
  controllerRef.current = null;
7922
8269
  }, [cleanupTargetRef, controllerRef]);
7923
- const initReviewKit = (0, import_react5.useCallback)(() => {
8270
+ const initReviewKit = (0, import_react6.useCallback)(() => {
7924
8271
  destroyReviewKit();
7925
8272
  const iframe = iframeRef.current;
7926
8273
  const targetWindow = iframe?.contentWindow;
@@ -8006,23 +8353,23 @@ var useReviewKitLifecycle = ({
8006
8353
  sizeRef,
8007
8354
  targetRef
8008
8355
  ]);
8009
- const reloadReviewKit = (0, import_react5.useCallback)(async () => {
8356
+ const reloadReviewKit = (0, import_react6.useCallback)(async () => {
8010
8357
  await controllerRef.current?.reload();
8011
8358
  }, [controllerRef]);
8012
- const setControllerReviewMode = (0, import_react5.useCallback)(
8359
+ const setControllerReviewMode = (0, import_react6.useCallback)(
8013
8360
  (nextMode) => {
8014
8361
  controllerRef.current?.setMode(nextMode);
8015
8362
  onModeChange(controllerRef.current?.getMode() ?? "idle");
8016
8363
  },
8017
8364
  [controllerRef, onModeChange]
8018
8365
  );
8019
- (0, import_react5.useEffect)(() => destroyReviewKit, [destroyReviewKit]);
8020
- (0, import_react5.useEffect)(() => {
8366
+ (0, import_react6.useEffect)(() => destroyReviewKit, [destroyReviewKit]);
8367
+ (0, import_react6.useEffect)(() => {
8021
8368
  const frameDocument = iframeRef.current?.contentDocument;
8022
8369
  if (!frameDocument || frameDocument.readyState !== "complete") return;
8023
8370
  initReviewKit();
8024
8371
  }, [iframeRef, initReviewKit]);
8025
- (0, import_react5.useEffect)(() => {
8372
+ (0, import_react6.useEffect)(() => {
8026
8373
  hiddenOverlayItemIdListRef.current = hiddenOverlayItemIdList;
8027
8374
  controllerRef.current?.setHiddenItemIds(hiddenOverlayItemIdList);
8028
8375
  }, [controllerRef, hiddenOverlayItemIdList, hiddenOverlayItemIdListRef]);
@@ -8035,19 +8382,19 @@ var useReviewKitLifecycle = ({
8035
8382
  };
8036
8383
 
8037
8384
  // src/react-shell/hooks/use.review.target.overlay.ts
8038
- var import_react6 = require("react");
8385
+ var import_react7 = require("react");
8039
8386
  var useReviewTargetOverlay = ({
8040
8387
  iframeRef,
8041
8388
  isFigmaOverlayAvailable,
8042
8389
  targetOverlayState,
8043
8390
  onTargetOverlayStateChange
8044
8391
  }) => {
8045
- const refreshTargetOverlayState = (0, import_react6.useCallback)(() => {
8392
+ const refreshTargetOverlayState = (0, import_react7.useCallback)(() => {
8046
8393
  onTargetOverlayStateChange(
8047
8394
  getTargetOverlayState(iframeRef.current?.contentDocument ?? void 0)
8048
8395
  );
8049
8396
  }, [iframeRef, onTargetOverlayStateChange]);
8050
- const dispatchTargetOverlayHotkey = (0, import_react6.useCallback)(
8397
+ const dispatchTargetOverlayHotkey = (0, import_react7.useCallback)(
8051
8398
  (overlay) => {
8052
8399
  const targetWindow = iframeRef.current?.contentWindow;
8053
8400
  if (!targetWindow) return false;
@@ -8066,7 +8413,7 @@ var useReviewTargetOverlay = ({
8066
8413
  },
8067
8414
  [iframeRef, refreshTargetOverlayState]
8068
8415
  );
8069
- const toggleTargetOverlay = (0, import_react6.useCallback)(
8416
+ const toggleTargetOverlay = (0, import_react7.useCallback)(
8070
8417
  (overlay) => {
8071
8418
  if (overlay === "figma" && !isFigmaOverlayAvailable) {
8072
8419
  refreshTargetOverlayState();
@@ -8080,7 +8427,7 @@ var useReviewTargetOverlay = ({
8080
8427
  refreshTargetOverlayState
8081
8428
  ]
8082
8429
  );
8083
- const closeTargetOverlay = (0, import_react6.useCallback)(
8430
+ const closeTargetOverlay = (0, import_react7.useCallback)(
8084
8431
  (overlay) => {
8085
8432
  const currentState = getTargetOverlayState(
8086
8433
  iframeRef.current?.contentDocument ?? void 0
@@ -8091,7 +8438,7 @@ var useReviewTargetOverlay = ({
8091
8438
  },
8092
8439
  [dispatchTargetOverlayHotkey, iframeRef, onTargetOverlayStateChange]
8093
8440
  );
8094
- (0, import_react6.useEffect)(() => {
8441
+ (0, import_react7.useEffect)(() => {
8095
8442
  if (isFigmaOverlayAvailable || !targetOverlayState.figma) return;
8096
8443
  closeTargetOverlay("figma");
8097
8444
  }, [closeTargetOverlay, isFigmaOverlayAvailable, targetOverlayState.figma]);
@@ -8103,7 +8450,7 @@ var useReviewTargetOverlay = ({
8103
8450
  };
8104
8451
 
8105
8452
  // src/react-shell/hooks/use.review.target.sync.ts
8106
- var import_react7 = require("react");
8453
+ var import_react8 = require("react");
8107
8454
  var useReviewTargetSync = ({
8108
8455
  iframeRef,
8109
8456
  reviewPathPrefix,
@@ -8119,7 +8466,7 @@ var useReviewTargetSync = ({
8119
8466
  onSyncTargetViewport,
8120
8467
  onTargetChange
8121
8468
  }) => {
8122
- const syncShellTarget = (0, import_react7.useCallback)(
8469
+ const syncShellTarget = (0, import_react8.useCallback)(
8123
8470
  (nextTarget) => {
8124
8471
  const normalizedTarget = normalizeTarget(nextTarget, reviewPathPrefix);
8125
8472
  if (normalizedTarget !== targetRef.current) {
@@ -8152,11 +8499,11 @@ var useReviewTargetSync = ({
8152
8499
  targetRef
8153
8500
  ]
8154
8501
  );
8155
- (0, import_react7.useEffect)(() => {
8502
+ (0, import_react8.useEffect)(() => {
8156
8503
  targetRef.current = target;
8157
8504
  onActiveRouteChange(target);
8158
8505
  }, [onActiveRouteChange, target, targetRef]);
8159
- (0, import_react7.useEffect)(() => {
8506
+ (0, import_react8.useEffect)(() => {
8160
8507
  sizeRef.current = size;
8161
8508
  if (selectedItemIdRef.current) {
8162
8509
  updateShellUrlForItem(
@@ -8224,7 +8571,7 @@ var useReviewController = ({
8224
8571
  onTargetOverlayStateChange,
8225
8572
  onCloseRuler
8226
8573
  }) => {
8227
- const syncTargetViewport = (0, import_react8.useCallback)(() => {
8574
+ const syncTargetViewport = (0, import_react9.useCallback)(() => {
8228
8575
  window.dispatchEvent(new Event("resize"));
8229
8576
  }, []);
8230
8577
  const {
@@ -8320,7 +8667,7 @@ var useReviewController = ({
8320
8667
  };
8321
8668
 
8322
8669
  // src/react-shell/hooks/use.review.presence.ts
8323
- var import_react9 = require("react");
8670
+ var import_react10 = require("react");
8324
8671
 
8325
8672
  // src/react-shell/presence/presence.ts
8326
8673
  var REVIEW_PRESENCE_SESSION_KEY = "df-review-presence-session-id";
@@ -8535,10 +8882,10 @@ var useReviewPresence = ({
8535
8882
  size,
8536
8883
  source
8537
8884
  }) => {
8538
- const presenceSessionRef = (0, import_react9.useRef)(null);
8539
- const [presenceUsers, setPresenceUsers] = (0, import_react9.useState)([]);
8540
- const [presenceSessionVersion, setPresenceSessionVersion] = (0, import_react9.useState)(0);
8541
- const presenceSessionId = (0, import_react9.useMemo)(getReviewPresenceSessionId, []);
8885
+ const presenceSessionRef = (0, import_react10.useRef)(null);
8886
+ const [presenceUsers, setPresenceUsers] = (0, import_react10.useState)([]);
8887
+ const [presenceSessionVersion, setPresenceSessionVersion] = (0, import_react10.useState)(0);
8888
+ const presenceSessionId = (0, import_react10.useMemo)(getReviewPresenceSessionId, []);
8542
8889
  const normalizedReviewUserId = reviewUserId.trim();
8543
8890
  const presenceDisplayName = getReviewPresenceDisplayName(
8544
8891
  normalizedReviewUserId
@@ -8546,7 +8893,7 @@ var useReviewPresence = ({
8546
8893
  const presenceColor = getReviewPresenceColor(
8547
8894
  normalizedReviewUserId || presenceSessionId
8548
8895
  );
8549
- const presenceViewport = (0, import_react9.useMemo)(
8896
+ const presenceViewport = (0, import_react10.useMemo)(
8550
8897
  () => ({
8551
8898
  label: size.label,
8552
8899
  width: size.width,
@@ -8556,7 +8903,7 @@ var useReviewPresence = ({
8556
8903
  [size]
8557
8904
  );
8558
8905
  const presenceStatus = mode === "idle" ? "reviewing" : "editing";
8559
- const visiblePresenceUsers = (0, import_react9.useMemo)(
8906
+ const visiblePresenceUsers = (0, import_react10.useMemo)(
8560
8907
  () => {
8561
8908
  const projectPresenceUsers = presenceUsers.filter(
8562
8909
  (user) => user.projectId === projectId && user.userId.trim()
@@ -8568,14 +8915,14 @@ var useReviewPresence = ({
8568
8915
  },
8569
8916
  [presenceUsers, projectId, reviewPathPrefix]
8570
8917
  );
8571
- const currentPagePresenceUsers = (0, import_react9.useMemo)(
8918
+ const currentPagePresenceUsers = (0, import_react10.useMemo)(
8572
8919
  () => visiblePresenceUsers.filter((user) => {
8573
8920
  const userTarget = getPresenceUserTarget(user, reviewPathPrefix);
8574
8921
  return userTarget === activeRoute;
8575
8922
  }),
8576
8923
  [activeRoute, reviewPathPrefix, visiblePresenceUsers]
8577
8924
  );
8578
- const pagePresenceUsers = (0, import_react9.useMemo)(() => {
8925
+ const pagePresenceUsers = (0, import_react10.useMemo)(() => {
8579
8926
  const usersByTarget = /* @__PURE__ */ new Map();
8580
8927
  visiblePresenceUsers.forEach((user) => {
8581
8928
  const userTarget = getPresenceUserTarget(user, reviewPathPrefix);
@@ -8585,7 +8932,7 @@ var useReviewPresence = ({
8585
8932
  });
8586
8933
  return usersByTarget;
8587
8934
  }, [reviewPathPrefix, visiblePresenceUsers]);
8588
- const getCurrentPresenceState = (0, import_react9.useCallback)(
8935
+ const getCurrentPresenceState = (0, import_react10.useCallback)(
8589
8936
  () => ({
8590
8937
  projectId,
8591
8938
  sessionId: presenceSessionId,
@@ -8616,9 +8963,9 @@ var useReviewPresence = ({
8616
8963
  source
8617
8964
  ]
8618
8965
  );
8619
- const getCurrentPresenceStateRef = (0, import_react9.useRef)(getCurrentPresenceState);
8966
+ const getCurrentPresenceStateRef = (0, import_react10.useRef)(getCurrentPresenceState);
8620
8967
  getCurrentPresenceStateRef.current = getCurrentPresenceState;
8621
- (0, import_react9.useEffect)(() => {
8968
+ (0, import_react10.useEffect)(() => {
8622
8969
  if (!presence || !normalizedReviewUserId) {
8623
8970
  const session = presenceSessionRef.current;
8624
8971
  presenceSessionRef.current = null;
@@ -8668,7 +9015,7 @@ var useReviewPresence = ({
8668
9015
  presenceSessionId,
8669
9016
  projectId
8670
9017
  ]);
8671
- (0, import_react9.useEffect)(() => {
9018
+ (0, import_react10.useEffect)(() => {
8672
9019
  const session = presenceSessionRef.current;
8673
9020
  if (!session || !normalizedReviewUserId) return;
8674
9021
  void session.update(getCurrentPresenceState());
@@ -8685,10 +9032,10 @@ var useReviewPresence = ({
8685
9032
  };
8686
9033
 
8687
9034
  // src/react-shell/hooks/use.review.ruler.ts
8688
- var import_react11 = require("react");
9035
+ var import_react12 = require("react");
8689
9036
 
8690
9037
  // src/react-shell/hooks/use.review.ruler.drag.ts
8691
- var import_react10 = require("react");
9038
+ var import_react11 = require("react");
8692
9039
 
8693
9040
  // src/react-shell/ruler/ruler.ts
8694
9041
  var getRulerPointFromRect = (clientX, clientY, rect) => {
@@ -8717,19 +9064,19 @@ var useReviewRulerDrag = ({
8717
9064
  size,
8718
9065
  targetSrc
8719
9066
  }) => {
8720
- const rulerOverlayRef = (0, import_react10.useRef)(null);
8721
- const rulerDragRectRef = (0, import_react10.useRef)(null);
8722
- const isRulerDraggingRef = (0, import_react10.useRef)(false);
8723
- const sizeRef = (0, import_react10.useRef)(size);
8724
- const [rulerStart, setRulerStart] = (0, import_react10.useState)(null);
8725
- const [rulerPoint, setRulerPoint] = (0, import_react10.useState)(null);
8726
- const [rulerHover, setRulerHover] = (0, import_react10.useState)(null);
8727
- const [isRulerDragging, setIsRulerDragging] = (0, import_react10.useState)(false);
8728
- const rulerMeasure = (0, import_react10.useMemo)(
9067
+ const rulerOverlayRef = (0, import_react11.useRef)(null);
9068
+ const rulerDragRectRef = (0, import_react11.useRef)(null);
9069
+ const isRulerDraggingRef = (0, import_react11.useRef)(false);
9070
+ const sizeRef = (0, import_react11.useRef)(size);
9071
+ const [rulerStart, setRulerStart] = (0, import_react11.useState)(null);
9072
+ const [rulerPoint, setRulerPoint] = (0, import_react11.useState)(null);
9073
+ const [rulerHover, setRulerHover] = (0, import_react11.useState)(null);
9074
+ const [isRulerDragging, setIsRulerDragging] = (0, import_react11.useState)(false);
9075
+ const rulerMeasure = (0, import_react11.useMemo)(
8729
9076
  () => getRulerMeasure(rulerStart, rulerPoint),
8730
9077
  [rulerPoint, rulerStart]
8731
9078
  );
8732
- const clearRulerMeasure = (0, import_react10.useCallback)(() => {
9079
+ const clearRulerMeasure = (0, import_react11.useCallback)(() => {
8733
9080
  rulerDragRectRef.current = null;
8734
9081
  isRulerDraggingRef.current = false;
8735
9082
  setRulerStart(null);
@@ -8737,7 +9084,7 @@ var useReviewRulerDrag = ({
8737
9084
  setRulerHover(null);
8738
9085
  setIsRulerDragging(false);
8739
9086
  }, []);
8740
- const finishRulerDrag = (0, import_react10.useCallback)((point) => {
9087
+ const finishRulerDrag = (0, import_react11.useCallback)((point) => {
8741
9088
  if (point) {
8742
9089
  setRulerPoint(point);
8743
9090
  }
@@ -8745,7 +9092,7 @@ var useReviewRulerDrag = ({
8745
9092
  isRulerDraggingRef.current = false;
8746
9093
  setIsRulerDragging(false);
8747
9094
  }, []);
8748
- const startRulerDrag = (0, import_react10.useCallback)(
9095
+ const startRulerDrag = (0, import_react11.useCallback)(
8749
9096
  (clientX, clientY, rect) => {
8750
9097
  const point = getRulerPointFromRect(clientX, clientY, rect);
8751
9098
  rulerDragRectRef.current = rect;
@@ -8756,10 +9103,10 @@ var useReviewRulerDrag = ({
8756
9103
  },
8757
9104
  []
8758
9105
  );
8759
- (0, import_react10.useEffect)(() => {
9106
+ (0, import_react11.useEffect)(() => {
8760
9107
  sizeRef.current = size;
8761
9108
  }, [size]);
8762
- (0, import_react10.useEffect)(() => {
9109
+ (0, import_react11.useEffect)(() => {
8763
9110
  if (!isRulerVisible || !isRulerAvailable) return void 0;
8764
9111
  const getRulerEventClientPoint = (event) => {
8765
9112
  const frame2 = iframeRef.current;
@@ -8873,7 +9220,7 @@ var useReviewRulerDrag = ({
8873
9220
  isRulerVisible,
8874
9221
  startRulerDrag
8875
9222
  ]);
8876
- (0, import_react10.useEffect)(() => {
9223
+ (0, import_react11.useEffect)(() => {
8877
9224
  clearRulerMeasure();
8878
9225
  }, [clearRulerMeasure, size.height, size.width, targetSrc]);
8879
9226
  return {
@@ -8894,7 +9241,7 @@ var useReviewRuler = ({
8894
9241
  onCancelReviewMode,
8895
9242
  onCloseTransientPanels
8896
9243
  }) => {
8897
- const [isRulerVisible, setIsRulerVisible] = (0, import_react11.useState)(false);
9244
+ const [isRulerVisible, setIsRulerVisible] = (0, import_react12.useState)(false);
8898
9245
  const isRulerAvailable = ruler?.enabled !== false && typeof size.designWidth === "number" && size.designWidth > 0;
8899
9246
  const rulerUnit = ruler?.unit ?? "px";
8900
9247
  const rulerScaleX = isRulerAvailable && size.designWidth ? size.width / size.designWidth : 1;
@@ -8912,16 +9259,16 @@ var useReviewRuler = ({
8912
9259
  size,
8913
9260
  targetSrc
8914
9261
  });
8915
- const rulerMeasureLabel = rulerMeasure ? `Figma ${Math.round(rulerMeasure.width / rulerScaleX)}x${Math.round(
9262
+ const rulerMeasureLabel = rulerMeasure ? `${Math.round(rulerMeasure.width / rulerScaleX)} \xD7 ${Math.round(
8916
9263
  rulerMeasure.height / rulerScaleY
8917
- )}${rulerUnit}` : "";
8918
- const closeRuler = (0, import_react11.useCallback)(() => {
9264
+ )} ${rulerUnit}` : "";
9265
+ const closeRuler = (0, import_react12.useCallback)(() => {
8919
9266
  if (!isRulerVisible) return false;
8920
9267
  setIsRulerVisible(false);
8921
9268
  clearRulerMeasure();
8922
9269
  return true;
8923
9270
  }, [clearRulerMeasure, isRulerVisible]);
8924
- const toggleRuler = (0, import_react11.useCallback)(() => {
9271
+ const toggleRuler = (0, import_react12.useCallback)(() => {
8925
9272
  if (!isRulerAvailable) return;
8926
9273
  onCancelReviewMode();
8927
9274
  onCloseTransientPanels();
@@ -8933,7 +9280,7 @@ var useReviewRuler = ({
8933
9280
  onCancelReviewMode,
8934
9281
  onCloseTransientPanels
8935
9282
  ]);
8936
- (0, import_react11.useEffect)(() => {
9283
+ (0, import_react12.useEffect)(() => {
8937
9284
  if (!isRulerVisible || isRulerAvailable) return;
8938
9285
  closeRuler();
8939
9286
  }, [closeRuler, isRulerAvailable, isRulerVisible]);
@@ -8954,33 +9301,33 @@ var useReviewRuler = ({
8954
9301
  };
8955
9302
 
8956
9303
  // src/react-shell/hooks/use.review.settings.ts
8957
- var import_react12 = require("react");
9304
+ var import_react13 = require("react");
8958
9305
  var useReviewSettings = ({
8959
9306
  onCancelReviewMode,
8960
9307
  onCloseInitialPrompt,
8961
9308
  onCloseSitemap,
8962
9309
  onReloadTargetFrame
8963
9310
  }) => {
8964
- const [figmaTokenDraft, setFigmaTokenDraft] = (0, import_react12.useState)(getStoredFigmaToken);
8965
- const [reviewUserId, setReviewUserId] = (0, import_react12.useState)(getStoredReviewUserId);
8966
- const [reviewUserIdDraft, setReviewUserIdDraft] = (0, import_react12.useState)(
9311
+ const [figmaTokenDraft, setFigmaTokenDraft] = (0, import_react13.useState)(getStoredFigmaToken);
9312
+ const [reviewUserId, setReviewUserId] = (0, import_react13.useState)(getStoredReviewUserId);
9313
+ const [reviewUserIdDraft, setReviewUserIdDraft] = (0, import_react13.useState)(
8967
9314
  getStoredReviewUserId
8968
9315
  );
8969
- const [reviewTheme, setReviewTheme] = (0, import_react12.useState)(getStoredReviewTheme);
8970
- const [reviewThemeDraft, setReviewThemeDraft] = (0, import_react12.useState)(getStoredReviewTheme);
8971
- const [systemReviewTheme, setSystemReviewTheme] = (0, import_react12.useState)(getSystemReviewTheme);
8972
- const [figmaSettingsStatus, setFigmaSettingsStatus] = (0, import_react12.useState)("");
8973
- const [isFigmaSettingsOpen, setIsFigmaSettingsOpen] = (0, import_react12.useState)(false);
8974
- const [isFigmaTokenVisible, setIsFigmaTokenVisible] = (0, import_react12.useState)(false);
8975
- const [isFigmaTokenGuideOpen, setIsFigmaTokenGuideOpen] = (0, import_react12.useState)(false);
9316
+ const [reviewTheme, setReviewTheme] = (0, import_react13.useState)(getStoredReviewTheme);
9317
+ const [reviewThemeDraft, setReviewThemeDraft] = (0, import_react13.useState)(getStoredReviewTheme);
9318
+ const [systemReviewTheme, setSystemReviewTheme] = (0, import_react13.useState)(getSystemReviewTheme);
9319
+ const [figmaSettingsStatus, setFigmaSettingsStatus] = (0, import_react13.useState)("");
9320
+ const [isFigmaSettingsOpen, setIsFigmaSettingsOpen] = (0, import_react13.useState)(false);
9321
+ const [isFigmaTokenVisible, setIsFigmaTokenVisible] = (0, import_react13.useState)(false);
9322
+ const [isFigmaTokenGuideOpen, setIsFigmaTokenGuideOpen] = (0, import_react13.useState)(false);
8976
9323
  const effectiveReviewTheme = reviewTheme === "system" ? systemReviewTheme : reviewTheme;
8977
- const closeFigmaSettings = (0, import_react12.useCallback)(() => {
9324
+ const closeFigmaSettings = (0, import_react13.useCallback)(() => {
8978
9325
  setIsFigmaSettingsOpen(false);
8979
9326
  setFigmaSettingsStatus("");
8980
9327
  setIsFigmaTokenVisible(false);
8981
9328
  setIsFigmaTokenGuideOpen(false);
8982
9329
  }, []);
8983
- const openFigmaSettings = (0, import_react12.useCallback)(() => {
9330
+ const openFigmaSettings = (0, import_react13.useCallback)(() => {
8984
9331
  onCancelReviewMode();
8985
9332
  onCloseSitemap();
8986
9333
  onCloseInitialPrompt();
@@ -8997,7 +9344,7 @@ var useReviewSettings = ({
8997
9344
  onCloseSitemap,
8998
9345
  reviewTheme
8999
9346
  ]);
9000
- const saveReviewSettings = (0, import_react12.useCallback)(
9347
+ const saveReviewSettings = (0, import_react13.useCallback)(
9001
9348
  (token, userId, theme) => {
9002
9349
  const nextToken = token.trim();
9003
9350
  const nextUserId = userId.trim();
@@ -9021,7 +9368,7 @@ var useReviewSettings = ({
9021
9368
  },
9022
9369
  [closeFigmaSettings, onReloadTargetFrame]
9023
9370
  );
9024
- (0, import_react12.useEffect)(() => {
9371
+ (0, import_react13.useEffect)(() => {
9025
9372
  if (typeof window === "undefined" || !window.matchMedia) return void 0;
9026
9373
  const query = window.matchMedia("(prefers-color-scheme: light)");
9027
9374
  const syncSystemTheme = () => {
@@ -9035,7 +9382,7 @@ var useReviewSettings = ({
9035
9382
  query.addListener(syncSystemTheme);
9036
9383
  return () => query.removeListener(syncSystemTheme);
9037
9384
  }, []);
9038
- (0, import_react12.useEffect)(() => {
9385
+ (0, import_react13.useEffect)(() => {
9039
9386
  document.body.classList.toggle(
9040
9387
  "df-review-theme-light",
9041
9388
  effectiveReviewTheme === "light"
@@ -9074,7 +9421,7 @@ var useReviewSettings = ({
9074
9421
  };
9075
9422
 
9076
9423
  // src/react-shell/hooks/use.review.shell.data.ts
9077
- var import_react13 = require("react");
9424
+ var import_react14 = require("react");
9078
9425
  var createEmptySitemapQaCount = () => ({
9079
9426
  local: 0,
9080
9427
  remote: 0
@@ -9089,41 +9436,41 @@ var useReviewShellData = ({
9089
9436
  target,
9090
9437
  viewportPresets
9091
9438
  }) => {
9092
- const [items, setItems] = (0, import_react13.useState)([]);
9093
- const [hiddenOverlayItemIds, setHiddenOverlayItemIds] = (0, import_react13.useState)(
9439
+ const [items, setItems] = (0, import_react14.useState)([]);
9440
+ const [hiddenOverlayItemIds, setHiddenOverlayItemIds] = (0, import_react14.useState)(
9094
9441
  () => /* @__PURE__ */ new Set()
9095
9442
  );
9096
- const [qaFilter, setQaFilter] = (0, import_react13.useState)("all");
9097
- const [sitemapItems, setSitemapItems] = (0, import_react13.useState)(() => ({
9443
+ const [qaFilter, setQaFilter] = (0, import_react14.useState)("all");
9444
+ const [sitemapItems, setSitemapItems] = (0, import_react14.useState)(() => ({
9098
9445
  local: [],
9099
9446
  remote: []
9100
9447
  }));
9101
- const targetSrc = (0, import_react13.useMemo)(() => buildTargetSrc(target), [target]);
9102
- const pageTargets = (0, import_react13.useMemo)(
9448
+ const targetSrc = (0, import_react14.useMemo)(() => buildTargetSrc(target), [target]);
9449
+ const pageTargets = (0, import_react14.useMemo)(
9103
9450
  () => new Set(
9104
9451
  pages.map((page) => normalizeTarget(page.href, reviewPathPrefix))
9105
9452
  ),
9106
9453
  [pages, reviewPathPrefix]
9107
9454
  );
9108
- const activeItems = (0, import_react13.useMemo)(
9109
- () => items.filter((item) => getItemTarget(item, reviewPathPrefix) === activeRoute).sort((a, b) => b.updatedAt.localeCompare(a.updatedAt)),
9455
+ const activeItems = (0, import_react14.useMemo)(
9456
+ () => items.filter((item) => getItemTarget(item, reviewPathPrefix) === activeRoute).sort((a, b) => b.createdAt.localeCompare(a.createdAt)),
9110
9457
  [activeRoute, items, reviewPathPrefix]
9111
9458
  );
9112
- const numberedActiveItems = (0, import_react13.useMemo)(
9459
+ const numberedActiveItems = (0, import_react14.useMemo)(
9113
9460
  () => getNumberedReviewItems(activeItems, reviewViewportPresets),
9114
9461
  [activeItems, reviewViewportPresets]
9115
9462
  );
9116
- const filteredNumberedActiveItems = (0, import_react13.useMemo)(
9463
+ const filteredNumberedActiveItems = (0, import_react14.useMemo)(
9117
9464
  () => qaFilter === "all" ? numberedActiveItems : numberedActiveItems.filter(
9118
9465
  (numberedItem) => numberedItem.scope === qaFilter
9119
9466
  ),
9120
9467
  [numberedActiveItems, qaFilter]
9121
9468
  );
9122
- const hiddenOverlayItemIdList = (0, import_react13.useMemo)(
9469
+ const hiddenOverlayItemIdList = (0, import_react14.useMemo)(
9123
9470
  () => Array.from(hiddenOverlayItemIds),
9124
9471
  [hiddenOverlayItemIds]
9125
9472
  );
9126
- const qaFilterCounts = (0, import_react13.useMemo)(() => {
9473
+ const qaFilterCounts = (0, import_react14.useMemo)(() => {
9127
9474
  const counts = /* @__PURE__ */ new Map();
9128
9475
  counts.set("all", numberedActiveItems.length);
9129
9476
  numberedActiveItems.forEach((numberedItem) => {
@@ -9131,7 +9478,7 @@ var useReviewShellData = ({
9131
9478
  });
9132
9479
  return counts;
9133
9480
  }, [numberedActiveItems]);
9134
- const getItemPresetScope = (0, import_react13.useCallback)(
9481
+ const getItemPresetScope = (0, import_react14.useCallback)(
9135
9482
  (item) => getViewportPresetKind(
9136
9483
  findViewportPreset(
9137
9484
  viewportPresets,
@@ -9141,7 +9488,7 @@ var useReviewShellData = ({
9141
9488
  ),
9142
9489
  [viewportPresets]
9143
9490
  );
9144
- const presetScopeCounts = (0, import_react13.useMemo)(() => {
9491
+ const presetScopeCounts = (0, import_react14.useMemo)(() => {
9145
9492
  const counts = /* @__PURE__ */ new Map();
9146
9493
  activeItems.forEach((item) => {
9147
9494
  const scope = getItemPresetScope(item);
@@ -9150,7 +9497,7 @@ var useReviewShellData = ({
9150
9497
  return counts;
9151
9498
  }, [activeItems, getItemPresetScope]);
9152
9499
  const currentPresetScope = getViewportPresetKind(size);
9153
- const pageQaCounts = (0, import_react13.useMemo)(() => {
9500
+ const pageQaCounts = (0, import_react14.useMemo)(() => {
9154
9501
  const counts = /* @__PURE__ */ new Map();
9155
9502
  const addItems = (sourceKey, sourceItems) => {
9156
9503
  sourceItems.forEach((item) => {
@@ -9167,7 +9514,7 @@ var useReviewShellData = ({
9167
9514
  addItems("remote", sitemapItems.remote);
9168
9515
  return counts;
9169
9516
  }, [reviewPathPrefix, sitemapItems]);
9170
- const selectedNumberedItem = (0, import_react13.useMemo)(
9517
+ const selectedNumberedItem = (0, import_react14.useMemo)(
9171
9518
  () => selectedItemId ? numberedActiveItems.find(
9172
9519
  (numberedItem) => numberedItem.item.id === selectedItemId
9173
9520
  ) : void 0,
@@ -9195,7 +9542,7 @@ var useReviewShellData = ({
9195
9542
  };
9196
9543
 
9197
9544
  // src/react-shell/hooks/use.review.shell.hotkeys.ts
9198
- var import_react14 = require("react");
9545
+ var import_react15 = require("react");
9199
9546
  var useReviewShellHotkeys = ({
9200
9547
  isFigmaSettingsOpen,
9201
9548
  isInitialPromptOpen,
@@ -9212,7 +9559,7 @@ var useReviewShellHotkeys = ({
9212
9559
  onToggleRuler,
9213
9560
  onToggleTargetOverlay
9214
9561
  }) => {
9215
- (0, import_react14.useEffect)(() => {
9562
+ (0, import_react15.useEffect)(() => {
9216
9563
  if (mode === "idle" && !isRulerVisible && !isInitialPromptOpen && !isSitemapOpen && !isFigmaSettingsOpen) {
9217
9564
  return;
9218
9565
  }
@@ -9256,12 +9603,12 @@ var useReviewShellHotkeys = ({
9256
9603
  onCloseRuler,
9257
9604
  onCloseSitemap
9258
9605
  ]);
9259
- (0, import_react14.useEffect)(() => {
9606
+ (0, import_react15.useEffect)(() => {
9260
9607
  const handleHotkey = (event) => {
9261
9608
  if (event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) {
9262
9609
  return;
9263
9610
  }
9264
- if (isEditableEventTarget(event)) return;
9611
+ if (isEditableEventTarget2(event)) return;
9265
9612
  const actions = {
9266
9613
  r: () => {
9267
9614
  if (isRulerAvailable) onToggleRuler();
@@ -9288,7 +9635,7 @@ var useReviewShellHotkeys = ({
9288
9635
  };
9289
9636
 
9290
9637
  // src/react-shell/hooks/use.review.shell.state.ts
9291
- var import_react15 = require("react");
9638
+ var import_react16 = require("react");
9292
9639
 
9293
9640
  // src/react-shell/adapters.ts
9294
9641
  var ALL_REVIEW_WRITE_MODES = ["dom", "note", "area"];
@@ -9316,6 +9663,7 @@ function normalizeLegacyAdapterMap(adapters) {
9316
9663
  updateStatus: ({ id, status }) => adapters.local.update(id, { status }),
9317
9664
  syncSubmission: ({ id, patch }) => adapters.local.update(id, patch),
9318
9665
  writeModes: [...ALL_REVIEW_WRITE_MODES],
9666
+ canUpdate: true,
9319
9667
  canRemove: true
9320
9668
  };
9321
9669
  const remote = adapters.remote ? {
@@ -9324,6 +9672,7 @@ function normalizeLegacyAdapterMap(adapters) {
9324
9672
  statusOptions: [...REVIEW_WORKFLOW_STATUS_OPTIONS],
9325
9673
  updateStatus: ({ id, status }) => adapters.remote?.update(id, { status }) ?? Promise.reject(new Error("Remote adapter is not available.")),
9326
9674
  writeModes: [],
9675
+ canUpdate: true,
9327
9676
  canRemove: false,
9328
9677
  pageId: adapters.remotePageId
9329
9678
  } : null;
@@ -9349,6 +9698,7 @@ function normalizeShellAdapter(adapterConfig) {
9349
9698
  updateStatus,
9350
9699
  syncSubmission: adapterConfig.syncSubmission,
9351
9700
  writeModes,
9701
+ canUpdate: Boolean(updateAdapter),
9352
9702
  canRemove: Boolean(adapterConfig.remove),
9353
9703
  adapter: {
9354
9704
  get: adapterConfig.get,
@@ -9429,11 +9779,11 @@ var useReviewShellState = ({
9429
9779
  reviewPathPrefix
9430
9780
  }) => {
9431
9781
  const viewportPresets = presets.length > 0 ? presets : DEFAULT_REVIEW_VIEWPORT_PRESETS;
9432
- const reviewViewportPresets = (0, import_react15.useMemo)(
9782
+ const reviewViewportPresets = (0, import_react16.useMemo)(
9433
9783
  () => toReviewViewportPresets(viewportPresets),
9434
9784
  [viewportPresets]
9435
9785
  );
9436
- const normalizedAdapters = (0, import_react15.useMemo)(
9786
+ const normalizedAdapters = (0, import_react16.useMemo)(
9437
9787
  () => normalizeReviewShellAdapters(adapters),
9438
9788
  [adapters]
9439
9789
  );
@@ -9441,7 +9791,7 @@ var useReviewShellState = ({
9441
9791
  const remoteAdapterEntry = normalizedAdapters.remote;
9442
9792
  const sourceEntries = normalizedAdapters.sources;
9443
9793
  const defaultSource = sourceEntries[0]?.label ?? "local";
9444
- const [source, setSource] = (0, import_react15.useState)(() => {
9794
+ const [source, setSource] = (0, import_react16.useState)(() => {
9445
9795
  const initialSource = getInitialSource(remoteAdapterEntry?.label);
9446
9796
  return sourceEntries.some((entry) => entry.label === initialSource) ? initialSource : defaultSource;
9447
9797
  });
@@ -9451,54 +9801,50 @@ var useReviewShellState = ({
9451
9801
  remoteSource && activeAdapterEntry.label === remoteSource
9452
9802
  );
9453
9803
  const showSourceSelect = sourceEntries.length > 1;
9454
- const canWriteDom = activeAdapterEntry.writeModes.includes("dom");
9455
- const canWriteNote = activeAdapterEntry.writeModes.includes("note");
9456
9804
  const canWriteArea = activeAdapterEntry.writeModes.includes("area");
9457
- const canWriteAny = canWriteDom || canWriteNote || canWriteArea;
9805
+ const canWriteDom = activeAdapterEntry.writeModes.includes("dom");
9458
9806
  const adapter = activeAdapterEntry.adapter;
9459
- const iframeRef = (0, import_react15.useRef)(null);
9460
- const frameScrollRef = (0, import_react15.useRef)(null);
9461
- const controllerRef = (0, import_react15.useRef)(null);
9462
- const cleanupTargetRef = (0, import_react15.useRef)(null);
9463
- const pendingRestoreRef = (0, import_react15.useRef)(null);
9464
- const pendingInitialItemIdRef = (0, import_react15.useRef)(getInitialItemId());
9465
- const selectedItemIdRef = (0, import_react15.useRef)(getInitialItemId());
9466
- const hiddenOverlayItemIdListRef = (0, import_react15.useRef)([]);
9467
- const [target, setTarget] = (0, import_react15.useState)(
9807
+ const iframeRef = (0, import_react16.useRef)(null);
9808
+ const frameScrollRef = (0, import_react16.useRef)(null);
9809
+ const controllerRef = (0, import_react16.useRef)(null);
9810
+ const cleanupTargetRef = (0, import_react16.useRef)(null);
9811
+ const pendingRestoreRef = (0, import_react16.useRef)(null);
9812
+ const pendingInitialItemIdRef = (0, import_react16.useRef)(getInitialItemId());
9813
+ const selectedItemIdRef = (0, import_react16.useRef)(getInitialItemId());
9814
+ const hiddenOverlayItemIdListRef = (0, import_react16.useRef)([]);
9815
+ const [target, setTarget] = (0, import_react16.useState)(
9468
9816
  () => getInitialTarget(reviewPathPrefix)
9469
9817
  );
9470
- const [draftTarget, setDraftTarget] = (0, import_react15.useState)(
9818
+ const [draftTarget, setDraftTarget] = (0, import_react16.useState)(
9471
9819
  () => getInitialTarget(reviewPathPrefix)
9472
9820
  );
9473
- const [activeRoute, setActiveRoute] = (0, import_react15.useState)(
9821
+ const [activeRoute, setActiveRoute] = (0, import_react16.useState)(
9474
9822
  () => getInitialTarget(reviewPathPrefix)
9475
9823
  );
9476
- const [size, setSize] = (0, import_react15.useState)(
9824
+ const [size, setSize] = (0, import_react16.useState)(
9477
9825
  () => getInitialSize(viewportPresets)
9478
9826
  );
9479
- const [mode, setMode] = (0, import_react15.useState)("idle");
9480
- const [targetOverlayState, setTargetOverlayState] = (0, import_react15.useState)({
9827
+ const [mode, setMode] = (0, import_react16.useState)("idle");
9828
+ const [targetOverlayState, setTargetOverlayState] = (0, import_react16.useState)({
9481
9829
  grid: false,
9482
9830
  figma: false
9483
9831
  });
9484
- const [selectedItemId, setSelectedItemId] = (0, import_react15.useState)(getInitialItemId());
9485
- const [isListVisible, setIsListVisible] = (0, import_react15.useState)(true);
9486
- const [isSitemapOpen, setIsSitemapOpen] = (0, import_react15.useState)(false);
9487
- const [isInitialPromptOpen, setIsInitialPromptOpen] = (0, import_react15.useState)(false);
9488
- const [copyLabel, setCopyLabel] = (0, import_react15.useState)("Copy URL");
9489
- const [toastMessage, setToastMessage] = (0, import_react15.useState)("");
9490
- const [copiedPromptKey, setCopiedPromptKey] = (0, import_react15.useState)(null);
9491
- const targetRef = (0, import_react15.useRef)(target);
9492
- const sizeRef = (0, import_react15.useRef)(size);
9832
+ const [selectedItemId, setSelectedItemId] = (0, import_react16.useState)(getInitialItemId());
9833
+ const [isListVisible, setIsListVisible] = (0, import_react16.useState)(true);
9834
+ const [isSitemapOpen, setIsSitemapOpen] = (0, import_react16.useState)(false);
9835
+ const [isInitialPromptOpen, setIsInitialPromptOpen] = (0, import_react16.useState)(false);
9836
+ const [copyLabel, setCopyLabel] = (0, import_react16.useState)("Copy URL");
9837
+ const [toastMessage, setToastMessage] = (0, import_react16.useState)("");
9838
+ const [copiedPromptKey, setCopiedPromptKey] = (0, import_react16.useState)(null);
9839
+ const targetRef = (0, import_react16.useRef)(target);
9840
+ const sizeRef = (0, import_react16.useRef)(size);
9493
9841
  const isFigmaOverlayAvailable = getIsFigmaOverlayAvailable(size);
9494
9842
  return {
9495
9843
  activeAdapterEntry,
9496
9844
  activeRoute,
9497
9845
  adapter,
9498
- canWriteAny,
9499
9846
  canWriteArea,
9500
9847
  canWriteDom,
9501
- canWriteNote,
9502
9848
  cleanupTargetRef,
9503
9849
  controllerRef,
9504
9850
  copiedPromptKey,
@@ -9663,6 +10009,31 @@ var updateReviewItemStatus = async ({
9663
10009
  await onRefreshReviewData();
9664
10010
  onToast?.("QA status updated");
9665
10011
  };
10012
+ var updateReviewItemComment = async ({
10013
+ activeAdapterEntry,
10014
+ item,
10015
+ comment,
10016
+ onRefreshReviewData,
10017
+ onToast
10018
+ }) => {
10019
+ const nextComment = comment.trim();
10020
+ if (!nextComment) throw new Error("Comment is required.");
10021
+ if (!activeAdapterEntry.canUpdate) {
10022
+ throw new Error(
10023
+ `Review adapter "${activeAdapterEntry.label}" does not support edit.`
10024
+ );
10025
+ }
10026
+ if (nextComment === item.comment.trim()) {
10027
+ onToast?.("No QA comment changes");
10028
+ return item;
10029
+ }
10030
+ const updated = await activeAdapterEntry.adapter.update(item.id, {
10031
+ comment: nextComment
10032
+ });
10033
+ await onRefreshReviewData();
10034
+ onToast?.("QA comment updated");
10035
+ return updated;
10036
+ };
9666
10037
  var submitReviewItem = async ({
9667
10038
  localAdapterEntry,
9668
10039
  numberedItem,
@@ -9756,7 +10127,7 @@ var removeReviewItem = async ({
9756
10127
  };
9757
10128
 
9758
10129
  // src/react-shell/review/shell.tsx
9759
- var import_jsx_runtime16 = require("react/jsx-runtime");
10130
+ var import_jsx_runtime17 = require("react/jsx-runtime");
9760
10131
  var getReviewModeWriteMode = (mode) => {
9761
10132
  if (mode === "element") return "dom";
9762
10133
  if (mode === "note" || mode === "area") return mode;
@@ -9770,16 +10141,15 @@ var ReviewShell = ({
9770
10141
  ruler,
9771
10142
  initialPrompt = DEFAULT_INITIAL_REVIEW_PROMPT,
9772
10143
  reviewPathPrefix = DEFAULT_REVIEW_PATH_PREFIX,
10144
+ sourceRoot,
9773
10145
  presence
9774
10146
  }) => {
9775
10147
  const {
9776
10148
  activeAdapterEntry,
9777
10149
  activeRoute,
9778
10150
  adapter,
9779
- canWriteAny,
9780
10151
  canWriteArea,
9781
10152
  canWriteDom,
9782
- canWriteNote,
9783
10153
  cleanupTargetRef,
9784
10154
  controllerRef,
9785
10155
  copiedPromptKey,
@@ -9830,6 +10200,7 @@ var ReviewShell = ({
9830
10200
  presets,
9831
10201
  reviewPathPrefix
9832
10202
  });
10203
+ const sourceShortcutCleanupRef = (0, import_react17.useRef)(null);
9833
10204
  const {
9834
10205
  activeItems,
9835
10206
  currentPresetScope,
@@ -9858,8 +10229,9 @@ var ReviewShell = ({
9858
10229
  target,
9859
10230
  viewportPresets
9860
10231
  });
10232
+ const [editingItem, setEditingItem] = (0, import_react17.useState)(null);
9861
10233
  const initialPromptText = initialPrompt.trim();
9862
- const refreshItems = (0, import_react16.useCallback)(
10234
+ const refreshItems = (0, import_react17.useCallback)(
9863
10235
  () => refreshReviewItems({
9864
10236
  activeRoute,
9865
10237
  adapter,
@@ -9870,7 +10242,7 @@ var ReviewShell = ({
9870
10242
  }),
9871
10243
  [activeAdapterEntry.pageId, activeRoute, adapter, isRemoteSource, projectId]
9872
10244
  );
9873
- const refreshSitemapItems = (0, import_react16.useCallback)(
10245
+ const refreshSitemapItems = (0, import_react17.useCallback)(
9874
10246
  () => refreshSitemapReviewItems({
9875
10247
  localAdapterEntry,
9876
10248
  projectId,
@@ -9879,20 +10251,20 @@ var ReviewShell = ({
9879
10251
  }),
9880
10252
  [localAdapterEntry, projectId, remoteAdapterEntry]
9881
10253
  );
9882
- const cancelReviewMode = (0, import_react16.useCallback)(() => {
10254
+ const cancelReviewMode = (0, import_react17.useCallback)(() => {
9883
10255
  const controller = controllerRef.current;
9884
10256
  if (!controller || controller.getMode() === "idle") return false;
9885
10257
  controller.setMode("idle");
9886
10258
  setMode(controller.getMode());
9887
10259
  return true;
9888
10260
  }, []);
9889
- const closePromptModal = (0, import_react16.useCallback)(() => {
10261
+ const closePromptModal = (0, import_react17.useCallback)(() => {
9890
10262
  setIsInitialPromptOpen(false);
9891
10263
  }, []);
9892
- const closeSitemap = (0, import_react16.useCallback)(() => {
10264
+ const closeSitemap = (0, import_react17.useCallback)(() => {
9893
10265
  setIsSitemapOpen(false);
9894
10266
  }, []);
9895
- const reloadTargetFrame = (0, import_react16.useCallback)(() => {
10267
+ const reloadTargetFrame = (0, import_react17.useCallback)(() => {
9896
10268
  try {
9897
10269
  iframeRef.current?.contentWindow?.location.reload();
9898
10270
  } catch {
@@ -9939,7 +10311,7 @@ var ReviewShell = ({
9939
10311
  size,
9940
10312
  source
9941
10313
  });
9942
- const closeRulerPanels = (0, import_react16.useCallback)(() => {
10314
+ const closeRulerPanels = (0, import_react17.useCallback)(() => {
9943
10315
  closeSitemap();
9944
10316
  closeFigmaSettings();
9945
10317
  }, [closeFigmaSettings, closeSitemap]);
@@ -10009,14 +10381,14 @@ var ReviewShell = ({
10009
10381
  onTargetChange: setTarget,
10010
10382
  onTargetOverlayStateChange: setTargetOverlayState
10011
10383
  });
10012
- const refreshReviewData2 = (0, import_react16.useCallback)(() => {
10384
+ const refreshReviewData2 = (0, import_react17.useCallback)(() => {
10013
10385
  return refreshReviewData({
10014
10386
  onRefreshItems: refreshItems,
10015
10387
  onRefreshSitemapItems: refreshSitemapItems,
10016
10388
  onReloadReviewKit: reloadReviewKit
10017
10389
  });
10018
10390
  }, [refreshItems, refreshSitemapItems, reloadReviewKit]);
10019
- const toggleItemOverlayVisibility = (0, import_react16.useCallback)((itemId) => {
10391
+ const toggleItemOverlayVisibility = (0, import_react17.useCallback)((itemId) => {
10020
10392
  setHiddenOverlayItemIds((currentHiddenOverlayItemIds) => {
10021
10393
  const nextHiddenItemIds = new Set(currentHiddenOverlayItemIds);
10022
10394
  if (nextHiddenItemIds.has(itemId)) {
@@ -10027,17 +10399,17 @@ var ReviewShell = ({
10027
10399
  return nextHiddenItemIds;
10028
10400
  });
10029
10401
  }, []);
10030
- (0, import_react16.useEffect)(() => {
10402
+ (0, import_react17.useEffect)(() => {
10031
10403
  void refreshItems();
10032
10404
  }, [refreshItems]);
10033
- (0, import_react16.useEffect)(() => {
10405
+ (0, import_react17.useEffect)(() => {
10034
10406
  void refreshSitemapItems();
10035
10407
  }, [refreshSitemapItems]);
10036
- (0, import_react16.useEffect)(() => {
10408
+ (0, import_react17.useEffect)(() => {
10037
10409
  if (!isSitemapOpen) return;
10038
10410
  void refreshSitemapItems();
10039
10411
  }, [isSitemapOpen, refreshSitemapItems]);
10040
- (0, import_react16.useEffect)(() => {
10412
+ (0, import_react17.useEffect)(() => {
10041
10413
  const frameScroll = frameScrollRef.current;
10042
10414
  if (!frameScroll) return void 0;
10043
10415
  const centerFrameScroll = () => {
@@ -10102,7 +10474,7 @@ var ReviewShell = ({
10102
10474
  const copyCurrentUrl = () => copyCurrentReviewUrl({
10103
10475
  onCopyLabelChange: setCopyLabel
10104
10476
  });
10105
- const showToast = (0, import_react16.useCallback)(
10477
+ const showToast = (0, import_react17.useCallback)(
10106
10478
  (message) => {
10107
10479
  setToastMessage(message);
10108
10480
  window.setTimeout(() => {
@@ -10111,7 +10483,223 @@ var ReviewShell = ({
10111
10483
  },
10112
10484
  [setToastMessage]
10113
10485
  );
10114
- const clearSelectedReviewItem = (0, import_react16.useCallback)(() => {
10486
+ const cleanupSourceOpenShortcut = (0, import_react17.useCallback)(() => {
10487
+ sourceShortcutCleanupRef.current?.();
10488
+ sourceShortcutCleanupRef.current = null;
10489
+ }, []);
10490
+ const bindSourceOpenShortcut = (0, import_react17.useCallback)(() => {
10491
+ cleanupSourceOpenShortcut();
10492
+ let frameDocument = null;
10493
+ try {
10494
+ frameDocument = iframeRef.current?.contentDocument ?? null;
10495
+ } catch {
10496
+ return;
10497
+ }
10498
+ if (!frameDocument) return;
10499
+ const hoverAttribute = "data-dfwr-source-hover";
10500
+ const optionAttribute = "data-dfwr-source-option";
10501
+ const fontOverlayAttribute = "data-dfwr-source-fonts";
10502
+ const style = frameDocument.createElement("style");
10503
+ style.dataset.dfwrSourceOpenShortcut = "true";
10504
+ style.textContent = `
10505
+ html[${optionAttribute}="true"],
10506
+ html[${optionAttribute}="true"] * {
10507
+ cursor: crosshair !important;
10508
+ }
10509
+
10510
+ html[${optionAttribute}="true"] body::before {
10511
+ position: fixed !important;
10512
+ z-index: 2147483647 !important;
10513
+ top: 10px !important;
10514
+ left: 50% !important;
10515
+ transform: translateX(-50%) !important;
10516
+ display: block !important;
10517
+ border: 1px solid rgba(124, 199, 255, 0.72) !important;
10518
+ border-radius: 999px !important;
10519
+ padding: 6px 10px !important;
10520
+ color: #ffffff !important;
10521
+ background: rgba(15, 23, 42, 0.86) !important;
10522
+ box-shadow: 0 10px 28px rgba(0, 0, 0, 0.24) !important;
10523
+ content: "Source select" !important;
10524
+ font: 700 12px/1 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif !important;
10525
+ pointer-events: none !important;
10526
+ }
10527
+
10528
+ [${hoverAttribute}="true"] {
10529
+ outline: 2px solid rgba(124, 199, 255, 0.96) !important;
10530
+ outline-offset: 2px !important;
10531
+ }
10532
+
10533
+ [${fontOverlayAttribute}] {
10534
+ position: fixed !important;
10535
+ z-index: 2147483647 !important;
10536
+ display: flex !important;
10537
+ flex-direction: column !important;
10538
+ max-width: 180px !important;
10539
+ border: 1px solid rgba(124, 199, 255, 0.72) !important;
10540
+ border-radius: 6px !important;
10541
+ padding: 4px 6px !important;
10542
+ color: #ffffff !important;
10543
+ background: rgba(15, 23, 42, 0.9) !important;
10544
+ box-shadow: 0 8px 22px rgba(0, 0, 0, 0.28) !important;
10545
+ font: 800 11px/1.35 ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace !important;
10546
+ pointer-events: none !important;
10547
+ white-space: nowrap !important;
10548
+ }
10549
+
10550
+ [${fontOverlayAttribute}] > span {
10551
+ display: flex !important;
10552
+ justify-content: space-between !important;
10553
+ gap: 10px !important;
10554
+ }
10555
+
10556
+ [${fontOverlayAttribute}][hidden] {
10557
+ display: none !important;
10558
+ }
10559
+ `;
10560
+ (frameDocument.head ?? frameDocument.documentElement).append(style);
10561
+ const fontOverlay = frameDocument.createElement("div");
10562
+ fontOverlay.setAttribute(fontOverlayAttribute, "true");
10563
+ fontOverlay.hidden = true;
10564
+ (frameDocument.body ?? frameDocument.documentElement).append(fontOverlay);
10565
+ let hoveredElement = null;
10566
+ let lastSourceElement = null;
10567
+ let isSourceSelecting = false;
10568
+ const getFontHints = (element) => {
10569
+ if (!element) return [];
10570
+ const values = [];
10571
+ const addValue = (target2) => {
10572
+ const value = target2.getAttribute("data-font")?.trim();
10573
+ const tag = target2.tagName.toLowerCase();
10574
+ if (value && !values.some((item) => item.tag === tag && item.value === value)) {
10575
+ values.push({ tag, value });
10576
+ }
10577
+ };
10578
+ addValue(element);
10579
+ element.querySelectorAll("[data-font]").forEach(addValue);
10580
+ return values;
10581
+ };
10582
+ const updateFontOverlay = (element) => {
10583
+ const values = isSourceSelecting ? getFontHints(element) : [];
10584
+ if (!values.length || !element) {
10585
+ fontOverlay.hidden = true;
10586
+ return;
10587
+ }
10588
+ const rect = element.getBoundingClientRect();
10589
+ const frameWidth = frameDocument.documentElement.clientWidth;
10590
+ const showAbove = rect.top > 48;
10591
+ const left = Math.max(4, Math.min(rect.left, frameWidth - 96));
10592
+ const top = Math.max(4, showAbove ? rect.top : rect.bottom);
10593
+ fontOverlay.replaceChildren();
10594
+ fontOverlay.style.minWidth = "72px";
10595
+ const rows = values.map(({ tag, value }) => {
10596
+ const row = frameDocument.createElement("span");
10597
+ const tagText = frameDocument.createElement("span");
10598
+ const valueText = frameDocument.createElement("span");
10599
+ tagText.textContent = tag;
10600
+ valueText.textContent = value;
10601
+ row.append(tagText, valueText);
10602
+ return row;
10603
+ });
10604
+ fontOverlay.append(...rows);
10605
+ fontOverlay.style.left = `${left}px`;
10606
+ fontOverlay.style.top = `${top}px`;
10607
+ fontOverlay.style.transform = showAbove ? "translateY(calc(-100% - 6px))" : "translateY(6px)";
10608
+ fontOverlay.hidden = false;
10609
+ };
10610
+ const setHoveredElement = (element) => {
10611
+ if (hoveredElement !== element) {
10612
+ hoveredElement?.removeAttribute(hoverAttribute);
10613
+ hoveredElement = element;
10614
+ hoveredElement?.setAttribute(hoverAttribute, "true");
10615
+ }
10616
+ updateFontOverlay(element);
10617
+ };
10618
+ const setSourceSelecting = (isSelecting) => {
10619
+ isSourceSelecting = isSelecting;
10620
+ if (isSelecting) {
10621
+ frameDocument.documentElement.setAttribute(optionAttribute, "true");
10622
+ setHoveredElement(lastSourceElement);
10623
+ return;
10624
+ }
10625
+ setHoveredElement(null);
10626
+ fontOverlay.hidden = true;
10627
+ frameDocument.documentElement.removeAttribute(optionAttribute);
10628
+ };
10629
+ const handleMouseMove = (event) => {
10630
+ lastSourceElement = getSourceHintElement(event.target);
10631
+ if (event.altKey && !isSourceSelecting) {
10632
+ setSourceSelecting(true);
10633
+ }
10634
+ setHoveredElement(isSourceSelecting ? lastSourceElement : null);
10635
+ };
10636
+ const handleClick = (event) => {
10637
+ if (!isSourceSelecting && !event.altKey) return;
10638
+ event.preventDefault();
10639
+ event.stopPropagation();
10640
+ event.stopImmediatePropagation();
10641
+ const source2 = getElementSourceHint(event.target);
10642
+ if (!source2?.file) {
10643
+ showToast("Source hint not found");
10644
+ setSourceSelecting(false);
10645
+ return;
10646
+ }
10647
+ const didOpen = openSourceInEditor(source2, sourceRoot);
10648
+ showToast(didOpen ? "Source opened" : "Source root required");
10649
+ setSourceSelecting(false);
10650
+ };
10651
+ const isOptionKeyEvent = (event) => event.key === "Alt" || event.code === "AltLeft" || event.code === "AltRight" || event.altKey;
10652
+ const handleKeyDown = (event) => {
10653
+ if (!isOptionKeyEvent(event)) return;
10654
+ cancelReviewMode();
10655
+ setSourceSelecting(true);
10656
+ };
10657
+ const handleKeyUp = (event) => {
10658
+ if (isOptionKeyEvent(event) || !event.altKey) setSourceSelecting(false);
10659
+ };
10660
+ const handleBlur = () => {
10661
+ setSourceSelecting(false);
10662
+ };
10663
+ frameDocument.addEventListener("mousemove", handleMouseMove, true);
10664
+ frameDocument.addEventListener("click", handleClick, true);
10665
+ frameDocument.addEventListener("keydown", handleKeyDown, true);
10666
+ frameDocument.addEventListener("keyup", handleKeyUp, true);
10667
+ frameDocument.defaultView?.addEventListener("blur", handleBlur);
10668
+ window.addEventListener("keydown", handleKeyDown, true);
10669
+ window.addEventListener("keyup", handleKeyUp, true);
10670
+ window.addEventListener("blur", handleBlur);
10671
+ sourceShortcutCleanupRef.current = () => {
10672
+ frameDocument.removeEventListener("mousemove", handleMouseMove, true);
10673
+ frameDocument.removeEventListener("click", handleClick, true);
10674
+ frameDocument.removeEventListener("keydown", handleKeyDown, true);
10675
+ frameDocument.removeEventListener("keyup", handleKeyUp, true);
10676
+ frameDocument.defaultView?.removeEventListener("blur", handleBlur);
10677
+ window.removeEventListener("keydown", handleKeyDown, true);
10678
+ window.removeEventListener("keyup", handleKeyUp, true);
10679
+ window.removeEventListener("blur", handleBlur);
10680
+ setSourceSelecting(false);
10681
+ style.remove();
10682
+ fontOverlay.remove();
10683
+ };
10684
+ }, [
10685
+ cancelReviewMode,
10686
+ cleanupSourceOpenShortcut,
10687
+ iframeRef,
10688
+ showToast,
10689
+ sourceRoot
10690
+ ]);
10691
+ (0, import_react17.useEffect)(() => {
10692
+ return cleanupSourceOpenShortcut;
10693
+ }, [cleanupSourceOpenShortcut]);
10694
+ const loadTargetFrame = (0, import_react17.useCallback)(() => {
10695
+ initReviewKit();
10696
+ bindSourceOpenShortcut();
10697
+ }, [bindSourceOpenShortcut, initReviewKit]);
10698
+ (0, import_react17.useEffect)(() => {
10699
+ const frame = window.requestAnimationFrame(bindSourceOpenShortcut);
10700
+ return () => window.cancelAnimationFrame(frame);
10701
+ }, [bindSourceOpenShortcut, targetSrc]);
10702
+ const clearSelectedReviewItem = (0, import_react17.useCallback)(() => {
10115
10703
  clearSelectedItem();
10116
10704
  updateShellUrl(targetRef.current, sizeRef.current, source);
10117
10705
  }, [clearSelectedItem, sizeRef, source, targetRef]);
@@ -10130,6 +10718,16 @@ var ReviewShell = ({
10130
10718
  onRefreshReviewData: refreshReviewData2,
10131
10719
  onToast: showToast
10132
10720
  });
10721
+ const saveItemComment = async (item, comment) => {
10722
+ await updateReviewItemComment({
10723
+ activeAdapterEntry,
10724
+ item,
10725
+ comment,
10726
+ onRefreshReviewData: refreshReviewData2,
10727
+ onToast: showToast
10728
+ });
10729
+ setEditingItem(null);
10730
+ };
10133
10731
  const submitItem = (numberedItem) => submitReviewItem({
10134
10732
  localAdapterEntry,
10135
10733
  numberedItem,
@@ -10163,12 +10761,12 @@ var ReviewShell = ({
10163
10761
  onRefreshReviewData: refreshReviewData2,
10164
10762
  onToast: showToast
10165
10763
  });
10166
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
10764
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
10167
10765
  "div",
10168
10766
  {
10169
10767
  className: `df-review-shell is-theme-${effectiveReviewTheme}${isListVisible ? " is-list-visible" : ""}`,
10170
10768
  children: [
10171
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
10769
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
10172
10770
  ReviewTopbar,
10173
10771
  {
10174
10772
  draftTarget,
@@ -10193,7 +10791,7 @@ var ReviewShell = ({
10193
10791
  onOpenSettings: openFigmaSettings
10194
10792
  }
10195
10793
  ),
10196
- isSitemapOpen && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
10794
+ isSitemapOpen && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
10197
10795
  SitemapModal,
10198
10796
  {
10199
10797
  pages,
@@ -10205,7 +10803,7 @@ var ReviewShell = ({
10205
10803
  onSelectPage: selectPage
10206
10804
  }
10207
10805
  ),
10208
- isFigmaSettingsOpen && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
10806
+ isFigmaSettingsOpen && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
10209
10807
  ReviewSettingsModal,
10210
10808
  {
10211
10809
  figmaTokenDraft,
@@ -10224,7 +10822,7 @@ var ReviewShell = ({
10224
10822
  onSave: saveReviewSettings
10225
10823
  }
10226
10824
  ),
10227
- isInitialPromptOpen && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
10825
+ isInitialPromptOpen && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
10228
10826
  PromptModal,
10229
10827
  {
10230
10828
  initialPromptText,
@@ -10233,8 +10831,16 @@ var ReviewShell = ({
10233
10831
  onCopyPrompt: (text, key) => void copyPrompt(text, key)
10234
10832
  }
10235
10833
  ),
10236
- toastMessage && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "df-review-copy-toast", role: "status", children: toastMessage }),
10237
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "df-review-side-rail", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
10834
+ editingItem && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
10835
+ QaItemEditModal,
10836
+ {
10837
+ item: editingItem,
10838
+ onClose: () => setEditingItem(null),
10839
+ onSave: saveItemComment
10840
+ }
10841
+ ),
10842
+ toastMessage && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "df-review-copy-toast", role: "status", children: toastMessage }),
10843
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "df-review-side-rail", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
10238
10844
  "button",
10239
10845
  {
10240
10846
  "aria-label": isListVisible ? "Hide QA list" : "Show QA list",
@@ -10242,12 +10848,12 @@ var ReviewShell = ({
10242
10848
  type: "button",
10243
10849
  onClick: () => setIsListVisible((current) => !current),
10244
10850
  children: [
10245
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(GripVertical, {}) }),
10246
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("strong", { children: "QA" })
10851
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(GripVertical, {}) }),
10852
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("strong", { children: "QA" })
10247
10853
  ]
10248
10854
  }
10249
10855
  ) }),
10250
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
10856
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
10251
10857
  ReviewQaPanel,
10252
10858
  {
10253
10859
  activeAdapterEntry,
@@ -10266,12 +10872,14 @@ var ReviewShell = ({
10266
10872
  remoteAdapterEntry,
10267
10873
  selectedItemId,
10268
10874
  showSourceSelect,
10875
+ sourceRoot,
10269
10876
  source,
10270
10877
  sourceEntries,
10271
10878
  onChangeItemStatus: changeItemStatus,
10272
10879
  onClearSelectedItem: clearSelectedReviewItem,
10273
10880
  onChangeReviewSource: changeReviewSource,
10274
10881
  onCopyItemPrompt: (numberedItem) => void copyItemPrompt(numberedItem),
10882
+ onEditItem: setEditingItem,
10275
10883
  onQaFilterChange: setQaFilter,
10276
10884
  onRefreshReviewData: refreshReviewData2,
10277
10885
  onRemoveItem: removeItem,
@@ -10280,13 +10888,11 @@ var ReviewShell = ({
10280
10888
  onToggleItemOverlayVisibility: toggleItemOverlayVisibility
10281
10889
  }
10282
10890
  ),
10283
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
10891
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
10284
10892
  ReviewTargetFrame,
10285
10893
  {
10286
- canWriteAny,
10287
10894
  canWriteArea,
10288
10895
  canWriteDom,
10289
- canWriteNote,
10290
10896
  frameScrollRef,
10291
10897
  iframeRef,
10292
10898
  isRulerAvailable,
@@ -10302,7 +10908,7 @@ var ReviewShell = ({
10302
10908
  rulerUnit,
10303
10909
  size,
10304
10910
  targetSrc,
10305
- onLoadTarget: initReviewKit,
10911
+ onLoadTarget: loadTargetFrame,
10306
10912
  onSetReviewMode: setReviewMode
10307
10913
  }
10308
10914
  )
@@ -10485,7 +11091,7 @@ var createSupabasePresenceAdapter = ({
10485
11091
  });
10486
11092
 
10487
11093
  // src/react-shell.tsx
10488
- var import_jsx_runtime17 = require("react/jsx-runtime");
11094
+ var import_jsx_runtime18 = require("react/jsx-runtime");
10489
11095
  var mountReviewShell = (options) => {
10490
11096
  if (typeof document === "undefined" || !document.head) return;
10491
11097
  const { rootId = "root", ...shellProps } = options;
@@ -10496,7 +11102,7 @@ var mountReviewShell = (options) => {
10496
11102
  root.style.height = "100%";
10497
11103
  root.style.margin = "0";
10498
11104
  (0, import_client.createRoot)(root).render(
10499
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_react17.default.StrictMode, { children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ReviewShell, { ...shellProps }) })
11105
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react18.default.StrictMode, { children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ReviewShell, { ...shellProps }) })
10500
11106
  );
10501
11107
  };
10502
11108
  // Annotate the CommonJS export names for ESM import in node:
@@ -10525,6 +11131,7 @@ lucide-react/dist/esm/icons/copy.mjs:
10525
11131
  lucide-react/dist/esm/icons/external-link.mjs:
10526
11132
  lucide-react/dist/esm/icons/eye-off.mjs:
10527
11133
  lucide-react/dist/esm/icons/eye.mjs:
11134
+ lucide-react/dist/esm/icons/file-code-corner.mjs:
10528
11135
  lucide-react/dist/esm/icons/grip-vertical.mjs:
10529
11136
  lucide-react/dist/esm/icons/image.mjs:
10530
11137
  lucide-react/dist/esm/icons/layout-grid.mjs:
@@ -10532,6 +11139,7 @@ lucide-react/dist/esm/icons/list-filter.mjs:
10532
11139
  lucide-react/dist/esm/icons/map.mjs:
10533
11140
  lucide-react/dist/esm/icons/maximize-2.mjs:
10534
11141
  lucide-react/dist/esm/icons/monitor.mjs:
11142
+ lucide-react/dist/esm/icons/pencil.mjs:
10535
11143
  lucide-react/dist/esm/icons/rectangle-horizontal.mjs:
10536
11144
  lucide-react/dist/esm/icons/refresh-cw.mjs:
10537
11145
  lucide-react/dist/esm/icons/ruler.mjs: