@designfever/web-review-kit 0.8.1 → 0.8.2

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.
@@ -4,6 +4,7 @@ import {
4
4
  clamp,
5
5
  createWebReviewKit,
6
6
  getBoundMarkerPoint,
7
+ getDraftViewportScale,
7
8
  getHotkeyActionKey,
8
9
  getItemHighlightSelection,
9
10
  getNumberedReviewItems,
@@ -15,10 +16,10 @@ import {
15
16
  runWithAutoScrollBehavior,
16
17
  shouldShowMarkerForScope,
17
18
  toHostPoint
18
- } from "./chunk-4ZP7B7R6.js";
19
+ } from "./chunk-ZWJNUOYV.js";
19
20
 
20
21
  // src/react-shell.tsx
21
- import React2 from "react";
22
+ import React3 from "react";
22
23
  import { createRoot as createRoot2 } from "react-dom/client";
23
24
 
24
25
  // src/react-shell/style/base.ts
@@ -122,6 +123,9 @@ var reviewShellBaseStyle = `
122
123
  --df-review-color-accent-contrast: #0f1218;
123
124
  --df-review-color-accent-soft: rgba(124, 199, 255, 0.12);
124
125
  --df-review-color-accent-hover: rgba(124, 199, 255, 0.2);
126
+ --df-review-color-dom: #d7ff5f;
127
+ --df-review-color-dom-contrast: #0f1218;
128
+ --df-review-color-dom-soft: rgba(215, 255, 95, 0.16);
125
129
  --df-review-color-danger: #ff8f61;
126
130
  --df-review-color-danger-soft: rgba(255, 143, 97, 0.12);
127
131
  --df-review-color-purple: #b395ff;
@@ -180,6 +184,9 @@ var reviewShellBaseStyle = `
180
184
  --df-review-accent-contrast: var(--df-review-color-accent-contrast);
181
185
  --df-review-accent-soft: var(--df-review-color-accent-soft);
182
186
  --df-review-accent-hover: var(--df-review-color-accent-hover);
187
+ --df-review-dom: var(--df-review-color-dom);
188
+ --df-review-dom-contrast: var(--df-review-color-dom-contrast);
189
+ --df-review-dom-soft: var(--df-review-color-dom-soft);
183
190
  --df-review-danger: var(--df-review-color-danger);
184
191
  --df-review-danger-soft: var(--df-review-color-danger-soft);
185
192
  --df-review-purple: var(--df-review-color-purple);
@@ -219,6 +226,9 @@ var reviewShellBaseStyle = `
219
226
  --df-review-color-accent-contrast: #ffffff;
220
227
  --df-review-color-accent-soft: rgba(23, 105, 170, 0.1);
221
228
  --df-review-color-accent-hover: rgba(23, 105, 170, 0.16);
229
+ --df-review-color-dom: #617f00;
230
+ --df-review-color-dom-contrast: #ffffff;
231
+ --df-review-color-dom-soft: rgba(97, 127, 0, 0.12);
222
232
  --df-review-color-danger: #b94418;
223
233
  --df-review-color-danger-soft: rgba(185, 68, 24, 0.1);
224
234
  --df-review-color-purple: #6543b8;
@@ -2267,7 +2277,7 @@ var reviewShellQaPanelStyle = `
2267
2277
  position: relative;
2268
2278
  z-index: 600;
2269
2279
  display: grid;
2270
- grid-template-rows: minmax(0, 1fr) auto;
2280
+ grid-template-rows: minmax(0, 1fr);
2271
2281
  min-width: 0;
2272
2282
  min-height: 0;
2273
2283
  overflow: hidden;
@@ -2277,8 +2287,11 @@ var reviewShellQaPanelStyle = `
2277
2287
  }
2278
2288
 
2279
2289
  .df-review-qa-draft-host {
2290
+ grid-column: 2;
2291
+ grid-row: 1 / span 3;
2280
2292
  position: relative;
2281
- z-index: 2;
2293
+ z-index: 720;
2294
+ align-self: end;
2282
2295
  display: none;
2283
2296
  justify-self: end;
2284
2297
  width: calc(100% - var(--df-review-space-4));
@@ -2290,11 +2303,6 @@ var reviewShellQaPanelStyle = `
2290
2303
  display: block;
2291
2304
  }
2292
2305
 
2293
- .df-review-qa-panel[data-has-draft-composer="true"] .df-review-panel-body {
2294
- opacity: 0.36;
2295
- pointer-events: none;
2296
- }
2297
-
2298
2306
  .df-review-shell:not(.is-list-visible) .df-review-qa-panel,
2299
2307
  .df-review-qa-panel[aria-hidden="true"] {
2300
2308
  visibility: hidden;
@@ -2302,11 +2310,16 @@ var reviewShellQaPanelStyle = `
2302
2310
  pointer-events: none;
2303
2311
  }
2304
2312
 
2313
+ .df-review-shell:not(.is-list-visible) .df-review-qa-draft-host {
2314
+ visibility: hidden;
2315
+ pointer-events: none;
2316
+ }
2317
+
2305
2318
  .df-review-source-tree-panel {
2306
2319
  grid-column: 2;
2307
2320
  grid-row: 1 / span 3;
2308
2321
  position: relative;
2309
- z-index: 600;
2322
+ z-index: 900;
2310
2323
  display: grid;
2311
2324
  min-width: 0;
2312
2325
  min-height: 0;
@@ -4320,151 +4333,18 @@ var reviewShellSourceInspectorStyle = `
4320
4333
  position: fixed;
4321
4334
  z-index: 880;
4322
4335
  pointer-events: none;
4323
- border: 2px solid rgba(124, 199, 255, 0.96);
4336
+ border: 2px solid var(--df-review-dom);
4324
4337
  border-radius: 4px;
4325
4338
  box-shadow:
4326
4339
  0 0 0 1px rgba(15, 18, 24, 0.58),
4327
- 0 0 0 5px rgba(124, 199, 255, 0.16);
4328
- }
4329
-
4330
- .df-review-source-outline.is-pinned {
4331
- border-color: var(--df-review-warning);
4332
- box-shadow:
4333
- 0 0 0 1px rgba(15, 18, 24, 0.58),
4334
- 0 0 0 5px rgba(243, 183, 95, 0.16);
4335
- }
4336
-
4337
- .df-review-source-popover {
4338
- --df-review-source-popover-line: rgba(226, 233, 245, 0.16);
4339
- --df-review-source-popover-text: #edf3fb;
4340
- --df-review-source-popover-muted: rgba(237, 243, 251, 0.68);
4341
- --df-review-source-popover-subtle: rgba(237, 243, 251, 0.5);
4342
- --df-review-source-popover-data: #f3b75f;
4343
- --df-review-source-popover-data-muted: rgba(243, 183, 95, 0.78);
4344
- --df-review-source-popover-data-subtle: rgba(243, 183, 95, 0.62);
4345
- --df-review-source-popover-hover: rgba(124, 199, 255, 0.14);
4346
- position: fixed;
4347
- z-index: 890;
4348
- display: grid;
4349
- width: fit-content;
4350
- min-width: min(240px, calc(100vw - 24px));
4351
- max-width: min(440px, calc(100vw - 24px));
4352
- max-height: 260px;
4353
- overflow: hidden;
4354
- border: 1px solid var(--df-review-source-popover-line);
4355
- border-radius: var(--df-review-radius-md);
4356
- padding: 6px;
4357
- color: var(--df-review-source-popover-text);
4358
- color-scheme: dark;
4359
- background: rgba(19, 24, 33, 0.96);
4360
- box-shadow: var(--df-review-shadow-panel);
4361
- backdrop-filter: blur(10px);
4362
- }
4363
-
4364
- .df-review-source-popover-close {
4365
- position: absolute;
4366
- top: 5px;
4367
- right: 5px;
4368
- z-index: 1;
4369
- }
4370
-
4371
- .df-review-source-popover-close button {
4372
- display: grid;
4373
- place-items: center;
4374
- width: 24px;
4375
- height: 24px;
4376
- border: 1px solid transparent;
4377
- border-radius: var(--df-review-radius-sm);
4378
- padding: 0;
4379
- color: var(--df-review-source-popover-subtle);
4380
- background: transparent;
4381
- font-size: var(--df-review-font-size-xl);
4382
- font-weight: var(--df-review-font-weight-normal);
4383
- line-height: 1;
4384
- }
4385
-
4386
- .df-review-source-popover-close button:hover {
4387
- border-color: var(--df-review-source-popover-line);
4388
- color: var(--df-review-source-popover-text);
4389
- background: var(--df-review-source-popover-hover);
4390
- }
4391
-
4392
- .df-review-source-candidate-list {
4393
- display: grid;
4394
- gap: 0;
4395
- max-height: min(220px, calc(100vh - 96px));
4396
- min-height: 0;
4397
- overflow-x: hidden;
4398
- overflow-y: auto;
4399
- padding-right: 2px;
4400
- scrollbar-gutter: stable;
4401
- }
4402
-
4403
- .df-review-source-candidate {
4404
- display: grid;
4405
- width: 100%;
4406
- border: 0;
4407
- border-top: 1px solid transparent;
4408
- border-radius: var(--df-review-radius-sm);
4409
- padding: 9px 30px 9px 8px;
4410
- color: var(--df-review-source-popover-text);
4411
- background: transparent;
4412
- text-align: left;
4413
- }
4414
-
4415
- .df-review-source-candidate + .df-review-source-candidate {
4416
- border-top-color: var(--df-review-source-popover-line);
4417
- }
4418
-
4419
- .df-review-source-candidate:hover {
4420
- background: var(--df-review-source-popover-hover);
4421
- }
4422
-
4423
- .df-review-source-candidate-main {
4424
- display: grid;
4425
- gap: 1px;
4426
- min-width: 0;
4427
- }
4428
-
4429
- .df-review-source-candidate-main strong,
4430
- .df-review-source-candidate-main small {
4431
- overflow: hidden;
4432
- text-overflow: ellipsis;
4433
- white-space: nowrap;
4434
- }
4435
-
4436
- .df-review-source-candidate-main strong {
4437
- font-size: var(--df-review-font-size-xs);
4438
- font-weight: var(--df-review-font-weight-emphasis);
4439
- line-height: 1.2;
4440
- }
4441
-
4442
- .df-review-source-candidate-main span {
4443
- overflow-wrap: anywhere;
4444
- color: var(--df-review-source-popover-muted);
4445
- font-family: var(--df-review-font-mono);
4446
- font-size: var(--df-review-font-size-2xs);
4447
- line-height: 1.24;
4448
- white-space: normal;
4340
+ 0 0 0 5px var(--df-review-dom-soft);
4449
4341
  }
4450
4342
 
4451
- .df-review-source-candidate-main small {
4452
- color: var(--df-review-source-popover-subtle);
4453
- font-family: var(--df-review-font-mono);
4454
- font-size: var(--df-review-font-size-2xs);
4455
- line-height: 1.2;
4456
- }
4457
-
4458
- .df-review-source-candidate.is-data .df-review-source-candidate-main strong {
4459
- color: var(--df-review-source-popover-data);
4460
- }
4461
-
4462
- .df-review-source-candidate.is-data .df-review-source-candidate-main span {
4463
- color: var(--df-review-source-popover-data-muted);
4464
- }
4465
-
4466
- .df-review-source-candidate.is-data .df-review-source-candidate-main small {
4467
- color: var(--df-review-source-popover-data-subtle);
4343
+ .df-review-source-outline.is-hover {
4344
+ border-width: 1px;
4345
+ border-color: var(--df-review-dom);
4346
+ opacity: 0.72;
4347
+ box-shadow: 0 0 0 1px rgba(15, 18, 24, 0.48);
4468
4348
  }
4469
4349
 
4470
4350
  `;
@@ -4699,6 +4579,7 @@ var reviewShellSectionOutlineStyle = `
4699
4579
  display: grid;
4700
4580
  border: 1px solid transparent;
4701
4581
  border-radius: var(--df-review-radius-sm);
4582
+ cursor: pointer;
4702
4583
  transition: border-color 140ms ease, background 140ms ease;
4703
4584
  }
4704
4585
 
@@ -4707,15 +4588,26 @@ var reviewShellSectionOutlineStyle = `
4707
4588
  background: var(--df-review-accent-soft);
4708
4589
  }
4709
4590
 
4591
+ .df-review-section-outline-entry-body:has(.df-review-section-outline-name:focus) {
4592
+ outline: 2px solid var(--df-review-dom);
4593
+ outline-offset: 1px;
4594
+ }
4595
+
4596
+ .df-review-section-outline-entry-body.is-selected {
4597
+ border-color: transparent;
4598
+ background: transparent;
4599
+ box-shadow: none;
4600
+ }
4601
+
4710
4602
 
4711
4603
  .df-review-section-outline-row {
4712
4604
  display: grid;
4713
- grid-template-columns: 18px minmax(0, 1fr) auto;
4714
- align-items: center;
4605
+ grid-template-columns: 18px minmax(0, 1fr);
4606
+ align-items: start;
4715
4607
  gap: 7px;
4716
4608
  border-radius: var(--df-review-radius-sm);
4717
- min-height: 42px;
4718
- padding: 6px 7px 6px 6px;
4609
+ min-height: 62px;
4610
+ padding: 8px 7px 7px 6px;
4719
4611
  }
4720
4612
 
4721
4613
  .df-review-section-outline-toggle {
@@ -4754,6 +4646,20 @@ var reviewShellSectionOutlineStyle = `
4754
4646
  pointer-events: none;
4755
4647
  }
4756
4648
 
4649
+ .df-review-section-outline-main {
4650
+ display: grid;
4651
+ gap: 7px;
4652
+ min-width: 0;
4653
+ }
4654
+
4655
+ .df-review-section-outline-title {
4656
+ display: grid;
4657
+ grid-template-columns: minmax(0, 1fr) auto;
4658
+ align-items: start;
4659
+ gap: 6px;
4660
+ min-width: 0;
4661
+ }
4662
+
4757
4663
  .df-review-section-outline-name {
4758
4664
  display: grid;
4759
4665
  gap: 2px;
@@ -4765,6 +4671,7 @@ var reviewShellSectionOutlineStyle = `
4765
4671
  background: transparent;
4766
4672
  font-size: var(--df-review-font-size-sm);
4767
4673
  font-weight: var(--df-review-font-weight-normal);
4674
+ line-height: 1.25;
4768
4675
  text-align: left;
4769
4676
  white-space: normal;
4770
4677
  cursor: pointer;
@@ -4772,19 +4679,24 @@ var reviewShellSectionOutlineStyle = `
4772
4679
 
4773
4680
  .df-review-section-outline-name span {
4774
4681
  min-width: 0;
4775
- overflow: hidden;
4776
- text-overflow: ellipsis;
4777
- white-space: nowrap;
4778
- }
4779
-
4780
- .df-review-section-outline-name span {
4682
+ overflow-wrap: anywhere;
4781
4683
  color: var(--df-review-section-outline-name-color);
4684
+ white-space: normal;
4782
4685
  }
4783
4686
 
4784
4687
  .df-review-section-outline-name:hover {
4785
4688
  color: var(--df-review-accent);
4786
4689
  }
4787
4690
 
4691
+ .df-review-section-outline-name:focus {
4692
+ outline: 0;
4693
+ }
4694
+
4695
+ .df-review-section-outline-row.is-selected .df-review-section-outline-name span {
4696
+ color: var(--df-review-dom);
4697
+ font-weight: var(--df-review-font-weight-emphasis);
4698
+ }
4699
+
4788
4700
  .df-review-section-outline-meta {
4789
4701
  position: relative;
4790
4702
  display: grid;
@@ -4902,11 +4814,27 @@ var reviewShellSectionOutlineStyle = `
4902
4814
  line-height: 1;
4903
4815
  }
4904
4816
 
4905
- .df-review-section-outline-links {
4817
+ .df-review-section-outline-action-group {
4906
4818
  display: inline-flex;
4907
4819
  align-items: center;
4820
+ gap: 4px;
4821
+ min-width: 0;
4822
+ }
4823
+
4824
+ .df-review-section-outline-action-group.is-left {
4825
+ justify-content: flex-start;
4826
+ }
4827
+
4828
+ .df-review-section-outline-action-group.is-right {
4908
4829
  justify-content: flex-end;
4909
- gap: 1px;
4830
+ }
4831
+
4832
+ .df-review-section-outline-actions {
4833
+ display: grid;
4834
+ grid-template-columns: minmax(0, 1fr) max-content;
4835
+ align-items: center;
4836
+ gap: 8px;
4837
+ min-width: 0;
4910
4838
  }
4911
4839
 
4912
4840
  .df-review-section-outline-divider {
@@ -4949,10 +4877,82 @@ var reviewShellSectionOutlineStyle = `
4949
4877
  height: 16px;
4950
4878
  }
4951
4879
 
4880
+ .df-review-section-outline-link.is-dom-adjust,
4881
+ .df-review-section-outline-link.is-dom-reset {
4882
+ width: 20px;
4883
+ min-width: 20px;
4884
+ height: 20px;
4885
+ padding: 0;
4886
+ }
4887
+
4888
+ .df-review-section-outline-link.is-dom-adjust svg,
4889
+ .df-review-section-outline-link.is-dom-reset svg {
4890
+ width: 14px;
4891
+ height: 14px;
4892
+ }
4893
+
4894
+ .df-review-section-outline-adjust-status {
4895
+ display: inline-flex;
4896
+ align-items: center;
4897
+ gap: 3px;
4898
+ min-width: 0;
4899
+ color: var(--df-review-muted);
4900
+ font-family: var(--df-review-font-mono);
4901
+ font-size: var(--df-review-font-size-2xs);
4902
+ font-variant-numeric: tabular-nums;
4903
+ line-height: 1;
4904
+ white-space: nowrap;
4905
+ }
4906
+
4907
+ .df-review-section-outline-adjust-status > span {
4908
+ color: var(--df-review-subtle);
4909
+ }
4910
+
4911
+ .df-review-section-outline-adjust-status code {
4912
+ display: inline-block;
4913
+ width: 5ch;
4914
+ color: inherit;
4915
+ font: inherit;
4916
+ text-align: right;
4917
+ }
4918
+
4952
4919
  .df-review-section-outline-link:hover {
4953
- border-color: rgba(124, 199, 255, 0.34);
4920
+ border-color: transparent;
4954
4921
  color: var(--df-review-accent);
4955
- background: var(--df-review-accent-soft);
4922
+ background: transparent;
4923
+ }
4924
+
4925
+ .df-review-section-outline-link:focus-visible {
4926
+ outline: 2px solid var(--df-review-focus-ring);
4927
+ outline-offset: 1px;
4928
+ }
4929
+
4930
+ .df-review-section-outline-link.is-active,
4931
+ .df-review-section-outline-link.is-copied {
4932
+ color: var(--df-review-accent);
4933
+ }
4934
+
4935
+ .df-review-section-outline-link.is-active {
4936
+ border-color: var(--df-review-accent);
4937
+ color: var(--df-review-accent-contrast);
4938
+ background: var(--df-review-accent);
4939
+ }
4940
+
4941
+ .df-review-section-outline-link.is-dom-adjust:hover,
4942
+ .df-review-section-outline-link.is-dom-reset:hover {
4943
+ color: var(--df-review-dom);
4944
+ }
4945
+
4946
+ .df-review-section-outline-link.is-dom-adjust.is-active {
4947
+ border-color: var(--df-review-dom);
4948
+ color: var(--df-review-dom-contrast);
4949
+ background: var(--df-review-dom);
4950
+ }
4951
+
4952
+ .df-review-section-outline-link.is-copied {
4953
+ border-color: rgba(243, 183, 95, 0.42);
4954
+ color: var(--df-review-warning);
4955
+ background: rgba(243, 183, 95, 0.1);
4956
4956
  }
4957
4957
 
4958
4958
  .df-review-section-outline-link svg {
@@ -5683,18 +5683,29 @@ var __iconNode25 = [
5683
5683
  ];
5684
5684
  var MoveVertical = createLucideIcon("move-vertical", __iconNode25);
5685
5685
 
5686
- // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/network.mjs
5686
+ // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/move.mjs
5687
5687
  var __iconNode26 = [
5688
+ ["path", { d: "M12 2v20", key: "t6zp3m" }],
5689
+ ["path", { d: "m15 19-3 3-3-3", key: "11eu04" }],
5690
+ ["path", { d: "m19 9 3 3-3 3", key: "1mg7y2" }],
5691
+ ["path", { d: "M2 12h20", key: "9i4pu4" }],
5692
+ ["path", { d: "m5 9-3 3 3 3", key: "j64kie" }],
5693
+ ["path", { d: "m9 5 3-3 3 3", key: "l8vdw6" }]
5694
+ ];
5695
+ var Move = createLucideIcon("move", __iconNode26);
5696
+
5697
+ // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/network.mjs
5698
+ var __iconNode27 = [
5688
5699
  ["rect", { x: "16", y: "16", width: "6", height: "6", rx: "1", key: "4q2zg0" }],
5689
5700
  ["rect", { x: "2", y: "16", width: "6", height: "6", rx: "1", key: "8cvhb9" }],
5690
5701
  ["rect", { x: "9", y: "2", width: "6", height: "6", rx: "1", key: "1egb70" }],
5691
5702
  ["path", { d: "M5 16v-3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v3", key: "1jsf9p" }],
5692
5703
  ["path", { d: "M12 12V8", key: "2874zd" }]
5693
5704
  ];
5694
- var Network = createLucideIcon("network", __iconNode26);
5705
+ var Network = createLucideIcon("network", __iconNode27);
5695
5706
 
5696
5707
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/pencil.mjs
5697
- var __iconNode27 = [
5708
+ var __iconNode28 = [
5698
5709
  [
5699
5710
  "path",
5700
5711
  {
@@ -5704,32 +5715,39 @@ var __iconNode27 = [
5704
5715
  ],
5705
5716
  ["path", { d: "m15 5 4 4", key: "1mk7zo" }]
5706
5717
  ];
5707
- var Pencil = createLucideIcon("pencil", __iconNode27);
5718
+ var Pencil = createLucideIcon("pencil", __iconNode28);
5708
5719
 
5709
5720
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/plus.mjs
5710
- var __iconNode28 = [
5721
+ var __iconNode29 = [
5711
5722
  ["path", { d: "M5 12h14", key: "1ays0h" }],
5712
5723
  ["path", { d: "M12 5v14", key: "s699le" }]
5713
5724
  ];
5714
- var Plus = createLucideIcon("plus", __iconNode28);
5725
+ var Plus = createLucideIcon("plus", __iconNode29);
5715
5726
 
5716
5727
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/rectangle-horizontal.mjs
5717
- var __iconNode29 = [
5728
+ var __iconNode30 = [
5718
5729
  ["rect", { width: "20", height: "12", x: "2", y: "6", rx: "2", key: "9lu3g6" }]
5719
5730
  ];
5720
- var RectangleHorizontal = createLucideIcon("rectangle-horizontal", __iconNode29);
5731
+ var RectangleHorizontal = createLucideIcon("rectangle-horizontal", __iconNode30);
5721
5732
 
5722
5733
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/refresh-cw.mjs
5723
- var __iconNode30 = [
5734
+ var __iconNode31 = [
5724
5735
  ["path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8", key: "v9h5vc" }],
5725
5736
  ["path", { d: "M21 3v5h-5", key: "1q7to0" }],
5726
5737
  ["path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16", key: "3uifl3" }],
5727
5738
  ["path", { d: "M8 16H3v5", key: "1cv678" }]
5728
5739
  ];
5729
- var RefreshCw = createLucideIcon("refresh-cw", __iconNode30);
5740
+ var RefreshCw = createLucideIcon("refresh-cw", __iconNode31);
5741
+
5742
+ // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/rotate-ccw.mjs
5743
+ var __iconNode32 = [
5744
+ ["path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8", key: "1357e3" }],
5745
+ ["path", { d: "M3 3v5h5", key: "1xhq8a" }]
5746
+ ];
5747
+ var RotateCcw = createLucideIcon("rotate-ccw", __iconNode32);
5730
5748
 
5731
5749
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/ruler.mjs
5732
- var __iconNode31 = [
5750
+ var __iconNode33 = [
5733
5751
  [
5734
5752
  "path",
5735
5753
  {
@@ -5742,26 +5760,26 @@ var __iconNode31 = [
5742
5760
  ["path", { d: "m8.5 6.5 2-2", key: "vc6u1g" }],
5743
5761
  ["path", { d: "m17.5 15.5 2-2", key: "wo5hmg" }]
5744
5762
  ];
5745
- var Ruler = createLucideIcon("ruler", __iconNode31);
5763
+ var Ruler = createLucideIcon("ruler", __iconNode33);
5746
5764
 
5747
5765
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/scan.mjs
5748
- var __iconNode32 = [
5766
+ var __iconNode34 = [
5749
5767
  ["path", { d: "M3 7V5a2 2 0 0 1 2-2h2", key: "aa7l1z" }],
5750
5768
  ["path", { d: "M17 3h2a2 2 0 0 1 2 2v2", key: "4qcy5o" }],
5751
5769
  ["path", { d: "M21 17v2a2 2 0 0 1-2 2h-2", key: "6vwrx8" }],
5752
5770
  ["path", { d: "M7 21H5a2 2 0 0 1-2-2v-2", key: "ioqczr" }]
5753
5771
  ];
5754
- var Scan = createLucideIcon("scan", __iconNode32);
5772
+ var Scan = createLucideIcon("scan", __iconNode34);
5755
5773
 
5756
5774
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/search.mjs
5757
- var __iconNode33 = [
5775
+ var __iconNode35 = [
5758
5776
  ["path", { d: "m21 21-4.34-4.34", key: "14j7rj" }],
5759
5777
  ["circle", { cx: "11", cy: "11", r: "8", key: "4ej97u" }]
5760
5778
  ];
5761
- var Search = createLucideIcon("search", __iconNode33);
5779
+ var Search = createLucideIcon("search", __iconNode35);
5762
5780
 
5763
5781
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/settings.mjs
5764
- var __iconNode34 = [
5782
+ var __iconNode36 = [
5765
5783
  [
5766
5784
  "path",
5767
5785
  {
@@ -5771,17 +5789,17 @@ var __iconNode34 = [
5771
5789
  ],
5772
5790
  ["circle", { cx: "12", cy: "12", r: "3", key: "1v7zrd" }]
5773
5791
  ];
5774
- var Settings = createLucideIcon("settings", __iconNode34);
5792
+ var Settings = createLucideIcon("settings", __iconNode36);
5775
5793
 
5776
5794
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/smartphone.mjs
5777
- var __iconNode35 = [
5795
+ var __iconNode37 = [
5778
5796
  ["rect", { width: "14", height: "20", x: "5", y: "2", rx: "2", ry: "2", key: "1yt0o3" }],
5779
5797
  ["path", { d: "M12 18h.01", key: "mhygvu" }]
5780
5798
  ];
5781
- var Smartphone = createLucideIcon("smartphone", __iconNode35);
5799
+ var Smartphone = createLucideIcon("smartphone", __iconNode37);
5782
5800
 
5783
5801
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/square-mouse-pointer.mjs
5784
- var __iconNode36 = [
5802
+ var __iconNode38 = [
5785
5803
  [
5786
5804
  "path",
5787
5805
  {
@@ -5791,10 +5809,10 @@ var __iconNode36 = [
5791
5809
  ],
5792
5810
  ["path", { d: "M21 11V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h6", key: "14rsvq" }]
5793
5811
  ];
5794
- var SquareMousePointer = createLucideIcon("square-mouse-pointer", __iconNode36);
5812
+ var SquareMousePointer = createLucideIcon("square-mouse-pointer", __iconNode38);
5795
5813
 
5796
5814
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/sun.mjs
5797
- var __iconNode37 = [
5815
+ var __iconNode39 = [
5798
5816
  ["circle", { cx: "12", cy: "12", r: "4", key: "4exip2" }],
5799
5817
  ["path", { d: "M12 2v2", key: "tus03m" }],
5800
5818
  ["path", { d: "M12 20v2", key: "1lh1kg" }],
@@ -5805,40 +5823,40 @@ var __iconNode37 = [
5805
5823
  ["path", { d: "m6.34 17.66-1.41 1.41", key: "1m8zz5" }],
5806
5824
  ["path", { d: "m19.07 4.93-1.41 1.41", key: "1shlcs" }]
5807
5825
  ];
5808
- var Sun = createLucideIcon("sun", __iconNode37);
5826
+ var Sun = createLucideIcon("sun", __iconNode39);
5809
5827
 
5810
5828
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/trash-2.mjs
5811
- var __iconNode38 = [
5829
+ var __iconNode40 = [
5812
5830
  ["path", { d: "M10 11v6", key: "nco0om" }],
5813
5831
  ["path", { d: "M14 11v6", key: "outv1u" }],
5814
5832
  ["path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6", key: "miytrc" }],
5815
5833
  ["path", { d: "M3 6h18", key: "d0wm0j" }],
5816
5834
  ["path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2", key: "e791ji" }]
5817
5835
  ];
5818
- var Trash2 = createLucideIcon("trash-2", __iconNode38);
5836
+ var Trash2 = createLucideIcon("trash-2", __iconNode40);
5819
5837
 
5820
5838
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/type.mjs
5821
- var __iconNode39 = [
5839
+ var __iconNode41 = [
5822
5840
  ["path", { d: "M12 4v16", key: "1654pz" }],
5823
5841
  ["path", { d: "M4 7V5a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v2", key: "e0r10z" }],
5824
5842
  ["path", { d: "M9 20h6", key: "s66wpe" }]
5825
5843
  ];
5826
- var Type = createLucideIcon("type", __iconNode39);
5844
+ var Type = createLucideIcon("type", __iconNode41);
5827
5845
 
5828
5846
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/upload.mjs
5829
- var __iconNode40 = [
5847
+ var __iconNode42 = [
5830
5848
  ["path", { d: "M12 3v12", key: "1x0j5s" }],
5831
5849
  ["path", { d: "m17 8-5-5-5 5", key: "7q97r8" }],
5832
5850
  ["path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4", key: "ih7n3h" }]
5833
5851
  ];
5834
- var Upload = createLucideIcon("upload", __iconNode40);
5852
+ var Upload = createLucideIcon("upload", __iconNode42);
5835
5853
 
5836
5854
  // node_modules/.pnpm/lucide-react@1.20.0_react@19.2.7/node_modules/lucide-react/dist/esm/icons/x.mjs
5837
- var __iconNode41 = [
5855
+ var __iconNode43 = [
5838
5856
  ["path", { d: "M18 6 6 18", key: "1bl5f8" }],
5839
5857
  ["path", { d: "m6 6 12 12", key: "d8bk6v" }]
5840
5858
  ];
5841
- var X = createLucideIcon("x", __iconNode41);
5859
+ var X = createLucideIcon("x", __iconNode43);
5842
5860
 
5843
5861
  // src/react-shell/figma/image.overlay.controller.ts
5844
5862
  import {
@@ -7277,9 +7295,7 @@ var FigmaImagesPanel = ({
7277
7295
  {
7278
7296
  "aria-label": `Edit ${imageLabel} label`,
7279
7297
  className: "df-review-figma-image-icon-button",
7280
- "data-review-tooltip": "Edit label",
7281
7298
  disabled: isMutating,
7282
- title: "Edit label",
7283
7299
  type: "button",
7284
7300
  onClick: (event) => {
7285
7301
  event.stopPropagation();
@@ -7298,7 +7314,6 @@ var FigmaImagesPanel = ({
7298
7314
  {
7299
7315
  "aria-label": "Delete Figma image",
7300
7316
  className: "df-review-figma-image-icon-button is-danger",
7301
- "data-review-tooltip": "Delete Figma image",
7302
7317
  disabled: isMutating,
7303
7318
  type: "button",
7304
7319
  onClick: (event) => {
@@ -7989,7 +8004,6 @@ var createReviewShellConfig = ({
7989
8004
  });
7990
8005
  const resolvedSourceInspector = resolvedReviewSourceOptions.sourceInspector;
7991
8006
  const resolvedSourceRoot = resolvedReviewSourceOptions.sourceRoot;
7992
- const isSourceInspectorEnabled = resolvedSourceInspector?.enabled !== false && Boolean(resolvedSourceRoot?.trim());
7993
8007
  return {
7994
8008
  initialPrompt,
7995
8009
  qaPrompt,
@@ -8015,8 +8029,7 @@ var createReviewShellConfig = ({
8015
8029
  sourceRoot: resolvedSourceRoot
8016
8030
  },
8017
8031
  showSourceSelect: normalizedAdapters.sources.length > 1,
8018
- isSourceInspectorEnabled,
8019
- isSourceTreeHoverOutlineEnabled: isSourceInspectorEnabled && resolvedSourceInspector?.hoverOutline !== false
8032
+ isSourceTreeHoverOutlineEnabled: resolvedSourceInspector?.hoverOutline !== false
8020
8033
  };
8021
8034
  };
8022
8035
  var ReviewShellConfigContext = createContext4(null);
@@ -9603,7 +9616,11 @@ var ReviewQaPanel = ({
9603
9616
  const listRef = useRef4(null);
9604
9617
  const emptyMessage = isAllQaVisible ? `No ${activeAdapterEntry.label} QA.` : isRemoteSource ? `No ${activeAdapterEntry.label} QA on this page.` : "No QA on this page.";
9605
9618
  useEffect5(() => {
9606
- if (!isListVisible || !selectedItemId) return;
9619
+ if (!isListVisible) return;
9620
+ if (!selectedItemId) {
9621
+ listRef.current?.querySelector("[data-review-qa-item-id]:focus")?.blur();
9622
+ return;
9623
+ }
9607
9624
  const selectedCard = Array.from(
9608
9625
  listRef.current?.querySelectorAll(
9609
9626
  "[data-review-qa-item-id]"
@@ -9614,90 +9631,87 @@ var ReviewQaPanel = ({
9614
9631
  selectedCard?.scrollIntoView({ block: "center", behavior: "smooth" });
9615
9632
  selectedCard?.focus({ preventScroll: true });
9616
9633
  }, [filteredNumberedActiveItems, isListVisible, selectedItemId]);
9617
- return /* @__PURE__ */ jsxs9("aside", { className: "df-review-qa-panel", "aria-hidden": !isListVisible, children: [
9618
- /* @__PURE__ */ jsx13("div", { className: "df-review-panel-body", children: /* @__PURE__ */ jsxs9("section", { className: "df-review-item-list", children: [
9619
- /* @__PURE__ */ jsx13(
9620
- QaPanelHeader,
9621
- {
9622
- activeItemCount: activeItems.length,
9623
- activeRemainingItemCount,
9624
- filteredItemCount: filteredNumberedActiveItems.length,
9625
- isAllQaVisible,
9626
- isLoading,
9627
- label: activeAdapterEntry.label,
9628
- qaStatusFilters,
9629
- qaStatusFilterCounts,
9630
- showSourceSelect,
9631
- source,
9632
- sourceEntries,
9633
- statusOptions: activeAdapterEntry.statusOptions,
9634
- onChangeReviewSource,
9635
- onEnableActiveQaStatusFilters,
9636
- onQaStatusFilterToggle,
9637
- onRefreshReviewData
9638
- }
9639
- ),
9640
- /* @__PURE__ */ jsxs9(
9641
- "div",
9642
- {
9643
- className: "df-review-list-scroll",
9644
- ref: listRef,
9645
- onClick: (event) => {
9646
- if (event.target === event.currentTarget) {
9647
- onClearSelectedItem();
9634
+ return /* @__PURE__ */ jsx13("aside", { className: "df-review-qa-panel", "aria-hidden": !isListVisible, children: /* @__PURE__ */ jsx13("div", { className: "df-review-panel-body", children: /* @__PURE__ */ jsxs9("section", { className: "df-review-item-list", children: [
9635
+ /* @__PURE__ */ jsx13(
9636
+ QaPanelHeader,
9637
+ {
9638
+ activeItemCount: activeItems.length,
9639
+ activeRemainingItemCount,
9640
+ filteredItemCount: filteredNumberedActiveItems.length,
9641
+ isAllQaVisible,
9642
+ isLoading,
9643
+ label: activeAdapterEntry.label,
9644
+ qaStatusFilters,
9645
+ qaStatusFilterCounts,
9646
+ showSourceSelect,
9647
+ source,
9648
+ sourceEntries,
9649
+ statusOptions: activeAdapterEntry.statusOptions,
9650
+ onChangeReviewSource,
9651
+ onEnableActiveQaStatusFilters,
9652
+ onQaStatusFilterToggle,
9653
+ onRefreshReviewData
9654
+ }
9655
+ ),
9656
+ /* @__PURE__ */ jsxs9(
9657
+ "div",
9658
+ {
9659
+ className: "df-review-list-scroll",
9660
+ ref: listRef,
9661
+ onClick: (event) => {
9662
+ if (event.target === event.currentTarget) {
9663
+ onClearSelectedItem();
9664
+ }
9665
+ },
9666
+ children: [
9667
+ activeItems.length === 0 && /* @__PURE__ */ jsxs9(
9668
+ "p",
9669
+ {
9670
+ className: `df-review-empty${isLoading ? " is-loading" : ""}`,
9671
+ children: [
9672
+ isLoading && /* @__PURE__ */ jsx13("span", { className: "df-review-spinner", "aria-hidden": "true" }),
9673
+ /* @__PURE__ */ jsx13("span", { children: isLoading ? `Loading ${activeAdapterEntry.label} QA...` : emptyMessage })
9674
+ ]
9648
9675
  }
9649
- },
9650
- children: [
9651
- activeItems.length === 0 && /* @__PURE__ */ jsxs9(
9652
- "p",
9676
+ ),
9677
+ activeItems.length > 0 && filteredNumberedActiveItems.length === 0 && /* @__PURE__ */ jsx13("p", { className: "df-review-empty", children: "No QA in this filter." }),
9678
+ filteredNumberedActiveItems.map((numberedItem) => {
9679
+ const { item } = numberedItem;
9680
+ return /* @__PURE__ */ jsx13(
9681
+ QaItemCard,
9653
9682
  {
9654
- className: `df-review-empty${isLoading ? " is-loading" : ""}`,
9655
- children: [
9656
- isLoading && /* @__PURE__ */ jsx13("span", { className: "df-review-spinner", "aria-hidden": "true" }),
9657
- /* @__PURE__ */ jsx13("span", { children: isLoading ? `Loading ${activeAdapterEntry.label} QA...` : emptyMessage })
9658
- ]
9659
- }
9660
- ),
9661
- activeItems.length > 0 && filteredNumberedActiveItems.length === 0 && /* @__PURE__ */ jsx13("p", { className: "df-review-empty", children: "No QA in this filter." }),
9662
- filteredNumberedActiveItems.map((numberedItem) => {
9663
- const { item } = numberedItem;
9664
- return /* @__PURE__ */ jsx13(
9665
- QaItemCard,
9666
- {
9667
- activeAdapterEntry,
9668
- fields,
9669
- assigneeTitle,
9670
- currentPresetScope,
9671
- getItemPresetScope,
9672
- isOverlayVisible: !hiddenOverlayItemIds.has(item.id),
9673
- isMutating: mutatingItemIds.has(item.id),
9674
- isRemoteSource,
9675
- numberedItem,
9676
- remoteAdapterEntry,
9677
- copiedPromptKey,
9678
- selectedItemId,
9679
- onChangeItemAssignee,
9680
- onChangeItemStatus,
9681
- onClearSelectedItem,
9682
- onCopyItemLabel,
9683
- onCopyItemLink,
9684
- onCopyItemPrompt,
9685
- onCopyRemoteIssuePath,
9686
- onEditItem,
9687
- onRemoveItem,
9688
- onRestoreReviewItem,
9689
- onSubmitItem,
9690
- onToggleItemOverlayVisibility
9691
- },
9692
- item.id
9693
- );
9694
- })
9695
- ]
9696
- }
9697
- )
9698
- ] }) }),
9699
- /* @__PURE__ */ jsx13("div", { className: "df-review-qa-draft-host" })
9700
- ] });
9683
+ activeAdapterEntry,
9684
+ fields,
9685
+ assigneeTitle,
9686
+ currentPresetScope,
9687
+ getItemPresetScope,
9688
+ isOverlayVisible: !hiddenOverlayItemIds.has(item.id),
9689
+ isMutating: mutatingItemIds.has(item.id),
9690
+ isRemoteSource,
9691
+ numberedItem,
9692
+ remoteAdapterEntry,
9693
+ copiedPromptKey,
9694
+ selectedItemId,
9695
+ onChangeItemAssignee,
9696
+ onChangeItemStatus,
9697
+ onClearSelectedItem,
9698
+ onCopyItemLabel,
9699
+ onCopyItemLink,
9700
+ onCopyItemPrompt,
9701
+ onCopyRemoteIssuePath,
9702
+ onEditItem,
9703
+ onRemoveItem,
9704
+ onRestoreReviewItem,
9705
+ onSubmitItem,
9706
+ onToggleItemOverlayVisibility
9707
+ },
9708
+ item.id
9709
+ );
9710
+ })
9711
+ ]
9712
+ }
9713
+ )
9714
+ ] }) }) });
9701
9715
  };
9702
9716
 
9703
9717
  // src/react-shell/qa/use.review.qa.panel.data.ts
@@ -10466,6 +10480,7 @@ var getSectionOutline = (root, options) => {
10466
10480
  function getSectionOutlineRoots(root, options) {
10467
10481
  return Array.from(root.querySelectorAll(SECTION_OUTLINE_ROOT_SELECTOR)).filter(
10468
10482
  (element) => {
10483
+ if (element.closest('[data-dfwr-adjust-preview="true"]')) return false;
10469
10484
  const source = getSourceHintFromElement(element);
10470
10485
  const label = getOutlineLabel(element, source, "");
10471
10486
  return !isSkippedOutlineNode(label, source?.file, options) && !hasSectionOutlineRootAncestor(element, root, options);
@@ -11020,22 +11035,268 @@ var useReviewShellRefs = () => {
11020
11035
  return refs;
11021
11036
  };
11022
11037
 
11038
+ // src/react-shell/target/dom-adjustment.layer.ts
11039
+ var SOURCE_HIDDEN_ATTRIBUTE = "data-dfwr-move-source-hidden";
11040
+ var LAYER_ROOT_ATTRIBUTE = "data-dfwr-move-layer-root";
11041
+ var DomAdjustmentLayerManager = class {
11042
+ constructor({
11043
+ document: document2,
11044
+ onClear,
11045
+ renderElement = renderDomElementToCanvas
11046
+ }) {
11047
+ this.layers = /* @__PURE__ */ new Map();
11048
+ this.pending = /* @__PURE__ */ new Map();
11049
+ this.document = document2;
11050
+ this.onClear = onClear;
11051
+ this.renderElement = renderElement;
11052
+ this.root = createLayerRoot(document2);
11053
+ this.style = createLayerStyle(document2);
11054
+ document2.head?.appendChild(this.style);
11055
+ document2.documentElement.appendChild(this.root);
11056
+ }
11057
+ belongsTo(document2) {
11058
+ return this.document === document2;
11059
+ }
11060
+ async create(entryId, label, element, position, viewportScale) {
11061
+ const existing = this.layers.get(entryId);
11062
+ if (existing) {
11063
+ existing.position = position;
11064
+ syncLayerPosition(existing.wrapper, position, viewportScale);
11065
+ return true;
11066
+ }
11067
+ const HTMLElementConstructor = element.ownerDocument.defaultView?.HTMLElement;
11068
+ if (!HTMLElementConstructor || !(element instanceof HTMLElementConstructor)) {
11069
+ return false;
11070
+ }
11071
+ const token = Symbol(entryId);
11072
+ this.pending.set(entryId, token);
11073
+ const rect = element.getBoundingClientRect();
11074
+ const canvas = await this.renderElement(element);
11075
+ if (this.pending.get(entryId) !== token) return false;
11076
+ this.pending.delete(entryId);
11077
+ const wrapper = createLayerWrapper(this.document, entryId, label, canvas);
11078
+ wrapper.style.left = `${roundCss(rect.left + (this.document.defaultView?.scrollX ?? 0))}px`;
11079
+ wrapper.style.top = `${roundCss(rect.top + (this.document.defaultView?.scrollY ?? 0))}px`;
11080
+ wrapper.style.width = `${roundCss(rect.width)}px`;
11081
+ wrapper.style.height = `${roundCss(rect.height)}px`;
11082
+ canvas.style.width = "100%";
11083
+ canvas.style.height = "100%";
11084
+ syncLayerPosition(wrapper, position, viewportScale);
11085
+ const hiddenAttributeValue = element.getAttribute(SOURCE_HIDDEN_ATTRIBUTE);
11086
+ element.setAttribute(SOURCE_HIDDEN_ATTRIBUTE, "true");
11087
+ wrapper.querySelector("button")?.addEventListener("click", () => {
11088
+ this.clear(entryId);
11089
+ });
11090
+ this.root.appendChild(wrapper);
11091
+ this.layers.set(entryId, {
11092
+ element,
11093
+ hiddenAttributeValue,
11094
+ position,
11095
+ wrapper
11096
+ });
11097
+ return true;
11098
+ }
11099
+ adjust(entryId, delta, viewportScale) {
11100
+ const layer = this.layers.get(entryId);
11101
+ if (!layer) return null;
11102
+ layer.position = {
11103
+ x: layer.position.x + (delta.x ?? 0),
11104
+ y: layer.position.y + (delta.y ?? 0)
11105
+ };
11106
+ syncLayerPosition(layer.wrapper, layer.position, viewportScale);
11107
+ return layer.position;
11108
+ }
11109
+ setActive(entryId) {
11110
+ this.layers.forEach(({ wrapper }, id) => {
11111
+ if (id === entryId) {
11112
+ wrapper.dataset.dfwrMoveActive = "true";
11113
+ } else {
11114
+ delete wrapper.dataset.dfwrMoveActive;
11115
+ }
11116
+ });
11117
+ }
11118
+ clear(entryId, notify = true) {
11119
+ this.pending.delete(entryId);
11120
+ const layer = this.layers.get(entryId);
11121
+ if (!layer) {
11122
+ if (notify) this.onClear(entryId);
11123
+ return;
11124
+ }
11125
+ layer.wrapper.remove();
11126
+ if (layer.hiddenAttributeValue === null) {
11127
+ layer.element.removeAttribute(SOURCE_HIDDEN_ATTRIBUTE);
11128
+ } else {
11129
+ layer.element.setAttribute(
11130
+ SOURCE_HIDDEN_ATTRIBUTE,
11131
+ layer.hiddenAttributeValue
11132
+ );
11133
+ }
11134
+ this.layers.delete(entryId);
11135
+ if (notify) this.onClear(entryId);
11136
+ }
11137
+ destroy() {
11138
+ this.pending.clear();
11139
+ [...this.layers.keys()].forEach((entryId) => this.clear(entryId, false));
11140
+ this.root.remove();
11141
+ this.style.remove();
11142
+ }
11143
+ };
11144
+ async function renderDomElementToCanvas(element) {
11145
+ const html2canvas = (await import("html2canvas")).default;
11146
+ return html2canvas(element, {
11147
+ allowTaint: false,
11148
+ backgroundColor: null,
11149
+ imageTimeout: 5e3,
11150
+ logging: false,
11151
+ removeContainer: true,
11152
+ scale: element.ownerDocument.defaultView?.devicePixelRatio ?? 1,
11153
+ useCORS: true
11154
+ });
11155
+ }
11156
+ function createLayerRoot(document2) {
11157
+ const root = document2.createElement("div");
11158
+ root.setAttribute(LAYER_ROOT_ATTRIBUTE, "true");
11159
+ root.style.position = "absolute";
11160
+ root.style.inset = "0 auto auto 0";
11161
+ root.style.width = "0";
11162
+ root.style.height = "0";
11163
+ root.style.zIndex = "2147483645";
11164
+ root.style.pointerEvents = "none";
11165
+ return root;
11166
+ }
11167
+ function createLayerStyle(document2) {
11168
+ const style = document2.createElement("style");
11169
+ style.textContent = `
11170
+ [${SOURCE_HIDDEN_ATTRIBUTE}='true'] {
11171
+ opacity: 0 !important;
11172
+ pointer-events: none !important;
11173
+ }
11174
+
11175
+ [data-dfwr-move-entry-id] {
11176
+ box-sizing: border-box;
11177
+ outline: 1px dashed rgba(215, 255, 95, 0.62);
11178
+ outline-offset: 2px;
11179
+ }
11180
+
11181
+ [data-dfwr-move-entry-id][data-dfwr-move-active='true'] {
11182
+ outline-color: #d7ff5f;
11183
+ outline-width: 2px;
11184
+ }
11185
+ `;
11186
+ return style;
11187
+ }
11188
+ function createLayerWrapper(document2, entryId, label, canvas) {
11189
+ const wrapper = document2.createElement("div");
11190
+ wrapper.dataset.dfwrMoveEntryId = entryId;
11191
+ wrapper.style.position = "absolute";
11192
+ wrapper.style.transformOrigin = "top left";
11193
+ wrapper.style.pointerEvents = "none";
11194
+ wrapper.style.willChange = "transform";
11195
+ canvas.setAttribute("aria-hidden", "true");
11196
+ canvas.style.display = "block";
11197
+ canvas.style.pointerEvents = "none";
11198
+ const clear = document2.createElement("button");
11199
+ clear.type = "button";
11200
+ clear.title = `Clear ${label} move`;
11201
+ clear.setAttribute("aria-label", `Clear ${label} move`);
11202
+ clear.setAttribute("data-dfwr-source-open-shortcut", "true");
11203
+ clear.style.position = "absolute";
11204
+ clear.style.top = "4px";
11205
+ clear.style.right = "4px";
11206
+ clear.style.width = "22px";
11207
+ clear.style.height = "22px";
11208
+ clear.style.display = "grid";
11209
+ clear.style.placeItems = "center";
11210
+ clear.style.padding = "0";
11211
+ clear.style.border = "1px solid rgba(255, 255, 255, 0.35)";
11212
+ clear.style.borderRadius = "50%";
11213
+ clear.style.background = "rgba(18, 23, 31, 0.88)";
11214
+ clear.style.color = "#edf3fb";
11215
+ clear.style.font = "16px/1 system-ui, sans-serif";
11216
+ clear.style.cursor = "pointer";
11217
+ clear.style.pointerEvents = "auto";
11218
+ const clearIcon = document2.createElement("span");
11219
+ clearIcon.textContent = "\xD7";
11220
+ clearIcon.style.transform = "translateY(-1px)";
11221
+ clear.appendChild(clearIcon);
11222
+ wrapper.append(canvas, clear);
11223
+ return wrapper;
11224
+ }
11225
+ function syncLayerPosition(wrapper, position, viewportScale) {
11226
+ wrapper.style.transform = `translate(${roundCss(position.x * viewportScale)}px, ${roundCss(position.y * viewportScale)}px)`;
11227
+ }
11228
+ function roundCss(value) {
11229
+ return Math.round(value * 1e3) / 1e3;
11230
+ }
11231
+
11023
11232
  // src/react-shell/hooks/use.review.section.outline.ts
11233
+ var EMPTY_DOM_ADJUSTMENT_POSITION = {
11234
+ x: 0,
11235
+ y: 0
11236
+ };
11024
11237
  var SOURCE_TREE_PANEL_CLOSE_DELAY_MS = 180;
11238
+ var getSectionDomAdjustmentKeyDelta = (event) => {
11239
+ const step = event.shiftKey ? 10 : 1;
11240
+ if (event.key === "ArrowLeft") return { x: -step };
11241
+ if (event.key === "ArrowRight") return { x: step };
11242
+ if (event.key === "ArrowUp") return { y: -step };
11243
+ if (event.key === "ArrowDown") return { y: step };
11244
+ return null;
11245
+ };
11246
+ var isDomAdjustmentEmpty = (position) => position.x === 0 && position.y === 0;
11247
+ var isEditableKeyTarget = (target) => {
11248
+ if (!(target instanceof HTMLElement)) return false;
11249
+ const tagName = target.tagName;
11250
+ return tagName === "INPUT" || tagName === "TEXTAREA" || tagName === "SELECT" || target.isContentEditable;
11251
+ };
11252
+ var COMPONENT_SELECTION_ACTION_SELECTOR = [
11253
+ "a",
11254
+ "button",
11255
+ "input",
11256
+ "select",
11257
+ "summary",
11258
+ "textarea",
11259
+ '[contenteditable="true"]',
11260
+ "[data-dfwr-move-entry-id]",
11261
+ '[role="button"]'
11262
+ ].join(", ");
11263
+ var getClosestElement = (target, selector) => {
11264
+ const element = target;
11265
+ return typeof element?.closest === "function" ? element.closest(selector) : null;
11266
+ };
11267
+ var findSectionOutlinePathForElement = (entries, element) => {
11268
+ let bestPath = null;
11269
+ const visit = (entry, path) => {
11270
+ const isMatch = entry.element === element || entry.element.contains(element);
11271
+ if (!isMatch) return;
11272
+ const nextPath = [...path, entry];
11273
+ bestPath = nextPath;
11274
+ entry.children.forEach((child) => visit(child, nextPath));
11275
+ };
11276
+ entries.forEach((entry) => visit(entry, []));
11277
+ return bestPath;
11278
+ };
11025
11279
  function useReviewSectionOutline({
11026
11280
  onClearSourceInspector,
11027
- onInitReviewKit
11281
+ onClearSourceSelection,
11282
+ onInitReviewKit,
11283
+ onSelectSourceElement
11028
11284
  }) {
11029
- const { sectionOutlineOptions, sourceOpenOptions } = useReviewShellConfig();
11285
+ const { reviewViewportPresets, sectionOutlineOptions, sourceOpenOptions } = useReviewShellConfig();
11030
11286
  const { controllerRef, frameScrollRef, iframeRef } = useReviewShellRefs();
11031
11287
  const { canWriteDom } = useReviewShellAdapterState();
11032
11288
  const storeApi = useReviewShellStoreApi();
11033
11289
  const isListVisible = useReviewShellStore((state) => state.isListVisible);
11034
11290
  const sidePanel = useReviewShellStore((state) => state.sidePanel);
11035
11291
  const target = useReviewShellStore((state) => state.target);
11292
+ const size = useReviewShellStore((state) => state.size);
11036
11293
  const targetFrameLoadVersion = useReviewShellStore(
11037
11294
  (state) => state.targetFrameLoadVersion
11038
11295
  );
11296
+ const sourceTreeFocusRequest = useReviewShellStore(
11297
+ (state) => state.sourceTreeFocusRequest
11298
+ );
11299
+ const mode = useReviewShellStore((state) => state.mode);
11039
11300
  const setMode = useReviewShellStore((state) => state.setMode);
11040
11301
  const showToast = useReviewToast();
11041
11302
  const isPanelVisible = isListVisible && sidePanel === "source";
@@ -11047,6 +11308,65 @@ function useReviewSectionOutline({
11047
11308
  );
11048
11309
  const [sectionOutlineMetaVisibility, setSectionOutlineMetaVisibility] = useState6(() => getStoredSourceTreeMetaVisibility());
11049
11310
  const [collapsedSectionOutlineIds, setCollapsedSectionOutlineIds] = useState6(() => /* @__PURE__ */ new Set());
11311
+ const [selectedSectionOutlineId, setSelectedSectionOutlineId] = useState6(null);
11312
+ const [activeDomAdjustmentEntryId, setActiveDomAdjustmentEntryId] = useState6(null);
11313
+ const [domAdjustmentByEntryId, setDomAdjustmentByEntryId] = useState6({});
11314
+ const handledSourceTreeFocusVersionRef = useRef5(0);
11315
+ const domAdjustmentManagerRef = useRef5(null);
11316
+ const domAdjustmentRequestVersionRef = useRef5(0);
11317
+ const clearSectionOutlineSelection = useCallback6(() => {
11318
+ const activeElement = document.activeElement;
11319
+ if (activeElement instanceof HTMLElement && activeElement.closest(".df-review-section-outline-entry-body")) {
11320
+ activeElement.blur();
11321
+ }
11322
+ setSelectedSectionOutlineId(null);
11323
+ onClearSourceSelection();
11324
+ }, [onClearSourceSelection]);
11325
+ const handleDomAdjustmentCleared = useCallback6((entryId) => {
11326
+ setActiveDomAdjustmentEntryId(
11327
+ (current) => current === entryId ? null : current
11328
+ );
11329
+ setDomAdjustmentByEntryId((current) => {
11330
+ if (!current[entryId]) return current;
11331
+ const next = { ...current };
11332
+ delete next[entryId];
11333
+ return next;
11334
+ });
11335
+ }, []);
11336
+ const getDomAdjustmentManager = useCallback6(() => {
11337
+ const frameDocument = iframeRef.current?.contentDocument;
11338
+ if (!frameDocument?.documentElement || !frameDocument.body) return null;
11339
+ const current = domAdjustmentManagerRef.current;
11340
+ if (current?.belongsTo(frameDocument)) return current;
11341
+ current?.destroy();
11342
+ const next = new DomAdjustmentLayerManager({
11343
+ document: frameDocument,
11344
+ onClear: handleDomAdjustmentCleared
11345
+ });
11346
+ domAdjustmentManagerRef.current = next;
11347
+ return next;
11348
+ }, [handleDomAdjustmentCleared, iframeRef]);
11349
+ const domAdjustmentViewportScale = useMemo5(
11350
+ () => getDraftViewportScale(
11351
+ { width: size.width, height: size.height },
11352
+ reviewViewportPresets
11353
+ ).scale,
11354
+ [reviewViewportPresets, size.height, size.width]
11355
+ );
11356
+ const clearActiveDomAdjustment = useCallback6(() => {
11357
+ setActiveDomAdjustmentEntryId(null);
11358
+ }, []);
11359
+ const clearDomAdjustments = useCallback6(() => {
11360
+ domAdjustmentRequestVersionRef.current += 1;
11361
+ domAdjustmentManagerRef.current?.destroy();
11362
+ domAdjustmentManagerRef.current = null;
11363
+ setActiveDomAdjustmentEntryId(null);
11364
+ setDomAdjustmentByEntryId({});
11365
+ }, []);
11366
+ const finishActiveDomAdjustment = useCallback6(() => {
11367
+ if (!activeDomAdjustmentEntryId) return;
11368
+ clearActiveDomAdjustment();
11369
+ }, [activeDomAdjustmentEntryId, clearActiveDomAdjustment]);
11050
11370
  const updateSectionOutlineFilter = useCallback6((nextFilter) => {
11051
11371
  setSectionOutlineFilter(nextFilter);
11052
11372
  writeStoredSourceTreeFilter(nextFilter);
@@ -11083,9 +11403,142 @@ function useReviewSectionOutline({
11083
11403
  }, [sectionOutlineTotalCount]);
11084
11404
  useEffect6(() => {
11085
11405
  onClearSourceInspector();
11406
+ onClearSourceSelection();
11086
11407
  setCollapsedSectionOutlineIds(/* @__PURE__ */ new Set());
11408
+ setSelectedSectionOutlineId(null);
11409
+ clearDomAdjustments();
11087
11410
  setSectionOutline(null);
11088
- }, [onClearSourceInspector, targetSrc]);
11411
+ }, [
11412
+ clearDomAdjustments,
11413
+ onClearSourceInspector,
11414
+ onClearSourceSelection,
11415
+ targetFrameLoadVersion,
11416
+ targetSrc
11417
+ ]);
11418
+ useEffect6(() => {
11419
+ if (!activeDomAdjustmentEntryId) return void 0;
11420
+ const handleKeyDown = (event) => {
11421
+ if (isEditableKeyTarget(event.target)) return;
11422
+ const delta = getSectionDomAdjustmentKeyDelta(event);
11423
+ if (!delta) return;
11424
+ const position = domAdjustmentManagerRef.current?.adjust(
11425
+ activeDomAdjustmentEntryId,
11426
+ delta,
11427
+ domAdjustmentViewportScale
11428
+ );
11429
+ if (!position) {
11430
+ clearActiveDomAdjustment();
11431
+ return;
11432
+ }
11433
+ setDomAdjustmentByEntryId((current) => ({
11434
+ ...current,
11435
+ [activeDomAdjustmentEntryId]: position
11436
+ }));
11437
+ event.preventDefault();
11438
+ event.stopPropagation();
11439
+ };
11440
+ window.addEventListener("keydown", handleKeyDown, true);
11441
+ return () => window.removeEventListener("keydown", handleKeyDown, true);
11442
+ }, [
11443
+ activeDomAdjustmentEntryId,
11444
+ clearActiveDomAdjustment,
11445
+ domAdjustmentViewportScale
11446
+ ]);
11447
+ useEffect6(() => {
11448
+ if (!activeDomAdjustmentEntryId) return void 0;
11449
+ const finishOnPointerDown = (event) => {
11450
+ if (event.target instanceof Element && event.target.closest(".df-review-section-outline-link.is-dom-adjust")) {
11451
+ return;
11452
+ }
11453
+ finishActiveDomAdjustment();
11454
+ };
11455
+ let frameDocument = null;
11456
+ try {
11457
+ frameDocument = iframeRef.current?.contentDocument ?? null;
11458
+ } catch {
11459
+ frameDocument = null;
11460
+ }
11461
+ window.addEventListener("pointerdown", finishOnPointerDown, true);
11462
+ frameDocument?.addEventListener(
11463
+ "pointerdown",
11464
+ finishOnPointerDown,
11465
+ true
11466
+ );
11467
+ return () => {
11468
+ window.removeEventListener("pointerdown", finishOnPointerDown, true);
11469
+ frameDocument?.removeEventListener(
11470
+ "pointerdown",
11471
+ finishOnPointerDown,
11472
+ true
11473
+ );
11474
+ };
11475
+ }, [
11476
+ activeDomAdjustmentEntryId,
11477
+ finishActiveDomAdjustment,
11478
+ iframeRef
11479
+ ]);
11480
+ useEffect6(() => {
11481
+ domAdjustmentManagerRef.current?.setActive(activeDomAdjustmentEntryId);
11482
+ }, [activeDomAdjustmentEntryId]);
11483
+ useEffect6(() => {
11484
+ if (!selectedSectionOutlineId || mode !== "idle" || activeDomAdjustmentEntryId) {
11485
+ return void 0;
11486
+ }
11487
+ let frameDocument = null;
11488
+ try {
11489
+ frameDocument = iframeRef.current?.contentDocument ?? null;
11490
+ } catch {
11491
+ frameDocument = null;
11492
+ }
11493
+ const clearOnFramePointerDown = (event) => {
11494
+ if (getClosestElement(event.target, COMPONENT_SELECTION_ACTION_SELECTOR)) {
11495
+ return;
11496
+ }
11497
+ clearSectionOutlineSelection();
11498
+ };
11499
+ const clearOnWorkspacePointerDown = (event) => {
11500
+ if (!getClosestElement(event.target, ".df-review-frame-scroll")) return;
11501
+ if (getClosestElement(event.target, COMPONENT_SELECTION_ACTION_SELECTOR)) {
11502
+ return;
11503
+ }
11504
+ clearSectionOutlineSelection();
11505
+ };
11506
+ const clearOnEscape = (event) => {
11507
+ if (event.key === "Escape") clearSectionOutlineSelection();
11508
+ };
11509
+ frameDocument?.addEventListener(
11510
+ "pointerdown",
11511
+ clearOnFramePointerDown,
11512
+ true
11513
+ );
11514
+ frameDocument?.addEventListener("keydown", clearOnEscape, true);
11515
+ window.addEventListener(
11516
+ "pointerdown",
11517
+ clearOnWorkspacePointerDown,
11518
+ true
11519
+ );
11520
+ window.addEventListener("keydown", clearOnEscape, true);
11521
+ return () => {
11522
+ frameDocument?.removeEventListener(
11523
+ "pointerdown",
11524
+ clearOnFramePointerDown,
11525
+ true
11526
+ );
11527
+ frameDocument?.removeEventListener("keydown", clearOnEscape, true);
11528
+ window.removeEventListener(
11529
+ "pointerdown",
11530
+ clearOnWorkspacePointerDown,
11531
+ true
11532
+ );
11533
+ window.removeEventListener("keydown", clearOnEscape, true);
11534
+ };
11535
+ }, [
11536
+ activeDomAdjustmentEntryId,
11537
+ clearSectionOutlineSelection,
11538
+ iframeRef,
11539
+ mode,
11540
+ selectedSectionOutlineId
11541
+ ]);
11089
11542
  const getCurrentSectionOutline = useCallback6(
11090
11543
  () => {
11091
11544
  let frameDocument = null;
@@ -11178,13 +11631,79 @@ function useReviewSectionOutline({
11178
11631
  });
11179
11632
  }, []);
11180
11633
  const scrollToSection = useCallback6((entry) => {
11181
- scrollElementInTarget(entry.element, "start");
11634
+ scrollElementInTarget(entry.element, "center");
11182
11635
  centerFrameScrollOnElement(
11183
11636
  frameScrollRef.current,
11184
11637
  iframeRef.current,
11185
11638
  entry.element
11186
11639
  );
11187
11640
  }, [frameScrollRef, iframeRef]);
11641
+ const selectSectionOutlinePath = useCallback6(
11642
+ (path) => {
11643
+ const entry = path[path.length - 1];
11644
+ if (!entry) return;
11645
+ setSelectedSectionOutlineId(entry.id);
11646
+ onSelectSourceElement(entry.element);
11647
+ setCollapsedSectionOutlineIds((current) => {
11648
+ const next = new Set(current);
11649
+ path.slice(0, -1).forEach((ancestor) => next.delete(ancestor.id));
11650
+ return next;
11651
+ });
11652
+ },
11653
+ [onSelectSourceElement]
11654
+ );
11655
+ const selectSectionOutlineEntry = useCallback6(
11656
+ (entry) => {
11657
+ finishActiveDomAdjustment();
11658
+ if (selectedSectionOutlineId === entry.id) {
11659
+ clearSectionOutlineSelection();
11660
+ return;
11661
+ }
11662
+ scrollToSection(entry);
11663
+ setSelectedSectionOutlineId(entry.id);
11664
+ onSelectSourceElement(entry.element);
11665
+ },
11666
+ [
11667
+ clearSectionOutlineSelection,
11668
+ finishActiveDomAdjustment,
11669
+ onSelectSourceElement,
11670
+ scrollToSection,
11671
+ selectedSectionOutlineId
11672
+ ]
11673
+ );
11674
+ useEffect6(() => {
11675
+ const request = sourceTreeFocusRequest;
11676
+ if (!request || handledSourceTreeFocusVersionRef.current === request.version || !isPanelVisible) {
11677
+ return;
11678
+ }
11679
+ const entries = sectionOutline ?? getCurrentSectionOutline();
11680
+ if (!entries) return;
11681
+ if (!sectionOutline) {
11682
+ setSectionOutline(entries);
11683
+ setCollapsedSectionOutlineIds(
11684
+ getDefaultCollapsedSectionOutlineIds(entries)
11685
+ );
11686
+ sectionOutlineCountRef.current = getSectionOutlineEntryCount(entries);
11687
+ }
11688
+ const path = findSectionOutlinePathForElement(entries, request.element);
11689
+ if (!path) {
11690
+ handledSourceTreeFocusVersionRef.current = request.version;
11691
+ showToast("Component not found");
11692
+ return;
11693
+ }
11694
+ handledSourceTreeFocusVersionRef.current = request.version;
11695
+ if (sectionOutlineFilter) updateSectionOutlineFilter("");
11696
+ selectSectionOutlinePath(path);
11697
+ }, [
11698
+ getCurrentSectionOutline,
11699
+ isPanelVisible,
11700
+ sectionOutline,
11701
+ sectionOutlineFilter,
11702
+ selectSectionOutlinePath,
11703
+ showToast,
11704
+ sourceTreeFocusRequest,
11705
+ updateSectionOutlineFilter
11706
+ ]);
11188
11707
  const openSectionSource = useCallback6(
11189
11708
  (entry) => {
11190
11709
  const didOpen = openSourceInEditor(entry.source, {
@@ -11223,9 +11742,12 @@ function useReviewSectionOutline({
11223
11742
  showToast("Component has no visible area here");
11224
11743
  return;
11225
11744
  }
11745
+ const position = domAdjustmentByEntryId[entry.id];
11746
+ setSelectedSectionOutlineId(entry.id);
11747
+ onSelectSourceElement(entry.element);
11748
+ clearActiveDomAdjustment();
11226
11749
  onClearSourceInspector();
11227
11750
  const state = storeApi.getState();
11228
- state.setSidePanel("qa");
11229
11751
  state.setIsListVisible(true);
11230
11752
  let targetWindow = null;
11231
11753
  try {
@@ -11250,6 +11772,9 @@ function useReviewSectionOutline({
11250
11772
  );
11251
11773
  await waitForFrame(targetWindow);
11252
11774
  await controller.startElementReview(entry.element);
11775
+ if (position && !isDomAdjustmentEmpty(position)) {
11776
+ controller.adjustElementSelection(position, { preview: false });
11777
+ }
11253
11778
  await waitForFrame(targetWindow);
11254
11779
  setMode(controller.getMode());
11255
11780
  }).catch(() => {
@@ -11259,15 +11784,95 @@ function useReviewSectionOutline({
11259
11784
  [
11260
11785
  canWriteDom,
11261
11786
  controllerRef,
11787
+ domAdjustmentByEntryId,
11262
11788
  frameScrollRef,
11263
11789
  iframeRef,
11264
11790
  onClearSourceInspector,
11265
11791
  onInitReviewKit,
11792
+ onSelectSourceElement,
11793
+ clearActiveDomAdjustment,
11266
11794
  setMode,
11267
11795
  showToast,
11268
11796
  storeApi
11269
11797
  ]
11270
11798
  );
11799
+ const startSectionDomAdjustment = useCallback6(
11800
+ (entry) => {
11801
+ if (!canWriteDom) {
11802
+ showToast("DOM select unavailable");
11803
+ return;
11804
+ }
11805
+ const rect = entry.element.getBoundingClientRect();
11806
+ if (rect.width <= 0 || rect.height <= 0) {
11807
+ showToast("Component has no visible area here");
11808
+ return;
11809
+ }
11810
+ finishActiveDomAdjustment();
11811
+ scrollToSection(entry);
11812
+ setSelectedSectionOutlineId(entry.id);
11813
+ onSelectSourceElement(entry.element);
11814
+ const requestVersion = domAdjustmentRequestVersionRef.current + 1;
11815
+ domAdjustmentRequestVersionRef.current = requestVersion;
11816
+ let targetWindow = null;
11817
+ try {
11818
+ targetWindow = entry.element.ownerDocument.defaultView ?? iframeRef.current?.contentWindow ?? null;
11819
+ } catch {
11820
+ targetWindow = null;
11821
+ }
11822
+ void waitForFrame(targetWindow).then(async () => {
11823
+ const position = domAdjustmentByEntryId[entry.id] ?? EMPTY_DOM_ADJUSTMENT_POSITION;
11824
+ const manager = getDomAdjustmentManager();
11825
+ if (!manager) {
11826
+ showToast("DOM move unavailable");
11827
+ return;
11828
+ }
11829
+ const didCreate = await manager.create(
11830
+ entry.id,
11831
+ entry.label,
11832
+ entry.element,
11833
+ position,
11834
+ domAdjustmentViewportScale
11835
+ );
11836
+ if (!didCreate) {
11837
+ showToast("DOM move unavailable");
11838
+ return;
11839
+ }
11840
+ setDomAdjustmentByEntryId((current) => ({
11841
+ ...current,
11842
+ [entry.id]: position
11843
+ }));
11844
+ if (domAdjustmentRequestVersionRef.current === requestVersion) {
11845
+ setActiveDomAdjustmentEntryId(entry.id);
11846
+ }
11847
+ }).catch(() => {
11848
+ clearActiveDomAdjustment();
11849
+ showToast("DOM move unavailable");
11850
+ });
11851
+ },
11852
+ [
11853
+ canWriteDom,
11854
+ clearActiveDomAdjustment,
11855
+ domAdjustmentByEntryId,
11856
+ domAdjustmentViewportScale,
11857
+ finishActiveDomAdjustment,
11858
+ getDomAdjustmentManager,
11859
+ iframeRef,
11860
+ onSelectSourceElement,
11861
+ scrollToSection,
11862
+ showToast
11863
+ ]
11864
+ );
11865
+ const clearSectionDomAdjustment = useCallback6(
11866
+ (entry) => {
11867
+ const manager = domAdjustmentManagerRef.current;
11868
+ if (manager) {
11869
+ manager.clear(entry.id);
11870
+ return;
11871
+ }
11872
+ handleDomAdjustmentCleared(entry.id);
11873
+ },
11874
+ [handleDomAdjustmentCleared]
11875
+ );
11271
11876
  return {
11272
11877
  canWriteDom,
11273
11878
  collapsedSectionOutlineIds,
@@ -11279,11 +11884,17 @@ function useReviewSectionOutline({
11279
11884
  openSectionSource,
11280
11885
  openSectionUsageSource,
11281
11886
  refreshCurrentSectionOutline,
11282
- scrollToSection,
11283
11887
  sectionOutline,
11284
11888
  sectionOutlineFilter,
11285
11889
  sectionOutlineMetaVisibility,
11286
11890
  sectionOutlineTotalCount,
11891
+ activeDomAdjustmentEntryId,
11892
+ domAdjustmentByEntryId,
11893
+ clearSectionDomAdjustment,
11894
+ clearSectionOutlineSelection,
11895
+ selectedSectionOutlineId,
11896
+ selectSectionOutlineEntry,
11897
+ startSectionDomAdjustment,
11287
11898
  startSectionDomReview,
11288
11899
  toggleSectionOutlineEntry,
11289
11900
  updateSectionOutlineFilter,
@@ -11292,7 +11903,9 @@ function useReviewSectionOutline({
11292
11903
  }
11293
11904
 
11294
11905
  // src/react-shell/review/section.outline.panel.tsx
11906
+ import React from "react";
11295
11907
  import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
11908
+ var ENTRY_ACTION_SELECTOR = 'a, button, input, select, textarea, [role="button"]';
11296
11909
  var SectionOutlinePanel = ({
11297
11910
  isPanelVisible,
11298
11911
  isFiltering,
@@ -11302,6 +11915,9 @@ var SectionOutlinePanel = ({
11302
11915
  filter,
11303
11916
  entries,
11304
11917
  collapsedIds,
11918
+ selectedEntryId,
11919
+ activeDomAdjustmentEntryId,
11920
+ domAdjustmentByEntryId,
11305
11921
  canWriteDom,
11306
11922
  isFontMetaVisible,
11307
11923
  isMediaMetaVisible,
@@ -11309,7 +11925,10 @@ var SectionOutlinePanel = ({
11309
11925
  onToggleMeta,
11310
11926
  onFilterChange,
11311
11927
  onToggleEntry,
11312
- onScrollToSection,
11928
+ onSelectEntry,
11929
+ onClearSelection,
11930
+ onClearDomAdjustment,
11931
+ onStartDomAdjustment,
11313
11932
  onOpenData,
11314
11933
  onOpenSource,
11315
11934
  onOpenUsageSource,
@@ -11317,6 +11936,13 @@ var SectionOutlinePanel = ({
11317
11936
  onHoverElement,
11318
11937
  onClearHover
11319
11938
  }) => {
11939
+ const selectedEntryRef = React.useRef(null);
11940
+ React.useEffect(() => {
11941
+ selectedEntryRef.current?.scrollIntoView({
11942
+ block: "nearest",
11943
+ inline: "nearest"
11944
+ });
11945
+ }, [selectedEntryId]);
11320
11946
  const renderMeta = (entry) => {
11321
11947
  const { metadata } = entry;
11322
11948
  const rows = [];
@@ -11446,6 +12072,17 @@ var SectionOutlinePanel = ({
11446
12072
  const renderEntry = (entry) => {
11447
12073
  const hasChildren = entry.children.length > 0;
11448
12074
  const isCollapsed = !isFiltering && collapsedIds.has(entry.id);
12075
+ const isSelected = selectedEntryId === entry.id;
12076
+ const isDomAdjusting = activeDomAdjustmentEntryId === entry.id;
12077
+ const hasDomAdjustment = Object.prototype.hasOwnProperty.call(
12078
+ domAdjustmentByEntryId,
12079
+ entry.id
12080
+ );
12081
+ const domAdjustmentPosition = domAdjustmentByEntryId[entry.id] ?? {
12082
+ x: 0,
12083
+ y: 0
12084
+ };
12085
+ const shouldShowDomAdjustment = isDomAdjusting || hasDomAdjustment;
11449
12086
  return /* @__PURE__ */ jsxs11(
11450
12087
  "div",
11451
12088
  {
@@ -11454,7 +12091,16 @@ var SectionOutlinePanel = ({
11454
12091
  /* @__PURE__ */ jsxs11(
11455
12092
  "div",
11456
12093
  {
11457
- className: "df-review-section-outline-entry-body",
12094
+ className: `df-review-section-outline-entry-body${isSelected ? " is-selected" : ""}`,
12095
+ onClick: (event) => {
12096
+ if (event.target instanceof Element && event.target.closest(ENTRY_ACTION_SELECTOR)) {
12097
+ return;
12098
+ }
12099
+ event.currentTarget.querySelector(
12100
+ ".df-review-section-outline-name"
12101
+ )?.focus();
12102
+ onSelectEntry(entry);
12103
+ },
11458
12104
  onMouseEnter: () => onHoverElement(entry.element),
11459
12105
  onMouseLeave: onClearHover,
11460
12106
  onMouseOver: () => onHoverElement(entry.element),
@@ -11470,7 +12116,8 @@ var SectionOutlinePanel = ({
11470
12116
  /* @__PURE__ */ jsxs11(
11471
12117
  "div",
11472
12118
  {
11473
- className: "df-review-section-outline-row",
12119
+ ref: isSelected ? selectedEntryRef : void 0,
12120
+ className: `df-review-section-outline-row${isSelected ? " is-selected" : ""}`,
11474
12121
  style: { paddingLeft: "6px" },
11475
12122
  children: [
11476
12123
  hasChildren ? /* @__PURE__ */ jsx15(
@@ -11491,77 +12138,120 @@ var SectionOutlinePanel = ({
11491
12138
  className: "df-review-section-outline-toggle is-placeholder"
11492
12139
  }
11493
12140
  ),
11494
- /* @__PURE__ */ jsx15(
11495
- "button",
11496
- {
11497
- className: "df-review-section-outline-name",
11498
- title: entry.filePath,
11499
- type: "button",
11500
- onClick: () => onScrollToSection(entry),
11501
- children: /* @__PURE__ */ jsx15("span", { children: entry.label })
11502
- }
11503
- ),
11504
- /* @__PURE__ */ jsxs11("span", { className: "df-review-section-outline-links", children: [
11505
- /* @__PURE__ */ jsx15(
11506
- "button",
11507
- {
11508
- "aria-label": `Open ${entry.label} data`,
11509
- className: "df-review-section-outline-link",
11510
- "data-review-tooltip": "Open data",
11511
- title: "Open data",
11512
- type: "button",
11513
- disabled: !entry.data?.file,
11514
- onClick: () => onOpenData(entry),
11515
- children: /* @__PURE__ */ jsx15(Database, { "aria-hidden": "true" })
11516
- }
11517
- ),
11518
- /* @__PURE__ */ jsx15(
11519
- "button",
11520
- {
11521
- "aria-label": `Open ${entry.label} source`,
11522
- className: "df-review-section-outline-link",
11523
- "data-review-tooltip": "Open source",
11524
- title: "Open source",
11525
- type: "button",
11526
- disabled: !entry.source?.file,
11527
- onClick: () => onOpenSource(entry),
11528
- children: /* @__PURE__ */ jsx15(CodeXml, { "aria-hidden": "true" })
11529
- }
11530
- ),
11531
- /* @__PURE__ */ jsx15(
11532
- "button",
11533
- {
11534
- "aria-label": `Open ${entry.label} usage`,
11535
- className: "df-review-section-outline-link",
11536
- "data-review-tooltip": "Open parent usage",
11537
- title: "Open parent usage",
11538
- type: "button",
11539
- disabled: !entry.metadata.usage?.source.file,
11540
- onClick: () => onOpenUsageSource(entry),
11541
- children: /* @__PURE__ */ jsx15(CornerUpRight, { "aria-hidden": "true" })
11542
- }
11543
- ),
11544
- /* @__PURE__ */ jsx15(
11545
- "span",
11546
- {
11547
- "aria-hidden": "true",
11548
- className: "df-review-section-outline-divider",
11549
- children: "|"
11550
- }
11551
- ),
11552
- /* @__PURE__ */ jsx15(
12141
+ /* @__PURE__ */ jsxs11("div", { className: "df-review-section-outline-main", children: [
12142
+ /* @__PURE__ */ jsx15("div", { className: "df-review-section-outline-title", children: /* @__PURE__ */ jsx15(
11553
12143
  "button",
11554
12144
  {
11555
- "aria-label": `Start DOM QA for ${entry.label}`,
11556
- className: "df-review-section-outline-link is-dom-select",
11557
- "data-review-tooltip": "DOM select",
11558
- title: "DOM select",
12145
+ className: "df-review-section-outline-name",
12146
+ title: entry.filePath,
11559
12147
  type: "button",
11560
- disabled: !canWriteDom,
11561
- onClick: () => onStartDomReview(entry),
11562
- children: /* @__PURE__ */ jsx15(SquareMousePointer, { "aria-hidden": "true" })
12148
+ onClick: () => onSelectEntry(entry),
12149
+ children: /* @__PURE__ */ jsx15("span", { children: entry.label })
11563
12150
  }
11564
- )
12151
+ ) }),
12152
+ /* @__PURE__ */ jsxs11("div", { className: "df-review-section-outline-actions", children: [
12153
+ /* @__PURE__ */ jsxs11("span", { className: "df-review-section-outline-action-group is-left", children: [
12154
+ /* @__PURE__ */ jsx15(
12155
+ "button",
12156
+ {
12157
+ "aria-label": `Move ${entry.label} DOM`,
12158
+ className: `df-review-section-outline-link is-dom-adjust${isDomAdjusting ? " is-active" : ""}`,
12159
+ "data-review-tooltip": isDomAdjusting ? "Moving DOM" : "Move DOM",
12160
+ title: isDomAdjusting ? "Moving DOM" : "Move DOM",
12161
+ type: "button",
12162
+ disabled: !canWriteDom,
12163
+ onClick: () => onStartDomAdjustment(entry),
12164
+ children: /* @__PURE__ */ jsx15(Move, { "aria-hidden": "true" })
12165
+ }
12166
+ ),
12167
+ shouldShowDomAdjustment ? /* @__PURE__ */ jsxs11(
12168
+ "span",
12169
+ {
12170
+ className: "df-review-section-outline-adjust-status",
12171
+ "aria-label": `DOM adjustment position x ${domAdjustmentPosition.x}, y ${domAdjustmentPosition.y}`,
12172
+ children: [
12173
+ /* @__PURE__ */ jsx15("code", { children: domAdjustmentPosition.x }),
12174
+ /* @__PURE__ */ jsx15("span", { "aria-hidden": "true", children: ":" }),
12175
+ /* @__PURE__ */ jsx15("code", { children: domAdjustmentPosition.y })
12176
+ ]
12177
+ }
12178
+ ) : null,
12179
+ shouldShowDomAdjustment ? /* @__PURE__ */ jsx15(
12180
+ "button",
12181
+ {
12182
+ "aria-label": `Clear ${entry.label} DOM adjustment`,
12183
+ className: "df-review-section-outline-link is-dom-reset",
12184
+ "data-review-tooltip": "Clear move",
12185
+ title: "Clear move",
12186
+ type: "button",
12187
+ onClick: () => onClearDomAdjustment(entry),
12188
+ children: /* @__PURE__ */ jsx15(RotateCcw, { "aria-hidden": "true" })
12189
+ }
12190
+ ) : null
12191
+ ] }),
12192
+ /* @__PURE__ */ jsxs11("span", { className: "df-review-section-outline-action-group is-right", children: [
12193
+ /* @__PURE__ */ jsx15(
12194
+ "button",
12195
+ {
12196
+ "aria-label": `Open ${entry.label} data`,
12197
+ className: "df-review-section-outline-link",
12198
+ "data-review-tooltip": "Open data",
12199
+ title: "Open data",
12200
+ type: "button",
12201
+ disabled: !entry.data?.file,
12202
+ onClick: () => onOpenData(entry),
12203
+ children: /* @__PURE__ */ jsx15(Database, { "aria-hidden": "true" })
12204
+ }
12205
+ ),
12206
+ /* @__PURE__ */ jsx15(
12207
+ "button",
12208
+ {
12209
+ "aria-label": `Open ${entry.label} source`,
12210
+ className: "df-review-section-outline-link",
12211
+ "data-review-tooltip": "Open source",
12212
+ title: "Open source",
12213
+ type: "button",
12214
+ disabled: !entry.source?.file,
12215
+ onClick: () => onOpenSource(entry),
12216
+ children: /* @__PURE__ */ jsx15(CodeXml, { "aria-hidden": "true" })
12217
+ }
12218
+ ),
12219
+ /* @__PURE__ */ jsx15(
12220
+ "button",
12221
+ {
12222
+ "aria-label": `Open ${entry.label} usage`,
12223
+ className: "df-review-section-outline-link",
12224
+ "data-review-tooltip": "Open parent usage",
12225
+ title: "Open parent usage",
12226
+ type: "button",
12227
+ disabled: !entry.metadata.usage?.source.file,
12228
+ onClick: () => onOpenUsageSource(entry),
12229
+ children: /* @__PURE__ */ jsx15(CornerUpRight, { "aria-hidden": "true" })
12230
+ }
12231
+ ),
12232
+ /* @__PURE__ */ jsx15(
12233
+ "span",
12234
+ {
12235
+ "aria-hidden": "true",
12236
+ className: "df-review-section-outline-divider",
12237
+ children: "|"
12238
+ }
12239
+ ),
12240
+ /* @__PURE__ */ jsx15(
12241
+ "button",
12242
+ {
12243
+ "aria-label": `Start DOM QA for ${entry.label}`,
12244
+ className: "df-review-section-outline-link is-dom-select",
12245
+ "data-review-tooltip": "DOM QA",
12246
+ title: "DOM QA",
12247
+ type: "button",
12248
+ disabled: !canWriteDom,
12249
+ onClick: () => onStartDomReview(entry),
12250
+ children: /* @__PURE__ */ jsx15(SquareMousePointer, { "aria-hidden": "true" })
12251
+ }
12252
+ )
12253
+ ] })
12254
+ ] })
11565
12255
  ] })
11566
12256
  ]
11567
12257
  }
@@ -11658,7 +12348,18 @@ var SectionOutlinePanel = ({
11658
12348
  )
11659
12349
  ] })
11660
12350
  ] }),
11661
- entries.length > 0 ? /* @__PURE__ */ jsx15("div", { className: "df-review-section-outline-list", children: entries.map(renderEntry) }) : /* @__PURE__ */ jsx15("div", { className: "df-review-section-outline-empty", children: isFiltering ? "No source matches" : "No sections found" })
12351
+ entries.length > 0 ? /* @__PURE__ */ jsx15(
12352
+ "div",
12353
+ {
12354
+ className: "df-review-section-outline-list",
12355
+ onPointerDown: (event) => {
12356
+ if (event.target instanceof Element && !event.target.closest(".df-review-section-outline-entry-body")) {
12357
+ onClearSelection();
12358
+ }
12359
+ },
12360
+ children: entries.map(renderEntry)
12361
+ }
12362
+ ) : /* @__PURE__ */ jsx15("div", { className: "df-review-section-outline-empty", children: isFiltering ? "No source matches" : "No sections found" })
11662
12363
  ] })
11663
12364
  }
11664
12365
  );
@@ -11667,16 +12368,19 @@ var SectionOutlinePanel = ({
11667
12368
  // src/react-shell/review/section.outline.container.tsx
11668
12369
  import { jsx as jsx16 } from "react/jsx-runtime";
11669
12370
  var SectionOutlineContainer = () => {
11670
- const { isSourceInspectorEnabled } = useReviewShellConfig();
11671
12371
  const {
11672
12372
  clearSourceInspector,
11673
12373
  clearSourceOutlineHover,
12374
+ clearSourceOutlineSelection,
11674
12375
  initReviewKit,
12376
+ selectSourceOutlineForElement,
11675
12377
  showSourceOutlineForElement
11676
12378
  } = useReviewShellActions();
11677
12379
  const {
12380
+ activeDomAdjustmentEntryId,
11678
12381
  canWriteDom,
11679
12382
  collapsedSectionOutlineIds,
12383
+ domAdjustmentByEntryId,
11680
12384
  filteredSectionOutline,
11681
12385
  filteredSectionOutlineCount,
11682
12386
  isPanelVisible,
@@ -11684,20 +12388,25 @@ var SectionOutlineContainer = () => {
11684
12388
  openSectionData,
11685
12389
  openSectionSource,
11686
12390
  openSectionUsageSource,
11687
- scrollToSection,
11688
12391
  sectionOutline,
11689
12392
  sectionOutlineFilter,
11690
12393
  sectionOutlineMetaVisibility,
11691
12394
  sectionOutlineTotalCount,
12395
+ selectedSectionOutlineId,
12396
+ selectSectionOutlineEntry,
12397
+ clearSectionOutlineSelection,
12398
+ clearSectionDomAdjustment,
12399
+ startSectionDomAdjustment,
11692
12400
  startSectionDomReview,
11693
12401
  toggleSectionOutlineEntry,
11694
12402
  updateSectionOutlineFilter,
11695
12403
  updateSectionOutlineMetaVisibility
11696
12404
  } = useReviewSectionOutline({
11697
12405
  onClearSourceInspector: clearSourceInspector,
11698
- onInitReviewKit: initReviewKit
12406
+ onClearSourceSelection: clearSourceOutlineSelection,
12407
+ onInitReviewKit: initReviewKit,
12408
+ onSelectSourceElement: selectSourceOutlineForElement
11699
12409
  });
11700
- if (!isSourceInspectorEnabled) return null;
11701
12410
  return /* @__PURE__ */ jsx16(
11702
12411
  SectionOutlinePanel,
11703
12412
  {
@@ -11709,6 +12418,9 @@ var SectionOutlineContainer = () => {
11709
12418
  filter: sectionOutlineFilter,
11710
12419
  entries: filteredSectionOutline,
11711
12420
  collapsedIds: collapsedSectionOutlineIds,
12421
+ selectedEntryId: selectedSectionOutlineId,
12422
+ activeDomAdjustmentEntryId,
12423
+ domAdjustmentByEntryId,
11712
12424
  canWriteDom,
11713
12425
  isFontMetaVisible: sectionOutlineMetaVisibility.font,
11714
12426
  isMediaMetaVisible: sectionOutlineMetaVisibility.media,
@@ -11716,7 +12428,10 @@ var SectionOutlineContainer = () => {
11716
12428
  onToggleMeta: updateSectionOutlineMetaVisibility,
11717
12429
  onFilterChange: updateSectionOutlineFilter,
11718
12430
  onToggleEntry: toggleSectionOutlineEntry,
11719
- onScrollToSection: scrollToSection,
12431
+ onSelectEntry: selectSectionOutlineEntry,
12432
+ onClearSelection: clearSectionOutlineSelection,
12433
+ onClearDomAdjustment: clearSectionDomAdjustment,
12434
+ onStartDomAdjustment: startSectionDomAdjustment,
11720
12435
  onOpenData: openSectionData,
11721
12436
  onOpenSource: openSectionSource,
11722
12437
  onOpenUsageSource: openSectionUsageSource,
@@ -11895,7 +12610,6 @@ var ReviewSideRail = ({
11895
12610
  isFigmaImageManagementEnabled,
11896
12611
  isFigmaImagesPanelVisible,
11897
12612
  isQaPanelVisible,
11898
- isSourceInspectorEnabled,
11899
12613
  isSourceTreePanelVisible,
11900
12614
  presenceSessionId,
11901
12615
  onOpenAbout,
@@ -11934,7 +12648,7 @@ var ReviewSideRail = ({
11934
12648
  children: /* @__PURE__ */ jsx20("span", { "aria-hidden": "true", children: /* @__PURE__ */ jsx20(ListChecks, {}) })
11935
12649
  }
11936
12650
  ),
11937
- isSourceInspectorEnabled && /* @__PURE__ */ jsx20(
12651
+ /* @__PURE__ */ jsx20(
11938
12652
  "button",
11939
12653
  {
11940
12654
  "aria-controls": "df-review-section-outline",
@@ -12017,7 +12731,6 @@ var ReviewSideRailContainer = () => {
12017
12731
  presenceSessionId
12018
12732
  } = useReviewPresenceState();
12019
12733
  const { isEnabled: isFigmaImageManagementEnabled } = useReviewFigmaImagesState();
12020
- const { isSourceInspectorEnabled } = useReviewShellConfig();
12021
12734
  const isListVisible = useReviewShellStore((state) => state.isListVisible);
12022
12735
  const sidePanel = useReviewShellStore((state) => state.sidePanel);
12023
12736
  return /* @__PURE__ */ jsx21(
@@ -12027,8 +12740,7 @@ var ReviewSideRailContainer = () => {
12027
12740
  isFigmaImageManagementEnabled,
12028
12741
  isFigmaImagesPanelVisible: isFigmaImageManagementEnabled && isListVisible && sidePanel === "figma-images",
12029
12742
  isQaPanelVisible: isListVisible && sidePanel === "qa",
12030
- isSourceInspectorEnabled,
12031
- isSourceTreePanelVisible: isSourceInspectorEnabled && isListVisible && sidePanel === "source",
12743
+ isSourceTreePanelVisible: isListVisible && sidePanel === "source",
12032
12744
  presenceSessionId,
12033
12745
  onOpenAbout: openAbout,
12034
12746
  onOpenInitialPrompt: openInitialPrompt,
@@ -12045,7 +12757,7 @@ import {
12045
12757
  useEffect as useEffect7,
12046
12758
  useRef as useRef6
12047
12759
  } from "react";
12048
- import { jsxs as jsxs16 } from "react/jsx-runtime";
12760
+ import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
12049
12761
  var getTooltipElements = (root) => Array.from(root.querySelectorAll("[data-review-tooltip]"));
12050
12762
  var restoreNativeTooltipTitles = (root) => {
12051
12763
  getTooltipElements(root).forEach((element) => {
@@ -12110,6 +12822,7 @@ var ReviewShellFrame = ({
12110
12822
  slots.qaPanel,
12111
12823
  slots.figmaImagesPanel,
12112
12824
  slots.sourceTreePanel,
12825
+ /* @__PURE__ */ jsx22("div", { className: "df-review-qa-draft-host" }),
12113
12826
  slots.targetFrame,
12114
12827
  slots.sourceInspector
12115
12828
  ]
@@ -12135,13 +12848,13 @@ var useReviewSettingsState = () => {
12135
12848
  };
12136
12849
 
12137
12850
  // src/react-shell/review/shell.frame.container.tsx
12138
- import { jsx as jsx22 } from "react/jsx-runtime";
12851
+ import { jsx as jsx23 } from "react/jsx-runtime";
12139
12852
  var ReviewShellFrameContainer = ({
12140
12853
  slots
12141
12854
  }) => {
12142
12855
  const { areTooltipsEnabled, effectiveReviewTheme } = useReviewSettingsState();
12143
12856
  const isListVisible = useReviewShellStore((state) => state.isListVisible);
12144
- return /* @__PURE__ */ jsx22(
12857
+ return /* @__PURE__ */ jsx23(
12145
12858
  ReviewShellFrame,
12146
12859
  {
12147
12860
  areTooltipsEnabled,
@@ -12156,7 +12869,7 @@ var ReviewShellFrameContainer = ({
12156
12869
  import { useCallback as useCallback8 } from "react";
12157
12870
 
12158
12871
  // src/react-shell/review/modal.tsx
12159
- import { jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
12872
+ import { jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
12160
12873
  var ReviewModal = ({
12161
12874
  ariaLabel,
12162
12875
  bodyClassName,
@@ -12176,7 +12889,7 @@ var ReviewModal = ({
12176
12889
  className: className ?? "df-review-prompt-modal",
12177
12890
  role: "dialog",
12178
12891
  children: [
12179
- /* @__PURE__ */ jsx23(
12892
+ /* @__PURE__ */ jsx24(
12180
12893
  "button",
12181
12894
  {
12182
12895
  "aria-label": `Close ${ariaLabel}`,
@@ -12192,21 +12905,21 @@ var ReviewModal = ({
12192
12905
  children: [
12193
12906
  /* @__PURE__ */ jsxs17("div", { className: "df-review-prompt-header", children: [
12194
12907
  /* @__PURE__ */ jsxs17("div", { children: [
12195
- /* @__PURE__ */ jsx23("strong", { id: titleId, children: title }),
12196
- description ? /* @__PURE__ */ jsx23("span", { children: description }) : null
12908
+ /* @__PURE__ */ jsx24("strong", { id: titleId, children: title }),
12909
+ description ? /* @__PURE__ */ jsx24("span", { children: description }) : null
12197
12910
  ] }),
12198
- /* @__PURE__ */ jsx23(
12911
+ /* @__PURE__ */ jsx24(
12199
12912
  "button",
12200
12913
  {
12201
12914
  "aria-label": `Close ${ariaLabel}`,
12202
12915
  className: "df-review-modal-close",
12203
12916
  type: "button",
12204
12917
  onClick: onClose,
12205
- children: /* @__PURE__ */ jsx23(X, { "aria-hidden": "true" })
12918
+ children: /* @__PURE__ */ jsx24(X, { "aria-hidden": "true" })
12206
12919
  }
12207
12920
  )
12208
12921
  ] }),
12209
- /* @__PURE__ */ jsx23("div", { className: bodyClassName ?? "df-review-prompt-body", children })
12922
+ /* @__PURE__ */ jsx24("div", { className: bodyClassName ?? "df-review-prompt-body", children })
12210
12923
  ]
12211
12924
  }
12212
12925
  )
@@ -12216,7 +12929,7 @@ var ReviewModal = ({
12216
12929
  };
12217
12930
 
12218
12931
  // src/react-shell/prompt/modal.tsx
12219
- import { jsx as jsx24, jsxs as jsxs18 } from "react/jsx-runtime";
12932
+ import { jsx as jsx25, jsxs as jsxs18 } from "react/jsx-runtime";
12220
12933
  var REVIEW_KIT_VERSION = "0.7.3";
12221
12934
  var SHORTCUT_SECTIONS = [
12222
12935
  {
@@ -12254,7 +12967,7 @@ var SHORTCUT_SECTIONS = [
12254
12967
  }
12255
12968
  ];
12256
12969
  var PromptModal = ({ onClose }) => {
12257
- return /* @__PURE__ */ jsx24(
12970
+ return /* @__PURE__ */ jsx25(
12258
12971
  ReviewModal,
12259
12972
  {
12260
12973
  ariaLabel: "Review help",
@@ -12263,11 +12976,11 @@ var PromptModal = ({ onClose }) => {
12263
12976
  dialogClassName: "df-review-about-dialog",
12264
12977
  title: "df-web-review-kit",
12265
12978
  onClose,
12266
- children: /* @__PURE__ */ jsx24("div", { className: "df-review-shortcut-groups", children: SHORTCUT_SECTIONS.map((section) => /* @__PURE__ */ jsxs18("section", { className: "df-review-shortcut-group", children: [
12267
- /* @__PURE__ */ jsx24("strong", { children: section.title }),
12268
- /* @__PURE__ */ jsx24("div", { className: "df-review-shortcut-list", children: section.items.map((item) => /* @__PURE__ */ jsxs18("div", { className: "df-review-shortcut-row", children: [
12269
- /* @__PURE__ */ jsx24("span", { className: "df-review-shortcut-keys", children: item.keys.map((key) => /* @__PURE__ */ jsx24("kbd", { children: key }, key)) }),
12270
- /* @__PURE__ */ jsx24("span", { children: item.label })
12979
+ children: /* @__PURE__ */ jsx25("div", { className: "df-review-shortcut-groups", children: SHORTCUT_SECTIONS.map((section) => /* @__PURE__ */ jsxs18("section", { className: "df-review-shortcut-group", children: [
12980
+ /* @__PURE__ */ jsx25("strong", { children: section.title }),
12981
+ /* @__PURE__ */ jsx25("div", { className: "df-review-shortcut-list", children: section.items.map((item) => /* @__PURE__ */ jsxs18("div", { className: "df-review-shortcut-row", children: [
12982
+ /* @__PURE__ */ jsx25("span", { className: "df-review-shortcut-keys", children: item.keys.map((key) => /* @__PURE__ */ jsx25("kbd", { children: key }, key)) }),
12983
+ /* @__PURE__ */ jsx25("span", { children: item.label })
12271
12984
  ] }, item.label)) })
12272
12985
  ] }, section.title)) })
12273
12986
  }
@@ -12275,14 +12988,14 @@ var PromptModal = ({ onClose }) => {
12275
12988
  };
12276
12989
 
12277
12990
  // src/react-shell/prompt/initial.modal.tsx
12278
- import { jsx as jsx25, jsxs as jsxs19 } from "react/jsx-runtime";
12991
+ import { jsx as jsx26, jsxs as jsxs19 } from "react/jsx-runtime";
12279
12992
  var InitialPromptModal = ({
12280
12993
  initialPromptText,
12281
12994
  copiedPromptKey,
12282
12995
  onClose,
12283
12996
  onCopyPrompt
12284
12997
  }) => {
12285
- return /* @__PURE__ */ jsx25(
12998
+ return /* @__PURE__ */ jsx26(
12286
12999
  ReviewModal,
12287
13000
  {
12288
13001
  ariaLabel: "Initial prompt",
@@ -12298,8 +13011,8 @@ var InitialPromptModal = ({
12298
13011
  children: [
12299
13012
  /* @__PURE__ */ jsxs19("div", { className: "df-review-prompt-block-header", children: [
12300
13013
  /* @__PURE__ */ jsxs19("div", { children: [
12301
- /* @__PURE__ */ jsx25("strong", { id: "df-review-initial-prompt-title", children: "QA handoff prompt" }),
12302
- /* @__PURE__ */ jsx25("span", { children: getPromptLengthLabel(initialPromptText) })
13014
+ /* @__PURE__ */ jsx26("strong", { id: "df-review-initial-prompt-title", children: "QA handoff prompt" }),
13015
+ /* @__PURE__ */ jsx26("span", { children: getPromptLengthLabel(initialPromptText) })
12303
13016
  ] }),
12304
13017
  /* @__PURE__ */ jsxs19(
12305
13018
  "button",
@@ -12308,13 +13021,13 @@ var InitialPromptModal = ({
12308
13021
  type: "button",
12309
13022
  onClick: () => onCopyPrompt(initialPromptText, "initial"),
12310
13023
  children: [
12311
- /* @__PURE__ */ jsx25(Copy, { "aria-hidden": "true" }),
13024
+ /* @__PURE__ */ jsx26(Copy, { "aria-hidden": "true" }),
12312
13025
  copiedPromptKey === "initial" ? "Copied" : "Copy"
12313
13026
  ]
12314
13027
  }
12315
13028
  )
12316
13029
  ] }),
12317
- /* @__PURE__ */ jsx25(
13030
+ /* @__PURE__ */ jsx26(
12318
13031
  "textarea",
12319
13032
  {
12320
13033
  readOnly: true,
@@ -12330,7 +13043,7 @@ var InitialPromptModal = ({
12330
13043
  };
12331
13044
 
12332
13045
  // src/react-shell/review/settings.modal.tsx
12333
- import { jsx as jsx26, jsxs as jsxs20 } from "react/jsx-runtime";
13046
+ import { jsx as jsx27, jsxs as jsxs20 } from "react/jsx-runtime";
12334
13047
  var getReviewThemeIcon = (theme) => {
12335
13048
  if (theme === "light") return Sun;
12336
13049
  if (theme === "system") return Monitor;
@@ -12362,7 +13075,7 @@ var ReviewSettingsModal = ({
12362
13075
  className: "df-review-settings-modal",
12363
13076
  role: "dialog",
12364
13077
  children: [
12365
- /* @__PURE__ */ jsx26(
13078
+ /* @__PURE__ */ jsx27(
12366
13079
  "button",
12367
13080
  {
12368
13081
  "aria-label": "Close settings",
@@ -12387,7 +13100,7 @@ var ReviewSettingsModal = ({
12387
13100
  children: [
12388
13101
  /* @__PURE__ */ jsxs20("div", { className: "df-review-settings-header", children: [
12389
13102
  /* @__PURE__ */ jsxs20("div", { className: "df-review-settings-title", children: [
12390
- /* @__PURE__ */ jsx26("strong", { children: "Settings" }),
13103
+ /* @__PURE__ */ jsx27("strong", { children: "Settings" }),
12391
13104
  /* @__PURE__ */ jsxs20("span", { children: [
12392
13105
  FIGMA_TOKEN_STORAGE_KEY,
12393
13106
  " / ",
@@ -12399,12 +13112,12 @@ var ReviewSettingsModal = ({
12399
13112
  REVIEW_TOOLTIP_STORAGE_KEY
12400
13113
  ] })
12401
13114
  ] }),
12402
- /* @__PURE__ */ jsx26("div", { className: "df-review-settings-header-actions", children: /* @__PURE__ */ jsx26("button", { "aria-label": "Close settings", type: "button", onClick: onClose, children: "x" }) })
13115
+ /* @__PURE__ */ jsx27("div", { className: "df-review-settings-header-actions", children: /* @__PURE__ */ jsx27("button", { "aria-label": "Close settings", type: "button", onClick: onClose, children: "x" }) })
12403
13116
  ] }),
12404
13117
  /* @__PURE__ */ jsxs20("div", { className: "df-review-settings-body", children: [
12405
13118
  /* @__PURE__ */ jsxs20("div", { className: "df-review-settings-row", children: [
12406
- /* @__PURE__ */ jsx26("span", { children: "Theme" }),
12407
- /* @__PURE__ */ jsx26("div", { className: "df-review-settings-theme-options", children: REVIEW_THEME_OPTIONS.map((option) => {
13119
+ /* @__PURE__ */ jsx27("span", { children: "Theme" }),
13120
+ /* @__PURE__ */ jsx27("div", { className: "df-review-settings-theme-options", children: REVIEW_THEME_OPTIONS.map((option) => {
12408
13121
  const ThemeIcon = getReviewThemeIcon(option.value);
12409
13122
  return /* @__PURE__ */ jsxs20(
12410
13123
  "button",
@@ -12419,8 +13132,8 @@ var ReviewSettingsModal = ({
12419
13132
  onClearStatus();
12420
13133
  },
12421
13134
  children: [
12422
- /* @__PURE__ */ jsx26(ThemeIcon, { "aria-hidden": "true" }),
12423
- /* @__PURE__ */ jsx26("span", { children: option.label })
13135
+ /* @__PURE__ */ jsx27(ThemeIcon, { "aria-hidden": "true" }),
13136
+ /* @__PURE__ */ jsx27("span", { children: option.label })
12424
13137
  ]
12425
13138
  },
12426
13139
  option.value
@@ -12428,9 +13141,9 @@ var ReviewSettingsModal = ({
12428
13141
  }) })
12429
13142
  ] }),
12430
13143
  /* @__PURE__ */ jsxs20("div", { className: "df-review-settings-row", children: [
12431
- /* @__PURE__ */ jsx26("span", { children: "Tooltips" }),
13144
+ /* @__PURE__ */ jsx27("span", { children: "Tooltips" }),
12432
13145
  /* @__PURE__ */ jsxs20("label", { className: "df-review-settings-toggle", children: [
12433
- /* @__PURE__ */ jsx26(
13146
+ /* @__PURE__ */ jsx27(
12434
13147
  "input",
12435
13148
  {
12436
13149
  "aria-label": "Show tooltips",
@@ -12442,13 +13155,13 @@ var ReviewSettingsModal = ({
12442
13155
  }
12443
13156
  }
12444
13157
  ),
12445
- /* @__PURE__ */ jsx26("span", { children: "Show" })
13158
+ /* @__PURE__ */ jsx27("span", { children: "Show" })
12446
13159
  ] })
12447
13160
  ] }),
12448
13161
  /* @__PURE__ */ jsxs20("div", { className: "df-review-settings-field", children: [
12449
13162
  /* @__PURE__ */ jsxs20("div", { className: "df-review-settings-label-row", children: [
12450
- /* @__PURE__ */ jsx26("label", { htmlFor: "df-review-figma-token", children: "Figma token" }),
12451
- /* @__PURE__ */ jsx26(
13163
+ /* @__PURE__ */ jsx27("label", { htmlFor: "df-review-figma-token", children: "Figma token" }),
13164
+ /* @__PURE__ */ jsx27(
12452
13165
  "button",
12453
13166
  {
12454
13167
  "aria-controls": FIGMA_TOKEN_GUIDE_ID,
@@ -12457,12 +13170,12 @@ var ReviewSettingsModal = ({
12457
13170
  className: `df-review-settings-help-button${isFigmaTokenGuideOpen ? " is-active" : ""}`,
12458
13171
  type: "button",
12459
13172
  onClick: onToggleFigmaTokenGuide,
12460
- children: /* @__PURE__ */ jsx26(CircleQuestionMark, { "aria-hidden": "true" })
13173
+ children: /* @__PURE__ */ jsx27(CircleQuestionMark, { "aria-hidden": "true" })
12461
13174
  }
12462
13175
  )
12463
13176
  ] }),
12464
13177
  /* @__PURE__ */ jsxs20("div", { className: "df-review-settings-token-input", children: [
12465
- /* @__PURE__ */ jsx26(
13178
+ /* @__PURE__ */ jsx27(
12466
13179
  "input",
12467
13180
  {
12468
13181
  id: "df-review-figma-token",
@@ -12485,34 +13198,34 @@ var ReviewSettingsModal = ({
12485
13198
  }
12486
13199
  }
12487
13200
  ),
12488
- /* @__PURE__ */ jsx26(
13201
+ /* @__PURE__ */ jsx27(
12489
13202
  "button",
12490
13203
  {
12491
13204
  "aria-label": isFigmaTokenVisible ? "Hide Figma token" : "Show Figma token",
12492
13205
  className: "df-review-settings-token-toggle",
12493
13206
  type: "button",
12494
13207
  onClick: onToggleFigmaTokenVisible,
12495
- children: isFigmaTokenVisible ? /* @__PURE__ */ jsx26(EyeOff, { "aria-hidden": "true" }) : /* @__PURE__ */ jsx26(Eye, { "aria-hidden": "true" })
13208
+ children: isFigmaTokenVisible ? /* @__PURE__ */ jsx27(EyeOff, { "aria-hidden": "true" }) : /* @__PURE__ */ jsx27(Eye, { "aria-hidden": "true" })
12496
13209
  }
12497
13210
  )
12498
13211
  ] }),
12499
- isFigmaTokenGuideOpen && /* @__PURE__ */ jsx26(
13212
+ isFigmaTokenGuideOpen && /* @__PURE__ */ jsx27(
12500
13213
  "div",
12501
13214
  {
12502
13215
  className: "df-review-settings-guide",
12503
13216
  id: FIGMA_TOKEN_GUIDE_ID,
12504
13217
  children: /* @__PURE__ */ jsxs20("ol", { children: [
12505
- /* @__PURE__ */ jsx26("li", { children: "Figma file browser\uC5D0\uC11C account menu\uB97C \uC5F4\uACE0 Settings\uB85C \uC774\uB3D9" }),
12506
- /* @__PURE__ */ jsx26("li", { children: "Security \uD0ED\uC758 Personal access tokens\uB85C \uC774\uB3D9" }),
12507
- /* @__PURE__ */ jsx26("li", { children: "Generate new token\uC5D0\uC11C \uC774\uB984\uACFC scope\uB97C \uC815\uD55C \uB4A4 \uC0DD\uC131" }),
12508
- /* @__PURE__ */ jsx26("li", { children: "\uC0DD\uC131\uB41C token\uC744 \uBCF5\uC0AC\uD574\uC11C \uC5EC\uAE30\uC5D0 \uBD99\uC5EC\uB123\uAE30" })
13218
+ /* @__PURE__ */ jsx27("li", { children: "Figma file browser\uC5D0\uC11C account menu\uB97C \uC5F4\uACE0 Settings\uB85C \uC774\uB3D9" }),
13219
+ /* @__PURE__ */ jsx27("li", { children: "Security \uD0ED\uC758 Personal access tokens\uB85C \uC774\uB3D9" }),
13220
+ /* @__PURE__ */ jsx27("li", { children: "Generate new token\uC5D0\uC11C \uC774\uB984\uACFC scope\uB97C \uC815\uD55C \uB4A4 \uC0DD\uC131" }),
13221
+ /* @__PURE__ */ jsx27("li", { children: "\uC0DD\uC131\uB41C token\uC744 \uBCF5\uC0AC\uD574\uC11C \uC5EC\uAE30\uC5D0 \uBD99\uC5EC\uB123\uAE30" })
12509
13222
  ] })
12510
13223
  }
12511
13224
  )
12512
13225
  ] }),
12513
13226
  /* @__PURE__ */ jsxs20("label", { className: "df-review-settings-field", children: [
12514
- /* @__PURE__ */ jsx26("span", { children: "User ID" }),
12515
- /* @__PURE__ */ jsx26("div", { className: "df-review-settings-text-input", children: /* @__PURE__ */ jsx26(
13227
+ /* @__PURE__ */ jsx27("span", { children: "User ID" }),
13228
+ /* @__PURE__ */ jsx27("div", { className: "df-review-settings-text-input", children: /* @__PURE__ */ jsx27(
12516
13229
  "input",
12517
13230
  {
12518
13231
  "aria-label": "Review user ID",
@@ -12527,9 +13240,9 @@ var ReviewSettingsModal = ({
12527
13240
  }
12528
13241
  ) })
12529
13242
  ] }),
12530
- figmaSettingsStatus && /* @__PURE__ */ jsx26("p", { className: "df-review-settings-status", children: figmaSettingsStatus }),
13243
+ figmaSettingsStatus && /* @__PURE__ */ jsx27("p", { className: "df-review-settings-status", children: figmaSettingsStatus }),
12531
13244
  /* @__PURE__ */ jsxs20("div", { className: "df-review-settings-actions", children: [
12532
- /* @__PURE__ */ jsx26(
13245
+ /* @__PURE__ */ jsx27(
12533
13246
  "button",
12534
13247
  {
12535
13248
  type: "button",
@@ -12542,9 +13255,9 @@ var ReviewSettingsModal = ({
12542
13255
  children: "Clear"
12543
13256
  }
12544
13257
  ),
12545
- /* @__PURE__ */ jsx26("span", {}),
12546
- /* @__PURE__ */ jsx26("button", { type: "button", onClick: onClose, children: "Cancel" }),
12547
- /* @__PURE__ */ jsx26("button", { type: "submit", children: "Save" })
13258
+ /* @__PURE__ */ jsx27("span", {}),
13259
+ /* @__PURE__ */ jsx27("button", { type: "button", onClick: onClose, children: "Cancel" }),
13260
+ /* @__PURE__ */ jsx27("button", { type: "submit", children: "Save" })
12548
13261
  ] })
12549
13262
  ] })
12550
13263
  ]
@@ -12810,7 +13523,7 @@ function sitemapNodeMatchesSearch(node, searchQuery, getPageTarget) {
12810
13523
  }
12811
13524
 
12812
13525
  // src/react-shell/sitemap/modal.tsx
12813
- import { Fragment as Fragment2, jsx as jsx27, jsxs as jsxs21 } from "react/jsx-runtime";
13526
+ import { Fragment as Fragment2, jsx as jsx28, jsxs as jsxs21 } from "react/jsx-runtime";
12814
13527
  var getNextSortDirection = (current, key) => {
12815
13528
  if (current.key !== key) return key === "page" ? "asc" : "desc";
12816
13529
  return current.direction === "desc" ? "asc" : "desc";
@@ -12909,7 +13622,7 @@ var SitemapModal = ({
12909
13622
  className: "df-review-sitemap-modal",
12910
13623
  role: "dialog",
12911
13624
  children: [
12912
- /* @__PURE__ */ jsx27(
13625
+ /* @__PURE__ */ jsx28(
12913
13626
  "button",
12914
13627
  {
12915
13628
  "aria-label": "Close sitemap",
@@ -12921,7 +13634,7 @@ var SitemapModal = ({
12921
13634
  /* @__PURE__ */ jsxs21("div", { className: "df-review-sitemap-dialog", children: [
12922
13635
  /* @__PURE__ */ jsxs21("div", { className: "df-review-sitemap-header", children: [
12923
13636
  /* @__PURE__ */ jsxs21("div", { children: [
12924
- /* @__PURE__ */ jsx27("strong", { children: "Sitemap" }),
13637
+ /* @__PURE__ */ jsx28("strong", { children: "Sitemap" }),
12925
13638
  /* @__PURE__ */ jsxs21("span", { children: [
12926
13639
  pages.length,
12927
13640
  " pages \xB7 ",
@@ -12934,12 +13647,12 @@ var SitemapModal = ({
12934
13647
  " hold"
12935
13648
  ] })
12936
13649
  ] }),
12937
- /* @__PURE__ */ jsx27("button", { "aria-label": "Close sitemap", type: "button", onClick: onClose, children: "x" })
13650
+ /* @__PURE__ */ jsx28("button", { "aria-label": "Close sitemap", type: "button", onClick: onClose, children: "x" })
12938
13651
  ] }),
12939
13652
  /* @__PURE__ */ jsxs21("div", { className: "df-review-sitemap-controls", children: [
12940
13653
  /* @__PURE__ */ jsxs21("label", { className: "df-review-sitemap-search", children: [
12941
- /* @__PURE__ */ jsx27(Search, { "aria-hidden": "true" }),
12942
- /* @__PURE__ */ jsx27(
13654
+ /* @__PURE__ */ jsx28(Search, { "aria-hidden": "true" }),
13655
+ /* @__PURE__ */ jsx28(
12943
13656
  "input",
12944
13657
  {
12945
13658
  "aria-label": "Search sitemap",
@@ -12951,20 +13664,20 @@ var SitemapModal = ({
12951
13664
  }
12952
13665
  )
12953
13666
  ] }),
12954
- trimmedSearchQuery && /* @__PURE__ */ jsx27(
13667
+ trimmedSearchQuery && /* @__PURE__ */ jsx28(
12955
13668
  "button",
12956
13669
  {
12957
13670
  "aria-label": "Clear sitemap search",
12958
13671
  className: "df-review-sitemap-search-clear",
12959
13672
  type: "button",
12960
13673
  onClick: () => setSearchQuery(""),
12961
- children: /* @__PURE__ */ jsx27(X, { "aria-hidden": "true" })
13674
+ children: /* @__PURE__ */ jsx28(X, { "aria-hidden": "true" })
12962
13675
  }
12963
13676
  ),
12964
- /* @__PURE__ */ jsx27("span", { className: "df-review-sitemap-search-count", children: trimmedSearchQuery ? `${matchingPageCount} matches` : `${pages.length} pages` })
13677
+ /* @__PURE__ */ jsx28("span", { className: "df-review-sitemap-search-count", children: trimmedSearchQuery ? `${matchingPageCount} matches` : `${pages.length} pages` })
12965
13678
  ] }),
12966
13679
  /* @__PURE__ */ jsxs21("div", { className: "df-review-sitemap-list", style: gridStyle, children: [
12967
- /* @__PURE__ */ jsx27("div", { className: "df-review-sitemap-table-head", role: "row", children: sortHeaders.map((header) => /* @__PURE__ */ jsxs21(
13680
+ /* @__PURE__ */ jsx28("div", { className: "df-review-sitemap-table-head", role: "row", children: sortHeaders.map((header) => /* @__PURE__ */ jsxs21(
12968
13681
  "button",
12969
13682
  {
12970
13683
  "aria-label": `Sort sitemap by ${header.title ?? header.label}`,
@@ -12977,7 +13690,7 @@ var SitemapModal = ({
12977
13690
  type: "button",
12978
13691
  onClick: () => setSortKey(header.key),
12979
13692
  children: [
12980
- /* @__PURE__ */ jsx27(
13693
+ /* @__PURE__ */ jsx28(
12981
13694
  "span",
12982
13695
  {
12983
13696
  "aria-hidden": "true",
@@ -12985,7 +13698,7 @@ var SitemapModal = ({
12985
13698
  children: getSortIndicator(sort, header.key)
12986
13699
  }
12987
13700
  ),
12988
- /* @__PURE__ */ jsx27("span", { className: "df-review-sitemap-sort-label", children: header.label })
13701
+ /* @__PURE__ */ jsx28("span", { className: "df-review-sitemap-sort-label", children: header.label })
12989
13702
  ]
12990
13703
  },
12991
13704
  header.key
@@ -13000,7 +13713,7 @@ var SitemapModal = ({
13000
13713
  row.isActive ? "is-active" : "",
13001
13714
  row.isPage ? "is-clickable" : ""
13002
13715
  ].filter(Boolean).join(" ");
13003
- const rowContent = /* @__PURE__ */ jsx27(
13716
+ const rowContent = /* @__PURE__ */ jsx28(
13004
13717
  SitemapRowContent,
13005
13718
  {
13006
13719
  depth: row.depth,
@@ -13013,7 +13726,7 @@ var SitemapModal = ({
13013
13726
  onToggleFolder: () => toggleFolder(row.href)
13014
13727
  }
13015
13728
  );
13016
- return /* @__PURE__ */ jsx27(
13729
+ return /* @__PURE__ */ jsx28(
13017
13730
  "div",
13018
13731
  {
13019
13732
  "aria-label": row.isPage ? `${row.href} / ${row.qaCount.status.todo} todo / ${row.qaCount.status.review} review / ${row.qaCount.status.hold} hold / ${row.users.length} online` : `${row.href} group / ${row.qaCount.status.todo} todo / ${row.qaCount.status.review} review / ${row.qaCount.status.hold} hold / ${row.users.length} online`,
@@ -13032,15 +13745,15 @@ var SitemapModal = ({
13032
13745
  row.href
13033
13746
  );
13034
13747
  }),
13035
- sitemapRows.length === 0 && /* @__PURE__ */ jsx27("div", { className: "df-review-sitemap-empty", role: "status", children: "No matching pages" }),
13036
- /* @__PURE__ */ jsx27(
13748
+ sitemapRows.length === 0 && /* @__PURE__ */ jsx28("div", { className: "df-review-sitemap-empty", role: "status", children: "No matching pages" }),
13749
+ /* @__PURE__ */ jsx28(
13037
13750
  "button",
13038
13751
  {
13039
13752
  "aria-label": `All QA / ${allQaCount.status.todo} todo / ${allQaCount.status.review} review / ${allQaCount.status.hold} hold`,
13040
13753
  className: `df-review-sitemap-row is-summary${isAllQaVisible ? " is-active" : ""}`,
13041
13754
  type: "button",
13042
13755
  onClick: onSelectAllQa,
13043
- children: /* @__PURE__ */ jsx27(
13756
+ children: /* @__PURE__ */ jsx28(
13044
13757
  SitemapRowContent,
13045
13758
  {
13046
13759
  depth: 0,
@@ -13076,7 +13789,7 @@ var SitemapRowContent = ({
13076
13789
  className: "df-review-sitemap-path",
13077
13790
  style: { "--df-review-sitemap-depth": depth },
13078
13791
  children: [
13079
- hasChildren ? /* @__PURE__ */ jsx27(
13792
+ hasChildren ? /* @__PURE__ */ jsx28(
13080
13793
  "button",
13081
13794
  {
13082
13795
  "aria-expanded": isExpanded,
@@ -13087,17 +13800,17 @@ var SitemapRowContent = ({
13087
13800
  event.stopPropagation();
13088
13801
  onToggleFolder?.();
13089
13802
  },
13090
- children: isExpanded ? /* @__PURE__ */ jsx27(ChevronDown, { "aria-hidden": "true" }) : /* @__PURE__ */ jsx27(ChevronRight, { "aria-hidden": "true" })
13803
+ children: isExpanded ? /* @__PURE__ */ jsx28(ChevronDown, { "aria-hidden": "true" }) : /* @__PURE__ */ jsx28(ChevronRight, { "aria-hidden": "true" })
13091
13804
  }
13092
- ) : /* @__PURE__ */ jsx27("span", { className: "df-review-sitemap-tree-spacer", "aria-hidden": "true" }),
13093
- isPage ? /* @__PURE__ */ jsx27("span", { className: "df-review-sitemap-page-label", children: label }) : /* @__PURE__ */ jsx27("span", { className: "df-review-sitemap-label", children: label })
13805
+ ) : /* @__PURE__ */ jsx28("span", { className: "df-review-sitemap-tree-spacer", "aria-hidden": "true" }),
13806
+ isPage ? /* @__PURE__ */ jsx28("span", { className: "df-review-sitemap-page-label", children: label }) : /* @__PURE__ */ jsx28("span", { className: "df-review-sitemap-label", children: label })
13094
13807
  ]
13095
13808
  }
13096
13809
  ),
13097
- /* @__PURE__ */ jsx27("span", { className: getCountCellClassName("todo", qaCount.status.todo), children: /* @__PURE__ */ jsx27("strong", { children: qaCount.status.todo }) }),
13098
- /* @__PURE__ */ jsx27("span", { className: getCountCellClassName("review", qaCount.status.review), children: qaCount.status.review }),
13099
- /* @__PURE__ */ jsx27("span", { className: getCountCellClassName("hold", qaCount.status.hold), children: qaCount.status.hold }),
13100
- /* @__PURE__ */ jsx27("span", { className: "df-review-sitemap-cell is-online", children: users.length > 0 ? /* @__PURE__ */ jsx27("span", { className: "df-review-sitemap-users", children: users.map((user) => /* @__PURE__ */ jsx27(
13810
+ /* @__PURE__ */ jsx28("span", { className: getCountCellClassName("todo", qaCount.status.todo), children: /* @__PURE__ */ jsx28("strong", { children: qaCount.status.todo }) }),
13811
+ /* @__PURE__ */ jsx28("span", { className: getCountCellClassName("review", qaCount.status.review), children: qaCount.status.review }),
13812
+ /* @__PURE__ */ jsx28("span", { className: getCountCellClassName("hold", qaCount.status.hold), children: qaCount.status.hold }),
13813
+ /* @__PURE__ */ jsx28("span", { className: "df-review-sitemap-cell is-online", children: users.length > 0 ? /* @__PURE__ */ jsx28("span", { className: "df-review-sitemap-users", children: users.map((user) => /* @__PURE__ */ jsx28(
13101
13814
  "span",
13102
13815
  {
13103
13816
  className: "df-review-sitemap-user",
@@ -13265,7 +13978,7 @@ var useReviewShellData = () => {
13265
13978
  };
13266
13979
 
13267
13980
  // src/react-shell/review/shell.modals.container.tsx
13268
- import { Fragment as Fragment3, jsx as jsx28, jsxs as jsxs22 } from "react/jsx-runtime";
13981
+ import { Fragment as Fragment3, jsx as jsx29, jsxs as jsxs22 } from "react/jsx-runtime";
13269
13982
  var ReviewShellModalsContainer = () => {
13270
13983
  const { initialPrompt, pages } = useReviewShellConfig();
13271
13984
  const {
@@ -13333,7 +14046,7 @@ var ReviewShellModalsContainer = () => {
13333
14046
  [setCopiedPromptKey, showToast]
13334
14047
  );
13335
14048
  return /* @__PURE__ */ jsxs22(Fragment3, { children: [
13336
- isSitemapOpen && /* @__PURE__ */ jsx28(
14049
+ isSitemapOpen && /* @__PURE__ */ jsx29(
13337
14050
  SitemapModal,
13338
14051
  {
13339
14052
  activeRoute,
@@ -13348,7 +14061,7 @@ var ReviewShellModalsContainer = () => {
13348
14061
  onSelectPage: selectPage
13349
14062
  }
13350
14063
  ),
13351
- isFigmaSettingsOpen && /* @__PURE__ */ jsx28(
14064
+ isFigmaSettingsOpen && /* @__PURE__ */ jsx29(
13352
14065
  ReviewSettingsModal,
13353
14066
  {
13354
14067
  areTooltipsEnabledDraft,
@@ -13369,8 +14082,8 @@ var ReviewShellModalsContainer = () => {
13369
14082
  onToggleFigmaTokenVisible: () => setIsFigmaTokenVisible((current) => !current)
13370
14083
  }
13371
14084
  ),
13372
- isInitialPromptOpen && /* @__PURE__ */ jsx28(PromptModal, { onClose: () => setIsInitialPromptOpen(false) }),
13373
- isInitialPromptScriptOpen && /* @__PURE__ */ jsx28(
14085
+ isInitialPromptOpen && /* @__PURE__ */ jsx29(PromptModal, { onClose: () => setIsInitialPromptOpen(false) }),
14086
+ isInitialPromptScriptOpen && /* @__PURE__ */ jsx29(
13374
14087
  InitialPromptModal,
13375
14088
  {
13376
14089
  copiedPromptKey,
@@ -13434,7 +14147,7 @@ var useReviewSourceInspectorState = () => {
13434
14147
  };
13435
14148
 
13436
14149
  // src/react-shell/review/shell.providers.tsx
13437
- import { jsx as jsx29 } from "react/jsx-runtime";
14150
+ import { jsx as jsx30 } from "react/jsx-runtime";
13438
14151
  var ReviewShellProviders = ({
13439
14152
  actions,
13440
14153
  children,
@@ -13444,100 +14157,52 @@ var ReviewShellProviders = ({
13444
14157
  ruler,
13445
14158
  settings,
13446
14159
  sourceInspector
13447
- }) => /* @__PURE__ */ jsx29(ReviewShellActionsProvider, { value: actions, children: /* @__PURE__ */ jsx29(ReviewRulerProvider, { value: ruler, children: /* @__PURE__ */ jsx29(ReviewFigmaImagesProvider, { value: figmaImages, children: /* @__PURE__ */ jsx29(ReviewSourceInspectorProvider, { value: sourceInspector, children: /* @__PURE__ */ jsx29(ReviewSettingsProvider, { value: settings, children: /* @__PURE__ */ jsx29(ReviewPresenceProvider, { value: presence, children: /* @__PURE__ */ jsx29(ReviewFigmaOverlayProvider, { value: figmaOverlay, children }) }) }) }) }) }) });
14160
+ }) => /* @__PURE__ */ jsx30(ReviewShellActionsProvider, { value: actions, children: /* @__PURE__ */ jsx30(ReviewRulerProvider, { value: ruler, children: /* @__PURE__ */ jsx30(ReviewFigmaImagesProvider, { value: figmaImages, children: /* @__PURE__ */ jsx30(ReviewSourceInspectorProvider, { value: sourceInspector, children: /* @__PURE__ */ jsx30(ReviewSettingsProvider, { value: settings, children: /* @__PURE__ */ jsx30(ReviewPresenceProvider, { value: presence, children: /* @__PURE__ */ jsx30(ReviewFigmaOverlayProvider, { value: figmaOverlay, children }) }) }) }) }) }) });
13448
14161
 
13449
14162
  // src/react-shell/review/source.inspector.overlay.tsx
13450
- import { Fragment as Fragment4, jsx as jsx30, jsxs as jsxs23 } from "react/jsx-runtime";
14163
+ import { Fragment as Fragment4, jsx as jsx31, jsxs as jsxs23 } from "react/jsx-runtime";
13451
14164
  var SourceInspectorOverlay = ({
13452
- state,
13453
- interactionRef,
13454
- onClear,
13455
- onOpenCandidate
14165
+ componentSelectionState,
14166
+ state
13456
14167
  }) => {
13457
- if (!state) return null;
14168
+ const hoverState = state?.targetElement === componentSelectionState?.targetElement ? null : state;
13458
14169
  return /* @__PURE__ */ jsxs23(Fragment4, { children: [
13459
- /* @__PURE__ */ jsx30(
14170
+ componentSelectionState ? /* @__PURE__ */ jsx31(
13460
14171
  "div",
13461
14172
  {
13462
- className: `df-review-source-outline${state.isPinned ? " is-pinned" : ""}`,
14173
+ className: "df-review-source-outline is-component-selection",
13463
14174
  style: {
13464
- height: `${state.rect.height}px`,
13465
- left: `${state.rect.left}px`,
13466
- top: `${state.rect.top}px`,
13467
- width: `${state.rect.width}px`
14175
+ height: `${componentSelectionState.rect.height}px`,
14176
+ left: `${componentSelectionState.rect.left}px`,
14177
+ top: `${componentSelectionState.rect.top}px`,
14178
+ width: `${componentSelectionState.rect.width}px`
13468
14179
  }
13469
14180
  }
13470
- ),
13471
- state.candidates.length > 0 && /* @__PURE__ */ jsxs23(
14181
+ ) : null,
14182
+ hoverState ? /* @__PURE__ */ jsx31(
13472
14183
  "div",
13473
14184
  {
13474
- className: `df-review-source-popover${state.isPinned ? " is-pinned" : ""}`,
14185
+ className: "df-review-source-outline is-hover",
13475
14186
  style: {
13476
- left: state.panelRight === null ? `${state.panelLeft}px` : void 0,
13477
- maxWidth: `${state.panelMaxWidth}px`,
13478
- right: state.panelRight === null ? void 0 : `${state.panelRight}px`,
13479
- top: `${state.panelTop}px`
13480
- },
13481
- onPointerDown: () => {
13482
- interactionRef.current = true;
13483
- },
13484
- onPointerEnter: () => {
13485
- interactionRef.current = true;
13486
- },
13487
- onPointerLeave: () => {
13488
- interactionRef.current = false;
13489
- },
13490
- onClick: (event) => event.stopPropagation(),
13491
- children: [
13492
- /* @__PURE__ */ jsx30("div", { className: "df-review-source-popover-close", children: /* @__PURE__ */ jsx30(
13493
- "button",
13494
- {
13495
- "aria-label": "Close source candidates",
13496
- type: "button",
13497
- onClick: onClear,
13498
- children: "\xD7"
13499
- }
13500
- ) }),
13501
- /* @__PURE__ */ jsx30("div", { className: "df-review-source-candidate-list", children: state.candidates.map((candidate) => /* @__PURE__ */ jsx30(
13502
- "button",
13503
- {
13504
- className: `df-review-source-candidate is-${candidate.kind}`,
13505
- type: "button",
13506
- onClick: (event) => {
13507
- event.preventDefault();
13508
- event.stopPropagation();
13509
- onOpenCandidate(candidate);
13510
- },
13511
- children: /* @__PURE__ */ jsxs23("span", { className: "df-review-source-candidate-main", children: [
13512
- /* @__PURE__ */ jsx30("strong", { children: candidate.label }),
13513
- /* @__PURE__ */ jsx30("span", { children: candidate.filePath }),
13514
- /* @__PURE__ */ jsx30("small", { children: [candidate.positionLabel || "-:-", candidate.detail].filter(Boolean).join(" \xB7 ") })
13515
- ] })
13516
- },
13517
- candidate.id
13518
- )) })
13519
- ]
14187
+ height: `${hoverState.rect.height}px`,
14188
+ left: `${hoverState.rect.left}px`,
14189
+ top: `${hoverState.rect.top}px`,
14190
+ width: `${hoverState.rect.width}px`
14191
+ }
13520
14192
  }
13521
- )
14193
+ ) : null
13522
14194
  ] });
13523
14195
  };
13524
14196
 
13525
14197
  // src/react-shell/review/source.inspector.overlay.container.tsx
13526
- import { jsx as jsx31 } from "react/jsx-runtime";
14198
+ import { jsx as jsx32 } from "react/jsx-runtime";
13527
14199
  var SourceInspectorOverlayContainer = () => {
13528
- const {
13529
- clearSourceInspector,
13530
- openSourceCandidate,
13531
- sourceInspectorInteractionRef,
13532
- sourceInspectorState
13533
- } = useReviewSourceInspectorState();
13534
- return /* @__PURE__ */ jsx31(
14200
+ const { componentSelectionState, sourceInspectorState } = useReviewSourceInspectorState();
14201
+ return /* @__PURE__ */ jsx32(
13535
14202
  SourceInspectorOverlay,
13536
14203
  {
13537
- interactionRef: sourceInspectorInteractionRef,
13538
- state: sourceInspectorState,
13539
- onClear: clearSourceInspector,
13540
- onOpenCandidate: openSourceCandidate
14204
+ componentSelectionState,
14205
+ state: sourceInspectorState
13541
14206
  }
13542
14207
  );
13543
14208
  };
@@ -13548,7 +14213,7 @@ import {
13548
14213
  } from "react";
13549
14214
 
13550
14215
  // src/react-shell/review/mode.toolbar.tsx
13551
- import { jsx as jsx32, jsxs as jsxs24 } from "react/jsx-runtime";
14216
+ import { jsx as jsx33, jsxs as jsxs24 } from "react/jsx-runtime";
13552
14217
  var ReviewModeToolbar = ({
13553
14218
  canWriteArea,
13554
14219
  canWriteDom,
@@ -13557,7 +14222,7 @@ var ReviewModeToolbar = ({
13557
14222
  }) => {
13558
14223
  if (!canWriteDom && !canWriteArea) return null;
13559
14224
  return /* @__PURE__ */ jsxs24("div", { className: "df-review-mode", "aria-label": "Add QA", children: [
13560
- canWriteDom && /* @__PURE__ */ jsx32(
14225
+ canWriteDom && /* @__PURE__ */ jsx33(
13561
14226
  "button",
13562
14227
  {
13563
14228
  "aria-label": "Element",
@@ -13565,11 +14230,11 @@ var ReviewModeToolbar = ({
13565
14230
  "data-review-tooltip": "Element QA",
13566
14231
  type: "button",
13567
14232
  onClick: () => onSetReviewMode("element"),
13568
- children: /* @__PURE__ */ jsx32(SquareMousePointer, { "aria-hidden": "true" })
14233
+ children: /* @__PURE__ */ jsx33(SquareMousePointer, { "aria-hidden": "true" })
13569
14234
  }
13570
14235
  ),
13571
- canWriteDom && canWriteArea && /* @__PURE__ */ jsx32("span", { className: "df-review-mode-divider", "aria-hidden": "true", children: "|" }),
13572
- canWriteArea && /* @__PURE__ */ jsx32(
14236
+ canWriteDom && canWriteArea && /* @__PURE__ */ jsx33("span", { className: "df-review-mode-divider", "aria-hidden": "true", children: "|" }),
14237
+ canWriteArea && /* @__PURE__ */ jsx33(
13573
14238
  "button",
13574
14239
  {
13575
14240
  "aria-label": "Area",
@@ -13577,14 +14242,14 @@ var ReviewModeToolbar = ({
13577
14242
  "data-review-tooltip": "Area QA",
13578
14243
  type: "button",
13579
14244
  onClick: () => onSetReviewMode("area"),
13580
- children: /* @__PURE__ */ jsx32(Scan, { "aria-hidden": "true" })
14245
+ children: /* @__PURE__ */ jsx33(Scan, { "aria-hidden": "true" })
13581
14246
  }
13582
14247
  )
13583
14248
  ] });
13584
14249
  };
13585
14250
 
13586
14251
  // src/react-shell/ruler/gutters.tsx
13587
- import { Fragment as Fragment5, jsx as jsx33, jsxs as jsxs25 } from "react/jsx-runtime";
14252
+ import { Fragment as Fragment5, jsx as jsx34, jsxs as jsxs25 } from "react/jsx-runtime";
13588
14253
  var RulerGutters = () => {
13589
14254
  const size = useReviewShellStore((state) => state.size);
13590
14255
  const {
@@ -13594,7 +14259,7 @@ var RulerGutters = () => {
13594
14259
  rulerUnit
13595
14260
  } = useReviewRulerState();
13596
14261
  return /* @__PURE__ */ jsxs25(Fragment5, { children: [
13597
- /* @__PURE__ */ jsx33("div", { className: "df-review-ruler-corner", "aria-hidden": "true" }),
14262
+ /* @__PURE__ */ jsx34("div", { className: "df-review-ruler-corner", "aria-hidden": "true" }),
13598
14263
  /* @__PURE__ */ jsxs25(
13599
14264
  "div",
13600
14265
  {
@@ -13604,14 +14269,14 @@ var RulerGutters = () => {
13604
14269
  },
13605
14270
  children: [
13606
14271
  /* @__PURE__ */ jsxs25("div", { className: "df-review-ruler-frame-label", children: [
13607
- /* @__PURE__ */ jsx33("strong", { children: size.label }),
14272
+ /* @__PURE__ */ jsx34("strong", { children: size.label }),
13608
14273
  /* @__PURE__ */ jsxs25("span", { children: [
13609
14274
  size.designWidth,
13610
14275
  size.designHeight ? `x${size.designHeight}` : "",
13611
14276
  rulerUnit
13612
14277
  ] })
13613
14278
  ] }),
13614
- rulerHover && /* @__PURE__ */ jsx33(
14279
+ rulerHover && /* @__PURE__ */ jsx34(
13615
14280
  "div",
13616
14281
  {
13617
14282
  className: "df-review-ruler-coord is-x",
@@ -13622,14 +14287,14 @@ var RulerGutters = () => {
13622
14287
  ]
13623
14288
  }
13624
14289
  ),
13625
- /* @__PURE__ */ jsx33(
14290
+ /* @__PURE__ */ jsx34(
13626
14291
  "div",
13627
14292
  {
13628
14293
  className: "df-review-ruler-gutter is-y",
13629
14294
  style: {
13630
14295
  "--df-review-ruler-step-y": `${rulerScaleY * 20}px`
13631
14296
  },
13632
- children: rulerHover && /* @__PURE__ */ jsx33(
14297
+ children: rulerHover && /* @__PURE__ */ jsx34(
13633
14298
  "div",
13634
14299
  {
13635
14300
  className: "df-review-ruler-coord is-y",
@@ -13643,7 +14308,7 @@ var RulerGutters = () => {
13643
14308
  };
13644
14309
 
13645
14310
  // src/react-shell/ruler/overlay.tsx
13646
- import { Fragment as Fragment6, jsx as jsx34, jsxs as jsxs26 } from "react/jsx-runtime";
14311
+ import { Fragment as Fragment6, jsx as jsx35, jsxs as jsxs26 } from "react/jsx-runtime";
13647
14312
  var RulerOverlay = () => {
13648
14313
  const { iframeRef } = useReviewShellRefs();
13649
14314
  const size = useReviewShellStore((state) => state.size);
@@ -13669,7 +14334,7 @@ var RulerOverlay = () => {
13669
14334
  },
13670
14335
  children: [
13671
14336
  rulerHover && /* @__PURE__ */ jsxs26(Fragment6, { children: [
13672
- /* @__PURE__ */ jsx34(
14337
+ /* @__PURE__ */ jsx35(
13673
14338
  "div",
13674
14339
  {
13675
14340
  className: "df-review-ruler-guide is-x",
@@ -13677,7 +14342,7 @@ var RulerOverlay = () => {
13677
14342
  style: { top: `${rulerHover.y}px` }
13678
14343
  }
13679
14344
  ),
13680
- /* @__PURE__ */ jsx34(
14345
+ /* @__PURE__ */ jsx35(
13681
14346
  "div",
13682
14347
  {
13683
14348
  className: "df-review-ruler-guide is-y",
@@ -13687,7 +14352,7 @@ var RulerOverlay = () => {
13687
14352
  )
13688
14353
  ] }),
13689
14354
  rulerMeasure && (rulerMeasure.width > 0 || rulerMeasure.height > 0) && /* @__PURE__ */ jsxs26(Fragment6, { children: [
13690
- /* @__PURE__ */ jsx34(
14355
+ /* @__PURE__ */ jsx35(
13691
14356
  "div",
13692
14357
  {
13693
14358
  className: "df-review-ruler-selection",
@@ -13700,7 +14365,7 @@ var RulerOverlay = () => {
13700
14365
  }
13701
14366
  }
13702
14367
  ),
13703
- /* @__PURE__ */ jsx34(
14368
+ /* @__PURE__ */ jsx35(
13704
14369
  "div",
13705
14370
  {
13706
14371
  className: "df-review-ruler-label",
@@ -14162,7 +14827,7 @@ import {
14162
14827
  useRef as useRef8,
14163
14828
  useState as useState9
14164
14829
  } from "react";
14165
- import { jsx as jsx35 } from "react/jsx-runtime";
14830
+ import { jsx as jsx36 } from "react/jsx-runtime";
14166
14831
  var OUTSIDE_MARKER_HEIGHT = 22;
14167
14832
  var OUTSIDE_MARKER_CONNECTOR_TOP = 10;
14168
14833
  var OUTSIDE_MARKER_GAP = 6;
@@ -14340,7 +15005,7 @@ var ReviewOutsideMarkers = () => {
14340
15005
  size
14341
15006
  ]);
14342
15007
  if (markers.length === 0) return null;
14343
- return /* @__PURE__ */ jsx35("div", { className: "df-review-outside-marker-layer", "aria-label": "QA markers", children: markers.map((marker) => {
15008
+ return /* @__PURE__ */ jsx36("div", { className: "df-review-outside-marker-layer", "aria-label": "QA markers", children: markers.map((marker) => {
14344
15009
  const isActive = marker.item.id === selectedItemId;
14345
15010
  const style = {
14346
15011
  top: `${marker.top}px`,
@@ -14349,7 +15014,7 @@ var ReviewOutsideMarkers = () => {
14349
15014
  "--df-review-outside-marker-connector-stem-height": `${marker.connectorStemHeight}px`,
14350
15015
  "--df-review-outside-marker-z-index": isActive ? 2 : 1
14351
15016
  };
14352
- return /* @__PURE__ */ jsx35(
15017
+ return /* @__PURE__ */ jsx36(
14353
15018
  "button",
14354
15019
  {
14355
15020
  "aria-label": `Focus ${marker.label}`,
@@ -14371,7 +15036,7 @@ var ReviewOutsideMarkers = () => {
14371
15036
  };
14372
15037
 
14373
15038
  // src/react-shell/target/frame.tsx
14374
- import { jsx as jsx36, jsxs as jsxs27 } from "react/jsx-runtime";
15039
+ import { jsx as jsx37, jsxs as jsxs27 } from "react/jsx-runtime";
14375
15040
  var ReviewTargetFrame = () => {
14376
15041
  const {
14377
15042
  figmaImageOverlays,
@@ -14382,9 +15047,17 @@ var ReviewTargetFrame = () => {
14382
15047
  const { isRulerAvailable, isRulerVisible } = useReviewRulerState();
14383
15048
  const { canWriteArea, canWriteDom } = useReviewShellAdapterState();
14384
15049
  const mode = useReviewShellStore((state) => state.mode);
15050
+ const frameNavigationVersion = useReviewShellStore(
15051
+ (state) => state.frameNavigationVersion
15052
+ );
15053
+ const frameTarget = useReviewShellStore((state) => state.frameTarget);
14385
15054
  const size = useReviewShellStore((state) => state.size);
14386
15055
  const target = useReviewShellStore((state) => state.target);
14387
15056
  const targetSrc = useMemo9(() => buildTargetSrc(target), [target]);
15057
+ const frameTargetSrc = useMemo9(
15058
+ () => buildTargetSrc(frameTarget),
15059
+ [frameTarget]
15060
+ );
14388
15061
  const showRuler = isRulerVisible && isRulerAvailable;
14389
15062
  const syncTargetFigmaImageOverlays = useTargetFigmaImageOverlays({
14390
15063
  figmaImageOverlays,
@@ -14398,14 +15071,14 @@ var ReviewTargetFrame = () => {
14398
15071
  syncTargetFigmaImageOverlays();
14399
15072
  window.requestAnimationFrame(syncTargetFigmaImageOverlays);
14400
15073
  };
14401
- return /* @__PURE__ */ jsx36("main", { className: "df-review-stage", children: /* @__PURE__ */ jsxs27("div", { className: "df-review-frame", children: [
14402
- /* @__PURE__ */ jsx36("div", { className: "df-review-frame-scroll", ref: frameScrollRef, children: /* @__PURE__ */ jsx36("div", { className: "df-review-frame-canvas", children: /* @__PURE__ */ jsx36("div", { className: "df-review-target-stack", children: /* @__PURE__ */ jsxs27(
15074
+ return /* @__PURE__ */ jsx37("main", { className: "df-review-stage", children: /* @__PURE__ */ jsxs27("div", { className: "df-review-frame", children: [
15075
+ /* @__PURE__ */ jsx37("div", { className: "df-review-frame-scroll", ref: frameScrollRef, children: /* @__PURE__ */ jsx37("div", { className: "df-review-frame-canvas", children: /* @__PURE__ */ jsx37("div", { className: "df-review-target-stack", children: /* @__PURE__ */ jsxs27(
14403
15076
  "div",
14404
15077
  {
14405
15078
  className: `df-review-device-frame${showRuler ? " is-ruler" : ""}`,
14406
15079
  children: [
14407
- showRuler && /* @__PURE__ */ jsx36(RulerGutters, {}),
14408
- /* @__PURE__ */ jsx36(ReviewOutsideMarkers, {}),
15080
+ showRuler && /* @__PURE__ */ jsx37(RulerGutters, {}),
15081
+ /* @__PURE__ */ jsx37(ReviewOutsideMarkers, {}),
14409
15082
  /* @__PURE__ */ jsxs27(
14410
15083
  "div",
14411
15084
  {
@@ -14417,26 +15090,26 @@ var ReviewTargetFrame = () => {
14417
15090
  minHeight: `${size.height}px`
14418
15091
  },
14419
15092
  children: [
14420
- /* @__PURE__ */ jsx36(
15093
+ /* @__PURE__ */ jsx37(
14421
15094
  "iframe",
14422
15095
  {
14423
15096
  ref: iframeRef,
14424
15097
  width: size.width,
14425
15098
  height: size.height,
14426
- src: targetSrc,
15099
+ src: frameTargetSrc,
14427
15100
  title: "Review target",
14428
15101
  onLoad: handleLoadTarget
14429
15102
  },
14430
- targetSrc
15103
+ `${frameTargetSrc}:${frameNavigationVersion}`
14431
15104
  ),
14432
- showRuler && /* @__PURE__ */ jsx36(RulerOverlay, {})
15105
+ showRuler && /* @__PURE__ */ jsx37(RulerOverlay, {})
14433
15106
  ]
14434
15107
  }
14435
15108
  )
14436
15109
  ]
14437
15110
  }
14438
15111
  ) }) }) }),
14439
- /* @__PURE__ */ jsx36("div", { className: "df-review-frame-actions", children: /* @__PURE__ */ jsx36(
15112
+ /* @__PURE__ */ jsx37("div", { className: "df-review-frame-actions", children: /* @__PURE__ */ jsx37(
14440
15113
  ReviewModeToolbar,
14441
15114
  {
14442
15115
  canWriteArea,
@@ -14452,18 +15125,18 @@ var ReviewTargetFrame = () => {
14452
15125
  import { useState as useState10 } from "react";
14453
15126
 
14454
15127
  // src/react-shell/topbar.tsx
14455
- import { jsx as jsx37, jsxs as jsxs28 } from "react/jsx-runtime";
15128
+ import { jsx as jsx38, jsxs as jsxs28 } from "react/jsx-runtime";
14456
15129
  var ReviewScopeIcon2 = ({ scope }) => {
14457
- if (scope === "mobile") return /* @__PURE__ */ jsx37(Smartphone, { "aria-hidden": "true" });
14458
- if (scope === "tablet") return /* @__PURE__ */ jsx37(RectangleHorizontal, { "aria-hidden": "true" });
14459
- if (scope === "wide") return /* @__PURE__ */ jsx37(Maximize2, { "aria-hidden": "true" });
14460
- if (scope === "dom") return /* @__PURE__ */ jsx37(SquareMousePointer, { "aria-hidden": "true" });
14461
- return /* @__PURE__ */ jsx37(Monitor, { "aria-hidden": "true" });
15130
+ if (scope === "mobile") return /* @__PURE__ */ jsx38(Smartphone, { "aria-hidden": "true" });
15131
+ if (scope === "tablet") return /* @__PURE__ */ jsx38(RectangleHorizontal, { "aria-hidden": "true" });
15132
+ if (scope === "wide") return /* @__PURE__ */ jsx38(Maximize2, { "aria-hidden": "true" });
15133
+ if (scope === "dom") return /* @__PURE__ */ jsx38(SquareMousePointer, { "aria-hidden": "true" });
15134
+ return /* @__PURE__ */ jsx38(Monitor, { "aria-hidden": "true" });
14462
15135
  };
14463
15136
  var ViewportPresetIcon = ({
14464
15137
  preset
14465
15138
  }) => {
14466
- return /* @__PURE__ */ jsx37(ReviewScopeIcon2, { scope: getViewportPresetKind(preset) });
15139
+ return /* @__PURE__ */ jsx38(ReviewScopeIcon2, { scope: getViewportPresetKind(preset) });
14467
15140
  };
14468
15141
  var getPresetSelectValue = (preset) => `${preset.label}:${preset.width}x${preset.height}`;
14469
15142
  function getTargetOpenHref(targetSrc) {
@@ -14510,7 +15183,7 @@ var ReviewTopbar = ({
14510
15183
  onApplyTarget();
14511
15184
  },
14512
15185
  children: [
14513
- /* @__PURE__ */ jsx37(
15186
+ /* @__PURE__ */ jsx38(
14514
15187
  "button",
14515
15188
  {
14516
15189
  "aria-label": "Open sitemap",
@@ -14519,10 +15192,10 @@ var ReviewTopbar = ({
14519
15192
  "data-review-tooltip-placement": "bottom",
14520
15193
  type: "button",
14521
15194
  onClick: onOpenSitemap,
14522
- children: /* @__PURE__ */ jsx37(Map2, { "aria-hidden": "true" })
15195
+ children: /* @__PURE__ */ jsx38(Map2, { "aria-hidden": "true" })
14523
15196
  }
14524
15197
  ),
14525
- /* @__PURE__ */ jsx37(
15198
+ /* @__PURE__ */ jsx38(
14526
15199
  "input",
14527
15200
  {
14528
15201
  "aria-label": "Path",
@@ -14531,7 +15204,7 @@ var ReviewTopbar = ({
14531
15204
  }
14532
15205
  ),
14533
15206
  /* @__PURE__ */ jsxs28("div", { className: "df-review-address-actions", children: [
14534
- /* @__PURE__ */ jsx37(
15207
+ /* @__PURE__ */ jsx38(
14535
15208
  "button",
14536
15209
  {
14537
15210
  "aria-label": "Refresh target",
@@ -14540,10 +15213,10 @@ var ReviewTopbar = ({
14540
15213
  "data-review-tooltip-placement": "bottom",
14541
15214
  title: "Refresh target",
14542
15215
  type: "submit",
14543
- children: /* @__PURE__ */ jsx37(RefreshCw, { "aria-hidden": "true" })
15216
+ children: /* @__PURE__ */ jsx38(RefreshCw, { "aria-hidden": "true" })
14544
15217
  }
14545
15218
  ),
14546
- /* @__PURE__ */ jsx37(
15219
+ /* @__PURE__ */ jsx38(
14547
15220
  "button",
14548
15221
  {
14549
15222
  "aria-label": copyLabel,
@@ -14553,10 +15226,10 @@ var ReviewTopbar = ({
14553
15226
  title: copyLabel,
14554
15227
  type: "button",
14555
15228
  onClick: onCopyCurrentUrl,
14556
- children: /* @__PURE__ */ jsx37(Copy, { "aria-hidden": "true" })
15229
+ children: /* @__PURE__ */ jsx38(Copy, { "aria-hidden": "true" })
14557
15230
  }
14558
15231
  ),
14559
- /* @__PURE__ */ jsx37(
15232
+ /* @__PURE__ */ jsx38(
14560
15233
  "a",
14561
15234
  {
14562
15235
  "aria-label": "Open target page",
@@ -14567,7 +15240,7 @@ var ReviewTopbar = ({
14567
15240
  rel: "noreferrer",
14568
15241
  target: "_blank",
14569
15242
  title: "Open target page",
14570
- children: /* @__PURE__ */ jsx37(ExternalLink, { "aria-hidden": "true" })
15243
+ children: /* @__PURE__ */ jsx38(ExternalLink, { "aria-hidden": "true" })
14571
15244
  }
14572
15245
  )
14573
15246
  ] })
@@ -14576,21 +15249,21 @@ var ReviewTopbar = ({
14576
15249
  ),
14577
15250
  /* @__PURE__ */ jsxs28("div", { className: "df-review-tools", children: [
14578
15251
  /* @__PURE__ */ jsxs28("div", { className: "df-review-tool-controls", children: [
14579
- /* @__PURE__ */ jsx37("div", { className: "df-review-presets", "aria-label": "Viewport presets", children: viewportPresets.map((preset) => /* @__PURE__ */ jsxs28(
15252
+ /* @__PURE__ */ jsx38("div", { className: "df-review-presets", "aria-label": "Viewport presets", children: viewportPresets.map((preset) => /* @__PURE__ */ jsxs28(
14580
15253
  "button",
14581
15254
  {
14582
15255
  className: preset.label === size.label ? "is-active" : "",
14583
15256
  type: "button",
14584
15257
  onClick: () => onSizeChange(preset),
14585
15258
  children: [
14586
- /* @__PURE__ */ jsx37(ViewportPresetIcon, { preset }),
14587
- /* @__PURE__ */ jsx37("span", { className: "df-review-preset-copy", children: /* @__PURE__ */ jsx37("strong", { children: preset.label }) }),
14588
- /* @__PURE__ */ jsx37("span", { className: "df-review-preset-count", children: presetScopeCounts.get(getViewportPresetKind(preset)) ?? 0 })
15259
+ /* @__PURE__ */ jsx38(ViewportPresetIcon, { preset }),
15260
+ /* @__PURE__ */ jsx38("span", { className: "df-review-preset-copy", children: /* @__PURE__ */ jsx38("strong", { children: preset.label }) }),
15261
+ /* @__PURE__ */ jsx38("span", { className: "df-review-preset-count", children: presetScopeCounts.get(getViewportPresetKind(preset)) ?? 0 })
14589
15262
  ]
14590
15263
  },
14591
15264
  preset.label
14592
15265
  )) }),
14593
- /* @__PURE__ */ jsx37(
15266
+ /* @__PURE__ */ jsx38(
14594
15267
  "select",
14595
15268
  {
14596
15269
  "aria-label": "Viewport preset",
@@ -14600,7 +15273,7 @@ var ReviewTopbar = ({
14600
15273
  children: viewportPresets.map((preset) => {
14601
15274
  const scope = getViewportPresetKind(preset);
14602
15275
  const count = presetScopeCounts.get(scope) ?? 0;
14603
- return /* @__PURE__ */ jsx37(
15276
+ return /* @__PURE__ */ jsx38(
14604
15277
  "option",
14605
15278
  {
14606
15279
  value: getPresetSelectValue(preset),
@@ -14611,7 +15284,7 @@ var ReviewTopbar = ({
14611
15284
  })
14612
15285
  }
14613
15286
  ),
14614
- /* @__PURE__ */ jsx37("span", { className: "df-review-tool-divider", "aria-hidden": "true", children: "|" }),
15287
+ /* @__PURE__ */ jsx38("span", { className: "df-review-tool-divider", "aria-hidden": "true", children: "|" }),
14615
15288
  /* @__PURE__ */ jsxs28("span", { className: "df-review-active-size", children: [
14616
15289
  size.width,
14617
15290
  "x",
@@ -14619,7 +15292,7 @@ var ReviewTopbar = ({
14619
15292
  ] })
14620
15293
  ] }),
14621
15294
  /* @__PURE__ */ jsxs28("div", { className: "df-review-overlays", "aria-label": "Target overlays", children: [
14622
- isRulerAvailable && /* @__PURE__ */ jsx37(
15295
+ isRulerAvailable && /* @__PURE__ */ jsx38(
14623
15296
  "button",
14624
15297
  {
14625
15298
  "aria-label": "Toggle ruler",
@@ -14628,10 +15301,10 @@ var ReviewTopbar = ({
14628
15301
  "data-review-tooltip-placement": "bottom",
14629
15302
  type: "button",
14630
15303
  onClick: onToggleRuler,
14631
- children: /* @__PURE__ */ jsx37(Ruler, { "aria-hidden": "true" })
15304
+ children: /* @__PURE__ */ jsx38(Ruler, { "aria-hidden": "true" })
14632
15305
  }
14633
15306
  ),
14634
- /* @__PURE__ */ jsx37(
15307
+ /* @__PURE__ */ jsx38(
14635
15308
  "button",
14636
15309
  {
14637
15310
  "aria-label": "Toggle grid overlay",
@@ -14640,10 +15313,10 @@ var ReviewTopbar = ({
14640
15313
  "data-review-tooltip-placement": "bottom",
14641
15314
  type: "button",
14642
15315
  onClick: () => onToggleTargetOverlay("grid"),
14643
- children: /* @__PURE__ */ jsx37(LayoutGrid, { "aria-hidden": "true" })
15316
+ children: /* @__PURE__ */ jsx38(LayoutGrid, { "aria-hidden": "true" })
14644
15317
  }
14645
15318
  ),
14646
- /* @__PURE__ */ jsx37(
15319
+ /* @__PURE__ */ jsx38(
14647
15320
  "button",
14648
15321
  {
14649
15322
  "aria-disabled": !isFigmaOverlayAvailable,
@@ -14654,7 +15327,7 @@ var ReviewTopbar = ({
14654
15327
  disabled: !isFigmaOverlayAvailable,
14655
15328
  type: "button",
14656
15329
  onClick: onToggleFigmaOverlay,
14657
- children: /* @__PURE__ */ jsx37(FigmaMarkIcon, {})
15330
+ children: /* @__PURE__ */ jsx38(FigmaMarkIcon, {})
14658
15331
  }
14659
15332
  )
14660
15333
  ] })
@@ -14663,7 +15336,7 @@ var ReviewTopbar = ({
14663
15336
  };
14664
15337
 
14665
15338
  // src/react-shell/topbar.container.tsx
14666
- import { jsx as jsx38 } from "react/jsx-runtime";
15339
+ import { jsx as jsx39 } from "react/jsx-runtime";
14667
15340
  var TopbarContainer = () => {
14668
15341
  const {
14669
15342
  applyTarget,
@@ -14696,7 +15369,7 @@ var TopbarContainer = () => {
14696
15369
  const copyCurrentUrl = () => copyCurrentReviewUrl({
14697
15370
  onCopyLabelChange: setCopyLabel
14698
15371
  });
14699
- return /* @__PURE__ */ jsx38(
15372
+ return /* @__PURE__ */ jsx39(
14700
15373
  ReviewTopbar,
14701
15374
  {
14702
15375
  draftTarget,
@@ -14723,11 +15396,11 @@ var TopbarContainer = () => {
14723
15396
  };
14724
15397
 
14725
15398
  // src/react-shell/review/toast.container.tsx
14726
- import { jsx as jsx39 } from "react/jsx-runtime";
15399
+ import { jsx as jsx40 } from "react/jsx-runtime";
14727
15400
  var ReviewToastContainer = () => {
14728
15401
  const toastMessage = useReviewShellStore((state) => state.toastMessage);
14729
15402
  if (!toastMessage) return null;
14730
- return /* @__PURE__ */ jsx39("div", { className: "df-review-copy-toast", role: "status", children: toastMessage });
15403
+ return /* @__PURE__ */ jsx40("div", { className: "df-review-copy-toast", role: "status", children: toastMessage });
14731
15404
  };
14732
15405
 
14733
15406
  // src/react-shell/hooks/use.review.shell.runtime.ts
@@ -15025,7 +15698,7 @@ var bindReviewFrameNavigation = ({
15025
15698
  onSyncShellTarget,
15026
15699
  onSyncTargetViewport
15027
15700
  }) => {
15028
- const syncRouteFromFrame = () => {
15701
+ const syncRouteFromFrame = (navigation) => {
15029
15702
  const nextTarget = getFrameRouteTarget(targetWindow, reviewPathPrefix);
15030
15703
  const nextRouteKey = getTargetRouteKey(nextTarget, reviewPathPrefix);
15031
15704
  const currentRouteKey = getTargetRouteKey(
@@ -15036,7 +15709,7 @@ var bindReviewFrameNavigation = ({
15036
15709
  if (!pageTargets.has(nextRouteKey)) {
15037
15710
  return;
15038
15711
  }
15039
- onSyncShellTarget(nextTarget);
15712
+ onSyncShellTarget(nextTarget, navigation);
15040
15713
  };
15041
15714
  const handleClick = (event) => {
15042
15715
  if (event.defaultPrevented || event.button !== 0) return;
@@ -15063,7 +15736,7 @@ var bindReviewFrameNavigation = ({
15063
15736
  if (nextRouteKey === currentRouteKey) return;
15064
15737
  if (!pageTargets.has(nextRouteKey)) return;
15065
15738
  event.preventDefault();
15066
- onSyncShellTarget(nextTarget);
15739
+ onSyncShellTarget(nextTarget, "hard");
15067
15740
  };
15068
15741
  const handleFrameKeyDown = (event) => {
15069
15742
  if (event.key !== "Escape") return;
@@ -15076,26 +15749,27 @@ var bindReviewFrameNavigation = ({
15076
15749
  const originalReplaceState = history.replaceState.bind(history);
15077
15750
  history.pushState = (...args) => {
15078
15751
  originalPushState(...args);
15079
- syncRouteFromFrame();
15752
+ syncRouteFromFrame("soft");
15080
15753
  };
15081
15754
  history.replaceState = (...args) => {
15082
15755
  originalReplaceState(...args);
15083
- syncRouteFromFrame();
15756
+ syncRouteFromFrame("soft");
15084
15757
  };
15085
- syncRouteFromFrame();
15086
- targetWindow.addEventListener("popstate", syncRouteFromFrame);
15087
- targetWindow.addEventListener("hashchange", syncRouteFromFrame);
15758
+ const syncHardRouteFromFrame = () => syncRouteFromFrame("hard");
15759
+ syncRouteFromFrame("soft");
15760
+ targetWindow.addEventListener("popstate", syncHardRouteFromFrame);
15761
+ targetWindow.addEventListener("hashchange", syncHardRouteFromFrame);
15088
15762
  targetWindow.addEventListener("keydown", handleFrameKeyDown, true);
15089
- targetDocument.addEventListener("click", handleClick, true);
15763
+ targetDocument.addEventListener("click", handleClick);
15090
15764
  targetWindow.addEventListener("scroll", onSyncTargetViewport, true);
15091
15765
  targetWindow.addEventListener("resize", onSyncTargetViewport);
15092
15766
  return () => {
15093
15767
  history.pushState = originalPushState;
15094
15768
  history.replaceState = originalReplaceState;
15095
- targetWindow.removeEventListener("popstate", syncRouteFromFrame);
15096
- targetWindow.removeEventListener("hashchange", syncRouteFromFrame);
15769
+ targetWindow.removeEventListener("popstate", syncHardRouteFromFrame);
15770
+ targetWindow.removeEventListener("hashchange", syncHardRouteFromFrame);
15097
15771
  targetWindow.removeEventListener("keydown", handleFrameKeyDown, true);
15098
- targetDocument.removeEventListener("click", handleClick, true);
15772
+ targetDocument.removeEventListener("click", handleClick);
15099
15773
  targetWindow.removeEventListener("scroll", onSyncTargetViewport, true);
15100
15774
  targetWindow.removeEventListener("resize", onSyncTargetViewport);
15101
15775
  };
@@ -15898,12 +16572,13 @@ var useReviewTargetSync = ({
15898
16572
  onActiveRouteChange,
15899
16573
  onClearSelectedItem,
15900
16574
  onDraftTargetChange,
16575
+ onFrameTargetChange,
15901
16576
  onSyncTargetViewport,
15902
16577
  onTargetChange
15903
16578
  }) => {
15904
16579
  const storeApi = useReviewShellStoreApi();
15905
16580
  const syncShellTarget = useCallback13(
15906
- (nextTarget) => {
16581
+ (nextTarget, navigation) => {
15907
16582
  const normalizedTarget = normalizeTarget(nextTarget, reviewPathPrefix);
15908
16583
  const nextRouteKey = getTargetRouteKey(
15909
16584
  normalizedTarget,
@@ -15914,6 +16589,9 @@ var useReviewTargetSync = ({
15914
16589
  onTargetChange(normalizedTarget);
15915
16590
  onDraftTargetChange(normalizedTarget);
15916
16591
  onActiveRouteChange(nextRouteKey);
16592
+ if (navigation === "hard") {
16593
+ onFrameTargetChange(normalizedTarget);
16594
+ }
15917
16595
  }
15918
16596
  const { size: currentSize, selectedItemId } = storeApi.getState();
15919
16597
  if (selectedItemId) {
@@ -15931,6 +16609,7 @@ var useReviewTargetSync = ({
15931
16609
  onActiveRouteChange,
15932
16610
  onClearSelectedItem,
15933
16611
  onDraftTargetChange,
16612
+ onFrameTargetChange,
15934
16613
  onTargetChange,
15935
16614
  reviewPathPrefix,
15936
16615
  source,
@@ -16002,15 +16681,29 @@ var useReviewController = ({
16002
16681
  );
16003
16682
  const setActiveRoute = useReviewShellStore((state) => state.setActiveRoute);
16004
16683
  const setDraftTarget = useReviewShellStore((state) => state.setDraftTarget);
16684
+ const navigateFrameTarget = useReviewShellStore(
16685
+ (state) => state.navigateFrameTarget
16686
+ );
16687
+ const setIsListVisible = useReviewShellStore(
16688
+ (state) => state.setIsListVisible
16689
+ );
16005
16690
  const setMode = useReviewShellStore((state) => state.setMode);
16006
16691
  const setSelectedItemId = useReviewShellStore(
16007
16692
  (state) => state.setSelectedItemId
16008
16693
  );
16694
+ const setSidePanel = useReviewShellStore((state) => state.setSidePanel);
16009
16695
  const setSize = useReviewShellStore((state) => state.setSize);
16010
16696
  const setTarget = useReviewShellStore((state) => state.setTarget);
16011
16697
  const setTargetOverlayState = useReviewShellStore(
16012
16698
  (state) => state.setTargetOverlayState
16013
16699
  );
16700
+ const setHardTarget = useCallback14(
16701
+ (nextTarget) => {
16702
+ setTarget(nextTarget);
16703
+ navigateFrameTarget(nextTarget);
16704
+ },
16705
+ [navigateFrameTarget, setTarget]
16706
+ );
16014
16707
  const syncTargetViewport = useCallback14(() => {
16015
16708
  window.dispatchEvent(new Event("resize"));
16016
16709
  }, []);
@@ -16049,8 +16742,20 @@ var useReviewController = ({
16049
16742
  onSelectedItemIdChange: setSelectedItemId,
16050
16743
  onSizeChange: setSize,
16051
16744
  onSyncTargetViewport: syncTargetViewport,
16052
- onTargetChange: setTarget
16745
+ onTargetChange: setHardTarget
16053
16746
  });
16747
+ const restoreCreatedReviewItem = useCallback14(
16748
+ (item) => {
16749
+ setSidePanel("qa");
16750
+ setIsListVisible(true);
16751
+ restoreReviewItem(item);
16752
+ },
16753
+ [
16754
+ restoreReviewItem,
16755
+ setIsListVisible,
16756
+ setSidePanel
16757
+ ]
16758
+ );
16054
16759
  const { syncShellTarget } = useReviewTargetSync({
16055
16760
  iframeRef,
16056
16761
  reviewPathPrefix,
@@ -16060,6 +16765,7 @@ var useReviewController = ({
16060
16765
  onActiveRouteChange: setActiveRoute,
16061
16766
  onClearSelectedItem: clearSelectedItem,
16062
16767
  onDraftTargetChange: setDraftTarget,
16768
+ onFrameTargetChange: navigateFrameTarget,
16063
16769
  onSyncTargetViewport: syncTargetViewport,
16064
16770
  onTargetChange: setTarget
16065
16771
  });
@@ -16087,7 +16793,7 @@ var useReviewController = ({
16087
16793
  onApplyPendingRestore: applyPendingRestore,
16088
16794
  onCancelReviewMode,
16089
16795
  onCloseRuler,
16090
- onCreateItem: restoreReviewItem,
16796
+ onCreateItem: restoreCreatedReviewItem,
16091
16797
  onItemsRefresh,
16092
16798
  onModeChange: setMode,
16093
16799
  onRefreshTargetOverlayState: refreshTargetOverlayState,
@@ -16394,6 +17100,7 @@ var useReviewShellActionsValue = ({
16394
17100
  changeReviewSource,
16395
17101
  clearSourceInspector,
16396
17102
  clearSourceOutlineHover,
17103
+ clearSourceOutlineSelection,
16397
17104
  clearSelectedReviewItem,
16398
17105
  getPageTarget,
16399
17106
  initReviewKit,
@@ -16403,6 +17110,7 @@ var useReviewShellActionsValue = ({
16403
17110
  restoreReviewItem,
16404
17111
  selectAllQa,
16405
17112
  selectPage,
17113
+ selectSourceOutlineForElement,
16406
17114
  setIsInitialPromptOpen,
16407
17115
  setIsInitialPromptScriptOpen,
16408
17116
  setReviewMode,
@@ -16419,6 +17127,7 @@ var useReviewShellActionsValue = ({
16419
17127
  changeReviewSource,
16420
17128
  clearSourceInspector,
16421
17129
  clearSourceOutlineHover,
17130
+ clearSourceOutlineSelection,
16422
17131
  clearSelectedReviewItem,
16423
17132
  getPageTarget,
16424
17133
  initReviewKit,
@@ -16430,6 +17139,7 @@ var useReviewShellActionsValue = ({
16430
17139
  restoreReviewItem,
16431
17140
  selectAllQa,
16432
17141
  selectPage,
17142
+ selectSourceOutlineForElement,
16433
17143
  setReviewMode,
16434
17144
  showSourceOutlineForElement,
16435
17145
  toggleFigmaImagesPanel,
@@ -16442,6 +17152,7 @@ var useReviewShellActionsValue = ({
16442
17152
  changeReviewSource,
16443
17153
  clearSourceInspector,
16444
17154
  clearSourceOutlineHover,
17155
+ clearSourceOutlineSelection,
16445
17156
  clearSelectedReviewItem,
16446
17157
  getPageTarget,
16447
17158
  initReviewKit,
@@ -16451,6 +17162,7 @@ var useReviewShellActionsValue = ({
16451
17162
  restoreReviewItem,
16452
17163
  selectAllQa,
16453
17164
  selectPage,
17165
+ selectSourceOutlineForElement,
16454
17166
  setIsInitialPromptOpen,
16455
17167
  setIsInitialPromptScriptOpen,
16456
17168
  setReviewMode,
@@ -16466,7 +17178,23 @@ var useReviewShellActionsValue = ({
16466
17178
  import {
16467
17179
  useEffect as useEffect16
16468
17180
  } from "react";
17181
+ var REVIEW_SELECTION_ACTION_SELECTOR = [
17182
+ "a",
17183
+ "button",
17184
+ "input",
17185
+ "select",
17186
+ "summary",
17187
+ "textarea",
17188
+ '[contenteditable="true"]',
17189
+ "[data-dfwr-move-entry-id]",
17190
+ '[role="button"]'
17191
+ ].join(", ");
17192
+ var isReviewSelectionAction = (target) => {
17193
+ const element = target;
17194
+ return typeof element?.closest === "function" && Boolean(element.closest(REVIEW_SELECTION_ACTION_SELECTOR));
17195
+ };
16469
17196
  var useReviewShellEffects = ({
17197
+ clearSelectedReviewItem,
16470
17198
  frameScrollRef,
16471
17199
  iframeRef,
16472
17200
  isListVisible,
@@ -16474,8 +17202,10 @@ var useReviewShellEffects = ({
16474
17202
  mode,
16475
17203
  pendingInitialItemIdRef,
16476
17204
  restoreReviewItem,
17205
+ selectedItemId,
16477
17206
  size,
16478
17207
  syncTargetViewport,
17208
+ targetFrameLoadVersion,
16479
17209
  targetSrc
16480
17210
  }) => {
16481
17211
  useEffect16(() => {
@@ -16519,6 +17249,60 @@ var useReviewShellEffects = ({
16519
17249
  setTargetFigmaOverlayLocked(targetDocument, false);
16520
17250
  };
16521
17251
  }, [iframeRef, mode, targetSrc]);
17252
+ useEffect16(() => {
17253
+ if (!selectedItemId) return void 0;
17254
+ const frameScroll = frameScrollRef.current;
17255
+ let frameDocument = null;
17256
+ try {
17257
+ frameDocument = iframeRef.current?.contentDocument ?? null;
17258
+ } catch {
17259
+ frameDocument = null;
17260
+ }
17261
+ const clearOnWorkspacePointerDown = (event) => {
17262
+ if (isReviewSelectionAction(event.target)) return;
17263
+ clearSelectedReviewItem();
17264
+ };
17265
+ const clearOnEscape = (event) => {
17266
+ if (event.key !== "Escape") return;
17267
+ const activeElement = document.activeElement;
17268
+ if (activeElement instanceof HTMLElement && activeElement.closest("[data-review-qa-item-id]")) {
17269
+ activeElement.blur();
17270
+ }
17271
+ clearSelectedReviewItem();
17272
+ };
17273
+ frameScroll?.addEventListener(
17274
+ "pointerdown",
17275
+ clearOnWorkspacePointerDown,
17276
+ true
17277
+ );
17278
+ frameDocument?.addEventListener(
17279
+ "pointerdown",
17280
+ clearOnWorkspacePointerDown,
17281
+ true
17282
+ );
17283
+ frameDocument?.addEventListener("keydown", clearOnEscape, true);
17284
+ window.addEventListener("keydown", clearOnEscape, true);
17285
+ return () => {
17286
+ frameScroll?.removeEventListener(
17287
+ "pointerdown",
17288
+ clearOnWorkspacePointerDown,
17289
+ true
17290
+ );
17291
+ frameDocument?.removeEventListener(
17292
+ "pointerdown",
17293
+ clearOnWorkspacePointerDown,
17294
+ true
17295
+ );
17296
+ frameDocument?.removeEventListener("keydown", clearOnEscape, true);
17297
+ window.removeEventListener("keydown", clearOnEscape, true);
17298
+ };
17299
+ }, [
17300
+ clearSelectedReviewItem,
17301
+ frameScrollRef,
17302
+ iframeRef,
17303
+ selectedItemId,
17304
+ targetFrameLoadVersion
17305
+ ]);
16522
17306
  };
16523
17307
 
16524
17308
  // src/react-shell/figma.ts
@@ -17322,16 +18106,14 @@ var useReviewShellTransientActions = ({
17322
18106
  };
17323
18107
  var useReviewShellPanelActions = ({
17324
18108
  isFigmaImageManagementEnabled,
17325
- isSourceInspectorEnabled,
17326
18109
  toggleSidePanel
17327
18110
  }) => {
17328
18111
  const toggleQaPanel = useCallback20(() => {
17329
18112
  toggleSidePanel("qa");
17330
18113
  }, [toggleSidePanel]);
17331
18114
  const toggleSourceTreePanel = useCallback20(() => {
17332
- if (!isSourceInspectorEnabled) return;
17333
18115
  toggleSidePanel("source");
17334
- }, [isSourceInspectorEnabled, toggleSidePanel]);
18116
+ }, [toggleSidePanel]);
17335
18117
  const toggleFigmaImagesPanel = useCallback20(() => {
17336
18118
  if (!isFigmaImageManagementEnabled) return;
17337
18119
  toggleSidePanel("figma-images");
@@ -17347,6 +18129,7 @@ var useReviewShellPanelActions = ({
17347
18129
  };
17348
18130
  var useReviewShellModeSetter = ({
17349
18131
  closeRuler,
18132
+ isListVisible,
17350
18133
  mode,
17351
18134
  openSidePanel,
17352
18135
  setControllerReviewMode,
@@ -17356,13 +18139,14 @@ var useReviewShellModeSetter = ({
17356
18139
  const writeMode = getReviewModeWriteMode(nextMode);
17357
18140
  if (writeMode && !writeModes.includes(writeMode)) return;
17358
18141
  closeRuler();
17359
- if (writeMode && mode !== nextMode) {
18142
+ if (writeMode && mode !== nextMode && !isListVisible) {
17360
18143
  openSidePanel("qa");
17361
18144
  }
17362
18145
  setControllerReviewMode(nextMode);
17363
18146
  },
17364
18147
  [
17365
18148
  closeRuler,
18149
+ isListVisible,
17366
18150
  mode,
17367
18151
  openSidePanel,
17368
18152
  setControllerReviewMode,
@@ -17716,39 +18500,34 @@ import {
17716
18500
  useEffect as useEffect21
17717
18501
  } from "react";
17718
18502
  var getAvailableSidePanel = (sidePanel, {
17719
- isFigmaImageManagementEnabled,
17720
- isSourceInspectorEnabled
18503
+ isFigmaImageManagementEnabled
17721
18504
  }) => {
17722
- if (sidePanel === "source" && !isSourceInspectorEnabled) return "qa";
17723
18505
  if (sidePanel === "figma-images" && !isFigmaImageManagementEnabled) {
17724
18506
  return "qa";
17725
18507
  }
17726
18508
  return sidePanel;
17727
18509
  };
17728
18510
  var useReviewSidePanel = ({
17729
- isFigmaImageManagementEnabled,
17730
- isSourceInspectorEnabled
18511
+ isFigmaImageManagementEnabled
17731
18512
  }) => {
17732
18513
  const storeApi = useReviewShellStoreApi();
17733
18514
  const rawSidePanel = useReviewShellStore((state) => state.sidePanel);
17734
18515
  const isListVisible = useReviewShellStore((state) => state.isListVisible);
17735
18516
  const sidePanel = getAvailableSidePanel(rawSidePanel, {
17736
- isFigmaImageManagementEnabled,
17737
- isSourceInspectorEnabled
18517
+ isFigmaImageManagementEnabled
17738
18518
  });
17739
18519
  const isQaPanelVisible = isListVisible && sidePanel === "qa";
17740
- const isSourceTreePanelVisible = isSourceInspectorEnabled && isListVisible && sidePanel === "source";
18520
+ const isSourceTreePanelVisible = isListVisible && sidePanel === "source";
17741
18521
  const isFigmaImagesPanelVisible = isFigmaImageManagementEnabled && isListVisible && sidePanel === "figma-images";
17742
18522
  useEffect21(() => {
17743
18523
  const state = storeApi.getState();
17744
18524
  const availableSidePanel = getAvailableSidePanel(state.sidePanel, {
17745
- isFigmaImageManagementEnabled,
17746
- isSourceInspectorEnabled
18525
+ isFigmaImageManagementEnabled
17747
18526
  });
17748
18527
  if (availableSidePanel !== state.sidePanel) {
17749
18528
  state.setSidePanel(availableSidePanel);
17750
18529
  }
17751
- }, [isFigmaImageManagementEnabled, isSourceInspectorEnabled, storeApi]);
18530
+ }, [isFigmaImageManagementEnabled, storeApi]);
17752
18531
  useEffect21(() => {
17753
18532
  writeStoredReviewSidePanel(sidePanel);
17754
18533
  }, [sidePanel]);
@@ -17760,31 +18539,28 @@ var useReviewSidePanel = ({
17760
18539
  const state = storeApi.getState();
17761
18540
  state.setSidePanel(
17762
18541
  getAvailableSidePanel(nextSidePanel, {
17763
- isFigmaImageManagementEnabled,
17764
- isSourceInspectorEnabled
18542
+ isFigmaImageManagementEnabled
17765
18543
  })
17766
18544
  );
17767
18545
  state.setIsListVisible(true);
17768
18546
  },
17769
- [isFigmaImageManagementEnabled, isSourceInspectorEnabled, storeApi]
18547
+ [isFigmaImageManagementEnabled, storeApi]
17770
18548
  );
17771
18549
  const toggleSidePanel = useCallback23(
17772
18550
  (nextSidePanel) => {
17773
18551
  const state = storeApi.getState();
17774
18552
  const currentSidePanel = getAvailableSidePanel(state.sidePanel, {
17775
- isFigmaImageManagementEnabled,
17776
- isSourceInspectorEnabled
18553
+ isFigmaImageManagementEnabled
17777
18554
  });
17778
18555
  const availableSidePanel = getAvailableSidePanel(nextSidePanel, {
17779
- isFigmaImageManagementEnabled,
17780
- isSourceInspectorEnabled
18556
+ isFigmaImageManagementEnabled
17781
18557
  });
17782
18558
  state.setSidePanel(availableSidePanel);
17783
18559
  state.setIsListVisible(
17784
18560
  currentSidePanel === availableSidePanel ? !state.isListVisible : true
17785
18561
  );
17786
18562
  },
17787
- [isFigmaImageManagementEnabled, isSourceInspectorEnabled, storeApi]
18563
+ [isFigmaImageManagementEnabled, storeApi]
17788
18564
  );
17789
18565
  return {
17790
18566
  isFigmaImagesPanelVisible,
@@ -17871,24 +18647,20 @@ function createSourceShortcutStyle(optionAttribute, fontOverlayAttribute) {
17871
18647
  }
17872
18648
 
17873
18649
  // src/react-shell/hooks/use.review.source.inspector.ts
17874
- var SOURCE_PANEL_MAX_WIDTH = 440;
17875
- var SOURCE_PANEL_MIN_WIDTH = 240;
17876
- var SOURCE_PANEL_MAX_HEIGHT = 260;
17877
18650
  function useReviewSourceInspector({
18651
+ frameScrollRef,
17878
18652
  iframeRef,
17879
- isSourceInspectorEnabled,
17880
18653
  isSourceTreeHoverOutlineEnabled,
17881
18654
  sourceCandidateOptions,
17882
- sourceOpenOptions,
17883
18655
  targetSrc,
17884
- onCancelReviewMode
18656
+ onCancelReviewMode,
18657
+ onRequestSourceTreeFocus
17885
18658
  }) {
17886
18659
  const showToast = useReviewToast();
17887
18660
  const sourceShortcutCleanupRef = useRef14(null);
17888
- const sourceInspectorInteractionRef = useRef14(false);
18661
+ const [componentSelectionState, setComponentSelectionState] = useState17(null);
17889
18662
  const [sourceInspectorState, setSourceInspectorState] = useState17(null);
17890
18663
  const clearSourceInspector = useCallback24(() => {
17891
- sourceInspectorInteractionRef.current = false;
17892
18664
  setSourceInspectorState(null);
17893
18665
  }, []);
17894
18666
  const getSourceInspectorRect = useCallback24(
@@ -17916,68 +18688,6 @@ function useReviewSourceInspector({
17916
18688
  },
17917
18689
  [iframeRef]
17918
18690
  );
17919
- const getSourceInspectorPanelPosition = useCallback24(
17920
- (rect) => {
17921
- const margin = 12;
17922
- const gap = 10;
17923
- const preferredLeft = rect.left + rect.width + gap;
17924
- const rightSpace = window.innerWidth - preferredLeft - margin;
17925
- const leftSpace = rect.left - gap - margin;
17926
- const canOpenRight = rightSpace >= SOURCE_PANEL_MIN_WIDTH;
17927
- const canOpenLeft = leftSpace >= SOURCE_PANEL_MIN_WIDTH;
17928
- const left = canOpenRight || !canOpenLeft ? preferredLeft : margin;
17929
- const right = canOpenRight || !canOpenLeft ? null : Math.max(margin, window.innerWidth - (rect.left - gap));
17930
- const maxWidth = Math.min(
17931
- SOURCE_PANEL_MAX_WIDTH,
17932
- Math.max(
17933
- SOURCE_PANEL_MIN_WIDTH,
17934
- canOpenRight ? rightSpace : canOpenLeft ? leftSpace : window.innerWidth - margin * 2
17935
- )
17936
- );
17937
- const top = Math.min(
17938
- Math.max(margin, rect.top),
17939
- Math.max(margin, window.innerHeight - SOURCE_PANEL_MAX_HEIGHT - margin)
17940
- );
17941
- return { left, maxWidth, right, top };
17942
- },
17943
- []
17944
- );
17945
- const showSourceInspectorForTarget = useCallback24(
17946
- (target, isPinned = false) => {
17947
- const candidates = getSourceCandidates(target, sourceCandidateOptions).map(
17948
- (candidate) => ({
17949
- ...candidate,
17950
- openUrl: getSourceOpenUrl(candidate.source, {
17951
- ...sourceOpenOptions,
17952
- omitPosition: !candidate.usesPosition
17953
- })
17954
- })
17955
- );
17956
- const firstCandidate = candidates[0];
17957
- const rect = firstCandidate ? getSourceInspectorRect(firstCandidate.element) : null;
17958
- if (!firstCandidate || !rect) {
17959
- setSourceInspectorState(null);
17960
- return [];
17961
- }
17962
- const { left, maxWidth, right, top } = getSourceInspectorPanelPosition(rect);
17963
- setSourceInspectorState({
17964
- candidates,
17965
- isPinned,
17966
- panelLeft: left,
17967
- panelMaxWidth: maxWidth,
17968
- panelRight: right,
17969
- panelTop: top,
17970
- rect
17971
- });
17972
- return candidates;
17973
- },
17974
- [
17975
- getSourceInspectorPanelPosition,
17976
- getSourceInspectorRect,
17977
- sourceCandidateOptions,
17978
- sourceOpenOptions
17979
- ]
17980
- );
17981
18691
  const showSourceOutlineForTarget = useCallback24(
17982
18692
  (target) => {
17983
18693
  const firstCandidate = getSourceCandidates(
@@ -17990,13 +18700,8 @@ function useReviewSourceInspector({
17990
18700
  return null;
17991
18701
  }
17992
18702
  setSourceInspectorState({
17993
- candidates: [],
17994
- isPinned: false,
17995
- panelLeft: 0,
17996
- panelMaxWidth: SOURCE_PANEL_MAX_WIDTH,
17997
- panelRight: null,
17998
- panelTop: 0,
17999
- rect
18703
+ rect,
18704
+ targetElement: firstCandidate.element
18000
18705
  });
18001
18706
  return firstCandidate;
18002
18707
  },
@@ -18007,52 +18712,91 @@ function useReviewSourceInspector({
18007
18712
  if (!isSourceTreeHoverOutlineEnabled) return;
18008
18713
  const rect = getSourceInspectorRect(element);
18009
18714
  if (!rect) {
18010
- setSourceInspectorState(
18011
- (current) => current?.isPinned ? current : null
18012
- );
18715
+ setSourceInspectorState(null);
18013
18716
  return;
18014
18717
  }
18015
- setSourceInspectorState(
18016
- (current) => current?.isPinned ? current : {
18017
- candidates: [],
18018
- isPinned: false,
18019
- panelLeft: 0,
18020
- panelMaxWidth: SOURCE_PANEL_MAX_WIDTH,
18021
- panelRight: null,
18022
- panelTop: 0,
18023
- rect
18024
- }
18025
- );
18718
+ setSourceInspectorState({ rect, targetElement: element });
18026
18719
  },
18027
18720
  [getSourceInspectorRect, isSourceTreeHoverOutlineEnabled]
18028
18721
  );
18722
+ const selectSourceOutlineForElement = useCallback24(
18723
+ (element) => {
18724
+ const rect = getSourceInspectorRect(element);
18725
+ setComponentSelectionState(
18726
+ rect ? { rect, targetElement: element } : null
18727
+ );
18728
+ },
18729
+ [getSourceInspectorRect]
18730
+ );
18731
+ const clearSourceOutlineSelection = useCallback24(() => {
18732
+ setComponentSelectionState(null);
18733
+ }, []);
18029
18734
  const clearSourceOutlineHover = useCallback24(() => {
18030
- setSourceInspectorState((current) => current?.isPinned ? current : null);
18735
+ setSourceInspectorState(null);
18031
18736
  }, []);
18032
- const openSourceCandidate = useCallback24(
18033
- (candidate) => {
18034
- const didOpen = openSourceInEditor(candidate.source, {
18035
- ...sourceOpenOptions,
18036
- omitPosition: !candidate.usesPosition
18737
+ const sourceInspectorTargetElement = sourceInspectorState?.targetElement ?? null;
18738
+ const componentSelectionTargetElement = componentSelectionState?.targetElement ?? null;
18739
+ useEffect22(() => {
18740
+ const trackedElement = sourceInspectorTargetElement ?? componentSelectionTargetElement;
18741
+ if (!trackedElement) return void 0;
18742
+ const targetWindow = trackedElement.ownerDocument.defaultView ?? iframeRef.current?.contentWindow ?? null;
18743
+ const frameScroll = frameScrollRef.current;
18744
+ if (!targetWindow) return void 0;
18745
+ let frameId = null;
18746
+ const scheduleUpdate = () => {
18747
+ if (frameId !== null) targetWindow.cancelAnimationFrame(frameId);
18748
+ frameId = targetWindow.requestAnimationFrame(() => {
18749
+ frameId = null;
18750
+ setSourceInspectorState((current) => {
18751
+ if (!current) return current;
18752
+ const rect = getSourceInspectorRect(current.targetElement);
18753
+ if (!rect) return null;
18754
+ return { ...current, rect };
18755
+ });
18756
+ setComponentSelectionState((current) => {
18757
+ if (!current) return current;
18758
+ const rect = getSourceInspectorRect(current.targetElement);
18759
+ if (!rect) return null;
18760
+ return { ...current, rect };
18761
+ });
18037
18762
  });
18038
- showToast(didOpen ? "Source opened" : "Source root required");
18039
- clearSourceInspector();
18040
- },
18041
- [clearSourceInspector, showToast, sourceOpenOptions]
18042
- );
18763
+ };
18764
+ targetWindow.addEventListener("scroll", scheduleUpdate, { passive: true });
18765
+ targetWindow.addEventListener("resize", scheduleUpdate);
18766
+ frameScroll?.addEventListener("scroll", scheduleUpdate, { passive: true });
18767
+ window.addEventListener("resize", scheduleUpdate);
18768
+ scheduleUpdate();
18769
+ return () => {
18770
+ if (frameId !== null) {
18771
+ targetWindow.cancelAnimationFrame(frameId);
18772
+ frameId = null;
18773
+ }
18774
+ targetWindow.removeEventListener("scroll", scheduleUpdate);
18775
+ targetWindow.removeEventListener("resize", scheduleUpdate);
18776
+ frameScroll?.removeEventListener("scroll", scheduleUpdate);
18777
+ window.removeEventListener("resize", scheduleUpdate);
18778
+ };
18779
+ }, [
18780
+ componentSelectionTargetElement,
18781
+ frameScrollRef,
18782
+ getSourceInspectorRect,
18783
+ iframeRef,
18784
+ sourceInspectorTargetElement
18785
+ ]);
18043
18786
  const cleanupSourceOpenShortcut = useCallback24(() => {
18044
18787
  sourceShortcutCleanupRef.current?.();
18045
18788
  sourceShortcutCleanupRef.current = null;
18046
18789
  }, []);
18047
18790
  const bindSourceOpenShortcut = useCallback24(() => {
18048
18791
  cleanupSourceOpenShortcut();
18792
+ setComponentSelectionState(null);
18049
18793
  let frameDocument = null;
18050
18794
  try {
18051
18795
  frameDocument = iframeRef.current?.contentDocument ?? null;
18052
18796
  } catch {
18053
18797
  return;
18054
18798
  }
18055
- if (!frameDocument || !isSourceInspectorEnabled) return;
18799
+ if (!frameDocument) return;
18056
18800
  const frameRoot = frameDocument.head ?? frameDocument.documentElement;
18057
18801
  const frameBody = frameDocument.body ?? frameDocument.documentElement;
18058
18802
  if (!frameRoot || !frameBody) return;
@@ -18072,7 +18816,6 @@ function useReviewSourceInspector({
18072
18816
  let hoveredElement = null;
18073
18817
  let lastSourceTarget = null;
18074
18818
  let isSourceSelecting = false;
18075
- let isSourcePanelPinned = false;
18076
18819
  const getFontHints = (element) => {
18077
18820
  if (!element) return [];
18078
18821
  const values = [];
@@ -18130,7 +18873,6 @@ function useReviewSourceInspector({
18130
18873
  isSourceSelecting = isSelecting;
18131
18874
  setTargetFigmaSourceSelectLocked(frameDocument, isSelecting);
18132
18875
  if (isSelecting) {
18133
- isSourcePanelPinned = false;
18134
18876
  frameDocument.documentElement.setAttribute(optionAttribute, "true");
18135
18877
  const candidate = showSourceOutlineForTarget(lastSourceTarget);
18136
18878
  setHoveredElement(candidate?.element ?? hoveredElement);
@@ -18139,48 +18881,63 @@ function useReviewSourceInspector({
18139
18881
  setHoveredElement(null);
18140
18882
  fontOverlay.hidden = true;
18141
18883
  frameDocument.documentElement.removeAttribute(optionAttribute);
18142
- if (!isSourcePanelPinned && !sourceInspectorInteractionRef.current) {
18143
- clearSourceInspector();
18144
- }
18884
+ clearSourceInspector();
18145
18885
  };
18146
- const handleMouseMove = (event) => {
18147
- if (isSourcePanelPinned) return;
18886
+ const handleTargetPointerMove = (event) => {
18148
18887
  lastSourceTarget = event.target;
18149
- const candidates = getSourceCandidates(event.target, sourceCandidateOptions);
18888
+ const candidates = getSourceCandidates(
18889
+ event.target,
18890
+ sourceCandidateOptions
18891
+ );
18150
18892
  const sourceElement = candidates[0]?.element ?? null;
18151
18893
  if (event.altKey && !isSourceSelecting) {
18152
18894
  setSourceSelecting(true);
18153
18895
  }
18154
- if (isSourceSelecting && !isSourcePanelPinned) {
18896
+ if (isSourceSelecting) {
18155
18897
  showSourceOutlineForTarget(event.target);
18156
18898
  }
18157
18899
  setHoveredElement(isSourceSelecting ? sourceElement : null);
18158
18900
  };
18159
- const handleClick = (event) => {
18901
+ const selectSourceTreeEntry = (event) => {
18160
18902
  if (!isSourceSelecting && !event.altKey) return;
18161
18903
  event.preventDefault();
18162
18904
  event.stopPropagation();
18163
18905
  event.stopImmediatePropagation();
18164
- const candidates = showSourceInspectorForTarget(event.target, true);
18165
- if (!candidates.length) {
18906
+ const candidates = getSourceCandidates(
18907
+ event.target,
18908
+ sourceCandidateOptions
18909
+ );
18910
+ const candidate = candidates.filter((item) => item.kind !== "data").sort((a, b) => a.depth - b.depth)[0] ?? candidates[0];
18911
+ if (!candidate) {
18166
18912
  showToast("Source hint not found");
18167
- isSourcePanelPinned = false;
18168
18913
  setSourceSelecting(false);
18169
18914
  return;
18170
18915
  }
18171
- isSourcePanelPinned = true;
18916
+ onRequestSourceTreeFocus?.(candidate.element);
18172
18917
  setSourceSelecting(false);
18173
18918
  };
18919
+ const handleClick = (event) => {
18920
+ selectSourceTreeEntry(event);
18921
+ };
18174
18922
  const isOptionKeyEvent = (event) => event.key === "Alt" || event.code === "AltLeft" || event.code === "AltRight" || event.altKey;
18923
+ const getActiveDomSelectButton = () => {
18924
+ const activeElement = document.activeElement;
18925
+ return activeElement instanceof HTMLButtonElement && activeElement.matches(
18926
+ ".df-review-section-outline-link.is-dom-select"
18927
+ ) ? activeElement : null;
18928
+ };
18929
+ const blurDomSelectButton = () => {
18930
+ getActiveDomSelectButton()?.blur();
18931
+ };
18175
18932
  const handleKeyDown = (event) => {
18176
18933
  if (event.key === "Escape") {
18177
- isSourcePanelPinned = false;
18934
+ onCancelReviewMode();
18178
18935
  setSourceSelecting(false);
18179
18936
  clearSourceInspector();
18937
+ blurDomSelectButton();
18180
18938
  return;
18181
18939
  }
18182
18940
  if (!isOptionKeyEvent(event)) return;
18183
- if (isSourcePanelPinned) return;
18184
18941
  onCancelReviewMode();
18185
18942
  setSourceSelecting(true);
18186
18943
  };
@@ -18188,39 +18945,63 @@ function useReviewSourceInspector({
18188
18945
  if (isOptionKeyEvent(event) || !event.altKey) setSourceSelecting(false);
18189
18946
  };
18190
18947
  const handleBlur = () => {
18191
- isSourcePanelPinned = false;
18192
18948
  setSourceSelecting(false);
18193
18949
  };
18194
18950
  const handleWindowPointerDown = (event) => {
18195
- const target = event.target;
18196
- if (target instanceof Element && target.closest(".df-review-source-popover")) {
18197
- sourceInspectorInteractionRef.current = true;
18951
+ setSourceSelecting(false);
18952
+ const activeElement = getActiveDomSelectButton();
18953
+ if (!activeElement || event.composedPath().includes(activeElement)) {
18198
18954
  return;
18199
18955
  }
18200
- isSourcePanelPinned = false;
18201
- sourceInspectorInteractionRef.current = false;
18202
- setSourceSelecting(false);
18203
- clearSourceInspector();
18956
+ const isComposerClick = event.composedPath().some((target) => {
18957
+ if (!(target instanceof Element)) return false;
18958
+ return Boolean(
18959
+ target.closest(".df-review-qa-draft-host, .dfwr-dom-popover")
18960
+ );
18961
+ });
18962
+ if (isComposerClick) return;
18963
+ onCancelReviewMode();
18964
+ activeElement.blur();
18204
18965
  };
18205
- frameDocument.addEventListener("mousemove", handleMouseMove, true);
18966
+ frameDocument.addEventListener("mousemove", handleTargetPointerMove, true);
18967
+ frameDocument.addEventListener("pointermove", handleTargetPointerMove, true);
18206
18968
  frameDocument.addEventListener("click", handleClick, true);
18207
18969
  frameDocument.addEventListener("keydown", handleKeyDown, true);
18208
18970
  frameDocument.addEventListener("keyup", handleKeyUp, true);
18971
+ frameDocument.addEventListener(
18972
+ "pointerdown",
18973
+ handleWindowPointerDown,
18974
+ true
18975
+ );
18209
18976
  window.addEventListener("keydown", handleKeyDown, true);
18210
18977
  window.addEventListener("keyup", handleKeyUp, true);
18211
18978
  window.addEventListener("blur", handleBlur);
18212
18979
  window.addEventListener("pointerdown", handleWindowPointerDown, true);
18213
18980
  sourceShortcutCleanupRef.current = () => {
18214
- frameDocument.removeEventListener("mousemove", handleMouseMove, true);
18981
+ frameDocument.removeEventListener(
18982
+ "mousemove",
18983
+ handleTargetPointerMove,
18984
+ true
18985
+ );
18986
+ frameDocument.removeEventListener(
18987
+ "pointermove",
18988
+ handleTargetPointerMove,
18989
+ true
18990
+ );
18215
18991
  frameDocument.removeEventListener("click", handleClick, true);
18216
18992
  frameDocument.removeEventListener("keydown", handleKeyDown, true);
18217
18993
  frameDocument.removeEventListener("keyup", handleKeyUp, true);
18994
+ frameDocument.removeEventListener(
18995
+ "pointerdown",
18996
+ handleWindowPointerDown,
18997
+ true
18998
+ );
18218
18999
  window.removeEventListener("keydown", handleKeyDown, true);
18219
19000
  window.removeEventListener("keyup", handleKeyUp, true);
18220
19001
  window.removeEventListener("blur", handleBlur);
18221
19002
  window.removeEventListener("pointerdown", handleWindowPointerDown, true);
18222
- isSourcePanelPinned = false;
18223
19003
  setSourceSelecting(false);
19004
+ blurDomSelectButton();
18224
19005
  style.remove();
18225
19006
  fontOverlay.remove();
18226
19007
  };
@@ -18229,11 +19010,10 @@ function useReviewSourceInspector({
18229
19010
  clearSourceInspector,
18230
19011
  cleanupSourceOpenShortcut,
18231
19012
  iframeRef,
18232
- isSourceInspectorEnabled,
19013
+ onRequestSourceTreeFocus,
18233
19014
  showToast,
18234
19015
  sourceCandidateOptions,
18235
- showSourceOutlineForTarget,
18236
- showSourceInspectorForTarget
19016
+ showSourceOutlineForTarget
18237
19017
  ]);
18238
19018
  useEffect22(() => {
18239
19019
  return cleanupSourceOpenShortcut;
@@ -18246,9 +19026,10 @@ function useReviewSourceInspector({
18246
19026
  bindSourceOpenShortcut,
18247
19027
  clearSourceInspector,
18248
19028
  clearSourceOutlineHover,
18249
- openSourceCandidate,
19029
+ clearSourceOutlineSelection,
19030
+ componentSelectionState,
19031
+ selectSourceOutlineForElement,
18250
19032
  showSourceOutlineForElement,
18251
- sourceInspectorInteractionRef,
18252
19033
  sourceInspectorState
18253
19034
  };
18254
19035
  }
@@ -18288,6 +19069,7 @@ var useReviewTargetNavigation = ({
18288
19069
  ) : currentSize;
18289
19070
  const nextAdapter = sourceEntries.find((entry) => entry.label === nextSource) ?? activeAdapterEntry;
18290
19071
  const isCurrentTarget = state.target === normalizedTarget && source === nextSource && currentSize.width === nextSize.width && currentSize.height === nextSize.height;
19072
+ const shouldNavigateFrame = state.target !== normalizedTarget || state.frameTarget !== normalizedTarget;
18291
19073
  if (parsedInput.itemId) {
18292
19074
  const item = await nextAdapter.adapter.get(parsedInput.itemId);
18293
19075
  if (item) {
@@ -18304,8 +19086,11 @@ var useReviewTargetNavigation = ({
18304
19086
  state.setDraftTarget(normalizedTarget);
18305
19087
  state.setSize(nextSize);
18306
19088
  state.setTarget(normalizedTarget);
19089
+ if (shouldNavigateFrame) {
19090
+ state.navigateFrameTarget(normalizedTarget);
19091
+ }
18307
19092
  updateShellUrl(normalizedTarget, nextSize, nextSource);
18308
- if (isCurrentTarget) onReloadTargetFrame();
19093
+ if (isCurrentTarget && !shouldNavigateFrame) onReloadTargetFrame();
18309
19094
  }, [
18310
19095
  activeAdapterEntry,
18311
19096
  onClearSelectedItem,
@@ -18326,10 +19111,14 @@ var useReviewTargetNavigation = ({
18326
19111
  );
18327
19112
  onClearSelectedItem();
18328
19113
  const state = storeApi.getState();
19114
+ const shouldNavigateFrame = state.target !== normalizedTarget || state.frameTarget !== normalizedTarget;
18329
19115
  state.setIsAllQaVisible(false);
18330
19116
  state.setActiveRoute(normalizedRoute);
18331
19117
  state.setDraftTarget(normalizedTarget);
18332
19118
  state.setTarget(normalizedTarget);
19119
+ if (shouldNavigateFrame) {
19120
+ state.navigateFrameTarget(normalizedTarget);
19121
+ }
18333
19122
  updateShellUrl(normalizedTarget, state.size, source);
18334
19123
  state.setIsSitemapOpen(false);
18335
19124
  },
@@ -18413,11 +19202,10 @@ var useReviewShellRuntime = ({
18413
19202
  const isItemEditing = useReviewShellStore(
18414
19203
  (state) => Boolean(state.editingItem)
18415
19204
  );
19205
+ const selectedItemId = useReviewShellStore((state) => state.selectedItemId);
18416
19206
  const {
18417
- isSourceInspectorEnabled,
18418
19207
  isSourceTreeHoverOutlineEnabled,
18419
- sourceCandidateOptions,
18420
- sourceOpenOptions
19208
+ sourceCandidateOptions
18421
19209
  } = useReviewShellConfig();
18422
19210
  const {
18423
19211
  figmaImagesController,
@@ -18434,8 +19222,7 @@ var useReviewShellRuntime = ({
18434
19222
  openSidePanel,
18435
19223
  toggleSidePanel
18436
19224
  } = useReviewSidePanel({
18437
- isFigmaImageManagementEnabled,
18438
- isSourceInspectorEnabled
19225
+ isFigmaImageManagementEnabled
18439
19226
  });
18440
19227
  const {
18441
19228
  activeItems,
@@ -18476,6 +19263,15 @@ var useReviewShellRuntime = ({
18476
19263
  setIsSitemapOpen,
18477
19264
  setMode
18478
19265
  });
19266
+ const requestSourceTreeFocus = useCallback26(
19267
+ (element) => {
19268
+ const state = storeApi.getState();
19269
+ state.setSidePanel("source");
19270
+ state.setIsListVisible(true);
19271
+ state.setSourceTreeFocusRequest(element);
19272
+ },
19273
+ [storeApi]
19274
+ );
18479
19275
  const reviewSettings = useReviewSettings({
18480
19276
  defaultReviewUserId: activeAdapterEntry.defaultUserId,
18481
19277
  onCancelReviewMode: cancelReviewMode,
@@ -18572,12 +19368,14 @@ var useReviewShellRuntime = ({
18572
19368
  });
18573
19369
  const setReviewMode = useReviewShellModeSetter({
18574
19370
  closeRuler,
19371
+ isListVisible,
18575
19372
  mode,
18576
19373
  openSidePanel,
18577
19374
  setControllerReviewMode,
18578
19375
  writeModes: activeAdapterEntry.writeModes
18579
19376
  });
18580
19377
  useReviewShellEffects({
19378
+ clearSelectedReviewItem,
18581
19379
  frameScrollRef,
18582
19380
  iframeRef,
18583
19381
  isListVisible,
@@ -18585,23 +19383,27 @@ var useReviewShellRuntime = ({
18585
19383
  mode,
18586
19384
  pendingInitialItemIdRef,
18587
19385
  restoreReviewItem,
19386
+ selectedItemId,
18588
19387
  size,
18589
19388
  syncTargetViewport,
19389
+ targetFrameLoadVersion,
18590
19390
  targetSrc
18591
19391
  });
18592
19392
  const sourceInspector = useReviewSourceInspector({
19393
+ frameScrollRef,
18593
19394
  iframeRef,
18594
- isSourceInspectorEnabled,
18595
19395
  isSourceTreeHoverOutlineEnabled,
18596
19396
  sourceCandidateOptions,
18597
- sourceOpenOptions,
18598
19397
  targetSrc,
18599
- onCancelReviewMode: cancelReviewMode
19398
+ onCancelReviewMode: cancelReviewMode,
19399
+ onRequestSourceTreeFocus: requestSourceTreeFocus
18600
19400
  });
18601
19401
  const {
18602
19402
  bindSourceOpenShortcut,
18603
19403
  clearSourceInspector,
18604
19404
  clearSourceOutlineHover,
19405
+ clearSourceOutlineSelection,
19406
+ selectSourceOutlineForElement,
18605
19407
  showSourceOutlineForElement
18606
19408
  } = sourceInspector;
18607
19409
  const {
@@ -18610,7 +19412,6 @@ var useReviewShellRuntime = ({
18610
19412
  toggleSourceTreePanel
18611
19413
  } = useReviewShellPanelActions({
18612
19414
  isFigmaImageManagementEnabled,
18613
- isSourceInspectorEnabled,
18614
19415
  toggleSidePanel
18615
19416
  });
18616
19417
  const figmaOverlayState = useReviewShellFigmaOverlay({
@@ -18650,6 +19451,7 @@ var useReviewShellRuntime = ({
18650
19451
  changeReviewSource,
18651
19452
  clearSourceInspector,
18652
19453
  clearSourceOutlineHover,
19454
+ clearSourceOutlineSelection,
18653
19455
  clearSelectedReviewItem,
18654
19456
  getPageTarget,
18655
19457
  initReviewKit,
@@ -18659,6 +19461,7 @@ var useReviewShellRuntime = ({
18659
19461
  restoreReviewItem,
18660
19462
  selectAllQa,
18661
19463
  selectPage,
19464
+ selectSourceOutlineForElement,
18662
19465
  setIsInitialPromptOpen,
18663
19466
  setIsInitialPromptScriptOpen,
18664
19467
  setReviewMode,
@@ -18751,6 +19554,8 @@ var getInitialTargetSliceState = (config) => {
18751
19554
  return {
18752
19555
  activeRoute: getTargetRouteKey(target, config.reviewPathPrefix),
18753
19556
  draftTarget: target,
19557
+ frameNavigationVersion: 0,
19558
+ frameTarget: target,
18754
19559
  size: getInitialSize(config.viewportPresets),
18755
19560
  source,
18756
19561
  target,
@@ -18762,6 +19567,10 @@ var getInitialTargetSliceState = (config) => {
18762
19567
  };
18763
19568
  var createTargetSlice = (initialState) => (set) => ({
18764
19569
  ...initialState,
19570
+ navigateFrameTarget: (frameTarget) => set((state) => ({
19571
+ frameNavigationVersion: state.frameNavigationVersion + 1,
19572
+ frameTarget
19573
+ })),
18765
19574
  setActiveRoute: (activeRoute) => set({ activeRoute }),
18766
19575
  setDraftTarget: (draftTarget) => set({ draftTarget }),
18767
19576
  setSize: (size) => set({ size }),
@@ -18777,6 +19586,7 @@ var createUiSlice = (set) => ({
18777
19586
  isInitialPromptScriptOpen: false,
18778
19587
  isSitemapOpen: false,
18779
19588
  mode: "idle",
19589
+ sourceTreeFocusRequest: null,
18780
19590
  targetFrameLoadVersion: 0,
18781
19591
  toastMessage: "",
18782
19592
  bumpTargetFrameLoadVersion: () => set((state) => ({
@@ -18798,6 +19608,12 @@ var createUiSlice = (set) => ({
18798
19608
  isSitemapOpen: resolveSetStateAction(value, state.isSitemapOpen)
18799
19609
  })),
18800
19610
  setMode: (mode) => set({ mode }),
19611
+ setSourceTreeFocusRequest: (element) => set((state) => ({
19612
+ sourceTreeFocusRequest: element ? {
19613
+ element,
19614
+ version: (state.sourceTreeFocusRequest?.version ?? 0) + 1
19615
+ } : null
19616
+ })),
18801
19617
  setToastMessage: (value) => set((state) => ({
18802
19618
  toastMessage: resolveSetStateAction(value, state.toastMessage)
18803
19619
  }))
@@ -18812,7 +19628,7 @@ var createReviewShellStore = (init) => createStore()((...args) => ({
18812
19628
  }));
18813
19629
 
18814
19630
  // src/react-shell/review/shell.tsx
18815
- import { jsx as jsx40 } from "react/jsx-runtime";
19631
+ import { jsx as jsx41 } from "react/jsx-runtime";
18816
19632
  var ReviewShell = (props) => {
18817
19633
  const config = useMemo18(
18818
19634
  () => createReviewShellConfig(props),
@@ -18832,36 +19648,36 @@ var ReviewShell = (props) => {
18832
19648
  () => createReviewShellStore({ target: getInitialTargetSliceState(config) })
18833
19649
  );
18834
19650
  const [refs] = useState18(createReviewShellRefs);
18835
- return /* @__PURE__ */ jsx40(ReviewShellConfigProvider, { value: config, children: /* @__PURE__ */ jsx40(ReviewShellStoreProvider, { value: store, children: /* @__PURE__ */ jsx40(ReviewShellRefsProvider, { value: refs, children: /* @__PURE__ */ jsx40(ReviewShellContent, { ...props }) }) }) });
19651
+ return /* @__PURE__ */ jsx41(ReviewShellConfigProvider, { value: config, children: /* @__PURE__ */ jsx41(ReviewShellStoreProvider, { value: store, children: /* @__PURE__ */ jsx41(ReviewShellRefsProvider, { value: refs, children: /* @__PURE__ */ jsx41(ReviewShellContent, { ...props }) }) }) });
18836
19652
  };
18837
19653
  var ReviewShellContent = (props) => {
18838
19654
  const runtime = useReviewShellRuntime(props);
18839
- return /* @__PURE__ */ jsx40(ReviewShellProviders, { ...runtime, children: /* @__PURE__ */ jsx40(
19655
+ return /* @__PURE__ */ jsx41(ReviewShellProviders, { ...runtime, children: /* @__PURE__ */ jsx41(
18840
19656
  ReviewShellFrameContainer,
18841
19657
  {
18842
19658
  slots: {
18843
- topbar: /* @__PURE__ */ jsx40(TopbarContainer, {}),
18844
- modals: /* @__PURE__ */ jsx40(ReviewShellModalsContainer, {}),
18845
- toast: /* @__PURE__ */ jsx40(ReviewToastContainer, {}),
18846
- sideRail: /* @__PURE__ */ jsx40(ReviewSideRailContainer, {}),
18847
- qaPanel: /* @__PURE__ */ jsx40(QaPanelContainer, {}),
18848
- figmaImagesPanel: /* @__PURE__ */ jsx40(FigmaImagesPanelContainer, {}),
18849
- sourceTreePanel: /* @__PURE__ */ jsx40(SectionOutlineContainer, {}),
18850
- targetFrame: /* @__PURE__ */ jsx40(ReviewTargetFrame, {}),
18851
- sourceInspector: /* @__PURE__ */ jsx40(SourceInspectorOverlayContainer, {})
19659
+ topbar: /* @__PURE__ */ jsx41(TopbarContainer, {}),
19660
+ modals: /* @__PURE__ */ jsx41(ReviewShellModalsContainer, {}),
19661
+ toast: /* @__PURE__ */ jsx41(ReviewToastContainer, {}),
19662
+ sideRail: /* @__PURE__ */ jsx41(ReviewSideRailContainer, {}),
19663
+ qaPanel: /* @__PURE__ */ jsx41(QaPanelContainer, {}),
19664
+ figmaImagesPanel: /* @__PURE__ */ jsx41(FigmaImagesPanelContainer, {}),
19665
+ sourceTreePanel: /* @__PURE__ */ jsx41(SectionOutlineContainer, {}),
19666
+ targetFrame: /* @__PURE__ */ jsx41(ReviewTargetFrame, {}),
19667
+ sourceInspector: /* @__PURE__ */ jsx41(SourceInspectorOverlayContainer, {})
18852
19668
  }
18853
19669
  }
18854
19670
  ) });
18855
19671
  };
18856
19672
 
18857
19673
  // src/react-shell/figma/dev-overlay.tsx
18858
- import React, {
19674
+ import React2, {
18859
19675
  useEffect as useEffect23,
18860
19676
  useMemo as useMemo19,
18861
19677
  useState as useState19
18862
19678
  } from "react";
18863
19679
  import { createRoot } from "react-dom/client";
18864
- import { jsx as jsx41, jsxs as jsxs29 } from "react/jsx-runtime";
19680
+ import { jsx as jsx42, jsxs as jsxs29 } from "react/jsx-runtime";
18865
19681
  var FIGMA_DEV_OVERLAY_ROOT_ID = "df-review-figma-dev-overlay-root";
18866
19682
  var FIGMA_DEV_OVERLAY_MOUNT_ID = "df-review-figma-dev-overlay-mount";
18867
19683
  var mountFigmaDevOverlay = (options) => {
@@ -18882,7 +19698,7 @@ var mountFigmaDevOverlay = (options) => {
18882
19698
  document.body.appendChild(host);
18883
19699
  const root = createRoot(mountNode);
18884
19700
  root.render(
18885
- /* @__PURE__ */ jsx41(React.StrictMode, { children: /* @__PURE__ */ jsx41(FigmaDevOverlayWidget, { ...options }) })
19701
+ /* @__PURE__ */ jsx42(React2.StrictMode, { children: /* @__PURE__ */ jsx42(FigmaDevOverlayWidget, { ...options }) })
18886
19702
  );
18887
19703
  return {
18888
19704
  destroy() {
@@ -19003,13 +19819,13 @@ var FigmaDevOverlayWidget = ({
19003
19819
  children: [
19004
19820
  isPanelOpen && /* @__PURE__ */ jsxs29("div", { className: "df-review-figma-dev-panel", children: [
19005
19821
  /* @__PURE__ */ jsxs29("div", { className: "df-review-figma-dev-panel-header", children: [
19006
- /* @__PURE__ */ jsx41("strong", { children: "Figma" }),
19007
- /* @__PURE__ */ jsx41("span", { children: matchedViewportMatch ? `${matchedViewportMatch.label} \xB7 ${matchedViewportMatch.rangeLabel}` : `${viewport.width}px` })
19822
+ /* @__PURE__ */ jsx42("strong", { children: "Figma" }),
19823
+ /* @__PURE__ */ jsx42("span", { children: matchedViewportMatch ? `${matchedViewportMatch.label} \xB7 ${matchedViewportMatch.rangeLabel}` : `${viewport.width}px` })
19008
19824
  ] }),
19009
19825
  selectedImage && /* @__PURE__ */ jsxs29("div", { className: "df-review-figma-dev-selected-controls", children: [
19010
19826
  /* @__PURE__ */ jsxs29("label", { className: "df-review-figma-dev-opacity-control", children: [
19011
- /* @__PURE__ */ jsx41("span", { children: "Opacity" }),
19012
- /* @__PURE__ */ jsx41(
19827
+ /* @__PURE__ */ jsx42("span", { children: "Opacity" }),
19828
+ /* @__PURE__ */ jsx42(
19013
19829
  "input",
19014
19830
  {
19015
19831
  "aria-label": `${selectedImageLabel} overlay opacity`,
@@ -19022,11 +19838,11 @@ var FigmaDevOverlayWidget = ({
19022
19838
  onInput: (event) => updateSelectedImageOpacity(event.currentTarget.value)
19023
19839
  }
19024
19840
  ),
19025
- /* @__PURE__ */ jsx41("strong", { children: selectedOpacityPercent })
19841
+ /* @__PURE__ */ jsx42("strong", { children: selectedOpacityPercent })
19026
19842
  ] }),
19027
19843
  /* @__PURE__ */ jsxs29("label", { className: "df-review-figma-dev-y-control", children: [
19028
- /* @__PURE__ */ jsx41(MoveVertical, { "aria-hidden": "true" }),
19029
- /* @__PURE__ */ jsx41(
19844
+ /* @__PURE__ */ jsx42(MoveVertical, { "aria-hidden": "true" }),
19845
+ /* @__PURE__ */ jsx42(
19030
19846
  "input",
19031
19847
  {
19032
19848
  "aria-label": `${selectedImageLabel} overlay Y offset`,
@@ -19056,11 +19872,11 @@ var FigmaDevOverlayWidget = ({
19056
19872
  )
19057
19873
  ] })
19058
19874
  ] }),
19059
- error && /* @__PURE__ */ jsx41("p", { className: "df-review-figma-dev-status", children: error }),
19875
+ error && /* @__PURE__ */ jsx42("p", { className: "df-review-figma-dev-status", children: error }),
19060
19876
  !matchedViewport ? /* @__PURE__ */ jsxs29("p", { className: "df-review-figma-dev-empty", children: [
19061
19877
  "No Figma layers for this viewport.",
19062
19878
  viewportBoundaries ? ` Mobile ${viewportBoundaries.mobileRangeLabel} / Full width ${viewportBoundaries.fullWidthRangeLabel}` : ""
19063
- ] }) : isLoading ? /* @__PURE__ */ jsx41("p", { className: "df-review-figma-dev-status", children: "Loading..." }) : images.length === 0 ? /* @__PURE__ */ jsx41("p", { className: "df-review-figma-dev-empty", children: "No Figma layers for this viewport." }) : /* @__PURE__ */ jsx41("div", { className: "df-review-figma-dev-list", children: images.map((image, index) => {
19879
+ ] }) : isLoading ? /* @__PURE__ */ jsx42("p", { className: "df-review-figma-dev-status", children: "Loading..." }) : images.length === 0 ? /* @__PURE__ */ jsx42("p", { className: "df-review-figma-dev-empty", children: "No Figma layers for this viewport." }) : /* @__PURE__ */ jsx42("div", { className: "df-review-figma-dev-list", children: images.map((image, index) => {
19064
19880
  const imageLabel = getFigmaImageLabel(image, index);
19065
19881
  const overlayState = imageOverlayStates[image.id] ?? DEFAULT_FIGMA_IMAGE_LAYER_STATE;
19066
19882
  return /* @__PURE__ */ jsxs29(
@@ -19076,7 +19892,7 @@ var FigmaDevOverlayWidget = ({
19076
19892
  setSelectedImageId(image.id);
19077
19893
  },
19078
19894
  children: [
19079
- /* @__PURE__ */ jsx41(
19895
+ /* @__PURE__ */ jsx42(
19080
19896
  FigmaImageLayerStateButtons,
19081
19897
  {
19082
19898
  imageLabel,
@@ -19089,8 +19905,8 @@ var FigmaDevOverlayWidget = ({
19089
19905
  }
19090
19906
  ),
19091
19907
  /* @__PURE__ */ jsxs29("span", { className: "df-review-figma-dev-row-main", children: [
19092
- /* @__PURE__ */ jsx41("strong", { children: imageLabel }),
19093
- /* @__PURE__ */ jsx41("small", { children: formatFigmaImageDate(image.updatedAt) })
19908
+ /* @__PURE__ */ jsx42("strong", { children: imageLabel }),
19909
+ /* @__PURE__ */ jsx42("small", { children: formatFigmaImageDate(image.updatedAt) })
19094
19910
  ] })
19095
19911
  ]
19096
19912
  },
@@ -19098,7 +19914,7 @@ var FigmaDevOverlayWidget = ({
19098
19914
  );
19099
19915
  }) })
19100
19916
  ] }),
19101
- /* @__PURE__ */ jsx41("div", { className: "df-review-figma-dev-bar", children: /* @__PURE__ */ jsxs29(
19917
+ /* @__PURE__ */ jsx42("div", { className: "df-review-figma-dev-bar", children: /* @__PURE__ */ jsxs29(
19102
19918
  "button",
19103
19919
  {
19104
19920
  "aria-expanded": isPanelOpen,
@@ -19108,8 +19924,8 @@ var FigmaDevOverlayWidget = ({
19108
19924
  type: "button",
19109
19925
  onClick: () => setIsPanelOpen((isOpen) => !isOpen),
19110
19926
  children: [
19111
- /* @__PURE__ */ jsx41(FigmaMarkIcon, {}),
19112
- /* @__PURE__ */ jsx41("span", { className: "df-review-figma-dev-button-count", children: images.length })
19927
+ /* @__PURE__ */ jsx42(FigmaMarkIcon, {}),
19928
+ /* @__PURE__ */ jsx42("span", { className: "df-review-figma-dev-button-count", children: images.length })
19113
19929
  ]
19114
19930
  }
19115
19931
  ) })
@@ -19700,7 +20516,7 @@ var createSupabasePresenceAdapter = ({
19700
20516
  });
19701
20517
 
19702
20518
  // src/react-shell.tsx
19703
- import { jsx as jsx42 } from "react/jsx-runtime";
20519
+ import { jsx as jsx43 } from "react/jsx-runtime";
19704
20520
  var mountReviewShell = (options) => {
19705
20521
  if (typeof document === "undefined" || !document.head) return;
19706
20522
  const { rootId = "root", ...shellProps } = options;
@@ -19711,7 +20527,7 @@ var mountReviewShell = (options) => {
19711
20527
  root.style.height = "100%";
19712
20528
  root.style.margin = "0";
19713
20529
  createRoot2(root).render(
19714
- /* @__PURE__ */ jsx42(React2.StrictMode, { children: /* @__PURE__ */ jsx42(ReviewShell, { ...shellProps }) })
20530
+ /* @__PURE__ */ jsx43(React3.StrictMode, { children: /* @__PURE__ */ jsx43(ReviewShell, { ...shellProps }) })
19715
20531
  );
19716
20532
  };
19717
20533
  export {
@@ -19760,11 +20576,13 @@ lucide-react/dist/esm/icons/maximize-2.mjs:
19760
20576
  lucide-react/dist/esm/icons/monitor.mjs:
19761
20577
  lucide-react/dist/esm/icons/moon.mjs:
19762
20578
  lucide-react/dist/esm/icons/move-vertical.mjs:
20579
+ lucide-react/dist/esm/icons/move.mjs:
19763
20580
  lucide-react/dist/esm/icons/network.mjs:
19764
20581
  lucide-react/dist/esm/icons/pencil.mjs:
19765
20582
  lucide-react/dist/esm/icons/plus.mjs:
19766
20583
  lucide-react/dist/esm/icons/rectangle-horizontal.mjs:
19767
20584
  lucide-react/dist/esm/icons/refresh-cw.mjs:
20585
+ lucide-react/dist/esm/icons/rotate-ccw.mjs:
19768
20586
  lucide-react/dist/esm/icons/ruler.mjs:
19769
20587
  lucide-react/dist/esm/icons/scan.mjs:
19770
20588
  lucide-react/dist/esm/icons/search.mjs: