@ohhwells/bridge 0.1.40 → 0.1.42-next.81
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 +1787 -489
- 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 +1736 -441
- package/dist/index.js.map +1 -1
- package/dist/styles.css +42 -18
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -35,6 +35,7 @@ __export(index_exports, {
|
|
|
35
35
|
CustomToolbarButton: () => CustomToolbarButton,
|
|
36
36
|
CustomToolbarDivider: () => CustomToolbarDivider,
|
|
37
37
|
DragHandle: () => DragHandle,
|
|
38
|
+
DropIndicator: () => DropIndicator,
|
|
38
39
|
ItemActionToolbar: () => ItemActionToolbar,
|
|
39
40
|
ItemInteractionLayer: () => ItemInteractionLayer,
|
|
40
41
|
LinkEditorPanel: () => LinkEditorPanel,
|
|
@@ -49,18 +50,20 @@ __export(index_exports, {
|
|
|
49
50
|
TooltipProvider: () => TooltipProvider,
|
|
50
51
|
TooltipTrigger: () => TooltipTrigger,
|
|
51
52
|
buildTarget: () => buildTarget,
|
|
53
|
+
dropIndicatorVariants: () => dropIndicatorVariants,
|
|
52
54
|
filterAvailablePages: () => filterAvailablePages,
|
|
53
55
|
getEditModeInitialState: () => getEditModeInitialState,
|
|
54
56
|
isEditSessionActive: () => isEditSessionActive,
|
|
55
57
|
isValidUrl: () => isValidUrl,
|
|
56
58
|
parseTarget: () => parseTarget,
|
|
57
59
|
toggleVariants: () => toggleVariants,
|
|
60
|
+
useOhwCarousel: () => useOhwCarousel,
|
|
58
61
|
validateUrlInput: () => validateUrlInput
|
|
59
62
|
});
|
|
60
63
|
module.exports = __toCommonJS(index_exports);
|
|
61
64
|
|
|
62
65
|
// src/OhhwellsBridge.tsx
|
|
63
|
-
var
|
|
66
|
+
var import_react9 = __toESM(require("react"), 1);
|
|
64
67
|
var import_client = require("react-dom/client");
|
|
65
68
|
var import_react_dom2 = require("react-dom");
|
|
66
69
|
|
|
@@ -113,6 +116,7 @@ var import_react3 = require("react");
|
|
|
113
116
|
var import_react2 = require("react");
|
|
114
117
|
var import_radix_ui = require("radix-ui");
|
|
115
118
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
119
|
+
var isValidEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
116
120
|
function Spinner() {
|
|
117
121
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
118
122
|
"svg",
|
|
@@ -146,12 +150,17 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
|
|
|
146
150
|
const [error, setError] = (0, import_react2.useState)(null);
|
|
147
151
|
const isBook = title === "Confirm your spot";
|
|
148
152
|
const handleSubmit = async () => {
|
|
149
|
-
|
|
153
|
+
const trimmed = email.trim();
|
|
154
|
+
if (!trimmed) return;
|
|
155
|
+
if (!isValidEmail(trimmed)) {
|
|
156
|
+
setError("Please enter a valid email address.");
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
150
159
|
setLoading(true);
|
|
151
160
|
setError(null);
|
|
152
161
|
try {
|
|
153
|
-
await onSubmit(
|
|
154
|
-
setSubmittedEmail(
|
|
162
|
+
await onSubmit(trimmed);
|
|
163
|
+
setSubmittedEmail(trimmed);
|
|
155
164
|
setSuccess(true);
|
|
156
165
|
} catch (e) {
|
|
157
166
|
setError(e instanceof Error ? e.message : "Something went wrong. Please try again.");
|
|
@@ -226,7 +235,10 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
|
|
|
226
235
|
{
|
|
227
236
|
type: "email",
|
|
228
237
|
value: email,
|
|
229
|
-
onChange: (e) =>
|
|
238
|
+
onChange: (e) => {
|
|
239
|
+
setEmail(e.target.value);
|
|
240
|
+
if (error) setError(null);
|
|
241
|
+
},
|
|
230
242
|
onKeyDown: handleKeyDown,
|
|
231
243
|
placeholder: "hello@gmail.com",
|
|
232
244
|
autoFocus: true,
|
|
@@ -283,12 +295,20 @@ function formatClassTime(cls) {
|
|
|
283
295
|
const em = endTotal % 60;
|
|
284
296
|
return `${h}:${cls.startTime.minutes}-${eh}:${String(em).padStart(2, "0")}`;
|
|
285
297
|
}
|
|
298
|
+
function formatBookingLabel(cls) {
|
|
299
|
+
const price = cls.price;
|
|
300
|
+
const isFree = price === null || price === void 0 || `${price}` === "" || `${price}` === "0";
|
|
301
|
+
return isFree ? "Book for free" : `Book for ${cls.currency ?? ""} ${price}`.trim();
|
|
302
|
+
}
|
|
286
303
|
function getBookingsOnDate(cls, date) {
|
|
287
304
|
if (!cls.bookings?.length) return 0;
|
|
288
|
-
const
|
|
305
|
+
const target = new Date(date);
|
|
306
|
+
target.setHours(0, 0, 0, 0);
|
|
289
307
|
return cls.bookings.filter((b) => {
|
|
290
308
|
try {
|
|
291
|
-
|
|
309
|
+
const bookingDate = new Date(b.classDate);
|
|
310
|
+
bookingDate.setHours(0, 0, 0, 0);
|
|
311
|
+
return bookingDate.getTime() === target.getTime();
|
|
292
312
|
} catch {
|
|
293
313
|
return false;
|
|
294
314
|
}
|
|
@@ -553,7 +573,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
|
|
|
553
573
|
}
|
|
554
574
|
)
|
|
555
575
|
] }),
|
|
556
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "sm:hidden flex flex-col gap-px", children: isFull ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
576
|
+
cls.showAvailability !== false && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "sm:hidden flex flex-col gap-px", children: isFull ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
557
577
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
|
|
558
578
|
available,
|
|
559
579
|
"/",
|
|
@@ -565,9 +585,10 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
|
|
|
565
585
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-1 flex-col gap-2 min-w-0 sm:contents", children: [
|
|
566
586
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex-1 flex flex-col gap-2 min-w-0", children: [
|
|
567
587
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-base font-bold text-(--color-dark,#200C02) block truncate", children: cls.name }),
|
|
568
|
-
cls.hostName && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block truncate", children: cls.hostName })
|
|
588
|
+
cls.hostName && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block truncate", children: cls.hostName }),
|
|
589
|
+
cls.description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-sm font-normal text-(--color-dark,#200C02) opacity-70 block truncate", children: cls.description })
|
|
569
590
|
] }),
|
|
570
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "hidden sm:flex w-14 shrink-0 flex-col gap-px", children: isFull ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
591
|
+
cls.showAvailability !== false && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "hidden sm:flex w-14 shrink-0 flex-col gap-px", children: isFull ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
571
592
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
|
|
572
593
|
available,
|
|
573
594
|
"/",
|
|
@@ -592,7 +613,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
|
|
|
592
613
|
if (!cls.id) return;
|
|
593
614
|
onOpenModal?.(isFull ? "waitlist" : "book", cls.id, selectedDate);
|
|
594
615
|
},
|
|
595
|
-
children: isFull ? "Join Waitlist" :
|
|
616
|
+
children: isFull ? "Join Waitlist" : formatBookingLabel(cls)
|
|
596
617
|
}
|
|
597
618
|
)
|
|
598
619
|
] })
|
|
@@ -634,6 +655,17 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
634
655
|
const [isHovered, setIsHovered] = (0, import_react3.useState)(false);
|
|
635
656
|
const [modalState, setModalState] = (0, import_react3.useState)(null);
|
|
636
657
|
const switchScheduleIdRef = (0, import_react3.useRef)(null);
|
|
658
|
+
const liveScheduleIdRef = (0, import_react3.useRef)(null);
|
|
659
|
+
const refetchLiveSchedule = (0, import_react3.useCallback)(async () => {
|
|
660
|
+
const id = liveScheduleIdRef.current;
|
|
661
|
+
if (!id) return;
|
|
662
|
+
try {
|
|
663
|
+
const res = await fetch(`${API_URL}/api/schedule/id/${id}`);
|
|
664
|
+
const data = await res.json();
|
|
665
|
+
if (data?.id) setSchedule(data);
|
|
666
|
+
} catch {
|
|
667
|
+
}
|
|
668
|
+
}, []);
|
|
637
669
|
const dates = (0, import_react3.useMemo)(() => {
|
|
638
670
|
const today = /* @__PURE__ */ new Date();
|
|
639
671
|
today.setHours(0, 0, 0, 0);
|
|
@@ -653,6 +685,18 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
653
685
|
}
|
|
654
686
|
}
|
|
655
687
|
}, [schedule, dates]);
|
|
688
|
+
(0, import_react3.useEffect)(() => {
|
|
689
|
+
if (typeof window === "undefined") return;
|
|
690
|
+
const onVisible = () => {
|
|
691
|
+
if (!document.hidden) void refetchLiveSchedule();
|
|
692
|
+
};
|
|
693
|
+
window.addEventListener("focus", refetchLiveSchedule);
|
|
694
|
+
document.addEventListener("visibilitychange", onVisible);
|
|
695
|
+
return () => {
|
|
696
|
+
window.removeEventListener("focus", refetchLiveSchedule);
|
|
697
|
+
document.removeEventListener("visibilitychange", onVisible);
|
|
698
|
+
};
|
|
699
|
+
}, [refetchLiveSchedule]);
|
|
656
700
|
(0, import_react3.useEffect)(() => {
|
|
657
701
|
if (typeof window === "undefined") return;
|
|
658
702
|
const isInEditor = window.self !== window.top;
|
|
@@ -714,7 +758,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
714
758
|
setLoading(false);
|
|
715
759
|
return;
|
|
716
760
|
}
|
|
717
|
-
;
|
|
761
|
+
liveScheduleIdRef.current = effectiveId;
|
|
718
762
|
(async () => {
|
|
719
763
|
try {
|
|
720
764
|
const res = await fetch(`${API_URL}/api/schedule/id/${effectiveId}`);
|
|
@@ -771,18 +815,14 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
771
815
|
const data = await res.json().catch(() => ({}));
|
|
772
816
|
throw new Error(data?.message ?? "Something went wrong. Please try again.");
|
|
773
817
|
}
|
|
818
|
+
await refetchLiveSchedule();
|
|
774
819
|
};
|
|
775
820
|
const handleReplaceSchedule = () => {
|
|
776
821
|
setIsHovered(false);
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
insertAfter
|
|
782
|
-
}, "*");
|
|
783
|
-
} else {
|
|
784
|
-
window.parent.postMessage({ type: "ow:scheduling-not-connected", insertAfter }, "*");
|
|
785
|
-
}
|
|
822
|
+
window.parent.postMessage(
|
|
823
|
+
{ type: "ow:scheduling-not-connected", insertAfter, currentScheduleId: schedule?.id },
|
|
824
|
+
"*"
|
|
825
|
+
);
|
|
786
826
|
};
|
|
787
827
|
if (!inEditor && !loading && !schedule) return null;
|
|
788
828
|
const sectionId = `scheduling-${insertAfter}`;
|
|
@@ -825,7 +865,19 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
825
865
|
),
|
|
826
866
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "max-w-[1280px] mx-auto flex flex-col items-center gap-16", children: [
|
|
827
867
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-col items-center gap-4", children: [
|
|
828
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
868
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
869
|
+
"h2",
|
|
870
|
+
{
|
|
871
|
+
className: "font-display text-center m-0 text-(--color-dark,#200C02)",
|
|
872
|
+
style: {
|
|
873
|
+
fontSize: "var(--fs-section-h2, clamp(40px, 4.4vw, 64px))",
|
|
874
|
+
fontWeight: "var(--font-weight-heading, 400)",
|
|
875
|
+
lineHeight: 1.05,
|
|
876
|
+
letterSpacing: "-0.02em"
|
|
877
|
+
},
|
|
878
|
+
children: schedule?.name ?? "Book an appointment"
|
|
879
|
+
}
|
|
880
|
+
),
|
|
829
881
|
schedule?.description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "font-body text-body text-center m-0 text-(--color-accent,#A89B83)", children: schedule.description })
|
|
830
882
|
] }),
|
|
831
883
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "w-full flex flex-col items-end gap-3", children: [
|
|
@@ -4503,7 +4555,7 @@ function getChromeStyle(state) {
|
|
|
4503
4555
|
case "dragging":
|
|
4504
4556
|
return {
|
|
4505
4557
|
border: `2px solid ${PRIMARY}`,
|
|
4506
|
-
boxShadow: DRAG_SHADOW
|
|
4558
|
+
boxShadow: `${FOCUS_RING}, ${DRAG_SHADOW}`
|
|
4507
4559
|
};
|
|
4508
4560
|
default:
|
|
4509
4561
|
return {};
|
|
@@ -4519,6 +4571,8 @@ function ItemInteractionLayer({
|
|
|
4519
4571
|
dragHandleLabel = "Reorder item",
|
|
4520
4572
|
onDragHandleDragStart,
|
|
4521
4573
|
onDragHandleDragEnd,
|
|
4574
|
+
onItemPointerDown,
|
|
4575
|
+
onItemClick,
|
|
4522
4576
|
chromeGap = 6,
|
|
4523
4577
|
className
|
|
4524
4578
|
}) {
|
|
@@ -4526,7 +4580,8 @@ function ItemInteractionLayer({
|
|
|
4526
4580
|
const isActive = state === "active-top" || state === "active-bottom";
|
|
4527
4581
|
const isDragging = state === "dragging";
|
|
4528
4582
|
const showToolbar = isActive && toolbar;
|
|
4529
|
-
const showDragHandle = isActive
|
|
4583
|
+
const showDragHandle = (isActive || isDragging) && showHandle;
|
|
4584
|
+
const itemDragEnabled = isActive && showHandle && !isDragging && !dragDisabled;
|
|
4530
4585
|
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
4531
4586
|
"div",
|
|
4532
4587
|
{
|
|
@@ -4551,11 +4606,28 @@ function ItemInteractionLayer({
|
|
|
4551
4606
|
style: getChromeStyle(state)
|
|
4552
4607
|
}
|
|
4553
4608
|
),
|
|
4609
|
+
itemDragEnabled && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4610
|
+
"div",
|
|
4611
|
+
{
|
|
4612
|
+
"data-ohw-item-drag-surface": "",
|
|
4613
|
+
className: "pointer-events-auto absolute inset-0 cursor-grab rounded-lg active:cursor-grabbing",
|
|
4614
|
+
onPointerDown: (e) => {
|
|
4615
|
+
if (e.button !== 0) return;
|
|
4616
|
+
onItemPointerDown?.(e);
|
|
4617
|
+
},
|
|
4618
|
+
onClick: (e) => {
|
|
4619
|
+
e.preventDefault();
|
|
4620
|
+
e.stopPropagation();
|
|
4621
|
+
onItemClick?.(e.clientX, e.clientY);
|
|
4622
|
+
}
|
|
4623
|
+
}
|
|
4624
|
+
),
|
|
4554
4625
|
showDragHandle && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4555
4626
|
"div",
|
|
4556
4627
|
{
|
|
4557
4628
|
"data-ohw-drag-handle-container": "",
|
|
4558
|
-
className: "pointer-events-auto absolute left-0 top-1/2 -translate-x-[calc(100%+7px)] -translate-y-1/2",
|
|
4629
|
+
className: "pointer-events-auto absolute left-0 top-1/2 z-10 -translate-x-[calc(100%+7px)] -translate-y-1/2",
|
|
4630
|
+
style: isDragging ? { visibility: "hidden" } : void 0,
|
|
4559
4631
|
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4560
4632
|
DragHandle,
|
|
4561
4633
|
{
|
|
@@ -4778,15 +4850,12 @@ function MediaOverlay({
|
|
|
4778
4850
|
className: "flex items-center justify-center cursor-pointer",
|
|
4779
4851
|
style: {
|
|
4780
4852
|
...box,
|
|
4781
|
-
//
|
|
4782
|
-
//
|
|
4783
|
-
|
|
4784
|
-
// Replace still works.
|
|
4785
|
-
pointerEvents: hover.hasTextOverlap ? "none" : "auto",
|
|
4853
|
+
// Keep the full-size visual overlay click-through so carousel controls and editable
|
|
4854
|
+
// content underneath remain interactive. The Replace button opts back in below.
|
|
4855
|
+
pointerEvents: "none",
|
|
4786
4856
|
boxShadow: "inset 0 0 0 1.5px var(--color-primary)",
|
|
4787
4857
|
background: "color-mix(in srgb, var(--color-primary) 20%, transparent)"
|
|
4788
4858
|
},
|
|
4789
|
-
onClick: () => onReplace(hover.key),
|
|
4790
4859
|
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
4791
4860
|
Button,
|
|
4792
4861
|
{
|
|
@@ -4811,6 +4880,61 @@ function MediaOverlay({
|
|
|
4811
4880
|
] });
|
|
4812
4881
|
}
|
|
4813
4882
|
|
|
4883
|
+
// src/ui/CarouselOverlay.tsx
|
|
4884
|
+
var import_lucide_react4 = require("lucide-react");
|
|
4885
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
4886
|
+
var OVERLAY_BUTTON_STYLE2 = {
|
|
4887
|
+
pointerEvents: "auto",
|
|
4888
|
+
fontFamily: "Inter, sans-serif",
|
|
4889
|
+
fontSize: 12,
|
|
4890
|
+
color: "#000"
|
|
4891
|
+
};
|
|
4892
|
+
function CarouselOverlay({
|
|
4893
|
+
hover,
|
|
4894
|
+
onEdit
|
|
4895
|
+
}) {
|
|
4896
|
+
const { rect } = hover;
|
|
4897
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
4898
|
+
"div",
|
|
4899
|
+
{
|
|
4900
|
+
"data-ohw-bridge": "",
|
|
4901
|
+
"data-ohw-carousel-overlay": "",
|
|
4902
|
+
className: "flex cursor-pointer items-center justify-center",
|
|
4903
|
+
style: {
|
|
4904
|
+
position: "fixed",
|
|
4905
|
+
top: rect.top,
|
|
4906
|
+
left: rect.left,
|
|
4907
|
+
width: rect.width,
|
|
4908
|
+
height: rect.height,
|
|
4909
|
+
zIndex: 2147483646,
|
|
4910
|
+
pointerEvents: "auto",
|
|
4911
|
+
boxShadow: "inset 0 0 0 1.5px var(--color-primary)",
|
|
4912
|
+
background: "color-mix(in srgb, var(--color-primary) 20%, transparent)"
|
|
4913
|
+
},
|
|
4914
|
+
onClick: () => onEdit(hover.key),
|
|
4915
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
4916
|
+
Button,
|
|
4917
|
+
{
|
|
4918
|
+
"data-ohw-carousel-overlay": "",
|
|
4919
|
+
variant: "outline",
|
|
4920
|
+
size: "sm",
|
|
4921
|
+
className: "cursor-pointer gap-1.5 hover:bg-background",
|
|
4922
|
+
style: OVERLAY_BUTTON_STYLE2,
|
|
4923
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
4924
|
+
onClick: (e) => {
|
|
4925
|
+
e.stopPropagation();
|
|
4926
|
+
onEdit(hover.key);
|
|
4927
|
+
},
|
|
4928
|
+
children: [
|
|
4929
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react4.GalleryHorizontal, { size: 14 }),
|
|
4930
|
+
"Edit gallery"
|
|
4931
|
+
]
|
|
4932
|
+
}
|
|
4933
|
+
)
|
|
4934
|
+
}
|
|
4935
|
+
);
|
|
4936
|
+
}
|
|
4937
|
+
|
|
4814
4938
|
// src/OhhwellsBridge.tsx
|
|
4815
4939
|
var import_react_dom3 = require("react-dom");
|
|
4816
4940
|
var import_navigation2 = require("next/navigation");
|
|
@@ -5096,23 +5220,23 @@ var import_react7 = require("react");
|
|
|
5096
5220
|
// src/ui/dialog.tsx
|
|
5097
5221
|
var React7 = __toESM(require("react"), 1);
|
|
5098
5222
|
var import_radix_ui5 = require("radix-ui");
|
|
5099
|
-
var
|
|
5100
|
-
var
|
|
5223
|
+
var import_lucide_react5 = require("lucide-react");
|
|
5224
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
5101
5225
|
function Dialog2({
|
|
5102
5226
|
...props
|
|
5103
5227
|
}) {
|
|
5104
|
-
return /* @__PURE__ */ (0,
|
|
5228
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_radix_ui5.Dialog.Root, { "data-slot": "dialog", ...props });
|
|
5105
5229
|
}
|
|
5106
5230
|
function DialogPortal({
|
|
5107
5231
|
...props
|
|
5108
5232
|
}) {
|
|
5109
|
-
return /* @__PURE__ */ (0,
|
|
5233
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_radix_ui5.Dialog.Portal, { ...props });
|
|
5110
5234
|
}
|
|
5111
5235
|
function DialogOverlay({
|
|
5112
5236
|
className,
|
|
5113
5237
|
...props
|
|
5114
5238
|
}) {
|
|
5115
|
-
return /* @__PURE__ */ (0,
|
|
5239
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
5116
5240
|
import_radix_ui5.Dialog.Overlay,
|
|
5117
5241
|
{
|
|
5118
5242
|
"data-slot": "dialog-overlay",
|
|
@@ -5125,9 +5249,9 @@ function DialogOverlay({
|
|
|
5125
5249
|
var DialogContent = React7.forwardRef(
|
|
5126
5250
|
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
5127
5251
|
const positionMode = container ? "absolute" : "fixed";
|
|
5128
|
-
return /* @__PURE__ */ (0,
|
|
5129
|
-
/* @__PURE__ */ (0,
|
|
5130
|
-
/* @__PURE__ */ (0,
|
|
5252
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(DialogPortal, { container: container ?? void 0, children: [
|
|
5253
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
5254
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
5131
5255
|
import_radix_ui5.Dialog.Content,
|
|
5132
5256
|
{
|
|
5133
5257
|
ref,
|
|
@@ -5143,13 +5267,13 @@ var DialogContent = React7.forwardRef(
|
|
|
5143
5267
|
...props,
|
|
5144
5268
|
children: [
|
|
5145
5269
|
children,
|
|
5146
|
-
showCloseButton ? /* @__PURE__ */ (0,
|
|
5270
|
+
showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
5147
5271
|
import_radix_ui5.Dialog.Close,
|
|
5148
5272
|
{
|
|
5149
5273
|
type: "button",
|
|
5150
5274
|
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
5151
5275
|
"aria-label": "Close",
|
|
5152
|
-
children: /* @__PURE__ */ (0,
|
|
5276
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react5.X, { size: 16, "aria-hidden": true })
|
|
5153
5277
|
}
|
|
5154
5278
|
) : null
|
|
5155
5279
|
]
|
|
@@ -5163,13 +5287,13 @@ function DialogHeader({
|
|
|
5163
5287
|
className,
|
|
5164
5288
|
...props
|
|
5165
5289
|
}) {
|
|
5166
|
-
return /* @__PURE__ */ (0,
|
|
5290
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
5167
5291
|
}
|
|
5168
5292
|
function DialogFooter({
|
|
5169
5293
|
className,
|
|
5170
5294
|
...props
|
|
5171
5295
|
}) {
|
|
5172
|
-
return /* @__PURE__ */ (0,
|
|
5296
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
5173
5297
|
"div",
|
|
5174
5298
|
{
|
|
5175
5299
|
className: cn("flex items-center justify-end gap-2", className),
|
|
@@ -5177,7 +5301,7 @@ function DialogFooter({
|
|
|
5177
5301
|
}
|
|
5178
5302
|
);
|
|
5179
5303
|
}
|
|
5180
|
-
var DialogTitle = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0,
|
|
5304
|
+
var DialogTitle = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
5181
5305
|
import_radix_ui5.Dialog.Title,
|
|
5182
5306
|
{
|
|
5183
5307
|
ref,
|
|
@@ -5189,7 +5313,7 @@ var DialogTitle = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE
|
|
|
5189
5313
|
}
|
|
5190
5314
|
));
|
|
5191
5315
|
DialogTitle.displayName = import_radix_ui5.Dialog.Title.displayName;
|
|
5192
|
-
var DialogDescription = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0,
|
|
5316
|
+
var DialogDescription = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
5193
5317
|
import_radix_ui5.Dialog.Description,
|
|
5194
5318
|
{
|
|
5195
5319
|
ref,
|
|
@@ -5201,63 +5325,63 @@ DialogDescription.displayName = import_radix_ui5.Dialog.Description.displayName;
|
|
|
5201
5325
|
var DialogClose = import_radix_ui5.Dialog.Close;
|
|
5202
5326
|
|
|
5203
5327
|
// src/ui/link-modal/LinkEditorPanel.tsx
|
|
5204
|
-
var
|
|
5328
|
+
var import_lucide_react9 = require("lucide-react");
|
|
5205
5329
|
|
|
5206
5330
|
// src/ui/link-modal/DestinationBreadcrumb.tsx
|
|
5207
|
-
var
|
|
5208
|
-
var
|
|
5331
|
+
var import_lucide_react6 = require("lucide-react");
|
|
5332
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
5209
5333
|
function DestinationBreadcrumb({
|
|
5210
5334
|
pageTitle,
|
|
5211
5335
|
sectionLabel
|
|
5212
5336
|
}) {
|
|
5213
|
-
return /* @__PURE__ */ (0,
|
|
5214
|
-
/* @__PURE__ */ (0,
|
|
5215
|
-
/* @__PURE__ */ (0,
|
|
5216
|
-
/* @__PURE__ */ (0,
|
|
5217
|
-
/* @__PURE__ */ (0,
|
|
5218
|
-
/* @__PURE__ */ (0,
|
|
5337
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex w-full flex-col gap-2", children: [
|
|
5338
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-sm font-medium! text-foreground m-0", children: "Destination" }),
|
|
5339
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-3", children: [
|
|
5340
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
5341
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react6.File, { size: 16, className: "shrink-0 text-foreground", "aria-hidden": true }),
|
|
5342
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "text-sm font-medium leading-none text-foreground!", children: pageTitle })
|
|
5219
5343
|
] }),
|
|
5220
|
-
/* @__PURE__ */ (0,
|
|
5221
|
-
|
|
5344
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
5345
|
+
import_lucide_react6.ArrowRight,
|
|
5222
5346
|
{
|
|
5223
5347
|
size: 16,
|
|
5224
5348
|
className: "shrink-0 text-muted-foreground",
|
|
5225
5349
|
"aria-hidden": true
|
|
5226
5350
|
}
|
|
5227
5351
|
),
|
|
5228
|
-
/* @__PURE__ */ (0,
|
|
5229
|
-
/* @__PURE__ */ (0,
|
|
5230
|
-
|
|
5352
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
|
|
5353
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
5354
|
+
import_lucide_react6.GalleryVertical,
|
|
5231
5355
|
{
|
|
5232
5356
|
size: 16,
|
|
5233
5357
|
className: "shrink-0 text-foreground",
|
|
5234
5358
|
"aria-hidden": true
|
|
5235
5359
|
}
|
|
5236
5360
|
),
|
|
5237
|
-
/* @__PURE__ */ (0,
|
|
5361
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
|
|
5238
5362
|
] })
|
|
5239
5363
|
] })
|
|
5240
5364
|
] });
|
|
5241
5365
|
}
|
|
5242
5366
|
|
|
5243
5367
|
// src/ui/link-modal/SectionTreeItem.tsx
|
|
5244
|
-
var
|
|
5245
|
-
var
|
|
5368
|
+
var import_lucide_react7 = require("lucide-react");
|
|
5369
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
5246
5370
|
function SectionTreeItem({
|
|
5247
5371
|
section,
|
|
5248
5372
|
onSelect,
|
|
5249
5373
|
selected
|
|
5250
5374
|
}) {
|
|
5251
5375
|
const interactive = Boolean(onSelect);
|
|
5252
|
-
return /* @__PURE__ */ (0,
|
|
5253
|
-
/* @__PURE__ */ (0,
|
|
5376
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex h-9 w-full items-end pl-3", children: [
|
|
5377
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
5254
5378
|
"div",
|
|
5255
5379
|
{
|
|
5256
5380
|
className: "mr-[-1px] h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
|
|
5257
5381
|
"aria-hidden": true
|
|
5258
5382
|
}
|
|
5259
5383
|
),
|
|
5260
|
-
/* @__PURE__ */ (0,
|
|
5384
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
5261
5385
|
"div",
|
|
5262
5386
|
{
|
|
5263
5387
|
role: interactive ? "button" : void 0,
|
|
@@ -5275,15 +5399,15 @@ function SectionTreeItem({
|
|
|
5275
5399
|
interactive && selected && "border-primary"
|
|
5276
5400
|
),
|
|
5277
5401
|
children: [
|
|
5278
|
-
/* @__PURE__ */ (0,
|
|
5279
|
-
|
|
5402
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
5403
|
+
import_lucide_react7.GalleryVertical,
|
|
5280
5404
|
{
|
|
5281
5405
|
size: 16,
|
|
5282
5406
|
className: "shrink-0 text-foreground",
|
|
5283
5407
|
"aria-hidden": true
|
|
5284
5408
|
}
|
|
5285
5409
|
),
|
|
5286
|
-
/* @__PURE__ */ (0,
|
|
5410
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
|
|
5287
5411
|
]
|
|
5288
5412
|
}
|
|
5289
5413
|
)
|
|
@@ -5295,10 +5419,10 @@ var import_react4 = require("react");
|
|
|
5295
5419
|
|
|
5296
5420
|
// src/ui/input.tsx
|
|
5297
5421
|
var React8 = __toESM(require("react"), 1);
|
|
5298
|
-
var
|
|
5422
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
5299
5423
|
var Input = React8.forwardRef(
|
|
5300
5424
|
({ className, type, ...props }, ref) => {
|
|
5301
|
-
return /* @__PURE__ */ (0,
|
|
5425
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
5302
5426
|
"input",
|
|
5303
5427
|
{
|
|
5304
5428
|
type,
|
|
@@ -5317,9 +5441,9 @@ Input.displayName = "Input";
|
|
|
5317
5441
|
|
|
5318
5442
|
// src/ui/label.tsx
|
|
5319
5443
|
var import_radix_ui6 = require("radix-ui");
|
|
5320
|
-
var
|
|
5444
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
5321
5445
|
function Label({ className, ...props }) {
|
|
5322
|
-
return /* @__PURE__ */ (0,
|
|
5446
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
5323
5447
|
import_radix_ui6.Label.Root,
|
|
5324
5448
|
{
|
|
5325
5449
|
"data-slot": "label",
|
|
@@ -5330,12 +5454,12 @@ function Label({ className, ...props }) {
|
|
|
5330
5454
|
}
|
|
5331
5455
|
|
|
5332
5456
|
// src/ui/link-modal/UrlOrPageInput.tsx
|
|
5333
|
-
var
|
|
5334
|
-
var
|
|
5457
|
+
var import_lucide_react8 = require("lucide-react");
|
|
5458
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
5335
5459
|
function FieldChevron({
|
|
5336
5460
|
onClick
|
|
5337
5461
|
}) {
|
|
5338
|
-
return /* @__PURE__ */ (0,
|
|
5462
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5339
5463
|
"button",
|
|
5340
5464
|
{
|
|
5341
5465
|
type: "button",
|
|
@@ -5343,7 +5467,7 @@ function FieldChevron({
|
|
|
5343
5467
|
onClick,
|
|
5344
5468
|
"aria-label": "Open page list",
|
|
5345
5469
|
tabIndex: -1,
|
|
5346
|
-
children: /* @__PURE__ */ (0,
|
|
5470
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.ChevronDown, { size: 16 })
|
|
5347
5471
|
}
|
|
5348
5472
|
);
|
|
5349
5473
|
}
|
|
@@ -5404,19 +5528,19 @@ function UrlOrPageInput({
|
|
|
5404
5528
|
"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]",
|
|
5405
5529
|
urlError ? "border-destructive shadow-[0_0_0_1px_var(--ohw-destructive)]" : isFocused ? "border-primary shadow-[0_0_0_1px_var(--ohw-primary)]" : "border-input"
|
|
5406
5530
|
);
|
|
5407
|
-
return /* @__PURE__ */ (0,
|
|
5408
|
-
/* @__PURE__ */ (0,
|
|
5409
|
-
/* @__PURE__ */ (0,
|
|
5410
|
-
/* @__PURE__ */ (0,
|
|
5411
|
-
selectedPage ? /* @__PURE__ */ (0,
|
|
5412
|
-
|
|
5531
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex w-full flex-col gap-2 p-0", children: [
|
|
5532
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
|
|
5533
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { ref: rootRef, className: "relative w-full", children: [
|
|
5534
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
|
|
5535
|
+
selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5536
|
+
import_lucide_react8.File,
|
|
5413
5537
|
{
|
|
5414
5538
|
size: 16,
|
|
5415
5539
|
className: "shrink-0 text-foreground",
|
|
5416
5540
|
"aria-hidden": true
|
|
5417
5541
|
}
|
|
5418
5542
|
) }) : null,
|
|
5419
|
-
readOnly ? /* @__PURE__ */ (0,
|
|
5543
|
+
readOnly ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm leading-5 text-foreground", children: selectedPage?.title ?? value }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5420
5544
|
Input,
|
|
5421
5545
|
{
|
|
5422
5546
|
ref: inputRef,
|
|
@@ -5442,7 +5566,7 @@ function UrlOrPageInput({
|
|
|
5442
5566
|
)
|
|
5443
5567
|
}
|
|
5444
5568
|
),
|
|
5445
|
-
selectedPage && !readOnly ? /* @__PURE__ */ (0,
|
|
5569
|
+
selectedPage && !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5446
5570
|
"button",
|
|
5447
5571
|
{
|
|
5448
5572
|
type: "button",
|
|
@@ -5450,26 +5574,26 @@ function UrlOrPageInput({
|
|
|
5450
5574
|
onMouseDown: clearSelection,
|
|
5451
5575
|
"aria-label": "Clear selected page",
|
|
5452
5576
|
tabIndex: -1,
|
|
5453
|
-
children: /* @__PURE__ */ (0,
|
|
5577
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.X, { size: 16, "aria-hidden": true })
|
|
5454
5578
|
}
|
|
5455
5579
|
) : null,
|
|
5456
|
-
!readOnly ? /* @__PURE__ */ (0,
|
|
5580
|
+
!readOnly ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(FieldChevron, { onClick: toggleDropdown }) : null
|
|
5457
5581
|
] }),
|
|
5458
|
-
dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ (0,
|
|
5582
|
+
dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5459
5583
|
"div",
|
|
5460
5584
|
{
|
|
5461
5585
|
"data-ohw-link-page-dropdown": "",
|
|
5462
5586
|
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",
|
|
5463
5587
|
onMouseDown: (e) => e.preventDefault(),
|
|
5464
|
-
children: filteredPages.map((page) => /* @__PURE__ */ (0,
|
|
5588
|
+
children: filteredPages.map((page) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
5465
5589
|
"button",
|
|
5466
5590
|
{
|
|
5467
5591
|
type: "button",
|
|
5468
5592
|
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",
|
|
5469
5593
|
onClick: () => onPageSelect(page),
|
|
5470
5594
|
children: [
|
|
5471
|
-
/* @__PURE__ */ (0,
|
|
5472
|
-
/* @__PURE__ */ (0,
|
|
5595
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.File, { size: 16, className: "shrink-0", "aria-hidden": true }),
|
|
5596
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "truncate", children: page.title })
|
|
5473
5597
|
]
|
|
5474
5598
|
},
|
|
5475
5599
|
page.path
|
|
@@ -5477,34 +5601,34 @@ function UrlOrPageInput({
|
|
|
5477
5601
|
}
|
|
5478
5602
|
) : null
|
|
5479
5603
|
] }),
|
|
5480
|
-
urlError ? /* @__PURE__ */ (0,
|
|
5604
|
+
urlError ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
|
|
5481
5605
|
] });
|
|
5482
5606
|
}
|
|
5483
5607
|
|
|
5484
5608
|
// src/ui/link-modal/LinkEditorPanel.tsx
|
|
5485
|
-
var
|
|
5609
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
5486
5610
|
function LinkEditorPanel({ state, onClose }) {
|
|
5487
5611
|
const isCancel = state.secondaryLabel === "Cancel" || state.secondaryLabel === "Back to sections";
|
|
5488
|
-
return /* @__PURE__ */ (0,
|
|
5489
|
-
/* @__PURE__ */ (0,
|
|
5612
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
|
|
5613
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DialogClose, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5490
5614
|
"button",
|
|
5491
5615
|
{
|
|
5492
5616
|
type: "button",
|
|
5493
5617
|
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50 h-7",
|
|
5494
5618
|
"aria-label": "Close",
|
|
5495
5619
|
onClick: onClose,
|
|
5496
|
-
children: /* @__PURE__ */ (0,
|
|
5620
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react9.X, { size: 16, "aria-hidden": true })
|
|
5497
5621
|
}
|
|
5498
5622
|
) }),
|
|
5499
|
-
/* @__PURE__ */ (0,
|
|
5500
|
-
/* @__PURE__ */ (0,
|
|
5501
|
-
state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ (0,
|
|
5623
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DialogHeader, { className: "w-full gap-1.5 p-6 pr-12", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DialogTitle, { className: "m-0 w-full break-words", children: state.title }) }),
|
|
5624
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
|
|
5625
|
+
state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5502
5626
|
DestinationBreadcrumb,
|
|
5503
5627
|
{
|
|
5504
5628
|
pageTitle: state.selectedPage.title,
|
|
5505
5629
|
sectionLabel: state.selectedSection.label
|
|
5506
5630
|
}
|
|
5507
|
-
) : /* @__PURE__ */ (0,
|
|
5631
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5508
5632
|
UrlOrPageInput,
|
|
5509
5633
|
{
|
|
5510
5634
|
value: state.searchValue,
|
|
@@ -5517,8 +5641,8 @@ function LinkEditorPanel({ state, onClose }) {
|
|
|
5517
5641
|
urlError: state.urlError
|
|
5518
5642
|
}
|
|
5519
5643
|
),
|
|
5520
|
-
state.showChooseSection ? /* @__PURE__ */ (0,
|
|
5521
|
-
/* @__PURE__ */ (0,
|
|
5644
|
+
state.showChooseSection ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex flex-col justify-center gap-2", children: [
|
|
5645
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5522
5646
|
Button,
|
|
5523
5647
|
{
|
|
5524
5648
|
type: "button",
|
|
@@ -5529,15 +5653,15 @@ function LinkEditorPanel({ state, onClose }) {
|
|
|
5529
5653
|
children: "Choose a section"
|
|
5530
5654
|
}
|
|
5531
5655
|
),
|
|
5532
|
-
/* @__PURE__ */ (0,
|
|
5533
|
-
/* @__PURE__ */ (0,
|
|
5534
|
-
/* @__PURE__ */ (0,
|
|
5656
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
|
|
5657
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react9.Info, { size: 16, className: "shrink-0", "aria-hidden": true }),
|
|
5658
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: "Pick a section this link should scroll to." })
|
|
5535
5659
|
] })
|
|
5536
5660
|
] }) : null,
|
|
5537
|
-
state.showSectionRow && state.selectedSection ? /* @__PURE__ */ (0,
|
|
5661
|
+
state.showSectionRow && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
|
|
5538
5662
|
] }),
|
|
5539
|
-
/* @__PURE__ */ (0,
|
|
5540
|
-
/* @__PURE__ */ (0,
|
|
5663
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(DialogFooter, { className: "w-full px-6 pb-6", children: [
|
|
5664
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5541
5665
|
Button,
|
|
5542
5666
|
{
|
|
5543
5667
|
type: "button",
|
|
@@ -5552,7 +5676,7 @@ function LinkEditorPanel({ state, onClose }) {
|
|
|
5552
5676
|
children: state.secondaryLabel
|
|
5553
5677
|
}
|
|
5554
5678
|
),
|
|
5555
|
-
/* @__PURE__ */ (0,
|
|
5679
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5556
5680
|
Button,
|
|
5557
5681
|
{
|
|
5558
5682
|
type: "button",
|
|
@@ -5573,9 +5697,9 @@ function LinkEditorPanel({ state, onClose }) {
|
|
|
5573
5697
|
// src/ui/link-modal/SectionPickerOverlay.tsx
|
|
5574
5698
|
var import_react5 = require("react");
|
|
5575
5699
|
var import_react_dom = require("react-dom");
|
|
5576
|
-
var
|
|
5700
|
+
var import_lucide_react10 = require("lucide-react");
|
|
5577
5701
|
var import_navigation = require("next/navigation");
|
|
5578
|
-
var
|
|
5702
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
5579
5703
|
var DIM_OVERLAY = "rgba(0, 0, 0, 0.45)";
|
|
5580
5704
|
function rectsEqual(a, b) {
|
|
5581
5705
|
if (a.size !== b.size) return false;
|
|
@@ -5804,7 +5928,7 @@ function SectionPickerOverlay({
|
|
|
5804
5928
|
const portalRoot = typeof document !== "undefined" ? document.querySelector("[data-ohw-bridge-root]") ?? document.body : null;
|
|
5805
5929
|
if (!portalRoot) return null;
|
|
5806
5930
|
return (0, import_react_dom.createPortal)(
|
|
5807
|
-
/* @__PURE__ */ (0,
|
|
5931
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
5808
5932
|
"div",
|
|
5809
5933
|
{
|
|
5810
5934
|
"data-ohw-section-picker": "",
|
|
@@ -5814,12 +5938,12 @@ function SectionPickerOverlay({
|
|
|
5814
5938
|
role: "dialog",
|
|
5815
5939
|
"aria-label": "Choose a section",
|
|
5816
5940
|
children: [
|
|
5817
|
-
/* @__PURE__ */ (0,
|
|
5941
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
5818
5942
|
"div",
|
|
5819
5943
|
{
|
|
5820
5944
|
className: "pointer-events-auto fixed left-5 z-[2]",
|
|
5821
5945
|
style: { top: chromeClip.top + 20 },
|
|
5822
|
-
children: /* @__PURE__ */ (0,
|
|
5946
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
5823
5947
|
Button,
|
|
5824
5948
|
{
|
|
5825
5949
|
type: "button",
|
|
@@ -5828,14 +5952,14 @@ function SectionPickerOverlay({
|
|
|
5828
5952
|
className: "h-8 min-w-0 gap-1 border-border bg-background px-2 py-1.5 shadow-sm hover:bg-muted cursor-pointer",
|
|
5829
5953
|
onClick: onBack,
|
|
5830
5954
|
children: [
|
|
5831
|
-
/* @__PURE__ */ (0,
|
|
5955
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react10.ArrowLeft, { className: "size-4 shrink-0", "aria-hidden": true }),
|
|
5832
5956
|
"Back"
|
|
5833
5957
|
]
|
|
5834
5958
|
}
|
|
5835
5959
|
)
|
|
5836
5960
|
}
|
|
5837
5961
|
),
|
|
5838
|
-
/* @__PURE__ */ (0,
|
|
5962
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
5839
5963
|
"div",
|
|
5840
5964
|
{
|
|
5841
5965
|
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",
|
|
@@ -5848,7 +5972,7 @@ function SectionPickerOverlay({
|
|
|
5848
5972
|
children: "Click on section to select"
|
|
5849
5973
|
}
|
|
5850
5974
|
),
|
|
5851
|
-
!isOnTargetPage ? /* @__PURE__ */ (0,
|
|
5975
|
+
!isOnTargetPage ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
5852
5976
|
"div",
|
|
5853
5977
|
{
|
|
5854
5978
|
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",
|
|
@@ -5856,14 +5980,14 @@ function SectionPickerOverlay({
|
|
|
5856
5980
|
children: "Loading page preview\u2026"
|
|
5857
5981
|
}
|
|
5858
5982
|
) : null,
|
|
5859
|
-
isOnTargetPage && liveSections.length === 0 ? /* @__PURE__ */ (0,
|
|
5983
|
+
isOnTargetPage && liveSections.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "pointer-events-auto fixed inset-0 z-[1] flex items-center justify-center bg-muted/40", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." }) }) : null,
|
|
5860
5984
|
isOnTargetPage ? liveSections.map((section) => {
|
|
5861
5985
|
const rect = rects.get(section.id);
|
|
5862
5986
|
if (!rect || rect.width <= 0 || rect.height <= 0) return null;
|
|
5863
5987
|
const isSelected = selectedId === section.id;
|
|
5864
5988
|
const isHovered = hoveredId === section.id;
|
|
5865
5989
|
const isLit = isSelected || isHovered;
|
|
5866
|
-
return /* @__PURE__ */ (0,
|
|
5990
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
5867
5991
|
"button",
|
|
5868
5992
|
{
|
|
5869
5993
|
type: "button",
|
|
@@ -5878,7 +6002,7 @@ function SectionPickerOverlay({
|
|
|
5878
6002
|
"aria-label": `Select section ${section.label}`,
|
|
5879
6003
|
onClick: () => handleSelect(section),
|
|
5880
6004
|
children: [
|
|
5881
|
-
isLit ? /* @__PURE__ */ (0,
|
|
6005
|
+
isLit ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
5882
6006
|
"span",
|
|
5883
6007
|
{
|
|
5884
6008
|
className: "pointer-events-none absolute",
|
|
@@ -5891,13 +6015,13 @@ function SectionPickerOverlay({
|
|
|
5891
6015
|
"aria-hidden": true
|
|
5892
6016
|
}
|
|
5893
6017
|
) : null,
|
|
5894
|
-
isSelected ? /* @__PURE__ */ (0,
|
|
6018
|
+
isSelected ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
5895
6019
|
"span",
|
|
5896
6020
|
{
|
|
5897
6021
|
className: "absolute right-3 top-3 flex size-8 items-center justify-center rounded-full text-white",
|
|
5898
6022
|
style: { backgroundColor: "var(--ohw-primary, #0885fe)" },
|
|
5899
6023
|
"aria-hidden": true,
|
|
5900
|
-
children: /* @__PURE__ */ (0,
|
|
6024
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react10.Check, { className: "size-5" })
|
|
5901
6025
|
}
|
|
5902
6026
|
) : null
|
|
5903
6027
|
]
|
|
@@ -6077,7 +6201,7 @@ function useLinkModalState({
|
|
|
6077
6201
|
}
|
|
6078
6202
|
|
|
6079
6203
|
// src/ui/link-modal/LinkPopover.tsx
|
|
6080
|
-
var
|
|
6204
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
6081
6205
|
function postToParent(data) {
|
|
6082
6206
|
window.parent?.postMessage(data, "*");
|
|
6083
6207
|
}
|
|
@@ -6173,15 +6297,15 @@ function LinkPopover({
|
|
|
6173
6297
|
);
|
|
6174
6298
|
};
|
|
6175
6299
|
}, [open, sectionPickerActive]);
|
|
6176
|
-
return /* @__PURE__ */ (0,
|
|
6177
|
-
/* @__PURE__ */ (0,
|
|
6300
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
6301
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6178
6302
|
Dialog2,
|
|
6179
6303
|
{
|
|
6180
6304
|
open: open && !sectionPickerActive,
|
|
6181
6305
|
onOpenChange: (next) => {
|
|
6182
6306
|
if (!next) onClose?.();
|
|
6183
6307
|
},
|
|
6184
|
-
children: /* @__PURE__ */ (0,
|
|
6308
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6185
6309
|
DialogContent,
|
|
6186
6310
|
{
|
|
6187
6311
|
ref: panelRef,
|
|
@@ -6191,12 +6315,12 @@ function LinkPopover({
|
|
|
6191
6315
|
"data-ohw-bridge": "",
|
|
6192
6316
|
showCloseButton: false,
|
|
6193
6317
|
className: "gap-0 p-0 w-full max-w-[448px] pointer-events-auto z-[2147483646] overflow-visible",
|
|
6194
|
-
children: /* @__PURE__ */ (0,
|
|
6318
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LinkEditorPanel, { state, onClose })
|
|
6195
6319
|
}
|
|
6196
6320
|
)
|
|
6197
6321
|
}
|
|
6198
6322
|
),
|
|
6199
|
-
sectionPickerActive && state.selectedPage ? /* @__PURE__ */ (0,
|
|
6323
|
+
sectionPickerActive && state.selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6200
6324
|
SectionPickerOverlay,
|
|
6201
6325
|
{
|
|
6202
6326
|
pagePath: state.selectedPage.path,
|
|
@@ -6502,15 +6626,412 @@ function insertNavbarItem(href, label, afterAnchor = null) {
|
|
|
6502
6626
|
};
|
|
6503
6627
|
}
|
|
6504
6628
|
|
|
6629
|
+
// src/lib/footer-items.ts
|
|
6630
|
+
var FOOTER_ORDER_KEY = "__ohw_footer_order";
|
|
6631
|
+
var FOOTER_HREF_RE = /^footer-(\d+)-(\d+)-href$/;
|
|
6632
|
+
function parseFooterHrefKey(key) {
|
|
6633
|
+
if (!key) return null;
|
|
6634
|
+
const match = key.match(FOOTER_HREF_RE);
|
|
6635
|
+
if (!match) return null;
|
|
6636
|
+
return { col: parseInt(match[1], 10), item: parseInt(match[2], 10) };
|
|
6637
|
+
}
|
|
6638
|
+
function isFooterHrefKey(key) {
|
|
6639
|
+
return parseFooterHrefKey(key) !== null;
|
|
6640
|
+
}
|
|
6641
|
+
function getFooterRoot() {
|
|
6642
|
+
return document.querySelector('footer[data-ohw-section="footer"], footer');
|
|
6643
|
+
}
|
|
6644
|
+
function getFooterLinksContainer() {
|
|
6645
|
+
return document.querySelector("[data-ohw-footer-links]") ?? document.querySelector(".rb-footer-links");
|
|
6646
|
+
}
|
|
6647
|
+
function isFooterLinkAnchor(el) {
|
|
6648
|
+
if (!el.matches("[data-ohw-href-key]")) return false;
|
|
6649
|
+
if (!isFooterHrefKey(el.getAttribute("data-ohw-href-key"))) return false;
|
|
6650
|
+
return Boolean(el.querySelector('[data-ohw-editable="text"]'));
|
|
6651
|
+
}
|
|
6652
|
+
function listFooterColumns() {
|
|
6653
|
+
const root = getFooterLinksContainer() ?? getFooterRoot()?.querySelector(".rb-footer-links") ?? null;
|
|
6654
|
+
if (!root) return [];
|
|
6655
|
+
const explicit = Array.from(root.querySelectorAll(":scope > [data-ohw-footer-col]"));
|
|
6656
|
+
if (explicit.length > 0) return explicit;
|
|
6657
|
+
return Array.from(root.children).filter((el) => {
|
|
6658
|
+
if (!(el instanceof HTMLElement)) return false;
|
|
6659
|
+
return Array.from(el.querySelectorAll(":scope > [data-ohw-href-key]")).some(
|
|
6660
|
+
isFooterLinkAnchor
|
|
6661
|
+
);
|
|
6662
|
+
});
|
|
6663
|
+
}
|
|
6664
|
+
function listFooterLinksInColumn(column) {
|
|
6665
|
+
return Array.from(column.querySelectorAll(":scope > [data-ohw-href-key]")).filter(
|
|
6666
|
+
isFooterLinkAnchor
|
|
6667
|
+
);
|
|
6668
|
+
}
|
|
6669
|
+
function findFooterColumnForLink(anchor) {
|
|
6670
|
+
const columns = listFooterColumns();
|
|
6671
|
+
return columns.find((col) => col.contains(anchor)) ?? null;
|
|
6672
|
+
}
|
|
6673
|
+
function getFooterOrderFromDom() {
|
|
6674
|
+
return listFooterColumns().map(
|
|
6675
|
+
(col) => listFooterLinksInColumn(col).map((el) => el.getAttribute("data-ohw-href-key")).filter((key) => Boolean(key))
|
|
6676
|
+
);
|
|
6677
|
+
}
|
|
6678
|
+
function findFooterLinkByKey(hrefKey) {
|
|
6679
|
+
return document.querySelector(
|
|
6680
|
+
`footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
6681
|
+
);
|
|
6682
|
+
}
|
|
6683
|
+
function syncFooterColumnIndices(columns) {
|
|
6684
|
+
columns.forEach((col, index) => {
|
|
6685
|
+
const next = String(index);
|
|
6686
|
+
if (col.getAttribute("data-ohw-footer-col") !== next) {
|
|
6687
|
+
col.setAttribute("data-ohw-footer-col", next);
|
|
6688
|
+
}
|
|
6689
|
+
});
|
|
6690
|
+
}
|
|
6691
|
+
function appendChildIfNeeded(parent, child) {
|
|
6692
|
+
if (parent.lastElementChild !== child) {
|
|
6693
|
+
parent.appendChild(child);
|
|
6694
|
+
}
|
|
6695
|
+
}
|
|
6696
|
+
function insertLinkBeforeNext(col, el, nextEl) {
|
|
6697
|
+
if (nextEl) {
|
|
6698
|
+
if (el.nextElementSibling !== nextEl) {
|
|
6699
|
+
col.insertBefore(el, nextEl);
|
|
6700
|
+
}
|
|
6701
|
+
return;
|
|
6702
|
+
}
|
|
6703
|
+
if (col.lastElementChild !== el) {
|
|
6704
|
+
col.appendChild(el);
|
|
6705
|
+
}
|
|
6706
|
+
}
|
|
6707
|
+
function applyFooterOrder(order) {
|
|
6708
|
+
const container = getFooterLinksContainer();
|
|
6709
|
+
if (!container) return;
|
|
6710
|
+
const columns = listFooterColumns();
|
|
6711
|
+
if (columns.length === 0) return;
|
|
6712
|
+
const currentOrder = getFooterOrderFromDom();
|
|
6713
|
+
if (ordersEqual(order, currentOrder)) {
|
|
6714
|
+
syncFooterColumnIndices(columns);
|
|
6715
|
+
return;
|
|
6716
|
+
}
|
|
6717
|
+
const colCount = Math.max(columns.length, order.length);
|
|
6718
|
+
const working = columns.slice(0, colCount);
|
|
6719
|
+
for (let i = 0; i < order.length && i < working.length; i++) {
|
|
6720
|
+
appendChildIfNeeded(container, working[i]);
|
|
6721
|
+
}
|
|
6722
|
+
for (let i = order.length; i < working.length; i++) {
|
|
6723
|
+
appendChildIfNeeded(container, working[i]);
|
|
6724
|
+
}
|
|
6725
|
+
const freshColumns = listFooterColumns();
|
|
6726
|
+
syncFooterColumnIndices(freshColumns);
|
|
6727
|
+
for (let c = 0; c < order.length; c++) {
|
|
6728
|
+
const col = freshColumns[c];
|
|
6729
|
+
if (!col) continue;
|
|
6730
|
+
const colOrder = order[c];
|
|
6731
|
+
for (let j = 0; j < colOrder.length; j++) {
|
|
6732
|
+
const hrefKey = colOrder[j];
|
|
6733
|
+
const el = findFooterLinkByKey(hrefKey);
|
|
6734
|
+
if (!el) continue;
|
|
6735
|
+
if (el.parentElement !== col) {
|
|
6736
|
+
col.appendChild(el);
|
|
6737
|
+
}
|
|
6738
|
+
const nextKey = colOrder[j + 1];
|
|
6739
|
+
const nextEl = nextKey ? findFooterLinkByKey(nextKey) : null;
|
|
6740
|
+
insertLinkBeforeNext(col, el, nextEl?.parentElement === col ? nextEl : null);
|
|
6741
|
+
}
|
|
6742
|
+
}
|
|
6743
|
+
}
|
|
6744
|
+
function ordersEqual(a, b) {
|
|
6745
|
+
if (a.length !== b.length) return false;
|
|
6746
|
+
for (let i = 0; i < a.length; i++) {
|
|
6747
|
+
const left = a[i];
|
|
6748
|
+
const right = b[i];
|
|
6749
|
+
if (left.length !== right.length) return false;
|
|
6750
|
+
for (let j = 0; j < left.length; j++) {
|
|
6751
|
+
if (left[j] !== right[j]) return false;
|
|
6752
|
+
}
|
|
6753
|
+
}
|
|
6754
|
+
return true;
|
|
6755
|
+
}
|
|
6756
|
+
function planFooterLinkMove(hrefKey, targetColIndex, insertIndex) {
|
|
6757
|
+
const order = getFooterOrderFromDom();
|
|
6758
|
+
if (targetColIndex < 0 || targetColIndex >= order.length) return null;
|
|
6759
|
+
let fromCol = -1;
|
|
6760
|
+
let fromIdx = -1;
|
|
6761
|
+
for (let c = 0; c < order.length; c++) {
|
|
6762
|
+
const idx = order[c].indexOf(hrefKey);
|
|
6763
|
+
if (idx >= 0) {
|
|
6764
|
+
fromCol = c;
|
|
6765
|
+
fromIdx = idx;
|
|
6766
|
+
break;
|
|
6767
|
+
}
|
|
6768
|
+
}
|
|
6769
|
+
if (fromCol < 0) return null;
|
|
6770
|
+
const next = order.map((col) => [...col]);
|
|
6771
|
+
next[fromCol].splice(fromIdx, 1);
|
|
6772
|
+
let adjusted = insertIndex;
|
|
6773
|
+
if (fromCol === targetColIndex && fromIdx < insertIndex) adjusted -= 1;
|
|
6774
|
+
adjusted = Math.max(0, Math.min(adjusted, next[targetColIndex].length));
|
|
6775
|
+
next[targetColIndex].splice(adjusted, 0, hrefKey);
|
|
6776
|
+
if (ordersEqual(next, order)) return null;
|
|
6777
|
+
return next;
|
|
6778
|
+
}
|
|
6779
|
+
function planFooterColumnMove(fromIndex, toIndex) {
|
|
6780
|
+
const order = getFooterOrderFromDom();
|
|
6781
|
+
const columns = listFooterColumns();
|
|
6782
|
+
if (fromIndex < 0 || fromIndex >= columns.length || toIndex < 0 || toIndex > columns.length) {
|
|
6783
|
+
return null;
|
|
6784
|
+
}
|
|
6785
|
+
if (toIndex === fromIndex || toIndex === fromIndex + 1) return null;
|
|
6786
|
+
const nextOrder = order.map((col) => [...col]);
|
|
6787
|
+
const [movedOrder] = nextOrder.splice(fromIndex, 1);
|
|
6788
|
+
if (!movedOrder) return null;
|
|
6789
|
+
let adjusted = toIndex;
|
|
6790
|
+
if (fromIndex < toIndex) adjusted -= 1;
|
|
6791
|
+
adjusted = Math.max(0, Math.min(adjusted, nextOrder.length));
|
|
6792
|
+
nextOrder.splice(adjusted, 0, movedOrder);
|
|
6793
|
+
if (ordersEqual(nextOrder, order)) return null;
|
|
6794
|
+
return nextOrder;
|
|
6795
|
+
}
|
|
6796
|
+
function parseFooterOrder(content) {
|
|
6797
|
+
const raw = content[FOOTER_ORDER_KEY];
|
|
6798
|
+
if (!raw) return null;
|
|
6799
|
+
try {
|
|
6800
|
+
const parsed = JSON.parse(raw);
|
|
6801
|
+
if (!Array.isArray(parsed)) return null;
|
|
6802
|
+
return parsed.filter((col) => Array.isArray(col)).map((col) => col.filter((key) => typeof key === "string" && key.length > 0));
|
|
6803
|
+
} catch {
|
|
6804
|
+
return null;
|
|
6805
|
+
}
|
|
6806
|
+
}
|
|
6807
|
+
function reconcileFooterOrderFromContent(content) {
|
|
6808
|
+
const order = parseFooterOrder(content);
|
|
6809
|
+
if (!order?.length) return;
|
|
6810
|
+
const current = getFooterOrderFromDom();
|
|
6811
|
+
if (ordersEqual(order, current)) {
|
|
6812
|
+
syncFooterColumnIndices(listFooterColumns());
|
|
6813
|
+
return;
|
|
6814
|
+
}
|
|
6815
|
+
applyFooterOrder(order);
|
|
6816
|
+
}
|
|
6817
|
+
function buildLinkDropSlots(column, columnIndex) {
|
|
6818
|
+
const links = listFooterLinksInColumn(column);
|
|
6819
|
+
const colRect = column.getBoundingClientRect();
|
|
6820
|
+
const slots = [];
|
|
6821
|
+
const barThickness = 3;
|
|
6822
|
+
if (links.length === 0) {
|
|
6823
|
+
slots.push({
|
|
6824
|
+
insertIndex: 0,
|
|
6825
|
+
columnIndex,
|
|
6826
|
+
left: colRect.left,
|
|
6827
|
+
top: colRect.top + colRect.height / 2 - barThickness / 2,
|
|
6828
|
+
width: colRect.width,
|
|
6829
|
+
height: barThickness,
|
|
6830
|
+
direction: "horizontal"
|
|
6831
|
+
});
|
|
6832
|
+
return slots;
|
|
6833
|
+
}
|
|
6834
|
+
for (let i = 0; i <= links.length; i++) {
|
|
6835
|
+
let top;
|
|
6836
|
+
if (i === 0) {
|
|
6837
|
+
top = links[0].getBoundingClientRect().top - barThickness / 2;
|
|
6838
|
+
} else if (i === links.length) {
|
|
6839
|
+
const last = links[links.length - 1].getBoundingClientRect();
|
|
6840
|
+
top = last.bottom - barThickness / 2;
|
|
6841
|
+
} else {
|
|
6842
|
+
const prev = links[i - 1].getBoundingClientRect();
|
|
6843
|
+
const next = links[i].getBoundingClientRect();
|
|
6844
|
+
top = (prev.bottom + next.top) / 2 - barThickness / 2;
|
|
6845
|
+
}
|
|
6846
|
+
const widthRef = i === 0 ? links[0].getBoundingClientRect() : i === links.length ? links[links.length - 1].getBoundingClientRect() : links[i].getBoundingClientRect();
|
|
6847
|
+
slots.push({
|
|
6848
|
+
insertIndex: i,
|
|
6849
|
+
columnIndex,
|
|
6850
|
+
left: widthRef.left,
|
|
6851
|
+
top,
|
|
6852
|
+
width: Math.max(widthRef.width, colRect.width * 0.8),
|
|
6853
|
+
height: barThickness,
|
|
6854
|
+
direction: "horizontal"
|
|
6855
|
+
});
|
|
6856
|
+
}
|
|
6857
|
+
return slots;
|
|
6858
|
+
}
|
|
6859
|
+
function buildColumnDropSlots() {
|
|
6860
|
+
const columns = listFooterColumns();
|
|
6861
|
+
const slots = [];
|
|
6862
|
+
const barThickness = 3;
|
|
6863
|
+
if (columns.length === 0) return slots;
|
|
6864
|
+
for (let i = 0; i <= columns.length; i++) {
|
|
6865
|
+
let left;
|
|
6866
|
+
let height;
|
|
6867
|
+
let top;
|
|
6868
|
+
if (i === 0) {
|
|
6869
|
+
const first = columns[0].getBoundingClientRect();
|
|
6870
|
+
left = first.left - barThickness / 2;
|
|
6871
|
+
top = first.top;
|
|
6872
|
+
height = first.height;
|
|
6873
|
+
} else if (i === columns.length) {
|
|
6874
|
+
const last = columns[columns.length - 1].getBoundingClientRect();
|
|
6875
|
+
left = last.right - barThickness / 2;
|
|
6876
|
+
top = last.top;
|
|
6877
|
+
height = last.height;
|
|
6878
|
+
} else {
|
|
6879
|
+
const prev = columns[i - 1].getBoundingClientRect();
|
|
6880
|
+
const next = columns[i].getBoundingClientRect();
|
|
6881
|
+
left = (prev.right + next.left) / 2 - barThickness / 2;
|
|
6882
|
+
top = Math.min(prev.top, next.top);
|
|
6883
|
+
height = Math.max(prev.bottom, next.bottom) - top;
|
|
6884
|
+
}
|
|
6885
|
+
slots.push({
|
|
6886
|
+
insertIndex: i,
|
|
6887
|
+
columnIndex: i,
|
|
6888
|
+
left,
|
|
6889
|
+
top,
|
|
6890
|
+
width: barThickness,
|
|
6891
|
+
height: Math.max(height, 24),
|
|
6892
|
+
direction: "vertical"
|
|
6893
|
+
});
|
|
6894
|
+
}
|
|
6895
|
+
return slots;
|
|
6896
|
+
}
|
|
6897
|
+
function hitTestLinkDropSlot(clientX, clientY, draggedHrefKey) {
|
|
6898
|
+
const columns = listFooterColumns();
|
|
6899
|
+
let best = null;
|
|
6900
|
+
for (let c = 0; c < columns.length; c++) {
|
|
6901
|
+
const col = columns[c];
|
|
6902
|
+
const colRect = col.getBoundingClientRect();
|
|
6903
|
+
const inColX = clientX >= colRect.left - 24 && clientX <= colRect.right + 24;
|
|
6904
|
+
if (!inColX) continue;
|
|
6905
|
+
const slots = buildLinkDropSlots(col, c).filter((slot) => {
|
|
6906
|
+
const links = listFooterLinksInColumn(col);
|
|
6907
|
+
const fromIdx = links.findIndex(
|
|
6908
|
+
(el) => el.getAttribute("data-ohw-href-key") === draggedHrefKey
|
|
6909
|
+
);
|
|
6910
|
+
if (fromIdx < 0) return true;
|
|
6911
|
+
if (c === findColumnIndexForKey(draggedHrefKey) && (slot.insertIndex === fromIdx || slot.insertIndex === fromIdx + 1)) {
|
|
6912
|
+
return true;
|
|
6913
|
+
}
|
|
6914
|
+
return true;
|
|
6915
|
+
});
|
|
6916
|
+
for (const slot of slots) {
|
|
6917
|
+
const cy = slot.top + slot.height / 2;
|
|
6918
|
+
const dist = Math.abs(clientY - cy) + (inColX ? 0 : 1e3);
|
|
6919
|
+
if (!best || dist < best.dist) best = { slot, dist };
|
|
6920
|
+
}
|
|
6921
|
+
}
|
|
6922
|
+
return best?.slot ?? null;
|
|
6923
|
+
}
|
|
6924
|
+
function findColumnIndexForKey(hrefKey) {
|
|
6925
|
+
const order = getFooterOrderFromDom();
|
|
6926
|
+
for (let c = 0; c < order.length; c++) {
|
|
6927
|
+
if (order[c].includes(hrefKey)) return c;
|
|
6928
|
+
}
|
|
6929
|
+
return -1;
|
|
6930
|
+
}
|
|
6931
|
+
function hitTestColumnDropSlot(clientX, _clientY) {
|
|
6932
|
+
const slots = buildColumnDropSlots();
|
|
6933
|
+
let best = null;
|
|
6934
|
+
for (const slot of slots) {
|
|
6935
|
+
const cx2 = slot.left + slot.width / 2;
|
|
6936
|
+
const dist = Math.abs(clientX - cx2);
|
|
6937
|
+
if (!best || dist < best.dist) best = { slot, dist };
|
|
6938
|
+
}
|
|
6939
|
+
return best?.slot ?? null;
|
|
6940
|
+
}
|
|
6941
|
+
|
|
6942
|
+
// src/lib/carousel.ts
|
|
6943
|
+
var import_react8 = require("react");
|
|
6944
|
+
var CAROUSEL_ATTR = "data-ohw-carousel";
|
|
6945
|
+
var CAROUSEL_VALUE_ATTR = "data-ohw-carousel-value";
|
|
6946
|
+
var CAROUSEL_SLIDE_ATTR = "data-ohw-carousel-slide";
|
|
6947
|
+
var CAROUSEL_EVENT = "ohw:carousel-change";
|
|
6948
|
+
function listCarouselKeys() {
|
|
6949
|
+
const keys = /* @__PURE__ */ new Set();
|
|
6950
|
+
document.querySelectorAll(`[${CAROUSEL_ATTR}]`).forEach((el) => {
|
|
6951
|
+
const key = el.getAttribute("data-ohw-key");
|
|
6952
|
+
if (key) keys.add(key);
|
|
6953
|
+
});
|
|
6954
|
+
return [...keys];
|
|
6955
|
+
}
|
|
6956
|
+
function containersForKey(key) {
|
|
6957
|
+
return Array.from(
|
|
6958
|
+
document.querySelectorAll(`[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`)
|
|
6959
|
+
);
|
|
6960
|
+
}
|
|
6961
|
+
function isCarouselKey(key) {
|
|
6962
|
+
return containersForKey(key).length > 0;
|
|
6963
|
+
}
|
|
6964
|
+
function parseSlides(raw) {
|
|
6965
|
+
if (!raw) return [];
|
|
6966
|
+
try {
|
|
6967
|
+
const parsed = JSON.parse(raw);
|
|
6968
|
+
if (!Array.isArray(parsed)) return [];
|
|
6969
|
+
return parsed.filter((s) => Boolean(s) && typeof s === "object").map((s) => ({ src: String(s.src ?? ""), alt: String(s.alt ?? "") }));
|
|
6970
|
+
} catch {
|
|
6971
|
+
return [];
|
|
6972
|
+
}
|
|
6973
|
+
}
|
|
6974
|
+
function readCarouselValue(key) {
|
|
6975
|
+
const container = containersForKey(key)[0];
|
|
6976
|
+
if (!container) return [];
|
|
6977
|
+
const fromAttr = parseSlides(container.getAttribute(CAROUSEL_VALUE_ATTR));
|
|
6978
|
+
if (fromAttr.length > 0) return fromAttr;
|
|
6979
|
+
return Array.from(container.querySelectorAll(`[${CAROUSEL_SLIDE_ATTR}]`)).filter((slide) => slide.closest(`[${CAROUSEL_ATTR}]`) === container).sort((a, b) => slideIndex(a) - slideIndex(b)).map((slide) => {
|
|
6980
|
+
const img = slide instanceof HTMLImageElement ? slide : slide.querySelector("img");
|
|
6981
|
+
return { src: img?.src ?? "", alt: img?.alt ?? "" };
|
|
6982
|
+
});
|
|
6983
|
+
}
|
|
6984
|
+
function slideIndex(el) {
|
|
6985
|
+
const raw = el.getAttribute(CAROUSEL_SLIDE_ATTR);
|
|
6986
|
+
const n = raw ? parseInt(raw, 10) : NaN;
|
|
6987
|
+
return Number.isFinite(n) ? n : 0;
|
|
6988
|
+
}
|
|
6989
|
+
function applyCarouselValue(key, slides) {
|
|
6990
|
+
const value = JSON.stringify(slides);
|
|
6991
|
+
for (const container of containersForKey(key)) {
|
|
6992
|
+
if (container.getAttribute(CAROUSEL_VALUE_ATTR) === value) continue;
|
|
6993
|
+
container.setAttribute(CAROUSEL_VALUE_ATTR, value);
|
|
6994
|
+
container.dispatchEvent(
|
|
6995
|
+
new CustomEvent(CAROUSEL_EVENT, { detail: { images: slides } })
|
|
6996
|
+
);
|
|
6997
|
+
}
|
|
6998
|
+
}
|
|
6999
|
+
function applyCarouselNode(key, val) {
|
|
7000
|
+
if (!isCarouselKey(key)) return false;
|
|
7001
|
+
applyCarouselValue(key, parseSlides(val));
|
|
7002
|
+
return true;
|
|
7003
|
+
}
|
|
7004
|
+
function useOhwCarousel(key, initial) {
|
|
7005
|
+
const [images, setImages] = (0, import_react8.useState)(initial);
|
|
7006
|
+
(0, import_react8.useEffect)(() => {
|
|
7007
|
+
const el = document.querySelector(
|
|
7008
|
+
`[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`
|
|
7009
|
+
);
|
|
7010
|
+
if (!el) return;
|
|
7011
|
+
const onChange = (e) => {
|
|
7012
|
+
const detail = e.detail;
|
|
7013
|
+
if (Array.isArray(detail?.images)) setImages(detail.images);
|
|
7014
|
+
};
|
|
7015
|
+
el.addEventListener(CAROUSEL_EVENT, onChange);
|
|
7016
|
+
return () => el.removeEventListener(CAROUSEL_EVENT, onChange);
|
|
7017
|
+
}, [key]);
|
|
7018
|
+
const bind = {
|
|
7019
|
+
[CAROUSEL_ATTR]: "",
|
|
7020
|
+
"data-ohw-key": key,
|
|
7021
|
+
[CAROUSEL_VALUE_ATTR]: JSON.stringify(images)
|
|
7022
|
+
};
|
|
7023
|
+
return { images, setImages, bind };
|
|
7024
|
+
}
|
|
7025
|
+
|
|
6505
7026
|
// src/ui/navbar-container-chrome.tsx
|
|
6506
|
-
var
|
|
6507
|
-
var
|
|
7027
|
+
var import_lucide_react11 = require("lucide-react");
|
|
7028
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
6508
7029
|
function NavbarContainerChrome({
|
|
6509
7030
|
rect,
|
|
6510
7031
|
onAdd
|
|
6511
7032
|
}) {
|
|
6512
7033
|
const chromeGap = 6;
|
|
6513
|
-
return /* @__PURE__ */ (0,
|
|
7034
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
6514
7035
|
"div",
|
|
6515
7036
|
{
|
|
6516
7037
|
"data-ohw-navbar-container-chrome": "",
|
|
@@ -6522,7 +7043,7 @@ function NavbarContainerChrome({
|
|
|
6522
7043
|
width: rect.width + chromeGap * 2,
|
|
6523
7044
|
height: rect.height + chromeGap * 2
|
|
6524
7045
|
},
|
|
6525
|
-
children: /* @__PURE__ */ (0,
|
|
7046
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
6526
7047
|
"button",
|
|
6527
7048
|
{
|
|
6528
7049
|
type: "button",
|
|
@@ -6539,15 +7060,57 @@ function NavbarContainerChrome({
|
|
|
6539
7060
|
e.stopPropagation();
|
|
6540
7061
|
onAdd();
|
|
6541
7062
|
},
|
|
6542
|
-
children: /* @__PURE__ */ (0,
|
|
7063
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react11.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
6543
7064
|
}
|
|
6544
7065
|
)
|
|
6545
7066
|
}
|
|
6546
7067
|
);
|
|
6547
7068
|
}
|
|
6548
7069
|
|
|
7070
|
+
// src/ui/drop-indicator.tsx
|
|
7071
|
+
var React9 = __toESM(require("react"), 1);
|
|
7072
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
7073
|
+
var dropIndicatorVariants = cva(
|
|
7074
|
+
"ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
|
|
7075
|
+
{
|
|
7076
|
+
variants: {
|
|
7077
|
+
direction: {
|
|
7078
|
+
vertical: "h-6 w-[3px]",
|
|
7079
|
+
horizontal: "h-[3px] w-[200px]"
|
|
7080
|
+
},
|
|
7081
|
+
state: {
|
|
7082
|
+
default: "opacity-0",
|
|
7083
|
+
hover: "opacity-100",
|
|
7084
|
+
dragIdle: "opacity-40",
|
|
7085
|
+
dragActive: "opacity-100"
|
|
7086
|
+
}
|
|
7087
|
+
},
|
|
7088
|
+
defaultVariants: {
|
|
7089
|
+
direction: "vertical",
|
|
7090
|
+
state: "default"
|
|
7091
|
+
}
|
|
7092
|
+
}
|
|
7093
|
+
);
|
|
7094
|
+
var DropIndicator = React9.forwardRef(
|
|
7095
|
+
({ className, direction, state, ...props }, ref) => {
|
|
7096
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
7097
|
+
"div",
|
|
7098
|
+
{
|
|
7099
|
+
ref,
|
|
7100
|
+
"data-slot": "drop-indicator",
|
|
7101
|
+
"data-direction": direction ?? "vertical",
|
|
7102
|
+
"data-state": state ?? "default",
|
|
7103
|
+
"aria-hidden": "true",
|
|
7104
|
+
className: cn(dropIndicatorVariants({ direction, state }), className),
|
|
7105
|
+
...props
|
|
7106
|
+
}
|
|
7107
|
+
);
|
|
7108
|
+
}
|
|
7109
|
+
);
|
|
7110
|
+
DropIndicator.displayName = "DropIndicator";
|
|
7111
|
+
|
|
6549
7112
|
// src/ui/badge.tsx
|
|
6550
|
-
var
|
|
7113
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
6551
7114
|
var badgeVariants = cva(
|
|
6552
7115
|
"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",
|
|
6553
7116
|
{
|
|
@@ -6565,12 +7128,12 @@ var badgeVariants = cva(
|
|
|
6565
7128
|
}
|
|
6566
7129
|
);
|
|
6567
7130
|
function Badge({ className, variant, ...props }) {
|
|
6568
|
-
return /* @__PURE__ */ (0,
|
|
7131
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
6569
7132
|
}
|
|
6570
7133
|
|
|
6571
7134
|
// src/OhhwellsBridge.tsx
|
|
6572
|
-
var
|
|
6573
|
-
var
|
|
7135
|
+
var import_lucide_react12 = require("lucide-react");
|
|
7136
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
6574
7137
|
var PRIMARY2 = "#0885FE";
|
|
6575
7138
|
var IMAGE_FADE_MS = 300;
|
|
6576
7139
|
function runOpacityFade(el, onDone) {
|
|
@@ -6749,7 +7312,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
6749
7312
|
const root = (0, import_client.createRoot)(container);
|
|
6750
7313
|
(0, import_react_dom2.flushSync)(() => {
|
|
6751
7314
|
root.render(
|
|
6752
|
-
/* @__PURE__ */ (0,
|
|
7315
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
6753
7316
|
SchedulingWidget,
|
|
6754
7317
|
{
|
|
6755
7318
|
notifyOnConnect,
|
|
@@ -6811,7 +7374,7 @@ function isDragHandleDisabled(el) {
|
|
|
6811
7374
|
return raw === "true" || raw === "";
|
|
6812
7375
|
});
|
|
6813
7376
|
}
|
|
6814
|
-
function collectEditableNodes() {
|
|
7377
|
+
function collectEditableNodes(extraContent) {
|
|
6815
7378
|
const nodes = Array.from(document.querySelectorAll("[data-ohw-editable]")).map((el) => {
|
|
6816
7379
|
if (el.dataset.ohwEditable === "image") {
|
|
6817
7380
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
@@ -6839,6 +7402,14 @@ function collectEditableNodes() {
|
|
|
6839
7402
|
if (!key) return;
|
|
6840
7403
|
nodes.push({ key, type: "link", text: getLinkHref2(el) });
|
|
6841
7404
|
});
|
|
7405
|
+
if (extraContent) {
|
|
7406
|
+
for (const key of [NAV_ORDER_KEY, FOOTER_ORDER_KEY, NAV_COUNT_KEY]) {
|
|
7407
|
+
const text = extraContent[key];
|
|
7408
|
+
if (typeof text === "string" && text.length > 0) {
|
|
7409
|
+
nodes.push({ key, type: "meta", text });
|
|
7410
|
+
}
|
|
7411
|
+
}
|
|
7412
|
+
}
|
|
6842
7413
|
document.querySelectorAll('[data-ohw-editable="video"]').forEach((el) => {
|
|
6843
7414
|
const key = el.dataset.ohwKey ?? "";
|
|
6844
7415
|
const video = getVideoEl(el);
|
|
@@ -6846,13 +7417,10 @@ function collectEditableNodes() {
|
|
|
6846
7417
|
nodes.push({ key: `${key}${VIDEO_AUTOPLAY_SUFFIX}`, type: "video-setting", text: String(video.autoplay) });
|
|
6847
7418
|
nodes.push({ key: `${key}${VIDEO_MUTED_SUFFIX}`, type: "video-setting", text: String(video.muted) });
|
|
6848
7419
|
});
|
|
6849
|
-
const
|
|
6850
|
-
|
|
6851
|
-
|
|
6852
|
-
|
|
6853
|
-
seen.add(node.key);
|
|
6854
|
-
return true;
|
|
6855
|
-
});
|
|
7420
|
+
for (const key of listCarouselKeys()) {
|
|
7421
|
+
nodes.push({ key, type: "carousel", text: JSON.stringify(readCarouselValue(key)) });
|
|
7422
|
+
}
|
|
7423
|
+
return nodes;
|
|
6856
7424
|
}
|
|
6857
7425
|
function isMediaEditable(el) {
|
|
6858
7426
|
const t = el.dataset.ohwEditable;
|
|
@@ -6940,6 +7508,29 @@ function getHrefKeyFromElement(el) {
|
|
|
6940
7508
|
if (!key) return null;
|
|
6941
7509
|
return { anchor, key };
|
|
6942
7510
|
}
|
|
7511
|
+
function disableNativeHrefDrag(el) {
|
|
7512
|
+
if (el.draggable) el.draggable = false;
|
|
7513
|
+
if (el.getAttribute("draggable") !== "false") {
|
|
7514
|
+
el.setAttribute("draggable", "false");
|
|
7515
|
+
}
|
|
7516
|
+
}
|
|
7517
|
+
function clearTextSelection() {
|
|
7518
|
+
const sel = window.getSelection();
|
|
7519
|
+
if (sel && !sel.isCollapsed) sel.removeAllRanges();
|
|
7520
|
+
}
|
|
7521
|
+
function armFooterPressDrag() {
|
|
7522
|
+
document.documentElement.setAttribute("data-ohw-footer-press-drag", "");
|
|
7523
|
+
}
|
|
7524
|
+
function lockFooterDuringDrag() {
|
|
7525
|
+
document.documentElement.removeAttribute("data-ohw-footer-press-drag");
|
|
7526
|
+
document.documentElement.setAttribute("data-ohw-item-dragging", "");
|
|
7527
|
+
clearTextSelection();
|
|
7528
|
+
}
|
|
7529
|
+
function unlockFooterDragInteraction() {
|
|
7530
|
+
document.documentElement.removeAttribute("data-ohw-footer-press-drag");
|
|
7531
|
+
document.documentElement.removeAttribute("data-ohw-item-dragging");
|
|
7532
|
+
clearTextSelection();
|
|
7533
|
+
}
|
|
6943
7534
|
function isNavbarButton2(el) {
|
|
6944
7535
|
return Boolean(el.closest('[data-ohw-role="navbar-button"]'));
|
|
6945
7536
|
}
|
|
@@ -7002,7 +7593,7 @@ function isInferredFooterGroup(el) {
|
|
|
7002
7593
|
return Array.from(el.querySelectorAll(":scope > [data-ohw-href-key]")).some(isNavigationItem);
|
|
7003
7594
|
}
|
|
7004
7595
|
function isNavigationContainer(el) {
|
|
7005
|
-
return el.hasAttribute("data-ohw-nav-container") || isNavigationRoot(el) || isInferredFooterGroup(el);
|
|
7596
|
+
return el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-footer-col") || isNavigationRoot(el) || isInferredFooterGroup(el);
|
|
7006
7597
|
}
|
|
7007
7598
|
function isPointOverNavigation(x, y) {
|
|
7008
7599
|
const navRoot = document.querySelector("[data-ohw-nav-root]") ?? document.querySelector("nav");
|
|
@@ -7073,6 +7664,22 @@ function placeCaretAtPoint(el, x, y) {
|
|
|
7073
7664
|
}
|
|
7074
7665
|
}
|
|
7075
7666
|
}
|
|
7667
|
+
function selectAllTextInEditable(el) {
|
|
7668
|
+
const selection = window.getSelection();
|
|
7669
|
+
if (!selection) return;
|
|
7670
|
+
const range = document.createRange();
|
|
7671
|
+
range.selectNodeContents(el);
|
|
7672
|
+
selection.removeAllRanges();
|
|
7673
|
+
selection.addRange(range);
|
|
7674
|
+
}
|
|
7675
|
+
function getNavigationLabelEditable(target) {
|
|
7676
|
+
const editable = target.closest('[data-ohw-editable="text"]');
|
|
7677
|
+
if (!editable) return null;
|
|
7678
|
+
const hrefCtx = getHrefKeyFromElement(editable);
|
|
7679
|
+
const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
|
|
7680
|
+
if (!navAnchor) return null;
|
|
7681
|
+
return { editable, navAnchor };
|
|
7682
|
+
}
|
|
7076
7683
|
function collectSections() {
|
|
7077
7684
|
return collectSectionsFromDom();
|
|
7078
7685
|
}
|
|
@@ -7196,6 +7803,8 @@ var ICONS = {
|
|
|
7196
7803
|
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"/>',
|
|
7197
7804
|
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"/>'
|
|
7198
7805
|
};
|
|
7806
|
+
var TOOLBAR_PILL_PADDING = 2;
|
|
7807
|
+
var TOOLBAR_TOGGLE_GAP = 4;
|
|
7199
7808
|
var TOOLBAR_GROUPS = [
|
|
7200
7809
|
[
|
|
7201
7810
|
{ cmd: "bold", title: "Bold" },
|
|
@@ -7220,7 +7829,7 @@ function EditGlowChrome({
|
|
|
7220
7829
|
dragDisabled = false
|
|
7221
7830
|
}) {
|
|
7222
7831
|
const GAP = 6;
|
|
7223
|
-
return /* @__PURE__ */ (0,
|
|
7832
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
7224
7833
|
"div",
|
|
7225
7834
|
{
|
|
7226
7835
|
ref: elRef,
|
|
@@ -7235,7 +7844,7 @@ function EditGlowChrome({
|
|
|
7235
7844
|
zIndex: 2147483646
|
|
7236
7845
|
},
|
|
7237
7846
|
children: [
|
|
7238
|
-
/* @__PURE__ */ (0,
|
|
7847
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7239
7848
|
"div",
|
|
7240
7849
|
{
|
|
7241
7850
|
style: {
|
|
@@ -7248,7 +7857,7 @@ function EditGlowChrome({
|
|
|
7248
7857
|
}
|
|
7249
7858
|
}
|
|
7250
7859
|
),
|
|
7251
|
-
reorderHrefKey && /* @__PURE__ */ (0,
|
|
7860
|
+
reorderHrefKey && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7252
7861
|
"div",
|
|
7253
7862
|
{
|
|
7254
7863
|
"data-ohw-drag-handle-container": "",
|
|
@@ -7260,7 +7869,7 @@ function EditGlowChrome({
|
|
|
7260
7869
|
transform: "translate(calc(-100% - 7px), -50%)",
|
|
7261
7870
|
pointerEvents: dragDisabled ? "none" : "auto"
|
|
7262
7871
|
},
|
|
7263
|
-
children: /* @__PURE__ */ (0,
|
|
7872
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7264
7873
|
DragHandle,
|
|
7265
7874
|
{
|
|
7266
7875
|
"aria-label": `Reorder ${reorderHrefKey}`,
|
|
@@ -7364,7 +7973,7 @@ function FloatingToolbar({
|
|
|
7364
7973
|
onEditLink
|
|
7365
7974
|
}) {
|
|
7366
7975
|
const { top, left, transform } = calcToolbarPos(rect, parentScroll, 330);
|
|
7367
|
-
return /* @__PURE__ */ (0,
|
|
7976
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7368
7977
|
"div",
|
|
7369
7978
|
{
|
|
7370
7979
|
ref: elRef,
|
|
@@ -7374,14 +7983,23 @@ function FloatingToolbar({
|
|
|
7374
7983
|
left,
|
|
7375
7984
|
transform,
|
|
7376
7985
|
zIndex: 2147483647,
|
|
7986
|
+
background: "#fff",
|
|
7987
|
+
border: "1px solid #E7E5E4",
|
|
7988
|
+
borderRadius: 6,
|
|
7989
|
+
boxShadow: "0px 2px 4px -2px rgba(0,0,0,.1),0px 4px 6px -1px rgba(0,0,0,.1)",
|
|
7990
|
+
display: "flex",
|
|
7991
|
+
alignItems: "center",
|
|
7992
|
+
padding: TOOLBAR_PILL_PADDING,
|
|
7993
|
+
gap: TOOLBAR_TOGGLE_GAP,
|
|
7994
|
+
fontFamily: "sans-serif",
|
|
7377
7995
|
pointerEvents: "auto"
|
|
7378
7996
|
},
|
|
7379
|
-
children: /* @__PURE__ */ (0,
|
|
7380
|
-
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0,
|
|
7381
|
-
gi > 0 && /* @__PURE__ */ (0,
|
|
7997
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(CustomToolbar, { children: [
|
|
7998
|
+
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react9.default.Fragment, { children: [
|
|
7999
|
+
gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(CustomToolbarDivider, {}),
|
|
7382
8000
|
btns.map((btn) => {
|
|
7383
8001
|
const isActive = activeCommands.has(btn.cmd);
|
|
7384
|
-
return /* @__PURE__ */ (0,
|
|
8002
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7385
8003
|
CustomToolbarButton,
|
|
7386
8004
|
{
|
|
7387
8005
|
title: btn.title,
|
|
@@ -7390,7 +8008,7 @@ function FloatingToolbar({
|
|
|
7390
8008
|
e.preventDefault();
|
|
7391
8009
|
onCommand(btn.cmd);
|
|
7392
8010
|
},
|
|
7393
|
-
children: /* @__PURE__ */ (0,
|
|
8011
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7394
8012
|
"svg",
|
|
7395
8013
|
{
|
|
7396
8014
|
width: "16",
|
|
@@ -7411,7 +8029,7 @@ function FloatingToolbar({
|
|
|
7411
8029
|
);
|
|
7412
8030
|
})
|
|
7413
8031
|
] }, gi)),
|
|
7414
|
-
showEditLink ? /* @__PURE__ */ (0,
|
|
8032
|
+
showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7415
8033
|
CustomToolbarButton,
|
|
7416
8034
|
{
|
|
7417
8035
|
type: "button",
|
|
@@ -7425,7 +8043,7 @@ function FloatingToolbar({
|
|
|
7425
8043
|
e.preventDefault();
|
|
7426
8044
|
e.stopPropagation();
|
|
7427
8045
|
},
|
|
7428
|
-
children: /* @__PURE__ */ (0,
|
|
8046
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.Link, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
7429
8047
|
}
|
|
7430
8048
|
) : null
|
|
7431
8049
|
] })
|
|
@@ -7442,7 +8060,7 @@ function StateToggle({
|
|
|
7442
8060
|
states,
|
|
7443
8061
|
onStateChange
|
|
7444
8062
|
}) {
|
|
7445
|
-
return /* @__PURE__ */ (0,
|
|
8063
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7446
8064
|
ToggleGroup,
|
|
7447
8065
|
{
|
|
7448
8066
|
"data-ohw-state-toggle": "",
|
|
@@ -7456,7 +8074,7 @@ function StateToggle({
|
|
|
7456
8074
|
left: rect.right - 8,
|
|
7457
8075
|
transform: "translateX(-100%)"
|
|
7458
8076
|
},
|
|
7459
|
-
children: states.map((state) => /* @__PURE__ */ (0,
|
|
8077
|
+
children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
|
|
7460
8078
|
}
|
|
7461
8079
|
);
|
|
7462
8080
|
}
|
|
@@ -7483,8 +8101,8 @@ function OhhwellsBridge() {
|
|
|
7483
8101
|
const router = (0, import_navigation2.useRouter)();
|
|
7484
8102
|
const searchParams = (0, import_navigation2.useSearchParams)();
|
|
7485
8103
|
const isEditMode = isEditSessionActive();
|
|
7486
|
-
const [bridgeRoot, setBridgeRoot] = (0,
|
|
7487
|
-
(0,
|
|
8104
|
+
const [bridgeRoot, setBridgeRoot] = (0, import_react9.useState)(null);
|
|
8105
|
+
(0, import_react9.useEffect)(() => {
|
|
7488
8106
|
const figtreeFontId = "ohw-figtree-font";
|
|
7489
8107
|
if (!document.getElementById(figtreeFontId)) {
|
|
7490
8108
|
const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
|
|
@@ -7512,91 +8130,101 @@ function OhhwellsBridge() {
|
|
|
7512
8130
|
const subdomainFromQuery = searchParams.get("subdomain");
|
|
7513
8131
|
const subdomain = resolveSubdomain(subdomainFromQuery);
|
|
7514
8132
|
useLinkHrefGuardian(pathname, subdomain, isEditMode);
|
|
7515
|
-
const postToParent2 = (0,
|
|
8133
|
+
const postToParent2 = (0, import_react9.useCallback)((data) => {
|
|
7516
8134
|
if (typeof window !== "undefined" && window.parent !== window) {
|
|
7517
8135
|
window.parent.postMessage(data, "*");
|
|
7518
8136
|
}
|
|
7519
8137
|
}, []);
|
|
7520
|
-
const [fetchState, setFetchState] = (0,
|
|
7521
|
-
const autoSaveTimers = (0,
|
|
7522
|
-
const activeElRef = (0,
|
|
7523
|
-
const selectedElRef = (0,
|
|
7524
|
-
const originalContentRef = (0,
|
|
7525
|
-
const activeStateElRef = (0,
|
|
7526
|
-
const parentScrollRef = (0,
|
|
7527
|
-
const visibleViewportRef = (0,
|
|
7528
|
-
const [dialogPortalContainer, setDialogPortalContainer] = (0,
|
|
7529
|
-
const attachVisibleViewport = (0,
|
|
8138
|
+
const [fetchState, setFetchState] = (0, import_react9.useState)("idle");
|
|
8139
|
+
const autoSaveTimers = (0, import_react9.useRef)(/* @__PURE__ */ new Map());
|
|
8140
|
+
const activeElRef = (0, import_react9.useRef)(null);
|
|
8141
|
+
const selectedElRef = (0, import_react9.useRef)(null);
|
|
8142
|
+
const originalContentRef = (0, import_react9.useRef)(null);
|
|
8143
|
+
const activeStateElRef = (0, import_react9.useRef)(null);
|
|
8144
|
+
const parentScrollRef = (0, import_react9.useRef)(null);
|
|
8145
|
+
const visibleViewportRef = (0, import_react9.useRef)(null);
|
|
8146
|
+
const [dialogPortalContainer, setDialogPortalContainer] = (0, import_react9.useState)(null);
|
|
8147
|
+
const attachVisibleViewport = (0, import_react9.useCallback)((node) => {
|
|
7530
8148
|
visibleViewportRef.current = node;
|
|
7531
8149
|
setDialogPortalContainer(node);
|
|
7532
8150
|
if (node) applyVisibleViewport(node, parentScrollRef.current);
|
|
7533
8151
|
}, []);
|
|
7534
|
-
const toolbarElRef = (0,
|
|
7535
|
-
const glowElRef = (0,
|
|
7536
|
-
const hoveredImageRef = (0,
|
|
7537
|
-
const hoveredImageHasTextOverlapRef = (0,
|
|
7538
|
-
const dragOverElRef = (0,
|
|
7539
|
-
const [mediaHover, setMediaHover] = (0,
|
|
7540
|
-
const [
|
|
7541
|
-
const
|
|
7542
|
-
const
|
|
7543
|
-
const
|
|
7544
|
-
const
|
|
7545
|
-
const
|
|
8152
|
+
const toolbarElRef = (0, import_react9.useRef)(null);
|
|
8153
|
+
const glowElRef = (0, import_react9.useRef)(null);
|
|
8154
|
+
const hoveredImageRef = (0, import_react9.useRef)(null);
|
|
8155
|
+
const hoveredImageHasTextOverlapRef = (0, import_react9.useRef)(false);
|
|
8156
|
+
const dragOverElRef = (0, import_react9.useRef)(null);
|
|
8157
|
+
const [mediaHover, setMediaHover] = (0, import_react9.useState)(null);
|
|
8158
|
+
const [carouselHover, setCarouselHover] = (0, import_react9.useState)(null);
|
|
8159
|
+
const [uploadingRects, setUploadingRects] = (0, import_react9.useState)({});
|
|
8160
|
+
const pendingUploadRectRef = (0, import_react9.useRef)(null);
|
|
8161
|
+
const hoveredGapRef = (0, import_react9.useRef)(null);
|
|
8162
|
+
const imageUnhoverTimerRef = (0, import_react9.useRef)(null);
|
|
8163
|
+
const imageShowTimerRef = (0, import_react9.useRef)(null);
|
|
8164
|
+
const editStylesRef = (0, import_react9.useRef)(null);
|
|
8165
|
+
const activateRef = (0, import_react9.useRef)(() => {
|
|
7546
8166
|
});
|
|
7547
|
-
const deactivateRef = (0,
|
|
8167
|
+
const deactivateRef = (0, import_react9.useRef)(() => {
|
|
7548
8168
|
});
|
|
7549
|
-
const selectRef = (0,
|
|
8169
|
+
const selectRef = (0, import_react9.useRef)(() => {
|
|
7550
8170
|
});
|
|
7551
|
-
const selectFrameRef = (0,
|
|
8171
|
+
const selectFrameRef = (0, import_react9.useRef)(() => {
|
|
7552
8172
|
});
|
|
7553
|
-
const deselectRef = (0,
|
|
8173
|
+
const deselectRef = (0, import_react9.useRef)(() => {
|
|
7554
8174
|
});
|
|
7555
|
-
const reselectNavigationItemRef = (0,
|
|
8175
|
+
const reselectNavigationItemRef = (0, import_react9.useRef)(() => {
|
|
7556
8176
|
});
|
|
7557
|
-
const commitNavigationTextEditRef = (0,
|
|
8177
|
+
const commitNavigationTextEditRef = (0, import_react9.useRef)(() => {
|
|
7558
8178
|
});
|
|
7559
|
-
const refreshActiveCommandsRef = (0,
|
|
8179
|
+
const refreshActiveCommandsRef = (0, import_react9.useRef)(() => {
|
|
7560
8180
|
});
|
|
7561
|
-
const postToParentRef = (0,
|
|
8181
|
+
const postToParentRef = (0, import_react9.useRef)(postToParent2);
|
|
7562
8182
|
postToParentRef.current = postToParent2;
|
|
7563
|
-
const sectionsLoadedRef = (0,
|
|
7564
|
-
const pendingScheduleConfigRequests = (0,
|
|
7565
|
-
const [toolbarRect, setToolbarRect] = (0,
|
|
7566
|
-
const [toolbarVariant, setToolbarVariant] = (0,
|
|
7567
|
-
const toolbarVariantRef = (0,
|
|
8183
|
+
const sectionsLoadedRef = (0, import_react9.useRef)(false);
|
|
8184
|
+
const pendingScheduleConfigRequests = (0, import_react9.useRef)([]);
|
|
8185
|
+
const [toolbarRect, setToolbarRect] = (0, import_react9.useState)(null);
|
|
8186
|
+
const [toolbarVariant, setToolbarVariant] = (0, import_react9.useState)("none");
|
|
8187
|
+
const toolbarVariantRef = (0, import_react9.useRef)("none");
|
|
7568
8188
|
toolbarVariantRef.current = toolbarVariant;
|
|
7569
|
-
const [reorderHrefKey, setReorderHrefKey] = (0,
|
|
7570
|
-
const [reorderDragDisabled, setReorderDragDisabled] = (0,
|
|
7571
|
-
const [toggleState, setToggleState] = (0,
|
|
7572
|
-
const [maxBadge, setMaxBadge] = (0,
|
|
7573
|
-
const [activeCommands, setActiveCommands] = (0,
|
|
7574
|
-
const [sectionGap, setSectionGap] = (0,
|
|
7575
|
-
const [toolbarShowEditLink, setToolbarShowEditLink] = (0,
|
|
7576
|
-
const hoveredNavContainerRef = (0,
|
|
7577
|
-
const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0,
|
|
7578
|
-
const hoveredItemElRef = (0,
|
|
7579
|
-
const [hoveredItemRect, setHoveredItemRect] = (0,
|
|
7580
|
-
const siblingHintElRef = (0,
|
|
7581
|
-
const [siblingHintRect, setSiblingHintRect] = (0,
|
|
7582
|
-
const [
|
|
7583
|
-
const [
|
|
7584
|
-
const
|
|
7585
|
-
const
|
|
7586
|
-
const
|
|
7587
|
-
const [
|
|
7588
|
-
const [
|
|
7589
|
-
const
|
|
7590
|
-
const
|
|
7591
|
-
const
|
|
7592
|
-
const
|
|
7593
|
-
const
|
|
8189
|
+
const [reorderHrefKey, setReorderHrefKey] = (0, import_react9.useState)(null);
|
|
8190
|
+
const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react9.useState)(false);
|
|
8191
|
+
const [toggleState, setToggleState] = (0, import_react9.useState)(null);
|
|
8192
|
+
const [maxBadge, setMaxBadge] = (0, import_react9.useState)(null);
|
|
8193
|
+
const [activeCommands, setActiveCommands] = (0, import_react9.useState)(/* @__PURE__ */ new Set());
|
|
8194
|
+
const [sectionGap, setSectionGap] = (0, import_react9.useState)(null);
|
|
8195
|
+
const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react9.useState)(false);
|
|
8196
|
+
const hoveredNavContainerRef = (0, import_react9.useRef)(null);
|
|
8197
|
+
const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0, import_react9.useState)(null);
|
|
8198
|
+
const hoveredItemElRef = (0, import_react9.useRef)(null);
|
|
8199
|
+
const [hoveredItemRect, setHoveredItemRect] = (0, import_react9.useState)(null);
|
|
8200
|
+
const siblingHintElRef = (0, import_react9.useRef)(null);
|
|
8201
|
+
const [siblingHintRect, setSiblingHintRect] = (0, import_react9.useState)(null);
|
|
8202
|
+
const [siblingHintRects, setSiblingHintRects] = (0, import_react9.useState)([]);
|
|
8203
|
+
const [isItemDragging, setIsItemDragging] = (0, import_react9.useState)(false);
|
|
8204
|
+
const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react9.useState)(false);
|
|
8205
|
+
const footerDragRef = (0, import_react9.useRef)(null);
|
|
8206
|
+
const [footerDropSlots, setFooterDropSlots] = (0, import_react9.useState)([]);
|
|
8207
|
+
const [activeFooterDropIndex, setActiveFooterDropIndex] = (0, import_react9.useState)(null);
|
|
8208
|
+
const [draggedItemRect, setDraggedItemRect] = (0, import_react9.useState)(null);
|
|
8209
|
+
const footerPointerDragRef = (0, import_react9.useRef)(null);
|
|
8210
|
+
const suppressNextClickRef = (0, import_react9.useRef)(false);
|
|
8211
|
+
const [linkPopover, setLinkPopover] = (0, import_react9.useState)(null);
|
|
8212
|
+
const linkPopoverSessionRef = (0, import_react9.useRef)(null);
|
|
8213
|
+
const addNavAfterAnchorRef = (0, import_react9.useRef)(null);
|
|
8214
|
+
const editContentRef = (0, import_react9.useRef)({});
|
|
8215
|
+
const [sitePages, setSitePages] = (0, import_react9.useState)([]);
|
|
8216
|
+
const [sectionsByPath, setSectionsByPath] = (0, import_react9.useState)({});
|
|
8217
|
+
const sectionsPrefetchGenRef = (0, import_react9.useRef)(0);
|
|
8218
|
+
const setLinkPopoverRef = (0, import_react9.useRef)(setLinkPopover);
|
|
8219
|
+
const linkPopoverPanelRef = (0, import_react9.useRef)(null);
|
|
8220
|
+
const linkPopoverOpenRef = (0, import_react9.useRef)(false);
|
|
8221
|
+
const linkPopoverGraceUntilRef = (0, import_react9.useRef)(0);
|
|
7594
8222
|
setLinkPopoverRef.current = setLinkPopover;
|
|
7595
8223
|
linkPopoverSessionRef.current = linkPopover;
|
|
7596
8224
|
const bumpLinkPopoverGrace = () => {
|
|
7597
8225
|
linkPopoverGraceUntilRef.current = Date.now() + 350;
|
|
7598
8226
|
};
|
|
7599
|
-
const runSectionsPrefetch = (0,
|
|
8227
|
+
const runSectionsPrefetch = (0, import_react9.useCallback)((pages) => {
|
|
7600
8228
|
if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
|
|
7601
8229
|
const gen = ++sectionsPrefetchGenRef.current;
|
|
7602
8230
|
const paths = pages.map((p) => p.path);
|
|
@@ -7615,10 +8243,14 @@ function OhhwellsBridge() {
|
|
|
7615
8243
|
);
|
|
7616
8244
|
});
|
|
7617
8245
|
}, [isEditMode, pathname]);
|
|
7618
|
-
const runSectionsPrefetchRef = (0,
|
|
8246
|
+
const runSectionsPrefetchRef = (0, import_react9.useRef)(runSectionsPrefetch);
|
|
7619
8247
|
runSectionsPrefetchRef.current = runSectionsPrefetch;
|
|
7620
|
-
(0,
|
|
7621
|
-
if (!linkPopover)
|
|
8248
|
+
(0, import_react9.useEffect)(() => {
|
|
8249
|
+
if (!linkPopover) {
|
|
8250
|
+
document.documentElement.removeAttribute("data-ohw-link-popover-open");
|
|
8251
|
+
return;
|
|
8252
|
+
}
|
|
8253
|
+
document.documentElement.setAttribute("data-ohw-link-popover-open", "");
|
|
7622
8254
|
if (hoveredImageRef.current) {
|
|
7623
8255
|
hoveredImageRef.current = null;
|
|
7624
8256
|
hoveredImageHasTextOverlapRef.current = false;
|
|
@@ -7645,14 +8277,10 @@ function OhhwellsBridge() {
|
|
|
7645
8277
|
document.addEventListener("touchmove", preventBackgroundScroll, scrollOpts);
|
|
7646
8278
|
postToParent2({ type: "ow:image-unhover" });
|
|
7647
8279
|
return () => {
|
|
7648
|
-
|
|
7649
|
-
html.style.overflow = prevHtmlOverflow;
|
|
7650
|
-
body.style.overflow = prevBodyOverflow;
|
|
7651
|
-
document.removeEventListener("wheel", preventBackgroundScroll, scrollOpts);
|
|
7652
|
-
document.removeEventListener("touchmove", preventBackgroundScroll, scrollOpts);
|
|
8280
|
+
document.documentElement.removeAttribute("data-ohw-link-popover-open");
|
|
7653
8281
|
};
|
|
7654
8282
|
}, [linkPopover, postToParent2]);
|
|
7655
|
-
(0,
|
|
8283
|
+
(0, import_react9.useEffect)(() => {
|
|
7656
8284
|
if (!isEditMode) return;
|
|
7657
8285
|
const useFixtures = shouldUseDevFixtures();
|
|
7658
8286
|
if (useFixtures) {
|
|
@@ -7676,14 +8304,14 @@ function OhhwellsBridge() {
|
|
|
7676
8304
|
if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
|
|
7677
8305
|
return () => window.removeEventListener("message", onSitePages);
|
|
7678
8306
|
}, [isEditMode, postToParent2]);
|
|
7679
|
-
(0,
|
|
8307
|
+
(0, import_react9.useEffect)(() => {
|
|
7680
8308
|
if (!isEditMode || shouldUseDevFixtures()) return;
|
|
7681
8309
|
void loadAllSectionsManifest().then((manifest) => {
|
|
7682
8310
|
if (Object.keys(manifest).length === 0) return;
|
|
7683
8311
|
setSectionsByPath((prev) => ({ ...manifest, ...prev }));
|
|
7684
8312
|
});
|
|
7685
8313
|
}, [isEditMode]);
|
|
7686
|
-
(0,
|
|
8314
|
+
(0, import_react9.useEffect)(() => {
|
|
7687
8315
|
const update = () => {
|
|
7688
8316
|
const el = activeElRef.current ?? selectedElRef.current;
|
|
7689
8317
|
if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
@@ -7707,10 +8335,10 @@ function OhhwellsBridge() {
|
|
|
7707
8335
|
vvp.removeEventListener("resize", update);
|
|
7708
8336
|
};
|
|
7709
8337
|
}, []);
|
|
7710
|
-
const refreshStateRules = (0,
|
|
8338
|
+
const refreshStateRules = (0, import_react9.useCallback)(() => {
|
|
7711
8339
|
editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
|
|
7712
8340
|
}, []);
|
|
7713
|
-
const processConfigRequest = (0,
|
|
8341
|
+
const processConfigRequest = (0, import_react9.useCallback)((insertAfterVal) => {
|
|
7714
8342
|
const tracker = getSectionsTracker();
|
|
7715
8343
|
let entries = [];
|
|
7716
8344
|
try {
|
|
@@ -7733,7 +8361,7 @@ function OhhwellsBridge() {
|
|
|
7733
8361
|
}
|
|
7734
8362
|
window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
|
|
7735
8363
|
}, [isEditMode]);
|
|
7736
|
-
const deactivate = (0,
|
|
8364
|
+
const deactivate = (0, import_react9.useCallback)(() => {
|
|
7737
8365
|
const el = activeElRef.current;
|
|
7738
8366
|
if (!el) return;
|
|
7739
8367
|
const key = el.dataset.ohwKey;
|
|
@@ -7764,12 +8392,14 @@ function OhhwellsBridge() {
|
|
|
7764
8392
|
setToolbarShowEditLink(false);
|
|
7765
8393
|
postToParent2({ type: "ow:exit-edit" });
|
|
7766
8394
|
}, [postToParent2]);
|
|
7767
|
-
const deselect = (0,
|
|
8395
|
+
const deselect = (0, import_react9.useCallback)(() => {
|
|
7768
8396
|
selectedElRef.current = null;
|
|
7769
8397
|
setReorderHrefKey(null);
|
|
7770
8398
|
setReorderDragDisabled(false);
|
|
8399
|
+
setIsFooterFrameSelection(false);
|
|
7771
8400
|
siblingHintElRef.current = null;
|
|
7772
8401
|
setSiblingHintRect(null);
|
|
8402
|
+
setSiblingHintRects([]);
|
|
7773
8403
|
setIsItemDragging(false);
|
|
7774
8404
|
hoveredNavContainerRef.current = null;
|
|
7775
8405
|
setHoveredNavContainerRect(null);
|
|
@@ -7778,7 +8408,7 @@ function OhhwellsBridge() {
|
|
|
7778
8408
|
setToolbarVariant("none");
|
|
7779
8409
|
}
|
|
7780
8410
|
}, []);
|
|
7781
|
-
const reselectNavigationItem = (0,
|
|
8411
|
+
const reselectNavigationItem = (0, import_react9.useCallback)((navAnchor) => {
|
|
7782
8412
|
selectedElRef.current = navAnchor;
|
|
7783
8413
|
const { key, disabled } = getNavigationItemReorderState(navAnchor);
|
|
7784
8414
|
setReorderHrefKey(key);
|
|
@@ -7788,7 +8418,7 @@ function OhhwellsBridge() {
|
|
|
7788
8418
|
setToolbarShowEditLink(false);
|
|
7789
8419
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
7790
8420
|
}, []);
|
|
7791
|
-
const commitNavigationTextEdit = (0,
|
|
8421
|
+
const commitNavigationTextEdit = (0, import_react9.useCallback)((navAnchor) => {
|
|
7792
8422
|
const el = activeElRef.current;
|
|
7793
8423
|
if (!el) return;
|
|
7794
8424
|
const key = el.dataset.ohwKey;
|
|
@@ -7814,7 +8444,7 @@ function OhhwellsBridge() {
|
|
|
7814
8444
|
postToParent2({ type: "ow:exit-edit" });
|
|
7815
8445
|
reselectNavigationItem(navAnchor);
|
|
7816
8446
|
}, [postToParent2, reselectNavigationItem]);
|
|
7817
|
-
const handleAddTopLevelNavItem = (0,
|
|
8447
|
+
const handleAddTopLevelNavItem = (0, import_react9.useCallback)(() => {
|
|
7818
8448
|
const items = listNavbarItems();
|
|
7819
8449
|
addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
|
|
7820
8450
|
deselectRef.current();
|
|
@@ -7826,96 +8456,393 @@ function OhhwellsBridge() {
|
|
|
7826
8456
|
intent: "add-nav"
|
|
7827
8457
|
});
|
|
7828
8458
|
}, []);
|
|
7829
|
-
const
|
|
7830
|
-
|
|
7831
|
-
|
|
7832
|
-
|
|
7833
|
-
|
|
7834
|
-
|
|
8459
|
+
const clearFooterDragVisuals = (0, import_react9.useCallback)(() => {
|
|
8460
|
+
footerDragRef.current = null;
|
|
8461
|
+
setSiblingHintRects([]);
|
|
8462
|
+
setFooterDropSlots([]);
|
|
8463
|
+
setActiveFooterDropIndex(null);
|
|
8464
|
+
setDraggedItemRect(null);
|
|
7835
8465
|
setIsItemDragging(false);
|
|
8466
|
+
unlockFooterDragInteraction();
|
|
7836
8467
|
}, []);
|
|
7837
|
-
|
|
7838
|
-
|
|
7839
|
-
|
|
7840
|
-
if (
|
|
7841
|
-
|
|
7842
|
-
|
|
7843
|
-
clearHrefKeyHover(anchor);
|
|
7844
|
-
hoveredNavContainerRef.current = null;
|
|
7845
|
-
setHoveredNavContainerRect(null);
|
|
7846
|
-
setHoveredItemRect(null);
|
|
7847
|
-
hoveredItemElRef.current = null;
|
|
7848
|
-
siblingHintElRef.current = null;
|
|
7849
|
-
setSiblingHintRect(null);
|
|
7850
|
-
setIsItemDragging(false);
|
|
7851
|
-
const { key, disabled } = getNavigationItemReorderState(anchor);
|
|
7852
|
-
setReorderHrefKey(key);
|
|
7853
|
-
setReorderDragDisabled(disabled);
|
|
7854
|
-
setToolbarVariant("link-action");
|
|
7855
|
-
setToolbarRect(anchor.getBoundingClientRect());
|
|
7856
|
-
setToolbarShowEditLink(false);
|
|
7857
|
-
setActiveCommands(/* @__PURE__ */ new Set());
|
|
7858
|
-
}, [deactivate]);
|
|
7859
|
-
const selectFrame = (0, import_react8.useCallback)((el) => {
|
|
7860
|
-
if (!isNavigationContainer(el)) return;
|
|
7861
|
-
if (activeElRef.current) deactivate();
|
|
7862
|
-
selectedElRef.current = el;
|
|
7863
|
-
clearHrefKeyHover(el);
|
|
7864
|
-
hoveredNavContainerRef.current = null;
|
|
7865
|
-
setHoveredNavContainerRect(null);
|
|
7866
|
-
setHoveredItemRect(null);
|
|
7867
|
-
hoveredItemElRef.current = null;
|
|
7868
|
-
siblingHintElRef.current = null;
|
|
7869
|
-
setSiblingHintRect(null);
|
|
7870
|
-
setIsItemDragging(false);
|
|
7871
|
-
setReorderHrefKey(null);
|
|
7872
|
-
setReorderDragDisabled(false);
|
|
7873
|
-
setToolbarVariant("select-frame");
|
|
7874
|
-
setToolbarRect(el.getBoundingClientRect());
|
|
7875
|
-
setToolbarShowEditLink(false);
|
|
7876
|
-
setActiveCommands(/* @__PURE__ */ new Set());
|
|
7877
|
-
}, [deactivate]);
|
|
7878
|
-
const activate = (0, import_react8.useCallback)((el, options) => {
|
|
7879
|
-
if (activeElRef.current === el) return;
|
|
7880
|
-
selectedElRef.current = null;
|
|
7881
|
-
deactivate();
|
|
7882
|
-
if (hoveredImageRef.current) {
|
|
7883
|
-
hoveredImageRef.current = null;
|
|
7884
|
-
setMediaHover(null);
|
|
8468
|
+
const refreshFooterDragVisuals = (0, import_react9.useCallback)((session, activeSlot, clientX, clientY) => {
|
|
8469
|
+
const dragged = session.draggedEl;
|
|
8470
|
+
setDraggedItemRect(dragged.getBoundingClientRect());
|
|
8471
|
+
if (typeof clientX === "number" && typeof clientY === "number") {
|
|
8472
|
+
session.lastClientX = clientX;
|
|
8473
|
+
session.lastClientY = clientY;
|
|
7885
8474
|
}
|
|
7886
|
-
|
|
7887
|
-
|
|
7888
|
-
|
|
7889
|
-
|
|
7890
|
-
|
|
7891
|
-
|
|
7892
|
-
|
|
7893
|
-
|
|
7894
|
-
|
|
7895
|
-
|
|
7896
|
-
|
|
7897
|
-
|
|
8475
|
+
session.activeSlot = activeSlot;
|
|
8476
|
+
if (session.kind === "link") {
|
|
8477
|
+
const columns2 = listFooterColumns();
|
|
8478
|
+
const focusCols = /* @__PURE__ */ new Set([session.sourceColumnIndex]);
|
|
8479
|
+
if (activeSlot) focusCols.add(activeSlot.columnIndex);
|
|
8480
|
+
const siblingRects = [];
|
|
8481
|
+
columns2.forEach((col, i) => {
|
|
8482
|
+
if (!focusCols.has(i)) return;
|
|
8483
|
+
for (const link of listFooterLinksInColumn(col)) {
|
|
8484
|
+
if (link === dragged) continue;
|
|
8485
|
+
siblingRects.push(link.getBoundingClientRect());
|
|
8486
|
+
}
|
|
8487
|
+
});
|
|
8488
|
+
setSiblingHintRects(siblingRects);
|
|
8489
|
+
const slots2 = [];
|
|
8490
|
+
columns2.forEach((col, i) => {
|
|
8491
|
+
slots2.push(...buildLinkDropSlots(col, i));
|
|
8492
|
+
});
|
|
8493
|
+
setFooterDropSlots(slots2);
|
|
8494
|
+
const activeIdx2 = activeSlot ? slots2.findIndex((s) => s.columnIndex === activeSlot.columnIndex && s.insertIndex === activeSlot.insertIndex) : -1;
|
|
8495
|
+
setActiveFooterDropIndex(activeIdx2 >= 0 ? activeIdx2 : null);
|
|
8496
|
+
return;
|
|
7898
8497
|
}
|
|
7899
|
-
|
|
7900
|
-
|
|
7901
|
-
|
|
8498
|
+
const columns = listFooterColumns();
|
|
8499
|
+
setSiblingHintRects(columns.filter((col) => col !== dragged).map((col) => col.getBoundingClientRect()));
|
|
8500
|
+
const slots = buildColumnDropSlots();
|
|
8501
|
+
setFooterDropSlots(slots);
|
|
8502
|
+
const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
|
|
8503
|
+
setActiveFooterDropIndex(activeIdx >= 0 ? activeIdx : null);
|
|
8504
|
+
}, []);
|
|
8505
|
+
const refreshFooterDragVisualsRef = (0, import_react9.useRef)(refreshFooterDragVisuals);
|
|
8506
|
+
refreshFooterDragVisualsRef.current = refreshFooterDragVisuals;
|
|
8507
|
+
const commitFooterDragRef = (0, import_react9.useRef)(() => {
|
|
8508
|
+
});
|
|
8509
|
+
const beginFooterDragRef = (0, import_react9.useRef)(() => {
|
|
8510
|
+
});
|
|
8511
|
+
const beginFooterDrag = (0, import_react9.useCallback)(
|
|
8512
|
+
(session) => {
|
|
8513
|
+
const rect = session.draggedEl.getBoundingClientRect();
|
|
8514
|
+
session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
|
|
8515
|
+
session.lastClientY = session.lastClientY || rect.top + rect.height / 2;
|
|
8516
|
+
session.activeSlot = session.activeSlot ?? null;
|
|
8517
|
+
footerDragRef.current = session;
|
|
8518
|
+
setIsItemDragging(true);
|
|
8519
|
+
lockFooterDuringDrag();
|
|
8520
|
+
siblingHintElRef.current = null;
|
|
8521
|
+
setSiblingHintRect(null);
|
|
8522
|
+
if (session.wasSelected && selectedElRef.current === session.draggedEl) {
|
|
8523
|
+
setToolbarRect(rect);
|
|
8524
|
+
}
|
|
8525
|
+
const initialSlot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
|
|
8526
|
+
refreshFooterDragVisuals(session, initialSlot, session.lastClientX, session.lastClientY);
|
|
8527
|
+
},
|
|
8528
|
+
[refreshFooterDragVisuals]
|
|
8529
|
+
);
|
|
8530
|
+
beginFooterDragRef.current = beginFooterDrag;
|
|
8531
|
+
const commitFooterDrag = (0, import_react9.useCallback)(
|
|
8532
|
+
(clientX, clientY) => {
|
|
8533
|
+
const session = footerDragRef.current;
|
|
8534
|
+
if (!session) {
|
|
8535
|
+
clearFooterDragVisuals();
|
|
8536
|
+
return;
|
|
8537
|
+
}
|
|
8538
|
+
const x = typeof clientX === "number" && (clientX !== 0 || clientY !== 0) ? clientX : session.lastClientX;
|
|
8539
|
+
const y = typeof clientY === "number" && (clientX !== 0 || clientY !== 0) ? clientY : session.lastClientY;
|
|
8540
|
+
let nextOrder = null;
|
|
8541
|
+
const slot = session.activeSlot ?? (session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(x, y, session.hrefKey) : session.kind === "column" ? hitTestColumnDropSlot(x, y) : null);
|
|
8542
|
+
if (session.kind === "link" && session.hrefKey && slot) {
|
|
8543
|
+
nextOrder = planFooterLinkMove(session.hrefKey, slot.columnIndex, slot.insertIndex);
|
|
8544
|
+
} else if (session.kind === "column" && slot) {
|
|
8545
|
+
nextOrder = planFooterColumnMove(session.sourceColumnIndex, slot.insertIndex);
|
|
8546
|
+
}
|
|
8547
|
+
const wasSelected = session.wasSelected;
|
|
8548
|
+
const draggedEl = session.draggedEl;
|
|
8549
|
+
const hrefKey = session.hrefKey;
|
|
8550
|
+
let movedColumnIndex = null;
|
|
8551
|
+
if (session.kind === "column" && slot && nextOrder) {
|
|
8552
|
+
let adjusted = slot.insertIndex;
|
|
8553
|
+
if (session.sourceColumnIndex < slot.insertIndex) adjusted -= 1;
|
|
8554
|
+
movedColumnIndex = Math.max(0, Math.min(adjusted, nextOrder.length - 1));
|
|
8555
|
+
}
|
|
8556
|
+
clearFooterDragVisuals();
|
|
8557
|
+
const applySelectionAfterDrop = () => {
|
|
8558
|
+
if (!wasSelected) {
|
|
8559
|
+
deselectRef.current();
|
|
8560
|
+
return;
|
|
8561
|
+
}
|
|
8562
|
+
if (hrefKey) {
|
|
8563
|
+
const link = document.querySelector(
|
|
8564
|
+
`footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
8565
|
+
);
|
|
8566
|
+
if (link && isNavigationItem(link)) {
|
|
8567
|
+
selectRef.current(link);
|
|
8568
|
+
return;
|
|
8569
|
+
}
|
|
8570
|
+
}
|
|
8571
|
+
if (movedColumnIndex !== null && nextOrder) {
|
|
8572
|
+
const colKeys = nextOrder[movedColumnIndex] ?? [];
|
|
8573
|
+
let column = null;
|
|
8574
|
+
for (const key of colKeys) {
|
|
8575
|
+
const link = document.querySelector(
|
|
8576
|
+
`footer [data-ohw-href-key="${CSS.escape(key)}"]`
|
|
8577
|
+
);
|
|
8578
|
+
if (link) {
|
|
8579
|
+
column = findFooterColumnForLink(link);
|
|
8580
|
+
if (column) break;
|
|
8581
|
+
}
|
|
8582
|
+
}
|
|
8583
|
+
if (!column) column = listFooterColumns()[movedColumnIndex] ?? null;
|
|
8584
|
+
if (column && isNavigationContainer(column)) {
|
|
8585
|
+
selectFrameRef.current(column);
|
|
8586
|
+
return;
|
|
8587
|
+
}
|
|
8588
|
+
}
|
|
8589
|
+
if (document.body.contains(draggedEl)) {
|
|
8590
|
+
if (isNavigationItem(draggedEl)) {
|
|
8591
|
+
selectRef.current(draggedEl);
|
|
8592
|
+
return;
|
|
8593
|
+
}
|
|
8594
|
+
if (isNavigationContainer(draggedEl)) {
|
|
8595
|
+
selectFrameRef.current(draggedEl);
|
|
8596
|
+
return;
|
|
8597
|
+
}
|
|
8598
|
+
}
|
|
8599
|
+
deselectRef.current();
|
|
8600
|
+
};
|
|
8601
|
+
if (!wasSelected) {
|
|
8602
|
+
deselectRef.current();
|
|
8603
|
+
}
|
|
8604
|
+
if (nextOrder) {
|
|
8605
|
+
const orderJson = JSON.stringify(nextOrder);
|
|
8606
|
+
editContentRef.current = {
|
|
8607
|
+
...editContentRef.current,
|
|
8608
|
+
[FOOTER_ORDER_KEY]: orderJson
|
|
8609
|
+
};
|
|
8610
|
+
applyFooterOrder(nextOrder);
|
|
8611
|
+
document.querySelectorAll("footer [data-ohw-href-key]").forEach(disableNativeHrefDrag);
|
|
8612
|
+
postToParentRef.current({
|
|
8613
|
+
type: "ow:change",
|
|
8614
|
+
nodes: [{ key: FOOTER_ORDER_KEY, text: orderJson }]
|
|
8615
|
+
});
|
|
8616
|
+
requestAnimationFrame(() => {
|
|
8617
|
+
if (editContentRef.current[FOOTER_ORDER_KEY] === orderJson) {
|
|
8618
|
+
applyFooterOrder(nextOrder);
|
|
8619
|
+
document.querySelectorAll("footer [data-ohw-href-key]").forEach(disableNativeHrefDrag);
|
|
8620
|
+
}
|
|
8621
|
+
requestAnimationFrame(applySelectionAfterDrop);
|
|
8622
|
+
});
|
|
8623
|
+
return;
|
|
8624
|
+
}
|
|
8625
|
+
applySelectionAfterDrop();
|
|
8626
|
+
},
|
|
8627
|
+
[clearFooterDragVisuals]
|
|
8628
|
+
);
|
|
8629
|
+
commitFooterDragRef.current = commitFooterDrag;
|
|
8630
|
+
const startFooterLinkDrag = (0, import_react9.useCallback)(
|
|
8631
|
+
(anchor, clientX, clientY, wasSelected) => {
|
|
8632
|
+
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
8633
|
+
if (!hrefKey || !isFooterHrefKey(hrefKey)) return false;
|
|
8634
|
+
const column = findFooterColumnForLink(anchor);
|
|
8635
|
+
const columns = listFooterColumns();
|
|
8636
|
+
beginFooterDrag({
|
|
8637
|
+
kind: "link",
|
|
8638
|
+
hrefKey,
|
|
8639
|
+
columnEl: column,
|
|
8640
|
+
sourceColumnIndex: column ? columns.indexOf(column) : 0,
|
|
8641
|
+
wasSelected,
|
|
8642
|
+
draggedEl: anchor,
|
|
8643
|
+
lastClientX: clientX,
|
|
8644
|
+
lastClientY: clientY,
|
|
8645
|
+
activeSlot: null
|
|
8646
|
+
});
|
|
8647
|
+
return true;
|
|
8648
|
+
},
|
|
8649
|
+
[beginFooterDrag]
|
|
8650
|
+
);
|
|
8651
|
+
const startFooterColumnDrag = (0, import_react9.useCallback)(
|
|
8652
|
+
(columnEl, clientX, clientY, wasSelected) => {
|
|
8653
|
+
const columns = listFooterColumns();
|
|
8654
|
+
const idx = columns.indexOf(columnEl);
|
|
8655
|
+
if (idx < 0) return false;
|
|
8656
|
+
beginFooterDrag({
|
|
8657
|
+
kind: "column",
|
|
8658
|
+
hrefKey: null,
|
|
8659
|
+
columnEl,
|
|
8660
|
+
sourceColumnIndex: idx,
|
|
8661
|
+
wasSelected,
|
|
8662
|
+
draggedEl: columnEl,
|
|
8663
|
+
lastClientX: clientX,
|
|
8664
|
+
lastClientY: clientY,
|
|
8665
|
+
activeSlot: null
|
|
8666
|
+
});
|
|
8667
|
+
return true;
|
|
8668
|
+
},
|
|
8669
|
+
[beginFooterDrag]
|
|
8670
|
+
);
|
|
8671
|
+
const handleItemDragStart = (0, import_react9.useCallback)(
|
|
8672
|
+
(e) => {
|
|
8673
|
+
const selected = selectedElRef.current;
|
|
8674
|
+
if (!selected) {
|
|
8675
|
+
setIsItemDragging(true);
|
|
8676
|
+
return;
|
|
8677
|
+
}
|
|
8678
|
+
const clientX = e?.clientX ?? selected.getBoundingClientRect().left + 8;
|
|
8679
|
+
const clientY = e?.clientY ?? selected.getBoundingClientRect().top + 8;
|
|
8680
|
+
if (startFooterLinkDrag(selected, clientX, clientY, true)) return;
|
|
8681
|
+
if (selected.hasAttribute("data-ohw-footer-col") || isInferredFooterGroup(selected) && selected.closest("footer")) {
|
|
8682
|
+
if (startFooterColumnDrag(selected, clientX, clientY, true)) return;
|
|
8683
|
+
}
|
|
8684
|
+
siblingHintElRef.current = null;
|
|
8685
|
+
setSiblingHintRect(null);
|
|
8686
|
+
setIsItemDragging(true);
|
|
8687
|
+
},
|
|
8688
|
+
[startFooterColumnDrag, startFooterLinkDrag]
|
|
8689
|
+
);
|
|
8690
|
+
const handleItemDragEnd = (0, import_react9.useCallback)(
|
|
8691
|
+
(e) => {
|
|
8692
|
+
if (footerDragRef.current) {
|
|
8693
|
+
const x = e?.clientX;
|
|
8694
|
+
const y = e?.clientY;
|
|
8695
|
+
if (typeof x === "number" && typeof y === "number" && (x !== 0 || y !== 0)) {
|
|
8696
|
+
commitFooterDrag(x, y);
|
|
8697
|
+
} else {
|
|
8698
|
+
commitFooterDrag();
|
|
8699
|
+
}
|
|
8700
|
+
return;
|
|
8701
|
+
}
|
|
8702
|
+
setIsItemDragging(false);
|
|
8703
|
+
},
|
|
8704
|
+
[commitFooterDrag]
|
|
8705
|
+
);
|
|
8706
|
+
const handleItemChromePointerDown = (0, import_react9.useCallback)((e) => {
|
|
8707
|
+
if (e.button !== 0) return;
|
|
8708
|
+
const selected = selectedElRef.current;
|
|
8709
|
+
if (!selected) return;
|
|
8710
|
+
armFooterPressDrag();
|
|
8711
|
+
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
8712
|
+
if (hrefKey && isFooterHrefKey(hrefKey)) {
|
|
8713
|
+
footerPointerDragRef.current = {
|
|
8714
|
+
el: selected,
|
|
8715
|
+
kind: "link",
|
|
8716
|
+
startX: e.clientX,
|
|
8717
|
+
startY: e.clientY,
|
|
8718
|
+
pointerId: e.pointerId,
|
|
8719
|
+
wasSelected: true,
|
|
8720
|
+
started: false
|
|
8721
|
+
};
|
|
8722
|
+
return;
|
|
8723
|
+
}
|
|
8724
|
+
if (selected.hasAttribute("data-ohw-footer-col") || isInferredFooterGroup(selected) && selected.closest("footer")) {
|
|
8725
|
+
footerPointerDragRef.current = {
|
|
8726
|
+
el: selected,
|
|
8727
|
+
kind: "column",
|
|
8728
|
+
startX: e.clientX,
|
|
8729
|
+
startY: e.clientY,
|
|
8730
|
+
pointerId: e.pointerId,
|
|
8731
|
+
wasSelected: true,
|
|
8732
|
+
started: false
|
|
8733
|
+
};
|
|
8734
|
+
}
|
|
8735
|
+
}, []);
|
|
8736
|
+
const handleItemChromeClick = (0, import_react9.useCallback)((clientX, clientY) => {
|
|
8737
|
+
if (suppressNextClickRef.current) {
|
|
8738
|
+
suppressNextClickRef.current = false;
|
|
8739
|
+
return;
|
|
8740
|
+
}
|
|
8741
|
+
const selected = selectedElRef.current;
|
|
8742
|
+
if (!selected || !isNavigationItem(selected)) return;
|
|
8743
|
+
const editable = selected.querySelector('[data-ohw-editable="text"]') ?? selected.querySelector("[data-ohw-editable]");
|
|
8744
|
+
if (!editable) return;
|
|
8745
|
+
activateRef.current(editable, { caretX: clientX, caretY: clientY });
|
|
8746
|
+
}, []);
|
|
8747
|
+
reselectNavigationItemRef.current = reselectNavigationItem;
|
|
8748
|
+
commitNavigationTextEditRef.current = commitNavigationTextEdit;
|
|
8749
|
+
const select = (0, import_react9.useCallback)(
|
|
8750
|
+
(anchor) => {
|
|
8751
|
+
if (!isNavigationItem(anchor)) return;
|
|
8752
|
+
if (activeElRef.current) deactivate();
|
|
8753
|
+
selectedElRef.current = anchor;
|
|
8754
|
+
clearHrefKeyHover(anchor);
|
|
8755
|
+
hoveredNavContainerRef.current = null;
|
|
8756
|
+
setHoveredNavContainerRect(null);
|
|
8757
|
+
setHoveredItemRect(null);
|
|
8758
|
+
hoveredItemElRef.current = null;
|
|
8759
|
+
siblingHintElRef.current = null;
|
|
8760
|
+
setSiblingHintRect(null);
|
|
8761
|
+
setSiblingHintRects([]);
|
|
8762
|
+
setIsItemDragging(false);
|
|
8763
|
+
const { key, disabled } = getNavigationItemReorderState(anchor);
|
|
8764
|
+
setReorderHrefKey(key);
|
|
8765
|
+
setReorderDragDisabled(disabled);
|
|
8766
|
+
setIsFooterFrameSelection(false);
|
|
8767
|
+
setToolbarVariant("link-action");
|
|
8768
|
+
setToolbarRect(anchor.getBoundingClientRect());
|
|
8769
|
+
setToolbarShowEditLink(false);
|
|
8770
|
+
setActiveCommands(/* @__PURE__ */ new Set());
|
|
8771
|
+
},
|
|
8772
|
+
[deactivate]
|
|
8773
|
+
);
|
|
8774
|
+
const selectFrame = (0, import_react9.useCallback)(
|
|
8775
|
+
(el) => {
|
|
8776
|
+
if (!isNavigationContainer(el)) return;
|
|
8777
|
+
if (activeElRef.current) deactivate();
|
|
8778
|
+
const isFooterColumn = el.hasAttribute("data-ohw-footer-col") || Boolean(el.closest("footer") && isInferredFooterGroup(el));
|
|
8779
|
+
selectedElRef.current = el;
|
|
8780
|
+
clearHrefKeyHover(el);
|
|
8781
|
+
hoveredNavContainerRef.current = null;
|
|
8782
|
+
setHoveredNavContainerRect(null);
|
|
8783
|
+
setHoveredItemRect(null);
|
|
8784
|
+
hoveredItemElRef.current = null;
|
|
8785
|
+
siblingHintElRef.current = null;
|
|
8786
|
+
setSiblingHintRect(null);
|
|
8787
|
+
setSiblingHintRects(
|
|
8788
|
+
isFooterColumn ? listFooterColumns().filter((column) => column !== el).map((column) => column.getBoundingClientRect()) : []
|
|
8789
|
+
);
|
|
8790
|
+
setIsItemDragging(false);
|
|
7902
8791
|
setReorderHrefKey(null);
|
|
7903
8792
|
setReorderDragDisabled(false);
|
|
7904
|
-
|
|
7905
|
-
|
|
7906
|
-
|
|
7907
|
-
|
|
7908
|
-
|
|
7909
|
-
|
|
7910
|
-
|
|
7911
|
-
|
|
7912
|
-
|
|
8793
|
+
setIsFooterFrameSelection(isFooterColumn);
|
|
8794
|
+
setToolbarVariant("select-frame");
|
|
8795
|
+
setToolbarRect(el.getBoundingClientRect());
|
|
8796
|
+
setToolbarShowEditLink(false);
|
|
8797
|
+
setActiveCommands(/* @__PURE__ */ new Set());
|
|
8798
|
+
},
|
|
8799
|
+
[deactivate]
|
|
8800
|
+
);
|
|
8801
|
+
const activate = (0, import_react9.useCallback)(
|
|
8802
|
+
(el, options) => {
|
|
8803
|
+
if (activeElRef.current === el) return;
|
|
8804
|
+
selectedElRef.current = null;
|
|
8805
|
+
deactivate();
|
|
8806
|
+
if (hoveredImageRef.current) {
|
|
8807
|
+
hoveredImageRef.current = null;
|
|
8808
|
+
postToParentRef.current({ type: "ow:image-unhover" });
|
|
8809
|
+
}
|
|
8810
|
+
setToolbarVariant("rich-text");
|
|
8811
|
+
siblingHintElRef.current = null;
|
|
8812
|
+
setSiblingHintRect(null);
|
|
8813
|
+
setSiblingHintRects([]);
|
|
8814
|
+
setIsItemDragging(false);
|
|
8815
|
+
el.setAttribute("contenteditable", "true");
|
|
8816
|
+
el.removeAttribute("data-ohw-hovered");
|
|
8817
|
+
el.closest("[data-ohw-href-key]")?.removeAttribute("data-ohw-hovered");
|
|
8818
|
+
activeElRef.current = el;
|
|
8819
|
+
originalContentRef.current = el.innerHTML;
|
|
8820
|
+
el.focus();
|
|
8821
|
+
if (options?.caretX !== void 0 && options?.caretY !== void 0) {
|
|
8822
|
+
placeCaretAtPoint(el, options.caretX, options.caretY);
|
|
8823
|
+
}
|
|
8824
|
+
setToolbarShowEditLink(Boolean(getHrefKeyFromElement(el)));
|
|
8825
|
+
const navAnchor = getNavigationItemAnchor(el);
|
|
8826
|
+
if (navAnchor) {
|
|
8827
|
+
setReorderHrefKey(null);
|
|
8828
|
+
setReorderDragDisabled(false);
|
|
8829
|
+
} else {
|
|
8830
|
+
const { key: reorderKey, disabled: reorderDisabled } = getReorderHandleState(el);
|
|
8831
|
+
setReorderHrefKey(reorderKey);
|
|
8832
|
+
setReorderDragDisabled(reorderDisabled);
|
|
8833
|
+
}
|
|
8834
|
+
setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
8835
|
+
postToParent2({ type: "ow:enter-edit", key: el.dataset.ohwKey });
|
|
8836
|
+
requestAnimationFrame(() => refreshActiveCommandsRef.current());
|
|
8837
|
+
},
|
|
8838
|
+
[deactivate, postToParent2]
|
|
8839
|
+
);
|
|
7913
8840
|
activateRef.current = activate;
|
|
7914
8841
|
deactivateRef.current = deactivate;
|
|
7915
8842
|
selectRef.current = select;
|
|
7916
8843
|
selectFrameRef.current = selectFrame;
|
|
7917
8844
|
deselectRef.current = deselect;
|
|
7918
|
-
(0,
|
|
8845
|
+
(0, import_react9.useLayoutEffect)(() => {
|
|
7919
8846
|
if (!subdomain || isEditMode) {
|
|
7920
8847
|
setFetchState("done");
|
|
7921
8848
|
return;
|
|
@@ -7925,6 +8852,7 @@ function OhhwellsBridge() {
|
|
|
7925
8852
|
for (const [key, val] of Object.entries(content)) {
|
|
7926
8853
|
if (key === "__ohw_sections") continue;
|
|
7927
8854
|
if (applyVideoSettingNode(key, val)) continue;
|
|
8855
|
+
if (applyCarouselNode(key, val)) continue;
|
|
7928
8856
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
7929
8857
|
if (el.dataset.ohwEditable === "image") {
|
|
7930
8858
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
@@ -7956,6 +8884,7 @@ function OhhwellsBridge() {
|
|
|
7956
8884
|
applyLinkByKey(key, val);
|
|
7957
8885
|
}
|
|
7958
8886
|
reconcileNavbarItemsFromContent(content);
|
|
8887
|
+
reconcileFooterOrderFromContent(content);
|
|
7959
8888
|
enforceLinkHrefs();
|
|
7960
8889
|
initSectionsFromContent(content, true);
|
|
7961
8890
|
sectionsLoadedRef.current = true;
|
|
@@ -7984,7 +8913,7 @@ function OhhwellsBridge() {
|
|
|
7984
8913
|
cancelled = true;
|
|
7985
8914
|
};
|
|
7986
8915
|
}, [subdomain, isEditMode]);
|
|
7987
|
-
(0,
|
|
8916
|
+
(0, import_react9.useEffect)(() => {
|
|
7988
8917
|
if (!subdomain || isEditMode) return;
|
|
7989
8918
|
let debounceTimer = null;
|
|
7990
8919
|
let observer = null;
|
|
@@ -7997,6 +8926,7 @@ function OhhwellsBridge() {
|
|
|
7997
8926
|
for (const [key, val] of Object.entries(content)) {
|
|
7998
8927
|
if (key === "__ohw_sections") continue;
|
|
7999
8928
|
if (applyVideoSettingNode(key, val)) continue;
|
|
8929
|
+
if (applyCarouselNode(key, val)) continue;
|
|
8000
8930
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
8001
8931
|
if (el.dataset.ohwEditable === "image") {
|
|
8002
8932
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
@@ -8016,6 +8946,7 @@ function OhhwellsBridge() {
|
|
|
8016
8946
|
applyLinkByKey(key, val);
|
|
8017
8947
|
}
|
|
8018
8948
|
reconcileNavbarItemsFromContent(content);
|
|
8949
|
+
reconcileFooterOrderFromContent(content);
|
|
8019
8950
|
} finally {
|
|
8020
8951
|
observer?.observe(document.body, { childList: true, subtree: true });
|
|
8021
8952
|
}
|
|
@@ -8033,16 +8964,16 @@ function OhhwellsBridge() {
|
|
|
8033
8964
|
if (debounceTimer) clearTimeout(debounceTimer);
|
|
8034
8965
|
};
|
|
8035
8966
|
}, [subdomain, isEditMode, pathname]);
|
|
8036
|
-
(0,
|
|
8967
|
+
(0, import_react9.useLayoutEffect)(() => {
|
|
8037
8968
|
const el = document.getElementById("ohw-loader");
|
|
8038
8969
|
if (!el) return;
|
|
8039
8970
|
const visible = Boolean(subdomain) && fetchState !== "done";
|
|
8040
8971
|
el.style.display = visible ? "flex" : "none";
|
|
8041
8972
|
}, [subdomain, fetchState]);
|
|
8042
|
-
(0,
|
|
8973
|
+
(0, import_react9.useEffect)(() => {
|
|
8043
8974
|
postToParent2({ type: "ow:navigation", path: pathname });
|
|
8044
8975
|
}, [pathname, postToParent2]);
|
|
8045
|
-
(0,
|
|
8976
|
+
(0, import_react9.useEffect)(() => {
|
|
8046
8977
|
if (!isEditMode) return;
|
|
8047
8978
|
if (linkPopoverSessionRef.current?.intent === "add-nav") return;
|
|
8048
8979
|
if (document.querySelector("[data-ohw-section-picker]")) return;
|
|
@@ -8050,23 +8981,50 @@ function OhhwellsBridge() {
|
|
|
8050
8981
|
deselectRef.current();
|
|
8051
8982
|
deactivateRef.current();
|
|
8052
8983
|
}, [pathname, isEditMode]);
|
|
8053
|
-
(0,
|
|
8984
|
+
(0, import_react9.useEffect)(() => {
|
|
8054
8985
|
const contentForNav = () => {
|
|
8055
8986
|
if (isEditMode) return editContentRef.current;
|
|
8056
8987
|
if (!subdomain) return {};
|
|
8057
8988
|
return contentCache.get(subdomain) ?? {};
|
|
8058
8989
|
};
|
|
8059
|
-
|
|
8990
|
+
let applying = false;
|
|
8991
|
+
let rafId = null;
|
|
8992
|
+
const run = () => {
|
|
8993
|
+
if (footerDragRef.current || applying) return;
|
|
8994
|
+
applying = true;
|
|
8995
|
+
try {
|
|
8996
|
+
const content = contentForNav();
|
|
8997
|
+
reconcileNavbarItemsFromContent(content);
|
|
8998
|
+
reconcileFooterOrderFromContent(content);
|
|
8999
|
+
document.querySelectorAll("footer [data-ohw-href-key]").forEach((el) => {
|
|
9000
|
+
if (isFooterHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
9001
|
+
disableNativeHrefDrag(el);
|
|
9002
|
+
}
|
|
9003
|
+
});
|
|
9004
|
+
} finally {
|
|
9005
|
+
applying = false;
|
|
9006
|
+
}
|
|
9007
|
+
};
|
|
9008
|
+
const scheduleRun = () => {
|
|
9009
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
9010
|
+
rafId = requestAnimationFrame(() => {
|
|
9011
|
+
rafId = null;
|
|
9012
|
+
run();
|
|
9013
|
+
});
|
|
9014
|
+
};
|
|
8060
9015
|
run();
|
|
8061
9016
|
const nav = document.querySelector("nav");
|
|
8062
|
-
|
|
8063
|
-
const observer = new MutationObserver(
|
|
8064
|
-
|
|
8065
|
-
});
|
|
8066
|
-
|
|
8067
|
-
return () =>
|
|
9017
|
+
const footer = document.querySelector("footer");
|
|
9018
|
+
const observer = new MutationObserver(scheduleRun);
|
|
9019
|
+
if (nav) observer.observe(nav, { childList: true, subtree: true });
|
|
9020
|
+
if (footer) observer.observe(footer, { childList: true, subtree: true });
|
|
9021
|
+
if (!nav && !footer) return;
|
|
9022
|
+
return () => {
|
|
9023
|
+
observer.disconnect();
|
|
9024
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
9025
|
+
};
|
|
8068
9026
|
}, [isEditMode, pathname, subdomain, fetchState]);
|
|
8069
|
-
(0,
|
|
9027
|
+
(0, import_react9.useEffect)(() => {
|
|
8070
9028
|
if (!isEditMode) return;
|
|
8071
9029
|
const measure = () => {
|
|
8072
9030
|
const h = document.body.scrollHeight;
|
|
@@ -8090,7 +9048,7 @@ function OhhwellsBridge() {
|
|
|
8090
9048
|
window.removeEventListener("resize", handleResize);
|
|
8091
9049
|
};
|
|
8092
9050
|
}, [pathname, isEditMode, postToParent2]);
|
|
8093
|
-
(0,
|
|
9051
|
+
(0, import_react9.useEffect)(() => {
|
|
8094
9052
|
if (!subdomainFromQuery || isEditMode) return;
|
|
8095
9053
|
const handleClick = (e) => {
|
|
8096
9054
|
const anchor = e.target.closest("a");
|
|
@@ -8106,7 +9064,7 @@ function OhhwellsBridge() {
|
|
|
8106
9064
|
document.addEventListener("click", handleClick, true);
|
|
8107
9065
|
return () => document.removeEventListener("click", handleClick, true);
|
|
8108
9066
|
}, [subdomainFromQuery, isEditMode, router]);
|
|
8109
|
-
(0,
|
|
9067
|
+
(0, import_react9.useEffect)(() => {
|
|
8110
9068
|
if (!isEditMode) {
|
|
8111
9069
|
editStylesRef.current?.base.remove();
|
|
8112
9070
|
editStylesRef.current?.forceHover.remove();
|
|
@@ -8129,6 +9087,32 @@ function OhhwellsBridge() {
|
|
|
8129
9087
|
[data-ohw-editable] {
|
|
8130
9088
|
display: block;
|
|
8131
9089
|
}
|
|
9090
|
+
/* Native <a> drag steals clicks \u2014 disable for edit links; reorder via press-to-drag / handle. */
|
|
9091
|
+
footer [data-ohw-href-key] {
|
|
9092
|
+
-webkit-user-drag: none !important;
|
|
9093
|
+
}
|
|
9094
|
+
footer [data-ohw-footer-col]:hover {
|
|
9095
|
+
outline: 1.5px dashed ${PRIMARY2} !important;
|
|
9096
|
+
outline-offset: 6px;
|
|
9097
|
+
border-radius: 8px;
|
|
9098
|
+
}
|
|
9099
|
+
html[data-ohw-link-popover-open] footer [data-ohw-footer-col]:hover {
|
|
9100
|
+
outline: none !important;
|
|
9101
|
+
}
|
|
9102
|
+
html[data-ohw-footer-press-drag] footer,
|
|
9103
|
+
html[data-ohw-footer-press-drag] footer * {
|
|
9104
|
+
user-select: none !important;
|
|
9105
|
+
-webkit-user-select: none !important;
|
|
9106
|
+
}
|
|
9107
|
+
html[data-ohw-item-dragging] footer,
|
|
9108
|
+
html[data-ohw-item-dragging] footer * {
|
|
9109
|
+
user-select: none !important;
|
|
9110
|
+
-webkit-user-select: none !important;
|
|
9111
|
+
pointer-events: none !important;
|
|
9112
|
+
}
|
|
9113
|
+
html[data-ohw-item-dragging] {
|
|
9114
|
+
cursor: grabbing !important;
|
|
9115
|
+
}
|
|
8132
9116
|
[data-ohw-editable]:not([contenteditable]):not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]):not([data-ohw-editable="video"]) { cursor: text !important; }
|
|
8133
9117
|
[data-ohw-editable="image"], [data-ohw-editable="image"] *,
|
|
8134
9118
|
[data-ohw-editable="video"], [data-ohw-editable="video"] *,
|
|
@@ -8173,12 +9157,39 @@ function OhhwellsBridge() {
|
|
|
8173
9157
|
}
|
|
8174
9158
|
refreshStateRules();
|
|
8175
9159
|
const handleClick = (e) => {
|
|
9160
|
+
if (suppressNextClickRef.current) {
|
|
9161
|
+
suppressNextClickRef.current = false;
|
|
9162
|
+
e.preventDefault();
|
|
9163
|
+
e.stopPropagation();
|
|
9164
|
+
return;
|
|
9165
|
+
}
|
|
8176
9166
|
const target = e.target;
|
|
8177
9167
|
if (target.closest("[data-ohw-toolbar]")) return;
|
|
8178
9168
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
8179
9169
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
8180
9170
|
if (isInsideLinkEditor(target)) return;
|
|
8181
9171
|
if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
9172
|
+
if (target.closest("[data-ohw-item-drag-surface]")) {
|
|
9173
|
+
e.preventDefault();
|
|
9174
|
+
e.stopPropagation();
|
|
9175
|
+
const selected = selectedElRef.current;
|
|
9176
|
+
if (selected && isNavigationItem(selected)) {
|
|
9177
|
+
const editable2 = selected.querySelector('[data-ohw-editable="text"]') ?? selected.querySelector("[data-ohw-editable]");
|
|
9178
|
+
if (editable2) {
|
|
9179
|
+
activateRef.current(editable2, {
|
|
9180
|
+
caretX: e.clientX,
|
|
9181
|
+
caretY: e.clientY
|
|
9182
|
+
});
|
|
9183
|
+
}
|
|
9184
|
+
} else if (selected?.hasAttribute("data-ohw-footer-col")) {
|
|
9185
|
+
const link = listFooterLinksInColumn(selected).find((el) => {
|
|
9186
|
+
const r2 = el.getBoundingClientRect();
|
|
9187
|
+
return e.clientX >= r2.left && e.clientX <= r2.right && e.clientY >= r2.top && e.clientY <= r2.bottom;
|
|
9188
|
+
});
|
|
9189
|
+
if (link) selectRef.current(link);
|
|
9190
|
+
}
|
|
9191
|
+
return;
|
|
9192
|
+
}
|
|
8182
9193
|
const navFromChrome = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
|
|
8183
9194
|
if (navFromChrome) {
|
|
8184
9195
|
e.preventDefault();
|
|
@@ -8208,7 +9219,15 @@ function OhhwellsBridge() {
|
|
|
8208
9219
|
if (isMediaEditable(editable)) {
|
|
8209
9220
|
e.preventDefault();
|
|
8210
9221
|
e.stopPropagation();
|
|
8211
|
-
|
|
9222
|
+
const key = editable.dataset.ohwKey ?? "";
|
|
9223
|
+
const r2 = editable.getBoundingClientRect();
|
|
9224
|
+
if (key && r2.width > 1 && r2.height > 1) {
|
|
9225
|
+
pendingUploadRectRef.current = {
|
|
9226
|
+
key,
|
|
9227
|
+
rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height }
|
|
9228
|
+
};
|
|
9229
|
+
}
|
|
9230
|
+
postToParentRef.current({ type: "ow:image-pick", key, elementType: editable.dataset.ohwEditable ?? "image" });
|
|
8212
9231
|
return;
|
|
8213
9232
|
}
|
|
8214
9233
|
const hrefCtx = getHrefKeyFromElement(editable);
|
|
@@ -8217,6 +9236,7 @@ function OhhwellsBridge() {
|
|
|
8217
9236
|
e.preventDefault();
|
|
8218
9237
|
e.stopPropagation();
|
|
8219
9238
|
if (selectedElRef.current === navAnchor) {
|
|
9239
|
+
if (e.detail >= 2) return;
|
|
8220
9240
|
activateRef.current(editable, { caretX: e.clientX, caretY: e.clientY });
|
|
8221
9241
|
return;
|
|
8222
9242
|
}
|
|
@@ -8232,10 +9252,26 @@ function OhhwellsBridge() {
|
|
|
8232
9252
|
if (hrefAnchor) {
|
|
8233
9253
|
e.preventDefault();
|
|
8234
9254
|
e.stopPropagation();
|
|
8235
|
-
if (selectedElRef.current === hrefAnchor)
|
|
9255
|
+
if (selectedElRef.current === hrefAnchor) {
|
|
9256
|
+
const textEditable = hrefAnchor.querySelector('[data-ohw-editable="text"]') ?? hrefAnchor.querySelector("[data-ohw-editable]");
|
|
9257
|
+
if (textEditable) {
|
|
9258
|
+
activateRef.current(textEditable, {
|
|
9259
|
+
caretX: e.clientX,
|
|
9260
|
+
caretY: e.clientY
|
|
9261
|
+
});
|
|
9262
|
+
}
|
|
9263
|
+
return;
|
|
9264
|
+
}
|
|
8236
9265
|
selectRef.current(hrefAnchor);
|
|
8237
9266
|
return;
|
|
8238
9267
|
}
|
|
9268
|
+
const footerColClick = target.closest("[data-ohw-footer-col]");
|
|
9269
|
+
if (footerColClick) {
|
|
9270
|
+
e.preventDefault();
|
|
9271
|
+
e.stopPropagation();
|
|
9272
|
+
selectFrameRef.current(footerColClick);
|
|
9273
|
+
return;
|
|
9274
|
+
}
|
|
8239
9275
|
const navContainerToSelect = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
|
|
8240
9276
|
if (navContainerToSelect) {
|
|
8241
9277
|
e.preventDefault();
|
|
@@ -8277,9 +9313,38 @@ function OhhwellsBridge() {
|
|
|
8277
9313
|
deselectRef.current();
|
|
8278
9314
|
deactivateRef.current();
|
|
8279
9315
|
};
|
|
9316
|
+
const handleDblClick = (e) => {
|
|
9317
|
+
const target = e.target;
|
|
9318
|
+
if (target.closest("[data-ohw-toolbar]")) return;
|
|
9319
|
+
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
9320
|
+
if (target.closest("[data-ohw-max-badge]")) return;
|
|
9321
|
+
if (isInsideLinkEditor(target)) return;
|
|
9322
|
+
if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
9323
|
+
return;
|
|
9324
|
+
}
|
|
9325
|
+
const navLabel = getNavigationLabelEditable(target);
|
|
9326
|
+
if (!navLabel) return;
|
|
9327
|
+
const { editable } = navLabel;
|
|
9328
|
+
e.preventDefault();
|
|
9329
|
+
e.stopPropagation();
|
|
9330
|
+
if (activeElRef.current !== editable) {
|
|
9331
|
+
activateRef.current(editable);
|
|
9332
|
+
}
|
|
9333
|
+
requestAnimationFrame(() => {
|
|
9334
|
+
selectAllTextInEditable(editable);
|
|
9335
|
+
refreshActiveCommandsRef.current();
|
|
9336
|
+
});
|
|
9337
|
+
};
|
|
8280
9338
|
const handleMouseOver = (e) => {
|
|
8281
9339
|
if (document.documentElement.hasAttribute("data-ohw-section-picking")) return;
|
|
8282
9340
|
const target = e.target;
|
|
9341
|
+
if (linkPopoverOpenRef.current) {
|
|
9342
|
+
hoveredItemElRef.current = null;
|
|
9343
|
+
setHoveredItemRect(null);
|
|
9344
|
+
hoveredNavContainerRef.current = null;
|
|
9345
|
+
setHoveredNavContainerRect(null);
|
|
9346
|
+
return;
|
|
9347
|
+
}
|
|
8283
9348
|
if (toolbarVariantRef.current !== "select-frame") {
|
|
8284
9349
|
const navContainer = target.closest("[data-ohw-nav-container]");
|
|
8285
9350
|
if (navContainer && !getNavigationItemAnchor(target)) {
|
|
@@ -8294,6 +9359,15 @@ function OhhwellsBridge() {
|
|
|
8294
9359
|
setHoveredNavContainerRect(null);
|
|
8295
9360
|
}
|
|
8296
9361
|
}
|
|
9362
|
+
const footerCol = target.closest("[data-ohw-footer-col]");
|
|
9363
|
+
if (footerCol) {
|
|
9364
|
+
hoveredNavContainerRef.current = null;
|
|
9365
|
+
setHoveredNavContainerRect(null);
|
|
9366
|
+
if (selectedElRef.current === footerCol) return;
|
|
9367
|
+
hoveredItemElRef.current = footerCol;
|
|
9368
|
+
setHoveredItemRect(footerCol.getBoundingClientRect());
|
|
9369
|
+
return;
|
|
9370
|
+
}
|
|
8297
9371
|
const navAnchor = getNavigationItemAnchor(target);
|
|
8298
9372
|
if (navAnchor) {
|
|
8299
9373
|
hoveredNavContainerRef.current = null;
|
|
@@ -8330,6 +9404,15 @@ function OhhwellsBridge() {
|
|
|
8330
9404
|
hoveredNavContainerRef.current = null;
|
|
8331
9405
|
setHoveredNavContainerRect(null);
|
|
8332
9406
|
}
|
|
9407
|
+
const footerCol = target.closest("[data-ohw-footer-col]");
|
|
9408
|
+
if (footerCol && hoveredItemElRef.current === footerCol) {
|
|
9409
|
+
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
9410
|
+
if (related2?.closest("[data-ohw-drag-handle-container], [data-ohw-item-interaction]")) return;
|
|
9411
|
+
if (related2?.closest("[data-ohw-footer-col]") === footerCol) return;
|
|
9412
|
+
hoveredItemElRef.current = null;
|
|
9413
|
+
setHoveredItemRect(null);
|
|
9414
|
+
return;
|
|
9415
|
+
}
|
|
8333
9416
|
const navAnchor = getNavigationItemAnchor(target);
|
|
8334
9417
|
if (navAnchor) {
|
|
8335
9418
|
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
@@ -8441,12 +9524,12 @@ function OhhwellsBridge() {
|
|
|
8441
9524
|
const stickyPad = 48;
|
|
8442
9525
|
const withinPad = x >= pr.left - stickyPad && x <= pr.left + pr.width + stickyPad && y >= pr.top - stickyPad && y <= pr.top + pr.height + stickyPad;
|
|
8443
9526
|
if (withinPad) {
|
|
8444
|
-
|
|
9527
|
+
const yieldToSmaller = smallest !== pinned && candidatePool.includes(smallest) && (() => {
|
|
8445
9528
|
const sr = getVisibleRect(smallest);
|
|
8446
|
-
const
|
|
8447
|
-
|
|
8448
|
-
}
|
|
8449
|
-
return pinned;
|
|
9529
|
+
const pr2 = getVisibleRect(pinned);
|
|
9530
|
+
return sr.width * sr.height < pr2.width * pr2.height;
|
|
9531
|
+
})();
|
|
9532
|
+
if (!yieldToSmaller) return pinned;
|
|
8450
9533
|
}
|
|
8451
9534
|
}
|
|
8452
9535
|
return smallest;
|
|
@@ -8458,6 +9541,7 @@ function OhhwellsBridge() {
|
|
|
8458
9541
|
resumeAnimTracks();
|
|
8459
9542
|
postToParentRef.current({ type: "ow:image-unhover" });
|
|
8460
9543
|
}
|
|
9544
|
+
clearImageHover();
|
|
8461
9545
|
};
|
|
8462
9546
|
const probeNavigationHoverAt = (x, y) => {
|
|
8463
9547
|
if (toolbarVariantRef.current === "select-frame") {
|
|
@@ -8560,7 +9644,7 @@ function OhhwellsBridge() {
|
|
|
8560
9644
|
return;
|
|
8561
9645
|
}
|
|
8562
9646
|
const topEl = document.elementFromPoint(x2, y2);
|
|
8563
|
-
if (topEl?.closest('[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
9647
|
+
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]')) {
|
|
8564
9648
|
if (hoveredImageRef.current) {
|
|
8565
9649
|
hoveredImageRef.current = null;
|
|
8566
9650
|
resumeAnimTracks();
|
|
@@ -8767,6 +9851,14 @@ function OhhwellsBridge() {
|
|
|
8767
9851
|
probeHoverCardsAt(clientX, clientY);
|
|
8768
9852
|
};
|
|
8769
9853
|
const handleDragOver = (e) => {
|
|
9854
|
+
const footerSession = footerDragRef.current;
|
|
9855
|
+
if (footerSession) {
|
|
9856
|
+
e.preventDefault();
|
|
9857
|
+
if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
|
|
9858
|
+
const slot = footerSession.kind === "link" && footerSession.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, footerSession.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
|
|
9859
|
+
refreshFooterDragVisualsRef.current(footerSession, slot, e.clientX, e.clientY);
|
|
9860
|
+
return;
|
|
9861
|
+
}
|
|
8770
9862
|
e.preventDefault();
|
|
8771
9863
|
const el = findImageAtPoint(e.clientX, e.clientY, false);
|
|
8772
9864
|
if (!el) {
|
|
@@ -8835,6 +9927,7 @@ function OhhwellsBridge() {
|
|
|
8835
9927
|
if (!entry || entry.fadingOut) return prev;
|
|
8836
9928
|
return { ...prev, [key]: { ...entry, fadingOut: true } };
|
|
8837
9929
|
});
|
|
9930
|
+
if (pendingUploadRectRef.current?.key === key) pendingUploadRectRef.current = null;
|
|
8838
9931
|
};
|
|
8839
9932
|
let found = false;
|
|
8840
9933
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -8949,6 +10042,7 @@ function OhhwellsBridge() {
|
|
|
8949
10042
|
continue;
|
|
8950
10043
|
}
|
|
8951
10044
|
if (applyVideoSettingNode(key, val)) continue;
|
|
10045
|
+
if (applyCarouselNode(key, val)) continue;
|
|
8952
10046
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
8953
10047
|
if (el.dataset.ohwEditable === "image") {
|
|
8954
10048
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
@@ -8973,6 +10067,7 @@ function OhhwellsBridge() {
|
|
|
8973
10067
|
}
|
|
8974
10068
|
editContentRef.current = { ...editContentRef.current, ...content };
|
|
8975
10069
|
reconcileNavbarItemsFromContent(editContentRef.current);
|
|
10070
|
+
reconcileFooterOrderFromContent(editContentRef.current);
|
|
8976
10071
|
enforceLinkHrefs();
|
|
8977
10072
|
postToParentRef.current({ type: "ow:hydrate-done" });
|
|
8978
10073
|
};
|
|
@@ -8998,6 +10093,15 @@ function OhhwellsBridge() {
|
|
|
8998
10093
|
window.addEventListener("message", handleUiEscape);
|
|
8999
10094
|
const handleKeyDown = (e) => {
|
|
9000
10095
|
if (e.key === "Escape" && document.querySelector("[data-ohw-section-picker]")) return;
|
|
10096
|
+
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "a" && activeElRef.current) {
|
|
10097
|
+
const navAnchor = getNavigationItemAnchor(activeElRef.current);
|
|
10098
|
+
if (navAnchor) {
|
|
10099
|
+
e.preventDefault();
|
|
10100
|
+
selectAllTextInEditable(activeElRef.current);
|
|
10101
|
+
refreshActiveCommandsRef.current();
|
|
10102
|
+
return;
|
|
10103
|
+
}
|
|
10104
|
+
}
|
|
9001
10105
|
if (e.key === "Escape" && linkPopoverOpenRef.current) {
|
|
9002
10106
|
setLinkPopoverRef.current(null);
|
|
9003
10107
|
return;
|
|
@@ -9077,6 +10181,17 @@ function OhhwellsBridge() {
|
|
|
9077
10181
|
if (siblingHintElRef.current) {
|
|
9078
10182
|
setSiblingHintRect(siblingHintElRef.current.getBoundingClientRect());
|
|
9079
10183
|
}
|
|
10184
|
+
const selected = selectedElRef.current;
|
|
10185
|
+
if (selected && !footerDragRef.current && (selected.hasAttribute("data-ohw-footer-col") || Boolean(selected.closest("footer") && isInferredFooterGroup(selected)))) {
|
|
10186
|
+
setSiblingHintRects(
|
|
10187
|
+
listFooterColumns().filter((column) => column !== selected).map((column) => column.getBoundingClientRect())
|
|
10188
|
+
);
|
|
10189
|
+
}
|
|
10190
|
+
if (footerDragRef.current) {
|
|
10191
|
+
const session = footerDragRef.current;
|
|
10192
|
+
const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
|
|
10193
|
+
refreshFooterDragVisualsRef.current(session, slot, session.lastClientX, session.lastClientY);
|
|
10194
|
+
}
|
|
9080
10195
|
if (hoveredImageRef.current) {
|
|
9081
10196
|
const el = hoveredImageRef.current;
|
|
9082
10197
|
const r2 = el.getBoundingClientRect();
|
|
@@ -9087,7 +10202,7 @@ function OhhwellsBridge() {
|
|
|
9087
10202
|
};
|
|
9088
10203
|
const handleSave = (e) => {
|
|
9089
10204
|
if (e.data?.type !== "ow:save") return;
|
|
9090
|
-
const nodes = collectEditableNodes();
|
|
10205
|
+
const nodes = collectEditableNodes(editContentRef.current);
|
|
9091
10206
|
const tracker = document.querySelector("[data-ohw-sections-tracker]");
|
|
9092
10207
|
if (tracker?.textContent) nodes.push({ key: "__ohw_sections", type: "sections", text: tracker.textContent });
|
|
9093
10208
|
postToParentRef.current({ type: "ow:save-result", nodes });
|
|
@@ -9172,28 +10287,49 @@ function OhhwellsBridge() {
|
|
|
9172
10287
|
const handleDocMouseLeave = () => {
|
|
9173
10288
|
hoveredImageRef.current = null;
|
|
9174
10289
|
setMediaHover(null);
|
|
10290
|
+
setCarouselHover(null);
|
|
9175
10291
|
document.querySelectorAll("[data-ohw-state-hovered]").forEach((el) => el.removeAttribute("data-ohw-state-hovered"));
|
|
9176
10292
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
9177
10293
|
activeStateElRef.current = null;
|
|
9178
10294
|
setToggleState(null);
|
|
9179
10295
|
};
|
|
10296
|
+
const resolveUploadRects = (key) => {
|
|
10297
|
+
const matches = Array.from(document.querySelectorAll(`[data-ohw-key="${key}"]`));
|
|
10298
|
+
const rects = matches.map((el) => {
|
|
10299
|
+
const r2 = el.getBoundingClientRect();
|
|
10300
|
+
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
10301
|
+
}).filter((r2) => r2.width > 1 && r2.height > 1);
|
|
10302
|
+
if (rects.length > 0) return rects;
|
|
10303
|
+
const pending = pendingUploadRectRef.current;
|
|
10304
|
+
if (pending?.key === key && pending.rect.width > 1 && pending.rect.height > 1) {
|
|
10305
|
+
return [pending.rect];
|
|
10306
|
+
}
|
|
10307
|
+
const hovered = hoveredImageRef.current;
|
|
10308
|
+
if (hovered?.dataset.ohwKey === key) {
|
|
10309
|
+
const r2 = hovered.getBoundingClientRect();
|
|
10310
|
+
if (r2.width > 1 && r2.height > 1) {
|
|
10311
|
+
return [{ top: r2.top, left: r2.left, width: r2.width, height: r2.height }];
|
|
10312
|
+
}
|
|
10313
|
+
}
|
|
10314
|
+
return [];
|
|
10315
|
+
};
|
|
9180
10316
|
const handleImageUploading = (e) => {
|
|
9181
|
-
|
|
9182
|
-
|
|
10317
|
+
const type = e.data?.type;
|
|
10318
|
+
if (type !== "ow:image-uploading" && type !== "ow:anim-lock") return;
|
|
10319
|
+
const key = e.data.key;
|
|
10320
|
+
if (!key) return;
|
|
10321
|
+
const uploading = type === "ow:anim-lock" ? true : !!e.data.uploading;
|
|
9183
10322
|
setUploadingRects((prev) => {
|
|
9184
10323
|
if (!uploading) {
|
|
10324
|
+
if (pendingUploadRectRef.current?.key === key) pendingUploadRectRef.current = null;
|
|
9185
10325
|
if (!(key in prev)) return prev;
|
|
9186
10326
|
const next = { ...prev };
|
|
9187
10327
|
delete next[key];
|
|
9188
10328
|
return next;
|
|
9189
10329
|
}
|
|
9190
|
-
const
|
|
9191
|
-
if (
|
|
9192
|
-
|
|
9193
|
-
return {
|
|
9194
|
-
...prev,
|
|
9195
|
-
[key]: { rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height } }
|
|
9196
|
-
};
|
|
10330
|
+
const rects = resolveUploadRects(key);
|
|
10331
|
+
if (rects.length === 0) return prev;
|
|
10332
|
+
return { ...prev, [key]: { rects } };
|
|
9197
10333
|
});
|
|
9198
10334
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
9199
10335
|
const track = el.closest("[data-ohw-hover-pause]");
|
|
@@ -9211,6 +10347,48 @@ function OhhwellsBridge() {
|
|
|
9211
10347
|
if (e.data?.type !== "ow:canvas-height" || typeof e.data.height !== "number") return;
|
|
9212
10348
|
document.documentElement.style.setProperty("--ohw-canvas-h", `${e.data.height}px`);
|
|
9213
10349
|
};
|
|
10350
|
+
const handleCarouselChange = (e) => {
|
|
10351
|
+
if (e.data?.type !== "ow:carousel-change") return;
|
|
10352
|
+
const { key, images } = e.data;
|
|
10353
|
+
if (!key || !Array.isArray(images)) return;
|
|
10354
|
+
const text = JSON.stringify(images);
|
|
10355
|
+
applyCarouselValue(key, images);
|
|
10356
|
+
editContentRef.current = { ...editContentRef.current, [key]: text };
|
|
10357
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key, text }] });
|
|
10358
|
+
setCarouselHover(null);
|
|
10359
|
+
};
|
|
10360
|
+
const findCarouselAtPoint = (clientX, clientY) => {
|
|
10361
|
+
const containers = Array.from(document.querySelectorAll(`[${CAROUSEL_ATTR}]`));
|
|
10362
|
+
for (let i = containers.length - 1; i >= 0; i--) {
|
|
10363
|
+
const r2 = containers[i].getBoundingClientRect();
|
|
10364
|
+
if (clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom) {
|
|
10365
|
+
return containers[i];
|
|
10366
|
+
}
|
|
10367
|
+
}
|
|
10368
|
+
return null;
|
|
10369
|
+
};
|
|
10370
|
+
const isPointOverEditable = (scope, clientX, clientY) => {
|
|
10371
|
+
const editables = scope.querySelectorAll("[data-ohw-editable], [data-ohw-href-key]");
|
|
10372
|
+
for (const el of editables) {
|
|
10373
|
+
const r2 = el.getBoundingClientRect();
|
|
10374
|
+
if (clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom) return true;
|
|
10375
|
+
}
|
|
10376
|
+
return false;
|
|
10377
|
+
};
|
|
10378
|
+
const handleCarouselHover = (e) => {
|
|
10379
|
+
const container = findCarouselAtPoint(e.clientX, e.clientY);
|
|
10380
|
+
const scope = container?.closest("[data-ohw-section]") ?? container?.parentElement ?? null;
|
|
10381
|
+
if (!container || !scope || isPointOverEditable(scope, e.clientX, e.clientY)) {
|
|
10382
|
+
setCarouselHover((prev) => prev ? null : prev);
|
|
10383
|
+
return;
|
|
10384
|
+
}
|
|
10385
|
+
const key = container.getAttribute("data-ohw-key") ?? "";
|
|
10386
|
+
if (!key) return;
|
|
10387
|
+
const r2 = getVisibleRect(container);
|
|
10388
|
+
setCarouselHover(
|
|
10389
|
+
(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 } }
|
|
10390
|
+
);
|
|
10391
|
+
};
|
|
9214
10392
|
const applyToolbarPos = (rect) => {
|
|
9215
10393
|
const ps = parentScrollRef.current;
|
|
9216
10394
|
const approxW = 330;
|
|
@@ -9319,6 +10497,7 @@ function OhhwellsBridge() {
|
|
|
9319
10497
|
window.addEventListener("message", handleRemoveSchedulingSection);
|
|
9320
10498
|
window.addEventListener("message", handleImageUrl);
|
|
9321
10499
|
window.addEventListener("message", handleImageUploading);
|
|
10500
|
+
window.addEventListener("message", handleCarouselChange);
|
|
9322
10501
|
window.addEventListener("message", handleCanvasHeight);
|
|
9323
10502
|
window.addEventListener("message", handleParentScroll);
|
|
9324
10503
|
window.addEventListener("message", handlePointerSync);
|
|
@@ -9330,11 +10509,13 @@ function OhhwellsBridge() {
|
|
|
9330
10509
|
};
|
|
9331
10510
|
window.addEventListener("resize", handleViewportResize, { passive: true });
|
|
9332
10511
|
document.addEventListener("click", handleClick, true);
|
|
10512
|
+
document.addEventListener("dblclick", handleDblClick, true);
|
|
9333
10513
|
document.addEventListener("paste", handlePaste, true);
|
|
9334
10514
|
document.addEventListener("input", handleInput, true);
|
|
9335
10515
|
document.addEventListener("mouseover", handleMouseOver, true);
|
|
9336
10516
|
document.addEventListener("mouseout", handleMouseOut, true);
|
|
9337
10517
|
document.addEventListener("mousemove", handleMouseMove, true);
|
|
10518
|
+
document.addEventListener("mousemove", handleCarouselHover, true);
|
|
9338
10519
|
document.addEventListener("mouseleave", handleDocMouseLeave);
|
|
9339
10520
|
document.addEventListener("dragover", handleDragOver, true);
|
|
9340
10521
|
document.addEventListener("dragleave", handleDragLeave, true);
|
|
@@ -9344,11 +10525,13 @@ function OhhwellsBridge() {
|
|
|
9344
10525
|
window.addEventListener("scroll", handleScroll, true);
|
|
9345
10526
|
return () => {
|
|
9346
10527
|
document.removeEventListener("click", handleClick, true);
|
|
10528
|
+
document.removeEventListener("dblclick", handleDblClick, true);
|
|
9347
10529
|
document.removeEventListener("paste", handlePaste, true);
|
|
9348
10530
|
document.removeEventListener("input", handleInput, true);
|
|
9349
10531
|
document.removeEventListener("mouseover", handleMouseOver, true);
|
|
9350
10532
|
document.removeEventListener("mouseout", handleMouseOut, true);
|
|
9351
10533
|
document.removeEventListener("mousemove", handleMouseMove, true);
|
|
10534
|
+
document.removeEventListener("mousemove", handleCarouselHover, true);
|
|
9352
10535
|
document.removeEventListener("mouseleave", handleDocMouseLeave);
|
|
9353
10536
|
document.removeEventListener("dragover", handleDragOver, true);
|
|
9354
10537
|
document.removeEventListener("dragleave", handleDragLeave, true);
|
|
@@ -9364,6 +10547,7 @@ function OhhwellsBridge() {
|
|
|
9364
10547
|
window.removeEventListener("message", handleRemoveSchedulingSection);
|
|
9365
10548
|
window.removeEventListener("message", handleImageUrl);
|
|
9366
10549
|
window.removeEventListener("message", handleImageUploading);
|
|
10550
|
+
window.removeEventListener("message", handleCarouselChange);
|
|
9367
10551
|
window.removeEventListener("message", handleCanvasHeight);
|
|
9368
10552
|
window.removeEventListener("message", handleParentScroll);
|
|
9369
10553
|
window.removeEventListener("resize", handleViewportResize);
|
|
@@ -9378,7 +10562,158 @@ function OhhwellsBridge() {
|
|
|
9378
10562
|
if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
|
|
9379
10563
|
};
|
|
9380
10564
|
}, [isEditMode, refreshStateRules]);
|
|
9381
|
-
(0,
|
|
10565
|
+
(0, import_react9.useEffect)(() => {
|
|
10566
|
+
if (!isEditMode) return;
|
|
10567
|
+
const THRESHOLD = 10;
|
|
10568
|
+
const resolveWasSelected = (el) => {
|
|
10569
|
+
if (selectedElRef.current === el) return true;
|
|
10570
|
+
const activeAnchor = activeElRef.current ? getNavigationItemAnchor(activeElRef.current) : null;
|
|
10571
|
+
return activeAnchor === el;
|
|
10572
|
+
};
|
|
10573
|
+
const onPointerDown = (e) => {
|
|
10574
|
+
if (e.button !== 0) return;
|
|
10575
|
+
if (suppressNextClickRef.current && !footerDragRef.current && !footerPointerDragRef.current?.started) {
|
|
10576
|
+
suppressNextClickRef.current = false;
|
|
10577
|
+
}
|
|
10578
|
+
if (footerDragRef.current) return;
|
|
10579
|
+
const target = e.target;
|
|
10580
|
+
if (!target) return;
|
|
10581
|
+
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]')) {
|
|
10582
|
+
return;
|
|
10583
|
+
}
|
|
10584
|
+
if (target.closest("[data-ohw-item-drag-surface]")) return;
|
|
10585
|
+
const anchor = getNavigationItemAnchor(target);
|
|
10586
|
+
const hrefKey = anchor?.getAttribute("data-ohw-href-key") ?? null;
|
|
10587
|
+
if (anchor && isFooterHrefKey(hrefKey)) {
|
|
10588
|
+
armFooterPressDrag();
|
|
10589
|
+
footerPointerDragRef.current = {
|
|
10590
|
+
el: anchor,
|
|
10591
|
+
kind: "link",
|
|
10592
|
+
startX: e.clientX,
|
|
10593
|
+
startY: e.clientY,
|
|
10594
|
+
pointerId: e.pointerId,
|
|
10595
|
+
wasSelected: resolveWasSelected(anchor),
|
|
10596
|
+
started: false
|
|
10597
|
+
};
|
|
10598
|
+
return;
|
|
10599
|
+
}
|
|
10600
|
+
const col = target.closest("[data-ohw-footer-col]");
|
|
10601
|
+
if (col && !getNavigationItemAnchor(target)) {
|
|
10602
|
+
armFooterPressDrag();
|
|
10603
|
+
footerPointerDragRef.current = {
|
|
10604
|
+
el: col,
|
|
10605
|
+
kind: "column",
|
|
10606
|
+
startX: e.clientX,
|
|
10607
|
+
startY: e.clientY,
|
|
10608
|
+
pointerId: e.pointerId,
|
|
10609
|
+
wasSelected: resolveWasSelected(col),
|
|
10610
|
+
started: false
|
|
10611
|
+
};
|
|
10612
|
+
}
|
|
10613
|
+
};
|
|
10614
|
+
const onPointerMove = (e) => {
|
|
10615
|
+
const pending = footerPointerDragRef.current;
|
|
10616
|
+
if (!pending) return;
|
|
10617
|
+
if (pending.started) {
|
|
10618
|
+
e.preventDefault();
|
|
10619
|
+
clearTextSelection();
|
|
10620
|
+
const session = footerDragRef.current;
|
|
10621
|
+
if (!session) return;
|
|
10622
|
+
const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, session.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
|
|
10623
|
+
refreshFooterDragVisualsRef.current(session, slot, e.clientX, e.clientY);
|
|
10624
|
+
return;
|
|
10625
|
+
}
|
|
10626
|
+
const dx = e.clientX - pending.startX;
|
|
10627
|
+
const dy = e.clientY - pending.startY;
|
|
10628
|
+
if (dx * dx + dy * dy < THRESHOLD * THRESHOLD) return;
|
|
10629
|
+
e.preventDefault();
|
|
10630
|
+
pending.started = true;
|
|
10631
|
+
clearTextSelection();
|
|
10632
|
+
try {
|
|
10633
|
+
document.body.setPointerCapture(pending.pointerId);
|
|
10634
|
+
} catch {
|
|
10635
|
+
}
|
|
10636
|
+
if (linkPopoverOpenRef.current) {
|
|
10637
|
+
setLinkPopoverRef.current(null);
|
|
10638
|
+
}
|
|
10639
|
+
if (activeElRef.current) {
|
|
10640
|
+
deactivateRef.current();
|
|
10641
|
+
}
|
|
10642
|
+
if (pending.kind === "link") {
|
|
10643
|
+
const key = pending.el.getAttribute("data-ohw-href-key");
|
|
10644
|
+
if (!key) return;
|
|
10645
|
+
const column = findFooterColumnForLink(pending.el);
|
|
10646
|
+
const columns2 = listFooterColumns();
|
|
10647
|
+
beginFooterDragRef.current({
|
|
10648
|
+
kind: "link",
|
|
10649
|
+
hrefKey: key,
|
|
10650
|
+
columnEl: column,
|
|
10651
|
+
sourceColumnIndex: column ? columns2.indexOf(column) : 0,
|
|
10652
|
+
wasSelected: pending.wasSelected,
|
|
10653
|
+
draggedEl: pending.el,
|
|
10654
|
+
lastClientX: e.clientX,
|
|
10655
|
+
lastClientY: e.clientY,
|
|
10656
|
+
activeSlot: null
|
|
10657
|
+
});
|
|
10658
|
+
return;
|
|
10659
|
+
}
|
|
10660
|
+
const columns = listFooterColumns();
|
|
10661
|
+
const idx = columns.indexOf(pending.el);
|
|
10662
|
+
if (idx < 0) return;
|
|
10663
|
+
beginFooterDragRef.current({
|
|
10664
|
+
kind: "column",
|
|
10665
|
+
hrefKey: null,
|
|
10666
|
+
columnEl: pending.el,
|
|
10667
|
+
sourceColumnIndex: idx,
|
|
10668
|
+
wasSelected: pending.wasSelected,
|
|
10669
|
+
draggedEl: pending.el,
|
|
10670
|
+
lastClientX: e.clientX,
|
|
10671
|
+
lastClientY: e.clientY,
|
|
10672
|
+
activeSlot: null
|
|
10673
|
+
});
|
|
10674
|
+
};
|
|
10675
|
+
const endPointerDrag = (e) => {
|
|
10676
|
+
const pending = footerPointerDragRef.current;
|
|
10677
|
+
footerPointerDragRef.current = null;
|
|
10678
|
+
try {
|
|
10679
|
+
if (document.body.hasPointerCapture(e.pointerId)) {
|
|
10680
|
+
document.body.releasePointerCapture(e.pointerId);
|
|
10681
|
+
}
|
|
10682
|
+
} catch {
|
|
10683
|
+
}
|
|
10684
|
+
if (!pending?.started) {
|
|
10685
|
+
unlockFooterDragInteraction();
|
|
10686
|
+
return;
|
|
10687
|
+
}
|
|
10688
|
+
suppressNextClickRef.current = true;
|
|
10689
|
+
commitFooterDragRef.current(e.clientX, e.clientY);
|
|
10690
|
+
};
|
|
10691
|
+
const blockSelectStart = (e) => {
|
|
10692
|
+
if (footerDragRef.current || footerPointerDragRef.current?.started || document.documentElement.hasAttribute("data-ohw-footer-press-drag")) {
|
|
10693
|
+
e.preventDefault();
|
|
10694
|
+
}
|
|
10695
|
+
};
|
|
10696
|
+
const onDragEnd = (_e) => {
|
|
10697
|
+
if (!footerDragRef.current) return;
|
|
10698
|
+
commitFooterDragRef.current();
|
|
10699
|
+
};
|
|
10700
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
10701
|
+
document.addEventListener("pointermove", onPointerMove, true);
|
|
10702
|
+
document.addEventListener("pointerup", endPointerDrag, true);
|
|
10703
|
+
document.addEventListener("pointercancel", endPointerDrag, true);
|
|
10704
|
+
document.addEventListener("selectstart", blockSelectStart, true);
|
|
10705
|
+
document.addEventListener("dragend", onDragEnd, true);
|
|
10706
|
+
return () => {
|
|
10707
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
10708
|
+
document.removeEventListener("pointermove", onPointerMove, true);
|
|
10709
|
+
document.removeEventListener("pointerup", endPointerDrag, true);
|
|
10710
|
+
document.removeEventListener("pointercancel", endPointerDrag, true);
|
|
10711
|
+
document.removeEventListener("selectstart", blockSelectStart, true);
|
|
10712
|
+
document.removeEventListener("dragend", onDragEnd, true);
|
|
10713
|
+
unlockFooterDragInteraction();
|
|
10714
|
+
};
|
|
10715
|
+
}, [isEditMode]);
|
|
10716
|
+
(0, import_react9.useEffect)(() => {
|
|
9382
10717
|
const handler = (e) => {
|
|
9383
10718
|
if (e.data?.type !== "ow:request-schedule-config") return;
|
|
9384
10719
|
const insertAfterVal = e.data.insertAfter;
|
|
@@ -9394,7 +10729,7 @@ function OhhwellsBridge() {
|
|
|
9394
10729
|
window.addEventListener("message", handler);
|
|
9395
10730
|
return () => window.removeEventListener("message", handler);
|
|
9396
10731
|
}, [processConfigRequest]);
|
|
9397
|
-
(0,
|
|
10732
|
+
(0, import_react9.useEffect)(() => {
|
|
9398
10733
|
if (!isEditMode) return;
|
|
9399
10734
|
document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
|
|
9400
10735
|
el.removeAttribute("data-ohw-active-state");
|
|
@@ -9415,7 +10750,13 @@ function OhhwellsBridge() {
|
|
|
9415
10750
|
const next = { ...prev, [pathKey]: sections };
|
|
9416
10751
|
return shouldUseDevFixtures() ? { ...DEV_SECTIONS_BY_PATH, ...next } : next;
|
|
9417
10752
|
});
|
|
9418
|
-
postToParent2({
|
|
10753
|
+
postToParent2({
|
|
10754
|
+
type: "ow:ready",
|
|
10755
|
+
version: "1",
|
|
10756
|
+
path: pathname,
|
|
10757
|
+
nodes: collectEditableNodes(editContentRef.current),
|
|
10758
|
+
sections
|
|
10759
|
+
});
|
|
9419
10760
|
postToParent2({ type: "ow:request-site-pages" });
|
|
9420
10761
|
}, 150);
|
|
9421
10762
|
return () => {
|
|
@@ -9423,19 +10764,19 @@ function OhhwellsBridge() {
|
|
|
9423
10764
|
clearTimeout(timer);
|
|
9424
10765
|
};
|
|
9425
10766
|
}, [pathname, isEditMode, refreshStateRules, postToParent2]);
|
|
9426
|
-
(0,
|
|
10767
|
+
(0, import_react9.useEffect)(() => {
|
|
9427
10768
|
scrollToHashSectionWhenReady();
|
|
9428
10769
|
const onHashChange = () => scrollToHashSectionWhenReady();
|
|
9429
10770
|
window.addEventListener("hashchange", onHashChange);
|
|
9430
10771
|
return () => window.removeEventListener("hashchange", onHashChange);
|
|
9431
10772
|
}, [pathname]);
|
|
9432
|
-
const handleCommand = (0,
|
|
10773
|
+
const handleCommand = (0, import_react9.useCallback)((cmd) => {
|
|
9433
10774
|
document.execCommand(cmd, false);
|
|
9434
10775
|
activeElRef.current?.focus();
|
|
9435
10776
|
if (activeElRef.current) setToolbarRect(getEditMeasureEl(activeElRef.current).getBoundingClientRect());
|
|
9436
10777
|
refreshActiveCommandsRef.current();
|
|
9437
10778
|
}, []);
|
|
9438
|
-
const handleStateChange = (0,
|
|
10779
|
+
const handleStateChange = (0, import_react9.useCallback)((state) => {
|
|
9439
10780
|
if (!activeStateElRef.current) return;
|
|
9440
10781
|
const el = activeStateElRef.current;
|
|
9441
10782
|
if (state === "Default") {
|
|
@@ -9448,11 +10789,11 @@ function OhhwellsBridge() {
|
|
|
9448
10789
|
}
|
|
9449
10790
|
setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
|
|
9450
10791
|
}, [deactivate]);
|
|
9451
|
-
const closeLinkPopover = (0,
|
|
10792
|
+
const closeLinkPopover = (0, import_react9.useCallback)(() => {
|
|
9452
10793
|
addNavAfterAnchorRef.current = null;
|
|
9453
10794
|
setLinkPopover(null);
|
|
9454
10795
|
}, []);
|
|
9455
|
-
const openLinkPopoverForActive = (0,
|
|
10796
|
+
const openLinkPopoverForActive = (0, import_react9.useCallback)(() => {
|
|
9456
10797
|
const hrefCtx = getHrefKeyFromElement(activeElRef.current);
|
|
9457
10798
|
if (!hrefCtx) return;
|
|
9458
10799
|
bumpLinkPopoverGrace();
|
|
@@ -9463,7 +10804,7 @@ function OhhwellsBridge() {
|
|
|
9463
10804
|
});
|
|
9464
10805
|
deactivate();
|
|
9465
10806
|
}, [deactivate]);
|
|
9466
|
-
const openLinkPopoverForSelected = (0,
|
|
10807
|
+
const openLinkPopoverForSelected = (0, import_react9.useCallback)(() => {
|
|
9467
10808
|
const anchor = selectedElRef.current;
|
|
9468
10809
|
if (!anchor) return;
|
|
9469
10810
|
const key = anchor.getAttribute("data-ohw-href-key");
|
|
@@ -9476,7 +10817,7 @@ function OhhwellsBridge() {
|
|
|
9476
10817
|
});
|
|
9477
10818
|
deselect();
|
|
9478
10819
|
}, [deselect]);
|
|
9479
|
-
const handleLinkPopoverSubmit = (0,
|
|
10820
|
+
const handleLinkPopoverSubmit = (0, import_react9.useCallback)(
|
|
9480
10821
|
(target) => {
|
|
9481
10822
|
const session = linkPopoverSessionRef.current;
|
|
9482
10823
|
if (!session) return;
|
|
@@ -9532,16 +10873,22 @@ function OhhwellsBridge() {
|
|
|
9532
10873
|
},
|
|
9533
10874
|
[postToParent2, sitePages, sectionsByPath]
|
|
9534
10875
|
);
|
|
9535
|
-
const
|
|
9536
|
-
const currentSections = sectionsByPath[pathname] ?? [];
|
|
9537
|
-
linkPopoverOpenRef.current = linkPopover !== null;
|
|
9538
|
-
const handleMediaReplace = (0, import_react8.useCallback)(
|
|
10876
|
+
const handleMediaReplace = (0, import_react9.useCallback)(
|
|
9539
10877
|
(key) => {
|
|
10878
|
+
if (mediaHover?.key === key) {
|
|
10879
|
+
pendingUploadRectRef.current = { key, rect: mediaHover.rect };
|
|
10880
|
+
}
|
|
9540
10881
|
postToParent2({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
|
|
9541
10882
|
},
|
|
9542
|
-
[postToParent2, mediaHover
|
|
10883
|
+
[postToParent2, mediaHover]
|
|
9543
10884
|
);
|
|
9544
|
-
const
|
|
10885
|
+
const handleEditCarousel = (0, import_react9.useCallback)(
|
|
10886
|
+
(key) => {
|
|
10887
|
+
postToParent2({ type: "ow:carousel-open", key, images: readCarouselValue(key) });
|
|
10888
|
+
},
|
|
10889
|
+
[postToParent2]
|
|
10890
|
+
);
|
|
10891
|
+
const handleMediaFadeOutComplete = (0, import_react9.useCallback)((key) => {
|
|
9545
10892
|
setUploadingRects((prev) => {
|
|
9546
10893
|
if (!(key in prev)) return prev;
|
|
9547
10894
|
const next = { ...prev };
|
|
@@ -9549,7 +10896,7 @@ function OhhwellsBridge() {
|
|
|
9549
10896
|
return next;
|
|
9550
10897
|
});
|
|
9551
10898
|
}, []);
|
|
9552
|
-
const handleVideoSettingsChange = (0,
|
|
10899
|
+
const handleVideoSettingsChange = (0, import_react9.useCallback)(
|
|
9553
10900
|
(key, settings) => {
|
|
9554
10901
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
9555
10902
|
const video = getVideoEl(el);
|
|
@@ -9571,21 +10918,26 @@ function OhhwellsBridge() {
|
|
|
9571
10918
|
},
|
|
9572
10919
|
[postToParent2]
|
|
9573
10920
|
);
|
|
10921
|
+
const showEditLink = toolbarShowEditLink;
|
|
10922
|
+
const currentSections = sectionsByPath[pathname] ?? [];
|
|
10923
|
+
linkPopoverOpenRef.current = linkPopover !== null;
|
|
9574
10924
|
return bridgeRoot ? (0, import_react_dom3.createPortal)(
|
|
9575
|
-
/* @__PURE__ */ (0,
|
|
9576
|
-
/* @__PURE__ */ (0,
|
|
9577
|
-
Object.entries(uploadingRects).
|
|
9578
|
-
|
|
9579
|
-
|
|
9580
|
-
|
|
9581
|
-
|
|
9582
|
-
|
|
9583
|
-
|
|
9584
|
-
|
|
9585
|
-
|
|
9586
|
-
|
|
9587
|
-
|
|
9588
|
-
|
|
10925
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
10926
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
10927
|
+
Object.entries(uploadingRects).flatMap(
|
|
10928
|
+
([key, { rects, fadingOut }]) => rects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
10929
|
+
MediaOverlay,
|
|
10930
|
+
{
|
|
10931
|
+
hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
|
|
10932
|
+
isUploading: true,
|
|
10933
|
+
fadingOut,
|
|
10934
|
+
onFadeOutComplete: handleMediaFadeOutComplete,
|
|
10935
|
+
onReplace: handleMediaReplace
|
|
10936
|
+
},
|
|
10937
|
+
`uploading-${key}-${i}`
|
|
10938
|
+
))
|
|
10939
|
+
),
|
|
10940
|
+
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
9589
10941
|
MediaOverlay,
|
|
9590
10942
|
{
|
|
9591
10943
|
hover: mediaHover,
|
|
@@ -9594,62 +10946,33 @@ function OhhwellsBridge() {
|
|
|
9594
10946
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
9595
10947
|
}
|
|
9596
10948
|
),
|
|
9597
|
-
|
|
9598
|
-
|
|
9599
|
-
|
|
9600
|
-
|
|
9601
|
-
|
|
9602
|
-
|
|
9603
|
-
onAdd: handleAddTopLevelNavItem
|
|
9604
|
-
}
|
|
9605
|
-
),
|
|
9606
|
-
hoveredItemRect && !hoveredNavContainerRect && !siblingHintRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
9607
|
-
toolbarRect && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
9608
|
-
ItemInteractionLayer,
|
|
10949
|
+
carouselHover && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
|
|
10950
|
+
siblingHintRect && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
10951
|
+
siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
|
|
10952
|
+
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
|
|
10953
|
+
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
10954
|
+
"div",
|
|
9609
10955
|
{
|
|
9610
|
-
|
|
9611
|
-
|
|
9612
|
-
|
|
9613
|
-
|
|
9614
|
-
|
|
9615
|
-
|
|
9616
|
-
|
|
9617
|
-
|
|
9618
|
-
|
|
9619
|
-
|
|
9620
|
-
|
|
9621
|
-
|
|
9622
|
-
|
|
9623
|
-
|
|
9624
|
-
|
|
9625
|
-
|
|
9626
|
-
|
|
9627
|
-
}
|
|
9628
|
-
),
|
|
9629
|
-
toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
9630
|
-
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
9631
|
-
EditGlowChrome,
|
|
9632
|
-
{
|
|
9633
|
-
rect: toolbarRect,
|
|
9634
|
-
elRef: glowElRef,
|
|
9635
|
-
reorderHrefKey,
|
|
9636
|
-
dragDisabled: reorderDragDisabled
|
|
9637
|
-
}
|
|
9638
|
-
),
|
|
9639
|
-
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
9640
|
-
FloatingToolbar,
|
|
9641
|
-
{
|
|
9642
|
-
rect: toolbarRect,
|
|
9643
|
-
parentScroll: parentScrollRef.current,
|
|
9644
|
-
elRef: toolbarElRef,
|
|
9645
|
-
onCommand: handleCommand,
|
|
9646
|
-
activeCommands,
|
|
9647
|
-
showEditLink,
|
|
9648
|
-
onEditLink: openLinkPopoverForActive
|
|
9649
|
-
}
|
|
9650
|
-
)
|
|
10956
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
10957
|
+
style: {
|
|
10958
|
+
left: slot.left,
|
|
10959
|
+
top: slot.top,
|
|
10960
|
+
width: slot.width,
|
|
10961
|
+
height: slot.height
|
|
10962
|
+
},
|
|
10963
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(DropIndicator, { direction: slot.direction, state: activeFooterDropIndex === i ? "dragActive" : "dragIdle", className: slot.direction === "horizontal" ? "!h-full !w-full" : "!h-full !w-full" })
|
|
10964
|
+
},
|
|
10965
|
+
`footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
|
|
10966
|
+
)),
|
|
10967
|
+
hoveredNavContainerRect && toolbarVariant !== "select-frame" && !linkPopover && !isItemDragging && !siblingHintRect && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
|
|
10968
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
|
|
10969
|
+
hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !siblingHintRect && siblingHintRects.length === 0 && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
10970
|
+
toolbarRect && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(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__ */ (0, import_jsx_runtime25.jsx)(ItemActionToolbar, { onEditLink: openLinkPopoverForSelected, addItemDisabled: true, editLinkDisabled: false, moreDisabled: true }) : void 0 }),
|
|
10971
|
+
toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
10972
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(EditGlowChrome, { rect: toolbarRect, elRef: glowElRef, reorderHrefKey, dragDisabled: reorderDragDisabled }),
|
|
10973
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(FloatingToolbar, { rect: toolbarRect, parentScroll: parentScrollRef.current, elRef: toolbarElRef, onCommand: handleCommand, activeCommands, showEditLink, onEditLink: openLinkPopoverForActive })
|
|
9651
10974
|
] }),
|
|
9652
|
-
maxBadge && /* @__PURE__ */ (0,
|
|
10975
|
+
maxBadge && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
9653
10976
|
"div",
|
|
9654
10977
|
{
|
|
9655
10978
|
"data-ohw-max-badge": "",
|
|
@@ -9675,57 +10998,29 @@ function OhhwellsBridge() {
|
|
|
9675
10998
|
]
|
|
9676
10999
|
}
|
|
9677
11000
|
),
|
|
9678
|
-
toggleState && !linkPopover && /* @__PURE__ */ (0,
|
|
9679
|
-
|
|
9680
|
-
{
|
|
9681
|
-
|
|
9682
|
-
|
|
9683
|
-
|
|
9684
|
-
|
|
9685
|
-
|
|
9686
|
-
|
|
9687
|
-
|
|
9688
|
-
|
|
9689
|
-
|
|
9690
|
-
|
|
9691
|
-
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
9692
|
-
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
9693
|
-
children: [
|
|
9694
|
-
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
9695
|
-
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
9696
|
-
Badge,
|
|
9697
|
-
{
|
|
9698
|
-
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",
|
|
9699
|
-
onClick: () => {
|
|
9700
|
-
window.parent.postMessage(
|
|
9701
|
-
{ type: "ow:add-section", insertAfter: sectionGap.insertAfter, insertBefore: sectionGap.insertBefore },
|
|
9702
|
-
"*"
|
|
9703
|
-
);
|
|
11001
|
+
toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(StateToggle, { rect: toggleState.rect, activeState: toggleState.activeState, states: toggleState.states, onStateChange: handleStateChange }),
|
|
11002
|
+
sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("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: [
|
|
11003
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
11004
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
11005
|
+
Badge,
|
|
11006
|
+
{
|
|
11007
|
+
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",
|
|
11008
|
+
onClick: () => {
|
|
11009
|
+
window.parent.postMessage(
|
|
11010
|
+
{
|
|
11011
|
+
type: "ow:add-section",
|
|
11012
|
+
insertAfter: sectionGap.insertAfter,
|
|
11013
|
+
insertBefore: sectionGap.insertBefore
|
|
9704
11014
|
},
|
|
9705
|
-
|
|
9706
|
-
|
|
9707
|
-
|
|
9708
|
-
|
|
9709
|
-
|
|
9710
|
-
|
|
9711
|
-
|
|
9712
|
-
|
|
9713
|
-
|
|
9714
|
-
{
|
|
9715
|
-
panelRef: linkPopoverPanelRef,
|
|
9716
|
-
portalContainer: dialogPortalContainer,
|
|
9717
|
-
open: true,
|
|
9718
|
-
mode: linkPopover.mode ?? "edit",
|
|
9719
|
-
pages: sitePages,
|
|
9720
|
-
sections: currentSections,
|
|
9721
|
-
sectionsByPath,
|
|
9722
|
-
initialTarget: linkPopover.target,
|
|
9723
|
-
existingTargets: linkPopover.intent === "add-nav" ? getNavbarExistingTargets() : [],
|
|
9724
|
-
onClose: closeLinkPopover,
|
|
9725
|
-
onSubmit: handleLinkPopoverSubmit
|
|
9726
|
-
},
|
|
9727
|
-
linkPopover.key
|
|
9728
|
-
) : null
|
|
11015
|
+
"*"
|
|
11016
|
+
);
|
|
11017
|
+
},
|
|
11018
|
+
children: "Add Section"
|
|
11019
|
+
}
|
|
11020
|
+
),
|
|
11021
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
|
|
11022
|
+
] }),
|
|
11023
|
+
linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(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
|
|
9729
11024
|
] }),
|
|
9730
11025
|
bridgeRoot
|
|
9731
11026
|
) : null;
|
|
@@ -9736,6 +11031,7 @@ function OhhwellsBridge() {
|
|
|
9736
11031
|
CustomToolbarButton,
|
|
9737
11032
|
CustomToolbarDivider,
|
|
9738
11033
|
DragHandle,
|
|
11034
|
+
DropIndicator,
|
|
9739
11035
|
ItemActionToolbar,
|
|
9740
11036
|
ItemInteractionLayer,
|
|
9741
11037
|
LinkEditorPanel,
|
|
@@ -9750,12 +11046,14 @@ function OhhwellsBridge() {
|
|
|
9750
11046
|
TooltipProvider,
|
|
9751
11047
|
TooltipTrigger,
|
|
9752
11048
|
buildTarget,
|
|
11049
|
+
dropIndicatorVariants,
|
|
9753
11050
|
filterAvailablePages,
|
|
9754
11051
|
getEditModeInitialState,
|
|
9755
11052
|
isEditSessionActive,
|
|
9756
11053
|
isValidUrl,
|
|
9757
11054
|
parseTarget,
|
|
9758
11055
|
toggleVariants,
|
|
11056
|
+
useOhwCarousel,
|
|
9759
11057
|
validateUrlInput
|
|
9760
11058
|
});
|
|
9761
11059
|
//# sourceMappingURL=index.cjs.map
|