@ohhwells/bridge 0.1.116 → 0.1.117
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 +113 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +113 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -8898,6 +8898,7 @@ function MediaOverlay({
|
|
|
8898
8898
|
fadingOut = false,
|
|
8899
8899
|
selected = false,
|
|
8900
8900
|
hovered = false,
|
|
8901
|
+
cueOnly = false,
|
|
8901
8902
|
onFadeOutComplete,
|
|
8902
8903
|
onReplace,
|
|
8903
8904
|
onSelect,
|
|
@@ -8906,7 +8907,7 @@ function MediaOverlay({
|
|
|
8906
8907
|
const { rect } = hover;
|
|
8907
8908
|
const skeletonRef = React8.useRef(null);
|
|
8908
8909
|
const isVideo = hover.elementType === "video";
|
|
8909
|
-
const showChrome = !selected || hovered;
|
|
8910
|
+
const showChrome = (!selected || hovered) && !cueOnly;
|
|
8910
8911
|
const autoplay = hover.videoAutoplay ?? true;
|
|
8911
8912
|
const muted = hover.videoMuted ?? true;
|
|
8912
8913
|
const probeRef = React8.useRef(null);
|
|
@@ -9022,7 +9023,7 @@ function MediaOverlay({
|
|
|
9022
9023
|
// parent this needed a whole `ow:click-at` round-trip to re-hit-test inside the iframe;
|
|
9023
9024
|
// in-document, pointer-events does it natively. The button below opts back in, so
|
|
9024
9025
|
// Replace still works.
|
|
9025
|
-
pointerEvents: hover.hasTextOverlap ? "none" : "auto",
|
|
9026
|
+
pointerEvents: hover.hasTextOverlap || cueOnly ? "none" : "auto",
|
|
9026
9027
|
// Selected: a firm component ring with no wash, so the image reads as chosen rather
|
|
9027
9028
|
// than hovered. Hover keeps the existing tinted preview.
|
|
9028
9029
|
boxShadow: selected ? "inset 0 0 0 2px var(--color-bridge-primary)" : "inset 0 0 0 1.5px var(--color-bridge-primary)",
|
|
@@ -9053,7 +9054,7 @@ function MediaOverlay({
|
|
|
9053
9054
|
]
|
|
9054
9055
|
}
|
|
9055
9056
|
),
|
|
9056
|
-
replaceMode === "none" ? null : /* @__PURE__ */ jsxs7(
|
|
9057
|
+
replaceMode === "none" || cueOnly ? null : /* @__PURE__ */ jsxs7(
|
|
9057
9058
|
Button,
|
|
9058
9059
|
{
|
|
9059
9060
|
"data-ohw-media-overlay": "",
|
|
@@ -9073,7 +9074,7 @@ function MediaOverlay({
|
|
|
9073
9074
|
justifyContent: "center"
|
|
9074
9075
|
} : null,
|
|
9075
9076
|
// Don't let Replace steal clicks when text (e.g. nav) sits on top of this media.
|
|
9076
|
-
pointerEvents: hover.hasTextOverlap ? "none" : "auto"
|
|
9077
|
+
pointerEvents: hover.hasTextOverlap || cueOnly ? "none" : "auto"
|
|
9077
9078
|
},
|
|
9078
9079
|
onMouseDown: (e) => e.preventDefault(),
|
|
9079
9080
|
onClick: (e) => {
|
|
@@ -9103,7 +9104,8 @@ var OVERLAY_BUTTON_STYLE2 = {
|
|
|
9103
9104
|
};
|
|
9104
9105
|
function CarouselOverlay({
|
|
9105
9106
|
hover,
|
|
9106
|
-
onEdit
|
|
9107
|
+
onEdit,
|
|
9108
|
+
cueOnly = false
|
|
9107
9109
|
}) {
|
|
9108
9110
|
const { rect } = hover;
|
|
9109
9111
|
return /* @__PURE__ */ jsx16(
|
|
@@ -9119,12 +9121,12 @@ function CarouselOverlay({
|
|
|
9119
9121
|
width: rect.width,
|
|
9120
9122
|
height: rect.height,
|
|
9121
9123
|
zIndex: 2147483646,
|
|
9122
|
-
pointerEvents: "auto",
|
|
9124
|
+
pointerEvents: cueOnly ? "none" : "auto",
|
|
9123
9125
|
boxShadow: "inset 0 0 0 1.5px var(--color-bridge-primary)",
|
|
9124
9126
|
background: "color-mix(in srgb, var(--color-bridge-primary) 20%, transparent)"
|
|
9125
9127
|
},
|
|
9126
9128
|
onClick: () => onEdit(hover.key),
|
|
9127
|
-
children: /* @__PURE__ */ jsxs8(
|
|
9129
|
+
children: cueOnly ? null : /* @__PURE__ */ jsxs8(
|
|
9128
9130
|
Button,
|
|
9129
9131
|
{
|
|
9130
9132
|
"data-ohw-carousel-overlay": "",
|
|
@@ -9315,7 +9317,8 @@ function ReviewButton({
|
|
|
9315
9317
|
}
|
|
9316
9318
|
function AiSectionOverlay({
|
|
9317
9319
|
postToParent: postToParent2,
|
|
9318
|
-
apiRef
|
|
9320
|
+
apiRef,
|
|
9321
|
+
onSelectionChange
|
|
9319
9322
|
}) {
|
|
9320
9323
|
const [selectedId, setSelectedId] = useState6(null);
|
|
9321
9324
|
const [reviewId, setReviewId] = useState6(null);
|
|
@@ -9324,6 +9327,9 @@ function AiSectionOverlay({
|
|
|
9324
9327
|
reviewIdRef.current = reviewId;
|
|
9325
9328
|
const selectedIdRef = useRef4(null);
|
|
9326
9329
|
selectedIdRef.current = selectedId;
|
|
9330
|
+
useEffect4(() => {
|
|
9331
|
+
onSelectionChange?.(selectedId);
|
|
9332
|
+
}, [selectedId, onSelectionChange]);
|
|
9327
9333
|
const report = useCallback2(
|
|
9328
9334
|
(el) => {
|
|
9329
9335
|
const labelSrc = el ? sectionElementOf(el) : null;
|
|
@@ -9341,6 +9347,7 @@ function AiSectionOverlay({
|
|
|
9341
9347
|
const sectionEl = inner ? movableUnit(inner) : null;
|
|
9342
9348
|
const id = sectionEl ? instanceIdOf(sectionEl) || null : null;
|
|
9343
9349
|
if (id === selectedIdRef.current) return;
|
|
9350
|
+
selectedIdRef.current = id;
|
|
9344
9351
|
setSelectedId(id);
|
|
9345
9352
|
if (options?.report !== false) report(sectionEl);
|
|
9346
9353
|
},
|
|
@@ -9361,9 +9368,11 @@ function AiSectionOverlay({
|
|
|
9361
9368
|
return sectionEl != null;
|
|
9362
9369
|
},
|
|
9363
9370
|
clear: () => {
|
|
9371
|
+
selectedIdRef.current = null;
|
|
9364
9372
|
setSelectedId(null);
|
|
9365
9373
|
report(null);
|
|
9366
|
-
}
|
|
9374
|
+
},
|
|
9375
|
+
getSelectedId: () => selectedIdRef.current
|
|
9367
9376
|
};
|
|
9368
9377
|
return () => {
|
|
9369
9378
|
apiRef.current = null;
|
|
@@ -9372,6 +9381,7 @@ function AiSectionOverlay({
|
|
|
9372
9381
|
useEffect4(() => {
|
|
9373
9382
|
const onMessage = (e) => {
|
|
9374
9383
|
if (e.data?.type === "ow:ai-select" && e.data.sectionId === null) {
|
|
9384
|
+
selectedIdRef.current = null;
|
|
9375
9385
|
setSelectedId(null);
|
|
9376
9386
|
return;
|
|
9377
9387
|
}
|
|
@@ -9422,6 +9432,7 @@ function AiSectionOverlay({
|
|
|
9422
9432
|
if (reviewIdRef.current) return;
|
|
9423
9433
|
if (document.querySelector("[data-ohw-editing]")) return;
|
|
9424
9434
|
if (selectedIdRef.current) {
|
|
9435
|
+
selectedIdRef.current = null;
|
|
9425
9436
|
setSelectedId(null);
|
|
9426
9437
|
report(null);
|
|
9427
9438
|
}
|
|
@@ -16436,6 +16447,19 @@ function isMediaEditable(el) {
|
|
|
16436
16447
|
const t = el.dataset.ohwEditable;
|
|
16437
16448
|
return t === "image" || t === "bg-image" || t === "video";
|
|
16438
16449
|
}
|
|
16450
|
+
var FULL_BLEED_MIN_COVERAGE = 0.98;
|
|
16451
|
+
function fullBleedSectionIdOf(media) {
|
|
16452
|
+
const section = media.closest("[data-ohw-section]");
|
|
16453
|
+
if (!section) return null;
|
|
16454
|
+
const s = section.getBoundingClientRect();
|
|
16455
|
+
if (s.width <= 0 || s.height <= 0) return null;
|
|
16456
|
+
const m = media.getBoundingClientRect();
|
|
16457
|
+
const overlapX = Math.min(m.right, s.right) - Math.max(m.left, s.left);
|
|
16458
|
+
const overlapY = Math.min(m.bottom, s.bottom) - Math.max(m.top, s.top);
|
|
16459
|
+
if (overlapX <= 0 || overlapY <= 0) return null;
|
|
16460
|
+
if (overlapX * overlapY / (s.width * s.height) < FULL_BLEED_MIN_COVERAGE) return null;
|
|
16461
|
+
return instanceIdOf(movableUnit(section)) || null;
|
|
16462
|
+
}
|
|
16439
16463
|
function isIconMarkupValue(value) {
|
|
16440
16464
|
return /^\s*<(svg|img)\b/i.test(value);
|
|
16441
16465
|
}
|
|
@@ -17609,20 +17633,38 @@ function OhhwellsBridge() {
|
|
|
17609
17633
|
const hoveredImageHasTextOverlapRef = useRef10(false);
|
|
17610
17634
|
const dragOverElRef = useRef10(null);
|
|
17611
17635
|
const [mediaHover, setMediaHover] = useState14(null);
|
|
17636
|
+
const [selectedAiSectionId, setSelectedAiSectionId] = useState14(null);
|
|
17637
|
+
const selectedAiSectionIdRef = useRef10(null);
|
|
17638
|
+
const handleAiSectionSelectionChange = useCallback8((id) => {
|
|
17639
|
+
selectedAiSectionIdRef.current = id;
|
|
17640
|
+
setSelectedAiSectionId(id);
|
|
17641
|
+
}, []);
|
|
17612
17642
|
const [selectedMedia, setSelectedMedia] = useState14(null);
|
|
17613
17643
|
const selectedMediaElRef = useRef10(null);
|
|
17644
|
+
const mediaKeyDropTokenRef = useRef10(0);
|
|
17614
17645
|
const clearMediaSelection = useCallback8(() => {
|
|
17615
17646
|
const prev = selectedMediaElRef.current;
|
|
17616
17647
|
selectedMediaElRef.current = null;
|
|
17617
17648
|
setSelectedMedia(null);
|
|
17618
17649
|
const sectionEl = prev?.closest("[data-ohw-section]") ?? null;
|
|
17619
17650
|
if (sectionEl) {
|
|
17620
|
-
|
|
17621
|
-
|
|
17622
|
-
|
|
17623
|
-
|
|
17624
|
-
key
|
|
17625
|
-
|
|
17651
|
+
const sectionInstanceId = instanceIdOf(movableUnit(sectionEl)) || null;
|
|
17652
|
+
if (!sectionInstanceId) return;
|
|
17653
|
+
const token = ++mediaKeyDropTokenRef.current;
|
|
17654
|
+
const onQueueDrained = (e) => {
|
|
17655
|
+
if (e.source !== window || e.data?.type !== "ow:media-key-drop" || e.data.token !== token) return;
|
|
17656
|
+
window.removeEventListener("message", onQueueDrained);
|
|
17657
|
+
if (aiSectionApiRef.current?.getSelectedId() !== sectionInstanceId) return;
|
|
17658
|
+
if (selectedMediaElRef.current) return;
|
|
17659
|
+
postToParentRef.current({
|
|
17660
|
+
type: "ow:section-selected",
|
|
17661
|
+
sectionId: sectionEl.dataset.ohwSection ?? null,
|
|
17662
|
+
sectionLabel: sectionEl.dataset.ohwSectionLabel ?? titleCaseSectionId(sectionEl.dataset.ohwSection ?? ""),
|
|
17663
|
+
key: null
|
|
17664
|
+
});
|
|
17665
|
+
};
|
|
17666
|
+
window.addEventListener("message", onQueueDrained);
|
|
17667
|
+
window.postMessage({ type: "ow:media-key-drop", token }, "*");
|
|
17626
17668
|
}
|
|
17627
17669
|
}, []);
|
|
17628
17670
|
const clearMediaSelectionRef = useRef10(clearMediaSelection);
|
|
@@ -20064,6 +20106,23 @@ function OhhwellsBridge() {
|
|
|
20064
20106
|
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
20065
20107
|
clearMediaSelectionRef.current();
|
|
20066
20108
|
}
|
|
20109
|
+
if (selectedMediaElRef.current && target.closest("[data-ohw-media-overlay]") && !findClosestButtonLike(target)) {
|
|
20110
|
+
const hit = findImageAtPoint(e.clientX, e.clientY, false);
|
|
20111
|
+
if (hit && hit !== selectedMediaElRef.current) {
|
|
20112
|
+
e.preventDefault();
|
|
20113
|
+
e.stopPropagation();
|
|
20114
|
+
const fullBleedSectionId = fullBleedSectionIdOf(hit);
|
|
20115
|
+
if (fullBleedSectionId && fullBleedSectionId !== selectedAiSectionIdRef.current) {
|
|
20116
|
+
clearMediaSelectionRef.current();
|
|
20117
|
+
deselectRef.current();
|
|
20118
|
+
deactivateRef.current();
|
|
20119
|
+
aiSectionApiRef.current?.selectFromElement(hit);
|
|
20120
|
+
return;
|
|
20121
|
+
}
|
|
20122
|
+
selectMediaElementRef.current(hit);
|
|
20123
|
+
return;
|
|
20124
|
+
}
|
|
20125
|
+
}
|
|
20067
20126
|
if (isInsideFloatingPanel(target)) return;
|
|
20068
20127
|
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
20069
20128
|
if (target.closest(
|
|
@@ -20245,6 +20304,14 @@ function OhhwellsBridge() {
|
|
|
20245
20304
|
if (isMediaEditable(editable) && !buttonOnMedia) {
|
|
20246
20305
|
e.preventDefault();
|
|
20247
20306
|
e.stopPropagation();
|
|
20307
|
+
const fullBleedSectionId = fullBleedSectionIdOf(editable);
|
|
20308
|
+
if (fullBleedSectionId && fullBleedSectionId !== selectedAiSectionIdRef.current) {
|
|
20309
|
+
clearMediaSelectionRef.current();
|
|
20310
|
+
deselectRef.current();
|
|
20311
|
+
deactivateRef.current();
|
|
20312
|
+
aiSectionApiRef.current?.selectFromElement(editable);
|
|
20313
|
+
return;
|
|
20314
|
+
}
|
|
20248
20315
|
if (selectedMediaElRef.current === editable) {
|
|
20249
20316
|
postToParentRef.current({ type: "ow:image-pick", key: editable.dataset.ohwKey ?? "", elementType: editable.dataset.ohwEditable ?? "image" });
|
|
20250
20317
|
} else {
|
|
@@ -20699,6 +20766,7 @@ function OhhwellsBridge() {
|
|
|
20699
20766
|
elementType: imgEl.dataset.ohwEditable ?? "image",
|
|
20700
20767
|
hasTextOverlap,
|
|
20701
20768
|
isDragOver,
|
|
20769
|
+
fullBleedSectionId: fullBleedSectionIdOf(imgEl),
|
|
20702
20770
|
...video ? { videoAutoplay: video.autoplay, videoMuted: video.muted } : {}
|
|
20703
20771
|
});
|
|
20704
20772
|
const track = imgEl.closest("[data-ohw-hover-pause]");
|
|
@@ -20871,7 +20939,13 @@ function OhhwellsBridge() {
|
|
|
20871
20939
|
setHoveredItemRect(null);
|
|
20872
20940
|
}
|
|
20873
20941
|
};
|
|
20942
|
+
const syncSelectedMediaPointerRelease = (released) => {
|
|
20943
|
+
setSelectedMedia(
|
|
20944
|
+
(prev) => prev && prev.hasTextOverlap !== released ? { ...prev, hasTextOverlap: released } : prev
|
|
20945
|
+
);
|
|
20946
|
+
};
|
|
20874
20947
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
20948
|
+
syncSelectedMediaPointerRelease(true);
|
|
20875
20949
|
if (linkPopoverOpenRef.current) {
|
|
20876
20950
|
if (hoveredImageRef.current) {
|
|
20877
20951
|
hoveredImageRef.current = null;
|
|
@@ -21066,6 +21140,7 @@ function OhhwellsBridge() {
|
|
|
21066
21140
|
return;
|
|
21067
21141
|
}
|
|
21068
21142
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
21143
|
+
syncSelectedMediaPointerRelease(false);
|
|
21069
21144
|
if (imgEl !== hoveredImageRef.current || hoveredImageHasTextOverlapRef.current) {
|
|
21070
21145
|
hoveredImageRef.current = imgEl;
|
|
21071
21146
|
showImageHover(imgEl, isDragOver);
|
|
@@ -22539,7 +22614,11 @@ function OhhwellsBridge() {
|
|
|
22539
22614
|
if (!key) return;
|
|
22540
22615
|
const r2 = getVisibleRect(container);
|
|
22541
22616
|
setCarouselHover(
|
|
22542
|
-
(prev) => prev && prev.key === key && prev.rect.top === r2.top && prev.rect.left === r2.left && prev.rect.width === r2.width && prev.rect.height === r2.height ? prev : {
|
|
22617
|
+
(prev) => prev && prev.key === key && prev.rect.top === r2.top && prev.rect.left === r2.left && prev.rect.width === r2.width && prev.rect.height === r2.height ? prev : {
|
|
22618
|
+
key,
|
|
22619
|
+
rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height },
|
|
22620
|
+
fullBleedSectionId: fullBleedSectionIdOf(container)
|
|
22621
|
+
}
|
|
22543
22622
|
);
|
|
22544
22623
|
};
|
|
22545
22624
|
const applyToolbarPos = (rect) => {
|
|
@@ -23001,7 +23080,7 @@ function OhhwellsBridge() {
|
|
|
23001
23080
|
postToParent2({
|
|
23002
23081
|
type: "ow:ready",
|
|
23003
23082
|
version: "1",
|
|
23004
|
-
bridgeVersion: "0.1.
|
|
23083
|
+
bridgeVersion: "0.1.116",
|
|
23005
23084
|
path: pathname,
|
|
23006
23085
|
nodes: collectEditableNodes(editContentRef.current),
|
|
23007
23086
|
sections
|
|
@@ -23468,7 +23547,14 @@ function OhhwellsBridge() {
|
|
|
23468
23547
|
bridgeRoot ? createPortal3(
|
|
23469
23548
|
/* @__PURE__ */ jsxs20(Fragment8, { children: [
|
|
23470
23549
|
/* @__PURE__ */ jsx33("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
23471
|
-
isEditMode && /* @__PURE__ */ jsx33(
|
|
23550
|
+
isEditMode && /* @__PURE__ */ jsx33(
|
|
23551
|
+
AiSectionOverlay,
|
|
23552
|
+
{
|
|
23553
|
+
postToParent: postToParent2,
|
|
23554
|
+
apiRef: aiSectionApiRef,
|
|
23555
|
+
onSelectionChange: handleAiSectionSelectionChange
|
|
23556
|
+
}
|
|
23557
|
+
),
|
|
23472
23558
|
isSectionDragging && sectionDropSlots.map((slot, i) => /* @__PURE__ */ jsx33(
|
|
23473
23559
|
"div",
|
|
23474
23560
|
{
|
|
@@ -23501,6 +23587,7 @@ function OhhwellsBridge() {
|
|
|
23501
23587
|
{
|
|
23502
23588
|
hover: mediaHover,
|
|
23503
23589
|
isUploading: false,
|
|
23590
|
+
cueOnly: !mediaHover.isDragOver && !!mediaHover.fullBleedSectionId && mediaHover.fullBleedSectionId !== selectedAiSectionId,
|
|
23504
23591
|
onReplace: handleMediaReplace,
|
|
23505
23592
|
onSelect: handleMediaSelect,
|
|
23506
23593
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
@@ -23518,7 +23605,14 @@ function OhhwellsBridge() {
|
|
|
23518
23605
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
23519
23606
|
}
|
|
23520
23607
|
),
|
|
23521
|
-
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx33(
|
|
23608
|
+
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx33(
|
|
23609
|
+
CarouselOverlay,
|
|
23610
|
+
{
|
|
23611
|
+
hover: carouselHover,
|
|
23612
|
+
onEdit: handleEditCarousel,
|
|
23613
|
+
cueOnly: !!carouselHover.fullBleedSectionId && carouselHover.fullBleedSectionId !== selectedAiSectionId
|
|
23614
|
+
}
|
|
23615
|
+
),
|
|
23522
23616
|
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
23523
23617
|
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
|
|
23524
23618
|
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ jsx33(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
|