@ohhwells/bridge 0.1.32 → 0.1.33-next.38

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,
@@ -760,15 +762,10 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
760
762
  };
761
763
  const handleReplaceSchedule = () => {
762
764
  setIsHovered(false);
763
- if (schedule) {
764
- window.parent.postMessage({
765
- type: "ow:schedule-connected",
766
- schedule: { id: schedule.id, name: schedule.name },
767
- insertAfter
768
- }, "*");
769
- } else {
770
- window.parent.postMessage({ type: "ow:scheduling-not-connected", insertAfter }, "*");
771
- }
765
+ window.parent.postMessage(
766
+ { type: "ow:scheduling-not-connected", insertAfter, currentScheduleId: schedule?.id },
767
+ "*"
768
+ );
772
769
  };
773
770
  if (!inEditor && !loading && !schedule) return null;
774
771
  const sectionId = `scheduling-${insertAfter}`;
@@ -811,7 +808,19 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
811
808
  ),
812
809
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "max-w-[1280px] mx-auto flex flex-col items-center gap-16", children: [
813
810
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-col items-center gap-4", children: [
814
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { className: "font-display text-4xl sm:text-5xl font-bold text-center m-0 text-(--color-dark,#200C02)", children: schedule?.name ?? "Book an appointment" }),
811
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
812
+ "h2",
813
+ {
814
+ className: "font-display text-center m-0 text-(--color-dark,#200C02)",
815
+ style: {
816
+ fontSize: "var(--fs-section-h2, clamp(40px, 4.4vw, 64px))",
817
+ fontWeight: "var(--font-weight-heading, 400)",
818
+ lineHeight: 1.05,
819
+ letterSpacing: "-0.02em"
820
+ },
821
+ children: schedule?.name ?? "Book an appointment"
822
+ }
823
+ ),
815
824
  schedule?.description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "font-body text-body text-center m-0 text-(--color-accent,#A89B83)", children: schedule.description })
816
825
  ] }),
817
826
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "w-full flex flex-col items-end gap-3", children: [
@@ -4250,6 +4259,34 @@ function ToggleGroupItem({
4250
4259
  );
4251
4260
  }
4252
4261
 
4262
+ // src/ui/drag-handle.tsx
4263
+ var React3 = __toESM(require("react"), 1);
4264
+ var import_lucide_react = require("lucide-react");
4265
+ var import_jsx_runtime5 = require("react/jsx-runtime");
4266
+ var DragHandle = React3.forwardRef(
4267
+ ({ className, type = "button", ...props }, ref) => {
4268
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4269
+ "button",
4270
+ {
4271
+ ref,
4272
+ type,
4273
+ "data-slot": "drag-handle",
4274
+ className: cn(
4275
+ "inline-flex h-7 w-4 shrink-0 items-center justify-center rounded-md transition-all duration-200 max-h-[30px]",
4276
+ "bg-white border border-transparent text-stone-500 shadow-md cursor-grab",
4277
+ "enabled:hover:border enabled:hover:border-stone-200 enabled:hover:text-stone-950",
4278
+ "enabled:active:border enabled:active:border-primary enabled:active:bg-primary-50 enabled:active:text-stone-950 enabled:active:shadow enabled:active:cursor-grabbing",
4279
+ "disabled:cursor-not-allowed disabled:opacity-40 disabled:text-stone-950 disabled:pointer-events-none",
4280
+ className
4281
+ ),
4282
+ ...props,
4283
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react.GripVertical, { className: "size-4 shrink-0", "aria-hidden": "true" })
4284
+ }
4285
+ );
4286
+ }
4287
+ );
4288
+ DragHandle.displayName = "DragHandle";
4289
+
4253
4290
  // src/OhhwellsBridge.tsx
4254
4291
  var import_react_dom2 = require("react-dom");
4255
4292
  var import_navigation = require("next/navigation");
@@ -4529,60 +4566,60 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
4529
4566
  }
4530
4567
 
4531
4568
  // src/ui/dialog.tsx
4532
- var React3 = __toESM(require("react"), 1);
4569
+ var React4 = __toESM(require("react"), 1);
4533
4570
  var import_radix_ui3 = require("radix-ui");
4534
4571
 
4535
4572
  // src/ui/icons.tsx
4536
- var import_jsx_runtime5 = require("react/jsx-runtime");
4573
+ var import_jsx_runtime6 = require("react/jsx-runtime");
4537
4574
  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" })
4575
+ 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: [
4576
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M18 6 6 18" }),
4577
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "m6 6 12 12" })
4541
4578
  ] });
4542
4579
  }
4543
4580
  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" }) });
4581
+ 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
4582
  }
4546
4583
  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" })
4584
+ 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: [
4585
+ /* @__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" }),
4586
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" })
4550
4587
  ] });
4551
4588
  }
4552
4589
  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" })
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)("circle", { cx: "12", cy: "12", r: "10" }),
4592
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M12 16v-4" }),
4593
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M12 8h.01" })
4557
4594
  ] });
4558
4595
  }
4559
4596
  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" })
4597
+ 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: [
4598
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M5 12h14" }),
4599
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "m12 5 7 7-7 7" })
4563
4600
  ] });
4564
4601
  }
4565
4602
  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" })
4603
+ 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: [
4604
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { width: "18", height: "7", x: "3", y: "3", rx: "1" }),
4605
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { width: "9", height: "7", x: "3", y: "14", rx: "1" }),
4606
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("rect", { width: "5", height: "7", x: "16", y: "14", rx: "1" })
4570
4607
  ] });
4571
4608
  }
4572
4609
 
4573
4610
  // src/ui/dialog.tsx
4574
- var import_jsx_runtime6 = require("react/jsx-runtime");
4611
+ var import_jsx_runtime7 = require("react/jsx-runtime");
4575
4612
  function Dialog2({ ...props }) {
4576
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_radix_ui3.Dialog.Root, { "data-slot": "dialog", ...props });
4613
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui3.Dialog.Root, { "data-slot": "dialog", ...props });
4577
4614
  }
4578
4615
  function DialogPortal({ ...props }) {
4579
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_radix_ui3.Dialog.Portal, { ...props });
4616
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui3.Dialog.Portal, { ...props });
4580
4617
  }
4581
4618
  function DialogOverlay({
4582
4619
  className,
4583
4620
  ...props
4584
4621
  }) {
4585
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4622
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4586
4623
  import_radix_ui3.Dialog.Overlay,
4587
4624
  {
4588
4625
  "data-slot": "dialog-overlay",
@@ -4592,11 +4629,11 @@ function DialogOverlay({
4592
4629
  }
4593
4630
  );
4594
4631
  }
4595
- var DialogContent = React3.forwardRef(({ className, children, showCloseButton = true, container, ...props }, ref) => {
4632
+ var DialogContent = React4.forwardRef(({ className, children, showCloseButton = true, container, ...props }, ref) => {
4596
4633
  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)(
4634
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(DialogPortal, { container: container ?? void 0, children: [
4635
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
4636
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
4600
4637
  import_radix_ui3.Dialog.Content,
4601
4638
  {
4602
4639
  ref,
@@ -4612,13 +4649,13 @@ var DialogContent = React3.forwardRef(({ className, children, showCloseButton =
4612
4649
  ...props,
4613
4650
  children: [
4614
4651
  children,
4615
- showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4652
+ showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4616
4653
  import_radix_ui3.Dialog.Close,
4617
4654
  {
4618
4655
  type: "button",
4619
4656
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
4620
4657
  "aria-label": "Close",
4621
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(IconX, { "aria-hidden": true })
4658
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconX, { "aria-hidden": true })
4622
4659
  }
4623
4660
  ) : null
4624
4661
  ]
@@ -4628,12 +4665,12 @@ var DialogContent = React3.forwardRef(({ className, children, showCloseButton =
4628
4665
  });
4629
4666
  DialogContent.displayName = import_radix_ui3.Dialog.Content.displayName;
4630
4667
  function DialogHeader({ className, ...props }) {
4631
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
4668
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
4632
4669
  }
4633
4670
  function DialogFooter({ className, ...props }) {
4634
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: cn("flex items-center justify-end gap-2", className), ...props });
4671
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: cn("flex items-center justify-end gap-2", className), ...props });
4635
4672
  }
4636
- var DialogTitle = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4673
+ var DialogTitle = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4637
4674
  import_radix_ui3.Dialog.Title,
4638
4675
  {
4639
4676
  ref,
@@ -4642,7 +4679,7 @@ var DialogTitle = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE
4642
4679
  }
4643
4680
  ));
4644
4681
  DialogTitle.displayName = import_radix_ui3.Dialog.Title.displayName;
4645
- var DialogDescription = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4682
+ var DialogDescription = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4646
4683
  import_radix_ui3.Dialog.Description,
4647
4684
  {
4648
4685
  ref,
@@ -4654,9 +4691,9 @@ DialogDescription.displayName = import_radix_ui3.Dialog.Description.displayName;
4654
4691
  var DialogClose = import_radix_ui3.Dialog.Close;
4655
4692
 
4656
4693
  // src/ui/button.tsx
4657
- var React4 = __toESM(require("react"), 1);
4694
+ var React5 = __toESM(require("react"), 1);
4658
4695
  var import_radix_ui4 = require("radix-ui");
4659
- var import_jsx_runtime7 = require("react/jsx-runtime");
4696
+ var import_jsx_runtime8 = require("react/jsx-runtime");
4660
4697
  var buttonVariants = cva(
4661
4698
  "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
4699
  {
@@ -4677,10 +4714,10 @@ var buttonVariants = cva(
4677
4714
  }
4678
4715
  }
4679
4716
  );
4680
- var Button = React4.forwardRef(
4717
+ var Button = React5.forwardRef(
4681
4718
  ({ className, variant, size, asChild = false, ...props }, ref) => {
4682
4719
  const Comp = asChild ? import_radix_ui4.Slot.Root : "button";
4683
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4720
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4684
4721
  Comp,
4685
4722
  {
4686
4723
  ref,
@@ -4694,37 +4731,37 @@ var Button = React4.forwardRef(
4694
4731
  Button.displayName = "Button";
4695
4732
 
4696
4733
  // src/ui/link-modal/DestinationBreadcrumb.tsx
4697
- var import_jsx_runtime8 = require("react/jsx-runtime");
4734
+ var import_jsx_runtime9 = require("react/jsx-runtime");
4698
4735
  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 })
4736
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex w-full flex-col gap-2", children: [
4737
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-sm font-medium text-foreground", children: "Destination" }),
4738
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center gap-3", children: [
4739
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center gap-2", children: [
4740
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconFile, { className: "shrink-0 text-foreground", "aria-hidden": true }),
4741
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-sm font-medium leading-none text-foreground", children: pageTitle })
4705
4742
  ] }),
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 })
4743
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconArrowRight, { className: "shrink-0 text-muted-foreground", "aria-hidden": true }),
4744
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex min-w-0 flex-1 items-center gap-2", 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-medium leading-none text-foreground", children: sectionLabel })
4710
4747
  ] })
4711
4748
  ] })
4712
4749
  ] });
4713
4750
  }
4714
4751
 
4715
4752
  // src/ui/link-modal/SectionTreeItem.tsx
4716
- var import_jsx_runtime9 = require("react/jsx-runtime");
4753
+ var import_jsx_runtime10 = require("react/jsx-runtime");
4717
4754
  function SectionTreeItem({ section, onSelect, selected }) {
4718
4755
  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)(
4756
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex h-9 w-full items-end pl-3", children: [
4757
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4721
4758
  "div",
4722
4759
  {
4723
4760
  className: "mr-[-1px] h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
4724
4761
  "aria-hidden": true
4725
4762
  }
4726
4763
  ),
4727
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
4764
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
4728
4765
  "div",
4729
4766
  {
4730
4767
  role: interactive ? "button" : void 0,
@@ -4742,8 +4779,8 @@ function SectionTreeItem({ section, onSelect, selected }) {
4742
4779
  interactive && selected && "border-primary"
4743
4780
  ),
4744
4781
  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 })
4782
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconSection, { className: "shrink-0 text-foreground", "aria-hidden": true }),
4783
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
4747
4784
  ]
4748
4785
  }
4749
4786
  )
@@ -4751,11 +4788,11 @@ function SectionTreeItem({ section, onSelect, selected }) {
4751
4788
  }
4752
4789
  function SectionPickerList({ sections, onSelect }) {
4753
4790
  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." });
4791
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." });
4755
4792
  }
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))
4793
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-1", children: [
4794
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "text-sm text-muted-foreground", children: "Pick a section this link should scroll to." }),
4795
+ sections.map((section) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SectionTreeItem, { section, onSelect }, section.id))
4759
4796
  ] });
4760
4797
  }
4761
4798
 
@@ -4763,11 +4800,11 @@ function SectionPickerList({ sections, onSelect }) {
4763
4800
  var import_react4 = require("react");
4764
4801
 
4765
4802
  // 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(
4803
+ var React6 = __toESM(require("react"), 1);
4804
+ var import_jsx_runtime11 = require("react/jsx-runtime");
4805
+ var Input = React6.forwardRef(
4769
4806
  ({ className, type, ...props }, ref) => {
4770
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4807
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
4771
4808
  "input",
4772
4809
  {
4773
4810
  type,
@@ -4786,9 +4823,9 @@ Input.displayName = "Input";
4786
4823
 
4787
4824
  // src/ui/label.tsx
4788
4825
  var import_radix_ui5 = require("radix-ui");
4789
- var import_jsx_runtime11 = require("react/jsx-runtime");
4826
+ var import_jsx_runtime12 = require("react/jsx-runtime");
4790
4827
  function Label({ className, ...props }) {
4791
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
4828
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4792
4829
  import_radix_ui5.Label.Root,
4793
4830
  {
4794
4831
  "data-slot": "label",
@@ -4799,9 +4836,9 @@ function Label({ className, ...props }) {
4799
4836
  }
4800
4837
 
4801
4838
  // src/ui/link-modal/UrlOrPageInput.tsx
4802
- var import_jsx_runtime12 = require("react/jsx-runtime");
4839
+ var import_jsx_runtime13 = require("react/jsx-runtime");
4803
4840
  function FieldChevron({ onClick }) {
4804
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4841
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4805
4842
  "button",
4806
4843
  {
4807
4844
  type: "button",
@@ -4809,7 +4846,7 @@ function FieldChevron({ onClick }) {
4809
4846
  onClick,
4810
4847
  "aria-label": "Open page list",
4811
4848
  tabIndex: -1,
4812
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconChevronDown, {})
4849
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconChevronDown, {})
4813
4850
  }
4814
4851
  );
4815
4852
  }
@@ -4848,12 +4885,12 @@ function UrlOrPageInput({
4848
4885
  "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
4886
  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
4887
  );
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)(
4888
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex w-full flex-col gap-2 p-0", children: [
4889
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
4890
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "relative w-full", children: [
4891
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
4892
+ 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,
4893
+ 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
4894
  Input,
4858
4895
  {
4859
4896
  ref: inputRef,
@@ -4872,7 +4909,7 @@ function UrlOrPageInput({
4872
4909
  )
4873
4910
  }
4874
4911
  ),
4875
- selectedPage && !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4912
+ selectedPage && !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4876
4913
  "button",
4877
4914
  {
4878
4915
  type: "button",
@@ -4880,26 +4917,26 @@ function UrlOrPageInput({
4880
4917
  onMouseDown: clearSelection,
4881
4918
  "aria-label": "Clear selected page",
4882
4919
  tabIndex: -1,
4883
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconX, { "aria-hidden": true })
4920
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconX, { "aria-hidden": true })
4884
4921
  }
4885
4922
  ) : null,
4886
- !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(FieldChevron, { onClick: toggleDropdown }) : null
4923
+ !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(FieldChevron, { onClick: toggleDropdown }) : null
4887
4924
  ] }),
4888
- dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4925
+ dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
4889
4926
  "div",
4890
4927
  {
4891
4928
  "data-ohw-link-page-dropdown": "",
4892
4929
  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
4930
  onMouseDown: (e) => e.preventDefault(),
4894
- children: filteredPages.map((page) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
4931
+ children: filteredPages.map((page) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
4895
4932
  "button",
4896
4933
  {
4897
4934
  type: "button",
4898
4935
  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
4936
  onClick: () => onPageSelect(page),
4900
4937
  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 })
4938
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconFile, { className: "shrink-0", "aria-hidden": true }),
4939
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "truncate", children: page.title })
4903
4940
  ]
4904
4941
  },
4905
4942
  page.path
@@ -4907,7 +4944,7 @@ function UrlOrPageInput({
4907
4944
  }
4908
4945
  ) : null
4909
4946
  ] }),
4910
- urlError ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
4947
+ urlError ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
4911
4948
  ] });
4912
4949
  }
4913
4950
 
@@ -5075,7 +5112,7 @@ function useLinkModalState({
5075
5112
  }
5076
5113
 
5077
5114
  // src/ui/link-modal/LinkEditorPanel.tsx
5078
- var import_jsx_runtime13 = require("react/jsx-runtime");
5115
+ var import_jsx_runtime14 = require("react/jsx-runtime");
5079
5116
  function LinkEditorPanel({
5080
5117
  open = true,
5081
5118
  mode = "create",
@@ -5099,25 +5136,25 @@ function LinkEditorPanel({
5099
5136
  onSubmit
5100
5137
  });
5101
5138
  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)(
5139
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
5140
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DialogClose, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5104
5141
  "button",
5105
5142
  {
5106
5143
  type: "button",
5107
5144
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
5108
5145
  "aria-label": "Close",
5109
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconX, { "aria-hidden": true })
5146
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(IconX, { "aria-hidden": true })
5110
5147
  }
5111
5148
  ) }),
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)(
5149
+ /* @__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 }) }),
5150
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
5151
+ state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5115
5152
  DestinationBreadcrumb,
5116
5153
  {
5117
5154
  pageTitle: state.selectedPage.title,
5118
5155
  sectionLabel: state.selectedSection.label
5119
5156
  }
5120
- ) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5157
+ ) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5121
5158
  UrlOrPageInput,
5122
5159
  {
5123
5160
  value: state.searchValue,
@@ -5130,18 +5167,18 @@ function LinkEditorPanel({
5130
5167
  urlError: state.urlError
5131
5168
  }
5132
5169
  ),
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." })
5170
+ state.showChooseSection ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex flex-col justify-center gap-2", children: [
5171
+ /* @__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" }),
5172
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
5173
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(IconInfo, { className: "shrink-0", "aria-hidden": true }),
5174
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: "Pick a section this link should scroll to." })
5138
5175
  ] })
5139
5176
  ] }) : 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
5177
+ state.showSectionPicker ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(SectionPickerList, { sections: state.activeSections, onSelect: state.handleSectionSelect }) : null,
5178
+ state.showSectionRow && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
5142
5179
  ] }),
5143
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(DialogFooter, { className: "w-full px-6 pb-6", children: [
5144
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5180
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(DialogFooter, { className: "w-full px-6 pb-6", children: [
5181
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5145
5182
  Button,
5146
5183
  {
5147
5184
  type: "button",
@@ -5156,7 +5193,7 @@ function LinkEditorPanel({
5156
5193
  children: state.secondaryLabel
5157
5194
  }
5158
5195
  ),
5159
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5196
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5160
5197
  Button,
5161
5198
  {
5162
5199
  type: "button",
@@ -5175,7 +5212,7 @@ function LinkEditorPanel({
5175
5212
  }
5176
5213
 
5177
5214
  // src/ui/link-modal/LinkPopover.tsx
5178
- var import_jsx_runtime14 = require("react/jsx-runtime");
5215
+ var import_jsx_runtime15 = require("react/jsx-runtime");
5179
5216
  function LinkPopover({
5180
5217
  open = true,
5181
5218
  panelRef,
@@ -5183,14 +5220,14 @@ function LinkPopover({
5183
5220
  onClose,
5184
5221
  ...editorProps
5185
5222
  }) {
5186
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5223
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5187
5224
  Dialog2,
5188
5225
  {
5189
5226
  open,
5190
5227
  onOpenChange: (next) => {
5191
5228
  if (!next) onClose?.();
5192
5229
  },
5193
- children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5230
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5194
5231
  DialogContent,
5195
5232
  {
5196
5233
  ref: panelRef,
@@ -5200,7 +5237,7 @@ function LinkPopover({
5200
5237
  "data-ohw-bridge": "",
5201
5238
  showCloseButton: false,
5202
5239
  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 })
5240
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(LinkEditorPanel, { ...editorProps, open, onClose })
5204
5241
  }
5205
5242
  )
5206
5243
  }
@@ -5266,7 +5303,7 @@ function shouldUseDevFixtures() {
5266
5303
  }
5267
5304
 
5268
5305
  // src/ui/badge.tsx
5269
- var import_jsx_runtime15 = require("react/jsx-runtime");
5306
+ var import_jsx_runtime16 = require("react/jsx-runtime");
5270
5307
  var badgeVariants = cva(
5271
5308
  "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
5309
  {
@@ -5284,11 +5321,11 @@ var badgeVariants = cva(
5284
5321
  }
5285
5322
  );
5286
5323
  function Badge({ className, variant, ...props }) {
5287
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
5324
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
5288
5325
  }
5289
5326
 
5290
5327
  // src/OhhwellsBridge.tsx
5291
- var import_jsx_runtime16 = require("react/jsx-runtime");
5328
+ var import_jsx_runtime17 = require("react/jsx-runtime");
5292
5329
  var PRIMARY = "#0885FE";
5293
5330
  var IMAGE_FADE_MS = 300;
5294
5331
  function runOpacityFade(el, onDone) {
@@ -5462,7 +5499,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
5462
5499
  const root = (0, import_client.createRoot)(container);
5463
5500
  (0, import_react_dom.flushSync)(() => {
5464
5501
  root.render(
5465
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5502
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5466
5503
  SchedulingWidget,
5467
5504
  {
5468
5505
  notifyOnConnect,
@@ -5510,6 +5547,20 @@ function applyLinkHref(el, val) {
5510
5547
  const anchor = el instanceof HTMLAnchorElement ? el : el.querySelector("a");
5511
5548
  if (anchor) anchor.setAttribute("href", val);
5512
5549
  }
5550
+ function getEditMeasureEl(editable) {
5551
+ return editable.closest("[data-ohw-href-key]") ?? editable;
5552
+ }
5553
+ function isDragHandleDisabled(el) {
5554
+ const carriers = [
5555
+ el.closest("[data-ohw-href-key]"),
5556
+ el.closest("[data-ohw-editable]")
5557
+ ];
5558
+ return carriers.some((carrier) => {
5559
+ if (!carrier) return false;
5560
+ const raw = carrier.getAttribute("data-ohw-drag-disabled");
5561
+ return raw === "true" || raw === "";
5562
+ });
5563
+ }
5513
5564
  function collectEditableNodes() {
5514
5565
  const nodes = Array.from(document.querySelectorAll("[data-ohw-editable]")).map((el) => {
5515
5566
  if (el.dataset.ohwEditable === "image") {
@@ -5563,6 +5614,14 @@ function getHrefKeyFromElement(el) {
5563
5614
  function isNavbarButton(el) {
5564
5615
  return Boolean(el.closest('[data-ohw-role="navbar-button"]'));
5565
5616
  }
5617
+ function getReorderHandleState(el) {
5618
+ const linkEl = el.closest("[data-ohw-href-key]");
5619
+ if (!linkEl || isNavbarButton(el)) return { key: null, disabled: false };
5620
+ return {
5621
+ key: linkEl.dataset.ohwHrefKey ?? null,
5622
+ disabled: isDragHandleDisabled(el)
5623
+ };
5624
+ }
5566
5625
  function clearHrefKeyHover(anchor) {
5567
5626
  anchor.removeAttribute("data-ohw-hovered");
5568
5627
  anchor.querySelectorAll("[data-ohw-hovered]").forEach((el) => {
@@ -5692,6 +5751,8 @@ var ICONS = {
5692
5751
  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
5752
  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
5753
  };
5754
+ var TOOLBAR_PILL_PADDING = 2;
5755
+ var TOOLBAR_TOGGLE_GAP = 4;
5695
5756
  var TOOLBAR_GROUPS = [
5696
5757
  [
5697
5758
  { cmd: "bold", title: "Bold" },
@@ -5709,24 +5770,64 @@ var TOOLBAR_GROUPS = [
5709
5770
  { cmd: "insertOrderedList", title: "Numbered List" }
5710
5771
  ]
5711
5772
  ];
5712
- function GlowFrame({ rect, elRef }) {
5773
+ function EditGlowChrome({
5774
+ rect,
5775
+ elRef,
5776
+ reorderHrefKey,
5777
+ dragDisabled = false
5778
+ }) {
5713
5779
  const GAP = 6;
5714
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5780
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
5715
5781
  "div",
5716
5782
  {
5717
5783
  ref: elRef,
5784
+ "data-ohw-edit-chrome": "",
5718
5785
  style: {
5719
5786
  position: "fixed",
5720
5787
  top: rect.top - GAP,
5721
5788
  left: rect.left - GAP,
5722
5789
  width: rect.width + GAP * 2,
5723
5790
  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
5791
  pointerEvents: "none",
5728
5792
  zIndex: 2147483646
5729
- }
5793
+ },
5794
+ children: [
5795
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5796
+ "div",
5797
+ {
5798
+ style: {
5799
+ position: "absolute",
5800
+ inset: 0,
5801
+ border: "2px solid #0885FE",
5802
+ borderRadius: 8,
5803
+ boxShadow: "0 0 0 4px rgba(8, 133, 254, 0.12)",
5804
+ pointerEvents: "none"
5805
+ }
5806
+ }
5807
+ ),
5808
+ reorderHrefKey && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5809
+ "div",
5810
+ {
5811
+ "data-ohw-drag-handle-container": "",
5812
+ "data-ohw-drag-disabled": dragDisabled ? "" : void 0,
5813
+ style: {
5814
+ position: "absolute",
5815
+ left: 0,
5816
+ top: "50%",
5817
+ transform: "translate(calc(-100% - 7px), -50%)",
5818
+ pointerEvents: dragDisabled ? "none" : "auto"
5819
+ },
5820
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5821
+ DragHandle,
5822
+ {
5823
+ "aria-label": `Reorder ${reorderHrefKey}`,
5824
+ disabled: dragDisabled,
5825
+ "aria-disabled": dragDisabled
5826
+ }
5827
+ )
5828
+ }
5829
+ )
5830
+ ]
5730
5831
  }
5731
5832
  );
5732
5833
  }
@@ -5770,9 +5871,9 @@ function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
5770
5871
  const pinnedTop = Math.min(maxBottom - approxH, Math.max(minTop, clip.top + gap));
5771
5872
  return { top: pinnedTop + approxH, transform: "translateX(-50%) translateY(-100%)" };
5772
5873
  }
5773
- function calcToolbarPos(rect, parentScroll, approxW = 330) {
5874
+ function calcToolbarPos(rect, parentScroll, approxW = 306) {
5774
5875
  const GAP = 8;
5775
- const APPROX_H = 36;
5876
+ const APPROX_H = 32;
5776
5877
  const APPROX_W = approxW;
5777
5878
  const clip = getIframeVisibleClip(parentScroll);
5778
5879
  const clipTop = clip?.top ?? 0;
@@ -5806,9 +5907,9 @@ function calcToolbarPos(rect, parentScroll, approxW = 330) {
5806
5907
  const left = Math.max(GAP + APPROX_W / 2, Math.min(rawLeft, window.innerWidth - GAP - APPROX_W / 2));
5807
5908
  return { top, left, transform };
5808
5909
  }
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" })
5910
+ 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: [
5911
+ /* @__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" }),
5912
+ /* @__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
5913
  ] });
5813
5914
  function FloatingToolbar({
5814
5915
  rect,
@@ -5820,10 +5921,10 @@ function FloatingToolbar({
5820
5921
  showEditLink,
5821
5922
  onEditLink
5822
5923
  }) {
5823
- const approxW = variant === "link-action" ? 120 : 330;
5924
+ const approxW = variant === "link-action" ? 112 : 306;
5824
5925
  const { top, left, transform } = calcToolbarPos(rect, parentScroll, approxW);
5825
5926
  if (variant === "link-action") {
5826
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
5927
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
5827
5928
  "div",
5828
5929
  {
5829
5930
  ref: elRef,
@@ -5840,15 +5941,15 @@ function FloatingToolbar({
5840
5941
  boxShadow: "0px 2px 4px -2px rgba(0,0,0,.1),0px 4px 6px -1px rgba(0,0,0,.1)",
5841
5942
  display: "flex",
5842
5943
  alignItems: "center",
5843
- padding: 4,
5844
- gap: 6,
5944
+ padding: TOOLBAR_PILL_PADDING,
5945
+ gap: TOOLBAR_TOGGLE_GAP,
5845
5946
  fontFamily: "sans-serif",
5846
5947
  pointerEvents: "auto",
5847
5948
  whiteSpace: "nowrap"
5848
5949
  },
5849
5950
  onMouseDown: (e) => e.stopPropagation(),
5850
5951
  children: [
5851
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5952
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5852
5953
  "button",
5853
5954
  {
5854
5955
  type: "button",
@@ -5883,8 +5984,8 @@ function FloatingToolbar({
5883
5984
  children: EDIT_LINK_ICON
5884
5985
  }
5885
5986
  ),
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)(
5987
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: { display: "block", width: 1, height: 24, background: "#E7E5E4", flexShrink: 0 } }),
5988
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5888
5989
  "button",
5889
5990
  {
5890
5991
  type: "button",
@@ -5903,10 +6004,10 @@ function FloatingToolbar({
5903
6004
  padding: 6,
5904
6005
  opacity: 0.6
5905
6006
  },
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" })
6007
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": true, children: [
6008
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("circle", { cx: "5", cy: "12", r: "1.5" }),
6009
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("circle", { cx: "12", cy: "12", r: "1.5" }),
6010
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("circle", { cx: "19", cy: "12", r: "1.5" })
5910
6011
  ] })
5911
6012
  }
5912
6013
  )
@@ -5914,7 +6015,7 @@ function FloatingToolbar({
5914
6015
  }
5915
6016
  );
5916
6017
  }
5917
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
6018
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
5918
6019
  "div",
5919
6020
  {
5920
6021
  ref: elRef,
@@ -5931,19 +6032,19 @@ function FloatingToolbar({
5931
6032
  boxShadow: "0px 2px 4px -2px rgba(0,0,0,.1),0px 4px 6px -1px rgba(0,0,0,.1)",
5932
6033
  display: "flex",
5933
6034
  alignItems: "center",
5934
- padding: 4,
5935
- gap: 6,
6035
+ padding: TOOLBAR_PILL_PADDING,
6036
+ gap: TOOLBAR_TOGGLE_GAP,
5936
6037
  fontFamily: "sans-serif",
5937
6038
  pointerEvents: "auto",
5938
6039
  whiteSpace: "nowrap"
5939
6040
  },
5940
6041
  onMouseDown: (e) => e.stopPropagation(),
5941
6042
  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 } }),
6043
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_react6.default.Fragment, { children: [
6044
+ gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: { display: "block", width: 1, height: 24, background: "#E7E5E4", flexShrink: 0 } }),
5944
6045
  btns.map((btn) => {
5945
6046
  const isActive = activeCommands.has(btn.cmd);
5946
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6047
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5947
6048
  "button",
5948
6049
  {
5949
6050
  title: btn.title,
@@ -5969,7 +6070,7 @@ function FloatingToolbar({
5969
6070
  flexShrink: 0,
5970
6071
  padding: 6
5971
6072
  },
5972
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6073
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5973
6074
  "svg",
5974
6075
  {
5975
6076
  width: "16",
@@ -5989,7 +6090,7 @@ function FloatingToolbar({
5989
6090
  );
5990
6091
  })
5991
6092
  ] }, gi)),
5992
- showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6093
+ showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5993
6094
  "button",
5994
6095
  {
5995
6096
  type: "button",
@@ -6038,7 +6139,7 @@ function StateToggle({
6038
6139
  states,
6039
6140
  onStateChange
6040
6141
  }) {
6041
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6142
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
6042
6143
  ToggleGroup,
6043
6144
  {
6044
6145
  "data-ohw-state-toggle": "",
@@ -6052,7 +6153,7 @@ function StateToggle({
6052
6153
  left: rect.right - 8,
6053
6154
  transform: "translateX(-100%)"
6054
6155
  },
6055
- children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
6156
+ children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
6056
6157
  }
6057
6158
  );
6058
6159
  }
@@ -6150,6 +6251,8 @@ function OhhwellsBridge() {
6150
6251
  const [toolbarVariant, setToolbarVariant] = (0, import_react6.useState)("none");
6151
6252
  const toolbarVariantRef = (0, import_react6.useRef)("none");
6152
6253
  toolbarVariantRef.current = toolbarVariant;
6254
+ const [reorderHrefKey, setReorderHrefKey] = (0, import_react6.useState)(null);
6255
+ const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react6.useState)(false);
6153
6256
  const [toggleState, setToggleState] = (0, import_react6.useState)(null);
6154
6257
  const [maxBadge, setMaxBadge] = (0, import_react6.useState)(null);
6155
6258
  const [activeCommands, setActiveCommands] = (0, import_react6.useState)(/* @__PURE__ */ new Set());
@@ -6256,7 +6359,7 @@ function OhhwellsBridge() {
6256
6359
  (0, import_react6.useEffect)(() => {
6257
6360
  const update = () => {
6258
6361
  const el = activeElRef.current ?? selectedElRef.current;
6259
- if (el) setToolbarRect(el.getBoundingClientRect());
6362
+ if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
6260
6363
  setToggleState((prev) => {
6261
6364
  if (!prev || !activeStateElRef.current) return prev;
6262
6365
  return { ...prev, rect: activeStateElRef.current.getBoundingClientRect() };
@@ -6323,6 +6426,8 @@ function OhhwellsBridge() {
6323
6426
  }
6324
6427
  el.removeAttribute("contenteditable");
6325
6428
  activeElRef.current = null;
6429
+ setReorderHrefKey(null);
6430
+ setReorderDragDisabled(false);
6326
6431
  if (!selectedElRef.current) {
6327
6432
  setToolbarRect(null);
6328
6433
  setToolbarVariant("none");
@@ -6360,11 +6465,15 @@ function OhhwellsBridge() {
6360
6465
  setToolbarVariant("rich-text");
6361
6466
  el.setAttribute("contenteditable", "true");
6362
6467
  el.removeAttribute("data-ohw-hovered");
6468
+ el.closest("[data-ohw-href-key]")?.removeAttribute("data-ohw-hovered");
6363
6469
  activeElRef.current = el;
6364
6470
  originalContentRef.current = el.innerHTML;
6365
6471
  el.focus();
6366
- setToolbarRect(el.getBoundingClientRect());
6367
6472
  setToolbarShowEditLink(Boolean(getHrefKeyFromElement(el)));
6473
+ const { key: reorderKey, disabled: reorderDisabled } = getReorderHandleState(el);
6474
+ setReorderHrefKey(reorderKey);
6475
+ setReorderDragDisabled(reorderDisabled);
6476
+ setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
6368
6477
  postToParent({ type: "ow:enter-edit", key: el.dataset.ohwKey });
6369
6478
  requestAnimationFrame(() => refreshActiveCommandsRef.current());
6370
6479
  }, [deactivate, postToParent]);
@@ -6429,30 +6538,36 @@ function OhhwellsBridge() {
6429
6538
  return () => {
6430
6539
  cancelled = true;
6431
6540
  };
6432
- }, [subdomain, isEditMode, pathname]);
6541
+ }, [subdomain, isEditMode]);
6433
6542
  (0, import_react6.useEffect)(() => {
6434
6543
  if (!subdomain || isEditMode) return;
6435
6544
  let debounceTimer = null;
6545
+ let observer = null;
6436
6546
  const applyFromCache = () => {
6437
6547
  const content = contentCache.get(subdomain);
6438
6548
  if (!content) return;
6439
6549
  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);
6550
+ observer?.disconnect();
6551
+ try {
6552
+ for (const [key, val] of Object.entries(content)) {
6553
+ if (key === "__ohw_sections") continue;
6554
+ document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
6555
+ if (el.dataset.ohwEditable === "image") {
6556
+ const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
6557
+ if (img && img.src !== val) img.src = val;
6558
+ } else if (el.dataset.ohwEditable === "bg-image") {
6559
+ const next = `url('${val}')`;
6560
+ if (el.style.backgroundImage !== next) el.style.backgroundImage = next;
6561
+ } else if (el.dataset.ohwEditable === "link") {
6562
+ applyLinkHref(el, val);
6563
+ } else if (el.innerHTML !== val) {
6564
+ el.innerHTML = val;
6565
+ }
6566
+ });
6567
+ applyLinkByKey(key, val);
6568
+ }
6569
+ } finally {
6570
+ observer?.observe(document.body, { childList: true, subtree: true });
6456
6571
  }
6457
6572
  enforceLinkHrefs();
6458
6573
  };
@@ -6460,11 +6575,11 @@ function OhhwellsBridge() {
6460
6575
  if (debounceTimer) clearTimeout(debounceTimer);
6461
6576
  debounceTimer = setTimeout(applyFromCache, 150);
6462
6577
  };
6463
- scheduleApply();
6464
- const observer = new MutationObserver(scheduleApply);
6578
+ applyFromCache();
6579
+ observer = new MutationObserver(scheduleApply);
6465
6580
  observer.observe(document.body, { childList: true, subtree: true });
6466
6581
  return () => {
6467
- observer.disconnect();
6582
+ observer?.disconnect();
6468
6583
  if (debounceTimer) clearTimeout(debounceTimer);
6469
6584
  };
6470
6585
  }, [subdomain, isEditMode, pathname]);
@@ -6588,6 +6703,11 @@ function OhhwellsBridge() {
6588
6703
  if (target.closest("[data-ohw-state-toggle]")) return;
6589
6704
  if (target.closest("[data-ohw-max-badge]")) return;
6590
6705
  if (isInsideLinkEditor(target)) return;
6706
+ if (target.closest('[data-ohw-edit-chrome], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
6707
+ e.preventDefault();
6708
+ e.stopPropagation();
6709
+ return;
6710
+ }
6591
6711
  const editable = target.closest("[data-ohw-editable]");
6592
6712
  if (editable) {
6593
6713
  if (editable.dataset.ohwEditable === "link") {
@@ -6664,14 +6784,18 @@ function OhhwellsBridge() {
6664
6784
  const selected = selectedElRef.current;
6665
6785
  if (selected && (selected === editable || selected.contains(editable))) return;
6666
6786
  if (editable.dataset.ohwEditable !== "image" && editable.dataset.ohwEditable !== "bg-image" && !editable.hasAttribute("contenteditable")) {
6667
- editable.setAttribute("data-ohw-hovered", "");
6787
+ const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
6788
+ hoverTarget.setAttribute("data-ohw-hovered", "");
6668
6789
  }
6669
6790
  };
6670
6791
  const handleMouseOut = (e) => {
6671
6792
  const editable = e.target.closest("[data-ohw-editable]");
6672
6793
  if (!editable) return;
6794
+ const related = e.relatedTarget instanceof Element ? e.relatedTarget : null;
6795
+ if (related?.closest("[data-ohw-drag-handle-container]")) return;
6673
6796
  if (editable.dataset.ohwEditable !== "image" && editable.dataset.ohwEditable !== "bg-image") {
6674
- editable.removeAttribute("data-ohw-hovered");
6797
+ const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
6798
+ hoverTarget.removeAttribute("data-ohw-hovered");
6675
6799
  }
6676
6800
  };
6677
6801
  const toProbeCoords = (clientX, clientY, fromParentViewport) => {
@@ -6786,11 +6910,20 @@ function OhhwellsBridge() {
6786
6910
  return;
6787
6911
  }
6788
6912
  }
6913
+ if (activeElRef.current) {
6914
+ if (hoveredImageRef.current) {
6915
+ hoveredImageRef.current = null;
6916
+ hoveredImageHasTextOverlapRef.current = false;
6917
+ resumeAnimTracks();
6918
+ postToParentRef.current({ type: "ow:image-unhover" });
6919
+ }
6920
+ return;
6921
+ }
6789
6922
  const imgEl = findImageAtPoint(clientX, clientY, fromParentViewport);
6790
6923
  if (imgEl) {
6791
6924
  const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
6792
6925
  const topEl = document.elementFromPoint(x, y);
6793
- if (topEl?.closest("[data-ohw-toolbar]")) {
6926
+ if (topEl?.closest('[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
6794
6927
  if (hoveredImageRef.current) {
6795
6928
  hoveredImageRef.current = null;
6796
6929
  resumeAnimTracks();
@@ -7083,7 +7216,7 @@ function OhhwellsBridge() {
7083
7216
  const el = e.target;
7084
7217
  const key = el.dataset.ohwKey;
7085
7218
  if (!key) return;
7086
- if (el === activeElRef.current) setToolbarRect(el.getBoundingClientRect());
7219
+ if (el === activeElRef.current) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
7087
7220
  const maxLen = el.dataset.ohwMaxLength ? parseInt(el.dataset.ohwMaxLength, 10) : null;
7088
7221
  if (maxLen) {
7089
7222
  const current = el.innerText.replace(/\n$/, "").length;
@@ -7313,7 +7446,7 @@ function OhhwellsBridge() {
7313
7446
  };
7314
7447
  const applyToolbarPos = (rect) => {
7315
7448
  const ps = parentScrollRef.current;
7316
- const approxW = toolbarVariantRef.current === "link-action" ? 120 : 330;
7449
+ const approxW = toolbarVariantRef.current === "link-action" ? 112 : 306;
7317
7450
  if (toolbarElRef.current) {
7318
7451
  const { top, left, transform } = calcToolbarPos(rect, ps, approxW);
7319
7452
  toolbarElRef.current.style.top = `${top}px`;
@@ -7492,7 +7625,7 @@ function OhhwellsBridge() {
7492
7625
  const handleCommand = (0, import_react6.useCallback)((cmd) => {
7493
7626
  document.execCommand(cmd, false);
7494
7627
  activeElRef.current?.focus();
7495
- if (activeElRef.current) setToolbarRect(activeElRef.current.getBoundingClientRect());
7628
+ if (activeElRef.current) setToolbarRect(getEditMeasureEl(activeElRef.current).getBoundingClientRect());
7496
7629
  refreshActiveCommandsRef.current();
7497
7630
  }, []);
7498
7631
  const handleStateChange = (0, import_react6.useCallback)((state) => {
@@ -7545,11 +7678,19 @@ function OhhwellsBridge() {
7545
7678
  const currentSections = sectionsByPath[pathname] ?? [];
7546
7679
  linkPopoverOpenRef.current = linkPopover !== null;
7547
7680
  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)(
7681
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
7682
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
7683
+ toolbarRect && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
7684
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
7685
+ EditGlowChrome,
7686
+ {
7687
+ rect: toolbarRect,
7688
+ elRef: glowElRef,
7689
+ reorderHrefKey,
7690
+ dragDisabled: reorderDragDisabled
7691
+ }
7692
+ ),
7693
+ toolbarVariant === "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
7553
7694
  FloatingToolbar,
7554
7695
  {
7555
7696
  variant: "rich-text",
@@ -7562,7 +7703,7 @@ function OhhwellsBridge() {
7562
7703
  onEditLink: openLinkPopoverForActive
7563
7704
  }
7564
7705
  ),
7565
- toolbarVariant === "link-action" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
7706
+ toolbarVariant === "link-action" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
7566
7707
  FloatingToolbar,
7567
7708
  {
7568
7709
  variant: "link-action",
@@ -7575,7 +7716,7 @@ function OhhwellsBridge() {
7575
7716
  }
7576
7717
  )
7577
7718
  ] }),
7578
- maxBadge && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
7719
+ maxBadge && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
7579
7720
  "div",
7580
7721
  {
7581
7722
  "data-ohw-max-badge": "",
@@ -7601,7 +7742,7 @@ function OhhwellsBridge() {
7601
7742
  ]
7602
7743
  }
7603
7744
  ),
7604
- toggleState && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
7745
+ toggleState && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
7605
7746
  StateToggle,
7606
7747
  {
7607
7748
  rect: toggleState.rect,
@@ -7610,15 +7751,15 @@ function OhhwellsBridge() {
7610
7751
  onStateChange: handleStateChange
7611
7752
  }
7612
7753
  ),
7613
- sectionGap && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
7754
+ sectionGap && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
7614
7755
  "div",
7615
7756
  {
7616
7757
  "data-ohw-section-insert-line": "",
7617
7758
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
7618
7759
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
7619
7760
  children: [
7620
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
7621
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
7761
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
7762
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
7622
7763
  Badge,
7623
7764
  {
7624
7765
  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 +7772,11 @@ function OhhwellsBridge() {
7631
7772
  children: "Add Section"
7632
7773
  }
7633
7774
  ),
7634
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
7775
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
7635
7776
  ]
7636
7777
  }
7637
7778
  ),
7638
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
7779
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
7639
7780
  LinkPopover,
7640
7781
  {
7641
7782
  panelRef: linkPopoverPanelRef,
@@ -7650,13 +7791,39 @@ function OhhwellsBridge() {
7650
7791
  onSubmit: handleLinkPopoverSubmit
7651
7792
  },
7652
7793
  `${linkPopover.key}-${pathname}`
7653
- ) : null
7794
+ ) : null,
7795
+ sectionGap && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
7796
+ "div",
7797
+ {
7798
+ "data-ohw-section-insert-line": "",
7799
+ className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
7800
+ style: { top: sectionGap.y, transform: "translateY(-50%)" },
7801
+ children: [
7802
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
7803
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
7804
+ Badge,
7805
+ {
7806
+ 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",
7807
+ onClick: () => {
7808
+ window.parent.postMessage(
7809
+ { type: "ow:add-section", insertAfter: sectionGap.insertAfter, insertBefore: sectionGap.insertBefore },
7810
+ "*"
7811
+ );
7812
+ },
7813
+ children: "Add Section"
7814
+ }
7815
+ ),
7816
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
7817
+ ]
7818
+ }
7819
+ )
7654
7820
  ] }),
7655
7821
  bridgeRoot
7656
7822
  ) : null;
7657
7823
  }
7658
7824
  // Annotate the CommonJS export names for ESM import in node:
7659
7825
  0 && (module.exports = {
7826
+ DragHandle,
7660
7827
  LinkEditorPanel,
7661
7828
  LinkPopover,
7662
7829
  OhhwellsBridge,
@@ -7667,6 +7834,7 @@ function OhhwellsBridge() {
7667
7834
  buildTarget,
7668
7835
  filterAvailablePages,
7669
7836
  getEditModeInitialState,
7837
+ isEditSessionActive,
7670
7838
  isValidUrl,
7671
7839
  parseTarget,
7672
7840
  toggleVariants,