@linhey/react-debug-inspector 1.2.1 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -102,6 +102,7 @@ function initInspector() {
102
102
  let latestHoverEvent = null;
103
103
  let pendingHoverFrame = false;
104
104
  let anchorUpdatePending = false;
105
+ let selectionLocked = false;
105
106
  const edgeOffset = 24;
106
107
  const successColor = "#10b981";
107
108
  const defaultOverlayBg = "rgba(14, 165, 233, 0.15)";
@@ -271,6 +272,11 @@ function initInspector() {
271
272
  event.stopImmediatePropagation?.();
272
273
  }
273
274
  };
275
+ const isInspectorChromeTarget = (target) => {
276
+ if (!target) return false;
277
+ if (target === toggleBtn || target === overlay || target === tooltip || target === actionMenu) return true;
278
+ return !!target.closest('[data-inspector-ignore="true"]');
279
+ };
274
280
  const extractTextContent = (target) => {
275
281
  const ariaLabel = normalizeText(target.getAttribute("aria-label") || "");
276
282
  if (ariaLabel) return truncateText(ariaLabel);
@@ -410,6 +416,30 @@ function initInspector() {
410
416
  if (!actionMenu) return;
411
417
  actionMenu.style.display = "none";
412
418
  };
419
+ const finalizeSelection = (debugId) => {
420
+ selectionLocked = true;
421
+ copyText(debugId).then(() => {
422
+ showCopyFeedback("Copied!", "success");
423
+ win.setTimeout(() => {
424
+ selectionLocked = false;
425
+ stopInspecting();
426
+ }, 600);
427
+ }).catch(() => {
428
+ selectionLocked = false;
429
+ });
430
+ };
431
+ const selectDebugTarget = (target) => {
432
+ if (selectionLocked) return;
433
+ const debugEl = target?.closest("[data-debug]");
434
+ if (!debugEl) {
435
+ selectionLocked = false;
436
+ stopInspecting();
437
+ return;
438
+ }
439
+ const debugId = debugEl.getAttribute("data-debug");
440
+ if (!debugId) return;
441
+ finalizeSelection(debugId);
442
+ };
413
443
  const copyText = async (value) => {
414
444
  await navigator.clipboard.writeText(value);
415
445
  };
@@ -464,7 +494,7 @@ function initInspector() {
464
494
  if (!isInspecting || !overlay || !tooltip) return;
465
495
  const target = event.target;
466
496
  if (!target) return;
467
- if (target === toggleBtn || target === overlay || target === tooltip || target.closest('[data-inspector-ignore="true"]')) {
497
+ if (isInspectorChromeTarget(target)) {
468
498
  return;
469
499
  }
470
500
  const debugEl = target.closest("[data-debug]");
@@ -498,6 +528,7 @@ function initInspector() {
498
528
  };
499
529
  const stopInspecting = () => {
500
530
  isInspecting = false;
531
+ selectionLocked = false;
501
532
  latestContext = null;
502
533
  lastHoveredDebugEl = null;
503
534
  toggleBtn.style.transform = "scale(1)";
@@ -617,25 +648,32 @@ function initInspector() {
617
648
  inspectByPointer(latestHoverEvent);
618
649
  });
619
650
  };
651
+ const handlePointerSuppression = (event) => {
652
+ if (!isInspecting) return;
653
+ const target = event.target;
654
+ if (!target || isInspectorChromeTarget(target)) return;
655
+ if (selectionLocked) {
656
+ suppressEvent(event, { preventDefault: true, immediate: true });
657
+ return;
658
+ }
659
+ const isTouchSelectionEvent = event.type === "touchend" || event.type === "pointerup" && "pointerType" in event && event.pointerType !== "mouse";
660
+ suppressEvent(event, { preventDefault: true, immediate: true });
661
+ if (isTouchSelectionEvent) {
662
+ selectDebugTarget(target);
663
+ }
664
+ };
620
665
  const handleWindowClick = (event) => {
621
666
  if (!isInspecting) return;
622
667
  const target = event.target;
623
668
  if (!target || target === toggleBtn) return;
624
- if (target.closest('[data-inspector-ignore="true"]')) {
669
+ if (isInspectorChromeTarget(target)) {
625
670
  return;
626
671
  }
627
672
  suppressEvent(event, { preventDefault: true, immediate: true });
628
- const debugEl = target.closest("[data-debug]");
629
- if (!debugEl) {
630
- stopInspecting();
673
+ if (selectionLocked) {
631
674
  return;
632
675
  }
633
- const debugId = debugEl.getAttribute("data-debug");
634
- if (!debugId) return;
635
- copyText(debugId).then(() => {
636
- showCopyFeedback("Copied!", "success");
637
- win.setTimeout(stopInspecting, 600);
638
- });
676
+ selectDebugTarget(target);
639
677
  };
640
678
  const handleKeyDown = (event) => {
641
679
  if (event.key === "Escape" && isInspecting) stopInspecting();
@@ -653,6 +691,12 @@ function initInspector() {
653
691
  win.addEventListener("resize", scheduleAnchorUpdate);
654
692
  win.addEventListener("scroll", scheduleAnchorUpdate, true);
655
693
  doc.addEventListener("mousemove", handleMouseMove);
694
+ win.addEventListener("pointerdown", handlePointerSuppression, { capture: true });
695
+ win.addEventListener("pointerup", handlePointerSuppression, { capture: true });
696
+ win.addEventListener("mousedown", handlePointerSuppression, { capture: true });
697
+ win.addEventListener("mouseup", handlePointerSuppression, { capture: true });
698
+ win.addEventListener("touchstart", handlePointerSuppression, { capture: true });
699
+ win.addEventListener("touchend", handlePointerSuppression, { capture: true });
656
700
  win.addEventListener("click", handleWindowClick, { capture: true });
657
701
  win.addEventListener("keydown", handleKeyDown);
658
702
  updateAnchorForDialogs();
@@ -662,6 +706,12 @@ function initInspector() {
662
706
  win.removeEventListener("resize", scheduleAnchorUpdate);
663
707
  win.removeEventListener("scroll", scheduleAnchorUpdate, true);
664
708
  doc.removeEventListener("mousemove", handleMouseMove);
709
+ win.removeEventListener("pointerdown", handlePointerSuppression, { capture: true });
710
+ win.removeEventListener("pointerup", handlePointerSuppression, { capture: true });
711
+ win.removeEventListener("mousedown", handlePointerSuppression, { capture: true });
712
+ win.removeEventListener("mouseup", handlePointerSuppression, { capture: true });
713
+ win.removeEventListener("touchstart", handlePointerSuppression, { capture: true });
714
+ win.removeEventListener("touchend", handlePointerSuppression, { capture: true });
665
715
  win.removeEventListener("click", handleWindowClick, { capture: true });
666
716
  win.removeEventListener("keydown", handleKeyDown);
667
717
  for (const eventName of shieldedEvents) {
package/dist/index.mjs CHANGED
@@ -75,6 +75,7 @@ function initInspector() {
75
75
  let latestHoverEvent = null;
76
76
  let pendingHoverFrame = false;
77
77
  let anchorUpdatePending = false;
78
+ let selectionLocked = false;
78
79
  const edgeOffset = 24;
79
80
  const successColor = "#10b981";
80
81
  const defaultOverlayBg = "rgba(14, 165, 233, 0.15)";
@@ -244,6 +245,11 @@ function initInspector() {
244
245
  event.stopImmediatePropagation?.();
245
246
  }
246
247
  };
248
+ const isInspectorChromeTarget = (target) => {
249
+ if (!target) return false;
250
+ if (target === toggleBtn || target === overlay || target === tooltip || target === actionMenu) return true;
251
+ return !!target.closest('[data-inspector-ignore="true"]');
252
+ };
247
253
  const extractTextContent = (target) => {
248
254
  const ariaLabel = normalizeText(target.getAttribute("aria-label") || "");
249
255
  if (ariaLabel) return truncateText(ariaLabel);
@@ -383,6 +389,30 @@ function initInspector() {
383
389
  if (!actionMenu) return;
384
390
  actionMenu.style.display = "none";
385
391
  };
392
+ const finalizeSelection = (debugId) => {
393
+ selectionLocked = true;
394
+ copyText(debugId).then(() => {
395
+ showCopyFeedback("Copied!", "success");
396
+ win.setTimeout(() => {
397
+ selectionLocked = false;
398
+ stopInspecting();
399
+ }, 600);
400
+ }).catch(() => {
401
+ selectionLocked = false;
402
+ });
403
+ };
404
+ const selectDebugTarget = (target) => {
405
+ if (selectionLocked) return;
406
+ const debugEl = target?.closest("[data-debug]");
407
+ if (!debugEl) {
408
+ selectionLocked = false;
409
+ stopInspecting();
410
+ return;
411
+ }
412
+ const debugId = debugEl.getAttribute("data-debug");
413
+ if (!debugId) return;
414
+ finalizeSelection(debugId);
415
+ };
386
416
  const copyText = async (value) => {
387
417
  await navigator.clipboard.writeText(value);
388
418
  };
@@ -437,7 +467,7 @@ function initInspector() {
437
467
  if (!isInspecting || !overlay || !tooltip) return;
438
468
  const target = event.target;
439
469
  if (!target) return;
440
- if (target === toggleBtn || target === overlay || target === tooltip || target.closest('[data-inspector-ignore="true"]')) {
470
+ if (isInspectorChromeTarget(target)) {
441
471
  return;
442
472
  }
443
473
  const debugEl = target.closest("[data-debug]");
@@ -471,6 +501,7 @@ function initInspector() {
471
501
  };
472
502
  const stopInspecting = () => {
473
503
  isInspecting = false;
504
+ selectionLocked = false;
474
505
  latestContext = null;
475
506
  lastHoveredDebugEl = null;
476
507
  toggleBtn.style.transform = "scale(1)";
@@ -590,25 +621,32 @@ function initInspector() {
590
621
  inspectByPointer(latestHoverEvent);
591
622
  });
592
623
  };
624
+ const handlePointerSuppression = (event) => {
625
+ if (!isInspecting) return;
626
+ const target = event.target;
627
+ if (!target || isInspectorChromeTarget(target)) return;
628
+ if (selectionLocked) {
629
+ suppressEvent(event, { preventDefault: true, immediate: true });
630
+ return;
631
+ }
632
+ const isTouchSelectionEvent = event.type === "touchend" || event.type === "pointerup" && "pointerType" in event && event.pointerType !== "mouse";
633
+ suppressEvent(event, { preventDefault: true, immediate: true });
634
+ if (isTouchSelectionEvent) {
635
+ selectDebugTarget(target);
636
+ }
637
+ };
593
638
  const handleWindowClick = (event) => {
594
639
  if (!isInspecting) return;
595
640
  const target = event.target;
596
641
  if (!target || target === toggleBtn) return;
597
- if (target.closest('[data-inspector-ignore="true"]')) {
642
+ if (isInspectorChromeTarget(target)) {
598
643
  return;
599
644
  }
600
645
  suppressEvent(event, { preventDefault: true, immediate: true });
601
- const debugEl = target.closest("[data-debug]");
602
- if (!debugEl) {
603
- stopInspecting();
646
+ if (selectionLocked) {
604
647
  return;
605
648
  }
606
- const debugId = debugEl.getAttribute("data-debug");
607
- if (!debugId) return;
608
- copyText(debugId).then(() => {
609
- showCopyFeedback("Copied!", "success");
610
- win.setTimeout(stopInspecting, 600);
611
- });
649
+ selectDebugTarget(target);
612
650
  };
613
651
  const handleKeyDown = (event) => {
614
652
  if (event.key === "Escape" && isInspecting) stopInspecting();
@@ -626,6 +664,12 @@ function initInspector() {
626
664
  win.addEventListener("resize", scheduleAnchorUpdate);
627
665
  win.addEventListener("scroll", scheduleAnchorUpdate, true);
628
666
  doc.addEventListener("mousemove", handleMouseMove);
667
+ win.addEventListener("pointerdown", handlePointerSuppression, { capture: true });
668
+ win.addEventListener("pointerup", handlePointerSuppression, { capture: true });
669
+ win.addEventListener("mousedown", handlePointerSuppression, { capture: true });
670
+ win.addEventListener("mouseup", handlePointerSuppression, { capture: true });
671
+ win.addEventListener("touchstart", handlePointerSuppression, { capture: true });
672
+ win.addEventListener("touchend", handlePointerSuppression, { capture: true });
629
673
  win.addEventListener("click", handleWindowClick, { capture: true });
630
674
  win.addEventListener("keydown", handleKeyDown);
631
675
  updateAnchorForDialogs();
@@ -635,6 +679,12 @@ function initInspector() {
635
679
  win.removeEventListener("resize", scheduleAnchorUpdate);
636
680
  win.removeEventListener("scroll", scheduleAnchorUpdate, true);
637
681
  doc.removeEventListener("mousemove", handleMouseMove);
682
+ win.removeEventListener("pointerdown", handlePointerSuppression, { capture: true });
683
+ win.removeEventListener("pointerup", handlePointerSuppression, { capture: true });
684
+ win.removeEventListener("mousedown", handlePointerSuppression, { capture: true });
685
+ win.removeEventListener("mouseup", handlePointerSuppression, { capture: true });
686
+ win.removeEventListener("touchstart", handlePointerSuppression, { capture: true });
687
+ win.removeEventListener("touchend", handlePointerSuppression, { capture: true });
638
688
  win.removeEventListener("click", handleWindowClick, { capture: true });
639
689
  win.removeEventListener("keydown", handleKeyDown);
640
690
  for (const eventName of shieldedEvents) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linhey/react-debug-inspector",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "A developer tool to inspect React components in browser and jump to source code.",
5
5
  "author": "linhey",
6
6
  "license": "MIT",