@ohhwells/bridge 0.1.48 → 0.1.49-next.114

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
@@ -36,6 +36,12 @@ __export(index_exports, {
36
36
  CustomToolbarDivider: () => CustomToolbarDivider,
37
37
  DragHandle: () => DragHandle,
38
38
  DropIndicator: () => DropIndicator,
39
+ DropdownMenu: () => DropdownMenu,
40
+ DropdownMenuContent: () => DropdownMenuContent,
41
+ DropdownMenuGroup: () => DropdownMenuGroup,
42
+ DropdownMenuItem: () => DropdownMenuItem,
43
+ DropdownMenuSeparator: () => DropdownMenuSeparator,
44
+ DropdownMenuTrigger: () => DropdownMenuTrigger,
39
45
  ItemActionToolbar: () => ItemActionToolbar,
40
46
  ItemInteractionLayer: () => ItemInteractionLayer,
41
47
  LinkEditorPanel: () => LinkEditorPanel,
@@ -63,7 +69,7 @@ __export(index_exports, {
63
69
  module.exports = __toCommonJS(index_exports);
64
70
 
65
71
  // src/OhhwellsBridge.tsx
66
- var import_react10 = __toESM(require("react"), 1);
72
+ var import_react11 = __toESM(require("react"), 1);
67
73
  var import_client = require("react-dom/client");
68
74
  var import_react_dom2 = require("react-dom");
69
75
 
@@ -116,6 +122,7 @@ var import_react3 = require("react");
116
122
  var import_react2 = require("react");
117
123
  var import_radix_ui = require("radix-ui");
118
124
  var import_jsx_runtime = require("react/jsx-runtime");
125
+ var isValidEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
119
126
  function Spinner() {
120
127
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
121
128
  "svg",
@@ -149,12 +156,17 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
149
156
  const [error, setError] = (0, import_react2.useState)(null);
150
157
  const isBook = title === "Confirm your spot";
151
158
  const handleSubmit = async () => {
152
- if (!email.trim()) return;
159
+ const trimmed = email.trim();
160
+ if (!trimmed) return;
161
+ if (!isValidEmail(trimmed)) {
162
+ setError("Please enter a valid email address.");
163
+ return;
164
+ }
153
165
  setLoading(true);
154
166
  setError(null);
155
167
  try {
156
- await onSubmit(email.trim());
157
- setSubmittedEmail(email.trim());
168
+ await onSubmit(trimmed);
169
+ setSubmittedEmail(trimmed);
158
170
  setSuccess(true);
159
171
  } catch (e) {
160
172
  setError(e instanceof Error ? e.message : "Something went wrong. Please try again.");
@@ -229,7 +241,10 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
229
241
  {
230
242
  type: "email",
231
243
  value: email,
232
- onChange: (e) => setEmail(e.target.value),
244
+ onChange: (e) => {
245
+ setEmail(e.target.value);
246
+ if (error) setError(null);
247
+ },
233
248
  onKeyDown: handleKeyDown,
234
249
  placeholder: "hello@gmail.com",
235
250
  autoFocus: true,
@@ -286,12 +301,20 @@ function formatClassTime(cls) {
286
301
  const em = endTotal % 60;
287
302
  return `${h}:${cls.startTime.minutes}-${eh}:${String(em).padStart(2, "0")}`;
288
303
  }
304
+ function formatBookingLabel(cls) {
305
+ const price = cls.price;
306
+ const isFree = price === null || price === void 0 || `${price}` === "" || `${price}` === "0";
307
+ return isFree ? "Book for free" : `Book for ${cls.currency ?? ""} ${price}`.trim();
308
+ }
289
309
  function getBookingsOnDate(cls, date) {
290
310
  if (!cls.bookings?.length) return 0;
291
- const ds = date.toISOString().split("T")[0];
311
+ const target = new Date(date);
312
+ target.setHours(0, 0, 0, 0);
292
313
  return cls.bookings.filter((b) => {
293
314
  try {
294
- return new Date(b.classDate).toISOString().split("T")[0] === ds;
315
+ const bookingDate = new Date(b.classDate);
316
+ bookingDate.setHours(0, 0, 0, 0);
317
+ return bookingDate.getTime() === target.getTime();
295
318
  } catch {
296
319
  return false;
297
320
  }
@@ -556,7 +579,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
556
579
  }
557
580
  )
558
581
  ] }),
559
- /* @__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: [
582
+ 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: [
560
583
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
561
584
  available,
562
585
  "/",
@@ -568,9 +591,17 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
568
591
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-1 flex-col gap-2 min-w-0 sm:contents", children: [
569
592
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex-1 flex flex-col gap-2 min-w-0", children: [
570
593
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-base font-bold text-(--color-dark,#200C02) block truncate", children: cls.name }),
571
- 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 })
594
+ 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 }),
595
+ cls.description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
596
+ "span",
597
+ {
598
+ className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block",
599
+ style: { wordBreak: "break-word" },
600
+ children: cls.description
601
+ }
602
+ )
572
603
  ] }),
573
- /* @__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: [
604
+ 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: [
574
605
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
575
606
  available,
576
607
  "/",
@@ -595,7 +626,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
595
626
  if (!cls.id) return;
596
627
  onOpenModal?.(isFull ? "waitlist" : "book", cls.id, selectedDate);
597
628
  },
598
- children: isFull ? "Join Waitlist" : "Book Now"
629
+ children: isFull ? "Join Waitlist" : formatBookingLabel(cls)
599
630
  }
600
631
  )
601
632
  ] })
@@ -637,6 +668,17 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
637
668
  const [isHovered, setIsHovered] = (0, import_react3.useState)(false);
638
669
  const [modalState, setModalState] = (0, import_react3.useState)(null);
639
670
  const switchScheduleIdRef = (0, import_react3.useRef)(null);
671
+ const liveScheduleIdRef = (0, import_react3.useRef)(null);
672
+ const refetchLiveSchedule = (0, import_react3.useCallback)(async () => {
673
+ const id = liveScheduleIdRef.current;
674
+ if (!id) return;
675
+ try {
676
+ const res = await fetch(`${API_URL}/api/schedule/id/${id}`);
677
+ const data = await res.json();
678
+ if (data?.id) setSchedule(data);
679
+ } catch {
680
+ }
681
+ }, []);
640
682
  const dates = (0, import_react3.useMemo)(() => {
641
683
  const today = /* @__PURE__ */ new Date();
642
684
  today.setHours(0, 0, 0, 0);
@@ -656,6 +698,18 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
656
698
  }
657
699
  }
658
700
  }, [schedule, dates]);
701
+ (0, import_react3.useEffect)(() => {
702
+ if (typeof window === "undefined") return;
703
+ const onVisible = () => {
704
+ if (!document.hidden) void refetchLiveSchedule();
705
+ };
706
+ window.addEventListener("focus", refetchLiveSchedule);
707
+ document.addEventListener("visibilitychange", onVisible);
708
+ return () => {
709
+ window.removeEventListener("focus", refetchLiveSchedule);
710
+ document.removeEventListener("visibilitychange", onVisible);
711
+ };
712
+ }, [refetchLiveSchedule]);
659
713
  (0, import_react3.useEffect)(() => {
660
714
  if (typeof window === "undefined") return;
661
715
  const isInEditor = window.self !== window.top;
@@ -717,7 +771,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
717
771
  setLoading(false);
718
772
  return;
719
773
  }
720
- ;
774
+ liveScheduleIdRef.current = effectiveId;
721
775
  (async () => {
722
776
  try {
723
777
  const res = await fetch(`${API_URL}/api/schedule/id/${effectiveId}`);
@@ -774,18 +828,14 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
774
828
  const data = await res.json().catch(() => ({}));
775
829
  throw new Error(data?.message ?? "Something went wrong. Please try again.");
776
830
  }
831
+ await refetchLiveSchedule();
777
832
  };
778
833
  const handleReplaceSchedule = () => {
779
834
  setIsHovered(false);
780
- if (schedule) {
781
- window.parent.postMessage({
782
- type: "ow:schedule-connected",
783
- schedule: { id: schedule.id, name: schedule.name },
784
- insertAfter
785
- }, "*");
786
- } else {
787
- window.parent.postMessage({ type: "ow:scheduling-not-connected", insertAfter }, "*");
788
- }
835
+ window.parent.postMessage(
836
+ { type: "ow:scheduling-not-connected", insertAfter, currentScheduleId: schedule?.id },
837
+ "*"
838
+ );
789
839
  };
790
840
  if (!inEditor && !loading && !schedule) return null;
791
841
  const sectionId = `scheduling-${insertAfter}`;
@@ -828,7 +878,19 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
828
878
  ),
829
879
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "max-w-[1280px] mx-auto flex flex-col items-center gap-16", children: [
830
880
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-col items-center gap-4", children: [
831
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { className: "font-display text-4xl sm:text-5xl font-bold text-center m-0 text-(--color-dark,#200C02)", children: schedule?.name ?? "Book an appointment" }),
881
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
882
+ "h2",
883
+ {
884
+ className: "font-display text-center m-0 text-(--color-dark,#200C02)",
885
+ style: {
886
+ fontSize: "var(--fs-section-h2, clamp(40px, 4.4vw, 64px))",
887
+ fontWeight: "var(--font-weight-heading, 400)",
888
+ lineHeight: 1.05,
889
+ letterSpacing: "-0.02em"
890
+ },
891
+ children: schedule?.name ?? "Book an appointment"
892
+ }
893
+ ),
832
894
  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 })
833
895
  ] }),
834
896
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "w-full flex flex-col items-end gap-3", children: [
@@ -4344,22 +4406,116 @@ var CustomToolbarButton = React4.forwardRef(
4344
4406
  CustomToolbarButton.displayName = "CustomToolbarButton";
4345
4407
 
4346
4408
  // src/ui/item-action-toolbar.tsx
4409
+ var import_react4 = require("react");
4347
4410
  var import_lucide_react2 = require("lucide-react");
4348
4411
 
4349
- // src/ui/tooltip.tsx
4412
+ // src/ui/dropdown-menu.tsx
4350
4413
  var import_radix_ui3 = require("radix-ui");
4351
4414
  var import_jsx_runtime7 = require("react/jsx-runtime");
4415
+ function DropdownMenu({ ...props }) {
4416
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui3.DropdownMenu.Root, { "data-slot": "dropdown-menu", ...props });
4417
+ }
4418
+ function DropdownMenuTrigger({
4419
+ ...props
4420
+ }) {
4421
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui3.DropdownMenu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
4422
+ }
4423
+ function DropdownMenuGroup({
4424
+ className,
4425
+ ...props
4426
+ }) {
4427
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4428
+ import_radix_ui3.DropdownMenu.Group,
4429
+ {
4430
+ "data-slot": "dropdown-menu-group",
4431
+ className: cn("flex w-full flex-col items-start p-1", className),
4432
+ ...props
4433
+ }
4434
+ );
4435
+ }
4436
+ function DropdownMenuContent({
4437
+ className,
4438
+ sideOffset = 6,
4439
+ ...props
4440
+ }) {
4441
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui3.DropdownMenu.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4442
+ import_radix_ui3.DropdownMenu.Content,
4443
+ {
4444
+ "data-slot": "dropdown-menu-content",
4445
+ "data-ohw-more-menu": "",
4446
+ sideOffset,
4447
+ className: cn(
4448
+ "z-[2147483647] flex w-56 min-w-32 flex-col items-center overflow-hidden rounded-[6px] border border-border bg-popover p-0 text-popover-foreground outline-none",
4449
+ "shadow-[0px_4px_6px_0px_rgba(0,0,0,0.1),0px_2px_4px_0px_rgba(0,0,0,0.1)]",
4450
+ "origin-[var(--radix-dropdown-menu-content-transform-origin)]",
4451
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
4452
+ "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
4453
+ className
4454
+ ),
4455
+ ...props
4456
+ }
4457
+ ) });
4458
+ }
4459
+ function DropdownMenuItem({
4460
+ className,
4461
+ inset,
4462
+ variant = "default",
4463
+ ...props
4464
+ }) {
4465
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4466
+ import_radix_ui3.DropdownMenu.Item,
4467
+ {
4468
+ "data-slot": "dropdown-menu-item",
4469
+ "data-inset": inset ? "" : void 0,
4470
+ "data-variant": variant,
4471
+ className: cn(
4472
+ "relative flex w-full min-w-32 cursor-pointer select-none items-center gap-2 rounded-[calc(var(--radius,0.5rem)-4px)] py-1.5 pl-8 pr-2 text-sm leading-5 outline-none",
4473
+ "text-popover-foreground",
4474
+ "focus:bg-muted data-[highlighted]:bg-muted",
4475
+ "data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
4476
+ "[&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
4477
+ "[&_svg:not([class*=absolute])]:relative",
4478
+ // Leading icon — Figma absolute left-2 / top-1/2
4479
+ "[&>svg:first-child]:absolute [&>svg:first-child]:left-2 [&>svg:first-child]:top-1/2 [&>svg:first-child]:-translate-y-1/2",
4480
+ "data-[variant=destructive]:text-destructive",
4481
+ "data-[variant=destructive]:focus:bg-bg-destructive-10 data-[variant=destructive]:focus:text-destructive",
4482
+ "data-[variant=destructive]:data-[highlighted]:bg-bg-destructive-10 data-[variant=destructive]:data-[highlighted]:text-destructive",
4483
+ "data-[variant=destructive]:[&_svg]:text-destructive",
4484
+ inset && "pl-8",
4485
+ className
4486
+ ),
4487
+ ...props
4488
+ }
4489
+ );
4490
+ }
4491
+ function DropdownMenuSeparator({
4492
+ className,
4493
+ ...props
4494
+ }) {
4495
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4496
+ import_radix_ui3.DropdownMenu.Separator,
4497
+ {
4498
+ "data-slot": "dropdown-menu-separator",
4499
+ className: cn("h-px w-full bg-border", className),
4500
+ ...props
4501
+ }
4502
+ );
4503
+ }
4504
+
4505
+ // src/ui/tooltip.tsx
4506
+ var import_radix_ui4 = require("radix-ui");
4507
+ var import_jsx_runtime8 = require("react/jsx-runtime");
4352
4508
  function TooltipProvider({
4353
4509
  delayDuration = 0,
4354
4510
  ...props
4355
4511
  }) {
4356
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui3.Tooltip.Provider, { "data-slot": "tooltip-provider", delayDuration, ...props });
4512
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_radix_ui4.Tooltip.Provider, { "data-slot": "tooltip-provider", delayDuration, ...props });
4357
4513
  }
4358
4514
  function Tooltip({ ...props }) {
4359
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui3.Tooltip.Root, { "data-slot": "tooltip", ...props });
4515
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_radix_ui4.Tooltip.Root, { "data-slot": "tooltip", ...props });
4360
4516
  }
4361
4517
  function TooltipTrigger({ ...props }) {
4362
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui3.Tooltip.Trigger, { "data-slot": "tooltip-trigger", ...props });
4518
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_radix_ui4.Tooltip.Trigger, { "data-slot": "tooltip-trigger", ...props });
4363
4519
  }
4364
4520
  var arrowClassBySide = {
4365
4521
  top: "before:bottom-0 before:left-1/2 before:-translate-x-1/2 before:translate-y-1/2",
@@ -4376,8 +4532,8 @@ function TooltipContent({
4376
4532
  ...props
4377
4533
  }) {
4378
4534
  const resolvedSide = side ?? "bottom";
4379
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui3.Tooltip.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4380
- import_radix_ui3.Tooltip.Content,
4535
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_radix_ui4.Tooltip.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4536
+ import_radix_ui4.Tooltip.Content,
4381
4537
  {
4382
4538
  "data-slot": "tooltip-content",
4383
4539
  side,
@@ -4399,7 +4555,7 @@ function TooltipContent({
4399
4555
  }
4400
4556
 
4401
4557
  // src/ui/item-action-toolbar.tsx
4402
- var import_jsx_runtime8 = require("react/jsx-runtime");
4558
+ var import_jsx_runtime9 = require("react/jsx-runtime");
4403
4559
  function ToolbarActionTooltip({
4404
4560
  label,
4405
4561
  side = "bottom",
@@ -4407,25 +4563,31 @@ function ToolbarActionTooltip({
4407
4563
  buttonProps,
4408
4564
  children
4409
4565
  }) {
4410
- const button = /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CustomToolbarButton, { type: "button", "aria-label": label, disabled, ...buttonProps, children });
4411
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Tooltip, { children: [
4412
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "inline-flex", children: button }) : button }),
4413
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TooltipContent, { side, sideOffset: 9, children: label })
4566
+ const button = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CustomToolbarButton, { type: "button", "aria-label": label, disabled, ...buttonProps, children });
4567
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Tooltip, { children: [
4568
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "inline-flex", children: button }) : button }),
4569
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TooltipContent, { side, sideOffset: 9, children: label })
4414
4570
  ] });
4415
4571
  }
4416
4572
  function ItemActionToolbar({
4417
4573
  onEditLink,
4418
4574
  onAddItem,
4419
- onMore,
4575
+ onSelectParent,
4576
+ onDuplicate,
4577
+ onDelete,
4420
4578
  editLinkDisabled = false,
4421
4579
  addItemDisabled = true,
4422
- moreDisabled = true,
4580
+ moreDisabled = false,
4581
+ selectParentDisabled = false,
4582
+ duplicateDisabled = false,
4583
+ deleteDisabled = false,
4423
4584
  showAddItem = true,
4424
4585
  showMore = true,
4425
4586
  tooltipSide = "bottom"
4426
4587
  }) {
4427
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(CustomToolbar, { children: [
4428
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4588
+ const [moreOpen, setMoreOpen] = (0, import_react4.useState)(false);
4589
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(CustomToolbar, { children: [
4590
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4429
4591
  ToolbarActionTooltip,
4430
4592
  {
4431
4593
  label: "Edit link",
@@ -4443,10 +4605,10 @@ function ItemActionToolbar({
4443
4605
  e.stopPropagation();
4444
4606
  }
4445
4607
  },
4446
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react2.Link, { className: "size-4 shrink-0", "aria-hidden": true })
4608
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_lucide_react2.Link, { className: "size-4 shrink-0", "aria-hidden": true })
4447
4609
  }
4448
4610
  ),
4449
- showAddItem ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4611
+ showAddItem ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4450
4612
  ToolbarActionTooltip,
4451
4613
  {
4452
4614
  label: "Add item",
@@ -4460,32 +4622,84 @@ function ItemActionToolbar({
4460
4622
  onAddItem?.();
4461
4623
  }
4462
4624
  },
4463
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react2.Plus, { className: "size-4 shrink-0", "aria-hidden": true })
4625
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_lucide_react2.Plus, { className: "size-4 shrink-0", "aria-hidden": true })
4464
4626
  }
4465
4627
  ) : null,
4466
- showMore ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4467
- ToolbarActionTooltip,
4468
- {
4469
- label: "More",
4470
- side: tooltipSide,
4471
- disabled: moreDisabled,
4472
- buttonProps: {
4628
+ showMore ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(DropdownMenu, { open: moreOpen, onOpenChange: setMoreOpen, children: [
4629
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Tooltip, { open: moreOpen ? false : void 0, children: [
4630
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(DropdownMenuTrigger, { asChild: true, disabled: moreDisabled, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4631
+ CustomToolbarButton,
4632
+ {
4633
+ type: "button",
4634
+ "aria-label": "More",
4635
+ disabled: moreDisabled,
4636
+ onMouseDown: (e) => {
4637
+ e.preventDefault();
4638
+ e.stopPropagation();
4639
+ },
4640
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_lucide_react2.MoreHorizontal, { className: "size-4 shrink-0", "aria-hidden": true })
4641
+ }
4642
+ ) }) }),
4643
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(TooltipContent, { side: tooltipSide, sideOffset: 9, children: "More" })
4644
+ ] }),
4645
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
4646
+ DropdownMenuContent,
4647
+ {
4648
+ align: "end",
4649
+ side: "bottom",
4650
+ onCloseAutoFocus: (e) => e.preventDefault(),
4473
4651
  onMouseDown: (e) => {
4474
- if (moreDisabled) return;
4475
4652
  e.preventDefault();
4476
4653
  e.stopPropagation();
4477
- onMore?.();
4478
- }
4479
- },
4480
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react2.MoreHorizontal, { className: "size-4 shrink-0", "aria-hidden": true })
4481
- }
4482
- ) : null
4654
+ },
4655
+ children: [
4656
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(DropdownMenuGroup, { children: [
4657
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
4658
+ DropdownMenuItem,
4659
+ {
4660
+ disabled: selectParentDisabled,
4661
+ onSelect: () => onSelectParent?.(),
4662
+ children: [
4663
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_lucide_react2.CornerLeftUp, { size: 12, "aria-hidden": true }),
4664
+ "Select parent"
4665
+ ]
4666
+ }
4667
+ ),
4668
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
4669
+ DropdownMenuItem,
4670
+ {
4671
+ disabled: duplicateDisabled,
4672
+ onSelect: () => onDuplicate?.(),
4673
+ children: [
4674
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_lucide_react2.Copy, { size: 12, "aria-hidden": true }),
4675
+ "Duplicate"
4676
+ ]
4677
+ }
4678
+ )
4679
+ ] }),
4680
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(DropdownMenuSeparator, {}),
4681
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(DropdownMenuGroup, { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
4682
+ DropdownMenuItem,
4683
+ {
4684
+ variant: "destructive",
4685
+ disabled: deleteDisabled,
4686
+ onSelect: () => onDelete?.(),
4687
+ children: [
4688
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_lucide_react2.Trash2, { size: 15, "aria-hidden": true }),
4689
+ "Delete"
4690
+ ]
4691
+ }
4692
+ ) })
4693
+ ]
4694
+ }
4695
+ )
4696
+ ] }) : null
4483
4697
  ] }) });
4484
4698
  }
4485
4699
 
4486
4700
  // src/ui/item-interaction-layer.tsx
4487
4701
  var React5 = __toESM(require("react"), 1);
4488
- var import_jsx_runtime9 = require("react/jsx-runtime");
4702
+ var import_jsx_runtime10 = require("react/jsx-runtime");
4489
4703
  var PRIMARY = "var(--ohw-primary, #0885FE)";
4490
4704
  var FOCUS_RING = `0 0 0 4px color-mix(in srgb, ${PRIMARY} 12%, transparent)`;
4491
4705
  var DRAG_SHADOW = "0px 4px 6px -1px rgba(0, 0, 0, 0.1), 0px 2px 4px -2px rgba(0, 0, 0, 0.1)";
@@ -4567,7 +4781,7 @@ function ClampedToolbarSlot({
4567
4781
  window.removeEventListener("resize", clamp);
4568
4782
  };
4569
4783
  }, [placement, children]);
4570
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4784
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4571
4785
  "div",
4572
4786
  {
4573
4787
  ref: slotRef,
@@ -4607,7 +4821,7 @@ function ItemInteractionLayer({
4607
4821
  const showToolbar = isActive && toolbar;
4608
4822
  const showDragHandle = (isActive || isDragging) && showHandle;
4609
4823
  const itemDragEnabled = itemDragSurface && isActive && showHandle && !isDragging && !dragDisabled;
4610
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
4824
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
4611
4825
  "div",
4612
4826
  {
4613
4827
  ref: elRef,
@@ -4623,7 +4837,7 @@ function ItemInteractionLayer({
4623
4837
  zIndex: getChromeZIndex(state)
4624
4838
  },
4625
4839
  children: [
4626
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4840
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4627
4841
  "div",
4628
4842
  {
4629
4843
  "aria-hidden": true,
@@ -4631,7 +4845,7 @@ function ItemInteractionLayer({
4631
4845
  style: getChromeStyle(state)
4632
4846
  }
4633
4847
  ),
4634
- itemDragEnabled && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4848
+ itemDragEnabled && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4635
4849
  "div",
4636
4850
  {
4637
4851
  "data-ohw-item-drag-surface": "",
@@ -4647,14 +4861,14 @@ function ItemInteractionLayer({
4647
4861
  }
4648
4862
  }
4649
4863
  ),
4650
- showDragHandle && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4864
+ showDragHandle && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4651
4865
  "div",
4652
4866
  {
4653
4867
  "data-ohw-drag-handle-container": "",
4654
4868
  className: "pointer-events-auto absolute left-0 top-1/2 z-10 -translate-x-[calc(100%+7px)] -translate-y-1/2",
4655
4869
  style: isDragging ? { opacity: 0 } : void 0,
4656
4870
  "aria-hidden": isDragging || void 0,
4657
- children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4871
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4658
4872
  DragHandle,
4659
4873
  {
4660
4874
  draggable: !dragDisabled,
@@ -4684,8 +4898,8 @@ function ItemInteractionLayer({
4684
4898
  )
4685
4899
  }
4686
4900
  ),
4687
- showToolbar && state === "active-top" && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ClampedToolbarSlot, { placement: "top", children: toolbar }),
4688
- showToolbar && state === "active-bottom" && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ClampedToolbarSlot, { placement: "bottom", children: toolbar })
4901
+ showToolbar && state === "active-top" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ClampedToolbarSlot, { placement: "top", children: toolbar }),
4902
+ showToolbar && state === "active-bottom" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ClampedToolbarSlot, { placement: "bottom", children: toolbar })
4689
4903
  ]
4690
4904
  }
4691
4905
  );
@@ -4697,8 +4911,8 @@ var import_lucide_react3 = require("lucide-react");
4697
4911
 
4698
4912
  // src/ui/button.tsx
4699
4913
  var React6 = __toESM(require("react"), 1);
4700
- var import_radix_ui4 = require("radix-ui");
4701
- var import_jsx_runtime10 = require("react/jsx-runtime");
4914
+ var import_radix_ui5 = require("radix-ui");
4915
+ var import_jsx_runtime11 = require("react/jsx-runtime");
4702
4916
  var buttonVariants = cva(
4703
4917
  "inline-flex items-center justify-center gap-1 whitespace-nowrap rounded-md text-sm font-medium transition-colors outline-none disabled:pointer-events-none disabled:opacity-50 min-w-[80px] px-3 py-2",
4704
4918
  {
@@ -4721,8 +4935,8 @@ var buttonVariants = cva(
4721
4935
  );
4722
4936
  var Button = React6.forwardRef(
4723
4937
  ({ className, variant, size, asChild = false, ...props }, ref) => {
4724
- const Comp = asChild ? import_radix_ui4.Slot.Root : "button";
4725
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4938
+ const Comp = asChild ? import_radix_ui5.Slot.Root : "button";
4939
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
4726
4940
  Comp,
4727
4941
  {
4728
4942
  ref,
@@ -4736,7 +4950,7 @@ var Button = React6.forwardRef(
4736
4950
  Button.displayName = "Button";
4737
4951
 
4738
4952
  // src/ui/MediaOverlay.tsx
4739
- var import_jsx_runtime11 = require("react/jsx-runtime");
4953
+ var import_jsx_runtime12 = require("react/jsx-runtime");
4740
4954
  var MEDIA_UPLOAD_FADE_MS = 300;
4741
4955
  var VIDEO_SETTINGS_BAR_INSET = 8;
4742
4956
  var OVERLAY_BUTTON_STYLE = {
@@ -4794,7 +5008,7 @@ function MediaOverlay({
4794
5008
  return () => anim.cancel();
4795
5009
  }, [isUploading, fadingOut, onFadeOutComplete, hover.key]);
4796
5010
  if (isUploading) {
4797
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
5011
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4798
5012
  "div",
4799
5013
  {
4800
5014
  ref: skeletonRef,
@@ -4803,11 +5017,11 @@ function MediaOverlay({
4803
5017
  "data-ohw-media-skeleton": "",
4804
5018
  "aria-hidden": true,
4805
5019
  style: { ...box, pointerEvents: "none" },
4806
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("style", { children: SKELETON_CSS })
5020
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("style", { children: SKELETON_CSS })
4807
5021
  }
4808
5022
  );
4809
5023
  }
4810
- const settingsBar = isVideo && !hover.isDragOver ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
5024
+ const settingsBar = isVideo && !hover.isDragOver ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
4811
5025
  "div",
4812
5026
  {
4813
5027
  "data-ohw-bridge": "",
@@ -4823,7 +5037,7 @@ function MediaOverlay({
4823
5037
  },
4824
5038
  onClick: (e) => e.stopPropagation(),
4825
5039
  children: [
4826
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
5040
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4827
5041
  Button,
4828
5042
  {
4829
5043
  "data-ohw-media-overlay": "",
@@ -4838,10 +5052,10 @@ function MediaOverlay({
4838
5052
  e.stopPropagation();
4839
5053
  onVideoSettingsChange?.(hover.key, { autoplay: !autoplay });
4840
5054
  },
4841
- children: autoplay ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.Pause, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.Play, { size: 14 })
5055
+ children: autoplay ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react3.Pause, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react3.Play, { size: 14 })
4842
5056
  }
4843
5057
  ),
4844
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
5058
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4845
5059
  Button,
4846
5060
  {
4847
5061
  "data-ohw-media-overlay": "",
@@ -4856,15 +5070,15 @@ function MediaOverlay({
4856
5070
  e.stopPropagation();
4857
5071
  onVideoSettingsChange?.(hover.key, { muted: !muted });
4858
5072
  },
4859
- children: muted ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.VolumeX, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.Volume2, { size: 14 })
5073
+ children: muted ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react3.VolumeX, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react3.Volume2, { size: 14 })
4860
5074
  }
4861
5075
  )
4862
5076
  ]
4863
5077
  }
4864
5078
  ) : null;
4865
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
5079
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
4866
5080
  settingsBar,
4867
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
5081
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4868
5082
  "div",
4869
5083
  {
4870
5084
  "data-ohw-bridge": "",
@@ -4881,21 +5095,25 @@ function MediaOverlay({
4881
5095
  background: "color-mix(in srgb, var(--color-primary) 20%, transparent)"
4882
5096
  },
4883
5097
  onClick: () => onReplace(hover.key),
4884
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
5098
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
4885
5099
  Button,
4886
5100
  {
4887
5101
  "data-ohw-media-overlay": "",
4888
5102
  variant: "outline",
4889
5103
  size: "sm",
4890
5104
  className: "gap-1.5 cursor-pointer hover:bg-background",
4891
- style: OVERLAY_BUTTON_STYLE,
5105
+ style: {
5106
+ ...OVERLAY_BUTTON_STYLE,
5107
+ // Don't let Replace steal clicks when text (e.g. nav) sits on top of this media.
5108
+ pointerEvents: hover.hasTextOverlap ? "none" : "auto"
5109
+ },
4892
5110
  onMouseDown: (e) => e.preventDefault(),
4893
5111
  onClick: (e) => {
4894
5112
  e.stopPropagation();
4895
5113
  onReplace(hover.key);
4896
5114
  },
4897
5115
  children: [
4898
- isVideo ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.Film, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.ImageIcon, { size: 14 }),
5116
+ isVideo ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react3.Film, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react3.ImageIcon, { size: 14 }),
4899
5117
  isVideo ? "Replace video" : "Replace image"
4900
5118
  ]
4901
5119
  }
@@ -4907,7 +5125,7 @@ function MediaOverlay({
4907
5125
 
4908
5126
  // src/ui/CarouselOverlay.tsx
4909
5127
  var import_lucide_react4 = require("lucide-react");
4910
- var import_jsx_runtime12 = require("react/jsx-runtime");
5128
+ var import_jsx_runtime13 = require("react/jsx-runtime");
4911
5129
  var OVERLAY_BUTTON_STYLE2 = {
4912
5130
  pointerEvents: "auto",
4913
5131
  fontFamily: "Inter, sans-serif",
@@ -4919,7 +5137,7 @@ function CarouselOverlay({
4919
5137
  onEdit
4920
5138
  }) {
4921
5139
  const { rect } = hover;
4922
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5140
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4923
5141
  "div",
4924
5142
  {
4925
5143
  "data-ohw-bridge": "",
@@ -4937,7 +5155,7 @@ function CarouselOverlay({
4937
5155
  background: "color-mix(in srgb, var(--color-primary) 20%, transparent)"
4938
5156
  },
4939
5157
  onClick: () => onEdit(hover.key),
4940
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
5158
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
4941
5159
  Button,
4942
5160
  {
4943
5161
  "data-ohw-carousel-overlay": "",
@@ -4951,7 +5169,7 @@ function CarouselOverlay({
4951
5169
  onEdit(hover.key);
4952
5170
  },
4953
5171
  children: [
4954
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react4.GalleryHorizontal, { size: 14 }),
5172
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react4.GalleryHorizontal, { size: 14 }),
4955
5173
  "Edit gallery"
4956
5174
  ]
4957
5175
  }
@@ -5240,29 +5458,29 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
5240
5458
  }
5241
5459
 
5242
5460
  // src/ui/link-modal/LinkPopover.tsx
5243
- var import_react7 = require("react");
5461
+ var import_react8 = require("react");
5244
5462
 
5245
5463
  // src/ui/dialog.tsx
5246
5464
  var React8 = __toESM(require("react"), 1);
5247
- var import_radix_ui5 = require("radix-ui");
5465
+ var import_radix_ui6 = require("radix-ui");
5248
5466
  var import_lucide_react5 = require("lucide-react");
5249
- var import_jsx_runtime13 = require("react/jsx-runtime");
5467
+ var import_jsx_runtime14 = require("react/jsx-runtime");
5250
5468
  function Dialog2({
5251
5469
  ...props
5252
5470
  }) {
5253
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_radix_ui5.Dialog.Root, { "data-slot": "dialog", ...props });
5471
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_radix_ui6.Dialog.Root, { "data-slot": "dialog", ...props });
5254
5472
  }
5255
5473
  function DialogPortal({
5256
5474
  ...props
5257
5475
  }) {
5258
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_radix_ui5.Dialog.Portal, { ...props });
5476
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_radix_ui6.Dialog.Portal, { ...props });
5259
5477
  }
5260
5478
  function DialogOverlay({
5261
5479
  className,
5262
5480
  ...props
5263
5481
  }) {
5264
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5265
- import_radix_ui5.Dialog.Overlay,
5482
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5483
+ import_radix_ui6.Dialog.Overlay,
5266
5484
  {
5267
5485
  "data-slot": "dialog-overlay",
5268
5486
  "data-ohw-link-modal-root": "",
@@ -5274,10 +5492,10 @@ function DialogOverlay({
5274
5492
  var DialogContent = React8.forwardRef(
5275
5493
  ({ className, children, showCloseButton = true, container, ...props }, ref) => {
5276
5494
  const positionMode = container ? "absolute" : "fixed";
5277
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(DialogPortal, { container: container ?? void 0, children: [
5278
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
5279
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
5280
- import_radix_ui5.Dialog.Content,
5495
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(DialogPortal, { container: container ?? void 0, children: [
5496
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
5497
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
5498
+ import_radix_ui6.Dialog.Content,
5281
5499
  {
5282
5500
  ref,
5283
5501
  "data-slot": "dialog-content",
@@ -5292,13 +5510,13 @@ var DialogContent = React8.forwardRef(
5292
5510
  ...props,
5293
5511
  children: [
5294
5512
  children,
5295
- showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5296
- import_radix_ui5.Dialog.Close,
5513
+ showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5514
+ import_radix_ui6.Dialog.Close,
5297
5515
  {
5298
5516
  type: "button",
5299
5517
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
5300
5518
  "aria-label": "Close",
5301
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react5.X, { size: 16, "aria-hidden": true })
5519
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react5.X, { size: 16, "aria-hidden": true })
5302
5520
  }
5303
5521
  ) : null
5304
5522
  ]
@@ -5307,18 +5525,18 @@ var DialogContent = React8.forwardRef(
5307
5525
  ] });
5308
5526
  }
5309
5527
  );
5310
- DialogContent.displayName = import_radix_ui5.Dialog.Content.displayName;
5528
+ DialogContent.displayName = import_radix_ui6.Dialog.Content.displayName;
5311
5529
  function DialogHeader({
5312
5530
  className,
5313
5531
  ...props
5314
5532
  }) {
5315
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
5533
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
5316
5534
  }
5317
5535
  function DialogFooter({
5318
5536
  className,
5319
5537
  ...props
5320
5538
  }) {
5321
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5539
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5322
5540
  "div",
5323
5541
  {
5324
5542
  className: cn("flex items-center justify-end gap-2", className),
@@ -5326,8 +5544,8 @@ function DialogFooter({
5326
5544
  }
5327
5545
  );
5328
5546
  }
5329
- var DialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5330
- import_radix_ui5.Dialog.Title,
5547
+ var DialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5548
+ import_radix_ui6.Dialog.Title,
5331
5549
  {
5332
5550
  ref,
5333
5551
  className: cn(
@@ -5337,36 +5555,36 @@ var DialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE
5337
5555
  ...props
5338
5556
  }
5339
5557
  ));
5340
- DialogTitle.displayName = import_radix_ui5.Dialog.Title.displayName;
5341
- var DialogDescription = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5342
- import_radix_ui5.Dialog.Description,
5558
+ DialogTitle.displayName = import_radix_ui6.Dialog.Title.displayName;
5559
+ var DialogDescription = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5560
+ import_radix_ui6.Dialog.Description,
5343
5561
  {
5344
5562
  ref,
5345
5563
  className: cn("text-sm text-muted-foreground", className),
5346
5564
  ...props
5347
5565
  }
5348
5566
  ));
5349
- DialogDescription.displayName = import_radix_ui5.Dialog.Description.displayName;
5350
- var DialogClose = import_radix_ui5.Dialog.Close;
5567
+ DialogDescription.displayName = import_radix_ui6.Dialog.Description.displayName;
5568
+ var DialogClose = import_radix_ui6.Dialog.Close;
5351
5569
 
5352
5570
  // src/ui/link-modal/LinkEditorPanel.tsx
5353
5571
  var import_lucide_react9 = require("lucide-react");
5354
5572
 
5355
5573
  // src/ui/link-modal/DestinationBreadcrumb.tsx
5356
5574
  var import_lucide_react6 = require("lucide-react");
5357
- var import_jsx_runtime14 = require("react/jsx-runtime");
5575
+ var import_jsx_runtime15 = require("react/jsx-runtime");
5358
5576
  function DestinationBreadcrumb({
5359
5577
  pageTitle,
5360
5578
  sectionLabel
5361
5579
  }) {
5362
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex w-full flex-col gap-2", children: [
5363
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-sm font-medium! text-foreground m-0", children: "Destination" }),
5364
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-3", children: [
5365
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-2", children: [
5366
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react6.File, { size: 16, className: "shrink-0 text-foreground", "aria-hidden": true }),
5367
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "text-sm font-medium leading-none text-foreground!", children: pageTitle })
5580
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex w-full flex-col gap-2", children: [
5581
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "text-sm font-medium! text-foreground m-0", children: "Destination" }),
5582
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-center gap-3", children: [
5583
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-center gap-2", children: [
5584
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react6.File, { size: 16, className: "shrink-0 text-foreground", "aria-hidden": true }),
5585
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "text-sm font-medium leading-none text-foreground!", children: pageTitle })
5368
5586
  ] }),
5369
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5587
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5370
5588
  import_lucide_react6.ArrowRight,
5371
5589
  {
5372
5590
  size: 16,
@@ -5374,8 +5592,8 @@ function DestinationBreadcrumb({
5374
5592
  "aria-hidden": true
5375
5593
  }
5376
5594
  ),
5377
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
5378
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5595
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
5596
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5379
5597
  import_lucide_react6.GalleryVertical,
5380
5598
  {
5381
5599
  size: 16,
@@ -5383,7 +5601,7 @@ function DestinationBreadcrumb({
5383
5601
  "aria-hidden": true
5384
5602
  }
5385
5603
  ),
5386
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
5604
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
5387
5605
  ] })
5388
5606
  ] })
5389
5607
  ] });
@@ -5391,22 +5609,22 @@ function DestinationBreadcrumb({
5391
5609
 
5392
5610
  // src/ui/link-modal/SectionTreeItem.tsx
5393
5611
  var import_lucide_react7 = require("lucide-react");
5394
- var import_jsx_runtime15 = require("react/jsx-runtime");
5612
+ var import_jsx_runtime16 = require("react/jsx-runtime");
5395
5613
  function SectionTreeItem({
5396
5614
  section,
5397
5615
  onSelect,
5398
5616
  selected
5399
5617
  }) {
5400
5618
  const interactive = Boolean(onSelect);
5401
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex h-9 w-full items-end pl-3", children: [
5402
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5619
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex h-9 w-full items-end pl-3", children: [
5620
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5403
5621
  "div",
5404
5622
  {
5405
5623
  className: "mr-[-1px] h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
5406
5624
  "aria-hidden": true
5407
5625
  }
5408
5626
  ),
5409
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5627
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
5410
5628
  "div",
5411
5629
  {
5412
5630
  role: interactive ? "button" : void 0,
@@ -5424,7 +5642,7 @@ function SectionTreeItem({
5424
5642
  interactive && selected && "border-primary"
5425
5643
  ),
5426
5644
  children: [
5427
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5645
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5428
5646
  import_lucide_react7.GalleryVertical,
5429
5647
  {
5430
5648
  size: 16,
@@ -5432,7 +5650,7 @@ function SectionTreeItem({
5432
5650
  "aria-hidden": true
5433
5651
  }
5434
5652
  ),
5435
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
5653
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
5436
5654
  ]
5437
5655
  }
5438
5656
  )
@@ -5440,14 +5658,14 @@ function SectionTreeItem({
5440
5658
  }
5441
5659
 
5442
5660
  // src/ui/link-modal/UrlOrPageInput.tsx
5443
- var import_react4 = require("react");
5661
+ var import_react5 = require("react");
5444
5662
 
5445
5663
  // src/ui/input.tsx
5446
5664
  var React9 = __toESM(require("react"), 1);
5447
- var import_jsx_runtime16 = require("react/jsx-runtime");
5665
+ var import_jsx_runtime17 = require("react/jsx-runtime");
5448
5666
  var Input = React9.forwardRef(
5449
5667
  ({ className, type, ...props }, ref) => {
5450
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5668
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5451
5669
  "input",
5452
5670
  {
5453
5671
  type,
@@ -5465,11 +5683,11 @@ var Input = React9.forwardRef(
5465
5683
  Input.displayName = "Input";
5466
5684
 
5467
5685
  // src/ui/label.tsx
5468
- var import_radix_ui6 = require("radix-ui");
5469
- var import_jsx_runtime17 = require("react/jsx-runtime");
5686
+ var import_radix_ui7 = require("radix-ui");
5687
+ var import_jsx_runtime18 = require("react/jsx-runtime");
5470
5688
  function Label({ className, ...props }) {
5471
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5472
- import_radix_ui6.Label.Root,
5689
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5690
+ import_radix_ui7.Label.Root,
5473
5691
  {
5474
5692
  "data-slot": "label",
5475
5693
  className: cn("text-sm font-medium leading-5 text-foreground", className),
@@ -5480,11 +5698,11 @@ function Label({ className, ...props }) {
5480
5698
 
5481
5699
  // src/ui/link-modal/UrlOrPageInput.tsx
5482
5700
  var import_lucide_react8 = require("lucide-react");
5483
- var import_jsx_runtime18 = require("react/jsx-runtime");
5701
+ var import_jsx_runtime19 = require("react/jsx-runtime");
5484
5702
  function FieldChevron({
5485
5703
  onClick
5486
5704
  }) {
5487
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5705
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5488
5706
  "button",
5489
5707
  {
5490
5708
  type: "button",
@@ -5492,7 +5710,7 @@ function FieldChevron({
5492
5710
  onClick,
5493
5711
  "aria-label": "Open page list",
5494
5712
  tabIndex: -1,
5495
- children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.ChevronDown, { size: 16 })
5713
+ children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react8.ChevronDown, { size: 16 })
5496
5714
  }
5497
5715
  );
5498
5716
  }
@@ -5508,11 +5726,11 @@ function UrlOrPageInput({
5508
5726
  readOnly = false,
5509
5727
  urlError
5510
5728
  }) {
5511
- const inputId = (0, import_react4.useId)();
5512
- const inputRef = (0, import_react4.useRef)(null);
5513
- const rootRef = (0, import_react4.useRef)(null);
5514
- const [isFocused, setIsFocused] = (0, import_react4.useState)(false);
5515
- (0, import_react4.useEffect)(() => {
5729
+ const inputId = (0, import_react5.useId)();
5730
+ const inputRef = (0, import_react5.useRef)(null);
5731
+ const rootRef = (0, import_react5.useRef)(null);
5732
+ const [isFocused, setIsFocused] = (0, import_react5.useState)(false);
5733
+ (0, import_react5.useEffect)(() => {
5516
5734
  if (!dropdownOpen) return;
5517
5735
  const isOutside = (e) => {
5518
5736
  const root = rootRef.current;
@@ -5553,11 +5771,11 @@ function UrlOrPageInput({
5553
5771
  "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]",
5554
5772
  urlError ? "border-destructive shadow-[0_0_0_1px_var(--ohw-destructive)]" : isFocused ? "border-primary shadow-[0_0_0_1px_var(--ohw-primary)]" : "border-input"
5555
5773
  );
5556
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex w-full flex-col gap-2 p-0", children: [
5557
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
5558
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { ref: rootRef, className: "relative w-full", children: [
5559
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
5560
- selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5774
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex w-full flex-col gap-2 p-0", children: [
5775
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
5776
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { ref: rootRef, className: "relative w-full", children: [
5777
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
5778
+ selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5561
5779
  import_lucide_react8.File,
5562
5780
  {
5563
5781
  size: 16,
@@ -5565,7 +5783,7 @@ function UrlOrPageInput({
5565
5783
  "aria-hidden": true
5566
5784
  }
5567
5785
  ) }) : null,
5568
- 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)(
5786
+ readOnly ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm leading-5 text-foreground", children: selectedPage?.title ?? value }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5569
5787
  Input,
5570
5788
  {
5571
5789
  ref: inputRef,
@@ -5591,7 +5809,7 @@ function UrlOrPageInput({
5591
5809
  )
5592
5810
  }
5593
5811
  ),
5594
- selectedPage && !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5812
+ selectedPage && !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5595
5813
  "button",
5596
5814
  {
5597
5815
  type: "button",
@@ -5599,26 +5817,26 @@ function UrlOrPageInput({
5599
5817
  onMouseDown: clearSelection,
5600
5818
  "aria-label": "Clear selected page",
5601
5819
  tabIndex: -1,
5602
- children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.X, { size: 16, "aria-hidden": true })
5820
+ children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react8.X, { size: 16, "aria-hidden": true })
5603
5821
  }
5604
5822
  ) : null,
5605
- !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(FieldChevron, { onClick: toggleDropdown }) : null
5823
+ !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(FieldChevron, { onClick: toggleDropdown }) : null
5606
5824
  ] }),
5607
- dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5825
+ dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5608
5826
  "div",
5609
5827
  {
5610
5828
  "data-ohw-link-page-dropdown": "",
5611
5829
  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",
5612
5830
  onMouseDown: (e) => e.preventDefault(),
5613
- children: filteredPages.map((page) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
5831
+ children: filteredPages.map((page) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
5614
5832
  "button",
5615
5833
  {
5616
5834
  type: "button",
5617
5835
  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",
5618
5836
  onClick: () => onPageSelect(page),
5619
5837
  children: [
5620
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.File, { size: 16, className: "shrink-0", "aria-hidden": true }),
5621
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "truncate", children: page.title })
5838
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react8.File, { size: 16, className: "shrink-0", "aria-hidden": true }),
5839
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "truncate", children: page.title })
5622
5840
  ]
5623
5841
  },
5624
5842
  page.path
@@ -5626,34 +5844,34 @@ function UrlOrPageInput({
5626
5844
  }
5627
5845
  ) : null
5628
5846
  ] }),
5629
- urlError ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
5847
+ urlError ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
5630
5848
  ] });
5631
5849
  }
5632
5850
 
5633
5851
  // src/ui/link-modal/LinkEditorPanel.tsx
5634
- var import_jsx_runtime19 = require("react/jsx-runtime");
5852
+ var import_jsx_runtime20 = require("react/jsx-runtime");
5635
5853
  function LinkEditorPanel({ state, onClose }) {
5636
5854
  const isCancel = state.secondaryLabel === "Cancel" || state.secondaryLabel === "Back to sections";
5637
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
5638
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DialogClose, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5855
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
5856
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DialogClose, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5639
5857
  "button",
5640
5858
  {
5641
5859
  type: "button",
5642
5860
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50 h-7",
5643
5861
  "aria-label": "Close",
5644
5862
  onClick: onClose,
5645
- children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react9.X, { size: 16, "aria-hidden": true })
5863
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.X, { size: 16, "aria-hidden": true })
5646
5864
  }
5647
5865
  ) }),
5648
- /* @__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 }) }),
5649
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
5650
- state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5866
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DialogHeader, { className: "w-full gap-1.5 p-6 pr-12", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DialogTitle, { className: "m-0 w-full break-words", children: state.title }) }),
5867
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
5868
+ state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5651
5869
  DestinationBreadcrumb,
5652
5870
  {
5653
5871
  pageTitle: state.selectedPage.title,
5654
5872
  sectionLabel: state.selectedSection.label
5655
5873
  }
5656
- ) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5874
+ ) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5657
5875
  UrlOrPageInput,
5658
5876
  {
5659
5877
  value: state.searchValue,
@@ -5666,8 +5884,8 @@ function LinkEditorPanel({ state, onClose }) {
5666
5884
  urlError: state.urlError
5667
5885
  }
5668
5886
  ),
5669
- state.showChooseSection ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex flex-col justify-center gap-2", children: [
5670
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5887
+ state.showChooseSection ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex flex-col justify-center gap-2", children: [
5888
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5671
5889
  Button,
5672
5890
  {
5673
5891
  type: "button",
@@ -5678,15 +5896,15 @@ function LinkEditorPanel({ state, onClose }) {
5678
5896
  children: "Choose a section"
5679
5897
  }
5680
5898
  ),
5681
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
5682
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react9.Info, { size: 16, className: "shrink-0", "aria-hidden": true }),
5683
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: "Pick a section this link should scroll to." })
5899
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
5900
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.Info, { size: 16, className: "shrink-0", "aria-hidden": true }),
5901
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { children: "Pick a section this link should scroll to." })
5684
5902
  ] })
5685
5903
  ] }) : null,
5686
- state.showSectionRow && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
5904
+ state.showSectionRow && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
5687
5905
  ] }),
5688
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(DialogFooter, { className: "w-full px-6 pb-6", children: [
5689
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5906
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(DialogFooter, { className: "w-full px-6 pb-6", children: [
5907
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5690
5908
  Button,
5691
5909
  {
5692
5910
  type: "button",
@@ -5701,7 +5919,7 @@ function LinkEditorPanel({ state, onClose }) {
5701
5919
  children: state.secondaryLabel
5702
5920
  }
5703
5921
  ),
5704
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5922
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5705
5923
  Button,
5706
5924
  {
5707
5925
  type: "button",
@@ -5720,11 +5938,11 @@ function LinkEditorPanel({ state, onClose }) {
5720
5938
  }
5721
5939
 
5722
5940
  // src/ui/link-modal/SectionPickerOverlay.tsx
5723
- var import_react5 = require("react");
5941
+ var import_react6 = require("react");
5724
5942
  var import_react_dom = require("react-dom");
5725
5943
  var import_lucide_react10 = require("lucide-react");
5726
5944
  var import_navigation = require("next/navigation");
5727
- var import_jsx_runtime20 = require("react/jsx-runtime");
5945
+ var import_jsx_runtime21 = require("react/jsx-runtime");
5728
5946
  var DIM_OVERLAY = "rgba(0, 0, 0, 0.45)";
5729
5947
  function rectsEqual(a, b) {
5730
5948
  if (a.size !== b.size) return false;
@@ -5757,12 +5975,12 @@ function hitTestSectionId(x, y, sectionIds, rects) {
5757
5975
  return null;
5758
5976
  }
5759
5977
  function useSectionRects(sectionIdsKey, enabled) {
5760
- const [rects, setRects] = (0, import_react5.useState)(/* @__PURE__ */ new Map());
5761
- const sectionIds = (0, import_react5.useMemo)(
5978
+ const [rects, setRects] = (0, import_react6.useState)(/* @__PURE__ */ new Map());
5979
+ const sectionIds = (0, import_react6.useMemo)(
5762
5980
  () => sectionIdsKey ? sectionIdsKey.split("\0") : [],
5763
5981
  [sectionIdsKey]
5764
5982
  );
5765
- (0, import_react5.useEffect)(() => {
5983
+ (0, import_react6.useEffect)(() => {
5766
5984
  if (!enabled || sectionIds.length === 0) {
5767
5985
  setRects((prev) => prev.size === 0 ? prev : /* @__PURE__ */ new Map());
5768
5986
  return;
@@ -5803,13 +6021,13 @@ function SectionPickerOverlay({
5803
6021
  }) {
5804
6022
  const router = (0, import_navigation.useRouter)();
5805
6023
  const pathname = (0, import_navigation.usePathname)();
5806
- const [selectedId, setSelectedId] = (0, import_react5.useState)(null);
5807
- const [hoveredId, setHoveredId] = (0, import_react5.useState)(null);
5808
- const pointerRef = (0, import_react5.useRef)(null);
5809
- const pointerScreenRef = (0, import_react5.useRef)(null);
5810
- const iframeOffsetTopRef = (0, import_react5.useRef)(null);
5811
- const sectionIdsRef = (0, import_react5.useRef)([]);
5812
- const [chromeClip, setChromeClip] = (0, import_react5.useState)(
6024
+ const [selectedId, setSelectedId] = (0, import_react6.useState)(null);
6025
+ const [hoveredId, setHoveredId] = (0, import_react6.useState)(null);
6026
+ const pointerRef = (0, import_react6.useRef)(null);
6027
+ const pointerScreenRef = (0, import_react6.useRef)(null);
6028
+ const iframeOffsetTopRef = (0, import_react6.useRef)(null);
6029
+ const sectionIdsRef = (0, import_react6.useRef)([]);
6030
+ const [chromeClip, setChromeClip] = (0, import_react6.useState)(
5813
6031
  () => ({
5814
6032
  top: 0,
5815
6033
  bottom: typeof window !== "undefined" ? window.innerHeight : 0
@@ -5817,12 +6035,12 @@ function SectionPickerOverlay({
5817
6035
  );
5818
6036
  const normalizedTarget = normalizePath(pagePath);
5819
6037
  const isOnTargetPage = normalizePath(pathname) === normalizedTarget;
5820
- (0, import_react5.useEffect)(() => {
6038
+ (0, import_react6.useEffect)(() => {
5821
6039
  if (isOnTargetPage) return;
5822
6040
  const search = readPreservedSearch();
5823
6041
  router.push(`${normalizedTarget}${search}`);
5824
6042
  }, [isOnTargetPage, normalizedTarget, router]);
5825
- (0, import_react5.useEffect)(() => {
6043
+ (0, import_react6.useEffect)(() => {
5826
6044
  document.documentElement.setAttribute("data-ohw-section-picking", "");
5827
6045
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => {
5828
6046
  el.removeAttribute("data-ohw-hovered");
@@ -5834,24 +6052,24 @@ function SectionPickerOverlay({
5834
6052
  document.documentElement.removeAttribute("data-ohw-section-picking");
5835
6053
  };
5836
6054
  }, []);
5837
- const liveSections = (0, import_react5.useMemo)(() => {
6055
+ const liveSections = (0, import_react6.useMemo)(() => {
5838
6056
  if (!isOnTargetPage) return sections;
5839
6057
  const live = collectSectionsFromDom();
5840
6058
  if (live.length === 0) return sections;
5841
6059
  const labels = new Map(sections.map((s) => [s.id, s.label]));
5842
6060
  return live.map((s) => ({ id: s.id, label: labels.get(s.id) ?? s.label }));
5843
6061
  }, [isOnTargetPage, sections, pathname]);
5844
- const sectionIdsKey = (0, import_react5.useMemo)(
6062
+ const sectionIdsKey = (0, import_react6.useMemo)(
5845
6063
  () => liveSections.map((s) => s.id).join("\0"),
5846
6064
  [liveSections]
5847
6065
  );
5848
- const sectionIds = (0, import_react5.useMemo)(
6066
+ const sectionIds = (0, import_react6.useMemo)(
5849
6067
  () => liveSections.map((s) => s.id),
5850
6068
  [liveSections]
5851
6069
  );
5852
6070
  sectionIdsRef.current = sectionIds;
5853
6071
  const rects = useSectionRects(sectionIdsKey, isOnTargetPage);
5854
- const applyHoverAt = (0, import_react5.useCallback)(
6072
+ const applyHoverAt = (0, import_react6.useCallback)(
5855
6073
  (x, y, liveRects) => {
5856
6074
  const ids = sectionIdsRef.current;
5857
6075
  const map = liveRects ?? readSectionRects(ids);
@@ -5860,7 +6078,7 @@ function SectionPickerOverlay({
5860
6078
  },
5861
6079
  []
5862
6080
  );
5863
- (0, import_react5.useEffect)(() => {
6081
+ (0, import_react6.useEffect)(() => {
5864
6082
  const applyClip = (iframeOffsetTop, visibleCanvasTop, canvasH) => {
5865
6083
  const top = Math.max(0, visibleCanvasTop - iframeOffsetTop);
5866
6084
  const bottom = Math.min(
@@ -5902,12 +6120,12 @@ function SectionPickerOverlay({
5902
6120
  window.removeEventListener("resize", onResize);
5903
6121
  };
5904
6122
  }, [applyHoverAt]);
5905
- (0, import_react5.useEffect)(() => {
6123
+ (0, import_react6.useEffect)(() => {
5906
6124
  const ptr = pointerRef.current;
5907
6125
  if (!ptr) return;
5908
6126
  applyHoverAt(ptr.x, ptr.y, rects);
5909
6127
  }, [rects, applyHoverAt]);
5910
- (0, import_react5.useEffect)(() => {
6128
+ (0, import_react6.useEffect)(() => {
5911
6129
  const rememberPointer = (clientX, clientY) => {
5912
6130
  pointerRef.current = { x: clientX, y: clientY };
5913
6131
  const top = iframeOffsetTopRef.current;
@@ -5931,7 +6149,7 @@ function SectionPickerOverlay({
5931
6149
  window.removeEventListener("message", onPointerSync);
5932
6150
  };
5933
6151
  }, [rects, applyHoverAt]);
5934
- const handleSelect = (0, import_react5.useCallback)(
6152
+ const handleSelect = (0, import_react6.useCallback)(
5935
6153
  (section) => {
5936
6154
  if (selectedId) return;
5937
6155
  setSelectedId(section.id);
@@ -5939,7 +6157,7 @@ function SectionPickerOverlay({
5939
6157
  },
5940
6158
  [selectedId, onSelect]
5941
6159
  );
5942
- (0, import_react5.useEffect)(() => {
6160
+ (0, import_react6.useEffect)(() => {
5943
6161
  const onKeyDown = (e) => {
5944
6162
  if (e.key === "Escape") {
5945
6163
  e.preventDefault();
@@ -5953,7 +6171,7 @@ function SectionPickerOverlay({
5953
6171
  const portalRoot = typeof document !== "undefined" ? document.querySelector("[data-ohw-bridge-root]") ?? document.body : null;
5954
6172
  if (!portalRoot) return null;
5955
6173
  return (0, import_react_dom.createPortal)(
5956
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
6174
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
5957
6175
  "div",
5958
6176
  {
5959
6177
  "data-ohw-section-picker": "",
@@ -5963,12 +6181,12 @@ function SectionPickerOverlay({
5963
6181
  role: "dialog",
5964
6182
  "aria-label": "Choose a section",
5965
6183
  children: [
5966
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6184
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
5967
6185
  "div",
5968
6186
  {
5969
6187
  className: "pointer-events-auto fixed left-5 z-[2]",
5970
6188
  style: { top: chromeClip.top + 20 },
5971
- children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
6189
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
5972
6190
  Button,
5973
6191
  {
5974
6192
  type: "button",
@@ -5977,14 +6195,14 @@ function SectionPickerOverlay({
5977
6195
  className: "h-8 min-w-0 gap-1 border-border bg-background px-2 py-1.5 shadow-sm hover:bg-muted cursor-pointer",
5978
6196
  onClick: onBack,
5979
6197
  children: [
5980
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react10.ArrowLeft, { className: "size-4 shrink-0", "aria-hidden": true }),
6198
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.ArrowLeft, { className: "size-4 shrink-0", "aria-hidden": true }),
5981
6199
  "Back"
5982
6200
  ]
5983
6201
  }
5984
6202
  )
5985
6203
  }
5986
6204
  ),
5987
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6205
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
5988
6206
  "div",
5989
6207
  {
5990
6208
  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",
@@ -5997,7 +6215,7 @@ function SectionPickerOverlay({
5997
6215
  children: "Click on section to select"
5998
6216
  }
5999
6217
  ),
6000
- !isOnTargetPage ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6218
+ !isOnTargetPage ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6001
6219
  "div",
6002
6220
  {
6003
6221
  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",
@@ -6005,14 +6223,14 @@ function SectionPickerOverlay({
6005
6223
  children: "Loading page preview\u2026"
6006
6224
  }
6007
6225
  ) : null,
6008
- 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,
6226
+ isOnTargetPage && liveSections.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "pointer-events-auto fixed inset-0 z-[1] flex items-center justify-center bg-muted/40", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." }) }) : null,
6009
6227
  isOnTargetPage ? liveSections.map((section) => {
6010
6228
  const rect = rects.get(section.id);
6011
6229
  if (!rect || rect.width <= 0 || rect.height <= 0) return null;
6012
6230
  const isSelected = selectedId === section.id;
6013
6231
  const isHovered = hoveredId === section.id;
6014
6232
  const isLit = isSelected || isHovered;
6015
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
6233
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
6016
6234
  "button",
6017
6235
  {
6018
6236
  type: "button",
@@ -6027,7 +6245,7 @@ function SectionPickerOverlay({
6027
6245
  "aria-label": `Select section ${section.label}`,
6028
6246
  onClick: () => handleSelect(section),
6029
6247
  children: [
6030
- isLit ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6248
+ isLit ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6031
6249
  "span",
6032
6250
  {
6033
6251
  className: "pointer-events-none absolute",
@@ -6040,13 +6258,13 @@ function SectionPickerOverlay({
6040
6258
  "aria-hidden": true
6041
6259
  }
6042
6260
  ) : null,
6043
- isSelected ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6261
+ isSelected ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6044
6262
  "span",
6045
6263
  {
6046
6264
  className: "absolute right-3 top-3 flex size-8 items-center justify-center rounded-full text-white",
6047
6265
  style: { backgroundColor: "var(--ohw-primary, #0885fe)" },
6048
6266
  "aria-hidden": true,
6049
- children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react10.Check, { className: "size-5" })
6267
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.Check, { className: "size-5" })
6050
6268
  }
6051
6269
  ) : null
6052
6270
  ]
@@ -6062,7 +6280,7 @@ function SectionPickerOverlay({
6062
6280
  }
6063
6281
 
6064
6282
  // src/ui/link-modal/useLinkModalState.ts
6065
- var import_react6 = require("react");
6283
+ var import_react7 = require("react");
6066
6284
  function useLinkModalState({
6067
6285
  open,
6068
6286
  mode,
@@ -6074,14 +6292,14 @@ function useLinkModalState({
6074
6292
  onClose,
6075
6293
  onSubmit
6076
6294
  }) {
6077
- const availablePages = (0, import_react6.useMemo)(() => pages, [pages]);
6078
- const [searchValue, setSearchValue] = (0, import_react6.useState)("");
6079
- const [selectedPage, setSelectedPage] = (0, import_react6.useState)(null);
6080
- const [selectedSection, setSelectedSection] = (0, import_react6.useState)(null);
6081
- const [step, setStep] = (0, import_react6.useState)("input");
6082
- const [dropdownOpen, setDropdownOpen] = (0, import_react6.useState)(false);
6083
- const [urlError, setUrlError] = (0, import_react6.useState)("");
6084
- const reset = (0, import_react6.useCallback)(() => {
6295
+ const availablePages = (0, import_react7.useMemo)(() => pages, [pages]);
6296
+ const [searchValue, setSearchValue] = (0, import_react7.useState)("");
6297
+ const [selectedPage, setSelectedPage] = (0, import_react7.useState)(null);
6298
+ const [selectedSection, setSelectedSection] = (0, import_react7.useState)(null);
6299
+ const [step, setStep] = (0, import_react7.useState)("input");
6300
+ const [dropdownOpen, setDropdownOpen] = (0, import_react7.useState)(false);
6301
+ const [urlError, setUrlError] = (0, import_react7.useState)("");
6302
+ const reset = (0, import_react7.useCallback)(() => {
6085
6303
  setSearchValue("");
6086
6304
  setSelectedPage(null);
6087
6305
  setSelectedSection(null);
@@ -6089,7 +6307,7 @@ function useLinkModalState({
6089
6307
  setDropdownOpen(false);
6090
6308
  setUrlError("");
6091
6309
  }, []);
6092
- (0, import_react6.useEffect)(() => {
6310
+ (0, import_react7.useEffect)(() => {
6093
6311
  if (!open) return;
6094
6312
  if (mode === "edit" && initialTarget) {
6095
6313
  const { pageRoute } = parseTarget(initialTarget);
@@ -6105,11 +6323,11 @@ function useLinkModalState({
6105
6323
  setDropdownOpen(false);
6106
6324
  setUrlError("");
6107
6325
  }, [open, mode, initialTarget, reset]);
6108
- const filteredPages = (0, import_react6.useMemo)(() => {
6326
+ const filteredPages = (0, import_react7.useMemo)(() => {
6109
6327
  if (!searchValue.trim()) return availablePages;
6110
6328
  return availablePages.filter((p) => p.title.toLowerCase().startsWith(searchValue.toLowerCase()));
6111
6329
  }, [availablePages, searchValue]);
6112
- const activeSections = (0, import_react6.useMemo)(() => {
6330
+ const activeSections = (0, import_react7.useMemo)(() => {
6113
6331
  if (!selectedPage) return [];
6114
6332
  return getSectionsForPath(sectionsByPath, selectedPage.path);
6115
6333
  }, [selectedPage, sectionsByPath]);
@@ -6158,7 +6376,7 @@ function useLinkModalState({
6158
6376
  reset();
6159
6377
  onClose();
6160
6378
  };
6161
- const isValid = (0, import_react6.useMemo)(() => {
6379
+ const isValid = (0, import_react7.useMemo)(() => {
6162
6380
  if (urlError) return false;
6163
6381
  if (showBreadcrumb) return true;
6164
6382
  if (selectedPage) return true;
@@ -6226,7 +6444,7 @@ function useLinkModalState({
6226
6444
  }
6227
6445
 
6228
6446
  // src/ui/link-modal/LinkPopover.tsx
6229
- var import_jsx_runtime21 = require("react/jsx-runtime");
6447
+ var import_jsx_runtime22 = require("react/jsx-runtime");
6230
6448
  function postToParent(data) {
6231
6449
  window.parent?.postMessage(data, "*");
6232
6450
  }
@@ -6255,7 +6473,7 @@ function LinkPopover({
6255
6473
  onSubmit
6256
6474
  });
6257
6475
  const sectionPickerActive = state.showSectionPicker && Boolean(state.selectedPage);
6258
- (0, import_react7.useEffect)(() => {
6476
+ (0, import_react8.useEffect)(() => {
6259
6477
  if (!open) return;
6260
6478
  if (sectionPickerActive) {
6261
6479
  postToParent({ type: "ui:unlock" });
@@ -6322,15 +6540,15 @@ function LinkPopover({
6322
6540
  );
6323
6541
  };
6324
6542
  }, [open, sectionPickerActive]);
6325
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
6326
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6543
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
6544
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6327
6545
  Dialog2,
6328
6546
  {
6329
6547
  open: open && !sectionPickerActive,
6330
6548
  onOpenChange: (next) => {
6331
6549
  if (!next) onClose?.();
6332
6550
  },
6333
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6551
+ children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6334
6552
  DialogContent,
6335
6553
  {
6336
6554
  ref: panelRef,
@@ -6340,12 +6558,12 @@ function LinkPopover({
6340
6558
  "data-ohw-bridge": "",
6341
6559
  showCloseButton: false,
6342
6560
  className: "gap-0 p-0 w-full max-w-[448px] pointer-events-auto z-[2147483646] overflow-visible",
6343
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LinkEditorPanel, { state, onClose })
6561
+ children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(LinkEditorPanel, { state, onClose })
6344
6562
  }
6345
6563
  )
6346
6564
  }
6347
6565
  ),
6348
- sectionPickerActive && state.selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6566
+ sectionPickerActive && state.selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6349
6567
  SectionPickerOverlay,
6350
6568
  {
6351
6569
  pagePath: state.selectedPage.path,
@@ -6884,6 +7102,53 @@ function insertNavbarItem(href, label, afterAnchor = null) {
6884
7102
  order
6885
7103
  };
6886
7104
  }
7105
+ function duplicateNavbarItem(sourceAnchor) {
7106
+ if (!isNavbarLinkItem(sourceAnchor)) return null;
7107
+ const sourceHrefKey = sourceAnchor.getAttribute("data-ohw-href-key");
7108
+ if (!sourceHrefKey || !isNavbarHrefKey(sourceHrefKey)) return null;
7109
+ const href = getLinkHref(sourceAnchor);
7110
+ const labelEl = sourceAnchor.querySelector('[data-ohw-editable="text"]');
7111
+ const label = (labelEl?.textContent ?? "").trim() || "Untitled";
7112
+ const forest = getNavForestFromDom();
7113
+ const sourceNode = forest.find((n) => n.id === sourceHrefKey);
7114
+ const childIds = sourceNode?.children.map((c) => c.id) ?? [];
7115
+ const primary = insertNavbarItem(href, label, sourceAnchor);
7116
+ const childResults = [];
7117
+ let after = primary.anchor;
7118
+ for (const childId of childIds) {
7119
+ const childEl = findCounterpartByHrefKey(childId, document) ?? document.querySelector(`[data-ohw-href-key="${CSS.escape(childId)}"]`);
7120
+ if (!childEl || !isNavbarLinkItem(childEl)) continue;
7121
+ const childHref = getLinkHref(childEl);
7122
+ const childLabelEl = childEl.querySelector('[data-ohw-editable="text"]');
7123
+ const childLabel = (childLabelEl?.textContent ?? "").trim() || "Untitled";
7124
+ const inserted = insertNavbarItem(childHref, childLabel, after);
7125
+ childResults.push(inserted);
7126
+ after = inserted.anchor;
7127
+ }
7128
+ let orderJson;
7129
+ if (childResults.length > 0) {
7130
+ const nextForest = getNavForestFromDom();
7131
+ const withoutNew = nextForest.filter(
7132
+ (n) => n.id !== primary.hrefKey && !childResults.some((c) => c.hrefKey === n.id)
7133
+ );
7134
+ const sourceIdx = withoutNew.findIndex((n) => n.id === sourceHrefKey);
7135
+ const insertAt = sourceIdx >= 0 ? sourceIdx + 1 : withoutNew.length;
7136
+ withoutNew.splice(insertAt, 0, {
7137
+ id: primary.hrefKey,
7138
+ children: childResults.map((c) => ({ id: c.hrefKey, children: [] }))
7139
+ });
7140
+ applyNavForest(withoutNew);
7141
+ orderJson = serializeNavOrder(withoutNew);
7142
+ } else {
7143
+ orderJson = serializeNavOrder(getNavForestFromDom());
7144
+ }
7145
+ return {
7146
+ ...primary,
7147
+ order: flattenNavOrder(parseNavOrderJson(orderJson) ?? getNavForestFromDom()),
7148
+ childResults,
7149
+ orderJson
7150
+ };
7151
+ }
6887
7152
 
6888
7153
  // src/lib/footer-items.ts
6889
7154
  var FOOTER_ORDER_KEY = "__ohw_footer_order";
@@ -7067,7 +7332,185 @@ function parseFooterOrder(content) {
7067
7332
  return null;
7068
7333
  }
7069
7334
  }
7335
+ var FOOTER_HEADING_RE = /^footer-(\d+)-heading$/;
7336
+ var FOOTER_LABEL_RE = /^footer-(\d+)-(\d+)-label$/;
7337
+ var DEFAULT_FOOTER_COLUMN_HEADING = "New";
7338
+ var DEFAULT_FOOTER_COLUMN_LINK_LABEL = "New link";
7339
+ var DEFAULT_FOOTER_COLUMN_LINK_HREF = "";
7340
+ function isFooterLinksContainer(el) {
7341
+ return el.hasAttribute("data-ohw-footer-links") || el.classList.contains("rb-footer-links");
7342
+ }
7343
+ function getFooterColumnIndicesInDom() {
7344
+ const indices = /* @__PURE__ */ new Set();
7345
+ for (const col of listFooterColumns()) {
7346
+ const attr = col.getAttribute("data-ohw-footer-col");
7347
+ if (attr != null) {
7348
+ const n = parseInt(attr, 10);
7349
+ if (Number.isFinite(n)) indices.add(n);
7350
+ }
7351
+ for (const link of listFooterLinksInColumn(col)) {
7352
+ const parsed = parseFooterHrefKey(link.getAttribute("data-ohw-href-key"));
7353
+ if (parsed) indices.add(parsed.col);
7354
+ }
7355
+ const heading = col.querySelector('[data-ohw-key^="footer-"][data-ohw-key$="-heading"]');
7356
+ const headingKey = heading?.getAttribute("data-ohw-key");
7357
+ if (headingKey) {
7358
+ const match = headingKey.match(FOOTER_HEADING_RE);
7359
+ if (match) indices.add(parseInt(match[1], 10));
7360
+ }
7361
+ }
7362
+ return [...indices].sort((a, b) => a - b);
7363
+ }
7364
+ function getNextFooterColumnIndex() {
7365
+ const indices = getFooterColumnIndicesInDom();
7366
+ if (indices.length === 0) return 0;
7367
+ return Math.max(...indices) + 1;
7368
+ }
7369
+ function buildFooterHeading(colIndex, text) {
7370
+ const heading = document.createElement("p");
7371
+ heading.setAttribute("data-ohw-editable", "text");
7372
+ heading.setAttribute("data-ohw-key", `footer-${colIndex}-heading`);
7373
+ heading.textContent = text;
7374
+ heading.style.cssText = [
7375
+ "color: var(--espresso, #3d312b)",
7376
+ "font-size: 14px",
7377
+ "font-weight: 800",
7378
+ "opacity: 0.82",
7379
+ "margin: 0 0 6px",
7380
+ "padding: 0",
7381
+ "line-height: 1.2"
7382
+ ].join(";");
7383
+ return heading;
7384
+ }
7385
+ function buildFooterLink(colIndex, itemIndex, href, label, template) {
7386
+ const anchor = cloneFooterLinkShell(template);
7387
+ anchor.setAttribute("href", href);
7388
+ anchor.setAttribute("data-ohw-href-key", `footer-${colIndex}-${itemIndex}-href`);
7389
+ const span = document.createElement("span");
7390
+ span.setAttribute("data-ohw-editable", "text");
7391
+ span.setAttribute("data-ohw-key", `footer-${colIndex}-${itemIndex}-label`);
7392
+ span.textContent = label;
7393
+ anchor.appendChild(span);
7394
+ return anchor;
7395
+ }
7396
+ function footerColumnExistsInDom(colIndex) {
7397
+ 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;
7398
+ }
7399
+ function getFooterLinkTemplate() {
7400
+ for (const col of listFooterColumns()) {
7401
+ const link = listFooterLinksInColumn(col)[0];
7402
+ if (link) return link;
7403
+ }
7404
+ return null;
7405
+ }
7406
+ function getFooterColumnTemplate() {
7407
+ return listFooterColumns()[0] ?? null;
7408
+ }
7409
+ function insertFooterColumnDom(colIndex, heading, items) {
7410
+ const container = getFooterLinksContainer();
7411
+ if (!container) return null;
7412
+ const colTemplate = getFooterColumnTemplate();
7413
+ const linkTemplate = getFooterLinkTemplate();
7414
+ const column = document.createElement("div");
7415
+ if (colTemplate?.className) column.className = colTemplate.className;
7416
+ else column.className = "rb-footer-link-col";
7417
+ column.setAttribute("data-ohw-footer-col", String(colIndex));
7418
+ if (colTemplate) {
7419
+ const gap = getComputedStyle(colTemplate).gap;
7420
+ if (gap && gap !== "normal") column.style.gap = gap;
7421
+ column.style.display = getComputedStyle(colTemplate).display || "flex";
7422
+ column.style.flexDirection = "column";
7423
+ }
7424
+ column.appendChild(buildFooterHeading(colIndex, heading));
7425
+ let firstLink = null;
7426
+ items.forEach((item, itemIndex) => {
7427
+ const link = buildFooterLink(colIndex, itemIndex, item.href, item.label, linkTemplate);
7428
+ column.appendChild(link);
7429
+ if (!firstLink) firstLink = link;
7430
+ });
7431
+ container.appendChild(column);
7432
+ return { column, firstLink };
7433
+ }
7434
+ function insertFooterColumn(heading = DEFAULT_FOOTER_COLUMN_HEADING, linkLabel = DEFAULT_FOOTER_COLUMN_LINK_LABEL, linkHref = DEFAULT_FOOTER_COLUMN_LINK_HREF) {
7435
+ const colIndex = getNextFooterColumnIndex();
7436
+ const inserted = insertFooterColumnDom(colIndex, heading, [{ href: linkHref, label: linkLabel }]);
7437
+ if (!inserted?.firstLink) throw new Error("Failed to insert footer column");
7438
+ syncFooterColumnIndices(listFooterColumns());
7439
+ return {
7440
+ column: inserted.column,
7441
+ firstLink: inserted.firstLink,
7442
+ colIndex,
7443
+ headingKey: `footer-${colIndex}-heading`,
7444
+ hrefKey: `footer-${colIndex}-0-href`,
7445
+ labelKey: `footer-${colIndex}-0-label`,
7446
+ heading,
7447
+ label: linkLabel,
7448
+ href: linkHref,
7449
+ order: getFooterOrderFromDom()
7450
+ };
7451
+ }
7452
+ function collectFooterColumnIndicesFromContent(content) {
7453
+ const indices = /* @__PURE__ */ new Set();
7454
+ for (const key of Object.keys(content)) {
7455
+ const href = parseFooterHrefKey(key);
7456
+ if (href) indices.add(href.col);
7457
+ const heading = key.match(FOOTER_HEADING_RE);
7458
+ if (heading) indices.add(parseInt(heading[1], 10));
7459
+ const label = key.match(FOOTER_LABEL_RE);
7460
+ if (label) indices.add(parseInt(label[1], 10));
7461
+ }
7462
+ const order = parseFooterOrder(content);
7463
+ if (order) {
7464
+ for (const col of order) {
7465
+ for (const hrefKey of col) {
7466
+ const parsed = parseFooterHrefKey(hrefKey);
7467
+ if (parsed) indices.add(parsed.col);
7468
+ }
7469
+ }
7470
+ }
7471
+ return [...indices].sort((a, b) => a - b);
7472
+ }
7473
+ function collectFooterItemsForColumn(content, colIndex) {
7474
+ const itemIndices = /* @__PURE__ */ new Set();
7475
+ for (const key of Object.keys(content)) {
7476
+ const href = parseFooterHrefKey(key);
7477
+ if (href?.col === colIndex) itemIndices.add(href.item);
7478
+ const label = key.match(FOOTER_LABEL_RE);
7479
+ if (label && parseInt(label[1], 10) === colIndex) {
7480
+ itemIndices.add(parseInt(label[2], 10));
7481
+ }
7482
+ }
7483
+ const sorted = [...itemIndices].sort((a, b) => a - b);
7484
+ if (sorted.length === 0) {
7485
+ return [
7486
+ {
7487
+ href: content[`footer-${colIndex}-0-href`] ?? DEFAULT_FOOTER_COLUMN_LINK_HREF,
7488
+ label: content[`footer-${colIndex}-0-label`] ?? DEFAULT_FOOTER_COLUMN_LINK_LABEL
7489
+ }
7490
+ ];
7491
+ }
7492
+ return sorted.map((itemIndex) => ({
7493
+ href: content[`footer-${colIndex}-${itemIndex}-href`] ?? DEFAULT_FOOTER_COLUMN_LINK_HREF,
7494
+ label: content[`footer-${colIndex}-${itemIndex}-label`] ?? DEFAULT_FOOTER_COLUMN_LINK_LABEL
7495
+ }));
7496
+ }
7497
+ function reconcileFooterColumnsFromContent(content) {
7498
+ const indices = collectFooterColumnIndicesFromContent(content);
7499
+ for (const colIndex of indices) {
7500
+ if (footerColumnExistsInDom(colIndex)) continue;
7501
+ const heading = content[`footer-${colIndex}-heading`] ?? DEFAULT_FOOTER_COLUMN_HEADING;
7502
+ const items = collectFooterItemsForColumn(content, colIndex);
7503
+ const hasPayload = Boolean(content[`footer-${colIndex}-heading`]) || items.some(
7504
+ (_, i) => content[`footer-${colIndex}-${i}-href`] !== void 0 || content[`footer-${colIndex}-${i}-label`] !== void 0
7505
+ ) || (parseFooterOrder(content)?.some(
7506
+ (col) => col.some((k) => parseFooterHrefKey(k)?.col === colIndex)
7507
+ ) ?? false);
7508
+ if (!hasPayload) continue;
7509
+ insertFooterColumnDom(colIndex, heading, items);
7510
+ }
7511
+ }
7070
7512
  function reconcileFooterOrderFromContent(content) {
7513
+ reconcileFooterColumnsFromContent(content);
7071
7514
  const order = parseFooterOrder(content);
7072
7515
  if (!order?.length) return;
7073
7516
  const current = getFooterOrderFromDom();
@@ -7077,6 +7520,26 @@ function reconcileFooterOrderFromContent(content) {
7077
7520
  }
7078
7521
  applyFooterOrder(order);
7079
7522
  }
7523
+ function resolveFooterLinksContainerSelectionTarget(target, clientX, clientY, isPointOverItem) {
7524
+ const container = getFooterLinksContainer();
7525
+ if (!container) return null;
7526
+ const inContainer = target === container || container.contains(target) && Boolean(target.closest("[data-ohw-footer-links], .rb-footer-links"));
7527
+ if (!inContainer && target !== container) {
7528
+ const r2 = container.getBoundingClientRect();
7529
+ const over = clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
7530
+ if (!over) return null;
7531
+ }
7532
+ if (isPointOverItem(container, clientX, clientY)) return null;
7533
+ const column = target.closest("[data-ohw-footer-col], [data-ohw-footer-column]") ?? null;
7534
+ if (column && container.contains(column)) {
7535
+ if (target === column || column.contains(target)) return null;
7536
+ }
7537
+ if (target === container || container.contains(target) || inContainer) {
7538
+ if (target === container || isFooterLinksContainer(target)) return container;
7539
+ if (!column) return container;
7540
+ }
7541
+ return null;
7542
+ }
7080
7543
  function isRowLayoutColumn(links) {
7081
7544
  if (links.length < 2) return false;
7082
7545
  const firstTop = links[0].getBoundingClientRect().top;
@@ -7231,6 +7694,100 @@ function hitTestColumnDropSlot(clientX, _clientY) {
7231
7694
  }
7232
7695
  return best?.slot ?? null;
7233
7696
  }
7697
+ function getLinkHref2(el) {
7698
+ const key = el.getAttribute("data-ohw-href-key");
7699
+ if (key) {
7700
+ const stored = getStoredLinkHref(key);
7701
+ if (stored !== void 0) return stored;
7702
+ }
7703
+ return el.getAttribute("href") ?? "";
7704
+ }
7705
+ function getNextFooterItemIndex(col) {
7706
+ let max = -1;
7707
+ for (const el of document.querySelectorAll("footer [data-ohw-href-key]")) {
7708
+ const parsed = parseFooterHrefKey(el.getAttribute("data-ohw-href-key"));
7709
+ if (!parsed || parsed.col !== col) continue;
7710
+ if (parsed.item > max) max = parsed.item;
7711
+ }
7712
+ return max + 1;
7713
+ }
7714
+ function cloneFooterLinkShell(template) {
7715
+ const anchor = document.createElement("a");
7716
+ if (template) {
7717
+ anchor.style.cssText = template.style.cssText;
7718
+ if (template.className) anchor.className = template.className;
7719
+ }
7720
+ anchor.style.cursor = "pointer";
7721
+ anchor.style.textDecoration = "none";
7722
+ return anchor;
7723
+ }
7724
+ function insertFooterItem(column, href, label, afterAnchor = null) {
7725
+ const columns = listFooterColumns();
7726
+ const colIndex = columns.indexOf(column);
7727
+ if (colIndex < 0) throw new Error("Footer column not found");
7728
+ const item = getNextFooterItemIndex(colIndex);
7729
+ const hrefKey = `footer-${colIndex}-${item}-href`;
7730
+ const labelKey = `footer-${colIndex}-${item}-label`;
7731
+ const template = listFooterLinksInColumn(column)[0] ?? null;
7732
+ const anchor = cloneFooterLinkShell(template);
7733
+ anchor.href = href;
7734
+ anchor.setAttribute("data-ohw-href-key", hrefKey);
7735
+ const span = document.createElement("span");
7736
+ span.setAttribute("data-ohw-editable", "text");
7737
+ span.setAttribute("data-ohw-key", labelKey);
7738
+ span.textContent = label;
7739
+ anchor.appendChild(span);
7740
+ if (afterAnchor && afterAnchor.parentElement === column) {
7741
+ afterAnchor.insertAdjacentElement("afterend", anchor);
7742
+ } else {
7743
+ column.appendChild(anchor);
7744
+ }
7745
+ const order = getFooterOrderFromDom();
7746
+ applyFooterOrder(order);
7747
+ return {
7748
+ anchor,
7749
+ col: colIndex,
7750
+ item,
7751
+ hrefKey,
7752
+ labelKey,
7753
+ href,
7754
+ label,
7755
+ order
7756
+ };
7757
+ }
7758
+ function duplicateFooterItem(sourceAnchor) {
7759
+ if (!isFooterLinkAnchor(sourceAnchor)) return null;
7760
+ const column = findFooterColumnForLink(sourceAnchor);
7761
+ if (!column) return null;
7762
+ const href = getLinkHref2(sourceAnchor);
7763
+ const labelEl = sourceAnchor.querySelector('[data-ohw-editable="text"]');
7764
+ const label = (labelEl?.textContent ?? "").trim() || "Untitled";
7765
+ return insertFooterItem(column, href || "/", label, sourceAnchor);
7766
+ }
7767
+
7768
+ // src/lib/add-footer-column.ts
7769
+ function buildFooterColumnEditContentPatch(result) {
7770
+ return {
7771
+ [result.headingKey]: result.heading,
7772
+ [result.hrefKey]: result.href,
7773
+ [result.labelKey]: result.label,
7774
+ [FOOTER_ORDER_KEY]: JSON.stringify(result.order)
7775
+ };
7776
+ }
7777
+ function addFooterColumnWithPersist({
7778
+ postToParent: postToParent2
7779
+ }) {
7780
+ const result = insertFooterColumn();
7781
+ const patch = buildFooterColumnEditContentPatch(result);
7782
+ setStoredLinkHref(result.hrefKey, result.href);
7783
+ postToParent2({
7784
+ type: "ow:change",
7785
+ nodes: Object.entries(patch).map(([key, text]) => ({ key, text }))
7786
+ });
7787
+ postToParent2({ type: "ow:toast", title: "Item added", toastType: "success" });
7788
+ enforceLinkHrefs();
7789
+ return result;
7790
+ }
7234
7791
 
7235
7792
  // src/lib/item-drag-interaction.ts
7236
7793
  function disableNativeHrefDrag(el) {
@@ -7429,7 +7986,7 @@ function hitTestNavDropSlot(clientX, clientY, draggedHrefKey) {
7429
7986
  }
7430
7987
 
7431
7988
  // src/useNavItemDrag.ts
7432
- var import_react8 = require("react");
7989
+ var import_react9 = require("react");
7433
7990
  function useNavItemDrag({
7434
7991
  isEditMode,
7435
7992
  editContentRef,
@@ -7454,11 +8011,11 @@ function useNavItemDrag({
7454
8011
  isDragHandleDisabled: isDragHandleDisabled2,
7455
8012
  isNavbarButton: isNavbarButton3
7456
8013
  }) {
7457
- const navDragRef = (0, import_react8.useRef)(null);
7458
- const [navDropSlots, setNavDropSlots] = (0, import_react8.useState)([]);
7459
- const [activeNavDropIndex, setActiveNavDropIndex] = (0, import_react8.useState)(null);
7460
- const navPointerDragRef = (0, import_react8.useRef)(null);
7461
- const clearNavDragVisuals = (0, import_react8.useCallback)(() => {
8014
+ const navDragRef = (0, import_react9.useRef)(null);
8015
+ const [navDropSlots, setNavDropSlots] = (0, import_react9.useState)([]);
8016
+ const [activeNavDropIndex, setActiveNavDropIndex] = (0, import_react9.useState)(null);
8017
+ const navPointerDragRef = (0, import_react9.useRef)(null);
8018
+ const clearNavDragVisuals = (0, import_react9.useCallback)(() => {
7462
8019
  navDragRef.current = null;
7463
8020
  setNavDropSlots([]);
7464
8021
  setActiveNavDropIndex(null);
@@ -7467,7 +8024,7 @@ function useNavItemDrag({
7467
8024
  setIsItemDragging(false);
7468
8025
  unlockItemDragInteraction();
7469
8026
  }, [setDraggedItemRect, setIsItemDragging, setSiblingHintRects]);
7470
- const refreshNavDragVisuals = (0, import_react8.useCallback)(
8027
+ const refreshNavDragVisuals = (0, import_react9.useCallback)(
7471
8028
  (session, activeSlot, clientX, clientY) => {
7472
8029
  setDraggedItemRect(session.draggedEl.getBoundingClientRect());
7473
8030
  if (typeof clientX === "number" && typeof clientY === "number") {
@@ -7485,13 +8042,13 @@ function useNavItemDrag({
7485
8042
  },
7486
8043
  [setDraggedItemRect, setSiblingHintRects]
7487
8044
  );
7488
- const refreshNavDragVisualsRef = (0, import_react8.useRef)(refreshNavDragVisuals);
8045
+ const refreshNavDragVisualsRef = (0, import_react9.useRef)(refreshNavDragVisuals);
7489
8046
  refreshNavDragVisualsRef.current = refreshNavDragVisuals;
7490
- const commitNavDragRef = (0, import_react8.useRef)(() => {
8047
+ const commitNavDragRef = (0, import_react9.useRef)(() => {
7491
8048
  });
7492
- const beginNavDragRef = (0, import_react8.useRef)(() => {
8049
+ const beginNavDragRef = (0, import_react9.useRef)(() => {
7493
8050
  });
7494
- const beginNavDrag = (0, import_react8.useCallback)(
8051
+ const beginNavDrag = (0, import_react9.useCallback)(
7495
8052
  (session) => {
7496
8053
  const rect = session.draggedEl.getBoundingClientRect();
7497
8054
  session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
@@ -7518,7 +8075,7 @@ function useNavItemDrag({
7518
8075
  ]
7519
8076
  );
7520
8077
  beginNavDragRef.current = beginNavDrag;
7521
- const commitNavDrag = (0, import_react8.useCallback)(
8078
+ const commitNavDrag = (0, import_react9.useCallback)(
7522
8079
  (clientX, clientY) => {
7523
8080
  const session = navDragRef.current;
7524
8081
  if (!session) {
@@ -7579,7 +8136,7 @@ function useNavItemDrag({
7579
8136
  [clearNavDragVisuals, deselectRef, editContentRef, postToParentRef, selectRef]
7580
8137
  );
7581
8138
  commitNavDragRef.current = commitNavDrag;
7582
- const startNavLinkDrag = (0, import_react8.useCallback)(
8139
+ const startNavLinkDrag = (0, import_react9.useCallback)(
7583
8140
  (anchor, clientX, clientY, wasSelected) => {
7584
8141
  if (footerDragRef.current) return false;
7585
8142
  const hrefKey = anchor.getAttribute("data-ohw-href-key");
@@ -7597,7 +8154,7 @@ function useNavItemDrag({
7597
8154
  },
7598
8155
  [beginNavDrag, footerDragRef, isDragHandleDisabled2, isNavbarButton3]
7599
8156
  );
7600
- const onNavDragOver = (0, import_react8.useCallback)(
8157
+ const onNavDragOver = (0, import_react9.useCallback)(
7601
8158
  (e) => {
7602
8159
  const session = navDragRef.current;
7603
8160
  if (!session) return false;
@@ -7609,7 +8166,7 @@ function useNavItemDrag({
7609
8166
  },
7610
8167
  []
7611
8168
  );
7612
- (0, import_react8.useEffect)(() => {
8169
+ (0, import_react9.useEffect)(() => {
7613
8170
  if (!isEditMode) return;
7614
8171
  const THRESHOLD = 10;
7615
8172
  const resolveWasSelected = (el) => {
@@ -7734,7 +8291,7 @@ function useNavItemDrag({
7734
8291
  setLinkPopover,
7735
8292
  suppressNextClickRef
7736
8293
  ]);
7737
- const armNavPressFromChrome = (0, import_react8.useCallback)(
8294
+ const armNavPressFromChrome = (0, import_react9.useCallback)(
7738
8295
  (selected, clientX, clientY, pointerId) => {
7739
8296
  const hrefKey = selected.getAttribute("data-ohw-href-key");
7740
8297
  if (!hrefKey || !isNavbarHrefKey(hrefKey)) return false;
@@ -7764,8 +8321,53 @@ function useNavItemDrag({
7764
8321
  };
7765
8322
  }
7766
8323
 
8324
+ // src/ui/footer-container-chrome.tsx
8325
+ var import_lucide_react11 = require("lucide-react");
8326
+ var import_jsx_runtime23 = require("react/jsx-runtime");
8327
+ function FooterContainerChrome({ rect, onAdd }) {
8328
+ const chromeGap = 6;
8329
+ const buttonMargin = 7;
8330
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8331
+ "div",
8332
+ {
8333
+ "data-ohw-footer-container-chrome": "",
8334
+ "data-ohw-bridge": "",
8335
+ className: "pointer-events-none fixed z-[2147483647]",
8336
+ style: {
8337
+ top: rect.top - chromeGap,
8338
+ left: rect.left - chromeGap,
8339
+ width: rect.width + chromeGap * 2,
8340
+ height: rect.height + chromeGap * 2
8341
+ },
8342
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(Tooltip, { children: [
8343
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8344
+ "button",
8345
+ {
8346
+ type: "button",
8347
+ "data-ohw-footer-add-button": "",
8348
+ 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",
8349
+ style: { top: chromeGap - buttonMargin },
8350
+ "aria-label": "Add item",
8351
+ onMouseDown: (e) => {
8352
+ e.preventDefault();
8353
+ e.stopPropagation();
8354
+ },
8355
+ onClick: (e) => {
8356
+ e.preventDefault();
8357
+ e.stopPropagation();
8358
+ onAdd();
8359
+ },
8360
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
8361
+ }
8362
+ ) }),
8363
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: "Add item" })
8364
+ ] })
8365
+ }
8366
+ ) });
8367
+ }
8368
+
7767
8369
  // src/lib/carousel.ts
7768
- var import_react9 = require("react");
8370
+ var import_react10 = require("react");
7769
8371
  var CAROUSEL_ATTR = "data-ohw-carousel";
7770
8372
  var CAROUSEL_VALUE_ATTR = "data-ohw-carousel-value";
7771
8373
  var CAROUSEL_SLIDE_ATTR = "data-ohw-carousel-slide";
@@ -7827,8 +8429,8 @@ function applyCarouselNode(key, val) {
7827
8429
  return true;
7828
8430
  }
7829
8431
  function useOhwCarousel(key, initial) {
7830
- const [images, setImages] = (0, import_react9.useState)(initial);
7831
- (0, import_react9.useEffect)(() => {
8432
+ const [images, setImages] = (0, import_react10.useState)(initial);
8433
+ (0, import_react10.useEffect)(() => {
7832
8434
  const el = document.querySelector(
7833
8435
  `[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`
7834
8436
  );
@@ -7849,14 +8451,14 @@ function useOhwCarousel(key, initial) {
7849
8451
  }
7850
8452
 
7851
8453
  // src/ui/navbar-container-chrome.tsx
7852
- var import_lucide_react11 = require("lucide-react");
7853
- var import_jsx_runtime22 = require("react/jsx-runtime");
8454
+ var import_lucide_react12 = require("lucide-react");
8455
+ var import_jsx_runtime24 = require("react/jsx-runtime");
7854
8456
  function NavbarContainerChrome({
7855
8457
  rect,
7856
8458
  onAdd
7857
8459
  }) {
7858
8460
  const chromeGap = 6;
7859
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8461
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
7860
8462
  "div",
7861
8463
  {
7862
8464
  "data-ohw-navbar-container-chrome": "",
@@ -7868,7 +8470,7 @@ function NavbarContainerChrome({
7868
8470
  width: rect.width + chromeGap * 2,
7869
8471
  height: rect.height + chromeGap * 2
7870
8472
  },
7871
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
8473
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
7872
8474
  "button",
7873
8475
  {
7874
8476
  type: "button",
@@ -7885,7 +8487,7 @@ function NavbarContainerChrome({
7885
8487
  e.stopPropagation();
7886
8488
  onAdd();
7887
8489
  },
7888
- children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react11.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
8490
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react12.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
7889
8491
  }
7890
8492
  )
7891
8493
  }
@@ -7894,7 +8496,7 @@ function NavbarContainerChrome({
7894
8496
 
7895
8497
  // src/ui/drop-indicator.tsx
7896
8498
  var React10 = __toESM(require("react"), 1);
7897
- var import_jsx_runtime23 = require("react/jsx-runtime");
8499
+ var import_jsx_runtime25 = require("react/jsx-runtime");
7898
8500
  var dropIndicatorVariants = cva(
7899
8501
  "ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
7900
8502
  {
@@ -7918,7 +8520,7 @@ var dropIndicatorVariants = cva(
7918
8520
  );
7919
8521
  var DropIndicator = React10.forwardRef(
7920
8522
  ({ className, direction, state, ...props }, ref) => {
7921
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
8523
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
7922
8524
  "div",
7923
8525
  {
7924
8526
  ref,
@@ -7935,7 +8537,7 @@ var DropIndicator = React10.forwardRef(
7935
8537
  DropIndicator.displayName = "DropIndicator";
7936
8538
 
7937
8539
  // src/ui/badge.tsx
7938
- var import_jsx_runtime24 = require("react/jsx-runtime");
8540
+ var import_jsx_runtime26 = require("react/jsx-runtime");
7939
8541
  var badgeVariants = cva(
7940
8542
  "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",
7941
8543
  {
@@ -7953,12 +8555,12 @@ var badgeVariants = cva(
7953
8555
  }
7954
8556
  );
7955
8557
  function Badge({ className, variant, ...props }) {
7956
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
8558
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
7957
8559
  }
7958
8560
 
7959
8561
  // src/OhhwellsBridge.tsx
7960
- var import_lucide_react12 = require("lucide-react");
7961
- var import_jsx_runtime25 = require("react/jsx-runtime");
8562
+ var import_lucide_react13 = require("lucide-react");
8563
+ var import_jsx_runtime27 = require("react/jsx-runtime");
7962
8564
  var PRIMARY2 = "#0885FE";
7963
8565
  var IMAGE_FADE_MS = 300;
7964
8566
  function runOpacityFade(el, onDone) {
@@ -8137,7 +8739,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
8137
8739
  const root = (0, import_client.createRoot)(container);
8138
8740
  (0, import_react_dom2.flushSync)(() => {
8139
8741
  root.render(
8140
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
8742
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
8141
8743
  SchedulingWidget,
8142
8744
  {
8143
8745
  notifyOnConnect,
@@ -8177,7 +8779,7 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
8177
8779
  }
8178
8780
  }
8179
8781
  }
8180
- function getLinkHref2(el) {
8782
+ function getLinkHref3(el) {
8181
8783
  const anchor = el instanceof HTMLAnchorElement ? el : el.querySelector("a");
8182
8784
  return anchor?.getAttribute("href") ?? "";
8183
8785
  }
@@ -8227,7 +8829,7 @@ function collectEditableNodes(extraContent) {
8227
8829
  return { key: el.dataset.ohwKey ?? "", type: "video", text: getVideoEl(el)?.src ?? "" };
8228
8830
  }
8229
8831
  if (el.dataset.ohwEditable === "link") {
8230
- return { key: el.dataset.ohwKey ?? "", type: "link", text: getLinkHref2(el) };
8832
+ return { key: el.dataset.ohwKey ?? "", type: "link", text: getLinkHref3(el) };
8231
8833
  }
8232
8834
  return {
8233
8835
  key: el.dataset.ohwKey ?? "",
@@ -8238,7 +8840,7 @@ function collectEditableNodes(extraContent) {
8238
8840
  document.querySelectorAll("[data-ohw-href-key]").forEach((el) => {
8239
8841
  const key = el.getAttribute("data-ohw-href-key") ?? "";
8240
8842
  if (!key) return;
8241
- nodes.push({ key, type: "link", text: getLinkHref2(el) });
8843
+ nodes.push({ key, type: "link", text: getLinkHref3(el) });
8242
8844
  });
8243
8845
  if (extraContent) {
8244
8846
  for (const key of [NAV_ORDER_KEY, FOOTER_ORDER_KEY, NAV_COUNT_KEY]) {
@@ -8341,7 +8943,7 @@ function applyLinkByKey(key, val) {
8341
8943
  }
8342
8944
  function isInsideLinkEditor(target) {
8343
8945
  return Boolean(
8344
- 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"]')
8946
+ 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-ohw-more-menu]") || target.closest('[data-slot="dropdown-menu-content"]') || target.closest('[data-slot="popover-content"]') || target.closest('[data-slot="dialog-content"]') || target.closest('[data-slot="dialog-overlay"]')
8345
8947
  );
8346
8948
  }
8347
8949
  function getHrefKeyFromElement(el) {
@@ -8422,7 +9024,7 @@ function isInferredFooterGroup(el) {
8422
9024
  return countFooterNavItems(el) >= 2;
8423
9025
  }
8424
9026
  function isNavigationContainer(el) {
8425
- return el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isNavigationRoot(el) || isInferredFooterGroup(el);
9027
+ 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);
8426
9028
  }
8427
9029
  function isNavbarLinksContainer(el) {
8428
9030
  return el.hasAttribute("data-ohw-nav-container");
@@ -8441,6 +9043,9 @@ function isPointOverNavigation(x, y) {
8441
9043
  const roots = /* @__PURE__ */ new Set();
8442
9044
  const navRoot = document.querySelector("[data-ohw-nav-root]") ?? document.querySelector("nav");
8443
9045
  if (navRoot) roots.add(navRoot);
9046
+ document.querySelectorAll("[data-ohw-nav-drawer], [data-ohw-nav-container]").forEach((el) => {
9047
+ roots.add(el);
9048
+ });
8444
9049
  const footer = document.querySelector("footer");
8445
9050
  if (footer) roots.add(footer);
8446
9051
  for (const root of roots) {
@@ -8469,6 +9074,12 @@ function isPointOverNavItem(container, x, y) {
8469
9074
  return x >= itemRect.left && x <= itemRect.right && y >= itemRect.top && y <= itemRect.bottom;
8470
9075
  });
8471
9076
  }
9077
+ function isPointOverFooterColumn(x, y) {
9078
+ return listFooterColumns().some((col) => {
9079
+ const r2 = col.getBoundingClientRect();
9080
+ return x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom;
9081
+ });
9082
+ }
8472
9083
  function resolveNavContainerSelectionTarget(target, clientX, clientY) {
8473
9084
  if (getNavigationItemAnchor(target)) return null;
8474
9085
  if (target.closest('[data-ohw-role="navbar-button"]')) return null;
@@ -8499,7 +9110,10 @@ function getNavigationSelectionParent(el) {
8499
9110
  if (footerGroup) return footerGroup;
8500
9111
  return getNavigationRoot(el);
8501
9112
  }
8502
- if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup(el)) {
9113
+ if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup(el))) {
9114
+ return getFooterLinksContainer();
9115
+ }
9116
+ if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isFooterLinksContainer(el) || isInferredFooterGroup(el)) {
8503
9117
  return getNavigationRoot(el);
8504
9118
  }
8505
9119
  return null;
@@ -8726,7 +9340,7 @@ function EditGlowChrome({
8726
9340
  hideHandle = false
8727
9341
  }) {
8728
9342
  const GAP = SELECTION_CHROME_GAP2;
8729
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
9343
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
8730
9344
  "div",
8731
9345
  {
8732
9346
  ref: elRef,
@@ -8741,7 +9355,7 @@ function EditGlowChrome({
8741
9355
  zIndex: 2147483646
8742
9356
  },
8743
9357
  children: [
8744
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
9358
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
8745
9359
  "div",
8746
9360
  {
8747
9361
  style: {
@@ -8754,7 +9368,7 @@ function EditGlowChrome({
8754
9368
  }
8755
9369
  }
8756
9370
  ),
8757
- reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
9371
+ reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
8758
9372
  "div",
8759
9373
  {
8760
9374
  "data-ohw-drag-handle-container": "",
@@ -8766,7 +9380,7 @@ function EditGlowChrome({
8766
9380
  transform: "translate(calc(-100% - 7px), -50%)",
8767
9381
  pointerEvents: dragDisabled ? "none" : "auto"
8768
9382
  },
8769
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
9383
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
8770
9384
  DragHandle,
8771
9385
  {
8772
9386
  "aria-label": `Reorder ${reorderHrefKey}`,
@@ -8949,9 +9563,9 @@ function FloatingToolbar({
8949
9563
  showEditLink,
8950
9564
  onEditLink
8951
9565
  }) {
8952
- const localRef = import_react10.default.useRef(null);
8953
- const [measuredW, setMeasuredW] = import_react10.default.useState(330);
8954
- const setRefs = import_react10.default.useCallback(
9566
+ const localRef = import_react11.default.useRef(null);
9567
+ const [measuredW, setMeasuredW] = import_react11.default.useState(330);
9568
+ const setRefs = import_react11.default.useCallback(
8955
9569
  (node) => {
8956
9570
  localRef.current = node;
8957
9571
  if (typeof elRef === "function") elRef(node);
@@ -8963,7 +9577,7 @@ function FloatingToolbar({
8963
9577
  },
8964
9578
  [elRef]
8965
9579
  );
8966
- import_react10.default.useLayoutEffect(() => {
9580
+ import_react11.default.useLayoutEffect(() => {
8967
9581
  const node = localRef.current;
8968
9582
  if (!node) return;
8969
9583
  const update = () => {
@@ -8976,7 +9590,7 @@ function FloatingToolbar({
8976
9590
  return () => ro.disconnect();
8977
9591
  }, [showEditLink, activeCommands]);
8978
9592
  const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
8979
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
9593
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
8980
9594
  "div",
8981
9595
  {
8982
9596
  ref: setRefs,
@@ -8988,12 +9602,12 @@ function FloatingToolbar({
8988
9602
  zIndex: 2147483647,
8989
9603
  pointerEvents: "auto"
8990
9604
  },
8991
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(CustomToolbar, { children: [
8992
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react10.default.Fragment, { children: [
8993
- gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(CustomToolbarDivider, {}),
9605
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(CustomToolbar, { children: [
9606
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_react11.default.Fragment, { children: [
9607
+ gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(CustomToolbarDivider, {}),
8994
9608
  btns.map((btn) => {
8995
9609
  const isActive = activeCommands.has(btn.cmd);
8996
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
9610
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
8997
9611
  CustomToolbarButton,
8998
9612
  {
8999
9613
  title: btn.title,
@@ -9002,7 +9616,7 @@ function FloatingToolbar({
9002
9616
  e.preventDefault();
9003
9617
  onCommand(btn.cmd);
9004
9618
  },
9005
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
9619
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
9006
9620
  "svg",
9007
9621
  {
9008
9622
  width: "16",
@@ -9023,7 +9637,7 @@ function FloatingToolbar({
9023
9637
  );
9024
9638
  })
9025
9639
  ] }, gi)),
9026
- showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
9640
+ showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
9027
9641
  CustomToolbarButton,
9028
9642
  {
9029
9643
  type: "button",
@@ -9037,7 +9651,7 @@ function FloatingToolbar({
9037
9651
  e.preventDefault();
9038
9652
  e.stopPropagation();
9039
9653
  },
9040
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.Link, { className: "size-4 shrink-0", "aria-hidden": true })
9654
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react13.Link, { className: "size-4 shrink-0", "aria-hidden": true })
9041
9655
  }
9042
9656
  ) : null
9043
9657
  ] })
@@ -9054,7 +9668,7 @@ function StateToggle({
9054
9668
  states,
9055
9669
  onStateChange
9056
9670
  }) {
9057
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
9671
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
9058
9672
  ToggleGroup,
9059
9673
  {
9060
9674
  "data-ohw-state-toggle": "",
@@ -9068,7 +9682,7 @@ function StateToggle({
9068
9682
  left: rect.right - 8,
9069
9683
  transform: "translateX(-100%)"
9070
9684
  },
9071
- children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
9685
+ children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
9072
9686
  }
9073
9687
  );
9074
9688
  }
@@ -9095,8 +9709,8 @@ function OhhwellsBridge() {
9095
9709
  const router = (0, import_navigation2.useRouter)();
9096
9710
  const searchParams = (0, import_navigation2.useSearchParams)();
9097
9711
  const isEditMode = isEditSessionActive();
9098
- const [bridgeRoot, setBridgeRoot] = (0, import_react10.useState)(null);
9099
- (0, import_react10.useEffect)(() => {
9712
+ const [bridgeRoot, setBridgeRoot] = (0, import_react11.useState)(null);
9713
+ (0, import_react11.useEffect)(() => {
9100
9714
  const figtreeFontId = "ohw-figtree-font";
9101
9715
  if (!document.getElementById(figtreeFontId)) {
9102
9716
  const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
@@ -9124,99 +9738,99 @@ function OhhwellsBridge() {
9124
9738
  const subdomainFromQuery = searchParams.get("subdomain");
9125
9739
  const subdomain = resolveSubdomain(subdomainFromQuery);
9126
9740
  useLinkHrefGuardian(pathname, subdomain, isEditMode);
9127
- const postToParent2 = (0, import_react10.useCallback)((data) => {
9741
+ const postToParent2 = (0, import_react11.useCallback)((data) => {
9128
9742
  if (typeof window !== "undefined" && window.parent !== window) {
9129
9743
  window.parent.postMessage(data, "*");
9130
9744
  }
9131
9745
  }, []);
9132
- const [fetchState, setFetchState] = (0, import_react10.useState)("idle");
9133
- const autoSaveTimers = (0, import_react10.useRef)(/* @__PURE__ */ new Map());
9134
- const activeElRef = (0, import_react10.useRef)(null);
9135
- const pointerHeldRef = (0, import_react10.useRef)(false);
9136
- const selectedElRef = (0, import_react10.useRef)(null);
9137
- const selectedHrefKeyRef = (0, import_react10.useRef)(null);
9138
- const selectedFooterColAttrRef = (0, import_react10.useRef)(null);
9139
- const originalContentRef = (0, import_react10.useRef)(null);
9140
- const activeStateElRef = (0, import_react10.useRef)(null);
9141
- const parentScrollRef = (0, import_react10.useRef)(null);
9142
- const visibleViewportRef = (0, import_react10.useRef)(null);
9143
- const [dialogPortalContainer, setDialogPortalContainer] = (0, import_react10.useState)(null);
9144
- const attachVisibleViewport = (0, import_react10.useCallback)((node) => {
9746
+ const [fetchState, setFetchState] = (0, import_react11.useState)("idle");
9747
+ const autoSaveTimers = (0, import_react11.useRef)(/* @__PURE__ */ new Map());
9748
+ const activeElRef = (0, import_react11.useRef)(null);
9749
+ const pointerHeldRef = (0, import_react11.useRef)(false);
9750
+ const selectedElRef = (0, import_react11.useRef)(null);
9751
+ const selectedHrefKeyRef = (0, import_react11.useRef)(null);
9752
+ const selectedFooterColAttrRef = (0, import_react11.useRef)(null);
9753
+ const originalContentRef = (0, import_react11.useRef)(null);
9754
+ const activeStateElRef = (0, import_react11.useRef)(null);
9755
+ const parentScrollRef = (0, import_react11.useRef)(null);
9756
+ const visibleViewportRef = (0, import_react11.useRef)(null);
9757
+ const [dialogPortalContainer, setDialogPortalContainer] = (0, import_react11.useState)(null);
9758
+ const attachVisibleViewport = (0, import_react11.useCallback)((node) => {
9145
9759
  visibleViewportRef.current = node;
9146
9760
  setDialogPortalContainer(node);
9147
9761
  if (node) applyVisibleViewport(node, parentScrollRef.current);
9148
9762
  }, []);
9149
- const toolbarElRef = (0, import_react10.useRef)(null);
9150
- const glowElRef = (0, import_react10.useRef)(null);
9151
- const hoveredImageRef = (0, import_react10.useRef)(null);
9152
- const hoveredImageHasTextOverlapRef = (0, import_react10.useRef)(false);
9153
- const dragOverElRef = (0, import_react10.useRef)(null);
9154
- const [mediaHover, setMediaHover] = (0, import_react10.useState)(null);
9155
- const [carouselHover, setCarouselHover] = (0, import_react10.useState)(null);
9156
- const [uploadingRects, setUploadingRects] = (0, import_react10.useState)({});
9157
- const hoveredGapRef = (0, import_react10.useRef)(null);
9158
- const imageUnhoverTimerRef = (0, import_react10.useRef)(null);
9159
- const imageShowTimerRef = (0, import_react10.useRef)(null);
9160
- const editStylesRef = (0, import_react10.useRef)(null);
9161
- const activateRef = (0, import_react10.useRef)(() => {
9763
+ const toolbarElRef = (0, import_react11.useRef)(null);
9764
+ const glowElRef = (0, import_react11.useRef)(null);
9765
+ const hoveredImageRef = (0, import_react11.useRef)(null);
9766
+ const hoveredImageHasTextOverlapRef = (0, import_react11.useRef)(false);
9767
+ const dragOverElRef = (0, import_react11.useRef)(null);
9768
+ const [mediaHover, setMediaHover] = (0, import_react11.useState)(null);
9769
+ const [carouselHover, setCarouselHover] = (0, import_react11.useState)(null);
9770
+ const [uploadingRects, setUploadingRects] = (0, import_react11.useState)({});
9771
+ const hoveredGapRef = (0, import_react11.useRef)(null);
9772
+ const imageUnhoverTimerRef = (0, import_react11.useRef)(null);
9773
+ const imageShowTimerRef = (0, import_react11.useRef)(null);
9774
+ const editStylesRef = (0, import_react11.useRef)(null);
9775
+ const activateRef = (0, import_react11.useRef)(() => {
9162
9776
  });
9163
- const deactivateRef = (0, import_react10.useRef)(() => {
9777
+ const deactivateRef = (0, import_react11.useRef)(() => {
9164
9778
  });
9165
- const selectRef = (0, import_react10.useRef)(() => {
9779
+ const selectRef = (0, import_react11.useRef)(() => {
9166
9780
  });
9167
- const selectFrameRef = (0, import_react10.useRef)(() => {
9781
+ const selectFrameRef = (0, import_react11.useRef)(() => {
9168
9782
  });
9169
- const deselectRef = (0, import_react10.useRef)(() => {
9783
+ const deselectRef = (0, import_react11.useRef)(() => {
9170
9784
  });
9171
- const reselectNavigationItemRef = (0, import_react10.useRef)(() => {
9785
+ const reselectNavigationItemRef = (0, import_react11.useRef)(() => {
9172
9786
  });
9173
- const commitNavigationTextEditRef = (0, import_react10.useRef)(() => {
9787
+ const commitNavigationTextEditRef = (0, import_react11.useRef)(() => {
9174
9788
  });
9175
- const refreshActiveCommandsRef = (0, import_react10.useRef)(() => {
9789
+ const refreshActiveCommandsRef = (0, import_react11.useRef)(() => {
9176
9790
  });
9177
- const postToParentRef = (0, import_react10.useRef)(postToParent2);
9791
+ const postToParentRef = (0, import_react11.useRef)(postToParent2);
9178
9792
  postToParentRef.current = postToParent2;
9179
- const sectionsLoadedRef = (0, import_react10.useRef)(false);
9180
- const pendingScheduleConfigRequests = (0, import_react10.useRef)([]);
9181
- const [toolbarRect, setToolbarRect] = (0, import_react10.useState)(null);
9182
- const [toolbarVariant, setToolbarVariant] = (0, import_react10.useState)("none");
9183
- const toolbarVariantRef = (0, import_react10.useRef)("none");
9793
+ const sectionsLoadedRef = (0, import_react11.useRef)(false);
9794
+ const pendingScheduleConfigRequests = (0, import_react11.useRef)([]);
9795
+ const [toolbarRect, setToolbarRect] = (0, import_react11.useState)(null);
9796
+ const [toolbarVariant, setToolbarVariant] = (0, import_react11.useState)("none");
9797
+ const toolbarVariantRef = (0, import_react11.useRef)("none");
9184
9798
  toolbarVariantRef.current = toolbarVariant;
9185
- const [selectedIsCta, setSelectedIsCta] = (0, import_react10.useState)(false);
9186
- const [reorderHrefKey, setReorderHrefKey] = (0, import_react10.useState)(null);
9187
- const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react10.useState)(false);
9188
- const [toggleState, setToggleState] = (0, import_react10.useState)(null);
9189
- const [maxBadge, setMaxBadge] = (0, import_react10.useState)(null);
9190
- const [activeCommands, setActiveCommands] = (0, import_react10.useState)(/* @__PURE__ */ new Set());
9191
- const [sectionGap, setSectionGap] = (0, import_react10.useState)(null);
9192
- const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react10.useState)(false);
9193
- const hoveredNavContainerRef = (0, import_react10.useRef)(null);
9194
- const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0, import_react10.useState)(null);
9195
- const hoveredItemElRef = (0, import_react10.useRef)(null);
9196
- const [hoveredItemRect, setHoveredItemRect] = (0, import_react10.useState)(null);
9197
- const siblingHintElRef = (0, import_react10.useRef)(null);
9198
- const [siblingHintRect, setSiblingHintRect] = (0, import_react10.useState)(null);
9199
- const [siblingHintRects, setSiblingHintRects] = (0, import_react10.useState)([]);
9200
- const [isItemDragging, setIsItemDragging] = (0, import_react10.useState)(false);
9201
- const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react10.useState)(false);
9202
- const footerDragRef = (0, import_react10.useRef)(null);
9203
- const [footerDropSlots, setFooterDropSlots] = (0, import_react10.useState)([]);
9204
- const [activeFooterDropIndex, setActiveFooterDropIndex] = (0, import_react10.useState)(null);
9205
- const [draggedItemRect, setDraggedItemRect] = (0, import_react10.useState)(null);
9206
- const footerPointerDragRef = (0, import_react10.useRef)(null);
9207
- const suppressNextClickRef = (0, import_react10.useRef)(false);
9208
- const suppressClickUntilRef = (0, import_react10.useRef)(0);
9209
- const [linkPopover, setLinkPopover] = (0, import_react10.useState)(null);
9210
- const linkPopoverSessionRef = (0, import_react10.useRef)(null);
9211
- const addNavAfterAnchorRef = (0, import_react10.useRef)(null);
9212
- const editContentRef = (0, import_react10.useRef)({});
9213
- const [sitePages, setSitePages] = (0, import_react10.useState)([]);
9214
- const [sectionsByPath, setSectionsByPath] = (0, import_react10.useState)({});
9215
- const sectionsPrefetchGenRef = (0, import_react10.useRef)(0);
9216
- const setLinkPopoverRef = (0, import_react10.useRef)(setLinkPopover);
9217
- const linkPopoverPanelRef = (0, import_react10.useRef)(null);
9218
- const linkPopoverOpenRef = (0, import_react10.useRef)(false);
9219
- const linkPopoverGraceUntilRef = (0, import_react10.useRef)(0);
9799
+ const [selectedIsCta, setSelectedIsCta] = (0, import_react11.useState)(false);
9800
+ const [reorderHrefKey, setReorderHrefKey] = (0, import_react11.useState)(null);
9801
+ const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react11.useState)(false);
9802
+ const [toggleState, setToggleState] = (0, import_react11.useState)(null);
9803
+ const [maxBadge, setMaxBadge] = (0, import_react11.useState)(null);
9804
+ const [activeCommands, setActiveCommands] = (0, import_react11.useState)(/* @__PURE__ */ new Set());
9805
+ const [sectionGap, setSectionGap] = (0, import_react11.useState)(null);
9806
+ const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react11.useState)(false);
9807
+ const hoveredNavContainerRef = (0, import_react11.useRef)(null);
9808
+ const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0, import_react11.useState)(null);
9809
+ const hoveredItemElRef = (0, import_react11.useRef)(null);
9810
+ const [hoveredItemRect, setHoveredItemRect] = (0, import_react11.useState)(null);
9811
+ const siblingHintElRef = (0, import_react11.useRef)(null);
9812
+ const [siblingHintRect, setSiblingHintRect] = (0, import_react11.useState)(null);
9813
+ const [siblingHintRects, setSiblingHintRects] = (0, import_react11.useState)([]);
9814
+ const [isItemDragging, setIsItemDragging] = (0, import_react11.useState)(false);
9815
+ const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react11.useState)(false);
9816
+ const footerDragRef = (0, import_react11.useRef)(null);
9817
+ const [footerDropSlots, setFooterDropSlots] = (0, import_react11.useState)([]);
9818
+ const [activeFooterDropIndex, setActiveFooterDropIndex] = (0, import_react11.useState)(null);
9819
+ const [draggedItemRect, setDraggedItemRect] = (0, import_react11.useState)(null);
9820
+ const footerPointerDragRef = (0, import_react11.useRef)(null);
9821
+ const suppressNextClickRef = (0, import_react11.useRef)(false);
9822
+ const suppressClickUntilRef = (0, import_react11.useRef)(0);
9823
+ const [linkPopover, setLinkPopover] = (0, import_react11.useState)(null);
9824
+ const linkPopoverSessionRef = (0, import_react11.useRef)(null);
9825
+ const addNavAfterAnchorRef = (0, import_react11.useRef)(null);
9826
+ const editContentRef = (0, import_react11.useRef)({});
9827
+ const [sitePages, setSitePages] = (0, import_react11.useState)([]);
9828
+ const [sectionsByPath, setSectionsByPath] = (0, import_react11.useState)({});
9829
+ const sectionsPrefetchGenRef = (0, import_react11.useRef)(0);
9830
+ const setLinkPopoverRef = (0, import_react11.useRef)(setLinkPopover);
9831
+ const linkPopoverPanelRef = (0, import_react11.useRef)(null);
9832
+ const linkPopoverOpenRef = (0, import_react11.useRef)(false);
9833
+ const linkPopoverGraceUntilRef = (0, import_react11.useRef)(0);
9220
9834
  setLinkPopoverRef.current = setLinkPopover;
9221
9835
  linkPopoverSessionRef.current = linkPopover;
9222
9836
  const {
@@ -9255,7 +9869,7 @@ function OhhwellsBridge() {
9255
9869
  const bumpLinkPopoverGrace = () => {
9256
9870
  linkPopoverGraceUntilRef.current = Date.now() + 350;
9257
9871
  };
9258
- const runSectionsPrefetch = (0, import_react10.useCallback)((pages) => {
9872
+ const runSectionsPrefetch = (0, import_react11.useCallback)((pages) => {
9259
9873
  if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
9260
9874
  const gen = ++sectionsPrefetchGenRef.current;
9261
9875
  const paths = pages.map((p) => p.path);
@@ -9274,9 +9888,9 @@ function OhhwellsBridge() {
9274
9888
  );
9275
9889
  });
9276
9890
  }, [isEditMode, pathname]);
9277
- const runSectionsPrefetchRef = (0, import_react10.useRef)(runSectionsPrefetch);
9891
+ const runSectionsPrefetchRef = (0, import_react11.useRef)(runSectionsPrefetch);
9278
9892
  runSectionsPrefetchRef.current = runSectionsPrefetch;
9279
- (0, import_react10.useEffect)(() => {
9893
+ (0, import_react11.useEffect)(() => {
9280
9894
  if (!linkPopover) {
9281
9895
  document.documentElement.removeAttribute("data-ohw-link-popover-open");
9282
9896
  return;
@@ -9326,7 +9940,7 @@ function OhhwellsBridge() {
9326
9940
  document.removeEventListener("touchmove", preventBackgroundScroll, scrollOpts);
9327
9941
  };
9328
9942
  }, [linkPopover, postToParent2]);
9329
- (0, import_react10.useEffect)(() => {
9943
+ (0, import_react11.useEffect)(() => {
9330
9944
  if (!isEditMode) return;
9331
9945
  const useFixtures = shouldUseDevFixtures();
9332
9946
  if (useFixtures) {
@@ -9350,14 +9964,14 @@ function OhhwellsBridge() {
9350
9964
  if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
9351
9965
  return () => window.removeEventListener("message", onSitePages);
9352
9966
  }, [isEditMode, postToParent2]);
9353
- (0, import_react10.useEffect)(() => {
9967
+ (0, import_react11.useEffect)(() => {
9354
9968
  if (!isEditMode || shouldUseDevFixtures()) return;
9355
9969
  void loadAllSectionsManifest().then((manifest) => {
9356
9970
  if (Object.keys(manifest).length === 0) return;
9357
9971
  setSectionsByPath((prev) => ({ ...manifest, ...prev }));
9358
9972
  });
9359
9973
  }, [isEditMode]);
9360
- (0, import_react10.useEffect)(() => {
9974
+ (0, import_react11.useEffect)(() => {
9361
9975
  const update = () => {
9362
9976
  const el = activeElRef.current ?? selectedElRef.current;
9363
9977
  if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
@@ -9381,10 +9995,10 @@ function OhhwellsBridge() {
9381
9995
  vvp.removeEventListener("resize", update);
9382
9996
  };
9383
9997
  }, []);
9384
- const refreshStateRules = (0, import_react10.useCallback)(() => {
9998
+ const refreshStateRules = (0, import_react11.useCallback)(() => {
9385
9999
  editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
9386
10000
  }, []);
9387
- const processConfigRequest = (0, import_react10.useCallback)((insertAfterVal) => {
10001
+ const processConfigRequest = (0, import_react11.useCallback)((insertAfterVal) => {
9388
10002
  const tracker = getSectionsTracker();
9389
10003
  let entries = [];
9390
10004
  try {
@@ -9407,7 +10021,7 @@ function OhhwellsBridge() {
9407
10021
  }
9408
10022
  window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
9409
10023
  }, [isEditMode]);
9410
- const deactivate = (0, import_react10.useCallback)(() => {
10024
+ const deactivate = (0, import_react11.useCallback)(() => {
9411
10025
  const el = activeElRef.current;
9412
10026
  if (!el) return;
9413
10027
  const key = el.dataset.ohwKey;
@@ -9439,12 +10053,12 @@ function OhhwellsBridge() {
9439
10053
  setToolbarShowEditLink(false);
9440
10054
  postToParent2({ type: "ow:exit-edit" });
9441
10055
  }, [postToParent2]);
9442
- const clearSelectedAttr = (0, import_react10.useCallback)(() => {
10056
+ const clearSelectedAttr = (0, import_react11.useCallback)(() => {
9443
10057
  document.querySelectorAll("[data-ohw-selected]").forEach((el) => {
9444
10058
  el.removeAttribute("data-ohw-selected");
9445
10059
  });
9446
10060
  }, []);
9447
- const deselect = (0, import_react10.useCallback)(() => {
10061
+ const deselect = (0, import_react11.useCallback)(() => {
9448
10062
  clearSelectedAttr();
9449
10063
  selectedElRef.current = null;
9450
10064
  selectedHrefKeyRef.current = null;
@@ -9464,11 +10078,11 @@ function OhhwellsBridge() {
9464
10078
  setToolbarVariant("none");
9465
10079
  }
9466
10080
  }, [clearSelectedAttr]);
9467
- const markSelected = (0, import_react10.useCallback)((el) => {
10081
+ const markSelected = (0, import_react11.useCallback)((el) => {
9468
10082
  clearSelectedAttr();
9469
10083
  el.setAttribute("data-ohw-selected", "");
9470
10084
  }, [clearSelectedAttr]);
9471
- const resolveHrefKeyElement = (0, import_react10.useCallback)((hrefKey) => {
10085
+ const resolveHrefKeyElement = (0, import_react11.useCallback)((hrefKey) => {
9472
10086
  if (isFooterHrefKey(hrefKey)) {
9473
10087
  return document.querySelector(
9474
10088
  `footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
@@ -9483,7 +10097,7 @@ function OhhwellsBridge() {
9483
10097
  `[data-ohw-href-key="${CSS.escape(hrefKey)}"]`
9484
10098
  );
9485
10099
  }, []);
9486
- const resyncSelectedNavigationItem = (0, import_react10.useCallback)(() => {
10100
+ const resyncSelectedNavigationItem = (0, import_react11.useCallback)(() => {
9487
10101
  const hrefKey = selectedHrefKeyRef.current;
9488
10102
  if (hrefKey) {
9489
10103
  const link = resolveHrefKeyElement(hrefKey);
@@ -9511,7 +10125,7 @@ function OhhwellsBridge() {
9511
10125
  );
9512
10126
  }
9513
10127
  }, [resolveHrefKeyElement]);
9514
- const reselectNavigationItem = (0, import_react10.useCallback)((navAnchor) => {
10128
+ const reselectNavigationItem = (0, import_react11.useCallback)((navAnchor) => {
9515
10129
  selectedElRef.current = navAnchor;
9516
10130
  selectedHrefKeyRef.current = navAnchor.getAttribute("data-ohw-href-key");
9517
10131
  selectedFooterColAttrRef.current = null;
@@ -9526,7 +10140,7 @@ function OhhwellsBridge() {
9526
10140
  setToolbarShowEditLink(false);
9527
10141
  setActiveCommands(/* @__PURE__ */ new Set());
9528
10142
  }, [markSelected]);
9529
- const commitNavigationTextEdit = (0, import_react10.useCallback)((navAnchor) => {
10143
+ const commitNavigationTextEdit = (0, import_react11.useCallback)((navAnchor) => {
9530
10144
  const el = activeElRef.current;
9531
10145
  if (!el) return;
9532
10146
  const key = el.dataset.ohwKey;
@@ -9553,7 +10167,7 @@ function OhhwellsBridge() {
9553
10167
  postToParent2({ type: "ow:exit-edit" });
9554
10168
  reselectNavigationItem(navAnchor);
9555
10169
  }, [postToParent2, reselectNavigationItem]);
9556
- const handleAddTopLevelNavItem = (0, import_react10.useCallback)(() => {
10170
+ const handleAddTopLevelNavItem = (0, import_react11.useCallback)(() => {
9557
10171
  const items = listNavbarItems();
9558
10172
  addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
9559
10173
  deselectRef.current();
@@ -9565,7 +10179,19 @@ function OhhwellsBridge() {
9565
10179
  intent: "add-nav"
9566
10180
  });
9567
10181
  }, []);
9568
- const clearFooterDragVisuals = (0, import_react10.useCallback)(() => {
10182
+ const handleAddFooterColumn = (0, import_react11.useCallback)(() => {
10183
+ deselectRef.current();
10184
+ deactivateRef.current();
10185
+ const result = addFooterColumnWithPersist({ postToParent: postToParent2 });
10186
+ editContentRef.current = {
10187
+ ...editContentRef.current,
10188
+ ...buildFooterColumnEditContentPatch(result)
10189
+ };
10190
+ requestAnimationFrame(() => {
10191
+ selectRef.current(result.firstLink);
10192
+ });
10193
+ }, [postToParent2]);
10194
+ const clearFooterDragVisuals = (0, import_react11.useCallback)(() => {
9569
10195
  footerDragRef.current = null;
9570
10196
  setSiblingHintRects([]);
9571
10197
  setFooterDropSlots([]);
@@ -9574,7 +10200,7 @@ function OhhwellsBridge() {
9574
10200
  setIsItemDragging(false);
9575
10201
  unlockFooterDragInteraction();
9576
10202
  }, []);
9577
- const refreshFooterDragVisuals = (0, import_react10.useCallback)((session, activeSlot, clientX, clientY) => {
10203
+ const refreshFooterDragVisuals = (0, import_react11.useCallback)((session, activeSlot, clientX, clientY) => {
9578
10204
  const dragged = session.draggedEl;
9579
10205
  setDraggedItemRect(dragged.getBoundingClientRect());
9580
10206
  if (typeof clientX === "number" && typeof clientY === "number") {
@@ -9599,13 +10225,13 @@ function OhhwellsBridge() {
9599
10225
  const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
9600
10226
  setActiveFooterDropIndex(activeIdx >= 0 ? activeIdx : null);
9601
10227
  }, []);
9602
- const refreshFooterDragVisualsRef = (0, import_react10.useRef)(refreshFooterDragVisuals);
10228
+ const refreshFooterDragVisualsRef = (0, import_react11.useRef)(refreshFooterDragVisuals);
9603
10229
  refreshFooterDragVisualsRef.current = refreshFooterDragVisuals;
9604
- const commitFooterDragRef = (0, import_react10.useRef)(() => {
10230
+ const commitFooterDragRef = (0, import_react11.useRef)(() => {
9605
10231
  });
9606
- const beginFooterDragRef = (0, import_react10.useRef)(() => {
10232
+ const beginFooterDragRef = (0, import_react11.useRef)(() => {
9607
10233
  });
9608
- const beginFooterDrag = (0, import_react10.useCallback)(
10234
+ const beginFooterDrag = (0, import_react11.useCallback)(
9609
10235
  (session) => {
9610
10236
  const rect = session.draggedEl.getBoundingClientRect();
9611
10237
  session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
@@ -9625,7 +10251,7 @@ function OhhwellsBridge() {
9625
10251
  [refreshFooterDragVisuals]
9626
10252
  );
9627
10253
  beginFooterDragRef.current = beginFooterDrag;
9628
- const commitFooterDrag = (0, import_react10.useCallback)(
10254
+ const commitFooterDrag = (0, import_react11.useCallback)(
9629
10255
  (clientX, clientY) => {
9630
10256
  const session = footerDragRef.current;
9631
10257
  if (!session) {
@@ -9729,7 +10355,7 @@ function OhhwellsBridge() {
9729
10355
  [clearFooterDragVisuals, resolveHrefKeyElement, resyncSelectedNavigationItem]
9730
10356
  );
9731
10357
  commitFooterDragRef.current = commitFooterDrag;
9732
- const startFooterLinkDrag = (0, import_react10.useCallback)(
10358
+ const startFooterLinkDrag = (0, import_react11.useCallback)(
9733
10359
  (anchor, clientX, clientY, wasSelected) => {
9734
10360
  const hrefKey = anchor.getAttribute("data-ohw-href-key");
9735
10361
  if (!hrefKey || !isFooterHrefKey(hrefKey)) return false;
@@ -9750,7 +10376,7 @@ function OhhwellsBridge() {
9750
10376
  },
9751
10377
  [beginFooterDrag]
9752
10378
  );
9753
- const startFooterColumnDrag = (0, import_react10.useCallback)(
10379
+ const startFooterColumnDrag = (0, import_react11.useCallback)(
9754
10380
  (columnEl, clientX, clientY, wasSelected) => {
9755
10381
  const columns = listFooterColumns();
9756
10382
  const idx = columns.indexOf(columnEl);
@@ -9770,7 +10396,7 @@ function OhhwellsBridge() {
9770
10396
  },
9771
10397
  [beginFooterDrag]
9772
10398
  );
9773
- const handleItemDragStart = (0, import_react10.useCallback)(
10399
+ const handleItemDragStart = (0, import_react11.useCallback)(
9774
10400
  (e) => {
9775
10401
  const selected = selectedElRef.current;
9776
10402
  if (!selected) {
@@ -9790,7 +10416,7 @@ function OhhwellsBridge() {
9790
10416
  },
9791
10417
  [startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag]
9792
10418
  );
9793
- const handleItemDragEnd = (0, import_react10.useCallback)(
10419
+ const handleItemDragEnd = (0, import_react11.useCallback)(
9794
10420
  (e) => {
9795
10421
  if (footerDragRef.current) {
9796
10422
  const x = e?.clientX;
@@ -9816,7 +10442,7 @@ function OhhwellsBridge() {
9816
10442
  },
9817
10443
  [commitFooterDrag, commitNavDrag, navDragRef]
9818
10444
  );
9819
- const handleItemChromePointerDown = (0, import_react10.useCallback)((e) => {
10445
+ const handleItemChromePointerDown = (0, import_react11.useCallback)((e) => {
9820
10446
  if (e.button !== 0) return;
9821
10447
  const selected = selectedElRef.current;
9822
10448
  if (!selected) return;
@@ -9847,7 +10473,7 @@ function OhhwellsBridge() {
9847
10473
  }
9848
10474
  if (armNavPressFromChrome(selected, e.clientX, e.clientY, e.pointerId)) return;
9849
10475
  }, [armNavPressFromChrome]);
9850
- const handleItemChromeClick = (0, import_react10.useCallback)((clientX, clientY) => {
10476
+ const handleItemChromeClick = (0, import_react11.useCallback)((clientX, clientY) => {
9851
10477
  if (suppressNextClickRef.current || Date.now() < suppressClickUntilRef.current) {
9852
10478
  suppressNextClickRef.current = false;
9853
10479
  return;
@@ -9860,7 +10486,7 @@ function OhhwellsBridge() {
9860
10486
  }, []);
9861
10487
  reselectNavigationItemRef.current = reselectNavigationItem;
9862
10488
  commitNavigationTextEditRef.current = commitNavigationTextEdit;
9863
- const select = (0, import_react10.useCallback)((anchor) => {
10489
+ const select = (0, import_react11.useCallback)((anchor) => {
9864
10490
  if (!isNavigationItem(anchor)) return;
9865
10491
  if (activeElRef.current) deactivate();
9866
10492
  selectedElRef.current = anchor;
@@ -9886,10 +10512,10 @@ function OhhwellsBridge() {
9886
10512
  setToolbarShowEditLink(false);
9887
10513
  setActiveCommands(/* @__PURE__ */ new Set());
9888
10514
  }, [deactivate, markSelected]);
9889
- const selectFrame = (0, import_react10.useCallback)((el) => {
10515
+ const selectFrame = (0, import_react11.useCallback)((el) => {
9890
10516
  if (!isNavigationContainer(el)) return;
9891
10517
  if (activeElRef.current) deactivate();
9892
- const isFooterColumn = el.hasAttribute("data-ohw-footer-col") || Boolean(el.closest("footer") && isInferredFooterGroup(el));
10518
+ const isFooterColumn = !isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || Boolean(el.closest("footer") && isInferredFooterGroup(el)));
9893
10519
  selectedElRef.current = el;
9894
10520
  selectedHrefKeyRef.current = null;
9895
10521
  selectedFooterColAttrRef.current = isFooterColumn ? el.getAttribute("data-ohw-footer-col") ?? String(listFooterColumns().indexOf(el)) : null;
@@ -9914,7 +10540,7 @@ function OhhwellsBridge() {
9914
10540
  setToolbarShowEditLink(false);
9915
10541
  setActiveCommands(/* @__PURE__ */ new Set());
9916
10542
  }, [deactivate, markSelected]);
9917
- const activate = (0, import_react10.useCallback)((el, options) => {
10543
+ const activate = (0, import_react11.useCallback)((el, options) => {
9918
10544
  if (activeElRef.current === el) return;
9919
10545
  clearSelectedAttr();
9920
10546
  selectedElRef.current = null;
@@ -9979,7 +10605,7 @@ function OhhwellsBridge() {
9979
10605
  selectRef.current = select;
9980
10606
  selectFrameRef.current = selectFrame;
9981
10607
  deselectRef.current = deselect;
9982
- (0, import_react10.useLayoutEffect)(() => {
10608
+ (0, import_react11.useLayoutEffect)(() => {
9983
10609
  if (!subdomain || isEditMode) {
9984
10610
  setFetchState("done");
9985
10611
  return;
@@ -10050,7 +10676,7 @@ function OhhwellsBridge() {
10050
10676
  cancelled = true;
10051
10677
  };
10052
10678
  }, [subdomain, isEditMode]);
10053
- (0, import_react10.useEffect)(() => {
10679
+ (0, import_react11.useEffect)(() => {
10054
10680
  if (!subdomain || isEditMode) return;
10055
10681
  let debounceTimer = null;
10056
10682
  let observer = null;
@@ -10101,16 +10727,16 @@ function OhhwellsBridge() {
10101
10727
  if (debounceTimer) clearTimeout(debounceTimer);
10102
10728
  };
10103
10729
  }, [subdomain, isEditMode, pathname]);
10104
- (0, import_react10.useLayoutEffect)(() => {
10730
+ (0, import_react11.useLayoutEffect)(() => {
10105
10731
  const el = document.getElementById("ohw-loader");
10106
10732
  if (!el) return;
10107
10733
  const visible = Boolean(subdomain) && fetchState !== "done";
10108
10734
  el.style.display = visible ? "flex" : "none";
10109
10735
  }, [subdomain, fetchState]);
10110
- (0, import_react10.useEffect)(() => {
10736
+ (0, import_react11.useEffect)(() => {
10111
10737
  postToParent2({ type: "ow:navigation", path: pathname });
10112
10738
  }, [pathname, postToParent2]);
10113
- (0, import_react10.useEffect)(() => {
10739
+ (0, import_react11.useEffect)(() => {
10114
10740
  if (!isEditMode) return;
10115
10741
  if (linkPopoverSessionRef.current?.intent === "add-nav") return;
10116
10742
  if (document.querySelector("[data-ohw-section-picker]")) return;
@@ -10118,7 +10744,7 @@ function OhhwellsBridge() {
10118
10744
  deselectRef.current();
10119
10745
  deactivateRef.current();
10120
10746
  }, [pathname, isEditMode]);
10121
- (0, import_react10.useEffect)(() => {
10747
+ (0, import_react11.useEffect)(() => {
10122
10748
  const contentForNav = () => {
10123
10749
  if (isEditMode) return editContentRef.current;
10124
10750
  if (!subdomain) return {};
@@ -10183,7 +10809,7 @@ function OhhwellsBridge() {
10183
10809
  observer?.disconnect();
10184
10810
  };
10185
10811
  }, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
10186
- (0, import_react10.useEffect)(() => {
10812
+ (0, import_react11.useEffect)(() => {
10187
10813
  if (!isEditMode) return;
10188
10814
  const measure = () => {
10189
10815
  const h = document.body.scrollHeight;
@@ -10207,7 +10833,7 @@ function OhhwellsBridge() {
10207
10833
  window.removeEventListener("resize", handleResize);
10208
10834
  };
10209
10835
  }, [pathname, isEditMode, postToParent2]);
10210
- (0, import_react10.useEffect)(() => {
10836
+ (0, import_react11.useEffect)(() => {
10211
10837
  if (!subdomainFromQuery || isEditMode) return;
10212
10838
  const handleClick = (e) => {
10213
10839
  const anchor = e.target.closest("a");
@@ -10223,7 +10849,7 @@ function OhhwellsBridge() {
10223
10849
  document.addEventListener("click", handleClick, true);
10224
10850
  return () => document.removeEventListener("click", handleClick, true);
10225
10851
  }, [subdomainFromQuery, isEditMode, router]);
10226
- (0, import_react10.useEffect)(() => {
10852
+ (0, import_react11.useEffect)(() => {
10227
10853
  if (!isEditMode) {
10228
10854
  editStylesRef.current?.base.remove();
10229
10855
  editStylesRef.current?.forceHover.remove();
@@ -10422,7 +11048,7 @@ function OhhwellsBridge() {
10422
11048
  setLinkPopoverRef.current({
10423
11049
  key: editable.dataset.ohwKey ?? "",
10424
11050
  mode: "edit",
10425
- target: getLinkHref2(editable)
11051
+ target: getLinkHref3(editable)
10426
11052
  });
10427
11053
  return;
10428
11054
  }
@@ -10447,7 +11073,7 @@ function OhhwellsBridge() {
10447
11073
  }
10448
11074
  e.preventDefault();
10449
11075
  e.stopPropagation();
10450
- activateRef.current(editable);
11076
+ activateRef.current(editable, { caretX: e.clientX, caretY: e.clientY });
10451
11077
  return;
10452
11078
  }
10453
11079
  const hrefAnchor = getNavigationItemAnchor(target);
@@ -10474,6 +11100,18 @@ function OhhwellsBridge() {
10474
11100
  selectFrameRef.current(footerColClick);
10475
11101
  return;
10476
11102
  }
11103
+ const footerLinksToSelect = resolveFooterLinksContainerSelectionTarget(
11104
+ target,
11105
+ e.clientX,
11106
+ e.clientY,
11107
+ isPointOverNavItem
11108
+ );
11109
+ if (footerLinksToSelect) {
11110
+ e.preventDefault();
11111
+ e.stopPropagation();
11112
+ selectFrameRef.current(footerLinksToSelect);
11113
+ return;
11114
+ }
10477
11115
  const navContainerToSelect = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
10478
11116
  if (navContainerToSelect) {
10479
11117
  e.preventDefault();
@@ -10532,8 +11170,8 @@ function OhhwellsBridge() {
10532
11170
  return;
10533
11171
  }
10534
11172
  const navLabel = getNavigationLabelEditable(target);
10535
- if (!navLabel) return;
10536
- const { editable } = navLabel;
11173
+ const editable = navLabel?.editable ?? target.closest('[data-ohw-editable="text"], [data-ohw-editable="plain"]');
11174
+ if (!editable || isMediaEditable(editable) || editable.dataset.ohwEditable === "link") return;
10537
11175
  e.preventDefault();
10538
11176
  e.stopPropagation();
10539
11177
  if (activeElRef.current !== editable) {
@@ -10554,16 +11192,38 @@ function OhhwellsBridge() {
10554
11192
  setHoveredNavContainerRect(null);
10555
11193
  return;
10556
11194
  }
10557
- if (toolbarVariantRef.current !== "select-frame") {
10558
- const navContainer = target.closest("[data-ohw-nav-container]");
10559
- if (navContainer && !getNavigationItemAnchor(target)) {
10560
- hoveredNavContainerRef.current = navContainer;
10561
- setHoveredNavContainerRect(navContainer.getBoundingClientRect());
10562
- hoveredItemElRef.current = null;
10563
- setHoveredItemRect(null);
10564
- return;
11195
+ {
11196
+ const selected2 = selectedElRef.current;
11197
+ const selectedIsFooterColumn = Boolean(selected2) && !isFooterLinksContainer(selected2) && (selected2.hasAttribute("data-ohw-footer-col") || selected2.hasAttribute("data-ohw-footer-column") || Boolean(selected2.closest("footer") && isInferredFooterGroup(selected2)));
11198
+ const allowNavContainerHover = toolbarVariantRef.current !== "select-frame";
11199
+ const allowFooterLinksHover = toolbarVariantRef.current !== "select-frame" || selectedIsFooterColumn;
11200
+ if (allowNavContainerHover) {
11201
+ const navContainer = target.closest("[data-ohw-nav-container]");
11202
+ if (navContainer && !getNavigationItemAnchor(target)) {
11203
+ hoveredNavContainerRef.current = navContainer;
11204
+ setHoveredNavContainerRect(navContainer.getBoundingClientRect());
11205
+ hoveredItemElRef.current = null;
11206
+ setHoveredItemRect(null);
11207
+ return;
11208
+ }
10565
11209
  }
10566
- if (!target.closest("[data-ohw-nav-container]")) {
11210
+ if (allowFooterLinksHover) {
11211
+ const navContainer = target.closest("[data-ohw-nav-container]");
11212
+ if (!navContainer) {
11213
+ const footerLinks = target.closest("[data-ohw-footer-links], .rb-footer-links") ?? null;
11214
+ if (footerLinks && selected2 !== footerLinks && !getNavigationItemAnchor(target) && !target.closest("[data-ohw-footer-col], [data-ohw-footer-column]")) {
11215
+ hoveredNavContainerRef.current = footerLinks;
11216
+ setHoveredNavContainerRect(footerLinks.getBoundingClientRect());
11217
+ hoveredItemElRef.current = null;
11218
+ setHoveredItemRect(null);
11219
+ return;
11220
+ }
11221
+ if (!footerLinks) {
11222
+ hoveredNavContainerRef.current = null;
11223
+ setHoveredNavContainerRect(null);
11224
+ }
11225
+ }
11226
+ } else if (toolbarVariantRef.current === "select-frame") {
10567
11227
  hoveredNavContainerRef.current = null;
10568
11228
  setHoveredNavContainerRect(null);
10569
11229
  }
@@ -10605,9 +11265,9 @@ function OhhwellsBridge() {
10605
11265
  };
10606
11266
  const handleMouseOut = (e) => {
10607
11267
  const target = e.target;
10608
- if (target.closest("[data-ohw-nav-container], [data-ohw-footer-col], [data-ohw-footer-column]")) {
11268
+ if (target.closest("[data-ohw-nav-container], [data-ohw-footer-col], [data-ohw-footer-column], [data-ohw-footer-links], .rb-footer-links")) {
10609
11269
  const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
10610
- 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]")) {
11270
+ 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]")) {
10611
11271
  return;
10612
11272
  }
10613
11273
  hoveredNavContainerRef.current = null;
@@ -10702,6 +11362,15 @@ function OhhwellsBridge() {
10702
11362
  if (track) track.setAttribute("data-ohw-hover-paused", "");
10703
11363
  };
10704
11364
  const clearImageHover = () => setMediaHover(null);
11365
+ const dismissImageHover = () => {
11366
+ if (hoveredImageRef.current) {
11367
+ hoveredImageRef.current = null;
11368
+ hoveredImageHasTextOverlapRef.current = false;
11369
+ resumeAnimTracks();
11370
+ postToParentRef.current({ type: "ow:image-unhover" });
11371
+ }
11372
+ clearImageHover();
11373
+ };
10705
11374
  const findImageAtPoint = (clientX, clientY, fromParentViewport) => {
10706
11375
  const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
10707
11376
  const images = Array.from(document.querySelectorAll(MEDIA_SELECTOR));
@@ -10745,16 +11414,13 @@ function OhhwellsBridge() {
10745
11414
  }
10746
11415
  return smallest;
10747
11416
  };
10748
- const dismissImageHover = () => {
10749
- if (hoveredImageRef.current) {
10750
- hoveredImageRef.current = null;
10751
- hoveredImageHasTextOverlapRef.current = false;
10752
- resumeAnimTracks();
10753
- postToParentRef.current({ type: "ow:image-unhover" });
10754
- }
10755
- };
10756
11417
  const probeNavigationHoverAt = (x, y) => {
10757
- if (toolbarVariantRef.current === "select-frame") {
11418
+ const selected = selectedElRef.current;
11419
+ const selectedIsFooterColumn = Boolean(selected) && !isFooterLinksContainer(selected) && (selected.hasAttribute("data-ohw-footer-col") || selected.hasAttribute("data-ohw-footer-column") || Boolean(selected.closest("footer") && isInferredFooterGroup(selected)));
11420
+ const selectedIsFooterLinks = Boolean(selected && isFooterLinksContainer(selected));
11421
+ const allowNavContainerHover = toolbarVariantRef.current !== "select-frame";
11422
+ const allowFooterLinksHover = (toolbarVariantRef.current !== "select-frame" || selectedIsFooterColumn) && !selectedIsFooterLinks;
11423
+ if (toolbarVariantRef.current === "select-frame" && !allowFooterLinksHover) {
10758
11424
  hoveredNavContainerRef.current = null;
10759
11425
  setHoveredNavContainerRect(null);
10760
11426
  }
@@ -10776,7 +11442,6 @@ function OhhwellsBridge() {
10776
11442
  if (navItemHit) {
10777
11443
  hoveredNavContainerRef.current = null;
10778
11444
  setHoveredNavContainerRect(null);
10779
- const selected = selectedElRef.current;
10780
11445
  if (selected !== navItemHit) {
10781
11446
  clearHrefKeyHover(navItemHit);
10782
11447
  hoveredItemElRef.current = navItemHit;
@@ -10788,7 +11453,7 @@ function OhhwellsBridge() {
10788
11453
  return;
10789
11454
  }
10790
11455
  }
10791
- if (toolbarVariantRef.current !== "select-frame") {
11456
+ if (allowNavContainerHover) {
10792
11457
  for (const container of navContainers) {
10793
11458
  const containerRect = container.getBoundingClientRect();
10794
11459
  const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
@@ -10800,12 +11465,23 @@ function OhhwellsBridge() {
10800
11465
  setHoveredItemRect(null);
10801
11466
  return;
10802
11467
  }
10803
- hoveredNavContainerRef.current = null;
10804
- setHoveredNavContainerRect(null);
10805
- } else {
10806
- hoveredNavContainerRef.current = null;
10807
- setHoveredNavContainerRect(null);
10808
11468
  }
11469
+ if (allowFooterLinksHover) {
11470
+ const footerLinks = getFooterLinksContainer();
11471
+ if (footerLinks) {
11472
+ const containerRect = footerLinks.getBoundingClientRect();
11473
+ const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
11474
+ if (overContainer && !isPointOverNavItem(footerLinks, x, y) && !isPointOverFooterColumn(x, y)) {
11475
+ hoveredNavContainerRef.current = footerLinks;
11476
+ setHoveredNavContainerRect(footerLinks.getBoundingClientRect());
11477
+ hoveredItemElRef.current = null;
11478
+ setHoveredItemRect(null);
11479
+ return;
11480
+ }
11481
+ }
11482
+ }
11483
+ hoveredNavContainerRef.current = null;
11484
+ setHoveredNavContainerRect(null);
10809
11485
  for (const column of footerColumns) {
10810
11486
  const containerRect = column.getBoundingClientRect();
10811
11487
  const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
@@ -10844,6 +11520,13 @@ function OhhwellsBridge() {
10844
11520
  probeNavigationHoverAt(x, y);
10845
11521
  return;
10846
11522
  }
11523
+ const overMoreMenu = document.elementFromPoint(x, y)?.closest?.(
11524
+ '[data-ohw-more-menu], [data-slot="dropdown-menu-content"], [data-slot="dropdown-menu-item"]'
11525
+ );
11526
+ if (overMoreMenu) {
11527
+ dismissImageHover();
11528
+ return;
11529
+ }
10847
11530
  hoveredNavContainerRef.current = null;
10848
11531
  setHoveredNavContainerRect(null);
10849
11532
  if (hoveredItemElRef.current?.hasAttribute("data-ohw-footer-col") || hoveredItemElRef.current?.hasAttribute("data-ohw-footer-column")) {
@@ -10890,7 +11573,7 @@ function OhhwellsBridge() {
10890
11573
  return;
10891
11574
  }
10892
11575
  const topEl = document.elementFromPoint(x2, y2);
10893
- if (topEl?.closest('[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
11576
+ if (topEl?.closest('[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"], [data-ohw-more-menu], [data-slot="dropdown-menu-content"], [data-slot="dropdown-menu-item"]')) {
10894
11577
  if (hoveredImageRef.current) {
10895
11578
  hoveredImageRef.current = null;
10896
11579
  resumeAnimTracks();
@@ -11067,6 +11750,7 @@ function OhhwellsBridge() {
11067
11750
  const ZONE = 20;
11068
11751
  for (let i = 0; i < sections.length; i++) {
11069
11752
  const a = sections[i];
11753
+ if (a.dataset.ohwSection === "footer") continue;
11070
11754
  const b = sections[i + 1] ?? null;
11071
11755
  const boundaryY = a.getBoundingClientRect().bottom;
11072
11756
  if (Math.abs(y - boundaryY) <= ZONE) {
@@ -11313,6 +11997,7 @@ function OhhwellsBridge() {
11313
11997
  }
11314
11998
  editContentRef.current = { ...editContentRef.current, ...content };
11315
11999
  reconcileNavbarItemsFromContent(editContentRef.current);
12000
+ reconcileFooterOrderFromContent(editContentRef.current);
11316
12001
  syncNavigationDragCursorAttrs();
11317
12002
  enforceLinkHrefs();
11318
12003
  postToParentRef.current({ type: "ow:hydrate-done" });
@@ -11332,6 +12017,7 @@ function OhhwellsBridge() {
11332
12017
  window.addEventListener("message", handleDeactivate);
11333
12018
  const handleUiEscape = (e) => {
11334
12019
  if (e.data?.type !== "ui:escape") return;
12020
+ if (document.querySelector("[data-ohw-more-menu]")) return;
11335
12021
  if (linkPopoverOpenRef.current) {
11336
12022
  setLinkPopoverRef.current(null);
11337
12023
  return;
@@ -11367,6 +12053,11 @@ function OhhwellsBridge() {
11367
12053
  }
11368
12054
  if (selectedElRef.current) {
11369
12055
  if (toolbarVariantRef.current === "select-frame") {
12056
+ const parent2 = getNavigationSelectionParent(selectedElRef.current);
12057
+ if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
12058
+ selectFrameRef.current(parent2);
12059
+ return;
12060
+ }
11370
12061
  deselectRef.current();
11371
12062
  return;
11372
12063
  }
@@ -11381,14 +12072,12 @@ function OhhwellsBridge() {
11381
12072
  window.addEventListener("message", handleUiEscape);
11382
12073
  const handleKeyDown = (e) => {
11383
12074
  if (e.key === "Escape" && document.querySelector("[data-ohw-section-picker]")) return;
12075
+ if (e.key === "Escape" && document.querySelector("[data-ohw-more-menu]")) return;
11384
12076
  if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "a" && activeElRef.current) {
11385
- const navAnchor = getNavigationItemAnchor(activeElRef.current);
11386
- if (navAnchor) {
11387
- e.preventDefault();
11388
- selectAllTextInEditable(activeElRef.current);
11389
- refreshActiveCommandsRef.current();
11390
- return;
11391
- }
12077
+ e.preventDefault();
12078
+ selectAllTextInEditable(activeElRef.current);
12079
+ refreshActiveCommandsRef.current();
12080
+ return;
11392
12081
  }
11393
12082
  if (e.key === "Escape" && linkPopoverOpenRef.current) {
11394
12083
  setLinkPopoverRef.current(null);
@@ -11396,6 +12085,12 @@ function OhhwellsBridge() {
11396
12085
  }
11397
12086
  if (e.key === "Escape" && selectedElRef.current && !activeElRef.current) {
11398
12087
  if (toolbarVariantRef.current === "select-frame") {
12088
+ const parent2 = getNavigationSelectionParent(selectedElRef.current);
12089
+ if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
12090
+ e.preventDefault();
12091
+ selectFrameRef.current(parent2);
12092
+ return;
12093
+ }
11399
12094
  deselectRef.current();
11400
12095
  return;
11401
12096
  }
@@ -11845,7 +12540,7 @@ function OhhwellsBridge() {
11845
12540
  if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
11846
12541
  };
11847
12542
  }, [isEditMode, refreshStateRules]);
11848
- (0, import_react10.useEffect)(() => {
12543
+ (0, import_react11.useEffect)(() => {
11849
12544
  if (!isEditMode) return;
11850
12545
  const THRESHOLD = 10;
11851
12546
  const resolveWasSelected = (el) => {
@@ -11999,7 +12694,7 @@ function OhhwellsBridge() {
11999
12694
  unlockFooterDragInteraction();
12000
12695
  };
12001
12696
  }, [isEditMode]);
12002
- (0, import_react10.useEffect)(() => {
12697
+ (0, import_react11.useEffect)(() => {
12003
12698
  const handler = (e) => {
12004
12699
  if (e.data?.type !== "ow:request-schedule-config") return;
12005
12700
  const insertAfterVal = e.data.insertAfter;
@@ -12015,7 +12710,7 @@ function OhhwellsBridge() {
12015
12710
  window.addEventListener("message", handler);
12016
12711
  return () => window.removeEventListener("message", handler);
12017
12712
  }, [processConfigRequest]);
12018
- (0, import_react10.useEffect)(() => {
12713
+ (0, import_react11.useEffect)(() => {
12019
12714
  if (!isEditMode) return;
12020
12715
  document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
12021
12716
  el.removeAttribute("data-ohw-active-state");
@@ -12050,13 +12745,13 @@ function OhhwellsBridge() {
12050
12745
  clearTimeout(timer);
12051
12746
  };
12052
12747
  }, [pathname, isEditMode, refreshStateRules, postToParent2]);
12053
- (0, import_react10.useEffect)(() => {
12748
+ (0, import_react11.useEffect)(() => {
12054
12749
  scrollToHashSectionWhenReady();
12055
12750
  const onHashChange = () => scrollToHashSectionWhenReady();
12056
12751
  window.addEventListener("hashchange", onHashChange);
12057
12752
  return () => window.removeEventListener("hashchange", onHashChange);
12058
12753
  }, [pathname]);
12059
- const handleCommand = (0, import_react10.useCallback)((cmd) => {
12754
+ const handleCommand = (0, import_react11.useCallback)((cmd) => {
12060
12755
  const el = activeElRef.current;
12061
12756
  const selBefore = window.getSelection();
12062
12757
  let savedOffsets = null;
@@ -12092,7 +12787,7 @@ function OhhwellsBridge() {
12092
12787
  if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
12093
12788
  refreshActiveCommandsRef.current();
12094
12789
  }, []);
12095
- const handleStateChange = (0, import_react10.useCallback)((state) => {
12790
+ const handleStateChange = (0, import_react11.useCallback)((state) => {
12096
12791
  if (!activeStateElRef.current) return;
12097
12792
  const el = activeStateElRef.current;
12098
12793
  if (state === "Default") {
@@ -12105,22 +12800,22 @@ function OhhwellsBridge() {
12105
12800
  }
12106
12801
  setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
12107
12802
  }, [deactivate]);
12108
- const closeLinkPopover = (0, import_react10.useCallback)(() => {
12803
+ const closeLinkPopover = (0, import_react11.useCallback)(() => {
12109
12804
  addNavAfterAnchorRef.current = null;
12110
12805
  setLinkPopover(null);
12111
12806
  }, []);
12112
- const openLinkPopoverForActive = (0, import_react10.useCallback)(() => {
12807
+ const openLinkPopoverForActive = (0, import_react11.useCallback)(() => {
12113
12808
  const hrefCtx = getHrefKeyFromElement(activeElRef.current);
12114
12809
  if (!hrefCtx) return;
12115
12810
  bumpLinkPopoverGrace();
12116
12811
  setLinkPopover({
12117
12812
  key: hrefCtx.key,
12118
12813
  mode: "edit",
12119
- target: getLinkHref2(hrefCtx.anchor)
12814
+ target: getLinkHref3(hrefCtx.anchor)
12120
12815
  });
12121
12816
  deactivate();
12122
12817
  }, [deactivate]);
12123
- const openLinkPopoverForSelected = (0, import_react10.useCallback)(() => {
12818
+ const openLinkPopoverForSelected = (0, import_react11.useCallback)(() => {
12124
12819
  const anchor = selectedElRef.current;
12125
12820
  if (!anchor) return;
12126
12821
  const key = anchor.getAttribute("data-ohw-href-key");
@@ -12129,11 +12824,108 @@ function OhhwellsBridge() {
12129
12824
  setLinkPopover({
12130
12825
  key,
12131
12826
  mode: "edit",
12132
- target: getLinkHref2(anchor)
12827
+ target: getLinkHref3(anchor)
12133
12828
  });
12134
12829
  deselect();
12135
12830
  }, [deselect]);
12136
- const handleLinkPopoverSubmit = (0, import_react10.useCallback)(
12831
+ const handleSelectParent = (0, import_react11.useCallback)(() => {
12832
+ const selected = selectedElRef.current;
12833
+ if (!selected) return;
12834
+ if (toolbarVariantRef.current === "select-frame") {
12835
+ deselectRef.current();
12836
+ return;
12837
+ }
12838
+ const parent = getNavigationSelectionParent(selected);
12839
+ if (parent && isNavigationContainer(parent)) {
12840
+ selectFrameRef.current(parent);
12841
+ } else {
12842
+ deselectRef.current();
12843
+ }
12844
+ }, []);
12845
+ const handleDuplicateSelected = (0, import_react11.useCallback)(() => {
12846
+ const selected = selectedElRef.current;
12847
+ if (!selected || !isNavigationItem(selected)) return;
12848
+ const hrefKey = selected.getAttribute("data-ohw-href-key");
12849
+ if (!hrefKey) return;
12850
+ if (isNavbarHrefKey(hrefKey)) {
12851
+ const result = duplicateNavbarItem(selected);
12852
+ if (!result) return;
12853
+ applyLinkByKey(result.hrefKey, result.href);
12854
+ document.querySelectorAll(`[data-ohw-key="${result.labelKey}"]`).forEach((el) => {
12855
+ el.textContent = result.label;
12856
+ });
12857
+ const nodes = [
12858
+ { key: result.hrefKey, text: result.href },
12859
+ { key: result.labelKey, text: result.label }
12860
+ ];
12861
+ for (const child of result.childResults) {
12862
+ applyLinkByKey(child.hrefKey, child.href);
12863
+ document.querySelectorAll(`[data-ohw-key="${child.labelKey}"]`).forEach((el) => {
12864
+ el.textContent = child.label;
12865
+ });
12866
+ nodes.push(
12867
+ { key: child.hrefKey, text: child.href },
12868
+ { key: child.labelKey, text: child.label }
12869
+ );
12870
+ }
12871
+ const maxIndex = Math.max(
12872
+ result.index,
12873
+ ...result.childResults.map((c) => c.index)
12874
+ );
12875
+ const navCount = String(maxIndex + 1);
12876
+ nodes.push(
12877
+ { key: NAV_COUNT_KEY, text: navCount },
12878
+ { key: NAV_ORDER_KEY, text: result.orderJson }
12879
+ );
12880
+ editContentRef.current = {
12881
+ ...editContentRef.current,
12882
+ [result.hrefKey]: result.href,
12883
+ [result.labelKey]: result.label,
12884
+ ...Object.fromEntries(
12885
+ result.childResults.flatMap((c) => [
12886
+ [c.hrefKey, c.href],
12887
+ [c.labelKey, c.label]
12888
+ ])
12889
+ ),
12890
+ [NAV_COUNT_KEY]: navCount,
12891
+ [NAV_ORDER_KEY]: result.orderJson
12892
+ };
12893
+ postToParent2({ type: "ow:change", nodes });
12894
+ enforceLinkHrefs();
12895
+ requestAnimationFrame(() => {
12896
+ selectRef.current(result.anchor);
12897
+ });
12898
+ return;
12899
+ }
12900
+ if (isFooterHrefKey(hrefKey)) {
12901
+ const result = duplicateFooterItem(selected);
12902
+ if (!result) return;
12903
+ applyLinkByKey(result.hrefKey, result.href);
12904
+ document.querySelectorAll(`[data-ohw-key="${result.labelKey}"]`).forEach((el) => {
12905
+ el.textContent = result.label;
12906
+ });
12907
+ const orderJson = JSON.stringify(result.order);
12908
+ editContentRef.current = {
12909
+ ...editContentRef.current,
12910
+ [result.hrefKey]: result.href,
12911
+ [result.labelKey]: result.label,
12912
+ [FOOTER_ORDER_KEY]: orderJson
12913
+ };
12914
+ postToParent2({
12915
+ type: "ow:change",
12916
+ nodes: [
12917
+ { key: result.hrefKey, text: result.href },
12918
+ { key: result.labelKey, text: result.label },
12919
+ { key: FOOTER_ORDER_KEY, text: orderJson }
12920
+ ]
12921
+ });
12922
+ enforceLinkHrefs();
12923
+ requestAnimationFrame(() => {
12924
+ selectRef.current(result.anchor);
12925
+ });
12926
+ }
12927
+ }, [postToParent2]);
12928
+ const handleLinkPopoverSubmit = (0, import_react11.useCallback)(
12137
12929
  (target) => {
12138
12930
  const session = linkPopoverSessionRef.current;
12139
12931
  if (!session) return;
@@ -12192,19 +12984,19 @@ function OhhwellsBridge() {
12192
12984
  const showEditLink = toolbarShowEditLink;
12193
12985
  const currentSections = sectionsByPath[pathname] ?? [];
12194
12986
  linkPopoverOpenRef.current = linkPopover !== null;
12195
- const handleMediaReplace = (0, import_react10.useCallback)(
12987
+ const handleMediaReplace = (0, import_react11.useCallback)(
12196
12988
  (key) => {
12197
12989
  postToParent2({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
12198
12990
  },
12199
12991
  [postToParent2, mediaHover?.elementType]
12200
12992
  );
12201
- const handleEditCarousel = (0, import_react10.useCallback)(
12993
+ const handleEditCarousel = (0, import_react11.useCallback)(
12202
12994
  (key) => {
12203
12995
  postToParent2({ type: "ow:carousel-open", key, images: readCarouselValue(key) });
12204
12996
  },
12205
12997
  [postToParent2]
12206
12998
  );
12207
- const handleMediaFadeOutComplete = (0, import_react10.useCallback)((key) => {
12999
+ const handleMediaFadeOutComplete = (0, import_react11.useCallback)((key) => {
12208
13000
  setUploadingRects((prev) => {
12209
13001
  if (!(key in prev)) return prev;
12210
13002
  const next = { ...prev };
@@ -12212,7 +13004,7 @@ function OhhwellsBridge() {
12212
13004
  return next;
12213
13005
  });
12214
13006
  }, []);
12215
- const handleVideoSettingsChange = (0, import_react10.useCallback)(
13007
+ const handleVideoSettingsChange = (0, import_react11.useCallback)(
12216
13008
  (key, settings) => {
12217
13009
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
12218
13010
  const video = getVideoEl(el);
@@ -12235,9 +13027,9 @@ function OhhwellsBridge() {
12235
13027
  [postToParent2]
12236
13028
  );
12237
13029
  return bridgeRoot ? (0, import_react_dom3.createPortal)(
12238
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
12239
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
12240
- Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
13030
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
13031
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
13032
+ Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
12241
13033
  MediaOverlay,
12242
13034
  {
12243
13035
  hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
@@ -12248,7 +13040,7 @@ function OhhwellsBridge() {
12248
13040
  },
12249
13041
  `uploading-${key}`
12250
13042
  )),
12251
- mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
13043
+ mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
12252
13044
  MediaOverlay,
12253
13045
  {
12254
13046
  hover: mediaHover,
@@ -12257,11 +13049,11 @@ function OhhwellsBridge() {
12257
13049
  onVideoSettingsChange: handleVideoSettingsChange
12258
13050
  }
12259
13051
  ),
12260
- carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
12261
- siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
12262
- siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
12263
- isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
12264
- isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
13052
+ carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
13053
+ siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
13054
+ siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
13055
+ isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
13056
+ isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
12265
13057
  "div",
12266
13058
  {
12267
13059
  className: "pointer-events-none fixed z-2147483646",
@@ -12271,7 +13063,7 @@ function OhhwellsBridge() {
12271
13063
  width: slot.width,
12272
13064
  height: slot.height
12273
13065
  },
12274
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
13066
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
12275
13067
  DropIndicator,
12276
13068
  {
12277
13069
  direction: slot.direction,
@@ -12282,7 +13074,7 @@ function OhhwellsBridge() {
12282
13074
  },
12283
13075
  `footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
12284
13076
  )),
12285
- isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
13077
+ isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
12286
13078
  "div",
12287
13079
  {
12288
13080
  className: "pointer-events-none fixed z-2147483646",
@@ -12292,7 +13084,7 @@ function OhhwellsBridge() {
12292
13084
  width: slot.width,
12293
13085
  height: slot.height
12294
13086
  },
12295
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
13087
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
12296
13088
  DropIndicator,
12297
13089
  {
12298
13090
  direction: slot.direction,
@@ -12303,10 +13095,11 @@ function OhhwellsBridge() {
12303
13095
  },
12304
13096
  `nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
12305
13097
  )),
12306
- hoveredNavContainerRect && toolbarVariant !== "select-frame" && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
12307
- hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
12308
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
12309
- toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
13098
+ hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
13099
+ hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
13100
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
13101
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(FooterContainerChrome, { rect: toolbarRect, onAdd: handleAddFooterColumn }),
13102
+ toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
12310
13103
  ItemInteractionLayer,
12311
13104
  {
12312
13105
  rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
@@ -12320,21 +13113,23 @@ function OhhwellsBridge() {
12320
13113
  onItemPointerDown: handleItemChromePointerDown,
12321
13114
  onItemClick: handleItemChromeClick,
12322
13115
  itemDragSurface: !isFooterFrameSelection,
12323
- toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
13116
+ toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
12324
13117
  ItemActionToolbar,
12325
13118
  {
12326
13119
  onEditLink: openLinkPopoverForSelected,
13120
+ onSelectParent: handleSelectParent,
13121
+ onDuplicate: handleDuplicateSelected,
12327
13122
  addItemDisabled: true,
12328
13123
  editLinkDisabled: false,
12329
- moreDisabled: true,
13124
+ moreDisabled: false,
12330
13125
  showAddItem: !selectedIsCta,
12331
13126
  showMore: !selectedIsCta
12332
13127
  }
12333
13128
  ) : void 0
12334
13129
  }
12335
13130
  ),
12336
- toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
12337
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
13131
+ toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
13132
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
12338
13133
  EditGlowChrome,
12339
13134
  {
12340
13135
  rect: toolbarRect,
@@ -12344,7 +13139,7 @@ function OhhwellsBridge() {
12344
13139
  hideHandle: isItemDragging
12345
13140
  }
12346
13141
  ),
12347
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
13142
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
12348
13143
  FloatingToolbar,
12349
13144
  {
12350
13145
  rect: toolbarRect,
@@ -12357,7 +13152,7 @@ function OhhwellsBridge() {
12357
13152
  }
12358
13153
  )
12359
13154
  ] }),
12360
- maxBadge && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
13155
+ maxBadge && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
12361
13156
  "div",
12362
13157
  {
12363
13158
  "data-ohw-max-badge": "",
@@ -12383,7 +13178,7 @@ function OhhwellsBridge() {
12383
13178
  ]
12384
13179
  }
12385
13180
  ),
12386
- toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
13181
+ toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
12387
13182
  StateToggle,
12388
13183
  {
12389
13184
  rect: toggleState.rect,
@@ -12392,15 +13187,15 @@ function OhhwellsBridge() {
12392
13187
  onStateChange: handleStateChange
12393
13188
  }
12394
13189
  ),
12395
- sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
13190
+ sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
12396
13191
  "div",
12397
13192
  {
12398
13193
  "data-ohw-section-insert-line": "",
12399
13194
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
12400
13195
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
12401
13196
  children: [
12402
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
12403
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
13197
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
13198
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
12404
13199
  Badge,
12405
13200
  {
12406
13201
  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",
@@ -12417,11 +13212,11 @@ function OhhwellsBridge() {
12417
13212
  children: "Add Section"
12418
13213
  }
12419
13214
  ),
12420
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
13215
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
12421
13216
  ]
12422
13217
  }
12423
13218
  ),
12424
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
13219
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
12425
13220
  LinkPopover,
12426
13221
  {
12427
13222
  panelRef: linkPopoverPanelRef,
@@ -12449,6 +13244,12 @@ function OhhwellsBridge() {
12449
13244
  CustomToolbarDivider,
12450
13245
  DragHandle,
12451
13246
  DropIndicator,
13247
+ DropdownMenu,
13248
+ DropdownMenuContent,
13249
+ DropdownMenuGroup,
13250
+ DropdownMenuItem,
13251
+ DropdownMenuSeparator,
13252
+ DropdownMenuTrigger,
12452
13253
  ItemActionToolbar,
12453
13254
  ItemInteractionLayer,
12454
13255
  LinkEditorPanel,