@designfever/web-review-kit 0.8.2 → 0.8.3

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,
@@ -16268,12 +16261,8 @@ function createMarkerSvg(x, y) {
16268
16261
  function formatCaptureTimestamp(timestamp) {
16269
16262
  return timestamp.replace(/[^0-9A-Za-z]+/g, "-").replace(/^-|-$/g, "");
16270
16263
  }
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.";
16264
+ function getCaptureErrorMessage(error) {
16265
+ return getErrorMessage(error, "Capture was saved as SVG fallback.");
16277
16266
  }
16278
16267
 
16279
16268
  // src/react-shell/hooks/review.kit.target.ts
@@ -16456,13 +16445,13 @@ var useReviewKitLifecycle = ({
16456
16445
  },
16457
16446
  [controllerRef, onModeChange]
16458
16447
  );
16459
- useEffect11(() => destroyReviewKit, [destroyReviewKit]);
16460
- useEffect11(() => {
16448
+ useEffect12(() => destroyReviewKit, [destroyReviewKit]);
16449
+ useEffect12(() => {
16461
16450
  const frameDocument = iframeRef.current?.contentDocument;
16462
16451
  if (!frameDocument || frameDocument.readyState !== "complete") return;
16463
16452
  initReviewKit();
16464
16453
  }, [iframeRef, initReviewKit]);
16465
- useEffect11(() => {
16454
+ useEffect12(() => {
16466
16455
  hiddenOverlayItemIdListRef.current = hiddenOverlayItemIdList;
16467
16456
  controllerRef.current?.setHiddenItemIds(hiddenOverlayItemIdList);
16468
16457
  }, [controllerRef, hiddenOverlayItemIdList]);
@@ -16475,7 +16464,7 @@ var useReviewKitLifecycle = ({
16475
16464
  };
16476
16465
 
16477
16466
  // src/react-shell/hooks/use.review.target.overlay.ts
16478
- import { useCallback as useCallback12, useEffect as useEffect12, useRef as useRef10 } from "react";
16467
+ import { useCallback as useCallback12, useEffect as useEffect13, useRef as useRef10 } from "react";
16479
16468
  var TARGET_OVERLAY_REFRESH_DELAYS = [80, 240, 600];
16480
16469
  var useReviewTargetOverlay = ({
16481
16470
  iframeRef,
@@ -16546,11 +16535,11 @@ var useReviewTargetOverlay = ({
16546
16535
  },
16547
16536
  [dispatchTargetOverlayHotkey, updateTargetOverlayState]
16548
16537
  );
16549
- useEffect12(() => {
16538
+ useEffect13(() => {
16550
16539
  if (isFigmaOverlayAvailable || !targetOverlayState.figma) return;
16551
16540
  closeTargetOverlay("figma");
16552
16541
  }, [closeTargetOverlay, isFigmaOverlayAvailable, targetOverlayState.figma]);
16553
- useEffect12(() => clearRefreshTimers, [clearRefreshTimers]);
16542
+ useEffect13(() => clearRefreshTimers, [clearRefreshTimers]);
16554
16543
  return {
16555
16544
  closeTargetOverlay,
16556
16545
  refreshTargetOverlayState,
@@ -16561,7 +16550,7 @@ var useReviewTargetOverlay = ({
16561
16550
  // src/react-shell/hooks/use.review.target.sync.ts
16562
16551
  import {
16563
16552
  useCallback as useCallback13,
16564
- useEffect as useEffect13
16553
+ useEffect as useEffect14
16565
16554
  } from "react";
16566
16555
  var useReviewTargetSync = ({
16567
16556
  iframeRef,
@@ -16616,10 +16605,10 @@ var useReviewTargetSync = ({
16616
16605
  storeApi
16617
16606
  ]
16618
16607
  );
16619
- useEffect13(() => {
16608
+ useEffect14(() => {
16620
16609
  onActiveRouteChange(getTargetRouteKey(target, reviewPathPrefix));
16621
16610
  }, [onActiveRouteChange, reviewPathPrefix, target]);
16622
- useEffect13(() => {
16611
+ useEffect14(() => {
16623
16612
  const { target: currentTarget, selectedItemId } = storeApi.getState();
16624
16613
  if (selectedItemId) {
16625
16614
  updateShellUrlForItem(currentTarget, size, selectedItemId, source);
@@ -16817,17 +16806,17 @@ var useReviewController = ({
16817
16806
  // src/react-shell/hooks/use.review.ruler.ts
16818
16807
  import {
16819
16808
  useCallback as useCallback16,
16820
- useEffect as useEffect15,
16821
- useState as useState13
16809
+ useEffect as useEffect16,
16810
+ useState as useState14
16822
16811
  } from "react";
16823
16812
 
16824
16813
  // src/react-shell/hooks/use.review.ruler.drag.ts
16825
16814
  import {
16826
16815
  useCallback as useCallback15,
16827
- useEffect as useEffect14,
16816
+ useEffect as useEffect15,
16828
16817
  useMemo as useMemo11,
16829
16818
  useRef as useRef11,
16830
- useState as useState12
16819
+ useState as useState13
16831
16820
  } from "react";
16832
16821
 
16833
16822
  // src/react-shell/ruler/ruler.ts
@@ -16861,10 +16850,10 @@ var useReviewRulerDrag = ({
16861
16850
  const rulerDragRectRef = useRef11(null);
16862
16851
  const isRulerDraggingRef = useRef11(false);
16863
16852
  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);
16853
+ const [rulerStart, setRulerStart] = useState13(null);
16854
+ const [rulerPoint, setRulerPoint] = useState13(null);
16855
+ const [rulerHover, setRulerHover] = useState13(null);
16856
+ const [isRulerDragging, setIsRulerDragging] = useState13(false);
16868
16857
  const rulerMeasure = useMemo11(
16869
16858
  () => getRulerMeasure(rulerStart, rulerPoint),
16870
16859
  [rulerPoint, rulerStart]
@@ -16896,10 +16885,10 @@ var useReviewRulerDrag = ({
16896
16885
  },
16897
16886
  []
16898
16887
  );
16899
- useEffect14(() => {
16888
+ useEffect15(() => {
16900
16889
  sizeRef.current = size;
16901
16890
  }, [size]);
16902
- useEffect14(() => {
16891
+ useEffect15(() => {
16903
16892
  if (!isRulerVisible || !isRulerAvailable) return void 0;
16904
16893
  const getRulerEventClientPoint = (event) => {
16905
16894
  const frame2 = iframeRef.current;
@@ -17013,7 +17002,7 @@ var useReviewRulerDrag = ({
17013
17002
  isRulerVisible,
17014
17003
  startRulerDrag
17015
17004
  ]);
17016
- useEffect14(() => {
17005
+ useEffect15(() => {
17017
17006
  clearRulerMeasure();
17018
17007
  }, [clearRulerMeasure, size.height, size.width, targetSrc]);
17019
17008
  return {
@@ -17034,7 +17023,7 @@ var useReviewRuler = ({
17034
17023
  onCancelReviewMode,
17035
17024
  onCloseTransientPanels
17036
17025
  }) => {
17037
- const [isRulerVisible, setIsRulerVisible] = useState13(false);
17026
+ const [isRulerVisible, setIsRulerVisible] = useState14(false);
17038
17027
  const isRulerAvailable = ruler?.enabled !== false && typeof size.designWidth === "number" && size.designWidth > 0;
17039
17028
  const rulerUnit = ruler?.unit ?? "px";
17040
17029
  const rulerScaleX = isRulerAvailable && size.designWidth ? size.width / size.designWidth : 1;
@@ -17073,7 +17062,7 @@ var useReviewRuler = ({
17073
17062
  onCancelReviewMode,
17074
17063
  onCloseTransientPanels
17075
17064
  ]);
17076
- useEffect15(() => {
17065
+ useEffect16(() => {
17077
17066
  if (!isRulerVisible || isRulerAvailable) return;
17078
17067
  closeRuler();
17079
17068
  }, [closeRuler, isRulerAvailable, isRulerVisible]);
@@ -17176,7 +17165,7 @@ var useReviewShellActionsValue = ({
17176
17165
 
17177
17166
  // src/react-shell/hooks/use.review.shell.effects.ts
17178
17167
  import {
17179
- useEffect as useEffect16
17168
+ useEffect as useEffect17
17180
17169
  } from "react";
17181
17170
  var REVIEW_SELECTION_ACTION_SELECTOR = [
17182
17171
  "a",
@@ -17208,7 +17197,7 @@ var useReviewShellEffects = ({
17208
17197
  targetFrameLoadVersion,
17209
17198
  targetSrc
17210
17199
  }) => {
17211
- useEffect16(() => {
17200
+ useEffect17(() => {
17212
17201
  const itemId = pendingInitialItemIdRef.current;
17213
17202
  if (!itemId) return;
17214
17203
  const item = items.find(
@@ -17217,7 +17206,7 @@ var useReviewShellEffects = ({
17217
17206
  if (!item) return;
17218
17207
  restoreReviewItem(item);
17219
17208
  }, [items, pendingInitialItemIdRef, restoreReviewItem]);
17220
- useEffect16(() => {
17209
+ useEffect17(() => {
17221
17210
  const frameScroll = frameScrollRef.current;
17222
17211
  if (!frameScroll) return void 0;
17223
17212
  const centerFrameScroll = () => {
@@ -17242,14 +17231,14 @@ var useReviewShellEffects = ({
17242
17231
  syncTargetViewport,
17243
17232
  targetSrc
17244
17233
  ]);
17245
- useEffect16(() => {
17234
+ useEffect17(() => {
17246
17235
  const targetDocument = iframeRef.current?.contentDocument;
17247
17236
  setTargetFigmaOverlayLocked(targetDocument, mode === "element");
17248
17237
  return () => {
17249
17238
  setTargetFigmaOverlayLocked(targetDocument, false);
17250
17239
  };
17251
17240
  }, [iframeRef, mode, targetSrc]);
17252
- useEffect16(() => {
17241
+ useEffect17(() => {
17253
17242
  if (!selectedItemId) return void 0;
17254
17243
  const frameScroll = frameScrollRef.current;
17255
17244
  let frameDocument = null;
@@ -17513,10 +17502,10 @@ import { useMemo as useMemo16 } from "react";
17513
17502
  // src/react-shell/hooks/use.review.presence.ts
17514
17503
  import {
17515
17504
  useCallback as useCallback18,
17516
- useEffect as useEffect17,
17505
+ useEffect as useEffect18,
17517
17506
  useMemo as useMemo15,
17518
17507
  useRef as useRef12,
17519
- useState as useState14
17508
+ useState as useState15
17520
17509
  } from "react";
17521
17510
 
17522
17511
  // src/react-shell/presence/presence.ts
@@ -17733,8 +17722,8 @@ var useReviewPresence = ({
17733
17722
  source
17734
17723
  }) => {
17735
17724
  const presenceSessionRef = useRef12(null);
17736
- const [presenceUsers, setPresenceUsers] = useState14([]);
17737
- const [presenceSessionVersion, setPresenceSessionVersion] = useState14(0);
17725
+ const [presenceUsers, setPresenceUsers] = useState15([]);
17726
+ const [presenceSessionVersion, setPresenceSessionVersion] = useState15(0);
17738
17727
  const presenceSessionId = useMemo15(getReviewPresenceSessionId, []);
17739
17728
  const normalizedReviewUserId = reviewUserId.trim();
17740
17729
  const presenceDisplayName = getReviewPresenceDisplayName(
@@ -17815,7 +17804,7 @@ var useReviewPresence = ({
17815
17804
  );
17816
17805
  const getCurrentPresenceStateRef = useRef12(getCurrentPresenceState);
17817
17806
  getCurrentPresenceStateRef.current = getCurrentPresenceState;
17818
- useEffect17(() => {
17807
+ useEffect18(() => {
17819
17808
  if (!presence || !normalizedReviewUserId) {
17820
17809
  const session = presenceSessionRef.current;
17821
17810
  presenceSessionRef.current = null;
@@ -17865,7 +17854,7 @@ var useReviewPresence = ({
17865
17854
  presenceSessionId,
17866
17855
  projectId
17867
17856
  ]);
17868
- useEffect17(() => {
17857
+ useEffect18(() => {
17869
17858
  const session = presenceSessionRef.current;
17870
17859
  if (!session || !normalizedReviewUserId) return;
17871
17860
  void session.update(getCurrentPresenceState());
@@ -17923,7 +17912,7 @@ var useReviewShellPresenceState = ({
17923
17912
  };
17924
17913
 
17925
17914
  // src/react-shell/hooks/use.review.settings.ts
17926
- import { useCallback as useCallback19, useEffect as useEffect18, useState as useState15 } from "react";
17915
+ import { useCallback as useCallback19, useEffect as useEffect19, useState as useState16 } from "react";
17927
17916
  var useReviewSettings = ({
17928
17917
  defaultReviewUserId = "",
17929
17918
  onCancelReviewMode,
@@ -17931,26 +17920,26 @@ var useReviewSettings = ({
17931
17920
  onCloseSitemap,
17932
17921
  onReloadTargetFrame
17933
17922
  }) => {
17934
- const [figmaTokenDraft, setFigmaTokenDraft] = useState15(getStoredFigmaToken);
17935
- const [reviewUserId, setReviewUserId] = useState15(
17923
+ const [figmaTokenDraft, setFigmaTokenDraft] = useState16(getStoredFigmaToken);
17924
+ const [reviewUserId, setReviewUserId] = useState16(
17936
17925
  () => getStoredReviewUserId(defaultReviewUserId)
17937
17926
  );
17938
- const [reviewUserIdDraft, setReviewUserIdDraft] = useState15(
17927
+ const [reviewUserIdDraft, setReviewUserIdDraft] = useState16(
17939
17928
  () => getStoredReviewUserId(defaultReviewUserId)
17940
17929
  );
17941
- const [reviewTheme, setReviewTheme] = useState15(getStoredReviewTheme);
17942
- const [reviewThemeDraft, setReviewThemeDraft] = useState15(getStoredReviewTheme);
17943
- const [areTooltipsEnabled, setAreTooltipsEnabled] = useState15(
17930
+ const [reviewTheme, setReviewTheme] = useState16(getStoredReviewTheme);
17931
+ const [reviewThemeDraft, setReviewThemeDraft] = useState16(getStoredReviewTheme);
17932
+ const [areTooltipsEnabled, setAreTooltipsEnabled] = useState16(
17944
17933
  getStoredReviewTooltipsEnabled
17945
17934
  );
17946
- const [areTooltipsEnabledDraft, setAreTooltipsEnabledDraft] = useState15(
17935
+ const [areTooltipsEnabledDraft, setAreTooltipsEnabledDraft] = useState16(
17947
17936
  getStoredReviewTooltipsEnabled
17948
17937
  );
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);
17938
+ const [systemReviewTheme, setSystemReviewTheme] = useState16(getSystemReviewTheme);
17939
+ const [figmaSettingsStatus, setFigmaSettingsStatus] = useState16("");
17940
+ const [isFigmaSettingsOpen, setIsFigmaSettingsOpen] = useState16(false);
17941
+ const [isFigmaTokenVisible, setIsFigmaTokenVisible] = useState16(false);
17942
+ const [isFigmaTokenGuideOpen, setIsFigmaTokenGuideOpen] = useState16(false);
17954
17943
  const effectiveReviewTheme = reviewTheme === "system" ? systemReviewTheme : reviewTheme;
17955
17944
  const closeFigmaSettings = useCallback19(() => {
17956
17945
  setIsFigmaSettingsOpen(false);
@@ -18005,13 +17994,13 @@ var useReviewSettings = ({
18005
17994
  },
18006
17995
  [closeFigmaSettings, onReloadTargetFrame]
18007
17996
  );
18008
- useEffect18(() => {
17997
+ useEffect19(() => {
18009
17998
  if (getStoredReviewUserId()) return;
18010
17999
  const nextDefaultUserId = defaultReviewUserId.trim();
18011
18000
  setReviewUserId(nextDefaultUserId);
18012
18001
  setReviewUserIdDraft(nextDefaultUserId);
18013
18002
  }, [defaultReviewUserId]);
18014
- useEffect18(() => {
18003
+ useEffect19(() => {
18015
18004
  if (typeof window === "undefined" || !window.matchMedia) return void 0;
18016
18005
  const query = window.matchMedia("(prefers-color-scheme: light)");
18017
18006
  const syncSystemTheme = () => {
@@ -18025,7 +18014,7 @@ var useReviewSettings = ({
18025
18014
  query.addListener(syncSystemTheme);
18026
18015
  return () => query.removeListener(syncSystemTheme);
18027
18016
  }, []);
18028
- useEffect18(() => {
18017
+ useEffect19(() => {
18029
18018
  document.body.classList.toggle(
18030
18019
  "df-review-theme-light",
18031
18020
  effectiveReviewTheme === "light"
@@ -18179,7 +18168,7 @@ var useReviewShellLoadTargetFrame = ({
18179
18168
  ]);
18180
18169
 
18181
18170
  // src/react-shell/hooks/use.review.shell.hotkeys.ts
18182
- import { useEffect as useEffect19 } from "react";
18171
+ import { useEffect as useEffect20 } from "react";
18183
18172
  var useReviewShellHotkeys = ({
18184
18173
  isRailHotkeyBlocked,
18185
18174
  isFigmaSettingsOpen,
@@ -18208,7 +18197,7 @@ var useReviewShellHotkeys = ({
18208
18197
  const setIsSitemapOpen = useReviewShellStore(
18209
18198
  (state) => state.setIsSitemapOpen
18210
18199
  );
18211
- useEffect19(() => {
18200
+ useEffect20(() => {
18212
18201
  if (mode === "idle" && !isRulerVisible && !isInitialPromptOpen && !isSitemapOpen && !isFigmaSettingsOpen) {
18213
18202
  return;
18214
18203
  }
@@ -18252,7 +18241,7 @@ var useReviewShellHotkeys = ({
18252
18241
  setIsInitialPromptOpen,
18253
18242
  setIsSitemapOpen
18254
18243
  ]);
18255
- useEffect19(() => {
18244
+ useEffect20(() => {
18256
18245
  const handleHotkey = (event) => {
18257
18246
  if (event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) {
18258
18247
  return;
@@ -18285,7 +18274,7 @@ var useReviewShellHotkeys = ({
18285
18274
  onToggleRuler,
18286
18275
  onToggleTargetOverlay
18287
18276
  ]);
18288
- useEffect19(() => {
18277
+ useEffect20(() => {
18289
18278
  const handleRailHotkey = (event) => {
18290
18279
  if (isRailHotkeyBlocked || isEditableEventTarget(event)) return;
18291
18280
  const actions = [
@@ -18312,7 +18301,7 @@ var useReviewShellHotkeys = ({
18312
18301
  // src/react-shell/hooks/use.review.shell.refresh.ts
18313
18302
  import {
18314
18303
  useCallback as useCallback21,
18315
- useEffect as useEffect20,
18304
+ useEffect as useEffect21,
18316
18305
  useRef as useRef13
18317
18306
  } from "react";
18318
18307
  var useReviewShellRefresh = ({
@@ -18364,13 +18353,13 @@ var useReviewShellRefresh = ({
18364
18353
  }),
18365
18354
  [localAdapterEntry, projectId, remoteAdapterEntry, storeApi]
18366
18355
  );
18367
- useEffect20(() => {
18356
+ useEffect21(() => {
18368
18357
  void refreshItems();
18369
18358
  }, [refreshItems]);
18370
- useEffect20(() => {
18359
+ useEffect21(() => {
18371
18360
  void refreshSitemapItems();
18372
18361
  }, [refreshSitemapItems]);
18373
- useEffect20(() => {
18362
+ useEffect21(() => {
18374
18363
  if (!isSitemapOpen) return;
18375
18364
  void refreshSitemapItems();
18376
18365
  }, [isSitemapOpen, refreshSitemapItems]);
@@ -18471,7 +18460,7 @@ var useReviewShellState = () => {
18471
18460
  // src/react-shell/hooks/use.review.shell.target.figma.ts
18472
18461
  import {
18473
18462
  useCallback as useCallback22,
18474
- useState as useState16
18463
+ useState as useState17
18475
18464
  } from "react";
18476
18465
  var useReviewShellTargetFigma = ({
18477
18466
  iframeRef,
@@ -18479,7 +18468,7 @@ var useReviewShellTargetFigma = ({
18479
18468
  isViewportFigmaOverlayAvailable,
18480
18469
  targetSrc
18481
18470
  }) => {
18482
- const [targetFigmaState, setTargetFigmaState] = useState16(null);
18471
+ const [targetFigmaState, setTargetFigmaState] = useState17(null);
18483
18472
  const targetFigmaConfig = targetFigmaState?.targetSrc === targetSrc ? targetFigmaState.config : null;
18484
18473
  const isFigmaOverlayAvailable = !isFigmaImageManagementEnabled && isViewportFigmaOverlayAvailable && Boolean(targetFigmaConfig);
18485
18474
  const refreshTargetFigmaConfig = useCallback22(() => {
@@ -18497,7 +18486,7 @@ var useReviewShellTargetFigma = ({
18497
18486
  // src/react-shell/hooks/use.review.side.panel.ts
18498
18487
  import {
18499
18488
  useCallback as useCallback23,
18500
- useEffect as useEffect21
18489
+ useEffect as useEffect22
18501
18490
  } from "react";
18502
18491
  var getAvailableSidePanel = (sidePanel, {
18503
18492
  isFigmaImageManagementEnabled
@@ -18519,7 +18508,7 @@ var useReviewSidePanel = ({
18519
18508
  const isQaPanelVisible = isListVisible && sidePanel === "qa";
18520
18509
  const isSourceTreePanelVisible = isListVisible && sidePanel === "source";
18521
18510
  const isFigmaImagesPanelVisible = isFigmaImageManagementEnabled && isListVisible && sidePanel === "figma-images";
18522
- useEffect21(() => {
18511
+ useEffect22(() => {
18523
18512
  const state = storeApi.getState();
18524
18513
  const availableSidePanel = getAvailableSidePanel(state.sidePanel, {
18525
18514
  isFigmaImageManagementEnabled
@@ -18528,10 +18517,10 @@ var useReviewSidePanel = ({
18528
18517
  state.setSidePanel(availableSidePanel);
18529
18518
  }
18530
18519
  }, [isFigmaImageManagementEnabled, storeApi]);
18531
- useEffect21(() => {
18520
+ useEffect22(() => {
18532
18521
  writeStoredReviewSidePanel(sidePanel);
18533
18522
  }, [sidePanel]);
18534
- useEffect21(() => {
18523
+ useEffect22(() => {
18535
18524
  writeStoredReviewSidePanelVisible(isListVisible);
18536
18525
  }, [isListVisible]);
18537
18526
  const openSidePanel = useCallback23(
@@ -18574,7 +18563,7 @@ var useReviewSidePanel = ({
18574
18563
  };
18575
18564
 
18576
18565
  // 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";
18566
+ import { useCallback as useCallback24, useEffect as useEffect23, useRef as useRef14, useState as useState18 } from "react";
18578
18567
 
18579
18568
  // src/react-shell/review/source.shortcut.style.ts
18580
18569
  function createSourceShortcutStyle(optionAttribute, fontOverlayAttribute) {
@@ -18658,8 +18647,8 @@ function useReviewSourceInspector({
18658
18647
  }) {
18659
18648
  const showToast = useReviewToast();
18660
18649
  const sourceShortcutCleanupRef = useRef14(null);
18661
- const [componentSelectionState, setComponentSelectionState] = useState17(null);
18662
- const [sourceInspectorState, setSourceInspectorState] = useState17(null);
18650
+ const [componentSelectionState, setComponentSelectionState] = useState18(null);
18651
+ const [sourceInspectorState, setSourceInspectorState] = useState18(null);
18663
18652
  const clearSourceInspector = useCallback24(() => {
18664
18653
  setSourceInspectorState(null);
18665
18654
  }, []);
@@ -18736,7 +18725,7 @@ function useReviewSourceInspector({
18736
18725
  }, []);
18737
18726
  const sourceInspectorTargetElement = sourceInspectorState?.targetElement ?? null;
18738
18727
  const componentSelectionTargetElement = componentSelectionState?.targetElement ?? null;
18739
- useEffect22(() => {
18728
+ useEffect23(() => {
18740
18729
  const trackedElement = sourceInspectorTargetElement ?? componentSelectionTargetElement;
18741
18730
  if (!trackedElement) return void 0;
18742
18731
  const targetWindow = trackedElement.ownerDocument.defaultView ?? iframeRef.current?.contentWindow ?? null;
@@ -19015,10 +19004,10 @@ function useReviewSourceInspector({
19015
19004
  sourceCandidateOptions,
19016
19005
  showSourceOutlineForTarget
19017
19006
  ]);
19018
- useEffect22(() => {
19007
+ useEffect23(() => {
19019
19008
  return cleanupSourceOpenShortcut;
19020
19009
  }, [cleanupSourceOpenShortcut]);
19021
- useEffect22(() => {
19010
+ useEffect23(() => {
19022
19011
  const frame = window.requestAnimationFrame(bindSourceOpenShortcut);
19023
19012
  return () => window.cancelAnimationFrame(frame);
19024
19013
  }, [bindSourceOpenShortcut, targetSrc]);
@@ -19628,7 +19617,7 @@ var createReviewShellStore = (init) => createStore()((...args) => ({
19628
19617
  }));
19629
19618
 
19630
19619
  // src/react-shell/review/shell.tsx
19631
- import { jsx as jsx41 } from "react/jsx-runtime";
19620
+ import { jsx as jsx42 } from "react/jsx-runtime";
19632
19621
  var ReviewShell = (props) => {
19633
19622
  const config = useMemo18(
19634
19623
  () => createReviewShellConfig(props),
@@ -19644,27 +19633,27 @@ var ReviewShell = (props) => {
19644
19633
  props.sourceRoot
19645
19634
  ]
19646
19635
  );
19647
- const [store] = useState18(
19636
+ const [store] = useState19(
19648
19637
  () => createReviewShellStore({ target: getInitialTargetSliceState(config) })
19649
19638
  );
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 }) }) }) });
19639
+ const [refs] = useState19(createReviewShellRefs);
19640
+ return /* @__PURE__ */ jsx42(ReviewShellConfigProvider, { value: config, children: /* @__PURE__ */ jsx42(ReviewShellStoreProvider, { value: store, children: /* @__PURE__ */ jsx42(ReviewShellRefsProvider, { value: refs, children: /* @__PURE__ */ jsx42(ReviewShellContent, { ...props }) }) }) });
19652
19641
  };
19653
19642
  var ReviewShellContent = (props) => {
19654
19643
  const runtime = useReviewShellRuntime(props);
19655
- return /* @__PURE__ */ jsx41(ReviewShellProviders, { ...runtime, children: /* @__PURE__ */ jsx41(
19644
+ return /* @__PURE__ */ jsx42(ReviewShellProviders, { ...runtime, children: /* @__PURE__ */ jsx42(
19656
19645
  ReviewShellFrameContainer,
19657
19646
  {
19658
19647
  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, {})
19648
+ topbar: /* @__PURE__ */ jsx42(TopbarContainer, {}),
19649
+ modals: /* @__PURE__ */ jsx42(ReviewShellModalsContainer, {}),
19650
+ toast: /* @__PURE__ */ jsx42(ReviewToastContainer, {}),
19651
+ sideRail: /* @__PURE__ */ jsx42(ReviewSideRailContainer, {}),
19652
+ qaPanel: /* @__PURE__ */ jsx42(QaPanelContainer, {}),
19653
+ figmaImagesPanel: /* @__PURE__ */ jsx42(FigmaImagesPanelContainer, {}),
19654
+ sourceTreePanel: /* @__PURE__ */ jsx42(SectionOutlineContainer, {}),
19655
+ targetFrame: /* @__PURE__ */ jsx42(ReviewTargetFrame, {}),
19656
+ sourceInspector: /* @__PURE__ */ jsx42(SourceInspectorOverlayContainer, {})
19668
19657
  }
19669
19658
  }
19670
19659
  ) });
@@ -19672,12 +19661,12 @@ var ReviewShellContent = (props) => {
19672
19661
 
19673
19662
  // src/react-shell/figma/dev-overlay.tsx
19674
19663
  import React2, {
19675
- useEffect as useEffect23,
19664
+ useEffect as useEffect24,
19676
19665
  useMemo as useMemo19,
19677
- useState as useState19
19666
+ useState as useState20
19678
19667
  } from "react";
19679
19668
  import { createRoot } from "react-dom/client";
19680
- import { jsx as jsx42, jsxs as jsxs29 } from "react/jsx-runtime";
19669
+ import { jsx as jsx43, jsxs as jsxs30 } from "react/jsx-runtime";
19681
19670
  var FIGMA_DEV_OVERLAY_ROOT_ID = "df-review-figma-dev-overlay-root";
19682
19671
  var FIGMA_DEV_OVERLAY_MOUNT_ID = "df-review-figma-dev-overlay-mount";
19683
19672
  var mountFigmaDevOverlay = (options) => {
@@ -19698,7 +19687,7 @@ var mountFigmaDevOverlay = (options) => {
19698
19687
  document.body.appendChild(host);
19699
19688
  const root = createRoot(mountNode);
19700
19689
  root.render(
19701
- /* @__PURE__ */ jsx42(React2.StrictMode, { children: /* @__PURE__ */ jsx42(FigmaDevOverlayWidget, { ...options }) })
19690
+ /* @__PURE__ */ jsx43(React2.StrictMode, { children: /* @__PURE__ */ jsx43(FigmaDevOverlayWidget, { ...options }) })
19702
19691
  );
19703
19692
  return {
19704
19693
  destroy() {
@@ -19748,9 +19737,9 @@ var FigmaDevOverlayWidget = ({
19748
19737
  store: matchedViewport ? figmaImageStore : null,
19749
19738
  viewport: activeViewport
19750
19739
  });
19751
- const [isPanelOpen, setIsPanelOpen] = useState19(false);
19752
- const [isWidgetVisible, setIsWidgetVisible] = useState19(false);
19753
- const [offsetYDraftByImageId, setOffsetYDraftByImageId] = useState19({});
19740
+ const [isPanelOpen, setIsPanelOpen] = useState20(false);
19741
+ const [isWidgetVisible, setIsWidgetVisible] = useState20(false);
19742
+ const [offsetYDraftByImageId, setOffsetYDraftByImageId] = useState20({});
19754
19743
  const selectedImage = selectedImageId ? images.find((image) => image.id === selectedImageId) ?? null : null;
19755
19744
  const selectedImageIndex = selectedImage ? images.indexOf(selectedImage) : -1;
19756
19745
  const selectedImageLabel = selectedImage ? getFigmaImageLabel(selectedImage, selectedImageIndex) : "Figma layer";
@@ -19764,7 +19753,7 @@ var FigmaDevOverlayWidget = ({
19764
19753
  }),
19765
19754
  [imageOverlayStates, images]
19766
19755
  );
19767
- useEffect23(() => {
19756
+ useEffect24(() => {
19768
19757
  if (!isWidgetVisible || !matchedViewport) {
19769
19758
  removeTargetFigmaImageOverlays(document);
19770
19759
  return;
@@ -19781,15 +19770,15 @@ var FigmaDevOverlayWidget = ({
19781
19770
  matchedViewport,
19782
19771
  setImageOverlayOffsetY
19783
19772
  ]);
19784
- useEffect23(
19773
+ useEffect24(
19785
19774
  () => () => {
19786
19775
  removeTargetFigmaImageOverlays(document);
19787
19776
  },
19788
19777
  []
19789
19778
  );
19790
- useEffect23(() => {
19779
+ useEffect24(() => {
19791
19780
  const handleKeyDown = (event) => {
19792
- if (!isHotkey(event, "Shift+F") || isEditableFigmaDevOverlayEventTarget(event)) {
19781
+ if (!isHotkey(event, "Shift+F") || isEditableEventTarget(event)) {
19793
19782
  return;
19794
19783
  }
19795
19784
  event.preventDefault();
@@ -19811,21 +19800,21 @@ var FigmaDevOverlayWidget = ({
19811
19800
  setImageOverlayOpacity(selectedImage.id, opacityPercent / 100);
19812
19801
  }
19813
19802
  };
19814
- return /* @__PURE__ */ jsxs29(
19803
+ return /* @__PURE__ */ jsxs30(
19815
19804
  "aside",
19816
19805
  {
19817
19806
  "aria-label": "Figma overlay",
19818
19807
  className: `df-review-figma-dev-widget${isPanelOpen ? " is-open" : ""}${isAnyImageOverlayVisible ? " is-active" : ""}`,
19819
19808
  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` })
19809
+ isPanelOpen && /* @__PURE__ */ jsxs30("div", { className: "df-review-figma-dev-panel", children: [
19810
+ /* @__PURE__ */ jsxs30("div", { className: "df-review-figma-dev-panel-header", children: [
19811
+ /* @__PURE__ */ jsx43("strong", { children: "Figma" }),
19812
+ /* @__PURE__ */ jsx43("span", { children: matchedViewportMatch ? `${matchedViewportMatch.label} \xB7 ${matchedViewportMatch.rangeLabel}` : `${viewport.width}px` })
19824
19813
  ] }),
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(
19814
+ selectedImage && /* @__PURE__ */ jsxs30("div", { className: "df-review-figma-dev-selected-controls", children: [
19815
+ /* @__PURE__ */ jsxs30("label", { className: "df-review-figma-dev-opacity-control", children: [
19816
+ /* @__PURE__ */ jsx43("span", { children: "Opacity" }),
19817
+ /* @__PURE__ */ jsx43(
19829
19818
  "input",
19830
19819
  {
19831
19820
  "aria-label": `${selectedImageLabel} overlay opacity`,
@@ -19838,11 +19827,11 @@ var FigmaDevOverlayWidget = ({
19838
19827
  onInput: (event) => updateSelectedImageOpacity(event.currentTarget.value)
19839
19828
  }
19840
19829
  ),
19841
- /* @__PURE__ */ jsx42("strong", { children: selectedOpacityPercent })
19830
+ /* @__PURE__ */ jsx43("strong", { children: selectedOpacityPercent })
19842
19831
  ] }),
19843
- /* @__PURE__ */ jsxs29("label", { className: "df-review-figma-dev-y-control", children: [
19844
- /* @__PURE__ */ jsx42(MoveVertical, { "aria-hidden": "true" }),
19845
- /* @__PURE__ */ jsx42(
19832
+ /* @__PURE__ */ jsxs30("label", { className: "df-review-figma-dev-y-control", children: [
19833
+ /* @__PURE__ */ jsx43(MoveVertical, { "aria-hidden": "true" }),
19834
+ /* @__PURE__ */ jsx43(
19846
19835
  "input",
19847
19836
  {
19848
19837
  "aria-label": `${selectedImageLabel} overlay Y offset`,
@@ -19872,14 +19861,14 @@ var FigmaDevOverlayWidget = ({
19872
19861
  )
19873
19862
  ] })
19874
19863
  ] }),
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: [
19864
+ error && /* @__PURE__ */ jsx43("p", { className: "df-review-figma-dev-status", children: error }),
19865
+ !matchedViewport ? /* @__PURE__ */ jsxs30("p", { className: "df-review-figma-dev-empty", children: [
19877
19866
  "No Figma layers for this viewport.",
19878
19867
  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) => {
19868
+ ] }) : 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
19869
  const imageLabel = getFigmaImageLabel(image, index);
19881
19870
  const overlayState = imageOverlayStates[image.id] ?? DEFAULT_FIGMA_IMAGE_LAYER_STATE;
19882
- return /* @__PURE__ */ jsxs29(
19871
+ return /* @__PURE__ */ jsxs30(
19883
19872
  "article",
19884
19873
  {
19885
19874
  className: `df-review-figma-dev-row${image.id === selectedImageId ? " is-active" : ""}`,
@@ -19892,7 +19881,7 @@ var FigmaDevOverlayWidget = ({
19892
19881
  setSelectedImageId(image.id);
19893
19882
  },
19894
19883
  children: [
19895
- /* @__PURE__ */ jsx42(
19884
+ /* @__PURE__ */ jsx43(
19896
19885
  FigmaImageLayerStateButtons,
19897
19886
  {
19898
19887
  imageLabel,
@@ -19904,9 +19893,9 @@ var FigmaDevOverlayWidget = ({
19904
19893
  onToggleVisible: () => toggleImageOverlayVisible(image.id)
19905
19894
  }
19906
19895
  ),
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) })
19896
+ /* @__PURE__ */ jsxs30("span", { className: "df-review-figma-dev-row-main", children: [
19897
+ /* @__PURE__ */ jsx43("strong", { children: imageLabel }),
19898
+ /* @__PURE__ */ jsx43("small", { children: formatFigmaImageDate(image.updatedAt) })
19910
19899
  ] })
19911
19900
  ]
19912
19901
  },
@@ -19914,7 +19903,7 @@ var FigmaDevOverlayWidget = ({
19914
19903
  );
19915
19904
  }) })
19916
19905
  ] }),
19917
- /* @__PURE__ */ jsx42("div", { className: "df-review-figma-dev-bar", children: /* @__PURE__ */ jsxs29(
19906
+ /* @__PURE__ */ jsx43("div", { className: "df-review-figma-dev-bar", children: /* @__PURE__ */ jsxs30(
19918
19907
  "button",
19919
19908
  {
19920
19909
  "aria-expanded": isPanelOpen,
@@ -19924,8 +19913,8 @@ var FigmaDevOverlayWidget = ({
19924
19913
  type: "button",
19925
19914
  onClick: () => setIsPanelOpen((isOpen) => !isOpen),
19926
19915
  children: [
19927
- /* @__PURE__ */ jsx42(FigmaMarkIcon, {}),
19928
- /* @__PURE__ */ jsx42("span", { className: "df-review-figma-dev-button-count", children: images.length })
19916
+ /* @__PURE__ */ jsx43(FigmaMarkIcon, {}),
19917
+ /* @__PURE__ */ jsx43("span", { className: "df-review-figma-dev-button-count", children: images.length })
19929
19918
  ]
19930
19919
  }
19931
19920
  ) })
@@ -19934,10 +19923,10 @@ var FigmaDevOverlayWidget = ({
19934
19923
  );
19935
19924
  };
19936
19925
  function useCurrentPageUrl(pageUrl, reviewPathPrefix) {
19937
- const [currentPageUrl, setCurrentPageUrl] = useState19(
19926
+ const [currentPageUrl, setCurrentPageUrl] = useState20(
19938
19927
  () => getFigmaDevOverlayPageUrl(pageUrl, reviewPathPrefix)
19939
19928
  );
19940
- useEffect23(() => {
19929
+ useEffect24(() => {
19941
19930
  const updatePageUrl = () => {
19942
19931
  setCurrentPageUrl(getFigmaDevOverlayPageUrl(pageUrl, reviewPathPrefix));
19943
19932
  };
@@ -19950,16 +19939,9 @@ function useCurrentPageUrl(pageUrl, reviewPathPrefix) {
19950
19939
  }, [pageUrl, reviewPathPrefix]);
19951
19940
  return currentPageUrl;
19952
19941
  }
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
19942
  function useCurrentViewport() {
19961
- const [viewport, setViewport] = useState19(getCurrentViewportSize);
19962
- useEffect23(() => {
19943
+ const [viewport, setViewport] = useState20(getCurrentViewportSize);
19944
+ useEffect24(() => {
19963
19945
  const updateViewport = () => setViewport(getCurrentViewportSize());
19964
19946
  window.addEventListener("resize", updateViewport);
19965
19947
  window.addEventListener("orientationchange", updateViewport);
@@ -20516,7 +20498,7 @@ var createSupabasePresenceAdapter = ({
20516
20498
  });
20517
20499
 
20518
20500
  // src/react-shell.tsx
20519
- import { jsx as jsx43 } from "react/jsx-runtime";
20501
+ import { jsx as jsx44 } from "react/jsx-runtime";
20520
20502
  var mountReviewShell = (options) => {
20521
20503
  if (typeof document === "undefined" || !document.head) return;
20522
20504
  const { rootId = "root", ...shellProps } = options;
@@ -20527,7 +20509,7 @@ var mountReviewShell = (options) => {
20527
20509
  root.style.height = "100%";
20528
20510
  root.style.margin = "0";
20529
20511
  createRoot2(root).render(
20530
- /* @__PURE__ */ jsx43(React3.StrictMode, { children: /* @__PURE__ */ jsx43(ReviewShell, { ...shellProps }) })
20512
+ /* @__PURE__ */ jsx44(React3.StrictMode, { children: /* @__PURE__ */ jsx44(ReviewShell, { ...shellProps }) })
20531
20513
  );
20532
20514
  };
20533
20515
  export {