@ohhwells/bridge 0.1.41 → 0.1.42-next.82
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 +13 -1
- package/dist/index.cjs +1744 -490
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +48 -3
- package/dist/index.d.ts +48 -3
- package/dist/index.js +1695 -444
- package/dist/index.js.map +1 -1
- package/dist/styles.css +42 -18
- 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 React10, { useCallback as useCallback4, useEffect as useEffect8, useLayoutEffect as useLayoutEffect2, useRef as useRef5, useState as useState7 } from "react";
|
|
5
5
|
import { createRoot } from "react-dom/client";
|
|
6
6
|
import { flushSync } from "react-dom";
|
|
7
7
|
|
|
@@ -48,12 +48,13 @@ function useLinkHrefGuardian(...deps) {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
// src/ui/SchedulingWidget.tsx
|
|
51
|
-
import { useEffect, useId, useMemo, useRef, useState as useState2 } from "react";
|
|
51
|
+
import { useCallback, useEffect, useId, useMemo, useRef, useState as useState2 } from "react";
|
|
52
52
|
|
|
53
53
|
// src/ui/EmailCaptureModal.tsx
|
|
54
54
|
import { useState } from "react";
|
|
55
55
|
import { Dialog } from "radix-ui";
|
|
56
56
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
57
|
+
var isValidEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
57
58
|
function Spinner() {
|
|
58
59
|
return /* @__PURE__ */ jsxs(
|
|
59
60
|
"svg",
|
|
@@ -87,12 +88,17 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
|
|
|
87
88
|
const [error, setError] = useState(null);
|
|
88
89
|
const isBook = title === "Confirm your spot";
|
|
89
90
|
const handleSubmit = async () => {
|
|
90
|
-
|
|
91
|
+
const trimmed = email.trim();
|
|
92
|
+
if (!trimmed) return;
|
|
93
|
+
if (!isValidEmail(trimmed)) {
|
|
94
|
+
setError("Please enter a valid email address.");
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
91
97
|
setLoading(true);
|
|
92
98
|
setError(null);
|
|
93
99
|
try {
|
|
94
|
-
await onSubmit(
|
|
95
|
-
setSubmittedEmail(
|
|
100
|
+
await onSubmit(trimmed);
|
|
101
|
+
setSubmittedEmail(trimmed);
|
|
96
102
|
setSuccess(true);
|
|
97
103
|
} catch (e) {
|
|
98
104
|
setError(e instanceof Error ? e.message : "Something went wrong. Please try again.");
|
|
@@ -167,7 +173,10 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
|
|
|
167
173
|
{
|
|
168
174
|
type: "email",
|
|
169
175
|
value: email,
|
|
170
|
-
onChange: (e) =>
|
|
176
|
+
onChange: (e) => {
|
|
177
|
+
setEmail(e.target.value);
|
|
178
|
+
if (error) setError(null);
|
|
179
|
+
},
|
|
171
180
|
onKeyDown: handleKeyDown,
|
|
172
181
|
placeholder: "hello@gmail.com",
|
|
173
182
|
autoFocus: true,
|
|
@@ -224,12 +233,20 @@ function formatClassTime(cls) {
|
|
|
224
233
|
const em = endTotal % 60;
|
|
225
234
|
return `${h}:${cls.startTime.minutes}-${eh}:${String(em).padStart(2, "0")}`;
|
|
226
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
|
+
}
|
|
227
241
|
function getBookingsOnDate(cls, date) {
|
|
228
242
|
if (!cls.bookings?.length) return 0;
|
|
229
|
-
const
|
|
243
|
+
const target = new Date(date);
|
|
244
|
+
target.setHours(0, 0, 0, 0);
|
|
230
245
|
return cls.bookings.filter((b) => {
|
|
231
246
|
try {
|
|
232
|
-
|
|
247
|
+
const bookingDate = new Date(b.classDate);
|
|
248
|
+
bookingDate.setHours(0, 0, 0, 0);
|
|
249
|
+
return bookingDate.getTime() === target.getTime();
|
|
233
250
|
} catch {
|
|
234
251
|
return false;
|
|
235
252
|
}
|
|
@@ -494,7 +511,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
|
|
|
494
511
|
}
|
|
495
512
|
)
|
|
496
513
|
] }),
|
|
497
|
-
/* @__PURE__ */ jsx2("div", { className: "sm:hidden flex flex-col gap-px", children: isFull ? /* @__PURE__ */ jsx2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
514
|
+
cls.showAvailability !== false && /* @__PURE__ */ jsx2("div", { className: "sm:hidden flex flex-col gap-px", children: isFull ? /* @__PURE__ */ jsx2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
498
515
|
/* @__PURE__ */ jsxs2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
|
|
499
516
|
available,
|
|
500
517
|
"/",
|
|
@@ -506,9 +523,10 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
|
|
|
506
523
|
/* @__PURE__ */ jsxs2("div", { className: "flex flex-1 flex-col gap-2 min-w-0 sm:contents", children: [
|
|
507
524
|
/* @__PURE__ */ jsxs2("div", { className: "flex-1 flex flex-col gap-2 min-w-0", children: [
|
|
508
525
|
/* @__PURE__ */ jsx2("span", { className: "font-body text-base font-bold text-(--color-dark,#200C02) block truncate", children: cls.name }),
|
|
509
|
-
cls.hostName && /* @__PURE__ */ jsx2("span", { className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block truncate", children: cls.hostName })
|
|
526
|
+
cls.hostName && /* @__PURE__ */ jsx2("span", { className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block truncate", children: cls.hostName }),
|
|
527
|
+
cls.description && /* @__PURE__ */ jsx2("span", { className: "font-body text-sm font-normal text-(--color-dark,#200C02) opacity-70 block truncate", children: cls.description })
|
|
510
528
|
] }),
|
|
511
|
-
/* @__PURE__ */ jsx2("div", { className: "hidden sm:flex w-14 shrink-0 flex-col gap-px", children: isFull ? /* @__PURE__ */ jsx2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
529
|
+
cls.showAvailability !== false && /* @__PURE__ */ jsx2("div", { className: "hidden sm:flex w-14 shrink-0 flex-col gap-px", children: isFull ? /* @__PURE__ */ jsx2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
512
530
|
/* @__PURE__ */ jsxs2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
|
|
513
531
|
available,
|
|
514
532
|
"/",
|
|
@@ -533,7 +551,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
|
|
|
533
551
|
if (!cls.id) return;
|
|
534
552
|
onOpenModal?.(isFull ? "waitlist" : "book", cls.id, selectedDate);
|
|
535
553
|
},
|
|
536
|
-
children: isFull ? "Join Waitlist" :
|
|
554
|
+
children: isFull ? "Join Waitlist" : formatBookingLabel(cls)
|
|
537
555
|
}
|
|
538
556
|
)
|
|
539
557
|
] })
|
|
@@ -575,6 +593,17 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
575
593
|
const [isHovered, setIsHovered] = useState2(false);
|
|
576
594
|
const [modalState, setModalState] = useState2(null);
|
|
577
595
|
const switchScheduleIdRef = useRef(null);
|
|
596
|
+
const liveScheduleIdRef = useRef(null);
|
|
597
|
+
const refetchLiveSchedule = useCallback(async () => {
|
|
598
|
+
const id = liveScheduleIdRef.current;
|
|
599
|
+
if (!id) return;
|
|
600
|
+
try {
|
|
601
|
+
const res = await fetch(`${API_URL}/api/schedule/id/${id}`);
|
|
602
|
+
const data = await res.json();
|
|
603
|
+
if (data?.id) setSchedule(data);
|
|
604
|
+
} catch {
|
|
605
|
+
}
|
|
606
|
+
}, []);
|
|
578
607
|
const dates = useMemo(() => {
|
|
579
608
|
const today = /* @__PURE__ */ new Date();
|
|
580
609
|
today.setHours(0, 0, 0, 0);
|
|
@@ -594,6 +623,18 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
594
623
|
}
|
|
595
624
|
}
|
|
596
625
|
}, [schedule, dates]);
|
|
626
|
+
useEffect(() => {
|
|
627
|
+
if (typeof window === "undefined") return;
|
|
628
|
+
const onVisible = () => {
|
|
629
|
+
if (!document.hidden) void refetchLiveSchedule();
|
|
630
|
+
};
|
|
631
|
+
window.addEventListener("focus", refetchLiveSchedule);
|
|
632
|
+
document.addEventListener("visibilitychange", onVisible);
|
|
633
|
+
return () => {
|
|
634
|
+
window.removeEventListener("focus", refetchLiveSchedule);
|
|
635
|
+
document.removeEventListener("visibilitychange", onVisible);
|
|
636
|
+
};
|
|
637
|
+
}, [refetchLiveSchedule]);
|
|
597
638
|
useEffect(() => {
|
|
598
639
|
if (typeof window === "undefined") return;
|
|
599
640
|
const isInEditor = window.self !== window.top;
|
|
@@ -655,7 +696,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
655
696
|
setLoading(false);
|
|
656
697
|
return;
|
|
657
698
|
}
|
|
658
|
-
;
|
|
699
|
+
liveScheduleIdRef.current = effectiveId;
|
|
659
700
|
(async () => {
|
|
660
701
|
try {
|
|
661
702
|
const res = await fetch(`${API_URL}/api/schedule/id/${effectiveId}`);
|
|
@@ -712,18 +753,14 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
712
753
|
const data = await res.json().catch(() => ({}));
|
|
713
754
|
throw new Error(data?.message ?? "Something went wrong. Please try again.");
|
|
714
755
|
}
|
|
756
|
+
await refetchLiveSchedule();
|
|
715
757
|
};
|
|
716
758
|
const handleReplaceSchedule = () => {
|
|
717
759
|
setIsHovered(false);
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
insertAfter
|
|
723
|
-
}, "*");
|
|
724
|
-
} else {
|
|
725
|
-
window.parent.postMessage({ type: "ow:scheduling-not-connected", insertAfter }, "*");
|
|
726
|
-
}
|
|
760
|
+
window.parent.postMessage(
|
|
761
|
+
{ type: "ow:scheduling-not-connected", insertAfter, currentScheduleId: schedule?.id },
|
|
762
|
+
"*"
|
|
763
|
+
);
|
|
727
764
|
};
|
|
728
765
|
if (!inEditor && !loading && !schedule) return null;
|
|
729
766
|
const sectionId = `scheduling-${insertAfter}`;
|
|
@@ -766,7 +803,19 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
766
803
|
),
|
|
767
804
|
/* @__PURE__ */ jsxs2("div", { className: "max-w-[1280px] mx-auto flex flex-col items-center gap-16", children: [
|
|
768
805
|
/* @__PURE__ */ jsxs2("div", { className: "flex flex-col items-center gap-4", children: [
|
|
769
|
-
/* @__PURE__ */ jsx2(
|
|
806
|
+
/* @__PURE__ */ jsx2(
|
|
807
|
+
"h2",
|
|
808
|
+
{
|
|
809
|
+
className: "font-display text-center m-0 text-(--color-dark,#200C02)",
|
|
810
|
+
style: {
|
|
811
|
+
fontSize: "var(--fs-section-h2, clamp(40px, 4.4vw, 64px))",
|
|
812
|
+
fontWeight: "var(--font-weight-heading, 400)",
|
|
813
|
+
lineHeight: 1.05,
|
|
814
|
+
letterSpacing: "-0.02em"
|
|
815
|
+
},
|
|
816
|
+
children: schedule?.name ?? "Book an appointment"
|
|
817
|
+
}
|
|
818
|
+
),
|
|
770
819
|
schedule?.description && /* @__PURE__ */ jsx2("p", { className: "font-body text-body text-center m-0 text-(--color-accent,#A89B83)", children: schedule.description })
|
|
771
820
|
] }),
|
|
772
821
|
/* @__PURE__ */ jsxs2("div", { className: "w-full flex flex-col items-end gap-3", children: [
|
|
@@ -4444,7 +4493,7 @@ function getChromeStyle(state) {
|
|
|
4444
4493
|
case "dragging":
|
|
4445
4494
|
return {
|
|
4446
4495
|
border: `2px solid ${PRIMARY}`,
|
|
4447
|
-
boxShadow: DRAG_SHADOW
|
|
4496
|
+
boxShadow: `${FOCUS_RING}, ${DRAG_SHADOW}`
|
|
4448
4497
|
};
|
|
4449
4498
|
default:
|
|
4450
4499
|
return {};
|
|
@@ -4460,6 +4509,8 @@ function ItemInteractionLayer({
|
|
|
4460
4509
|
dragHandleLabel = "Reorder item",
|
|
4461
4510
|
onDragHandleDragStart,
|
|
4462
4511
|
onDragHandleDragEnd,
|
|
4512
|
+
onItemPointerDown,
|
|
4513
|
+
onItemClick,
|
|
4463
4514
|
chromeGap = 6,
|
|
4464
4515
|
className
|
|
4465
4516
|
}) {
|
|
@@ -4467,7 +4518,8 @@ function ItemInteractionLayer({
|
|
|
4467
4518
|
const isActive = state === "active-top" || state === "active-bottom";
|
|
4468
4519
|
const isDragging = state === "dragging";
|
|
4469
4520
|
const showToolbar = isActive && toolbar;
|
|
4470
|
-
const showDragHandle = isActive
|
|
4521
|
+
const showDragHandle = (isActive || isDragging) && showHandle;
|
|
4522
|
+
const itemDragEnabled = isActive && showHandle && !isDragging && !dragDisabled;
|
|
4471
4523
|
return /* @__PURE__ */ jsxs4(
|
|
4472
4524
|
"div",
|
|
4473
4525
|
{
|
|
@@ -4492,11 +4544,28 @@ function ItemInteractionLayer({
|
|
|
4492
4544
|
style: getChromeStyle(state)
|
|
4493
4545
|
}
|
|
4494
4546
|
),
|
|
4547
|
+
itemDragEnabled && /* @__PURE__ */ jsx9(
|
|
4548
|
+
"div",
|
|
4549
|
+
{
|
|
4550
|
+
"data-ohw-item-drag-surface": "",
|
|
4551
|
+
className: "pointer-events-auto absolute inset-0 cursor-grab rounded-lg active:cursor-grabbing",
|
|
4552
|
+
onPointerDown: (e) => {
|
|
4553
|
+
if (e.button !== 0) return;
|
|
4554
|
+
onItemPointerDown?.(e);
|
|
4555
|
+
},
|
|
4556
|
+
onClick: (e) => {
|
|
4557
|
+
e.preventDefault();
|
|
4558
|
+
e.stopPropagation();
|
|
4559
|
+
onItemClick?.(e.clientX, e.clientY);
|
|
4560
|
+
}
|
|
4561
|
+
}
|
|
4562
|
+
),
|
|
4495
4563
|
showDragHandle && /* @__PURE__ */ jsx9(
|
|
4496
4564
|
"div",
|
|
4497
4565
|
{
|
|
4498
4566
|
"data-ohw-drag-handle-container": "",
|
|
4499
|
-
className: "pointer-events-auto absolute left-0 top-1/2 -translate-x-[calc(100%+7px)] -translate-y-1/2",
|
|
4567
|
+
className: "pointer-events-auto absolute left-0 top-1/2 z-10 -translate-x-[calc(100%+7px)] -translate-y-1/2",
|
|
4568
|
+
style: isDragging ? { visibility: "hidden" } : void 0,
|
|
4500
4569
|
children: /* @__PURE__ */ jsx9(
|
|
4501
4570
|
DragHandle,
|
|
4502
4571
|
{
|
|
@@ -4719,15 +4788,12 @@ function MediaOverlay({
|
|
|
4719
4788
|
className: "flex items-center justify-center cursor-pointer",
|
|
4720
4789
|
style: {
|
|
4721
4790
|
...box,
|
|
4722
|
-
//
|
|
4723
|
-
//
|
|
4724
|
-
|
|
4725
|
-
// Replace still works.
|
|
4726
|
-
pointerEvents: hover.hasTextOverlap ? "none" : "auto",
|
|
4791
|
+
// Keep the full-size visual overlay click-through so carousel controls and editable
|
|
4792
|
+
// content underneath remain interactive. The Replace button opts back in below.
|
|
4793
|
+
pointerEvents: "none",
|
|
4727
4794
|
boxShadow: "inset 0 0 0 1.5px var(--color-primary)",
|
|
4728
4795
|
background: "color-mix(in srgb, var(--color-primary) 20%, transparent)"
|
|
4729
4796
|
},
|
|
4730
|
-
onClick: () => onReplace(hover.key),
|
|
4731
4797
|
children: /* @__PURE__ */ jsxs5(
|
|
4732
4798
|
Button,
|
|
4733
4799
|
{
|
|
@@ -4752,6 +4818,61 @@ function MediaOverlay({
|
|
|
4752
4818
|
] });
|
|
4753
4819
|
}
|
|
4754
4820
|
|
|
4821
|
+
// src/ui/CarouselOverlay.tsx
|
|
4822
|
+
import { GalleryHorizontal } from "lucide-react";
|
|
4823
|
+
import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
4824
|
+
var OVERLAY_BUTTON_STYLE2 = {
|
|
4825
|
+
pointerEvents: "auto",
|
|
4826
|
+
fontFamily: "Inter, sans-serif",
|
|
4827
|
+
fontSize: 12,
|
|
4828
|
+
color: "#000"
|
|
4829
|
+
};
|
|
4830
|
+
function CarouselOverlay({
|
|
4831
|
+
hover,
|
|
4832
|
+
onEdit
|
|
4833
|
+
}) {
|
|
4834
|
+
const { rect } = hover;
|
|
4835
|
+
return /* @__PURE__ */ jsx12(
|
|
4836
|
+
"div",
|
|
4837
|
+
{
|
|
4838
|
+
"data-ohw-bridge": "",
|
|
4839
|
+
"data-ohw-carousel-overlay": "",
|
|
4840
|
+
className: "flex cursor-pointer items-center justify-center",
|
|
4841
|
+
style: {
|
|
4842
|
+
position: "fixed",
|
|
4843
|
+
top: rect.top,
|
|
4844
|
+
left: rect.left,
|
|
4845
|
+
width: rect.width,
|
|
4846
|
+
height: rect.height,
|
|
4847
|
+
zIndex: 2147483646,
|
|
4848
|
+
pointerEvents: "auto",
|
|
4849
|
+
boxShadow: "inset 0 0 0 1.5px var(--color-primary)",
|
|
4850
|
+
background: "color-mix(in srgb, var(--color-primary) 20%, transparent)"
|
|
4851
|
+
},
|
|
4852
|
+
onClick: () => onEdit(hover.key),
|
|
4853
|
+
children: /* @__PURE__ */ jsxs6(
|
|
4854
|
+
Button,
|
|
4855
|
+
{
|
|
4856
|
+
"data-ohw-carousel-overlay": "",
|
|
4857
|
+
variant: "outline",
|
|
4858
|
+
size: "sm",
|
|
4859
|
+
className: "cursor-pointer gap-1.5 hover:bg-background",
|
|
4860
|
+
style: OVERLAY_BUTTON_STYLE2,
|
|
4861
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
4862
|
+
onClick: (e) => {
|
|
4863
|
+
e.stopPropagation();
|
|
4864
|
+
onEdit(hover.key);
|
|
4865
|
+
},
|
|
4866
|
+
children: [
|
|
4867
|
+
/* @__PURE__ */ jsx12(GalleryHorizontal, { size: 14 }),
|
|
4868
|
+
"Edit gallery"
|
|
4869
|
+
]
|
|
4870
|
+
}
|
|
4871
|
+
)
|
|
4872
|
+
}
|
|
4873
|
+
);
|
|
4874
|
+
}
|
|
4875
|
+
|
|
4755
4876
|
// src/OhhwellsBridge.tsx
|
|
4756
4877
|
import { createPortal as createPortal2 } from "react-dom";
|
|
4757
4878
|
import { usePathname as usePathname2, useRouter as useRouter2, useSearchParams } from "next/navigation";
|
|
@@ -5038,22 +5159,22 @@ import { useEffect as useEffect6 } from "react";
|
|
|
5038
5159
|
import * as React7 from "react";
|
|
5039
5160
|
import { Dialog as DialogPrimitive } from "radix-ui";
|
|
5040
5161
|
import { X } from "lucide-react";
|
|
5041
|
-
import { jsx as
|
|
5162
|
+
import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
5042
5163
|
function Dialog2({
|
|
5043
5164
|
...props
|
|
5044
5165
|
}) {
|
|
5045
|
-
return /* @__PURE__ */
|
|
5166
|
+
return /* @__PURE__ */ jsx13(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
|
|
5046
5167
|
}
|
|
5047
5168
|
function DialogPortal({
|
|
5048
5169
|
...props
|
|
5049
5170
|
}) {
|
|
5050
|
-
return /* @__PURE__ */
|
|
5171
|
+
return /* @__PURE__ */ jsx13(DialogPrimitive.Portal, { ...props });
|
|
5051
5172
|
}
|
|
5052
5173
|
function DialogOverlay({
|
|
5053
5174
|
className,
|
|
5054
5175
|
...props
|
|
5055
5176
|
}) {
|
|
5056
|
-
return /* @__PURE__ */
|
|
5177
|
+
return /* @__PURE__ */ jsx13(
|
|
5057
5178
|
DialogPrimitive.Overlay,
|
|
5058
5179
|
{
|
|
5059
5180
|
"data-slot": "dialog-overlay",
|
|
@@ -5066,9 +5187,9 @@ function DialogOverlay({
|
|
|
5066
5187
|
var DialogContent = React7.forwardRef(
|
|
5067
5188
|
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
5068
5189
|
const positionMode = container ? "absolute" : "fixed";
|
|
5069
|
-
return /* @__PURE__ */
|
|
5070
|
-
/* @__PURE__ */
|
|
5071
|
-
/* @__PURE__ */
|
|
5190
|
+
return /* @__PURE__ */ jsxs7(DialogPortal, { container: container ?? void 0, children: [
|
|
5191
|
+
/* @__PURE__ */ jsx13(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
5192
|
+
/* @__PURE__ */ jsxs7(
|
|
5072
5193
|
DialogPrimitive.Content,
|
|
5073
5194
|
{
|
|
5074
5195
|
ref,
|
|
@@ -5084,13 +5205,13 @@ var DialogContent = React7.forwardRef(
|
|
|
5084
5205
|
...props,
|
|
5085
5206
|
children: [
|
|
5086
5207
|
children,
|
|
5087
|
-
showCloseButton ? /* @__PURE__ */
|
|
5208
|
+
showCloseButton ? /* @__PURE__ */ jsx13(
|
|
5088
5209
|
DialogPrimitive.Close,
|
|
5089
5210
|
{
|
|
5090
5211
|
type: "button",
|
|
5091
5212
|
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
5092
5213
|
"aria-label": "Close",
|
|
5093
|
-
children: /* @__PURE__ */
|
|
5214
|
+
children: /* @__PURE__ */ jsx13(X, { size: 16, "aria-hidden": true })
|
|
5094
5215
|
}
|
|
5095
5216
|
) : null
|
|
5096
5217
|
]
|
|
@@ -5104,13 +5225,13 @@ function DialogHeader({
|
|
|
5104
5225
|
className,
|
|
5105
5226
|
...props
|
|
5106
5227
|
}) {
|
|
5107
|
-
return /* @__PURE__ */
|
|
5228
|
+
return /* @__PURE__ */ jsx13("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
5108
5229
|
}
|
|
5109
5230
|
function DialogFooter({
|
|
5110
5231
|
className,
|
|
5111
5232
|
...props
|
|
5112
5233
|
}) {
|
|
5113
|
-
return /* @__PURE__ */
|
|
5234
|
+
return /* @__PURE__ */ jsx13(
|
|
5114
5235
|
"div",
|
|
5115
5236
|
{
|
|
5116
5237
|
className: cn("flex items-center justify-end gap-2", className),
|
|
@@ -5118,7 +5239,7 @@ function DialogFooter({
|
|
|
5118
5239
|
}
|
|
5119
5240
|
);
|
|
5120
5241
|
}
|
|
5121
|
-
var DialogTitle = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
|
|
5242
|
+
var DialogTitle = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
|
|
5122
5243
|
DialogPrimitive.Title,
|
|
5123
5244
|
{
|
|
5124
5245
|
ref,
|
|
@@ -5130,7 +5251,7 @@ var DialogTitle = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE
|
|
|
5130
5251
|
}
|
|
5131
5252
|
));
|
|
5132
5253
|
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
5133
|
-
var DialogDescription = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
|
|
5254
|
+
var DialogDescription = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
|
|
5134
5255
|
DialogPrimitive.Description,
|
|
5135
5256
|
{
|
|
5136
5257
|
ref,
|
|
@@ -5146,19 +5267,19 @@ import { Info, X as X3 } from "lucide-react";
|
|
|
5146
5267
|
|
|
5147
5268
|
// src/ui/link-modal/DestinationBreadcrumb.tsx
|
|
5148
5269
|
import { ArrowRight, File, GalleryVertical } from "lucide-react";
|
|
5149
|
-
import { jsx as
|
|
5270
|
+
import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
5150
5271
|
function DestinationBreadcrumb({
|
|
5151
5272
|
pageTitle,
|
|
5152
5273
|
sectionLabel
|
|
5153
5274
|
}) {
|
|
5154
|
-
return /* @__PURE__ */
|
|
5155
|
-
/* @__PURE__ */
|
|
5156
|
-
/* @__PURE__ */
|
|
5157
|
-
/* @__PURE__ */
|
|
5158
|
-
/* @__PURE__ */
|
|
5159
|
-
/* @__PURE__ */
|
|
5275
|
+
return /* @__PURE__ */ jsxs8("div", { className: "flex w-full flex-col gap-2", children: [
|
|
5276
|
+
/* @__PURE__ */ jsx14("p", { className: "text-sm font-medium! text-foreground m-0", children: "Destination" }),
|
|
5277
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3", children: [
|
|
5278
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
|
|
5279
|
+
/* @__PURE__ */ jsx14(File, { size: 16, className: "shrink-0 text-foreground", "aria-hidden": true }),
|
|
5280
|
+
/* @__PURE__ */ jsx14("span", { className: "text-sm font-medium leading-none text-foreground!", children: pageTitle })
|
|
5160
5281
|
] }),
|
|
5161
|
-
/* @__PURE__ */
|
|
5282
|
+
/* @__PURE__ */ jsx14(
|
|
5162
5283
|
ArrowRight,
|
|
5163
5284
|
{
|
|
5164
5285
|
size: 16,
|
|
@@ -5166,8 +5287,8 @@ function DestinationBreadcrumb({
|
|
|
5166
5287
|
"aria-hidden": true
|
|
5167
5288
|
}
|
|
5168
5289
|
),
|
|
5169
|
-
/* @__PURE__ */
|
|
5170
|
-
/* @__PURE__ */
|
|
5290
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
|
|
5291
|
+
/* @__PURE__ */ jsx14(
|
|
5171
5292
|
GalleryVertical,
|
|
5172
5293
|
{
|
|
5173
5294
|
size: 16,
|
|
@@ -5175,7 +5296,7 @@ function DestinationBreadcrumb({
|
|
|
5175
5296
|
"aria-hidden": true
|
|
5176
5297
|
}
|
|
5177
5298
|
),
|
|
5178
|
-
/* @__PURE__ */
|
|
5299
|
+
/* @__PURE__ */ jsx14("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
|
|
5179
5300
|
] })
|
|
5180
5301
|
] })
|
|
5181
5302
|
] });
|
|
@@ -5183,22 +5304,22 @@ function DestinationBreadcrumb({
|
|
|
5183
5304
|
|
|
5184
5305
|
// src/ui/link-modal/SectionTreeItem.tsx
|
|
5185
5306
|
import { GalleryVertical as GalleryVertical2 } from "lucide-react";
|
|
5186
|
-
import { jsx as
|
|
5307
|
+
import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
5187
5308
|
function SectionTreeItem({
|
|
5188
5309
|
section,
|
|
5189
5310
|
onSelect,
|
|
5190
5311
|
selected
|
|
5191
5312
|
}) {
|
|
5192
5313
|
const interactive = Boolean(onSelect);
|
|
5193
|
-
return /* @__PURE__ */
|
|
5194
|
-
/* @__PURE__ */
|
|
5314
|
+
return /* @__PURE__ */ jsxs9("div", { className: "flex h-9 w-full items-end pl-3", children: [
|
|
5315
|
+
/* @__PURE__ */ jsx15(
|
|
5195
5316
|
"div",
|
|
5196
5317
|
{
|
|
5197
5318
|
className: "mr-[-1px] h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
|
|
5198
5319
|
"aria-hidden": true
|
|
5199
5320
|
}
|
|
5200
5321
|
),
|
|
5201
|
-
/* @__PURE__ */
|
|
5322
|
+
/* @__PURE__ */ jsxs9(
|
|
5202
5323
|
"div",
|
|
5203
5324
|
{
|
|
5204
5325
|
role: interactive ? "button" : void 0,
|
|
@@ -5216,7 +5337,7 @@ function SectionTreeItem({
|
|
|
5216
5337
|
interactive && selected && "border-primary"
|
|
5217
5338
|
),
|
|
5218
5339
|
children: [
|
|
5219
|
-
/* @__PURE__ */
|
|
5340
|
+
/* @__PURE__ */ jsx15(
|
|
5220
5341
|
GalleryVertical2,
|
|
5221
5342
|
{
|
|
5222
5343
|
size: 16,
|
|
@@ -5224,7 +5345,7 @@ function SectionTreeItem({
|
|
|
5224
5345
|
"aria-hidden": true
|
|
5225
5346
|
}
|
|
5226
5347
|
),
|
|
5227
|
-
/* @__PURE__ */
|
|
5348
|
+
/* @__PURE__ */ jsx15("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
|
|
5228
5349
|
]
|
|
5229
5350
|
}
|
|
5230
5351
|
)
|
|
@@ -5236,10 +5357,10 @@ import { useEffect as useEffect3, useId as useId2, useRef as useRef3, useState a
|
|
|
5236
5357
|
|
|
5237
5358
|
// src/ui/input.tsx
|
|
5238
5359
|
import * as React8 from "react";
|
|
5239
|
-
import { jsx as
|
|
5360
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
5240
5361
|
var Input = React8.forwardRef(
|
|
5241
5362
|
({ className, type, ...props }, ref) => {
|
|
5242
|
-
return /* @__PURE__ */
|
|
5363
|
+
return /* @__PURE__ */ jsx16(
|
|
5243
5364
|
"input",
|
|
5244
5365
|
{
|
|
5245
5366
|
type,
|
|
@@ -5258,9 +5379,9 @@ Input.displayName = "Input";
|
|
|
5258
5379
|
|
|
5259
5380
|
// src/ui/label.tsx
|
|
5260
5381
|
import { Label as LabelPrimitive } from "radix-ui";
|
|
5261
|
-
import { jsx as
|
|
5382
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
5262
5383
|
function Label({ className, ...props }) {
|
|
5263
|
-
return /* @__PURE__ */
|
|
5384
|
+
return /* @__PURE__ */ jsx17(
|
|
5264
5385
|
LabelPrimitive.Root,
|
|
5265
5386
|
{
|
|
5266
5387
|
"data-slot": "label",
|
|
@@ -5272,11 +5393,11 @@ function Label({ className, ...props }) {
|
|
|
5272
5393
|
|
|
5273
5394
|
// src/ui/link-modal/UrlOrPageInput.tsx
|
|
5274
5395
|
import { ChevronDown, File as File2, X as X2 } from "lucide-react";
|
|
5275
|
-
import { jsx as
|
|
5396
|
+
import { jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
5276
5397
|
function FieldChevron({
|
|
5277
5398
|
onClick
|
|
5278
5399
|
}) {
|
|
5279
|
-
return /* @__PURE__ */
|
|
5400
|
+
return /* @__PURE__ */ jsx18(
|
|
5280
5401
|
"button",
|
|
5281
5402
|
{
|
|
5282
5403
|
type: "button",
|
|
@@ -5284,7 +5405,7 @@ function FieldChevron({
|
|
|
5284
5405
|
onClick,
|
|
5285
5406
|
"aria-label": "Open page list",
|
|
5286
5407
|
tabIndex: -1,
|
|
5287
|
-
children: /* @__PURE__ */
|
|
5408
|
+
children: /* @__PURE__ */ jsx18(ChevronDown, { size: 16 })
|
|
5288
5409
|
}
|
|
5289
5410
|
);
|
|
5290
5411
|
}
|
|
@@ -5345,11 +5466,11 @@ function UrlOrPageInput({
|
|
|
5345
5466
|
"data-ohw-link-field flex h-[36px] w-full items-center overflow-hidden rounded-md border bg-background pl-3 pr-3 py-2 outline-none transition-[border-color,box-shadow]",
|
|
5346
5467
|
urlError ? "border-destructive shadow-[0_0_0_1px_var(--ohw-destructive)]" : isFocused ? "border-primary shadow-[0_0_0_1px_var(--ohw-primary)]" : "border-input"
|
|
5347
5468
|
);
|
|
5348
|
-
return /* @__PURE__ */
|
|
5349
|
-
/* @__PURE__ */
|
|
5350
|
-
/* @__PURE__ */
|
|
5351
|
-
/* @__PURE__ */
|
|
5352
|
-
selectedPage ? /* @__PURE__ */
|
|
5469
|
+
return /* @__PURE__ */ jsxs10("div", { className: "flex w-full flex-col gap-2 p-0", children: [
|
|
5470
|
+
/* @__PURE__ */ jsx18(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
|
|
5471
|
+
/* @__PURE__ */ jsxs10("div", { ref: rootRef, className: "relative w-full", children: [
|
|
5472
|
+
/* @__PURE__ */ jsxs10("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
|
|
5473
|
+
selectedPage ? /* @__PURE__ */ jsx18("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ jsx18(
|
|
5353
5474
|
File2,
|
|
5354
5475
|
{
|
|
5355
5476
|
size: 16,
|
|
@@ -5357,7 +5478,7 @@ function UrlOrPageInput({
|
|
|
5357
5478
|
"aria-hidden": true
|
|
5358
5479
|
}
|
|
5359
5480
|
) }) : null,
|
|
5360
|
-
readOnly ? /* @__PURE__ */
|
|
5481
|
+
readOnly ? /* @__PURE__ */ jsx18("span", { className: "min-w-0 flex-1 truncate text-sm leading-5 text-foreground", children: selectedPage?.title ?? value }) : /* @__PURE__ */ jsx18(
|
|
5361
5482
|
Input,
|
|
5362
5483
|
{
|
|
5363
5484
|
ref: inputRef,
|
|
@@ -5383,7 +5504,7 @@ function UrlOrPageInput({
|
|
|
5383
5504
|
)
|
|
5384
5505
|
}
|
|
5385
5506
|
),
|
|
5386
|
-
selectedPage && !readOnly ? /* @__PURE__ */
|
|
5507
|
+
selectedPage && !readOnly ? /* @__PURE__ */ jsx18(
|
|
5387
5508
|
"button",
|
|
5388
5509
|
{
|
|
5389
5510
|
type: "button",
|
|
@@ -5391,26 +5512,26 @@ function UrlOrPageInput({
|
|
|
5391
5512
|
onMouseDown: clearSelection,
|
|
5392
5513
|
"aria-label": "Clear selected page",
|
|
5393
5514
|
tabIndex: -1,
|
|
5394
|
-
children: /* @__PURE__ */
|
|
5515
|
+
children: /* @__PURE__ */ jsx18(X2, { size: 16, "aria-hidden": true })
|
|
5395
5516
|
}
|
|
5396
5517
|
) : null,
|
|
5397
|
-
!readOnly ? /* @__PURE__ */
|
|
5518
|
+
!readOnly ? /* @__PURE__ */ jsx18(FieldChevron, { onClick: toggleDropdown }) : null
|
|
5398
5519
|
] }),
|
|
5399
|
-
dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */
|
|
5520
|
+
dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ jsx18(
|
|
5400
5521
|
"div",
|
|
5401
5522
|
{
|
|
5402
5523
|
"data-ohw-link-page-dropdown": "",
|
|
5403
5524
|
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",
|
|
5404
5525
|
onMouseDown: (e) => e.preventDefault(),
|
|
5405
|
-
children: filteredPages.map((page) => /* @__PURE__ */
|
|
5526
|
+
children: filteredPages.map((page) => /* @__PURE__ */ jsxs10(
|
|
5406
5527
|
"button",
|
|
5407
5528
|
{
|
|
5408
5529
|
type: "button",
|
|
5409
5530
|
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",
|
|
5410
5531
|
onClick: () => onPageSelect(page),
|
|
5411
5532
|
children: [
|
|
5412
|
-
/* @__PURE__ */
|
|
5413
|
-
/* @__PURE__ */
|
|
5533
|
+
/* @__PURE__ */ jsx18(File2, { size: 16, className: "shrink-0", "aria-hidden": true }),
|
|
5534
|
+
/* @__PURE__ */ jsx18("span", { className: "truncate", children: page.title })
|
|
5414
5535
|
]
|
|
5415
5536
|
},
|
|
5416
5537
|
page.path
|
|
@@ -5418,34 +5539,34 @@ function UrlOrPageInput({
|
|
|
5418
5539
|
}
|
|
5419
5540
|
) : null
|
|
5420
5541
|
] }),
|
|
5421
|
-
urlError ? /* @__PURE__ */
|
|
5542
|
+
urlError ? /* @__PURE__ */ jsx18("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
|
|
5422
5543
|
] });
|
|
5423
5544
|
}
|
|
5424
5545
|
|
|
5425
5546
|
// src/ui/link-modal/LinkEditorPanel.tsx
|
|
5426
|
-
import { Fragment as Fragment3, jsx as
|
|
5547
|
+
import { Fragment as Fragment3, jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
5427
5548
|
function LinkEditorPanel({ state, onClose }) {
|
|
5428
5549
|
const isCancel = state.secondaryLabel === "Cancel" || state.secondaryLabel === "Back to sections";
|
|
5429
|
-
return /* @__PURE__ */
|
|
5430
|
-
/* @__PURE__ */
|
|
5550
|
+
return /* @__PURE__ */ jsxs11(Fragment3, { children: [
|
|
5551
|
+
/* @__PURE__ */ jsx19(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx19(
|
|
5431
5552
|
"button",
|
|
5432
5553
|
{
|
|
5433
5554
|
type: "button",
|
|
5434
5555
|
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50 h-7",
|
|
5435
5556
|
"aria-label": "Close",
|
|
5436
5557
|
onClick: onClose,
|
|
5437
|
-
children: /* @__PURE__ */
|
|
5558
|
+
children: /* @__PURE__ */ jsx19(X3, { size: 16, "aria-hidden": true })
|
|
5438
5559
|
}
|
|
5439
5560
|
) }),
|
|
5440
|
-
/* @__PURE__ */
|
|
5441
|
-
/* @__PURE__ */
|
|
5442
|
-
state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */
|
|
5561
|
+
/* @__PURE__ */ jsx19(DialogHeader, { className: "w-full gap-1.5 p-6 pr-12", children: /* @__PURE__ */ jsx19(DialogTitle, { className: "m-0 w-full break-words", children: state.title }) }),
|
|
5562
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
|
|
5563
|
+
state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ jsx19(
|
|
5443
5564
|
DestinationBreadcrumb,
|
|
5444
5565
|
{
|
|
5445
5566
|
pageTitle: state.selectedPage.title,
|
|
5446
5567
|
sectionLabel: state.selectedSection.label
|
|
5447
5568
|
}
|
|
5448
|
-
) : /* @__PURE__ */
|
|
5569
|
+
) : /* @__PURE__ */ jsx19(
|
|
5449
5570
|
UrlOrPageInput,
|
|
5450
5571
|
{
|
|
5451
5572
|
value: state.searchValue,
|
|
@@ -5458,8 +5579,8 @@ function LinkEditorPanel({ state, onClose }) {
|
|
|
5458
5579
|
urlError: state.urlError
|
|
5459
5580
|
}
|
|
5460
5581
|
),
|
|
5461
|
-
state.showChooseSection ? /* @__PURE__ */
|
|
5462
|
-
/* @__PURE__ */
|
|
5582
|
+
state.showChooseSection ? /* @__PURE__ */ jsxs11("div", { className: "flex flex-col justify-center gap-2", children: [
|
|
5583
|
+
/* @__PURE__ */ jsx19(
|
|
5463
5584
|
Button,
|
|
5464
5585
|
{
|
|
5465
5586
|
type: "button",
|
|
@@ -5470,15 +5591,15 @@ function LinkEditorPanel({ state, onClose }) {
|
|
|
5470
5591
|
children: "Choose a section"
|
|
5471
5592
|
}
|
|
5472
5593
|
),
|
|
5473
|
-
/* @__PURE__ */
|
|
5474
|
-
/* @__PURE__ */
|
|
5475
|
-
/* @__PURE__ */
|
|
5594
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
|
|
5595
|
+
/* @__PURE__ */ jsx19(Info, { size: 16, className: "shrink-0", "aria-hidden": true }),
|
|
5596
|
+
/* @__PURE__ */ jsx19("span", { children: "Pick a section this link should scroll to." })
|
|
5476
5597
|
] })
|
|
5477
5598
|
] }) : null,
|
|
5478
|
-
state.showSectionRow && state.selectedSection ? /* @__PURE__ */
|
|
5599
|
+
state.showSectionRow && state.selectedSection ? /* @__PURE__ */ jsx19(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
|
|
5479
5600
|
] }),
|
|
5480
|
-
/* @__PURE__ */
|
|
5481
|
-
/* @__PURE__ */
|
|
5601
|
+
/* @__PURE__ */ jsxs11(DialogFooter, { className: "w-full px-6 pb-6", children: [
|
|
5602
|
+
/* @__PURE__ */ jsx19(
|
|
5482
5603
|
Button,
|
|
5483
5604
|
{
|
|
5484
5605
|
type: "button",
|
|
@@ -5493,7 +5614,7 @@ function LinkEditorPanel({ state, onClose }) {
|
|
|
5493
5614
|
children: state.secondaryLabel
|
|
5494
5615
|
}
|
|
5495
5616
|
),
|
|
5496
|
-
/* @__PURE__ */
|
|
5617
|
+
/* @__PURE__ */ jsx19(
|
|
5497
5618
|
Button,
|
|
5498
5619
|
{
|
|
5499
5620
|
type: "button",
|
|
@@ -5512,11 +5633,11 @@ function LinkEditorPanel({ state, onClose }) {
|
|
|
5512
5633
|
}
|
|
5513
5634
|
|
|
5514
5635
|
// src/ui/link-modal/SectionPickerOverlay.tsx
|
|
5515
|
-
import { useCallback, useEffect as useEffect4, useMemo as useMemo2, useRef as useRef4, useState as useState4 } from "react";
|
|
5636
|
+
import { useCallback as useCallback2, useEffect as useEffect4, useMemo as useMemo2, useRef as useRef4, useState as useState4 } from "react";
|
|
5516
5637
|
import { createPortal } from "react-dom";
|
|
5517
5638
|
import { ArrowLeft, Check } from "lucide-react";
|
|
5518
5639
|
import { usePathname, useRouter } from "next/navigation";
|
|
5519
|
-
import { jsx as
|
|
5640
|
+
import { jsx as jsx20, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
5520
5641
|
var DIM_OVERLAY = "rgba(0, 0, 0, 0.45)";
|
|
5521
5642
|
function rectsEqual(a, b) {
|
|
5522
5643
|
if (a.size !== b.size) return false;
|
|
@@ -5643,7 +5764,7 @@ function SectionPickerOverlay({
|
|
|
5643
5764
|
);
|
|
5644
5765
|
sectionIdsRef.current = sectionIds;
|
|
5645
5766
|
const rects = useSectionRects(sectionIdsKey, isOnTargetPage);
|
|
5646
|
-
const applyHoverAt =
|
|
5767
|
+
const applyHoverAt = useCallback2(
|
|
5647
5768
|
(x, y, liveRects) => {
|
|
5648
5769
|
const ids = sectionIdsRef.current;
|
|
5649
5770
|
const map = liveRects ?? readSectionRects(ids);
|
|
@@ -5723,7 +5844,7 @@ function SectionPickerOverlay({
|
|
|
5723
5844
|
window.removeEventListener("message", onPointerSync);
|
|
5724
5845
|
};
|
|
5725
5846
|
}, [rects, applyHoverAt]);
|
|
5726
|
-
const handleSelect =
|
|
5847
|
+
const handleSelect = useCallback2(
|
|
5727
5848
|
(section) => {
|
|
5728
5849
|
if (selectedId) return;
|
|
5729
5850
|
setSelectedId(section.id);
|
|
@@ -5745,7 +5866,7 @@ function SectionPickerOverlay({
|
|
|
5745
5866
|
const portalRoot = typeof document !== "undefined" ? document.querySelector("[data-ohw-bridge-root]") ?? document.body : null;
|
|
5746
5867
|
if (!portalRoot) return null;
|
|
5747
5868
|
return createPortal(
|
|
5748
|
-
/* @__PURE__ */
|
|
5869
|
+
/* @__PURE__ */ jsxs12(
|
|
5749
5870
|
"div",
|
|
5750
5871
|
{
|
|
5751
5872
|
"data-ohw-section-picker": "",
|
|
@@ -5755,12 +5876,12 @@ function SectionPickerOverlay({
|
|
|
5755
5876
|
role: "dialog",
|
|
5756
5877
|
"aria-label": "Choose a section",
|
|
5757
5878
|
children: [
|
|
5758
|
-
/* @__PURE__ */
|
|
5879
|
+
/* @__PURE__ */ jsx20(
|
|
5759
5880
|
"div",
|
|
5760
5881
|
{
|
|
5761
5882
|
className: "pointer-events-auto fixed left-5 z-[2]",
|
|
5762
5883
|
style: { top: chromeClip.top + 20 },
|
|
5763
|
-
children: /* @__PURE__ */
|
|
5884
|
+
children: /* @__PURE__ */ jsxs12(
|
|
5764
5885
|
Button,
|
|
5765
5886
|
{
|
|
5766
5887
|
type: "button",
|
|
@@ -5769,14 +5890,14 @@ function SectionPickerOverlay({
|
|
|
5769
5890
|
className: "h-8 min-w-0 gap-1 border-border bg-background px-2 py-1.5 shadow-sm hover:bg-muted cursor-pointer",
|
|
5770
5891
|
onClick: onBack,
|
|
5771
5892
|
children: [
|
|
5772
|
-
/* @__PURE__ */
|
|
5893
|
+
/* @__PURE__ */ jsx20(ArrowLeft, { className: "size-4 shrink-0", "aria-hidden": true }),
|
|
5773
5894
|
"Back"
|
|
5774
5895
|
]
|
|
5775
5896
|
}
|
|
5776
5897
|
)
|
|
5777
5898
|
}
|
|
5778
5899
|
),
|
|
5779
|
-
/* @__PURE__ */
|
|
5900
|
+
/* @__PURE__ */ jsx20(
|
|
5780
5901
|
"div",
|
|
5781
5902
|
{
|
|
5782
5903
|
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",
|
|
@@ -5789,7 +5910,7 @@ function SectionPickerOverlay({
|
|
|
5789
5910
|
children: "Click on section to select"
|
|
5790
5911
|
}
|
|
5791
5912
|
),
|
|
5792
|
-
!isOnTargetPage ? /* @__PURE__ */
|
|
5913
|
+
!isOnTargetPage ? /* @__PURE__ */ jsx20(
|
|
5793
5914
|
"div",
|
|
5794
5915
|
{
|
|
5795
5916
|
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",
|
|
@@ -5797,14 +5918,14 @@ function SectionPickerOverlay({
|
|
|
5797
5918
|
children: "Loading page preview\u2026"
|
|
5798
5919
|
}
|
|
5799
5920
|
) : null,
|
|
5800
|
-
isOnTargetPage && liveSections.length === 0 ? /* @__PURE__ */
|
|
5921
|
+
isOnTargetPage && liveSections.length === 0 ? /* @__PURE__ */ jsx20("div", { className: "pointer-events-auto fixed inset-0 z-[1] flex items-center justify-center bg-muted/40", children: /* @__PURE__ */ jsx20("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." }) }) : null,
|
|
5801
5922
|
isOnTargetPage ? liveSections.map((section) => {
|
|
5802
5923
|
const rect = rects.get(section.id);
|
|
5803
5924
|
if (!rect || rect.width <= 0 || rect.height <= 0) return null;
|
|
5804
5925
|
const isSelected = selectedId === section.id;
|
|
5805
5926
|
const isHovered = hoveredId === section.id;
|
|
5806
5927
|
const isLit = isSelected || isHovered;
|
|
5807
|
-
return /* @__PURE__ */
|
|
5928
|
+
return /* @__PURE__ */ jsxs12(
|
|
5808
5929
|
"button",
|
|
5809
5930
|
{
|
|
5810
5931
|
type: "button",
|
|
@@ -5819,7 +5940,7 @@ function SectionPickerOverlay({
|
|
|
5819
5940
|
"aria-label": `Select section ${section.label}`,
|
|
5820
5941
|
onClick: () => handleSelect(section),
|
|
5821
5942
|
children: [
|
|
5822
|
-
isLit ? /* @__PURE__ */
|
|
5943
|
+
isLit ? /* @__PURE__ */ jsx20(
|
|
5823
5944
|
"span",
|
|
5824
5945
|
{
|
|
5825
5946
|
className: "pointer-events-none absolute",
|
|
@@ -5832,13 +5953,13 @@ function SectionPickerOverlay({
|
|
|
5832
5953
|
"aria-hidden": true
|
|
5833
5954
|
}
|
|
5834
5955
|
) : null,
|
|
5835
|
-
isSelected ? /* @__PURE__ */
|
|
5956
|
+
isSelected ? /* @__PURE__ */ jsx20(
|
|
5836
5957
|
"span",
|
|
5837
5958
|
{
|
|
5838
5959
|
className: "absolute right-3 top-3 flex size-8 items-center justify-center rounded-full text-white",
|
|
5839
5960
|
style: { backgroundColor: "var(--ohw-primary, #0885fe)" },
|
|
5840
5961
|
"aria-hidden": true,
|
|
5841
|
-
children: /* @__PURE__ */
|
|
5962
|
+
children: /* @__PURE__ */ jsx20(Check, { className: "size-5" })
|
|
5842
5963
|
}
|
|
5843
5964
|
) : null
|
|
5844
5965
|
]
|
|
@@ -5854,7 +5975,7 @@ function SectionPickerOverlay({
|
|
|
5854
5975
|
}
|
|
5855
5976
|
|
|
5856
5977
|
// src/ui/link-modal/useLinkModalState.ts
|
|
5857
|
-
import { useCallback as
|
|
5978
|
+
import { useCallback as useCallback3, useEffect as useEffect5, useMemo as useMemo3, useState as useState5 } from "react";
|
|
5858
5979
|
function useLinkModalState({
|
|
5859
5980
|
open,
|
|
5860
5981
|
mode,
|
|
@@ -5873,7 +5994,7 @@ function useLinkModalState({
|
|
|
5873
5994
|
const [step, setStep] = useState5("input");
|
|
5874
5995
|
const [dropdownOpen, setDropdownOpen] = useState5(false);
|
|
5875
5996
|
const [urlError, setUrlError] = useState5("");
|
|
5876
|
-
const reset =
|
|
5997
|
+
const reset = useCallback3(() => {
|
|
5877
5998
|
setSearchValue("");
|
|
5878
5999
|
setSelectedPage(null);
|
|
5879
6000
|
setSelectedSection(null);
|
|
@@ -6018,7 +6139,7 @@ function useLinkModalState({
|
|
|
6018
6139
|
}
|
|
6019
6140
|
|
|
6020
6141
|
// src/ui/link-modal/LinkPopover.tsx
|
|
6021
|
-
import { Fragment as Fragment4, jsx as
|
|
6142
|
+
import { Fragment as Fragment4, jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
6022
6143
|
function postToParent(data) {
|
|
6023
6144
|
window.parent?.postMessage(data, "*");
|
|
6024
6145
|
}
|
|
@@ -6114,15 +6235,15 @@ function LinkPopover({
|
|
|
6114
6235
|
);
|
|
6115
6236
|
};
|
|
6116
6237
|
}, [open, sectionPickerActive]);
|
|
6117
|
-
return /* @__PURE__ */
|
|
6118
|
-
/* @__PURE__ */
|
|
6238
|
+
return /* @__PURE__ */ jsxs13(Fragment4, { children: [
|
|
6239
|
+
/* @__PURE__ */ jsx21(
|
|
6119
6240
|
Dialog2,
|
|
6120
6241
|
{
|
|
6121
6242
|
open: open && !sectionPickerActive,
|
|
6122
6243
|
onOpenChange: (next) => {
|
|
6123
6244
|
if (!next) onClose?.();
|
|
6124
6245
|
},
|
|
6125
|
-
children: /* @__PURE__ */
|
|
6246
|
+
children: /* @__PURE__ */ jsx21(
|
|
6126
6247
|
DialogContent,
|
|
6127
6248
|
{
|
|
6128
6249
|
ref: panelRef,
|
|
@@ -6132,12 +6253,12 @@ function LinkPopover({
|
|
|
6132
6253
|
"data-ohw-bridge": "",
|
|
6133
6254
|
showCloseButton: false,
|
|
6134
6255
|
className: "gap-0 p-0 w-full max-w-[448px] pointer-events-auto z-[2147483646] overflow-visible",
|
|
6135
|
-
children: /* @__PURE__ */
|
|
6256
|
+
children: /* @__PURE__ */ jsx21(LinkEditorPanel, { state, onClose })
|
|
6136
6257
|
}
|
|
6137
6258
|
)
|
|
6138
6259
|
}
|
|
6139
6260
|
),
|
|
6140
|
-
sectionPickerActive && state.selectedPage ? /* @__PURE__ */
|
|
6261
|
+
sectionPickerActive && state.selectedPage ? /* @__PURE__ */ jsx21(
|
|
6141
6262
|
SectionPickerOverlay,
|
|
6142
6263
|
{
|
|
6143
6264
|
pagePath: state.selectedPage.path,
|
|
@@ -6443,15 +6564,412 @@ function insertNavbarItem(href, label, afterAnchor = null) {
|
|
|
6443
6564
|
};
|
|
6444
6565
|
}
|
|
6445
6566
|
|
|
6567
|
+
// src/lib/footer-items.ts
|
|
6568
|
+
var FOOTER_ORDER_KEY = "__ohw_footer_order";
|
|
6569
|
+
var FOOTER_HREF_RE = /^footer-(\d+)-(\d+)-href$/;
|
|
6570
|
+
function parseFooterHrefKey(key) {
|
|
6571
|
+
if (!key) return null;
|
|
6572
|
+
const match = key.match(FOOTER_HREF_RE);
|
|
6573
|
+
if (!match) return null;
|
|
6574
|
+
return { col: parseInt(match[1], 10), item: parseInt(match[2], 10) };
|
|
6575
|
+
}
|
|
6576
|
+
function isFooterHrefKey(key) {
|
|
6577
|
+
return parseFooterHrefKey(key) !== null;
|
|
6578
|
+
}
|
|
6579
|
+
function getFooterRoot() {
|
|
6580
|
+
return document.querySelector('footer[data-ohw-section="footer"], footer');
|
|
6581
|
+
}
|
|
6582
|
+
function getFooterLinksContainer() {
|
|
6583
|
+
return document.querySelector("[data-ohw-footer-links]") ?? document.querySelector(".rb-footer-links");
|
|
6584
|
+
}
|
|
6585
|
+
function isFooterLinkAnchor(el) {
|
|
6586
|
+
if (!el.matches("[data-ohw-href-key]")) return false;
|
|
6587
|
+
if (!isFooterHrefKey(el.getAttribute("data-ohw-href-key"))) return false;
|
|
6588
|
+
return Boolean(el.querySelector('[data-ohw-editable="text"]'));
|
|
6589
|
+
}
|
|
6590
|
+
function listFooterColumns() {
|
|
6591
|
+
const root = getFooterLinksContainer() ?? getFooterRoot()?.querySelector(".rb-footer-links") ?? null;
|
|
6592
|
+
if (!root) return [];
|
|
6593
|
+
const explicit = Array.from(root.querySelectorAll(":scope > [data-ohw-footer-col]"));
|
|
6594
|
+
if (explicit.length > 0) return explicit;
|
|
6595
|
+
return Array.from(root.children).filter((el) => {
|
|
6596
|
+
if (!(el instanceof HTMLElement)) return false;
|
|
6597
|
+
return Array.from(el.querySelectorAll(":scope > [data-ohw-href-key]")).some(
|
|
6598
|
+
isFooterLinkAnchor
|
|
6599
|
+
);
|
|
6600
|
+
});
|
|
6601
|
+
}
|
|
6602
|
+
function listFooterLinksInColumn(column) {
|
|
6603
|
+
return Array.from(column.querySelectorAll(":scope > [data-ohw-href-key]")).filter(
|
|
6604
|
+
isFooterLinkAnchor
|
|
6605
|
+
);
|
|
6606
|
+
}
|
|
6607
|
+
function findFooterColumnForLink(anchor) {
|
|
6608
|
+
const columns = listFooterColumns();
|
|
6609
|
+
return columns.find((col) => col.contains(anchor)) ?? null;
|
|
6610
|
+
}
|
|
6611
|
+
function getFooterOrderFromDom() {
|
|
6612
|
+
return listFooterColumns().map(
|
|
6613
|
+
(col) => listFooterLinksInColumn(col).map((el) => el.getAttribute("data-ohw-href-key")).filter((key) => Boolean(key))
|
|
6614
|
+
);
|
|
6615
|
+
}
|
|
6616
|
+
function findFooterLinkByKey(hrefKey) {
|
|
6617
|
+
return document.querySelector(
|
|
6618
|
+
`footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
6619
|
+
);
|
|
6620
|
+
}
|
|
6621
|
+
function syncFooterColumnIndices(columns) {
|
|
6622
|
+
columns.forEach((col, index) => {
|
|
6623
|
+
const next = String(index);
|
|
6624
|
+
if (col.getAttribute("data-ohw-footer-col") !== next) {
|
|
6625
|
+
col.setAttribute("data-ohw-footer-col", next);
|
|
6626
|
+
}
|
|
6627
|
+
});
|
|
6628
|
+
}
|
|
6629
|
+
function appendChildIfNeeded(parent, child) {
|
|
6630
|
+
if (parent.lastElementChild !== child) {
|
|
6631
|
+
parent.appendChild(child);
|
|
6632
|
+
}
|
|
6633
|
+
}
|
|
6634
|
+
function insertLinkBeforeNext(col, el, nextEl) {
|
|
6635
|
+
if (nextEl) {
|
|
6636
|
+
if (el.nextElementSibling !== nextEl) {
|
|
6637
|
+
col.insertBefore(el, nextEl);
|
|
6638
|
+
}
|
|
6639
|
+
return;
|
|
6640
|
+
}
|
|
6641
|
+
if (col.lastElementChild !== el) {
|
|
6642
|
+
col.appendChild(el);
|
|
6643
|
+
}
|
|
6644
|
+
}
|
|
6645
|
+
function applyFooterOrder(order) {
|
|
6646
|
+
const container = getFooterLinksContainer();
|
|
6647
|
+
if (!container) return;
|
|
6648
|
+
const columns = listFooterColumns();
|
|
6649
|
+
if (columns.length === 0) return;
|
|
6650
|
+
const currentOrder = getFooterOrderFromDom();
|
|
6651
|
+
if (ordersEqual(order, currentOrder)) {
|
|
6652
|
+
syncFooterColumnIndices(columns);
|
|
6653
|
+
return;
|
|
6654
|
+
}
|
|
6655
|
+
const colCount = Math.max(columns.length, order.length);
|
|
6656
|
+
const working = columns.slice(0, colCount);
|
|
6657
|
+
for (let i = 0; i < order.length && i < working.length; i++) {
|
|
6658
|
+
appendChildIfNeeded(container, working[i]);
|
|
6659
|
+
}
|
|
6660
|
+
for (let i = order.length; i < working.length; i++) {
|
|
6661
|
+
appendChildIfNeeded(container, working[i]);
|
|
6662
|
+
}
|
|
6663
|
+
const freshColumns = listFooterColumns();
|
|
6664
|
+
syncFooterColumnIndices(freshColumns);
|
|
6665
|
+
for (let c = 0; c < order.length; c++) {
|
|
6666
|
+
const col = freshColumns[c];
|
|
6667
|
+
if (!col) continue;
|
|
6668
|
+
const colOrder = order[c];
|
|
6669
|
+
for (let j = 0; j < colOrder.length; j++) {
|
|
6670
|
+
const hrefKey = colOrder[j];
|
|
6671
|
+
const el = findFooterLinkByKey(hrefKey);
|
|
6672
|
+
if (!el) continue;
|
|
6673
|
+
if (el.parentElement !== col) {
|
|
6674
|
+
col.appendChild(el);
|
|
6675
|
+
}
|
|
6676
|
+
const nextKey = colOrder[j + 1];
|
|
6677
|
+
const nextEl = nextKey ? findFooterLinkByKey(nextKey) : null;
|
|
6678
|
+
insertLinkBeforeNext(col, el, nextEl?.parentElement === col ? nextEl : null);
|
|
6679
|
+
}
|
|
6680
|
+
}
|
|
6681
|
+
}
|
|
6682
|
+
function ordersEqual(a, b) {
|
|
6683
|
+
if (a.length !== b.length) return false;
|
|
6684
|
+
for (let i = 0; i < a.length; i++) {
|
|
6685
|
+
const left = a[i];
|
|
6686
|
+
const right = b[i];
|
|
6687
|
+
if (left.length !== right.length) return false;
|
|
6688
|
+
for (let j = 0; j < left.length; j++) {
|
|
6689
|
+
if (left[j] !== right[j]) return false;
|
|
6690
|
+
}
|
|
6691
|
+
}
|
|
6692
|
+
return true;
|
|
6693
|
+
}
|
|
6694
|
+
function planFooterLinkMove(hrefKey, targetColIndex, insertIndex) {
|
|
6695
|
+
const order = getFooterOrderFromDom();
|
|
6696
|
+
if (targetColIndex < 0 || targetColIndex >= order.length) return null;
|
|
6697
|
+
let fromCol = -1;
|
|
6698
|
+
let fromIdx = -1;
|
|
6699
|
+
for (let c = 0; c < order.length; c++) {
|
|
6700
|
+
const idx = order[c].indexOf(hrefKey);
|
|
6701
|
+
if (idx >= 0) {
|
|
6702
|
+
fromCol = c;
|
|
6703
|
+
fromIdx = idx;
|
|
6704
|
+
break;
|
|
6705
|
+
}
|
|
6706
|
+
}
|
|
6707
|
+
if (fromCol < 0) return null;
|
|
6708
|
+
const next = order.map((col) => [...col]);
|
|
6709
|
+
next[fromCol].splice(fromIdx, 1);
|
|
6710
|
+
let adjusted = insertIndex;
|
|
6711
|
+
if (fromCol === targetColIndex && fromIdx < insertIndex) adjusted -= 1;
|
|
6712
|
+
adjusted = Math.max(0, Math.min(adjusted, next[targetColIndex].length));
|
|
6713
|
+
next[targetColIndex].splice(adjusted, 0, hrefKey);
|
|
6714
|
+
if (ordersEqual(next, order)) return null;
|
|
6715
|
+
return next;
|
|
6716
|
+
}
|
|
6717
|
+
function planFooterColumnMove(fromIndex, toIndex) {
|
|
6718
|
+
const order = getFooterOrderFromDom();
|
|
6719
|
+
const columns = listFooterColumns();
|
|
6720
|
+
if (fromIndex < 0 || fromIndex >= columns.length || toIndex < 0 || toIndex > columns.length) {
|
|
6721
|
+
return null;
|
|
6722
|
+
}
|
|
6723
|
+
if (toIndex === fromIndex || toIndex === fromIndex + 1) return null;
|
|
6724
|
+
const nextOrder = order.map((col) => [...col]);
|
|
6725
|
+
const [movedOrder] = nextOrder.splice(fromIndex, 1);
|
|
6726
|
+
if (!movedOrder) return null;
|
|
6727
|
+
let adjusted = toIndex;
|
|
6728
|
+
if (fromIndex < toIndex) adjusted -= 1;
|
|
6729
|
+
adjusted = Math.max(0, Math.min(adjusted, nextOrder.length));
|
|
6730
|
+
nextOrder.splice(adjusted, 0, movedOrder);
|
|
6731
|
+
if (ordersEqual(nextOrder, order)) return null;
|
|
6732
|
+
return nextOrder;
|
|
6733
|
+
}
|
|
6734
|
+
function parseFooterOrder(content) {
|
|
6735
|
+
const raw = content[FOOTER_ORDER_KEY];
|
|
6736
|
+
if (!raw) return null;
|
|
6737
|
+
try {
|
|
6738
|
+
const parsed = JSON.parse(raw);
|
|
6739
|
+
if (!Array.isArray(parsed)) return null;
|
|
6740
|
+
return parsed.filter((col) => Array.isArray(col)).map((col) => col.filter((key) => typeof key === "string" && key.length > 0));
|
|
6741
|
+
} catch {
|
|
6742
|
+
return null;
|
|
6743
|
+
}
|
|
6744
|
+
}
|
|
6745
|
+
function reconcileFooterOrderFromContent(content) {
|
|
6746
|
+
const order = parseFooterOrder(content);
|
|
6747
|
+
if (!order?.length) return;
|
|
6748
|
+
const current = getFooterOrderFromDom();
|
|
6749
|
+
if (ordersEqual(order, current)) {
|
|
6750
|
+
syncFooterColumnIndices(listFooterColumns());
|
|
6751
|
+
return;
|
|
6752
|
+
}
|
|
6753
|
+
applyFooterOrder(order);
|
|
6754
|
+
}
|
|
6755
|
+
function buildLinkDropSlots(column, columnIndex) {
|
|
6756
|
+
const links = listFooterLinksInColumn(column);
|
|
6757
|
+
const colRect = column.getBoundingClientRect();
|
|
6758
|
+
const slots = [];
|
|
6759
|
+
const barThickness = 3;
|
|
6760
|
+
if (links.length === 0) {
|
|
6761
|
+
slots.push({
|
|
6762
|
+
insertIndex: 0,
|
|
6763
|
+
columnIndex,
|
|
6764
|
+
left: colRect.left,
|
|
6765
|
+
top: colRect.top + colRect.height / 2 - barThickness / 2,
|
|
6766
|
+
width: colRect.width,
|
|
6767
|
+
height: barThickness,
|
|
6768
|
+
direction: "horizontal"
|
|
6769
|
+
});
|
|
6770
|
+
return slots;
|
|
6771
|
+
}
|
|
6772
|
+
for (let i = 0; i <= links.length; i++) {
|
|
6773
|
+
let top;
|
|
6774
|
+
if (i === 0) {
|
|
6775
|
+
top = links[0].getBoundingClientRect().top - barThickness / 2;
|
|
6776
|
+
} else if (i === links.length) {
|
|
6777
|
+
const last = links[links.length - 1].getBoundingClientRect();
|
|
6778
|
+
top = last.bottom - barThickness / 2;
|
|
6779
|
+
} else {
|
|
6780
|
+
const prev = links[i - 1].getBoundingClientRect();
|
|
6781
|
+
const next = links[i].getBoundingClientRect();
|
|
6782
|
+
top = (prev.bottom + next.top) / 2 - barThickness / 2;
|
|
6783
|
+
}
|
|
6784
|
+
const widthRef = i === 0 ? links[0].getBoundingClientRect() : i === links.length ? links[links.length - 1].getBoundingClientRect() : links[i].getBoundingClientRect();
|
|
6785
|
+
slots.push({
|
|
6786
|
+
insertIndex: i,
|
|
6787
|
+
columnIndex,
|
|
6788
|
+
left: widthRef.left,
|
|
6789
|
+
top,
|
|
6790
|
+
width: Math.max(widthRef.width, colRect.width * 0.8),
|
|
6791
|
+
height: barThickness,
|
|
6792
|
+
direction: "horizontal"
|
|
6793
|
+
});
|
|
6794
|
+
}
|
|
6795
|
+
return slots;
|
|
6796
|
+
}
|
|
6797
|
+
function buildColumnDropSlots() {
|
|
6798
|
+
const columns = listFooterColumns();
|
|
6799
|
+
const slots = [];
|
|
6800
|
+
const barThickness = 3;
|
|
6801
|
+
if (columns.length === 0) return slots;
|
|
6802
|
+
for (let i = 0; i <= columns.length; i++) {
|
|
6803
|
+
let left;
|
|
6804
|
+
let height;
|
|
6805
|
+
let top;
|
|
6806
|
+
if (i === 0) {
|
|
6807
|
+
const first = columns[0].getBoundingClientRect();
|
|
6808
|
+
left = first.left - barThickness / 2;
|
|
6809
|
+
top = first.top;
|
|
6810
|
+
height = first.height;
|
|
6811
|
+
} else if (i === columns.length) {
|
|
6812
|
+
const last = columns[columns.length - 1].getBoundingClientRect();
|
|
6813
|
+
left = last.right - barThickness / 2;
|
|
6814
|
+
top = last.top;
|
|
6815
|
+
height = last.height;
|
|
6816
|
+
} else {
|
|
6817
|
+
const prev = columns[i - 1].getBoundingClientRect();
|
|
6818
|
+
const next = columns[i].getBoundingClientRect();
|
|
6819
|
+
left = (prev.right + next.left) / 2 - barThickness / 2;
|
|
6820
|
+
top = Math.min(prev.top, next.top);
|
|
6821
|
+
height = Math.max(prev.bottom, next.bottom) - top;
|
|
6822
|
+
}
|
|
6823
|
+
slots.push({
|
|
6824
|
+
insertIndex: i,
|
|
6825
|
+
columnIndex: i,
|
|
6826
|
+
left,
|
|
6827
|
+
top,
|
|
6828
|
+
width: barThickness,
|
|
6829
|
+
height: Math.max(height, 24),
|
|
6830
|
+
direction: "vertical"
|
|
6831
|
+
});
|
|
6832
|
+
}
|
|
6833
|
+
return slots;
|
|
6834
|
+
}
|
|
6835
|
+
function hitTestLinkDropSlot(clientX, clientY, draggedHrefKey) {
|
|
6836
|
+
const columns = listFooterColumns();
|
|
6837
|
+
let best = null;
|
|
6838
|
+
for (let c = 0; c < columns.length; c++) {
|
|
6839
|
+
const col = columns[c];
|
|
6840
|
+
const colRect = col.getBoundingClientRect();
|
|
6841
|
+
const inColX = clientX >= colRect.left - 24 && clientX <= colRect.right + 24;
|
|
6842
|
+
if (!inColX) continue;
|
|
6843
|
+
const slots = buildLinkDropSlots(col, c).filter((slot) => {
|
|
6844
|
+
const links = listFooterLinksInColumn(col);
|
|
6845
|
+
const fromIdx = links.findIndex(
|
|
6846
|
+
(el) => el.getAttribute("data-ohw-href-key") === draggedHrefKey
|
|
6847
|
+
);
|
|
6848
|
+
if (fromIdx < 0) return true;
|
|
6849
|
+
if (c === findColumnIndexForKey(draggedHrefKey) && (slot.insertIndex === fromIdx || slot.insertIndex === fromIdx + 1)) {
|
|
6850
|
+
return true;
|
|
6851
|
+
}
|
|
6852
|
+
return true;
|
|
6853
|
+
});
|
|
6854
|
+
for (const slot of slots) {
|
|
6855
|
+
const cy = slot.top + slot.height / 2;
|
|
6856
|
+
const dist = Math.abs(clientY - cy) + (inColX ? 0 : 1e3);
|
|
6857
|
+
if (!best || dist < best.dist) best = { slot, dist };
|
|
6858
|
+
}
|
|
6859
|
+
}
|
|
6860
|
+
return best?.slot ?? null;
|
|
6861
|
+
}
|
|
6862
|
+
function findColumnIndexForKey(hrefKey) {
|
|
6863
|
+
const order = getFooterOrderFromDom();
|
|
6864
|
+
for (let c = 0; c < order.length; c++) {
|
|
6865
|
+
if (order[c].includes(hrefKey)) return c;
|
|
6866
|
+
}
|
|
6867
|
+
return -1;
|
|
6868
|
+
}
|
|
6869
|
+
function hitTestColumnDropSlot(clientX, _clientY) {
|
|
6870
|
+
const slots = buildColumnDropSlots();
|
|
6871
|
+
let best = null;
|
|
6872
|
+
for (const slot of slots) {
|
|
6873
|
+
const cx2 = slot.left + slot.width / 2;
|
|
6874
|
+
const dist = Math.abs(clientX - cx2);
|
|
6875
|
+
if (!best || dist < best.dist) best = { slot, dist };
|
|
6876
|
+
}
|
|
6877
|
+
return best?.slot ?? null;
|
|
6878
|
+
}
|
|
6879
|
+
|
|
6880
|
+
// src/lib/carousel.ts
|
|
6881
|
+
import { useEffect as useEffect7, useState as useState6 } from "react";
|
|
6882
|
+
var CAROUSEL_ATTR = "data-ohw-carousel";
|
|
6883
|
+
var CAROUSEL_VALUE_ATTR = "data-ohw-carousel-value";
|
|
6884
|
+
var CAROUSEL_SLIDE_ATTR = "data-ohw-carousel-slide";
|
|
6885
|
+
var CAROUSEL_EVENT = "ohw:carousel-change";
|
|
6886
|
+
function listCarouselKeys() {
|
|
6887
|
+
const keys = /* @__PURE__ */ new Set();
|
|
6888
|
+
document.querySelectorAll(`[${CAROUSEL_ATTR}]`).forEach((el) => {
|
|
6889
|
+
const key = el.getAttribute("data-ohw-key");
|
|
6890
|
+
if (key) keys.add(key);
|
|
6891
|
+
});
|
|
6892
|
+
return [...keys];
|
|
6893
|
+
}
|
|
6894
|
+
function containersForKey(key) {
|
|
6895
|
+
return Array.from(
|
|
6896
|
+
document.querySelectorAll(`[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`)
|
|
6897
|
+
);
|
|
6898
|
+
}
|
|
6899
|
+
function isCarouselKey(key) {
|
|
6900
|
+
return containersForKey(key).length > 0;
|
|
6901
|
+
}
|
|
6902
|
+
function parseSlides(raw) {
|
|
6903
|
+
if (!raw) return [];
|
|
6904
|
+
try {
|
|
6905
|
+
const parsed = JSON.parse(raw);
|
|
6906
|
+
if (!Array.isArray(parsed)) return [];
|
|
6907
|
+
return parsed.filter((s) => Boolean(s) && typeof s === "object").map((s) => ({ src: String(s.src ?? ""), alt: String(s.alt ?? "") }));
|
|
6908
|
+
} catch {
|
|
6909
|
+
return [];
|
|
6910
|
+
}
|
|
6911
|
+
}
|
|
6912
|
+
function readCarouselValue(key) {
|
|
6913
|
+
const container = containersForKey(key)[0];
|
|
6914
|
+
if (!container) return [];
|
|
6915
|
+
const fromAttr = parseSlides(container.getAttribute(CAROUSEL_VALUE_ATTR));
|
|
6916
|
+
if (fromAttr.length > 0) return fromAttr;
|
|
6917
|
+
return Array.from(container.querySelectorAll(`[${CAROUSEL_SLIDE_ATTR}]`)).filter((slide) => slide.closest(`[${CAROUSEL_ATTR}]`) === container).sort((a, b) => slideIndex(a) - slideIndex(b)).map((slide) => {
|
|
6918
|
+
const img = slide instanceof HTMLImageElement ? slide : slide.querySelector("img");
|
|
6919
|
+
return { src: img?.src ?? "", alt: img?.alt ?? "" };
|
|
6920
|
+
});
|
|
6921
|
+
}
|
|
6922
|
+
function slideIndex(el) {
|
|
6923
|
+
const raw = el.getAttribute(CAROUSEL_SLIDE_ATTR);
|
|
6924
|
+
const n = raw ? parseInt(raw, 10) : NaN;
|
|
6925
|
+
return Number.isFinite(n) ? n : 0;
|
|
6926
|
+
}
|
|
6927
|
+
function applyCarouselValue(key, slides) {
|
|
6928
|
+
const value = JSON.stringify(slides);
|
|
6929
|
+
for (const container of containersForKey(key)) {
|
|
6930
|
+
if (container.getAttribute(CAROUSEL_VALUE_ATTR) === value) continue;
|
|
6931
|
+
container.setAttribute(CAROUSEL_VALUE_ATTR, value);
|
|
6932
|
+
container.dispatchEvent(
|
|
6933
|
+
new CustomEvent(CAROUSEL_EVENT, { detail: { images: slides } })
|
|
6934
|
+
);
|
|
6935
|
+
}
|
|
6936
|
+
}
|
|
6937
|
+
function applyCarouselNode(key, val) {
|
|
6938
|
+
if (!isCarouselKey(key)) return false;
|
|
6939
|
+
applyCarouselValue(key, parseSlides(val));
|
|
6940
|
+
return true;
|
|
6941
|
+
}
|
|
6942
|
+
function useOhwCarousel(key, initial) {
|
|
6943
|
+
const [images, setImages] = useState6(initial);
|
|
6944
|
+
useEffect7(() => {
|
|
6945
|
+
const el = document.querySelector(
|
|
6946
|
+
`[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`
|
|
6947
|
+
);
|
|
6948
|
+
if (!el) return;
|
|
6949
|
+
const onChange = (e) => {
|
|
6950
|
+
const detail = e.detail;
|
|
6951
|
+
if (Array.isArray(detail?.images)) setImages(detail.images);
|
|
6952
|
+
};
|
|
6953
|
+
el.addEventListener(CAROUSEL_EVENT, onChange);
|
|
6954
|
+
return () => el.removeEventListener(CAROUSEL_EVENT, onChange);
|
|
6955
|
+
}, [key]);
|
|
6956
|
+
const bind = {
|
|
6957
|
+
[CAROUSEL_ATTR]: "",
|
|
6958
|
+
"data-ohw-key": key,
|
|
6959
|
+
[CAROUSEL_VALUE_ATTR]: JSON.stringify(images)
|
|
6960
|
+
};
|
|
6961
|
+
return { images, setImages, bind };
|
|
6962
|
+
}
|
|
6963
|
+
|
|
6446
6964
|
// src/ui/navbar-container-chrome.tsx
|
|
6447
6965
|
import { Plus as Plus2 } from "lucide-react";
|
|
6448
|
-
import { jsx as
|
|
6966
|
+
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
6449
6967
|
function NavbarContainerChrome({
|
|
6450
6968
|
rect,
|
|
6451
6969
|
onAdd
|
|
6452
6970
|
}) {
|
|
6453
6971
|
const chromeGap = 6;
|
|
6454
|
-
return /* @__PURE__ */
|
|
6972
|
+
return /* @__PURE__ */ jsx22(
|
|
6455
6973
|
"div",
|
|
6456
6974
|
{
|
|
6457
6975
|
"data-ohw-navbar-container-chrome": "",
|
|
@@ -6463,7 +6981,7 @@ function NavbarContainerChrome({
|
|
|
6463
6981
|
width: rect.width + chromeGap * 2,
|
|
6464
6982
|
height: rect.height + chromeGap * 2
|
|
6465
6983
|
},
|
|
6466
|
-
children: /* @__PURE__ */
|
|
6984
|
+
children: /* @__PURE__ */ jsx22(
|
|
6467
6985
|
"button",
|
|
6468
6986
|
{
|
|
6469
6987
|
type: "button",
|
|
@@ -6480,15 +6998,57 @@ function NavbarContainerChrome({
|
|
|
6480
6998
|
e.stopPropagation();
|
|
6481
6999
|
onAdd();
|
|
6482
7000
|
},
|
|
6483
|
-
children: /* @__PURE__ */
|
|
7001
|
+
children: /* @__PURE__ */ jsx22(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
6484
7002
|
}
|
|
6485
7003
|
)
|
|
6486
7004
|
}
|
|
6487
7005
|
);
|
|
6488
7006
|
}
|
|
6489
7007
|
|
|
7008
|
+
// src/ui/drop-indicator.tsx
|
|
7009
|
+
import * as React9 from "react";
|
|
7010
|
+
import { jsx as jsx23 } from "react/jsx-runtime";
|
|
7011
|
+
var dropIndicatorVariants = cva(
|
|
7012
|
+
"ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
|
|
7013
|
+
{
|
|
7014
|
+
variants: {
|
|
7015
|
+
direction: {
|
|
7016
|
+
vertical: "h-6 w-[3px]",
|
|
7017
|
+
horizontal: "h-[3px] w-[200px]"
|
|
7018
|
+
},
|
|
7019
|
+
state: {
|
|
7020
|
+
default: "opacity-0",
|
|
7021
|
+
hover: "opacity-100",
|
|
7022
|
+
dragIdle: "opacity-40",
|
|
7023
|
+
dragActive: "opacity-100"
|
|
7024
|
+
}
|
|
7025
|
+
},
|
|
7026
|
+
defaultVariants: {
|
|
7027
|
+
direction: "vertical",
|
|
7028
|
+
state: "default"
|
|
7029
|
+
}
|
|
7030
|
+
}
|
|
7031
|
+
);
|
|
7032
|
+
var DropIndicator = React9.forwardRef(
|
|
7033
|
+
({ className, direction, state, ...props }, ref) => {
|
|
7034
|
+
return /* @__PURE__ */ jsx23(
|
|
7035
|
+
"div",
|
|
7036
|
+
{
|
|
7037
|
+
ref,
|
|
7038
|
+
"data-slot": "drop-indicator",
|
|
7039
|
+
"data-direction": direction ?? "vertical",
|
|
7040
|
+
"data-state": state ?? "default",
|
|
7041
|
+
"aria-hidden": "true",
|
|
7042
|
+
className: cn(dropIndicatorVariants({ direction, state }), className),
|
|
7043
|
+
...props
|
|
7044
|
+
}
|
|
7045
|
+
);
|
|
7046
|
+
}
|
|
7047
|
+
);
|
|
7048
|
+
DropIndicator.displayName = "DropIndicator";
|
|
7049
|
+
|
|
6490
7050
|
// src/ui/badge.tsx
|
|
6491
|
-
import { jsx as
|
|
7051
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
6492
7052
|
var badgeVariants = cva(
|
|
6493
7053
|
"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",
|
|
6494
7054
|
{
|
|
@@ -6506,12 +7066,12 @@ var badgeVariants = cva(
|
|
|
6506
7066
|
}
|
|
6507
7067
|
);
|
|
6508
7068
|
function Badge({ className, variant, ...props }) {
|
|
6509
|
-
return /* @__PURE__ */
|
|
7069
|
+
return /* @__PURE__ */ jsx24("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
6510
7070
|
}
|
|
6511
7071
|
|
|
6512
7072
|
// src/OhhwellsBridge.tsx
|
|
6513
7073
|
import { Link as Link2 } from "lucide-react";
|
|
6514
|
-
import { Fragment as Fragment5, jsx as
|
|
7074
|
+
import { Fragment as Fragment5, jsx as jsx25, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
6515
7075
|
var PRIMARY2 = "#0885FE";
|
|
6516
7076
|
var IMAGE_FADE_MS = 300;
|
|
6517
7077
|
function runOpacityFade(el, onDone) {
|
|
@@ -6690,7 +7250,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
6690
7250
|
const root = createRoot(container);
|
|
6691
7251
|
flushSync(() => {
|
|
6692
7252
|
root.render(
|
|
6693
|
-
/* @__PURE__ */
|
|
7253
|
+
/* @__PURE__ */ jsx25(
|
|
6694
7254
|
SchedulingWidget,
|
|
6695
7255
|
{
|
|
6696
7256
|
notifyOnConnect,
|
|
@@ -6752,7 +7312,7 @@ function isDragHandleDisabled(el) {
|
|
|
6752
7312
|
return raw === "true" || raw === "";
|
|
6753
7313
|
});
|
|
6754
7314
|
}
|
|
6755
|
-
function collectEditableNodes() {
|
|
7315
|
+
function collectEditableNodes(extraContent) {
|
|
6756
7316
|
const nodes = Array.from(document.querySelectorAll("[data-ohw-editable]")).map((el) => {
|
|
6757
7317
|
if (el.dataset.ohwEditable === "image") {
|
|
6758
7318
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
@@ -6780,6 +7340,14 @@ function collectEditableNodes() {
|
|
|
6780
7340
|
if (!key) return;
|
|
6781
7341
|
nodes.push({ key, type: "link", text: getLinkHref2(el) });
|
|
6782
7342
|
});
|
|
7343
|
+
if (extraContent) {
|
|
7344
|
+
for (const key of [NAV_ORDER_KEY, FOOTER_ORDER_KEY, NAV_COUNT_KEY]) {
|
|
7345
|
+
const text = extraContent[key];
|
|
7346
|
+
if (typeof text === "string" && text.length > 0) {
|
|
7347
|
+
nodes.push({ key, type: "meta", text });
|
|
7348
|
+
}
|
|
7349
|
+
}
|
|
7350
|
+
}
|
|
6783
7351
|
document.querySelectorAll('[data-ohw-editable="video"]').forEach((el) => {
|
|
6784
7352
|
const key = el.dataset.ohwKey ?? "";
|
|
6785
7353
|
const video = getVideoEl(el);
|
|
@@ -6787,13 +7355,10 @@ function collectEditableNodes() {
|
|
|
6787
7355
|
nodes.push({ key: `${key}${VIDEO_AUTOPLAY_SUFFIX}`, type: "video-setting", text: String(video.autoplay) });
|
|
6788
7356
|
nodes.push({ key: `${key}${VIDEO_MUTED_SUFFIX}`, type: "video-setting", text: String(video.muted) });
|
|
6789
7357
|
});
|
|
6790
|
-
const
|
|
6791
|
-
|
|
6792
|
-
|
|
6793
|
-
|
|
6794
|
-
seen.add(node.key);
|
|
6795
|
-
return true;
|
|
6796
|
-
});
|
|
7358
|
+
for (const key of listCarouselKeys()) {
|
|
7359
|
+
nodes.push({ key, type: "carousel", text: JSON.stringify(readCarouselValue(key)) });
|
|
7360
|
+
}
|
|
7361
|
+
return nodes;
|
|
6797
7362
|
}
|
|
6798
7363
|
function isMediaEditable(el) {
|
|
6799
7364
|
const t = el.dataset.ohwEditable;
|
|
@@ -6881,6 +7446,29 @@ function getHrefKeyFromElement(el) {
|
|
|
6881
7446
|
if (!key) return null;
|
|
6882
7447
|
return { anchor, key };
|
|
6883
7448
|
}
|
|
7449
|
+
function disableNativeHrefDrag(el) {
|
|
7450
|
+
if (el.draggable) el.draggable = false;
|
|
7451
|
+
if (el.getAttribute("draggable") !== "false") {
|
|
7452
|
+
el.setAttribute("draggable", "false");
|
|
7453
|
+
}
|
|
7454
|
+
}
|
|
7455
|
+
function clearTextSelection() {
|
|
7456
|
+
const sel = window.getSelection();
|
|
7457
|
+
if (sel && !sel.isCollapsed) sel.removeAllRanges();
|
|
7458
|
+
}
|
|
7459
|
+
function armFooterPressDrag() {
|
|
7460
|
+
document.documentElement.setAttribute("data-ohw-footer-press-drag", "");
|
|
7461
|
+
}
|
|
7462
|
+
function lockFooterDuringDrag() {
|
|
7463
|
+
document.documentElement.removeAttribute("data-ohw-footer-press-drag");
|
|
7464
|
+
document.documentElement.setAttribute("data-ohw-item-dragging", "");
|
|
7465
|
+
clearTextSelection();
|
|
7466
|
+
}
|
|
7467
|
+
function unlockFooterDragInteraction() {
|
|
7468
|
+
document.documentElement.removeAttribute("data-ohw-footer-press-drag");
|
|
7469
|
+
document.documentElement.removeAttribute("data-ohw-item-dragging");
|
|
7470
|
+
clearTextSelection();
|
|
7471
|
+
}
|
|
6884
7472
|
function isNavbarButton2(el) {
|
|
6885
7473
|
return Boolean(el.closest('[data-ohw-role="navbar-button"]'));
|
|
6886
7474
|
}
|
|
@@ -6943,7 +7531,7 @@ function isInferredFooterGroup(el) {
|
|
|
6943
7531
|
return Array.from(el.querySelectorAll(":scope > [data-ohw-href-key]")).some(isNavigationItem);
|
|
6944
7532
|
}
|
|
6945
7533
|
function isNavigationContainer(el) {
|
|
6946
|
-
return el.hasAttribute("data-ohw-nav-container") || isNavigationRoot(el) || isInferredFooterGroup(el);
|
|
7534
|
+
return el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-footer-col") || isNavigationRoot(el) || isInferredFooterGroup(el);
|
|
6947
7535
|
}
|
|
6948
7536
|
function isPointOverNavigation(x, y) {
|
|
6949
7537
|
const navRoot = document.querySelector("[data-ohw-nav-root]") ?? document.querySelector("nav");
|
|
@@ -7153,6 +7741,8 @@ var ICONS = {
|
|
|
7153
7741
|
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"/>',
|
|
7154
7742
|
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"/>'
|
|
7155
7743
|
};
|
|
7744
|
+
var TOOLBAR_PILL_PADDING = 2;
|
|
7745
|
+
var TOOLBAR_TOGGLE_GAP = 4;
|
|
7156
7746
|
var TOOLBAR_GROUPS = [
|
|
7157
7747
|
[
|
|
7158
7748
|
{ cmd: "bold", title: "Bold" },
|
|
@@ -7177,7 +7767,7 @@ function EditGlowChrome({
|
|
|
7177
7767
|
dragDisabled = false
|
|
7178
7768
|
}) {
|
|
7179
7769
|
const GAP = 6;
|
|
7180
|
-
return /* @__PURE__ */
|
|
7770
|
+
return /* @__PURE__ */ jsxs14(
|
|
7181
7771
|
"div",
|
|
7182
7772
|
{
|
|
7183
7773
|
ref: elRef,
|
|
@@ -7192,7 +7782,7 @@ function EditGlowChrome({
|
|
|
7192
7782
|
zIndex: 2147483646
|
|
7193
7783
|
},
|
|
7194
7784
|
children: [
|
|
7195
|
-
/* @__PURE__ */
|
|
7785
|
+
/* @__PURE__ */ jsx25(
|
|
7196
7786
|
"div",
|
|
7197
7787
|
{
|
|
7198
7788
|
style: {
|
|
@@ -7205,7 +7795,7 @@ function EditGlowChrome({
|
|
|
7205
7795
|
}
|
|
7206
7796
|
}
|
|
7207
7797
|
),
|
|
7208
|
-
reorderHrefKey && /* @__PURE__ */
|
|
7798
|
+
reorderHrefKey && /* @__PURE__ */ jsx25(
|
|
7209
7799
|
"div",
|
|
7210
7800
|
{
|
|
7211
7801
|
"data-ohw-drag-handle-container": "",
|
|
@@ -7217,7 +7807,7 @@ function EditGlowChrome({
|
|
|
7217
7807
|
transform: "translate(calc(-100% - 7px), -50%)",
|
|
7218
7808
|
pointerEvents: dragDisabled ? "none" : "auto"
|
|
7219
7809
|
},
|
|
7220
|
-
children: /* @__PURE__ */
|
|
7810
|
+
children: /* @__PURE__ */ jsx25(
|
|
7221
7811
|
DragHandle,
|
|
7222
7812
|
{
|
|
7223
7813
|
"aria-label": `Reorder ${reorderHrefKey}`,
|
|
@@ -7321,7 +7911,7 @@ function FloatingToolbar({
|
|
|
7321
7911
|
onEditLink
|
|
7322
7912
|
}) {
|
|
7323
7913
|
const { top, left, transform } = calcToolbarPos(rect, parentScroll, 330);
|
|
7324
|
-
return /* @__PURE__ */
|
|
7914
|
+
return /* @__PURE__ */ jsx25(
|
|
7325
7915
|
"div",
|
|
7326
7916
|
{
|
|
7327
7917
|
ref: elRef,
|
|
@@ -7331,14 +7921,23 @@ function FloatingToolbar({
|
|
|
7331
7921
|
left,
|
|
7332
7922
|
transform,
|
|
7333
7923
|
zIndex: 2147483647,
|
|
7924
|
+
background: "#fff",
|
|
7925
|
+
border: "1px solid #E7E5E4",
|
|
7926
|
+
borderRadius: 6,
|
|
7927
|
+
boxShadow: "0px 2px 4px -2px rgba(0,0,0,.1),0px 4px 6px -1px rgba(0,0,0,.1)",
|
|
7928
|
+
display: "flex",
|
|
7929
|
+
alignItems: "center",
|
|
7930
|
+
padding: TOOLBAR_PILL_PADDING,
|
|
7931
|
+
gap: TOOLBAR_TOGGLE_GAP,
|
|
7932
|
+
fontFamily: "sans-serif",
|
|
7334
7933
|
pointerEvents: "auto"
|
|
7335
7934
|
},
|
|
7336
|
-
children: /* @__PURE__ */
|
|
7337
|
-
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */
|
|
7338
|
-
gi > 0 && /* @__PURE__ */
|
|
7935
|
+
children: /* @__PURE__ */ jsxs14(CustomToolbar, { children: [
|
|
7936
|
+
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs14(React10.Fragment, { children: [
|
|
7937
|
+
gi > 0 && /* @__PURE__ */ jsx25(CustomToolbarDivider, {}),
|
|
7339
7938
|
btns.map((btn) => {
|
|
7340
7939
|
const isActive = activeCommands.has(btn.cmd);
|
|
7341
|
-
return /* @__PURE__ */
|
|
7940
|
+
return /* @__PURE__ */ jsx25(
|
|
7342
7941
|
CustomToolbarButton,
|
|
7343
7942
|
{
|
|
7344
7943
|
title: btn.title,
|
|
@@ -7347,7 +7946,7 @@ function FloatingToolbar({
|
|
|
7347
7946
|
e.preventDefault();
|
|
7348
7947
|
onCommand(btn.cmd);
|
|
7349
7948
|
},
|
|
7350
|
-
children: /* @__PURE__ */
|
|
7949
|
+
children: /* @__PURE__ */ jsx25(
|
|
7351
7950
|
"svg",
|
|
7352
7951
|
{
|
|
7353
7952
|
width: "16",
|
|
@@ -7368,7 +7967,7 @@ function FloatingToolbar({
|
|
|
7368
7967
|
);
|
|
7369
7968
|
})
|
|
7370
7969
|
] }, gi)),
|
|
7371
|
-
showEditLink ? /* @__PURE__ */
|
|
7970
|
+
showEditLink ? /* @__PURE__ */ jsx25(
|
|
7372
7971
|
CustomToolbarButton,
|
|
7373
7972
|
{
|
|
7374
7973
|
type: "button",
|
|
@@ -7382,7 +7981,7 @@ function FloatingToolbar({
|
|
|
7382
7981
|
e.preventDefault();
|
|
7383
7982
|
e.stopPropagation();
|
|
7384
7983
|
},
|
|
7385
|
-
children: /* @__PURE__ */
|
|
7984
|
+
children: /* @__PURE__ */ jsx25(Link2, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
7386
7985
|
}
|
|
7387
7986
|
) : null
|
|
7388
7987
|
] })
|
|
@@ -7399,7 +7998,7 @@ function StateToggle({
|
|
|
7399
7998
|
states,
|
|
7400
7999
|
onStateChange
|
|
7401
8000
|
}) {
|
|
7402
|
-
return /* @__PURE__ */
|
|
8001
|
+
return /* @__PURE__ */ jsx25(
|
|
7403
8002
|
ToggleGroup,
|
|
7404
8003
|
{
|
|
7405
8004
|
"data-ohw-state-toggle": "",
|
|
@@ -7413,7 +8012,7 @@ function StateToggle({
|
|
|
7413
8012
|
left: rect.right - 8,
|
|
7414
8013
|
transform: "translateX(-100%)"
|
|
7415
8014
|
},
|
|
7416
|
-
children: states.map((state) => /* @__PURE__ */
|
|
8015
|
+
children: states.map((state) => /* @__PURE__ */ jsx25(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
|
|
7417
8016
|
}
|
|
7418
8017
|
);
|
|
7419
8018
|
}
|
|
@@ -7440,8 +8039,8 @@ function OhhwellsBridge() {
|
|
|
7440
8039
|
const router = useRouter2();
|
|
7441
8040
|
const searchParams = useSearchParams();
|
|
7442
8041
|
const isEditMode = isEditSessionActive();
|
|
7443
|
-
const [bridgeRoot, setBridgeRoot] =
|
|
7444
|
-
|
|
8042
|
+
const [bridgeRoot, setBridgeRoot] = useState7(null);
|
|
8043
|
+
useEffect8(() => {
|
|
7445
8044
|
const figtreeFontId = "ohw-figtree-font";
|
|
7446
8045
|
if (!document.getElementById(figtreeFontId)) {
|
|
7447
8046
|
const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
|
|
@@ -7469,12 +8068,12 @@ function OhhwellsBridge() {
|
|
|
7469
8068
|
const subdomainFromQuery = searchParams.get("subdomain");
|
|
7470
8069
|
const subdomain = resolveSubdomain(subdomainFromQuery);
|
|
7471
8070
|
useLinkHrefGuardian(pathname, subdomain, isEditMode);
|
|
7472
|
-
const postToParent2 =
|
|
8071
|
+
const postToParent2 = useCallback4((data) => {
|
|
7473
8072
|
if (typeof window !== "undefined" && window.parent !== window) {
|
|
7474
8073
|
window.parent.postMessage(data, "*");
|
|
7475
8074
|
}
|
|
7476
8075
|
}, []);
|
|
7477
|
-
const [fetchState, setFetchState] =
|
|
8076
|
+
const [fetchState, setFetchState] = useState7("idle");
|
|
7478
8077
|
const autoSaveTimers = useRef5(/* @__PURE__ */ new Map());
|
|
7479
8078
|
const activeElRef = useRef5(null);
|
|
7480
8079
|
const selectedElRef = useRef5(null);
|
|
@@ -7482,8 +8081,8 @@ function OhhwellsBridge() {
|
|
|
7482
8081
|
const activeStateElRef = useRef5(null);
|
|
7483
8082
|
const parentScrollRef = useRef5(null);
|
|
7484
8083
|
const visibleViewportRef = useRef5(null);
|
|
7485
|
-
const [dialogPortalContainer, setDialogPortalContainer] =
|
|
7486
|
-
const attachVisibleViewport =
|
|
8084
|
+
const [dialogPortalContainer, setDialogPortalContainer] = useState7(null);
|
|
8085
|
+
const attachVisibleViewport = useCallback4((node) => {
|
|
7487
8086
|
visibleViewportRef.current = node;
|
|
7488
8087
|
setDialogPortalContainer(node);
|
|
7489
8088
|
if (node) applyVisibleViewport(node, parentScrollRef.current);
|
|
@@ -7493,8 +8092,10 @@ function OhhwellsBridge() {
|
|
|
7493
8092
|
const hoveredImageRef = useRef5(null);
|
|
7494
8093
|
const hoveredImageHasTextOverlapRef = useRef5(false);
|
|
7495
8094
|
const dragOverElRef = useRef5(null);
|
|
7496
|
-
const [mediaHover, setMediaHover] =
|
|
7497
|
-
const [
|
|
8095
|
+
const [mediaHover, setMediaHover] = useState7(null);
|
|
8096
|
+
const [carouselHover, setCarouselHover] = useState7(null);
|
|
8097
|
+
const [uploadingRects, setUploadingRects] = useState7({});
|
|
8098
|
+
const pendingUploadRectRef = useRef5(null);
|
|
7498
8099
|
const hoveredGapRef = useRef5(null);
|
|
7499
8100
|
const imageUnhoverTimerRef = useRef5(null);
|
|
7500
8101
|
const imageShowTimerRef = useRef5(null);
|
|
@@ -7519,30 +8120,38 @@ function OhhwellsBridge() {
|
|
|
7519
8120
|
postToParentRef.current = postToParent2;
|
|
7520
8121
|
const sectionsLoadedRef = useRef5(false);
|
|
7521
8122
|
const pendingScheduleConfigRequests = useRef5([]);
|
|
7522
|
-
const [toolbarRect, setToolbarRect] =
|
|
7523
|
-
const [toolbarVariant, setToolbarVariant] =
|
|
8123
|
+
const [toolbarRect, setToolbarRect] = useState7(null);
|
|
8124
|
+
const [toolbarVariant, setToolbarVariant] = useState7("none");
|
|
7524
8125
|
const toolbarVariantRef = useRef5("none");
|
|
7525
8126
|
toolbarVariantRef.current = toolbarVariant;
|
|
7526
|
-
const [reorderHrefKey, setReorderHrefKey] =
|
|
7527
|
-
const [reorderDragDisabled, setReorderDragDisabled] =
|
|
7528
|
-
const [toggleState, setToggleState] =
|
|
7529
|
-
const [maxBadge, setMaxBadge] =
|
|
7530
|
-
const [activeCommands, setActiveCommands] =
|
|
7531
|
-
const [sectionGap, setSectionGap] =
|
|
7532
|
-
const [toolbarShowEditLink, setToolbarShowEditLink] =
|
|
8127
|
+
const [reorderHrefKey, setReorderHrefKey] = useState7(null);
|
|
8128
|
+
const [reorderDragDisabled, setReorderDragDisabled] = useState7(false);
|
|
8129
|
+
const [toggleState, setToggleState] = useState7(null);
|
|
8130
|
+
const [maxBadge, setMaxBadge] = useState7(null);
|
|
8131
|
+
const [activeCommands, setActiveCommands] = useState7(/* @__PURE__ */ new Set());
|
|
8132
|
+
const [sectionGap, setSectionGap] = useState7(null);
|
|
8133
|
+
const [toolbarShowEditLink, setToolbarShowEditLink] = useState7(false);
|
|
7533
8134
|
const hoveredNavContainerRef = useRef5(null);
|
|
7534
|
-
const [hoveredNavContainerRect, setHoveredNavContainerRect] =
|
|
8135
|
+
const [hoveredNavContainerRect, setHoveredNavContainerRect] = useState7(null);
|
|
7535
8136
|
const hoveredItemElRef = useRef5(null);
|
|
7536
|
-
const [hoveredItemRect, setHoveredItemRect] =
|
|
8137
|
+
const [hoveredItemRect, setHoveredItemRect] = useState7(null);
|
|
7537
8138
|
const siblingHintElRef = useRef5(null);
|
|
7538
|
-
const [siblingHintRect, setSiblingHintRect] =
|
|
7539
|
-
const [
|
|
7540
|
-
const [
|
|
8139
|
+
const [siblingHintRect, setSiblingHintRect] = useState7(null);
|
|
8140
|
+
const [siblingHintRects, setSiblingHintRects] = useState7([]);
|
|
8141
|
+
const [isItemDragging, setIsItemDragging] = useState7(false);
|
|
8142
|
+
const [isFooterFrameSelection, setIsFooterFrameSelection] = useState7(false);
|
|
8143
|
+
const footerDragRef = useRef5(null);
|
|
8144
|
+
const [footerDropSlots, setFooterDropSlots] = useState7([]);
|
|
8145
|
+
const [activeFooterDropIndex, setActiveFooterDropIndex] = useState7(null);
|
|
8146
|
+
const [draggedItemRect, setDraggedItemRect] = useState7(null);
|
|
8147
|
+
const footerPointerDragRef = useRef5(null);
|
|
8148
|
+
const suppressNextClickRef = useRef5(false);
|
|
8149
|
+
const [linkPopover, setLinkPopover] = useState7(null);
|
|
7541
8150
|
const linkPopoverSessionRef = useRef5(null);
|
|
7542
8151
|
const addNavAfterAnchorRef = useRef5(null);
|
|
7543
8152
|
const editContentRef = useRef5({});
|
|
7544
|
-
const [sitePages, setSitePages] =
|
|
7545
|
-
const [sectionsByPath, setSectionsByPath] =
|
|
8153
|
+
const [sitePages, setSitePages] = useState7([]);
|
|
8154
|
+
const [sectionsByPath, setSectionsByPath] = useState7({});
|
|
7546
8155
|
const sectionsPrefetchGenRef = useRef5(0);
|
|
7547
8156
|
const setLinkPopoverRef = useRef5(setLinkPopover);
|
|
7548
8157
|
const linkPopoverPanelRef = useRef5(null);
|
|
@@ -7553,7 +8162,7 @@ function OhhwellsBridge() {
|
|
|
7553
8162
|
const bumpLinkPopoverGrace = () => {
|
|
7554
8163
|
linkPopoverGraceUntilRef.current = Date.now() + 350;
|
|
7555
8164
|
};
|
|
7556
|
-
const runSectionsPrefetch =
|
|
8165
|
+
const runSectionsPrefetch = useCallback4((pages) => {
|
|
7557
8166
|
if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
|
|
7558
8167
|
const gen = ++sectionsPrefetchGenRef.current;
|
|
7559
8168
|
const paths = pages.map((p) => p.path);
|
|
@@ -7574,8 +8183,12 @@ function OhhwellsBridge() {
|
|
|
7574
8183
|
}, [isEditMode, pathname]);
|
|
7575
8184
|
const runSectionsPrefetchRef = useRef5(runSectionsPrefetch);
|
|
7576
8185
|
runSectionsPrefetchRef.current = runSectionsPrefetch;
|
|
7577
|
-
|
|
7578
|
-
if (!linkPopover)
|
|
8186
|
+
useEffect8(() => {
|
|
8187
|
+
if (!linkPopover) {
|
|
8188
|
+
document.documentElement.removeAttribute("data-ohw-link-popover-open");
|
|
8189
|
+
return;
|
|
8190
|
+
}
|
|
8191
|
+
document.documentElement.setAttribute("data-ohw-link-popover-open", "");
|
|
7579
8192
|
if (hoveredImageRef.current) {
|
|
7580
8193
|
hoveredImageRef.current = null;
|
|
7581
8194
|
hoveredImageHasTextOverlapRef.current = false;
|
|
@@ -7602,14 +8215,10 @@ function OhhwellsBridge() {
|
|
|
7602
8215
|
document.addEventListener("touchmove", preventBackgroundScroll, scrollOpts);
|
|
7603
8216
|
postToParent2({ type: "ow:image-unhover" });
|
|
7604
8217
|
return () => {
|
|
7605
|
-
|
|
7606
|
-
html.style.overflow = prevHtmlOverflow;
|
|
7607
|
-
body.style.overflow = prevBodyOverflow;
|
|
7608
|
-
document.removeEventListener("wheel", preventBackgroundScroll, scrollOpts);
|
|
7609
|
-
document.removeEventListener("touchmove", preventBackgroundScroll, scrollOpts);
|
|
8218
|
+
document.documentElement.removeAttribute("data-ohw-link-popover-open");
|
|
7610
8219
|
};
|
|
7611
8220
|
}, [linkPopover, postToParent2]);
|
|
7612
|
-
|
|
8221
|
+
useEffect8(() => {
|
|
7613
8222
|
if (!isEditMode) return;
|
|
7614
8223
|
const useFixtures = shouldUseDevFixtures();
|
|
7615
8224
|
if (useFixtures) {
|
|
@@ -7633,14 +8242,14 @@ function OhhwellsBridge() {
|
|
|
7633
8242
|
if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
|
|
7634
8243
|
return () => window.removeEventListener("message", onSitePages);
|
|
7635
8244
|
}, [isEditMode, postToParent2]);
|
|
7636
|
-
|
|
8245
|
+
useEffect8(() => {
|
|
7637
8246
|
if (!isEditMode || shouldUseDevFixtures()) return;
|
|
7638
8247
|
void loadAllSectionsManifest().then((manifest) => {
|
|
7639
8248
|
if (Object.keys(manifest).length === 0) return;
|
|
7640
8249
|
setSectionsByPath((prev) => ({ ...manifest, ...prev }));
|
|
7641
8250
|
});
|
|
7642
8251
|
}, [isEditMode]);
|
|
7643
|
-
|
|
8252
|
+
useEffect8(() => {
|
|
7644
8253
|
const update = () => {
|
|
7645
8254
|
const el = activeElRef.current ?? selectedElRef.current;
|
|
7646
8255
|
if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
@@ -7664,10 +8273,10 @@ function OhhwellsBridge() {
|
|
|
7664
8273
|
vvp.removeEventListener("resize", update);
|
|
7665
8274
|
};
|
|
7666
8275
|
}, []);
|
|
7667
|
-
const refreshStateRules =
|
|
8276
|
+
const refreshStateRules = useCallback4(() => {
|
|
7668
8277
|
editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
|
|
7669
8278
|
}, []);
|
|
7670
|
-
const processConfigRequest =
|
|
8279
|
+
const processConfigRequest = useCallback4((insertAfterVal) => {
|
|
7671
8280
|
const tracker = getSectionsTracker();
|
|
7672
8281
|
let entries = [];
|
|
7673
8282
|
try {
|
|
@@ -7690,7 +8299,7 @@ function OhhwellsBridge() {
|
|
|
7690
8299
|
}
|
|
7691
8300
|
window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
|
|
7692
8301
|
}, [isEditMode]);
|
|
7693
|
-
const deactivate =
|
|
8302
|
+
const deactivate = useCallback4(() => {
|
|
7694
8303
|
const el = activeElRef.current;
|
|
7695
8304
|
if (!el) return;
|
|
7696
8305
|
const key = el.dataset.ohwKey;
|
|
@@ -7721,12 +8330,14 @@ function OhhwellsBridge() {
|
|
|
7721
8330
|
setToolbarShowEditLink(false);
|
|
7722
8331
|
postToParent2({ type: "ow:exit-edit" });
|
|
7723
8332
|
}, [postToParent2]);
|
|
7724
|
-
const deselect =
|
|
8333
|
+
const deselect = useCallback4(() => {
|
|
7725
8334
|
selectedElRef.current = null;
|
|
7726
8335
|
setReorderHrefKey(null);
|
|
7727
8336
|
setReorderDragDisabled(false);
|
|
8337
|
+
setIsFooterFrameSelection(false);
|
|
7728
8338
|
siblingHintElRef.current = null;
|
|
7729
8339
|
setSiblingHintRect(null);
|
|
8340
|
+
setSiblingHintRects([]);
|
|
7730
8341
|
setIsItemDragging(false);
|
|
7731
8342
|
hoveredNavContainerRef.current = null;
|
|
7732
8343
|
setHoveredNavContainerRect(null);
|
|
@@ -7735,7 +8346,7 @@ function OhhwellsBridge() {
|
|
|
7735
8346
|
setToolbarVariant("none");
|
|
7736
8347
|
}
|
|
7737
8348
|
}, []);
|
|
7738
|
-
const reselectNavigationItem =
|
|
8349
|
+
const reselectNavigationItem = useCallback4((navAnchor) => {
|
|
7739
8350
|
selectedElRef.current = navAnchor;
|
|
7740
8351
|
const { key, disabled } = getNavigationItemReorderState(navAnchor);
|
|
7741
8352
|
setReorderHrefKey(key);
|
|
@@ -7745,7 +8356,7 @@ function OhhwellsBridge() {
|
|
|
7745
8356
|
setToolbarShowEditLink(false);
|
|
7746
8357
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
7747
8358
|
}, []);
|
|
7748
|
-
const commitNavigationTextEdit =
|
|
8359
|
+
const commitNavigationTextEdit = useCallback4((navAnchor) => {
|
|
7749
8360
|
const el = activeElRef.current;
|
|
7750
8361
|
if (!el) return;
|
|
7751
8362
|
const key = el.dataset.ohwKey;
|
|
@@ -7771,7 +8382,7 @@ function OhhwellsBridge() {
|
|
|
7771
8382
|
postToParent2({ type: "ow:exit-edit" });
|
|
7772
8383
|
reselectNavigationItem(navAnchor);
|
|
7773
8384
|
}, [postToParent2, reselectNavigationItem]);
|
|
7774
|
-
const handleAddTopLevelNavItem =
|
|
8385
|
+
const handleAddTopLevelNavItem = useCallback4(() => {
|
|
7775
8386
|
const items = listNavbarItems();
|
|
7776
8387
|
addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
|
|
7777
8388
|
deselectRef.current();
|
|
@@ -7783,90 +8394,387 @@ function OhhwellsBridge() {
|
|
|
7783
8394
|
intent: "add-nav"
|
|
7784
8395
|
});
|
|
7785
8396
|
}, []);
|
|
7786
|
-
const
|
|
7787
|
-
|
|
7788
|
-
|
|
7789
|
-
|
|
7790
|
-
|
|
7791
|
-
|
|
8397
|
+
const clearFooterDragVisuals = useCallback4(() => {
|
|
8398
|
+
footerDragRef.current = null;
|
|
8399
|
+
setSiblingHintRects([]);
|
|
8400
|
+
setFooterDropSlots([]);
|
|
8401
|
+
setActiveFooterDropIndex(null);
|
|
8402
|
+
setDraggedItemRect(null);
|
|
7792
8403
|
setIsItemDragging(false);
|
|
8404
|
+
unlockFooterDragInteraction();
|
|
7793
8405
|
}, []);
|
|
7794
|
-
|
|
7795
|
-
|
|
7796
|
-
|
|
7797
|
-
if (
|
|
7798
|
-
|
|
7799
|
-
|
|
7800
|
-
clearHrefKeyHover(anchor);
|
|
7801
|
-
hoveredNavContainerRef.current = null;
|
|
7802
|
-
setHoveredNavContainerRect(null);
|
|
7803
|
-
setHoveredItemRect(null);
|
|
7804
|
-
hoveredItemElRef.current = null;
|
|
7805
|
-
siblingHintElRef.current = null;
|
|
7806
|
-
setSiblingHintRect(null);
|
|
7807
|
-
setIsItemDragging(false);
|
|
7808
|
-
const { key, disabled } = getNavigationItemReorderState(anchor);
|
|
7809
|
-
setReorderHrefKey(key);
|
|
7810
|
-
setReorderDragDisabled(disabled);
|
|
7811
|
-
setToolbarVariant("link-action");
|
|
7812
|
-
setToolbarRect(anchor.getBoundingClientRect());
|
|
7813
|
-
setToolbarShowEditLink(false);
|
|
7814
|
-
setActiveCommands(/* @__PURE__ */ new Set());
|
|
7815
|
-
}, [deactivate]);
|
|
7816
|
-
const selectFrame = useCallback3((el) => {
|
|
7817
|
-
if (!isNavigationContainer(el)) return;
|
|
7818
|
-
if (activeElRef.current) deactivate();
|
|
7819
|
-
selectedElRef.current = el;
|
|
7820
|
-
clearHrefKeyHover(el);
|
|
7821
|
-
hoveredNavContainerRef.current = null;
|
|
7822
|
-
setHoveredNavContainerRect(null);
|
|
7823
|
-
setHoveredItemRect(null);
|
|
7824
|
-
hoveredItemElRef.current = null;
|
|
7825
|
-
siblingHintElRef.current = null;
|
|
7826
|
-
setSiblingHintRect(null);
|
|
7827
|
-
setIsItemDragging(false);
|
|
7828
|
-
setReorderHrefKey(null);
|
|
7829
|
-
setReorderDragDisabled(false);
|
|
7830
|
-
setToolbarVariant("select-frame");
|
|
7831
|
-
setToolbarRect(el.getBoundingClientRect());
|
|
7832
|
-
setToolbarShowEditLink(false);
|
|
7833
|
-
setActiveCommands(/* @__PURE__ */ new Set());
|
|
7834
|
-
}, [deactivate]);
|
|
7835
|
-
const activate = useCallback3((el, options) => {
|
|
7836
|
-
if (activeElRef.current === el) return;
|
|
7837
|
-
selectedElRef.current = null;
|
|
7838
|
-
deactivate();
|
|
7839
|
-
if (hoveredImageRef.current) {
|
|
7840
|
-
hoveredImageRef.current = null;
|
|
7841
|
-
setMediaHover(null);
|
|
7842
|
-
}
|
|
7843
|
-
setToolbarVariant("rich-text");
|
|
7844
|
-
siblingHintElRef.current = null;
|
|
7845
|
-
setSiblingHintRect(null);
|
|
7846
|
-
setIsItemDragging(false);
|
|
7847
|
-
el.setAttribute("contenteditable", "true");
|
|
7848
|
-
el.removeAttribute("data-ohw-hovered");
|
|
7849
|
-
el.closest("[data-ohw-href-key]")?.removeAttribute("data-ohw-hovered");
|
|
7850
|
-
activeElRef.current = el;
|
|
7851
|
-
originalContentRef.current = el.innerHTML;
|
|
7852
|
-
el.focus();
|
|
7853
|
-
if (options?.caretX !== void 0 && options?.caretY !== void 0) {
|
|
7854
|
-
placeCaretAtPoint(el, options.caretX, options.caretY);
|
|
8406
|
+
const refreshFooterDragVisuals = useCallback4((session, activeSlot, clientX, clientY) => {
|
|
8407
|
+
const dragged = session.draggedEl;
|
|
8408
|
+
setDraggedItemRect(dragged.getBoundingClientRect());
|
|
8409
|
+
if (typeof clientX === "number" && typeof clientY === "number") {
|
|
8410
|
+
session.lastClientX = clientX;
|
|
8411
|
+
session.lastClientY = clientY;
|
|
7855
8412
|
}
|
|
7856
|
-
|
|
7857
|
-
|
|
7858
|
-
|
|
7859
|
-
|
|
7860
|
-
|
|
7861
|
-
|
|
7862
|
-
|
|
7863
|
-
|
|
7864
|
-
|
|
8413
|
+
session.activeSlot = activeSlot;
|
|
8414
|
+
if (session.kind === "link") {
|
|
8415
|
+
const columns2 = listFooterColumns();
|
|
8416
|
+
const focusCols = /* @__PURE__ */ new Set([session.sourceColumnIndex]);
|
|
8417
|
+
if (activeSlot) focusCols.add(activeSlot.columnIndex);
|
|
8418
|
+
const siblingRects = [];
|
|
8419
|
+
columns2.forEach((col, i) => {
|
|
8420
|
+
if (!focusCols.has(i)) return;
|
|
8421
|
+
for (const link of listFooterLinksInColumn(col)) {
|
|
8422
|
+
if (link === dragged) continue;
|
|
8423
|
+
siblingRects.push(link.getBoundingClientRect());
|
|
8424
|
+
}
|
|
8425
|
+
});
|
|
8426
|
+
setSiblingHintRects(siblingRects);
|
|
8427
|
+
const slots2 = [];
|
|
8428
|
+
columns2.forEach((col, i) => {
|
|
8429
|
+
slots2.push(...buildLinkDropSlots(col, i));
|
|
8430
|
+
});
|
|
8431
|
+
setFooterDropSlots(slots2);
|
|
8432
|
+
const activeIdx2 = activeSlot ? slots2.findIndex((s) => s.columnIndex === activeSlot.columnIndex && s.insertIndex === activeSlot.insertIndex) : -1;
|
|
8433
|
+
setActiveFooterDropIndex(activeIdx2 >= 0 ? activeIdx2 : null);
|
|
8434
|
+
return;
|
|
8435
|
+
}
|
|
8436
|
+
const columns = listFooterColumns();
|
|
8437
|
+
setSiblingHintRects(columns.filter((col) => col !== dragged).map((col) => col.getBoundingClientRect()));
|
|
8438
|
+
const slots = buildColumnDropSlots();
|
|
8439
|
+
setFooterDropSlots(slots);
|
|
8440
|
+
const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
|
|
8441
|
+
setActiveFooterDropIndex(activeIdx >= 0 ? activeIdx : null);
|
|
8442
|
+
}, []);
|
|
8443
|
+
const refreshFooterDragVisualsRef = useRef5(refreshFooterDragVisuals);
|
|
8444
|
+
refreshFooterDragVisualsRef.current = refreshFooterDragVisuals;
|
|
8445
|
+
const commitFooterDragRef = useRef5(() => {
|
|
8446
|
+
});
|
|
8447
|
+
const beginFooterDragRef = useRef5(() => {
|
|
8448
|
+
});
|
|
8449
|
+
const beginFooterDrag = useCallback4(
|
|
8450
|
+
(session) => {
|
|
8451
|
+
const rect = session.draggedEl.getBoundingClientRect();
|
|
8452
|
+
session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
|
|
8453
|
+
session.lastClientY = session.lastClientY || rect.top + rect.height / 2;
|
|
8454
|
+
session.activeSlot = session.activeSlot ?? null;
|
|
8455
|
+
footerDragRef.current = session;
|
|
8456
|
+
setIsItemDragging(true);
|
|
8457
|
+
lockFooterDuringDrag();
|
|
8458
|
+
siblingHintElRef.current = null;
|
|
8459
|
+
setSiblingHintRect(null);
|
|
8460
|
+
if (session.wasSelected && selectedElRef.current === session.draggedEl) {
|
|
8461
|
+
setToolbarRect(rect);
|
|
8462
|
+
}
|
|
8463
|
+
const initialSlot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
|
|
8464
|
+
refreshFooterDragVisuals(session, initialSlot, session.lastClientX, session.lastClientY);
|
|
8465
|
+
},
|
|
8466
|
+
[refreshFooterDragVisuals]
|
|
8467
|
+
);
|
|
8468
|
+
beginFooterDragRef.current = beginFooterDrag;
|
|
8469
|
+
const commitFooterDrag = useCallback4(
|
|
8470
|
+
(clientX, clientY) => {
|
|
8471
|
+
const session = footerDragRef.current;
|
|
8472
|
+
if (!session) {
|
|
8473
|
+
clearFooterDragVisuals();
|
|
8474
|
+
return;
|
|
8475
|
+
}
|
|
8476
|
+
const x = typeof clientX === "number" && (clientX !== 0 || clientY !== 0) ? clientX : session.lastClientX;
|
|
8477
|
+
const y = typeof clientY === "number" && (clientX !== 0 || clientY !== 0) ? clientY : session.lastClientY;
|
|
8478
|
+
let nextOrder = null;
|
|
8479
|
+
const slot = session.activeSlot ?? (session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(x, y, session.hrefKey) : session.kind === "column" ? hitTestColumnDropSlot(x, y) : null);
|
|
8480
|
+
if (session.kind === "link" && session.hrefKey && slot) {
|
|
8481
|
+
nextOrder = planFooterLinkMove(session.hrefKey, slot.columnIndex, slot.insertIndex);
|
|
8482
|
+
} else if (session.kind === "column" && slot) {
|
|
8483
|
+
nextOrder = planFooterColumnMove(session.sourceColumnIndex, slot.insertIndex);
|
|
8484
|
+
}
|
|
8485
|
+
const wasSelected = session.wasSelected;
|
|
8486
|
+
const draggedEl = session.draggedEl;
|
|
8487
|
+
const hrefKey = session.hrefKey;
|
|
8488
|
+
let movedColumnIndex = null;
|
|
8489
|
+
if (session.kind === "column" && slot && nextOrder) {
|
|
8490
|
+
let adjusted = slot.insertIndex;
|
|
8491
|
+
if (session.sourceColumnIndex < slot.insertIndex) adjusted -= 1;
|
|
8492
|
+
movedColumnIndex = Math.max(0, Math.min(adjusted, nextOrder.length - 1));
|
|
8493
|
+
}
|
|
8494
|
+
clearFooterDragVisuals();
|
|
8495
|
+
const applySelectionAfterDrop = () => {
|
|
8496
|
+
if (!wasSelected) {
|
|
8497
|
+
deselectRef.current();
|
|
8498
|
+
return;
|
|
8499
|
+
}
|
|
8500
|
+
if (hrefKey) {
|
|
8501
|
+
const link = document.querySelector(
|
|
8502
|
+
`footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
8503
|
+
);
|
|
8504
|
+
if (link && isNavigationItem(link)) {
|
|
8505
|
+
selectRef.current(link);
|
|
8506
|
+
return;
|
|
8507
|
+
}
|
|
8508
|
+
}
|
|
8509
|
+
if (movedColumnIndex !== null && nextOrder) {
|
|
8510
|
+
const colKeys = nextOrder[movedColumnIndex] ?? [];
|
|
8511
|
+
let column = null;
|
|
8512
|
+
for (const key of colKeys) {
|
|
8513
|
+
const link = document.querySelector(
|
|
8514
|
+
`footer [data-ohw-href-key="${CSS.escape(key)}"]`
|
|
8515
|
+
);
|
|
8516
|
+
if (link) {
|
|
8517
|
+
column = findFooterColumnForLink(link);
|
|
8518
|
+
if (column) break;
|
|
8519
|
+
}
|
|
8520
|
+
}
|
|
8521
|
+
if (!column) column = listFooterColumns()[movedColumnIndex] ?? null;
|
|
8522
|
+
if (column && isNavigationContainer(column)) {
|
|
8523
|
+
selectFrameRef.current(column);
|
|
8524
|
+
return;
|
|
8525
|
+
}
|
|
8526
|
+
}
|
|
8527
|
+
if (document.body.contains(draggedEl)) {
|
|
8528
|
+
if (isNavigationItem(draggedEl)) {
|
|
8529
|
+
selectRef.current(draggedEl);
|
|
8530
|
+
return;
|
|
8531
|
+
}
|
|
8532
|
+
if (isNavigationContainer(draggedEl)) {
|
|
8533
|
+
selectFrameRef.current(draggedEl);
|
|
8534
|
+
return;
|
|
8535
|
+
}
|
|
8536
|
+
}
|
|
8537
|
+
deselectRef.current();
|
|
8538
|
+
};
|
|
8539
|
+
if (!wasSelected) {
|
|
8540
|
+
deselectRef.current();
|
|
8541
|
+
}
|
|
8542
|
+
if (nextOrder) {
|
|
8543
|
+
const orderJson = JSON.stringify(nextOrder);
|
|
8544
|
+
editContentRef.current = {
|
|
8545
|
+
...editContentRef.current,
|
|
8546
|
+
[FOOTER_ORDER_KEY]: orderJson
|
|
8547
|
+
};
|
|
8548
|
+
applyFooterOrder(nextOrder);
|
|
8549
|
+
document.querySelectorAll("footer [data-ohw-href-key]").forEach(disableNativeHrefDrag);
|
|
8550
|
+
postToParentRef.current({
|
|
8551
|
+
type: "ow:change",
|
|
8552
|
+
nodes: [{ key: FOOTER_ORDER_KEY, text: orderJson }]
|
|
8553
|
+
});
|
|
8554
|
+
requestAnimationFrame(() => {
|
|
8555
|
+
if (editContentRef.current[FOOTER_ORDER_KEY] === orderJson) {
|
|
8556
|
+
applyFooterOrder(nextOrder);
|
|
8557
|
+
document.querySelectorAll("footer [data-ohw-href-key]").forEach(disableNativeHrefDrag);
|
|
8558
|
+
}
|
|
8559
|
+
requestAnimationFrame(applySelectionAfterDrop);
|
|
8560
|
+
});
|
|
8561
|
+
return;
|
|
8562
|
+
}
|
|
8563
|
+
applySelectionAfterDrop();
|
|
8564
|
+
},
|
|
8565
|
+
[clearFooterDragVisuals]
|
|
8566
|
+
);
|
|
8567
|
+
commitFooterDragRef.current = commitFooterDrag;
|
|
8568
|
+
const startFooterLinkDrag = useCallback4(
|
|
8569
|
+
(anchor, clientX, clientY, wasSelected) => {
|
|
8570
|
+
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
8571
|
+
if (!hrefKey || !isFooterHrefKey(hrefKey)) return false;
|
|
8572
|
+
const column = findFooterColumnForLink(anchor);
|
|
8573
|
+
const columns = listFooterColumns();
|
|
8574
|
+
beginFooterDrag({
|
|
8575
|
+
kind: "link",
|
|
8576
|
+
hrefKey,
|
|
8577
|
+
columnEl: column,
|
|
8578
|
+
sourceColumnIndex: column ? columns.indexOf(column) : 0,
|
|
8579
|
+
wasSelected,
|
|
8580
|
+
draggedEl: anchor,
|
|
8581
|
+
lastClientX: clientX,
|
|
8582
|
+
lastClientY: clientY,
|
|
8583
|
+
activeSlot: null
|
|
8584
|
+
});
|
|
8585
|
+
return true;
|
|
8586
|
+
},
|
|
8587
|
+
[beginFooterDrag]
|
|
8588
|
+
);
|
|
8589
|
+
const startFooterColumnDrag = useCallback4(
|
|
8590
|
+
(columnEl, clientX, clientY, wasSelected) => {
|
|
8591
|
+
const columns = listFooterColumns();
|
|
8592
|
+
const idx = columns.indexOf(columnEl);
|
|
8593
|
+
if (idx < 0) return false;
|
|
8594
|
+
beginFooterDrag({
|
|
8595
|
+
kind: "column",
|
|
8596
|
+
hrefKey: null,
|
|
8597
|
+
columnEl,
|
|
8598
|
+
sourceColumnIndex: idx,
|
|
8599
|
+
wasSelected,
|
|
8600
|
+
draggedEl: columnEl,
|
|
8601
|
+
lastClientX: clientX,
|
|
8602
|
+
lastClientY: clientY,
|
|
8603
|
+
activeSlot: null
|
|
8604
|
+
});
|
|
8605
|
+
return true;
|
|
8606
|
+
},
|
|
8607
|
+
[beginFooterDrag]
|
|
8608
|
+
);
|
|
8609
|
+
const handleItemDragStart = useCallback4(
|
|
8610
|
+
(e) => {
|
|
8611
|
+
const selected = selectedElRef.current;
|
|
8612
|
+
if (!selected) {
|
|
8613
|
+
setIsItemDragging(true);
|
|
8614
|
+
return;
|
|
8615
|
+
}
|
|
8616
|
+
const clientX = e?.clientX ?? selected.getBoundingClientRect().left + 8;
|
|
8617
|
+
const clientY = e?.clientY ?? selected.getBoundingClientRect().top + 8;
|
|
8618
|
+
if (startFooterLinkDrag(selected, clientX, clientY, true)) return;
|
|
8619
|
+
if (selected.hasAttribute("data-ohw-footer-col") || isInferredFooterGroup(selected) && selected.closest("footer")) {
|
|
8620
|
+
if (startFooterColumnDrag(selected, clientX, clientY, true)) return;
|
|
8621
|
+
}
|
|
8622
|
+
siblingHintElRef.current = null;
|
|
8623
|
+
setSiblingHintRect(null);
|
|
8624
|
+
setIsItemDragging(true);
|
|
8625
|
+
},
|
|
8626
|
+
[startFooterColumnDrag, startFooterLinkDrag]
|
|
8627
|
+
);
|
|
8628
|
+
const handleItemDragEnd = useCallback4(
|
|
8629
|
+
(e) => {
|
|
8630
|
+
if (footerDragRef.current) {
|
|
8631
|
+
const x = e?.clientX;
|
|
8632
|
+
const y = e?.clientY;
|
|
8633
|
+
if (typeof x === "number" && typeof y === "number" && (x !== 0 || y !== 0)) {
|
|
8634
|
+
commitFooterDrag(x, y);
|
|
8635
|
+
} else {
|
|
8636
|
+
commitFooterDrag();
|
|
8637
|
+
}
|
|
8638
|
+
return;
|
|
8639
|
+
}
|
|
8640
|
+
setIsItemDragging(false);
|
|
8641
|
+
},
|
|
8642
|
+
[commitFooterDrag]
|
|
8643
|
+
);
|
|
8644
|
+
const handleItemChromePointerDown = useCallback4((e) => {
|
|
8645
|
+
if (e.button !== 0) return;
|
|
8646
|
+
const selected = selectedElRef.current;
|
|
8647
|
+
if (!selected) return;
|
|
8648
|
+
armFooterPressDrag();
|
|
8649
|
+
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
8650
|
+
if (hrefKey && isFooterHrefKey(hrefKey)) {
|
|
8651
|
+
footerPointerDragRef.current = {
|
|
8652
|
+
el: selected,
|
|
8653
|
+
kind: "link",
|
|
8654
|
+
startX: e.clientX,
|
|
8655
|
+
startY: e.clientY,
|
|
8656
|
+
pointerId: e.pointerId,
|
|
8657
|
+
wasSelected: true,
|
|
8658
|
+
started: false
|
|
8659
|
+
};
|
|
8660
|
+
return;
|
|
8661
|
+
}
|
|
8662
|
+
if (selected.hasAttribute("data-ohw-footer-col") || isInferredFooterGroup(selected) && selected.closest("footer")) {
|
|
8663
|
+
footerPointerDragRef.current = {
|
|
8664
|
+
el: selected,
|
|
8665
|
+
kind: "column",
|
|
8666
|
+
startX: e.clientX,
|
|
8667
|
+
startY: e.clientY,
|
|
8668
|
+
pointerId: e.pointerId,
|
|
8669
|
+
wasSelected: true,
|
|
8670
|
+
started: false
|
|
8671
|
+
};
|
|
7865
8672
|
}
|
|
7866
|
-
|
|
7867
|
-
|
|
7868
|
-
|
|
7869
|
-
|
|
8673
|
+
}, []);
|
|
8674
|
+
const handleItemChromeClick = useCallback4((clientX, clientY) => {
|
|
8675
|
+
if (suppressNextClickRef.current) {
|
|
8676
|
+
suppressNextClickRef.current = false;
|
|
8677
|
+
return;
|
|
8678
|
+
}
|
|
8679
|
+
const selected = selectedElRef.current;
|
|
8680
|
+
if (!selected || !isNavigationItem(selected)) return;
|
|
8681
|
+
const editable = selected.querySelector('[data-ohw-editable="text"]') ?? selected.querySelector("[data-ohw-editable]");
|
|
8682
|
+
if (!editable) return;
|
|
8683
|
+
activateRef.current(editable, { caretX: clientX, caretY: clientY });
|
|
8684
|
+
}, []);
|
|
8685
|
+
reselectNavigationItemRef.current = reselectNavigationItem;
|
|
8686
|
+
commitNavigationTextEditRef.current = commitNavigationTextEdit;
|
|
8687
|
+
const select = useCallback4(
|
|
8688
|
+
(anchor) => {
|
|
8689
|
+
if (!isNavigationItem(anchor)) return;
|
|
8690
|
+
if (activeElRef.current) deactivate();
|
|
8691
|
+
selectedElRef.current = anchor;
|
|
8692
|
+
clearHrefKeyHover(anchor);
|
|
8693
|
+
hoveredNavContainerRef.current = null;
|
|
8694
|
+
setHoveredNavContainerRect(null);
|
|
8695
|
+
setHoveredItemRect(null);
|
|
8696
|
+
hoveredItemElRef.current = null;
|
|
8697
|
+
siblingHintElRef.current = null;
|
|
8698
|
+
setSiblingHintRect(null);
|
|
8699
|
+
setSiblingHintRects([]);
|
|
8700
|
+
setIsItemDragging(false);
|
|
8701
|
+
const { key, disabled } = getNavigationItemReorderState(anchor);
|
|
8702
|
+
setReorderHrefKey(key);
|
|
8703
|
+
setReorderDragDisabled(disabled);
|
|
8704
|
+
setIsFooterFrameSelection(false);
|
|
8705
|
+
setToolbarVariant("link-action");
|
|
8706
|
+
setToolbarRect(anchor.getBoundingClientRect());
|
|
8707
|
+
setToolbarShowEditLink(false);
|
|
8708
|
+
setActiveCommands(/* @__PURE__ */ new Set());
|
|
8709
|
+
},
|
|
8710
|
+
[deactivate]
|
|
8711
|
+
);
|
|
8712
|
+
const selectFrame = useCallback4(
|
|
8713
|
+
(el) => {
|
|
8714
|
+
if (!isNavigationContainer(el)) return;
|
|
8715
|
+
if (activeElRef.current) deactivate();
|
|
8716
|
+
const isFooterColumn = el.hasAttribute("data-ohw-footer-col") || Boolean(el.closest("footer") && isInferredFooterGroup(el));
|
|
8717
|
+
selectedElRef.current = el;
|
|
8718
|
+
clearHrefKeyHover(el);
|
|
8719
|
+
hoveredNavContainerRef.current = null;
|
|
8720
|
+
setHoveredNavContainerRect(null);
|
|
8721
|
+
setHoveredItemRect(null);
|
|
8722
|
+
hoveredItemElRef.current = null;
|
|
8723
|
+
siblingHintElRef.current = null;
|
|
8724
|
+
setSiblingHintRect(null);
|
|
8725
|
+
setSiblingHintRects(
|
|
8726
|
+
isFooterColumn ? listFooterColumns().filter((column) => column !== el).map((column) => column.getBoundingClientRect()) : []
|
|
8727
|
+
);
|
|
8728
|
+
setIsItemDragging(false);
|
|
8729
|
+
setReorderHrefKey(null);
|
|
8730
|
+
setReorderDragDisabled(false);
|
|
8731
|
+
setIsFooterFrameSelection(isFooterColumn);
|
|
8732
|
+
setToolbarVariant("select-frame");
|
|
8733
|
+
setToolbarRect(el.getBoundingClientRect());
|
|
8734
|
+
setToolbarShowEditLink(false);
|
|
8735
|
+
setActiveCommands(/* @__PURE__ */ new Set());
|
|
8736
|
+
},
|
|
8737
|
+
[deactivate]
|
|
8738
|
+
);
|
|
8739
|
+
const activate = useCallback4(
|
|
8740
|
+
(el, options) => {
|
|
8741
|
+
if (activeElRef.current === el) return;
|
|
8742
|
+
selectedElRef.current = null;
|
|
8743
|
+
deactivate();
|
|
8744
|
+
if (hoveredImageRef.current) {
|
|
8745
|
+
hoveredImageRef.current = null;
|
|
8746
|
+
postToParentRef.current({ type: "ow:image-unhover" });
|
|
8747
|
+
}
|
|
8748
|
+
setToolbarVariant("rich-text");
|
|
8749
|
+
siblingHintElRef.current = null;
|
|
8750
|
+
setSiblingHintRect(null);
|
|
8751
|
+
setSiblingHintRects([]);
|
|
8752
|
+
setIsItemDragging(false);
|
|
8753
|
+
el.setAttribute("contenteditable", "true");
|
|
8754
|
+
el.removeAttribute("data-ohw-hovered");
|
|
8755
|
+
el.closest("[data-ohw-href-key]")?.removeAttribute("data-ohw-hovered");
|
|
8756
|
+
activeElRef.current = el;
|
|
8757
|
+
originalContentRef.current = el.innerHTML;
|
|
8758
|
+
el.focus();
|
|
8759
|
+
if (options?.caretX !== void 0 && options?.caretY !== void 0) {
|
|
8760
|
+
placeCaretAtPoint(el, options.caretX, options.caretY);
|
|
8761
|
+
}
|
|
8762
|
+
setToolbarShowEditLink(Boolean(getHrefKeyFromElement(el)));
|
|
8763
|
+
const navAnchor = getNavigationItemAnchor(el);
|
|
8764
|
+
if (navAnchor) {
|
|
8765
|
+
setReorderHrefKey(null);
|
|
8766
|
+
setReorderDragDisabled(false);
|
|
8767
|
+
} else {
|
|
8768
|
+
const { key: reorderKey, disabled: reorderDisabled } = getReorderHandleState(el);
|
|
8769
|
+
setReorderHrefKey(reorderKey);
|
|
8770
|
+
setReorderDragDisabled(reorderDisabled);
|
|
8771
|
+
}
|
|
8772
|
+
setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
8773
|
+
postToParent2({ type: "ow:enter-edit", key: el.dataset.ohwKey });
|
|
8774
|
+
requestAnimationFrame(() => refreshActiveCommandsRef.current());
|
|
8775
|
+
},
|
|
8776
|
+
[deactivate, postToParent2]
|
|
8777
|
+
);
|
|
7870
8778
|
activateRef.current = activate;
|
|
7871
8779
|
deactivateRef.current = deactivate;
|
|
7872
8780
|
selectRef.current = select;
|
|
@@ -7882,6 +8790,7 @@ function OhhwellsBridge() {
|
|
|
7882
8790
|
for (const [key, val] of Object.entries(content)) {
|
|
7883
8791
|
if (key === "__ohw_sections") continue;
|
|
7884
8792
|
if (applyVideoSettingNode(key, val)) continue;
|
|
8793
|
+
if (applyCarouselNode(key, val)) continue;
|
|
7885
8794
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
7886
8795
|
if (el.dataset.ohwEditable === "image") {
|
|
7887
8796
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
@@ -7913,6 +8822,7 @@ function OhhwellsBridge() {
|
|
|
7913
8822
|
applyLinkByKey(key, val);
|
|
7914
8823
|
}
|
|
7915
8824
|
reconcileNavbarItemsFromContent(content);
|
|
8825
|
+
reconcileFooterOrderFromContent(content);
|
|
7916
8826
|
enforceLinkHrefs();
|
|
7917
8827
|
initSectionsFromContent(content, true);
|
|
7918
8828
|
sectionsLoadedRef.current = true;
|
|
@@ -7941,7 +8851,7 @@ function OhhwellsBridge() {
|
|
|
7941
8851
|
cancelled = true;
|
|
7942
8852
|
};
|
|
7943
8853
|
}, [subdomain, isEditMode]);
|
|
7944
|
-
|
|
8854
|
+
useEffect8(() => {
|
|
7945
8855
|
if (!subdomain || isEditMode) return;
|
|
7946
8856
|
let debounceTimer = null;
|
|
7947
8857
|
let observer = null;
|
|
@@ -7954,6 +8864,7 @@ function OhhwellsBridge() {
|
|
|
7954
8864
|
for (const [key, val] of Object.entries(content)) {
|
|
7955
8865
|
if (key === "__ohw_sections") continue;
|
|
7956
8866
|
if (applyVideoSettingNode(key, val)) continue;
|
|
8867
|
+
if (applyCarouselNode(key, val)) continue;
|
|
7957
8868
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
7958
8869
|
if (el.dataset.ohwEditable === "image") {
|
|
7959
8870
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
@@ -7973,6 +8884,7 @@ function OhhwellsBridge() {
|
|
|
7973
8884
|
applyLinkByKey(key, val);
|
|
7974
8885
|
}
|
|
7975
8886
|
reconcileNavbarItemsFromContent(content);
|
|
8887
|
+
reconcileFooterOrderFromContent(content);
|
|
7976
8888
|
} finally {
|
|
7977
8889
|
observer?.observe(document.body, { childList: true, subtree: true });
|
|
7978
8890
|
}
|
|
@@ -7996,10 +8908,10 @@ function OhhwellsBridge() {
|
|
|
7996
8908
|
const visible = Boolean(subdomain) && fetchState !== "done";
|
|
7997
8909
|
el.style.display = visible ? "flex" : "none";
|
|
7998
8910
|
}, [subdomain, fetchState]);
|
|
7999
|
-
|
|
8911
|
+
useEffect8(() => {
|
|
8000
8912
|
postToParent2({ type: "ow:navigation", path: pathname });
|
|
8001
8913
|
}, [pathname, postToParent2]);
|
|
8002
|
-
|
|
8914
|
+
useEffect8(() => {
|
|
8003
8915
|
if (!isEditMode) return;
|
|
8004
8916
|
if (linkPopoverSessionRef.current?.intent === "add-nav") return;
|
|
8005
8917
|
if (document.querySelector("[data-ohw-section-picker]")) return;
|
|
@@ -8007,23 +8919,50 @@ function OhhwellsBridge() {
|
|
|
8007
8919
|
deselectRef.current();
|
|
8008
8920
|
deactivateRef.current();
|
|
8009
8921
|
}, [pathname, isEditMode]);
|
|
8010
|
-
|
|
8922
|
+
useEffect8(() => {
|
|
8011
8923
|
const contentForNav = () => {
|
|
8012
8924
|
if (isEditMode) return editContentRef.current;
|
|
8013
8925
|
if (!subdomain) return {};
|
|
8014
8926
|
return contentCache.get(subdomain) ?? {};
|
|
8015
8927
|
};
|
|
8016
|
-
|
|
8928
|
+
let applying = false;
|
|
8929
|
+
let rafId = null;
|
|
8930
|
+
const run = () => {
|
|
8931
|
+
if (footerDragRef.current || applying) return;
|
|
8932
|
+
applying = true;
|
|
8933
|
+
try {
|
|
8934
|
+
const content = contentForNav();
|
|
8935
|
+
reconcileNavbarItemsFromContent(content);
|
|
8936
|
+
reconcileFooterOrderFromContent(content);
|
|
8937
|
+
document.querySelectorAll("footer [data-ohw-href-key]").forEach((el) => {
|
|
8938
|
+
if (isFooterHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
8939
|
+
disableNativeHrefDrag(el);
|
|
8940
|
+
}
|
|
8941
|
+
});
|
|
8942
|
+
} finally {
|
|
8943
|
+
applying = false;
|
|
8944
|
+
}
|
|
8945
|
+
};
|
|
8946
|
+
const scheduleRun = () => {
|
|
8947
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
8948
|
+
rafId = requestAnimationFrame(() => {
|
|
8949
|
+
rafId = null;
|
|
8950
|
+
run();
|
|
8951
|
+
});
|
|
8952
|
+
};
|
|
8017
8953
|
run();
|
|
8018
8954
|
const nav = document.querySelector("nav");
|
|
8019
|
-
|
|
8020
|
-
const observer = new MutationObserver(
|
|
8021
|
-
|
|
8022
|
-
});
|
|
8023
|
-
|
|
8024
|
-
return () =>
|
|
8955
|
+
const footer = document.querySelector("footer");
|
|
8956
|
+
const observer = new MutationObserver(scheduleRun);
|
|
8957
|
+
if (nav) observer.observe(nav, { childList: true, subtree: true });
|
|
8958
|
+
if (footer) observer.observe(footer, { childList: true, subtree: true });
|
|
8959
|
+
if (!nav && !footer) return;
|
|
8960
|
+
return () => {
|
|
8961
|
+
observer.disconnect();
|
|
8962
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
8963
|
+
};
|
|
8025
8964
|
}, [isEditMode, pathname, subdomain, fetchState]);
|
|
8026
|
-
|
|
8965
|
+
useEffect8(() => {
|
|
8027
8966
|
if (!isEditMode) return;
|
|
8028
8967
|
const measure = () => {
|
|
8029
8968
|
const h = document.body.scrollHeight;
|
|
@@ -8047,7 +8986,7 @@ function OhhwellsBridge() {
|
|
|
8047
8986
|
window.removeEventListener("resize", handleResize);
|
|
8048
8987
|
};
|
|
8049
8988
|
}, [pathname, isEditMode, postToParent2]);
|
|
8050
|
-
|
|
8989
|
+
useEffect8(() => {
|
|
8051
8990
|
if (!subdomainFromQuery || isEditMode) return;
|
|
8052
8991
|
const handleClick = (e) => {
|
|
8053
8992
|
const anchor = e.target.closest("a");
|
|
@@ -8063,7 +9002,7 @@ function OhhwellsBridge() {
|
|
|
8063
9002
|
document.addEventListener("click", handleClick, true);
|
|
8064
9003
|
return () => document.removeEventListener("click", handleClick, true);
|
|
8065
9004
|
}, [subdomainFromQuery, isEditMode, router]);
|
|
8066
|
-
|
|
9005
|
+
useEffect8(() => {
|
|
8067
9006
|
if (!isEditMode) {
|
|
8068
9007
|
editStylesRef.current?.base.remove();
|
|
8069
9008
|
editStylesRef.current?.forceHover.remove();
|
|
@@ -8086,7 +9025,39 @@ function OhhwellsBridge() {
|
|
|
8086
9025
|
[data-ohw-editable] {
|
|
8087
9026
|
display: block;
|
|
8088
9027
|
}
|
|
8089
|
-
|
|
9028
|
+
/* Native <a> drag steals clicks \u2014 disable for edit links; reorder via press-to-drag / handle. */
|
|
9029
|
+
footer [data-ohw-href-key] {
|
|
9030
|
+
-webkit-user-drag: none !important;
|
|
9031
|
+
}
|
|
9032
|
+
footer [data-ohw-footer-col]:hover {
|
|
9033
|
+
outline: 1.5px dashed ${PRIMARY2} !important;
|
|
9034
|
+
outline-offset: 6px;
|
|
9035
|
+
border-radius: 8px;
|
|
9036
|
+
}
|
|
9037
|
+
html[data-ohw-link-popover-open] footer [data-ohw-footer-col]:hover {
|
|
9038
|
+
outline: none !important;
|
|
9039
|
+
}
|
|
9040
|
+
html[data-ohw-footer-press-drag] footer,
|
|
9041
|
+
html[data-ohw-footer-press-drag] footer * {
|
|
9042
|
+
user-select: none !important;
|
|
9043
|
+
-webkit-user-select: none !important;
|
|
9044
|
+
}
|
|
9045
|
+
html[data-ohw-item-dragging] footer,
|
|
9046
|
+
html[data-ohw-item-dragging] footer * {
|
|
9047
|
+
user-select: none !important;
|
|
9048
|
+
-webkit-user-select: none !important;
|
|
9049
|
+
pointer-events: none !important;
|
|
9050
|
+
}
|
|
9051
|
+
html[data-ohw-item-dragging] {
|
|
9052
|
+
cursor: grabbing !important;
|
|
9053
|
+
}
|
|
9054
|
+
[data-ohw-editable]:not([contenteditable]):not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]):not(nav [data-ohw-href-key] *):not(footer [data-ohw-href-key] *) { cursor: text !important; }
|
|
9055
|
+
nav [data-ohw-href-key],
|
|
9056
|
+
nav [data-ohw-href-key] [data-ohw-editable]:not([contenteditable]),
|
|
9057
|
+
footer [data-ohw-href-key],
|
|
9058
|
+
footer [data-ohw-href-key] [data-ohw-editable]:not([contenteditable]) {
|
|
9059
|
+
cursor: grab !important;
|
|
9060
|
+
}
|
|
8090
9061
|
[data-ohw-editable="image"], [data-ohw-editable="image"] *,
|
|
8091
9062
|
[data-ohw-editable="video"], [data-ohw-editable="video"] *,
|
|
8092
9063
|
[data-ohw-editable="bg-image"], [data-ohw-editable="bg-image"] * { cursor: pointer !important; }
|
|
@@ -8130,12 +9101,39 @@ function OhhwellsBridge() {
|
|
|
8130
9101
|
}
|
|
8131
9102
|
refreshStateRules();
|
|
8132
9103
|
const handleClick = (e) => {
|
|
9104
|
+
if (suppressNextClickRef.current) {
|
|
9105
|
+
suppressNextClickRef.current = false;
|
|
9106
|
+
e.preventDefault();
|
|
9107
|
+
e.stopPropagation();
|
|
9108
|
+
return;
|
|
9109
|
+
}
|
|
8133
9110
|
const target = e.target;
|
|
8134
9111
|
if (target.closest("[data-ohw-toolbar]")) return;
|
|
8135
9112
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
8136
9113
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
8137
9114
|
if (isInsideLinkEditor(target)) return;
|
|
8138
9115
|
if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
9116
|
+
if (target.closest("[data-ohw-item-drag-surface]")) {
|
|
9117
|
+
e.preventDefault();
|
|
9118
|
+
e.stopPropagation();
|
|
9119
|
+
const selected = selectedElRef.current;
|
|
9120
|
+
if (selected && isNavigationItem(selected)) {
|
|
9121
|
+
const editable2 = selected.querySelector('[data-ohw-editable="text"]') ?? selected.querySelector("[data-ohw-editable]");
|
|
9122
|
+
if (editable2) {
|
|
9123
|
+
activateRef.current(editable2, {
|
|
9124
|
+
caretX: e.clientX,
|
|
9125
|
+
caretY: e.clientY
|
|
9126
|
+
});
|
|
9127
|
+
}
|
|
9128
|
+
} else if (selected?.hasAttribute("data-ohw-footer-col")) {
|
|
9129
|
+
const link = listFooterLinksInColumn(selected).find((el) => {
|
|
9130
|
+
const r2 = el.getBoundingClientRect();
|
|
9131
|
+
return e.clientX >= r2.left && e.clientX <= r2.right && e.clientY >= r2.top && e.clientY <= r2.bottom;
|
|
9132
|
+
});
|
|
9133
|
+
if (link) selectRef.current(link);
|
|
9134
|
+
}
|
|
9135
|
+
return;
|
|
9136
|
+
}
|
|
8139
9137
|
const navFromChrome = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
|
|
8140
9138
|
if (navFromChrome) {
|
|
8141
9139
|
e.preventDefault();
|
|
@@ -8165,7 +9163,15 @@ function OhhwellsBridge() {
|
|
|
8165
9163
|
if (isMediaEditable(editable)) {
|
|
8166
9164
|
e.preventDefault();
|
|
8167
9165
|
e.stopPropagation();
|
|
8168
|
-
|
|
9166
|
+
const key = editable.dataset.ohwKey ?? "";
|
|
9167
|
+
const r2 = editable.getBoundingClientRect();
|
|
9168
|
+
if (key && r2.width > 1 && r2.height > 1) {
|
|
9169
|
+
pendingUploadRectRef.current = {
|
|
9170
|
+
key,
|
|
9171
|
+
rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height }
|
|
9172
|
+
};
|
|
9173
|
+
}
|
|
9174
|
+
postToParentRef.current({ type: "ow:image-pick", key, elementType: editable.dataset.ohwEditable ?? "image" });
|
|
8169
9175
|
return;
|
|
8170
9176
|
}
|
|
8171
9177
|
const hrefCtx = getHrefKeyFromElement(editable);
|
|
@@ -8190,10 +9196,26 @@ function OhhwellsBridge() {
|
|
|
8190
9196
|
if (hrefAnchor) {
|
|
8191
9197
|
e.preventDefault();
|
|
8192
9198
|
e.stopPropagation();
|
|
8193
|
-
if (selectedElRef.current === hrefAnchor)
|
|
9199
|
+
if (selectedElRef.current === hrefAnchor) {
|
|
9200
|
+
const textEditable = hrefAnchor.querySelector('[data-ohw-editable="text"]') ?? hrefAnchor.querySelector("[data-ohw-editable]");
|
|
9201
|
+
if (textEditable) {
|
|
9202
|
+
activateRef.current(textEditable, {
|
|
9203
|
+
caretX: e.clientX,
|
|
9204
|
+
caretY: e.clientY
|
|
9205
|
+
});
|
|
9206
|
+
}
|
|
9207
|
+
return;
|
|
9208
|
+
}
|
|
8194
9209
|
selectRef.current(hrefAnchor);
|
|
8195
9210
|
return;
|
|
8196
9211
|
}
|
|
9212
|
+
const footerColClick = target.closest("[data-ohw-footer-col]");
|
|
9213
|
+
if (footerColClick) {
|
|
9214
|
+
e.preventDefault();
|
|
9215
|
+
e.stopPropagation();
|
|
9216
|
+
selectFrameRef.current(footerColClick);
|
|
9217
|
+
return;
|
|
9218
|
+
}
|
|
8197
9219
|
const navContainerToSelect = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
|
|
8198
9220
|
if (navContainerToSelect) {
|
|
8199
9221
|
e.preventDefault();
|
|
@@ -8260,6 +9282,13 @@ function OhhwellsBridge() {
|
|
|
8260
9282
|
const handleMouseOver = (e) => {
|
|
8261
9283
|
if (document.documentElement.hasAttribute("data-ohw-section-picking")) return;
|
|
8262
9284
|
const target = e.target;
|
|
9285
|
+
if (linkPopoverOpenRef.current) {
|
|
9286
|
+
hoveredItemElRef.current = null;
|
|
9287
|
+
setHoveredItemRect(null);
|
|
9288
|
+
hoveredNavContainerRef.current = null;
|
|
9289
|
+
setHoveredNavContainerRect(null);
|
|
9290
|
+
return;
|
|
9291
|
+
}
|
|
8263
9292
|
if (toolbarVariantRef.current !== "select-frame") {
|
|
8264
9293
|
const navContainer = target.closest("[data-ohw-nav-container]");
|
|
8265
9294
|
if (navContainer && !getNavigationItemAnchor(target)) {
|
|
@@ -8274,6 +9303,15 @@ function OhhwellsBridge() {
|
|
|
8274
9303
|
setHoveredNavContainerRect(null);
|
|
8275
9304
|
}
|
|
8276
9305
|
}
|
|
9306
|
+
const footerCol = target.closest("[data-ohw-footer-col]");
|
|
9307
|
+
if (footerCol) {
|
|
9308
|
+
hoveredNavContainerRef.current = null;
|
|
9309
|
+
setHoveredNavContainerRect(null);
|
|
9310
|
+
if (selectedElRef.current === footerCol) return;
|
|
9311
|
+
hoveredItemElRef.current = footerCol;
|
|
9312
|
+
setHoveredItemRect(footerCol.getBoundingClientRect());
|
|
9313
|
+
return;
|
|
9314
|
+
}
|
|
8277
9315
|
const navAnchor = getNavigationItemAnchor(target);
|
|
8278
9316
|
if (navAnchor) {
|
|
8279
9317
|
hoveredNavContainerRef.current = null;
|
|
@@ -8310,6 +9348,15 @@ function OhhwellsBridge() {
|
|
|
8310
9348
|
hoveredNavContainerRef.current = null;
|
|
8311
9349
|
setHoveredNavContainerRect(null);
|
|
8312
9350
|
}
|
|
9351
|
+
const footerCol = target.closest("[data-ohw-footer-col]");
|
|
9352
|
+
if (footerCol && hoveredItemElRef.current === footerCol) {
|
|
9353
|
+
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
9354
|
+
if (related2?.closest("[data-ohw-drag-handle-container], [data-ohw-item-interaction]")) return;
|
|
9355
|
+
if (related2?.closest("[data-ohw-footer-col]") === footerCol) return;
|
|
9356
|
+
hoveredItemElRef.current = null;
|
|
9357
|
+
setHoveredItemRect(null);
|
|
9358
|
+
return;
|
|
9359
|
+
}
|
|
8313
9360
|
const navAnchor = getNavigationItemAnchor(target);
|
|
8314
9361
|
if (navAnchor) {
|
|
8315
9362
|
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
@@ -8421,12 +9468,12 @@ function OhhwellsBridge() {
|
|
|
8421
9468
|
const stickyPad = 48;
|
|
8422
9469
|
const withinPad = x >= pr.left - stickyPad && x <= pr.left + pr.width + stickyPad && y >= pr.top - stickyPad && y <= pr.top + pr.height + stickyPad;
|
|
8423
9470
|
if (withinPad) {
|
|
8424
|
-
|
|
9471
|
+
const yieldToSmaller = smallest !== pinned && candidatePool.includes(smallest) && (() => {
|
|
8425
9472
|
const sr = getVisibleRect(smallest);
|
|
8426
|
-
const
|
|
8427
|
-
|
|
8428
|
-
}
|
|
8429
|
-
return pinned;
|
|
9473
|
+
const pr2 = getVisibleRect(pinned);
|
|
9474
|
+
return sr.width * sr.height < pr2.width * pr2.height;
|
|
9475
|
+
})();
|
|
9476
|
+
if (!yieldToSmaller) return pinned;
|
|
8430
9477
|
}
|
|
8431
9478
|
}
|
|
8432
9479
|
return smallest;
|
|
@@ -8438,6 +9485,7 @@ function OhhwellsBridge() {
|
|
|
8438
9485
|
resumeAnimTracks();
|
|
8439
9486
|
postToParentRef.current({ type: "ow:image-unhover" });
|
|
8440
9487
|
}
|
|
9488
|
+
clearImageHover();
|
|
8441
9489
|
};
|
|
8442
9490
|
const probeNavigationHoverAt = (x, y) => {
|
|
8443
9491
|
if (toolbarVariantRef.current === "select-frame") {
|
|
@@ -8540,7 +9588,7 @@ function OhhwellsBridge() {
|
|
|
8540
9588
|
return;
|
|
8541
9589
|
}
|
|
8542
9590
|
const topEl = document.elementFromPoint(x2, y2);
|
|
8543
|
-
if (topEl?.closest('[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
9591
|
+
if (topEl?.closest('[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"], [data-ohw-media-chrome]')) {
|
|
8544
9592
|
if (hoveredImageRef.current) {
|
|
8545
9593
|
hoveredImageRef.current = null;
|
|
8546
9594
|
resumeAnimTracks();
|
|
@@ -8747,6 +9795,14 @@ function OhhwellsBridge() {
|
|
|
8747
9795
|
probeHoverCardsAt(clientX, clientY);
|
|
8748
9796
|
};
|
|
8749
9797
|
const handleDragOver = (e) => {
|
|
9798
|
+
const footerSession = footerDragRef.current;
|
|
9799
|
+
if (footerSession) {
|
|
9800
|
+
e.preventDefault();
|
|
9801
|
+
if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
|
|
9802
|
+
const slot = footerSession.kind === "link" && footerSession.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, footerSession.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
|
|
9803
|
+
refreshFooterDragVisualsRef.current(footerSession, slot, e.clientX, e.clientY);
|
|
9804
|
+
return;
|
|
9805
|
+
}
|
|
8750
9806
|
e.preventDefault();
|
|
8751
9807
|
const el = findImageAtPoint(e.clientX, e.clientY, false);
|
|
8752
9808
|
if (!el) {
|
|
@@ -8815,6 +9871,7 @@ function OhhwellsBridge() {
|
|
|
8815
9871
|
if (!entry || entry.fadingOut) return prev;
|
|
8816
9872
|
return { ...prev, [key]: { ...entry, fadingOut: true } };
|
|
8817
9873
|
});
|
|
9874
|
+
if (pendingUploadRectRef.current?.key === key) pendingUploadRectRef.current = null;
|
|
8818
9875
|
};
|
|
8819
9876
|
let found = false;
|
|
8820
9877
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -8929,6 +9986,7 @@ function OhhwellsBridge() {
|
|
|
8929
9986
|
continue;
|
|
8930
9987
|
}
|
|
8931
9988
|
if (applyVideoSettingNode(key, val)) continue;
|
|
9989
|
+
if (applyCarouselNode(key, val)) continue;
|
|
8932
9990
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
8933
9991
|
if (el.dataset.ohwEditable === "image") {
|
|
8934
9992
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
@@ -8953,6 +10011,7 @@ function OhhwellsBridge() {
|
|
|
8953
10011
|
}
|
|
8954
10012
|
editContentRef.current = { ...editContentRef.current, ...content };
|
|
8955
10013
|
reconcileNavbarItemsFromContent(editContentRef.current);
|
|
10014
|
+
reconcileFooterOrderFromContent(editContentRef.current);
|
|
8956
10015
|
enforceLinkHrefs();
|
|
8957
10016
|
postToParentRef.current({ type: "ow:hydrate-done" });
|
|
8958
10017
|
};
|
|
@@ -9066,6 +10125,17 @@ function OhhwellsBridge() {
|
|
|
9066
10125
|
if (siblingHintElRef.current) {
|
|
9067
10126
|
setSiblingHintRect(siblingHintElRef.current.getBoundingClientRect());
|
|
9068
10127
|
}
|
|
10128
|
+
const selected = selectedElRef.current;
|
|
10129
|
+
if (selected && !footerDragRef.current && (selected.hasAttribute("data-ohw-footer-col") || Boolean(selected.closest("footer") && isInferredFooterGroup(selected)))) {
|
|
10130
|
+
setSiblingHintRects(
|
|
10131
|
+
listFooterColumns().filter((column) => column !== selected).map((column) => column.getBoundingClientRect())
|
|
10132
|
+
);
|
|
10133
|
+
}
|
|
10134
|
+
if (footerDragRef.current) {
|
|
10135
|
+
const session = footerDragRef.current;
|
|
10136
|
+
const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
|
|
10137
|
+
refreshFooterDragVisualsRef.current(session, slot, session.lastClientX, session.lastClientY);
|
|
10138
|
+
}
|
|
9069
10139
|
if (hoveredImageRef.current) {
|
|
9070
10140
|
const el = hoveredImageRef.current;
|
|
9071
10141
|
const r2 = el.getBoundingClientRect();
|
|
@@ -9076,7 +10146,7 @@ function OhhwellsBridge() {
|
|
|
9076
10146
|
};
|
|
9077
10147
|
const handleSave = (e) => {
|
|
9078
10148
|
if (e.data?.type !== "ow:save") return;
|
|
9079
|
-
const nodes = collectEditableNodes();
|
|
10149
|
+
const nodes = collectEditableNodes(editContentRef.current);
|
|
9080
10150
|
const tracker = document.querySelector("[data-ohw-sections-tracker]");
|
|
9081
10151
|
if (tracker?.textContent) nodes.push({ key: "__ohw_sections", type: "sections", text: tracker.textContent });
|
|
9082
10152
|
postToParentRef.current({ type: "ow:save-result", nodes });
|
|
@@ -9161,28 +10231,49 @@ function OhhwellsBridge() {
|
|
|
9161
10231
|
const handleDocMouseLeave = () => {
|
|
9162
10232
|
hoveredImageRef.current = null;
|
|
9163
10233
|
setMediaHover(null);
|
|
10234
|
+
setCarouselHover(null);
|
|
9164
10235
|
document.querySelectorAll("[data-ohw-state-hovered]").forEach((el) => el.removeAttribute("data-ohw-state-hovered"));
|
|
9165
10236
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
9166
10237
|
activeStateElRef.current = null;
|
|
9167
10238
|
setToggleState(null);
|
|
9168
10239
|
};
|
|
10240
|
+
const resolveUploadRects = (key) => {
|
|
10241
|
+
const matches = Array.from(document.querySelectorAll(`[data-ohw-key="${key}"]`));
|
|
10242
|
+
const rects = matches.map((el) => {
|
|
10243
|
+
const r2 = el.getBoundingClientRect();
|
|
10244
|
+
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
10245
|
+
}).filter((r2) => r2.width > 1 && r2.height > 1);
|
|
10246
|
+
if (rects.length > 0) return rects;
|
|
10247
|
+
const pending = pendingUploadRectRef.current;
|
|
10248
|
+
if (pending?.key === key && pending.rect.width > 1 && pending.rect.height > 1) {
|
|
10249
|
+
return [pending.rect];
|
|
10250
|
+
}
|
|
10251
|
+
const hovered = hoveredImageRef.current;
|
|
10252
|
+
if (hovered?.dataset.ohwKey === key) {
|
|
10253
|
+
const r2 = hovered.getBoundingClientRect();
|
|
10254
|
+
if (r2.width > 1 && r2.height > 1) {
|
|
10255
|
+
return [{ top: r2.top, left: r2.left, width: r2.width, height: r2.height }];
|
|
10256
|
+
}
|
|
10257
|
+
}
|
|
10258
|
+
return [];
|
|
10259
|
+
};
|
|
9169
10260
|
const handleImageUploading = (e) => {
|
|
9170
|
-
|
|
9171
|
-
|
|
10261
|
+
const type = e.data?.type;
|
|
10262
|
+
if (type !== "ow:image-uploading" && type !== "ow:anim-lock") return;
|
|
10263
|
+
const key = e.data.key;
|
|
10264
|
+
if (!key) return;
|
|
10265
|
+
const uploading = type === "ow:anim-lock" ? true : !!e.data.uploading;
|
|
9172
10266
|
setUploadingRects((prev) => {
|
|
9173
10267
|
if (!uploading) {
|
|
10268
|
+
if (pendingUploadRectRef.current?.key === key) pendingUploadRectRef.current = null;
|
|
9174
10269
|
if (!(key in prev)) return prev;
|
|
9175
10270
|
const next = { ...prev };
|
|
9176
10271
|
delete next[key];
|
|
9177
10272
|
return next;
|
|
9178
10273
|
}
|
|
9179
|
-
const
|
|
9180
|
-
if (
|
|
9181
|
-
|
|
9182
|
-
return {
|
|
9183
|
-
...prev,
|
|
9184
|
-
[key]: { rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height } }
|
|
9185
|
-
};
|
|
10274
|
+
const rects = resolveUploadRects(key);
|
|
10275
|
+
if (rects.length === 0) return prev;
|
|
10276
|
+
return { ...prev, [key]: { rects } };
|
|
9186
10277
|
});
|
|
9187
10278
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
9188
10279
|
const track = el.closest("[data-ohw-hover-pause]");
|
|
@@ -9200,6 +10291,48 @@ function OhhwellsBridge() {
|
|
|
9200
10291
|
if (e.data?.type !== "ow:canvas-height" || typeof e.data.height !== "number") return;
|
|
9201
10292
|
document.documentElement.style.setProperty("--ohw-canvas-h", `${e.data.height}px`);
|
|
9202
10293
|
};
|
|
10294
|
+
const handleCarouselChange = (e) => {
|
|
10295
|
+
if (e.data?.type !== "ow:carousel-change") return;
|
|
10296
|
+
const { key, images } = e.data;
|
|
10297
|
+
if (!key || !Array.isArray(images)) return;
|
|
10298
|
+
const text = JSON.stringify(images);
|
|
10299
|
+
applyCarouselValue(key, images);
|
|
10300
|
+
editContentRef.current = { ...editContentRef.current, [key]: text };
|
|
10301
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key, text }] });
|
|
10302
|
+
setCarouselHover(null);
|
|
10303
|
+
};
|
|
10304
|
+
const findCarouselAtPoint = (clientX, clientY) => {
|
|
10305
|
+
const containers = Array.from(document.querySelectorAll(`[${CAROUSEL_ATTR}]`));
|
|
10306
|
+
for (let i = containers.length - 1; i >= 0; i--) {
|
|
10307
|
+
const r2 = containers[i].getBoundingClientRect();
|
|
10308
|
+
if (clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom) {
|
|
10309
|
+
return containers[i];
|
|
10310
|
+
}
|
|
10311
|
+
}
|
|
10312
|
+
return null;
|
|
10313
|
+
};
|
|
10314
|
+
const isPointOverEditable = (scope, clientX, clientY) => {
|
|
10315
|
+
const editables = scope.querySelectorAll("[data-ohw-editable], [data-ohw-href-key]");
|
|
10316
|
+
for (const el of editables) {
|
|
10317
|
+
const r2 = el.getBoundingClientRect();
|
|
10318
|
+
if (clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom) return true;
|
|
10319
|
+
}
|
|
10320
|
+
return false;
|
|
10321
|
+
};
|
|
10322
|
+
const handleCarouselHover = (e) => {
|
|
10323
|
+
const container = findCarouselAtPoint(e.clientX, e.clientY);
|
|
10324
|
+
const scope = container?.closest("[data-ohw-section]") ?? container?.parentElement ?? null;
|
|
10325
|
+
if (!container || !scope || isPointOverEditable(scope, e.clientX, e.clientY)) {
|
|
10326
|
+
setCarouselHover((prev) => prev ? null : prev);
|
|
10327
|
+
return;
|
|
10328
|
+
}
|
|
10329
|
+
const key = container.getAttribute("data-ohw-key") ?? "";
|
|
10330
|
+
if (!key) return;
|
|
10331
|
+
const r2 = getVisibleRect(container);
|
|
10332
|
+
setCarouselHover(
|
|
10333
|
+
(prev) => prev && prev.key === key && prev.rect.top === r2.top && prev.rect.left === r2.left && prev.rect.width === r2.width && prev.rect.height === r2.height ? prev : { key, rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height } }
|
|
10334
|
+
);
|
|
10335
|
+
};
|
|
9203
10336
|
const applyToolbarPos = (rect) => {
|
|
9204
10337
|
const ps = parentScrollRef.current;
|
|
9205
10338
|
const approxW = 330;
|
|
@@ -9308,6 +10441,7 @@ function OhhwellsBridge() {
|
|
|
9308
10441
|
window.addEventListener("message", handleRemoveSchedulingSection);
|
|
9309
10442
|
window.addEventListener("message", handleImageUrl);
|
|
9310
10443
|
window.addEventListener("message", handleImageUploading);
|
|
10444
|
+
window.addEventListener("message", handleCarouselChange);
|
|
9311
10445
|
window.addEventListener("message", handleCanvasHeight);
|
|
9312
10446
|
window.addEventListener("message", handleParentScroll);
|
|
9313
10447
|
window.addEventListener("message", handlePointerSync);
|
|
@@ -9325,6 +10459,7 @@ function OhhwellsBridge() {
|
|
|
9325
10459
|
document.addEventListener("mouseover", handleMouseOver, true);
|
|
9326
10460
|
document.addEventListener("mouseout", handleMouseOut, true);
|
|
9327
10461
|
document.addEventListener("mousemove", handleMouseMove, true);
|
|
10462
|
+
document.addEventListener("mousemove", handleCarouselHover, true);
|
|
9328
10463
|
document.addEventListener("mouseleave", handleDocMouseLeave);
|
|
9329
10464
|
document.addEventListener("dragover", handleDragOver, true);
|
|
9330
10465
|
document.addEventListener("dragleave", handleDragLeave, true);
|
|
@@ -9340,6 +10475,7 @@ function OhhwellsBridge() {
|
|
|
9340
10475
|
document.removeEventListener("mouseover", handleMouseOver, true);
|
|
9341
10476
|
document.removeEventListener("mouseout", handleMouseOut, true);
|
|
9342
10477
|
document.removeEventListener("mousemove", handleMouseMove, true);
|
|
10478
|
+
document.removeEventListener("mousemove", handleCarouselHover, true);
|
|
9343
10479
|
document.removeEventListener("mouseleave", handleDocMouseLeave);
|
|
9344
10480
|
document.removeEventListener("dragover", handleDragOver, true);
|
|
9345
10481
|
document.removeEventListener("dragleave", handleDragLeave, true);
|
|
@@ -9355,6 +10491,7 @@ function OhhwellsBridge() {
|
|
|
9355
10491
|
window.removeEventListener("message", handleRemoveSchedulingSection);
|
|
9356
10492
|
window.removeEventListener("message", handleImageUrl);
|
|
9357
10493
|
window.removeEventListener("message", handleImageUploading);
|
|
10494
|
+
window.removeEventListener("message", handleCarouselChange);
|
|
9358
10495
|
window.removeEventListener("message", handleCanvasHeight);
|
|
9359
10496
|
window.removeEventListener("message", handleParentScroll);
|
|
9360
10497
|
window.removeEventListener("resize", handleViewportResize);
|
|
@@ -9369,7 +10506,158 @@ function OhhwellsBridge() {
|
|
|
9369
10506
|
if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
|
|
9370
10507
|
};
|
|
9371
10508
|
}, [isEditMode, refreshStateRules]);
|
|
9372
|
-
|
|
10509
|
+
useEffect8(() => {
|
|
10510
|
+
if (!isEditMode) return;
|
|
10511
|
+
const THRESHOLD = 10;
|
|
10512
|
+
const resolveWasSelected = (el) => {
|
|
10513
|
+
if (selectedElRef.current === el) return true;
|
|
10514
|
+
const activeAnchor = activeElRef.current ? getNavigationItemAnchor(activeElRef.current) : null;
|
|
10515
|
+
return activeAnchor === el;
|
|
10516
|
+
};
|
|
10517
|
+
const onPointerDown = (e) => {
|
|
10518
|
+
if (e.button !== 0) return;
|
|
10519
|
+
if (suppressNextClickRef.current && !footerDragRef.current && !footerPointerDragRef.current?.started) {
|
|
10520
|
+
suppressNextClickRef.current = false;
|
|
10521
|
+
}
|
|
10522
|
+
if (footerDragRef.current) return;
|
|
10523
|
+
const target = e.target;
|
|
10524
|
+
if (!target) return;
|
|
10525
|
+
if (target.closest('[data-ohw-drag-handle-container], [data-slot="drag-handle"], [data-ohw-toolbar], [data-ohw-item-toolbar-anchor], [data-ohw-link-popover-root]')) {
|
|
10526
|
+
return;
|
|
10527
|
+
}
|
|
10528
|
+
if (target.closest("[data-ohw-item-drag-surface]")) return;
|
|
10529
|
+
const anchor = getNavigationItemAnchor(target);
|
|
10530
|
+
const hrefKey = anchor?.getAttribute("data-ohw-href-key") ?? null;
|
|
10531
|
+
if (anchor && isFooterHrefKey(hrefKey)) {
|
|
10532
|
+
armFooterPressDrag();
|
|
10533
|
+
footerPointerDragRef.current = {
|
|
10534
|
+
el: anchor,
|
|
10535
|
+
kind: "link",
|
|
10536
|
+
startX: e.clientX,
|
|
10537
|
+
startY: e.clientY,
|
|
10538
|
+
pointerId: e.pointerId,
|
|
10539
|
+
wasSelected: resolveWasSelected(anchor),
|
|
10540
|
+
started: false
|
|
10541
|
+
};
|
|
10542
|
+
return;
|
|
10543
|
+
}
|
|
10544
|
+
const col = target.closest("[data-ohw-footer-col]");
|
|
10545
|
+
if (col && !getNavigationItemAnchor(target)) {
|
|
10546
|
+
armFooterPressDrag();
|
|
10547
|
+
footerPointerDragRef.current = {
|
|
10548
|
+
el: col,
|
|
10549
|
+
kind: "column",
|
|
10550
|
+
startX: e.clientX,
|
|
10551
|
+
startY: e.clientY,
|
|
10552
|
+
pointerId: e.pointerId,
|
|
10553
|
+
wasSelected: resolveWasSelected(col),
|
|
10554
|
+
started: false
|
|
10555
|
+
};
|
|
10556
|
+
}
|
|
10557
|
+
};
|
|
10558
|
+
const onPointerMove = (e) => {
|
|
10559
|
+
const pending = footerPointerDragRef.current;
|
|
10560
|
+
if (!pending) return;
|
|
10561
|
+
if (pending.started) {
|
|
10562
|
+
e.preventDefault();
|
|
10563
|
+
clearTextSelection();
|
|
10564
|
+
const session = footerDragRef.current;
|
|
10565
|
+
if (!session) return;
|
|
10566
|
+
const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, session.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
|
|
10567
|
+
refreshFooterDragVisualsRef.current(session, slot, e.clientX, e.clientY);
|
|
10568
|
+
return;
|
|
10569
|
+
}
|
|
10570
|
+
const dx = e.clientX - pending.startX;
|
|
10571
|
+
const dy = e.clientY - pending.startY;
|
|
10572
|
+
if (dx * dx + dy * dy < THRESHOLD * THRESHOLD) return;
|
|
10573
|
+
e.preventDefault();
|
|
10574
|
+
pending.started = true;
|
|
10575
|
+
clearTextSelection();
|
|
10576
|
+
try {
|
|
10577
|
+
document.body.setPointerCapture(pending.pointerId);
|
|
10578
|
+
} catch {
|
|
10579
|
+
}
|
|
10580
|
+
if (linkPopoverOpenRef.current) {
|
|
10581
|
+
setLinkPopoverRef.current(null);
|
|
10582
|
+
}
|
|
10583
|
+
if (activeElRef.current) {
|
|
10584
|
+
deactivateRef.current();
|
|
10585
|
+
}
|
|
10586
|
+
if (pending.kind === "link") {
|
|
10587
|
+
const key = pending.el.getAttribute("data-ohw-href-key");
|
|
10588
|
+
if (!key) return;
|
|
10589
|
+
const column = findFooterColumnForLink(pending.el);
|
|
10590
|
+
const columns2 = listFooterColumns();
|
|
10591
|
+
beginFooterDragRef.current({
|
|
10592
|
+
kind: "link",
|
|
10593
|
+
hrefKey: key,
|
|
10594
|
+
columnEl: column,
|
|
10595
|
+
sourceColumnIndex: column ? columns2.indexOf(column) : 0,
|
|
10596
|
+
wasSelected: pending.wasSelected,
|
|
10597
|
+
draggedEl: pending.el,
|
|
10598
|
+
lastClientX: e.clientX,
|
|
10599
|
+
lastClientY: e.clientY,
|
|
10600
|
+
activeSlot: null
|
|
10601
|
+
});
|
|
10602
|
+
return;
|
|
10603
|
+
}
|
|
10604
|
+
const columns = listFooterColumns();
|
|
10605
|
+
const idx = columns.indexOf(pending.el);
|
|
10606
|
+
if (idx < 0) return;
|
|
10607
|
+
beginFooterDragRef.current({
|
|
10608
|
+
kind: "column",
|
|
10609
|
+
hrefKey: null,
|
|
10610
|
+
columnEl: pending.el,
|
|
10611
|
+
sourceColumnIndex: idx,
|
|
10612
|
+
wasSelected: pending.wasSelected,
|
|
10613
|
+
draggedEl: pending.el,
|
|
10614
|
+
lastClientX: e.clientX,
|
|
10615
|
+
lastClientY: e.clientY,
|
|
10616
|
+
activeSlot: null
|
|
10617
|
+
});
|
|
10618
|
+
};
|
|
10619
|
+
const endPointerDrag = (e) => {
|
|
10620
|
+
const pending = footerPointerDragRef.current;
|
|
10621
|
+
footerPointerDragRef.current = null;
|
|
10622
|
+
try {
|
|
10623
|
+
if (document.body.hasPointerCapture(e.pointerId)) {
|
|
10624
|
+
document.body.releasePointerCapture(e.pointerId);
|
|
10625
|
+
}
|
|
10626
|
+
} catch {
|
|
10627
|
+
}
|
|
10628
|
+
if (!pending?.started) {
|
|
10629
|
+
unlockFooterDragInteraction();
|
|
10630
|
+
return;
|
|
10631
|
+
}
|
|
10632
|
+
suppressNextClickRef.current = true;
|
|
10633
|
+
commitFooterDragRef.current(e.clientX, e.clientY);
|
|
10634
|
+
};
|
|
10635
|
+
const blockSelectStart = (e) => {
|
|
10636
|
+
if (footerDragRef.current || footerPointerDragRef.current?.started || document.documentElement.hasAttribute("data-ohw-footer-press-drag")) {
|
|
10637
|
+
e.preventDefault();
|
|
10638
|
+
}
|
|
10639
|
+
};
|
|
10640
|
+
const onDragEnd = (_e) => {
|
|
10641
|
+
if (!footerDragRef.current) return;
|
|
10642
|
+
commitFooterDragRef.current();
|
|
10643
|
+
};
|
|
10644
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
10645
|
+
document.addEventListener("pointermove", onPointerMove, true);
|
|
10646
|
+
document.addEventListener("pointerup", endPointerDrag, true);
|
|
10647
|
+
document.addEventListener("pointercancel", endPointerDrag, true);
|
|
10648
|
+
document.addEventListener("selectstart", blockSelectStart, true);
|
|
10649
|
+
document.addEventListener("dragend", onDragEnd, true);
|
|
10650
|
+
return () => {
|
|
10651
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
10652
|
+
document.removeEventListener("pointermove", onPointerMove, true);
|
|
10653
|
+
document.removeEventListener("pointerup", endPointerDrag, true);
|
|
10654
|
+
document.removeEventListener("pointercancel", endPointerDrag, true);
|
|
10655
|
+
document.removeEventListener("selectstart", blockSelectStart, true);
|
|
10656
|
+
document.removeEventListener("dragend", onDragEnd, true);
|
|
10657
|
+
unlockFooterDragInteraction();
|
|
10658
|
+
};
|
|
10659
|
+
}, [isEditMode]);
|
|
10660
|
+
useEffect8(() => {
|
|
9373
10661
|
const handler = (e) => {
|
|
9374
10662
|
if (e.data?.type !== "ow:request-schedule-config") return;
|
|
9375
10663
|
const insertAfterVal = e.data.insertAfter;
|
|
@@ -9385,7 +10673,7 @@ function OhhwellsBridge() {
|
|
|
9385
10673
|
window.addEventListener("message", handler);
|
|
9386
10674
|
return () => window.removeEventListener("message", handler);
|
|
9387
10675
|
}, [processConfigRequest]);
|
|
9388
|
-
|
|
10676
|
+
useEffect8(() => {
|
|
9389
10677
|
if (!isEditMode) return;
|
|
9390
10678
|
document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
|
|
9391
10679
|
el.removeAttribute("data-ohw-active-state");
|
|
@@ -9406,7 +10694,13 @@ function OhhwellsBridge() {
|
|
|
9406
10694
|
const next = { ...prev, [pathKey]: sections };
|
|
9407
10695
|
return shouldUseDevFixtures() ? { ...DEV_SECTIONS_BY_PATH, ...next } : next;
|
|
9408
10696
|
});
|
|
9409
|
-
postToParent2({
|
|
10697
|
+
postToParent2({
|
|
10698
|
+
type: "ow:ready",
|
|
10699
|
+
version: "1",
|
|
10700
|
+
path: pathname,
|
|
10701
|
+
nodes: collectEditableNodes(editContentRef.current),
|
|
10702
|
+
sections
|
|
10703
|
+
});
|
|
9410
10704
|
postToParent2({ type: "ow:request-site-pages" });
|
|
9411
10705
|
}, 150);
|
|
9412
10706
|
return () => {
|
|
@@ -9414,19 +10708,19 @@ function OhhwellsBridge() {
|
|
|
9414
10708
|
clearTimeout(timer);
|
|
9415
10709
|
};
|
|
9416
10710
|
}, [pathname, isEditMode, refreshStateRules, postToParent2]);
|
|
9417
|
-
|
|
10711
|
+
useEffect8(() => {
|
|
9418
10712
|
scrollToHashSectionWhenReady();
|
|
9419
10713
|
const onHashChange = () => scrollToHashSectionWhenReady();
|
|
9420
10714
|
window.addEventListener("hashchange", onHashChange);
|
|
9421
10715
|
return () => window.removeEventListener("hashchange", onHashChange);
|
|
9422
10716
|
}, [pathname]);
|
|
9423
|
-
const handleCommand =
|
|
10717
|
+
const handleCommand = useCallback4((cmd) => {
|
|
9424
10718
|
document.execCommand(cmd, false);
|
|
9425
10719
|
activeElRef.current?.focus();
|
|
9426
10720
|
if (activeElRef.current) setToolbarRect(getEditMeasureEl(activeElRef.current).getBoundingClientRect());
|
|
9427
10721
|
refreshActiveCommandsRef.current();
|
|
9428
10722
|
}, []);
|
|
9429
|
-
const handleStateChange =
|
|
10723
|
+
const handleStateChange = useCallback4((state) => {
|
|
9430
10724
|
if (!activeStateElRef.current) return;
|
|
9431
10725
|
const el = activeStateElRef.current;
|
|
9432
10726
|
if (state === "Default") {
|
|
@@ -9439,11 +10733,11 @@ function OhhwellsBridge() {
|
|
|
9439
10733
|
}
|
|
9440
10734
|
setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
|
|
9441
10735
|
}, [deactivate]);
|
|
9442
|
-
const closeLinkPopover =
|
|
10736
|
+
const closeLinkPopover = useCallback4(() => {
|
|
9443
10737
|
addNavAfterAnchorRef.current = null;
|
|
9444
10738
|
setLinkPopover(null);
|
|
9445
10739
|
}, []);
|
|
9446
|
-
const openLinkPopoverForActive =
|
|
10740
|
+
const openLinkPopoverForActive = useCallback4(() => {
|
|
9447
10741
|
const hrefCtx = getHrefKeyFromElement(activeElRef.current);
|
|
9448
10742
|
if (!hrefCtx) return;
|
|
9449
10743
|
bumpLinkPopoverGrace();
|
|
@@ -9454,7 +10748,7 @@ function OhhwellsBridge() {
|
|
|
9454
10748
|
});
|
|
9455
10749
|
deactivate();
|
|
9456
10750
|
}, [deactivate]);
|
|
9457
|
-
const openLinkPopoverForSelected =
|
|
10751
|
+
const openLinkPopoverForSelected = useCallback4(() => {
|
|
9458
10752
|
const anchor = selectedElRef.current;
|
|
9459
10753
|
if (!anchor) return;
|
|
9460
10754
|
const key = anchor.getAttribute("data-ohw-href-key");
|
|
@@ -9467,7 +10761,7 @@ function OhhwellsBridge() {
|
|
|
9467
10761
|
});
|
|
9468
10762
|
deselect();
|
|
9469
10763
|
}, [deselect]);
|
|
9470
|
-
const handleLinkPopoverSubmit =
|
|
10764
|
+
const handleLinkPopoverSubmit = useCallback4(
|
|
9471
10765
|
(target) => {
|
|
9472
10766
|
const session = linkPopoverSessionRef.current;
|
|
9473
10767
|
if (!session) return;
|
|
@@ -9523,16 +10817,22 @@ function OhhwellsBridge() {
|
|
|
9523
10817
|
},
|
|
9524
10818
|
[postToParent2, sitePages, sectionsByPath]
|
|
9525
10819
|
);
|
|
9526
|
-
const
|
|
9527
|
-
const currentSections = sectionsByPath[pathname] ?? [];
|
|
9528
|
-
linkPopoverOpenRef.current = linkPopover !== null;
|
|
9529
|
-
const handleMediaReplace = useCallback3(
|
|
10820
|
+
const handleMediaReplace = useCallback4(
|
|
9530
10821
|
(key) => {
|
|
10822
|
+
if (mediaHover?.key === key) {
|
|
10823
|
+
pendingUploadRectRef.current = { key, rect: mediaHover.rect };
|
|
10824
|
+
}
|
|
9531
10825
|
postToParent2({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
|
|
9532
10826
|
},
|
|
9533
|
-
[postToParent2, mediaHover
|
|
10827
|
+
[postToParent2, mediaHover]
|
|
9534
10828
|
);
|
|
9535
|
-
const
|
|
10829
|
+
const handleEditCarousel = useCallback4(
|
|
10830
|
+
(key) => {
|
|
10831
|
+
postToParent2({ type: "ow:carousel-open", key, images: readCarouselValue(key) });
|
|
10832
|
+
},
|
|
10833
|
+
[postToParent2]
|
|
10834
|
+
);
|
|
10835
|
+
const handleMediaFadeOutComplete = useCallback4((key) => {
|
|
9536
10836
|
setUploadingRects((prev) => {
|
|
9537
10837
|
if (!(key in prev)) return prev;
|
|
9538
10838
|
const next = { ...prev };
|
|
@@ -9540,7 +10840,7 @@ function OhhwellsBridge() {
|
|
|
9540
10840
|
return next;
|
|
9541
10841
|
});
|
|
9542
10842
|
}, []);
|
|
9543
|
-
const handleVideoSettingsChange =
|
|
10843
|
+
const handleVideoSettingsChange = useCallback4(
|
|
9544
10844
|
(key, settings) => {
|
|
9545
10845
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
9546
10846
|
const video = getVideoEl(el);
|
|
@@ -9562,21 +10862,26 @@ function OhhwellsBridge() {
|
|
|
9562
10862
|
},
|
|
9563
10863
|
[postToParent2]
|
|
9564
10864
|
);
|
|
10865
|
+
const showEditLink = toolbarShowEditLink;
|
|
10866
|
+
const currentSections = sectionsByPath[pathname] ?? [];
|
|
10867
|
+
linkPopoverOpenRef.current = linkPopover !== null;
|
|
9565
10868
|
return bridgeRoot ? createPortal2(
|
|
9566
|
-
/* @__PURE__ */
|
|
9567
|
-
/* @__PURE__ */
|
|
9568
|
-
Object.entries(uploadingRects).
|
|
9569
|
-
|
|
9570
|
-
|
|
9571
|
-
|
|
9572
|
-
|
|
9573
|
-
|
|
9574
|
-
|
|
9575
|
-
|
|
9576
|
-
|
|
9577
|
-
|
|
9578
|
-
|
|
9579
|
-
|
|
10869
|
+
/* @__PURE__ */ jsxs14(Fragment5, { children: [
|
|
10870
|
+
/* @__PURE__ */ jsx25("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
10871
|
+
Object.entries(uploadingRects).flatMap(
|
|
10872
|
+
([key, { rects, fadingOut }]) => rects.map((rect, i) => /* @__PURE__ */ jsx25(
|
|
10873
|
+
MediaOverlay,
|
|
10874
|
+
{
|
|
10875
|
+
hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
|
|
10876
|
+
isUploading: true,
|
|
10877
|
+
fadingOut,
|
|
10878
|
+
onFadeOutComplete: handleMediaFadeOutComplete,
|
|
10879
|
+
onReplace: handleMediaReplace
|
|
10880
|
+
},
|
|
10881
|
+
`uploading-${key}-${i}`
|
|
10882
|
+
))
|
|
10883
|
+
),
|
|
10884
|
+
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ jsx25(
|
|
9580
10885
|
MediaOverlay,
|
|
9581
10886
|
{
|
|
9582
10887
|
hover: mediaHover,
|
|
@@ -9585,62 +10890,33 @@ function OhhwellsBridge() {
|
|
|
9585
10890
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
9586
10891
|
}
|
|
9587
10892
|
),
|
|
9588
|
-
|
|
9589
|
-
|
|
9590
|
-
|
|
9591
|
-
|
|
9592
|
-
|
|
9593
|
-
|
|
9594
|
-
onAdd: handleAddTopLevelNavItem
|
|
9595
|
-
}
|
|
9596
|
-
),
|
|
9597
|
-
hoveredItemRect && !hoveredNavContainerRect && !siblingHintRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx23(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
9598
|
-
toolbarRect && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ jsx23(
|
|
9599
|
-
ItemInteractionLayer,
|
|
10893
|
+
carouselHover && /* @__PURE__ */ jsx25(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
|
|
10894
|
+
siblingHintRect && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
10895
|
+
siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
|
|
10896
|
+
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
|
|
10897
|
+
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ jsx25(
|
|
10898
|
+
"div",
|
|
9600
10899
|
{
|
|
9601
|
-
|
|
9602
|
-
|
|
9603
|
-
|
|
9604
|
-
|
|
9605
|
-
|
|
9606
|
-
|
|
9607
|
-
|
|
9608
|
-
|
|
9609
|
-
|
|
9610
|
-
|
|
9611
|
-
|
|
9612
|
-
|
|
9613
|
-
|
|
9614
|
-
|
|
9615
|
-
|
|
9616
|
-
|
|
9617
|
-
|
|
9618
|
-
}
|
|
9619
|
-
),
|
|
9620
|
-
toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
9621
|
-
/* @__PURE__ */ jsx23(
|
|
9622
|
-
EditGlowChrome,
|
|
9623
|
-
{
|
|
9624
|
-
rect: toolbarRect,
|
|
9625
|
-
elRef: glowElRef,
|
|
9626
|
-
reorderHrefKey,
|
|
9627
|
-
dragDisabled: reorderDragDisabled
|
|
9628
|
-
}
|
|
9629
|
-
),
|
|
9630
|
-
/* @__PURE__ */ jsx23(
|
|
9631
|
-
FloatingToolbar,
|
|
9632
|
-
{
|
|
9633
|
-
rect: toolbarRect,
|
|
9634
|
-
parentScroll: parentScrollRef.current,
|
|
9635
|
-
elRef: toolbarElRef,
|
|
9636
|
-
onCommand: handleCommand,
|
|
9637
|
-
activeCommands,
|
|
9638
|
-
showEditLink,
|
|
9639
|
-
onEditLink: openLinkPopoverForActive
|
|
9640
|
-
}
|
|
9641
|
-
)
|
|
10900
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
10901
|
+
style: {
|
|
10902
|
+
left: slot.left,
|
|
10903
|
+
top: slot.top,
|
|
10904
|
+
width: slot.width,
|
|
10905
|
+
height: slot.height
|
|
10906
|
+
},
|
|
10907
|
+
children: /* @__PURE__ */ jsx25(DropIndicator, { direction: slot.direction, state: activeFooterDropIndex === i ? "dragActive" : "dragIdle", className: slot.direction === "horizontal" ? "!h-full !w-full" : "!h-full !w-full" })
|
|
10908
|
+
},
|
|
10909
|
+
`footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
|
|
10910
|
+
)),
|
|
10911
|
+
hoveredNavContainerRect && toolbarVariant !== "select-frame" && !linkPopover && !isItemDragging && !siblingHintRect && siblingHintRects.length === 0 && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
|
|
10912
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && /* @__PURE__ */ jsx25(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
|
|
10913
|
+
hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !siblingHintRect && siblingHintRects.length === 0 && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
10914
|
+
toolbarRect && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: isItemDragging && draggedItemRect && footerDragRef.current?.wasSelected ? draggedItemRect : toolbarRect, elRef: glowElRef, state: isItemDragging ? "dragging" : resolveItemInteractionState(toolbarRect, parentScrollRef.current), showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey) || toolbarVariant === "select-frame" && isFooterFrameSelection, dragDisabled: reorderDragDisabled, dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item", onDragHandleDragStart: handleItemDragStart, onDragHandleDragEnd: handleItemDragEnd, onItemPointerDown: handleItemChromePointerDown, onItemClick: handleItemChromeClick, toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ jsx25(ItemActionToolbar, { onEditLink: openLinkPopoverForSelected, addItemDisabled: true, editLinkDisabled: false, moreDisabled: true }) : void 0 }),
|
|
10915
|
+
toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ jsxs14(Fragment5, { children: [
|
|
10916
|
+
/* @__PURE__ */ jsx25(EditGlowChrome, { rect: toolbarRect, elRef: glowElRef, reorderHrefKey, dragDisabled: reorderDragDisabled }),
|
|
10917
|
+
/* @__PURE__ */ jsx25(FloatingToolbar, { rect: toolbarRect, parentScroll: parentScrollRef.current, elRef: toolbarElRef, onCommand: handleCommand, activeCommands, showEditLink, onEditLink: openLinkPopoverForActive })
|
|
9642
10918
|
] }),
|
|
9643
|
-
maxBadge && /* @__PURE__ */
|
|
10919
|
+
maxBadge && /* @__PURE__ */ jsxs14(
|
|
9644
10920
|
"div",
|
|
9645
10921
|
{
|
|
9646
10922
|
"data-ohw-max-badge": "",
|
|
@@ -9666,57 +10942,29 @@ function OhhwellsBridge() {
|
|
|
9666
10942
|
]
|
|
9667
10943
|
}
|
|
9668
10944
|
),
|
|
9669
|
-
toggleState && !linkPopover && /* @__PURE__ */
|
|
9670
|
-
|
|
9671
|
-
{
|
|
9672
|
-
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
|
|
9677
|
-
|
|
9678
|
-
|
|
9679
|
-
|
|
9680
|
-
|
|
9681
|
-
|
|
9682
|
-
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
9683
|
-
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
9684
|
-
children: [
|
|
9685
|
-
/* @__PURE__ */ jsx23("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
9686
|
-
/* @__PURE__ */ jsx23(
|
|
9687
|
-
Badge,
|
|
9688
|
-
{
|
|
9689
|
-
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",
|
|
9690
|
-
onClick: () => {
|
|
9691
|
-
window.parent.postMessage(
|
|
9692
|
-
{ type: "ow:add-section", insertAfter: sectionGap.insertAfter, insertBefore: sectionGap.insertBefore },
|
|
9693
|
-
"*"
|
|
9694
|
-
);
|
|
10945
|
+
toggleState && !linkPopover && /* @__PURE__ */ jsx25(StateToggle, { rect: toggleState.rect, activeState: toggleState.activeState, states: toggleState.states, onStateChange: handleStateChange }),
|
|
10946
|
+
sectionGap && !linkPopover && /* @__PURE__ */ jsxs14("div", { "data-ohw-section-insert-line": "", className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none", style: { top: sectionGap.y, transform: "translateY(-50%)" }, children: [
|
|
10947
|
+
/* @__PURE__ */ jsx25("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
10948
|
+
/* @__PURE__ */ jsx25(
|
|
10949
|
+
Badge,
|
|
10950
|
+
{
|
|
10951
|
+
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",
|
|
10952
|
+
onClick: () => {
|
|
10953
|
+
window.parent.postMessage(
|
|
10954
|
+
{
|
|
10955
|
+
type: "ow:add-section",
|
|
10956
|
+
insertAfter: sectionGap.insertAfter,
|
|
10957
|
+
insertBefore: sectionGap.insertBefore
|
|
9695
10958
|
},
|
|
9696
|
-
|
|
9697
|
-
|
|
9698
|
-
|
|
9699
|
-
|
|
9700
|
-
|
|
9701
|
-
|
|
9702
|
-
|
|
9703
|
-
|
|
9704
|
-
|
|
9705
|
-
{
|
|
9706
|
-
panelRef: linkPopoverPanelRef,
|
|
9707
|
-
portalContainer: dialogPortalContainer,
|
|
9708
|
-
open: true,
|
|
9709
|
-
mode: linkPopover.mode ?? "edit",
|
|
9710
|
-
pages: sitePages,
|
|
9711
|
-
sections: currentSections,
|
|
9712
|
-
sectionsByPath,
|
|
9713
|
-
initialTarget: linkPopover.target,
|
|
9714
|
-
existingTargets: linkPopover.intent === "add-nav" ? getNavbarExistingTargets() : [],
|
|
9715
|
-
onClose: closeLinkPopover,
|
|
9716
|
-
onSubmit: handleLinkPopoverSubmit
|
|
9717
|
-
},
|
|
9718
|
-
linkPopover.key
|
|
9719
|
-
) : null
|
|
10959
|
+
"*"
|
|
10960
|
+
);
|
|
10961
|
+
},
|
|
10962
|
+
children: "Add Section"
|
|
10963
|
+
}
|
|
10964
|
+
),
|
|
10965
|
+
/* @__PURE__ */ jsx25("div", { className: "flex-1 bg-primary", style: { height: 3 } })
|
|
10966
|
+
] }),
|
|
10967
|
+
linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx25(LinkPopover, { panelRef: linkPopoverPanelRef, portalContainer: dialogPortalContainer, open: true, mode: linkPopover.mode ?? "edit", pages: sitePages, sections: currentSections, sectionsByPath, initialTarget: linkPopover.target, existingTargets: linkPopover.intent === "add-nav" ? getNavbarExistingTargets() : [], onClose: closeLinkPopover, onSubmit: handleLinkPopoverSubmit }, linkPopover.key) : null
|
|
9720
10968
|
] }),
|
|
9721
10969
|
bridgeRoot
|
|
9722
10970
|
) : null;
|
|
@@ -9726,6 +10974,7 @@ export {
|
|
|
9726
10974
|
CustomToolbarButton,
|
|
9727
10975
|
CustomToolbarDivider,
|
|
9728
10976
|
DragHandle,
|
|
10977
|
+
DropIndicator,
|
|
9729
10978
|
ItemActionToolbar,
|
|
9730
10979
|
ItemInteractionLayer,
|
|
9731
10980
|
LinkEditorPanel,
|
|
@@ -9740,12 +10989,14 @@ export {
|
|
|
9740
10989
|
TooltipProvider,
|
|
9741
10990
|
TooltipTrigger,
|
|
9742
10991
|
buildTarget,
|
|
10992
|
+
dropIndicatorVariants,
|
|
9743
10993
|
filterAvailablePages,
|
|
9744
10994
|
getEditModeInitialState,
|
|
9745
10995
|
isEditSessionActive,
|
|
9746
10996
|
isValidUrl,
|
|
9747
10997
|
parseTarget,
|
|
9748
10998
|
toggleVariants,
|
|
10999
|
+
useOhwCarousel,
|
|
9749
11000
|
validateUrlInput
|
|
9750
11001
|
};
|
|
9751
11002
|
//# sourceMappingURL=index.js.map
|