@ohhwells/bridge 0.1.38-next.69 → 0.1.39
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 +1 -13
- package/dist/index.cjs +700 -3004
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -98
- package/dist/index.d.ts +6 -98
- package/dist/index.js +709 -3010
- package/dist/index.js.map +1 -1
- package/dist/styles.css +34 -169
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -35,7 +35,6 @@ __export(index_exports, {
|
|
|
35
35
|
CustomToolbarButton: () => CustomToolbarButton,
|
|
36
36
|
CustomToolbarDivider: () => CustomToolbarDivider,
|
|
37
37
|
DragHandle: () => DragHandle,
|
|
38
|
-
DropIndicator: () => DropIndicator,
|
|
39
38
|
ItemActionToolbar: () => ItemActionToolbar,
|
|
40
39
|
ItemInteractionLayer: () => ItemInteractionLayer,
|
|
41
40
|
LinkEditorPanel: () => LinkEditorPanel,
|
|
@@ -50,31 +49,26 @@ __export(index_exports, {
|
|
|
50
49
|
TooltipProvider: () => TooltipProvider,
|
|
51
50
|
TooltipTrigger: () => TooltipTrigger,
|
|
52
51
|
buildTarget: () => buildTarget,
|
|
53
|
-
dropIndicatorVariants: () => dropIndicatorVariants,
|
|
54
52
|
filterAvailablePages: () => filterAvailablePages,
|
|
55
53
|
getEditModeInitialState: () => getEditModeInitialState,
|
|
56
54
|
isEditSessionActive: () => isEditSessionActive,
|
|
57
55
|
isValidUrl: () => isValidUrl,
|
|
58
56
|
parseTarget: () => parseTarget,
|
|
59
57
|
toggleVariants: () => toggleVariants,
|
|
60
|
-
useOhwCarousel: () => useOhwCarousel,
|
|
61
58
|
validateUrlInput: () => validateUrlInput
|
|
62
59
|
});
|
|
63
60
|
module.exports = __toCommonJS(index_exports);
|
|
64
61
|
|
|
65
62
|
// src/OhhwellsBridge.tsx
|
|
66
|
-
var
|
|
63
|
+
var import_react6 = __toESM(require("react"), 1);
|
|
67
64
|
var import_client = require("react-dom/client");
|
|
68
|
-
var
|
|
65
|
+
var import_react_dom = require("react-dom");
|
|
69
66
|
|
|
70
67
|
// src/linkHrefStore.ts
|
|
71
68
|
var linkHrefStore = /* @__PURE__ */ new Map();
|
|
72
69
|
function setStoredLinkHref(key, href) {
|
|
73
70
|
linkHrefStore.set(key, href);
|
|
74
71
|
}
|
|
75
|
-
function getStoredLinkHref(key) {
|
|
76
|
-
return linkHrefStore.get(key);
|
|
77
|
-
}
|
|
78
72
|
function enforceLinkHrefs() {
|
|
79
73
|
document.querySelectorAll("[data-ohw-href-key]").forEach((el) => {
|
|
80
74
|
const key = el.getAttribute("data-ohw-href-key") ?? "";
|
|
@@ -116,7 +110,6 @@ var import_react3 = require("react");
|
|
|
116
110
|
var import_react2 = require("react");
|
|
117
111
|
var import_radix_ui = require("radix-ui");
|
|
118
112
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
119
|
-
var isValidEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
120
113
|
function Spinner() {
|
|
121
114
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
122
115
|
"svg",
|
|
@@ -150,17 +143,12 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
|
|
|
150
143
|
const [error, setError] = (0, import_react2.useState)(null);
|
|
151
144
|
const isBook = title === "Confirm your spot";
|
|
152
145
|
const handleSubmit = async () => {
|
|
153
|
-
|
|
154
|
-
if (!trimmed) return;
|
|
155
|
-
if (!isValidEmail(trimmed)) {
|
|
156
|
-
setError("Please enter a valid email address.");
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
146
|
+
if (!email.trim()) return;
|
|
159
147
|
setLoading(true);
|
|
160
148
|
setError(null);
|
|
161
149
|
try {
|
|
162
|
-
await onSubmit(
|
|
163
|
-
setSubmittedEmail(
|
|
150
|
+
await onSubmit(email.trim());
|
|
151
|
+
setSubmittedEmail(email.trim());
|
|
164
152
|
setSuccess(true);
|
|
165
153
|
} catch (e) {
|
|
166
154
|
setError(e instanceof Error ? e.message : "Something went wrong. Please try again.");
|
|
@@ -235,10 +223,7 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
|
|
|
235
223
|
{
|
|
236
224
|
type: "email",
|
|
237
225
|
value: email,
|
|
238
|
-
onChange: (e) =>
|
|
239
|
-
setEmail(e.target.value);
|
|
240
|
-
if (error) setError(null);
|
|
241
|
-
},
|
|
226
|
+
onChange: (e) => setEmail(e.target.value),
|
|
242
227
|
onKeyDown: handleKeyDown,
|
|
243
228
|
placeholder: "hello@gmail.com",
|
|
244
229
|
autoFocus: true,
|
|
@@ -295,20 +280,12 @@ function formatClassTime(cls) {
|
|
|
295
280
|
const em = endTotal % 60;
|
|
296
281
|
return `${h}:${cls.startTime.minutes}-${eh}:${String(em).padStart(2, "0")}`;
|
|
297
282
|
}
|
|
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
|
-
}
|
|
303
283
|
function getBookingsOnDate(cls, date) {
|
|
304
284
|
if (!cls.bookings?.length) return 0;
|
|
305
|
-
const
|
|
306
|
-
target.setHours(0, 0, 0, 0);
|
|
285
|
+
const ds = date.toISOString().split("T")[0];
|
|
307
286
|
return cls.bookings.filter((b) => {
|
|
308
287
|
try {
|
|
309
|
-
|
|
310
|
-
bookingDate.setHours(0, 0, 0, 0);
|
|
311
|
-
return bookingDate.getTime() === target.getTime();
|
|
288
|
+
return new Date(b.classDate).toISOString().split("T")[0] === ds;
|
|
312
289
|
} catch {
|
|
313
290
|
return false;
|
|
314
291
|
}
|
|
@@ -573,7 +550,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
|
|
|
573
550
|
}
|
|
574
551
|
)
|
|
575
552
|
] }),
|
|
576
|
-
|
|
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: [
|
|
577
554
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
|
|
578
555
|
available,
|
|
579
556
|
"/",
|
|
@@ -585,10 +562,9 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
|
|
|
585
562
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-1 flex-col gap-2 min-w-0 sm:contents", children: [
|
|
586
563
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex-1 flex flex-col gap-2 min-w-0", children: [
|
|
587
564
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-base font-bold text-(--color-dark,#200C02) block truncate", children: cls.name }),
|
|
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 })
|
|
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 })
|
|
590
566
|
] }),
|
|
591
|
-
|
|
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: [
|
|
592
568
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
|
|
593
569
|
available,
|
|
594
570
|
"/",
|
|
@@ -613,7 +589,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
|
|
|
613
589
|
if (!cls.id) return;
|
|
614
590
|
onOpenModal?.(isFull ? "waitlist" : "book", cls.id, selectedDate);
|
|
615
591
|
},
|
|
616
|
-
children: isFull ? "Join Waitlist" :
|
|
592
|
+
children: isFull ? "Join Waitlist" : "Book Now"
|
|
617
593
|
}
|
|
618
594
|
)
|
|
619
595
|
] })
|
|
@@ -655,17 +631,6 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
655
631
|
const [isHovered, setIsHovered] = (0, import_react3.useState)(false);
|
|
656
632
|
const [modalState, setModalState] = (0, import_react3.useState)(null);
|
|
657
633
|
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
|
-
}, []);
|
|
669
634
|
const dates = (0, import_react3.useMemo)(() => {
|
|
670
635
|
const today = /* @__PURE__ */ new Date();
|
|
671
636
|
today.setHours(0, 0, 0, 0);
|
|
@@ -685,18 +650,6 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
685
650
|
}
|
|
686
651
|
}
|
|
687
652
|
}, [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]);
|
|
700
653
|
(0, import_react3.useEffect)(() => {
|
|
701
654
|
if (typeof window === "undefined") return;
|
|
702
655
|
const isInEditor = window.self !== window.top;
|
|
@@ -758,7 +711,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
758
711
|
setLoading(false);
|
|
759
712
|
return;
|
|
760
713
|
}
|
|
761
|
-
|
|
714
|
+
;
|
|
762
715
|
(async () => {
|
|
763
716
|
try {
|
|
764
717
|
const res = await fetch(`${API_URL}/api/schedule/id/${effectiveId}`);
|
|
@@ -815,14 +768,18 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
815
768
|
const data = await res.json().catch(() => ({}));
|
|
816
769
|
throw new Error(data?.message ?? "Something went wrong. Please try again.");
|
|
817
770
|
}
|
|
818
|
-
await refetchLiveSchedule();
|
|
819
771
|
};
|
|
820
772
|
const handleReplaceSchedule = () => {
|
|
821
773
|
setIsHovered(false);
|
|
822
|
-
|
|
823
|
-
{
|
|
824
|
-
|
|
825
|
-
|
|
774
|
+
if (schedule) {
|
|
775
|
+
window.parent.postMessage({
|
|
776
|
+
type: "ow:schedule-connected",
|
|
777
|
+
schedule: { id: schedule.id, name: schedule.name },
|
|
778
|
+
insertAfter
|
|
779
|
+
}, "*");
|
|
780
|
+
} else {
|
|
781
|
+
window.parent.postMessage({ type: "ow:scheduling-not-connected", insertAfter }, "*");
|
|
782
|
+
}
|
|
826
783
|
};
|
|
827
784
|
if (!inEditor && !loading && !schedule) return null;
|
|
828
785
|
const sectionId = `scheduling-${insertAfter}`;
|
|
@@ -865,19 +822,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
865
822
|
),
|
|
866
823
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "max-w-[1280px] mx-auto flex flex-col items-center gap-16", children: [
|
|
867
824
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-col items-center gap-4", children: [
|
|
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
|
-
),
|
|
825
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { className: "font-display text-4xl sm:text-5xl font-bold text-center m-0 text-(--color-dark,#200C02)", children: schedule?.name ?? "Book an appointment" }),
|
|
881
826
|
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 })
|
|
882
827
|
] }),
|
|
883
828
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "w-full flex flex-col items-end gap-3", children: [
|
|
@@ -4463,7 +4408,6 @@ function ItemActionToolbar({
|
|
|
4463
4408
|
onEditLink,
|
|
4464
4409
|
onAddItem,
|
|
4465
4410
|
onMore,
|
|
4466
|
-
editLinkDisabled = false,
|
|
4467
4411
|
addItemDisabled = true,
|
|
4468
4412
|
moreDisabled = true,
|
|
4469
4413
|
tooltipSide = "bottom"
|
|
@@ -4472,12 +4416,10 @@ function ItemActionToolbar({
|
|
|
4472
4416
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
4473
4417
|
ToolbarActionTooltip,
|
|
4474
4418
|
{
|
|
4475
|
-
label: "
|
|
4419
|
+
label: "Add link",
|
|
4476
4420
|
side: tooltipSide,
|
|
4477
|
-
disabled: editLinkDisabled,
|
|
4478
4421
|
buttonProps: {
|
|
4479
4422
|
onMouseDown: (e) => {
|
|
4480
|
-
if (editLinkDisabled) return;
|
|
4481
4423
|
e.preventDefault();
|
|
4482
4424
|
e.stopPropagation();
|
|
4483
4425
|
onEditLink?.();
|
|
@@ -4555,7 +4497,7 @@ function getChromeStyle(state) {
|
|
|
4555
4497
|
case "dragging":
|
|
4556
4498
|
return {
|
|
4557
4499
|
border: `2px solid ${PRIMARY}`,
|
|
4558
|
-
boxShadow:
|
|
4500
|
+
boxShadow: DRAG_SHADOW
|
|
4559
4501
|
};
|
|
4560
4502
|
default:
|
|
4561
4503
|
return {};
|
|
@@ -4571,8 +4513,6 @@ function ItemInteractionLayer({
|
|
|
4571
4513
|
dragHandleLabel = "Reorder item",
|
|
4572
4514
|
onDragHandleDragStart,
|
|
4573
4515
|
onDragHandleDragEnd,
|
|
4574
|
-
onItemPointerDown,
|
|
4575
|
-
onItemClick,
|
|
4576
4516
|
chromeGap = 6,
|
|
4577
4517
|
className
|
|
4578
4518
|
}) {
|
|
@@ -4580,8 +4520,7 @@ function ItemInteractionLayer({
|
|
|
4580
4520
|
const isActive = state === "active-top" || state === "active-bottom";
|
|
4581
4521
|
const isDragging = state === "dragging";
|
|
4582
4522
|
const showToolbar = isActive && toolbar;
|
|
4583
|
-
const showDragHandle =
|
|
4584
|
-
const itemDragEnabled = isActive && showHandle && !isDragging && !dragDisabled;
|
|
4523
|
+
const showDragHandle = isActive && showHandle && !isDragging;
|
|
4585
4524
|
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
4586
4525
|
"div",
|
|
4587
4526
|
{
|
|
@@ -4606,28 +4545,11 @@ function ItemInteractionLayer({
|
|
|
4606
4545
|
style: getChromeStyle(state)
|
|
4607
4546
|
}
|
|
4608
4547
|
),
|
|
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
|
-
),
|
|
4625
4548
|
showDragHandle && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4626
4549
|
"div",
|
|
4627
4550
|
{
|
|
4628
4551
|
"data-ohw-drag-handle-container": "",
|
|
4629
|
-
className: "pointer-events-auto absolute left-0 top-1/2
|
|
4630
|
-
style: isDragging ? { visibility: "hidden" } : void 0,
|
|
4552
|
+
className: "pointer-events-auto absolute left-0 top-1/2 -translate-x-[calc(100%+7px)] -translate-y-1/2",
|
|
4631
4553
|
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4632
4554
|
DragHandle,
|
|
4633
4555
|
{
|
|
@@ -4850,12 +4772,15 @@ function MediaOverlay({
|
|
|
4850
4772
|
className: "flex items-center justify-center cursor-pointer",
|
|
4851
4773
|
style: {
|
|
4852
4774
|
...box,
|
|
4853
|
-
//
|
|
4854
|
-
//
|
|
4855
|
-
|
|
4775
|
+
// When text overlays this media, let clicks fall THROUGH to the text underneath. In the
|
|
4776
|
+
// parent this needed a whole `ow:click-at` round-trip to re-hit-test inside the iframe;
|
|
4777
|
+
// in-document, pointer-events does it natively. The button below opts back in, so
|
|
4778
|
+
// Replace still works.
|
|
4779
|
+
pointerEvents: hover.hasTextOverlap ? "none" : "auto",
|
|
4856
4780
|
boxShadow: "inset 0 0 0 1.5px var(--color-primary)",
|
|
4857
4781
|
background: "color-mix(in srgb, var(--color-primary) 20%, transparent)"
|
|
4858
4782
|
},
|
|
4783
|
+
onClick: () => onReplace(hover.key),
|
|
4859
4784
|
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
4860
4785
|
Button,
|
|
4861
4786
|
{
|
|
@@ -4880,64 +4805,9 @@ function MediaOverlay({
|
|
|
4880
4805
|
] });
|
|
4881
4806
|
}
|
|
4882
4807
|
|
|
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
|
-
|
|
4938
4808
|
// src/OhhwellsBridge.tsx
|
|
4939
|
-
var
|
|
4940
|
-
var
|
|
4809
|
+
var import_react_dom2 = require("react-dom");
|
|
4810
|
+
var import_navigation = require("next/navigation");
|
|
4941
4811
|
|
|
4942
4812
|
// src/lib/session-search.ts
|
|
4943
4813
|
var STORAGE_KEY = "ohw-preserved-search";
|
|
@@ -4967,7 +4837,6 @@ function parseSectionsFromRoot(root) {
|
|
|
4967
4837
|
for (const el of root.querySelectorAll("[data-ohw-section]")) {
|
|
4968
4838
|
const id = el.getAttribute("data-ohw-section") ?? "";
|
|
4969
4839
|
if (!id || seen.has(id)) continue;
|
|
4970
|
-
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
4971
4840
|
seen.add(id);
|
|
4972
4841
|
const label = el.getAttribute("data-ohw-section-label") ?? titleCaseSectionId(id);
|
|
4973
4842
|
sections.push({ id, label });
|
|
@@ -5214,22 +5083,54 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
|
|
|
5214
5083
|
tick();
|
|
5215
5084
|
}
|
|
5216
5085
|
|
|
5217
|
-
// src/ui/link-modal/LinkPopover.tsx
|
|
5218
|
-
var import_react7 = require("react");
|
|
5219
|
-
|
|
5220
5086
|
// src/ui/dialog.tsx
|
|
5221
5087
|
var React7 = __toESM(require("react"), 1);
|
|
5222
5088
|
var import_radix_ui5 = require("radix-ui");
|
|
5223
|
-
|
|
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
|
|
5224
5129
|
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
5225
|
-
function Dialog2({
|
|
5226
|
-
...props
|
|
5227
|
-
}) {
|
|
5130
|
+
function Dialog2({ ...props }) {
|
|
5228
5131
|
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_radix_ui5.Dialog.Root, { "data-slot": "dialog", ...props });
|
|
5229
5132
|
}
|
|
5230
|
-
function DialogPortal({
|
|
5231
|
-
...props
|
|
5232
|
-
}) {
|
|
5133
|
+
function DialogPortal({ ...props }) {
|
|
5233
5134
|
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_radix_ui5.Dialog.Portal, { ...props });
|
|
5234
5135
|
}
|
|
5235
5136
|
function DialogOverlay({
|
|
@@ -5246,69 +5147,52 @@ function DialogOverlay({
|
|
|
5246
5147
|
}
|
|
5247
5148
|
);
|
|
5248
5149
|
}
|
|
5249
|
-
var DialogContent = React7.forwardRef(
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
5260
|
-
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
children
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
}
|
|
5284
|
-
);
|
|
5150
|
+
var DialogContent = React7.forwardRef(({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
5151
|
+
const positionMode = container ? "absolute" : "fixed";
|
|
5152
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(DialogPortal, { container: container ?? void 0, children: [
|
|
5153
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
5154
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
5155
|
+
import_radix_ui5.Dialog.Content,
|
|
5156
|
+
{
|
|
5157
|
+
ref,
|
|
5158
|
+
"data-slot": "dialog-content",
|
|
5159
|
+
className: cn(
|
|
5160
|
+
positionMode,
|
|
5161
|
+
"left-1/2 top-1/2 z-[2147483647] flex w-full max-w-[483px] -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden",
|
|
5162
|
+
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
5163
|
+
container ? "max-h-[calc(100%-32px)] max-w-[calc(100%-16px)]" : "max-h-[calc(100vh-32px)] max-w-[calc(100vw-16px)]",
|
|
5164
|
+
className
|
|
5165
|
+
),
|
|
5166
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
5167
|
+
...props,
|
|
5168
|
+
children: [
|
|
5169
|
+
children,
|
|
5170
|
+
showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
5171
|
+
import_radix_ui5.Dialog.Close,
|
|
5172
|
+
{
|
|
5173
|
+
type: "button",
|
|
5174
|
+
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
5175
|
+
"aria-label": "Close",
|
|
5176
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconX, { "aria-hidden": true })
|
|
5177
|
+
}
|
|
5178
|
+
) : null
|
|
5179
|
+
]
|
|
5180
|
+
}
|
|
5181
|
+
)
|
|
5182
|
+
] });
|
|
5183
|
+
});
|
|
5285
5184
|
DialogContent.displayName = import_radix_ui5.Dialog.Content.displayName;
|
|
5286
|
-
function DialogHeader({
|
|
5287
|
-
className,
|
|
5288
|
-
...props
|
|
5289
|
-
}) {
|
|
5185
|
+
function DialogHeader({ className, ...props }) {
|
|
5290
5186
|
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
5291
5187
|
}
|
|
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
|
-
);
|
|
5188
|
+
function DialogFooter({ className, ...props }) {
|
|
5189
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: cn("flex items-center justify-end gap-2", className), ...props });
|
|
5303
5190
|
}
|
|
5304
5191
|
var DialogTitle = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
5305
5192
|
import_radix_ui5.Dialog.Title,
|
|
5306
5193
|
{
|
|
5307
5194
|
ref,
|
|
5308
|
-
className: cn(
|
|
5309
|
-
"text-lg font-semibold leading-none tracking-tight text-card-foreground",
|
|
5310
|
-
className
|
|
5311
|
-
),
|
|
5195
|
+
className: cn("text-lg font-semibold leading-none tracking-tight text-card-foreground", className),
|
|
5312
5196
|
...props
|
|
5313
5197
|
}
|
|
5314
5198
|
));
|
|
@@ -5324,40 +5208,19 @@ var DialogDescription = React7.forwardRef(({ className, ...props }, ref) => /* @
|
|
|
5324
5208
|
DialogDescription.displayName = import_radix_ui5.Dialog.Description.displayName;
|
|
5325
5209
|
var DialogClose = import_radix_ui5.Dialog.Close;
|
|
5326
5210
|
|
|
5327
|
-
// src/ui/link-modal/LinkEditorPanel.tsx
|
|
5328
|
-
var import_lucide_react9 = require("lucide-react");
|
|
5329
|
-
|
|
5330
5211
|
// src/ui/link-modal/DestinationBreadcrumb.tsx
|
|
5331
|
-
var import_lucide_react6 = require("lucide-react");
|
|
5332
5212
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
5333
|
-
function DestinationBreadcrumb({
|
|
5334
|
-
pageTitle,
|
|
5335
|
-
sectionLabel
|
|
5336
|
-
}) {
|
|
5213
|
+
function DestinationBreadcrumb({ pageTitle, sectionLabel }) {
|
|
5337
5214
|
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex w-full flex-col gap-2", children: [
|
|
5338
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-sm font-medium
|
|
5215
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-sm font-medium text-foreground", children: "Destination" }),
|
|
5339
5216
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-3", children: [
|
|
5340
5217
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
5341
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
5342
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "text-sm font-medium leading-none text-foreground
|
|
5218
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(IconFile, { className: "shrink-0 text-foreground", "aria-hidden": true }),
|
|
5219
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "text-sm font-medium leading-none text-foreground", children: pageTitle })
|
|
5343
5220
|
] }),
|
|
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
|
-
),
|
|
5221
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(IconArrowRight, { className: "shrink-0 text-muted-foreground", "aria-hidden": true }),
|
|
5352
5222
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
|
|
5353
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
5354
|
-
import_lucide_react6.GalleryVertical,
|
|
5355
|
-
{
|
|
5356
|
-
size: 16,
|
|
5357
|
-
className: "shrink-0 text-foreground",
|
|
5358
|
-
"aria-hidden": true
|
|
5359
|
-
}
|
|
5360
|
-
),
|
|
5223
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(IconSection, { className: "shrink-0 text-foreground", "aria-hidden": true }),
|
|
5361
5224
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
|
|
5362
5225
|
] })
|
|
5363
5226
|
] })
|
|
@@ -5365,13 +5228,8 @@ function DestinationBreadcrumb({
|
|
|
5365
5228
|
}
|
|
5366
5229
|
|
|
5367
5230
|
// src/ui/link-modal/SectionTreeItem.tsx
|
|
5368
|
-
var import_lucide_react7 = require("lucide-react");
|
|
5369
5231
|
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
5370
|
-
function SectionTreeItem({
|
|
5371
|
-
section,
|
|
5372
|
-
onSelect,
|
|
5373
|
-
selected
|
|
5374
|
-
}) {
|
|
5232
|
+
function SectionTreeItem({ section, onSelect, selected }) {
|
|
5375
5233
|
const interactive = Boolean(onSelect);
|
|
5376
5234
|
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex h-9 w-full items-end pl-3", children: [
|
|
5377
5235
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
@@ -5399,20 +5257,22 @@ function SectionTreeItem({
|
|
|
5399
5257
|
interactive && selected && "border-primary"
|
|
5400
5258
|
),
|
|
5401
5259
|
children: [
|
|
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
|
-
),
|
|
5260
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(IconSection, { className: "shrink-0 text-foreground", "aria-hidden": true }),
|
|
5410
5261
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
|
|
5411
5262
|
]
|
|
5412
5263
|
}
|
|
5413
5264
|
)
|
|
5414
5265
|
] });
|
|
5415
5266
|
}
|
|
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
|
+
}
|
|
5416
5276
|
|
|
5417
5277
|
// src/ui/link-modal/UrlOrPageInput.tsx
|
|
5418
5278
|
var import_react4 = require("react");
|
|
@@ -5454,11 +5314,8 @@ function Label({ className, ...props }) {
|
|
|
5454
5314
|
}
|
|
5455
5315
|
|
|
5456
5316
|
// src/ui/link-modal/UrlOrPageInput.tsx
|
|
5457
|
-
var import_lucide_react8 = require("lucide-react");
|
|
5458
5317
|
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
5459
|
-
function FieldChevron({
|
|
5460
|
-
onClick
|
|
5461
|
-
}) {
|
|
5318
|
+
function FieldChevron({ onClick }) {
|
|
5462
5319
|
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5463
5320
|
"button",
|
|
5464
5321
|
{
|
|
@@ -5467,7 +5324,7 @@ function FieldChevron({
|
|
|
5467
5324
|
onClick,
|
|
5468
5325
|
"aria-label": "Open page list",
|
|
5469
5326
|
tabIndex: -1,
|
|
5470
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5327
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(IconChevronDown, {})
|
|
5471
5328
|
}
|
|
5472
5329
|
);
|
|
5473
5330
|
}
|
|
@@ -5485,29 +5342,7 @@ function UrlOrPageInput({
|
|
|
5485
5342
|
}) {
|
|
5486
5343
|
const inputId = (0, import_react4.useId)();
|
|
5487
5344
|
const inputRef = (0, import_react4.useRef)(null);
|
|
5488
|
-
const rootRef = (0, import_react4.useRef)(null);
|
|
5489
5345
|
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]);
|
|
5511
5346
|
const openDropdown = () => {
|
|
5512
5347
|
if (readOnly || filteredPages.length === 0) return;
|
|
5513
5348
|
onDropdownOpenChange(true);
|
|
@@ -5525,21 +5360,14 @@ function UrlOrPageInput({
|
|
|
5525
5360
|
requestAnimationFrame(() => inputRef.current?.focus());
|
|
5526
5361
|
};
|
|
5527
5362
|
const fieldClassName = cn(
|
|
5528
|
-
"data-ohw-link-field flex h-
|
|
5363
|
+
"data-ohw-link-field flex h-10 w-full items-center overflow-hidden rounded-md border bg-background pl-3 pr-3 py-2 outline-none transition-[border-color,box-shadow]",
|
|
5529
5364
|
urlError ? "border-destructive shadow-[0_0_0_1px_var(--ohw-destructive)]" : isFocused ? "border-primary shadow-[0_0_0_1px_var(--ohw-primary)]" : "border-input"
|
|
5530
5365
|
);
|
|
5531
5366
|
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex w-full flex-col gap-2 p-0", children: [
|
|
5532
5367
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
|
|
5533
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", {
|
|
5368
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "relative w-full", children: [
|
|
5534
5369
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
|
|
5535
|
-
selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5536
|
-
import_lucide_react8.File,
|
|
5537
|
-
{
|
|
5538
|
-
size: 16,
|
|
5539
|
-
className: "shrink-0 text-foreground",
|
|
5540
|
-
"aria-hidden": true
|
|
5541
|
-
}
|
|
5542
|
-
) }) : null,
|
|
5370
|
+
selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(IconFile, { className: "text-foreground", "aria-hidden": true }) }) : null,
|
|
5543
5371
|
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)(
|
|
5544
5372
|
Input,
|
|
5545
5373
|
{
|
|
@@ -5551,14 +5379,7 @@ function UrlOrPageInput({
|
|
|
5551
5379
|
setIsFocused(true);
|
|
5552
5380
|
if (!selectedPage) openDropdown();
|
|
5553
5381
|
},
|
|
5554
|
-
onBlur: () =>
|
|
5555
|
-
setIsFocused(false);
|
|
5556
|
-
requestAnimationFrame(() => {
|
|
5557
|
-
if (!rootRef.current?.contains(document.activeElement)) {
|
|
5558
|
-
onDropdownOpenChange(false);
|
|
5559
|
-
}
|
|
5560
|
-
});
|
|
5561
|
-
},
|
|
5382
|
+
onBlur: () => setIsFocused(false),
|
|
5562
5383
|
placeholder,
|
|
5563
5384
|
className: cn(
|
|
5564
5385
|
"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",
|
|
@@ -5574,7 +5395,7 @@ function UrlOrPageInput({
|
|
|
5574
5395
|
onMouseDown: clearSelection,
|
|
5575
5396
|
"aria-label": "Clear selected page",
|
|
5576
5397
|
tabIndex: -1,
|
|
5577
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5398
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(IconX, { "aria-hidden": true })
|
|
5578
5399
|
}
|
|
5579
5400
|
) : null,
|
|
5580
5401
|
!readOnly ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(FieldChevron, { onClick: toggleDropdown }) : null
|
|
@@ -5583,7 +5404,7 @@ function UrlOrPageInput({
|
|
|
5583
5404
|
"div",
|
|
5584
5405
|
{
|
|
5585
5406
|
"data-ohw-link-page-dropdown": "",
|
|
5586
|
-
className: "absolute left-0 right-0 top-[calc(100%+4px)] z-
|
|
5407
|
+
className: "absolute left-0 right-0 h-20 top-[calc(100%+4px)] z-10 max-h-48 overflow-auto rounded-lg border border-border bg-popover py-1 shadow-lg",
|
|
5587
5408
|
onMouseDown: (e) => e.preventDefault(),
|
|
5588
5409
|
children: filteredPages.map((page) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
5589
5410
|
"button",
|
|
@@ -5592,7 +5413,7 @@ function UrlOrPageInput({
|
|
|
5592
5413
|
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",
|
|
5593
5414
|
onClick: () => onPageSelect(page),
|
|
5594
5415
|
children: [
|
|
5595
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5416
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(IconFile, { className: "shrink-0", "aria-hidden": true }),
|
|
5596
5417
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "truncate", children: page.title })
|
|
5597
5418
|
]
|
|
5598
5419
|
},
|
|
@@ -5605,439 +5426,8 @@ function UrlOrPageInput({
|
|
|
5605
5426
|
] });
|
|
5606
5427
|
}
|
|
5607
5428
|
|
|
5608
|
-
// src/ui/link-modal/
|
|
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
|
|
5429
|
+
// src/ui/link-modal/useLinkModalState.ts
|
|
5698
5430
|
var import_react5 = require("react");
|
|
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
5431
|
function useLinkModalState({
|
|
6042
5432
|
open,
|
|
6043
5433
|
mode,
|
|
@@ -6045,18 +5435,21 @@ function useLinkModalState({
|
|
|
6045
5435
|
sections: _sections,
|
|
6046
5436
|
sectionsByPath,
|
|
6047
5437
|
initialTarget,
|
|
6048
|
-
existingTargets
|
|
5438
|
+
existingTargets,
|
|
6049
5439
|
onClose,
|
|
6050
5440
|
onSubmit
|
|
6051
5441
|
}) {
|
|
6052
|
-
const availablePages = (0,
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
const [
|
|
6057
|
-
const [
|
|
6058
|
-
const [
|
|
6059
|
-
const
|
|
5442
|
+
const availablePages = (0, import_react5.useMemo)(
|
|
5443
|
+
() => mode === "create" ? filterAvailablePages(pages, existingTargets) : pages,
|
|
5444
|
+
[mode, pages, existingTargets]
|
|
5445
|
+
);
|
|
5446
|
+
const [searchValue, setSearchValue] = (0, import_react5.useState)("");
|
|
5447
|
+
const [selectedPage, setSelectedPage] = (0, import_react5.useState)(null);
|
|
5448
|
+
const [selectedSection, setSelectedSection] = (0, import_react5.useState)(null);
|
|
5449
|
+
const [step, setStep] = (0, import_react5.useState)("input");
|
|
5450
|
+
const [dropdownOpen, setDropdownOpen] = (0, import_react5.useState)(false);
|
|
5451
|
+
const [urlError, setUrlError] = (0, import_react5.useState)("");
|
|
5452
|
+
const reset = (0, import_react5.useCallback)(() => {
|
|
6060
5453
|
setSearchValue("");
|
|
6061
5454
|
setSelectedPage(null);
|
|
6062
5455
|
setSelectedSection(null);
|
|
@@ -6064,7 +5457,7 @@ function useLinkModalState({
|
|
|
6064
5457
|
setDropdownOpen(false);
|
|
6065
5458
|
setUrlError("");
|
|
6066
5459
|
}, []);
|
|
6067
|
-
(0,
|
|
5460
|
+
(0, import_react5.useEffect)(() => {
|
|
6068
5461
|
if (!open) return;
|
|
6069
5462
|
if (mode === "edit" && initialTarget) {
|
|
6070
5463
|
const { pageRoute } = parseTarget(initialTarget);
|
|
@@ -6079,12 +5472,12 @@ function useLinkModalState({
|
|
|
6079
5472
|
}
|
|
6080
5473
|
setDropdownOpen(false);
|
|
6081
5474
|
setUrlError("");
|
|
6082
|
-
}, [open, mode, initialTarget, reset]);
|
|
6083
|
-
const filteredPages = (0,
|
|
5475
|
+
}, [open, mode, initialTarget, pages, sectionsByPath, reset]);
|
|
5476
|
+
const filteredPages = (0, import_react5.useMemo)(() => {
|
|
6084
5477
|
if (!searchValue.trim()) return availablePages;
|
|
6085
5478
|
return availablePages.filter((p) => p.title.toLowerCase().startsWith(searchValue.toLowerCase()));
|
|
6086
5479
|
}, [availablePages, searchValue]);
|
|
6087
|
-
const activeSections = (0,
|
|
5480
|
+
const activeSections = (0, import_react5.useMemo)(() => {
|
|
6088
5481
|
if (!selectedPage) return [];
|
|
6089
5482
|
return getSectionsForPath(sectionsByPath, selectedPage.path);
|
|
6090
5483
|
}, [selectedPage, sectionsByPath]);
|
|
@@ -6126,14 +5519,11 @@ function useLinkModalState({
|
|
|
6126
5519
|
const handleBackToSections = () => {
|
|
6127
5520
|
setStep("sectionPicker");
|
|
6128
5521
|
};
|
|
6129
|
-
const handleSectionPickerBack = () => {
|
|
6130
|
-
setStep("input");
|
|
6131
|
-
};
|
|
6132
5522
|
const handleClose = () => {
|
|
6133
5523
|
reset();
|
|
6134
5524
|
onClose();
|
|
6135
5525
|
};
|
|
6136
|
-
const isValid = (0,
|
|
5526
|
+
const isValid = (0, import_react5.useMemo)(() => {
|
|
6137
5527
|
if (urlError) return false;
|
|
6138
5528
|
if (showBreadcrumb) return true;
|
|
6139
5529
|
if (selectedPage) return true;
|
|
@@ -6166,7 +5556,7 @@ function useLinkModalState({
|
|
|
6166
5556
|
onSubmit(normalizeUrl(searchValue));
|
|
6167
5557
|
handleClose();
|
|
6168
5558
|
};
|
|
6169
|
-
const submitLabel =
|
|
5559
|
+
const submitLabel = mode === "edit" ? "Save" : "Create";
|
|
6170
5560
|
const title = mode === "edit" ? "Edit navigation item" : "Create navigation item";
|
|
6171
5561
|
const secondaryLabel = showBreadcrumb ? "Back to sections" : "Cancel";
|
|
6172
5562
|
const handleSecondary = showBreadcrumb ? handleBackToSections : handleClose;
|
|
@@ -6193,29 +5583,23 @@ function useLinkModalState({
|
|
|
6193
5583
|
handleChooseSection,
|
|
6194
5584
|
handleSectionSelect,
|
|
6195
5585
|
handleBackToSections,
|
|
6196
|
-
handleSectionPickerBack,
|
|
6197
5586
|
handleClose,
|
|
6198
5587
|
handleSecondary,
|
|
6199
5588
|
handleSubmit
|
|
6200
5589
|
};
|
|
6201
5590
|
}
|
|
6202
5591
|
|
|
6203
|
-
// src/ui/link-modal/
|
|
6204
|
-
var
|
|
6205
|
-
function
|
|
6206
|
-
window.parent?.postMessage(data, "*");
|
|
6207
|
-
}
|
|
6208
|
-
function LinkPopover({
|
|
5592
|
+
// src/ui/link-modal/LinkEditorPanel.tsx
|
|
5593
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
5594
|
+
function LinkEditorPanel({
|
|
6209
5595
|
open = true,
|
|
6210
|
-
panelRef,
|
|
6211
|
-
portalContainer,
|
|
6212
|
-
onClose,
|
|
6213
5596
|
mode = "create",
|
|
6214
5597
|
pages,
|
|
6215
5598
|
sections = [],
|
|
6216
5599
|
sectionsByPath,
|
|
6217
5600
|
initialTarget,
|
|
6218
5601
|
existingTargets = [],
|
|
5602
|
+
onClose,
|
|
6219
5603
|
onSubmit
|
|
6220
5604
|
}) {
|
|
6221
5605
|
const state = useLinkModalState({
|
|
@@ -6229,109 +5613,115 @@ function LinkPopover({
|
|
|
6229
5613
|
onClose,
|
|
6230
5614
|
onSubmit
|
|
6231
5615
|
});
|
|
6232
|
-
const
|
|
6233
|
-
(0,
|
|
6234
|
-
|
|
6235
|
-
|
|
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,
|
|
6303
|
-
{
|
|
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
|
-
)
|
|
6321
|
-
}
|
|
6322
|
-
),
|
|
6323
|
-
sectionPickerActive && state.selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6324
|
-
SectionPickerOverlay,
|
|
5616
|
+
const isCancel = state.secondaryLabel === "Cancel";
|
|
5617
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
|
|
5618
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DialogClose, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5619
|
+
"button",
|
|
6325
5620
|
{
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
|
|
6329
|
-
|
|
5621
|
+
type: "button",
|
|
5622
|
+
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
5623
|
+
"aria-label": "Close",
|
|
5624
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(IconX, { "aria-hidden": true })
|
|
6330
5625
|
}
|
|
6331
|
-
)
|
|
5626
|
+
) }),
|
|
5627
|
+
/* @__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 }) }),
|
|
5628
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
|
|
5629
|
+
state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5630
|
+
DestinationBreadcrumb,
|
|
5631
|
+
{
|
|
5632
|
+
pageTitle: state.selectedPage.title,
|
|
5633
|
+
sectionLabel: state.selectedSection.label
|
|
5634
|
+
}
|
|
5635
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
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
|
+
] })
|
|
6332
5689
|
] });
|
|
6333
5690
|
}
|
|
6334
5691
|
|
|
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
|
+
|
|
6335
5725
|
// src/ui/link-modal/devFixtures.ts
|
|
6336
5726
|
var DEV_SITE_PAGES = [
|
|
6337
5727
|
{ path: "/", title: "Home" },
|
|
@@ -6351,766 +5741,47 @@ var DEV_SECTIONS_BY_PATH = {
|
|
|
6351
5741
|
{ id: "founder-teaser", label: "Founder" },
|
|
6352
5742
|
{ id: "plan-form", label: "Plan Form" },
|
|
6353
5743
|
{ id: "testimonials", label: "Testimonials" },
|
|
6354
|
-
{ id: "wordmark", label: "Wordmark" }
|
|
6355
|
-
{ id: "footer", label: "Footer" }
|
|
5744
|
+
{ id: "wordmark", label: "Wordmark" }
|
|
6356
5745
|
],
|
|
6357
5746
|
"/about": [
|
|
6358
5747
|
{ id: "manifesto", label: "Manifesto" },
|
|
6359
5748
|
{ id: "story-letter", label: "Our Story" },
|
|
6360
5749
|
{ id: "lagree-explainer", label: "Lagree Explainer" },
|
|
6361
5750
|
{ id: "waitlist-cta", label: "Waitlist" },
|
|
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" }
|
|
5751
|
+
{ id: "personal-training", label: "Personal training" }
|
|
6368
5752
|
],
|
|
5753
|
+
"/classes": [{ id: "class-library", label: "Class Library" }],
|
|
6369
5754
|
"/pricing": [
|
|
6370
5755
|
{ id: "page-header", label: "Page Header" },
|
|
6371
5756
|
{ id: "free-class-cta", label: "Free Class" },
|
|
6372
|
-
{ id: "benefits-marquee", label: "Benefits" },
|
|
6373
|
-
{ id: "monthly-memberships", label: "Memberships" },
|
|
6374
|
-
{ id: "specialty-programs", label: "Specialty Programs" },
|
|
6375
|
-
{ id: "package-matcher", label: "Packages" },
|
|
6376
|
-
{ id: "wordmark", label: "Wordmark" }
|
|
6377
|
-
|
|
6378
|
-
|
|
6379
|
-
|
|
6380
|
-
{ id: "studio-
|
|
6381
|
-
{ id: "studio-
|
|
6382
|
-
{ id: "studio-
|
|
6383
|
-
|
|
6384
|
-
|
|
6385
|
-
|
|
6386
|
-
|
|
6387
|
-
{ id: "
|
|
6388
|
-
{ id: "
|
|
6389
|
-
]
|
|
6390
|
-
|
|
6391
|
-
|
|
6392
|
-
|
|
6393
|
-
|
|
6394
|
-
|
|
6395
|
-
|
|
6396
|
-
};
|
|
6397
|
-
function shouldUseDevFixtures() {
|
|
6398
|
-
if (typeof window === "undefined") return false;
|
|
6399
|
-
const raw = readPreservedSearch();
|
|
6400
|
-
const q = raw.startsWith("?") ? raw.slice(1) : raw;
|
|
6401
|
-
return new URLSearchParams(q).get("ohw-fixtures") === "1";
|
|
6402
|
-
}
|
|
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
|
-
);
|
|
5757
|
+
{ id: "benefits-marquee", label: "Benefits" },
|
|
5758
|
+
{ id: "monthly-memberships", label: "Memberships" },
|
|
5759
|
+
{ id: "specialty-programs", label: "Specialty Programs" },
|
|
5760
|
+
{ id: "package-matcher", label: "Packages" },
|
|
5761
|
+
{ id: "wordmark", label: "Wordmark" }
|
|
5762
|
+
],
|
|
5763
|
+
"/studio": [
|
|
5764
|
+
{ id: "studio-intro", label: "Studio Intro" },
|
|
5765
|
+
{ id: "studio-features", label: "Studio Features" },
|
|
5766
|
+
{ id: "studio-gallery", label: "Studio Gallery" },
|
|
5767
|
+
{ id: "studio-visit", label: "Visit Studio" }
|
|
5768
|
+
],
|
|
5769
|
+
"/instructors": [{ id: "instructor-grid", label: "Instructors" }],
|
|
5770
|
+
"/contact": [
|
|
5771
|
+
{ id: "hello-hero", label: "Hello" },
|
|
5772
|
+
{ id: "contact-form", label: "Contact Form" },
|
|
5773
|
+
{ id: "faq", label: "FAQ" }
|
|
5774
|
+
]
|
|
5775
|
+
};
|
|
5776
|
+
function shouldUseDevFixtures() {
|
|
5777
|
+
if (typeof window === "undefined") return false;
|
|
5778
|
+
const raw = readPreservedSearch();
|
|
5779
|
+
const q = raw.startsWith("?") ? raw.slice(1) : raw;
|
|
5780
|
+
return new URLSearchParams(q).get("ohw-fixtures") === "1";
|
|
7068
5781
|
}
|
|
7069
5782
|
|
|
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
|
-
|
|
7112
5783
|
// src/ui/badge.tsx
|
|
7113
|
-
var
|
|
5784
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
7114
5785
|
var badgeVariants = cva(
|
|
7115
5786
|
"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",
|
|
7116
5787
|
{
|
|
@@ -7128,12 +5799,12 @@ var badgeVariants = cva(
|
|
|
7128
5799
|
}
|
|
7129
5800
|
);
|
|
7130
5801
|
function Badge({ className, variant, ...props }) {
|
|
7131
|
-
return /* @__PURE__ */ (0,
|
|
5802
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
7132
5803
|
}
|
|
7133
5804
|
|
|
7134
5805
|
// src/OhhwellsBridge.tsx
|
|
7135
|
-
var
|
|
7136
|
-
var
|
|
5806
|
+
var import_lucide_react4 = require("lucide-react");
|
|
5807
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
7137
5808
|
var PRIMARY2 = "#0885FE";
|
|
7138
5809
|
var IMAGE_FADE_MS = 300;
|
|
7139
5810
|
function runOpacityFade(el, onDone) {
|
|
@@ -7310,9 +5981,9 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
7310
5981
|
tail.insertAdjacentElement("afterend", container);
|
|
7311
5982
|
}
|
|
7312
5983
|
const root = (0, import_client.createRoot)(container);
|
|
7313
|
-
(0,
|
|
5984
|
+
(0, import_react_dom.flushSync)(() => {
|
|
7314
5985
|
root.render(
|
|
7315
|
-
/* @__PURE__ */ (0,
|
|
5986
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7316
5987
|
SchedulingWidget,
|
|
7317
5988
|
{
|
|
7318
5989
|
notifyOnConnect,
|
|
@@ -7352,7 +6023,7 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
|
|
|
7352
6023
|
}
|
|
7353
6024
|
}
|
|
7354
6025
|
}
|
|
7355
|
-
function
|
|
6026
|
+
function getLinkHref(el) {
|
|
7356
6027
|
const anchor = el instanceof HTMLAnchorElement ? el : el.querySelector("a");
|
|
7357
6028
|
return anchor?.getAttribute("href") ?? "";
|
|
7358
6029
|
}
|
|
@@ -7374,7 +6045,7 @@ function isDragHandleDisabled(el) {
|
|
|
7374
6045
|
return raw === "true" || raw === "";
|
|
7375
6046
|
});
|
|
7376
6047
|
}
|
|
7377
|
-
function collectEditableNodes(
|
|
6048
|
+
function collectEditableNodes() {
|
|
7378
6049
|
const nodes = Array.from(document.querySelectorAll("[data-ohw-editable]")).map((el) => {
|
|
7379
6050
|
if (el.dataset.ohwEditable === "image") {
|
|
7380
6051
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
@@ -7389,7 +6060,7 @@ function collectEditableNodes(extraContent) {
|
|
|
7389
6060
|
return { key: el.dataset.ohwKey ?? "", type: "video", text: getVideoEl(el)?.src ?? "" };
|
|
7390
6061
|
}
|
|
7391
6062
|
if (el.dataset.ohwEditable === "link") {
|
|
7392
|
-
return { key: el.dataset.ohwKey ?? "", type: "link", text:
|
|
6063
|
+
return { key: el.dataset.ohwKey ?? "", type: "link", text: getLinkHref(el) };
|
|
7393
6064
|
}
|
|
7394
6065
|
return {
|
|
7395
6066
|
key: el.dataset.ohwKey ?? "",
|
|
@@ -7400,16 +6071,8 @@ function collectEditableNodes(extraContent) {
|
|
|
7400
6071
|
document.querySelectorAll("[data-ohw-href-key]").forEach((el) => {
|
|
7401
6072
|
const key = el.getAttribute("data-ohw-href-key") ?? "";
|
|
7402
6073
|
if (!key) return;
|
|
7403
|
-
nodes.push({ key, type: "link", text:
|
|
6074
|
+
nodes.push({ key, type: "link", text: getLinkHref(el) });
|
|
7404
6075
|
});
|
|
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
|
-
}
|
|
7413
6076
|
document.querySelectorAll('[data-ohw-editable="video"]').forEach((el) => {
|
|
7414
6077
|
const key = el.dataset.ohwKey ?? "";
|
|
7415
6078
|
const video = getVideoEl(el);
|
|
@@ -7417,10 +6080,13 @@ function collectEditableNodes(extraContent) {
|
|
|
7417
6080
|
nodes.push({ key: `${key}${VIDEO_AUTOPLAY_SUFFIX}`, type: "video-setting", text: String(video.autoplay) });
|
|
7418
6081
|
nodes.push({ key: `${key}${VIDEO_MUTED_SUFFIX}`, type: "video-setting", text: String(video.muted) });
|
|
7419
6082
|
});
|
|
7420
|
-
|
|
7421
|
-
|
|
7422
|
-
|
|
7423
|
-
|
|
6083
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6084
|
+
return nodes.filter((node) => {
|
|
6085
|
+
if (!node.key) return true;
|
|
6086
|
+
if (seen.has(node.key)) return false;
|
|
6087
|
+
seen.add(node.key);
|
|
6088
|
+
return true;
|
|
6089
|
+
});
|
|
7424
6090
|
}
|
|
7425
6091
|
function isMediaEditable(el) {
|
|
7426
6092
|
const t = el.dataset.ohwEditable;
|
|
@@ -7497,7 +6163,7 @@ function applyLinkByKey(key, val) {
|
|
|
7497
6163
|
}
|
|
7498
6164
|
function isInsideLinkEditor(target) {
|
|
7499
6165
|
return Boolean(
|
|
7500
|
-
target.closest("[data-ohw-link-popover-root]") || target.closest("[data-ohw-link-modal-root]") || target.closest("[data-ohw-link-page-dropdown]") || target.closest(
|
|
6166
|
+
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"]')
|
|
7501
6167
|
);
|
|
7502
6168
|
}
|
|
7503
6169
|
function getHrefKeyFromElement(el) {
|
|
@@ -7508,30 +6174,7 @@ function getHrefKeyFromElement(el) {
|
|
|
7508
6174
|
if (!key) return null;
|
|
7509
6175
|
return { anchor, key };
|
|
7510
6176
|
}
|
|
7511
|
-
function
|
|
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) {
|
|
6177
|
+
function isNavbarButton(el) {
|
|
7535
6178
|
return Boolean(el.closest('[data-ohw-role="navbar-button"]'));
|
|
7536
6179
|
}
|
|
7537
6180
|
function getNavigationItemAnchor(el) {
|
|
@@ -7543,8 +6186,19 @@ function getNavigationItemAnchor(el) {
|
|
|
7543
6186
|
function isNavigationItem(el) {
|
|
7544
6187
|
return getNavigationItemAnchor(el) !== null;
|
|
7545
6188
|
}
|
|
6189
|
+
function getNavigationItemAddHintTarget(anchor) {
|
|
6190
|
+
const items = listNavigationItems();
|
|
6191
|
+
const idx = items.indexOf(anchor);
|
|
6192
|
+
if (idx >= 0 && idx < items.length - 1) return items[idx + 1];
|
|
6193
|
+
return anchor;
|
|
6194
|
+
}
|
|
6195
|
+
function listNavigationItems() {
|
|
6196
|
+
return Array.from(
|
|
6197
|
+
document.querySelectorAll("nav [data-ohw-href-key], footer [data-ohw-href-key]")
|
|
6198
|
+
).filter((el) => isNavigationItem(el));
|
|
6199
|
+
}
|
|
7546
6200
|
function getNavigationItemReorderState(anchor) {
|
|
7547
|
-
if (
|
|
6201
|
+
if (isNavbarButton(anchor)) return { key: null, disabled: false };
|
|
7548
6202
|
return getReorderHandleStateFromAnchor(anchor);
|
|
7549
6203
|
}
|
|
7550
6204
|
function getReorderHandleState(el) {
|
|
@@ -7566,120 +6220,6 @@ function clearHrefKeyHover(anchor) {
|
|
|
7566
6220
|
function isInsideNavigationItem(el) {
|
|
7567
6221
|
return getNavigationItemAnchor(el) !== null;
|
|
7568
6222
|
}
|
|
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") || 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
|
-
}
|
|
7683
6223
|
function collectSections() {
|
|
7684
6224
|
return collectSectionsFromDom();
|
|
7685
6225
|
}
|
|
@@ -7803,8 +6343,6 @@ var ICONS = {
|
|
|
7803
6343
|
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"/>',
|
|
7804
6344
|
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"/>'
|
|
7805
6345
|
};
|
|
7806
|
-
var TOOLBAR_PILL_PADDING = 2;
|
|
7807
|
-
var TOOLBAR_TOGGLE_GAP = 4;
|
|
7808
6346
|
var TOOLBAR_GROUPS = [
|
|
7809
6347
|
[
|
|
7810
6348
|
{ cmd: "bold", title: "Bold" },
|
|
@@ -7829,7 +6367,7 @@ function EditGlowChrome({
|
|
|
7829
6367
|
dragDisabled = false
|
|
7830
6368
|
}) {
|
|
7831
6369
|
const GAP = 6;
|
|
7832
|
-
return /* @__PURE__ */ (0,
|
|
6370
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
7833
6371
|
"div",
|
|
7834
6372
|
{
|
|
7835
6373
|
ref: elRef,
|
|
@@ -7844,7 +6382,7 @@ function EditGlowChrome({
|
|
|
7844
6382
|
zIndex: 2147483646
|
|
7845
6383
|
},
|
|
7846
6384
|
children: [
|
|
7847
|
-
/* @__PURE__ */ (0,
|
|
6385
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7848
6386
|
"div",
|
|
7849
6387
|
{
|
|
7850
6388
|
style: {
|
|
@@ -7857,7 +6395,7 @@ function EditGlowChrome({
|
|
|
7857
6395
|
}
|
|
7858
6396
|
}
|
|
7859
6397
|
),
|
|
7860
|
-
reorderHrefKey && /* @__PURE__ */ (0,
|
|
6398
|
+
reorderHrefKey && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7861
6399
|
"div",
|
|
7862
6400
|
{
|
|
7863
6401
|
"data-ohw-drag-handle-container": "",
|
|
@@ -7869,7 +6407,7 @@ function EditGlowChrome({
|
|
|
7869
6407
|
transform: "translate(calc(-100% - 7px), -50%)",
|
|
7870
6408
|
pointerEvents: dragDisabled ? "none" : "auto"
|
|
7871
6409
|
},
|
|
7872
|
-
children: /* @__PURE__ */ (0,
|
|
6410
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7873
6411
|
DragHandle,
|
|
7874
6412
|
{
|
|
7875
6413
|
"aria-label": `Reorder ${reorderHrefKey}`,
|
|
@@ -7973,7 +6511,7 @@ function FloatingToolbar({
|
|
|
7973
6511
|
onEditLink
|
|
7974
6512
|
}) {
|
|
7975
6513
|
const { top, left, transform } = calcToolbarPos(rect, parentScroll, 330);
|
|
7976
|
-
return /* @__PURE__ */ (0,
|
|
6514
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7977
6515
|
"div",
|
|
7978
6516
|
{
|
|
7979
6517
|
ref: elRef,
|
|
@@ -7983,23 +6521,14 @@ function FloatingToolbar({
|
|
|
7983
6521
|
left,
|
|
7984
6522
|
transform,
|
|
7985
6523
|
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",
|
|
7995
6524
|
pointerEvents: "auto"
|
|
7996
6525
|
},
|
|
7997
|
-
children: /* @__PURE__ */ (0,
|
|
7998
|
-
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0,
|
|
7999
|
-
gi > 0 && /* @__PURE__ */ (0,
|
|
6526
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(CustomToolbar, { children: [
|
|
6527
|
+
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react6.default.Fragment, { children: [
|
|
6528
|
+
gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CustomToolbarDivider, {}),
|
|
8000
6529
|
btns.map((btn) => {
|
|
8001
6530
|
const isActive = activeCommands.has(btn.cmd);
|
|
8002
|
-
return /* @__PURE__ */ (0,
|
|
6531
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
8003
6532
|
CustomToolbarButton,
|
|
8004
6533
|
{
|
|
8005
6534
|
title: btn.title,
|
|
@@ -8008,7 +6537,7 @@ function FloatingToolbar({
|
|
|
8008
6537
|
e.preventDefault();
|
|
8009
6538
|
onCommand(btn.cmd);
|
|
8010
6539
|
},
|
|
8011
|
-
children: /* @__PURE__ */ (0,
|
|
6540
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
8012
6541
|
"svg",
|
|
8013
6542
|
{
|
|
8014
6543
|
width: "16",
|
|
@@ -8029,7 +6558,7 @@ function FloatingToolbar({
|
|
|
8029
6558
|
);
|
|
8030
6559
|
})
|
|
8031
6560
|
] }, gi)),
|
|
8032
|
-
showEditLink ? /* @__PURE__ */ (0,
|
|
6561
|
+
showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
8033
6562
|
CustomToolbarButton,
|
|
8034
6563
|
{
|
|
8035
6564
|
type: "button",
|
|
@@ -8043,7 +6572,7 @@ function FloatingToolbar({
|
|
|
8043
6572
|
e.preventDefault();
|
|
8044
6573
|
e.stopPropagation();
|
|
8045
6574
|
},
|
|
8046
|
-
children: /* @__PURE__ */ (0,
|
|
6575
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react4.Link, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
8047
6576
|
}
|
|
8048
6577
|
) : null
|
|
8049
6578
|
] })
|
|
@@ -8060,7 +6589,7 @@ function StateToggle({
|
|
|
8060
6589
|
states,
|
|
8061
6590
|
onStateChange
|
|
8062
6591
|
}) {
|
|
8063
|
-
return /* @__PURE__ */ (0,
|
|
6592
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
8064
6593
|
ToggleGroup,
|
|
8065
6594
|
{
|
|
8066
6595
|
"data-ohw-state-toggle": "",
|
|
@@ -8074,7 +6603,7 @@ function StateToggle({
|
|
|
8074
6603
|
left: rect.right - 8,
|
|
8075
6604
|
transform: "translateX(-100%)"
|
|
8076
6605
|
},
|
|
8077
|
-
children: states.map((state) => /* @__PURE__ */ (0,
|
|
6606
|
+
children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
|
|
8078
6607
|
}
|
|
8079
6608
|
);
|
|
8080
6609
|
}
|
|
@@ -8097,12 +6626,12 @@ function resolveSubdomain(subdomainFromQuery) {
|
|
|
8097
6626
|
return "";
|
|
8098
6627
|
}
|
|
8099
6628
|
function OhhwellsBridge() {
|
|
8100
|
-
const pathname = (0,
|
|
8101
|
-
const router = (0,
|
|
8102
|
-
const searchParams = (0,
|
|
6629
|
+
const pathname = (0, import_navigation.usePathname)();
|
|
6630
|
+
const router = (0, import_navigation.useRouter)();
|
|
6631
|
+
const searchParams = (0, import_navigation.useSearchParams)();
|
|
8103
6632
|
const isEditMode = isEditSessionActive();
|
|
8104
|
-
const [bridgeRoot, setBridgeRoot] = (0,
|
|
8105
|
-
(0,
|
|
6633
|
+
const [bridgeRoot, setBridgeRoot] = (0, import_react6.useState)(null);
|
|
6634
|
+
(0, import_react6.useEffect)(() => {
|
|
8106
6635
|
const figtreeFontId = "ohw-figtree-font";
|
|
8107
6636
|
if (!document.getElementById(figtreeFontId)) {
|
|
8108
6637
|
const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
|
|
@@ -8130,100 +6659,83 @@ function OhhwellsBridge() {
|
|
|
8130
6659
|
const subdomainFromQuery = searchParams.get("subdomain");
|
|
8131
6660
|
const subdomain = resolveSubdomain(subdomainFromQuery);
|
|
8132
6661
|
useLinkHrefGuardian(pathname, subdomain, isEditMode);
|
|
8133
|
-
const
|
|
6662
|
+
const postToParent = (0, import_react6.useCallback)((data) => {
|
|
8134
6663
|
if (typeof window !== "undefined" && window.parent !== window) {
|
|
8135
6664
|
window.parent.postMessage(data, "*");
|
|
8136
6665
|
}
|
|
8137
6666
|
}, []);
|
|
8138
|
-
const [fetchState, setFetchState] = (0,
|
|
8139
|
-
const autoSaveTimers = (0,
|
|
8140
|
-
const activeElRef = (0,
|
|
8141
|
-
const selectedElRef = (0,
|
|
8142
|
-
const originalContentRef = (0,
|
|
8143
|
-
const activeStateElRef = (0,
|
|
8144
|
-
const parentScrollRef = (0,
|
|
8145
|
-
const visibleViewportRef = (0,
|
|
8146
|
-
const [dialogPortalContainer, setDialogPortalContainer] = (0,
|
|
8147
|
-
const attachVisibleViewport = (0,
|
|
6667
|
+
const [fetchState, setFetchState] = (0, import_react6.useState)("idle");
|
|
6668
|
+
const autoSaveTimers = (0, import_react6.useRef)(/* @__PURE__ */ new Map());
|
|
6669
|
+
const activeElRef = (0, import_react6.useRef)(null);
|
|
6670
|
+
const selectedElRef = (0, import_react6.useRef)(null);
|
|
6671
|
+
const originalContentRef = (0, import_react6.useRef)(null);
|
|
6672
|
+
const activeStateElRef = (0, import_react6.useRef)(null);
|
|
6673
|
+
const parentScrollRef = (0, import_react6.useRef)(null);
|
|
6674
|
+
const visibleViewportRef = (0, import_react6.useRef)(null);
|
|
6675
|
+
const [dialogPortalContainer, setDialogPortalContainer] = (0, import_react6.useState)(null);
|
|
6676
|
+
const attachVisibleViewport = (0, import_react6.useCallback)((node) => {
|
|
8148
6677
|
visibleViewportRef.current = node;
|
|
8149
6678
|
setDialogPortalContainer(node);
|
|
8150
6679
|
if (node) applyVisibleViewport(node, parentScrollRef.current);
|
|
8151
6680
|
}, []);
|
|
8152
|
-
const toolbarElRef = (0,
|
|
8153
|
-
const glowElRef = (0,
|
|
8154
|
-
const hoveredImageRef = (0,
|
|
8155
|
-
const hoveredImageHasTextOverlapRef = (0,
|
|
8156
|
-
const dragOverElRef = (0,
|
|
8157
|
-
const [mediaHover, setMediaHover] = (0,
|
|
8158
|
-
const [
|
|
8159
|
-
const
|
|
8160
|
-
const
|
|
8161
|
-
const
|
|
8162
|
-
const
|
|
8163
|
-
const
|
|
8164
|
-
const activateRef = (0, import_react9.useRef)(() => {
|
|
8165
|
-
});
|
|
8166
|
-
const deactivateRef = (0, import_react9.useRef)(() => {
|
|
6681
|
+
const toolbarElRef = (0, import_react6.useRef)(null);
|
|
6682
|
+
const glowElRef = (0, import_react6.useRef)(null);
|
|
6683
|
+
const hoveredImageRef = (0, import_react6.useRef)(null);
|
|
6684
|
+
const hoveredImageHasTextOverlapRef = (0, import_react6.useRef)(false);
|
|
6685
|
+
const dragOverElRef = (0, import_react6.useRef)(null);
|
|
6686
|
+
const [mediaHover, setMediaHover] = (0, import_react6.useState)(null);
|
|
6687
|
+
const [uploadingRects, setUploadingRects] = (0, import_react6.useState)({});
|
|
6688
|
+
const hoveredGapRef = (0, import_react6.useRef)(null);
|
|
6689
|
+
const imageUnhoverTimerRef = (0, import_react6.useRef)(null);
|
|
6690
|
+
const imageShowTimerRef = (0, import_react6.useRef)(null);
|
|
6691
|
+
const editStylesRef = (0, import_react6.useRef)(null);
|
|
6692
|
+
const activateRef = (0, import_react6.useRef)(() => {
|
|
8167
6693
|
});
|
|
8168
|
-
const
|
|
6694
|
+
const deactivateRef = (0, import_react6.useRef)(() => {
|
|
8169
6695
|
});
|
|
8170
|
-
const
|
|
6696
|
+
const selectRef = (0, import_react6.useRef)(() => {
|
|
8171
6697
|
});
|
|
8172
|
-
const deselectRef = (0,
|
|
6698
|
+
const deselectRef = (0, import_react6.useRef)(() => {
|
|
8173
6699
|
});
|
|
8174
|
-
const reselectNavigationItemRef = (0,
|
|
6700
|
+
const reselectNavigationItemRef = (0, import_react6.useRef)(() => {
|
|
8175
6701
|
});
|
|
8176
|
-
const commitNavigationTextEditRef = (0,
|
|
6702
|
+
const commitNavigationTextEditRef = (0, import_react6.useRef)(() => {
|
|
8177
6703
|
});
|
|
8178
|
-
const refreshActiveCommandsRef = (0,
|
|
6704
|
+
const refreshActiveCommandsRef = (0, import_react6.useRef)(() => {
|
|
8179
6705
|
});
|
|
8180
|
-
const postToParentRef = (0,
|
|
8181
|
-
postToParentRef.current =
|
|
8182
|
-
const sectionsLoadedRef = (0,
|
|
8183
|
-
const pendingScheduleConfigRequests = (0,
|
|
8184
|
-
const [toolbarRect, setToolbarRect] = (0,
|
|
8185
|
-
const [toolbarVariant, setToolbarVariant] = (0,
|
|
8186
|
-
const toolbarVariantRef = (0,
|
|
6706
|
+
const postToParentRef = (0, import_react6.useRef)(postToParent);
|
|
6707
|
+
postToParentRef.current = postToParent;
|
|
6708
|
+
const sectionsLoadedRef = (0, import_react6.useRef)(false);
|
|
6709
|
+
const pendingScheduleConfigRequests = (0, import_react6.useRef)([]);
|
|
6710
|
+
const [toolbarRect, setToolbarRect] = (0, import_react6.useState)(null);
|
|
6711
|
+
const [toolbarVariant, setToolbarVariant] = (0, import_react6.useState)("none");
|
|
6712
|
+
const toolbarVariantRef = (0, import_react6.useRef)("none");
|
|
8187
6713
|
toolbarVariantRef.current = toolbarVariant;
|
|
8188
|
-
const [reorderHrefKey, setReorderHrefKey] = (0,
|
|
8189
|
-
const [reorderDragDisabled, setReorderDragDisabled] = (0,
|
|
8190
|
-
const [toggleState, setToggleState] = (0,
|
|
8191
|
-
const [maxBadge, setMaxBadge] = (0,
|
|
8192
|
-
const [activeCommands, setActiveCommands] = (0,
|
|
8193
|
-
const [sectionGap, setSectionGap] = (0,
|
|
8194
|
-
const [toolbarShowEditLink, setToolbarShowEditLink] = (0,
|
|
8195
|
-
const
|
|
8196
|
-
const [
|
|
8197
|
-
const
|
|
8198
|
-
const [
|
|
8199
|
-
const
|
|
8200
|
-
const [
|
|
8201
|
-
const [
|
|
8202
|
-
const [
|
|
8203
|
-
const
|
|
8204
|
-
const
|
|
8205
|
-
const
|
|
8206
|
-
const
|
|
8207
|
-
const
|
|
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);
|
|
6714
|
+
const [reorderHrefKey, setReorderHrefKey] = (0, import_react6.useState)(null);
|
|
6715
|
+
const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react6.useState)(false);
|
|
6716
|
+
const [toggleState, setToggleState] = (0, import_react6.useState)(null);
|
|
6717
|
+
const [maxBadge, setMaxBadge] = (0, import_react6.useState)(null);
|
|
6718
|
+
const [activeCommands, setActiveCommands] = (0, import_react6.useState)(/* @__PURE__ */ new Set());
|
|
6719
|
+
const [sectionGap, setSectionGap] = (0, import_react6.useState)(null);
|
|
6720
|
+
const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react6.useState)(false);
|
|
6721
|
+
const hoveredItemElRef = (0, import_react6.useRef)(null);
|
|
6722
|
+
const [hoveredItemRect, setHoveredItemRect] = (0, import_react6.useState)(null);
|
|
6723
|
+
const siblingHintElRef = (0, import_react6.useRef)(null);
|
|
6724
|
+
const [siblingHintRect, setSiblingHintRect] = (0, import_react6.useState)(null);
|
|
6725
|
+
const [isItemDragging, setIsItemDragging] = (0, import_react6.useState)(false);
|
|
6726
|
+
const [linkPopover, setLinkPopover] = (0, import_react6.useState)(null);
|
|
6727
|
+
const [sitePages, setSitePages] = (0, import_react6.useState)([]);
|
|
6728
|
+
const [sectionsByPath, setSectionsByPath] = (0, import_react6.useState)({});
|
|
6729
|
+
const sectionsPrefetchGenRef = (0, import_react6.useRef)(0);
|
|
6730
|
+
const setLinkPopoverRef = (0, import_react6.useRef)(setLinkPopover);
|
|
6731
|
+
const linkPopoverPanelRef = (0, import_react6.useRef)(null);
|
|
6732
|
+
const linkPopoverOpenRef = (0, import_react6.useRef)(false);
|
|
6733
|
+
const linkPopoverGraceUntilRef = (0, import_react6.useRef)(0);
|
|
8221
6734
|
setLinkPopoverRef.current = setLinkPopover;
|
|
8222
|
-
linkPopoverSessionRef.current = linkPopover;
|
|
8223
6735
|
const bumpLinkPopoverGrace = () => {
|
|
8224
6736
|
linkPopoverGraceUntilRef.current = Date.now() + 350;
|
|
8225
6737
|
};
|
|
8226
|
-
const runSectionsPrefetch = (0,
|
|
6738
|
+
const runSectionsPrefetch = (0, import_react6.useCallback)((pages) => {
|
|
8227
6739
|
if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
|
|
8228
6740
|
const gen = ++sectionsPrefetchGenRef.current;
|
|
8229
6741
|
const paths = pages.map((p) => p.path);
|
|
@@ -8242,9 +6754,9 @@ function OhhwellsBridge() {
|
|
|
8242
6754
|
);
|
|
8243
6755
|
});
|
|
8244
6756
|
}, [isEditMode, pathname]);
|
|
8245
|
-
const runSectionsPrefetchRef = (0,
|
|
6757
|
+
const runSectionsPrefetchRef = (0, import_react6.useRef)(runSectionsPrefetch);
|
|
8246
6758
|
runSectionsPrefetchRef.current = runSectionsPrefetch;
|
|
8247
|
-
(0,
|
|
6759
|
+
(0, import_react6.useEffect)(() => {
|
|
8248
6760
|
if (!linkPopover) return;
|
|
8249
6761
|
if (hoveredImageRef.current) {
|
|
8250
6762
|
hoveredImageRef.current = null;
|
|
@@ -8252,9 +6764,33 @@ function OhhwellsBridge() {
|
|
|
8252
6764
|
}
|
|
8253
6765
|
hoveredGapRef.current = null;
|
|
8254
6766
|
setSectionGap(null);
|
|
8255
|
-
|
|
8256
|
-
|
|
8257
|
-
|
|
6767
|
+
setMediaHover(null);
|
|
6768
|
+
postToParent({ type: "ow:link-modal-lock", locked: true });
|
|
6769
|
+
const html = document.documentElement;
|
|
6770
|
+
const body = document.body;
|
|
6771
|
+
const prevHtmlOverflow = html.style.overflow;
|
|
6772
|
+
const prevBodyOverflow = body.style.overflow;
|
|
6773
|
+
html.style.overflow = "hidden";
|
|
6774
|
+
body.style.overflow = "hidden";
|
|
6775
|
+
const preventBackgroundScroll = (e) => {
|
|
6776
|
+
const target = e.target;
|
|
6777
|
+
if (target instanceof Element && target.closest('[data-ohw-link-modal-root], [data-slot="dialog-overlay"]')) {
|
|
6778
|
+
return;
|
|
6779
|
+
}
|
|
6780
|
+
e.preventDefault();
|
|
6781
|
+
};
|
|
6782
|
+
const scrollOpts = { passive: false, capture: true };
|
|
6783
|
+
document.addEventListener("wheel", preventBackgroundScroll, scrollOpts);
|
|
6784
|
+
document.addEventListener("touchmove", preventBackgroundScroll, scrollOpts);
|
|
6785
|
+
return () => {
|
|
6786
|
+
postToParent({ type: "ow:link-modal-lock", locked: false });
|
|
6787
|
+
html.style.overflow = prevHtmlOverflow;
|
|
6788
|
+
body.style.overflow = prevBodyOverflow;
|
|
6789
|
+
document.removeEventListener("wheel", preventBackgroundScroll, scrollOpts);
|
|
6790
|
+
document.removeEventListener("touchmove", preventBackgroundScroll, scrollOpts);
|
|
6791
|
+
};
|
|
6792
|
+
}, [linkPopover, postToParent]);
|
|
6793
|
+
(0, import_react6.useEffect)(() => {
|
|
8258
6794
|
if (!isEditMode) return;
|
|
8259
6795
|
const useFixtures = shouldUseDevFixtures();
|
|
8260
6796
|
if (useFixtures) {
|
|
@@ -8275,17 +6811,17 @@ function OhhwellsBridge() {
|
|
|
8275
6811
|
runSectionsPrefetchRef.current(mapped);
|
|
8276
6812
|
};
|
|
8277
6813
|
window.addEventListener("message", onSitePages);
|
|
8278
|
-
if (!useFixtures)
|
|
6814
|
+
if (!useFixtures) postToParent({ type: "ow:request-site-pages" });
|
|
8279
6815
|
return () => window.removeEventListener("message", onSitePages);
|
|
8280
|
-
}, [isEditMode,
|
|
8281
|
-
(0,
|
|
6816
|
+
}, [isEditMode, postToParent]);
|
|
6817
|
+
(0, import_react6.useEffect)(() => {
|
|
8282
6818
|
if (!isEditMode || shouldUseDevFixtures()) return;
|
|
8283
6819
|
void loadAllSectionsManifest().then((manifest) => {
|
|
8284
6820
|
if (Object.keys(manifest).length === 0) return;
|
|
8285
6821
|
setSectionsByPath((prev) => ({ ...manifest, ...prev }));
|
|
8286
6822
|
});
|
|
8287
6823
|
}, [isEditMode]);
|
|
8288
|
-
(0,
|
|
6824
|
+
(0, import_react6.useEffect)(() => {
|
|
8289
6825
|
const update = () => {
|
|
8290
6826
|
const el = activeElRef.current ?? selectedElRef.current;
|
|
8291
6827
|
if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
@@ -8309,10 +6845,10 @@ function OhhwellsBridge() {
|
|
|
8309
6845
|
vvp.removeEventListener("resize", update);
|
|
8310
6846
|
};
|
|
8311
6847
|
}, []);
|
|
8312
|
-
const refreshStateRules = (0,
|
|
6848
|
+
const refreshStateRules = (0, import_react6.useCallback)(() => {
|
|
8313
6849
|
editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
|
|
8314
6850
|
}, []);
|
|
8315
|
-
const processConfigRequest = (0,
|
|
6851
|
+
const processConfigRequest = (0, import_react6.useCallback)((insertAfterVal) => {
|
|
8316
6852
|
const tracker = getSectionsTracker();
|
|
8317
6853
|
let entries = [];
|
|
8318
6854
|
try {
|
|
@@ -8335,7 +6871,7 @@ function OhhwellsBridge() {
|
|
|
8335
6871
|
}
|
|
8336
6872
|
window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
|
|
8337
6873
|
}, [isEditMode]);
|
|
8338
|
-
const deactivate = (0,
|
|
6874
|
+
const deactivate = (0, import_react6.useCallback)(() => {
|
|
8339
6875
|
const el = activeElRef.current;
|
|
8340
6876
|
if (!el) return;
|
|
8341
6877
|
const key = el.dataset.ohwKey;
|
|
@@ -8364,25 +6900,21 @@ function OhhwellsBridge() {
|
|
|
8364
6900
|
setMaxBadge(null);
|
|
8365
6901
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
8366
6902
|
setToolbarShowEditLink(false);
|
|
8367
|
-
|
|
8368
|
-
}, [
|
|
8369
|
-
const deselect = (0,
|
|
6903
|
+
postToParent({ type: "ow:exit-edit" });
|
|
6904
|
+
}, [postToParent]);
|
|
6905
|
+
const deselect = (0, import_react6.useCallback)(() => {
|
|
8370
6906
|
selectedElRef.current = null;
|
|
8371
6907
|
setReorderHrefKey(null);
|
|
8372
6908
|
setReorderDragDisabled(false);
|
|
8373
|
-
setIsFooterFrameSelection(false);
|
|
8374
6909
|
siblingHintElRef.current = null;
|
|
8375
6910
|
setSiblingHintRect(null);
|
|
8376
|
-
setSiblingHintRects([]);
|
|
8377
6911
|
setIsItemDragging(false);
|
|
8378
|
-
hoveredNavContainerRef.current = null;
|
|
8379
|
-
setHoveredNavContainerRect(null);
|
|
8380
6912
|
if (!activeElRef.current) {
|
|
8381
6913
|
setToolbarRect(null);
|
|
8382
6914
|
setToolbarVariant("none");
|
|
8383
6915
|
}
|
|
8384
6916
|
}, []);
|
|
8385
|
-
const reselectNavigationItem = (0,
|
|
6917
|
+
const reselectNavigationItem = (0, import_react6.useCallback)((navAnchor) => {
|
|
8386
6918
|
selectedElRef.current = navAnchor;
|
|
8387
6919
|
const { key, disabled } = getNavigationItemReorderState(navAnchor);
|
|
8388
6920
|
setReorderHrefKey(key);
|
|
@@ -8392,7 +6924,7 @@ function OhhwellsBridge() {
|
|
|
8392
6924
|
setToolbarShowEditLink(false);
|
|
8393
6925
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
8394
6926
|
}, []);
|
|
8395
|
-
const commitNavigationTextEdit = (0,
|
|
6927
|
+
const commitNavigationTextEdit = (0, import_react6.useCallback)((navAnchor) => {
|
|
8396
6928
|
const el = activeElRef.current;
|
|
8397
6929
|
if (!el) return;
|
|
8398
6930
|
const key = el.dataset.ohwKey;
|
|
@@ -8405,9 +6937,9 @@ function OhhwellsBridge() {
|
|
|
8405
6937
|
const html = sanitizeHtml(el.innerHTML);
|
|
8406
6938
|
const original = originalContentRef.current ?? "";
|
|
8407
6939
|
if (html !== sanitizeHtml(original)) {
|
|
8408
|
-
|
|
6940
|
+
postToParent({ type: "ow:change", nodes: [{ key, text: html }] });
|
|
8409
6941
|
const h = document.documentElement.scrollHeight;
|
|
8410
|
-
if (h > 50)
|
|
6942
|
+
if (h > 50) postToParent({ type: "ow:height", height: h });
|
|
8411
6943
|
}
|
|
8412
6944
|
}
|
|
8413
6945
|
el.removeAttribute("contenteditable");
|
|
@@ -8415,366 +6947,81 @@ function OhhwellsBridge() {
|
|
|
8415
6947
|
setMaxBadge(null);
|
|
8416
6948
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
8417
6949
|
setToolbarShowEditLink(false);
|
|
8418
|
-
|
|
6950
|
+
postToParent({ type: "ow:exit-edit" });
|
|
8419
6951
|
reselectNavigationItem(navAnchor);
|
|
8420
|
-
}, [
|
|
8421
|
-
const
|
|
8422
|
-
const items = listNavbarItems();
|
|
8423
|
-
addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
|
|
8424
|
-
deselectRef.current();
|
|
8425
|
-
deactivateRef.current();
|
|
8426
|
-
bumpLinkPopoverGrace();
|
|
8427
|
-
setLinkPopover({
|
|
8428
|
-
key: "__add-nav__",
|
|
8429
|
-
mode: "create",
|
|
8430
|
-
intent: "add-nav"
|
|
8431
|
-
});
|
|
8432
|
-
}, []);
|
|
8433
|
-
const clearFooterDragVisuals = (0, import_react9.useCallback)(() => {
|
|
8434
|
-
footerDragRef.current = null;
|
|
8435
|
-
setSiblingHintRects([]);
|
|
8436
|
-
setFooterDropSlots([]);
|
|
8437
|
-
setActiveFooterDropIndex(null);
|
|
8438
|
-
setDraggedItemRect(null);
|
|
8439
|
-
setIsItemDragging(false);
|
|
8440
|
-
unlockFooterDragInteraction();
|
|
8441
|
-
}, []);
|
|
8442
|
-
const refreshFooterDragVisuals = (0, import_react9.useCallback)((session, activeSlot, clientX, clientY) => {
|
|
8443
|
-
const dragged = session.draggedEl;
|
|
8444
|
-
setDraggedItemRect(dragged.getBoundingClientRect());
|
|
8445
|
-
if (typeof clientX === "number" && typeof clientY === "number") {
|
|
8446
|
-
session.lastClientX = clientX;
|
|
8447
|
-
session.lastClientY = clientY;
|
|
8448
|
-
}
|
|
8449
|
-
session.activeSlot = activeSlot;
|
|
8450
|
-
if (session.kind === "link") {
|
|
8451
|
-
const columns2 = listFooterColumns();
|
|
8452
|
-
const focusCols = /* @__PURE__ */ new Set([session.sourceColumnIndex]);
|
|
8453
|
-
if (activeSlot) focusCols.add(activeSlot.columnIndex);
|
|
8454
|
-
const siblingRects = [];
|
|
8455
|
-
columns2.forEach((col, i) => {
|
|
8456
|
-
if (!focusCols.has(i)) return;
|
|
8457
|
-
for (const link of listFooterLinksInColumn(col)) {
|
|
8458
|
-
if (link === dragged) continue;
|
|
8459
|
-
siblingRects.push(link.getBoundingClientRect());
|
|
8460
|
-
}
|
|
8461
|
-
});
|
|
8462
|
-
setSiblingHintRects(siblingRects);
|
|
8463
|
-
const slots2 = [];
|
|
8464
|
-
columns2.forEach((col, i) => {
|
|
8465
|
-
slots2.push(...buildLinkDropSlots(col, i));
|
|
8466
|
-
});
|
|
8467
|
-
setFooterDropSlots(slots2);
|
|
8468
|
-
const activeIdx2 = activeSlot ? slots2.findIndex((s) => s.columnIndex === activeSlot.columnIndex && s.insertIndex === activeSlot.insertIndex) : -1;
|
|
8469
|
-
setActiveFooterDropIndex(activeIdx2 >= 0 ? activeIdx2 : null);
|
|
8470
|
-
return;
|
|
8471
|
-
}
|
|
8472
|
-
const columns = listFooterColumns();
|
|
8473
|
-
setSiblingHintRects(columns.filter((col) => col !== dragged).map((col) => col.getBoundingClientRect()));
|
|
8474
|
-
const slots = buildColumnDropSlots();
|
|
8475
|
-
setFooterDropSlots(slots);
|
|
8476
|
-
const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
|
|
8477
|
-
setActiveFooterDropIndex(activeIdx >= 0 ? activeIdx : null);
|
|
8478
|
-
}, []);
|
|
8479
|
-
const refreshFooterDragVisualsRef = (0, import_react9.useRef)(refreshFooterDragVisuals);
|
|
8480
|
-
refreshFooterDragVisualsRef.current = refreshFooterDragVisuals;
|
|
8481
|
-
const commitFooterDragRef = (0, import_react9.useRef)(() => {
|
|
8482
|
-
});
|
|
8483
|
-
const beginFooterDragRef = (0, import_react9.useRef)(() => {
|
|
8484
|
-
});
|
|
8485
|
-
const beginFooterDrag = (0, import_react9.useCallback)(
|
|
8486
|
-
(session) => {
|
|
8487
|
-
const rect = session.draggedEl.getBoundingClientRect();
|
|
8488
|
-
session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
|
|
8489
|
-
session.lastClientY = session.lastClientY || rect.top + rect.height / 2;
|
|
8490
|
-
session.activeSlot = session.activeSlot ?? null;
|
|
8491
|
-
footerDragRef.current = session;
|
|
8492
|
-
setIsItemDragging(true);
|
|
8493
|
-
lockFooterDuringDrag();
|
|
8494
|
-
siblingHintElRef.current = null;
|
|
8495
|
-
setSiblingHintRect(null);
|
|
8496
|
-
if (session.wasSelected && selectedElRef.current === session.draggedEl) {
|
|
8497
|
-
setToolbarRect(rect);
|
|
8498
|
-
}
|
|
8499
|
-
const initialSlot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
|
|
8500
|
-
refreshFooterDragVisuals(session, initialSlot, session.lastClientX, session.lastClientY);
|
|
8501
|
-
},
|
|
8502
|
-
[refreshFooterDragVisuals]
|
|
8503
|
-
);
|
|
8504
|
-
beginFooterDragRef.current = beginFooterDrag;
|
|
8505
|
-
const commitFooterDrag = (0, import_react9.useCallback)(
|
|
8506
|
-
(clientX, clientY) => {
|
|
8507
|
-
const session = footerDragRef.current;
|
|
8508
|
-
if (!session) {
|
|
8509
|
-
clearFooterDragVisuals();
|
|
8510
|
-
return;
|
|
8511
|
-
}
|
|
8512
|
-
const x = typeof clientX === "number" && (clientX !== 0 || clientY !== 0) ? clientX : session.lastClientX;
|
|
8513
|
-
const y = typeof clientY === "number" && (clientX !== 0 || clientY !== 0) ? clientY : session.lastClientY;
|
|
8514
|
-
let nextOrder = null;
|
|
8515
|
-
const slot = session.activeSlot ?? (session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(x, y, session.hrefKey) : session.kind === "column" ? hitTestColumnDropSlot(x, y) : null);
|
|
8516
|
-
if (session.kind === "link" && session.hrefKey && slot) {
|
|
8517
|
-
nextOrder = planFooterLinkMove(session.hrefKey, slot.columnIndex, slot.insertIndex);
|
|
8518
|
-
} else if (session.kind === "column" && slot) {
|
|
8519
|
-
nextOrder = planFooterColumnMove(session.sourceColumnIndex, slot.insertIndex);
|
|
8520
|
-
}
|
|
8521
|
-
const wasSelected = session.wasSelected;
|
|
8522
|
-
const draggedEl = session.draggedEl;
|
|
8523
|
-
const hrefKey = session.hrefKey;
|
|
8524
|
-
let movedColumnIndex = null;
|
|
8525
|
-
if (session.kind === "column" && slot && nextOrder) {
|
|
8526
|
-
let adjusted = slot.insertIndex;
|
|
8527
|
-
if (session.sourceColumnIndex < slot.insertIndex) adjusted -= 1;
|
|
8528
|
-
movedColumnIndex = Math.max(0, Math.min(adjusted, nextOrder.length - 1));
|
|
8529
|
-
}
|
|
8530
|
-
clearFooterDragVisuals();
|
|
8531
|
-
if (nextOrder) {
|
|
8532
|
-
const orderJson = JSON.stringify(nextOrder);
|
|
8533
|
-
editContentRef.current = {
|
|
8534
|
-
...editContentRef.current,
|
|
8535
|
-
[FOOTER_ORDER_KEY]: orderJson
|
|
8536
|
-
};
|
|
8537
|
-
applyFooterOrder(nextOrder);
|
|
8538
|
-
document.querySelectorAll("footer [data-ohw-href-key]").forEach(disableNativeHrefDrag);
|
|
8539
|
-
requestAnimationFrame(() => {
|
|
8540
|
-
if (editContentRef.current[FOOTER_ORDER_KEY] === orderJson) {
|
|
8541
|
-
applyFooterOrder(nextOrder);
|
|
8542
|
-
document.querySelectorAll("footer [data-ohw-href-key]").forEach(disableNativeHrefDrag);
|
|
8543
|
-
}
|
|
8544
|
-
});
|
|
8545
|
-
postToParentRef.current({
|
|
8546
|
-
type: "ow:change",
|
|
8547
|
-
nodes: [{ key: FOOTER_ORDER_KEY, text: orderJson }]
|
|
8548
|
-
});
|
|
8549
|
-
}
|
|
8550
|
-
const still = (hrefKey ? document.querySelector(`footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`) : null) ?? (movedColumnIndex !== null ? listFooterColumns()[movedColumnIndex] ?? null : null) ?? (document.body.contains(draggedEl) ? draggedEl : null);
|
|
8551
|
-
if (still && isNavigationItem(still)) {
|
|
8552
|
-
selectRef.current(still);
|
|
8553
|
-
} else if (still && isNavigationContainer(still)) {
|
|
8554
|
-
selectFrameRef.current(still);
|
|
8555
|
-
} else if (wasSelected) {
|
|
8556
|
-
deselectRef.current();
|
|
8557
|
-
}
|
|
8558
|
-
},
|
|
8559
|
-
[clearFooterDragVisuals]
|
|
8560
|
-
);
|
|
8561
|
-
commitFooterDragRef.current = commitFooterDrag;
|
|
8562
|
-
const startFooterLinkDrag = (0, import_react9.useCallback)(
|
|
8563
|
-
(anchor, clientX, clientY, wasSelected) => {
|
|
8564
|
-
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
8565
|
-
if (!hrefKey || !isFooterHrefKey(hrefKey)) return false;
|
|
8566
|
-
const column = findFooterColumnForLink(anchor);
|
|
8567
|
-
const columns = listFooterColumns();
|
|
8568
|
-
beginFooterDrag({
|
|
8569
|
-
kind: "link",
|
|
8570
|
-
hrefKey,
|
|
8571
|
-
columnEl: column,
|
|
8572
|
-
sourceColumnIndex: column ? columns.indexOf(column) : 0,
|
|
8573
|
-
wasSelected,
|
|
8574
|
-
draggedEl: anchor,
|
|
8575
|
-
lastClientX: clientX,
|
|
8576
|
-
lastClientY: clientY,
|
|
8577
|
-
activeSlot: null
|
|
8578
|
-
});
|
|
8579
|
-
return true;
|
|
8580
|
-
},
|
|
8581
|
-
[beginFooterDrag]
|
|
8582
|
-
);
|
|
8583
|
-
const startFooterColumnDrag = (0, import_react9.useCallback)(
|
|
8584
|
-
(columnEl, clientX, clientY, wasSelected) => {
|
|
8585
|
-
const columns = listFooterColumns();
|
|
8586
|
-
const idx = columns.indexOf(columnEl);
|
|
8587
|
-
if (idx < 0) return false;
|
|
8588
|
-
beginFooterDrag({
|
|
8589
|
-
kind: "column",
|
|
8590
|
-
hrefKey: null,
|
|
8591
|
-
columnEl,
|
|
8592
|
-
sourceColumnIndex: idx,
|
|
8593
|
-
wasSelected,
|
|
8594
|
-
draggedEl: columnEl,
|
|
8595
|
-
lastClientX: clientX,
|
|
8596
|
-
lastClientY: clientY,
|
|
8597
|
-
activeSlot: null
|
|
8598
|
-
});
|
|
8599
|
-
return true;
|
|
8600
|
-
},
|
|
8601
|
-
[beginFooterDrag]
|
|
8602
|
-
);
|
|
8603
|
-
const handleItemDragStart = (0, import_react9.useCallback)(
|
|
8604
|
-
(e) => {
|
|
8605
|
-
const selected = selectedElRef.current;
|
|
8606
|
-
if (!selected) {
|
|
8607
|
-
setIsItemDragging(true);
|
|
8608
|
-
return;
|
|
8609
|
-
}
|
|
8610
|
-
const clientX = e?.clientX ?? selected.getBoundingClientRect().left + 8;
|
|
8611
|
-
const clientY = e?.clientY ?? selected.getBoundingClientRect().top + 8;
|
|
8612
|
-
if (startFooterLinkDrag(selected, clientX, clientY, true)) return;
|
|
8613
|
-
if (selected.hasAttribute("data-ohw-footer-col") || isInferredFooterGroup(selected) && selected.closest("footer")) {
|
|
8614
|
-
if (startFooterColumnDrag(selected, clientX, clientY, true)) return;
|
|
8615
|
-
}
|
|
8616
|
-
siblingHintElRef.current = null;
|
|
8617
|
-
setSiblingHintRect(null);
|
|
8618
|
-
setIsItemDragging(true);
|
|
8619
|
-
},
|
|
8620
|
-
[startFooterColumnDrag, startFooterLinkDrag]
|
|
8621
|
-
);
|
|
8622
|
-
const handleItemDragEnd = (0, import_react9.useCallback)(
|
|
8623
|
-
(e) => {
|
|
8624
|
-
if (footerDragRef.current) {
|
|
8625
|
-
const x = e?.clientX;
|
|
8626
|
-
const y = e?.clientY;
|
|
8627
|
-
if (typeof x === "number" && typeof y === "number" && (x !== 0 || y !== 0)) {
|
|
8628
|
-
commitFooterDrag(x, y);
|
|
8629
|
-
} else {
|
|
8630
|
-
commitFooterDrag();
|
|
8631
|
-
}
|
|
8632
|
-
return;
|
|
8633
|
-
}
|
|
8634
|
-
setIsItemDragging(false);
|
|
8635
|
-
},
|
|
8636
|
-
[commitFooterDrag]
|
|
8637
|
-
);
|
|
8638
|
-
const handleItemChromePointerDown = (0, import_react9.useCallback)((e) => {
|
|
8639
|
-
if (e.button !== 0) return;
|
|
6952
|
+
}, [postToParent, reselectNavigationItem]);
|
|
6953
|
+
const handleAddNavigationItem = (0, import_react6.useCallback)(() => {
|
|
8640
6954
|
const selected = selectedElRef.current;
|
|
8641
6955
|
if (!selected) return;
|
|
8642
|
-
|
|
8643
|
-
|
|
8644
|
-
|
|
8645
|
-
footerPointerDragRef.current = {
|
|
8646
|
-
el: selected,
|
|
8647
|
-
kind: "link",
|
|
8648
|
-
startX: e.clientX,
|
|
8649
|
-
startY: e.clientY,
|
|
8650
|
-
pointerId: e.pointerId,
|
|
8651
|
-
wasSelected: true,
|
|
8652
|
-
started: false
|
|
8653
|
-
};
|
|
8654
|
-
return;
|
|
8655
|
-
}
|
|
8656
|
-
if (selected.hasAttribute("data-ohw-footer-col") || isInferredFooterGroup(selected) && selected.closest("footer")) {
|
|
8657
|
-
footerPointerDragRef.current = {
|
|
8658
|
-
el: selected,
|
|
8659
|
-
kind: "column",
|
|
8660
|
-
startX: e.clientX,
|
|
8661
|
-
startY: e.clientY,
|
|
8662
|
-
pointerId: e.pointerId,
|
|
8663
|
-
wasSelected: true,
|
|
8664
|
-
started: false
|
|
8665
|
-
};
|
|
8666
|
-
}
|
|
6956
|
+
const target = getNavigationItemAddHintTarget(selected);
|
|
6957
|
+
siblingHintElRef.current = target;
|
|
6958
|
+
setSiblingHintRect(target.getBoundingClientRect());
|
|
8667
6959
|
}, []);
|
|
8668
|
-
const
|
|
8669
|
-
|
|
8670
|
-
|
|
8671
|
-
|
|
8672
|
-
|
|
8673
|
-
|
|
8674
|
-
|
|
8675
|
-
const editable = selected.querySelector('[data-ohw-editable="text"]') ?? selected.querySelector("[data-ohw-editable]");
|
|
8676
|
-
if (!editable) return;
|
|
8677
|
-
activateRef.current(editable, { caretX: clientX, caretY: clientY });
|
|
6960
|
+
const handleItemDragStart = (0, import_react6.useCallback)(() => {
|
|
6961
|
+
siblingHintElRef.current = null;
|
|
6962
|
+
setSiblingHintRect(null);
|
|
6963
|
+
setIsItemDragging(true);
|
|
6964
|
+
}, []);
|
|
6965
|
+
const handleItemDragEnd = (0, import_react6.useCallback)(() => {
|
|
6966
|
+
setIsItemDragging(false);
|
|
8678
6967
|
}, []);
|
|
8679
6968
|
reselectNavigationItemRef.current = reselectNavigationItem;
|
|
8680
6969
|
commitNavigationTextEditRef.current = commitNavigationTextEdit;
|
|
8681
|
-
const select = (0,
|
|
8682
|
-
(anchor)
|
|
8683
|
-
|
|
8684
|
-
|
|
8685
|
-
|
|
8686
|
-
|
|
8687
|
-
|
|
8688
|
-
|
|
8689
|
-
|
|
8690
|
-
|
|
8691
|
-
|
|
8692
|
-
|
|
8693
|
-
|
|
8694
|
-
|
|
8695
|
-
|
|
8696
|
-
|
|
8697
|
-
|
|
8698
|
-
|
|
8699
|
-
|
|
8700
|
-
|
|
8701
|
-
|
|
8702
|
-
|
|
8703
|
-
|
|
8704
|
-
|
|
8705
|
-
|
|
8706
|
-
|
|
8707
|
-
(
|
|
8708
|
-
|
|
8709
|
-
|
|
8710
|
-
|
|
8711
|
-
|
|
8712
|
-
|
|
8713
|
-
|
|
8714
|
-
|
|
8715
|
-
|
|
8716
|
-
|
|
8717
|
-
|
|
8718
|
-
|
|
8719
|
-
|
|
8720
|
-
isFooterColumn ? listFooterColumns().filter((column) => column !== el).map((column) => column.getBoundingClientRect()) : []
|
|
8721
|
-
);
|
|
8722
|
-
setIsItemDragging(false);
|
|
6970
|
+
const select = (0, import_react6.useCallback)((anchor) => {
|
|
6971
|
+
if (!isNavigationItem(anchor)) return;
|
|
6972
|
+
if (activeElRef.current) deactivate();
|
|
6973
|
+
selectedElRef.current = anchor;
|
|
6974
|
+
clearHrefKeyHover(anchor);
|
|
6975
|
+
setHoveredItemRect(null);
|
|
6976
|
+
hoveredItemElRef.current = null;
|
|
6977
|
+
siblingHintElRef.current = null;
|
|
6978
|
+
setSiblingHintRect(null);
|
|
6979
|
+
setIsItemDragging(false);
|
|
6980
|
+
const { key, disabled } = getNavigationItemReorderState(anchor);
|
|
6981
|
+
setReorderHrefKey(key);
|
|
6982
|
+
setReorderDragDisabled(disabled);
|
|
6983
|
+
setToolbarVariant("link-action");
|
|
6984
|
+
setToolbarRect(anchor.getBoundingClientRect());
|
|
6985
|
+
setToolbarShowEditLink(false);
|
|
6986
|
+
setActiveCommands(/* @__PURE__ */ new Set());
|
|
6987
|
+
}, [deactivate]);
|
|
6988
|
+
const activate = (0, import_react6.useCallback)((el) => {
|
|
6989
|
+
if (activeElRef.current === el) return;
|
|
6990
|
+
selectedElRef.current = null;
|
|
6991
|
+
deactivate();
|
|
6992
|
+
if (hoveredImageRef.current) {
|
|
6993
|
+
hoveredImageRef.current = null;
|
|
6994
|
+
setMediaHover(null);
|
|
6995
|
+
}
|
|
6996
|
+
setToolbarVariant("rich-text");
|
|
6997
|
+
siblingHintElRef.current = null;
|
|
6998
|
+
setSiblingHintRect(null);
|
|
6999
|
+
setIsItemDragging(false);
|
|
7000
|
+
el.setAttribute("contenteditable", "true");
|
|
7001
|
+
el.removeAttribute("data-ohw-hovered");
|
|
7002
|
+
el.closest("[data-ohw-href-key]")?.removeAttribute("data-ohw-hovered");
|
|
7003
|
+
activeElRef.current = el;
|
|
7004
|
+
originalContentRef.current = el.innerHTML;
|
|
7005
|
+
el.focus();
|
|
7006
|
+
setToolbarShowEditLink(Boolean(getHrefKeyFromElement(el)));
|
|
7007
|
+
const navAnchor = getNavigationItemAnchor(el);
|
|
7008
|
+
if (navAnchor) {
|
|
8723
7009
|
setReorderHrefKey(null);
|
|
8724
7010
|
setReorderDragDisabled(false);
|
|
8725
|
-
|
|
8726
|
-
|
|
8727
|
-
|
|
8728
|
-
|
|
8729
|
-
|
|
8730
|
-
|
|
8731
|
-
|
|
8732
|
-
|
|
8733
|
-
|
|
8734
|
-
(el, options) => {
|
|
8735
|
-
if (activeElRef.current === el) return;
|
|
8736
|
-
selectedElRef.current = null;
|
|
8737
|
-
deactivate();
|
|
8738
|
-
if (hoveredImageRef.current) {
|
|
8739
|
-
hoveredImageRef.current = null;
|
|
8740
|
-
postToParentRef.current({ type: "ow:image-unhover" });
|
|
8741
|
-
}
|
|
8742
|
-
setToolbarVariant("rich-text");
|
|
8743
|
-
siblingHintElRef.current = null;
|
|
8744
|
-
setSiblingHintRect(null);
|
|
8745
|
-
setSiblingHintRects([]);
|
|
8746
|
-
setIsItemDragging(false);
|
|
8747
|
-
el.setAttribute("contenteditable", "true");
|
|
8748
|
-
el.removeAttribute("data-ohw-hovered");
|
|
8749
|
-
el.closest("[data-ohw-href-key]")?.removeAttribute("data-ohw-hovered");
|
|
8750
|
-
activeElRef.current = el;
|
|
8751
|
-
originalContentRef.current = el.innerHTML;
|
|
8752
|
-
el.focus();
|
|
8753
|
-
if (options?.caretX !== void 0 && options?.caretY !== void 0) {
|
|
8754
|
-
placeCaretAtPoint(el, options.caretX, options.caretY);
|
|
8755
|
-
}
|
|
8756
|
-
setToolbarShowEditLink(Boolean(getHrefKeyFromElement(el)));
|
|
8757
|
-
const navAnchor = getNavigationItemAnchor(el);
|
|
8758
|
-
if (navAnchor) {
|
|
8759
|
-
setReorderHrefKey(null);
|
|
8760
|
-
setReorderDragDisabled(false);
|
|
8761
|
-
} else {
|
|
8762
|
-
const { key: reorderKey, disabled: reorderDisabled } = getReorderHandleState(el);
|
|
8763
|
-
setReorderHrefKey(reorderKey);
|
|
8764
|
-
setReorderDragDisabled(reorderDisabled);
|
|
8765
|
-
}
|
|
8766
|
-
setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
8767
|
-
postToParent2({ type: "ow:enter-edit", key: el.dataset.ohwKey });
|
|
8768
|
-
requestAnimationFrame(() => refreshActiveCommandsRef.current());
|
|
8769
|
-
},
|
|
8770
|
-
[deactivate, postToParent2]
|
|
8771
|
-
);
|
|
7011
|
+
} else {
|
|
7012
|
+
const { key: reorderKey, disabled: reorderDisabled } = getReorderHandleState(el);
|
|
7013
|
+
setReorderHrefKey(reorderKey);
|
|
7014
|
+
setReorderDragDisabled(reorderDisabled);
|
|
7015
|
+
}
|
|
7016
|
+
setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
7017
|
+
postToParent({ type: "ow:enter-edit", key: el.dataset.ohwKey });
|
|
7018
|
+
requestAnimationFrame(() => refreshActiveCommandsRef.current());
|
|
7019
|
+
}, [deactivate, postToParent]);
|
|
8772
7020
|
activateRef.current = activate;
|
|
8773
7021
|
deactivateRef.current = deactivate;
|
|
8774
7022
|
selectRef.current = select;
|
|
8775
|
-
selectFrameRef.current = selectFrame;
|
|
8776
7023
|
deselectRef.current = deselect;
|
|
8777
|
-
(0,
|
|
7024
|
+
(0, import_react6.useLayoutEffect)(() => {
|
|
8778
7025
|
if (!subdomain || isEditMode) {
|
|
8779
7026
|
setFetchState("done");
|
|
8780
7027
|
return;
|
|
@@ -8784,7 +7031,6 @@ function OhhwellsBridge() {
|
|
|
8784
7031
|
for (const [key, val] of Object.entries(content)) {
|
|
8785
7032
|
if (key === "__ohw_sections") continue;
|
|
8786
7033
|
if (applyVideoSettingNode(key, val)) continue;
|
|
8787
|
-
if (applyCarouselNode(key, val)) continue;
|
|
8788
7034
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
8789
7035
|
if (el.dataset.ohwEditable === "image") {
|
|
8790
7036
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
@@ -8815,8 +7061,6 @@ function OhhwellsBridge() {
|
|
|
8815
7061
|
});
|
|
8816
7062
|
applyLinkByKey(key, val);
|
|
8817
7063
|
}
|
|
8818
|
-
reconcileNavbarItemsFromContent(content);
|
|
8819
|
-
reconcileFooterOrderFromContent(content);
|
|
8820
7064
|
enforceLinkHrefs();
|
|
8821
7065
|
initSectionsFromContent(content, true);
|
|
8822
7066
|
sectionsLoadedRef.current = true;
|
|
@@ -8845,7 +7089,7 @@ function OhhwellsBridge() {
|
|
|
8845
7089
|
cancelled = true;
|
|
8846
7090
|
};
|
|
8847
7091
|
}, [subdomain, isEditMode]);
|
|
8848
|
-
(0,
|
|
7092
|
+
(0, import_react6.useEffect)(() => {
|
|
8849
7093
|
if (!subdomain || isEditMode) return;
|
|
8850
7094
|
let debounceTimer = null;
|
|
8851
7095
|
let observer = null;
|
|
@@ -8858,7 +7102,6 @@ function OhhwellsBridge() {
|
|
|
8858
7102
|
for (const [key, val] of Object.entries(content)) {
|
|
8859
7103
|
if (key === "__ohw_sections") continue;
|
|
8860
7104
|
if (applyVideoSettingNode(key, val)) continue;
|
|
8861
|
-
if (applyCarouselNode(key, val)) continue;
|
|
8862
7105
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
8863
7106
|
if (el.dataset.ohwEditable === "image") {
|
|
8864
7107
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
@@ -8877,8 +7120,6 @@ function OhhwellsBridge() {
|
|
|
8877
7120
|
});
|
|
8878
7121
|
applyLinkByKey(key, val);
|
|
8879
7122
|
}
|
|
8880
|
-
reconcileNavbarItemsFromContent(content);
|
|
8881
|
-
reconcileFooterOrderFromContent(content);
|
|
8882
7123
|
} finally {
|
|
8883
7124
|
observer?.observe(document.body, { childList: true, subtree: true });
|
|
8884
7125
|
}
|
|
@@ -8896,71 +7137,26 @@ function OhhwellsBridge() {
|
|
|
8896
7137
|
if (debounceTimer) clearTimeout(debounceTimer);
|
|
8897
7138
|
};
|
|
8898
7139
|
}, [subdomain, isEditMode, pathname]);
|
|
8899
|
-
(0,
|
|
7140
|
+
(0, import_react6.useLayoutEffect)(() => {
|
|
8900
7141
|
const el = document.getElementById("ohw-loader");
|
|
8901
7142
|
if (!el) return;
|
|
8902
7143
|
const visible = Boolean(subdomain) && fetchState !== "done";
|
|
8903
7144
|
el.style.display = visible ? "flex" : "none";
|
|
8904
7145
|
}, [subdomain, fetchState]);
|
|
8905
|
-
(0,
|
|
8906
|
-
|
|
8907
|
-
}, [pathname,
|
|
8908
|
-
(0,
|
|
7146
|
+
(0, import_react6.useEffect)(() => {
|
|
7147
|
+
postToParent({ type: "ow:navigation", path: pathname });
|
|
7148
|
+
}, [pathname, postToParent]);
|
|
7149
|
+
(0, import_react6.useEffect)(() => {
|
|
8909
7150
|
if (!isEditMode) return;
|
|
8910
|
-
if (linkPopoverSessionRef.current?.intent === "add-nav") return;
|
|
8911
|
-
if (document.querySelector("[data-ohw-section-picker]")) return;
|
|
8912
7151
|
setLinkPopover(null);
|
|
8913
7152
|
deselectRef.current();
|
|
8914
7153
|
deactivateRef.current();
|
|
8915
7154
|
}, [pathname, isEditMode]);
|
|
8916
|
-
(0,
|
|
8917
|
-
const contentForNav = () => {
|
|
8918
|
-
if (isEditMode) return editContentRef.current;
|
|
8919
|
-
if (!subdomain) return {};
|
|
8920
|
-
return contentCache.get(subdomain) ?? {};
|
|
8921
|
-
};
|
|
8922
|
-
let applying = false;
|
|
8923
|
-
let rafId = null;
|
|
8924
|
-
const run = () => {
|
|
8925
|
-
if (footerDragRef.current || applying) return;
|
|
8926
|
-
applying = true;
|
|
8927
|
-
try {
|
|
8928
|
-
const content = contentForNav();
|
|
8929
|
-
reconcileNavbarItemsFromContent(content);
|
|
8930
|
-
reconcileFooterOrderFromContent(content);
|
|
8931
|
-
document.querySelectorAll("footer [data-ohw-href-key]").forEach((el) => {
|
|
8932
|
-
if (isFooterHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
8933
|
-
disableNativeHrefDrag(el);
|
|
8934
|
-
}
|
|
8935
|
-
});
|
|
8936
|
-
} finally {
|
|
8937
|
-
applying = false;
|
|
8938
|
-
}
|
|
8939
|
-
};
|
|
8940
|
-
const scheduleRun = () => {
|
|
8941
|
-
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
8942
|
-
rafId = requestAnimationFrame(() => {
|
|
8943
|
-
rafId = null;
|
|
8944
|
-
run();
|
|
8945
|
-
});
|
|
8946
|
-
};
|
|
8947
|
-
run();
|
|
8948
|
-
const nav = document.querySelector("nav");
|
|
8949
|
-
const footer = document.querySelector("footer");
|
|
8950
|
-
const observer = new MutationObserver(scheduleRun);
|
|
8951
|
-
if (nav) observer.observe(nav, { childList: true, subtree: true });
|
|
8952
|
-
if (footer) observer.observe(footer, { childList: true, subtree: true });
|
|
8953
|
-
if (!nav && !footer) return;
|
|
8954
|
-
return () => {
|
|
8955
|
-
observer.disconnect();
|
|
8956
|
-
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
8957
|
-
};
|
|
8958
|
-
}, [isEditMode, pathname, subdomain, fetchState]);
|
|
8959
|
-
(0, import_react9.useEffect)(() => {
|
|
7155
|
+
(0, import_react6.useEffect)(() => {
|
|
8960
7156
|
if (!isEditMode) return;
|
|
8961
7157
|
const measure = () => {
|
|
8962
7158
|
const h = document.body.scrollHeight;
|
|
8963
|
-
if (h > 50)
|
|
7159
|
+
if (h > 50) postToParent({ type: "ow:height", height: h });
|
|
8964
7160
|
};
|
|
8965
7161
|
const t1 = setTimeout(measure, 50);
|
|
8966
7162
|
const t2 = setTimeout(measure, 500);
|
|
@@ -8979,8 +7175,8 @@ function OhhwellsBridge() {
|
|
|
8979
7175
|
if (resizeTimer) clearTimeout(resizeTimer);
|
|
8980
7176
|
window.removeEventListener("resize", handleResize);
|
|
8981
7177
|
};
|
|
8982
|
-
}, [pathname, isEditMode,
|
|
8983
|
-
(0,
|
|
7178
|
+
}, [pathname, isEditMode, postToParent]);
|
|
7179
|
+
(0, import_react6.useEffect)(() => {
|
|
8984
7180
|
if (!subdomainFromQuery || isEditMode) return;
|
|
8985
7181
|
const handleClick = (e) => {
|
|
8986
7182
|
const anchor = e.target.closest("a");
|
|
@@ -8996,7 +7192,7 @@ function OhhwellsBridge() {
|
|
|
8996
7192
|
document.addEventListener("click", handleClick, true);
|
|
8997
7193
|
return () => document.removeEventListener("click", handleClick, true);
|
|
8998
7194
|
}, [subdomainFromQuery, isEditMode, router]);
|
|
8999
|
-
(0,
|
|
7195
|
+
(0, import_react6.useEffect)(() => {
|
|
9000
7196
|
if (!isEditMode) {
|
|
9001
7197
|
editStylesRef.current?.base.remove();
|
|
9002
7198
|
editStylesRef.current?.forceHover.remove();
|
|
@@ -9019,29 +7215,6 @@ function OhhwellsBridge() {
|
|
|
9019
7215
|
[data-ohw-editable] {
|
|
9020
7216
|
display: block;
|
|
9021
7217
|
}
|
|
9022
|
-
/* Native <a> drag steals clicks \u2014 disable for edit links; reorder via press-to-drag / handle. */
|
|
9023
|
-
footer [data-ohw-href-key] {
|
|
9024
|
-
-webkit-user-drag: none !important;
|
|
9025
|
-
}
|
|
9026
|
-
footer [data-ohw-footer-col]:hover {
|
|
9027
|
-
outline: 1.5px dashed ${PRIMARY2} !important;
|
|
9028
|
-
outline-offset: 6px;
|
|
9029
|
-
border-radius: 8px;
|
|
9030
|
-
}
|
|
9031
|
-
html[data-ohw-footer-press-drag] footer,
|
|
9032
|
-
html[data-ohw-footer-press-drag] footer * {
|
|
9033
|
-
user-select: none !important;
|
|
9034
|
-
-webkit-user-select: none !important;
|
|
9035
|
-
}
|
|
9036
|
-
html[data-ohw-item-dragging] footer,
|
|
9037
|
-
html[data-ohw-item-dragging] footer * {
|
|
9038
|
-
user-select: none !important;
|
|
9039
|
-
-webkit-user-select: none !important;
|
|
9040
|
-
pointer-events: none !important;
|
|
9041
|
-
}
|
|
9042
|
-
html[data-ohw-item-dragging] {
|
|
9043
|
-
cursor: grabbing !important;
|
|
9044
|
-
}
|
|
9045
7218
|
[data-ohw-editable]:not([contenteditable]):not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]):not([data-ohw-editable="video"]) { cursor: text !important; }
|
|
9046
7219
|
[data-ohw-editable="image"], [data-ohw-editable="image"] *,
|
|
9047
7220
|
[data-ohw-editable="video"], [data-ohw-editable="video"] *,
|
|
@@ -9050,7 +7223,6 @@ function OhhwellsBridge() {
|
|
|
9050
7223
|
[data-ohw-hovered]:not([contenteditable]):not([data-ohw-href-key]) {
|
|
9051
7224
|
outline: 2px dashed ${PRIMARY2} !important;
|
|
9052
7225
|
outline-offset: 4px;
|
|
9053
|
-
border-radius: 2px;
|
|
9054
7226
|
}
|
|
9055
7227
|
[data-ohw-href-key] [data-ohw-hovered],
|
|
9056
7228
|
[data-ohw-href-key][data-ohw-hovered],
|
|
@@ -9077,7 +7249,7 @@ function OhhwellsBridge() {
|
|
|
9077
7249
|
stateViews.textContent = `
|
|
9078
7250
|
[data-ohw-state-view]:not([data-ohw-state-view="default"]) { display: none; }
|
|
9079
7251
|
[data-ohw-state-view="default"] [data-ohw-editable] { pointer-events: auto !important; }
|
|
9080
|
-
[data-ohw-state-hovered] { outline: 2px dashed ${PRIMARY2} !important; outline-offset: 4px;
|
|
7252
|
+
[data-ohw-state-hovered] { outline: 2px dashed ${PRIMARY2} !important; outline-offset: 4px; }
|
|
9081
7253
|
[data-ohw-state-hovered]:has([data-ohw-hovered]) { outline: none !important; }
|
|
9082
7254
|
`;
|
|
9083
7255
|
document.head.appendChild(base);
|
|
@@ -9087,46 +7259,12 @@ function OhhwellsBridge() {
|
|
|
9087
7259
|
}
|
|
9088
7260
|
refreshStateRules();
|
|
9089
7261
|
const handleClick = (e) => {
|
|
9090
|
-
if (suppressNextClickRef.current) {
|
|
9091
|
-
suppressNextClickRef.current = false;
|
|
9092
|
-
e.preventDefault();
|
|
9093
|
-
e.stopPropagation();
|
|
9094
|
-
return;
|
|
9095
|
-
}
|
|
9096
7262
|
const target = e.target;
|
|
9097
7263
|
if (target.closest("[data-ohw-toolbar]")) return;
|
|
9098
7264
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
9099
7265
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
9100
7266
|
if (isInsideLinkEditor(target)) return;
|
|
9101
7267
|
if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
9102
|
-
if (target.closest("[data-ohw-item-drag-surface]")) {
|
|
9103
|
-
e.preventDefault();
|
|
9104
|
-
e.stopPropagation();
|
|
9105
|
-
const selected = selectedElRef.current;
|
|
9106
|
-
if (selected && isNavigationItem(selected)) {
|
|
9107
|
-
const editable2 = selected.querySelector('[data-ohw-editable="text"]') ?? selected.querySelector("[data-ohw-editable]");
|
|
9108
|
-
if (editable2) {
|
|
9109
|
-
activateRef.current(editable2, {
|
|
9110
|
-
caretX: e.clientX,
|
|
9111
|
-
caretY: e.clientY
|
|
9112
|
-
});
|
|
9113
|
-
}
|
|
9114
|
-
} else if (selected?.hasAttribute("data-ohw-footer-col")) {
|
|
9115
|
-
const link = listFooterLinksInColumn(selected).find((el) => {
|
|
9116
|
-
const r2 = el.getBoundingClientRect();
|
|
9117
|
-
return e.clientX >= r2.left && e.clientX <= r2.right && e.clientY >= r2.top && e.clientY <= r2.bottom;
|
|
9118
|
-
});
|
|
9119
|
-
if (link) selectRef.current(link);
|
|
9120
|
-
}
|
|
9121
|
-
return;
|
|
9122
|
-
}
|
|
9123
|
-
const navFromChrome = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
|
|
9124
|
-
if (navFromChrome) {
|
|
9125
|
-
e.preventDefault();
|
|
9126
|
-
e.stopPropagation();
|
|
9127
|
-
selectFrameRef.current(navFromChrome);
|
|
9128
|
-
return;
|
|
9129
|
-
}
|
|
9130
7268
|
e.preventDefault();
|
|
9131
7269
|
e.stopPropagation();
|
|
9132
7270
|
return;
|
|
@@ -9141,8 +7279,7 @@ function OhhwellsBridge() {
|
|
|
9141
7279
|
bumpLinkPopoverGrace();
|
|
9142
7280
|
setLinkPopoverRef.current({
|
|
9143
7281
|
key: editable.dataset.ohwKey ?? "",
|
|
9144
|
-
|
|
9145
|
-
target: getLinkHref2(editable)
|
|
7282
|
+
target: getLinkHref(editable)
|
|
9146
7283
|
});
|
|
9147
7284
|
return;
|
|
9148
7285
|
}
|
|
@@ -9158,58 +7295,25 @@ function OhhwellsBridge() {
|
|
|
9158
7295
|
e.preventDefault();
|
|
9159
7296
|
e.stopPropagation();
|
|
9160
7297
|
if (selectedElRef.current === navAnchor) {
|
|
9161
|
-
|
|
9162
|
-
|
|
9163
|
-
return;
|
|
9164
|
-
}
|
|
9165
|
-
selectRef.current(navAnchor);
|
|
9166
|
-
return;
|
|
9167
|
-
}
|
|
9168
|
-
e.preventDefault();
|
|
9169
|
-
e.stopPropagation();
|
|
9170
|
-
activateRef.current(editable);
|
|
9171
|
-
return;
|
|
9172
|
-
}
|
|
9173
|
-
const hrefAnchor = getNavigationItemAnchor(target);
|
|
9174
|
-
if (hrefAnchor) {
|
|
9175
|
-
e.preventDefault();
|
|
9176
|
-
e.stopPropagation();
|
|
9177
|
-
if (selectedElRef.current === hrefAnchor) {
|
|
9178
|
-
const textEditable = hrefAnchor.querySelector('[data-ohw-editable="text"]') ?? hrefAnchor.querySelector("[data-ohw-editable]");
|
|
9179
|
-
if (textEditable) {
|
|
9180
|
-
activateRef.current(textEditable, {
|
|
9181
|
-
caretX: e.clientX,
|
|
9182
|
-
caretY: e.clientY
|
|
9183
|
-
});
|
|
7298
|
+
activateRef.current(editable);
|
|
7299
|
+
return;
|
|
9184
7300
|
}
|
|
7301
|
+
selectRef.current(navAnchor);
|
|
9185
7302
|
return;
|
|
9186
7303
|
}
|
|
9187
|
-
selectRef.current(hrefAnchor);
|
|
9188
|
-
return;
|
|
9189
|
-
}
|
|
9190
|
-
const footerColClick = target.closest("[data-ohw-footer-col]");
|
|
9191
|
-
if (footerColClick) {
|
|
9192
7304
|
e.preventDefault();
|
|
9193
7305
|
e.stopPropagation();
|
|
9194
|
-
|
|
7306
|
+
activateRef.current(editable);
|
|
9195
7307
|
return;
|
|
9196
7308
|
}
|
|
9197
|
-
const
|
|
9198
|
-
if (
|
|
7309
|
+
const hrefAnchor = getNavigationItemAnchor(target);
|
|
7310
|
+
if (hrefAnchor) {
|
|
9199
7311
|
e.preventDefault();
|
|
9200
7312
|
e.stopPropagation();
|
|
9201
|
-
|
|
7313
|
+
if (selectedElRef.current === hrefAnchor) return;
|
|
7314
|
+
selectRef.current(hrefAnchor);
|
|
9202
7315
|
return;
|
|
9203
7316
|
}
|
|
9204
|
-
const selectedContainer = selectedElRef.current;
|
|
9205
|
-
if (selectedContainer && isNavigationContainer(selectedContainer)) {
|
|
9206
|
-
const navItem = getNavigationItemAnchor(target);
|
|
9207
|
-
if (!navItem && (selectedContainer === target || selectedContainer.contains(target))) {
|
|
9208
|
-
e.preventDefault();
|
|
9209
|
-
e.stopPropagation();
|
|
9210
|
-
return;
|
|
9211
|
-
}
|
|
9212
|
-
}
|
|
9213
7317
|
if (activeElRef.current) {
|
|
9214
7318
|
const sel = window.getSelection();
|
|
9215
7319
|
if (sel && !sel.isCollapsed) {
|
|
@@ -9235,58 +7339,10 @@ function OhhwellsBridge() {
|
|
|
9235
7339
|
deselectRef.current();
|
|
9236
7340
|
deactivateRef.current();
|
|
9237
7341
|
};
|
|
9238
|
-
const handleDblClick = (e) => {
|
|
9239
|
-
const target = e.target;
|
|
9240
|
-
if (target.closest("[data-ohw-toolbar]")) return;
|
|
9241
|
-
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
9242
|
-
if (target.closest("[data-ohw-max-badge]")) return;
|
|
9243
|
-
if (isInsideLinkEditor(target)) return;
|
|
9244
|
-
if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
9245
|
-
return;
|
|
9246
|
-
}
|
|
9247
|
-
const navLabel = getNavigationLabelEditable(target);
|
|
9248
|
-
if (!navLabel) return;
|
|
9249
|
-
const { editable } = navLabel;
|
|
9250
|
-
e.preventDefault();
|
|
9251
|
-
e.stopPropagation();
|
|
9252
|
-
if (activeElRef.current !== editable) {
|
|
9253
|
-
activateRef.current(editable);
|
|
9254
|
-
}
|
|
9255
|
-
requestAnimationFrame(() => {
|
|
9256
|
-
selectAllTextInEditable(editable);
|
|
9257
|
-
refreshActiveCommandsRef.current();
|
|
9258
|
-
});
|
|
9259
|
-
};
|
|
9260
7342
|
const handleMouseOver = (e) => {
|
|
9261
|
-
if (document.documentElement.hasAttribute("data-ohw-section-picking")) return;
|
|
9262
7343
|
const target = e.target;
|
|
9263
|
-
if (toolbarVariantRef.current !== "select-frame") {
|
|
9264
|
-
const navContainer = target.closest("[data-ohw-nav-container]");
|
|
9265
|
-
if (navContainer && !getNavigationItemAnchor(target)) {
|
|
9266
|
-
hoveredNavContainerRef.current = navContainer;
|
|
9267
|
-
setHoveredNavContainerRect(navContainer.getBoundingClientRect());
|
|
9268
|
-
hoveredItemElRef.current = null;
|
|
9269
|
-
setHoveredItemRect(null);
|
|
9270
|
-
return;
|
|
9271
|
-
}
|
|
9272
|
-
if (!target.closest("[data-ohw-nav-container]")) {
|
|
9273
|
-
hoveredNavContainerRef.current = null;
|
|
9274
|
-
setHoveredNavContainerRect(null);
|
|
9275
|
-
}
|
|
9276
|
-
}
|
|
9277
|
-
const footerCol = target.closest("[data-ohw-footer-col]");
|
|
9278
|
-
if (footerCol) {
|
|
9279
|
-
hoveredNavContainerRef.current = null;
|
|
9280
|
-
setHoveredNavContainerRect(null);
|
|
9281
|
-
if (selectedElRef.current === footerCol) return;
|
|
9282
|
-
hoveredItemElRef.current = footerCol;
|
|
9283
|
-
setHoveredItemRect(footerCol.getBoundingClientRect());
|
|
9284
|
-
return;
|
|
9285
|
-
}
|
|
9286
7344
|
const navAnchor = getNavigationItemAnchor(target);
|
|
9287
7345
|
if (navAnchor) {
|
|
9288
|
-
hoveredNavContainerRef.current = null;
|
|
9289
|
-
setHoveredNavContainerRect(null);
|
|
9290
7346
|
const selected2 = selectedElRef.current;
|
|
9291
7347
|
if (selected2 === navAnchor || selected2?.contains(navAnchor)) return;
|
|
9292
7348
|
clearHrefKeyHover(navAnchor);
|
|
@@ -9311,23 +7367,6 @@ function OhhwellsBridge() {
|
|
|
9311
7367
|
};
|
|
9312
7368
|
const handleMouseOut = (e) => {
|
|
9313
7369
|
const target = e.target;
|
|
9314
|
-
if (target.closest("[data-ohw-nav-container]")) {
|
|
9315
|
-
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
9316
|
-
if (related2?.closest("[data-ohw-nav-container], [data-ohw-navbar-container-chrome], [data-ohw-navbar-add-button]")) {
|
|
9317
|
-
return;
|
|
9318
|
-
}
|
|
9319
|
-
hoveredNavContainerRef.current = null;
|
|
9320
|
-
setHoveredNavContainerRect(null);
|
|
9321
|
-
}
|
|
9322
|
-
const footerCol = target.closest("[data-ohw-footer-col]");
|
|
9323
|
-
if (footerCol && hoveredItemElRef.current === footerCol) {
|
|
9324
|
-
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
9325
|
-
if (related2?.closest("[data-ohw-drag-handle-container], [data-ohw-item-interaction]")) return;
|
|
9326
|
-
if (related2?.closest("[data-ohw-footer-col]") === footerCol) return;
|
|
9327
|
-
hoveredItemElRef.current = null;
|
|
9328
|
-
setHoveredItemRect(null);
|
|
9329
|
-
return;
|
|
9330
|
-
}
|
|
9331
7370
|
const navAnchor = getNavigationItemAnchor(target);
|
|
9332
7371
|
if (navAnchor) {
|
|
9333
7372
|
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
@@ -9439,97 +7478,69 @@ function OhhwellsBridge() {
|
|
|
9439
7478
|
const stickyPad = 48;
|
|
9440
7479
|
const withinPad = x >= pr.left - stickyPad && x <= pr.left + pr.width + stickyPad && y >= pr.top - stickyPad && y <= pr.top + pr.height + stickyPad;
|
|
9441
7480
|
if (withinPad) {
|
|
9442
|
-
|
|
7481
|
+
if (smallest !== pinned && candidatePool.includes(smallest)) {
|
|
9443
7482
|
const sr = getVisibleRect(smallest);
|
|
9444
|
-
const
|
|
9445
|
-
|
|
9446
|
-
}
|
|
9447
|
-
|
|
7483
|
+
const overOther = x >= sr.left && x <= sr.left + sr.width && y >= sr.top && y <= sr.top + sr.height;
|
|
7484
|
+
if (overOther) return smallest;
|
|
7485
|
+
}
|
|
7486
|
+
return pinned;
|
|
9448
7487
|
}
|
|
9449
7488
|
}
|
|
9450
7489
|
return smallest;
|
|
9451
7490
|
};
|
|
9452
|
-
const dismissImageHover = () => {
|
|
9453
|
-
if (hoveredImageRef.current) {
|
|
9454
|
-
hoveredImageRef.current = null;
|
|
9455
|
-
hoveredImageHasTextOverlapRef.current = false;
|
|
9456
|
-
resumeAnimTracks();
|
|
9457
|
-
postToParentRef.current({ type: "ow:image-unhover" });
|
|
9458
|
-
}
|
|
9459
|
-
clearImageHover();
|
|
9460
|
-
};
|
|
9461
|
-
const probeNavigationHoverAt = (x, y) => {
|
|
9462
|
-
if (toolbarVariantRef.current === "select-frame") {
|
|
9463
|
-
hoveredNavContainerRef.current = null;
|
|
9464
|
-
setHoveredNavContainerRect(null);
|
|
9465
|
-
return;
|
|
9466
|
-
}
|
|
9467
|
-
const navContainer = document.querySelector("[data-ohw-nav-container]");
|
|
9468
|
-
if (!navContainer) {
|
|
9469
|
-
hoveredNavContainerRef.current = null;
|
|
9470
|
-
setHoveredNavContainerRect(null);
|
|
9471
|
-
return;
|
|
9472
|
-
}
|
|
9473
|
-
const containerRect = navContainer.getBoundingClientRect();
|
|
9474
|
-
const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
|
|
9475
|
-
if (!overContainer) {
|
|
9476
|
-
hoveredNavContainerRef.current = null;
|
|
9477
|
-
setHoveredNavContainerRect(null);
|
|
9478
|
-
return;
|
|
9479
|
-
}
|
|
9480
|
-
const navItemHit = Array.from(
|
|
9481
|
-
navContainer.querySelectorAll("[data-ohw-href-key]")
|
|
9482
|
-
).find((el) => {
|
|
9483
|
-
if (!isNavigationItem(el) || isNavbarButton2(el)) return false;
|
|
9484
|
-
const itemRect = el.getBoundingClientRect();
|
|
9485
|
-
return x >= itemRect.left && x <= itemRect.right && y >= itemRect.top && y <= itemRect.bottom;
|
|
9486
|
-
});
|
|
9487
|
-
if (navItemHit) {
|
|
9488
|
-
hoveredNavContainerRef.current = null;
|
|
9489
|
-
setHoveredNavContainerRect(null);
|
|
9490
|
-
const selected = selectedElRef.current;
|
|
9491
|
-
if (selected !== navItemHit && !selected?.contains(navItemHit)) {
|
|
9492
|
-
clearHrefKeyHover(navItemHit);
|
|
9493
|
-
hoveredItemElRef.current = navItemHit;
|
|
9494
|
-
setHoveredItemRect(navItemHit.getBoundingClientRect());
|
|
9495
|
-
}
|
|
9496
|
-
return;
|
|
9497
|
-
}
|
|
9498
|
-
hoveredNavContainerRef.current = navContainer;
|
|
9499
|
-
setHoveredNavContainerRect(containerRect);
|
|
9500
|
-
hoveredItemElRef.current = null;
|
|
9501
|
-
setHoveredItemRect(null);
|
|
9502
|
-
};
|
|
9503
7491
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
9504
7492
|
if (linkPopoverOpenRef.current) {
|
|
9505
|
-
|
|
9506
|
-
|
|
9507
|
-
|
|
9508
|
-
|
|
9509
|
-
|
|
9510
|
-
|
|
9511
|
-
probeNavigationHoverAt(x, y);
|
|
7493
|
+
if (hoveredImageRef.current) {
|
|
7494
|
+
hoveredImageRef.current = null;
|
|
7495
|
+
hoveredImageHasTextOverlapRef.current = false;
|
|
7496
|
+
resumeAnimTracks();
|
|
7497
|
+
clearImageHover();
|
|
7498
|
+
}
|
|
9512
7499
|
return;
|
|
9513
7500
|
}
|
|
9514
|
-
hoveredNavContainerRef.current = null;
|
|
9515
|
-
setHoveredNavContainerRect(null);
|
|
9516
7501
|
const toggleEl = document.querySelector("[data-ohw-state-toggle]");
|
|
9517
7502
|
if (toggleEl) {
|
|
7503
|
+
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
9518
7504
|
const tr = toggleEl.getBoundingClientRect();
|
|
9519
7505
|
if (x >= tr.left && x <= tr.right && y >= tr.top && y <= tr.bottom) {
|
|
9520
|
-
|
|
7506
|
+
if (hoveredImageRef.current) {
|
|
7507
|
+
hoveredImageRef.current = null;
|
|
7508
|
+
resumeAnimTracks();
|
|
7509
|
+
clearImageHover();
|
|
7510
|
+
}
|
|
9521
7511
|
return;
|
|
9522
7512
|
}
|
|
9523
7513
|
}
|
|
9524
7514
|
const imgEl = findImageAtPoint(clientX, clientY, fromParentViewport);
|
|
9525
7515
|
const activeEl = activeElRef.current;
|
|
9526
7516
|
if (activeEl && (!imgEl || imgEl.contains(activeEl))) {
|
|
9527
|
-
|
|
7517
|
+
if (hoveredImageRef.current) {
|
|
7518
|
+
hoveredImageRef.current = null;
|
|
7519
|
+
hoveredImageHasTextOverlapRef.current = false;
|
|
7520
|
+
resumeAnimTracks();
|
|
7521
|
+
clearImageHover();
|
|
7522
|
+
}
|
|
9528
7523
|
return;
|
|
9529
7524
|
}
|
|
9530
7525
|
if (imgEl) {
|
|
7526
|
+
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
7527
|
+
const overMediaChrome = Array.from(
|
|
7528
|
+
document.querySelectorAll("[data-ohw-media-chrome]")
|
|
7529
|
+
).some((el) => {
|
|
7530
|
+
const r2 = el.getBoundingClientRect();
|
|
7531
|
+
return x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom;
|
|
7532
|
+
});
|
|
7533
|
+
if (overMediaChrome) {
|
|
7534
|
+
if (hoveredImageRef.current) {
|
|
7535
|
+
hoveredImageRef.current = null;
|
|
7536
|
+
hoveredImageHasTextOverlapRef.current = false;
|
|
7537
|
+
resumeAnimTracks();
|
|
7538
|
+
clearImageHover();
|
|
7539
|
+
}
|
|
7540
|
+
return;
|
|
7541
|
+
}
|
|
9531
7542
|
const topEl = document.elementFromPoint(x, y);
|
|
9532
|
-
if (topEl?.closest('[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]
|
|
7543
|
+
if (topEl?.closest('[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
9533
7544
|
if (hoveredImageRef.current) {
|
|
9534
7545
|
hoveredImageRef.current = null;
|
|
9535
7546
|
resumeAnimTracks();
|
|
@@ -9627,12 +7638,12 @@ function OhhwellsBridge() {
|
|
|
9627
7638
|
resumeAnimTracks();
|
|
9628
7639
|
clearImageHover();
|
|
9629
7640
|
}
|
|
9630
|
-
const { x
|
|
7641
|
+
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
9631
7642
|
const textEl = Array.from(
|
|
9632
7643
|
document.querySelectorAll(NON_MEDIA_SELECTOR)
|
|
9633
7644
|
).find((el) => {
|
|
9634
7645
|
const er = el.getBoundingClientRect();
|
|
9635
|
-
return
|
|
7646
|
+
return x >= er.left && x <= er.right && y >= er.top && y <= er.bottom;
|
|
9636
7647
|
});
|
|
9637
7648
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
9638
7649
|
if (textEl && !textEl.hasAttribute("contenteditable")) {
|
|
@@ -9656,14 +7667,6 @@ function OhhwellsBridge() {
|
|
|
9656
7667
|
}
|
|
9657
7668
|
};
|
|
9658
7669
|
const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
|
|
9659
|
-
if (linkPopoverOpenRef.current || document.documentElement.hasAttribute("data-ohw-section-picking")) {
|
|
9660
|
-
if (activeStateElRef.current) {
|
|
9661
|
-
activeStateElRef.current.removeAttribute("data-ohw-state-hovered");
|
|
9662
|
-
activeStateElRef.current = null;
|
|
9663
|
-
setToggleState(null);
|
|
9664
|
-
}
|
|
9665
|
-
return;
|
|
9666
|
-
}
|
|
9667
7670
|
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
9668
7671
|
const toggleEl = document.querySelector("[data-ohw-state-toggle]");
|
|
9669
7672
|
if (toggleEl) {
|
|
@@ -9736,14 +7739,6 @@ function OhhwellsBridge() {
|
|
|
9736
7739
|
probeHoverCardsAt(clientX, clientY);
|
|
9737
7740
|
};
|
|
9738
7741
|
const handleDragOver = (e) => {
|
|
9739
|
-
const footerSession = footerDragRef.current;
|
|
9740
|
-
if (footerSession) {
|
|
9741
|
-
e.preventDefault();
|
|
9742
|
-
if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
|
|
9743
|
-
const slot = footerSession.kind === "link" && footerSession.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, footerSession.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
|
|
9744
|
-
refreshFooterDragVisualsRef.current(footerSession, slot, e.clientX, e.clientY);
|
|
9745
|
-
return;
|
|
9746
|
-
}
|
|
9747
7742
|
e.preventDefault();
|
|
9748
7743
|
const el = findImageAtPoint(e.clientX, e.clientY, false);
|
|
9749
7744
|
if (!el) {
|
|
@@ -9926,7 +7921,6 @@ function OhhwellsBridge() {
|
|
|
9926
7921
|
continue;
|
|
9927
7922
|
}
|
|
9928
7923
|
if (applyVideoSettingNode(key, val)) continue;
|
|
9929
|
-
if (applyCarouselNode(key, val)) continue;
|
|
9930
7924
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
9931
7925
|
if (el.dataset.ohwEditable === "image") {
|
|
9932
7926
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
@@ -9949,9 +7943,6 @@ function OhhwellsBridge() {
|
|
|
9949
7943
|
sectionsLoadedRef.current = true;
|
|
9950
7944
|
pendingScheduleConfigRequests.current.splice(0).forEach(processConfigRequest);
|
|
9951
7945
|
}
|
|
9952
|
-
editContentRef.current = { ...editContentRef.current, ...content };
|
|
9953
|
-
reconcileNavbarItemsFromContent(editContentRef.current);
|
|
9954
|
-
reconcileFooterOrderFromContent(editContentRef.current);
|
|
9955
7946
|
enforceLinkHrefs();
|
|
9956
7947
|
postToParentRef.current({ type: "ow:hydrate-done" });
|
|
9957
7948
|
};
|
|
@@ -9959,7 +7950,6 @@ function OhhwellsBridge() {
|
|
|
9959
7950
|
const handleDeactivate = (e) => {
|
|
9960
7951
|
if (e.data?.type !== "ow:deactivate") return;
|
|
9961
7952
|
if (Date.now() < linkPopoverGraceUntilRef.current) return;
|
|
9962
|
-
if (document.querySelector("[data-ohw-section-picker]")) return;
|
|
9963
7953
|
if (linkPopoverOpenRef.current) {
|
|
9964
7954
|
setLinkPopoverRef.current(null);
|
|
9965
7955
|
return;
|
|
@@ -9968,40 +7958,13 @@ function OhhwellsBridge() {
|
|
|
9968
7958
|
deactivateRef.current();
|
|
9969
7959
|
};
|
|
9970
7960
|
window.addEventListener("message", handleDeactivate);
|
|
9971
|
-
const handleUiEscape = (e) => {
|
|
9972
|
-
if (e.data?.type !== "ui:escape") return;
|
|
9973
|
-
if (linkPopoverOpenRef.current) {
|
|
9974
|
-
setLinkPopoverRef.current(null);
|
|
9975
|
-
}
|
|
9976
|
-
};
|
|
9977
|
-
window.addEventListener("message", handleUiEscape);
|
|
9978
7961
|
const handleKeyDown = (e) => {
|
|
9979
|
-
if (e.key === "Escape" && document.querySelector("[data-ohw-section-picker]")) return;
|
|
9980
|
-
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "a" && activeElRef.current) {
|
|
9981
|
-
const navAnchor = getNavigationItemAnchor(activeElRef.current);
|
|
9982
|
-
if (navAnchor) {
|
|
9983
|
-
e.preventDefault();
|
|
9984
|
-
selectAllTextInEditable(activeElRef.current);
|
|
9985
|
-
refreshActiveCommandsRef.current();
|
|
9986
|
-
return;
|
|
9987
|
-
}
|
|
9988
|
-
}
|
|
9989
7962
|
if (e.key === "Escape" && linkPopoverOpenRef.current) {
|
|
9990
7963
|
setLinkPopoverRef.current(null);
|
|
9991
7964
|
return;
|
|
9992
7965
|
}
|
|
9993
7966
|
if (e.key === "Escape" && selectedElRef.current && !activeElRef.current) {
|
|
9994
|
-
|
|
9995
|
-
deselectRef.current();
|
|
9996
|
-
return;
|
|
9997
|
-
}
|
|
9998
|
-
const parent = getNavigationSelectionParent(selectedElRef.current);
|
|
9999
|
-
if (parent) {
|
|
10000
|
-
e.preventDefault();
|
|
10001
|
-
selectFrameRef.current(parent);
|
|
10002
|
-
} else {
|
|
10003
|
-
deselectRef.current();
|
|
10004
|
-
}
|
|
7967
|
+
deselectRef.current();
|
|
10005
7968
|
return;
|
|
10006
7969
|
}
|
|
10007
7970
|
if (e.key === "Escape" && activeElRef.current) {
|
|
@@ -10059,23 +8022,9 @@ function OhhwellsBridge() {
|
|
|
10059
8022
|
if (hoveredItemElRef.current) {
|
|
10060
8023
|
setHoveredItemRect(hoveredItemElRef.current.getBoundingClientRect());
|
|
10061
8024
|
}
|
|
10062
|
-
if (hoveredNavContainerRef.current) {
|
|
10063
|
-
setHoveredNavContainerRect(hoveredNavContainerRef.current.getBoundingClientRect());
|
|
10064
|
-
}
|
|
10065
8025
|
if (siblingHintElRef.current) {
|
|
10066
8026
|
setSiblingHintRect(siblingHintElRef.current.getBoundingClientRect());
|
|
10067
8027
|
}
|
|
10068
|
-
const selected = selectedElRef.current;
|
|
10069
|
-
if (selected && !footerDragRef.current && (selected.hasAttribute("data-ohw-footer-col") || Boolean(selected.closest("footer") && isInferredFooterGroup(selected)))) {
|
|
10070
|
-
setSiblingHintRects(
|
|
10071
|
-
listFooterColumns().filter((column) => column !== selected).map((column) => column.getBoundingClientRect())
|
|
10072
|
-
);
|
|
10073
|
-
}
|
|
10074
|
-
if (footerDragRef.current) {
|
|
10075
|
-
const session = footerDragRef.current;
|
|
10076
|
-
const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
|
|
10077
|
-
refreshFooterDragVisualsRef.current(session, slot, session.lastClientX, session.lastClientY);
|
|
10078
|
-
}
|
|
10079
8028
|
if (hoveredImageRef.current) {
|
|
10080
8029
|
const el = hoveredImageRef.current;
|
|
10081
8030
|
const r2 = el.getBoundingClientRect();
|
|
@@ -10086,7 +8035,7 @@ function OhhwellsBridge() {
|
|
|
10086
8035
|
};
|
|
10087
8036
|
const handleSave = (e) => {
|
|
10088
8037
|
if (e.data?.type !== "ow:save") return;
|
|
10089
|
-
const nodes = collectEditableNodes(
|
|
8038
|
+
const nodes = collectEditableNodes();
|
|
10090
8039
|
const tracker = document.querySelector("[data-ohw-sections-tracker]");
|
|
10091
8040
|
if (tracker?.textContent) nodes.push({ key: "__ohw_sections", type: "sections", text: tracker.textContent });
|
|
10092
8041
|
postToParentRef.current({ type: "ow:save-result", nodes });
|
|
@@ -10171,7 +8120,6 @@ function OhhwellsBridge() {
|
|
|
10171
8120
|
const handleDocMouseLeave = () => {
|
|
10172
8121
|
hoveredImageRef.current = null;
|
|
10173
8122
|
setMediaHover(null);
|
|
10174
|
-
setCarouselHover(null);
|
|
10175
8123
|
document.querySelectorAll("[data-ohw-state-hovered]").forEach((el) => el.removeAttribute("data-ohw-state-hovered"));
|
|
10176
8124
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
10177
8125
|
activeStateElRef.current = null;
|
|
@@ -10211,48 +8159,6 @@ function OhhwellsBridge() {
|
|
|
10211
8159
|
if (e.data?.type !== "ow:canvas-height" || typeof e.data.height !== "number") return;
|
|
10212
8160
|
document.documentElement.style.setProperty("--ohw-canvas-h", `${e.data.height}px`);
|
|
10213
8161
|
};
|
|
10214
|
-
const handleCarouselChange = (e) => {
|
|
10215
|
-
if (e.data?.type !== "ow:carousel-change") return;
|
|
10216
|
-
const { key, images } = e.data;
|
|
10217
|
-
if (!key || !Array.isArray(images)) return;
|
|
10218
|
-
const text = JSON.stringify(images);
|
|
10219
|
-
applyCarouselValue(key, images);
|
|
10220
|
-
editContentRef.current = { ...editContentRef.current, [key]: text };
|
|
10221
|
-
postToParentRef.current({ type: "ow:change", nodes: [{ key, text }] });
|
|
10222
|
-
setCarouselHover(null);
|
|
10223
|
-
};
|
|
10224
|
-
const findCarouselAtPoint = (clientX, clientY) => {
|
|
10225
|
-
const containers = Array.from(document.querySelectorAll(`[${CAROUSEL_ATTR}]`));
|
|
10226
|
-
for (let i = containers.length - 1; i >= 0; i--) {
|
|
10227
|
-
const r2 = containers[i].getBoundingClientRect();
|
|
10228
|
-
if (clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom) {
|
|
10229
|
-
return containers[i];
|
|
10230
|
-
}
|
|
10231
|
-
}
|
|
10232
|
-
return null;
|
|
10233
|
-
};
|
|
10234
|
-
const isPointOverEditable = (scope, clientX, clientY) => {
|
|
10235
|
-
const editables = scope.querySelectorAll("[data-ohw-editable], [data-ohw-href-key]");
|
|
10236
|
-
for (const el of editables) {
|
|
10237
|
-
const r2 = el.getBoundingClientRect();
|
|
10238
|
-
if (clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom) return true;
|
|
10239
|
-
}
|
|
10240
|
-
return false;
|
|
10241
|
-
};
|
|
10242
|
-
const handleCarouselHover = (e) => {
|
|
10243
|
-
const container = findCarouselAtPoint(e.clientX, e.clientY);
|
|
10244
|
-
const scope = container?.closest("[data-ohw-section]") ?? container?.parentElement ?? null;
|
|
10245
|
-
if (!container || !scope || isPointOverEditable(scope, e.clientX, e.clientY)) {
|
|
10246
|
-
setCarouselHover((prev) => prev ? null : prev);
|
|
10247
|
-
return;
|
|
10248
|
-
}
|
|
10249
|
-
const key = container.getAttribute("data-ohw-key") ?? "";
|
|
10250
|
-
if (!key) return;
|
|
10251
|
-
const r2 = getVisibleRect(container);
|
|
10252
|
-
setCarouselHover(
|
|
10253
|
-
(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 } }
|
|
10254
|
-
);
|
|
10255
|
-
};
|
|
10256
8162
|
const applyToolbarPos = (rect) => {
|
|
10257
8163
|
const ps = parentScrollRef.current;
|
|
10258
8164
|
const approxW = 330;
|
|
@@ -10312,45 +8218,9 @@ function OhhwellsBridge() {
|
|
|
10312
8218
|
return clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
|
|
10313
8219
|
});
|
|
10314
8220
|
if (textEditable) {
|
|
10315
|
-
|
|
10316
|
-
const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
|
|
10317
|
-
if (navAnchor) {
|
|
10318
|
-
if (selectedElRef.current === navAnchor) {
|
|
10319
|
-
activateRef.current(textEditable, { caretX: clientX, caretY: clientY });
|
|
10320
|
-
} else {
|
|
10321
|
-
selectRef.current(navAnchor);
|
|
10322
|
-
}
|
|
10323
|
-
return;
|
|
10324
|
-
}
|
|
10325
|
-
activateRef.current(textEditable, { caretX: clientX, caretY: clientY });
|
|
8221
|
+
activateRef.current(textEditable);
|
|
10326
8222
|
return;
|
|
10327
8223
|
}
|
|
10328
|
-
const navContainer = document.querySelector("[data-ohw-nav-container]");
|
|
10329
|
-
if (navContainer) {
|
|
10330
|
-
const r2 = navContainer.getBoundingClientRect();
|
|
10331
|
-
const pad = 8;
|
|
10332
|
-
const over = clientX >= r2.left - pad && clientX <= r2.right + pad && clientY >= r2.top - pad && clientY <= r2.bottom + pad;
|
|
10333
|
-
if (over && !isPointOverNavItem(navContainer, clientX, clientY)) {
|
|
10334
|
-
selectFrameRef.current(navContainer);
|
|
10335
|
-
return;
|
|
10336
|
-
}
|
|
10337
|
-
}
|
|
10338
|
-
const navRoot = document.querySelector("[data-ohw-nav-root]");
|
|
10339
|
-
if (navRoot && navContainer) {
|
|
10340
|
-
const rr = navRoot.getBoundingClientRect();
|
|
10341
|
-
if (clientX >= rr.left && clientX <= rr.right && clientY >= rr.top && clientY <= rr.bottom && !isPointOverNavItem(navContainer, clientX, clientY)) {
|
|
10342
|
-
const book = navRoot.querySelector('[data-ohw-role="navbar-button"]');
|
|
10343
|
-
if (book) {
|
|
10344
|
-
const br = book.getBoundingClientRect();
|
|
10345
|
-
if (clientX >= br.left && clientX <= br.right && clientY >= br.top && clientY <= br.bottom) {
|
|
10346
|
-
deactivateRef.current();
|
|
10347
|
-
return;
|
|
10348
|
-
}
|
|
10349
|
-
}
|
|
10350
|
-
selectFrameRef.current(navContainer);
|
|
10351
|
-
return;
|
|
10352
|
-
}
|
|
10353
|
-
}
|
|
10354
8224
|
deactivateRef.current();
|
|
10355
8225
|
};
|
|
10356
8226
|
window.addEventListener("message", handleSave);
|
|
@@ -10361,7 +8231,6 @@ function OhhwellsBridge() {
|
|
|
10361
8231
|
window.addEventListener("message", handleRemoveSchedulingSection);
|
|
10362
8232
|
window.addEventListener("message", handleImageUrl);
|
|
10363
8233
|
window.addEventListener("message", handleImageUploading);
|
|
10364
|
-
window.addEventListener("message", handleCarouselChange);
|
|
10365
8234
|
window.addEventListener("message", handleCanvasHeight);
|
|
10366
8235
|
window.addEventListener("message", handleParentScroll);
|
|
10367
8236
|
window.addEventListener("message", handlePointerSync);
|
|
@@ -10373,13 +8242,11 @@ function OhhwellsBridge() {
|
|
|
10373
8242
|
};
|
|
10374
8243
|
window.addEventListener("resize", handleViewportResize, { passive: true });
|
|
10375
8244
|
document.addEventListener("click", handleClick, true);
|
|
10376
|
-
document.addEventListener("dblclick", handleDblClick, true);
|
|
10377
8245
|
document.addEventListener("paste", handlePaste, true);
|
|
10378
8246
|
document.addEventListener("input", handleInput, true);
|
|
10379
8247
|
document.addEventListener("mouseover", handleMouseOver, true);
|
|
10380
8248
|
document.addEventListener("mouseout", handleMouseOut, true);
|
|
10381
8249
|
document.addEventListener("mousemove", handleMouseMove, true);
|
|
10382
|
-
document.addEventListener("mousemove", handleCarouselHover, true);
|
|
10383
8250
|
document.addEventListener("mouseleave", handleDocMouseLeave);
|
|
10384
8251
|
document.addEventListener("dragover", handleDragOver, true);
|
|
10385
8252
|
document.addEventListener("dragleave", handleDragLeave, true);
|
|
@@ -10389,13 +8256,11 @@ function OhhwellsBridge() {
|
|
|
10389
8256
|
window.addEventListener("scroll", handleScroll, true);
|
|
10390
8257
|
return () => {
|
|
10391
8258
|
document.removeEventListener("click", handleClick, true);
|
|
10392
|
-
document.removeEventListener("dblclick", handleDblClick, true);
|
|
10393
8259
|
document.removeEventListener("paste", handlePaste, true);
|
|
10394
8260
|
document.removeEventListener("input", handleInput, true);
|
|
10395
8261
|
document.removeEventListener("mouseover", handleMouseOver, true);
|
|
10396
8262
|
document.removeEventListener("mouseout", handleMouseOut, true);
|
|
10397
8263
|
document.removeEventListener("mousemove", handleMouseMove, true);
|
|
10398
|
-
document.removeEventListener("mousemove", handleCarouselHover, true);
|
|
10399
8264
|
document.removeEventListener("mouseleave", handleDocMouseLeave);
|
|
10400
8265
|
document.removeEventListener("dragover", handleDragOver, true);
|
|
10401
8266
|
document.removeEventListener("dragleave", handleDragLeave, true);
|
|
@@ -10411,7 +8276,6 @@ function OhhwellsBridge() {
|
|
|
10411
8276
|
window.removeEventListener("message", handleRemoveSchedulingSection);
|
|
10412
8277
|
window.removeEventListener("message", handleImageUrl);
|
|
10413
8278
|
window.removeEventListener("message", handleImageUploading);
|
|
10414
|
-
window.removeEventListener("message", handleCarouselChange);
|
|
10415
8279
|
window.removeEventListener("message", handleCanvasHeight);
|
|
10416
8280
|
window.removeEventListener("message", handleParentScroll);
|
|
10417
8281
|
window.removeEventListener("resize", handleViewportResize);
|
|
@@ -10419,162 +8283,13 @@ function OhhwellsBridge() {
|
|
|
10419
8283
|
window.removeEventListener("message", handleClickAt);
|
|
10420
8284
|
window.removeEventListener("message", handleHydrate);
|
|
10421
8285
|
window.removeEventListener("message", handleDeactivate);
|
|
10422
|
-
window.removeEventListener("message", handleUiEscape);
|
|
10423
8286
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
10424
8287
|
autoSaveTimers.current.clear();
|
|
10425
8288
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
10426
8289
|
if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
|
|
10427
8290
|
};
|
|
10428
8291
|
}, [isEditMode, refreshStateRules]);
|
|
10429
|
-
(0,
|
|
10430
|
-
if (!isEditMode) return;
|
|
10431
|
-
const THRESHOLD = 10;
|
|
10432
|
-
const resolveWasSelected = (el) => {
|
|
10433
|
-
if (selectedElRef.current === el) return true;
|
|
10434
|
-
const activeAnchor = activeElRef.current ? getNavigationItemAnchor(activeElRef.current) : null;
|
|
10435
|
-
return activeAnchor === el;
|
|
10436
|
-
};
|
|
10437
|
-
const onPointerDown = (e) => {
|
|
10438
|
-
if (e.button !== 0) return;
|
|
10439
|
-
if (footerDragRef.current) return;
|
|
10440
|
-
const target = e.target;
|
|
10441
|
-
if (!target) return;
|
|
10442
|
-
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]')) {
|
|
10443
|
-
return;
|
|
10444
|
-
}
|
|
10445
|
-
if (target.closest("[data-ohw-item-drag-surface]")) return;
|
|
10446
|
-
const anchor = getNavigationItemAnchor(target);
|
|
10447
|
-
const hrefKey = anchor?.getAttribute("data-ohw-href-key") ?? null;
|
|
10448
|
-
if (anchor && isFooterHrefKey(hrefKey)) {
|
|
10449
|
-
armFooterPressDrag();
|
|
10450
|
-
footerPointerDragRef.current = {
|
|
10451
|
-
el: anchor,
|
|
10452
|
-
kind: "link",
|
|
10453
|
-
startX: e.clientX,
|
|
10454
|
-
startY: e.clientY,
|
|
10455
|
-
pointerId: e.pointerId,
|
|
10456
|
-
wasSelected: resolveWasSelected(anchor),
|
|
10457
|
-
started: false
|
|
10458
|
-
};
|
|
10459
|
-
return;
|
|
10460
|
-
}
|
|
10461
|
-
const col = target.closest("[data-ohw-footer-col]");
|
|
10462
|
-
if (col && !getNavigationItemAnchor(target)) {
|
|
10463
|
-
armFooterPressDrag();
|
|
10464
|
-
footerPointerDragRef.current = {
|
|
10465
|
-
el: col,
|
|
10466
|
-
kind: "column",
|
|
10467
|
-
startX: e.clientX,
|
|
10468
|
-
startY: e.clientY,
|
|
10469
|
-
pointerId: e.pointerId,
|
|
10470
|
-
wasSelected: resolveWasSelected(col),
|
|
10471
|
-
started: false
|
|
10472
|
-
};
|
|
10473
|
-
}
|
|
10474
|
-
};
|
|
10475
|
-
const onPointerMove = (e) => {
|
|
10476
|
-
const pending = footerPointerDragRef.current;
|
|
10477
|
-
if (!pending) return;
|
|
10478
|
-
if (pending.started) {
|
|
10479
|
-
e.preventDefault();
|
|
10480
|
-
clearTextSelection();
|
|
10481
|
-
const session = footerDragRef.current;
|
|
10482
|
-
if (!session) return;
|
|
10483
|
-
const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, session.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
|
|
10484
|
-
refreshFooterDragVisualsRef.current(session, slot, e.clientX, e.clientY);
|
|
10485
|
-
return;
|
|
10486
|
-
}
|
|
10487
|
-
const dx = e.clientX - pending.startX;
|
|
10488
|
-
const dy = e.clientY - pending.startY;
|
|
10489
|
-
if (dx * dx + dy * dy < THRESHOLD * THRESHOLD) return;
|
|
10490
|
-
e.preventDefault();
|
|
10491
|
-
pending.started = true;
|
|
10492
|
-
clearTextSelection();
|
|
10493
|
-
try {
|
|
10494
|
-
document.body.setPointerCapture(pending.pointerId);
|
|
10495
|
-
} catch {
|
|
10496
|
-
}
|
|
10497
|
-
if (linkPopoverOpenRef.current) {
|
|
10498
|
-
setLinkPopoverRef.current(null);
|
|
10499
|
-
}
|
|
10500
|
-
if (activeElRef.current) {
|
|
10501
|
-
deactivateRef.current();
|
|
10502
|
-
}
|
|
10503
|
-
if (pending.kind === "link") {
|
|
10504
|
-
const key = pending.el.getAttribute("data-ohw-href-key");
|
|
10505
|
-
if (!key) return;
|
|
10506
|
-
const column = findFooterColumnForLink(pending.el);
|
|
10507
|
-
const columns2 = listFooterColumns();
|
|
10508
|
-
beginFooterDragRef.current({
|
|
10509
|
-
kind: "link",
|
|
10510
|
-
hrefKey: key,
|
|
10511
|
-
columnEl: column,
|
|
10512
|
-
sourceColumnIndex: column ? columns2.indexOf(column) : 0,
|
|
10513
|
-
wasSelected: pending.wasSelected,
|
|
10514
|
-
draggedEl: pending.el,
|
|
10515
|
-
lastClientX: e.clientX,
|
|
10516
|
-
lastClientY: e.clientY,
|
|
10517
|
-
activeSlot: null
|
|
10518
|
-
});
|
|
10519
|
-
return;
|
|
10520
|
-
}
|
|
10521
|
-
const columns = listFooterColumns();
|
|
10522
|
-
const idx = columns.indexOf(pending.el);
|
|
10523
|
-
if (idx < 0) return;
|
|
10524
|
-
beginFooterDragRef.current({
|
|
10525
|
-
kind: "column",
|
|
10526
|
-
hrefKey: null,
|
|
10527
|
-
columnEl: pending.el,
|
|
10528
|
-
sourceColumnIndex: idx,
|
|
10529
|
-
wasSelected: pending.wasSelected,
|
|
10530
|
-
draggedEl: pending.el,
|
|
10531
|
-
lastClientX: e.clientX,
|
|
10532
|
-
lastClientY: e.clientY,
|
|
10533
|
-
activeSlot: null
|
|
10534
|
-
});
|
|
10535
|
-
};
|
|
10536
|
-
const endPointerDrag = (e) => {
|
|
10537
|
-
const pending = footerPointerDragRef.current;
|
|
10538
|
-
footerPointerDragRef.current = null;
|
|
10539
|
-
try {
|
|
10540
|
-
if (document.body.hasPointerCapture(e.pointerId)) {
|
|
10541
|
-
document.body.releasePointerCapture(e.pointerId);
|
|
10542
|
-
}
|
|
10543
|
-
} catch {
|
|
10544
|
-
}
|
|
10545
|
-
if (!pending?.started) {
|
|
10546
|
-
unlockFooterDragInteraction();
|
|
10547
|
-
return;
|
|
10548
|
-
}
|
|
10549
|
-
suppressNextClickRef.current = true;
|
|
10550
|
-
commitFooterDragRef.current(e.clientX, e.clientY);
|
|
10551
|
-
};
|
|
10552
|
-
const blockSelectStart = (e) => {
|
|
10553
|
-
if (footerDragRef.current || footerPointerDragRef.current?.started || document.documentElement.hasAttribute("data-ohw-footer-press-drag")) {
|
|
10554
|
-
e.preventDefault();
|
|
10555
|
-
}
|
|
10556
|
-
};
|
|
10557
|
-
const onDragEnd = (_e) => {
|
|
10558
|
-
if (!footerDragRef.current) return;
|
|
10559
|
-
commitFooterDragRef.current();
|
|
10560
|
-
};
|
|
10561
|
-
document.addEventListener("pointerdown", onPointerDown, true);
|
|
10562
|
-
document.addEventListener("pointermove", onPointerMove, true);
|
|
10563
|
-
document.addEventListener("pointerup", endPointerDrag, true);
|
|
10564
|
-
document.addEventListener("pointercancel", endPointerDrag, true);
|
|
10565
|
-
document.addEventListener("selectstart", blockSelectStart, true);
|
|
10566
|
-
document.addEventListener("dragend", onDragEnd, true);
|
|
10567
|
-
return () => {
|
|
10568
|
-
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
10569
|
-
document.removeEventListener("pointermove", onPointerMove, true);
|
|
10570
|
-
document.removeEventListener("pointerup", endPointerDrag, true);
|
|
10571
|
-
document.removeEventListener("pointercancel", endPointerDrag, true);
|
|
10572
|
-
document.removeEventListener("selectstart", blockSelectStart, true);
|
|
10573
|
-
document.removeEventListener("dragend", onDragEnd, true);
|
|
10574
|
-
unlockFooterDragInteraction();
|
|
10575
|
-
};
|
|
10576
|
-
}, [isEditMode]);
|
|
10577
|
-
(0, import_react9.useEffect)(() => {
|
|
8292
|
+
(0, import_react6.useEffect)(() => {
|
|
10578
8293
|
const handler = (e) => {
|
|
10579
8294
|
if (e.data?.type !== "ow:request-schedule-config") return;
|
|
10580
8295
|
const insertAfterVal = e.data.insertAfter;
|
|
@@ -10590,7 +8305,7 @@ function OhhwellsBridge() {
|
|
|
10590
8305
|
window.addEventListener("message", handler);
|
|
10591
8306
|
return () => window.removeEventListener("message", handler);
|
|
10592
8307
|
}, [processConfigRequest]);
|
|
10593
|
-
(0,
|
|
8308
|
+
(0, import_react6.useEffect)(() => {
|
|
10594
8309
|
if (!isEditMode) return;
|
|
10595
8310
|
document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
|
|
10596
8311
|
el.removeAttribute("data-ohw-active-state");
|
|
@@ -10611,33 +8326,27 @@ function OhhwellsBridge() {
|
|
|
10611
8326
|
const next = { ...prev, [pathKey]: sections };
|
|
10612
8327
|
return shouldUseDevFixtures() ? { ...DEV_SECTIONS_BY_PATH, ...next } : next;
|
|
10613
8328
|
});
|
|
10614
|
-
|
|
10615
|
-
|
|
10616
|
-
version: "1",
|
|
10617
|
-
path: pathname,
|
|
10618
|
-
nodes: collectEditableNodes(editContentRef.current),
|
|
10619
|
-
sections
|
|
10620
|
-
});
|
|
10621
|
-
postToParent2({ type: "ow:request-site-pages" });
|
|
8329
|
+
postToParent({ type: "ow:ready", version: "1", path: pathname, nodes: collectEditableNodes(), sections });
|
|
8330
|
+
postToParent({ type: "ow:request-site-pages" });
|
|
10622
8331
|
}, 150);
|
|
10623
8332
|
return () => {
|
|
10624
8333
|
cancelAnimationFrame(raf);
|
|
10625
8334
|
clearTimeout(timer);
|
|
10626
8335
|
};
|
|
10627
|
-
}, [pathname, isEditMode, refreshStateRules,
|
|
10628
|
-
(0,
|
|
8336
|
+
}, [pathname, isEditMode, refreshStateRules, postToParent]);
|
|
8337
|
+
(0, import_react6.useEffect)(() => {
|
|
10629
8338
|
scrollToHashSectionWhenReady();
|
|
10630
8339
|
const onHashChange = () => scrollToHashSectionWhenReady();
|
|
10631
8340
|
window.addEventListener("hashchange", onHashChange);
|
|
10632
8341
|
return () => window.removeEventListener("hashchange", onHashChange);
|
|
10633
8342
|
}, [pathname]);
|
|
10634
|
-
const handleCommand = (0,
|
|
8343
|
+
const handleCommand = (0, import_react6.useCallback)((cmd) => {
|
|
10635
8344
|
document.execCommand(cmd, false);
|
|
10636
8345
|
activeElRef.current?.focus();
|
|
10637
8346
|
if (activeElRef.current) setToolbarRect(getEditMeasureEl(activeElRef.current).getBoundingClientRect());
|
|
10638
8347
|
refreshActiveCommandsRef.current();
|
|
10639
8348
|
}, []);
|
|
10640
|
-
const handleStateChange = (0,
|
|
8349
|
+
const handleStateChange = (0, import_react6.useCallback)((state) => {
|
|
10641
8350
|
if (!activeStateElRef.current) return;
|
|
10642
8351
|
const el = activeStateElRef.current;
|
|
10643
8352
|
if (state === "Default") {
|
|
@@ -10650,22 +8359,18 @@ function OhhwellsBridge() {
|
|
|
10650
8359
|
}
|
|
10651
8360
|
setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
|
|
10652
8361
|
}, [deactivate]);
|
|
10653
|
-
const closeLinkPopover = (0,
|
|
10654
|
-
|
|
10655
|
-
setLinkPopover(null);
|
|
10656
|
-
}, []);
|
|
10657
|
-
const openLinkPopoverForActive = (0, import_react9.useCallback)(() => {
|
|
8362
|
+
const closeLinkPopover = (0, import_react6.useCallback)(() => setLinkPopover(null), []);
|
|
8363
|
+
const openLinkPopoverForActive = (0, import_react6.useCallback)(() => {
|
|
10658
8364
|
const hrefCtx = getHrefKeyFromElement(activeElRef.current);
|
|
10659
8365
|
if (!hrefCtx) return;
|
|
10660
8366
|
bumpLinkPopoverGrace();
|
|
10661
8367
|
setLinkPopover({
|
|
10662
8368
|
key: hrefCtx.key,
|
|
10663
|
-
|
|
10664
|
-
target: getLinkHref2(hrefCtx.anchor)
|
|
8369
|
+
target: getLinkHref(hrefCtx.anchor)
|
|
10665
8370
|
});
|
|
10666
8371
|
deactivate();
|
|
10667
8372
|
}, [deactivate]);
|
|
10668
|
-
const openLinkPopoverForSelected = (0,
|
|
8373
|
+
const openLinkPopoverForSelected = (0, import_react6.useCallback)(() => {
|
|
10669
8374
|
const anchor = selectedElRef.current;
|
|
10670
8375
|
if (!anchor) return;
|
|
10671
8376
|
const key = anchor.getAttribute("data-ohw-href-key");
|
|
@@ -10673,80 +8378,30 @@ function OhhwellsBridge() {
|
|
|
10673
8378
|
bumpLinkPopoverGrace();
|
|
10674
8379
|
setLinkPopover({
|
|
10675
8380
|
key,
|
|
10676
|
-
|
|
10677
|
-
target: getLinkHref2(anchor)
|
|
8381
|
+
target: getLinkHref(anchor)
|
|
10678
8382
|
});
|
|
10679
8383
|
deselect();
|
|
10680
8384
|
}, [deselect]);
|
|
10681
|
-
const handleLinkPopoverSubmit = (0,
|
|
8385
|
+
const handleLinkPopoverSubmit = (0, import_react6.useCallback)(
|
|
10682
8386
|
(target) => {
|
|
10683
|
-
|
|
10684
|
-
|
|
10685
|
-
if (session.intent === "add-nav") {
|
|
10686
|
-
const trimmed = target.trim();
|
|
10687
|
-
let href = trimmed;
|
|
10688
|
-
let label = "Untitled";
|
|
10689
|
-
if (trimmed) {
|
|
10690
|
-
const { pageRoute, sectionId } = parseTarget(trimmed);
|
|
10691
|
-
const page = resolvePage(pageRoute, sitePages);
|
|
10692
|
-
const pageSections = getSectionsForPath(sectionsByPath, pageRoute);
|
|
10693
|
-
const section = sectionId ? pageSections.find((s) => s.id === sectionId) : void 0;
|
|
10694
|
-
label = section?.label ?? page.title;
|
|
10695
|
-
href = trimmed;
|
|
10696
|
-
}
|
|
10697
|
-
const afterAnchor = addNavAfterAnchorRef.current;
|
|
10698
|
-
const { anchor, hrefKey, labelKey, index, order } = insertNavbarItem(href, label, afterAnchor);
|
|
10699
|
-
applyLinkByKey(hrefKey, href);
|
|
10700
|
-
document.querySelectorAll(`[data-ohw-key="${labelKey}"]`).forEach((el) => {
|
|
10701
|
-
el.textContent = label;
|
|
10702
|
-
});
|
|
10703
|
-
const navCount = String(index + 1);
|
|
10704
|
-
const orderJson = JSON.stringify(order);
|
|
10705
|
-
editContentRef.current = {
|
|
10706
|
-
...editContentRef.current,
|
|
10707
|
-
[hrefKey]: href,
|
|
10708
|
-
[labelKey]: label,
|
|
10709
|
-
[NAV_COUNT_KEY]: navCount,
|
|
10710
|
-
[NAV_ORDER_KEY]: orderJson
|
|
10711
|
-
};
|
|
10712
|
-
postToParent2({
|
|
10713
|
-
type: "ow:change",
|
|
10714
|
-
nodes: [
|
|
10715
|
-
{ key: hrefKey, text: href },
|
|
10716
|
-
{ key: labelKey, text: label },
|
|
10717
|
-
{ key: NAV_COUNT_KEY, text: navCount },
|
|
10718
|
-
{ key: NAV_ORDER_KEY, text: orderJson }
|
|
10719
|
-
]
|
|
10720
|
-
});
|
|
10721
|
-
postToParent2({ type: "ow:toast", title: "Link added", toastType: "success" });
|
|
10722
|
-
addNavAfterAnchorRef.current = null;
|
|
10723
|
-
setLinkPopover(null);
|
|
10724
|
-
enforceLinkHrefs();
|
|
10725
|
-
requestAnimationFrame(() => {
|
|
10726
|
-
selectRef.current(anchor);
|
|
10727
|
-
});
|
|
10728
|
-
return;
|
|
10729
|
-
}
|
|
10730
|
-
const { key } = session;
|
|
8387
|
+
if (!linkPopover) return;
|
|
8388
|
+
const { key } = linkPopover;
|
|
10731
8389
|
applyLinkByKey(key, target);
|
|
10732
|
-
|
|
8390
|
+
postToParent({ type: "ow:change", nodes: [{ key, text: target }] });
|
|
10733
8391
|
setLinkPopover(null);
|
|
10734
8392
|
},
|
|
10735
|
-
[
|
|
10736
|
-
);
|
|
10737
|
-
const handleMediaReplace = (0, import_react9.useCallback)(
|
|
10738
|
-
(key) => {
|
|
10739
|
-
postToParent2({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
|
|
10740
|
-
},
|
|
10741
|
-
[postToParent2, mediaHover?.elementType]
|
|
8393
|
+
[linkPopover, postToParent]
|
|
10742
8394
|
);
|
|
10743
|
-
const
|
|
8395
|
+
const showEditLink = toolbarShowEditLink;
|
|
8396
|
+
const currentSections = sectionsByPath[pathname] ?? [];
|
|
8397
|
+
linkPopoverOpenRef.current = linkPopover !== null;
|
|
8398
|
+
const handleMediaReplace = (0, import_react6.useCallback)(
|
|
10744
8399
|
(key) => {
|
|
10745
|
-
|
|
8400
|
+
postToParent({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
|
|
10746
8401
|
},
|
|
10747
|
-
[
|
|
8402
|
+
[postToParent, mediaHover?.elementType]
|
|
10748
8403
|
);
|
|
10749
|
-
const handleMediaFadeOutComplete = (0,
|
|
8404
|
+
const handleMediaFadeOutComplete = (0, import_react6.useCallback)((key) => {
|
|
10750
8405
|
setUploadingRects((prev) => {
|
|
10751
8406
|
if (!(key in prev)) return prev;
|
|
10752
8407
|
const next = { ...prev };
|
|
@@ -10754,7 +8409,7 @@ function OhhwellsBridge() {
|
|
|
10754
8409
|
return next;
|
|
10755
8410
|
});
|
|
10756
8411
|
}, []);
|
|
10757
|
-
const handleVideoSettingsChange = (0,
|
|
8412
|
+
const handleVideoSettingsChange = (0, import_react6.useCallback)(
|
|
10758
8413
|
(key, settings) => {
|
|
10759
8414
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
10760
8415
|
const video = getVideoEl(el);
|
|
@@ -10762,7 +8417,7 @@ function OhhwellsBridge() {
|
|
|
10762
8417
|
if (typeof settings.autoplay === "boolean") video.autoplay = settings.autoplay;
|
|
10763
8418
|
if (typeof settings.muted === "boolean") video.muted = settings.muted;
|
|
10764
8419
|
syncVideoPlayback(video);
|
|
10765
|
-
|
|
8420
|
+
postToParent({
|
|
10766
8421
|
type: "ow:change",
|
|
10767
8422
|
nodes: [
|
|
10768
8423
|
{ key: `${key}${VIDEO_AUTOPLAY_SUFFIX}`, text: String(video.autoplay) },
|
|
@@ -10774,15 +8429,12 @@ function OhhwellsBridge() {
|
|
|
10774
8429
|
);
|
|
10775
8430
|
});
|
|
10776
8431
|
},
|
|
10777
|
-
[
|
|
8432
|
+
[postToParent]
|
|
10778
8433
|
);
|
|
10779
|
-
|
|
10780
|
-
|
|
10781
|
-
|
|
10782
|
-
|
|
10783
|
-
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
10784
|
-
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
10785
|
-
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
8434
|
+
return bridgeRoot ? (0, import_react_dom2.createPortal)(
|
|
8435
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
8436
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
8437
|
+
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
10786
8438
|
MediaOverlay,
|
|
10787
8439
|
{
|
|
10788
8440
|
hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
|
|
@@ -10793,7 +8445,7 @@ function OhhwellsBridge() {
|
|
|
10793
8445
|
},
|
|
10794
8446
|
`uploading-${key}`
|
|
10795
8447
|
)),
|
|
10796
|
-
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0,
|
|
8448
|
+
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
10797
8449
|
MediaOverlay,
|
|
10798
8450
|
{
|
|
10799
8451
|
hover: mediaHover,
|
|
@@ -10802,33 +8454,53 @@ function OhhwellsBridge() {
|
|
|
10802
8454
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
10803
8455
|
}
|
|
10804
8456
|
),
|
|
10805
|
-
|
|
10806
|
-
siblingHintRect && !isItemDragging &&
|
|
10807
|
-
|
|
10808
|
-
|
|
10809
|
-
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
10810
|
-
"div",
|
|
8457
|
+
siblingHintRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
8458
|
+
hoveredItemRect && !siblingHintRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
8459
|
+
toolbarRect && toolbarVariant === "link-action" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
8460
|
+
ItemInteractionLayer,
|
|
10811
8461
|
{
|
|
10812
|
-
|
|
10813
|
-
|
|
10814
|
-
|
|
10815
|
-
|
|
10816
|
-
|
|
10817
|
-
|
|
10818
|
-
|
|
10819
|
-
|
|
10820
|
-
|
|
10821
|
-
|
|
10822
|
-
|
|
10823
|
-
|
|
10824
|
-
|
|
10825
|
-
|
|
10826
|
-
|
|
10827
|
-
|
|
10828
|
-
|
|
10829
|
-
|
|
8462
|
+
rect: toolbarRect,
|
|
8463
|
+
elRef: glowElRef,
|
|
8464
|
+
state: isItemDragging ? "dragging" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
|
|
8465
|
+
showHandle: Boolean(reorderHrefKey),
|
|
8466
|
+
dragDisabled: reorderDragDisabled,
|
|
8467
|
+
dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
|
|
8468
|
+
onDragHandleDragStart: handleItemDragStart,
|
|
8469
|
+
onDragHandleDragEnd: handleItemDragEnd,
|
|
8470
|
+
toolbar: isItemDragging ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
8471
|
+
ItemActionToolbar,
|
|
8472
|
+
{
|
|
8473
|
+
onEditLink: openLinkPopoverForSelected,
|
|
8474
|
+
onAddItem: handleAddNavigationItem,
|
|
8475
|
+
addItemDisabled: false
|
|
8476
|
+
}
|
|
8477
|
+
)
|
|
8478
|
+
}
|
|
8479
|
+
),
|
|
8480
|
+
toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
8481
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
8482
|
+
EditGlowChrome,
|
|
8483
|
+
{
|
|
8484
|
+
rect: toolbarRect,
|
|
8485
|
+
elRef: glowElRef,
|
|
8486
|
+
reorderHrefKey,
|
|
8487
|
+
dragDisabled: reorderDragDisabled
|
|
8488
|
+
}
|
|
8489
|
+
),
|
|
8490
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
8491
|
+
FloatingToolbar,
|
|
8492
|
+
{
|
|
8493
|
+
rect: toolbarRect,
|
|
8494
|
+
parentScroll: parentScrollRef.current,
|
|
8495
|
+
elRef: toolbarElRef,
|
|
8496
|
+
onCommand: handleCommand,
|
|
8497
|
+
activeCommands,
|
|
8498
|
+
showEditLink,
|
|
8499
|
+
onEditLink: openLinkPopoverForActive
|
|
8500
|
+
}
|
|
8501
|
+
)
|
|
10830
8502
|
] }),
|
|
10831
|
-
maxBadge && /* @__PURE__ */ (0,
|
|
8503
|
+
maxBadge && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
10832
8504
|
"div",
|
|
10833
8505
|
{
|
|
10834
8506
|
"data-ohw-max-badge": "",
|
|
@@ -10854,29 +8526,56 @@ function OhhwellsBridge() {
|
|
|
10854
8526
|
]
|
|
10855
8527
|
}
|
|
10856
8528
|
),
|
|
10857
|
-
toggleState &&
|
|
10858
|
-
|
|
10859
|
-
|
|
10860
|
-
|
|
10861
|
-
|
|
10862
|
-
|
|
10863
|
-
|
|
10864
|
-
|
|
10865
|
-
|
|
10866
|
-
|
|
10867
|
-
|
|
10868
|
-
|
|
10869
|
-
|
|
8529
|
+
toggleState && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
8530
|
+
StateToggle,
|
|
8531
|
+
{
|
|
8532
|
+
rect: toggleState.rect,
|
|
8533
|
+
activeState: toggleState.activeState,
|
|
8534
|
+
states: toggleState.states,
|
|
8535
|
+
onStateChange: handleStateChange
|
|
8536
|
+
}
|
|
8537
|
+
),
|
|
8538
|
+
sectionGap && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
8539
|
+
"div",
|
|
8540
|
+
{
|
|
8541
|
+
"data-ohw-section-insert-line": "",
|
|
8542
|
+
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
8543
|
+
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
8544
|
+
children: [
|
|
8545
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
8546
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
8547
|
+
Badge,
|
|
8548
|
+
{
|
|
8549
|
+
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",
|
|
8550
|
+
onClick: () => {
|
|
8551
|
+
window.parent.postMessage(
|
|
8552
|
+
{ type: "ow:add-section", insertAfter: sectionGap.insertAfter, insertBefore: sectionGap.insertBefore },
|
|
8553
|
+
"*"
|
|
8554
|
+
);
|
|
10870
8555
|
},
|
|
10871
|
-
"
|
|
10872
|
-
|
|
10873
|
-
|
|
10874
|
-
|
|
10875
|
-
|
|
10876
|
-
|
|
10877
|
-
|
|
10878
|
-
|
|
10879
|
-
|
|
8556
|
+
children: "Add Section"
|
|
8557
|
+
}
|
|
8558
|
+
),
|
|
8559
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
|
|
8560
|
+
]
|
|
8561
|
+
}
|
|
8562
|
+
),
|
|
8563
|
+
linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
8564
|
+
LinkPopover,
|
|
8565
|
+
{
|
|
8566
|
+
panelRef: linkPopoverPanelRef,
|
|
8567
|
+
portalContainer: dialogPortalContainer,
|
|
8568
|
+
open: true,
|
|
8569
|
+
mode: "edit",
|
|
8570
|
+
pages: sitePages,
|
|
8571
|
+
sections: currentSections,
|
|
8572
|
+
sectionsByPath,
|
|
8573
|
+
initialTarget: linkPopover.target,
|
|
8574
|
+
onClose: closeLinkPopover,
|
|
8575
|
+
onSubmit: handleLinkPopoverSubmit
|
|
8576
|
+
},
|
|
8577
|
+
`${linkPopover.key}-${pathname}`
|
|
8578
|
+
) : null
|
|
10880
8579
|
] }),
|
|
10881
8580
|
bridgeRoot
|
|
10882
8581
|
) : null;
|
|
@@ -10887,7 +8586,6 @@ function OhhwellsBridge() {
|
|
|
10887
8586
|
CustomToolbarButton,
|
|
10888
8587
|
CustomToolbarDivider,
|
|
10889
8588
|
DragHandle,
|
|
10890
|
-
DropIndicator,
|
|
10891
8589
|
ItemActionToolbar,
|
|
10892
8590
|
ItemInteractionLayer,
|
|
10893
8591
|
LinkEditorPanel,
|
|
@@ -10902,14 +8600,12 @@ function OhhwellsBridge() {
|
|
|
10902
8600
|
TooltipProvider,
|
|
10903
8601
|
TooltipTrigger,
|
|
10904
8602
|
buildTarget,
|
|
10905
|
-
dropIndicatorVariants,
|
|
10906
8603
|
filterAvailablePages,
|
|
10907
8604
|
getEditModeInitialState,
|
|
10908
8605
|
isEditSessionActive,
|
|
10909
8606
|
isValidUrl,
|
|
10910
8607
|
parseTarget,
|
|
10911
8608
|
toggleVariants,
|
|
10912
|
-
useOhwCarousel,
|
|
10913
8609
|
validateUrlInput
|
|
10914
8610
|
});
|
|
10915
8611
|
//# sourceMappingURL=index.cjs.map
|