@ohhwells/bridge 0.1.38-next.56 → 0.1.38-next.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 +169 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -1
- package/dist/index.d.ts +21 -1
- package/dist/index.js +209 -80
- package/dist/index.js.map +1 -1
- package/dist/styles.css +25 -14
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -35,6 +35,7 @@ __export(index_exports, {
|
|
|
35
35
|
CustomToolbarButton: () => CustomToolbarButton,
|
|
36
36
|
CustomToolbarDivider: () => CustomToolbarDivider,
|
|
37
37
|
DragHandle: () => DragHandle,
|
|
38
|
+
DropIndicator: () => DropIndicator,
|
|
38
39
|
ItemActionToolbar: () => ItemActionToolbar,
|
|
39
40
|
ItemInteractionLayer: () => ItemInteractionLayer,
|
|
40
41
|
LinkEditorPanel: () => LinkEditorPanel,
|
|
@@ -49,6 +50,7 @@ __export(index_exports, {
|
|
|
49
50
|
TooltipProvider: () => TooltipProvider,
|
|
50
51
|
TooltipTrigger: () => TooltipTrigger,
|
|
51
52
|
buildTarget: () => buildTarget,
|
|
53
|
+
dropIndicatorVariants: () => dropIndicatorVariants,
|
|
52
54
|
filterAvailablePages: () => filterAvailablePages,
|
|
53
55
|
getEditModeInitialState: () => getEditModeInitialState,
|
|
54
56
|
isEditSessionActive: () => isEditSessionActive,
|
|
@@ -5181,9 +5183,9 @@ var DialogContent = React7.forwardRef(
|
|
|
5181
5183
|
"data-slot": "dialog-content",
|
|
5182
5184
|
className: cn(
|
|
5183
5185
|
positionMode,
|
|
5184
|
-
"left-1/2 top-1/2 z-[2147483647] flex w-full max-w-[
|
|
5186
|
+
"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
5187
|
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
5186
|
-
container ? "max-h-[calc(100%-32px)]
|
|
5188
|
+
container ? "max-h-[calc(100%-32px)]" : "max-h-[calc(100vh-32px)]",
|
|
5187
5189
|
className
|
|
5188
5190
|
),
|
|
5189
5191
|
onMouseDown: (e) => e.stopPropagation(),
|
|
@@ -5448,7 +5450,7 @@ function UrlOrPageInput({
|
|
|
5448
5450
|
requestAnimationFrame(() => inputRef.current?.focus());
|
|
5449
5451
|
};
|
|
5450
5452
|
const fieldClassName = cn(
|
|
5451
|
-
"data-ohw-link-field flex h-
|
|
5453
|
+
"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
5454
|
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
5455
|
);
|
|
5454
5456
|
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex w-full flex-col gap-2 p-0", children: [
|
|
@@ -5634,6 +5636,26 @@ function rectsEqual(a, b) {
|
|
|
5634
5636
|
}
|
|
5635
5637
|
return true;
|
|
5636
5638
|
}
|
|
5639
|
+
function readSectionRects(sectionIds) {
|
|
5640
|
+
const next = /* @__PURE__ */ new Map();
|
|
5641
|
+
for (const id of sectionIds) {
|
|
5642
|
+
const el = document.querySelector(
|
|
5643
|
+
`[data-ohw-section="${CSS.escape(id)}"]`
|
|
5644
|
+
);
|
|
5645
|
+
if (el) next.set(id, el.getBoundingClientRect());
|
|
5646
|
+
}
|
|
5647
|
+
return next;
|
|
5648
|
+
}
|
|
5649
|
+
function hitTestSectionId(x, y, sectionIds, rects) {
|
|
5650
|
+
for (const id of sectionIds) {
|
|
5651
|
+
const rect = rects.get(id);
|
|
5652
|
+
if (!rect || rect.width <= 0 || rect.height <= 0) continue;
|
|
5653
|
+
if (x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom) {
|
|
5654
|
+
return id;
|
|
5655
|
+
}
|
|
5656
|
+
}
|
|
5657
|
+
return null;
|
|
5658
|
+
}
|
|
5637
5659
|
function useSectionRects(sectionIdsKey, enabled) {
|
|
5638
5660
|
const [rects, setRects] = (0, import_react5.useState)(/* @__PURE__ */ new Map());
|
|
5639
5661
|
const sectionIds = (0, import_react5.useMemo)(
|
|
@@ -5646,13 +5668,7 @@ function useSectionRects(sectionIdsKey, enabled) {
|
|
|
5646
5668
|
return;
|
|
5647
5669
|
}
|
|
5648
5670
|
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
|
-
}
|
|
5671
|
+
const next = readSectionRects(sectionIds);
|
|
5656
5672
|
setRects((prev) => rectsEqual(prev, next) ? prev : next);
|
|
5657
5673
|
};
|
|
5658
5674
|
update();
|
|
@@ -5689,6 +5705,10 @@ function SectionPickerOverlay({
|
|
|
5689
5705
|
const pathname = (0, import_navigation.usePathname)();
|
|
5690
5706
|
const [selectedId, setSelectedId] = (0, import_react5.useState)(null);
|
|
5691
5707
|
const [hoveredId, setHoveredId] = (0, import_react5.useState)(null);
|
|
5708
|
+
const pointerRef = (0, import_react5.useRef)(null);
|
|
5709
|
+
const pointerScreenRef = (0, import_react5.useRef)(null);
|
|
5710
|
+
const iframeOffsetTopRef = (0, import_react5.useRef)(null);
|
|
5711
|
+
const sectionIdsRef = (0, import_react5.useRef)([]);
|
|
5692
5712
|
const [chromeClip, setChromeClip] = (0, import_react5.useState)(
|
|
5693
5713
|
() => ({
|
|
5694
5714
|
top: 0,
|
|
@@ -5711,6 +5731,29 @@ function SectionPickerOverlay({
|
|
|
5711
5731
|
document.documentElement.removeAttribute("data-ohw-section-picking");
|
|
5712
5732
|
};
|
|
5713
5733
|
}, []);
|
|
5734
|
+
const liveSections = (0, import_react5.useMemo)(() => {
|
|
5735
|
+
if (!isOnTargetPage) return sections;
|
|
5736
|
+
const live = collectSectionsFromDom();
|
|
5737
|
+
if (live.length === 0) return sections;
|
|
5738
|
+
const labels = new Map(sections.map((s) => [s.id, s.label]));
|
|
5739
|
+
return live.map((s) => ({ id: s.id, label: labels.get(s.id) ?? s.label }));
|
|
5740
|
+
}, [isOnTargetPage, sections, pathname]);
|
|
5741
|
+
const sectionIdsKey = (0, import_react5.useMemo)(
|
|
5742
|
+
() => liveSections.map((s) => s.id).join("\0"),
|
|
5743
|
+
[liveSections]
|
|
5744
|
+
);
|
|
5745
|
+
const sectionIds = (0, import_react5.useMemo)(
|
|
5746
|
+
() => liveSections.map((s) => s.id),
|
|
5747
|
+
[liveSections]
|
|
5748
|
+
);
|
|
5749
|
+
sectionIdsRef.current = sectionIds;
|
|
5750
|
+
const rects = useSectionRects(sectionIdsKey, isOnTargetPage);
|
|
5751
|
+
const applyHoverAt = (0, import_react5.useCallback)((x, y, liveRects) => {
|
|
5752
|
+
const ids = sectionIdsRef.current;
|
|
5753
|
+
const map = liveRects ?? readSectionRects(ids);
|
|
5754
|
+
const next = hitTestSectionId(x, y, ids, map);
|
|
5755
|
+
setHoveredId((prev) => prev === next ? prev : next);
|
|
5756
|
+
}, []);
|
|
5714
5757
|
(0, import_react5.useEffect)(() => {
|
|
5715
5758
|
const applyClip = (iframeOffsetTop, visibleCanvasTop, canvasH) => {
|
|
5716
5759
|
const top = Math.max(0, visibleCanvasTop - iframeOffsetTop);
|
|
@@ -5726,6 +5769,19 @@ function SectionPickerOverlay({
|
|
|
5726
5769
|
if (e.data?.type !== "ow:parent-scroll") return;
|
|
5727
5770
|
const { iframeOffsetTop, headerH, canvasH } = e.data;
|
|
5728
5771
|
applyClip(iframeOffsetTop, headerH, canvasH);
|
|
5772
|
+
iframeOffsetTopRef.current = iframeOffsetTop;
|
|
5773
|
+
if (!pointerScreenRef.current && pointerRef.current) {
|
|
5774
|
+
pointerScreenRef.current = {
|
|
5775
|
+
x: pointerRef.current.x,
|
|
5776
|
+
y: pointerRef.current.y + iframeOffsetTop
|
|
5777
|
+
};
|
|
5778
|
+
}
|
|
5779
|
+
const screen = pointerScreenRef.current;
|
|
5780
|
+
if (screen) {
|
|
5781
|
+
const next = { x: screen.x, y: screen.y - iframeOffsetTop };
|
|
5782
|
+
pointerRef.current = next;
|
|
5783
|
+
applyHoverAt(next.x, next.y);
|
|
5784
|
+
}
|
|
5729
5785
|
};
|
|
5730
5786
|
const onResize = () => {
|
|
5731
5787
|
setChromeClip((prev) => {
|
|
@@ -5739,19 +5795,36 @@ function SectionPickerOverlay({
|
|
|
5739
5795
|
window.removeEventListener("message", onParentScroll);
|
|
5740
5796
|
window.removeEventListener("resize", onResize);
|
|
5741
5797
|
};
|
|
5742
|
-
}, []);
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5798
|
+
}, [applyHoverAt]);
|
|
5799
|
+
(0, import_react5.useEffect)(() => {
|
|
5800
|
+
const ptr = pointerRef.current;
|
|
5801
|
+
if (!ptr) return;
|
|
5802
|
+
applyHoverAt(ptr.x, ptr.y, rects);
|
|
5803
|
+
}, [rects, applyHoverAt]);
|
|
5804
|
+
(0, import_react5.useEffect)(() => {
|
|
5805
|
+
const rememberPointer = (clientX, clientY) => {
|
|
5806
|
+
pointerRef.current = { x: clientX, y: clientY };
|
|
5807
|
+
const top = iframeOffsetTopRef.current;
|
|
5808
|
+
if (top != null) {
|
|
5809
|
+
pointerScreenRef.current = { x: clientX, y: clientY + top };
|
|
5810
|
+
}
|
|
5811
|
+
applyHoverAt(clientX, clientY, rects);
|
|
5812
|
+
};
|
|
5813
|
+
const onPointerMove = (e) => {
|
|
5814
|
+
rememberPointer(e.clientX, e.clientY);
|
|
5815
|
+
};
|
|
5816
|
+
const onPointerSync = (e) => {
|
|
5817
|
+
if (e.data?.type !== "ow:pointer-sync") return;
|
|
5818
|
+
const { clientX, clientY } = e.data;
|
|
5819
|
+
rememberPointer(clientX, clientY);
|
|
5820
|
+
};
|
|
5821
|
+
window.addEventListener("pointermove", onPointerMove, { passive: true });
|
|
5822
|
+
window.addEventListener("message", onPointerSync);
|
|
5823
|
+
return () => {
|
|
5824
|
+
window.removeEventListener("pointermove", onPointerMove);
|
|
5825
|
+
window.removeEventListener("message", onPointerSync);
|
|
5826
|
+
};
|
|
5827
|
+
}, [rects, applyHoverAt]);
|
|
5755
5828
|
const handleSelect = (0, import_react5.useCallback)(
|
|
5756
5829
|
(section) => {
|
|
5757
5830
|
if (selectedId) return;
|
|
@@ -5845,8 +5918,6 @@ function SectionPickerOverlay({
|
|
|
5845
5918
|
backgroundColor: isLit ? "transparent" : DIM_OVERLAY
|
|
5846
5919
|
},
|
|
5847
5920
|
"aria-label": `Select section ${section.label}`,
|
|
5848
|
-
onMouseEnter: () => setHoveredId(section.id),
|
|
5849
|
-
onMouseLeave: () => setHoveredId((prev) => prev === section.id ? null : prev),
|
|
5850
5921
|
onClick: () => handleSelect(section),
|
|
5851
5922
|
children: isSelected ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5852
5923
|
"span",
|
|
@@ -6090,7 +6161,8 @@ function LinkPopover({
|
|
|
6090
6161
|
if (overflowY !== "auto" && overflowY !== "scroll") return false;
|
|
6091
6162
|
if (el.scrollHeight <= el.clientHeight + 1) return false;
|
|
6092
6163
|
if (deltaY < 0) return el.scrollTop > 0;
|
|
6093
|
-
if (deltaY > 0)
|
|
6164
|
+
if (deltaY > 0)
|
|
6165
|
+
return el.scrollTop + el.clientHeight < el.scrollHeight - 1;
|
|
6094
6166
|
return true;
|
|
6095
6167
|
};
|
|
6096
6168
|
const allowsInternalScroll = (e) => {
|
|
@@ -6116,8 +6188,16 @@ function LinkPopover({
|
|
|
6116
6188
|
body.style.overflow = prevBodyOverflow;
|
|
6117
6189
|
html.style.overscrollBehavior = prevHtmlOverscroll;
|
|
6118
6190
|
body.style.overscrollBehavior = prevBodyOverscroll;
|
|
6119
|
-
document.removeEventListener(
|
|
6120
|
-
|
|
6191
|
+
document.removeEventListener(
|
|
6192
|
+
"wheel",
|
|
6193
|
+
preventBackgroundScroll,
|
|
6194
|
+
scrollOpts
|
|
6195
|
+
);
|
|
6196
|
+
document.removeEventListener(
|
|
6197
|
+
"touchmove",
|
|
6198
|
+
preventBackgroundScroll,
|
|
6199
|
+
scrollOpts
|
|
6200
|
+
);
|
|
6121
6201
|
};
|
|
6122
6202
|
}, [open, sectionPickerActive]);
|
|
6123
6203
|
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
|
|
@@ -6137,7 +6217,7 @@ function LinkPopover({
|
|
|
6137
6217
|
"data-ohw-link-modal-root": "",
|
|
6138
6218
|
"data-ohw-bridge": "",
|
|
6139
6219
|
showCloseButton: false,
|
|
6140
|
-
className: "gap-0 p-0 w-full
|
|
6220
|
+
className: "gap-0 p-0 w-full max-w-[448px] pointer-events-auto z-[2147483646] overflow-visible",
|
|
6141
6221
|
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(LinkEditorPanel, { state, onClose })
|
|
6142
6222
|
}
|
|
6143
6223
|
)
|
|
@@ -9413,14 +9493,20 @@ function OhhwellsBridge() {
|
|
|
9413
9493
|
const session = linkPopoverSessionRef.current;
|
|
9414
9494
|
if (!session) return;
|
|
9415
9495
|
if (session.intent === "add-nav") {
|
|
9416
|
-
const
|
|
9417
|
-
|
|
9418
|
-
|
|
9419
|
-
|
|
9420
|
-
|
|
9496
|
+
const trimmed = target.trim();
|
|
9497
|
+
let href = trimmed;
|
|
9498
|
+
let label = "Untitled";
|
|
9499
|
+
if (trimmed) {
|
|
9500
|
+
const { pageRoute, sectionId } = parseTarget(trimmed);
|
|
9501
|
+
const page = resolvePage(pageRoute, sitePages);
|
|
9502
|
+
const pageSections = getSectionsForPath(sectionsByPath, pageRoute);
|
|
9503
|
+
const section = sectionId ? pageSections.find((s) => s.id === sectionId) : void 0;
|
|
9504
|
+
label = section?.label ?? page.title;
|
|
9505
|
+
href = trimmed;
|
|
9506
|
+
}
|
|
9421
9507
|
const afterAnchor = addNavAfterAnchorRef.current;
|
|
9422
|
-
const { anchor, hrefKey, labelKey, index, order } = insertNavbarItem(
|
|
9423
|
-
applyLinkByKey(hrefKey,
|
|
9508
|
+
const { anchor, hrefKey, labelKey, index, order } = insertNavbarItem(href, label, afterAnchor);
|
|
9509
|
+
applyLinkByKey(hrefKey, href);
|
|
9424
9510
|
document.querySelectorAll(`[data-ohw-key="${labelKey}"]`).forEach((el) => {
|
|
9425
9511
|
el.textContent = label;
|
|
9426
9512
|
});
|
|
@@ -9428,7 +9514,7 @@ function OhhwellsBridge() {
|
|
|
9428
9514
|
const orderJson = JSON.stringify(order);
|
|
9429
9515
|
editContentRef.current = {
|
|
9430
9516
|
...editContentRef.current,
|
|
9431
|
-
[hrefKey]:
|
|
9517
|
+
[hrefKey]: href,
|
|
9432
9518
|
[labelKey]: label,
|
|
9433
9519
|
[NAV_COUNT_KEY]: navCount,
|
|
9434
9520
|
[NAV_ORDER_KEY]: orderJson
|
|
@@ -9436,12 +9522,13 @@ function OhhwellsBridge() {
|
|
|
9436
9522
|
postToParent2({
|
|
9437
9523
|
type: "ow:change",
|
|
9438
9524
|
nodes: [
|
|
9439
|
-
{ key: hrefKey, text:
|
|
9525
|
+
{ key: hrefKey, text: href },
|
|
9440
9526
|
{ key: labelKey, text: label },
|
|
9441
9527
|
{ key: NAV_COUNT_KEY, text: navCount },
|
|
9442
9528
|
{ key: NAV_ORDER_KEY, text: orderJson }
|
|
9443
9529
|
]
|
|
9444
9530
|
});
|
|
9531
|
+
postToParent2({ type: "ow:toast", title: "Link added", toastType: "success" });
|
|
9445
9532
|
addNavAfterAnchorRef.current = null;
|
|
9446
9533
|
setLinkPopover(null);
|
|
9447
9534
|
enforceLinkHrefs();
|
|
@@ -9680,12 +9767,55 @@ function OhhwellsBridge() {
|
|
|
9680
9767
|
bridgeRoot
|
|
9681
9768
|
) : null;
|
|
9682
9769
|
}
|
|
9770
|
+
|
|
9771
|
+
// src/ui/drop-indicator.tsx
|
|
9772
|
+
var React10 = __toESM(require("react"), 1);
|
|
9773
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
9774
|
+
var dropIndicatorVariants = cva(
|
|
9775
|
+
"ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
|
|
9776
|
+
{
|
|
9777
|
+
variants: {
|
|
9778
|
+
direction: {
|
|
9779
|
+
vertical: "h-6 w-[3px]",
|
|
9780
|
+
horizontal: "h-[3px] w-[200px]"
|
|
9781
|
+
},
|
|
9782
|
+
state: {
|
|
9783
|
+
default: "opacity-0",
|
|
9784
|
+
hover: "opacity-100",
|
|
9785
|
+
dragIdle: "opacity-40",
|
|
9786
|
+
dragActive: "opacity-100"
|
|
9787
|
+
}
|
|
9788
|
+
},
|
|
9789
|
+
defaultVariants: {
|
|
9790
|
+
direction: "vertical",
|
|
9791
|
+
state: "default"
|
|
9792
|
+
}
|
|
9793
|
+
}
|
|
9794
|
+
);
|
|
9795
|
+
var DropIndicator = React10.forwardRef(
|
|
9796
|
+
({ className, direction, state, ...props }, ref) => {
|
|
9797
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
9798
|
+
"div",
|
|
9799
|
+
{
|
|
9800
|
+
ref,
|
|
9801
|
+
"data-slot": "drop-indicator",
|
|
9802
|
+
"data-direction": direction ?? "vertical",
|
|
9803
|
+
"data-state": state ?? "default",
|
|
9804
|
+
"aria-hidden": "true",
|
|
9805
|
+
className: cn(dropIndicatorVariants({ direction, state }), className),
|
|
9806
|
+
...props
|
|
9807
|
+
}
|
|
9808
|
+
);
|
|
9809
|
+
}
|
|
9810
|
+
);
|
|
9811
|
+
DropIndicator.displayName = "DropIndicator";
|
|
9683
9812
|
// Annotate the CommonJS export names for ESM import in node:
|
|
9684
9813
|
0 && (module.exports = {
|
|
9685
9814
|
CustomToolbar,
|
|
9686
9815
|
CustomToolbarButton,
|
|
9687
9816
|
CustomToolbarDivider,
|
|
9688
9817
|
DragHandle,
|
|
9818
|
+
DropIndicator,
|
|
9689
9819
|
ItemActionToolbar,
|
|
9690
9820
|
ItemInteractionLayer,
|
|
9691
9821
|
LinkEditorPanel,
|
|
@@ -9700,6 +9830,7 @@ function OhhwellsBridge() {
|
|
|
9700
9830
|
TooltipProvider,
|
|
9701
9831
|
TooltipTrigger,
|
|
9702
9832
|
buildTarget,
|
|
9833
|
+
dropIndicatorVariants,
|
|
9703
9834
|
filterAvailablePages,
|
|
9704
9835
|
getEditModeInitialState,
|
|
9705
9836
|
isEditSessionActive,
|