@ohhwells/bridge 0.1.36 → 0.1.38-next.56
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 -0
- package/dist/index.cjs +2114 -618
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +51 -4
- package/dist/index.d.ts +51 -4
- package/dist/index.js +2112 -616
- package/dist/index.js.map +1 -1
- package/dist/styles.css +156 -21
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
// src/OhhwellsBridge.tsx
|
|
4
|
-
import
|
|
4
|
+
import React9, { useCallback as useCallback4, useEffect as useEffect7, useLayoutEffect as useLayoutEffect2, useRef as useRef4, useState as useState6 } from "react";
|
|
5
5
|
import { createRoot } from "react-dom/client";
|
|
6
6
|
import { flushSync } from "react-dom";
|
|
7
7
|
|
|
@@ -10,6 +10,9 @@ var linkHrefStore = /* @__PURE__ */ new Map();
|
|
|
10
10
|
function setStoredLinkHref(key, href) {
|
|
11
11
|
linkHrefStore.set(key, href);
|
|
12
12
|
}
|
|
13
|
+
function getStoredLinkHref(key) {
|
|
14
|
+
return linkHrefStore.get(key);
|
|
15
|
+
}
|
|
13
16
|
function enforceLinkHrefs() {
|
|
14
17
|
document.querySelectorAll("[data-ohw-href-key]").forEach((el) => {
|
|
15
18
|
const key = el.getAttribute("data-ohw-href-key") ?? "";
|
|
@@ -45,12 +48,13 @@ function useLinkHrefGuardian(...deps) {
|
|
|
45
48
|
}
|
|
46
49
|
|
|
47
50
|
// src/ui/SchedulingWidget.tsx
|
|
48
|
-
import { useEffect, useId, useMemo, useRef, useState as useState2 } from "react";
|
|
51
|
+
import { useCallback, useEffect, useId, useMemo, useRef, useState as useState2 } from "react";
|
|
49
52
|
|
|
50
53
|
// src/ui/EmailCaptureModal.tsx
|
|
51
54
|
import { useState } from "react";
|
|
52
55
|
import { Dialog } from "radix-ui";
|
|
53
56
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
57
|
+
var isValidEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
54
58
|
function Spinner() {
|
|
55
59
|
return /* @__PURE__ */ jsxs(
|
|
56
60
|
"svg",
|
|
@@ -84,12 +88,17 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
|
|
|
84
88
|
const [error, setError] = useState(null);
|
|
85
89
|
const isBook = title === "Confirm your spot";
|
|
86
90
|
const handleSubmit = async () => {
|
|
87
|
-
|
|
91
|
+
const trimmed = email.trim();
|
|
92
|
+
if (!trimmed) return;
|
|
93
|
+
if (!isValidEmail(trimmed)) {
|
|
94
|
+
setError("Please enter a valid email address.");
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
88
97
|
setLoading(true);
|
|
89
98
|
setError(null);
|
|
90
99
|
try {
|
|
91
|
-
await onSubmit(
|
|
92
|
-
setSubmittedEmail(
|
|
100
|
+
await onSubmit(trimmed);
|
|
101
|
+
setSubmittedEmail(trimmed);
|
|
93
102
|
setSuccess(true);
|
|
94
103
|
} catch (e) {
|
|
95
104
|
setError(e instanceof Error ? e.message : "Something went wrong. Please try again.");
|
|
@@ -164,7 +173,10 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
|
|
|
164
173
|
{
|
|
165
174
|
type: "email",
|
|
166
175
|
value: email,
|
|
167
|
-
onChange: (e) =>
|
|
176
|
+
onChange: (e) => {
|
|
177
|
+
setEmail(e.target.value);
|
|
178
|
+
if (error) setError(null);
|
|
179
|
+
},
|
|
168
180
|
onKeyDown: handleKeyDown,
|
|
169
181
|
placeholder: "hello@gmail.com",
|
|
170
182
|
autoFocus: true,
|
|
@@ -221,12 +233,20 @@ function formatClassTime(cls) {
|
|
|
221
233
|
const em = endTotal % 60;
|
|
222
234
|
return `${h}:${cls.startTime.minutes}-${eh}:${String(em).padStart(2, "0")}`;
|
|
223
235
|
}
|
|
236
|
+
function formatBookingLabel(cls) {
|
|
237
|
+
const price = cls.price;
|
|
238
|
+
const isFree = price === null || price === void 0 || `${price}` === "" || `${price}` === "0";
|
|
239
|
+
return isFree ? "Book for free" : `Book for ${cls.currency ?? ""} ${price}`.trim();
|
|
240
|
+
}
|
|
224
241
|
function getBookingsOnDate(cls, date) {
|
|
225
242
|
if (!cls.bookings?.length) return 0;
|
|
226
|
-
const
|
|
243
|
+
const target = new Date(date);
|
|
244
|
+
target.setHours(0, 0, 0, 0);
|
|
227
245
|
return cls.bookings.filter((b) => {
|
|
228
246
|
try {
|
|
229
|
-
|
|
247
|
+
const bookingDate = new Date(b.classDate);
|
|
248
|
+
bookingDate.setHours(0, 0, 0, 0);
|
|
249
|
+
return bookingDate.getTime() === target.getTime();
|
|
230
250
|
} catch {
|
|
231
251
|
return false;
|
|
232
252
|
}
|
|
@@ -530,7 +550,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
|
|
|
530
550
|
if (!cls.id) return;
|
|
531
551
|
onOpenModal?.(isFull ? "waitlist" : "book", cls.id, selectedDate);
|
|
532
552
|
},
|
|
533
|
-
children: isFull ? "Join Waitlist" :
|
|
553
|
+
children: isFull ? "Join Waitlist" : formatBookingLabel(cls)
|
|
534
554
|
}
|
|
535
555
|
)
|
|
536
556
|
] })
|
|
@@ -572,6 +592,17 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
572
592
|
const [isHovered, setIsHovered] = useState2(false);
|
|
573
593
|
const [modalState, setModalState] = useState2(null);
|
|
574
594
|
const switchScheduleIdRef = useRef(null);
|
|
595
|
+
const liveScheduleIdRef = useRef(null);
|
|
596
|
+
const refetchLiveSchedule = useCallback(async () => {
|
|
597
|
+
const id = liveScheduleIdRef.current;
|
|
598
|
+
if (!id) return;
|
|
599
|
+
try {
|
|
600
|
+
const res = await fetch(`${API_URL}/api/schedule/id/${id}`);
|
|
601
|
+
const data = await res.json();
|
|
602
|
+
if (data?.id) setSchedule(data);
|
|
603
|
+
} catch {
|
|
604
|
+
}
|
|
605
|
+
}, []);
|
|
575
606
|
const dates = useMemo(() => {
|
|
576
607
|
const today = /* @__PURE__ */ new Date();
|
|
577
608
|
today.setHours(0, 0, 0, 0);
|
|
@@ -591,6 +622,18 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
591
622
|
}
|
|
592
623
|
}
|
|
593
624
|
}, [schedule, dates]);
|
|
625
|
+
useEffect(() => {
|
|
626
|
+
if (typeof window === "undefined") return;
|
|
627
|
+
const onVisible = () => {
|
|
628
|
+
if (!document.hidden) void refetchLiveSchedule();
|
|
629
|
+
};
|
|
630
|
+
window.addEventListener("focus", refetchLiveSchedule);
|
|
631
|
+
document.addEventListener("visibilitychange", onVisible);
|
|
632
|
+
return () => {
|
|
633
|
+
window.removeEventListener("focus", refetchLiveSchedule);
|
|
634
|
+
document.removeEventListener("visibilitychange", onVisible);
|
|
635
|
+
};
|
|
636
|
+
}, [refetchLiveSchedule]);
|
|
594
637
|
useEffect(() => {
|
|
595
638
|
if (typeof window === "undefined") return;
|
|
596
639
|
const isInEditor = window.self !== window.top;
|
|
@@ -652,7 +695,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
652
695
|
setLoading(false);
|
|
653
696
|
return;
|
|
654
697
|
}
|
|
655
|
-
;
|
|
698
|
+
liveScheduleIdRef.current = effectiveId;
|
|
656
699
|
(async () => {
|
|
657
700
|
try {
|
|
658
701
|
const res = await fetch(`${API_URL}/api/schedule/id/${effectiveId}`);
|
|
@@ -709,18 +752,14 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
709
752
|
const data = await res.json().catch(() => ({}));
|
|
710
753
|
throw new Error(data?.message ?? "Something went wrong. Please try again.");
|
|
711
754
|
}
|
|
755
|
+
await refetchLiveSchedule();
|
|
712
756
|
};
|
|
713
757
|
const handleReplaceSchedule = () => {
|
|
714
758
|
setIsHovered(false);
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
insertAfter
|
|
720
|
-
}, "*");
|
|
721
|
-
} else {
|
|
722
|
-
window.parent.postMessage({ type: "ow:scheduling-not-connected", insertAfter }, "*");
|
|
723
|
-
}
|
|
759
|
+
window.parent.postMessage(
|
|
760
|
+
{ type: "ow:scheduling-not-connected", insertAfter, currentScheduleId: schedule?.id },
|
|
761
|
+
"*"
|
|
762
|
+
);
|
|
724
763
|
};
|
|
725
764
|
if (!inEditor && !loading && !schedule) return null;
|
|
726
765
|
const sectionId = `scheduling-${insertAfter}`;
|
|
@@ -763,7 +802,19 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
763
802
|
),
|
|
764
803
|
/* @__PURE__ */ jsxs2("div", { className: "max-w-[1280px] mx-auto flex flex-col items-center gap-16", children: [
|
|
765
804
|
/* @__PURE__ */ jsxs2("div", { className: "flex flex-col items-center gap-4", children: [
|
|
766
|
-
/* @__PURE__ */ jsx2(
|
|
805
|
+
/* @__PURE__ */ jsx2(
|
|
806
|
+
"h2",
|
|
807
|
+
{
|
|
808
|
+
className: "font-display text-center m-0 text-(--color-dark,#200C02)",
|
|
809
|
+
style: {
|
|
810
|
+
fontSize: "var(--fs-section-h2, clamp(40px, 4.4vw, 64px))",
|
|
811
|
+
fontWeight: "var(--font-weight-heading, 400)",
|
|
812
|
+
lineHeight: 1.05,
|
|
813
|
+
letterSpacing: "-0.02em"
|
|
814
|
+
},
|
|
815
|
+
children: schedule?.name ?? "Book an appointment"
|
|
816
|
+
}
|
|
817
|
+
),
|
|
767
818
|
schedule?.description && /* @__PURE__ */ jsx2("p", { className: "font-body text-body text-center m-0 text-(--color-accent,#A89B83)", children: schedule.description })
|
|
768
819
|
] }),
|
|
769
820
|
/* @__PURE__ */ jsxs2("div", { className: "w-full flex flex-col items-end gap-3", children: [
|
|
@@ -4349,6 +4400,7 @@ function ItemActionToolbar({
|
|
|
4349
4400
|
onEditLink,
|
|
4350
4401
|
onAddItem,
|
|
4351
4402
|
onMore,
|
|
4403
|
+
editLinkDisabled = false,
|
|
4352
4404
|
addItemDisabled = true,
|
|
4353
4405
|
moreDisabled = true,
|
|
4354
4406
|
tooltipSide = "bottom"
|
|
@@ -4357,10 +4409,12 @@ function ItemActionToolbar({
|
|
|
4357
4409
|
/* @__PURE__ */ jsx8(
|
|
4358
4410
|
ToolbarActionTooltip,
|
|
4359
4411
|
{
|
|
4360
|
-
label: "
|
|
4412
|
+
label: "Edit link",
|
|
4361
4413
|
side: tooltipSide,
|
|
4414
|
+
disabled: editLinkDisabled,
|
|
4362
4415
|
buttonProps: {
|
|
4363
4416
|
onMouseDown: (e) => {
|
|
4417
|
+
if (editLinkDisabled) return;
|
|
4364
4418
|
e.preventDefault();
|
|
4365
4419
|
e.stopPropagation();
|
|
4366
4420
|
onEditLink?.();
|
|
@@ -4532,9 +4586,223 @@ function ItemInteractionLayer({
|
|
|
4532
4586
|
);
|
|
4533
4587
|
}
|
|
4534
4588
|
|
|
4589
|
+
// src/ui/MediaOverlay.tsx
|
|
4590
|
+
import * as React6 from "react";
|
|
4591
|
+
import { Film, ImageIcon, Pause, Play, Volume2, VolumeX } from "lucide-react";
|
|
4592
|
+
|
|
4593
|
+
// src/ui/button.tsx
|
|
4594
|
+
import * as React5 from "react";
|
|
4595
|
+
import { Slot } from "radix-ui";
|
|
4596
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
4597
|
+
var buttonVariants = cva(
|
|
4598
|
+
"inline-flex items-center justify-center gap-1 whitespace-nowrap rounded-md text-sm font-medium transition-colors outline-none disabled:pointer-events-none disabled:opacity-50 min-w-[80px] px-3 py-2",
|
|
4599
|
+
{
|
|
4600
|
+
variants: {
|
|
4601
|
+
variant: {
|
|
4602
|
+
default: "bg-primary text-primary-foreground hover:opacity-90",
|
|
4603
|
+
outline: "border border-border bg-background text-foreground shadow-sm hover:bg-muted/80",
|
|
4604
|
+
ghost: "min-w-0 px-3 py-2 text-foreground hover:bg-muted/50"
|
|
4605
|
+
},
|
|
4606
|
+
size: {
|
|
4607
|
+
default: "h-9",
|
|
4608
|
+
sm: "h-8 min-w-[64px] px-2 py-1.5 text-sm"
|
|
4609
|
+
}
|
|
4610
|
+
},
|
|
4611
|
+
defaultVariants: {
|
|
4612
|
+
variant: "default",
|
|
4613
|
+
size: "default"
|
|
4614
|
+
}
|
|
4615
|
+
}
|
|
4616
|
+
);
|
|
4617
|
+
var Button = React5.forwardRef(
|
|
4618
|
+
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
4619
|
+
const Comp = asChild ? Slot.Root : "button";
|
|
4620
|
+
return /* @__PURE__ */ jsx10(
|
|
4621
|
+
Comp,
|
|
4622
|
+
{
|
|
4623
|
+
ref,
|
|
4624
|
+
"data-slot": "button",
|
|
4625
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
4626
|
+
...props
|
|
4627
|
+
}
|
|
4628
|
+
);
|
|
4629
|
+
}
|
|
4630
|
+
);
|
|
4631
|
+
Button.displayName = "Button";
|
|
4632
|
+
|
|
4633
|
+
// src/ui/MediaOverlay.tsx
|
|
4634
|
+
import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
4635
|
+
var MEDIA_UPLOAD_FADE_MS = 300;
|
|
4636
|
+
var VIDEO_SETTINGS_BAR_INSET = 8;
|
|
4637
|
+
var OVERLAY_BUTTON_STYLE = {
|
|
4638
|
+
pointerEvents: "auto",
|
|
4639
|
+
fontFamily: "Inter, sans-serif",
|
|
4640
|
+
fontSize: 12,
|
|
4641
|
+
color: "#000"
|
|
4642
|
+
};
|
|
4643
|
+
var SKELETON_CSS = `
|
|
4644
|
+
@keyframes ohw-media-shimmer {
|
|
4645
|
+
0% { transform: translateX(-100%); }
|
|
4646
|
+
100% { transform: translateX(100%); }
|
|
4647
|
+
}
|
|
4648
|
+
[data-ohw-media-skeleton] {
|
|
4649
|
+
overflow: hidden;
|
|
4650
|
+
background-color: #d1d5db; /* tailwind gray-300 */
|
|
4651
|
+
}
|
|
4652
|
+
[data-ohw-media-skeleton]::after {
|
|
4653
|
+
content: "";
|
|
4654
|
+
position: absolute;
|
|
4655
|
+
inset: 0;
|
|
4656
|
+
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.6), transparent);
|
|
4657
|
+
animation: ohw-media-shimmer 1.4s infinite;
|
|
4658
|
+
}
|
|
4659
|
+
`;
|
|
4660
|
+
function MediaOverlay({
|
|
4661
|
+
hover,
|
|
4662
|
+
isUploading,
|
|
4663
|
+
fadingOut = false,
|
|
4664
|
+
onFadeOutComplete,
|
|
4665
|
+
onReplace,
|
|
4666
|
+
onVideoSettingsChange
|
|
4667
|
+
}) {
|
|
4668
|
+
const { rect } = hover;
|
|
4669
|
+
const skeletonRef = React6.useRef(null);
|
|
4670
|
+
const isVideo = hover.elementType === "video";
|
|
4671
|
+
const autoplay = hover.videoAutoplay ?? true;
|
|
4672
|
+
const muted = hover.videoMuted ?? true;
|
|
4673
|
+
const box = {
|
|
4674
|
+
position: "fixed",
|
|
4675
|
+
top: rect.top,
|
|
4676
|
+
left: rect.left,
|
|
4677
|
+
width: rect.width,
|
|
4678
|
+
height: rect.height,
|
|
4679
|
+
zIndex: 2147483646
|
|
4680
|
+
};
|
|
4681
|
+
React6.useEffect(() => {
|
|
4682
|
+
if (!isUploading || !fadingOut || !skeletonRef.current) return;
|
|
4683
|
+
const anim = skeletonRef.current.animate([{ opacity: 1 }, { opacity: 0 }], {
|
|
4684
|
+
duration: MEDIA_UPLOAD_FADE_MS,
|
|
4685
|
+
easing: "ease-out",
|
|
4686
|
+
fill: "forwards"
|
|
4687
|
+
});
|
|
4688
|
+
anim.finished.then(() => onFadeOutComplete?.(hover.key)).catch(() => onFadeOutComplete?.(hover.key));
|
|
4689
|
+
return () => anim.cancel();
|
|
4690
|
+
}, [isUploading, fadingOut, onFadeOutComplete, hover.key]);
|
|
4691
|
+
if (isUploading) {
|
|
4692
|
+
return /* @__PURE__ */ jsx11(
|
|
4693
|
+
"div",
|
|
4694
|
+
{
|
|
4695
|
+
ref: skeletonRef,
|
|
4696
|
+
"data-ohw-bridge": "",
|
|
4697
|
+
"data-ohw-media-overlay": "",
|
|
4698
|
+
"data-ohw-media-skeleton": "",
|
|
4699
|
+
"aria-hidden": true,
|
|
4700
|
+
style: { ...box, pointerEvents: "none" },
|
|
4701
|
+
children: /* @__PURE__ */ jsx11("style", { children: SKELETON_CSS })
|
|
4702
|
+
}
|
|
4703
|
+
);
|
|
4704
|
+
}
|
|
4705
|
+
const settingsBar = isVideo && !hover.isDragOver ? /* @__PURE__ */ jsxs5(
|
|
4706
|
+
"div",
|
|
4707
|
+
{
|
|
4708
|
+
"data-ohw-bridge": "",
|
|
4709
|
+
"data-ohw-media-overlay": "",
|
|
4710
|
+
className: "flex items-center justify-center gap-1.5",
|
|
4711
|
+
style: {
|
|
4712
|
+
position: "fixed",
|
|
4713
|
+
top: rect.top + VIDEO_SETTINGS_BAR_INSET,
|
|
4714
|
+
left: rect.left,
|
|
4715
|
+
width: rect.width,
|
|
4716
|
+
zIndex: 2147483647,
|
|
4717
|
+
pointerEvents: "auto"
|
|
4718
|
+
},
|
|
4719
|
+
onClick: (e) => e.stopPropagation(),
|
|
4720
|
+
children: [
|
|
4721
|
+
/* @__PURE__ */ jsx11(
|
|
4722
|
+
Button,
|
|
4723
|
+
{
|
|
4724
|
+
"data-ohw-media-overlay": "",
|
|
4725
|
+
variant: "outline",
|
|
4726
|
+
size: "sm",
|
|
4727
|
+
className: "cursor-pointer hover:bg-background",
|
|
4728
|
+
style: { ...OVERLAY_BUTTON_STYLE, minWidth: 0, padding: "0 8px" },
|
|
4729
|
+
"aria-label": autoplay ? "Disable autoplay" : "Enable autoplay",
|
|
4730
|
+
title: autoplay ? "Autoplay on \u2014 click to disable" : "Autoplay off \u2014 click to enable",
|
|
4731
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
4732
|
+
onClick: (e) => {
|
|
4733
|
+
e.stopPropagation();
|
|
4734
|
+
onVideoSettingsChange?.(hover.key, { autoplay: !autoplay });
|
|
4735
|
+
},
|
|
4736
|
+
children: autoplay ? /* @__PURE__ */ jsx11(Pause, { size: 14 }) : /* @__PURE__ */ jsx11(Play, { size: 14 })
|
|
4737
|
+
}
|
|
4738
|
+
),
|
|
4739
|
+
/* @__PURE__ */ jsx11(
|
|
4740
|
+
Button,
|
|
4741
|
+
{
|
|
4742
|
+
"data-ohw-media-overlay": "",
|
|
4743
|
+
variant: "outline",
|
|
4744
|
+
size: "sm",
|
|
4745
|
+
className: "cursor-pointer hover:bg-background",
|
|
4746
|
+
style: { ...OVERLAY_BUTTON_STYLE, minWidth: 0, padding: "0 8px" },
|
|
4747
|
+
"aria-label": muted ? "Unmute video" : "Mute video",
|
|
4748
|
+
title: muted ? "Muted \u2014 click to unmute" : "Sound on \u2014 click to mute",
|
|
4749
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
4750
|
+
onClick: (e) => {
|
|
4751
|
+
e.stopPropagation();
|
|
4752
|
+
onVideoSettingsChange?.(hover.key, { muted: !muted });
|
|
4753
|
+
},
|
|
4754
|
+
children: muted ? /* @__PURE__ */ jsx11(VolumeX, { size: 14 }) : /* @__PURE__ */ jsx11(Volume2, { size: 14 })
|
|
4755
|
+
}
|
|
4756
|
+
)
|
|
4757
|
+
]
|
|
4758
|
+
}
|
|
4759
|
+
) : null;
|
|
4760
|
+
return /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
4761
|
+
settingsBar,
|
|
4762
|
+
/* @__PURE__ */ jsx11(
|
|
4763
|
+
"div",
|
|
4764
|
+
{
|
|
4765
|
+
"data-ohw-bridge": "",
|
|
4766
|
+
"data-ohw-media-overlay": "",
|
|
4767
|
+
className: "flex items-center justify-center cursor-pointer",
|
|
4768
|
+
style: {
|
|
4769
|
+
...box,
|
|
4770
|
+
// When text overlays this media, let clicks fall THROUGH to the text underneath. In the
|
|
4771
|
+
// parent this needed a whole `ow:click-at` round-trip to re-hit-test inside the iframe;
|
|
4772
|
+
// in-document, pointer-events does it natively. The button below opts back in, so
|
|
4773
|
+
// Replace still works.
|
|
4774
|
+
pointerEvents: hover.hasTextOverlap ? "none" : "auto",
|
|
4775
|
+
boxShadow: "inset 0 0 0 1.5px var(--color-primary)",
|
|
4776
|
+
background: "color-mix(in srgb, var(--color-primary) 20%, transparent)"
|
|
4777
|
+
},
|
|
4778
|
+
onClick: () => onReplace(hover.key),
|
|
4779
|
+
children: /* @__PURE__ */ jsxs5(
|
|
4780
|
+
Button,
|
|
4781
|
+
{
|
|
4782
|
+
"data-ohw-media-overlay": "",
|
|
4783
|
+
variant: "outline",
|
|
4784
|
+
size: "sm",
|
|
4785
|
+
className: "gap-1.5 cursor-pointer hover:bg-background",
|
|
4786
|
+
style: OVERLAY_BUTTON_STYLE,
|
|
4787
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
4788
|
+
onClick: (e) => {
|
|
4789
|
+
e.stopPropagation();
|
|
4790
|
+
onReplace(hover.key);
|
|
4791
|
+
},
|
|
4792
|
+
children: [
|
|
4793
|
+
isVideo ? /* @__PURE__ */ jsx11(Film, { size: 14 }) : /* @__PURE__ */ jsx11(ImageIcon, { size: 14 }),
|
|
4794
|
+
isVideo ? "Replace video" : "Replace image"
|
|
4795
|
+
]
|
|
4796
|
+
}
|
|
4797
|
+
)
|
|
4798
|
+
}
|
|
4799
|
+
)
|
|
4800
|
+
] });
|
|
4801
|
+
}
|
|
4802
|
+
|
|
4535
4803
|
// src/OhhwellsBridge.tsx
|
|
4536
|
-
import { createPortal } from "react-dom";
|
|
4537
|
-
import { usePathname, useRouter, useSearchParams } from "next/navigation";
|
|
4804
|
+
import { createPortal as createPortal2 } from "react-dom";
|
|
4805
|
+
import { usePathname as usePathname2, useRouter as useRouter2, useSearchParams } from "next/navigation";
|
|
4538
4806
|
|
|
4539
4807
|
// src/lib/session-search.ts
|
|
4540
4808
|
var STORAGE_KEY = "ohw-preserved-search";
|
|
@@ -4810,61 +5078,29 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
|
|
|
4810
5078
|
tick();
|
|
4811
5079
|
}
|
|
4812
5080
|
|
|
4813
|
-
// src/ui/
|
|
4814
|
-
import
|
|
4815
|
-
import { Dialog as DialogPrimitive } from "radix-ui";
|
|
4816
|
-
|
|
4817
|
-
// src/ui/icons.tsx
|
|
4818
|
-
import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
4819
|
-
function IconX({ className, ...props }) {
|
|
4820
|
-
return /* @__PURE__ */ jsxs5("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
|
|
4821
|
-
/* @__PURE__ */ jsx10("path", { d: "M18 6 6 18" }),
|
|
4822
|
-
/* @__PURE__ */ jsx10("path", { d: "m6 6 12 12" })
|
|
4823
|
-
] });
|
|
4824
|
-
}
|
|
4825
|
-
function IconChevronDown({ className, ...props }) {
|
|
4826
|
-
return /* @__PURE__ */ jsx10("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: /* @__PURE__ */ jsx10("path", { d: "m6 9 6 6 6-6" }) });
|
|
4827
|
-
}
|
|
4828
|
-
function IconFile({ className, ...props }) {
|
|
4829
|
-
return /* @__PURE__ */ jsxs5("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
|
|
4830
|
-
/* @__PURE__ */ jsx10("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }),
|
|
4831
|
-
/* @__PURE__ */ jsx10("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" })
|
|
4832
|
-
] });
|
|
4833
|
-
}
|
|
4834
|
-
function IconInfo({ className, ...props }) {
|
|
4835
|
-
return /* @__PURE__ */ jsxs5("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
|
|
4836
|
-
/* @__PURE__ */ jsx10("circle", { cx: "12", cy: "12", r: "10" }),
|
|
4837
|
-
/* @__PURE__ */ jsx10("path", { d: "M12 16v-4" }),
|
|
4838
|
-
/* @__PURE__ */ jsx10("path", { d: "M12 8h.01" })
|
|
4839
|
-
] });
|
|
4840
|
-
}
|
|
4841
|
-
function IconArrowRight({ className, ...props }) {
|
|
4842
|
-
return /* @__PURE__ */ jsxs5("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
|
|
4843
|
-
/* @__PURE__ */ jsx10("path", { d: "M5 12h14" }),
|
|
4844
|
-
/* @__PURE__ */ jsx10("path", { d: "m12 5 7 7-7 7" })
|
|
4845
|
-
] });
|
|
4846
|
-
}
|
|
4847
|
-
function IconSection({ className, ...props }) {
|
|
4848
|
-
return /* @__PURE__ */ jsxs5("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
|
|
4849
|
-
/* @__PURE__ */ jsx10("rect", { width: "18", height: "7", x: "3", y: "3", rx: "1" }),
|
|
4850
|
-
/* @__PURE__ */ jsx10("rect", { width: "9", height: "7", x: "3", y: "14", rx: "1" }),
|
|
4851
|
-
/* @__PURE__ */ jsx10("rect", { width: "5", height: "7", x: "16", y: "14", rx: "1" })
|
|
4852
|
-
] });
|
|
4853
|
-
}
|
|
5081
|
+
// src/ui/link-modal/LinkPopover.tsx
|
|
5082
|
+
import { useEffect as useEffect6 } from "react";
|
|
4854
5083
|
|
|
4855
5084
|
// src/ui/dialog.tsx
|
|
4856
|
-
import
|
|
4857
|
-
|
|
4858
|
-
|
|
5085
|
+
import * as React7 from "react";
|
|
5086
|
+
import { Dialog as DialogPrimitive } from "radix-ui";
|
|
5087
|
+
import { X } from "lucide-react";
|
|
5088
|
+
import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
5089
|
+
function Dialog2({
|
|
5090
|
+
...props
|
|
5091
|
+
}) {
|
|
5092
|
+
return /* @__PURE__ */ jsx12(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
|
|
4859
5093
|
}
|
|
4860
|
-
function DialogPortal({
|
|
4861
|
-
|
|
5094
|
+
function DialogPortal({
|
|
5095
|
+
...props
|
|
5096
|
+
}) {
|
|
5097
|
+
return /* @__PURE__ */ jsx12(DialogPrimitive.Portal, { ...props });
|
|
4862
5098
|
}
|
|
4863
5099
|
function DialogOverlay({
|
|
4864
5100
|
className,
|
|
4865
5101
|
...props
|
|
4866
5102
|
}) {
|
|
4867
|
-
return /* @__PURE__ */
|
|
5103
|
+
return /* @__PURE__ */ jsx12(
|
|
4868
5104
|
DialogPrimitive.Overlay,
|
|
4869
5105
|
{
|
|
4870
5106
|
"data-slot": "dialog-overlay",
|
|
@@ -4874,57 +5110,74 @@ function DialogOverlay({
|
|
|
4874
5110
|
}
|
|
4875
5111
|
);
|
|
4876
5112
|
}
|
|
4877
|
-
var DialogContent =
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
/* @__PURE__ */
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
4896
|
-
children
|
|
4897
|
-
|
|
4898
|
-
|
|
4899
|
-
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
|
|
4908
|
-
|
|
4909
|
-
|
|
4910
|
-
});
|
|
5113
|
+
var DialogContent = React7.forwardRef(
|
|
5114
|
+
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
5115
|
+
const positionMode = container ? "absolute" : "fixed";
|
|
5116
|
+
return /* @__PURE__ */ jsxs6(DialogPortal, { container: container ?? void 0, children: [
|
|
5117
|
+
/* @__PURE__ */ jsx12(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
5118
|
+
/* @__PURE__ */ jsxs6(
|
|
5119
|
+
DialogPrimitive.Content,
|
|
5120
|
+
{
|
|
5121
|
+
ref,
|
|
5122
|
+
"data-slot": "dialog-content",
|
|
5123
|
+
className: cn(
|
|
5124
|
+
positionMode,
|
|
5125
|
+
"left-1/2 top-1/2 z-[2147483647] flex w-full max-w-[483px] -translate-x-1/2 -translate-y-1/2 flex-col overflow-visible",
|
|
5126
|
+
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
5127
|
+
container ? "max-h-[calc(100%-32px)] max-w-[calc(100%-16px)]" : "max-h-[calc(100vh-32px)] max-w-[calc(100vw-16px)]",
|
|
5128
|
+
className
|
|
5129
|
+
),
|
|
5130
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
5131
|
+
...props,
|
|
5132
|
+
children: [
|
|
5133
|
+
children,
|
|
5134
|
+
showCloseButton ? /* @__PURE__ */ jsx12(
|
|
5135
|
+
DialogPrimitive.Close,
|
|
5136
|
+
{
|
|
5137
|
+
type: "button",
|
|
5138
|
+
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
5139
|
+
"aria-label": "Close",
|
|
5140
|
+
children: /* @__PURE__ */ jsx12(X, { size: 16, "aria-hidden": true })
|
|
5141
|
+
}
|
|
5142
|
+
) : null
|
|
5143
|
+
]
|
|
5144
|
+
}
|
|
5145
|
+
)
|
|
5146
|
+
] });
|
|
5147
|
+
}
|
|
5148
|
+
);
|
|
4911
5149
|
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
4912
|
-
function DialogHeader({
|
|
4913
|
-
|
|
5150
|
+
function DialogHeader({
|
|
5151
|
+
className,
|
|
5152
|
+
...props
|
|
5153
|
+
}) {
|
|
5154
|
+
return /* @__PURE__ */ jsx12("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
4914
5155
|
}
|
|
4915
|
-
function DialogFooter({
|
|
4916
|
-
|
|
5156
|
+
function DialogFooter({
|
|
5157
|
+
className,
|
|
5158
|
+
...props
|
|
5159
|
+
}) {
|
|
5160
|
+
return /* @__PURE__ */ jsx12(
|
|
5161
|
+
"div",
|
|
5162
|
+
{
|
|
5163
|
+
className: cn("flex items-center justify-end gap-2", className),
|
|
5164
|
+
...props
|
|
5165
|
+
}
|
|
5166
|
+
);
|
|
4917
5167
|
}
|
|
4918
|
-
var DialogTitle =
|
|
5168
|
+
var DialogTitle = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx12(
|
|
4919
5169
|
DialogPrimitive.Title,
|
|
4920
5170
|
{
|
|
4921
5171
|
ref,
|
|
4922
|
-
className: cn(
|
|
5172
|
+
className: cn(
|
|
5173
|
+
"text-lg font-semibold leading-none tracking-tight text-card-foreground",
|
|
5174
|
+
className
|
|
5175
|
+
),
|
|
4923
5176
|
...props
|
|
4924
5177
|
}
|
|
4925
5178
|
));
|
|
4926
5179
|
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
4927
|
-
var DialogDescription =
|
|
5180
|
+
var DialogDescription = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx12(
|
|
4928
5181
|
DialogPrimitive.Description,
|
|
4929
5182
|
{
|
|
4930
5183
|
ref,
|
|
@@ -4935,59 +5188,40 @@ var DialogDescription = React5.forwardRef(({ className, ...props }, ref) => /* @
|
|
|
4935
5188
|
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
4936
5189
|
var DialogClose = DialogPrimitive.Close;
|
|
4937
5190
|
|
|
4938
|
-
// src/ui/
|
|
4939
|
-
import
|
|
4940
|
-
import { Slot } from "radix-ui";
|
|
4941
|
-
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
4942
|
-
var buttonVariants = cva(
|
|
4943
|
-
"inline-flex items-center justify-center gap-1 whitespace-nowrap rounded-md text-sm font-medium transition-colors outline-none disabled:pointer-events-none disabled:opacity-50 min-w-[80px] px-3 py-2",
|
|
4944
|
-
{
|
|
4945
|
-
variants: {
|
|
4946
|
-
variant: {
|
|
4947
|
-
default: "bg-primary text-primary-foreground hover:opacity-90",
|
|
4948
|
-
outline: "border border-border bg-background text-foreground shadow-sm hover:bg-muted/80",
|
|
4949
|
-
ghost: "min-w-0 px-3 py-2 text-foreground hover:bg-muted/50"
|
|
4950
|
-
},
|
|
4951
|
-
size: {
|
|
4952
|
-
default: "h-9",
|
|
4953
|
-
sm: "h-8 min-w-[64px] px-2 py-1.5 text-sm"
|
|
4954
|
-
}
|
|
4955
|
-
},
|
|
4956
|
-
defaultVariants: {
|
|
4957
|
-
variant: "default",
|
|
4958
|
-
size: "default"
|
|
4959
|
-
}
|
|
4960
|
-
}
|
|
4961
|
-
);
|
|
4962
|
-
var Button = React6.forwardRef(
|
|
4963
|
-
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
4964
|
-
const Comp = asChild ? Slot.Root : "button";
|
|
4965
|
-
return /* @__PURE__ */ jsx12(
|
|
4966
|
-
Comp,
|
|
4967
|
-
{
|
|
4968
|
-
ref,
|
|
4969
|
-
"data-slot": "button",
|
|
4970
|
-
className: cn(buttonVariants({ variant, size, className })),
|
|
4971
|
-
...props
|
|
4972
|
-
}
|
|
4973
|
-
);
|
|
4974
|
-
}
|
|
4975
|
-
);
|
|
4976
|
-
Button.displayName = "Button";
|
|
5191
|
+
// src/ui/link-modal/LinkEditorPanel.tsx
|
|
5192
|
+
import { Info, X as X3 } from "lucide-react";
|
|
4977
5193
|
|
|
4978
5194
|
// src/ui/link-modal/DestinationBreadcrumb.tsx
|
|
5195
|
+
import { ArrowRight, File, GalleryVertical } from "lucide-react";
|
|
4979
5196
|
import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
4980
|
-
function DestinationBreadcrumb({
|
|
5197
|
+
function DestinationBreadcrumb({
|
|
5198
|
+
pageTitle,
|
|
5199
|
+
sectionLabel
|
|
5200
|
+
}) {
|
|
4981
5201
|
return /* @__PURE__ */ jsxs7("div", { className: "flex w-full flex-col gap-2", children: [
|
|
4982
|
-
/* @__PURE__ */ jsx13("p", { className: "text-sm font-medium text-foreground", children: "Destination" }),
|
|
5202
|
+
/* @__PURE__ */ jsx13("p", { className: "text-sm font-medium! text-foreground m-0", children: "Destination" }),
|
|
4983
5203
|
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-3", children: [
|
|
4984
5204
|
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
|
|
4985
|
-
/* @__PURE__ */ jsx13(
|
|
4986
|
-
/* @__PURE__ */ jsx13("span", { className: "text-sm font-medium leading-none text-foreground", children: pageTitle })
|
|
5205
|
+
/* @__PURE__ */ jsx13(File, { size: 16, className: "shrink-0 text-foreground", "aria-hidden": true }),
|
|
5206
|
+
/* @__PURE__ */ jsx13("span", { className: "text-sm font-medium leading-none text-foreground!", children: pageTitle })
|
|
4987
5207
|
] }),
|
|
4988
|
-
/* @__PURE__ */ jsx13(
|
|
5208
|
+
/* @__PURE__ */ jsx13(
|
|
5209
|
+
ArrowRight,
|
|
5210
|
+
{
|
|
5211
|
+
size: 16,
|
|
5212
|
+
className: "shrink-0 text-muted-foreground",
|
|
5213
|
+
"aria-hidden": true
|
|
5214
|
+
}
|
|
5215
|
+
),
|
|
4989
5216
|
/* @__PURE__ */ jsxs7("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
|
|
4990
|
-
/* @__PURE__ */ jsx13(
|
|
5217
|
+
/* @__PURE__ */ jsx13(
|
|
5218
|
+
GalleryVertical,
|
|
5219
|
+
{
|
|
5220
|
+
size: 16,
|
|
5221
|
+
className: "shrink-0 text-foreground",
|
|
5222
|
+
"aria-hidden": true
|
|
5223
|
+
}
|
|
5224
|
+
),
|
|
4991
5225
|
/* @__PURE__ */ jsx13("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
|
|
4992
5226
|
] })
|
|
4993
5227
|
] })
|
|
@@ -4995,8 +5229,13 @@ function DestinationBreadcrumb({ pageTitle, sectionLabel }) {
|
|
|
4995
5229
|
}
|
|
4996
5230
|
|
|
4997
5231
|
// src/ui/link-modal/SectionTreeItem.tsx
|
|
5232
|
+
import { GalleryVertical as GalleryVertical2 } from "lucide-react";
|
|
4998
5233
|
import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
4999
|
-
function SectionTreeItem({
|
|
5234
|
+
function SectionTreeItem({
|
|
5235
|
+
section,
|
|
5236
|
+
onSelect,
|
|
5237
|
+
selected
|
|
5238
|
+
}) {
|
|
5000
5239
|
const interactive = Boolean(onSelect);
|
|
5001
5240
|
return /* @__PURE__ */ jsxs8("div", { className: "flex h-9 w-full items-end pl-3", children: [
|
|
5002
5241
|
/* @__PURE__ */ jsx14(
|
|
@@ -5024,30 +5263,28 @@ function SectionTreeItem({ section, onSelect, selected }) {
|
|
|
5024
5263
|
interactive && selected && "border-primary"
|
|
5025
5264
|
),
|
|
5026
5265
|
children: [
|
|
5027
|
-
/* @__PURE__ */ jsx14(
|
|
5266
|
+
/* @__PURE__ */ jsx14(
|
|
5267
|
+
GalleryVertical2,
|
|
5268
|
+
{
|
|
5269
|
+
size: 16,
|
|
5270
|
+
className: "shrink-0 text-foreground",
|
|
5271
|
+
"aria-hidden": true
|
|
5272
|
+
}
|
|
5273
|
+
),
|
|
5028
5274
|
/* @__PURE__ */ jsx14("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
|
|
5029
5275
|
]
|
|
5030
5276
|
}
|
|
5031
5277
|
)
|
|
5032
5278
|
] });
|
|
5033
5279
|
}
|
|
5034
|
-
function SectionPickerList({ sections, onSelect }) {
|
|
5035
|
-
if (sections.length === 0) {
|
|
5036
|
-
return /* @__PURE__ */ jsx14("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." });
|
|
5037
|
-
}
|
|
5038
|
-
return /* @__PURE__ */ jsxs8("div", { className: "flex flex-col gap-1", children: [
|
|
5039
|
-
/* @__PURE__ */ jsx14("p", { className: "text-sm text-muted-foreground", children: "Pick a section this link should scroll to." }),
|
|
5040
|
-
sections.map((section) => /* @__PURE__ */ jsx14(SectionTreeItem, { section, onSelect }, section.id))
|
|
5041
|
-
] });
|
|
5042
|
-
}
|
|
5043
5280
|
|
|
5044
5281
|
// src/ui/link-modal/UrlOrPageInput.tsx
|
|
5045
|
-
import { useId as useId2, useRef as
|
|
5282
|
+
import { useEffect as useEffect3, useId as useId2, useRef as useRef3, useState as useState3 } from "react";
|
|
5046
5283
|
|
|
5047
5284
|
// src/ui/input.tsx
|
|
5048
|
-
import * as
|
|
5285
|
+
import * as React8 from "react";
|
|
5049
5286
|
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
5050
|
-
var Input =
|
|
5287
|
+
var Input = React8.forwardRef(
|
|
5051
5288
|
({ className, type, ...props }, ref) => {
|
|
5052
5289
|
return /* @__PURE__ */ jsx15(
|
|
5053
5290
|
"input",
|
|
@@ -5081,8 +5318,11 @@ function Label({ className, ...props }) {
|
|
|
5081
5318
|
}
|
|
5082
5319
|
|
|
5083
5320
|
// src/ui/link-modal/UrlOrPageInput.tsx
|
|
5321
|
+
import { ChevronDown, File as File2, X as X2 } from "lucide-react";
|
|
5084
5322
|
import { jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
5085
|
-
function FieldChevron({
|
|
5323
|
+
function FieldChevron({
|
|
5324
|
+
onClick
|
|
5325
|
+
}) {
|
|
5086
5326
|
return /* @__PURE__ */ jsx17(
|
|
5087
5327
|
"button",
|
|
5088
5328
|
{
|
|
@@ -5091,7 +5331,7 @@ function FieldChevron({ onClick }) {
|
|
|
5091
5331
|
onClick,
|
|
5092
5332
|
"aria-label": "Open page list",
|
|
5093
5333
|
tabIndex: -1,
|
|
5094
|
-
children: /* @__PURE__ */ jsx17(
|
|
5334
|
+
children: /* @__PURE__ */ jsx17(ChevronDown, { size: 16 })
|
|
5095
5335
|
}
|
|
5096
5336
|
);
|
|
5097
5337
|
}
|
|
@@ -5108,8 +5348,30 @@ function UrlOrPageInput({
|
|
|
5108
5348
|
urlError
|
|
5109
5349
|
}) {
|
|
5110
5350
|
const inputId = useId2();
|
|
5111
|
-
const inputRef =
|
|
5351
|
+
const inputRef = useRef3(null);
|
|
5352
|
+
const rootRef = useRef3(null);
|
|
5112
5353
|
const [isFocused, setIsFocused] = useState3(false);
|
|
5354
|
+
useEffect3(() => {
|
|
5355
|
+
if (!dropdownOpen) return;
|
|
5356
|
+
const isOutside = (e) => {
|
|
5357
|
+
const root = rootRef.current;
|
|
5358
|
+
if (!root) return true;
|
|
5359
|
+
const path = typeof e.composedPath === "function" ? e.composedPath() : [];
|
|
5360
|
+
if (path.includes(root)) return false;
|
|
5361
|
+
const target = e.target;
|
|
5362
|
+
return !(target instanceof Node && root.contains(target));
|
|
5363
|
+
};
|
|
5364
|
+
const closeIfOutside = (e) => {
|
|
5365
|
+
if (!isOutside(e)) return;
|
|
5366
|
+
onDropdownOpenChange(false);
|
|
5367
|
+
};
|
|
5368
|
+
document.addEventListener("pointerdown", closeIfOutside, true);
|
|
5369
|
+
document.addEventListener("mousedown", closeIfOutside, true);
|
|
5370
|
+
return () => {
|
|
5371
|
+
document.removeEventListener("pointerdown", closeIfOutside, true);
|
|
5372
|
+
document.removeEventListener("mousedown", closeIfOutside, true);
|
|
5373
|
+
};
|
|
5374
|
+
}, [dropdownOpen, onDropdownOpenChange]);
|
|
5113
5375
|
const openDropdown = () => {
|
|
5114
5376
|
if (readOnly || filteredPages.length === 0) return;
|
|
5115
5377
|
onDropdownOpenChange(true);
|
|
@@ -5132,9 +5394,16 @@ function UrlOrPageInput({
|
|
|
5132
5394
|
);
|
|
5133
5395
|
return /* @__PURE__ */ jsxs9("div", { className: "flex w-full flex-col gap-2 p-0", children: [
|
|
5134
5396
|
/* @__PURE__ */ jsx17(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
|
|
5135
|
-
/* @__PURE__ */ jsxs9("div", { className: "relative w-full", children: [
|
|
5397
|
+
/* @__PURE__ */ jsxs9("div", { ref: rootRef, className: "relative w-full", children: [
|
|
5136
5398
|
/* @__PURE__ */ jsxs9("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
|
|
5137
|
-
selectedPage ? /* @__PURE__ */ jsx17("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ jsx17(
|
|
5399
|
+
selectedPage ? /* @__PURE__ */ jsx17("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ jsx17(
|
|
5400
|
+
File2,
|
|
5401
|
+
{
|
|
5402
|
+
size: 16,
|
|
5403
|
+
className: "shrink-0 text-foreground",
|
|
5404
|
+
"aria-hidden": true
|
|
5405
|
+
}
|
|
5406
|
+
) }) : null,
|
|
5138
5407
|
readOnly ? /* @__PURE__ */ jsx17("span", { className: "min-w-0 flex-1 truncate text-sm leading-5 text-foreground", children: selectedPage?.title ?? value }) : /* @__PURE__ */ jsx17(
|
|
5139
5408
|
Input,
|
|
5140
5409
|
{
|
|
@@ -5146,7 +5415,14 @@ function UrlOrPageInput({
|
|
|
5146
5415
|
setIsFocused(true);
|
|
5147
5416
|
if (!selectedPage) openDropdown();
|
|
5148
5417
|
},
|
|
5149
|
-
onBlur: () =>
|
|
5418
|
+
onBlur: () => {
|
|
5419
|
+
setIsFocused(false);
|
|
5420
|
+
requestAnimationFrame(() => {
|
|
5421
|
+
if (!rootRef.current?.contains(document.activeElement)) {
|
|
5422
|
+
onDropdownOpenChange(false);
|
|
5423
|
+
}
|
|
5424
|
+
});
|
|
5425
|
+
},
|
|
5150
5426
|
placeholder,
|
|
5151
5427
|
className: cn(
|
|
5152
5428
|
"min-w-0 flex-1 truncate border-0 bg-transparent p-0 text-sm font-normal leading-5 shadow-none outline-none ring-0 caret-foreground",
|
|
@@ -5162,7 +5438,7 @@ function UrlOrPageInput({
|
|
|
5162
5438
|
onMouseDown: clearSelection,
|
|
5163
5439
|
"aria-label": "Clear selected page",
|
|
5164
5440
|
tabIndex: -1,
|
|
5165
|
-
children: /* @__PURE__ */ jsx17(
|
|
5441
|
+
children: /* @__PURE__ */ jsx17(X2, { size: 16, "aria-hidden": true })
|
|
5166
5442
|
}
|
|
5167
5443
|
) : null,
|
|
5168
5444
|
!readOnly ? /* @__PURE__ */ jsx17(FieldChevron, { onClick: toggleDropdown }) : null
|
|
@@ -5171,7 +5447,7 @@ function UrlOrPageInput({
|
|
|
5171
5447
|
"div",
|
|
5172
5448
|
{
|
|
5173
5449
|
"data-ohw-link-page-dropdown": "",
|
|
5174
|
-
className: "absolute left-0 right-0
|
|
5450
|
+
className: "absolute left-0 right-0 top-[calc(100%+4px)] z-50 max-h-48 overflow-auto rounded-lg border border-border bg-popover py-1 shadow-lg",
|
|
5175
5451
|
onMouseDown: (e) => e.preventDefault(),
|
|
5176
5452
|
children: filteredPages.map((page) => /* @__PURE__ */ jsxs9(
|
|
5177
5453
|
"button",
|
|
@@ -5180,7 +5456,7 @@ function UrlOrPageInput({
|
|
|
5180
5456
|
className: "flex h-9 w-full items-center gap-2 border-0 bg-transparent px-3 text-left text-sm leading-5 text-foreground outline-none hover:bg-muted",
|
|
5181
5457
|
onClick: () => onPageSelect(page),
|
|
5182
5458
|
children: [
|
|
5183
|
-
/* @__PURE__ */ jsx17(
|
|
5459
|
+
/* @__PURE__ */ jsx17(File2, { size: 16, className: "shrink-0", "aria-hidden": true }),
|
|
5184
5460
|
/* @__PURE__ */ jsx17("span", { className: "truncate", children: page.title })
|
|
5185
5461
|
]
|
|
5186
5462
|
},
|
|
@@ -5193,41 +5469,378 @@ function UrlOrPageInput({
|
|
|
5193
5469
|
] });
|
|
5194
5470
|
}
|
|
5195
5471
|
|
|
5196
|
-
// src/ui/link-modal/
|
|
5197
|
-
import {
|
|
5198
|
-
function
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5208
|
-
})
|
|
5209
|
-
|
|
5210
|
-
|
|
5211
|
-
|
|
5212
|
-
|
|
5213
|
-
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5472
|
+
// src/ui/link-modal/LinkEditorPanel.tsx
|
|
5473
|
+
import { Fragment as Fragment3, jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
5474
|
+
function LinkEditorPanel({ state, onClose }) {
|
|
5475
|
+
const isCancel = state.secondaryLabel === "Cancel" || state.secondaryLabel === "Back to sections";
|
|
5476
|
+
return /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
5477
|
+
/* @__PURE__ */ jsx18(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx18(
|
|
5478
|
+
"button",
|
|
5479
|
+
{
|
|
5480
|
+
type: "button",
|
|
5481
|
+
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50 h-7",
|
|
5482
|
+
"aria-label": "Close",
|
|
5483
|
+
onClick: onClose,
|
|
5484
|
+
children: /* @__PURE__ */ jsx18(X3, { size: 16, "aria-hidden": true })
|
|
5485
|
+
}
|
|
5486
|
+
) }),
|
|
5487
|
+
/* @__PURE__ */ jsx18(DialogHeader, { className: "w-full gap-1.5 p-6 pr-12", children: /* @__PURE__ */ jsx18(DialogTitle, { className: "m-0 w-full break-words", children: state.title }) }),
|
|
5488
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
|
|
5489
|
+
state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ jsx18(
|
|
5490
|
+
DestinationBreadcrumb,
|
|
5491
|
+
{
|
|
5492
|
+
pageTitle: state.selectedPage.title,
|
|
5493
|
+
sectionLabel: state.selectedSection.label
|
|
5494
|
+
}
|
|
5495
|
+
) : /* @__PURE__ */ jsx18(
|
|
5496
|
+
UrlOrPageInput,
|
|
5497
|
+
{
|
|
5498
|
+
value: state.searchValue,
|
|
5499
|
+
selectedPage: state.selectedPage,
|
|
5500
|
+
dropdownOpen: state.dropdownOpen,
|
|
5501
|
+
onDropdownOpenChange: state.setDropdownOpen,
|
|
5502
|
+
filteredPages: state.filteredPages,
|
|
5503
|
+
onInputChange: state.handleInputChange,
|
|
5504
|
+
onPageSelect: state.handlePageSelect,
|
|
5505
|
+
urlError: state.urlError
|
|
5506
|
+
}
|
|
5507
|
+
),
|
|
5508
|
+
state.showChooseSection ? /* @__PURE__ */ jsxs10("div", { className: "flex flex-col justify-center gap-2", children: [
|
|
5509
|
+
/* @__PURE__ */ jsx18(
|
|
5510
|
+
Button,
|
|
5511
|
+
{
|
|
5512
|
+
type: "button",
|
|
5513
|
+
variant: "outline",
|
|
5514
|
+
className: "w-fit cursor-pointer",
|
|
5515
|
+
size: "sm",
|
|
5516
|
+
onClick: state.handleChooseSection,
|
|
5517
|
+
children: "Choose a section"
|
|
5518
|
+
}
|
|
5519
|
+
),
|
|
5520
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
|
|
5521
|
+
/* @__PURE__ */ jsx18(Info, { size: 16, className: "shrink-0", "aria-hidden": true }),
|
|
5522
|
+
/* @__PURE__ */ jsx18("span", { children: "Pick a section this link should scroll to." })
|
|
5523
|
+
] })
|
|
5524
|
+
] }) : null,
|
|
5525
|
+
state.showSectionRow && state.selectedSection ? /* @__PURE__ */ jsx18(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
|
|
5526
|
+
] }),
|
|
5527
|
+
/* @__PURE__ */ jsxs10(DialogFooter, { className: "w-full px-6 pb-6", children: [
|
|
5528
|
+
/* @__PURE__ */ jsx18(
|
|
5529
|
+
Button,
|
|
5530
|
+
{
|
|
5531
|
+
type: "button",
|
|
5532
|
+
variant: isCancel ? "outline" : "ghost",
|
|
5533
|
+
className: "leading-6 shadow-none cursor-pointer",
|
|
5534
|
+
style: isCancel ? {
|
|
5535
|
+
backgroundColor: "var(--ohw-background)",
|
|
5536
|
+
borderColor: "var(--ohw-border)",
|
|
5537
|
+
color: "var(--ohw-foreground)"
|
|
5538
|
+
} : void 0,
|
|
5539
|
+
onClick: state.handleSecondary,
|
|
5540
|
+
children: state.secondaryLabel
|
|
5541
|
+
}
|
|
5542
|
+
),
|
|
5543
|
+
/* @__PURE__ */ jsx18(
|
|
5544
|
+
Button,
|
|
5545
|
+
{
|
|
5546
|
+
type: "button",
|
|
5547
|
+
className: "border-0 leading-6 shadow-none hover:opacity-90 disabled:opacity-50 cursor-pointer",
|
|
5548
|
+
style: {
|
|
5549
|
+
backgroundColor: "var(--ohw-primary)",
|
|
5550
|
+
color: "var(--ohw-primary-foreground)"
|
|
5551
|
+
},
|
|
5552
|
+
disabled: !state.isValid,
|
|
5553
|
+
onClick: state.handleSubmit,
|
|
5554
|
+
children: state.submitLabel
|
|
5555
|
+
}
|
|
5556
|
+
)
|
|
5557
|
+
] })
|
|
5558
|
+
] });
|
|
5559
|
+
}
|
|
5560
|
+
|
|
5561
|
+
// src/ui/link-modal/SectionPickerOverlay.tsx
|
|
5562
|
+
import { useCallback as useCallback2, useEffect as useEffect4, useMemo as useMemo2, useState as useState4 } from "react";
|
|
5563
|
+
import { createPortal } from "react-dom";
|
|
5564
|
+
import { ArrowLeft, Check } from "lucide-react";
|
|
5565
|
+
import { usePathname, useRouter } from "next/navigation";
|
|
5566
|
+
import { jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
5567
|
+
var DIM_OVERLAY = "rgba(0, 0, 0, 0.45)";
|
|
5568
|
+
function rectsEqual(a, b) {
|
|
5569
|
+
if (a.size !== b.size) return false;
|
|
5570
|
+
for (const [id, rect] of a) {
|
|
5571
|
+
const other = b.get(id);
|
|
5572
|
+
if (!other || rect.top !== other.top || rect.left !== other.left || rect.width !== other.width || rect.height !== other.height) {
|
|
5573
|
+
return false;
|
|
5574
|
+
}
|
|
5575
|
+
}
|
|
5576
|
+
return true;
|
|
5577
|
+
}
|
|
5578
|
+
function useSectionRects(sectionIdsKey, enabled) {
|
|
5579
|
+
const [rects, setRects] = useState4(/* @__PURE__ */ new Map());
|
|
5580
|
+
const sectionIds = useMemo2(
|
|
5581
|
+
() => sectionIdsKey ? sectionIdsKey.split("\0") : [],
|
|
5582
|
+
[sectionIdsKey]
|
|
5583
|
+
);
|
|
5584
|
+
useEffect4(() => {
|
|
5585
|
+
if (!enabled || sectionIds.length === 0) {
|
|
5586
|
+
setRects((prev) => prev.size === 0 ? prev : /* @__PURE__ */ new Map());
|
|
5587
|
+
return;
|
|
5588
|
+
}
|
|
5589
|
+
const update = () => {
|
|
5590
|
+
const next = /* @__PURE__ */ new Map();
|
|
5591
|
+
for (const id of sectionIds) {
|
|
5592
|
+
const el = document.querySelector(
|
|
5593
|
+
`[data-ohw-section="${CSS.escape(id)}"]`
|
|
5594
|
+
);
|
|
5595
|
+
if (el) next.set(id, el.getBoundingClientRect());
|
|
5596
|
+
}
|
|
5597
|
+
setRects((prev) => rectsEqual(prev, next) ? prev : next);
|
|
5598
|
+
};
|
|
5599
|
+
update();
|
|
5600
|
+
const opts = { capture: true, passive: true };
|
|
5601
|
+
window.addEventListener("scroll", update, opts);
|
|
5602
|
+
window.addEventListener("resize", update);
|
|
5603
|
+
const vv = window.visualViewport;
|
|
5604
|
+
vv?.addEventListener("resize", update);
|
|
5605
|
+
vv?.addEventListener("scroll", update);
|
|
5606
|
+
const ro = new ResizeObserver(update);
|
|
5607
|
+
for (const id of sectionIds) {
|
|
5608
|
+
const el = document.querySelector(
|
|
5609
|
+
`[data-ohw-section="${CSS.escape(id)}"]`
|
|
5610
|
+
);
|
|
5611
|
+
if (el) ro.observe(el);
|
|
5612
|
+
}
|
|
5613
|
+
return () => {
|
|
5614
|
+
window.removeEventListener("scroll", update, opts);
|
|
5615
|
+
window.removeEventListener("resize", update);
|
|
5616
|
+
vv?.removeEventListener("resize", update);
|
|
5617
|
+
vv?.removeEventListener("scroll", update);
|
|
5618
|
+
ro.disconnect();
|
|
5619
|
+
};
|
|
5620
|
+
}, [sectionIds, enabled]);
|
|
5621
|
+
return rects;
|
|
5622
|
+
}
|
|
5623
|
+
function SectionPickerOverlay({
|
|
5624
|
+
pagePath,
|
|
5625
|
+
sections,
|
|
5626
|
+
onBack,
|
|
5627
|
+
onSelect
|
|
5628
|
+
}) {
|
|
5629
|
+
const router = useRouter();
|
|
5630
|
+
const pathname = usePathname();
|
|
5631
|
+
const [selectedId, setSelectedId] = useState4(null);
|
|
5632
|
+
const [hoveredId, setHoveredId] = useState4(null);
|
|
5633
|
+
const [chromeClip, setChromeClip] = useState4(
|
|
5634
|
+
() => ({
|
|
5635
|
+
top: 0,
|
|
5636
|
+
bottom: typeof window !== "undefined" ? window.innerHeight : 0
|
|
5637
|
+
})
|
|
5638
|
+
);
|
|
5639
|
+
const normalizedTarget = normalizePath(pagePath);
|
|
5640
|
+
const isOnTargetPage = normalizePath(pathname) === normalizedTarget;
|
|
5641
|
+
useEffect4(() => {
|
|
5642
|
+
if (isOnTargetPage) return;
|
|
5643
|
+
const search = readPreservedSearch();
|
|
5644
|
+
router.push(`${normalizedTarget}${search}`);
|
|
5645
|
+
}, [isOnTargetPage, normalizedTarget, router]);
|
|
5646
|
+
useEffect4(() => {
|
|
5647
|
+
document.documentElement.setAttribute("data-ohw-section-picking", "");
|
|
5648
|
+
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => {
|
|
5649
|
+
el.removeAttribute("data-ohw-hovered");
|
|
5650
|
+
});
|
|
5651
|
+
return () => {
|
|
5652
|
+
document.documentElement.removeAttribute("data-ohw-section-picking");
|
|
5653
|
+
};
|
|
5654
|
+
}, []);
|
|
5655
|
+
useEffect4(() => {
|
|
5656
|
+
const applyClip = (iframeOffsetTop, visibleCanvasTop, canvasH) => {
|
|
5657
|
+
const top = Math.max(0, visibleCanvasTop - iframeOffsetTop);
|
|
5658
|
+
const bottom = Math.min(
|
|
5659
|
+
window.innerHeight,
|
|
5660
|
+
visibleCanvasTop + canvasH - iframeOffsetTop
|
|
5661
|
+
);
|
|
5662
|
+
setChromeClip(
|
|
5663
|
+
(prev) => prev.top === top && prev.bottom === bottom ? prev : { top, bottom: Math.max(top, bottom) }
|
|
5664
|
+
);
|
|
5665
|
+
};
|
|
5666
|
+
const onParentScroll = (e) => {
|
|
5667
|
+
if (e.data?.type !== "ow:parent-scroll") return;
|
|
5668
|
+
const { iframeOffsetTop, headerH, canvasH } = e.data;
|
|
5669
|
+
applyClip(iframeOffsetTop, headerH, canvasH);
|
|
5670
|
+
};
|
|
5671
|
+
const onResize = () => {
|
|
5672
|
+
setChromeClip((prev) => {
|
|
5673
|
+
const bottom = Math.max(prev.top, window.innerHeight);
|
|
5674
|
+
return prev.bottom === bottom ? prev : { ...prev, bottom };
|
|
5675
|
+
});
|
|
5676
|
+
};
|
|
5677
|
+
window.addEventListener("message", onParentScroll);
|
|
5678
|
+
window.addEventListener("resize", onResize);
|
|
5679
|
+
return () => {
|
|
5680
|
+
window.removeEventListener("message", onParentScroll);
|
|
5681
|
+
window.removeEventListener("resize", onResize);
|
|
5682
|
+
};
|
|
5683
|
+
}, []);
|
|
5684
|
+
const liveSections = useMemo2(() => {
|
|
5685
|
+
if (!isOnTargetPage) return sections;
|
|
5686
|
+
const live = collectSectionsFromDom();
|
|
5687
|
+
if (live.length === 0) return sections;
|
|
5688
|
+
const labels = new Map(sections.map((s) => [s.id, s.label]));
|
|
5689
|
+
return live.map((s) => ({ id: s.id, label: labels.get(s.id) ?? s.label }));
|
|
5690
|
+
}, [isOnTargetPage, sections, pathname]);
|
|
5691
|
+
const sectionIdsKey = useMemo2(
|
|
5692
|
+
() => liveSections.map((s) => s.id).join("\0"),
|
|
5693
|
+
[liveSections]
|
|
5694
|
+
);
|
|
5695
|
+
const rects = useSectionRects(sectionIdsKey, isOnTargetPage);
|
|
5696
|
+
const handleSelect = useCallback2(
|
|
5697
|
+
(section) => {
|
|
5698
|
+
if (selectedId) return;
|
|
5699
|
+
setSelectedId(section.id);
|
|
5700
|
+
onSelect(section);
|
|
5701
|
+
},
|
|
5702
|
+
[selectedId, onSelect]
|
|
5703
|
+
);
|
|
5704
|
+
useEffect4(() => {
|
|
5705
|
+
const onKeyDown = (e) => {
|
|
5706
|
+
if (e.key === "Escape") {
|
|
5707
|
+
e.preventDefault();
|
|
5708
|
+
e.stopPropagation();
|
|
5709
|
+
onBack();
|
|
5710
|
+
}
|
|
5711
|
+
};
|
|
5712
|
+
window.addEventListener("keydown", onKeyDown, true);
|
|
5713
|
+
return () => window.removeEventListener("keydown", onKeyDown, true);
|
|
5714
|
+
}, [onBack]);
|
|
5715
|
+
const portalRoot = typeof document !== "undefined" ? document.querySelector("[data-ohw-bridge-root]") ?? document.body : null;
|
|
5716
|
+
if (!portalRoot) return null;
|
|
5717
|
+
return createPortal(
|
|
5718
|
+
/* @__PURE__ */ jsxs11(
|
|
5719
|
+
"div",
|
|
5720
|
+
{
|
|
5721
|
+
"data-ohw-section-picker": "",
|
|
5722
|
+
"data-ohw-bridge": "",
|
|
5723
|
+
className: `pointer-events-none fixed inset-0 z-[2147483647] transition-opacity duration-200 ${"opacity-100"}`,
|
|
5724
|
+
"aria-modal": true,
|
|
5725
|
+
role: "dialog",
|
|
5726
|
+
"aria-label": "Choose a section",
|
|
5727
|
+
children: [
|
|
5728
|
+
/* @__PURE__ */ jsx19(
|
|
5729
|
+
"div",
|
|
5730
|
+
{
|
|
5731
|
+
className: "pointer-events-auto fixed left-5 z-[2]",
|
|
5732
|
+
style: { top: chromeClip.top + 20 },
|
|
5733
|
+
children: /* @__PURE__ */ jsxs11(
|
|
5734
|
+
Button,
|
|
5735
|
+
{
|
|
5736
|
+
type: "button",
|
|
5737
|
+
variant: "outline",
|
|
5738
|
+
size: "sm",
|
|
5739
|
+
className: "h-8 min-w-0 gap-1 border-border bg-background px-2 py-1.5 shadow-sm hover:bg-muted cursor-pointer",
|
|
5740
|
+
onClick: onBack,
|
|
5741
|
+
children: [
|
|
5742
|
+
/* @__PURE__ */ jsx19(ArrowLeft, { className: "size-4 shrink-0", "aria-hidden": true }),
|
|
5743
|
+
"Back"
|
|
5744
|
+
]
|
|
5745
|
+
}
|
|
5746
|
+
)
|
|
5747
|
+
}
|
|
5748
|
+
),
|
|
5749
|
+
/* @__PURE__ */ jsx19(
|
|
5750
|
+
"div",
|
|
5751
|
+
{
|
|
5752
|
+
className: "pointer-events-none fixed left-1/2 z-[2] rounded-lg px-4 py-3 text-xs leading-4 tracking-[0.18px] text-white shadow-md",
|
|
5753
|
+
style: {
|
|
5754
|
+
top: chromeClip.bottom - 20,
|
|
5755
|
+
transform: "translate(-50%, -100%)",
|
|
5756
|
+
backgroundColor: "var(--ohw-popover-foreground, #0c0a09)"
|
|
5757
|
+
},
|
|
5758
|
+
"data-ohw-section-picker-hint": "",
|
|
5759
|
+
children: "Click on section to select"
|
|
5760
|
+
}
|
|
5761
|
+
),
|
|
5762
|
+
!isOnTargetPage ? /* @__PURE__ */ jsx19(
|
|
5763
|
+
"div",
|
|
5764
|
+
{
|
|
5765
|
+
className: "pointer-events-none fixed left-1/2 z-[1] -translate-x-1/2 rounded-md bg-background/90 px-3 py-2 text-sm text-muted-foreground shadow-sm",
|
|
5766
|
+
style: { top: chromeClip.top + 64 },
|
|
5767
|
+
children: "Loading page preview\u2026"
|
|
5768
|
+
}
|
|
5769
|
+
) : null,
|
|
5770
|
+
isOnTargetPage && liveSections.length === 0 ? /* @__PURE__ */ jsx19("div", { className: "pointer-events-auto fixed inset-0 z-[1] flex items-center justify-center bg-muted/40", children: /* @__PURE__ */ jsx19("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." }) }) : null,
|
|
5771
|
+
isOnTargetPage ? liveSections.map((section) => {
|
|
5772
|
+
const rect = rects.get(section.id);
|
|
5773
|
+
if (!rect || rect.width <= 0 || rect.height <= 0) return null;
|
|
5774
|
+
const isSelected = selectedId === section.id;
|
|
5775
|
+
const isLit = isSelected || hoveredId === section.id;
|
|
5776
|
+
return /* @__PURE__ */ jsx19(
|
|
5777
|
+
"button",
|
|
5778
|
+
{
|
|
5779
|
+
type: "button",
|
|
5780
|
+
className: "pointer-events-auto fixed z-[1] cursor-pointer border-0 bg-transparent p-0 transition-[background-color] duration-150",
|
|
5781
|
+
style: {
|
|
5782
|
+
top: rect.top,
|
|
5783
|
+
left: rect.left,
|
|
5784
|
+
width: rect.width,
|
|
5785
|
+
height: rect.height,
|
|
5786
|
+
backgroundColor: isLit ? "transparent" : DIM_OVERLAY
|
|
5787
|
+
},
|
|
5788
|
+
"aria-label": `Select section ${section.label}`,
|
|
5789
|
+
onMouseEnter: () => setHoveredId(section.id),
|
|
5790
|
+
onMouseLeave: () => setHoveredId((prev) => prev === section.id ? null : prev),
|
|
5791
|
+
onClick: () => handleSelect(section),
|
|
5792
|
+
children: isSelected ? /* @__PURE__ */ jsx19(
|
|
5793
|
+
"span",
|
|
5794
|
+
{
|
|
5795
|
+
className: "absolute right-3 top-3 flex size-8 items-center justify-center rounded-full text-white",
|
|
5796
|
+
style: { backgroundColor: "var(--ohw-primary, #0885fe)" },
|
|
5797
|
+
"aria-hidden": true,
|
|
5798
|
+
children: /* @__PURE__ */ jsx19(Check, { className: "size-5" })
|
|
5799
|
+
}
|
|
5800
|
+
) : null
|
|
5801
|
+
},
|
|
5802
|
+
section.id
|
|
5803
|
+
);
|
|
5804
|
+
}) : null
|
|
5805
|
+
]
|
|
5806
|
+
}
|
|
5807
|
+
),
|
|
5808
|
+
portalRoot
|
|
5809
|
+
);
|
|
5810
|
+
}
|
|
5811
|
+
|
|
5812
|
+
// src/ui/link-modal/useLinkModalState.ts
|
|
5813
|
+
import { useCallback as useCallback3, useEffect as useEffect5, useMemo as useMemo3, useState as useState5 } from "react";
|
|
5814
|
+
function useLinkModalState({
|
|
5815
|
+
open,
|
|
5816
|
+
mode,
|
|
5817
|
+
pages,
|
|
5818
|
+
sections: _sections,
|
|
5819
|
+
sectionsByPath,
|
|
5820
|
+
initialTarget,
|
|
5821
|
+
existingTargets: _existingTargets,
|
|
5822
|
+
onClose,
|
|
5823
|
+
onSubmit
|
|
5824
|
+
}) {
|
|
5825
|
+
const availablePages = useMemo3(() => pages, [pages]);
|
|
5826
|
+
const [searchValue, setSearchValue] = useState5("");
|
|
5827
|
+
const [selectedPage, setSelectedPage] = useState5(null);
|
|
5828
|
+
const [selectedSection, setSelectedSection] = useState5(null);
|
|
5829
|
+
const [step, setStep] = useState5("input");
|
|
5830
|
+
const [dropdownOpen, setDropdownOpen] = useState5(false);
|
|
5831
|
+
const [urlError, setUrlError] = useState5("");
|
|
5832
|
+
const reset = useCallback3(() => {
|
|
5833
|
+
setSearchValue("");
|
|
5834
|
+
setSelectedPage(null);
|
|
5835
|
+
setSelectedSection(null);
|
|
5836
|
+
setStep("input");
|
|
5837
|
+
setDropdownOpen(false);
|
|
5838
|
+
setUrlError("");
|
|
5839
|
+
}, []);
|
|
5840
|
+
useEffect5(() => {
|
|
5841
|
+
if (!open) return;
|
|
5842
|
+
if (mode === "edit" && initialTarget) {
|
|
5843
|
+
const { pageRoute } = parseTarget(initialTarget);
|
|
5231
5844
|
const targetSections = getSectionsForPath(sectionsByPath, pageRoute);
|
|
5232
5845
|
const init = getEditModeInitialState(initialTarget, pages, targetSections);
|
|
5233
5846
|
setSearchValue(init.searchValue);
|
|
@@ -5239,12 +5852,12 @@ function useLinkModalState({
|
|
|
5239
5852
|
}
|
|
5240
5853
|
setDropdownOpen(false);
|
|
5241
5854
|
setUrlError("");
|
|
5242
|
-
}, [open, mode, initialTarget,
|
|
5243
|
-
const filteredPages =
|
|
5855
|
+
}, [open, mode, initialTarget, reset]);
|
|
5856
|
+
const filteredPages = useMemo3(() => {
|
|
5244
5857
|
if (!searchValue.trim()) return availablePages;
|
|
5245
5858
|
return availablePages.filter((p) => p.title.toLowerCase().startsWith(searchValue.toLowerCase()));
|
|
5246
5859
|
}, [availablePages, searchValue]);
|
|
5247
|
-
const activeSections =
|
|
5860
|
+
const activeSections = useMemo3(() => {
|
|
5248
5861
|
if (!selectedPage) return [];
|
|
5249
5862
|
return getSectionsForPath(sectionsByPath, selectedPage.path);
|
|
5250
5863
|
}, [selectedPage, sectionsByPath]);
|
|
@@ -5286,11 +5899,14 @@ function useLinkModalState({
|
|
|
5286
5899
|
const handleBackToSections = () => {
|
|
5287
5900
|
setStep("sectionPicker");
|
|
5288
5901
|
};
|
|
5902
|
+
const handleSectionPickerBack = () => {
|
|
5903
|
+
setStep("input");
|
|
5904
|
+
};
|
|
5289
5905
|
const handleClose = () => {
|
|
5290
5906
|
reset();
|
|
5291
5907
|
onClose();
|
|
5292
5908
|
};
|
|
5293
|
-
const isValid =
|
|
5909
|
+
const isValid = useMemo3(() => {
|
|
5294
5910
|
if (urlError) return false;
|
|
5295
5911
|
if (showBreadcrumb) return true;
|
|
5296
5912
|
if (selectedPage) return true;
|
|
@@ -5323,7 +5939,7 @@ function useLinkModalState({
|
|
|
5323
5939
|
onSubmit(normalizeUrl(searchValue));
|
|
5324
5940
|
handleClose();
|
|
5325
5941
|
};
|
|
5326
|
-
const submitLabel = mode === "edit" ? "Save" : "Create";
|
|
5942
|
+
const submitLabel = showBreadcrumb ? "Save" : mode === "edit" ? "Save" : "Create";
|
|
5327
5943
|
const title = mode === "edit" ? "Edit navigation item" : "Create navigation item";
|
|
5328
5944
|
const secondaryLabel = showBreadcrumb ? "Back to sections" : "Cancel";
|
|
5329
5945
|
const handleSecondary = showBreadcrumb ? handleBackToSections : handleClose;
|
|
@@ -5350,23 +5966,29 @@ function useLinkModalState({
|
|
|
5350
5966
|
handleChooseSection,
|
|
5351
5967
|
handleSectionSelect,
|
|
5352
5968
|
handleBackToSections,
|
|
5969
|
+
handleSectionPickerBack,
|
|
5353
5970
|
handleClose,
|
|
5354
5971
|
handleSecondary,
|
|
5355
5972
|
handleSubmit
|
|
5356
5973
|
};
|
|
5357
5974
|
}
|
|
5358
5975
|
|
|
5359
|
-
// src/ui/link-modal/
|
|
5360
|
-
import { Fragment as
|
|
5361
|
-
function
|
|
5976
|
+
// src/ui/link-modal/LinkPopover.tsx
|
|
5977
|
+
import { Fragment as Fragment4, jsx as jsx20, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
5978
|
+
function postToParent(data) {
|
|
5979
|
+
window.parent?.postMessage(data, "*");
|
|
5980
|
+
}
|
|
5981
|
+
function LinkPopover({
|
|
5362
5982
|
open = true,
|
|
5983
|
+
panelRef,
|
|
5984
|
+
portalContainer,
|
|
5985
|
+
onClose,
|
|
5363
5986
|
mode = "create",
|
|
5364
5987
|
pages,
|
|
5365
5988
|
sections = [],
|
|
5366
5989
|
sectionsByPath,
|
|
5367
5990
|
initialTarget,
|
|
5368
5991
|
existingTargets = [],
|
|
5369
|
-
onClose,
|
|
5370
5992
|
onSubmit
|
|
5371
5993
|
}) {
|
|
5372
5994
|
const state = useLinkModalState({
|
|
@@ -5380,115 +6002,100 @@ function LinkEditorPanel({
|
|
|
5380
6002
|
onClose,
|
|
5381
6003
|
onSubmit
|
|
5382
6004
|
});
|
|
5383
|
-
const
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
6005
|
+
const sectionPickerActive = state.showSectionPicker && Boolean(state.selectedPage);
|
|
6006
|
+
useEffect6(() => {
|
|
6007
|
+
if (!open) return;
|
|
6008
|
+
if (sectionPickerActive) {
|
|
6009
|
+
postToParent({ type: "ow:link-modal-lock", locked: false });
|
|
6010
|
+
postToParent({ type: "ow:section-picker", active: true });
|
|
6011
|
+
document.documentElement.style.overflow = "";
|
|
6012
|
+
document.body.style.overflow = "";
|
|
6013
|
+
return () => {
|
|
6014
|
+
postToParent({ type: "ow:section-picker", active: false });
|
|
6015
|
+
};
|
|
6016
|
+
}
|
|
6017
|
+
postToParent({ type: "ow:section-picker", active: false });
|
|
6018
|
+
postToParent({ type: "ow:link-modal-lock", locked: true });
|
|
6019
|
+
const html = document.documentElement;
|
|
6020
|
+
const body = document.body;
|
|
6021
|
+
const prevHtmlOverflow = html.style.overflow;
|
|
6022
|
+
const prevBodyOverflow = body.style.overflow;
|
|
6023
|
+
const prevHtmlOverscroll = html.style.overscrollBehavior;
|
|
6024
|
+
const prevBodyOverscroll = body.style.overscrollBehavior;
|
|
6025
|
+
html.style.overflow = "hidden";
|
|
6026
|
+
body.style.overflow = "hidden";
|
|
6027
|
+
html.style.overscrollBehavior = "none";
|
|
6028
|
+
body.style.overscrollBehavior = "none";
|
|
6029
|
+
const canScrollElement = (el, deltaY) => {
|
|
6030
|
+
const { overflowY } = getComputedStyle(el);
|
|
6031
|
+
if (overflowY !== "auto" && overflowY !== "scroll") return false;
|
|
6032
|
+
if (el.scrollHeight <= el.clientHeight + 1) return false;
|
|
6033
|
+
if (deltaY < 0) return el.scrollTop > 0;
|
|
6034
|
+
if (deltaY > 0) return el.scrollTop + el.clientHeight < el.scrollHeight - 1;
|
|
6035
|
+
return true;
|
|
6036
|
+
};
|
|
6037
|
+
const allowsInternalScroll = (e) => {
|
|
6038
|
+
const target = e.target;
|
|
6039
|
+
if (!(target instanceof Element)) return false;
|
|
6040
|
+
const scrollRoot = target.closest(
|
|
6041
|
+
"[data-ohw-link-page-dropdown], [data-ohw-allow-scroll]"
|
|
6042
|
+
);
|
|
6043
|
+
if (!scrollRoot) return false;
|
|
6044
|
+
const deltaY = e instanceof WheelEvent ? e.deltaY : 0;
|
|
6045
|
+
return canScrollElement(scrollRoot, deltaY);
|
|
6046
|
+
};
|
|
6047
|
+
const preventBackgroundScroll = (e) => {
|
|
6048
|
+
if (allowsInternalScroll(e)) return;
|
|
6049
|
+
e.preventDefault();
|
|
6050
|
+
};
|
|
6051
|
+
const scrollOpts = { passive: false, capture: true };
|
|
6052
|
+
document.addEventListener("wheel", preventBackgroundScroll, scrollOpts);
|
|
6053
|
+
document.addEventListener("touchmove", preventBackgroundScroll, scrollOpts);
|
|
6054
|
+
return () => {
|
|
6055
|
+
postToParent({ type: "ow:link-modal-lock", locked: false });
|
|
6056
|
+
html.style.overflow = prevHtmlOverflow;
|
|
6057
|
+
body.style.overflow = prevBodyOverflow;
|
|
6058
|
+
html.style.overscrollBehavior = prevHtmlOverscroll;
|
|
6059
|
+
body.style.overscrollBehavior = prevBodyOverscroll;
|
|
6060
|
+
document.removeEventListener("wheel", preventBackgroundScroll, scrollOpts);
|
|
6061
|
+
document.removeEventListener("touchmove", preventBackgroundScroll, scrollOpts);
|
|
6062
|
+
};
|
|
6063
|
+
}, [open, sectionPickerActive]);
|
|
6064
|
+
return /* @__PURE__ */ jsxs12(Fragment4, { children: [
|
|
6065
|
+
/* @__PURE__ */ jsx20(
|
|
6066
|
+
Dialog2,
|
|
5387
6067
|
{
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
6068
|
+
open: open && !sectionPickerActive,
|
|
6069
|
+
onOpenChange: (next) => {
|
|
6070
|
+
if (!next) onClose?.();
|
|
6071
|
+
},
|
|
6072
|
+
children: /* @__PURE__ */ jsx20(
|
|
6073
|
+
DialogContent,
|
|
6074
|
+
{
|
|
6075
|
+
ref: panelRef,
|
|
6076
|
+
container: portalContainer,
|
|
6077
|
+
"data-ohw-link-popover-root": "",
|
|
6078
|
+
"data-ohw-link-modal-root": "",
|
|
6079
|
+
"data-ohw-bridge": "",
|
|
6080
|
+
showCloseButton: false,
|
|
6081
|
+
className: "gap-0 p-0 w-full md:w-md pointer-events-auto z-[2147483646] overflow-visible",
|
|
6082
|
+
children: /* @__PURE__ */ jsx20(LinkEditorPanel, { state, onClose })
|
|
6083
|
+
}
|
|
6084
|
+
)
|
|
5392
6085
|
}
|
|
5393
|
-
)
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
UrlOrPageInput,
|
|
5404
|
-
{
|
|
5405
|
-
value: state.searchValue,
|
|
5406
|
-
selectedPage: state.selectedPage,
|
|
5407
|
-
dropdownOpen: state.dropdownOpen,
|
|
5408
|
-
onDropdownOpenChange: state.setDropdownOpen,
|
|
5409
|
-
filteredPages: state.filteredPages,
|
|
5410
|
-
onInputChange: state.handleInputChange,
|
|
5411
|
-
onPageSelect: state.handlePageSelect,
|
|
5412
|
-
urlError: state.urlError
|
|
5413
|
-
}
|
|
5414
|
-
),
|
|
5415
|
-
state.showChooseSection ? /* @__PURE__ */ jsxs10("div", { className: "flex flex-col justify-center gap-2", children: [
|
|
5416
|
-
/* @__PURE__ */ jsx18(Button, { type: "button", variant: "outline", className: "w-fit cursor-pointer", size: "sm", onClick: state.handleChooseSection, children: "Choose a section" }),
|
|
5417
|
-
/* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
|
|
5418
|
-
/* @__PURE__ */ jsx18(IconInfo, { className: "shrink-0", "aria-hidden": true }),
|
|
5419
|
-
/* @__PURE__ */ jsx18("span", { children: "Pick a section this link should scroll to." })
|
|
5420
|
-
] })
|
|
5421
|
-
] }) : null,
|
|
5422
|
-
state.showSectionPicker ? /* @__PURE__ */ jsx18(SectionPickerList, { sections: state.activeSections, onSelect: state.handleSectionSelect }) : null,
|
|
5423
|
-
state.showSectionRow && state.selectedSection ? /* @__PURE__ */ jsx18(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
|
|
5424
|
-
] }),
|
|
5425
|
-
/* @__PURE__ */ jsxs10(DialogFooter, { className: "w-full px-6 pb-6", children: [
|
|
5426
|
-
/* @__PURE__ */ jsx18(
|
|
5427
|
-
Button,
|
|
5428
|
-
{
|
|
5429
|
-
type: "button",
|
|
5430
|
-
variant: isCancel ? "outline" : "ghost",
|
|
5431
|
-
className: "leading-6 shadow-none cursor-pointer",
|
|
5432
|
-
style: isCancel ? {
|
|
5433
|
-
backgroundColor: "var(--ohw-background)",
|
|
5434
|
-
borderColor: "var(--ohw-border)",
|
|
5435
|
-
color: "var(--ohw-foreground)"
|
|
5436
|
-
} : void 0,
|
|
5437
|
-
onClick: state.handleSecondary,
|
|
5438
|
-
children: state.secondaryLabel
|
|
5439
|
-
}
|
|
5440
|
-
),
|
|
5441
|
-
/* @__PURE__ */ jsx18(
|
|
5442
|
-
Button,
|
|
5443
|
-
{
|
|
5444
|
-
type: "button",
|
|
5445
|
-
className: "border-0 leading-6 shadow-none hover:opacity-90 disabled:opacity-50 cursor-pointer",
|
|
5446
|
-
style: {
|
|
5447
|
-
backgroundColor: "var(--ohw-primary)",
|
|
5448
|
-
color: "var(--ohw-primary-foreground)"
|
|
5449
|
-
},
|
|
5450
|
-
disabled: !state.isValid,
|
|
5451
|
-
onClick: state.handleSubmit,
|
|
5452
|
-
children: state.submitLabel
|
|
5453
|
-
}
|
|
5454
|
-
)
|
|
5455
|
-
] })
|
|
6086
|
+
),
|
|
6087
|
+
sectionPickerActive && state.selectedPage ? /* @__PURE__ */ jsx20(
|
|
6088
|
+
SectionPickerOverlay,
|
|
6089
|
+
{
|
|
6090
|
+
pagePath: state.selectedPage.path,
|
|
6091
|
+
sections: state.activeSections,
|
|
6092
|
+
onBack: state.handleSectionPickerBack,
|
|
6093
|
+
onSelect: state.handleSectionSelect
|
|
6094
|
+
}
|
|
6095
|
+
) : null
|
|
5456
6096
|
] });
|
|
5457
6097
|
}
|
|
5458
6098
|
|
|
5459
|
-
// src/ui/link-modal/LinkPopover.tsx
|
|
5460
|
-
import { jsx as jsx19 } from "react/jsx-runtime";
|
|
5461
|
-
function LinkPopover({
|
|
5462
|
-
open = true,
|
|
5463
|
-
panelRef,
|
|
5464
|
-
portalContainer,
|
|
5465
|
-
onClose,
|
|
5466
|
-
...editorProps
|
|
5467
|
-
}) {
|
|
5468
|
-
return /* @__PURE__ */ jsx19(
|
|
5469
|
-
Dialog2,
|
|
5470
|
-
{
|
|
5471
|
-
open,
|
|
5472
|
-
onOpenChange: (next) => {
|
|
5473
|
-
if (!next) onClose?.();
|
|
5474
|
-
},
|
|
5475
|
-
children: /* @__PURE__ */ jsx19(
|
|
5476
|
-
DialogContent,
|
|
5477
|
-
{
|
|
5478
|
-
ref: panelRef,
|
|
5479
|
-
container: portalContainer,
|
|
5480
|
-
"data-ohw-link-popover-root": "",
|
|
5481
|
-
"data-ohw-link-modal-root": "",
|
|
5482
|
-
"data-ohw-bridge": "",
|
|
5483
|
-
showCloseButton: false,
|
|
5484
|
-
className: "gap-0 p-0 w-full md:w-md pointer-events-auto",
|
|
5485
|
-
children: /* @__PURE__ */ jsx19(LinkEditorPanel, { ...editorProps, open, onClose })
|
|
5486
|
-
}
|
|
5487
|
-
)
|
|
5488
|
-
}
|
|
5489
|
-
);
|
|
5490
|
-
}
|
|
5491
|
-
|
|
5492
6099
|
// src/ui/link-modal/devFixtures.ts
|
|
5493
6100
|
var DEV_SITE_PAGES = [
|
|
5494
6101
|
{ path: "/", title: "Home" },
|
|
@@ -5508,16 +6115,21 @@ var DEV_SECTIONS_BY_PATH = {
|
|
|
5508
6115
|
{ id: "founder-teaser", label: "Founder" },
|
|
5509
6116
|
{ id: "plan-form", label: "Plan Form" },
|
|
5510
6117
|
{ id: "testimonials", label: "Testimonials" },
|
|
5511
|
-
{ id: "wordmark", label: "Wordmark" }
|
|
6118
|
+
{ id: "wordmark", label: "Wordmark" },
|
|
6119
|
+
{ id: "footer", label: "Footer" }
|
|
5512
6120
|
],
|
|
5513
6121
|
"/about": [
|
|
5514
6122
|
{ id: "manifesto", label: "Manifesto" },
|
|
5515
6123
|
{ id: "story-letter", label: "Our Story" },
|
|
5516
6124
|
{ id: "lagree-explainer", label: "Lagree Explainer" },
|
|
5517
6125
|
{ id: "waitlist-cta", label: "Waitlist" },
|
|
5518
|
-
{ id: "personal-training", label: "Personal training" }
|
|
6126
|
+
{ id: "personal-training", label: "Personal training" },
|
|
6127
|
+
{ id: "footer", label: "Footer" }
|
|
6128
|
+
],
|
|
6129
|
+
"/classes": [
|
|
6130
|
+
{ id: "class-library", label: "Class Library" },
|
|
6131
|
+
{ id: "footer", label: "Footer" }
|
|
5519
6132
|
],
|
|
5520
|
-
"/classes": [{ id: "class-library", label: "Class Library" }],
|
|
5521
6133
|
"/pricing": [
|
|
5522
6134
|
{ id: "page-header", label: "Page Header" },
|
|
5523
6135
|
{ id: "free-class-cta", label: "Free Class" },
|
|
@@ -5525,19 +6137,25 @@ var DEV_SECTIONS_BY_PATH = {
|
|
|
5525
6137
|
{ id: "monthly-memberships", label: "Memberships" },
|
|
5526
6138
|
{ id: "specialty-programs", label: "Specialty Programs" },
|
|
5527
6139
|
{ id: "package-matcher", label: "Packages" },
|
|
5528
|
-
{ id: "wordmark", label: "Wordmark" }
|
|
6140
|
+
{ id: "wordmark", label: "Wordmark" },
|
|
6141
|
+
{ id: "footer", label: "Footer" }
|
|
5529
6142
|
],
|
|
5530
6143
|
"/studio": [
|
|
5531
6144
|
{ id: "studio-intro", label: "Studio Intro" },
|
|
5532
6145
|
{ id: "studio-features", label: "Studio Features" },
|
|
5533
6146
|
{ id: "studio-gallery", label: "Studio Gallery" },
|
|
5534
|
-
{ id: "studio-visit", label: "Visit Studio" }
|
|
6147
|
+
{ id: "studio-visit", label: "Visit Studio" },
|
|
6148
|
+
{ id: "footer", label: "Footer" }
|
|
6149
|
+
],
|
|
6150
|
+
"/instructors": [
|
|
6151
|
+
{ id: "instructor-grid", label: "Instructors" },
|
|
6152
|
+
{ id: "footer", label: "Footer" }
|
|
5535
6153
|
],
|
|
5536
|
-
"/instructors": [{ id: "instructor-grid", label: "Instructors" }],
|
|
5537
6154
|
"/contact": [
|
|
5538
6155
|
{ id: "hello-hero", label: "Hello" },
|
|
5539
6156
|
{ id: "contact-form", label: "Contact Form" },
|
|
5540
|
-
{ id: "faq", label: "FAQ" }
|
|
6157
|
+
{ id: "faq", label: "FAQ" },
|
|
6158
|
+
{ id: "footer", label: "Footer" }
|
|
5541
6159
|
]
|
|
5542
6160
|
};
|
|
5543
6161
|
function shouldUseDevFixtures() {
|
|
@@ -5547,8 +6165,277 @@ function shouldUseDevFixtures() {
|
|
|
5547
6165
|
return new URLSearchParams(q).get("ohw-fixtures") === "1";
|
|
5548
6166
|
}
|
|
5549
6167
|
|
|
6168
|
+
// src/lib/nav-items.ts
|
|
6169
|
+
var NAV_COUNT_KEY = "__ohw_nav_count";
|
|
6170
|
+
var NAV_ORDER_KEY = "__ohw_nav_order";
|
|
6171
|
+
function getLinkHref(el) {
|
|
6172
|
+
const key = el.getAttribute("data-ohw-href-key");
|
|
6173
|
+
if (key) {
|
|
6174
|
+
const stored = getStoredLinkHref(key);
|
|
6175
|
+
if (stored !== void 0) return stored;
|
|
6176
|
+
}
|
|
6177
|
+
return el.getAttribute("href") ?? "";
|
|
6178
|
+
}
|
|
6179
|
+
function isNavbarButton(el) {
|
|
6180
|
+
return el.hasAttribute("data-ohw-role") && el.getAttribute("data-ohw-role") === "navbar-button";
|
|
6181
|
+
}
|
|
6182
|
+
function isNavbarLinkItem(el) {
|
|
6183
|
+
if (!el.matches("[data-ohw-href-key]")) return false;
|
|
6184
|
+
if (isNavbarButton(el)) return false;
|
|
6185
|
+
if (!el.querySelector('[data-ohw-editable="text"]')) return false;
|
|
6186
|
+
return Boolean(el.closest("nav, [data-ohw-nav-container], [data-ohw-nav-drawer]"));
|
|
6187
|
+
}
|
|
6188
|
+
function getNavbarDesktopContainer() {
|
|
6189
|
+
return document.querySelector("[data-ohw-nav-container]");
|
|
6190
|
+
}
|
|
6191
|
+
function getNavbarDrawerContainer() {
|
|
6192
|
+
return document.querySelector("[data-ohw-nav-drawer]");
|
|
6193
|
+
}
|
|
6194
|
+
function listNavbarItems() {
|
|
6195
|
+
const desktop = getNavbarDesktopContainer();
|
|
6196
|
+
if (desktop) {
|
|
6197
|
+
return Array.from(desktop.querySelectorAll("[data-ohw-href-key]")).filter(isNavbarLinkItem);
|
|
6198
|
+
}
|
|
6199
|
+
const drawer = getNavbarDrawerContainer();
|
|
6200
|
+
if (drawer) {
|
|
6201
|
+
return Array.from(drawer.querySelectorAll("[data-ohw-href-key]")).filter(isNavbarLinkItem);
|
|
6202
|
+
}
|
|
6203
|
+
return Array.from(document.querySelectorAll("nav [data-ohw-href-key]")).filter(isNavbarLinkItem);
|
|
6204
|
+
}
|
|
6205
|
+
function parseNavIndexFromKey(key) {
|
|
6206
|
+
if (!key) return null;
|
|
6207
|
+
const match = key.match(/^nav-(\d+)-href$/);
|
|
6208
|
+
if (!match) return null;
|
|
6209
|
+
return parseInt(match[1], 10);
|
|
6210
|
+
}
|
|
6211
|
+
function getNavbarIndicesInDom() {
|
|
6212
|
+
const indices = /* @__PURE__ */ new Set();
|
|
6213
|
+
for (const item of listNavbarItems()) {
|
|
6214
|
+
const idx = parseNavIndexFromKey(item.getAttribute("data-ohw-href-key"));
|
|
6215
|
+
if (idx !== null) indices.add(idx);
|
|
6216
|
+
}
|
|
6217
|
+
return [...indices].sort((a, b) => a - b);
|
|
6218
|
+
}
|
|
6219
|
+
function getNextNavbarIndex() {
|
|
6220
|
+
const indices = getNavbarIndicesInDom();
|
|
6221
|
+
if (indices.length === 0) return 0;
|
|
6222
|
+
return Math.max(...indices) + 1;
|
|
6223
|
+
}
|
|
6224
|
+
function getNavbarExistingTargets() {
|
|
6225
|
+
return listNavbarItems().map((el) => getLinkHref(el)).filter(Boolean);
|
|
6226
|
+
}
|
|
6227
|
+
function getNavOrderFromDom() {
|
|
6228
|
+
return listNavbarItems().map((el) => el.getAttribute("data-ohw-href-key")).filter((key) => Boolean(key));
|
|
6229
|
+
}
|
|
6230
|
+
function parseNavOrder(content) {
|
|
6231
|
+
const raw = content[NAV_ORDER_KEY];
|
|
6232
|
+
if (!raw) return null;
|
|
6233
|
+
try {
|
|
6234
|
+
const parsed = JSON.parse(raw);
|
|
6235
|
+
if (!Array.isArray(parsed)) return null;
|
|
6236
|
+
return parsed.filter((key) => typeof key === "string" && key.length > 0);
|
|
6237
|
+
} catch {
|
|
6238
|
+
return null;
|
|
6239
|
+
}
|
|
6240
|
+
}
|
|
6241
|
+
function findCounterpartByHrefKey(hrefKey, root) {
|
|
6242
|
+
return root.querySelector(`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`);
|
|
6243
|
+
}
|
|
6244
|
+
function cloneNavLinkShell(template) {
|
|
6245
|
+
const anchor = document.createElement("a");
|
|
6246
|
+
if (template) {
|
|
6247
|
+
anchor.style.cssText = template.style.cssText;
|
|
6248
|
+
if (template.className) anchor.className = template.className;
|
|
6249
|
+
}
|
|
6250
|
+
anchor.style.cursor = "pointer";
|
|
6251
|
+
anchor.style.textDecoration = "none";
|
|
6252
|
+
return anchor;
|
|
6253
|
+
}
|
|
6254
|
+
function buildNavLink(index, href, label, template) {
|
|
6255
|
+
const anchor = cloneNavLinkShell(template);
|
|
6256
|
+
anchor.href = href;
|
|
6257
|
+
anchor.setAttribute("data-ohw-href-key", `nav-${index}-href`);
|
|
6258
|
+
const span = document.createElement("span");
|
|
6259
|
+
span.setAttribute("data-ohw-editable", "text");
|
|
6260
|
+
span.setAttribute("data-ohw-key", `nav-${index}-label`);
|
|
6261
|
+
span.textContent = label;
|
|
6262
|
+
anchor.appendChild(span);
|
|
6263
|
+
return anchor;
|
|
6264
|
+
}
|
|
6265
|
+
function insertNavLinkInContainer(container, anchor, afterHrefKey) {
|
|
6266
|
+
if (!afterHrefKey) {
|
|
6267
|
+
container.appendChild(anchor);
|
|
6268
|
+
return;
|
|
6269
|
+
}
|
|
6270
|
+
const afterEl = findCounterpartByHrefKey(afterHrefKey, container);
|
|
6271
|
+
if (afterEl?.parentElement === container) {
|
|
6272
|
+
afterEl.insertAdjacentElement("afterend", anchor);
|
|
6273
|
+
return;
|
|
6274
|
+
}
|
|
6275
|
+
container.appendChild(anchor);
|
|
6276
|
+
}
|
|
6277
|
+
function insertNavbarItemDom(index, href, label, afterAnchor) {
|
|
6278
|
+
const afterHrefKey = afterAnchor?.getAttribute("data-ohw-href-key") ?? null;
|
|
6279
|
+
const desktopItems = getNavbarDesktopContainer()?.querySelectorAll("[data-ohw-href-key]") ?? [];
|
|
6280
|
+
const drawerItems = getNavbarDrawerContainer()?.querySelectorAll("[data-ohw-href-key]") ?? [];
|
|
6281
|
+
const desktopTemplate = Array.from(desktopItems).find(isNavbarLinkItem) ?? null;
|
|
6282
|
+
const drawerTemplate = Array.from(drawerItems).find(isNavbarLinkItem) ?? null;
|
|
6283
|
+
let primary = null;
|
|
6284
|
+
const desktopContainer = getNavbarDesktopContainer();
|
|
6285
|
+
if (desktopContainer) {
|
|
6286
|
+
const desktopAnchor = buildNavLink(index, href, label, desktopTemplate);
|
|
6287
|
+
insertNavLinkInContainer(desktopContainer, desktopAnchor, afterHrefKey);
|
|
6288
|
+
primary = desktopAnchor;
|
|
6289
|
+
}
|
|
6290
|
+
const drawerContainer = getNavbarDrawerContainer();
|
|
6291
|
+
if (drawerContainer) {
|
|
6292
|
+
const drawerAnchor = buildNavLink(index, href, label, drawerTemplate);
|
|
6293
|
+
insertNavLinkInContainer(drawerContainer, drawerAnchor, afterHrefKey);
|
|
6294
|
+
if (!primary) primary = drawerAnchor;
|
|
6295
|
+
}
|
|
6296
|
+
if (!primary) {
|
|
6297
|
+
const fallback = buildNavLink(index, href, label, listNavbarItems()[0] ?? null);
|
|
6298
|
+
const nav = document.querySelector("nav");
|
|
6299
|
+
nav?.appendChild(fallback);
|
|
6300
|
+
primary = fallback;
|
|
6301
|
+
}
|
|
6302
|
+
return primary;
|
|
6303
|
+
}
|
|
6304
|
+
function applyNavOrderToContainer(container, order) {
|
|
6305
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6306
|
+
for (const hrefKey of order) {
|
|
6307
|
+
if (seen.has(hrefKey)) continue;
|
|
6308
|
+
seen.add(hrefKey);
|
|
6309
|
+
const el = findCounterpartByHrefKey(hrefKey, container);
|
|
6310
|
+
if (el) container.appendChild(el);
|
|
6311
|
+
}
|
|
6312
|
+
for (const el of container.querySelectorAll("[data-ohw-href-key]")) {
|
|
6313
|
+
if (!isNavbarLinkItem(el)) continue;
|
|
6314
|
+
const key = el.getAttribute("data-ohw-href-key");
|
|
6315
|
+
if (!key || seen.has(key)) continue;
|
|
6316
|
+
container.appendChild(el);
|
|
6317
|
+
}
|
|
6318
|
+
}
|
|
6319
|
+
function applyNavOrder(order) {
|
|
6320
|
+
const desktop = getNavbarDesktopContainer();
|
|
6321
|
+
if (desktop) applyNavOrderToContainer(desktop, order);
|
|
6322
|
+
const drawer = getNavbarDrawerContainer();
|
|
6323
|
+
if (drawer) applyNavOrderToContainer(drawer, order);
|
|
6324
|
+
}
|
|
6325
|
+
function collectNavbarIndicesFromContent(content) {
|
|
6326
|
+
const indices = /* @__PURE__ */ new Set();
|
|
6327
|
+
for (const key of Object.keys(content)) {
|
|
6328
|
+
const idx = parseNavIndexFromKey(key);
|
|
6329
|
+
if (idx !== null) indices.add(idx);
|
|
6330
|
+
}
|
|
6331
|
+
const countRaw = content[NAV_COUNT_KEY];
|
|
6332
|
+
if (countRaw) {
|
|
6333
|
+
const count = parseInt(countRaw, 10);
|
|
6334
|
+
if (Number.isFinite(count) && count > 0) {
|
|
6335
|
+
for (let i = 0; i < count; i++) indices.add(i);
|
|
6336
|
+
}
|
|
6337
|
+
}
|
|
6338
|
+
return [...indices].sort((a, b) => a - b);
|
|
6339
|
+
}
|
|
6340
|
+
function navbarIndexExistsInDom(index) {
|
|
6341
|
+
return document.querySelector(`[data-ohw-href-key="nav-${index}-href"]`) !== null;
|
|
6342
|
+
}
|
|
6343
|
+
function reconcileNavbarItemsFromContent(content) {
|
|
6344
|
+
const indices = collectNavbarIndicesFromContent(content);
|
|
6345
|
+
for (const index of indices) {
|
|
6346
|
+
if (navbarIndexExistsInDom(index)) continue;
|
|
6347
|
+
const href = content[`nav-${index}-href`];
|
|
6348
|
+
const label = content[`nav-${index}-label`];
|
|
6349
|
+
if (!href && !label) continue;
|
|
6350
|
+
insertNavbarItemDom(index, href ?? "/", label ?? "Untitled", null);
|
|
6351
|
+
}
|
|
6352
|
+
const order = parseNavOrder(content);
|
|
6353
|
+
if (order?.length) applyNavOrder(order);
|
|
6354
|
+
}
|
|
6355
|
+
function buildNavOrderAfterInsert(afterAnchor, newHrefKey) {
|
|
6356
|
+
const order = getNavOrderFromDom();
|
|
6357
|
+
if (!afterAnchor) {
|
|
6358
|
+
if (!order.includes(newHrefKey)) order.push(newHrefKey);
|
|
6359
|
+
return order;
|
|
6360
|
+
}
|
|
6361
|
+
const afterKey = afterAnchor.getAttribute("data-ohw-href-key");
|
|
6362
|
+
if (!afterKey) {
|
|
6363
|
+
if (!order.includes(newHrefKey)) order.push(newHrefKey);
|
|
6364
|
+
return order;
|
|
6365
|
+
}
|
|
6366
|
+
const withoutNew = order.filter((key) => key !== newHrefKey);
|
|
6367
|
+
const pos = withoutNew.indexOf(afterKey);
|
|
6368
|
+
if (pos >= 0) {
|
|
6369
|
+
withoutNew.splice(pos + 1, 0, newHrefKey);
|
|
6370
|
+
return withoutNew;
|
|
6371
|
+
}
|
|
6372
|
+
withoutNew.push(newHrefKey);
|
|
6373
|
+
return withoutNew;
|
|
6374
|
+
}
|
|
6375
|
+
function insertNavbarItem(href, label, afterAnchor = null) {
|
|
6376
|
+
const index = getNextNavbarIndex();
|
|
6377
|
+
const anchor = insertNavbarItemDom(index, href, label, afterAnchor);
|
|
6378
|
+
if (!anchor) throw new Error("Failed to insert navbar item");
|
|
6379
|
+
const hrefKey = `nav-${index}-href`;
|
|
6380
|
+
const order = buildNavOrderAfterInsert(afterAnchor, hrefKey);
|
|
6381
|
+
applyNavOrder(order);
|
|
6382
|
+
return {
|
|
6383
|
+
anchor,
|
|
6384
|
+
index,
|
|
6385
|
+
hrefKey,
|
|
6386
|
+
labelKey: `nav-${index}-label`,
|
|
6387
|
+
href,
|
|
6388
|
+
label,
|
|
6389
|
+
order
|
|
6390
|
+
};
|
|
6391
|
+
}
|
|
6392
|
+
|
|
6393
|
+
// src/ui/navbar-container-chrome.tsx
|
|
6394
|
+
import { Plus as Plus2 } from "lucide-react";
|
|
6395
|
+
import { jsx as jsx21 } from "react/jsx-runtime";
|
|
6396
|
+
function NavbarContainerChrome({
|
|
6397
|
+
rect,
|
|
6398
|
+
onAdd
|
|
6399
|
+
}) {
|
|
6400
|
+
const chromeGap = 6;
|
|
6401
|
+
return /* @__PURE__ */ jsx21(
|
|
6402
|
+
"div",
|
|
6403
|
+
{
|
|
6404
|
+
"data-ohw-navbar-container-chrome": "",
|
|
6405
|
+
"data-ohw-bridge": "",
|
|
6406
|
+
className: "pointer-events-none fixed z-[2147483647]",
|
|
6407
|
+
style: {
|
|
6408
|
+
top: rect.top - chromeGap,
|
|
6409
|
+
left: rect.left - chromeGap,
|
|
6410
|
+
width: rect.width + chromeGap * 2,
|
|
6411
|
+
height: rect.height + chromeGap * 2
|
|
6412
|
+
},
|
|
6413
|
+
children: /* @__PURE__ */ jsx21(
|
|
6414
|
+
"button",
|
|
6415
|
+
{
|
|
6416
|
+
type: "button",
|
|
6417
|
+
"data-ohw-navbar-add-button": "",
|
|
6418
|
+
className: "pointer-events-auto absolute left-1/2 flex p-0.5 rounded-[10px] size-7 -translate-x-1/2 translate-y-1/2 items-center justify-center border border-border bg-background shadow-sm transition-colors hover:bg-muted/80",
|
|
6419
|
+
style: { top: "70%" },
|
|
6420
|
+
"aria-label": "Add item",
|
|
6421
|
+
onMouseDown: (e) => {
|
|
6422
|
+
e.preventDefault();
|
|
6423
|
+
e.stopPropagation();
|
|
6424
|
+
},
|
|
6425
|
+
onClick: (e) => {
|
|
6426
|
+
e.preventDefault();
|
|
6427
|
+
e.stopPropagation();
|
|
6428
|
+
onAdd();
|
|
6429
|
+
},
|
|
6430
|
+
children: /* @__PURE__ */ jsx21(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
6431
|
+
}
|
|
6432
|
+
)
|
|
6433
|
+
}
|
|
6434
|
+
);
|
|
6435
|
+
}
|
|
6436
|
+
|
|
5550
6437
|
// src/ui/badge.tsx
|
|
5551
|
-
import { jsx as
|
|
6438
|
+
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
5552
6439
|
var badgeVariants = cva(
|
|
5553
6440
|
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
5554
6441
|
{
|
|
@@ -5566,12 +6453,12 @@ var badgeVariants = cva(
|
|
|
5566
6453
|
}
|
|
5567
6454
|
);
|
|
5568
6455
|
function Badge({ className, variant, ...props }) {
|
|
5569
|
-
return /* @__PURE__ */
|
|
6456
|
+
return /* @__PURE__ */ jsx22("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
5570
6457
|
}
|
|
5571
6458
|
|
|
5572
6459
|
// src/OhhwellsBridge.tsx
|
|
5573
6460
|
import { Link as Link2 } from "lucide-react";
|
|
5574
|
-
import { Fragment as
|
|
6461
|
+
import { Fragment as Fragment5, jsx as jsx23, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
5575
6462
|
var PRIMARY2 = "#0885FE";
|
|
5576
6463
|
var IMAGE_FADE_MS = 300;
|
|
5577
6464
|
function runOpacityFade(el, onDone) {
|
|
@@ -5598,6 +6485,11 @@ function fadeInImageElement(img, onReady) {
|
|
|
5598
6485
|
img.style.opacity = "";
|
|
5599
6486
|
});
|
|
5600
6487
|
}
|
|
6488
|
+
function applyEditableImageSrc(img, url) {
|
|
6489
|
+
img.removeAttribute("srcset");
|
|
6490
|
+
img.removeAttribute("sizes");
|
|
6491
|
+
img.src = url;
|
|
6492
|
+
}
|
|
5601
6493
|
function fadeInBgImage(el, url, onReady) {
|
|
5602
6494
|
const prevPos = el.style.position;
|
|
5603
6495
|
if (!prevPos || prevPos === "static") el.style.position = "relative";
|
|
@@ -5745,7 +6637,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
5745
6637
|
const root = createRoot(container);
|
|
5746
6638
|
flushSync(() => {
|
|
5747
6639
|
root.render(
|
|
5748
|
-
/* @__PURE__ */
|
|
6640
|
+
/* @__PURE__ */ jsx23(
|
|
5749
6641
|
SchedulingWidget,
|
|
5750
6642
|
{
|
|
5751
6643
|
notifyOnConnect,
|
|
@@ -5785,7 +6677,7 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
|
|
|
5785
6677
|
}
|
|
5786
6678
|
}
|
|
5787
6679
|
}
|
|
5788
|
-
function
|
|
6680
|
+
function getLinkHref2(el) {
|
|
5789
6681
|
const anchor = el instanceof HTMLAnchorElement ? el : el.querySelector("a");
|
|
5790
6682
|
return anchor?.getAttribute("href") ?? "";
|
|
5791
6683
|
}
|
|
@@ -5818,8 +6710,11 @@ function collectEditableNodes() {
|
|
|
5818
6710
|
const url = raw.replace(/^url\(['"]?/, "").replace(/['"]?\)$/, "");
|
|
5819
6711
|
return { key: el.dataset.ohwKey ?? "", type: "bg-image", text: url };
|
|
5820
6712
|
}
|
|
6713
|
+
if (el.dataset.ohwEditable === "video") {
|
|
6714
|
+
return { key: el.dataset.ohwKey ?? "", type: "video", text: getVideoEl(el)?.src ?? "" };
|
|
6715
|
+
}
|
|
5821
6716
|
if (el.dataset.ohwEditable === "link") {
|
|
5822
|
-
return { key: el.dataset.ohwKey ?? "", type: "link", text:
|
|
6717
|
+
return { key: el.dataset.ohwKey ?? "", type: "link", text: getLinkHref2(el) };
|
|
5823
6718
|
}
|
|
5824
6719
|
return {
|
|
5825
6720
|
key: el.dataset.ohwKey ?? "",
|
|
@@ -5830,9 +6725,79 @@ function collectEditableNodes() {
|
|
|
5830
6725
|
document.querySelectorAll("[data-ohw-href-key]").forEach((el) => {
|
|
5831
6726
|
const key = el.getAttribute("data-ohw-href-key") ?? "";
|
|
5832
6727
|
if (!key) return;
|
|
5833
|
-
nodes.push({ key, type: "link", text:
|
|
6728
|
+
nodes.push({ key, type: "link", text: getLinkHref2(el) });
|
|
6729
|
+
});
|
|
6730
|
+
document.querySelectorAll('[data-ohw-editable="video"]').forEach((el) => {
|
|
6731
|
+
const key = el.dataset.ohwKey ?? "";
|
|
6732
|
+
const video = getVideoEl(el);
|
|
6733
|
+
if (!key || !video) return;
|
|
6734
|
+
nodes.push({ key: `${key}${VIDEO_AUTOPLAY_SUFFIX}`, type: "video-setting", text: String(video.autoplay) });
|
|
6735
|
+
nodes.push({ key: `${key}${VIDEO_MUTED_SUFFIX}`, type: "video-setting", text: String(video.muted) });
|
|
6736
|
+
});
|
|
6737
|
+
return nodes;
|
|
6738
|
+
}
|
|
6739
|
+
function isMediaEditable(el) {
|
|
6740
|
+
const t = el.dataset.ohwEditable;
|
|
6741
|
+
return t === "image" || t === "bg-image" || t === "video";
|
|
6742
|
+
}
|
|
6743
|
+
var MEDIA_SELECTOR = '[data-ohw-editable="image"], [data-ohw-editable="bg-image"], [data-ohw-editable="video"]';
|
|
6744
|
+
var NON_MEDIA_SELECTOR = '[data-ohw-editable]:not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]):not([data-ohw-editable="video"])';
|
|
6745
|
+
function getVideoEl(el) {
|
|
6746
|
+
return el instanceof HTMLVideoElement ? el : el.querySelector("video");
|
|
6747
|
+
}
|
|
6748
|
+
var VIDEO_AUTOPLAY_SUFFIX = "__ohw_autoplay";
|
|
6749
|
+
var VIDEO_MUTED_SUFFIX = "__ohw_muted";
|
|
6750
|
+
function isBackgroundVideo(video) {
|
|
6751
|
+
return video.autoplay && video.muted;
|
|
6752
|
+
}
|
|
6753
|
+
function syncVideoPlayback(video) {
|
|
6754
|
+
const background = isBackgroundVideo(video);
|
|
6755
|
+
video.controls = !background;
|
|
6756
|
+
if (video.autoplay) void video.play().catch(() => {
|
|
6757
|
+
});
|
|
6758
|
+
else video.pause();
|
|
6759
|
+
}
|
|
6760
|
+
function lockVideoBox(video) {
|
|
6761
|
+
const { width, height } = video.getBoundingClientRect();
|
|
6762
|
+
if (width > 0 && height > 0 && !video.style.aspectRatio) {
|
|
6763
|
+
video.style.aspectRatio = `${width} / ${height}`;
|
|
6764
|
+
}
|
|
6765
|
+
if (getComputedStyle(video).objectFit === "fill") {
|
|
6766
|
+
video.style.objectFit = "contain";
|
|
6767
|
+
}
|
|
6768
|
+
const fit = video.style.objectFit || getComputedStyle(video).objectFit;
|
|
6769
|
+
const bg = getComputedStyle(video).backgroundColor;
|
|
6770
|
+
const isTransparent = bg === "rgba(0, 0, 0, 0)" || bg === "transparent" || !bg;
|
|
6771
|
+
if (fit === "contain" && isTransparent) {
|
|
6772
|
+
video.style.backgroundColor = "var(--color-dark, #000)";
|
|
6773
|
+
}
|
|
6774
|
+
}
|
|
6775
|
+
function applyVideoSrc(video, url) {
|
|
6776
|
+
const { autoplay, muted } = video;
|
|
6777
|
+
lockVideoBox(video);
|
|
6778
|
+
video.src = url;
|
|
6779
|
+
video.loop = true;
|
|
6780
|
+
video.playsInline = true;
|
|
6781
|
+
video.autoplay = autoplay;
|
|
6782
|
+
video.muted = muted;
|
|
6783
|
+
video.load();
|
|
6784
|
+
syncVideoPlayback(video);
|
|
6785
|
+
}
|
|
6786
|
+
function applyVideoSettingNode(key, val) {
|
|
6787
|
+
const isAutoplay = key.endsWith(VIDEO_AUTOPLAY_SUFFIX);
|
|
6788
|
+
const isMuted = key.endsWith(VIDEO_MUTED_SUFFIX);
|
|
6789
|
+
if (!isAutoplay && !isMuted) return false;
|
|
6790
|
+
const suffixLen = (isAutoplay ? VIDEO_AUTOPLAY_SUFFIX : VIDEO_MUTED_SUFFIX).length;
|
|
6791
|
+
const baseKey = key.slice(0, key.length - suffixLen);
|
|
6792
|
+
const on = val === "true";
|
|
6793
|
+
document.querySelectorAll(`[data-ohw-key="${baseKey}"]`).forEach((el) => {
|
|
6794
|
+
const video = getVideoEl(el);
|
|
6795
|
+
if (!video) return;
|
|
6796
|
+
if (isAutoplay) video.autoplay = on;
|
|
6797
|
+
else video.muted = on;
|
|
6798
|
+
syncVideoPlayback(video);
|
|
5834
6799
|
});
|
|
5835
|
-
return
|
|
6800
|
+
return true;
|
|
5836
6801
|
}
|
|
5837
6802
|
function applyLinkByKey(key, val) {
|
|
5838
6803
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -5846,7 +6811,7 @@ function applyLinkByKey(key, val) {
|
|
|
5846
6811
|
}
|
|
5847
6812
|
function isInsideLinkEditor(target) {
|
|
5848
6813
|
return Boolean(
|
|
5849
|
-
target.closest("[data-ohw-link-popover-root]") || target.closest("[data-ohw-link-modal-root]") || target.closest("[data-ohw-link-page-dropdown]") || target.closest('[data-slot="popover-content"]') || target.closest('[data-slot="dialog-content"]') || target.closest('[data-slot="dialog-overlay"]')
|
|
6814
|
+
target.closest("[data-ohw-link-popover-root]") || target.closest("[data-ohw-link-modal-root]") || target.closest("[data-ohw-link-page-dropdown]") || target.closest("[data-ohw-section-picker]") || target.closest("[data-ohw-navbar-container-chrome]") || target.closest("[data-ohw-navbar-add-button]") || target.closest('[data-slot="popover-content"]') || target.closest('[data-slot="dialog-content"]') || target.closest('[data-slot="dialog-overlay"]')
|
|
5850
6815
|
);
|
|
5851
6816
|
}
|
|
5852
6817
|
function getHrefKeyFromElement(el) {
|
|
@@ -5857,7 +6822,7 @@ function getHrefKeyFromElement(el) {
|
|
|
5857
6822
|
if (!key) return null;
|
|
5858
6823
|
return { anchor, key };
|
|
5859
6824
|
}
|
|
5860
|
-
function
|
|
6825
|
+
function isNavbarButton2(el) {
|
|
5861
6826
|
return Boolean(el.closest('[data-ohw-role="navbar-button"]'));
|
|
5862
6827
|
}
|
|
5863
6828
|
function getNavigationItemAnchor(el) {
|
|
@@ -5869,19 +6834,8 @@ function getNavigationItemAnchor(el) {
|
|
|
5869
6834
|
function isNavigationItem(el) {
|
|
5870
6835
|
return getNavigationItemAnchor(el) !== null;
|
|
5871
6836
|
}
|
|
5872
|
-
function getNavigationItemAddHintTarget(anchor) {
|
|
5873
|
-
const items = listNavigationItems();
|
|
5874
|
-
const idx = items.indexOf(anchor);
|
|
5875
|
-
if (idx >= 0 && idx < items.length - 1) return items[idx + 1];
|
|
5876
|
-
return anchor;
|
|
5877
|
-
}
|
|
5878
|
-
function listNavigationItems() {
|
|
5879
|
-
return Array.from(
|
|
5880
|
-
document.querySelectorAll("nav [data-ohw-href-key], footer [data-ohw-href-key]")
|
|
5881
|
-
).filter((el) => isNavigationItem(el));
|
|
5882
|
-
}
|
|
5883
6837
|
function getNavigationItemReorderState(anchor) {
|
|
5884
|
-
if (
|
|
6838
|
+
if (isNavbarButton2(anchor)) return { key: null, disabled: false };
|
|
5885
6839
|
return getReorderHandleStateFromAnchor(anchor);
|
|
5886
6840
|
}
|
|
5887
6841
|
function getReorderHandleState(el) {
|
|
@@ -5903,6 +6857,120 @@ function clearHrefKeyHover(anchor) {
|
|
|
5903
6857
|
function isInsideNavigationItem(el) {
|
|
5904
6858
|
return getNavigationItemAnchor(el) !== null;
|
|
5905
6859
|
}
|
|
6860
|
+
function getNavigationRoot(el) {
|
|
6861
|
+
const explicit = el.closest("[data-ohw-nav-root]");
|
|
6862
|
+
if (explicit) return explicit;
|
|
6863
|
+
return el.closest("nav, footer, aside");
|
|
6864
|
+
}
|
|
6865
|
+
function findFooterItemGroup(item) {
|
|
6866
|
+
const footer = item.closest("footer");
|
|
6867
|
+
if (!footer) return null;
|
|
6868
|
+
let node = item.parentElement;
|
|
6869
|
+
while (node && node !== footer) {
|
|
6870
|
+
const hasDirectNavItems = Array.from(
|
|
6871
|
+
node.querySelectorAll(":scope > [data-ohw-href-key]")
|
|
6872
|
+
).some(isNavigationItem);
|
|
6873
|
+
if (hasDirectNavItems) return node;
|
|
6874
|
+
node = node.parentElement;
|
|
6875
|
+
}
|
|
6876
|
+
return null;
|
|
6877
|
+
}
|
|
6878
|
+
function isNavigationRoot(el) {
|
|
6879
|
+
return el.hasAttribute("data-ohw-nav-root") || el.matches("nav, footer, aside");
|
|
6880
|
+
}
|
|
6881
|
+
function isInferredFooterGroup(el) {
|
|
6882
|
+
const footer = el.closest("footer");
|
|
6883
|
+
if (!footer || el === footer) return false;
|
|
6884
|
+
return Array.from(el.querySelectorAll(":scope > [data-ohw-href-key]")).some(isNavigationItem);
|
|
6885
|
+
}
|
|
6886
|
+
function isNavigationContainer(el) {
|
|
6887
|
+
return el.hasAttribute("data-ohw-nav-container") || isNavigationRoot(el) || isInferredFooterGroup(el);
|
|
6888
|
+
}
|
|
6889
|
+
function isPointOverNavigation(x, y) {
|
|
6890
|
+
const navRoot = document.querySelector("[data-ohw-nav-root]") ?? document.querySelector("nav");
|
|
6891
|
+
if (!navRoot) return false;
|
|
6892
|
+
const r2 = navRoot.getBoundingClientRect();
|
|
6893
|
+
return x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom;
|
|
6894
|
+
}
|
|
6895
|
+
function isPointOverNavItem(container, x, y) {
|
|
6896
|
+
return Array.from(container.querySelectorAll("[data-ohw-href-key]")).some((el) => {
|
|
6897
|
+
if (!isNavigationItem(el) || isNavbarButton2(el)) return false;
|
|
6898
|
+
const itemRect = el.getBoundingClientRect();
|
|
6899
|
+
return x >= itemRect.left && x <= itemRect.right && y >= itemRect.top && y <= itemRect.bottom;
|
|
6900
|
+
});
|
|
6901
|
+
}
|
|
6902
|
+
function resolveNavContainerSelectionTarget(target, clientX, clientY) {
|
|
6903
|
+
if (getNavigationItemAnchor(target)) return null;
|
|
6904
|
+
if (target.closest('[data-ohw-role="navbar-button"]')) return null;
|
|
6905
|
+
const plainLink = target.closest("a");
|
|
6906
|
+
if (plainLink && !plainLink.hasAttribute("data-ohw-href-key") && !plainLink.closest("[data-ohw-nav-container]")) {
|
|
6907
|
+
return null;
|
|
6908
|
+
}
|
|
6909
|
+
const fromClosest = target.closest("[data-ohw-nav-container]");
|
|
6910
|
+
if (fromClosest && !isPointOverNavItem(fromClosest, clientX, clientY)) {
|
|
6911
|
+
return fromClosest;
|
|
6912
|
+
}
|
|
6913
|
+
const navRoot = target.closest("[data-ohw-nav-root]");
|
|
6914
|
+
if (!navRoot) return null;
|
|
6915
|
+
const container = navRoot.querySelector("[data-ohw-nav-container]");
|
|
6916
|
+
if (!container || isPointOverNavItem(container, clientX, clientY)) return null;
|
|
6917
|
+
if (target === navRoot || target.hasAttribute("data-ohw-nav-root")) {
|
|
6918
|
+
return container;
|
|
6919
|
+
}
|
|
6920
|
+
return null;
|
|
6921
|
+
}
|
|
6922
|
+
function getNavigationSelectionParent(el) {
|
|
6923
|
+
if (isNavigationItem(el)) {
|
|
6924
|
+
const explicit = el.closest("[data-ohw-nav-container]");
|
|
6925
|
+
if (explicit) return explicit;
|
|
6926
|
+
const footerGroup = findFooterItemGroup(el);
|
|
6927
|
+
if (footerGroup) return footerGroup;
|
|
6928
|
+
return getNavigationRoot(el);
|
|
6929
|
+
}
|
|
6930
|
+
if (el.hasAttribute("data-ohw-nav-container") || isInferredFooterGroup(el)) {
|
|
6931
|
+
return getNavigationRoot(el);
|
|
6932
|
+
}
|
|
6933
|
+
return null;
|
|
6934
|
+
}
|
|
6935
|
+
function placeCaretAtPoint(el, x, y) {
|
|
6936
|
+
const selection = window.getSelection();
|
|
6937
|
+
if (!selection) return;
|
|
6938
|
+
if (typeof document.caretRangeFromPoint === "function") {
|
|
6939
|
+
const range = document.caretRangeFromPoint(x, y);
|
|
6940
|
+
if (range && el.contains(range.startContainer)) {
|
|
6941
|
+
selection.removeAllRanges();
|
|
6942
|
+
selection.addRange(range);
|
|
6943
|
+
return;
|
|
6944
|
+
}
|
|
6945
|
+
}
|
|
6946
|
+
const caretPositionFromPoint = document.caretPositionFromPoint;
|
|
6947
|
+
if (typeof caretPositionFromPoint === "function") {
|
|
6948
|
+
const position = caretPositionFromPoint(x, y);
|
|
6949
|
+
if (position && el.contains(position.offsetNode)) {
|
|
6950
|
+
const range = document.createRange();
|
|
6951
|
+
range.setStart(position.offsetNode, position.offset);
|
|
6952
|
+
range.collapse(true);
|
|
6953
|
+
selection.removeAllRanges();
|
|
6954
|
+
selection.addRange(range);
|
|
6955
|
+
}
|
|
6956
|
+
}
|
|
6957
|
+
}
|
|
6958
|
+
function selectAllTextInEditable(el) {
|
|
6959
|
+
const selection = window.getSelection();
|
|
6960
|
+
if (!selection) return;
|
|
6961
|
+
const range = document.createRange();
|
|
6962
|
+
range.selectNodeContents(el);
|
|
6963
|
+
selection.removeAllRanges();
|
|
6964
|
+
selection.addRange(range);
|
|
6965
|
+
}
|
|
6966
|
+
function getNavigationLabelEditable(target) {
|
|
6967
|
+
const editable = target.closest('[data-ohw-editable="text"]');
|
|
6968
|
+
if (!editable) return null;
|
|
6969
|
+
const hrefCtx = getHrefKeyFromElement(editable);
|
|
6970
|
+
const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
|
|
6971
|
+
if (!navAnchor) return null;
|
|
6972
|
+
return { editable, navAnchor };
|
|
6973
|
+
}
|
|
5906
6974
|
function collectSections() {
|
|
5907
6975
|
return collectSectionsFromDom();
|
|
5908
6976
|
}
|
|
@@ -6026,6 +7094,8 @@ var ICONS = {
|
|
|
6026
7094
|
insertUnorderedList: '<line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/>',
|
|
6027
7095
|
insertOrderedList: '<line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"/>'
|
|
6028
7096
|
};
|
|
7097
|
+
var TOOLBAR_PILL_PADDING = 2;
|
|
7098
|
+
var TOOLBAR_TOGGLE_GAP = 4;
|
|
6029
7099
|
var TOOLBAR_GROUPS = [
|
|
6030
7100
|
[
|
|
6031
7101
|
{ cmd: "bold", title: "Bold" },
|
|
@@ -6050,7 +7120,7 @@ function EditGlowChrome({
|
|
|
6050
7120
|
dragDisabled = false
|
|
6051
7121
|
}) {
|
|
6052
7122
|
const GAP = 6;
|
|
6053
|
-
return /* @__PURE__ */
|
|
7123
|
+
return /* @__PURE__ */ jsxs13(
|
|
6054
7124
|
"div",
|
|
6055
7125
|
{
|
|
6056
7126
|
ref: elRef,
|
|
@@ -6065,7 +7135,7 @@ function EditGlowChrome({
|
|
|
6065
7135
|
zIndex: 2147483646
|
|
6066
7136
|
},
|
|
6067
7137
|
children: [
|
|
6068
|
-
/* @__PURE__ */
|
|
7138
|
+
/* @__PURE__ */ jsx23(
|
|
6069
7139
|
"div",
|
|
6070
7140
|
{
|
|
6071
7141
|
style: {
|
|
@@ -6078,7 +7148,7 @@ function EditGlowChrome({
|
|
|
6078
7148
|
}
|
|
6079
7149
|
}
|
|
6080
7150
|
),
|
|
6081
|
-
reorderHrefKey && /* @__PURE__ */
|
|
7151
|
+
reorderHrefKey && /* @__PURE__ */ jsx23(
|
|
6082
7152
|
"div",
|
|
6083
7153
|
{
|
|
6084
7154
|
"data-ohw-drag-handle-container": "",
|
|
@@ -6090,7 +7160,7 @@ function EditGlowChrome({
|
|
|
6090
7160
|
transform: "translate(calc(-100% - 7px), -50%)",
|
|
6091
7161
|
pointerEvents: dragDisabled ? "none" : "auto"
|
|
6092
7162
|
},
|
|
6093
|
-
children: /* @__PURE__ */
|
|
7163
|
+
children: /* @__PURE__ */ jsx23(
|
|
6094
7164
|
DragHandle,
|
|
6095
7165
|
{
|
|
6096
7166
|
"aria-label": `Reorder ${reorderHrefKey}`,
|
|
@@ -6194,7 +7264,7 @@ function FloatingToolbar({
|
|
|
6194
7264
|
onEditLink
|
|
6195
7265
|
}) {
|
|
6196
7266
|
const { top, left, transform } = calcToolbarPos(rect, parentScroll, 330);
|
|
6197
|
-
return /* @__PURE__ */
|
|
7267
|
+
return /* @__PURE__ */ jsx23(
|
|
6198
7268
|
"div",
|
|
6199
7269
|
{
|
|
6200
7270
|
ref: elRef,
|
|
@@ -6204,14 +7274,23 @@ function FloatingToolbar({
|
|
|
6204
7274
|
left,
|
|
6205
7275
|
transform,
|
|
6206
7276
|
zIndex: 2147483647,
|
|
7277
|
+
background: "#fff",
|
|
7278
|
+
border: "1px solid #E7E5E4",
|
|
7279
|
+
borderRadius: 6,
|
|
7280
|
+
boxShadow: "0px 2px 4px -2px rgba(0,0,0,.1),0px 4px 6px -1px rgba(0,0,0,.1)",
|
|
7281
|
+
display: "flex",
|
|
7282
|
+
alignItems: "center",
|
|
7283
|
+
padding: TOOLBAR_PILL_PADDING,
|
|
7284
|
+
gap: TOOLBAR_TOGGLE_GAP,
|
|
7285
|
+
fontFamily: "sans-serif",
|
|
6207
7286
|
pointerEvents: "auto"
|
|
6208
7287
|
},
|
|
6209
|
-
children: /* @__PURE__ */
|
|
6210
|
-
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */
|
|
6211
|
-
gi > 0 && /* @__PURE__ */
|
|
7288
|
+
children: /* @__PURE__ */ jsxs13(CustomToolbar, { children: [
|
|
7289
|
+
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs13(React9.Fragment, { children: [
|
|
7290
|
+
gi > 0 && /* @__PURE__ */ jsx23(CustomToolbarDivider, {}),
|
|
6212
7291
|
btns.map((btn) => {
|
|
6213
7292
|
const isActive = activeCommands.has(btn.cmd);
|
|
6214
|
-
return /* @__PURE__ */
|
|
7293
|
+
return /* @__PURE__ */ jsx23(
|
|
6215
7294
|
CustomToolbarButton,
|
|
6216
7295
|
{
|
|
6217
7296
|
title: btn.title,
|
|
@@ -6220,7 +7299,7 @@ function FloatingToolbar({
|
|
|
6220
7299
|
e.preventDefault();
|
|
6221
7300
|
onCommand(btn.cmd);
|
|
6222
7301
|
},
|
|
6223
|
-
children: /* @__PURE__ */
|
|
7302
|
+
children: /* @__PURE__ */ jsx23(
|
|
6224
7303
|
"svg",
|
|
6225
7304
|
{
|
|
6226
7305
|
width: "16",
|
|
@@ -6241,7 +7320,7 @@ function FloatingToolbar({
|
|
|
6241
7320
|
);
|
|
6242
7321
|
})
|
|
6243
7322
|
] }, gi)),
|
|
6244
|
-
showEditLink ? /* @__PURE__ */
|
|
7323
|
+
showEditLink ? /* @__PURE__ */ jsx23(
|
|
6245
7324
|
CustomToolbarButton,
|
|
6246
7325
|
{
|
|
6247
7326
|
type: "button",
|
|
@@ -6255,7 +7334,7 @@ function FloatingToolbar({
|
|
|
6255
7334
|
e.preventDefault();
|
|
6256
7335
|
e.stopPropagation();
|
|
6257
7336
|
},
|
|
6258
|
-
children: /* @__PURE__ */
|
|
7337
|
+
children: /* @__PURE__ */ jsx23(Link2, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
6259
7338
|
}
|
|
6260
7339
|
) : null
|
|
6261
7340
|
] })
|
|
@@ -6272,7 +7351,7 @@ function StateToggle({
|
|
|
6272
7351
|
states,
|
|
6273
7352
|
onStateChange
|
|
6274
7353
|
}) {
|
|
6275
|
-
return /* @__PURE__ */
|
|
7354
|
+
return /* @__PURE__ */ jsx23(
|
|
6276
7355
|
ToggleGroup,
|
|
6277
7356
|
{
|
|
6278
7357
|
"data-ohw-state-toggle": "",
|
|
@@ -6286,7 +7365,7 @@ function StateToggle({
|
|
|
6286
7365
|
left: rect.right - 8,
|
|
6287
7366
|
transform: "translateX(-100%)"
|
|
6288
7367
|
},
|
|
6289
|
-
children: states.map((state) => /* @__PURE__ */
|
|
7368
|
+
children: states.map((state) => /* @__PURE__ */ jsx23(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
|
|
6290
7369
|
}
|
|
6291
7370
|
);
|
|
6292
7371
|
}
|
|
@@ -6309,12 +7388,12 @@ function resolveSubdomain(subdomainFromQuery) {
|
|
|
6309
7388
|
return "";
|
|
6310
7389
|
}
|
|
6311
7390
|
function OhhwellsBridge() {
|
|
6312
|
-
const pathname =
|
|
6313
|
-
const router =
|
|
7391
|
+
const pathname = usePathname2();
|
|
7392
|
+
const router = useRouter2();
|
|
6314
7393
|
const searchParams = useSearchParams();
|
|
6315
7394
|
const isEditMode = isEditSessionActive();
|
|
6316
|
-
const [bridgeRoot, setBridgeRoot] =
|
|
6317
|
-
|
|
7395
|
+
const [bridgeRoot, setBridgeRoot] = useState6(null);
|
|
7396
|
+
useEffect7(() => {
|
|
6318
7397
|
const figtreeFontId = "ohw-figtree-font";
|
|
6319
7398
|
if (!document.getElementById(figtreeFontId)) {
|
|
6320
7399
|
const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
|
|
@@ -6322,7 +7401,10 @@ function OhhwellsBridge() {
|
|
|
6322
7401
|
const stylesheet = Object.assign(document.createElement("link"), {
|
|
6323
7402
|
id: figtreeFontId,
|
|
6324
7403
|
rel: "stylesheet",
|
|
6325
|
-
|
|
7404
|
+
// Inter is loaded alongside Figtree for the media overlay's Replace button. The bridge
|
|
7405
|
+
// renders inside the customer's document, so it cannot assume any font is present — an
|
|
7406
|
+
// unloaded family would silently fall back to whatever the template happens to use.
|
|
7407
|
+
href: "https://fonts.googleapis.com/css2?family=Figtree:ital,wght@0,300..900;1,300..900&family=Inter:wght@400;500;600&display=swap"
|
|
6326
7408
|
});
|
|
6327
7409
|
document.head.append(preconnect1, preconnect2, stylesheet);
|
|
6328
7410
|
}
|
|
@@ -6339,80 +7421,91 @@ function OhhwellsBridge() {
|
|
|
6339
7421
|
const subdomainFromQuery = searchParams.get("subdomain");
|
|
6340
7422
|
const subdomain = resolveSubdomain(subdomainFromQuery);
|
|
6341
7423
|
useLinkHrefGuardian(pathname, subdomain, isEditMode);
|
|
6342
|
-
const
|
|
7424
|
+
const postToParent2 = useCallback4((data) => {
|
|
6343
7425
|
if (typeof window !== "undefined" && window.parent !== window) {
|
|
6344
7426
|
window.parent.postMessage(data, "*");
|
|
6345
7427
|
}
|
|
6346
7428
|
}, []);
|
|
6347
|
-
const [fetchState, setFetchState] =
|
|
6348
|
-
const autoSaveTimers =
|
|
6349
|
-
const activeElRef =
|
|
6350
|
-
const selectedElRef =
|
|
6351
|
-
const originalContentRef =
|
|
6352
|
-
const activeStateElRef =
|
|
6353
|
-
const parentScrollRef =
|
|
6354
|
-
const visibleViewportRef =
|
|
6355
|
-
const [dialogPortalContainer, setDialogPortalContainer] =
|
|
6356
|
-
const attachVisibleViewport =
|
|
7429
|
+
const [fetchState, setFetchState] = useState6("idle");
|
|
7430
|
+
const autoSaveTimers = useRef4(/* @__PURE__ */ new Map());
|
|
7431
|
+
const activeElRef = useRef4(null);
|
|
7432
|
+
const selectedElRef = useRef4(null);
|
|
7433
|
+
const originalContentRef = useRef4(null);
|
|
7434
|
+
const activeStateElRef = useRef4(null);
|
|
7435
|
+
const parentScrollRef = useRef4(null);
|
|
7436
|
+
const visibleViewportRef = useRef4(null);
|
|
7437
|
+
const [dialogPortalContainer, setDialogPortalContainer] = useState6(null);
|
|
7438
|
+
const attachVisibleViewport = useCallback4((node) => {
|
|
6357
7439
|
visibleViewportRef.current = node;
|
|
6358
7440
|
setDialogPortalContainer(node);
|
|
6359
7441
|
if (node) applyVisibleViewport(node, parentScrollRef.current);
|
|
6360
7442
|
}, []);
|
|
6361
|
-
const toolbarElRef =
|
|
6362
|
-
const glowElRef =
|
|
6363
|
-
const hoveredImageRef =
|
|
6364
|
-
const hoveredImageHasTextOverlapRef =
|
|
6365
|
-
const
|
|
6366
|
-
const
|
|
6367
|
-
const
|
|
6368
|
-
const
|
|
6369
|
-
const
|
|
7443
|
+
const toolbarElRef = useRef4(null);
|
|
7444
|
+
const glowElRef = useRef4(null);
|
|
7445
|
+
const hoveredImageRef = useRef4(null);
|
|
7446
|
+
const hoveredImageHasTextOverlapRef = useRef4(false);
|
|
7447
|
+
const dragOverElRef = useRef4(null);
|
|
7448
|
+
const [mediaHover, setMediaHover] = useState6(null);
|
|
7449
|
+
const [uploadingRects, setUploadingRects] = useState6({});
|
|
7450
|
+
const hoveredGapRef = useRef4(null);
|
|
7451
|
+
const imageUnhoverTimerRef = useRef4(null);
|
|
7452
|
+
const imageShowTimerRef = useRef4(null);
|
|
7453
|
+
const editStylesRef = useRef4(null);
|
|
7454
|
+
const activateRef = useRef4(() => {
|
|
7455
|
+
});
|
|
7456
|
+
const deactivateRef = useRef4(() => {
|
|
6370
7457
|
});
|
|
6371
|
-
const
|
|
7458
|
+
const selectRef = useRef4(() => {
|
|
6372
7459
|
});
|
|
6373
|
-
const
|
|
7460
|
+
const selectFrameRef = useRef4(() => {
|
|
6374
7461
|
});
|
|
6375
|
-
const deselectRef =
|
|
7462
|
+
const deselectRef = useRef4(() => {
|
|
6376
7463
|
});
|
|
6377
|
-
const reselectNavigationItemRef =
|
|
7464
|
+
const reselectNavigationItemRef = useRef4(() => {
|
|
6378
7465
|
});
|
|
6379
|
-
const commitNavigationTextEditRef =
|
|
7466
|
+
const commitNavigationTextEditRef = useRef4(() => {
|
|
6380
7467
|
});
|
|
6381
|
-
const refreshActiveCommandsRef =
|
|
7468
|
+
const refreshActiveCommandsRef = useRef4(() => {
|
|
6382
7469
|
});
|
|
6383
|
-
const postToParentRef =
|
|
6384
|
-
postToParentRef.current =
|
|
6385
|
-
const sectionsLoadedRef =
|
|
6386
|
-
const pendingScheduleConfigRequests =
|
|
6387
|
-
const [toolbarRect, setToolbarRect] =
|
|
6388
|
-
const [toolbarVariant, setToolbarVariant] =
|
|
6389
|
-
const toolbarVariantRef =
|
|
7470
|
+
const postToParentRef = useRef4(postToParent2);
|
|
7471
|
+
postToParentRef.current = postToParent2;
|
|
7472
|
+
const sectionsLoadedRef = useRef4(false);
|
|
7473
|
+
const pendingScheduleConfigRequests = useRef4([]);
|
|
7474
|
+
const [toolbarRect, setToolbarRect] = useState6(null);
|
|
7475
|
+
const [toolbarVariant, setToolbarVariant] = useState6("none");
|
|
7476
|
+
const toolbarVariantRef = useRef4("none");
|
|
6390
7477
|
toolbarVariantRef.current = toolbarVariant;
|
|
6391
|
-
const [reorderHrefKey, setReorderHrefKey] =
|
|
6392
|
-
const [reorderDragDisabled, setReorderDragDisabled] =
|
|
6393
|
-
const [toggleState, setToggleState] =
|
|
6394
|
-
const [maxBadge, setMaxBadge] =
|
|
6395
|
-
const [activeCommands, setActiveCommands] =
|
|
6396
|
-
const [sectionGap, setSectionGap] =
|
|
6397
|
-
const [toolbarShowEditLink, setToolbarShowEditLink] =
|
|
6398
|
-
const
|
|
6399
|
-
const [
|
|
6400
|
-
const
|
|
6401
|
-
const [
|
|
6402
|
-
const
|
|
6403
|
-
const [
|
|
6404
|
-
const [
|
|
6405
|
-
const [
|
|
6406
|
-
const
|
|
6407
|
-
const
|
|
6408
|
-
const
|
|
6409
|
-
const
|
|
6410
|
-
const
|
|
7478
|
+
const [reorderHrefKey, setReorderHrefKey] = useState6(null);
|
|
7479
|
+
const [reorderDragDisabled, setReorderDragDisabled] = useState6(false);
|
|
7480
|
+
const [toggleState, setToggleState] = useState6(null);
|
|
7481
|
+
const [maxBadge, setMaxBadge] = useState6(null);
|
|
7482
|
+
const [activeCommands, setActiveCommands] = useState6(/* @__PURE__ */ new Set());
|
|
7483
|
+
const [sectionGap, setSectionGap] = useState6(null);
|
|
7484
|
+
const [toolbarShowEditLink, setToolbarShowEditLink] = useState6(false);
|
|
7485
|
+
const hoveredNavContainerRef = useRef4(null);
|
|
7486
|
+
const [hoveredNavContainerRect, setHoveredNavContainerRect] = useState6(null);
|
|
7487
|
+
const hoveredItemElRef = useRef4(null);
|
|
7488
|
+
const [hoveredItemRect, setHoveredItemRect] = useState6(null);
|
|
7489
|
+
const siblingHintElRef = useRef4(null);
|
|
7490
|
+
const [siblingHintRect, setSiblingHintRect] = useState6(null);
|
|
7491
|
+
const [isItemDragging, setIsItemDragging] = useState6(false);
|
|
7492
|
+
const [linkPopover, setLinkPopover] = useState6(null);
|
|
7493
|
+
const linkPopoverSessionRef = useRef4(null);
|
|
7494
|
+
const addNavAfterAnchorRef = useRef4(null);
|
|
7495
|
+
const editContentRef = useRef4({});
|
|
7496
|
+
const [sitePages, setSitePages] = useState6([]);
|
|
7497
|
+
const [sectionsByPath, setSectionsByPath] = useState6({});
|
|
7498
|
+
const sectionsPrefetchGenRef = useRef4(0);
|
|
7499
|
+
const setLinkPopoverRef = useRef4(setLinkPopover);
|
|
7500
|
+
const linkPopoverPanelRef = useRef4(null);
|
|
7501
|
+
const linkPopoverOpenRef = useRef4(false);
|
|
7502
|
+
const linkPopoverGraceUntilRef = useRef4(0);
|
|
6411
7503
|
setLinkPopoverRef.current = setLinkPopover;
|
|
7504
|
+
linkPopoverSessionRef.current = linkPopover;
|
|
6412
7505
|
const bumpLinkPopoverGrace = () => {
|
|
6413
7506
|
linkPopoverGraceUntilRef.current = Date.now() + 350;
|
|
6414
7507
|
};
|
|
6415
|
-
const runSectionsPrefetch =
|
|
7508
|
+
const runSectionsPrefetch = useCallback4((pages) => {
|
|
6416
7509
|
if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
|
|
6417
7510
|
const gen = ++sectionsPrefetchGenRef.current;
|
|
6418
7511
|
const paths = pages.map((p) => p.path);
|
|
@@ -6431,9 +7524,9 @@ function OhhwellsBridge() {
|
|
|
6431
7524
|
);
|
|
6432
7525
|
});
|
|
6433
7526
|
}, [isEditMode, pathname]);
|
|
6434
|
-
const runSectionsPrefetchRef =
|
|
7527
|
+
const runSectionsPrefetchRef = useRef4(runSectionsPrefetch);
|
|
6435
7528
|
runSectionsPrefetchRef.current = runSectionsPrefetch;
|
|
6436
|
-
|
|
7529
|
+
useEffect7(() => {
|
|
6437
7530
|
if (!linkPopover) return;
|
|
6438
7531
|
if (hoveredImageRef.current) {
|
|
6439
7532
|
hoveredImageRef.current = null;
|
|
@@ -6441,33 +7534,9 @@ function OhhwellsBridge() {
|
|
|
6441
7534
|
}
|
|
6442
7535
|
hoveredGapRef.current = null;
|
|
6443
7536
|
setSectionGap(null);
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
|
|
6447
|
-
const body = document.body;
|
|
6448
|
-
const prevHtmlOverflow = html.style.overflow;
|
|
6449
|
-
const prevBodyOverflow = body.style.overflow;
|
|
6450
|
-
html.style.overflow = "hidden";
|
|
6451
|
-
body.style.overflow = "hidden";
|
|
6452
|
-
const preventBackgroundScroll = (e) => {
|
|
6453
|
-
const target = e.target;
|
|
6454
|
-
if (target instanceof Element && target.closest('[data-ohw-link-modal-root], [data-slot="dialog-overlay"]')) {
|
|
6455
|
-
return;
|
|
6456
|
-
}
|
|
6457
|
-
e.preventDefault();
|
|
6458
|
-
};
|
|
6459
|
-
const scrollOpts = { passive: false, capture: true };
|
|
6460
|
-
document.addEventListener("wheel", preventBackgroundScroll, scrollOpts);
|
|
6461
|
-
document.addEventListener("touchmove", preventBackgroundScroll, scrollOpts);
|
|
6462
|
-
return () => {
|
|
6463
|
-
postToParent({ type: "ow:link-modal-lock", locked: false });
|
|
6464
|
-
html.style.overflow = prevHtmlOverflow;
|
|
6465
|
-
body.style.overflow = prevBodyOverflow;
|
|
6466
|
-
document.removeEventListener("wheel", preventBackgroundScroll, scrollOpts);
|
|
6467
|
-
document.removeEventListener("touchmove", preventBackgroundScroll, scrollOpts);
|
|
6468
|
-
};
|
|
6469
|
-
}, [linkPopover, postToParent]);
|
|
6470
|
-
useEffect3(() => {
|
|
7537
|
+
postToParent2({ type: "ow:image-unhover" });
|
|
7538
|
+
}, [linkPopover, postToParent2]);
|
|
7539
|
+
useEffect7(() => {
|
|
6471
7540
|
if (!isEditMode) return;
|
|
6472
7541
|
const useFixtures = shouldUseDevFixtures();
|
|
6473
7542
|
if (useFixtures) {
|
|
@@ -6488,17 +7557,17 @@ function OhhwellsBridge() {
|
|
|
6488
7557
|
runSectionsPrefetchRef.current(mapped);
|
|
6489
7558
|
};
|
|
6490
7559
|
window.addEventListener("message", onSitePages);
|
|
6491
|
-
if (!useFixtures)
|
|
7560
|
+
if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
|
|
6492
7561
|
return () => window.removeEventListener("message", onSitePages);
|
|
6493
|
-
}, [isEditMode,
|
|
6494
|
-
|
|
7562
|
+
}, [isEditMode, postToParent2]);
|
|
7563
|
+
useEffect7(() => {
|
|
6495
7564
|
if (!isEditMode || shouldUseDevFixtures()) return;
|
|
6496
7565
|
void loadAllSectionsManifest().then((manifest) => {
|
|
6497
7566
|
if (Object.keys(manifest).length === 0) return;
|
|
6498
7567
|
setSectionsByPath((prev) => ({ ...manifest, ...prev }));
|
|
6499
7568
|
});
|
|
6500
7569
|
}, [isEditMode]);
|
|
6501
|
-
|
|
7570
|
+
useEffect7(() => {
|
|
6502
7571
|
const update = () => {
|
|
6503
7572
|
const el = activeElRef.current ?? selectedElRef.current;
|
|
6504
7573
|
if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
@@ -6522,10 +7591,10 @@ function OhhwellsBridge() {
|
|
|
6522
7591
|
vvp.removeEventListener("resize", update);
|
|
6523
7592
|
};
|
|
6524
7593
|
}, []);
|
|
6525
|
-
const refreshStateRules =
|
|
7594
|
+
const refreshStateRules = useCallback4(() => {
|
|
6526
7595
|
editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
|
|
6527
7596
|
}, []);
|
|
6528
|
-
const processConfigRequest =
|
|
7597
|
+
const processConfigRequest = useCallback4((insertAfterVal) => {
|
|
6529
7598
|
const tracker = getSectionsTracker();
|
|
6530
7599
|
let entries = [];
|
|
6531
7600
|
try {
|
|
@@ -6548,7 +7617,7 @@ function OhhwellsBridge() {
|
|
|
6548
7617
|
}
|
|
6549
7618
|
window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
|
|
6550
7619
|
}, [isEditMode]);
|
|
6551
|
-
const deactivate =
|
|
7620
|
+
const deactivate = useCallback4(() => {
|
|
6552
7621
|
const el = activeElRef.current;
|
|
6553
7622
|
if (!el) return;
|
|
6554
7623
|
const key = el.dataset.ohwKey;
|
|
@@ -6577,21 +7646,23 @@ function OhhwellsBridge() {
|
|
|
6577
7646
|
setMaxBadge(null);
|
|
6578
7647
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
6579
7648
|
setToolbarShowEditLink(false);
|
|
6580
|
-
|
|
6581
|
-
}, [
|
|
6582
|
-
const deselect =
|
|
7649
|
+
postToParent2({ type: "ow:exit-edit" });
|
|
7650
|
+
}, [postToParent2]);
|
|
7651
|
+
const deselect = useCallback4(() => {
|
|
6583
7652
|
selectedElRef.current = null;
|
|
6584
7653
|
setReorderHrefKey(null);
|
|
6585
7654
|
setReorderDragDisabled(false);
|
|
6586
7655
|
siblingHintElRef.current = null;
|
|
6587
7656
|
setSiblingHintRect(null);
|
|
6588
7657
|
setIsItemDragging(false);
|
|
7658
|
+
hoveredNavContainerRef.current = null;
|
|
7659
|
+
setHoveredNavContainerRect(null);
|
|
6589
7660
|
if (!activeElRef.current) {
|
|
6590
7661
|
setToolbarRect(null);
|
|
6591
7662
|
setToolbarVariant("none");
|
|
6592
7663
|
}
|
|
6593
7664
|
}, []);
|
|
6594
|
-
const reselectNavigationItem =
|
|
7665
|
+
const reselectNavigationItem = useCallback4((navAnchor) => {
|
|
6595
7666
|
selectedElRef.current = navAnchor;
|
|
6596
7667
|
const { key, disabled } = getNavigationItemReorderState(navAnchor);
|
|
6597
7668
|
setReorderHrefKey(key);
|
|
@@ -6601,7 +7672,7 @@ function OhhwellsBridge() {
|
|
|
6601
7672
|
setToolbarShowEditLink(false);
|
|
6602
7673
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
6603
7674
|
}, []);
|
|
6604
|
-
const commitNavigationTextEdit =
|
|
7675
|
+
const commitNavigationTextEdit = useCallback4((navAnchor) => {
|
|
6605
7676
|
const el = activeElRef.current;
|
|
6606
7677
|
if (!el) return;
|
|
6607
7678
|
const key = el.dataset.ohwKey;
|
|
@@ -6614,9 +7685,9 @@ function OhhwellsBridge() {
|
|
|
6614
7685
|
const html = sanitizeHtml(el.innerHTML);
|
|
6615
7686
|
const original = originalContentRef.current ?? "";
|
|
6616
7687
|
if (html !== sanitizeHtml(original)) {
|
|
6617
|
-
|
|
7688
|
+
postToParent2({ type: "ow:change", nodes: [{ key, text: html }] });
|
|
6618
7689
|
const h = document.documentElement.scrollHeight;
|
|
6619
|
-
if (h > 50)
|
|
7690
|
+
if (h > 50) postToParent2({ type: "ow:height", height: h });
|
|
6620
7691
|
}
|
|
6621
7692
|
}
|
|
6622
7693
|
el.removeAttribute("contenteditable");
|
|
@@ -6624,31 +7695,38 @@ function OhhwellsBridge() {
|
|
|
6624
7695
|
setMaxBadge(null);
|
|
6625
7696
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
6626
7697
|
setToolbarShowEditLink(false);
|
|
6627
|
-
|
|
7698
|
+
postToParent2({ type: "ow:exit-edit" });
|
|
6628
7699
|
reselectNavigationItem(navAnchor);
|
|
6629
|
-
}, [
|
|
6630
|
-
const
|
|
6631
|
-
const
|
|
6632
|
-
|
|
6633
|
-
|
|
6634
|
-
|
|
6635
|
-
|
|
7700
|
+
}, [postToParent2, reselectNavigationItem]);
|
|
7701
|
+
const handleAddTopLevelNavItem = useCallback4(() => {
|
|
7702
|
+
const items = listNavbarItems();
|
|
7703
|
+
addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
|
|
7704
|
+
deselectRef.current();
|
|
7705
|
+
deactivateRef.current();
|
|
7706
|
+
bumpLinkPopoverGrace();
|
|
7707
|
+
setLinkPopover({
|
|
7708
|
+
key: "__add-nav__",
|
|
7709
|
+
mode: "create",
|
|
7710
|
+
intent: "add-nav"
|
|
7711
|
+
});
|
|
6636
7712
|
}, []);
|
|
6637
|
-
const handleItemDragStart =
|
|
7713
|
+
const handleItemDragStart = useCallback4(() => {
|
|
6638
7714
|
siblingHintElRef.current = null;
|
|
6639
7715
|
setSiblingHintRect(null);
|
|
6640
7716
|
setIsItemDragging(true);
|
|
6641
7717
|
}, []);
|
|
6642
|
-
const handleItemDragEnd =
|
|
7718
|
+
const handleItemDragEnd = useCallback4(() => {
|
|
6643
7719
|
setIsItemDragging(false);
|
|
6644
7720
|
}, []);
|
|
6645
7721
|
reselectNavigationItemRef.current = reselectNavigationItem;
|
|
6646
7722
|
commitNavigationTextEditRef.current = commitNavigationTextEdit;
|
|
6647
|
-
const select =
|
|
7723
|
+
const select = useCallback4((anchor) => {
|
|
6648
7724
|
if (!isNavigationItem(anchor)) return;
|
|
6649
7725
|
if (activeElRef.current) deactivate();
|
|
6650
7726
|
selectedElRef.current = anchor;
|
|
6651
7727
|
clearHrefKeyHover(anchor);
|
|
7728
|
+
hoveredNavContainerRef.current = null;
|
|
7729
|
+
setHoveredNavContainerRect(null);
|
|
6652
7730
|
setHoveredItemRect(null);
|
|
6653
7731
|
hoveredItemElRef.current = null;
|
|
6654
7732
|
siblingHintElRef.current = null;
|
|
@@ -6662,13 +7740,32 @@ function OhhwellsBridge() {
|
|
|
6662
7740
|
setToolbarShowEditLink(false);
|
|
6663
7741
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
6664
7742
|
}, [deactivate]);
|
|
6665
|
-
const
|
|
7743
|
+
const selectFrame = useCallback4((el) => {
|
|
7744
|
+
if (!isNavigationContainer(el)) return;
|
|
7745
|
+
if (activeElRef.current) deactivate();
|
|
7746
|
+
selectedElRef.current = el;
|
|
7747
|
+
clearHrefKeyHover(el);
|
|
7748
|
+
hoveredNavContainerRef.current = null;
|
|
7749
|
+
setHoveredNavContainerRect(null);
|
|
7750
|
+
setHoveredItemRect(null);
|
|
7751
|
+
hoveredItemElRef.current = null;
|
|
7752
|
+
siblingHintElRef.current = null;
|
|
7753
|
+
setSiblingHintRect(null);
|
|
7754
|
+
setIsItemDragging(false);
|
|
7755
|
+
setReorderHrefKey(null);
|
|
7756
|
+
setReorderDragDisabled(false);
|
|
7757
|
+
setToolbarVariant("select-frame");
|
|
7758
|
+
setToolbarRect(el.getBoundingClientRect());
|
|
7759
|
+
setToolbarShowEditLink(false);
|
|
7760
|
+
setActiveCommands(/* @__PURE__ */ new Set());
|
|
7761
|
+
}, [deactivate]);
|
|
7762
|
+
const activate = useCallback4((el, options) => {
|
|
6666
7763
|
if (activeElRef.current === el) return;
|
|
6667
7764
|
selectedElRef.current = null;
|
|
6668
7765
|
deactivate();
|
|
6669
7766
|
if (hoveredImageRef.current) {
|
|
6670
7767
|
hoveredImageRef.current = null;
|
|
6671
|
-
|
|
7768
|
+
setMediaHover(null);
|
|
6672
7769
|
}
|
|
6673
7770
|
setToolbarVariant("rich-text");
|
|
6674
7771
|
siblingHintElRef.current = null;
|
|
@@ -6680,6 +7777,9 @@ function OhhwellsBridge() {
|
|
|
6680
7777
|
activeElRef.current = el;
|
|
6681
7778
|
originalContentRef.current = el.innerHTML;
|
|
6682
7779
|
el.focus();
|
|
7780
|
+
if (options?.caretX !== void 0 && options?.caretY !== void 0) {
|
|
7781
|
+
placeCaretAtPoint(el, options.caretX, options.caretY);
|
|
7782
|
+
}
|
|
6683
7783
|
setToolbarShowEditLink(Boolean(getHrefKeyFromElement(el)));
|
|
6684
7784
|
const navAnchor = getNavigationItemAnchor(el);
|
|
6685
7785
|
if (navAnchor) {
|
|
@@ -6691,12 +7791,13 @@ function OhhwellsBridge() {
|
|
|
6691
7791
|
setReorderDragDisabled(reorderDisabled);
|
|
6692
7792
|
}
|
|
6693
7793
|
setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
6694
|
-
|
|
7794
|
+
postToParent2({ type: "ow:enter-edit", key: el.dataset.ohwKey });
|
|
6695
7795
|
requestAnimationFrame(() => refreshActiveCommandsRef.current());
|
|
6696
|
-
}, [deactivate,
|
|
7796
|
+
}, [deactivate, postToParent2]);
|
|
6697
7797
|
activateRef.current = activate;
|
|
6698
7798
|
deactivateRef.current = deactivate;
|
|
6699
7799
|
selectRef.current = select;
|
|
7800
|
+
selectFrameRef.current = selectFrame;
|
|
6700
7801
|
deselectRef.current = deselect;
|
|
6701
7802
|
useLayoutEffect2(() => {
|
|
6702
7803
|
if (!subdomain || isEditMode) {
|
|
@@ -6707,11 +7808,12 @@ function OhhwellsBridge() {
|
|
|
6707
7808
|
const imageLoads = [];
|
|
6708
7809
|
for (const [key, val] of Object.entries(content)) {
|
|
6709
7810
|
if (key === "__ohw_sections") continue;
|
|
7811
|
+
if (applyVideoSettingNode(key, val)) continue;
|
|
6710
7812
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
6711
7813
|
if (el.dataset.ohwEditable === "image") {
|
|
6712
7814
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
6713
7815
|
if (img && img.src !== val) {
|
|
6714
|
-
img
|
|
7816
|
+
applyEditableImageSrc(img, val);
|
|
6715
7817
|
imageLoads.push(new Promise((resolve) => {
|
|
6716
7818
|
img.onload = () => resolve();
|
|
6717
7819
|
img.onerror = () => resolve();
|
|
@@ -6720,6 +7822,15 @@ function OhhwellsBridge() {
|
|
|
6720
7822
|
} else if (el.dataset.ohwEditable === "bg-image") {
|
|
6721
7823
|
const next = `url('${val}')`;
|
|
6722
7824
|
if (el.style.backgroundImage !== next) el.style.backgroundImage = next;
|
|
7825
|
+
} else if (el.dataset.ohwEditable === "video") {
|
|
7826
|
+
const video = getVideoEl(el);
|
|
7827
|
+
if (video && video.src !== val) {
|
|
7828
|
+
applyVideoSrc(video, val);
|
|
7829
|
+
imageLoads.push(new Promise((resolve) => {
|
|
7830
|
+
video.onloadeddata = () => resolve();
|
|
7831
|
+
video.onerror = () => resolve();
|
|
7832
|
+
}));
|
|
7833
|
+
}
|
|
6723
7834
|
} else if (el.dataset.ohwEditable === "link") {
|
|
6724
7835
|
applyLinkHref(el, val);
|
|
6725
7836
|
} else if (el.innerHTML !== val) {
|
|
@@ -6728,6 +7839,7 @@ function OhhwellsBridge() {
|
|
|
6728
7839
|
});
|
|
6729
7840
|
applyLinkByKey(key, val);
|
|
6730
7841
|
}
|
|
7842
|
+
reconcileNavbarItemsFromContent(content);
|
|
6731
7843
|
enforceLinkHrefs();
|
|
6732
7844
|
initSectionsFromContent(content, true);
|
|
6733
7845
|
sectionsLoadedRef.current = true;
|
|
@@ -6756,7 +7868,7 @@ function OhhwellsBridge() {
|
|
|
6756
7868
|
cancelled = true;
|
|
6757
7869
|
};
|
|
6758
7870
|
}, [subdomain, isEditMode]);
|
|
6759
|
-
|
|
7871
|
+
useEffect7(() => {
|
|
6760
7872
|
if (!subdomain || isEditMode) return;
|
|
6761
7873
|
let debounceTimer = null;
|
|
6762
7874
|
let observer = null;
|
|
@@ -6768,13 +7880,17 @@ function OhhwellsBridge() {
|
|
|
6768
7880
|
try {
|
|
6769
7881
|
for (const [key, val] of Object.entries(content)) {
|
|
6770
7882
|
if (key === "__ohw_sections") continue;
|
|
7883
|
+
if (applyVideoSettingNode(key, val)) continue;
|
|
6771
7884
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
6772
7885
|
if (el.dataset.ohwEditable === "image") {
|
|
6773
7886
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
6774
|
-
if (img && img.src !== val) img
|
|
7887
|
+
if (img && img.src !== val) applyEditableImageSrc(img, val);
|
|
6775
7888
|
} else if (el.dataset.ohwEditable === "bg-image") {
|
|
6776
7889
|
const next = `url('${val}')`;
|
|
6777
7890
|
if (el.style.backgroundImage !== next) el.style.backgroundImage = next;
|
|
7891
|
+
} else if (el.dataset.ohwEditable === "video") {
|
|
7892
|
+
const video = getVideoEl(el);
|
|
7893
|
+
if (video && video.src !== val) applyVideoSrc(video, val);
|
|
6778
7894
|
} else if (el.dataset.ohwEditable === "link") {
|
|
6779
7895
|
applyLinkHref(el, val);
|
|
6780
7896
|
} else if (el.innerHTML !== val) {
|
|
@@ -6783,6 +7899,7 @@ function OhhwellsBridge() {
|
|
|
6783
7899
|
});
|
|
6784
7900
|
applyLinkByKey(key, val);
|
|
6785
7901
|
}
|
|
7902
|
+
reconcileNavbarItemsFromContent(content);
|
|
6786
7903
|
} finally {
|
|
6787
7904
|
observer?.observe(document.body, { childList: true, subtree: true });
|
|
6788
7905
|
}
|
|
@@ -6806,20 +7923,38 @@ function OhhwellsBridge() {
|
|
|
6806
7923
|
const visible = Boolean(subdomain) && fetchState !== "done";
|
|
6807
7924
|
el.style.display = visible ? "flex" : "none";
|
|
6808
7925
|
}, [subdomain, fetchState]);
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
}, [pathname,
|
|
6812
|
-
|
|
7926
|
+
useEffect7(() => {
|
|
7927
|
+
postToParent2({ type: "ow:navigation", path: pathname });
|
|
7928
|
+
}, [pathname, postToParent2]);
|
|
7929
|
+
useEffect7(() => {
|
|
6813
7930
|
if (!isEditMode) return;
|
|
7931
|
+
if (linkPopoverSessionRef.current?.intent === "add-nav") return;
|
|
7932
|
+
if (document.querySelector("[data-ohw-section-picker]")) return;
|
|
6814
7933
|
setLinkPopover(null);
|
|
6815
7934
|
deselectRef.current();
|
|
6816
7935
|
deactivateRef.current();
|
|
6817
7936
|
}, [pathname, isEditMode]);
|
|
6818
|
-
|
|
7937
|
+
useEffect7(() => {
|
|
7938
|
+
const contentForNav = () => {
|
|
7939
|
+
if (isEditMode) return editContentRef.current;
|
|
7940
|
+
if (!subdomain) return {};
|
|
7941
|
+
return contentCache.get(subdomain) ?? {};
|
|
7942
|
+
};
|
|
7943
|
+
const run = () => reconcileNavbarItemsFromContent(contentForNav());
|
|
7944
|
+
run();
|
|
7945
|
+
const nav = document.querySelector("nav");
|
|
7946
|
+
if (!nav) return;
|
|
7947
|
+
const observer = new MutationObserver(() => {
|
|
7948
|
+
requestAnimationFrame(run);
|
|
7949
|
+
});
|
|
7950
|
+
observer.observe(nav, { childList: true, subtree: true });
|
|
7951
|
+
return () => observer.disconnect();
|
|
7952
|
+
}, [isEditMode, pathname, subdomain, fetchState]);
|
|
7953
|
+
useEffect7(() => {
|
|
6819
7954
|
if (!isEditMode) return;
|
|
6820
7955
|
const measure = () => {
|
|
6821
7956
|
const h = document.body.scrollHeight;
|
|
6822
|
-
if (h > 50)
|
|
7957
|
+
if (h > 50) postToParent2({ type: "ow:height", height: h });
|
|
6823
7958
|
};
|
|
6824
7959
|
const t1 = setTimeout(measure, 50);
|
|
6825
7960
|
const t2 = setTimeout(measure, 500);
|
|
@@ -6838,8 +7973,8 @@ function OhhwellsBridge() {
|
|
|
6838
7973
|
if (resizeTimer) clearTimeout(resizeTimer);
|
|
6839
7974
|
window.removeEventListener("resize", handleResize);
|
|
6840
7975
|
};
|
|
6841
|
-
}, [pathname, isEditMode,
|
|
6842
|
-
|
|
7976
|
+
}, [pathname, isEditMode, postToParent2]);
|
|
7977
|
+
useEffect7(() => {
|
|
6843
7978
|
if (!subdomainFromQuery || isEditMode) return;
|
|
6844
7979
|
const handleClick = (e) => {
|
|
6845
7980
|
const anchor = e.target.closest("a");
|
|
@@ -6855,7 +7990,7 @@ function OhhwellsBridge() {
|
|
|
6855
7990
|
document.addEventListener("click", handleClick, true);
|
|
6856
7991
|
return () => document.removeEventListener("click", handleClick, true);
|
|
6857
7992
|
}, [subdomainFromQuery, isEditMode, router]);
|
|
6858
|
-
|
|
7993
|
+
useEffect7(() => {
|
|
6859
7994
|
if (!isEditMode) {
|
|
6860
7995
|
editStylesRef.current?.base.remove();
|
|
6861
7996
|
editStylesRef.current?.forceHover.remove();
|
|
@@ -6878,8 +8013,9 @@ function OhhwellsBridge() {
|
|
|
6878
8013
|
[data-ohw-editable] {
|
|
6879
8014
|
display: block;
|
|
6880
8015
|
}
|
|
6881
|
-
[data-ohw-editable]:not([contenteditable]):not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]) { cursor: text !important; }
|
|
8016
|
+
[data-ohw-editable]:not([contenteditable]):not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]):not([data-ohw-editable="video"]) { cursor: text !important; }
|
|
6882
8017
|
[data-ohw-editable="image"], [data-ohw-editable="image"] *,
|
|
8018
|
+
[data-ohw-editable="video"], [data-ohw-editable="video"] *,
|
|
6883
8019
|
[data-ohw-editable="bg-image"], [data-ohw-editable="bg-image"] * { cursor: pointer !important; }
|
|
6884
8020
|
[data-ohw-editable="link"], [data-ohw-editable="link"] * { cursor: pointer !important; }
|
|
6885
8021
|
[data-ohw-hovered]:not([contenteditable]):not([data-ohw-href-key]) {
|
|
@@ -6928,6 +8064,13 @@ function OhhwellsBridge() {
|
|
|
6928
8064
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
6929
8065
|
if (isInsideLinkEditor(target)) return;
|
|
6930
8066
|
if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
8067
|
+
const navFromChrome = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
|
|
8068
|
+
if (navFromChrome) {
|
|
8069
|
+
e.preventDefault();
|
|
8070
|
+
e.stopPropagation();
|
|
8071
|
+
selectFrameRef.current(navFromChrome);
|
|
8072
|
+
return;
|
|
8073
|
+
}
|
|
6931
8074
|
e.preventDefault();
|
|
6932
8075
|
e.stopPropagation();
|
|
6933
8076
|
return;
|
|
@@ -6942,14 +8085,15 @@ function OhhwellsBridge() {
|
|
|
6942
8085
|
bumpLinkPopoverGrace();
|
|
6943
8086
|
setLinkPopoverRef.current({
|
|
6944
8087
|
key: editable.dataset.ohwKey ?? "",
|
|
6945
|
-
|
|
8088
|
+
mode: "edit",
|
|
8089
|
+
target: getLinkHref2(editable)
|
|
6946
8090
|
});
|
|
6947
8091
|
return;
|
|
6948
8092
|
}
|
|
6949
|
-
if (editable
|
|
8093
|
+
if (isMediaEditable(editable)) {
|
|
6950
8094
|
e.preventDefault();
|
|
6951
8095
|
e.stopPropagation();
|
|
6952
|
-
postToParentRef.current({ type: "ow:image-pick", key: editable.dataset.ohwKey ?? "" });
|
|
8096
|
+
postToParentRef.current({ type: "ow:image-pick", key: editable.dataset.ohwKey ?? "", elementType: editable.dataset.ohwEditable ?? "image" });
|
|
6953
8097
|
return;
|
|
6954
8098
|
}
|
|
6955
8099
|
const hrefCtx = getHrefKeyFromElement(editable);
|
|
@@ -6958,7 +8102,8 @@ function OhhwellsBridge() {
|
|
|
6958
8102
|
e.preventDefault();
|
|
6959
8103
|
e.stopPropagation();
|
|
6960
8104
|
if (selectedElRef.current === navAnchor) {
|
|
6961
|
-
|
|
8105
|
+
if (e.detail >= 2) return;
|
|
8106
|
+
activateRef.current(editable, { caretX: e.clientX, caretY: e.clientY });
|
|
6962
8107
|
return;
|
|
6963
8108
|
}
|
|
6964
8109
|
selectRef.current(navAnchor);
|
|
@@ -6977,6 +8122,22 @@ function OhhwellsBridge() {
|
|
|
6977
8122
|
selectRef.current(hrefAnchor);
|
|
6978
8123
|
return;
|
|
6979
8124
|
}
|
|
8125
|
+
const navContainerToSelect = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
|
|
8126
|
+
if (navContainerToSelect) {
|
|
8127
|
+
e.preventDefault();
|
|
8128
|
+
e.stopPropagation();
|
|
8129
|
+
selectFrameRef.current(navContainerToSelect);
|
|
8130
|
+
return;
|
|
8131
|
+
}
|
|
8132
|
+
const selectedContainer = selectedElRef.current;
|
|
8133
|
+
if (selectedContainer && isNavigationContainer(selectedContainer)) {
|
|
8134
|
+
const navItem = getNavigationItemAnchor(target);
|
|
8135
|
+
if (!navItem && (selectedContainer === target || selectedContainer.contains(target))) {
|
|
8136
|
+
e.preventDefault();
|
|
8137
|
+
e.stopPropagation();
|
|
8138
|
+
return;
|
|
8139
|
+
}
|
|
8140
|
+
}
|
|
6980
8141
|
if (activeElRef.current) {
|
|
6981
8142
|
const sel = window.getSelection();
|
|
6982
8143
|
if (sel && !sel.isCollapsed) {
|
|
@@ -7002,10 +8163,48 @@ function OhhwellsBridge() {
|
|
|
7002
8163
|
deselectRef.current();
|
|
7003
8164
|
deactivateRef.current();
|
|
7004
8165
|
};
|
|
8166
|
+
const handleDblClick = (e) => {
|
|
8167
|
+
const target = e.target;
|
|
8168
|
+
if (target.closest("[data-ohw-toolbar]")) return;
|
|
8169
|
+
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
8170
|
+
if (target.closest("[data-ohw-max-badge]")) return;
|
|
8171
|
+
if (isInsideLinkEditor(target)) return;
|
|
8172
|
+
if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
8173
|
+
return;
|
|
8174
|
+
}
|
|
8175
|
+
const navLabel = getNavigationLabelEditable(target);
|
|
8176
|
+
if (!navLabel) return;
|
|
8177
|
+
const { editable } = navLabel;
|
|
8178
|
+
e.preventDefault();
|
|
8179
|
+
e.stopPropagation();
|
|
8180
|
+
if (activeElRef.current !== editable) {
|
|
8181
|
+
activateRef.current(editable);
|
|
8182
|
+
}
|
|
8183
|
+
requestAnimationFrame(() => {
|
|
8184
|
+
selectAllTextInEditable(editable);
|
|
8185
|
+
refreshActiveCommandsRef.current();
|
|
8186
|
+
});
|
|
8187
|
+
};
|
|
7005
8188
|
const handleMouseOver = (e) => {
|
|
7006
8189
|
const target = e.target;
|
|
8190
|
+
if (toolbarVariantRef.current !== "select-frame") {
|
|
8191
|
+
const navContainer = target.closest("[data-ohw-nav-container]");
|
|
8192
|
+
if (navContainer && !getNavigationItemAnchor(target)) {
|
|
8193
|
+
hoveredNavContainerRef.current = navContainer;
|
|
8194
|
+
setHoveredNavContainerRect(navContainer.getBoundingClientRect());
|
|
8195
|
+
hoveredItemElRef.current = null;
|
|
8196
|
+
setHoveredItemRect(null);
|
|
8197
|
+
return;
|
|
8198
|
+
}
|
|
8199
|
+
if (!target.closest("[data-ohw-nav-container]")) {
|
|
8200
|
+
hoveredNavContainerRef.current = null;
|
|
8201
|
+
setHoveredNavContainerRect(null);
|
|
8202
|
+
}
|
|
8203
|
+
}
|
|
7007
8204
|
const navAnchor = getNavigationItemAnchor(target);
|
|
7008
8205
|
if (navAnchor) {
|
|
8206
|
+
hoveredNavContainerRef.current = null;
|
|
8207
|
+
setHoveredNavContainerRect(null);
|
|
7009
8208
|
const selected2 = selectedElRef.current;
|
|
7010
8209
|
if (selected2 === navAnchor || selected2?.contains(navAnchor)) return;
|
|
7011
8210
|
clearHrefKeyHover(navAnchor);
|
|
@@ -7017,7 +8216,7 @@ function OhhwellsBridge() {
|
|
|
7017
8216
|
if (!editable) return;
|
|
7018
8217
|
const selected = selectedElRef.current;
|
|
7019
8218
|
if (selected && (selected === editable || selected.contains(editable))) return;
|
|
7020
|
-
if (editable
|
|
8219
|
+
if (!isMediaEditable(editable) && !editable.hasAttribute("contenteditable")) {
|
|
7021
8220
|
const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
|
|
7022
8221
|
if (hoverTarget.hasAttribute("data-ohw-href-key")) {
|
|
7023
8222
|
clearHrefKeyHover(hoverTarget);
|
|
@@ -7030,6 +8229,14 @@ function OhhwellsBridge() {
|
|
|
7030
8229
|
};
|
|
7031
8230
|
const handleMouseOut = (e) => {
|
|
7032
8231
|
const target = e.target;
|
|
8232
|
+
if (target.closest("[data-ohw-nav-container]")) {
|
|
8233
|
+
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
8234
|
+
if (related2?.closest("[data-ohw-nav-container], [data-ohw-navbar-container-chrome], [data-ohw-navbar-add-button]")) {
|
|
8235
|
+
return;
|
|
8236
|
+
}
|
|
8237
|
+
hoveredNavContainerRef.current = null;
|
|
8238
|
+
setHoveredNavContainerRect(null);
|
|
8239
|
+
}
|
|
7033
8240
|
const navAnchor = getNavigationItemAnchor(target);
|
|
7034
8241
|
if (navAnchor) {
|
|
7035
8242
|
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
@@ -7045,7 +8252,7 @@ function OhhwellsBridge() {
|
|
|
7045
8252
|
if (!editable) return;
|
|
7046
8253
|
const related = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
7047
8254
|
if (related?.closest("[data-ohw-drag-handle-container], [data-ohw-item-interaction]")) return;
|
|
7048
|
-
if (editable
|
|
8255
|
+
if (!isMediaEditable(editable)) {
|
|
7049
8256
|
const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
|
|
7050
8257
|
if (hoverTarget.hasAttribute("data-ohw-href-key")) {
|
|
7051
8258
|
if (!related?.closest("[data-ohw-href-key]")) {
|
|
@@ -7091,23 +8298,26 @@ function OhhwellsBridge() {
|
|
|
7091
8298
|
}
|
|
7092
8299
|
return { top, left, width: Math.max(0, right - left), height: Math.max(0, bottom - top) };
|
|
7093
8300
|
};
|
|
7094
|
-
const
|
|
8301
|
+
const showImageHover = (imgEl, isDragOver = false, forceTextOverlap) => {
|
|
7095
8302
|
const r2 = getVisibleRect(imgEl);
|
|
7096
8303
|
const hasTextOverlap = forceTextOverlap ?? false;
|
|
7097
8304
|
hoveredImageHasTextOverlapRef.current = hasTextOverlap;
|
|
7098
|
-
|
|
7099
|
-
|
|
8305
|
+
const video = imgEl.dataset.ohwEditable === "video" ? getVideoEl(imgEl) : null;
|
|
8306
|
+
setMediaHover({
|
|
7100
8307
|
key: imgEl.dataset.ohwKey ?? "",
|
|
7101
8308
|
rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height },
|
|
8309
|
+
elementType: imgEl.dataset.ohwEditable ?? "image",
|
|
7102
8310
|
hasTextOverlap,
|
|
7103
|
-
|
|
8311
|
+
isDragOver,
|
|
8312
|
+
...video ? { videoAutoplay: video.autoplay, videoMuted: video.muted } : {}
|
|
7104
8313
|
});
|
|
7105
8314
|
const track = imgEl.closest("[data-ohw-hover-pause]");
|
|
7106
8315
|
if (track) track.setAttribute("data-ohw-hover-paused", "");
|
|
7107
8316
|
};
|
|
8317
|
+
const clearImageHover = () => setMediaHover(null);
|
|
7108
8318
|
const findImageAtPoint = (clientX, clientY, fromParentViewport) => {
|
|
7109
8319
|
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
7110
|
-
const images = Array.from(document.querySelectorAll(
|
|
8320
|
+
const images = Array.from(document.querySelectorAll(MEDIA_SELECTOR));
|
|
7111
8321
|
const matches = [];
|
|
7112
8322
|
for (let i = images.length - 1; i >= 0; i--) {
|
|
7113
8323
|
const el = images[i];
|
|
@@ -7123,7 +8333,9 @@ function OhhwellsBridge() {
|
|
|
7123
8333
|
if (x >= r2.left && x <= r2.left + r2.width && y >= r2.top && y <= r2.top + r2.height) matches.push(el);
|
|
7124
8334
|
}
|
|
7125
8335
|
if (matches.length === 0) return null;
|
|
7126
|
-
const imageTypeMatches = matches.filter(
|
|
8336
|
+
const imageTypeMatches = matches.filter(
|
|
8337
|
+
(el) => el.dataset.ohwEditable === "image" || el.dataset.ohwEditable === "video"
|
|
8338
|
+
);
|
|
7127
8339
|
const candidatePool = imageTypeMatches.length > 0 ? imageTypeMatches : matches;
|
|
7128
8340
|
const smallest = candidatePool.reduce((best, el) => {
|
|
7129
8341
|
const br = getVisibleRect(best);
|
|
@@ -7146,47 +8358,91 @@ function OhhwellsBridge() {
|
|
|
7146
8358
|
}
|
|
7147
8359
|
return smallest;
|
|
7148
8360
|
};
|
|
8361
|
+
const dismissImageHover = () => {
|
|
8362
|
+
if (hoveredImageRef.current) {
|
|
8363
|
+
hoveredImageRef.current = null;
|
|
8364
|
+
hoveredImageHasTextOverlapRef.current = false;
|
|
8365
|
+
resumeAnimTracks();
|
|
8366
|
+
postToParentRef.current({ type: "ow:image-unhover" });
|
|
8367
|
+
}
|
|
8368
|
+
clearImageHover();
|
|
8369
|
+
};
|
|
8370
|
+
const probeNavigationHoverAt = (x, y) => {
|
|
8371
|
+
if (toolbarVariantRef.current === "select-frame") {
|
|
8372
|
+
hoveredNavContainerRef.current = null;
|
|
8373
|
+
setHoveredNavContainerRect(null);
|
|
8374
|
+
return;
|
|
8375
|
+
}
|
|
8376
|
+
const navContainer = document.querySelector("[data-ohw-nav-container]");
|
|
8377
|
+
if (!navContainer) {
|
|
8378
|
+
hoveredNavContainerRef.current = null;
|
|
8379
|
+
setHoveredNavContainerRect(null);
|
|
8380
|
+
return;
|
|
8381
|
+
}
|
|
8382
|
+
const containerRect = navContainer.getBoundingClientRect();
|
|
8383
|
+
const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
|
|
8384
|
+
if (!overContainer) {
|
|
8385
|
+
hoveredNavContainerRef.current = null;
|
|
8386
|
+
setHoveredNavContainerRect(null);
|
|
8387
|
+
return;
|
|
8388
|
+
}
|
|
8389
|
+
const navItemHit = Array.from(
|
|
8390
|
+
navContainer.querySelectorAll("[data-ohw-href-key]")
|
|
8391
|
+
).find((el) => {
|
|
8392
|
+
if (!isNavigationItem(el) || isNavbarButton2(el)) return false;
|
|
8393
|
+
const itemRect = el.getBoundingClientRect();
|
|
8394
|
+
return x >= itemRect.left && x <= itemRect.right && y >= itemRect.top && y <= itemRect.bottom;
|
|
8395
|
+
});
|
|
8396
|
+
if (navItemHit) {
|
|
8397
|
+
hoveredNavContainerRef.current = null;
|
|
8398
|
+
setHoveredNavContainerRect(null);
|
|
8399
|
+
const selected = selectedElRef.current;
|
|
8400
|
+
if (selected !== navItemHit && !selected?.contains(navItemHit)) {
|
|
8401
|
+
clearHrefKeyHover(navItemHit);
|
|
8402
|
+
hoveredItemElRef.current = navItemHit;
|
|
8403
|
+
setHoveredItemRect(navItemHit.getBoundingClientRect());
|
|
8404
|
+
}
|
|
8405
|
+
return;
|
|
8406
|
+
}
|
|
8407
|
+
hoveredNavContainerRef.current = navContainer;
|
|
8408
|
+
setHoveredNavContainerRect(containerRect);
|
|
8409
|
+
hoveredItemElRef.current = null;
|
|
8410
|
+
setHoveredItemRect(null);
|
|
8411
|
+
};
|
|
7149
8412
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
7150
8413
|
if (linkPopoverOpenRef.current) {
|
|
7151
|
-
|
|
7152
|
-
|
|
7153
|
-
|
|
7154
|
-
|
|
7155
|
-
|
|
7156
|
-
|
|
8414
|
+
dismissImageHover();
|
|
8415
|
+
return;
|
|
8416
|
+
}
|
|
8417
|
+
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
8418
|
+
if (isPointOverNavigation(x, y)) {
|
|
8419
|
+
dismissImageHover();
|
|
8420
|
+
probeNavigationHoverAt(x, y);
|
|
7157
8421
|
return;
|
|
7158
8422
|
}
|
|
8423
|
+
hoveredNavContainerRef.current = null;
|
|
8424
|
+
setHoveredNavContainerRect(null);
|
|
7159
8425
|
const toggleEl = document.querySelector("[data-ohw-state-toggle]");
|
|
7160
8426
|
if (toggleEl) {
|
|
7161
|
-
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
7162
8427
|
const tr = toggleEl.getBoundingClientRect();
|
|
7163
8428
|
if (x >= tr.left && x <= tr.right && y >= tr.top && y <= tr.bottom) {
|
|
7164
|
-
|
|
7165
|
-
hoveredImageRef.current = null;
|
|
7166
|
-
resumeAnimTracks();
|
|
7167
|
-
postToParentRef.current({ type: "ow:image-unhover" });
|
|
7168
|
-
}
|
|
8429
|
+
dismissImageHover();
|
|
7169
8430
|
return;
|
|
7170
8431
|
}
|
|
7171
8432
|
}
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
|
-
|
|
7175
|
-
|
|
7176
|
-
resumeAnimTracks();
|
|
7177
|
-
postToParentRef.current({ type: "ow:image-unhover" });
|
|
7178
|
-
}
|
|
8433
|
+
const imgEl = findImageAtPoint(clientX, clientY, fromParentViewport);
|
|
8434
|
+
const activeEl = activeElRef.current;
|
|
8435
|
+
if (activeEl && (!imgEl || imgEl.contains(activeEl))) {
|
|
8436
|
+
dismissImageHover();
|
|
7179
8437
|
return;
|
|
7180
8438
|
}
|
|
7181
|
-
const imgEl = findImageAtPoint(clientX, clientY, fromParentViewport);
|
|
7182
8439
|
if (imgEl) {
|
|
7183
|
-
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
7184
8440
|
const topEl = document.elementFromPoint(x, y);
|
|
7185
8441
|
if (topEl?.closest('[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
7186
8442
|
if (hoveredImageRef.current) {
|
|
7187
8443
|
hoveredImageRef.current = null;
|
|
7188
8444
|
resumeAnimTracks();
|
|
7189
|
-
|
|
8445
|
+
clearImageHover();
|
|
7190
8446
|
}
|
|
7191
8447
|
return;
|
|
7192
8448
|
}
|
|
@@ -7195,13 +8451,13 @@ function OhhwellsBridge() {
|
|
|
7195
8451
|
hoveredImageRef.current = null;
|
|
7196
8452
|
hoveredImageHasTextOverlapRef.current = false;
|
|
7197
8453
|
resumeAnimTracks();
|
|
7198
|
-
|
|
8454
|
+
clearImageHover();
|
|
7199
8455
|
}
|
|
7200
8456
|
return;
|
|
7201
8457
|
}
|
|
7202
8458
|
const isStateCardImage = !!imgEl.closest("[data-ohw-editable-state]");
|
|
7203
8459
|
const textEditable = Array.from(
|
|
7204
|
-
document.querySelectorAll(
|
|
8460
|
+
document.querySelectorAll(NON_MEDIA_SELECTOR)
|
|
7205
8461
|
).find((el) => {
|
|
7206
8462
|
const er = el.getBoundingClientRect();
|
|
7207
8463
|
return x >= er.left && x <= er.right && y >= er.top && y <= er.bottom;
|
|
@@ -7220,14 +8476,14 @@ function OhhwellsBridge() {
|
|
|
7220
8476
|
hoveredImageRef.current = null;
|
|
7221
8477
|
hoveredImageHasTextOverlapRef.current = false;
|
|
7222
8478
|
resumeAnimTracks();
|
|
7223
|
-
|
|
8479
|
+
clearImageHover();
|
|
7224
8480
|
}
|
|
7225
8481
|
return;
|
|
7226
8482
|
}
|
|
7227
8483
|
if (isStateCardImage) {
|
|
7228
8484
|
if (imgEl !== hoveredImageRef.current || !hoveredImageHasTextOverlapRef.current) {
|
|
7229
8485
|
hoveredImageRef.current = imgEl;
|
|
7230
|
-
|
|
8486
|
+
showImageHover(imgEl, isDragOver, true);
|
|
7231
8487
|
}
|
|
7232
8488
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
7233
8489
|
if (textEditable && !isInsideNavigationItem(textEditable)) {
|
|
@@ -7239,7 +8495,7 @@ function OhhwellsBridge() {
|
|
|
7239
8495
|
hoveredImageRef.current = null;
|
|
7240
8496
|
hoveredImageHasTextOverlapRef.current = false;
|
|
7241
8497
|
resumeAnimTracks();
|
|
7242
|
-
|
|
8498
|
+
clearImageHover();
|
|
7243
8499
|
}
|
|
7244
8500
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
7245
8501
|
if (textEditable && !isInsideNavigationItem(textEditable)) {
|
|
@@ -7251,7 +8507,7 @@ function OhhwellsBridge() {
|
|
|
7251
8507
|
if (hoveredImageRef.current) {
|
|
7252
8508
|
hoveredImageRef.current = null;
|
|
7253
8509
|
resumeAnimTracks();
|
|
7254
|
-
|
|
8510
|
+
clearImageHover();
|
|
7255
8511
|
}
|
|
7256
8512
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
7257
8513
|
return;
|
|
@@ -7259,9 +8515,9 @@ function OhhwellsBridge() {
|
|
|
7259
8515
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
7260
8516
|
if (imgEl !== hoveredImageRef.current || hoveredImageHasTextOverlapRef.current) {
|
|
7261
8517
|
hoveredImageRef.current = imgEl;
|
|
7262
|
-
|
|
8518
|
+
showImageHover(imgEl, isDragOver);
|
|
7263
8519
|
} else if (isDragOver) {
|
|
7264
|
-
|
|
8520
|
+
showImageHover(imgEl, true);
|
|
7265
8521
|
}
|
|
7266
8522
|
} else {
|
|
7267
8523
|
const inIframeView = clientX >= 0 && clientY >= 0 && clientX <= window.innerWidth && clientY <= window.innerHeight;
|
|
@@ -7278,14 +8534,14 @@ function OhhwellsBridge() {
|
|
|
7278
8534
|
hoveredImageRef.current = null;
|
|
7279
8535
|
hoveredImageHasTextOverlapRef.current = false;
|
|
7280
8536
|
resumeAnimTracks();
|
|
7281
|
-
|
|
8537
|
+
clearImageHover();
|
|
7282
8538
|
}
|
|
7283
|
-
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
8539
|
+
const { x: x2, y: y2 } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
7284
8540
|
const textEl = Array.from(
|
|
7285
|
-
document.querySelectorAll(
|
|
8541
|
+
document.querySelectorAll(NON_MEDIA_SELECTOR)
|
|
7286
8542
|
).find((el) => {
|
|
7287
8543
|
const er = el.getBoundingClientRect();
|
|
7288
|
-
return
|
|
8544
|
+
return x2 >= er.left && x2 <= er.right && y2 >= er.top && y2 <= er.bottom;
|
|
7289
8545
|
});
|
|
7290
8546
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
7291
8547
|
if (textEl && !textEl.hasAttribute("contenteditable")) {
|
|
@@ -7388,18 +8644,20 @@ function OhhwellsBridge() {
|
|
|
7388
8644
|
return;
|
|
7389
8645
|
}
|
|
7390
8646
|
e.dataTransfer.dropEffect = "copy";
|
|
7391
|
-
if (
|
|
8647
|
+
if (dragOverElRef.current !== el) {
|
|
8648
|
+
dragOverElRef.current = el;
|
|
7392
8649
|
hoveredImageRef.current = el;
|
|
7393
8650
|
const isStateCard = !!el.closest("[data-ohw-editable-state]");
|
|
7394
|
-
|
|
8651
|
+
showImageHover(el, true, isStateCard ? true : void 0);
|
|
7395
8652
|
}
|
|
7396
8653
|
};
|
|
7397
8654
|
const handleDragLeave = (e) => {
|
|
7398
8655
|
const imgEl = findImageAtPoint(e.clientX, e.clientY, false);
|
|
7399
8656
|
if (imgEl) return;
|
|
8657
|
+
dragOverElRef.current = null;
|
|
7400
8658
|
hoveredImageRef.current = null;
|
|
7401
8659
|
resumeAnimTracks();
|
|
7402
|
-
|
|
8660
|
+
clearImageHover();
|
|
7403
8661
|
};
|
|
7404
8662
|
const handleDrop = (e) => {
|
|
7405
8663
|
e.preventDefault();
|
|
@@ -7407,7 +8665,9 @@ function OhhwellsBridge() {
|
|
|
7407
8665
|
if (!el) return;
|
|
7408
8666
|
const file = e.dataTransfer?.files?.[0];
|
|
7409
8667
|
if (file) {
|
|
7410
|
-
|
|
8668
|
+
const wantsVideo = el.dataset.ohwEditable === "video";
|
|
8669
|
+
const accepted = wantsVideo ? file.type.startsWith("video/") : file.type.startsWith("image/");
|
|
8670
|
+
if (accepted) {
|
|
7411
8671
|
const key = el.dataset.ohwKey ?? "";
|
|
7412
8672
|
const { name, type: mimeType } = file;
|
|
7413
8673
|
const r2 = el.getBoundingClientRect();
|
|
@@ -7416,12 +8676,13 @@ function OhhwellsBridge() {
|
|
|
7416
8676
|
window.parent.postMessage({ type: "ow:image-drop", key, name, mimeType, buf, rect }, "*", [buf]);
|
|
7417
8677
|
});
|
|
7418
8678
|
} else {
|
|
7419
|
-
postToParentRef.current({ type: "ow:image-drop-invalid" });
|
|
8679
|
+
postToParentRef.current({ type: "ow:image-drop-invalid", expected: wantsVideo ? "video" : "image" });
|
|
7420
8680
|
}
|
|
7421
8681
|
}
|
|
8682
|
+
dragOverElRef.current = null;
|
|
7422
8683
|
hoveredImageRef.current = null;
|
|
7423
8684
|
resumeAnimTracks();
|
|
7424
|
-
|
|
8685
|
+
clearImageHover();
|
|
7425
8686
|
};
|
|
7426
8687
|
const handleImageUrl = (e) => {
|
|
7427
8688
|
if (e.data?.type !== "ow:image-url") return;
|
|
@@ -7439,7 +8700,11 @@ function OhhwellsBridge() {
|
|
|
7439
8700
|
}
|
|
7440
8701
|
});
|
|
7441
8702
|
hoveredImageRef.current = null;
|
|
7442
|
-
|
|
8703
|
+
setUploadingRects((prev) => {
|
|
8704
|
+
const entry = prev[key];
|
|
8705
|
+
if (!entry || entry.fadingOut) return prev;
|
|
8706
|
+
return { ...prev, [key]: { ...entry, fadingOut: true } };
|
|
8707
|
+
});
|
|
7443
8708
|
};
|
|
7444
8709
|
let found = false;
|
|
7445
8710
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -7469,11 +8734,24 @@ function OhhwellsBridge() {
|
|
|
7469
8734
|
};
|
|
7470
8735
|
img.onload = onReady;
|
|
7471
8736
|
img.onerror = onReady;
|
|
7472
|
-
img
|
|
8737
|
+
applyEditableImageSrc(img, url);
|
|
7473
8738
|
if (img.complete && img.naturalWidth > 0) {
|
|
7474
8739
|
requestAnimationFrame(() => onReady());
|
|
7475
8740
|
}
|
|
7476
8741
|
}
|
|
8742
|
+
} else if (el.dataset.ohwEditable === "video") {
|
|
8743
|
+
const video = getVideoEl(el);
|
|
8744
|
+
if (video) {
|
|
8745
|
+
found = true;
|
|
8746
|
+
const onReady = () => {
|
|
8747
|
+
video.onloadeddata = null;
|
|
8748
|
+
video.onerror = null;
|
|
8749
|
+
notify();
|
|
8750
|
+
};
|
|
8751
|
+
video.onloadeddata = onReady;
|
|
8752
|
+
video.onerror = onReady;
|
|
8753
|
+
applyVideoSrc(video, url);
|
|
8754
|
+
}
|
|
7477
8755
|
}
|
|
7478
8756
|
});
|
|
7479
8757
|
if (!found) notify();
|
|
@@ -7540,12 +8818,16 @@ function OhhwellsBridge() {
|
|
|
7540
8818
|
sectionsJson = val;
|
|
7541
8819
|
continue;
|
|
7542
8820
|
}
|
|
8821
|
+
if (applyVideoSettingNode(key, val)) continue;
|
|
7543
8822
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
7544
8823
|
if (el.dataset.ohwEditable === "image") {
|
|
7545
8824
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
7546
|
-
if (img) img
|
|
8825
|
+
if (img) applyEditableImageSrc(img, val);
|
|
7547
8826
|
} else if (el.dataset.ohwEditable === "bg-image") {
|
|
7548
8827
|
el.style.backgroundImage = `url('${val}')`;
|
|
8828
|
+
} else if (el.dataset.ohwEditable === "video") {
|
|
8829
|
+
const video = getVideoEl(el);
|
|
8830
|
+
if (video && video.src !== val) applyVideoSrc(video, val);
|
|
7549
8831
|
} else if (el.dataset.ohwEditable === "link") {
|
|
7550
8832
|
applyLinkHref(el, val);
|
|
7551
8833
|
} else {
|
|
@@ -7559,6 +8841,8 @@ function OhhwellsBridge() {
|
|
|
7559
8841
|
sectionsLoadedRef.current = true;
|
|
7560
8842
|
pendingScheduleConfigRequests.current.splice(0).forEach(processConfigRequest);
|
|
7561
8843
|
}
|
|
8844
|
+
editContentRef.current = { ...editContentRef.current, ...content };
|
|
8845
|
+
reconcileNavbarItemsFromContent(editContentRef.current);
|
|
7562
8846
|
enforceLinkHrefs();
|
|
7563
8847
|
postToParentRef.current({ type: "ow:hydrate-done" });
|
|
7564
8848
|
};
|
|
@@ -7566,6 +8850,7 @@ function OhhwellsBridge() {
|
|
|
7566
8850
|
const handleDeactivate = (e) => {
|
|
7567
8851
|
if (e.data?.type !== "ow:deactivate") return;
|
|
7568
8852
|
if (Date.now() < linkPopoverGraceUntilRef.current) return;
|
|
8853
|
+
if (document.querySelector("[data-ohw-section-picker]")) return;
|
|
7569
8854
|
if (linkPopoverOpenRef.current) {
|
|
7570
8855
|
setLinkPopoverRef.current(null);
|
|
7571
8856
|
return;
|
|
@@ -7575,12 +8860,32 @@ function OhhwellsBridge() {
|
|
|
7575
8860
|
};
|
|
7576
8861
|
window.addEventListener("message", handleDeactivate);
|
|
7577
8862
|
const handleKeyDown = (e) => {
|
|
8863
|
+
if (e.key === "Escape" && document.querySelector("[data-ohw-section-picker]")) return;
|
|
8864
|
+
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "a" && activeElRef.current) {
|
|
8865
|
+
const navAnchor = getNavigationItemAnchor(activeElRef.current);
|
|
8866
|
+
if (navAnchor) {
|
|
8867
|
+
e.preventDefault();
|
|
8868
|
+
selectAllTextInEditable(activeElRef.current);
|
|
8869
|
+
refreshActiveCommandsRef.current();
|
|
8870
|
+
return;
|
|
8871
|
+
}
|
|
8872
|
+
}
|
|
7578
8873
|
if (e.key === "Escape" && linkPopoverOpenRef.current) {
|
|
7579
8874
|
setLinkPopoverRef.current(null);
|
|
7580
8875
|
return;
|
|
7581
8876
|
}
|
|
7582
8877
|
if (e.key === "Escape" && selectedElRef.current && !activeElRef.current) {
|
|
7583
|
-
|
|
8878
|
+
if (toolbarVariantRef.current === "select-frame") {
|
|
8879
|
+
deselectRef.current();
|
|
8880
|
+
return;
|
|
8881
|
+
}
|
|
8882
|
+
const parent = getNavigationSelectionParent(selectedElRef.current);
|
|
8883
|
+
if (parent) {
|
|
8884
|
+
e.preventDefault();
|
|
8885
|
+
selectFrameRef.current(parent);
|
|
8886
|
+
} else {
|
|
8887
|
+
deselectRef.current();
|
|
8888
|
+
}
|
|
7584
8889
|
return;
|
|
7585
8890
|
}
|
|
7586
8891
|
if (e.key === "Escape" && activeElRef.current) {
|
|
@@ -7638,18 +8943,18 @@ function OhhwellsBridge() {
|
|
|
7638
8943
|
if (hoveredItemElRef.current) {
|
|
7639
8944
|
setHoveredItemRect(hoveredItemElRef.current.getBoundingClientRect());
|
|
7640
8945
|
}
|
|
8946
|
+
if (hoveredNavContainerRef.current) {
|
|
8947
|
+
setHoveredNavContainerRect(hoveredNavContainerRef.current.getBoundingClientRect());
|
|
8948
|
+
}
|
|
7641
8949
|
if (siblingHintElRef.current) {
|
|
7642
8950
|
setSiblingHintRect(siblingHintElRef.current.getBoundingClientRect());
|
|
7643
8951
|
}
|
|
7644
8952
|
if (hoveredImageRef.current) {
|
|
7645
8953
|
const el = hoveredImageRef.current;
|
|
7646
8954
|
const r2 = el.getBoundingClientRect();
|
|
7647
|
-
|
|
7648
|
-
|
|
7649
|
-
|
|
7650
|
-
rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height },
|
|
7651
|
-
hasTextOverlap: hoveredImageHasTextOverlapRef.current
|
|
7652
|
-
});
|
|
8955
|
+
setMediaHover(
|
|
8956
|
+
(prev) => prev ? { ...prev, rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height } } : prev
|
|
8957
|
+
);
|
|
7653
8958
|
}
|
|
7654
8959
|
};
|
|
7655
8960
|
const handleSave = (e) => {
|
|
@@ -7738,19 +9043,39 @@ function OhhwellsBridge() {
|
|
|
7738
9043
|
refreshActiveCommandsRef.current = handleSelectionChange;
|
|
7739
9044
|
const handleDocMouseLeave = () => {
|
|
7740
9045
|
hoveredImageRef.current = null;
|
|
9046
|
+
setMediaHover(null);
|
|
7741
9047
|
document.querySelectorAll("[data-ohw-state-hovered]").forEach((el) => el.removeAttribute("data-ohw-state-hovered"));
|
|
7742
9048
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
7743
9049
|
activeStateElRef.current = null;
|
|
7744
9050
|
setToggleState(null);
|
|
7745
9051
|
};
|
|
7746
|
-
const
|
|
7747
|
-
if (e.data?.type !== "ow:
|
|
7748
|
-
const { key } = e.data;
|
|
9052
|
+
const handleImageUploading = (e) => {
|
|
9053
|
+
if (e.data?.type !== "ow:image-uploading") return;
|
|
9054
|
+
const { key, uploading } = e.data;
|
|
9055
|
+
setUploadingRects((prev) => {
|
|
9056
|
+
if (!uploading) {
|
|
9057
|
+
if (!(key in prev)) return prev;
|
|
9058
|
+
const next = { ...prev };
|
|
9059
|
+
delete next[key];
|
|
9060
|
+
return next;
|
|
9061
|
+
}
|
|
9062
|
+
const el = document.querySelector(`[data-ohw-key="${key}"]`);
|
|
9063
|
+
if (!el) return prev;
|
|
9064
|
+
const r2 = getVisibleRect(el);
|
|
9065
|
+
return {
|
|
9066
|
+
...prev,
|
|
9067
|
+
[key]: { rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height } }
|
|
9068
|
+
};
|
|
9069
|
+
});
|
|
7749
9070
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
7750
9071
|
const track = el.closest("[data-ohw-hover-pause]");
|
|
7751
|
-
if (track)
|
|
9072
|
+
if (!track) return;
|
|
9073
|
+
if (uploading) {
|
|
7752
9074
|
uploadLockedTracks.add(track);
|
|
7753
9075
|
track.setAttribute("data-ohw-hover-paused", "");
|
|
9076
|
+
} else {
|
|
9077
|
+
uploadLockedTracks.delete(track);
|
|
9078
|
+
track.removeAttribute("data-ohw-hover-paused");
|
|
7754
9079
|
}
|
|
7755
9080
|
});
|
|
7756
9081
|
};
|
|
@@ -7792,7 +9117,7 @@ function OhhwellsBridge() {
|
|
|
7792
9117
|
if (e.data?.type !== "ow:click-at") return;
|
|
7793
9118
|
const { clientX, clientY } = e.data;
|
|
7794
9119
|
const allImages = Array.from(
|
|
7795
|
-
document.querySelectorAll(
|
|
9120
|
+
document.querySelectorAll(MEDIA_SELECTOR)
|
|
7796
9121
|
).filter((el) => !!el.closest("[data-ohw-editable-state]"));
|
|
7797
9122
|
const stateCardImage = allImages.find((el) => {
|
|
7798
9123
|
const ownerCard = el.closest("[data-ohw-editable-state]");
|
|
@@ -7807,21 +9132,55 @@ function OhhwellsBridge() {
|
|
|
7807
9132
|
return clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
|
|
7808
9133
|
});
|
|
7809
9134
|
if (stateCardImage) {
|
|
7810
|
-
postToParentRef.current({ type: "ow:image-pick", key: stateCardImage.dataset.ohwKey ?? "" });
|
|
9135
|
+
postToParentRef.current({ type: "ow:image-pick", key: stateCardImage.dataset.ohwKey ?? "", elementType: stateCardImage.dataset.ohwEditable ?? "image" });
|
|
7811
9136
|
return;
|
|
7812
9137
|
}
|
|
7813
9138
|
const textEditable = Array.from(
|
|
7814
|
-
document.querySelectorAll(
|
|
7815
|
-
'[data-ohw-editable]:not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"])'
|
|
7816
|
-
)
|
|
9139
|
+
document.querySelectorAll(NON_MEDIA_SELECTOR)
|
|
7817
9140
|
).find((el) => {
|
|
7818
9141
|
const r2 = el.getBoundingClientRect();
|
|
7819
9142
|
return clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
|
|
7820
9143
|
});
|
|
7821
9144
|
if (textEditable) {
|
|
7822
|
-
|
|
9145
|
+
const hrefCtx = getHrefKeyFromElement(textEditable);
|
|
9146
|
+
const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
|
|
9147
|
+
if (navAnchor) {
|
|
9148
|
+
if (selectedElRef.current === navAnchor) {
|
|
9149
|
+
activateRef.current(textEditable, { caretX: clientX, caretY: clientY });
|
|
9150
|
+
} else {
|
|
9151
|
+
selectRef.current(navAnchor);
|
|
9152
|
+
}
|
|
9153
|
+
return;
|
|
9154
|
+
}
|
|
9155
|
+
activateRef.current(textEditable, { caretX: clientX, caretY: clientY });
|
|
7823
9156
|
return;
|
|
7824
9157
|
}
|
|
9158
|
+
const navContainer = document.querySelector("[data-ohw-nav-container]");
|
|
9159
|
+
if (navContainer) {
|
|
9160
|
+
const r2 = navContainer.getBoundingClientRect();
|
|
9161
|
+
const pad = 8;
|
|
9162
|
+
const over = clientX >= r2.left - pad && clientX <= r2.right + pad && clientY >= r2.top - pad && clientY <= r2.bottom + pad;
|
|
9163
|
+
if (over && !isPointOverNavItem(navContainer, clientX, clientY)) {
|
|
9164
|
+
selectFrameRef.current(navContainer);
|
|
9165
|
+
return;
|
|
9166
|
+
}
|
|
9167
|
+
}
|
|
9168
|
+
const navRoot = document.querySelector("[data-ohw-nav-root]");
|
|
9169
|
+
if (navRoot && navContainer) {
|
|
9170
|
+
const rr = navRoot.getBoundingClientRect();
|
|
9171
|
+
if (clientX >= rr.left && clientX <= rr.right && clientY >= rr.top && clientY <= rr.bottom && !isPointOverNavItem(navContainer, clientX, clientY)) {
|
|
9172
|
+
const book = navRoot.querySelector('[data-ohw-role="navbar-button"]');
|
|
9173
|
+
if (book) {
|
|
9174
|
+
const br = book.getBoundingClientRect();
|
|
9175
|
+
if (clientX >= br.left && clientX <= br.right && clientY >= br.top && clientY <= br.bottom) {
|
|
9176
|
+
deactivateRef.current();
|
|
9177
|
+
return;
|
|
9178
|
+
}
|
|
9179
|
+
}
|
|
9180
|
+
selectFrameRef.current(navContainer);
|
|
9181
|
+
return;
|
|
9182
|
+
}
|
|
9183
|
+
}
|
|
7825
9184
|
deactivateRef.current();
|
|
7826
9185
|
};
|
|
7827
9186
|
window.addEventListener("message", handleSave);
|
|
@@ -7831,7 +9190,7 @@ function OhhwellsBridge() {
|
|
|
7831
9190
|
window.addEventListener("message", handleClearSchedulingWidget);
|
|
7832
9191
|
window.addEventListener("message", handleRemoveSchedulingSection);
|
|
7833
9192
|
window.addEventListener("message", handleImageUrl);
|
|
7834
|
-
window.addEventListener("message",
|
|
9193
|
+
window.addEventListener("message", handleImageUploading);
|
|
7835
9194
|
window.addEventListener("message", handleCanvasHeight);
|
|
7836
9195
|
window.addEventListener("message", handleParentScroll);
|
|
7837
9196
|
window.addEventListener("message", handlePointerSync);
|
|
@@ -7843,6 +9202,7 @@ function OhhwellsBridge() {
|
|
|
7843
9202
|
};
|
|
7844
9203
|
window.addEventListener("resize", handleViewportResize, { passive: true });
|
|
7845
9204
|
document.addEventListener("click", handleClick, true);
|
|
9205
|
+
document.addEventListener("dblclick", handleDblClick, true);
|
|
7846
9206
|
document.addEventListener("paste", handlePaste, true);
|
|
7847
9207
|
document.addEventListener("input", handleInput, true);
|
|
7848
9208
|
document.addEventListener("mouseover", handleMouseOver, true);
|
|
@@ -7857,6 +9217,7 @@ function OhhwellsBridge() {
|
|
|
7857
9217
|
window.addEventListener("scroll", handleScroll, true);
|
|
7858
9218
|
return () => {
|
|
7859
9219
|
document.removeEventListener("click", handleClick, true);
|
|
9220
|
+
document.removeEventListener("dblclick", handleDblClick, true);
|
|
7860
9221
|
document.removeEventListener("paste", handlePaste, true);
|
|
7861
9222
|
document.removeEventListener("input", handleInput, true);
|
|
7862
9223
|
document.removeEventListener("mouseover", handleMouseOver, true);
|
|
@@ -7876,7 +9237,7 @@ function OhhwellsBridge() {
|
|
|
7876
9237
|
window.removeEventListener("message", handleClearSchedulingWidget);
|
|
7877
9238
|
window.removeEventListener("message", handleRemoveSchedulingSection);
|
|
7878
9239
|
window.removeEventListener("message", handleImageUrl);
|
|
7879
|
-
window.removeEventListener("message",
|
|
9240
|
+
window.removeEventListener("message", handleImageUploading);
|
|
7880
9241
|
window.removeEventListener("message", handleCanvasHeight);
|
|
7881
9242
|
window.removeEventListener("message", handleParentScroll);
|
|
7882
9243
|
window.removeEventListener("resize", handleViewportResize);
|
|
@@ -7890,7 +9251,7 @@ function OhhwellsBridge() {
|
|
|
7890
9251
|
if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
|
|
7891
9252
|
};
|
|
7892
9253
|
}, [isEditMode, refreshStateRules]);
|
|
7893
|
-
|
|
9254
|
+
useEffect7(() => {
|
|
7894
9255
|
const handler = (e) => {
|
|
7895
9256
|
if (e.data?.type !== "ow:request-schedule-config") return;
|
|
7896
9257
|
const insertAfterVal = e.data.insertAfter;
|
|
@@ -7906,7 +9267,7 @@ function OhhwellsBridge() {
|
|
|
7906
9267
|
window.addEventListener("message", handler);
|
|
7907
9268
|
return () => window.removeEventListener("message", handler);
|
|
7908
9269
|
}, [processConfigRequest]);
|
|
7909
|
-
|
|
9270
|
+
useEffect7(() => {
|
|
7910
9271
|
if (!isEditMode) return;
|
|
7911
9272
|
document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
|
|
7912
9273
|
el.removeAttribute("data-ohw-active-state");
|
|
@@ -7927,27 +9288,27 @@ function OhhwellsBridge() {
|
|
|
7927
9288
|
const next = { ...prev, [pathKey]: sections };
|
|
7928
9289
|
return shouldUseDevFixtures() ? { ...DEV_SECTIONS_BY_PATH, ...next } : next;
|
|
7929
9290
|
});
|
|
7930
|
-
|
|
7931
|
-
|
|
9291
|
+
postToParent2({ type: "ow:ready", version: "1", path: pathname, nodes: collectEditableNodes(), sections });
|
|
9292
|
+
postToParent2({ type: "ow:request-site-pages" });
|
|
7932
9293
|
}, 150);
|
|
7933
9294
|
return () => {
|
|
7934
9295
|
cancelAnimationFrame(raf);
|
|
7935
9296
|
clearTimeout(timer);
|
|
7936
9297
|
};
|
|
7937
|
-
}, [pathname, isEditMode, refreshStateRules,
|
|
7938
|
-
|
|
9298
|
+
}, [pathname, isEditMode, refreshStateRules, postToParent2]);
|
|
9299
|
+
useEffect7(() => {
|
|
7939
9300
|
scrollToHashSectionWhenReady();
|
|
7940
9301
|
const onHashChange = () => scrollToHashSectionWhenReady();
|
|
7941
9302
|
window.addEventListener("hashchange", onHashChange);
|
|
7942
9303
|
return () => window.removeEventListener("hashchange", onHashChange);
|
|
7943
9304
|
}, [pathname]);
|
|
7944
|
-
const handleCommand =
|
|
9305
|
+
const handleCommand = useCallback4((cmd) => {
|
|
7945
9306
|
document.execCommand(cmd, false);
|
|
7946
9307
|
activeElRef.current?.focus();
|
|
7947
9308
|
if (activeElRef.current) setToolbarRect(getEditMeasureEl(activeElRef.current).getBoundingClientRect());
|
|
7948
9309
|
refreshActiveCommandsRef.current();
|
|
7949
9310
|
}, []);
|
|
7950
|
-
const handleStateChange =
|
|
9311
|
+
const handleStateChange = useCallback4((state) => {
|
|
7951
9312
|
if (!activeStateElRef.current) return;
|
|
7952
9313
|
const el = activeStateElRef.current;
|
|
7953
9314
|
if (state === "Default") {
|
|
@@ -7960,18 +9321,22 @@ function OhhwellsBridge() {
|
|
|
7960
9321
|
}
|
|
7961
9322
|
setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
|
|
7962
9323
|
}, [deactivate]);
|
|
7963
|
-
const closeLinkPopover =
|
|
7964
|
-
|
|
9324
|
+
const closeLinkPopover = useCallback4(() => {
|
|
9325
|
+
addNavAfterAnchorRef.current = null;
|
|
9326
|
+
setLinkPopover(null);
|
|
9327
|
+
}, []);
|
|
9328
|
+
const openLinkPopoverForActive = useCallback4(() => {
|
|
7965
9329
|
const hrefCtx = getHrefKeyFromElement(activeElRef.current);
|
|
7966
9330
|
if (!hrefCtx) return;
|
|
7967
9331
|
bumpLinkPopoverGrace();
|
|
7968
9332
|
setLinkPopover({
|
|
7969
9333
|
key: hrefCtx.key,
|
|
7970
|
-
|
|
9334
|
+
mode: "edit",
|
|
9335
|
+
target: getLinkHref2(hrefCtx.anchor)
|
|
7971
9336
|
});
|
|
7972
9337
|
deactivate();
|
|
7973
9338
|
}, [deactivate]);
|
|
7974
|
-
const openLinkPopoverForSelected =
|
|
9339
|
+
const openLinkPopoverForSelected = useCallback4(() => {
|
|
7975
9340
|
const anchor = selectedElRef.current;
|
|
7976
9341
|
if (!anchor) return;
|
|
7977
9342
|
const key = anchor.getAttribute("data-ohw-href-key");
|
|
@@ -7979,51 +9344,156 @@ function OhhwellsBridge() {
|
|
|
7979
9344
|
bumpLinkPopoverGrace();
|
|
7980
9345
|
setLinkPopover({
|
|
7981
9346
|
key,
|
|
7982
|
-
|
|
9347
|
+
mode: "edit",
|
|
9348
|
+
target: getLinkHref2(anchor)
|
|
7983
9349
|
});
|
|
7984
9350
|
deselect();
|
|
7985
9351
|
}, [deselect]);
|
|
7986
|
-
const handleLinkPopoverSubmit =
|
|
9352
|
+
const handleLinkPopoverSubmit = useCallback4(
|
|
7987
9353
|
(target) => {
|
|
7988
|
-
|
|
7989
|
-
|
|
9354
|
+
const session = linkPopoverSessionRef.current;
|
|
9355
|
+
if (!session) return;
|
|
9356
|
+
if (session.intent === "add-nav") {
|
|
9357
|
+
const { pageRoute, sectionId } = parseTarget(target);
|
|
9358
|
+
const page = resolvePage(pageRoute, sitePages);
|
|
9359
|
+
const pageSections = getSectionsForPath(sectionsByPath, pageRoute);
|
|
9360
|
+
const section = sectionId ? pageSections.find((s) => s.id === sectionId) : void 0;
|
|
9361
|
+
const label = section?.label ?? page.title;
|
|
9362
|
+
const afterAnchor = addNavAfterAnchorRef.current;
|
|
9363
|
+
const { anchor, hrefKey, labelKey, index, order } = insertNavbarItem(target, label, afterAnchor);
|
|
9364
|
+
applyLinkByKey(hrefKey, target);
|
|
9365
|
+
document.querySelectorAll(`[data-ohw-key="${labelKey}"]`).forEach((el) => {
|
|
9366
|
+
el.textContent = label;
|
|
9367
|
+
});
|
|
9368
|
+
const navCount = String(index + 1);
|
|
9369
|
+
const orderJson = JSON.stringify(order);
|
|
9370
|
+
editContentRef.current = {
|
|
9371
|
+
...editContentRef.current,
|
|
9372
|
+
[hrefKey]: target,
|
|
9373
|
+
[labelKey]: label,
|
|
9374
|
+
[NAV_COUNT_KEY]: navCount,
|
|
9375
|
+
[NAV_ORDER_KEY]: orderJson
|
|
9376
|
+
};
|
|
9377
|
+
postToParent2({
|
|
9378
|
+
type: "ow:change",
|
|
9379
|
+
nodes: [
|
|
9380
|
+
{ key: hrefKey, text: target },
|
|
9381
|
+
{ key: labelKey, text: label },
|
|
9382
|
+
{ key: NAV_COUNT_KEY, text: navCount },
|
|
9383
|
+
{ key: NAV_ORDER_KEY, text: orderJson }
|
|
9384
|
+
]
|
|
9385
|
+
});
|
|
9386
|
+
addNavAfterAnchorRef.current = null;
|
|
9387
|
+
setLinkPopover(null);
|
|
9388
|
+
enforceLinkHrefs();
|
|
9389
|
+
requestAnimationFrame(() => {
|
|
9390
|
+
selectRef.current(anchor);
|
|
9391
|
+
});
|
|
9392
|
+
return;
|
|
9393
|
+
}
|
|
9394
|
+
const { key } = session;
|
|
7990
9395
|
applyLinkByKey(key, target);
|
|
7991
|
-
|
|
9396
|
+
postToParent2({ type: "ow:change", nodes: [{ key, text: target }] });
|
|
7992
9397
|
setLinkPopover(null);
|
|
7993
9398
|
},
|
|
7994
|
-
[
|
|
9399
|
+
[postToParent2, sitePages, sectionsByPath]
|
|
7995
9400
|
);
|
|
7996
9401
|
const showEditLink = toolbarShowEditLink;
|
|
7997
9402
|
const currentSections = sectionsByPath[pathname] ?? [];
|
|
7998
9403
|
linkPopoverOpenRef.current = linkPopover !== null;
|
|
7999
|
-
|
|
8000
|
-
|
|
8001
|
-
|
|
8002
|
-
|
|
8003
|
-
|
|
8004
|
-
|
|
9404
|
+
const handleMediaReplace = useCallback4(
|
|
9405
|
+
(key) => {
|
|
9406
|
+
postToParent2({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
|
|
9407
|
+
},
|
|
9408
|
+
[postToParent2, mediaHover?.elementType]
|
|
9409
|
+
);
|
|
9410
|
+
const handleMediaFadeOutComplete = useCallback4((key) => {
|
|
9411
|
+
setUploadingRects((prev) => {
|
|
9412
|
+
if (!(key in prev)) return prev;
|
|
9413
|
+
const next = { ...prev };
|
|
9414
|
+
delete next[key];
|
|
9415
|
+
return next;
|
|
9416
|
+
});
|
|
9417
|
+
}, []);
|
|
9418
|
+
const handleVideoSettingsChange = useCallback4(
|
|
9419
|
+
(key, settings) => {
|
|
9420
|
+
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
9421
|
+
const video = getVideoEl(el);
|
|
9422
|
+
if (!video) return;
|
|
9423
|
+
if (typeof settings.autoplay === "boolean") video.autoplay = settings.autoplay;
|
|
9424
|
+
if (typeof settings.muted === "boolean") video.muted = settings.muted;
|
|
9425
|
+
syncVideoPlayback(video);
|
|
9426
|
+
postToParent2({
|
|
9427
|
+
type: "ow:change",
|
|
9428
|
+
nodes: [
|
|
9429
|
+
{ key: `${key}${VIDEO_AUTOPLAY_SUFFIX}`, text: String(video.autoplay) },
|
|
9430
|
+
{ key: `${key}${VIDEO_MUTED_SUFFIX}`, text: String(video.muted) }
|
|
9431
|
+
]
|
|
9432
|
+
});
|
|
9433
|
+
setMediaHover(
|
|
9434
|
+
(prev) => prev && prev.key === key ? { ...prev, videoAutoplay: video.autoplay, videoMuted: video.muted } : prev
|
|
9435
|
+
);
|
|
9436
|
+
});
|
|
9437
|
+
},
|
|
9438
|
+
[postToParent2]
|
|
9439
|
+
);
|
|
9440
|
+
return bridgeRoot ? createPortal2(
|
|
9441
|
+
/* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
9442
|
+
/* @__PURE__ */ jsx23("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
9443
|
+
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ jsx23(
|
|
9444
|
+
MediaOverlay,
|
|
9445
|
+
{
|
|
9446
|
+
hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
|
|
9447
|
+
isUploading: true,
|
|
9448
|
+
fadingOut,
|
|
9449
|
+
onFadeOutComplete: handleMediaFadeOutComplete,
|
|
9450
|
+
onReplace: handleMediaReplace
|
|
9451
|
+
},
|
|
9452
|
+
`uploading-${key}`
|
|
9453
|
+
)),
|
|
9454
|
+
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ jsx23(
|
|
9455
|
+
MediaOverlay,
|
|
9456
|
+
{
|
|
9457
|
+
hover: mediaHover,
|
|
9458
|
+
isUploading: false,
|
|
9459
|
+
onReplace: handleMediaReplace,
|
|
9460
|
+
onVideoSettingsChange: handleVideoSettingsChange
|
|
9461
|
+
}
|
|
9462
|
+
),
|
|
9463
|
+
siblingHintRect && !isItemDragging && /* @__PURE__ */ jsx23(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
9464
|
+
hoveredNavContainerRect && toolbarVariant !== "select-frame" && !linkPopover && !isItemDragging && !siblingHintRect && /* @__PURE__ */ jsx23(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
|
|
9465
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx23(
|
|
9466
|
+
NavbarContainerChrome,
|
|
9467
|
+
{
|
|
9468
|
+
rect: toolbarRect,
|
|
9469
|
+
onAdd: handleAddTopLevelNavItem
|
|
9470
|
+
}
|
|
9471
|
+
),
|
|
9472
|
+
hoveredItemRect && !hoveredNavContainerRect && !siblingHintRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx23(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
9473
|
+
toolbarRect && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ jsx23(
|
|
8005
9474
|
ItemInteractionLayer,
|
|
8006
9475
|
{
|
|
8007
9476
|
rect: toolbarRect,
|
|
8008
9477
|
elRef: glowElRef,
|
|
8009
9478
|
state: isItemDragging ? "dragging" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
|
|
8010
|
-
showHandle: Boolean(reorderHrefKey),
|
|
9479
|
+
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey),
|
|
8011
9480
|
dragDisabled: reorderDragDisabled,
|
|
8012
9481
|
dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
|
|
8013
9482
|
onDragHandleDragStart: handleItemDragStart,
|
|
8014
9483
|
onDragHandleDragEnd: handleItemDragEnd,
|
|
8015
|
-
toolbar:
|
|
9484
|
+
toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ jsx23(
|
|
8016
9485
|
ItemActionToolbar,
|
|
8017
9486
|
{
|
|
8018
9487
|
onEditLink: openLinkPopoverForSelected,
|
|
8019
|
-
|
|
8020
|
-
|
|
9488
|
+
addItemDisabled: true,
|
|
9489
|
+
editLinkDisabled: false,
|
|
9490
|
+
moreDisabled: true
|
|
8021
9491
|
}
|
|
8022
|
-
)
|
|
9492
|
+
) : void 0
|
|
8023
9493
|
}
|
|
8024
9494
|
),
|
|
8025
|
-
toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */
|
|
8026
|
-
/* @__PURE__ */
|
|
9495
|
+
toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
9496
|
+
/* @__PURE__ */ jsx23(
|
|
8027
9497
|
EditGlowChrome,
|
|
8028
9498
|
{
|
|
8029
9499
|
rect: toolbarRect,
|
|
@@ -8032,7 +9502,7 @@ function OhhwellsBridge() {
|
|
|
8032
9502
|
dragDisabled: reorderDragDisabled
|
|
8033
9503
|
}
|
|
8034
9504
|
),
|
|
8035
|
-
/* @__PURE__ */
|
|
9505
|
+
/* @__PURE__ */ jsx23(
|
|
8036
9506
|
FloatingToolbar,
|
|
8037
9507
|
{
|
|
8038
9508
|
rect: toolbarRect,
|
|
@@ -8045,7 +9515,7 @@ function OhhwellsBridge() {
|
|
|
8045
9515
|
}
|
|
8046
9516
|
)
|
|
8047
9517
|
] }),
|
|
8048
|
-
maxBadge && /* @__PURE__ */
|
|
9518
|
+
maxBadge && /* @__PURE__ */ jsxs13(
|
|
8049
9519
|
"div",
|
|
8050
9520
|
{
|
|
8051
9521
|
"data-ohw-max-badge": "",
|
|
@@ -8071,7 +9541,7 @@ function OhhwellsBridge() {
|
|
|
8071
9541
|
]
|
|
8072
9542
|
}
|
|
8073
9543
|
),
|
|
8074
|
-
toggleState && /* @__PURE__ */
|
|
9544
|
+
toggleState && !linkPopover && /* @__PURE__ */ jsx23(
|
|
8075
9545
|
StateToggle,
|
|
8076
9546
|
{
|
|
8077
9547
|
rect: toggleState.rect,
|
|
@@ -8080,15 +9550,15 @@ function OhhwellsBridge() {
|
|
|
8080
9550
|
onStateChange: handleStateChange
|
|
8081
9551
|
}
|
|
8082
9552
|
),
|
|
8083
|
-
sectionGap && /* @__PURE__ */
|
|
9553
|
+
sectionGap && !linkPopover && /* @__PURE__ */ jsxs13(
|
|
8084
9554
|
"div",
|
|
8085
9555
|
{
|
|
8086
9556
|
"data-ohw-section-insert-line": "",
|
|
8087
9557
|
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
8088
9558
|
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
8089
9559
|
children: [
|
|
8090
|
-
/* @__PURE__ */
|
|
8091
|
-
/* @__PURE__ */
|
|
9560
|
+
/* @__PURE__ */ jsx23("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
9561
|
+
/* @__PURE__ */ jsx23(
|
|
8092
9562
|
Badge,
|
|
8093
9563
|
{
|
|
8094
9564
|
className: "px-8 py-1 bg-primary hover:bg-primary text-primary-foreground text-xs font-medium shrink-0 rounded-full cursor-pointer pointer-events-auto",
|
|
@@ -8101,26 +9571,52 @@ function OhhwellsBridge() {
|
|
|
8101
9571
|
children: "Add Section"
|
|
8102
9572
|
}
|
|
8103
9573
|
),
|
|
8104
|
-
/* @__PURE__ */
|
|
9574
|
+
/* @__PURE__ */ jsx23("div", { className: "flex-1 bg-primary", style: { height: 3 } })
|
|
8105
9575
|
]
|
|
8106
9576
|
}
|
|
8107
9577
|
),
|
|
8108
|
-
linkPopover && dialogPortalContainer ? /* @__PURE__ */
|
|
9578
|
+
linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx23(
|
|
8109
9579
|
LinkPopover,
|
|
8110
9580
|
{
|
|
8111
9581
|
panelRef: linkPopoverPanelRef,
|
|
8112
9582
|
portalContainer: dialogPortalContainer,
|
|
8113
9583
|
open: true,
|
|
8114
|
-
mode: "edit",
|
|
9584
|
+
mode: linkPopover.mode ?? "edit",
|
|
8115
9585
|
pages: sitePages,
|
|
8116
9586
|
sections: currentSections,
|
|
8117
9587
|
sectionsByPath,
|
|
8118
9588
|
initialTarget: linkPopover.target,
|
|
9589
|
+
existingTargets: linkPopover.intent === "add-nav" ? getNavbarExistingTargets() : [],
|
|
8119
9590
|
onClose: closeLinkPopover,
|
|
8120
9591
|
onSubmit: handleLinkPopoverSubmit
|
|
8121
9592
|
},
|
|
8122
|
-
|
|
8123
|
-
) : null
|
|
9593
|
+
linkPopover.key
|
|
9594
|
+
) : null,
|
|
9595
|
+
sectionGap && /* @__PURE__ */ jsxs13(
|
|
9596
|
+
"div",
|
|
9597
|
+
{
|
|
9598
|
+
"data-ohw-section-insert-line": "",
|
|
9599
|
+
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
9600
|
+
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
9601
|
+
children: [
|
|
9602
|
+
/* @__PURE__ */ jsx23("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
9603
|
+
/* @__PURE__ */ jsx23(
|
|
9604
|
+
Badge,
|
|
9605
|
+
{
|
|
9606
|
+
className: "px-8 py-1 bg-primary hover:bg-primary text-primary-foreground text-xs font-medium shrink-0 rounded-full cursor-pointer pointer-events-auto",
|
|
9607
|
+
onClick: () => {
|
|
9608
|
+
window.parent.postMessage(
|
|
9609
|
+
{ type: "ow:add-section", insertAfter: sectionGap.insertAfter, insertBefore: sectionGap.insertBefore },
|
|
9610
|
+
"*"
|
|
9611
|
+
);
|
|
9612
|
+
},
|
|
9613
|
+
children: "Add Section"
|
|
9614
|
+
}
|
|
9615
|
+
),
|
|
9616
|
+
/* @__PURE__ */ jsx23("div", { className: "flex-1 bg-primary", style: { height: 3 } })
|
|
9617
|
+
]
|
|
9618
|
+
}
|
|
9619
|
+
)
|
|
8124
9620
|
] }),
|
|
8125
9621
|
bridgeRoot
|
|
8126
9622
|
) : null;
|