@designfever/web-review-kit 0.4.0 → 0.5.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.
@@ -1,9 +1,11 @@
1
1
  import {
2
2
  REVIEW_WORKFLOW_STATUS_OPTIONS,
3
+ clamp,
3
4
  createWebReviewKit,
4
5
  getNumberedReviewItems,
5
- normalizeReviewItemStatus
6
- } from "./chunk-QFNYQCTA.js";
6
+ normalizeReviewItemStatus,
7
+ runWithAutoScrollBehavior
8
+ } from "./chunk-TWCSIBMY.js";
7
9
 
8
10
  // src/react-shell.tsx
9
11
  import React2 from "react";
@@ -68,10 +70,10 @@ function ensureReviewShellStyle() {
68
70
  --df-review-font-size-lg: 14px;
69
71
  --df-review-font-size-xl: 15px;
70
72
  --df-review-font-size-2xl: 18px;
71
- --df-review-font-weight-medium: 650;
72
- --df-review-font-weight-bold: 700;
73
- --df-review-font-weight-strong: 800;
74
- --df-review-font-weight-heavy: 900;
73
+ --df-review-font-weight-medium: 400;
74
+ --df-review-font-weight-bold: 500;
75
+ --df-review-font-weight-strong: 500;
76
+ --df-review-font-weight-heavy: 600;
75
77
  --df-review-line-height-tight: 1.25;
76
78
  --df-review-line-height-base: 1.42;
77
79
  --df-review-line-height-relaxed: 1.55;
@@ -88,7 +90,7 @@ function ensureReviewShellStyle() {
88
90
  --df-review-space-8: 32px;
89
91
  --df-review-control-height-sm: 32px;
90
92
  --df-review-control-height-md: 34px;
91
- --df-review-control-height-lg: 38px;
93
+ --df-review-control-height-lg: 34px;
92
94
  --df-review-radius-xs: 3px;
93
95
  --df-review-radius-sm: 6px;
94
96
  --df-review-radius-md: 8px;
@@ -152,6 +154,7 @@ function ensureReviewShellStyle() {
152
154
 
153
155
  /* Semantic aliases consumed by the existing shell chrome. */
154
156
  --df-review-bg: var(--df-review-color-canvas);
157
+ --df-review-surface: var(--df-review-color-surface);
155
158
  --df-review-topbar: var(--df-review-color-surface);
156
159
  --df-review-panel: var(--df-review-color-panel);
157
160
  --df-review-panel-strong: var(--df-review-color-panel-strong);
@@ -261,7 +264,7 @@ function ensureReviewShellStyle() {
261
264
  .df-review-shell {
262
265
  --df-review-frame-gutter-x: var(--df-review-space-4);
263
266
  display: grid;
264
- grid-template-columns: minmax(0, 1fr) 0 32px;
267
+ grid-template-columns: minmax(0, 1fr) 0 48px;
265
268
  grid-template-rows: auto auto minmax(0, 1fr);
266
269
  width: 100%;
267
270
  height: 100%;
@@ -270,7 +273,7 @@ function ensureReviewShellStyle() {
270
273
  }
271
274
 
272
275
  .df-review-shell.is-list-visible {
273
- grid-template-columns: minmax(0, 1fr) clamp(320px, 28vw, 420px) 32px;
276
+ grid-template-columns: minmax(0, 1fr) clamp(320px, 28vw, 420px) 48px;
274
277
  }
275
278
 
276
279
  .df-review-topbar {
@@ -289,20 +292,6 @@ function ensureReviewShellStyle() {
289
292
  box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.025);
290
293
  }
291
294
 
292
- .df-review-presence-row {
293
- grid-column: 1;
294
- grid-row: 2;
295
- position: relative;
296
- z-index: 590;
297
- display: flex;
298
- align-items: center;
299
- justify-content: flex-start;
300
- min-width: 0;
301
- padding: var(--df-review-space-2) var(--df-review-frame-gutter-x);
302
- border-bottom: 1px solid var(--df-review-line-soft);
303
- background: var(--df-review-panel);
304
- }
305
-
306
295
  .df-review-address {
307
296
  display: grid;
308
297
  grid-template-columns: auto minmax(160px, 1fr) auto auto;
@@ -315,6 +304,7 @@ function ensureReviewShellStyle() {
315
304
 
316
305
  .df-review-address input {
317
306
  width: 100%;
307
+ height: var(--df-review-control-height-md);
318
308
  min-height: var(--df-review-control-height-md);
319
309
  border: 1px solid var(--df-review-line);
320
310
  border-radius: var(--df-review-radius-sm);
@@ -332,7 +322,6 @@ function ensureReviewShellStyle() {
332
322
  }
333
323
 
334
324
  .df-review-address button,
335
- .df-review-side-toggle,
336
325
  .df-review-presets button,
337
326
  .df-review-overlay-button,
338
327
  .df-review-mode-button,
@@ -341,6 +330,7 @@ function ensureReviewShellStyle() {
341
330
  .df-review-settings-actions button,
342
331
  .df-review-prompt-block-header button,
343
332
  .df-review-item-actions button {
333
+ height: var(--df-review-control-height-md);
344
334
  min-height: var(--df-review-control-height-md);
345
335
  border: 1px solid var(--df-review-line);
346
336
  border-radius: var(--df-review-radius-sm);
@@ -348,12 +338,11 @@ function ensureReviewShellStyle() {
348
338
  box-shadow: var(--df-review-shadow-control);
349
339
  color: var(--df-review-text);
350
340
  font-size: var(--df-review-font-size-sm);
351
- font-weight: 700;
341
+ font-weight: 500;
352
342
  transition: border-color 140ms ease, background 140ms ease, color 140ms ease, box-shadow 140ms ease, opacity 140ms ease;
353
343
  }
354
344
 
355
345
  .df-review-address button:hover,
356
- .df-review-side-toggle:hover,
357
346
  .df-review-presets button:hover,
358
347
  .df-review-overlay-button:hover,
359
348
  .df-review-mode-button:hover,
@@ -454,12 +443,13 @@ function ensureReviewShellStyle() {
454
443
 
455
444
  .df-review-sitemap-header strong {
456
445
  font-size: var(--df-review-font-size-lg);
446
+ font-weight: 600;
457
447
  }
458
448
 
459
449
  .df-review-sitemap-header span {
460
450
  color: var(--df-review-muted);
461
451
  font-size: var(--df-review-font-size-sm);
462
- font-weight: 700;
452
+ font-weight: 500;
463
453
  }
464
454
 
465
455
  .df-review-sitemap-header button {
@@ -473,7 +463,7 @@ function ensureReviewShellStyle() {
473
463
  background: var(--df-review-control);
474
464
  color: var(--df-review-text);
475
465
  font-size: var(--df-review-font-size-md);
476
- font-weight: 800;
466
+ font-weight: 500;
477
467
  }
478
468
 
479
469
  .df-review-sitemap-header button:hover {
@@ -501,15 +491,18 @@ function ensureReviewShellStyle() {
501
491
  background: var(--df-review-control);
502
492
  box-shadow: var(--df-review-shadow-control);
503
493
  font-size: var(--df-review-font-size-xs);
504
- font-weight: 850;
494
+ font-weight: 600;
505
495
  }
506
496
 
507
497
  .df-review-sitemap-list {
508
498
  --df-review-sitemap-grid-template: minmax(190px, 1fr) 74px 78px 64px minmax(108px, 160px);
499
+ position: relative;
509
500
  display: grid;
510
501
  align-content: start;
511
502
  min-height: 0;
512
- overflow: auto;
503
+ overflow-x: hidden;
504
+ overflow-y: auto;
505
+ overscroll-behavior: contain;
513
506
  padding: 8px;
514
507
  }
515
508
 
@@ -524,14 +517,17 @@ function ensureReviewShellStyle() {
524
517
  .df-review-sitemap-table-head {
525
518
  position: sticky;
526
519
  top: 0;
527
- z-index: 1;
520
+ z-index: 3;
528
521
  min-height: 32px;
529
522
  border-bottom: 1px solid var(--df-review-line);
530
523
  padding: 0 10px;
531
- background: var(--df-review-surface);
524
+ background: var(--df-review-panel);
525
+ box-shadow:
526
+ 0 -8px 0 0 var(--df-review-panel),
527
+ 0 1px 0 var(--df-review-line);
532
528
  color: var(--df-review-muted);
533
529
  font-size: var(--df-review-font-size-xs);
534
- font-weight: 720;
530
+ font-weight: 500;
535
531
  letter-spacing: 0.03em;
536
532
  text-transform: uppercase;
537
533
  }
@@ -599,10 +595,13 @@ function ensureReviewShellStyle() {
599
595
  .df-review-sitemap-row.is-summary {
600
596
  position: sticky;
601
597
  bottom: 0;
602
- z-index: 1;
598
+ z-index: 3;
603
599
  border-top: 1px solid var(--df-review-line);
604
600
  border-bottom: 0;
605
- background: var(--df-review-surface);
601
+ background: var(--df-review-panel);
602
+ box-shadow:
603
+ 0 8px 0 0 var(--df-review-panel),
604
+ 0 -1px 0 var(--df-review-line);
606
605
  }
607
606
 
608
607
  .df-review-sitemap-row.is-folder {
@@ -626,7 +625,7 @@ function ensureReviewShellStyle() {
626
625
  overflow-wrap: anywhere;
627
626
  color: var(--df-review-text);
628
627
  font-size: var(--df-review-font-size-md);
629
- font-weight: 650;
628
+ font-weight: 400;
630
629
  line-height: 1.35;
631
630
  }
632
631
 
@@ -638,7 +637,7 @@ function ensureReviewShellStyle() {
638
637
  flex: 0 0 auto;
639
638
  color: var(--df-review-muted);
640
639
  font-family: var(--df-review-font-mono);
641
- font-weight: 500;
640
+ font-weight: 400;
642
641
  white-space: pre;
643
642
  }
644
643
 
@@ -653,14 +652,14 @@ function ensureReviewShellStyle() {
653
652
  color: var(--df-review-muted);
654
653
  font-size: var(--df-review-font-size-sm);
655
654
  font-variant-numeric: tabular-nums;
656
- font-weight: 650;
655
+ font-weight: 400;
657
656
  line-height: 1;
658
657
  text-align: right;
659
658
  }
660
659
 
661
660
  .df-review-sitemap-cell.is-total {
662
661
  color: var(--df-review-accent);
663
- font-weight: 760;
662
+ font-weight: 500;
664
663
  }
665
664
 
666
665
  .df-review-sitemap-cell.is-total strong {
@@ -693,7 +692,7 @@ function ensureReviewShellStyle() {
693
692
  background: var(--df-review-chip-bg);
694
693
  color: var(--df-review-text);
695
694
  font-size: var(--df-review-font-size-xs);
696
- font-weight: 900;
695
+ font-weight: 600;
697
696
  line-height: 1.1;
698
697
  white-space: nowrap;
699
698
  }
@@ -765,12 +764,13 @@ function ensureReviewShellStyle() {
765
764
  .df-review-settings-header strong {
766
765
  color: var(--df-review-text);
767
766
  font-size: var(--df-review-font-size-lg);
767
+ font-weight: 600;
768
768
  }
769
769
 
770
770
  .df-review-settings-header span {
771
771
  color: var(--df-review-muted);
772
772
  font-size: var(--df-review-font-size-xs);
773
- font-weight: 800;
773
+ font-weight: 500;
774
774
  }
775
775
 
776
776
  .df-review-settings-header button {
@@ -780,7 +780,7 @@ function ensureReviewShellStyle() {
780
780
  min-width: 34px;
781
781
  padding: 0;
782
782
  font-size: var(--df-review-font-size-md);
783
- font-weight: 800;
783
+ font-weight: 500;
784
784
  }
785
785
 
786
786
  .df-review-settings-body {
@@ -806,7 +806,7 @@ function ensureReviewShellStyle() {
806
806
  .df-review-settings-label-row label {
807
807
  color: var(--df-review-muted);
808
808
  font-size: var(--df-review-font-size-sm);
809
- font-weight: 800;
809
+ font-weight: 500;
810
810
  }
811
811
 
812
812
  .df-review-settings-theme-options {
@@ -818,17 +818,32 @@ function ensureReviewShellStyle() {
818
818
  }
819
819
 
820
820
  .df-review-settings-theme-option {
821
+ display: inline-flex;
822
+ align-items: center;
823
+ justify-content: center;
824
+ gap: 7px;
821
825
  min-height: 30px;
822
826
  border: 1px solid var(--df-review-line);
823
827
  border-radius: var(--df-review-radius-sm);
824
- padding: 0 10px;
828
+ padding: 0 11px;
825
829
  color: var(--df-review-muted);
826
830
  background: var(--df-review-control);
827
831
  box-shadow: var(--df-review-shadow-control);
828
832
  font-size: var(--df-review-font-size-sm);
829
- font-weight: 800;
833
+ font-weight: 500;
830
834
  }
831
835
 
836
+ .df-review-settings-theme-option svg {
837
+ width: 15px;
838
+ height: 15px;
839
+ flex: 0 0 auto;
840
+ stroke-width: 2.2;
841
+ }
842
+
843
+ .df-review-settings-theme-option span {
844
+ color: inherit;
845
+ }
846
+
832
847
  .df-review-settings-theme-option:hover {
833
848
  border-color: var(--df-review-accent);
834
849
  background: var(--df-review-control-hover);
@@ -973,7 +988,7 @@ function ensureReviewShellStyle() {
973
988
  background: var(--df-review-chip-bg);
974
989
  color: var(--df-review-muted);
975
990
  font-size: var(--df-review-font-size-xs);
976
- font-weight: 700;
991
+ font-weight: 500;
977
992
  line-height: 1.55;
978
993
  }
979
994
 
@@ -989,7 +1004,7 @@ function ensureReviewShellStyle() {
989
1004
  margin: 0;
990
1005
  color: var(--df-review-accent);
991
1006
  font-size: var(--df-review-font-size-sm);
992
- font-weight: 800;
1007
+ font-weight: 500;
993
1008
  }
994
1009
 
995
1010
  .df-review-settings-actions {
@@ -1055,7 +1070,7 @@ function ensureReviewShellStyle() {
1055
1070
  margin: 0;
1056
1071
  color: var(--df-review-danger);
1057
1072
  font-size: var(--df-review-font-size-sm);
1058
- font-weight: 800;
1073
+ font-weight: 500;
1059
1074
  }
1060
1075
 
1061
1076
  .df-review-edit-actions {
@@ -1108,7 +1123,7 @@ function ensureReviewShellStyle() {
1108
1123
  box-shadow: var(--df-review-shadow-modal);
1109
1124
  color: var(--df-review-text);
1110
1125
  font-size: var(--df-review-font-size-sm);
1111
- font-weight: 800;
1126
+ font-weight: 500;
1112
1127
  line-height: 1.25;
1113
1128
  pointer-events: none;
1114
1129
  }
@@ -1132,13 +1147,14 @@ function ensureReviewShellStyle() {
1132
1147
  .df-review-prompt-header strong {
1133
1148
  color: var(--df-review-text);
1134
1149
  font-size: var(--df-review-font-size-lg);
1150
+ font-weight: 600;
1135
1151
  }
1136
1152
 
1137
1153
  .df-review-prompt-header span {
1138
1154
  overflow: hidden;
1139
1155
  color: var(--df-review-muted);
1140
1156
  font-size: var(--df-review-font-size-xs);
1141
- font-weight: 800;
1157
+ font-weight: 500;
1142
1158
  text-overflow: ellipsis;
1143
1159
  white-space: nowrap;
1144
1160
  }
@@ -1150,7 +1166,7 @@ function ensureReviewShellStyle() {
1150
1166
  min-width: 34px;
1151
1167
  padding: 0;
1152
1168
  font-size: var(--df-review-font-size-md);
1153
- font-weight: 800;
1169
+ font-weight: 500;
1154
1170
  }
1155
1171
 
1156
1172
  .df-review-prompt-body {
@@ -1184,13 +1200,13 @@ function ensureReviewShellStyle() {
1184
1200
  .df-review-prompt-block-header strong {
1185
1201
  color: var(--df-review-text);
1186
1202
  font-size: var(--df-review-font-size-sm);
1187
- font-weight: 900;
1203
+ font-weight: 600;
1188
1204
  }
1189
1205
 
1190
1206
  .df-review-prompt-block-header span {
1191
1207
  color: var(--df-review-muted);
1192
1208
  font-size: var(--df-review-font-size-xs);
1193
- font-weight: 800;
1209
+ font-weight: 500;
1194
1210
  }
1195
1211
 
1196
1212
  .df-review-prompt-block-header button {
@@ -1229,7 +1245,7 @@ function ensureReviewShellStyle() {
1229
1245
  color: var(--df-review-text);
1230
1246
  font-family: var(--df-review-font-mono);
1231
1247
  font-size: var(--df-review-font-size-xs);
1232
- font-weight: 600;
1248
+ font-weight: 400;
1233
1249
  line-height: 1.5;
1234
1250
  white-space: pre;
1235
1251
  }
@@ -1248,13 +1264,13 @@ function ensureReviewShellStyle() {
1248
1264
  .df-review-prompt-section-header strong {
1249
1265
  color: var(--df-review-text);
1250
1266
  font-size: var(--df-review-font-size-md);
1251
- font-weight: 900;
1267
+ font-weight: 600;
1252
1268
  }
1253
1269
 
1254
1270
  .df-review-prompt-section-header span {
1255
1271
  color: var(--df-review-muted);
1256
1272
  font-size: var(--df-review-font-size-xs);
1257
- font-weight: 800;
1273
+ font-weight: 500;
1258
1274
  }
1259
1275
 
1260
1276
  .df-review-prompt-about {
@@ -1283,14 +1299,14 @@ function ensureReviewShellStyle() {
1283
1299
  .df-review-prompt-about-grid strong {
1284
1300
  color: var(--df-review-text);
1285
1301
  font-size: var(--df-review-font-size-sm);
1286
- font-weight: 900;
1302
+ font-weight: 600;
1287
1303
  }
1288
1304
 
1289
1305
  .df-review-prompt-about-grid p {
1290
1306
  margin: 0;
1291
1307
  color: var(--df-review-muted);
1292
1308
  font-size: var(--df-review-font-size-sm);
1293
- font-weight: 700;
1309
+ font-weight: 500;
1294
1310
  line-height: 1.55;
1295
1311
  }
1296
1312
 
@@ -1320,8 +1336,9 @@ function ensureReviewShellStyle() {
1320
1336
  display: flex;
1321
1337
  align-items: center;
1322
1338
  gap: var(--df-review-space-1-5);
1323
- min-height: calc(var(--df-review-control-height-lg) + 6px);
1324
- padding: 3px;
1339
+ height: var(--df-review-control-height-md);
1340
+ min-height: var(--df-review-control-height-md);
1341
+ padding: 0;
1325
1342
  border: 1px solid var(--df-review-line-soft);
1326
1343
  border-radius: var(--df-review-radius-md);
1327
1344
  background: var(--df-review-card);
@@ -1333,28 +1350,50 @@ function ensureReviewShellStyle() {
1333
1350
  align-items: center;
1334
1351
  color: var(--df-review-line);
1335
1352
  font-size: var(--df-review-font-size-2xl);
1336
- font-weight: 700;
1353
+ font-weight: 500;
1337
1354
  line-height: 1;
1338
1355
  user-select: none;
1339
1356
  }
1340
1357
 
1341
- .df-review-active-size {
1358
+ .df-review-active-size {
1342
1359
  flex: 0 0 auto;
1343
1360
  display: inline-flex;
1344
1361
  align-items: center;
1345
- min-height: var(--df-review-control-height-lg);
1362
+ min-height: var(--df-review-control-height-md);
1346
1363
  color: var(--df-review-muted);
1347
1364
  font-size: var(--df-review-font-size-sm);
1348
1365
  font-variant-numeric: tabular-nums;
1349
- font-weight: 800;
1366
+ font-weight: 500;
1350
1367
  line-height: 1;
1351
1368
  }
1352
1369
 
1370
+ .df-review-preset-select {
1371
+ -webkit-appearance: none;
1372
+ appearance: none;
1373
+ display: none;
1374
+ height: var(--df-review-control-height-md);
1375
+ min-height: var(--df-review-control-height-md);
1376
+ min-width: 154px;
1377
+ border: 1px solid var(--df-review-line-soft);
1378
+ border-radius: var(--df-review-radius-md);
1379
+ padding: 0 42px 0 14px;
1380
+ color: var(--df-review-text);
1381
+ background-color: var(--df-review-control);
1382
+ background-image: url("data:image/svg+xml,%3Csvg width='18' height='18' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m6 9 6 6 6-6' stroke='%23d7deea' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
1383
+ background-position: right 14px center;
1384
+ background-repeat: no-repeat;
1385
+ background-size: 18px 18px;
1386
+ box-shadow: var(--df-review-shadow-control);
1387
+ font-size: var(--df-review-font-size-sm);
1388
+ font-weight: 500;
1389
+ }
1390
+
1353
1391
  .df-review-presets button {
1354
1392
  display: inline-flex;
1355
1393
  align-items: center;
1356
1394
  gap: 7px;
1357
- min-height: var(--df-review-control-height-lg);
1395
+ height: var(--df-review-control-height-md);
1396
+ min-height: var(--df-review-control-height-md);
1358
1397
  padding: 0 11px 0 9px;
1359
1398
  border-color: transparent;
1360
1399
  background: transparent;
@@ -1379,7 +1418,7 @@ function ensureReviewShellStyle() {
1379
1418
  background: var(--df-review-line-soft);
1380
1419
  color: var(--df-review-muted);
1381
1420
  font-size: var(--df-review-font-size-2xs);
1382
- font-weight: 800;
1421
+ font-weight: 500;
1383
1422
  line-height: 16px;
1384
1423
  text-align: center;
1385
1424
  }
@@ -1405,6 +1444,7 @@ function ensureReviewShellStyle() {
1405
1444
  .df-review-preset-copy strong {
1406
1445
  color: var(--df-review-text);
1407
1446
  font-size: var(--df-review-font-size-sm);
1447
+ font-weight: 500;
1408
1448
  }
1409
1449
 
1410
1450
  .df-review-overlay-button,
@@ -1412,8 +1452,10 @@ function ensureReviewShellStyle() {
1412
1452
  position: relative;
1413
1453
  display: inline-grid;
1414
1454
  place-items: center;
1415
- width: 38px;
1416
- min-width: 38px;
1455
+ width: var(--df-review-control-height-md);
1456
+ min-width: var(--df-review-control-height-md);
1457
+ height: var(--df-review-control-height-md);
1458
+ min-height: var(--df-review-control-height-md);
1417
1459
  padding: 0;
1418
1460
  border-color: transparent;
1419
1461
  background: transparent;
@@ -1421,6 +1463,72 @@ function ensureReviewShellStyle() {
1421
1463
  color: var(--df-review-muted);
1422
1464
  }
1423
1465
 
1466
+ .df-review-overlays-menu {
1467
+ position: relative;
1468
+ display: none;
1469
+ flex: 0 0 auto;
1470
+ }
1471
+
1472
+ .df-review-overlays-menu summary {
1473
+ display: grid;
1474
+ place-items: center;
1475
+ width: var(--df-review-control-height-md);
1476
+ min-width: var(--df-review-control-height-md);
1477
+ height: var(--df-review-control-height-md);
1478
+ border: 1px solid var(--df-review-line-soft);
1479
+ border-radius: var(--df-review-radius-md);
1480
+ padding: 0;
1481
+ color: var(--df-review-muted);
1482
+ background: var(--df-review-card);
1483
+ box-shadow: var(--df-review-shadow-control);
1484
+ cursor: pointer;
1485
+ }
1486
+
1487
+ .df-review-overlays-menu summary::-webkit-details-marker {
1488
+ display: none;
1489
+ }
1490
+
1491
+ .df-review-overlays-menu summary::marker {
1492
+ content: '';
1493
+ }
1494
+
1495
+ .df-review-overlays-menu summary:hover,
1496
+ .df-review-overlays-menu[open] summary {
1497
+ border-color: var(--df-review-accent);
1498
+ background: var(--df-review-control-hover);
1499
+ color: var(--df-review-accent);
1500
+ }
1501
+
1502
+ .df-review-overlays-menu summary svg {
1503
+ width: 20px;
1504
+ height: 20px;
1505
+ fill: none;
1506
+ stroke: currentColor;
1507
+ stroke-linecap: round;
1508
+ stroke-linejoin: round;
1509
+ stroke-width: 1.9;
1510
+ }
1511
+
1512
+ .df-review-overlays-popover {
1513
+ position: absolute;
1514
+ top: calc(100% + 6px);
1515
+ right: 0;
1516
+ z-index: 700;
1517
+ display: none;
1518
+ align-items: center;
1519
+ gap: var(--df-review-space-1-5);
1520
+ min-height: var(--df-review-control-height-md);
1521
+ padding: 0;
1522
+ border: 1px solid var(--df-review-line-soft);
1523
+ border-radius: var(--df-review-radius-md);
1524
+ background: var(--df-review-card);
1525
+ box-shadow: var(--df-review-shadow-modal);
1526
+ }
1527
+
1528
+ .df-review-overlays-menu[open] .df-review-overlays-popover {
1529
+ display: flex;
1530
+ }
1531
+
1424
1532
  .df-review-overlay-button svg,
1425
1533
  .df-review-mode-button svg {
1426
1534
  width: 18px;
@@ -1456,33 +1564,46 @@ function ensureReviewShellStyle() {
1456
1564
 
1457
1565
  @container (max-width: 1040px) {
1458
1566
  .df-review-tools {
1459
- flex-direction: column;
1460
- align-items: stretch;
1461
- justify-content: flex-start;
1567
+ flex-direction: row;
1568
+ align-items: center;
1569
+ justify-content: space-between;
1462
1570
  }
1463
1571
 
1464
1572
  .df-review-tool-controls {
1465
- width: 100%;
1573
+ flex: 1 1 auto;
1574
+ width: auto;
1575
+ min-width: 0;
1576
+ flex-wrap: nowrap;
1466
1577
  }
1467
1578
 
1468
1579
  .df-review-presets {
1469
- flex-wrap: wrap;
1580
+ display: none;
1581
+ }
1582
+
1583
+ .df-review-preset-select {
1584
+ display: block;
1585
+ flex: 0 1 190px;
1586
+ width: clamp(154px, 26vw, 190px);
1470
1587
  }
1471
1588
 
1472
1589
  .df-review-overlays {
1473
- width: 100%;
1474
- justify-content: flex-start;
1590
+ display: none;
1475
1591
  }
1592
+
1593
+ .df-review-overlays-menu {
1594
+ display: block;
1595
+ }
1476
1596
  }
1477
1597
 
1478
1598
  .df-review-side-rail {
1479
1599
  grid-column: 3;
1480
1600
  grid-row: 1 / span 3;
1481
1601
  position: relative;
1482
- z-index: 600;
1602
+ z-index: 640;
1483
1603
  display: flex;
1604
+ flex-direction: column;
1484
1605
  align-items: stretch;
1485
- justify-content: center;
1606
+ justify-content: flex-start;
1486
1607
  min-width: 0;
1487
1608
  min-height: 0;
1488
1609
  border-left: 1px solid var(--df-review-line);
@@ -1490,49 +1611,166 @@ function ensureReviewShellStyle() {
1490
1611
  }
1491
1612
 
1492
1613
  .df-review-side-toggle {
1614
+ position: relative;
1615
+ flex: 0 0 58px;
1493
1616
  display: grid;
1494
- grid-template-rows: 28px auto;
1495
- align-items: start;
1496
- justify-items: center;
1497
- gap: 8px;
1617
+ place-items: center;
1498
1618
  width: 100%;
1499
- min-height: 100%;
1619
+ min-height: 58px;
1500
1620
  border: 0;
1501
1621
  border-radius: 0;
1502
- padding: 10px 0;
1622
+ padding: 0;
1503
1623
  background: transparent;
1504
1624
  color: var(--df-review-muted);
1625
+ transition: color 140ms ease, background 140ms ease;
1505
1626
  }
1506
1627
 
1507
1628
  .df-review-side-toggle:hover {
1508
- background: var(--df-review-accent-soft);
1509
1629
  color: var(--df-review-text);
1510
1630
  }
1511
1631
 
1632
+ .df-review-side-toggle.is-active {
1633
+ color: var(--df-review-accent);
1634
+ }
1635
+
1636
+ .df-review-side-toggle.is-active::after {
1637
+ position: absolute;
1638
+ top: 12px;
1639
+ right: 0;
1640
+ bottom: 12px;
1641
+ width: 3px;
1642
+ border-radius: 3px 0 0 3px;
1643
+ background: var(--df-review-accent);
1644
+ content: '';
1645
+ }
1646
+
1647
+ .df-review-side-toggle:focus-visible {
1648
+ outline: 0;
1649
+ color: var(--df-review-text);
1650
+ }
1651
+
1652
+ .df-review-side-toggle:focus-visible span {
1653
+ border-radius: 6px;
1654
+ outline: 2px solid var(--df-review-focus-ring);
1655
+ outline-offset: 3px;
1656
+ }
1657
+
1512
1658
  .df-review-side-toggle span {
1513
1659
  display: grid;
1514
1660
  place-items: center;
1515
- width: 20px;
1516
- height: 24px;
1661
+ width: 30px;
1662
+ height: 30px;
1517
1663
  line-height: 1;
1518
1664
  }
1519
1665
 
1520
1666
  .df-review-side-toggle svg {
1521
- width: 18px;
1522
- height: 18px;
1667
+ width: 30px;
1668
+ height: 30px;
1523
1669
  fill: none;
1524
1670
  stroke: currentColor;
1525
1671
  stroke-linecap: round;
1526
- stroke-width: 2;
1672
+ stroke-width: 1.55;
1527
1673
  }
1528
1674
 
1529
- .df-review-side-toggle strong {
1530
- writing-mode: vertical-rl;
1531
- text-orientation: mixed;
1532
- color: inherit;
1533
- font-size: var(--df-review-font-size-2xs);
1534
- font-weight: 900;
1535
- letter-spacing: 0.08em;
1675
+ .df-review-presence-overlay {
1676
+ position: relative;
1677
+ margin-top: auto;
1678
+ }
1679
+
1680
+ .df-review-presence-button {
1681
+ position: relative;
1682
+ display: grid;
1683
+ place-items: center;
1684
+ width: 100%;
1685
+ min-height: 58px;
1686
+ border: 0;
1687
+ border-radius: 0;
1688
+ padding: 0;
1689
+ color: var(--df-review-muted);
1690
+ background: transparent;
1691
+ }
1692
+
1693
+ .df-review-presence-button:hover,
1694
+ .df-review-presence-button[aria-expanded="true"] {
1695
+ color: var(--df-review-text);
1696
+ }
1697
+
1698
+ .df-review-presence-button:focus-visible {
1699
+ outline: 0;
1700
+ }
1701
+
1702
+ .df-review-presence-button:focus-visible svg {
1703
+ border-radius: 6px;
1704
+ outline: 2px solid var(--df-review-focus-ring);
1705
+ outline-offset: 3px;
1706
+ }
1707
+
1708
+ .df-review-presence-button svg {
1709
+ width: 30px;
1710
+ height: 30px;
1711
+ fill: none;
1712
+ stroke: currentColor;
1713
+ stroke-linecap: round;
1714
+ stroke-linejoin: round;
1715
+ stroke-width: 1.55;
1716
+ }
1717
+
1718
+ .df-review-presence-badge {
1719
+ position: absolute;
1720
+ top: 10px;
1721
+ right: 7px;
1722
+ display: grid;
1723
+ place-items: center;
1724
+ min-width: 17px;
1725
+ height: 17px;
1726
+ border: 1px solid var(--df-review-side-rail);
1727
+ border-radius: var(--df-review-radius-pill);
1728
+ padding: 0 4px;
1729
+ color: #17202c;
1730
+ background: var(--df-review-accent);
1731
+ font-size: var(--df-review-font-size-3xs);
1732
+ font-weight: 600;
1733
+ line-height: 1;
1734
+ pointer-events: none;
1735
+ }
1736
+
1737
+ .df-review-presence-list {
1738
+ position: absolute;
1739
+ right: calc(100% + 8px);
1740
+ bottom: 8px;
1741
+ display: grid;
1742
+ gap: 5px;
1743
+ min-width: 132px;
1744
+ max-width: 220px;
1745
+ border: 1px solid var(--df-review-line);
1746
+ border-radius: var(--df-review-radius-md);
1747
+ padding: 8px;
1748
+ background: var(--df-review-panel);
1749
+ box-shadow: var(--df-review-shadow-modal);
1750
+ }
1751
+
1752
+ .df-review-presence-chip {
1753
+ --df-review-presence-color: var(--df-review-accent);
1754
+ display: flex;
1755
+ align-items: center;
1756
+ min-width: 0;
1757
+ min-height: 24px;
1758
+ border-left: 2px solid var(--df-review-presence-color);
1759
+ border-radius: var(--df-review-radius-sm);
1760
+ padding: 0 8px;
1761
+ color: var(--df-review-text);
1762
+ background: var(--df-review-control);
1763
+ font-size: var(--df-review-font-size-xs);
1764
+ font-weight: 500;
1765
+ line-height: 1.1;
1766
+ overflow: hidden;
1767
+ text-overflow: ellipsis;
1768
+ white-space: nowrap;
1769
+ }
1770
+
1771
+ .df-review-presence-chip.is-self {
1772
+ color: var(--df-review-accent);
1773
+ background: var(--df-review-accent-soft);
1536
1774
  }
1537
1775
 
1538
1776
  .df-review-qa-panel {
@@ -1550,11 +1788,34 @@ function ensureReviewShellStyle() {
1550
1788
  linear-gradient(180deg, var(--df-review-panel), var(--df-review-bg));
1551
1789
  }
1552
1790
 
1553
- .df-review-shell:not(.is-list-visible) .df-review-qa-panel {
1791
+ .df-review-shell:not(.is-list-visible) .df-review-qa-panel,
1792
+ .df-review-qa-panel[aria-hidden="true"] {
1554
1793
  visibility: hidden;
1555
1794
  border-left: 0;
1795
+ pointer-events: none;
1556
1796
  }
1557
1797
 
1798
+ .df-review-source-tree-panel {
1799
+ grid-column: 2;
1800
+ grid-row: 1 / span 3;
1801
+ position: relative;
1802
+ z-index: 600;
1803
+ display: grid;
1804
+ min-width: 0;
1805
+ min-height: 0;
1806
+ overflow: hidden;
1807
+ border-left: 1px solid var(--df-review-line-soft);
1808
+ background:
1809
+ linear-gradient(180deg, var(--df-review-panel), var(--df-review-bg));
1810
+ }
1811
+
1812
+ .df-review-shell:not(.is-list-visible) .df-review-source-tree-panel,
1813
+ .df-review-source-tree-panel[aria-hidden="true"] {
1814
+ visibility: hidden;
1815
+ border-left: 0;
1816
+ pointer-events: none;
1817
+ }
1818
+
1558
1819
  .df-review-panel-body {
1559
1820
  display: grid;
1560
1821
  min-width: 0;
@@ -1571,14 +1832,16 @@ function ensureReviewShellStyle() {
1571
1832
 
1572
1833
  .df-review-list-header {
1573
1834
  display: grid;
1574
- grid-template-rows: auto auto;
1835
+ grid-template-rows:
1836
+ var(--df-review-control-height-md)
1837
+ var(--df-review-control-height-md);
1575
1838
  gap: var(--df-review-space-2);
1576
1839
  padding: var(--df-review-space-3) var(--df-review-frame-gutter-x);
1577
1840
  border-bottom: 1px solid var(--df-review-line-soft);
1578
1841
  background: var(--df-review-card);
1579
1842
  color: var(--df-review-muted);
1580
1843
  font-size: var(--df-review-font-size-sm);
1581
- font-weight: 800;
1844
+ font-weight: 500;
1582
1845
  }
1583
1846
 
1584
1847
  .df-review-list-toolbar {
@@ -1586,122 +1849,59 @@ function ensureReviewShellStyle() {
1586
1849
  grid-template-columns: minmax(0, 1fr) auto;
1587
1850
  align-items: center;
1588
1851
  gap: 8px;
1852
+ min-height: var(--df-review-control-height-md);
1589
1853
  min-width: 0;
1590
1854
  }
1591
1855
 
1592
1856
  .df-review-list-title {
1593
- display: flex;
1857
+ display: grid;
1858
+ grid-template-columns: minmax(0, 1fr) auto;
1594
1859
  align-items: center;
1595
1860
  gap: 8px;
1861
+ min-height: var(--df-review-control-height-md);
1596
1862
  min-width: 0;
1597
1863
  }
1598
1864
 
1599
- .df-review-list-title span {
1865
+ .df-review-list-meta {
1866
+ display: flex;
1867
+ align-items: center;
1868
+ gap: 8px;
1869
+ min-width: 0;
1870
+ }
1871
+
1872
+ .df-review-list-meta span {
1600
1873
  min-width: 0;
1601
1874
  overflow: hidden;
1602
1875
  text-overflow: ellipsis;
1603
1876
  white-space: nowrap;
1604
1877
  }
1605
1878
 
1606
- .df-review-list-title strong {
1607
- flex: 0 0 auto;
1608
- color: var(--df-review-muted);
1609
- font-size: var(--df-review-font-size-xs);
1610
- font-variant-numeric: tabular-nums;
1611
- }
1879
+ .df-review-list-meta strong {
1880
+ flex: 0 0 auto;
1881
+ color: var(--df-review-muted);
1882
+ font-size: var(--df-review-font-size-xs);
1883
+ font-variant-numeric: tabular-nums;
1884
+ font-weight: 500;
1885
+ }
1612
1886
 
1613
- .df-review-presence-overlay {
1887
+ .df-review-list-controls {
1614
1888
  display: flex;
1615
1889
  align-items: center;
1616
- flex-wrap: wrap;
1617
- gap: 5px;
1618
- max-width: 100%;
1619
- pointer-events: none;
1890
+ gap: 4px;
1620
1891
  }
1621
1892
 
1622
- .df-review-presence-row .df-review-presence-overlay {
1623
- width: 100%;
1624
- max-width: 1440px;
1625
- margin: 0 auto;
1626
- }
1627
-
1628
- .df-review-presence-chip {
1629
- --df-review-presence-color: var(--df-review-accent);
1630
- display: inline-flex;
1631
- align-items: center;
1632
- min-width: 0;
1633
- max-width: min(220px, calc(100% - 20px));
1634
- min-height: 24px;
1635
- border: 1px solid rgba(15, 23, 42, 0.12);
1636
- border-radius: var(--df-review-radius-pill);
1637
- padding: 0 8px;
1638
- color: #17202c;
1639
- background: rgba(255, 255, 255, 0.92);
1640
- box-shadow: 0 8px 22px rgba(15, 23, 42, 0.14);
1641
- font-size: var(--df-review-font-size-2xs);
1642
- font-weight: 900;
1643
- line-height: 1.1;
1644
- overflow: hidden;
1645
- text-overflow: ellipsis;
1646
- white-space: nowrap;
1647
- backdrop-filter: blur(8px);
1648
- }
1649
-
1650
- .df-review-presence-row .df-review-presence-chip {
1651
- max-width: none;
1652
- }
1653
-
1654
- .df-review-presence-chip.is-self {
1655
- border-color: var(--df-review-presence-color);
1656
- box-shadow:
1657
- inset 0 0 0 1px var(--df-review-presence-color),
1658
- 0 8px 22px rgba(15, 23, 42, 0.14);
1659
- }
1660
-
1661
- .df-review-presence-more {
1662
- display: inline-flex;
1663
- align-items: center;
1664
- justify-content: center;
1665
- min-width: 28px;
1666
- min-height: 24px;
1667
- border: 1px solid rgba(15, 23, 42, 0.12);
1668
- border-radius: var(--df-review-radius-pill);
1669
- padding: 0 8px;
1670
- color: #17202c;
1671
- background: rgba(255, 255, 255, 0.92);
1672
- box-shadow: 0 8px 22px rgba(15, 23, 42, 0.14);
1673
- cursor: pointer;
1674
- font: inherit;
1675
- font-size: var(--df-review-font-size-2xs);
1676
- font-weight: 900;
1677
- line-height: 1;
1678
- pointer-events: auto;
1679
- backdrop-filter: blur(8px);
1680
- }
1681
-
1682
- .df-review-presence-more:hover {
1683
- border-color: rgba(0, 102, 255, 0.42);
1684
- color: #005be8;
1685
- background: rgba(255, 255, 255, 0.98);
1686
- }
1687
-
1688
- .df-review-list-controls {
1689
- display: flex;
1690
- align-items: center;
1691
- gap: 4px;
1692
- }
1693
-
1694
- .df-review-source-select,
1695
- .df-review-status-filter-select {
1696
- min-height: 30px;
1697
- border: 1px solid var(--df-review-line-soft);
1698
- border-radius: var(--df-review-radius-sm);
1699
- padding: 0 24px 0 8px;
1700
- color: var(--df-review-text);
1701
- background: var(--df-review-control);
1702
- box-shadow: var(--df-review-shadow-control);
1703
- font-size: var(--df-review-font-size-xs);
1704
- font-weight: 800;
1893
+ .df-review-source-select,
1894
+ .df-review-status-filter-select {
1895
+ height: var(--df-review-control-height-md);
1896
+ min-height: var(--df-review-control-height-md);
1897
+ border: 1px solid var(--df-review-line-soft);
1898
+ border-radius: var(--df-review-radius-sm);
1899
+ padding: 0 24px 0 8px;
1900
+ color: var(--df-review-text);
1901
+ background: var(--df-review-control);
1902
+ box-shadow: var(--df-review-shadow-control);
1903
+ font-size: var(--df-review-font-size-xs);
1904
+ font-weight: 500;
1705
1905
  }
1706
1906
 
1707
1907
  .df-review-source-select {
@@ -1712,17 +1912,13 @@ function ensureReviewShellStyle() {
1712
1912
  width: 124px;
1713
1913
  }
1714
1914
 
1715
- .df-review-list-title .df-review-status-filter-select {
1716
- margin-left: auto;
1717
- }
1718
-
1719
1915
  .df-review-source-refresh {
1720
1916
  position: relative;
1721
1917
  display: inline-grid;
1722
1918
  place-items: center;
1723
- width: 30px;
1724
- min-width: 30px;
1725
- height: 30px;
1919
+ width: var(--df-review-control-height-md);
1920
+ min-width: var(--df-review-control-height-md);
1921
+ height: var(--df-review-control-height-md);
1726
1922
  border: 1px solid var(--df-review-line-soft);
1727
1923
  border-radius: var(--df-review-radius-sm);
1728
1924
  padding: 0;
@@ -1732,16 +1928,18 @@ function ensureReviewShellStyle() {
1732
1928
  }
1733
1929
 
1734
1930
  .df-review-source-refresh svg {
1735
- width: 14px;
1736
- height: 14px;
1931
+ width: 16px;
1932
+ height: 16px;
1737
1933
  }
1738
1934
 
1739
1935
  .df-review-filter-tabs {
1740
1936
  display: flex;
1741
1937
  align-items: center;
1742
- gap: 2px;
1743
- height: 30px;
1744
- padding: 2px;
1938
+ justify-self: end;
1939
+ gap: var(--df-review-space-1-5);
1940
+ height: var(--df-review-control-height-md);
1941
+ min-height: var(--df-review-control-height-md);
1942
+ padding: 0;
1745
1943
  border: 1px solid var(--df-review-line-soft);
1746
1944
  border-radius: var(--df-review-radius-md);
1747
1945
  background: var(--df-review-card);
@@ -1752,11 +1950,11 @@ function ensureReviewShellStyle() {
1752
1950
  position: relative;
1753
1951
  display: grid;
1754
1952
  place-items: center;
1755
- width: 26px;
1756
- min-width: 26px;
1757
- height: 26px;
1953
+ width: var(--df-review-control-height-md);
1954
+ min-width: var(--df-review-control-height-md);
1955
+ height: var(--df-review-control-height-md);
1758
1956
  border: 0;
1759
- border-radius: 5px;
1957
+ border-radius: var(--df-review-radius-sm);
1760
1958
  background: transparent;
1761
1959
  color: var(--df-review-subtle);
1762
1960
  }
@@ -1789,19 +1987,19 @@ function ensureReviewShellStyle() {
1789
1987
  }
1790
1988
 
1791
1989
  .df-review-filter-icon svg {
1792
- width: 15px;
1793
- height: 15px;
1990
+ width: 18px;
1991
+ height: 18px;
1794
1992
  fill: none;
1795
1993
  stroke: currentColor;
1796
1994
  stroke-linecap: round;
1797
1995
  stroke-linejoin: round;
1798
- stroke-width: 2;
1996
+ stroke-width: 1.9;
1799
1997
  }
1800
1998
 
1801
1999
  .df-review-filter-count {
1802
2000
  color: currentColor;
1803
2001
  font-size: var(--df-review-font-size-3xs);
1804
- font-weight: 900;
2002
+ font-weight: 600;
1805
2003
  font-variant-numeric: tabular-nums;
1806
2004
  line-height: 1;
1807
2005
  }
@@ -1882,6 +2080,7 @@ function ensureReviewShellStyle() {
1882
2080
  .df-review-item-main strong {
1883
2081
  overflow-wrap: anywhere;
1884
2082
  font-size: var(--df-review-font-size-md);
2083
+ font-weight: 500;
1885
2084
  line-height: 1.35;
1886
2085
  }
1887
2086
 
@@ -1929,7 +2128,7 @@ function ensureReviewShellStyle() {
1929
2128
  border-radius: var(--df-review-radius-pill);
1930
2129
  padding: 0 7px;
1931
2130
  font-size: var(--df-review-font-size-2xs);
1932
- font-weight: 900;
2131
+ font-weight: 600;
1933
2132
  line-height: 1;
1934
2133
  text-transform: uppercase;
1935
2134
  }
@@ -1996,7 +2195,7 @@ function ensureReviewShellStyle() {
1996
2195
  border-radius: var(--df-review-radius-sm);
1997
2196
  padding: 0 11px;
1998
2197
  font-size: var(--df-review-font-size-xs);
1999
- font-weight: 750;
2198
+ font-weight: 500;
2000
2199
  text-transform: none;
2001
2200
  }
2002
2201
 
@@ -2009,7 +2208,7 @@ function ensureReviewShellStyle() {
2009
2208
  cursor: pointer;
2010
2209
  outline: 0;
2011
2210
  font-size: var(--df-review-font-size-xs);
2012
- font-weight: 750;
2211
+ font-weight: 500;
2013
2212
  text-transform: none;
2014
2213
  }
2015
2214
 
@@ -2234,7 +2433,7 @@ function ensureReviewShellStyle() {
2234
2433
 
2235
2434
  .df-review-item-submit-button span {
2236
2435
  font-size: var(--df-review-font-size-xs);
2237
- font-weight: 750;
2436
+ font-weight: 500;
2238
2437
  line-height: 1;
2239
2438
  text-transform: none;
2240
2439
  white-space: nowrap;
@@ -2406,6 +2605,9 @@ function ensureReviewShellStyle() {
2406
2605
  --df-review-source-popover-text: #edf3fb;
2407
2606
  --df-review-source-popover-muted: rgba(237, 243, 251, 0.68);
2408
2607
  --df-review-source-popover-subtle: rgba(237, 243, 251, 0.5);
2608
+ --df-review-source-popover-data: #f3b75f;
2609
+ --df-review-source-popover-data-muted: rgba(243, 183, 95, 0.78);
2610
+ --df-review-source-popover-data-subtle: rgba(243, 183, 95, 0.62);
2409
2611
  --df-review-source-popover-hover: rgba(124, 199, 255, 0.14);
2410
2612
  position: fixed;
2411
2613
  z-index: 890;
@@ -2417,7 +2619,7 @@ function ensureReviewShellStyle() {
2417
2619
  overflow: hidden;
2418
2620
  border: 1px solid var(--df-review-source-popover-line);
2419
2621
  border-radius: var(--df-review-radius-md);
2420
- padding: 8px 6px 6px;
2622
+ padding: 6px;
2421
2623
  color: var(--df-review-source-popover-text);
2422
2624
  color-scheme: dark;
2423
2625
  background: rgba(19, 24, 33, 0.96);
@@ -2443,7 +2645,7 @@ function ensureReviewShellStyle() {
2443
2645
  color: var(--df-review-source-popover-subtle);
2444
2646
  background: transparent;
2445
2647
  font-size: 16px;
2446
- font-weight: 800;
2648
+ font-weight: 500;
2447
2649
  line-height: 1;
2448
2650
  }
2449
2651
 
@@ -2456,29 +2658,37 @@ function ensureReviewShellStyle() {
2456
2658
  .df-review-source-candidate-list {
2457
2659
  display: grid;
2458
2660
  gap: 0;
2661
+ max-height: min(220px, calc(100vh - 96px));
2459
2662
  min-height: 0;
2460
- overflow: auto;
2663
+ overflow-x: hidden;
2664
+ overflow-y: auto;
2665
+ padding-right: 2px;
2666
+ scrollbar-gutter: stable;
2461
2667
  }
2462
2668
 
2463
2669
  .df-review-source-candidate {
2464
2670
  display: grid;
2465
2671
  width: 100%;
2466
- min-height: 54px;
2467
2672
  border: 0;
2673
+ border-top: 1px solid transparent;
2468
2674
  border-radius: var(--df-review-radius-sm);
2469
- padding: 6px 30px 6px 8px;
2675
+ padding: 9px 30px 9px 8px;
2470
2676
  color: var(--df-review-source-popover-text);
2471
2677
  background: transparent;
2472
2678
  text-align: left;
2473
2679
  }
2474
2680
 
2681
+ .df-review-source-candidate + .df-review-source-candidate {
2682
+ border-top-color: var(--df-review-source-popover-line);
2683
+ }
2684
+
2475
2685
  .df-review-source-candidate:hover {
2476
2686
  background: var(--df-review-source-popover-hover);
2477
2687
  }
2478
2688
 
2479
2689
  .df-review-source-candidate-main {
2480
2690
  display: grid;
2481
- gap: 2px;
2691
+ gap: 1px;
2482
2692
  min-width: 0;
2483
2693
  }
2484
2694
 
@@ -2491,7 +2701,8 @@ function ensureReviewShellStyle() {
2491
2701
 
2492
2702
  .df-review-source-candidate-main strong {
2493
2703
  font-size: var(--df-review-font-size-xs);
2494
- font-weight: 900;
2704
+ font-weight: 600;
2705
+ line-height: 1.2;
2495
2706
  }
2496
2707
 
2497
2708
  .df-review-source-candidate-main span {
@@ -2499,7 +2710,7 @@ function ensureReviewShellStyle() {
2499
2710
  color: var(--df-review-source-popover-muted);
2500
2711
  font-family: var(--df-review-font-mono);
2501
2712
  font-size: var(--df-review-font-size-2xs);
2502
- line-height: 1.25;
2713
+ line-height: 1.24;
2503
2714
  white-space: normal;
2504
2715
  }
2505
2716
 
@@ -2507,6 +2718,335 @@ function ensureReviewShellStyle() {
2507
2718
  color: var(--df-review-source-popover-subtle);
2508
2719
  font-family: var(--df-review-font-mono);
2509
2720
  font-size: var(--df-review-font-size-2xs);
2721
+ line-height: 1.2;
2722
+ }
2723
+
2724
+ .df-review-source-candidate.is-data .df-review-source-candidate-main strong {
2725
+ color: var(--df-review-source-popover-data);
2726
+ }
2727
+
2728
+ .df-review-source-candidate.is-data .df-review-source-candidate-main span {
2729
+ color: var(--df-review-source-popover-data-muted);
2730
+ }
2731
+
2732
+ .df-review-source-candidate.is-data .df-review-source-candidate-main small {
2733
+ color: var(--df-review-source-popover-data-subtle);
2734
+ }
2735
+
2736
+ .df-review-section-outline {
2737
+ position: relative;
2738
+ z-index: 1;
2739
+ display: grid;
2740
+ grid-template-rows: auto minmax(0, 1fr);
2741
+ width: 100%;
2742
+ height: 100%;
2743
+ min-width: 0;
2744
+ min-height: 0;
2745
+ border: 0;
2746
+ border-radius: 0;
2747
+ color: var(--df-review-text);
2748
+ background: transparent;
2749
+ box-shadow: none;
2750
+ overflow: hidden;
2751
+ }
2752
+
2753
+ .df-review-section-outline-head {
2754
+ display: grid;
2755
+ grid-template-rows:
2756
+ var(--df-review-control-height-md)
2757
+ var(--df-review-control-height-md);
2758
+ align-items: center;
2759
+ gap: 8px;
2760
+ min-width: 0;
2761
+ padding: var(--df-review-space-3) var(--df-review-frame-gutter-x);
2762
+ border-bottom: 1px solid var(--df-review-line-soft);
2763
+ background: var(--df-review-card);
2764
+ color: var(--df-review-muted);
2765
+ }
2766
+
2767
+ .df-review-section-outline-head span {
2768
+ display: grid;
2769
+ gap: 2px;
2770
+ min-width: 0;
2771
+ }
2772
+
2773
+ .df-review-section-outline-head strong {
2774
+ overflow: hidden;
2775
+ color: var(--df-review-text);
2776
+ font-size: var(--df-review-font-size-lg);
2777
+ font-weight: 600;
2778
+ text-overflow: ellipsis;
2779
+ white-space: nowrap;
2780
+ }
2781
+
2782
+ .df-review-section-outline-head small {
2783
+ overflow: hidden;
2784
+ color: var(--df-review-muted);
2785
+ font-size: var(--df-review-font-size-xs);
2786
+ font-weight: 500;
2787
+ text-overflow: ellipsis;
2788
+ white-space: nowrap;
2789
+ }
2790
+
2791
+ .df-review-section-outline-filter {
2792
+ display: grid;
2793
+ grid-template-columns: 18px minmax(0, 1fr) auto;
2794
+ align-items: center;
2795
+ align-self: stretch;
2796
+ gap: 8px;
2797
+ min-width: 0;
2798
+ height: var(--df-review-control-height-md);
2799
+ min-height: var(--df-review-control-height-md);
2800
+ border: 1px solid var(--df-review-line-soft);
2801
+ border-radius: var(--df-review-radius-md);
2802
+ padding: 0 7px 0 11px;
2803
+ color: var(--df-review-muted);
2804
+ background: var(--df-review-control);
2805
+ box-shadow: var(--df-review-shadow-control);
2806
+ }
2807
+
2808
+ .df-review-section-outline-filter:focus-within {
2809
+ border-color: var(--df-review-accent);
2810
+ box-shadow: inset 0 0 0 1px var(--df-review-accent-hover);
2811
+ }
2812
+
2813
+ .df-review-section-outline-filter svg {
2814
+ width: 18px;
2815
+ height: 18px;
2816
+ fill: none;
2817
+ stroke: currentColor;
2818
+ stroke-linecap: round;
2819
+ stroke-linejoin: round;
2820
+ stroke-width: 1.9;
2821
+ }
2822
+
2823
+ .df-review-section-outline-filter input {
2824
+ width: 100%;
2825
+ min-width: 0;
2826
+ height: 100%;
2827
+ border: 0;
2828
+ padding: 0;
2829
+ color: var(--df-review-text);
2830
+ background: transparent;
2831
+ font-size: var(--df-review-font-size-xs);
2832
+ font-weight: 500;
2833
+ outline: 0;
2834
+ -webkit-appearance: none;
2835
+ appearance: none;
2836
+ }
2837
+
2838
+ .df-review-section-outline-filter input::placeholder {
2839
+ color: var(--df-review-subtle);
2840
+ }
2841
+
2842
+ .df-review-section-outline-filter input::-webkit-search-cancel-button,
2843
+ .df-review-section-outline-filter input::-webkit-search-decoration {
2844
+ display: none;
2845
+ -webkit-appearance: none;
2846
+ appearance: none;
2847
+ }
2848
+
2849
+ .df-review-section-outline-filter-clear {
2850
+ display: inline-grid;
2851
+ place-items: center;
2852
+ width: var(--df-review-control-height-md);
2853
+ height: var(--df-review-control-height-md);
2854
+ border: 0;
2855
+ border-radius: var(--df-review-radius-sm);
2856
+ padding: 0;
2857
+ color: var(--df-review-muted);
2858
+ background: transparent;
2859
+ cursor: pointer;
2860
+ }
2861
+
2862
+ .df-review-section-outline-filter-clear:hover,
2863
+ .df-review-section-outline-filter-clear:focus-visible {
2864
+ color: var(--df-review-text);
2865
+ background: var(--df-review-accent-soft);
2866
+ outline: 0;
2867
+ }
2868
+
2869
+ .df-review-section-outline-list {
2870
+ display: grid;
2871
+ align-content: start;
2872
+ gap: 2px;
2873
+ min-height: 0;
2874
+ overflow-y: auto;
2875
+ padding: 8px 1px 8px 15px;
2876
+ scrollbar-gutter: stable;
2877
+ }
2878
+
2879
+ .df-review-section-outline-item {
2880
+ display: grid;
2881
+ }
2882
+
2883
+ .df-review-section-outline-item.is-depth-1:not(:last-child) {
2884
+ margin-bottom: 7px;
2885
+ padding-bottom: 7px;
2886
+ border-bottom: 1px solid var(--df-review-line-soft);
2887
+ }
2888
+
2889
+ .df-review-section-outline-row {
2890
+ display: grid;
2891
+ grid-template-columns: 18px minmax(0, 1fr) auto;
2892
+ align-items: center;
2893
+ gap: 5px;
2894
+ border-radius: var(--df-review-radius-sm);
2895
+ padding: 7px 6px;
2896
+ }
2897
+
2898
+ .df-review-section-outline-row:hover {
2899
+ background: var(--df-review-accent-soft);
2900
+ }
2901
+
2902
+ .df-review-section-outline-toggle {
2903
+ display: grid;
2904
+ place-items: center;
2905
+ width: 18px;
2906
+ height: 18px;
2907
+ border: 0;
2908
+ border-radius: var(--df-review-radius-sm);
2909
+ padding: 0;
2910
+ color: var(--df-review-muted);
2911
+ background: transparent;
2912
+ }
2913
+
2914
+ .df-review-section-outline-toggle:hover {
2915
+ color: var(--df-review-text);
2916
+ background: var(--df-review-accent-soft);
2917
+ }
2918
+
2919
+ .df-review-section-outline-toggle svg {
2920
+ width: 13px;
2921
+ height: 13px;
2922
+ fill: none;
2923
+ stroke: currentColor;
2924
+ stroke-linecap: round;
2925
+ stroke-linejoin: round;
2926
+ stroke-width: 2.4;
2927
+ transition: transform 120ms ease;
2928
+ }
2929
+
2930
+ .df-review-section-outline-toggle.is-collapsed svg {
2931
+ transform: rotate(-90deg);
2932
+ }
2933
+
2934
+ .df-review-section-outline-toggle.is-placeholder {
2935
+ pointer-events: none;
2936
+ }
2937
+
2938
+ .df-review-section-outline-name {
2939
+ display: grid;
2940
+ gap: 2px;
2941
+ min-width: 0;
2942
+ overflow: visible;
2943
+ border: 0;
2944
+ padding: 0;
2945
+ color: var(--df-review-text);
2946
+ background: transparent;
2947
+ font-size: var(--df-review-font-size-sm);
2948
+ font-weight: 500;
2949
+ text-align: left;
2950
+ white-space: normal;
2951
+ cursor: pointer;
2952
+ }
2953
+
2954
+ .df-review-section-outline-name span,
2955
+ .df-review-section-outline-name small {
2956
+ overflow: visible;
2957
+ overflow-wrap: anywhere;
2958
+ text-overflow: clip;
2959
+ white-space: normal;
2960
+ }
2961
+
2962
+ .df-review-section-outline-name small {
2963
+ color: var(--df-review-muted);
2964
+ font-family: var(--df-review-font-mono);
2965
+ font-size: var(--df-review-font-size-xs);
2966
+ font-weight: 500;
2967
+ }
2968
+
2969
+ .df-review-section-outline-name:hover {
2970
+ color: var(--df-review-accent);
2971
+ }
2972
+
2973
+ .df-review-section-outline-links {
2974
+ display: inline-flex;
2975
+ align-items: center;
2976
+ justify-content: flex-end;
2977
+ gap: 2px;
2978
+ }
2979
+
2980
+ .df-review-section-outline-divider {
2981
+ color: var(--df-review-subtle);
2982
+ font-size: var(--df-review-font-size-xs);
2983
+ line-height: 1;
2984
+ user-select: none;
2985
+ }
2986
+
2987
+ .df-review-section-outline-link {
2988
+ display: inline-grid;
2989
+ place-items: center;
2990
+ width: 26px;
2991
+ height: 26px;
2992
+ border: 1px solid transparent;
2993
+ border-radius: var(--df-review-radius-sm);
2994
+ padding: 0;
2995
+ color: var(--df-review-muted);
2996
+ background: transparent;
2997
+ cursor: pointer;
2998
+ transition: border-color 140ms ease, background 140ms ease,
2999
+ color 140ms ease, opacity 140ms ease;
3000
+ }
3001
+
3002
+ .df-review-section-outline-link.is-dom-select {
3003
+ width: 26px;
3004
+ min-width: 26px;
3005
+ padding: 0;
3006
+ }
3007
+
3008
+ .df-review-section-outline-link.is-dom-select svg {
3009
+ width: 16px;
3010
+ height: 16px;
3011
+ }
3012
+
3013
+ .df-review-section-outline-link:hover {
3014
+ border-color: rgba(124, 199, 255, 0.34);
3015
+ color: var(--df-review-accent);
3016
+ background: var(--df-review-accent-soft);
3017
+ }
3018
+
3019
+ .df-review-section-outline-link svg {
3020
+ width: 14px;
3021
+ height: 14px;
3022
+ fill: none;
3023
+ stroke: currentColor;
3024
+ stroke-linecap: round;
3025
+ stroke-linejoin: round;
3026
+ stroke-width: 2;
3027
+ }
3028
+
3029
+ .df-review-section-outline-link:disabled {
3030
+ color: var(--df-review-subtle);
3031
+ cursor: not-allowed;
3032
+ opacity: 0.42;
3033
+ }
3034
+
3035
+ .df-review-section-outline-link:disabled:hover {
3036
+ border-color: transparent;
3037
+ color: var(--df-review-subtle);
3038
+ background: transparent;
3039
+ }
3040
+
3041
+ .df-review-section-outline-children {
3042
+ display: grid;
3043
+ }
3044
+
3045
+ .df-review-section-outline-empty {
3046
+ padding: 14px 12px 16px;
3047
+ color: var(--df-review-muted);
3048
+ font-size: var(--df-review-font-size-xs);
3049
+ font-weight: 500;
2510
3050
  }
2511
3051
 
2512
3052
  .df-review-device-frame {
@@ -2603,13 +3143,13 @@ function ensureReviewShellStyle() {
2603
3143
  .df-review-ruler-frame-label strong {
2604
3144
  color: var(--df-review-color-ruler-label-text);
2605
3145
  font-size: var(--df-review-font-size-xs);
2606
- font-weight: 900;
3146
+ font-weight: 600;
2607
3147
  }
2608
3148
 
2609
3149
  .df-review-ruler-frame-label span {
2610
3150
  color: var(--df-review-color-ruler-label-text);
2611
3151
  font-size: var(--df-review-font-size-xs);
2612
- font-weight: 900;
3152
+ font-weight: 600;
2613
3153
  opacity: 0.78;
2614
3154
  }
2615
3155
 
@@ -2622,7 +3162,7 @@ function ensureReviewShellStyle() {
2622
3162
  background: var(--df-review-color-ruler-coord-bg);
2623
3163
  color: var(--df-review-color-ruler-coord-text);
2624
3164
  font-size: var(--df-review-font-size-xs);
2625
- font-weight: 900;
3165
+ font-weight: 600;
2626
3166
  line-height: 1;
2627
3167
  white-space: nowrap;
2628
3168
  pointer-events: none;
@@ -2700,7 +3240,7 @@ function ensureReviewShellStyle() {
2700
3240
  color: var(--df-review-color-ruler-popover-text);
2701
3241
  font-family: var(--df-review-font-mono);
2702
3242
  font-size: var(--df-review-font-size-lg);
2703
- font-weight: 900;
3243
+ font-weight: 600;
2704
3244
  line-height: 1;
2705
3245
  white-space: nowrap;
2706
3246
  letter-spacing: -0.02em;
@@ -2713,12 +3253,12 @@ function ensureReviewShellStyle() {
2713
3253
  @media (max-width: 860px) {
2714
3254
  .df-review-shell,
2715
3255
  .df-review-shell.is-list-visible {
2716
- grid-template-columns: minmax(0, 1fr) 0 32px;
3256
+ grid-template-columns: minmax(0, 1fr) 0 48px;
2717
3257
  grid-template-rows: auto auto minmax(0, 1fr);
2718
3258
  }
2719
3259
 
2720
3260
  .df-review-shell.is-list-visible {
2721
- grid-template-columns: minmax(0, 1fr) minmax(260px, 70vw) 32px;
3261
+ grid-template-columns: minmax(0, 1fr) minmax(260px, 70vw) 48px;
2722
3262
  }
2723
3263
 
2724
3264
  .df-review-qa-panel {
@@ -2727,7 +3267,7 @@ function ensureReviewShellStyle() {
2727
3267
  }
2728
3268
 
2729
3269
  .df-review-tools {
2730
- flex-wrap: wrap;
3270
+ flex-wrap: nowrap;
2731
3271
  }
2732
3272
 
2733
3273
  .df-review-tool-controls {
@@ -2757,11 +3297,19 @@ function ensureReviewShellStyle() {
2757
3297
  max-height: calc(100vh - 270px);
2758
3298
  }
2759
3299
 
2760
- .df-review-panel-body {
2761
- min-height: 0;
2762
- }
2763
- }
2764
- `;
3300
+ .df-review-panel-body {
3301
+ min-height: 0;
3302
+ }
3303
+ }
3304
+
3305
+ @media (hover: none) and (pointer: coarse) {
3306
+ .df-review-edit-textarea textarea,
3307
+ .df-review-preset-select,
3308
+ .df-review-prompt-block textarea {
3309
+ font-size: 16px;
3310
+ }
3311
+ }
3312
+ `;
2765
3313
  document.head.append(style);
2766
3314
  }
2767
3315
  }
@@ -2771,7 +3319,7 @@ import {
2771
3319
  useCallback as useCallback11,
2772
3320
  useEffect as useEffect10,
2773
3321
  useMemo as useMemo7,
2774
- useRef as useRef4,
3322
+ useRef as useRef5,
2775
3323
  useState as useState10
2776
3324
  } from "react";
2777
3325
 
@@ -2890,31 +3438,59 @@ var __iconNode = [
2890
3438
  ];
2891
3439
  var Bot = createLucideIcon("bot", __iconNode);
2892
3440
 
3441
+ // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/chevron-down.mjs
3442
+ var __iconNode2 = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
3443
+ var ChevronDown = createLucideIcon("chevron-down", __iconNode2);
3444
+
2893
3445
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/circle-question-mark.mjs
2894
- var __iconNode2 = [
3446
+ var __iconNode3 = [
2895
3447
  ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
2896
3448
  ["path", { d: "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3", key: "1u773s" }],
2897
3449
  ["path", { d: "M12 17h.01", key: "p32p05" }]
2898
3450
  ];
2899
- var CircleQuestionMark = createLucideIcon("circle-question-mark", __iconNode2);
3451
+ var CircleQuestionMark = createLucideIcon("circle-question-mark", __iconNode3);
3452
+
3453
+ // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/code-xml.mjs
3454
+ var __iconNode4 = [
3455
+ ["path", { d: "m18 16 4-4-4-4", key: "1inbqp" }],
3456
+ ["path", { d: "m6 8-4 4 4 4", key: "15zrgr" }],
3457
+ ["path", { d: "m14.5 4-5 16", key: "e7oirm" }]
3458
+ ];
3459
+ var CodeXml = createLucideIcon("code-xml", __iconNode4);
2900
3460
 
2901
3461
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/copy.mjs
2902
- var __iconNode3 = [
3462
+ var __iconNode5 = [
2903
3463
  ["rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2", key: "17jyea" }],
2904
3464
  ["path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2", key: "zix9uf" }]
2905
3465
  ];
2906
- var Copy = createLucideIcon("copy", __iconNode3);
3466
+ var Copy = createLucideIcon("copy", __iconNode5);
3467
+
3468
+ // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/database.mjs
3469
+ var __iconNode6 = [
3470
+ ["ellipse", { cx: "12", cy: "5", rx: "9", ry: "3", key: "msslwz" }],
3471
+ ["path", { d: "M3 5V19A9 3 0 0 0 21 19V5", key: "1wlel7" }],
3472
+ ["path", { d: "M3 12A9 3 0 0 0 21 12", key: "mv7ke4" }]
3473
+ ];
3474
+ var Database = createLucideIcon("database", __iconNode6);
3475
+
3476
+ // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/ellipsis.mjs
3477
+ var __iconNode7 = [
3478
+ ["circle", { cx: "12", cy: "12", r: "1", key: "41hilf" }],
3479
+ ["circle", { cx: "19", cy: "12", r: "1", key: "1wjl8i" }],
3480
+ ["circle", { cx: "5", cy: "12", r: "1", key: "1pcz8c" }]
3481
+ ];
3482
+ var Ellipsis = createLucideIcon("ellipsis", __iconNode7);
2907
3483
 
2908
3484
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/external-link.mjs
2909
- var __iconNode4 = [
3485
+ var __iconNode8 = [
2910
3486
  ["path", { d: "M15 3h6v6", key: "1q9fwt" }],
2911
3487
  ["path", { d: "M10 14 21 3", key: "gplh6r" }],
2912
3488
  ["path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6", key: "a6xqqp" }]
2913
3489
  ];
2914
- var ExternalLink = createLucideIcon("external-link", __iconNode4);
3490
+ var ExternalLink = createLucideIcon("external-link", __iconNode8);
2915
3491
 
2916
3492
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/eye-off.mjs
2917
- var __iconNode5 = [
3493
+ var __iconNode9 = [
2918
3494
  [
2919
3495
  "path",
2920
3496
  {
@@ -2932,10 +3508,10 @@ var __iconNode5 = [
2932
3508
  ],
2933
3509
  ["path", { d: "m2 2 20 20", key: "1ooewy" }]
2934
3510
  ];
2935
- var EyeOff = createLucideIcon("eye-off", __iconNode5);
3511
+ var EyeOff = createLucideIcon("eye-off", __iconNode9);
2936
3512
 
2937
3513
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/eye.mjs
2938
- var __iconNode6 = [
3514
+ var __iconNode10 = [
2939
3515
  [
2940
3516
  "path",
2941
3517
  {
@@ -2943,56 +3519,61 @@ var __iconNode6 = [
2943
3519
  key: "1nclc0"
2944
3520
  }
2945
3521
  ],
2946
- ["circle", { cx: "12", cy: "12", r: "3", key: "1v7zrd" }]
2947
- ];
2948
- var Eye = createLucideIcon("eye", __iconNode6);
2949
-
2950
- // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/grip-vertical.mjs
2951
- var __iconNode7 = [
2952
- ["circle", { cx: "9", cy: "12", r: "1", key: "1vctgf" }],
2953
- ["circle", { cx: "9", cy: "5", r: "1", key: "hp0tcf" }],
2954
- ["circle", { cx: "9", cy: "19", r: "1", key: "fkjjf6" }],
2955
- ["circle", { cx: "15", cy: "12", r: "1", key: "1tmaij" }],
2956
- ["circle", { cx: "15", cy: "5", r: "1", key: "19l28e" }],
2957
- ["circle", { cx: "15", cy: "19", r: "1", key: "f4zoj3" }]
3522
+ ["circle", { cx: "12", cy: "12", r: "3", key: "1v7zrd" }]
3523
+ ];
3524
+ var Eye = createLucideIcon("eye", __iconNode10);
3525
+
3526
+ // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/file-text.mjs
3527
+ var __iconNode11 = [
3528
+ [
3529
+ "path",
3530
+ {
3531
+ d: "M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z",
3532
+ key: "1oefj6"
3533
+ }
3534
+ ],
3535
+ ["path", { d: "M14 2v5a1 1 0 0 0 1 1h5", key: "wfsgrz" }],
3536
+ ["path", { d: "M10 9H8", key: "b1mrlr" }],
3537
+ ["path", { d: "M16 13H8", key: "t4e002" }],
3538
+ ["path", { d: "M16 17H8", key: "z1uh3a" }]
2958
3539
  ];
2959
- var GripVertical = createLucideIcon("grip-vertical", __iconNode7);
3540
+ var FileText = createLucideIcon("file-text", __iconNode11);
2960
3541
 
2961
3542
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/image.mjs
2962
- var __iconNode8 = [
3543
+ var __iconNode12 = [
2963
3544
  ["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2", key: "1m3agn" }],
2964
3545
  ["circle", { cx: "9", cy: "9", r: "2", key: "af1f0g" }],
2965
3546
  ["path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21", key: "1xmnt7" }]
2966
3547
  ];
2967
- var Image = createLucideIcon("image", __iconNode8);
3548
+ var Image = createLucideIcon("image", __iconNode12);
2968
3549
 
2969
3550
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/layout-grid.mjs
2970
- var __iconNode9 = [
3551
+ var __iconNode13 = [
2971
3552
  ["rect", { width: "7", height: "7", x: "3", y: "3", rx: "1", key: "1g98yp" }],
2972
3553
  ["rect", { width: "7", height: "7", x: "14", y: "3", rx: "1", key: "6d4xhi" }],
2973
3554
  ["rect", { width: "7", height: "7", x: "14", y: "14", rx: "1", key: "nxv5o0" }],
2974
3555
  ["rect", { width: "7", height: "7", x: "3", y: "14", rx: "1", key: "1bb6yr" }]
2975
3556
  ];
2976
- var LayoutGrid = createLucideIcon("layout-grid", __iconNode9);
3557
+ var LayoutGrid = createLucideIcon("layout-grid", __iconNode13);
2977
3558
 
2978
3559
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/link-2.mjs
2979
- var __iconNode10 = [
3560
+ var __iconNode14 = [
2980
3561
  ["path", { d: "M9 17H7A5 5 0 0 1 7 7h2", key: "8i5ue5" }],
2981
3562
  ["path", { d: "M15 7h2a5 5 0 1 1 0 10h-2", key: "1b9ql8" }],
2982
3563
  ["line", { x1: "8", x2: "16", y1: "12", y2: "12", key: "1jonct" }]
2983
3564
  ];
2984
- var Link2 = createLucideIcon("link-2", __iconNode10);
3565
+ var Link2 = createLucideIcon("link-2", __iconNode14);
2985
3566
 
2986
3567
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/list-filter.mjs
2987
- var __iconNode11 = [
3568
+ var __iconNode15 = [
2988
3569
  ["path", { d: "M2 5h20", key: "1fs1ex" }],
2989
3570
  ["path", { d: "M6 12h12", key: "8npq4p" }],
2990
3571
  ["path", { d: "M9 19h6", key: "456am0" }]
2991
3572
  ];
2992
- var ListFilter = createLucideIcon("list-filter", __iconNode11);
3573
+ var ListFilter = createLucideIcon("list-filter", __iconNode15);
2993
3574
 
2994
3575
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/map.mjs
2995
- var __iconNode12 = [
3576
+ var __iconNode16 = [
2996
3577
  [
2997
3578
  "path",
2998
3579
  {
@@ -3003,27 +3584,39 @@ var __iconNode12 = [
3003
3584
  ["path", { d: "M15 5.764v15", key: "1pn4in" }],
3004
3585
  ["path", { d: "M9 3.236v15", key: "1uimfh" }]
3005
3586
  ];
3006
- var Map2 = createLucideIcon("map", __iconNode12);
3587
+ var Map2 = createLucideIcon("map", __iconNode16);
3007
3588
 
3008
3589
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/maximize-2.mjs
3009
- var __iconNode13 = [
3590
+ var __iconNode17 = [
3010
3591
  ["path", { d: "M15 3h6v6", key: "1q9fwt" }],
3011
3592
  ["path", { d: "m21 3-7 7", key: "1l2asr" }],
3012
3593
  ["path", { d: "m3 21 7-7", key: "tjx5ai" }],
3013
3594
  ["path", { d: "M9 21H3v-6", key: "wtvkvv" }]
3014
3595
  ];
3015
- var Maximize2 = createLucideIcon("maximize-2", __iconNode13);
3596
+ var Maximize2 = createLucideIcon("maximize-2", __iconNode17);
3016
3597
 
3017
3598
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/monitor.mjs
3018
- var __iconNode14 = [
3599
+ var __iconNode18 = [
3019
3600
  ["rect", { width: "20", height: "14", x: "2", y: "3", rx: "2", key: "48i651" }],
3020
3601
  ["line", { x1: "8", x2: "16", y1: "21", y2: "21", key: "1svkeh" }],
3021
3602
  ["line", { x1: "12", x2: "12", y1: "17", y2: "21", key: "vw1qmm" }]
3022
3603
  ];
3023
- var Monitor = createLucideIcon("monitor", __iconNode14);
3604
+ var Monitor = createLucideIcon("monitor", __iconNode18);
3605
+
3606
+ // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/moon.mjs
3607
+ var __iconNode19 = [
3608
+ [
3609
+ "path",
3610
+ {
3611
+ d: "M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401",
3612
+ key: "kfwtm"
3613
+ }
3614
+ ]
3615
+ ];
3616
+ var Moon = createLucideIcon("moon", __iconNode19);
3024
3617
 
3025
3618
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/pencil.mjs
3026
- var __iconNode15 = [
3619
+ var __iconNode20 = [
3027
3620
  [
3028
3621
  "path",
3029
3622
  {
@@ -3033,25 +3626,25 @@ var __iconNode15 = [
3033
3626
  ],
3034
3627
  ["path", { d: "m15 5 4 4", key: "1mk7zo" }]
3035
3628
  ];
3036
- var Pencil = createLucideIcon("pencil", __iconNode15);
3629
+ var Pencil = createLucideIcon("pencil", __iconNode20);
3037
3630
 
3038
3631
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/rectangle-horizontal.mjs
3039
- var __iconNode16 = [
3632
+ var __iconNode21 = [
3040
3633
  ["rect", { width: "20", height: "12", x: "2", y: "6", rx: "2", key: "9lu3g6" }]
3041
3634
  ];
3042
- var RectangleHorizontal = createLucideIcon("rectangle-horizontal", __iconNode16);
3635
+ var RectangleHorizontal = createLucideIcon("rectangle-horizontal", __iconNode21);
3043
3636
 
3044
3637
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/refresh-cw.mjs
3045
- var __iconNode17 = [
3638
+ var __iconNode22 = [
3046
3639
  ["path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8", key: "v9h5vc" }],
3047
3640
  ["path", { d: "M21 3v5h-5", key: "1q7to0" }],
3048
3641
  ["path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16", key: "3uifl3" }],
3049
3642
  ["path", { d: "M8 16H3v5", key: "1cv678" }]
3050
3643
  ];
3051
- var RefreshCw = createLucideIcon("refresh-cw", __iconNode17);
3644
+ var RefreshCw = createLucideIcon("refresh-cw", __iconNode22);
3052
3645
 
3053
3646
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/ruler.mjs
3054
- var __iconNode18 = [
3647
+ var __iconNode23 = [
3055
3648
  [
3056
3649
  "path",
3057
3650
  {
@@ -3064,19 +3657,26 @@ var __iconNode18 = [
3064
3657
  ["path", { d: "m8.5 6.5 2-2", key: "vc6u1g" }],
3065
3658
  ["path", { d: "m17.5 15.5 2-2", key: "wo5hmg" }]
3066
3659
  ];
3067
- var Ruler = createLucideIcon("ruler", __iconNode18);
3660
+ var Ruler = createLucideIcon("ruler", __iconNode23);
3068
3661
 
3069
3662
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/scan.mjs
3070
- var __iconNode19 = [
3663
+ var __iconNode24 = [
3071
3664
  ["path", { d: "M3 7V5a2 2 0 0 1 2-2h2", key: "aa7l1z" }],
3072
3665
  ["path", { d: "M17 3h2a2 2 0 0 1 2 2v2", key: "4qcy5o" }],
3073
3666
  ["path", { d: "M21 17v2a2 2 0 0 1-2 2h-2", key: "6vwrx8" }],
3074
3667
  ["path", { d: "M7 21H5a2 2 0 0 1-2-2v-2", key: "ioqczr" }]
3075
3668
  ];
3076
- var Scan = createLucideIcon("scan", __iconNode19);
3669
+ var Scan = createLucideIcon("scan", __iconNode24);
3670
+
3671
+ // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/search.mjs
3672
+ var __iconNode25 = [
3673
+ ["path", { d: "m21 21-4.34-4.34", key: "14j7rj" }],
3674
+ ["circle", { cx: "11", cy: "11", r: "8", key: "4ej97u" }]
3675
+ ];
3676
+ var Search = createLucideIcon("search", __iconNode25);
3077
3677
 
3078
3678
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/settings.mjs
3079
- var __iconNode20 = [
3679
+ var __iconNode26 = [
3080
3680
  [
3081
3681
  "path",
3082
3682
  {
@@ -3086,17 +3686,17 @@ var __iconNode20 = [
3086
3686
  ],
3087
3687
  ["circle", { cx: "12", cy: "12", r: "3", key: "1v7zrd" }]
3088
3688
  ];
3089
- var Settings = createLucideIcon("settings", __iconNode20);
3689
+ var Settings = createLucideIcon("settings", __iconNode26);
3090
3690
 
3091
3691
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/smartphone.mjs
3092
- var __iconNode21 = [
3692
+ var __iconNode27 = [
3093
3693
  ["rect", { width: "14", height: "20", x: "5", y: "2", rx: "2", ry: "2", key: "1yt0o3" }],
3094
3694
  ["path", { d: "M12 18h.01", key: "mhygvu" }]
3095
3695
  ];
3096
- var Smartphone = createLucideIcon("smartphone", __iconNode21);
3696
+ var Smartphone = createLucideIcon("smartphone", __iconNode27);
3097
3697
 
3098
3698
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/square-mouse-pointer.mjs
3099
- var __iconNode22 = [
3699
+ var __iconNode28 = [
3100
3700
  [
3101
3701
  "path",
3102
3702
  {
@@ -3106,10 +3706,10 @@ var __iconNode22 = [
3106
3706
  ],
3107
3707
  ["path", { d: "M21 11V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h6", key: "14rsvq" }]
3108
3708
  ];
3109
- var SquareMousePointer = createLucideIcon("square-mouse-pointer", __iconNode22);
3709
+ var SquareMousePointer = createLucideIcon("square-mouse-pointer", __iconNode28);
3110
3710
 
3111
3711
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/sticky-note.mjs
3112
- var __iconNode23 = [
3712
+ var __iconNode29 = [
3113
3713
  [
3114
3714
  "path",
3115
3715
  {
@@ -3119,22 +3719,43 @@ var __iconNode23 = [
3119
3719
  ],
3120
3720
  ["path", { d: "M15 3v5a1 1 0 0 0 1 1h5", key: "6s6qgf" }]
3121
3721
  ];
3122
- var StickyNote = createLucideIcon("sticky-note", __iconNode23);
3722
+ var StickyNote = createLucideIcon("sticky-note", __iconNode29);
3723
+
3724
+ // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/sun.mjs
3725
+ var __iconNode30 = [
3726
+ ["circle", { cx: "12", cy: "12", r: "4", key: "4exip2" }],
3727
+ ["path", { d: "M12 2v2", key: "tus03m" }],
3728
+ ["path", { d: "M12 20v2", key: "1lh1kg" }],
3729
+ ["path", { d: "m4.93 4.93 1.41 1.41", key: "149t6j" }],
3730
+ ["path", { d: "m17.66 17.66 1.41 1.41", key: "ptbguv" }],
3731
+ ["path", { d: "M2 12h2", key: "1t8f8n" }],
3732
+ ["path", { d: "M20 12h2", key: "1q8mjw" }],
3733
+ ["path", { d: "m6.34 17.66-1.41 1.41", key: "1m8zz5" }],
3734
+ ["path", { d: "m19.07 4.93-1.41 1.41", key: "1shlcs" }]
3735
+ ];
3736
+ var Sun = createLucideIcon("sun", __iconNode30);
3123
3737
 
3124
3738
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/upload.mjs
3125
- var __iconNode24 = [
3739
+ var __iconNode31 = [
3126
3740
  ["path", { d: "M12 3v12", key: "1x0j5s" }],
3127
3741
  ["path", { d: "m17 8-5-5-5 5", key: "7q97r8" }],
3128
3742
  ["path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4", key: "ih7n3h" }]
3129
3743
  ];
3130
- var Upload = createLucideIcon("upload", __iconNode24);
3744
+ var Upload = createLucideIcon("upload", __iconNode31);
3745
+
3746
+ // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/user-round.mjs
3747
+ var __iconNode32 = [
3748
+ ["circle", { cx: "12", cy: "8", r: "5", key: "1hypcn" }],
3749
+ ["path", { d: "M20 21a8 8 0 0 0-16 0", key: "rfgkzh" }]
3750
+ ];
3751
+ var UserRound = createLucideIcon("user-round", __iconNode32);
3131
3752
 
3132
3753
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/x.mjs
3133
- var __iconNode25 = [
3754
+ var __iconNode33 = [
3134
3755
  ["path", { d: "M18 6 6 18", key: "1bl5f8" }],
3135
3756
  ["path", { d: "m6 6 12 12", key: "d8bk6v" }]
3136
3757
  ];
3137
- var X = createLucideIcon("x", __iconNode25);
3758
+ var X = createLucideIcon("x", __iconNode33);
3138
3759
 
3139
3760
  // src/react-shell/constants.ts
3140
3761
  var REVIEW_QA_FILTERS = [
@@ -3643,6 +4264,11 @@ var getSystemReviewTheme = () => {
3643
4264
 
3644
4265
  // src/react-shell/review/settings.modal.tsx
3645
4266
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
4267
+ var getReviewThemeIcon = (theme) => {
4268
+ if (theme === "light") return Sun;
4269
+ if (theme === "system") return Monitor;
4270
+ return Moon;
4271
+ };
3646
4272
  var ReviewSettingsModal = ({
3647
4273
  figmaTokenDraft,
3648
4274
  reviewUserIdDraft,
@@ -3702,20 +4328,28 @@ var ReviewSettingsModal = ({
3702
4328
  /* @__PURE__ */ jsxs2("div", { className: "df-review-settings-body", children: [
3703
4329
  /* @__PURE__ */ jsxs2("div", { className: "df-review-settings-row", children: [
3704
4330
  /* @__PURE__ */ jsx2("span", { children: "Theme" }),
3705
- /* @__PURE__ */ jsx2("div", { className: "df-review-settings-theme-options", children: REVIEW_THEME_OPTIONS.map((option) => /* @__PURE__ */ jsx2(
3706
- "button",
3707
- {
3708
- "aria-pressed": reviewThemeDraft === option.value,
3709
- className: `df-review-settings-theme-option${reviewThemeDraft === option.value ? " is-active" : ""}`,
3710
- type: "button",
3711
- onClick: () => {
3712
- onReviewThemeDraftChange(normalizeReviewTheme(option.value));
3713
- onClearStatus();
4331
+ /* @__PURE__ */ jsx2("div", { className: "df-review-settings-theme-options", children: REVIEW_THEME_OPTIONS.map((option) => {
4332
+ const ThemeIcon = getReviewThemeIcon(option.value);
4333
+ return /* @__PURE__ */ jsxs2(
4334
+ "button",
4335
+ {
4336
+ "aria-pressed": reviewThemeDraft === option.value,
4337
+ className: `df-review-settings-theme-option${reviewThemeDraft === option.value ? " is-active" : ""}`,
4338
+ type: "button",
4339
+ onClick: () => {
4340
+ onReviewThemeDraftChange(
4341
+ normalizeReviewTheme(option.value)
4342
+ );
4343
+ onClearStatus();
4344
+ },
4345
+ children: [
4346
+ /* @__PURE__ */ jsx2(ThemeIcon, { "aria-hidden": "true" }),
4347
+ /* @__PURE__ */ jsx2("span", { children: option.label })
4348
+ ]
3714
4349
  },
3715
- children: option.label
3716
- },
3717
- option.value
3718
- )) })
4350
+ option.value
4351
+ );
4352
+ }) })
3719
4353
  ] }),
3720
4354
  /* @__PURE__ */ jsxs2("div", { className: "df-review-settings-field", children: [
3721
4355
  /* @__PURE__ */ jsxs2("div", { className: "df-review-settings-label-row", children: [
@@ -4893,6 +5527,33 @@ var QaPanelHeader = ({
4893
5527
  }
4894
5528
  )
4895
5529
  ] }),
5530
+ /* @__PURE__ */ jsxs7(
5531
+ "select",
5532
+ {
5533
+ "aria-label": "QA status filter",
5534
+ className: "df-review-status-filter-select",
5535
+ value: qaStatusFilter,
5536
+ onChange: (event) => onQaStatusFilterChange(
5537
+ event.currentTarget.value
5538
+ ),
5539
+ children: [
5540
+ /* @__PURE__ */ jsx9("option", { value: "all", children: `All status (${qaStatusFilterCounts.get("all") ?? 0})` }),
5541
+ statusFilterOptions.map((statusOption) => /* @__PURE__ */ jsx9("option", { value: statusOption.value, children: `${statusOption.label} (${qaStatusFilterCounts.get(statusOption.value) ?? 0})` }, statusOption.value))
5542
+ ]
5543
+ }
5544
+ )
5545
+ ] }),
5546
+ /* @__PURE__ */ jsxs7("div", { className: "df-review-list-title", children: [
5547
+ /* @__PURE__ */ jsxs7("span", { className: "df-review-list-meta", children: [
5548
+ /* @__PURE__ */ jsx9("span", { children: isAllQaVisible ? `${label} QA \xB7 All pages` : `${label} QA` }),
5549
+ /* @__PURE__ */ jsx9(
5550
+ "strong",
5551
+ {
5552
+ title: `${activeRemainingItemCount} remaining of ${activeItemCount}`,
5553
+ children: !hasActiveFilter ? `${activeRemainingItemCount}/${activeItemCount}` : `${filteredItemCount}/${activeItemCount}`
5554
+ }
5555
+ )
5556
+ ] }),
4896
5557
  /* @__PURE__ */ jsx9("div", { className: "df-review-filter-tabs", "aria-label": "QA filters", children: REVIEW_QA_FILTERS.map((filter) => {
4897
5558
  const count = qaFilterCounts.get(filter.key) ?? 0;
4898
5559
  const isActive = qaFilter === filter.key;
@@ -4909,25 +5570,6 @@ var QaPanelHeader = ({
4909
5570
  filter.key
4910
5571
  );
4911
5572
  }) })
4912
- ] }),
4913
- /* @__PURE__ */ jsxs7("div", { className: "df-review-list-title", children: [
4914
- /* @__PURE__ */ jsx9("span", { children: isAllQaVisible ? `${label} QA \xB7 All pages` : `${label} QA` }),
4915
- /* @__PURE__ */ jsx9("strong", { title: `${activeRemainingItemCount} remaining of ${activeItemCount}`, children: !hasActiveFilter ? `${activeRemainingItemCount}/${activeItemCount}` : `${filteredItemCount}/${activeItemCount}` }),
4916
- /* @__PURE__ */ jsxs7(
4917
- "select",
4918
- {
4919
- "aria-label": "QA status filter",
4920
- className: "df-review-status-filter-select",
4921
- value: qaStatusFilter,
4922
- onChange: (event) => onQaStatusFilterChange(
4923
- event.currentTarget.value
4924
- ),
4925
- children: [
4926
- /* @__PURE__ */ jsx9("option", { value: "all", children: `All status (${qaStatusFilterCounts.get("all") ?? 0})` }),
4927
- statusFilterOptions.map((statusOption) => /* @__PURE__ */ jsx9("option", { value: statusOption.value, children: `${statusOption.label} (${qaStatusFilterCounts.get(statusOption.value) ?? 0})` }, statusOption.value))
4928
- ]
4929
- }
4930
- )
4931
5573
  ] })
4932
5574
  ] });
4933
5575
  };
@@ -5053,7 +5695,6 @@ var ReviewQaPanel = ({
5053
5695
  // src/react-shell/presence/overlay.tsx
5054
5696
  import { useState as useState3 } from "react";
5055
5697
  import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
5056
- var COLLAPSED_USER_COUNT = 1;
5057
5698
  var getPresenceName = (user) => user.displayName || user.userId;
5058
5699
  var PresenceOverlay = ({
5059
5700
  presenceSessionId,
@@ -5061,18 +5702,31 @@ var PresenceOverlay = ({
5061
5702
  }) => {
5062
5703
  const [isExpanded, setIsExpanded] = useState3(false);
5063
5704
  if (users.length === 0) return null;
5064
- const visibleUsers = isExpanded ? users : users.slice(0, COLLAPSED_USER_COUNT);
5065
- const hiddenUserCount = users.length - visibleUsers.length;
5066
5705
  return /* @__PURE__ */ jsxs9(
5067
5706
  "div",
5068
5707
  {
5069
5708
  "aria-label": `Review presence, ${users.length} online`,
5070
5709
  className: `df-review-presence-overlay${isExpanded ? " is-expanded" : ""}`,
5071
5710
  children: [
5072
- visibleUsers.map((user) => /* @__PURE__ */ jsx11(
5711
+ /* @__PURE__ */ jsxs9(
5712
+ "button",
5713
+ {
5714
+ "aria-label": `Show online reviewers, ${users.length} online`,
5715
+ "aria-expanded": isExpanded,
5716
+ className: "df-review-presence-button",
5717
+ type: "button",
5718
+ onClick: () => setIsExpanded((current) => !current),
5719
+ children: [
5720
+ /* @__PURE__ */ jsx11(UserRound, { "aria-hidden": "true" }),
5721
+ /* @__PURE__ */ jsx11("span", { className: "df-review-presence-badge", children: users.length })
5722
+ ]
5723
+ }
5724
+ ),
5725
+ isExpanded && /* @__PURE__ */ jsx11("div", { className: "df-review-presence-list", role: "list", children: users.map((user) => /* @__PURE__ */ jsx11(
5073
5726
  "span",
5074
5727
  {
5075
5728
  className: `df-review-presence-chip${user.sessionId === presenceSessionId ? " is-self" : ""}`,
5729
+ role: "listitem",
5076
5730
  style: {
5077
5731
  "--df-review-presence-color": user.color
5078
5732
  },
@@ -5080,21 +5734,7 @@ var PresenceOverlay = ({
5080
5734
  children: getPresenceName(user)
5081
5735
  },
5082
5736
  user.sessionId
5083
- )),
5084
- hiddenUserCount > 0 && /* @__PURE__ */ jsxs9(
5085
- "button",
5086
- {
5087
- "aria-label": `Show ${hiddenUserCount} more online reviewers`,
5088
- "aria-expanded": isExpanded,
5089
- className: "df-review-presence-more",
5090
- type: "button",
5091
- onClick: () => setIsExpanded(true),
5092
- children: [
5093
- "+",
5094
- hiddenUserCount
5095
- ]
5096
- }
5097
- )
5737
+ )) })
5098
5738
  ]
5099
5739
  }
5100
5740
  );
@@ -5111,28 +5751,173 @@ var SOURCE_SELECTOR = [
5111
5751
  "[data-section-index]",
5112
5752
  "[data-section-id]"
5113
5753
  ].join(", ");
5114
- var getSourceCandidates = (target) => {
5754
+ var SECTION_OUTLINE_ROOT_SELECTOR = [
5755
+ "[data-wrk-source-component]",
5756
+ "header[data-wrk-source-file]",
5757
+ "footer[data-wrk-source-file]",
5758
+ '[role="banner"][data-wrk-source-file]',
5759
+ '[role="contentinfo"][data-wrk-source-file]'
5760
+ ].join(", ");
5761
+ var matchesIgnore = (file, patterns) => {
5762
+ const normalized = file.replace(/\\/g, "/");
5763
+ return patterns.some(
5764
+ (pattern) => typeof pattern === "string" ? normalized.includes(pattern) : pattern.test(normalized)
5765
+ );
5766
+ };
5767
+ var getSourceCandidates = (target, options) => {
5115
5768
  const startElement = getEventElement(target);
5116
5769
  if (!startElement) return [];
5117
5770
  const candidates = [];
5118
5771
  const seen = /* @__PURE__ */ new Set();
5772
+ const add = (element2, source, depth2, kind) => {
5773
+ if (!source?.file) return;
5774
+ const key = getSourceFileCompareKey(source.file);
5775
+ if (!addSourceFileCompareKey(seen, key)) return;
5776
+ candidates.push(createSourceCandidate(element2, source, depth2, kind));
5777
+ };
5119
5778
  let element = startElement;
5120
5779
  let depth = 0;
5121
5780
  while (element && element.nodeType === 1) {
5122
- const source = getSourceHintFromElement(element);
5123
- if (source?.file) {
5124
- const key = getSourceCandidateKey(source);
5125
- if (!seen.has(key)) {
5126
- seen.add(key);
5127
- candidates.push(createSourceCandidate(element, source, depth));
5128
- }
5129
- }
5781
+ add(element, getSourceHintFromElement(element), depth, "source");
5782
+ add(element, getDataHintFromElement(element), 0, "data");
5130
5783
  if (element === element.ownerDocument.documentElement) break;
5131
5784
  element = element.parentElement;
5132
5785
  depth += 1;
5133
5786
  }
5134
- return candidates.slice(0, 8);
5787
+ const ignore = options?.ignore;
5788
+ const visible = candidates.filter(
5789
+ (candidate) => !isCoreOutlineNode(candidate.label, candidate.source.file) && !(ignore?.length && matchesIgnore(candidate.source.file ?? "", ignore))
5790
+ );
5791
+ return visible.slice(0, 8);
5792
+ };
5793
+ var getSectionOutline = (root, options) => {
5794
+ const maxDepth = options?.maxDepth ?? 9;
5795
+ return getSectionOutlineRoots(root, options).map((element, index) => {
5796
+ const source = getSourceHintFromElement(element);
5797
+ const label = getOutlineLabel(element, source, "section");
5798
+ const seen = /* @__PURE__ */ new Set();
5799
+ if (source?.file) {
5800
+ addSourceFileCompareKey(seen, getOutlineSourceKey(source));
5801
+ }
5802
+ return {
5803
+ id: `${label}-${index}`,
5804
+ label,
5805
+ depth: 1,
5806
+ filePath: getDisplaySourcePath(source?.file) ?? label,
5807
+ element,
5808
+ source,
5809
+ data: getDataHintFromElement(element),
5810
+ children: getSectionOutlineChildren(
5811
+ element,
5812
+ 2,
5813
+ maxDepth,
5814
+ seen,
5815
+ options
5816
+ )
5817
+ };
5818
+ });
5135
5819
  };
5820
+ function getSectionOutlineRoots(root, options) {
5821
+ return Array.from(root.querySelectorAll(SECTION_OUTLINE_ROOT_SELECTOR)).filter(
5822
+ (element) => {
5823
+ const source = getSourceHintFromElement(element);
5824
+ const label = getOutlineLabel(element, source, "");
5825
+ return !isSkippedOutlineNode(label, source?.file, options);
5826
+ }
5827
+ );
5828
+ }
5829
+ function getSectionOutlineChildren(parent, depth, maxDepth, seen, options) {
5830
+ if (depth > maxDepth) return [];
5831
+ const entries = [];
5832
+ for (const child of Array.from(parent.children)) {
5833
+ const source = getSourceHintFromElement(child);
5834
+ const label = getOutlineLabel(child, source, child.tagName.toLowerCase());
5835
+ const sourceKey = source?.file ? getOutlineSourceKey(source) : "";
5836
+ const isNewSource = Boolean(sourceKey) && !hasEquivalentSourceFileKey(seen, sourceKey);
5837
+ if (shouldStopOutlineBranch(label, source?.file, options)) continue;
5838
+ if (isHiddenOutlineNode(label, source?.file, options)) {
5839
+ entries.push(
5840
+ ...getSectionOutlineChildren(child, depth, maxDepth, seen, options)
5841
+ );
5842
+ continue;
5843
+ }
5844
+ if (source?.file && isNewSource) {
5845
+ const childSeen = new Set(seen);
5846
+ addSourceFileCompareKey(childSeen, sourceKey);
5847
+ entries.push({
5848
+ id: `${sourceKey}-${getElementOutlinePath(child)}-${entries.length}`,
5849
+ label,
5850
+ depth,
5851
+ filePath: getDisplaySourcePath(source.file) ?? source.file,
5852
+ element: child,
5853
+ source,
5854
+ data: getDataHintFromElement(child),
5855
+ children: getSectionOutlineChildren(
5856
+ child,
5857
+ depth + 1,
5858
+ maxDepth,
5859
+ childSeen,
5860
+ options
5861
+ )
5862
+ });
5863
+ continue;
5864
+ }
5865
+ entries.push(
5866
+ ...getSectionOutlineChildren(child, depth, maxDepth, seen, options)
5867
+ );
5868
+ }
5869
+ return entries;
5870
+ }
5871
+ function getElementOutlinePath(element) {
5872
+ const indices = [];
5873
+ let current = element;
5874
+ while (current?.parentElement) {
5875
+ indices.unshift(Array.from(current.parentElement.children).indexOf(current));
5876
+ current = current.parentElement;
5877
+ }
5878
+ return indices.join("-");
5879
+ }
5880
+ function getOutlineSourceKey(source) {
5881
+ return getSourceFileCompareKey(source.file);
5882
+ }
5883
+ function getSourceFileCompareKey(file) {
5884
+ return file?.trim().replace(/\\/g, "/") ?? "";
5885
+ }
5886
+ function addSourceFileCompareKey(seen, key) {
5887
+ if (!key || hasEquivalentSourceFileKey(seen, key)) return false;
5888
+ seen.add(key);
5889
+ return true;
5890
+ }
5891
+ function hasEquivalentSourceFileKey(seen, key) {
5892
+ for (const seenKey of seen) {
5893
+ if (isEquivalentSourceFileKey(seenKey, key)) return true;
5894
+ }
5895
+ return false;
5896
+ }
5897
+ function isEquivalentSourceFileKey(a, b) {
5898
+ return a === b || a.endsWith(`/${b}`) || b.endsWith(`/${a}`);
5899
+ }
5900
+ function getOutlineLabel(element, source, fallback) {
5901
+ return source?.component?.trim() || getComponentNameFromSourceFile(source?.file) || element.id.trim() || fallback;
5902
+ }
5903
+ function isHiddenOutlineNode(label, file, options) {
5904
+ const ignore = options?.ignore;
5905
+ const isIgnoredSource = file && ignore?.length ? matchesIgnore(file, ignore) : false;
5906
+ return isCoreOutlineNode(label, file) || isIgnoredSource;
5907
+ }
5908
+ function shouldStopOutlineBranch(label, file, options) {
5909
+ return !options?.includePlacer && isPlacerOutlineNode(label, file);
5910
+ }
5911
+ function isSkippedOutlineNode(label, file, options) {
5912
+ return shouldStopOutlineBranch(label, file, options) || isHiddenOutlineNode(label, file, options);
5913
+ }
5914
+ function isCoreOutlineNode(label, file) {
5915
+ const text = `${label} ${file ?? ""}`.toLowerCase();
5916
+ return text.includes("core.section") || text.includes("core.content") || text.includes("core.column") || ["coresection", "corecontent", "corecolumn"].includes(label.toLowerCase());
5917
+ }
5918
+ function isPlacerOutlineNode(label, file) {
5919
+ return `${label} ${file ?? ""}`.toLowerCase().includes("placer");
5920
+ }
5136
5921
  var getSourceOpenUrl = (source, options) => {
5137
5922
  const normalizedOptions = normalizeSourceOpenOptions(options);
5138
5923
  const file = source?.file?.trim();
@@ -5171,6 +5956,18 @@ var openSourceInEditor = (source, options) => {
5171
5956
  window.open(url, "_blank", "noreferrer");
5172
5957
  return true;
5173
5958
  };
5959
+ function getDataHintFromElement(element) {
5960
+ const file = getSourceAttribute(element, "data-wrk-data-file");
5961
+ if (!file) return void 0;
5962
+ return {
5963
+ component: void 0,
5964
+ file,
5965
+ line: getSourceAttribute(element, "data-wrk-data-line"),
5966
+ column: void 0,
5967
+ sectionId: void 0,
5968
+ sectionIndex: void 0
5969
+ };
5970
+ }
5174
5971
  function getSourceHintFromElement(element) {
5175
5972
  const source = {
5176
5973
  component: getSourceAttribute(
@@ -5186,7 +5983,7 @@ function getSourceHintFromElement(element) {
5186
5983
  };
5187
5984
  return Object.values(source).some(Boolean) ? source : void 0;
5188
5985
  }
5189
- function createSourceCandidate(element, source, depth) {
5986
+ function createSourceCandidate(element, source, depth, kind) {
5190
5987
  const confidence = getSourceConfidence(source, depth);
5191
5988
  const fileName = source.file?.split(/[\\/]/).pop() ?? source.file ?? "source";
5192
5989
  const component = source.component?.trim();
@@ -5196,7 +5993,7 @@ function createSourceCandidate(element, source, depth) {
5196
5993
  const column = getSourcePosition(source.column);
5197
5994
  const position = line ? `:${line}${column ? `:${column}` : ""}` : "";
5198
5995
  return {
5199
- id: getSourceCandidateKey(source),
5996
+ id: `${kind}:${getSourceCandidateKey(source)}`,
5200
5997
  depth,
5201
5998
  element,
5202
5999
  filePath: getDisplaySourcePath(source.file) ?? fileName,
@@ -5205,6 +6002,7 @@ function createSourceCandidate(element, source, depth) {
5205
6002
  positionLabel: line ? `${line}:${column ?? 1}` : "",
5206
6003
  confidence,
5207
6004
  confidenceLabel: confidence >= 0.82 ? "high" : confidence >= 0.58 ? "medium" : "low",
6005
+ kind,
5208
6006
  usesPosition: confidence >= 0.72 && Boolean(line),
5209
6007
  source
5210
6008
  };
@@ -5228,7 +6026,7 @@ function getDisplaySourcePath(file) {
5228
6026
  const normalizedFile = file?.trim().replace(/\\/g, "/");
5229
6027
  if (!normalizedFile) return void 0;
5230
6028
  const sourceRootMatch = normalizedFile.match(
5231
- /(?:^|\/)((?:dev\/)?src\/.+|app\/.+|pages\/.+|components\/.+)$/
6029
+ /(?:^|\/)((?:dev\/)?src\/.+|app\/.+|pages?\/.+|components\/.+)$/
5232
6030
  );
5233
6031
  return sourceRootMatch?.[1] ?? normalizedFile;
5234
6032
  }
@@ -5614,6 +6412,97 @@ var FigmaIcon = () => /* @__PURE__ */ jsx15(
5614
6412
  }
5615
6413
  );
5616
6414
 
6415
+ // src/react-shell/target/target.ts
6416
+ var HIDE_SCROLLBAR_STYLE_ID = "df-review-hide-scrollbar";
6417
+ var FIGMA_POINTER_LOCK_STYLE_ID = "df-review-figma-pointer-lock";
6418
+ var setTargetScrollbarHidden = (targetDocument, hidden) => {
6419
+ if (!targetDocument) return;
6420
+ const existing = targetDocument.getElementById(HIDE_SCROLLBAR_STYLE_ID);
6421
+ if (hidden) {
6422
+ if (existing) return;
6423
+ const style = targetDocument.createElement("style");
6424
+ style.id = HIDE_SCROLLBAR_STYLE_ID;
6425
+ style.textContent = "html{scrollbar-width:none}html::-webkit-scrollbar,body::-webkit-scrollbar{width:0;height:0;display:none}";
6426
+ targetDocument.head?.appendChild(style);
6427
+ } else {
6428
+ existing?.remove();
6429
+ }
6430
+ };
6431
+ var setTargetFigmaOverlayLocked = (targetDocument, locked) => {
6432
+ if (!targetDocument) return;
6433
+ const existing = targetDocument.getElementById(FIGMA_POINTER_LOCK_STYLE_ID);
6434
+ if (locked) {
6435
+ if (existing) return;
6436
+ const style = targetDocument.createElement("style");
6437
+ style.id = FIGMA_POINTER_LOCK_STYLE_ID;
6438
+ style.textContent = [
6439
+ ".helper-figma-root,",
6440
+ ".helper-figma-root *,",
6441
+ ".helper-figma-loading-backdrop,",
6442
+ ".helper-figma-loading-backdrop * {",
6443
+ "pointer-events: none !important;",
6444
+ "}"
6445
+ ].join("\n");
6446
+ targetDocument.head?.appendChild(style);
6447
+ } else {
6448
+ existing?.remove();
6449
+ }
6450
+ };
6451
+ var isEditableEventTarget = (event) => {
6452
+ const path = event.composedPath?.() ?? [];
6453
+ const element = path[0] ?? event.target;
6454
+ if (!element || typeof element.tagName !== "string") return false;
6455
+ const tag = element.tagName;
6456
+ return tag === "INPUT" || tag === "TEXTAREA" || element.isContentEditable === true;
6457
+ };
6458
+ var TRUE_STORAGE_VALUES = /* @__PURE__ */ new Set([
6459
+ "1",
6460
+ "true",
6461
+ "on",
6462
+ "show",
6463
+ "shown",
6464
+ "visible",
6465
+ "enabled",
6466
+ "yes"
6467
+ ]);
6468
+ var OVERLAY_STORAGE_KEYS = {
6469
+ grid: ["isHelp", "df-review-grid-overlay", "dfReviewGridOverlay"],
6470
+ figma: ["isFigmaHelp", "df-review-figma-overlay", "dfReviewFigmaOverlay"]
6471
+ };
6472
+ var isStoredOverlayEnabled = (value) => TRUE_STORAGE_VALUES.has(value?.trim().toLowerCase() ?? "");
6473
+ var getCookieValue = (targetDocument, name) => {
6474
+ const cookies = targetDocument?.cookie ? targetDocument.cookie.split(";") : [];
6475
+ const prefix = `${name}=`;
6476
+ const match = cookies.map((cookie) => cookie.trim()).find((cookie) => cookie.startsWith(prefix));
6477
+ return match ? decodeURIComponent(match.slice(prefix.length)) : null;
6478
+ };
6479
+ var getStorageValue = (storage, key) => {
6480
+ try {
6481
+ return storage?.getItem(key) ?? null;
6482
+ } catch {
6483
+ return null;
6484
+ }
6485
+ };
6486
+ var getStoredOverlayState = (targetDocument, overlay) => {
6487
+ const targetWindow = targetDocument?.defaultView;
6488
+ return OVERLAY_STORAGE_KEYS[overlay].some((key) => {
6489
+ if (isStoredOverlayEnabled(getCookieValue(targetDocument, key))) {
6490
+ return true;
6491
+ }
6492
+ return isStoredOverlayEnabled(getStorageValue(targetWindow?.localStorage, key)) || isStoredOverlayEnabled(getStorageValue(targetWindow?.sessionStorage, key));
6493
+ });
6494
+ };
6495
+ var getTargetOverlayState = (targetDocument) => ({
6496
+ grid: Boolean(
6497
+ targetDocument?.body.classList.contains("is-help") || targetDocument?.querySelector(".helper.onShow") || getStoredOverlayState(targetDocument, "grid")
6498
+ ),
6499
+ figma: Boolean(
6500
+ targetDocument?.querySelector(
6501
+ ".helper-figma-root, .helper-figma-loading-backdrop"
6502
+ ) || getStoredOverlayState(targetDocument, "figma")
6503
+ )
6504
+ });
6505
+
5617
6506
  // src/react-shell/topbar.tsx
5618
6507
  import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
5619
6508
  var ReviewScopeIcon2 = ({ scope }) => {
@@ -5628,6 +6517,7 @@ var ViewportPresetIcon = ({
5628
6517
  }) => {
5629
6518
  return /* @__PURE__ */ jsx16(ReviewScopeIcon2, { scope: getViewportPresetKind(preset) });
5630
6519
  };
6520
+ var getPresetSelectValue = (preset) => `${preset.label}:${preset.width}x${preset.height}`;
5631
6521
  var ReviewTopbar = ({
5632
6522
  draftTarget,
5633
6523
  copyLabel,
@@ -5648,6 +6538,13 @@ var ReviewTopbar = ({
5648
6538
  onOpenInitialPrompt,
5649
6539
  onOpenSettings
5650
6540
  }) => {
6541
+ const selectedPresetValue = getPresetSelectValue(size);
6542
+ const handlePresetSelectChange = (event) => {
6543
+ const nextPreset = viewportPresets.find(
6544
+ (preset) => getPresetSelectValue(preset) === event.currentTarget.value
6545
+ );
6546
+ if (nextPreset) onSizeChange(nextPreset);
6547
+ };
5651
6548
  return /* @__PURE__ */ jsxs14("header", { className: "df-review-topbar", children: [
5652
6549
  /* @__PURE__ */ jsxs14(
5653
6550
  "form",
@@ -5697,6 +6594,27 @@ var ReviewTopbar = ({
5697
6594
  },
5698
6595
  preset.label
5699
6596
  )) }),
6597
+ /* @__PURE__ */ jsx16(
6598
+ "select",
6599
+ {
6600
+ "aria-label": "Viewport preset",
6601
+ className: "df-review-preset-select",
6602
+ value: selectedPresetValue,
6603
+ onChange: handlePresetSelectChange,
6604
+ children: viewportPresets.map((preset) => {
6605
+ const scope = getViewportPresetKind(preset);
6606
+ const count = presetScopeCounts.get(scope) ?? 0;
6607
+ return /* @__PURE__ */ jsx16(
6608
+ "option",
6609
+ {
6610
+ value: getPresetSelectValue(preset),
6611
+ children: `${preset.label} (${count})`
6612
+ },
6613
+ getPresetSelectValue(preset)
6614
+ );
6615
+ })
6616
+ }
6617
+ ),
5700
6618
  /* @__PURE__ */ jsx16("span", { className: "df-review-tool-divider", "aria-hidden": "true", children: "|" }),
5701
6619
  /* @__PURE__ */ jsxs14("span", { className: "df-review-active-size", children: [
5702
6620
  size.width,
@@ -5758,6 +6676,64 @@ var ReviewTopbar = ({
5758
6676
  children: /* @__PURE__ */ jsx16(Settings, { "aria-hidden": "true" })
5759
6677
  }
5760
6678
  )
6679
+ ] }),
6680
+ /* @__PURE__ */ jsxs14("details", { className: "df-review-overlays-menu", children: [
6681
+ /* @__PURE__ */ jsx16("summary", { "aria-label": "Open target tools", title: "Tools", children: /* @__PURE__ */ jsx16(Ellipsis, { "aria-hidden": "true" }) }),
6682
+ /* @__PURE__ */ jsxs14("div", { className: "df-review-overlays-popover", "aria-label": "Target tools", children: [
6683
+ isRulerAvailable && /* @__PURE__ */ jsx16(
6684
+ "button",
6685
+ {
6686
+ "aria-label": "Toggle ruler",
6687
+ className: `df-review-overlay-button is-ruler${isRulerVisible ? " is-active" : ""}`,
6688
+ type: "button",
6689
+ onClick: onToggleRuler,
6690
+ children: /* @__PURE__ */ jsx16(Ruler, { "aria-hidden": "true" })
6691
+ }
6692
+ ),
6693
+ /* @__PURE__ */ jsx16(
6694
+ "button",
6695
+ {
6696
+ "aria-label": "Toggle grid overlay",
6697
+ className: `df-review-overlay-button is-grid${targetOverlayState.grid ? " is-active" : ""}`,
6698
+ type: "button",
6699
+ onClick: () => onToggleTargetOverlay("grid"),
6700
+ children: /* @__PURE__ */ jsx16(LayoutGrid, { "aria-hidden": "true" })
6701
+ }
6702
+ ),
6703
+ /* @__PURE__ */ jsx16(
6704
+ "button",
6705
+ {
6706
+ "aria-disabled": !isFigmaOverlayAvailable,
6707
+ "aria-label": isFigmaOverlayAvailable ? "Toggle Figma overlay" : FIGMA_OVERLAY_UNAVAILABLE_MESSAGE,
6708
+ className: `df-review-overlay-button is-figma${targetOverlayState.figma ? " is-active" : ""}${isFigmaOverlayAvailable ? "" : " is-disabled"}`,
6709
+ disabled: !isFigmaOverlayAvailable,
6710
+ type: "button",
6711
+ onClick: () => onToggleTargetOverlay("figma"),
6712
+ children: /* @__PURE__ */ jsx16(Image, { "aria-hidden": "true" })
6713
+ }
6714
+ ),
6715
+ /* @__PURE__ */ jsx16("span", { className: "df-review-tool-divider", "aria-hidden": "true", children: "|" }),
6716
+ /* @__PURE__ */ jsx16(
6717
+ "button",
6718
+ {
6719
+ "aria-label": "Open initial prompt",
6720
+ className: "df-review-overlay-button is-prompt",
6721
+ type: "button",
6722
+ onClick: onOpenInitialPrompt,
6723
+ children: /* @__PURE__ */ jsx16(CircleQuestionMark, { "aria-hidden": "true" })
6724
+ }
6725
+ ),
6726
+ /* @__PURE__ */ jsx16(
6727
+ "button",
6728
+ {
6729
+ "aria-label": "Open settings",
6730
+ className: "df-review-overlay-button is-settings",
6731
+ type: "button",
6732
+ onClick: onOpenSettings,
6733
+ children: /* @__PURE__ */ jsx16(Settings, { "aria-hidden": "true" })
6734
+ }
6735
+ )
6736
+ ] })
5761
6737
  ] })
5762
6738
  ] })
5763
6739
  ] });
@@ -5772,7 +6748,7 @@ import {
5772
6748
  import {
5773
6749
  useCallback
5774
6750
  } from "react";
5775
- function runWithAutoScrollBehavior(targetDocument, callback) {
6751
+ function runWithAutoScrollBehavior2(targetDocument, callback) {
5776
6752
  const elements = [
5777
6753
  targetDocument?.documentElement,
5778
6754
  targetDocument?.body
@@ -5873,7 +6849,7 @@ var useReviewItemRestore = ({
5873
6849
  isCurrentRestore
5874
6850
  );
5875
6851
  if (!isCurrentRestore()) return false;
5876
- runWithAutoScrollBehavior(targetDocument, () => {
6852
+ runWithAutoScrollBehavior2(targetDocument, () => {
5877
6853
  setDocumentScrollInstantly(
5878
6854
  targetWindow,
5879
6855
  targetDocument,
@@ -5955,39 +6931,6 @@ import {
5955
6931
  useEffect as useEffect2
5956
6932
  } from "react";
5957
6933
 
5958
- // src/react-shell/target/target.ts
5959
- var HIDE_SCROLLBAR_STYLE_ID = "df-review-hide-scrollbar";
5960
- var setTargetScrollbarHidden = (targetDocument, hidden) => {
5961
- if (!targetDocument) return;
5962
- const existing = targetDocument.getElementById(HIDE_SCROLLBAR_STYLE_ID);
5963
- if (hidden) {
5964
- if (existing) return;
5965
- const style = targetDocument.createElement("style");
5966
- style.id = HIDE_SCROLLBAR_STYLE_ID;
5967
- style.textContent = "html{scrollbar-width:none}html::-webkit-scrollbar,body::-webkit-scrollbar{width:0;height:0;display:none}";
5968
- targetDocument.head?.appendChild(style);
5969
- } else {
5970
- existing?.remove();
5971
- }
5972
- };
5973
- var isEditableEventTarget = (event) => {
5974
- const path = event.composedPath?.() ?? [];
5975
- const element = path[0] ?? event.target;
5976
- if (!element || typeof element.tagName !== "string") return false;
5977
- const tag = element.tagName;
5978
- return tag === "INPUT" || tag === "TEXTAREA" || element.isContentEditable === true;
5979
- };
5980
- var getTargetOverlayState = (targetDocument) => ({
5981
- grid: Boolean(
5982
- targetDocument?.body.classList.contains("is-help") || targetDocument?.querySelector(".helper.onShow")
5983
- ),
5984
- figma: Boolean(
5985
- targetDocument?.querySelector(
5986
- ".helper-figma-root, .helper-figma-loading-backdrop"
5987
- )
5988
- )
5989
- });
5990
-
5991
6934
  // src/react-shell/hooks/review.frame.navigation.ts
5992
6935
  var bindReviewFrameNavigation = ({
5993
6936
  pageTargets,
@@ -6250,18 +7193,33 @@ var useReviewKitLifecycle = ({
6250
7193
  };
6251
7194
 
6252
7195
  // src/react-shell/hooks/use.review.target.overlay.ts
6253
- import { useCallback as useCallback3, useEffect as useEffect3 } from "react";
7196
+ import { useCallback as useCallback3, useEffect as useEffect3, useRef } from "react";
7197
+ var TARGET_OVERLAY_REFRESH_DELAYS = [80, 240, 600];
6254
7198
  var useReviewTargetOverlay = ({
6255
7199
  iframeRef,
6256
7200
  isFigmaOverlayAvailable,
6257
7201
  targetOverlayState,
6258
7202
  onTargetOverlayStateChange
6259
7203
  }) => {
6260
- const refreshTargetOverlayState = useCallback3(() => {
6261
- onTargetOverlayStateChange(
6262
- getTargetOverlayState(iframeRef.current?.contentDocument ?? void 0)
7204
+ const refreshTimersRef = useRef([]);
7205
+ const clearRefreshTimers = useCallback3(() => {
7206
+ refreshTimersRef.current.forEach((timer) => window.clearTimeout(timer));
7207
+ refreshTimersRef.current = [];
7208
+ }, []);
7209
+ const updateTargetOverlayState = useCallback3(() => {
7210
+ const state = getTargetOverlayState(
7211
+ iframeRef.current?.contentDocument ?? void 0
6263
7212
  );
7213
+ onTargetOverlayStateChange(state);
7214
+ return state;
6264
7215
  }, [iframeRef, onTargetOverlayStateChange]);
7216
+ const refreshTargetOverlayState = useCallback3(() => {
7217
+ clearRefreshTimers();
7218
+ updateTargetOverlayState();
7219
+ refreshTimersRef.current = TARGET_OVERLAY_REFRESH_DELAYS.map(
7220
+ (delay) => window.setTimeout(updateTargetOverlayState, delay)
7221
+ );
7222
+ }, [clearRefreshTimers, updateTargetOverlayState]);
6265
7223
  const dispatchTargetOverlayHotkey = useCallback3(
6266
7224
  (overlay) => {
6267
7225
  const targetWindow = iframeRef.current?.contentWindow;
@@ -6297,19 +7255,17 @@ var useReviewTargetOverlay = ({
6297
7255
  );
6298
7256
  const closeTargetOverlay = useCallback3(
6299
7257
  (overlay) => {
6300
- const currentState = getTargetOverlayState(
6301
- iframeRef.current?.contentDocument ?? void 0
6302
- );
6303
- onTargetOverlayStateChange(currentState);
7258
+ const currentState = updateTargetOverlayState();
6304
7259
  if (!currentState[overlay]) return false;
6305
7260
  return dispatchTargetOverlayHotkey(overlay);
6306
7261
  },
6307
- [dispatchTargetOverlayHotkey, iframeRef, onTargetOverlayStateChange]
7262
+ [dispatchTargetOverlayHotkey, updateTargetOverlayState]
6308
7263
  );
6309
7264
  useEffect3(() => {
6310
7265
  if (isFigmaOverlayAvailable || !targetOverlayState.figma) return;
6311
7266
  closeTargetOverlay("figma");
6312
7267
  }, [closeTargetOverlay, isFigmaOverlayAvailable, targetOverlayState.figma]);
7268
+ useEffect3(() => clearRefreshTimers, [clearRefreshTimers]);
6313
7269
  return {
6314
7270
  closeTargetOverlay,
6315
7271
  refreshTargetOverlayState,
@@ -6544,7 +7500,7 @@ import {
6544
7500
  useCallback as useCallback6,
6545
7501
  useEffect as useEffect5,
6546
7502
  useMemo as useMemo3,
6547
- useRef,
7503
+ useRef as useRef2,
6548
7504
  useState as useState4
6549
7505
  } from "react";
6550
7506
 
@@ -6761,7 +7717,7 @@ var useReviewPresence = ({
6761
7717
  size,
6762
7718
  source
6763
7719
  }) => {
6764
- const presenceSessionRef = useRef(null);
7720
+ const presenceSessionRef = useRef2(null);
6765
7721
  const [presenceUsers, setPresenceUsers] = useState4([]);
6766
7722
  const [presenceSessionVersion, setPresenceSessionVersion] = useState4(0);
6767
7723
  const presenceSessionId = useMemo3(getReviewPresenceSessionId, []);
@@ -6842,7 +7798,7 @@ var useReviewPresence = ({
6842
7798
  source
6843
7799
  ]
6844
7800
  );
6845
- const getCurrentPresenceStateRef = useRef(getCurrentPresenceState);
7801
+ const getCurrentPresenceStateRef = useRef2(getCurrentPresenceState);
6846
7802
  getCurrentPresenceStateRef.current = getCurrentPresenceState;
6847
7803
  useEffect5(() => {
6848
7804
  if (!presence || !normalizedReviewUserId) {
@@ -6922,7 +7878,7 @@ import {
6922
7878
  useCallback as useCallback7,
6923
7879
  useEffect as useEffect6,
6924
7880
  useMemo as useMemo4,
6925
- useRef as useRef2,
7881
+ useRef as useRef3,
6926
7882
  useState as useState5
6927
7883
  } from "react";
6928
7884
 
@@ -6953,10 +7909,10 @@ var useReviewRulerDrag = ({
6953
7909
  size,
6954
7910
  targetSrc
6955
7911
  }) => {
6956
- const rulerOverlayRef = useRef2(null);
6957
- const rulerDragRectRef = useRef2(null);
6958
- const isRulerDraggingRef = useRef2(false);
6959
- const sizeRef = useRef2(size);
7912
+ const rulerOverlayRef = useRef3(null);
7913
+ const rulerDragRectRef = useRef3(null);
7914
+ const isRulerDraggingRef = useRef3(false);
7915
+ const sizeRef = useRef3(size);
6960
7916
  const [rulerStart, setRulerStart] = useState5(null);
6961
7917
  const [rulerPoint, setRulerPoint] = useState5(null);
6962
7918
  const [rulerHover, setRulerHover] = useState5(null);
@@ -7379,8 +8335,18 @@ var useReviewShellData = ({
7379
8335
  [qaStatusFilter, scopeFilteredNumberedActiveItems]
7380
8336
  );
7381
8337
  const hiddenOverlayItemIdList = useMemo5(
7382
- () => Array.from(hiddenOverlayItemIds),
7383
- [hiddenOverlayItemIds]
8338
+ () => {
8339
+ const nextHiddenItemIds = new Set(hiddenOverlayItemIds);
8340
+ if (qaStatusFilter !== "all") {
8341
+ activeItems.forEach((item) => {
8342
+ if (normalizeReviewItemStatus(item.status) !== qaStatusFilter) {
8343
+ nextHiddenItemIds.add(item.id);
8344
+ }
8345
+ });
8346
+ }
8347
+ return Array.from(nextHiddenItemIds);
8348
+ },
8349
+ [activeItems, hiddenOverlayItemIds, qaStatusFilter]
7384
8350
  );
7385
8351
  const qaFilterCounts = useMemo5(() => {
7386
8352
  const counts = /* @__PURE__ */ new Map();
@@ -7615,7 +8581,7 @@ var useReviewShellHotkeys = ({
7615
8581
  // src/react-shell/hooks/use.review.shell.state.ts
7616
8582
  import {
7617
8583
  useMemo as useMemo6,
7618
- useRef as useRef3,
8584
+ useRef as useRef4,
7619
8585
  useState as useState9
7620
8586
  } from "react";
7621
8587
 
@@ -7786,14 +8752,14 @@ var useReviewShellState = ({
7786
8752
  const canWriteArea = activeAdapterEntry.writeModes.includes("area");
7787
8753
  const canWriteDom = activeAdapterEntry.writeModes.includes("dom");
7788
8754
  const adapter = activeAdapterEntry.adapter;
7789
- const iframeRef = useRef3(null);
7790
- const frameScrollRef = useRef3(null);
7791
- const controllerRef = useRef3(null);
7792
- const cleanupTargetRef = useRef3(null);
7793
- const pendingRestoreRef = useRef3(null);
7794
- const pendingInitialItemIdRef = useRef3(getInitialItemId());
7795
- const selectedItemIdRef = useRef3(getInitialItemId());
7796
- const hiddenOverlayItemIdListRef = useRef3([]);
8755
+ const iframeRef = useRef4(null);
8756
+ const frameScrollRef = useRef4(null);
8757
+ const controllerRef = useRef4(null);
8758
+ const cleanupTargetRef = useRef4(null);
8759
+ const pendingRestoreRef = useRef4(null);
8760
+ const pendingInitialItemIdRef = useRef4(getInitialItemId());
8761
+ const selectedItemIdRef = useRef4(getInitialItemId());
8762
+ const hiddenOverlayItemIdListRef = useRef4([]);
7797
8763
  const [target, setTarget] = useState9(
7798
8764
  () => getInitialTarget(reviewPathPrefix)
7799
8765
  );
@@ -7818,8 +8784,8 @@ var useReviewShellState = ({
7818
8784
  const [copyLabel, setCopyLabel] = useState9("Copy URL");
7819
8785
  const [toastMessage, setToastMessage] = useState9("");
7820
8786
  const [copiedPromptKey, setCopiedPromptKey] = useState9(null);
7821
- const targetRef = useRef3(target);
7822
- const sizeRef = useRef3(size);
8787
+ const targetRef = useRef4(target);
8788
+ const sizeRef = useRef4(size);
7823
8789
  const isFigmaOverlayAvailable = getIsFigmaOverlayAvailable(size);
7824
8790
  return {
7825
8791
  activeAdapterEntry,
@@ -8118,6 +9084,112 @@ var getReviewModeWriteMode = (mode) => {
8118
9084
  var SOURCE_PANEL_MAX_WIDTH = 440;
8119
9085
  var SOURCE_PANEL_MIN_WIDTH = 240;
8120
9086
  var SOURCE_PANEL_MAX_HEIGHT = 260;
9087
+ var SOURCE_TREE_PANEL_CLOSE_DELAY_MS = 180;
9088
+ var waitForFrame = (targetWindow) => new Promise((resolve) => {
9089
+ (targetWindow ?? window).requestAnimationFrame(() => resolve());
9090
+ });
9091
+ var waitForMs = (ms) => new Promise((resolve) => {
9092
+ window.setTimeout(resolve, ms);
9093
+ });
9094
+ var getScrollElement = (targetDocument) => targetDocument.scrollingElement;
9095
+ var scrollElementInTarget = (element, block) => {
9096
+ const targetWindow = element.ownerDocument.defaultView;
9097
+ if (!targetWindow) return;
9098
+ const targetDocument = element.ownerDocument;
9099
+ const scrollElement = getScrollElement(targetDocument);
9100
+ const rect = element.getBoundingClientRect();
9101
+ const currentLeft = scrollElement?.scrollLeft ?? targetWindow.scrollX;
9102
+ const currentTop = scrollElement?.scrollTop ?? targetWindow.scrollY;
9103
+ const clientWidth = scrollElement?.clientWidth ?? targetWindow.innerWidth;
9104
+ const clientHeight = scrollElement?.clientHeight ?? targetWindow.innerHeight;
9105
+ const scrollWidth = scrollElement?.scrollWidth ?? targetDocument.documentElement.scrollWidth;
9106
+ const scrollHeight = scrollElement?.scrollHeight ?? targetDocument.documentElement.scrollHeight;
9107
+ const nextLeft = clamp(
9108
+ currentLeft + rect.left + rect.width / 2 - clientWidth / 2,
9109
+ 0,
9110
+ Math.max(0, scrollWidth - clientWidth)
9111
+ );
9112
+ const nextTop = block === "center" ? clamp(
9113
+ currentTop + rect.top + rect.height / 2 - clientHeight / 2,
9114
+ 0,
9115
+ Math.max(0, scrollHeight - clientHeight)
9116
+ ) : clamp(
9117
+ currentTop + rect.top,
9118
+ 0,
9119
+ Math.max(0, scrollHeight - clientHeight)
9120
+ );
9121
+ runWithAutoScrollBehavior(targetDocument, () => {
9122
+ if (scrollElement) {
9123
+ scrollElement.scrollLeft = Math.round(nextLeft);
9124
+ scrollElement.scrollTop = Math.round(nextTop);
9125
+ return;
9126
+ }
9127
+ targetWindow.scrollTo(Math.round(nextLeft), Math.round(nextTop));
9128
+ });
9129
+ };
9130
+ var centerFrameScrollOnElement = (frameScroll, frame, element) => {
9131
+ if (!frameScroll || !frame) return;
9132
+ const frameScrollRect = frameScroll.getBoundingClientRect();
9133
+ const frameRect = frame.getBoundingClientRect();
9134
+ const elementRect = element.getBoundingClientRect();
9135
+ const elementHostCenterX = frameRect.left + elementRect.left + elementRect.width / 2;
9136
+ const elementHostCenterY = frameRect.top + elementRect.top + elementRect.height / 2;
9137
+ const visibleCenterX = frameScrollRect.left + frameScrollRect.width / 2;
9138
+ const visibleCenterY = frameScrollRect.top + frameScrollRect.height / 2;
9139
+ const nextLeft = clamp(
9140
+ frameScroll.scrollLeft + elementHostCenterX - visibleCenterX,
9141
+ 0,
9142
+ Math.max(0, frameScroll.scrollWidth - frameScroll.clientWidth)
9143
+ );
9144
+ const nextTop = clamp(
9145
+ frameScroll.scrollTop + elementHostCenterY - visibleCenterY,
9146
+ 0,
9147
+ Math.max(0, frameScroll.scrollHeight - frameScroll.clientHeight)
9148
+ );
9149
+ const previousScrollBehavior = frameScroll.style.scrollBehavior;
9150
+ frameScroll.style.scrollBehavior = "auto";
9151
+ frameScroll.scrollLeft = Math.round(nextLeft);
9152
+ frameScroll.scrollTop = Math.round(nextTop);
9153
+ frameScroll.style.scrollBehavior = previousScrollBehavior;
9154
+ };
9155
+ var getSectionOutlineFilterTerms = (value) => value.trim().toLowerCase().split(/\s+/).filter(Boolean);
9156
+ var getSectionOutlineEntryCount = (entries) => entries.reduce(
9157
+ (count, entry) => count + 1 + getSectionOutlineEntryCount(entry.children),
9158
+ 0
9159
+ );
9160
+ var DEFAULT_COLLAPSED_ROOT_LABELS = /* @__PURE__ */ new Set(["FrameHeader", "FrameFooter"]);
9161
+ var getDefaultCollapsedSectionOutlineIds = (entries) => {
9162
+ const collapsedIds = /* @__PURE__ */ new Set();
9163
+ const visit = (entry) => {
9164
+ const shouldCollapseRoot = entry.depth === 1 && DEFAULT_COLLAPSED_ROOT_LABELS.has(entry.label);
9165
+ if ((entry.depth >= 2 || shouldCollapseRoot) && entry.children.length > 0) {
9166
+ collapsedIds.add(entry.id);
9167
+ }
9168
+ entry.children.forEach(visit);
9169
+ };
9170
+ entries.forEach(visit);
9171
+ return collapsedIds;
9172
+ };
9173
+ var matchesSectionOutlineFilter = (entry, terms) => {
9174
+ if (terms.length === 0) return true;
9175
+ const text = [
9176
+ entry.label,
9177
+ entry.filePath,
9178
+ entry.source?.file,
9179
+ entry.data?.file
9180
+ ].filter(Boolean).join(" ").toLowerCase();
9181
+ return terms.every((term) => text.includes(term));
9182
+ };
9183
+ var filterSectionOutlineEntries = (entries, terms) => {
9184
+ if (terms.length === 0) return entries;
9185
+ return entries.flatMap((entry) => {
9186
+ const children = filterSectionOutlineEntries(entry.children, terms);
9187
+ if (!matchesSectionOutlineFilter(entry, terms) && children.length === 0) {
9188
+ return [];
9189
+ }
9190
+ return [{ ...entry, children }];
9191
+ });
9192
+ };
8121
9193
  var ReviewShell = ({
8122
9194
  projectId,
8123
9195
  pages,
@@ -8187,9 +9259,13 @@ var ReviewShell = ({
8187
9259
  presets,
8188
9260
  reviewPathPrefix
8189
9261
  });
8190
- const sourceShortcutCleanupRef = useRef4(null);
8191
- const sourceInspectorInteractionRef = useRef4(false);
9262
+ const sourceShortcutCleanupRef = useRef5(null);
9263
+ const sourceInspectorInteractionRef = useRef5(false);
9264
+ const [sidePanel, setSidePanel] = useState10("qa");
8192
9265
  const [sourceInspectorState, setSourceInspectorState] = useState10(null);
9266
+ const [sectionOutline, setSectionOutline] = useState10(null);
9267
+ const [sectionOutlineFilter, setSectionOutlineFilter] = useState10("");
9268
+ const [collapsedSectionOutlineIds, setCollapsedSectionOutlineIds] = useState10(() => /* @__PURE__ */ new Set());
8193
9269
  const [isAllQaVisible, setIsAllQaVisible] = useState10(false);
8194
9270
  const sourceOpenOptions = useMemo7(
8195
9271
  () => ({
@@ -8198,7 +9274,42 @@ var ReviewShell = ({
8198
9274
  }),
8199
9275
  [sourceInspector, sourceRoot]
8200
9276
  );
9277
+ const sourceCandidateOptions = useMemo7(
9278
+ () => ({
9279
+ ignore: sourceInspector?.ignore,
9280
+ includePlacer: sourceInspector?.includePlacer
9281
+ }),
9282
+ [sourceInspector]
9283
+ );
9284
+ const sectionOutlineOptions = useMemo7(
9285
+ () => ({
9286
+ includePlacer: sourceInspector?.includePlacer,
9287
+ ignore: sourceInspector?.ignore,
9288
+ maxDepth: sourceInspector?.maxDepth
9289
+ }),
9290
+ [sourceInspector]
9291
+ );
8201
9292
  const isSourceInspectorEnabled = sourceInspector?.enabled !== false;
9293
+ const isSourceTreeHoverOutlineEnabled = sourceInspector?.hoverOutline !== false;
9294
+ const isQaPanelVisible = isListVisible && sidePanel === "qa";
9295
+ const isSourceTreePanelVisible = isSourceInspectorEnabled && isListVisible && sidePanel === "source";
9296
+ const sectionOutlineFilterTerms = useMemo7(
9297
+ () => getSectionOutlineFilterTerms(sectionOutlineFilter),
9298
+ [sectionOutlineFilter]
9299
+ );
9300
+ const filteredSectionOutline = useMemo7(
9301
+ () => sectionOutline ? filterSectionOutlineEntries(sectionOutline, sectionOutlineFilterTerms) : [],
9302
+ [sectionOutline, sectionOutlineFilterTerms]
9303
+ );
9304
+ const sectionOutlineTotalCount = useMemo7(
9305
+ () => getSectionOutlineEntryCount(sectionOutline ?? []),
9306
+ [sectionOutline]
9307
+ );
9308
+ const filteredSectionOutlineCount = useMemo7(
9309
+ () => getSectionOutlineEntryCount(filteredSectionOutline),
9310
+ [filteredSectionOutline]
9311
+ );
9312
+ const isSectionOutlineFiltering = sectionOutlineFilterTerms.length > 0;
8202
9313
  const {
8203
9314
  activeItems,
8204
9315
  activeRemainingItemCount,
@@ -8350,7 +9461,6 @@ var ReviewShell = ({
8350
9461
  });
8351
9462
  const {
8352
9463
  clearSelectedItem,
8353
- closeTargetOverlay,
8354
9464
  initReviewKit,
8355
9465
  reloadReviewKit,
8356
9466
  restoreReviewItem,
@@ -8488,9 +9598,6 @@ var ReviewShell = ({
8488
9598
  const writeMode = getReviewModeWriteMode(nextMode);
8489
9599
  if (writeMode && !activeAdapterEntry.writeModes.includes(writeMode)) return;
8490
9600
  closeRuler();
8491
- if (nextMode === "element") {
8492
- closeTargetOverlay("figma");
8493
- }
8494
9601
  setControllerReviewMode(nextMode);
8495
9602
  };
8496
9603
  useReviewShellHotkeys({
@@ -8527,10 +9634,23 @@ var ReviewShell = ({
8527
9634
  );
8528
9635
  setTargetFigmaState(config ? { targetSrc, config } : null);
8529
9636
  }, [iframeRef, targetSrc]);
9637
+ useEffect10(() => {
9638
+ const targetDocument = iframeRef.current?.contentDocument;
9639
+ setTargetFigmaOverlayLocked(targetDocument, mode === "element");
9640
+ return () => {
9641
+ setTargetFigmaOverlayLocked(targetDocument, false);
9642
+ };
9643
+ }, [iframeRef, mode, targetSrc]);
8530
9644
  const clearSourceInspector = useCallback11(() => {
8531
9645
  sourceInspectorInteractionRef.current = false;
8532
9646
  setSourceInspectorState(null);
8533
9647
  }, []);
9648
+ useEffect10(() => {
9649
+ clearSourceInspector();
9650
+ setSectionOutlineFilter("");
9651
+ setCollapsedSectionOutlineIds(/* @__PURE__ */ new Set());
9652
+ setSectionOutline(null);
9653
+ }, [clearSourceInspector, targetSrc]);
8534
9654
  const getSourceInspectorRect = useCallback11(
8535
9655
  (element) => {
8536
9656
  const frame = iframeRef.current;
@@ -8584,13 +9704,15 @@ var ReviewShell = ({
8584
9704
  );
8585
9705
  const showSourceInspectorForTarget = useCallback11(
8586
9706
  (target2, isPinned = false) => {
8587
- const candidates = getSourceCandidates(target2).map((candidate) => ({
8588
- ...candidate,
8589
- openUrl: getSourceOpenUrl(candidate.source, {
8590
- ...sourceOpenOptions,
8591
- omitPosition: !candidate.usesPosition
9707
+ const candidates = getSourceCandidates(target2, sourceCandidateOptions).map(
9708
+ (candidate) => ({
9709
+ ...candidate,
9710
+ openUrl: getSourceOpenUrl(candidate.source, {
9711
+ ...sourceOpenOptions,
9712
+ omitPosition: !candidate.usesPosition
9713
+ })
8592
9714
  })
8593
- }));
9715
+ );
8594
9716
  const firstCandidate = candidates[0];
8595
9717
  const rect = firstCandidate ? getSourceInspectorRect(firstCandidate.element) : null;
8596
9718
  if (!firstCandidate || !rect) {
@@ -8612,12 +9734,16 @@ var ReviewShell = ({
8612
9734
  [
8613
9735
  getSourceInspectorPanelPosition,
8614
9736
  getSourceInspectorRect,
9737
+ sourceCandidateOptions,
8615
9738
  sourceOpenOptions
8616
9739
  ]
8617
9740
  );
8618
9741
  const showSourceOutlineForTarget = useCallback11(
8619
9742
  (target2) => {
8620
- const firstCandidate = getSourceCandidates(target2)[0];
9743
+ const firstCandidate = getSourceCandidates(
9744
+ target2,
9745
+ sourceCandidateOptions
9746
+ )[0];
8621
9747
  const rect = firstCandidate ? getSourceInspectorRect(firstCandidate.element) : null;
8622
9748
  if (!firstCandidate || !rect) {
8623
9749
  setSourceInspectorState(null);
@@ -8634,8 +9760,35 @@ var ReviewShell = ({
8634
9760
  });
8635
9761
  return firstCandidate;
8636
9762
  },
8637
- [getSourceInspectorRect]
9763
+ [getSourceInspectorRect, sourceCandidateOptions]
9764
+ );
9765
+ const showSourceOutlineForElement = useCallback11(
9766
+ (element) => {
9767
+ if (!isSourceTreeHoverOutlineEnabled) return;
9768
+ const rect = getSourceInspectorRect(element);
9769
+ if (!rect) {
9770
+ setSourceInspectorState(
9771
+ (current) => current?.isPinned ? current : null
9772
+ );
9773
+ return;
9774
+ }
9775
+ setSourceInspectorState(
9776
+ (current) => current?.isPinned ? current : {
9777
+ candidates: [],
9778
+ isPinned: false,
9779
+ panelLeft: 0,
9780
+ panelMaxWidth: SOURCE_PANEL_MAX_WIDTH,
9781
+ panelRight: null,
9782
+ panelTop: 0,
9783
+ rect
9784
+ }
9785
+ );
9786
+ },
9787
+ [getSourceInspectorRect, isSourceTreeHoverOutlineEnabled]
8638
9788
  );
9789
+ const clearSourceOutlineHover = useCallback11(() => {
9790
+ setSourceInspectorState((current) => current?.isPinned ? current : null);
9791
+ }, []);
8639
9792
  const openSourceCandidate = useCallback11(
8640
9793
  (candidate) => {
8641
9794
  const didOpen = openSourceInEditor(candidate.source, {
@@ -8647,6 +9800,153 @@ var ReviewShell = ({
8647
9800
  },
8648
9801
  [clearSourceInspector, showToast, sourceOpenOptions]
8649
9802
  );
9803
+ const getCurrentSectionOutline = useCallback11(
9804
+ () => {
9805
+ let frameDocument = null;
9806
+ try {
9807
+ frameDocument = iframeRef.current?.contentDocument ?? null;
9808
+ } catch {
9809
+ frameDocument = null;
9810
+ }
9811
+ return frameDocument ? getSectionOutline(frameDocument, sectionOutlineOptions) : [];
9812
+ },
9813
+ [iframeRef, sectionOutlineOptions]
9814
+ );
9815
+ const setSectionOutlineWithDefaultCollapse = useCallback11(
9816
+ (nextSectionOutline) => {
9817
+ setSectionOutline(nextSectionOutline);
9818
+ setCollapsedSectionOutlineIds(
9819
+ getDefaultCollapsedSectionOutlineIds(nextSectionOutline)
9820
+ );
9821
+ },
9822
+ []
9823
+ );
9824
+ useEffect10(() => {
9825
+ if (sidePanel !== "source" || !isListVisible) return void 0;
9826
+ const refreshSectionOutline = () => {
9827
+ setSectionOutlineWithDefaultCollapse(getCurrentSectionOutline());
9828
+ };
9829
+ const animationFrame = window.requestAnimationFrame(refreshSectionOutline);
9830
+ const firstTimeout = window.setTimeout(refreshSectionOutline, 120);
9831
+ const secondTimeout = window.setTimeout(refreshSectionOutline, 500);
9832
+ return () => {
9833
+ window.cancelAnimationFrame(animationFrame);
9834
+ window.clearTimeout(firstTimeout);
9835
+ window.clearTimeout(secondTimeout);
9836
+ };
9837
+ }, [
9838
+ getCurrentSectionOutline,
9839
+ isListVisible,
9840
+ setSectionOutlineWithDefaultCollapse,
9841
+ sidePanel,
9842
+ targetSrc
9843
+ ]);
9844
+ const toggleQaPanel = useCallback11(() => {
9845
+ setSidePanel("qa");
9846
+ setIsListVisible((current) => sidePanel === "qa" ? !current : true);
9847
+ }, [setIsListVisible, sidePanel]);
9848
+ const toggleSourceTreePanel = useCallback11(() => {
9849
+ if (!isSourceInspectorEnabled) return;
9850
+ if (sidePanel === "source" && isListVisible) {
9851
+ setIsListVisible(false);
9852
+ return;
9853
+ }
9854
+ setSidePanel("source");
9855
+ setSectionOutlineWithDefaultCollapse(getCurrentSectionOutline());
9856
+ setIsListVisible(true);
9857
+ }, [
9858
+ getCurrentSectionOutline,
9859
+ isListVisible,
9860
+ isSourceInspectorEnabled,
9861
+ setSectionOutlineWithDefaultCollapse,
9862
+ setIsListVisible,
9863
+ sidePanel
9864
+ ]);
9865
+ const toggleSectionOutlineEntry = useCallback11((entryId) => {
9866
+ setCollapsedSectionOutlineIds((current) => {
9867
+ const next = new Set(current);
9868
+ if (next.has(entryId)) {
9869
+ next.delete(entryId);
9870
+ } else {
9871
+ next.add(entryId);
9872
+ }
9873
+ return next;
9874
+ });
9875
+ }, []);
9876
+ const scrollToSection = useCallback11((entry) => {
9877
+ scrollElementInTarget(entry.element, "start");
9878
+ centerFrameScrollOnElement(
9879
+ frameScrollRef.current,
9880
+ iframeRef.current,
9881
+ entry.element
9882
+ );
9883
+ }, [frameScrollRef, iframeRef]);
9884
+ const openSectionSource = useCallback11(
9885
+ (entry) => {
9886
+ const didOpen = openSourceInEditor(entry.source, {
9887
+ ...sourceOpenOptions,
9888
+ omitPosition: true
9889
+ });
9890
+ showToast(didOpen ? "Source opened" : "Source root required");
9891
+ },
9892
+ [showToast, sourceOpenOptions]
9893
+ );
9894
+ const openSectionData = useCallback11(
9895
+ (entry) => {
9896
+ const didOpen = openSourceInEditor(entry.data, sourceOpenOptions);
9897
+ showToast(didOpen ? "Data opened" : "Data hint not found");
9898
+ },
9899
+ [showToast, sourceOpenOptions]
9900
+ );
9901
+ const startSectionDomReview = useCallback11(
9902
+ (entry) => {
9903
+ if (!canWriteDom) {
9904
+ showToast("DOM QA unavailable");
9905
+ return;
9906
+ }
9907
+ clearSourceInspector();
9908
+ setIsListVisible(false);
9909
+ let targetWindow = null;
9910
+ try {
9911
+ targetWindow = entry.element.ownerDocument.defaultView ?? iframeRef.current?.contentWindow ?? null;
9912
+ } catch {
9913
+ targetWindow = null;
9914
+ }
9915
+ void waitForMs(SOURCE_TREE_PANEL_CLOSE_DELAY_MS).then(async () => {
9916
+ initReviewKit();
9917
+ await waitForFrame(targetWindow);
9918
+ const controller = controllerRef.current;
9919
+ if (!controller) {
9920
+ showToast("DOM QA unavailable");
9921
+ return;
9922
+ }
9923
+ scrollElementInTarget(entry.element, "center");
9924
+ await waitForFrame(targetWindow);
9925
+ centerFrameScrollOnElement(
9926
+ frameScrollRef.current,
9927
+ iframeRef.current,
9928
+ entry.element
9929
+ );
9930
+ await waitForFrame(targetWindow);
9931
+ await controller.startElementReview(entry.element);
9932
+ await waitForFrame(targetWindow);
9933
+ setMode(controller.getMode());
9934
+ }).catch(() => {
9935
+ setMode(controllerRef.current?.getMode() ?? "idle");
9936
+ });
9937
+ },
9938
+ [
9939
+ canWriteDom,
9940
+ clearSourceInspector,
9941
+ controllerRef,
9942
+ frameScrollRef,
9943
+ iframeRef,
9944
+ initReviewKit,
9945
+ setIsListVisible,
9946
+ setMode,
9947
+ showToast
9948
+ ]
9949
+ );
8650
9950
  const cleanupSourceOpenShortcut = useCallback11(() => {
8651
9951
  sourceShortcutCleanupRef.current?.();
8652
9952
  sourceShortcutCleanupRef.current = null;
@@ -8673,6 +9973,13 @@ var ReviewShell = ({
8673
9973
  cursor: crosshair !important;
8674
9974
  }
8675
9975
 
9976
+ html[${optionAttribute}="true"] .helper-figma-root,
9977
+ html[${optionAttribute}="true"] .helper-figma-root *,
9978
+ html[${optionAttribute}="true"] .helper-figma-loading-backdrop,
9979
+ html[${optionAttribute}="true"] .helper-figma-loading-backdrop * {
9980
+ pointer-events: none !important;
9981
+ }
9982
+
8676
9983
  html[${optionAttribute}="true"] body::before {
8677
9984
  position: fixed !important;
8678
9985
  z-index: 2147483647 !important;
@@ -8687,7 +9994,7 @@ var ReviewShell = ({
8687
9994
  background: rgba(15, 23, 42, 0.86) !important;
8688
9995
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.24) !important;
8689
9996
  content: "Source select" !important;
8690
- font: 700 12px/1 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif !important;
9997
+ font: 500 12px/1 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif !important;
8691
9998
  pointer-events: none !important;
8692
9999
  }
8693
10000
 
@@ -8704,7 +10011,7 @@ var ReviewShell = ({
8704
10011
  color: #ffffff !important;
8705
10012
  background: rgba(15, 23, 42, 0.9) !important;
8706
10013
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.28) !important;
8707
- font: 800 11px/1.35 ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace !important;
10014
+ font: 500 11px/1.35 ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace !important;
8708
10015
  overflow-wrap: anywhere !important;
8709
10016
  pointer-events: none !important;
8710
10017
  white-space: normal !important;
@@ -8805,8 +10112,9 @@ var ReviewShell = ({
8805
10112
  }
8806
10113
  };
8807
10114
  const handleMouseMove = (event) => {
10115
+ if (isSourcePanelPinned) return;
8808
10116
  lastSourceTarget = event.target;
8809
- const candidates = getSourceCandidates(event.target);
10117
+ const candidates = getSourceCandidates(event.target, sourceCandidateOptions);
8810
10118
  const sourceElement = candidates[0]?.element ?? null;
8811
10119
  if (event.altKey && !isSourceSelecting) {
8812
10120
  setSourceSelecting(true);
@@ -8840,6 +10148,7 @@ var ReviewShell = ({
8840
10148
  return;
8841
10149
  }
8842
10150
  if (!isOptionKeyEvent(event)) return;
10151
+ if (isSourcePanelPinned) return;
8843
10152
  cancelReviewMode();
8844
10153
  setSourceSelecting(true);
8845
10154
  };
@@ -8890,6 +10199,7 @@ var ReviewShell = ({
8890
10199
  iframeRef,
8891
10200
  isSourceInspectorEnabled,
8892
10201
  showToast,
10202
+ sourceCandidateOptions,
8893
10203
  showSourceOutlineForTarget,
8894
10204
  showSourceInspectorForTarget
8895
10205
  ]);
@@ -8899,8 +10209,25 @@ var ReviewShell = ({
8899
10209
  const loadTargetFrame = useCallback11(() => {
8900
10210
  initReviewKit();
8901
10211
  refreshTargetFigmaConfig();
10212
+ setTargetFigmaOverlayLocked(
10213
+ iframeRef.current?.contentDocument,
10214
+ mode === "element"
10215
+ );
8902
10216
  bindSourceOpenShortcut();
8903
- }, [bindSourceOpenShortcut, initReviewKit, refreshTargetFigmaConfig]);
10217
+ if (sidePanel === "source" && isListVisible) {
10218
+ setSectionOutlineWithDefaultCollapse(getCurrentSectionOutline());
10219
+ }
10220
+ }, [
10221
+ bindSourceOpenShortcut,
10222
+ getCurrentSectionOutline,
10223
+ iframeRef,
10224
+ initReviewKit,
10225
+ isListVisible,
10226
+ mode,
10227
+ refreshTargetFigmaConfig,
10228
+ setSectionOutlineWithDefaultCollapse,
10229
+ sidePanel
10230
+ ]);
8904
10231
  useEffect10(() => {
8905
10232
  const frame = window.requestAnimationFrame(bindSourceOpenShortcut);
8906
10233
  return () => window.cancelAnimationFrame(frame);
@@ -8980,6 +10307,112 @@ var ReviewShell = ({
8980
10307
  onRefreshReviewData: refreshReviewData2,
8981
10308
  onToast: showToast
8982
10309
  });
10310
+ const renderSectionOutlineEntry = (entry) => {
10311
+ const hasChildren = entry.children.length > 0;
10312
+ const isCollapsed = !isSectionOutlineFiltering && collapsedSectionOutlineIds.has(entry.id);
10313
+ return /* @__PURE__ */ jsxs15(
10314
+ "div",
10315
+ {
10316
+ className: `df-review-section-outline-item is-depth-${entry.depth}`,
10317
+ children: [
10318
+ /* @__PURE__ */ jsxs15(
10319
+ "div",
10320
+ {
10321
+ className: "df-review-section-outline-row",
10322
+ style: { paddingLeft: `${Math.max(0, entry.depth - 1) * 12 + 6}px` },
10323
+ onMouseEnter: () => showSourceOutlineForElement(entry.element),
10324
+ onMouseLeave: clearSourceOutlineHover,
10325
+ onMouseOver: () => showSourceOutlineForElement(entry.element),
10326
+ onMouseOut: (event) => {
10327
+ if (event.relatedTarget instanceof Node && event.currentTarget.contains(event.relatedTarget)) {
10328
+ return;
10329
+ }
10330
+ clearSourceOutlineHover();
10331
+ },
10332
+ onPointerEnter: () => showSourceOutlineForElement(entry.element),
10333
+ onPointerLeave: clearSourceOutlineHover,
10334
+ children: [
10335
+ hasChildren ? /* @__PURE__ */ jsx17(
10336
+ "button",
10337
+ {
10338
+ "aria-label": isCollapsed ? `Expand ${entry.label}` : `Collapse ${entry.label}`,
10339
+ "aria-expanded": !isCollapsed,
10340
+ className: `df-review-section-outline-toggle${isCollapsed ? " is-collapsed" : ""}`,
10341
+ type: "button",
10342
+ onClick: () => toggleSectionOutlineEntry(entry.id),
10343
+ children: /* @__PURE__ */ jsx17(ChevronDown, { "aria-hidden": "true" })
10344
+ }
10345
+ ) : /* @__PURE__ */ jsx17(
10346
+ "span",
10347
+ {
10348
+ "aria-hidden": "true",
10349
+ className: "df-review-section-outline-toggle is-placeholder"
10350
+ }
10351
+ ),
10352
+ /* @__PURE__ */ jsx17(
10353
+ "button",
10354
+ {
10355
+ className: "df-review-section-outline-name",
10356
+ type: "button",
10357
+ onClick: () => scrollToSection(entry),
10358
+ children: /* @__PURE__ */ jsx17("span", { children: entry.label })
10359
+ }
10360
+ ),
10361
+ /* @__PURE__ */ jsxs15("span", { className: "df-review-section-outline-links", children: [
10362
+ /* @__PURE__ */ jsx17(
10363
+ "button",
10364
+ {
10365
+ "aria-label": `Open ${entry.label} data`,
10366
+ className: "df-review-section-outline-link",
10367
+ title: "Open data",
10368
+ type: "button",
10369
+ disabled: !entry.data?.file,
10370
+ onClick: () => openSectionData(entry),
10371
+ children: /* @__PURE__ */ jsx17(Database, { "aria-hidden": "true" })
10372
+ }
10373
+ ),
10374
+ /* @__PURE__ */ jsx17(
10375
+ "button",
10376
+ {
10377
+ "aria-label": `Open ${entry.label} source`,
10378
+ className: "df-review-section-outline-link",
10379
+ title: "Open source",
10380
+ type: "button",
10381
+ disabled: !entry.source?.file,
10382
+ onClick: () => openSectionSource(entry),
10383
+ children: /* @__PURE__ */ jsx17(CodeXml, { "aria-hidden": "true" })
10384
+ }
10385
+ ),
10386
+ /* @__PURE__ */ jsx17(
10387
+ "span",
10388
+ {
10389
+ "aria-hidden": "true",
10390
+ className: "df-review-section-outline-divider",
10391
+ children: "|"
10392
+ }
10393
+ ),
10394
+ /* @__PURE__ */ jsx17(
10395
+ "button",
10396
+ {
10397
+ "aria-label": `Start DOM QA for ${entry.label}`,
10398
+ className: "df-review-section-outline-link is-dom-select",
10399
+ title: "DOM select",
10400
+ type: "button",
10401
+ disabled: !canWriteDom,
10402
+ onClick: () => startSectionDomReview(entry),
10403
+ children: /* @__PURE__ */ jsx17(SquareMousePointer, { "aria-hidden": "true" })
10404
+ }
10405
+ )
10406
+ ] })
10407
+ ]
10408
+ }
10409
+ ),
10410
+ hasChildren && !isCollapsed && /* @__PURE__ */ jsx17("div", { className: "df-review-section-outline-children", children: entry.children.map(renderSectionOutlineEntry) })
10411
+ ]
10412
+ },
10413
+ entry.id
10414
+ );
10415
+ };
8983
10416
  return /* @__PURE__ */ jsxs15(
8984
10417
  "div",
8985
10418
  {
@@ -9010,13 +10443,6 @@ var ReviewShell = ({
9010
10443
  onOpenSettings: openFigmaSettings
9011
10444
  }
9012
10445
  ),
9013
- currentPagePresenceUsers.length > 0 && /* @__PURE__ */ jsx17("div", { className: "df-review-presence-row", children: /* @__PURE__ */ jsx17(
9014
- PresenceOverlay,
9015
- {
9016
- presenceSessionId,
9017
- users: currentPagePresenceUsers
9018
- }
9019
- ) }),
9020
10446
  isSitemapOpen && /* @__PURE__ */ jsx17(
9021
10447
  SitemapModal,
9022
10448
  {
@@ -9069,19 +10495,40 @@ var ReviewShell = ({
9069
10495
  }
9070
10496
  ),
9071
10497
  toastMessage && /* @__PURE__ */ jsx17("div", { className: "df-review-copy-toast", role: "status", children: toastMessage }),
9072
- /* @__PURE__ */ jsx17("div", { className: "df-review-side-rail", children: /* @__PURE__ */ jsxs15(
9073
- "button",
9074
- {
9075
- "aria-label": isListVisible ? "Hide QA list" : "Show QA list",
9076
- className: "df-review-side-toggle",
9077
- type: "button",
9078
- onClick: () => setIsListVisible((current) => !current),
9079
- children: [
9080
- /* @__PURE__ */ jsx17("span", { "aria-hidden": "true", children: /* @__PURE__ */ jsx17(GripVertical, {}) }),
9081
- /* @__PURE__ */ jsx17("strong", { children: "QA" })
9082
- ]
9083
- }
9084
- ) }),
10498
+ /* @__PURE__ */ jsxs15("div", { className: "df-review-side-rail", children: [
10499
+ /* @__PURE__ */ jsx17(
10500
+ "button",
10501
+ {
10502
+ "aria-label": isQaPanelVisible ? "Hide QA list" : "Show QA list",
10503
+ "aria-pressed": isQaPanelVisible,
10504
+ className: `df-review-side-toggle${isQaPanelVisible ? " is-active" : ""}`,
10505
+ type: "button",
10506
+ onClick: toggleQaPanel,
10507
+ title: "QA",
10508
+ children: /* @__PURE__ */ jsx17("span", { "aria-hidden": "true", children: /* @__PURE__ */ jsx17(FileText, {}) })
10509
+ }
10510
+ ),
10511
+ isSourceInspectorEnabled && /* @__PURE__ */ jsx17(
10512
+ "button",
10513
+ {
10514
+ "aria-controls": "df-review-section-outline",
10515
+ "aria-label": isSourceTreePanelVisible ? "Hide source tree" : "Show source tree",
10516
+ "aria-pressed": isSourceTreePanelVisible,
10517
+ className: `df-review-side-toggle${isSourceTreePanelVisible ? " is-active" : ""}`,
10518
+ type: "button",
10519
+ onClick: toggleSourceTreePanel,
10520
+ title: "Source Tree",
10521
+ children: /* @__PURE__ */ jsx17("span", { "aria-hidden": "true", children: /* @__PURE__ */ jsx17(Search, {}) })
10522
+ }
10523
+ ),
10524
+ currentPagePresenceUsers.length > 0 && /* @__PURE__ */ jsx17(
10525
+ PresenceOverlay,
10526
+ {
10527
+ presenceSessionId,
10528
+ users: currentPagePresenceUsers
10529
+ }
10530
+ )
10531
+ ] }),
9085
10532
  /* @__PURE__ */ jsx17(
9086
10533
  ReviewQaPanel,
9087
10534
  {
@@ -9092,7 +10539,7 @@ var ReviewShell = ({
9092
10539
  filteredNumberedActiveItems,
9093
10540
  getItemPresetScope,
9094
10541
  hiddenOverlayItemIds,
9095
- isListVisible,
10542
+ isListVisible: isQaPanelVisible,
9096
10543
  isAllQaVisible,
9097
10544
  isRemoteSource,
9098
10545
  copiedPromptKey,
@@ -9120,6 +10567,49 @@ var ReviewShell = ({
9120
10567
  onToggleItemOverlayVisibility: toggleItemOverlayVisibility
9121
10568
  }
9122
10569
  ),
10570
+ isSourceInspectorEnabled && /* @__PURE__ */ jsx17(
10571
+ "aside",
10572
+ {
10573
+ className: "df-review-source-tree-panel",
10574
+ "aria-hidden": !isSourceTreePanelVisible,
10575
+ children: /* @__PURE__ */ jsxs15("div", { id: "df-review-section-outline", className: "df-review-section-outline", children: [
10576
+ /* @__PURE__ */ jsxs15("div", { className: "df-review-section-outline-head", children: [
10577
+ /* @__PURE__ */ jsxs15("span", { children: [
10578
+ /* @__PURE__ */ jsx17("strong", { children: "Source Tree" }),
10579
+ /* @__PURE__ */ jsx17("small", { children: isSectionOutlineFiltering ? `${filteredSectionOutlineCount} / ${sectionOutlineTotalCount} results` : `${sectionOutline?.length ?? 0} roots` })
10580
+ ] }),
10581
+ /* @__PURE__ */ jsxs15("div", { className: "df-review-section-outline-filter", children: [
10582
+ /* @__PURE__ */ jsx17(Search, { "aria-hidden": "true" }),
10583
+ /* @__PURE__ */ jsx17(
10584
+ "input",
10585
+ {
10586
+ "aria-label": "Filter source tree",
10587
+ type: "text",
10588
+ value: sectionOutlineFilter,
10589
+ placeholder: "Filter",
10590
+ autoComplete: "off",
10591
+ enterKeyHint: "search",
10592
+ spellCheck: false,
10593
+ onChange: (event) => setSectionOutlineFilter(event.currentTarget.value)
10594
+ }
10595
+ ),
10596
+ sectionOutlineFilter && /* @__PURE__ */ jsx17(
10597
+ "button",
10598
+ {
10599
+ "aria-label": "Clear source tree filter",
10600
+ className: "df-review-section-outline-filter-clear",
10601
+ type: "button",
10602
+ onMouseDown: (event) => event.preventDefault(),
10603
+ onClick: () => setSectionOutlineFilter(""),
10604
+ children: /* @__PURE__ */ jsx17(X, { "aria-hidden": "true" })
10605
+ }
10606
+ )
10607
+ ] })
10608
+ ] }),
10609
+ filteredSectionOutline.length > 0 ? /* @__PURE__ */ jsx17("div", { className: "df-review-section-outline-list", children: filteredSectionOutline.map(renderSectionOutlineEntry) }) : /* @__PURE__ */ jsx17("div", { className: "df-review-section-outline-empty", children: isSectionOutlineFiltering ? "No source matches" : "No sections found" })
10610
+ ] })
10611
+ }
10612
+ ),
9123
10613
  /* @__PURE__ */ jsx17(
9124
10614
  ReviewTargetFrame,
9125
10615
  {
@@ -9191,7 +10681,7 @@ var ReviewShell = ({
9191
10681
  /* @__PURE__ */ jsx17("div", { className: "df-review-source-candidate-list", children: sourceInspectorState.candidates.map((candidate) => /* @__PURE__ */ jsx17(
9192
10682
  "button",
9193
10683
  {
9194
- className: "df-review-source-candidate",
10684
+ className: `df-review-source-candidate is-${candidate.kind}`,
9195
10685
  type: "button",
9196
10686
  onClick: (event) => {
9197
10687
  event.preventDefault();
@@ -9201,7 +10691,7 @@ var ReviewShell = ({
9201
10691
  children: /* @__PURE__ */ jsxs15("span", { className: "df-review-source-candidate-main", children: [
9202
10692
  /* @__PURE__ */ jsx17("strong", { children: candidate.label }),
9203
10693
  /* @__PURE__ */ jsx17("span", { children: candidate.filePath }),
9204
- /* @__PURE__ */ jsx17("small", { children: candidate.positionLabel || (candidate.usesPosition ? "" : "file only") })
10694
+ /* @__PURE__ */ jsx17("small", { children: candidate.positionLabel || "-:-" })
9205
10695
  ] })
9206
10696
  },
9207
10697
  candidate.id
@@ -9424,12 +10914,16 @@ lucide-react/dist/esm/context.mjs:
9424
10914
  lucide-react/dist/esm/Icon.mjs:
9425
10915
  lucide-react/dist/esm/createLucideIcon.mjs:
9426
10916
  lucide-react/dist/esm/icons/bot.mjs:
10917
+ lucide-react/dist/esm/icons/chevron-down.mjs:
9427
10918
  lucide-react/dist/esm/icons/circle-question-mark.mjs:
10919
+ lucide-react/dist/esm/icons/code-xml.mjs:
9428
10920
  lucide-react/dist/esm/icons/copy.mjs:
10921
+ lucide-react/dist/esm/icons/database.mjs:
10922
+ lucide-react/dist/esm/icons/ellipsis.mjs:
9429
10923
  lucide-react/dist/esm/icons/external-link.mjs:
9430
10924
  lucide-react/dist/esm/icons/eye-off.mjs:
9431
10925
  lucide-react/dist/esm/icons/eye.mjs:
9432
- lucide-react/dist/esm/icons/grip-vertical.mjs:
10926
+ lucide-react/dist/esm/icons/file-text.mjs:
9433
10927
  lucide-react/dist/esm/icons/image.mjs:
9434
10928
  lucide-react/dist/esm/icons/layout-grid.mjs:
9435
10929
  lucide-react/dist/esm/icons/link-2.mjs:
@@ -9437,16 +10931,20 @@ lucide-react/dist/esm/icons/list-filter.mjs:
9437
10931
  lucide-react/dist/esm/icons/map.mjs:
9438
10932
  lucide-react/dist/esm/icons/maximize-2.mjs:
9439
10933
  lucide-react/dist/esm/icons/monitor.mjs:
10934
+ lucide-react/dist/esm/icons/moon.mjs:
9440
10935
  lucide-react/dist/esm/icons/pencil.mjs:
9441
10936
  lucide-react/dist/esm/icons/rectangle-horizontal.mjs:
9442
10937
  lucide-react/dist/esm/icons/refresh-cw.mjs:
9443
10938
  lucide-react/dist/esm/icons/ruler.mjs:
9444
10939
  lucide-react/dist/esm/icons/scan.mjs:
10940
+ lucide-react/dist/esm/icons/search.mjs:
9445
10941
  lucide-react/dist/esm/icons/settings.mjs:
9446
10942
  lucide-react/dist/esm/icons/smartphone.mjs:
9447
10943
  lucide-react/dist/esm/icons/square-mouse-pointer.mjs:
9448
10944
  lucide-react/dist/esm/icons/sticky-note.mjs:
10945
+ lucide-react/dist/esm/icons/sun.mjs:
9449
10946
  lucide-react/dist/esm/icons/upload.mjs:
10947
+ lucide-react/dist/esm/icons/user-round.mjs:
9450
10948
  lucide-react/dist/esm/icons/x.mjs:
9451
10949
  lucide-react/dist/esm/lucide-react.mjs:
9452
10950
  (**