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