@ohhwells/bridge 0.1.113-next.292 → 0.1.113-next.293

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.cjs CHANGED
@@ -722,8 +722,8 @@ function applyStylesToDom(store) {
722
722
  if (prop === "sectionBackground" && override.sectionBackgroundColor !== void 0) continue;
723
723
  section.setAttribute(attr, String(value).replace(":", "-"));
724
724
  }
725
- const bgOverride = isDrawerMarker ? override.navbarMobileBackground ?? override.sectionBackgroundColor : override.sectionBackgroundColor;
726
- const textOverride = isDrawerMarker ? override.navbarMobileTextColor ?? override.textColor : override.textColor;
725
+ const bgOverride = isDrawerMarker ? override.navbarMobileBackground : override.sectionBackgroundColor;
726
+ const textOverride = isDrawerMarker ? override.navbarMobileTextColor : override.textColor;
727
727
  const bgValue = isNavbar ? resolveNavbarValue(bgOverride) : bgOverride;
728
728
  const textValue = isNavbar ? resolveNavbarValue(textOverride) : textOverride;
729
729
  if (bgValue !== void 0) {
@@ -9284,6 +9284,57 @@ function useLiveSectionRect(sectionId) {
9284
9284
  }, [sectionId]);
9285
9285
  return rect;
9286
9286
  }
9287
+ var NAV_TOGGLE_LABEL_RE = /^(toggle menu|open menu|close menu)$/i;
9288
+ function readNavToggleRect() {
9289
+ const el = Array.from(document.querySelectorAll("button[aria-label]")).find(
9290
+ (e) => NAV_TOGGLE_LABEL_RE.test(e.getAttribute("aria-label") ?? "")
9291
+ );
9292
+ if (!el) return null;
9293
+ const r2 = el.getBoundingClientRect();
9294
+ if (r2.width <= 0 || r2.height <= 0) return null;
9295
+ return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
9296
+ }
9297
+ function useLiveNavToggleHole(active) {
9298
+ const [rect, setRect] = (0, import_react8.useState)(null);
9299
+ (0, import_react8.useEffect)(() => {
9300
+ if (!active) {
9301
+ setRect(null);
9302
+ return;
9303
+ }
9304
+ const update = () => {
9305
+ const next = readNavToggleRect();
9306
+ setRect(
9307
+ (prev) => prev && next && prev.top === next.top && prev.left === next.left && prev.width === next.width && prev.height === next.height ? prev : next
9308
+ );
9309
+ };
9310
+ update();
9311
+ const opts = { capture: true, passive: true };
9312
+ window.addEventListener("scroll", update, opts);
9313
+ window.addEventListener("resize", update);
9314
+ const interval = setInterval(update, 500);
9315
+ return () => {
9316
+ window.removeEventListener("scroll", update, opts);
9317
+ window.removeEventListener("resize", update);
9318
+ clearInterval(interval);
9319
+ };
9320
+ }, [active]);
9321
+ return rect;
9322
+ }
9323
+ function subtractRect(outer, hole) {
9324
+ if (!hole) return [outer];
9325
+ const l = Math.max(outer.left, hole.left);
9326
+ const t = Math.max(outer.top, hole.top);
9327
+ const r2 = Math.min(outer.left + outer.width, hole.left + hole.width);
9328
+ const b = Math.min(outer.top + outer.height, hole.top + hole.height);
9329
+ if (l >= r2 || t >= b) return [outer];
9330
+ const rects = [];
9331
+ if (t > outer.top) rects.push({ left: outer.left, top: outer.top, width: outer.width, height: t - outer.top });
9332
+ const midHeight = b - t;
9333
+ if (l > outer.left) rects.push({ left: outer.left, top: t, width: l - outer.left, height: midHeight });
9334
+ if (r2 < outer.left + outer.width) rects.push({ left: r2, top: t, width: outer.left + outer.width - r2, height: midHeight });
9335
+ if (b < outer.top + outer.height) rects.push({ left: outer.left, top: b, width: outer.width, height: outer.top + outer.height - b });
9336
+ return rects;
9337
+ }
9287
9338
  function computeSectionBoundaryFlags(instanceId) {
9288
9339
  const topLevel = topLevelSections();
9289
9340
  const index = topLevel.findIndex((el) => instanceIdOf(el) === instanceId);
@@ -9499,6 +9550,7 @@ function AiSectionOverlay({
9499
9550
  const activeSelectionId = reviewId ? null : selectedId;
9500
9551
  const selectionRect = useLiveSectionRect(activeSelectionId);
9501
9552
  const reviewRect = useLiveSectionRect(reviewId);
9553
+ const navToggleHole = useLiveNavToggleHole(Boolean(reviewId));
9502
9554
  const hoverRect = useLiveSectionRect(reviewId || hoveredId === selectedId ? null : hoveredId);
9503
9555
  const showSelectionBorder = Boolean(selectionRect) && !navDropdownForceOpen;
9504
9556
  (0, import_react8.useEffect)(() => {
@@ -9558,48 +9610,65 @@ function AiSectionOverlay({
9558
9610
  }
9559
9611
  }
9560
9612
  ),
9561
- reviewRect && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
9562
- "div",
9563
- {
9564
- "data-ohw-ai-review": "",
9565
- style: {
9566
- position: "fixed",
9567
- top: reviewRect.top,
9568
- left: reviewRect.left,
9569
- width: reviewRect.width,
9570
- height: reviewRect.height,
9571
- border: `2px solid ${PRIMARY2}`,
9572
- borderRadius: edgeAwareRadius(reviewRect),
9573
- zIndex: 2147483200,
9574
- // The veil itself: swallows clicks so the section stays locked until decided. This
9575
- // stopPropagation only guards the bubble phase; the bridge's capture-phase click
9576
- // handlers additionally bail on `[data-ohw-ai-review]`, without which a click on
9577
- // Accept/Discard resolves to the media beneath and opens the file picker.
9578
- background: "rgba(8, 133, 254, 0.04)",
9579
- pointerEvents: "auto",
9580
- cursor: "default"
9613
+ reviewRect && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
9614
+ subtractRect(reviewRect, navToggleHole).map((r2, i) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
9615
+ "div",
9616
+ {
9617
+ "data-ohw-ai-review": "",
9618
+ "aria-hidden": true,
9619
+ style: {
9620
+ position: "fixed",
9621
+ top: r2.top,
9622
+ left: r2.left,
9623
+ width: r2.width,
9624
+ height: r2.height,
9625
+ background: "rgba(8, 133, 254, 0.04)",
9626
+ pointerEvents: "auto",
9627
+ cursor: "default",
9628
+ zIndex: 2147483200
9629
+ },
9630
+ onClick: (e) => e.stopPropagation()
9581
9631
  },
9582
- onClick: (e) => e.stopPropagation(),
9583
- children: !reviewButtonsHidden && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
9584
- "div",
9585
- {
9586
- style: {
9587
- position: "sticky",
9588
- top: 12,
9589
- display: "flex",
9590
- gap: 8,
9591
- justifyContent: "flex-end",
9592
- paddingRight: 12,
9593
- paddingTop: 12
9594
- },
9595
- children: [
9596
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ReviewButton, { label: "Accept", onClick: () => decide("accept"), background: PRIMARY2, color: "#ffffff", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.Check, { size: 16, strokeWidth: 2.5, "aria-hidden": true }) }),
9597
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ReviewButton, { label: "Discard", onClick: () => decide("discard"), background: "#EFF6FF", color: "#0c0a09", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.X, { size: 16, strokeWidth: 2, "aria-hidden": true }) })
9598
- ]
9632
+ i
9633
+ )),
9634
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
9635
+ "div",
9636
+ {
9637
+ "aria-hidden": true,
9638
+ style: {
9639
+ position: "fixed",
9640
+ top: reviewRect.top,
9641
+ left: reviewRect.left,
9642
+ width: reviewRect.width,
9643
+ height: reviewRect.height,
9644
+ border: `2px solid ${PRIMARY2}`,
9645
+ borderRadius: edgeAwareRadius(reviewRect),
9646
+ pointerEvents: "none",
9647
+ zIndex: 2147483200
9599
9648
  }
9600
- )
9601
- }
9602
- )
9649
+ }
9650
+ ),
9651
+ !reviewButtonsHidden && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
9652
+ "div",
9653
+ {
9654
+ style: {
9655
+ position: "fixed",
9656
+ top: reviewRect.top + 12,
9657
+ left: reviewRect.left,
9658
+ width: reviewRect.width,
9659
+ display: "flex",
9660
+ gap: 8,
9661
+ justifyContent: "flex-end",
9662
+ paddingRight: 12,
9663
+ zIndex: 2147483201
9664
+ },
9665
+ children: [
9666
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ReviewButton, { label: "Accept", onClick: () => decide("accept"), background: PRIMARY2, color: "#ffffff", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.Check, { size: 16, strokeWidth: 2.5, "aria-hidden": true }) }),
9667
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ReviewButton, { label: "Discard", onClick: () => decide("discard"), background: "#EFF6FF", color: "#0c0a09", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.X, { size: 16, strokeWidth: 2, "aria-hidden": true }) })
9668
+ ]
9669
+ }
9670
+ )
9671
+ ] })
9603
9672
  ] });
9604
9673
  }
9605
9674
 
@@ -11262,6 +11331,15 @@ function getNavbarDesktopContainer() {
11262
11331
  function getNavbarDrawerContainer() {
11263
11332
  return document.querySelector("[data-ohw-nav-drawer]");
11264
11333
  }
11334
+ function isNavDrawerOpen() {
11335
+ return document.querySelector('[data-ohw-nav-drawer][data-ohw-section="navbar"]') !== null;
11336
+ }
11337
+ function isPointOutsideOpenDrawer(clientX, clientY) {
11338
+ const drawer = document.querySelector('[data-ohw-nav-drawer][data-ohw-section="navbar"]');
11339
+ if (!drawer) return false;
11340
+ const r2 = drawer.getBoundingClientRect();
11341
+ return clientX < r2.left || clientX > r2.right || clientY < r2.top || clientY > r2.bottom;
11342
+ }
11265
11343
  function isNavbarListContainerVisible(el) {
11266
11344
  if (el.hasAttribute("hidden")) return false;
11267
11345
  if (el.closest("[hidden]")) return false;
@@ -20462,6 +20540,19 @@ function OhhwellsBridge() {
20462
20540
  const handleMouseOver = (e) => {
20463
20541
  if (document.documentElement.hasAttribute("data-ohw-section-picking")) return;
20464
20542
  const target = e.target;
20543
+ if (isNavDrawerOpen() && isPointOutsideOpenDrawer(e.clientX, e.clientY)) {
20544
+ document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
20545
+ hoveredItemElRef.current = null;
20546
+ setHoveredItemRect(null);
20547
+ hoveredNavContainerRef.current = null;
20548
+ setHoveredNavContainerRect(null);
20549
+ formHoverElRef.current = null;
20550
+ setFormHoverRect(null);
20551
+ siblingHintElRef.current = null;
20552
+ setSiblingHintRect(null);
20553
+ setSiblingHintRects([]);
20554
+ return;
20555
+ }
20465
20556
  if (linkPopoverOpenRef.current) {
20466
20557
  hoveredItemElRef.current = null;
20467
20558
  setHoveredItemRect(null);
@@ -21279,7 +21370,32 @@ function OhhwellsBridge() {
21279
21370
  };
21280
21371
  const handleMouseMove = (e) => {
21281
21372
  const { clientX, clientY } = e;
21282
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || isOverEditorChrome(clientX, clientY)) {
21373
+ if (pointOwnedByFloatingPanel(clientX, clientY)) {
21374
+ dismissImageHover();
21375
+ clearImageHover();
21376
+ return;
21377
+ }
21378
+ if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) {
21379
+ document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
21380
+ formHoverElRef.current = null;
21381
+ setFormHoverRect(null);
21382
+ hoveredItemElRef.current = null;
21383
+ setHoveredItemRect(null);
21384
+ hoveredNavContainerRef.current = null;
21385
+ setHoveredNavContainerRect(null);
21386
+ dismissImageHover();
21387
+ if (hoveredGapRef.current) {
21388
+ hoveredGapRef.current = null;
21389
+ setSectionGap(null);
21390
+ }
21391
+ if (activeStateElRef.current) {
21392
+ activeStateElRef.current.removeAttribute("data-ohw-state-hovered");
21393
+ activeStateElRef.current = null;
21394
+ setToggleState(null);
21395
+ }
21396
+ return;
21397
+ }
21398
+ if (isOverEditorChrome(clientX, clientY)) {
21283
21399
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
21284
21400
  formHoverElRef.current = null;
21285
21401
  setFormHoverRect(null);
@@ -21304,11 +21420,12 @@ function OhhwellsBridge() {
21304
21420
  if (e.data?.type !== "ow:pointer-sync") return;
21305
21421
  const { clientX, clientY } = e.data;
21306
21422
  if (typeof clientX !== "number" || typeof clientY !== "number") return;
21307
- if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
21423
+ if (pointOwnedByFloatingPanel(clientX, clientY)) {
21308
21424
  dismissImageHover();
21309
21425
  clearImageHover();
21310
21426
  return;
21311
21427
  }
21428
+ if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) return;
21312
21429
  if (probeSocialsRowAt(clientX, clientY)) return;
21313
21430
  probeSectionGapAt(clientX, clientY);
21314
21431
  probeImageAt(clientX, clientY);