@ohhwells/bridge 0.1.32 → 0.1.33-next.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  // src/index.ts
32
32
  var index_exports = {};
33
33
  __export(index_exports, {
34
+ DragHandle: () => DragHandle,
34
35
  LinkEditorPanel: () => LinkEditorPanel,
35
36
  LinkPopover: () => LinkPopover,
36
37
  OhhwellsBridge: () => OhhwellsBridge,
@@ -41,6 +42,7 @@ __export(index_exports, {
41
42
  buildTarget: () => buildTarget,
42
43
  filterAvailablePages: () => filterAvailablePages,
43
44
  getEditModeInitialState: () => getEditModeInitialState,
45
+ isEditSessionActive: () => isEditSessionActive,
44
46
  isValidUrl: () => isValidUrl,
45
47
  parseTarget: () => parseTarget,
46
48
  toggleVariants: () => toggleVariants,
@@ -4250,6 +4252,34 @@ function ToggleGroupItem({
4250
4252
  );
4251
4253
  }
4252
4254
 
4255
+ // src/ui/drag-handle.tsx
4256
+ var React3 = __toESM(require("react"), 1);
4257
+ var import_lucide_react = require("lucide-react");
4258
+ var import_jsx_runtime5 = require("react/jsx-runtime");
4259
+ var DragHandle = React3.forwardRef(
4260
+ ({ className, type = "button", ...props }, ref) => {
4261
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4262
+ "button",
4263
+ {
4264
+ ref,
4265
+ type,
4266
+ "data-slot": "drag-handle",
4267
+ className: cn(
4268
+ "inline-flex h-7 w-4 shrink-0 items-center justify-center rounded-md transition-all duration-200 max-h-[30px]",
4269
+ "bg-white border border-transparent text-stone-500 shadow-md cursor-grab",
4270
+ "enabled:hover:border enabled:hover:border-stone-200 enabled:hover:text-stone-950",
4271
+ "enabled:active:border enabled:active:border-primary enabled:active:bg-primary-50 enabled:active:text-stone-950 enabled:active:shadow enabled:active:cursor-grabbing",
4272
+ "disabled:cursor-not-allowed disabled:opacity-40 disabled:text-stone-950 disabled:pointer-events-none",
4273
+ className
4274
+ ),
4275
+ ...props,
4276
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react.GripVertical, { className: "size-4 shrink-0", "aria-hidden": "true" })
4277
+ }
4278
+ );
4279
+ }
4280
+ );
4281
+ DragHandle.displayName = "DragHandle";
4282
+
4253
4283
  // src/OhhwellsBridge.tsx
4254
4284
  var import_react_dom2 = require("react-dom");
4255
4285
  var import_navigation = require("next/navigation");
@@ -4529,60 +4559,60 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
4529
4559
  }
4530
4560
 
4531
4561
  // src/ui/dialog.tsx
4532
- var React3 = __toESM(require("react"), 1);
4562
+ var React4 = __toESM(require("react"), 1);
4533
4563
  var import_radix_ui3 = require("radix-ui");
4534
4564
 
4535
4565
  // src/ui/icons.tsx
4536
- var import_jsx_runtime5 = require("react/jsx-runtime");
4566
+ var import_jsx_runtime6 = require("react/jsx-runtime");
4537
4567
  function IconX({ className, ...props }) {
4538
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4539
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M18 6 6 18" }),
4540
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "m6 6 12 12" })
4568
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4569
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M18 6 6 18" }),
4570
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "m6 6 12 12" })
4541
4571
  ] });
4542
4572
  }
4543
4573
  function IconChevronDown({ className, ...props }) {
4544
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "m6 9 6 6 6-6" }) });
4574
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "m6 9 6 6 6-6" }) });
4545
4575
  }
4546
4576
  function IconFile({ className, ...props }) {
4547
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4548
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }),
4549
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" })
4577
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4578
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }),
4579
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" })
4550
4580
  ] });
4551
4581
  }
4552
4582
  function IconInfo({ className, ...props }) {
4553
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4554
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
4555
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M12 16v-4" }),
4556
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M12 8h.01" })
4583
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4584
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
4585
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M12 16v-4" }),
4586
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M12 8h.01" })
4557
4587
  ] });
4558
4588
  }
4559
4589
  function IconArrowRight({ className, ...props }) {
4560
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4561
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M5 12h14" }),
4562
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "m12 5 7 7-7 7" })
4590
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4591
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M5 12h14" }),
4592
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "m12 5 7 7-7 7" })
4563
4593
  ] });
4564
4594
  }
4565
4595
  function IconSection({ className, ...props }) {
4566
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4567
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("rect", { width: "18", height: "7", x: "3", y: "3", rx: "1" }),
4568
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("rect", { width: "9", height: "7", x: "3", y: "14", rx: "1" }),
4569
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("rect", { width: "5", height: "7", x: "16", y: "14", rx: "1" })
4596
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4597
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { width: "18", height: "7", x: "3", y: "3", rx: "1" }),
4598
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { width: "9", height: "7", x: "3", y: "14", rx: "1" }),
4599
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { width: "5", height: "7", x: "16", y: "14", rx: "1" })
4570
4600
  ] });
4571
4601
  }
4572
4602
 
4573
4603
  // src/ui/dialog.tsx
4574
- var import_jsx_runtime6 = require("react/jsx-runtime");
4604
+ var import_jsx_runtime7 = require("react/jsx-runtime");
4575
4605
  function Dialog2({ ...props }) {
4576
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_radix_ui3.Dialog.Root, { "data-slot": "dialog", ...props });
4606
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui3.Dialog.Root, { "data-slot": "dialog", ...props });
4577
4607
  }
4578
4608
  function DialogPortal({ ...props }) {
4579
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_radix_ui3.Dialog.Portal, { ...props });
4609
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui3.Dialog.Portal, { ...props });
4580
4610
  }
4581
4611
  function DialogOverlay({
4582
4612
  className,
4583
4613
  ...props
4584
4614
  }) {
4585
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4615
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4586
4616
  import_radix_ui3.Dialog.Overlay,
4587
4617
  {
4588
4618
  "data-slot": "dialog-overlay",
@@ -4592,11 +4622,11 @@ function DialogOverlay({
4592
4622
  }
4593
4623
  );
4594
4624
  }
4595
- var DialogContent = React3.forwardRef(({ className, children, showCloseButton = true, container, ...props }, ref) => {
4625
+ var DialogContent = React4.forwardRef(({ className, children, showCloseButton = true, container, ...props }, ref) => {
4596
4626
  const positionMode = container ? "absolute" : "fixed";
4597
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(DialogPortal, { container: container ?? void 0, children: [
4598
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
4599
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4627
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(DialogPortal, { container: container ?? void 0, children: [
4628
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
4629
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
4600
4630
  import_radix_ui3.Dialog.Content,
4601
4631
  {
4602
4632
  ref,
@@ -4612,13 +4642,13 @@ var DialogContent = React3.forwardRef(({ className, children, showCloseButton =
4612
4642
  ...props,
4613
4643
  children: [
4614
4644
  children,
4615
- showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4645
+ showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4616
4646
  import_radix_ui3.Dialog.Close,
4617
4647
  {
4618
4648
  type: "button",
4619
4649
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
4620
4650
  "aria-label": "Close",
4621
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(IconX, { "aria-hidden": true })
4651
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconX, { "aria-hidden": true })
4622
4652
  }
4623
4653
  ) : null
4624
4654
  ]
@@ -4628,12 +4658,12 @@ var DialogContent = React3.forwardRef(({ className, children, showCloseButton =
4628
4658
  });
4629
4659
  DialogContent.displayName = import_radix_ui3.Dialog.Content.displayName;
4630
4660
  function DialogHeader({ className, ...props }) {
4631
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
4661
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
4632
4662
  }
4633
4663
  function DialogFooter({ className, ...props }) {
4634
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: cn("flex items-center justify-end gap-2", className), ...props });
4664
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: cn("flex items-center justify-end gap-2", className), ...props });
4635
4665
  }
4636
- var DialogTitle = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4666
+ var DialogTitle = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4637
4667
  import_radix_ui3.Dialog.Title,
4638
4668
  {
4639
4669
  ref,
@@ -4642,7 +4672,7 @@ var DialogTitle = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE
4642
4672
  }
4643
4673
  ));
4644
4674
  DialogTitle.displayName = import_radix_ui3.Dialog.Title.displayName;
4645
- var DialogDescription = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4675
+ var DialogDescription = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4646
4676
  import_radix_ui3.Dialog.Description,
4647
4677
  {
4648
4678
  ref,
@@ -4654,9 +4684,9 @@ DialogDescription.displayName = import_radix_ui3.Dialog.Description.displayName;
4654
4684
  var DialogClose = import_radix_ui3.Dialog.Close;
4655
4685
 
4656
4686
  // src/ui/button.tsx
4657
- var React4 = __toESM(require("react"), 1);
4687
+ var React5 = __toESM(require("react"), 1);
4658
4688
  var import_radix_ui4 = require("radix-ui");
4659
- var import_jsx_runtime7 = require("react/jsx-runtime");
4689
+ var import_jsx_runtime8 = require("react/jsx-runtime");
4660
4690
  var buttonVariants = cva(
4661
4691
  "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",
4662
4692
  {
@@ -4677,10 +4707,10 @@ var buttonVariants = cva(
4677
4707
  }
4678
4708
  }
4679
4709
  );
4680
- var Button = React4.forwardRef(
4710
+ var Button = React5.forwardRef(
4681
4711
  ({ className, variant, size, asChild = false, ...props }, ref) => {
4682
4712
  const Comp = asChild ? import_radix_ui4.Slot.Root : "button";
4683
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4713
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4684
4714
  Comp,
4685
4715
  {
4686
4716
  ref,
@@ -4694,37 +4724,37 @@ var Button = React4.forwardRef(
4694
4724
  Button.displayName = "Button";
4695
4725
 
4696
4726
  // src/ui/link-modal/DestinationBreadcrumb.tsx
4697
- var import_jsx_runtime8 = require("react/jsx-runtime");
4727
+ var import_jsx_runtime9 = require("react/jsx-runtime");
4698
4728
  function DestinationBreadcrumb({ pageTitle, sectionLabel }) {
4699
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex w-full flex-col gap-2", children: [
4700
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-sm font-medium text-foreground", children: "Destination" }),
4701
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-3", children: [
4702
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-2", children: [
4703
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconFile, { className: "shrink-0 text-foreground", "aria-hidden": true }),
4704
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-sm font-medium leading-none text-foreground", children: pageTitle })
4729
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex w-full flex-col gap-2", children: [
4730
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-sm font-medium text-foreground", children: "Destination" }),
4731
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center gap-3", children: [
4732
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center gap-2", children: [
4733
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconFile, { className: "shrink-0 text-foreground", "aria-hidden": true }),
4734
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-sm font-medium leading-none text-foreground", children: pageTitle })
4705
4735
  ] }),
4706
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconArrowRight, { className: "shrink-0 text-muted-foreground", "aria-hidden": true }),
4707
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
4708
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconSection, { className: "shrink-0 text-foreground", "aria-hidden": true }),
4709
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
4736
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconArrowRight, { className: "shrink-0 text-muted-foreground", "aria-hidden": true }),
4737
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
4738
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconSection, { className: "shrink-0 text-foreground", "aria-hidden": true }),
4739
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
4710
4740
  ] })
4711
4741
  ] })
4712
4742
  ] });
4713
4743
  }
4714
4744
 
4715
4745
  // src/ui/link-modal/SectionTreeItem.tsx
4716
- var import_jsx_runtime9 = require("react/jsx-runtime");
4746
+ var import_jsx_runtime10 = require("react/jsx-runtime");
4717
4747
  function SectionTreeItem({ section, onSelect, selected }) {
4718
4748
  const interactive = Boolean(onSelect);
4719
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex h-9 w-full items-end pl-3", children: [
4720
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4749
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex h-9 w-full items-end pl-3", children: [
4750
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4721
4751
  "div",
4722
4752
  {
4723
4753
  className: "mr-[-1px] h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
4724
4754
  "aria-hidden": true
4725
4755
  }
4726
4756
  ),
4727
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
4757
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
4728
4758
  "div",
4729
4759
  {
4730
4760
  role: interactive ? "button" : void 0,
@@ -4742,8 +4772,8 @@ function SectionTreeItem({ section, onSelect, selected }) {
4742
4772
  interactive && selected && "border-primary"
4743
4773
  ),
4744
4774
  children: [
4745
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconSection, { className: "shrink-0 text-foreground", "aria-hidden": true }),
4746
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
4775
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconSection, { className: "shrink-0 text-foreground", "aria-hidden": true }),
4776
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
4747
4777
  ]
4748
4778
  }
4749
4779
  )
@@ -4751,11 +4781,11 @@ function SectionTreeItem({ section, onSelect, selected }) {
4751
4781
  }
4752
4782
  function SectionPickerList({ sections, onSelect }) {
4753
4783
  if (sections.length === 0) {
4754
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." });
4784
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." });
4755
4785
  }
4756
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-col gap-1", children: [
4757
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-sm text-muted-foreground", children: "Pick a section this link should scroll to." }),
4758
- sections.map((section) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SectionTreeItem, { section, onSelect }, section.id))
4786
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-1", children: [
4787
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "text-sm text-muted-foreground", children: "Pick a section this link should scroll to." }),
4788
+ sections.map((section) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SectionTreeItem, { section, onSelect }, section.id))
4759
4789
  ] });
4760
4790
  }
4761
4791
 
@@ -4763,11 +4793,11 @@ function SectionPickerList({ sections, onSelect }) {
4763
4793
  var import_react4 = require("react");
4764
4794
 
4765
4795
  // src/ui/input.tsx
4766
- var React5 = __toESM(require("react"), 1);
4767
- var import_jsx_runtime10 = require("react/jsx-runtime");
4768
- var Input = React5.forwardRef(
4796
+ var React6 = __toESM(require("react"), 1);
4797
+ var import_jsx_runtime11 = require("react/jsx-runtime");
4798
+ var Input = React6.forwardRef(
4769
4799
  ({ className, type, ...props }, ref) => {
4770
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4800
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
4771
4801
  "input",
4772
4802
  {
4773
4803
  type,
@@ -4786,9 +4816,9 @@ Input.displayName = "Input";
4786
4816
 
4787
4817
  // src/ui/label.tsx
4788
4818
  var import_radix_ui5 = require("radix-ui");
4789
- var import_jsx_runtime11 = require("react/jsx-runtime");
4819
+ var import_jsx_runtime12 = require("react/jsx-runtime");
4790
4820
  function Label({ className, ...props }) {
4791
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
4821
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4792
4822
  import_radix_ui5.Label.Root,
4793
4823
  {
4794
4824
  "data-slot": "label",
@@ -4799,9 +4829,9 @@ function Label({ className, ...props }) {
4799
4829
  }
4800
4830
 
4801
4831
  // src/ui/link-modal/UrlOrPageInput.tsx
4802
- var import_jsx_runtime12 = require("react/jsx-runtime");
4832
+ var import_jsx_runtime13 = require("react/jsx-runtime");
4803
4833
  function FieldChevron({ onClick }) {
4804
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4834
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4805
4835
  "button",
4806
4836
  {
4807
4837
  type: "button",
@@ -4809,7 +4839,7 @@ function FieldChevron({ onClick }) {
4809
4839
  onClick,
4810
4840
  "aria-label": "Open page list",
4811
4841
  tabIndex: -1,
4812
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconChevronDown, {})
4842
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconChevronDown, {})
4813
4843
  }
4814
4844
  );
4815
4845
  }
@@ -4848,12 +4878,12 @@ function UrlOrPageInput({
4848
4878
  "data-ohw-link-field flex h-10 w-full items-center overflow-hidden rounded-md border bg-background pl-3 pr-3 py-2 outline-none transition-[border-color,box-shadow]",
4849
4879
  urlError ? "border-destructive shadow-[0_0_0_1px_var(--ohw-destructive)]" : isFocused ? "border-primary shadow-[0_0_0_1px_var(--ohw-primary)]" : "border-input"
4850
4880
  );
4851
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex w-full flex-col gap-2 p-0", children: [
4852
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
4853
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "relative w-full", children: [
4854
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
4855
- selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconFile, { className: "text-foreground", "aria-hidden": true }) }) : null,
4856
- readOnly ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm leading-5 text-foreground", children: selectedPage?.title ?? value }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4881
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex w-full flex-col gap-2 p-0", children: [
4882
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
4883
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "relative w-full", children: [
4884
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
4885
+ selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconFile, { className: "text-foreground", "aria-hidden": true }) }) : null,
4886
+ readOnly ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm leading-5 text-foreground", children: selectedPage?.title ?? value }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4857
4887
  Input,
4858
4888
  {
4859
4889
  ref: inputRef,
@@ -4872,7 +4902,7 @@ function UrlOrPageInput({
4872
4902
  )
4873
4903
  }
4874
4904
  ),
4875
- selectedPage && !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4905
+ selectedPage && !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4876
4906
  "button",
4877
4907
  {
4878
4908
  type: "button",
@@ -4880,26 +4910,26 @@ function UrlOrPageInput({
4880
4910
  onMouseDown: clearSelection,
4881
4911
  "aria-label": "Clear selected page",
4882
4912
  tabIndex: -1,
4883
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconX, { "aria-hidden": true })
4913
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconX, { "aria-hidden": true })
4884
4914
  }
4885
4915
  ) : null,
4886
- !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(FieldChevron, { onClick: toggleDropdown }) : null
4916
+ !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(FieldChevron, { onClick: toggleDropdown }) : null
4887
4917
  ] }),
4888
- dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4918
+ dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4889
4919
  "div",
4890
4920
  {
4891
4921
  "data-ohw-link-page-dropdown": "",
4892
4922
  className: "absolute left-0 right-0 h-20 top-[calc(100%+4px)] z-10 max-h-48 overflow-auto rounded-lg border border-border bg-popover py-1 shadow-lg",
4893
4923
  onMouseDown: (e) => e.preventDefault(),
4894
- children: filteredPages.map((page) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
4924
+ children: filteredPages.map((page) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
4895
4925
  "button",
4896
4926
  {
4897
4927
  type: "button",
4898
4928
  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",
4899
4929
  onClick: () => onPageSelect(page),
4900
4930
  children: [
4901
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconFile, { className: "shrink-0", "aria-hidden": true }),
4902
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "truncate", children: page.title })
4931
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconFile, { className: "shrink-0", "aria-hidden": true }),
4932
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "truncate", children: page.title })
4903
4933
  ]
4904
4934
  },
4905
4935
  page.path
@@ -4907,7 +4937,7 @@ function UrlOrPageInput({
4907
4937
  }
4908
4938
  ) : null
4909
4939
  ] }),
4910
- urlError ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
4940
+ urlError ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
4911
4941
  ] });
4912
4942
  }
4913
4943
 
@@ -5075,7 +5105,7 @@ function useLinkModalState({
5075
5105
  }
5076
5106
 
5077
5107
  // src/ui/link-modal/LinkEditorPanel.tsx
5078
- var import_jsx_runtime13 = require("react/jsx-runtime");
5108
+ var import_jsx_runtime14 = require("react/jsx-runtime");
5079
5109
  function LinkEditorPanel({
5080
5110
  open = true,
5081
5111
  mode = "create",
@@ -5099,25 +5129,25 @@ function LinkEditorPanel({
5099
5129
  onSubmit
5100
5130
  });
5101
5131
  const isCancel = state.secondaryLabel === "Cancel";
5102
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
5103
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(DialogClose, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5132
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
5133
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DialogClose, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5104
5134
  "button",
5105
5135
  {
5106
5136
  type: "button",
5107
5137
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
5108
5138
  "aria-label": "Close",
5109
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconX, { "aria-hidden": true })
5139
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(IconX, { "aria-hidden": true })
5110
5140
  }
5111
5141
  ) }),
5112
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(DialogHeader, { className: "w-full gap-1.5 p-6 pr-12", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(DialogTitle, { className: "m-0 w-full break-words", children: state.title }) }),
5113
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
5114
- state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5142
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DialogHeader, { className: "w-full gap-1.5 p-6 pr-12", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DialogTitle, { className: "m-0 w-full break-words", children: state.title }) }),
5143
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
5144
+ state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5115
5145
  DestinationBreadcrumb,
5116
5146
  {
5117
5147
  pageTitle: state.selectedPage.title,
5118
5148
  sectionLabel: state.selectedSection.label
5119
5149
  }
5120
- ) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5150
+ ) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5121
5151
  UrlOrPageInput,
5122
5152
  {
5123
5153
  value: state.searchValue,
@@ -5130,18 +5160,18 @@ function LinkEditorPanel({
5130
5160
  urlError: state.urlError
5131
5161
  }
5132
5162
  ),
5133
- state.showChooseSection ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-col justify-center gap-2", children: [
5134
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Button, { type: "button", variant: "outline", className: "w-fit cursor-pointer", size: "sm", onClick: state.handleChooseSection, children: "Choose a section" }),
5135
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
5136
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconInfo, { className: "shrink-0", "aria-hidden": true }),
5137
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: "Pick a section this link should scroll to." })
5163
+ state.showChooseSection ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex flex-col justify-center gap-2", children: [
5164
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Button, { type: "button", variant: "outline", className: "w-fit cursor-pointer", size: "sm", onClick: state.handleChooseSection, children: "Choose a section" }),
5165
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
5166
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(IconInfo, { className: "shrink-0", "aria-hidden": true }),
5167
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: "Pick a section this link should scroll to." })
5138
5168
  ] })
5139
5169
  ] }) : null,
5140
- state.showSectionPicker ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SectionPickerList, { sections: state.activeSections, onSelect: state.handleSectionSelect }) : null,
5141
- state.showSectionRow && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
5170
+ state.showSectionPicker ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(SectionPickerList, { sections: state.activeSections, onSelect: state.handleSectionSelect }) : null,
5171
+ state.showSectionRow && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
5142
5172
  ] }),
5143
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(DialogFooter, { className: "w-full px-6 pb-6", children: [
5144
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5173
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(DialogFooter, { className: "w-full px-6 pb-6", children: [
5174
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5145
5175
  Button,
5146
5176
  {
5147
5177
  type: "button",
@@ -5156,7 +5186,7 @@ function LinkEditorPanel({
5156
5186
  children: state.secondaryLabel
5157
5187
  }
5158
5188
  ),
5159
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5189
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5160
5190
  Button,
5161
5191
  {
5162
5192
  type: "button",
@@ -5175,7 +5205,7 @@ function LinkEditorPanel({
5175
5205
  }
5176
5206
 
5177
5207
  // src/ui/link-modal/LinkPopover.tsx
5178
- var import_jsx_runtime14 = require("react/jsx-runtime");
5208
+ var import_jsx_runtime15 = require("react/jsx-runtime");
5179
5209
  function LinkPopover({
5180
5210
  open = true,
5181
5211
  panelRef,
@@ -5183,14 +5213,14 @@ function LinkPopover({
5183
5213
  onClose,
5184
5214
  ...editorProps
5185
5215
  }) {
5186
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5216
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5187
5217
  Dialog2,
5188
5218
  {
5189
5219
  open,
5190
5220
  onOpenChange: (next) => {
5191
5221
  if (!next) onClose?.();
5192
5222
  },
5193
- children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5223
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5194
5224
  DialogContent,
5195
5225
  {
5196
5226
  ref: panelRef,
@@ -5200,7 +5230,7 @@ function LinkPopover({
5200
5230
  "data-ohw-bridge": "",
5201
5231
  showCloseButton: false,
5202
5232
  className: "gap-0 p-0 w-full md:w-md pointer-events-auto",
5203
- children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(LinkEditorPanel, { ...editorProps, open, onClose })
5233
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(LinkEditorPanel, { ...editorProps, open, onClose })
5204
5234
  }
5205
5235
  )
5206
5236
  }
@@ -5266,7 +5296,7 @@ function shouldUseDevFixtures() {
5266
5296
  }
5267
5297
 
5268
5298
  // src/ui/badge.tsx
5269
- var import_jsx_runtime15 = require("react/jsx-runtime");
5299
+ var import_jsx_runtime16 = require("react/jsx-runtime");
5270
5300
  var badgeVariants = cva(
5271
5301
  "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",
5272
5302
  {
@@ -5284,11 +5314,11 @@ var badgeVariants = cva(
5284
5314
  }
5285
5315
  );
5286
5316
  function Badge({ className, variant, ...props }) {
5287
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
5317
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
5288
5318
  }
5289
5319
 
5290
5320
  // src/OhhwellsBridge.tsx
5291
- var import_jsx_runtime16 = require("react/jsx-runtime");
5321
+ var import_jsx_runtime17 = require("react/jsx-runtime");
5292
5322
  var PRIMARY = "#0885FE";
5293
5323
  var IMAGE_FADE_MS = 300;
5294
5324
  function runOpacityFade(el, onDone) {
@@ -5462,7 +5492,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
5462
5492
  const root = (0, import_client.createRoot)(container);
5463
5493
  (0, import_react_dom.flushSync)(() => {
5464
5494
  root.render(
5465
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5495
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5466
5496
  SchedulingWidget,
5467
5497
  {
5468
5498
  notifyOnConnect,
@@ -5510,6 +5540,20 @@ function applyLinkHref(el, val) {
5510
5540
  const anchor = el instanceof HTMLAnchorElement ? el : el.querySelector("a");
5511
5541
  if (anchor) anchor.setAttribute("href", val);
5512
5542
  }
5543
+ function getEditMeasureEl(editable) {
5544
+ return editable.closest("[data-ohw-href-key]") ?? editable;
5545
+ }
5546
+ function isDragHandleDisabled(el) {
5547
+ const carriers = [
5548
+ el.closest("[data-ohw-href-key]"),
5549
+ el.closest("[data-ohw-editable]")
5550
+ ];
5551
+ return carriers.some((carrier) => {
5552
+ if (!carrier) return false;
5553
+ const raw = carrier.getAttribute("data-ohw-drag-disabled");
5554
+ return raw === "true" || raw === "";
5555
+ });
5556
+ }
5513
5557
  function collectEditableNodes() {
5514
5558
  const nodes = Array.from(document.querySelectorAll("[data-ohw-editable]")).map((el) => {
5515
5559
  if (el.dataset.ohwEditable === "image") {
@@ -5563,6 +5607,14 @@ function getHrefKeyFromElement(el) {
5563
5607
  function isNavbarButton(el) {
5564
5608
  return Boolean(el.closest('[data-ohw-role="navbar-button"]'));
5565
5609
  }
5610
+ function getReorderHandleState(el) {
5611
+ const linkEl = el.closest("[data-ohw-href-key]");
5612
+ if (!linkEl || isNavbarButton(el)) return { key: null, disabled: false };
5613
+ return {
5614
+ key: linkEl.dataset.ohwHrefKey ?? null,
5615
+ disabled: isDragHandleDisabled(el)
5616
+ };
5617
+ }
5566
5618
  function clearHrefKeyHover(anchor) {
5567
5619
  anchor.removeAttribute("data-ohw-hovered");
5568
5620
  anchor.querySelectorAll("[data-ohw-hovered]").forEach((el) => {
@@ -5692,6 +5744,8 @@ var ICONS = {
5692
5744
  insertUnorderedList: '<line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/>',
5693
5745
  insertOrderedList: '<line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"/>'
5694
5746
  };
5747
+ var TOOLBAR_PILL_PADDING = 2;
5748
+ var TOOLBAR_TOGGLE_GAP = 4;
5695
5749
  var TOOLBAR_GROUPS = [
5696
5750
  [
5697
5751
  { cmd: "bold", title: "Bold" },
@@ -5709,24 +5763,64 @@ var TOOLBAR_GROUPS = [
5709
5763
  { cmd: "insertOrderedList", title: "Numbered List" }
5710
5764
  ]
5711
5765
  ];
5712
- function GlowFrame({ rect, elRef }) {
5766
+ function EditGlowChrome({
5767
+ rect,
5768
+ elRef,
5769
+ reorderHrefKey,
5770
+ dragDisabled = false
5771
+ }) {
5713
5772
  const GAP = 6;
5714
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5773
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
5715
5774
  "div",
5716
5775
  {
5717
5776
  ref: elRef,
5777
+ "data-ohw-edit-chrome": "",
5718
5778
  style: {
5719
5779
  position: "fixed",
5720
5780
  top: rect.top - GAP,
5721
5781
  left: rect.left - GAP,
5722
5782
  width: rect.width + GAP * 2,
5723
5783
  height: rect.height + GAP * 2,
5724
- border: "2px solid #0885FE",
5725
- borderRadius: 8,
5726
- boxShadow: "0 0 0 4px rgba(8, 133, 254, 0.12)",
5727
5784
  pointerEvents: "none",
5728
5785
  zIndex: 2147483646
5729
- }
5786
+ },
5787
+ children: [
5788
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5789
+ "div",
5790
+ {
5791
+ style: {
5792
+ position: "absolute",
5793
+ inset: 0,
5794
+ border: "2px solid #0885FE",
5795
+ borderRadius: 8,
5796
+ boxShadow: "0 0 0 4px rgba(8, 133, 254, 0.12)",
5797
+ pointerEvents: "none"
5798
+ }
5799
+ }
5800
+ ),
5801
+ reorderHrefKey && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5802
+ "div",
5803
+ {
5804
+ "data-ohw-drag-handle-container": "",
5805
+ "data-ohw-drag-disabled": dragDisabled ? "" : void 0,
5806
+ style: {
5807
+ position: "absolute",
5808
+ left: 0,
5809
+ top: "50%",
5810
+ transform: "translate(calc(-100% - 7px), -50%)",
5811
+ pointerEvents: dragDisabled ? "none" : "auto"
5812
+ },
5813
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5814
+ DragHandle,
5815
+ {
5816
+ "aria-label": `Reorder ${reorderHrefKey}`,
5817
+ disabled: dragDisabled,
5818
+ "aria-disabled": dragDisabled
5819
+ }
5820
+ )
5821
+ }
5822
+ )
5823
+ ]
5730
5824
  }
5731
5825
  );
5732
5826
  }
@@ -5770,9 +5864,9 @@ function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
5770
5864
  const pinnedTop = Math.min(maxBottom - approxH, Math.max(minTop, clip.top + gap));
5771
5865
  return { top: pinnedTop + approxH, transform: "translateX(-50%) translateY(-100%)" };
5772
5866
  }
5773
- function calcToolbarPos(rect, parentScroll, approxW = 330) {
5867
+ function calcToolbarPos(rect, parentScroll, approxW = 306) {
5774
5868
  const GAP = 8;
5775
- const APPROX_H = 36;
5869
+ const APPROX_H = 32;
5776
5870
  const APPROX_W = approxW;
5777
5871
  const clip = getIframeVisibleClip(parentScroll);
5778
5872
  const clipTop = clip?.top ?? 0;
@@ -5806,9 +5900,9 @@ function calcToolbarPos(rect, parentScroll, approxW = 330) {
5806
5900
  const left = Math.max(GAP + APPROX_W / 2, Math.min(rawLeft, window.innerWidth - GAP - APPROX_W / 2));
5807
5901
  return { top, left, transform };
5808
5902
  }
5809
- var EDIT_LINK_ICON = /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
5810
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
5811
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
5903
+ var EDIT_LINK_ICON = /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
5904
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
5905
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
5812
5906
  ] });
5813
5907
  function FloatingToolbar({
5814
5908
  rect,
@@ -5820,10 +5914,10 @@ function FloatingToolbar({
5820
5914
  showEditLink,
5821
5915
  onEditLink
5822
5916
  }) {
5823
- const approxW = variant === "link-action" ? 120 : 330;
5917
+ const approxW = variant === "link-action" ? 112 : 306;
5824
5918
  const { top, left, transform } = calcToolbarPos(rect, parentScroll, approxW);
5825
5919
  if (variant === "link-action") {
5826
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
5920
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
5827
5921
  "div",
5828
5922
  {
5829
5923
  ref: elRef,
@@ -5840,15 +5934,15 @@ function FloatingToolbar({
5840
5934
  boxShadow: "0px 2px 4px -2px rgba(0,0,0,.1),0px 4px 6px -1px rgba(0,0,0,.1)",
5841
5935
  display: "flex",
5842
5936
  alignItems: "center",
5843
- padding: 4,
5844
- gap: 6,
5937
+ padding: TOOLBAR_PILL_PADDING,
5938
+ gap: TOOLBAR_TOGGLE_GAP,
5845
5939
  fontFamily: "sans-serif",
5846
5940
  pointerEvents: "auto",
5847
5941
  whiteSpace: "nowrap"
5848
5942
  },
5849
5943
  onMouseDown: (e) => e.stopPropagation(),
5850
5944
  children: [
5851
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5945
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5852
5946
  "button",
5853
5947
  {
5854
5948
  type: "button",
@@ -5883,8 +5977,8 @@ function FloatingToolbar({
5883
5977
  children: EDIT_LINK_ICON
5884
5978
  }
5885
5979
  ),
5886
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { style: { display: "block", width: 1, height: 24, background: "#E7E5E4", flexShrink: 0 } }),
5887
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5980
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: { display: "block", width: 1, height: 24, background: "#E7E5E4", flexShrink: 0 } }),
5981
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5888
5982
  "button",
5889
5983
  {
5890
5984
  type: "button",
@@ -5903,10 +5997,10 @@ function FloatingToolbar({
5903
5997
  padding: 6,
5904
5998
  opacity: 0.6
5905
5999
  },
5906
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": true, children: [
5907
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("circle", { cx: "5", cy: "12", r: "1.5" }),
5908
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("circle", { cx: "12", cy: "12", r: "1.5" }),
5909
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("circle", { cx: "19", cy: "12", r: "1.5" })
6000
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": true, children: [
6001
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("circle", { cx: "5", cy: "12", r: "1.5" }),
6002
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("circle", { cx: "12", cy: "12", r: "1.5" }),
6003
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("circle", { cx: "19", cy: "12", r: "1.5" })
5910
6004
  ] })
5911
6005
  }
5912
6006
  )
@@ -5914,7 +6008,7 @@ function FloatingToolbar({
5914
6008
  }
5915
6009
  );
5916
6010
  }
5917
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
6011
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
5918
6012
  "div",
5919
6013
  {
5920
6014
  ref: elRef,
@@ -5931,19 +6025,19 @@ function FloatingToolbar({
5931
6025
  boxShadow: "0px 2px 4px -2px rgba(0,0,0,.1),0px 4px 6px -1px rgba(0,0,0,.1)",
5932
6026
  display: "flex",
5933
6027
  alignItems: "center",
5934
- padding: 4,
5935
- gap: 6,
6028
+ padding: TOOLBAR_PILL_PADDING,
6029
+ gap: TOOLBAR_TOGGLE_GAP,
5936
6030
  fontFamily: "sans-serif",
5937
6031
  pointerEvents: "auto",
5938
6032
  whiteSpace: "nowrap"
5939
6033
  },
5940
6034
  onMouseDown: (e) => e.stopPropagation(),
5941
6035
  children: [
5942
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react6.default.Fragment, { children: [
5943
- gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { style: { display: "block", width: 1, height: 24, background: "#E7E5E4", flexShrink: 0 } }),
6036
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_react6.default.Fragment, { children: [
6037
+ gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: { display: "block", width: 1, height: 24, background: "#E7E5E4", flexShrink: 0 } }),
5944
6038
  btns.map((btn) => {
5945
6039
  const isActive = activeCommands.has(btn.cmd);
5946
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6040
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5947
6041
  "button",
5948
6042
  {
5949
6043
  title: btn.title,
@@ -5969,7 +6063,7 @@ function FloatingToolbar({
5969
6063
  flexShrink: 0,
5970
6064
  padding: 6
5971
6065
  },
5972
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6066
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5973
6067
  "svg",
5974
6068
  {
5975
6069
  width: "16",
@@ -5989,7 +6083,7 @@ function FloatingToolbar({
5989
6083
  );
5990
6084
  })
5991
6085
  ] }, gi)),
5992
- showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6086
+ showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5993
6087
  "button",
5994
6088
  {
5995
6089
  type: "button",
@@ -6038,7 +6132,7 @@ function StateToggle({
6038
6132
  states,
6039
6133
  onStateChange
6040
6134
  }) {
6041
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6135
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
6042
6136
  ToggleGroup,
6043
6137
  {
6044
6138
  "data-ohw-state-toggle": "",
@@ -6052,7 +6146,7 @@ function StateToggle({
6052
6146
  left: rect.right - 8,
6053
6147
  transform: "translateX(-100%)"
6054
6148
  },
6055
- children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
6149
+ children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
6056
6150
  }
6057
6151
  );
6058
6152
  }
@@ -6150,6 +6244,8 @@ function OhhwellsBridge() {
6150
6244
  const [toolbarVariant, setToolbarVariant] = (0, import_react6.useState)("none");
6151
6245
  const toolbarVariantRef = (0, import_react6.useRef)("none");
6152
6246
  toolbarVariantRef.current = toolbarVariant;
6247
+ const [reorderHrefKey, setReorderHrefKey] = (0, import_react6.useState)(null);
6248
+ const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react6.useState)(false);
6153
6249
  const [toggleState, setToggleState] = (0, import_react6.useState)(null);
6154
6250
  const [maxBadge, setMaxBadge] = (0, import_react6.useState)(null);
6155
6251
  const [activeCommands, setActiveCommands] = (0, import_react6.useState)(/* @__PURE__ */ new Set());
@@ -6256,7 +6352,7 @@ function OhhwellsBridge() {
6256
6352
  (0, import_react6.useEffect)(() => {
6257
6353
  const update = () => {
6258
6354
  const el = activeElRef.current ?? selectedElRef.current;
6259
- if (el) setToolbarRect(el.getBoundingClientRect());
6355
+ if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
6260
6356
  setToggleState((prev) => {
6261
6357
  if (!prev || !activeStateElRef.current) return prev;
6262
6358
  return { ...prev, rect: activeStateElRef.current.getBoundingClientRect() };
@@ -6323,6 +6419,8 @@ function OhhwellsBridge() {
6323
6419
  }
6324
6420
  el.removeAttribute("contenteditable");
6325
6421
  activeElRef.current = null;
6422
+ setReorderHrefKey(null);
6423
+ setReorderDragDisabled(false);
6326
6424
  if (!selectedElRef.current) {
6327
6425
  setToolbarRect(null);
6328
6426
  setToolbarVariant("none");
@@ -6360,11 +6458,15 @@ function OhhwellsBridge() {
6360
6458
  setToolbarVariant("rich-text");
6361
6459
  el.setAttribute("contenteditable", "true");
6362
6460
  el.removeAttribute("data-ohw-hovered");
6461
+ el.closest("[data-ohw-href-key]")?.removeAttribute("data-ohw-hovered");
6363
6462
  activeElRef.current = el;
6364
6463
  originalContentRef.current = el.innerHTML;
6365
6464
  el.focus();
6366
- setToolbarRect(el.getBoundingClientRect());
6367
6465
  setToolbarShowEditLink(Boolean(getHrefKeyFromElement(el)));
6466
+ const { key: reorderKey, disabled: reorderDisabled } = getReorderHandleState(el);
6467
+ setReorderHrefKey(reorderKey);
6468
+ setReorderDragDisabled(reorderDisabled);
6469
+ setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
6368
6470
  postToParent({ type: "ow:enter-edit", key: el.dataset.ohwKey });
6369
6471
  requestAnimationFrame(() => refreshActiveCommandsRef.current());
6370
6472
  }, [deactivate, postToParent]);
@@ -6429,30 +6531,36 @@ function OhhwellsBridge() {
6429
6531
  return () => {
6430
6532
  cancelled = true;
6431
6533
  };
6432
- }, [subdomain, isEditMode, pathname]);
6534
+ }, [subdomain, isEditMode]);
6433
6535
  (0, import_react6.useEffect)(() => {
6434
6536
  if (!subdomain || isEditMode) return;
6435
6537
  let debounceTimer = null;
6538
+ let observer = null;
6436
6539
  const applyFromCache = () => {
6437
6540
  const content = contentCache.get(subdomain);
6438
6541
  if (!content) return;
6439
6542
  retryMissingSchedulingMounts(getPageSchedulingEntries(content["__ohw_sections"]), false);
6440
- for (const [key, val] of Object.entries(content)) {
6441
- if (key === "__ohw_sections") continue;
6442
- document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
6443
- if (el.dataset.ohwEditable === "image") {
6444
- const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
6445
- if (img && img.src !== val) img.src = val;
6446
- } else if (el.dataset.ohwEditable === "bg-image") {
6447
- const next = `url('${val}')`;
6448
- if (el.style.backgroundImage !== next) el.style.backgroundImage = next;
6449
- } else if (el.dataset.ohwEditable === "link") {
6450
- applyLinkHref(el, val);
6451
- } else if (el.innerHTML !== val) {
6452
- el.innerHTML = val;
6453
- }
6454
- });
6455
- applyLinkByKey(key, val);
6543
+ observer?.disconnect();
6544
+ try {
6545
+ for (const [key, val] of Object.entries(content)) {
6546
+ if (key === "__ohw_sections") continue;
6547
+ document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
6548
+ if (el.dataset.ohwEditable === "image") {
6549
+ const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
6550
+ if (img && img.src !== val) img.src = val;
6551
+ } else if (el.dataset.ohwEditable === "bg-image") {
6552
+ const next = `url('${val}')`;
6553
+ if (el.style.backgroundImage !== next) el.style.backgroundImage = next;
6554
+ } else if (el.dataset.ohwEditable === "link") {
6555
+ applyLinkHref(el, val);
6556
+ } else if (el.innerHTML !== val) {
6557
+ el.innerHTML = val;
6558
+ }
6559
+ });
6560
+ applyLinkByKey(key, val);
6561
+ }
6562
+ } finally {
6563
+ observer?.observe(document.body, { childList: true, subtree: true });
6456
6564
  }
6457
6565
  enforceLinkHrefs();
6458
6566
  };
@@ -6460,11 +6568,11 @@ function OhhwellsBridge() {
6460
6568
  if (debounceTimer) clearTimeout(debounceTimer);
6461
6569
  debounceTimer = setTimeout(applyFromCache, 150);
6462
6570
  };
6463
- scheduleApply();
6464
- const observer = new MutationObserver(scheduleApply);
6571
+ applyFromCache();
6572
+ observer = new MutationObserver(scheduleApply);
6465
6573
  observer.observe(document.body, { childList: true, subtree: true });
6466
6574
  return () => {
6467
- observer.disconnect();
6575
+ observer?.disconnect();
6468
6576
  if (debounceTimer) clearTimeout(debounceTimer);
6469
6577
  };
6470
6578
  }, [subdomain, isEditMode, pathname]);
@@ -6588,6 +6696,11 @@ function OhhwellsBridge() {
6588
6696
  if (target.closest("[data-ohw-state-toggle]")) return;
6589
6697
  if (target.closest("[data-ohw-max-badge]")) return;
6590
6698
  if (isInsideLinkEditor(target)) return;
6699
+ if (target.closest('[data-ohw-edit-chrome], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
6700
+ e.preventDefault();
6701
+ e.stopPropagation();
6702
+ return;
6703
+ }
6591
6704
  const editable = target.closest("[data-ohw-editable]");
6592
6705
  if (editable) {
6593
6706
  if (editable.dataset.ohwEditable === "link") {
@@ -6664,14 +6777,18 @@ function OhhwellsBridge() {
6664
6777
  const selected = selectedElRef.current;
6665
6778
  if (selected && (selected === editable || selected.contains(editable))) return;
6666
6779
  if (editable.dataset.ohwEditable !== "image" && editable.dataset.ohwEditable !== "bg-image" && !editable.hasAttribute("contenteditable")) {
6667
- editable.setAttribute("data-ohw-hovered", "");
6780
+ const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
6781
+ hoverTarget.setAttribute("data-ohw-hovered", "");
6668
6782
  }
6669
6783
  };
6670
6784
  const handleMouseOut = (e) => {
6671
6785
  const editable = e.target.closest("[data-ohw-editable]");
6672
6786
  if (!editable) return;
6787
+ const related = e.relatedTarget instanceof Element ? e.relatedTarget : null;
6788
+ if (related?.closest("[data-ohw-drag-handle-container]")) return;
6673
6789
  if (editable.dataset.ohwEditable !== "image" && editable.dataset.ohwEditable !== "bg-image") {
6674
- editable.removeAttribute("data-ohw-hovered");
6790
+ const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
6791
+ hoverTarget.removeAttribute("data-ohw-hovered");
6675
6792
  }
6676
6793
  };
6677
6794
  const toProbeCoords = (clientX, clientY, fromParentViewport) => {
@@ -6786,11 +6903,20 @@ function OhhwellsBridge() {
6786
6903
  return;
6787
6904
  }
6788
6905
  }
6906
+ if (activeElRef.current) {
6907
+ if (hoveredImageRef.current) {
6908
+ hoveredImageRef.current = null;
6909
+ hoveredImageHasTextOverlapRef.current = false;
6910
+ resumeAnimTracks();
6911
+ postToParentRef.current({ type: "ow:image-unhover" });
6912
+ }
6913
+ return;
6914
+ }
6789
6915
  const imgEl = findImageAtPoint(clientX, clientY, fromParentViewport);
6790
6916
  if (imgEl) {
6791
6917
  const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
6792
6918
  const topEl = document.elementFromPoint(x, y);
6793
- if (topEl?.closest("[data-ohw-toolbar]")) {
6919
+ if (topEl?.closest('[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
6794
6920
  if (hoveredImageRef.current) {
6795
6921
  hoveredImageRef.current = null;
6796
6922
  resumeAnimTracks();
@@ -7083,7 +7209,7 @@ function OhhwellsBridge() {
7083
7209
  const el = e.target;
7084
7210
  const key = el.dataset.ohwKey;
7085
7211
  if (!key) return;
7086
- if (el === activeElRef.current) setToolbarRect(el.getBoundingClientRect());
7212
+ if (el === activeElRef.current) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
7087
7213
  const maxLen = el.dataset.ohwMaxLength ? parseInt(el.dataset.ohwMaxLength, 10) : null;
7088
7214
  if (maxLen) {
7089
7215
  const current = el.innerText.replace(/\n$/, "").length;
@@ -7313,7 +7439,7 @@ function OhhwellsBridge() {
7313
7439
  };
7314
7440
  const applyToolbarPos = (rect) => {
7315
7441
  const ps = parentScrollRef.current;
7316
- const approxW = toolbarVariantRef.current === "link-action" ? 120 : 330;
7442
+ const approxW = toolbarVariantRef.current === "link-action" ? 112 : 306;
7317
7443
  if (toolbarElRef.current) {
7318
7444
  const { top, left, transform } = calcToolbarPos(rect, ps, approxW);
7319
7445
  toolbarElRef.current.style.top = `${top}px`;
@@ -7492,7 +7618,7 @@ function OhhwellsBridge() {
7492
7618
  const handleCommand = (0, import_react6.useCallback)((cmd) => {
7493
7619
  document.execCommand(cmd, false);
7494
7620
  activeElRef.current?.focus();
7495
- if (activeElRef.current) setToolbarRect(activeElRef.current.getBoundingClientRect());
7621
+ if (activeElRef.current) setToolbarRect(getEditMeasureEl(activeElRef.current).getBoundingClientRect());
7496
7622
  refreshActiveCommandsRef.current();
7497
7623
  }, []);
7498
7624
  const handleStateChange = (0, import_react6.useCallback)((state) => {
@@ -7545,11 +7671,19 @@ function OhhwellsBridge() {
7545
7671
  const currentSections = sectionsByPath[pathname] ?? [];
7546
7672
  linkPopoverOpenRef.current = linkPopover !== null;
7547
7673
  return bridgeRoot ? (0, import_react_dom2.createPortal)(
7548
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
7549
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
7550
- toolbarRect && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
7551
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(GlowFrame, { rect: toolbarRect, elRef: glowElRef }),
7552
- toolbarVariant === "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
7674
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
7675
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
7676
+ toolbarRect && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
7677
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
7678
+ EditGlowChrome,
7679
+ {
7680
+ rect: toolbarRect,
7681
+ elRef: glowElRef,
7682
+ reorderHrefKey,
7683
+ dragDisabled: reorderDragDisabled
7684
+ }
7685
+ ),
7686
+ toolbarVariant === "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
7553
7687
  FloatingToolbar,
7554
7688
  {
7555
7689
  variant: "rich-text",
@@ -7562,7 +7696,7 @@ function OhhwellsBridge() {
7562
7696
  onEditLink: openLinkPopoverForActive
7563
7697
  }
7564
7698
  ),
7565
- toolbarVariant === "link-action" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
7699
+ toolbarVariant === "link-action" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
7566
7700
  FloatingToolbar,
7567
7701
  {
7568
7702
  variant: "link-action",
@@ -7575,7 +7709,7 @@ function OhhwellsBridge() {
7575
7709
  }
7576
7710
  )
7577
7711
  ] }),
7578
- maxBadge && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
7712
+ maxBadge && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
7579
7713
  "div",
7580
7714
  {
7581
7715
  "data-ohw-max-badge": "",
@@ -7601,7 +7735,7 @@ function OhhwellsBridge() {
7601
7735
  ]
7602
7736
  }
7603
7737
  ),
7604
- toggleState && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
7738
+ toggleState && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
7605
7739
  StateToggle,
7606
7740
  {
7607
7741
  rect: toggleState.rect,
@@ -7610,15 +7744,15 @@ function OhhwellsBridge() {
7610
7744
  onStateChange: handleStateChange
7611
7745
  }
7612
7746
  ),
7613
- sectionGap && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
7747
+ sectionGap && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
7614
7748
  "div",
7615
7749
  {
7616
7750
  "data-ohw-section-insert-line": "",
7617
7751
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
7618
7752
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
7619
7753
  children: [
7620
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
7621
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
7754
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
7755
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
7622
7756
  Badge,
7623
7757
  {
7624
7758
  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",
@@ -7631,11 +7765,11 @@ function OhhwellsBridge() {
7631
7765
  children: "Add Section"
7632
7766
  }
7633
7767
  ),
7634
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
7768
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
7635
7769
  ]
7636
7770
  }
7637
7771
  ),
7638
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
7772
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
7639
7773
  LinkPopover,
7640
7774
  {
7641
7775
  panelRef: linkPopoverPanelRef,
@@ -7650,13 +7784,39 @@ function OhhwellsBridge() {
7650
7784
  onSubmit: handleLinkPopoverSubmit
7651
7785
  },
7652
7786
  `${linkPopover.key}-${pathname}`
7653
- ) : null
7787
+ ) : null,
7788
+ sectionGap && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
7789
+ "div",
7790
+ {
7791
+ "data-ohw-section-insert-line": "",
7792
+ className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
7793
+ style: { top: sectionGap.y, transform: "translateY(-50%)" },
7794
+ children: [
7795
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
7796
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
7797
+ Badge,
7798
+ {
7799
+ 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",
7800
+ onClick: () => {
7801
+ window.parent.postMessage(
7802
+ { type: "ow:add-section", insertAfter: sectionGap.insertAfter, insertBefore: sectionGap.insertBefore },
7803
+ "*"
7804
+ );
7805
+ },
7806
+ children: "Add Section"
7807
+ }
7808
+ ),
7809
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
7810
+ ]
7811
+ }
7812
+ )
7654
7813
  ] }),
7655
7814
  bridgeRoot
7656
7815
  ) : null;
7657
7816
  }
7658
7817
  // Annotate the CommonJS export names for ESM import in node:
7659
7818
  0 && (module.exports = {
7819
+ DragHandle,
7660
7820
  LinkEditorPanel,
7661
7821
  LinkPopover,
7662
7822
  OhhwellsBridge,
@@ -7667,6 +7827,7 @@ function OhhwellsBridge() {
7667
7827
  buildTarget,
7668
7828
  filterAvailablePages,
7669
7829
  getEditModeInitialState,
7830
+ isEditSessionActive,
7670
7831
  isValidUrl,
7671
7832
  parseTarget,
7672
7833
  toggleVariants,