@ohhwells/bridge 0.1.47 → 0.1.48-next.113

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
@@ -57,12 +57,13 @@ __export(index_exports, {
57
57
  isValidUrl: () => isValidUrl,
58
58
  parseTarget: () => parseTarget,
59
59
  toggleVariants: () => toggleVariants,
60
+ useOhwCarousel: () => useOhwCarousel,
60
61
  validateUrlInput: () => validateUrlInput
61
62
  });
62
63
  module.exports = __toCommonJS(index_exports);
63
64
 
64
65
  // src/OhhwellsBridge.tsx
65
- var import_react9 = __toESM(require("react"), 1);
66
+ var import_react10 = __toESM(require("react"), 1);
66
67
  var import_client = require("react-dom/client");
67
68
  var import_react_dom2 = require("react-dom");
68
69
 
@@ -115,6 +116,7 @@ var import_react3 = require("react");
115
116
  var import_react2 = require("react");
116
117
  var import_radix_ui = require("radix-ui");
117
118
  var import_jsx_runtime = require("react/jsx-runtime");
119
+ var isValidEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
118
120
  function Spinner() {
119
121
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
120
122
  "svg",
@@ -148,12 +150,17 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
148
150
  const [error, setError] = (0, import_react2.useState)(null);
149
151
  const isBook = title === "Confirm your spot";
150
152
  const handleSubmit = async () => {
151
- if (!email.trim()) return;
153
+ const trimmed = email.trim();
154
+ if (!trimmed) return;
155
+ if (!isValidEmail(trimmed)) {
156
+ setError("Please enter a valid email address.");
157
+ return;
158
+ }
152
159
  setLoading(true);
153
160
  setError(null);
154
161
  try {
155
- await onSubmit(email.trim());
156
- setSubmittedEmail(email.trim());
162
+ await onSubmit(trimmed);
163
+ setSubmittedEmail(trimmed);
157
164
  setSuccess(true);
158
165
  } catch (e) {
159
166
  setError(e instanceof Error ? e.message : "Something went wrong. Please try again.");
@@ -228,7 +235,10 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
228
235
  {
229
236
  type: "email",
230
237
  value: email,
231
- onChange: (e) => setEmail(e.target.value),
238
+ onChange: (e) => {
239
+ setEmail(e.target.value);
240
+ if (error) setError(null);
241
+ },
232
242
  onKeyDown: handleKeyDown,
233
243
  placeholder: "hello@gmail.com",
234
244
  autoFocus: true,
@@ -285,12 +295,20 @@ function formatClassTime(cls) {
285
295
  const em = endTotal % 60;
286
296
  return `${h}:${cls.startTime.minutes}-${eh}:${String(em).padStart(2, "0")}`;
287
297
  }
298
+ function formatBookingLabel(cls) {
299
+ const price = cls.price;
300
+ const isFree = price === null || price === void 0 || `${price}` === "" || `${price}` === "0";
301
+ return isFree ? "Book for free" : `Book for ${cls.currency ?? ""} ${price}`.trim();
302
+ }
288
303
  function getBookingsOnDate(cls, date) {
289
304
  if (!cls.bookings?.length) return 0;
290
- const ds = date.toISOString().split("T")[0];
305
+ const target = new Date(date);
306
+ target.setHours(0, 0, 0, 0);
291
307
  return cls.bookings.filter((b) => {
292
308
  try {
293
- return new Date(b.classDate).toISOString().split("T")[0] === ds;
309
+ const bookingDate = new Date(b.classDate);
310
+ bookingDate.setHours(0, 0, 0, 0);
311
+ return bookingDate.getTime() === target.getTime();
294
312
  } catch {
295
313
  return false;
296
314
  }
@@ -555,7 +573,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
555
573
  }
556
574
  )
557
575
  ] }),
558
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "sm:hidden flex flex-col gap-px", children: isFull ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
576
+ cls.showAvailability !== false && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "sm:hidden flex flex-col gap-px", children: isFull ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
559
577
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
560
578
  available,
561
579
  "/",
@@ -567,9 +585,17 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
567
585
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-1 flex-col gap-2 min-w-0 sm:contents", children: [
568
586
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex-1 flex flex-col gap-2 min-w-0", children: [
569
587
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-base font-bold text-(--color-dark,#200C02) block truncate", children: cls.name }),
570
- cls.hostName && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block truncate", children: cls.hostName })
588
+ cls.hostName && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block truncate", children: cls.hostName }),
589
+ cls.description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
590
+ "span",
591
+ {
592
+ className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block",
593
+ style: { wordBreak: "break-word" },
594
+ children: cls.description
595
+ }
596
+ )
571
597
  ] }),
572
- /* @__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: [
598
+ 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: [
573
599
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
574
600
  available,
575
601
  "/",
@@ -594,7 +620,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
594
620
  if (!cls.id) return;
595
621
  onOpenModal?.(isFull ? "waitlist" : "book", cls.id, selectedDate);
596
622
  },
597
- children: isFull ? "Join Waitlist" : "Book Now"
623
+ children: isFull ? "Join Waitlist" : formatBookingLabel(cls)
598
624
  }
599
625
  )
600
626
  ] })
@@ -636,6 +662,17 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
636
662
  const [isHovered, setIsHovered] = (0, import_react3.useState)(false);
637
663
  const [modalState, setModalState] = (0, import_react3.useState)(null);
638
664
  const switchScheduleIdRef = (0, import_react3.useRef)(null);
665
+ const liveScheduleIdRef = (0, import_react3.useRef)(null);
666
+ const refetchLiveSchedule = (0, import_react3.useCallback)(async () => {
667
+ const id = liveScheduleIdRef.current;
668
+ if (!id) return;
669
+ try {
670
+ const res = await fetch(`${API_URL}/api/schedule/id/${id}`);
671
+ const data = await res.json();
672
+ if (data?.id) setSchedule(data);
673
+ } catch {
674
+ }
675
+ }, []);
639
676
  const dates = (0, import_react3.useMemo)(() => {
640
677
  const today = /* @__PURE__ */ new Date();
641
678
  today.setHours(0, 0, 0, 0);
@@ -655,6 +692,18 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
655
692
  }
656
693
  }
657
694
  }, [schedule, dates]);
695
+ (0, import_react3.useEffect)(() => {
696
+ if (typeof window === "undefined") return;
697
+ const onVisible = () => {
698
+ if (!document.hidden) void refetchLiveSchedule();
699
+ };
700
+ window.addEventListener("focus", refetchLiveSchedule);
701
+ document.addEventListener("visibilitychange", onVisible);
702
+ return () => {
703
+ window.removeEventListener("focus", refetchLiveSchedule);
704
+ document.removeEventListener("visibilitychange", onVisible);
705
+ };
706
+ }, [refetchLiveSchedule]);
658
707
  (0, import_react3.useEffect)(() => {
659
708
  if (typeof window === "undefined") return;
660
709
  const isInEditor = window.self !== window.top;
@@ -716,7 +765,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
716
765
  setLoading(false);
717
766
  return;
718
767
  }
719
- ;
768
+ liveScheduleIdRef.current = effectiveId;
720
769
  (async () => {
721
770
  try {
722
771
  const res = await fetch(`${API_URL}/api/schedule/id/${effectiveId}`);
@@ -773,18 +822,14 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
773
822
  const data = await res.json().catch(() => ({}));
774
823
  throw new Error(data?.message ?? "Something went wrong. Please try again.");
775
824
  }
825
+ await refetchLiveSchedule();
776
826
  };
777
827
  const handleReplaceSchedule = () => {
778
828
  setIsHovered(false);
779
- if (schedule) {
780
- window.parent.postMessage({
781
- type: "ow:schedule-connected",
782
- schedule: { id: schedule.id, name: schedule.name },
783
- insertAfter
784
- }, "*");
785
- } else {
786
- window.parent.postMessage({ type: "ow:scheduling-not-connected", insertAfter }, "*");
787
- }
829
+ window.parent.postMessage(
830
+ { type: "ow:scheduling-not-connected", insertAfter, currentScheduleId: schedule?.id },
831
+ "*"
832
+ );
788
833
  };
789
834
  if (!inEditor && !loading && !schedule) return null;
790
835
  const sectionId = `scheduling-${insertAfter}`;
@@ -827,7 +872,19 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
827
872
  ),
828
873
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "max-w-[1280px] mx-auto flex flex-col items-center gap-16", children: [
829
874
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-col items-center gap-4", children: [
830
- /* @__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" }),
875
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
876
+ "h2",
877
+ {
878
+ className: "font-display text-center m-0 text-(--color-dark,#200C02)",
879
+ style: {
880
+ fontSize: "var(--fs-section-h2, clamp(40px, 4.4vw, 64px))",
881
+ fontWeight: "var(--font-weight-heading, 400)",
882
+ lineHeight: 1.05,
883
+ letterSpacing: "-0.02em"
884
+ },
885
+ children: schedule?.name ?? "Book an appointment"
886
+ }
887
+ ),
831
888
  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 })
832
889
  ] }),
833
890
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "w-full flex flex-col items-end gap-3", children: [
@@ -4887,7 +4944,11 @@ function MediaOverlay({
4887
4944
  variant: "outline",
4888
4945
  size: "sm",
4889
4946
  className: "gap-1.5 cursor-pointer hover:bg-background",
4890
- style: OVERLAY_BUTTON_STYLE,
4947
+ style: {
4948
+ ...OVERLAY_BUTTON_STYLE,
4949
+ // Don't let Replace steal clicks when text (e.g. nav) sits on top of this media.
4950
+ pointerEvents: hover.hasTextOverlap ? "none" : "auto"
4951
+ },
4891
4952
  onMouseDown: (e) => e.preventDefault(),
4892
4953
  onClick: (e) => {
4893
4954
  e.stopPropagation();
@@ -4904,6 +4965,61 @@ function MediaOverlay({
4904
4965
  ] });
4905
4966
  }
4906
4967
 
4968
+ // src/ui/CarouselOverlay.tsx
4969
+ var import_lucide_react4 = require("lucide-react");
4970
+ var import_jsx_runtime12 = require("react/jsx-runtime");
4971
+ var OVERLAY_BUTTON_STYLE2 = {
4972
+ pointerEvents: "auto",
4973
+ fontFamily: "Inter, sans-serif",
4974
+ fontSize: 12,
4975
+ color: "#000"
4976
+ };
4977
+ function CarouselOverlay({
4978
+ hover,
4979
+ onEdit
4980
+ }) {
4981
+ const { rect } = hover;
4982
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4983
+ "div",
4984
+ {
4985
+ "data-ohw-bridge": "",
4986
+ "data-ohw-carousel-overlay": "",
4987
+ className: "flex cursor-pointer items-center justify-center",
4988
+ style: {
4989
+ position: "fixed",
4990
+ top: rect.top,
4991
+ left: rect.left,
4992
+ width: rect.width,
4993
+ height: rect.height,
4994
+ zIndex: 2147483646,
4995
+ pointerEvents: "auto",
4996
+ boxShadow: "inset 0 0 0 1.5px var(--color-primary)",
4997
+ background: "color-mix(in srgb, var(--color-primary) 20%, transparent)"
4998
+ },
4999
+ onClick: () => onEdit(hover.key),
5000
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
5001
+ Button,
5002
+ {
5003
+ "data-ohw-carousel-overlay": "",
5004
+ variant: "outline",
5005
+ size: "sm",
5006
+ className: "cursor-pointer gap-1.5 hover:bg-background",
5007
+ style: OVERLAY_BUTTON_STYLE2,
5008
+ onMouseDown: (e) => e.preventDefault(),
5009
+ onClick: (e) => {
5010
+ e.stopPropagation();
5011
+ onEdit(hover.key);
5012
+ },
5013
+ children: [
5014
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react4.GalleryHorizontal, { size: 14 }),
5015
+ "Edit gallery"
5016
+ ]
5017
+ }
5018
+ )
5019
+ }
5020
+ );
5021
+ }
5022
+
4907
5023
  // src/OhhwellsBridge.tsx
4908
5024
  var import_react_dom3 = require("react-dom");
4909
5025
  var import_navigation2 = require("next/navigation");
@@ -5189,23 +5305,23 @@ var import_react7 = require("react");
5189
5305
  // src/ui/dialog.tsx
5190
5306
  var React8 = __toESM(require("react"), 1);
5191
5307
  var import_radix_ui5 = require("radix-ui");
5192
- var import_lucide_react4 = require("lucide-react");
5193
- var import_jsx_runtime12 = require("react/jsx-runtime");
5308
+ var import_lucide_react5 = require("lucide-react");
5309
+ var import_jsx_runtime13 = require("react/jsx-runtime");
5194
5310
  function Dialog2({
5195
5311
  ...props
5196
5312
  }) {
5197
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_radix_ui5.Dialog.Root, { "data-slot": "dialog", ...props });
5313
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_radix_ui5.Dialog.Root, { "data-slot": "dialog", ...props });
5198
5314
  }
5199
5315
  function DialogPortal({
5200
5316
  ...props
5201
5317
  }) {
5202
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_radix_ui5.Dialog.Portal, { ...props });
5318
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_radix_ui5.Dialog.Portal, { ...props });
5203
5319
  }
5204
5320
  function DialogOverlay({
5205
5321
  className,
5206
5322
  ...props
5207
5323
  }) {
5208
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5324
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5209
5325
  import_radix_ui5.Dialog.Overlay,
5210
5326
  {
5211
5327
  "data-slot": "dialog-overlay",
@@ -5218,9 +5334,9 @@ function DialogOverlay({
5218
5334
  var DialogContent = React8.forwardRef(
5219
5335
  ({ className, children, showCloseButton = true, container, ...props }, ref) => {
5220
5336
  const positionMode = container ? "absolute" : "fixed";
5221
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(DialogPortal, { container: container ?? void 0, children: [
5222
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
5223
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
5337
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(DialogPortal, { container: container ?? void 0, children: [
5338
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
5339
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
5224
5340
  import_radix_ui5.Dialog.Content,
5225
5341
  {
5226
5342
  ref,
@@ -5236,13 +5352,13 @@ var DialogContent = React8.forwardRef(
5236
5352
  ...props,
5237
5353
  children: [
5238
5354
  children,
5239
- showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5355
+ showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5240
5356
  import_radix_ui5.Dialog.Close,
5241
5357
  {
5242
5358
  type: "button",
5243
5359
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
5244
5360
  "aria-label": "Close",
5245
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react4.X, { size: 16, "aria-hidden": true })
5361
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react5.X, { size: 16, "aria-hidden": true })
5246
5362
  }
5247
5363
  ) : null
5248
5364
  ]
@@ -5256,13 +5372,13 @@ function DialogHeader({
5256
5372
  className,
5257
5373
  ...props
5258
5374
  }) {
5259
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
5375
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
5260
5376
  }
5261
5377
  function DialogFooter({
5262
5378
  className,
5263
5379
  ...props
5264
5380
  }) {
5265
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5381
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5266
5382
  "div",
5267
5383
  {
5268
5384
  className: cn("flex items-center justify-end gap-2", className),
@@ -5270,7 +5386,7 @@ function DialogFooter({
5270
5386
  }
5271
5387
  );
5272
5388
  }
5273
- var DialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5389
+ var DialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5274
5390
  import_radix_ui5.Dialog.Title,
5275
5391
  {
5276
5392
  ref,
@@ -5282,7 +5398,7 @@ var DialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE
5282
5398
  }
5283
5399
  ));
5284
5400
  DialogTitle.displayName = import_radix_ui5.Dialog.Title.displayName;
5285
- var DialogDescription = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5401
+ var DialogDescription = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5286
5402
  import_radix_ui5.Dialog.Description,
5287
5403
  {
5288
5404
  ref,
@@ -5294,63 +5410,63 @@ DialogDescription.displayName = import_radix_ui5.Dialog.Description.displayName;
5294
5410
  var DialogClose = import_radix_ui5.Dialog.Close;
5295
5411
 
5296
5412
  // src/ui/link-modal/LinkEditorPanel.tsx
5297
- var import_lucide_react8 = require("lucide-react");
5413
+ var import_lucide_react9 = require("lucide-react");
5298
5414
 
5299
5415
  // src/ui/link-modal/DestinationBreadcrumb.tsx
5300
- var import_lucide_react5 = require("lucide-react");
5301
- var import_jsx_runtime13 = require("react/jsx-runtime");
5416
+ var import_lucide_react6 = require("lucide-react");
5417
+ var import_jsx_runtime14 = require("react/jsx-runtime");
5302
5418
  function DestinationBreadcrumb({
5303
5419
  pageTitle,
5304
5420
  sectionLabel
5305
5421
  }) {
5306
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex w-full flex-col gap-2", children: [
5307
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "text-sm font-medium! text-foreground m-0", children: "Destination" }),
5308
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-3", children: [
5309
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-2", children: [
5310
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react5.File, { size: 16, className: "shrink-0 text-foreground", "aria-hidden": true }),
5311
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-sm font-medium leading-none text-foreground!", children: pageTitle })
5422
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex w-full flex-col gap-2", children: [
5423
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-sm font-medium! text-foreground m-0", children: "Destination" }),
5424
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-3", children: [
5425
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-2", children: [
5426
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react6.File, { size: 16, className: "shrink-0 text-foreground", "aria-hidden": true }),
5427
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "text-sm font-medium leading-none text-foreground!", children: pageTitle })
5312
5428
  ] }),
5313
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5314
- import_lucide_react5.ArrowRight,
5429
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5430
+ import_lucide_react6.ArrowRight,
5315
5431
  {
5316
5432
  size: 16,
5317
5433
  className: "shrink-0 text-muted-foreground",
5318
5434
  "aria-hidden": true
5319
5435
  }
5320
5436
  ),
5321
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
5322
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5323
- import_lucide_react5.GalleryVertical,
5437
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
5438
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5439
+ import_lucide_react6.GalleryVertical,
5324
5440
  {
5325
5441
  size: 16,
5326
5442
  className: "shrink-0 text-foreground",
5327
5443
  "aria-hidden": true
5328
5444
  }
5329
5445
  ),
5330
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
5446
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
5331
5447
  ] })
5332
5448
  ] })
5333
5449
  ] });
5334
5450
  }
5335
5451
 
5336
5452
  // src/ui/link-modal/SectionTreeItem.tsx
5337
- var import_lucide_react6 = require("lucide-react");
5338
- var import_jsx_runtime14 = require("react/jsx-runtime");
5453
+ var import_lucide_react7 = require("lucide-react");
5454
+ var import_jsx_runtime15 = require("react/jsx-runtime");
5339
5455
  function SectionTreeItem({
5340
5456
  section,
5341
5457
  onSelect,
5342
5458
  selected
5343
5459
  }) {
5344
5460
  const interactive = Boolean(onSelect);
5345
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex h-9 w-full items-end pl-3", children: [
5346
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5461
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex h-9 w-full items-end pl-3", children: [
5462
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5347
5463
  "div",
5348
5464
  {
5349
5465
  className: "mr-[-1px] h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
5350
5466
  "aria-hidden": true
5351
5467
  }
5352
5468
  ),
5353
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
5469
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5354
5470
  "div",
5355
5471
  {
5356
5472
  role: interactive ? "button" : void 0,
@@ -5368,15 +5484,15 @@ function SectionTreeItem({
5368
5484
  interactive && selected && "border-primary"
5369
5485
  ),
5370
5486
  children: [
5371
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5372
- import_lucide_react6.GalleryVertical,
5487
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5488
+ import_lucide_react7.GalleryVertical,
5373
5489
  {
5374
5490
  size: 16,
5375
5491
  className: "shrink-0 text-foreground",
5376
5492
  "aria-hidden": true
5377
5493
  }
5378
5494
  ),
5379
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
5495
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
5380
5496
  ]
5381
5497
  }
5382
5498
  )
@@ -5388,10 +5504,10 @@ var import_react4 = require("react");
5388
5504
 
5389
5505
  // src/ui/input.tsx
5390
5506
  var React9 = __toESM(require("react"), 1);
5391
- var import_jsx_runtime15 = require("react/jsx-runtime");
5507
+ var import_jsx_runtime16 = require("react/jsx-runtime");
5392
5508
  var Input = React9.forwardRef(
5393
5509
  ({ className, type, ...props }, ref) => {
5394
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5510
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5395
5511
  "input",
5396
5512
  {
5397
5513
  type,
@@ -5410,9 +5526,9 @@ Input.displayName = "Input";
5410
5526
 
5411
5527
  // src/ui/label.tsx
5412
5528
  var import_radix_ui6 = require("radix-ui");
5413
- var import_jsx_runtime16 = require("react/jsx-runtime");
5529
+ var import_jsx_runtime17 = require("react/jsx-runtime");
5414
5530
  function Label({ className, ...props }) {
5415
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5531
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5416
5532
  import_radix_ui6.Label.Root,
5417
5533
  {
5418
5534
  "data-slot": "label",
@@ -5423,12 +5539,12 @@ function Label({ className, ...props }) {
5423
5539
  }
5424
5540
 
5425
5541
  // src/ui/link-modal/UrlOrPageInput.tsx
5426
- var import_lucide_react7 = require("lucide-react");
5427
- var import_jsx_runtime17 = require("react/jsx-runtime");
5542
+ var import_lucide_react8 = require("lucide-react");
5543
+ var import_jsx_runtime18 = require("react/jsx-runtime");
5428
5544
  function FieldChevron({
5429
5545
  onClick
5430
5546
  }) {
5431
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5547
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5432
5548
  "button",
5433
5549
  {
5434
5550
  type: "button",
@@ -5436,7 +5552,7 @@ function FieldChevron({
5436
5552
  onClick,
5437
5553
  "aria-label": "Open page list",
5438
5554
  tabIndex: -1,
5439
- children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.ChevronDown, { size: 16 })
5555
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.ChevronDown, { size: 16 })
5440
5556
  }
5441
5557
  );
5442
5558
  }
@@ -5497,19 +5613,19 @@ function UrlOrPageInput({
5497
5613
  "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]",
5498
5614
  urlError ? "border-destructive shadow-[0_0_0_1px_var(--ohw-destructive)]" : isFocused ? "border-primary shadow-[0_0_0_1px_var(--ohw-primary)]" : "border-input"
5499
5615
  );
5500
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex w-full flex-col gap-2 p-0", children: [
5501
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
5502
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { ref: rootRef, className: "relative w-full", children: [
5503
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
5504
- selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5505
- import_lucide_react7.File,
5616
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex w-full flex-col gap-2 p-0", children: [
5617
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
5618
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { ref: rootRef, className: "relative w-full", children: [
5619
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
5620
+ selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5621
+ import_lucide_react8.File,
5506
5622
  {
5507
5623
  size: 16,
5508
5624
  className: "shrink-0 text-foreground",
5509
5625
  "aria-hidden": true
5510
5626
  }
5511
5627
  ) }) : null,
5512
- 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)(
5628
+ 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)(
5513
5629
  Input,
5514
5630
  {
5515
5631
  ref: inputRef,
@@ -5535,7 +5651,7 @@ function UrlOrPageInput({
5535
5651
  )
5536
5652
  }
5537
5653
  ),
5538
- selectedPage && !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5654
+ selectedPage && !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5539
5655
  "button",
5540
5656
  {
5541
5657
  type: "button",
@@ -5543,26 +5659,26 @@ function UrlOrPageInput({
5543
5659
  onMouseDown: clearSelection,
5544
5660
  "aria-label": "Clear selected page",
5545
5661
  tabIndex: -1,
5546
- children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.X, { size: 16, "aria-hidden": true })
5662
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.X, { size: 16, "aria-hidden": true })
5547
5663
  }
5548
5664
  ) : null,
5549
- !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(FieldChevron, { onClick: toggleDropdown }) : null
5665
+ !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(FieldChevron, { onClick: toggleDropdown }) : null
5550
5666
  ] }),
5551
- dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5667
+ dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5552
5668
  "div",
5553
5669
  {
5554
5670
  "data-ohw-link-page-dropdown": "",
5555
5671
  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",
5556
5672
  onMouseDown: (e) => e.preventDefault(),
5557
- children: filteredPages.map((page) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
5673
+ children: filteredPages.map((page) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
5558
5674
  "button",
5559
5675
  {
5560
5676
  type: "button",
5561
5677
  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",
5562
5678
  onClick: () => onPageSelect(page),
5563
5679
  children: [
5564
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.File, { size: 16, className: "shrink-0", "aria-hidden": true }),
5565
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "truncate", children: page.title })
5680
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.File, { size: 16, className: "shrink-0", "aria-hidden": true }),
5681
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "truncate", children: page.title })
5566
5682
  ]
5567
5683
  },
5568
5684
  page.path
@@ -5570,34 +5686,34 @@ function UrlOrPageInput({
5570
5686
  }
5571
5687
  ) : null
5572
5688
  ] }),
5573
- urlError ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
5689
+ urlError ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
5574
5690
  ] });
5575
5691
  }
5576
5692
 
5577
5693
  // src/ui/link-modal/LinkEditorPanel.tsx
5578
- var import_jsx_runtime18 = require("react/jsx-runtime");
5694
+ var import_jsx_runtime19 = require("react/jsx-runtime");
5579
5695
  function LinkEditorPanel({ state, onClose }) {
5580
5696
  const isCancel = state.secondaryLabel === "Cancel" || state.secondaryLabel === "Back to sections";
5581
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
5582
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DialogClose, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5697
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
5698
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DialogClose, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5583
5699
  "button",
5584
5700
  {
5585
5701
  type: "button",
5586
5702
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50 h-7",
5587
5703
  "aria-label": "Close",
5588
5704
  onClick: onClose,
5589
- children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.X, { size: 16, "aria-hidden": true })
5705
+ children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react9.X, { size: 16, "aria-hidden": true })
5590
5706
  }
5591
5707
  ) }),
5592
- /* @__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 }) }),
5593
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
5594
- state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5708
+ /* @__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 }) }),
5709
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
5710
+ state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5595
5711
  DestinationBreadcrumb,
5596
5712
  {
5597
5713
  pageTitle: state.selectedPage.title,
5598
5714
  sectionLabel: state.selectedSection.label
5599
5715
  }
5600
- ) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5716
+ ) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5601
5717
  UrlOrPageInput,
5602
5718
  {
5603
5719
  value: state.searchValue,
@@ -5610,8 +5726,8 @@ function LinkEditorPanel({ state, onClose }) {
5610
5726
  urlError: state.urlError
5611
5727
  }
5612
5728
  ),
5613
- state.showChooseSection ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex flex-col justify-center gap-2", children: [
5614
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5729
+ state.showChooseSection ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex flex-col justify-center gap-2", children: [
5730
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5615
5731
  Button,
5616
5732
  {
5617
5733
  type: "button",
@@ -5622,15 +5738,15 @@ function LinkEditorPanel({ state, onClose }) {
5622
5738
  children: "Choose a section"
5623
5739
  }
5624
5740
  ),
5625
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
5626
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.Info, { size: 16, className: "shrink-0", "aria-hidden": true }),
5627
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: "Pick a section this link should scroll to." })
5741
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
5742
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react9.Info, { size: 16, className: "shrink-0", "aria-hidden": true }),
5743
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: "Pick a section this link should scroll to." })
5628
5744
  ] })
5629
5745
  ] }) : null,
5630
- state.showSectionRow && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
5746
+ state.showSectionRow && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
5631
5747
  ] }),
5632
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(DialogFooter, { className: "w-full px-6 pb-6", children: [
5633
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5748
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(DialogFooter, { className: "w-full px-6 pb-6", children: [
5749
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5634
5750
  Button,
5635
5751
  {
5636
5752
  type: "button",
@@ -5645,7 +5761,7 @@ function LinkEditorPanel({ state, onClose }) {
5645
5761
  children: state.secondaryLabel
5646
5762
  }
5647
5763
  ),
5648
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5764
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5649
5765
  Button,
5650
5766
  {
5651
5767
  type: "button",
@@ -5666,9 +5782,9 @@ function LinkEditorPanel({ state, onClose }) {
5666
5782
  // src/ui/link-modal/SectionPickerOverlay.tsx
5667
5783
  var import_react5 = require("react");
5668
5784
  var import_react_dom = require("react-dom");
5669
- var import_lucide_react9 = require("lucide-react");
5785
+ var import_lucide_react10 = require("lucide-react");
5670
5786
  var import_navigation = require("next/navigation");
5671
- var import_jsx_runtime19 = require("react/jsx-runtime");
5787
+ var import_jsx_runtime20 = require("react/jsx-runtime");
5672
5788
  var DIM_OVERLAY = "rgba(0, 0, 0, 0.45)";
5673
5789
  function rectsEqual(a, b) {
5674
5790
  if (a.size !== b.size) return false;
@@ -5897,7 +6013,7 @@ function SectionPickerOverlay({
5897
6013
  const portalRoot = typeof document !== "undefined" ? document.querySelector("[data-ohw-bridge-root]") ?? document.body : null;
5898
6014
  if (!portalRoot) return null;
5899
6015
  return (0, import_react_dom.createPortal)(
5900
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
6016
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
5901
6017
  "div",
5902
6018
  {
5903
6019
  "data-ohw-section-picker": "",
@@ -5907,12 +6023,12 @@ function SectionPickerOverlay({
5907
6023
  role: "dialog",
5908
6024
  "aria-label": "Choose a section",
5909
6025
  children: [
5910
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6026
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5911
6027
  "div",
5912
6028
  {
5913
6029
  className: "pointer-events-auto fixed left-5 z-[2]",
5914
6030
  style: { top: chromeClip.top + 20 },
5915
- children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
6031
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
5916
6032
  Button,
5917
6033
  {
5918
6034
  type: "button",
@@ -5921,14 +6037,14 @@ function SectionPickerOverlay({
5921
6037
  className: "h-8 min-w-0 gap-1 border-border bg-background px-2 py-1.5 shadow-sm hover:bg-muted cursor-pointer",
5922
6038
  onClick: onBack,
5923
6039
  children: [
5924
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react9.ArrowLeft, { className: "size-4 shrink-0", "aria-hidden": true }),
6040
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react10.ArrowLeft, { className: "size-4 shrink-0", "aria-hidden": true }),
5925
6041
  "Back"
5926
6042
  ]
5927
6043
  }
5928
6044
  )
5929
6045
  }
5930
6046
  ),
5931
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6047
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5932
6048
  "div",
5933
6049
  {
5934
6050
  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",
@@ -5941,7 +6057,7 @@ function SectionPickerOverlay({
5941
6057
  children: "Click on section to select"
5942
6058
  }
5943
6059
  ),
5944
- !isOnTargetPage ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6060
+ !isOnTargetPage ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5945
6061
  "div",
5946
6062
  {
5947
6063
  className: "pointer-events-none fixed left-1/2 z-[1] -translate-x-1/2 rounded-md px-3 py-2 text-sm text-muted-foreground shadow-sm",
@@ -5949,14 +6065,14 @@ function SectionPickerOverlay({
5949
6065
  children: "Loading page preview\u2026"
5950
6066
  }
5951
6067
  ) : null,
5952
- 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,
6068
+ 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,
5953
6069
  isOnTargetPage ? liveSections.map((section) => {
5954
6070
  const rect = rects.get(section.id);
5955
6071
  if (!rect || rect.width <= 0 || rect.height <= 0) return null;
5956
6072
  const isSelected = selectedId === section.id;
5957
6073
  const isHovered = hoveredId === section.id;
5958
6074
  const isLit = isSelected || isHovered;
5959
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
6075
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
5960
6076
  "button",
5961
6077
  {
5962
6078
  type: "button",
@@ -5971,7 +6087,7 @@ function SectionPickerOverlay({
5971
6087
  "aria-label": `Select section ${section.label}`,
5972
6088
  onClick: () => handleSelect(section),
5973
6089
  children: [
5974
- isLit ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6090
+ isLit ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5975
6091
  "span",
5976
6092
  {
5977
6093
  className: "pointer-events-none absolute",
@@ -5984,13 +6100,13 @@ function SectionPickerOverlay({
5984
6100
  "aria-hidden": true
5985
6101
  }
5986
6102
  ) : null,
5987
- isSelected ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6103
+ isSelected ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5988
6104
  "span",
5989
6105
  {
5990
6106
  className: "absolute right-3 top-3 flex size-8 items-center justify-center rounded-full text-white",
5991
6107
  style: { backgroundColor: "var(--ohw-primary, #0885fe)" },
5992
6108
  "aria-hidden": true,
5993
- children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react9.Check, { className: "size-5" })
6109
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react10.Check, { className: "size-5" })
5994
6110
  }
5995
6111
  ) : null
5996
6112
  ]
@@ -6170,7 +6286,7 @@ function useLinkModalState({
6170
6286
  }
6171
6287
 
6172
6288
  // src/ui/link-modal/LinkPopover.tsx
6173
- var import_jsx_runtime20 = require("react/jsx-runtime");
6289
+ var import_jsx_runtime21 = require("react/jsx-runtime");
6174
6290
  function postToParent(data) {
6175
6291
  window.parent?.postMessage(data, "*");
6176
6292
  }
@@ -6266,15 +6382,15 @@ function LinkPopover({
6266
6382
  );
6267
6383
  };
6268
6384
  }, [open, sectionPickerActive]);
6269
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
6270
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6385
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
6386
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6271
6387
  Dialog2,
6272
6388
  {
6273
6389
  open: open && !sectionPickerActive,
6274
6390
  onOpenChange: (next) => {
6275
6391
  if (!next) onClose?.();
6276
6392
  },
6277
- children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6393
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6278
6394
  DialogContent,
6279
6395
  {
6280
6396
  ref: panelRef,
@@ -6284,12 +6400,12 @@ function LinkPopover({
6284
6400
  "data-ohw-bridge": "",
6285
6401
  showCloseButton: false,
6286
6402
  className: "gap-0 p-0 w-full max-w-[448px] pointer-events-auto z-[2147483646] overflow-visible",
6287
- children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(LinkEditorPanel, { state, onClose })
6403
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LinkEditorPanel, { state, onClose })
6288
6404
  }
6289
6405
  )
6290
6406
  }
6291
6407
  ),
6292
- sectionPickerActive && state.selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6408
+ sectionPickerActive && state.selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6293
6409
  SectionPickerOverlay,
6294
6410
  {
6295
6411
  pagePath: state.selectedPage.path,
@@ -7011,7 +7127,195 @@ function parseFooterOrder(content) {
7011
7127
  return null;
7012
7128
  }
7013
7129
  }
7130
+ var FOOTER_HEADING_RE = /^footer-(\d+)-heading$/;
7131
+ var FOOTER_LABEL_RE = /^footer-(\d+)-(\d+)-label$/;
7132
+ var DEFAULT_FOOTER_COLUMN_HEADING = "New";
7133
+ var DEFAULT_FOOTER_COLUMN_LINK_LABEL = "New link";
7134
+ var DEFAULT_FOOTER_COLUMN_LINK_HREF = "";
7135
+ function isFooterLinksContainer(el) {
7136
+ return el.hasAttribute("data-ohw-footer-links") || el.classList.contains("rb-footer-links");
7137
+ }
7138
+ function getFooterColumnIndicesInDom() {
7139
+ const indices = /* @__PURE__ */ new Set();
7140
+ for (const col of listFooterColumns()) {
7141
+ const attr = col.getAttribute("data-ohw-footer-col");
7142
+ if (attr != null) {
7143
+ const n = parseInt(attr, 10);
7144
+ if (Number.isFinite(n)) indices.add(n);
7145
+ }
7146
+ for (const link of listFooterLinksInColumn(col)) {
7147
+ const parsed = parseFooterHrefKey(link.getAttribute("data-ohw-href-key"));
7148
+ if (parsed) indices.add(parsed.col);
7149
+ }
7150
+ const heading = col.querySelector('[data-ohw-key^="footer-"][data-ohw-key$="-heading"]');
7151
+ const headingKey = heading?.getAttribute("data-ohw-key");
7152
+ if (headingKey) {
7153
+ const match = headingKey.match(FOOTER_HEADING_RE);
7154
+ if (match) indices.add(parseInt(match[1], 10));
7155
+ }
7156
+ }
7157
+ return [...indices].sort((a, b) => a - b);
7158
+ }
7159
+ function getNextFooterColumnIndex() {
7160
+ const indices = getFooterColumnIndicesInDom();
7161
+ if (indices.length === 0) return 0;
7162
+ return Math.max(...indices) + 1;
7163
+ }
7164
+ function cloneFooterLinkShell(template) {
7165
+ const anchor = document.createElement("a");
7166
+ if (template) {
7167
+ anchor.style.cssText = template.style.cssText;
7168
+ if (template.className) anchor.className = template.className;
7169
+ }
7170
+ anchor.style.cursor = "pointer";
7171
+ anchor.style.textDecoration = "none";
7172
+ return anchor;
7173
+ }
7174
+ function buildFooterHeading(colIndex, text) {
7175
+ const heading = document.createElement("p");
7176
+ heading.setAttribute("data-ohw-editable", "text");
7177
+ heading.setAttribute("data-ohw-key", `footer-${colIndex}-heading`);
7178
+ heading.textContent = text;
7179
+ heading.style.cssText = [
7180
+ "color: var(--espresso, #3d312b)",
7181
+ "font-size: 14px",
7182
+ "font-weight: 800",
7183
+ "opacity: 0.82",
7184
+ "margin: 0 0 6px",
7185
+ "padding: 0",
7186
+ "line-height: 1.2"
7187
+ ].join(";");
7188
+ return heading;
7189
+ }
7190
+ function buildFooterLink(colIndex, itemIndex, href, label, template) {
7191
+ const anchor = cloneFooterLinkShell(template);
7192
+ anchor.setAttribute("href", href);
7193
+ anchor.setAttribute("data-ohw-href-key", `footer-${colIndex}-${itemIndex}-href`);
7194
+ const span = document.createElement("span");
7195
+ span.setAttribute("data-ohw-editable", "text");
7196
+ span.setAttribute("data-ohw-key", `footer-${colIndex}-${itemIndex}-label`);
7197
+ span.textContent = label;
7198
+ anchor.appendChild(span);
7199
+ return anchor;
7200
+ }
7201
+ function footerColumnExistsInDom(colIndex) {
7202
+ return document.querySelector(`[data-ohw-footer-col="${colIndex}"]`) !== null || document.querySelector(`[data-ohw-href-key^="footer-${colIndex}-"]`) !== null || document.querySelector(`[data-ohw-key="footer-${colIndex}-heading"]`) !== null;
7203
+ }
7204
+ function getFooterLinkTemplate() {
7205
+ for (const col of listFooterColumns()) {
7206
+ const link = listFooterLinksInColumn(col)[0];
7207
+ if (link) return link;
7208
+ }
7209
+ return null;
7210
+ }
7211
+ function getFooterColumnTemplate() {
7212
+ return listFooterColumns()[0] ?? null;
7213
+ }
7214
+ function insertFooterColumnDom(colIndex, heading, items) {
7215
+ const container = getFooterLinksContainer();
7216
+ if (!container) return null;
7217
+ const colTemplate = getFooterColumnTemplate();
7218
+ const linkTemplate = getFooterLinkTemplate();
7219
+ const column = document.createElement("div");
7220
+ if (colTemplate?.className) column.className = colTemplate.className;
7221
+ else column.className = "rb-footer-link-col";
7222
+ column.setAttribute("data-ohw-footer-col", String(colIndex));
7223
+ if (colTemplate) {
7224
+ const gap = getComputedStyle(colTemplate).gap;
7225
+ if (gap && gap !== "normal") column.style.gap = gap;
7226
+ column.style.display = getComputedStyle(colTemplate).display || "flex";
7227
+ column.style.flexDirection = "column";
7228
+ }
7229
+ column.appendChild(buildFooterHeading(colIndex, heading));
7230
+ let firstLink = null;
7231
+ items.forEach((item, itemIndex) => {
7232
+ const link = buildFooterLink(colIndex, itemIndex, item.href, item.label, linkTemplate);
7233
+ column.appendChild(link);
7234
+ if (!firstLink) firstLink = link;
7235
+ });
7236
+ container.appendChild(column);
7237
+ return { column, firstLink };
7238
+ }
7239
+ function insertFooterColumn(heading = DEFAULT_FOOTER_COLUMN_HEADING, linkLabel = DEFAULT_FOOTER_COLUMN_LINK_LABEL, linkHref = DEFAULT_FOOTER_COLUMN_LINK_HREF) {
7240
+ const colIndex = getNextFooterColumnIndex();
7241
+ const inserted = insertFooterColumnDom(colIndex, heading, [{ href: linkHref, label: linkLabel }]);
7242
+ if (!inserted?.firstLink) throw new Error("Failed to insert footer column");
7243
+ syncFooterColumnIndices(listFooterColumns());
7244
+ return {
7245
+ column: inserted.column,
7246
+ firstLink: inserted.firstLink,
7247
+ colIndex,
7248
+ headingKey: `footer-${colIndex}-heading`,
7249
+ hrefKey: `footer-${colIndex}-0-href`,
7250
+ labelKey: `footer-${colIndex}-0-label`,
7251
+ heading,
7252
+ label: linkLabel,
7253
+ href: linkHref,
7254
+ order: getFooterOrderFromDom()
7255
+ };
7256
+ }
7257
+ function collectFooterColumnIndicesFromContent(content) {
7258
+ const indices = /* @__PURE__ */ new Set();
7259
+ for (const key of Object.keys(content)) {
7260
+ const href = parseFooterHrefKey(key);
7261
+ if (href) indices.add(href.col);
7262
+ const heading = key.match(FOOTER_HEADING_RE);
7263
+ if (heading) indices.add(parseInt(heading[1], 10));
7264
+ const label = key.match(FOOTER_LABEL_RE);
7265
+ if (label) indices.add(parseInt(label[1], 10));
7266
+ }
7267
+ const order = parseFooterOrder(content);
7268
+ if (order) {
7269
+ for (const col of order) {
7270
+ for (const hrefKey of col) {
7271
+ const parsed = parseFooterHrefKey(hrefKey);
7272
+ if (parsed) indices.add(parsed.col);
7273
+ }
7274
+ }
7275
+ }
7276
+ return [...indices].sort((a, b) => a - b);
7277
+ }
7278
+ function collectFooterItemsForColumn(content, colIndex) {
7279
+ const itemIndices = /* @__PURE__ */ new Set();
7280
+ for (const key of Object.keys(content)) {
7281
+ const href = parseFooterHrefKey(key);
7282
+ if (href?.col === colIndex) itemIndices.add(href.item);
7283
+ const label = key.match(FOOTER_LABEL_RE);
7284
+ if (label && parseInt(label[1], 10) === colIndex) {
7285
+ itemIndices.add(parseInt(label[2], 10));
7286
+ }
7287
+ }
7288
+ const sorted = [...itemIndices].sort((a, b) => a - b);
7289
+ if (sorted.length === 0) {
7290
+ return [
7291
+ {
7292
+ href: content[`footer-${colIndex}-0-href`] ?? DEFAULT_FOOTER_COLUMN_LINK_HREF,
7293
+ label: content[`footer-${colIndex}-0-label`] ?? DEFAULT_FOOTER_COLUMN_LINK_LABEL
7294
+ }
7295
+ ];
7296
+ }
7297
+ return sorted.map((itemIndex) => ({
7298
+ href: content[`footer-${colIndex}-${itemIndex}-href`] ?? DEFAULT_FOOTER_COLUMN_LINK_HREF,
7299
+ label: content[`footer-${colIndex}-${itemIndex}-label`] ?? DEFAULT_FOOTER_COLUMN_LINK_LABEL
7300
+ }));
7301
+ }
7302
+ function reconcileFooterColumnsFromContent(content) {
7303
+ const indices = collectFooterColumnIndicesFromContent(content);
7304
+ for (const colIndex of indices) {
7305
+ if (footerColumnExistsInDom(colIndex)) continue;
7306
+ const heading = content[`footer-${colIndex}-heading`] ?? DEFAULT_FOOTER_COLUMN_HEADING;
7307
+ const items = collectFooterItemsForColumn(content, colIndex);
7308
+ const hasPayload = Boolean(content[`footer-${colIndex}-heading`]) || items.some(
7309
+ (_, i) => content[`footer-${colIndex}-${i}-href`] !== void 0 || content[`footer-${colIndex}-${i}-label`] !== void 0
7310
+ ) || (parseFooterOrder(content)?.some(
7311
+ (col) => col.some((k) => parseFooterHrefKey(k)?.col === colIndex)
7312
+ ) ?? false);
7313
+ if (!hasPayload) continue;
7314
+ insertFooterColumnDom(colIndex, heading, items);
7315
+ }
7316
+ }
7014
7317
  function reconcileFooterOrderFromContent(content) {
7318
+ reconcileFooterColumnsFromContent(content);
7015
7319
  const order = parseFooterOrder(content);
7016
7320
  if (!order?.length) return;
7017
7321
  const current = getFooterOrderFromDom();
@@ -7021,6 +7325,26 @@ function reconcileFooterOrderFromContent(content) {
7021
7325
  }
7022
7326
  applyFooterOrder(order);
7023
7327
  }
7328
+ function resolveFooterLinksContainerSelectionTarget(target, clientX, clientY, isPointOverItem) {
7329
+ const container = getFooterLinksContainer();
7330
+ if (!container) return null;
7331
+ const inContainer = target === container || container.contains(target) && Boolean(target.closest("[data-ohw-footer-links], .rb-footer-links"));
7332
+ if (!inContainer && target !== container) {
7333
+ const r2 = container.getBoundingClientRect();
7334
+ const over = clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
7335
+ if (!over) return null;
7336
+ }
7337
+ if (isPointOverItem(container, clientX, clientY)) return null;
7338
+ const column = target.closest("[data-ohw-footer-col], [data-ohw-footer-column]") ?? null;
7339
+ if (column && container.contains(column)) {
7340
+ if (target === column || column.contains(target)) return null;
7341
+ }
7342
+ if (target === container || container.contains(target) || inContainer) {
7343
+ if (target === container || isFooterLinksContainer(target)) return container;
7344
+ if (!column) return container;
7345
+ }
7346
+ return null;
7347
+ }
7024
7348
  function isRowLayoutColumn(links) {
7025
7349
  if (links.length < 2) return false;
7026
7350
  const firstTop = links[0].getBoundingClientRect().top;
@@ -7176,6 +7500,30 @@ function hitTestColumnDropSlot(clientX, _clientY) {
7176
7500
  return best?.slot ?? null;
7177
7501
  }
7178
7502
 
7503
+ // src/lib/add-footer-column.ts
7504
+ function buildFooterColumnEditContentPatch(result) {
7505
+ return {
7506
+ [result.headingKey]: result.heading,
7507
+ [result.hrefKey]: result.href,
7508
+ [result.labelKey]: result.label,
7509
+ [FOOTER_ORDER_KEY]: JSON.stringify(result.order)
7510
+ };
7511
+ }
7512
+ function addFooterColumnWithPersist({
7513
+ postToParent: postToParent2
7514
+ }) {
7515
+ const result = insertFooterColumn();
7516
+ const patch = buildFooterColumnEditContentPatch(result);
7517
+ setStoredLinkHref(result.hrefKey, result.href);
7518
+ postToParent2({
7519
+ type: "ow:change",
7520
+ nodes: Object.entries(patch).map(([key, text]) => ({ key, text }))
7521
+ });
7522
+ postToParent2({ type: "ow:toast", title: "Item added", toastType: "success" });
7523
+ enforceLinkHrefs();
7524
+ return result;
7525
+ }
7526
+
7179
7527
  // src/lib/item-drag-interaction.ts
7180
7528
  function disableNativeHrefDrag(el) {
7181
7529
  if (el.draggable) el.draggable = false;
@@ -7708,15 +8056,144 @@ function useNavItemDrag({
7708
8056
  };
7709
8057
  }
7710
8058
 
8059
+ // src/ui/footer-container-chrome.tsx
8060
+ var import_lucide_react11 = require("lucide-react");
8061
+ var import_jsx_runtime22 = require("react/jsx-runtime");
8062
+ function FooterContainerChrome({ rect, onAdd }) {
8063
+ const chromeGap = 6;
8064
+ const buttonMargin = 7;
8065
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8066
+ "div",
8067
+ {
8068
+ "data-ohw-footer-container-chrome": "",
8069
+ "data-ohw-bridge": "",
8070
+ className: "pointer-events-none fixed z-[2147483647]",
8071
+ style: {
8072
+ top: rect.top - chromeGap,
8073
+ left: rect.left - chromeGap,
8074
+ width: rect.width + chromeGap * 2,
8075
+ height: rect.height + chromeGap * 2
8076
+ },
8077
+ children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Tooltip, { children: [
8078
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8079
+ "button",
8080
+ {
8081
+ type: "button",
8082
+ "data-ohw-footer-add-button": "",
8083
+ className: "pointer-events-auto absolute left-1/2 flex size-7 -translate-x-1/2 -translate-y-full items-center justify-center rounded-[10px] border border-border bg-background p-0.5 shadow-sm transition-colors hover:bg-muted/80",
8084
+ style: { top: chromeGap - buttonMargin },
8085
+ "aria-label": "Add item",
8086
+ onMouseDown: (e) => {
8087
+ e.preventDefault();
8088
+ e.stopPropagation();
8089
+ },
8090
+ onClick: (e) => {
8091
+ e.preventDefault();
8092
+ e.stopPropagation();
8093
+ onAdd();
8094
+ },
8095
+ children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react11.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
8096
+ }
8097
+ ) }),
8098
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: "Add item" })
8099
+ ] })
8100
+ }
8101
+ ) });
8102
+ }
8103
+
8104
+ // src/lib/carousel.ts
8105
+ var import_react9 = require("react");
8106
+ var CAROUSEL_ATTR = "data-ohw-carousel";
8107
+ var CAROUSEL_VALUE_ATTR = "data-ohw-carousel-value";
8108
+ var CAROUSEL_SLIDE_ATTR = "data-ohw-carousel-slide";
8109
+ var CAROUSEL_EVENT = "ohw:carousel-change";
8110
+ function listCarouselKeys() {
8111
+ const keys = /* @__PURE__ */ new Set();
8112
+ document.querySelectorAll(`[${CAROUSEL_ATTR}]`).forEach((el) => {
8113
+ const key = el.getAttribute("data-ohw-key");
8114
+ if (key) keys.add(key);
8115
+ });
8116
+ return [...keys];
8117
+ }
8118
+ function containersForKey(key) {
8119
+ return Array.from(
8120
+ document.querySelectorAll(`[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`)
8121
+ );
8122
+ }
8123
+ function isCarouselKey(key) {
8124
+ return containersForKey(key).length > 0;
8125
+ }
8126
+ function parseSlides(raw) {
8127
+ if (!raw) return [];
8128
+ try {
8129
+ const parsed = JSON.parse(raw);
8130
+ if (!Array.isArray(parsed)) return [];
8131
+ return parsed.filter((s) => Boolean(s) && typeof s === "object").map((s) => ({ src: String(s.src ?? ""), alt: String(s.alt ?? "") }));
8132
+ } catch {
8133
+ return [];
8134
+ }
8135
+ }
8136
+ function readCarouselValue(key) {
8137
+ const container = containersForKey(key)[0];
8138
+ if (!container) return [];
8139
+ const fromAttr = parseSlides(container.getAttribute(CAROUSEL_VALUE_ATTR));
8140
+ if (fromAttr.length > 0) return fromAttr;
8141
+ return Array.from(container.querySelectorAll(`[${CAROUSEL_SLIDE_ATTR}]`)).filter((slide) => slide.closest(`[${CAROUSEL_ATTR}]`) === container).sort((a, b) => slideIndex(a) - slideIndex(b)).map((slide) => {
8142
+ const img = slide instanceof HTMLImageElement ? slide : slide.querySelector("img");
8143
+ return { src: img?.src ?? "", alt: img?.alt ?? "" };
8144
+ });
8145
+ }
8146
+ function slideIndex(el) {
8147
+ const raw = el.getAttribute(CAROUSEL_SLIDE_ATTR);
8148
+ const n = raw ? parseInt(raw, 10) : NaN;
8149
+ return Number.isFinite(n) ? n : 0;
8150
+ }
8151
+ function applyCarouselValue(key, slides) {
8152
+ const value = JSON.stringify(slides);
8153
+ for (const container of containersForKey(key)) {
8154
+ if (container.getAttribute(CAROUSEL_VALUE_ATTR) === value) continue;
8155
+ container.setAttribute(CAROUSEL_VALUE_ATTR, value);
8156
+ container.dispatchEvent(
8157
+ new CustomEvent(CAROUSEL_EVENT, { detail: { images: slides } })
8158
+ );
8159
+ }
8160
+ }
8161
+ function applyCarouselNode(key, val) {
8162
+ if (!isCarouselKey(key)) return false;
8163
+ applyCarouselValue(key, parseSlides(val));
8164
+ return true;
8165
+ }
8166
+ function useOhwCarousel(key, initial) {
8167
+ const [images, setImages] = (0, import_react9.useState)(initial);
8168
+ (0, import_react9.useEffect)(() => {
8169
+ const el = document.querySelector(
8170
+ `[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`
8171
+ );
8172
+ if (!el) return;
8173
+ const onChange = (e) => {
8174
+ const detail = e.detail;
8175
+ if (Array.isArray(detail?.images)) setImages(detail.images);
8176
+ };
8177
+ el.addEventListener(CAROUSEL_EVENT, onChange);
8178
+ return () => el.removeEventListener(CAROUSEL_EVENT, onChange);
8179
+ }, [key]);
8180
+ const bind = {
8181
+ [CAROUSEL_ATTR]: "",
8182
+ "data-ohw-key": key,
8183
+ [CAROUSEL_VALUE_ATTR]: JSON.stringify(images)
8184
+ };
8185
+ return { images, setImages, bind };
8186
+ }
8187
+
7711
8188
  // src/ui/navbar-container-chrome.tsx
7712
- var import_lucide_react10 = require("lucide-react");
7713
- var import_jsx_runtime21 = require("react/jsx-runtime");
8189
+ var import_lucide_react12 = require("lucide-react");
8190
+ var import_jsx_runtime23 = require("react/jsx-runtime");
7714
8191
  function NavbarContainerChrome({
7715
8192
  rect,
7716
8193
  onAdd
7717
8194
  }) {
7718
8195
  const chromeGap = 6;
7719
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
8196
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
7720
8197
  "div",
7721
8198
  {
7722
8199
  "data-ohw-navbar-container-chrome": "",
@@ -7728,7 +8205,7 @@ function NavbarContainerChrome({
7728
8205
  width: rect.width + chromeGap * 2,
7729
8206
  height: rect.height + chromeGap * 2
7730
8207
  },
7731
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
8208
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
7732
8209
  "button",
7733
8210
  {
7734
8211
  type: "button",
@@ -7745,7 +8222,7 @@ function NavbarContainerChrome({
7745
8222
  e.stopPropagation();
7746
8223
  onAdd();
7747
8224
  },
7748
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
8225
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react12.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
7749
8226
  }
7750
8227
  )
7751
8228
  }
@@ -7754,7 +8231,7 @@ function NavbarContainerChrome({
7754
8231
 
7755
8232
  // src/ui/drop-indicator.tsx
7756
8233
  var React10 = __toESM(require("react"), 1);
7757
- var import_jsx_runtime22 = require("react/jsx-runtime");
8234
+ var import_jsx_runtime24 = require("react/jsx-runtime");
7758
8235
  var dropIndicatorVariants = cva(
7759
8236
  "ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
7760
8237
  {
@@ -7778,7 +8255,7 @@ var dropIndicatorVariants = cva(
7778
8255
  );
7779
8256
  var DropIndicator = React10.forwardRef(
7780
8257
  ({ className, direction, state, ...props }, ref) => {
7781
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8258
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
7782
8259
  "div",
7783
8260
  {
7784
8261
  ref,
@@ -7795,7 +8272,7 @@ var DropIndicator = React10.forwardRef(
7795
8272
  DropIndicator.displayName = "DropIndicator";
7796
8273
 
7797
8274
  // src/ui/badge.tsx
7798
- var import_jsx_runtime23 = require("react/jsx-runtime");
8275
+ var import_jsx_runtime25 = require("react/jsx-runtime");
7799
8276
  var badgeVariants = cva(
7800
8277
  "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",
7801
8278
  {
@@ -7813,12 +8290,12 @@ var badgeVariants = cva(
7813
8290
  }
7814
8291
  );
7815
8292
  function Badge({ className, variant, ...props }) {
7816
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
8293
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
7817
8294
  }
7818
8295
 
7819
8296
  // src/OhhwellsBridge.tsx
7820
- var import_lucide_react11 = require("lucide-react");
7821
- var import_jsx_runtime24 = require("react/jsx-runtime");
8297
+ var import_lucide_react13 = require("lucide-react");
8298
+ var import_jsx_runtime26 = require("react/jsx-runtime");
7822
8299
  var PRIMARY2 = "#0885FE";
7823
8300
  var IMAGE_FADE_MS = 300;
7824
8301
  function runOpacityFade(el, onDone) {
@@ -7997,7 +8474,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
7997
8474
  const root = (0, import_client.createRoot)(container);
7998
8475
  (0, import_react_dom2.flushSync)(() => {
7999
8476
  root.render(
8000
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
8477
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
8001
8478
  SchedulingWidget,
8002
8479
  {
8003
8480
  notifyOnConnect,
@@ -8115,6 +8592,9 @@ function collectEditableNodes(extraContent) {
8115
8592
  nodes.push({ key: `${key}${VIDEO_AUTOPLAY_SUFFIX}`, type: "video-setting", text: String(video.autoplay) });
8116
8593
  nodes.push({ key: `${key}${VIDEO_MUTED_SUFFIX}`, type: "video-setting", text: String(video.muted) });
8117
8594
  });
8595
+ for (const key of listCarouselKeys()) {
8596
+ nodes.push({ key, type: "carousel", text: JSON.stringify(readCarouselValue(key)) });
8597
+ }
8118
8598
  const seen = /* @__PURE__ */ new Set();
8119
8599
  return nodes.filter((node) => {
8120
8600
  if (!node.key) return true;
@@ -8198,7 +8678,7 @@ function applyLinkByKey(key, val) {
8198
8678
  }
8199
8679
  function isInsideLinkEditor(target) {
8200
8680
  return Boolean(
8201
- target.closest("[data-ohw-link-popover-root]") || target.closest("[data-ohw-link-modal-root]") || target.closest("[data-ohw-link-page-dropdown]") || target.closest("[data-ohw-section-picker]") || target.closest("[data-ohw-navbar-container-chrome]") || target.closest("[data-ohw-navbar-add-button]") || target.closest('[data-slot="popover-content"]') || target.closest('[data-slot="dialog-content"]') || target.closest('[data-slot="dialog-overlay"]')
8681
+ target.closest("[data-ohw-link-popover-root]") || target.closest("[data-ohw-link-modal-root]") || target.closest("[data-ohw-link-page-dropdown]") || target.closest("[data-ohw-section-picker]") || target.closest("[data-ohw-navbar-container-chrome]") || target.closest("[data-ohw-navbar-add-button]") || target.closest("[data-ohw-footer-container-chrome]") || target.closest("[data-ohw-footer-add-button]") || target.closest('[data-slot="popover-content"]') || target.closest('[data-slot="dialog-content"]') || target.closest('[data-slot="dialog-overlay"]')
8202
8682
  );
8203
8683
  }
8204
8684
  function getHrefKeyFromElement(el) {
@@ -8279,7 +8759,7 @@ function isInferredFooterGroup(el) {
8279
8759
  return countFooterNavItems(el) >= 2;
8280
8760
  }
8281
8761
  function isNavigationContainer(el) {
8282
- return el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isNavigationRoot(el) || isInferredFooterGroup(el);
8762
+ return el.hasAttribute("data-ohw-nav-container") || isFooterLinksContainer(el) || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isNavigationRoot(el) || isInferredFooterGroup(el);
8283
8763
  }
8284
8764
  function isNavbarLinksContainer(el) {
8285
8765
  return el.hasAttribute("data-ohw-nav-container");
@@ -8298,6 +8778,9 @@ function isPointOverNavigation(x, y) {
8298
8778
  const roots = /* @__PURE__ */ new Set();
8299
8779
  const navRoot = document.querySelector("[data-ohw-nav-root]") ?? document.querySelector("nav");
8300
8780
  if (navRoot) roots.add(navRoot);
8781
+ document.querySelectorAll("[data-ohw-nav-drawer], [data-ohw-nav-container]").forEach((el) => {
8782
+ roots.add(el);
8783
+ });
8301
8784
  const footer = document.querySelector("footer");
8302
8785
  if (footer) roots.add(footer);
8303
8786
  for (const root of roots) {
@@ -8326,6 +8809,12 @@ function isPointOverNavItem(container, x, y) {
8326
8809
  return x >= itemRect.left && x <= itemRect.right && y >= itemRect.top && y <= itemRect.bottom;
8327
8810
  });
8328
8811
  }
8812
+ function isPointOverFooterColumn(x, y) {
8813
+ return listFooterColumns().some((col) => {
8814
+ const r2 = col.getBoundingClientRect();
8815
+ return x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom;
8816
+ });
8817
+ }
8329
8818
  function resolveNavContainerSelectionTarget(target, clientX, clientY) {
8330
8819
  if (getNavigationItemAnchor(target)) return null;
8331
8820
  if (target.closest('[data-ohw-role="navbar-button"]')) return null;
@@ -8356,7 +8845,10 @@ function getNavigationSelectionParent(el) {
8356
8845
  if (footerGroup) return footerGroup;
8357
8846
  return getNavigationRoot(el);
8358
8847
  }
8359
- if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup(el)) {
8848
+ if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup(el))) {
8849
+ return getFooterLinksContainer();
8850
+ }
8851
+ if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isFooterLinksContainer(el) || isInferredFooterGroup(el)) {
8360
8852
  return getNavigationRoot(el);
8361
8853
  }
8362
8854
  return null;
@@ -8583,7 +9075,7 @@ function EditGlowChrome({
8583
9075
  hideHandle = false
8584
9076
  }) {
8585
9077
  const GAP = SELECTION_CHROME_GAP2;
8586
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
9078
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
8587
9079
  "div",
8588
9080
  {
8589
9081
  ref: elRef,
@@ -8598,7 +9090,7 @@ function EditGlowChrome({
8598
9090
  zIndex: 2147483646
8599
9091
  },
8600
9092
  children: [
8601
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9093
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
8602
9094
  "div",
8603
9095
  {
8604
9096
  style: {
@@ -8611,7 +9103,7 @@ function EditGlowChrome({
8611
9103
  }
8612
9104
  }
8613
9105
  ),
8614
- reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9106
+ reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
8615
9107
  "div",
8616
9108
  {
8617
9109
  "data-ohw-drag-handle-container": "",
@@ -8623,7 +9115,7 @@ function EditGlowChrome({
8623
9115
  transform: "translate(calc(-100% - 7px), -50%)",
8624
9116
  pointerEvents: dragDisabled ? "none" : "auto"
8625
9117
  },
8626
- children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9118
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
8627
9119
  DragHandle,
8628
9120
  {
8629
9121
  "aria-label": `Reorder ${reorderHrefKey}`,
@@ -8806,9 +9298,9 @@ function FloatingToolbar({
8806
9298
  showEditLink,
8807
9299
  onEditLink
8808
9300
  }) {
8809
- const localRef = import_react9.default.useRef(null);
8810
- const [measuredW, setMeasuredW] = import_react9.default.useState(330);
8811
- const setRefs = import_react9.default.useCallback(
9301
+ const localRef = import_react10.default.useRef(null);
9302
+ const [measuredW, setMeasuredW] = import_react10.default.useState(330);
9303
+ const setRefs = import_react10.default.useCallback(
8812
9304
  (node) => {
8813
9305
  localRef.current = node;
8814
9306
  if (typeof elRef === "function") elRef(node);
@@ -8820,7 +9312,7 @@ function FloatingToolbar({
8820
9312
  },
8821
9313
  [elRef]
8822
9314
  );
8823
- import_react9.default.useLayoutEffect(() => {
9315
+ import_react10.default.useLayoutEffect(() => {
8824
9316
  const node = localRef.current;
8825
9317
  if (!node) return;
8826
9318
  const update = () => {
@@ -8833,7 +9325,7 @@ function FloatingToolbar({
8833
9325
  return () => ro.disconnect();
8834
9326
  }, [showEditLink, activeCommands]);
8835
9327
  const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
8836
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9328
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
8837
9329
  "div",
8838
9330
  {
8839
9331
  ref: setRefs,
@@ -8845,12 +9337,12 @@ function FloatingToolbar({
8845
9337
  zIndex: 2147483647,
8846
9338
  pointerEvents: "auto"
8847
9339
  },
8848
- children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(CustomToolbar, { children: [
8849
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react9.default.Fragment, { children: [
8850
- gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(CustomToolbarDivider, {}),
9340
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(CustomToolbar, { children: [
9341
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_react10.default.Fragment, { children: [
9342
+ gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(CustomToolbarDivider, {}),
8851
9343
  btns.map((btn) => {
8852
9344
  const isActive = activeCommands.has(btn.cmd);
8853
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9345
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
8854
9346
  CustomToolbarButton,
8855
9347
  {
8856
9348
  title: btn.title,
@@ -8859,7 +9351,7 @@ function FloatingToolbar({
8859
9351
  e.preventDefault();
8860
9352
  onCommand(btn.cmd);
8861
9353
  },
8862
- children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9354
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
8863
9355
  "svg",
8864
9356
  {
8865
9357
  width: "16",
@@ -8880,7 +9372,7 @@ function FloatingToolbar({
8880
9372
  );
8881
9373
  })
8882
9374
  ] }, gi)),
8883
- showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9375
+ showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
8884
9376
  CustomToolbarButton,
8885
9377
  {
8886
9378
  type: "button",
@@ -8894,7 +9386,7 @@ function FloatingToolbar({
8894
9386
  e.preventDefault();
8895
9387
  e.stopPropagation();
8896
9388
  },
8897
- children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Link, { className: "size-4 shrink-0", "aria-hidden": true })
9389
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.Link, { className: "size-4 shrink-0", "aria-hidden": true })
8898
9390
  }
8899
9391
  ) : null
8900
9392
  ] })
@@ -8911,7 +9403,7 @@ function StateToggle({
8911
9403
  states,
8912
9404
  onStateChange
8913
9405
  }) {
8914
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9406
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
8915
9407
  ToggleGroup,
8916
9408
  {
8917
9409
  "data-ohw-state-toggle": "",
@@ -8925,7 +9417,7 @@ function StateToggle({
8925
9417
  left: rect.right - 8,
8926
9418
  transform: "translateX(-100%)"
8927
9419
  },
8928
- children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
9420
+ children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
8929
9421
  }
8930
9422
  );
8931
9423
  }
@@ -8952,8 +9444,8 @@ function OhhwellsBridge() {
8952
9444
  const router = (0, import_navigation2.useRouter)();
8953
9445
  const searchParams = (0, import_navigation2.useSearchParams)();
8954
9446
  const isEditMode = isEditSessionActive();
8955
- const [bridgeRoot, setBridgeRoot] = (0, import_react9.useState)(null);
8956
- (0, import_react9.useEffect)(() => {
9447
+ const [bridgeRoot, setBridgeRoot] = (0, import_react10.useState)(null);
9448
+ (0, import_react10.useEffect)(() => {
8957
9449
  const figtreeFontId = "ohw-figtree-font";
8958
9450
  if (!document.getElementById(figtreeFontId)) {
8959
9451
  const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
@@ -8981,98 +9473,99 @@ function OhhwellsBridge() {
8981
9473
  const subdomainFromQuery = searchParams.get("subdomain");
8982
9474
  const subdomain = resolveSubdomain(subdomainFromQuery);
8983
9475
  useLinkHrefGuardian(pathname, subdomain, isEditMode);
8984
- const postToParent2 = (0, import_react9.useCallback)((data) => {
9476
+ const postToParent2 = (0, import_react10.useCallback)((data) => {
8985
9477
  if (typeof window !== "undefined" && window.parent !== window) {
8986
9478
  window.parent.postMessage(data, "*");
8987
9479
  }
8988
9480
  }, []);
8989
- const [fetchState, setFetchState] = (0, import_react9.useState)("idle");
8990
- const autoSaveTimers = (0, import_react9.useRef)(/* @__PURE__ */ new Map());
8991
- const activeElRef = (0, import_react9.useRef)(null);
8992
- const pointerHeldRef = (0, import_react9.useRef)(false);
8993
- const selectedElRef = (0, import_react9.useRef)(null);
8994
- const selectedHrefKeyRef = (0, import_react9.useRef)(null);
8995
- const selectedFooterColAttrRef = (0, import_react9.useRef)(null);
8996
- const originalContentRef = (0, import_react9.useRef)(null);
8997
- const activeStateElRef = (0, import_react9.useRef)(null);
8998
- const parentScrollRef = (0, import_react9.useRef)(null);
8999
- const visibleViewportRef = (0, import_react9.useRef)(null);
9000
- const [dialogPortalContainer, setDialogPortalContainer] = (0, import_react9.useState)(null);
9001
- const attachVisibleViewport = (0, import_react9.useCallback)((node) => {
9481
+ const [fetchState, setFetchState] = (0, import_react10.useState)("idle");
9482
+ const autoSaveTimers = (0, import_react10.useRef)(/* @__PURE__ */ new Map());
9483
+ const activeElRef = (0, import_react10.useRef)(null);
9484
+ const pointerHeldRef = (0, import_react10.useRef)(false);
9485
+ const selectedElRef = (0, import_react10.useRef)(null);
9486
+ const selectedHrefKeyRef = (0, import_react10.useRef)(null);
9487
+ const selectedFooterColAttrRef = (0, import_react10.useRef)(null);
9488
+ const originalContentRef = (0, import_react10.useRef)(null);
9489
+ const activeStateElRef = (0, import_react10.useRef)(null);
9490
+ const parentScrollRef = (0, import_react10.useRef)(null);
9491
+ const visibleViewportRef = (0, import_react10.useRef)(null);
9492
+ const [dialogPortalContainer, setDialogPortalContainer] = (0, import_react10.useState)(null);
9493
+ const attachVisibleViewport = (0, import_react10.useCallback)((node) => {
9002
9494
  visibleViewportRef.current = node;
9003
9495
  setDialogPortalContainer(node);
9004
9496
  if (node) applyVisibleViewport(node, parentScrollRef.current);
9005
9497
  }, []);
9006
- const toolbarElRef = (0, import_react9.useRef)(null);
9007
- const glowElRef = (0, import_react9.useRef)(null);
9008
- const hoveredImageRef = (0, import_react9.useRef)(null);
9009
- const hoveredImageHasTextOverlapRef = (0, import_react9.useRef)(false);
9010
- const dragOverElRef = (0, import_react9.useRef)(null);
9011
- const [mediaHover, setMediaHover] = (0, import_react9.useState)(null);
9012
- const [uploadingRects, setUploadingRects] = (0, import_react9.useState)({});
9013
- const hoveredGapRef = (0, import_react9.useRef)(null);
9014
- const imageUnhoverTimerRef = (0, import_react9.useRef)(null);
9015
- const imageShowTimerRef = (0, import_react9.useRef)(null);
9016
- const editStylesRef = (0, import_react9.useRef)(null);
9017
- const activateRef = (0, import_react9.useRef)(() => {
9498
+ const toolbarElRef = (0, import_react10.useRef)(null);
9499
+ const glowElRef = (0, import_react10.useRef)(null);
9500
+ const hoveredImageRef = (0, import_react10.useRef)(null);
9501
+ const hoveredImageHasTextOverlapRef = (0, import_react10.useRef)(false);
9502
+ const dragOverElRef = (0, import_react10.useRef)(null);
9503
+ const [mediaHover, setMediaHover] = (0, import_react10.useState)(null);
9504
+ const [carouselHover, setCarouselHover] = (0, import_react10.useState)(null);
9505
+ const [uploadingRects, setUploadingRects] = (0, import_react10.useState)({});
9506
+ const hoveredGapRef = (0, import_react10.useRef)(null);
9507
+ const imageUnhoverTimerRef = (0, import_react10.useRef)(null);
9508
+ const imageShowTimerRef = (0, import_react10.useRef)(null);
9509
+ const editStylesRef = (0, import_react10.useRef)(null);
9510
+ const activateRef = (0, import_react10.useRef)(() => {
9018
9511
  });
9019
- const deactivateRef = (0, import_react9.useRef)(() => {
9512
+ const deactivateRef = (0, import_react10.useRef)(() => {
9020
9513
  });
9021
- const selectRef = (0, import_react9.useRef)(() => {
9514
+ const selectRef = (0, import_react10.useRef)(() => {
9022
9515
  });
9023
- const selectFrameRef = (0, import_react9.useRef)(() => {
9516
+ const selectFrameRef = (0, import_react10.useRef)(() => {
9024
9517
  });
9025
- const deselectRef = (0, import_react9.useRef)(() => {
9518
+ const deselectRef = (0, import_react10.useRef)(() => {
9026
9519
  });
9027
- const reselectNavigationItemRef = (0, import_react9.useRef)(() => {
9520
+ const reselectNavigationItemRef = (0, import_react10.useRef)(() => {
9028
9521
  });
9029
- const commitNavigationTextEditRef = (0, import_react9.useRef)(() => {
9522
+ const commitNavigationTextEditRef = (0, import_react10.useRef)(() => {
9030
9523
  });
9031
- const refreshActiveCommandsRef = (0, import_react9.useRef)(() => {
9524
+ const refreshActiveCommandsRef = (0, import_react10.useRef)(() => {
9032
9525
  });
9033
- const postToParentRef = (0, import_react9.useRef)(postToParent2);
9526
+ const postToParentRef = (0, import_react10.useRef)(postToParent2);
9034
9527
  postToParentRef.current = postToParent2;
9035
- const sectionsLoadedRef = (0, import_react9.useRef)(false);
9036
- const pendingScheduleConfigRequests = (0, import_react9.useRef)([]);
9037
- const [toolbarRect, setToolbarRect] = (0, import_react9.useState)(null);
9038
- const [toolbarVariant, setToolbarVariant] = (0, import_react9.useState)("none");
9039
- const toolbarVariantRef = (0, import_react9.useRef)("none");
9528
+ const sectionsLoadedRef = (0, import_react10.useRef)(false);
9529
+ const pendingScheduleConfigRequests = (0, import_react10.useRef)([]);
9530
+ const [toolbarRect, setToolbarRect] = (0, import_react10.useState)(null);
9531
+ const [toolbarVariant, setToolbarVariant] = (0, import_react10.useState)("none");
9532
+ const toolbarVariantRef = (0, import_react10.useRef)("none");
9040
9533
  toolbarVariantRef.current = toolbarVariant;
9041
- const [selectedIsCta, setSelectedIsCta] = (0, import_react9.useState)(false);
9042
- const [reorderHrefKey, setReorderHrefKey] = (0, import_react9.useState)(null);
9043
- const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react9.useState)(false);
9044
- const [toggleState, setToggleState] = (0, import_react9.useState)(null);
9045
- const [maxBadge, setMaxBadge] = (0, import_react9.useState)(null);
9046
- const [activeCommands, setActiveCommands] = (0, import_react9.useState)(/* @__PURE__ */ new Set());
9047
- const [sectionGap, setSectionGap] = (0, import_react9.useState)(null);
9048
- const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react9.useState)(false);
9049
- const hoveredNavContainerRef = (0, import_react9.useRef)(null);
9050
- const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0, import_react9.useState)(null);
9051
- const hoveredItemElRef = (0, import_react9.useRef)(null);
9052
- const [hoveredItemRect, setHoveredItemRect] = (0, import_react9.useState)(null);
9053
- const siblingHintElRef = (0, import_react9.useRef)(null);
9054
- const [siblingHintRect, setSiblingHintRect] = (0, import_react9.useState)(null);
9055
- const [siblingHintRects, setSiblingHintRects] = (0, import_react9.useState)([]);
9056
- const [isItemDragging, setIsItemDragging] = (0, import_react9.useState)(false);
9057
- const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react9.useState)(false);
9058
- const footerDragRef = (0, import_react9.useRef)(null);
9059
- const [footerDropSlots, setFooterDropSlots] = (0, import_react9.useState)([]);
9060
- const [activeFooterDropIndex, setActiveFooterDropIndex] = (0, import_react9.useState)(null);
9061
- const [draggedItemRect, setDraggedItemRect] = (0, import_react9.useState)(null);
9062
- const footerPointerDragRef = (0, import_react9.useRef)(null);
9063
- const suppressNextClickRef = (0, import_react9.useRef)(false);
9064
- const suppressClickUntilRef = (0, import_react9.useRef)(0);
9065
- const [linkPopover, setLinkPopover] = (0, import_react9.useState)(null);
9066
- const linkPopoverSessionRef = (0, import_react9.useRef)(null);
9067
- const addNavAfterAnchorRef = (0, import_react9.useRef)(null);
9068
- const editContentRef = (0, import_react9.useRef)({});
9069
- const [sitePages, setSitePages] = (0, import_react9.useState)([]);
9070
- const [sectionsByPath, setSectionsByPath] = (0, import_react9.useState)({});
9071
- const sectionsPrefetchGenRef = (0, import_react9.useRef)(0);
9072
- const setLinkPopoverRef = (0, import_react9.useRef)(setLinkPopover);
9073
- const linkPopoverPanelRef = (0, import_react9.useRef)(null);
9074
- const linkPopoverOpenRef = (0, import_react9.useRef)(false);
9075
- const linkPopoverGraceUntilRef = (0, import_react9.useRef)(0);
9534
+ const [selectedIsCta, setSelectedIsCta] = (0, import_react10.useState)(false);
9535
+ const [reorderHrefKey, setReorderHrefKey] = (0, import_react10.useState)(null);
9536
+ const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react10.useState)(false);
9537
+ const [toggleState, setToggleState] = (0, import_react10.useState)(null);
9538
+ const [maxBadge, setMaxBadge] = (0, import_react10.useState)(null);
9539
+ const [activeCommands, setActiveCommands] = (0, import_react10.useState)(/* @__PURE__ */ new Set());
9540
+ const [sectionGap, setSectionGap] = (0, import_react10.useState)(null);
9541
+ const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react10.useState)(false);
9542
+ const hoveredNavContainerRef = (0, import_react10.useRef)(null);
9543
+ const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0, import_react10.useState)(null);
9544
+ const hoveredItemElRef = (0, import_react10.useRef)(null);
9545
+ const [hoveredItemRect, setHoveredItemRect] = (0, import_react10.useState)(null);
9546
+ const siblingHintElRef = (0, import_react10.useRef)(null);
9547
+ const [siblingHintRect, setSiblingHintRect] = (0, import_react10.useState)(null);
9548
+ const [siblingHintRects, setSiblingHintRects] = (0, import_react10.useState)([]);
9549
+ const [isItemDragging, setIsItemDragging] = (0, import_react10.useState)(false);
9550
+ const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react10.useState)(false);
9551
+ const footerDragRef = (0, import_react10.useRef)(null);
9552
+ const [footerDropSlots, setFooterDropSlots] = (0, import_react10.useState)([]);
9553
+ const [activeFooterDropIndex, setActiveFooterDropIndex] = (0, import_react10.useState)(null);
9554
+ const [draggedItemRect, setDraggedItemRect] = (0, import_react10.useState)(null);
9555
+ const footerPointerDragRef = (0, import_react10.useRef)(null);
9556
+ const suppressNextClickRef = (0, import_react10.useRef)(false);
9557
+ const suppressClickUntilRef = (0, import_react10.useRef)(0);
9558
+ const [linkPopover, setLinkPopover] = (0, import_react10.useState)(null);
9559
+ const linkPopoverSessionRef = (0, import_react10.useRef)(null);
9560
+ const addNavAfterAnchorRef = (0, import_react10.useRef)(null);
9561
+ const editContentRef = (0, import_react10.useRef)({});
9562
+ const [sitePages, setSitePages] = (0, import_react10.useState)([]);
9563
+ const [sectionsByPath, setSectionsByPath] = (0, import_react10.useState)({});
9564
+ const sectionsPrefetchGenRef = (0, import_react10.useRef)(0);
9565
+ const setLinkPopoverRef = (0, import_react10.useRef)(setLinkPopover);
9566
+ const linkPopoverPanelRef = (0, import_react10.useRef)(null);
9567
+ const linkPopoverOpenRef = (0, import_react10.useRef)(false);
9568
+ const linkPopoverGraceUntilRef = (0, import_react10.useRef)(0);
9076
9569
  setLinkPopoverRef.current = setLinkPopover;
9077
9570
  linkPopoverSessionRef.current = linkPopover;
9078
9571
  const {
@@ -9111,7 +9604,7 @@ function OhhwellsBridge() {
9111
9604
  const bumpLinkPopoverGrace = () => {
9112
9605
  linkPopoverGraceUntilRef.current = Date.now() + 350;
9113
9606
  };
9114
- const runSectionsPrefetch = (0, import_react9.useCallback)((pages) => {
9607
+ const runSectionsPrefetch = (0, import_react10.useCallback)((pages) => {
9115
9608
  if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
9116
9609
  const gen = ++sectionsPrefetchGenRef.current;
9117
9610
  const paths = pages.map((p) => p.path);
@@ -9130,9 +9623,9 @@ function OhhwellsBridge() {
9130
9623
  );
9131
9624
  });
9132
9625
  }, [isEditMode, pathname]);
9133
- const runSectionsPrefetchRef = (0, import_react9.useRef)(runSectionsPrefetch);
9626
+ const runSectionsPrefetchRef = (0, import_react10.useRef)(runSectionsPrefetch);
9134
9627
  runSectionsPrefetchRef.current = runSectionsPrefetch;
9135
- (0, import_react9.useEffect)(() => {
9628
+ (0, import_react10.useEffect)(() => {
9136
9629
  if (!linkPopover) {
9137
9630
  document.documentElement.removeAttribute("data-ohw-link-popover-open");
9138
9631
  return;
@@ -9182,7 +9675,7 @@ function OhhwellsBridge() {
9182
9675
  document.removeEventListener("touchmove", preventBackgroundScroll, scrollOpts);
9183
9676
  };
9184
9677
  }, [linkPopover, postToParent2]);
9185
- (0, import_react9.useEffect)(() => {
9678
+ (0, import_react10.useEffect)(() => {
9186
9679
  if (!isEditMode) return;
9187
9680
  const useFixtures = shouldUseDevFixtures();
9188
9681
  if (useFixtures) {
@@ -9206,14 +9699,14 @@ function OhhwellsBridge() {
9206
9699
  if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
9207
9700
  return () => window.removeEventListener("message", onSitePages);
9208
9701
  }, [isEditMode, postToParent2]);
9209
- (0, import_react9.useEffect)(() => {
9702
+ (0, import_react10.useEffect)(() => {
9210
9703
  if (!isEditMode || shouldUseDevFixtures()) return;
9211
9704
  void loadAllSectionsManifest().then((manifest) => {
9212
9705
  if (Object.keys(manifest).length === 0) return;
9213
9706
  setSectionsByPath((prev) => ({ ...manifest, ...prev }));
9214
9707
  });
9215
9708
  }, [isEditMode]);
9216
- (0, import_react9.useEffect)(() => {
9709
+ (0, import_react10.useEffect)(() => {
9217
9710
  const update = () => {
9218
9711
  const el = activeElRef.current ?? selectedElRef.current;
9219
9712
  if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
@@ -9237,10 +9730,10 @@ function OhhwellsBridge() {
9237
9730
  vvp.removeEventListener("resize", update);
9238
9731
  };
9239
9732
  }, []);
9240
- const refreshStateRules = (0, import_react9.useCallback)(() => {
9733
+ const refreshStateRules = (0, import_react10.useCallback)(() => {
9241
9734
  editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
9242
9735
  }, []);
9243
- const processConfigRequest = (0, import_react9.useCallback)((insertAfterVal) => {
9736
+ const processConfigRequest = (0, import_react10.useCallback)((insertAfterVal) => {
9244
9737
  const tracker = getSectionsTracker();
9245
9738
  let entries = [];
9246
9739
  try {
@@ -9263,7 +9756,7 @@ function OhhwellsBridge() {
9263
9756
  }
9264
9757
  window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
9265
9758
  }, [isEditMode]);
9266
- const deactivate = (0, import_react9.useCallback)(() => {
9759
+ const deactivate = (0, import_react10.useCallback)(() => {
9267
9760
  const el = activeElRef.current;
9268
9761
  if (!el) return;
9269
9762
  const key = el.dataset.ohwKey;
@@ -9295,12 +9788,12 @@ function OhhwellsBridge() {
9295
9788
  setToolbarShowEditLink(false);
9296
9789
  postToParent2({ type: "ow:exit-edit" });
9297
9790
  }, [postToParent2]);
9298
- const clearSelectedAttr = (0, import_react9.useCallback)(() => {
9791
+ const clearSelectedAttr = (0, import_react10.useCallback)(() => {
9299
9792
  document.querySelectorAll("[data-ohw-selected]").forEach((el) => {
9300
9793
  el.removeAttribute("data-ohw-selected");
9301
9794
  });
9302
9795
  }, []);
9303
- const deselect = (0, import_react9.useCallback)(() => {
9796
+ const deselect = (0, import_react10.useCallback)(() => {
9304
9797
  clearSelectedAttr();
9305
9798
  selectedElRef.current = null;
9306
9799
  selectedHrefKeyRef.current = null;
@@ -9320,11 +9813,11 @@ function OhhwellsBridge() {
9320
9813
  setToolbarVariant("none");
9321
9814
  }
9322
9815
  }, [clearSelectedAttr]);
9323
- const markSelected = (0, import_react9.useCallback)((el) => {
9816
+ const markSelected = (0, import_react10.useCallback)((el) => {
9324
9817
  clearSelectedAttr();
9325
9818
  el.setAttribute("data-ohw-selected", "");
9326
9819
  }, [clearSelectedAttr]);
9327
- const resolveHrefKeyElement = (0, import_react9.useCallback)((hrefKey) => {
9820
+ const resolveHrefKeyElement = (0, import_react10.useCallback)((hrefKey) => {
9328
9821
  if (isFooterHrefKey(hrefKey)) {
9329
9822
  return document.querySelector(
9330
9823
  `footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
@@ -9339,7 +9832,7 @@ function OhhwellsBridge() {
9339
9832
  `[data-ohw-href-key="${CSS.escape(hrefKey)}"]`
9340
9833
  );
9341
9834
  }, []);
9342
- const resyncSelectedNavigationItem = (0, import_react9.useCallback)(() => {
9835
+ const resyncSelectedNavigationItem = (0, import_react10.useCallback)(() => {
9343
9836
  const hrefKey = selectedHrefKeyRef.current;
9344
9837
  if (hrefKey) {
9345
9838
  const link = resolveHrefKeyElement(hrefKey);
@@ -9367,7 +9860,7 @@ function OhhwellsBridge() {
9367
9860
  );
9368
9861
  }
9369
9862
  }, [resolveHrefKeyElement]);
9370
- const reselectNavigationItem = (0, import_react9.useCallback)((navAnchor) => {
9863
+ const reselectNavigationItem = (0, import_react10.useCallback)((navAnchor) => {
9371
9864
  selectedElRef.current = navAnchor;
9372
9865
  selectedHrefKeyRef.current = navAnchor.getAttribute("data-ohw-href-key");
9373
9866
  selectedFooterColAttrRef.current = null;
@@ -9382,7 +9875,7 @@ function OhhwellsBridge() {
9382
9875
  setToolbarShowEditLink(false);
9383
9876
  setActiveCommands(/* @__PURE__ */ new Set());
9384
9877
  }, [markSelected]);
9385
- const commitNavigationTextEdit = (0, import_react9.useCallback)((navAnchor) => {
9878
+ const commitNavigationTextEdit = (0, import_react10.useCallback)((navAnchor) => {
9386
9879
  const el = activeElRef.current;
9387
9880
  if (!el) return;
9388
9881
  const key = el.dataset.ohwKey;
@@ -9409,7 +9902,7 @@ function OhhwellsBridge() {
9409
9902
  postToParent2({ type: "ow:exit-edit" });
9410
9903
  reselectNavigationItem(navAnchor);
9411
9904
  }, [postToParent2, reselectNavigationItem]);
9412
- const handleAddTopLevelNavItem = (0, import_react9.useCallback)(() => {
9905
+ const handleAddTopLevelNavItem = (0, import_react10.useCallback)(() => {
9413
9906
  const items = listNavbarItems();
9414
9907
  addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
9415
9908
  deselectRef.current();
@@ -9421,7 +9914,19 @@ function OhhwellsBridge() {
9421
9914
  intent: "add-nav"
9422
9915
  });
9423
9916
  }, []);
9424
- const clearFooterDragVisuals = (0, import_react9.useCallback)(() => {
9917
+ const handleAddFooterColumn = (0, import_react10.useCallback)(() => {
9918
+ deselectRef.current();
9919
+ deactivateRef.current();
9920
+ const result = addFooterColumnWithPersist({ postToParent: postToParent2 });
9921
+ editContentRef.current = {
9922
+ ...editContentRef.current,
9923
+ ...buildFooterColumnEditContentPatch(result)
9924
+ };
9925
+ requestAnimationFrame(() => {
9926
+ selectRef.current(result.firstLink);
9927
+ });
9928
+ }, [postToParent2]);
9929
+ const clearFooterDragVisuals = (0, import_react10.useCallback)(() => {
9425
9930
  footerDragRef.current = null;
9426
9931
  setSiblingHintRects([]);
9427
9932
  setFooterDropSlots([]);
@@ -9430,7 +9935,7 @@ function OhhwellsBridge() {
9430
9935
  setIsItemDragging(false);
9431
9936
  unlockFooterDragInteraction();
9432
9937
  }, []);
9433
- const refreshFooterDragVisuals = (0, import_react9.useCallback)((session, activeSlot, clientX, clientY) => {
9938
+ const refreshFooterDragVisuals = (0, import_react10.useCallback)((session, activeSlot, clientX, clientY) => {
9434
9939
  const dragged = session.draggedEl;
9435
9940
  setDraggedItemRect(dragged.getBoundingClientRect());
9436
9941
  if (typeof clientX === "number" && typeof clientY === "number") {
@@ -9455,13 +9960,13 @@ function OhhwellsBridge() {
9455
9960
  const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
9456
9961
  setActiveFooterDropIndex(activeIdx >= 0 ? activeIdx : null);
9457
9962
  }, []);
9458
- const refreshFooterDragVisualsRef = (0, import_react9.useRef)(refreshFooterDragVisuals);
9963
+ const refreshFooterDragVisualsRef = (0, import_react10.useRef)(refreshFooterDragVisuals);
9459
9964
  refreshFooterDragVisualsRef.current = refreshFooterDragVisuals;
9460
- const commitFooterDragRef = (0, import_react9.useRef)(() => {
9965
+ const commitFooterDragRef = (0, import_react10.useRef)(() => {
9461
9966
  });
9462
- const beginFooterDragRef = (0, import_react9.useRef)(() => {
9967
+ const beginFooterDragRef = (0, import_react10.useRef)(() => {
9463
9968
  });
9464
- const beginFooterDrag = (0, import_react9.useCallback)(
9969
+ const beginFooterDrag = (0, import_react10.useCallback)(
9465
9970
  (session) => {
9466
9971
  const rect = session.draggedEl.getBoundingClientRect();
9467
9972
  session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
@@ -9481,7 +9986,7 @@ function OhhwellsBridge() {
9481
9986
  [refreshFooterDragVisuals]
9482
9987
  );
9483
9988
  beginFooterDragRef.current = beginFooterDrag;
9484
- const commitFooterDrag = (0, import_react9.useCallback)(
9989
+ const commitFooterDrag = (0, import_react10.useCallback)(
9485
9990
  (clientX, clientY) => {
9486
9991
  const session = footerDragRef.current;
9487
9992
  if (!session) {
@@ -9585,7 +10090,7 @@ function OhhwellsBridge() {
9585
10090
  [clearFooterDragVisuals, resolveHrefKeyElement, resyncSelectedNavigationItem]
9586
10091
  );
9587
10092
  commitFooterDragRef.current = commitFooterDrag;
9588
- const startFooterLinkDrag = (0, import_react9.useCallback)(
10093
+ const startFooterLinkDrag = (0, import_react10.useCallback)(
9589
10094
  (anchor, clientX, clientY, wasSelected) => {
9590
10095
  const hrefKey = anchor.getAttribute("data-ohw-href-key");
9591
10096
  if (!hrefKey || !isFooterHrefKey(hrefKey)) return false;
@@ -9606,7 +10111,7 @@ function OhhwellsBridge() {
9606
10111
  },
9607
10112
  [beginFooterDrag]
9608
10113
  );
9609
- const startFooterColumnDrag = (0, import_react9.useCallback)(
10114
+ const startFooterColumnDrag = (0, import_react10.useCallback)(
9610
10115
  (columnEl, clientX, clientY, wasSelected) => {
9611
10116
  const columns = listFooterColumns();
9612
10117
  const idx = columns.indexOf(columnEl);
@@ -9626,7 +10131,7 @@ function OhhwellsBridge() {
9626
10131
  },
9627
10132
  [beginFooterDrag]
9628
10133
  );
9629
- const handleItemDragStart = (0, import_react9.useCallback)(
10134
+ const handleItemDragStart = (0, import_react10.useCallback)(
9630
10135
  (e) => {
9631
10136
  const selected = selectedElRef.current;
9632
10137
  if (!selected) {
@@ -9646,7 +10151,7 @@ function OhhwellsBridge() {
9646
10151
  },
9647
10152
  [startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag]
9648
10153
  );
9649
- const handleItemDragEnd = (0, import_react9.useCallback)(
10154
+ const handleItemDragEnd = (0, import_react10.useCallback)(
9650
10155
  (e) => {
9651
10156
  if (footerDragRef.current) {
9652
10157
  const x = e?.clientX;
@@ -9672,7 +10177,7 @@ function OhhwellsBridge() {
9672
10177
  },
9673
10178
  [commitFooterDrag, commitNavDrag, navDragRef]
9674
10179
  );
9675
- const handleItemChromePointerDown = (0, import_react9.useCallback)((e) => {
10180
+ const handleItemChromePointerDown = (0, import_react10.useCallback)((e) => {
9676
10181
  if (e.button !== 0) return;
9677
10182
  const selected = selectedElRef.current;
9678
10183
  if (!selected) return;
@@ -9703,7 +10208,7 @@ function OhhwellsBridge() {
9703
10208
  }
9704
10209
  if (armNavPressFromChrome(selected, e.clientX, e.clientY, e.pointerId)) return;
9705
10210
  }, [armNavPressFromChrome]);
9706
- const handleItemChromeClick = (0, import_react9.useCallback)((clientX, clientY) => {
10211
+ const handleItemChromeClick = (0, import_react10.useCallback)((clientX, clientY) => {
9707
10212
  if (suppressNextClickRef.current || Date.now() < suppressClickUntilRef.current) {
9708
10213
  suppressNextClickRef.current = false;
9709
10214
  return;
@@ -9716,7 +10221,7 @@ function OhhwellsBridge() {
9716
10221
  }, []);
9717
10222
  reselectNavigationItemRef.current = reselectNavigationItem;
9718
10223
  commitNavigationTextEditRef.current = commitNavigationTextEdit;
9719
- const select = (0, import_react9.useCallback)((anchor) => {
10224
+ const select = (0, import_react10.useCallback)((anchor) => {
9720
10225
  if (!isNavigationItem(anchor)) return;
9721
10226
  if (activeElRef.current) deactivate();
9722
10227
  selectedElRef.current = anchor;
@@ -9742,10 +10247,10 @@ function OhhwellsBridge() {
9742
10247
  setToolbarShowEditLink(false);
9743
10248
  setActiveCommands(/* @__PURE__ */ new Set());
9744
10249
  }, [deactivate, markSelected]);
9745
- const selectFrame = (0, import_react9.useCallback)((el) => {
10250
+ const selectFrame = (0, import_react10.useCallback)((el) => {
9746
10251
  if (!isNavigationContainer(el)) return;
9747
10252
  if (activeElRef.current) deactivate();
9748
- const isFooterColumn = el.hasAttribute("data-ohw-footer-col") || Boolean(el.closest("footer") && isInferredFooterGroup(el));
10253
+ const isFooterColumn = !isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || Boolean(el.closest("footer") && isInferredFooterGroup(el)));
9749
10254
  selectedElRef.current = el;
9750
10255
  selectedHrefKeyRef.current = null;
9751
10256
  selectedFooterColAttrRef.current = isFooterColumn ? el.getAttribute("data-ohw-footer-col") ?? String(listFooterColumns().indexOf(el)) : null;
@@ -9770,7 +10275,7 @@ function OhhwellsBridge() {
9770
10275
  setToolbarShowEditLink(false);
9771
10276
  setActiveCommands(/* @__PURE__ */ new Set());
9772
10277
  }, [deactivate, markSelected]);
9773
- const activate = (0, import_react9.useCallback)((el, options) => {
10278
+ const activate = (0, import_react10.useCallback)((el, options) => {
9774
10279
  if (activeElRef.current === el) return;
9775
10280
  clearSelectedAttr();
9776
10281
  selectedElRef.current = null;
@@ -9835,7 +10340,7 @@ function OhhwellsBridge() {
9835
10340
  selectRef.current = select;
9836
10341
  selectFrameRef.current = selectFrame;
9837
10342
  deselectRef.current = deselect;
9838
- (0, import_react9.useLayoutEffect)(() => {
10343
+ (0, import_react10.useLayoutEffect)(() => {
9839
10344
  if (!subdomain || isEditMode) {
9840
10345
  setFetchState("done");
9841
10346
  return;
@@ -9845,6 +10350,7 @@ function OhhwellsBridge() {
9845
10350
  for (const [key, val] of Object.entries(content)) {
9846
10351
  if (key === "__ohw_sections") continue;
9847
10352
  if (applyVideoSettingNode(key, val)) continue;
10353
+ if (applyCarouselNode(key, val)) continue;
9848
10354
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
9849
10355
  if (el.dataset.ohwEditable === "image") {
9850
10356
  const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
@@ -9905,7 +10411,7 @@ function OhhwellsBridge() {
9905
10411
  cancelled = true;
9906
10412
  };
9907
10413
  }, [subdomain, isEditMode]);
9908
- (0, import_react9.useEffect)(() => {
10414
+ (0, import_react10.useEffect)(() => {
9909
10415
  if (!subdomain || isEditMode) return;
9910
10416
  let debounceTimer = null;
9911
10417
  let observer = null;
@@ -9918,6 +10424,7 @@ function OhhwellsBridge() {
9918
10424
  for (const [key, val] of Object.entries(content)) {
9919
10425
  if (key === "__ohw_sections") continue;
9920
10426
  if (applyVideoSettingNode(key, val)) continue;
10427
+ if (applyCarouselNode(key, val)) continue;
9921
10428
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
9922
10429
  if (el.dataset.ohwEditable === "image") {
9923
10430
  const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
@@ -9955,16 +10462,16 @@ function OhhwellsBridge() {
9955
10462
  if (debounceTimer) clearTimeout(debounceTimer);
9956
10463
  };
9957
10464
  }, [subdomain, isEditMode, pathname]);
9958
- (0, import_react9.useLayoutEffect)(() => {
10465
+ (0, import_react10.useLayoutEffect)(() => {
9959
10466
  const el = document.getElementById("ohw-loader");
9960
10467
  if (!el) return;
9961
10468
  const visible = Boolean(subdomain) && fetchState !== "done";
9962
10469
  el.style.display = visible ? "flex" : "none";
9963
10470
  }, [subdomain, fetchState]);
9964
- (0, import_react9.useEffect)(() => {
10471
+ (0, import_react10.useEffect)(() => {
9965
10472
  postToParent2({ type: "ow:navigation", path: pathname });
9966
10473
  }, [pathname, postToParent2]);
9967
- (0, import_react9.useEffect)(() => {
10474
+ (0, import_react10.useEffect)(() => {
9968
10475
  if (!isEditMode) return;
9969
10476
  if (linkPopoverSessionRef.current?.intent === "add-nav") return;
9970
10477
  if (document.querySelector("[data-ohw-section-picker]")) return;
@@ -9972,7 +10479,7 @@ function OhhwellsBridge() {
9972
10479
  deselectRef.current();
9973
10480
  deactivateRef.current();
9974
10481
  }, [pathname, isEditMode]);
9975
- (0, import_react9.useEffect)(() => {
10482
+ (0, import_react10.useEffect)(() => {
9976
10483
  const contentForNav = () => {
9977
10484
  if (isEditMode) return editContentRef.current;
9978
10485
  if (!subdomain) return {};
@@ -10037,7 +10544,7 @@ function OhhwellsBridge() {
10037
10544
  observer?.disconnect();
10038
10545
  };
10039
10546
  }, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
10040
- (0, import_react9.useEffect)(() => {
10547
+ (0, import_react10.useEffect)(() => {
10041
10548
  if (!isEditMode) return;
10042
10549
  const measure = () => {
10043
10550
  const h = document.body.scrollHeight;
@@ -10061,7 +10568,7 @@ function OhhwellsBridge() {
10061
10568
  window.removeEventListener("resize", handleResize);
10062
10569
  };
10063
10570
  }, [pathname, isEditMode, postToParent2]);
10064
- (0, import_react9.useEffect)(() => {
10571
+ (0, import_react10.useEffect)(() => {
10065
10572
  if (!subdomainFromQuery || isEditMode) return;
10066
10573
  const handleClick = (e) => {
10067
10574
  const anchor = e.target.closest("a");
@@ -10077,7 +10584,7 @@ function OhhwellsBridge() {
10077
10584
  document.addEventListener("click", handleClick, true);
10078
10585
  return () => document.removeEventListener("click", handleClick, true);
10079
10586
  }, [subdomainFromQuery, isEditMode, router]);
10080
- (0, import_react9.useEffect)(() => {
10587
+ (0, import_react10.useEffect)(() => {
10081
10588
  if (!isEditMode) {
10082
10589
  editStylesRef.current?.base.remove();
10083
10590
  editStylesRef.current?.forceHover.remove();
@@ -10301,7 +10808,7 @@ function OhhwellsBridge() {
10301
10808
  }
10302
10809
  e.preventDefault();
10303
10810
  e.stopPropagation();
10304
- activateRef.current(editable);
10811
+ activateRef.current(editable, { caretX: e.clientX, caretY: e.clientY });
10305
10812
  return;
10306
10813
  }
10307
10814
  const hrefAnchor = getNavigationItemAnchor(target);
@@ -10328,6 +10835,18 @@ function OhhwellsBridge() {
10328
10835
  selectFrameRef.current(footerColClick);
10329
10836
  return;
10330
10837
  }
10838
+ const footerLinksToSelect = resolveFooterLinksContainerSelectionTarget(
10839
+ target,
10840
+ e.clientX,
10841
+ e.clientY,
10842
+ isPointOverNavItem
10843
+ );
10844
+ if (footerLinksToSelect) {
10845
+ e.preventDefault();
10846
+ e.stopPropagation();
10847
+ selectFrameRef.current(footerLinksToSelect);
10848
+ return;
10849
+ }
10331
10850
  const navContainerToSelect = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
10332
10851
  if (navContainerToSelect) {
10333
10852
  e.preventDefault();
@@ -10386,8 +10905,8 @@ function OhhwellsBridge() {
10386
10905
  return;
10387
10906
  }
10388
10907
  const navLabel = getNavigationLabelEditable(target);
10389
- if (!navLabel) return;
10390
- const { editable } = navLabel;
10908
+ const editable = navLabel?.editable ?? target.closest('[data-ohw-editable="text"], [data-ohw-editable="plain"]');
10909
+ if (!editable || isMediaEditable(editable) || editable.dataset.ohwEditable === "link") return;
10391
10910
  e.preventDefault();
10392
10911
  e.stopPropagation();
10393
10912
  if (activeElRef.current !== editable) {
@@ -10408,16 +10927,38 @@ function OhhwellsBridge() {
10408
10927
  setHoveredNavContainerRect(null);
10409
10928
  return;
10410
10929
  }
10411
- if (toolbarVariantRef.current !== "select-frame") {
10412
- const navContainer = target.closest("[data-ohw-nav-container]");
10413
- if (navContainer && !getNavigationItemAnchor(target)) {
10414
- hoveredNavContainerRef.current = navContainer;
10415
- setHoveredNavContainerRect(navContainer.getBoundingClientRect());
10416
- hoveredItemElRef.current = null;
10417
- setHoveredItemRect(null);
10418
- return;
10930
+ {
10931
+ const selected2 = selectedElRef.current;
10932
+ const selectedIsFooterColumn = Boolean(selected2) && !isFooterLinksContainer(selected2) && (selected2.hasAttribute("data-ohw-footer-col") || selected2.hasAttribute("data-ohw-footer-column") || Boolean(selected2.closest("footer") && isInferredFooterGroup(selected2)));
10933
+ const allowNavContainerHover = toolbarVariantRef.current !== "select-frame";
10934
+ const allowFooterLinksHover = toolbarVariantRef.current !== "select-frame" || selectedIsFooterColumn;
10935
+ if (allowNavContainerHover) {
10936
+ const navContainer = target.closest("[data-ohw-nav-container]");
10937
+ if (navContainer && !getNavigationItemAnchor(target)) {
10938
+ hoveredNavContainerRef.current = navContainer;
10939
+ setHoveredNavContainerRect(navContainer.getBoundingClientRect());
10940
+ hoveredItemElRef.current = null;
10941
+ setHoveredItemRect(null);
10942
+ return;
10943
+ }
10419
10944
  }
10420
- if (!target.closest("[data-ohw-nav-container]")) {
10945
+ if (allowFooterLinksHover) {
10946
+ const navContainer = target.closest("[data-ohw-nav-container]");
10947
+ if (!navContainer) {
10948
+ const footerLinks = target.closest("[data-ohw-footer-links], .rb-footer-links") ?? null;
10949
+ if (footerLinks && selected2 !== footerLinks && !getNavigationItemAnchor(target) && !target.closest("[data-ohw-footer-col], [data-ohw-footer-column]")) {
10950
+ hoveredNavContainerRef.current = footerLinks;
10951
+ setHoveredNavContainerRect(footerLinks.getBoundingClientRect());
10952
+ hoveredItemElRef.current = null;
10953
+ setHoveredItemRect(null);
10954
+ return;
10955
+ }
10956
+ if (!footerLinks) {
10957
+ hoveredNavContainerRef.current = null;
10958
+ setHoveredNavContainerRect(null);
10959
+ }
10960
+ }
10961
+ } else if (toolbarVariantRef.current === "select-frame") {
10421
10962
  hoveredNavContainerRef.current = null;
10422
10963
  setHoveredNavContainerRect(null);
10423
10964
  }
@@ -10459,9 +11000,9 @@ function OhhwellsBridge() {
10459
11000
  };
10460
11001
  const handleMouseOut = (e) => {
10461
11002
  const target = e.target;
10462
- if (target.closest("[data-ohw-nav-container], [data-ohw-footer-col], [data-ohw-footer-column]")) {
11003
+ if (target.closest("[data-ohw-nav-container], [data-ohw-footer-col], [data-ohw-footer-column], [data-ohw-footer-links], .rb-footer-links")) {
10463
11004
  const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
10464
- if (related2?.closest("[data-ohw-nav-container], [data-ohw-footer-col], [data-ohw-footer-column], [data-ohw-navbar-container-chrome], [data-ohw-navbar-add-button]")) {
11005
+ if (related2?.closest("[data-ohw-nav-container], [data-ohw-footer-col], [data-ohw-footer-column], [data-ohw-footer-links], .rb-footer-links, [data-ohw-navbar-container-chrome], [data-ohw-navbar-add-button], [data-ohw-footer-container-chrome], [data-ohw-footer-add-button]")) {
10465
11006
  return;
10466
11007
  }
10467
11008
  hoveredNavContainerRef.current = null;
@@ -10556,6 +11097,15 @@ function OhhwellsBridge() {
10556
11097
  if (track) track.setAttribute("data-ohw-hover-paused", "");
10557
11098
  };
10558
11099
  const clearImageHover = () => setMediaHover(null);
11100
+ const dismissImageHover = () => {
11101
+ if (hoveredImageRef.current) {
11102
+ hoveredImageRef.current = null;
11103
+ hoveredImageHasTextOverlapRef.current = false;
11104
+ resumeAnimTracks();
11105
+ postToParentRef.current({ type: "ow:image-unhover" });
11106
+ }
11107
+ clearImageHover();
11108
+ };
10559
11109
  const findImageAtPoint = (clientX, clientY, fromParentViewport) => {
10560
11110
  const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
10561
11111
  const images = Array.from(document.querySelectorAll(MEDIA_SELECTOR));
@@ -10599,16 +11149,13 @@ function OhhwellsBridge() {
10599
11149
  }
10600
11150
  return smallest;
10601
11151
  };
10602
- const dismissImageHover = () => {
10603
- if (hoveredImageRef.current) {
10604
- hoveredImageRef.current = null;
10605
- hoveredImageHasTextOverlapRef.current = false;
10606
- resumeAnimTracks();
10607
- postToParentRef.current({ type: "ow:image-unhover" });
10608
- }
10609
- };
10610
11152
  const probeNavigationHoverAt = (x, y) => {
10611
- if (toolbarVariantRef.current === "select-frame") {
11153
+ const selected = selectedElRef.current;
11154
+ const selectedIsFooterColumn = Boolean(selected) && !isFooterLinksContainer(selected) && (selected.hasAttribute("data-ohw-footer-col") || selected.hasAttribute("data-ohw-footer-column") || Boolean(selected.closest("footer") && isInferredFooterGroup(selected)));
11155
+ const selectedIsFooterLinks = Boolean(selected && isFooterLinksContainer(selected));
11156
+ const allowNavContainerHover = toolbarVariantRef.current !== "select-frame";
11157
+ const allowFooterLinksHover = (toolbarVariantRef.current !== "select-frame" || selectedIsFooterColumn) && !selectedIsFooterLinks;
11158
+ if (toolbarVariantRef.current === "select-frame" && !allowFooterLinksHover) {
10612
11159
  hoveredNavContainerRef.current = null;
10613
11160
  setHoveredNavContainerRect(null);
10614
11161
  }
@@ -10630,7 +11177,6 @@ function OhhwellsBridge() {
10630
11177
  if (navItemHit) {
10631
11178
  hoveredNavContainerRef.current = null;
10632
11179
  setHoveredNavContainerRect(null);
10633
- const selected = selectedElRef.current;
10634
11180
  if (selected !== navItemHit) {
10635
11181
  clearHrefKeyHover(navItemHit);
10636
11182
  hoveredItemElRef.current = navItemHit;
@@ -10642,7 +11188,7 @@ function OhhwellsBridge() {
10642
11188
  return;
10643
11189
  }
10644
11190
  }
10645
- if (toolbarVariantRef.current !== "select-frame") {
11191
+ if (allowNavContainerHover) {
10646
11192
  for (const container of navContainers) {
10647
11193
  const containerRect = container.getBoundingClientRect();
10648
11194
  const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
@@ -10654,12 +11200,23 @@ function OhhwellsBridge() {
10654
11200
  setHoveredItemRect(null);
10655
11201
  return;
10656
11202
  }
10657
- hoveredNavContainerRef.current = null;
10658
- setHoveredNavContainerRect(null);
10659
- } else {
10660
- hoveredNavContainerRef.current = null;
10661
- setHoveredNavContainerRect(null);
10662
11203
  }
11204
+ if (allowFooterLinksHover) {
11205
+ const footerLinks = getFooterLinksContainer();
11206
+ if (footerLinks) {
11207
+ const containerRect = footerLinks.getBoundingClientRect();
11208
+ const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
11209
+ if (overContainer && !isPointOverNavItem(footerLinks, x, y) && !isPointOverFooterColumn(x, y)) {
11210
+ hoveredNavContainerRef.current = footerLinks;
11211
+ setHoveredNavContainerRect(footerLinks.getBoundingClientRect());
11212
+ hoveredItemElRef.current = null;
11213
+ setHoveredItemRect(null);
11214
+ return;
11215
+ }
11216
+ }
11217
+ }
11218
+ hoveredNavContainerRef.current = null;
11219
+ setHoveredNavContainerRect(null);
10663
11220
  for (const column of footerColumns) {
10664
11221
  const containerRect = column.getBoundingClientRect();
10665
11222
  const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
@@ -10921,6 +11478,7 @@ function OhhwellsBridge() {
10921
11478
  const ZONE = 20;
10922
11479
  for (let i = 0; i < sections.length; i++) {
10923
11480
  const a = sections[i];
11481
+ if (a.dataset.ohwSection === "footer") continue;
10924
11482
  const b = sections[i + 1] ?? null;
10925
11483
  const boundaryY = a.getBoundingClientRect().bottom;
10926
11484
  if (Math.abs(y - boundaryY) <= ZONE) {
@@ -11142,6 +11700,7 @@ function OhhwellsBridge() {
11142
11700
  continue;
11143
11701
  }
11144
11702
  if (applyVideoSettingNode(key, val)) continue;
11703
+ if (applyCarouselNode(key, val)) continue;
11145
11704
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
11146
11705
  if (el.dataset.ohwEditable === "image") {
11147
11706
  const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
@@ -11166,6 +11725,7 @@ function OhhwellsBridge() {
11166
11725
  }
11167
11726
  editContentRef.current = { ...editContentRef.current, ...content };
11168
11727
  reconcileNavbarItemsFromContent(editContentRef.current);
11728
+ reconcileFooterOrderFromContent(editContentRef.current);
11169
11729
  syncNavigationDragCursorAttrs();
11170
11730
  enforceLinkHrefs();
11171
11731
  postToParentRef.current({ type: "ow:hydrate-done" });
@@ -11220,6 +11780,11 @@ function OhhwellsBridge() {
11220
11780
  }
11221
11781
  if (selectedElRef.current) {
11222
11782
  if (toolbarVariantRef.current === "select-frame") {
11783
+ const parent2 = getNavigationSelectionParent(selectedElRef.current);
11784
+ if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
11785
+ selectFrameRef.current(parent2);
11786
+ return;
11787
+ }
11223
11788
  deselectRef.current();
11224
11789
  return;
11225
11790
  }
@@ -11235,13 +11800,10 @@ function OhhwellsBridge() {
11235
11800
  const handleKeyDown = (e) => {
11236
11801
  if (e.key === "Escape" && document.querySelector("[data-ohw-section-picker]")) return;
11237
11802
  if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "a" && activeElRef.current) {
11238
- const navAnchor = getNavigationItemAnchor(activeElRef.current);
11239
- if (navAnchor) {
11240
- e.preventDefault();
11241
- selectAllTextInEditable(activeElRef.current);
11242
- refreshActiveCommandsRef.current();
11243
- return;
11244
- }
11803
+ e.preventDefault();
11804
+ selectAllTextInEditable(activeElRef.current);
11805
+ refreshActiveCommandsRef.current();
11806
+ return;
11245
11807
  }
11246
11808
  if (e.key === "Escape" && linkPopoverOpenRef.current) {
11247
11809
  setLinkPopoverRef.current(null);
@@ -11249,6 +11811,12 @@ function OhhwellsBridge() {
11249
11811
  }
11250
11812
  if (e.key === "Escape" && selectedElRef.current && !activeElRef.current) {
11251
11813
  if (toolbarVariantRef.current === "select-frame") {
11814
+ const parent2 = getNavigationSelectionParent(selectedElRef.current);
11815
+ if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
11816
+ e.preventDefault();
11817
+ selectFrameRef.current(parent2);
11818
+ return;
11819
+ }
11252
11820
  deselectRef.current();
11253
11821
  return;
11254
11822
  }
@@ -11438,6 +12006,7 @@ function OhhwellsBridge() {
11438
12006
  const handleDocMouseLeave = () => {
11439
12007
  hoveredImageRef.current = null;
11440
12008
  setMediaHover(null);
12009
+ setCarouselHover(null);
11441
12010
  document.querySelectorAll("[data-ohw-state-hovered]").forEach((el) => el.removeAttribute("data-ohw-state-hovered"));
11442
12011
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
11443
12012
  activeStateElRef.current = null;
@@ -11477,6 +12046,48 @@ function OhhwellsBridge() {
11477
12046
  if (e.data?.type !== "ow:canvas-height" || typeof e.data.height !== "number") return;
11478
12047
  document.documentElement.style.setProperty("--ohw-canvas-h", `${e.data.height}px`);
11479
12048
  };
12049
+ const handleCarouselChange = (e) => {
12050
+ if (e.data?.type !== "ow:carousel-change") return;
12051
+ const { key, images } = e.data;
12052
+ if (!key || !Array.isArray(images)) return;
12053
+ const text = JSON.stringify(images);
12054
+ applyCarouselValue(key, images);
12055
+ editContentRef.current = { ...editContentRef.current, [key]: text };
12056
+ postToParentRef.current({ type: "ow:change", nodes: [{ key, text }] });
12057
+ setCarouselHover(null);
12058
+ };
12059
+ const findCarouselAtPoint = (clientX, clientY) => {
12060
+ const containers = Array.from(document.querySelectorAll(`[${CAROUSEL_ATTR}]`));
12061
+ for (let i = containers.length - 1; i >= 0; i--) {
12062
+ const r2 = containers[i].getBoundingClientRect();
12063
+ if (clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom) {
12064
+ return containers[i];
12065
+ }
12066
+ }
12067
+ return null;
12068
+ };
12069
+ const isPointOverEditable = (scope, clientX, clientY) => {
12070
+ const editables = scope.querySelectorAll("[data-ohw-editable], [data-ohw-href-key]");
12071
+ for (const el of editables) {
12072
+ const r2 = el.getBoundingClientRect();
12073
+ if (clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom) return true;
12074
+ }
12075
+ return false;
12076
+ };
12077
+ const handleCarouselHover = (e) => {
12078
+ const container = findCarouselAtPoint(e.clientX, e.clientY);
12079
+ const scope = container?.closest("[data-ohw-section]") ?? container?.parentElement ?? null;
12080
+ if (!container || !scope || isPointOverEditable(scope, e.clientX, e.clientY)) {
12081
+ setCarouselHover((prev) => prev ? null : prev);
12082
+ return;
12083
+ }
12084
+ const key = container.getAttribute("data-ohw-key") ?? "";
12085
+ if (!key) return;
12086
+ const r2 = getVisibleRect(container);
12087
+ setCarouselHover(
12088
+ (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 } }
12089
+ );
12090
+ };
11480
12091
  const applyToolbarPos = (rect) => {
11481
12092
  const ps = parentScrollRef.current;
11482
12093
  const measuredW = toolbarElRef.current?.offsetWidth || 330;
@@ -11590,6 +12201,7 @@ function OhhwellsBridge() {
11590
12201
  window.addEventListener("message", handleRemoveSchedulingSection);
11591
12202
  window.addEventListener("message", handleImageUrl);
11592
12203
  window.addEventListener("message", handleImageUploading);
12204
+ window.addEventListener("message", handleCarouselChange);
11593
12205
  window.addEventListener("message", handleCanvasHeight);
11594
12206
  window.addEventListener("message", handleParentScroll);
11595
12207
  window.addEventListener("message", handlePointerSync);
@@ -11607,6 +12219,7 @@ function OhhwellsBridge() {
11607
12219
  document.addEventListener("mouseover", handleMouseOver, true);
11608
12220
  document.addEventListener("mouseout", handleMouseOut, true);
11609
12221
  document.addEventListener("mousemove", handleMouseMove, true);
12222
+ document.addEventListener("mousemove", handleCarouselHover, true);
11610
12223
  document.addEventListener("mouseleave", handleDocMouseLeave);
11611
12224
  document.addEventListener("dragover", handleDragOver, true);
11612
12225
  document.addEventListener("dragleave", handleDragLeave, true);
@@ -11622,6 +12235,7 @@ function OhhwellsBridge() {
11622
12235
  document.removeEventListener("mouseover", handleMouseOver, true);
11623
12236
  document.removeEventListener("mouseout", handleMouseOut, true);
11624
12237
  document.removeEventListener("mousemove", handleMouseMove, true);
12238
+ document.removeEventListener("mousemove", handleCarouselHover, true);
11625
12239
  document.removeEventListener("mouseleave", handleDocMouseLeave);
11626
12240
  document.removeEventListener("dragover", handleDragOver, true);
11627
12241
  document.removeEventListener("dragleave", handleDragLeave, true);
@@ -11637,6 +12251,7 @@ function OhhwellsBridge() {
11637
12251
  window.removeEventListener("message", handleRemoveSchedulingSection);
11638
12252
  window.removeEventListener("message", handleImageUrl);
11639
12253
  window.removeEventListener("message", handleImageUploading);
12254
+ window.removeEventListener("message", handleCarouselChange);
11640
12255
  window.removeEventListener("message", handleCanvasHeight);
11641
12256
  window.removeEventListener("message", handleParentScroll);
11642
12257
  window.removeEventListener("resize", handleViewportResize);
@@ -11651,7 +12266,7 @@ function OhhwellsBridge() {
11651
12266
  if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
11652
12267
  };
11653
12268
  }, [isEditMode, refreshStateRules]);
11654
- (0, import_react9.useEffect)(() => {
12269
+ (0, import_react10.useEffect)(() => {
11655
12270
  if (!isEditMode) return;
11656
12271
  const THRESHOLD = 10;
11657
12272
  const resolveWasSelected = (el) => {
@@ -11805,7 +12420,7 @@ function OhhwellsBridge() {
11805
12420
  unlockFooterDragInteraction();
11806
12421
  };
11807
12422
  }, [isEditMode]);
11808
- (0, import_react9.useEffect)(() => {
12423
+ (0, import_react10.useEffect)(() => {
11809
12424
  const handler = (e) => {
11810
12425
  if (e.data?.type !== "ow:request-schedule-config") return;
11811
12426
  const insertAfterVal = e.data.insertAfter;
@@ -11821,7 +12436,7 @@ function OhhwellsBridge() {
11821
12436
  window.addEventListener("message", handler);
11822
12437
  return () => window.removeEventListener("message", handler);
11823
12438
  }, [processConfigRequest]);
11824
- (0, import_react9.useEffect)(() => {
12439
+ (0, import_react10.useEffect)(() => {
11825
12440
  if (!isEditMode) return;
11826
12441
  document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
11827
12442
  el.removeAttribute("data-ohw-active-state");
@@ -11856,13 +12471,13 @@ function OhhwellsBridge() {
11856
12471
  clearTimeout(timer);
11857
12472
  };
11858
12473
  }, [pathname, isEditMode, refreshStateRules, postToParent2]);
11859
- (0, import_react9.useEffect)(() => {
12474
+ (0, import_react10.useEffect)(() => {
11860
12475
  scrollToHashSectionWhenReady();
11861
12476
  const onHashChange = () => scrollToHashSectionWhenReady();
11862
12477
  window.addEventListener("hashchange", onHashChange);
11863
12478
  return () => window.removeEventListener("hashchange", onHashChange);
11864
12479
  }, [pathname]);
11865
- const handleCommand = (0, import_react9.useCallback)((cmd) => {
12480
+ const handleCommand = (0, import_react10.useCallback)((cmd) => {
11866
12481
  const el = activeElRef.current;
11867
12482
  const selBefore = window.getSelection();
11868
12483
  let savedOffsets = null;
@@ -11898,7 +12513,7 @@ function OhhwellsBridge() {
11898
12513
  if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
11899
12514
  refreshActiveCommandsRef.current();
11900
12515
  }, []);
11901
- const handleStateChange = (0, import_react9.useCallback)((state) => {
12516
+ const handleStateChange = (0, import_react10.useCallback)((state) => {
11902
12517
  if (!activeStateElRef.current) return;
11903
12518
  const el = activeStateElRef.current;
11904
12519
  if (state === "Default") {
@@ -11911,11 +12526,11 @@ function OhhwellsBridge() {
11911
12526
  }
11912
12527
  setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
11913
12528
  }, [deactivate]);
11914
- const closeLinkPopover = (0, import_react9.useCallback)(() => {
12529
+ const closeLinkPopover = (0, import_react10.useCallback)(() => {
11915
12530
  addNavAfterAnchorRef.current = null;
11916
12531
  setLinkPopover(null);
11917
12532
  }, []);
11918
- const openLinkPopoverForActive = (0, import_react9.useCallback)(() => {
12533
+ const openLinkPopoverForActive = (0, import_react10.useCallback)(() => {
11919
12534
  const hrefCtx = getHrefKeyFromElement(activeElRef.current);
11920
12535
  if (!hrefCtx) return;
11921
12536
  bumpLinkPopoverGrace();
@@ -11926,7 +12541,7 @@ function OhhwellsBridge() {
11926
12541
  });
11927
12542
  deactivate();
11928
12543
  }, [deactivate]);
11929
- const openLinkPopoverForSelected = (0, import_react9.useCallback)(() => {
12544
+ const openLinkPopoverForSelected = (0, import_react10.useCallback)(() => {
11930
12545
  const anchor = selectedElRef.current;
11931
12546
  if (!anchor) return;
11932
12547
  const key = anchor.getAttribute("data-ohw-href-key");
@@ -11939,7 +12554,7 @@ function OhhwellsBridge() {
11939
12554
  });
11940
12555
  deselect();
11941
12556
  }, [deselect]);
11942
- const handleLinkPopoverSubmit = (0, import_react9.useCallback)(
12557
+ const handleLinkPopoverSubmit = (0, import_react10.useCallback)(
11943
12558
  (target) => {
11944
12559
  const session = linkPopoverSessionRef.current;
11945
12560
  if (!session) return;
@@ -11998,13 +12613,19 @@ function OhhwellsBridge() {
11998
12613
  const showEditLink = toolbarShowEditLink;
11999
12614
  const currentSections = sectionsByPath[pathname] ?? [];
12000
12615
  linkPopoverOpenRef.current = linkPopover !== null;
12001
- const handleMediaReplace = (0, import_react9.useCallback)(
12616
+ const handleMediaReplace = (0, import_react10.useCallback)(
12002
12617
  (key) => {
12003
12618
  postToParent2({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
12004
12619
  },
12005
12620
  [postToParent2, mediaHover?.elementType]
12006
12621
  );
12007
- const handleMediaFadeOutComplete = (0, import_react9.useCallback)((key) => {
12622
+ const handleEditCarousel = (0, import_react10.useCallback)(
12623
+ (key) => {
12624
+ postToParent2({ type: "ow:carousel-open", key, images: readCarouselValue(key) });
12625
+ },
12626
+ [postToParent2]
12627
+ );
12628
+ const handleMediaFadeOutComplete = (0, import_react10.useCallback)((key) => {
12008
12629
  setUploadingRects((prev) => {
12009
12630
  if (!(key in prev)) return prev;
12010
12631
  const next = { ...prev };
@@ -12012,7 +12633,7 @@ function OhhwellsBridge() {
12012
12633
  return next;
12013
12634
  });
12014
12635
  }, []);
12015
- const handleVideoSettingsChange = (0, import_react9.useCallback)(
12636
+ const handleVideoSettingsChange = (0, import_react10.useCallback)(
12016
12637
  (key, settings) => {
12017
12638
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
12018
12639
  const video = getVideoEl(el);
@@ -12035,9 +12656,9 @@ function OhhwellsBridge() {
12035
12656
  [postToParent2]
12036
12657
  );
12037
12658
  return bridgeRoot ? (0, import_react_dom3.createPortal)(
12038
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
12039
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
12040
- Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12659
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
12660
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
12661
+ Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
12041
12662
  MediaOverlay,
12042
12663
  {
12043
12664
  hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
@@ -12048,7 +12669,7 @@ function OhhwellsBridge() {
12048
12669
  },
12049
12670
  `uploading-${key}`
12050
12671
  )),
12051
- mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12672
+ mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
12052
12673
  MediaOverlay,
12053
12674
  {
12054
12675
  hover: mediaHover,
@@ -12057,10 +12678,11 @@ function OhhwellsBridge() {
12057
12678
  onVideoSettingsChange: handleVideoSettingsChange
12058
12679
  }
12059
12680
  ),
12060
- siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
12061
- siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
12062
- isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
12063
- isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12681
+ carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
12682
+ siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
12683
+ siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
12684
+ isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
12685
+ isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
12064
12686
  "div",
12065
12687
  {
12066
12688
  className: "pointer-events-none fixed z-2147483646",
@@ -12070,7 +12692,7 @@ function OhhwellsBridge() {
12070
12692
  width: slot.width,
12071
12693
  height: slot.height
12072
12694
  },
12073
- children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12695
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
12074
12696
  DropIndicator,
12075
12697
  {
12076
12698
  direction: slot.direction,
@@ -12081,7 +12703,7 @@ function OhhwellsBridge() {
12081
12703
  },
12082
12704
  `footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
12083
12705
  )),
12084
- isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12706
+ isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
12085
12707
  "div",
12086
12708
  {
12087
12709
  className: "pointer-events-none fixed z-2147483646",
@@ -12091,7 +12713,7 @@ function OhhwellsBridge() {
12091
12713
  width: slot.width,
12092
12714
  height: slot.height
12093
12715
  },
12094
- children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12716
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
12095
12717
  DropIndicator,
12096
12718
  {
12097
12719
  direction: slot.direction,
@@ -12102,10 +12724,11 @@ function OhhwellsBridge() {
12102
12724
  },
12103
12725
  `nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
12104
12726
  )),
12105
- hoveredNavContainerRect && toolbarVariant !== "select-frame" && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
12106
- hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
12107
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
12108
- toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12727
+ hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
12728
+ hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
12729
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
12730
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(FooterContainerChrome, { rect: toolbarRect, onAdd: handleAddFooterColumn }),
12731
+ toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
12109
12732
  ItemInteractionLayer,
12110
12733
  {
12111
12734
  rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
@@ -12119,7 +12742,7 @@ function OhhwellsBridge() {
12119
12742
  onItemPointerDown: handleItemChromePointerDown,
12120
12743
  onItemClick: handleItemChromeClick,
12121
12744
  itemDragSurface: !isFooterFrameSelection,
12122
- toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12745
+ toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
12123
12746
  ItemActionToolbar,
12124
12747
  {
12125
12748
  onEditLink: openLinkPopoverForSelected,
@@ -12132,8 +12755,8 @@ function OhhwellsBridge() {
12132
12755
  ) : void 0
12133
12756
  }
12134
12757
  ),
12135
- toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
12136
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12758
+ toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
12759
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
12137
12760
  EditGlowChrome,
12138
12761
  {
12139
12762
  rect: toolbarRect,
@@ -12143,7 +12766,7 @@ function OhhwellsBridge() {
12143
12766
  hideHandle: isItemDragging
12144
12767
  }
12145
12768
  ),
12146
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12769
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
12147
12770
  FloatingToolbar,
12148
12771
  {
12149
12772
  rect: toolbarRect,
@@ -12156,7 +12779,7 @@ function OhhwellsBridge() {
12156
12779
  }
12157
12780
  )
12158
12781
  ] }),
12159
- maxBadge && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
12782
+ maxBadge && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
12160
12783
  "div",
12161
12784
  {
12162
12785
  "data-ohw-max-badge": "",
@@ -12182,7 +12805,7 @@ function OhhwellsBridge() {
12182
12805
  ]
12183
12806
  }
12184
12807
  ),
12185
- toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12808
+ toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
12186
12809
  StateToggle,
12187
12810
  {
12188
12811
  rect: toggleState.rect,
@@ -12191,15 +12814,15 @@ function OhhwellsBridge() {
12191
12814
  onStateChange: handleStateChange
12192
12815
  }
12193
12816
  ),
12194
- sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
12817
+ sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
12195
12818
  "div",
12196
12819
  {
12197
12820
  "data-ohw-section-insert-line": "",
12198
12821
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
12199
12822
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
12200
12823
  children: [
12201
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
12202
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12824
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
12825
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
12203
12826
  Badge,
12204
12827
  {
12205
12828
  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",
@@ -12216,11 +12839,11 @@ function OhhwellsBridge() {
12216
12839
  children: "Add Section"
12217
12840
  }
12218
12841
  ),
12219
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
12842
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
12220
12843
  ]
12221
12844
  }
12222
12845
  ),
12223
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12846
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
12224
12847
  LinkPopover,
12225
12848
  {
12226
12849
  panelRef: linkPopoverPanelRef,
@@ -12269,6 +12892,7 @@ function OhhwellsBridge() {
12269
12892
  isValidUrl,
12270
12893
  parseTarget,
12271
12894
  toggleVariants,
12895
+ useOhwCarousel,
12272
12896
  validateUrlInput
12273
12897
  });
12274
12898
  //# sourceMappingURL=index.cjs.map