@ohhwells/bridge 0.1.38 → 0.1.39-next.72
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 +3059 -666
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +98 -6
- package/dist/index.d.ts +98 -6
- package/dist/index.js +3044 -654
- package/dist/index.js.map +1 -1
- package/dist/styles.css +169 -34
- 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,26 +50,31 @@ __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
|
-
var
|
|
68
|
+
var import_react_dom2 = require("react-dom");
|
|
66
69
|
|
|
67
70
|
// src/linkHrefStore.ts
|
|
68
71
|
var linkHrefStore = /* @__PURE__ */ new Map();
|
|
69
72
|
function setStoredLinkHref(key, href) {
|
|
70
73
|
linkHrefStore.set(key, href);
|
|
71
74
|
}
|
|
75
|
+
function getStoredLinkHref(key) {
|
|
76
|
+
return linkHrefStore.get(key);
|
|
77
|
+
}
|
|
72
78
|
function enforceLinkHrefs() {
|
|
73
79
|
document.querySelectorAll("[data-ohw-href-key]").forEach((el) => {
|
|
74
80
|
const key = el.getAttribute("data-ohw-href-key") ?? "";
|
|
@@ -110,6 +116,7 @@ var import_react3 = require("react");
|
|
|
110
116
|
var import_react2 = require("react");
|
|
111
117
|
var import_radix_ui = require("radix-ui");
|
|
112
118
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
119
|
+
var isValidEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
113
120
|
function Spinner() {
|
|
114
121
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
115
122
|
"svg",
|
|
@@ -143,12 +150,17 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
|
|
|
143
150
|
const [error, setError] = (0, import_react2.useState)(null);
|
|
144
151
|
const isBook = title === "Confirm your spot";
|
|
145
152
|
const handleSubmit = async () => {
|
|
146
|
-
|
|
153
|
+
const trimmed = email.trim();
|
|
154
|
+
if (!trimmed) return;
|
|
155
|
+
if (!isValidEmail(trimmed)) {
|
|
156
|
+
setError("Please enter a valid email address.");
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
147
159
|
setLoading(true);
|
|
148
160
|
setError(null);
|
|
149
161
|
try {
|
|
150
|
-
await onSubmit(
|
|
151
|
-
setSubmittedEmail(
|
|
162
|
+
await onSubmit(trimmed);
|
|
163
|
+
setSubmittedEmail(trimmed);
|
|
152
164
|
setSuccess(true);
|
|
153
165
|
} catch (e) {
|
|
154
166
|
setError(e instanceof Error ? e.message : "Something went wrong. Please try again.");
|
|
@@ -223,7 +235,10 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
|
|
|
223
235
|
{
|
|
224
236
|
type: "email",
|
|
225
237
|
value: email,
|
|
226
|
-
onChange: (e) =>
|
|
238
|
+
onChange: (e) => {
|
|
239
|
+
setEmail(e.target.value);
|
|
240
|
+
if (error) setError(null);
|
|
241
|
+
},
|
|
227
242
|
onKeyDown: handleKeyDown,
|
|
228
243
|
placeholder: "hello@gmail.com",
|
|
229
244
|
autoFocus: true,
|
|
@@ -280,12 +295,20 @@ function formatClassTime(cls) {
|
|
|
280
295
|
const em = endTotal % 60;
|
|
281
296
|
return `${h}:${cls.startTime.minutes}-${eh}:${String(em).padStart(2, "0")}`;
|
|
282
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
|
+
}
|
|
283
303
|
function getBookingsOnDate(cls, date) {
|
|
284
304
|
if (!cls.bookings?.length) return 0;
|
|
285
|
-
const
|
|
305
|
+
const target = new Date(date);
|
|
306
|
+
target.setHours(0, 0, 0, 0);
|
|
286
307
|
return cls.bookings.filter((b) => {
|
|
287
308
|
try {
|
|
288
|
-
|
|
309
|
+
const bookingDate = new Date(b.classDate);
|
|
310
|
+
bookingDate.setHours(0, 0, 0, 0);
|
|
311
|
+
return bookingDate.getTime() === target.getTime();
|
|
289
312
|
} catch {
|
|
290
313
|
return false;
|
|
291
314
|
}
|
|
@@ -550,7 +573,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
|
|
|
550
573
|
}
|
|
551
574
|
)
|
|
552
575
|
] }),
|
|
553
|
-
/* @__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: [
|
|
554
577
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
|
|
555
578
|
available,
|
|
556
579
|
"/",
|
|
@@ -562,9 +585,10 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
|
|
|
562
585
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-1 flex-col gap-2 min-w-0 sm:contents", children: [
|
|
563
586
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex-1 flex flex-col gap-2 min-w-0", children: [
|
|
564
587
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-base font-bold text-(--color-dark,#200C02) block truncate", children: cls.name }),
|
|
565
|
-
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 })
|
|
566
590
|
] }),
|
|
567
|
-
/* @__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: [
|
|
568
592
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
|
|
569
593
|
available,
|
|
570
594
|
"/",
|
|
@@ -589,7 +613,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
|
|
|
589
613
|
if (!cls.id) return;
|
|
590
614
|
onOpenModal?.(isFull ? "waitlist" : "book", cls.id, selectedDate);
|
|
591
615
|
},
|
|
592
|
-
children: isFull ? "Join Waitlist" :
|
|
616
|
+
children: isFull ? "Join Waitlist" : formatBookingLabel(cls)
|
|
593
617
|
}
|
|
594
618
|
)
|
|
595
619
|
] })
|
|
@@ -631,6 +655,17 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
631
655
|
const [isHovered, setIsHovered] = (0, import_react3.useState)(false);
|
|
632
656
|
const [modalState, setModalState] = (0, import_react3.useState)(null);
|
|
633
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
|
+
}, []);
|
|
634
669
|
const dates = (0, import_react3.useMemo)(() => {
|
|
635
670
|
const today = /* @__PURE__ */ new Date();
|
|
636
671
|
today.setHours(0, 0, 0, 0);
|
|
@@ -650,6 +685,18 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
650
685
|
}
|
|
651
686
|
}
|
|
652
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]);
|
|
653
700
|
(0, import_react3.useEffect)(() => {
|
|
654
701
|
if (typeof window === "undefined") return;
|
|
655
702
|
const isInEditor = window.self !== window.top;
|
|
@@ -711,7 +758,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
711
758
|
setLoading(false);
|
|
712
759
|
return;
|
|
713
760
|
}
|
|
714
|
-
;
|
|
761
|
+
liveScheduleIdRef.current = effectiveId;
|
|
715
762
|
(async () => {
|
|
716
763
|
try {
|
|
717
764
|
const res = await fetch(`${API_URL}/api/schedule/id/${effectiveId}`);
|
|
@@ -768,18 +815,14 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
768
815
|
const data = await res.json().catch(() => ({}));
|
|
769
816
|
throw new Error(data?.message ?? "Something went wrong. Please try again.");
|
|
770
817
|
}
|
|
818
|
+
await refetchLiveSchedule();
|
|
771
819
|
};
|
|
772
820
|
const handleReplaceSchedule = () => {
|
|
773
821
|
setIsHovered(false);
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
insertAfter
|
|
779
|
-
}, "*");
|
|
780
|
-
} else {
|
|
781
|
-
window.parent.postMessage({ type: "ow:scheduling-not-connected", insertAfter }, "*");
|
|
782
|
-
}
|
|
822
|
+
window.parent.postMessage(
|
|
823
|
+
{ type: "ow:scheduling-not-connected", insertAfter, currentScheduleId: schedule?.id },
|
|
824
|
+
"*"
|
|
825
|
+
);
|
|
783
826
|
};
|
|
784
827
|
if (!inEditor && !loading && !schedule) return null;
|
|
785
828
|
const sectionId = `scheduling-${insertAfter}`;
|
|
@@ -822,7 +865,19 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
822
865
|
),
|
|
823
866
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "max-w-[1280px] mx-auto flex flex-col items-center gap-16", children: [
|
|
824
867
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-col items-center gap-4", children: [
|
|
825
|
-
/* @__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
|
+
),
|
|
826
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 })
|
|
827
882
|
] }),
|
|
828
883
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "w-full flex flex-col items-end gap-3", children: [
|
|
@@ -4408,6 +4463,7 @@ function ItemActionToolbar({
|
|
|
4408
4463
|
onEditLink,
|
|
4409
4464
|
onAddItem,
|
|
4410
4465
|
onMore,
|
|
4466
|
+
editLinkDisabled = false,
|
|
4411
4467
|
addItemDisabled = true,
|
|
4412
4468
|
moreDisabled = true,
|
|
4413
4469
|
tooltipSide = "bottom"
|
|
@@ -4416,10 +4472,12 @@ function ItemActionToolbar({
|
|
|
4416
4472
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
4417
4473
|
ToolbarActionTooltip,
|
|
4418
4474
|
{
|
|
4419
|
-
label: "
|
|
4475
|
+
label: "Edit link",
|
|
4420
4476
|
side: tooltipSide,
|
|
4477
|
+
disabled: editLinkDisabled,
|
|
4421
4478
|
buttonProps: {
|
|
4422
4479
|
onMouseDown: (e) => {
|
|
4480
|
+
if (editLinkDisabled) return;
|
|
4423
4481
|
e.preventDefault();
|
|
4424
4482
|
e.stopPropagation();
|
|
4425
4483
|
onEditLink?.();
|
|
@@ -4497,7 +4555,7 @@ function getChromeStyle(state) {
|
|
|
4497
4555
|
case "dragging":
|
|
4498
4556
|
return {
|
|
4499
4557
|
border: `2px solid ${PRIMARY}`,
|
|
4500
|
-
boxShadow: DRAG_SHADOW
|
|
4558
|
+
boxShadow: `${FOCUS_RING}, ${DRAG_SHADOW}`
|
|
4501
4559
|
};
|
|
4502
4560
|
default:
|
|
4503
4561
|
return {};
|
|
@@ -4513,6 +4571,8 @@ function ItemInteractionLayer({
|
|
|
4513
4571
|
dragHandleLabel = "Reorder item",
|
|
4514
4572
|
onDragHandleDragStart,
|
|
4515
4573
|
onDragHandleDragEnd,
|
|
4574
|
+
onItemPointerDown,
|
|
4575
|
+
onItemClick,
|
|
4516
4576
|
chromeGap = 6,
|
|
4517
4577
|
className
|
|
4518
4578
|
}) {
|
|
@@ -4520,7 +4580,8 @@ function ItemInteractionLayer({
|
|
|
4520
4580
|
const isActive = state === "active-top" || state === "active-bottom";
|
|
4521
4581
|
const isDragging = state === "dragging";
|
|
4522
4582
|
const showToolbar = isActive && toolbar;
|
|
4523
|
-
const showDragHandle = isActive
|
|
4583
|
+
const showDragHandle = (isActive || isDragging) && showHandle;
|
|
4584
|
+
const itemDragEnabled = isActive && showHandle && !isDragging && !dragDisabled;
|
|
4524
4585
|
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
4525
4586
|
"div",
|
|
4526
4587
|
{
|
|
@@ -4545,11 +4606,28 @@ function ItemInteractionLayer({
|
|
|
4545
4606
|
style: getChromeStyle(state)
|
|
4546
4607
|
}
|
|
4547
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
|
+
),
|
|
4548
4625
|
showDragHandle && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4549
4626
|
"div",
|
|
4550
4627
|
{
|
|
4551
4628
|
"data-ohw-drag-handle-container": "",
|
|
4552
|
-
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,
|
|
4553
4631
|
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4554
4632
|
DragHandle,
|
|
4555
4633
|
{
|
|
@@ -4772,15 +4850,12 @@ function MediaOverlay({
|
|
|
4772
4850
|
className: "flex items-center justify-center cursor-pointer",
|
|
4773
4851
|
style: {
|
|
4774
4852
|
...box,
|
|
4775
|
-
//
|
|
4776
|
-
//
|
|
4777
|
-
|
|
4778
|
-
// Replace still works.
|
|
4779
|
-
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",
|
|
4780
4856
|
boxShadow: "inset 0 0 0 1.5px var(--color-primary)",
|
|
4781
4857
|
background: "color-mix(in srgb, var(--color-primary) 20%, transparent)"
|
|
4782
4858
|
},
|
|
4783
|
-
onClick: () => onReplace(hover.key),
|
|
4784
4859
|
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
4785
4860
|
Button,
|
|
4786
4861
|
{
|
|
@@ -4805,9 +4880,64 @@ function MediaOverlay({
|
|
|
4805
4880
|
] });
|
|
4806
4881
|
}
|
|
4807
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
|
+
|
|
4808
4938
|
// src/OhhwellsBridge.tsx
|
|
4809
|
-
var
|
|
4810
|
-
var
|
|
4939
|
+
var import_react_dom3 = require("react-dom");
|
|
4940
|
+
var import_navigation2 = require("next/navigation");
|
|
4811
4941
|
|
|
4812
4942
|
// src/lib/session-search.ts
|
|
4813
4943
|
var STORAGE_KEY = "ohw-preserved-search";
|
|
@@ -4837,6 +4967,7 @@ function parseSectionsFromRoot(root) {
|
|
|
4837
4967
|
for (const el of root.querySelectorAll("[data-ohw-section]")) {
|
|
4838
4968
|
const id = el.getAttribute("data-ohw-section") ?? "";
|
|
4839
4969
|
if (!id || seen.has(id)) continue;
|
|
4970
|
+
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
4840
4971
|
seen.add(id);
|
|
4841
4972
|
const label = el.getAttribute("data-ohw-section-label") ?? titleCaseSectionId(id);
|
|
4842
4973
|
sections.push({ id, label });
|
|
@@ -5083,54 +5214,22 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
|
|
|
5083
5214
|
tick();
|
|
5084
5215
|
}
|
|
5085
5216
|
|
|
5217
|
+
// src/ui/link-modal/LinkPopover.tsx
|
|
5218
|
+
var import_react7 = require("react");
|
|
5219
|
+
|
|
5086
5220
|
// src/ui/dialog.tsx
|
|
5087
5221
|
var React7 = __toESM(require("react"), 1);
|
|
5088
5222
|
var import_radix_ui5 = require("radix-ui");
|
|
5089
|
-
|
|
5090
|
-
// src/ui/icons.tsx
|
|
5091
|
-
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
5092
|
-
function IconX({ className, ...props }) {
|
|
5093
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
|
|
5094
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M18 6 6 18" }),
|
|
5095
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m6 6 12 12" })
|
|
5096
|
-
] });
|
|
5097
|
-
}
|
|
5098
|
-
function IconChevronDown({ className, ...props }) {
|
|
5099
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m6 9 6 6 6-6" }) });
|
|
5100
|
-
}
|
|
5101
|
-
function IconFile({ className, ...props }) {
|
|
5102
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
|
|
5103
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }),
|
|
5104
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" })
|
|
5105
|
-
] });
|
|
5106
|
-
}
|
|
5107
|
-
function IconInfo({ className, ...props }) {
|
|
5108
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
|
|
5109
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
|
|
5110
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M12 16v-4" }),
|
|
5111
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M12 8h.01" })
|
|
5112
|
-
] });
|
|
5113
|
-
}
|
|
5114
|
-
function IconArrowRight({ className, ...props }) {
|
|
5115
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
|
|
5116
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M5 12h14" }),
|
|
5117
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "m12 5 7 7-7 7" })
|
|
5118
|
-
] });
|
|
5119
|
-
}
|
|
5120
|
-
function IconSection({ className, ...props }) {
|
|
5121
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
|
|
5122
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("rect", { width: "18", height: "7", x: "3", y: "3", rx: "1" }),
|
|
5123
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("rect", { width: "9", height: "7", x: "3", y: "14", rx: "1" }),
|
|
5124
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("rect", { width: "5", height: "7", x: "16", y: "14", rx: "1" })
|
|
5125
|
-
] });
|
|
5126
|
-
}
|
|
5127
|
-
|
|
5128
|
-
// src/ui/dialog.tsx
|
|
5223
|
+
var import_lucide_react5 = require("lucide-react");
|
|
5129
5224
|
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
5130
|
-
function Dialog2({
|
|
5225
|
+
function Dialog2({
|
|
5226
|
+
...props
|
|
5227
|
+
}) {
|
|
5131
5228
|
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_radix_ui5.Dialog.Root, { "data-slot": "dialog", ...props });
|
|
5132
5229
|
}
|
|
5133
|
-
function DialogPortal({
|
|
5230
|
+
function DialogPortal({
|
|
5231
|
+
...props
|
|
5232
|
+
}) {
|
|
5134
5233
|
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_radix_ui5.Dialog.Portal, { ...props });
|
|
5135
5234
|
}
|
|
5136
5235
|
function DialogOverlay({
|
|
@@ -5147,52 +5246,69 @@ function DialogOverlay({
|
|
|
5147
5246
|
}
|
|
5148
5247
|
);
|
|
5149
5248
|
}
|
|
5150
|
-
var DialogContent = React7.forwardRef(
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
children
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
});
|
|
5249
|
+
var DialogContent = React7.forwardRef(
|
|
5250
|
+
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
5251
|
+
const positionMode = container ? "absolute" : "fixed";
|
|
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)(
|
|
5255
|
+
import_radix_ui5.Dialog.Content,
|
|
5256
|
+
{
|
|
5257
|
+
ref,
|
|
5258
|
+
"data-slot": "dialog-content",
|
|
5259
|
+
className: cn(
|
|
5260
|
+
positionMode,
|
|
5261
|
+
"left-1/2 top-1/2 z-[2147483647] flex w-full max-w-[448px] -translate-x-1/2 -translate-y-1/2 flex-col overflow-visible",
|
|
5262
|
+
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
5263
|
+
container ? "max-h-[calc(100%-32px)]" : "max-h-[calc(100vh-32px)]",
|
|
5264
|
+
className
|
|
5265
|
+
),
|
|
5266
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
5267
|
+
...props,
|
|
5268
|
+
children: [
|
|
5269
|
+
children,
|
|
5270
|
+
showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
5271
|
+
import_radix_ui5.Dialog.Close,
|
|
5272
|
+
{
|
|
5273
|
+
type: "button",
|
|
5274
|
+
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
5275
|
+
"aria-label": "Close",
|
|
5276
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react5.X, { size: 16, "aria-hidden": true })
|
|
5277
|
+
}
|
|
5278
|
+
) : null
|
|
5279
|
+
]
|
|
5280
|
+
}
|
|
5281
|
+
)
|
|
5282
|
+
] });
|
|
5283
|
+
}
|
|
5284
|
+
);
|
|
5184
5285
|
DialogContent.displayName = import_radix_ui5.Dialog.Content.displayName;
|
|
5185
|
-
function DialogHeader({
|
|
5286
|
+
function DialogHeader({
|
|
5287
|
+
className,
|
|
5288
|
+
...props
|
|
5289
|
+
}) {
|
|
5186
5290
|
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
5187
5291
|
}
|
|
5188
|
-
function DialogFooter({
|
|
5189
|
-
|
|
5292
|
+
function DialogFooter({
|
|
5293
|
+
className,
|
|
5294
|
+
...props
|
|
5295
|
+
}) {
|
|
5296
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
5297
|
+
"div",
|
|
5298
|
+
{
|
|
5299
|
+
className: cn("flex items-center justify-end gap-2", className),
|
|
5300
|
+
...props
|
|
5301
|
+
}
|
|
5302
|
+
);
|
|
5190
5303
|
}
|
|
5191
5304
|
var DialogTitle = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
5192
5305
|
import_radix_ui5.Dialog.Title,
|
|
5193
5306
|
{
|
|
5194
5307
|
ref,
|
|
5195
|
-
className: cn(
|
|
5308
|
+
className: cn(
|
|
5309
|
+
"text-lg font-semibold leading-none tracking-tight text-card-foreground",
|
|
5310
|
+
className
|
|
5311
|
+
),
|
|
5196
5312
|
...props
|
|
5197
5313
|
}
|
|
5198
5314
|
));
|
|
@@ -5208,19 +5324,40 @@ var DialogDescription = React7.forwardRef(({ className, ...props }, ref) => /* @
|
|
|
5208
5324
|
DialogDescription.displayName = import_radix_ui5.Dialog.Description.displayName;
|
|
5209
5325
|
var DialogClose = import_radix_ui5.Dialog.Close;
|
|
5210
5326
|
|
|
5327
|
+
// src/ui/link-modal/LinkEditorPanel.tsx
|
|
5328
|
+
var import_lucide_react9 = require("lucide-react");
|
|
5329
|
+
|
|
5211
5330
|
// src/ui/link-modal/DestinationBreadcrumb.tsx
|
|
5331
|
+
var import_lucide_react6 = require("lucide-react");
|
|
5212
5332
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
5213
|
-
function DestinationBreadcrumb({
|
|
5333
|
+
function DestinationBreadcrumb({
|
|
5334
|
+
pageTitle,
|
|
5335
|
+
sectionLabel
|
|
5336
|
+
}) {
|
|
5214
5337
|
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex w-full flex-col gap-2", children: [
|
|
5215
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-sm font-medium text-foreground", children: "Destination" }),
|
|
5338
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-sm font-medium! text-foreground m-0", children: "Destination" }),
|
|
5216
5339
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-3", children: [
|
|
5217
5340
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
5218
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
5219
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "text-sm font-medium leading-none text-foreground", children: pageTitle })
|
|
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 })
|
|
5220
5343
|
] }),
|
|
5221
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
5344
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
5345
|
+
import_lucide_react6.ArrowRight,
|
|
5346
|
+
{
|
|
5347
|
+
size: 16,
|
|
5348
|
+
className: "shrink-0 text-muted-foreground",
|
|
5349
|
+
"aria-hidden": true
|
|
5350
|
+
}
|
|
5351
|
+
),
|
|
5222
5352
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
|
|
5223
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
5353
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
5354
|
+
import_lucide_react6.GalleryVertical,
|
|
5355
|
+
{
|
|
5356
|
+
size: 16,
|
|
5357
|
+
className: "shrink-0 text-foreground",
|
|
5358
|
+
"aria-hidden": true
|
|
5359
|
+
}
|
|
5360
|
+
),
|
|
5224
5361
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
|
|
5225
5362
|
] })
|
|
5226
5363
|
] })
|
|
@@ -5228,8 +5365,13 @@ function DestinationBreadcrumb({ pageTitle, sectionLabel }) {
|
|
|
5228
5365
|
}
|
|
5229
5366
|
|
|
5230
5367
|
// src/ui/link-modal/SectionTreeItem.tsx
|
|
5368
|
+
var import_lucide_react7 = require("lucide-react");
|
|
5231
5369
|
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
5232
|
-
function SectionTreeItem({
|
|
5370
|
+
function SectionTreeItem({
|
|
5371
|
+
section,
|
|
5372
|
+
onSelect,
|
|
5373
|
+
selected
|
|
5374
|
+
}) {
|
|
5233
5375
|
const interactive = Boolean(onSelect);
|
|
5234
5376
|
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex h-9 w-full items-end pl-3", children: [
|
|
5235
5377
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
@@ -5257,22 +5399,20 @@ function SectionTreeItem({ section, onSelect, selected }) {
|
|
|
5257
5399
|
interactive && selected && "border-primary"
|
|
5258
5400
|
),
|
|
5259
5401
|
children: [
|
|
5260
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
5402
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
5403
|
+
import_lucide_react7.GalleryVertical,
|
|
5404
|
+
{
|
|
5405
|
+
size: 16,
|
|
5406
|
+
className: "shrink-0 text-foreground",
|
|
5407
|
+
"aria-hidden": true
|
|
5408
|
+
}
|
|
5409
|
+
),
|
|
5261
5410
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
|
|
5262
5411
|
]
|
|
5263
5412
|
}
|
|
5264
5413
|
)
|
|
5265
5414
|
] });
|
|
5266
5415
|
}
|
|
5267
|
-
function SectionPickerList({ sections, onSelect }) {
|
|
5268
|
-
if (sections.length === 0) {
|
|
5269
|
-
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." });
|
|
5270
|
-
}
|
|
5271
|
-
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
5272
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "text-sm text-muted-foreground", children: "Pick a section this link should scroll to." }),
|
|
5273
|
-
sections.map((section) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(SectionTreeItem, { section, onSelect }, section.id))
|
|
5274
|
-
] });
|
|
5275
|
-
}
|
|
5276
5416
|
|
|
5277
5417
|
// src/ui/link-modal/UrlOrPageInput.tsx
|
|
5278
5418
|
var import_react4 = require("react");
|
|
@@ -5314,8 +5454,11 @@ function Label({ className, ...props }) {
|
|
|
5314
5454
|
}
|
|
5315
5455
|
|
|
5316
5456
|
// src/ui/link-modal/UrlOrPageInput.tsx
|
|
5457
|
+
var import_lucide_react8 = require("lucide-react");
|
|
5317
5458
|
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
5318
|
-
function FieldChevron({
|
|
5459
|
+
function FieldChevron({
|
|
5460
|
+
onClick
|
|
5461
|
+
}) {
|
|
5319
5462
|
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5320
5463
|
"button",
|
|
5321
5464
|
{
|
|
@@ -5324,7 +5467,7 @@ function FieldChevron({ onClick }) {
|
|
|
5324
5467
|
onClick,
|
|
5325
5468
|
"aria-label": "Open page list",
|
|
5326
5469
|
tabIndex: -1,
|
|
5327
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5470
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.ChevronDown, { size: 16 })
|
|
5328
5471
|
}
|
|
5329
5472
|
);
|
|
5330
5473
|
}
|
|
@@ -5342,7 +5485,29 @@ function UrlOrPageInput({
|
|
|
5342
5485
|
}) {
|
|
5343
5486
|
const inputId = (0, import_react4.useId)();
|
|
5344
5487
|
const inputRef = (0, import_react4.useRef)(null);
|
|
5488
|
+
const rootRef = (0, import_react4.useRef)(null);
|
|
5345
5489
|
const [isFocused, setIsFocused] = (0, import_react4.useState)(false);
|
|
5490
|
+
(0, import_react4.useEffect)(() => {
|
|
5491
|
+
if (!dropdownOpen) return;
|
|
5492
|
+
const isOutside = (e) => {
|
|
5493
|
+
const root = rootRef.current;
|
|
5494
|
+
if (!root) return true;
|
|
5495
|
+
const path = typeof e.composedPath === "function" ? e.composedPath() : [];
|
|
5496
|
+
if (path.includes(root)) return false;
|
|
5497
|
+
const target = e.target;
|
|
5498
|
+
return !(target instanceof Node && root.contains(target));
|
|
5499
|
+
};
|
|
5500
|
+
const closeIfOutside = (e) => {
|
|
5501
|
+
if (!isOutside(e)) return;
|
|
5502
|
+
onDropdownOpenChange(false);
|
|
5503
|
+
};
|
|
5504
|
+
document.addEventListener("pointerdown", closeIfOutside, true);
|
|
5505
|
+
document.addEventListener("mousedown", closeIfOutside, true);
|
|
5506
|
+
return () => {
|
|
5507
|
+
document.removeEventListener("pointerdown", closeIfOutside, true);
|
|
5508
|
+
document.removeEventListener("mousedown", closeIfOutside, true);
|
|
5509
|
+
};
|
|
5510
|
+
}, [dropdownOpen, onDropdownOpenChange]);
|
|
5346
5511
|
const openDropdown = () => {
|
|
5347
5512
|
if (readOnly || filteredPages.length === 0) return;
|
|
5348
5513
|
onDropdownOpenChange(true);
|
|
@@ -5360,14 +5525,21 @@ function UrlOrPageInput({
|
|
|
5360
5525
|
requestAnimationFrame(() => inputRef.current?.focus());
|
|
5361
5526
|
};
|
|
5362
5527
|
const fieldClassName = cn(
|
|
5363
|
-
"data-ohw-link-field flex h-
|
|
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]",
|
|
5364
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"
|
|
5365
5530
|
);
|
|
5366
5531
|
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex w-full flex-col gap-2 p-0", children: [
|
|
5367
5532
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
|
|
5368
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "relative w-full", children: [
|
|
5533
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { ref: rootRef, className: "relative w-full", children: [
|
|
5369
5534
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
|
|
5370
|
-
selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
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,
|
|
5537
|
+
{
|
|
5538
|
+
size: 16,
|
|
5539
|
+
className: "shrink-0 text-foreground",
|
|
5540
|
+
"aria-hidden": true
|
|
5541
|
+
}
|
|
5542
|
+
) }) : null,
|
|
5371
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)(
|
|
5372
5544
|
Input,
|
|
5373
5545
|
{
|
|
@@ -5379,7 +5551,14 @@ function UrlOrPageInput({
|
|
|
5379
5551
|
setIsFocused(true);
|
|
5380
5552
|
if (!selectedPage) openDropdown();
|
|
5381
5553
|
},
|
|
5382
|
-
onBlur: () =>
|
|
5554
|
+
onBlur: () => {
|
|
5555
|
+
setIsFocused(false);
|
|
5556
|
+
requestAnimationFrame(() => {
|
|
5557
|
+
if (!rootRef.current?.contains(document.activeElement)) {
|
|
5558
|
+
onDropdownOpenChange(false);
|
|
5559
|
+
}
|
|
5560
|
+
});
|
|
5561
|
+
},
|
|
5383
5562
|
placeholder,
|
|
5384
5563
|
className: cn(
|
|
5385
5564
|
"min-w-0 flex-1 truncate border-0 bg-transparent p-0 text-sm font-normal leading-5 shadow-none outline-none ring-0 caret-foreground",
|
|
@@ -5395,7 +5574,7 @@ function UrlOrPageInput({
|
|
|
5395
5574
|
onMouseDown: clearSelection,
|
|
5396
5575
|
"aria-label": "Clear selected page",
|
|
5397
5576
|
tabIndex: -1,
|
|
5398
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5577
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.X, { size: 16, "aria-hidden": true })
|
|
5399
5578
|
}
|
|
5400
5579
|
) : null,
|
|
5401
5580
|
!readOnly ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(FieldChevron, { onClick: toggleDropdown }) : null
|
|
@@ -5404,7 +5583,7 @@ function UrlOrPageInput({
|
|
|
5404
5583
|
"div",
|
|
5405
5584
|
{
|
|
5406
5585
|
"data-ohw-link-page-dropdown": "",
|
|
5407
|
-
className: "absolute left-0 right-0
|
|
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",
|
|
5408
5587
|
onMouseDown: (e) => e.preventDefault(),
|
|
5409
5588
|
children: filteredPages.map((page) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
5410
5589
|
"button",
|
|
@@ -5413,7 +5592,7 @@ function UrlOrPageInput({
|
|
|
5413
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",
|
|
5414
5593
|
onClick: () => onPageSelect(page),
|
|
5415
5594
|
children: [
|
|
5416
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5595
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.File, { size: 16, className: "shrink-0", "aria-hidden": true }),
|
|
5417
5596
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "truncate", children: page.title })
|
|
5418
5597
|
]
|
|
5419
5598
|
},
|
|
@@ -5426,42 +5605,470 @@ function UrlOrPageInput({
|
|
|
5426
5605
|
] });
|
|
5427
5606
|
}
|
|
5428
5607
|
|
|
5429
|
-
// src/ui/link-modal/
|
|
5608
|
+
// src/ui/link-modal/LinkEditorPanel.tsx
|
|
5609
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
5610
|
+
function LinkEditorPanel({ state, onClose }) {
|
|
5611
|
+
const isCancel = state.secondaryLabel === "Cancel" || state.secondaryLabel === "Back to sections";
|
|
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)(
|
|
5614
|
+
"button",
|
|
5615
|
+
{
|
|
5616
|
+
type: "button",
|
|
5617
|
+
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50 h-7",
|
|
5618
|
+
"aria-label": "Close",
|
|
5619
|
+
onClick: onClose,
|
|
5620
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react9.X, { size: 16, "aria-hidden": true })
|
|
5621
|
+
}
|
|
5622
|
+
) }),
|
|
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)(
|
|
5626
|
+
DestinationBreadcrumb,
|
|
5627
|
+
{
|
|
5628
|
+
pageTitle: state.selectedPage.title,
|
|
5629
|
+
sectionLabel: state.selectedSection.label
|
|
5630
|
+
}
|
|
5631
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5632
|
+
UrlOrPageInput,
|
|
5633
|
+
{
|
|
5634
|
+
value: state.searchValue,
|
|
5635
|
+
selectedPage: state.selectedPage,
|
|
5636
|
+
dropdownOpen: state.dropdownOpen,
|
|
5637
|
+
onDropdownOpenChange: state.setDropdownOpen,
|
|
5638
|
+
filteredPages: state.filteredPages,
|
|
5639
|
+
onInputChange: state.handleInputChange,
|
|
5640
|
+
onPageSelect: state.handlePageSelect,
|
|
5641
|
+
urlError: state.urlError
|
|
5642
|
+
}
|
|
5643
|
+
),
|
|
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)(
|
|
5646
|
+
Button,
|
|
5647
|
+
{
|
|
5648
|
+
type: "button",
|
|
5649
|
+
variant: "outline",
|
|
5650
|
+
className: "w-fit cursor-pointer",
|
|
5651
|
+
size: "sm",
|
|
5652
|
+
onClick: state.handleChooseSection,
|
|
5653
|
+
children: "Choose a section"
|
|
5654
|
+
}
|
|
5655
|
+
),
|
|
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." })
|
|
5659
|
+
] })
|
|
5660
|
+
] }) : null,
|
|
5661
|
+
state.showSectionRow && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
|
|
5662
|
+
] }),
|
|
5663
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(DialogFooter, { className: "w-full px-6 pb-6", children: [
|
|
5664
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5665
|
+
Button,
|
|
5666
|
+
{
|
|
5667
|
+
type: "button",
|
|
5668
|
+
variant: isCancel ? "outline" : "ghost",
|
|
5669
|
+
className: "leading-6 shadow-none cursor-pointer",
|
|
5670
|
+
style: isCancel ? {
|
|
5671
|
+
backgroundColor: "var(--ohw-background)",
|
|
5672
|
+
borderColor: "var(--ohw-border)",
|
|
5673
|
+
color: "var(--ohw-foreground)"
|
|
5674
|
+
} : void 0,
|
|
5675
|
+
onClick: state.handleSecondary,
|
|
5676
|
+
children: state.secondaryLabel
|
|
5677
|
+
}
|
|
5678
|
+
),
|
|
5679
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5680
|
+
Button,
|
|
5681
|
+
{
|
|
5682
|
+
type: "button",
|
|
5683
|
+
className: "border-0 leading-6 shadow-none hover:opacity-90 disabled:opacity-50 cursor-pointer",
|
|
5684
|
+
style: {
|
|
5685
|
+
backgroundColor: "var(--ohw-primary)",
|
|
5686
|
+
color: "var(--ohw-primary-foreground)"
|
|
5687
|
+
},
|
|
5688
|
+
disabled: !state.isValid,
|
|
5689
|
+
onClick: state.handleSubmit,
|
|
5690
|
+
children: state.submitLabel
|
|
5691
|
+
}
|
|
5692
|
+
)
|
|
5693
|
+
] })
|
|
5694
|
+
] });
|
|
5695
|
+
}
|
|
5696
|
+
|
|
5697
|
+
// src/ui/link-modal/SectionPickerOverlay.tsx
|
|
5430
5698
|
var import_react5 = require("react");
|
|
5431
|
-
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
|
|
5438
|
-
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
const
|
|
5448
|
-
const
|
|
5449
|
-
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
5461
|
-
|
|
5462
|
-
|
|
5463
|
-
|
|
5464
|
-
|
|
5699
|
+
var import_react_dom = require("react-dom");
|
|
5700
|
+
var import_lucide_react10 = require("lucide-react");
|
|
5701
|
+
var import_navigation = require("next/navigation");
|
|
5702
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
5703
|
+
var DIM_OVERLAY = "rgba(0, 0, 0, 0.45)";
|
|
5704
|
+
function rectsEqual(a, b) {
|
|
5705
|
+
if (a.size !== b.size) return false;
|
|
5706
|
+
for (const [id, rect] of a) {
|
|
5707
|
+
const other = b.get(id);
|
|
5708
|
+
if (!other || rect.top !== other.top || rect.left !== other.left || rect.width !== other.width || rect.height !== other.height) {
|
|
5709
|
+
return false;
|
|
5710
|
+
}
|
|
5711
|
+
}
|
|
5712
|
+
return true;
|
|
5713
|
+
}
|
|
5714
|
+
function readSectionRects(sectionIds) {
|
|
5715
|
+
const next = /* @__PURE__ */ new Map();
|
|
5716
|
+
for (const id of sectionIds) {
|
|
5717
|
+
const el = document.querySelector(
|
|
5718
|
+
`[data-ohw-section="${CSS.escape(id)}"]`
|
|
5719
|
+
);
|
|
5720
|
+
if (el) next.set(id, el.getBoundingClientRect());
|
|
5721
|
+
}
|
|
5722
|
+
return next;
|
|
5723
|
+
}
|
|
5724
|
+
function hitTestSectionId(x, y, sectionIds, rects) {
|
|
5725
|
+
for (const id of sectionIds) {
|
|
5726
|
+
const rect = rects.get(id);
|
|
5727
|
+
if (!rect || rect.width <= 0 || rect.height <= 0) continue;
|
|
5728
|
+
if (x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom) {
|
|
5729
|
+
return id;
|
|
5730
|
+
}
|
|
5731
|
+
}
|
|
5732
|
+
return null;
|
|
5733
|
+
}
|
|
5734
|
+
function useSectionRects(sectionIdsKey, enabled) {
|
|
5735
|
+
const [rects, setRects] = (0, import_react5.useState)(/* @__PURE__ */ new Map());
|
|
5736
|
+
const sectionIds = (0, import_react5.useMemo)(
|
|
5737
|
+
() => sectionIdsKey ? sectionIdsKey.split("\0") : [],
|
|
5738
|
+
[sectionIdsKey]
|
|
5739
|
+
);
|
|
5740
|
+
(0, import_react5.useEffect)(() => {
|
|
5741
|
+
if (!enabled || sectionIds.length === 0) {
|
|
5742
|
+
setRects((prev) => prev.size === 0 ? prev : /* @__PURE__ */ new Map());
|
|
5743
|
+
return;
|
|
5744
|
+
}
|
|
5745
|
+
const update = () => {
|
|
5746
|
+
const next = readSectionRects(sectionIds);
|
|
5747
|
+
setRects((prev) => rectsEqual(prev, next) ? prev : next);
|
|
5748
|
+
};
|
|
5749
|
+
update();
|
|
5750
|
+
const opts = { capture: true, passive: true };
|
|
5751
|
+
window.addEventListener("scroll", update, opts);
|
|
5752
|
+
window.addEventListener("resize", update);
|
|
5753
|
+
const vv = window.visualViewport;
|
|
5754
|
+
vv?.addEventListener("resize", update);
|
|
5755
|
+
vv?.addEventListener("scroll", update);
|
|
5756
|
+
const ro = new ResizeObserver(update);
|
|
5757
|
+
for (const id of sectionIds) {
|
|
5758
|
+
const el = document.querySelector(
|
|
5759
|
+
`[data-ohw-section="${CSS.escape(id)}"]`
|
|
5760
|
+
);
|
|
5761
|
+
if (el) ro.observe(el);
|
|
5762
|
+
}
|
|
5763
|
+
return () => {
|
|
5764
|
+
window.removeEventListener("scroll", update, opts);
|
|
5765
|
+
window.removeEventListener("resize", update);
|
|
5766
|
+
vv?.removeEventListener("resize", update);
|
|
5767
|
+
vv?.removeEventListener("scroll", update);
|
|
5768
|
+
ro.disconnect();
|
|
5769
|
+
};
|
|
5770
|
+
}, [sectionIds, enabled]);
|
|
5771
|
+
return rects;
|
|
5772
|
+
}
|
|
5773
|
+
function SectionPickerOverlay({
|
|
5774
|
+
pagePath,
|
|
5775
|
+
sections,
|
|
5776
|
+
onBack,
|
|
5777
|
+
onSelect
|
|
5778
|
+
}) {
|
|
5779
|
+
const router = (0, import_navigation.useRouter)();
|
|
5780
|
+
const pathname = (0, import_navigation.usePathname)();
|
|
5781
|
+
const [selectedId, setSelectedId] = (0, import_react5.useState)(null);
|
|
5782
|
+
const [hoveredId, setHoveredId] = (0, import_react5.useState)(null);
|
|
5783
|
+
const pointerRef = (0, import_react5.useRef)(null);
|
|
5784
|
+
const pointerScreenRef = (0, import_react5.useRef)(null);
|
|
5785
|
+
const iframeOffsetTopRef = (0, import_react5.useRef)(null);
|
|
5786
|
+
const sectionIdsRef = (0, import_react5.useRef)([]);
|
|
5787
|
+
const [chromeClip, setChromeClip] = (0, import_react5.useState)(
|
|
5788
|
+
() => ({
|
|
5789
|
+
top: 0,
|
|
5790
|
+
bottom: typeof window !== "undefined" ? window.innerHeight : 0
|
|
5791
|
+
})
|
|
5792
|
+
);
|
|
5793
|
+
const normalizedTarget = normalizePath(pagePath);
|
|
5794
|
+
const isOnTargetPage = normalizePath(pathname) === normalizedTarget;
|
|
5795
|
+
(0, import_react5.useEffect)(() => {
|
|
5796
|
+
if (isOnTargetPage) return;
|
|
5797
|
+
const search = readPreservedSearch();
|
|
5798
|
+
router.push(`${normalizedTarget}${search}`);
|
|
5799
|
+
}, [isOnTargetPage, normalizedTarget, router]);
|
|
5800
|
+
(0, import_react5.useEffect)(() => {
|
|
5801
|
+
document.documentElement.setAttribute("data-ohw-section-picking", "");
|
|
5802
|
+
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => {
|
|
5803
|
+
el.removeAttribute("data-ohw-hovered");
|
|
5804
|
+
});
|
|
5805
|
+
document.querySelectorAll("[data-ohw-state-hovered]").forEach((el) => {
|
|
5806
|
+
el.removeAttribute("data-ohw-state-hovered");
|
|
5807
|
+
});
|
|
5808
|
+
return () => {
|
|
5809
|
+
document.documentElement.removeAttribute("data-ohw-section-picking");
|
|
5810
|
+
};
|
|
5811
|
+
}, []);
|
|
5812
|
+
const liveSections = (0, import_react5.useMemo)(() => {
|
|
5813
|
+
if (!isOnTargetPage) return sections;
|
|
5814
|
+
const live = collectSectionsFromDom();
|
|
5815
|
+
if (live.length === 0) return sections;
|
|
5816
|
+
const labels = new Map(sections.map((s) => [s.id, s.label]));
|
|
5817
|
+
return live.map((s) => ({ id: s.id, label: labels.get(s.id) ?? s.label }));
|
|
5818
|
+
}, [isOnTargetPage, sections, pathname]);
|
|
5819
|
+
const sectionIdsKey = (0, import_react5.useMemo)(
|
|
5820
|
+
() => liveSections.map((s) => s.id).join("\0"),
|
|
5821
|
+
[liveSections]
|
|
5822
|
+
);
|
|
5823
|
+
const sectionIds = (0, import_react5.useMemo)(
|
|
5824
|
+
() => liveSections.map((s) => s.id),
|
|
5825
|
+
[liveSections]
|
|
5826
|
+
);
|
|
5827
|
+
sectionIdsRef.current = sectionIds;
|
|
5828
|
+
const rects = useSectionRects(sectionIdsKey, isOnTargetPage);
|
|
5829
|
+
const applyHoverAt = (0, import_react5.useCallback)(
|
|
5830
|
+
(x, y, liveRects) => {
|
|
5831
|
+
const ids = sectionIdsRef.current;
|
|
5832
|
+
const map = liveRects ?? readSectionRects(ids);
|
|
5833
|
+
const next = hitTestSectionId(x, y, ids, map);
|
|
5834
|
+
setHoveredId((prev) => prev === next ? prev : next);
|
|
5835
|
+
},
|
|
5836
|
+
[]
|
|
5837
|
+
);
|
|
5838
|
+
(0, import_react5.useEffect)(() => {
|
|
5839
|
+
const applyClip = (iframeOffsetTop, visibleCanvasTop, canvasH) => {
|
|
5840
|
+
const top = Math.max(0, visibleCanvasTop - iframeOffsetTop);
|
|
5841
|
+
const bottom = Math.min(
|
|
5842
|
+
window.innerHeight,
|
|
5843
|
+
visibleCanvasTop + canvasH - iframeOffsetTop
|
|
5844
|
+
);
|
|
5845
|
+
setChromeClip(
|
|
5846
|
+
(prev) => prev.top === top && prev.bottom === bottom ? prev : { top, bottom: Math.max(top, bottom) }
|
|
5847
|
+
);
|
|
5848
|
+
};
|
|
5849
|
+
const onParentScroll = (e) => {
|
|
5850
|
+
if (e.data?.type !== "ow:parent-scroll") return;
|
|
5851
|
+
const { iframeOffsetTop, headerH, canvasH } = e.data;
|
|
5852
|
+
applyClip(iframeOffsetTop, headerH, canvasH);
|
|
5853
|
+
iframeOffsetTopRef.current = iframeOffsetTop;
|
|
5854
|
+
if (!pointerScreenRef.current && pointerRef.current) {
|
|
5855
|
+
pointerScreenRef.current = {
|
|
5856
|
+
x: pointerRef.current.x,
|
|
5857
|
+
y: pointerRef.current.y + iframeOffsetTop
|
|
5858
|
+
};
|
|
5859
|
+
}
|
|
5860
|
+
const screen = pointerScreenRef.current;
|
|
5861
|
+
if (screen) {
|
|
5862
|
+
const next = { x: screen.x, y: screen.y - iframeOffsetTop };
|
|
5863
|
+
pointerRef.current = next;
|
|
5864
|
+
applyHoverAt(next.x, next.y);
|
|
5865
|
+
}
|
|
5866
|
+
};
|
|
5867
|
+
const onResize = () => {
|
|
5868
|
+
setChromeClip((prev) => {
|
|
5869
|
+
const bottom = Math.max(prev.top, window.innerHeight);
|
|
5870
|
+
return prev.bottom === bottom ? prev : { ...prev, bottom };
|
|
5871
|
+
});
|
|
5872
|
+
};
|
|
5873
|
+
window.addEventListener("message", onParentScroll);
|
|
5874
|
+
window.addEventListener("resize", onResize);
|
|
5875
|
+
return () => {
|
|
5876
|
+
window.removeEventListener("message", onParentScroll);
|
|
5877
|
+
window.removeEventListener("resize", onResize);
|
|
5878
|
+
};
|
|
5879
|
+
}, [applyHoverAt]);
|
|
5880
|
+
(0, import_react5.useEffect)(() => {
|
|
5881
|
+
const ptr = pointerRef.current;
|
|
5882
|
+
if (!ptr) return;
|
|
5883
|
+
applyHoverAt(ptr.x, ptr.y, rects);
|
|
5884
|
+
}, [rects, applyHoverAt]);
|
|
5885
|
+
(0, import_react5.useEffect)(() => {
|
|
5886
|
+
const rememberPointer = (clientX, clientY) => {
|
|
5887
|
+
pointerRef.current = { x: clientX, y: clientY };
|
|
5888
|
+
const top = iframeOffsetTopRef.current;
|
|
5889
|
+
if (top != null) {
|
|
5890
|
+
pointerScreenRef.current = { x: clientX, y: clientY + top };
|
|
5891
|
+
}
|
|
5892
|
+
applyHoverAt(clientX, clientY, rects);
|
|
5893
|
+
};
|
|
5894
|
+
const onPointerMove = (e) => {
|
|
5895
|
+
rememberPointer(e.clientX, e.clientY);
|
|
5896
|
+
};
|
|
5897
|
+
const onPointerSync = (e) => {
|
|
5898
|
+
if (e.data?.type !== "ow:pointer-sync") return;
|
|
5899
|
+
const { clientX, clientY } = e.data;
|
|
5900
|
+
rememberPointer(clientX, clientY);
|
|
5901
|
+
};
|
|
5902
|
+
window.addEventListener("pointermove", onPointerMove, { passive: true });
|
|
5903
|
+
window.addEventListener("message", onPointerSync);
|
|
5904
|
+
return () => {
|
|
5905
|
+
window.removeEventListener("pointermove", onPointerMove);
|
|
5906
|
+
window.removeEventListener("message", onPointerSync);
|
|
5907
|
+
};
|
|
5908
|
+
}, [rects, applyHoverAt]);
|
|
5909
|
+
const handleSelect = (0, import_react5.useCallback)(
|
|
5910
|
+
(section) => {
|
|
5911
|
+
if (selectedId) return;
|
|
5912
|
+
setSelectedId(section.id);
|
|
5913
|
+
onSelect(section);
|
|
5914
|
+
},
|
|
5915
|
+
[selectedId, onSelect]
|
|
5916
|
+
);
|
|
5917
|
+
(0, import_react5.useEffect)(() => {
|
|
5918
|
+
const onKeyDown = (e) => {
|
|
5919
|
+
if (e.key === "Escape") {
|
|
5920
|
+
e.preventDefault();
|
|
5921
|
+
e.stopPropagation();
|
|
5922
|
+
onBack();
|
|
5923
|
+
}
|
|
5924
|
+
};
|
|
5925
|
+
window.addEventListener("keydown", onKeyDown, true);
|
|
5926
|
+
return () => window.removeEventListener("keydown", onKeyDown, true);
|
|
5927
|
+
}, [onBack]);
|
|
5928
|
+
const portalRoot = typeof document !== "undefined" ? document.querySelector("[data-ohw-bridge-root]") ?? document.body : null;
|
|
5929
|
+
if (!portalRoot) return null;
|
|
5930
|
+
return (0, import_react_dom.createPortal)(
|
|
5931
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
5932
|
+
"div",
|
|
5933
|
+
{
|
|
5934
|
+
"data-ohw-section-picker": "",
|
|
5935
|
+
"data-ohw-bridge": "",
|
|
5936
|
+
className: `pointer-events-none fixed inset-0 z-[2147483647] transition-opacity duration-200 ${"opacity-100"}`,
|
|
5937
|
+
"aria-modal": true,
|
|
5938
|
+
role: "dialog",
|
|
5939
|
+
"aria-label": "Choose a section",
|
|
5940
|
+
children: [
|
|
5941
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
5942
|
+
"div",
|
|
5943
|
+
{
|
|
5944
|
+
className: "pointer-events-auto fixed left-5 z-[2]",
|
|
5945
|
+
style: { top: chromeClip.top + 20 },
|
|
5946
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
5947
|
+
Button,
|
|
5948
|
+
{
|
|
5949
|
+
type: "button",
|
|
5950
|
+
variant: "outline",
|
|
5951
|
+
size: "sm",
|
|
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",
|
|
5953
|
+
onClick: onBack,
|
|
5954
|
+
children: [
|
|
5955
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react10.ArrowLeft, { className: "size-4 shrink-0", "aria-hidden": true }),
|
|
5956
|
+
"Back"
|
|
5957
|
+
]
|
|
5958
|
+
}
|
|
5959
|
+
)
|
|
5960
|
+
}
|
|
5961
|
+
),
|
|
5962
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
5963
|
+
"div",
|
|
5964
|
+
{
|
|
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",
|
|
5966
|
+
style: {
|
|
5967
|
+
top: chromeClip.bottom - 20,
|
|
5968
|
+
transform: "translate(-50%, -100%)",
|
|
5969
|
+
backgroundColor: "var(--ohw-popover-foreground, #0c0a09)"
|
|
5970
|
+
},
|
|
5971
|
+
"data-ohw-section-picker-hint": "",
|
|
5972
|
+
children: "Click on section to select"
|
|
5973
|
+
}
|
|
5974
|
+
),
|
|
5975
|
+
!isOnTargetPage ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
5976
|
+
"div",
|
|
5977
|
+
{
|
|
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",
|
|
5979
|
+
style: { top: chromeClip.top + 64 },
|
|
5980
|
+
children: "Loading page preview\u2026"
|
|
5981
|
+
}
|
|
5982
|
+
) : null,
|
|
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,
|
|
5984
|
+
isOnTargetPage ? liveSections.map((section) => {
|
|
5985
|
+
const rect = rects.get(section.id);
|
|
5986
|
+
if (!rect || rect.width <= 0 || rect.height <= 0) return null;
|
|
5987
|
+
const isSelected = selectedId === section.id;
|
|
5988
|
+
const isHovered = hoveredId === section.id;
|
|
5989
|
+
const isLit = isSelected || isHovered;
|
|
5990
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
5991
|
+
"button",
|
|
5992
|
+
{
|
|
5993
|
+
type: "button",
|
|
5994
|
+
className: "pointer-events-auto fixed z-[1] cursor-pointer border-0 bg-transparent p-0 transition-[background-color] duration-150",
|
|
5995
|
+
style: {
|
|
5996
|
+
top: rect.top,
|
|
5997
|
+
left: rect.left,
|
|
5998
|
+
width: rect.width,
|
|
5999
|
+
height: rect.height,
|
|
6000
|
+
backgroundColor: isLit ? "transparent" : DIM_OVERLAY
|
|
6001
|
+
},
|
|
6002
|
+
"aria-label": `Select section ${section.label}`,
|
|
6003
|
+
onClick: () => handleSelect(section),
|
|
6004
|
+
children: [
|
|
6005
|
+
isLit ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
6006
|
+
"span",
|
|
6007
|
+
{
|
|
6008
|
+
className: "pointer-events-none absolute",
|
|
6009
|
+
style: {
|
|
6010
|
+
inset: 4,
|
|
6011
|
+
borderRadius: "var(--radius, 6px)",
|
|
6012
|
+
border: "1.5px dashed var(--primary, #0885FE)",
|
|
6013
|
+
boxSizing: "border-box"
|
|
6014
|
+
},
|
|
6015
|
+
"aria-hidden": true
|
|
6016
|
+
}
|
|
6017
|
+
) : null,
|
|
6018
|
+
isSelected ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
6019
|
+
"span",
|
|
6020
|
+
{
|
|
6021
|
+
className: "absolute right-3 top-3 flex size-8 items-center justify-center rounded-full text-white",
|
|
6022
|
+
style: { backgroundColor: "var(--ohw-primary, #0885fe)" },
|
|
6023
|
+
"aria-hidden": true,
|
|
6024
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react10.Check, { className: "size-5" })
|
|
6025
|
+
}
|
|
6026
|
+
) : null
|
|
6027
|
+
]
|
|
6028
|
+
},
|
|
6029
|
+
section.id
|
|
6030
|
+
);
|
|
6031
|
+
}) : null
|
|
6032
|
+
]
|
|
6033
|
+
}
|
|
6034
|
+
),
|
|
6035
|
+
portalRoot
|
|
6036
|
+
);
|
|
6037
|
+
}
|
|
6038
|
+
|
|
6039
|
+
// src/ui/link-modal/useLinkModalState.ts
|
|
6040
|
+
var import_react6 = require("react");
|
|
6041
|
+
function useLinkModalState({
|
|
6042
|
+
open,
|
|
6043
|
+
mode,
|
|
6044
|
+
pages,
|
|
6045
|
+
sections: _sections,
|
|
6046
|
+
sectionsByPath,
|
|
6047
|
+
initialTarget,
|
|
6048
|
+
existingTargets: _existingTargets,
|
|
6049
|
+
onClose,
|
|
6050
|
+
onSubmit
|
|
6051
|
+
}) {
|
|
6052
|
+
const availablePages = (0, import_react6.useMemo)(() => pages, [pages]);
|
|
6053
|
+
const [searchValue, setSearchValue] = (0, import_react6.useState)("");
|
|
6054
|
+
const [selectedPage, setSelectedPage] = (0, import_react6.useState)(null);
|
|
6055
|
+
const [selectedSection, setSelectedSection] = (0, import_react6.useState)(null);
|
|
6056
|
+
const [step, setStep] = (0, import_react6.useState)("input");
|
|
6057
|
+
const [dropdownOpen, setDropdownOpen] = (0, import_react6.useState)(false);
|
|
6058
|
+
const [urlError, setUrlError] = (0, import_react6.useState)("");
|
|
6059
|
+
const reset = (0, import_react6.useCallback)(() => {
|
|
6060
|
+
setSearchValue("");
|
|
6061
|
+
setSelectedPage(null);
|
|
6062
|
+
setSelectedSection(null);
|
|
6063
|
+
setStep("input");
|
|
6064
|
+
setDropdownOpen(false);
|
|
6065
|
+
setUrlError("");
|
|
6066
|
+
}, []);
|
|
6067
|
+
(0, import_react6.useEffect)(() => {
|
|
6068
|
+
if (!open) return;
|
|
6069
|
+
if (mode === "edit" && initialTarget) {
|
|
6070
|
+
const { pageRoute } = parseTarget(initialTarget);
|
|
6071
|
+
const targetSections = getSectionsForPath(sectionsByPath, pageRoute);
|
|
5465
6072
|
const init = getEditModeInitialState(initialTarget, pages, targetSections);
|
|
5466
6073
|
setSearchValue(init.searchValue);
|
|
5467
6074
|
setSelectedPage(init.selectedPage);
|
|
@@ -5472,12 +6079,12 @@ function useLinkModalState({
|
|
|
5472
6079
|
}
|
|
5473
6080
|
setDropdownOpen(false);
|
|
5474
6081
|
setUrlError("");
|
|
5475
|
-
}, [open, mode, initialTarget,
|
|
5476
|
-
const filteredPages = (0,
|
|
6082
|
+
}, [open, mode, initialTarget, reset]);
|
|
6083
|
+
const filteredPages = (0, import_react6.useMemo)(() => {
|
|
5477
6084
|
if (!searchValue.trim()) return availablePages;
|
|
5478
6085
|
return availablePages.filter((p) => p.title.toLowerCase().startsWith(searchValue.toLowerCase()));
|
|
5479
6086
|
}, [availablePages, searchValue]);
|
|
5480
|
-
const activeSections = (0,
|
|
6087
|
+
const activeSections = (0, import_react6.useMemo)(() => {
|
|
5481
6088
|
if (!selectedPage) return [];
|
|
5482
6089
|
return getSectionsForPath(sectionsByPath, selectedPage.path);
|
|
5483
6090
|
}, [selectedPage, sectionsByPath]);
|
|
@@ -5519,11 +6126,14 @@ function useLinkModalState({
|
|
|
5519
6126
|
const handleBackToSections = () => {
|
|
5520
6127
|
setStep("sectionPicker");
|
|
5521
6128
|
};
|
|
6129
|
+
const handleSectionPickerBack = () => {
|
|
6130
|
+
setStep("input");
|
|
6131
|
+
};
|
|
5522
6132
|
const handleClose = () => {
|
|
5523
6133
|
reset();
|
|
5524
6134
|
onClose();
|
|
5525
6135
|
};
|
|
5526
|
-
const isValid = (0,
|
|
6136
|
+
const isValid = (0, import_react6.useMemo)(() => {
|
|
5527
6137
|
if (urlError) return false;
|
|
5528
6138
|
if (showBreadcrumb) return true;
|
|
5529
6139
|
if (selectedPage) return true;
|
|
@@ -5556,7 +6166,7 @@ function useLinkModalState({
|
|
|
5556
6166
|
onSubmit(normalizeUrl(searchValue));
|
|
5557
6167
|
handleClose();
|
|
5558
6168
|
};
|
|
5559
|
-
const submitLabel = mode === "edit" ? "Save" : "Create";
|
|
6169
|
+
const submitLabel = showBreadcrumb ? "Save" : mode === "edit" ? "Save" : "Create";
|
|
5560
6170
|
const title = mode === "edit" ? "Edit navigation item" : "Create navigation item";
|
|
5561
6171
|
const secondaryLabel = showBreadcrumb ? "Back to sections" : "Cancel";
|
|
5562
6172
|
const handleSecondary = showBreadcrumb ? handleBackToSections : handleClose;
|
|
@@ -5583,23 +6193,29 @@ function useLinkModalState({
|
|
|
5583
6193
|
handleChooseSection,
|
|
5584
6194
|
handleSectionSelect,
|
|
5585
6195
|
handleBackToSections,
|
|
6196
|
+
handleSectionPickerBack,
|
|
5586
6197
|
handleClose,
|
|
5587
6198
|
handleSecondary,
|
|
5588
6199
|
handleSubmit
|
|
5589
6200
|
};
|
|
5590
6201
|
}
|
|
5591
6202
|
|
|
5592
|
-
// src/ui/link-modal/
|
|
5593
|
-
var
|
|
5594
|
-
function
|
|
6203
|
+
// src/ui/link-modal/LinkPopover.tsx
|
|
6204
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
6205
|
+
function postToParent(data) {
|
|
6206
|
+
window.parent?.postMessage(data, "*");
|
|
6207
|
+
}
|
|
6208
|
+
function LinkPopover({
|
|
5595
6209
|
open = true,
|
|
6210
|
+
panelRef,
|
|
6211
|
+
portalContainer,
|
|
6212
|
+
onClose,
|
|
5596
6213
|
mode = "create",
|
|
5597
6214
|
pages,
|
|
5598
6215
|
sections = [],
|
|
5599
6216
|
sectionsByPath,
|
|
5600
6217
|
initialTarget,
|
|
5601
6218
|
existingTargets = [],
|
|
5602
|
-
onClose,
|
|
5603
6219
|
onSubmit
|
|
5604
6220
|
}) {
|
|
5605
6221
|
const state = useLinkModalState({
|
|
@@ -5613,115 +6229,109 @@ function LinkEditorPanel({
|
|
|
5613
6229
|
onClose,
|
|
5614
6230
|
onSubmit
|
|
5615
6231
|
});
|
|
5616
|
-
const
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
6232
|
+
const sectionPickerActive = state.showSectionPicker && Boolean(state.selectedPage);
|
|
6233
|
+
(0, import_react7.useEffect)(() => {
|
|
6234
|
+
if (!open) return;
|
|
6235
|
+
if (sectionPickerActive) {
|
|
6236
|
+
postToParent({ type: "ui:unlock" });
|
|
6237
|
+
postToParent({ type: "ow:section-picker", active: true });
|
|
6238
|
+
document.documentElement.style.overflow = "";
|
|
6239
|
+
document.body.style.overflow = "";
|
|
6240
|
+
return () => {
|
|
6241
|
+
postToParent({ type: "ow:section-picker", active: false });
|
|
6242
|
+
};
|
|
6243
|
+
}
|
|
6244
|
+
postToParent({ type: "ow:section-picker", active: false });
|
|
6245
|
+
postToParent({ type: "ui:lock" });
|
|
6246
|
+
const html = document.documentElement;
|
|
6247
|
+
const body = document.body;
|
|
6248
|
+
const prevHtmlOverflow = html.style.overflow;
|
|
6249
|
+
const prevBodyOverflow = body.style.overflow;
|
|
6250
|
+
const prevHtmlOverscroll = html.style.overscrollBehavior;
|
|
6251
|
+
const prevBodyOverscroll = body.style.overscrollBehavior;
|
|
6252
|
+
html.style.overflow = "hidden";
|
|
6253
|
+
body.style.overflow = "hidden";
|
|
6254
|
+
html.style.overscrollBehavior = "none";
|
|
6255
|
+
body.style.overscrollBehavior = "none";
|
|
6256
|
+
const canScrollElement = (el, deltaY) => {
|
|
6257
|
+
const { overflowY } = getComputedStyle(el);
|
|
6258
|
+
if (overflowY !== "auto" && overflowY !== "scroll") return false;
|
|
6259
|
+
if (el.scrollHeight <= el.clientHeight + 1) return false;
|
|
6260
|
+
if (deltaY < 0) return el.scrollTop > 0;
|
|
6261
|
+
if (deltaY > 0)
|
|
6262
|
+
return el.scrollTop + el.clientHeight < el.scrollHeight - 1;
|
|
6263
|
+
return true;
|
|
6264
|
+
};
|
|
6265
|
+
const allowsInternalScroll = (e) => {
|
|
6266
|
+
const target = e.target;
|
|
6267
|
+
if (!(target instanceof Element)) return false;
|
|
6268
|
+
const scrollRoot = target.closest(
|
|
6269
|
+
"[data-ohw-link-page-dropdown], [data-ohw-allow-scroll]"
|
|
6270
|
+
);
|
|
6271
|
+
if (!scrollRoot) return false;
|
|
6272
|
+
const deltaY = e instanceof WheelEvent ? e.deltaY : 0;
|
|
6273
|
+
return canScrollElement(scrollRoot, deltaY);
|
|
6274
|
+
};
|
|
6275
|
+
const preventBackgroundScroll = (e) => {
|
|
6276
|
+
if (allowsInternalScroll(e)) return;
|
|
6277
|
+
e.preventDefault();
|
|
6278
|
+
};
|
|
6279
|
+
const scrollOpts = { passive: false, capture: true };
|
|
6280
|
+
document.addEventListener("wheel", preventBackgroundScroll, scrollOpts);
|
|
6281
|
+
document.addEventListener("touchmove", preventBackgroundScroll, scrollOpts);
|
|
6282
|
+
return () => {
|
|
6283
|
+
postToParent({ type: "ui:unlock" });
|
|
6284
|
+
html.style.overflow = prevHtmlOverflow;
|
|
6285
|
+
body.style.overflow = prevBodyOverflow;
|
|
6286
|
+
html.style.overscrollBehavior = prevHtmlOverscroll;
|
|
6287
|
+
body.style.overscrollBehavior = prevBodyOverscroll;
|
|
6288
|
+
document.removeEventListener(
|
|
6289
|
+
"wheel",
|
|
6290
|
+
preventBackgroundScroll,
|
|
6291
|
+
scrollOpts
|
|
6292
|
+
);
|
|
6293
|
+
document.removeEventListener(
|
|
6294
|
+
"touchmove",
|
|
6295
|
+
preventBackgroundScroll,
|
|
6296
|
+
scrollOpts
|
|
6297
|
+
);
|
|
6298
|
+
};
|
|
6299
|
+
}, [open, sectionPickerActive]);
|
|
6300
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
6301
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6302
|
+
Dialog2,
|
|
5620
6303
|
{
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
6304
|
+
open: open && !sectionPickerActive,
|
|
6305
|
+
onOpenChange: (next) => {
|
|
6306
|
+
if (!next) onClose?.();
|
|
6307
|
+
},
|
|
6308
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6309
|
+
DialogContent,
|
|
6310
|
+
{
|
|
6311
|
+
ref: panelRef,
|
|
6312
|
+
container: portalContainer,
|
|
6313
|
+
"data-ohw-link-popover-root": "",
|
|
6314
|
+
"data-ohw-link-modal-root": "",
|
|
6315
|
+
"data-ohw-bridge": "",
|
|
6316
|
+
showCloseButton: false,
|
|
6317
|
+
className: "gap-0 p-0 w-full max-w-[448px] pointer-events-auto z-[2147483646] overflow-visible",
|
|
6318
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LinkEditorPanel, { state, onClose })
|
|
6319
|
+
}
|
|
6320
|
+
)
|
|
5625
6321
|
}
|
|
5626
|
-
)
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
UrlOrPageInput,
|
|
5637
|
-
{
|
|
5638
|
-
value: state.searchValue,
|
|
5639
|
-
selectedPage: state.selectedPage,
|
|
5640
|
-
dropdownOpen: state.dropdownOpen,
|
|
5641
|
-
onDropdownOpenChange: state.setDropdownOpen,
|
|
5642
|
-
filteredPages: state.filteredPages,
|
|
5643
|
-
onInputChange: state.handleInputChange,
|
|
5644
|
-
onPageSelect: state.handlePageSelect,
|
|
5645
|
-
urlError: state.urlError
|
|
5646
|
-
}
|
|
5647
|
-
),
|
|
5648
|
-
state.showChooseSection ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex flex-col justify-center gap-2", children: [
|
|
5649
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Button, { type: "button", variant: "outline", className: "w-fit cursor-pointer", size: "sm", onClick: state.handleChooseSection, children: "Choose a section" }),
|
|
5650
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
|
|
5651
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(IconInfo, { className: "shrink-0", "aria-hidden": true }),
|
|
5652
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: "Pick a section this link should scroll to." })
|
|
5653
|
-
] })
|
|
5654
|
-
] }) : null,
|
|
5655
|
-
state.showSectionPicker ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(SectionPickerList, { sections: state.activeSections, onSelect: state.handleSectionSelect }) : null,
|
|
5656
|
-
state.showSectionRow && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
|
|
5657
|
-
] }),
|
|
5658
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(DialogFooter, { className: "w-full px-6 pb-6", children: [
|
|
5659
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5660
|
-
Button,
|
|
5661
|
-
{
|
|
5662
|
-
type: "button",
|
|
5663
|
-
variant: isCancel ? "outline" : "ghost",
|
|
5664
|
-
className: "leading-6 shadow-none cursor-pointer",
|
|
5665
|
-
style: isCancel ? {
|
|
5666
|
-
backgroundColor: "var(--ohw-background)",
|
|
5667
|
-
borderColor: "var(--ohw-border)",
|
|
5668
|
-
color: "var(--ohw-foreground)"
|
|
5669
|
-
} : void 0,
|
|
5670
|
-
onClick: state.handleSecondary,
|
|
5671
|
-
children: state.secondaryLabel
|
|
5672
|
-
}
|
|
5673
|
-
),
|
|
5674
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5675
|
-
Button,
|
|
5676
|
-
{
|
|
5677
|
-
type: "button",
|
|
5678
|
-
className: "border-0 leading-6 shadow-none hover:opacity-90 disabled:opacity-50 cursor-pointer",
|
|
5679
|
-
style: {
|
|
5680
|
-
backgroundColor: "var(--ohw-primary)",
|
|
5681
|
-
color: "var(--ohw-primary-foreground)"
|
|
5682
|
-
},
|
|
5683
|
-
disabled: !state.isValid,
|
|
5684
|
-
onClick: state.handleSubmit,
|
|
5685
|
-
children: state.submitLabel
|
|
5686
|
-
}
|
|
5687
|
-
)
|
|
5688
|
-
] })
|
|
6322
|
+
),
|
|
6323
|
+
sectionPickerActive && state.selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6324
|
+
SectionPickerOverlay,
|
|
6325
|
+
{
|
|
6326
|
+
pagePath: state.selectedPage.path,
|
|
6327
|
+
sections: state.activeSections,
|
|
6328
|
+
onBack: state.handleSectionPickerBack,
|
|
6329
|
+
onSelect: state.handleSectionSelect
|
|
6330
|
+
}
|
|
6331
|
+
) : null
|
|
5689
6332
|
] });
|
|
5690
6333
|
}
|
|
5691
6334
|
|
|
5692
|
-
// src/ui/link-modal/LinkPopover.tsx
|
|
5693
|
-
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
5694
|
-
function LinkPopover({
|
|
5695
|
-
open = true,
|
|
5696
|
-
panelRef,
|
|
5697
|
-
portalContainer,
|
|
5698
|
-
onClose,
|
|
5699
|
-
...editorProps
|
|
5700
|
-
}) {
|
|
5701
|
-
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
5702
|
-
Dialog2,
|
|
5703
|
-
{
|
|
5704
|
-
open,
|
|
5705
|
-
onOpenChange: (next) => {
|
|
5706
|
-
if (!next) onClose?.();
|
|
5707
|
-
},
|
|
5708
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
5709
|
-
DialogContent,
|
|
5710
|
-
{
|
|
5711
|
-
ref: panelRef,
|
|
5712
|
-
container: portalContainer,
|
|
5713
|
-
"data-ohw-link-popover-root": "",
|
|
5714
|
-
"data-ohw-link-modal-root": "",
|
|
5715
|
-
"data-ohw-bridge": "",
|
|
5716
|
-
showCloseButton: false,
|
|
5717
|
-
className: "gap-0 p-0 w-full md:w-md pointer-events-auto",
|
|
5718
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(LinkEditorPanel, { ...editorProps, open, onClose })
|
|
5719
|
-
}
|
|
5720
|
-
)
|
|
5721
|
-
}
|
|
5722
|
-
);
|
|
5723
|
-
}
|
|
5724
|
-
|
|
5725
6335
|
// src/ui/link-modal/devFixtures.ts
|
|
5726
6336
|
var DEV_SITE_PAGES = [
|
|
5727
6337
|
{ path: "/", title: "Home" },
|
|
@@ -5741,16 +6351,21 @@ var DEV_SECTIONS_BY_PATH = {
|
|
|
5741
6351
|
{ id: "founder-teaser", label: "Founder" },
|
|
5742
6352
|
{ id: "plan-form", label: "Plan Form" },
|
|
5743
6353
|
{ id: "testimonials", label: "Testimonials" },
|
|
5744
|
-
{ id: "wordmark", label: "Wordmark" }
|
|
6354
|
+
{ id: "wordmark", label: "Wordmark" },
|
|
6355
|
+
{ id: "footer", label: "Footer" }
|
|
5745
6356
|
],
|
|
5746
6357
|
"/about": [
|
|
5747
6358
|
{ id: "manifesto", label: "Manifesto" },
|
|
5748
6359
|
{ id: "story-letter", label: "Our Story" },
|
|
5749
6360
|
{ id: "lagree-explainer", label: "Lagree Explainer" },
|
|
5750
6361
|
{ id: "waitlist-cta", label: "Waitlist" },
|
|
5751
|
-
{ id: "personal-training", label: "Personal training" }
|
|
6362
|
+
{ id: "personal-training", label: "Personal training" },
|
|
6363
|
+
{ id: "footer", label: "Footer" }
|
|
6364
|
+
],
|
|
6365
|
+
"/classes": [
|
|
6366
|
+
{ id: "class-library", label: "Class Library" },
|
|
6367
|
+
{ id: "footer", label: "Footer" }
|
|
5752
6368
|
],
|
|
5753
|
-
"/classes": [{ id: "class-library", label: "Class Library" }],
|
|
5754
6369
|
"/pricing": [
|
|
5755
6370
|
{ id: "page-header", label: "Page Header" },
|
|
5756
6371
|
{ id: "free-class-cta", label: "Free Class" },
|
|
@@ -5758,19 +6373,25 @@ var DEV_SECTIONS_BY_PATH = {
|
|
|
5758
6373
|
{ id: "monthly-memberships", label: "Memberships" },
|
|
5759
6374
|
{ id: "specialty-programs", label: "Specialty Programs" },
|
|
5760
6375
|
{ id: "package-matcher", label: "Packages" },
|
|
5761
|
-
{ id: "wordmark", label: "Wordmark" }
|
|
6376
|
+
{ id: "wordmark", label: "Wordmark" },
|
|
6377
|
+
{ id: "footer", label: "Footer" }
|
|
5762
6378
|
],
|
|
5763
6379
|
"/studio": [
|
|
5764
6380
|
{ id: "studio-intro", label: "Studio Intro" },
|
|
5765
6381
|
{ id: "studio-features", label: "Studio Features" },
|
|
5766
6382
|
{ id: "studio-gallery", label: "Studio Gallery" },
|
|
5767
|
-
{ id: "studio-visit", label: "Visit Studio" }
|
|
6383
|
+
{ id: "studio-visit", label: "Visit Studio" },
|
|
6384
|
+
{ id: "footer", label: "Footer" }
|
|
6385
|
+
],
|
|
6386
|
+
"/instructors": [
|
|
6387
|
+
{ id: "instructor-grid", label: "Instructors" },
|
|
6388
|
+
{ id: "footer", label: "Footer" }
|
|
5768
6389
|
],
|
|
5769
|
-
"/instructors": [{ id: "instructor-grid", label: "Instructors" }],
|
|
5770
6390
|
"/contact": [
|
|
5771
6391
|
{ id: "hello-hero", label: "Hello" },
|
|
5772
6392
|
{ id: "contact-form", label: "Contact Form" },
|
|
5773
|
-
{ id: "faq", label: "FAQ" }
|
|
6393
|
+
{ id: "faq", label: "FAQ" },
|
|
6394
|
+
{ id: "footer", label: "Footer" }
|
|
5774
6395
|
]
|
|
5775
6396
|
};
|
|
5776
6397
|
function shouldUseDevFixtures() {
|
|
@@ -5780,8 +6401,716 @@ function shouldUseDevFixtures() {
|
|
|
5780
6401
|
return new URLSearchParams(q).get("ohw-fixtures") === "1";
|
|
5781
6402
|
}
|
|
5782
6403
|
|
|
6404
|
+
// src/lib/nav-items.ts
|
|
6405
|
+
var NAV_COUNT_KEY = "__ohw_nav_count";
|
|
6406
|
+
var NAV_ORDER_KEY = "__ohw_nav_order";
|
|
6407
|
+
function getLinkHref(el) {
|
|
6408
|
+
const key = el.getAttribute("data-ohw-href-key");
|
|
6409
|
+
if (key) {
|
|
6410
|
+
const stored = getStoredLinkHref(key);
|
|
6411
|
+
if (stored !== void 0) return stored;
|
|
6412
|
+
}
|
|
6413
|
+
return el.getAttribute("href") ?? "";
|
|
6414
|
+
}
|
|
6415
|
+
function isNavbarButton(el) {
|
|
6416
|
+
return el.hasAttribute("data-ohw-role") && el.getAttribute("data-ohw-role") === "navbar-button";
|
|
6417
|
+
}
|
|
6418
|
+
function isNavbarLinkItem(el) {
|
|
6419
|
+
if (!el.matches("[data-ohw-href-key]")) return false;
|
|
6420
|
+
if (isNavbarButton(el)) return false;
|
|
6421
|
+
if (!el.querySelector('[data-ohw-editable="text"]')) return false;
|
|
6422
|
+
return Boolean(el.closest("nav, [data-ohw-nav-container], [data-ohw-nav-drawer]"));
|
|
6423
|
+
}
|
|
6424
|
+
function getNavbarDesktopContainer() {
|
|
6425
|
+
return document.querySelector("[data-ohw-nav-container]");
|
|
6426
|
+
}
|
|
6427
|
+
function getNavbarDrawerContainer() {
|
|
6428
|
+
return document.querySelector("[data-ohw-nav-drawer]");
|
|
6429
|
+
}
|
|
6430
|
+
function listNavbarItems() {
|
|
6431
|
+
const desktop = getNavbarDesktopContainer();
|
|
6432
|
+
if (desktop) {
|
|
6433
|
+
return Array.from(desktop.querySelectorAll("[data-ohw-href-key]")).filter(isNavbarLinkItem);
|
|
6434
|
+
}
|
|
6435
|
+
const drawer = getNavbarDrawerContainer();
|
|
6436
|
+
if (drawer) {
|
|
6437
|
+
return Array.from(drawer.querySelectorAll("[data-ohw-href-key]")).filter(isNavbarLinkItem);
|
|
6438
|
+
}
|
|
6439
|
+
return Array.from(document.querySelectorAll("nav [data-ohw-href-key]")).filter(isNavbarLinkItem);
|
|
6440
|
+
}
|
|
6441
|
+
function parseNavIndexFromKey(key) {
|
|
6442
|
+
if (!key) return null;
|
|
6443
|
+
const match = key.match(/^nav-(\d+)-href$/);
|
|
6444
|
+
if (!match) return null;
|
|
6445
|
+
return parseInt(match[1], 10);
|
|
6446
|
+
}
|
|
6447
|
+
function getNavbarIndicesInDom() {
|
|
6448
|
+
const indices = /* @__PURE__ */ new Set();
|
|
6449
|
+
for (const item of listNavbarItems()) {
|
|
6450
|
+
const idx = parseNavIndexFromKey(item.getAttribute("data-ohw-href-key"));
|
|
6451
|
+
if (idx !== null) indices.add(idx);
|
|
6452
|
+
}
|
|
6453
|
+
return [...indices].sort((a, b) => a - b);
|
|
6454
|
+
}
|
|
6455
|
+
function getNextNavbarIndex() {
|
|
6456
|
+
const indices = getNavbarIndicesInDom();
|
|
6457
|
+
if (indices.length === 0) return 0;
|
|
6458
|
+
return Math.max(...indices) + 1;
|
|
6459
|
+
}
|
|
6460
|
+
function getNavbarExistingTargets() {
|
|
6461
|
+
return listNavbarItems().map((el) => getLinkHref(el)).filter(Boolean);
|
|
6462
|
+
}
|
|
6463
|
+
function getNavOrderFromDom() {
|
|
6464
|
+
return listNavbarItems().map((el) => el.getAttribute("data-ohw-href-key")).filter((key) => Boolean(key));
|
|
6465
|
+
}
|
|
6466
|
+
function parseNavOrder(content) {
|
|
6467
|
+
const raw = content[NAV_ORDER_KEY];
|
|
6468
|
+
if (!raw) return null;
|
|
6469
|
+
try {
|
|
6470
|
+
const parsed = JSON.parse(raw);
|
|
6471
|
+
if (!Array.isArray(parsed)) return null;
|
|
6472
|
+
return parsed.filter((key) => typeof key === "string" && key.length > 0);
|
|
6473
|
+
} catch {
|
|
6474
|
+
return null;
|
|
6475
|
+
}
|
|
6476
|
+
}
|
|
6477
|
+
function findCounterpartByHrefKey(hrefKey, root) {
|
|
6478
|
+
return root.querySelector(`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`);
|
|
6479
|
+
}
|
|
6480
|
+
function cloneNavLinkShell(template) {
|
|
6481
|
+
const anchor = document.createElement("a");
|
|
6482
|
+
if (template) {
|
|
6483
|
+
anchor.style.cssText = template.style.cssText;
|
|
6484
|
+
if (template.className) anchor.className = template.className;
|
|
6485
|
+
}
|
|
6486
|
+
anchor.style.cursor = "pointer";
|
|
6487
|
+
anchor.style.textDecoration = "none";
|
|
6488
|
+
return anchor;
|
|
6489
|
+
}
|
|
6490
|
+
function buildNavLink(index, href, label, template) {
|
|
6491
|
+
const anchor = cloneNavLinkShell(template);
|
|
6492
|
+
anchor.href = href;
|
|
6493
|
+
anchor.setAttribute("data-ohw-href-key", `nav-${index}-href`);
|
|
6494
|
+
const span = document.createElement("span");
|
|
6495
|
+
span.setAttribute("data-ohw-editable", "text");
|
|
6496
|
+
span.setAttribute("data-ohw-key", `nav-${index}-label`);
|
|
6497
|
+
span.textContent = label;
|
|
6498
|
+
anchor.appendChild(span);
|
|
6499
|
+
return anchor;
|
|
6500
|
+
}
|
|
6501
|
+
function insertNavLinkInContainer(container, anchor, afterHrefKey) {
|
|
6502
|
+
if (!afterHrefKey) {
|
|
6503
|
+
container.appendChild(anchor);
|
|
6504
|
+
return;
|
|
6505
|
+
}
|
|
6506
|
+
const afterEl = findCounterpartByHrefKey(afterHrefKey, container);
|
|
6507
|
+
if (afterEl?.parentElement === container) {
|
|
6508
|
+
afterEl.insertAdjacentElement("afterend", anchor);
|
|
6509
|
+
return;
|
|
6510
|
+
}
|
|
6511
|
+
container.appendChild(anchor);
|
|
6512
|
+
}
|
|
6513
|
+
function insertNavbarItemDom(index, href, label, afterAnchor) {
|
|
6514
|
+
const afterHrefKey = afterAnchor?.getAttribute("data-ohw-href-key") ?? null;
|
|
6515
|
+
const desktopItems = getNavbarDesktopContainer()?.querySelectorAll("[data-ohw-href-key]") ?? [];
|
|
6516
|
+
const drawerItems = getNavbarDrawerContainer()?.querySelectorAll("[data-ohw-href-key]") ?? [];
|
|
6517
|
+
const desktopTemplate = Array.from(desktopItems).find(isNavbarLinkItem) ?? null;
|
|
6518
|
+
const drawerTemplate = Array.from(drawerItems).find(isNavbarLinkItem) ?? null;
|
|
6519
|
+
let primary = null;
|
|
6520
|
+
const desktopContainer = getNavbarDesktopContainer();
|
|
6521
|
+
if (desktopContainer) {
|
|
6522
|
+
const desktopAnchor = buildNavLink(index, href, label, desktopTemplate);
|
|
6523
|
+
insertNavLinkInContainer(desktopContainer, desktopAnchor, afterHrefKey);
|
|
6524
|
+
primary = desktopAnchor;
|
|
6525
|
+
}
|
|
6526
|
+
const drawerContainer = getNavbarDrawerContainer();
|
|
6527
|
+
if (drawerContainer) {
|
|
6528
|
+
const drawerAnchor = buildNavLink(index, href, label, drawerTemplate);
|
|
6529
|
+
insertNavLinkInContainer(drawerContainer, drawerAnchor, afterHrefKey);
|
|
6530
|
+
if (!primary) primary = drawerAnchor;
|
|
6531
|
+
}
|
|
6532
|
+
if (!primary) {
|
|
6533
|
+
const fallback = buildNavLink(index, href, label, listNavbarItems()[0] ?? null);
|
|
6534
|
+
const nav = document.querySelector("nav");
|
|
6535
|
+
nav?.appendChild(fallback);
|
|
6536
|
+
primary = fallback;
|
|
6537
|
+
}
|
|
6538
|
+
return primary;
|
|
6539
|
+
}
|
|
6540
|
+
function applyNavOrderToContainer(container, order) {
|
|
6541
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6542
|
+
for (const hrefKey of order) {
|
|
6543
|
+
if (seen.has(hrefKey)) continue;
|
|
6544
|
+
seen.add(hrefKey);
|
|
6545
|
+
const el = findCounterpartByHrefKey(hrefKey, container);
|
|
6546
|
+
if (el) container.appendChild(el);
|
|
6547
|
+
}
|
|
6548
|
+
for (const el of container.querySelectorAll("[data-ohw-href-key]")) {
|
|
6549
|
+
if (!isNavbarLinkItem(el)) continue;
|
|
6550
|
+
const key = el.getAttribute("data-ohw-href-key");
|
|
6551
|
+
if (!key || seen.has(key)) continue;
|
|
6552
|
+
container.appendChild(el);
|
|
6553
|
+
}
|
|
6554
|
+
}
|
|
6555
|
+
function applyNavOrder(order) {
|
|
6556
|
+
const desktop = getNavbarDesktopContainer();
|
|
6557
|
+
if (desktop) applyNavOrderToContainer(desktop, order);
|
|
6558
|
+
const drawer = getNavbarDrawerContainer();
|
|
6559
|
+
if (drawer) applyNavOrderToContainer(drawer, order);
|
|
6560
|
+
}
|
|
6561
|
+
function collectNavbarIndicesFromContent(content) {
|
|
6562
|
+
const indices = /* @__PURE__ */ new Set();
|
|
6563
|
+
for (const key of Object.keys(content)) {
|
|
6564
|
+
const idx = parseNavIndexFromKey(key);
|
|
6565
|
+
if (idx !== null) indices.add(idx);
|
|
6566
|
+
}
|
|
6567
|
+
const countRaw = content[NAV_COUNT_KEY];
|
|
6568
|
+
if (countRaw) {
|
|
6569
|
+
const count = parseInt(countRaw, 10);
|
|
6570
|
+
if (Number.isFinite(count) && count > 0) {
|
|
6571
|
+
for (let i = 0; i < count; i++) indices.add(i);
|
|
6572
|
+
}
|
|
6573
|
+
}
|
|
6574
|
+
return [...indices].sort((a, b) => a - b);
|
|
6575
|
+
}
|
|
6576
|
+
function navbarIndexExistsInDom(index) {
|
|
6577
|
+
return document.querySelector(`[data-ohw-href-key="nav-${index}-href"]`) !== null;
|
|
6578
|
+
}
|
|
6579
|
+
function reconcileNavbarItemsFromContent(content) {
|
|
6580
|
+
const indices = collectNavbarIndicesFromContent(content);
|
|
6581
|
+
for (const index of indices) {
|
|
6582
|
+
if (navbarIndexExistsInDom(index)) continue;
|
|
6583
|
+
const href = content[`nav-${index}-href`];
|
|
6584
|
+
const label = content[`nav-${index}-label`];
|
|
6585
|
+
if (!href && !label) continue;
|
|
6586
|
+
insertNavbarItemDom(index, href ?? "/", label ?? "Untitled", null);
|
|
6587
|
+
}
|
|
6588
|
+
const order = parseNavOrder(content);
|
|
6589
|
+
if (order?.length) applyNavOrder(order);
|
|
6590
|
+
}
|
|
6591
|
+
function buildNavOrderAfterInsert(afterAnchor, newHrefKey) {
|
|
6592
|
+
const order = getNavOrderFromDom();
|
|
6593
|
+
if (!afterAnchor) {
|
|
6594
|
+
if (!order.includes(newHrefKey)) order.push(newHrefKey);
|
|
6595
|
+
return order;
|
|
6596
|
+
}
|
|
6597
|
+
const afterKey = afterAnchor.getAttribute("data-ohw-href-key");
|
|
6598
|
+
if (!afterKey) {
|
|
6599
|
+
if (!order.includes(newHrefKey)) order.push(newHrefKey);
|
|
6600
|
+
return order;
|
|
6601
|
+
}
|
|
6602
|
+
const withoutNew = order.filter((key) => key !== newHrefKey);
|
|
6603
|
+
const pos = withoutNew.indexOf(afterKey);
|
|
6604
|
+
if (pos >= 0) {
|
|
6605
|
+
withoutNew.splice(pos + 1, 0, newHrefKey);
|
|
6606
|
+
return withoutNew;
|
|
6607
|
+
}
|
|
6608
|
+
withoutNew.push(newHrefKey);
|
|
6609
|
+
return withoutNew;
|
|
6610
|
+
}
|
|
6611
|
+
function insertNavbarItem(href, label, afterAnchor = null) {
|
|
6612
|
+
const index = getNextNavbarIndex();
|
|
6613
|
+
const anchor = insertNavbarItemDom(index, href, label, afterAnchor);
|
|
6614
|
+
if (!anchor) throw new Error("Failed to insert navbar item");
|
|
6615
|
+
const hrefKey = `nav-${index}-href`;
|
|
6616
|
+
const order = buildNavOrderAfterInsert(afterAnchor, hrefKey);
|
|
6617
|
+
applyNavOrder(order);
|
|
6618
|
+
return {
|
|
6619
|
+
anchor,
|
|
6620
|
+
index,
|
|
6621
|
+
hrefKey,
|
|
6622
|
+
labelKey: `nav-${index}-label`,
|
|
6623
|
+
href,
|
|
6624
|
+
label,
|
|
6625
|
+
order
|
|
6626
|
+
};
|
|
6627
|
+
}
|
|
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
|
+
|
|
7026
|
+
// src/ui/navbar-container-chrome.tsx
|
|
7027
|
+
var import_lucide_react11 = require("lucide-react");
|
|
7028
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
7029
|
+
function NavbarContainerChrome({
|
|
7030
|
+
rect,
|
|
7031
|
+
onAdd
|
|
7032
|
+
}) {
|
|
7033
|
+
const chromeGap = 6;
|
|
7034
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7035
|
+
"div",
|
|
7036
|
+
{
|
|
7037
|
+
"data-ohw-navbar-container-chrome": "",
|
|
7038
|
+
"data-ohw-bridge": "",
|
|
7039
|
+
className: "pointer-events-none fixed z-[2147483647]",
|
|
7040
|
+
style: {
|
|
7041
|
+
top: rect.top - chromeGap,
|
|
7042
|
+
left: rect.left - chromeGap,
|
|
7043
|
+
width: rect.width + chromeGap * 2,
|
|
7044
|
+
height: rect.height + chromeGap * 2
|
|
7045
|
+
},
|
|
7046
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7047
|
+
"button",
|
|
7048
|
+
{
|
|
7049
|
+
type: "button",
|
|
7050
|
+
"data-ohw-navbar-add-button": "",
|
|
7051
|
+
className: "pointer-events-auto absolute left-1/2 flex p-0.5 rounded-[10px] size-7 -translate-x-1/2 translate-y-1/2 items-center justify-center border border-border bg-background shadow-sm transition-colors hover:bg-muted/80",
|
|
7052
|
+
style: { top: "70%" },
|
|
7053
|
+
"aria-label": "Add item",
|
|
7054
|
+
onMouseDown: (e) => {
|
|
7055
|
+
e.preventDefault();
|
|
7056
|
+
e.stopPropagation();
|
|
7057
|
+
},
|
|
7058
|
+
onClick: (e) => {
|
|
7059
|
+
e.preventDefault();
|
|
7060
|
+
e.stopPropagation();
|
|
7061
|
+
onAdd();
|
|
7062
|
+
},
|
|
7063
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react11.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
7064
|
+
}
|
|
7065
|
+
)
|
|
7066
|
+
}
|
|
7067
|
+
);
|
|
7068
|
+
}
|
|
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
|
+
|
|
5783
7112
|
// src/ui/badge.tsx
|
|
5784
|
-
var
|
|
7113
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
5785
7114
|
var badgeVariants = cva(
|
|
5786
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",
|
|
5787
7116
|
{
|
|
@@ -5799,12 +7128,12 @@ var badgeVariants = cva(
|
|
|
5799
7128
|
}
|
|
5800
7129
|
);
|
|
5801
7130
|
function Badge({ className, variant, ...props }) {
|
|
5802
|
-
return /* @__PURE__ */ (0,
|
|
7131
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
5803
7132
|
}
|
|
5804
7133
|
|
|
5805
7134
|
// src/OhhwellsBridge.tsx
|
|
5806
|
-
var
|
|
5807
|
-
var
|
|
7135
|
+
var import_lucide_react12 = require("lucide-react");
|
|
7136
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
5808
7137
|
var PRIMARY2 = "#0885FE";
|
|
5809
7138
|
var IMAGE_FADE_MS = 300;
|
|
5810
7139
|
function runOpacityFade(el, onDone) {
|
|
@@ -5981,9 +7310,9 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
5981
7310
|
tail.insertAdjacentElement("afterend", container);
|
|
5982
7311
|
}
|
|
5983
7312
|
const root = (0, import_client.createRoot)(container);
|
|
5984
|
-
(0,
|
|
7313
|
+
(0, import_react_dom2.flushSync)(() => {
|
|
5985
7314
|
root.render(
|
|
5986
|
-
/* @__PURE__ */ (0,
|
|
7315
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
5987
7316
|
SchedulingWidget,
|
|
5988
7317
|
{
|
|
5989
7318
|
notifyOnConnect,
|
|
@@ -6023,7 +7352,7 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
|
|
|
6023
7352
|
}
|
|
6024
7353
|
}
|
|
6025
7354
|
}
|
|
6026
|
-
function
|
|
7355
|
+
function getLinkHref2(el) {
|
|
6027
7356
|
const anchor = el instanceof HTMLAnchorElement ? el : el.querySelector("a");
|
|
6028
7357
|
return anchor?.getAttribute("href") ?? "";
|
|
6029
7358
|
}
|
|
@@ -6045,7 +7374,7 @@ function isDragHandleDisabled(el) {
|
|
|
6045
7374
|
return raw === "true" || raw === "";
|
|
6046
7375
|
});
|
|
6047
7376
|
}
|
|
6048
|
-
function collectEditableNodes() {
|
|
7377
|
+
function collectEditableNodes(extraContent) {
|
|
6049
7378
|
const nodes = Array.from(document.querySelectorAll("[data-ohw-editable]")).map((el) => {
|
|
6050
7379
|
if (el.dataset.ohwEditable === "image") {
|
|
6051
7380
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
@@ -6060,7 +7389,7 @@ function collectEditableNodes() {
|
|
|
6060
7389
|
return { key: el.dataset.ohwKey ?? "", type: "video", text: getVideoEl(el)?.src ?? "" };
|
|
6061
7390
|
}
|
|
6062
7391
|
if (el.dataset.ohwEditable === "link") {
|
|
6063
|
-
return { key: el.dataset.ohwKey ?? "", type: "link", text:
|
|
7392
|
+
return { key: el.dataset.ohwKey ?? "", type: "link", text: getLinkHref2(el) };
|
|
6064
7393
|
}
|
|
6065
7394
|
return {
|
|
6066
7395
|
key: el.dataset.ohwKey ?? "",
|
|
@@ -6071,8 +7400,16 @@ function collectEditableNodes() {
|
|
|
6071
7400
|
document.querySelectorAll("[data-ohw-href-key]").forEach((el) => {
|
|
6072
7401
|
const key = el.getAttribute("data-ohw-href-key") ?? "";
|
|
6073
7402
|
if (!key) return;
|
|
6074
|
-
nodes.push({ key, type: "link", text:
|
|
7403
|
+
nodes.push({ key, type: "link", text: getLinkHref2(el) });
|
|
6075
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
|
+
}
|
|
6076
7413
|
document.querySelectorAll('[data-ohw-editable="video"]').forEach((el) => {
|
|
6077
7414
|
const key = el.dataset.ohwKey ?? "";
|
|
6078
7415
|
const video = getVideoEl(el);
|
|
@@ -6080,6 +7417,9 @@ function collectEditableNodes() {
|
|
|
6080
7417
|
nodes.push({ key: `${key}${VIDEO_AUTOPLAY_SUFFIX}`, type: "video-setting", text: String(video.autoplay) });
|
|
6081
7418
|
nodes.push({ key: `${key}${VIDEO_MUTED_SUFFIX}`, type: "video-setting", text: String(video.muted) });
|
|
6082
7419
|
});
|
|
7420
|
+
for (const key of listCarouselKeys()) {
|
|
7421
|
+
nodes.push({ key, type: "carousel", text: JSON.stringify(readCarouselValue(key)) });
|
|
7422
|
+
}
|
|
6083
7423
|
return nodes;
|
|
6084
7424
|
}
|
|
6085
7425
|
function isMediaEditable(el) {
|
|
@@ -6157,7 +7497,7 @@ function applyLinkByKey(key, val) {
|
|
|
6157
7497
|
}
|
|
6158
7498
|
function isInsideLinkEditor(target) {
|
|
6159
7499
|
return Boolean(
|
|
6160
|
-
target.closest("[data-ohw-link-popover-root]") || target.closest("[data-ohw-link-modal-root]") || target.closest("[data-ohw-link-page-dropdown]") || target.closest('[data-slot="popover-content"]') || target.closest('[data-slot="dialog-content"]') || target.closest('[data-slot="dialog-overlay"]')
|
|
7500
|
+
target.closest("[data-ohw-link-popover-root]") || target.closest("[data-ohw-link-modal-root]") || target.closest("[data-ohw-link-page-dropdown]") || target.closest("[data-ohw-section-picker]") || target.closest("[data-ohw-navbar-container-chrome]") || target.closest("[data-ohw-navbar-add-button]") || target.closest('[data-slot="popover-content"]') || target.closest('[data-slot="dialog-content"]') || target.closest('[data-slot="dialog-overlay"]')
|
|
6161
7501
|
);
|
|
6162
7502
|
}
|
|
6163
7503
|
function getHrefKeyFromElement(el) {
|
|
@@ -6168,7 +7508,30 @@ function getHrefKeyFromElement(el) {
|
|
|
6168
7508
|
if (!key) return null;
|
|
6169
7509
|
return { anchor, key };
|
|
6170
7510
|
}
|
|
6171
|
-
function
|
|
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
|
+
}
|
|
7534
|
+
function isNavbarButton2(el) {
|
|
6172
7535
|
return Boolean(el.closest('[data-ohw-role="navbar-button"]'));
|
|
6173
7536
|
}
|
|
6174
7537
|
function getNavigationItemAnchor(el) {
|
|
@@ -6180,19 +7543,8 @@ function getNavigationItemAnchor(el) {
|
|
|
6180
7543
|
function isNavigationItem(el) {
|
|
6181
7544
|
return getNavigationItemAnchor(el) !== null;
|
|
6182
7545
|
}
|
|
6183
|
-
function getNavigationItemAddHintTarget(anchor) {
|
|
6184
|
-
const items = listNavigationItems();
|
|
6185
|
-
const idx = items.indexOf(anchor);
|
|
6186
|
-
if (idx >= 0 && idx < items.length - 1) return items[idx + 1];
|
|
6187
|
-
return anchor;
|
|
6188
|
-
}
|
|
6189
|
-
function listNavigationItems() {
|
|
6190
|
-
return Array.from(
|
|
6191
|
-
document.querySelectorAll("nav [data-ohw-href-key], footer [data-ohw-href-key]")
|
|
6192
|
-
).filter((el) => isNavigationItem(el));
|
|
6193
|
-
}
|
|
6194
7546
|
function getNavigationItemReorderState(anchor) {
|
|
6195
|
-
if (
|
|
7547
|
+
if (isNavbarButton2(anchor)) return { key: null, disabled: false };
|
|
6196
7548
|
return getReorderHandleStateFromAnchor(anchor);
|
|
6197
7549
|
}
|
|
6198
7550
|
function getReorderHandleState(el) {
|
|
@@ -6214,6 +7566,120 @@ function clearHrefKeyHover(anchor) {
|
|
|
6214
7566
|
function isInsideNavigationItem(el) {
|
|
6215
7567
|
return getNavigationItemAnchor(el) !== null;
|
|
6216
7568
|
}
|
|
7569
|
+
function getNavigationRoot(el) {
|
|
7570
|
+
const explicit = el.closest("[data-ohw-nav-root]");
|
|
7571
|
+
if (explicit) return explicit;
|
|
7572
|
+
return el.closest("nav, footer, aside");
|
|
7573
|
+
}
|
|
7574
|
+
function findFooterItemGroup(item) {
|
|
7575
|
+
const footer = item.closest("footer");
|
|
7576
|
+
if (!footer) return null;
|
|
7577
|
+
let node = item.parentElement;
|
|
7578
|
+
while (node && node !== footer) {
|
|
7579
|
+
const hasDirectNavItems = Array.from(
|
|
7580
|
+
node.querySelectorAll(":scope > [data-ohw-href-key]")
|
|
7581
|
+
).some(isNavigationItem);
|
|
7582
|
+
if (hasDirectNavItems) return node;
|
|
7583
|
+
node = node.parentElement;
|
|
7584
|
+
}
|
|
7585
|
+
return null;
|
|
7586
|
+
}
|
|
7587
|
+
function isNavigationRoot(el) {
|
|
7588
|
+
return el.hasAttribute("data-ohw-nav-root") || el.matches("nav, footer, aside");
|
|
7589
|
+
}
|
|
7590
|
+
function isInferredFooterGroup(el) {
|
|
7591
|
+
const footer = el.closest("footer");
|
|
7592
|
+
if (!footer || el === footer) return false;
|
|
7593
|
+
return Array.from(el.querySelectorAll(":scope > [data-ohw-href-key]")).some(isNavigationItem);
|
|
7594
|
+
}
|
|
7595
|
+
function isNavigationContainer(el) {
|
|
7596
|
+
return el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-footer-col") || isNavigationRoot(el) || isInferredFooterGroup(el);
|
|
7597
|
+
}
|
|
7598
|
+
function isPointOverNavigation(x, y) {
|
|
7599
|
+
const navRoot = document.querySelector("[data-ohw-nav-root]") ?? document.querySelector("nav");
|
|
7600
|
+
if (!navRoot) return false;
|
|
7601
|
+
const r2 = navRoot.getBoundingClientRect();
|
|
7602
|
+
return x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom;
|
|
7603
|
+
}
|
|
7604
|
+
function isPointOverNavItem(container, x, y) {
|
|
7605
|
+
return Array.from(container.querySelectorAll("[data-ohw-href-key]")).some((el) => {
|
|
7606
|
+
if (!isNavigationItem(el) || isNavbarButton2(el)) return false;
|
|
7607
|
+
const itemRect = el.getBoundingClientRect();
|
|
7608
|
+
return x >= itemRect.left && x <= itemRect.right && y >= itemRect.top && y <= itemRect.bottom;
|
|
7609
|
+
});
|
|
7610
|
+
}
|
|
7611
|
+
function resolveNavContainerSelectionTarget(target, clientX, clientY) {
|
|
7612
|
+
if (getNavigationItemAnchor(target)) return null;
|
|
7613
|
+
if (target.closest('[data-ohw-role="navbar-button"]')) return null;
|
|
7614
|
+
const plainLink = target.closest("a");
|
|
7615
|
+
if (plainLink && !plainLink.hasAttribute("data-ohw-href-key") && !plainLink.closest("[data-ohw-nav-container]")) {
|
|
7616
|
+
return null;
|
|
7617
|
+
}
|
|
7618
|
+
const fromClosest = target.closest("[data-ohw-nav-container]");
|
|
7619
|
+
if (fromClosest && !isPointOverNavItem(fromClosest, clientX, clientY)) {
|
|
7620
|
+
return fromClosest;
|
|
7621
|
+
}
|
|
7622
|
+
const navRoot = target.closest("[data-ohw-nav-root]");
|
|
7623
|
+
if (!navRoot) return null;
|
|
7624
|
+
const container = navRoot.querySelector("[data-ohw-nav-container]");
|
|
7625
|
+
if (!container || isPointOverNavItem(container, clientX, clientY)) return null;
|
|
7626
|
+
if (target === navRoot || target.hasAttribute("data-ohw-nav-root")) {
|
|
7627
|
+
return container;
|
|
7628
|
+
}
|
|
7629
|
+
return null;
|
|
7630
|
+
}
|
|
7631
|
+
function getNavigationSelectionParent(el) {
|
|
7632
|
+
if (isNavigationItem(el)) {
|
|
7633
|
+
const explicit = el.closest("[data-ohw-nav-container]");
|
|
7634
|
+
if (explicit) return explicit;
|
|
7635
|
+
const footerGroup = findFooterItemGroup(el);
|
|
7636
|
+
if (footerGroup) return footerGroup;
|
|
7637
|
+
return getNavigationRoot(el);
|
|
7638
|
+
}
|
|
7639
|
+
if (el.hasAttribute("data-ohw-nav-container") || isInferredFooterGroup(el)) {
|
|
7640
|
+
return getNavigationRoot(el);
|
|
7641
|
+
}
|
|
7642
|
+
return null;
|
|
7643
|
+
}
|
|
7644
|
+
function placeCaretAtPoint(el, x, y) {
|
|
7645
|
+
const selection = window.getSelection();
|
|
7646
|
+
if (!selection) return;
|
|
7647
|
+
if (typeof document.caretRangeFromPoint === "function") {
|
|
7648
|
+
const range = document.caretRangeFromPoint(x, y);
|
|
7649
|
+
if (range && el.contains(range.startContainer)) {
|
|
7650
|
+
selection.removeAllRanges();
|
|
7651
|
+
selection.addRange(range);
|
|
7652
|
+
return;
|
|
7653
|
+
}
|
|
7654
|
+
}
|
|
7655
|
+
const caretPositionFromPoint = document.caretPositionFromPoint;
|
|
7656
|
+
if (typeof caretPositionFromPoint === "function") {
|
|
7657
|
+
const position = caretPositionFromPoint(x, y);
|
|
7658
|
+
if (position && el.contains(position.offsetNode)) {
|
|
7659
|
+
const range = document.createRange();
|
|
7660
|
+
range.setStart(position.offsetNode, position.offset);
|
|
7661
|
+
range.collapse(true);
|
|
7662
|
+
selection.removeAllRanges();
|
|
7663
|
+
selection.addRange(range);
|
|
7664
|
+
}
|
|
7665
|
+
}
|
|
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
|
+
}
|
|
6217
7683
|
function collectSections() {
|
|
6218
7684
|
return collectSectionsFromDom();
|
|
6219
7685
|
}
|
|
@@ -6337,6 +7803,8 @@ var ICONS = {
|
|
|
6337
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"/>',
|
|
6338
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"/>'
|
|
6339
7805
|
};
|
|
7806
|
+
var TOOLBAR_PILL_PADDING = 2;
|
|
7807
|
+
var TOOLBAR_TOGGLE_GAP = 4;
|
|
6340
7808
|
var TOOLBAR_GROUPS = [
|
|
6341
7809
|
[
|
|
6342
7810
|
{ cmd: "bold", title: "Bold" },
|
|
@@ -6361,7 +7829,7 @@ function EditGlowChrome({
|
|
|
6361
7829
|
dragDisabled = false
|
|
6362
7830
|
}) {
|
|
6363
7831
|
const GAP = 6;
|
|
6364
|
-
return /* @__PURE__ */ (0,
|
|
7832
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
6365
7833
|
"div",
|
|
6366
7834
|
{
|
|
6367
7835
|
ref: elRef,
|
|
@@ -6376,7 +7844,7 @@ function EditGlowChrome({
|
|
|
6376
7844
|
zIndex: 2147483646
|
|
6377
7845
|
},
|
|
6378
7846
|
children: [
|
|
6379
|
-
/* @__PURE__ */ (0,
|
|
7847
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
6380
7848
|
"div",
|
|
6381
7849
|
{
|
|
6382
7850
|
style: {
|
|
@@ -6389,7 +7857,7 @@ function EditGlowChrome({
|
|
|
6389
7857
|
}
|
|
6390
7858
|
}
|
|
6391
7859
|
),
|
|
6392
|
-
reorderHrefKey && /* @__PURE__ */ (0,
|
|
7860
|
+
reorderHrefKey && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
6393
7861
|
"div",
|
|
6394
7862
|
{
|
|
6395
7863
|
"data-ohw-drag-handle-container": "",
|
|
@@ -6401,7 +7869,7 @@ function EditGlowChrome({
|
|
|
6401
7869
|
transform: "translate(calc(-100% - 7px), -50%)",
|
|
6402
7870
|
pointerEvents: dragDisabled ? "none" : "auto"
|
|
6403
7871
|
},
|
|
6404
|
-
children: /* @__PURE__ */ (0,
|
|
7872
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
6405
7873
|
DragHandle,
|
|
6406
7874
|
{
|
|
6407
7875
|
"aria-label": `Reorder ${reorderHrefKey}`,
|
|
@@ -6505,7 +7973,7 @@ function FloatingToolbar({
|
|
|
6505
7973
|
onEditLink
|
|
6506
7974
|
}) {
|
|
6507
7975
|
const { top, left, transform } = calcToolbarPos(rect, parentScroll, 330);
|
|
6508
|
-
return /* @__PURE__ */ (0,
|
|
7976
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
6509
7977
|
"div",
|
|
6510
7978
|
{
|
|
6511
7979
|
ref: elRef,
|
|
@@ -6515,14 +7983,23 @@ function FloatingToolbar({
|
|
|
6515
7983
|
left,
|
|
6516
7984
|
transform,
|
|
6517
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",
|
|
6518
7995
|
pointerEvents: "auto"
|
|
6519
7996
|
},
|
|
6520
|
-
children: /* @__PURE__ */ (0,
|
|
6521
|
-
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0,
|
|
6522
|
-
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, {}),
|
|
6523
8000
|
btns.map((btn) => {
|
|
6524
8001
|
const isActive = activeCommands.has(btn.cmd);
|
|
6525
|
-
return /* @__PURE__ */ (0,
|
|
8002
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
6526
8003
|
CustomToolbarButton,
|
|
6527
8004
|
{
|
|
6528
8005
|
title: btn.title,
|
|
@@ -6531,7 +8008,7 @@ function FloatingToolbar({
|
|
|
6531
8008
|
e.preventDefault();
|
|
6532
8009
|
onCommand(btn.cmd);
|
|
6533
8010
|
},
|
|
6534
|
-
children: /* @__PURE__ */ (0,
|
|
8011
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
6535
8012
|
"svg",
|
|
6536
8013
|
{
|
|
6537
8014
|
width: "16",
|
|
@@ -6552,7 +8029,7 @@ function FloatingToolbar({
|
|
|
6552
8029
|
);
|
|
6553
8030
|
})
|
|
6554
8031
|
] }, gi)),
|
|
6555
|
-
showEditLink ? /* @__PURE__ */ (0,
|
|
8032
|
+
showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
6556
8033
|
CustomToolbarButton,
|
|
6557
8034
|
{
|
|
6558
8035
|
type: "button",
|
|
@@ -6566,7 +8043,7 @@ function FloatingToolbar({
|
|
|
6566
8043
|
e.preventDefault();
|
|
6567
8044
|
e.stopPropagation();
|
|
6568
8045
|
},
|
|
6569
|
-
children: /* @__PURE__ */ (0,
|
|
8046
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.Link, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
6570
8047
|
}
|
|
6571
8048
|
) : null
|
|
6572
8049
|
] })
|
|
@@ -6583,7 +8060,7 @@ function StateToggle({
|
|
|
6583
8060
|
states,
|
|
6584
8061
|
onStateChange
|
|
6585
8062
|
}) {
|
|
6586
|
-
return /* @__PURE__ */ (0,
|
|
8063
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
6587
8064
|
ToggleGroup,
|
|
6588
8065
|
{
|
|
6589
8066
|
"data-ohw-state-toggle": "",
|
|
@@ -6597,7 +8074,7 @@ function StateToggle({
|
|
|
6597
8074
|
left: rect.right - 8,
|
|
6598
8075
|
transform: "translateX(-100%)"
|
|
6599
8076
|
},
|
|
6600
|
-
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))
|
|
6601
8078
|
}
|
|
6602
8079
|
);
|
|
6603
8080
|
}
|
|
@@ -6620,12 +8097,12 @@ function resolveSubdomain(subdomainFromQuery) {
|
|
|
6620
8097
|
return "";
|
|
6621
8098
|
}
|
|
6622
8099
|
function OhhwellsBridge() {
|
|
6623
|
-
const pathname = (0,
|
|
6624
|
-
const router = (0,
|
|
6625
|
-
const searchParams = (0,
|
|
8100
|
+
const pathname = (0, import_navigation2.usePathname)();
|
|
8101
|
+
const router = (0, import_navigation2.useRouter)();
|
|
8102
|
+
const searchParams = (0, import_navigation2.useSearchParams)();
|
|
6626
8103
|
const isEditMode = isEditSessionActive();
|
|
6627
|
-
const [bridgeRoot, setBridgeRoot] = (0,
|
|
6628
|
-
(0,
|
|
8104
|
+
const [bridgeRoot, setBridgeRoot] = (0, import_react9.useState)(null);
|
|
8105
|
+
(0, import_react9.useEffect)(() => {
|
|
6629
8106
|
const figtreeFontId = "ohw-figtree-font";
|
|
6630
8107
|
if (!document.getElementById(figtreeFontId)) {
|
|
6631
8108
|
const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
|
|
@@ -6653,83 +8130,100 @@ function OhhwellsBridge() {
|
|
|
6653
8130
|
const subdomainFromQuery = searchParams.get("subdomain");
|
|
6654
8131
|
const subdomain = resolveSubdomain(subdomainFromQuery);
|
|
6655
8132
|
useLinkHrefGuardian(pathname, subdomain, isEditMode);
|
|
6656
|
-
const
|
|
8133
|
+
const postToParent2 = (0, import_react9.useCallback)((data) => {
|
|
6657
8134
|
if (typeof window !== "undefined" && window.parent !== window) {
|
|
6658
8135
|
window.parent.postMessage(data, "*");
|
|
6659
8136
|
}
|
|
6660
8137
|
}, []);
|
|
6661
|
-
const [fetchState, setFetchState] = (0,
|
|
6662
|
-
const autoSaveTimers = (0,
|
|
6663
|
-
const activeElRef = (0,
|
|
6664
|
-
const selectedElRef = (0,
|
|
6665
|
-
const originalContentRef = (0,
|
|
6666
|
-
const activeStateElRef = (0,
|
|
6667
|
-
const parentScrollRef = (0,
|
|
6668
|
-
const visibleViewportRef = (0,
|
|
6669
|
-
const [dialogPortalContainer, setDialogPortalContainer] = (0,
|
|
6670
|
-
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) => {
|
|
6671
8148
|
visibleViewportRef.current = node;
|
|
6672
8149
|
setDialogPortalContainer(node);
|
|
6673
8150
|
if (node) applyVisibleViewport(node, parentScrollRef.current);
|
|
6674
8151
|
}, []);
|
|
6675
|
-
const toolbarElRef = (0,
|
|
6676
|
-
const glowElRef = (0,
|
|
6677
|
-
const hoveredImageRef = (0,
|
|
6678
|
-
const hoveredImageHasTextOverlapRef = (0,
|
|
6679
|
-
const dragOverElRef = (0,
|
|
6680
|
-
const [mediaHover, setMediaHover] = (0,
|
|
6681
|
-
const [
|
|
6682
|
-
const
|
|
6683
|
-
const
|
|
6684
|
-
const
|
|
6685
|
-
const
|
|
6686
|
-
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 hoveredGapRef = (0, import_react9.useRef)(null);
|
|
8161
|
+
const imageUnhoverTimerRef = (0, import_react9.useRef)(null);
|
|
8162
|
+
const imageShowTimerRef = (0, import_react9.useRef)(null);
|
|
8163
|
+
const editStylesRef = (0, import_react9.useRef)(null);
|
|
8164
|
+
const activateRef = (0, import_react9.useRef)(() => {
|
|
8165
|
+
});
|
|
8166
|
+
const deactivateRef = (0, import_react9.useRef)(() => {
|
|
6687
8167
|
});
|
|
6688
|
-
const
|
|
8168
|
+
const selectRef = (0, import_react9.useRef)(() => {
|
|
6689
8169
|
});
|
|
6690
|
-
const
|
|
8170
|
+
const selectFrameRef = (0, import_react9.useRef)(() => {
|
|
6691
8171
|
});
|
|
6692
|
-
const deselectRef = (0,
|
|
8172
|
+
const deselectRef = (0, import_react9.useRef)(() => {
|
|
6693
8173
|
});
|
|
6694
|
-
const reselectNavigationItemRef = (0,
|
|
8174
|
+
const reselectNavigationItemRef = (0, import_react9.useRef)(() => {
|
|
6695
8175
|
});
|
|
6696
|
-
const commitNavigationTextEditRef = (0,
|
|
8176
|
+
const commitNavigationTextEditRef = (0, import_react9.useRef)(() => {
|
|
6697
8177
|
});
|
|
6698
|
-
const refreshActiveCommandsRef = (0,
|
|
8178
|
+
const refreshActiveCommandsRef = (0, import_react9.useRef)(() => {
|
|
6699
8179
|
});
|
|
6700
|
-
const postToParentRef = (0,
|
|
6701
|
-
postToParentRef.current =
|
|
6702
|
-
const sectionsLoadedRef = (0,
|
|
6703
|
-
const pendingScheduleConfigRequests = (0,
|
|
6704
|
-
const [toolbarRect, setToolbarRect] = (0,
|
|
6705
|
-
const [toolbarVariant, setToolbarVariant] = (0,
|
|
6706
|
-
const toolbarVariantRef = (0,
|
|
8180
|
+
const postToParentRef = (0, import_react9.useRef)(postToParent2);
|
|
8181
|
+
postToParentRef.current = postToParent2;
|
|
8182
|
+
const sectionsLoadedRef = (0, import_react9.useRef)(false);
|
|
8183
|
+
const pendingScheduleConfigRequests = (0, import_react9.useRef)([]);
|
|
8184
|
+
const [toolbarRect, setToolbarRect] = (0, import_react9.useState)(null);
|
|
8185
|
+
const [toolbarVariant, setToolbarVariant] = (0, import_react9.useState)("none");
|
|
8186
|
+
const toolbarVariantRef = (0, import_react9.useRef)("none");
|
|
6707
8187
|
toolbarVariantRef.current = toolbarVariant;
|
|
6708
|
-
const [reorderHrefKey, setReorderHrefKey] = (0,
|
|
6709
|
-
const [reorderDragDisabled, setReorderDragDisabled] = (0,
|
|
6710
|
-
const [toggleState, setToggleState] = (0,
|
|
6711
|
-
const [maxBadge, setMaxBadge] = (0,
|
|
6712
|
-
const [activeCommands, setActiveCommands] = (0,
|
|
6713
|
-
const [sectionGap, setSectionGap] = (0,
|
|
6714
|
-
const [toolbarShowEditLink, setToolbarShowEditLink] = (0,
|
|
6715
|
-
const
|
|
6716
|
-
const [
|
|
6717
|
-
const
|
|
6718
|
-
const [
|
|
6719
|
-
const
|
|
6720
|
-
const [
|
|
6721
|
-
const [
|
|
6722
|
-
const [
|
|
6723
|
-
const
|
|
6724
|
-
const
|
|
6725
|
-
const
|
|
6726
|
-
const
|
|
6727
|
-
const
|
|
8188
|
+
const [reorderHrefKey, setReorderHrefKey] = (0, import_react9.useState)(null);
|
|
8189
|
+
const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react9.useState)(false);
|
|
8190
|
+
const [toggleState, setToggleState] = (0, import_react9.useState)(null);
|
|
8191
|
+
const [maxBadge, setMaxBadge] = (0, import_react9.useState)(null);
|
|
8192
|
+
const [activeCommands, setActiveCommands] = (0, import_react9.useState)(/* @__PURE__ */ new Set());
|
|
8193
|
+
const [sectionGap, setSectionGap] = (0, import_react9.useState)(null);
|
|
8194
|
+
const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react9.useState)(false);
|
|
8195
|
+
const hoveredNavContainerRef = (0, import_react9.useRef)(null);
|
|
8196
|
+
const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0, import_react9.useState)(null);
|
|
8197
|
+
const hoveredItemElRef = (0, import_react9.useRef)(null);
|
|
8198
|
+
const [hoveredItemRect, setHoveredItemRect] = (0, import_react9.useState)(null);
|
|
8199
|
+
const siblingHintElRef = (0, import_react9.useRef)(null);
|
|
8200
|
+
const [siblingHintRect, setSiblingHintRect] = (0, import_react9.useState)(null);
|
|
8201
|
+
const [siblingHintRects, setSiblingHintRects] = (0, import_react9.useState)([]);
|
|
8202
|
+
const [isItemDragging, setIsItemDragging] = (0, import_react9.useState)(false);
|
|
8203
|
+
const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react9.useState)(false);
|
|
8204
|
+
const footerDragRef = (0, import_react9.useRef)(null);
|
|
8205
|
+
const [footerDropSlots, setFooterDropSlots] = (0, import_react9.useState)([]);
|
|
8206
|
+
const [activeFooterDropIndex, setActiveFooterDropIndex] = (0, import_react9.useState)(null);
|
|
8207
|
+
const [draggedItemRect, setDraggedItemRect] = (0, import_react9.useState)(null);
|
|
8208
|
+
const footerPointerDragRef = (0, import_react9.useRef)(null);
|
|
8209
|
+
const suppressNextClickRef = (0, import_react9.useRef)(false);
|
|
8210
|
+
const [linkPopover, setLinkPopover] = (0, import_react9.useState)(null);
|
|
8211
|
+
const linkPopoverSessionRef = (0, import_react9.useRef)(null);
|
|
8212
|
+
const addNavAfterAnchorRef = (0, import_react9.useRef)(null);
|
|
8213
|
+
const editContentRef = (0, import_react9.useRef)({});
|
|
8214
|
+
const [sitePages, setSitePages] = (0, import_react9.useState)([]);
|
|
8215
|
+
const [sectionsByPath, setSectionsByPath] = (0, import_react9.useState)({});
|
|
8216
|
+
const sectionsPrefetchGenRef = (0, import_react9.useRef)(0);
|
|
8217
|
+
const setLinkPopoverRef = (0, import_react9.useRef)(setLinkPopover);
|
|
8218
|
+
const linkPopoverPanelRef = (0, import_react9.useRef)(null);
|
|
8219
|
+
const linkPopoverOpenRef = (0, import_react9.useRef)(false);
|
|
8220
|
+
const linkPopoverGraceUntilRef = (0, import_react9.useRef)(0);
|
|
6728
8221
|
setLinkPopoverRef.current = setLinkPopover;
|
|
8222
|
+
linkPopoverSessionRef.current = linkPopover;
|
|
6729
8223
|
const bumpLinkPopoverGrace = () => {
|
|
6730
8224
|
linkPopoverGraceUntilRef.current = Date.now() + 350;
|
|
6731
8225
|
};
|
|
6732
|
-
const runSectionsPrefetch = (0,
|
|
8226
|
+
const runSectionsPrefetch = (0, import_react9.useCallback)((pages) => {
|
|
6733
8227
|
if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
|
|
6734
8228
|
const gen = ++sectionsPrefetchGenRef.current;
|
|
6735
8229
|
const paths = pages.map((p) => p.path);
|
|
@@ -6748,43 +8242,33 @@ function OhhwellsBridge() {
|
|
|
6748
8242
|
);
|
|
6749
8243
|
});
|
|
6750
8244
|
}, [isEditMode, pathname]);
|
|
6751
|
-
const runSectionsPrefetchRef = (0,
|
|
8245
|
+
const runSectionsPrefetchRef = (0, import_react9.useRef)(runSectionsPrefetch);
|
|
6752
8246
|
runSectionsPrefetchRef.current = runSectionsPrefetch;
|
|
6753
|
-
(0,
|
|
6754
|
-
if (!linkPopover)
|
|
8247
|
+
(0, import_react9.useEffect)(() => {
|
|
8248
|
+
if (!linkPopover) {
|
|
8249
|
+
document.documentElement.removeAttribute("data-ohw-link-popover-open");
|
|
8250
|
+
return;
|
|
8251
|
+
}
|
|
8252
|
+
document.documentElement.setAttribute("data-ohw-link-popover-open", "");
|
|
6755
8253
|
if (hoveredImageRef.current) {
|
|
6756
8254
|
hoveredImageRef.current = null;
|
|
6757
8255
|
hoveredImageHasTextOverlapRef.current = false;
|
|
6758
8256
|
}
|
|
6759
8257
|
hoveredGapRef.current = null;
|
|
6760
8258
|
setSectionGap(null);
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
6766
|
-
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
const preventBackgroundScroll = (e) => {
|
|
6770
|
-
const target = e.target;
|
|
6771
|
-
if (target instanceof Element && target.closest('[data-ohw-link-modal-root], [data-slot="dialog-overlay"]')) {
|
|
6772
|
-
return;
|
|
6773
|
-
}
|
|
6774
|
-
e.preventDefault();
|
|
6775
|
-
};
|
|
6776
|
-
const scrollOpts = { passive: false, capture: true };
|
|
6777
|
-
document.addEventListener("wheel", preventBackgroundScroll, scrollOpts);
|
|
6778
|
-
document.addEventListener("touchmove", preventBackgroundScroll, scrollOpts);
|
|
8259
|
+
hoveredItemElRef.current = null;
|
|
8260
|
+
setHoveredItemRect(null);
|
|
8261
|
+
hoveredNavContainerRef.current = null;
|
|
8262
|
+
setHoveredNavContainerRect(null);
|
|
8263
|
+
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => {
|
|
8264
|
+
el.removeAttribute("data-ohw-hovered");
|
|
8265
|
+
});
|
|
8266
|
+
postToParent2({ type: "ow:image-unhover" });
|
|
6779
8267
|
return () => {
|
|
6780
|
-
|
|
6781
|
-
html.style.overflow = prevHtmlOverflow;
|
|
6782
|
-
body.style.overflow = prevBodyOverflow;
|
|
6783
|
-
document.removeEventListener("wheel", preventBackgroundScroll, scrollOpts);
|
|
6784
|
-
document.removeEventListener("touchmove", preventBackgroundScroll, scrollOpts);
|
|
8268
|
+
document.documentElement.removeAttribute("data-ohw-link-popover-open");
|
|
6785
8269
|
};
|
|
6786
|
-
}, [linkPopover,
|
|
6787
|
-
(0,
|
|
8270
|
+
}, [linkPopover, postToParent2]);
|
|
8271
|
+
(0, import_react9.useEffect)(() => {
|
|
6788
8272
|
if (!isEditMode) return;
|
|
6789
8273
|
const useFixtures = shouldUseDevFixtures();
|
|
6790
8274
|
if (useFixtures) {
|
|
@@ -6805,17 +8289,17 @@ function OhhwellsBridge() {
|
|
|
6805
8289
|
runSectionsPrefetchRef.current(mapped);
|
|
6806
8290
|
};
|
|
6807
8291
|
window.addEventListener("message", onSitePages);
|
|
6808
|
-
if (!useFixtures)
|
|
8292
|
+
if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
|
|
6809
8293
|
return () => window.removeEventListener("message", onSitePages);
|
|
6810
|
-
}, [isEditMode,
|
|
6811
|
-
(0,
|
|
8294
|
+
}, [isEditMode, postToParent2]);
|
|
8295
|
+
(0, import_react9.useEffect)(() => {
|
|
6812
8296
|
if (!isEditMode || shouldUseDevFixtures()) return;
|
|
6813
8297
|
void loadAllSectionsManifest().then((manifest) => {
|
|
6814
8298
|
if (Object.keys(manifest).length === 0) return;
|
|
6815
8299
|
setSectionsByPath((prev) => ({ ...manifest, ...prev }));
|
|
6816
8300
|
});
|
|
6817
8301
|
}, [isEditMode]);
|
|
6818
|
-
(0,
|
|
8302
|
+
(0, import_react9.useEffect)(() => {
|
|
6819
8303
|
const update = () => {
|
|
6820
8304
|
const el = activeElRef.current ?? selectedElRef.current;
|
|
6821
8305
|
if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
@@ -6839,10 +8323,10 @@ function OhhwellsBridge() {
|
|
|
6839
8323
|
vvp.removeEventListener("resize", update);
|
|
6840
8324
|
};
|
|
6841
8325
|
}, []);
|
|
6842
|
-
const refreshStateRules = (0,
|
|
8326
|
+
const refreshStateRules = (0, import_react9.useCallback)(() => {
|
|
6843
8327
|
editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
|
|
6844
8328
|
}, []);
|
|
6845
|
-
const processConfigRequest = (0,
|
|
8329
|
+
const processConfigRequest = (0, import_react9.useCallback)((insertAfterVal) => {
|
|
6846
8330
|
const tracker = getSectionsTracker();
|
|
6847
8331
|
let entries = [];
|
|
6848
8332
|
try {
|
|
@@ -6865,7 +8349,7 @@ function OhhwellsBridge() {
|
|
|
6865
8349
|
}
|
|
6866
8350
|
window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
|
|
6867
8351
|
}, [isEditMode]);
|
|
6868
|
-
const deactivate = (0,
|
|
8352
|
+
const deactivate = (0, import_react9.useCallback)(() => {
|
|
6869
8353
|
const el = activeElRef.current;
|
|
6870
8354
|
if (!el) return;
|
|
6871
8355
|
const key = el.dataset.ohwKey;
|
|
@@ -6894,21 +8378,25 @@ function OhhwellsBridge() {
|
|
|
6894
8378
|
setMaxBadge(null);
|
|
6895
8379
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
6896
8380
|
setToolbarShowEditLink(false);
|
|
6897
|
-
|
|
6898
|
-
}, [
|
|
6899
|
-
const deselect = (0,
|
|
8381
|
+
postToParent2({ type: "ow:exit-edit" });
|
|
8382
|
+
}, [postToParent2]);
|
|
8383
|
+
const deselect = (0, import_react9.useCallback)(() => {
|
|
6900
8384
|
selectedElRef.current = null;
|
|
6901
8385
|
setReorderHrefKey(null);
|
|
6902
8386
|
setReorderDragDisabled(false);
|
|
8387
|
+
setIsFooterFrameSelection(false);
|
|
6903
8388
|
siblingHintElRef.current = null;
|
|
6904
8389
|
setSiblingHintRect(null);
|
|
8390
|
+
setSiblingHintRects([]);
|
|
6905
8391
|
setIsItemDragging(false);
|
|
8392
|
+
hoveredNavContainerRef.current = null;
|
|
8393
|
+
setHoveredNavContainerRect(null);
|
|
6906
8394
|
if (!activeElRef.current) {
|
|
6907
8395
|
setToolbarRect(null);
|
|
6908
8396
|
setToolbarVariant("none");
|
|
6909
8397
|
}
|
|
6910
8398
|
}, []);
|
|
6911
|
-
const reselectNavigationItem = (0,
|
|
8399
|
+
const reselectNavigationItem = (0, import_react9.useCallback)((navAnchor) => {
|
|
6912
8400
|
selectedElRef.current = navAnchor;
|
|
6913
8401
|
const { key, disabled } = getNavigationItemReorderState(navAnchor);
|
|
6914
8402
|
setReorderHrefKey(key);
|
|
@@ -6918,7 +8406,7 @@ function OhhwellsBridge() {
|
|
|
6918
8406
|
setToolbarShowEditLink(false);
|
|
6919
8407
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
6920
8408
|
}, []);
|
|
6921
|
-
const commitNavigationTextEdit = (0,
|
|
8409
|
+
const commitNavigationTextEdit = (0, import_react9.useCallback)((navAnchor) => {
|
|
6922
8410
|
const el = activeElRef.current;
|
|
6923
8411
|
if (!el) return;
|
|
6924
8412
|
const key = el.dataset.ohwKey;
|
|
@@ -6931,9 +8419,9 @@ function OhhwellsBridge() {
|
|
|
6931
8419
|
const html = sanitizeHtml(el.innerHTML);
|
|
6932
8420
|
const original = originalContentRef.current ?? "";
|
|
6933
8421
|
if (html !== sanitizeHtml(original)) {
|
|
6934
|
-
|
|
8422
|
+
postToParent2({ type: "ow:change", nodes: [{ key, text: html }] });
|
|
6935
8423
|
const h = document.documentElement.scrollHeight;
|
|
6936
|
-
if (h > 50)
|
|
8424
|
+
if (h > 50) postToParent2({ type: "ow:height", height: h });
|
|
6937
8425
|
}
|
|
6938
8426
|
}
|
|
6939
8427
|
el.removeAttribute("contenteditable");
|
|
@@ -6941,81 +8429,408 @@ function OhhwellsBridge() {
|
|
|
6941
8429
|
setMaxBadge(null);
|
|
6942
8430
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
6943
8431
|
setToolbarShowEditLink(false);
|
|
6944
|
-
|
|
8432
|
+
postToParent2({ type: "ow:exit-edit" });
|
|
6945
8433
|
reselectNavigationItem(navAnchor);
|
|
6946
|
-
}, [
|
|
6947
|
-
const
|
|
8434
|
+
}, [postToParent2, reselectNavigationItem]);
|
|
8435
|
+
const handleAddTopLevelNavItem = (0, import_react9.useCallback)(() => {
|
|
8436
|
+
const items = listNavbarItems();
|
|
8437
|
+
addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
|
|
8438
|
+
deselectRef.current();
|
|
8439
|
+
deactivateRef.current();
|
|
8440
|
+
bumpLinkPopoverGrace();
|
|
8441
|
+
setLinkPopover({
|
|
8442
|
+
key: "__add-nav__",
|
|
8443
|
+
mode: "create",
|
|
8444
|
+
intent: "add-nav"
|
|
8445
|
+
});
|
|
8446
|
+
}, []);
|
|
8447
|
+
const clearFooterDragVisuals = (0, import_react9.useCallback)(() => {
|
|
8448
|
+
footerDragRef.current = null;
|
|
8449
|
+
setSiblingHintRects([]);
|
|
8450
|
+
setFooterDropSlots([]);
|
|
8451
|
+
setActiveFooterDropIndex(null);
|
|
8452
|
+
setDraggedItemRect(null);
|
|
8453
|
+
setIsItemDragging(false);
|
|
8454
|
+
unlockFooterDragInteraction();
|
|
8455
|
+
}, []);
|
|
8456
|
+
const refreshFooterDragVisuals = (0, import_react9.useCallback)((session, activeSlot, clientX, clientY) => {
|
|
8457
|
+
const dragged = session.draggedEl;
|
|
8458
|
+
setDraggedItemRect(dragged.getBoundingClientRect());
|
|
8459
|
+
if (typeof clientX === "number" && typeof clientY === "number") {
|
|
8460
|
+
session.lastClientX = clientX;
|
|
8461
|
+
session.lastClientY = clientY;
|
|
8462
|
+
}
|
|
8463
|
+
session.activeSlot = activeSlot;
|
|
8464
|
+
if (session.kind === "link") {
|
|
8465
|
+
const columns2 = listFooterColumns();
|
|
8466
|
+
const focusCols = /* @__PURE__ */ new Set([session.sourceColumnIndex]);
|
|
8467
|
+
if (activeSlot) focusCols.add(activeSlot.columnIndex);
|
|
8468
|
+
const siblingRects = [];
|
|
8469
|
+
columns2.forEach((col, i) => {
|
|
8470
|
+
if (!focusCols.has(i)) return;
|
|
8471
|
+
for (const link of listFooterLinksInColumn(col)) {
|
|
8472
|
+
if (link === dragged) continue;
|
|
8473
|
+
siblingRects.push(link.getBoundingClientRect());
|
|
8474
|
+
}
|
|
8475
|
+
});
|
|
8476
|
+
setSiblingHintRects(siblingRects);
|
|
8477
|
+
const slots2 = [];
|
|
8478
|
+
columns2.forEach((col, i) => {
|
|
8479
|
+
slots2.push(...buildLinkDropSlots(col, i));
|
|
8480
|
+
});
|
|
8481
|
+
setFooterDropSlots(slots2);
|
|
8482
|
+
const activeIdx2 = activeSlot ? slots2.findIndex((s) => s.columnIndex === activeSlot.columnIndex && s.insertIndex === activeSlot.insertIndex) : -1;
|
|
8483
|
+
setActiveFooterDropIndex(activeIdx2 >= 0 ? activeIdx2 : null);
|
|
8484
|
+
return;
|
|
8485
|
+
}
|
|
8486
|
+
const columns = listFooterColumns();
|
|
8487
|
+
setSiblingHintRects(columns.filter((col) => col !== dragged).map((col) => col.getBoundingClientRect()));
|
|
8488
|
+
const slots = buildColumnDropSlots();
|
|
8489
|
+
setFooterDropSlots(slots);
|
|
8490
|
+
const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
|
|
8491
|
+
setActiveFooterDropIndex(activeIdx >= 0 ? activeIdx : null);
|
|
8492
|
+
}, []);
|
|
8493
|
+
const refreshFooterDragVisualsRef = (0, import_react9.useRef)(refreshFooterDragVisuals);
|
|
8494
|
+
refreshFooterDragVisualsRef.current = refreshFooterDragVisuals;
|
|
8495
|
+
const commitFooterDragRef = (0, import_react9.useRef)(() => {
|
|
8496
|
+
});
|
|
8497
|
+
const beginFooterDragRef = (0, import_react9.useRef)(() => {
|
|
8498
|
+
});
|
|
8499
|
+
const beginFooterDrag = (0, import_react9.useCallback)(
|
|
8500
|
+
(session) => {
|
|
8501
|
+
const rect = session.draggedEl.getBoundingClientRect();
|
|
8502
|
+
session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
|
|
8503
|
+
session.lastClientY = session.lastClientY || rect.top + rect.height / 2;
|
|
8504
|
+
session.activeSlot = session.activeSlot ?? null;
|
|
8505
|
+
footerDragRef.current = session;
|
|
8506
|
+
setIsItemDragging(true);
|
|
8507
|
+
lockFooterDuringDrag();
|
|
8508
|
+
siblingHintElRef.current = null;
|
|
8509
|
+
setSiblingHintRect(null);
|
|
8510
|
+
if (session.wasSelected && selectedElRef.current === session.draggedEl) {
|
|
8511
|
+
setToolbarRect(rect);
|
|
8512
|
+
}
|
|
8513
|
+
const initialSlot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
|
|
8514
|
+
refreshFooterDragVisuals(session, initialSlot, session.lastClientX, session.lastClientY);
|
|
8515
|
+
},
|
|
8516
|
+
[refreshFooterDragVisuals]
|
|
8517
|
+
);
|
|
8518
|
+
beginFooterDragRef.current = beginFooterDrag;
|
|
8519
|
+
const commitFooterDrag = (0, import_react9.useCallback)(
|
|
8520
|
+
(clientX, clientY) => {
|
|
8521
|
+
const session = footerDragRef.current;
|
|
8522
|
+
if (!session) {
|
|
8523
|
+
clearFooterDragVisuals();
|
|
8524
|
+
return;
|
|
8525
|
+
}
|
|
8526
|
+
const x = typeof clientX === "number" && (clientX !== 0 || clientY !== 0) ? clientX : session.lastClientX;
|
|
8527
|
+
const y = typeof clientY === "number" && (clientX !== 0 || clientY !== 0) ? clientY : session.lastClientY;
|
|
8528
|
+
let nextOrder = null;
|
|
8529
|
+
const slot = session.activeSlot ?? (session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(x, y, session.hrefKey) : session.kind === "column" ? hitTestColumnDropSlot(x, y) : null);
|
|
8530
|
+
if (session.kind === "link" && session.hrefKey && slot) {
|
|
8531
|
+
nextOrder = planFooterLinkMove(session.hrefKey, slot.columnIndex, slot.insertIndex);
|
|
8532
|
+
} else if (session.kind === "column" && slot) {
|
|
8533
|
+
nextOrder = planFooterColumnMove(session.sourceColumnIndex, slot.insertIndex);
|
|
8534
|
+
}
|
|
8535
|
+
const wasSelected = session.wasSelected;
|
|
8536
|
+
const draggedEl = session.draggedEl;
|
|
8537
|
+
const hrefKey = session.hrefKey;
|
|
8538
|
+
let movedColumnIndex = null;
|
|
8539
|
+
if (session.kind === "column" && slot && nextOrder) {
|
|
8540
|
+
let adjusted = slot.insertIndex;
|
|
8541
|
+
if (session.sourceColumnIndex < slot.insertIndex) adjusted -= 1;
|
|
8542
|
+
movedColumnIndex = Math.max(0, Math.min(adjusted, nextOrder.length - 1));
|
|
8543
|
+
}
|
|
8544
|
+
clearFooterDragVisuals();
|
|
8545
|
+
const applySelectionAfterDrop = () => {
|
|
8546
|
+
if (!wasSelected) {
|
|
8547
|
+
deselectRef.current();
|
|
8548
|
+
return;
|
|
8549
|
+
}
|
|
8550
|
+
if (hrefKey) {
|
|
8551
|
+
const link = document.querySelector(
|
|
8552
|
+
`footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
8553
|
+
);
|
|
8554
|
+
if (link && isNavigationItem(link)) {
|
|
8555
|
+
selectRef.current(link);
|
|
8556
|
+
return;
|
|
8557
|
+
}
|
|
8558
|
+
}
|
|
8559
|
+
if (movedColumnIndex !== null && nextOrder) {
|
|
8560
|
+
const colKeys = nextOrder[movedColumnIndex] ?? [];
|
|
8561
|
+
let column = null;
|
|
8562
|
+
for (const key of colKeys) {
|
|
8563
|
+
const link = document.querySelector(
|
|
8564
|
+
`footer [data-ohw-href-key="${CSS.escape(key)}"]`
|
|
8565
|
+
);
|
|
8566
|
+
if (link) {
|
|
8567
|
+
column = findFooterColumnForLink(link);
|
|
8568
|
+
if (column) break;
|
|
8569
|
+
}
|
|
8570
|
+
}
|
|
8571
|
+
if (!column) column = listFooterColumns()[movedColumnIndex] ?? null;
|
|
8572
|
+
if (column && isNavigationContainer(column)) {
|
|
8573
|
+
selectFrameRef.current(column);
|
|
8574
|
+
return;
|
|
8575
|
+
}
|
|
8576
|
+
}
|
|
8577
|
+
if (document.body.contains(draggedEl)) {
|
|
8578
|
+
if (isNavigationItem(draggedEl)) {
|
|
8579
|
+
selectRef.current(draggedEl);
|
|
8580
|
+
return;
|
|
8581
|
+
}
|
|
8582
|
+
if (isNavigationContainer(draggedEl)) {
|
|
8583
|
+
selectFrameRef.current(draggedEl);
|
|
8584
|
+
return;
|
|
8585
|
+
}
|
|
8586
|
+
}
|
|
8587
|
+
deselectRef.current();
|
|
8588
|
+
};
|
|
8589
|
+
if (!wasSelected) {
|
|
8590
|
+
deselectRef.current();
|
|
8591
|
+
}
|
|
8592
|
+
if (nextOrder) {
|
|
8593
|
+
const orderJson = JSON.stringify(nextOrder);
|
|
8594
|
+
editContentRef.current = {
|
|
8595
|
+
...editContentRef.current,
|
|
8596
|
+
[FOOTER_ORDER_KEY]: orderJson
|
|
8597
|
+
};
|
|
8598
|
+
applyFooterOrder(nextOrder);
|
|
8599
|
+
document.querySelectorAll("footer [data-ohw-href-key]").forEach(disableNativeHrefDrag);
|
|
8600
|
+
postToParentRef.current({
|
|
8601
|
+
type: "ow:change",
|
|
8602
|
+
nodes: [{ key: FOOTER_ORDER_KEY, text: orderJson }]
|
|
8603
|
+
});
|
|
8604
|
+
requestAnimationFrame(() => {
|
|
8605
|
+
if (editContentRef.current[FOOTER_ORDER_KEY] === orderJson) {
|
|
8606
|
+
applyFooterOrder(nextOrder);
|
|
8607
|
+
document.querySelectorAll("footer [data-ohw-href-key]").forEach(disableNativeHrefDrag);
|
|
8608
|
+
}
|
|
8609
|
+
requestAnimationFrame(applySelectionAfterDrop);
|
|
8610
|
+
});
|
|
8611
|
+
return;
|
|
8612
|
+
}
|
|
8613
|
+
applySelectionAfterDrop();
|
|
8614
|
+
},
|
|
8615
|
+
[clearFooterDragVisuals]
|
|
8616
|
+
);
|
|
8617
|
+
commitFooterDragRef.current = commitFooterDrag;
|
|
8618
|
+
const startFooterLinkDrag = (0, import_react9.useCallback)(
|
|
8619
|
+
(anchor, clientX, clientY, wasSelected) => {
|
|
8620
|
+
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
8621
|
+
if (!hrefKey || !isFooterHrefKey(hrefKey)) return false;
|
|
8622
|
+
const column = findFooterColumnForLink(anchor);
|
|
8623
|
+
const columns = listFooterColumns();
|
|
8624
|
+
beginFooterDrag({
|
|
8625
|
+
kind: "link",
|
|
8626
|
+
hrefKey,
|
|
8627
|
+
columnEl: column,
|
|
8628
|
+
sourceColumnIndex: column ? columns.indexOf(column) : 0,
|
|
8629
|
+
wasSelected,
|
|
8630
|
+
draggedEl: anchor,
|
|
8631
|
+
lastClientX: clientX,
|
|
8632
|
+
lastClientY: clientY,
|
|
8633
|
+
activeSlot: null
|
|
8634
|
+
});
|
|
8635
|
+
return true;
|
|
8636
|
+
},
|
|
8637
|
+
[beginFooterDrag]
|
|
8638
|
+
);
|
|
8639
|
+
const startFooterColumnDrag = (0, import_react9.useCallback)(
|
|
8640
|
+
(columnEl, clientX, clientY, wasSelected) => {
|
|
8641
|
+
const columns = listFooterColumns();
|
|
8642
|
+
const idx = columns.indexOf(columnEl);
|
|
8643
|
+
if (idx < 0) return false;
|
|
8644
|
+
beginFooterDrag({
|
|
8645
|
+
kind: "column",
|
|
8646
|
+
hrefKey: null,
|
|
8647
|
+
columnEl,
|
|
8648
|
+
sourceColumnIndex: idx,
|
|
8649
|
+
wasSelected,
|
|
8650
|
+
draggedEl: columnEl,
|
|
8651
|
+
lastClientX: clientX,
|
|
8652
|
+
lastClientY: clientY,
|
|
8653
|
+
activeSlot: null
|
|
8654
|
+
});
|
|
8655
|
+
return true;
|
|
8656
|
+
},
|
|
8657
|
+
[beginFooterDrag]
|
|
8658
|
+
);
|
|
8659
|
+
const handleItemDragStart = (0, import_react9.useCallback)(
|
|
8660
|
+
(e) => {
|
|
8661
|
+
const selected = selectedElRef.current;
|
|
8662
|
+
if (!selected) {
|
|
8663
|
+
setIsItemDragging(true);
|
|
8664
|
+
return;
|
|
8665
|
+
}
|
|
8666
|
+
const clientX = e?.clientX ?? selected.getBoundingClientRect().left + 8;
|
|
8667
|
+
const clientY = e?.clientY ?? selected.getBoundingClientRect().top + 8;
|
|
8668
|
+
if (startFooterLinkDrag(selected, clientX, clientY, true)) return;
|
|
8669
|
+
if (selected.hasAttribute("data-ohw-footer-col") || isInferredFooterGroup(selected) && selected.closest("footer")) {
|
|
8670
|
+
if (startFooterColumnDrag(selected, clientX, clientY, true)) return;
|
|
8671
|
+
}
|
|
8672
|
+
siblingHintElRef.current = null;
|
|
8673
|
+
setSiblingHintRect(null);
|
|
8674
|
+
setIsItemDragging(true);
|
|
8675
|
+
},
|
|
8676
|
+
[startFooterColumnDrag, startFooterLinkDrag]
|
|
8677
|
+
);
|
|
8678
|
+
const handleItemDragEnd = (0, import_react9.useCallback)(
|
|
8679
|
+
(e) => {
|
|
8680
|
+
if (footerDragRef.current) {
|
|
8681
|
+
const x = e?.clientX;
|
|
8682
|
+
const y = e?.clientY;
|
|
8683
|
+
if (typeof x === "number" && typeof y === "number" && (x !== 0 || y !== 0)) {
|
|
8684
|
+
commitFooterDrag(x, y);
|
|
8685
|
+
} else {
|
|
8686
|
+
commitFooterDrag();
|
|
8687
|
+
}
|
|
8688
|
+
return;
|
|
8689
|
+
}
|
|
8690
|
+
setIsItemDragging(false);
|
|
8691
|
+
},
|
|
8692
|
+
[commitFooterDrag]
|
|
8693
|
+
);
|
|
8694
|
+
const handleItemChromePointerDown = (0, import_react9.useCallback)((e) => {
|
|
8695
|
+
if (e.button !== 0) return;
|
|
6948
8696
|
const selected = selectedElRef.current;
|
|
6949
8697
|
if (!selected) return;
|
|
6950
|
-
|
|
6951
|
-
|
|
6952
|
-
|
|
6953
|
-
|
|
6954
|
-
|
|
6955
|
-
|
|
6956
|
-
|
|
6957
|
-
|
|
8698
|
+
armFooterPressDrag();
|
|
8699
|
+
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
8700
|
+
if (hrefKey && isFooterHrefKey(hrefKey)) {
|
|
8701
|
+
footerPointerDragRef.current = {
|
|
8702
|
+
el: selected,
|
|
8703
|
+
kind: "link",
|
|
8704
|
+
startX: e.clientX,
|
|
8705
|
+
startY: e.clientY,
|
|
8706
|
+
pointerId: e.pointerId,
|
|
8707
|
+
wasSelected: true,
|
|
8708
|
+
started: false
|
|
8709
|
+
};
|
|
8710
|
+
return;
|
|
8711
|
+
}
|
|
8712
|
+
if (selected.hasAttribute("data-ohw-footer-col") || isInferredFooterGroup(selected) && selected.closest("footer")) {
|
|
8713
|
+
footerPointerDragRef.current = {
|
|
8714
|
+
el: selected,
|
|
8715
|
+
kind: "column",
|
|
8716
|
+
startX: e.clientX,
|
|
8717
|
+
startY: e.clientY,
|
|
8718
|
+
pointerId: e.pointerId,
|
|
8719
|
+
wasSelected: true,
|
|
8720
|
+
started: false
|
|
8721
|
+
};
|
|
8722
|
+
}
|
|
6958
8723
|
}, []);
|
|
6959
|
-
const
|
|
6960
|
-
|
|
8724
|
+
const handleItemChromeClick = (0, import_react9.useCallback)((clientX, clientY) => {
|
|
8725
|
+
if (suppressNextClickRef.current) {
|
|
8726
|
+
suppressNextClickRef.current = false;
|
|
8727
|
+
return;
|
|
8728
|
+
}
|
|
8729
|
+
const selected = selectedElRef.current;
|
|
8730
|
+
if (!selected || !isNavigationItem(selected)) return;
|
|
8731
|
+
const editable = selected.querySelector('[data-ohw-editable="text"]') ?? selected.querySelector("[data-ohw-editable]");
|
|
8732
|
+
if (!editable) return;
|
|
8733
|
+
activateRef.current(editable, { caretX: clientX, caretY: clientY });
|
|
6961
8734
|
}, []);
|
|
6962
8735
|
reselectNavigationItemRef.current = reselectNavigationItem;
|
|
6963
8736
|
commitNavigationTextEditRef.current = commitNavigationTextEdit;
|
|
6964
|
-
const select = (0,
|
|
6965
|
-
|
|
6966
|
-
|
|
6967
|
-
|
|
6968
|
-
|
|
6969
|
-
|
|
6970
|
-
|
|
6971
|
-
|
|
6972
|
-
|
|
6973
|
-
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
6979
|
-
|
|
6980
|
-
|
|
6981
|
-
|
|
6982
|
-
|
|
6983
|
-
|
|
6984
|
-
|
|
6985
|
-
|
|
6986
|
-
|
|
6987
|
-
|
|
6988
|
-
|
|
6989
|
-
|
|
6990
|
-
|
|
6991
|
-
|
|
6992
|
-
|
|
6993
|
-
|
|
6994
|
-
|
|
6995
|
-
|
|
6996
|
-
|
|
6997
|
-
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
7001
|
-
|
|
7002
|
-
|
|
8737
|
+
const select = (0, import_react9.useCallback)(
|
|
8738
|
+
(anchor) => {
|
|
8739
|
+
if (!isNavigationItem(anchor)) return;
|
|
8740
|
+
if (activeElRef.current) deactivate();
|
|
8741
|
+
selectedElRef.current = anchor;
|
|
8742
|
+
clearHrefKeyHover(anchor);
|
|
8743
|
+
hoveredNavContainerRef.current = null;
|
|
8744
|
+
setHoveredNavContainerRect(null);
|
|
8745
|
+
setHoveredItemRect(null);
|
|
8746
|
+
hoveredItemElRef.current = null;
|
|
8747
|
+
siblingHintElRef.current = null;
|
|
8748
|
+
setSiblingHintRect(null);
|
|
8749
|
+
setSiblingHintRects([]);
|
|
8750
|
+
setIsItemDragging(false);
|
|
8751
|
+
const { key, disabled } = getNavigationItemReorderState(anchor);
|
|
8752
|
+
setReorderHrefKey(key);
|
|
8753
|
+
setReorderDragDisabled(disabled);
|
|
8754
|
+
setIsFooterFrameSelection(false);
|
|
8755
|
+
setToolbarVariant("link-action");
|
|
8756
|
+
setToolbarRect(anchor.getBoundingClientRect());
|
|
8757
|
+
setToolbarShowEditLink(false);
|
|
8758
|
+
setActiveCommands(/* @__PURE__ */ new Set());
|
|
8759
|
+
},
|
|
8760
|
+
[deactivate]
|
|
8761
|
+
);
|
|
8762
|
+
const selectFrame = (0, import_react9.useCallback)(
|
|
8763
|
+
(el) => {
|
|
8764
|
+
if (!isNavigationContainer(el)) return;
|
|
8765
|
+
if (activeElRef.current) deactivate();
|
|
8766
|
+
const isFooterColumn = el.hasAttribute("data-ohw-footer-col") || Boolean(el.closest("footer") && isInferredFooterGroup(el));
|
|
8767
|
+
selectedElRef.current = el;
|
|
8768
|
+
clearHrefKeyHover(el);
|
|
8769
|
+
hoveredNavContainerRef.current = null;
|
|
8770
|
+
setHoveredNavContainerRect(null);
|
|
8771
|
+
setHoveredItemRect(null);
|
|
8772
|
+
hoveredItemElRef.current = null;
|
|
8773
|
+
siblingHintElRef.current = null;
|
|
8774
|
+
setSiblingHintRect(null);
|
|
8775
|
+
setSiblingHintRects(
|
|
8776
|
+
isFooterColumn ? listFooterColumns().filter((column) => column !== el).map((column) => column.getBoundingClientRect()) : []
|
|
8777
|
+
);
|
|
8778
|
+
setIsItemDragging(false);
|
|
7003
8779
|
setReorderHrefKey(null);
|
|
7004
8780
|
setReorderDragDisabled(false);
|
|
7005
|
-
|
|
7006
|
-
|
|
7007
|
-
|
|
7008
|
-
|
|
7009
|
-
|
|
7010
|
-
|
|
7011
|
-
|
|
7012
|
-
|
|
7013
|
-
|
|
8781
|
+
setIsFooterFrameSelection(isFooterColumn);
|
|
8782
|
+
setToolbarVariant("select-frame");
|
|
8783
|
+
setToolbarRect(el.getBoundingClientRect());
|
|
8784
|
+
setToolbarShowEditLink(false);
|
|
8785
|
+
setActiveCommands(/* @__PURE__ */ new Set());
|
|
8786
|
+
},
|
|
8787
|
+
[deactivate]
|
|
8788
|
+
);
|
|
8789
|
+
const activate = (0, import_react9.useCallback)(
|
|
8790
|
+
(el, options) => {
|
|
8791
|
+
if (activeElRef.current === el) return;
|
|
8792
|
+
selectedElRef.current = null;
|
|
8793
|
+
deactivate();
|
|
8794
|
+
if (hoveredImageRef.current) {
|
|
8795
|
+
hoveredImageRef.current = null;
|
|
8796
|
+
postToParentRef.current({ type: "ow:image-unhover" });
|
|
8797
|
+
}
|
|
8798
|
+
setToolbarVariant("rich-text");
|
|
8799
|
+
siblingHintElRef.current = null;
|
|
8800
|
+
setSiblingHintRect(null);
|
|
8801
|
+
setSiblingHintRects([]);
|
|
8802
|
+
setIsItemDragging(false);
|
|
8803
|
+
el.setAttribute("contenteditable", "true");
|
|
8804
|
+
el.removeAttribute("data-ohw-hovered");
|
|
8805
|
+
el.closest("[data-ohw-href-key]")?.removeAttribute("data-ohw-hovered");
|
|
8806
|
+
activeElRef.current = el;
|
|
8807
|
+
originalContentRef.current = el.innerHTML;
|
|
8808
|
+
el.focus();
|
|
8809
|
+
if (options?.caretX !== void 0 && options?.caretY !== void 0) {
|
|
8810
|
+
placeCaretAtPoint(el, options.caretX, options.caretY);
|
|
8811
|
+
}
|
|
8812
|
+
setToolbarShowEditLink(Boolean(getHrefKeyFromElement(el)));
|
|
8813
|
+
const navAnchor = getNavigationItemAnchor(el);
|
|
8814
|
+
if (navAnchor) {
|
|
8815
|
+
setReorderHrefKey(null);
|
|
8816
|
+
setReorderDragDisabled(false);
|
|
8817
|
+
} else {
|
|
8818
|
+
const { key: reorderKey, disabled: reorderDisabled } = getReorderHandleState(el);
|
|
8819
|
+
setReorderHrefKey(reorderKey);
|
|
8820
|
+
setReorderDragDisabled(reorderDisabled);
|
|
8821
|
+
}
|
|
8822
|
+
setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
8823
|
+
postToParent2({ type: "ow:enter-edit", key: el.dataset.ohwKey });
|
|
8824
|
+
requestAnimationFrame(() => refreshActiveCommandsRef.current());
|
|
8825
|
+
},
|
|
8826
|
+
[deactivate, postToParent2]
|
|
8827
|
+
);
|
|
7014
8828
|
activateRef.current = activate;
|
|
7015
8829
|
deactivateRef.current = deactivate;
|
|
7016
8830
|
selectRef.current = select;
|
|
8831
|
+
selectFrameRef.current = selectFrame;
|
|
7017
8832
|
deselectRef.current = deselect;
|
|
7018
|
-
(0,
|
|
8833
|
+
(0, import_react9.useLayoutEffect)(() => {
|
|
7019
8834
|
if (!subdomain || isEditMode) {
|
|
7020
8835
|
setFetchState("done");
|
|
7021
8836
|
return;
|
|
@@ -7025,6 +8840,7 @@ function OhhwellsBridge() {
|
|
|
7025
8840
|
for (const [key, val] of Object.entries(content)) {
|
|
7026
8841
|
if (key === "__ohw_sections") continue;
|
|
7027
8842
|
if (applyVideoSettingNode(key, val)) continue;
|
|
8843
|
+
if (applyCarouselNode(key, val)) continue;
|
|
7028
8844
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
7029
8845
|
if (el.dataset.ohwEditable === "image") {
|
|
7030
8846
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
@@ -7055,6 +8871,8 @@ function OhhwellsBridge() {
|
|
|
7055
8871
|
});
|
|
7056
8872
|
applyLinkByKey(key, val);
|
|
7057
8873
|
}
|
|
8874
|
+
reconcileNavbarItemsFromContent(content);
|
|
8875
|
+
reconcileFooterOrderFromContent(content);
|
|
7058
8876
|
enforceLinkHrefs();
|
|
7059
8877
|
initSectionsFromContent(content, true);
|
|
7060
8878
|
sectionsLoadedRef.current = true;
|
|
@@ -7083,7 +8901,7 @@ function OhhwellsBridge() {
|
|
|
7083
8901
|
cancelled = true;
|
|
7084
8902
|
};
|
|
7085
8903
|
}, [subdomain, isEditMode]);
|
|
7086
|
-
(0,
|
|
8904
|
+
(0, import_react9.useEffect)(() => {
|
|
7087
8905
|
if (!subdomain || isEditMode) return;
|
|
7088
8906
|
let debounceTimer = null;
|
|
7089
8907
|
let observer = null;
|
|
@@ -7096,6 +8914,7 @@ function OhhwellsBridge() {
|
|
|
7096
8914
|
for (const [key, val] of Object.entries(content)) {
|
|
7097
8915
|
if (key === "__ohw_sections") continue;
|
|
7098
8916
|
if (applyVideoSettingNode(key, val)) continue;
|
|
8917
|
+
if (applyCarouselNode(key, val)) continue;
|
|
7099
8918
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
7100
8919
|
if (el.dataset.ohwEditable === "image") {
|
|
7101
8920
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
@@ -7114,6 +8933,8 @@ function OhhwellsBridge() {
|
|
|
7114
8933
|
});
|
|
7115
8934
|
applyLinkByKey(key, val);
|
|
7116
8935
|
}
|
|
8936
|
+
reconcileNavbarItemsFromContent(content);
|
|
8937
|
+
reconcileFooterOrderFromContent(content);
|
|
7117
8938
|
} finally {
|
|
7118
8939
|
observer?.observe(document.body, { childList: true, subtree: true });
|
|
7119
8940
|
}
|
|
@@ -7131,26 +8952,71 @@ function OhhwellsBridge() {
|
|
|
7131
8952
|
if (debounceTimer) clearTimeout(debounceTimer);
|
|
7132
8953
|
};
|
|
7133
8954
|
}, [subdomain, isEditMode, pathname]);
|
|
7134
|
-
(0,
|
|
8955
|
+
(0, import_react9.useLayoutEffect)(() => {
|
|
7135
8956
|
const el = document.getElementById("ohw-loader");
|
|
7136
8957
|
if (!el) return;
|
|
7137
8958
|
const visible = Boolean(subdomain) && fetchState !== "done";
|
|
7138
8959
|
el.style.display = visible ? "flex" : "none";
|
|
7139
8960
|
}, [subdomain, fetchState]);
|
|
7140
|
-
(0,
|
|
7141
|
-
|
|
7142
|
-
}, [pathname,
|
|
7143
|
-
(0,
|
|
8961
|
+
(0, import_react9.useEffect)(() => {
|
|
8962
|
+
postToParent2({ type: "ow:navigation", path: pathname });
|
|
8963
|
+
}, [pathname, postToParent2]);
|
|
8964
|
+
(0, import_react9.useEffect)(() => {
|
|
7144
8965
|
if (!isEditMode) return;
|
|
8966
|
+
if (linkPopoverSessionRef.current?.intent === "add-nav") return;
|
|
8967
|
+
if (document.querySelector("[data-ohw-section-picker]")) return;
|
|
7145
8968
|
setLinkPopover(null);
|
|
7146
8969
|
deselectRef.current();
|
|
7147
8970
|
deactivateRef.current();
|
|
7148
8971
|
}, [pathname, isEditMode]);
|
|
7149
|
-
(0,
|
|
8972
|
+
(0, import_react9.useEffect)(() => {
|
|
8973
|
+
const contentForNav = () => {
|
|
8974
|
+
if (isEditMode) return editContentRef.current;
|
|
8975
|
+
if (!subdomain) return {};
|
|
8976
|
+
return contentCache.get(subdomain) ?? {};
|
|
8977
|
+
};
|
|
8978
|
+
let applying = false;
|
|
8979
|
+
let rafId = null;
|
|
8980
|
+
const run = () => {
|
|
8981
|
+
if (footerDragRef.current || applying) return;
|
|
8982
|
+
applying = true;
|
|
8983
|
+
try {
|
|
8984
|
+
const content = contentForNav();
|
|
8985
|
+
reconcileNavbarItemsFromContent(content);
|
|
8986
|
+
reconcileFooterOrderFromContent(content);
|
|
8987
|
+
document.querySelectorAll("footer [data-ohw-href-key]").forEach((el) => {
|
|
8988
|
+
if (isFooterHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
8989
|
+
disableNativeHrefDrag(el);
|
|
8990
|
+
}
|
|
8991
|
+
});
|
|
8992
|
+
} finally {
|
|
8993
|
+
applying = false;
|
|
8994
|
+
}
|
|
8995
|
+
};
|
|
8996
|
+
const scheduleRun = () => {
|
|
8997
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
8998
|
+
rafId = requestAnimationFrame(() => {
|
|
8999
|
+
rafId = null;
|
|
9000
|
+
run();
|
|
9001
|
+
});
|
|
9002
|
+
};
|
|
9003
|
+
run();
|
|
9004
|
+
const nav = document.querySelector("nav");
|
|
9005
|
+
const footer = document.querySelector("footer");
|
|
9006
|
+
const observer = new MutationObserver(scheduleRun);
|
|
9007
|
+
if (nav) observer.observe(nav, { childList: true, subtree: true });
|
|
9008
|
+
if (footer) observer.observe(footer, { childList: true, subtree: true });
|
|
9009
|
+
if (!nav && !footer) return;
|
|
9010
|
+
return () => {
|
|
9011
|
+
observer.disconnect();
|
|
9012
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
9013
|
+
};
|
|
9014
|
+
}, [isEditMode, pathname, subdomain, fetchState]);
|
|
9015
|
+
(0, import_react9.useEffect)(() => {
|
|
7150
9016
|
if (!isEditMode) return;
|
|
7151
9017
|
const measure = () => {
|
|
7152
9018
|
const h = document.body.scrollHeight;
|
|
7153
|
-
if (h > 50)
|
|
9019
|
+
if (h > 50) postToParent2({ type: "ow:height", height: h });
|
|
7154
9020
|
};
|
|
7155
9021
|
const t1 = setTimeout(measure, 50);
|
|
7156
9022
|
const t2 = setTimeout(measure, 500);
|
|
@@ -7169,8 +9035,8 @@ function OhhwellsBridge() {
|
|
|
7169
9035
|
if (resizeTimer) clearTimeout(resizeTimer);
|
|
7170
9036
|
window.removeEventListener("resize", handleResize);
|
|
7171
9037
|
};
|
|
7172
|
-
}, [pathname, isEditMode,
|
|
7173
|
-
(0,
|
|
9038
|
+
}, [pathname, isEditMode, postToParent2]);
|
|
9039
|
+
(0, import_react9.useEffect)(() => {
|
|
7174
9040
|
if (!subdomainFromQuery || isEditMode) return;
|
|
7175
9041
|
const handleClick = (e) => {
|
|
7176
9042
|
const anchor = e.target.closest("a");
|
|
@@ -7186,7 +9052,7 @@ function OhhwellsBridge() {
|
|
|
7186
9052
|
document.addEventListener("click", handleClick, true);
|
|
7187
9053
|
return () => document.removeEventListener("click", handleClick, true);
|
|
7188
9054
|
}, [subdomainFromQuery, isEditMode, router]);
|
|
7189
|
-
(0,
|
|
9055
|
+
(0, import_react9.useEffect)(() => {
|
|
7190
9056
|
if (!isEditMode) {
|
|
7191
9057
|
editStylesRef.current?.base.remove();
|
|
7192
9058
|
editStylesRef.current?.forceHover.remove();
|
|
@@ -7209,6 +9075,32 @@ function OhhwellsBridge() {
|
|
|
7209
9075
|
[data-ohw-editable] {
|
|
7210
9076
|
display: block;
|
|
7211
9077
|
}
|
|
9078
|
+
/* Native <a> drag steals clicks \u2014 disable for edit links; reorder via press-to-drag / handle. */
|
|
9079
|
+
footer [data-ohw-href-key] {
|
|
9080
|
+
-webkit-user-drag: none !important;
|
|
9081
|
+
}
|
|
9082
|
+
footer [data-ohw-footer-col]:hover {
|
|
9083
|
+
outline: 1.5px dashed ${PRIMARY2} !important;
|
|
9084
|
+
outline-offset: 6px;
|
|
9085
|
+
border-radius: 8px;
|
|
9086
|
+
}
|
|
9087
|
+
html[data-ohw-link-popover-open] footer [data-ohw-footer-col]:hover {
|
|
9088
|
+
outline: none !important;
|
|
9089
|
+
}
|
|
9090
|
+
html[data-ohw-footer-press-drag] footer,
|
|
9091
|
+
html[data-ohw-footer-press-drag] footer * {
|
|
9092
|
+
user-select: none !important;
|
|
9093
|
+
-webkit-user-select: none !important;
|
|
9094
|
+
}
|
|
9095
|
+
html[data-ohw-item-dragging] footer,
|
|
9096
|
+
html[data-ohw-item-dragging] footer * {
|
|
9097
|
+
user-select: none !important;
|
|
9098
|
+
-webkit-user-select: none !important;
|
|
9099
|
+
pointer-events: none !important;
|
|
9100
|
+
}
|
|
9101
|
+
html[data-ohw-item-dragging] {
|
|
9102
|
+
cursor: grabbing !important;
|
|
9103
|
+
}
|
|
7212
9104
|
[data-ohw-editable]:not([contenteditable]):not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]):not([data-ohw-editable="video"]) { cursor: text !important; }
|
|
7213
9105
|
[data-ohw-editable="image"], [data-ohw-editable="image"] *,
|
|
7214
9106
|
[data-ohw-editable="video"], [data-ohw-editable="video"] *,
|
|
@@ -7254,12 +9146,46 @@ function OhhwellsBridge() {
|
|
|
7254
9146
|
}
|
|
7255
9147
|
refreshStateRules();
|
|
7256
9148
|
const handleClick = (e) => {
|
|
9149
|
+
if (suppressNextClickRef.current) {
|
|
9150
|
+
suppressNextClickRef.current = false;
|
|
9151
|
+
e.preventDefault();
|
|
9152
|
+
e.stopPropagation();
|
|
9153
|
+
return;
|
|
9154
|
+
}
|
|
7257
9155
|
const target = e.target;
|
|
7258
9156
|
if (target.closest("[data-ohw-toolbar]")) return;
|
|
7259
9157
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
7260
9158
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
7261
9159
|
if (isInsideLinkEditor(target)) return;
|
|
7262
9160
|
if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
9161
|
+
if (target.closest("[data-ohw-item-drag-surface]")) {
|
|
9162
|
+
e.preventDefault();
|
|
9163
|
+
e.stopPropagation();
|
|
9164
|
+
const selected = selectedElRef.current;
|
|
9165
|
+
if (selected && isNavigationItem(selected)) {
|
|
9166
|
+
const editable2 = selected.querySelector('[data-ohw-editable="text"]') ?? selected.querySelector("[data-ohw-editable]");
|
|
9167
|
+
if (editable2) {
|
|
9168
|
+
activateRef.current(editable2, {
|
|
9169
|
+
caretX: e.clientX,
|
|
9170
|
+
caretY: e.clientY
|
|
9171
|
+
});
|
|
9172
|
+
}
|
|
9173
|
+
} else if (selected?.hasAttribute("data-ohw-footer-col")) {
|
|
9174
|
+
const link = listFooterLinksInColumn(selected).find((el) => {
|
|
9175
|
+
const r2 = el.getBoundingClientRect();
|
|
9176
|
+
return e.clientX >= r2.left && e.clientX <= r2.right && e.clientY >= r2.top && e.clientY <= r2.bottom;
|
|
9177
|
+
});
|
|
9178
|
+
if (link) selectRef.current(link);
|
|
9179
|
+
}
|
|
9180
|
+
return;
|
|
9181
|
+
}
|
|
9182
|
+
const navFromChrome = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
|
|
9183
|
+
if (navFromChrome) {
|
|
9184
|
+
e.preventDefault();
|
|
9185
|
+
e.stopPropagation();
|
|
9186
|
+
selectFrameRef.current(navFromChrome);
|
|
9187
|
+
return;
|
|
9188
|
+
}
|
|
7263
9189
|
e.preventDefault();
|
|
7264
9190
|
e.stopPropagation();
|
|
7265
9191
|
return;
|
|
@@ -7274,7 +9200,8 @@ function OhhwellsBridge() {
|
|
|
7274
9200
|
bumpLinkPopoverGrace();
|
|
7275
9201
|
setLinkPopoverRef.current({
|
|
7276
9202
|
key: editable.dataset.ohwKey ?? "",
|
|
7277
|
-
|
|
9203
|
+
mode: "edit",
|
|
9204
|
+
target: getLinkHref2(editable)
|
|
7278
9205
|
});
|
|
7279
9206
|
return;
|
|
7280
9207
|
}
|
|
@@ -7290,7 +9217,8 @@ function OhhwellsBridge() {
|
|
|
7290
9217
|
e.preventDefault();
|
|
7291
9218
|
e.stopPropagation();
|
|
7292
9219
|
if (selectedElRef.current === navAnchor) {
|
|
7293
|
-
|
|
9220
|
+
if (e.detail >= 2) return;
|
|
9221
|
+
activateRef.current(editable, { caretX: e.clientX, caretY: e.clientY });
|
|
7294
9222
|
return;
|
|
7295
9223
|
}
|
|
7296
9224
|
selectRef.current(navAnchor);
|
|
@@ -7305,10 +9233,42 @@ function OhhwellsBridge() {
|
|
|
7305
9233
|
if (hrefAnchor) {
|
|
7306
9234
|
e.preventDefault();
|
|
7307
9235
|
e.stopPropagation();
|
|
7308
|
-
if (selectedElRef.current === hrefAnchor)
|
|
9236
|
+
if (selectedElRef.current === hrefAnchor) {
|
|
9237
|
+
const textEditable = hrefAnchor.querySelector('[data-ohw-editable="text"]') ?? hrefAnchor.querySelector("[data-ohw-editable]");
|
|
9238
|
+
if (textEditable) {
|
|
9239
|
+
activateRef.current(textEditable, {
|
|
9240
|
+
caretX: e.clientX,
|
|
9241
|
+
caretY: e.clientY
|
|
9242
|
+
});
|
|
9243
|
+
}
|
|
9244
|
+
return;
|
|
9245
|
+
}
|
|
7309
9246
|
selectRef.current(hrefAnchor);
|
|
7310
9247
|
return;
|
|
7311
9248
|
}
|
|
9249
|
+
const footerColClick = target.closest("[data-ohw-footer-col]");
|
|
9250
|
+
if (footerColClick) {
|
|
9251
|
+
e.preventDefault();
|
|
9252
|
+
e.stopPropagation();
|
|
9253
|
+
selectFrameRef.current(footerColClick);
|
|
9254
|
+
return;
|
|
9255
|
+
}
|
|
9256
|
+
const navContainerToSelect = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
|
|
9257
|
+
if (navContainerToSelect) {
|
|
9258
|
+
e.preventDefault();
|
|
9259
|
+
e.stopPropagation();
|
|
9260
|
+
selectFrameRef.current(navContainerToSelect);
|
|
9261
|
+
return;
|
|
9262
|
+
}
|
|
9263
|
+
const selectedContainer = selectedElRef.current;
|
|
9264
|
+
if (selectedContainer && isNavigationContainer(selectedContainer)) {
|
|
9265
|
+
const navItem = getNavigationItemAnchor(target);
|
|
9266
|
+
if (!navItem && (selectedContainer === target || selectedContainer.contains(target))) {
|
|
9267
|
+
e.preventDefault();
|
|
9268
|
+
e.stopPropagation();
|
|
9269
|
+
return;
|
|
9270
|
+
}
|
|
9271
|
+
}
|
|
7312
9272
|
if (activeElRef.current) {
|
|
7313
9273
|
const sel = window.getSelection();
|
|
7314
9274
|
if (sel && !sel.isCollapsed) {
|
|
@@ -7334,10 +9294,65 @@ function OhhwellsBridge() {
|
|
|
7334
9294
|
deselectRef.current();
|
|
7335
9295
|
deactivateRef.current();
|
|
7336
9296
|
};
|
|
9297
|
+
const handleDblClick = (e) => {
|
|
9298
|
+
const target = e.target;
|
|
9299
|
+
if (target.closest("[data-ohw-toolbar]")) return;
|
|
9300
|
+
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
9301
|
+
if (target.closest("[data-ohw-max-badge]")) return;
|
|
9302
|
+
if (isInsideLinkEditor(target)) return;
|
|
9303
|
+
if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
9304
|
+
return;
|
|
9305
|
+
}
|
|
9306
|
+
const navLabel = getNavigationLabelEditable(target);
|
|
9307
|
+
if (!navLabel) return;
|
|
9308
|
+
const { editable } = navLabel;
|
|
9309
|
+
e.preventDefault();
|
|
9310
|
+
e.stopPropagation();
|
|
9311
|
+
if (activeElRef.current !== editable) {
|
|
9312
|
+
activateRef.current(editable);
|
|
9313
|
+
}
|
|
9314
|
+
requestAnimationFrame(() => {
|
|
9315
|
+
selectAllTextInEditable(editable);
|
|
9316
|
+
refreshActiveCommandsRef.current();
|
|
9317
|
+
});
|
|
9318
|
+
};
|
|
7337
9319
|
const handleMouseOver = (e) => {
|
|
9320
|
+
if (document.documentElement.hasAttribute("data-ohw-section-picking")) return;
|
|
7338
9321
|
const target = e.target;
|
|
9322
|
+
if (linkPopoverOpenRef.current) {
|
|
9323
|
+
hoveredItemElRef.current = null;
|
|
9324
|
+
setHoveredItemRect(null);
|
|
9325
|
+
hoveredNavContainerRef.current = null;
|
|
9326
|
+
setHoveredNavContainerRect(null);
|
|
9327
|
+
return;
|
|
9328
|
+
}
|
|
9329
|
+
if (toolbarVariantRef.current !== "select-frame") {
|
|
9330
|
+
const navContainer = target.closest("[data-ohw-nav-container]");
|
|
9331
|
+
if (navContainer && !getNavigationItemAnchor(target)) {
|
|
9332
|
+
hoveredNavContainerRef.current = navContainer;
|
|
9333
|
+
setHoveredNavContainerRect(navContainer.getBoundingClientRect());
|
|
9334
|
+
hoveredItemElRef.current = null;
|
|
9335
|
+
setHoveredItemRect(null);
|
|
9336
|
+
return;
|
|
9337
|
+
}
|
|
9338
|
+
if (!target.closest("[data-ohw-nav-container]")) {
|
|
9339
|
+
hoveredNavContainerRef.current = null;
|
|
9340
|
+
setHoveredNavContainerRect(null);
|
|
9341
|
+
}
|
|
9342
|
+
}
|
|
9343
|
+
const footerCol = target.closest("[data-ohw-footer-col]");
|
|
9344
|
+
if (footerCol) {
|
|
9345
|
+
hoveredNavContainerRef.current = null;
|
|
9346
|
+
setHoveredNavContainerRect(null);
|
|
9347
|
+
if (selectedElRef.current === footerCol) return;
|
|
9348
|
+
hoveredItemElRef.current = footerCol;
|
|
9349
|
+
setHoveredItemRect(footerCol.getBoundingClientRect());
|
|
9350
|
+
return;
|
|
9351
|
+
}
|
|
7339
9352
|
const navAnchor = getNavigationItemAnchor(target);
|
|
7340
9353
|
if (navAnchor) {
|
|
9354
|
+
hoveredNavContainerRef.current = null;
|
|
9355
|
+
setHoveredNavContainerRect(null);
|
|
7341
9356
|
const selected2 = selectedElRef.current;
|
|
7342
9357
|
if (selected2 === navAnchor || selected2?.contains(navAnchor)) return;
|
|
7343
9358
|
clearHrefKeyHover(navAnchor);
|
|
@@ -7362,6 +9377,23 @@ function OhhwellsBridge() {
|
|
|
7362
9377
|
};
|
|
7363
9378
|
const handleMouseOut = (e) => {
|
|
7364
9379
|
const target = e.target;
|
|
9380
|
+
if (target.closest("[data-ohw-nav-container]")) {
|
|
9381
|
+
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
9382
|
+
if (related2?.closest("[data-ohw-nav-container], [data-ohw-navbar-container-chrome], [data-ohw-navbar-add-button]")) {
|
|
9383
|
+
return;
|
|
9384
|
+
}
|
|
9385
|
+
hoveredNavContainerRef.current = null;
|
|
9386
|
+
setHoveredNavContainerRect(null);
|
|
9387
|
+
}
|
|
9388
|
+
const footerCol = target.closest("[data-ohw-footer-col]");
|
|
9389
|
+
if (footerCol && hoveredItemElRef.current === footerCol) {
|
|
9390
|
+
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
9391
|
+
if (related2?.closest("[data-ohw-drag-handle-container], [data-ohw-item-interaction]")) return;
|
|
9392
|
+
if (related2?.closest("[data-ohw-footer-col]") === footerCol) return;
|
|
9393
|
+
hoveredItemElRef.current = null;
|
|
9394
|
+
setHoveredItemRect(null);
|
|
9395
|
+
return;
|
|
9396
|
+
}
|
|
7365
9397
|
const navAnchor = getNavigationItemAnchor(target);
|
|
7366
9398
|
if (navAnchor) {
|
|
7367
9399
|
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
@@ -7483,44 +9515,87 @@ function OhhwellsBridge() {
|
|
|
7483
9515
|
}
|
|
7484
9516
|
return smallest;
|
|
7485
9517
|
};
|
|
9518
|
+
const dismissImageHover = () => {
|
|
9519
|
+
if (hoveredImageRef.current) {
|
|
9520
|
+
hoveredImageRef.current = null;
|
|
9521
|
+
hoveredImageHasTextOverlapRef.current = false;
|
|
9522
|
+
resumeAnimTracks();
|
|
9523
|
+
postToParentRef.current({ type: "ow:image-unhover" });
|
|
9524
|
+
}
|
|
9525
|
+
clearImageHover();
|
|
9526
|
+
};
|
|
9527
|
+
const probeNavigationHoverAt = (x, y) => {
|
|
9528
|
+
if (toolbarVariantRef.current === "select-frame") {
|
|
9529
|
+
hoveredNavContainerRef.current = null;
|
|
9530
|
+
setHoveredNavContainerRect(null);
|
|
9531
|
+
return;
|
|
9532
|
+
}
|
|
9533
|
+
const navContainer = document.querySelector("[data-ohw-nav-container]");
|
|
9534
|
+
if (!navContainer) {
|
|
9535
|
+
hoveredNavContainerRef.current = null;
|
|
9536
|
+
setHoveredNavContainerRect(null);
|
|
9537
|
+
return;
|
|
9538
|
+
}
|
|
9539
|
+
const containerRect = navContainer.getBoundingClientRect();
|
|
9540
|
+
const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
|
|
9541
|
+
if (!overContainer) {
|
|
9542
|
+
hoveredNavContainerRef.current = null;
|
|
9543
|
+
setHoveredNavContainerRect(null);
|
|
9544
|
+
return;
|
|
9545
|
+
}
|
|
9546
|
+
const navItemHit = Array.from(
|
|
9547
|
+
navContainer.querySelectorAll("[data-ohw-href-key]")
|
|
9548
|
+
).find((el) => {
|
|
9549
|
+
if (!isNavigationItem(el) || isNavbarButton2(el)) return false;
|
|
9550
|
+
const itemRect = el.getBoundingClientRect();
|
|
9551
|
+
return x >= itemRect.left && x <= itemRect.right && y >= itemRect.top && y <= itemRect.bottom;
|
|
9552
|
+
});
|
|
9553
|
+
if (navItemHit) {
|
|
9554
|
+
hoveredNavContainerRef.current = null;
|
|
9555
|
+
setHoveredNavContainerRect(null);
|
|
9556
|
+
const selected = selectedElRef.current;
|
|
9557
|
+
if (selected !== navItemHit && !selected?.contains(navItemHit)) {
|
|
9558
|
+
clearHrefKeyHover(navItemHit);
|
|
9559
|
+
hoveredItemElRef.current = navItemHit;
|
|
9560
|
+
setHoveredItemRect(navItemHit.getBoundingClientRect());
|
|
9561
|
+
}
|
|
9562
|
+
return;
|
|
9563
|
+
}
|
|
9564
|
+
hoveredNavContainerRef.current = navContainer;
|
|
9565
|
+
setHoveredNavContainerRect(containerRect);
|
|
9566
|
+
hoveredItemElRef.current = null;
|
|
9567
|
+
setHoveredItemRect(null);
|
|
9568
|
+
};
|
|
7486
9569
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
7487
9570
|
if (linkPopoverOpenRef.current) {
|
|
7488
|
-
|
|
7489
|
-
|
|
7490
|
-
|
|
7491
|
-
|
|
7492
|
-
|
|
7493
|
-
|
|
9571
|
+
dismissImageHover();
|
|
9572
|
+
return;
|
|
9573
|
+
}
|
|
9574
|
+
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
9575
|
+
if (isPointOverNavigation(x, y)) {
|
|
9576
|
+
dismissImageHover();
|
|
9577
|
+
probeNavigationHoverAt(x, y);
|
|
7494
9578
|
return;
|
|
7495
9579
|
}
|
|
9580
|
+
hoveredNavContainerRef.current = null;
|
|
9581
|
+
setHoveredNavContainerRect(null);
|
|
7496
9582
|
const toggleEl = document.querySelector("[data-ohw-state-toggle]");
|
|
7497
9583
|
if (toggleEl) {
|
|
7498
|
-
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
7499
9584
|
const tr = toggleEl.getBoundingClientRect();
|
|
7500
9585
|
if (x >= tr.left && x <= tr.right && y >= tr.top && y <= tr.bottom) {
|
|
7501
|
-
|
|
7502
|
-
hoveredImageRef.current = null;
|
|
7503
|
-
resumeAnimTracks();
|
|
7504
|
-
clearImageHover();
|
|
7505
|
-
}
|
|
9586
|
+
dismissImageHover();
|
|
7506
9587
|
return;
|
|
7507
9588
|
}
|
|
7508
9589
|
}
|
|
7509
9590
|
const imgEl = findImageAtPoint(clientX, clientY, fromParentViewport);
|
|
7510
9591
|
const activeEl = activeElRef.current;
|
|
7511
9592
|
if (activeEl && (!imgEl || imgEl.contains(activeEl))) {
|
|
7512
|
-
|
|
7513
|
-
hoveredImageRef.current = null;
|
|
7514
|
-
hoveredImageHasTextOverlapRef.current = false;
|
|
7515
|
-
resumeAnimTracks();
|
|
7516
|
-
clearImageHover();
|
|
7517
|
-
}
|
|
9593
|
+
dismissImageHover();
|
|
7518
9594
|
return;
|
|
7519
9595
|
}
|
|
7520
9596
|
if (imgEl) {
|
|
7521
|
-
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
7522
9597
|
const topEl = document.elementFromPoint(x, y);
|
|
7523
|
-
if (topEl?.closest('[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
9598
|
+
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]')) {
|
|
7524
9599
|
if (hoveredImageRef.current) {
|
|
7525
9600
|
hoveredImageRef.current = null;
|
|
7526
9601
|
resumeAnimTracks();
|
|
@@ -7618,12 +9693,12 @@ function OhhwellsBridge() {
|
|
|
7618
9693
|
resumeAnimTracks();
|
|
7619
9694
|
clearImageHover();
|
|
7620
9695
|
}
|
|
7621
|
-
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
9696
|
+
const { x: x2, y: y2 } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
7622
9697
|
const textEl = Array.from(
|
|
7623
9698
|
document.querySelectorAll(NON_MEDIA_SELECTOR)
|
|
7624
9699
|
).find((el) => {
|
|
7625
9700
|
const er = el.getBoundingClientRect();
|
|
7626
|
-
return
|
|
9701
|
+
return x2 >= er.left && x2 <= er.right && y2 >= er.top && y2 <= er.bottom;
|
|
7627
9702
|
});
|
|
7628
9703
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
7629
9704
|
if (textEl && !textEl.hasAttribute("contenteditable")) {
|
|
@@ -7647,6 +9722,14 @@ function OhhwellsBridge() {
|
|
|
7647
9722
|
}
|
|
7648
9723
|
};
|
|
7649
9724
|
const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
|
|
9725
|
+
if (linkPopoverOpenRef.current || document.documentElement.hasAttribute("data-ohw-section-picking")) {
|
|
9726
|
+
if (activeStateElRef.current) {
|
|
9727
|
+
activeStateElRef.current.removeAttribute("data-ohw-state-hovered");
|
|
9728
|
+
activeStateElRef.current = null;
|
|
9729
|
+
setToggleState(null);
|
|
9730
|
+
}
|
|
9731
|
+
return;
|
|
9732
|
+
}
|
|
7650
9733
|
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
7651
9734
|
const toggleEl = document.querySelector("[data-ohw-state-toggle]");
|
|
7652
9735
|
if (toggleEl) {
|
|
@@ -7719,6 +9802,14 @@ function OhhwellsBridge() {
|
|
|
7719
9802
|
probeHoverCardsAt(clientX, clientY);
|
|
7720
9803
|
};
|
|
7721
9804
|
const handleDragOver = (e) => {
|
|
9805
|
+
const footerSession = footerDragRef.current;
|
|
9806
|
+
if (footerSession) {
|
|
9807
|
+
e.preventDefault();
|
|
9808
|
+
if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
|
|
9809
|
+
const slot = footerSession.kind === "link" && footerSession.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, footerSession.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
|
|
9810
|
+
refreshFooterDragVisualsRef.current(footerSession, slot, e.clientX, e.clientY);
|
|
9811
|
+
return;
|
|
9812
|
+
}
|
|
7722
9813
|
e.preventDefault();
|
|
7723
9814
|
const el = findImageAtPoint(e.clientX, e.clientY, false);
|
|
7724
9815
|
if (!el) {
|
|
@@ -7901,6 +9992,7 @@ function OhhwellsBridge() {
|
|
|
7901
9992
|
continue;
|
|
7902
9993
|
}
|
|
7903
9994
|
if (applyVideoSettingNode(key, val)) continue;
|
|
9995
|
+
if (applyCarouselNode(key, val)) continue;
|
|
7904
9996
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
7905
9997
|
if (el.dataset.ohwEditable === "image") {
|
|
7906
9998
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
@@ -7923,6 +10015,9 @@ function OhhwellsBridge() {
|
|
|
7923
10015
|
sectionsLoadedRef.current = true;
|
|
7924
10016
|
pendingScheduleConfigRequests.current.splice(0).forEach(processConfigRequest);
|
|
7925
10017
|
}
|
|
10018
|
+
editContentRef.current = { ...editContentRef.current, ...content };
|
|
10019
|
+
reconcileNavbarItemsFromContent(editContentRef.current);
|
|
10020
|
+
reconcileFooterOrderFromContent(editContentRef.current);
|
|
7926
10021
|
enforceLinkHrefs();
|
|
7927
10022
|
postToParentRef.current({ type: "ow:hydrate-done" });
|
|
7928
10023
|
};
|
|
@@ -7930,6 +10025,7 @@ function OhhwellsBridge() {
|
|
|
7930
10025
|
const handleDeactivate = (e) => {
|
|
7931
10026
|
if (e.data?.type !== "ow:deactivate") return;
|
|
7932
10027
|
if (Date.now() < linkPopoverGraceUntilRef.current) return;
|
|
10028
|
+
if (document.querySelector("[data-ohw-section-picker]")) return;
|
|
7933
10029
|
if (linkPopoverOpenRef.current) {
|
|
7934
10030
|
setLinkPopoverRef.current(null);
|
|
7935
10031
|
return;
|
|
@@ -7938,13 +10034,40 @@ function OhhwellsBridge() {
|
|
|
7938
10034
|
deactivateRef.current();
|
|
7939
10035
|
};
|
|
7940
10036
|
window.addEventListener("message", handleDeactivate);
|
|
10037
|
+
const handleUiEscape = (e) => {
|
|
10038
|
+
if (e.data?.type !== "ui:escape") return;
|
|
10039
|
+
if (linkPopoverOpenRef.current) {
|
|
10040
|
+
setLinkPopoverRef.current(null);
|
|
10041
|
+
}
|
|
10042
|
+
};
|
|
10043
|
+
window.addEventListener("message", handleUiEscape);
|
|
7941
10044
|
const handleKeyDown = (e) => {
|
|
10045
|
+
if (e.key === "Escape" && document.querySelector("[data-ohw-section-picker]")) return;
|
|
10046
|
+
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "a" && activeElRef.current) {
|
|
10047
|
+
const navAnchor = getNavigationItemAnchor(activeElRef.current);
|
|
10048
|
+
if (navAnchor) {
|
|
10049
|
+
e.preventDefault();
|
|
10050
|
+
selectAllTextInEditable(activeElRef.current);
|
|
10051
|
+
refreshActiveCommandsRef.current();
|
|
10052
|
+
return;
|
|
10053
|
+
}
|
|
10054
|
+
}
|
|
7942
10055
|
if (e.key === "Escape" && linkPopoverOpenRef.current) {
|
|
7943
10056
|
setLinkPopoverRef.current(null);
|
|
7944
10057
|
return;
|
|
7945
10058
|
}
|
|
7946
10059
|
if (e.key === "Escape" && selectedElRef.current && !activeElRef.current) {
|
|
7947
|
-
|
|
10060
|
+
if (toolbarVariantRef.current === "select-frame") {
|
|
10061
|
+
deselectRef.current();
|
|
10062
|
+
return;
|
|
10063
|
+
}
|
|
10064
|
+
const parent = getNavigationSelectionParent(selectedElRef.current);
|
|
10065
|
+
if (parent) {
|
|
10066
|
+
e.preventDefault();
|
|
10067
|
+
selectFrameRef.current(parent);
|
|
10068
|
+
} else {
|
|
10069
|
+
deselectRef.current();
|
|
10070
|
+
}
|
|
7948
10071
|
return;
|
|
7949
10072
|
}
|
|
7950
10073
|
if (e.key === "Escape" && activeElRef.current) {
|
|
@@ -8002,9 +10125,23 @@ function OhhwellsBridge() {
|
|
|
8002
10125
|
if (hoveredItemElRef.current) {
|
|
8003
10126
|
setHoveredItemRect(hoveredItemElRef.current.getBoundingClientRect());
|
|
8004
10127
|
}
|
|
10128
|
+
if (hoveredNavContainerRef.current) {
|
|
10129
|
+
setHoveredNavContainerRect(hoveredNavContainerRef.current.getBoundingClientRect());
|
|
10130
|
+
}
|
|
8005
10131
|
if (siblingHintElRef.current) {
|
|
8006
10132
|
setSiblingHintRect(siblingHintElRef.current.getBoundingClientRect());
|
|
8007
10133
|
}
|
|
10134
|
+
const selected = selectedElRef.current;
|
|
10135
|
+
if (selected && !footerDragRef.current && (selected.hasAttribute("data-ohw-footer-col") || Boolean(selected.closest("footer") && isInferredFooterGroup(selected)))) {
|
|
10136
|
+
setSiblingHintRects(
|
|
10137
|
+
listFooterColumns().filter((column) => column !== selected).map((column) => column.getBoundingClientRect())
|
|
10138
|
+
);
|
|
10139
|
+
}
|
|
10140
|
+
if (footerDragRef.current) {
|
|
10141
|
+
const session = footerDragRef.current;
|
|
10142
|
+
const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
|
|
10143
|
+
refreshFooterDragVisualsRef.current(session, slot, session.lastClientX, session.lastClientY);
|
|
10144
|
+
}
|
|
8008
10145
|
if (hoveredImageRef.current) {
|
|
8009
10146
|
const el = hoveredImageRef.current;
|
|
8010
10147
|
const r2 = el.getBoundingClientRect();
|
|
@@ -8015,7 +10152,7 @@ function OhhwellsBridge() {
|
|
|
8015
10152
|
};
|
|
8016
10153
|
const handleSave = (e) => {
|
|
8017
10154
|
if (e.data?.type !== "ow:save") return;
|
|
8018
|
-
const nodes = collectEditableNodes();
|
|
10155
|
+
const nodes = collectEditableNodes(editContentRef.current);
|
|
8019
10156
|
const tracker = document.querySelector("[data-ohw-sections-tracker]");
|
|
8020
10157
|
if (tracker?.textContent) nodes.push({ key: "__ohw_sections", type: "sections", text: tracker.textContent });
|
|
8021
10158
|
postToParentRef.current({ type: "ow:save-result", nodes });
|
|
@@ -8100,6 +10237,7 @@ function OhhwellsBridge() {
|
|
|
8100
10237
|
const handleDocMouseLeave = () => {
|
|
8101
10238
|
hoveredImageRef.current = null;
|
|
8102
10239
|
setMediaHover(null);
|
|
10240
|
+
setCarouselHover(null);
|
|
8103
10241
|
document.querySelectorAll("[data-ohw-state-hovered]").forEach((el) => el.removeAttribute("data-ohw-state-hovered"));
|
|
8104
10242
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
8105
10243
|
activeStateElRef.current = null;
|
|
@@ -8139,6 +10277,48 @@ function OhhwellsBridge() {
|
|
|
8139
10277
|
if (e.data?.type !== "ow:canvas-height" || typeof e.data.height !== "number") return;
|
|
8140
10278
|
document.documentElement.style.setProperty("--ohw-canvas-h", `${e.data.height}px`);
|
|
8141
10279
|
};
|
|
10280
|
+
const handleCarouselChange = (e) => {
|
|
10281
|
+
if (e.data?.type !== "ow:carousel-change") return;
|
|
10282
|
+
const { key, images } = e.data;
|
|
10283
|
+
if (!key || !Array.isArray(images)) return;
|
|
10284
|
+
const text = JSON.stringify(images);
|
|
10285
|
+
applyCarouselValue(key, images);
|
|
10286
|
+
editContentRef.current = { ...editContentRef.current, [key]: text };
|
|
10287
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key, text }] });
|
|
10288
|
+
setCarouselHover(null);
|
|
10289
|
+
};
|
|
10290
|
+
const findCarouselAtPoint = (clientX, clientY) => {
|
|
10291
|
+
const containers = Array.from(document.querySelectorAll(`[${CAROUSEL_ATTR}]`));
|
|
10292
|
+
for (let i = containers.length - 1; i >= 0; i--) {
|
|
10293
|
+
const r2 = containers[i].getBoundingClientRect();
|
|
10294
|
+
if (clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom) {
|
|
10295
|
+
return containers[i];
|
|
10296
|
+
}
|
|
10297
|
+
}
|
|
10298
|
+
return null;
|
|
10299
|
+
};
|
|
10300
|
+
const isPointOverEditable = (scope, clientX, clientY) => {
|
|
10301
|
+
const editables = scope.querySelectorAll("[data-ohw-editable], [data-ohw-href-key]");
|
|
10302
|
+
for (const el of editables) {
|
|
10303
|
+
const r2 = el.getBoundingClientRect();
|
|
10304
|
+
if (clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom) return true;
|
|
10305
|
+
}
|
|
10306
|
+
return false;
|
|
10307
|
+
};
|
|
10308
|
+
const handleCarouselHover = (e) => {
|
|
10309
|
+
const container = findCarouselAtPoint(e.clientX, e.clientY);
|
|
10310
|
+
const scope = container?.closest("[data-ohw-section]") ?? container?.parentElement ?? null;
|
|
10311
|
+
if (!container || !scope || isPointOverEditable(scope, e.clientX, e.clientY)) {
|
|
10312
|
+
setCarouselHover((prev) => prev ? null : prev);
|
|
10313
|
+
return;
|
|
10314
|
+
}
|
|
10315
|
+
const key = container.getAttribute("data-ohw-key") ?? "";
|
|
10316
|
+
if (!key) return;
|
|
10317
|
+
const r2 = getVisibleRect(container);
|
|
10318
|
+
setCarouselHover(
|
|
10319
|
+
(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 } }
|
|
10320
|
+
);
|
|
10321
|
+
};
|
|
8142
10322
|
const applyToolbarPos = (rect) => {
|
|
8143
10323
|
const ps = parentScrollRef.current;
|
|
8144
10324
|
const approxW = 330;
|
|
@@ -8198,9 +10378,45 @@ function OhhwellsBridge() {
|
|
|
8198
10378
|
return clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
|
|
8199
10379
|
});
|
|
8200
10380
|
if (textEditable) {
|
|
8201
|
-
|
|
10381
|
+
const hrefCtx = getHrefKeyFromElement(textEditable);
|
|
10382
|
+
const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
|
|
10383
|
+
if (navAnchor) {
|
|
10384
|
+
if (selectedElRef.current === navAnchor) {
|
|
10385
|
+
activateRef.current(textEditable, { caretX: clientX, caretY: clientY });
|
|
10386
|
+
} else {
|
|
10387
|
+
selectRef.current(navAnchor);
|
|
10388
|
+
}
|
|
10389
|
+
return;
|
|
10390
|
+
}
|
|
10391
|
+
activateRef.current(textEditable, { caretX: clientX, caretY: clientY });
|
|
8202
10392
|
return;
|
|
8203
10393
|
}
|
|
10394
|
+
const navContainer = document.querySelector("[data-ohw-nav-container]");
|
|
10395
|
+
if (navContainer) {
|
|
10396
|
+
const r2 = navContainer.getBoundingClientRect();
|
|
10397
|
+
const pad = 8;
|
|
10398
|
+
const over = clientX >= r2.left - pad && clientX <= r2.right + pad && clientY >= r2.top - pad && clientY <= r2.bottom + pad;
|
|
10399
|
+
if (over && !isPointOverNavItem(navContainer, clientX, clientY)) {
|
|
10400
|
+
selectFrameRef.current(navContainer);
|
|
10401
|
+
return;
|
|
10402
|
+
}
|
|
10403
|
+
}
|
|
10404
|
+
const navRoot = document.querySelector("[data-ohw-nav-root]");
|
|
10405
|
+
if (navRoot && navContainer) {
|
|
10406
|
+
const rr = navRoot.getBoundingClientRect();
|
|
10407
|
+
if (clientX >= rr.left && clientX <= rr.right && clientY >= rr.top && clientY <= rr.bottom && !isPointOverNavItem(navContainer, clientX, clientY)) {
|
|
10408
|
+
const book = navRoot.querySelector('[data-ohw-role="navbar-button"]');
|
|
10409
|
+
if (book) {
|
|
10410
|
+
const br = book.getBoundingClientRect();
|
|
10411
|
+
if (clientX >= br.left && clientX <= br.right && clientY >= br.top && clientY <= br.bottom) {
|
|
10412
|
+
deactivateRef.current();
|
|
10413
|
+
return;
|
|
10414
|
+
}
|
|
10415
|
+
}
|
|
10416
|
+
selectFrameRef.current(navContainer);
|
|
10417
|
+
return;
|
|
10418
|
+
}
|
|
10419
|
+
}
|
|
8204
10420
|
deactivateRef.current();
|
|
8205
10421
|
};
|
|
8206
10422
|
window.addEventListener("message", handleSave);
|
|
@@ -8211,6 +10427,7 @@ function OhhwellsBridge() {
|
|
|
8211
10427
|
window.addEventListener("message", handleRemoveSchedulingSection);
|
|
8212
10428
|
window.addEventListener("message", handleImageUrl);
|
|
8213
10429
|
window.addEventListener("message", handleImageUploading);
|
|
10430
|
+
window.addEventListener("message", handleCarouselChange);
|
|
8214
10431
|
window.addEventListener("message", handleCanvasHeight);
|
|
8215
10432
|
window.addEventListener("message", handleParentScroll);
|
|
8216
10433
|
window.addEventListener("message", handlePointerSync);
|
|
@@ -8222,11 +10439,13 @@ function OhhwellsBridge() {
|
|
|
8222
10439
|
};
|
|
8223
10440
|
window.addEventListener("resize", handleViewportResize, { passive: true });
|
|
8224
10441
|
document.addEventListener("click", handleClick, true);
|
|
10442
|
+
document.addEventListener("dblclick", handleDblClick, true);
|
|
8225
10443
|
document.addEventListener("paste", handlePaste, true);
|
|
8226
10444
|
document.addEventListener("input", handleInput, true);
|
|
8227
10445
|
document.addEventListener("mouseover", handleMouseOver, true);
|
|
8228
10446
|
document.addEventListener("mouseout", handleMouseOut, true);
|
|
8229
10447
|
document.addEventListener("mousemove", handleMouseMove, true);
|
|
10448
|
+
document.addEventListener("mousemove", handleCarouselHover, true);
|
|
8230
10449
|
document.addEventListener("mouseleave", handleDocMouseLeave);
|
|
8231
10450
|
document.addEventListener("dragover", handleDragOver, true);
|
|
8232
10451
|
document.addEventListener("dragleave", handleDragLeave, true);
|
|
@@ -8236,11 +10455,13 @@ function OhhwellsBridge() {
|
|
|
8236
10455
|
window.addEventListener("scroll", handleScroll, true);
|
|
8237
10456
|
return () => {
|
|
8238
10457
|
document.removeEventListener("click", handleClick, true);
|
|
10458
|
+
document.removeEventListener("dblclick", handleDblClick, true);
|
|
8239
10459
|
document.removeEventListener("paste", handlePaste, true);
|
|
8240
10460
|
document.removeEventListener("input", handleInput, true);
|
|
8241
10461
|
document.removeEventListener("mouseover", handleMouseOver, true);
|
|
8242
10462
|
document.removeEventListener("mouseout", handleMouseOut, true);
|
|
8243
10463
|
document.removeEventListener("mousemove", handleMouseMove, true);
|
|
10464
|
+
document.removeEventListener("mousemove", handleCarouselHover, true);
|
|
8244
10465
|
document.removeEventListener("mouseleave", handleDocMouseLeave);
|
|
8245
10466
|
document.removeEventListener("dragover", handleDragOver, true);
|
|
8246
10467
|
document.removeEventListener("dragleave", handleDragLeave, true);
|
|
@@ -8256,6 +10477,7 @@ function OhhwellsBridge() {
|
|
|
8256
10477
|
window.removeEventListener("message", handleRemoveSchedulingSection);
|
|
8257
10478
|
window.removeEventListener("message", handleImageUrl);
|
|
8258
10479
|
window.removeEventListener("message", handleImageUploading);
|
|
10480
|
+
window.removeEventListener("message", handleCarouselChange);
|
|
8259
10481
|
window.removeEventListener("message", handleCanvasHeight);
|
|
8260
10482
|
window.removeEventListener("message", handleParentScroll);
|
|
8261
10483
|
window.removeEventListener("resize", handleViewportResize);
|
|
@@ -8263,13 +10485,165 @@ function OhhwellsBridge() {
|
|
|
8263
10485
|
window.removeEventListener("message", handleClickAt);
|
|
8264
10486
|
window.removeEventListener("message", handleHydrate);
|
|
8265
10487
|
window.removeEventListener("message", handleDeactivate);
|
|
10488
|
+
window.removeEventListener("message", handleUiEscape);
|
|
8266
10489
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
8267
10490
|
autoSaveTimers.current.clear();
|
|
8268
10491
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
8269
10492
|
if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
|
|
8270
10493
|
};
|
|
8271
10494
|
}, [isEditMode, refreshStateRules]);
|
|
8272
|
-
(0,
|
|
10495
|
+
(0, import_react9.useEffect)(() => {
|
|
10496
|
+
if (!isEditMode) return;
|
|
10497
|
+
const THRESHOLD = 10;
|
|
10498
|
+
const resolveWasSelected = (el) => {
|
|
10499
|
+
if (selectedElRef.current === el) return true;
|
|
10500
|
+
const activeAnchor = activeElRef.current ? getNavigationItemAnchor(activeElRef.current) : null;
|
|
10501
|
+
return activeAnchor === el;
|
|
10502
|
+
};
|
|
10503
|
+
const onPointerDown = (e) => {
|
|
10504
|
+
if (e.button !== 0) return;
|
|
10505
|
+
if (suppressNextClickRef.current && !footerDragRef.current && !footerPointerDragRef.current?.started) {
|
|
10506
|
+
suppressNextClickRef.current = false;
|
|
10507
|
+
}
|
|
10508
|
+
if (footerDragRef.current) return;
|
|
10509
|
+
const target = e.target;
|
|
10510
|
+
if (!target) return;
|
|
10511
|
+
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]')) {
|
|
10512
|
+
return;
|
|
10513
|
+
}
|
|
10514
|
+
if (target.closest("[data-ohw-item-drag-surface]")) return;
|
|
10515
|
+
const anchor = getNavigationItemAnchor(target);
|
|
10516
|
+
const hrefKey = anchor?.getAttribute("data-ohw-href-key") ?? null;
|
|
10517
|
+
if (anchor && isFooterHrefKey(hrefKey)) {
|
|
10518
|
+
armFooterPressDrag();
|
|
10519
|
+
footerPointerDragRef.current = {
|
|
10520
|
+
el: anchor,
|
|
10521
|
+
kind: "link",
|
|
10522
|
+
startX: e.clientX,
|
|
10523
|
+
startY: e.clientY,
|
|
10524
|
+
pointerId: e.pointerId,
|
|
10525
|
+
wasSelected: resolveWasSelected(anchor),
|
|
10526
|
+
started: false
|
|
10527
|
+
};
|
|
10528
|
+
return;
|
|
10529
|
+
}
|
|
10530
|
+
const col = target.closest("[data-ohw-footer-col]");
|
|
10531
|
+
if (col && !getNavigationItemAnchor(target)) {
|
|
10532
|
+
armFooterPressDrag();
|
|
10533
|
+
footerPointerDragRef.current = {
|
|
10534
|
+
el: col,
|
|
10535
|
+
kind: "column",
|
|
10536
|
+
startX: e.clientX,
|
|
10537
|
+
startY: e.clientY,
|
|
10538
|
+
pointerId: e.pointerId,
|
|
10539
|
+
wasSelected: resolveWasSelected(col),
|
|
10540
|
+
started: false
|
|
10541
|
+
};
|
|
10542
|
+
}
|
|
10543
|
+
};
|
|
10544
|
+
const onPointerMove = (e) => {
|
|
10545
|
+
const pending = footerPointerDragRef.current;
|
|
10546
|
+
if (!pending) return;
|
|
10547
|
+
if (pending.started) {
|
|
10548
|
+
e.preventDefault();
|
|
10549
|
+
clearTextSelection();
|
|
10550
|
+
const session = footerDragRef.current;
|
|
10551
|
+
if (!session) return;
|
|
10552
|
+
const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, session.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
|
|
10553
|
+
refreshFooterDragVisualsRef.current(session, slot, e.clientX, e.clientY);
|
|
10554
|
+
return;
|
|
10555
|
+
}
|
|
10556
|
+
const dx = e.clientX - pending.startX;
|
|
10557
|
+
const dy = e.clientY - pending.startY;
|
|
10558
|
+
if (dx * dx + dy * dy < THRESHOLD * THRESHOLD) return;
|
|
10559
|
+
e.preventDefault();
|
|
10560
|
+
pending.started = true;
|
|
10561
|
+
clearTextSelection();
|
|
10562
|
+
try {
|
|
10563
|
+
document.body.setPointerCapture(pending.pointerId);
|
|
10564
|
+
} catch {
|
|
10565
|
+
}
|
|
10566
|
+
if (linkPopoverOpenRef.current) {
|
|
10567
|
+
setLinkPopoverRef.current(null);
|
|
10568
|
+
}
|
|
10569
|
+
if (activeElRef.current) {
|
|
10570
|
+
deactivateRef.current();
|
|
10571
|
+
}
|
|
10572
|
+
if (pending.kind === "link") {
|
|
10573
|
+
const key = pending.el.getAttribute("data-ohw-href-key");
|
|
10574
|
+
if (!key) return;
|
|
10575
|
+
const column = findFooterColumnForLink(pending.el);
|
|
10576
|
+
const columns2 = listFooterColumns();
|
|
10577
|
+
beginFooterDragRef.current({
|
|
10578
|
+
kind: "link",
|
|
10579
|
+
hrefKey: key,
|
|
10580
|
+
columnEl: column,
|
|
10581
|
+
sourceColumnIndex: column ? columns2.indexOf(column) : 0,
|
|
10582
|
+
wasSelected: pending.wasSelected,
|
|
10583
|
+
draggedEl: pending.el,
|
|
10584
|
+
lastClientX: e.clientX,
|
|
10585
|
+
lastClientY: e.clientY,
|
|
10586
|
+
activeSlot: null
|
|
10587
|
+
});
|
|
10588
|
+
return;
|
|
10589
|
+
}
|
|
10590
|
+
const columns = listFooterColumns();
|
|
10591
|
+
const idx = columns.indexOf(pending.el);
|
|
10592
|
+
if (idx < 0) return;
|
|
10593
|
+
beginFooterDragRef.current({
|
|
10594
|
+
kind: "column",
|
|
10595
|
+
hrefKey: null,
|
|
10596
|
+
columnEl: pending.el,
|
|
10597
|
+
sourceColumnIndex: idx,
|
|
10598
|
+
wasSelected: pending.wasSelected,
|
|
10599
|
+
draggedEl: pending.el,
|
|
10600
|
+
lastClientX: e.clientX,
|
|
10601
|
+
lastClientY: e.clientY,
|
|
10602
|
+
activeSlot: null
|
|
10603
|
+
});
|
|
10604
|
+
};
|
|
10605
|
+
const endPointerDrag = (e) => {
|
|
10606
|
+
const pending = footerPointerDragRef.current;
|
|
10607
|
+
footerPointerDragRef.current = null;
|
|
10608
|
+
try {
|
|
10609
|
+
if (document.body.hasPointerCapture(e.pointerId)) {
|
|
10610
|
+
document.body.releasePointerCapture(e.pointerId);
|
|
10611
|
+
}
|
|
10612
|
+
} catch {
|
|
10613
|
+
}
|
|
10614
|
+
if (!pending?.started) {
|
|
10615
|
+
unlockFooterDragInteraction();
|
|
10616
|
+
return;
|
|
10617
|
+
}
|
|
10618
|
+
suppressNextClickRef.current = true;
|
|
10619
|
+
commitFooterDragRef.current(e.clientX, e.clientY);
|
|
10620
|
+
};
|
|
10621
|
+
const blockSelectStart = (e) => {
|
|
10622
|
+
if (footerDragRef.current || footerPointerDragRef.current?.started || document.documentElement.hasAttribute("data-ohw-footer-press-drag")) {
|
|
10623
|
+
e.preventDefault();
|
|
10624
|
+
}
|
|
10625
|
+
};
|
|
10626
|
+
const onDragEnd = (_e) => {
|
|
10627
|
+
if (!footerDragRef.current) return;
|
|
10628
|
+
commitFooterDragRef.current();
|
|
10629
|
+
};
|
|
10630
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
10631
|
+
document.addEventListener("pointermove", onPointerMove, true);
|
|
10632
|
+
document.addEventListener("pointerup", endPointerDrag, true);
|
|
10633
|
+
document.addEventListener("pointercancel", endPointerDrag, true);
|
|
10634
|
+
document.addEventListener("selectstart", blockSelectStart, true);
|
|
10635
|
+
document.addEventListener("dragend", onDragEnd, true);
|
|
10636
|
+
return () => {
|
|
10637
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
10638
|
+
document.removeEventListener("pointermove", onPointerMove, true);
|
|
10639
|
+
document.removeEventListener("pointerup", endPointerDrag, true);
|
|
10640
|
+
document.removeEventListener("pointercancel", endPointerDrag, true);
|
|
10641
|
+
document.removeEventListener("selectstart", blockSelectStart, true);
|
|
10642
|
+
document.removeEventListener("dragend", onDragEnd, true);
|
|
10643
|
+
unlockFooterDragInteraction();
|
|
10644
|
+
};
|
|
10645
|
+
}, [isEditMode]);
|
|
10646
|
+
(0, import_react9.useEffect)(() => {
|
|
8273
10647
|
const handler = (e) => {
|
|
8274
10648
|
if (e.data?.type !== "ow:request-schedule-config") return;
|
|
8275
10649
|
const insertAfterVal = e.data.insertAfter;
|
|
@@ -8285,7 +10659,7 @@ function OhhwellsBridge() {
|
|
|
8285
10659
|
window.addEventListener("message", handler);
|
|
8286
10660
|
return () => window.removeEventListener("message", handler);
|
|
8287
10661
|
}, [processConfigRequest]);
|
|
8288
|
-
(0,
|
|
10662
|
+
(0, import_react9.useEffect)(() => {
|
|
8289
10663
|
if (!isEditMode) return;
|
|
8290
10664
|
document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
|
|
8291
10665
|
el.removeAttribute("data-ohw-active-state");
|
|
@@ -8306,27 +10680,33 @@ function OhhwellsBridge() {
|
|
|
8306
10680
|
const next = { ...prev, [pathKey]: sections };
|
|
8307
10681
|
return shouldUseDevFixtures() ? { ...DEV_SECTIONS_BY_PATH, ...next } : next;
|
|
8308
10682
|
});
|
|
8309
|
-
|
|
8310
|
-
|
|
10683
|
+
postToParent2({
|
|
10684
|
+
type: "ow:ready",
|
|
10685
|
+
version: "1",
|
|
10686
|
+
path: pathname,
|
|
10687
|
+
nodes: collectEditableNodes(editContentRef.current),
|
|
10688
|
+
sections
|
|
10689
|
+
});
|
|
10690
|
+
postToParent2({ type: "ow:request-site-pages" });
|
|
8311
10691
|
}, 150);
|
|
8312
10692
|
return () => {
|
|
8313
10693
|
cancelAnimationFrame(raf);
|
|
8314
10694
|
clearTimeout(timer);
|
|
8315
10695
|
};
|
|
8316
|
-
}, [pathname, isEditMode, refreshStateRules,
|
|
8317
|
-
(0,
|
|
10696
|
+
}, [pathname, isEditMode, refreshStateRules, postToParent2]);
|
|
10697
|
+
(0, import_react9.useEffect)(() => {
|
|
8318
10698
|
scrollToHashSectionWhenReady();
|
|
8319
10699
|
const onHashChange = () => scrollToHashSectionWhenReady();
|
|
8320
10700
|
window.addEventListener("hashchange", onHashChange);
|
|
8321
10701
|
return () => window.removeEventListener("hashchange", onHashChange);
|
|
8322
10702
|
}, [pathname]);
|
|
8323
|
-
const handleCommand = (0,
|
|
10703
|
+
const handleCommand = (0, import_react9.useCallback)((cmd) => {
|
|
8324
10704
|
document.execCommand(cmd, false);
|
|
8325
10705
|
activeElRef.current?.focus();
|
|
8326
10706
|
if (activeElRef.current) setToolbarRect(getEditMeasureEl(activeElRef.current).getBoundingClientRect());
|
|
8327
10707
|
refreshActiveCommandsRef.current();
|
|
8328
10708
|
}, []);
|
|
8329
|
-
const handleStateChange = (0,
|
|
10709
|
+
const handleStateChange = (0, import_react9.useCallback)((state) => {
|
|
8330
10710
|
if (!activeStateElRef.current) return;
|
|
8331
10711
|
const el = activeStateElRef.current;
|
|
8332
10712
|
if (state === "Default") {
|
|
@@ -8339,18 +10719,22 @@ function OhhwellsBridge() {
|
|
|
8339
10719
|
}
|
|
8340
10720
|
setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
|
|
8341
10721
|
}, [deactivate]);
|
|
8342
|
-
const closeLinkPopover = (0,
|
|
8343
|
-
|
|
10722
|
+
const closeLinkPopover = (0, import_react9.useCallback)(() => {
|
|
10723
|
+
addNavAfterAnchorRef.current = null;
|
|
10724
|
+
setLinkPopover(null);
|
|
10725
|
+
}, []);
|
|
10726
|
+
const openLinkPopoverForActive = (0, import_react9.useCallback)(() => {
|
|
8344
10727
|
const hrefCtx = getHrefKeyFromElement(activeElRef.current);
|
|
8345
10728
|
if (!hrefCtx) return;
|
|
8346
10729
|
bumpLinkPopoverGrace();
|
|
8347
10730
|
setLinkPopover({
|
|
8348
10731
|
key: hrefCtx.key,
|
|
8349
|
-
|
|
10732
|
+
mode: "edit",
|
|
10733
|
+
target: getLinkHref2(hrefCtx.anchor)
|
|
8350
10734
|
});
|
|
8351
10735
|
deactivate();
|
|
8352
10736
|
}, [deactivate]);
|
|
8353
|
-
const openLinkPopoverForSelected = (0,
|
|
10737
|
+
const openLinkPopoverForSelected = (0, import_react9.useCallback)(() => {
|
|
8354
10738
|
const anchor = selectedElRef.current;
|
|
8355
10739
|
if (!anchor) return;
|
|
8356
10740
|
const key = anchor.getAttribute("data-ohw-href-key");
|
|
@@ -8358,30 +10742,80 @@ function OhhwellsBridge() {
|
|
|
8358
10742
|
bumpLinkPopoverGrace();
|
|
8359
10743
|
setLinkPopover({
|
|
8360
10744
|
key,
|
|
8361
|
-
|
|
10745
|
+
mode: "edit",
|
|
10746
|
+
target: getLinkHref2(anchor)
|
|
8362
10747
|
});
|
|
8363
10748
|
deselect();
|
|
8364
10749
|
}, [deselect]);
|
|
8365
|
-
const handleLinkPopoverSubmit = (0,
|
|
10750
|
+
const handleLinkPopoverSubmit = (0, import_react9.useCallback)(
|
|
8366
10751
|
(target) => {
|
|
8367
|
-
|
|
8368
|
-
|
|
10752
|
+
const session = linkPopoverSessionRef.current;
|
|
10753
|
+
if (!session) return;
|
|
10754
|
+
if (session.intent === "add-nav") {
|
|
10755
|
+
const trimmed = target.trim();
|
|
10756
|
+
let href = trimmed;
|
|
10757
|
+
let label = "Untitled";
|
|
10758
|
+
if (trimmed) {
|
|
10759
|
+
const { pageRoute, sectionId } = parseTarget(trimmed);
|
|
10760
|
+
const page = resolvePage(pageRoute, sitePages);
|
|
10761
|
+
const pageSections = getSectionsForPath(sectionsByPath, pageRoute);
|
|
10762
|
+
const section = sectionId ? pageSections.find((s) => s.id === sectionId) : void 0;
|
|
10763
|
+
label = section?.label ?? page.title;
|
|
10764
|
+
href = trimmed;
|
|
10765
|
+
}
|
|
10766
|
+
const afterAnchor = addNavAfterAnchorRef.current;
|
|
10767
|
+
const { anchor, hrefKey, labelKey, index, order } = insertNavbarItem(href, label, afterAnchor);
|
|
10768
|
+
applyLinkByKey(hrefKey, href);
|
|
10769
|
+
document.querySelectorAll(`[data-ohw-key="${labelKey}"]`).forEach((el) => {
|
|
10770
|
+
el.textContent = label;
|
|
10771
|
+
});
|
|
10772
|
+
const navCount = String(index + 1);
|
|
10773
|
+
const orderJson = JSON.stringify(order);
|
|
10774
|
+
editContentRef.current = {
|
|
10775
|
+
...editContentRef.current,
|
|
10776
|
+
[hrefKey]: href,
|
|
10777
|
+
[labelKey]: label,
|
|
10778
|
+
[NAV_COUNT_KEY]: navCount,
|
|
10779
|
+
[NAV_ORDER_KEY]: orderJson
|
|
10780
|
+
};
|
|
10781
|
+
postToParent2({
|
|
10782
|
+
type: "ow:change",
|
|
10783
|
+
nodes: [
|
|
10784
|
+
{ key: hrefKey, text: href },
|
|
10785
|
+
{ key: labelKey, text: label },
|
|
10786
|
+
{ key: NAV_COUNT_KEY, text: navCount },
|
|
10787
|
+
{ key: NAV_ORDER_KEY, text: orderJson }
|
|
10788
|
+
]
|
|
10789
|
+
});
|
|
10790
|
+
postToParent2({ type: "ow:toast", title: "Link added", toastType: "success" });
|
|
10791
|
+
addNavAfterAnchorRef.current = null;
|
|
10792
|
+
setLinkPopover(null);
|
|
10793
|
+
enforceLinkHrefs();
|
|
10794
|
+
requestAnimationFrame(() => {
|
|
10795
|
+
selectRef.current(anchor);
|
|
10796
|
+
});
|
|
10797
|
+
return;
|
|
10798
|
+
}
|
|
10799
|
+
const { key } = session;
|
|
8369
10800
|
applyLinkByKey(key, target);
|
|
8370
|
-
|
|
10801
|
+
postToParent2({ type: "ow:change", nodes: [{ key, text: target }] });
|
|
8371
10802
|
setLinkPopover(null);
|
|
8372
10803
|
},
|
|
8373
|
-
[
|
|
10804
|
+
[postToParent2, sitePages, sectionsByPath]
|
|
8374
10805
|
);
|
|
8375
|
-
const
|
|
8376
|
-
|
|
8377
|
-
|
|
8378
|
-
|
|
10806
|
+
const handleMediaReplace = (0, import_react9.useCallback)(
|
|
10807
|
+
(key) => {
|
|
10808
|
+
postToParent2({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
|
|
10809
|
+
},
|
|
10810
|
+
[postToParent2, mediaHover?.elementType]
|
|
10811
|
+
);
|
|
10812
|
+
const handleEditCarousel = (0, import_react9.useCallback)(
|
|
8379
10813
|
(key) => {
|
|
8380
|
-
|
|
10814
|
+
postToParent2({ type: "ow:carousel-open", key, images: readCarouselValue(key) });
|
|
8381
10815
|
},
|
|
8382
|
-
[
|
|
10816
|
+
[postToParent2]
|
|
8383
10817
|
);
|
|
8384
|
-
const handleMediaFadeOutComplete = (0,
|
|
10818
|
+
const handleMediaFadeOutComplete = (0, import_react9.useCallback)((key) => {
|
|
8385
10819
|
setUploadingRects((prev) => {
|
|
8386
10820
|
if (!(key in prev)) return prev;
|
|
8387
10821
|
const next = { ...prev };
|
|
@@ -8389,7 +10823,7 @@ function OhhwellsBridge() {
|
|
|
8389
10823
|
return next;
|
|
8390
10824
|
});
|
|
8391
10825
|
}, []);
|
|
8392
|
-
const handleVideoSettingsChange = (0,
|
|
10826
|
+
const handleVideoSettingsChange = (0, import_react9.useCallback)(
|
|
8393
10827
|
(key, settings) => {
|
|
8394
10828
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
8395
10829
|
const video = getVideoEl(el);
|
|
@@ -8397,7 +10831,7 @@ function OhhwellsBridge() {
|
|
|
8397
10831
|
if (typeof settings.autoplay === "boolean") video.autoplay = settings.autoplay;
|
|
8398
10832
|
if (typeof settings.muted === "boolean") video.muted = settings.muted;
|
|
8399
10833
|
syncVideoPlayback(video);
|
|
8400
|
-
|
|
10834
|
+
postToParent2({
|
|
8401
10835
|
type: "ow:change",
|
|
8402
10836
|
nodes: [
|
|
8403
10837
|
{ key: `${key}${VIDEO_AUTOPLAY_SUFFIX}`, text: String(video.autoplay) },
|
|
@@ -8409,12 +10843,15 @@ function OhhwellsBridge() {
|
|
|
8409
10843
|
);
|
|
8410
10844
|
});
|
|
8411
10845
|
},
|
|
8412
|
-
[
|
|
10846
|
+
[postToParent2]
|
|
8413
10847
|
);
|
|
8414
|
-
|
|
8415
|
-
|
|
8416
|
-
|
|
8417
|
-
|
|
10848
|
+
const showEditLink = toolbarShowEditLink;
|
|
10849
|
+
const currentSections = sectionsByPath[pathname] ?? [];
|
|
10850
|
+
linkPopoverOpenRef.current = linkPopover !== null;
|
|
10851
|
+
return bridgeRoot ? (0, import_react_dom3.createPortal)(
|
|
10852
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
10853
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
10854
|
+
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
8418
10855
|
MediaOverlay,
|
|
8419
10856
|
{
|
|
8420
10857
|
hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
|
|
@@ -8425,7 +10862,7 @@ function OhhwellsBridge() {
|
|
|
8425
10862
|
},
|
|
8426
10863
|
`uploading-${key}`
|
|
8427
10864
|
)),
|
|
8428
|
-
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0,
|
|
10865
|
+
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
8429
10866
|
MediaOverlay,
|
|
8430
10867
|
{
|
|
8431
10868
|
hover: mediaHover,
|
|
@@ -8434,53 +10871,33 @@ function OhhwellsBridge() {
|
|
|
8434
10871
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
8435
10872
|
}
|
|
8436
10873
|
),
|
|
8437
|
-
|
|
8438
|
-
|
|
8439
|
-
|
|
8440
|
-
|
|
10874
|
+
carouselHover && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
|
|
10875
|
+
siblingHintRect && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
10876
|
+
siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
|
|
10877
|
+
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
|
|
10878
|
+
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
10879
|
+
"div",
|
|
8441
10880
|
{
|
|
8442
|
-
|
|
8443
|
-
|
|
8444
|
-
|
|
8445
|
-
|
|
8446
|
-
|
|
8447
|
-
|
|
8448
|
-
|
|
8449
|
-
|
|
8450
|
-
|
|
8451
|
-
|
|
8452
|
-
|
|
8453
|
-
|
|
8454
|
-
|
|
8455
|
-
|
|
8456
|
-
|
|
8457
|
-
|
|
8458
|
-
}
|
|
8459
|
-
|
|
8460
|
-
toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
8461
|
-
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
8462
|
-
EditGlowChrome,
|
|
8463
|
-
{
|
|
8464
|
-
rect: toolbarRect,
|
|
8465
|
-
elRef: glowElRef,
|
|
8466
|
-
reorderHrefKey,
|
|
8467
|
-
dragDisabled: reorderDragDisabled
|
|
8468
|
-
}
|
|
8469
|
-
),
|
|
8470
|
-
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
8471
|
-
FloatingToolbar,
|
|
8472
|
-
{
|
|
8473
|
-
rect: toolbarRect,
|
|
8474
|
-
parentScroll: parentScrollRef.current,
|
|
8475
|
-
elRef: toolbarElRef,
|
|
8476
|
-
onCommand: handleCommand,
|
|
8477
|
-
activeCommands,
|
|
8478
|
-
showEditLink,
|
|
8479
|
-
onEditLink: openLinkPopoverForActive
|
|
8480
|
-
}
|
|
8481
|
-
)
|
|
10881
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
10882
|
+
style: {
|
|
10883
|
+
left: slot.left,
|
|
10884
|
+
top: slot.top,
|
|
10885
|
+
width: slot.width,
|
|
10886
|
+
height: slot.height
|
|
10887
|
+
},
|
|
10888
|
+
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" })
|
|
10889
|
+
},
|
|
10890
|
+
`footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
|
|
10891
|
+
)),
|
|
10892
|
+
hoveredNavContainerRect && toolbarVariant !== "select-frame" && !linkPopover && !isItemDragging && !siblingHintRect && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
|
|
10893
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
|
|
10894
|
+
hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !siblingHintRect && siblingHintRects.length === 0 && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
10895
|
+
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 }),
|
|
10896
|
+
toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
10897
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(EditGlowChrome, { rect: toolbarRect, elRef: glowElRef, reorderHrefKey, dragDisabled: reorderDragDisabled }),
|
|
10898
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(FloatingToolbar, { rect: toolbarRect, parentScroll: parentScrollRef.current, elRef: toolbarElRef, onCommand: handleCommand, activeCommands, showEditLink, onEditLink: openLinkPopoverForActive })
|
|
8482
10899
|
] }),
|
|
8483
|
-
maxBadge && /* @__PURE__ */ (0,
|
|
10900
|
+
maxBadge && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
8484
10901
|
"div",
|
|
8485
10902
|
{
|
|
8486
10903
|
"data-ohw-max-badge": "",
|
|
@@ -8506,56 +10923,29 @@ function OhhwellsBridge() {
|
|
|
8506
10923
|
]
|
|
8507
10924
|
}
|
|
8508
10925
|
),
|
|
8509
|
-
toggleState && /* @__PURE__ */ (0,
|
|
8510
|
-
|
|
8511
|
-
{
|
|
8512
|
-
|
|
8513
|
-
|
|
8514
|
-
|
|
8515
|
-
|
|
8516
|
-
|
|
8517
|
-
|
|
8518
|
-
|
|
8519
|
-
|
|
8520
|
-
|
|
8521
|
-
|
|
8522
|
-
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
8523
|
-
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
8524
|
-
children: [
|
|
8525
|
-
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
8526
|
-
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
8527
|
-
Badge,
|
|
8528
|
-
{
|
|
8529
|
-
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",
|
|
8530
|
-
onClick: () => {
|
|
8531
|
-
window.parent.postMessage(
|
|
8532
|
-
{ type: "ow:add-section", insertAfter: sectionGap.insertAfter, insertBefore: sectionGap.insertBefore },
|
|
8533
|
-
"*"
|
|
8534
|
-
);
|
|
10926
|
+
toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(StateToggle, { rect: toggleState.rect, activeState: toggleState.activeState, states: toggleState.states, onStateChange: handleStateChange }),
|
|
10927
|
+
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: [
|
|
10928
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
10929
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
10930
|
+
Badge,
|
|
10931
|
+
{
|
|
10932
|
+
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",
|
|
10933
|
+
onClick: () => {
|
|
10934
|
+
window.parent.postMessage(
|
|
10935
|
+
{
|
|
10936
|
+
type: "ow:add-section",
|
|
10937
|
+
insertAfter: sectionGap.insertAfter,
|
|
10938
|
+
insertBefore: sectionGap.insertBefore
|
|
8535
10939
|
},
|
|
8536
|
-
|
|
8537
|
-
|
|
8538
|
-
|
|
8539
|
-
|
|
8540
|
-
|
|
8541
|
-
|
|
8542
|
-
|
|
8543
|
-
|
|
8544
|
-
|
|
8545
|
-
{
|
|
8546
|
-
panelRef: linkPopoverPanelRef,
|
|
8547
|
-
portalContainer: dialogPortalContainer,
|
|
8548
|
-
open: true,
|
|
8549
|
-
mode: "edit",
|
|
8550
|
-
pages: sitePages,
|
|
8551
|
-
sections: currentSections,
|
|
8552
|
-
sectionsByPath,
|
|
8553
|
-
initialTarget: linkPopover.target,
|
|
8554
|
-
onClose: closeLinkPopover,
|
|
8555
|
-
onSubmit: handleLinkPopoverSubmit
|
|
8556
|
-
},
|
|
8557
|
-
`${linkPopover.key}-${pathname}`
|
|
8558
|
-
) : null
|
|
10940
|
+
"*"
|
|
10941
|
+
);
|
|
10942
|
+
},
|
|
10943
|
+
children: "Add Section"
|
|
10944
|
+
}
|
|
10945
|
+
),
|
|
10946
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
|
|
10947
|
+
] }),
|
|
10948
|
+
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
|
|
8559
10949
|
] }),
|
|
8560
10950
|
bridgeRoot
|
|
8561
10951
|
) : null;
|
|
@@ -8566,6 +10956,7 @@ function OhhwellsBridge() {
|
|
|
8566
10956
|
CustomToolbarButton,
|
|
8567
10957
|
CustomToolbarDivider,
|
|
8568
10958
|
DragHandle,
|
|
10959
|
+
DropIndicator,
|
|
8569
10960
|
ItemActionToolbar,
|
|
8570
10961
|
ItemInteractionLayer,
|
|
8571
10962
|
LinkEditorPanel,
|
|
@@ -8580,12 +10971,14 @@ function OhhwellsBridge() {
|
|
|
8580
10971
|
TooltipProvider,
|
|
8581
10972
|
TooltipTrigger,
|
|
8582
10973
|
buildTarget,
|
|
10974
|
+
dropIndicatorVariants,
|
|
8583
10975
|
filterAvailablePages,
|
|
8584
10976
|
getEditModeInitialState,
|
|
8585
10977
|
isEditSessionActive,
|
|
8586
10978
|
isValidUrl,
|
|
8587
10979
|
parseTarget,
|
|
8588
10980
|
toggleVariants,
|
|
10981
|
+
useOhwCarousel,
|
|
8589
10982
|
validateUrlInput
|
|
8590
10983
|
});
|
|
8591
10984
|
//# sourceMappingURL=index.cjs.map
|