afterbefore 0.2.5 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  // src/overlay/index.tsx
4
- import { useState as useState6, useCallback as useCallback6, useRef as useRef5, useEffect as useEffect5 } from "react";
4
+ import { useState as useState7, useCallback as useCallback7, useRef as useRef5, useEffect as useEffect6 } from "react";
5
5
 
6
6
  // src/overlay/state.ts
7
7
  import { useState, useCallback } from "react";
@@ -368,9 +368,308 @@ function Icon({ phase, onClick, loading, onPositionChange }) {
368
368
  );
369
369
  }
370
370
 
371
+ // src/overlay/ui/toolbar.tsx
372
+ import { useState as useState3, useEffect as useEffect2 } from "react";
373
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
374
+ var MODES = [
375
+ { mode: "area", label: "Capture Selected Area" },
376
+ { mode: "viewport", label: "Capture Viewport" },
377
+ { mode: "fullpage", label: "Capture Full Page" },
378
+ { mode: "component", label: "Capture Component" }
379
+ ];
380
+ function Toolbar({ onCapture, onCancel }) {
381
+ const [selectedMode, setSelectedMode] = useState3("area");
382
+ const [hoveredMode, setHoveredMode] = useState3(null);
383
+ useEffect2(() => {
384
+ const onKey = (e) => {
385
+ if (e.key === "Escape") onCancel();
386
+ else if (e.key === "Enter") onCapture(selectedMode);
387
+ };
388
+ document.addEventListener("keydown", onKey);
389
+ return () => document.removeEventListener("keydown", onKey);
390
+ }, [onCancel, onCapture, selectedMode]);
391
+ const tooltipLabel = hoveredMode ? MODES.find((m) => m.mode === hoveredMode)?.label : null;
392
+ return /* @__PURE__ */ jsxs2(
393
+ "div",
394
+ {
395
+ "data-afterbefore": "true",
396
+ style: {
397
+ position: "fixed",
398
+ bottom: 48,
399
+ left: "50%",
400
+ transform: "translateX(-50%)",
401
+ zIndex: 2147483647,
402
+ display: "flex",
403
+ flexDirection: "column",
404
+ alignItems: "center",
405
+ gap: 8
406
+ },
407
+ children: [
408
+ tooltipLabel && /* @__PURE__ */ jsx2(
409
+ "div",
410
+ {
411
+ style: {
412
+ background: "rgba(32, 32, 36, 0.92)",
413
+ backdropFilter: "blur(20px)",
414
+ WebkitBackdropFilter: "blur(20px)",
415
+ border: "1px solid rgba(255, 255, 255, 0.1)",
416
+ borderRadius: 6,
417
+ padding: "4px 10px",
418
+ color: "rgba(255, 255, 255, 0.85)",
419
+ fontSize: 12,
420
+ fontFamily: "system-ui, -apple-system, sans-serif",
421
+ whiteSpace: "nowrap",
422
+ boxShadow: "0 4px 12px rgba(0, 0, 0, 0.3)"
423
+ },
424
+ children: tooltipLabel
425
+ }
426
+ ),
427
+ /* @__PURE__ */ jsxs2(
428
+ "div",
429
+ {
430
+ style: {
431
+ display: "flex",
432
+ alignItems: "center",
433
+ gap: 0,
434
+ background: "rgba(32, 32, 36, 0.92)",
435
+ backdropFilter: "blur(20px)",
436
+ WebkitBackdropFilter: "blur(20px)",
437
+ border: "1px solid rgba(255, 255, 255, 0.1)",
438
+ borderRadius: 14,
439
+ padding: "6px 6px",
440
+ boxShadow: "0 8px 32px rgba(0, 0, 0, 0.4)",
441
+ fontFamily: "system-ui, -apple-system, sans-serif"
442
+ },
443
+ children: [
444
+ /* @__PURE__ */ jsx2(CloseButton, { onClick: onCancel }),
445
+ /* @__PURE__ */ jsx2("div", { style: { display: "flex", alignItems: "center", gap: 2, padding: "0 4px" }, children: MODES.map(({ mode, label }) => /* @__PURE__ */ jsx2(
446
+ ModeButton,
447
+ {
448
+ mode,
449
+ label,
450
+ selected: selectedMode === mode,
451
+ onClick: () => setSelectedMode(mode),
452
+ onHover: (hovered) => setHoveredMode(hovered ? mode : null)
453
+ },
454
+ mode
455
+ )) }),
456
+ /* @__PURE__ */ jsx2(
457
+ "div",
458
+ {
459
+ style: {
460
+ width: 1,
461
+ height: 24,
462
+ background: "rgba(255, 255, 255, 0.15)",
463
+ margin: "0 6px",
464
+ flexShrink: 0
465
+ }
466
+ }
467
+ ),
468
+ /* @__PURE__ */ jsx2(CaptureButton, { onClick: () => onCapture(selectedMode) })
469
+ ]
470
+ }
471
+ )
472
+ ]
473
+ }
474
+ );
475
+ }
476
+ function CloseButton({ onClick }) {
477
+ const [hovered, setHovered] = useState3(false);
478
+ return /* @__PURE__ */ jsx2(
479
+ "button",
480
+ {
481
+ onClick,
482
+ onMouseEnter: () => setHovered(true),
483
+ onMouseLeave: () => setHovered(false),
484
+ style: {
485
+ width: 28,
486
+ height: 28,
487
+ borderRadius: "50%",
488
+ border: "1px solid rgba(255, 255, 255, 0.1)",
489
+ background: hovered ? "rgba(255, 255, 255, 0.12)" : "rgba(255, 255, 255, 0.06)",
490
+ display: "flex",
491
+ alignItems: "center",
492
+ justifyContent: "center",
493
+ cursor: "pointer",
494
+ flexShrink: 0,
495
+ padding: 0,
496
+ transition: "background 0.1s",
497
+ marginRight: 4
498
+ },
499
+ children: /* @__PURE__ */ jsx2("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", children: /* @__PURE__ */ jsx2(
500
+ "path",
501
+ {
502
+ d: "M3 3l6 6M9 3l-6 6",
503
+ stroke: "rgba(255, 255, 255, 0.6)",
504
+ strokeWidth: "1.5",
505
+ strokeLinecap: "round"
506
+ }
507
+ ) })
508
+ }
509
+ );
510
+ }
511
+ function ModeButton({
512
+ mode,
513
+ label,
514
+ selected,
515
+ onClick,
516
+ onHover
517
+ }) {
518
+ const [hovered, setHovered] = useState3(false);
519
+ return /* @__PURE__ */ jsx2(
520
+ "button",
521
+ {
522
+ onClick,
523
+ onMouseEnter: () => {
524
+ setHovered(true);
525
+ onHover(true);
526
+ },
527
+ onMouseLeave: () => {
528
+ setHovered(false);
529
+ onHover(false);
530
+ },
531
+ title: label,
532
+ style: {
533
+ width: 40,
534
+ height: 34,
535
+ borderRadius: 8,
536
+ border: "none",
537
+ background: selected ? "rgba(255, 255, 255, 0.15)" : hovered ? "rgba(255, 255, 255, 0.08)" : "transparent",
538
+ display: "flex",
539
+ alignItems: "center",
540
+ justifyContent: "center",
541
+ cursor: "pointer",
542
+ padding: 0,
543
+ color: selected ? "rgba(255, 255, 255, 0.95)" : "rgba(255, 255, 255, 0.45)",
544
+ transition: "background 0.1s, color 0.1s"
545
+ },
546
+ children: /* @__PURE__ */ jsx2(ModeIcon, { mode })
547
+ }
548
+ );
549
+ }
550
+ function CaptureButton({ onClick }) {
551
+ const [hovered, setHovered] = useState3(false);
552
+ return /* @__PURE__ */ jsx2(
553
+ "button",
554
+ {
555
+ onClick,
556
+ onMouseEnter: () => setHovered(true),
557
+ onMouseLeave: () => setHovered(false),
558
+ style: {
559
+ padding: "6px 16px",
560
+ borderRadius: 8,
561
+ border: "none",
562
+ background: hovered ? "#2563eb" : "#3b82f6",
563
+ color: "white",
564
+ fontSize: 13,
565
+ fontWeight: 600,
566
+ fontFamily: "inherit",
567
+ cursor: "pointer",
568
+ whiteSpace: "nowrap",
569
+ transition: "background 0.1s",
570
+ flexShrink: 0
571
+ },
572
+ children: "Capture"
573
+ }
574
+ );
575
+ }
576
+ function ModeIcon({ mode }) {
577
+ switch (mode) {
578
+ case "area":
579
+ return /* @__PURE__ */ jsxs2("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: [
580
+ /* @__PURE__ */ jsx2(
581
+ "rect",
582
+ {
583
+ x: "3",
584
+ y: "4",
585
+ width: "14",
586
+ height: "12",
587
+ rx: "1.5",
588
+ stroke: "currentColor",
589
+ strokeWidth: "1.3",
590
+ strokeDasharray: "3 2"
591
+ }
592
+ ),
593
+ /* @__PURE__ */ jsx2("line", { x1: "10", y1: "7", x2: "10", y2: "13", stroke: "currentColor", strokeWidth: "1", strokeLinecap: "round" }),
594
+ /* @__PURE__ */ jsx2("line", { x1: "7", y1: "10", x2: "13", y2: "10", stroke: "currentColor", strokeWidth: "1", strokeLinecap: "round" })
595
+ ] });
596
+ case "viewport":
597
+ return /* @__PURE__ */ jsxs2("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: [
598
+ /* @__PURE__ */ jsx2(
599
+ "rect",
600
+ {
601
+ x: "2",
602
+ y: "3",
603
+ width: "16",
604
+ height: "12",
605
+ rx: "1.5",
606
+ stroke: "currentColor",
607
+ strokeWidth: "1.3"
608
+ }
609
+ ),
610
+ /* @__PURE__ */ jsx2(
611
+ "line",
612
+ {
613
+ x1: "2",
614
+ y1: "17",
615
+ x2: "18",
616
+ y2: "17",
617
+ stroke: "currentColor",
618
+ strokeWidth: "1.3",
619
+ strokeLinecap: "round"
620
+ }
621
+ )
622
+ ] });
623
+ case "fullpage":
624
+ return /* @__PURE__ */ jsxs2("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: [
625
+ /* @__PURE__ */ jsx2(
626
+ "rect",
627
+ {
628
+ x: "4",
629
+ y: "1",
630
+ width: "12",
631
+ height: "18",
632
+ rx: "1.5",
633
+ stroke: "currentColor",
634
+ strokeWidth: "1.3"
635
+ }
636
+ ),
637
+ /* @__PURE__ */ jsx2("line", { x1: "7", y1: "5", x2: "13", y2: "5", stroke: "currentColor", strokeWidth: "1", strokeLinecap: "round" }),
638
+ /* @__PURE__ */ jsx2("line", { x1: "7", y1: "8", x2: "13", y2: "8", stroke: "currentColor", strokeWidth: "1", strokeLinecap: "round" }),
639
+ /* @__PURE__ */ jsx2("line", { x1: "7", y1: "11", x2: "13", y2: "11", stroke: "currentColor", strokeWidth: "1", strokeLinecap: "round" })
640
+ ] });
641
+ case "component":
642
+ return /* @__PURE__ */ jsxs2("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: [
643
+ /* @__PURE__ */ jsx2(
644
+ "path",
645
+ {
646
+ d: "M4 3l3 12 2.5-4.5L14 13 4 3z",
647
+ stroke: "currentColor",
648
+ strokeWidth: "1.2",
649
+ strokeLinejoin: "round",
650
+ strokeLinecap: "round"
651
+ }
652
+ ),
653
+ /* @__PURE__ */ jsx2(
654
+ "rect",
655
+ {
656
+ x: "10",
657
+ y: "7",
658
+ width: "7",
659
+ height: "7",
660
+ rx: "1",
661
+ stroke: "currentColor",
662
+ strokeWidth: "1.1",
663
+ strokeDasharray: "2 1.5"
664
+ }
665
+ )
666
+ ] });
667
+ }
668
+ }
669
+
371
670
  // src/overlay/ui/selector.tsx
372
- import React2, { useState as useState3, useRef as useRef2, useCallback as useCallback3, useEffect as useEffect2 } from "react";
373
- import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
671
+ import React3, { useState as useState4, useRef as useRef2, useCallback as useCallback4, useEffect as useEffect3 } from "react";
672
+ import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
374
673
  var HANDLE_R = 6;
375
674
  var HANDLE_HIT = 16;
376
675
  var MIN_SIZE = 20;
@@ -384,13 +683,13 @@ var ASPECT_RATIOS = [
384
683
  { label: "3:2", value: 3 / 2 },
385
684
  { label: "21:9", value: 21 / 9 }
386
685
  ];
387
- function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
388
- const [rect, setRect] = useState3(null);
389
- const [placed, setPlaced] = useState3(false);
390
- const [aspect, setAspect] = useState3("Free");
391
- const [aspectOpen, setAspectOpen] = useState3(false);
392
- const [savedOpen, setSavedOpen] = useState3(false);
393
- const [presets, setPresets] = useState3(
686
+ function Selector({ onSelect, onCancel }) {
687
+ const [rect, setRect] = useState4(null);
688
+ const [placed, setPlaced] = useState4(false);
689
+ const [aspect, setAspect] = useState4("Free");
690
+ const [aspectOpen, setAspectOpen] = useState4(false);
691
+ const [savedOpen, setSavedOpen] = useState4(false);
692
+ const [presets, setPresets] = useState4(
394
693
  () => {
395
694
  try {
396
695
  const s = localStorage.getItem("ab-area-presets");
@@ -400,22 +699,22 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
400
699
  }
401
700
  }
402
701
  );
403
- const [cursor, setCursor] = useState3("crosshair");
404
- const [magnet, setMagnet] = useState3(() => {
702
+ const [cursor, setCursor] = useState4("crosshair");
703
+ const [magnet, setMagnet] = useState4(() => {
405
704
  try {
406
705
  return localStorage.getItem("ab-magnet") !== "false";
407
706
  } catch {
408
707
  return true;
409
708
  }
410
709
  });
411
- const [snappedX, setSnappedX] = useState3(false);
710
+ const [snappedX, setSnappedX] = useState4(false);
412
711
  const mode = useRef2("none");
413
712
  const start = useRef2({ x: 0, y: 0 });
414
713
  const snapRef = useRef2({ x: 0, y: 0, w: 0, h: 0 });
415
714
  const corner = useRef2("br");
416
715
  const panelRef = useRef2(null);
417
716
  const ratio = ASPECT_RATIOS.find((a) => a.label === aspect)?.value ?? 0;
418
- const applySnap = useCallback3(
717
+ const applySnap = useCallback4(
419
718
  (r) => {
420
719
  if (!magnet) {
421
720
  setSnappedX(false);
@@ -433,7 +732,7 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
433
732
  },
434
733
  [magnet]
435
734
  );
436
- useEffect2(() => {
735
+ useEffect3(() => {
437
736
  const onKey = (e) => {
438
737
  if (e.target?.tagName === "INPUT") {
439
738
  if (e.key === "Escape") e.target.blur();
@@ -458,7 +757,7 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
458
757
  document.addEventListener("keydown", onKey);
459
758
  return () => document.removeEventListener("keydown", onKey);
460
759
  }, [placed, rect, onSelect, onCancel]);
461
- const hitCorner = useCallback3(
760
+ const hitCorner = useCallback4(
462
761
  (mx, my, r) => {
463
762
  const cs = [
464
763
  ["tl", r.x, r.y],
@@ -474,11 +773,11 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
474
773
  },
475
774
  []
476
775
  );
477
- const hitInside = useCallback3(
776
+ const hitInside = useCallback4(
478
777
  (mx, my, r) => mx >= r.x && mx <= r.x + r.w && my >= r.y && my <= r.y + r.h,
479
778
  []
480
779
  );
481
- const onDown = useCallback3(
780
+ const onDown = useCallback4(
482
781
  (e) => {
483
782
  if (panelRef.current?.contains(e.target)) return;
484
783
  e.preventDefault();
@@ -508,7 +807,7 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
508
807
  },
509
808
  [placed, rect, hitCorner, hitInside]
510
809
  );
511
- const onMove = useCallback3(
810
+ const onMove = useCallback4(
512
811
  (e) => {
513
812
  const mx = e.clientX, my = e.clientY;
514
813
  if (mode.current === "drawing") {
@@ -561,7 +860,7 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
561
860
  },
562
861
  [ratio, placed, rect, hitCorner, hitInside, applySnap]
563
862
  );
564
- const onUp = useCallback3(
863
+ const onUp = useCallback4(
565
864
  (e) => {
566
865
  const prevMode = mode.current;
567
866
  if (prevMode === "drawing" && rect) {
@@ -587,7 +886,7 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
587
886
  },
588
887
  [rect, placed, onSelect]
589
888
  );
590
- const setSize = useCallback3(
889
+ const setSize = useCallback4(
591
890
  (field, v) => {
592
891
  const n = parseInt(v, 10);
593
892
  if (isNaN(n) || n < MIN_SIZE || !rect) return;
@@ -599,7 +898,7 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
599
898
  },
600
899
  [rect, ratio]
601
900
  );
602
- const setPos = useCallback3(
901
+ const setPos = useCallback4(
603
902
  (field, v) => {
604
903
  const n = parseInt(v, 10);
605
904
  if (isNaN(n) || !rect) return;
@@ -607,7 +906,7 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
607
906
  },
608
907
  [rect]
609
908
  );
610
- const savePreset = useCallback3(() => {
909
+ const savePreset = useCallback4(() => {
611
910
  if (!rect) return;
612
911
  const label = `${Math.round(rect.w)}\xD7${Math.round(rect.h)}`;
613
912
  const next = [
@@ -621,7 +920,7 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
621
920
  }
622
921
  setSavedOpen(false);
623
922
  }, [rect, presets]);
624
- const loadPreset = useCallback3((p) => {
923
+ const loadPreset = useCallback4((p) => {
625
924
  setRect({ ...p.rect });
626
925
  setPlaced(true);
627
926
  setSavedOpen(false);
@@ -629,7 +928,7 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
629
928
  const activeCursor = mode.current === "moving" ? "move" : mode.current === "resizing" ? "nwse-resize" : mode.current === "drawing" ? "crosshair" : cursor;
630
929
  const panelAbove = rect && rect.y + rect.h + PANEL_HEIGHT_EST > window.innerHeight;
631
930
  const hasRect = rect && rect.w > 0 && rect.h > 0;
632
- return /* @__PURE__ */ jsxs2(
931
+ return /* @__PURE__ */ jsxs3(
633
932
  "div",
634
933
  {
635
934
  "data-afterbefore": "true",
@@ -643,7 +942,7 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
643
942
  cursor: activeCursor
644
943
  },
645
944
  children: [
646
- snappedX && /* @__PURE__ */ jsx2(
945
+ snappedX && /* @__PURE__ */ jsx3(
647
946
  "div",
648
947
  {
649
948
  style: {
@@ -658,7 +957,7 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
658
957
  }
659
958
  }
660
959
  ),
661
- /* @__PURE__ */ jsx2(
960
+ /* @__PURE__ */ jsx3(
662
961
  "div",
663
962
  {
664
963
  style: {
@@ -679,8 +978,8 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
679
978
  }
680
979
  }
681
980
  ),
682
- hasRect && /* @__PURE__ */ jsxs2(Fragment, { children: [
683
- /* @__PURE__ */ jsx2(
981
+ hasRect && /* @__PURE__ */ jsxs3(Fragment, { children: [
982
+ /* @__PURE__ */ jsx3(
684
983
  "div",
685
984
  {
686
985
  style: {
@@ -694,8 +993,8 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
694
993
  }
695
994
  }
696
995
  ),
697
- placed && [1, 2].map((i) => /* @__PURE__ */ jsxs2(React2.Fragment, { children: [
698
- /* @__PURE__ */ jsx2(
996
+ placed && [1, 2].map((i) => /* @__PURE__ */ jsxs3(React3.Fragment, { children: [
997
+ /* @__PURE__ */ jsx3(
699
998
  "div",
700
999
  {
701
1000
  style: {
@@ -709,7 +1008,7 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
709
1008
  }
710
1009
  }
711
1010
  ),
712
- /* @__PURE__ */ jsx2(
1011
+ /* @__PURE__ */ jsx3(
713
1012
  "div",
714
1013
  {
715
1014
  style: {
@@ -729,7 +1028,7 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
729
1028
  [rect.x + rect.w, rect.y],
730
1029
  [rect.x, rect.y + rect.h],
731
1030
  [rect.x + rect.w, rect.y + rect.h]
732
- ].map(([cx, cy], i) => /* @__PURE__ */ jsx2(
1031
+ ].map(([cx, cy], i) => /* @__PURE__ */ jsx3(
733
1032
  "div",
734
1033
  {
735
1034
  style: {
@@ -746,7 +1045,7 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
746
1045
  },
747
1046
  i
748
1047
  )),
749
- placed && /* @__PURE__ */ jsxs2(
1048
+ placed && /* @__PURE__ */ jsxs3(
750
1049
  "div",
751
1050
  {
752
1051
  ref: panelRef,
@@ -772,43 +1071,43 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
772
1071
  zIndex: 1
773
1072
  },
774
1073
  children: [
775
- /* @__PURE__ */ jsxs2(Row, { label: "Size", children: [
776
- /* @__PURE__ */ jsx2(
1074
+ /* @__PURE__ */ jsxs3(Row, { label: "Size", children: [
1075
+ /* @__PURE__ */ jsx3(
777
1076
  NumInput,
778
1077
  {
779
1078
  value: Math.round(rect.w),
780
1079
  onChange: (v) => setSize("w", v)
781
1080
  }
782
1081
  ),
783
- /* @__PURE__ */ jsx2(Sep, { children: "\xD7" }),
784
- /* @__PURE__ */ jsx2(
1082
+ /* @__PURE__ */ jsx3(Sep, { children: "\xD7" }),
1083
+ /* @__PURE__ */ jsx3(
785
1084
  NumInput,
786
1085
  {
787
1086
  value: Math.round(rect.h),
788
1087
  onChange: (v) => setSize("h", v)
789
1088
  }
790
1089
  ),
791
- /* @__PURE__ */ jsx2(Unit, { children: "px" })
1090
+ /* @__PURE__ */ jsx3(Unit, { children: "px" })
792
1091
  ] }),
793
- /* @__PURE__ */ jsxs2(Row, { label: "Position", children: [
794
- /* @__PURE__ */ jsx2(
1092
+ /* @__PURE__ */ jsxs3(Row, { label: "Position", children: [
1093
+ /* @__PURE__ */ jsx3(
795
1094
  NumInput,
796
1095
  {
797
1096
  value: Math.round(rect.x),
798
1097
  onChange: (v) => setPos("x", v)
799
1098
  }
800
1099
  ),
801
- /* @__PURE__ */ jsx2(Sep, {}),
802
- /* @__PURE__ */ jsx2(
1100
+ /* @__PURE__ */ jsx3(Sep, {}),
1101
+ /* @__PURE__ */ jsx3(
803
1102
  NumInput,
804
1103
  {
805
1104
  value: Math.round(rect.y),
806
1105
  onChange: (v) => setPos("y", v)
807
1106
  }
808
1107
  ),
809
- /* @__PURE__ */ jsx2(Unit, { children: "px" })
1108
+ /* @__PURE__ */ jsx3(Unit, { children: "px" })
810
1109
  ] }),
811
- /* @__PURE__ */ jsx2(
1110
+ /* @__PURE__ */ jsx3(
812
1111
  "div",
813
1112
  {
814
1113
  style: {
@@ -818,13 +1117,13 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
818
1117
  }
819
1118
  }
820
1119
  ),
821
- /* @__PURE__ */ jsxs2(
1120
+ /* @__PURE__ */ jsxs3(
822
1121
  "div",
823
1122
  {
824
1123
  style: { display: "flex", alignItems: "center", gap: 12 },
825
1124
  children: [
826
- /* @__PURE__ */ jsxs2("div", { style: { position: "relative" }, children: [
827
- /* @__PURE__ */ jsxs2(
1125
+ /* @__PURE__ */ jsxs3("div", { style: { position: "relative" }, children: [
1126
+ /* @__PURE__ */ jsxs3(
828
1127
  DropBtn,
829
1128
  {
830
1129
  active: aspect !== "Free",
@@ -833,13 +1132,13 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
833
1132
  setSavedOpen(false);
834
1133
  },
835
1134
  children: [
836
- /* @__PURE__ */ jsx2(AspectIcon, {}),
1135
+ /* @__PURE__ */ jsx3(AspectIcon, {}),
837
1136
  aspect === "Free" ? "Free" : aspect,
838
- /* @__PURE__ */ jsx2(Chevron, {})
1137
+ /* @__PURE__ */ jsx3(Chevron, {})
839
1138
  ]
840
1139
  }
841
1140
  ),
842
- aspectOpen && /* @__PURE__ */ jsx2(DropMenu, { children: ASPECT_RATIOS.map((ar) => /* @__PURE__ */ jsx2(
1141
+ aspectOpen && /* @__PURE__ */ jsx3(DropMenu, { children: ASPECT_RATIOS.map((ar) => /* @__PURE__ */ jsx3(
843
1142
  DropItem,
844
1143
  {
845
1144
  active: ar.label === aspect,
@@ -855,8 +1154,8 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
855
1154
  ar.label
856
1155
  )) })
857
1156
  ] }),
858
- /* @__PURE__ */ jsxs2("div", { style: { position: "relative" }, children: [
859
- /* @__PURE__ */ jsxs2(
1157
+ /* @__PURE__ */ jsxs3("div", { style: { position: "relative" }, children: [
1158
+ /* @__PURE__ */ jsxs3(
860
1159
  DropBtn,
861
1160
  {
862
1161
  onClick: () => {
@@ -864,14 +1163,14 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
864
1163
  setAspectOpen(false);
865
1164
  },
866
1165
  children: [
867
- /* @__PURE__ */ jsx2(SavedIcon, {}),
1166
+ /* @__PURE__ */ jsx3(SavedIcon, {}),
868
1167
  "Saved",
869
- /* @__PURE__ */ jsx2(Chevron, {})
1168
+ /* @__PURE__ */ jsx3(Chevron, {})
870
1169
  ]
871
1170
  }
872
1171
  ),
873
- savedOpen && /* @__PURE__ */ jsxs2(DropMenu, { children: [
874
- /* @__PURE__ */ jsx2(
1172
+ savedOpen && /* @__PURE__ */ jsxs3(DropMenu, { children: [
1173
+ /* @__PURE__ */ jsx3(
875
1174
  DropItem,
876
1175
  {
877
1176
  accent: true,
@@ -879,7 +1178,7 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
879
1178
  children: "Save current"
880
1179
  }
881
1180
  ),
882
- presets.length > 0 && /* @__PURE__ */ jsx2(
1181
+ presets.length > 0 && /* @__PURE__ */ jsx3(
883
1182
  "div",
884
1183
  {
885
1184
  style: {
@@ -889,7 +1188,7 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
889
1188
  }
890
1189
  }
891
1190
  ),
892
- presets.map((p) => /* @__PURE__ */ jsx2(
1191
+ presets.map((p) => /* @__PURE__ */ jsx3(
893
1192
  DropItem,
894
1193
  {
895
1194
  onClick: () => loadPreset(p),
@@ -897,7 +1196,7 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
897
1196
  },
898
1197
  p.label
899
1198
  )),
900
- presets.length === 0 && /* @__PURE__ */ jsx2(
1199
+ presets.length === 0 && /* @__PURE__ */ jsx3(
901
1200
  "div",
902
1201
  {
903
1202
  style: {
@@ -913,39 +1212,7 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
913
1212
  ]
914
1213
  }
915
1214
  ),
916
- (onViewport || onFullPage || onComponent) && /* @__PURE__ */ jsxs2(Fragment, { children: [
917
- /* @__PURE__ */ jsx2(
918
- "div",
919
- {
920
- style: {
921
- height: 1,
922
- background: "rgba(255, 255, 255, 0.08)",
923
- margin: "1px 0"
924
- }
925
- }
926
- ),
927
- /* @__PURE__ */ jsxs2(
928
- "div",
929
- {
930
- style: { display: "flex", alignItems: "center", gap: 4 },
931
- children: [
932
- onViewport && /* @__PURE__ */ jsxs2(ModeBtn, { onClick: onViewport, children: [
933
- /* @__PURE__ */ jsx2(ViewportIcon, {}),
934
- "Viewport"
935
- ] }),
936
- onFullPage && /* @__PURE__ */ jsxs2(ModeBtn, { onClick: onFullPage, children: [
937
- /* @__PURE__ */ jsx2(FullPageIcon, {}),
938
- "Full Page"
939
- ] }),
940
- onComponent && /* @__PURE__ */ jsxs2(ModeBtn, { onClick: onComponent, children: [
941
- /* @__PURE__ */ jsx2(ComponentIcon, {}),
942
- "Component"
943
- ] })
944
- ]
945
- }
946
- )
947
- ] }),
948
- /* @__PURE__ */ jsx2(
1215
+ /* @__PURE__ */ jsx3(
949
1216
  "div",
950
1217
  {
951
1218
  style: {
@@ -953,7 +1220,7 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
953
1220
  alignItems: "center",
954
1221
  gap: 6
955
1222
  },
956
- children: /* @__PURE__ */ jsx2(
1223
+ children: /* @__PURE__ */ jsx3(
957
1224
  MagnetToggle,
958
1225
  {
959
1226
  enabled: magnet,
@@ -969,7 +1236,7 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
969
1236
  )
970
1237
  }
971
1238
  ),
972
- /* @__PURE__ */ jsx2(
1239
+ /* @__PURE__ */ jsx3(
973
1240
  "div",
974
1241
  {
975
1242
  style: {
@@ -983,7 +1250,7 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
983
1250
  ]
984
1251
  }
985
1252
  ),
986
- !placed && /* @__PURE__ */ jsxs2(
1253
+ !placed && /* @__PURE__ */ jsxs3(
987
1254
  "div",
988
1255
  {
989
1256
  style: {
@@ -1008,7 +1275,7 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
1008
1275
  }
1009
1276
  )
1010
1277
  ] }),
1011
- !rect && /* @__PURE__ */ jsxs2(
1278
+ !rect && /* @__PURE__ */ jsx3(
1012
1279
  "div",
1013
1280
  {
1014
1281
  style: {
@@ -1016,57 +1283,13 @@ function Selector({ onSelect, onCancel, onViewport, onFullPage, onComponent }) {
1016
1283
  top: "50%",
1017
1284
  left: "50%",
1018
1285
  transform: "translate(-50%, -50%)",
1019
- display: "flex",
1020
- flexDirection: "column",
1021
- alignItems: "center",
1022
- gap: 16,
1023
- fontFamily: "system-ui, -apple-system, sans-serif"
1286
+ color: "rgba(255, 255, 255, 0.7)",
1287
+ fontSize: 14,
1288
+ fontFamily: "system-ui, -apple-system, sans-serif",
1289
+ pointerEvents: "none",
1290
+ textShadow: "0 1px 4px rgba(0, 0, 0, 0.5)"
1024
1291
  },
1025
- children: [
1026
- /* @__PURE__ */ jsx2(
1027
- "div",
1028
- {
1029
- style: {
1030
- color: "rgba(255, 255, 255, 0.7)",
1031
- fontSize: 14,
1032
- pointerEvents: "none",
1033
- textShadow: "0 1px 4px rgba(0, 0, 0, 0.5)"
1034
- },
1035
- children: "Drag to select an area \xB7 Esc to cancel"
1036
- }
1037
- ),
1038
- (onViewport || onFullPage || onComponent) && /* @__PURE__ */ jsxs2(
1039
- "div",
1040
- {
1041
- onMouseDown: (e) => e.stopPropagation(),
1042
- style: {
1043
- display: "flex",
1044
- alignItems: "center",
1045
- gap: 4,
1046
- background: "rgba(32, 32, 36, 0.92)",
1047
- backdropFilter: "blur(20px)",
1048
- WebkitBackdropFilter: "blur(20px)",
1049
- border: "1px solid rgba(255, 255, 255, 0.1)",
1050
- borderRadius: 8,
1051
- padding: "6px 8px"
1052
- },
1053
- children: [
1054
- onViewport && /* @__PURE__ */ jsxs2(ModeBtn, { onClick: onViewport, children: [
1055
- /* @__PURE__ */ jsx2(ViewportIcon, {}),
1056
- "Viewport"
1057
- ] }),
1058
- onFullPage && /* @__PURE__ */ jsxs2(ModeBtn, { onClick: onFullPage, children: [
1059
- /* @__PURE__ */ jsx2(FullPageIcon, {}),
1060
- "Full Page"
1061
- ] }),
1062
- onComponent && /* @__PURE__ */ jsxs2(ModeBtn, { onClick: onComponent, children: [
1063
- /* @__PURE__ */ jsx2(ComponentIcon, {}),
1064
- "Component"
1065
- ] })
1066
- ]
1067
- }
1068
- )
1069
- ]
1292
+ children: "Drag to select an area \xB7 Esc to cancel"
1070
1293
  }
1071
1294
  )
1072
1295
  ]
@@ -1077,8 +1300,8 @@ function Row({
1077
1300
  label,
1078
1301
  children
1079
1302
  }) {
1080
- return /* @__PURE__ */ jsxs2("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
1081
- /* @__PURE__ */ jsx2(
1303
+ return /* @__PURE__ */ jsxs3("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
1304
+ /* @__PURE__ */ jsx3(
1082
1305
  "span",
1083
1306
  {
1084
1307
  style: {
@@ -1095,7 +1318,7 @@ function Row({
1095
1318
  ] });
1096
1319
  }
1097
1320
  function Sep({ children }) {
1098
- return /* @__PURE__ */ jsx2(
1321
+ return /* @__PURE__ */ jsx3(
1099
1322
  "span",
1100
1323
  {
1101
1324
  style: {
@@ -1111,7 +1334,7 @@ function Sep({ children }) {
1111
1334
  );
1112
1335
  }
1113
1336
  function Unit({ children }) {
1114
- return /* @__PURE__ */ jsx2(
1337
+ return /* @__PURE__ */ jsx3(
1115
1338
  "span",
1116
1339
  {
1117
1340
  style: {
@@ -1127,12 +1350,12 @@ function NumInput({
1127
1350
  value,
1128
1351
  onChange
1129
1352
  }) {
1130
- const [editing, setEditing] = useState3(false);
1131
- const [text, setText] = useState3(String(value));
1132
- useEffect2(() => {
1353
+ const [editing, setEditing] = useState4(false);
1354
+ const [text, setText] = useState4(String(value));
1355
+ useEffect3(() => {
1133
1356
  if (!editing) setText(String(value));
1134
1357
  }, [value, editing]);
1135
- return /* @__PURE__ */ jsx2(
1358
+ return /* @__PURE__ */ jsx3(
1136
1359
  "input",
1137
1360
  {
1138
1361
  type: "text",
@@ -1169,7 +1392,7 @@ function DropBtn({
1169
1392
  onClick,
1170
1393
  active
1171
1394
  }) {
1172
- return /* @__PURE__ */ jsx2(
1395
+ return /* @__PURE__ */ jsx3(
1173
1396
  "button",
1174
1397
  {
1175
1398
  onClick,
@@ -1190,7 +1413,7 @@ function DropBtn({
1190
1413
  );
1191
1414
  }
1192
1415
  function DropMenu({ children }) {
1193
- return /* @__PURE__ */ jsx2(
1416
+ return /* @__PURE__ */ jsx3(
1194
1417
  "div",
1195
1418
  {
1196
1419
  style: {
@@ -1217,7 +1440,7 @@ function DropItem({
1217
1440
  active,
1218
1441
  accent
1219
1442
  }) {
1220
- return /* @__PURE__ */ jsx2(
1443
+ return /* @__PURE__ */ jsx3(
1221
1444
  "button",
1222
1445
  {
1223
1446
  onClick,
@@ -1238,7 +1461,7 @@ function DropItem({
1238
1461
  );
1239
1462
  }
1240
1463
  function Chevron() {
1241
- return /* @__PURE__ */ jsx2("svg", { width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", children: /* @__PURE__ */ jsx2(
1464
+ return /* @__PURE__ */ jsx3("svg", { width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", children: /* @__PURE__ */ jsx3(
1242
1465
  "path",
1243
1466
  {
1244
1467
  d: "M3 4l2 2.5L7 4",
@@ -1248,8 +1471,8 @@ function Chevron() {
1248
1471
  ) });
1249
1472
  }
1250
1473
  function AspectIcon() {
1251
- return /* @__PURE__ */ jsxs2("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
1252
- /* @__PURE__ */ jsx2(
1474
+ return /* @__PURE__ */ jsxs3("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
1475
+ /* @__PURE__ */ jsx3(
1253
1476
  "rect",
1254
1477
  {
1255
1478
  x: "2",
@@ -1262,7 +1485,7 @@ function AspectIcon() {
1262
1485
  strokeDasharray: "2 1.5"
1263
1486
  }
1264
1487
  ),
1265
- /* @__PURE__ */ jsx2(
1488
+ /* @__PURE__ */ jsx3(
1266
1489
  "line",
1267
1490
  {
1268
1491
  x1: "6.33",
@@ -1274,7 +1497,7 @@ function AspectIcon() {
1274
1497
  strokeDasharray: "1.5 1"
1275
1498
  }
1276
1499
  ),
1277
- /* @__PURE__ */ jsx2(
1500
+ /* @__PURE__ */ jsx3(
1278
1501
  "line",
1279
1502
  {
1280
1503
  x1: "9.67",
@@ -1289,7 +1512,7 @@ function AspectIcon() {
1289
1512
  ] });
1290
1513
  }
1291
1514
  function SavedIcon() {
1292
- return /* @__PURE__ */ jsx2("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx2(
1515
+ return /* @__PURE__ */ jsx3("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx3(
1293
1516
  "rect",
1294
1517
  {
1295
1518
  x: "2",
@@ -1303,47 +1526,11 @@ function SavedIcon() {
1303
1526
  }
1304
1527
  ) });
1305
1528
  }
1306
- function ModeBtn({
1307
- children,
1308
- onClick
1309
- }) {
1310
- return /* @__PURE__ */ jsx2(
1311
- "button",
1312
- {
1313
- onClick,
1314
- style: {
1315
- display: "flex",
1316
- alignItems: "center",
1317
- gap: 5,
1318
- background: "rgba(255, 255, 255, 0.06)",
1319
- border: "1px solid rgba(255, 255, 255, 0.08)",
1320
- borderRadius: 6,
1321
- color: "rgba(255, 255, 255, 0.55)",
1322
- cursor: "pointer",
1323
- fontSize: 11,
1324
- fontFamily: "inherit",
1325
- padding: "4px 8px",
1326
- transition: "background 0.1s, color 0.1s"
1327
- },
1328
- onMouseEnter: (e) => {
1329
- const btn = e.currentTarget;
1330
- btn.style.background = "rgba(255, 255, 255, 0.12)";
1331
- btn.style.color = "rgba(255, 255, 255, 0.85)";
1332
- },
1333
- onMouseLeave: (e) => {
1334
- const btn = e.currentTarget;
1335
- btn.style.background = "rgba(255, 255, 255, 0.06)";
1336
- btn.style.color = "rgba(255, 255, 255, 0.55)";
1337
- },
1338
- children
1339
- }
1340
- );
1341
- }
1342
1529
  function MagnetToggle({
1343
1530
  enabled,
1344
1531
  onToggle
1345
1532
  }) {
1346
- return /* @__PURE__ */ jsxs2(
1533
+ return /* @__PURE__ */ jsxs3(
1347
1534
  "button",
1348
1535
  {
1349
1536
  onClick: onToggle,
@@ -1360,15 +1547,15 @@ function MagnetToggle({
1360
1547
  padding: "2px 0"
1361
1548
  },
1362
1549
  children: [
1363
- /* @__PURE__ */ jsx2(MagnetIcon, {}),
1550
+ /* @__PURE__ */ jsx3(MagnetIcon, {}),
1364
1551
  "Magnet"
1365
1552
  ]
1366
1553
  }
1367
1554
  );
1368
1555
  }
1369
1556
  function MagnetIcon() {
1370
- return /* @__PURE__ */ jsxs2("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", children: [
1371
- /* @__PURE__ */ jsx2(
1557
+ return /* @__PURE__ */ jsxs3("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", children: [
1558
+ /* @__PURE__ */ jsx3(
1372
1559
  "path",
1373
1560
  {
1374
1561
  d: "M4 2v4a4 4 0 008 0V2",
@@ -1377,126 +1564,19 @@ function MagnetIcon() {
1377
1564
  strokeLinecap: "round"
1378
1565
  }
1379
1566
  ),
1380
- /* @__PURE__ */ jsx2("line", { x1: "4", y1: "2", x2: "4", y2: "5", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round" }),
1381
- /* @__PURE__ */ jsx2("line", { x1: "12", y1: "2", x2: "12", y2: "5", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round" })
1382
- ] });
1383
- }
1384
- function ViewportIcon() {
1385
- return /* @__PURE__ */ jsxs2("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", children: [
1386
- /* @__PURE__ */ jsx2(
1387
- "rect",
1388
- {
1389
- x: "1",
1390
- y: "2",
1391
- width: "14",
1392
- height: "11",
1393
- rx: "1.5",
1394
- stroke: "currentColor",
1395
- strokeWidth: "1.3"
1396
- }
1397
- ),
1398
- /* @__PURE__ */ jsx2(
1399
- "line",
1400
- {
1401
- x1: "1",
1402
- y1: "14",
1403
- x2: "15",
1404
- y2: "14",
1405
- stroke: "currentColor",
1406
- strokeWidth: "1.3",
1407
- strokeLinecap: "round"
1408
- }
1409
- )
1410
- ] });
1411
- }
1412
- function FullPageIcon() {
1413
- return /* @__PURE__ */ jsxs2("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", children: [
1414
- /* @__PURE__ */ jsx2(
1415
- "rect",
1416
- {
1417
- x: "3",
1418
- y: "1",
1419
- width: "10",
1420
- height: "14",
1421
- rx: "1.5",
1422
- stroke: "currentColor",
1423
- strokeWidth: "1.3"
1424
- }
1425
- ),
1426
- /* @__PURE__ */ jsx2(
1427
- "line",
1428
- {
1429
- x1: "5.5",
1430
- y1: "4",
1431
- x2: "10.5",
1432
- y2: "4",
1433
- stroke: "currentColor",
1434
- strokeWidth: "1",
1435
- strokeLinecap: "round"
1436
- }
1437
- ),
1438
- /* @__PURE__ */ jsx2(
1439
- "line",
1440
- {
1441
- x1: "5.5",
1442
- y1: "6.5",
1443
- x2: "10.5",
1444
- y2: "6.5",
1445
- stroke: "currentColor",
1446
- strokeWidth: "1",
1447
- strokeLinecap: "round"
1448
- }
1449
- ),
1450
- /* @__PURE__ */ jsx2(
1451
- "line",
1452
- {
1453
- x1: "5.5",
1454
- y1: "9",
1455
- x2: "10.5",
1456
- y2: "9",
1457
- stroke: "currentColor",
1458
- strokeWidth: "1",
1459
- strokeLinecap: "round"
1460
- }
1461
- )
1462
- ] });
1463
- }
1464
- function ComponentIcon() {
1465
- return /* @__PURE__ */ jsxs2("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", children: [
1466
- /* @__PURE__ */ jsx2(
1467
- "path",
1468
- {
1469
- d: "M3 2l2.5 10 2-3.5L11 11 3 2z",
1470
- stroke: "currentColor",
1471
- strokeWidth: "1.2",
1472
- strokeLinejoin: "round",
1473
- strokeLinecap: "round"
1474
- }
1475
- ),
1476
- /* @__PURE__ */ jsx2(
1477
- "rect",
1478
- {
1479
- x: "8",
1480
- y: "5",
1481
- width: "6.5",
1482
- height: "6.5",
1483
- rx: "1",
1484
- stroke: "currentColor",
1485
- strokeWidth: "1.1",
1486
- strokeDasharray: "2 1.5"
1487
- }
1488
- )
1567
+ /* @__PURE__ */ jsx3("line", { x1: "4", y1: "2", x2: "4", y2: "5", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round" }),
1568
+ /* @__PURE__ */ jsx3("line", { x1: "12", y1: "2", x2: "12", y2: "5", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round" })
1489
1569
  ] });
1490
1570
  }
1491
1571
 
1492
1572
  // src/overlay/ui/inspector.tsx
1493
- import { useEffect as useEffect3, useRef as useRef3, useCallback as useCallback4, useState as useState4 } from "react";
1494
- import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1573
+ import { useEffect as useEffect4, useRef as useRef3, useCallback as useCallback5, useState as useState5 } from "react";
1574
+ import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1495
1575
  function Inspector({ onSelect, onCancel }) {
1496
- const [highlight, setHighlight] = useState4(null);
1576
+ const [highlight, setHighlight] = useState5(null);
1497
1577
  const hoveredEl = useRef3(null);
1498
1578
  const styleEl = useRef3(null);
1499
- useEffect3(() => {
1579
+ useEffect4(() => {
1500
1580
  const style = document.createElement("style");
1501
1581
  style.setAttribute("data-afterbefore", "true");
1502
1582
  style.textContent = "*, *::before, *::after { cursor: crosshair !important; }";
@@ -1506,7 +1586,7 @@ function Inspector({ onSelect, onCancel }) {
1506
1586
  style.remove();
1507
1587
  };
1508
1588
  }, []);
1509
- const isOverlayElement = useCallback4((el) => {
1589
+ const isOverlayElement = useCallback5((el) => {
1510
1590
  let node = el;
1511
1591
  while (node) {
1512
1592
  if (node instanceof HTMLElement && node.dataset.afterbefore) return true;
@@ -1514,7 +1594,7 @@ function Inspector({ onSelect, onCancel }) {
1514
1594
  }
1515
1595
  return false;
1516
1596
  }, []);
1517
- const handleMouseMove = useCallback4(
1597
+ const handleMouseMove = useCallback5(
1518
1598
  (e) => {
1519
1599
  const el = document.elementFromPoint(e.clientX, e.clientY);
1520
1600
  if (!el || !(el instanceof HTMLElement) || isOverlayElement(el)) {
@@ -1534,7 +1614,7 @@ function Inspector({ onSelect, onCancel }) {
1534
1614
  },
1535
1615
  [isOverlayElement]
1536
1616
  );
1537
- const handleClick = useCallback4(
1617
+ const handleClick = useCallback5(
1538
1618
  (e) => {
1539
1619
  e.preventDefault();
1540
1620
  e.stopPropagation();
@@ -1545,7 +1625,7 @@ function Inspector({ onSelect, onCancel }) {
1545
1625
  },
1546
1626
  [onSelect]
1547
1627
  );
1548
- const handleKeyDown = useCallback4(
1628
+ const handleKeyDown = useCallback5(
1549
1629
  (e) => {
1550
1630
  if (e.key === "Escape") {
1551
1631
  onCancel();
@@ -1553,7 +1633,7 @@ function Inspector({ onSelect, onCancel }) {
1553
1633
  },
1554
1634
  [onCancel]
1555
1635
  );
1556
- useEffect3(() => {
1636
+ useEffect4(() => {
1557
1637
  document.addEventListener("mousemove", handleMouseMove, true);
1558
1638
  document.addEventListener("click", handleClick, true);
1559
1639
  document.addEventListener("keydown", handleKeyDown);
@@ -1563,9 +1643,9 @@ function Inspector({ onSelect, onCancel }) {
1563
1643
  document.removeEventListener("keydown", handleKeyDown);
1564
1644
  };
1565
1645
  }, [handleMouseMove, handleClick, handleKeyDown]);
1566
- return /* @__PURE__ */ jsxs3("div", { "data-afterbefore": "true", style: { position: "fixed", inset: 0, zIndex: 2147483646, pointerEvents: "none" }, children: [
1567
- highlight && /* @__PURE__ */ jsxs3(Fragment2, { children: [
1568
- /* @__PURE__ */ jsx3(
1646
+ return /* @__PURE__ */ jsxs4("div", { "data-afterbefore": "true", style: { position: "fixed", inset: 0, zIndex: 2147483646, pointerEvents: "none" }, children: [
1647
+ highlight && /* @__PURE__ */ jsxs4(Fragment2, { children: [
1648
+ /* @__PURE__ */ jsx4(
1569
1649
  "div",
1570
1650
  {
1571
1651
  style: {
@@ -1581,7 +1661,7 @@ function Inspector({ onSelect, onCancel }) {
1581
1661
  }
1582
1662
  }
1583
1663
  ),
1584
- /* @__PURE__ */ jsx3(
1664
+ /* @__PURE__ */ jsx4(
1585
1665
  "div",
1586
1666
  {
1587
1667
  style: {
@@ -1602,7 +1682,7 @@ function Inspector({ onSelect, onCancel }) {
1602
1682
  }
1603
1683
  )
1604
1684
  ] }),
1605
- !highlight && /* @__PURE__ */ jsx3(
1685
+ !highlight && /* @__PURE__ */ jsx4(
1606
1686
  "div",
1607
1687
  {
1608
1688
  style: {
@@ -1626,18 +1706,18 @@ function Inspector({ onSelect, onCancel }) {
1626
1706
  }
1627
1707
 
1628
1708
  // src/overlay/ui/status.tsx
1629
- import { useState as useState5, useRef as useRef4, useEffect as useEffect4, useCallback as useCallback5 } from "react";
1630
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1709
+ import { useState as useState6, useRef as useRef4, useEffect as useEffect5, useCallback as useCallback6 } from "react";
1710
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1631
1711
  var PANEL_WIDTH = 220;
1632
1712
  function Status({ onReset, position, onClose }) {
1633
1713
  const panelRef = useRef4(null);
1634
- const [toast, setToast] = useState5(null);
1635
- const [pushing, setPushing] = useState5(false);
1636
- const showToast = useCallback5((message, type) => {
1714
+ const [toast, setToast] = useState6(null);
1715
+ const [pushing, setPushing] = useState6(false);
1716
+ const showToast = useCallback6((message, type) => {
1637
1717
  setToast({ message, type });
1638
1718
  setTimeout(() => setToast(null), 3e3);
1639
1719
  }, []);
1640
- useEffect4(() => {
1720
+ useEffect5(() => {
1641
1721
  const handler = (e) => {
1642
1722
  if (panelRef.current && !panelRef.current.contains(e.target)) {
1643
1723
  onClose();
@@ -1646,7 +1726,7 @@ function Status({ onReset, position, onClose }) {
1646
1726
  document.addEventListener("mousedown", handler);
1647
1727
  return () => document.removeEventListener("mousedown", handler);
1648
1728
  }, [onClose]);
1649
- useEffect4(() => {
1729
+ useEffect5(() => {
1650
1730
  const handler = (e) => {
1651
1731
  if (e.key === "Escape") onClose();
1652
1732
  };
@@ -1722,7 +1802,7 @@ function Status({ onReset, position, onClose }) {
1722
1802
  const onLeave = (e) => {
1723
1803
  e.currentTarget.style.background = "transparent";
1724
1804
  };
1725
- return /* @__PURE__ */ jsxs4(
1805
+ return /* @__PURE__ */ jsxs5(
1726
1806
  "div",
1727
1807
  {
1728
1808
  ref: panelRef,
@@ -1741,7 +1821,7 @@ function Status({ onReset, position, onClose }) {
1741
1821
  overflow: "hidden"
1742
1822
  },
1743
1823
  children: [
1744
- /* @__PURE__ */ jsx4(
1824
+ /* @__PURE__ */ jsx5(
1745
1825
  "div",
1746
1826
  {
1747
1827
  style: {
@@ -1754,8 +1834,8 @@ function Status({ onReset, position, onClose }) {
1754
1834
  children: "Before & After captured"
1755
1835
  }
1756
1836
  ),
1757
- /* @__PURE__ */ jsxs4("div", { style: { padding: "0 4px 4px" }, children: [
1758
- /* @__PURE__ */ jsxs4(
1837
+ /* @__PURE__ */ jsxs5("div", { style: { padding: "0 4px 4px" }, children: [
1838
+ /* @__PURE__ */ jsxs5(
1759
1839
  "button",
1760
1840
  {
1761
1841
  style: buttonStyle,
@@ -1763,12 +1843,12 @@ function Status({ onReset, position, onClose }) {
1763
1843
  onMouseEnter: onEnter,
1764
1844
  onMouseLeave: onLeave,
1765
1845
  children: [
1766
- /* @__PURE__ */ jsx4(FolderIcon, {}),
1846
+ /* @__PURE__ */ jsx5(FolderIcon, {}),
1767
1847
  "Open Folder"
1768
1848
  ]
1769
1849
  }
1770
1850
  ),
1771
- /* @__PURE__ */ jsxs4(
1851
+ /* @__PURE__ */ jsxs5(
1772
1852
  "button",
1773
1853
  {
1774
1854
  style: buttonStyle,
@@ -1776,12 +1856,12 @@ function Status({ onReset, position, onClose }) {
1776
1856
  onMouseEnter: onEnter,
1777
1857
  onMouseLeave: onLeave,
1778
1858
  children: [
1779
- /* @__PURE__ */ jsx4(CopyIcon, {}),
1859
+ /* @__PURE__ */ jsx5(CopyIcon, {}),
1780
1860
  "Copy Markdown"
1781
1861
  ]
1782
1862
  }
1783
1863
  ),
1784
- /* @__PURE__ */ jsxs4(
1864
+ /* @__PURE__ */ jsxs5(
1785
1865
  "button",
1786
1866
  {
1787
1867
  style: buttonStyle,
@@ -1790,12 +1870,12 @@ function Status({ onReset, position, onClose }) {
1790
1870
  onMouseEnter: onEnter,
1791
1871
  onMouseLeave: onLeave,
1792
1872
  children: [
1793
- /* @__PURE__ */ jsx4(PushIcon, {}),
1873
+ /* @__PURE__ */ jsx5(PushIcon, {}),
1794
1874
  pushing ? "Pushing..." : "Push to PR"
1795
1875
  ]
1796
1876
  }
1797
1877
  ),
1798
- /* @__PURE__ */ jsx4(
1878
+ /* @__PURE__ */ jsx5(
1799
1879
  "div",
1800
1880
  {
1801
1881
  style: {
@@ -1805,7 +1885,7 @@ function Status({ onReset, position, onClose }) {
1805
1885
  }
1806
1886
  }
1807
1887
  ),
1808
- /* @__PURE__ */ jsxs4(
1888
+ /* @__PURE__ */ jsxs5(
1809
1889
  "button",
1810
1890
  {
1811
1891
  style: { ...buttonStyle, color: "rgba(255,255,255,0.5)" },
@@ -1813,13 +1893,13 @@ function Status({ onReset, position, onClose }) {
1813
1893
  onMouseEnter: onEnter,
1814
1894
  onMouseLeave: onLeave,
1815
1895
  children: [
1816
- /* @__PURE__ */ jsx4(ResetIcon, {}),
1896
+ /* @__PURE__ */ jsx5(ResetIcon, {}),
1817
1897
  "Reset"
1818
1898
  ]
1819
1899
  }
1820
1900
  )
1821
1901
  ] }),
1822
- toast && /* @__PURE__ */ jsx4(
1902
+ toast && /* @__PURE__ */ jsx5(
1823
1903
  "div",
1824
1904
  {
1825
1905
  style: {
@@ -1845,14 +1925,14 @@ function Status({ onReset, position, onClose }) {
1845
1925
  );
1846
1926
  }
1847
1927
  function FolderIcon() {
1848
- return /* @__PURE__ */ jsx4(
1928
+ return /* @__PURE__ */ jsx5(
1849
1929
  "svg",
1850
1930
  {
1851
1931
  width: "14",
1852
1932
  height: "14",
1853
1933
  viewBox: "0 0 14 14",
1854
1934
  style: { color: "rgba(255,255,255,0.5)" },
1855
- children: /* @__PURE__ */ jsx4(
1935
+ children: /* @__PURE__ */ jsx5(
1856
1936
  "path",
1857
1937
  {
1858
1938
  d: "M1.5 3A1.5 1.5 0 013 1.5h2.38a1 1 0 01.72.3L7 2.72a1 1 0 00.72.3H11A1.5 1.5 0 0112.5 4.5v6A1.5 1.5 0 0111 12H3A1.5 1.5 0 011.5 10.5V3z",
@@ -1865,7 +1945,7 @@ function FolderIcon() {
1865
1945
  );
1866
1946
  }
1867
1947
  function CopyIcon() {
1868
- return /* @__PURE__ */ jsxs4(
1948
+ return /* @__PURE__ */ jsxs5(
1869
1949
  "svg",
1870
1950
  {
1871
1951
  width: "14",
@@ -1873,7 +1953,7 @@ function CopyIcon() {
1873
1953
  viewBox: "0 0 14 14",
1874
1954
  style: { color: "rgba(255,255,255,0.5)" },
1875
1955
  children: [
1876
- /* @__PURE__ */ jsx4(
1956
+ /* @__PURE__ */ jsx5(
1877
1957
  "rect",
1878
1958
  {
1879
1959
  x: "4",
@@ -1886,7 +1966,7 @@ function CopyIcon() {
1886
1966
  strokeWidth: "1.3"
1887
1967
  }
1888
1968
  ),
1889
- /* @__PURE__ */ jsx4(
1969
+ /* @__PURE__ */ jsx5(
1890
1970
  "path",
1891
1971
  {
1892
1972
  d: "M10 4V2.5A1.5 1.5 0 008.5 1h-6A1.5 1.5 0 001 2.5v6A1.5 1.5 0 002.5 10H4",
@@ -1900,14 +1980,14 @@ function CopyIcon() {
1900
1980
  );
1901
1981
  }
1902
1982
  function PushIcon() {
1903
- return /* @__PURE__ */ jsx4(
1983
+ return /* @__PURE__ */ jsx5(
1904
1984
  "svg",
1905
1985
  {
1906
1986
  width: "14",
1907
1987
  height: "14",
1908
1988
  viewBox: "0 0 14 14",
1909
1989
  style: { color: "rgba(255,255,255,0.5)" },
1910
- children: /* @__PURE__ */ jsx4(
1990
+ children: /* @__PURE__ */ jsx5(
1911
1991
  "path",
1912
1992
  {
1913
1993
  d: "M7 11V3m0 0L4 6m3-3l3 3",
@@ -1922,7 +2002,7 @@ function PushIcon() {
1922
2002
  );
1923
2003
  }
1924
2004
  function ResetIcon() {
1925
- return /* @__PURE__ */ jsxs4(
2005
+ return /* @__PURE__ */ jsxs5(
1926
2006
  "svg",
1927
2007
  {
1928
2008
  width: "14",
@@ -1930,7 +2010,7 @@ function ResetIcon() {
1930
2010
  viewBox: "0 0 14 14",
1931
2011
  style: { color: "rgba(255,255,255,0.4)" },
1932
2012
  children: [
1933
- /* @__PURE__ */ jsx4(
2013
+ /* @__PURE__ */ jsx5(
1934
2014
  "path",
1935
2015
  {
1936
2016
  d: "M2.5 7a4.5 4.5 0 118 2.5",
@@ -1940,7 +2020,7 @@ function ResetIcon() {
1940
2020
  strokeLinecap: "round"
1941
2021
  }
1942
2022
  ),
1943
- /* @__PURE__ */ jsx4(
2023
+ /* @__PURE__ */ jsx5(
1944
2024
  "path",
1945
2025
  {
1946
2026
  d: "M2.5 3v4h4",
@@ -1957,7 +2037,7 @@ function ResetIcon() {
1957
2037
  }
1958
2038
 
1959
2039
  // src/overlay/index.tsx
1960
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
2040
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1961
2041
  async function saveCapture(type, mode, dataUrl) {
1962
2042
  try {
1963
2043
  const res = await fetch("/__afterbefore/save", {
@@ -1975,12 +2055,13 @@ async function saveCapture(type, mode, dataUrl) {
1975
2055
  }
1976
2056
  function AfterBefore() {
1977
2057
  const { state, captureComplete, reset } = useOverlayState();
1978
- const [statusOpen, setStatusOpen] = useState6(false);
1979
- const [selectorActive, setSelectorActive] = useState6(false);
1980
- const [inspectorActive, setInspectorActive] = useState6(false);
1981
- const [loading, setLoading] = useState6(false);
2058
+ const [statusOpen, setStatusOpen] = useState7(false);
2059
+ const [toolbarActive, setToolbarActive] = useState7(false);
2060
+ const [selectorActive, setSelectorActive] = useState7(false);
2061
+ const [inspectorActive, setInspectorActive] = useState7(false);
2062
+ const [loading, setLoading] = useState7(false);
1982
2063
  const iconPos = useRef5({ x: 24, y: 0 });
1983
- useEffect5(() => {
2064
+ useEffect6(() => {
1984
2065
  if (state.phase === "ready") {
1985
2066
  const timer = setTimeout(() => {
1986
2067
  reset();
@@ -1989,22 +2070,24 @@ function AfterBefore() {
1989
2070
  return () => clearTimeout(timer);
1990
2071
  }
1991
2072
  }, [state.phase, reset]);
1992
- const handlePositionChange = useCallback6(
2073
+ const handlePositionChange = useCallback7(
1993
2074
  (pos) => {
1994
2075
  iconPos.current = pos;
1995
2076
  },
1996
2077
  []
1997
2078
  );
1998
- const handleIconClick = useCallback6(() => {
2079
+ const handleIconClick = useCallback7(() => {
1999
2080
  if (loading) return;
2000
2081
  if (state.phase === "ready") {
2001
2082
  setStatusOpen((prev) => !prev);
2002
2083
  } else {
2003
- setSelectorActive((prev) => !prev);
2084
+ setToolbarActive((prev) => !prev);
2085
+ setSelectorActive(false);
2086
+ setInspectorActive(false);
2004
2087
  setStatusOpen(false);
2005
2088
  }
2006
2089
  }, [state.phase, loading]);
2007
- const performCapture = useCallback6(
2090
+ const performCapture = useCallback7(
2008
2091
  async (mode, area, element) => {
2009
2092
  setLoading(true);
2010
2093
  try {
@@ -2024,47 +2107,53 @@ function AfterBefore() {
2024
2107
  },
2025
2108
  [state.phase, captureComplete]
2026
2109
  );
2027
- const handleViewportCapture = useCallback6(() => {
2028
- setSelectorActive(false);
2029
- performCapture("viewport");
2030
- }, [performCapture]);
2031
- const handleFullPageCapture = useCallback6(() => {
2032
- setSelectorActive(false);
2033
- performCapture("fullpage");
2034
- }, [performCapture]);
2035
- const handleComponentMode = useCallback6(() => {
2036
- setSelectorActive(false);
2037
- setInspectorActive(true);
2110
+ const handleToolbarCapture = useCallback7(
2111
+ (mode) => {
2112
+ setToolbarActive(false);
2113
+ if (mode === "area") {
2114
+ setSelectorActive(true);
2115
+ } else if (mode === "viewport") {
2116
+ performCapture("viewport");
2117
+ } else if (mode === "fullpage") {
2118
+ performCapture("fullpage");
2119
+ } else if (mode === "component") {
2120
+ setInspectorActive(true);
2121
+ }
2122
+ },
2123
+ [performCapture]
2124
+ );
2125
+ const handleToolbarCancel = useCallback7(() => {
2126
+ setToolbarActive(false);
2038
2127
  }, []);
2039
- const handleComponentSelect = useCallback6(
2128
+ const handleComponentSelect = useCallback7(
2040
2129
  (element) => {
2041
2130
  setInspectorActive(false);
2042
2131
  performCapture("component", void 0, element);
2043
2132
  },
2044
2133
  [performCapture]
2045
2134
  );
2046
- const handleComponentCancel = useCallback6(() => {
2135
+ const handleComponentCancel = useCallback7(() => {
2047
2136
  setInspectorActive(false);
2048
2137
  }, []);
2049
- const handleAreaSelect = useCallback6(
2138
+ const handleAreaSelect = useCallback7(
2050
2139
  (area) => {
2051
2140
  setSelectorActive(false);
2052
2141
  performCapture("area", area);
2053
2142
  },
2054
2143
  [performCapture]
2055
2144
  );
2056
- const handleAreaCancel = useCallback6(() => {
2145
+ const handleAreaCancel = useCallback7(() => {
2057
2146
  setSelectorActive(false);
2058
2147
  }, []);
2059
- const handleReset = useCallback6(() => {
2148
+ const handleReset = useCallback7(() => {
2060
2149
  reset();
2061
2150
  setStatusOpen(false);
2062
2151
  }, [reset]);
2063
- const handleStatusClose = useCallback6(() => {
2152
+ const handleStatusClose = useCallback7(() => {
2064
2153
  setStatusOpen(false);
2065
2154
  }, []);
2066
- return /* @__PURE__ */ jsxs5("div", { "data-afterbefore": "true", children: [
2067
- /* @__PURE__ */ jsx5(
2155
+ return /* @__PURE__ */ jsxs6("div", { "data-afterbefore": "true", children: [
2156
+ /* @__PURE__ */ jsx6(
2068
2157
  Icon,
2069
2158
  {
2070
2159
  phase: state.phase,
@@ -2073,18 +2162,16 @@ function AfterBefore() {
2073
2162
  onPositionChange: handlePositionChange
2074
2163
  }
2075
2164
  ),
2076
- selectorActive && /* @__PURE__ */ jsx5(
2165
+ toolbarActive && !selectorActive && !inspectorActive && /* @__PURE__ */ jsx6(Toolbar, { onCapture: handleToolbarCapture, onCancel: handleToolbarCancel }),
2166
+ selectorActive && /* @__PURE__ */ jsx6(
2077
2167
  Selector,
2078
2168
  {
2079
2169
  onSelect: handleAreaSelect,
2080
- onCancel: handleAreaCancel,
2081
- onViewport: handleViewportCapture,
2082
- onFullPage: handleFullPageCapture,
2083
- onComponent: handleComponentMode
2170
+ onCancel: handleAreaCancel
2084
2171
  }
2085
2172
  ),
2086
- inspectorActive && /* @__PURE__ */ jsx5(Inspector, { onSelect: handleComponentSelect, onCancel: handleComponentCancel }),
2087
- statusOpen && state.phase === "ready" && /* @__PURE__ */ jsx5(
2173
+ inspectorActive && /* @__PURE__ */ jsx6(Inspector, { onSelect: handleComponentSelect, onCancel: handleComponentCancel }),
2174
+ statusOpen && state.phase === "ready" && /* @__PURE__ */ jsx6(
2088
2175
  Status,
2089
2176
  {
2090
2177
  onReset: handleReset,