@ohhwells/bridge 0.1.37 → 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 +2105 -614
- 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 +2103 -612
- package/dist/index.js.map +1 -1
- package/dist/styles.css +156 -21
- package/package.json +1 -1
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) {
|
|
@@ -5750,7 +6637,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
5750
6637
|
const root = createRoot(container);
|
|
5751
6638
|
flushSync(() => {
|
|
5752
6639
|
root.render(
|
|
5753
|
-
/* @__PURE__ */
|
|
6640
|
+
/* @__PURE__ */ jsx23(
|
|
5754
6641
|
SchedulingWidget,
|
|
5755
6642
|
{
|
|
5756
6643
|
notifyOnConnect,
|
|
@@ -5790,7 +6677,7 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
|
|
|
5790
6677
|
}
|
|
5791
6678
|
}
|
|
5792
6679
|
}
|
|
5793
|
-
function
|
|
6680
|
+
function getLinkHref2(el) {
|
|
5794
6681
|
const anchor = el instanceof HTMLAnchorElement ? el : el.querySelector("a");
|
|
5795
6682
|
return anchor?.getAttribute("href") ?? "";
|
|
5796
6683
|
}
|
|
@@ -5823,8 +6710,11 @@ function collectEditableNodes() {
|
|
|
5823
6710
|
const url = raw.replace(/^url\(['"]?/, "").replace(/['"]?\)$/, "");
|
|
5824
6711
|
return { key: el.dataset.ohwKey ?? "", type: "bg-image", text: url };
|
|
5825
6712
|
}
|
|
6713
|
+
if (el.dataset.ohwEditable === "video") {
|
|
6714
|
+
return { key: el.dataset.ohwKey ?? "", type: "video", text: getVideoEl(el)?.src ?? "" };
|
|
6715
|
+
}
|
|
5826
6716
|
if (el.dataset.ohwEditable === "link") {
|
|
5827
|
-
return { key: el.dataset.ohwKey ?? "", type: "link", text:
|
|
6717
|
+
return { key: el.dataset.ohwKey ?? "", type: "link", text: getLinkHref2(el) };
|
|
5828
6718
|
}
|
|
5829
6719
|
return {
|
|
5830
6720
|
key: el.dataset.ohwKey ?? "",
|
|
@@ -5835,9 +6725,79 @@ function collectEditableNodes() {
|
|
|
5835
6725
|
document.querySelectorAll("[data-ohw-href-key]").forEach((el) => {
|
|
5836
6726
|
const key = el.getAttribute("data-ohw-href-key") ?? "";
|
|
5837
6727
|
if (!key) return;
|
|
5838
|
-
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);
|
|
5839
6799
|
});
|
|
5840
|
-
return
|
|
6800
|
+
return true;
|
|
5841
6801
|
}
|
|
5842
6802
|
function applyLinkByKey(key, val) {
|
|
5843
6803
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -5851,7 +6811,7 @@ function applyLinkByKey(key, val) {
|
|
|
5851
6811
|
}
|
|
5852
6812
|
function isInsideLinkEditor(target) {
|
|
5853
6813
|
return Boolean(
|
|
5854
|
-
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"]')
|
|
5855
6815
|
);
|
|
5856
6816
|
}
|
|
5857
6817
|
function getHrefKeyFromElement(el) {
|
|
@@ -5862,7 +6822,7 @@ function getHrefKeyFromElement(el) {
|
|
|
5862
6822
|
if (!key) return null;
|
|
5863
6823
|
return { anchor, key };
|
|
5864
6824
|
}
|
|
5865
|
-
function
|
|
6825
|
+
function isNavbarButton2(el) {
|
|
5866
6826
|
return Boolean(el.closest('[data-ohw-role="navbar-button"]'));
|
|
5867
6827
|
}
|
|
5868
6828
|
function getNavigationItemAnchor(el) {
|
|
@@ -5874,19 +6834,8 @@ function getNavigationItemAnchor(el) {
|
|
|
5874
6834
|
function isNavigationItem(el) {
|
|
5875
6835
|
return getNavigationItemAnchor(el) !== null;
|
|
5876
6836
|
}
|
|
5877
|
-
function getNavigationItemAddHintTarget(anchor) {
|
|
5878
|
-
const items = listNavigationItems();
|
|
5879
|
-
const idx = items.indexOf(anchor);
|
|
5880
|
-
if (idx >= 0 && idx < items.length - 1) return items[idx + 1];
|
|
5881
|
-
return anchor;
|
|
5882
|
-
}
|
|
5883
|
-
function listNavigationItems() {
|
|
5884
|
-
return Array.from(
|
|
5885
|
-
document.querySelectorAll("nav [data-ohw-href-key], footer [data-ohw-href-key]")
|
|
5886
|
-
).filter((el) => isNavigationItem(el));
|
|
5887
|
-
}
|
|
5888
6837
|
function getNavigationItemReorderState(anchor) {
|
|
5889
|
-
if (
|
|
6838
|
+
if (isNavbarButton2(anchor)) return { key: null, disabled: false };
|
|
5890
6839
|
return getReorderHandleStateFromAnchor(anchor);
|
|
5891
6840
|
}
|
|
5892
6841
|
function getReorderHandleState(el) {
|
|
@@ -5908,6 +6857,120 @@ function clearHrefKeyHover(anchor) {
|
|
|
5908
6857
|
function isInsideNavigationItem(el) {
|
|
5909
6858
|
return getNavigationItemAnchor(el) !== null;
|
|
5910
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
|
+
}
|
|
5911
6974
|
function collectSections() {
|
|
5912
6975
|
return collectSectionsFromDom();
|
|
5913
6976
|
}
|
|
@@ -6031,6 +7094,8 @@ var ICONS = {
|
|
|
6031
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"/>',
|
|
6032
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"/>'
|
|
6033
7096
|
};
|
|
7097
|
+
var TOOLBAR_PILL_PADDING = 2;
|
|
7098
|
+
var TOOLBAR_TOGGLE_GAP = 4;
|
|
6034
7099
|
var TOOLBAR_GROUPS = [
|
|
6035
7100
|
[
|
|
6036
7101
|
{ cmd: "bold", title: "Bold" },
|
|
@@ -6055,7 +7120,7 @@ function EditGlowChrome({
|
|
|
6055
7120
|
dragDisabled = false
|
|
6056
7121
|
}) {
|
|
6057
7122
|
const GAP = 6;
|
|
6058
|
-
return /* @__PURE__ */
|
|
7123
|
+
return /* @__PURE__ */ jsxs13(
|
|
6059
7124
|
"div",
|
|
6060
7125
|
{
|
|
6061
7126
|
ref: elRef,
|
|
@@ -6070,7 +7135,7 @@ function EditGlowChrome({
|
|
|
6070
7135
|
zIndex: 2147483646
|
|
6071
7136
|
},
|
|
6072
7137
|
children: [
|
|
6073
|
-
/* @__PURE__ */
|
|
7138
|
+
/* @__PURE__ */ jsx23(
|
|
6074
7139
|
"div",
|
|
6075
7140
|
{
|
|
6076
7141
|
style: {
|
|
@@ -6083,7 +7148,7 @@ function EditGlowChrome({
|
|
|
6083
7148
|
}
|
|
6084
7149
|
}
|
|
6085
7150
|
),
|
|
6086
|
-
reorderHrefKey && /* @__PURE__ */
|
|
7151
|
+
reorderHrefKey && /* @__PURE__ */ jsx23(
|
|
6087
7152
|
"div",
|
|
6088
7153
|
{
|
|
6089
7154
|
"data-ohw-drag-handle-container": "",
|
|
@@ -6095,7 +7160,7 @@ function EditGlowChrome({
|
|
|
6095
7160
|
transform: "translate(calc(-100% - 7px), -50%)",
|
|
6096
7161
|
pointerEvents: dragDisabled ? "none" : "auto"
|
|
6097
7162
|
},
|
|
6098
|
-
children: /* @__PURE__ */
|
|
7163
|
+
children: /* @__PURE__ */ jsx23(
|
|
6099
7164
|
DragHandle,
|
|
6100
7165
|
{
|
|
6101
7166
|
"aria-label": `Reorder ${reorderHrefKey}`,
|
|
@@ -6199,7 +7264,7 @@ function FloatingToolbar({
|
|
|
6199
7264
|
onEditLink
|
|
6200
7265
|
}) {
|
|
6201
7266
|
const { top, left, transform } = calcToolbarPos(rect, parentScroll, 330);
|
|
6202
|
-
return /* @__PURE__ */
|
|
7267
|
+
return /* @__PURE__ */ jsx23(
|
|
6203
7268
|
"div",
|
|
6204
7269
|
{
|
|
6205
7270
|
ref: elRef,
|
|
@@ -6209,14 +7274,23 @@ function FloatingToolbar({
|
|
|
6209
7274
|
left,
|
|
6210
7275
|
transform,
|
|
6211
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",
|
|
6212
7286
|
pointerEvents: "auto"
|
|
6213
7287
|
},
|
|
6214
|
-
children: /* @__PURE__ */
|
|
6215
|
-
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */
|
|
6216
|
-
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, {}),
|
|
6217
7291
|
btns.map((btn) => {
|
|
6218
7292
|
const isActive = activeCommands.has(btn.cmd);
|
|
6219
|
-
return /* @__PURE__ */
|
|
7293
|
+
return /* @__PURE__ */ jsx23(
|
|
6220
7294
|
CustomToolbarButton,
|
|
6221
7295
|
{
|
|
6222
7296
|
title: btn.title,
|
|
@@ -6225,7 +7299,7 @@ function FloatingToolbar({
|
|
|
6225
7299
|
e.preventDefault();
|
|
6226
7300
|
onCommand(btn.cmd);
|
|
6227
7301
|
},
|
|
6228
|
-
children: /* @__PURE__ */
|
|
7302
|
+
children: /* @__PURE__ */ jsx23(
|
|
6229
7303
|
"svg",
|
|
6230
7304
|
{
|
|
6231
7305
|
width: "16",
|
|
@@ -6246,7 +7320,7 @@ function FloatingToolbar({
|
|
|
6246
7320
|
);
|
|
6247
7321
|
})
|
|
6248
7322
|
] }, gi)),
|
|
6249
|
-
showEditLink ? /* @__PURE__ */
|
|
7323
|
+
showEditLink ? /* @__PURE__ */ jsx23(
|
|
6250
7324
|
CustomToolbarButton,
|
|
6251
7325
|
{
|
|
6252
7326
|
type: "button",
|
|
@@ -6260,7 +7334,7 @@ function FloatingToolbar({
|
|
|
6260
7334
|
e.preventDefault();
|
|
6261
7335
|
e.stopPropagation();
|
|
6262
7336
|
},
|
|
6263
|
-
children: /* @__PURE__ */
|
|
7337
|
+
children: /* @__PURE__ */ jsx23(Link2, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
6264
7338
|
}
|
|
6265
7339
|
) : null
|
|
6266
7340
|
] })
|
|
@@ -6277,7 +7351,7 @@ function StateToggle({
|
|
|
6277
7351
|
states,
|
|
6278
7352
|
onStateChange
|
|
6279
7353
|
}) {
|
|
6280
|
-
return /* @__PURE__ */
|
|
7354
|
+
return /* @__PURE__ */ jsx23(
|
|
6281
7355
|
ToggleGroup,
|
|
6282
7356
|
{
|
|
6283
7357
|
"data-ohw-state-toggle": "",
|
|
@@ -6291,7 +7365,7 @@ function StateToggle({
|
|
|
6291
7365
|
left: rect.right - 8,
|
|
6292
7366
|
transform: "translateX(-100%)"
|
|
6293
7367
|
},
|
|
6294
|
-
children: states.map((state) => /* @__PURE__ */
|
|
7368
|
+
children: states.map((state) => /* @__PURE__ */ jsx23(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
|
|
6295
7369
|
}
|
|
6296
7370
|
);
|
|
6297
7371
|
}
|
|
@@ -6314,12 +7388,12 @@ function resolveSubdomain(subdomainFromQuery) {
|
|
|
6314
7388
|
return "";
|
|
6315
7389
|
}
|
|
6316
7390
|
function OhhwellsBridge() {
|
|
6317
|
-
const pathname =
|
|
6318
|
-
const router =
|
|
7391
|
+
const pathname = usePathname2();
|
|
7392
|
+
const router = useRouter2();
|
|
6319
7393
|
const searchParams = useSearchParams();
|
|
6320
7394
|
const isEditMode = isEditSessionActive();
|
|
6321
|
-
const [bridgeRoot, setBridgeRoot] =
|
|
6322
|
-
|
|
7395
|
+
const [bridgeRoot, setBridgeRoot] = useState6(null);
|
|
7396
|
+
useEffect7(() => {
|
|
6323
7397
|
const figtreeFontId = "ohw-figtree-font";
|
|
6324
7398
|
if (!document.getElementById(figtreeFontId)) {
|
|
6325
7399
|
const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
|
|
@@ -6327,7 +7401,10 @@ function OhhwellsBridge() {
|
|
|
6327
7401
|
const stylesheet = Object.assign(document.createElement("link"), {
|
|
6328
7402
|
id: figtreeFontId,
|
|
6329
7403
|
rel: "stylesheet",
|
|
6330
|
-
|
|
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"
|
|
6331
7408
|
});
|
|
6332
7409
|
document.head.append(preconnect1, preconnect2, stylesheet);
|
|
6333
7410
|
}
|
|
@@ -6344,80 +7421,91 @@ function OhhwellsBridge() {
|
|
|
6344
7421
|
const subdomainFromQuery = searchParams.get("subdomain");
|
|
6345
7422
|
const subdomain = resolveSubdomain(subdomainFromQuery);
|
|
6346
7423
|
useLinkHrefGuardian(pathname, subdomain, isEditMode);
|
|
6347
|
-
const
|
|
7424
|
+
const postToParent2 = useCallback4((data) => {
|
|
6348
7425
|
if (typeof window !== "undefined" && window.parent !== window) {
|
|
6349
7426
|
window.parent.postMessage(data, "*");
|
|
6350
7427
|
}
|
|
6351
7428
|
}, []);
|
|
6352
|
-
const [fetchState, setFetchState] =
|
|
6353
|
-
const autoSaveTimers =
|
|
6354
|
-
const activeElRef =
|
|
6355
|
-
const selectedElRef =
|
|
6356
|
-
const originalContentRef =
|
|
6357
|
-
const activeStateElRef =
|
|
6358
|
-
const parentScrollRef =
|
|
6359
|
-
const visibleViewportRef =
|
|
6360
|
-
const [dialogPortalContainer, setDialogPortalContainer] =
|
|
6361
|
-
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) => {
|
|
6362
7439
|
visibleViewportRef.current = node;
|
|
6363
7440
|
setDialogPortalContainer(node);
|
|
6364
7441
|
if (node) applyVisibleViewport(node, parentScrollRef.current);
|
|
6365
7442
|
}, []);
|
|
6366
|
-
const toolbarElRef =
|
|
6367
|
-
const glowElRef =
|
|
6368
|
-
const hoveredImageRef =
|
|
6369
|
-
const hoveredImageHasTextOverlapRef =
|
|
6370
|
-
const
|
|
6371
|
-
const
|
|
6372
|
-
const
|
|
6373
|
-
const
|
|
6374
|
-
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(() => {
|
|
6375
7457
|
});
|
|
6376
|
-
const
|
|
7458
|
+
const selectRef = useRef4(() => {
|
|
6377
7459
|
});
|
|
6378
|
-
const
|
|
7460
|
+
const selectFrameRef = useRef4(() => {
|
|
6379
7461
|
});
|
|
6380
|
-
const deselectRef =
|
|
7462
|
+
const deselectRef = useRef4(() => {
|
|
6381
7463
|
});
|
|
6382
|
-
const reselectNavigationItemRef =
|
|
7464
|
+
const reselectNavigationItemRef = useRef4(() => {
|
|
6383
7465
|
});
|
|
6384
|
-
const commitNavigationTextEditRef =
|
|
7466
|
+
const commitNavigationTextEditRef = useRef4(() => {
|
|
6385
7467
|
});
|
|
6386
|
-
const refreshActiveCommandsRef =
|
|
7468
|
+
const refreshActiveCommandsRef = useRef4(() => {
|
|
6387
7469
|
});
|
|
6388
|
-
const postToParentRef =
|
|
6389
|
-
postToParentRef.current =
|
|
6390
|
-
const sectionsLoadedRef =
|
|
6391
|
-
const pendingScheduleConfigRequests =
|
|
6392
|
-
const [toolbarRect, setToolbarRect] =
|
|
6393
|
-
const [toolbarVariant, setToolbarVariant] =
|
|
6394
|
-
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");
|
|
6395
7477
|
toolbarVariantRef.current = toolbarVariant;
|
|
6396
|
-
const [reorderHrefKey, setReorderHrefKey] =
|
|
6397
|
-
const [reorderDragDisabled, setReorderDragDisabled] =
|
|
6398
|
-
const [toggleState, setToggleState] =
|
|
6399
|
-
const [maxBadge, setMaxBadge] =
|
|
6400
|
-
const [activeCommands, setActiveCommands] =
|
|
6401
|
-
const [sectionGap, setSectionGap] =
|
|
6402
|
-
const [toolbarShowEditLink, setToolbarShowEditLink] =
|
|
6403
|
-
const
|
|
6404
|
-
const [
|
|
6405
|
-
const
|
|
6406
|
-
const [
|
|
6407
|
-
const
|
|
6408
|
-
const [
|
|
6409
|
-
const [
|
|
6410
|
-
const [
|
|
6411
|
-
const
|
|
6412
|
-
const
|
|
6413
|
-
const
|
|
6414
|
-
const
|
|
6415
|
-
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);
|
|
6416
7503
|
setLinkPopoverRef.current = setLinkPopover;
|
|
7504
|
+
linkPopoverSessionRef.current = linkPopover;
|
|
6417
7505
|
const bumpLinkPopoverGrace = () => {
|
|
6418
7506
|
linkPopoverGraceUntilRef.current = Date.now() + 350;
|
|
6419
7507
|
};
|
|
6420
|
-
const runSectionsPrefetch =
|
|
7508
|
+
const runSectionsPrefetch = useCallback4((pages) => {
|
|
6421
7509
|
if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
|
|
6422
7510
|
const gen = ++sectionsPrefetchGenRef.current;
|
|
6423
7511
|
const paths = pages.map((p) => p.path);
|
|
@@ -6436,9 +7524,9 @@ function OhhwellsBridge() {
|
|
|
6436
7524
|
);
|
|
6437
7525
|
});
|
|
6438
7526
|
}, [isEditMode, pathname]);
|
|
6439
|
-
const runSectionsPrefetchRef =
|
|
7527
|
+
const runSectionsPrefetchRef = useRef4(runSectionsPrefetch);
|
|
6440
7528
|
runSectionsPrefetchRef.current = runSectionsPrefetch;
|
|
6441
|
-
|
|
7529
|
+
useEffect7(() => {
|
|
6442
7530
|
if (!linkPopover) return;
|
|
6443
7531
|
if (hoveredImageRef.current) {
|
|
6444
7532
|
hoveredImageRef.current = null;
|
|
@@ -6446,33 +7534,9 @@ function OhhwellsBridge() {
|
|
|
6446
7534
|
}
|
|
6447
7535
|
hoveredGapRef.current = null;
|
|
6448
7536
|
setSectionGap(null);
|
|
6449
|
-
|
|
6450
|
-
|
|
6451
|
-
|
|
6452
|
-
const body = document.body;
|
|
6453
|
-
const prevHtmlOverflow = html.style.overflow;
|
|
6454
|
-
const prevBodyOverflow = body.style.overflow;
|
|
6455
|
-
html.style.overflow = "hidden";
|
|
6456
|
-
body.style.overflow = "hidden";
|
|
6457
|
-
const preventBackgroundScroll = (e) => {
|
|
6458
|
-
const target = e.target;
|
|
6459
|
-
if (target instanceof Element && target.closest('[data-ohw-link-modal-root], [data-slot="dialog-overlay"]')) {
|
|
6460
|
-
return;
|
|
6461
|
-
}
|
|
6462
|
-
e.preventDefault();
|
|
6463
|
-
};
|
|
6464
|
-
const scrollOpts = { passive: false, capture: true };
|
|
6465
|
-
document.addEventListener("wheel", preventBackgroundScroll, scrollOpts);
|
|
6466
|
-
document.addEventListener("touchmove", preventBackgroundScroll, scrollOpts);
|
|
6467
|
-
return () => {
|
|
6468
|
-
postToParent({ type: "ow:link-modal-lock", locked: false });
|
|
6469
|
-
html.style.overflow = prevHtmlOverflow;
|
|
6470
|
-
body.style.overflow = prevBodyOverflow;
|
|
6471
|
-
document.removeEventListener("wheel", preventBackgroundScroll, scrollOpts);
|
|
6472
|
-
document.removeEventListener("touchmove", preventBackgroundScroll, scrollOpts);
|
|
6473
|
-
};
|
|
6474
|
-
}, [linkPopover, postToParent]);
|
|
6475
|
-
useEffect3(() => {
|
|
7537
|
+
postToParent2({ type: "ow:image-unhover" });
|
|
7538
|
+
}, [linkPopover, postToParent2]);
|
|
7539
|
+
useEffect7(() => {
|
|
6476
7540
|
if (!isEditMode) return;
|
|
6477
7541
|
const useFixtures = shouldUseDevFixtures();
|
|
6478
7542
|
if (useFixtures) {
|
|
@@ -6493,17 +7557,17 @@ function OhhwellsBridge() {
|
|
|
6493
7557
|
runSectionsPrefetchRef.current(mapped);
|
|
6494
7558
|
};
|
|
6495
7559
|
window.addEventListener("message", onSitePages);
|
|
6496
|
-
if (!useFixtures)
|
|
7560
|
+
if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
|
|
6497
7561
|
return () => window.removeEventListener("message", onSitePages);
|
|
6498
|
-
}, [isEditMode,
|
|
6499
|
-
|
|
7562
|
+
}, [isEditMode, postToParent2]);
|
|
7563
|
+
useEffect7(() => {
|
|
6500
7564
|
if (!isEditMode || shouldUseDevFixtures()) return;
|
|
6501
7565
|
void loadAllSectionsManifest().then((manifest) => {
|
|
6502
7566
|
if (Object.keys(manifest).length === 0) return;
|
|
6503
7567
|
setSectionsByPath((prev) => ({ ...manifest, ...prev }));
|
|
6504
7568
|
});
|
|
6505
7569
|
}, [isEditMode]);
|
|
6506
|
-
|
|
7570
|
+
useEffect7(() => {
|
|
6507
7571
|
const update = () => {
|
|
6508
7572
|
const el = activeElRef.current ?? selectedElRef.current;
|
|
6509
7573
|
if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
@@ -6527,10 +7591,10 @@ function OhhwellsBridge() {
|
|
|
6527
7591
|
vvp.removeEventListener("resize", update);
|
|
6528
7592
|
};
|
|
6529
7593
|
}, []);
|
|
6530
|
-
const refreshStateRules =
|
|
7594
|
+
const refreshStateRules = useCallback4(() => {
|
|
6531
7595
|
editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
|
|
6532
7596
|
}, []);
|
|
6533
|
-
const processConfigRequest =
|
|
7597
|
+
const processConfigRequest = useCallback4((insertAfterVal) => {
|
|
6534
7598
|
const tracker = getSectionsTracker();
|
|
6535
7599
|
let entries = [];
|
|
6536
7600
|
try {
|
|
@@ -6553,7 +7617,7 @@ function OhhwellsBridge() {
|
|
|
6553
7617
|
}
|
|
6554
7618
|
window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
|
|
6555
7619
|
}, [isEditMode]);
|
|
6556
|
-
const deactivate =
|
|
7620
|
+
const deactivate = useCallback4(() => {
|
|
6557
7621
|
const el = activeElRef.current;
|
|
6558
7622
|
if (!el) return;
|
|
6559
7623
|
const key = el.dataset.ohwKey;
|
|
@@ -6582,21 +7646,23 @@ function OhhwellsBridge() {
|
|
|
6582
7646
|
setMaxBadge(null);
|
|
6583
7647
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
6584
7648
|
setToolbarShowEditLink(false);
|
|
6585
|
-
|
|
6586
|
-
}, [
|
|
6587
|
-
const deselect =
|
|
7649
|
+
postToParent2({ type: "ow:exit-edit" });
|
|
7650
|
+
}, [postToParent2]);
|
|
7651
|
+
const deselect = useCallback4(() => {
|
|
6588
7652
|
selectedElRef.current = null;
|
|
6589
7653
|
setReorderHrefKey(null);
|
|
6590
7654
|
setReorderDragDisabled(false);
|
|
6591
7655
|
siblingHintElRef.current = null;
|
|
6592
7656
|
setSiblingHintRect(null);
|
|
6593
7657
|
setIsItemDragging(false);
|
|
7658
|
+
hoveredNavContainerRef.current = null;
|
|
7659
|
+
setHoveredNavContainerRect(null);
|
|
6594
7660
|
if (!activeElRef.current) {
|
|
6595
7661
|
setToolbarRect(null);
|
|
6596
7662
|
setToolbarVariant("none");
|
|
6597
7663
|
}
|
|
6598
7664
|
}, []);
|
|
6599
|
-
const reselectNavigationItem =
|
|
7665
|
+
const reselectNavigationItem = useCallback4((navAnchor) => {
|
|
6600
7666
|
selectedElRef.current = navAnchor;
|
|
6601
7667
|
const { key, disabled } = getNavigationItemReorderState(navAnchor);
|
|
6602
7668
|
setReorderHrefKey(key);
|
|
@@ -6606,7 +7672,7 @@ function OhhwellsBridge() {
|
|
|
6606
7672
|
setToolbarShowEditLink(false);
|
|
6607
7673
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
6608
7674
|
}, []);
|
|
6609
|
-
const commitNavigationTextEdit =
|
|
7675
|
+
const commitNavigationTextEdit = useCallback4((navAnchor) => {
|
|
6610
7676
|
const el = activeElRef.current;
|
|
6611
7677
|
if (!el) return;
|
|
6612
7678
|
const key = el.dataset.ohwKey;
|
|
@@ -6619,9 +7685,9 @@ function OhhwellsBridge() {
|
|
|
6619
7685
|
const html = sanitizeHtml(el.innerHTML);
|
|
6620
7686
|
const original = originalContentRef.current ?? "";
|
|
6621
7687
|
if (html !== sanitizeHtml(original)) {
|
|
6622
|
-
|
|
7688
|
+
postToParent2({ type: "ow:change", nodes: [{ key, text: html }] });
|
|
6623
7689
|
const h = document.documentElement.scrollHeight;
|
|
6624
|
-
if (h > 50)
|
|
7690
|
+
if (h > 50) postToParent2({ type: "ow:height", height: h });
|
|
6625
7691
|
}
|
|
6626
7692
|
}
|
|
6627
7693
|
el.removeAttribute("contenteditable");
|
|
@@ -6629,31 +7695,38 @@ function OhhwellsBridge() {
|
|
|
6629
7695
|
setMaxBadge(null);
|
|
6630
7696
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
6631
7697
|
setToolbarShowEditLink(false);
|
|
6632
|
-
|
|
7698
|
+
postToParent2({ type: "ow:exit-edit" });
|
|
6633
7699
|
reselectNavigationItem(navAnchor);
|
|
6634
|
-
}, [
|
|
6635
|
-
const
|
|
6636
|
-
const
|
|
6637
|
-
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
|
|
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
|
+
});
|
|
6641
7712
|
}, []);
|
|
6642
|
-
const handleItemDragStart =
|
|
7713
|
+
const handleItemDragStart = useCallback4(() => {
|
|
6643
7714
|
siblingHintElRef.current = null;
|
|
6644
7715
|
setSiblingHintRect(null);
|
|
6645
7716
|
setIsItemDragging(true);
|
|
6646
7717
|
}, []);
|
|
6647
|
-
const handleItemDragEnd =
|
|
7718
|
+
const handleItemDragEnd = useCallback4(() => {
|
|
6648
7719
|
setIsItemDragging(false);
|
|
6649
7720
|
}, []);
|
|
6650
7721
|
reselectNavigationItemRef.current = reselectNavigationItem;
|
|
6651
7722
|
commitNavigationTextEditRef.current = commitNavigationTextEdit;
|
|
6652
|
-
const select =
|
|
7723
|
+
const select = useCallback4((anchor) => {
|
|
6653
7724
|
if (!isNavigationItem(anchor)) return;
|
|
6654
7725
|
if (activeElRef.current) deactivate();
|
|
6655
7726
|
selectedElRef.current = anchor;
|
|
6656
7727
|
clearHrefKeyHover(anchor);
|
|
7728
|
+
hoveredNavContainerRef.current = null;
|
|
7729
|
+
setHoveredNavContainerRect(null);
|
|
6657
7730
|
setHoveredItemRect(null);
|
|
6658
7731
|
hoveredItemElRef.current = null;
|
|
6659
7732
|
siblingHintElRef.current = null;
|
|
@@ -6667,13 +7740,32 @@ function OhhwellsBridge() {
|
|
|
6667
7740
|
setToolbarShowEditLink(false);
|
|
6668
7741
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
6669
7742
|
}, [deactivate]);
|
|
6670
|
-
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) => {
|
|
6671
7763
|
if (activeElRef.current === el) return;
|
|
6672
7764
|
selectedElRef.current = null;
|
|
6673
7765
|
deactivate();
|
|
6674
7766
|
if (hoveredImageRef.current) {
|
|
6675
7767
|
hoveredImageRef.current = null;
|
|
6676
|
-
|
|
7768
|
+
setMediaHover(null);
|
|
6677
7769
|
}
|
|
6678
7770
|
setToolbarVariant("rich-text");
|
|
6679
7771
|
siblingHintElRef.current = null;
|
|
@@ -6685,6 +7777,9 @@ function OhhwellsBridge() {
|
|
|
6685
7777
|
activeElRef.current = el;
|
|
6686
7778
|
originalContentRef.current = el.innerHTML;
|
|
6687
7779
|
el.focus();
|
|
7780
|
+
if (options?.caretX !== void 0 && options?.caretY !== void 0) {
|
|
7781
|
+
placeCaretAtPoint(el, options.caretX, options.caretY);
|
|
7782
|
+
}
|
|
6688
7783
|
setToolbarShowEditLink(Boolean(getHrefKeyFromElement(el)));
|
|
6689
7784
|
const navAnchor = getNavigationItemAnchor(el);
|
|
6690
7785
|
if (navAnchor) {
|
|
@@ -6696,12 +7791,13 @@ function OhhwellsBridge() {
|
|
|
6696
7791
|
setReorderDragDisabled(reorderDisabled);
|
|
6697
7792
|
}
|
|
6698
7793
|
setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
6699
|
-
|
|
7794
|
+
postToParent2({ type: "ow:enter-edit", key: el.dataset.ohwKey });
|
|
6700
7795
|
requestAnimationFrame(() => refreshActiveCommandsRef.current());
|
|
6701
|
-
}, [deactivate,
|
|
7796
|
+
}, [deactivate, postToParent2]);
|
|
6702
7797
|
activateRef.current = activate;
|
|
6703
7798
|
deactivateRef.current = deactivate;
|
|
6704
7799
|
selectRef.current = select;
|
|
7800
|
+
selectFrameRef.current = selectFrame;
|
|
6705
7801
|
deselectRef.current = deselect;
|
|
6706
7802
|
useLayoutEffect2(() => {
|
|
6707
7803
|
if (!subdomain || isEditMode) {
|
|
@@ -6712,6 +7808,7 @@ function OhhwellsBridge() {
|
|
|
6712
7808
|
const imageLoads = [];
|
|
6713
7809
|
for (const [key, val] of Object.entries(content)) {
|
|
6714
7810
|
if (key === "__ohw_sections") continue;
|
|
7811
|
+
if (applyVideoSettingNode(key, val)) continue;
|
|
6715
7812
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
6716
7813
|
if (el.dataset.ohwEditable === "image") {
|
|
6717
7814
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
@@ -6725,6 +7822,15 @@ function OhhwellsBridge() {
|
|
|
6725
7822
|
} else if (el.dataset.ohwEditable === "bg-image") {
|
|
6726
7823
|
const next = `url('${val}')`;
|
|
6727
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
|
+
}
|
|
6728
7834
|
} else if (el.dataset.ohwEditable === "link") {
|
|
6729
7835
|
applyLinkHref(el, val);
|
|
6730
7836
|
} else if (el.innerHTML !== val) {
|
|
@@ -6733,6 +7839,7 @@ function OhhwellsBridge() {
|
|
|
6733
7839
|
});
|
|
6734
7840
|
applyLinkByKey(key, val);
|
|
6735
7841
|
}
|
|
7842
|
+
reconcileNavbarItemsFromContent(content);
|
|
6736
7843
|
enforceLinkHrefs();
|
|
6737
7844
|
initSectionsFromContent(content, true);
|
|
6738
7845
|
sectionsLoadedRef.current = true;
|
|
@@ -6761,7 +7868,7 @@ function OhhwellsBridge() {
|
|
|
6761
7868
|
cancelled = true;
|
|
6762
7869
|
};
|
|
6763
7870
|
}, [subdomain, isEditMode]);
|
|
6764
|
-
|
|
7871
|
+
useEffect7(() => {
|
|
6765
7872
|
if (!subdomain || isEditMode) return;
|
|
6766
7873
|
let debounceTimer = null;
|
|
6767
7874
|
let observer = null;
|
|
@@ -6773,6 +7880,7 @@ function OhhwellsBridge() {
|
|
|
6773
7880
|
try {
|
|
6774
7881
|
for (const [key, val] of Object.entries(content)) {
|
|
6775
7882
|
if (key === "__ohw_sections") continue;
|
|
7883
|
+
if (applyVideoSettingNode(key, val)) continue;
|
|
6776
7884
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
6777
7885
|
if (el.dataset.ohwEditable === "image") {
|
|
6778
7886
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
@@ -6780,6 +7888,9 @@ function OhhwellsBridge() {
|
|
|
6780
7888
|
} else if (el.dataset.ohwEditable === "bg-image") {
|
|
6781
7889
|
const next = `url('${val}')`;
|
|
6782
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);
|
|
6783
7894
|
} else if (el.dataset.ohwEditable === "link") {
|
|
6784
7895
|
applyLinkHref(el, val);
|
|
6785
7896
|
} else if (el.innerHTML !== val) {
|
|
@@ -6788,6 +7899,7 @@ function OhhwellsBridge() {
|
|
|
6788
7899
|
});
|
|
6789
7900
|
applyLinkByKey(key, val);
|
|
6790
7901
|
}
|
|
7902
|
+
reconcileNavbarItemsFromContent(content);
|
|
6791
7903
|
} finally {
|
|
6792
7904
|
observer?.observe(document.body, { childList: true, subtree: true });
|
|
6793
7905
|
}
|
|
@@ -6811,20 +7923,38 @@ function OhhwellsBridge() {
|
|
|
6811
7923
|
const visible = Boolean(subdomain) && fetchState !== "done";
|
|
6812
7924
|
el.style.display = visible ? "flex" : "none";
|
|
6813
7925
|
}, [subdomain, fetchState]);
|
|
6814
|
-
|
|
6815
|
-
|
|
6816
|
-
}, [pathname,
|
|
6817
|
-
|
|
7926
|
+
useEffect7(() => {
|
|
7927
|
+
postToParent2({ type: "ow:navigation", path: pathname });
|
|
7928
|
+
}, [pathname, postToParent2]);
|
|
7929
|
+
useEffect7(() => {
|
|
6818
7930
|
if (!isEditMode) return;
|
|
7931
|
+
if (linkPopoverSessionRef.current?.intent === "add-nav") return;
|
|
7932
|
+
if (document.querySelector("[data-ohw-section-picker]")) return;
|
|
6819
7933
|
setLinkPopover(null);
|
|
6820
7934
|
deselectRef.current();
|
|
6821
7935
|
deactivateRef.current();
|
|
6822
7936
|
}, [pathname, isEditMode]);
|
|
6823
|
-
|
|
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(() => {
|
|
6824
7954
|
if (!isEditMode) return;
|
|
6825
7955
|
const measure = () => {
|
|
6826
7956
|
const h = document.body.scrollHeight;
|
|
6827
|
-
if (h > 50)
|
|
7957
|
+
if (h > 50) postToParent2({ type: "ow:height", height: h });
|
|
6828
7958
|
};
|
|
6829
7959
|
const t1 = setTimeout(measure, 50);
|
|
6830
7960
|
const t2 = setTimeout(measure, 500);
|
|
@@ -6843,8 +7973,8 @@ function OhhwellsBridge() {
|
|
|
6843
7973
|
if (resizeTimer) clearTimeout(resizeTimer);
|
|
6844
7974
|
window.removeEventListener("resize", handleResize);
|
|
6845
7975
|
};
|
|
6846
|
-
}, [pathname, isEditMode,
|
|
6847
|
-
|
|
7976
|
+
}, [pathname, isEditMode, postToParent2]);
|
|
7977
|
+
useEffect7(() => {
|
|
6848
7978
|
if (!subdomainFromQuery || isEditMode) return;
|
|
6849
7979
|
const handleClick = (e) => {
|
|
6850
7980
|
const anchor = e.target.closest("a");
|
|
@@ -6860,7 +7990,7 @@ function OhhwellsBridge() {
|
|
|
6860
7990
|
document.addEventListener("click", handleClick, true);
|
|
6861
7991
|
return () => document.removeEventListener("click", handleClick, true);
|
|
6862
7992
|
}, [subdomainFromQuery, isEditMode, router]);
|
|
6863
|
-
|
|
7993
|
+
useEffect7(() => {
|
|
6864
7994
|
if (!isEditMode) {
|
|
6865
7995
|
editStylesRef.current?.base.remove();
|
|
6866
7996
|
editStylesRef.current?.forceHover.remove();
|
|
@@ -6883,8 +8013,9 @@ function OhhwellsBridge() {
|
|
|
6883
8013
|
[data-ohw-editable] {
|
|
6884
8014
|
display: block;
|
|
6885
8015
|
}
|
|
6886
|
-
[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; }
|
|
6887
8017
|
[data-ohw-editable="image"], [data-ohw-editable="image"] *,
|
|
8018
|
+
[data-ohw-editable="video"], [data-ohw-editable="video"] *,
|
|
6888
8019
|
[data-ohw-editable="bg-image"], [data-ohw-editable="bg-image"] * { cursor: pointer !important; }
|
|
6889
8020
|
[data-ohw-editable="link"], [data-ohw-editable="link"] * { cursor: pointer !important; }
|
|
6890
8021
|
[data-ohw-hovered]:not([contenteditable]):not([data-ohw-href-key]) {
|
|
@@ -6933,6 +8064,13 @@ function OhhwellsBridge() {
|
|
|
6933
8064
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
6934
8065
|
if (isInsideLinkEditor(target)) return;
|
|
6935
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
|
+
}
|
|
6936
8074
|
e.preventDefault();
|
|
6937
8075
|
e.stopPropagation();
|
|
6938
8076
|
return;
|
|
@@ -6947,14 +8085,15 @@ function OhhwellsBridge() {
|
|
|
6947
8085
|
bumpLinkPopoverGrace();
|
|
6948
8086
|
setLinkPopoverRef.current({
|
|
6949
8087
|
key: editable.dataset.ohwKey ?? "",
|
|
6950
|
-
|
|
8088
|
+
mode: "edit",
|
|
8089
|
+
target: getLinkHref2(editable)
|
|
6951
8090
|
});
|
|
6952
8091
|
return;
|
|
6953
8092
|
}
|
|
6954
|
-
if (editable
|
|
8093
|
+
if (isMediaEditable(editable)) {
|
|
6955
8094
|
e.preventDefault();
|
|
6956
8095
|
e.stopPropagation();
|
|
6957
|
-
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" });
|
|
6958
8097
|
return;
|
|
6959
8098
|
}
|
|
6960
8099
|
const hrefCtx = getHrefKeyFromElement(editable);
|
|
@@ -6963,7 +8102,8 @@ function OhhwellsBridge() {
|
|
|
6963
8102
|
e.preventDefault();
|
|
6964
8103
|
e.stopPropagation();
|
|
6965
8104
|
if (selectedElRef.current === navAnchor) {
|
|
6966
|
-
|
|
8105
|
+
if (e.detail >= 2) return;
|
|
8106
|
+
activateRef.current(editable, { caretX: e.clientX, caretY: e.clientY });
|
|
6967
8107
|
return;
|
|
6968
8108
|
}
|
|
6969
8109
|
selectRef.current(navAnchor);
|
|
@@ -6982,6 +8122,22 @@ function OhhwellsBridge() {
|
|
|
6982
8122
|
selectRef.current(hrefAnchor);
|
|
6983
8123
|
return;
|
|
6984
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
|
+
}
|
|
6985
8141
|
if (activeElRef.current) {
|
|
6986
8142
|
const sel = window.getSelection();
|
|
6987
8143
|
if (sel && !sel.isCollapsed) {
|
|
@@ -7007,10 +8163,48 @@ function OhhwellsBridge() {
|
|
|
7007
8163
|
deselectRef.current();
|
|
7008
8164
|
deactivateRef.current();
|
|
7009
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
|
+
};
|
|
7010
8188
|
const handleMouseOver = (e) => {
|
|
7011
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
|
+
}
|
|
7012
8204
|
const navAnchor = getNavigationItemAnchor(target);
|
|
7013
8205
|
if (navAnchor) {
|
|
8206
|
+
hoveredNavContainerRef.current = null;
|
|
8207
|
+
setHoveredNavContainerRect(null);
|
|
7014
8208
|
const selected2 = selectedElRef.current;
|
|
7015
8209
|
if (selected2 === navAnchor || selected2?.contains(navAnchor)) return;
|
|
7016
8210
|
clearHrefKeyHover(navAnchor);
|
|
@@ -7022,7 +8216,7 @@ function OhhwellsBridge() {
|
|
|
7022
8216
|
if (!editable) return;
|
|
7023
8217
|
const selected = selectedElRef.current;
|
|
7024
8218
|
if (selected && (selected === editable || selected.contains(editable))) return;
|
|
7025
|
-
if (editable
|
|
8219
|
+
if (!isMediaEditable(editable) && !editable.hasAttribute("contenteditable")) {
|
|
7026
8220
|
const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
|
|
7027
8221
|
if (hoverTarget.hasAttribute("data-ohw-href-key")) {
|
|
7028
8222
|
clearHrefKeyHover(hoverTarget);
|
|
@@ -7035,6 +8229,14 @@ function OhhwellsBridge() {
|
|
|
7035
8229
|
};
|
|
7036
8230
|
const handleMouseOut = (e) => {
|
|
7037
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
|
+
}
|
|
7038
8240
|
const navAnchor = getNavigationItemAnchor(target);
|
|
7039
8241
|
if (navAnchor) {
|
|
7040
8242
|
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
@@ -7050,7 +8252,7 @@ function OhhwellsBridge() {
|
|
|
7050
8252
|
if (!editable) return;
|
|
7051
8253
|
const related = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
7052
8254
|
if (related?.closest("[data-ohw-drag-handle-container], [data-ohw-item-interaction]")) return;
|
|
7053
|
-
if (editable
|
|
8255
|
+
if (!isMediaEditable(editable)) {
|
|
7054
8256
|
const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
|
|
7055
8257
|
if (hoverTarget.hasAttribute("data-ohw-href-key")) {
|
|
7056
8258
|
if (!related?.closest("[data-ohw-href-key]")) {
|
|
@@ -7096,23 +8298,26 @@ function OhhwellsBridge() {
|
|
|
7096
8298
|
}
|
|
7097
8299
|
return { top, left, width: Math.max(0, right - left), height: Math.max(0, bottom - top) };
|
|
7098
8300
|
};
|
|
7099
|
-
const
|
|
8301
|
+
const showImageHover = (imgEl, isDragOver = false, forceTextOverlap) => {
|
|
7100
8302
|
const r2 = getVisibleRect(imgEl);
|
|
7101
8303
|
const hasTextOverlap = forceTextOverlap ?? false;
|
|
7102
8304
|
hoveredImageHasTextOverlapRef.current = hasTextOverlap;
|
|
7103
|
-
|
|
7104
|
-
|
|
8305
|
+
const video = imgEl.dataset.ohwEditable === "video" ? getVideoEl(imgEl) : null;
|
|
8306
|
+
setMediaHover({
|
|
7105
8307
|
key: imgEl.dataset.ohwKey ?? "",
|
|
7106
8308
|
rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height },
|
|
8309
|
+
elementType: imgEl.dataset.ohwEditable ?? "image",
|
|
7107
8310
|
hasTextOverlap,
|
|
7108
|
-
|
|
8311
|
+
isDragOver,
|
|
8312
|
+
...video ? { videoAutoplay: video.autoplay, videoMuted: video.muted } : {}
|
|
7109
8313
|
});
|
|
7110
8314
|
const track = imgEl.closest("[data-ohw-hover-pause]");
|
|
7111
8315
|
if (track) track.setAttribute("data-ohw-hover-paused", "");
|
|
7112
8316
|
};
|
|
8317
|
+
const clearImageHover = () => setMediaHover(null);
|
|
7113
8318
|
const findImageAtPoint = (clientX, clientY, fromParentViewport) => {
|
|
7114
8319
|
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
7115
|
-
const images = Array.from(document.querySelectorAll(
|
|
8320
|
+
const images = Array.from(document.querySelectorAll(MEDIA_SELECTOR));
|
|
7116
8321
|
const matches = [];
|
|
7117
8322
|
for (let i = images.length - 1; i >= 0; i--) {
|
|
7118
8323
|
const el = images[i];
|
|
@@ -7128,7 +8333,9 @@ function OhhwellsBridge() {
|
|
|
7128
8333
|
if (x >= r2.left && x <= r2.left + r2.width && y >= r2.top && y <= r2.top + r2.height) matches.push(el);
|
|
7129
8334
|
}
|
|
7130
8335
|
if (matches.length === 0) return null;
|
|
7131
|
-
const imageTypeMatches = matches.filter(
|
|
8336
|
+
const imageTypeMatches = matches.filter(
|
|
8337
|
+
(el) => el.dataset.ohwEditable === "image" || el.dataset.ohwEditable === "video"
|
|
8338
|
+
);
|
|
7132
8339
|
const candidatePool = imageTypeMatches.length > 0 ? imageTypeMatches : matches;
|
|
7133
8340
|
const smallest = candidatePool.reduce((best, el) => {
|
|
7134
8341
|
const br = getVisibleRect(best);
|
|
@@ -7151,47 +8358,91 @@ function OhhwellsBridge() {
|
|
|
7151
8358
|
}
|
|
7152
8359
|
return smallest;
|
|
7153
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
|
+
};
|
|
7154
8412
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
7155
8413
|
if (linkPopoverOpenRef.current) {
|
|
7156
|
-
|
|
7157
|
-
|
|
7158
|
-
|
|
7159
|
-
|
|
7160
|
-
|
|
7161
|
-
|
|
8414
|
+
dismissImageHover();
|
|
8415
|
+
return;
|
|
8416
|
+
}
|
|
8417
|
+
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
8418
|
+
if (isPointOverNavigation(x, y)) {
|
|
8419
|
+
dismissImageHover();
|
|
8420
|
+
probeNavigationHoverAt(x, y);
|
|
7162
8421
|
return;
|
|
7163
8422
|
}
|
|
8423
|
+
hoveredNavContainerRef.current = null;
|
|
8424
|
+
setHoveredNavContainerRect(null);
|
|
7164
8425
|
const toggleEl = document.querySelector("[data-ohw-state-toggle]");
|
|
7165
8426
|
if (toggleEl) {
|
|
7166
|
-
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
7167
8427
|
const tr = toggleEl.getBoundingClientRect();
|
|
7168
8428
|
if (x >= tr.left && x <= tr.right && y >= tr.top && y <= tr.bottom) {
|
|
7169
|
-
|
|
7170
|
-
hoveredImageRef.current = null;
|
|
7171
|
-
resumeAnimTracks();
|
|
7172
|
-
postToParentRef.current({ type: "ow:image-unhover" });
|
|
7173
|
-
}
|
|
8429
|
+
dismissImageHover();
|
|
7174
8430
|
return;
|
|
7175
8431
|
}
|
|
7176
8432
|
}
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
|
|
7180
|
-
|
|
7181
|
-
resumeAnimTracks();
|
|
7182
|
-
postToParentRef.current({ type: "ow:image-unhover" });
|
|
7183
|
-
}
|
|
8433
|
+
const imgEl = findImageAtPoint(clientX, clientY, fromParentViewport);
|
|
8434
|
+
const activeEl = activeElRef.current;
|
|
8435
|
+
if (activeEl && (!imgEl || imgEl.contains(activeEl))) {
|
|
8436
|
+
dismissImageHover();
|
|
7184
8437
|
return;
|
|
7185
8438
|
}
|
|
7186
|
-
const imgEl = findImageAtPoint(clientX, clientY, fromParentViewport);
|
|
7187
8439
|
if (imgEl) {
|
|
7188
|
-
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
7189
8440
|
const topEl = document.elementFromPoint(x, y);
|
|
7190
8441
|
if (topEl?.closest('[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
7191
8442
|
if (hoveredImageRef.current) {
|
|
7192
8443
|
hoveredImageRef.current = null;
|
|
7193
8444
|
resumeAnimTracks();
|
|
7194
|
-
|
|
8445
|
+
clearImageHover();
|
|
7195
8446
|
}
|
|
7196
8447
|
return;
|
|
7197
8448
|
}
|
|
@@ -7200,13 +8451,13 @@ function OhhwellsBridge() {
|
|
|
7200
8451
|
hoveredImageRef.current = null;
|
|
7201
8452
|
hoveredImageHasTextOverlapRef.current = false;
|
|
7202
8453
|
resumeAnimTracks();
|
|
7203
|
-
|
|
8454
|
+
clearImageHover();
|
|
7204
8455
|
}
|
|
7205
8456
|
return;
|
|
7206
8457
|
}
|
|
7207
8458
|
const isStateCardImage = !!imgEl.closest("[data-ohw-editable-state]");
|
|
7208
8459
|
const textEditable = Array.from(
|
|
7209
|
-
document.querySelectorAll(
|
|
8460
|
+
document.querySelectorAll(NON_MEDIA_SELECTOR)
|
|
7210
8461
|
).find((el) => {
|
|
7211
8462
|
const er = el.getBoundingClientRect();
|
|
7212
8463
|
return x >= er.left && x <= er.right && y >= er.top && y <= er.bottom;
|
|
@@ -7225,14 +8476,14 @@ function OhhwellsBridge() {
|
|
|
7225
8476
|
hoveredImageRef.current = null;
|
|
7226
8477
|
hoveredImageHasTextOverlapRef.current = false;
|
|
7227
8478
|
resumeAnimTracks();
|
|
7228
|
-
|
|
8479
|
+
clearImageHover();
|
|
7229
8480
|
}
|
|
7230
8481
|
return;
|
|
7231
8482
|
}
|
|
7232
8483
|
if (isStateCardImage) {
|
|
7233
8484
|
if (imgEl !== hoveredImageRef.current || !hoveredImageHasTextOverlapRef.current) {
|
|
7234
8485
|
hoveredImageRef.current = imgEl;
|
|
7235
|
-
|
|
8486
|
+
showImageHover(imgEl, isDragOver, true);
|
|
7236
8487
|
}
|
|
7237
8488
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
7238
8489
|
if (textEditable && !isInsideNavigationItem(textEditable)) {
|
|
@@ -7244,7 +8495,7 @@ function OhhwellsBridge() {
|
|
|
7244
8495
|
hoveredImageRef.current = null;
|
|
7245
8496
|
hoveredImageHasTextOverlapRef.current = false;
|
|
7246
8497
|
resumeAnimTracks();
|
|
7247
|
-
|
|
8498
|
+
clearImageHover();
|
|
7248
8499
|
}
|
|
7249
8500
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
7250
8501
|
if (textEditable && !isInsideNavigationItem(textEditable)) {
|
|
@@ -7256,7 +8507,7 @@ function OhhwellsBridge() {
|
|
|
7256
8507
|
if (hoveredImageRef.current) {
|
|
7257
8508
|
hoveredImageRef.current = null;
|
|
7258
8509
|
resumeAnimTracks();
|
|
7259
|
-
|
|
8510
|
+
clearImageHover();
|
|
7260
8511
|
}
|
|
7261
8512
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
7262
8513
|
return;
|
|
@@ -7264,9 +8515,9 @@ function OhhwellsBridge() {
|
|
|
7264
8515
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
7265
8516
|
if (imgEl !== hoveredImageRef.current || hoveredImageHasTextOverlapRef.current) {
|
|
7266
8517
|
hoveredImageRef.current = imgEl;
|
|
7267
|
-
|
|
8518
|
+
showImageHover(imgEl, isDragOver);
|
|
7268
8519
|
} else if (isDragOver) {
|
|
7269
|
-
|
|
8520
|
+
showImageHover(imgEl, true);
|
|
7270
8521
|
}
|
|
7271
8522
|
} else {
|
|
7272
8523
|
const inIframeView = clientX >= 0 && clientY >= 0 && clientX <= window.innerWidth && clientY <= window.innerHeight;
|
|
@@ -7283,14 +8534,14 @@ function OhhwellsBridge() {
|
|
|
7283
8534
|
hoveredImageRef.current = null;
|
|
7284
8535
|
hoveredImageHasTextOverlapRef.current = false;
|
|
7285
8536
|
resumeAnimTracks();
|
|
7286
|
-
|
|
8537
|
+
clearImageHover();
|
|
7287
8538
|
}
|
|
7288
|
-
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
8539
|
+
const { x: x2, y: y2 } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
7289
8540
|
const textEl = Array.from(
|
|
7290
|
-
document.querySelectorAll(
|
|
8541
|
+
document.querySelectorAll(NON_MEDIA_SELECTOR)
|
|
7291
8542
|
).find((el) => {
|
|
7292
8543
|
const er = el.getBoundingClientRect();
|
|
7293
|
-
return
|
|
8544
|
+
return x2 >= er.left && x2 <= er.right && y2 >= er.top && y2 <= er.bottom;
|
|
7294
8545
|
});
|
|
7295
8546
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
7296
8547
|
if (textEl && !textEl.hasAttribute("contenteditable")) {
|
|
@@ -7393,18 +8644,20 @@ function OhhwellsBridge() {
|
|
|
7393
8644
|
return;
|
|
7394
8645
|
}
|
|
7395
8646
|
e.dataTransfer.dropEffect = "copy";
|
|
7396
|
-
if (
|
|
8647
|
+
if (dragOverElRef.current !== el) {
|
|
8648
|
+
dragOverElRef.current = el;
|
|
7397
8649
|
hoveredImageRef.current = el;
|
|
7398
8650
|
const isStateCard = !!el.closest("[data-ohw-editable-state]");
|
|
7399
|
-
|
|
8651
|
+
showImageHover(el, true, isStateCard ? true : void 0);
|
|
7400
8652
|
}
|
|
7401
8653
|
};
|
|
7402
8654
|
const handleDragLeave = (e) => {
|
|
7403
8655
|
const imgEl = findImageAtPoint(e.clientX, e.clientY, false);
|
|
7404
8656
|
if (imgEl) return;
|
|
8657
|
+
dragOverElRef.current = null;
|
|
7405
8658
|
hoveredImageRef.current = null;
|
|
7406
8659
|
resumeAnimTracks();
|
|
7407
|
-
|
|
8660
|
+
clearImageHover();
|
|
7408
8661
|
};
|
|
7409
8662
|
const handleDrop = (e) => {
|
|
7410
8663
|
e.preventDefault();
|
|
@@ -7412,7 +8665,9 @@ function OhhwellsBridge() {
|
|
|
7412
8665
|
if (!el) return;
|
|
7413
8666
|
const file = e.dataTransfer?.files?.[0];
|
|
7414
8667
|
if (file) {
|
|
7415
|
-
|
|
8668
|
+
const wantsVideo = el.dataset.ohwEditable === "video";
|
|
8669
|
+
const accepted = wantsVideo ? file.type.startsWith("video/") : file.type.startsWith("image/");
|
|
8670
|
+
if (accepted) {
|
|
7416
8671
|
const key = el.dataset.ohwKey ?? "";
|
|
7417
8672
|
const { name, type: mimeType } = file;
|
|
7418
8673
|
const r2 = el.getBoundingClientRect();
|
|
@@ -7421,12 +8676,13 @@ function OhhwellsBridge() {
|
|
|
7421
8676
|
window.parent.postMessage({ type: "ow:image-drop", key, name, mimeType, buf, rect }, "*", [buf]);
|
|
7422
8677
|
});
|
|
7423
8678
|
} else {
|
|
7424
|
-
postToParentRef.current({ type: "ow:image-drop-invalid" });
|
|
8679
|
+
postToParentRef.current({ type: "ow:image-drop-invalid", expected: wantsVideo ? "video" : "image" });
|
|
7425
8680
|
}
|
|
7426
8681
|
}
|
|
8682
|
+
dragOverElRef.current = null;
|
|
7427
8683
|
hoveredImageRef.current = null;
|
|
7428
8684
|
resumeAnimTracks();
|
|
7429
|
-
|
|
8685
|
+
clearImageHover();
|
|
7430
8686
|
};
|
|
7431
8687
|
const handleImageUrl = (e) => {
|
|
7432
8688
|
if (e.data?.type !== "ow:image-url") return;
|
|
@@ -7444,7 +8700,11 @@ function OhhwellsBridge() {
|
|
|
7444
8700
|
}
|
|
7445
8701
|
});
|
|
7446
8702
|
hoveredImageRef.current = null;
|
|
7447
|
-
|
|
8703
|
+
setUploadingRects((prev) => {
|
|
8704
|
+
const entry = prev[key];
|
|
8705
|
+
if (!entry || entry.fadingOut) return prev;
|
|
8706
|
+
return { ...prev, [key]: { ...entry, fadingOut: true } };
|
|
8707
|
+
});
|
|
7448
8708
|
};
|
|
7449
8709
|
let found = false;
|
|
7450
8710
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -7479,6 +8739,19 @@ function OhhwellsBridge() {
|
|
|
7479
8739
|
requestAnimationFrame(() => onReady());
|
|
7480
8740
|
}
|
|
7481
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
|
+
}
|
|
7482
8755
|
}
|
|
7483
8756
|
});
|
|
7484
8757
|
if (!found) notify();
|
|
@@ -7545,12 +8818,16 @@ function OhhwellsBridge() {
|
|
|
7545
8818
|
sectionsJson = val;
|
|
7546
8819
|
continue;
|
|
7547
8820
|
}
|
|
8821
|
+
if (applyVideoSettingNode(key, val)) continue;
|
|
7548
8822
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
7549
8823
|
if (el.dataset.ohwEditable === "image") {
|
|
7550
8824
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
7551
8825
|
if (img) applyEditableImageSrc(img, val);
|
|
7552
8826
|
} else if (el.dataset.ohwEditable === "bg-image") {
|
|
7553
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);
|
|
7554
8831
|
} else if (el.dataset.ohwEditable === "link") {
|
|
7555
8832
|
applyLinkHref(el, val);
|
|
7556
8833
|
} else {
|
|
@@ -7564,6 +8841,8 @@ function OhhwellsBridge() {
|
|
|
7564
8841
|
sectionsLoadedRef.current = true;
|
|
7565
8842
|
pendingScheduleConfigRequests.current.splice(0).forEach(processConfigRequest);
|
|
7566
8843
|
}
|
|
8844
|
+
editContentRef.current = { ...editContentRef.current, ...content };
|
|
8845
|
+
reconcileNavbarItemsFromContent(editContentRef.current);
|
|
7567
8846
|
enforceLinkHrefs();
|
|
7568
8847
|
postToParentRef.current({ type: "ow:hydrate-done" });
|
|
7569
8848
|
};
|
|
@@ -7571,6 +8850,7 @@ function OhhwellsBridge() {
|
|
|
7571
8850
|
const handleDeactivate = (e) => {
|
|
7572
8851
|
if (e.data?.type !== "ow:deactivate") return;
|
|
7573
8852
|
if (Date.now() < linkPopoverGraceUntilRef.current) return;
|
|
8853
|
+
if (document.querySelector("[data-ohw-section-picker]")) return;
|
|
7574
8854
|
if (linkPopoverOpenRef.current) {
|
|
7575
8855
|
setLinkPopoverRef.current(null);
|
|
7576
8856
|
return;
|
|
@@ -7580,12 +8860,32 @@ function OhhwellsBridge() {
|
|
|
7580
8860
|
};
|
|
7581
8861
|
window.addEventListener("message", handleDeactivate);
|
|
7582
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
|
+
}
|
|
7583
8873
|
if (e.key === "Escape" && linkPopoverOpenRef.current) {
|
|
7584
8874
|
setLinkPopoverRef.current(null);
|
|
7585
8875
|
return;
|
|
7586
8876
|
}
|
|
7587
8877
|
if (e.key === "Escape" && selectedElRef.current && !activeElRef.current) {
|
|
7588
|
-
|
|
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
|
+
}
|
|
7589
8889
|
return;
|
|
7590
8890
|
}
|
|
7591
8891
|
if (e.key === "Escape" && activeElRef.current) {
|
|
@@ -7643,18 +8943,18 @@ function OhhwellsBridge() {
|
|
|
7643
8943
|
if (hoveredItemElRef.current) {
|
|
7644
8944
|
setHoveredItemRect(hoveredItemElRef.current.getBoundingClientRect());
|
|
7645
8945
|
}
|
|
8946
|
+
if (hoveredNavContainerRef.current) {
|
|
8947
|
+
setHoveredNavContainerRect(hoveredNavContainerRef.current.getBoundingClientRect());
|
|
8948
|
+
}
|
|
7646
8949
|
if (siblingHintElRef.current) {
|
|
7647
8950
|
setSiblingHintRect(siblingHintElRef.current.getBoundingClientRect());
|
|
7648
8951
|
}
|
|
7649
8952
|
if (hoveredImageRef.current) {
|
|
7650
8953
|
const el = hoveredImageRef.current;
|
|
7651
8954
|
const r2 = el.getBoundingClientRect();
|
|
7652
|
-
|
|
7653
|
-
|
|
7654
|
-
|
|
7655
|
-
rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height },
|
|
7656
|
-
hasTextOverlap: hoveredImageHasTextOverlapRef.current
|
|
7657
|
-
});
|
|
8955
|
+
setMediaHover(
|
|
8956
|
+
(prev) => prev ? { ...prev, rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height } } : prev
|
|
8957
|
+
);
|
|
7658
8958
|
}
|
|
7659
8959
|
};
|
|
7660
8960
|
const handleSave = (e) => {
|
|
@@ -7743,19 +9043,39 @@ function OhhwellsBridge() {
|
|
|
7743
9043
|
refreshActiveCommandsRef.current = handleSelectionChange;
|
|
7744
9044
|
const handleDocMouseLeave = () => {
|
|
7745
9045
|
hoveredImageRef.current = null;
|
|
9046
|
+
setMediaHover(null);
|
|
7746
9047
|
document.querySelectorAll("[data-ohw-state-hovered]").forEach((el) => el.removeAttribute("data-ohw-state-hovered"));
|
|
7747
9048
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
7748
9049
|
activeStateElRef.current = null;
|
|
7749
9050
|
setToggleState(null);
|
|
7750
9051
|
};
|
|
7751
|
-
const
|
|
7752
|
-
if (e.data?.type !== "ow:
|
|
7753
|
-
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
|
+
});
|
|
7754
9070
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
7755
9071
|
const track = el.closest("[data-ohw-hover-pause]");
|
|
7756
|
-
if (track)
|
|
9072
|
+
if (!track) return;
|
|
9073
|
+
if (uploading) {
|
|
7757
9074
|
uploadLockedTracks.add(track);
|
|
7758
9075
|
track.setAttribute("data-ohw-hover-paused", "");
|
|
9076
|
+
} else {
|
|
9077
|
+
uploadLockedTracks.delete(track);
|
|
9078
|
+
track.removeAttribute("data-ohw-hover-paused");
|
|
7759
9079
|
}
|
|
7760
9080
|
});
|
|
7761
9081
|
};
|
|
@@ -7797,7 +9117,7 @@ function OhhwellsBridge() {
|
|
|
7797
9117
|
if (e.data?.type !== "ow:click-at") return;
|
|
7798
9118
|
const { clientX, clientY } = e.data;
|
|
7799
9119
|
const allImages = Array.from(
|
|
7800
|
-
document.querySelectorAll(
|
|
9120
|
+
document.querySelectorAll(MEDIA_SELECTOR)
|
|
7801
9121
|
).filter((el) => !!el.closest("[data-ohw-editable-state]"));
|
|
7802
9122
|
const stateCardImage = allImages.find((el) => {
|
|
7803
9123
|
const ownerCard = el.closest("[data-ohw-editable-state]");
|
|
@@ -7812,21 +9132,55 @@ function OhhwellsBridge() {
|
|
|
7812
9132
|
return clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
|
|
7813
9133
|
});
|
|
7814
9134
|
if (stateCardImage) {
|
|
7815
|
-
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" });
|
|
7816
9136
|
return;
|
|
7817
9137
|
}
|
|
7818
9138
|
const textEditable = Array.from(
|
|
7819
|
-
document.querySelectorAll(
|
|
7820
|
-
'[data-ohw-editable]:not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"])'
|
|
7821
|
-
)
|
|
9139
|
+
document.querySelectorAll(NON_MEDIA_SELECTOR)
|
|
7822
9140
|
).find((el) => {
|
|
7823
9141
|
const r2 = el.getBoundingClientRect();
|
|
7824
9142
|
return clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
|
|
7825
9143
|
});
|
|
7826
9144
|
if (textEditable) {
|
|
7827
|
-
|
|
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 });
|
|
7828
9156
|
return;
|
|
7829
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
|
+
}
|
|
7830
9184
|
deactivateRef.current();
|
|
7831
9185
|
};
|
|
7832
9186
|
window.addEventListener("message", handleSave);
|
|
@@ -7836,7 +9190,7 @@ function OhhwellsBridge() {
|
|
|
7836
9190
|
window.addEventListener("message", handleClearSchedulingWidget);
|
|
7837
9191
|
window.addEventListener("message", handleRemoveSchedulingSection);
|
|
7838
9192
|
window.addEventListener("message", handleImageUrl);
|
|
7839
|
-
window.addEventListener("message",
|
|
9193
|
+
window.addEventListener("message", handleImageUploading);
|
|
7840
9194
|
window.addEventListener("message", handleCanvasHeight);
|
|
7841
9195
|
window.addEventListener("message", handleParentScroll);
|
|
7842
9196
|
window.addEventListener("message", handlePointerSync);
|
|
@@ -7848,6 +9202,7 @@ function OhhwellsBridge() {
|
|
|
7848
9202
|
};
|
|
7849
9203
|
window.addEventListener("resize", handleViewportResize, { passive: true });
|
|
7850
9204
|
document.addEventListener("click", handleClick, true);
|
|
9205
|
+
document.addEventListener("dblclick", handleDblClick, true);
|
|
7851
9206
|
document.addEventListener("paste", handlePaste, true);
|
|
7852
9207
|
document.addEventListener("input", handleInput, true);
|
|
7853
9208
|
document.addEventListener("mouseover", handleMouseOver, true);
|
|
@@ -7862,6 +9217,7 @@ function OhhwellsBridge() {
|
|
|
7862
9217
|
window.addEventListener("scroll", handleScroll, true);
|
|
7863
9218
|
return () => {
|
|
7864
9219
|
document.removeEventListener("click", handleClick, true);
|
|
9220
|
+
document.removeEventListener("dblclick", handleDblClick, true);
|
|
7865
9221
|
document.removeEventListener("paste", handlePaste, true);
|
|
7866
9222
|
document.removeEventListener("input", handleInput, true);
|
|
7867
9223
|
document.removeEventListener("mouseover", handleMouseOver, true);
|
|
@@ -7881,7 +9237,7 @@ function OhhwellsBridge() {
|
|
|
7881
9237
|
window.removeEventListener("message", handleClearSchedulingWidget);
|
|
7882
9238
|
window.removeEventListener("message", handleRemoveSchedulingSection);
|
|
7883
9239
|
window.removeEventListener("message", handleImageUrl);
|
|
7884
|
-
window.removeEventListener("message",
|
|
9240
|
+
window.removeEventListener("message", handleImageUploading);
|
|
7885
9241
|
window.removeEventListener("message", handleCanvasHeight);
|
|
7886
9242
|
window.removeEventListener("message", handleParentScroll);
|
|
7887
9243
|
window.removeEventListener("resize", handleViewportResize);
|
|
@@ -7895,7 +9251,7 @@ function OhhwellsBridge() {
|
|
|
7895
9251
|
if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
|
|
7896
9252
|
};
|
|
7897
9253
|
}, [isEditMode, refreshStateRules]);
|
|
7898
|
-
|
|
9254
|
+
useEffect7(() => {
|
|
7899
9255
|
const handler = (e) => {
|
|
7900
9256
|
if (e.data?.type !== "ow:request-schedule-config") return;
|
|
7901
9257
|
const insertAfterVal = e.data.insertAfter;
|
|
@@ -7911,7 +9267,7 @@ function OhhwellsBridge() {
|
|
|
7911
9267
|
window.addEventListener("message", handler);
|
|
7912
9268
|
return () => window.removeEventListener("message", handler);
|
|
7913
9269
|
}, [processConfigRequest]);
|
|
7914
|
-
|
|
9270
|
+
useEffect7(() => {
|
|
7915
9271
|
if (!isEditMode) return;
|
|
7916
9272
|
document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
|
|
7917
9273
|
el.removeAttribute("data-ohw-active-state");
|
|
@@ -7932,27 +9288,27 @@ function OhhwellsBridge() {
|
|
|
7932
9288
|
const next = { ...prev, [pathKey]: sections };
|
|
7933
9289
|
return shouldUseDevFixtures() ? { ...DEV_SECTIONS_BY_PATH, ...next } : next;
|
|
7934
9290
|
});
|
|
7935
|
-
|
|
7936
|
-
|
|
9291
|
+
postToParent2({ type: "ow:ready", version: "1", path: pathname, nodes: collectEditableNodes(), sections });
|
|
9292
|
+
postToParent2({ type: "ow:request-site-pages" });
|
|
7937
9293
|
}, 150);
|
|
7938
9294
|
return () => {
|
|
7939
9295
|
cancelAnimationFrame(raf);
|
|
7940
9296
|
clearTimeout(timer);
|
|
7941
9297
|
};
|
|
7942
|
-
}, [pathname, isEditMode, refreshStateRules,
|
|
7943
|
-
|
|
9298
|
+
}, [pathname, isEditMode, refreshStateRules, postToParent2]);
|
|
9299
|
+
useEffect7(() => {
|
|
7944
9300
|
scrollToHashSectionWhenReady();
|
|
7945
9301
|
const onHashChange = () => scrollToHashSectionWhenReady();
|
|
7946
9302
|
window.addEventListener("hashchange", onHashChange);
|
|
7947
9303
|
return () => window.removeEventListener("hashchange", onHashChange);
|
|
7948
9304
|
}, [pathname]);
|
|
7949
|
-
const handleCommand =
|
|
9305
|
+
const handleCommand = useCallback4((cmd) => {
|
|
7950
9306
|
document.execCommand(cmd, false);
|
|
7951
9307
|
activeElRef.current?.focus();
|
|
7952
9308
|
if (activeElRef.current) setToolbarRect(getEditMeasureEl(activeElRef.current).getBoundingClientRect());
|
|
7953
9309
|
refreshActiveCommandsRef.current();
|
|
7954
9310
|
}, []);
|
|
7955
|
-
const handleStateChange =
|
|
9311
|
+
const handleStateChange = useCallback4((state) => {
|
|
7956
9312
|
if (!activeStateElRef.current) return;
|
|
7957
9313
|
const el = activeStateElRef.current;
|
|
7958
9314
|
if (state === "Default") {
|
|
@@ -7965,18 +9321,22 @@ function OhhwellsBridge() {
|
|
|
7965
9321
|
}
|
|
7966
9322
|
setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
|
|
7967
9323
|
}, [deactivate]);
|
|
7968
|
-
const closeLinkPopover =
|
|
7969
|
-
|
|
9324
|
+
const closeLinkPopover = useCallback4(() => {
|
|
9325
|
+
addNavAfterAnchorRef.current = null;
|
|
9326
|
+
setLinkPopover(null);
|
|
9327
|
+
}, []);
|
|
9328
|
+
const openLinkPopoverForActive = useCallback4(() => {
|
|
7970
9329
|
const hrefCtx = getHrefKeyFromElement(activeElRef.current);
|
|
7971
9330
|
if (!hrefCtx) return;
|
|
7972
9331
|
bumpLinkPopoverGrace();
|
|
7973
9332
|
setLinkPopover({
|
|
7974
9333
|
key: hrefCtx.key,
|
|
7975
|
-
|
|
9334
|
+
mode: "edit",
|
|
9335
|
+
target: getLinkHref2(hrefCtx.anchor)
|
|
7976
9336
|
});
|
|
7977
9337
|
deactivate();
|
|
7978
9338
|
}, [deactivate]);
|
|
7979
|
-
const openLinkPopoverForSelected =
|
|
9339
|
+
const openLinkPopoverForSelected = useCallback4(() => {
|
|
7980
9340
|
const anchor = selectedElRef.current;
|
|
7981
9341
|
if (!anchor) return;
|
|
7982
9342
|
const key = anchor.getAttribute("data-ohw-href-key");
|
|
@@ -7984,51 +9344,156 @@ function OhhwellsBridge() {
|
|
|
7984
9344
|
bumpLinkPopoverGrace();
|
|
7985
9345
|
setLinkPopover({
|
|
7986
9346
|
key,
|
|
7987
|
-
|
|
9347
|
+
mode: "edit",
|
|
9348
|
+
target: getLinkHref2(anchor)
|
|
7988
9349
|
});
|
|
7989
9350
|
deselect();
|
|
7990
9351
|
}, [deselect]);
|
|
7991
|
-
const handleLinkPopoverSubmit =
|
|
9352
|
+
const handleLinkPopoverSubmit = useCallback4(
|
|
7992
9353
|
(target) => {
|
|
7993
|
-
|
|
7994
|
-
|
|
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;
|
|
7995
9395
|
applyLinkByKey(key, target);
|
|
7996
|
-
|
|
9396
|
+
postToParent2({ type: "ow:change", nodes: [{ key, text: target }] });
|
|
7997
9397
|
setLinkPopover(null);
|
|
7998
9398
|
},
|
|
7999
|
-
[
|
|
9399
|
+
[postToParent2, sitePages, sectionsByPath]
|
|
8000
9400
|
);
|
|
8001
9401
|
const showEditLink = toolbarShowEditLink;
|
|
8002
9402
|
const currentSections = sectionsByPath[pathname] ?? [];
|
|
8003
9403
|
linkPopoverOpenRef.current = linkPopover !== null;
|
|
8004
|
-
|
|
8005
|
-
|
|
8006
|
-
|
|
8007
|
-
|
|
8008
|
-
|
|
8009
|
-
|
|
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(
|
|
8010
9474
|
ItemInteractionLayer,
|
|
8011
9475
|
{
|
|
8012
9476
|
rect: toolbarRect,
|
|
8013
9477
|
elRef: glowElRef,
|
|
8014
9478
|
state: isItemDragging ? "dragging" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
|
|
8015
|
-
showHandle: Boolean(reorderHrefKey),
|
|
9479
|
+
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey),
|
|
8016
9480
|
dragDisabled: reorderDragDisabled,
|
|
8017
9481
|
dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
|
|
8018
9482
|
onDragHandleDragStart: handleItemDragStart,
|
|
8019
9483
|
onDragHandleDragEnd: handleItemDragEnd,
|
|
8020
|
-
toolbar:
|
|
9484
|
+
toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ jsx23(
|
|
8021
9485
|
ItemActionToolbar,
|
|
8022
9486
|
{
|
|
8023
9487
|
onEditLink: openLinkPopoverForSelected,
|
|
8024
|
-
|
|
8025
|
-
|
|
9488
|
+
addItemDisabled: true,
|
|
9489
|
+
editLinkDisabled: false,
|
|
9490
|
+
moreDisabled: true
|
|
8026
9491
|
}
|
|
8027
|
-
)
|
|
9492
|
+
) : void 0
|
|
8028
9493
|
}
|
|
8029
9494
|
),
|
|
8030
|
-
toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */
|
|
8031
|
-
/* @__PURE__ */
|
|
9495
|
+
toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
9496
|
+
/* @__PURE__ */ jsx23(
|
|
8032
9497
|
EditGlowChrome,
|
|
8033
9498
|
{
|
|
8034
9499
|
rect: toolbarRect,
|
|
@@ -8037,7 +9502,7 @@ function OhhwellsBridge() {
|
|
|
8037
9502
|
dragDisabled: reorderDragDisabled
|
|
8038
9503
|
}
|
|
8039
9504
|
),
|
|
8040
|
-
/* @__PURE__ */
|
|
9505
|
+
/* @__PURE__ */ jsx23(
|
|
8041
9506
|
FloatingToolbar,
|
|
8042
9507
|
{
|
|
8043
9508
|
rect: toolbarRect,
|
|
@@ -8050,7 +9515,7 @@ function OhhwellsBridge() {
|
|
|
8050
9515
|
}
|
|
8051
9516
|
)
|
|
8052
9517
|
] }),
|
|
8053
|
-
maxBadge && /* @__PURE__ */
|
|
9518
|
+
maxBadge && /* @__PURE__ */ jsxs13(
|
|
8054
9519
|
"div",
|
|
8055
9520
|
{
|
|
8056
9521
|
"data-ohw-max-badge": "",
|
|
@@ -8076,7 +9541,7 @@ function OhhwellsBridge() {
|
|
|
8076
9541
|
]
|
|
8077
9542
|
}
|
|
8078
9543
|
),
|
|
8079
|
-
toggleState && /* @__PURE__ */
|
|
9544
|
+
toggleState && !linkPopover && /* @__PURE__ */ jsx23(
|
|
8080
9545
|
StateToggle,
|
|
8081
9546
|
{
|
|
8082
9547
|
rect: toggleState.rect,
|
|
@@ -8085,15 +9550,15 @@ function OhhwellsBridge() {
|
|
|
8085
9550
|
onStateChange: handleStateChange
|
|
8086
9551
|
}
|
|
8087
9552
|
),
|
|
8088
|
-
sectionGap && /* @__PURE__ */
|
|
9553
|
+
sectionGap && !linkPopover && /* @__PURE__ */ jsxs13(
|
|
8089
9554
|
"div",
|
|
8090
9555
|
{
|
|
8091
9556
|
"data-ohw-section-insert-line": "",
|
|
8092
9557
|
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
8093
9558
|
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
8094
9559
|
children: [
|
|
8095
|
-
/* @__PURE__ */
|
|
8096
|
-
/* @__PURE__ */
|
|
9560
|
+
/* @__PURE__ */ jsx23("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
9561
|
+
/* @__PURE__ */ jsx23(
|
|
8097
9562
|
Badge,
|
|
8098
9563
|
{
|
|
8099
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",
|
|
@@ -8106,26 +9571,52 @@ function OhhwellsBridge() {
|
|
|
8106
9571
|
children: "Add Section"
|
|
8107
9572
|
}
|
|
8108
9573
|
),
|
|
8109
|
-
/* @__PURE__ */
|
|
9574
|
+
/* @__PURE__ */ jsx23("div", { className: "flex-1 bg-primary", style: { height: 3 } })
|
|
8110
9575
|
]
|
|
8111
9576
|
}
|
|
8112
9577
|
),
|
|
8113
|
-
linkPopover && dialogPortalContainer ? /* @__PURE__ */
|
|
9578
|
+
linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx23(
|
|
8114
9579
|
LinkPopover,
|
|
8115
9580
|
{
|
|
8116
9581
|
panelRef: linkPopoverPanelRef,
|
|
8117
9582
|
portalContainer: dialogPortalContainer,
|
|
8118
9583
|
open: true,
|
|
8119
|
-
mode: "edit",
|
|
9584
|
+
mode: linkPopover.mode ?? "edit",
|
|
8120
9585
|
pages: sitePages,
|
|
8121
9586
|
sections: currentSections,
|
|
8122
9587
|
sectionsByPath,
|
|
8123
9588
|
initialTarget: linkPopover.target,
|
|
9589
|
+
existingTargets: linkPopover.intent === "add-nav" ? getNavbarExistingTargets() : [],
|
|
8124
9590
|
onClose: closeLinkPopover,
|
|
8125
9591
|
onSubmit: handleLinkPopoverSubmit
|
|
8126
9592
|
},
|
|
8127
|
-
|
|
8128
|
-
) : 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
|
+
)
|
|
8129
9620
|
] }),
|
|
8130
9621
|
bridgeRoot
|
|
8131
9622
|
) : null;
|