@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.cjs CHANGED
@@ -7025,6 +7025,47 @@ function AiSectionOverlay({
7025
7025
  ] });
7026
7026
  }
7027
7027
 
7028
+ // src/lib/section-instances.ts
7029
+ var SECTION_ORDER_KEY = "__ohw_section_order";
7030
+ function getPageSectionOrderEntries(raw, currentPath) {
7031
+ if (!raw) return [];
7032
+ try {
7033
+ const entries = JSON.parse(raw);
7034
+ return entries.filter((e) => !e.pagePath || e.pagePath === currentPath);
7035
+ } catch {
7036
+ return [];
7037
+ }
7038
+ }
7039
+ function rekeySectionSubtree(root, instanceId) {
7040
+ const suffix = `::${instanceId}`;
7041
+ const rekey = (el, attr) => {
7042
+ const current = el.getAttribute(attr);
7043
+ if (current) el.setAttribute(attr, `${current}${suffix}`);
7044
+ };
7045
+ if (root.hasAttribute("data-ohw-key")) rekey(root, "data-ohw-key");
7046
+ if (root.hasAttribute("data-ohw-href-key")) rekey(root, "data-ohw-href-key");
7047
+ root.querySelectorAll("[data-ohw-key]").forEach((el) => rekey(el, "data-ohw-key"));
7048
+ root.querySelectorAll("[data-ohw-href-key]").forEach((el) => rekey(el, "data-ohw-href-key"));
7049
+ }
7050
+ function initSectionInstancesFromContent(content, currentPath) {
7051
+ document.querySelectorAll("[data-ohw-section]:not([data-ohw-instance])").forEach((el) => {
7052
+ el.setAttribute("data-ohw-instance", el.getAttribute("data-ohw-section") ?? "");
7053
+ });
7054
+ const entries = getPageSectionOrderEntries(content[SECTION_ORDER_KEY], currentPath);
7055
+ for (const entry of entries) {
7056
+ if (entry.instanceId === entry.type) continue;
7057
+ if (document.querySelector(`[data-ohw-instance="${CSS.escape(entry.instanceId)}"]`)) continue;
7058
+ const original = document.querySelector(
7059
+ `[data-ohw-section="${CSS.escape(entry.type)}"][data-ohw-instance="${CSS.escape(entry.type)}"]`
7060
+ );
7061
+ if (!original) continue;
7062
+ const clone = original.cloneNode(true);
7063
+ clone.setAttribute("data-ohw-instance", entry.instanceId);
7064
+ rekeySectionSubtree(clone, entry.instanceId);
7065
+ original.insertAdjacentElement("afterend", clone);
7066
+ }
7067
+ }
7068
+
7028
7069
  // src/OhhwellsBridge.tsx
7029
7070
  var import_react_dom4 = require("react-dom");
7030
7071
  var import_navigation3 = require("next/navigation");
@@ -7057,9 +7098,16 @@ function isPointOverBridgeChrome(x, y) {
7057
7098
  }
7058
7099
  return false;
7059
7100
  }
7060
- function findCtaButtonAtPoint(x, y, media) {
7101
+ var BUTTON_LIKE_SELECTOR = `button, [role="button"], ${CTA_BUTTON_SELECTOR}`;
7102
+ function isButtonLikeElement(el) {
7103
+ return el.matches(BUTTON_LIKE_SELECTOR);
7104
+ }
7105
+ function findClosestButtonLike(target) {
7106
+ return target.closest(BUTTON_LIKE_SELECTOR);
7107
+ }
7108
+ function findButtonAtPoint(x, y, media) {
7061
7109
  const hits = Array.from(
7062
- document.querySelectorAll(CTA_BUTTON_SELECTOR)
7110
+ document.querySelectorAll(BUTTON_LIKE_SELECTOR)
7063
7111
  ).filter((el) => containsPoint(el, x, y) && !(media && el.contains(media)));
7064
7112
  if (hits.length === 0) return null;
7065
7113
  return hits.reduce((best, el) => best.contains(el) ? el : best);
@@ -13575,6 +13623,8 @@ function OhhwellsBridge() {
13575
13623
  const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react16.useState)(false);
13576
13624
  isFooterFrameSelectionRef.current = isFooterFrameSelection;
13577
13625
  const [floatingPanel, setFloatingPanel] = (0, import_react16.useState)(null);
13626
+ const floatingPanelOpenRef = (0, import_react16.useRef)(false);
13627
+ floatingPanelOpenRef.current = floatingPanel !== null;
13578
13628
  const [floatingPanelPos, setFloatingPanelPos] = (0, import_react16.useState)(null);
13579
13629
  const [parentScrollSnap, setParentScrollSnap] = (0, import_react16.useState)(null);
13580
13630
  const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react16.useState)(null);
@@ -14600,6 +14650,8 @@ function OhhwellsBridge() {
14600
14650
  const closeFloatingPanelOnly = (0, import_react16.useCallback)(() => {
14601
14651
  setFloatingPanel(null);
14602
14652
  }, []);
14653
+ const closeFloatingPanelOnlyRef = (0, import_react16.useRef)(closeFloatingPanelOnly);
14654
+ closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
14603
14655
  const closeFloatingPanelAndDeselect = (0, import_react16.useCallback)(() => {
14604
14656
  setFloatingPanel(null);
14605
14657
  deselectRef.current();
@@ -14739,6 +14791,7 @@ function OhhwellsBridge() {
14739
14791
  applySocialsDisplayFromContent(content);
14740
14792
  enforceLinkHrefs();
14741
14793
  initSectionsFromContent(content, true);
14794
+ initSectionInstancesFromContent(content, window.location.pathname);
14742
14795
  sectionsLoadedRef.current = true;
14743
14796
  pendingScheduleConfigRequests.current.splice(0).forEach(processConfigRequest);
14744
14797
  return imageLoads.length > 0 ? Promise.all(imageLoads).then(() => {
@@ -14773,6 +14826,7 @@ function OhhwellsBridge() {
14773
14826
  const content = contentCache.get(subdomain);
14774
14827
  if (!content) return;
14775
14828
  retryMissingSchedulingMounts(getPageSchedulingEntries(content["__ohw_sections"]), false);
14829
+ initSectionInstancesFromContent(content, window.location.pathname);
14776
14830
  observer?.disconnect();
14777
14831
  try {
14778
14832
  for (const [key, val] of Object.entries(content)) {
@@ -15161,14 +15215,17 @@ function OhhwellsBridge() {
15161
15215
  });
15162
15216
  return;
15163
15217
  }
15164
- if (isMediaEditable(editable)) {
15218
+ const clickedButton = findClosestButtonLike(target);
15219
+ const buttonOnMedia = Boolean(clickedButton && isMediaEditable(editable) && editable.contains(clickedButton));
15220
+ if (isMediaEditable(editable) && !buttonOnMedia) {
15165
15221
  e.preventDefault();
15166
15222
  e.stopPropagation();
15167
15223
  aiSectionApiRef.current?.selectFromElement(editable);
15168
15224
  postToParentRef.current({ type: "ow:image-pick", key: editable.dataset.ohwKey ?? "", elementType: editable.dataset.ohwEditable ?? "image" });
15169
15225
  return;
15170
15226
  }
15171
- const hrefCtx = getHrefKeyFromElement(editable);
15227
+ const hrefLookupTarget = buttonOnMedia ? clickedButton : editable;
15228
+ const hrefCtx = getHrefKeyFromElement(hrefLookupTarget);
15172
15229
  const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
15173
15230
  if (navAnchor) {
15174
15231
  e.preventDefault();
@@ -15176,7 +15233,8 @@ function OhhwellsBridge() {
15176
15233
  if (selectedElRef.current === navAnchor) {
15177
15234
  if (e.detail >= 2) return;
15178
15235
  if (requestSocialDialog(navAnchor, postToParentRef.current, editContentRef.current)) return;
15179
- activateRef.current(editable, { caretX: e.clientX, caretY: e.clientY });
15236
+ const activateTarget = isButtonLikeElement(hrefLookupTarget) ? navAnchor.querySelector('[data-ohw-editable="text"]') ?? hrefLookupTarget : hrefLookupTarget;
15237
+ activateRef.current(activateTarget, { caretX: e.clientX, caretY: e.clientY });
15180
15238
  return;
15181
15239
  }
15182
15240
  selectRef.current(navAnchor);
@@ -15184,7 +15242,7 @@ function OhhwellsBridge() {
15184
15242
  }
15185
15243
  e.preventDefault();
15186
15244
  e.stopPropagation();
15187
- activateRef.current(editable, { caretX: e.clientX, caretY: e.clientY });
15245
+ activateRef.current(hrefLookupTarget, { caretX: e.clientX, caretY: e.clientY });
15188
15246
  return;
15189
15247
  }
15190
15248
  const hrefAnchor = getNavigationItemAnchor(target);
@@ -15714,15 +15772,15 @@ function OhhwellsBridge() {
15714
15772
  dismissImageHover();
15715
15773
  return;
15716
15774
  }
15717
- const ctaHit = isDragOver ? null : findCtaButtonAtPoint(x2, y2, imgEl);
15718
- if (ctaHit) {
15775
+ const buttonHit = isDragOver ? null : findButtonAtPoint(x2, y2, imgEl);
15776
+ if (buttonHit) {
15719
15777
  dismissImageHover();
15720
15778
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
15721
15779
  const selected = selectedElRef.current;
15722
- if (selected !== ctaHit && !selected?.contains(ctaHit)) {
15723
- clearHrefKeyHover(ctaHit);
15724
- hoveredItemElRef.current = ctaHit;
15725
- setHoveredItemRect(ctaHit.getBoundingClientRect());
15780
+ if (selected !== buttonHit && !selected?.contains(buttonHit)) {
15781
+ clearHrefKeyHover(buttonHit);
15782
+ hoveredItemElRef.current = buttonHit;
15783
+ setHoveredItemRect(buttonHit.getBoundingClientRect());
15726
15784
  }
15727
15785
  return;
15728
15786
  }
@@ -16252,6 +16310,7 @@ function OhhwellsBridge() {
16252
16310
  sectionsLoadedRef.current = true;
16253
16311
  pendingScheduleConfigRequests.current.splice(0).forEach(processConfigRequest);
16254
16312
  }
16313
+ initSectionInstancesFromContent(content, window.location.pathname);
16255
16314
  editContentRef.current = { ...editContentRef.current, ...content };
16256
16315
  reconcileNavbarItemsFromContent(editContentRef.current);
16257
16316
  reconcileFooterOrderFromContent(editContentRef.current);
@@ -16344,6 +16403,10 @@ function OhhwellsBridge() {
16344
16403
  closeLinkPopoverRef.current();
16345
16404
  return;
16346
16405
  }
16406
+ if (floatingPanelOpenRef.current) {
16407
+ closeFloatingPanelOnlyRef.current();
16408
+ return;
16409
+ }
16347
16410
  if (activeElRef.current) {
16348
16411
  const hrefCtx = getHrefKeyFromElement(activeElRef.current);
16349
16412
  const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
@@ -16407,6 +16470,11 @@ function OhhwellsBridge() {
16407
16470
  closeLinkPopoverRef.current();
16408
16471
  return;
16409
16472
  }
16473
+ if (e.key === "Escape" && floatingPanelOpenRef.current) {
16474
+ e.preventDefault();
16475
+ closeFloatingPanelOnlyRef.current();
16476
+ return;
16477
+ }
16410
16478
  if (e.key === "Escape" && selectedElRef.current && !activeElRef.current) {
16411
16479
  if (toolbarVariantRef.current === "select-frame") {
16412
16480
  const parent2 = getNavigationSelectionParent(selectedElRef.current);
@@ -17107,7 +17175,7 @@ function OhhwellsBridge() {
17107
17175
  postToParent2({
17108
17176
  type: "ow:ready",
17109
17177
  version: "1",
17110
- bridgeVersion: "0.1.55",
17178
+ bridgeVersion: "0.1.57",
17111
17179
  path: pathname,
17112
17180
  nodes: collectEditableNodes(editContentRef.current),
17113
17181
  sections