@ohhwells/bridge 0.1.49 → 0.1.51-next.118

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  // src/OhhwellsBridge.tsx
4
- import React11, { useCallback as useCallback4, useEffect as useEffect9, useLayoutEffect as useLayoutEffect3, useRef as useRef7, useState as useState8 } from "react";
4
+ import React11, { useCallback as useCallback5, useEffect as useEffect9, useLayoutEffect as useLayoutEffect3, useRef as useRef7, useState as useState9 } from "react";
5
5
  import { createRoot } from "react-dom/client";
6
6
  import { flushSync } from "react-dom";
7
7
 
@@ -48,12 +48,13 @@ function useLinkHrefGuardian(...deps) {
48
48
  }
49
49
 
50
50
  // src/ui/SchedulingWidget.tsx
51
- import { useEffect, useId, useMemo, useRef, useState as useState2 } from "react";
51
+ import { useCallback, useEffect, useId, useMemo, useRef, useState as useState2 } from "react";
52
52
 
53
53
  // src/ui/EmailCaptureModal.tsx
54
54
  import { useState } from "react";
55
55
  import { Dialog } from "radix-ui";
56
56
  import { jsx, jsxs } from "react/jsx-runtime";
57
+ var isValidEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
57
58
  function Spinner() {
58
59
  return /* @__PURE__ */ jsxs(
59
60
  "svg",
@@ -87,12 +88,17 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
87
88
  const [error, setError] = useState(null);
88
89
  const isBook = title === "Confirm your spot";
89
90
  const handleSubmit = async () => {
90
- if (!email.trim()) return;
91
+ const trimmed = email.trim();
92
+ if (!trimmed) return;
93
+ if (!isValidEmail(trimmed)) {
94
+ setError("Please enter a valid email address.");
95
+ return;
96
+ }
91
97
  setLoading(true);
92
98
  setError(null);
93
99
  try {
94
- await onSubmit(email.trim());
95
- setSubmittedEmail(email.trim());
100
+ await onSubmit(trimmed);
101
+ setSubmittedEmail(trimmed);
96
102
  setSuccess(true);
97
103
  } catch (e) {
98
104
  setError(e instanceof Error ? e.message : "Something went wrong. Please try again.");
@@ -167,7 +173,10 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
167
173
  {
168
174
  type: "email",
169
175
  value: email,
170
- onChange: (e) => setEmail(e.target.value),
176
+ onChange: (e) => {
177
+ setEmail(e.target.value);
178
+ if (error) setError(null);
179
+ },
171
180
  onKeyDown: handleKeyDown,
172
181
  placeholder: "hello@gmail.com",
173
182
  autoFocus: true,
@@ -224,12 +233,20 @@ function formatClassTime(cls) {
224
233
  const em = endTotal % 60;
225
234
  return `${h}:${cls.startTime.minutes}-${eh}:${String(em).padStart(2, "0")}`;
226
235
  }
236
+ function formatBookingLabel(cls) {
237
+ const price = cls.price;
238
+ const isFree = price === null || price === void 0 || `${price}` === "" || `${price}` === "0";
239
+ return isFree ? "Book for free" : `Book for ${cls.currency ?? ""} ${price}`.trim();
240
+ }
227
241
  function getBookingsOnDate(cls, date) {
228
242
  if (!cls.bookings?.length) return 0;
229
- const ds = date.toISOString().split("T")[0];
243
+ const target = new Date(date);
244
+ target.setHours(0, 0, 0, 0);
230
245
  return cls.bookings.filter((b) => {
231
246
  try {
232
- return new Date(b.classDate).toISOString().split("T")[0] === ds;
247
+ const bookingDate = new Date(b.classDate);
248
+ bookingDate.setHours(0, 0, 0, 0);
249
+ return bookingDate.getTime() === target.getTime();
233
250
  } catch {
234
251
  return false;
235
252
  }
@@ -494,7 +511,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
494
511
  }
495
512
  )
496
513
  ] }),
497
- /* @__PURE__ */ jsx2("div", { className: "sm:hidden flex flex-col gap-px", children: isFull ? /* @__PURE__ */ jsx2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
514
+ cls.showAvailability !== false && /* @__PURE__ */ jsx2("div", { className: "sm:hidden flex flex-col gap-px", children: isFull ? /* @__PURE__ */ jsx2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
498
515
  /* @__PURE__ */ jsxs2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
499
516
  available,
500
517
  "/",
@@ -506,9 +523,17 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
506
523
  /* @__PURE__ */ jsxs2("div", { className: "flex flex-1 flex-col gap-2 min-w-0 sm:contents", children: [
507
524
  /* @__PURE__ */ jsxs2("div", { className: "flex-1 flex flex-col gap-2 min-w-0", children: [
508
525
  /* @__PURE__ */ jsx2("span", { className: "font-body text-base font-bold text-(--color-dark,#200C02) block truncate", children: cls.name }),
509
- cls.hostName && /* @__PURE__ */ jsx2("span", { className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block truncate", children: cls.hostName })
526
+ cls.hostName && /* @__PURE__ */ jsx2("span", { className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block truncate", children: cls.hostName }),
527
+ cls.description && /* @__PURE__ */ jsx2(
528
+ "span",
529
+ {
530
+ className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block",
531
+ style: { wordBreak: "break-word" },
532
+ children: cls.description
533
+ }
534
+ )
510
535
  ] }),
511
- /* @__PURE__ */ jsx2("div", { className: "hidden sm:flex w-14 shrink-0 flex-col gap-px", children: isFull ? /* @__PURE__ */ jsx2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
536
+ cls.showAvailability !== false && /* @__PURE__ */ jsx2("div", { className: "hidden sm:flex w-14 shrink-0 flex-col gap-px", children: isFull ? /* @__PURE__ */ jsx2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
512
537
  /* @__PURE__ */ jsxs2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
513
538
  available,
514
539
  "/",
@@ -533,7 +558,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
533
558
  if (!cls.id) return;
534
559
  onOpenModal?.(isFull ? "waitlist" : "book", cls.id, selectedDate);
535
560
  },
536
- children: isFull ? "Join Waitlist" : "Book Now"
561
+ children: isFull ? "Join Waitlist" : formatBookingLabel(cls)
537
562
  }
538
563
  )
539
564
  ] })
@@ -575,6 +600,17 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
575
600
  const [isHovered, setIsHovered] = useState2(false);
576
601
  const [modalState, setModalState] = useState2(null);
577
602
  const switchScheduleIdRef = useRef(null);
603
+ const liveScheduleIdRef = useRef(null);
604
+ const refetchLiveSchedule = useCallback(async () => {
605
+ const id = liveScheduleIdRef.current;
606
+ if (!id) return;
607
+ try {
608
+ const res = await fetch(`${API_URL}/api/schedule/id/${id}`);
609
+ const data = await res.json();
610
+ if (data?.id) setSchedule(data);
611
+ } catch {
612
+ }
613
+ }, []);
578
614
  const dates = useMemo(() => {
579
615
  const today = /* @__PURE__ */ new Date();
580
616
  today.setHours(0, 0, 0, 0);
@@ -594,6 +630,18 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
594
630
  }
595
631
  }
596
632
  }, [schedule, dates]);
633
+ useEffect(() => {
634
+ if (typeof window === "undefined") return;
635
+ const onVisible = () => {
636
+ if (!document.hidden) void refetchLiveSchedule();
637
+ };
638
+ window.addEventListener("focus", refetchLiveSchedule);
639
+ document.addEventListener("visibilitychange", onVisible);
640
+ return () => {
641
+ window.removeEventListener("focus", refetchLiveSchedule);
642
+ document.removeEventListener("visibilitychange", onVisible);
643
+ };
644
+ }, [refetchLiveSchedule]);
597
645
  useEffect(() => {
598
646
  if (typeof window === "undefined") return;
599
647
  const isInEditor = window.self !== window.top;
@@ -655,7 +703,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
655
703
  setLoading(false);
656
704
  return;
657
705
  }
658
- ;
706
+ liveScheduleIdRef.current = effectiveId;
659
707
  (async () => {
660
708
  try {
661
709
  const res = await fetch(`${API_URL}/api/schedule/id/${effectiveId}`);
@@ -712,18 +760,14 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
712
760
  const data = await res.json().catch(() => ({}));
713
761
  throw new Error(data?.message ?? "Something went wrong. Please try again.");
714
762
  }
763
+ await refetchLiveSchedule();
715
764
  };
716
765
  const handleReplaceSchedule = () => {
717
766
  setIsHovered(false);
718
- if (schedule) {
719
- window.parent.postMessage({
720
- type: "ow:schedule-connected",
721
- schedule: { id: schedule.id, name: schedule.name },
722
- insertAfter
723
- }, "*");
724
- } else {
725
- window.parent.postMessage({ type: "ow:scheduling-not-connected", insertAfter }, "*");
726
- }
767
+ window.parent.postMessage(
768
+ { type: "ow:scheduling-not-connected", insertAfter, currentScheduleId: schedule?.id },
769
+ "*"
770
+ );
727
771
  };
728
772
  if (!inEditor && !loading && !schedule) return null;
729
773
  const sectionId = `scheduling-${insertAfter}`;
@@ -766,7 +810,19 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
766
810
  ),
767
811
  /* @__PURE__ */ jsxs2("div", { className: "max-w-[1280px] mx-auto flex flex-col items-center gap-16", children: [
768
812
  /* @__PURE__ */ jsxs2("div", { className: "flex flex-col items-center gap-4", children: [
769
- /* @__PURE__ */ jsx2("h2", { className: "font-display text-4xl sm:text-5xl font-bold text-center m-0 text-(--color-dark,#200C02)", children: schedule?.name ?? "Book an appointment" }),
813
+ /* @__PURE__ */ jsx2(
814
+ "h2",
815
+ {
816
+ className: "font-display text-center m-0 text-(--color-dark,#200C02)",
817
+ style: {
818
+ fontSize: "var(--fs-section-h2, clamp(40px, 4.4vw, 64px))",
819
+ fontWeight: "var(--font-weight-heading, 400)",
820
+ lineHeight: 1.05,
821
+ letterSpacing: "-0.02em"
822
+ },
823
+ children: schedule?.name ?? "Book an appointment"
824
+ }
825
+ ),
770
826
  schedule?.description && /* @__PURE__ */ jsx2("p", { className: "font-body text-body text-center m-0 text-(--color-accent,#A89B83)", children: schedule.description })
771
827
  ] }),
772
828
  /* @__PURE__ */ jsxs2("div", { className: "w-full flex flex-col items-end gap-3", children: [
@@ -4282,22 +4338,116 @@ var CustomToolbarButton = React4.forwardRef(
4282
4338
  CustomToolbarButton.displayName = "CustomToolbarButton";
4283
4339
 
4284
4340
  // src/ui/item-action-toolbar.tsx
4285
- import { Link, MoreHorizontal, Plus } from "lucide-react";
4341
+ import { useState as useState3 } from "react";
4342
+ import { Copy, CornerLeftUp, Link, MoreHorizontal, Plus, Trash2 } from "lucide-react";
4343
+
4344
+ // src/ui/dropdown-menu.tsx
4345
+ import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui";
4346
+ import { jsx as jsx7 } from "react/jsx-runtime";
4347
+ function DropdownMenu({ ...props }) {
4348
+ return /* @__PURE__ */ jsx7(DropdownMenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
4349
+ }
4350
+ function DropdownMenuTrigger({
4351
+ ...props
4352
+ }) {
4353
+ return /* @__PURE__ */ jsx7(DropdownMenuPrimitive.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
4354
+ }
4355
+ function DropdownMenuGroup({
4356
+ className,
4357
+ ...props
4358
+ }) {
4359
+ return /* @__PURE__ */ jsx7(
4360
+ DropdownMenuPrimitive.Group,
4361
+ {
4362
+ "data-slot": "dropdown-menu-group",
4363
+ className: cn("flex w-full flex-col items-start p-1", className),
4364
+ ...props
4365
+ }
4366
+ );
4367
+ }
4368
+ function DropdownMenuContent({
4369
+ className,
4370
+ sideOffset = 6,
4371
+ ...props
4372
+ }) {
4373
+ return /* @__PURE__ */ jsx7(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx7(
4374
+ DropdownMenuPrimitive.Content,
4375
+ {
4376
+ "data-slot": "dropdown-menu-content",
4377
+ "data-ohw-more-menu": "",
4378
+ sideOffset,
4379
+ className: cn(
4380
+ "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",
4381
+ "shadow-[0px_4px_6px_0px_rgba(0,0,0,0.1),0px_2px_4px_0px_rgba(0,0,0,0.1)]",
4382
+ "origin-[var(--radix-dropdown-menu-content-transform-origin)]",
4383
+ "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",
4384
+ "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",
4385
+ className
4386
+ ),
4387
+ ...props
4388
+ }
4389
+ ) });
4390
+ }
4391
+ function DropdownMenuItem({
4392
+ className,
4393
+ inset,
4394
+ variant = "default",
4395
+ ...props
4396
+ }) {
4397
+ return /* @__PURE__ */ jsx7(
4398
+ DropdownMenuPrimitive.Item,
4399
+ {
4400
+ "data-slot": "dropdown-menu-item",
4401
+ "data-inset": inset ? "" : void 0,
4402
+ "data-variant": variant,
4403
+ className: cn(
4404
+ "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",
4405
+ "text-popover-foreground",
4406
+ "focus:bg-muted data-[highlighted]:bg-muted",
4407
+ "data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
4408
+ "[&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
4409
+ "[&_svg:not([class*=absolute])]:relative",
4410
+ // Leading icon — Figma absolute left-2 / top-1/2
4411
+ "[&>svg:first-child]:absolute [&>svg:first-child]:left-2 [&>svg:first-child]:top-1/2 [&>svg:first-child]:-translate-y-1/2",
4412
+ "data-[variant=destructive]:text-destructive",
4413
+ "data-[variant=destructive]:focus:bg-bg-destructive-10 data-[variant=destructive]:focus:text-destructive",
4414
+ "data-[variant=destructive]:data-[highlighted]:bg-bg-destructive-10 data-[variant=destructive]:data-[highlighted]:text-destructive",
4415
+ "data-[variant=destructive]:[&_svg]:text-destructive",
4416
+ inset && "pl-8",
4417
+ className
4418
+ ),
4419
+ ...props
4420
+ }
4421
+ );
4422
+ }
4423
+ function DropdownMenuSeparator({
4424
+ className,
4425
+ ...props
4426
+ }) {
4427
+ return /* @__PURE__ */ jsx7(
4428
+ DropdownMenuPrimitive.Separator,
4429
+ {
4430
+ "data-slot": "dropdown-menu-separator",
4431
+ className: cn("h-px w-full bg-border", className),
4432
+ ...props
4433
+ }
4434
+ );
4435
+ }
4286
4436
 
4287
4437
  // src/ui/tooltip.tsx
4288
4438
  import { Tooltip as TooltipPrimitive } from "radix-ui";
4289
- import { jsx as jsx7 } from "react/jsx-runtime";
4439
+ import { jsx as jsx8 } from "react/jsx-runtime";
4290
4440
  function TooltipProvider({
4291
4441
  delayDuration = 0,
4292
4442
  ...props
4293
4443
  }) {
4294
- return /* @__PURE__ */ jsx7(TooltipPrimitive.Provider, { "data-slot": "tooltip-provider", delayDuration, ...props });
4444
+ return /* @__PURE__ */ jsx8(TooltipPrimitive.Provider, { "data-slot": "tooltip-provider", delayDuration, ...props });
4295
4445
  }
4296
4446
  function Tooltip({ ...props }) {
4297
- return /* @__PURE__ */ jsx7(TooltipPrimitive.Root, { "data-slot": "tooltip", ...props });
4447
+ return /* @__PURE__ */ jsx8(TooltipPrimitive.Root, { "data-slot": "tooltip", ...props });
4298
4448
  }
4299
4449
  function TooltipTrigger({ ...props }) {
4300
- return /* @__PURE__ */ jsx7(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
4450
+ return /* @__PURE__ */ jsx8(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
4301
4451
  }
4302
4452
  var arrowClassBySide = {
4303
4453
  top: "before:bottom-0 before:left-1/2 before:-translate-x-1/2 before:translate-y-1/2",
@@ -4314,7 +4464,7 @@ function TooltipContent({
4314
4464
  ...props
4315
4465
  }) {
4316
4466
  const resolvedSide = side ?? "bottom";
4317
- return /* @__PURE__ */ jsx7(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx7(
4467
+ return /* @__PURE__ */ jsx8(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx8(
4318
4468
  TooltipPrimitive.Content,
4319
4469
  {
4320
4470
  "data-slot": "tooltip-content",
@@ -4337,7 +4487,7 @@ function TooltipContent({
4337
4487
  }
4338
4488
 
4339
4489
  // src/ui/item-action-toolbar.tsx
4340
- import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
4490
+ import { jsx as jsx9, jsxs as jsxs3 } from "react/jsx-runtime";
4341
4491
  function ToolbarActionTooltip({
4342
4492
  label,
4343
4493
  side = "bottom",
@@ -4345,25 +4495,31 @@ function ToolbarActionTooltip({
4345
4495
  buttonProps,
4346
4496
  children
4347
4497
  }) {
4348
- const button = /* @__PURE__ */ jsx8(CustomToolbarButton, { type: "button", "aria-label": label, disabled, ...buttonProps, children });
4498
+ const button = /* @__PURE__ */ jsx9(CustomToolbarButton, { type: "button", "aria-label": label, disabled, ...buttonProps, children });
4349
4499
  return /* @__PURE__ */ jsxs3(Tooltip, { children: [
4350
- /* @__PURE__ */ jsx8(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ jsx8("span", { className: "inline-flex", children: button }) : button }),
4351
- /* @__PURE__ */ jsx8(TooltipContent, { side, sideOffset: 9, children: label })
4500
+ /* @__PURE__ */ jsx9(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ jsx9("span", { className: "inline-flex", children: button }) : button }),
4501
+ /* @__PURE__ */ jsx9(TooltipContent, { side, sideOffset: 9, children: label })
4352
4502
  ] });
4353
4503
  }
4354
4504
  function ItemActionToolbar({
4355
4505
  onEditLink,
4356
4506
  onAddItem,
4357
- onMore,
4507
+ onSelectParent,
4508
+ onDuplicate,
4509
+ onDelete,
4358
4510
  editLinkDisabled = false,
4359
4511
  addItemDisabled = true,
4360
- moreDisabled = true,
4512
+ moreDisabled = false,
4513
+ selectParentDisabled = false,
4514
+ duplicateDisabled = false,
4515
+ deleteDisabled = false,
4361
4516
  showAddItem = true,
4362
4517
  showMore = true,
4363
4518
  tooltipSide = "bottom"
4364
4519
  }) {
4365
- return /* @__PURE__ */ jsx8(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs3(CustomToolbar, { children: [
4366
- /* @__PURE__ */ jsx8(
4520
+ const [moreOpen, setMoreOpen] = useState3(false);
4521
+ return /* @__PURE__ */ jsx9(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs3(CustomToolbar, { children: [
4522
+ /* @__PURE__ */ jsx9(
4367
4523
  ToolbarActionTooltip,
4368
4524
  {
4369
4525
  label: "Edit link",
@@ -4381,10 +4537,10 @@ function ItemActionToolbar({
4381
4537
  e.stopPropagation();
4382
4538
  }
4383
4539
  },
4384
- children: /* @__PURE__ */ jsx8(Link, { className: "size-4 shrink-0", "aria-hidden": true })
4540
+ children: /* @__PURE__ */ jsx9(Link, { className: "size-4 shrink-0", "aria-hidden": true })
4385
4541
  }
4386
4542
  ),
4387
- showAddItem ? /* @__PURE__ */ jsx8(
4543
+ showAddItem ? /* @__PURE__ */ jsx9(
4388
4544
  ToolbarActionTooltip,
4389
4545
  {
4390
4546
  label: "Add item",
@@ -4398,32 +4554,84 @@ function ItemActionToolbar({
4398
4554
  onAddItem?.();
4399
4555
  }
4400
4556
  },
4401
- children: /* @__PURE__ */ jsx8(Plus, { className: "size-4 shrink-0", "aria-hidden": true })
4557
+ children: /* @__PURE__ */ jsx9(Plus, { className: "size-4 shrink-0", "aria-hidden": true })
4402
4558
  }
4403
4559
  ) : null,
4404
- showMore ? /* @__PURE__ */ jsx8(
4405
- ToolbarActionTooltip,
4406
- {
4407
- label: "More",
4408
- side: tooltipSide,
4409
- disabled: moreDisabled,
4410
- buttonProps: {
4560
+ showMore ? /* @__PURE__ */ jsxs3(DropdownMenu, { open: moreOpen, onOpenChange: setMoreOpen, children: [
4561
+ /* @__PURE__ */ jsxs3(Tooltip, { open: moreOpen ? false : void 0, children: [
4562
+ /* @__PURE__ */ jsx9(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx9(DropdownMenuTrigger, { asChild: true, disabled: moreDisabled, children: /* @__PURE__ */ jsx9(
4563
+ CustomToolbarButton,
4564
+ {
4565
+ type: "button",
4566
+ "aria-label": "More",
4567
+ disabled: moreDisabled,
4568
+ onMouseDown: (e) => {
4569
+ e.preventDefault();
4570
+ e.stopPropagation();
4571
+ },
4572
+ children: /* @__PURE__ */ jsx9(MoreHorizontal, { className: "size-4 shrink-0", "aria-hidden": true })
4573
+ }
4574
+ ) }) }),
4575
+ /* @__PURE__ */ jsx9(TooltipContent, { side: tooltipSide, sideOffset: 9, children: "More" })
4576
+ ] }),
4577
+ /* @__PURE__ */ jsxs3(
4578
+ DropdownMenuContent,
4579
+ {
4580
+ align: "end",
4581
+ side: "bottom",
4582
+ onCloseAutoFocus: (e) => e.preventDefault(),
4411
4583
  onMouseDown: (e) => {
4412
- if (moreDisabled) return;
4413
4584
  e.preventDefault();
4414
4585
  e.stopPropagation();
4415
- onMore?.();
4416
- }
4417
- },
4418
- children: /* @__PURE__ */ jsx8(MoreHorizontal, { className: "size-4 shrink-0", "aria-hidden": true })
4419
- }
4420
- ) : null
4586
+ },
4587
+ children: [
4588
+ /* @__PURE__ */ jsxs3(DropdownMenuGroup, { children: [
4589
+ /* @__PURE__ */ jsxs3(
4590
+ DropdownMenuItem,
4591
+ {
4592
+ disabled: selectParentDisabled,
4593
+ onSelect: () => onSelectParent?.(),
4594
+ children: [
4595
+ /* @__PURE__ */ jsx9(CornerLeftUp, { size: 12, "aria-hidden": true }),
4596
+ "Select parent"
4597
+ ]
4598
+ }
4599
+ ),
4600
+ /* @__PURE__ */ jsxs3(
4601
+ DropdownMenuItem,
4602
+ {
4603
+ disabled: duplicateDisabled,
4604
+ onSelect: () => onDuplicate?.(),
4605
+ children: [
4606
+ /* @__PURE__ */ jsx9(Copy, { size: 12, "aria-hidden": true }),
4607
+ "Duplicate"
4608
+ ]
4609
+ }
4610
+ )
4611
+ ] }),
4612
+ /* @__PURE__ */ jsx9(DropdownMenuSeparator, {}),
4613
+ /* @__PURE__ */ jsx9(DropdownMenuGroup, { children: /* @__PURE__ */ jsxs3(
4614
+ DropdownMenuItem,
4615
+ {
4616
+ variant: "destructive",
4617
+ disabled: deleteDisabled,
4618
+ onSelect: () => onDelete?.(),
4619
+ children: [
4620
+ /* @__PURE__ */ jsx9(Trash2, { size: 15, "aria-hidden": true }),
4621
+ "Delete"
4622
+ ]
4623
+ }
4624
+ ) })
4625
+ ]
4626
+ }
4627
+ )
4628
+ ] }) : null
4421
4629
  ] }) });
4422
4630
  }
4423
4631
 
4424
4632
  // src/ui/item-interaction-layer.tsx
4425
4633
  import * as React5 from "react";
4426
- import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
4634
+ import { jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
4427
4635
  var PRIMARY = "var(--ohw-primary, #0885FE)";
4428
4636
  var FOCUS_RING = `0 0 0 4px color-mix(in srgb, ${PRIMARY} 12%, transparent)`;
4429
4637
  var DRAG_SHADOW = "0px 4px 6px -1px rgba(0, 0, 0, 0.1), 0px 2px 4px -2px rgba(0, 0, 0, 0.1)";
@@ -4505,7 +4713,7 @@ function ClampedToolbarSlot({
4505
4713
  window.removeEventListener("resize", clamp);
4506
4714
  };
4507
4715
  }, [placement, children]);
4508
- return /* @__PURE__ */ jsx9(
4716
+ return /* @__PURE__ */ jsx10(
4509
4717
  "div",
4510
4718
  {
4511
4719
  ref: slotRef,
@@ -4561,7 +4769,7 @@ function ItemInteractionLayer({
4561
4769
  zIndex: getChromeZIndex(state)
4562
4770
  },
4563
4771
  children: [
4564
- /* @__PURE__ */ jsx9(
4772
+ /* @__PURE__ */ jsx10(
4565
4773
  "div",
4566
4774
  {
4567
4775
  "aria-hidden": true,
@@ -4569,7 +4777,7 @@ function ItemInteractionLayer({
4569
4777
  style: getChromeStyle(state)
4570
4778
  }
4571
4779
  ),
4572
- itemDragEnabled && /* @__PURE__ */ jsx9(
4780
+ itemDragEnabled && /* @__PURE__ */ jsx10(
4573
4781
  "div",
4574
4782
  {
4575
4783
  "data-ohw-item-drag-surface": "",
@@ -4585,14 +4793,14 @@ function ItemInteractionLayer({
4585
4793
  }
4586
4794
  }
4587
4795
  ),
4588
- showDragHandle && /* @__PURE__ */ jsx9(
4796
+ showDragHandle && /* @__PURE__ */ jsx10(
4589
4797
  "div",
4590
4798
  {
4591
4799
  "data-ohw-drag-handle-container": "",
4592
4800
  className: "pointer-events-auto absolute left-0 top-1/2 z-10 -translate-x-[calc(100%+7px)] -translate-y-1/2",
4593
4801
  style: isDragging ? { opacity: 0 } : void 0,
4594
4802
  "aria-hidden": isDragging || void 0,
4595
- children: /* @__PURE__ */ jsx9(
4803
+ children: /* @__PURE__ */ jsx10(
4596
4804
  DragHandle,
4597
4805
  {
4598
4806
  draggable: !dragDisabled,
@@ -4622,8 +4830,8 @@ function ItemInteractionLayer({
4622
4830
  )
4623
4831
  }
4624
4832
  ),
4625
- showToolbar && state === "active-top" && /* @__PURE__ */ jsx9(ClampedToolbarSlot, { placement: "top", children: toolbar }),
4626
- showToolbar && state === "active-bottom" && /* @__PURE__ */ jsx9(ClampedToolbarSlot, { placement: "bottom", children: toolbar })
4833
+ showToolbar && state === "active-top" && /* @__PURE__ */ jsx10(ClampedToolbarSlot, { placement: "top", children: toolbar }),
4834
+ showToolbar && state === "active-bottom" && /* @__PURE__ */ jsx10(ClampedToolbarSlot, { placement: "bottom", children: toolbar })
4627
4835
  ]
4628
4836
  }
4629
4837
  );
@@ -4636,7 +4844,7 @@ import { Film, ImageIcon, Pause, Play, Volume2, VolumeX } from "lucide-react";
4636
4844
  // src/ui/button.tsx
4637
4845
  import * as React6 from "react";
4638
4846
  import { Slot } from "radix-ui";
4639
- import { jsx as jsx10 } from "react/jsx-runtime";
4847
+ import { jsx as jsx11 } from "react/jsx-runtime";
4640
4848
  var buttonVariants = cva(
4641
4849
  "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",
4642
4850
  {
@@ -4660,7 +4868,7 @@ var buttonVariants = cva(
4660
4868
  var Button = React6.forwardRef(
4661
4869
  ({ className, variant, size, asChild = false, ...props }, ref) => {
4662
4870
  const Comp = asChild ? Slot.Root : "button";
4663
- return /* @__PURE__ */ jsx10(
4871
+ return /* @__PURE__ */ jsx11(
4664
4872
  Comp,
4665
4873
  {
4666
4874
  ref,
@@ -4674,7 +4882,7 @@ var Button = React6.forwardRef(
4674
4882
  Button.displayName = "Button";
4675
4883
 
4676
4884
  // src/ui/MediaOverlay.tsx
4677
- import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
4885
+ import { Fragment as Fragment2, jsx as jsx12, jsxs as jsxs5 } from "react/jsx-runtime";
4678
4886
  var MEDIA_UPLOAD_FADE_MS = 300;
4679
4887
  var VIDEO_SETTINGS_BAR_INSET = 8;
4680
4888
  var OVERLAY_BUTTON_STYLE = {
@@ -4732,7 +4940,7 @@ function MediaOverlay({
4732
4940
  return () => anim.cancel();
4733
4941
  }, [isUploading, fadingOut, onFadeOutComplete, hover.key]);
4734
4942
  if (isUploading) {
4735
- return /* @__PURE__ */ jsx11(
4943
+ return /* @__PURE__ */ jsx12(
4736
4944
  "div",
4737
4945
  {
4738
4946
  ref: skeletonRef,
@@ -4741,7 +4949,7 @@ function MediaOverlay({
4741
4949
  "data-ohw-media-skeleton": "",
4742
4950
  "aria-hidden": true,
4743
4951
  style: { ...box, pointerEvents: "none" },
4744
- children: /* @__PURE__ */ jsx11("style", { children: SKELETON_CSS })
4952
+ children: /* @__PURE__ */ jsx12("style", { children: SKELETON_CSS })
4745
4953
  }
4746
4954
  );
4747
4955
  }
@@ -4761,7 +4969,7 @@ function MediaOverlay({
4761
4969
  },
4762
4970
  onClick: (e) => e.stopPropagation(),
4763
4971
  children: [
4764
- /* @__PURE__ */ jsx11(
4972
+ /* @__PURE__ */ jsx12(
4765
4973
  Button,
4766
4974
  {
4767
4975
  "data-ohw-media-overlay": "",
@@ -4776,10 +4984,10 @@ function MediaOverlay({
4776
4984
  e.stopPropagation();
4777
4985
  onVideoSettingsChange?.(hover.key, { autoplay: !autoplay });
4778
4986
  },
4779
- children: autoplay ? /* @__PURE__ */ jsx11(Pause, { size: 14 }) : /* @__PURE__ */ jsx11(Play, { size: 14 })
4987
+ children: autoplay ? /* @__PURE__ */ jsx12(Pause, { size: 14 }) : /* @__PURE__ */ jsx12(Play, { size: 14 })
4780
4988
  }
4781
4989
  ),
4782
- /* @__PURE__ */ jsx11(
4990
+ /* @__PURE__ */ jsx12(
4783
4991
  Button,
4784
4992
  {
4785
4993
  "data-ohw-media-overlay": "",
@@ -4794,7 +5002,7 @@ function MediaOverlay({
4794
5002
  e.stopPropagation();
4795
5003
  onVideoSettingsChange?.(hover.key, { muted: !muted });
4796
5004
  },
4797
- children: muted ? /* @__PURE__ */ jsx11(VolumeX, { size: 14 }) : /* @__PURE__ */ jsx11(Volume2, { size: 14 })
5005
+ children: muted ? /* @__PURE__ */ jsx12(VolumeX, { size: 14 }) : /* @__PURE__ */ jsx12(Volume2, { size: 14 })
4798
5006
  }
4799
5007
  )
4800
5008
  ]
@@ -4802,7 +5010,7 @@ function MediaOverlay({
4802
5010
  ) : null;
4803
5011
  return /* @__PURE__ */ jsxs5(Fragment2, { children: [
4804
5012
  settingsBar,
4805
- /* @__PURE__ */ jsx11(
5013
+ /* @__PURE__ */ jsx12(
4806
5014
  "div",
4807
5015
  {
4808
5016
  "data-ohw-bridge": "",
@@ -4826,14 +5034,18 @@ function MediaOverlay({
4826
5034
  variant: "outline",
4827
5035
  size: "sm",
4828
5036
  className: "gap-1.5 cursor-pointer hover:bg-background",
4829
- style: OVERLAY_BUTTON_STYLE,
5037
+ style: {
5038
+ ...OVERLAY_BUTTON_STYLE,
5039
+ // Don't let Replace steal clicks when text (e.g. nav) sits on top of this media.
5040
+ pointerEvents: hover.hasTextOverlap ? "none" : "auto"
5041
+ },
4830
5042
  onMouseDown: (e) => e.preventDefault(),
4831
5043
  onClick: (e) => {
4832
5044
  e.stopPropagation();
4833
5045
  onReplace(hover.key);
4834
5046
  },
4835
5047
  children: [
4836
- isVideo ? /* @__PURE__ */ jsx11(Film, { size: 14 }) : /* @__PURE__ */ jsx11(ImageIcon, { size: 14 }),
5048
+ isVideo ? /* @__PURE__ */ jsx12(Film, { size: 14 }) : /* @__PURE__ */ jsx12(ImageIcon, { size: 14 }),
4837
5049
  isVideo ? "Replace video" : "Replace image"
4838
5050
  ]
4839
5051
  }
@@ -4845,7 +5057,7 @@ function MediaOverlay({
4845
5057
 
4846
5058
  // src/ui/CarouselOverlay.tsx
4847
5059
  import { GalleryHorizontal } from "lucide-react";
4848
- import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
5060
+ import { jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
4849
5061
  var OVERLAY_BUTTON_STYLE2 = {
4850
5062
  pointerEvents: "auto",
4851
5063
  fontFamily: "Inter, sans-serif",
@@ -4857,7 +5069,7 @@ function CarouselOverlay({
4857
5069
  onEdit
4858
5070
  }) {
4859
5071
  const { rect } = hover;
4860
- return /* @__PURE__ */ jsx12(
5072
+ return /* @__PURE__ */ jsx13(
4861
5073
  "div",
4862
5074
  {
4863
5075
  "data-ohw-bridge": "",
@@ -4889,7 +5101,7 @@ function CarouselOverlay({
4889
5101
  onEdit(hover.key);
4890
5102
  },
4891
5103
  children: [
4892
- /* @__PURE__ */ jsx12(GalleryHorizontal, { size: 14 }),
5104
+ /* @__PURE__ */ jsx13(GalleryHorizontal, { size: 14 }),
4893
5105
  "Edit gallery"
4894
5106
  ]
4895
5107
  }
@@ -5184,22 +5396,22 @@ import { useEffect as useEffect6 } from "react";
5184
5396
  import * as React8 from "react";
5185
5397
  import { Dialog as DialogPrimitive } from "radix-ui";
5186
5398
  import { X } from "lucide-react";
5187
- import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
5399
+ import { jsx as jsx14, jsxs as jsxs7 } from "react/jsx-runtime";
5188
5400
  function Dialog2({
5189
5401
  ...props
5190
5402
  }) {
5191
- return /* @__PURE__ */ jsx13(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
5403
+ return /* @__PURE__ */ jsx14(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
5192
5404
  }
5193
5405
  function DialogPortal({
5194
5406
  ...props
5195
5407
  }) {
5196
- return /* @__PURE__ */ jsx13(DialogPrimitive.Portal, { ...props });
5408
+ return /* @__PURE__ */ jsx14(DialogPrimitive.Portal, { ...props });
5197
5409
  }
5198
5410
  function DialogOverlay({
5199
5411
  className,
5200
5412
  ...props
5201
5413
  }) {
5202
- return /* @__PURE__ */ jsx13(
5414
+ return /* @__PURE__ */ jsx14(
5203
5415
  DialogPrimitive.Overlay,
5204
5416
  {
5205
5417
  "data-slot": "dialog-overlay",
@@ -5213,7 +5425,7 @@ var DialogContent = React8.forwardRef(
5213
5425
  ({ className, children, showCloseButton = true, container, ...props }, ref) => {
5214
5426
  const positionMode = container ? "absolute" : "fixed";
5215
5427
  return /* @__PURE__ */ jsxs7(DialogPortal, { container: container ?? void 0, children: [
5216
- /* @__PURE__ */ jsx13(DialogOverlay, { className: cn(positionMode, "inset-0") }),
5428
+ /* @__PURE__ */ jsx14(DialogOverlay, { className: cn(positionMode, "inset-0") }),
5217
5429
  /* @__PURE__ */ jsxs7(
5218
5430
  DialogPrimitive.Content,
5219
5431
  {
@@ -5230,13 +5442,13 @@ var DialogContent = React8.forwardRef(
5230
5442
  ...props,
5231
5443
  children: [
5232
5444
  children,
5233
- showCloseButton ? /* @__PURE__ */ jsx13(
5445
+ showCloseButton ? /* @__PURE__ */ jsx14(
5234
5446
  DialogPrimitive.Close,
5235
5447
  {
5236
5448
  type: "button",
5237
5449
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
5238
5450
  "aria-label": "Close",
5239
- children: /* @__PURE__ */ jsx13(X, { size: 16, "aria-hidden": true })
5451
+ children: /* @__PURE__ */ jsx14(X, { size: 16, "aria-hidden": true })
5240
5452
  }
5241
5453
  ) : null
5242
5454
  ]
@@ -5250,13 +5462,13 @@ function DialogHeader({
5250
5462
  className,
5251
5463
  ...props
5252
5464
  }) {
5253
- return /* @__PURE__ */ jsx13("div", { className: cn("flex flex-col gap-1.5", className), ...props });
5465
+ return /* @__PURE__ */ jsx14("div", { className: cn("flex flex-col gap-1.5", className), ...props });
5254
5466
  }
5255
5467
  function DialogFooter({
5256
5468
  className,
5257
5469
  ...props
5258
5470
  }) {
5259
- return /* @__PURE__ */ jsx13(
5471
+ return /* @__PURE__ */ jsx14(
5260
5472
  "div",
5261
5473
  {
5262
5474
  className: cn("flex items-center justify-end gap-2", className),
@@ -5264,7 +5476,7 @@ function DialogFooter({
5264
5476
  }
5265
5477
  );
5266
5478
  }
5267
- var DialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
5479
+ var DialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx14(
5268
5480
  DialogPrimitive.Title,
5269
5481
  {
5270
5482
  ref,
@@ -5276,7 +5488,7 @@ var DialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE
5276
5488
  }
5277
5489
  ));
5278
5490
  DialogTitle.displayName = DialogPrimitive.Title.displayName;
5279
- var DialogDescription = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
5491
+ var DialogDescription = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx14(
5280
5492
  DialogPrimitive.Description,
5281
5493
  {
5282
5494
  ref,
@@ -5292,19 +5504,19 @@ import { Info, X as X3 } from "lucide-react";
5292
5504
 
5293
5505
  // src/ui/link-modal/DestinationBreadcrumb.tsx
5294
5506
  import { ArrowRight, File, GalleryVertical } from "lucide-react";
5295
- import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
5507
+ import { jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
5296
5508
  function DestinationBreadcrumb({
5297
5509
  pageTitle,
5298
5510
  sectionLabel
5299
5511
  }) {
5300
5512
  return /* @__PURE__ */ jsxs8("div", { className: "flex w-full flex-col gap-2", children: [
5301
- /* @__PURE__ */ jsx14("p", { className: "text-sm font-medium! text-foreground m-0", children: "Destination" }),
5513
+ /* @__PURE__ */ jsx15("p", { className: "text-sm font-medium! text-foreground m-0", children: "Destination" }),
5302
5514
  /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3", children: [
5303
5515
  /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
5304
- /* @__PURE__ */ jsx14(File, { size: 16, className: "shrink-0 text-foreground", "aria-hidden": true }),
5305
- /* @__PURE__ */ jsx14("span", { className: "text-sm font-medium leading-none text-foreground!", children: pageTitle })
5516
+ /* @__PURE__ */ jsx15(File, { size: 16, className: "shrink-0 text-foreground", "aria-hidden": true }),
5517
+ /* @__PURE__ */ jsx15("span", { className: "text-sm font-medium leading-none text-foreground!", children: pageTitle })
5306
5518
  ] }),
5307
- /* @__PURE__ */ jsx14(
5519
+ /* @__PURE__ */ jsx15(
5308
5520
  ArrowRight,
5309
5521
  {
5310
5522
  size: 16,
@@ -5313,7 +5525,7 @@ function DestinationBreadcrumb({
5313
5525
  }
5314
5526
  ),
5315
5527
  /* @__PURE__ */ jsxs8("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
5316
- /* @__PURE__ */ jsx14(
5528
+ /* @__PURE__ */ jsx15(
5317
5529
  GalleryVertical,
5318
5530
  {
5319
5531
  size: 16,
@@ -5321,7 +5533,7 @@ function DestinationBreadcrumb({
5321
5533
  "aria-hidden": true
5322
5534
  }
5323
5535
  ),
5324
- /* @__PURE__ */ jsx14("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
5536
+ /* @__PURE__ */ jsx15("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
5325
5537
  ] })
5326
5538
  ] })
5327
5539
  ] });
@@ -5329,7 +5541,7 @@ function DestinationBreadcrumb({
5329
5541
 
5330
5542
  // src/ui/link-modal/SectionTreeItem.tsx
5331
5543
  import { GalleryVertical as GalleryVertical2 } from "lucide-react";
5332
- import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
5544
+ import { jsx as jsx16, jsxs as jsxs9 } from "react/jsx-runtime";
5333
5545
  function SectionTreeItem({
5334
5546
  section,
5335
5547
  onSelect,
@@ -5337,7 +5549,7 @@ function SectionTreeItem({
5337
5549
  }) {
5338
5550
  const interactive = Boolean(onSelect);
5339
5551
  return /* @__PURE__ */ jsxs9("div", { className: "flex h-9 w-full items-end pl-3", children: [
5340
- /* @__PURE__ */ jsx15(
5552
+ /* @__PURE__ */ jsx16(
5341
5553
  "div",
5342
5554
  {
5343
5555
  className: "mr-[-1px] h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
@@ -5362,7 +5574,7 @@ function SectionTreeItem({
5362
5574
  interactive && selected && "border-primary"
5363
5575
  ),
5364
5576
  children: [
5365
- /* @__PURE__ */ jsx15(
5577
+ /* @__PURE__ */ jsx16(
5366
5578
  GalleryVertical2,
5367
5579
  {
5368
5580
  size: 16,
@@ -5370,7 +5582,7 @@ function SectionTreeItem({
5370
5582
  "aria-hidden": true
5371
5583
  }
5372
5584
  ),
5373
- /* @__PURE__ */ jsx15("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
5585
+ /* @__PURE__ */ jsx16("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
5374
5586
  ]
5375
5587
  }
5376
5588
  )
@@ -5378,14 +5590,14 @@ function SectionTreeItem({
5378
5590
  }
5379
5591
 
5380
5592
  // src/ui/link-modal/UrlOrPageInput.tsx
5381
- import { useEffect as useEffect3, useId as useId2, useRef as useRef4, useState as useState3 } from "react";
5593
+ import { useEffect as useEffect3, useId as useId2, useRef as useRef4, useState as useState4 } from "react";
5382
5594
 
5383
5595
  // src/ui/input.tsx
5384
5596
  import * as React9 from "react";
5385
- import { jsx as jsx16 } from "react/jsx-runtime";
5597
+ import { jsx as jsx17 } from "react/jsx-runtime";
5386
5598
  var Input = React9.forwardRef(
5387
5599
  ({ className, type, ...props }, ref) => {
5388
- return /* @__PURE__ */ jsx16(
5600
+ return /* @__PURE__ */ jsx17(
5389
5601
  "input",
5390
5602
  {
5391
5603
  type,
@@ -5404,9 +5616,9 @@ Input.displayName = "Input";
5404
5616
 
5405
5617
  // src/ui/label.tsx
5406
5618
  import { Label as LabelPrimitive } from "radix-ui";
5407
- import { jsx as jsx17 } from "react/jsx-runtime";
5619
+ import { jsx as jsx18 } from "react/jsx-runtime";
5408
5620
  function Label({ className, ...props }) {
5409
- return /* @__PURE__ */ jsx17(
5621
+ return /* @__PURE__ */ jsx18(
5410
5622
  LabelPrimitive.Root,
5411
5623
  {
5412
5624
  "data-slot": "label",
@@ -5418,11 +5630,11 @@ function Label({ className, ...props }) {
5418
5630
 
5419
5631
  // src/ui/link-modal/UrlOrPageInput.tsx
5420
5632
  import { ChevronDown, File as File2, X as X2 } from "lucide-react";
5421
- import { jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
5633
+ import { jsx as jsx19, jsxs as jsxs10 } from "react/jsx-runtime";
5422
5634
  function FieldChevron({
5423
5635
  onClick
5424
5636
  }) {
5425
- return /* @__PURE__ */ jsx18(
5637
+ return /* @__PURE__ */ jsx19(
5426
5638
  "button",
5427
5639
  {
5428
5640
  type: "button",
@@ -5430,7 +5642,7 @@ function FieldChevron({
5430
5642
  onClick,
5431
5643
  "aria-label": "Open page list",
5432
5644
  tabIndex: -1,
5433
- children: /* @__PURE__ */ jsx18(ChevronDown, { size: 16 })
5645
+ children: /* @__PURE__ */ jsx19(ChevronDown, { size: 16 })
5434
5646
  }
5435
5647
  );
5436
5648
  }
@@ -5449,7 +5661,7 @@ function UrlOrPageInput({
5449
5661
  const inputId = useId2();
5450
5662
  const inputRef = useRef4(null);
5451
5663
  const rootRef = useRef4(null);
5452
- const [isFocused, setIsFocused] = useState3(false);
5664
+ const [isFocused, setIsFocused] = useState4(false);
5453
5665
  useEffect3(() => {
5454
5666
  if (!dropdownOpen) return;
5455
5667
  const isOutside = (e) => {
@@ -5492,10 +5704,10 @@ function UrlOrPageInput({
5492
5704
  urlError ? "border-destructive shadow-[0_0_0_1px_var(--ohw-destructive)]" : isFocused ? "border-primary shadow-[0_0_0_1px_var(--ohw-primary)]" : "border-input"
5493
5705
  );
5494
5706
  return /* @__PURE__ */ jsxs10("div", { className: "flex w-full flex-col gap-2 p-0", children: [
5495
- /* @__PURE__ */ jsx18(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
5707
+ /* @__PURE__ */ jsx19(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
5496
5708
  /* @__PURE__ */ jsxs10("div", { ref: rootRef, className: "relative w-full", children: [
5497
5709
  /* @__PURE__ */ jsxs10("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
5498
- selectedPage ? /* @__PURE__ */ jsx18("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ jsx18(
5710
+ selectedPage ? /* @__PURE__ */ jsx19("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ jsx19(
5499
5711
  File2,
5500
5712
  {
5501
5713
  size: 16,
@@ -5503,7 +5715,7 @@ function UrlOrPageInput({
5503
5715
  "aria-hidden": true
5504
5716
  }
5505
5717
  ) }) : null,
5506
- readOnly ? /* @__PURE__ */ jsx18("span", { className: "min-w-0 flex-1 truncate text-sm leading-5 text-foreground", children: selectedPage?.title ?? value }) : /* @__PURE__ */ jsx18(
5718
+ readOnly ? /* @__PURE__ */ jsx19("span", { className: "min-w-0 flex-1 truncate text-sm leading-5 text-foreground", children: selectedPage?.title ?? value }) : /* @__PURE__ */ jsx19(
5507
5719
  Input,
5508
5720
  {
5509
5721
  ref: inputRef,
@@ -5529,7 +5741,7 @@ function UrlOrPageInput({
5529
5741
  )
5530
5742
  }
5531
5743
  ),
5532
- selectedPage && !readOnly ? /* @__PURE__ */ jsx18(
5744
+ selectedPage && !readOnly ? /* @__PURE__ */ jsx19(
5533
5745
  "button",
5534
5746
  {
5535
5747
  type: "button",
@@ -5537,12 +5749,12 @@ function UrlOrPageInput({
5537
5749
  onMouseDown: clearSelection,
5538
5750
  "aria-label": "Clear selected page",
5539
5751
  tabIndex: -1,
5540
- children: /* @__PURE__ */ jsx18(X2, { size: 16, "aria-hidden": true })
5752
+ children: /* @__PURE__ */ jsx19(X2, { size: 16, "aria-hidden": true })
5541
5753
  }
5542
5754
  ) : null,
5543
- !readOnly ? /* @__PURE__ */ jsx18(FieldChevron, { onClick: toggleDropdown }) : null
5755
+ !readOnly ? /* @__PURE__ */ jsx19(FieldChevron, { onClick: toggleDropdown }) : null
5544
5756
  ] }),
5545
- dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ jsx18(
5757
+ dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ jsx19(
5546
5758
  "div",
5547
5759
  {
5548
5760
  "data-ohw-link-page-dropdown": "",
@@ -5555,8 +5767,8 @@ function UrlOrPageInput({
5555
5767
  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",
5556
5768
  onClick: () => onPageSelect(page),
5557
5769
  children: [
5558
- /* @__PURE__ */ jsx18(File2, { size: 16, className: "shrink-0", "aria-hidden": true }),
5559
- /* @__PURE__ */ jsx18("span", { className: "truncate", children: page.title })
5770
+ /* @__PURE__ */ jsx19(File2, { size: 16, className: "shrink-0", "aria-hidden": true }),
5771
+ /* @__PURE__ */ jsx19("span", { className: "truncate", children: page.title })
5560
5772
  ]
5561
5773
  },
5562
5774
  page.path
@@ -5564,34 +5776,34 @@ function UrlOrPageInput({
5564
5776
  }
5565
5777
  ) : null
5566
5778
  ] }),
5567
- urlError ? /* @__PURE__ */ jsx18("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
5779
+ urlError ? /* @__PURE__ */ jsx19("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
5568
5780
  ] });
5569
5781
  }
5570
5782
 
5571
5783
  // src/ui/link-modal/LinkEditorPanel.tsx
5572
- import { Fragment as Fragment3, jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
5784
+ import { Fragment as Fragment3, jsx as jsx20, jsxs as jsxs11 } from "react/jsx-runtime";
5573
5785
  function LinkEditorPanel({ state, onClose }) {
5574
5786
  const isCancel = state.secondaryLabel === "Cancel" || state.secondaryLabel === "Back to sections";
5575
5787
  return /* @__PURE__ */ jsxs11(Fragment3, { children: [
5576
- /* @__PURE__ */ jsx19(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx19(
5788
+ /* @__PURE__ */ jsx20(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx20(
5577
5789
  "button",
5578
5790
  {
5579
5791
  type: "button",
5580
5792
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50 h-7",
5581
5793
  "aria-label": "Close",
5582
5794
  onClick: onClose,
5583
- children: /* @__PURE__ */ jsx19(X3, { size: 16, "aria-hidden": true })
5795
+ children: /* @__PURE__ */ jsx20(X3, { size: 16, "aria-hidden": true })
5584
5796
  }
5585
5797
  ) }),
5586
- /* @__PURE__ */ jsx19(DialogHeader, { className: "w-full gap-1.5 p-6 pr-12", children: /* @__PURE__ */ jsx19(DialogTitle, { className: "m-0 w-full break-words", children: state.title }) }),
5798
+ /* @__PURE__ */ jsx20(DialogHeader, { className: "w-full gap-1.5 p-6 pr-12", children: /* @__PURE__ */ jsx20(DialogTitle, { className: "m-0 w-full break-words", children: state.title }) }),
5587
5799
  /* @__PURE__ */ jsxs11("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
5588
- state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ jsx19(
5800
+ state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ jsx20(
5589
5801
  DestinationBreadcrumb,
5590
5802
  {
5591
5803
  pageTitle: state.selectedPage.title,
5592
5804
  sectionLabel: state.selectedSection.label
5593
5805
  }
5594
- ) : /* @__PURE__ */ jsx19(
5806
+ ) : /* @__PURE__ */ jsx20(
5595
5807
  UrlOrPageInput,
5596
5808
  {
5597
5809
  value: state.searchValue,
@@ -5605,7 +5817,7 @@ function LinkEditorPanel({ state, onClose }) {
5605
5817
  }
5606
5818
  ),
5607
5819
  state.showChooseSection ? /* @__PURE__ */ jsxs11("div", { className: "flex flex-col justify-center gap-2", children: [
5608
- /* @__PURE__ */ jsx19(
5820
+ /* @__PURE__ */ jsx20(
5609
5821
  Button,
5610
5822
  {
5611
5823
  type: "button",
@@ -5617,14 +5829,14 @@ function LinkEditorPanel({ state, onClose }) {
5617
5829
  }
5618
5830
  ),
5619
5831
  /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
5620
- /* @__PURE__ */ jsx19(Info, { size: 16, className: "shrink-0", "aria-hidden": true }),
5621
- /* @__PURE__ */ jsx19("span", { children: "Pick a section this link should scroll to." })
5832
+ /* @__PURE__ */ jsx20(Info, { size: 16, className: "shrink-0", "aria-hidden": true }),
5833
+ /* @__PURE__ */ jsx20("span", { children: "Pick a section this link should scroll to." })
5622
5834
  ] })
5623
5835
  ] }) : null,
5624
- state.showSectionRow && state.selectedSection ? /* @__PURE__ */ jsx19(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
5836
+ state.showSectionRow && state.selectedSection ? /* @__PURE__ */ jsx20(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
5625
5837
  ] }),
5626
5838
  /* @__PURE__ */ jsxs11(DialogFooter, { className: "w-full px-6 pb-6", children: [
5627
- /* @__PURE__ */ jsx19(
5839
+ /* @__PURE__ */ jsx20(
5628
5840
  Button,
5629
5841
  {
5630
5842
  type: "button",
@@ -5639,7 +5851,7 @@ function LinkEditorPanel({ state, onClose }) {
5639
5851
  children: state.secondaryLabel
5640
5852
  }
5641
5853
  ),
5642
- /* @__PURE__ */ jsx19(
5854
+ /* @__PURE__ */ jsx20(
5643
5855
  Button,
5644
5856
  {
5645
5857
  type: "button",
@@ -5658,11 +5870,11 @@ function LinkEditorPanel({ state, onClose }) {
5658
5870
  }
5659
5871
 
5660
5872
  // src/ui/link-modal/SectionPickerOverlay.tsx
5661
- import { useCallback, useEffect as useEffect4, useMemo as useMemo2, useRef as useRef5, useState as useState4 } from "react";
5873
+ import { useCallback as useCallback2, useEffect as useEffect4, useMemo as useMemo2, useRef as useRef5, useState as useState5 } from "react";
5662
5874
  import { createPortal } from "react-dom";
5663
5875
  import { ArrowLeft, Check } from "lucide-react";
5664
5876
  import { usePathname, useRouter } from "next/navigation";
5665
- import { jsx as jsx20, jsxs as jsxs12 } from "react/jsx-runtime";
5877
+ import { jsx as jsx21, jsxs as jsxs12 } from "react/jsx-runtime";
5666
5878
  var DIM_OVERLAY = "rgba(0, 0, 0, 0.45)";
5667
5879
  function rectsEqual(a, b) {
5668
5880
  if (a.size !== b.size) return false;
@@ -5695,7 +5907,7 @@ function hitTestSectionId(x, y, sectionIds, rects) {
5695
5907
  return null;
5696
5908
  }
5697
5909
  function useSectionRects(sectionIdsKey, enabled) {
5698
- const [rects, setRects] = useState4(/* @__PURE__ */ new Map());
5910
+ const [rects, setRects] = useState5(/* @__PURE__ */ new Map());
5699
5911
  const sectionIds = useMemo2(
5700
5912
  () => sectionIdsKey ? sectionIdsKey.split("\0") : [],
5701
5913
  [sectionIdsKey]
@@ -5741,13 +5953,13 @@ function SectionPickerOverlay({
5741
5953
  }) {
5742
5954
  const router = useRouter();
5743
5955
  const pathname = usePathname();
5744
- const [selectedId, setSelectedId] = useState4(null);
5745
- const [hoveredId, setHoveredId] = useState4(null);
5956
+ const [selectedId, setSelectedId] = useState5(null);
5957
+ const [hoveredId, setHoveredId] = useState5(null);
5746
5958
  const pointerRef = useRef5(null);
5747
5959
  const pointerScreenRef = useRef5(null);
5748
5960
  const iframeOffsetTopRef = useRef5(null);
5749
5961
  const sectionIdsRef = useRef5([]);
5750
- const [chromeClip, setChromeClip] = useState4(
5962
+ const [chromeClip, setChromeClip] = useState5(
5751
5963
  () => ({
5752
5964
  top: 0,
5753
5965
  bottom: typeof window !== "undefined" ? window.innerHeight : 0
@@ -5789,7 +6001,7 @@ function SectionPickerOverlay({
5789
6001
  );
5790
6002
  sectionIdsRef.current = sectionIds;
5791
6003
  const rects = useSectionRects(sectionIdsKey, isOnTargetPage);
5792
- const applyHoverAt = useCallback(
6004
+ const applyHoverAt = useCallback2(
5793
6005
  (x, y, liveRects) => {
5794
6006
  const ids = sectionIdsRef.current;
5795
6007
  const map = liveRects ?? readSectionRects(ids);
@@ -5869,7 +6081,7 @@ function SectionPickerOverlay({
5869
6081
  window.removeEventListener("message", onPointerSync);
5870
6082
  };
5871
6083
  }, [rects, applyHoverAt]);
5872
- const handleSelect = useCallback(
6084
+ const handleSelect = useCallback2(
5873
6085
  (section) => {
5874
6086
  if (selectedId) return;
5875
6087
  setSelectedId(section.id);
@@ -5901,7 +6113,7 @@ function SectionPickerOverlay({
5901
6113
  role: "dialog",
5902
6114
  "aria-label": "Choose a section",
5903
6115
  children: [
5904
- /* @__PURE__ */ jsx20(
6116
+ /* @__PURE__ */ jsx21(
5905
6117
  "div",
5906
6118
  {
5907
6119
  className: "pointer-events-auto fixed left-5 z-[2]",
@@ -5915,14 +6127,14 @@ function SectionPickerOverlay({
5915
6127
  className: "h-8 min-w-0 gap-1 border-border bg-background px-2 py-1.5 shadow-sm hover:bg-muted cursor-pointer",
5916
6128
  onClick: onBack,
5917
6129
  children: [
5918
- /* @__PURE__ */ jsx20(ArrowLeft, { className: "size-4 shrink-0", "aria-hidden": true }),
6130
+ /* @__PURE__ */ jsx21(ArrowLeft, { className: "size-4 shrink-0", "aria-hidden": true }),
5919
6131
  "Back"
5920
6132
  ]
5921
6133
  }
5922
6134
  )
5923
6135
  }
5924
6136
  ),
5925
- /* @__PURE__ */ jsx20(
6137
+ /* @__PURE__ */ jsx21(
5926
6138
  "div",
5927
6139
  {
5928
6140
  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",
@@ -5935,7 +6147,7 @@ function SectionPickerOverlay({
5935
6147
  children: "Click on section to select"
5936
6148
  }
5937
6149
  ),
5938
- !isOnTargetPage ? /* @__PURE__ */ jsx20(
6150
+ !isOnTargetPage ? /* @__PURE__ */ jsx21(
5939
6151
  "div",
5940
6152
  {
5941
6153
  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",
@@ -5943,7 +6155,7 @@ function SectionPickerOverlay({
5943
6155
  children: "Loading page preview\u2026"
5944
6156
  }
5945
6157
  ) : null,
5946
- isOnTargetPage && liveSections.length === 0 ? /* @__PURE__ */ jsx20("div", { className: "pointer-events-auto fixed inset-0 z-[1] flex items-center justify-center bg-muted/40", children: /* @__PURE__ */ jsx20("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." }) }) : null,
6158
+ isOnTargetPage && liveSections.length === 0 ? /* @__PURE__ */ jsx21("div", { className: "pointer-events-auto fixed inset-0 z-[1] flex items-center justify-center bg-muted/40", children: /* @__PURE__ */ jsx21("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." }) }) : null,
5947
6159
  isOnTargetPage ? liveSections.map((section) => {
5948
6160
  const rect = rects.get(section.id);
5949
6161
  if (!rect || rect.width <= 0 || rect.height <= 0) return null;
@@ -5965,7 +6177,7 @@ function SectionPickerOverlay({
5965
6177
  "aria-label": `Select section ${section.label}`,
5966
6178
  onClick: () => handleSelect(section),
5967
6179
  children: [
5968
- isLit ? /* @__PURE__ */ jsx20(
6180
+ isLit ? /* @__PURE__ */ jsx21(
5969
6181
  "span",
5970
6182
  {
5971
6183
  className: "pointer-events-none absolute",
@@ -5978,13 +6190,13 @@ function SectionPickerOverlay({
5978
6190
  "aria-hidden": true
5979
6191
  }
5980
6192
  ) : null,
5981
- isSelected ? /* @__PURE__ */ jsx20(
6193
+ isSelected ? /* @__PURE__ */ jsx21(
5982
6194
  "span",
5983
6195
  {
5984
6196
  className: "absolute right-3 top-3 flex size-8 items-center justify-center rounded-full text-white",
5985
6197
  style: { backgroundColor: "var(--ohw-primary, #0885fe)" },
5986
6198
  "aria-hidden": true,
5987
- children: /* @__PURE__ */ jsx20(Check, { className: "size-5" })
6199
+ children: /* @__PURE__ */ jsx21(Check, { className: "size-5" })
5988
6200
  }
5989
6201
  ) : null
5990
6202
  ]
@@ -6000,7 +6212,7 @@ function SectionPickerOverlay({
6000
6212
  }
6001
6213
 
6002
6214
  // src/ui/link-modal/useLinkModalState.ts
6003
- import { useCallback as useCallback2, useEffect as useEffect5, useMemo as useMemo3, useState as useState5 } from "react";
6215
+ import { useCallback as useCallback3, useEffect as useEffect5, useMemo as useMemo3, useState as useState6 } from "react";
6004
6216
  function useLinkModalState({
6005
6217
  open,
6006
6218
  mode,
@@ -6013,13 +6225,13 @@ function useLinkModalState({
6013
6225
  onSubmit
6014
6226
  }) {
6015
6227
  const availablePages = useMemo3(() => pages, [pages]);
6016
- const [searchValue, setSearchValue] = useState5("");
6017
- const [selectedPage, setSelectedPage] = useState5(null);
6018
- const [selectedSection, setSelectedSection] = useState5(null);
6019
- const [step, setStep] = useState5("input");
6020
- const [dropdownOpen, setDropdownOpen] = useState5(false);
6021
- const [urlError, setUrlError] = useState5("");
6022
- const reset = useCallback2(() => {
6228
+ const [searchValue, setSearchValue] = useState6("");
6229
+ const [selectedPage, setSelectedPage] = useState6(null);
6230
+ const [selectedSection, setSelectedSection] = useState6(null);
6231
+ const [step, setStep] = useState6("input");
6232
+ const [dropdownOpen, setDropdownOpen] = useState6(false);
6233
+ const [urlError, setUrlError] = useState6("");
6234
+ const reset = useCallback3(() => {
6023
6235
  setSearchValue("");
6024
6236
  setSelectedPage(null);
6025
6237
  setSelectedSection(null);
@@ -6164,7 +6376,7 @@ function useLinkModalState({
6164
6376
  }
6165
6377
 
6166
6378
  // src/ui/link-modal/LinkPopover.tsx
6167
- import { Fragment as Fragment4, jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
6379
+ import { Fragment as Fragment4, jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
6168
6380
  function postToParent(data) {
6169
6381
  window.parent?.postMessage(data, "*");
6170
6382
  }
@@ -6261,14 +6473,14 @@ function LinkPopover({
6261
6473
  };
6262
6474
  }, [open, sectionPickerActive]);
6263
6475
  return /* @__PURE__ */ jsxs13(Fragment4, { children: [
6264
- /* @__PURE__ */ jsx21(
6476
+ /* @__PURE__ */ jsx22(
6265
6477
  Dialog2,
6266
6478
  {
6267
6479
  open: open && !sectionPickerActive,
6268
6480
  onOpenChange: (next) => {
6269
6481
  if (!next) onClose?.();
6270
6482
  },
6271
- children: /* @__PURE__ */ jsx21(
6483
+ children: /* @__PURE__ */ jsx22(
6272
6484
  DialogContent,
6273
6485
  {
6274
6486
  ref: panelRef,
@@ -6278,12 +6490,12 @@ function LinkPopover({
6278
6490
  "data-ohw-bridge": "",
6279
6491
  showCloseButton: false,
6280
6492
  className: "gap-0 p-0 w-full max-w-[448px] pointer-events-auto z-[2147483646] overflow-visible",
6281
- children: /* @__PURE__ */ jsx21(LinkEditorPanel, { state, onClose })
6493
+ children: /* @__PURE__ */ jsx22(LinkEditorPanel, { state, onClose })
6282
6494
  }
6283
6495
  )
6284
6496
  }
6285
6497
  ),
6286
- sectionPickerActive && state.selectedPage ? /* @__PURE__ */ jsx21(
6498
+ sectionPickerActive && state.selectedPage ? /* @__PURE__ */ jsx22(
6287
6499
  SectionPickerOverlay,
6288
6500
  {
6289
6501
  pagePath: state.selectedPage.path,
@@ -6822,9 +7034,57 @@ function insertNavbarItem(href, label, afterAnchor = null) {
6822
7034
  order
6823
7035
  };
6824
7036
  }
7037
+ function duplicateNavbarItem(sourceAnchor) {
7038
+ if (!isNavbarLinkItem(sourceAnchor)) return null;
7039
+ const sourceHrefKey = sourceAnchor.getAttribute("data-ohw-href-key");
7040
+ if (!sourceHrefKey || !isNavbarHrefKey(sourceHrefKey)) return null;
7041
+ const href = getLinkHref(sourceAnchor);
7042
+ const labelEl = sourceAnchor.querySelector('[data-ohw-editable="text"]');
7043
+ const label = (labelEl?.textContent ?? "").trim() || "Untitled";
7044
+ const forest = getNavForestFromDom();
7045
+ const sourceNode = forest.find((n) => n.id === sourceHrefKey);
7046
+ const childIds = sourceNode?.children.map((c) => c.id) ?? [];
7047
+ const primary = insertNavbarItem(href, label, sourceAnchor);
7048
+ const childResults = [];
7049
+ let after = primary.anchor;
7050
+ for (const childId of childIds) {
7051
+ const childEl = findCounterpartByHrefKey(childId, document) ?? document.querySelector(`[data-ohw-href-key="${CSS.escape(childId)}"]`);
7052
+ if (!childEl || !isNavbarLinkItem(childEl)) continue;
7053
+ const childHref = getLinkHref(childEl);
7054
+ const childLabelEl = childEl.querySelector('[data-ohw-editable="text"]');
7055
+ const childLabel = (childLabelEl?.textContent ?? "").trim() || "Untitled";
7056
+ const inserted = insertNavbarItem(childHref, childLabel, after);
7057
+ childResults.push(inserted);
7058
+ after = inserted.anchor;
7059
+ }
7060
+ let orderJson;
7061
+ if (childResults.length > 0) {
7062
+ const nextForest = getNavForestFromDom();
7063
+ const withoutNew = nextForest.filter(
7064
+ (n) => n.id !== primary.hrefKey && !childResults.some((c) => c.hrefKey === n.id)
7065
+ );
7066
+ const sourceIdx = withoutNew.findIndex((n) => n.id === sourceHrefKey);
7067
+ const insertAt = sourceIdx >= 0 ? sourceIdx + 1 : withoutNew.length;
7068
+ withoutNew.splice(insertAt, 0, {
7069
+ id: primary.hrefKey,
7070
+ children: childResults.map((c) => ({ id: c.hrefKey, children: [] }))
7071
+ });
7072
+ applyNavForest(withoutNew);
7073
+ orderJson = serializeNavOrder(withoutNew);
7074
+ } else {
7075
+ orderJson = serializeNavOrder(getNavForestFromDom());
7076
+ }
7077
+ return {
7078
+ ...primary,
7079
+ order: flattenNavOrder(parseNavOrderJson(orderJson) ?? getNavForestFromDom()),
7080
+ childResults,
7081
+ orderJson
7082
+ };
7083
+ }
6825
7084
 
6826
7085
  // src/lib/footer-items.ts
6827
7086
  var FOOTER_ORDER_KEY = "__ohw_footer_order";
7087
+ var MAX_FOOTER_COLUMNS = 18;
6828
7088
  var FOOTER_HREF_RE = /^footer-(\d+)-(\d+)-href$/;
6829
7089
  function parseFooterHrefKey(key) {
6830
7090
  if (!key) return null;
@@ -7005,7 +7265,191 @@ function parseFooterOrder(content) {
7005
7265
  return null;
7006
7266
  }
7007
7267
  }
7268
+ var FOOTER_HEADING_RE = /^footer-(\d+)-heading$/;
7269
+ var FOOTER_LABEL_RE = /^footer-(\d+)-(\d+)-label$/;
7270
+ var DEFAULT_FOOTER_COLUMN_HEADING = "New";
7271
+ var DEFAULT_FOOTER_COLUMN_LINK_LABEL = "New link";
7272
+ var DEFAULT_FOOTER_COLUMN_LINK_HREF = "";
7273
+ function isFooterLinksContainer(el) {
7274
+ return el.hasAttribute("data-ohw-footer-links") || el.classList.contains("rb-footer-links");
7275
+ }
7276
+ function getFooterColumnIndicesInDom() {
7277
+ const indices = /* @__PURE__ */ new Set();
7278
+ for (const col of listFooterColumns()) {
7279
+ const attr = col.getAttribute("data-ohw-footer-col");
7280
+ if (attr != null) {
7281
+ const n = parseInt(attr, 10);
7282
+ if (Number.isFinite(n)) indices.add(n);
7283
+ }
7284
+ for (const link of listFooterLinksInColumn(col)) {
7285
+ const parsed = parseFooterHrefKey(link.getAttribute("data-ohw-href-key"));
7286
+ if (parsed) indices.add(parsed.col);
7287
+ }
7288
+ const heading = col.querySelector('[data-ohw-key^="footer-"][data-ohw-key$="-heading"]');
7289
+ const headingKey = heading?.getAttribute("data-ohw-key");
7290
+ if (headingKey) {
7291
+ const match = headingKey.match(FOOTER_HEADING_RE);
7292
+ if (match) indices.add(parseInt(match[1], 10));
7293
+ }
7294
+ }
7295
+ return [...indices].sort((a, b) => a - b);
7296
+ }
7297
+ function getNextFooterColumnIndex() {
7298
+ const indices = getFooterColumnIndicesInDom();
7299
+ if (indices.length === 0) return 0;
7300
+ return Math.max(...indices) + 1;
7301
+ }
7302
+ function canAddFooterColumn() {
7303
+ return listFooterColumns().length < MAX_FOOTER_COLUMNS;
7304
+ }
7305
+ function buildFooterHeading(colIndex, text) {
7306
+ const heading = document.createElement("p");
7307
+ heading.setAttribute("data-ohw-editable", "text");
7308
+ heading.setAttribute("data-ohw-key", `footer-${colIndex}-heading`);
7309
+ heading.textContent = text;
7310
+ heading.style.cssText = [
7311
+ "color: var(--espresso, #3d312b)",
7312
+ "font-size: 14px",
7313
+ "font-weight: 800",
7314
+ "opacity: 0.82",
7315
+ "margin: 0 0 6px",
7316
+ "padding: 0",
7317
+ "line-height: 1.2"
7318
+ ].join(";");
7319
+ return heading;
7320
+ }
7321
+ function buildFooterLink(colIndex, itemIndex, href, label, template) {
7322
+ const anchor = cloneFooterLinkShell(template);
7323
+ anchor.setAttribute("href", href);
7324
+ anchor.setAttribute("data-ohw-href-key", `footer-${colIndex}-${itemIndex}-href`);
7325
+ const span = document.createElement("span");
7326
+ span.setAttribute("data-ohw-editable", "text");
7327
+ span.setAttribute("data-ohw-key", `footer-${colIndex}-${itemIndex}-label`);
7328
+ span.textContent = label;
7329
+ anchor.appendChild(span);
7330
+ return anchor;
7331
+ }
7332
+ function footerColumnExistsInDom(colIndex) {
7333
+ 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;
7334
+ }
7335
+ function getFooterLinkTemplate() {
7336
+ for (const col of listFooterColumns()) {
7337
+ const link = listFooterLinksInColumn(col)[0];
7338
+ if (link) return link;
7339
+ }
7340
+ return null;
7341
+ }
7342
+ function getFooterColumnTemplate() {
7343
+ return listFooterColumns()[0] ?? null;
7344
+ }
7345
+ function insertFooterColumnDom(colIndex, heading, items) {
7346
+ const container = getFooterLinksContainer();
7347
+ if (!container) return null;
7348
+ const colTemplate = getFooterColumnTemplate();
7349
+ const linkTemplate = getFooterLinkTemplate();
7350
+ const column = document.createElement("div");
7351
+ if (colTemplate?.className) column.className = colTemplate.className;
7352
+ else column.className = "rb-footer-link-col";
7353
+ column.setAttribute("data-ohw-footer-col", String(colIndex));
7354
+ if (colTemplate) {
7355
+ const gap = getComputedStyle(colTemplate).gap;
7356
+ if (gap && gap !== "normal") column.style.gap = gap;
7357
+ column.style.display = getComputedStyle(colTemplate).display || "flex";
7358
+ column.style.flexDirection = "column";
7359
+ }
7360
+ column.appendChild(buildFooterHeading(colIndex, heading));
7361
+ let firstLink = null;
7362
+ items.forEach((item, itemIndex) => {
7363
+ const link = buildFooterLink(colIndex, itemIndex, item.href, item.label, linkTemplate);
7364
+ column.appendChild(link);
7365
+ if (!firstLink) firstLink = link;
7366
+ });
7367
+ container.appendChild(column);
7368
+ return { column, firstLink };
7369
+ }
7370
+ function insertFooterColumn(heading = DEFAULT_FOOTER_COLUMN_HEADING, linkLabel = DEFAULT_FOOTER_COLUMN_LINK_LABEL, linkHref = DEFAULT_FOOTER_COLUMN_LINK_HREF) {
7371
+ if (!canAddFooterColumn()) {
7372
+ throw new Error(`Footer column limit reached (${MAX_FOOTER_COLUMNS})`);
7373
+ }
7374
+ const colIndex = getNextFooterColumnIndex();
7375
+ const inserted = insertFooterColumnDom(colIndex, heading, [{ href: linkHref, label: linkLabel }]);
7376
+ if (!inserted?.firstLink) throw new Error("Failed to insert footer column");
7377
+ syncFooterColumnIndices(listFooterColumns());
7378
+ return {
7379
+ column: inserted.column,
7380
+ firstLink: inserted.firstLink,
7381
+ colIndex,
7382
+ headingKey: `footer-${colIndex}-heading`,
7383
+ hrefKey: `footer-${colIndex}-0-href`,
7384
+ labelKey: `footer-${colIndex}-0-label`,
7385
+ heading,
7386
+ label: linkLabel,
7387
+ href: linkHref,
7388
+ order: getFooterOrderFromDom()
7389
+ };
7390
+ }
7391
+ function collectFooterColumnIndicesFromContent(content) {
7392
+ const indices = /* @__PURE__ */ new Set();
7393
+ for (const key of Object.keys(content)) {
7394
+ const href = parseFooterHrefKey(key);
7395
+ if (href) indices.add(href.col);
7396
+ const heading = key.match(FOOTER_HEADING_RE);
7397
+ if (heading) indices.add(parseInt(heading[1], 10));
7398
+ const label = key.match(FOOTER_LABEL_RE);
7399
+ if (label) indices.add(parseInt(label[1], 10));
7400
+ }
7401
+ const order = parseFooterOrder(content);
7402
+ if (order) {
7403
+ for (const col of order) {
7404
+ for (const hrefKey of col) {
7405
+ const parsed = parseFooterHrefKey(hrefKey);
7406
+ if (parsed) indices.add(parsed.col);
7407
+ }
7408
+ }
7409
+ }
7410
+ return [...indices].sort((a, b) => a - b);
7411
+ }
7412
+ function collectFooterItemsForColumn(content, colIndex) {
7413
+ const itemIndices = /* @__PURE__ */ new Set();
7414
+ for (const key of Object.keys(content)) {
7415
+ const href = parseFooterHrefKey(key);
7416
+ if (href?.col === colIndex) itemIndices.add(href.item);
7417
+ const label = key.match(FOOTER_LABEL_RE);
7418
+ if (label && parseInt(label[1], 10) === colIndex) {
7419
+ itemIndices.add(parseInt(label[2], 10));
7420
+ }
7421
+ }
7422
+ const sorted = [...itemIndices].sort((a, b) => a - b);
7423
+ if (sorted.length === 0) {
7424
+ return [
7425
+ {
7426
+ href: content[`footer-${colIndex}-0-href`] ?? DEFAULT_FOOTER_COLUMN_LINK_HREF,
7427
+ label: content[`footer-${colIndex}-0-label`] ?? DEFAULT_FOOTER_COLUMN_LINK_LABEL
7428
+ }
7429
+ ];
7430
+ }
7431
+ return sorted.map((itemIndex) => ({
7432
+ href: content[`footer-${colIndex}-${itemIndex}-href`] ?? DEFAULT_FOOTER_COLUMN_LINK_HREF,
7433
+ label: content[`footer-${colIndex}-${itemIndex}-label`] ?? DEFAULT_FOOTER_COLUMN_LINK_LABEL
7434
+ }));
7435
+ }
7436
+ function reconcileFooterColumnsFromContent(content) {
7437
+ const indices = collectFooterColumnIndicesFromContent(content);
7438
+ for (const colIndex of indices) {
7439
+ if (footerColumnExistsInDom(colIndex)) continue;
7440
+ const heading = content[`footer-${colIndex}-heading`] ?? DEFAULT_FOOTER_COLUMN_HEADING;
7441
+ const items = collectFooterItemsForColumn(content, colIndex);
7442
+ const hasPayload = Boolean(content[`footer-${colIndex}-heading`]) || items.some(
7443
+ (_, i) => content[`footer-${colIndex}-${i}-href`] !== void 0 || content[`footer-${colIndex}-${i}-label`] !== void 0
7444
+ ) || (parseFooterOrder(content)?.some(
7445
+ (col) => col.some((k) => parseFooterHrefKey(k)?.col === colIndex)
7446
+ ) ?? false);
7447
+ if (!hasPayload) continue;
7448
+ insertFooterColumnDom(colIndex, heading, items);
7449
+ }
7450
+ }
7008
7451
  function reconcileFooterOrderFromContent(content) {
7452
+ reconcileFooterColumnsFromContent(content);
7009
7453
  const order = parseFooterOrder(content);
7010
7454
  if (!order?.length) return;
7011
7455
  const current = getFooterOrderFromDom();
@@ -7015,6 +7459,26 @@ function reconcileFooterOrderFromContent(content) {
7015
7459
  }
7016
7460
  applyFooterOrder(order);
7017
7461
  }
7462
+ function resolveFooterLinksContainerSelectionTarget(target, clientX, clientY, isPointOverItem) {
7463
+ const container = getFooterLinksContainer();
7464
+ if (!container) return null;
7465
+ const inContainer = target === container || container.contains(target) && Boolean(target.closest("[data-ohw-footer-links], .rb-footer-links"));
7466
+ if (!inContainer && target !== container) {
7467
+ const r2 = container.getBoundingClientRect();
7468
+ const over = clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
7469
+ if (!over) return null;
7470
+ }
7471
+ if (isPointOverItem(container, clientX, clientY)) return null;
7472
+ const column = target.closest("[data-ohw-footer-col], [data-ohw-footer-column]") ?? null;
7473
+ if (column && container.contains(column)) {
7474
+ if (target === column || column.contains(target)) return null;
7475
+ }
7476
+ if (target === container || container.contains(target) || inContainer) {
7477
+ if (target === container || isFooterLinksContainer(target)) return container;
7478
+ if (!column) return container;
7479
+ }
7480
+ return null;
7481
+ }
7018
7482
  function isRowLayoutColumn(links) {
7019
7483
  if (links.length < 2) return false;
7020
7484
  const firstTop = links[0].getBoundingClientRect().top;
@@ -7169,6 +7633,108 @@ function hitTestColumnDropSlot(clientX, _clientY) {
7169
7633
  }
7170
7634
  return best?.slot ?? null;
7171
7635
  }
7636
+ function getLinkHref2(el) {
7637
+ const key = el.getAttribute("data-ohw-href-key");
7638
+ if (key) {
7639
+ const stored = getStoredLinkHref(key);
7640
+ if (stored !== void 0) return stored;
7641
+ }
7642
+ return el.getAttribute("href") ?? "";
7643
+ }
7644
+ function getNextFooterItemIndex(col) {
7645
+ let max = -1;
7646
+ for (const el of document.querySelectorAll("footer [data-ohw-href-key]")) {
7647
+ const parsed = parseFooterHrefKey(el.getAttribute("data-ohw-href-key"));
7648
+ if (!parsed || parsed.col !== col) continue;
7649
+ if (parsed.item > max) max = parsed.item;
7650
+ }
7651
+ return max + 1;
7652
+ }
7653
+ function cloneFooterLinkShell(template) {
7654
+ const anchor = document.createElement("a");
7655
+ if (template) {
7656
+ anchor.style.cssText = template.style.cssText;
7657
+ if (template.className) anchor.className = template.className;
7658
+ }
7659
+ anchor.style.cursor = "pointer";
7660
+ anchor.style.textDecoration = "none";
7661
+ return anchor;
7662
+ }
7663
+ function insertFooterItem(column, href, label, afterAnchor = null) {
7664
+ const columns = listFooterColumns();
7665
+ const colIndex = columns.indexOf(column);
7666
+ if (colIndex < 0) throw new Error("Footer column not found");
7667
+ const item = getNextFooterItemIndex(colIndex);
7668
+ const hrefKey = `footer-${colIndex}-${item}-href`;
7669
+ const labelKey = `footer-${colIndex}-${item}-label`;
7670
+ const template = listFooterLinksInColumn(column)[0] ?? null;
7671
+ const anchor = cloneFooterLinkShell(template);
7672
+ anchor.href = href;
7673
+ anchor.setAttribute("data-ohw-href-key", hrefKey);
7674
+ const span = document.createElement("span");
7675
+ span.setAttribute("data-ohw-editable", "text");
7676
+ span.setAttribute("data-ohw-key", labelKey);
7677
+ span.textContent = label;
7678
+ anchor.appendChild(span);
7679
+ if (afterAnchor && afterAnchor.parentElement === column) {
7680
+ afterAnchor.insertAdjacentElement("afterend", anchor);
7681
+ } else {
7682
+ column.appendChild(anchor);
7683
+ }
7684
+ const order = getFooterOrderFromDom();
7685
+ applyFooterOrder(order);
7686
+ return {
7687
+ anchor,
7688
+ col: colIndex,
7689
+ item,
7690
+ hrefKey,
7691
+ labelKey,
7692
+ href,
7693
+ label,
7694
+ order
7695
+ };
7696
+ }
7697
+ function duplicateFooterItem(sourceAnchor) {
7698
+ if (!isFooterLinkAnchor(sourceAnchor)) return null;
7699
+ const column = findFooterColumnForLink(sourceAnchor);
7700
+ if (!column) return null;
7701
+ const href = getLinkHref2(sourceAnchor);
7702
+ const labelEl = sourceAnchor.querySelector('[data-ohw-editable="text"]');
7703
+ const label = (labelEl?.textContent ?? "").trim() || "Untitled";
7704
+ return insertFooterItem(column, href || "/", label, sourceAnchor);
7705
+ }
7706
+
7707
+ // src/lib/add-footer-column.ts
7708
+ function buildFooterColumnEditContentPatch(result) {
7709
+ return {
7710
+ [result.headingKey]: result.heading,
7711
+ [result.hrefKey]: result.href,
7712
+ [result.labelKey]: result.label,
7713
+ [FOOTER_ORDER_KEY]: JSON.stringify(result.order)
7714
+ };
7715
+ }
7716
+ function addFooterColumnWithPersist({
7717
+ postToParent: postToParent2
7718
+ }) {
7719
+ if (!canAddFooterColumn()) {
7720
+ postToParent2({
7721
+ type: "ow:toast",
7722
+ title: `Maximum ${MAX_FOOTER_COLUMNS} columns`,
7723
+ toastType: "error"
7724
+ });
7725
+ return null;
7726
+ }
7727
+ const result = insertFooterColumn();
7728
+ const patch = buildFooterColumnEditContentPatch(result);
7729
+ setStoredLinkHref(result.hrefKey, result.href);
7730
+ postToParent2({
7731
+ type: "ow:change",
7732
+ nodes: Object.entries(patch).map(([key, text]) => ({ key, text }))
7733
+ });
7734
+ postToParent2({ type: "ow:toast", title: "Item added", toastType: "success" });
7735
+ enforceLinkHrefs();
7736
+ return result;
7737
+ }
7172
7738
 
7173
7739
  // src/lib/item-drag-interaction.ts
7174
7740
  function disableNativeHrefDrag(el) {
@@ -7367,7 +7933,7 @@ function hitTestNavDropSlot(clientX, clientY, draggedHrefKey) {
7367
7933
  }
7368
7934
 
7369
7935
  // src/useNavItemDrag.ts
7370
- import { useCallback as useCallback3, useEffect as useEffect7, useRef as useRef6, useState as useState6 } from "react";
7936
+ import { useCallback as useCallback4, useEffect as useEffect7, useRef as useRef6, useState as useState7 } from "react";
7371
7937
  function useNavItemDrag({
7372
7938
  isEditMode,
7373
7939
  editContentRef,
@@ -7393,10 +7959,10 @@ function useNavItemDrag({
7393
7959
  isNavbarButton: isNavbarButton3
7394
7960
  }) {
7395
7961
  const navDragRef = useRef6(null);
7396
- const [navDropSlots, setNavDropSlots] = useState6([]);
7397
- const [activeNavDropIndex, setActiveNavDropIndex] = useState6(null);
7962
+ const [navDropSlots, setNavDropSlots] = useState7([]);
7963
+ const [activeNavDropIndex, setActiveNavDropIndex] = useState7(null);
7398
7964
  const navPointerDragRef = useRef6(null);
7399
- const clearNavDragVisuals = useCallback3(() => {
7965
+ const clearNavDragVisuals = useCallback4(() => {
7400
7966
  navDragRef.current = null;
7401
7967
  setNavDropSlots([]);
7402
7968
  setActiveNavDropIndex(null);
@@ -7405,7 +7971,7 @@ function useNavItemDrag({
7405
7971
  setIsItemDragging(false);
7406
7972
  unlockItemDragInteraction();
7407
7973
  }, [setDraggedItemRect, setIsItemDragging, setSiblingHintRects]);
7408
- const refreshNavDragVisuals = useCallback3(
7974
+ const refreshNavDragVisuals = useCallback4(
7409
7975
  (session, activeSlot, clientX, clientY) => {
7410
7976
  setDraggedItemRect(session.draggedEl.getBoundingClientRect());
7411
7977
  if (typeof clientX === "number" && typeof clientY === "number") {
@@ -7429,7 +7995,7 @@ function useNavItemDrag({
7429
7995
  });
7430
7996
  const beginNavDragRef = useRef6(() => {
7431
7997
  });
7432
- const beginNavDrag = useCallback3(
7998
+ const beginNavDrag = useCallback4(
7433
7999
  (session) => {
7434
8000
  const rect = session.draggedEl.getBoundingClientRect();
7435
8001
  session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
@@ -7456,7 +8022,7 @@ function useNavItemDrag({
7456
8022
  ]
7457
8023
  );
7458
8024
  beginNavDragRef.current = beginNavDrag;
7459
- const commitNavDrag = useCallback3(
8025
+ const commitNavDrag = useCallback4(
7460
8026
  (clientX, clientY) => {
7461
8027
  const session = navDragRef.current;
7462
8028
  if (!session) {
@@ -7517,7 +8083,7 @@ function useNavItemDrag({
7517
8083
  [clearNavDragVisuals, deselectRef, editContentRef, postToParentRef, selectRef]
7518
8084
  );
7519
8085
  commitNavDragRef.current = commitNavDrag;
7520
- const startNavLinkDrag = useCallback3(
8086
+ const startNavLinkDrag = useCallback4(
7521
8087
  (anchor, clientX, clientY, wasSelected) => {
7522
8088
  if (footerDragRef.current) return false;
7523
8089
  const hrefKey = anchor.getAttribute("data-ohw-href-key");
@@ -7535,7 +8101,7 @@ function useNavItemDrag({
7535
8101
  },
7536
8102
  [beginNavDrag, footerDragRef, isDragHandleDisabled2, isNavbarButton3]
7537
8103
  );
7538
- const onNavDragOver = useCallback3(
8104
+ const onNavDragOver = useCallback4(
7539
8105
  (e) => {
7540
8106
  const session = navDragRef.current;
7541
8107
  if (!session) return false;
@@ -7672,7 +8238,7 @@ function useNavItemDrag({
7672
8238
  setLinkPopover,
7673
8239
  suppressNextClickRef
7674
8240
  ]);
7675
- const armNavPressFromChrome = useCallback3(
8241
+ const armNavPressFromChrome = useCallback4(
7676
8242
  (selected, clientX, clientY, pointerId) => {
7677
8243
  const hrefKey = selected.getAttribute("data-ohw-href-key");
7678
8244
  if (!hrefKey || !isNavbarHrefKey(hrefKey)) return false;
@@ -7702,8 +8268,59 @@ function useNavItemDrag({
7702
8268
  };
7703
8269
  }
7704
8270
 
8271
+ // src/ui/footer-container-chrome.tsx
8272
+ import { Plus as Plus2 } from "lucide-react";
8273
+ import { jsx as jsx23, jsxs as jsxs14 } from "react/jsx-runtime";
8274
+ function FooterContainerChrome({
8275
+ rect,
8276
+ onAdd,
8277
+ addDisabled = false
8278
+ }) {
8279
+ const chromeGap = 6;
8280
+ const buttonMargin = 7;
8281
+ return /* @__PURE__ */ jsx23(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsx23(
8282
+ "div",
8283
+ {
8284
+ "data-ohw-footer-container-chrome": "",
8285
+ "data-ohw-bridge": "",
8286
+ className: "pointer-events-none fixed z-[2147483647]",
8287
+ style: {
8288
+ top: rect.top - chromeGap,
8289
+ left: rect.left - chromeGap,
8290
+ width: rect.width + chromeGap * 2,
8291
+ height: rect.height + chromeGap * 2
8292
+ },
8293
+ children: /* @__PURE__ */ jsxs14(Tooltip, { children: [
8294
+ /* @__PURE__ */ jsx23(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx23(
8295
+ "button",
8296
+ {
8297
+ type: "button",
8298
+ "data-ohw-footer-add-button": "",
8299
+ disabled: addDisabled,
8300
+ 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 disabled:pointer-events-none disabled:opacity-40",
8301
+ style: { top: chromeGap - buttonMargin },
8302
+ "aria-label": "Add item",
8303
+ onMouseDown: (e) => {
8304
+ e.preventDefault();
8305
+ e.stopPropagation();
8306
+ },
8307
+ onClick: (e) => {
8308
+ e.preventDefault();
8309
+ e.stopPropagation();
8310
+ if (addDisabled) return;
8311
+ onAdd();
8312
+ },
8313
+ children: /* @__PURE__ */ jsx23(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
8314
+ }
8315
+ ) }),
8316
+ /* @__PURE__ */ jsx23(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
8317
+ ] })
8318
+ }
8319
+ ) });
8320
+ }
8321
+
7705
8322
  // src/lib/carousel.ts
7706
- import { useEffect as useEffect8, useState as useState7 } from "react";
8323
+ import { useEffect as useEffect8, useState as useState8 } from "react";
7707
8324
  var CAROUSEL_ATTR = "data-ohw-carousel";
7708
8325
  var CAROUSEL_VALUE_ATTR = "data-ohw-carousel-value";
7709
8326
  var CAROUSEL_SLIDE_ATTR = "data-ohw-carousel-slide";
@@ -7765,7 +8382,7 @@ function applyCarouselNode(key, val) {
7765
8382
  return true;
7766
8383
  }
7767
8384
  function useOhwCarousel(key, initial) {
7768
- const [images, setImages] = useState7(initial);
8385
+ const [images, setImages] = useState8(initial);
7769
8386
  useEffect8(() => {
7770
8387
  const el = document.querySelector(
7771
8388
  `[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`
@@ -7787,14 +8404,14 @@ function useOhwCarousel(key, initial) {
7787
8404
  }
7788
8405
 
7789
8406
  // src/ui/navbar-container-chrome.tsx
7790
- import { Plus as Plus2 } from "lucide-react";
7791
- import { jsx as jsx22 } from "react/jsx-runtime";
8407
+ import { Plus as Plus3 } from "lucide-react";
8408
+ import { jsx as jsx24 } from "react/jsx-runtime";
7792
8409
  function NavbarContainerChrome({
7793
8410
  rect,
7794
8411
  onAdd
7795
8412
  }) {
7796
8413
  const chromeGap = 6;
7797
- return /* @__PURE__ */ jsx22(
8414
+ return /* @__PURE__ */ jsx24(
7798
8415
  "div",
7799
8416
  {
7800
8417
  "data-ohw-navbar-container-chrome": "",
@@ -7806,7 +8423,7 @@ function NavbarContainerChrome({
7806
8423
  width: rect.width + chromeGap * 2,
7807
8424
  height: rect.height + chromeGap * 2
7808
8425
  },
7809
- children: /* @__PURE__ */ jsx22(
8426
+ children: /* @__PURE__ */ jsx24(
7810
8427
  "button",
7811
8428
  {
7812
8429
  type: "button",
@@ -7823,7 +8440,7 @@ function NavbarContainerChrome({
7823
8440
  e.stopPropagation();
7824
8441
  onAdd();
7825
8442
  },
7826
- children: /* @__PURE__ */ jsx22(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
8443
+ children: /* @__PURE__ */ jsx24(Plus3, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
7827
8444
  }
7828
8445
  )
7829
8446
  }
@@ -7832,7 +8449,7 @@ function NavbarContainerChrome({
7832
8449
 
7833
8450
  // src/ui/drop-indicator.tsx
7834
8451
  import * as React10 from "react";
7835
- import { jsx as jsx23 } from "react/jsx-runtime";
8452
+ import { jsx as jsx25 } from "react/jsx-runtime";
7836
8453
  var dropIndicatorVariants = cva(
7837
8454
  "ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
7838
8455
  {
@@ -7856,7 +8473,7 @@ var dropIndicatorVariants = cva(
7856
8473
  );
7857
8474
  var DropIndicator = React10.forwardRef(
7858
8475
  ({ className, direction, state, ...props }, ref) => {
7859
- return /* @__PURE__ */ jsx23(
8476
+ return /* @__PURE__ */ jsx25(
7860
8477
  "div",
7861
8478
  {
7862
8479
  ref,
@@ -7873,7 +8490,7 @@ var DropIndicator = React10.forwardRef(
7873
8490
  DropIndicator.displayName = "DropIndicator";
7874
8491
 
7875
8492
  // src/ui/badge.tsx
7876
- import { jsx as jsx24 } from "react/jsx-runtime";
8493
+ import { jsx as jsx26 } from "react/jsx-runtime";
7877
8494
  var badgeVariants = cva(
7878
8495
  "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",
7879
8496
  {
@@ -7891,12 +8508,12 @@ var badgeVariants = cva(
7891
8508
  }
7892
8509
  );
7893
8510
  function Badge({ className, variant, ...props }) {
7894
- return /* @__PURE__ */ jsx24("div", { className: cn(badgeVariants({ variant }), className), ...props });
8511
+ return /* @__PURE__ */ jsx26("div", { className: cn(badgeVariants({ variant }), className), ...props });
7895
8512
  }
7896
8513
 
7897
8514
  // src/OhhwellsBridge.tsx
7898
8515
  import { Link as Link2 } from "lucide-react";
7899
- import { Fragment as Fragment5, jsx as jsx25, jsxs as jsxs14 } from "react/jsx-runtime";
8516
+ import { Fragment as Fragment5, jsx as jsx27, jsxs as jsxs15 } from "react/jsx-runtime";
7900
8517
  var PRIMARY2 = "#0885FE";
7901
8518
  var IMAGE_FADE_MS = 300;
7902
8519
  function runOpacityFade(el, onDone) {
@@ -8075,7 +8692,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
8075
8692
  const root = createRoot(container);
8076
8693
  flushSync(() => {
8077
8694
  root.render(
8078
- /* @__PURE__ */ jsx25(
8695
+ /* @__PURE__ */ jsx27(
8079
8696
  SchedulingWidget,
8080
8697
  {
8081
8698
  notifyOnConnect,
@@ -8115,7 +8732,7 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
8115
8732
  }
8116
8733
  }
8117
8734
  }
8118
- function getLinkHref2(el) {
8735
+ function getLinkHref3(el) {
8119
8736
  const anchor = el instanceof HTMLAnchorElement ? el : el.querySelector("a");
8120
8737
  return anchor?.getAttribute("href") ?? "";
8121
8738
  }
@@ -8165,7 +8782,7 @@ function collectEditableNodes(extraContent) {
8165
8782
  return { key: el.dataset.ohwKey ?? "", type: "video", text: getVideoEl(el)?.src ?? "" };
8166
8783
  }
8167
8784
  if (el.dataset.ohwEditable === "link") {
8168
- return { key: el.dataset.ohwKey ?? "", type: "link", text: getLinkHref2(el) };
8785
+ return { key: el.dataset.ohwKey ?? "", type: "link", text: getLinkHref3(el) };
8169
8786
  }
8170
8787
  return {
8171
8788
  key: el.dataset.ohwKey ?? "",
@@ -8176,7 +8793,7 @@ function collectEditableNodes(extraContent) {
8176
8793
  document.querySelectorAll("[data-ohw-href-key]").forEach((el) => {
8177
8794
  const key = el.getAttribute("data-ohw-href-key") ?? "";
8178
8795
  if (!key) return;
8179
- nodes.push({ key, type: "link", text: getLinkHref2(el) });
8796
+ nodes.push({ key, type: "link", text: getLinkHref3(el) });
8180
8797
  });
8181
8798
  if (extraContent) {
8182
8799
  for (const key of [NAV_ORDER_KEY, FOOTER_ORDER_KEY, NAV_COUNT_KEY]) {
@@ -8279,7 +8896,7 @@ function applyLinkByKey(key, val) {
8279
8896
  }
8280
8897
  function isInsideLinkEditor(target) {
8281
8898
  return Boolean(
8282
- 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"]')
8899
+ 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"]')
8283
8900
  );
8284
8901
  }
8285
8902
  function getHrefKeyFromElement(el) {
@@ -8360,7 +8977,7 @@ function isInferredFooterGroup(el) {
8360
8977
  return countFooterNavItems(el) >= 2;
8361
8978
  }
8362
8979
  function isNavigationContainer(el) {
8363
- return el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isNavigationRoot(el) || isInferredFooterGroup(el);
8980
+ 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);
8364
8981
  }
8365
8982
  function isNavbarLinksContainer(el) {
8366
8983
  return el.hasAttribute("data-ohw-nav-container");
@@ -8379,6 +8996,9 @@ function isPointOverNavigation(x, y) {
8379
8996
  const roots = /* @__PURE__ */ new Set();
8380
8997
  const navRoot = document.querySelector("[data-ohw-nav-root]") ?? document.querySelector("nav");
8381
8998
  if (navRoot) roots.add(navRoot);
8999
+ document.querySelectorAll("[data-ohw-nav-drawer], [data-ohw-nav-container]").forEach((el) => {
9000
+ roots.add(el);
9001
+ });
8382
9002
  const footer = document.querySelector("footer");
8383
9003
  if (footer) roots.add(footer);
8384
9004
  for (const root of roots) {
@@ -8407,6 +9027,12 @@ function isPointOverNavItem(container, x, y) {
8407
9027
  return x >= itemRect.left && x <= itemRect.right && y >= itemRect.top && y <= itemRect.bottom;
8408
9028
  });
8409
9029
  }
9030
+ function isPointOverFooterColumn(x, y) {
9031
+ return listFooterColumns().some((col) => {
9032
+ const r2 = col.getBoundingClientRect();
9033
+ return x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom;
9034
+ });
9035
+ }
8410
9036
  function resolveNavContainerSelectionTarget(target, clientX, clientY) {
8411
9037
  if (getNavigationItemAnchor(target)) return null;
8412
9038
  if (target.closest('[data-ohw-role="navbar-button"]')) return null;
@@ -8437,7 +9063,10 @@ function getNavigationSelectionParent(el) {
8437
9063
  if (footerGroup) return footerGroup;
8438
9064
  return getNavigationRoot(el);
8439
9065
  }
8440
- if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup(el)) {
9066
+ if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup(el))) {
9067
+ return getFooterLinksContainer();
9068
+ }
9069
+ if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isFooterLinksContainer(el) || isInferredFooterGroup(el)) {
8441
9070
  return getNavigationRoot(el);
8442
9071
  }
8443
9072
  return null;
@@ -8664,7 +9293,7 @@ function EditGlowChrome({
8664
9293
  hideHandle = false
8665
9294
  }) {
8666
9295
  const GAP = SELECTION_CHROME_GAP2;
8667
- return /* @__PURE__ */ jsxs14(
9296
+ return /* @__PURE__ */ jsxs15(
8668
9297
  "div",
8669
9298
  {
8670
9299
  ref: elRef,
@@ -8679,7 +9308,7 @@ function EditGlowChrome({
8679
9308
  zIndex: 2147483646
8680
9309
  },
8681
9310
  children: [
8682
- /* @__PURE__ */ jsx25(
9311
+ /* @__PURE__ */ jsx27(
8683
9312
  "div",
8684
9313
  {
8685
9314
  style: {
@@ -8692,7 +9321,7 @@ function EditGlowChrome({
8692
9321
  }
8693
9322
  }
8694
9323
  ),
8695
- reorderHrefKey && !hideHandle && /* @__PURE__ */ jsx25(
9324
+ reorderHrefKey && !hideHandle && /* @__PURE__ */ jsx27(
8696
9325
  "div",
8697
9326
  {
8698
9327
  "data-ohw-drag-handle-container": "",
@@ -8704,7 +9333,7 @@ function EditGlowChrome({
8704
9333
  transform: "translate(calc(-100% - 7px), -50%)",
8705
9334
  pointerEvents: dragDisabled ? "none" : "auto"
8706
9335
  },
8707
- children: /* @__PURE__ */ jsx25(
9336
+ children: /* @__PURE__ */ jsx27(
8708
9337
  DragHandle,
8709
9338
  {
8710
9339
  "aria-label": `Reorder ${reorderHrefKey}`,
@@ -8914,7 +9543,7 @@ function FloatingToolbar({
8914
9543
  return () => ro.disconnect();
8915
9544
  }, [showEditLink, activeCommands]);
8916
9545
  const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
8917
- return /* @__PURE__ */ jsx25(
9546
+ return /* @__PURE__ */ jsx27(
8918
9547
  "div",
8919
9548
  {
8920
9549
  ref: setRefs,
@@ -8926,12 +9555,12 @@ function FloatingToolbar({
8926
9555
  zIndex: 2147483647,
8927
9556
  pointerEvents: "auto"
8928
9557
  },
8929
- children: /* @__PURE__ */ jsxs14(CustomToolbar, { children: [
8930
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs14(React11.Fragment, { children: [
8931
- gi > 0 && /* @__PURE__ */ jsx25(CustomToolbarDivider, {}),
9558
+ children: /* @__PURE__ */ jsxs15(CustomToolbar, { children: [
9559
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs15(React11.Fragment, { children: [
9560
+ gi > 0 && /* @__PURE__ */ jsx27(CustomToolbarDivider, {}),
8932
9561
  btns.map((btn) => {
8933
9562
  const isActive = activeCommands.has(btn.cmd);
8934
- return /* @__PURE__ */ jsx25(
9563
+ return /* @__PURE__ */ jsx27(
8935
9564
  CustomToolbarButton,
8936
9565
  {
8937
9566
  title: btn.title,
@@ -8940,7 +9569,7 @@ function FloatingToolbar({
8940
9569
  e.preventDefault();
8941
9570
  onCommand(btn.cmd);
8942
9571
  },
8943
- children: /* @__PURE__ */ jsx25(
9572
+ children: /* @__PURE__ */ jsx27(
8944
9573
  "svg",
8945
9574
  {
8946
9575
  width: "16",
@@ -8961,7 +9590,7 @@ function FloatingToolbar({
8961
9590
  );
8962
9591
  })
8963
9592
  ] }, gi)),
8964
- showEditLink ? /* @__PURE__ */ jsx25(
9593
+ showEditLink ? /* @__PURE__ */ jsx27(
8965
9594
  CustomToolbarButton,
8966
9595
  {
8967
9596
  type: "button",
@@ -8975,7 +9604,7 @@ function FloatingToolbar({
8975
9604
  e.preventDefault();
8976
9605
  e.stopPropagation();
8977
9606
  },
8978
- children: /* @__PURE__ */ jsx25(Link2, { className: "size-4 shrink-0", "aria-hidden": true })
9607
+ children: /* @__PURE__ */ jsx27(Link2, { className: "size-4 shrink-0", "aria-hidden": true })
8979
9608
  }
8980
9609
  ) : null
8981
9610
  ] })
@@ -8992,7 +9621,7 @@ function StateToggle({
8992
9621
  states,
8993
9622
  onStateChange
8994
9623
  }) {
8995
- return /* @__PURE__ */ jsx25(
9624
+ return /* @__PURE__ */ jsx27(
8996
9625
  ToggleGroup,
8997
9626
  {
8998
9627
  "data-ohw-state-toggle": "",
@@ -9006,7 +9635,7 @@ function StateToggle({
9006
9635
  left: rect.right - 8,
9007
9636
  transform: "translateX(-100%)"
9008
9637
  },
9009
- children: states.map((state) => /* @__PURE__ */ jsx25(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
9638
+ children: states.map((state) => /* @__PURE__ */ jsx27(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
9010
9639
  }
9011
9640
  );
9012
9641
  }
@@ -9033,7 +9662,7 @@ function OhhwellsBridge() {
9033
9662
  const router = useRouter2();
9034
9663
  const searchParams = useSearchParams();
9035
9664
  const isEditMode = isEditSessionActive();
9036
- const [bridgeRoot, setBridgeRoot] = useState8(null);
9665
+ const [bridgeRoot, setBridgeRoot] = useState9(null);
9037
9666
  useEffect9(() => {
9038
9667
  const figtreeFontId = "ohw-figtree-font";
9039
9668
  if (!document.getElementById(figtreeFontId)) {
@@ -9062,12 +9691,12 @@ function OhhwellsBridge() {
9062
9691
  const subdomainFromQuery = searchParams.get("subdomain");
9063
9692
  const subdomain = resolveSubdomain(subdomainFromQuery);
9064
9693
  useLinkHrefGuardian(pathname, subdomain, isEditMode);
9065
- const postToParent2 = useCallback4((data) => {
9694
+ const postToParent2 = useCallback5((data) => {
9066
9695
  if (typeof window !== "undefined" && window.parent !== window) {
9067
9696
  window.parent.postMessage(data, "*");
9068
9697
  }
9069
9698
  }, []);
9070
- const [fetchState, setFetchState] = useState8("idle");
9699
+ const [fetchState, setFetchState] = useState9("idle");
9071
9700
  const autoSaveTimers = useRef7(/* @__PURE__ */ new Map());
9072
9701
  const activeElRef = useRef7(null);
9073
9702
  const pointerHeldRef = useRef7(false);
@@ -9078,8 +9707,8 @@ function OhhwellsBridge() {
9078
9707
  const activeStateElRef = useRef7(null);
9079
9708
  const parentScrollRef = useRef7(null);
9080
9709
  const visibleViewportRef = useRef7(null);
9081
- const [dialogPortalContainer, setDialogPortalContainer] = useState8(null);
9082
- const attachVisibleViewport = useCallback4((node) => {
9710
+ const [dialogPortalContainer, setDialogPortalContainer] = useState9(null);
9711
+ const attachVisibleViewport = useCallback5((node) => {
9083
9712
  visibleViewportRef.current = node;
9084
9713
  setDialogPortalContainer(node);
9085
9714
  if (node) applyVisibleViewport(node, parentScrollRef.current);
@@ -9089,9 +9718,9 @@ function OhhwellsBridge() {
9089
9718
  const hoveredImageRef = useRef7(null);
9090
9719
  const hoveredImageHasTextOverlapRef = useRef7(false);
9091
9720
  const dragOverElRef = useRef7(null);
9092
- const [mediaHover, setMediaHover] = useState8(null);
9093
- const [carouselHover, setCarouselHover] = useState8(null);
9094
- const [uploadingRects, setUploadingRects] = useState8({});
9721
+ const [mediaHover, setMediaHover] = useState9(null);
9722
+ const [carouselHover, setCarouselHover] = useState9(null);
9723
+ const [uploadingRects, setUploadingRects] = useState9({});
9095
9724
  const hoveredGapRef = useRef7(null);
9096
9725
  const imageUnhoverTimerRef = useRef7(null);
9097
9726
  const imageShowTimerRef = useRef7(null);
@@ -9116,40 +9745,40 @@ function OhhwellsBridge() {
9116
9745
  postToParentRef.current = postToParent2;
9117
9746
  const sectionsLoadedRef = useRef7(false);
9118
9747
  const pendingScheduleConfigRequests = useRef7([]);
9119
- const [toolbarRect, setToolbarRect] = useState8(null);
9120
- const [toolbarVariant, setToolbarVariant] = useState8("none");
9748
+ const [toolbarRect, setToolbarRect] = useState9(null);
9749
+ const [toolbarVariant, setToolbarVariant] = useState9("none");
9121
9750
  const toolbarVariantRef = useRef7("none");
9122
9751
  toolbarVariantRef.current = toolbarVariant;
9123
- const [selectedIsCta, setSelectedIsCta] = useState8(false);
9124
- const [reorderHrefKey, setReorderHrefKey] = useState8(null);
9125
- const [reorderDragDisabled, setReorderDragDisabled] = useState8(false);
9126
- const [toggleState, setToggleState] = useState8(null);
9127
- const [maxBadge, setMaxBadge] = useState8(null);
9128
- const [activeCommands, setActiveCommands] = useState8(/* @__PURE__ */ new Set());
9129
- const [sectionGap, setSectionGap] = useState8(null);
9130
- const [toolbarShowEditLink, setToolbarShowEditLink] = useState8(false);
9752
+ const [selectedIsCta, setSelectedIsCta] = useState9(false);
9753
+ const [reorderHrefKey, setReorderHrefKey] = useState9(null);
9754
+ const [reorderDragDisabled, setReorderDragDisabled] = useState9(false);
9755
+ const [toggleState, setToggleState] = useState9(null);
9756
+ const [maxBadge, setMaxBadge] = useState9(null);
9757
+ const [activeCommands, setActiveCommands] = useState9(/* @__PURE__ */ new Set());
9758
+ const [sectionGap, setSectionGap] = useState9(null);
9759
+ const [toolbarShowEditLink, setToolbarShowEditLink] = useState9(false);
9131
9760
  const hoveredNavContainerRef = useRef7(null);
9132
- const [hoveredNavContainerRect, setHoveredNavContainerRect] = useState8(null);
9761
+ const [hoveredNavContainerRect, setHoveredNavContainerRect] = useState9(null);
9133
9762
  const hoveredItemElRef = useRef7(null);
9134
- const [hoveredItemRect, setHoveredItemRect] = useState8(null);
9763
+ const [hoveredItemRect, setHoveredItemRect] = useState9(null);
9135
9764
  const siblingHintElRef = useRef7(null);
9136
- const [siblingHintRect, setSiblingHintRect] = useState8(null);
9137
- const [siblingHintRects, setSiblingHintRects] = useState8([]);
9138
- const [isItemDragging, setIsItemDragging] = useState8(false);
9139
- const [isFooterFrameSelection, setIsFooterFrameSelection] = useState8(false);
9765
+ const [siblingHintRect, setSiblingHintRect] = useState9(null);
9766
+ const [siblingHintRects, setSiblingHintRects] = useState9([]);
9767
+ const [isItemDragging, setIsItemDragging] = useState9(false);
9768
+ const [isFooterFrameSelection, setIsFooterFrameSelection] = useState9(false);
9140
9769
  const footerDragRef = useRef7(null);
9141
- const [footerDropSlots, setFooterDropSlots] = useState8([]);
9142
- const [activeFooterDropIndex, setActiveFooterDropIndex] = useState8(null);
9143
- const [draggedItemRect, setDraggedItemRect] = useState8(null);
9770
+ const [footerDropSlots, setFooterDropSlots] = useState9([]);
9771
+ const [activeFooterDropIndex, setActiveFooterDropIndex] = useState9(null);
9772
+ const [draggedItemRect, setDraggedItemRect] = useState9(null);
9144
9773
  const footerPointerDragRef = useRef7(null);
9145
9774
  const suppressNextClickRef = useRef7(false);
9146
9775
  const suppressClickUntilRef = useRef7(0);
9147
- const [linkPopover, setLinkPopover] = useState8(null);
9776
+ const [linkPopover, setLinkPopover] = useState9(null);
9148
9777
  const linkPopoverSessionRef = useRef7(null);
9149
9778
  const addNavAfterAnchorRef = useRef7(null);
9150
9779
  const editContentRef = useRef7({});
9151
- const [sitePages, setSitePages] = useState8([]);
9152
- const [sectionsByPath, setSectionsByPath] = useState8({});
9780
+ const [sitePages, setSitePages] = useState9([]);
9781
+ const [sectionsByPath, setSectionsByPath] = useState9({});
9153
9782
  const sectionsPrefetchGenRef = useRef7(0);
9154
9783
  const setLinkPopoverRef = useRef7(setLinkPopover);
9155
9784
  const linkPopoverPanelRef = useRef7(null);
@@ -9193,7 +9822,7 @@ function OhhwellsBridge() {
9193
9822
  const bumpLinkPopoverGrace = () => {
9194
9823
  linkPopoverGraceUntilRef.current = Date.now() + 350;
9195
9824
  };
9196
- const runSectionsPrefetch = useCallback4((pages) => {
9825
+ const runSectionsPrefetch = useCallback5((pages) => {
9197
9826
  if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
9198
9827
  const gen = ++sectionsPrefetchGenRef.current;
9199
9828
  const paths = pages.map((p) => p.path);
@@ -9319,10 +9948,10 @@ function OhhwellsBridge() {
9319
9948
  vvp.removeEventListener("resize", update);
9320
9949
  };
9321
9950
  }, []);
9322
- const refreshStateRules = useCallback4(() => {
9951
+ const refreshStateRules = useCallback5(() => {
9323
9952
  editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
9324
9953
  }, []);
9325
- const processConfigRequest = useCallback4((insertAfterVal) => {
9954
+ const processConfigRequest = useCallback5((insertAfterVal) => {
9326
9955
  const tracker = getSectionsTracker();
9327
9956
  let entries = [];
9328
9957
  try {
@@ -9345,7 +9974,7 @@ function OhhwellsBridge() {
9345
9974
  }
9346
9975
  window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
9347
9976
  }, [isEditMode]);
9348
- const deactivate = useCallback4(() => {
9977
+ const deactivate = useCallback5(() => {
9349
9978
  const el = activeElRef.current;
9350
9979
  if (!el) return;
9351
9980
  const key = el.dataset.ohwKey;
@@ -9377,12 +10006,12 @@ function OhhwellsBridge() {
9377
10006
  setToolbarShowEditLink(false);
9378
10007
  postToParent2({ type: "ow:exit-edit" });
9379
10008
  }, [postToParent2]);
9380
- const clearSelectedAttr = useCallback4(() => {
10009
+ const clearSelectedAttr = useCallback5(() => {
9381
10010
  document.querySelectorAll("[data-ohw-selected]").forEach((el) => {
9382
10011
  el.removeAttribute("data-ohw-selected");
9383
10012
  });
9384
10013
  }, []);
9385
- const deselect = useCallback4(() => {
10014
+ const deselect = useCallback5(() => {
9386
10015
  clearSelectedAttr();
9387
10016
  selectedElRef.current = null;
9388
10017
  selectedHrefKeyRef.current = null;
@@ -9402,11 +10031,11 @@ function OhhwellsBridge() {
9402
10031
  setToolbarVariant("none");
9403
10032
  }
9404
10033
  }, [clearSelectedAttr]);
9405
- const markSelected = useCallback4((el) => {
10034
+ const markSelected = useCallback5((el) => {
9406
10035
  clearSelectedAttr();
9407
10036
  el.setAttribute("data-ohw-selected", "");
9408
10037
  }, [clearSelectedAttr]);
9409
- const resolveHrefKeyElement = useCallback4((hrefKey) => {
10038
+ const resolveHrefKeyElement = useCallback5((hrefKey) => {
9410
10039
  if (isFooterHrefKey(hrefKey)) {
9411
10040
  return document.querySelector(
9412
10041
  `footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
@@ -9421,7 +10050,7 @@ function OhhwellsBridge() {
9421
10050
  `[data-ohw-href-key="${CSS.escape(hrefKey)}"]`
9422
10051
  );
9423
10052
  }, []);
9424
- const resyncSelectedNavigationItem = useCallback4(() => {
10053
+ const resyncSelectedNavigationItem = useCallback5(() => {
9425
10054
  const hrefKey = selectedHrefKeyRef.current;
9426
10055
  if (hrefKey) {
9427
10056
  const link = resolveHrefKeyElement(hrefKey);
@@ -9449,7 +10078,7 @@ function OhhwellsBridge() {
9449
10078
  );
9450
10079
  }
9451
10080
  }, [resolveHrefKeyElement]);
9452
- const reselectNavigationItem = useCallback4((navAnchor) => {
10081
+ const reselectNavigationItem = useCallback5((navAnchor) => {
9453
10082
  selectedElRef.current = navAnchor;
9454
10083
  selectedHrefKeyRef.current = navAnchor.getAttribute("data-ohw-href-key");
9455
10084
  selectedFooterColAttrRef.current = null;
@@ -9464,7 +10093,7 @@ function OhhwellsBridge() {
9464
10093
  setToolbarShowEditLink(false);
9465
10094
  setActiveCommands(/* @__PURE__ */ new Set());
9466
10095
  }, [markSelected]);
9467
- const commitNavigationTextEdit = useCallback4((navAnchor) => {
10096
+ const commitNavigationTextEdit = useCallback5((navAnchor) => {
9468
10097
  const el = activeElRef.current;
9469
10098
  if (!el) return;
9470
10099
  const key = el.dataset.ohwKey;
@@ -9491,7 +10120,7 @@ function OhhwellsBridge() {
9491
10120
  postToParent2({ type: "ow:exit-edit" });
9492
10121
  reselectNavigationItem(navAnchor);
9493
10122
  }, [postToParent2, reselectNavigationItem]);
9494
- const handleAddTopLevelNavItem = useCallback4(() => {
10123
+ const handleAddTopLevelNavItem = useCallback5(() => {
9495
10124
  const items = listNavbarItems();
9496
10125
  addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
9497
10126
  deselectRef.current();
@@ -9503,7 +10132,28 @@ function OhhwellsBridge() {
9503
10132
  intent: "add-nav"
9504
10133
  });
9505
10134
  }, []);
9506
- const clearFooterDragVisuals = useCallback4(() => {
10135
+ const handleAddFooterColumn = useCallback5(() => {
10136
+ if (!canAddFooterColumn()) {
10137
+ postToParent2({
10138
+ type: "ow:toast",
10139
+ title: `Maximum ${MAX_FOOTER_COLUMNS} columns`,
10140
+ toastType: "error"
10141
+ });
10142
+ return;
10143
+ }
10144
+ deselectRef.current();
10145
+ deactivateRef.current();
10146
+ const result = addFooterColumnWithPersist({ postToParent: postToParent2 });
10147
+ if (!result) return;
10148
+ editContentRef.current = {
10149
+ ...editContentRef.current,
10150
+ ...buildFooterColumnEditContentPatch(result)
10151
+ };
10152
+ requestAnimationFrame(() => {
10153
+ selectRef.current(result.firstLink);
10154
+ });
10155
+ }, [postToParent2]);
10156
+ const clearFooterDragVisuals = useCallback5(() => {
9507
10157
  footerDragRef.current = null;
9508
10158
  setSiblingHintRects([]);
9509
10159
  setFooterDropSlots([]);
@@ -9512,7 +10162,7 @@ function OhhwellsBridge() {
9512
10162
  setIsItemDragging(false);
9513
10163
  unlockFooterDragInteraction();
9514
10164
  }, []);
9515
- const refreshFooterDragVisuals = useCallback4((session, activeSlot, clientX, clientY) => {
10165
+ const refreshFooterDragVisuals = useCallback5((session, activeSlot, clientX, clientY) => {
9516
10166
  const dragged = session.draggedEl;
9517
10167
  setDraggedItemRect(dragged.getBoundingClientRect());
9518
10168
  if (typeof clientX === "number" && typeof clientY === "number") {
@@ -9543,7 +10193,7 @@ function OhhwellsBridge() {
9543
10193
  });
9544
10194
  const beginFooterDragRef = useRef7(() => {
9545
10195
  });
9546
- const beginFooterDrag = useCallback4(
10196
+ const beginFooterDrag = useCallback5(
9547
10197
  (session) => {
9548
10198
  const rect = session.draggedEl.getBoundingClientRect();
9549
10199
  session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
@@ -9563,7 +10213,7 @@ function OhhwellsBridge() {
9563
10213
  [refreshFooterDragVisuals]
9564
10214
  );
9565
10215
  beginFooterDragRef.current = beginFooterDrag;
9566
- const commitFooterDrag = useCallback4(
10216
+ const commitFooterDrag = useCallback5(
9567
10217
  (clientX, clientY) => {
9568
10218
  const session = footerDragRef.current;
9569
10219
  if (!session) {
@@ -9667,7 +10317,7 @@ function OhhwellsBridge() {
9667
10317
  [clearFooterDragVisuals, resolveHrefKeyElement, resyncSelectedNavigationItem]
9668
10318
  );
9669
10319
  commitFooterDragRef.current = commitFooterDrag;
9670
- const startFooterLinkDrag = useCallback4(
10320
+ const startFooterLinkDrag = useCallback5(
9671
10321
  (anchor, clientX, clientY, wasSelected) => {
9672
10322
  const hrefKey = anchor.getAttribute("data-ohw-href-key");
9673
10323
  if (!hrefKey || !isFooterHrefKey(hrefKey)) return false;
@@ -9688,7 +10338,7 @@ function OhhwellsBridge() {
9688
10338
  },
9689
10339
  [beginFooterDrag]
9690
10340
  );
9691
- const startFooterColumnDrag = useCallback4(
10341
+ const startFooterColumnDrag = useCallback5(
9692
10342
  (columnEl, clientX, clientY, wasSelected) => {
9693
10343
  const columns = listFooterColumns();
9694
10344
  const idx = columns.indexOf(columnEl);
@@ -9708,7 +10358,7 @@ function OhhwellsBridge() {
9708
10358
  },
9709
10359
  [beginFooterDrag]
9710
10360
  );
9711
- const handleItemDragStart = useCallback4(
10361
+ const handleItemDragStart = useCallback5(
9712
10362
  (e) => {
9713
10363
  const selected = selectedElRef.current;
9714
10364
  if (!selected) {
@@ -9728,7 +10378,7 @@ function OhhwellsBridge() {
9728
10378
  },
9729
10379
  [startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag]
9730
10380
  );
9731
- const handleItemDragEnd = useCallback4(
10381
+ const handleItemDragEnd = useCallback5(
9732
10382
  (e) => {
9733
10383
  if (footerDragRef.current) {
9734
10384
  const x = e?.clientX;
@@ -9754,7 +10404,7 @@ function OhhwellsBridge() {
9754
10404
  },
9755
10405
  [commitFooterDrag, commitNavDrag, navDragRef]
9756
10406
  );
9757
- const handleItemChromePointerDown = useCallback4((e) => {
10407
+ const handleItemChromePointerDown = useCallback5((e) => {
9758
10408
  if (e.button !== 0) return;
9759
10409
  const selected = selectedElRef.current;
9760
10410
  if (!selected) return;
@@ -9785,7 +10435,7 @@ function OhhwellsBridge() {
9785
10435
  }
9786
10436
  if (armNavPressFromChrome(selected, e.clientX, e.clientY, e.pointerId)) return;
9787
10437
  }, [armNavPressFromChrome]);
9788
- const handleItemChromeClick = useCallback4((clientX, clientY) => {
10438
+ const handleItemChromeClick = useCallback5((clientX, clientY) => {
9789
10439
  if (suppressNextClickRef.current || Date.now() < suppressClickUntilRef.current) {
9790
10440
  suppressNextClickRef.current = false;
9791
10441
  return;
@@ -9798,7 +10448,7 @@ function OhhwellsBridge() {
9798
10448
  }, []);
9799
10449
  reselectNavigationItemRef.current = reselectNavigationItem;
9800
10450
  commitNavigationTextEditRef.current = commitNavigationTextEdit;
9801
- const select = useCallback4((anchor) => {
10451
+ const select = useCallback5((anchor) => {
9802
10452
  if (!isNavigationItem(anchor)) return;
9803
10453
  if (activeElRef.current) deactivate();
9804
10454
  selectedElRef.current = anchor;
@@ -9824,10 +10474,10 @@ function OhhwellsBridge() {
9824
10474
  setToolbarShowEditLink(false);
9825
10475
  setActiveCommands(/* @__PURE__ */ new Set());
9826
10476
  }, [deactivate, markSelected]);
9827
- const selectFrame = useCallback4((el) => {
10477
+ const selectFrame = useCallback5((el) => {
9828
10478
  if (!isNavigationContainer(el)) return;
9829
10479
  if (activeElRef.current) deactivate();
9830
- const isFooterColumn = el.hasAttribute("data-ohw-footer-col") || Boolean(el.closest("footer") && isInferredFooterGroup(el));
10480
+ const isFooterColumn = !isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || Boolean(el.closest("footer") && isInferredFooterGroup(el)));
9831
10481
  selectedElRef.current = el;
9832
10482
  selectedHrefKeyRef.current = null;
9833
10483
  selectedFooterColAttrRef.current = isFooterColumn ? el.getAttribute("data-ohw-footer-col") ?? String(listFooterColumns().indexOf(el)) : null;
@@ -9852,7 +10502,7 @@ function OhhwellsBridge() {
9852
10502
  setToolbarShowEditLink(false);
9853
10503
  setActiveCommands(/* @__PURE__ */ new Set());
9854
10504
  }, [deactivate, markSelected]);
9855
- const activate = useCallback4((el, options) => {
10505
+ const activate = useCallback5((el, options) => {
9856
10506
  if (activeElRef.current === el) return;
9857
10507
  clearSelectedAttr();
9858
10508
  selectedElRef.current = null;
@@ -10360,7 +11010,7 @@ function OhhwellsBridge() {
10360
11010
  setLinkPopoverRef.current({
10361
11011
  key: editable.dataset.ohwKey ?? "",
10362
11012
  mode: "edit",
10363
- target: getLinkHref2(editable)
11013
+ target: getLinkHref3(editable)
10364
11014
  });
10365
11015
  return;
10366
11016
  }
@@ -10385,7 +11035,7 @@ function OhhwellsBridge() {
10385
11035
  }
10386
11036
  e.preventDefault();
10387
11037
  e.stopPropagation();
10388
- activateRef.current(editable);
11038
+ activateRef.current(editable, { caretX: e.clientX, caretY: e.clientY });
10389
11039
  return;
10390
11040
  }
10391
11041
  const hrefAnchor = getNavigationItemAnchor(target);
@@ -10412,6 +11062,18 @@ function OhhwellsBridge() {
10412
11062
  selectFrameRef.current(footerColClick);
10413
11063
  return;
10414
11064
  }
11065
+ const footerLinksToSelect = resolveFooterLinksContainerSelectionTarget(
11066
+ target,
11067
+ e.clientX,
11068
+ e.clientY,
11069
+ isPointOverNavItem
11070
+ );
11071
+ if (footerLinksToSelect) {
11072
+ e.preventDefault();
11073
+ e.stopPropagation();
11074
+ selectFrameRef.current(footerLinksToSelect);
11075
+ return;
11076
+ }
10415
11077
  const navContainerToSelect = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
10416
11078
  if (navContainerToSelect) {
10417
11079
  e.preventDefault();
@@ -10470,8 +11132,8 @@ function OhhwellsBridge() {
10470
11132
  return;
10471
11133
  }
10472
11134
  const navLabel = getNavigationLabelEditable(target);
10473
- if (!navLabel) return;
10474
- const { editable } = navLabel;
11135
+ const editable = navLabel?.editable ?? target.closest('[data-ohw-editable="text"], [data-ohw-editable="plain"]');
11136
+ if (!editable || isMediaEditable(editable) || editable.dataset.ohwEditable === "link") return;
10475
11137
  e.preventDefault();
10476
11138
  e.stopPropagation();
10477
11139
  if (activeElRef.current !== editable) {
@@ -10492,16 +11154,38 @@ function OhhwellsBridge() {
10492
11154
  setHoveredNavContainerRect(null);
10493
11155
  return;
10494
11156
  }
10495
- if (toolbarVariantRef.current !== "select-frame") {
10496
- const navContainer = target.closest("[data-ohw-nav-container]");
10497
- if (navContainer && !getNavigationItemAnchor(target)) {
10498
- hoveredNavContainerRef.current = navContainer;
10499
- setHoveredNavContainerRect(navContainer.getBoundingClientRect());
10500
- hoveredItemElRef.current = null;
10501
- setHoveredItemRect(null);
10502
- return;
11157
+ {
11158
+ const selected2 = selectedElRef.current;
11159
+ const selectedIsFooterColumn = Boolean(selected2) && !isFooterLinksContainer(selected2) && (selected2.hasAttribute("data-ohw-footer-col") || selected2.hasAttribute("data-ohw-footer-column") || Boolean(selected2.closest("footer") && isInferredFooterGroup(selected2)));
11160
+ const allowNavContainerHover = toolbarVariantRef.current !== "select-frame";
11161
+ const allowFooterLinksHover = toolbarVariantRef.current !== "select-frame" || selectedIsFooterColumn;
11162
+ if (allowNavContainerHover) {
11163
+ const navContainer = target.closest("[data-ohw-nav-container]");
11164
+ if (navContainer && !getNavigationItemAnchor(target)) {
11165
+ hoveredNavContainerRef.current = navContainer;
11166
+ setHoveredNavContainerRect(navContainer.getBoundingClientRect());
11167
+ hoveredItemElRef.current = null;
11168
+ setHoveredItemRect(null);
11169
+ return;
11170
+ }
10503
11171
  }
10504
- if (!target.closest("[data-ohw-nav-container]")) {
11172
+ if (allowFooterLinksHover) {
11173
+ const navContainer = target.closest("[data-ohw-nav-container]");
11174
+ if (!navContainer) {
11175
+ const footerLinks = target.closest("[data-ohw-footer-links], .rb-footer-links") ?? null;
11176
+ if (footerLinks && selected2 !== footerLinks && !getNavigationItemAnchor(target) && !target.closest("[data-ohw-footer-col], [data-ohw-footer-column]")) {
11177
+ hoveredNavContainerRef.current = footerLinks;
11178
+ setHoveredNavContainerRect(footerLinks.getBoundingClientRect());
11179
+ hoveredItemElRef.current = null;
11180
+ setHoveredItemRect(null);
11181
+ return;
11182
+ }
11183
+ if (!footerLinks) {
11184
+ hoveredNavContainerRef.current = null;
11185
+ setHoveredNavContainerRect(null);
11186
+ }
11187
+ }
11188
+ } else if (toolbarVariantRef.current === "select-frame") {
10505
11189
  hoveredNavContainerRef.current = null;
10506
11190
  setHoveredNavContainerRect(null);
10507
11191
  }
@@ -10543,9 +11227,9 @@ function OhhwellsBridge() {
10543
11227
  };
10544
11228
  const handleMouseOut = (e) => {
10545
11229
  const target = e.target;
10546
- if (target.closest("[data-ohw-nav-container], [data-ohw-footer-col], [data-ohw-footer-column]")) {
11230
+ if (target.closest("[data-ohw-nav-container], [data-ohw-footer-col], [data-ohw-footer-column], [data-ohw-footer-links], .rb-footer-links")) {
10547
11231
  const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
10548
- 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]")) {
11232
+ 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]")) {
10549
11233
  return;
10550
11234
  }
10551
11235
  hoveredNavContainerRef.current = null;
@@ -10640,6 +11324,15 @@ function OhhwellsBridge() {
10640
11324
  if (track) track.setAttribute("data-ohw-hover-paused", "");
10641
11325
  };
10642
11326
  const clearImageHover = () => setMediaHover(null);
11327
+ const dismissImageHover = () => {
11328
+ if (hoveredImageRef.current) {
11329
+ hoveredImageRef.current = null;
11330
+ hoveredImageHasTextOverlapRef.current = false;
11331
+ resumeAnimTracks();
11332
+ postToParentRef.current({ type: "ow:image-unhover" });
11333
+ }
11334
+ clearImageHover();
11335
+ };
10643
11336
  const findImageAtPoint = (clientX, clientY, fromParentViewport) => {
10644
11337
  const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
10645
11338
  const images = Array.from(document.querySelectorAll(MEDIA_SELECTOR));
@@ -10683,16 +11376,13 @@ function OhhwellsBridge() {
10683
11376
  }
10684
11377
  return smallest;
10685
11378
  };
10686
- const dismissImageHover = () => {
10687
- if (hoveredImageRef.current) {
10688
- hoveredImageRef.current = null;
10689
- hoveredImageHasTextOverlapRef.current = false;
10690
- resumeAnimTracks();
10691
- postToParentRef.current({ type: "ow:image-unhover" });
10692
- }
10693
- };
10694
11379
  const probeNavigationHoverAt = (x, y) => {
10695
- if (toolbarVariantRef.current === "select-frame") {
11380
+ const selected = selectedElRef.current;
11381
+ const selectedIsFooterColumn = Boolean(selected) && !isFooterLinksContainer(selected) && (selected.hasAttribute("data-ohw-footer-col") || selected.hasAttribute("data-ohw-footer-column") || Boolean(selected.closest("footer") && isInferredFooterGroup(selected)));
11382
+ const selectedIsFooterLinks = Boolean(selected && isFooterLinksContainer(selected));
11383
+ const allowNavContainerHover = toolbarVariantRef.current !== "select-frame";
11384
+ const allowFooterLinksHover = (toolbarVariantRef.current !== "select-frame" || selectedIsFooterColumn) && !selectedIsFooterLinks;
11385
+ if (toolbarVariantRef.current === "select-frame" && !allowFooterLinksHover) {
10696
11386
  hoveredNavContainerRef.current = null;
10697
11387
  setHoveredNavContainerRect(null);
10698
11388
  }
@@ -10714,7 +11404,6 @@ function OhhwellsBridge() {
10714
11404
  if (navItemHit) {
10715
11405
  hoveredNavContainerRef.current = null;
10716
11406
  setHoveredNavContainerRect(null);
10717
- const selected = selectedElRef.current;
10718
11407
  if (selected !== navItemHit) {
10719
11408
  clearHrefKeyHover(navItemHit);
10720
11409
  hoveredItemElRef.current = navItemHit;
@@ -10726,7 +11415,7 @@ function OhhwellsBridge() {
10726
11415
  return;
10727
11416
  }
10728
11417
  }
10729
- if (toolbarVariantRef.current !== "select-frame") {
11418
+ if (allowNavContainerHover) {
10730
11419
  for (const container of navContainers) {
10731
11420
  const containerRect = container.getBoundingClientRect();
10732
11421
  const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
@@ -10738,12 +11427,23 @@ function OhhwellsBridge() {
10738
11427
  setHoveredItemRect(null);
10739
11428
  return;
10740
11429
  }
10741
- hoveredNavContainerRef.current = null;
10742
- setHoveredNavContainerRect(null);
10743
- } else {
10744
- hoveredNavContainerRef.current = null;
10745
- setHoveredNavContainerRect(null);
10746
11430
  }
11431
+ if (allowFooterLinksHover) {
11432
+ const footerLinks = getFooterLinksContainer();
11433
+ if (footerLinks) {
11434
+ const containerRect = footerLinks.getBoundingClientRect();
11435
+ const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
11436
+ if (overContainer && !isPointOverNavItem(footerLinks, x, y) && !isPointOverFooterColumn(x, y)) {
11437
+ hoveredNavContainerRef.current = footerLinks;
11438
+ setHoveredNavContainerRect(footerLinks.getBoundingClientRect());
11439
+ hoveredItemElRef.current = null;
11440
+ setHoveredItemRect(null);
11441
+ return;
11442
+ }
11443
+ }
11444
+ }
11445
+ hoveredNavContainerRef.current = null;
11446
+ setHoveredNavContainerRect(null);
10747
11447
  for (const column of footerColumns) {
10748
11448
  const containerRect = column.getBoundingClientRect();
10749
11449
  const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
@@ -10782,6 +11482,13 @@ function OhhwellsBridge() {
10782
11482
  probeNavigationHoverAt(x, y);
10783
11483
  return;
10784
11484
  }
11485
+ const overMoreMenu = document.elementFromPoint(x, y)?.closest?.(
11486
+ '[data-ohw-more-menu], [data-slot="dropdown-menu-content"], [data-slot="dropdown-menu-item"]'
11487
+ );
11488
+ if (overMoreMenu) {
11489
+ dismissImageHover();
11490
+ return;
11491
+ }
10785
11492
  hoveredNavContainerRef.current = null;
10786
11493
  setHoveredNavContainerRect(null);
10787
11494
  if (hoveredItemElRef.current?.hasAttribute("data-ohw-footer-col") || hoveredItemElRef.current?.hasAttribute("data-ohw-footer-column")) {
@@ -10828,7 +11535,7 @@ function OhhwellsBridge() {
10828
11535
  return;
10829
11536
  }
10830
11537
  const topEl = document.elementFromPoint(x2, y2);
10831
- if (topEl?.closest('[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
11538
+ 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"]')) {
10832
11539
  if (hoveredImageRef.current) {
10833
11540
  hoveredImageRef.current = null;
10834
11541
  resumeAnimTracks();
@@ -11252,6 +11959,7 @@ function OhhwellsBridge() {
11252
11959
  }
11253
11960
  editContentRef.current = { ...editContentRef.current, ...content };
11254
11961
  reconcileNavbarItemsFromContent(editContentRef.current);
11962
+ reconcileFooterOrderFromContent(editContentRef.current);
11255
11963
  syncNavigationDragCursorAttrs();
11256
11964
  enforceLinkHrefs();
11257
11965
  postToParentRef.current({ type: "ow:hydrate-done" });
@@ -11271,6 +11979,7 @@ function OhhwellsBridge() {
11271
11979
  window.addEventListener("message", handleDeactivate);
11272
11980
  const handleUiEscape = (e) => {
11273
11981
  if (e.data?.type !== "ui:escape") return;
11982
+ if (document.querySelector("[data-ohw-more-menu]")) return;
11274
11983
  if (linkPopoverOpenRef.current) {
11275
11984
  setLinkPopoverRef.current(null);
11276
11985
  return;
@@ -11306,6 +12015,11 @@ function OhhwellsBridge() {
11306
12015
  }
11307
12016
  if (selectedElRef.current) {
11308
12017
  if (toolbarVariantRef.current === "select-frame") {
12018
+ const parent2 = getNavigationSelectionParent(selectedElRef.current);
12019
+ if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
12020
+ selectFrameRef.current(parent2);
12021
+ return;
12022
+ }
11309
12023
  deselectRef.current();
11310
12024
  return;
11311
12025
  }
@@ -11320,14 +12034,12 @@ function OhhwellsBridge() {
11320
12034
  window.addEventListener("message", handleUiEscape);
11321
12035
  const handleKeyDown = (e) => {
11322
12036
  if (e.key === "Escape" && document.querySelector("[data-ohw-section-picker]")) return;
12037
+ if (e.key === "Escape" && document.querySelector("[data-ohw-more-menu]")) return;
11323
12038
  if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "a" && activeElRef.current) {
11324
- const navAnchor = getNavigationItemAnchor(activeElRef.current);
11325
- if (navAnchor) {
11326
- e.preventDefault();
11327
- selectAllTextInEditable(activeElRef.current);
11328
- refreshActiveCommandsRef.current();
11329
- return;
11330
- }
12039
+ e.preventDefault();
12040
+ selectAllTextInEditable(activeElRef.current);
12041
+ refreshActiveCommandsRef.current();
12042
+ return;
11331
12043
  }
11332
12044
  if (e.key === "Escape" && linkPopoverOpenRef.current) {
11333
12045
  setLinkPopoverRef.current(null);
@@ -11335,6 +12047,12 @@ function OhhwellsBridge() {
11335
12047
  }
11336
12048
  if (e.key === "Escape" && selectedElRef.current && !activeElRef.current) {
11337
12049
  if (toolbarVariantRef.current === "select-frame") {
12050
+ const parent2 = getNavigationSelectionParent(selectedElRef.current);
12051
+ if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
12052
+ e.preventDefault();
12053
+ selectFrameRef.current(parent2);
12054
+ return;
12055
+ }
11338
12056
  deselectRef.current();
11339
12057
  return;
11340
12058
  }
@@ -11995,7 +12713,7 @@ function OhhwellsBridge() {
11995
12713
  window.addEventListener("hashchange", onHashChange);
11996
12714
  return () => window.removeEventListener("hashchange", onHashChange);
11997
12715
  }, [pathname]);
11998
- const handleCommand = useCallback4((cmd) => {
12716
+ const handleCommand = useCallback5((cmd) => {
11999
12717
  const el = activeElRef.current;
12000
12718
  const selBefore = window.getSelection();
12001
12719
  let savedOffsets = null;
@@ -12031,7 +12749,7 @@ function OhhwellsBridge() {
12031
12749
  if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
12032
12750
  refreshActiveCommandsRef.current();
12033
12751
  }, []);
12034
- const handleStateChange = useCallback4((state) => {
12752
+ const handleStateChange = useCallback5((state) => {
12035
12753
  if (!activeStateElRef.current) return;
12036
12754
  const el = activeStateElRef.current;
12037
12755
  if (state === "Default") {
@@ -12044,22 +12762,22 @@ function OhhwellsBridge() {
12044
12762
  }
12045
12763
  setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
12046
12764
  }, [deactivate]);
12047
- const closeLinkPopover = useCallback4(() => {
12765
+ const closeLinkPopover = useCallback5(() => {
12048
12766
  addNavAfterAnchorRef.current = null;
12049
12767
  setLinkPopover(null);
12050
12768
  }, []);
12051
- const openLinkPopoverForActive = useCallback4(() => {
12769
+ const openLinkPopoverForActive = useCallback5(() => {
12052
12770
  const hrefCtx = getHrefKeyFromElement(activeElRef.current);
12053
12771
  if (!hrefCtx) return;
12054
12772
  bumpLinkPopoverGrace();
12055
12773
  setLinkPopover({
12056
12774
  key: hrefCtx.key,
12057
12775
  mode: "edit",
12058
- target: getLinkHref2(hrefCtx.anchor)
12776
+ target: getLinkHref3(hrefCtx.anchor)
12059
12777
  });
12060
12778
  deactivate();
12061
12779
  }, [deactivate]);
12062
- const openLinkPopoverForSelected = useCallback4(() => {
12780
+ const openLinkPopoverForSelected = useCallback5(() => {
12063
12781
  const anchor = selectedElRef.current;
12064
12782
  if (!anchor) return;
12065
12783
  const key = anchor.getAttribute("data-ohw-href-key");
@@ -12068,11 +12786,108 @@ function OhhwellsBridge() {
12068
12786
  setLinkPopover({
12069
12787
  key,
12070
12788
  mode: "edit",
12071
- target: getLinkHref2(anchor)
12789
+ target: getLinkHref3(anchor)
12072
12790
  });
12073
12791
  deselect();
12074
12792
  }, [deselect]);
12075
- const handleLinkPopoverSubmit = useCallback4(
12793
+ const handleSelectParent = useCallback5(() => {
12794
+ const selected = selectedElRef.current;
12795
+ if (!selected) return;
12796
+ if (toolbarVariantRef.current === "select-frame") {
12797
+ deselectRef.current();
12798
+ return;
12799
+ }
12800
+ const parent = getNavigationSelectionParent(selected);
12801
+ if (parent && isNavigationContainer(parent)) {
12802
+ selectFrameRef.current(parent);
12803
+ } else {
12804
+ deselectRef.current();
12805
+ }
12806
+ }, []);
12807
+ const handleDuplicateSelected = useCallback5(() => {
12808
+ const selected = selectedElRef.current;
12809
+ if (!selected || !isNavigationItem(selected)) return;
12810
+ const hrefKey = selected.getAttribute("data-ohw-href-key");
12811
+ if (!hrefKey) return;
12812
+ if (isNavbarHrefKey(hrefKey)) {
12813
+ const result = duplicateNavbarItem(selected);
12814
+ if (!result) return;
12815
+ applyLinkByKey(result.hrefKey, result.href);
12816
+ document.querySelectorAll(`[data-ohw-key="${result.labelKey}"]`).forEach((el) => {
12817
+ el.textContent = result.label;
12818
+ });
12819
+ const nodes = [
12820
+ { key: result.hrefKey, text: result.href },
12821
+ { key: result.labelKey, text: result.label }
12822
+ ];
12823
+ for (const child of result.childResults) {
12824
+ applyLinkByKey(child.hrefKey, child.href);
12825
+ document.querySelectorAll(`[data-ohw-key="${child.labelKey}"]`).forEach((el) => {
12826
+ el.textContent = child.label;
12827
+ });
12828
+ nodes.push(
12829
+ { key: child.hrefKey, text: child.href },
12830
+ { key: child.labelKey, text: child.label }
12831
+ );
12832
+ }
12833
+ const maxIndex = Math.max(
12834
+ result.index,
12835
+ ...result.childResults.map((c) => c.index)
12836
+ );
12837
+ const navCount = String(maxIndex + 1);
12838
+ nodes.push(
12839
+ { key: NAV_COUNT_KEY, text: navCount },
12840
+ { key: NAV_ORDER_KEY, text: result.orderJson }
12841
+ );
12842
+ editContentRef.current = {
12843
+ ...editContentRef.current,
12844
+ [result.hrefKey]: result.href,
12845
+ [result.labelKey]: result.label,
12846
+ ...Object.fromEntries(
12847
+ result.childResults.flatMap((c) => [
12848
+ [c.hrefKey, c.href],
12849
+ [c.labelKey, c.label]
12850
+ ])
12851
+ ),
12852
+ [NAV_COUNT_KEY]: navCount,
12853
+ [NAV_ORDER_KEY]: result.orderJson
12854
+ };
12855
+ postToParent2({ type: "ow:change", nodes });
12856
+ enforceLinkHrefs();
12857
+ requestAnimationFrame(() => {
12858
+ selectRef.current(result.anchor);
12859
+ });
12860
+ return;
12861
+ }
12862
+ if (isFooterHrefKey(hrefKey)) {
12863
+ const result = duplicateFooterItem(selected);
12864
+ if (!result) return;
12865
+ applyLinkByKey(result.hrefKey, result.href);
12866
+ document.querySelectorAll(`[data-ohw-key="${result.labelKey}"]`).forEach((el) => {
12867
+ el.textContent = result.label;
12868
+ });
12869
+ const orderJson = JSON.stringify(result.order);
12870
+ editContentRef.current = {
12871
+ ...editContentRef.current,
12872
+ [result.hrefKey]: result.href,
12873
+ [result.labelKey]: result.label,
12874
+ [FOOTER_ORDER_KEY]: orderJson
12875
+ };
12876
+ postToParent2({
12877
+ type: "ow:change",
12878
+ nodes: [
12879
+ { key: result.hrefKey, text: result.href },
12880
+ { key: result.labelKey, text: result.label },
12881
+ { key: FOOTER_ORDER_KEY, text: orderJson }
12882
+ ]
12883
+ });
12884
+ enforceLinkHrefs();
12885
+ requestAnimationFrame(() => {
12886
+ selectRef.current(result.anchor);
12887
+ });
12888
+ }
12889
+ }, [postToParent2]);
12890
+ const handleLinkPopoverSubmit = useCallback5(
12076
12891
  (target) => {
12077
12892
  const session = linkPopoverSessionRef.current;
12078
12893
  if (!session) return;
@@ -12131,19 +12946,19 @@ function OhhwellsBridge() {
12131
12946
  const showEditLink = toolbarShowEditLink;
12132
12947
  const currentSections = sectionsByPath[pathname] ?? [];
12133
12948
  linkPopoverOpenRef.current = linkPopover !== null;
12134
- const handleMediaReplace = useCallback4(
12949
+ const handleMediaReplace = useCallback5(
12135
12950
  (key) => {
12136
12951
  postToParent2({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
12137
12952
  },
12138
12953
  [postToParent2, mediaHover?.elementType]
12139
12954
  );
12140
- const handleEditCarousel = useCallback4(
12955
+ const handleEditCarousel = useCallback5(
12141
12956
  (key) => {
12142
12957
  postToParent2({ type: "ow:carousel-open", key, images: readCarouselValue(key) });
12143
12958
  },
12144
12959
  [postToParent2]
12145
12960
  );
12146
- const handleMediaFadeOutComplete = useCallback4((key) => {
12961
+ const handleMediaFadeOutComplete = useCallback5((key) => {
12147
12962
  setUploadingRects((prev) => {
12148
12963
  if (!(key in prev)) return prev;
12149
12964
  const next = { ...prev };
@@ -12151,7 +12966,7 @@ function OhhwellsBridge() {
12151
12966
  return next;
12152
12967
  });
12153
12968
  }, []);
12154
- const handleVideoSettingsChange = useCallback4(
12969
+ const handleVideoSettingsChange = useCallback5(
12155
12970
  (key, settings) => {
12156
12971
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
12157
12972
  const video = getVideoEl(el);
@@ -12174,9 +12989,9 @@ function OhhwellsBridge() {
12174
12989
  [postToParent2]
12175
12990
  );
12176
12991
  return bridgeRoot ? createPortal2(
12177
- /* @__PURE__ */ jsxs14(Fragment5, { children: [
12178
- /* @__PURE__ */ jsx25("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
12179
- Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ jsx25(
12992
+ /* @__PURE__ */ jsxs15(Fragment5, { children: [
12993
+ /* @__PURE__ */ jsx27("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
12994
+ Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ jsx27(
12180
12995
  MediaOverlay,
12181
12996
  {
12182
12997
  hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
@@ -12187,7 +13002,7 @@ function OhhwellsBridge() {
12187
13002
  },
12188
13003
  `uploading-${key}`
12189
13004
  )),
12190
- mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ jsx25(
13005
+ mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ jsx27(
12191
13006
  MediaOverlay,
12192
13007
  {
12193
13008
  hover: mediaHover,
@@ -12196,11 +13011,11 @@ function OhhwellsBridge() {
12196
13011
  onVideoSettingsChange: handleVideoSettingsChange
12197
13012
  }
12198
13013
  ),
12199
- carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx25(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
12200
- siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
12201
- siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
12202
- isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
12203
- isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ jsx25(
13014
+ carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx27(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
13015
+ siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx27(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
13016
+ siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx27(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
13017
+ isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ jsx27(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
13018
+ isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ jsx27(
12204
13019
  "div",
12205
13020
  {
12206
13021
  className: "pointer-events-none fixed z-2147483646",
@@ -12210,7 +13025,7 @@ function OhhwellsBridge() {
12210
13025
  width: slot.width,
12211
13026
  height: slot.height
12212
13027
  },
12213
- children: /* @__PURE__ */ jsx25(
13028
+ children: /* @__PURE__ */ jsx27(
12214
13029
  DropIndicator,
12215
13030
  {
12216
13031
  direction: slot.direction,
@@ -12221,7 +13036,7 @@ function OhhwellsBridge() {
12221
13036
  },
12222
13037
  `footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
12223
13038
  )),
12224
- isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx25(
13039
+ isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx27(
12225
13040
  "div",
12226
13041
  {
12227
13042
  className: "pointer-events-none fixed z-2147483646",
@@ -12231,7 +13046,7 @@ function OhhwellsBridge() {
12231
13046
  width: slot.width,
12232
13047
  height: slot.height
12233
13048
  },
12234
- children: /* @__PURE__ */ jsx25(
13049
+ children: /* @__PURE__ */ jsx27(
12235
13050
  DropIndicator,
12236
13051
  {
12237
13052
  direction: slot.direction,
@@ -12242,10 +13057,18 @@ function OhhwellsBridge() {
12242
13057
  },
12243
13058
  `nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
12244
13059
  )),
12245
- hoveredNavContainerRect && toolbarVariant !== "select-frame" && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
12246
- hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
12247
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx25(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
12248
- toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ jsx25(
13060
+ hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx27(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
13061
+ hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx27(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
13062
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx27(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
13063
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx27(
13064
+ FooterContainerChrome,
13065
+ {
13066
+ rect: toolbarRect,
13067
+ onAdd: handleAddFooterColumn,
13068
+ addDisabled: !canAddFooterColumn()
13069
+ }
13070
+ ),
13071
+ toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ jsx27(
12249
13072
  ItemInteractionLayer,
12250
13073
  {
12251
13074
  rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
@@ -12259,21 +13082,23 @@ function OhhwellsBridge() {
12259
13082
  onItemPointerDown: handleItemChromePointerDown,
12260
13083
  onItemClick: handleItemChromeClick,
12261
13084
  itemDragSurface: !isFooterFrameSelection,
12262
- toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ jsx25(
13085
+ toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ jsx27(
12263
13086
  ItemActionToolbar,
12264
13087
  {
12265
13088
  onEditLink: openLinkPopoverForSelected,
13089
+ onSelectParent: handleSelectParent,
13090
+ onDuplicate: handleDuplicateSelected,
12266
13091
  addItemDisabled: true,
12267
13092
  editLinkDisabled: false,
12268
- moreDisabled: true,
13093
+ moreDisabled: false,
12269
13094
  showAddItem: !selectedIsCta,
12270
13095
  showMore: !selectedIsCta
12271
13096
  }
12272
13097
  ) : void 0
12273
13098
  }
12274
13099
  ),
12275
- toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ jsxs14(Fragment5, { children: [
12276
- /* @__PURE__ */ jsx25(
13100
+ toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ jsxs15(Fragment5, { children: [
13101
+ /* @__PURE__ */ jsx27(
12277
13102
  EditGlowChrome,
12278
13103
  {
12279
13104
  rect: toolbarRect,
@@ -12283,7 +13108,7 @@ function OhhwellsBridge() {
12283
13108
  hideHandle: isItemDragging
12284
13109
  }
12285
13110
  ),
12286
- /* @__PURE__ */ jsx25(
13111
+ /* @__PURE__ */ jsx27(
12287
13112
  FloatingToolbar,
12288
13113
  {
12289
13114
  rect: toolbarRect,
@@ -12296,7 +13121,7 @@ function OhhwellsBridge() {
12296
13121
  }
12297
13122
  )
12298
13123
  ] }),
12299
- maxBadge && /* @__PURE__ */ jsxs14(
13124
+ maxBadge && /* @__PURE__ */ jsxs15(
12300
13125
  "div",
12301
13126
  {
12302
13127
  "data-ohw-max-badge": "",
@@ -12322,7 +13147,7 @@ function OhhwellsBridge() {
12322
13147
  ]
12323
13148
  }
12324
13149
  ),
12325
- toggleState && !linkPopover && /* @__PURE__ */ jsx25(
13150
+ toggleState && !linkPopover && /* @__PURE__ */ jsx27(
12326
13151
  StateToggle,
12327
13152
  {
12328
13153
  rect: toggleState.rect,
@@ -12331,15 +13156,15 @@ function OhhwellsBridge() {
12331
13156
  onStateChange: handleStateChange
12332
13157
  }
12333
13158
  ),
12334
- sectionGap && !linkPopover && /* @__PURE__ */ jsxs14(
13159
+ sectionGap && !linkPopover && /* @__PURE__ */ jsxs15(
12335
13160
  "div",
12336
13161
  {
12337
13162
  "data-ohw-section-insert-line": "",
12338
13163
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
12339
13164
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
12340
13165
  children: [
12341
- /* @__PURE__ */ jsx25("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
12342
- /* @__PURE__ */ jsx25(
13166
+ /* @__PURE__ */ jsx27("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
13167
+ /* @__PURE__ */ jsx27(
12343
13168
  Badge,
12344
13169
  {
12345
13170
  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",
@@ -12356,11 +13181,11 @@ function OhhwellsBridge() {
12356
13181
  children: "Add Section"
12357
13182
  }
12358
13183
  ),
12359
- /* @__PURE__ */ jsx25("div", { className: "flex-1 bg-primary", style: { height: 3 } })
13184
+ /* @__PURE__ */ jsx27("div", { className: "flex-1 bg-primary", style: { height: 3 } })
12360
13185
  ]
12361
13186
  }
12362
13187
  ),
12363
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx25(
13188
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx27(
12364
13189
  LinkPopover,
12365
13190
  {
12366
13191
  panelRef: linkPopoverPanelRef,
@@ -12387,6 +13212,12 @@ export {
12387
13212
  CustomToolbarDivider,
12388
13213
  DragHandle,
12389
13214
  DropIndicator,
13215
+ DropdownMenu,
13216
+ DropdownMenuContent,
13217
+ DropdownMenuGroup,
13218
+ DropdownMenuItem,
13219
+ DropdownMenuSeparator,
13220
+ DropdownMenuTrigger,
12390
13221
  ItemActionToolbar,
12391
13222
  ItemInteractionLayer,
12392
13223
  LinkEditorPanel,