@ohhwells/bridge 0.1.56 → 0.1.58

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
@@ -6952,6 +6952,47 @@ function AiSectionOverlay({
6952
6952
  ] });
6953
6953
  }
6954
6954
 
6955
+ // src/lib/section-instances.ts
6956
+ var SECTION_ORDER_KEY = "__ohw_section_order";
6957
+ function getPageSectionOrderEntries(raw, currentPath) {
6958
+ if (!raw) return [];
6959
+ try {
6960
+ const entries = JSON.parse(raw);
6961
+ return entries.filter((e) => !e.pagePath || e.pagePath === currentPath);
6962
+ } catch {
6963
+ return [];
6964
+ }
6965
+ }
6966
+ function rekeySectionSubtree(root, instanceId) {
6967
+ const suffix = `::${instanceId}`;
6968
+ const rekey = (el, attr) => {
6969
+ const current = el.getAttribute(attr);
6970
+ if (current) el.setAttribute(attr, `${current}${suffix}`);
6971
+ };
6972
+ if (root.hasAttribute("data-ohw-key")) rekey(root, "data-ohw-key");
6973
+ if (root.hasAttribute("data-ohw-href-key")) rekey(root, "data-ohw-href-key");
6974
+ root.querySelectorAll("[data-ohw-key]").forEach((el) => rekey(el, "data-ohw-key"));
6975
+ root.querySelectorAll("[data-ohw-href-key]").forEach((el) => rekey(el, "data-ohw-href-key"));
6976
+ }
6977
+ function initSectionInstancesFromContent(content, currentPath) {
6978
+ document.querySelectorAll("[data-ohw-section]:not([data-ohw-instance])").forEach((el) => {
6979
+ el.setAttribute("data-ohw-instance", el.getAttribute("data-ohw-section") ?? "");
6980
+ });
6981
+ const entries = getPageSectionOrderEntries(content[SECTION_ORDER_KEY], currentPath);
6982
+ for (const entry of entries) {
6983
+ if (entry.instanceId === entry.type) continue;
6984
+ if (document.querySelector(`[data-ohw-instance="${CSS.escape(entry.instanceId)}"]`)) continue;
6985
+ const original = document.querySelector(
6986
+ `[data-ohw-section="${CSS.escape(entry.type)}"][data-ohw-instance="${CSS.escape(entry.type)}"]`
6987
+ );
6988
+ if (!original) continue;
6989
+ const clone = original.cloneNode(true);
6990
+ clone.setAttribute("data-ohw-instance", entry.instanceId);
6991
+ rekeySectionSubtree(clone, entry.instanceId);
6992
+ original.insertAdjacentElement("afterend", clone);
6993
+ }
6994
+ }
6995
+
6955
6996
  // src/OhhwellsBridge.tsx
6956
6997
  import { createPortal as createPortal2 } from "react-dom";
6957
6998
  import { usePathname as usePathname2, useRouter as useRouter3, useSearchParams } from "next/navigation";
@@ -6984,9 +7025,16 @@ function isPointOverBridgeChrome(x, y) {
6984
7025
  }
6985
7026
  return false;
6986
7027
  }
6987
- function findCtaButtonAtPoint(x, y, media) {
7028
+ var BUTTON_LIKE_SELECTOR = `button, [role="button"], ${CTA_BUTTON_SELECTOR}`;
7029
+ function isButtonLikeElement(el) {
7030
+ return el.matches(BUTTON_LIKE_SELECTOR);
7031
+ }
7032
+ function findClosestButtonLike(target) {
7033
+ return target.closest(BUTTON_LIKE_SELECTOR);
7034
+ }
7035
+ function findButtonAtPoint(x, y, media) {
6988
7036
  const hits = Array.from(
6989
- document.querySelectorAll(CTA_BUTTON_SELECTOR)
7037
+ document.querySelectorAll(BUTTON_LIKE_SELECTOR)
6990
7038
  ).filter((el) => containsPoint(el, x, y) && !(media && el.contains(media)));
6991
7039
  if (hits.length === 0) return null;
6992
7040
  return hits.reduce((best, el) => best.contains(el) ? el : best);
@@ -13508,6 +13556,8 @@ function OhhwellsBridge() {
13508
13556
  const [isFooterFrameSelection, setIsFooterFrameSelection] = useState11(false);
13509
13557
  isFooterFrameSelectionRef.current = isFooterFrameSelection;
13510
13558
  const [floatingPanel, setFloatingPanel] = useState11(null);
13559
+ const floatingPanelOpenRef = useRef9(false);
13560
+ floatingPanelOpenRef.current = floatingPanel !== null;
13511
13561
  const [floatingPanelPos, setFloatingPanelPos] = useState11(null);
13512
13562
  const [parentScrollSnap, setParentScrollSnap] = useState11(null);
13513
13563
  const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = useState11(null);
@@ -14533,6 +14583,8 @@ function OhhwellsBridge() {
14533
14583
  const closeFloatingPanelOnly = useCallback7(() => {
14534
14584
  setFloatingPanel(null);
14535
14585
  }, []);
14586
+ const closeFloatingPanelOnlyRef = useRef9(closeFloatingPanelOnly);
14587
+ closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
14536
14588
  const closeFloatingPanelAndDeselect = useCallback7(() => {
14537
14589
  setFloatingPanel(null);
14538
14590
  deselectRef.current();
@@ -14672,6 +14724,7 @@ function OhhwellsBridge() {
14672
14724
  applySocialsDisplayFromContent(content);
14673
14725
  enforceLinkHrefs();
14674
14726
  initSectionsFromContent(content, true);
14727
+ initSectionInstancesFromContent(content, window.location.pathname);
14675
14728
  sectionsLoadedRef.current = true;
14676
14729
  pendingScheduleConfigRequests.current.splice(0).forEach(processConfigRequest);
14677
14730
  return imageLoads.length > 0 ? Promise.all(imageLoads).then(() => {
@@ -14706,6 +14759,7 @@ function OhhwellsBridge() {
14706
14759
  const content = contentCache.get(subdomain);
14707
14760
  if (!content) return;
14708
14761
  retryMissingSchedulingMounts(getPageSchedulingEntries(content["__ohw_sections"]), false);
14762
+ initSectionInstancesFromContent(content, window.location.pathname);
14709
14763
  observer?.disconnect();
14710
14764
  try {
14711
14765
  for (const [key, val] of Object.entries(content)) {
@@ -15094,14 +15148,17 @@ function OhhwellsBridge() {
15094
15148
  });
15095
15149
  return;
15096
15150
  }
15097
- if (isMediaEditable(editable)) {
15151
+ const clickedButton = findClosestButtonLike(target);
15152
+ const buttonOnMedia = Boolean(clickedButton && isMediaEditable(editable) && editable.contains(clickedButton));
15153
+ if (isMediaEditable(editable) && !buttonOnMedia) {
15098
15154
  e.preventDefault();
15099
15155
  e.stopPropagation();
15100
15156
  aiSectionApiRef.current?.selectFromElement(editable);
15101
15157
  postToParentRef.current({ type: "ow:image-pick", key: editable.dataset.ohwKey ?? "", elementType: editable.dataset.ohwEditable ?? "image" });
15102
15158
  return;
15103
15159
  }
15104
- const hrefCtx = getHrefKeyFromElement(editable);
15160
+ const hrefLookupTarget = buttonOnMedia ? clickedButton : editable;
15161
+ const hrefCtx = getHrefKeyFromElement(hrefLookupTarget);
15105
15162
  const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
15106
15163
  if (navAnchor) {
15107
15164
  e.preventDefault();
@@ -15109,7 +15166,8 @@ function OhhwellsBridge() {
15109
15166
  if (selectedElRef.current === navAnchor) {
15110
15167
  if (e.detail >= 2) return;
15111
15168
  if (requestSocialDialog(navAnchor, postToParentRef.current, editContentRef.current)) return;
15112
- activateRef.current(editable, { caretX: e.clientX, caretY: e.clientY });
15169
+ const activateTarget = isButtonLikeElement(hrefLookupTarget) ? navAnchor.querySelector('[data-ohw-editable="text"]') ?? hrefLookupTarget : hrefLookupTarget;
15170
+ activateRef.current(activateTarget, { caretX: e.clientX, caretY: e.clientY });
15113
15171
  return;
15114
15172
  }
15115
15173
  selectRef.current(navAnchor);
@@ -15117,7 +15175,7 @@ function OhhwellsBridge() {
15117
15175
  }
15118
15176
  e.preventDefault();
15119
15177
  e.stopPropagation();
15120
- activateRef.current(editable, { caretX: e.clientX, caretY: e.clientY });
15178
+ activateRef.current(hrefLookupTarget, { caretX: e.clientX, caretY: e.clientY });
15121
15179
  return;
15122
15180
  }
15123
15181
  const hrefAnchor = getNavigationItemAnchor(target);
@@ -15647,15 +15705,15 @@ function OhhwellsBridge() {
15647
15705
  dismissImageHover();
15648
15706
  return;
15649
15707
  }
15650
- const ctaHit = isDragOver ? null : findCtaButtonAtPoint(x2, y2, imgEl);
15651
- if (ctaHit) {
15708
+ const buttonHit = isDragOver ? null : findButtonAtPoint(x2, y2, imgEl);
15709
+ if (buttonHit) {
15652
15710
  dismissImageHover();
15653
15711
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
15654
15712
  const selected = selectedElRef.current;
15655
- if (selected !== ctaHit && !selected?.contains(ctaHit)) {
15656
- clearHrefKeyHover(ctaHit);
15657
- hoveredItemElRef.current = ctaHit;
15658
- setHoveredItemRect(ctaHit.getBoundingClientRect());
15713
+ if (selected !== buttonHit && !selected?.contains(buttonHit)) {
15714
+ clearHrefKeyHover(buttonHit);
15715
+ hoveredItemElRef.current = buttonHit;
15716
+ setHoveredItemRect(buttonHit.getBoundingClientRect());
15659
15717
  }
15660
15718
  return;
15661
15719
  }
@@ -16185,6 +16243,7 @@ function OhhwellsBridge() {
16185
16243
  sectionsLoadedRef.current = true;
16186
16244
  pendingScheduleConfigRequests.current.splice(0).forEach(processConfigRequest);
16187
16245
  }
16246
+ initSectionInstancesFromContent(content, window.location.pathname);
16188
16247
  editContentRef.current = { ...editContentRef.current, ...content };
16189
16248
  reconcileNavbarItemsFromContent(editContentRef.current);
16190
16249
  reconcileFooterOrderFromContent(editContentRef.current);
@@ -16277,6 +16336,10 @@ function OhhwellsBridge() {
16277
16336
  closeLinkPopoverRef.current();
16278
16337
  return;
16279
16338
  }
16339
+ if (floatingPanelOpenRef.current) {
16340
+ closeFloatingPanelOnlyRef.current();
16341
+ return;
16342
+ }
16280
16343
  if (activeElRef.current) {
16281
16344
  const hrefCtx = getHrefKeyFromElement(activeElRef.current);
16282
16345
  const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
@@ -16340,6 +16403,11 @@ function OhhwellsBridge() {
16340
16403
  closeLinkPopoverRef.current();
16341
16404
  return;
16342
16405
  }
16406
+ if (e.key === "Escape" && floatingPanelOpenRef.current) {
16407
+ e.preventDefault();
16408
+ closeFloatingPanelOnlyRef.current();
16409
+ return;
16410
+ }
16343
16411
  if (e.key === "Escape" && selectedElRef.current && !activeElRef.current) {
16344
16412
  if (toolbarVariantRef.current === "select-frame") {
16345
16413
  const parent2 = getNavigationSelectionParent(selectedElRef.current);
@@ -17040,7 +17108,7 @@ function OhhwellsBridge() {
17040
17108
  postToParent2({
17041
17109
  type: "ow:ready",
17042
17110
  version: "1",
17043
- bridgeVersion: "0.1.55",
17111
+ bridgeVersion: "0.1.57",
17044
17112
  path: pathname,
17045
17113
  nodes: collectEditableNodes(editContentRef.current),
17046
17114
  sections