@ohhwells/bridge 0.1.38-next.56 → 0.1.38-next.57
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 +123 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +165 -80
- package/dist/index.js.map +1 -1
- package/dist/styles.css +5 -14
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -5181,9 +5181,9 @@ var DialogContent = React7.forwardRef(
|
|
|
5181
5181
|
"data-slot": "dialog-content",
|
|
5182
5182
|
className: cn(
|
|
5183
5183
|
positionMode,
|
|
5184
|
-
"left-1/2 top-1/2 z-[2147483647] flex w-full max-w-[
|
|
5184
|
+
"left-1/2 top-1/2 z-[2147483647] flex w-full max-w-[448px] -translate-x-1/2 -translate-y-1/2 flex-col overflow-visible",
|
|
5185
5185
|
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
5186
|
-
container ? "max-h-[calc(100%-32px)]
|
|
5186
|
+
container ? "max-h-[calc(100%-32px)]" : "max-h-[calc(100vh-32px)]",
|
|
5187
5187
|
className
|
|
5188
5188
|
),
|
|
5189
5189
|
onMouseDown: (e) => e.stopPropagation(),
|
|
@@ -5448,7 +5448,7 @@ function UrlOrPageInput({
|
|
|
5448
5448
|
requestAnimationFrame(() => inputRef.current?.focus());
|
|
5449
5449
|
};
|
|
5450
5450
|
const fieldClassName = cn(
|
|
5451
|
-
"data-ohw-link-field flex h-
|
|
5451
|
+
"data-ohw-link-field flex h-[36px] w-full items-center overflow-hidden rounded-md border bg-background pl-3 pr-3 py-2 outline-none transition-[border-color,box-shadow]",
|
|
5452
5452
|
urlError ? "border-destructive shadow-[0_0_0_1px_var(--ohw-destructive)]" : isFocused ? "border-primary shadow-[0_0_0_1px_var(--ohw-primary)]" : "border-input"
|
|
5453
5453
|
);
|
|
5454
5454
|
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex w-full flex-col gap-2 p-0", children: [
|
|
@@ -5634,6 +5634,26 @@ function rectsEqual(a, b) {
|
|
|
5634
5634
|
}
|
|
5635
5635
|
return true;
|
|
5636
5636
|
}
|
|
5637
|
+
function readSectionRects(sectionIds) {
|
|
5638
|
+
const next = /* @__PURE__ */ new Map();
|
|
5639
|
+
for (const id of sectionIds) {
|
|
5640
|
+
const el = document.querySelector(
|
|
5641
|
+
`[data-ohw-section="${CSS.escape(id)}"]`
|
|
5642
|
+
);
|
|
5643
|
+
if (el) next.set(id, el.getBoundingClientRect());
|
|
5644
|
+
}
|
|
5645
|
+
return next;
|
|
5646
|
+
}
|
|
5647
|
+
function hitTestSectionId(x, y, sectionIds, rects) {
|
|
5648
|
+
for (const id of sectionIds) {
|
|
5649
|
+
const rect = rects.get(id);
|
|
5650
|
+
if (!rect || rect.width <= 0 || rect.height <= 0) continue;
|
|
5651
|
+
if (x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom) {
|
|
5652
|
+
return id;
|
|
5653
|
+
}
|
|
5654
|
+
}
|
|
5655
|
+
return null;
|
|
5656
|
+
}
|
|
5637
5657
|
function useSectionRects(sectionIdsKey, enabled) {
|
|
5638
5658
|
const [rects, setRects] = (0, import_react5.useState)(/* @__PURE__ */ new Map());
|
|
5639
5659
|
const sectionIds = (0, import_react5.useMemo)(
|
|
@@ -5646,13 +5666,7 @@ function useSectionRects(sectionIdsKey, enabled) {
|
|
|
5646
5666
|
return;
|
|
5647
5667
|
}
|
|
5648
5668
|
const update = () => {
|
|
5649
|
-
const next =
|
|
5650
|
-
for (const id of sectionIds) {
|
|
5651
|
-
const el = document.querySelector(
|
|
5652
|
-
`[data-ohw-section="${CSS.escape(id)}"]`
|
|
5653
|
-
);
|
|
5654
|
-
if (el) next.set(id, el.getBoundingClientRect());
|
|
5655
|
-
}
|
|
5669
|
+
const next = readSectionRects(sectionIds);
|
|
5656
5670
|
setRects((prev) => rectsEqual(prev, next) ? prev : next);
|
|
5657
5671
|
};
|
|
5658
5672
|
update();
|
|
@@ -5689,6 +5703,10 @@ function SectionPickerOverlay({
|
|
|
5689
5703
|
const pathname = (0, import_navigation.usePathname)();
|
|
5690
5704
|
const [selectedId, setSelectedId] = (0, import_react5.useState)(null);
|
|
5691
5705
|
const [hoveredId, setHoveredId] = (0, import_react5.useState)(null);
|
|
5706
|
+
const pointerRef = (0, import_react5.useRef)(null);
|
|
5707
|
+
const pointerScreenRef = (0, import_react5.useRef)(null);
|
|
5708
|
+
const iframeOffsetTopRef = (0, import_react5.useRef)(null);
|
|
5709
|
+
const sectionIdsRef = (0, import_react5.useRef)([]);
|
|
5692
5710
|
const [chromeClip, setChromeClip] = (0, import_react5.useState)(
|
|
5693
5711
|
() => ({
|
|
5694
5712
|
top: 0,
|
|
@@ -5711,6 +5729,29 @@ function SectionPickerOverlay({
|
|
|
5711
5729
|
document.documentElement.removeAttribute("data-ohw-section-picking");
|
|
5712
5730
|
};
|
|
5713
5731
|
}, []);
|
|
5732
|
+
const liveSections = (0, import_react5.useMemo)(() => {
|
|
5733
|
+
if (!isOnTargetPage) return sections;
|
|
5734
|
+
const live = collectSectionsFromDom();
|
|
5735
|
+
if (live.length === 0) return sections;
|
|
5736
|
+
const labels = new Map(sections.map((s) => [s.id, s.label]));
|
|
5737
|
+
return live.map((s) => ({ id: s.id, label: labels.get(s.id) ?? s.label }));
|
|
5738
|
+
}, [isOnTargetPage, sections, pathname]);
|
|
5739
|
+
const sectionIdsKey = (0, import_react5.useMemo)(
|
|
5740
|
+
() => liveSections.map((s) => s.id).join("\0"),
|
|
5741
|
+
[liveSections]
|
|
5742
|
+
);
|
|
5743
|
+
const sectionIds = (0, import_react5.useMemo)(
|
|
5744
|
+
() => liveSections.map((s) => s.id),
|
|
5745
|
+
[liveSections]
|
|
5746
|
+
);
|
|
5747
|
+
sectionIdsRef.current = sectionIds;
|
|
5748
|
+
const rects = useSectionRects(sectionIdsKey, isOnTargetPage);
|
|
5749
|
+
const applyHoverAt = (0, import_react5.useCallback)((x, y, liveRects) => {
|
|
5750
|
+
const ids = sectionIdsRef.current;
|
|
5751
|
+
const map = liveRects ?? readSectionRects(ids);
|
|
5752
|
+
const next = hitTestSectionId(x, y, ids, map);
|
|
5753
|
+
setHoveredId((prev) => prev === next ? prev : next);
|
|
5754
|
+
}, []);
|
|
5714
5755
|
(0, import_react5.useEffect)(() => {
|
|
5715
5756
|
const applyClip = (iframeOffsetTop, visibleCanvasTop, canvasH) => {
|
|
5716
5757
|
const top = Math.max(0, visibleCanvasTop - iframeOffsetTop);
|
|
@@ -5726,6 +5767,19 @@ function SectionPickerOverlay({
|
|
|
5726
5767
|
if (e.data?.type !== "ow:parent-scroll") return;
|
|
5727
5768
|
const { iframeOffsetTop, headerH, canvasH } = e.data;
|
|
5728
5769
|
applyClip(iframeOffsetTop, headerH, canvasH);
|
|
5770
|
+
iframeOffsetTopRef.current = iframeOffsetTop;
|
|
5771
|
+
if (!pointerScreenRef.current && pointerRef.current) {
|
|
5772
|
+
pointerScreenRef.current = {
|
|
5773
|
+
x: pointerRef.current.x,
|
|
5774
|
+
y: pointerRef.current.y + iframeOffsetTop
|
|
5775
|
+
};
|
|
5776
|
+
}
|
|
5777
|
+
const screen = pointerScreenRef.current;
|
|
5778
|
+
if (screen) {
|
|
5779
|
+
const next = { x: screen.x, y: screen.y - iframeOffsetTop };
|
|
5780
|
+
pointerRef.current = next;
|
|
5781
|
+
applyHoverAt(next.x, next.y);
|
|
5782
|
+
}
|
|
5729
5783
|
};
|
|
5730
5784
|
const onResize = () => {
|
|
5731
5785
|
setChromeClip((prev) => {
|
|
@@ -5739,19 +5793,36 @@ function SectionPickerOverlay({
|
|
|
5739
5793
|
window.removeEventListener("message", onParentScroll);
|
|
5740
5794
|
window.removeEventListener("resize", onResize);
|
|
5741
5795
|
};
|
|
5742
|
-
}, []);
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5796
|
+
}, [applyHoverAt]);
|
|
5797
|
+
(0, import_react5.useEffect)(() => {
|
|
5798
|
+
const ptr = pointerRef.current;
|
|
5799
|
+
if (!ptr) return;
|
|
5800
|
+
applyHoverAt(ptr.x, ptr.y, rects);
|
|
5801
|
+
}, [rects, applyHoverAt]);
|
|
5802
|
+
(0, import_react5.useEffect)(() => {
|
|
5803
|
+
const rememberPointer = (clientX, clientY) => {
|
|
5804
|
+
pointerRef.current = { x: clientX, y: clientY };
|
|
5805
|
+
const top = iframeOffsetTopRef.current;
|
|
5806
|
+
if (top != null) {
|
|
5807
|
+
pointerScreenRef.current = { x: clientX, y: clientY + top };
|
|
5808
|
+
}
|
|
5809
|
+
applyHoverAt(clientX, clientY, rects);
|
|
5810
|
+
};
|
|
5811
|
+
const onPointerMove = (e) => {
|
|
5812
|
+
rememberPointer(e.clientX, e.clientY);
|
|
5813
|
+
};
|
|
5814
|
+
const onPointerSync = (e) => {
|
|
5815
|
+
if (e.data?.type !== "ow:pointer-sync") return;
|
|
5816
|
+
const { clientX, clientY } = e.data;
|
|
5817
|
+
rememberPointer(clientX, clientY);
|
|
5818
|
+
};
|
|
5819
|
+
window.addEventListener("pointermove", onPointerMove, { passive: true });
|
|
5820
|
+
window.addEventListener("message", onPointerSync);
|
|
5821
|
+
return () => {
|
|
5822
|
+
window.removeEventListener("pointermove", onPointerMove);
|
|
5823
|
+
window.removeEventListener("message", onPointerSync);
|
|
5824
|
+
};
|
|
5825
|
+
}, [rects, applyHoverAt]);
|
|
5755
5826
|
const handleSelect = (0, import_react5.useCallback)(
|
|
5756
5827
|
(section) => {
|
|
5757
5828
|
if (selectedId) return;
|
|
@@ -5845,8 +5916,6 @@ function SectionPickerOverlay({
|
|
|
5845
5916
|
backgroundColor: isLit ? "transparent" : DIM_OVERLAY
|
|
5846
5917
|
},
|
|
5847
5918
|
"aria-label": `Select section ${section.label}`,
|
|
5848
|
-
onMouseEnter: () => setHoveredId(section.id),
|
|
5849
|
-
onMouseLeave: () => setHoveredId((prev) => prev === section.id ? null : prev),
|
|
5850
5919
|
onClick: () => handleSelect(section),
|
|
5851
5920
|
children: isSelected ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5852
5921
|
"span",
|
|
@@ -6090,7 +6159,8 @@ function LinkPopover({
|
|
|
6090
6159
|
if (overflowY !== "auto" && overflowY !== "scroll") return false;
|
|
6091
6160
|
if (el.scrollHeight <= el.clientHeight + 1) return false;
|
|
6092
6161
|
if (deltaY < 0) return el.scrollTop > 0;
|
|
6093
|
-
if (deltaY > 0)
|
|
6162
|
+
if (deltaY > 0)
|
|
6163
|
+
return el.scrollTop + el.clientHeight < el.scrollHeight - 1;
|
|
6094
6164
|
return true;
|
|
6095
6165
|
};
|
|
6096
6166
|
const allowsInternalScroll = (e) => {
|
|
@@ -6116,8 +6186,16 @@ function LinkPopover({
|
|
|
6116
6186
|
body.style.overflow = prevBodyOverflow;
|
|
6117
6187
|
html.style.overscrollBehavior = prevHtmlOverscroll;
|
|
6118
6188
|
body.style.overscrollBehavior = prevBodyOverscroll;
|
|
6119
|
-
document.removeEventListener(
|
|
6120
|
-
|
|
6189
|
+
document.removeEventListener(
|
|
6190
|
+
"wheel",
|
|
6191
|
+
preventBackgroundScroll,
|
|
6192
|
+
scrollOpts
|
|
6193
|
+
);
|
|
6194
|
+
document.removeEventListener(
|
|
6195
|
+
"touchmove",
|
|
6196
|
+
preventBackgroundScroll,
|
|
6197
|
+
scrollOpts
|
|
6198
|
+
);
|
|
6121
6199
|
};
|
|
6122
6200
|
}, [open, sectionPickerActive]);
|
|
6123
6201
|
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
|
|
@@ -6137,7 +6215,7 @@ function LinkPopover({
|
|
|
6137
6215
|
"data-ohw-link-modal-root": "",
|
|
6138
6216
|
"data-ohw-bridge": "",
|
|
6139
6217
|
showCloseButton: false,
|
|
6140
|
-
className: "gap-0 p-0 w-full
|
|
6218
|
+
className: "gap-0 p-0 w-full max-w-[448px] pointer-events-auto z-[2147483646] overflow-visible",
|
|
6141
6219
|
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(LinkEditorPanel, { state, onClose })
|
|
6142
6220
|
}
|
|
6143
6221
|
)
|
|
@@ -9413,14 +9491,20 @@ function OhhwellsBridge() {
|
|
|
9413
9491
|
const session = linkPopoverSessionRef.current;
|
|
9414
9492
|
if (!session) return;
|
|
9415
9493
|
if (session.intent === "add-nav") {
|
|
9416
|
-
const
|
|
9417
|
-
|
|
9418
|
-
|
|
9419
|
-
|
|
9420
|
-
|
|
9494
|
+
const trimmed = target.trim();
|
|
9495
|
+
let href = trimmed;
|
|
9496
|
+
let label = "Untitled";
|
|
9497
|
+
if (trimmed) {
|
|
9498
|
+
const { pageRoute, sectionId } = parseTarget(trimmed);
|
|
9499
|
+
const page = resolvePage(pageRoute, sitePages);
|
|
9500
|
+
const pageSections = getSectionsForPath(sectionsByPath, pageRoute);
|
|
9501
|
+
const section = sectionId ? pageSections.find((s) => s.id === sectionId) : void 0;
|
|
9502
|
+
label = section?.label ?? page.title;
|
|
9503
|
+
href = trimmed;
|
|
9504
|
+
}
|
|
9421
9505
|
const afterAnchor = addNavAfterAnchorRef.current;
|
|
9422
|
-
const { anchor, hrefKey, labelKey, index, order } = insertNavbarItem(
|
|
9423
|
-
applyLinkByKey(hrefKey,
|
|
9506
|
+
const { anchor, hrefKey, labelKey, index, order } = insertNavbarItem(href, label, afterAnchor);
|
|
9507
|
+
applyLinkByKey(hrefKey, href);
|
|
9424
9508
|
document.querySelectorAll(`[data-ohw-key="${labelKey}"]`).forEach((el) => {
|
|
9425
9509
|
el.textContent = label;
|
|
9426
9510
|
});
|
|
@@ -9428,7 +9512,7 @@ function OhhwellsBridge() {
|
|
|
9428
9512
|
const orderJson = JSON.stringify(order);
|
|
9429
9513
|
editContentRef.current = {
|
|
9430
9514
|
...editContentRef.current,
|
|
9431
|
-
[hrefKey]:
|
|
9515
|
+
[hrefKey]: href,
|
|
9432
9516
|
[labelKey]: label,
|
|
9433
9517
|
[NAV_COUNT_KEY]: navCount,
|
|
9434
9518
|
[NAV_ORDER_KEY]: orderJson
|
|
@@ -9436,12 +9520,13 @@ function OhhwellsBridge() {
|
|
|
9436
9520
|
postToParent2({
|
|
9437
9521
|
type: "ow:change",
|
|
9438
9522
|
nodes: [
|
|
9439
|
-
{ key: hrefKey, text:
|
|
9523
|
+
{ key: hrefKey, text: href },
|
|
9440
9524
|
{ key: labelKey, text: label },
|
|
9441
9525
|
{ key: NAV_COUNT_KEY, text: navCount },
|
|
9442
9526
|
{ key: NAV_ORDER_KEY, text: orderJson }
|
|
9443
9527
|
]
|
|
9444
9528
|
});
|
|
9529
|
+
postToParent2({ type: "ow:toast", title: "Link added", toastType: "success" });
|
|
9445
9530
|
addNavAfterAnchorRef.current = null;
|
|
9446
9531
|
setLinkPopover(null);
|
|
9447
9532
|
enforceLinkHrefs();
|