@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.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  // src/OhhwellsBridge.tsx
4
- import React6, { useCallback as useCallback2, useEffect as useEffect3, useLayoutEffect as useLayoutEffect2, useRef as useRef3, useState as useState5 } from "react";
4
+ import React7, { useCallback as useCallback2, useEffect as useEffect3, useLayoutEffect as useLayoutEffect2, useRef as useRef3, useState as useState5 } from "react";
5
5
  import { createRoot } from "react-dom/client";
6
6
  import { flushSync } from "react-dom";
7
7
 
@@ -4202,6 +4202,34 @@ function ToggleGroupItem({
4202
4202
  );
4203
4203
  }
4204
4204
 
4205
+ // src/ui/drag-handle.tsx
4206
+ import * as React3 from "react";
4207
+ import { GripVertical } from "lucide-react";
4208
+ import { jsx as jsx5 } from "react/jsx-runtime";
4209
+ var DragHandle = React3.forwardRef(
4210
+ ({ className, type = "button", ...props }, ref) => {
4211
+ return /* @__PURE__ */ jsx5(
4212
+ "button",
4213
+ {
4214
+ ref,
4215
+ type,
4216
+ "data-slot": "drag-handle",
4217
+ className: cn(
4218
+ "inline-flex h-7 w-4 shrink-0 items-center justify-center rounded-md transition-all duration-200 max-h-[30px]",
4219
+ "bg-white border border-transparent text-stone-500 shadow-md cursor-grab",
4220
+ "enabled:hover:border enabled:hover:border-stone-200 enabled:hover:text-stone-950",
4221
+ "enabled:active:border enabled:active:border-primary enabled:active:bg-primary-50 enabled:active:text-stone-950 enabled:active:shadow enabled:active:cursor-grabbing",
4222
+ "disabled:cursor-not-allowed disabled:opacity-40 disabled:text-stone-950 disabled:pointer-events-none",
4223
+ className
4224
+ ),
4225
+ ...props,
4226
+ children: /* @__PURE__ */ jsx5(GripVertical, { className: "size-4 shrink-0", "aria-hidden": "true" })
4227
+ }
4228
+ );
4229
+ }
4230
+ );
4231
+ DragHandle.displayName = "DragHandle";
4232
+
4205
4233
  // src/OhhwellsBridge.tsx
4206
4234
  import { createPortal } from "react-dom";
4207
4235
  import { usePathname, useRouter, useSearchParams } from "next/navigation";
@@ -4481,60 +4509,60 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
4481
4509
  }
4482
4510
 
4483
4511
  // src/ui/dialog.tsx
4484
- import * as React3 from "react";
4512
+ import * as React4 from "react";
4485
4513
  import { Dialog as DialogPrimitive } from "radix-ui";
4486
4514
 
4487
4515
  // src/ui/icons.tsx
4488
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
4516
+ import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
4489
4517
  function IconX({ className, ...props }) {
4490
4518
  return /* @__PURE__ */ jsxs3("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4491
- /* @__PURE__ */ jsx5("path", { d: "M18 6 6 18" }),
4492
- /* @__PURE__ */ jsx5("path", { d: "m6 6 12 12" })
4519
+ /* @__PURE__ */ jsx6("path", { d: "M18 6 6 18" }),
4520
+ /* @__PURE__ */ jsx6("path", { d: "m6 6 12 12" })
4493
4521
  ] });
4494
4522
  }
4495
4523
  function IconChevronDown({ className, ...props }) {
4496
- return /* @__PURE__ */ jsx5("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: /* @__PURE__ */ jsx5("path", { d: "m6 9 6 6 6-6" }) });
4524
+ return /* @__PURE__ */ jsx6("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: /* @__PURE__ */ jsx6("path", { d: "m6 9 6 6 6-6" }) });
4497
4525
  }
4498
4526
  function IconFile({ className, ...props }) {
4499
4527
  return /* @__PURE__ */ jsxs3("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4500
- /* @__PURE__ */ jsx5("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }),
4501
- /* @__PURE__ */ jsx5("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" })
4528
+ /* @__PURE__ */ jsx6("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }),
4529
+ /* @__PURE__ */ jsx6("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" })
4502
4530
  ] });
4503
4531
  }
4504
4532
  function IconInfo({ className, ...props }) {
4505
4533
  return /* @__PURE__ */ jsxs3("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4506
- /* @__PURE__ */ jsx5("circle", { cx: "12", cy: "12", r: "10" }),
4507
- /* @__PURE__ */ jsx5("path", { d: "M12 16v-4" }),
4508
- /* @__PURE__ */ jsx5("path", { d: "M12 8h.01" })
4534
+ /* @__PURE__ */ jsx6("circle", { cx: "12", cy: "12", r: "10" }),
4535
+ /* @__PURE__ */ jsx6("path", { d: "M12 16v-4" }),
4536
+ /* @__PURE__ */ jsx6("path", { d: "M12 8h.01" })
4509
4537
  ] });
4510
4538
  }
4511
4539
  function IconArrowRight({ className, ...props }) {
4512
4540
  return /* @__PURE__ */ jsxs3("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4513
- /* @__PURE__ */ jsx5("path", { d: "M5 12h14" }),
4514
- /* @__PURE__ */ jsx5("path", { d: "m12 5 7 7-7 7" })
4541
+ /* @__PURE__ */ jsx6("path", { d: "M5 12h14" }),
4542
+ /* @__PURE__ */ jsx6("path", { d: "m12 5 7 7-7 7" })
4515
4543
  ] });
4516
4544
  }
4517
4545
  function IconSection({ className, ...props }) {
4518
4546
  return /* @__PURE__ */ jsxs3("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4519
- /* @__PURE__ */ jsx5("rect", { width: "18", height: "7", x: "3", y: "3", rx: "1" }),
4520
- /* @__PURE__ */ jsx5("rect", { width: "9", height: "7", x: "3", y: "14", rx: "1" }),
4521
- /* @__PURE__ */ jsx5("rect", { width: "5", height: "7", x: "16", y: "14", rx: "1" })
4547
+ /* @__PURE__ */ jsx6("rect", { width: "18", height: "7", x: "3", y: "3", rx: "1" }),
4548
+ /* @__PURE__ */ jsx6("rect", { width: "9", height: "7", x: "3", y: "14", rx: "1" }),
4549
+ /* @__PURE__ */ jsx6("rect", { width: "5", height: "7", x: "16", y: "14", rx: "1" })
4522
4550
  ] });
4523
4551
  }
4524
4552
 
4525
4553
  // src/ui/dialog.tsx
4526
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
4554
+ import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
4527
4555
  function Dialog2({ ...props }) {
4528
- return /* @__PURE__ */ jsx6(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
4556
+ return /* @__PURE__ */ jsx7(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
4529
4557
  }
4530
4558
  function DialogPortal({ ...props }) {
4531
- return /* @__PURE__ */ jsx6(DialogPrimitive.Portal, { ...props });
4559
+ return /* @__PURE__ */ jsx7(DialogPrimitive.Portal, { ...props });
4532
4560
  }
4533
4561
  function DialogOverlay({
4534
4562
  className,
4535
4563
  ...props
4536
4564
  }) {
4537
- return /* @__PURE__ */ jsx6(
4565
+ return /* @__PURE__ */ jsx7(
4538
4566
  DialogPrimitive.Overlay,
4539
4567
  {
4540
4568
  "data-slot": "dialog-overlay",
@@ -4544,10 +4572,10 @@ function DialogOverlay({
4544
4572
  }
4545
4573
  );
4546
4574
  }
4547
- var DialogContent = React3.forwardRef(({ className, children, showCloseButton = true, container, ...props }, ref) => {
4575
+ var DialogContent = React4.forwardRef(({ className, children, showCloseButton = true, container, ...props }, ref) => {
4548
4576
  const positionMode = container ? "absolute" : "fixed";
4549
4577
  return /* @__PURE__ */ jsxs4(DialogPortal, { container: container ?? void 0, children: [
4550
- /* @__PURE__ */ jsx6(DialogOverlay, { className: cn(positionMode, "inset-0") }),
4578
+ /* @__PURE__ */ jsx7(DialogOverlay, { className: cn(positionMode, "inset-0") }),
4551
4579
  /* @__PURE__ */ jsxs4(
4552
4580
  DialogPrimitive.Content,
4553
4581
  {
@@ -4564,13 +4592,13 @@ var DialogContent = React3.forwardRef(({ className, children, showCloseButton =
4564
4592
  ...props,
4565
4593
  children: [
4566
4594
  children,
4567
- showCloseButton ? /* @__PURE__ */ jsx6(
4595
+ showCloseButton ? /* @__PURE__ */ jsx7(
4568
4596
  DialogPrimitive.Close,
4569
4597
  {
4570
4598
  type: "button",
4571
4599
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
4572
4600
  "aria-label": "Close",
4573
- children: /* @__PURE__ */ jsx6(IconX, { "aria-hidden": true })
4601
+ children: /* @__PURE__ */ jsx7(IconX, { "aria-hidden": true })
4574
4602
  }
4575
4603
  ) : null
4576
4604
  ]
@@ -4580,12 +4608,12 @@ var DialogContent = React3.forwardRef(({ className, children, showCloseButton =
4580
4608
  });
4581
4609
  DialogContent.displayName = DialogPrimitive.Content.displayName;
4582
4610
  function DialogHeader({ className, ...props }) {
4583
- return /* @__PURE__ */ jsx6("div", { className: cn("flex flex-col gap-1.5", className), ...props });
4611
+ return /* @__PURE__ */ jsx7("div", { className: cn("flex flex-col gap-1.5", className), ...props });
4584
4612
  }
4585
4613
  function DialogFooter({ className, ...props }) {
4586
- return /* @__PURE__ */ jsx6("div", { className: cn("flex items-center justify-end gap-2", className), ...props });
4614
+ return /* @__PURE__ */ jsx7("div", { className: cn("flex items-center justify-end gap-2", className), ...props });
4587
4615
  }
4588
- var DialogTitle = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx6(
4616
+ var DialogTitle = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx7(
4589
4617
  DialogPrimitive.Title,
4590
4618
  {
4591
4619
  ref,
@@ -4594,7 +4622,7 @@ var DialogTitle = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE
4594
4622
  }
4595
4623
  ));
4596
4624
  DialogTitle.displayName = DialogPrimitive.Title.displayName;
4597
- var DialogDescription = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx6(
4625
+ var DialogDescription = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx7(
4598
4626
  DialogPrimitive.Description,
4599
4627
  {
4600
4628
  ref,
@@ -4606,9 +4634,9 @@ DialogDescription.displayName = DialogPrimitive.Description.displayName;
4606
4634
  var DialogClose = DialogPrimitive.Close;
4607
4635
 
4608
4636
  // src/ui/button.tsx
4609
- import * as React4 from "react";
4637
+ import * as React5 from "react";
4610
4638
  import { Slot } from "radix-ui";
4611
- import { jsx as jsx7 } from "react/jsx-runtime";
4639
+ import { jsx as jsx8 } from "react/jsx-runtime";
4612
4640
  var buttonVariants = cva(
4613
4641
  "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",
4614
4642
  {
@@ -4629,10 +4657,10 @@ var buttonVariants = cva(
4629
4657
  }
4630
4658
  }
4631
4659
  );
4632
- var Button = React4.forwardRef(
4660
+ var Button = React5.forwardRef(
4633
4661
  ({ className, variant, size, asChild = false, ...props }, ref) => {
4634
4662
  const Comp = asChild ? Slot.Root : "button";
4635
- return /* @__PURE__ */ jsx7(
4663
+ return /* @__PURE__ */ jsx8(
4636
4664
  Comp,
4637
4665
  {
4638
4666
  ref,
@@ -4646,30 +4674,30 @@ var Button = React4.forwardRef(
4646
4674
  Button.displayName = "Button";
4647
4675
 
4648
4676
  // src/ui/link-modal/DestinationBreadcrumb.tsx
4649
- import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
4677
+ import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
4650
4678
  function DestinationBreadcrumb({ pageTitle, sectionLabel }) {
4651
4679
  return /* @__PURE__ */ jsxs5("div", { className: "flex w-full flex-col gap-2", children: [
4652
- /* @__PURE__ */ jsx8("p", { className: "text-sm font-medium text-foreground", children: "Destination" }),
4680
+ /* @__PURE__ */ jsx9("p", { className: "text-sm font-medium text-foreground", children: "Destination" }),
4653
4681
  /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-3", children: [
4654
4682
  /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
4655
- /* @__PURE__ */ jsx8(IconFile, { className: "shrink-0 text-foreground", "aria-hidden": true }),
4656
- /* @__PURE__ */ jsx8("span", { className: "text-sm font-medium leading-none text-foreground", children: pageTitle })
4683
+ /* @__PURE__ */ jsx9(IconFile, { className: "shrink-0 text-foreground", "aria-hidden": true }),
4684
+ /* @__PURE__ */ jsx9("span", { className: "text-sm font-medium leading-none text-foreground", children: pageTitle })
4657
4685
  ] }),
4658
- /* @__PURE__ */ jsx8(IconArrowRight, { className: "shrink-0 text-muted-foreground", "aria-hidden": true }),
4686
+ /* @__PURE__ */ jsx9(IconArrowRight, { className: "shrink-0 text-muted-foreground", "aria-hidden": true }),
4659
4687
  /* @__PURE__ */ jsxs5("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
4660
- /* @__PURE__ */ jsx8(IconSection, { className: "shrink-0 text-foreground", "aria-hidden": true }),
4661
- /* @__PURE__ */ jsx8("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
4688
+ /* @__PURE__ */ jsx9(IconSection, { className: "shrink-0 text-foreground", "aria-hidden": true }),
4689
+ /* @__PURE__ */ jsx9("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
4662
4690
  ] })
4663
4691
  ] })
4664
4692
  ] });
4665
4693
  }
4666
4694
 
4667
4695
  // src/ui/link-modal/SectionTreeItem.tsx
4668
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
4696
+ import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
4669
4697
  function SectionTreeItem({ section, onSelect, selected }) {
4670
4698
  const interactive = Boolean(onSelect);
4671
4699
  return /* @__PURE__ */ jsxs6("div", { className: "flex h-9 w-full items-end pl-3", children: [
4672
- /* @__PURE__ */ jsx9(
4700
+ /* @__PURE__ */ jsx10(
4673
4701
  "div",
4674
4702
  {
4675
4703
  className: "mr-[-1px] h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
@@ -4694,8 +4722,8 @@ function SectionTreeItem({ section, onSelect, selected }) {
4694
4722
  interactive && selected && "border-primary"
4695
4723
  ),
4696
4724
  children: [
4697
- /* @__PURE__ */ jsx9(IconSection, { className: "shrink-0 text-foreground", "aria-hidden": true }),
4698
- /* @__PURE__ */ jsx9("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
4725
+ /* @__PURE__ */ jsx10(IconSection, { className: "shrink-0 text-foreground", "aria-hidden": true }),
4726
+ /* @__PURE__ */ jsx10("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
4699
4727
  ]
4700
4728
  }
4701
4729
  )
@@ -4703,11 +4731,11 @@ function SectionTreeItem({ section, onSelect, selected }) {
4703
4731
  }
4704
4732
  function SectionPickerList({ sections, onSelect }) {
4705
4733
  if (sections.length === 0) {
4706
- return /* @__PURE__ */ jsx9("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." });
4734
+ return /* @__PURE__ */ jsx10("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." });
4707
4735
  }
4708
4736
  return /* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-1", children: [
4709
- /* @__PURE__ */ jsx9("p", { className: "text-sm text-muted-foreground", children: "Pick a section this link should scroll to." }),
4710
- sections.map((section) => /* @__PURE__ */ jsx9(SectionTreeItem, { section, onSelect }, section.id))
4737
+ /* @__PURE__ */ jsx10("p", { className: "text-sm text-muted-foreground", children: "Pick a section this link should scroll to." }),
4738
+ sections.map((section) => /* @__PURE__ */ jsx10(SectionTreeItem, { section, onSelect }, section.id))
4711
4739
  ] });
4712
4740
  }
4713
4741
 
@@ -4715,11 +4743,11 @@ function SectionPickerList({ sections, onSelect }) {
4715
4743
  import { useId as useId2, useRef as useRef2, useState as useState3 } from "react";
4716
4744
 
4717
4745
  // src/ui/input.tsx
4718
- import * as React5 from "react";
4719
- import { jsx as jsx10 } from "react/jsx-runtime";
4720
- var Input = React5.forwardRef(
4746
+ import * as React6 from "react";
4747
+ import { jsx as jsx11 } from "react/jsx-runtime";
4748
+ var Input = React6.forwardRef(
4721
4749
  ({ className, type, ...props }, ref) => {
4722
- return /* @__PURE__ */ jsx10(
4750
+ return /* @__PURE__ */ jsx11(
4723
4751
  "input",
4724
4752
  {
4725
4753
  type,
@@ -4738,9 +4766,9 @@ Input.displayName = "Input";
4738
4766
 
4739
4767
  // src/ui/label.tsx
4740
4768
  import { Label as LabelPrimitive } from "radix-ui";
4741
- import { jsx as jsx11 } from "react/jsx-runtime";
4769
+ import { jsx as jsx12 } from "react/jsx-runtime";
4742
4770
  function Label({ className, ...props }) {
4743
- return /* @__PURE__ */ jsx11(
4771
+ return /* @__PURE__ */ jsx12(
4744
4772
  LabelPrimitive.Root,
4745
4773
  {
4746
4774
  "data-slot": "label",
@@ -4751,9 +4779,9 @@ function Label({ className, ...props }) {
4751
4779
  }
4752
4780
 
4753
4781
  // src/ui/link-modal/UrlOrPageInput.tsx
4754
- import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
4782
+ import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
4755
4783
  function FieldChevron({ onClick }) {
4756
- return /* @__PURE__ */ jsx12(
4784
+ return /* @__PURE__ */ jsx13(
4757
4785
  "button",
4758
4786
  {
4759
4787
  type: "button",
@@ -4761,7 +4789,7 @@ function FieldChevron({ onClick }) {
4761
4789
  onClick,
4762
4790
  "aria-label": "Open page list",
4763
4791
  tabIndex: -1,
4764
- children: /* @__PURE__ */ jsx12(IconChevronDown, {})
4792
+ children: /* @__PURE__ */ jsx13(IconChevronDown, {})
4765
4793
  }
4766
4794
  );
4767
4795
  }
@@ -4801,11 +4829,11 @@ function UrlOrPageInput({
4801
4829
  urlError ? "border-destructive shadow-[0_0_0_1px_var(--ohw-destructive)]" : isFocused ? "border-primary shadow-[0_0_0_1px_var(--ohw-primary)]" : "border-input"
4802
4830
  );
4803
4831
  return /* @__PURE__ */ jsxs7("div", { className: "flex w-full flex-col gap-2 p-0", children: [
4804
- /* @__PURE__ */ jsx12(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
4832
+ /* @__PURE__ */ jsx13(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
4805
4833
  /* @__PURE__ */ jsxs7("div", { className: "relative w-full", children: [
4806
4834
  /* @__PURE__ */ jsxs7("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
4807
- selectedPage ? /* @__PURE__ */ jsx12("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ jsx12(IconFile, { className: "text-foreground", "aria-hidden": true }) }) : null,
4808
- readOnly ? /* @__PURE__ */ jsx12("span", { className: "min-w-0 flex-1 truncate text-sm leading-5 text-foreground", children: selectedPage?.title ?? value }) : /* @__PURE__ */ jsx12(
4835
+ selectedPage ? /* @__PURE__ */ jsx13("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ jsx13(IconFile, { className: "text-foreground", "aria-hidden": true }) }) : null,
4836
+ readOnly ? /* @__PURE__ */ jsx13("span", { className: "min-w-0 flex-1 truncate text-sm leading-5 text-foreground", children: selectedPage?.title ?? value }) : /* @__PURE__ */ jsx13(
4809
4837
  Input,
4810
4838
  {
4811
4839
  ref: inputRef,
@@ -4824,7 +4852,7 @@ function UrlOrPageInput({
4824
4852
  )
4825
4853
  }
4826
4854
  ),
4827
- selectedPage && !readOnly ? /* @__PURE__ */ jsx12(
4855
+ selectedPage && !readOnly ? /* @__PURE__ */ jsx13(
4828
4856
  "button",
4829
4857
  {
4830
4858
  type: "button",
@@ -4832,12 +4860,12 @@ function UrlOrPageInput({
4832
4860
  onMouseDown: clearSelection,
4833
4861
  "aria-label": "Clear selected page",
4834
4862
  tabIndex: -1,
4835
- children: /* @__PURE__ */ jsx12(IconX, { "aria-hidden": true })
4863
+ children: /* @__PURE__ */ jsx13(IconX, { "aria-hidden": true })
4836
4864
  }
4837
4865
  ) : null,
4838
- !readOnly ? /* @__PURE__ */ jsx12(FieldChevron, { onClick: toggleDropdown }) : null
4866
+ !readOnly ? /* @__PURE__ */ jsx13(FieldChevron, { onClick: toggleDropdown }) : null
4839
4867
  ] }),
4840
- dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ jsx12(
4868
+ dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ jsx13(
4841
4869
  "div",
4842
4870
  {
4843
4871
  "data-ohw-link-page-dropdown": "",
@@ -4850,8 +4878,8 @@ function UrlOrPageInput({
4850
4878
  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",
4851
4879
  onClick: () => onPageSelect(page),
4852
4880
  children: [
4853
- /* @__PURE__ */ jsx12(IconFile, { className: "shrink-0", "aria-hidden": true }),
4854
- /* @__PURE__ */ jsx12("span", { className: "truncate", children: page.title })
4881
+ /* @__PURE__ */ jsx13(IconFile, { className: "shrink-0", "aria-hidden": true }),
4882
+ /* @__PURE__ */ jsx13("span", { className: "truncate", children: page.title })
4855
4883
  ]
4856
4884
  },
4857
4885
  page.path
@@ -4859,7 +4887,7 @@ function UrlOrPageInput({
4859
4887
  }
4860
4888
  ) : null
4861
4889
  ] }),
4862
- urlError ? /* @__PURE__ */ jsx12("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
4890
+ urlError ? /* @__PURE__ */ jsx13("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
4863
4891
  ] });
4864
4892
  }
4865
4893
 
@@ -5027,7 +5055,7 @@ function useLinkModalState({
5027
5055
  }
5028
5056
 
5029
5057
  // src/ui/link-modal/LinkEditorPanel.tsx
5030
- import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
5058
+ import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
5031
5059
  function LinkEditorPanel({
5032
5060
  open = true,
5033
5061
  mode = "create",
@@ -5052,24 +5080,24 @@ function LinkEditorPanel({
5052
5080
  });
5053
5081
  const isCancel = state.secondaryLabel === "Cancel";
5054
5082
  return /* @__PURE__ */ jsxs8(Fragment2, { children: [
5055
- /* @__PURE__ */ jsx13(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx13(
5083
+ /* @__PURE__ */ jsx14(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx14(
5056
5084
  "button",
5057
5085
  {
5058
5086
  type: "button",
5059
5087
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
5060
5088
  "aria-label": "Close",
5061
- children: /* @__PURE__ */ jsx13(IconX, { "aria-hidden": true })
5089
+ children: /* @__PURE__ */ jsx14(IconX, { "aria-hidden": true })
5062
5090
  }
5063
5091
  ) }),
5064
- /* @__PURE__ */ jsx13(DialogHeader, { className: "w-full gap-1.5 p-6 pr-12", children: /* @__PURE__ */ jsx13(DialogTitle, { className: "m-0 w-full break-words", children: state.title }) }),
5092
+ /* @__PURE__ */ jsx14(DialogHeader, { className: "w-full gap-1.5 p-6 pr-12", children: /* @__PURE__ */ jsx14(DialogTitle, { className: "m-0 w-full break-words", children: state.title }) }),
5065
5093
  /* @__PURE__ */ jsxs8("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
5066
- state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ jsx13(
5094
+ state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ jsx14(
5067
5095
  DestinationBreadcrumb,
5068
5096
  {
5069
5097
  pageTitle: state.selectedPage.title,
5070
5098
  sectionLabel: state.selectedSection.label
5071
5099
  }
5072
- ) : /* @__PURE__ */ jsx13(
5100
+ ) : /* @__PURE__ */ jsx14(
5073
5101
  UrlOrPageInput,
5074
5102
  {
5075
5103
  value: state.searchValue,
@@ -5083,17 +5111,17 @@ function LinkEditorPanel({
5083
5111
  }
5084
5112
  ),
5085
5113
  state.showChooseSection ? /* @__PURE__ */ jsxs8("div", { className: "flex flex-col justify-center gap-2", children: [
5086
- /* @__PURE__ */ jsx13(Button, { type: "button", variant: "outline", className: "w-fit cursor-pointer", size: "sm", onClick: state.handleChooseSection, children: "Choose a section" }),
5114
+ /* @__PURE__ */ jsx14(Button, { type: "button", variant: "outline", className: "w-fit cursor-pointer", size: "sm", onClick: state.handleChooseSection, children: "Choose a section" }),
5087
5115
  /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
5088
- /* @__PURE__ */ jsx13(IconInfo, { className: "shrink-0", "aria-hidden": true }),
5089
- /* @__PURE__ */ jsx13("span", { children: "Pick a section this link should scroll to." })
5116
+ /* @__PURE__ */ jsx14(IconInfo, { className: "shrink-0", "aria-hidden": true }),
5117
+ /* @__PURE__ */ jsx14("span", { children: "Pick a section this link should scroll to." })
5090
5118
  ] })
5091
5119
  ] }) : null,
5092
- state.showSectionPicker ? /* @__PURE__ */ jsx13(SectionPickerList, { sections: state.activeSections, onSelect: state.handleSectionSelect }) : null,
5093
- state.showSectionRow && state.selectedSection ? /* @__PURE__ */ jsx13(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
5120
+ state.showSectionPicker ? /* @__PURE__ */ jsx14(SectionPickerList, { sections: state.activeSections, onSelect: state.handleSectionSelect }) : null,
5121
+ state.showSectionRow && state.selectedSection ? /* @__PURE__ */ jsx14(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
5094
5122
  ] }),
5095
5123
  /* @__PURE__ */ jsxs8(DialogFooter, { className: "w-full px-6 pb-6", children: [
5096
- /* @__PURE__ */ jsx13(
5124
+ /* @__PURE__ */ jsx14(
5097
5125
  Button,
5098
5126
  {
5099
5127
  type: "button",
@@ -5108,7 +5136,7 @@ function LinkEditorPanel({
5108
5136
  children: state.secondaryLabel
5109
5137
  }
5110
5138
  ),
5111
- /* @__PURE__ */ jsx13(
5139
+ /* @__PURE__ */ jsx14(
5112
5140
  Button,
5113
5141
  {
5114
5142
  type: "button",
@@ -5127,7 +5155,7 @@ function LinkEditorPanel({
5127
5155
  }
5128
5156
 
5129
5157
  // src/ui/link-modal/LinkPopover.tsx
5130
- import { jsx as jsx14 } from "react/jsx-runtime";
5158
+ import { jsx as jsx15 } from "react/jsx-runtime";
5131
5159
  function LinkPopover({
5132
5160
  open = true,
5133
5161
  panelRef,
@@ -5135,14 +5163,14 @@ function LinkPopover({
5135
5163
  onClose,
5136
5164
  ...editorProps
5137
5165
  }) {
5138
- return /* @__PURE__ */ jsx14(
5166
+ return /* @__PURE__ */ jsx15(
5139
5167
  Dialog2,
5140
5168
  {
5141
5169
  open,
5142
5170
  onOpenChange: (next) => {
5143
5171
  if (!next) onClose?.();
5144
5172
  },
5145
- children: /* @__PURE__ */ jsx14(
5173
+ children: /* @__PURE__ */ jsx15(
5146
5174
  DialogContent,
5147
5175
  {
5148
5176
  ref: panelRef,
@@ -5152,7 +5180,7 @@ function LinkPopover({
5152
5180
  "data-ohw-bridge": "",
5153
5181
  showCloseButton: false,
5154
5182
  className: "gap-0 p-0 w-full md:w-md pointer-events-auto",
5155
- children: /* @__PURE__ */ jsx14(LinkEditorPanel, { ...editorProps, open, onClose })
5183
+ children: /* @__PURE__ */ jsx15(LinkEditorPanel, { ...editorProps, open, onClose })
5156
5184
  }
5157
5185
  )
5158
5186
  }
@@ -5218,7 +5246,7 @@ function shouldUseDevFixtures() {
5218
5246
  }
5219
5247
 
5220
5248
  // src/ui/badge.tsx
5221
- import { jsx as jsx15 } from "react/jsx-runtime";
5249
+ import { jsx as jsx16 } from "react/jsx-runtime";
5222
5250
  var badgeVariants = cva(
5223
5251
  "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",
5224
5252
  {
@@ -5236,11 +5264,11 @@ var badgeVariants = cva(
5236
5264
  }
5237
5265
  );
5238
5266
  function Badge({ className, variant, ...props }) {
5239
- return /* @__PURE__ */ jsx15("div", { className: cn(badgeVariants({ variant }), className), ...props });
5267
+ return /* @__PURE__ */ jsx16("div", { className: cn(badgeVariants({ variant }), className), ...props });
5240
5268
  }
5241
5269
 
5242
5270
  // src/OhhwellsBridge.tsx
5243
- import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs9 } from "react/jsx-runtime";
5271
+ import { Fragment as Fragment3, jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
5244
5272
  var PRIMARY = "#0885FE";
5245
5273
  var IMAGE_FADE_MS = 300;
5246
5274
  function runOpacityFade(el, onDone) {
@@ -5414,7 +5442,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
5414
5442
  const root = createRoot(container);
5415
5443
  flushSync(() => {
5416
5444
  root.render(
5417
- /* @__PURE__ */ jsx16(
5445
+ /* @__PURE__ */ jsx17(
5418
5446
  SchedulingWidget,
5419
5447
  {
5420
5448
  notifyOnConnect,
@@ -5462,6 +5490,20 @@ function applyLinkHref(el, val) {
5462
5490
  const anchor = el instanceof HTMLAnchorElement ? el : el.querySelector("a");
5463
5491
  if (anchor) anchor.setAttribute("href", val);
5464
5492
  }
5493
+ function getEditMeasureEl(editable) {
5494
+ return editable.closest("[data-ohw-href-key]") ?? editable;
5495
+ }
5496
+ function isDragHandleDisabled(el) {
5497
+ const carriers = [
5498
+ el.closest("[data-ohw-href-key]"),
5499
+ el.closest("[data-ohw-editable]")
5500
+ ];
5501
+ return carriers.some((carrier) => {
5502
+ if (!carrier) return false;
5503
+ const raw = carrier.getAttribute("data-ohw-drag-disabled");
5504
+ return raw === "true" || raw === "";
5505
+ });
5506
+ }
5465
5507
  function collectEditableNodes() {
5466
5508
  const nodes = Array.from(document.querySelectorAll("[data-ohw-editable]")).map((el) => {
5467
5509
  if (el.dataset.ohwEditable === "image") {
@@ -5515,6 +5557,14 @@ function getHrefKeyFromElement(el) {
5515
5557
  function isNavbarButton(el) {
5516
5558
  return Boolean(el.closest('[data-ohw-role="navbar-button"]'));
5517
5559
  }
5560
+ function getReorderHandleState(el) {
5561
+ const linkEl = el.closest("[data-ohw-href-key]");
5562
+ if (!linkEl || isNavbarButton(el)) return { key: null, disabled: false };
5563
+ return {
5564
+ key: linkEl.dataset.ohwHrefKey ?? null,
5565
+ disabled: isDragHandleDisabled(el)
5566
+ };
5567
+ }
5518
5568
  function clearHrefKeyHover(anchor) {
5519
5569
  anchor.removeAttribute("data-ohw-hovered");
5520
5570
  anchor.querySelectorAll("[data-ohw-hovered]").forEach((el) => {
@@ -5644,6 +5694,8 @@ var ICONS = {
5644
5694
  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"/>',
5645
5695
  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"/>'
5646
5696
  };
5697
+ var TOOLBAR_PILL_PADDING = 2;
5698
+ var TOOLBAR_TOGGLE_GAP = 4;
5647
5699
  var TOOLBAR_GROUPS = [
5648
5700
  [
5649
5701
  { cmd: "bold", title: "Bold" },
@@ -5661,24 +5713,64 @@ var TOOLBAR_GROUPS = [
5661
5713
  { cmd: "insertOrderedList", title: "Numbered List" }
5662
5714
  ]
5663
5715
  ];
5664
- function GlowFrame({ rect, elRef }) {
5716
+ function EditGlowChrome({
5717
+ rect,
5718
+ elRef,
5719
+ reorderHrefKey,
5720
+ dragDisabled = false
5721
+ }) {
5665
5722
  const GAP = 6;
5666
- return /* @__PURE__ */ jsx16(
5723
+ return /* @__PURE__ */ jsxs9(
5667
5724
  "div",
5668
5725
  {
5669
5726
  ref: elRef,
5727
+ "data-ohw-edit-chrome": "",
5670
5728
  style: {
5671
5729
  position: "fixed",
5672
5730
  top: rect.top - GAP,
5673
5731
  left: rect.left - GAP,
5674
5732
  width: rect.width + GAP * 2,
5675
5733
  height: rect.height + GAP * 2,
5676
- border: "2px solid #0885FE",
5677
- borderRadius: 8,
5678
- boxShadow: "0 0 0 4px rgba(8, 133, 254, 0.12)",
5679
5734
  pointerEvents: "none",
5680
5735
  zIndex: 2147483646
5681
- }
5736
+ },
5737
+ children: [
5738
+ /* @__PURE__ */ jsx17(
5739
+ "div",
5740
+ {
5741
+ style: {
5742
+ position: "absolute",
5743
+ inset: 0,
5744
+ border: "2px solid #0885FE",
5745
+ borderRadius: 8,
5746
+ boxShadow: "0 0 0 4px rgba(8, 133, 254, 0.12)",
5747
+ pointerEvents: "none"
5748
+ }
5749
+ }
5750
+ ),
5751
+ reorderHrefKey && /* @__PURE__ */ jsx17(
5752
+ "div",
5753
+ {
5754
+ "data-ohw-drag-handle-container": "",
5755
+ "data-ohw-drag-disabled": dragDisabled ? "" : void 0,
5756
+ style: {
5757
+ position: "absolute",
5758
+ left: 0,
5759
+ top: "50%",
5760
+ transform: "translate(calc(-100% - 7px), -50%)",
5761
+ pointerEvents: dragDisabled ? "none" : "auto"
5762
+ },
5763
+ children: /* @__PURE__ */ jsx17(
5764
+ DragHandle,
5765
+ {
5766
+ "aria-label": `Reorder ${reorderHrefKey}`,
5767
+ disabled: dragDisabled,
5768
+ "aria-disabled": dragDisabled
5769
+ }
5770
+ )
5771
+ }
5772
+ )
5773
+ ]
5682
5774
  }
5683
5775
  );
5684
5776
  }
@@ -5722,9 +5814,9 @@ function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
5722
5814
  const pinnedTop = Math.min(maxBottom - approxH, Math.max(minTop, clip.top + gap));
5723
5815
  return { top: pinnedTop + approxH, transform: "translateX(-50%) translateY(-100%)" };
5724
5816
  }
5725
- function calcToolbarPos(rect, parentScroll, approxW = 330) {
5817
+ function calcToolbarPos(rect, parentScroll, approxW = 306) {
5726
5818
  const GAP = 8;
5727
- const APPROX_H = 36;
5819
+ const APPROX_H = 32;
5728
5820
  const APPROX_W = approxW;
5729
5821
  const clip = getIframeVisibleClip(parentScroll);
5730
5822
  const clipTop = clip?.top ?? 0;
@@ -5759,8 +5851,8 @@ function calcToolbarPos(rect, parentScroll, approxW = 330) {
5759
5851
  return { top, left, transform };
5760
5852
  }
5761
5853
  var EDIT_LINK_ICON = /* @__PURE__ */ jsxs9("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: [
5762
- /* @__PURE__ */ jsx16("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
5763
- /* @__PURE__ */ jsx16("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
5854
+ /* @__PURE__ */ jsx17("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
5855
+ /* @__PURE__ */ jsx17("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
5764
5856
  ] });
5765
5857
  function FloatingToolbar({
5766
5858
  rect,
@@ -5772,7 +5864,7 @@ function FloatingToolbar({
5772
5864
  showEditLink,
5773
5865
  onEditLink
5774
5866
  }) {
5775
- const approxW = variant === "link-action" ? 120 : 330;
5867
+ const approxW = variant === "link-action" ? 112 : 306;
5776
5868
  const { top, left, transform } = calcToolbarPos(rect, parentScroll, approxW);
5777
5869
  if (variant === "link-action") {
5778
5870
  return /* @__PURE__ */ jsxs9(
@@ -5792,15 +5884,15 @@ function FloatingToolbar({
5792
5884
  boxShadow: "0px 2px 4px -2px rgba(0,0,0,.1),0px 4px 6px -1px rgba(0,0,0,.1)",
5793
5885
  display: "flex",
5794
5886
  alignItems: "center",
5795
- padding: 4,
5796
- gap: 6,
5887
+ padding: TOOLBAR_PILL_PADDING,
5888
+ gap: TOOLBAR_TOGGLE_GAP,
5797
5889
  fontFamily: "sans-serif",
5798
5890
  pointerEvents: "auto",
5799
5891
  whiteSpace: "nowrap"
5800
5892
  },
5801
5893
  onMouseDown: (e) => e.stopPropagation(),
5802
5894
  children: [
5803
- /* @__PURE__ */ jsx16(
5895
+ /* @__PURE__ */ jsx17(
5804
5896
  "button",
5805
5897
  {
5806
5898
  type: "button",
@@ -5835,8 +5927,8 @@ function FloatingToolbar({
5835
5927
  children: EDIT_LINK_ICON
5836
5928
  }
5837
5929
  ),
5838
- /* @__PURE__ */ jsx16("span", { style: { display: "block", width: 1, height: 24, background: "#E7E5E4", flexShrink: 0 } }),
5839
- /* @__PURE__ */ jsx16(
5930
+ /* @__PURE__ */ jsx17("span", { style: { display: "block", width: 1, height: 24, background: "#E7E5E4", flexShrink: 0 } }),
5931
+ /* @__PURE__ */ jsx17(
5840
5932
  "button",
5841
5933
  {
5842
5934
  type: "button",
@@ -5856,9 +5948,9 @@ function FloatingToolbar({
5856
5948
  opacity: 0.6
5857
5949
  },
5858
5950
  children: /* @__PURE__ */ jsxs9("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": true, children: [
5859
- /* @__PURE__ */ jsx16("circle", { cx: "5", cy: "12", r: "1.5" }),
5860
- /* @__PURE__ */ jsx16("circle", { cx: "12", cy: "12", r: "1.5" }),
5861
- /* @__PURE__ */ jsx16("circle", { cx: "19", cy: "12", r: "1.5" })
5951
+ /* @__PURE__ */ jsx17("circle", { cx: "5", cy: "12", r: "1.5" }),
5952
+ /* @__PURE__ */ jsx17("circle", { cx: "12", cy: "12", r: "1.5" }),
5953
+ /* @__PURE__ */ jsx17("circle", { cx: "19", cy: "12", r: "1.5" })
5862
5954
  ] })
5863
5955
  }
5864
5956
  )
@@ -5883,19 +5975,19 @@ function FloatingToolbar({
5883
5975
  boxShadow: "0px 2px 4px -2px rgba(0,0,0,.1),0px 4px 6px -1px rgba(0,0,0,.1)",
5884
5976
  display: "flex",
5885
5977
  alignItems: "center",
5886
- padding: 4,
5887
- gap: 6,
5978
+ padding: TOOLBAR_PILL_PADDING,
5979
+ gap: TOOLBAR_TOGGLE_GAP,
5888
5980
  fontFamily: "sans-serif",
5889
5981
  pointerEvents: "auto",
5890
5982
  whiteSpace: "nowrap"
5891
5983
  },
5892
5984
  onMouseDown: (e) => e.stopPropagation(),
5893
5985
  children: [
5894
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs9(React6.Fragment, { children: [
5895
- gi > 0 && /* @__PURE__ */ jsx16("span", { style: { display: "block", width: 1, height: 24, background: "#E7E5E4", flexShrink: 0 } }),
5986
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs9(React7.Fragment, { children: [
5987
+ gi > 0 && /* @__PURE__ */ jsx17("span", { style: { display: "block", width: 1, height: 24, background: "#E7E5E4", flexShrink: 0 } }),
5896
5988
  btns.map((btn) => {
5897
5989
  const isActive = activeCommands.has(btn.cmd);
5898
- return /* @__PURE__ */ jsx16(
5990
+ return /* @__PURE__ */ jsx17(
5899
5991
  "button",
5900
5992
  {
5901
5993
  title: btn.title,
@@ -5921,7 +6013,7 @@ function FloatingToolbar({
5921
6013
  flexShrink: 0,
5922
6014
  padding: 6
5923
6015
  },
5924
- children: /* @__PURE__ */ jsx16(
6016
+ children: /* @__PURE__ */ jsx17(
5925
6017
  "svg",
5926
6018
  {
5927
6019
  width: "16",
@@ -5941,7 +6033,7 @@ function FloatingToolbar({
5941
6033
  );
5942
6034
  })
5943
6035
  ] }, gi)),
5944
- showEditLink ? /* @__PURE__ */ jsx16(
6036
+ showEditLink ? /* @__PURE__ */ jsx17(
5945
6037
  "button",
5946
6038
  {
5947
6039
  type: "button",
@@ -5990,7 +6082,7 @@ function StateToggle({
5990
6082
  states,
5991
6083
  onStateChange
5992
6084
  }) {
5993
- return /* @__PURE__ */ jsx16(
6085
+ return /* @__PURE__ */ jsx17(
5994
6086
  ToggleGroup,
5995
6087
  {
5996
6088
  "data-ohw-state-toggle": "",
@@ -6004,7 +6096,7 @@ function StateToggle({
6004
6096
  left: rect.right - 8,
6005
6097
  transform: "translateX(-100%)"
6006
6098
  },
6007
- children: states.map((state) => /* @__PURE__ */ jsx16(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
6099
+ children: states.map((state) => /* @__PURE__ */ jsx17(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
6008
6100
  }
6009
6101
  );
6010
6102
  }
@@ -6102,6 +6194,8 @@ function OhhwellsBridge() {
6102
6194
  const [toolbarVariant, setToolbarVariant] = useState5("none");
6103
6195
  const toolbarVariantRef = useRef3("none");
6104
6196
  toolbarVariantRef.current = toolbarVariant;
6197
+ const [reorderHrefKey, setReorderHrefKey] = useState5(null);
6198
+ const [reorderDragDisabled, setReorderDragDisabled] = useState5(false);
6105
6199
  const [toggleState, setToggleState] = useState5(null);
6106
6200
  const [maxBadge, setMaxBadge] = useState5(null);
6107
6201
  const [activeCommands, setActiveCommands] = useState5(/* @__PURE__ */ new Set());
@@ -6208,7 +6302,7 @@ function OhhwellsBridge() {
6208
6302
  useEffect3(() => {
6209
6303
  const update = () => {
6210
6304
  const el = activeElRef.current ?? selectedElRef.current;
6211
- if (el) setToolbarRect(el.getBoundingClientRect());
6305
+ if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
6212
6306
  setToggleState((prev) => {
6213
6307
  if (!prev || !activeStateElRef.current) return prev;
6214
6308
  return { ...prev, rect: activeStateElRef.current.getBoundingClientRect() };
@@ -6275,6 +6369,8 @@ function OhhwellsBridge() {
6275
6369
  }
6276
6370
  el.removeAttribute("contenteditable");
6277
6371
  activeElRef.current = null;
6372
+ setReorderHrefKey(null);
6373
+ setReorderDragDisabled(false);
6278
6374
  if (!selectedElRef.current) {
6279
6375
  setToolbarRect(null);
6280
6376
  setToolbarVariant("none");
@@ -6312,11 +6408,15 @@ function OhhwellsBridge() {
6312
6408
  setToolbarVariant("rich-text");
6313
6409
  el.setAttribute("contenteditable", "true");
6314
6410
  el.removeAttribute("data-ohw-hovered");
6411
+ el.closest("[data-ohw-href-key]")?.removeAttribute("data-ohw-hovered");
6315
6412
  activeElRef.current = el;
6316
6413
  originalContentRef.current = el.innerHTML;
6317
6414
  el.focus();
6318
- setToolbarRect(el.getBoundingClientRect());
6319
6415
  setToolbarShowEditLink(Boolean(getHrefKeyFromElement(el)));
6416
+ const { key: reorderKey, disabled: reorderDisabled } = getReorderHandleState(el);
6417
+ setReorderHrefKey(reorderKey);
6418
+ setReorderDragDisabled(reorderDisabled);
6419
+ setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
6320
6420
  postToParent({ type: "ow:enter-edit", key: el.dataset.ohwKey });
6321
6421
  requestAnimationFrame(() => refreshActiveCommandsRef.current());
6322
6422
  }, [deactivate, postToParent]);
@@ -6381,30 +6481,36 @@ function OhhwellsBridge() {
6381
6481
  return () => {
6382
6482
  cancelled = true;
6383
6483
  };
6384
- }, [subdomain, isEditMode, pathname]);
6484
+ }, [subdomain, isEditMode]);
6385
6485
  useEffect3(() => {
6386
6486
  if (!subdomain || isEditMode) return;
6387
6487
  let debounceTimer = null;
6488
+ let observer = null;
6388
6489
  const applyFromCache = () => {
6389
6490
  const content = contentCache.get(subdomain);
6390
6491
  if (!content) return;
6391
6492
  retryMissingSchedulingMounts(getPageSchedulingEntries(content["__ohw_sections"]), false);
6392
- for (const [key, val] of Object.entries(content)) {
6393
- if (key === "__ohw_sections") continue;
6394
- document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
6395
- if (el.dataset.ohwEditable === "image") {
6396
- const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
6397
- if (img && img.src !== val) img.src = val;
6398
- } else if (el.dataset.ohwEditable === "bg-image") {
6399
- const next = `url('${val}')`;
6400
- if (el.style.backgroundImage !== next) el.style.backgroundImage = next;
6401
- } else if (el.dataset.ohwEditable === "link") {
6402
- applyLinkHref(el, val);
6403
- } else if (el.innerHTML !== val) {
6404
- el.innerHTML = val;
6405
- }
6406
- });
6407
- applyLinkByKey(key, val);
6493
+ observer?.disconnect();
6494
+ try {
6495
+ for (const [key, val] of Object.entries(content)) {
6496
+ if (key === "__ohw_sections") continue;
6497
+ document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
6498
+ if (el.dataset.ohwEditable === "image") {
6499
+ const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
6500
+ if (img && img.src !== val) img.src = val;
6501
+ } else if (el.dataset.ohwEditable === "bg-image") {
6502
+ const next = `url('${val}')`;
6503
+ if (el.style.backgroundImage !== next) el.style.backgroundImage = next;
6504
+ } else if (el.dataset.ohwEditable === "link") {
6505
+ applyLinkHref(el, val);
6506
+ } else if (el.innerHTML !== val) {
6507
+ el.innerHTML = val;
6508
+ }
6509
+ });
6510
+ applyLinkByKey(key, val);
6511
+ }
6512
+ } finally {
6513
+ observer?.observe(document.body, { childList: true, subtree: true });
6408
6514
  }
6409
6515
  enforceLinkHrefs();
6410
6516
  };
@@ -6412,11 +6518,11 @@ function OhhwellsBridge() {
6412
6518
  if (debounceTimer) clearTimeout(debounceTimer);
6413
6519
  debounceTimer = setTimeout(applyFromCache, 150);
6414
6520
  };
6415
- scheduleApply();
6416
- const observer = new MutationObserver(scheduleApply);
6521
+ applyFromCache();
6522
+ observer = new MutationObserver(scheduleApply);
6417
6523
  observer.observe(document.body, { childList: true, subtree: true });
6418
6524
  return () => {
6419
- observer.disconnect();
6525
+ observer?.disconnect();
6420
6526
  if (debounceTimer) clearTimeout(debounceTimer);
6421
6527
  };
6422
6528
  }, [subdomain, isEditMode, pathname]);
@@ -6540,6 +6646,11 @@ function OhhwellsBridge() {
6540
6646
  if (target.closest("[data-ohw-state-toggle]")) return;
6541
6647
  if (target.closest("[data-ohw-max-badge]")) return;
6542
6648
  if (isInsideLinkEditor(target)) return;
6649
+ if (target.closest('[data-ohw-edit-chrome], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
6650
+ e.preventDefault();
6651
+ e.stopPropagation();
6652
+ return;
6653
+ }
6543
6654
  const editable = target.closest("[data-ohw-editable]");
6544
6655
  if (editable) {
6545
6656
  if (editable.dataset.ohwEditable === "link") {
@@ -6616,14 +6727,18 @@ function OhhwellsBridge() {
6616
6727
  const selected = selectedElRef.current;
6617
6728
  if (selected && (selected === editable || selected.contains(editable))) return;
6618
6729
  if (editable.dataset.ohwEditable !== "image" && editable.dataset.ohwEditable !== "bg-image" && !editable.hasAttribute("contenteditable")) {
6619
- editable.setAttribute("data-ohw-hovered", "");
6730
+ const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
6731
+ hoverTarget.setAttribute("data-ohw-hovered", "");
6620
6732
  }
6621
6733
  };
6622
6734
  const handleMouseOut = (e) => {
6623
6735
  const editable = e.target.closest("[data-ohw-editable]");
6624
6736
  if (!editable) return;
6737
+ const related = e.relatedTarget instanceof Element ? e.relatedTarget : null;
6738
+ if (related?.closest("[data-ohw-drag-handle-container]")) return;
6625
6739
  if (editable.dataset.ohwEditable !== "image" && editable.dataset.ohwEditable !== "bg-image") {
6626
- editable.removeAttribute("data-ohw-hovered");
6740
+ const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
6741
+ hoverTarget.removeAttribute("data-ohw-hovered");
6627
6742
  }
6628
6743
  };
6629
6744
  const toProbeCoords = (clientX, clientY, fromParentViewport) => {
@@ -6738,11 +6853,20 @@ function OhhwellsBridge() {
6738
6853
  return;
6739
6854
  }
6740
6855
  }
6856
+ if (activeElRef.current) {
6857
+ if (hoveredImageRef.current) {
6858
+ hoveredImageRef.current = null;
6859
+ hoveredImageHasTextOverlapRef.current = false;
6860
+ resumeAnimTracks();
6861
+ postToParentRef.current({ type: "ow:image-unhover" });
6862
+ }
6863
+ return;
6864
+ }
6741
6865
  const imgEl = findImageAtPoint(clientX, clientY, fromParentViewport);
6742
6866
  if (imgEl) {
6743
6867
  const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
6744
6868
  const topEl = document.elementFromPoint(x, y);
6745
- if (topEl?.closest("[data-ohw-toolbar]")) {
6869
+ if (topEl?.closest('[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
6746
6870
  if (hoveredImageRef.current) {
6747
6871
  hoveredImageRef.current = null;
6748
6872
  resumeAnimTracks();
@@ -7035,7 +7159,7 @@ function OhhwellsBridge() {
7035
7159
  const el = e.target;
7036
7160
  const key = el.dataset.ohwKey;
7037
7161
  if (!key) return;
7038
- if (el === activeElRef.current) setToolbarRect(el.getBoundingClientRect());
7162
+ if (el === activeElRef.current) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
7039
7163
  const maxLen = el.dataset.ohwMaxLength ? parseInt(el.dataset.ohwMaxLength, 10) : null;
7040
7164
  if (maxLen) {
7041
7165
  const current = el.innerText.replace(/\n$/, "").length;
@@ -7265,7 +7389,7 @@ function OhhwellsBridge() {
7265
7389
  };
7266
7390
  const applyToolbarPos = (rect) => {
7267
7391
  const ps = parentScrollRef.current;
7268
- const approxW = toolbarVariantRef.current === "link-action" ? 120 : 330;
7392
+ const approxW = toolbarVariantRef.current === "link-action" ? 112 : 306;
7269
7393
  if (toolbarElRef.current) {
7270
7394
  const { top, left, transform } = calcToolbarPos(rect, ps, approxW);
7271
7395
  toolbarElRef.current.style.top = `${top}px`;
@@ -7444,7 +7568,7 @@ function OhhwellsBridge() {
7444
7568
  const handleCommand = useCallback2((cmd) => {
7445
7569
  document.execCommand(cmd, false);
7446
7570
  activeElRef.current?.focus();
7447
- if (activeElRef.current) setToolbarRect(activeElRef.current.getBoundingClientRect());
7571
+ if (activeElRef.current) setToolbarRect(getEditMeasureEl(activeElRef.current).getBoundingClientRect());
7448
7572
  refreshActiveCommandsRef.current();
7449
7573
  }, []);
7450
7574
  const handleStateChange = useCallback2((state) => {
@@ -7498,10 +7622,18 @@ function OhhwellsBridge() {
7498
7622
  linkPopoverOpenRef.current = linkPopover !== null;
7499
7623
  return bridgeRoot ? createPortal(
7500
7624
  /* @__PURE__ */ jsxs9(Fragment3, { children: [
7501
- /* @__PURE__ */ jsx16("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
7625
+ /* @__PURE__ */ jsx17("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
7502
7626
  toolbarRect && /* @__PURE__ */ jsxs9(Fragment3, { children: [
7503
- /* @__PURE__ */ jsx16(GlowFrame, { rect: toolbarRect, elRef: glowElRef }),
7504
- toolbarVariant === "rich-text" && /* @__PURE__ */ jsx16(
7627
+ /* @__PURE__ */ jsx17(
7628
+ EditGlowChrome,
7629
+ {
7630
+ rect: toolbarRect,
7631
+ elRef: glowElRef,
7632
+ reorderHrefKey,
7633
+ dragDisabled: reorderDragDisabled
7634
+ }
7635
+ ),
7636
+ toolbarVariant === "rich-text" && /* @__PURE__ */ jsx17(
7505
7637
  FloatingToolbar,
7506
7638
  {
7507
7639
  variant: "rich-text",
@@ -7514,7 +7646,7 @@ function OhhwellsBridge() {
7514
7646
  onEditLink: openLinkPopoverForActive
7515
7647
  }
7516
7648
  ),
7517
- toolbarVariant === "link-action" && /* @__PURE__ */ jsx16(
7649
+ toolbarVariant === "link-action" && /* @__PURE__ */ jsx17(
7518
7650
  FloatingToolbar,
7519
7651
  {
7520
7652
  variant: "link-action",
@@ -7553,7 +7685,7 @@ function OhhwellsBridge() {
7553
7685
  ]
7554
7686
  }
7555
7687
  ),
7556
- toggleState && /* @__PURE__ */ jsx16(
7688
+ toggleState && /* @__PURE__ */ jsx17(
7557
7689
  StateToggle,
7558
7690
  {
7559
7691
  rect: toggleState.rect,
@@ -7569,8 +7701,8 @@ function OhhwellsBridge() {
7569
7701
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
7570
7702
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
7571
7703
  children: [
7572
- /* @__PURE__ */ jsx16("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
7573
- /* @__PURE__ */ jsx16(
7704
+ /* @__PURE__ */ jsx17("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
7705
+ /* @__PURE__ */ jsx17(
7574
7706
  Badge,
7575
7707
  {
7576
7708
  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",
@@ -7583,11 +7715,11 @@ function OhhwellsBridge() {
7583
7715
  children: "Add Section"
7584
7716
  }
7585
7717
  ),
7586
- /* @__PURE__ */ jsx16("div", { className: "flex-1 bg-primary", style: { height: 3 } })
7718
+ /* @__PURE__ */ jsx17("div", { className: "flex-1 bg-primary", style: { height: 3 } })
7587
7719
  ]
7588
7720
  }
7589
7721
  ),
7590
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx16(
7722
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx17(
7591
7723
  LinkPopover,
7592
7724
  {
7593
7725
  panelRef: linkPopoverPanelRef,
@@ -7602,12 +7734,38 @@ function OhhwellsBridge() {
7602
7734
  onSubmit: handleLinkPopoverSubmit
7603
7735
  },
7604
7736
  `${linkPopover.key}-${pathname}`
7605
- ) : null
7737
+ ) : null,
7738
+ sectionGap && /* @__PURE__ */ jsxs9(
7739
+ "div",
7740
+ {
7741
+ "data-ohw-section-insert-line": "",
7742
+ className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
7743
+ style: { top: sectionGap.y, transform: "translateY(-50%)" },
7744
+ children: [
7745
+ /* @__PURE__ */ jsx17("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
7746
+ /* @__PURE__ */ jsx17(
7747
+ Badge,
7748
+ {
7749
+ 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",
7750
+ onClick: () => {
7751
+ window.parent.postMessage(
7752
+ { type: "ow:add-section", insertAfter: sectionGap.insertAfter, insertBefore: sectionGap.insertBefore },
7753
+ "*"
7754
+ );
7755
+ },
7756
+ children: "Add Section"
7757
+ }
7758
+ ),
7759
+ /* @__PURE__ */ jsx17("div", { className: "flex-1 bg-primary", style: { height: 3 } })
7760
+ ]
7761
+ }
7762
+ )
7606
7763
  ] }),
7607
7764
  bridgeRoot
7608
7765
  ) : null;
7609
7766
  }
7610
7767
  export {
7768
+ DragHandle,
7611
7769
  LinkEditorPanel,
7612
7770
  LinkPopover,
7613
7771
  OhhwellsBridge,
@@ -7618,6 +7776,7 @@ export {
7618
7776
  buildTarget,
7619
7777
  filterAvailablePages,
7620
7778
  getEditModeInitialState,
7779
+ isEditSessionActive,
7621
7780
  isValidUrl,
7622
7781
  parseTarget,
7623
7782
  toggleVariants,