@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.cjs
CHANGED
|
@@ -8971,6 +8971,7 @@ function MediaOverlay({
|
|
|
8971
8971
|
fadingOut = false,
|
|
8972
8972
|
selected = false,
|
|
8973
8973
|
hovered = false,
|
|
8974
|
+
cueOnly = false,
|
|
8974
8975
|
onFadeOutComplete,
|
|
8975
8976
|
onReplace,
|
|
8976
8977
|
onSelect,
|
|
@@ -8979,7 +8980,7 @@ function MediaOverlay({
|
|
|
8979
8980
|
const { rect } = hover;
|
|
8980
8981
|
const skeletonRef = React8.useRef(null);
|
|
8981
8982
|
const isVideo = hover.elementType === "video";
|
|
8982
|
-
const showChrome = !selected || hovered;
|
|
8983
|
+
const showChrome = (!selected || hovered) && !cueOnly;
|
|
8983
8984
|
const autoplay = hover.videoAutoplay ?? true;
|
|
8984
8985
|
const muted = hover.videoMuted ?? true;
|
|
8985
8986
|
const probeRef = React8.useRef(null);
|
|
@@ -9095,7 +9096,7 @@ function MediaOverlay({
|
|
|
9095
9096
|
// parent this needed a whole `ow:click-at` round-trip to re-hit-test inside the iframe;
|
|
9096
9097
|
// in-document, pointer-events does it natively. The button below opts back in, so
|
|
9097
9098
|
// Replace still works.
|
|
9098
|
-
pointerEvents: hover.hasTextOverlap ? "none" : "auto",
|
|
9099
|
+
pointerEvents: hover.hasTextOverlap || cueOnly ? "none" : "auto",
|
|
9099
9100
|
// Selected: a firm component ring with no wash, so the image reads as chosen rather
|
|
9100
9101
|
// than hovered. Hover keeps the existing tinted preview.
|
|
9101
9102
|
boxShadow: selected ? "inset 0 0 0 2px var(--color-bridge-primary)" : "inset 0 0 0 1.5px var(--color-bridge-primary)",
|
|
@@ -9126,7 +9127,7 @@ function MediaOverlay({
|
|
|
9126
9127
|
]
|
|
9127
9128
|
}
|
|
9128
9129
|
),
|
|
9129
|
-
replaceMode === "none" ? null : /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
9130
|
+
replaceMode === "none" || cueOnly ? null : /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
9130
9131
|
Button,
|
|
9131
9132
|
{
|
|
9132
9133
|
"data-ohw-media-overlay": "",
|
|
@@ -9146,7 +9147,7 @@ function MediaOverlay({
|
|
|
9146
9147
|
justifyContent: "center"
|
|
9147
9148
|
} : null,
|
|
9148
9149
|
// Don't let Replace steal clicks when text (e.g. nav) sits on top of this media.
|
|
9149
|
-
pointerEvents: hover.hasTextOverlap ? "none" : "auto"
|
|
9150
|
+
pointerEvents: hover.hasTextOverlap || cueOnly ? "none" : "auto"
|
|
9150
9151
|
},
|
|
9151
9152
|
onMouseDown: (e) => e.preventDefault(),
|
|
9152
9153
|
onClick: (e) => {
|
|
@@ -9176,7 +9177,8 @@ var OVERLAY_BUTTON_STYLE2 = {
|
|
|
9176
9177
|
};
|
|
9177
9178
|
function CarouselOverlay({
|
|
9178
9179
|
hover,
|
|
9179
|
-
onEdit
|
|
9180
|
+
onEdit,
|
|
9181
|
+
cueOnly = false
|
|
9180
9182
|
}) {
|
|
9181
9183
|
const { rect } = hover;
|
|
9182
9184
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
@@ -9192,12 +9194,12 @@ function CarouselOverlay({
|
|
|
9192
9194
|
width: rect.width,
|
|
9193
9195
|
height: rect.height,
|
|
9194
9196
|
zIndex: 2147483646,
|
|
9195
|
-
pointerEvents: "auto",
|
|
9197
|
+
pointerEvents: cueOnly ? "none" : "auto",
|
|
9196
9198
|
boxShadow: "inset 0 0 0 1.5px var(--color-bridge-primary)",
|
|
9197
9199
|
background: "color-mix(in srgb, var(--color-bridge-primary) 20%, transparent)"
|
|
9198
9200
|
},
|
|
9199
9201
|
onClick: () => onEdit(hover.key),
|
|
9200
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
9202
|
+
children: cueOnly ? null : /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
9201
9203
|
Button,
|
|
9202
9204
|
{
|
|
9203
9205
|
"data-ohw-carousel-overlay": "",
|
|
@@ -9388,7 +9390,8 @@ function ReviewButton({
|
|
|
9388
9390
|
}
|
|
9389
9391
|
function AiSectionOverlay({
|
|
9390
9392
|
postToParent: postToParent2,
|
|
9391
|
-
apiRef
|
|
9393
|
+
apiRef,
|
|
9394
|
+
onSelectionChange
|
|
9392
9395
|
}) {
|
|
9393
9396
|
const [selectedId, setSelectedId] = (0, import_react8.useState)(null);
|
|
9394
9397
|
const [reviewId, setReviewId] = (0, import_react8.useState)(null);
|
|
@@ -9397,6 +9400,9 @@ function AiSectionOverlay({
|
|
|
9397
9400
|
reviewIdRef.current = reviewId;
|
|
9398
9401
|
const selectedIdRef = (0, import_react8.useRef)(null);
|
|
9399
9402
|
selectedIdRef.current = selectedId;
|
|
9403
|
+
(0, import_react8.useEffect)(() => {
|
|
9404
|
+
onSelectionChange?.(selectedId);
|
|
9405
|
+
}, [selectedId, onSelectionChange]);
|
|
9400
9406
|
const report = (0, import_react8.useCallback)(
|
|
9401
9407
|
(el) => {
|
|
9402
9408
|
const labelSrc = el ? sectionElementOf(el) : null;
|
|
@@ -9414,6 +9420,7 @@ function AiSectionOverlay({
|
|
|
9414
9420
|
const sectionEl = inner ? movableUnit(inner) : null;
|
|
9415
9421
|
const id = sectionEl ? instanceIdOf(sectionEl) || null : null;
|
|
9416
9422
|
if (id === selectedIdRef.current) return;
|
|
9423
|
+
selectedIdRef.current = id;
|
|
9417
9424
|
setSelectedId(id);
|
|
9418
9425
|
if (options?.report !== false) report(sectionEl);
|
|
9419
9426
|
},
|
|
@@ -9434,9 +9441,11 @@ function AiSectionOverlay({
|
|
|
9434
9441
|
return sectionEl != null;
|
|
9435
9442
|
},
|
|
9436
9443
|
clear: () => {
|
|
9444
|
+
selectedIdRef.current = null;
|
|
9437
9445
|
setSelectedId(null);
|
|
9438
9446
|
report(null);
|
|
9439
|
-
}
|
|
9447
|
+
},
|
|
9448
|
+
getSelectedId: () => selectedIdRef.current
|
|
9440
9449
|
};
|
|
9441
9450
|
return () => {
|
|
9442
9451
|
apiRef.current = null;
|
|
@@ -9445,6 +9454,7 @@ function AiSectionOverlay({
|
|
|
9445
9454
|
(0, import_react8.useEffect)(() => {
|
|
9446
9455
|
const onMessage = (e) => {
|
|
9447
9456
|
if (e.data?.type === "ow:ai-select" && e.data.sectionId === null) {
|
|
9457
|
+
selectedIdRef.current = null;
|
|
9448
9458
|
setSelectedId(null);
|
|
9449
9459
|
return;
|
|
9450
9460
|
}
|
|
@@ -9495,6 +9505,7 @@ function AiSectionOverlay({
|
|
|
9495
9505
|
if (reviewIdRef.current) return;
|
|
9496
9506
|
if (document.querySelector("[data-ohw-editing]")) return;
|
|
9497
9507
|
if (selectedIdRef.current) {
|
|
9508
|
+
selectedIdRef.current = null;
|
|
9498
9509
|
setSelectedId(null);
|
|
9499
9510
|
report(null);
|
|
9500
9511
|
}
|
|
@@ -16503,6 +16514,19 @@ function isMediaEditable(el) {
|
|
|
16503
16514
|
const t = el.dataset.ohwEditable;
|
|
16504
16515
|
return t === "image" || t === "bg-image" || t === "video";
|
|
16505
16516
|
}
|
|
16517
|
+
var FULL_BLEED_MIN_COVERAGE = 0.98;
|
|
16518
|
+
function fullBleedSectionIdOf(media) {
|
|
16519
|
+
const section = media.closest("[data-ohw-section]");
|
|
16520
|
+
if (!section) return null;
|
|
16521
|
+
const s = section.getBoundingClientRect();
|
|
16522
|
+
if (s.width <= 0 || s.height <= 0) return null;
|
|
16523
|
+
const m = media.getBoundingClientRect();
|
|
16524
|
+
const overlapX = Math.min(m.right, s.right) - Math.max(m.left, s.left);
|
|
16525
|
+
const overlapY = Math.min(m.bottom, s.bottom) - Math.max(m.top, s.top);
|
|
16526
|
+
if (overlapX <= 0 || overlapY <= 0) return null;
|
|
16527
|
+
if (overlapX * overlapY / (s.width * s.height) < FULL_BLEED_MIN_COVERAGE) return null;
|
|
16528
|
+
return instanceIdOf(movableUnit(section)) || null;
|
|
16529
|
+
}
|
|
16506
16530
|
function isIconMarkupValue(value) {
|
|
16507
16531
|
return /^\s*<(svg|img)\b/i.test(value);
|
|
16508
16532
|
}
|
|
@@ -17676,20 +17700,38 @@ function OhhwellsBridge() {
|
|
|
17676
17700
|
const hoveredImageHasTextOverlapRef = (0, import_react17.useRef)(false);
|
|
17677
17701
|
const dragOverElRef = (0, import_react17.useRef)(null);
|
|
17678
17702
|
const [mediaHover, setMediaHover] = (0, import_react17.useState)(null);
|
|
17703
|
+
const [selectedAiSectionId, setSelectedAiSectionId] = (0, import_react17.useState)(null);
|
|
17704
|
+
const selectedAiSectionIdRef = (0, import_react17.useRef)(null);
|
|
17705
|
+
const handleAiSectionSelectionChange = (0, import_react17.useCallback)((id) => {
|
|
17706
|
+
selectedAiSectionIdRef.current = id;
|
|
17707
|
+
setSelectedAiSectionId(id);
|
|
17708
|
+
}, []);
|
|
17679
17709
|
const [selectedMedia, setSelectedMedia] = (0, import_react17.useState)(null);
|
|
17680
17710
|
const selectedMediaElRef = (0, import_react17.useRef)(null);
|
|
17711
|
+
const mediaKeyDropTokenRef = (0, import_react17.useRef)(0);
|
|
17681
17712
|
const clearMediaSelection = (0, import_react17.useCallback)(() => {
|
|
17682
17713
|
const prev = selectedMediaElRef.current;
|
|
17683
17714
|
selectedMediaElRef.current = null;
|
|
17684
17715
|
setSelectedMedia(null);
|
|
17685
17716
|
const sectionEl = prev?.closest("[data-ohw-section]") ?? null;
|
|
17686
17717
|
if (sectionEl) {
|
|
17687
|
-
|
|
17688
|
-
|
|
17689
|
-
|
|
17690
|
-
|
|
17691
|
-
key
|
|
17692
|
-
|
|
17718
|
+
const sectionInstanceId = instanceIdOf(movableUnit(sectionEl)) || null;
|
|
17719
|
+
if (!sectionInstanceId) return;
|
|
17720
|
+
const token = ++mediaKeyDropTokenRef.current;
|
|
17721
|
+
const onQueueDrained = (e) => {
|
|
17722
|
+
if (e.source !== window || e.data?.type !== "ow:media-key-drop" || e.data.token !== token) return;
|
|
17723
|
+
window.removeEventListener("message", onQueueDrained);
|
|
17724
|
+
if (aiSectionApiRef.current?.getSelectedId() !== sectionInstanceId) return;
|
|
17725
|
+
if (selectedMediaElRef.current) return;
|
|
17726
|
+
postToParentRef.current({
|
|
17727
|
+
type: "ow:section-selected",
|
|
17728
|
+
sectionId: sectionEl.dataset.ohwSection ?? null,
|
|
17729
|
+
sectionLabel: sectionEl.dataset.ohwSectionLabel ?? titleCaseSectionId(sectionEl.dataset.ohwSection ?? ""),
|
|
17730
|
+
key: null
|
|
17731
|
+
});
|
|
17732
|
+
};
|
|
17733
|
+
window.addEventListener("message", onQueueDrained);
|
|
17734
|
+
window.postMessage({ type: "ow:media-key-drop", token }, "*");
|
|
17693
17735
|
}
|
|
17694
17736
|
}, []);
|
|
17695
17737
|
const clearMediaSelectionRef = (0, import_react17.useRef)(clearMediaSelection);
|
|
@@ -20131,6 +20173,23 @@ function OhhwellsBridge() {
|
|
|
20131
20173
|
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
20132
20174
|
clearMediaSelectionRef.current();
|
|
20133
20175
|
}
|
|
20176
|
+
if (selectedMediaElRef.current && target.closest("[data-ohw-media-overlay]") && !findClosestButtonLike(target)) {
|
|
20177
|
+
const hit = findImageAtPoint(e.clientX, e.clientY, false);
|
|
20178
|
+
if (hit && hit !== selectedMediaElRef.current) {
|
|
20179
|
+
e.preventDefault();
|
|
20180
|
+
e.stopPropagation();
|
|
20181
|
+
const fullBleedSectionId = fullBleedSectionIdOf(hit);
|
|
20182
|
+
if (fullBleedSectionId && fullBleedSectionId !== selectedAiSectionIdRef.current) {
|
|
20183
|
+
clearMediaSelectionRef.current();
|
|
20184
|
+
deselectRef.current();
|
|
20185
|
+
deactivateRef.current();
|
|
20186
|
+
aiSectionApiRef.current?.selectFromElement(hit);
|
|
20187
|
+
return;
|
|
20188
|
+
}
|
|
20189
|
+
selectMediaElementRef.current(hit);
|
|
20190
|
+
return;
|
|
20191
|
+
}
|
|
20192
|
+
}
|
|
20134
20193
|
if (isInsideFloatingPanel(target)) return;
|
|
20135
20194
|
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
20136
20195
|
if (target.closest(
|
|
@@ -20312,6 +20371,14 @@ function OhhwellsBridge() {
|
|
|
20312
20371
|
if (isMediaEditable(editable) && !buttonOnMedia) {
|
|
20313
20372
|
e.preventDefault();
|
|
20314
20373
|
e.stopPropagation();
|
|
20374
|
+
const fullBleedSectionId = fullBleedSectionIdOf(editable);
|
|
20375
|
+
if (fullBleedSectionId && fullBleedSectionId !== selectedAiSectionIdRef.current) {
|
|
20376
|
+
clearMediaSelectionRef.current();
|
|
20377
|
+
deselectRef.current();
|
|
20378
|
+
deactivateRef.current();
|
|
20379
|
+
aiSectionApiRef.current?.selectFromElement(editable);
|
|
20380
|
+
return;
|
|
20381
|
+
}
|
|
20315
20382
|
if (selectedMediaElRef.current === editable) {
|
|
20316
20383
|
postToParentRef.current({ type: "ow:image-pick", key: editable.dataset.ohwKey ?? "", elementType: editable.dataset.ohwEditable ?? "image" });
|
|
20317
20384
|
} else {
|
|
@@ -20766,6 +20833,7 @@ function OhhwellsBridge() {
|
|
|
20766
20833
|
elementType: imgEl.dataset.ohwEditable ?? "image",
|
|
20767
20834
|
hasTextOverlap,
|
|
20768
20835
|
isDragOver,
|
|
20836
|
+
fullBleedSectionId: fullBleedSectionIdOf(imgEl),
|
|
20769
20837
|
...video ? { videoAutoplay: video.autoplay, videoMuted: video.muted } : {}
|
|
20770
20838
|
});
|
|
20771
20839
|
const track = imgEl.closest("[data-ohw-hover-pause]");
|
|
@@ -20938,7 +21006,13 @@ function OhhwellsBridge() {
|
|
|
20938
21006
|
setHoveredItemRect(null);
|
|
20939
21007
|
}
|
|
20940
21008
|
};
|
|
21009
|
+
const syncSelectedMediaPointerRelease = (released) => {
|
|
21010
|
+
setSelectedMedia(
|
|
21011
|
+
(prev) => prev && prev.hasTextOverlap !== released ? { ...prev, hasTextOverlap: released } : prev
|
|
21012
|
+
);
|
|
21013
|
+
};
|
|
20941
21014
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
21015
|
+
syncSelectedMediaPointerRelease(true);
|
|
20942
21016
|
if (linkPopoverOpenRef.current) {
|
|
20943
21017
|
if (hoveredImageRef.current) {
|
|
20944
21018
|
hoveredImageRef.current = null;
|
|
@@ -21133,6 +21207,7 @@ function OhhwellsBridge() {
|
|
|
21133
21207
|
return;
|
|
21134
21208
|
}
|
|
21135
21209
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
21210
|
+
syncSelectedMediaPointerRelease(false);
|
|
21136
21211
|
if (imgEl !== hoveredImageRef.current || hoveredImageHasTextOverlapRef.current) {
|
|
21137
21212
|
hoveredImageRef.current = imgEl;
|
|
21138
21213
|
showImageHover(imgEl, isDragOver);
|
|
@@ -22606,7 +22681,11 @@ function OhhwellsBridge() {
|
|
|
22606
22681
|
if (!key) return;
|
|
22607
22682
|
const r2 = getVisibleRect(container);
|
|
22608
22683
|
setCarouselHover(
|
|
22609
|
-
(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 : {
|
|
22684
|
+
(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 : {
|
|
22685
|
+
key,
|
|
22686
|
+
rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height },
|
|
22687
|
+
fullBleedSectionId: fullBleedSectionIdOf(container)
|
|
22688
|
+
}
|
|
22610
22689
|
);
|
|
22611
22690
|
};
|
|
22612
22691
|
const applyToolbarPos = (rect) => {
|
|
@@ -23068,7 +23147,7 @@ function OhhwellsBridge() {
|
|
|
23068
23147
|
postToParent2({
|
|
23069
23148
|
type: "ow:ready",
|
|
23070
23149
|
version: "1",
|
|
23071
|
-
bridgeVersion: "0.1.
|
|
23150
|
+
bridgeVersion: "0.1.116",
|
|
23072
23151
|
path: pathname,
|
|
23073
23152
|
nodes: collectEditableNodes(editContentRef.current),
|
|
23074
23153
|
sections
|
|
@@ -23535,7 +23614,14 @@ function OhhwellsBridge() {
|
|
|
23535
23614
|
bridgeRoot ? (0, import_react_dom5.createPortal)(
|
|
23536
23615
|
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
|
|
23537
23616
|
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
23538
|
-
isEditMode && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
23617
|
+
isEditMode && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
23618
|
+
AiSectionOverlay,
|
|
23619
|
+
{
|
|
23620
|
+
postToParent: postToParent2,
|
|
23621
|
+
apiRef: aiSectionApiRef,
|
|
23622
|
+
onSelectionChange: handleAiSectionSelectionChange
|
|
23623
|
+
}
|
|
23624
|
+
),
|
|
23539
23625
|
isSectionDragging && sectionDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
23540
23626
|
"div",
|
|
23541
23627
|
{
|
|
@@ -23568,6 +23654,7 @@ function OhhwellsBridge() {
|
|
|
23568
23654
|
{
|
|
23569
23655
|
hover: mediaHover,
|
|
23570
23656
|
isUploading: false,
|
|
23657
|
+
cueOnly: !mediaHover.isDragOver && !!mediaHover.fullBleedSectionId && mediaHover.fullBleedSectionId !== selectedAiSectionId,
|
|
23571
23658
|
onReplace: handleMediaReplace,
|
|
23572
23659
|
onSelect: handleMediaSelect,
|
|
23573
23660
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
@@ -23585,7 +23672,14 @@ function OhhwellsBridge() {
|
|
|
23585
23672
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
23586
23673
|
}
|
|
23587
23674
|
),
|
|
23588
|
-
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
23675
|
+
carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
23676
|
+
CarouselOverlay,
|
|
23677
|
+
{
|
|
23678
|
+
hover: carouselHover,
|
|
23679
|
+
onEdit: handleEditCarousel,
|
|
23680
|
+
cueOnly: !!carouselHover.fullBleedSectionId && carouselHover.fullBleedSectionId !== selectedAiSectionId
|
|
23681
|
+
}
|
|
23682
|
+
),
|
|
23589
23683
|
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
23590
23684
|
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
|
|
23591
23685
|
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
|