@ohhwells/bridge 0.1.50 → 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 useCallback5, 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
 
@@ -4338,22 +4338,116 @@ var CustomToolbarButton = React4.forwardRef(
4338
4338
  CustomToolbarButton.displayName = "CustomToolbarButton";
4339
4339
 
4340
4340
  // src/ui/item-action-toolbar.tsx
4341
- 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
+ }
4342
4436
 
4343
4437
  // src/ui/tooltip.tsx
4344
4438
  import { Tooltip as TooltipPrimitive } from "radix-ui";
4345
- import { jsx as jsx7 } from "react/jsx-runtime";
4439
+ import { jsx as jsx8 } from "react/jsx-runtime";
4346
4440
  function TooltipProvider({
4347
4441
  delayDuration = 0,
4348
4442
  ...props
4349
4443
  }) {
4350
- return /* @__PURE__ */ jsx7(TooltipPrimitive.Provider, { "data-slot": "tooltip-provider", delayDuration, ...props });
4444
+ return /* @__PURE__ */ jsx8(TooltipPrimitive.Provider, { "data-slot": "tooltip-provider", delayDuration, ...props });
4351
4445
  }
4352
4446
  function Tooltip({ ...props }) {
4353
- return /* @__PURE__ */ jsx7(TooltipPrimitive.Root, { "data-slot": "tooltip", ...props });
4447
+ return /* @__PURE__ */ jsx8(TooltipPrimitive.Root, { "data-slot": "tooltip", ...props });
4354
4448
  }
4355
4449
  function TooltipTrigger({ ...props }) {
4356
- return /* @__PURE__ */ jsx7(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
4450
+ return /* @__PURE__ */ jsx8(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
4357
4451
  }
4358
4452
  var arrowClassBySide = {
4359
4453
  top: "before:bottom-0 before:left-1/2 before:-translate-x-1/2 before:translate-y-1/2",
@@ -4370,7 +4464,7 @@ function TooltipContent({
4370
4464
  ...props
4371
4465
  }) {
4372
4466
  const resolvedSide = side ?? "bottom";
4373
- return /* @__PURE__ */ jsx7(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx7(
4467
+ return /* @__PURE__ */ jsx8(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx8(
4374
4468
  TooltipPrimitive.Content,
4375
4469
  {
4376
4470
  "data-slot": "tooltip-content",
@@ -4393,7 +4487,7 @@ function TooltipContent({
4393
4487
  }
4394
4488
 
4395
4489
  // src/ui/item-action-toolbar.tsx
4396
- import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
4490
+ import { jsx as jsx9, jsxs as jsxs3 } from "react/jsx-runtime";
4397
4491
  function ToolbarActionTooltip({
4398
4492
  label,
4399
4493
  side = "bottom",
@@ -4401,25 +4495,31 @@ function ToolbarActionTooltip({
4401
4495
  buttonProps,
4402
4496
  children
4403
4497
  }) {
4404
- 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 });
4405
4499
  return /* @__PURE__ */ jsxs3(Tooltip, { children: [
4406
- /* @__PURE__ */ jsx8(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ jsx8("span", { className: "inline-flex", children: button }) : button }),
4407
- /* @__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 })
4408
4502
  ] });
4409
4503
  }
4410
4504
  function ItemActionToolbar({
4411
4505
  onEditLink,
4412
4506
  onAddItem,
4413
- onMore,
4507
+ onSelectParent,
4508
+ onDuplicate,
4509
+ onDelete,
4414
4510
  editLinkDisabled = false,
4415
4511
  addItemDisabled = true,
4416
- moreDisabled = true,
4512
+ moreDisabled = false,
4513
+ selectParentDisabled = false,
4514
+ duplicateDisabled = false,
4515
+ deleteDisabled = false,
4417
4516
  showAddItem = true,
4418
4517
  showMore = true,
4419
4518
  tooltipSide = "bottom"
4420
4519
  }) {
4421
- return /* @__PURE__ */ jsx8(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs3(CustomToolbar, { children: [
4422
- /* @__PURE__ */ jsx8(
4520
+ const [moreOpen, setMoreOpen] = useState3(false);
4521
+ return /* @__PURE__ */ jsx9(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs3(CustomToolbar, { children: [
4522
+ /* @__PURE__ */ jsx9(
4423
4523
  ToolbarActionTooltip,
4424
4524
  {
4425
4525
  label: "Edit link",
@@ -4437,10 +4537,10 @@ function ItemActionToolbar({
4437
4537
  e.stopPropagation();
4438
4538
  }
4439
4539
  },
4440
- 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 })
4441
4541
  }
4442
4542
  ),
4443
- showAddItem ? /* @__PURE__ */ jsx8(
4543
+ showAddItem ? /* @__PURE__ */ jsx9(
4444
4544
  ToolbarActionTooltip,
4445
4545
  {
4446
4546
  label: "Add item",
@@ -4454,32 +4554,84 @@ function ItemActionToolbar({
4454
4554
  onAddItem?.();
4455
4555
  }
4456
4556
  },
4457
- 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 })
4458
4558
  }
4459
4559
  ) : null,
4460
- showMore ? /* @__PURE__ */ jsx8(
4461
- ToolbarActionTooltip,
4462
- {
4463
- label: "More",
4464
- side: tooltipSide,
4465
- disabled: moreDisabled,
4466
- 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(),
4467
4583
  onMouseDown: (e) => {
4468
- if (moreDisabled) return;
4469
4584
  e.preventDefault();
4470
4585
  e.stopPropagation();
4471
- onMore?.();
4472
- }
4473
- },
4474
- children: /* @__PURE__ */ jsx8(MoreHorizontal, { className: "size-4 shrink-0", "aria-hidden": true })
4475
- }
4476
- ) : 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
4477
4629
  ] }) });
4478
4630
  }
4479
4631
 
4480
4632
  // src/ui/item-interaction-layer.tsx
4481
4633
  import * as React5 from "react";
4482
- import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
4634
+ import { jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
4483
4635
  var PRIMARY = "var(--ohw-primary, #0885FE)";
4484
4636
  var FOCUS_RING = `0 0 0 4px color-mix(in srgb, ${PRIMARY} 12%, transparent)`;
4485
4637
  var DRAG_SHADOW = "0px 4px 6px -1px rgba(0, 0, 0, 0.1), 0px 2px 4px -2px rgba(0, 0, 0, 0.1)";
@@ -4561,7 +4713,7 @@ function ClampedToolbarSlot({
4561
4713
  window.removeEventListener("resize", clamp);
4562
4714
  };
4563
4715
  }, [placement, children]);
4564
- return /* @__PURE__ */ jsx9(
4716
+ return /* @__PURE__ */ jsx10(
4565
4717
  "div",
4566
4718
  {
4567
4719
  ref: slotRef,
@@ -4617,7 +4769,7 @@ function ItemInteractionLayer({
4617
4769
  zIndex: getChromeZIndex(state)
4618
4770
  },
4619
4771
  children: [
4620
- /* @__PURE__ */ jsx9(
4772
+ /* @__PURE__ */ jsx10(
4621
4773
  "div",
4622
4774
  {
4623
4775
  "aria-hidden": true,
@@ -4625,7 +4777,7 @@ function ItemInteractionLayer({
4625
4777
  style: getChromeStyle(state)
4626
4778
  }
4627
4779
  ),
4628
- itemDragEnabled && /* @__PURE__ */ jsx9(
4780
+ itemDragEnabled && /* @__PURE__ */ jsx10(
4629
4781
  "div",
4630
4782
  {
4631
4783
  "data-ohw-item-drag-surface": "",
@@ -4641,14 +4793,14 @@ function ItemInteractionLayer({
4641
4793
  }
4642
4794
  }
4643
4795
  ),
4644
- showDragHandle && /* @__PURE__ */ jsx9(
4796
+ showDragHandle && /* @__PURE__ */ jsx10(
4645
4797
  "div",
4646
4798
  {
4647
4799
  "data-ohw-drag-handle-container": "",
4648
4800
  className: "pointer-events-auto absolute left-0 top-1/2 z-10 -translate-x-[calc(100%+7px)] -translate-y-1/2",
4649
4801
  style: isDragging ? { opacity: 0 } : void 0,
4650
4802
  "aria-hidden": isDragging || void 0,
4651
- children: /* @__PURE__ */ jsx9(
4803
+ children: /* @__PURE__ */ jsx10(
4652
4804
  DragHandle,
4653
4805
  {
4654
4806
  draggable: !dragDisabled,
@@ -4678,8 +4830,8 @@ function ItemInteractionLayer({
4678
4830
  )
4679
4831
  }
4680
4832
  ),
4681
- showToolbar && state === "active-top" && /* @__PURE__ */ jsx9(ClampedToolbarSlot, { placement: "top", children: toolbar }),
4682
- 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 })
4683
4835
  ]
4684
4836
  }
4685
4837
  );
@@ -4692,7 +4844,7 @@ import { Film, ImageIcon, Pause, Play, Volume2, VolumeX } from "lucide-react";
4692
4844
  // src/ui/button.tsx
4693
4845
  import * as React6 from "react";
4694
4846
  import { Slot } from "radix-ui";
4695
- import { jsx as jsx10 } from "react/jsx-runtime";
4847
+ import { jsx as jsx11 } from "react/jsx-runtime";
4696
4848
  var buttonVariants = cva(
4697
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",
4698
4850
  {
@@ -4716,7 +4868,7 @@ var buttonVariants = cva(
4716
4868
  var Button = React6.forwardRef(
4717
4869
  ({ className, variant, size, asChild = false, ...props }, ref) => {
4718
4870
  const Comp = asChild ? Slot.Root : "button";
4719
- return /* @__PURE__ */ jsx10(
4871
+ return /* @__PURE__ */ jsx11(
4720
4872
  Comp,
4721
4873
  {
4722
4874
  ref,
@@ -4730,7 +4882,7 @@ var Button = React6.forwardRef(
4730
4882
  Button.displayName = "Button";
4731
4883
 
4732
4884
  // src/ui/MediaOverlay.tsx
4733
- 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";
4734
4886
  var MEDIA_UPLOAD_FADE_MS = 300;
4735
4887
  var VIDEO_SETTINGS_BAR_INSET = 8;
4736
4888
  var OVERLAY_BUTTON_STYLE = {
@@ -4788,7 +4940,7 @@ function MediaOverlay({
4788
4940
  return () => anim.cancel();
4789
4941
  }, [isUploading, fadingOut, onFadeOutComplete, hover.key]);
4790
4942
  if (isUploading) {
4791
- return /* @__PURE__ */ jsx11(
4943
+ return /* @__PURE__ */ jsx12(
4792
4944
  "div",
4793
4945
  {
4794
4946
  ref: skeletonRef,
@@ -4797,7 +4949,7 @@ function MediaOverlay({
4797
4949
  "data-ohw-media-skeleton": "",
4798
4950
  "aria-hidden": true,
4799
4951
  style: { ...box, pointerEvents: "none" },
4800
- children: /* @__PURE__ */ jsx11("style", { children: SKELETON_CSS })
4952
+ children: /* @__PURE__ */ jsx12("style", { children: SKELETON_CSS })
4801
4953
  }
4802
4954
  );
4803
4955
  }
@@ -4817,7 +4969,7 @@ function MediaOverlay({
4817
4969
  },
4818
4970
  onClick: (e) => e.stopPropagation(),
4819
4971
  children: [
4820
- /* @__PURE__ */ jsx11(
4972
+ /* @__PURE__ */ jsx12(
4821
4973
  Button,
4822
4974
  {
4823
4975
  "data-ohw-media-overlay": "",
@@ -4832,10 +4984,10 @@ function MediaOverlay({
4832
4984
  e.stopPropagation();
4833
4985
  onVideoSettingsChange?.(hover.key, { autoplay: !autoplay });
4834
4986
  },
4835
- 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 })
4836
4988
  }
4837
4989
  ),
4838
- /* @__PURE__ */ jsx11(
4990
+ /* @__PURE__ */ jsx12(
4839
4991
  Button,
4840
4992
  {
4841
4993
  "data-ohw-media-overlay": "",
@@ -4850,7 +5002,7 @@ function MediaOverlay({
4850
5002
  e.stopPropagation();
4851
5003
  onVideoSettingsChange?.(hover.key, { muted: !muted });
4852
5004
  },
4853
- 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 })
4854
5006
  }
4855
5007
  )
4856
5008
  ]
@@ -4858,7 +5010,7 @@ function MediaOverlay({
4858
5010
  ) : null;
4859
5011
  return /* @__PURE__ */ jsxs5(Fragment2, { children: [
4860
5012
  settingsBar,
4861
- /* @__PURE__ */ jsx11(
5013
+ /* @__PURE__ */ jsx12(
4862
5014
  "div",
4863
5015
  {
4864
5016
  "data-ohw-bridge": "",
@@ -4882,14 +5034,18 @@ function MediaOverlay({
4882
5034
  variant: "outline",
4883
5035
  size: "sm",
4884
5036
  className: "gap-1.5 cursor-pointer hover:bg-background",
4885
- 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
+ },
4886
5042
  onMouseDown: (e) => e.preventDefault(),
4887
5043
  onClick: (e) => {
4888
5044
  e.stopPropagation();
4889
5045
  onReplace(hover.key);
4890
5046
  },
4891
5047
  children: [
4892
- isVideo ? /* @__PURE__ */ jsx11(Film, { size: 14 }) : /* @__PURE__ */ jsx11(ImageIcon, { size: 14 }),
5048
+ isVideo ? /* @__PURE__ */ jsx12(Film, { size: 14 }) : /* @__PURE__ */ jsx12(ImageIcon, { size: 14 }),
4893
5049
  isVideo ? "Replace video" : "Replace image"
4894
5050
  ]
4895
5051
  }
@@ -4901,7 +5057,7 @@ function MediaOverlay({
4901
5057
 
4902
5058
  // src/ui/CarouselOverlay.tsx
4903
5059
  import { GalleryHorizontal } from "lucide-react";
4904
- import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
5060
+ import { jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
4905
5061
  var OVERLAY_BUTTON_STYLE2 = {
4906
5062
  pointerEvents: "auto",
4907
5063
  fontFamily: "Inter, sans-serif",
@@ -4913,7 +5069,7 @@ function CarouselOverlay({
4913
5069
  onEdit
4914
5070
  }) {
4915
5071
  const { rect } = hover;
4916
- return /* @__PURE__ */ jsx12(
5072
+ return /* @__PURE__ */ jsx13(
4917
5073
  "div",
4918
5074
  {
4919
5075
  "data-ohw-bridge": "",
@@ -4945,7 +5101,7 @@ function CarouselOverlay({
4945
5101
  onEdit(hover.key);
4946
5102
  },
4947
5103
  children: [
4948
- /* @__PURE__ */ jsx12(GalleryHorizontal, { size: 14 }),
5104
+ /* @__PURE__ */ jsx13(GalleryHorizontal, { size: 14 }),
4949
5105
  "Edit gallery"
4950
5106
  ]
4951
5107
  }
@@ -5240,22 +5396,22 @@ import { useEffect as useEffect6 } from "react";
5240
5396
  import * as React8 from "react";
5241
5397
  import { Dialog as DialogPrimitive } from "radix-ui";
5242
5398
  import { X } from "lucide-react";
5243
- import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
5399
+ import { jsx as jsx14, jsxs as jsxs7 } from "react/jsx-runtime";
5244
5400
  function Dialog2({
5245
5401
  ...props
5246
5402
  }) {
5247
- return /* @__PURE__ */ jsx13(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
5403
+ return /* @__PURE__ */ jsx14(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
5248
5404
  }
5249
5405
  function DialogPortal({
5250
5406
  ...props
5251
5407
  }) {
5252
- return /* @__PURE__ */ jsx13(DialogPrimitive.Portal, { ...props });
5408
+ return /* @__PURE__ */ jsx14(DialogPrimitive.Portal, { ...props });
5253
5409
  }
5254
5410
  function DialogOverlay({
5255
5411
  className,
5256
5412
  ...props
5257
5413
  }) {
5258
- return /* @__PURE__ */ jsx13(
5414
+ return /* @__PURE__ */ jsx14(
5259
5415
  DialogPrimitive.Overlay,
5260
5416
  {
5261
5417
  "data-slot": "dialog-overlay",
@@ -5269,7 +5425,7 @@ var DialogContent = React8.forwardRef(
5269
5425
  ({ className, children, showCloseButton = true, container, ...props }, ref) => {
5270
5426
  const positionMode = container ? "absolute" : "fixed";
5271
5427
  return /* @__PURE__ */ jsxs7(DialogPortal, { container: container ?? void 0, children: [
5272
- /* @__PURE__ */ jsx13(DialogOverlay, { className: cn(positionMode, "inset-0") }),
5428
+ /* @__PURE__ */ jsx14(DialogOverlay, { className: cn(positionMode, "inset-0") }),
5273
5429
  /* @__PURE__ */ jsxs7(
5274
5430
  DialogPrimitive.Content,
5275
5431
  {
@@ -5286,13 +5442,13 @@ var DialogContent = React8.forwardRef(
5286
5442
  ...props,
5287
5443
  children: [
5288
5444
  children,
5289
- showCloseButton ? /* @__PURE__ */ jsx13(
5445
+ showCloseButton ? /* @__PURE__ */ jsx14(
5290
5446
  DialogPrimitive.Close,
5291
5447
  {
5292
5448
  type: "button",
5293
5449
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
5294
5450
  "aria-label": "Close",
5295
- children: /* @__PURE__ */ jsx13(X, { size: 16, "aria-hidden": true })
5451
+ children: /* @__PURE__ */ jsx14(X, { size: 16, "aria-hidden": true })
5296
5452
  }
5297
5453
  ) : null
5298
5454
  ]
@@ -5306,13 +5462,13 @@ function DialogHeader({
5306
5462
  className,
5307
5463
  ...props
5308
5464
  }) {
5309
- 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 });
5310
5466
  }
5311
5467
  function DialogFooter({
5312
5468
  className,
5313
5469
  ...props
5314
5470
  }) {
5315
- return /* @__PURE__ */ jsx13(
5471
+ return /* @__PURE__ */ jsx14(
5316
5472
  "div",
5317
5473
  {
5318
5474
  className: cn("flex items-center justify-end gap-2", className),
@@ -5320,7 +5476,7 @@ function DialogFooter({
5320
5476
  }
5321
5477
  );
5322
5478
  }
5323
- var DialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
5479
+ var DialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx14(
5324
5480
  DialogPrimitive.Title,
5325
5481
  {
5326
5482
  ref,
@@ -5332,7 +5488,7 @@ var DialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE
5332
5488
  }
5333
5489
  ));
5334
5490
  DialogTitle.displayName = DialogPrimitive.Title.displayName;
5335
- var DialogDescription = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
5491
+ var DialogDescription = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx14(
5336
5492
  DialogPrimitive.Description,
5337
5493
  {
5338
5494
  ref,
@@ -5348,19 +5504,19 @@ import { Info, X as X3 } from "lucide-react";
5348
5504
 
5349
5505
  // src/ui/link-modal/DestinationBreadcrumb.tsx
5350
5506
  import { ArrowRight, File, GalleryVertical } from "lucide-react";
5351
- import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
5507
+ import { jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
5352
5508
  function DestinationBreadcrumb({
5353
5509
  pageTitle,
5354
5510
  sectionLabel
5355
5511
  }) {
5356
5512
  return /* @__PURE__ */ jsxs8("div", { className: "flex w-full flex-col gap-2", children: [
5357
- /* @__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" }),
5358
5514
  /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3", children: [
5359
5515
  /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
5360
- /* @__PURE__ */ jsx14(File, { size: 16, className: "shrink-0 text-foreground", "aria-hidden": true }),
5361
- /* @__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 })
5362
5518
  ] }),
5363
- /* @__PURE__ */ jsx14(
5519
+ /* @__PURE__ */ jsx15(
5364
5520
  ArrowRight,
5365
5521
  {
5366
5522
  size: 16,
@@ -5369,7 +5525,7 @@ function DestinationBreadcrumb({
5369
5525
  }
5370
5526
  ),
5371
5527
  /* @__PURE__ */ jsxs8("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
5372
- /* @__PURE__ */ jsx14(
5528
+ /* @__PURE__ */ jsx15(
5373
5529
  GalleryVertical,
5374
5530
  {
5375
5531
  size: 16,
@@ -5377,7 +5533,7 @@ function DestinationBreadcrumb({
5377
5533
  "aria-hidden": true
5378
5534
  }
5379
5535
  ),
5380
- /* @__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 })
5381
5537
  ] })
5382
5538
  ] })
5383
5539
  ] });
@@ -5385,7 +5541,7 @@ function DestinationBreadcrumb({
5385
5541
 
5386
5542
  // src/ui/link-modal/SectionTreeItem.tsx
5387
5543
  import { GalleryVertical as GalleryVertical2 } from "lucide-react";
5388
- import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
5544
+ import { jsx as jsx16, jsxs as jsxs9 } from "react/jsx-runtime";
5389
5545
  function SectionTreeItem({
5390
5546
  section,
5391
5547
  onSelect,
@@ -5393,7 +5549,7 @@ function SectionTreeItem({
5393
5549
  }) {
5394
5550
  const interactive = Boolean(onSelect);
5395
5551
  return /* @__PURE__ */ jsxs9("div", { className: "flex h-9 w-full items-end pl-3", children: [
5396
- /* @__PURE__ */ jsx15(
5552
+ /* @__PURE__ */ jsx16(
5397
5553
  "div",
5398
5554
  {
5399
5555
  className: "mr-[-1px] h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
@@ -5418,7 +5574,7 @@ function SectionTreeItem({
5418
5574
  interactive && selected && "border-primary"
5419
5575
  ),
5420
5576
  children: [
5421
- /* @__PURE__ */ jsx15(
5577
+ /* @__PURE__ */ jsx16(
5422
5578
  GalleryVertical2,
5423
5579
  {
5424
5580
  size: 16,
@@ -5426,7 +5582,7 @@ function SectionTreeItem({
5426
5582
  "aria-hidden": true
5427
5583
  }
5428
5584
  ),
5429
- /* @__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 })
5430
5586
  ]
5431
5587
  }
5432
5588
  )
@@ -5434,14 +5590,14 @@ function SectionTreeItem({
5434
5590
  }
5435
5591
 
5436
5592
  // src/ui/link-modal/UrlOrPageInput.tsx
5437
- 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";
5438
5594
 
5439
5595
  // src/ui/input.tsx
5440
5596
  import * as React9 from "react";
5441
- import { jsx as jsx16 } from "react/jsx-runtime";
5597
+ import { jsx as jsx17 } from "react/jsx-runtime";
5442
5598
  var Input = React9.forwardRef(
5443
5599
  ({ className, type, ...props }, ref) => {
5444
- return /* @__PURE__ */ jsx16(
5600
+ return /* @__PURE__ */ jsx17(
5445
5601
  "input",
5446
5602
  {
5447
5603
  type,
@@ -5460,9 +5616,9 @@ Input.displayName = "Input";
5460
5616
 
5461
5617
  // src/ui/label.tsx
5462
5618
  import { Label as LabelPrimitive } from "radix-ui";
5463
- import { jsx as jsx17 } from "react/jsx-runtime";
5619
+ import { jsx as jsx18 } from "react/jsx-runtime";
5464
5620
  function Label({ className, ...props }) {
5465
- return /* @__PURE__ */ jsx17(
5621
+ return /* @__PURE__ */ jsx18(
5466
5622
  LabelPrimitive.Root,
5467
5623
  {
5468
5624
  "data-slot": "label",
@@ -5474,11 +5630,11 @@ function Label({ className, ...props }) {
5474
5630
 
5475
5631
  // src/ui/link-modal/UrlOrPageInput.tsx
5476
5632
  import { ChevronDown, File as File2, X as X2 } from "lucide-react";
5477
- import { jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
5633
+ import { jsx as jsx19, jsxs as jsxs10 } from "react/jsx-runtime";
5478
5634
  function FieldChevron({
5479
5635
  onClick
5480
5636
  }) {
5481
- return /* @__PURE__ */ jsx18(
5637
+ return /* @__PURE__ */ jsx19(
5482
5638
  "button",
5483
5639
  {
5484
5640
  type: "button",
@@ -5486,7 +5642,7 @@ function FieldChevron({
5486
5642
  onClick,
5487
5643
  "aria-label": "Open page list",
5488
5644
  tabIndex: -1,
5489
- children: /* @__PURE__ */ jsx18(ChevronDown, { size: 16 })
5645
+ children: /* @__PURE__ */ jsx19(ChevronDown, { size: 16 })
5490
5646
  }
5491
5647
  );
5492
5648
  }
@@ -5505,7 +5661,7 @@ function UrlOrPageInput({
5505
5661
  const inputId = useId2();
5506
5662
  const inputRef = useRef4(null);
5507
5663
  const rootRef = useRef4(null);
5508
- const [isFocused, setIsFocused] = useState3(false);
5664
+ const [isFocused, setIsFocused] = useState4(false);
5509
5665
  useEffect3(() => {
5510
5666
  if (!dropdownOpen) return;
5511
5667
  const isOutside = (e) => {
@@ -5548,10 +5704,10 @@ function UrlOrPageInput({
5548
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"
5549
5705
  );
5550
5706
  return /* @__PURE__ */ jsxs10("div", { className: "flex w-full flex-col gap-2 p-0", children: [
5551
- /* @__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" }),
5552
5708
  /* @__PURE__ */ jsxs10("div", { ref: rootRef, className: "relative w-full", children: [
5553
5709
  /* @__PURE__ */ jsxs10("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
5554
- 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(
5555
5711
  File2,
5556
5712
  {
5557
5713
  size: 16,
@@ -5559,7 +5715,7 @@ function UrlOrPageInput({
5559
5715
  "aria-hidden": true
5560
5716
  }
5561
5717
  ) }) : null,
5562
- 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(
5563
5719
  Input,
5564
5720
  {
5565
5721
  ref: inputRef,
@@ -5585,7 +5741,7 @@ function UrlOrPageInput({
5585
5741
  )
5586
5742
  }
5587
5743
  ),
5588
- selectedPage && !readOnly ? /* @__PURE__ */ jsx18(
5744
+ selectedPage && !readOnly ? /* @__PURE__ */ jsx19(
5589
5745
  "button",
5590
5746
  {
5591
5747
  type: "button",
@@ -5593,12 +5749,12 @@ function UrlOrPageInput({
5593
5749
  onMouseDown: clearSelection,
5594
5750
  "aria-label": "Clear selected page",
5595
5751
  tabIndex: -1,
5596
- children: /* @__PURE__ */ jsx18(X2, { size: 16, "aria-hidden": true })
5752
+ children: /* @__PURE__ */ jsx19(X2, { size: 16, "aria-hidden": true })
5597
5753
  }
5598
5754
  ) : null,
5599
- !readOnly ? /* @__PURE__ */ jsx18(FieldChevron, { onClick: toggleDropdown }) : null
5755
+ !readOnly ? /* @__PURE__ */ jsx19(FieldChevron, { onClick: toggleDropdown }) : null
5600
5756
  ] }),
5601
- dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ jsx18(
5757
+ dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ jsx19(
5602
5758
  "div",
5603
5759
  {
5604
5760
  "data-ohw-link-page-dropdown": "",
@@ -5611,8 +5767,8 @@ function UrlOrPageInput({
5611
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",
5612
5768
  onClick: () => onPageSelect(page),
5613
5769
  children: [
5614
- /* @__PURE__ */ jsx18(File2, { size: 16, className: "shrink-0", "aria-hidden": true }),
5615
- /* @__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 })
5616
5772
  ]
5617
5773
  },
5618
5774
  page.path
@@ -5620,34 +5776,34 @@ function UrlOrPageInput({
5620
5776
  }
5621
5777
  ) : null
5622
5778
  ] }),
5623
- 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
5624
5780
  ] });
5625
5781
  }
5626
5782
 
5627
5783
  // src/ui/link-modal/LinkEditorPanel.tsx
5628
- 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";
5629
5785
  function LinkEditorPanel({ state, onClose }) {
5630
5786
  const isCancel = state.secondaryLabel === "Cancel" || state.secondaryLabel === "Back to sections";
5631
5787
  return /* @__PURE__ */ jsxs11(Fragment3, { children: [
5632
- /* @__PURE__ */ jsx19(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx19(
5788
+ /* @__PURE__ */ jsx20(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx20(
5633
5789
  "button",
5634
5790
  {
5635
5791
  type: "button",
5636
5792
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50 h-7",
5637
5793
  "aria-label": "Close",
5638
5794
  onClick: onClose,
5639
- children: /* @__PURE__ */ jsx19(X3, { size: 16, "aria-hidden": true })
5795
+ children: /* @__PURE__ */ jsx20(X3, { size: 16, "aria-hidden": true })
5640
5796
  }
5641
5797
  ) }),
5642
- /* @__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 }) }),
5643
5799
  /* @__PURE__ */ jsxs11("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
5644
- state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ jsx19(
5800
+ state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ jsx20(
5645
5801
  DestinationBreadcrumb,
5646
5802
  {
5647
5803
  pageTitle: state.selectedPage.title,
5648
5804
  sectionLabel: state.selectedSection.label
5649
5805
  }
5650
- ) : /* @__PURE__ */ jsx19(
5806
+ ) : /* @__PURE__ */ jsx20(
5651
5807
  UrlOrPageInput,
5652
5808
  {
5653
5809
  value: state.searchValue,
@@ -5661,7 +5817,7 @@ function LinkEditorPanel({ state, onClose }) {
5661
5817
  }
5662
5818
  ),
5663
5819
  state.showChooseSection ? /* @__PURE__ */ jsxs11("div", { className: "flex flex-col justify-center gap-2", children: [
5664
- /* @__PURE__ */ jsx19(
5820
+ /* @__PURE__ */ jsx20(
5665
5821
  Button,
5666
5822
  {
5667
5823
  type: "button",
@@ -5673,14 +5829,14 @@ function LinkEditorPanel({ state, onClose }) {
5673
5829
  }
5674
5830
  ),
5675
5831
  /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
5676
- /* @__PURE__ */ jsx19(Info, { size: 16, className: "shrink-0", "aria-hidden": true }),
5677
- /* @__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." })
5678
5834
  ] })
5679
5835
  ] }) : null,
5680
- 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
5681
5837
  ] }),
5682
5838
  /* @__PURE__ */ jsxs11(DialogFooter, { className: "w-full px-6 pb-6", children: [
5683
- /* @__PURE__ */ jsx19(
5839
+ /* @__PURE__ */ jsx20(
5684
5840
  Button,
5685
5841
  {
5686
5842
  type: "button",
@@ -5695,7 +5851,7 @@ function LinkEditorPanel({ state, onClose }) {
5695
5851
  children: state.secondaryLabel
5696
5852
  }
5697
5853
  ),
5698
- /* @__PURE__ */ jsx19(
5854
+ /* @__PURE__ */ jsx20(
5699
5855
  Button,
5700
5856
  {
5701
5857
  type: "button",
@@ -5714,11 +5870,11 @@ function LinkEditorPanel({ state, onClose }) {
5714
5870
  }
5715
5871
 
5716
5872
  // src/ui/link-modal/SectionPickerOverlay.tsx
5717
- import { useCallback as useCallback2, 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";
5718
5874
  import { createPortal } from "react-dom";
5719
5875
  import { ArrowLeft, Check } from "lucide-react";
5720
5876
  import { usePathname, useRouter } from "next/navigation";
5721
- import { jsx as jsx20, jsxs as jsxs12 } from "react/jsx-runtime";
5877
+ import { jsx as jsx21, jsxs as jsxs12 } from "react/jsx-runtime";
5722
5878
  var DIM_OVERLAY = "rgba(0, 0, 0, 0.45)";
5723
5879
  function rectsEqual(a, b) {
5724
5880
  if (a.size !== b.size) return false;
@@ -5751,7 +5907,7 @@ function hitTestSectionId(x, y, sectionIds, rects) {
5751
5907
  return null;
5752
5908
  }
5753
5909
  function useSectionRects(sectionIdsKey, enabled) {
5754
- const [rects, setRects] = useState4(/* @__PURE__ */ new Map());
5910
+ const [rects, setRects] = useState5(/* @__PURE__ */ new Map());
5755
5911
  const sectionIds = useMemo2(
5756
5912
  () => sectionIdsKey ? sectionIdsKey.split("\0") : [],
5757
5913
  [sectionIdsKey]
@@ -5797,13 +5953,13 @@ function SectionPickerOverlay({
5797
5953
  }) {
5798
5954
  const router = useRouter();
5799
5955
  const pathname = usePathname();
5800
- const [selectedId, setSelectedId] = useState4(null);
5801
- const [hoveredId, setHoveredId] = useState4(null);
5956
+ const [selectedId, setSelectedId] = useState5(null);
5957
+ const [hoveredId, setHoveredId] = useState5(null);
5802
5958
  const pointerRef = useRef5(null);
5803
5959
  const pointerScreenRef = useRef5(null);
5804
5960
  const iframeOffsetTopRef = useRef5(null);
5805
5961
  const sectionIdsRef = useRef5([]);
5806
- const [chromeClip, setChromeClip] = useState4(
5962
+ const [chromeClip, setChromeClip] = useState5(
5807
5963
  () => ({
5808
5964
  top: 0,
5809
5965
  bottom: typeof window !== "undefined" ? window.innerHeight : 0
@@ -5957,7 +6113,7 @@ function SectionPickerOverlay({
5957
6113
  role: "dialog",
5958
6114
  "aria-label": "Choose a section",
5959
6115
  children: [
5960
- /* @__PURE__ */ jsx20(
6116
+ /* @__PURE__ */ jsx21(
5961
6117
  "div",
5962
6118
  {
5963
6119
  className: "pointer-events-auto fixed left-5 z-[2]",
@@ -5971,14 +6127,14 @@ function SectionPickerOverlay({
5971
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",
5972
6128
  onClick: onBack,
5973
6129
  children: [
5974
- /* @__PURE__ */ jsx20(ArrowLeft, { className: "size-4 shrink-0", "aria-hidden": true }),
6130
+ /* @__PURE__ */ jsx21(ArrowLeft, { className: "size-4 shrink-0", "aria-hidden": true }),
5975
6131
  "Back"
5976
6132
  ]
5977
6133
  }
5978
6134
  )
5979
6135
  }
5980
6136
  ),
5981
- /* @__PURE__ */ jsx20(
6137
+ /* @__PURE__ */ jsx21(
5982
6138
  "div",
5983
6139
  {
5984
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",
@@ -5991,7 +6147,7 @@ function SectionPickerOverlay({
5991
6147
  children: "Click on section to select"
5992
6148
  }
5993
6149
  ),
5994
- !isOnTargetPage ? /* @__PURE__ */ jsx20(
6150
+ !isOnTargetPage ? /* @__PURE__ */ jsx21(
5995
6151
  "div",
5996
6152
  {
5997
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",
@@ -5999,7 +6155,7 @@ function SectionPickerOverlay({
5999
6155
  children: "Loading page preview\u2026"
6000
6156
  }
6001
6157
  ) : null,
6002
- 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,
6003
6159
  isOnTargetPage ? liveSections.map((section) => {
6004
6160
  const rect = rects.get(section.id);
6005
6161
  if (!rect || rect.width <= 0 || rect.height <= 0) return null;
@@ -6021,7 +6177,7 @@ function SectionPickerOverlay({
6021
6177
  "aria-label": `Select section ${section.label}`,
6022
6178
  onClick: () => handleSelect(section),
6023
6179
  children: [
6024
- isLit ? /* @__PURE__ */ jsx20(
6180
+ isLit ? /* @__PURE__ */ jsx21(
6025
6181
  "span",
6026
6182
  {
6027
6183
  className: "pointer-events-none absolute",
@@ -6034,13 +6190,13 @@ function SectionPickerOverlay({
6034
6190
  "aria-hidden": true
6035
6191
  }
6036
6192
  ) : null,
6037
- isSelected ? /* @__PURE__ */ jsx20(
6193
+ isSelected ? /* @__PURE__ */ jsx21(
6038
6194
  "span",
6039
6195
  {
6040
6196
  className: "absolute right-3 top-3 flex size-8 items-center justify-center rounded-full text-white",
6041
6197
  style: { backgroundColor: "var(--ohw-primary, #0885fe)" },
6042
6198
  "aria-hidden": true,
6043
- children: /* @__PURE__ */ jsx20(Check, { className: "size-5" })
6199
+ children: /* @__PURE__ */ jsx21(Check, { className: "size-5" })
6044
6200
  }
6045
6201
  ) : null
6046
6202
  ]
@@ -6056,7 +6212,7 @@ function SectionPickerOverlay({
6056
6212
  }
6057
6213
 
6058
6214
  // src/ui/link-modal/useLinkModalState.ts
6059
- import { useCallback as useCallback3, 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";
6060
6216
  function useLinkModalState({
6061
6217
  open,
6062
6218
  mode,
@@ -6069,12 +6225,12 @@ function useLinkModalState({
6069
6225
  onSubmit
6070
6226
  }) {
6071
6227
  const availablePages = useMemo3(() => pages, [pages]);
6072
- const [searchValue, setSearchValue] = useState5("");
6073
- const [selectedPage, setSelectedPage] = useState5(null);
6074
- const [selectedSection, setSelectedSection] = useState5(null);
6075
- const [step, setStep] = useState5("input");
6076
- const [dropdownOpen, setDropdownOpen] = useState5(false);
6077
- const [urlError, setUrlError] = useState5("");
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("");
6078
6234
  const reset = useCallback3(() => {
6079
6235
  setSearchValue("");
6080
6236
  setSelectedPage(null);
@@ -6220,7 +6376,7 @@ function useLinkModalState({
6220
6376
  }
6221
6377
 
6222
6378
  // src/ui/link-modal/LinkPopover.tsx
6223
- 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";
6224
6380
  function postToParent(data) {
6225
6381
  window.parent?.postMessage(data, "*");
6226
6382
  }
@@ -6317,14 +6473,14 @@ function LinkPopover({
6317
6473
  };
6318
6474
  }, [open, sectionPickerActive]);
6319
6475
  return /* @__PURE__ */ jsxs13(Fragment4, { children: [
6320
- /* @__PURE__ */ jsx21(
6476
+ /* @__PURE__ */ jsx22(
6321
6477
  Dialog2,
6322
6478
  {
6323
6479
  open: open && !sectionPickerActive,
6324
6480
  onOpenChange: (next) => {
6325
6481
  if (!next) onClose?.();
6326
6482
  },
6327
- children: /* @__PURE__ */ jsx21(
6483
+ children: /* @__PURE__ */ jsx22(
6328
6484
  DialogContent,
6329
6485
  {
6330
6486
  ref: panelRef,
@@ -6334,12 +6490,12 @@ function LinkPopover({
6334
6490
  "data-ohw-bridge": "",
6335
6491
  showCloseButton: false,
6336
6492
  className: "gap-0 p-0 w-full max-w-[448px] pointer-events-auto z-[2147483646] overflow-visible",
6337
- children: /* @__PURE__ */ jsx21(LinkEditorPanel, { state, onClose })
6493
+ children: /* @__PURE__ */ jsx22(LinkEditorPanel, { state, onClose })
6338
6494
  }
6339
6495
  )
6340
6496
  }
6341
6497
  ),
6342
- sectionPickerActive && state.selectedPage ? /* @__PURE__ */ jsx21(
6498
+ sectionPickerActive && state.selectedPage ? /* @__PURE__ */ jsx22(
6343
6499
  SectionPickerOverlay,
6344
6500
  {
6345
6501
  pagePath: state.selectedPage.path,
@@ -6878,9 +7034,57 @@ function insertNavbarItem(href, label, afterAnchor = null) {
6878
7034
  order
6879
7035
  };
6880
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
+ }
6881
7084
 
6882
7085
  // src/lib/footer-items.ts
6883
7086
  var FOOTER_ORDER_KEY = "__ohw_footer_order";
7087
+ var MAX_FOOTER_COLUMNS = 18;
6884
7088
  var FOOTER_HREF_RE = /^footer-(\d+)-(\d+)-href$/;
6885
7089
  function parseFooterHrefKey(key) {
6886
7090
  if (!key) return null;
@@ -7061,7 +7265,191 @@ function parseFooterOrder(content) {
7061
7265
  return null;
7062
7266
  }
7063
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
+ }
7064
7451
  function reconcileFooterOrderFromContent(content) {
7452
+ reconcileFooterColumnsFromContent(content);
7065
7453
  const order = parseFooterOrder(content);
7066
7454
  if (!order?.length) return;
7067
7455
  const current = getFooterOrderFromDom();
@@ -7071,6 +7459,26 @@ function reconcileFooterOrderFromContent(content) {
7071
7459
  }
7072
7460
  applyFooterOrder(order);
7073
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
+ }
7074
7482
  function isRowLayoutColumn(links) {
7075
7483
  if (links.length < 2) return false;
7076
7484
  const firstTop = links[0].getBoundingClientRect().top;
@@ -7225,6 +7633,108 @@ function hitTestColumnDropSlot(clientX, _clientY) {
7225
7633
  }
7226
7634
  return best?.slot ?? null;
7227
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
+ }
7228
7738
 
7229
7739
  // src/lib/item-drag-interaction.ts
7230
7740
  function disableNativeHrefDrag(el) {
@@ -7423,7 +7933,7 @@ function hitTestNavDropSlot(clientX, clientY, draggedHrefKey) {
7423
7933
  }
7424
7934
 
7425
7935
  // src/useNavItemDrag.ts
7426
- import { useCallback as useCallback4, 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";
7427
7937
  function useNavItemDrag({
7428
7938
  isEditMode,
7429
7939
  editContentRef,
@@ -7449,8 +7959,8 @@ function useNavItemDrag({
7449
7959
  isNavbarButton: isNavbarButton3
7450
7960
  }) {
7451
7961
  const navDragRef = useRef6(null);
7452
- const [navDropSlots, setNavDropSlots] = useState6([]);
7453
- const [activeNavDropIndex, setActiveNavDropIndex] = useState6(null);
7962
+ const [navDropSlots, setNavDropSlots] = useState7([]);
7963
+ const [activeNavDropIndex, setActiveNavDropIndex] = useState7(null);
7454
7964
  const navPointerDragRef = useRef6(null);
7455
7965
  const clearNavDragVisuals = useCallback4(() => {
7456
7966
  navDragRef.current = null;
@@ -7758,8 +8268,59 @@ function useNavItemDrag({
7758
8268
  };
7759
8269
  }
7760
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
+
7761
8322
  // src/lib/carousel.ts
7762
- import { useEffect as useEffect8, useState as useState7 } from "react";
8323
+ import { useEffect as useEffect8, useState as useState8 } from "react";
7763
8324
  var CAROUSEL_ATTR = "data-ohw-carousel";
7764
8325
  var CAROUSEL_VALUE_ATTR = "data-ohw-carousel-value";
7765
8326
  var CAROUSEL_SLIDE_ATTR = "data-ohw-carousel-slide";
@@ -7821,7 +8382,7 @@ function applyCarouselNode(key, val) {
7821
8382
  return true;
7822
8383
  }
7823
8384
  function useOhwCarousel(key, initial) {
7824
- const [images, setImages] = useState7(initial);
8385
+ const [images, setImages] = useState8(initial);
7825
8386
  useEffect8(() => {
7826
8387
  const el = document.querySelector(
7827
8388
  `[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`
@@ -7843,14 +8404,14 @@ function useOhwCarousel(key, initial) {
7843
8404
  }
7844
8405
 
7845
8406
  // src/ui/navbar-container-chrome.tsx
7846
- import { Plus as Plus2 } from "lucide-react";
7847
- 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";
7848
8409
  function NavbarContainerChrome({
7849
8410
  rect,
7850
8411
  onAdd
7851
8412
  }) {
7852
8413
  const chromeGap = 6;
7853
- return /* @__PURE__ */ jsx22(
8414
+ return /* @__PURE__ */ jsx24(
7854
8415
  "div",
7855
8416
  {
7856
8417
  "data-ohw-navbar-container-chrome": "",
@@ -7862,7 +8423,7 @@ function NavbarContainerChrome({
7862
8423
  width: rect.width + chromeGap * 2,
7863
8424
  height: rect.height + chromeGap * 2
7864
8425
  },
7865
- children: /* @__PURE__ */ jsx22(
8426
+ children: /* @__PURE__ */ jsx24(
7866
8427
  "button",
7867
8428
  {
7868
8429
  type: "button",
@@ -7879,7 +8440,7 @@ function NavbarContainerChrome({
7879
8440
  e.stopPropagation();
7880
8441
  onAdd();
7881
8442
  },
7882
- 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 })
7883
8444
  }
7884
8445
  )
7885
8446
  }
@@ -7888,7 +8449,7 @@ function NavbarContainerChrome({
7888
8449
 
7889
8450
  // src/ui/drop-indicator.tsx
7890
8451
  import * as React10 from "react";
7891
- import { jsx as jsx23 } from "react/jsx-runtime";
8452
+ import { jsx as jsx25 } from "react/jsx-runtime";
7892
8453
  var dropIndicatorVariants = cva(
7893
8454
  "ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
7894
8455
  {
@@ -7912,7 +8473,7 @@ var dropIndicatorVariants = cva(
7912
8473
  );
7913
8474
  var DropIndicator = React10.forwardRef(
7914
8475
  ({ className, direction, state, ...props }, ref) => {
7915
- return /* @__PURE__ */ jsx23(
8476
+ return /* @__PURE__ */ jsx25(
7916
8477
  "div",
7917
8478
  {
7918
8479
  ref,
@@ -7929,7 +8490,7 @@ var DropIndicator = React10.forwardRef(
7929
8490
  DropIndicator.displayName = "DropIndicator";
7930
8491
 
7931
8492
  // src/ui/badge.tsx
7932
- import { jsx as jsx24 } from "react/jsx-runtime";
8493
+ import { jsx as jsx26 } from "react/jsx-runtime";
7933
8494
  var badgeVariants = cva(
7934
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",
7935
8496
  {
@@ -7947,12 +8508,12 @@ var badgeVariants = cva(
7947
8508
  }
7948
8509
  );
7949
8510
  function Badge({ className, variant, ...props }) {
7950
- return /* @__PURE__ */ jsx24("div", { className: cn(badgeVariants({ variant }), className), ...props });
8511
+ return /* @__PURE__ */ jsx26("div", { className: cn(badgeVariants({ variant }), className), ...props });
7951
8512
  }
7952
8513
 
7953
8514
  // src/OhhwellsBridge.tsx
7954
8515
  import { Link as Link2 } from "lucide-react";
7955
- 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";
7956
8517
  var PRIMARY2 = "#0885FE";
7957
8518
  var IMAGE_FADE_MS = 300;
7958
8519
  function runOpacityFade(el, onDone) {
@@ -8131,7 +8692,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
8131
8692
  const root = createRoot(container);
8132
8693
  flushSync(() => {
8133
8694
  root.render(
8134
- /* @__PURE__ */ jsx25(
8695
+ /* @__PURE__ */ jsx27(
8135
8696
  SchedulingWidget,
8136
8697
  {
8137
8698
  notifyOnConnect,
@@ -8171,7 +8732,7 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
8171
8732
  }
8172
8733
  }
8173
8734
  }
8174
- function getLinkHref2(el) {
8735
+ function getLinkHref3(el) {
8175
8736
  const anchor = el instanceof HTMLAnchorElement ? el : el.querySelector("a");
8176
8737
  return anchor?.getAttribute("href") ?? "";
8177
8738
  }
@@ -8221,7 +8782,7 @@ function collectEditableNodes(extraContent) {
8221
8782
  return { key: el.dataset.ohwKey ?? "", type: "video", text: getVideoEl(el)?.src ?? "" };
8222
8783
  }
8223
8784
  if (el.dataset.ohwEditable === "link") {
8224
- return { key: el.dataset.ohwKey ?? "", type: "link", text: getLinkHref2(el) };
8785
+ return { key: el.dataset.ohwKey ?? "", type: "link", text: getLinkHref3(el) };
8225
8786
  }
8226
8787
  return {
8227
8788
  key: el.dataset.ohwKey ?? "",
@@ -8232,7 +8793,7 @@ function collectEditableNodes(extraContent) {
8232
8793
  document.querySelectorAll("[data-ohw-href-key]").forEach((el) => {
8233
8794
  const key = el.getAttribute("data-ohw-href-key") ?? "";
8234
8795
  if (!key) return;
8235
- nodes.push({ key, type: "link", text: getLinkHref2(el) });
8796
+ nodes.push({ key, type: "link", text: getLinkHref3(el) });
8236
8797
  });
8237
8798
  if (extraContent) {
8238
8799
  for (const key of [NAV_ORDER_KEY, FOOTER_ORDER_KEY, NAV_COUNT_KEY]) {
@@ -8335,7 +8896,7 @@ function applyLinkByKey(key, val) {
8335
8896
  }
8336
8897
  function isInsideLinkEditor(target) {
8337
8898
  return Boolean(
8338
- 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"]')
8339
8900
  );
8340
8901
  }
8341
8902
  function getHrefKeyFromElement(el) {
@@ -8416,7 +8977,7 @@ function isInferredFooterGroup(el) {
8416
8977
  return countFooterNavItems(el) >= 2;
8417
8978
  }
8418
8979
  function isNavigationContainer(el) {
8419
- 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);
8420
8981
  }
8421
8982
  function isNavbarLinksContainer(el) {
8422
8983
  return el.hasAttribute("data-ohw-nav-container");
@@ -8435,6 +8996,9 @@ function isPointOverNavigation(x, y) {
8435
8996
  const roots = /* @__PURE__ */ new Set();
8436
8997
  const navRoot = document.querySelector("[data-ohw-nav-root]") ?? document.querySelector("nav");
8437
8998
  if (navRoot) roots.add(navRoot);
8999
+ document.querySelectorAll("[data-ohw-nav-drawer], [data-ohw-nav-container]").forEach((el) => {
9000
+ roots.add(el);
9001
+ });
8438
9002
  const footer = document.querySelector("footer");
8439
9003
  if (footer) roots.add(footer);
8440
9004
  for (const root of roots) {
@@ -8463,6 +9027,12 @@ function isPointOverNavItem(container, x, y) {
8463
9027
  return x >= itemRect.left && x <= itemRect.right && y >= itemRect.top && y <= itemRect.bottom;
8464
9028
  });
8465
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
+ }
8466
9036
  function resolveNavContainerSelectionTarget(target, clientX, clientY) {
8467
9037
  if (getNavigationItemAnchor(target)) return null;
8468
9038
  if (target.closest('[data-ohw-role="navbar-button"]')) return null;
@@ -8493,7 +9063,10 @@ function getNavigationSelectionParent(el) {
8493
9063
  if (footerGroup) return footerGroup;
8494
9064
  return getNavigationRoot(el);
8495
9065
  }
8496
- 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)) {
8497
9070
  return getNavigationRoot(el);
8498
9071
  }
8499
9072
  return null;
@@ -8720,7 +9293,7 @@ function EditGlowChrome({
8720
9293
  hideHandle = false
8721
9294
  }) {
8722
9295
  const GAP = SELECTION_CHROME_GAP2;
8723
- return /* @__PURE__ */ jsxs14(
9296
+ return /* @__PURE__ */ jsxs15(
8724
9297
  "div",
8725
9298
  {
8726
9299
  ref: elRef,
@@ -8735,7 +9308,7 @@ function EditGlowChrome({
8735
9308
  zIndex: 2147483646
8736
9309
  },
8737
9310
  children: [
8738
- /* @__PURE__ */ jsx25(
9311
+ /* @__PURE__ */ jsx27(
8739
9312
  "div",
8740
9313
  {
8741
9314
  style: {
@@ -8748,7 +9321,7 @@ function EditGlowChrome({
8748
9321
  }
8749
9322
  }
8750
9323
  ),
8751
- reorderHrefKey && !hideHandle && /* @__PURE__ */ jsx25(
9324
+ reorderHrefKey && !hideHandle && /* @__PURE__ */ jsx27(
8752
9325
  "div",
8753
9326
  {
8754
9327
  "data-ohw-drag-handle-container": "",
@@ -8760,7 +9333,7 @@ function EditGlowChrome({
8760
9333
  transform: "translate(calc(-100% - 7px), -50%)",
8761
9334
  pointerEvents: dragDisabled ? "none" : "auto"
8762
9335
  },
8763
- children: /* @__PURE__ */ jsx25(
9336
+ children: /* @__PURE__ */ jsx27(
8764
9337
  DragHandle,
8765
9338
  {
8766
9339
  "aria-label": `Reorder ${reorderHrefKey}`,
@@ -8970,7 +9543,7 @@ function FloatingToolbar({
8970
9543
  return () => ro.disconnect();
8971
9544
  }, [showEditLink, activeCommands]);
8972
9545
  const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
8973
- return /* @__PURE__ */ jsx25(
9546
+ return /* @__PURE__ */ jsx27(
8974
9547
  "div",
8975
9548
  {
8976
9549
  ref: setRefs,
@@ -8982,12 +9555,12 @@ function FloatingToolbar({
8982
9555
  zIndex: 2147483647,
8983
9556
  pointerEvents: "auto"
8984
9557
  },
8985
- children: /* @__PURE__ */ jsxs14(CustomToolbar, { children: [
8986
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs14(React11.Fragment, { children: [
8987
- 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, {}),
8988
9561
  btns.map((btn) => {
8989
9562
  const isActive = activeCommands.has(btn.cmd);
8990
- return /* @__PURE__ */ jsx25(
9563
+ return /* @__PURE__ */ jsx27(
8991
9564
  CustomToolbarButton,
8992
9565
  {
8993
9566
  title: btn.title,
@@ -8996,7 +9569,7 @@ function FloatingToolbar({
8996
9569
  e.preventDefault();
8997
9570
  onCommand(btn.cmd);
8998
9571
  },
8999
- children: /* @__PURE__ */ jsx25(
9572
+ children: /* @__PURE__ */ jsx27(
9000
9573
  "svg",
9001
9574
  {
9002
9575
  width: "16",
@@ -9017,7 +9590,7 @@ function FloatingToolbar({
9017
9590
  );
9018
9591
  })
9019
9592
  ] }, gi)),
9020
- showEditLink ? /* @__PURE__ */ jsx25(
9593
+ showEditLink ? /* @__PURE__ */ jsx27(
9021
9594
  CustomToolbarButton,
9022
9595
  {
9023
9596
  type: "button",
@@ -9031,7 +9604,7 @@ function FloatingToolbar({
9031
9604
  e.preventDefault();
9032
9605
  e.stopPropagation();
9033
9606
  },
9034
- 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 })
9035
9608
  }
9036
9609
  ) : null
9037
9610
  ] })
@@ -9048,7 +9621,7 @@ function StateToggle({
9048
9621
  states,
9049
9622
  onStateChange
9050
9623
  }) {
9051
- return /* @__PURE__ */ jsx25(
9624
+ return /* @__PURE__ */ jsx27(
9052
9625
  ToggleGroup,
9053
9626
  {
9054
9627
  "data-ohw-state-toggle": "",
@@ -9062,7 +9635,7 @@ function StateToggle({
9062
9635
  left: rect.right - 8,
9063
9636
  transform: "translateX(-100%)"
9064
9637
  },
9065
- 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))
9066
9639
  }
9067
9640
  );
9068
9641
  }
@@ -9089,7 +9662,7 @@ function OhhwellsBridge() {
9089
9662
  const router = useRouter2();
9090
9663
  const searchParams = useSearchParams();
9091
9664
  const isEditMode = isEditSessionActive();
9092
- const [bridgeRoot, setBridgeRoot] = useState8(null);
9665
+ const [bridgeRoot, setBridgeRoot] = useState9(null);
9093
9666
  useEffect9(() => {
9094
9667
  const figtreeFontId = "ohw-figtree-font";
9095
9668
  if (!document.getElementById(figtreeFontId)) {
@@ -9123,7 +9696,7 @@ function OhhwellsBridge() {
9123
9696
  window.parent.postMessage(data, "*");
9124
9697
  }
9125
9698
  }, []);
9126
- const [fetchState, setFetchState] = useState8("idle");
9699
+ const [fetchState, setFetchState] = useState9("idle");
9127
9700
  const autoSaveTimers = useRef7(/* @__PURE__ */ new Map());
9128
9701
  const activeElRef = useRef7(null);
9129
9702
  const pointerHeldRef = useRef7(false);
@@ -9134,7 +9707,7 @@ function OhhwellsBridge() {
9134
9707
  const activeStateElRef = useRef7(null);
9135
9708
  const parentScrollRef = useRef7(null);
9136
9709
  const visibleViewportRef = useRef7(null);
9137
- const [dialogPortalContainer, setDialogPortalContainer] = useState8(null);
9710
+ const [dialogPortalContainer, setDialogPortalContainer] = useState9(null);
9138
9711
  const attachVisibleViewport = useCallback5((node) => {
9139
9712
  visibleViewportRef.current = node;
9140
9713
  setDialogPortalContainer(node);
@@ -9145,9 +9718,9 @@ function OhhwellsBridge() {
9145
9718
  const hoveredImageRef = useRef7(null);
9146
9719
  const hoveredImageHasTextOverlapRef = useRef7(false);
9147
9720
  const dragOverElRef = useRef7(null);
9148
- const [mediaHover, setMediaHover] = useState8(null);
9149
- const [carouselHover, setCarouselHover] = useState8(null);
9150
- const [uploadingRects, setUploadingRects] = useState8({});
9721
+ const [mediaHover, setMediaHover] = useState9(null);
9722
+ const [carouselHover, setCarouselHover] = useState9(null);
9723
+ const [uploadingRects, setUploadingRects] = useState9({});
9151
9724
  const hoveredGapRef = useRef7(null);
9152
9725
  const imageUnhoverTimerRef = useRef7(null);
9153
9726
  const imageShowTimerRef = useRef7(null);
@@ -9172,40 +9745,40 @@ function OhhwellsBridge() {
9172
9745
  postToParentRef.current = postToParent2;
9173
9746
  const sectionsLoadedRef = useRef7(false);
9174
9747
  const pendingScheduleConfigRequests = useRef7([]);
9175
- const [toolbarRect, setToolbarRect] = useState8(null);
9176
- const [toolbarVariant, setToolbarVariant] = useState8("none");
9748
+ const [toolbarRect, setToolbarRect] = useState9(null);
9749
+ const [toolbarVariant, setToolbarVariant] = useState9("none");
9177
9750
  const toolbarVariantRef = useRef7("none");
9178
9751
  toolbarVariantRef.current = toolbarVariant;
9179
- const [selectedIsCta, setSelectedIsCta] = useState8(false);
9180
- const [reorderHrefKey, setReorderHrefKey] = useState8(null);
9181
- const [reorderDragDisabled, setReorderDragDisabled] = useState8(false);
9182
- const [toggleState, setToggleState] = useState8(null);
9183
- const [maxBadge, setMaxBadge] = useState8(null);
9184
- const [activeCommands, setActiveCommands] = useState8(/* @__PURE__ */ new Set());
9185
- const [sectionGap, setSectionGap] = useState8(null);
9186
- 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);
9187
9760
  const hoveredNavContainerRef = useRef7(null);
9188
- const [hoveredNavContainerRect, setHoveredNavContainerRect] = useState8(null);
9761
+ const [hoveredNavContainerRect, setHoveredNavContainerRect] = useState9(null);
9189
9762
  const hoveredItemElRef = useRef7(null);
9190
- const [hoveredItemRect, setHoveredItemRect] = useState8(null);
9763
+ const [hoveredItemRect, setHoveredItemRect] = useState9(null);
9191
9764
  const siblingHintElRef = useRef7(null);
9192
- const [siblingHintRect, setSiblingHintRect] = useState8(null);
9193
- const [siblingHintRects, setSiblingHintRects] = useState8([]);
9194
- const [isItemDragging, setIsItemDragging] = useState8(false);
9195
- 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);
9196
9769
  const footerDragRef = useRef7(null);
9197
- const [footerDropSlots, setFooterDropSlots] = useState8([]);
9198
- const [activeFooterDropIndex, setActiveFooterDropIndex] = useState8(null);
9199
- const [draggedItemRect, setDraggedItemRect] = useState8(null);
9770
+ const [footerDropSlots, setFooterDropSlots] = useState9([]);
9771
+ const [activeFooterDropIndex, setActiveFooterDropIndex] = useState9(null);
9772
+ const [draggedItemRect, setDraggedItemRect] = useState9(null);
9200
9773
  const footerPointerDragRef = useRef7(null);
9201
9774
  const suppressNextClickRef = useRef7(false);
9202
9775
  const suppressClickUntilRef = useRef7(0);
9203
- const [linkPopover, setLinkPopover] = useState8(null);
9776
+ const [linkPopover, setLinkPopover] = useState9(null);
9204
9777
  const linkPopoverSessionRef = useRef7(null);
9205
9778
  const addNavAfterAnchorRef = useRef7(null);
9206
9779
  const editContentRef = useRef7({});
9207
- const [sitePages, setSitePages] = useState8([]);
9208
- const [sectionsByPath, setSectionsByPath] = useState8({});
9780
+ const [sitePages, setSitePages] = useState9([]);
9781
+ const [sectionsByPath, setSectionsByPath] = useState9({});
9209
9782
  const sectionsPrefetchGenRef = useRef7(0);
9210
9783
  const setLinkPopoverRef = useRef7(setLinkPopover);
9211
9784
  const linkPopoverPanelRef = useRef7(null);
@@ -9559,6 +10132,27 @@ function OhhwellsBridge() {
9559
10132
  intent: "add-nav"
9560
10133
  });
9561
10134
  }, []);
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]);
9562
10156
  const clearFooterDragVisuals = useCallback5(() => {
9563
10157
  footerDragRef.current = null;
9564
10158
  setSiblingHintRects([]);
@@ -9883,7 +10477,7 @@ function OhhwellsBridge() {
9883
10477
  const selectFrame = useCallback5((el) => {
9884
10478
  if (!isNavigationContainer(el)) return;
9885
10479
  if (activeElRef.current) deactivate();
9886
- 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)));
9887
10481
  selectedElRef.current = el;
9888
10482
  selectedHrefKeyRef.current = null;
9889
10483
  selectedFooterColAttrRef.current = isFooterColumn ? el.getAttribute("data-ohw-footer-col") ?? String(listFooterColumns().indexOf(el)) : null;
@@ -10416,7 +11010,7 @@ function OhhwellsBridge() {
10416
11010
  setLinkPopoverRef.current({
10417
11011
  key: editable.dataset.ohwKey ?? "",
10418
11012
  mode: "edit",
10419
- target: getLinkHref2(editable)
11013
+ target: getLinkHref3(editable)
10420
11014
  });
10421
11015
  return;
10422
11016
  }
@@ -10441,7 +11035,7 @@ function OhhwellsBridge() {
10441
11035
  }
10442
11036
  e.preventDefault();
10443
11037
  e.stopPropagation();
10444
- activateRef.current(editable);
11038
+ activateRef.current(editable, { caretX: e.clientX, caretY: e.clientY });
10445
11039
  return;
10446
11040
  }
10447
11041
  const hrefAnchor = getNavigationItemAnchor(target);
@@ -10468,6 +11062,18 @@ function OhhwellsBridge() {
10468
11062
  selectFrameRef.current(footerColClick);
10469
11063
  return;
10470
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
+ }
10471
11077
  const navContainerToSelect = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
10472
11078
  if (navContainerToSelect) {
10473
11079
  e.preventDefault();
@@ -10526,8 +11132,8 @@ function OhhwellsBridge() {
10526
11132
  return;
10527
11133
  }
10528
11134
  const navLabel = getNavigationLabelEditable(target);
10529
- if (!navLabel) return;
10530
- 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;
10531
11137
  e.preventDefault();
10532
11138
  e.stopPropagation();
10533
11139
  if (activeElRef.current !== editable) {
@@ -10548,16 +11154,38 @@ function OhhwellsBridge() {
10548
11154
  setHoveredNavContainerRect(null);
10549
11155
  return;
10550
11156
  }
10551
- if (toolbarVariantRef.current !== "select-frame") {
10552
- const navContainer = target.closest("[data-ohw-nav-container]");
10553
- if (navContainer && !getNavigationItemAnchor(target)) {
10554
- hoveredNavContainerRef.current = navContainer;
10555
- setHoveredNavContainerRect(navContainer.getBoundingClientRect());
10556
- hoveredItemElRef.current = null;
10557
- setHoveredItemRect(null);
10558
- 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
+ }
10559
11171
  }
10560
- 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") {
10561
11189
  hoveredNavContainerRef.current = null;
10562
11190
  setHoveredNavContainerRect(null);
10563
11191
  }
@@ -10599,9 +11227,9 @@ function OhhwellsBridge() {
10599
11227
  };
10600
11228
  const handleMouseOut = (e) => {
10601
11229
  const target = e.target;
10602
- 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")) {
10603
11231
  const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
10604
- 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]")) {
10605
11233
  return;
10606
11234
  }
10607
11235
  hoveredNavContainerRef.current = null;
@@ -10696,6 +11324,15 @@ function OhhwellsBridge() {
10696
11324
  if (track) track.setAttribute("data-ohw-hover-paused", "");
10697
11325
  };
10698
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
+ };
10699
11336
  const findImageAtPoint = (clientX, clientY, fromParentViewport) => {
10700
11337
  const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
10701
11338
  const images = Array.from(document.querySelectorAll(MEDIA_SELECTOR));
@@ -10739,16 +11376,13 @@ function OhhwellsBridge() {
10739
11376
  }
10740
11377
  return smallest;
10741
11378
  };
10742
- const dismissImageHover = () => {
10743
- if (hoveredImageRef.current) {
10744
- hoveredImageRef.current = null;
10745
- hoveredImageHasTextOverlapRef.current = false;
10746
- resumeAnimTracks();
10747
- postToParentRef.current({ type: "ow:image-unhover" });
10748
- }
10749
- };
10750
11379
  const probeNavigationHoverAt = (x, y) => {
10751
- 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) {
10752
11386
  hoveredNavContainerRef.current = null;
10753
11387
  setHoveredNavContainerRect(null);
10754
11388
  }
@@ -10770,7 +11404,6 @@ function OhhwellsBridge() {
10770
11404
  if (navItemHit) {
10771
11405
  hoveredNavContainerRef.current = null;
10772
11406
  setHoveredNavContainerRect(null);
10773
- const selected = selectedElRef.current;
10774
11407
  if (selected !== navItemHit) {
10775
11408
  clearHrefKeyHover(navItemHit);
10776
11409
  hoveredItemElRef.current = navItemHit;
@@ -10782,7 +11415,7 @@ function OhhwellsBridge() {
10782
11415
  return;
10783
11416
  }
10784
11417
  }
10785
- if (toolbarVariantRef.current !== "select-frame") {
11418
+ if (allowNavContainerHover) {
10786
11419
  for (const container of navContainers) {
10787
11420
  const containerRect = container.getBoundingClientRect();
10788
11421
  const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
@@ -10794,12 +11427,23 @@ function OhhwellsBridge() {
10794
11427
  setHoveredItemRect(null);
10795
11428
  return;
10796
11429
  }
10797
- hoveredNavContainerRef.current = null;
10798
- setHoveredNavContainerRect(null);
10799
- } else {
10800
- hoveredNavContainerRef.current = null;
10801
- setHoveredNavContainerRect(null);
10802
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);
10803
11447
  for (const column of footerColumns) {
10804
11448
  const containerRect = column.getBoundingClientRect();
10805
11449
  const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
@@ -10838,6 +11482,13 @@ function OhhwellsBridge() {
10838
11482
  probeNavigationHoverAt(x, y);
10839
11483
  return;
10840
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
+ }
10841
11492
  hoveredNavContainerRef.current = null;
10842
11493
  setHoveredNavContainerRect(null);
10843
11494
  if (hoveredItemElRef.current?.hasAttribute("data-ohw-footer-col") || hoveredItemElRef.current?.hasAttribute("data-ohw-footer-column")) {
@@ -10884,7 +11535,7 @@ function OhhwellsBridge() {
10884
11535
  return;
10885
11536
  }
10886
11537
  const topEl = document.elementFromPoint(x2, y2);
10887
- 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"]')) {
10888
11539
  if (hoveredImageRef.current) {
10889
11540
  hoveredImageRef.current = null;
10890
11541
  resumeAnimTracks();
@@ -11308,6 +11959,7 @@ function OhhwellsBridge() {
11308
11959
  }
11309
11960
  editContentRef.current = { ...editContentRef.current, ...content };
11310
11961
  reconcileNavbarItemsFromContent(editContentRef.current);
11962
+ reconcileFooterOrderFromContent(editContentRef.current);
11311
11963
  syncNavigationDragCursorAttrs();
11312
11964
  enforceLinkHrefs();
11313
11965
  postToParentRef.current({ type: "ow:hydrate-done" });
@@ -11327,6 +11979,7 @@ function OhhwellsBridge() {
11327
11979
  window.addEventListener("message", handleDeactivate);
11328
11980
  const handleUiEscape = (e) => {
11329
11981
  if (e.data?.type !== "ui:escape") return;
11982
+ if (document.querySelector("[data-ohw-more-menu]")) return;
11330
11983
  if (linkPopoverOpenRef.current) {
11331
11984
  setLinkPopoverRef.current(null);
11332
11985
  return;
@@ -11362,6 +12015,11 @@ function OhhwellsBridge() {
11362
12015
  }
11363
12016
  if (selectedElRef.current) {
11364
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
+ }
11365
12023
  deselectRef.current();
11366
12024
  return;
11367
12025
  }
@@ -11376,14 +12034,12 @@ function OhhwellsBridge() {
11376
12034
  window.addEventListener("message", handleUiEscape);
11377
12035
  const handleKeyDown = (e) => {
11378
12036
  if (e.key === "Escape" && document.querySelector("[data-ohw-section-picker]")) return;
12037
+ if (e.key === "Escape" && document.querySelector("[data-ohw-more-menu]")) return;
11379
12038
  if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "a" && activeElRef.current) {
11380
- const navAnchor = getNavigationItemAnchor(activeElRef.current);
11381
- if (navAnchor) {
11382
- e.preventDefault();
11383
- selectAllTextInEditable(activeElRef.current);
11384
- refreshActiveCommandsRef.current();
11385
- return;
11386
- }
12039
+ e.preventDefault();
12040
+ selectAllTextInEditable(activeElRef.current);
12041
+ refreshActiveCommandsRef.current();
12042
+ return;
11387
12043
  }
11388
12044
  if (e.key === "Escape" && linkPopoverOpenRef.current) {
11389
12045
  setLinkPopoverRef.current(null);
@@ -11391,6 +12047,12 @@ function OhhwellsBridge() {
11391
12047
  }
11392
12048
  if (e.key === "Escape" && selectedElRef.current && !activeElRef.current) {
11393
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
+ }
11394
12056
  deselectRef.current();
11395
12057
  return;
11396
12058
  }
@@ -12111,7 +12773,7 @@ function OhhwellsBridge() {
12111
12773
  setLinkPopover({
12112
12774
  key: hrefCtx.key,
12113
12775
  mode: "edit",
12114
- target: getLinkHref2(hrefCtx.anchor)
12776
+ target: getLinkHref3(hrefCtx.anchor)
12115
12777
  });
12116
12778
  deactivate();
12117
12779
  }, [deactivate]);
@@ -12124,10 +12786,107 @@ function OhhwellsBridge() {
12124
12786
  setLinkPopover({
12125
12787
  key,
12126
12788
  mode: "edit",
12127
- target: getLinkHref2(anchor)
12789
+ target: getLinkHref3(anchor)
12128
12790
  });
12129
12791
  deselect();
12130
12792
  }, [deselect]);
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]);
12131
12890
  const handleLinkPopoverSubmit = useCallback5(
12132
12891
  (target) => {
12133
12892
  const session = linkPopoverSessionRef.current;
@@ -12230,9 +12989,9 @@ function OhhwellsBridge() {
12230
12989
  [postToParent2]
12231
12990
  );
12232
12991
  return bridgeRoot ? createPortal2(
12233
- /* @__PURE__ */ jsxs14(Fragment5, { children: [
12234
- /* @__PURE__ */ jsx25("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
12235
- 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(
12236
12995
  MediaOverlay,
12237
12996
  {
12238
12997
  hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
@@ -12243,7 +13002,7 @@ function OhhwellsBridge() {
12243
13002
  },
12244
13003
  `uploading-${key}`
12245
13004
  )),
12246
- mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ jsx25(
13005
+ mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ jsx27(
12247
13006
  MediaOverlay,
12248
13007
  {
12249
13008
  hover: mediaHover,
@@ -12252,11 +13011,11 @@ function OhhwellsBridge() {
12252
13011
  onVideoSettingsChange: handleVideoSettingsChange
12253
13012
  }
12254
13013
  ),
12255
- carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx25(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
12256
- siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
12257
- siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
12258
- isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
12259
- 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(
12260
13019
  "div",
12261
13020
  {
12262
13021
  className: "pointer-events-none fixed z-2147483646",
@@ -12266,7 +13025,7 @@ function OhhwellsBridge() {
12266
13025
  width: slot.width,
12267
13026
  height: slot.height
12268
13027
  },
12269
- children: /* @__PURE__ */ jsx25(
13028
+ children: /* @__PURE__ */ jsx27(
12270
13029
  DropIndicator,
12271
13030
  {
12272
13031
  direction: slot.direction,
@@ -12277,7 +13036,7 @@ function OhhwellsBridge() {
12277
13036
  },
12278
13037
  `footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
12279
13038
  )),
12280
- isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx25(
13039
+ isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx27(
12281
13040
  "div",
12282
13041
  {
12283
13042
  className: "pointer-events-none fixed z-2147483646",
@@ -12287,7 +13046,7 @@ function OhhwellsBridge() {
12287
13046
  width: slot.width,
12288
13047
  height: slot.height
12289
13048
  },
12290
- children: /* @__PURE__ */ jsx25(
13049
+ children: /* @__PURE__ */ jsx27(
12291
13050
  DropIndicator,
12292
13051
  {
12293
13052
  direction: slot.direction,
@@ -12298,10 +13057,18 @@ function OhhwellsBridge() {
12298
13057
  },
12299
13058
  `nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
12300
13059
  )),
12301
- hoveredNavContainerRect && toolbarVariant !== "select-frame" && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
12302
- hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
12303
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx25(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
12304
- 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(
12305
13072
  ItemInteractionLayer,
12306
13073
  {
12307
13074
  rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
@@ -12315,21 +13082,23 @@ function OhhwellsBridge() {
12315
13082
  onItemPointerDown: handleItemChromePointerDown,
12316
13083
  onItemClick: handleItemChromeClick,
12317
13084
  itemDragSurface: !isFooterFrameSelection,
12318
- toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ jsx25(
13085
+ toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ jsx27(
12319
13086
  ItemActionToolbar,
12320
13087
  {
12321
13088
  onEditLink: openLinkPopoverForSelected,
13089
+ onSelectParent: handleSelectParent,
13090
+ onDuplicate: handleDuplicateSelected,
12322
13091
  addItemDisabled: true,
12323
13092
  editLinkDisabled: false,
12324
- moreDisabled: true,
13093
+ moreDisabled: false,
12325
13094
  showAddItem: !selectedIsCta,
12326
13095
  showMore: !selectedIsCta
12327
13096
  }
12328
13097
  ) : void 0
12329
13098
  }
12330
13099
  ),
12331
- toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ jsxs14(Fragment5, { children: [
12332
- /* @__PURE__ */ jsx25(
13100
+ toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ jsxs15(Fragment5, { children: [
13101
+ /* @__PURE__ */ jsx27(
12333
13102
  EditGlowChrome,
12334
13103
  {
12335
13104
  rect: toolbarRect,
@@ -12339,7 +13108,7 @@ function OhhwellsBridge() {
12339
13108
  hideHandle: isItemDragging
12340
13109
  }
12341
13110
  ),
12342
- /* @__PURE__ */ jsx25(
13111
+ /* @__PURE__ */ jsx27(
12343
13112
  FloatingToolbar,
12344
13113
  {
12345
13114
  rect: toolbarRect,
@@ -12352,7 +13121,7 @@ function OhhwellsBridge() {
12352
13121
  }
12353
13122
  )
12354
13123
  ] }),
12355
- maxBadge && /* @__PURE__ */ jsxs14(
13124
+ maxBadge && /* @__PURE__ */ jsxs15(
12356
13125
  "div",
12357
13126
  {
12358
13127
  "data-ohw-max-badge": "",
@@ -12378,7 +13147,7 @@ function OhhwellsBridge() {
12378
13147
  ]
12379
13148
  }
12380
13149
  ),
12381
- toggleState && !linkPopover && /* @__PURE__ */ jsx25(
13150
+ toggleState && !linkPopover && /* @__PURE__ */ jsx27(
12382
13151
  StateToggle,
12383
13152
  {
12384
13153
  rect: toggleState.rect,
@@ -12387,15 +13156,15 @@ function OhhwellsBridge() {
12387
13156
  onStateChange: handleStateChange
12388
13157
  }
12389
13158
  ),
12390
- sectionGap && !linkPopover && /* @__PURE__ */ jsxs14(
13159
+ sectionGap && !linkPopover && /* @__PURE__ */ jsxs15(
12391
13160
  "div",
12392
13161
  {
12393
13162
  "data-ohw-section-insert-line": "",
12394
13163
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
12395
13164
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
12396
13165
  children: [
12397
- /* @__PURE__ */ jsx25("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
12398
- /* @__PURE__ */ jsx25(
13166
+ /* @__PURE__ */ jsx27("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
13167
+ /* @__PURE__ */ jsx27(
12399
13168
  Badge,
12400
13169
  {
12401
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",
@@ -12412,11 +13181,11 @@ function OhhwellsBridge() {
12412
13181
  children: "Add Section"
12413
13182
  }
12414
13183
  ),
12415
- /* @__PURE__ */ jsx25("div", { className: "flex-1 bg-primary", style: { height: 3 } })
13184
+ /* @__PURE__ */ jsx27("div", { className: "flex-1 bg-primary", style: { height: 3 } })
12416
13185
  ]
12417
13186
  }
12418
13187
  ),
12419
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx25(
13188
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx27(
12420
13189
  LinkPopover,
12421
13190
  {
12422
13191
  panelRef: linkPopoverPanelRef,
@@ -12443,6 +13212,12 @@ export {
12443
13212
  CustomToolbarDivider,
12444
13213
  DragHandle,
12445
13214
  DropIndicator,
13215
+ DropdownMenu,
13216
+ DropdownMenuContent,
13217
+ DropdownMenuGroup,
13218
+ DropdownMenuItem,
13219
+ DropdownMenuSeparator,
13220
+ DropdownMenuTrigger,
12446
13221
  ItemActionToolbar,
12447
13222
  ItemInteractionLayer,
12448
13223
  LinkEditorPanel,