@ohhwells/bridge 0.1.39-next.77 → 0.1.40

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/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  // src/OhhwellsBridge.tsx
4
- import React10, { useCallback as useCallback4, useEffect as useEffect8, useLayoutEffect as useLayoutEffect2, useRef as useRef5, useState as useState7 } from "react";
4
+ import React9, { useCallback as useCallback3, useEffect as useEffect7, useLayoutEffect as useLayoutEffect2, useRef as useRef5, useState as useState6 } from "react";
5
5
  import { createRoot } from "react-dom/client";
6
6
  import { flushSync } from "react-dom";
7
7
 
@@ -48,13 +48,12 @@ function useLinkHrefGuardian(...deps) {
48
48
  }
49
49
 
50
50
  // src/ui/SchedulingWidget.tsx
51
- import { useCallback, useEffect, useId, useMemo, useRef, useState as useState2 } from "react";
51
+ import { useEffect, useId, useMemo, useRef, useState as useState2 } from "react";
52
52
 
53
53
  // src/ui/EmailCaptureModal.tsx
54
54
  import { useState } from "react";
55
55
  import { Dialog } from "radix-ui";
56
56
  import { jsx, jsxs } from "react/jsx-runtime";
57
- var isValidEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
58
57
  function Spinner() {
59
58
  return /* @__PURE__ */ jsxs(
60
59
  "svg",
@@ -88,17 +87,12 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
88
87
  const [error, setError] = useState(null);
89
88
  const isBook = title === "Confirm your spot";
90
89
  const handleSubmit = async () => {
91
- const trimmed = email.trim();
92
- if (!trimmed) return;
93
- if (!isValidEmail(trimmed)) {
94
- setError("Please enter a valid email address.");
95
- return;
96
- }
90
+ if (!email.trim()) return;
97
91
  setLoading(true);
98
92
  setError(null);
99
93
  try {
100
- await onSubmit(trimmed);
101
- setSubmittedEmail(trimmed);
94
+ await onSubmit(email.trim());
95
+ setSubmittedEmail(email.trim());
102
96
  setSuccess(true);
103
97
  } catch (e) {
104
98
  setError(e instanceof Error ? e.message : "Something went wrong. Please try again.");
@@ -173,10 +167,7 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
173
167
  {
174
168
  type: "email",
175
169
  value: email,
176
- onChange: (e) => {
177
- setEmail(e.target.value);
178
- if (error) setError(null);
179
- },
170
+ onChange: (e) => setEmail(e.target.value),
180
171
  onKeyDown: handleKeyDown,
181
172
  placeholder: "hello@gmail.com",
182
173
  autoFocus: true,
@@ -233,20 +224,12 @@ function formatClassTime(cls) {
233
224
  const em = endTotal % 60;
234
225
  return `${h}:${cls.startTime.minutes}-${eh}:${String(em).padStart(2, "0")}`;
235
226
  }
236
- function formatBookingLabel(cls) {
237
- const price = cls.price;
238
- const isFree = price === null || price === void 0 || `${price}` === "" || `${price}` === "0";
239
- return isFree ? "Book for free" : `Book for ${cls.currency ?? ""} ${price}`.trim();
240
- }
241
227
  function getBookingsOnDate(cls, date) {
242
228
  if (!cls.bookings?.length) return 0;
243
- const target = new Date(date);
244
- target.setHours(0, 0, 0, 0);
229
+ const ds = date.toISOString().split("T")[0];
245
230
  return cls.bookings.filter((b) => {
246
231
  try {
247
- const bookingDate = new Date(b.classDate);
248
- bookingDate.setHours(0, 0, 0, 0);
249
- return bookingDate.getTime() === target.getTime();
232
+ return new Date(b.classDate).toISOString().split("T")[0] === ds;
250
233
  } catch {
251
234
  return false;
252
235
  }
@@ -511,7 +494,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
511
494
  }
512
495
  )
513
496
  ] }),
514
- cls.showAvailability !== false && /* @__PURE__ */ jsx2("div", { className: "sm:hidden flex flex-col gap-px", children: isFull ? /* @__PURE__ */ jsx2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
497
+ /* @__PURE__ */ jsx2("div", { className: "sm:hidden flex flex-col gap-px", children: isFull ? /* @__PURE__ */ jsx2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
515
498
  /* @__PURE__ */ jsxs2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
516
499
  available,
517
500
  "/",
@@ -523,10 +506,9 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
523
506
  /* @__PURE__ */ jsxs2("div", { className: "flex flex-1 flex-col gap-2 min-w-0 sm:contents", children: [
524
507
  /* @__PURE__ */ jsxs2("div", { className: "flex-1 flex flex-col gap-2 min-w-0", children: [
525
508
  /* @__PURE__ */ jsx2("span", { className: "font-body text-base font-bold text-(--color-dark,#200C02) block truncate", children: cls.name }),
526
- cls.hostName && /* @__PURE__ */ jsx2("span", { className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block truncate", children: cls.hostName }),
527
- cls.description && /* @__PURE__ */ jsx2("span", { className: "font-body text-sm font-normal text-(--color-dark,#200C02) opacity-70 block truncate", children: cls.description })
509
+ cls.hostName && /* @__PURE__ */ jsx2("span", { className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block truncate", children: cls.hostName })
528
510
  ] }),
529
- cls.showAvailability !== false && /* @__PURE__ */ jsx2("div", { className: "hidden sm:flex w-14 shrink-0 flex-col gap-px", children: isFull ? /* @__PURE__ */ jsx2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
511
+ /* @__PURE__ */ jsx2("div", { className: "hidden sm:flex w-14 shrink-0 flex-col gap-px", children: isFull ? /* @__PURE__ */ jsx2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
530
512
  /* @__PURE__ */ jsxs2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
531
513
  available,
532
514
  "/",
@@ -551,7 +533,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
551
533
  if (!cls.id) return;
552
534
  onOpenModal?.(isFull ? "waitlist" : "book", cls.id, selectedDate);
553
535
  },
554
- children: isFull ? "Join Waitlist" : formatBookingLabel(cls)
536
+ children: isFull ? "Join Waitlist" : "Book Now"
555
537
  }
556
538
  )
557
539
  ] })
@@ -593,17 +575,6 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
593
575
  const [isHovered, setIsHovered] = useState2(false);
594
576
  const [modalState, setModalState] = useState2(null);
595
577
  const switchScheduleIdRef = useRef(null);
596
- const liveScheduleIdRef = useRef(null);
597
- const refetchLiveSchedule = useCallback(async () => {
598
- const id = liveScheduleIdRef.current;
599
- if (!id) return;
600
- try {
601
- const res = await fetch(`${API_URL}/api/schedule/id/${id}`);
602
- const data = await res.json();
603
- if (data?.id) setSchedule(data);
604
- } catch {
605
- }
606
- }, []);
607
578
  const dates = useMemo(() => {
608
579
  const today = /* @__PURE__ */ new Date();
609
580
  today.setHours(0, 0, 0, 0);
@@ -623,18 +594,6 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
623
594
  }
624
595
  }
625
596
  }, [schedule, dates]);
626
- useEffect(() => {
627
- if (typeof window === "undefined") return;
628
- const onVisible = () => {
629
- if (!document.hidden) void refetchLiveSchedule();
630
- };
631
- window.addEventListener("focus", refetchLiveSchedule);
632
- document.addEventListener("visibilitychange", onVisible);
633
- return () => {
634
- window.removeEventListener("focus", refetchLiveSchedule);
635
- document.removeEventListener("visibilitychange", onVisible);
636
- };
637
- }, [refetchLiveSchedule]);
638
597
  useEffect(() => {
639
598
  if (typeof window === "undefined") return;
640
599
  const isInEditor = window.self !== window.top;
@@ -696,7 +655,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
696
655
  setLoading(false);
697
656
  return;
698
657
  }
699
- liveScheduleIdRef.current = effectiveId;
658
+ ;
700
659
  (async () => {
701
660
  try {
702
661
  const res = await fetch(`${API_URL}/api/schedule/id/${effectiveId}`);
@@ -753,14 +712,18 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
753
712
  const data = await res.json().catch(() => ({}));
754
713
  throw new Error(data?.message ?? "Something went wrong. Please try again.");
755
714
  }
756
- await refetchLiveSchedule();
757
715
  };
758
716
  const handleReplaceSchedule = () => {
759
717
  setIsHovered(false);
760
- window.parent.postMessage(
761
- { type: "ow:scheduling-not-connected", insertAfter, currentScheduleId: schedule?.id },
762
- "*"
763
- );
718
+ if (schedule) {
719
+ window.parent.postMessage({
720
+ type: "ow:schedule-connected",
721
+ schedule: { id: schedule.id, name: schedule.name },
722
+ insertAfter
723
+ }, "*");
724
+ } else {
725
+ window.parent.postMessage({ type: "ow:scheduling-not-connected", insertAfter }, "*");
726
+ }
764
727
  };
765
728
  if (!inEditor && !loading && !schedule) return null;
766
729
  const sectionId = `scheduling-${insertAfter}`;
@@ -803,19 +766,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
803
766
  ),
804
767
  /* @__PURE__ */ jsxs2("div", { className: "max-w-[1280px] mx-auto flex flex-col items-center gap-16", children: [
805
768
  /* @__PURE__ */ jsxs2("div", { className: "flex flex-col items-center gap-4", children: [
806
- /* @__PURE__ */ jsx2(
807
- "h2",
808
- {
809
- className: "font-display text-center m-0 text-(--color-dark,#200C02)",
810
- style: {
811
- fontSize: "var(--fs-section-h2, clamp(40px, 4.4vw, 64px))",
812
- fontWeight: "var(--font-weight-heading, 400)",
813
- lineHeight: 1.05,
814
- letterSpacing: "-0.02em"
815
- },
816
- children: schedule?.name ?? "Book an appointment"
817
- }
818
- ),
769
+ /* @__PURE__ */ jsx2("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" }),
819
770
  schedule?.description && /* @__PURE__ */ jsx2("p", { className: "font-body text-body text-center m-0 text-(--color-accent,#A89B83)", children: schedule.description })
820
771
  ] }),
821
772
  /* @__PURE__ */ jsxs2("div", { className: "w-full flex flex-col items-end gap-3", children: [
@@ -4493,7 +4444,7 @@ function getChromeStyle(state) {
4493
4444
  case "dragging":
4494
4445
  return {
4495
4446
  border: `2px solid ${PRIMARY}`,
4496
- boxShadow: `${FOCUS_RING}, ${DRAG_SHADOW}`
4447
+ boxShadow: DRAG_SHADOW
4497
4448
  };
4498
4449
  default:
4499
4450
  return {};
@@ -4509,8 +4460,6 @@ function ItemInteractionLayer({
4509
4460
  dragHandleLabel = "Reorder item",
4510
4461
  onDragHandleDragStart,
4511
4462
  onDragHandleDragEnd,
4512
- onItemPointerDown,
4513
- onItemClick,
4514
4463
  chromeGap = 6,
4515
4464
  className
4516
4465
  }) {
@@ -4518,8 +4467,7 @@ function ItemInteractionLayer({
4518
4467
  const isActive = state === "active-top" || state === "active-bottom";
4519
4468
  const isDragging = state === "dragging";
4520
4469
  const showToolbar = isActive && toolbar;
4521
- const showDragHandle = (isActive || isDragging) && showHandle;
4522
- const itemDragEnabled = isActive && showHandle && !isDragging && !dragDisabled;
4470
+ const showDragHandle = isActive && showHandle && !isDragging;
4523
4471
  return /* @__PURE__ */ jsxs4(
4524
4472
  "div",
4525
4473
  {
@@ -4544,28 +4492,11 @@ function ItemInteractionLayer({
4544
4492
  style: getChromeStyle(state)
4545
4493
  }
4546
4494
  ),
4547
- itemDragEnabled && /* @__PURE__ */ jsx9(
4548
- "div",
4549
- {
4550
- "data-ohw-item-drag-surface": "",
4551
- className: "pointer-events-auto absolute inset-0 cursor-grab rounded-lg active:cursor-grabbing",
4552
- onPointerDown: (e) => {
4553
- if (e.button !== 0) return;
4554
- onItemPointerDown?.(e);
4555
- },
4556
- onClick: (e) => {
4557
- e.preventDefault();
4558
- e.stopPropagation();
4559
- onItemClick?.(e.clientX, e.clientY);
4560
- }
4561
- }
4562
- ),
4563
4495
  showDragHandle && /* @__PURE__ */ jsx9(
4564
4496
  "div",
4565
4497
  {
4566
4498
  "data-ohw-drag-handle-container": "",
4567
- className: "pointer-events-auto absolute left-0 top-1/2 z-10 -translate-x-[calc(100%+7px)] -translate-y-1/2",
4568
- style: isDragging ? { visibility: "hidden" } : void 0,
4499
+ className: "pointer-events-auto absolute left-0 top-1/2 -translate-x-[calc(100%+7px)] -translate-y-1/2",
4569
4500
  children: /* @__PURE__ */ jsx9(
4570
4501
  DragHandle,
4571
4502
  {
@@ -4788,12 +4719,15 @@ function MediaOverlay({
4788
4719
  className: "flex items-center justify-center cursor-pointer",
4789
4720
  style: {
4790
4721
  ...box,
4791
- // Keep the full-size visual overlay click-through so carousel controls and editable
4792
- // content underneath remain interactive. The Replace button opts back in below.
4793
- pointerEvents: "none",
4722
+ // When text overlays this media, let clicks fall THROUGH to the text underneath. In the
4723
+ // parent this needed a whole `ow:click-at` round-trip to re-hit-test inside the iframe;
4724
+ // in-document, pointer-events does it natively. The button below opts back in, so
4725
+ // Replace still works.
4726
+ pointerEvents: hover.hasTextOverlap ? "none" : "auto",
4794
4727
  boxShadow: "inset 0 0 0 1.5px var(--color-primary)",
4795
4728
  background: "color-mix(in srgb, var(--color-primary) 20%, transparent)"
4796
4729
  },
4730
+ onClick: () => onReplace(hover.key),
4797
4731
  children: /* @__PURE__ */ jsxs5(
4798
4732
  Button,
4799
4733
  {
@@ -4818,61 +4752,6 @@ function MediaOverlay({
4818
4752
  ] });
4819
4753
  }
4820
4754
 
4821
- // src/ui/CarouselOverlay.tsx
4822
- import { GalleryHorizontal } from "lucide-react";
4823
- import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
4824
- var OVERLAY_BUTTON_STYLE2 = {
4825
- pointerEvents: "auto",
4826
- fontFamily: "Inter, sans-serif",
4827
- fontSize: 12,
4828
- color: "#000"
4829
- };
4830
- function CarouselOverlay({
4831
- hover,
4832
- onEdit
4833
- }) {
4834
- const { rect } = hover;
4835
- return /* @__PURE__ */ jsx12(
4836
- "div",
4837
- {
4838
- "data-ohw-bridge": "",
4839
- "data-ohw-carousel-overlay": "",
4840
- className: "flex cursor-pointer items-center justify-center",
4841
- style: {
4842
- position: "fixed",
4843
- top: rect.top,
4844
- left: rect.left,
4845
- width: rect.width,
4846
- height: rect.height,
4847
- zIndex: 2147483646,
4848
- pointerEvents: "auto",
4849
- boxShadow: "inset 0 0 0 1.5px var(--color-primary)",
4850
- background: "color-mix(in srgb, var(--color-primary) 20%, transparent)"
4851
- },
4852
- onClick: () => onEdit(hover.key),
4853
- children: /* @__PURE__ */ jsxs6(
4854
- Button,
4855
- {
4856
- "data-ohw-carousel-overlay": "",
4857
- variant: "outline",
4858
- size: "sm",
4859
- className: "cursor-pointer gap-1.5 hover:bg-background",
4860
- style: OVERLAY_BUTTON_STYLE2,
4861
- onMouseDown: (e) => e.preventDefault(),
4862
- onClick: (e) => {
4863
- e.stopPropagation();
4864
- onEdit(hover.key);
4865
- },
4866
- children: [
4867
- /* @__PURE__ */ jsx12(GalleryHorizontal, { size: 14 }),
4868
- "Edit gallery"
4869
- ]
4870
- }
4871
- )
4872
- }
4873
- );
4874
- }
4875
-
4876
4755
  // src/OhhwellsBridge.tsx
4877
4756
  import { createPortal as createPortal2 } from "react-dom";
4878
4757
  import { usePathname as usePathname2, useRouter as useRouter2, useSearchParams } from "next/navigation";
@@ -5159,22 +5038,22 @@ import { useEffect as useEffect6 } from "react";
5159
5038
  import * as React7 from "react";
5160
5039
  import { Dialog as DialogPrimitive } from "radix-ui";
5161
5040
  import { X } from "lucide-react";
5162
- import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
5041
+ import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
5163
5042
  function Dialog2({
5164
5043
  ...props
5165
5044
  }) {
5166
- return /* @__PURE__ */ jsx13(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
5045
+ return /* @__PURE__ */ jsx12(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
5167
5046
  }
5168
5047
  function DialogPortal({
5169
5048
  ...props
5170
5049
  }) {
5171
- return /* @__PURE__ */ jsx13(DialogPrimitive.Portal, { ...props });
5050
+ return /* @__PURE__ */ jsx12(DialogPrimitive.Portal, { ...props });
5172
5051
  }
5173
5052
  function DialogOverlay({
5174
5053
  className,
5175
5054
  ...props
5176
5055
  }) {
5177
- return /* @__PURE__ */ jsx13(
5056
+ return /* @__PURE__ */ jsx12(
5178
5057
  DialogPrimitive.Overlay,
5179
5058
  {
5180
5059
  "data-slot": "dialog-overlay",
@@ -5187,9 +5066,9 @@ function DialogOverlay({
5187
5066
  var DialogContent = React7.forwardRef(
5188
5067
  ({ className, children, showCloseButton = true, container, ...props }, ref) => {
5189
5068
  const positionMode = container ? "absolute" : "fixed";
5190
- return /* @__PURE__ */ jsxs7(DialogPortal, { container: container ?? void 0, children: [
5191
- /* @__PURE__ */ jsx13(DialogOverlay, { className: cn(positionMode, "inset-0") }),
5192
- /* @__PURE__ */ jsxs7(
5069
+ return /* @__PURE__ */ jsxs6(DialogPortal, { container: container ?? void 0, children: [
5070
+ /* @__PURE__ */ jsx12(DialogOverlay, { className: cn(positionMode, "inset-0") }),
5071
+ /* @__PURE__ */ jsxs6(
5193
5072
  DialogPrimitive.Content,
5194
5073
  {
5195
5074
  ref,
@@ -5205,13 +5084,13 @@ var DialogContent = React7.forwardRef(
5205
5084
  ...props,
5206
5085
  children: [
5207
5086
  children,
5208
- showCloseButton ? /* @__PURE__ */ jsx13(
5087
+ showCloseButton ? /* @__PURE__ */ jsx12(
5209
5088
  DialogPrimitive.Close,
5210
5089
  {
5211
5090
  type: "button",
5212
5091
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
5213
5092
  "aria-label": "Close",
5214
- children: /* @__PURE__ */ jsx13(X, { size: 16, "aria-hidden": true })
5093
+ children: /* @__PURE__ */ jsx12(X, { size: 16, "aria-hidden": true })
5215
5094
  }
5216
5095
  ) : null
5217
5096
  ]
@@ -5225,13 +5104,13 @@ function DialogHeader({
5225
5104
  className,
5226
5105
  ...props
5227
5106
  }) {
5228
- return /* @__PURE__ */ jsx13("div", { className: cn("flex flex-col gap-1.5", className), ...props });
5107
+ return /* @__PURE__ */ jsx12("div", { className: cn("flex flex-col gap-1.5", className), ...props });
5229
5108
  }
5230
5109
  function DialogFooter({
5231
5110
  className,
5232
5111
  ...props
5233
5112
  }) {
5234
- return /* @__PURE__ */ jsx13(
5113
+ return /* @__PURE__ */ jsx12(
5235
5114
  "div",
5236
5115
  {
5237
5116
  className: cn("flex items-center justify-end gap-2", className),
@@ -5239,7 +5118,7 @@ function DialogFooter({
5239
5118
  }
5240
5119
  );
5241
5120
  }
5242
- var DialogTitle = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
5121
+ var DialogTitle = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx12(
5243
5122
  DialogPrimitive.Title,
5244
5123
  {
5245
5124
  ref,
@@ -5251,7 +5130,7 @@ var DialogTitle = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE
5251
5130
  }
5252
5131
  ));
5253
5132
  DialogTitle.displayName = DialogPrimitive.Title.displayName;
5254
- var DialogDescription = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
5133
+ var DialogDescription = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx12(
5255
5134
  DialogPrimitive.Description,
5256
5135
  {
5257
5136
  ref,
@@ -5267,19 +5146,19 @@ import { Info, X as X3 } from "lucide-react";
5267
5146
 
5268
5147
  // src/ui/link-modal/DestinationBreadcrumb.tsx
5269
5148
  import { ArrowRight, File, GalleryVertical } from "lucide-react";
5270
- import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
5149
+ import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
5271
5150
  function DestinationBreadcrumb({
5272
5151
  pageTitle,
5273
5152
  sectionLabel
5274
5153
  }) {
5275
- return /* @__PURE__ */ jsxs8("div", { className: "flex w-full flex-col gap-2", children: [
5276
- /* @__PURE__ */ jsx14("p", { className: "text-sm font-medium! text-foreground m-0", children: "Destination" }),
5277
- /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3", children: [
5278
- /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
5279
- /* @__PURE__ */ jsx14(File, { size: 16, className: "shrink-0 text-foreground", "aria-hidden": true }),
5280
- /* @__PURE__ */ jsx14("span", { className: "text-sm font-medium leading-none text-foreground!", children: pageTitle })
5154
+ return /* @__PURE__ */ jsxs7("div", { className: "flex w-full flex-col gap-2", children: [
5155
+ /* @__PURE__ */ jsx13("p", { className: "text-sm font-medium! text-foreground m-0", children: "Destination" }),
5156
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-3", children: [
5157
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
5158
+ /* @__PURE__ */ jsx13(File, { size: 16, className: "shrink-0 text-foreground", "aria-hidden": true }),
5159
+ /* @__PURE__ */ jsx13("span", { className: "text-sm font-medium leading-none text-foreground!", children: pageTitle })
5281
5160
  ] }),
5282
- /* @__PURE__ */ jsx14(
5161
+ /* @__PURE__ */ jsx13(
5283
5162
  ArrowRight,
5284
5163
  {
5285
5164
  size: 16,
@@ -5287,8 +5166,8 @@ function DestinationBreadcrumb({
5287
5166
  "aria-hidden": true
5288
5167
  }
5289
5168
  ),
5290
- /* @__PURE__ */ jsxs8("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
5291
- /* @__PURE__ */ jsx14(
5169
+ /* @__PURE__ */ jsxs7("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
5170
+ /* @__PURE__ */ jsx13(
5292
5171
  GalleryVertical,
5293
5172
  {
5294
5173
  size: 16,
@@ -5296,7 +5175,7 @@ function DestinationBreadcrumb({
5296
5175
  "aria-hidden": true
5297
5176
  }
5298
5177
  ),
5299
- /* @__PURE__ */ jsx14("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
5178
+ /* @__PURE__ */ jsx13("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
5300
5179
  ] })
5301
5180
  ] })
5302
5181
  ] });
@@ -5304,22 +5183,22 @@ function DestinationBreadcrumb({
5304
5183
 
5305
5184
  // src/ui/link-modal/SectionTreeItem.tsx
5306
5185
  import { GalleryVertical as GalleryVertical2 } from "lucide-react";
5307
- import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
5186
+ import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
5308
5187
  function SectionTreeItem({
5309
5188
  section,
5310
5189
  onSelect,
5311
5190
  selected
5312
5191
  }) {
5313
5192
  const interactive = Boolean(onSelect);
5314
- return /* @__PURE__ */ jsxs9("div", { className: "flex h-9 w-full items-end pl-3", children: [
5315
- /* @__PURE__ */ jsx15(
5193
+ return /* @__PURE__ */ jsxs8("div", { className: "flex h-9 w-full items-end pl-3", children: [
5194
+ /* @__PURE__ */ jsx14(
5316
5195
  "div",
5317
5196
  {
5318
5197
  className: "mr-[-1px] h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
5319
5198
  "aria-hidden": true
5320
5199
  }
5321
5200
  ),
5322
- /* @__PURE__ */ jsxs9(
5201
+ /* @__PURE__ */ jsxs8(
5323
5202
  "div",
5324
5203
  {
5325
5204
  role: interactive ? "button" : void 0,
@@ -5337,7 +5216,7 @@ function SectionTreeItem({
5337
5216
  interactive && selected && "border-primary"
5338
5217
  ),
5339
5218
  children: [
5340
- /* @__PURE__ */ jsx15(
5219
+ /* @__PURE__ */ jsx14(
5341
5220
  GalleryVertical2,
5342
5221
  {
5343
5222
  size: 16,
@@ -5345,7 +5224,7 @@ function SectionTreeItem({
5345
5224
  "aria-hidden": true
5346
5225
  }
5347
5226
  ),
5348
- /* @__PURE__ */ jsx15("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
5227
+ /* @__PURE__ */ jsx14("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
5349
5228
  ]
5350
5229
  }
5351
5230
  )
@@ -5357,10 +5236,10 @@ import { useEffect as useEffect3, useId as useId2, useRef as useRef3, useState a
5357
5236
 
5358
5237
  // src/ui/input.tsx
5359
5238
  import * as React8 from "react";
5360
- import { jsx as jsx16 } from "react/jsx-runtime";
5239
+ import { jsx as jsx15 } from "react/jsx-runtime";
5361
5240
  var Input = React8.forwardRef(
5362
5241
  ({ className, type, ...props }, ref) => {
5363
- return /* @__PURE__ */ jsx16(
5242
+ return /* @__PURE__ */ jsx15(
5364
5243
  "input",
5365
5244
  {
5366
5245
  type,
@@ -5379,9 +5258,9 @@ Input.displayName = "Input";
5379
5258
 
5380
5259
  // src/ui/label.tsx
5381
5260
  import { Label as LabelPrimitive } from "radix-ui";
5382
- import { jsx as jsx17 } from "react/jsx-runtime";
5261
+ import { jsx as jsx16 } from "react/jsx-runtime";
5383
5262
  function Label({ className, ...props }) {
5384
- return /* @__PURE__ */ jsx17(
5263
+ return /* @__PURE__ */ jsx16(
5385
5264
  LabelPrimitive.Root,
5386
5265
  {
5387
5266
  "data-slot": "label",
@@ -5393,11 +5272,11 @@ function Label({ className, ...props }) {
5393
5272
 
5394
5273
  // src/ui/link-modal/UrlOrPageInput.tsx
5395
5274
  import { ChevronDown, File as File2, X as X2 } from "lucide-react";
5396
- import { jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
5275
+ import { jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
5397
5276
  function FieldChevron({
5398
5277
  onClick
5399
5278
  }) {
5400
- return /* @__PURE__ */ jsx18(
5279
+ return /* @__PURE__ */ jsx17(
5401
5280
  "button",
5402
5281
  {
5403
5282
  type: "button",
@@ -5405,7 +5284,7 @@ function FieldChevron({
5405
5284
  onClick,
5406
5285
  "aria-label": "Open page list",
5407
5286
  tabIndex: -1,
5408
- children: /* @__PURE__ */ jsx18(ChevronDown, { size: 16 })
5287
+ children: /* @__PURE__ */ jsx17(ChevronDown, { size: 16 })
5409
5288
  }
5410
5289
  );
5411
5290
  }
@@ -5466,11 +5345,11 @@ function UrlOrPageInput({
5466
5345
  "data-ohw-link-field flex h-[36px] w-full items-center overflow-hidden rounded-md border bg-background pl-3 pr-3 py-2 outline-none transition-[border-color,box-shadow]",
5467
5346
  urlError ? "border-destructive shadow-[0_0_0_1px_var(--ohw-destructive)]" : isFocused ? "border-primary shadow-[0_0_0_1px_var(--ohw-primary)]" : "border-input"
5468
5347
  );
5469
- return /* @__PURE__ */ jsxs10("div", { className: "flex w-full flex-col gap-2 p-0", children: [
5470
- /* @__PURE__ */ jsx18(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
5471
- /* @__PURE__ */ jsxs10("div", { ref: rootRef, className: "relative w-full", children: [
5472
- /* @__PURE__ */ jsxs10("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
5473
- selectedPage ? /* @__PURE__ */ jsx18("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ jsx18(
5348
+ return /* @__PURE__ */ jsxs9("div", { className: "flex w-full flex-col gap-2 p-0", children: [
5349
+ /* @__PURE__ */ jsx17(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
5350
+ /* @__PURE__ */ jsxs9("div", { ref: rootRef, className: "relative w-full", children: [
5351
+ /* @__PURE__ */ jsxs9("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
5352
+ selectedPage ? /* @__PURE__ */ jsx17("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ jsx17(
5474
5353
  File2,
5475
5354
  {
5476
5355
  size: 16,
@@ -5478,7 +5357,7 @@ function UrlOrPageInput({
5478
5357
  "aria-hidden": true
5479
5358
  }
5480
5359
  ) }) : null,
5481
- readOnly ? /* @__PURE__ */ jsx18("span", { className: "min-w-0 flex-1 truncate text-sm leading-5 text-foreground", children: selectedPage?.title ?? value }) : /* @__PURE__ */ jsx18(
5360
+ readOnly ? /* @__PURE__ */ jsx17("span", { className: "min-w-0 flex-1 truncate text-sm leading-5 text-foreground", children: selectedPage?.title ?? value }) : /* @__PURE__ */ jsx17(
5482
5361
  Input,
5483
5362
  {
5484
5363
  ref: inputRef,
@@ -5504,7 +5383,7 @@ function UrlOrPageInput({
5504
5383
  )
5505
5384
  }
5506
5385
  ),
5507
- selectedPage && !readOnly ? /* @__PURE__ */ jsx18(
5386
+ selectedPage && !readOnly ? /* @__PURE__ */ jsx17(
5508
5387
  "button",
5509
5388
  {
5510
5389
  type: "button",
@@ -5512,26 +5391,26 @@ function UrlOrPageInput({
5512
5391
  onMouseDown: clearSelection,
5513
5392
  "aria-label": "Clear selected page",
5514
5393
  tabIndex: -1,
5515
- children: /* @__PURE__ */ jsx18(X2, { size: 16, "aria-hidden": true })
5394
+ children: /* @__PURE__ */ jsx17(X2, { size: 16, "aria-hidden": true })
5516
5395
  }
5517
5396
  ) : null,
5518
- !readOnly ? /* @__PURE__ */ jsx18(FieldChevron, { onClick: toggleDropdown }) : null
5397
+ !readOnly ? /* @__PURE__ */ jsx17(FieldChevron, { onClick: toggleDropdown }) : null
5519
5398
  ] }),
5520
- dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ jsx18(
5399
+ dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ jsx17(
5521
5400
  "div",
5522
5401
  {
5523
5402
  "data-ohw-link-page-dropdown": "",
5524
5403
  className: "absolute left-0 right-0 top-[calc(100%+4px)] z-50 max-h-48 overflow-auto rounded-lg border border-border bg-popover py-1 shadow-lg",
5525
5404
  onMouseDown: (e) => e.preventDefault(),
5526
- children: filteredPages.map((page) => /* @__PURE__ */ jsxs10(
5405
+ children: filteredPages.map((page) => /* @__PURE__ */ jsxs9(
5527
5406
  "button",
5528
5407
  {
5529
5408
  type: "button",
5530
5409
  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",
5531
5410
  onClick: () => onPageSelect(page),
5532
5411
  children: [
5533
- /* @__PURE__ */ jsx18(File2, { size: 16, className: "shrink-0", "aria-hidden": true }),
5534
- /* @__PURE__ */ jsx18("span", { className: "truncate", children: page.title })
5412
+ /* @__PURE__ */ jsx17(File2, { size: 16, className: "shrink-0", "aria-hidden": true }),
5413
+ /* @__PURE__ */ jsx17("span", { className: "truncate", children: page.title })
5535
5414
  ]
5536
5415
  },
5537
5416
  page.path
@@ -5539,34 +5418,34 @@ function UrlOrPageInput({
5539
5418
  }
5540
5419
  ) : null
5541
5420
  ] }),
5542
- urlError ? /* @__PURE__ */ jsx18("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
5421
+ urlError ? /* @__PURE__ */ jsx17("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
5543
5422
  ] });
5544
5423
  }
5545
5424
 
5546
5425
  // src/ui/link-modal/LinkEditorPanel.tsx
5547
- import { Fragment as Fragment3, jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
5426
+ import { Fragment as Fragment3, jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
5548
5427
  function LinkEditorPanel({ state, onClose }) {
5549
5428
  const isCancel = state.secondaryLabel === "Cancel" || state.secondaryLabel === "Back to sections";
5550
- return /* @__PURE__ */ jsxs11(Fragment3, { children: [
5551
- /* @__PURE__ */ jsx19(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx19(
5429
+ return /* @__PURE__ */ jsxs10(Fragment3, { children: [
5430
+ /* @__PURE__ */ jsx18(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx18(
5552
5431
  "button",
5553
5432
  {
5554
5433
  type: "button",
5555
5434
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50 h-7",
5556
5435
  "aria-label": "Close",
5557
5436
  onClick: onClose,
5558
- children: /* @__PURE__ */ jsx19(X3, { size: 16, "aria-hidden": true })
5437
+ children: /* @__PURE__ */ jsx18(X3, { size: 16, "aria-hidden": true })
5559
5438
  }
5560
5439
  ) }),
5561
- /* @__PURE__ */ jsx19(DialogHeader, { className: "w-full gap-1.5 p-6 pr-12", children: /* @__PURE__ */ jsx19(DialogTitle, { className: "m-0 w-full break-words", children: state.title }) }),
5562
- /* @__PURE__ */ jsxs11("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
5563
- state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ jsx19(
5440
+ /* @__PURE__ */ jsx18(DialogHeader, { className: "w-full gap-1.5 p-6 pr-12", children: /* @__PURE__ */ jsx18(DialogTitle, { className: "m-0 w-full break-words", children: state.title }) }),
5441
+ /* @__PURE__ */ jsxs10("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
5442
+ state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ jsx18(
5564
5443
  DestinationBreadcrumb,
5565
5444
  {
5566
5445
  pageTitle: state.selectedPage.title,
5567
5446
  sectionLabel: state.selectedSection.label
5568
5447
  }
5569
- ) : /* @__PURE__ */ jsx19(
5448
+ ) : /* @__PURE__ */ jsx18(
5570
5449
  UrlOrPageInput,
5571
5450
  {
5572
5451
  value: state.searchValue,
@@ -5579,8 +5458,8 @@ function LinkEditorPanel({ state, onClose }) {
5579
5458
  urlError: state.urlError
5580
5459
  }
5581
5460
  ),
5582
- state.showChooseSection ? /* @__PURE__ */ jsxs11("div", { className: "flex flex-col justify-center gap-2", children: [
5583
- /* @__PURE__ */ jsx19(
5461
+ state.showChooseSection ? /* @__PURE__ */ jsxs10("div", { className: "flex flex-col justify-center gap-2", children: [
5462
+ /* @__PURE__ */ jsx18(
5584
5463
  Button,
5585
5464
  {
5586
5465
  type: "button",
@@ -5591,15 +5470,15 @@ function LinkEditorPanel({ state, onClose }) {
5591
5470
  children: "Choose a section"
5592
5471
  }
5593
5472
  ),
5594
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
5595
- /* @__PURE__ */ jsx19(Info, { size: 16, className: "shrink-0", "aria-hidden": true }),
5596
- /* @__PURE__ */ jsx19("span", { children: "Pick a section this link should scroll to." })
5473
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
5474
+ /* @__PURE__ */ jsx18(Info, { size: 16, className: "shrink-0", "aria-hidden": true }),
5475
+ /* @__PURE__ */ jsx18("span", { children: "Pick a section this link should scroll to." })
5597
5476
  ] })
5598
5477
  ] }) : null,
5599
- state.showSectionRow && state.selectedSection ? /* @__PURE__ */ jsx19(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
5478
+ state.showSectionRow && state.selectedSection ? /* @__PURE__ */ jsx18(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
5600
5479
  ] }),
5601
- /* @__PURE__ */ jsxs11(DialogFooter, { className: "w-full px-6 pb-6", children: [
5602
- /* @__PURE__ */ jsx19(
5480
+ /* @__PURE__ */ jsxs10(DialogFooter, { className: "w-full px-6 pb-6", children: [
5481
+ /* @__PURE__ */ jsx18(
5603
5482
  Button,
5604
5483
  {
5605
5484
  type: "button",
@@ -5614,7 +5493,7 @@ function LinkEditorPanel({ state, onClose }) {
5614
5493
  children: state.secondaryLabel
5615
5494
  }
5616
5495
  ),
5617
- /* @__PURE__ */ jsx19(
5496
+ /* @__PURE__ */ jsx18(
5618
5497
  Button,
5619
5498
  {
5620
5499
  type: "button",
@@ -5633,11 +5512,11 @@ function LinkEditorPanel({ state, onClose }) {
5633
5512
  }
5634
5513
 
5635
5514
  // src/ui/link-modal/SectionPickerOverlay.tsx
5636
- import { useCallback as useCallback2, useEffect as useEffect4, useMemo as useMemo2, useRef as useRef4, useState as useState4 } from "react";
5515
+ import { useCallback, useEffect as useEffect4, useMemo as useMemo2, useRef as useRef4, useState as useState4 } from "react";
5637
5516
  import { createPortal } from "react-dom";
5638
5517
  import { ArrowLeft, Check } from "lucide-react";
5639
5518
  import { usePathname, useRouter } from "next/navigation";
5640
- import { jsx as jsx20, jsxs as jsxs12 } from "react/jsx-runtime";
5519
+ import { jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
5641
5520
  var DIM_OVERLAY = "rgba(0, 0, 0, 0.45)";
5642
5521
  function rectsEqual(a, b) {
5643
5522
  if (a.size !== b.size) return false;
@@ -5764,7 +5643,7 @@ function SectionPickerOverlay({
5764
5643
  );
5765
5644
  sectionIdsRef.current = sectionIds;
5766
5645
  const rects = useSectionRects(sectionIdsKey, isOnTargetPage);
5767
- const applyHoverAt = useCallback2(
5646
+ const applyHoverAt = useCallback(
5768
5647
  (x, y, liveRects) => {
5769
5648
  const ids = sectionIdsRef.current;
5770
5649
  const map = liveRects ?? readSectionRects(ids);
@@ -5844,7 +5723,7 @@ function SectionPickerOverlay({
5844
5723
  window.removeEventListener("message", onPointerSync);
5845
5724
  };
5846
5725
  }, [rects, applyHoverAt]);
5847
- const handleSelect = useCallback2(
5726
+ const handleSelect = useCallback(
5848
5727
  (section) => {
5849
5728
  if (selectedId) return;
5850
5729
  setSelectedId(section.id);
@@ -5866,7 +5745,7 @@ function SectionPickerOverlay({
5866
5745
  const portalRoot = typeof document !== "undefined" ? document.querySelector("[data-ohw-bridge-root]") ?? document.body : null;
5867
5746
  if (!portalRoot) return null;
5868
5747
  return createPortal(
5869
- /* @__PURE__ */ jsxs12(
5748
+ /* @__PURE__ */ jsxs11(
5870
5749
  "div",
5871
5750
  {
5872
5751
  "data-ohw-section-picker": "",
@@ -5876,12 +5755,12 @@ function SectionPickerOverlay({
5876
5755
  role: "dialog",
5877
5756
  "aria-label": "Choose a section",
5878
5757
  children: [
5879
- /* @__PURE__ */ jsx20(
5758
+ /* @__PURE__ */ jsx19(
5880
5759
  "div",
5881
5760
  {
5882
5761
  className: "pointer-events-auto fixed left-5 z-[2]",
5883
5762
  style: { top: chromeClip.top + 20 },
5884
- children: /* @__PURE__ */ jsxs12(
5763
+ children: /* @__PURE__ */ jsxs11(
5885
5764
  Button,
5886
5765
  {
5887
5766
  type: "button",
@@ -5890,14 +5769,14 @@ function SectionPickerOverlay({
5890
5769
  className: "h-8 min-w-0 gap-1 border-border bg-background px-2 py-1.5 shadow-sm hover:bg-muted cursor-pointer",
5891
5770
  onClick: onBack,
5892
5771
  children: [
5893
- /* @__PURE__ */ jsx20(ArrowLeft, { className: "size-4 shrink-0", "aria-hidden": true }),
5772
+ /* @__PURE__ */ jsx19(ArrowLeft, { className: "size-4 shrink-0", "aria-hidden": true }),
5894
5773
  "Back"
5895
5774
  ]
5896
5775
  }
5897
5776
  )
5898
5777
  }
5899
5778
  ),
5900
- /* @__PURE__ */ jsx20(
5779
+ /* @__PURE__ */ jsx19(
5901
5780
  "div",
5902
5781
  {
5903
5782
  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",
@@ -5910,7 +5789,7 @@ function SectionPickerOverlay({
5910
5789
  children: "Click on section to select"
5911
5790
  }
5912
5791
  ),
5913
- !isOnTargetPage ? /* @__PURE__ */ jsx20(
5792
+ !isOnTargetPage ? /* @__PURE__ */ jsx19(
5914
5793
  "div",
5915
5794
  {
5916
5795
  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",
@@ -5918,14 +5797,14 @@ function SectionPickerOverlay({
5918
5797
  children: "Loading page preview\u2026"
5919
5798
  }
5920
5799
  ) : null,
5921
- isOnTargetPage && liveSections.length === 0 ? /* @__PURE__ */ jsx20("div", { className: "pointer-events-auto fixed inset-0 z-[1] flex items-center justify-center bg-muted/40", children: /* @__PURE__ */ jsx20("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." }) }) : null,
5800
+ isOnTargetPage && liveSections.length === 0 ? /* @__PURE__ */ jsx19("div", { className: "pointer-events-auto fixed inset-0 z-[1] flex items-center justify-center bg-muted/40", children: /* @__PURE__ */ jsx19("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." }) }) : null,
5922
5801
  isOnTargetPage ? liveSections.map((section) => {
5923
5802
  const rect = rects.get(section.id);
5924
5803
  if (!rect || rect.width <= 0 || rect.height <= 0) return null;
5925
5804
  const isSelected = selectedId === section.id;
5926
5805
  const isHovered = hoveredId === section.id;
5927
5806
  const isLit = isSelected || isHovered;
5928
- return /* @__PURE__ */ jsxs12(
5807
+ return /* @__PURE__ */ jsxs11(
5929
5808
  "button",
5930
5809
  {
5931
5810
  type: "button",
@@ -5940,7 +5819,7 @@ function SectionPickerOverlay({
5940
5819
  "aria-label": `Select section ${section.label}`,
5941
5820
  onClick: () => handleSelect(section),
5942
5821
  children: [
5943
- isLit ? /* @__PURE__ */ jsx20(
5822
+ isLit ? /* @__PURE__ */ jsx19(
5944
5823
  "span",
5945
5824
  {
5946
5825
  className: "pointer-events-none absolute",
@@ -5953,13 +5832,13 @@ function SectionPickerOverlay({
5953
5832
  "aria-hidden": true
5954
5833
  }
5955
5834
  ) : null,
5956
- isSelected ? /* @__PURE__ */ jsx20(
5835
+ isSelected ? /* @__PURE__ */ jsx19(
5957
5836
  "span",
5958
5837
  {
5959
5838
  className: "absolute right-3 top-3 flex size-8 items-center justify-center rounded-full text-white",
5960
5839
  style: { backgroundColor: "var(--ohw-primary, #0885fe)" },
5961
5840
  "aria-hidden": true,
5962
- children: /* @__PURE__ */ jsx20(Check, { className: "size-5" })
5841
+ children: /* @__PURE__ */ jsx19(Check, { className: "size-5" })
5963
5842
  }
5964
5843
  ) : null
5965
5844
  ]
@@ -5975,7 +5854,7 @@ function SectionPickerOverlay({
5975
5854
  }
5976
5855
 
5977
5856
  // src/ui/link-modal/useLinkModalState.ts
5978
- import { useCallback as useCallback3, useEffect as useEffect5, useMemo as useMemo3, useState as useState5 } from "react";
5857
+ import { useCallback as useCallback2, useEffect as useEffect5, useMemo as useMemo3, useState as useState5 } from "react";
5979
5858
  function useLinkModalState({
5980
5859
  open,
5981
5860
  mode,
@@ -5994,7 +5873,7 @@ function useLinkModalState({
5994
5873
  const [step, setStep] = useState5("input");
5995
5874
  const [dropdownOpen, setDropdownOpen] = useState5(false);
5996
5875
  const [urlError, setUrlError] = useState5("");
5997
- const reset = useCallback3(() => {
5876
+ const reset = useCallback2(() => {
5998
5877
  setSearchValue("");
5999
5878
  setSelectedPage(null);
6000
5879
  setSelectedSection(null);
@@ -6139,7 +6018,7 @@ function useLinkModalState({
6139
6018
  }
6140
6019
 
6141
6020
  // src/ui/link-modal/LinkPopover.tsx
6142
- import { Fragment as Fragment4, jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
6021
+ import { Fragment as Fragment4, jsx as jsx20, jsxs as jsxs12 } from "react/jsx-runtime";
6143
6022
  function postToParent(data) {
6144
6023
  window.parent?.postMessage(data, "*");
6145
6024
  }
@@ -6235,15 +6114,15 @@ function LinkPopover({
6235
6114
  );
6236
6115
  };
6237
6116
  }, [open, sectionPickerActive]);
6238
- return /* @__PURE__ */ jsxs13(Fragment4, { children: [
6239
- /* @__PURE__ */ jsx21(
6117
+ return /* @__PURE__ */ jsxs12(Fragment4, { children: [
6118
+ /* @__PURE__ */ jsx20(
6240
6119
  Dialog2,
6241
6120
  {
6242
6121
  open: open && !sectionPickerActive,
6243
6122
  onOpenChange: (next) => {
6244
6123
  if (!next) onClose?.();
6245
6124
  },
6246
- children: /* @__PURE__ */ jsx21(
6125
+ children: /* @__PURE__ */ jsx20(
6247
6126
  DialogContent,
6248
6127
  {
6249
6128
  ref: panelRef,
@@ -6253,12 +6132,12 @@ function LinkPopover({
6253
6132
  "data-ohw-bridge": "",
6254
6133
  showCloseButton: false,
6255
6134
  className: "gap-0 p-0 w-full max-w-[448px] pointer-events-auto z-[2147483646] overflow-visible",
6256
- children: /* @__PURE__ */ jsx21(LinkEditorPanel, { state, onClose })
6135
+ children: /* @__PURE__ */ jsx20(LinkEditorPanel, { state, onClose })
6257
6136
  }
6258
6137
  )
6259
6138
  }
6260
6139
  ),
6261
- sectionPickerActive && state.selectedPage ? /* @__PURE__ */ jsx21(
6140
+ sectionPickerActive && state.selectedPage ? /* @__PURE__ */ jsx20(
6262
6141
  SectionPickerOverlay,
6263
6142
  {
6264
6143
  pagePath: state.selectedPage.path,
@@ -6564,412 +6443,15 @@ function insertNavbarItem(href, label, afterAnchor = null) {
6564
6443
  };
6565
6444
  }
6566
6445
 
6567
- // src/lib/footer-items.ts
6568
- var FOOTER_ORDER_KEY = "__ohw_footer_order";
6569
- var FOOTER_HREF_RE = /^footer-(\d+)-(\d+)-href$/;
6570
- function parseFooterHrefKey(key) {
6571
- if (!key) return null;
6572
- const match = key.match(FOOTER_HREF_RE);
6573
- if (!match) return null;
6574
- return { col: parseInt(match[1], 10), item: parseInt(match[2], 10) };
6575
- }
6576
- function isFooterHrefKey(key) {
6577
- return parseFooterHrefKey(key) !== null;
6578
- }
6579
- function getFooterRoot() {
6580
- return document.querySelector('footer[data-ohw-section="footer"], footer');
6581
- }
6582
- function getFooterLinksContainer() {
6583
- return document.querySelector("[data-ohw-footer-links]") ?? document.querySelector(".rb-footer-links");
6584
- }
6585
- function isFooterLinkAnchor(el) {
6586
- if (!el.matches("[data-ohw-href-key]")) return false;
6587
- if (!isFooterHrefKey(el.getAttribute("data-ohw-href-key"))) return false;
6588
- return Boolean(el.querySelector('[data-ohw-editable="text"]'));
6589
- }
6590
- function listFooterColumns() {
6591
- const root = getFooterLinksContainer() ?? getFooterRoot()?.querySelector(".rb-footer-links") ?? null;
6592
- if (!root) return [];
6593
- const explicit = Array.from(root.querySelectorAll(":scope > [data-ohw-footer-col]"));
6594
- if (explicit.length > 0) return explicit;
6595
- return Array.from(root.children).filter((el) => {
6596
- if (!(el instanceof HTMLElement)) return false;
6597
- return Array.from(el.querySelectorAll(":scope > [data-ohw-href-key]")).some(
6598
- isFooterLinkAnchor
6599
- );
6600
- });
6601
- }
6602
- function listFooterLinksInColumn(column) {
6603
- return Array.from(column.querySelectorAll(":scope > [data-ohw-href-key]")).filter(
6604
- isFooterLinkAnchor
6605
- );
6606
- }
6607
- function findFooterColumnForLink(anchor) {
6608
- const columns = listFooterColumns();
6609
- return columns.find((col) => col.contains(anchor)) ?? null;
6610
- }
6611
- function getFooterOrderFromDom() {
6612
- return listFooterColumns().map(
6613
- (col) => listFooterLinksInColumn(col).map((el) => el.getAttribute("data-ohw-href-key")).filter((key) => Boolean(key))
6614
- );
6615
- }
6616
- function findFooterLinkByKey(hrefKey) {
6617
- return document.querySelector(
6618
- `footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
6619
- );
6620
- }
6621
- function syncFooterColumnIndices(columns) {
6622
- columns.forEach((col, index) => {
6623
- const next = String(index);
6624
- if (col.getAttribute("data-ohw-footer-col") !== next) {
6625
- col.setAttribute("data-ohw-footer-col", next);
6626
- }
6627
- });
6628
- }
6629
- function appendChildIfNeeded(parent, child) {
6630
- if (parent.lastElementChild !== child) {
6631
- parent.appendChild(child);
6632
- }
6633
- }
6634
- function insertLinkBeforeNext(col, el, nextEl) {
6635
- if (nextEl) {
6636
- if (el.nextElementSibling !== nextEl) {
6637
- col.insertBefore(el, nextEl);
6638
- }
6639
- return;
6640
- }
6641
- if (col.lastElementChild !== el) {
6642
- col.appendChild(el);
6643
- }
6644
- }
6645
- function applyFooterOrder(order) {
6646
- const container = getFooterLinksContainer();
6647
- if (!container) return;
6648
- const columns = listFooterColumns();
6649
- if (columns.length === 0) return;
6650
- const currentOrder = getFooterOrderFromDom();
6651
- if (ordersEqual(order, currentOrder)) {
6652
- syncFooterColumnIndices(columns);
6653
- return;
6654
- }
6655
- const colCount = Math.max(columns.length, order.length);
6656
- const working = columns.slice(0, colCount);
6657
- for (let i = 0; i < order.length && i < working.length; i++) {
6658
- appendChildIfNeeded(container, working[i]);
6659
- }
6660
- for (let i = order.length; i < working.length; i++) {
6661
- appendChildIfNeeded(container, working[i]);
6662
- }
6663
- const freshColumns = listFooterColumns();
6664
- syncFooterColumnIndices(freshColumns);
6665
- for (let c = 0; c < order.length; c++) {
6666
- const col = freshColumns[c];
6667
- if (!col) continue;
6668
- const colOrder = order[c];
6669
- for (let j = 0; j < colOrder.length; j++) {
6670
- const hrefKey = colOrder[j];
6671
- const el = findFooterLinkByKey(hrefKey);
6672
- if (!el) continue;
6673
- if (el.parentElement !== col) {
6674
- col.appendChild(el);
6675
- }
6676
- const nextKey = colOrder[j + 1];
6677
- const nextEl = nextKey ? findFooterLinkByKey(nextKey) : null;
6678
- insertLinkBeforeNext(col, el, nextEl?.parentElement === col ? nextEl : null);
6679
- }
6680
- }
6681
- }
6682
- function ordersEqual(a, b) {
6683
- if (a.length !== b.length) return false;
6684
- for (let i = 0; i < a.length; i++) {
6685
- const left = a[i];
6686
- const right = b[i];
6687
- if (left.length !== right.length) return false;
6688
- for (let j = 0; j < left.length; j++) {
6689
- if (left[j] !== right[j]) return false;
6690
- }
6691
- }
6692
- return true;
6693
- }
6694
- function planFooterLinkMove(hrefKey, targetColIndex, insertIndex) {
6695
- const order = getFooterOrderFromDom();
6696
- if (targetColIndex < 0 || targetColIndex >= order.length) return null;
6697
- let fromCol = -1;
6698
- let fromIdx = -1;
6699
- for (let c = 0; c < order.length; c++) {
6700
- const idx = order[c].indexOf(hrefKey);
6701
- if (idx >= 0) {
6702
- fromCol = c;
6703
- fromIdx = idx;
6704
- break;
6705
- }
6706
- }
6707
- if (fromCol < 0) return null;
6708
- const next = order.map((col) => [...col]);
6709
- next[fromCol].splice(fromIdx, 1);
6710
- let adjusted = insertIndex;
6711
- if (fromCol === targetColIndex && fromIdx < insertIndex) adjusted -= 1;
6712
- adjusted = Math.max(0, Math.min(adjusted, next[targetColIndex].length));
6713
- next[targetColIndex].splice(adjusted, 0, hrefKey);
6714
- if (ordersEqual(next, order)) return null;
6715
- return next;
6716
- }
6717
- function planFooterColumnMove(fromIndex, toIndex) {
6718
- const order = getFooterOrderFromDom();
6719
- const columns = listFooterColumns();
6720
- if (fromIndex < 0 || fromIndex >= columns.length || toIndex < 0 || toIndex > columns.length) {
6721
- return null;
6722
- }
6723
- if (toIndex === fromIndex || toIndex === fromIndex + 1) return null;
6724
- const nextOrder = order.map((col) => [...col]);
6725
- const [movedOrder] = nextOrder.splice(fromIndex, 1);
6726
- if (!movedOrder) return null;
6727
- let adjusted = toIndex;
6728
- if (fromIndex < toIndex) adjusted -= 1;
6729
- adjusted = Math.max(0, Math.min(adjusted, nextOrder.length));
6730
- nextOrder.splice(adjusted, 0, movedOrder);
6731
- if (ordersEqual(nextOrder, order)) return null;
6732
- return nextOrder;
6733
- }
6734
- function parseFooterOrder(content) {
6735
- const raw = content[FOOTER_ORDER_KEY];
6736
- if (!raw) return null;
6737
- try {
6738
- const parsed = JSON.parse(raw);
6739
- if (!Array.isArray(parsed)) return null;
6740
- return parsed.filter((col) => Array.isArray(col)).map((col) => col.filter((key) => typeof key === "string" && key.length > 0));
6741
- } catch {
6742
- return null;
6743
- }
6744
- }
6745
- function reconcileFooterOrderFromContent(content) {
6746
- const order = parseFooterOrder(content);
6747
- if (!order?.length) return;
6748
- const current = getFooterOrderFromDom();
6749
- if (ordersEqual(order, current)) {
6750
- syncFooterColumnIndices(listFooterColumns());
6751
- return;
6752
- }
6753
- applyFooterOrder(order);
6754
- }
6755
- function buildLinkDropSlots(column, columnIndex) {
6756
- const links = listFooterLinksInColumn(column);
6757
- const colRect = column.getBoundingClientRect();
6758
- const slots = [];
6759
- const barThickness = 3;
6760
- if (links.length === 0) {
6761
- slots.push({
6762
- insertIndex: 0,
6763
- columnIndex,
6764
- left: colRect.left,
6765
- top: colRect.top + colRect.height / 2 - barThickness / 2,
6766
- width: colRect.width,
6767
- height: barThickness,
6768
- direction: "horizontal"
6769
- });
6770
- return slots;
6771
- }
6772
- for (let i = 0; i <= links.length; i++) {
6773
- let top;
6774
- if (i === 0) {
6775
- top = links[0].getBoundingClientRect().top - barThickness / 2;
6776
- } else if (i === links.length) {
6777
- const last = links[links.length - 1].getBoundingClientRect();
6778
- top = last.bottom - barThickness / 2;
6779
- } else {
6780
- const prev = links[i - 1].getBoundingClientRect();
6781
- const next = links[i].getBoundingClientRect();
6782
- top = (prev.bottom + next.top) / 2 - barThickness / 2;
6783
- }
6784
- const widthRef = i === 0 ? links[0].getBoundingClientRect() : i === links.length ? links[links.length - 1].getBoundingClientRect() : links[i].getBoundingClientRect();
6785
- slots.push({
6786
- insertIndex: i,
6787
- columnIndex,
6788
- left: widthRef.left,
6789
- top,
6790
- width: Math.max(widthRef.width, colRect.width * 0.8),
6791
- height: barThickness,
6792
- direction: "horizontal"
6793
- });
6794
- }
6795
- return slots;
6796
- }
6797
- function buildColumnDropSlots() {
6798
- const columns = listFooterColumns();
6799
- const slots = [];
6800
- const barThickness = 3;
6801
- if (columns.length === 0) return slots;
6802
- for (let i = 0; i <= columns.length; i++) {
6803
- let left;
6804
- let height;
6805
- let top;
6806
- if (i === 0) {
6807
- const first = columns[0].getBoundingClientRect();
6808
- left = first.left - barThickness / 2;
6809
- top = first.top;
6810
- height = first.height;
6811
- } else if (i === columns.length) {
6812
- const last = columns[columns.length - 1].getBoundingClientRect();
6813
- left = last.right - barThickness / 2;
6814
- top = last.top;
6815
- height = last.height;
6816
- } else {
6817
- const prev = columns[i - 1].getBoundingClientRect();
6818
- const next = columns[i].getBoundingClientRect();
6819
- left = (prev.right + next.left) / 2 - barThickness / 2;
6820
- top = Math.min(prev.top, next.top);
6821
- height = Math.max(prev.bottom, next.bottom) - top;
6822
- }
6823
- slots.push({
6824
- insertIndex: i,
6825
- columnIndex: i,
6826
- left,
6827
- top,
6828
- width: barThickness,
6829
- height: Math.max(height, 24),
6830
- direction: "vertical"
6831
- });
6832
- }
6833
- return slots;
6834
- }
6835
- function hitTestLinkDropSlot(clientX, clientY, draggedHrefKey) {
6836
- const columns = listFooterColumns();
6837
- let best = null;
6838
- for (let c = 0; c < columns.length; c++) {
6839
- const col = columns[c];
6840
- const colRect = col.getBoundingClientRect();
6841
- const inColX = clientX >= colRect.left - 24 && clientX <= colRect.right + 24;
6842
- if (!inColX) continue;
6843
- const slots = buildLinkDropSlots(col, c).filter((slot) => {
6844
- const links = listFooterLinksInColumn(col);
6845
- const fromIdx = links.findIndex(
6846
- (el) => el.getAttribute("data-ohw-href-key") === draggedHrefKey
6847
- );
6848
- if (fromIdx < 0) return true;
6849
- if (c === findColumnIndexForKey(draggedHrefKey) && (slot.insertIndex === fromIdx || slot.insertIndex === fromIdx + 1)) {
6850
- return true;
6851
- }
6852
- return true;
6853
- });
6854
- for (const slot of slots) {
6855
- const cy = slot.top + slot.height / 2;
6856
- const dist = Math.abs(clientY - cy) + (inColX ? 0 : 1e3);
6857
- if (!best || dist < best.dist) best = { slot, dist };
6858
- }
6859
- }
6860
- return best?.slot ?? null;
6861
- }
6862
- function findColumnIndexForKey(hrefKey) {
6863
- const order = getFooterOrderFromDom();
6864
- for (let c = 0; c < order.length; c++) {
6865
- if (order[c].includes(hrefKey)) return c;
6866
- }
6867
- return -1;
6868
- }
6869
- function hitTestColumnDropSlot(clientX, _clientY) {
6870
- const slots = buildColumnDropSlots();
6871
- let best = null;
6872
- for (const slot of slots) {
6873
- const cx2 = slot.left + slot.width / 2;
6874
- const dist = Math.abs(clientX - cx2);
6875
- if (!best || dist < best.dist) best = { slot, dist };
6876
- }
6877
- return best?.slot ?? null;
6878
- }
6879
-
6880
- // src/lib/carousel.ts
6881
- import { useEffect as useEffect7, useState as useState6 } from "react";
6882
- var CAROUSEL_ATTR = "data-ohw-carousel";
6883
- var CAROUSEL_VALUE_ATTR = "data-ohw-carousel-value";
6884
- var CAROUSEL_SLIDE_ATTR = "data-ohw-carousel-slide";
6885
- var CAROUSEL_EVENT = "ohw:carousel-change";
6886
- function listCarouselKeys() {
6887
- const keys = /* @__PURE__ */ new Set();
6888
- document.querySelectorAll(`[${CAROUSEL_ATTR}]`).forEach((el) => {
6889
- const key = el.getAttribute("data-ohw-key");
6890
- if (key) keys.add(key);
6891
- });
6892
- return [...keys];
6893
- }
6894
- function containersForKey(key) {
6895
- return Array.from(
6896
- document.querySelectorAll(`[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`)
6897
- );
6898
- }
6899
- function isCarouselKey(key) {
6900
- return containersForKey(key).length > 0;
6901
- }
6902
- function parseSlides(raw) {
6903
- if (!raw) return [];
6904
- try {
6905
- const parsed = JSON.parse(raw);
6906
- if (!Array.isArray(parsed)) return [];
6907
- return parsed.filter((s) => Boolean(s) && typeof s === "object").map((s) => ({ src: String(s.src ?? ""), alt: String(s.alt ?? "") }));
6908
- } catch {
6909
- return [];
6910
- }
6911
- }
6912
- function readCarouselValue(key) {
6913
- const container = containersForKey(key)[0];
6914
- if (!container) return [];
6915
- const fromAttr = parseSlides(container.getAttribute(CAROUSEL_VALUE_ATTR));
6916
- if (fromAttr.length > 0) return fromAttr;
6917
- return Array.from(container.querySelectorAll(`[${CAROUSEL_SLIDE_ATTR}]`)).filter((slide) => slide.closest(`[${CAROUSEL_ATTR}]`) === container).sort((a, b) => slideIndex(a) - slideIndex(b)).map((slide) => {
6918
- const img = slide instanceof HTMLImageElement ? slide : slide.querySelector("img");
6919
- return { src: img?.src ?? "", alt: img?.alt ?? "" };
6920
- });
6921
- }
6922
- function slideIndex(el) {
6923
- const raw = el.getAttribute(CAROUSEL_SLIDE_ATTR);
6924
- const n = raw ? parseInt(raw, 10) : NaN;
6925
- return Number.isFinite(n) ? n : 0;
6926
- }
6927
- function applyCarouselValue(key, slides) {
6928
- const value = JSON.stringify(slides);
6929
- for (const container of containersForKey(key)) {
6930
- if (container.getAttribute(CAROUSEL_VALUE_ATTR) === value) continue;
6931
- container.setAttribute(CAROUSEL_VALUE_ATTR, value);
6932
- container.dispatchEvent(
6933
- new CustomEvent(CAROUSEL_EVENT, { detail: { images: slides } })
6934
- );
6935
- }
6936
- }
6937
- function applyCarouselNode(key, val) {
6938
- if (!isCarouselKey(key)) return false;
6939
- applyCarouselValue(key, parseSlides(val));
6940
- return true;
6941
- }
6942
- function useOhwCarousel(key, initial) {
6943
- const [images, setImages] = useState6(initial);
6944
- useEffect7(() => {
6945
- const el = document.querySelector(
6946
- `[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`
6947
- );
6948
- if (!el) return;
6949
- const onChange = (e) => {
6950
- const detail = e.detail;
6951
- if (Array.isArray(detail?.images)) setImages(detail.images);
6952
- };
6953
- el.addEventListener(CAROUSEL_EVENT, onChange);
6954
- return () => el.removeEventListener(CAROUSEL_EVENT, onChange);
6955
- }, [key]);
6956
- const bind = {
6957
- [CAROUSEL_ATTR]: "",
6958
- "data-ohw-key": key,
6959
- [CAROUSEL_VALUE_ATTR]: JSON.stringify(images)
6960
- };
6961
- return { images, setImages, bind };
6962
- }
6963
-
6964
6446
  // src/ui/navbar-container-chrome.tsx
6965
6447
  import { Plus as Plus2 } from "lucide-react";
6966
- import { jsx as jsx22 } from "react/jsx-runtime";
6448
+ import { jsx as jsx21 } from "react/jsx-runtime";
6967
6449
  function NavbarContainerChrome({
6968
6450
  rect,
6969
6451
  onAdd
6970
6452
  }) {
6971
6453
  const chromeGap = 6;
6972
- return /* @__PURE__ */ jsx22(
6454
+ return /* @__PURE__ */ jsx21(
6973
6455
  "div",
6974
6456
  {
6975
6457
  "data-ohw-navbar-container-chrome": "",
@@ -6981,7 +6463,7 @@ function NavbarContainerChrome({
6981
6463
  width: rect.width + chromeGap * 2,
6982
6464
  height: rect.height + chromeGap * 2
6983
6465
  },
6984
- children: /* @__PURE__ */ jsx22(
6466
+ children: /* @__PURE__ */ jsx21(
6985
6467
  "button",
6986
6468
  {
6987
6469
  type: "button",
@@ -6998,57 +6480,15 @@ function NavbarContainerChrome({
6998
6480
  e.stopPropagation();
6999
6481
  onAdd();
7000
6482
  },
7001
- children: /* @__PURE__ */ jsx22(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
6483
+ children: /* @__PURE__ */ jsx21(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
7002
6484
  }
7003
6485
  )
7004
6486
  }
7005
6487
  );
7006
6488
  }
7007
6489
 
7008
- // src/ui/drop-indicator.tsx
7009
- import * as React9 from "react";
7010
- import { jsx as jsx23 } from "react/jsx-runtime";
7011
- var dropIndicatorVariants = cva(
7012
- "ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
7013
- {
7014
- variants: {
7015
- direction: {
7016
- vertical: "h-6 w-[3px]",
7017
- horizontal: "h-[3px] w-[200px]"
7018
- },
7019
- state: {
7020
- default: "opacity-0",
7021
- hover: "opacity-100",
7022
- dragIdle: "opacity-40",
7023
- dragActive: "opacity-100"
7024
- }
7025
- },
7026
- defaultVariants: {
7027
- direction: "vertical",
7028
- state: "default"
7029
- }
7030
- }
7031
- );
7032
- var DropIndicator = React9.forwardRef(
7033
- ({ className, direction, state, ...props }, ref) => {
7034
- return /* @__PURE__ */ jsx23(
7035
- "div",
7036
- {
7037
- ref,
7038
- "data-slot": "drop-indicator",
7039
- "data-direction": direction ?? "vertical",
7040
- "data-state": state ?? "default",
7041
- "aria-hidden": "true",
7042
- className: cn(dropIndicatorVariants({ direction, state }), className),
7043
- ...props
7044
- }
7045
- );
7046
- }
7047
- );
7048
- DropIndicator.displayName = "DropIndicator";
7049
-
7050
6490
  // src/ui/badge.tsx
7051
- import { jsx as jsx24 } from "react/jsx-runtime";
6491
+ import { jsx as jsx22 } from "react/jsx-runtime";
7052
6492
  var badgeVariants = cva(
7053
6493
  "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",
7054
6494
  {
@@ -7066,12 +6506,12 @@ var badgeVariants = cva(
7066
6506
  }
7067
6507
  );
7068
6508
  function Badge({ className, variant, ...props }) {
7069
- return /* @__PURE__ */ jsx24("div", { className: cn(badgeVariants({ variant }), className), ...props });
6509
+ return /* @__PURE__ */ jsx22("div", { className: cn(badgeVariants({ variant }), className), ...props });
7070
6510
  }
7071
6511
 
7072
6512
  // src/OhhwellsBridge.tsx
7073
6513
  import { Link as Link2 } from "lucide-react";
7074
- import { Fragment as Fragment5, jsx as jsx25, jsxs as jsxs14 } from "react/jsx-runtime";
6514
+ import { Fragment as Fragment5, jsx as jsx23, jsxs as jsxs13 } from "react/jsx-runtime";
7075
6515
  var PRIMARY2 = "#0885FE";
7076
6516
  var IMAGE_FADE_MS = 300;
7077
6517
  function runOpacityFade(el, onDone) {
@@ -7250,7 +6690,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
7250
6690
  const root = createRoot(container);
7251
6691
  flushSync(() => {
7252
6692
  root.render(
7253
- /* @__PURE__ */ jsx25(
6693
+ /* @__PURE__ */ jsx23(
7254
6694
  SchedulingWidget,
7255
6695
  {
7256
6696
  notifyOnConnect,
@@ -7312,7 +6752,7 @@ function isDragHandleDisabled(el) {
7312
6752
  return raw === "true" || raw === "";
7313
6753
  });
7314
6754
  }
7315
- function collectEditableNodes(extraContent) {
6755
+ function collectEditableNodes() {
7316
6756
  const nodes = Array.from(document.querySelectorAll("[data-ohw-editable]")).map((el) => {
7317
6757
  if (el.dataset.ohwEditable === "image") {
7318
6758
  const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
@@ -7340,14 +6780,6 @@ function collectEditableNodes(extraContent) {
7340
6780
  if (!key) return;
7341
6781
  nodes.push({ key, type: "link", text: getLinkHref2(el) });
7342
6782
  });
7343
- if (extraContent) {
7344
- for (const key of [NAV_ORDER_KEY, FOOTER_ORDER_KEY, NAV_COUNT_KEY]) {
7345
- const text = extraContent[key];
7346
- if (typeof text === "string" && text.length > 0) {
7347
- nodes.push({ key, type: "meta", text });
7348
- }
7349
- }
7350
- }
7351
6783
  document.querySelectorAll('[data-ohw-editable="video"]').forEach((el) => {
7352
6784
  const key = el.dataset.ohwKey ?? "";
7353
6785
  const video = getVideoEl(el);
@@ -7355,10 +6787,13 @@ function collectEditableNodes(extraContent) {
7355
6787
  nodes.push({ key: `${key}${VIDEO_AUTOPLAY_SUFFIX}`, type: "video-setting", text: String(video.autoplay) });
7356
6788
  nodes.push({ key: `${key}${VIDEO_MUTED_SUFFIX}`, type: "video-setting", text: String(video.muted) });
7357
6789
  });
7358
- for (const key of listCarouselKeys()) {
7359
- nodes.push({ key, type: "carousel", text: JSON.stringify(readCarouselValue(key)) });
7360
- }
7361
- return nodes;
6790
+ const seen = /* @__PURE__ */ new Set();
6791
+ return nodes.filter((node) => {
6792
+ if (!node.key) return true;
6793
+ if (seen.has(node.key)) return false;
6794
+ seen.add(node.key);
6795
+ return true;
6796
+ });
7362
6797
  }
7363
6798
  function isMediaEditable(el) {
7364
6799
  const t = el.dataset.ohwEditable;
@@ -7446,29 +6881,6 @@ function getHrefKeyFromElement(el) {
7446
6881
  if (!key) return null;
7447
6882
  return { anchor, key };
7448
6883
  }
7449
- function disableNativeHrefDrag(el) {
7450
- if (el.draggable) el.draggable = false;
7451
- if (el.getAttribute("draggable") !== "false") {
7452
- el.setAttribute("draggable", "false");
7453
- }
7454
- }
7455
- function clearTextSelection() {
7456
- const sel = window.getSelection();
7457
- if (sel && !sel.isCollapsed) sel.removeAllRanges();
7458
- }
7459
- function armFooterPressDrag() {
7460
- document.documentElement.setAttribute("data-ohw-footer-press-drag", "");
7461
- }
7462
- function lockFooterDuringDrag() {
7463
- document.documentElement.removeAttribute("data-ohw-footer-press-drag");
7464
- document.documentElement.setAttribute("data-ohw-item-dragging", "");
7465
- clearTextSelection();
7466
- }
7467
- function unlockFooterDragInteraction() {
7468
- document.documentElement.removeAttribute("data-ohw-footer-press-drag");
7469
- document.documentElement.removeAttribute("data-ohw-item-dragging");
7470
- clearTextSelection();
7471
- }
7472
6884
  function isNavbarButton2(el) {
7473
6885
  return Boolean(el.closest('[data-ohw-role="navbar-button"]'));
7474
6886
  }
@@ -7531,7 +6943,7 @@ function isInferredFooterGroup(el) {
7531
6943
  return Array.from(el.querySelectorAll(":scope > [data-ohw-href-key]")).some(isNavigationItem);
7532
6944
  }
7533
6945
  function isNavigationContainer(el) {
7534
- return el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-footer-col") || isNavigationRoot(el) || isInferredFooterGroup(el);
6946
+ return el.hasAttribute("data-ohw-nav-container") || isNavigationRoot(el) || isInferredFooterGroup(el);
7535
6947
  }
7536
6948
  function isPointOverNavigation(x, y) {
7537
6949
  const navRoot = document.querySelector("[data-ohw-nav-root]") ?? document.querySelector("nav");
@@ -7602,22 +7014,6 @@ function placeCaretAtPoint(el, x, y) {
7602
7014
  }
7603
7015
  }
7604
7016
  }
7605
- function selectAllTextInEditable(el) {
7606
- const selection = window.getSelection();
7607
- if (!selection) return;
7608
- const range = document.createRange();
7609
- range.selectNodeContents(el);
7610
- selection.removeAllRanges();
7611
- selection.addRange(range);
7612
- }
7613
- function getNavigationLabelEditable(target) {
7614
- const editable = target.closest('[data-ohw-editable="text"]');
7615
- if (!editable) return null;
7616
- const hrefCtx = getHrefKeyFromElement(editable);
7617
- const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
7618
- if (!navAnchor) return null;
7619
- return { editable, navAnchor };
7620
- }
7621
7017
  function collectSections() {
7622
7018
  return collectSectionsFromDom();
7623
7019
  }
@@ -7741,8 +7137,6 @@ var ICONS = {
7741
7137
  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"/>',
7742
7138
  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"/>'
7743
7139
  };
7744
- var TOOLBAR_PILL_PADDING = 2;
7745
- var TOOLBAR_TOGGLE_GAP = 4;
7746
7140
  var TOOLBAR_GROUPS = [
7747
7141
  [
7748
7142
  { cmd: "bold", title: "Bold" },
@@ -7767,7 +7161,7 @@ function EditGlowChrome({
7767
7161
  dragDisabled = false
7768
7162
  }) {
7769
7163
  const GAP = 6;
7770
- return /* @__PURE__ */ jsxs14(
7164
+ return /* @__PURE__ */ jsxs13(
7771
7165
  "div",
7772
7166
  {
7773
7167
  ref: elRef,
@@ -7782,7 +7176,7 @@ function EditGlowChrome({
7782
7176
  zIndex: 2147483646
7783
7177
  },
7784
7178
  children: [
7785
- /* @__PURE__ */ jsx25(
7179
+ /* @__PURE__ */ jsx23(
7786
7180
  "div",
7787
7181
  {
7788
7182
  style: {
@@ -7795,7 +7189,7 @@ function EditGlowChrome({
7795
7189
  }
7796
7190
  }
7797
7191
  ),
7798
- reorderHrefKey && /* @__PURE__ */ jsx25(
7192
+ reorderHrefKey && /* @__PURE__ */ jsx23(
7799
7193
  "div",
7800
7194
  {
7801
7195
  "data-ohw-drag-handle-container": "",
@@ -7807,7 +7201,7 @@ function EditGlowChrome({
7807
7201
  transform: "translate(calc(-100% - 7px), -50%)",
7808
7202
  pointerEvents: dragDisabled ? "none" : "auto"
7809
7203
  },
7810
- children: /* @__PURE__ */ jsx25(
7204
+ children: /* @__PURE__ */ jsx23(
7811
7205
  DragHandle,
7812
7206
  {
7813
7207
  "aria-label": `Reorder ${reorderHrefKey}`,
@@ -7911,7 +7305,7 @@ function FloatingToolbar({
7911
7305
  onEditLink
7912
7306
  }) {
7913
7307
  const { top, left, transform } = calcToolbarPos(rect, parentScroll, 330);
7914
- return /* @__PURE__ */ jsx25(
7308
+ return /* @__PURE__ */ jsx23(
7915
7309
  "div",
7916
7310
  {
7917
7311
  ref: elRef,
@@ -7921,23 +7315,14 @@ function FloatingToolbar({
7921
7315
  left,
7922
7316
  transform,
7923
7317
  zIndex: 2147483647,
7924
- background: "#fff",
7925
- border: "1px solid #E7E5E4",
7926
- borderRadius: 6,
7927
- boxShadow: "0px 2px 4px -2px rgba(0,0,0,.1),0px 4px 6px -1px rgba(0,0,0,.1)",
7928
- display: "flex",
7929
- alignItems: "center",
7930
- padding: TOOLBAR_PILL_PADDING,
7931
- gap: TOOLBAR_TOGGLE_GAP,
7932
- fontFamily: "sans-serif",
7933
7318
  pointerEvents: "auto"
7934
7319
  },
7935
- children: /* @__PURE__ */ jsxs14(CustomToolbar, { children: [
7936
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs14(React10.Fragment, { children: [
7937
- gi > 0 && /* @__PURE__ */ jsx25(CustomToolbarDivider, {}),
7320
+ children: /* @__PURE__ */ jsxs13(CustomToolbar, { children: [
7321
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs13(React9.Fragment, { children: [
7322
+ gi > 0 && /* @__PURE__ */ jsx23(CustomToolbarDivider, {}),
7938
7323
  btns.map((btn) => {
7939
7324
  const isActive = activeCommands.has(btn.cmd);
7940
- return /* @__PURE__ */ jsx25(
7325
+ return /* @__PURE__ */ jsx23(
7941
7326
  CustomToolbarButton,
7942
7327
  {
7943
7328
  title: btn.title,
@@ -7946,7 +7331,7 @@ function FloatingToolbar({
7946
7331
  e.preventDefault();
7947
7332
  onCommand(btn.cmd);
7948
7333
  },
7949
- children: /* @__PURE__ */ jsx25(
7334
+ children: /* @__PURE__ */ jsx23(
7950
7335
  "svg",
7951
7336
  {
7952
7337
  width: "16",
@@ -7967,7 +7352,7 @@ function FloatingToolbar({
7967
7352
  );
7968
7353
  })
7969
7354
  ] }, gi)),
7970
- showEditLink ? /* @__PURE__ */ jsx25(
7355
+ showEditLink ? /* @__PURE__ */ jsx23(
7971
7356
  CustomToolbarButton,
7972
7357
  {
7973
7358
  type: "button",
@@ -7981,7 +7366,7 @@ function FloatingToolbar({
7981
7366
  e.preventDefault();
7982
7367
  e.stopPropagation();
7983
7368
  },
7984
- children: /* @__PURE__ */ jsx25(Link2, { className: "size-4 shrink-0", "aria-hidden": true })
7369
+ children: /* @__PURE__ */ jsx23(Link2, { className: "size-4 shrink-0", "aria-hidden": true })
7985
7370
  }
7986
7371
  ) : null
7987
7372
  ] })
@@ -7998,7 +7383,7 @@ function StateToggle({
7998
7383
  states,
7999
7384
  onStateChange
8000
7385
  }) {
8001
- return /* @__PURE__ */ jsx25(
7386
+ return /* @__PURE__ */ jsx23(
8002
7387
  ToggleGroup,
8003
7388
  {
8004
7389
  "data-ohw-state-toggle": "",
@@ -8012,7 +7397,7 @@ function StateToggle({
8012
7397
  left: rect.right - 8,
8013
7398
  transform: "translateX(-100%)"
8014
7399
  },
8015
- children: states.map((state) => /* @__PURE__ */ jsx25(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
7400
+ children: states.map((state) => /* @__PURE__ */ jsx23(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
8016
7401
  }
8017
7402
  );
8018
7403
  }
@@ -8039,8 +7424,8 @@ function OhhwellsBridge() {
8039
7424
  const router = useRouter2();
8040
7425
  const searchParams = useSearchParams();
8041
7426
  const isEditMode = isEditSessionActive();
8042
- const [bridgeRoot, setBridgeRoot] = useState7(null);
8043
- useEffect8(() => {
7427
+ const [bridgeRoot, setBridgeRoot] = useState6(null);
7428
+ useEffect7(() => {
8044
7429
  const figtreeFontId = "ohw-figtree-font";
8045
7430
  if (!document.getElementById(figtreeFontId)) {
8046
7431
  const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
@@ -8068,12 +7453,12 @@ function OhhwellsBridge() {
8068
7453
  const subdomainFromQuery = searchParams.get("subdomain");
8069
7454
  const subdomain = resolveSubdomain(subdomainFromQuery);
8070
7455
  useLinkHrefGuardian(pathname, subdomain, isEditMode);
8071
- const postToParent2 = useCallback4((data) => {
7456
+ const postToParent2 = useCallback3((data) => {
8072
7457
  if (typeof window !== "undefined" && window.parent !== window) {
8073
7458
  window.parent.postMessage(data, "*");
8074
7459
  }
8075
7460
  }, []);
8076
- const [fetchState, setFetchState] = useState7("idle");
7461
+ const [fetchState, setFetchState] = useState6("idle");
8077
7462
  const autoSaveTimers = useRef5(/* @__PURE__ */ new Map());
8078
7463
  const activeElRef = useRef5(null);
8079
7464
  const selectedElRef = useRef5(null);
@@ -8081,8 +7466,8 @@ function OhhwellsBridge() {
8081
7466
  const activeStateElRef = useRef5(null);
8082
7467
  const parentScrollRef = useRef5(null);
8083
7468
  const visibleViewportRef = useRef5(null);
8084
- const [dialogPortalContainer, setDialogPortalContainer] = useState7(null);
8085
- const attachVisibleViewport = useCallback4((node) => {
7469
+ const [dialogPortalContainer, setDialogPortalContainer] = useState6(null);
7470
+ const attachVisibleViewport = useCallback3((node) => {
8086
7471
  visibleViewportRef.current = node;
8087
7472
  setDialogPortalContainer(node);
8088
7473
  if (node) applyVisibleViewport(node, parentScrollRef.current);
@@ -8092,10 +7477,8 @@ function OhhwellsBridge() {
8092
7477
  const hoveredImageRef = useRef5(null);
8093
7478
  const hoveredImageHasTextOverlapRef = useRef5(false);
8094
7479
  const dragOverElRef = useRef5(null);
8095
- const [mediaHover, setMediaHover] = useState7(null);
8096
- const [carouselHover, setCarouselHover] = useState7(null);
8097
- const [uploadingRects, setUploadingRects] = useState7({});
8098
- const pendingUploadRectRef = useRef5(null);
7480
+ const [mediaHover, setMediaHover] = useState6(null);
7481
+ const [uploadingRects, setUploadingRects] = useState6({});
8099
7482
  const hoveredGapRef = useRef5(null);
8100
7483
  const imageUnhoverTimerRef = useRef5(null);
8101
7484
  const imageShowTimerRef = useRef5(null);
@@ -8120,38 +7503,30 @@ function OhhwellsBridge() {
8120
7503
  postToParentRef.current = postToParent2;
8121
7504
  const sectionsLoadedRef = useRef5(false);
8122
7505
  const pendingScheduleConfigRequests = useRef5([]);
8123
- const [toolbarRect, setToolbarRect] = useState7(null);
8124
- const [toolbarVariant, setToolbarVariant] = useState7("none");
7506
+ const [toolbarRect, setToolbarRect] = useState6(null);
7507
+ const [toolbarVariant, setToolbarVariant] = useState6("none");
8125
7508
  const toolbarVariantRef = useRef5("none");
8126
7509
  toolbarVariantRef.current = toolbarVariant;
8127
- const [reorderHrefKey, setReorderHrefKey] = useState7(null);
8128
- const [reorderDragDisabled, setReorderDragDisabled] = useState7(false);
8129
- const [toggleState, setToggleState] = useState7(null);
8130
- const [maxBadge, setMaxBadge] = useState7(null);
8131
- const [activeCommands, setActiveCommands] = useState7(/* @__PURE__ */ new Set());
8132
- const [sectionGap, setSectionGap] = useState7(null);
8133
- const [toolbarShowEditLink, setToolbarShowEditLink] = useState7(false);
7510
+ const [reorderHrefKey, setReorderHrefKey] = useState6(null);
7511
+ const [reorderDragDisabled, setReorderDragDisabled] = useState6(false);
7512
+ const [toggleState, setToggleState] = useState6(null);
7513
+ const [maxBadge, setMaxBadge] = useState6(null);
7514
+ const [activeCommands, setActiveCommands] = useState6(/* @__PURE__ */ new Set());
7515
+ const [sectionGap, setSectionGap] = useState6(null);
7516
+ const [toolbarShowEditLink, setToolbarShowEditLink] = useState6(false);
8134
7517
  const hoveredNavContainerRef = useRef5(null);
8135
- const [hoveredNavContainerRect, setHoveredNavContainerRect] = useState7(null);
7518
+ const [hoveredNavContainerRect, setHoveredNavContainerRect] = useState6(null);
8136
7519
  const hoveredItemElRef = useRef5(null);
8137
- const [hoveredItemRect, setHoveredItemRect] = useState7(null);
7520
+ const [hoveredItemRect, setHoveredItemRect] = useState6(null);
8138
7521
  const siblingHintElRef = useRef5(null);
8139
- const [siblingHintRect, setSiblingHintRect] = useState7(null);
8140
- const [siblingHintRects, setSiblingHintRects] = useState7([]);
8141
- const [isItemDragging, setIsItemDragging] = useState7(false);
8142
- const [isFooterFrameSelection, setIsFooterFrameSelection] = useState7(false);
8143
- const footerDragRef = useRef5(null);
8144
- const [footerDropSlots, setFooterDropSlots] = useState7([]);
8145
- const [activeFooterDropIndex, setActiveFooterDropIndex] = useState7(null);
8146
- const [draggedItemRect, setDraggedItemRect] = useState7(null);
8147
- const footerPointerDragRef = useRef5(null);
8148
- const suppressNextClickRef = useRef5(false);
8149
- const [linkPopover, setLinkPopover] = useState7(null);
7522
+ const [siblingHintRect, setSiblingHintRect] = useState6(null);
7523
+ const [isItemDragging, setIsItemDragging] = useState6(false);
7524
+ const [linkPopover, setLinkPopover] = useState6(null);
8150
7525
  const linkPopoverSessionRef = useRef5(null);
8151
7526
  const addNavAfterAnchorRef = useRef5(null);
8152
7527
  const editContentRef = useRef5({});
8153
- const [sitePages, setSitePages] = useState7([]);
8154
- const [sectionsByPath, setSectionsByPath] = useState7({});
7528
+ const [sitePages, setSitePages] = useState6([]);
7529
+ const [sectionsByPath, setSectionsByPath] = useState6({});
8155
7530
  const sectionsPrefetchGenRef = useRef5(0);
8156
7531
  const setLinkPopoverRef = useRef5(setLinkPopover);
8157
7532
  const linkPopoverPanelRef = useRef5(null);
@@ -8162,7 +7537,7 @@ function OhhwellsBridge() {
8162
7537
  const bumpLinkPopoverGrace = () => {
8163
7538
  linkPopoverGraceUntilRef.current = Date.now() + 350;
8164
7539
  };
8165
- const runSectionsPrefetch = useCallback4((pages) => {
7540
+ const runSectionsPrefetch = useCallback3((pages) => {
8166
7541
  if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
8167
7542
  const gen = ++sectionsPrefetchGenRef.current;
8168
7543
  const paths = pages.map((p) => p.path);
@@ -8183,31 +7558,42 @@ function OhhwellsBridge() {
8183
7558
  }, [isEditMode, pathname]);
8184
7559
  const runSectionsPrefetchRef = useRef5(runSectionsPrefetch);
8185
7560
  runSectionsPrefetchRef.current = runSectionsPrefetch;
8186
- useEffect8(() => {
8187
- if (!linkPopover) {
8188
- document.documentElement.removeAttribute("data-ohw-link-popover-open");
8189
- return;
8190
- }
8191
- document.documentElement.setAttribute("data-ohw-link-popover-open", "");
7561
+ useEffect7(() => {
7562
+ if (!linkPopover) return;
8192
7563
  if (hoveredImageRef.current) {
8193
7564
  hoveredImageRef.current = null;
8194
7565
  hoveredImageHasTextOverlapRef.current = false;
8195
7566
  }
8196
7567
  hoveredGapRef.current = null;
8197
7568
  setSectionGap(null);
8198
- hoveredItemElRef.current = null;
8199
- setHoveredItemRect(null);
8200
- hoveredNavContainerRef.current = null;
8201
- setHoveredNavContainerRect(null);
8202
- document.querySelectorAll("[data-ohw-hovered]").forEach((el) => {
8203
- el.removeAttribute("data-ohw-hovered");
8204
- });
7569
+ setMediaHover(null);
7570
+ postToParent2({ type: "ow:link-modal-lock", locked: true });
7571
+ const html = document.documentElement;
7572
+ const body = document.body;
7573
+ const prevHtmlOverflow = html.style.overflow;
7574
+ const prevBodyOverflow = body.style.overflow;
7575
+ html.style.overflow = "hidden";
7576
+ body.style.overflow = "hidden";
7577
+ const preventBackgroundScroll = (e) => {
7578
+ const target = e.target;
7579
+ if (target instanceof Element && target.closest('[data-ohw-link-modal-root], [data-slot="dialog-overlay"]')) {
7580
+ return;
7581
+ }
7582
+ e.preventDefault();
7583
+ };
7584
+ const scrollOpts = { passive: false, capture: true };
7585
+ document.addEventListener("wheel", preventBackgroundScroll, scrollOpts);
7586
+ document.addEventListener("touchmove", preventBackgroundScroll, scrollOpts);
8205
7587
  postToParent2({ type: "ow:image-unhover" });
8206
7588
  return () => {
8207
- document.documentElement.removeAttribute("data-ohw-link-popover-open");
7589
+ postToParent2({ type: "ow:link-modal-lock", locked: false });
7590
+ html.style.overflow = prevHtmlOverflow;
7591
+ body.style.overflow = prevBodyOverflow;
7592
+ document.removeEventListener("wheel", preventBackgroundScroll, scrollOpts);
7593
+ document.removeEventListener("touchmove", preventBackgroundScroll, scrollOpts);
8208
7594
  };
8209
7595
  }, [linkPopover, postToParent2]);
8210
- useEffect8(() => {
7596
+ useEffect7(() => {
8211
7597
  if (!isEditMode) return;
8212
7598
  const useFixtures = shouldUseDevFixtures();
8213
7599
  if (useFixtures) {
@@ -8231,14 +7617,14 @@ function OhhwellsBridge() {
8231
7617
  if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
8232
7618
  return () => window.removeEventListener("message", onSitePages);
8233
7619
  }, [isEditMode, postToParent2]);
8234
- useEffect8(() => {
7620
+ useEffect7(() => {
8235
7621
  if (!isEditMode || shouldUseDevFixtures()) return;
8236
7622
  void loadAllSectionsManifest().then((manifest) => {
8237
7623
  if (Object.keys(manifest).length === 0) return;
8238
7624
  setSectionsByPath((prev) => ({ ...manifest, ...prev }));
8239
7625
  });
8240
7626
  }, [isEditMode]);
8241
- useEffect8(() => {
7627
+ useEffect7(() => {
8242
7628
  const update = () => {
8243
7629
  const el = activeElRef.current ?? selectedElRef.current;
8244
7630
  if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
@@ -8262,10 +7648,10 @@ function OhhwellsBridge() {
8262
7648
  vvp.removeEventListener("resize", update);
8263
7649
  };
8264
7650
  }, []);
8265
- const refreshStateRules = useCallback4(() => {
7651
+ const refreshStateRules = useCallback3(() => {
8266
7652
  editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
8267
7653
  }, []);
8268
- const processConfigRequest = useCallback4((insertAfterVal) => {
7654
+ const processConfigRequest = useCallback3((insertAfterVal) => {
8269
7655
  const tracker = getSectionsTracker();
8270
7656
  let entries = [];
8271
7657
  try {
@@ -8288,7 +7674,7 @@ function OhhwellsBridge() {
8288
7674
  }
8289
7675
  window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
8290
7676
  }, [isEditMode]);
8291
- const deactivate = useCallback4(() => {
7677
+ const deactivate = useCallback3(() => {
8292
7678
  const el = activeElRef.current;
8293
7679
  if (!el) return;
8294
7680
  const key = el.dataset.ohwKey;
@@ -8319,14 +7705,12 @@ function OhhwellsBridge() {
8319
7705
  setToolbarShowEditLink(false);
8320
7706
  postToParent2({ type: "ow:exit-edit" });
8321
7707
  }, [postToParent2]);
8322
- const deselect = useCallback4(() => {
7708
+ const deselect = useCallback3(() => {
8323
7709
  selectedElRef.current = null;
8324
7710
  setReorderHrefKey(null);
8325
7711
  setReorderDragDisabled(false);
8326
- setIsFooterFrameSelection(false);
8327
7712
  siblingHintElRef.current = null;
8328
7713
  setSiblingHintRect(null);
8329
- setSiblingHintRects([]);
8330
7714
  setIsItemDragging(false);
8331
7715
  hoveredNavContainerRef.current = null;
8332
7716
  setHoveredNavContainerRect(null);
@@ -8335,7 +7719,7 @@ function OhhwellsBridge() {
8335
7719
  setToolbarVariant("none");
8336
7720
  }
8337
7721
  }, []);
8338
- const reselectNavigationItem = useCallback4((navAnchor) => {
7722
+ const reselectNavigationItem = useCallback3((navAnchor) => {
8339
7723
  selectedElRef.current = navAnchor;
8340
7724
  const { key, disabled } = getNavigationItemReorderState(navAnchor);
8341
7725
  setReorderHrefKey(key);
@@ -8345,7 +7729,7 @@ function OhhwellsBridge() {
8345
7729
  setToolbarShowEditLink(false);
8346
7730
  setActiveCommands(/* @__PURE__ */ new Set());
8347
7731
  }, []);
8348
- const commitNavigationTextEdit = useCallback4((navAnchor) => {
7732
+ const commitNavigationTextEdit = useCallback3((navAnchor) => {
8349
7733
  const el = activeElRef.current;
8350
7734
  if (!el) return;
8351
7735
  const key = el.dataset.ohwKey;
@@ -8371,7 +7755,7 @@ function OhhwellsBridge() {
8371
7755
  postToParent2({ type: "ow:exit-edit" });
8372
7756
  reselectNavigationItem(navAnchor);
8373
7757
  }, [postToParent2, reselectNavigationItem]);
8374
- const handleAddTopLevelNavItem = useCallback4(() => {
7758
+ const handleAddTopLevelNavItem = useCallback3(() => {
8375
7759
  const items = listNavbarItems();
8376
7760
  addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
8377
7761
  deselectRef.current();
@@ -8383,387 +7767,90 @@ function OhhwellsBridge() {
8383
7767
  intent: "add-nav"
8384
7768
  });
8385
7769
  }, []);
8386
- const clearFooterDragVisuals = useCallback4(() => {
8387
- footerDragRef.current = null;
8388
- setSiblingHintRects([]);
8389
- setFooterDropSlots([]);
8390
- setActiveFooterDropIndex(null);
8391
- setDraggedItemRect(null);
8392
- setIsItemDragging(false);
8393
- unlockFooterDragInteraction();
7770
+ const handleItemDragStart = useCallback3(() => {
7771
+ siblingHintElRef.current = null;
7772
+ setSiblingHintRect(null);
7773
+ setIsItemDragging(true);
8394
7774
  }, []);
8395
- const refreshFooterDragVisuals = useCallback4((session, activeSlot, clientX, clientY) => {
8396
- const dragged = session.draggedEl;
8397
- setDraggedItemRect(dragged.getBoundingClientRect());
8398
- if (typeof clientX === "number" && typeof clientY === "number") {
8399
- session.lastClientX = clientX;
8400
- session.lastClientY = clientY;
8401
- }
8402
- session.activeSlot = activeSlot;
8403
- if (session.kind === "link") {
8404
- const columns2 = listFooterColumns();
8405
- const focusCols = /* @__PURE__ */ new Set([session.sourceColumnIndex]);
8406
- if (activeSlot) focusCols.add(activeSlot.columnIndex);
8407
- const siblingRects = [];
8408
- columns2.forEach((col, i) => {
8409
- if (!focusCols.has(i)) return;
8410
- for (const link of listFooterLinksInColumn(col)) {
8411
- if (link === dragged) continue;
8412
- siblingRects.push(link.getBoundingClientRect());
8413
- }
8414
- });
8415
- setSiblingHintRects(siblingRects);
8416
- const slots2 = [];
8417
- columns2.forEach((col, i) => {
8418
- slots2.push(...buildLinkDropSlots(col, i));
8419
- });
8420
- setFooterDropSlots(slots2);
8421
- const activeIdx2 = activeSlot ? slots2.findIndex((s) => s.columnIndex === activeSlot.columnIndex && s.insertIndex === activeSlot.insertIndex) : -1;
8422
- setActiveFooterDropIndex(activeIdx2 >= 0 ? activeIdx2 : null);
8423
- return;
8424
- }
8425
- const columns = listFooterColumns();
8426
- setSiblingHintRects(columns.filter((col) => col !== dragged).map((col) => col.getBoundingClientRect()));
8427
- const slots = buildColumnDropSlots();
8428
- setFooterDropSlots(slots);
8429
- const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
8430
- setActiveFooterDropIndex(activeIdx >= 0 ? activeIdx : null);
8431
- }, []);
8432
- const refreshFooterDragVisualsRef = useRef5(refreshFooterDragVisuals);
8433
- refreshFooterDragVisualsRef.current = refreshFooterDragVisuals;
8434
- const commitFooterDragRef = useRef5(() => {
8435
- });
8436
- const beginFooterDragRef = useRef5(() => {
8437
- });
8438
- const beginFooterDrag = useCallback4(
8439
- (session) => {
8440
- const rect = session.draggedEl.getBoundingClientRect();
8441
- session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
8442
- session.lastClientY = session.lastClientY || rect.top + rect.height / 2;
8443
- session.activeSlot = session.activeSlot ?? null;
8444
- footerDragRef.current = session;
8445
- setIsItemDragging(true);
8446
- lockFooterDuringDrag();
8447
- siblingHintElRef.current = null;
8448
- setSiblingHintRect(null);
8449
- if (session.wasSelected && selectedElRef.current === session.draggedEl) {
8450
- setToolbarRect(rect);
8451
- }
8452
- const initialSlot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
8453
- refreshFooterDragVisuals(session, initialSlot, session.lastClientX, session.lastClientY);
8454
- },
8455
- [refreshFooterDragVisuals]
8456
- );
8457
- beginFooterDragRef.current = beginFooterDrag;
8458
- const commitFooterDrag = useCallback4(
8459
- (clientX, clientY) => {
8460
- const session = footerDragRef.current;
8461
- if (!session) {
8462
- clearFooterDragVisuals();
8463
- return;
8464
- }
8465
- const x = typeof clientX === "number" && (clientX !== 0 || clientY !== 0) ? clientX : session.lastClientX;
8466
- const y = typeof clientY === "number" && (clientX !== 0 || clientY !== 0) ? clientY : session.lastClientY;
8467
- let nextOrder = null;
8468
- const slot = session.activeSlot ?? (session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(x, y, session.hrefKey) : session.kind === "column" ? hitTestColumnDropSlot(x, y) : null);
8469
- if (session.kind === "link" && session.hrefKey && slot) {
8470
- nextOrder = planFooterLinkMove(session.hrefKey, slot.columnIndex, slot.insertIndex);
8471
- } else if (session.kind === "column" && slot) {
8472
- nextOrder = planFooterColumnMove(session.sourceColumnIndex, slot.insertIndex);
8473
- }
8474
- const wasSelected = session.wasSelected;
8475
- const draggedEl = session.draggedEl;
8476
- const hrefKey = session.hrefKey;
8477
- let movedColumnIndex = null;
8478
- if (session.kind === "column" && slot && nextOrder) {
8479
- let adjusted = slot.insertIndex;
8480
- if (session.sourceColumnIndex < slot.insertIndex) adjusted -= 1;
8481
- movedColumnIndex = Math.max(0, Math.min(adjusted, nextOrder.length - 1));
8482
- }
8483
- clearFooterDragVisuals();
8484
- const applySelectionAfterDrop = () => {
8485
- if (!wasSelected) {
8486
- deselectRef.current();
8487
- return;
8488
- }
8489
- if (hrefKey) {
8490
- const link = document.querySelector(
8491
- `footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
8492
- );
8493
- if (link && isNavigationItem(link)) {
8494
- selectRef.current(link);
8495
- return;
8496
- }
8497
- }
8498
- if (movedColumnIndex !== null && nextOrder) {
8499
- const colKeys = nextOrder[movedColumnIndex] ?? [];
8500
- let column = null;
8501
- for (const key of colKeys) {
8502
- const link = document.querySelector(
8503
- `footer [data-ohw-href-key="${CSS.escape(key)}"]`
8504
- );
8505
- if (link) {
8506
- column = findFooterColumnForLink(link);
8507
- if (column) break;
8508
- }
8509
- }
8510
- if (!column) column = listFooterColumns()[movedColumnIndex] ?? null;
8511
- if (column && isNavigationContainer(column)) {
8512
- selectFrameRef.current(column);
8513
- return;
8514
- }
8515
- }
8516
- if (document.body.contains(draggedEl)) {
8517
- if (isNavigationItem(draggedEl)) {
8518
- selectRef.current(draggedEl);
8519
- return;
8520
- }
8521
- if (isNavigationContainer(draggedEl)) {
8522
- selectFrameRef.current(draggedEl);
8523
- return;
8524
- }
8525
- }
8526
- deselectRef.current();
8527
- };
8528
- if (!wasSelected) {
8529
- deselectRef.current();
8530
- }
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
- postToParentRef.current({
8540
- type: "ow:change",
8541
- nodes: [{ key: FOOTER_ORDER_KEY, text: orderJson }]
8542
- });
8543
- requestAnimationFrame(() => {
8544
- if (editContentRef.current[FOOTER_ORDER_KEY] === orderJson) {
8545
- applyFooterOrder(nextOrder);
8546
- document.querySelectorAll("footer [data-ohw-href-key]").forEach(disableNativeHrefDrag);
8547
- }
8548
- requestAnimationFrame(applySelectionAfterDrop);
8549
- });
8550
- return;
8551
- }
8552
- applySelectionAfterDrop();
8553
- },
8554
- [clearFooterDragVisuals]
8555
- );
8556
- commitFooterDragRef.current = commitFooterDrag;
8557
- const startFooterLinkDrag = useCallback4(
8558
- (anchor, clientX, clientY, wasSelected) => {
8559
- const hrefKey = anchor.getAttribute("data-ohw-href-key");
8560
- if (!hrefKey || !isFooterHrefKey(hrefKey)) return false;
8561
- const column = findFooterColumnForLink(anchor);
8562
- const columns = listFooterColumns();
8563
- beginFooterDrag({
8564
- kind: "link",
8565
- hrefKey,
8566
- columnEl: column,
8567
- sourceColumnIndex: column ? columns.indexOf(column) : 0,
8568
- wasSelected,
8569
- draggedEl: anchor,
8570
- lastClientX: clientX,
8571
- lastClientY: clientY,
8572
- activeSlot: null
8573
- });
8574
- return true;
8575
- },
8576
- [beginFooterDrag]
8577
- );
8578
- const startFooterColumnDrag = useCallback4(
8579
- (columnEl, clientX, clientY, wasSelected) => {
8580
- const columns = listFooterColumns();
8581
- const idx = columns.indexOf(columnEl);
8582
- if (idx < 0) return false;
8583
- beginFooterDrag({
8584
- kind: "column",
8585
- hrefKey: null,
8586
- columnEl,
8587
- sourceColumnIndex: idx,
8588
- wasSelected,
8589
- draggedEl: columnEl,
8590
- lastClientX: clientX,
8591
- lastClientY: clientY,
8592
- activeSlot: null
8593
- });
8594
- return true;
8595
- },
8596
- [beginFooterDrag]
8597
- );
8598
- const handleItemDragStart = useCallback4(
8599
- (e) => {
8600
- const selected = selectedElRef.current;
8601
- if (!selected) {
8602
- setIsItemDragging(true);
8603
- return;
8604
- }
8605
- const clientX = e?.clientX ?? selected.getBoundingClientRect().left + 8;
8606
- const clientY = e?.clientY ?? selected.getBoundingClientRect().top + 8;
8607
- if (startFooterLinkDrag(selected, clientX, clientY, true)) return;
8608
- if (selected.hasAttribute("data-ohw-footer-col") || isInferredFooterGroup(selected) && selected.closest("footer")) {
8609
- if (startFooterColumnDrag(selected, clientX, clientY, true)) return;
8610
- }
8611
- siblingHintElRef.current = null;
8612
- setSiblingHintRect(null);
8613
- setIsItemDragging(true);
8614
- },
8615
- [startFooterColumnDrag, startFooterLinkDrag]
8616
- );
8617
- const handleItemDragEnd = useCallback4(
8618
- (e) => {
8619
- if (footerDragRef.current) {
8620
- const x = e?.clientX;
8621
- const y = e?.clientY;
8622
- if (typeof x === "number" && typeof y === "number" && (x !== 0 || y !== 0)) {
8623
- commitFooterDrag(x, y);
8624
- } else {
8625
- commitFooterDrag();
8626
- }
8627
- return;
8628
- }
8629
- setIsItemDragging(false);
8630
- },
8631
- [commitFooterDrag]
8632
- );
8633
- const handleItemChromePointerDown = useCallback4((e) => {
8634
- if (e.button !== 0) return;
8635
- const selected = selectedElRef.current;
8636
- if (!selected) return;
8637
- armFooterPressDrag();
8638
- const hrefKey = selected.getAttribute("data-ohw-href-key");
8639
- if (hrefKey && isFooterHrefKey(hrefKey)) {
8640
- footerPointerDragRef.current = {
8641
- el: selected,
8642
- kind: "link",
8643
- startX: e.clientX,
8644
- startY: e.clientY,
8645
- pointerId: e.pointerId,
8646
- wasSelected: true,
8647
- started: false
8648
- };
8649
- return;
8650
- }
8651
- if (selected.hasAttribute("data-ohw-footer-col") || isInferredFooterGroup(selected) && selected.closest("footer")) {
8652
- footerPointerDragRef.current = {
8653
- el: selected,
8654
- kind: "column",
8655
- startX: e.clientX,
8656
- startY: e.clientY,
8657
- pointerId: e.pointerId,
8658
- wasSelected: true,
8659
- started: false
8660
- };
8661
- }
8662
- }, []);
8663
- const handleItemChromeClick = useCallback4((clientX, clientY) => {
8664
- if (suppressNextClickRef.current) {
8665
- suppressNextClickRef.current = false;
8666
- return;
8667
- }
8668
- const selected = selectedElRef.current;
8669
- if (!selected || !isNavigationItem(selected)) return;
8670
- const editable = selected.querySelector('[data-ohw-editable="text"]') ?? selected.querySelector("[data-ohw-editable]");
8671
- if (!editable) return;
8672
- activateRef.current(editable, { caretX: clientX, caretY: clientY });
7775
+ const handleItemDragEnd = useCallback3(() => {
7776
+ setIsItemDragging(false);
8673
7777
  }, []);
8674
7778
  reselectNavigationItemRef.current = reselectNavigationItem;
8675
7779
  commitNavigationTextEditRef.current = commitNavigationTextEdit;
8676
- const select = useCallback4(
8677
- (anchor) => {
8678
- if (!isNavigationItem(anchor)) return;
8679
- if (activeElRef.current) deactivate();
8680
- selectedElRef.current = anchor;
8681
- clearHrefKeyHover(anchor);
8682
- hoveredNavContainerRef.current = null;
8683
- setHoveredNavContainerRect(null);
8684
- setHoveredItemRect(null);
8685
- hoveredItemElRef.current = null;
8686
- siblingHintElRef.current = null;
8687
- setSiblingHintRect(null);
8688
- setSiblingHintRects([]);
8689
- setIsItemDragging(false);
8690
- const { key, disabled } = getNavigationItemReorderState(anchor);
8691
- setReorderHrefKey(key);
8692
- setReorderDragDisabled(disabled);
8693
- setIsFooterFrameSelection(false);
8694
- setToolbarVariant("link-action");
8695
- setToolbarRect(anchor.getBoundingClientRect());
8696
- setToolbarShowEditLink(false);
8697
- setActiveCommands(/* @__PURE__ */ new Set());
8698
- },
8699
- [deactivate]
8700
- );
8701
- const selectFrame = useCallback4(
8702
- (el) => {
8703
- if (!isNavigationContainer(el)) return;
8704
- if (activeElRef.current) deactivate();
8705
- const isFooterColumn = el.hasAttribute("data-ohw-footer-col") || Boolean(el.closest("footer") && isInferredFooterGroup(el));
8706
- selectedElRef.current = el;
8707
- clearHrefKeyHover(el);
8708
- hoveredNavContainerRef.current = null;
8709
- setHoveredNavContainerRect(null);
8710
- setHoveredItemRect(null);
8711
- hoveredItemElRef.current = null;
8712
- siblingHintElRef.current = null;
8713
- setSiblingHintRect(null);
8714
- setSiblingHintRects(
8715
- isFooterColumn ? listFooterColumns().filter((column) => column !== el).map((column) => column.getBoundingClientRect()) : []
8716
- );
8717
- setIsItemDragging(false);
7780
+ const select = useCallback3((anchor) => {
7781
+ if (!isNavigationItem(anchor)) return;
7782
+ if (activeElRef.current) deactivate();
7783
+ selectedElRef.current = anchor;
7784
+ clearHrefKeyHover(anchor);
7785
+ hoveredNavContainerRef.current = null;
7786
+ setHoveredNavContainerRect(null);
7787
+ setHoveredItemRect(null);
7788
+ hoveredItemElRef.current = null;
7789
+ siblingHintElRef.current = null;
7790
+ setSiblingHintRect(null);
7791
+ setIsItemDragging(false);
7792
+ const { key, disabled } = getNavigationItemReorderState(anchor);
7793
+ setReorderHrefKey(key);
7794
+ setReorderDragDisabled(disabled);
7795
+ setToolbarVariant("link-action");
7796
+ setToolbarRect(anchor.getBoundingClientRect());
7797
+ setToolbarShowEditLink(false);
7798
+ setActiveCommands(/* @__PURE__ */ new Set());
7799
+ }, [deactivate]);
7800
+ const selectFrame = useCallback3((el) => {
7801
+ if (!isNavigationContainer(el)) return;
7802
+ if (activeElRef.current) deactivate();
7803
+ selectedElRef.current = el;
7804
+ clearHrefKeyHover(el);
7805
+ hoveredNavContainerRef.current = null;
7806
+ setHoveredNavContainerRect(null);
7807
+ setHoveredItemRect(null);
7808
+ hoveredItemElRef.current = null;
7809
+ siblingHintElRef.current = null;
7810
+ setSiblingHintRect(null);
7811
+ setIsItemDragging(false);
7812
+ setReorderHrefKey(null);
7813
+ setReorderDragDisabled(false);
7814
+ setToolbarVariant("select-frame");
7815
+ setToolbarRect(el.getBoundingClientRect());
7816
+ setToolbarShowEditLink(false);
7817
+ setActiveCommands(/* @__PURE__ */ new Set());
7818
+ }, [deactivate]);
7819
+ const activate = useCallback3((el, options) => {
7820
+ if (activeElRef.current === el) return;
7821
+ selectedElRef.current = null;
7822
+ deactivate();
7823
+ if (hoveredImageRef.current) {
7824
+ hoveredImageRef.current = null;
7825
+ setMediaHover(null);
7826
+ }
7827
+ setToolbarVariant("rich-text");
7828
+ siblingHintElRef.current = null;
7829
+ setSiblingHintRect(null);
7830
+ setIsItemDragging(false);
7831
+ el.setAttribute("contenteditable", "true");
7832
+ el.removeAttribute("data-ohw-hovered");
7833
+ el.closest("[data-ohw-href-key]")?.removeAttribute("data-ohw-hovered");
7834
+ activeElRef.current = el;
7835
+ originalContentRef.current = el.innerHTML;
7836
+ el.focus();
7837
+ if (options?.caretX !== void 0 && options?.caretY !== void 0) {
7838
+ placeCaretAtPoint(el, options.caretX, options.caretY);
7839
+ }
7840
+ setToolbarShowEditLink(Boolean(getHrefKeyFromElement(el)));
7841
+ const navAnchor = getNavigationItemAnchor(el);
7842
+ if (navAnchor) {
8718
7843
  setReorderHrefKey(null);
8719
7844
  setReorderDragDisabled(false);
8720
- setIsFooterFrameSelection(isFooterColumn);
8721
- setToolbarVariant("select-frame");
8722
- setToolbarRect(el.getBoundingClientRect());
8723
- setToolbarShowEditLink(false);
8724
- setActiveCommands(/* @__PURE__ */ new Set());
8725
- },
8726
- [deactivate]
8727
- );
8728
- const activate = useCallback4(
8729
- (el, options) => {
8730
- if (activeElRef.current === el) return;
8731
- selectedElRef.current = null;
8732
- deactivate();
8733
- if (hoveredImageRef.current) {
8734
- hoveredImageRef.current = null;
8735
- postToParentRef.current({ type: "ow:image-unhover" });
8736
- }
8737
- setToolbarVariant("rich-text");
8738
- siblingHintElRef.current = null;
8739
- setSiblingHintRect(null);
8740
- setSiblingHintRects([]);
8741
- setIsItemDragging(false);
8742
- el.setAttribute("contenteditable", "true");
8743
- el.removeAttribute("data-ohw-hovered");
8744
- el.closest("[data-ohw-href-key]")?.removeAttribute("data-ohw-hovered");
8745
- activeElRef.current = el;
8746
- originalContentRef.current = el.innerHTML;
8747
- el.focus();
8748
- if (options?.caretX !== void 0 && options?.caretY !== void 0) {
8749
- placeCaretAtPoint(el, options.caretX, options.caretY);
8750
- }
8751
- setToolbarShowEditLink(Boolean(getHrefKeyFromElement(el)));
8752
- const navAnchor = getNavigationItemAnchor(el);
8753
- if (navAnchor) {
8754
- setReorderHrefKey(null);
8755
- setReorderDragDisabled(false);
8756
- } else {
8757
- const { key: reorderKey, disabled: reorderDisabled } = getReorderHandleState(el);
8758
- setReorderHrefKey(reorderKey);
8759
- setReorderDragDisabled(reorderDisabled);
8760
- }
8761
- setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
8762
- postToParent2({ type: "ow:enter-edit", key: el.dataset.ohwKey });
8763
- requestAnimationFrame(() => refreshActiveCommandsRef.current());
8764
- },
8765
- [deactivate, postToParent2]
8766
- );
7845
+ } else {
7846
+ const { key: reorderKey, disabled: reorderDisabled } = getReorderHandleState(el);
7847
+ setReorderHrefKey(reorderKey);
7848
+ setReorderDragDisabled(reorderDisabled);
7849
+ }
7850
+ setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
7851
+ postToParent2({ type: "ow:enter-edit", key: el.dataset.ohwKey });
7852
+ requestAnimationFrame(() => refreshActiveCommandsRef.current());
7853
+ }, [deactivate, postToParent2]);
8767
7854
  activateRef.current = activate;
8768
7855
  deactivateRef.current = deactivate;
8769
7856
  selectRef.current = select;
@@ -8779,7 +7866,6 @@ function OhhwellsBridge() {
8779
7866
  for (const [key, val] of Object.entries(content)) {
8780
7867
  if (key === "__ohw_sections") continue;
8781
7868
  if (applyVideoSettingNode(key, val)) continue;
8782
- if (applyCarouselNode(key, val)) continue;
8783
7869
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
8784
7870
  if (el.dataset.ohwEditable === "image") {
8785
7871
  const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
@@ -8811,7 +7897,6 @@ function OhhwellsBridge() {
8811
7897
  applyLinkByKey(key, val);
8812
7898
  }
8813
7899
  reconcileNavbarItemsFromContent(content);
8814
- reconcileFooterOrderFromContent(content);
8815
7900
  enforceLinkHrefs();
8816
7901
  initSectionsFromContent(content, true);
8817
7902
  sectionsLoadedRef.current = true;
@@ -8840,7 +7925,7 @@ function OhhwellsBridge() {
8840
7925
  cancelled = true;
8841
7926
  };
8842
7927
  }, [subdomain, isEditMode]);
8843
- useEffect8(() => {
7928
+ useEffect7(() => {
8844
7929
  if (!subdomain || isEditMode) return;
8845
7930
  let debounceTimer = null;
8846
7931
  let observer = null;
@@ -8853,7 +7938,6 @@ function OhhwellsBridge() {
8853
7938
  for (const [key, val] of Object.entries(content)) {
8854
7939
  if (key === "__ohw_sections") continue;
8855
7940
  if (applyVideoSettingNode(key, val)) continue;
8856
- if (applyCarouselNode(key, val)) continue;
8857
7941
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
8858
7942
  if (el.dataset.ohwEditable === "image") {
8859
7943
  const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
@@ -8873,7 +7957,6 @@ function OhhwellsBridge() {
8873
7957
  applyLinkByKey(key, val);
8874
7958
  }
8875
7959
  reconcileNavbarItemsFromContent(content);
8876
- reconcileFooterOrderFromContent(content);
8877
7960
  } finally {
8878
7961
  observer?.observe(document.body, { childList: true, subtree: true });
8879
7962
  }
@@ -8897,10 +7980,10 @@ function OhhwellsBridge() {
8897
7980
  const visible = Boolean(subdomain) && fetchState !== "done";
8898
7981
  el.style.display = visible ? "flex" : "none";
8899
7982
  }, [subdomain, fetchState]);
8900
- useEffect8(() => {
7983
+ useEffect7(() => {
8901
7984
  postToParent2({ type: "ow:navigation", path: pathname });
8902
7985
  }, [pathname, postToParent2]);
8903
- useEffect8(() => {
7986
+ useEffect7(() => {
8904
7987
  if (!isEditMode) return;
8905
7988
  if (linkPopoverSessionRef.current?.intent === "add-nav") return;
8906
7989
  if (document.querySelector("[data-ohw-section-picker]")) return;
@@ -8908,50 +7991,23 @@ function OhhwellsBridge() {
8908
7991
  deselectRef.current();
8909
7992
  deactivateRef.current();
8910
7993
  }, [pathname, isEditMode]);
8911
- useEffect8(() => {
7994
+ useEffect7(() => {
8912
7995
  const contentForNav = () => {
8913
7996
  if (isEditMode) return editContentRef.current;
8914
7997
  if (!subdomain) return {};
8915
7998
  return contentCache.get(subdomain) ?? {};
8916
7999
  };
8917
- let applying = false;
8918
- let rafId = null;
8919
- const run = () => {
8920
- if (footerDragRef.current || applying) return;
8921
- applying = true;
8922
- try {
8923
- const content = contentForNav();
8924
- reconcileNavbarItemsFromContent(content);
8925
- reconcileFooterOrderFromContent(content);
8926
- document.querySelectorAll("footer [data-ohw-href-key]").forEach((el) => {
8927
- if (isFooterHrefKey(el.getAttribute("data-ohw-href-key"))) {
8928
- disableNativeHrefDrag(el);
8929
- }
8930
- });
8931
- } finally {
8932
- applying = false;
8933
- }
8934
- };
8935
- const scheduleRun = () => {
8936
- if (rafId !== null) cancelAnimationFrame(rafId);
8937
- rafId = requestAnimationFrame(() => {
8938
- rafId = null;
8939
- run();
8940
- });
8941
- };
8000
+ const run = () => reconcileNavbarItemsFromContent(contentForNav());
8942
8001
  run();
8943
8002
  const nav = document.querySelector("nav");
8944
- const footer = document.querySelector("footer");
8945
- const observer = new MutationObserver(scheduleRun);
8946
- if (nav) observer.observe(nav, { childList: true, subtree: true });
8947
- if (footer) observer.observe(footer, { childList: true, subtree: true });
8948
- if (!nav && !footer) return;
8949
- return () => {
8950
- observer.disconnect();
8951
- if (rafId !== null) cancelAnimationFrame(rafId);
8952
- };
8003
+ if (!nav) return;
8004
+ const observer = new MutationObserver(() => {
8005
+ requestAnimationFrame(run);
8006
+ });
8007
+ observer.observe(nav, { childList: true, subtree: true });
8008
+ return () => observer.disconnect();
8953
8009
  }, [isEditMode, pathname, subdomain, fetchState]);
8954
- useEffect8(() => {
8010
+ useEffect7(() => {
8955
8011
  if (!isEditMode) return;
8956
8012
  const measure = () => {
8957
8013
  const h = document.body.scrollHeight;
@@ -8975,7 +8031,7 @@ function OhhwellsBridge() {
8975
8031
  window.removeEventListener("resize", handleResize);
8976
8032
  };
8977
8033
  }, [pathname, isEditMode, postToParent2]);
8978
- useEffect8(() => {
8034
+ useEffect7(() => {
8979
8035
  if (!subdomainFromQuery || isEditMode) return;
8980
8036
  const handleClick = (e) => {
8981
8037
  const anchor = e.target.closest("a");
@@ -8991,7 +8047,7 @@ function OhhwellsBridge() {
8991
8047
  document.addEventListener("click", handleClick, true);
8992
8048
  return () => document.removeEventListener("click", handleClick, true);
8993
8049
  }, [subdomainFromQuery, isEditMode, router]);
8994
- useEffect8(() => {
8050
+ useEffect7(() => {
8995
8051
  if (!isEditMode) {
8996
8052
  editStylesRef.current?.base.remove();
8997
8053
  editStylesRef.current?.forceHover.remove();
@@ -9014,32 +8070,6 @@ function OhhwellsBridge() {
9014
8070
  [data-ohw-editable] {
9015
8071
  display: block;
9016
8072
  }
9017
- /* Native <a> drag steals clicks \u2014 disable for edit links; reorder via press-to-drag / handle. */
9018
- footer [data-ohw-href-key] {
9019
- -webkit-user-drag: none !important;
9020
- }
9021
- footer [data-ohw-footer-col]:hover {
9022
- outline: 1.5px dashed ${PRIMARY2} !important;
9023
- outline-offset: 6px;
9024
- border-radius: 8px;
9025
- }
9026
- html[data-ohw-link-popover-open] footer [data-ohw-footer-col]:hover {
9027
- outline: none !important;
9028
- }
9029
- html[data-ohw-footer-press-drag] footer,
9030
- html[data-ohw-footer-press-drag] footer * {
9031
- user-select: none !important;
9032
- -webkit-user-select: none !important;
9033
- }
9034
- html[data-ohw-item-dragging] footer,
9035
- html[data-ohw-item-dragging] footer * {
9036
- user-select: none !important;
9037
- -webkit-user-select: none !important;
9038
- pointer-events: none !important;
9039
- }
9040
- html[data-ohw-item-dragging] {
9041
- cursor: grabbing !important;
9042
- }
9043
8073
  [data-ohw-editable]:not([contenteditable]):not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]):not([data-ohw-editable="video"]) { cursor: text !important; }
9044
8074
  [data-ohw-editable="image"], [data-ohw-editable="image"] *,
9045
8075
  [data-ohw-editable="video"], [data-ohw-editable="video"] *,
@@ -9084,39 +8114,12 @@ function OhhwellsBridge() {
9084
8114
  }
9085
8115
  refreshStateRules();
9086
8116
  const handleClick = (e) => {
9087
- if (suppressNextClickRef.current) {
9088
- suppressNextClickRef.current = false;
9089
- e.preventDefault();
9090
- e.stopPropagation();
9091
- return;
9092
- }
9093
8117
  const target = e.target;
9094
8118
  if (target.closest("[data-ohw-toolbar]")) return;
9095
8119
  if (target.closest("[data-ohw-state-toggle]")) return;
9096
8120
  if (target.closest("[data-ohw-max-badge]")) return;
9097
8121
  if (isInsideLinkEditor(target)) return;
9098
8122
  if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
9099
- if (target.closest("[data-ohw-item-drag-surface]")) {
9100
- e.preventDefault();
9101
- e.stopPropagation();
9102
- const selected = selectedElRef.current;
9103
- if (selected && isNavigationItem(selected)) {
9104
- const editable2 = selected.querySelector('[data-ohw-editable="text"]') ?? selected.querySelector("[data-ohw-editable]");
9105
- if (editable2) {
9106
- activateRef.current(editable2, {
9107
- caretX: e.clientX,
9108
- caretY: e.clientY
9109
- });
9110
- }
9111
- } else if (selected?.hasAttribute("data-ohw-footer-col")) {
9112
- const link = listFooterLinksInColumn(selected).find((el) => {
9113
- const r2 = el.getBoundingClientRect();
9114
- return e.clientX >= r2.left && e.clientX <= r2.right && e.clientY >= r2.top && e.clientY <= r2.bottom;
9115
- });
9116
- if (link) selectRef.current(link);
9117
- }
9118
- return;
9119
- }
9120
8123
  const navFromChrome = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
9121
8124
  if (navFromChrome) {
9122
8125
  e.preventDefault();
@@ -9146,15 +8149,7 @@ function OhhwellsBridge() {
9146
8149
  if (isMediaEditable(editable)) {
9147
8150
  e.preventDefault();
9148
8151
  e.stopPropagation();
9149
- const key = editable.dataset.ohwKey ?? "";
9150
- const r2 = editable.getBoundingClientRect();
9151
- if (key && r2.width > 1 && r2.height > 1) {
9152
- pendingUploadRectRef.current = {
9153
- key,
9154
- rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height }
9155
- };
9156
- }
9157
- postToParentRef.current({ type: "ow:image-pick", key, elementType: editable.dataset.ohwEditable ?? "image" });
8152
+ postToParentRef.current({ type: "ow:image-pick", key: editable.dataset.ohwKey ?? "", elementType: editable.dataset.ohwEditable ?? "image" });
9158
8153
  return;
9159
8154
  }
9160
8155
  const hrefCtx = getHrefKeyFromElement(editable);
@@ -9163,7 +8158,6 @@ function OhhwellsBridge() {
9163
8158
  e.preventDefault();
9164
8159
  e.stopPropagation();
9165
8160
  if (selectedElRef.current === navAnchor) {
9166
- if (e.detail >= 2) return;
9167
8161
  activateRef.current(editable, { caretX: e.clientX, caretY: e.clientY });
9168
8162
  return;
9169
8163
  }
@@ -9179,26 +8173,10 @@ function OhhwellsBridge() {
9179
8173
  if (hrefAnchor) {
9180
8174
  e.preventDefault();
9181
8175
  e.stopPropagation();
9182
- if (selectedElRef.current === hrefAnchor) {
9183
- const textEditable = hrefAnchor.querySelector('[data-ohw-editable="text"]') ?? hrefAnchor.querySelector("[data-ohw-editable]");
9184
- if (textEditable) {
9185
- activateRef.current(textEditable, {
9186
- caretX: e.clientX,
9187
- caretY: e.clientY
9188
- });
9189
- }
9190
- return;
9191
- }
8176
+ if (selectedElRef.current === hrefAnchor) return;
9192
8177
  selectRef.current(hrefAnchor);
9193
8178
  return;
9194
8179
  }
9195
- const footerColClick = target.closest("[data-ohw-footer-col]");
9196
- if (footerColClick) {
9197
- e.preventDefault();
9198
- e.stopPropagation();
9199
- selectFrameRef.current(footerColClick);
9200
- return;
9201
- }
9202
8180
  const navContainerToSelect = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
9203
8181
  if (navContainerToSelect) {
9204
8182
  e.preventDefault();
@@ -9240,38 +8218,9 @@ function OhhwellsBridge() {
9240
8218
  deselectRef.current();
9241
8219
  deactivateRef.current();
9242
8220
  };
9243
- const handleDblClick = (e) => {
9244
- const target = e.target;
9245
- if (target.closest("[data-ohw-toolbar]")) return;
9246
- if (target.closest("[data-ohw-state-toggle]")) return;
9247
- if (target.closest("[data-ohw-max-badge]")) return;
9248
- if (isInsideLinkEditor(target)) return;
9249
- if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
9250
- return;
9251
- }
9252
- const navLabel = getNavigationLabelEditable(target);
9253
- if (!navLabel) return;
9254
- const { editable } = navLabel;
9255
- e.preventDefault();
9256
- e.stopPropagation();
9257
- if (activeElRef.current !== editable) {
9258
- activateRef.current(editable);
9259
- }
9260
- requestAnimationFrame(() => {
9261
- selectAllTextInEditable(editable);
9262
- refreshActiveCommandsRef.current();
9263
- });
9264
- };
9265
8221
  const handleMouseOver = (e) => {
9266
8222
  if (document.documentElement.hasAttribute("data-ohw-section-picking")) return;
9267
8223
  const target = e.target;
9268
- if (linkPopoverOpenRef.current) {
9269
- hoveredItemElRef.current = null;
9270
- setHoveredItemRect(null);
9271
- hoveredNavContainerRef.current = null;
9272
- setHoveredNavContainerRect(null);
9273
- return;
9274
- }
9275
8224
  if (toolbarVariantRef.current !== "select-frame") {
9276
8225
  const navContainer = target.closest("[data-ohw-nav-container]");
9277
8226
  if (navContainer && !getNavigationItemAnchor(target)) {
@@ -9286,15 +8235,6 @@ function OhhwellsBridge() {
9286
8235
  setHoveredNavContainerRect(null);
9287
8236
  }
9288
8237
  }
9289
- const footerCol = target.closest("[data-ohw-footer-col]");
9290
- if (footerCol) {
9291
- hoveredNavContainerRef.current = null;
9292
- setHoveredNavContainerRect(null);
9293
- if (selectedElRef.current === footerCol) return;
9294
- hoveredItemElRef.current = footerCol;
9295
- setHoveredItemRect(footerCol.getBoundingClientRect());
9296
- return;
9297
- }
9298
8238
  const navAnchor = getNavigationItemAnchor(target);
9299
8239
  if (navAnchor) {
9300
8240
  hoveredNavContainerRef.current = null;
@@ -9331,15 +8271,6 @@ function OhhwellsBridge() {
9331
8271
  hoveredNavContainerRef.current = null;
9332
8272
  setHoveredNavContainerRect(null);
9333
8273
  }
9334
- const footerCol = target.closest("[data-ohw-footer-col]");
9335
- if (footerCol && hoveredItemElRef.current === footerCol) {
9336
- const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
9337
- if (related2?.closest("[data-ohw-drag-handle-container], [data-ohw-item-interaction]")) return;
9338
- if (related2?.closest("[data-ohw-footer-col]") === footerCol) return;
9339
- hoveredItemElRef.current = null;
9340
- setHoveredItemRect(null);
9341
- return;
9342
- }
9343
8274
  const navAnchor = getNavigationItemAnchor(target);
9344
8275
  if (navAnchor) {
9345
8276
  const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
@@ -9451,12 +8382,12 @@ function OhhwellsBridge() {
9451
8382
  const stickyPad = 48;
9452
8383
  const withinPad = x >= pr.left - stickyPad && x <= pr.left + pr.width + stickyPad && y >= pr.top - stickyPad && y <= pr.top + pr.height + stickyPad;
9453
8384
  if (withinPad) {
9454
- const yieldToSmaller = smallest !== pinned && candidatePool.includes(smallest) && (() => {
8385
+ if (smallest !== pinned && candidatePool.includes(smallest)) {
9455
8386
  const sr = getVisibleRect(smallest);
9456
- const pr2 = getVisibleRect(pinned);
9457
- return sr.width * sr.height < pr2.width * pr2.height;
9458
- })();
9459
- if (!yieldToSmaller) return pinned;
8387
+ const overOther = x >= sr.left && x <= sr.left + sr.width && y >= sr.top && y <= sr.top + sr.height;
8388
+ if (overOther) return smallest;
8389
+ }
8390
+ return pinned;
9460
8391
  }
9461
8392
  }
9462
8393
  return smallest;
@@ -9468,7 +8399,6 @@ function OhhwellsBridge() {
9468
8399
  resumeAnimTracks();
9469
8400
  postToParentRef.current({ type: "ow:image-unhover" });
9470
8401
  }
9471
- clearImageHover();
9472
8402
  };
9473
8403
  const probeNavigationHoverAt = (x, y) => {
9474
8404
  if (toolbarVariantRef.current === "select-frame") {
@@ -9514,6 +8444,12 @@ function OhhwellsBridge() {
9514
8444
  };
9515
8445
  const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
9516
8446
  if (linkPopoverOpenRef.current) {
8447
+ if (hoveredImageRef.current) {
8448
+ hoveredImageRef.current = null;
8449
+ hoveredImageHasTextOverlapRef.current = false;
8450
+ resumeAnimTracks();
8451
+ clearImageHover();
8452
+ }
9517
8453
  dismissImageHover();
9518
8454
  return;
9519
8455
  }
@@ -9536,12 +8472,36 @@ function OhhwellsBridge() {
9536
8472
  const imgEl = findImageAtPoint(clientX, clientY, fromParentViewport);
9537
8473
  const activeEl = activeElRef.current;
9538
8474
  if (activeEl && (!imgEl || imgEl.contains(activeEl))) {
9539
- dismissImageHover();
9540
- return;
8475
+ if (hoveredImageRef.current) {
8476
+ hoveredImageRef.current = null;
8477
+ hoveredImageHasTextOverlapRef.current = false;
8478
+ resumeAnimTracks();
8479
+ clearImageHover();
8480
+ }
8481
+ if (activeElRef.current) {
8482
+ dismissImageHover();
8483
+ return;
8484
+ }
9541
8485
  }
9542
8486
  if (imgEl) {
9543
- const topEl = document.elementFromPoint(x, y);
9544
- if (topEl?.closest('[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"], [data-ohw-media-chrome]')) {
8487
+ const { x: x2, y: y2 } = toProbeCoords(clientX, clientY, fromParentViewport);
8488
+ const overMediaChrome = Array.from(
8489
+ document.querySelectorAll("[data-ohw-media-chrome]")
8490
+ ).some((el) => {
8491
+ const r2 = el.getBoundingClientRect();
8492
+ return x2 >= r2.left && x2 <= r2.right && y2 >= r2.top && y2 <= r2.bottom;
8493
+ });
8494
+ if (overMediaChrome) {
8495
+ if (hoveredImageRef.current) {
8496
+ hoveredImageRef.current = null;
8497
+ hoveredImageHasTextOverlapRef.current = false;
8498
+ resumeAnimTracks();
8499
+ clearImageHover();
8500
+ }
8501
+ return;
8502
+ }
8503
+ const topEl = document.elementFromPoint(x2, y2);
8504
+ if (topEl?.closest('[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
9545
8505
  if (hoveredImageRef.current) {
9546
8506
  hoveredImageRef.current = null;
9547
8507
  resumeAnimTracks();
@@ -9563,7 +8523,7 @@ function OhhwellsBridge() {
9563
8523
  document.querySelectorAll(NON_MEDIA_SELECTOR)
9564
8524
  ).find((el) => {
9565
8525
  const er = el.getBoundingClientRect();
9566
- return x >= er.left && x <= er.right && y >= er.top && y <= er.bottom;
8526
+ return x2 >= er.left && x2 <= er.right && y2 >= er.top && y2 <= er.bottom;
9567
8527
  });
9568
8528
  if (imageUnhoverTimerRef.current) {
9569
8529
  clearTimeout(imageUnhoverTimerRef.current);
@@ -9748,14 +8708,6 @@ function OhhwellsBridge() {
9748
8708
  probeHoverCardsAt(clientX, clientY);
9749
8709
  };
9750
8710
  const handleDragOver = (e) => {
9751
- const footerSession = footerDragRef.current;
9752
- if (footerSession) {
9753
- e.preventDefault();
9754
- if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
9755
- const slot = footerSession.kind === "link" && footerSession.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, footerSession.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
9756
- refreshFooterDragVisualsRef.current(footerSession, slot, e.clientX, e.clientY);
9757
- return;
9758
- }
9759
8711
  e.preventDefault();
9760
8712
  const el = findImageAtPoint(e.clientX, e.clientY, false);
9761
8713
  if (!el) {
@@ -9824,7 +8776,6 @@ function OhhwellsBridge() {
9824
8776
  if (!entry || entry.fadingOut) return prev;
9825
8777
  return { ...prev, [key]: { ...entry, fadingOut: true } };
9826
8778
  });
9827
- if (pendingUploadRectRef.current?.key === key) pendingUploadRectRef.current = null;
9828
8779
  };
9829
8780
  let found = false;
9830
8781
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -9939,7 +8890,6 @@ function OhhwellsBridge() {
9939
8890
  continue;
9940
8891
  }
9941
8892
  if (applyVideoSettingNode(key, val)) continue;
9942
- if (applyCarouselNode(key, val)) continue;
9943
8893
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
9944
8894
  if (el.dataset.ohwEditable === "image") {
9945
8895
  const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
@@ -9964,7 +8914,6 @@ function OhhwellsBridge() {
9964
8914
  }
9965
8915
  editContentRef.current = { ...editContentRef.current, ...content };
9966
8916
  reconcileNavbarItemsFromContent(editContentRef.current);
9967
- reconcileFooterOrderFromContent(editContentRef.current);
9968
8917
  enforceLinkHrefs();
9969
8918
  postToParentRef.current({ type: "ow:hydrate-done" });
9970
8919
  };
@@ -9990,15 +8939,6 @@ function OhhwellsBridge() {
9990
8939
  window.addEventListener("message", handleUiEscape);
9991
8940
  const handleKeyDown = (e) => {
9992
8941
  if (e.key === "Escape" && document.querySelector("[data-ohw-section-picker]")) return;
9993
- if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "a" && activeElRef.current) {
9994
- const navAnchor = getNavigationItemAnchor(activeElRef.current);
9995
- if (navAnchor) {
9996
- e.preventDefault();
9997
- selectAllTextInEditable(activeElRef.current);
9998
- refreshActiveCommandsRef.current();
9999
- return;
10000
- }
10001
- }
10002
8942
  if (e.key === "Escape" && linkPopoverOpenRef.current) {
10003
8943
  setLinkPopoverRef.current(null);
10004
8944
  return;
@@ -10078,17 +9018,6 @@ function OhhwellsBridge() {
10078
9018
  if (siblingHintElRef.current) {
10079
9019
  setSiblingHintRect(siblingHintElRef.current.getBoundingClientRect());
10080
9020
  }
10081
- const selected = selectedElRef.current;
10082
- if (selected && !footerDragRef.current && (selected.hasAttribute("data-ohw-footer-col") || Boolean(selected.closest("footer") && isInferredFooterGroup(selected)))) {
10083
- setSiblingHintRects(
10084
- listFooterColumns().filter((column) => column !== selected).map((column) => column.getBoundingClientRect())
10085
- );
10086
- }
10087
- if (footerDragRef.current) {
10088
- const session = footerDragRef.current;
10089
- const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
10090
- refreshFooterDragVisualsRef.current(session, slot, session.lastClientX, session.lastClientY);
10091
- }
10092
9021
  if (hoveredImageRef.current) {
10093
9022
  const el = hoveredImageRef.current;
10094
9023
  const r2 = el.getBoundingClientRect();
@@ -10099,7 +9028,7 @@ function OhhwellsBridge() {
10099
9028
  };
10100
9029
  const handleSave = (e) => {
10101
9030
  if (e.data?.type !== "ow:save") return;
10102
- const nodes = collectEditableNodes(editContentRef.current);
9031
+ const nodes = collectEditableNodes();
10103
9032
  const tracker = document.querySelector("[data-ohw-sections-tracker]");
10104
9033
  if (tracker?.textContent) nodes.push({ key: "__ohw_sections", type: "sections", text: tracker.textContent });
10105
9034
  postToParentRef.current({ type: "ow:save-result", nodes });
@@ -10184,49 +9113,28 @@ function OhhwellsBridge() {
10184
9113
  const handleDocMouseLeave = () => {
10185
9114
  hoveredImageRef.current = null;
10186
9115
  setMediaHover(null);
10187
- setCarouselHover(null);
10188
9116
  document.querySelectorAll("[data-ohw-state-hovered]").forEach((el) => el.removeAttribute("data-ohw-state-hovered"));
10189
9117
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
10190
9118
  activeStateElRef.current = null;
10191
9119
  setToggleState(null);
10192
9120
  };
10193
- const resolveUploadRects = (key) => {
10194
- const matches = Array.from(document.querySelectorAll(`[data-ohw-key="${key}"]`));
10195
- const rects = matches.map((el) => {
10196
- const r2 = el.getBoundingClientRect();
10197
- return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
10198
- }).filter((r2) => r2.width > 1 && r2.height > 1);
10199
- if (rects.length > 0) return rects;
10200
- const pending = pendingUploadRectRef.current;
10201
- if (pending?.key === key && pending.rect.width > 1 && pending.rect.height > 1) {
10202
- return [pending.rect];
10203
- }
10204
- const hovered = hoveredImageRef.current;
10205
- if (hovered?.dataset.ohwKey === key) {
10206
- const r2 = hovered.getBoundingClientRect();
10207
- if (r2.width > 1 && r2.height > 1) {
10208
- return [{ top: r2.top, left: r2.left, width: r2.width, height: r2.height }];
10209
- }
10210
- }
10211
- return [];
10212
- };
10213
9121
  const handleImageUploading = (e) => {
10214
- const type = e.data?.type;
10215
- if (type !== "ow:image-uploading" && type !== "ow:anim-lock") return;
10216
- const key = e.data.key;
10217
- if (!key) return;
10218
- const uploading = type === "ow:anim-lock" ? true : !!e.data.uploading;
9122
+ if (e.data?.type !== "ow:image-uploading") return;
9123
+ const { key, uploading } = e.data;
10219
9124
  setUploadingRects((prev) => {
10220
9125
  if (!uploading) {
10221
- if (pendingUploadRectRef.current?.key === key) pendingUploadRectRef.current = null;
10222
9126
  if (!(key in prev)) return prev;
10223
9127
  const next = { ...prev };
10224
9128
  delete next[key];
10225
9129
  return next;
10226
9130
  }
10227
- const rects = resolveUploadRects(key);
10228
- if (rects.length === 0) return prev;
10229
- return { ...prev, [key]: { rects } };
9131
+ const el = document.querySelector(`[data-ohw-key="${key}"]`);
9132
+ if (!el) return prev;
9133
+ const r2 = getVisibleRect(el);
9134
+ return {
9135
+ ...prev,
9136
+ [key]: { rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height } }
9137
+ };
10230
9138
  });
10231
9139
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
10232
9140
  const track = el.closest("[data-ohw-hover-pause]");
@@ -10244,48 +9152,6 @@ function OhhwellsBridge() {
10244
9152
  if (e.data?.type !== "ow:canvas-height" || typeof e.data.height !== "number") return;
10245
9153
  document.documentElement.style.setProperty("--ohw-canvas-h", `${e.data.height}px`);
10246
9154
  };
10247
- const handleCarouselChange = (e) => {
10248
- if (e.data?.type !== "ow:carousel-change") return;
10249
- const { key, images } = e.data;
10250
- if (!key || !Array.isArray(images)) return;
10251
- const text = JSON.stringify(images);
10252
- applyCarouselValue(key, images);
10253
- editContentRef.current = { ...editContentRef.current, [key]: text };
10254
- postToParentRef.current({ type: "ow:change", nodes: [{ key, text }] });
10255
- setCarouselHover(null);
10256
- };
10257
- const findCarouselAtPoint = (clientX, clientY) => {
10258
- const containers = Array.from(document.querySelectorAll(`[${CAROUSEL_ATTR}]`));
10259
- for (let i = containers.length - 1; i >= 0; i--) {
10260
- const r2 = containers[i].getBoundingClientRect();
10261
- if (clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom) {
10262
- return containers[i];
10263
- }
10264
- }
10265
- return null;
10266
- };
10267
- const isPointOverEditable = (scope, clientX, clientY) => {
10268
- const editables = scope.querySelectorAll("[data-ohw-editable], [data-ohw-href-key]");
10269
- for (const el of editables) {
10270
- const r2 = el.getBoundingClientRect();
10271
- if (clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom) return true;
10272
- }
10273
- return false;
10274
- };
10275
- const handleCarouselHover = (e) => {
10276
- const container = findCarouselAtPoint(e.clientX, e.clientY);
10277
- const scope = container?.closest("[data-ohw-section]") ?? container?.parentElement ?? null;
10278
- if (!container || !scope || isPointOverEditable(scope, e.clientX, e.clientY)) {
10279
- setCarouselHover((prev) => prev ? null : prev);
10280
- return;
10281
- }
10282
- const key = container.getAttribute("data-ohw-key") ?? "";
10283
- if (!key) return;
10284
- const r2 = getVisibleRect(container);
10285
- setCarouselHover(
10286
- (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 } }
10287
- );
10288
- };
10289
9155
  const applyToolbarPos = (rect) => {
10290
9156
  const ps = parentScrollRef.current;
10291
9157
  const approxW = 330;
@@ -10394,7 +9260,6 @@ function OhhwellsBridge() {
10394
9260
  window.addEventListener("message", handleRemoveSchedulingSection);
10395
9261
  window.addEventListener("message", handleImageUrl);
10396
9262
  window.addEventListener("message", handleImageUploading);
10397
- window.addEventListener("message", handleCarouselChange);
10398
9263
  window.addEventListener("message", handleCanvasHeight);
10399
9264
  window.addEventListener("message", handleParentScroll);
10400
9265
  window.addEventListener("message", handlePointerSync);
@@ -10406,13 +9271,11 @@ function OhhwellsBridge() {
10406
9271
  };
10407
9272
  window.addEventListener("resize", handleViewportResize, { passive: true });
10408
9273
  document.addEventListener("click", handleClick, true);
10409
- document.addEventListener("dblclick", handleDblClick, true);
10410
9274
  document.addEventListener("paste", handlePaste, true);
10411
9275
  document.addEventListener("input", handleInput, true);
10412
9276
  document.addEventListener("mouseover", handleMouseOver, true);
10413
9277
  document.addEventListener("mouseout", handleMouseOut, true);
10414
9278
  document.addEventListener("mousemove", handleMouseMove, true);
10415
- document.addEventListener("mousemove", handleCarouselHover, true);
10416
9279
  document.addEventListener("mouseleave", handleDocMouseLeave);
10417
9280
  document.addEventListener("dragover", handleDragOver, true);
10418
9281
  document.addEventListener("dragleave", handleDragLeave, true);
@@ -10422,13 +9285,11 @@ function OhhwellsBridge() {
10422
9285
  window.addEventListener("scroll", handleScroll, true);
10423
9286
  return () => {
10424
9287
  document.removeEventListener("click", handleClick, true);
10425
- document.removeEventListener("dblclick", handleDblClick, true);
10426
9288
  document.removeEventListener("paste", handlePaste, true);
10427
9289
  document.removeEventListener("input", handleInput, true);
10428
9290
  document.removeEventListener("mouseover", handleMouseOver, true);
10429
9291
  document.removeEventListener("mouseout", handleMouseOut, true);
10430
9292
  document.removeEventListener("mousemove", handleMouseMove, true);
10431
- document.removeEventListener("mousemove", handleCarouselHover, true);
10432
9293
  document.removeEventListener("mouseleave", handleDocMouseLeave);
10433
9294
  document.removeEventListener("dragover", handleDragOver, true);
10434
9295
  document.removeEventListener("dragleave", handleDragLeave, true);
@@ -10444,7 +9305,6 @@ function OhhwellsBridge() {
10444
9305
  window.removeEventListener("message", handleRemoveSchedulingSection);
10445
9306
  window.removeEventListener("message", handleImageUrl);
10446
9307
  window.removeEventListener("message", handleImageUploading);
10447
- window.removeEventListener("message", handleCarouselChange);
10448
9308
  window.removeEventListener("message", handleCanvasHeight);
10449
9309
  window.removeEventListener("message", handleParentScroll);
10450
9310
  window.removeEventListener("resize", handleViewportResize);
@@ -10459,158 +9319,7 @@ function OhhwellsBridge() {
10459
9319
  if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
10460
9320
  };
10461
9321
  }, [isEditMode, refreshStateRules]);
10462
- useEffect8(() => {
10463
- if (!isEditMode) return;
10464
- const THRESHOLD = 10;
10465
- const resolveWasSelected = (el) => {
10466
- if (selectedElRef.current === el) return true;
10467
- const activeAnchor = activeElRef.current ? getNavigationItemAnchor(activeElRef.current) : null;
10468
- return activeAnchor === el;
10469
- };
10470
- const onPointerDown = (e) => {
10471
- if (e.button !== 0) return;
10472
- if (suppressNextClickRef.current && !footerDragRef.current && !footerPointerDragRef.current?.started) {
10473
- suppressNextClickRef.current = false;
10474
- }
10475
- if (footerDragRef.current) return;
10476
- const target = e.target;
10477
- if (!target) return;
10478
- 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]')) {
10479
- return;
10480
- }
10481
- if (target.closest("[data-ohw-item-drag-surface]")) return;
10482
- const anchor = getNavigationItemAnchor(target);
10483
- const hrefKey = anchor?.getAttribute("data-ohw-href-key") ?? null;
10484
- if (anchor && isFooterHrefKey(hrefKey)) {
10485
- armFooterPressDrag();
10486
- footerPointerDragRef.current = {
10487
- el: anchor,
10488
- kind: "link",
10489
- startX: e.clientX,
10490
- startY: e.clientY,
10491
- pointerId: e.pointerId,
10492
- wasSelected: resolveWasSelected(anchor),
10493
- started: false
10494
- };
10495
- return;
10496
- }
10497
- const col = target.closest("[data-ohw-footer-col]");
10498
- if (col && !getNavigationItemAnchor(target)) {
10499
- armFooterPressDrag();
10500
- footerPointerDragRef.current = {
10501
- el: col,
10502
- kind: "column",
10503
- startX: e.clientX,
10504
- startY: e.clientY,
10505
- pointerId: e.pointerId,
10506
- wasSelected: resolveWasSelected(col),
10507
- started: false
10508
- };
10509
- }
10510
- };
10511
- const onPointerMove = (e) => {
10512
- const pending = footerPointerDragRef.current;
10513
- if (!pending) return;
10514
- if (pending.started) {
10515
- e.preventDefault();
10516
- clearTextSelection();
10517
- const session = footerDragRef.current;
10518
- if (!session) return;
10519
- const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, session.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
10520
- refreshFooterDragVisualsRef.current(session, slot, e.clientX, e.clientY);
10521
- return;
10522
- }
10523
- const dx = e.clientX - pending.startX;
10524
- const dy = e.clientY - pending.startY;
10525
- if (dx * dx + dy * dy < THRESHOLD * THRESHOLD) return;
10526
- e.preventDefault();
10527
- pending.started = true;
10528
- clearTextSelection();
10529
- try {
10530
- document.body.setPointerCapture(pending.pointerId);
10531
- } catch {
10532
- }
10533
- if (linkPopoverOpenRef.current) {
10534
- setLinkPopoverRef.current(null);
10535
- }
10536
- if (activeElRef.current) {
10537
- deactivateRef.current();
10538
- }
10539
- if (pending.kind === "link") {
10540
- const key = pending.el.getAttribute("data-ohw-href-key");
10541
- if (!key) return;
10542
- const column = findFooterColumnForLink(pending.el);
10543
- const columns2 = listFooterColumns();
10544
- beginFooterDragRef.current({
10545
- kind: "link",
10546
- hrefKey: key,
10547
- columnEl: column,
10548
- sourceColumnIndex: column ? columns2.indexOf(column) : 0,
10549
- wasSelected: pending.wasSelected,
10550
- draggedEl: pending.el,
10551
- lastClientX: e.clientX,
10552
- lastClientY: e.clientY,
10553
- activeSlot: null
10554
- });
10555
- return;
10556
- }
10557
- const columns = listFooterColumns();
10558
- const idx = columns.indexOf(pending.el);
10559
- if (idx < 0) return;
10560
- beginFooterDragRef.current({
10561
- kind: "column",
10562
- hrefKey: null,
10563
- columnEl: pending.el,
10564
- sourceColumnIndex: idx,
10565
- wasSelected: pending.wasSelected,
10566
- draggedEl: pending.el,
10567
- lastClientX: e.clientX,
10568
- lastClientY: e.clientY,
10569
- activeSlot: null
10570
- });
10571
- };
10572
- const endPointerDrag = (e) => {
10573
- const pending = footerPointerDragRef.current;
10574
- footerPointerDragRef.current = null;
10575
- try {
10576
- if (document.body.hasPointerCapture(e.pointerId)) {
10577
- document.body.releasePointerCapture(e.pointerId);
10578
- }
10579
- } catch {
10580
- }
10581
- if (!pending?.started) {
10582
- unlockFooterDragInteraction();
10583
- return;
10584
- }
10585
- suppressNextClickRef.current = true;
10586
- commitFooterDragRef.current(e.clientX, e.clientY);
10587
- };
10588
- const blockSelectStart = (e) => {
10589
- if (footerDragRef.current || footerPointerDragRef.current?.started || document.documentElement.hasAttribute("data-ohw-footer-press-drag")) {
10590
- e.preventDefault();
10591
- }
10592
- };
10593
- const onDragEnd = (_e) => {
10594
- if (!footerDragRef.current) return;
10595
- commitFooterDragRef.current();
10596
- };
10597
- document.addEventListener("pointerdown", onPointerDown, true);
10598
- document.addEventListener("pointermove", onPointerMove, true);
10599
- document.addEventListener("pointerup", endPointerDrag, true);
10600
- document.addEventListener("pointercancel", endPointerDrag, true);
10601
- document.addEventListener("selectstart", blockSelectStart, true);
10602
- document.addEventListener("dragend", onDragEnd, true);
10603
- return () => {
10604
- document.removeEventListener("pointerdown", onPointerDown, true);
10605
- document.removeEventListener("pointermove", onPointerMove, true);
10606
- document.removeEventListener("pointerup", endPointerDrag, true);
10607
- document.removeEventListener("pointercancel", endPointerDrag, true);
10608
- document.removeEventListener("selectstart", blockSelectStart, true);
10609
- document.removeEventListener("dragend", onDragEnd, true);
10610
- unlockFooterDragInteraction();
10611
- };
10612
- }, [isEditMode]);
10613
- useEffect8(() => {
9322
+ useEffect7(() => {
10614
9323
  const handler = (e) => {
10615
9324
  if (e.data?.type !== "ow:request-schedule-config") return;
10616
9325
  const insertAfterVal = e.data.insertAfter;
@@ -10626,7 +9335,7 @@ function OhhwellsBridge() {
10626
9335
  window.addEventListener("message", handler);
10627
9336
  return () => window.removeEventListener("message", handler);
10628
9337
  }, [processConfigRequest]);
10629
- useEffect8(() => {
9338
+ useEffect7(() => {
10630
9339
  if (!isEditMode) return;
10631
9340
  document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
10632
9341
  el.removeAttribute("data-ohw-active-state");
@@ -10647,13 +9356,7 @@ function OhhwellsBridge() {
10647
9356
  const next = { ...prev, [pathKey]: sections };
10648
9357
  return shouldUseDevFixtures() ? { ...DEV_SECTIONS_BY_PATH, ...next } : next;
10649
9358
  });
10650
- postToParent2({
10651
- type: "ow:ready",
10652
- version: "1",
10653
- path: pathname,
10654
- nodes: collectEditableNodes(editContentRef.current),
10655
- sections
10656
- });
9359
+ postToParent2({ type: "ow:ready", version: "1", path: pathname, nodes: collectEditableNodes(), sections });
10657
9360
  postToParent2({ type: "ow:request-site-pages" });
10658
9361
  }, 150);
10659
9362
  return () => {
@@ -10661,19 +9364,19 @@ function OhhwellsBridge() {
10661
9364
  clearTimeout(timer);
10662
9365
  };
10663
9366
  }, [pathname, isEditMode, refreshStateRules, postToParent2]);
10664
- useEffect8(() => {
9367
+ useEffect7(() => {
10665
9368
  scrollToHashSectionWhenReady();
10666
9369
  const onHashChange = () => scrollToHashSectionWhenReady();
10667
9370
  window.addEventListener("hashchange", onHashChange);
10668
9371
  return () => window.removeEventListener("hashchange", onHashChange);
10669
9372
  }, [pathname]);
10670
- const handleCommand = useCallback4((cmd) => {
9373
+ const handleCommand = useCallback3((cmd) => {
10671
9374
  document.execCommand(cmd, false);
10672
9375
  activeElRef.current?.focus();
10673
9376
  if (activeElRef.current) setToolbarRect(getEditMeasureEl(activeElRef.current).getBoundingClientRect());
10674
9377
  refreshActiveCommandsRef.current();
10675
9378
  }, []);
10676
- const handleStateChange = useCallback4((state) => {
9379
+ const handleStateChange = useCallback3((state) => {
10677
9380
  if (!activeStateElRef.current) return;
10678
9381
  const el = activeStateElRef.current;
10679
9382
  if (state === "Default") {
@@ -10686,11 +9389,11 @@ function OhhwellsBridge() {
10686
9389
  }
10687
9390
  setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
10688
9391
  }, [deactivate]);
10689
- const closeLinkPopover = useCallback4(() => {
9392
+ const closeLinkPopover = useCallback3(() => {
10690
9393
  addNavAfterAnchorRef.current = null;
10691
9394
  setLinkPopover(null);
10692
9395
  }, []);
10693
- const openLinkPopoverForActive = useCallback4(() => {
9396
+ const openLinkPopoverForActive = useCallback3(() => {
10694
9397
  const hrefCtx = getHrefKeyFromElement(activeElRef.current);
10695
9398
  if (!hrefCtx) return;
10696
9399
  bumpLinkPopoverGrace();
@@ -10701,7 +9404,7 @@ function OhhwellsBridge() {
10701
9404
  });
10702
9405
  deactivate();
10703
9406
  }, [deactivate]);
10704
- const openLinkPopoverForSelected = useCallback4(() => {
9407
+ const openLinkPopoverForSelected = useCallback3(() => {
10705
9408
  const anchor = selectedElRef.current;
10706
9409
  if (!anchor) return;
10707
9410
  const key = anchor.getAttribute("data-ohw-href-key");
@@ -10714,7 +9417,7 @@ function OhhwellsBridge() {
10714
9417
  });
10715
9418
  deselect();
10716
9419
  }, [deselect]);
10717
- const handleLinkPopoverSubmit = useCallback4(
9420
+ const handleLinkPopoverSubmit = useCallback3(
10718
9421
  (target) => {
10719
9422
  const session = linkPopoverSessionRef.current;
10720
9423
  if (!session) return;
@@ -10770,22 +9473,16 @@ function OhhwellsBridge() {
10770
9473
  },
10771
9474
  [postToParent2, sitePages, sectionsByPath]
10772
9475
  );
10773
- const handleMediaReplace = useCallback4(
9476
+ const showEditLink = toolbarShowEditLink;
9477
+ const currentSections = sectionsByPath[pathname] ?? [];
9478
+ linkPopoverOpenRef.current = linkPopover !== null;
9479
+ const handleMediaReplace = useCallback3(
10774
9480
  (key) => {
10775
- if (mediaHover?.key === key) {
10776
- pendingUploadRectRef.current = { key, rect: mediaHover.rect };
10777
- }
10778
9481
  postToParent2({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
10779
9482
  },
10780
- [postToParent2, mediaHover]
9483
+ [postToParent2, mediaHover?.elementType]
10781
9484
  );
10782
- const handleEditCarousel = useCallback4(
10783
- (key) => {
10784
- postToParent2({ type: "ow:carousel-open", key, images: readCarouselValue(key) });
10785
- },
10786
- [postToParent2]
10787
- );
10788
- const handleMediaFadeOutComplete = useCallback4((key) => {
9485
+ const handleMediaFadeOutComplete = useCallback3((key) => {
10789
9486
  setUploadingRects((prev) => {
10790
9487
  if (!(key in prev)) return prev;
10791
9488
  const next = { ...prev };
@@ -10793,7 +9490,7 @@ function OhhwellsBridge() {
10793
9490
  return next;
10794
9491
  });
10795
9492
  }, []);
10796
- const handleVideoSettingsChange = useCallback4(
9493
+ const handleVideoSettingsChange = useCallback3(
10797
9494
  (key, settings) => {
10798
9495
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
10799
9496
  const video = getVideoEl(el);
@@ -10815,26 +9512,21 @@ function OhhwellsBridge() {
10815
9512
  },
10816
9513
  [postToParent2]
10817
9514
  );
10818
- const showEditLink = toolbarShowEditLink;
10819
- const currentSections = sectionsByPath[pathname] ?? [];
10820
- linkPopoverOpenRef.current = linkPopover !== null;
10821
9515
  return bridgeRoot ? createPortal2(
10822
- /* @__PURE__ */ jsxs14(Fragment5, { children: [
10823
- /* @__PURE__ */ jsx25("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
10824
- Object.entries(uploadingRects).flatMap(
10825
- ([key, { rects, fadingOut }]) => rects.map((rect, i) => /* @__PURE__ */ jsx25(
10826
- MediaOverlay,
10827
- {
10828
- hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
10829
- isUploading: true,
10830
- fadingOut,
10831
- onFadeOutComplete: handleMediaFadeOutComplete,
10832
- onReplace: handleMediaReplace
10833
- },
10834
- `uploading-${key}-${i}`
10835
- ))
10836
- ),
10837
- mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ jsx25(
9516
+ /* @__PURE__ */ jsxs13(Fragment5, { children: [
9517
+ /* @__PURE__ */ jsx23("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
9518
+ Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ jsx23(
9519
+ MediaOverlay,
9520
+ {
9521
+ hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
9522
+ isUploading: true,
9523
+ fadingOut,
9524
+ onFadeOutComplete: handleMediaFadeOutComplete,
9525
+ onReplace: handleMediaReplace
9526
+ },
9527
+ `uploading-${key}`
9528
+ )),
9529
+ mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ jsx23(
10838
9530
  MediaOverlay,
10839
9531
  {
10840
9532
  hover: mediaHover,
@@ -10843,33 +9535,62 @@ function OhhwellsBridge() {
10843
9535
  onVideoSettingsChange: handleVideoSettingsChange
10844
9536
  }
10845
9537
  ),
10846
- carouselHover && /* @__PURE__ */ jsx25(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
10847
- siblingHintRect && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
10848
- siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
10849
- isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
10850
- isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ jsx25(
10851
- "div",
9538
+ siblingHintRect && !isItemDragging && /* @__PURE__ */ jsx23(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
9539
+ hoveredNavContainerRect && toolbarVariant !== "select-frame" && !linkPopover && !isItemDragging && !siblingHintRect && /* @__PURE__ */ jsx23(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
9540
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx23(
9541
+ NavbarContainerChrome,
10852
9542
  {
10853
- className: "pointer-events-none fixed z-2147483646",
10854
- style: {
10855
- left: slot.left,
10856
- top: slot.top,
10857
- width: slot.width,
10858
- height: slot.height
10859
- },
10860
- children: /* @__PURE__ */ jsx25(DropIndicator, { direction: slot.direction, state: activeFooterDropIndex === i ? "dragActive" : "dragIdle", className: slot.direction === "horizontal" ? "!h-full !w-full" : "!h-full !w-full" })
10861
- },
10862
- `footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
10863
- )),
10864
- hoveredNavContainerRect && toolbarVariant !== "select-frame" && !linkPopover && !isItemDragging && !siblingHintRect && siblingHintRects.length === 0 && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
10865
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && /* @__PURE__ */ jsx25(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
10866
- hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !siblingHintRect && siblingHintRects.length === 0 && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
10867
- toolbarRect && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: isItemDragging && draggedItemRect && footerDragRef.current?.wasSelected ? draggedItemRect : toolbarRect, elRef: glowElRef, state: isItemDragging ? "dragging" : resolveItemInteractionState(toolbarRect, parentScrollRef.current), showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey) || toolbarVariant === "select-frame" && isFooterFrameSelection, dragDisabled: reorderDragDisabled, dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item", onDragHandleDragStart: handleItemDragStart, onDragHandleDragEnd: handleItemDragEnd, onItemPointerDown: handleItemChromePointerDown, onItemClick: handleItemChromeClick, toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ jsx25(ItemActionToolbar, { onEditLink: openLinkPopoverForSelected, addItemDisabled: true, editLinkDisabled: false, moreDisabled: true }) : void 0 }),
10868
- toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ jsxs14(Fragment5, { children: [
10869
- /* @__PURE__ */ jsx25(EditGlowChrome, { rect: toolbarRect, elRef: glowElRef, reorderHrefKey, dragDisabled: reorderDragDisabled }),
10870
- /* @__PURE__ */ jsx25(FloatingToolbar, { rect: toolbarRect, parentScroll: parentScrollRef.current, elRef: toolbarElRef, onCommand: handleCommand, activeCommands, showEditLink, onEditLink: openLinkPopoverForActive })
9543
+ rect: toolbarRect,
9544
+ onAdd: handleAddTopLevelNavItem
9545
+ }
9546
+ ),
9547
+ hoveredItemRect && !hoveredNavContainerRect && !siblingHintRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx23(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
9548
+ toolbarRect && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ jsx23(
9549
+ ItemInteractionLayer,
9550
+ {
9551
+ rect: toolbarRect,
9552
+ elRef: glowElRef,
9553
+ state: isItemDragging ? "dragging" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
9554
+ showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey),
9555
+ dragDisabled: reorderDragDisabled,
9556
+ dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
9557
+ onDragHandleDragStart: handleItemDragStart,
9558
+ onDragHandleDragEnd: handleItemDragEnd,
9559
+ toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ jsx23(
9560
+ ItemActionToolbar,
9561
+ {
9562
+ onEditLink: openLinkPopoverForSelected,
9563
+ addItemDisabled: true,
9564
+ editLinkDisabled: false,
9565
+ moreDisabled: true
9566
+ }
9567
+ ) : void 0
9568
+ }
9569
+ ),
9570
+ toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ jsxs13(Fragment5, { children: [
9571
+ /* @__PURE__ */ jsx23(
9572
+ EditGlowChrome,
9573
+ {
9574
+ rect: toolbarRect,
9575
+ elRef: glowElRef,
9576
+ reorderHrefKey,
9577
+ dragDisabled: reorderDragDisabled
9578
+ }
9579
+ ),
9580
+ /* @__PURE__ */ jsx23(
9581
+ FloatingToolbar,
9582
+ {
9583
+ rect: toolbarRect,
9584
+ parentScroll: parentScrollRef.current,
9585
+ elRef: toolbarElRef,
9586
+ onCommand: handleCommand,
9587
+ activeCommands,
9588
+ showEditLink,
9589
+ onEditLink: openLinkPopoverForActive
9590
+ }
9591
+ )
10871
9592
  ] }),
10872
- maxBadge && /* @__PURE__ */ jsxs14(
9593
+ maxBadge && /* @__PURE__ */ jsxs13(
10873
9594
  "div",
10874
9595
  {
10875
9596
  "data-ohw-max-badge": "",
@@ -10895,29 +9616,57 @@ function OhhwellsBridge() {
10895
9616
  ]
10896
9617
  }
10897
9618
  ),
10898
- toggleState && !linkPopover && /* @__PURE__ */ jsx25(StateToggle, { rect: toggleState.rect, activeState: toggleState.activeState, states: toggleState.states, onStateChange: handleStateChange }),
10899
- sectionGap && !linkPopover && /* @__PURE__ */ jsxs14("div", { "data-ohw-section-insert-line": "", className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none", style: { top: sectionGap.y, transform: "translateY(-50%)" }, children: [
10900
- /* @__PURE__ */ jsx25("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
10901
- /* @__PURE__ */ jsx25(
10902
- Badge,
10903
- {
10904
- 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",
10905
- onClick: () => {
10906
- window.parent.postMessage(
10907
- {
10908
- type: "ow:add-section",
10909
- insertAfter: sectionGap.insertAfter,
10910
- insertBefore: sectionGap.insertBefore
9619
+ toggleState && !linkPopover && /* @__PURE__ */ jsx23(
9620
+ StateToggle,
9621
+ {
9622
+ rect: toggleState.rect,
9623
+ activeState: toggleState.activeState,
9624
+ states: toggleState.states,
9625
+ onStateChange: handleStateChange
9626
+ }
9627
+ ),
9628
+ sectionGap && !linkPopover && /* @__PURE__ */ jsxs13(
9629
+ "div",
9630
+ {
9631
+ "data-ohw-section-insert-line": "",
9632
+ className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
9633
+ style: { top: sectionGap.y, transform: "translateY(-50%)" },
9634
+ children: [
9635
+ /* @__PURE__ */ jsx23("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
9636
+ /* @__PURE__ */ jsx23(
9637
+ Badge,
9638
+ {
9639
+ 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",
9640
+ onClick: () => {
9641
+ window.parent.postMessage(
9642
+ { type: "ow:add-section", insertAfter: sectionGap.insertAfter, insertBefore: sectionGap.insertBefore },
9643
+ "*"
9644
+ );
10911
9645
  },
10912
- "*"
10913
- );
10914
- },
10915
- children: "Add Section"
10916
- }
10917
- ),
10918
- /* @__PURE__ */ jsx25("div", { className: "flex-1 bg-primary", style: { height: 3 } })
10919
- ] }),
10920
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx25(LinkPopover, { panelRef: linkPopoverPanelRef, portalContainer: dialogPortalContainer, open: true, mode: linkPopover.mode ?? "edit", pages: sitePages, sections: currentSections, sectionsByPath, initialTarget: linkPopover.target, existingTargets: linkPopover.intent === "add-nav" ? getNavbarExistingTargets() : [], onClose: closeLinkPopover, onSubmit: handleLinkPopoverSubmit }, linkPopover.key) : null
9646
+ children: "Add Section"
9647
+ }
9648
+ ),
9649
+ /* @__PURE__ */ jsx23("div", { className: "flex-1 bg-primary", style: { height: 3 } })
9650
+ ]
9651
+ }
9652
+ ),
9653
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx23(
9654
+ LinkPopover,
9655
+ {
9656
+ panelRef: linkPopoverPanelRef,
9657
+ portalContainer: dialogPortalContainer,
9658
+ open: true,
9659
+ mode: linkPopover.mode ?? "edit",
9660
+ pages: sitePages,
9661
+ sections: currentSections,
9662
+ sectionsByPath,
9663
+ initialTarget: linkPopover.target,
9664
+ existingTargets: linkPopover.intent === "add-nav" ? getNavbarExistingTargets() : [],
9665
+ onClose: closeLinkPopover,
9666
+ onSubmit: handleLinkPopoverSubmit
9667
+ },
9668
+ linkPopover.key
9669
+ ) : null
10921
9670
  ] }),
10922
9671
  bridgeRoot
10923
9672
  ) : null;
@@ -10927,7 +9676,6 @@ export {
10927
9676
  CustomToolbarButton,
10928
9677
  CustomToolbarDivider,
10929
9678
  DragHandle,
10930
- DropIndicator,
10931
9679
  ItemActionToolbar,
10932
9680
  ItemInteractionLayer,
10933
9681
  LinkEditorPanel,
@@ -10942,14 +9690,12 @@ export {
10942
9690
  TooltipProvider,
10943
9691
  TooltipTrigger,
10944
9692
  buildTarget,
10945
- dropIndicatorVariants,
10946
9693
  filterAvailablePages,
10947
9694
  getEditModeInitialState,
10948
9695
  isEditSessionActive,
10949
9696
  isValidUrl,
10950
9697
  parseTarget,
10951
9698
  toggleVariants,
10952
- useOhwCarousel,
10953
9699
  validateUrlInput
10954
9700
  };
10955
9701
  //# sourceMappingURL=index.js.map