@ohhwells/bridge 0.1.52-next.132 → 0.1.52-next.133
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/README.md +12 -1
- package/dist/index.cjs +78 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +78 -27
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -194,12 +194,23 @@ For links whose **destination URL** is edited in the canvas, use a plain `<a>` w
|
|
|
194
194
|
</a>
|
|
195
195
|
```
|
|
196
196
|
|
|
197
|
+
Section / body CTAs use the same two-phase select + Edit-link toolbar with `data-ohw-role="button"` (preferred). `navbar-button` remains supported as an alias for nav header CTAs:
|
|
198
|
+
|
|
199
|
+
```tsx
|
|
200
|
+
<a href="/contact" data-ohw-href-key="hero-cta-href" data-ohw-role="button" data-ohw-drag-disabled="true">
|
|
201
|
+
<span data-ohw-editable="text" data-ohw-key="hero-cta-label">
|
|
202
|
+
Get started
|
|
203
|
+
</span>
|
|
204
|
+
</a>
|
|
205
|
+
```
|
|
206
|
+
|
|
197
207
|
| Attribute | Purpose |
|
|
198
208
|
|-----------|---------|
|
|
199
209
|
| `data-ohw-href-key` | Storage key for the link destination |
|
|
200
210
|
| `href` | Default URL for SSR / first paint |
|
|
201
211
|
| `data-ohw-key` + `data-ohw-editable` on inner span | Editable label text |
|
|
202
|
-
| `data-ohw-role="
|
|
212
|
+
| `data-ohw-role="button"` | Section CTA — two-phase select + link-action toolbar (no reorder/More) |
|
|
213
|
+
| `data-ohw-role="navbar-button"` | Alias of `button` for navbar / header CTAs |
|
|
203
214
|
|
|
204
215
|
The bridge persists and restores `href` values (including after React re-renders). No template-side wrapper component is required.
|
|
205
216
|
|
package/dist/index.cjs
CHANGED
|
@@ -84,6 +84,9 @@ function getStoredLinkHref(key) {
|
|
|
84
84
|
function clearStoredLinkHref(key) {
|
|
85
85
|
linkHrefStore.delete(key);
|
|
86
86
|
}
|
|
87
|
+
function listStoredLinkHrefs() {
|
|
88
|
+
return Array.from(linkHrefStore.entries());
|
|
89
|
+
}
|
|
87
90
|
function enforceLinkHrefs() {
|
|
88
91
|
document.querySelectorAll("[data-ohw-href-key]").forEach((el) => {
|
|
89
92
|
const key = el.getAttribute("data-ohw-href-key") ?? "";
|
|
@@ -5646,6 +5649,42 @@ function AiSectionOverlay({
|
|
|
5646
5649
|
var import_react_dom3 = require("react-dom");
|
|
5647
5650
|
var import_navigation2 = require("next/navigation");
|
|
5648
5651
|
|
|
5652
|
+
// src/lib/cta-button.ts
|
|
5653
|
+
function isCtaButton(el) {
|
|
5654
|
+
return Boolean(
|
|
5655
|
+
el.closest('[data-ohw-role="navbar-button"], [data-ohw-role="button"]')
|
|
5656
|
+
);
|
|
5657
|
+
}
|
|
5658
|
+
var CTA_BUTTON_SELECTOR = '[data-ohw-role="navbar-button"], [data-ohw-role="button"]';
|
|
5659
|
+
|
|
5660
|
+
// src/lib/media-overlay-guards.ts
|
|
5661
|
+
var BRIDGE_CHROME_SELECTOR = [
|
|
5662
|
+
"[data-ohw-toolbar]",
|
|
5663
|
+
"[data-ohw-item-toolbar-anchor]",
|
|
5664
|
+
"[data-ohw-drag-handle-container]",
|
|
5665
|
+
'[data-slot="drag-handle"]',
|
|
5666
|
+
"[data-ohw-more-menu]",
|
|
5667
|
+
'[data-slot="dropdown-menu-content"]'
|
|
5668
|
+
].join(", ");
|
|
5669
|
+
function containsPoint(el, x, y) {
|
|
5670
|
+
const r2 = el.getBoundingClientRect();
|
|
5671
|
+
if (r2.width <= 0 || r2.height <= 0) return false;
|
|
5672
|
+
return x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom;
|
|
5673
|
+
}
|
|
5674
|
+
function isPointOverBridgeChrome(x, y) {
|
|
5675
|
+
for (const el of document.querySelectorAll(BRIDGE_CHROME_SELECTOR)) {
|
|
5676
|
+
if (containsPoint(el, x, y)) return true;
|
|
5677
|
+
}
|
|
5678
|
+
return false;
|
|
5679
|
+
}
|
|
5680
|
+
function findCtaButtonAtPoint(x, y, media) {
|
|
5681
|
+
const hits = Array.from(
|
|
5682
|
+
document.querySelectorAll(CTA_BUTTON_SELECTOR)
|
|
5683
|
+
).filter((el) => containsPoint(el, x, y) && !(media && el.contains(media)));
|
|
5684
|
+
if (hits.length === 0) return null;
|
|
5685
|
+
return hits.reduce((best, el) => best.contains(el) ? el : best);
|
|
5686
|
+
}
|
|
5687
|
+
|
|
5649
5688
|
// src/lib/session-search.ts
|
|
5650
5689
|
var STORAGE_KEY = "ohw-preserved-search";
|
|
5651
5690
|
function readPreservedSearch() {
|
|
@@ -7239,12 +7278,9 @@ function getLinkHref(el) {
|
|
|
7239
7278
|
}
|
|
7240
7279
|
return el.getAttribute("href") ?? "";
|
|
7241
7280
|
}
|
|
7242
|
-
function isNavbarButton(el) {
|
|
7243
|
-
return el.hasAttribute("data-ohw-role") && el.getAttribute("data-ohw-role") === "navbar-button";
|
|
7244
|
-
}
|
|
7245
7281
|
function isNavbarLinkItem(el) {
|
|
7246
7282
|
if (!el.matches("[data-ohw-href-key]")) return false;
|
|
7247
|
-
if (
|
|
7283
|
+
if (isCtaButton(el)) return false;
|
|
7248
7284
|
if (!el.querySelector('[data-ohw-editable="text"]')) return false;
|
|
7249
7285
|
return Boolean(el.closest("nav, [data-ohw-nav-container], [data-ohw-nav-drawer]"));
|
|
7250
7286
|
}
|
|
@@ -7325,7 +7361,7 @@ function buildNavLink(index, href, label, template) {
|
|
|
7325
7361
|
}
|
|
7326
7362
|
function insertNavLinkInContainer(container, anchor, afterHrefKey) {
|
|
7327
7363
|
if (!afterHrefKey) {
|
|
7328
|
-
const cta = container.querySelector(
|
|
7364
|
+
const cta = container.querySelector(CTA_BUTTON_SELECTOR);
|
|
7329
7365
|
if (cta && cta.parentElement === container) {
|
|
7330
7366
|
container.insertBefore(anchor, cta);
|
|
7331
7367
|
return;
|
|
@@ -9316,8 +9352,7 @@ function useNavItemDrag({
|
|
|
9316
9352
|
setSiblingHintRects,
|
|
9317
9353
|
setToolbarRect,
|
|
9318
9354
|
getNavigationItemAnchor: getNavigationItemAnchor2,
|
|
9319
|
-
isDragHandleDisabled: isDragHandleDisabled2
|
|
9320
|
-
isNavbarButton: isNavbarButton3
|
|
9355
|
+
isDragHandleDisabled: isDragHandleDisabled2
|
|
9321
9356
|
}) {
|
|
9322
9357
|
const navDragRef = (0, import_react11.useRef)(null);
|
|
9323
9358
|
const [navDropSlots, setNavDropSlots] = (0, import_react11.useState)([]);
|
|
@@ -9464,7 +9499,7 @@ function useNavItemDrag({
|
|
|
9464
9499
|
if (footerDragRef.current) return false;
|
|
9465
9500
|
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
9466
9501
|
if (!hrefKey || !isNavbarHrefKey(hrefKey)) return false;
|
|
9467
|
-
if (
|
|
9502
|
+
if (isCtaButton(anchor) || isDragHandleDisabled2(anchor)) return false;
|
|
9468
9503
|
beginNavDrag({
|
|
9469
9504
|
hrefKey,
|
|
9470
9505
|
wasSelected,
|
|
@@ -9475,7 +9510,7 @@ function useNavItemDrag({
|
|
|
9475
9510
|
});
|
|
9476
9511
|
return true;
|
|
9477
9512
|
},
|
|
9478
|
-
[beginNavDrag, footerDragRef, isDragHandleDisabled2,
|
|
9513
|
+
[beginNavDrag, footerDragRef, isDragHandleDisabled2, isCtaButton]
|
|
9479
9514
|
);
|
|
9480
9515
|
const onNavDragOver = (0, import_react11.useCallback)(
|
|
9481
9516
|
(e) => {
|
|
@@ -9511,7 +9546,7 @@ function useNavItemDrag({
|
|
|
9511
9546
|
const anchor = getNavigationItemAnchor2(target);
|
|
9512
9547
|
const hrefKey = anchor?.getAttribute("data-ohw-href-key") ?? null;
|
|
9513
9548
|
if (!anchor || !isNavbarHrefKey(hrefKey)) return;
|
|
9514
|
-
if (
|
|
9549
|
+
if (isCtaButton(anchor) || isDragHandleDisabled2(anchor)) return;
|
|
9515
9550
|
navPointerDragRef.current = {
|
|
9516
9551
|
el: anchor,
|
|
9517
9552
|
startX: e.clientX,
|
|
@@ -9608,7 +9643,7 @@ function useNavItemDrag({
|
|
|
9608
9643
|
getNavigationItemAnchor2,
|
|
9609
9644
|
isDragHandleDisabled2,
|
|
9610
9645
|
isEditMode,
|
|
9611
|
-
|
|
9646
|
+
isCtaButton,
|
|
9612
9647
|
linkPopoverOpenRef,
|
|
9613
9648
|
selectedElRef,
|
|
9614
9649
|
setLinkPopover,
|
|
@@ -9618,7 +9653,7 @@ function useNavItemDrag({
|
|
|
9618
9653
|
(selected, clientX, clientY, pointerId) => {
|
|
9619
9654
|
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
9620
9655
|
if (!hrefKey || !isNavbarHrefKey(hrefKey)) return false;
|
|
9621
|
-
if (
|
|
9656
|
+
if (isCtaButton(selected) || isDragHandleDisabled2(selected)) return false;
|
|
9622
9657
|
navPointerDragRef.current = {
|
|
9623
9658
|
el: selected,
|
|
9624
9659
|
startX: clientX,
|
|
@@ -9629,7 +9664,7 @@ function useNavItemDrag({
|
|
|
9629
9664
|
};
|
|
9630
9665
|
return true;
|
|
9631
9666
|
},
|
|
9632
|
-
[isDragHandleDisabled2,
|
|
9667
|
+
[isDragHandleDisabled2, isCtaButton]
|
|
9633
9668
|
);
|
|
9634
9669
|
return {
|
|
9635
9670
|
navDragRef,
|
|
@@ -9831,7 +9866,10 @@ function collectEditableNodes(extraContent, root = document) {
|
|
|
9831
9866
|
if (!key) return;
|
|
9832
9867
|
nodes.push({ key, type: "link", text: getLinkHref3(el) });
|
|
9833
9868
|
});
|
|
9834
|
-
|
|
9869
|
+
for (const [key, href] of listStoredLinkHrefs()) {
|
|
9870
|
+
nodes.push({ key, type: "link", text: href });
|
|
9871
|
+
}
|
|
9872
|
+
if (extraContent) {
|
|
9835
9873
|
for (const key of [NAV_ORDER_KEY, FOOTER_ORDER_KEY, NAV_COUNT_KEY]) {
|
|
9836
9874
|
const text = extraContent[key];
|
|
9837
9875
|
if (typeof text === "string" && text.length > 0) {
|
|
@@ -10565,9 +10603,6 @@ function getHrefKeyFromElement(el) {
|
|
|
10565
10603
|
if (!key) return null;
|
|
10566
10604
|
return { anchor, key };
|
|
10567
10605
|
}
|
|
10568
|
-
function isNavbarButton2(el) {
|
|
10569
|
-
return Boolean(el.closest('[data-ohw-role="navbar-button"]'));
|
|
10570
|
-
}
|
|
10571
10606
|
function isNavDropdownPanelOpen(childrenRoot) {
|
|
10572
10607
|
if (childrenRoot.closest("[data-ohw-nav-drawer]")) return true;
|
|
10573
10608
|
const group = childrenRoot.closest("[data-ohw-nav-group]");
|
|
@@ -10620,7 +10655,7 @@ function listNavigationItems() {
|
|
|
10620
10655
|
).filter((el) => isNavigationItem2(el));
|
|
10621
10656
|
}
|
|
10622
10657
|
function getNavigationItemReorderState(anchor) {
|
|
10623
|
-
if (
|
|
10658
|
+
if (isCtaButton(anchor)) return { key: null, disabled: false };
|
|
10624
10659
|
return getReorderHandleStateFromAnchor(anchor);
|
|
10625
10660
|
}
|
|
10626
10661
|
function getReorderHandleState(el) {
|
|
@@ -10722,7 +10757,7 @@ function findHoveredNavOrFooterContainer(x, y) {
|
|
|
10722
10757
|
}
|
|
10723
10758
|
function isPointOverNavItem(container, x, y) {
|
|
10724
10759
|
return Array.from(container.querySelectorAll("[data-ohw-href-key]")).some((el) => {
|
|
10725
|
-
if (!isNavigationItem2(el) ||
|
|
10760
|
+
if (!isNavigationItem2(el) || isCtaButton(el)) return false;
|
|
10726
10761
|
if (!isNavItemPointerTarget(el)) return false;
|
|
10727
10762
|
const itemRect = el.getBoundingClientRect();
|
|
10728
10763
|
return x >= itemRect.left && x <= itemRect.right && y >= itemRect.top && y <= itemRect.bottom;
|
|
@@ -10736,7 +10771,7 @@ function isPointOverFooterColumn(x, y) {
|
|
|
10736
10771
|
}
|
|
10737
10772
|
function resolveNavContainerSelectionTarget(target, clientX, clientY) {
|
|
10738
10773
|
if (getNavigationItemAnchor(target)) return null;
|
|
10739
|
-
if (target.closest(
|
|
10774
|
+
if (target.closest(CTA_BUTTON_SELECTOR)) return null;
|
|
10740
10775
|
const plainLink = target.closest("a");
|
|
10741
10776
|
if (plainLink && !plainLink.hasAttribute("data-ohw-href-key") && !plainLink.closest("[data-ohw-nav-container]")) {
|
|
10742
10777
|
return null;
|
|
@@ -11543,8 +11578,7 @@ function OhhwellsBridge() {
|
|
|
11543
11578
|
setSiblingHintRects,
|
|
11544
11579
|
setToolbarRect,
|
|
11545
11580
|
getNavigationItemAnchor,
|
|
11546
|
-
isDragHandleDisabled
|
|
11547
|
-
isNavbarButton: isNavbarButton2
|
|
11581
|
+
isDragHandleDisabled
|
|
11548
11582
|
});
|
|
11549
11583
|
const bumpLinkPopoverGrace = () => {
|
|
11550
11584
|
linkPopoverGraceUntilRef.current = Date.now() + 350;
|
|
@@ -11804,7 +11838,7 @@ function OhhwellsBridge() {
|
|
|
11804
11838
|
selectedHrefKeyRef.current = navAnchor.getAttribute("data-ohw-href-key");
|
|
11805
11839
|
selectedFooterColAttrRef.current = null;
|
|
11806
11840
|
markSelected(navAnchor);
|
|
11807
|
-
setSelectedIsCta(
|
|
11841
|
+
setSelectedIsCta(isCtaButton(navAnchor));
|
|
11808
11842
|
const isDropdownTrigger = !isNestedNavChild(navAnchor) && (navItemHasDropdownChildren(navAnchor) || navItemOwnsDropdownPanel(navAnchor));
|
|
11809
11843
|
if (isNestedNavChild(navAnchor)) {
|
|
11810
11844
|
setNavGroupForceOpen(navAnchor, true);
|
|
@@ -12325,7 +12359,7 @@ function OhhwellsBridge() {
|
|
|
12325
12359
|
selectedHrefKeyRef.current = anchor.getAttribute("data-ohw-href-key");
|
|
12326
12360
|
selectedFooterColAttrRef.current = null;
|
|
12327
12361
|
markSelected(anchor);
|
|
12328
|
-
setSelectedIsCta(
|
|
12362
|
+
setSelectedIsCta(isCtaButton(anchor));
|
|
12329
12363
|
clearHrefKeyHover(anchor);
|
|
12330
12364
|
const isDropdownTrigger = !isNestedNavChild(anchor) && (navItemHasDropdownChildren(anchor) || navItemOwnsDropdownPanel(anchor));
|
|
12331
12365
|
if (isNestedNavChild(anchor)) {
|
|
@@ -13408,7 +13442,7 @@ function OhhwellsBridge() {
|
|
|
13408
13442
|
const navItemHit = Array.from(
|
|
13409
13443
|
container.querySelectorAll("[data-ohw-href-key]")
|
|
13410
13444
|
).filter((el) => {
|
|
13411
|
-
if (!isNavigationItem2(el) ||
|
|
13445
|
+
if (!isNavigationItem2(el) || isCtaButton(el)) return false;
|
|
13412
13446
|
if (!isNavItemPointerTarget(el)) return false;
|
|
13413
13447
|
const itemRect = el.getBoundingClientRect();
|
|
13414
13448
|
return x >= itemRect.left && x <= itemRect.right && y >= itemRect.top && y <= itemRect.bottom;
|
|
@@ -13550,6 +13584,22 @@ function OhhwellsBridge() {
|
|
|
13550
13584
|
}
|
|
13551
13585
|
return;
|
|
13552
13586
|
}
|
|
13587
|
+
if (!isDragOver && isPointOverBridgeChrome(x2, y2)) {
|
|
13588
|
+
dismissImageHover();
|
|
13589
|
+
return;
|
|
13590
|
+
}
|
|
13591
|
+
const ctaHit = isDragOver ? null : findCtaButtonAtPoint(x2, y2, imgEl);
|
|
13592
|
+
if (ctaHit) {
|
|
13593
|
+
dismissImageHover();
|
|
13594
|
+
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
13595
|
+
const selected = selectedElRef.current;
|
|
13596
|
+
if (selected !== ctaHit && !selected?.contains(ctaHit)) {
|
|
13597
|
+
clearHrefKeyHover(ctaHit);
|
|
13598
|
+
hoveredItemElRef.current = ctaHit;
|
|
13599
|
+
setHoveredItemRect(ctaHit.getBoundingClientRect());
|
|
13600
|
+
}
|
|
13601
|
+
return;
|
|
13602
|
+
}
|
|
13553
13603
|
const topEl = document.elementFromPoint(x2, y2);
|
|
13554
13604
|
if (topEl?.closest('[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"], [data-ohw-more-menu], [data-slot="dropdown-menu-content"], [data-slot="dropdown-menu-item"]')) {
|
|
13555
13605
|
if (hoveredImageRef.current) {
|
|
@@ -13673,7 +13723,7 @@ function OhhwellsBridge() {
|
|
|
13673
13723
|
const navLinkHit = Array.from(
|
|
13674
13724
|
document.querySelectorAll("nav [data-ohw-href-key], footer [data-ohw-href-key]")
|
|
13675
13725
|
).find((el) => {
|
|
13676
|
-
if (!isNavigationItem2(el) ||
|
|
13726
|
+
if (!isNavigationItem2(el) || isCtaButton(el)) return false;
|
|
13677
13727
|
if (!isNavItemPointerTarget(el)) return false;
|
|
13678
13728
|
const er = el.getBoundingClientRect();
|
|
13679
13729
|
return x2 >= er.left && x2 <= er.right && y2 >= er.top && y2 <= er.bottom;
|
|
@@ -14547,7 +14597,7 @@ function OhhwellsBridge() {
|
|
|
14547
14597
|
if (navRoot && navContainer) {
|
|
14548
14598
|
const rr = navRoot.getBoundingClientRect();
|
|
14549
14599
|
if (clientX >= rr.left && clientX <= rr.right && clientY >= rr.top && clientY <= rr.bottom && !isPointOverNavItem(navContainer, clientX, clientY)) {
|
|
14550
|
-
const book = navRoot.querySelector(
|
|
14600
|
+
const book = navRoot.querySelector(CTA_BUTTON_SELECTOR);
|
|
14551
14601
|
if (book) {
|
|
14552
14602
|
const br = book.getBoundingClientRect();
|
|
14553
14603
|
if (clientX >= br.left && clientX <= br.right && clientY >= br.top && clientY <= br.bottom) {
|
|
@@ -15145,6 +15195,7 @@ function OhhwellsBridge() {
|
|
|
15145
15195
|
return;
|
|
15146
15196
|
}
|
|
15147
15197
|
const { key } = session;
|
|
15198
|
+
setStoredLinkHref(key, target);
|
|
15148
15199
|
applyLinkByKey(key, target);
|
|
15149
15200
|
editContentRef.current = { ...editContentRef.current, [key]: target };
|
|
15150
15201
|
postToParent2({ type: "ow:change", nodes: [{ key, text: target }] });
|