@ohhwells/bridge 0.1.16 → 0.1.18

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
@@ -3433,8 +3433,30 @@ function isEditSessionActive() {
3433
3433
  return new URLSearchParams(q).get("mode") === "edit";
3434
3434
  }
3435
3435
 
3436
+ // src/ui/badge.tsx
3437
+ import { jsx as jsx3 } from "react/jsx-runtime";
3438
+ var badgeVariants = cva(
3439
+ "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
3440
+ {
3441
+ variants: {
3442
+ variant: {
3443
+ default: "border-transparent bg-primary text-primary-foreground",
3444
+ secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
3445
+ destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
3446
+ outline: "text-foreground"
3447
+ }
3448
+ },
3449
+ defaultVariants: {
3450
+ variant: "default"
3451
+ }
3452
+ }
3453
+ );
3454
+ function Badge({ className, variant, ...props }) {
3455
+ return /* @__PURE__ */ jsx3("div", { className: cn(badgeVariants({ variant }), className), ...props });
3456
+ }
3457
+
3436
3458
  // src/OhhwellsBridge.tsx
3437
- import { Fragment, jsx as jsx3, jsxs } from "react/jsx-runtime";
3459
+ import { Fragment, jsx as jsx4, jsxs } from "react/jsx-runtime";
3438
3460
  var PRIMARY = "#0885FE";
3439
3461
  var IMAGE_FADE_MS = 300;
3440
3462
  function runOpacityFade(el, onDone) {
@@ -3642,7 +3664,7 @@ var TOOLBAR_GROUPS = [
3642
3664
  ];
3643
3665
  function GlowFrame({ rect, elRef }) {
3644
3666
  const GAP = 6;
3645
- return /* @__PURE__ */ jsx3(
3667
+ return /* @__PURE__ */ jsx4(
3646
3668
  "div",
3647
3669
  {
3648
3670
  ref: elRef,
@@ -3693,7 +3715,7 @@ function FloatingToolbar({
3693
3715
  activeCommands
3694
3716
  }) {
3695
3717
  const { top, left, transform } = calcToolbarPos(rect, parentScroll);
3696
- return /* @__PURE__ */ jsx3(
3718
+ return /* @__PURE__ */ jsx4(
3697
3719
  "div",
3698
3720
  {
3699
3721
  ref: elRef,
@@ -3717,10 +3739,10 @@ function FloatingToolbar({
3717
3739
  whiteSpace: "nowrap"
3718
3740
  },
3719
3741
  children: TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs(React2.Fragment, { children: [
3720
- gi > 0 && /* @__PURE__ */ jsx3("span", { style: { display: "block", width: 1, height: 24, background: "#E7E5E4", flexShrink: 0 } }),
3742
+ gi > 0 && /* @__PURE__ */ jsx4("span", { style: { display: "block", width: 1, height: 24, background: "#E7E5E4", flexShrink: 0 } }),
3721
3743
  btns.map((btn) => {
3722
3744
  const isActive = activeCommands.has(btn.cmd);
3723
- return /* @__PURE__ */ jsx3(
3745
+ return /* @__PURE__ */ jsx4(
3724
3746
  "button",
3725
3747
  {
3726
3748
  title: btn.title,
@@ -3746,7 +3768,7 @@ function FloatingToolbar({
3746
3768
  flexShrink: 0,
3747
3769
  padding: 6
3748
3770
  },
3749
- children: /* @__PURE__ */ jsx3(
3771
+ children: /* @__PURE__ */ jsx4(
3750
3772
  "svg",
3751
3773
  {
3752
3774
  width: "16",
@@ -3779,7 +3801,7 @@ function StateToggle({
3779
3801
  states,
3780
3802
  onStateChange
3781
3803
  }) {
3782
- return /* @__PURE__ */ jsx3(
3804
+ return /* @__PURE__ */ jsx4(
3783
3805
  ToggleGroup,
3784
3806
  {
3785
3807
  "data-ohw-state-toggle": "",
@@ -3793,7 +3815,7 @@ function StateToggle({
3793
3815
  left: rect.right - 8,
3794
3816
  transform: "translateX(-100%)"
3795
3817
  },
3796
- children: states.map((state) => /* @__PURE__ */ jsx3(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
3818
+ children: states.map((state) => /* @__PURE__ */ jsx4(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
3797
3819
  }
3798
3820
  );
3799
3821
  }
@@ -3847,6 +3869,7 @@ function OhhwellsBridge() {
3847
3869
  const glowElRef = useRef(null);
3848
3870
  const hoveredImageRef = useRef(null);
3849
3871
  const hoveredImageHasTextOverlapRef = useRef(false);
3872
+ const hoveredGapRef = useRef(null);
3850
3873
  const imageUnhoverTimerRef = useRef(null);
3851
3874
  const imageShowTimerRef = useRef(null);
3852
3875
  const editStylesRef = useRef(null);
@@ -3862,6 +3885,7 @@ function OhhwellsBridge() {
3862
3885
  const [toggleState, setToggleState] = useState(null);
3863
3886
  const [maxBadge, setMaxBadge] = useState(null);
3864
3887
  const [activeCommands, setActiveCommands] = useState(/* @__PURE__ */ new Set());
3888
+ const [sectionGap, setSectionGap] = useState(null);
3865
3889
  useEffect(() => {
3866
3890
  const update = () => {
3867
3891
  const el = activeElRef.current;
@@ -3870,6 +3894,12 @@ function OhhwellsBridge() {
3870
3894
  if (!prev || !activeStateElRef.current) return prev;
3871
3895
  return { ...prev, rect: activeStateElRef.current.getBoundingClientRect() };
3872
3896
  });
3897
+ setSectionGap((prev) => {
3898
+ if (!prev) return prev;
3899
+ const anchor = document.querySelector(`[data-ohw-section="${prev.insertAfter}"]`);
3900
+ if (!anchor) return prev;
3901
+ return { ...prev, y: anchor.getBoundingClientRect().bottom };
3902
+ });
3873
3903
  };
3874
3904
  const vvp = window.visualViewport;
3875
3905
  if (!vvp) return;
@@ -4374,10 +4404,32 @@ function OhhwellsBridge() {
4374
4404
  }
4375
4405
  }
4376
4406
  };
4407
+ const probeSectionGapAt = (clientX, clientY, fromParentViewport = false) => {
4408
+ const { y } = toProbeCoords(clientX, clientY, fromParentViewport);
4409
+ const sections = Array.from(document.querySelectorAll("[data-ohw-section]")).sort((a, b) => a.getBoundingClientRect().top - b.getBoundingClientRect().top);
4410
+ const ZONE = 20;
4411
+ for (let i = 0; i < sections.length; i++) {
4412
+ const a = sections[i];
4413
+ const b = sections[i + 1] ?? null;
4414
+ const boundaryY = a.getBoundingClientRect().bottom;
4415
+ if (Math.abs(y - boundaryY) <= ZONE) {
4416
+ const insertAfter = a.dataset.ohwSection ?? "";
4417
+ const insertBefore = b?.dataset.ohwSection ?? null;
4418
+ hoveredGapRef.current = { insertAfter, insertBefore };
4419
+ setSectionGap({ insertAfter, insertBefore, y: boundaryY });
4420
+ return;
4421
+ }
4422
+ }
4423
+ if (hoveredGapRef.current) {
4424
+ hoveredGapRef.current = null;
4425
+ setSectionGap(null);
4426
+ }
4427
+ };
4377
4428
  const handleMouseMove = (e) => {
4378
4429
  const { clientX, clientY } = e;
4379
4430
  probeImageAt(clientX, clientY);
4380
4431
  probeHoverCardsAt(clientX, clientY);
4432
+ probeSectionGapAt(clientX, clientY);
4381
4433
  };
4382
4434
  const handlePointerSync = (e) => {
4383
4435
  if (e.data?.type !== "ow:pointer-sync") return;
@@ -4385,6 +4437,7 @@ function OhhwellsBridge() {
4385
4437
  if (typeof clientX !== "number" || typeof clientY !== "number") return;
4386
4438
  probeImageAt(clientX, clientY);
4387
4439
  probeHoverCardsAt(clientX, clientY);
4440
+ probeSectionGapAt(clientX, clientY);
4388
4441
  };
4389
4442
  const handleDragOver = (e) => {
4390
4443
  e.preventDefault();
@@ -4792,8 +4845,8 @@ function OhhwellsBridge() {
4792
4845
  return bridgeRoot ? createPortal(
4793
4846
  /* @__PURE__ */ jsxs(Fragment, { children: [
4794
4847
  toolbarRect && /* @__PURE__ */ jsxs(Fragment, { children: [
4795
- /* @__PURE__ */ jsx3(GlowFrame, { rect: toolbarRect, elRef: glowElRef }),
4796
- /* @__PURE__ */ jsx3(FloatingToolbar, { rect: toolbarRect, parentScroll: parentScrollRef.current, elRef: toolbarElRef, onCommand: handleCommand, activeCommands })
4848
+ /* @__PURE__ */ jsx4(GlowFrame, { rect: toolbarRect, elRef: glowElRef }),
4849
+ /* @__PURE__ */ jsx4(FloatingToolbar, { rect: toolbarRect, parentScroll: parentScrollRef.current, elRef: toolbarElRef, onCommand: handleCommand, activeCommands })
4797
4850
  ] }),
4798
4851
  maxBadge && /* @__PURE__ */ jsxs(
4799
4852
  "div",
@@ -4821,7 +4874,7 @@ function OhhwellsBridge() {
4821
4874
  ]
4822
4875
  }
4823
4876
  ),
4824
- toggleState && /* @__PURE__ */ jsx3(
4877
+ toggleState && /* @__PURE__ */ jsx4(
4825
4878
  StateToggle,
4826
4879
  {
4827
4880
  rect: toggleState.rect,
@@ -4829,6 +4882,31 @@ function OhhwellsBridge() {
4829
4882
  states: toggleState.states,
4830
4883
  onStateChange: handleStateChange
4831
4884
  }
4885
+ ),
4886
+ sectionGap && /* @__PURE__ */ jsxs(
4887
+ "div",
4888
+ {
4889
+ "data-ohw-section-insert-line": "",
4890
+ className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
4891
+ style: { top: sectionGap.y, transform: "translateY(-50%)" },
4892
+ children: [
4893
+ /* @__PURE__ */ jsx4("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
4894
+ /* @__PURE__ */ jsx4(
4895
+ Badge,
4896
+ {
4897
+ className: "px-8 py-1 bg-primary hover:bg-primary text-primary-foreground text-xs font-medium shrink-0 rounded-full cursor-pointer pointer-events-auto",
4898
+ onClick: () => {
4899
+ window.parent.postMessage(
4900
+ { type: "ow:add-section", insertAfter: sectionGap.insertAfter, insertBefore: sectionGap.insertBefore },
4901
+ "*"
4902
+ );
4903
+ },
4904
+ children: "Add Section"
4905
+ }
4906
+ ),
4907
+ /* @__PURE__ */ jsx4("div", { className: "flex-1 bg-primary", style: { height: 3 } })
4908
+ ]
4909
+ }
4832
4910
  )
4833
4911
  ] }),
4834
4912
  bridgeRoot