@designfever/web-review-kit 0.8.2 → 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,10 +5,12 @@ import {
5
5
  createWebReviewKit,
6
6
  getBoundMarkerPoint,
7
7
  getDraftViewportScale,
8
+ getErrorMessage,
8
9
  getHotkeyActionKey,
9
10
  getItemHighlightSelection,
10
11
  getNumberedReviewItems,
11
12
  getReviewViewportScope,
13
+ isEditableEventTarget,
12
14
  isHotkey,
13
15
  isPointInViewport,
14
16
  normalizeReviewItemStatus,
@@ -16,7 +18,7 @@ import {
16
18
  runWithAutoScrollBehavior,
17
19
  shouldShowMarkerForScope,
18
20
  toHostPoint
19
- } from "./chunk-ZWJNUOYV.js";
21
+ } from "./chunk-FWN7RQCW.js";
20
22
 
21
23
  // src/react-shell.tsx
22
24
  import React3 from "react";
@@ -452,6 +454,11 @@ var reviewShellSitemapStyle = `
452
454
  padding: 18px;
453
455
  }
454
456
 
457
+ /* \uB2EB\uC544\uB3C4 unmount \uD558\uC9C0 \uC54A\uACE0 \uC228\uAE34\uB2E4. visibility \uB294 \uB9AC\uC2A4\uD2B8 \uC2A4\uD06C\uB864 \uC704\uCE58\uB97C \uBCF4\uC874\uD55C\uB2E4. */
458
+ .df-review-sitemap-modal.is-hidden {
459
+ visibility: hidden;
460
+ }
461
+
455
462
  .df-review-sitemap-backdrop {
456
463
  position: absolute;
457
464
  inset: 0;
@@ -504,7 +511,7 @@ var reviewShellSitemapStyle = `
504
511
  font-weight: var(--df-review-font-weight-normal);
505
512
  }
506
513
 
507
- .df-review-sitemap-header button {
514
+ .df-review-sitemap-header > button {
508
515
  display: grid;
509
516
  place-items: center;
510
517
  width: 34px;
@@ -518,11 +525,36 @@ var reviewShellSitemapStyle = `
518
525
  font-weight: var(--df-review-font-weight-normal);
519
526
  }
520
527
 
521
- .df-review-sitemap-header button:hover {
528
+ .df-review-sitemap-header > button:hover {
522
529
  border-color: var(--df-review-accent);
523
530
  background: var(--df-review-control-hover);
524
531
  }
525
532
 
533
+ /* \uD5E4\uB354 \uC694\uC57D \uCE74\uC6B4\uD2B8\uB97C \uADF8\uB300\uB85C status filter \uD1A0\uAE00\uB85C \uC4F4\uB2E4. */
534
+ .df-review-sitemap-summary-filter {
535
+ display: inline;
536
+ border: 0;
537
+ padding: 0;
538
+ background: none;
539
+ color: var(--df-review-muted);
540
+ font: inherit;
541
+ cursor: pointer;
542
+ }
543
+
544
+ .df-review-sitemap-summary-filter:hover,
545
+ .df-review-sitemap-summary-filter:focus-visible {
546
+ color: var(--df-review-text);
547
+ text-decoration: underline;
548
+ text-underline-offset: 3px;
549
+ outline: none;
550
+ }
551
+
552
+ .df-review-sitemap-summary-filter.is-active {
553
+ color: var(--df-review-accent);
554
+ text-decoration: underline;
555
+ text-underline-offset: 3px;
556
+ }
557
+
526
558
  .df-review-sitemap-controls {
527
559
  display: flex;
528
560
  align-items: center;
@@ -2301,6 +2333,8 @@ var reviewShellQaPanelStyle = `
2301
2333
 
2302
2334
  .df-review-qa-draft-host[data-has-draft-composer="true"] {
2303
2335
  display: block;
2336
+ /* Source Tree \uD328\uB110(z 900) \uC704\uB85C \uC62C\uB824 draft composer \uAC00 \uAC00\uB824\uC9C0\uC9C0 \uC54A\uAC8C \uD55C\uB2E4. */
2337
+ z-index: 950;
2304
2338
  }
2305
2339
 
2306
2340
  .df-review-shell:not(.is-list-visible) .df-review-qa-panel,
@@ -5317,7 +5351,7 @@ function ensureReviewShellStyle() {
5317
5351
  // src/react-shell/review/shell.tsx
5318
5352
  import {
5319
5353
  useMemo as useMemo18,
5320
- useState as useState18
5354
+ useState as useState19
5321
5355
  } from "react";
5322
5356
 
5323
5357
  // src/react-shell/store/store.context.tsx
@@ -6190,11 +6224,140 @@ function getReviewFigmaImageErrorMessage(error) {
6190
6224
  return error instanceof Error ? error.message : "Figma image request failed.";
6191
6225
  }
6192
6226
 
6193
- // src/react-shell/figma/image.overlay.controller.ts
6227
+ // src/react-shell/figma/image.overlay.state.ts
6228
+ var STORAGE_KEY_PREFIX = "df-review-figma-image-overlay-state:";
6229
+ var STORAGE_VERSION = 2;
6230
+ var DEFAULT_MODE = "normal";
6194
6231
  var DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_OPACITY = 0.48;
6195
- var REVIEW_FIGMA_IMAGE_OVERLAY_STORAGE_KEY_PREFIX = "df-review-figma-image-overlay-state:";
6196
- var REVIEW_FIGMA_IMAGE_OVERLAY_STORAGE_VERSION = 2;
6197
- var DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_MODE = "normal";
6232
+ var DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_STATE = {
6233
+ selectedImageId: null,
6234
+ imageStates: {},
6235
+ lastVisibleImageIds: []
6236
+ };
6237
+ var DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_ITEM_STATE = {
6238
+ isVisible: false,
6239
+ opacity: DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_OPACITY,
6240
+ isLocked: false,
6241
+ mode: DEFAULT_MODE,
6242
+ offsetY: 0
6243
+ };
6244
+ function createReviewFigmaImageOverlayStorageKey(target) {
6245
+ return `${STORAGE_KEY_PREFIX}${createReviewFigmaImageTargetKey(target)}`;
6246
+ }
6247
+ function readStoredReviewFigmaImageOverlayState(storageKey) {
6248
+ if (typeof window === "undefined") {
6249
+ return DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_STATE;
6250
+ }
6251
+ try {
6252
+ const value = window.localStorage.getItem(storageKey);
6253
+ if (!value) return DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_STATE;
6254
+ return normalizeReviewFigmaImageOverlayState(JSON.parse(value));
6255
+ } catch {
6256
+ return DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_STATE;
6257
+ }
6258
+ }
6259
+ function writeStoredReviewFigmaImageOverlayState(storageKey, state) {
6260
+ if (typeof window === "undefined") return;
6261
+ try {
6262
+ if (isDefaultReviewFigmaImageOverlayState(state)) {
6263
+ window.localStorage.removeItem(storageKey);
6264
+ return;
6265
+ }
6266
+ window.localStorage.setItem(
6267
+ storageKey,
6268
+ JSON.stringify({
6269
+ version: STORAGE_VERSION,
6270
+ ...state
6271
+ })
6272
+ );
6273
+ } catch {
6274
+ return;
6275
+ }
6276
+ }
6277
+ function normalizeReviewFigmaImageOverlayMode(value) {
6278
+ return value === "invert" ? "invert" : DEFAULT_MODE;
6279
+ }
6280
+ function normalizeReviewFigmaImageOverlayOffsetY(value) {
6281
+ if (typeof value !== "number" || !Number.isFinite(value)) return 0;
6282
+ return Math.round(value);
6283
+ }
6284
+ function clampReviewFigmaImageOverlayOpacity(value) {
6285
+ if (!Number.isFinite(value)) return DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_OPACITY;
6286
+ return Math.min(1, Math.max(0, value));
6287
+ }
6288
+ function getReviewFigmaImageOverlayItemState(state, imageId) {
6289
+ return imageId ? state.imageStates[imageId] ?? DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_ITEM_STATE : DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_ITEM_STATE;
6290
+ }
6291
+ function updateSelectedReviewFigmaImageOverlayItemState(state, updater) {
6292
+ return state.selectedImageId ? updateReviewFigmaImageOverlayItemState(
6293
+ state.imageStates,
6294
+ state.selectedImageId,
6295
+ updater
6296
+ ) : state.imageStates;
6297
+ }
6298
+ function updateReviewFigmaImageOverlayItemState(imageStates, imageId, updater) {
6299
+ return {
6300
+ ...imageStates,
6301
+ [imageId]: updater(
6302
+ imageStates[imageId] ?? DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_ITEM_STATE
6303
+ )
6304
+ };
6305
+ }
6306
+ function normalizeReviewFigmaImageOverlayState(value) {
6307
+ if (!value || typeof value !== "object") {
6308
+ return DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_STATE;
6309
+ }
6310
+ const state = value;
6311
+ const selectedImageId = typeof state.selectedImageId === "string" ? state.selectedImageId : null;
6312
+ const lastVisibleImageIds = Array.isArray(state.lastVisibleImageIds) ? state.lastVisibleImageIds.filter(
6313
+ (imageId) => typeof imageId === "string"
6314
+ ) : [];
6315
+ const imageStates = normalizeReviewFigmaImageOverlayItemStateRecord(
6316
+ state.imageStates
6317
+ );
6318
+ if (Object.keys(imageStates).length === 0 && selectedImageId) {
6319
+ imageStates[selectedImageId] = normalizeReviewFigmaImageOverlayItemState(
6320
+ state
6321
+ );
6322
+ }
6323
+ return {
6324
+ selectedImageId,
6325
+ imageStates,
6326
+ lastVisibleImageIds
6327
+ };
6328
+ }
6329
+ function normalizeReviewFigmaImageOverlayItemStateRecord(value) {
6330
+ if (!value || typeof value !== "object") return {};
6331
+ return Object.fromEntries(
6332
+ Object.entries(value).flatMap(([imageId, itemState]) => {
6333
+ if (!imageId || typeof itemState !== "object") return [];
6334
+ return [
6335
+ [
6336
+ imageId,
6337
+ normalizeReviewFigmaImageOverlayItemState(
6338
+ itemState
6339
+ )
6340
+ ]
6341
+ ];
6342
+ })
6343
+ );
6344
+ }
6345
+ function normalizeReviewFigmaImageOverlayItemState(value) {
6346
+ return {
6347
+ isVisible: value.isVisible === true,
6348
+ opacity: clampReviewFigmaImageOverlayOpacity(
6349
+ typeof value.opacity === "number" ? value.opacity : DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_OPACITY
6350
+ ),
6351
+ isLocked: value.isLocked === true,
6352
+ mode: normalizeReviewFigmaImageOverlayMode(value.mode),
6353
+ offsetY: normalizeReviewFigmaImageOverlayOffsetY(value.offsetY)
6354
+ };
6355
+ }
6356
+ function isDefaultReviewFigmaImageOverlayState(state) {
6357
+ return state.selectedImageId === null && Object.keys(state.imageStates).length === 0 && state.lastVisibleImageIds.length === 0;
6358
+ }
6359
+
6360
+ // src/react-shell/figma/image.overlay.controller.ts
6198
6361
  var useReviewFigmaImageOverlayController = ({
6199
6362
  images,
6200
6363
  isLoading,
@@ -6213,8 +6376,12 @@ var useReviewFigmaImageOverlayController = ({
6213
6376
  (updater) => {
6214
6377
  setStateContainer((currentContainer) => {
6215
6378
  const currentState = currentContainer.storageKey === storageKey ? currentContainer.state : readStoredReviewFigmaImageOverlayState(storageKey);
6379
+ const nextState = updater(currentState);
6380
+ if (currentContainer.storageKey === storageKey && nextState === currentState) {
6381
+ return currentContainer;
6382
+ }
6216
6383
  return {
6217
- state: updater(currentState),
6384
+ state: nextState,
6218
6385
  storageKey
6219
6386
  };
6220
6387
  });
@@ -6254,7 +6421,7 @@ var useReviewFigmaImageOverlayController = ({
6254
6421
  const lastVisibleImageIds = currentState.lastVisibleImageIds.filter(
6255
6422
  (imageId) => nextImageIds.has(imageId)
6256
6423
  );
6257
- if (selectedImageId === currentState.selectedImageId && imageStates === currentState.imageStates && lastVisibleImageIds.length === currentState.lastVisibleImageIds.length) {
6424
+ if (selectedImageId === currentState.selectedImageId && Object.keys(imageStates).length === Object.keys(currentState.imageStates).length && lastVisibleImageIds.length === currentState.lastVisibleImageIds.length) {
6258
6425
  return currentState;
6259
6426
  }
6260
6427
  return {
@@ -6451,78 +6618,54 @@ var useReviewFigmaImageOverlayController = ({
6451
6618
  };
6452
6619
  });
6453
6620
  }, [images, updateState]);
6621
+ const updateSelectedOverlayState = useCallback2(
6622
+ (updater) => {
6623
+ updateState((currentState) => ({
6624
+ ...currentState,
6625
+ imageStates: updateSelectedReviewFigmaImageOverlayItemState(
6626
+ currentState,
6627
+ updater
6628
+ )
6629
+ }));
6630
+ },
6631
+ [updateState]
6632
+ );
6454
6633
  const setOverlayOpacity = useCallback2((opacity) => {
6455
- updateState((currentState) => ({
6456
- ...currentState,
6457
- imageStates: updateSelectedReviewFigmaImageOverlayItemState(
6458
- currentState,
6459
- (itemState) => ({
6460
- ...itemState,
6461
- opacity: clampReviewFigmaImageOverlayOpacity(opacity)
6462
- })
6463
- )
6634
+ updateSelectedOverlayState((itemState) => ({
6635
+ ...itemState,
6636
+ opacity: clampReviewFigmaImageOverlayOpacity(opacity)
6464
6637
  }));
6465
- }, [updateState]);
6638
+ }, [updateSelectedOverlayState]);
6466
6639
  const setOverlayLocked = useCallback2((isLocked) => {
6467
- updateState((currentState) => ({
6468
- ...currentState,
6469
- imageStates: updateSelectedReviewFigmaImageOverlayItemState(
6470
- currentState,
6471
- (itemState) => ({
6472
- ...itemState,
6473
- isLocked
6474
- })
6475
- )
6640
+ updateSelectedOverlayState((itemState) => ({
6641
+ ...itemState,
6642
+ isLocked
6476
6643
  }));
6477
- }, [updateState]);
6644
+ }, [updateSelectedOverlayState]);
6478
6645
  const toggleOverlayLocked = useCallback2(() => {
6479
- updateState((currentState) => ({
6480
- ...currentState,
6481
- imageStates: updateSelectedReviewFigmaImageOverlayItemState(
6482
- currentState,
6483
- (itemState) => ({
6484
- ...itemState,
6485
- isLocked: !itemState.isLocked
6486
- })
6487
- )
6646
+ updateSelectedOverlayState((itemState) => ({
6647
+ ...itemState,
6648
+ isLocked: !itemState.isLocked
6488
6649
  }));
6489
- }, [updateState]);
6650
+ }, [updateSelectedOverlayState]);
6490
6651
  const setOverlayMode = useCallback2((mode) => {
6491
- updateState((currentState) => ({
6492
- ...currentState,
6493
- imageStates: updateSelectedReviewFigmaImageOverlayItemState(
6494
- currentState,
6495
- (itemState) => ({
6496
- ...itemState,
6497
- mode: normalizeReviewFigmaImageOverlayMode(mode)
6498
- })
6499
- )
6652
+ updateSelectedOverlayState((itemState) => ({
6653
+ ...itemState,
6654
+ mode: normalizeReviewFigmaImageOverlayMode(mode)
6500
6655
  }));
6501
- }, [updateState]);
6656
+ }, [updateSelectedOverlayState]);
6502
6657
  const toggleOverlayMode = useCallback2(() => {
6503
- updateState((currentState) => ({
6504
- ...currentState,
6505
- imageStates: updateSelectedReviewFigmaImageOverlayItemState(
6506
- currentState,
6507
- (itemState) => ({
6508
- ...itemState,
6509
- mode: itemState.mode === "invert" ? "normal" : "invert"
6510
- })
6511
- )
6658
+ updateSelectedOverlayState((itemState) => ({
6659
+ ...itemState,
6660
+ mode: itemState.mode === "invert" ? "normal" : "invert"
6512
6661
  }));
6513
- }, [updateState]);
6662
+ }, [updateSelectedOverlayState]);
6514
6663
  const setOverlayOffsetY = useCallback2((offsetY) => {
6515
- updateState((currentState) => ({
6516
- ...currentState,
6517
- imageStates: updateSelectedReviewFigmaImageOverlayItemState(
6518
- currentState,
6519
- (itemState) => ({
6520
- ...itemState,
6521
- offsetY: normalizeReviewFigmaImageOverlayOffsetY(offsetY)
6522
- })
6523
- )
6664
+ updateSelectedOverlayState((itemState) => ({
6665
+ ...itemState,
6666
+ offsetY: normalizeReviewFigmaImageOverlayOffsetY(offsetY)
6524
6667
  }));
6525
- }, [updateState]);
6668
+ }, [updateSelectedOverlayState]);
6526
6669
  const resetOverlay = useCallback2(() => {
6527
6670
  updateState((currentState) => ({
6528
6671
  ...currentState,
@@ -6563,137 +6706,6 @@ var useReviewFigmaImageOverlayController = ({
6563
6706
  toggleOverlayVisible
6564
6707
  };
6565
6708
  };
6566
- function createReviewFigmaImageOverlayStorageKey(target) {
6567
- return `${REVIEW_FIGMA_IMAGE_OVERLAY_STORAGE_KEY_PREFIX}${createReviewFigmaImageTargetKey(target)}`;
6568
- }
6569
- function readStoredReviewFigmaImageOverlayState(storageKey) {
6570
- if (typeof window === "undefined") {
6571
- return DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_STATE;
6572
- }
6573
- try {
6574
- const value = window.localStorage.getItem(storageKey);
6575
- if (!value) return DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_STATE;
6576
- return normalizeReviewFigmaImageOverlayState(JSON.parse(value));
6577
- } catch {
6578
- return DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_STATE;
6579
- }
6580
- }
6581
- function writeStoredReviewFigmaImageOverlayState(storageKey, state) {
6582
- if (typeof window === "undefined") return;
6583
- if (isDefaultReviewFigmaImageOverlayState(state)) {
6584
- try {
6585
- window.localStorage.removeItem(storageKey);
6586
- } catch {
6587
- return;
6588
- }
6589
- return;
6590
- }
6591
- try {
6592
- window.localStorage.setItem(
6593
- storageKey,
6594
- JSON.stringify({
6595
- version: REVIEW_FIGMA_IMAGE_OVERLAY_STORAGE_VERSION,
6596
- ...state
6597
- })
6598
- );
6599
- } catch {
6600
- return;
6601
- }
6602
- }
6603
- var DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_STATE = {
6604
- selectedImageId: null,
6605
- imageStates: {},
6606
- lastVisibleImageIds: []
6607
- };
6608
- var DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_ITEM_STATE = {
6609
- isVisible: false,
6610
- opacity: DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_OPACITY,
6611
- isLocked: false,
6612
- mode: DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_MODE,
6613
- offsetY: 0
6614
- };
6615
- function normalizeReviewFigmaImageOverlayState(value) {
6616
- if (!value || typeof value !== "object") {
6617
- return DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_STATE;
6618
- }
6619
- const state = value;
6620
- const selectedImageId = typeof state.selectedImageId === "string" ? state.selectedImageId : null;
6621
- const lastVisibleImageIds = Array.isArray(state.lastVisibleImageIds) ? state.lastVisibleImageIds.filter(
6622
- (imageId) => typeof imageId === "string"
6623
- ) : [];
6624
- const imageStates = normalizeReviewFigmaImageOverlayItemStateRecord(
6625
- state.imageStates
6626
- );
6627
- if (Object.keys(imageStates).length === 0 && selectedImageId) {
6628
- imageStates[selectedImageId] = normalizeReviewFigmaImageOverlayItemState(
6629
- state
6630
- );
6631
- }
6632
- return {
6633
- selectedImageId,
6634
- imageStates,
6635
- lastVisibleImageIds
6636
- };
6637
- }
6638
- function normalizeReviewFigmaImageOverlayItemStateRecord(value) {
6639
- if (!value || typeof value !== "object") return {};
6640
- return Object.fromEntries(
6641
- Object.entries(value).flatMap(([imageId, itemState]) => {
6642
- if (!imageId || typeof itemState !== "object") return [];
6643
- return [
6644
- [
6645
- imageId,
6646
- normalizeReviewFigmaImageOverlayItemState(
6647
- itemState
6648
- )
6649
- ]
6650
- ];
6651
- })
6652
- );
6653
- }
6654
- function normalizeReviewFigmaImageOverlayItemState(value) {
6655
- return {
6656
- isVisible: value.isVisible === true,
6657
- opacity: clampReviewFigmaImageOverlayOpacity(
6658
- typeof value.opacity === "number" ? value.opacity : DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_OPACITY
6659
- ),
6660
- isLocked: value.isLocked === true,
6661
- mode: normalizeReviewFigmaImageOverlayMode(value.mode),
6662
- offsetY: normalizeReviewFigmaImageOverlayOffsetY(value.offsetY)
6663
- };
6664
- }
6665
- function normalizeReviewFigmaImageOverlayMode(value) {
6666
- return value === "invert" ? "invert" : DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_MODE;
6667
- }
6668
- function normalizeReviewFigmaImageOverlayOffsetY(value) {
6669
- if (typeof value !== "number" || !Number.isFinite(value)) return 0;
6670
- return Math.round(value);
6671
- }
6672
- function clampReviewFigmaImageOverlayOpacity(value) {
6673
- if (!Number.isFinite(value)) return DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_OPACITY;
6674
- return Math.min(1, Math.max(0, value));
6675
- }
6676
- function isDefaultReviewFigmaImageOverlayState(state) {
6677
- return state.selectedImageId === null && Object.keys(state.imageStates).length === 0 && state.lastVisibleImageIds.length === 0;
6678
- }
6679
- function getReviewFigmaImageOverlayItemState(state, imageId) {
6680
- return imageId ? state.imageStates[imageId] ?? DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_ITEM_STATE : DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_ITEM_STATE;
6681
- }
6682
- function updateSelectedReviewFigmaImageOverlayItemState(state, updater) {
6683
- return state.selectedImageId ? updateReviewFigmaImageOverlayItemState(
6684
- state.imageStates,
6685
- state.selectedImageId,
6686
- updater
6687
- ) : state.imageStates;
6688
- }
6689
- function updateReviewFigmaImageOverlayItemState(imageStates, imageId, updater) {
6690
- return {
6691
- ...imageStates,
6692
- [imageId]: updater(
6693
- imageStates[imageId] ?? DEFAULT_REVIEW_FIGMA_IMAGE_OVERLAY_ITEM_STATE
6694
- )
6695
- };
6696
- }
6697
6709
 
6698
6710
  // src/react-shell/figma/image-panel.utils.ts
6699
6711
  var DEFAULT_FIGMA_IMAGE_LAYER_STATE = {
@@ -7551,11 +7563,19 @@ var updateShellUrl = (target, size, source) => {
7551
7563
  }
7552
7564
  url.searchParams.delete("item");
7553
7565
  url.searchParams.delete("panel");
7554
- window.history.replaceState(null, "", `${url.pathname}${url.search}`);
7566
+ window.history.replaceState(
7567
+ null,
7568
+ "",
7569
+ `${url.pathname}${url.search}${url.hash}`
7570
+ );
7555
7571
  };
7556
7572
  var updateShellUrlForItem = (target, size, itemId, source) => {
7557
7573
  const url = getShellUrlForItem(target, size, itemId, source);
7558
- window.history.replaceState(null, "", `${url.pathname}${url.search}`);
7574
+ window.history.replaceState(
7575
+ null,
7576
+ "",
7577
+ `${url.pathname}${url.search}${url.hash}`
7578
+ );
7559
7579
  };
7560
7580
  var getShellUrlForItem = (target, size, itemId, source) => {
7561
7581
  const url = new URL(window.location.href);
@@ -9732,6 +9752,26 @@ var REVIEW_QA_STATUS_FILTER_VALUES = /* @__PURE__ */ new Set([
9732
9752
  "hold",
9733
9753
  "done"
9734
9754
  ]);
9755
+ var readStorage = (key) => {
9756
+ if (typeof window === "undefined") return null;
9757
+ try {
9758
+ return window.localStorage.getItem(key);
9759
+ } catch {
9760
+ return null;
9761
+ }
9762
+ };
9763
+ var writeStorage = (key, value) => {
9764
+ if (typeof window === "undefined") return;
9765
+ try {
9766
+ if (value === null) {
9767
+ window.localStorage.removeItem(key);
9768
+ } else {
9769
+ window.localStorage.setItem(key, value);
9770
+ }
9771
+ } catch {
9772
+ return;
9773
+ }
9774
+ };
9735
9775
  var normalizeReviewTheme = (value) => value === "light" || value === "system" || value === "dark" ? value : DEFAULT_REVIEW_THEME;
9736
9776
  var normalizeReviewSidePanel = (value) => {
9737
9777
  if (value === "qa" || value === "source" || value === "figma-images") {
@@ -9770,100 +9810,35 @@ var normalizeStoredSourceTreeMetaVisibility = (value) => {
9770
9810
  className: typeof metaVisibility.className === "boolean" ? metaVisibility.className : DEFAULT_SOURCE_TREE_META_VISIBILITY.className
9771
9811
  };
9772
9812
  };
9773
- var getStoredFigmaToken = () => {
9774
- if (typeof window === "undefined") return "";
9775
- try {
9776
- return window.localStorage.getItem(FIGMA_TOKEN_STORAGE_KEY) ?? "";
9777
- } catch {
9778
- return "";
9779
- }
9780
- };
9813
+ var getStoredFigmaToken = () => readStorage(FIGMA_TOKEN_STORAGE_KEY) ?? "";
9781
9814
  var writeStoredFigmaToken = (token) => {
9782
- if (typeof window === "undefined") return;
9783
- try {
9784
- if (token) {
9785
- window.localStorage.setItem(FIGMA_TOKEN_STORAGE_KEY, token);
9786
- } else {
9787
- window.localStorage.removeItem(FIGMA_TOKEN_STORAGE_KEY);
9788
- }
9789
- } catch {
9790
- return;
9791
- }
9815
+ writeStorage(FIGMA_TOKEN_STORAGE_KEY, token || null);
9792
9816
  };
9793
9817
  var getStoredReviewUserId = (fallback = "") => {
9794
9818
  const normalizedFallback = fallback.trim();
9795
- if (typeof window === "undefined") return normalizedFallback;
9796
- try {
9797
- return window.localStorage.getItem(REVIEW_USER_ID_STORAGE_KEY)?.trim() || normalizedFallback;
9798
- } catch {
9799
- return normalizedFallback;
9800
- }
9819
+ return readStorage(REVIEW_USER_ID_STORAGE_KEY)?.trim() || normalizedFallback;
9801
9820
  };
9802
9821
  var writeStoredReviewUserId = (userId) => {
9803
- if (typeof window === "undefined") return;
9804
- try {
9805
- if (userId) {
9806
- window.localStorage.setItem(REVIEW_USER_ID_STORAGE_KEY, userId);
9807
- } else {
9808
- window.localStorage.removeItem(REVIEW_USER_ID_STORAGE_KEY);
9809
- }
9810
- } catch {
9811
- return;
9812
- }
9813
- };
9814
- var getStoredReviewTheme = () => {
9815
- if (typeof window === "undefined") return DEFAULT_REVIEW_THEME;
9816
- try {
9817
- return normalizeReviewTheme(
9818
- window.localStorage.getItem(REVIEW_THEME_STORAGE_KEY)
9819
- );
9820
- } catch {
9821
- return DEFAULT_REVIEW_THEME;
9822
- }
9822
+ writeStorage(REVIEW_USER_ID_STORAGE_KEY, userId || null);
9823
9823
  };
9824
+ var getStoredReviewTheme = () => normalizeReviewTheme(readStorage(REVIEW_THEME_STORAGE_KEY));
9824
9825
  var writeStoredReviewTheme = (theme) => {
9825
- if (typeof window === "undefined") return;
9826
- try {
9827
- if (theme === DEFAULT_REVIEW_THEME) {
9828
- window.localStorage.removeItem(REVIEW_THEME_STORAGE_KEY);
9829
- } else {
9830
- window.localStorage.setItem(REVIEW_THEME_STORAGE_KEY, theme);
9831
- }
9832
- } catch {
9833
- return;
9834
- }
9826
+ writeStorage(
9827
+ REVIEW_THEME_STORAGE_KEY,
9828
+ theme === DEFAULT_REVIEW_THEME ? null : theme
9829
+ );
9835
9830
  };
9836
9831
  var getStoredReviewTooltipsEnabled = () => {
9837
- if (typeof window === "undefined") return DEFAULT_REVIEW_TOOLTIPS_ENABLED;
9838
- try {
9839
- const value = window.localStorage.getItem(REVIEW_TOOLTIP_STORAGE_KEY);
9840
- return value === null ? DEFAULT_REVIEW_TOOLTIPS_ENABLED : value !== "false";
9841
- } catch {
9842
- return DEFAULT_REVIEW_TOOLTIPS_ENABLED;
9843
- }
9832
+ const value = readStorage(REVIEW_TOOLTIP_STORAGE_KEY);
9833
+ return value === null ? DEFAULT_REVIEW_TOOLTIPS_ENABLED : value !== "false";
9844
9834
  };
9845
9835
  var writeStoredReviewTooltipsEnabled = (isEnabled) => {
9846
- if (typeof window === "undefined") return;
9847
- try {
9848
- if (isEnabled === DEFAULT_REVIEW_TOOLTIPS_ENABLED) {
9849
- window.localStorage.removeItem(REVIEW_TOOLTIP_STORAGE_KEY);
9850
- } else {
9851
- window.localStorage.setItem(REVIEW_TOOLTIP_STORAGE_KEY, "false");
9852
- }
9853
- } catch {
9854
- return;
9855
- }
9856
- };
9857
- var getStoredReviewSidePanel = () => {
9858
- if (typeof window === "undefined") return "qa";
9859
- try {
9860
- return normalizeStoredReviewSidePanel(
9861
- window.localStorage.getItem(REVIEW_SIDE_PANEL_STORAGE_KEY)
9862
- );
9863
- } catch {
9864
- return "qa";
9865
- }
9836
+ writeStorage(
9837
+ REVIEW_TOOLTIP_STORAGE_KEY,
9838
+ isEnabled === DEFAULT_REVIEW_TOOLTIPS_ENABLED ? null : "false"
9839
+ );
9866
9840
  };
9841
+ var getStoredReviewSidePanel = () => normalizeStoredReviewSidePanel(readStorage(REVIEW_SIDE_PANEL_STORAGE_KEY));
9867
9842
  var getInitialReviewSidePanel = () => {
9868
9843
  if (typeof window === "undefined") return null;
9869
9844
  try {
@@ -9875,106 +9850,49 @@ var getInitialReviewSidePanel = () => {
9875
9850
  }
9876
9851
  };
9877
9852
  var writeStoredReviewSidePanel = (sidePanel) => {
9878
- if (typeof window === "undefined") return;
9879
- try {
9880
- window.localStorage.setItem(
9881
- REVIEW_SIDE_PANEL_STORAGE_KEY,
9882
- normalizeStoredReviewSidePanel(sidePanel)
9883
- );
9884
- } catch {
9885
- return;
9886
- }
9853
+ writeStorage(
9854
+ REVIEW_SIDE_PANEL_STORAGE_KEY,
9855
+ normalizeStoredReviewSidePanel(sidePanel)
9856
+ );
9887
9857
  };
9888
9858
  var getStoredReviewSidePanelVisible = () => {
9889
- if (typeof window === "undefined") return true;
9890
- try {
9891
- const value = window.localStorage.getItem(
9892
- REVIEW_SIDE_PANEL_VISIBLE_STORAGE_KEY
9893
- );
9894
- return value === null ? true : value === "true";
9895
- } catch {
9896
- return true;
9897
- }
9859
+ const value = readStorage(REVIEW_SIDE_PANEL_VISIBLE_STORAGE_KEY);
9860
+ return value === null ? true : value === "true";
9898
9861
  };
9899
9862
  var writeStoredReviewSidePanelVisible = (isVisible) => {
9900
- if (typeof window === "undefined") return;
9901
- try {
9902
- window.localStorage.setItem(
9903
- REVIEW_SIDE_PANEL_VISIBLE_STORAGE_KEY,
9904
- isVisible ? "true" : "false"
9905
- );
9906
- } catch {
9907
- return;
9908
- }
9909
- };
9910
- var getStoredReviewQaStatusFilters = () => {
9911
- if (typeof window === "undefined") return getDefaultReviewQaStatusFilters();
9912
- try {
9913
- return normalizeStoredReviewQaStatusFilters(
9914
- window.localStorage.getItem(REVIEW_QA_STATUS_FILTER_STORAGE_KEY)
9915
- );
9916
- } catch {
9917
- return getDefaultReviewQaStatusFilters();
9918
- }
9863
+ writeStorage(
9864
+ REVIEW_SIDE_PANEL_VISIBLE_STORAGE_KEY,
9865
+ isVisible ? "true" : "false"
9866
+ );
9919
9867
  };
9868
+ var getStoredReviewQaStatusFilters = () => normalizeStoredReviewQaStatusFilters(
9869
+ readStorage(REVIEW_QA_STATUS_FILTER_STORAGE_KEY)
9870
+ );
9920
9871
  var writeStoredReviewQaStatusFilters = (filters) => {
9921
- if (typeof window === "undefined") return;
9922
- try {
9923
- const normalizedFilters = normalizeReviewQaStatusFilters(filters);
9924
- if (isDefaultReviewQaStatusFilters(normalizedFilters)) {
9925
- window.localStorage.removeItem(REVIEW_QA_STATUS_FILTER_STORAGE_KEY);
9926
- } else {
9927
- window.localStorage.setItem(
9928
- REVIEW_QA_STATUS_FILTER_STORAGE_KEY,
9929
- JSON.stringify(normalizedFilters)
9930
- );
9931
- }
9932
- } catch {
9933
- return;
9934
- }
9935
- };
9936
- var getStoredSourceTreeFilter = () => {
9937
- if (typeof window === "undefined") return "";
9938
- try {
9939
- return window.localStorage.getItem(REVIEW_SOURCE_TREE_FILTER_STORAGE_KEY) ?? "";
9940
- } catch {
9941
- return "";
9942
- }
9872
+ const normalizedFilters = normalizeReviewQaStatusFilters(filters);
9873
+ writeStorage(
9874
+ REVIEW_QA_STATUS_FILTER_STORAGE_KEY,
9875
+ isDefaultReviewQaStatusFilters(normalizedFilters) ? null : JSON.stringify(normalizedFilters)
9876
+ );
9943
9877
  };
9878
+ var getStoredSourceTreeFilter = () => readStorage(REVIEW_SOURCE_TREE_FILTER_STORAGE_KEY) ?? "";
9944
9879
  var writeStoredSourceTreeFilter = (filter) => {
9945
- if (typeof window === "undefined") return;
9946
- try {
9947
- if (filter) {
9948
- window.localStorage.setItem(REVIEW_SOURCE_TREE_FILTER_STORAGE_KEY, filter);
9949
- } else {
9950
- window.localStorage.removeItem(REVIEW_SOURCE_TREE_FILTER_STORAGE_KEY);
9951
- }
9952
- } catch {
9953
- return;
9954
- }
9880
+ writeStorage(REVIEW_SOURCE_TREE_FILTER_STORAGE_KEY, filter || null);
9955
9881
  };
9956
9882
  var getStoredSourceTreeMetaVisibility = () => {
9957
- if (typeof window === "undefined") return DEFAULT_SOURCE_TREE_META_VISIBILITY;
9883
+ const value = readStorage(REVIEW_SOURCE_TREE_META_STORAGE_KEY);
9884
+ if (!value) return DEFAULT_SOURCE_TREE_META_VISIBILITY;
9958
9885
  try {
9959
- const value = window.localStorage.getItem(
9960
- REVIEW_SOURCE_TREE_META_STORAGE_KEY
9961
- );
9962
- if (!value) return DEFAULT_SOURCE_TREE_META_VISIBILITY;
9963
9886
  return normalizeStoredSourceTreeMetaVisibility(JSON.parse(value));
9964
9887
  } catch {
9965
9888
  return DEFAULT_SOURCE_TREE_META_VISIBILITY;
9966
9889
  }
9967
9890
  };
9968
9891
  var writeStoredSourceTreeMetaVisibility = (metaVisibility) => {
9969
- if (typeof window === "undefined") return;
9970
- try {
9971
- window.localStorage.setItem(
9972
- REVIEW_SOURCE_TREE_META_STORAGE_KEY,
9973
- JSON.stringify(normalizeStoredSourceTreeMetaVisibility(metaVisibility))
9974
- );
9975
- } catch {
9976
- return;
9977
- }
9892
+ writeStorage(
9893
+ REVIEW_SOURCE_TREE_META_STORAGE_KEY,
9894
+ JSON.stringify(normalizeStoredSourceTreeMetaVisibility(metaVisibility))
9895
+ );
9978
9896
  };
9979
9897
  var getSystemReviewTheme = () => {
9980
9898
  if (typeof window === "undefined" || !window.matchMedia) return "dark";
@@ -10784,7 +10702,7 @@ function createSourceCandidate(element, source, depth, kind, context) {
10784
10702
  const column = getSourcePosition(source.column);
10785
10703
  const position = line ? `:${line}${column ? `:${column}` : ""}` : "";
10786
10704
  return {
10787
- id: `${kind}:${getSourceCandidateKey(source)}:${repeatInfo?.index ?? 0}:${depth}`,
10705
+ id: `${kind}:${getSourceCandidateDedupeKey(source)}:${repeatInfo?.index ?? 0}:${depth}`,
10788
10706
  depth,
10789
10707
  element,
10790
10708
  filePath: getDisplaySourcePath(source.file) ?? fileName,
@@ -10814,16 +10732,6 @@ function takeVisibleSourceCandidates(candidates) {
10814
10732
  }
10815
10733
  return visible;
10816
10734
  }
10817
- function getSourceCandidateKey(source) {
10818
- return [
10819
- source.file,
10820
- source.component,
10821
- source.line,
10822
- source.column,
10823
- source.sectionId,
10824
- source.sectionIndex
10825
- ].filter(Boolean).join("|");
10826
- }
10827
10735
  function getSourceCandidateDedupeKey(source) {
10828
10736
  return [
10829
10737
  source.file,
@@ -11244,11 +11152,6 @@ var getSectionDomAdjustmentKeyDelta = (event) => {
11244
11152
  return null;
11245
11153
  };
11246
11154
  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
11155
  var COMPONENT_SELECTION_ACTION_SELECTOR = [
11253
11156
  "a",
11254
11157
  "button",
@@ -11418,7 +11321,7 @@ function useReviewSectionOutline({
11418
11321
  useEffect6(() => {
11419
11322
  if (!activeDomAdjustmentEntryId) return void 0;
11420
11323
  const handleKeyDown = (event) => {
11421
- if (isEditableKeyTarget(event.target)) return;
11324
+ if (isEditableEventTarget(event)) return;
11422
11325
  const delta = getSectionDomAdjustmentKeyDelta(event);
11423
11326
  if (!delta) return;
11424
11327
  const position = domAdjustmentManagerRef.current?.adjust(
@@ -12866,7 +12769,7 @@ var ReviewShellFrameContainer = ({
12866
12769
  };
12867
12770
 
12868
12771
  // src/react-shell/review/shell.modals.container.tsx
12869
- import { useCallback as useCallback8 } from "react";
12772
+ import { useCallback as useCallback8, useEffect as useEffect8, useState as useState9 } from "react";
12870
12773
 
12871
12774
  // src/react-shell/review/modal.tsx
12872
12775
  import { jsx as jsx24, jsxs as jsxs17 } from "react/jsx-runtime";
@@ -13270,11 +13173,12 @@ var ReviewSettingsModal = ({
13270
13173
 
13271
13174
  // src/react-shell/sitemap/modal.tsx
13272
13175
  import {
13176
+ Fragment as Fragment3,
13273
13177
  useMemo as useMemo6,
13274
13178
  useState as useState8
13275
13179
  } from "react";
13276
13180
 
13277
- // src/react-shell/sitemap/tree.ts
13181
+ // src/react-shell/sitemap/count.ts
13278
13182
  var WORKFLOW_STATUSES = [
13279
13183
  "todo",
13280
13184
  "doing",
@@ -13298,33 +13202,11 @@ var createEmptySitemapQaCount = () => ({
13298
13202
  viewport: {}
13299
13203
  });
13300
13204
  var createSitemapViewportColumn = (preset, index) => ({
13205
+ // 크기가 같은 preset도 별도 열로 유지될 수 있게 순서를 key에 포함한다.
13301
13206
  key: `${index}:${preset.width}x${preset.height}`,
13302
13207
  label: preset.label,
13303
13208
  title: `${preset.label} ${preset.width}x${preset.height}`
13304
13209
  });
13305
- var normalizeSitemapHref = (href) => {
13306
- const [path = "/"] = href.split(/[?#]/);
13307
- const normalizedPath = path.startsWith("/") ? path : `/${path}`;
13308
- return normalizedPath || "/";
13309
- };
13310
- var getSitemapSegments = (href) => normalizeSitemapHref(href).split("/").map((segment) => segment.trim()).filter(Boolean);
13311
- var createSitemapNode = (href, label, isPage = false) => ({
13312
- href,
13313
- label,
13314
- isPage,
13315
- children: /* @__PURE__ */ new Map()
13316
- });
13317
- var mergeSitemapUsers = (users) => {
13318
- const userByKey = /* @__PURE__ */ new Map();
13319
- users.forEach((user) => {
13320
- const key = user.sessionId || user.userId;
13321
- const currentUser = userByKey.get(key);
13322
- if (!currentUser || Date.parse(user.updatedAt) >= Date.parse(currentUser.updatedAt)) {
13323
- userByKey.set(key, user);
13324
- }
13325
- });
13326
- return Array.from(userByKey.values());
13327
- };
13328
13210
  var addSitemapQaCounts = (first, second) => ({
13329
13211
  total: first.total + second.total,
13330
13212
  remaining: first.remaining + second.remaining,
@@ -13362,9 +13244,37 @@ var addSitemapQaCounts = (first, second) => ({
13362
13244
  {}
13363
13245
  )
13364
13246
  });
13247
+
13248
+ // src/react-shell/sitemap/tree.ts
13249
+ var SITEMAP_STATUS_FILTERS = ["todo", "review", "hold"];
13250
+ var normalizeSitemapHref = (href) => {
13251
+ const [path = "/"] = href.split(/[?#]/);
13252
+ const normalizedPath = path.startsWith("/") ? path : `/${path}`;
13253
+ return normalizedPath || "/";
13254
+ };
13255
+ var getSitemapSegments = (href) => normalizeSitemapHref(href).split("/").map((segment) => segment.trim()).filter(Boolean);
13256
+ var createSitemapNode = (href, label, isPage = false) => ({
13257
+ href,
13258
+ label,
13259
+ isPage,
13260
+ children: /* @__PURE__ */ new Map()
13261
+ });
13262
+ var mergeSitemapUsers = (users) => {
13263
+ const userByKey = /* @__PURE__ */ new Map();
13264
+ users.forEach((user) => {
13265
+ const key = user.sessionId || user.userId;
13266
+ const currentUser = userByKey.get(key);
13267
+ if (!currentUser || Date.parse(user.updatedAt) >= Date.parse(currentUser.updatedAt)) {
13268
+ userByKey.set(key, user);
13269
+ }
13270
+ });
13271
+ return Array.from(userByKey.values());
13272
+ };
13365
13273
  var createSitemapRows = (pages, activeRoute, pageQaCounts, pagePresenceUsers, getPageTarget, options = {}) => {
13366
13274
  const collapsedFolderHrefs = options.collapsedFolderHrefs ?? /* @__PURE__ */ new Set();
13367
13275
  const searchQuery = normalizeSitemapSearchQuery(options.searchQuery);
13276
+ const statusFilters = options.statusFilters ?? /* @__PURE__ */ new Set();
13277
+ const isStatusFiltering = statusFilters.size > 0;
13368
13278
  const sortKey = options.sortKey ?? "page";
13369
13279
  const sortDirection = options.sortDirection ?? "asc";
13370
13280
  const root = createSitemapNode("/", "/", false);
@@ -13418,23 +13328,25 @@ var createSitemapRows = (pages, activeRoute, pageQaCounts, pagePresenceUsers, ge
13418
13328
  node,
13419
13329
  directCount,
13420
13330
  directUsers,
13331
+ // folder는 하위 page 합계, 실제 page는 자신의 수치를 별도로 보존한다.
13421
13332
  count: node.isPage ? addSitemapQaCounts(directCount, childAggregate.count) : childAggregate.count,
13422
13333
  users: mergeSitemapUsers([...directUsers, ...childAggregate.users]),
13423
13334
  children
13424
13335
  };
13425
13336
  };
13426
- const getSortValue = (summary) => {
13427
- if (sortKey === "page") return summary.node.label;
13428
- if (sortKey === "todo") return summary.count.status.todo;
13429
- if (sortKey === "review") return summary.count.status.review;
13430
- if (sortKey === "hold") return summary.count.status.hold;
13431
- if (sortKey === "online") return summary.users.length;
13337
+ const getSortValueFor = (label, count, users) => {
13338
+ if (sortKey === "page") return label;
13339
+ if (sortKey === "todo") return count.status.todo;
13340
+ if (sortKey === "review") return count.status.review;
13341
+ if (sortKey === "hold") return count.status.hold;
13342
+ if (sortKey === "online") return users.length;
13432
13343
  if (sortKey.startsWith("viewport:")) {
13433
13344
  const viewportKey = sortKey.slice("viewport:".length);
13434
- return summary.count.viewport[viewportKey]?.remaining ?? 0;
13345
+ return count.viewport[viewportKey]?.remaining ?? 0;
13435
13346
  }
13436
13347
  return 0;
13437
13348
  };
13349
+ const getSortValue = (summary) => getSortValueFor(summary.node.label, summary.count, summary.users);
13438
13350
  const sortSummaries = (summaries) => {
13439
13351
  return [...summaries].sort((a, b) => {
13440
13352
  const firstValue = getSortValue(a);
@@ -13455,6 +13367,53 @@ var createSitemapRows = (pages, activeRoute, pageQaCounts, pagePresenceUsers, ge
13455
13367
  }
13456
13368
  return summary.children.some(summaryMatchesSearch);
13457
13369
  };
13370
+ const countMatchesStatusFilters = (count) => Array.from(statusFilters).some((status) => count.status[status] > 0);
13371
+ if (isStatusFiltering) {
13372
+ const flatEntries = [];
13373
+ const collectMatchingPages = (node) => {
13374
+ if (node.isPage) {
13375
+ const directCount = getDirectCount(node);
13376
+ if (countMatchesStatusFilters(directCount) && (!searchQuery || sitemapNodeMatchesSearch(node, searchQuery, getPageTarget))) {
13377
+ flatEntries.push({
13378
+ node,
13379
+ count: directCount,
13380
+ users: getDirectUsers(node)
13381
+ });
13382
+ }
13383
+ }
13384
+ node.children.forEach(collectMatchingPages);
13385
+ };
13386
+ collectMatchingPages(root);
13387
+ return flatEntries.sort((a, b) => {
13388
+ const firstValue = getSortValueFor(
13389
+ normalizeSitemapHref(a.node.href),
13390
+ a.count,
13391
+ a.users
13392
+ );
13393
+ const secondValue = getSortValueFor(
13394
+ normalizeSitemapHref(b.node.href),
13395
+ b.count,
13396
+ b.users
13397
+ );
13398
+ const valueDiff = typeof firstValue === "string" && typeof secondValue === "string" ? firstValue.localeCompare(secondValue) : Number(firstValue) - Number(secondValue);
13399
+ if (valueDiff !== 0) {
13400
+ return sortDirection === "asc" ? valueDiff : -valueDiff;
13401
+ }
13402
+ const remainingDiff = b.count.remaining - a.count.remaining;
13403
+ if (remainingDiff !== 0) return remainingDiff;
13404
+ return a.node.href.localeCompare(b.node.href);
13405
+ }).map((entry) => ({
13406
+ href: entry.node.href,
13407
+ label: normalizeSitemapHref(entry.node.href),
13408
+ depth: 0,
13409
+ hasChildren: false,
13410
+ isExpanded: false,
13411
+ isPage: true,
13412
+ isActive: getPageTarget(entry.node.href) === activeRoute,
13413
+ qaCount: entry.count,
13414
+ users: entry.users
13415
+ }));
13416
+ }
13458
13417
  const rows = [];
13459
13418
  const appendSummaryRows = (summary, depth) => {
13460
13419
  const { node } = summary;
@@ -13522,8 +13481,70 @@ function sitemapNodeMatchesSearch(node, searchQuery, getPageTarget) {
13522
13481
  ].join(" ").toLowerCase().includes(searchQuery);
13523
13482
  }
13524
13483
 
13525
- // src/react-shell/sitemap/modal.tsx
13484
+ // src/react-shell/sitemap/row.tsx
13526
13485
  import { Fragment as Fragment2, jsx as jsx28, jsxs as jsxs21 } from "react/jsx-runtime";
13486
+ var getCountCellClassName = (status, count) => [
13487
+ "df-review-sitemap-cell",
13488
+ `is-${status}`,
13489
+ count === 0 ? "is-zero" : ""
13490
+ ].filter(Boolean).join(" ");
13491
+ var SitemapRowContent = ({
13492
+ depth,
13493
+ hasChildren,
13494
+ isExpanded,
13495
+ isPage,
13496
+ label,
13497
+ qaCount,
13498
+ users,
13499
+ onToggleFolder
13500
+ }) => /* @__PURE__ */ jsxs21(Fragment2, { children: [
13501
+ /* @__PURE__ */ jsxs21(
13502
+ "span",
13503
+ {
13504
+ className: "df-review-sitemap-path",
13505
+ style: { "--df-review-sitemap-depth": depth },
13506
+ children: [
13507
+ hasChildren ? /* @__PURE__ */ jsx28(
13508
+ "button",
13509
+ {
13510
+ "aria-expanded": isExpanded,
13511
+ "aria-label": `${isExpanded ? "Collapse" : "Expand"} ${label}`,
13512
+ className: "df-review-sitemap-tree-toggle",
13513
+ type: "button",
13514
+ onClick: (event) => {
13515
+ event.stopPropagation();
13516
+ onToggleFolder?.();
13517
+ },
13518
+ children: isExpanded ? /* @__PURE__ */ jsx28(ChevronDown, { "aria-hidden": "true" }) : /* @__PURE__ */ jsx28(ChevronRight, { "aria-hidden": "true" })
13519
+ }
13520
+ ) : /* @__PURE__ */ jsx28("span", { className: "df-review-sitemap-tree-spacer", "aria-hidden": "true" }),
13521
+ isPage ? /* @__PURE__ */ jsx28("span", { className: "df-review-sitemap-page-label", children: label }) : /* @__PURE__ */ jsx28("span", { className: "df-review-sitemap-label", children: label })
13522
+ ]
13523
+ }
13524
+ ),
13525
+ /* @__PURE__ */ jsx28("span", { className: getCountCellClassName("todo", qaCount.status.todo), children: /* @__PURE__ */ jsx28("strong", { children: qaCount.status.todo }) }),
13526
+ /* @__PURE__ */ jsx28("span", { className: getCountCellClassName("review", qaCount.status.review), children: qaCount.status.review }),
13527
+ /* @__PURE__ */ jsx28("span", { className: getCountCellClassName("hold", qaCount.status.hold), children: qaCount.status.hold }),
13528
+ /* @__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(
13529
+ "span",
13530
+ {
13531
+ className: "df-review-sitemap-user",
13532
+ style: {
13533
+ "--df-review-presence-color": user.color
13534
+ },
13535
+ children: user.userId
13536
+ },
13537
+ user.sessionId
13538
+ )) }) : null })
13539
+ ] });
13540
+
13541
+ // src/react-shell/sitemap/modal.tsx
13542
+ import { jsx as jsx29, jsxs as jsxs22 } from "react/jsx-runtime";
13543
+ var STATUS_FILTER_LABELS = {
13544
+ todo: "Todo",
13545
+ review: "Review",
13546
+ hold: "Hold"
13547
+ };
13527
13548
  var getNextSortDirection = (current, key) => {
13528
13549
  if (current.key !== key) return key === "page" ? "asc" : "desc";
13529
13550
  return current.direction === "desc" ? "asc" : "desc";
@@ -13532,11 +13553,6 @@ var getSortIndicator = (sort, key) => {
13532
13553
  if (sort.key !== key) return "";
13533
13554
  return sort.direction === "desc" ? "\u2193" : "\u2191";
13534
13555
  };
13535
- var getCountCellClassName = (status, count) => [
13536
- "df-review-sitemap-cell",
13537
- `is-${status}`,
13538
- count === 0 ? "is-zero" : ""
13539
- ].filter(Boolean).join(" ");
13540
13556
  var mergePresenceUsers = (users) => {
13541
13557
  const userByKey = /* @__PURE__ */ new Map();
13542
13558
  users.forEach((user) => {
@@ -13549,6 +13565,7 @@ var mergePresenceUsers = (users) => {
13549
13565
  return Array.from(userByKey.values());
13550
13566
  };
13551
13567
  var SitemapModal = ({
13568
+ isOpen,
13552
13569
  pages,
13553
13570
  activeRoute,
13554
13571
  allQaCount,
@@ -13568,7 +13585,11 @@ var SitemapModal = ({
13568
13585
  () => /* @__PURE__ */ new Set()
13569
13586
  );
13570
13587
  const [searchQuery, setSearchQuery] = useState8("");
13588
+ const [statusFilters, setStatusFilters] = useState8(
13589
+ () => /* @__PURE__ */ new Set()
13590
+ );
13571
13591
  const trimmedSearchQuery = searchQuery.trim();
13592
+ const isFiltering = Boolean(trimmedSearchQuery) || statusFilters.size > 0;
13572
13593
  const allQaUsers = useMemo6(
13573
13594
  () => mergePresenceUsers(Array.from(pagePresenceUsers.values()).flat()),
13574
13595
  [pagePresenceUsers]
@@ -13583,7 +13604,8 @@ var SitemapModal = ({
13583
13604
  collapsedFolderHrefs,
13584
13605
  searchQuery: trimmedSearchQuery,
13585
13606
  sortKey: sort.key,
13586
- sortDirection: sort.direction
13607
+ sortDirection: sort.direction,
13608
+ statusFilters
13587
13609
  }
13588
13610
  );
13589
13611
  const matchingPageCount = sitemapRows.filter((row) => row.isPage).length;
@@ -13603,6 +13625,17 @@ var SitemapModal = ({
13603
13625
  direction: getNextSortDirection(current, key)
13604
13626
  }));
13605
13627
  };
13628
+ const toggleStatusFilter = (status) => {
13629
+ setStatusFilters((currentFilters) => {
13630
+ const nextFilters = new Set(currentFilters);
13631
+ if (nextFilters.has(status)) {
13632
+ nextFilters.delete(status);
13633
+ } else {
13634
+ nextFilters.add(status);
13635
+ }
13636
+ return nextFilters;
13637
+ });
13638
+ };
13606
13639
  const toggleFolder = (href) => {
13607
13640
  setCollapsedFolderHrefs((currentHrefs) => {
13608
13641
  const nextHrefs = new Set(currentHrefs);
@@ -13614,15 +13647,15 @@ var SitemapModal = ({
13614
13647
  return nextHrefs;
13615
13648
  });
13616
13649
  };
13617
- return /* @__PURE__ */ jsxs21(
13650
+ return /* @__PURE__ */ jsxs22(
13618
13651
  "div",
13619
13652
  {
13620
13653
  "aria-label": "Sitemap",
13621
13654
  "aria-modal": "true",
13622
- className: "df-review-sitemap-modal",
13655
+ className: `df-review-sitemap-modal${isOpen ? "" : " is-hidden"}`,
13623
13656
  role: "dialog",
13624
13657
  children: [
13625
- /* @__PURE__ */ jsx28(
13658
+ /* @__PURE__ */ jsx29(
13626
13659
  "button",
13627
13660
  {
13628
13661
  "aria-label": "Close sitemap",
@@ -13631,28 +13664,39 @@ var SitemapModal = ({
13631
13664
  onClick: onClose
13632
13665
  }
13633
13666
  ),
13634
- /* @__PURE__ */ jsxs21("div", { className: "df-review-sitemap-dialog", children: [
13635
- /* @__PURE__ */ jsxs21("div", { className: "df-review-sitemap-header", children: [
13636
- /* @__PURE__ */ jsxs21("div", { children: [
13637
- /* @__PURE__ */ jsx28("strong", { children: "Sitemap" }),
13638
- /* @__PURE__ */ jsxs21("span", { children: [
13667
+ /* @__PURE__ */ jsxs22("div", { className: "df-review-sitemap-dialog", children: [
13668
+ /* @__PURE__ */ jsxs22("div", { className: "df-review-sitemap-header", children: [
13669
+ /* @__PURE__ */ jsxs22("div", { children: [
13670
+ /* @__PURE__ */ jsx29("strong", { children: "Sitemap" }),
13671
+ /* @__PURE__ */ jsxs22("span", { children: [
13639
13672
  pages.length,
13640
- " pages \xB7 ",
13641
- allQaCount.status.todo,
13642
- " todo \xB7",
13643
- " ",
13644
- allQaCount.status.review,
13645
- " review \xB7 ",
13646
- allQaCount.status.hold,
13647
- " hold"
13673
+ " pages",
13674
+ SITEMAP_STATUS_FILTERS.map((status) => /* @__PURE__ */ jsxs22(Fragment3, { children: [
13675
+ " \xB7 ",
13676
+ /* @__PURE__ */ jsxs22(
13677
+ "button",
13678
+ {
13679
+ "aria-pressed": statusFilters.has(status),
13680
+ className: `df-review-sitemap-summary-filter${statusFilters.has(status) ? " is-active" : ""}`,
13681
+ title: `Show pages with ${STATUS_FILTER_LABELS[status]} QA`,
13682
+ type: "button",
13683
+ onClick: () => toggleStatusFilter(status),
13684
+ children: [
13685
+ allQaCount.status[status],
13686
+ " ",
13687
+ status
13688
+ ]
13689
+ }
13690
+ )
13691
+ ] }, status))
13648
13692
  ] })
13649
13693
  ] }),
13650
- /* @__PURE__ */ jsx28("button", { "aria-label": "Close sitemap", type: "button", onClick: onClose, children: "x" })
13694
+ /* @__PURE__ */ jsx29("button", { "aria-label": "Close sitemap", type: "button", onClick: onClose, children: "x" })
13651
13695
  ] }),
13652
- /* @__PURE__ */ jsxs21("div", { className: "df-review-sitemap-controls", children: [
13653
- /* @__PURE__ */ jsxs21("label", { className: "df-review-sitemap-search", children: [
13654
- /* @__PURE__ */ jsx28(Search, { "aria-hidden": "true" }),
13655
- /* @__PURE__ */ jsx28(
13696
+ /* @__PURE__ */ jsxs22("div", { className: "df-review-sitemap-controls", children: [
13697
+ /* @__PURE__ */ jsxs22("label", { className: "df-review-sitemap-search", children: [
13698
+ /* @__PURE__ */ jsx29(Search, { "aria-hidden": "true" }),
13699
+ /* @__PURE__ */ jsx29(
13656
13700
  "input",
13657
13701
  {
13658
13702
  "aria-label": "Search sitemap",
@@ -13664,20 +13708,20 @@ var SitemapModal = ({
13664
13708
  }
13665
13709
  )
13666
13710
  ] }),
13667
- trimmedSearchQuery && /* @__PURE__ */ jsx28(
13711
+ trimmedSearchQuery && /* @__PURE__ */ jsx29(
13668
13712
  "button",
13669
13713
  {
13670
13714
  "aria-label": "Clear sitemap search",
13671
13715
  className: "df-review-sitemap-search-clear",
13672
13716
  type: "button",
13673
13717
  onClick: () => setSearchQuery(""),
13674
- children: /* @__PURE__ */ jsx28(X, { "aria-hidden": "true" })
13718
+ children: /* @__PURE__ */ jsx29(X, { "aria-hidden": "true" })
13675
13719
  }
13676
13720
  ),
13677
- /* @__PURE__ */ jsx28("span", { className: "df-review-sitemap-search-count", children: trimmedSearchQuery ? `${matchingPageCount} matches` : `${pages.length} pages` })
13721
+ /* @__PURE__ */ jsx29("span", { className: "df-review-sitemap-search-count", children: isFiltering ? `${matchingPageCount} matches` : `${pages.length} pages` })
13678
13722
  ] }),
13679
- /* @__PURE__ */ jsxs21("div", { className: "df-review-sitemap-list", style: gridStyle, children: [
13680
- /* @__PURE__ */ jsx28("div", { className: "df-review-sitemap-table-head", role: "row", children: sortHeaders.map((header) => /* @__PURE__ */ jsxs21(
13723
+ /* @__PURE__ */ jsxs22("div", { className: "df-review-sitemap-list", style: gridStyle, children: [
13724
+ /* @__PURE__ */ jsx29("div", { className: "df-review-sitemap-table-head", role: "row", children: sortHeaders.map((header) => /* @__PURE__ */ jsxs22(
13681
13725
  "button",
13682
13726
  {
13683
13727
  "aria-label": `Sort sitemap by ${header.title ?? header.label}`,
@@ -13690,7 +13734,7 @@ var SitemapModal = ({
13690
13734
  type: "button",
13691
13735
  onClick: () => setSortKey(header.key),
13692
13736
  children: [
13693
- /* @__PURE__ */ jsx28(
13737
+ /* @__PURE__ */ jsx29(
13694
13738
  "span",
13695
13739
  {
13696
13740
  "aria-hidden": "true",
@@ -13698,7 +13742,7 @@ var SitemapModal = ({
13698
13742
  children: getSortIndicator(sort, header.key)
13699
13743
  }
13700
13744
  ),
13701
- /* @__PURE__ */ jsx28("span", { className: "df-review-sitemap-sort-label", children: header.label })
13745
+ /* @__PURE__ */ jsx29("span", { className: "df-review-sitemap-sort-label", children: header.label })
13702
13746
  ]
13703
13747
  },
13704
13748
  header.key
@@ -13713,7 +13757,7 @@ var SitemapModal = ({
13713
13757
  row.isActive ? "is-active" : "",
13714
13758
  row.isPage ? "is-clickable" : ""
13715
13759
  ].filter(Boolean).join(" ");
13716
- const rowContent = /* @__PURE__ */ jsx28(
13760
+ const rowContent = /* @__PURE__ */ jsx29(
13717
13761
  SitemapRowContent,
13718
13762
  {
13719
13763
  depth: row.depth,
@@ -13726,7 +13770,7 @@ var SitemapModal = ({
13726
13770
  onToggleFolder: () => toggleFolder(row.href)
13727
13771
  }
13728
13772
  );
13729
- return /* @__PURE__ */ jsx28(
13773
+ return /* @__PURE__ */ jsx29(
13730
13774
  "div",
13731
13775
  {
13732
13776
  "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`,
@@ -13745,15 +13789,15 @@ var SitemapModal = ({
13745
13789
  row.href
13746
13790
  );
13747
13791
  }),
13748
- sitemapRows.length === 0 && /* @__PURE__ */ jsx28("div", { className: "df-review-sitemap-empty", role: "status", children: "No matching pages" }),
13749
- /* @__PURE__ */ jsx28(
13792
+ sitemapRows.length === 0 && /* @__PURE__ */ jsx29("div", { className: "df-review-sitemap-empty", role: "status", children: "No matching pages" }),
13793
+ /* @__PURE__ */ jsx29(
13750
13794
  "button",
13751
13795
  {
13752
13796
  "aria-label": `All QA / ${allQaCount.status.todo} todo / ${allQaCount.status.review} review / ${allQaCount.status.hold} hold`,
13753
13797
  className: `df-review-sitemap-row is-summary${isAllQaVisible ? " is-active" : ""}`,
13754
13798
  type: "button",
13755
13799
  onClick: onSelectAllQa,
13756
- children: /* @__PURE__ */ jsx28(
13800
+ children: /* @__PURE__ */ jsx29(
13757
13801
  SitemapRowContent,
13758
13802
  {
13759
13803
  depth: 0,
@@ -13773,55 +13817,6 @@ var SitemapModal = ({
13773
13817
  }
13774
13818
  );
13775
13819
  };
13776
- var SitemapRowContent = ({
13777
- depth,
13778
- hasChildren,
13779
- isExpanded,
13780
- isPage,
13781
- label,
13782
- qaCount,
13783
- users,
13784
- onToggleFolder
13785
- }) => /* @__PURE__ */ jsxs21(Fragment2, { children: [
13786
- /* @__PURE__ */ jsxs21(
13787
- "span",
13788
- {
13789
- className: "df-review-sitemap-path",
13790
- style: { "--df-review-sitemap-depth": depth },
13791
- children: [
13792
- hasChildren ? /* @__PURE__ */ jsx28(
13793
- "button",
13794
- {
13795
- "aria-expanded": isExpanded,
13796
- "aria-label": `${isExpanded ? "Collapse" : "Expand"} ${label}`,
13797
- className: "df-review-sitemap-tree-toggle",
13798
- type: "button",
13799
- onClick: (event) => {
13800
- event.stopPropagation();
13801
- onToggleFolder?.();
13802
- },
13803
- children: isExpanded ? /* @__PURE__ */ jsx28(ChevronDown, { "aria-hidden": "true" }) : /* @__PURE__ */ jsx28(ChevronRight, { "aria-hidden": "true" })
13804
- }
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 })
13807
- ]
13808
- }
13809
- ),
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(
13814
- "span",
13815
- {
13816
- className: "df-review-sitemap-user",
13817
- style: {
13818
- "--df-review-presence-color": user.color
13819
- },
13820
- children: user.userId
13821
- },
13822
- user.sessionId
13823
- )) }) : null })
13824
- ] });
13825
13820
 
13826
13821
  // src/react-shell/hooks/use.review.shell.data.ts
13827
13822
  import { useCallback as useCallback7, useMemo as useMemo7 } from "react";
@@ -13978,7 +13973,7 @@ var useReviewShellData = () => {
13978
13973
  };
13979
13974
 
13980
13975
  // src/react-shell/review/shell.modals.container.tsx
13981
- import { Fragment as Fragment3, jsx as jsx29, jsxs as jsxs22 } from "react/jsx-runtime";
13976
+ import { Fragment as Fragment4, jsx as jsx30, jsxs as jsxs23 } from "react/jsx-runtime";
13982
13977
  var ReviewShellModalsContainer = () => {
13983
13978
  const { initialPrompt, pages } = useReviewShellConfig();
13984
13979
  const {
@@ -14035,6 +14030,10 @@ var ReviewShellModalsContainer = () => {
14035
14030
  (state) => state.setIsSitemapOpen
14036
14031
  );
14037
14032
  const showToast = useReviewToast();
14033
+ const [hasSitemapOpened, setHasSitemapOpened] = useState9(false);
14034
+ useEffect8(() => {
14035
+ if (isSitemapOpen) setHasSitemapOpened(true);
14036
+ }, [isSitemapOpen]);
14038
14037
  const initialPromptText = initialPrompt.trim();
14039
14038
  const copyInitialPrompt = useCallback8(
14040
14039
  (value, key) => copyReviewPrompt({
@@ -14045,10 +14044,11 @@ var ReviewShellModalsContainer = () => {
14045
14044
  }),
14046
14045
  [setCopiedPromptKey, showToast]
14047
14046
  );
14048
- return /* @__PURE__ */ jsxs22(Fragment3, { children: [
14049
- isSitemapOpen && /* @__PURE__ */ jsx29(
14047
+ return /* @__PURE__ */ jsxs23(Fragment4, { children: [
14048
+ hasSitemapOpened && /* @__PURE__ */ jsx30(
14050
14049
  SitemapModal,
14051
14050
  {
14051
+ isOpen: isSitemapOpen,
14052
14052
  activeRoute,
14053
14053
  allQaCount,
14054
14054
  getPageTarget,
@@ -14061,7 +14061,7 @@ var ReviewShellModalsContainer = () => {
14061
14061
  onSelectPage: selectPage
14062
14062
  }
14063
14063
  ),
14064
- isFigmaSettingsOpen && /* @__PURE__ */ jsx29(
14064
+ isFigmaSettingsOpen && /* @__PURE__ */ jsx30(
14065
14065
  ReviewSettingsModal,
14066
14066
  {
14067
14067
  areTooltipsEnabledDraft,
@@ -14082,8 +14082,8 @@ var ReviewShellModalsContainer = () => {
14082
14082
  onToggleFigmaTokenVisible: () => setIsFigmaTokenVisible((current) => !current)
14083
14083
  }
14084
14084
  ),
14085
- isInitialPromptOpen && /* @__PURE__ */ jsx29(PromptModal, { onClose: () => setIsInitialPromptOpen(false) }),
14086
- isInitialPromptScriptOpen && /* @__PURE__ */ jsx29(
14085
+ isInitialPromptOpen && /* @__PURE__ */ jsx30(PromptModal, { onClose: () => setIsInitialPromptOpen(false) }),
14086
+ isInitialPromptScriptOpen && /* @__PURE__ */ jsx30(
14087
14087
  InitialPromptModal,
14088
14088
  {
14089
14089
  copiedPromptKey,
@@ -14147,7 +14147,7 @@ var useReviewSourceInspectorState = () => {
14147
14147
  };
14148
14148
 
14149
14149
  // src/react-shell/review/shell.providers.tsx
14150
- import { jsx as jsx30 } from "react/jsx-runtime";
14150
+ import { jsx as jsx31 } from "react/jsx-runtime";
14151
14151
  var ReviewShellProviders = ({
14152
14152
  actions,
14153
14153
  children,
@@ -14157,17 +14157,17 @@ var ReviewShellProviders = ({
14157
14157
  ruler,
14158
14158
  settings,
14159
14159
  sourceInspector
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 }) }) }) }) }) }) });
14160
+ }) => /* @__PURE__ */ jsx31(ReviewShellActionsProvider, { value: actions, children: /* @__PURE__ */ jsx31(ReviewRulerProvider, { value: ruler, children: /* @__PURE__ */ jsx31(ReviewFigmaImagesProvider, { value: figmaImages, children: /* @__PURE__ */ jsx31(ReviewSourceInspectorProvider, { value: sourceInspector, children: /* @__PURE__ */ jsx31(ReviewSettingsProvider, { value: settings, children: /* @__PURE__ */ jsx31(ReviewPresenceProvider, { value: presence, children: /* @__PURE__ */ jsx31(ReviewFigmaOverlayProvider, { value: figmaOverlay, children }) }) }) }) }) }) });
14161
14161
 
14162
14162
  // src/react-shell/review/source.inspector.overlay.tsx
14163
- import { Fragment as Fragment4, jsx as jsx31, jsxs as jsxs23 } from "react/jsx-runtime";
14163
+ import { Fragment as Fragment5, jsx as jsx32, jsxs as jsxs24 } from "react/jsx-runtime";
14164
14164
  var SourceInspectorOverlay = ({
14165
14165
  componentSelectionState,
14166
14166
  state
14167
14167
  }) => {
14168
14168
  const hoverState = state?.targetElement === componentSelectionState?.targetElement ? null : state;
14169
- return /* @__PURE__ */ jsxs23(Fragment4, { children: [
14170
- componentSelectionState ? /* @__PURE__ */ jsx31(
14169
+ return /* @__PURE__ */ jsxs24(Fragment5, { children: [
14170
+ componentSelectionState ? /* @__PURE__ */ jsx32(
14171
14171
  "div",
14172
14172
  {
14173
14173
  className: "df-review-source-outline is-component-selection",
@@ -14179,7 +14179,7 @@ var SourceInspectorOverlay = ({
14179
14179
  }
14180
14180
  }
14181
14181
  ) : null,
14182
- hoverState ? /* @__PURE__ */ jsx31(
14182
+ hoverState ? /* @__PURE__ */ jsx32(
14183
14183
  "div",
14184
14184
  {
14185
14185
  className: "df-review-source-outline is-hover",
@@ -14195,10 +14195,10 @@ var SourceInspectorOverlay = ({
14195
14195
  };
14196
14196
 
14197
14197
  // src/react-shell/review/source.inspector.overlay.container.tsx
14198
- import { jsx as jsx32 } from "react/jsx-runtime";
14198
+ import { jsx as jsx33 } from "react/jsx-runtime";
14199
14199
  var SourceInspectorOverlayContainer = () => {
14200
14200
  const { componentSelectionState, sourceInspectorState } = useReviewSourceInspectorState();
14201
- return /* @__PURE__ */ jsx32(
14201
+ return /* @__PURE__ */ jsx33(
14202
14202
  SourceInspectorOverlay,
14203
14203
  {
14204
14204
  componentSelectionState,
@@ -14213,7 +14213,7 @@ import {
14213
14213
  } from "react";
14214
14214
 
14215
14215
  // src/react-shell/review/mode.toolbar.tsx
14216
- import { jsx as jsx33, jsxs as jsxs24 } from "react/jsx-runtime";
14216
+ import { jsx as jsx34, jsxs as jsxs25 } from "react/jsx-runtime";
14217
14217
  var ReviewModeToolbar = ({
14218
14218
  canWriteArea,
14219
14219
  canWriteDom,
@@ -14221,8 +14221,8 @@ var ReviewModeToolbar = ({
14221
14221
  onSetReviewMode
14222
14222
  }) => {
14223
14223
  if (!canWriteDom && !canWriteArea) return null;
14224
- return /* @__PURE__ */ jsxs24("div", { className: "df-review-mode", "aria-label": "Add QA", children: [
14225
- canWriteDom && /* @__PURE__ */ jsx33(
14224
+ return /* @__PURE__ */ jsxs25("div", { className: "df-review-mode", "aria-label": "Add QA", children: [
14225
+ canWriteDom && /* @__PURE__ */ jsx34(
14226
14226
  "button",
14227
14227
  {
14228
14228
  "aria-label": "Element",
@@ -14230,11 +14230,11 @@ var ReviewModeToolbar = ({
14230
14230
  "data-review-tooltip": "Element QA",
14231
14231
  type: "button",
14232
14232
  onClick: () => onSetReviewMode("element"),
14233
- children: /* @__PURE__ */ jsx33(SquareMousePointer, { "aria-hidden": "true" })
14233
+ children: /* @__PURE__ */ jsx34(SquareMousePointer, { "aria-hidden": "true" })
14234
14234
  }
14235
14235
  ),
14236
- canWriteDom && canWriteArea && /* @__PURE__ */ jsx33("span", { className: "df-review-mode-divider", "aria-hidden": "true", children: "|" }),
14237
- canWriteArea && /* @__PURE__ */ jsx33(
14236
+ canWriteDom && canWriteArea && /* @__PURE__ */ jsx34("span", { className: "df-review-mode-divider", "aria-hidden": "true", children: "|" }),
14237
+ canWriteArea && /* @__PURE__ */ jsx34(
14238
14238
  "button",
14239
14239
  {
14240
14240
  "aria-label": "Area",
@@ -14242,14 +14242,14 @@ var ReviewModeToolbar = ({
14242
14242
  "data-review-tooltip": "Area QA",
14243
14243
  type: "button",
14244
14244
  onClick: () => onSetReviewMode("area"),
14245
- children: /* @__PURE__ */ jsx33(Scan, { "aria-hidden": "true" })
14245
+ children: /* @__PURE__ */ jsx34(Scan, { "aria-hidden": "true" })
14246
14246
  }
14247
14247
  )
14248
14248
  ] });
14249
14249
  };
14250
14250
 
14251
14251
  // src/react-shell/ruler/gutters.tsx
14252
- import { Fragment as Fragment5, jsx as jsx34, jsxs as jsxs25 } from "react/jsx-runtime";
14252
+ import { Fragment as Fragment6, jsx as jsx35, jsxs as jsxs26 } from "react/jsx-runtime";
14253
14253
  var RulerGutters = () => {
14254
14254
  const size = useReviewShellStore((state) => state.size);
14255
14255
  const {
@@ -14258,9 +14258,9 @@ var RulerGutters = () => {
14258
14258
  rulerScaleY,
14259
14259
  rulerUnit
14260
14260
  } = useReviewRulerState();
14261
- return /* @__PURE__ */ jsxs25(Fragment5, { children: [
14262
- /* @__PURE__ */ jsx34("div", { className: "df-review-ruler-corner", "aria-hidden": "true" }),
14263
- /* @__PURE__ */ jsxs25(
14261
+ return /* @__PURE__ */ jsxs26(Fragment6, { children: [
14262
+ /* @__PURE__ */ jsx35("div", { className: "df-review-ruler-corner", "aria-hidden": "true" }),
14263
+ /* @__PURE__ */ jsxs26(
14264
14264
  "div",
14265
14265
  {
14266
14266
  className: "df-review-ruler-gutter is-x",
@@ -14268,15 +14268,15 @@ var RulerGutters = () => {
14268
14268
  "--df-review-ruler-step-x": `${rulerScaleX * 20}px`
14269
14269
  },
14270
14270
  children: [
14271
- /* @__PURE__ */ jsxs25("div", { className: "df-review-ruler-frame-label", children: [
14272
- /* @__PURE__ */ jsx34("strong", { children: size.label }),
14273
- /* @__PURE__ */ jsxs25("span", { children: [
14271
+ /* @__PURE__ */ jsxs26("div", { className: "df-review-ruler-frame-label", children: [
14272
+ /* @__PURE__ */ jsx35("strong", { children: size.label }),
14273
+ /* @__PURE__ */ jsxs26("span", { children: [
14274
14274
  size.designWidth,
14275
14275
  size.designHeight ? `x${size.designHeight}` : "",
14276
14276
  rulerUnit
14277
14277
  ] })
14278
14278
  ] }),
14279
- rulerHover && /* @__PURE__ */ jsx34(
14279
+ rulerHover && /* @__PURE__ */ jsx35(
14280
14280
  "div",
14281
14281
  {
14282
14282
  className: "df-review-ruler-coord is-x",
@@ -14287,14 +14287,14 @@ var RulerGutters = () => {
14287
14287
  ]
14288
14288
  }
14289
14289
  ),
14290
- /* @__PURE__ */ jsx34(
14290
+ /* @__PURE__ */ jsx35(
14291
14291
  "div",
14292
14292
  {
14293
14293
  className: "df-review-ruler-gutter is-y",
14294
14294
  style: {
14295
14295
  "--df-review-ruler-step-y": `${rulerScaleY * 20}px`
14296
14296
  },
14297
- children: rulerHover && /* @__PURE__ */ jsx34(
14297
+ children: rulerHover && /* @__PURE__ */ jsx35(
14298
14298
  "div",
14299
14299
  {
14300
14300
  className: "df-review-ruler-coord is-y",
@@ -14308,7 +14308,7 @@ var RulerGutters = () => {
14308
14308
  };
14309
14309
 
14310
14310
  // src/react-shell/ruler/overlay.tsx
14311
- import { Fragment as Fragment6, jsx as jsx35, jsxs as jsxs26 } from "react/jsx-runtime";
14311
+ import { Fragment as Fragment7, jsx as jsx36, jsxs as jsxs27 } from "react/jsx-runtime";
14312
14312
  var RulerOverlay = () => {
14313
14313
  const { iframeRef } = useReviewShellRefs();
14314
14314
  const size = useReviewShellStore((state) => state.size);
@@ -14319,7 +14319,7 @@ var RulerOverlay = () => {
14319
14319
  rulerMeasureLabel,
14320
14320
  rulerOverlayRef
14321
14321
  } = useReviewRulerState();
14322
- return /* @__PURE__ */ jsxs26(
14322
+ return /* @__PURE__ */ jsxs27(
14323
14323
  "div",
14324
14324
  {
14325
14325
  ref: rulerOverlayRef,
@@ -14333,8 +14333,8 @@ var RulerOverlay = () => {
14333
14333
  );
14334
14334
  },
14335
14335
  children: [
14336
- rulerHover && /* @__PURE__ */ jsxs26(Fragment6, { children: [
14337
- /* @__PURE__ */ jsx35(
14336
+ rulerHover && /* @__PURE__ */ jsxs27(Fragment7, { children: [
14337
+ /* @__PURE__ */ jsx36(
14338
14338
  "div",
14339
14339
  {
14340
14340
  className: "df-review-ruler-guide is-x",
@@ -14342,7 +14342,7 @@ var RulerOverlay = () => {
14342
14342
  style: { top: `${rulerHover.y}px` }
14343
14343
  }
14344
14344
  ),
14345
- /* @__PURE__ */ jsx35(
14345
+ /* @__PURE__ */ jsx36(
14346
14346
  "div",
14347
14347
  {
14348
14348
  className: "df-review-ruler-guide is-y",
@@ -14351,8 +14351,8 @@ var RulerOverlay = () => {
14351
14351
  }
14352
14352
  )
14353
14353
  ] }),
14354
- rulerMeasure && (rulerMeasure.width > 0 || rulerMeasure.height > 0) && /* @__PURE__ */ jsxs26(Fragment6, { children: [
14355
- /* @__PURE__ */ jsx35(
14354
+ rulerMeasure && (rulerMeasure.width > 0 || rulerMeasure.height > 0) && /* @__PURE__ */ jsxs27(Fragment7, { children: [
14355
+ /* @__PURE__ */ jsx36(
14356
14356
  "div",
14357
14357
  {
14358
14358
  className: "df-review-ruler-selection",
@@ -14365,7 +14365,7 @@ var RulerOverlay = () => {
14365
14365
  }
14366
14366
  }
14367
14367
  ),
14368
- /* @__PURE__ */ jsx35(
14368
+ /* @__PURE__ */ jsx36(
14369
14369
  "div",
14370
14370
  {
14371
14371
  className: "df-review-ruler-label",
@@ -14389,7 +14389,7 @@ var RulerOverlay = () => {
14389
14389
  };
14390
14390
 
14391
14391
  // src/react-shell/target/figma.image.overlay.ts
14392
- import { useCallback as useCallback9, useEffect as useEffect8, useRef as useRef7 } from "react";
14392
+ import { useCallback as useCallback9, useEffect as useEffect9, useRef as useRef7 } from "react";
14393
14393
 
14394
14394
  // src/react-shell/target/target.ts
14395
14395
  var HIDE_SCROLLBAR_STYLE_ID = "df-review-hide-scrollbar";
@@ -14491,13 +14491,6 @@ var setTargetFigmaSourceSelectLocked = (targetDocument, locked) => {
14491
14491
  locked
14492
14492
  );
14493
14493
  };
14494
- var isEditableEventTarget = (event) => {
14495
- const path = event.composedPath?.() ?? [];
14496
- const element = path[0] ?? event.target;
14497
- if (!element || typeof element.tagName !== "string") return false;
14498
- const tag = element.tagName;
14499
- return tag === "INPUT" || tag === "TEXTAREA" || element.isContentEditable === true;
14500
- };
14501
14494
  var TRUE_STORAGE_VALUES = /* @__PURE__ */ new Set([
14502
14495
  "1",
14503
14496
  "true",
@@ -14608,10 +14601,10 @@ var useTargetFigmaImageOverlays = ({
14608
14601
  size,
14609
14602
  targetSrc
14610
14603
  ]);
14611
- useEffect8(() => {
14604
+ useEffect9(() => {
14612
14605
  syncTargetFigmaImageOverlays();
14613
14606
  }, [syncTargetFigmaImageOverlays]);
14614
- useEffect8(() => {
14607
+ useEffect9(() => {
14615
14608
  return () => {
14616
14609
  if (!targetDocumentRef.current) return;
14617
14610
  removeTargetFigmaImageOverlays(targetDocumentRef.current);
@@ -14822,12 +14815,12 @@ function normalizeTargetFigmaImageOffsetY(value) {
14822
14815
 
14823
14816
  // src/react-shell/target/outside.markers.tsx
14824
14817
  import {
14825
- useEffect as useEffect9,
14818
+ useEffect as useEffect10,
14826
14819
  useMemo as useMemo8,
14827
14820
  useRef as useRef8,
14828
- useState as useState9
14821
+ useState as useState10
14829
14822
  } from "react";
14830
- import { jsx as jsx36 } from "react/jsx-runtime";
14823
+ import { jsx as jsx37 } from "react/jsx-runtime";
14831
14824
  var OUTSIDE_MARKER_HEIGHT = 22;
14832
14825
  var OUTSIDE_MARKER_CONNECTOR_TOP = 10;
14833
14826
  var OUTSIDE_MARKER_GAP = 6;
@@ -14941,9 +14934,9 @@ var ReviewOutsideMarkers = () => {
14941
14934
  (state) => state.setIsListVisible
14942
14935
  );
14943
14936
  const setSidePanel = useReviewShellStore((state) => state.setSidePanel);
14944
- const [layoutVersion, setLayoutVersion] = useState9(0);
14937
+ const [layoutVersion, setLayoutVersion] = useState10(0);
14945
14938
  const frameUpdateRef = useRef8(null);
14946
- useEffect9(() => {
14939
+ useEffect10(() => {
14947
14940
  const targetWindow = iframeRef.current?.contentWindow;
14948
14941
  const frameScroll = frameScrollRef.current;
14949
14942
  if (!targetWindow) return void 0;
@@ -15005,7 +14998,7 @@ var ReviewOutsideMarkers = () => {
15005
14998
  size
15006
14999
  ]);
15007
15000
  if (markers.length === 0) return null;
15008
- return /* @__PURE__ */ jsx36("div", { className: "df-review-outside-marker-layer", "aria-label": "QA markers", children: markers.map((marker) => {
15001
+ return /* @__PURE__ */ jsx37("div", { className: "df-review-outside-marker-layer", "aria-label": "QA markers", children: markers.map((marker) => {
15009
15002
  const isActive = marker.item.id === selectedItemId;
15010
15003
  const style = {
15011
15004
  top: `${marker.top}px`,
@@ -15014,7 +15007,7 @@ var ReviewOutsideMarkers = () => {
15014
15007
  "--df-review-outside-marker-connector-stem-height": `${marker.connectorStemHeight}px`,
15015
15008
  "--df-review-outside-marker-z-index": isActive ? 2 : 1
15016
15009
  };
15017
- return /* @__PURE__ */ jsx36(
15010
+ return /* @__PURE__ */ jsx37(
15018
15011
  "button",
15019
15012
  {
15020
15013
  "aria-label": `Focus ${marker.label}`,
@@ -15036,7 +15029,7 @@ var ReviewOutsideMarkers = () => {
15036
15029
  };
15037
15030
 
15038
15031
  // src/react-shell/target/frame.tsx
15039
- import { jsx as jsx37, jsxs as jsxs27 } from "react/jsx-runtime";
15032
+ import { jsx as jsx38, jsxs as jsxs28 } from "react/jsx-runtime";
15040
15033
  var ReviewTargetFrame = () => {
15041
15034
  const {
15042
15035
  figmaImageOverlays,
@@ -15071,15 +15064,15 @@ var ReviewTargetFrame = () => {
15071
15064
  syncTargetFigmaImageOverlays();
15072
15065
  window.requestAnimationFrame(syncTargetFigmaImageOverlays);
15073
15066
  };
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(
15067
+ return /* @__PURE__ */ jsx38("main", { className: "df-review-stage", children: /* @__PURE__ */ jsxs28("div", { className: "df-review-frame", children: [
15068
+ /* @__PURE__ */ jsx38("div", { className: "df-review-frame-scroll", ref: frameScrollRef, children: /* @__PURE__ */ jsx38("div", { className: "df-review-frame-canvas", children: /* @__PURE__ */ jsx38("div", { className: "df-review-target-stack", children: /* @__PURE__ */ jsxs28(
15076
15069
  "div",
15077
15070
  {
15078
15071
  className: `df-review-device-frame${showRuler ? " is-ruler" : ""}`,
15079
15072
  children: [
15080
- showRuler && /* @__PURE__ */ jsx37(RulerGutters, {}),
15081
- /* @__PURE__ */ jsx37(ReviewOutsideMarkers, {}),
15082
- /* @__PURE__ */ jsxs27(
15073
+ showRuler && /* @__PURE__ */ jsx38(RulerGutters, {}),
15074
+ /* @__PURE__ */ jsx38(ReviewOutsideMarkers, {}),
15075
+ /* @__PURE__ */ jsxs28(
15083
15076
  "div",
15084
15077
  {
15085
15078
  className: "df-review-device",
@@ -15090,7 +15083,7 @@ var ReviewTargetFrame = () => {
15090
15083
  minHeight: `${size.height}px`
15091
15084
  },
15092
15085
  children: [
15093
- /* @__PURE__ */ jsx37(
15086
+ /* @__PURE__ */ jsx38(
15094
15087
  "iframe",
15095
15088
  {
15096
15089
  ref: iframeRef,
@@ -15102,14 +15095,14 @@ var ReviewTargetFrame = () => {
15102
15095
  },
15103
15096
  `${frameTargetSrc}:${frameNavigationVersion}`
15104
15097
  ),
15105
- showRuler && /* @__PURE__ */ jsx37(RulerOverlay, {})
15098
+ showRuler && /* @__PURE__ */ jsx38(RulerOverlay, {})
15106
15099
  ]
15107
15100
  }
15108
15101
  )
15109
15102
  ]
15110
15103
  }
15111
15104
  ) }) }) }),
15112
- /* @__PURE__ */ jsx37("div", { className: "df-review-frame-actions", children: /* @__PURE__ */ jsx37(
15105
+ /* @__PURE__ */ jsx38("div", { className: "df-review-frame-actions", children: /* @__PURE__ */ jsx38(
15113
15106
  ReviewModeToolbar,
15114
15107
  {
15115
15108
  canWriteArea,
@@ -15122,21 +15115,21 @@ var ReviewTargetFrame = () => {
15122
15115
  };
15123
15116
 
15124
15117
  // src/react-shell/topbar.container.tsx
15125
- import { useState as useState10 } from "react";
15118
+ import { useState as useState11 } from "react";
15126
15119
 
15127
15120
  // src/react-shell/topbar.tsx
15128
- import { jsx as jsx38, jsxs as jsxs28 } from "react/jsx-runtime";
15121
+ import { jsx as jsx39, jsxs as jsxs29 } from "react/jsx-runtime";
15129
15122
  var ReviewScopeIcon2 = ({ scope }) => {
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" });
15123
+ if (scope === "mobile") return /* @__PURE__ */ jsx39(Smartphone, { "aria-hidden": "true" });
15124
+ if (scope === "tablet") return /* @__PURE__ */ jsx39(RectangleHorizontal, { "aria-hidden": "true" });
15125
+ if (scope === "wide") return /* @__PURE__ */ jsx39(Maximize2, { "aria-hidden": "true" });
15126
+ if (scope === "dom") return /* @__PURE__ */ jsx39(SquareMousePointer, { "aria-hidden": "true" });
15127
+ return /* @__PURE__ */ jsx39(Monitor, { "aria-hidden": "true" });
15135
15128
  };
15136
15129
  var ViewportPresetIcon = ({
15137
15130
  preset
15138
15131
  }) => {
15139
- return /* @__PURE__ */ jsx38(ReviewScopeIcon2, { scope: getViewportPresetKind(preset) });
15132
+ return /* @__PURE__ */ jsx39(ReviewScopeIcon2, { scope: getViewportPresetKind(preset) });
15140
15133
  };
15141
15134
  var getPresetSelectValue = (preset) => `${preset.label}:${preset.width}x${preset.height}`;
15142
15135
  function getTargetOpenHref(targetSrc) {
@@ -15173,8 +15166,8 @@ var ReviewTopbar = ({
15173
15166
  );
15174
15167
  if (nextPreset) onSizeChange(nextPreset);
15175
15168
  };
15176
- return /* @__PURE__ */ jsxs28("header", { className: "df-review-topbar", children: [
15177
- /* @__PURE__ */ jsxs28(
15169
+ return /* @__PURE__ */ jsxs29("header", { className: "df-review-topbar", children: [
15170
+ /* @__PURE__ */ jsxs29(
15178
15171
  "form",
15179
15172
  {
15180
15173
  className: "df-review-address",
@@ -15183,7 +15176,7 @@ var ReviewTopbar = ({
15183
15176
  onApplyTarget();
15184
15177
  },
15185
15178
  children: [
15186
- /* @__PURE__ */ jsx38(
15179
+ /* @__PURE__ */ jsx39(
15187
15180
  "button",
15188
15181
  {
15189
15182
  "aria-label": "Open sitemap",
@@ -15192,10 +15185,10 @@ var ReviewTopbar = ({
15192
15185
  "data-review-tooltip-placement": "bottom",
15193
15186
  type: "button",
15194
15187
  onClick: onOpenSitemap,
15195
- children: /* @__PURE__ */ jsx38(Map2, { "aria-hidden": "true" })
15188
+ children: /* @__PURE__ */ jsx39(Map2, { "aria-hidden": "true" })
15196
15189
  }
15197
15190
  ),
15198
- /* @__PURE__ */ jsx38(
15191
+ /* @__PURE__ */ jsx39(
15199
15192
  "input",
15200
15193
  {
15201
15194
  "aria-label": "Path",
@@ -15203,8 +15196,8 @@ var ReviewTopbar = ({
15203
15196
  onChange: (event) => onDraftTargetChange(event.target.value)
15204
15197
  }
15205
15198
  ),
15206
- /* @__PURE__ */ jsxs28("div", { className: "df-review-address-actions", children: [
15207
- /* @__PURE__ */ jsx38(
15199
+ /* @__PURE__ */ jsxs29("div", { className: "df-review-address-actions", children: [
15200
+ /* @__PURE__ */ jsx39(
15208
15201
  "button",
15209
15202
  {
15210
15203
  "aria-label": "Refresh target",
@@ -15213,10 +15206,10 @@ var ReviewTopbar = ({
15213
15206
  "data-review-tooltip-placement": "bottom",
15214
15207
  title: "Refresh target",
15215
15208
  type: "submit",
15216
- children: /* @__PURE__ */ jsx38(RefreshCw, { "aria-hidden": "true" })
15209
+ children: /* @__PURE__ */ jsx39(RefreshCw, { "aria-hidden": "true" })
15217
15210
  }
15218
15211
  ),
15219
- /* @__PURE__ */ jsx38(
15212
+ /* @__PURE__ */ jsx39(
15220
15213
  "button",
15221
15214
  {
15222
15215
  "aria-label": copyLabel,
@@ -15226,10 +15219,10 @@ var ReviewTopbar = ({
15226
15219
  title: copyLabel,
15227
15220
  type: "button",
15228
15221
  onClick: onCopyCurrentUrl,
15229
- children: /* @__PURE__ */ jsx38(Copy, { "aria-hidden": "true" })
15222
+ children: /* @__PURE__ */ jsx39(Copy, { "aria-hidden": "true" })
15230
15223
  }
15231
15224
  ),
15232
- /* @__PURE__ */ jsx38(
15225
+ /* @__PURE__ */ jsx39(
15233
15226
  "a",
15234
15227
  {
15235
15228
  "aria-label": "Open target page",
@@ -15240,30 +15233,30 @@ var ReviewTopbar = ({
15240
15233
  rel: "noreferrer",
15241
15234
  target: "_blank",
15242
15235
  title: "Open target page",
15243
- children: /* @__PURE__ */ jsx38(ExternalLink, { "aria-hidden": "true" })
15236
+ children: /* @__PURE__ */ jsx39(ExternalLink, { "aria-hidden": "true" })
15244
15237
  }
15245
15238
  )
15246
15239
  ] })
15247
15240
  ]
15248
15241
  }
15249
15242
  ),
15250
- /* @__PURE__ */ jsxs28("div", { className: "df-review-tools", children: [
15251
- /* @__PURE__ */ jsxs28("div", { className: "df-review-tool-controls", children: [
15252
- /* @__PURE__ */ jsx38("div", { className: "df-review-presets", "aria-label": "Viewport presets", children: viewportPresets.map((preset) => /* @__PURE__ */ jsxs28(
15243
+ /* @__PURE__ */ jsxs29("div", { className: "df-review-tools", children: [
15244
+ /* @__PURE__ */ jsxs29("div", { className: "df-review-tool-controls", children: [
15245
+ /* @__PURE__ */ jsx39("div", { className: "df-review-presets", "aria-label": "Viewport presets", children: viewportPresets.map((preset) => /* @__PURE__ */ jsxs29(
15253
15246
  "button",
15254
15247
  {
15255
15248
  className: preset.label === size.label ? "is-active" : "",
15256
15249
  type: "button",
15257
15250
  onClick: () => onSizeChange(preset),
15258
15251
  children: [
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 })
15252
+ /* @__PURE__ */ jsx39(ViewportPresetIcon, { preset }),
15253
+ /* @__PURE__ */ jsx39("span", { className: "df-review-preset-copy", children: /* @__PURE__ */ jsx39("strong", { children: preset.label }) }),
15254
+ /* @__PURE__ */ jsx39("span", { className: "df-review-preset-count", children: presetScopeCounts.get(getViewportPresetKind(preset)) ?? 0 })
15262
15255
  ]
15263
15256
  },
15264
15257
  preset.label
15265
15258
  )) }),
15266
- /* @__PURE__ */ jsx38(
15259
+ /* @__PURE__ */ jsx39(
15267
15260
  "select",
15268
15261
  {
15269
15262
  "aria-label": "Viewport preset",
@@ -15273,7 +15266,7 @@ var ReviewTopbar = ({
15273
15266
  children: viewportPresets.map((preset) => {
15274
15267
  const scope = getViewportPresetKind(preset);
15275
15268
  const count = presetScopeCounts.get(scope) ?? 0;
15276
- return /* @__PURE__ */ jsx38(
15269
+ return /* @__PURE__ */ jsx39(
15277
15270
  "option",
15278
15271
  {
15279
15272
  value: getPresetSelectValue(preset),
@@ -15284,15 +15277,15 @@ var ReviewTopbar = ({
15284
15277
  })
15285
15278
  }
15286
15279
  ),
15287
- /* @__PURE__ */ jsx38("span", { className: "df-review-tool-divider", "aria-hidden": "true", children: "|" }),
15288
- /* @__PURE__ */ jsxs28("span", { className: "df-review-active-size", children: [
15280
+ /* @__PURE__ */ jsx39("span", { className: "df-review-tool-divider", "aria-hidden": "true", children: "|" }),
15281
+ /* @__PURE__ */ jsxs29("span", { className: "df-review-active-size", children: [
15289
15282
  size.width,
15290
15283
  "x",
15291
15284
  size.height
15292
15285
  ] })
15293
15286
  ] }),
15294
- /* @__PURE__ */ jsxs28("div", { className: "df-review-overlays", "aria-label": "Target overlays", children: [
15295
- isRulerAvailable && /* @__PURE__ */ jsx38(
15287
+ /* @__PURE__ */ jsxs29("div", { className: "df-review-overlays", "aria-label": "Target overlays", children: [
15288
+ isRulerAvailable && /* @__PURE__ */ jsx39(
15296
15289
  "button",
15297
15290
  {
15298
15291
  "aria-label": "Toggle ruler",
@@ -15301,10 +15294,10 @@ var ReviewTopbar = ({
15301
15294
  "data-review-tooltip-placement": "bottom",
15302
15295
  type: "button",
15303
15296
  onClick: onToggleRuler,
15304
- children: /* @__PURE__ */ jsx38(Ruler, { "aria-hidden": "true" })
15297
+ children: /* @__PURE__ */ jsx39(Ruler, { "aria-hidden": "true" })
15305
15298
  }
15306
15299
  ),
15307
- /* @__PURE__ */ jsx38(
15300
+ /* @__PURE__ */ jsx39(
15308
15301
  "button",
15309
15302
  {
15310
15303
  "aria-label": "Toggle grid overlay",
@@ -15313,10 +15306,10 @@ var ReviewTopbar = ({
15313
15306
  "data-review-tooltip-placement": "bottom",
15314
15307
  type: "button",
15315
15308
  onClick: () => onToggleTargetOverlay("grid"),
15316
- children: /* @__PURE__ */ jsx38(LayoutGrid, { "aria-hidden": "true" })
15309
+ children: /* @__PURE__ */ jsx39(LayoutGrid, { "aria-hidden": "true" })
15317
15310
  }
15318
15311
  ),
15319
- /* @__PURE__ */ jsx38(
15312
+ /* @__PURE__ */ jsx39(
15320
15313
  "button",
15321
15314
  {
15322
15315
  "aria-disabled": !isFigmaOverlayAvailable,
@@ -15327,7 +15320,7 @@ var ReviewTopbar = ({
15327
15320
  disabled: !isFigmaOverlayAvailable,
15328
15321
  type: "button",
15329
15322
  onClick: onToggleFigmaOverlay,
15330
- children: /* @__PURE__ */ jsx38(FigmaMarkIcon, {})
15323
+ children: /* @__PURE__ */ jsx39(FigmaMarkIcon, {})
15331
15324
  }
15332
15325
  )
15333
15326
  ] })
@@ -15336,7 +15329,7 @@ var ReviewTopbar = ({
15336
15329
  };
15337
15330
 
15338
15331
  // src/react-shell/topbar.container.tsx
15339
- import { jsx as jsx39 } from "react/jsx-runtime";
15332
+ import { jsx as jsx40 } from "react/jsx-runtime";
15340
15333
  var TopbarContainer = () => {
15341
15334
  const {
15342
15335
  applyTarget,
@@ -15365,11 +15358,11 @@ var TopbarContainer = () => {
15365
15358
  (state) => state.setIsSitemapOpen
15366
15359
  );
15367
15360
  const setSize = useReviewShellStore((state) => state.setSize);
15368
- const [copyLabel, setCopyLabel] = useState10("Copy URL");
15361
+ const [copyLabel, setCopyLabel] = useState11("Copy URL");
15369
15362
  const copyCurrentUrl = () => copyCurrentReviewUrl({
15370
15363
  onCopyLabelChange: setCopyLabel
15371
15364
  });
15372
- return /* @__PURE__ */ jsx39(
15365
+ return /* @__PURE__ */ jsx40(
15373
15366
  ReviewTopbar,
15374
15367
  {
15375
15368
  draftTarget,
@@ -15396,11 +15389,11 @@ var TopbarContainer = () => {
15396
15389
  };
15397
15390
 
15398
15391
  // src/react-shell/review/toast.container.tsx
15399
- import { jsx as jsx40 } from "react/jsx-runtime";
15392
+ import { jsx as jsx41 } from "react/jsx-runtime";
15400
15393
  var ReviewToastContainer = () => {
15401
15394
  const toastMessage = useReviewShellStore((state) => state.toastMessage);
15402
15395
  if (!toastMessage) return null;
15403
- return /* @__PURE__ */ jsx40("div", { className: "df-review-copy-toast", role: "status", children: toastMessage });
15396
+ return /* @__PURE__ */ jsx41("div", { className: "df-review-copy-toast", role: "status", children: toastMessage });
15404
15397
  };
15405
15398
 
15406
15399
  // src/react-shell/hooks/use.review.shell.runtime.ts
@@ -15410,7 +15403,7 @@ import {
15410
15403
  } from "react";
15411
15404
 
15412
15405
  // src/react-shell/hooks/use.review.command.key.ts
15413
- import { useEffect as useEffect10, useState as useState11 } from "react";
15406
+ import { useEffect as useEffect11, useState as useState12 } from "react";
15414
15407
  var isCommandModifierKeyEvent = (event) => event.key === "Meta" || event.code === "MetaLeft" || event.code === "MetaRight";
15415
15408
  var isCommandKeyDownEvent = (event) => isCommandModifierKeyEvent(event) || event.metaKey;
15416
15409
  function useReviewCommandKey({
@@ -15418,8 +15411,8 @@ function useReviewCommandKey({
15418
15411
  targetFrameLoadVersion,
15419
15412
  targetSrc
15420
15413
  }) {
15421
- const [isCommandKeyPressed, setIsCommandKeyPressed] = useState11(false);
15422
- useEffect10(() => {
15414
+ const [isCommandKeyPressed, setIsCommandKeyPressed] = useState12(false);
15415
+ useEffect11(() => {
15423
15416
  const targetDocument = iframeRef.current?.contentDocument;
15424
15417
  const targetWindow = iframeRef.current?.contentWindow;
15425
15418
  const setCommandKeyPressed = (pressed) => {
@@ -15682,7 +15675,7 @@ function highlightControllerItem(item, controller, isCurrent) {
15682
15675
  // src/react-shell/hooks/use.review.kit.lifecycle.ts
15683
15676
  import {
15684
15677
  useCallback as useCallback11,
15685
- useEffect as useEffect11,
15678
+ useEffect as useEffect12,
15686
15679
  useRef as useRef9
15687
15680
  } from "react";
15688
15681
 
@@ -15805,7 +15798,7 @@ async function captureIframeViewport(frame, input) {
15805
15798
  );
15806
15799
  } catch (error) {
15807
15800
  throw new Error(
15808
- `Selected region capture failed: ${getUnknownErrorMessage(error)}`
15801
+ `Selected region capture failed: ${getCaptureErrorMessage(error)}`
15809
15802
  );
15810
15803
  }
15811
15804
  }
@@ -15818,7 +15811,7 @@ async function captureIframeViewport(frame, input) {
15818
15811
  input
15819
15812
  );
15820
15813
  } catch (error) {
15821
- errors.push(`html2canvas: ${getUnknownErrorMessage(error)}`);
15814
+ errors.push(`html2canvas: ${getCaptureErrorMessage(error)}`);
15822
15815
  }
15823
15816
  const svg = createViewportSvg(targetDocument, targetWindow, viewport, input);
15824
15817
  const svgFile = new Blob([svg], { type: "image/svg+xml;charset=utf-8" });
@@ -15832,7 +15825,7 @@ async function captureIframeViewport(frame, input) {
15832
15825
  input
15833
15826
  );
15834
15827
  } catch (error) {
15835
- errors.push(`svg-canvas: ${getUnknownErrorMessage(error)}`);
15828
+ errors.push(`svg-canvas: ${getCaptureErrorMessage(error)}`);
15836
15829
  }
15837
15830
  return {
15838
15831
  file: svgFile,
@@ -15861,6 +15854,7 @@ async function createHtml2CanvasCapture(targetDocument, targetWindow, viewport,
15861
15854
  onclone: (documentClone) => {
15862
15855
  normalizeUnsupportedCaptureStyles(documentClone);
15863
15856
  normalizeUnsupportedCaptureColors(documentClone);
15857
+ normalizeZeroSizeCaptureGradients(documentClone);
15864
15858
  },
15865
15859
  removeContainer: true,
15866
15860
  scale,
@@ -16060,6 +16054,19 @@ function normalizeUnsupportedCaptureColors(documentClone) {
16060
16054
  }
16061
16055
  });
16062
16056
  }
16057
+ function normalizeZeroSizeCaptureGradients(documentClone) {
16058
+ const view = documentClone.defaultView;
16059
+ if (!view) return;
16060
+ documentClone.documentElement.querySelectorAll("*").forEach(
16061
+ (element) => {
16062
+ const backgroundImage = view.getComputedStyle(element).backgroundImage;
16063
+ if (!backgroundImage.includes("gradient(")) return;
16064
+ const bounds = element.getBoundingClientRect();
16065
+ if (bounds.width > 0 && bounds.height > 0) return;
16066
+ element.style.setProperty("background-image", "none", "important");
16067
+ }
16068
+ );
16069
+ }
16063
16070
  function hasUnsupportedColorFunction(value) {
16064
16071
  return /okl(?:ch|ab)\(|color-mix\(/i.test(value);
16065
16072
  }
@@ -16268,12 +16275,8 @@ function createMarkerSvg(x, y) {
16268
16275
  function formatCaptureTimestamp(timestamp) {
16269
16276
  return timestamp.replace(/[^0-9A-Za-z]+/g, "-").replace(/^-|-$/g, "");
16270
16277
  }
16271
- function getUnknownErrorMessage(error) {
16272
- if (error instanceof Error) return error.message;
16273
- if (error && typeof error === "object" && "message" in error && typeof error.message === "string") {
16274
- return error.message;
16275
- }
16276
- return "Capture was saved as SVG fallback.";
16278
+ function getCaptureErrorMessage(error) {
16279
+ return getErrorMessage(error, "Capture was saved as SVG fallback.");
16277
16280
  }
16278
16281
 
16279
16282
  // src/react-shell/hooks/review.kit.target.ts
@@ -16456,13 +16459,13 @@ var useReviewKitLifecycle = ({
16456
16459
  },
16457
16460
  [controllerRef, onModeChange]
16458
16461
  );
16459
- useEffect11(() => destroyReviewKit, [destroyReviewKit]);
16460
- useEffect11(() => {
16462
+ useEffect12(() => destroyReviewKit, [destroyReviewKit]);
16463
+ useEffect12(() => {
16461
16464
  const frameDocument = iframeRef.current?.contentDocument;
16462
16465
  if (!frameDocument || frameDocument.readyState !== "complete") return;
16463
16466
  initReviewKit();
16464
16467
  }, [iframeRef, initReviewKit]);
16465
- useEffect11(() => {
16468
+ useEffect12(() => {
16466
16469
  hiddenOverlayItemIdListRef.current = hiddenOverlayItemIdList;
16467
16470
  controllerRef.current?.setHiddenItemIds(hiddenOverlayItemIdList);
16468
16471
  }, [controllerRef, hiddenOverlayItemIdList]);
@@ -16475,7 +16478,7 @@ var useReviewKitLifecycle = ({
16475
16478
  };
16476
16479
 
16477
16480
  // src/react-shell/hooks/use.review.target.overlay.ts
16478
- import { useCallback as useCallback12, useEffect as useEffect12, useRef as useRef10 } from "react";
16481
+ import { useCallback as useCallback12, useEffect as useEffect13, useRef as useRef10 } from "react";
16479
16482
  var TARGET_OVERLAY_REFRESH_DELAYS = [80, 240, 600];
16480
16483
  var useReviewTargetOverlay = ({
16481
16484
  iframeRef,
@@ -16546,11 +16549,11 @@ var useReviewTargetOverlay = ({
16546
16549
  },
16547
16550
  [dispatchTargetOverlayHotkey, updateTargetOverlayState]
16548
16551
  );
16549
- useEffect12(() => {
16552
+ useEffect13(() => {
16550
16553
  if (isFigmaOverlayAvailable || !targetOverlayState.figma) return;
16551
16554
  closeTargetOverlay("figma");
16552
16555
  }, [closeTargetOverlay, isFigmaOverlayAvailable, targetOverlayState.figma]);
16553
- useEffect12(() => clearRefreshTimers, [clearRefreshTimers]);
16556
+ useEffect13(() => clearRefreshTimers, [clearRefreshTimers]);
16554
16557
  return {
16555
16558
  closeTargetOverlay,
16556
16559
  refreshTargetOverlayState,
@@ -16561,7 +16564,7 @@ var useReviewTargetOverlay = ({
16561
16564
  // src/react-shell/hooks/use.review.target.sync.ts
16562
16565
  import {
16563
16566
  useCallback as useCallback13,
16564
- useEffect as useEffect13
16567
+ useEffect as useEffect14
16565
16568
  } from "react";
16566
16569
  var useReviewTargetSync = ({
16567
16570
  iframeRef,
@@ -16616,10 +16619,10 @@ var useReviewTargetSync = ({
16616
16619
  storeApi
16617
16620
  ]
16618
16621
  );
16619
- useEffect13(() => {
16622
+ useEffect14(() => {
16620
16623
  onActiveRouteChange(getTargetRouteKey(target, reviewPathPrefix));
16621
16624
  }, [onActiveRouteChange, reviewPathPrefix, target]);
16622
- useEffect13(() => {
16625
+ useEffect14(() => {
16623
16626
  const { target: currentTarget, selectedItemId } = storeApi.getState();
16624
16627
  if (selectedItemId) {
16625
16628
  updateShellUrlForItem(currentTarget, size, selectedItemId, source);
@@ -16817,17 +16820,17 @@ var useReviewController = ({
16817
16820
  // src/react-shell/hooks/use.review.ruler.ts
16818
16821
  import {
16819
16822
  useCallback as useCallback16,
16820
- useEffect as useEffect15,
16821
- useState as useState13
16823
+ useEffect as useEffect16,
16824
+ useState as useState14
16822
16825
  } from "react";
16823
16826
 
16824
16827
  // src/react-shell/hooks/use.review.ruler.drag.ts
16825
16828
  import {
16826
16829
  useCallback as useCallback15,
16827
- useEffect as useEffect14,
16830
+ useEffect as useEffect15,
16828
16831
  useMemo as useMemo11,
16829
16832
  useRef as useRef11,
16830
- useState as useState12
16833
+ useState as useState13
16831
16834
  } from "react";
16832
16835
 
16833
16836
  // src/react-shell/ruler/ruler.ts
@@ -16861,10 +16864,10 @@ var useReviewRulerDrag = ({
16861
16864
  const rulerDragRectRef = useRef11(null);
16862
16865
  const isRulerDraggingRef = useRef11(false);
16863
16866
  const sizeRef = useRef11(size);
16864
- const [rulerStart, setRulerStart] = useState12(null);
16865
- const [rulerPoint, setRulerPoint] = useState12(null);
16866
- const [rulerHover, setRulerHover] = useState12(null);
16867
- const [isRulerDragging, setIsRulerDragging] = useState12(false);
16867
+ const [rulerStart, setRulerStart] = useState13(null);
16868
+ const [rulerPoint, setRulerPoint] = useState13(null);
16869
+ const [rulerHover, setRulerHover] = useState13(null);
16870
+ const [isRulerDragging, setIsRulerDragging] = useState13(false);
16868
16871
  const rulerMeasure = useMemo11(
16869
16872
  () => getRulerMeasure(rulerStart, rulerPoint),
16870
16873
  [rulerPoint, rulerStart]
@@ -16896,10 +16899,10 @@ var useReviewRulerDrag = ({
16896
16899
  },
16897
16900
  []
16898
16901
  );
16899
- useEffect14(() => {
16902
+ useEffect15(() => {
16900
16903
  sizeRef.current = size;
16901
16904
  }, [size]);
16902
- useEffect14(() => {
16905
+ useEffect15(() => {
16903
16906
  if (!isRulerVisible || !isRulerAvailable) return void 0;
16904
16907
  const getRulerEventClientPoint = (event) => {
16905
16908
  const frame2 = iframeRef.current;
@@ -17013,7 +17016,7 @@ var useReviewRulerDrag = ({
17013
17016
  isRulerVisible,
17014
17017
  startRulerDrag
17015
17018
  ]);
17016
- useEffect14(() => {
17019
+ useEffect15(() => {
17017
17020
  clearRulerMeasure();
17018
17021
  }, [clearRulerMeasure, size.height, size.width, targetSrc]);
17019
17022
  return {
@@ -17034,7 +17037,7 @@ var useReviewRuler = ({
17034
17037
  onCancelReviewMode,
17035
17038
  onCloseTransientPanels
17036
17039
  }) => {
17037
- const [isRulerVisible, setIsRulerVisible] = useState13(false);
17040
+ const [isRulerVisible, setIsRulerVisible] = useState14(false);
17038
17041
  const isRulerAvailable = ruler?.enabled !== false && typeof size.designWidth === "number" && size.designWidth > 0;
17039
17042
  const rulerUnit = ruler?.unit ?? "px";
17040
17043
  const rulerScaleX = isRulerAvailable && size.designWidth ? size.width / size.designWidth : 1;
@@ -17073,7 +17076,7 @@ var useReviewRuler = ({
17073
17076
  onCancelReviewMode,
17074
17077
  onCloseTransientPanels
17075
17078
  ]);
17076
- useEffect15(() => {
17079
+ useEffect16(() => {
17077
17080
  if (!isRulerVisible || isRulerAvailable) return;
17078
17081
  closeRuler();
17079
17082
  }, [closeRuler, isRulerAvailable, isRulerVisible]);
@@ -17176,7 +17179,7 @@ var useReviewShellActionsValue = ({
17176
17179
 
17177
17180
  // src/react-shell/hooks/use.review.shell.effects.ts
17178
17181
  import {
17179
- useEffect as useEffect16
17182
+ useEffect as useEffect17
17180
17183
  } from "react";
17181
17184
  var REVIEW_SELECTION_ACTION_SELECTOR = [
17182
17185
  "a",
@@ -17208,7 +17211,7 @@ var useReviewShellEffects = ({
17208
17211
  targetFrameLoadVersion,
17209
17212
  targetSrc
17210
17213
  }) => {
17211
- useEffect16(() => {
17214
+ useEffect17(() => {
17212
17215
  const itemId = pendingInitialItemIdRef.current;
17213
17216
  if (!itemId) return;
17214
17217
  const item = items.find(
@@ -17217,7 +17220,7 @@ var useReviewShellEffects = ({
17217
17220
  if (!item) return;
17218
17221
  restoreReviewItem(item);
17219
17222
  }, [items, pendingInitialItemIdRef, restoreReviewItem]);
17220
- useEffect16(() => {
17223
+ useEffect17(() => {
17221
17224
  const frameScroll = frameScrollRef.current;
17222
17225
  if (!frameScroll) return void 0;
17223
17226
  const centerFrameScroll = () => {
@@ -17242,14 +17245,14 @@ var useReviewShellEffects = ({
17242
17245
  syncTargetViewport,
17243
17246
  targetSrc
17244
17247
  ]);
17245
- useEffect16(() => {
17248
+ useEffect17(() => {
17246
17249
  const targetDocument = iframeRef.current?.contentDocument;
17247
17250
  setTargetFigmaOverlayLocked(targetDocument, mode === "element");
17248
17251
  return () => {
17249
17252
  setTargetFigmaOverlayLocked(targetDocument, false);
17250
17253
  };
17251
17254
  }, [iframeRef, mode, targetSrc]);
17252
- useEffect16(() => {
17255
+ useEffect17(() => {
17253
17256
  if (!selectedItemId) return void 0;
17254
17257
  const frameScroll = frameScrollRef.current;
17255
17258
  let frameDocument = null;
@@ -17513,10 +17516,10 @@ import { useMemo as useMemo16 } from "react";
17513
17516
  // src/react-shell/hooks/use.review.presence.ts
17514
17517
  import {
17515
17518
  useCallback as useCallback18,
17516
- useEffect as useEffect17,
17519
+ useEffect as useEffect18,
17517
17520
  useMemo as useMemo15,
17518
17521
  useRef as useRef12,
17519
- useState as useState14
17522
+ useState as useState15
17520
17523
  } from "react";
17521
17524
 
17522
17525
  // src/react-shell/presence/presence.ts
@@ -17733,8 +17736,8 @@ var useReviewPresence = ({
17733
17736
  source
17734
17737
  }) => {
17735
17738
  const presenceSessionRef = useRef12(null);
17736
- const [presenceUsers, setPresenceUsers] = useState14([]);
17737
- const [presenceSessionVersion, setPresenceSessionVersion] = useState14(0);
17739
+ const [presenceUsers, setPresenceUsers] = useState15([]);
17740
+ const [presenceSessionVersion, setPresenceSessionVersion] = useState15(0);
17738
17741
  const presenceSessionId = useMemo15(getReviewPresenceSessionId, []);
17739
17742
  const normalizedReviewUserId = reviewUserId.trim();
17740
17743
  const presenceDisplayName = getReviewPresenceDisplayName(
@@ -17815,7 +17818,7 @@ var useReviewPresence = ({
17815
17818
  );
17816
17819
  const getCurrentPresenceStateRef = useRef12(getCurrentPresenceState);
17817
17820
  getCurrentPresenceStateRef.current = getCurrentPresenceState;
17818
- useEffect17(() => {
17821
+ useEffect18(() => {
17819
17822
  if (!presence || !normalizedReviewUserId) {
17820
17823
  const session = presenceSessionRef.current;
17821
17824
  presenceSessionRef.current = null;
@@ -17865,7 +17868,7 @@ var useReviewPresence = ({
17865
17868
  presenceSessionId,
17866
17869
  projectId
17867
17870
  ]);
17868
- useEffect17(() => {
17871
+ useEffect18(() => {
17869
17872
  const session = presenceSessionRef.current;
17870
17873
  if (!session || !normalizedReviewUserId) return;
17871
17874
  void session.update(getCurrentPresenceState());
@@ -17923,7 +17926,7 @@ var useReviewShellPresenceState = ({
17923
17926
  };
17924
17927
 
17925
17928
  // src/react-shell/hooks/use.review.settings.ts
17926
- import { useCallback as useCallback19, useEffect as useEffect18, useState as useState15 } from "react";
17929
+ import { useCallback as useCallback19, useEffect as useEffect19, useState as useState16 } from "react";
17927
17930
  var useReviewSettings = ({
17928
17931
  defaultReviewUserId = "",
17929
17932
  onCancelReviewMode,
@@ -17931,26 +17934,26 @@ var useReviewSettings = ({
17931
17934
  onCloseSitemap,
17932
17935
  onReloadTargetFrame
17933
17936
  }) => {
17934
- const [figmaTokenDraft, setFigmaTokenDraft] = useState15(getStoredFigmaToken);
17935
- const [reviewUserId, setReviewUserId] = useState15(
17937
+ const [figmaTokenDraft, setFigmaTokenDraft] = useState16(getStoredFigmaToken);
17938
+ const [reviewUserId, setReviewUserId] = useState16(
17936
17939
  () => getStoredReviewUserId(defaultReviewUserId)
17937
17940
  );
17938
- const [reviewUserIdDraft, setReviewUserIdDraft] = useState15(
17941
+ const [reviewUserIdDraft, setReviewUserIdDraft] = useState16(
17939
17942
  () => getStoredReviewUserId(defaultReviewUserId)
17940
17943
  );
17941
- const [reviewTheme, setReviewTheme] = useState15(getStoredReviewTheme);
17942
- const [reviewThemeDraft, setReviewThemeDraft] = useState15(getStoredReviewTheme);
17943
- const [areTooltipsEnabled, setAreTooltipsEnabled] = useState15(
17944
+ const [reviewTheme, setReviewTheme] = useState16(getStoredReviewTheme);
17945
+ const [reviewThemeDraft, setReviewThemeDraft] = useState16(getStoredReviewTheme);
17946
+ const [areTooltipsEnabled, setAreTooltipsEnabled] = useState16(
17944
17947
  getStoredReviewTooltipsEnabled
17945
17948
  );
17946
- const [areTooltipsEnabledDraft, setAreTooltipsEnabledDraft] = useState15(
17949
+ const [areTooltipsEnabledDraft, setAreTooltipsEnabledDraft] = useState16(
17947
17950
  getStoredReviewTooltipsEnabled
17948
17951
  );
17949
- const [systemReviewTheme, setSystemReviewTheme] = useState15(getSystemReviewTheme);
17950
- const [figmaSettingsStatus, setFigmaSettingsStatus] = useState15("");
17951
- const [isFigmaSettingsOpen, setIsFigmaSettingsOpen] = useState15(false);
17952
- const [isFigmaTokenVisible, setIsFigmaTokenVisible] = useState15(false);
17953
- const [isFigmaTokenGuideOpen, setIsFigmaTokenGuideOpen] = useState15(false);
17952
+ const [systemReviewTheme, setSystemReviewTheme] = useState16(getSystemReviewTheme);
17953
+ const [figmaSettingsStatus, setFigmaSettingsStatus] = useState16("");
17954
+ const [isFigmaSettingsOpen, setIsFigmaSettingsOpen] = useState16(false);
17955
+ const [isFigmaTokenVisible, setIsFigmaTokenVisible] = useState16(false);
17956
+ const [isFigmaTokenGuideOpen, setIsFigmaTokenGuideOpen] = useState16(false);
17954
17957
  const effectiveReviewTheme = reviewTheme === "system" ? systemReviewTheme : reviewTheme;
17955
17958
  const closeFigmaSettings = useCallback19(() => {
17956
17959
  setIsFigmaSettingsOpen(false);
@@ -18005,13 +18008,13 @@ var useReviewSettings = ({
18005
18008
  },
18006
18009
  [closeFigmaSettings, onReloadTargetFrame]
18007
18010
  );
18008
- useEffect18(() => {
18011
+ useEffect19(() => {
18009
18012
  if (getStoredReviewUserId()) return;
18010
18013
  const nextDefaultUserId = defaultReviewUserId.trim();
18011
18014
  setReviewUserId(nextDefaultUserId);
18012
18015
  setReviewUserIdDraft(nextDefaultUserId);
18013
18016
  }, [defaultReviewUserId]);
18014
- useEffect18(() => {
18017
+ useEffect19(() => {
18015
18018
  if (typeof window === "undefined" || !window.matchMedia) return void 0;
18016
18019
  const query = window.matchMedia("(prefers-color-scheme: light)");
18017
18020
  const syncSystemTheme = () => {
@@ -18025,7 +18028,7 @@ var useReviewSettings = ({
18025
18028
  query.addListener(syncSystemTheme);
18026
18029
  return () => query.removeListener(syncSystemTheme);
18027
18030
  }, []);
18028
- useEffect18(() => {
18031
+ useEffect19(() => {
18029
18032
  document.body.classList.toggle(
18030
18033
  "df-review-theme-light",
18031
18034
  effectiveReviewTheme === "light"
@@ -18179,7 +18182,7 @@ var useReviewShellLoadTargetFrame = ({
18179
18182
  ]);
18180
18183
 
18181
18184
  // src/react-shell/hooks/use.review.shell.hotkeys.ts
18182
- import { useEffect as useEffect19 } from "react";
18185
+ import { useEffect as useEffect20 } from "react";
18183
18186
  var useReviewShellHotkeys = ({
18184
18187
  isRailHotkeyBlocked,
18185
18188
  isFigmaSettingsOpen,
@@ -18208,7 +18211,7 @@ var useReviewShellHotkeys = ({
18208
18211
  const setIsSitemapOpen = useReviewShellStore(
18209
18212
  (state) => state.setIsSitemapOpen
18210
18213
  );
18211
- useEffect19(() => {
18214
+ useEffect20(() => {
18212
18215
  if (mode === "idle" && !isRulerVisible && !isInitialPromptOpen && !isSitemapOpen && !isFigmaSettingsOpen) {
18213
18216
  return;
18214
18217
  }
@@ -18252,7 +18255,7 @@ var useReviewShellHotkeys = ({
18252
18255
  setIsInitialPromptOpen,
18253
18256
  setIsSitemapOpen
18254
18257
  ]);
18255
- useEffect19(() => {
18258
+ useEffect20(() => {
18256
18259
  const handleHotkey = (event) => {
18257
18260
  if (event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) {
18258
18261
  return;
@@ -18285,7 +18288,7 @@ var useReviewShellHotkeys = ({
18285
18288
  onToggleRuler,
18286
18289
  onToggleTargetOverlay
18287
18290
  ]);
18288
- useEffect19(() => {
18291
+ useEffect20(() => {
18289
18292
  const handleRailHotkey = (event) => {
18290
18293
  if (isRailHotkeyBlocked || isEditableEventTarget(event)) return;
18291
18294
  const actions = [
@@ -18312,7 +18315,7 @@ var useReviewShellHotkeys = ({
18312
18315
  // src/react-shell/hooks/use.review.shell.refresh.ts
18313
18316
  import {
18314
18317
  useCallback as useCallback21,
18315
- useEffect as useEffect20,
18318
+ useEffect as useEffect21,
18316
18319
  useRef as useRef13
18317
18320
  } from "react";
18318
18321
  var useReviewShellRefresh = ({
@@ -18364,13 +18367,13 @@ var useReviewShellRefresh = ({
18364
18367
  }),
18365
18368
  [localAdapterEntry, projectId, remoteAdapterEntry, storeApi]
18366
18369
  );
18367
- useEffect20(() => {
18370
+ useEffect21(() => {
18368
18371
  void refreshItems();
18369
18372
  }, [refreshItems]);
18370
- useEffect20(() => {
18373
+ useEffect21(() => {
18371
18374
  void refreshSitemapItems();
18372
18375
  }, [refreshSitemapItems]);
18373
- useEffect20(() => {
18376
+ useEffect21(() => {
18374
18377
  if (!isSitemapOpen) return;
18375
18378
  void refreshSitemapItems();
18376
18379
  }, [isSitemapOpen, refreshSitemapItems]);
@@ -18471,7 +18474,7 @@ var useReviewShellState = () => {
18471
18474
  // src/react-shell/hooks/use.review.shell.target.figma.ts
18472
18475
  import {
18473
18476
  useCallback as useCallback22,
18474
- useState as useState16
18477
+ useState as useState17
18475
18478
  } from "react";
18476
18479
  var useReviewShellTargetFigma = ({
18477
18480
  iframeRef,
@@ -18479,7 +18482,7 @@ var useReviewShellTargetFigma = ({
18479
18482
  isViewportFigmaOverlayAvailable,
18480
18483
  targetSrc
18481
18484
  }) => {
18482
- const [targetFigmaState, setTargetFigmaState] = useState16(null);
18485
+ const [targetFigmaState, setTargetFigmaState] = useState17(null);
18483
18486
  const targetFigmaConfig = targetFigmaState?.targetSrc === targetSrc ? targetFigmaState.config : null;
18484
18487
  const isFigmaOverlayAvailable = !isFigmaImageManagementEnabled && isViewportFigmaOverlayAvailable && Boolean(targetFigmaConfig);
18485
18488
  const refreshTargetFigmaConfig = useCallback22(() => {
@@ -18497,7 +18500,7 @@ var useReviewShellTargetFigma = ({
18497
18500
  // src/react-shell/hooks/use.review.side.panel.ts
18498
18501
  import {
18499
18502
  useCallback as useCallback23,
18500
- useEffect as useEffect21
18503
+ useEffect as useEffect22
18501
18504
  } from "react";
18502
18505
  var getAvailableSidePanel = (sidePanel, {
18503
18506
  isFigmaImageManagementEnabled
@@ -18519,7 +18522,7 @@ var useReviewSidePanel = ({
18519
18522
  const isQaPanelVisible = isListVisible && sidePanel === "qa";
18520
18523
  const isSourceTreePanelVisible = isListVisible && sidePanel === "source";
18521
18524
  const isFigmaImagesPanelVisible = isFigmaImageManagementEnabled && isListVisible && sidePanel === "figma-images";
18522
- useEffect21(() => {
18525
+ useEffect22(() => {
18523
18526
  const state = storeApi.getState();
18524
18527
  const availableSidePanel = getAvailableSidePanel(state.sidePanel, {
18525
18528
  isFigmaImageManagementEnabled
@@ -18528,10 +18531,10 @@ var useReviewSidePanel = ({
18528
18531
  state.setSidePanel(availableSidePanel);
18529
18532
  }
18530
18533
  }, [isFigmaImageManagementEnabled, storeApi]);
18531
- useEffect21(() => {
18534
+ useEffect22(() => {
18532
18535
  writeStoredReviewSidePanel(sidePanel);
18533
18536
  }, [sidePanel]);
18534
- useEffect21(() => {
18537
+ useEffect22(() => {
18535
18538
  writeStoredReviewSidePanelVisible(isListVisible);
18536
18539
  }, [isListVisible]);
18537
18540
  const openSidePanel = useCallback23(
@@ -18574,7 +18577,7 @@ var useReviewSidePanel = ({
18574
18577
  };
18575
18578
 
18576
18579
  // src/react-shell/hooks/use.review.source.inspector.ts
18577
- import { useCallback as useCallback24, useEffect as useEffect22, useRef as useRef14, useState as useState17 } from "react";
18580
+ import { useCallback as useCallback24, useEffect as useEffect23, useRef as useRef14, useState as useState18 } from "react";
18578
18581
 
18579
18582
  // src/react-shell/review/source.shortcut.style.ts
18580
18583
  function createSourceShortcutStyle(optionAttribute, fontOverlayAttribute) {
@@ -18658,8 +18661,8 @@ function useReviewSourceInspector({
18658
18661
  }) {
18659
18662
  const showToast = useReviewToast();
18660
18663
  const sourceShortcutCleanupRef = useRef14(null);
18661
- const [componentSelectionState, setComponentSelectionState] = useState17(null);
18662
- const [sourceInspectorState, setSourceInspectorState] = useState17(null);
18664
+ const [componentSelectionState, setComponentSelectionState] = useState18(null);
18665
+ const [sourceInspectorState, setSourceInspectorState] = useState18(null);
18663
18666
  const clearSourceInspector = useCallback24(() => {
18664
18667
  setSourceInspectorState(null);
18665
18668
  }, []);
@@ -18736,7 +18739,7 @@ function useReviewSourceInspector({
18736
18739
  }, []);
18737
18740
  const sourceInspectorTargetElement = sourceInspectorState?.targetElement ?? null;
18738
18741
  const componentSelectionTargetElement = componentSelectionState?.targetElement ?? null;
18739
- useEffect22(() => {
18742
+ useEffect23(() => {
18740
18743
  const trackedElement = sourceInspectorTargetElement ?? componentSelectionTargetElement;
18741
18744
  if (!trackedElement) return void 0;
18742
18745
  const targetWindow = trackedElement.ownerDocument.defaultView ?? iframeRef.current?.contentWindow ?? null;
@@ -19015,10 +19018,10 @@ function useReviewSourceInspector({
19015
19018
  sourceCandidateOptions,
19016
19019
  showSourceOutlineForTarget
19017
19020
  ]);
19018
- useEffect22(() => {
19021
+ useEffect23(() => {
19019
19022
  return cleanupSourceOpenShortcut;
19020
19023
  }, [cleanupSourceOpenShortcut]);
19021
- useEffect22(() => {
19024
+ useEffect23(() => {
19022
19025
  const frame = window.requestAnimationFrame(bindSourceOpenShortcut);
19023
19026
  return () => window.cancelAnimationFrame(frame);
19024
19027
  }, [bindSourceOpenShortcut, targetSrc]);
@@ -19628,7 +19631,7 @@ var createReviewShellStore = (init) => createStore()((...args) => ({
19628
19631
  }));
19629
19632
 
19630
19633
  // src/react-shell/review/shell.tsx
19631
- import { jsx as jsx41 } from "react/jsx-runtime";
19634
+ import { jsx as jsx42 } from "react/jsx-runtime";
19632
19635
  var ReviewShell = (props) => {
19633
19636
  const config = useMemo18(
19634
19637
  () => createReviewShellConfig(props),
@@ -19644,27 +19647,27 @@ var ReviewShell = (props) => {
19644
19647
  props.sourceRoot
19645
19648
  ]
19646
19649
  );
19647
- const [store] = useState18(
19650
+ const [store] = useState19(
19648
19651
  () => createReviewShellStore({ target: getInitialTargetSliceState(config) })
19649
19652
  );
19650
- const [refs] = useState18(createReviewShellRefs);
19651
- return /* @__PURE__ */ jsx41(ReviewShellConfigProvider, { value: config, children: /* @__PURE__ */ jsx41(ReviewShellStoreProvider, { value: store, children: /* @__PURE__ */ jsx41(ReviewShellRefsProvider, { value: refs, children: /* @__PURE__ */ jsx41(ReviewShellContent, { ...props }) }) }) });
19653
+ const [refs] = useState19(createReviewShellRefs);
19654
+ return /* @__PURE__ */ jsx42(ReviewShellConfigProvider, { value: config, children: /* @__PURE__ */ jsx42(ReviewShellStoreProvider, { value: store, children: /* @__PURE__ */ jsx42(ReviewShellRefsProvider, { value: refs, children: /* @__PURE__ */ jsx42(ReviewShellContent, { ...props }) }) }) });
19652
19655
  };
19653
19656
  var ReviewShellContent = (props) => {
19654
19657
  const runtime = useReviewShellRuntime(props);
19655
- return /* @__PURE__ */ jsx41(ReviewShellProviders, { ...runtime, children: /* @__PURE__ */ jsx41(
19658
+ return /* @__PURE__ */ jsx42(ReviewShellProviders, { ...runtime, children: /* @__PURE__ */ jsx42(
19656
19659
  ReviewShellFrameContainer,
19657
19660
  {
19658
19661
  slots: {
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, {})
19662
+ topbar: /* @__PURE__ */ jsx42(TopbarContainer, {}),
19663
+ modals: /* @__PURE__ */ jsx42(ReviewShellModalsContainer, {}),
19664
+ toast: /* @__PURE__ */ jsx42(ReviewToastContainer, {}),
19665
+ sideRail: /* @__PURE__ */ jsx42(ReviewSideRailContainer, {}),
19666
+ qaPanel: /* @__PURE__ */ jsx42(QaPanelContainer, {}),
19667
+ figmaImagesPanel: /* @__PURE__ */ jsx42(FigmaImagesPanelContainer, {}),
19668
+ sourceTreePanel: /* @__PURE__ */ jsx42(SectionOutlineContainer, {}),
19669
+ targetFrame: /* @__PURE__ */ jsx42(ReviewTargetFrame, {}),
19670
+ sourceInspector: /* @__PURE__ */ jsx42(SourceInspectorOverlayContainer, {})
19668
19671
  }
19669
19672
  }
19670
19673
  ) });
@@ -19672,12 +19675,12 @@ var ReviewShellContent = (props) => {
19672
19675
 
19673
19676
  // src/react-shell/figma/dev-overlay.tsx
19674
19677
  import React2, {
19675
- useEffect as useEffect23,
19678
+ useEffect as useEffect24,
19676
19679
  useMemo as useMemo19,
19677
- useState as useState19
19680
+ useState as useState20
19678
19681
  } from "react";
19679
19682
  import { createRoot } from "react-dom/client";
19680
- import { jsx as jsx42, jsxs as jsxs29 } from "react/jsx-runtime";
19683
+ import { jsx as jsx43, jsxs as jsxs30 } from "react/jsx-runtime";
19681
19684
  var FIGMA_DEV_OVERLAY_ROOT_ID = "df-review-figma-dev-overlay-root";
19682
19685
  var FIGMA_DEV_OVERLAY_MOUNT_ID = "df-review-figma-dev-overlay-mount";
19683
19686
  var mountFigmaDevOverlay = (options) => {
@@ -19698,7 +19701,7 @@ var mountFigmaDevOverlay = (options) => {
19698
19701
  document.body.appendChild(host);
19699
19702
  const root = createRoot(mountNode);
19700
19703
  root.render(
19701
- /* @__PURE__ */ jsx42(React2.StrictMode, { children: /* @__PURE__ */ jsx42(FigmaDevOverlayWidget, { ...options }) })
19704
+ /* @__PURE__ */ jsx43(React2.StrictMode, { children: /* @__PURE__ */ jsx43(FigmaDevOverlayWidget, { ...options }) })
19702
19705
  );
19703
19706
  return {
19704
19707
  destroy() {
@@ -19748,9 +19751,9 @@ var FigmaDevOverlayWidget = ({
19748
19751
  store: matchedViewport ? figmaImageStore : null,
19749
19752
  viewport: activeViewport
19750
19753
  });
19751
- const [isPanelOpen, setIsPanelOpen] = useState19(false);
19752
- const [isWidgetVisible, setIsWidgetVisible] = useState19(false);
19753
- const [offsetYDraftByImageId, setOffsetYDraftByImageId] = useState19({});
19754
+ const [isPanelOpen, setIsPanelOpen] = useState20(false);
19755
+ const [isWidgetVisible, setIsWidgetVisible] = useState20(false);
19756
+ const [offsetYDraftByImageId, setOffsetYDraftByImageId] = useState20({});
19754
19757
  const selectedImage = selectedImageId ? images.find((image) => image.id === selectedImageId) ?? null : null;
19755
19758
  const selectedImageIndex = selectedImage ? images.indexOf(selectedImage) : -1;
19756
19759
  const selectedImageLabel = selectedImage ? getFigmaImageLabel(selectedImage, selectedImageIndex) : "Figma layer";
@@ -19764,7 +19767,7 @@ var FigmaDevOverlayWidget = ({
19764
19767
  }),
19765
19768
  [imageOverlayStates, images]
19766
19769
  );
19767
- useEffect23(() => {
19770
+ useEffect24(() => {
19768
19771
  if (!isWidgetVisible || !matchedViewport) {
19769
19772
  removeTargetFigmaImageOverlays(document);
19770
19773
  return;
@@ -19781,15 +19784,15 @@ var FigmaDevOverlayWidget = ({
19781
19784
  matchedViewport,
19782
19785
  setImageOverlayOffsetY
19783
19786
  ]);
19784
- useEffect23(
19787
+ useEffect24(
19785
19788
  () => () => {
19786
19789
  removeTargetFigmaImageOverlays(document);
19787
19790
  },
19788
19791
  []
19789
19792
  );
19790
- useEffect23(() => {
19793
+ useEffect24(() => {
19791
19794
  const handleKeyDown = (event) => {
19792
- if (!isHotkey(event, "Shift+F") || isEditableFigmaDevOverlayEventTarget(event)) {
19795
+ if (!isHotkey(event, "Shift+F") || isEditableEventTarget(event)) {
19793
19796
  return;
19794
19797
  }
19795
19798
  event.preventDefault();
@@ -19811,21 +19814,21 @@ var FigmaDevOverlayWidget = ({
19811
19814
  setImageOverlayOpacity(selectedImage.id, opacityPercent / 100);
19812
19815
  }
19813
19816
  };
19814
- return /* @__PURE__ */ jsxs29(
19817
+ return /* @__PURE__ */ jsxs30(
19815
19818
  "aside",
19816
19819
  {
19817
19820
  "aria-label": "Figma overlay",
19818
19821
  className: `df-review-figma-dev-widget${isPanelOpen ? " is-open" : ""}${isAnyImageOverlayVisible ? " is-active" : ""}`,
19819
19822
  children: [
19820
- isPanelOpen && /* @__PURE__ */ jsxs29("div", { className: "df-review-figma-dev-panel", children: [
19821
- /* @__PURE__ */ jsxs29("div", { className: "df-review-figma-dev-panel-header", children: [
19822
- /* @__PURE__ */ jsx42("strong", { children: "Figma" }),
19823
- /* @__PURE__ */ jsx42("span", { children: matchedViewportMatch ? `${matchedViewportMatch.label} \xB7 ${matchedViewportMatch.rangeLabel}` : `${viewport.width}px` })
19823
+ isPanelOpen && /* @__PURE__ */ jsxs30("div", { className: "df-review-figma-dev-panel", children: [
19824
+ /* @__PURE__ */ jsxs30("div", { className: "df-review-figma-dev-panel-header", children: [
19825
+ /* @__PURE__ */ jsx43("strong", { children: "Figma" }),
19826
+ /* @__PURE__ */ jsx43("span", { children: matchedViewportMatch ? `${matchedViewportMatch.label} \xB7 ${matchedViewportMatch.rangeLabel}` : `${viewport.width}px` })
19824
19827
  ] }),
19825
- selectedImage && /* @__PURE__ */ jsxs29("div", { className: "df-review-figma-dev-selected-controls", children: [
19826
- /* @__PURE__ */ jsxs29("label", { className: "df-review-figma-dev-opacity-control", children: [
19827
- /* @__PURE__ */ jsx42("span", { children: "Opacity" }),
19828
- /* @__PURE__ */ jsx42(
19828
+ selectedImage && /* @__PURE__ */ jsxs30("div", { className: "df-review-figma-dev-selected-controls", children: [
19829
+ /* @__PURE__ */ jsxs30("label", { className: "df-review-figma-dev-opacity-control", children: [
19830
+ /* @__PURE__ */ jsx43("span", { children: "Opacity" }),
19831
+ /* @__PURE__ */ jsx43(
19829
19832
  "input",
19830
19833
  {
19831
19834
  "aria-label": `${selectedImageLabel} overlay opacity`,
@@ -19838,11 +19841,11 @@ var FigmaDevOverlayWidget = ({
19838
19841
  onInput: (event) => updateSelectedImageOpacity(event.currentTarget.value)
19839
19842
  }
19840
19843
  ),
19841
- /* @__PURE__ */ jsx42("strong", { children: selectedOpacityPercent })
19844
+ /* @__PURE__ */ jsx43("strong", { children: selectedOpacityPercent })
19842
19845
  ] }),
19843
- /* @__PURE__ */ jsxs29("label", { className: "df-review-figma-dev-y-control", children: [
19844
- /* @__PURE__ */ jsx42(MoveVertical, { "aria-hidden": "true" }),
19845
- /* @__PURE__ */ jsx42(
19846
+ /* @__PURE__ */ jsxs30("label", { className: "df-review-figma-dev-y-control", children: [
19847
+ /* @__PURE__ */ jsx43(MoveVertical, { "aria-hidden": "true" }),
19848
+ /* @__PURE__ */ jsx43(
19846
19849
  "input",
19847
19850
  {
19848
19851
  "aria-label": `${selectedImageLabel} overlay Y offset`,
@@ -19872,14 +19875,14 @@ var FigmaDevOverlayWidget = ({
19872
19875
  )
19873
19876
  ] })
19874
19877
  ] }),
19875
- error && /* @__PURE__ */ jsx42("p", { className: "df-review-figma-dev-status", children: error }),
19876
- !matchedViewport ? /* @__PURE__ */ jsxs29("p", { className: "df-review-figma-dev-empty", children: [
19878
+ error && /* @__PURE__ */ jsx43("p", { className: "df-review-figma-dev-status", children: error }),
19879
+ !matchedViewport ? /* @__PURE__ */ jsxs30("p", { className: "df-review-figma-dev-empty", children: [
19877
19880
  "No Figma layers for this viewport.",
19878
19881
  viewportBoundaries ? ` Mobile ${viewportBoundaries.mobileRangeLabel} / Full width ${viewportBoundaries.fullWidthRangeLabel}` : ""
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) => {
19882
+ ] }) : isLoading ? /* @__PURE__ */ jsx43("p", { className: "df-review-figma-dev-status", children: "Loading..." }) : images.length === 0 ? /* @__PURE__ */ jsx43("p", { className: "df-review-figma-dev-empty", children: "No Figma layers for this viewport." }) : /* @__PURE__ */ jsx43("div", { className: "df-review-figma-dev-list", children: images.map((image, index) => {
19880
19883
  const imageLabel = getFigmaImageLabel(image, index);
19881
19884
  const overlayState = imageOverlayStates[image.id] ?? DEFAULT_FIGMA_IMAGE_LAYER_STATE;
19882
- return /* @__PURE__ */ jsxs29(
19885
+ return /* @__PURE__ */ jsxs30(
19883
19886
  "article",
19884
19887
  {
19885
19888
  className: `df-review-figma-dev-row${image.id === selectedImageId ? " is-active" : ""}`,
@@ -19892,7 +19895,7 @@ var FigmaDevOverlayWidget = ({
19892
19895
  setSelectedImageId(image.id);
19893
19896
  },
19894
19897
  children: [
19895
- /* @__PURE__ */ jsx42(
19898
+ /* @__PURE__ */ jsx43(
19896
19899
  FigmaImageLayerStateButtons,
19897
19900
  {
19898
19901
  imageLabel,
@@ -19904,9 +19907,9 @@ var FigmaDevOverlayWidget = ({
19904
19907
  onToggleVisible: () => toggleImageOverlayVisible(image.id)
19905
19908
  }
19906
19909
  ),
19907
- /* @__PURE__ */ jsxs29("span", { className: "df-review-figma-dev-row-main", children: [
19908
- /* @__PURE__ */ jsx42("strong", { children: imageLabel }),
19909
- /* @__PURE__ */ jsx42("small", { children: formatFigmaImageDate(image.updatedAt) })
19910
+ /* @__PURE__ */ jsxs30("span", { className: "df-review-figma-dev-row-main", children: [
19911
+ /* @__PURE__ */ jsx43("strong", { children: imageLabel }),
19912
+ /* @__PURE__ */ jsx43("small", { children: formatFigmaImageDate(image.updatedAt) })
19910
19913
  ] })
19911
19914
  ]
19912
19915
  },
@@ -19914,7 +19917,7 @@ var FigmaDevOverlayWidget = ({
19914
19917
  );
19915
19918
  }) })
19916
19919
  ] }),
19917
- /* @__PURE__ */ jsx42("div", { className: "df-review-figma-dev-bar", children: /* @__PURE__ */ jsxs29(
19920
+ /* @__PURE__ */ jsx43("div", { className: "df-review-figma-dev-bar", children: /* @__PURE__ */ jsxs30(
19918
19921
  "button",
19919
19922
  {
19920
19923
  "aria-expanded": isPanelOpen,
@@ -19924,8 +19927,8 @@ var FigmaDevOverlayWidget = ({
19924
19927
  type: "button",
19925
19928
  onClick: () => setIsPanelOpen((isOpen) => !isOpen),
19926
19929
  children: [
19927
- /* @__PURE__ */ jsx42(FigmaMarkIcon, {}),
19928
- /* @__PURE__ */ jsx42("span", { className: "df-review-figma-dev-button-count", children: images.length })
19930
+ /* @__PURE__ */ jsx43(FigmaMarkIcon, {}),
19931
+ /* @__PURE__ */ jsx43("span", { className: "df-review-figma-dev-button-count", children: images.length })
19929
19932
  ]
19930
19933
  }
19931
19934
  ) })
@@ -19934,10 +19937,10 @@ var FigmaDevOverlayWidget = ({
19934
19937
  );
19935
19938
  };
19936
19939
  function useCurrentPageUrl(pageUrl, reviewPathPrefix) {
19937
- const [currentPageUrl, setCurrentPageUrl] = useState19(
19940
+ const [currentPageUrl, setCurrentPageUrl] = useState20(
19938
19941
  () => getFigmaDevOverlayPageUrl(pageUrl, reviewPathPrefix)
19939
19942
  );
19940
- useEffect23(() => {
19943
+ useEffect24(() => {
19941
19944
  const updatePageUrl = () => {
19942
19945
  setCurrentPageUrl(getFigmaDevOverlayPageUrl(pageUrl, reviewPathPrefix));
19943
19946
  };
@@ -19950,16 +19953,9 @@ function useCurrentPageUrl(pageUrl, reviewPathPrefix) {
19950
19953
  }, [pageUrl, reviewPathPrefix]);
19951
19954
  return currentPageUrl;
19952
19955
  }
19953
- function isEditableFigmaDevOverlayEventTarget(event) {
19954
- const path = event.composedPath?.() ?? [];
19955
- const element = path[0] ?? event.target;
19956
- if (!element || typeof element.tagName !== "string") return false;
19957
- const tagName = element.tagName;
19958
- return tagName === "INPUT" || tagName === "TEXTAREA" || tagName === "SELECT" || element.isContentEditable === true;
19959
- }
19960
19956
  function useCurrentViewport() {
19961
- const [viewport, setViewport] = useState19(getCurrentViewportSize);
19962
- useEffect23(() => {
19957
+ const [viewport, setViewport] = useState20(getCurrentViewportSize);
19958
+ useEffect24(() => {
19963
19959
  const updateViewport = () => setViewport(getCurrentViewportSize());
19964
19960
  window.addEventListener("resize", updateViewport);
19965
19961
  window.addEventListener("orientationchange", updateViewport);
@@ -20516,7 +20512,7 @@ var createSupabasePresenceAdapter = ({
20516
20512
  });
20517
20513
 
20518
20514
  // src/react-shell.tsx
20519
- import { jsx as jsx43 } from "react/jsx-runtime";
20515
+ import { jsx as jsx44 } from "react/jsx-runtime";
20520
20516
  var mountReviewShell = (options) => {
20521
20517
  if (typeof document === "undefined" || !document.head) return;
20522
20518
  const { rootId = "root", ...shellProps } = options;
@@ -20527,7 +20523,7 @@ var mountReviewShell = (options) => {
20527
20523
  root.style.height = "100%";
20528
20524
  root.style.margin = "0";
20529
20525
  createRoot2(root).render(
20530
- /* @__PURE__ */ jsx43(React3.StrictMode, { children: /* @__PURE__ */ jsx43(ReviewShell, { ...shellProps }) })
20526
+ /* @__PURE__ */ jsx44(React3.StrictMode, { children: /* @__PURE__ */ jsx44(ReviewShell, { ...shellProps }) })
20531
20527
  );
20532
20528
  };
20533
20529
  export {