@ohhwells/bridge 0.1.34 → 0.1.36-next.45

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 React8, { useCallback as useCallback3, 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
 
@@ -45,12 +45,13 @@ function useLinkHrefGuardian(...deps) {
45
45
  }
46
46
 
47
47
  // src/ui/SchedulingWidget.tsx
48
- import { useEffect, useId, useMemo, useRef, useState as useState2 } from "react";
48
+ import { useCallback, useEffect, useId, useMemo, useRef, useState as useState2 } from "react";
49
49
 
50
50
  // src/ui/EmailCaptureModal.tsx
51
51
  import { useState } from "react";
52
52
  import { Dialog } from "radix-ui";
53
53
  import { jsx, jsxs } from "react/jsx-runtime";
54
+ var isValidEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
54
55
  function Spinner() {
55
56
  return /* @__PURE__ */ jsxs(
56
57
  "svg",
@@ -84,12 +85,17 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
84
85
  const [error, setError] = useState(null);
85
86
  const isBook = title === "Confirm your spot";
86
87
  const handleSubmit = async () => {
87
- if (!email.trim()) return;
88
+ const trimmed = email.trim();
89
+ if (!trimmed) return;
90
+ if (!isValidEmail(trimmed)) {
91
+ setError("Please enter a valid email address.");
92
+ return;
93
+ }
88
94
  setLoading(true);
89
95
  setError(null);
90
96
  try {
91
- await onSubmit(email.trim());
92
- setSubmittedEmail(email.trim());
97
+ await onSubmit(trimmed);
98
+ setSubmittedEmail(trimmed);
93
99
  setSuccess(true);
94
100
  } catch (e) {
95
101
  setError(e instanceof Error ? e.message : "Something went wrong. Please try again.");
@@ -164,7 +170,10 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
164
170
  {
165
171
  type: "email",
166
172
  value: email,
167
- onChange: (e) => setEmail(e.target.value),
173
+ onChange: (e) => {
174
+ setEmail(e.target.value);
175
+ if (error) setError(null);
176
+ },
168
177
  onKeyDown: handleKeyDown,
169
178
  placeholder: "hello@gmail.com",
170
179
  autoFocus: true,
@@ -221,12 +230,20 @@ function formatClassTime(cls) {
221
230
  const em = endTotal % 60;
222
231
  return `${h}:${cls.startTime.minutes}-${eh}:${String(em).padStart(2, "0")}`;
223
232
  }
233
+ function formatBookingLabel(cls) {
234
+ const price = cls.price;
235
+ const isFree = price === null || price === void 0 || `${price}` === "" || `${price}` === "0";
236
+ return isFree ? "Book for free" : `Book for ${cls.currency ?? ""} ${price}`.trim();
237
+ }
224
238
  function getBookingsOnDate(cls, date) {
225
239
  if (!cls.bookings?.length) return 0;
226
- const ds = date.toISOString().split("T")[0];
240
+ const target = new Date(date);
241
+ target.setHours(0, 0, 0, 0);
227
242
  return cls.bookings.filter((b) => {
228
243
  try {
229
- return new Date(b.classDate).toISOString().split("T")[0] === ds;
244
+ const bookingDate = new Date(b.classDate);
245
+ bookingDate.setHours(0, 0, 0, 0);
246
+ return bookingDate.getTime() === target.getTime();
230
247
  } catch {
231
248
  return false;
232
249
  }
@@ -530,7 +547,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
530
547
  if (!cls.id) return;
531
548
  onOpenModal?.(isFull ? "waitlist" : "book", cls.id, selectedDate);
532
549
  },
533
- children: isFull ? "Join Waitlist" : "Book Now"
550
+ children: isFull ? "Join Waitlist" : formatBookingLabel(cls)
534
551
  }
535
552
  )
536
553
  ] })
@@ -572,6 +589,17 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
572
589
  const [isHovered, setIsHovered] = useState2(false);
573
590
  const [modalState, setModalState] = useState2(null);
574
591
  const switchScheduleIdRef = useRef(null);
592
+ const liveScheduleIdRef = useRef(null);
593
+ const refetchLiveSchedule = useCallback(async () => {
594
+ const id = liveScheduleIdRef.current;
595
+ if (!id) return;
596
+ try {
597
+ const res = await fetch(`${API_URL}/api/schedule/id/${id}`);
598
+ const data = await res.json();
599
+ if (data?.id) setSchedule(data);
600
+ } catch {
601
+ }
602
+ }, []);
575
603
  const dates = useMemo(() => {
576
604
  const today = /* @__PURE__ */ new Date();
577
605
  today.setHours(0, 0, 0, 0);
@@ -591,6 +619,18 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
591
619
  }
592
620
  }
593
621
  }, [schedule, dates]);
622
+ useEffect(() => {
623
+ if (typeof window === "undefined") return;
624
+ const onVisible = () => {
625
+ if (!document.hidden) void refetchLiveSchedule();
626
+ };
627
+ window.addEventListener("focus", refetchLiveSchedule);
628
+ document.addEventListener("visibilitychange", onVisible);
629
+ return () => {
630
+ window.removeEventListener("focus", refetchLiveSchedule);
631
+ document.removeEventListener("visibilitychange", onVisible);
632
+ };
633
+ }, [refetchLiveSchedule]);
594
634
  useEffect(() => {
595
635
  if (typeof window === "undefined") return;
596
636
  const isInEditor = window.self !== window.top;
@@ -652,7 +692,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
652
692
  setLoading(false);
653
693
  return;
654
694
  }
655
- ;
695
+ liveScheduleIdRef.current = effectiveId;
656
696
  (async () => {
657
697
  try {
658
698
  const res = await fetch(`${API_URL}/api/schedule/id/${effectiveId}`);
@@ -709,18 +749,14 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
709
749
  const data = await res.json().catch(() => ({}));
710
750
  throw new Error(data?.message ?? "Something went wrong. Please try again.");
711
751
  }
752
+ await refetchLiveSchedule();
712
753
  };
713
754
  const handleReplaceSchedule = () => {
714
755
  setIsHovered(false);
715
- if (schedule) {
716
- window.parent.postMessage({
717
- type: "ow:schedule-connected",
718
- schedule: { id: schedule.id, name: schedule.name },
719
- insertAfter
720
- }, "*");
721
- } else {
722
- window.parent.postMessage({ type: "ow:scheduling-not-connected", insertAfter }, "*");
723
- }
756
+ window.parent.postMessage(
757
+ { type: "ow:scheduling-not-connected", insertAfter, currentScheduleId: schedule?.id },
758
+ "*"
759
+ );
724
760
  };
725
761
  if (!inEditor && !loading && !schedule) return null;
726
762
  const sectionId = `scheduling-${insertAfter}`;
@@ -763,7 +799,19 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
763
799
  ),
764
800
  /* @__PURE__ */ jsxs2("div", { className: "max-w-[1280px] mx-auto flex flex-col items-center gap-16", children: [
765
801
  /* @__PURE__ */ jsxs2("div", { className: "flex flex-col items-center gap-4", children: [
766
- /* @__PURE__ */ jsx2("h2", { className: "font-display text-4xl sm:text-5xl font-bold text-center m-0 text-(--color-dark,#200C02)", children: schedule?.name ?? "Book an appointment" }),
802
+ /* @__PURE__ */ jsx2(
803
+ "h2",
804
+ {
805
+ className: "font-display text-center m-0 text-(--color-dark,#200C02)",
806
+ style: {
807
+ fontSize: "var(--fs-section-h2, clamp(40px, 4.4vw, 64px))",
808
+ fontWeight: "var(--font-weight-heading, 400)",
809
+ lineHeight: 1.05,
810
+ letterSpacing: "-0.02em"
811
+ },
812
+ children: schedule?.name ?? "Book an appointment"
813
+ }
814
+ ),
767
815
  schedule?.description && /* @__PURE__ */ jsx2("p", { className: "font-body text-body text-center m-0 text-(--color-accent,#A89B83)", children: schedule.description })
768
816
  ] }),
769
817
  /* @__PURE__ */ jsxs2("div", { className: "w-full flex flex-col items-end gap-3", children: [
@@ -4202,6 +4250,336 @@ function ToggleGroupItem({
4202
4250
  );
4203
4251
  }
4204
4252
 
4253
+ // src/ui/drag-handle.tsx
4254
+ import * as React3 from "react";
4255
+ import { GripVertical } from "lucide-react";
4256
+ import { jsx as jsx5 } from "react/jsx-runtime";
4257
+ var DragHandle = React3.forwardRef(
4258
+ ({ className, type = "button", ...props }, ref) => {
4259
+ return /* @__PURE__ */ jsx5(
4260
+ "button",
4261
+ {
4262
+ ref,
4263
+ type,
4264
+ "data-slot": "drag-handle",
4265
+ className: cn(
4266
+ "inline-flex h-7 w-4 shrink-0 items-center justify-center rounded-md transition-all duration-200 max-h-[30px]",
4267
+ "bg-white border border-transparent text-stone-500 shadow-md cursor-grab",
4268
+ "enabled:hover:border enabled:hover:border-stone-200 enabled:hover:text-stone-950",
4269
+ "enabled:active:border enabled:active:border-primary enabled:active:bg-primary-50 enabled:active:text-stone-950 enabled:active:shadow enabled:active:cursor-grabbing",
4270
+ "disabled:cursor-not-allowed disabled:opacity-40 disabled:text-stone-950 disabled:pointer-events-none",
4271
+ className
4272
+ ),
4273
+ ...props,
4274
+ children: /* @__PURE__ */ jsx5(GripVertical, { className: "size-4 shrink-0", "aria-hidden": "true" })
4275
+ }
4276
+ );
4277
+ }
4278
+ );
4279
+ DragHandle.displayName = "DragHandle";
4280
+
4281
+ // src/ui/custom-toolbar.tsx
4282
+ import * as React4 from "react";
4283
+ import { jsx as jsx6 } from "react/jsx-runtime";
4284
+ var CustomToolbar = React4.forwardRef(({ className, onMouseDown, ...props }, ref) => /* @__PURE__ */ jsx6(
4285
+ "div",
4286
+ {
4287
+ ref,
4288
+ "data-ohw-toolbar": "",
4289
+ className: cn(
4290
+ "inline-flex items-center gap-1 rounded-lg border border-border bg-background p-0.5 font-sans whitespace-nowrap shadow-[0px_2px_4px_-2px_rgba(0,0,0,0.1),0px_4px_6px_-1px_rgba(0,0,0,0.1)]",
4291
+ className
4292
+ ),
4293
+ onMouseDown: (e) => {
4294
+ e.stopPropagation();
4295
+ onMouseDown?.(e);
4296
+ },
4297
+ ...props
4298
+ }
4299
+ ));
4300
+ CustomToolbar.displayName = "CustomToolbar";
4301
+ function CustomToolbarDivider({ className, ...props }) {
4302
+ return /* @__PURE__ */ jsx6(
4303
+ "span",
4304
+ {
4305
+ "aria-hidden": true,
4306
+ className: cn("block h-6 w-px shrink-0 bg-border", className),
4307
+ ...props
4308
+ }
4309
+ );
4310
+ }
4311
+ var CustomToolbarButton = React4.forwardRef(
4312
+ ({ className, active = false, type = "button", ...props }, ref) => /* @__PURE__ */ jsx6(
4313
+ "button",
4314
+ {
4315
+ ref,
4316
+ type,
4317
+ className: cn(
4318
+ "inline-flex shrink-0 items-center justify-center rounded p-1.5 transition-colors",
4319
+ active ? "bg-primary text-primary-foreground" : "bg-transparent text-foreground hover:bg-muted disabled:cursor-not-allowed disabled:text-muted-foreground disabled:opacity-60",
4320
+ className
4321
+ ),
4322
+ ...props
4323
+ }
4324
+ )
4325
+ );
4326
+ CustomToolbarButton.displayName = "CustomToolbarButton";
4327
+
4328
+ // src/ui/item-action-toolbar.tsx
4329
+ import { Link, MoreHorizontal, Plus } from "lucide-react";
4330
+
4331
+ // src/ui/tooltip.tsx
4332
+ import { Tooltip as TooltipPrimitive } from "radix-ui";
4333
+ import { jsx as jsx7 } from "react/jsx-runtime";
4334
+ function TooltipProvider({
4335
+ delayDuration = 0,
4336
+ ...props
4337
+ }) {
4338
+ return /* @__PURE__ */ jsx7(TooltipPrimitive.Provider, { "data-slot": "tooltip-provider", delayDuration, ...props });
4339
+ }
4340
+ function Tooltip({ ...props }) {
4341
+ return /* @__PURE__ */ jsx7(TooltipPrimitive.Root, { "data-slot": "tooltip", ...props });
4342
+ }
4343
+ function TooltipTrigger({ ...props }) {
4344
+ return /* @__PURE__ */ jsx7(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
4345
+ }
4346
+ var arrowClassBySide = {
4347
+ top: "before:bottom-0 before:left-1/2 before:-translate-x-1/2 before:translate-y-1/2",
4348
+ bottom: "before:top-0 before:left-1/2 before:-translate-x-1/2 before:-translate-y-1/2",
4349
+ left: "before:right-0 before:top-1/2 before:-translate-y-1/2 before:translate-x-1/2",
4350
+ right: "before:left-0 before:top-1/2 before:-translate-y-1/2 before:-translate-x-1/2"
4351
+ };
4352
+ function TooltipContent({
4353
+ className,
4354
+ sideOffset = 6,
4355
+ side = "bottom",
4356
+ children,
4357
+ ...props
4358
+ }) {
4359
+ const resolvedSide = side ?? "bottom";
4360
+ return /* @__PURE__ */ jsx7(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx7(
4361
+ TooltipPrimitive.Content,
4362
+ {
4363
+ "data-slot": "tooltip-content",
4364
+ side,
4365
+ sideOffset,
4366
+ className: cn(
4367
+ "relative z-[2147483647] w-fit max-w-xs rounded-md bg-foreground px-3 py-1.5 text-xs text-background shadow-md",
4368
+ 'before:pointer-events-none before:absolute before:size-2 before:rotate-45 before:bg-foreground before:content-[""]',
4369
+ arrowClassBySide[resolvedSide],
4370
+ "animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
4371
+ "data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2",
4372
+ "data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2",
4373
+ className
4374
+ ),
4375
+ ...props,
4376
+ children
4377
+ }
4378
+ ) });
4379
+ }
4380
+
4381
+ // src/ui/item-action-toolbar.tsx
4382
+ import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
4383
+ function ToolbarActionTooltip({
4384
+ label,
4385
+ side = "bottom",
4386
+ disabled = false,
4387
+ buttonProps,
4388
+ children
4389
+ }) {
4390
+ const button = /* @__PURE__ */ jsx8(CustomToolbarButton, { type: "button", "aria-label": label, disabled, ...buttonProps, children });
4391
+ return /* @__PURE__ */ jsxs3(Tooltip, { children: [
4392
+ /* @__PURE__ */ jsx8(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ jsx8("span", { className: "inline-flex", children: button }) : button }),
4393
+ /* @__PURE__ */ jsx8(TooltipContent, { side, children: label })
4394
+ ] });
4395
+ }
4396
+ function ItemActionToolbar({
4397
+ onEditLink,
4398
+ onAddItem,
4399
+ onMore,
4400
+ addItemDisabled = true,
4401
+ moreDisabled = true,
4402
+ tooltipSide = "bottom"
4403
+ }) {
4404
+ return /* @__PURE__ */ jsx8(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs3(CustomToolbar, { children: [
4405
+ /* @__PURE__ */ jsx8(
4406
+ ToolbarActionTooltip,
4407
+ {
4408
+ label: "Add link",
4409
+ side: tooltipSide,
4410
+ buttonProps: {
4411
+ onMouseDown: (e) => {
4412
+ e.preventDefault();
4413
+ e.stopPropagation();
4414
+ onEditLink?.();
4415
+ },
4416
+ onClick: (e) => {
4417
+ e.preventDefault();
4418
+ e.stopPropagation();
4419
+ }
4420
+ },
4421
+ children: /* @__PURE__ */ jsx8(Link, { className: "size-4 shrink-0", "aria-hidden": true })
4422
+ }
4423
+ ),
4424
+ /* @__PURE__ */ jsx8(CustomToolbarDivider, {}),
4425
+ /* @__PURE__ */ jsx8(
4426
+ ToolbarActionTooltip,
4427
+ {
4428
+ label: "Add item",
4429
+ side: tooltipSide,
4430
+ disabled: addItemDisabled,
4431
+ buttonProps: {
4432
+ onMouseDown: (e) => {
4433
+ if (addItemDisabled) return;
4434
+ e.preventDefault();
4435
+ e.stopPropagation();
4436
+ onAddItem?.();
4437
+ }
4438
+ },
4439
+ children: /* @__PURE__ */ jsx8(Plus, { className: "size-4 shrink-0", "aria-hidden": true })
4440
+ }
4441
+ ),
4442
+ /* @__PURE__ */ jsx8(CustomToolbarDivider, {}),
4443
+ /* @__PURE__ */ jsx8(
4444
+ ToolbarActionTooltip,
4445
+ {
4446
+ label: "More",
4447
+ side: tooltipSide,
4448
+ disabled: moreDisabled,
4449
+ buttonProps: {
4450
+ onMouseDown: (e) => {
4451
+ if (moreDisabled) return;
4452
+ e.preventDefault();
4453
+ e.stopPropagation();
4454
+ onMore?.();
4455
+ }
4456
+ },
4457
+ children: /* @__PURE__ */ jsx8(MoreHorizontal, { className: "size-4 shrink-0", "aria-hidden": true })
4458
+ }
4459
+ )
4460
+ ] }) });
4461
+ }
4462
+
4463
+ // src/ui/item-interaction-layer.tsx
4464
+ import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
4465
+ var PRIMARY = "var(--ohw-primary, #0885FE)";
4466
+ var FOCUS_RING = "0 0 0 4px rgba(8, 133, 254, 0.12)";
4467
+ var DRAG_SHADOW = "0px 4px 6px -1px rgba(0, 0, 0, 0.1), 0px 2px 4px -2px rgba(0, 0, 0, 0.1)";
4468
+ function getChromeStyle(state) {
4469
+ switch (state) {
4470
+ case "hover":
4471
+ return {
4472
+ border: `1.5px dashed ${PRIMARY}`,
4473
+ boxShadow: "none"
4474
+ };
4475
+ case "sibling-hint":
4476
+ return {
4477
+ border: `1.5px dashed color-mix(in srgb, ${PRIMARY} 30%, transparent)`,
4478
+ boxShadow: "none"
4479
+ };
4480
+ case "active-top":
4481
+ case "active-bottom":
4482
+ return {
4483
+ border: `2px solid ${PRIMARY}`,
4484
+ boxShadow: FOCUS_RING
4485
+ };
4486
+ case "dragging":
4487
+ return {
4488
+ border: `2px solid ${PRIMARY}`,
4489
+ boxShadow: DRAG_SHADOW
4490
+ };
4491
+ default:
4492
+ return {};
4493
+ }
4494
+ }
4495
+ function ItemInteractionLayer({
4496
+ rect,
4497
+ state,
4498
+ elRef,
4499
+ toolbar,
4500
+ showHandle = false,
4501
+ dragDisabled = false,
4502
+ dragHandleLabel = "Reorder item",
4503
+ onDragHandleDragStart,
4504
+ onDragHandleDragEnd,
4505
+ chromeGap = 6,
4506
+ className
4507
+ }) {
4508
+ if (state === "default") return null;
4509
+ const isActive = state === "active-top" || state === "active-bottom";
4510
+ const isDragging = state === "dragging";
4511
+ const showToolbar = isActive && toolbar;
4512
+ const showDragHandle = isActive && showHandle && !isDragging;
4513
+ return /* @__PURE__ */ jsxs4(
4514
+ "div",
4515
+ {
4516
+ ref: elRef,
4517
+ "data-ohw-item-interaction": "",
4518
+ "data-ohw-item-interaction-state": state,
4519
+ className: cn("pointer-events-none", className),
4520
+ style: {
4521
+ position: "fixed",
4522
+ top: rect.top - chromeGap,
4523
+ left: rect.left - chromeGap,
4524
+ width: rect.width + chromeGap * 2,
4525
+ height: rect.height + chromeGap * 2,
4526
+ zIndex: 2147483646
4527
+ },
4528
+ children: [
4529
+ /* @__PURE__ */ jsx9(
4530
+ "div",
4531
+ {
4532
+ "aria-hidden": true,
4533
+ className: "absolute inset-0 rounded-lg",
4534
+ style: getChromeStyle(state)
4535
+ }
4536
+ ),
4537
+ showDragHandle && /* @__PURE__ */ jsx9(
4538
+ "div",
4539
+ {
4540
+ "data-ohw-drag-handle-container": "",
4541
+ className: "pointer-events-auto absolute left-0 top-1/2 -translate-x-[calc(100%+7px)] -translate-y-1/2",
4542
+ children: /* @__PURE__ */ jsx9(
4543
+ DragHandle,
4544
+ {
4545
+ draggable: !dragDisabled,
4546
+ "aria-label": dragHandleLabel,
4547
+ disabled: dragDisabled,
4548
+ onDragStart: (e) => {
4549
+ if (dragDisabled) {
4550
+ e.preventDefault();
4551
+ return;
4552
+ }
4553
+ e.dataTransfer?.setData("text/plain", dragHandleLabel);
4554
+ e.dataTransfer.effectAllowed = "move";
4555
+ onDragHandleDragStart?.(e);
4556
+ },
4557
+ onDragEnd: onDragHandleDragEnd
4558
+ }
4559
+ )
4560
+ }
4561
+ ),
4562
+ showToolbar && state === "active-top" && /* @__PURE__ */ jsx9(
4563
+ "div",
4564
+ {
4565
+ className: "pointer-events-auto absolute bottom-full left-1/2 mb-2 -translate-x-1/2",
4566
+ "data-ohw-item-toolbar-anchor": "top",
4567
+ children: toolbar
4568
+ }
4569
+ ),
4570
+ showToolbar && state === "active-bottom" && /* @__PURE__ */ jsx9(
4571
+ "div",
4572
+ {
4573
+ className: "pointer-events-auto absolute left-1/2 top-full mt-2 -translate-x-1/2",
4574
+ "data-ohw-item-toolbar-anchor": "bottom",
4575
+ children: toolbar
4576
+ }
4577
+ )
4578
+ ]
4579
+ }
4580
+ );
4581
+ }
4582
+
4205
4583
  // src/OhhwellsBridge.tsx
4206
4584
  import { createPortal } from "react-dom";
4207
4585
  import { usePathname, useRouter, useSearchParams } from "next/navigation";
@@ -4481,60 +4859,60 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
4481
4859
  }
4482
4860
 
4483
4861
  // src/ui/dialog.tsx
4484
- import * as React3 from "react";
4862
+ import * as React5 from "react";
4485
4863
  import { Dialog as DialogPrimitive } from "radix-ui";
4486
4864
 
4487
4865
  // src/ui/icons.tsx
4488
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
4866
+ import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
4489
4867
  function IconX({ className, ...props }) {
4490
- 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" })
4868
+ return /* @__PURE__ */ jsxs5("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4869
+ /* @__PURE__ */ jsx10("path", { d: "M18 6 6 18" }),
4870
+ /* @__PURE__ */ jsx10("path", { d: "m6 6 12 12" })
4493
4871
  ] });
4494
4872
  }
4495
4873
  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" }) });
4874
+ return /* @__PURE__ */ jsx10("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: /* @__PURE__ */ jsx10("path", { d: "m6 9 6 6 6-6" }) });
4497
4875
  }
4498
4876
  function IconFile({ className, ...props }) {
4499
- 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" })
4877
+ return /* @__PURE__ */ jsxs5("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4878
+ /* @__PURE__ */ jsx10("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }),
4879
+ /* @__PURE__ */ jsx10("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" })
4502
4880
  ] });
4503
4881
  }
4504
4882
  function IconInfo({ className, ...props }) {
4505
- 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" })
4883
+ return /* @__PURE__ */ jsxs5("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4884
+ /* @__PURE__ */ jsx10("circle", { cx: "12", cy: "12", r: "10" }),
4885
+ /* @__PURE__ */ jsx10("path", { d: "M12 16v-4" }),
4886
+ /* @__PURE__ */ jsx10("path", { d: "M12 8h.01" })
4509
4887
  ] });
4510
4888
  }
4511
4889
  function IconArrowRight({ className, ...props }) {
4512
- 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" })
4890
+ return /* @__PURE__ */ jsxs5("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4891
+ /* @__PURE__ */ jsx10("path", { d: "M5 12h14" }),
4892
+ /* @__PURE__ */ jsx10("path", { d: "m12 5 7 7-7 7" })
4515
4893
  ] });
4516
4894
  }
4517
4895
  function IconSection({ className, ...props }) {
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: [
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" })
4896
+ return /* @__PURE__ */ jsxs5("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4897
+ /* @__PURE__ */ jsx10("rect", { width: "18", height: "7", x: "3", y: "3", rx: "1" }),
4898
+ /* @__PURE__ */ jsx10("rect", { width: "9", height: "7", x: "3", y: "14", rx: "1" }),
4899
+ /* @__PURE__ */ jsx10("rect", { width: "5", height: "7", x: "16", y: "14", rx: "1" })
4522
4900
  ] });
4523
4901
  }
4524
4902
 
4525
4903
  // src/ui/dialog.tsx
4526
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
4904
+ import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
4527
4905
  function Dialog2({ ...props }) {
4528
- return /* @__PURE__ */ jsx6(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
4906
+ return /* @__PURE__ */ jsx11(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
4529
4907
  }
4530
4908
  function DialogPortal({ ...props }) {
4531
- return /* @__PURE__ */ jsx6(DialogPrimitive.Portal, { ...props });
4909
+ return /* @__PURE__ */ jsx11(DialogPrimitive.Portal, { ...props });
4532
4910
  }
4533
4911
  function DialogOverlay({
4534
4912
  className,
4535
4913
  ...props
4536
4914
  }) {
4537
- return /* @__PURE__ */ jsx6(
4915
+ return /* @__PURE__ */ jsx11(
4538
4916
  DialogPrimitive.Overlay,
4539
4917
  {
4540
4918
  "data-slot": "dialog-overlay",
@@ -4544,11 +4922,11 @@ function DialogOverlay({
4544
4922
  }
4545
4923
  );
4546
4924
  }
4547
- var DialogContent = React3.forwardRef(({ className, children, showCloseButton = true, container, ...props }, ref) => {
4925
+ var DialogContent = React5.forwardRef(({ className, children, showCloseButton = true, container, ...props }, ref) => {
4548
4926
  const positionMode = container ? "absolute" : "fixed";
4549
- return /* @__PURE__ */ jsxs4(DialogPortal, { container: container ?? void 0, children: [
4550
- /* @__PURE__ */ jsx6(DialogOverlay, { className: cn(positionMode, "inset-0") }),
4551
- /* @__PURE__ */ jsxs4(
4927
+ return /* @__PURE__ */ jsxs6(DialogPortal, { container: container ?? void 0, children: [
4928
+ /* @__PURE__ */ jsx11(DialogOverlay, { className: cn(positionMode, "inset-0") }),
4929
+ /* @__PURE__ */ jsxs6(
4552
4930
  DialogPrimitive.Content,
4553
4931
  {
4554
4932
  ref,
@@ -4564,13 +4942,13 @@ var DialogContent = React3.forwardRef(({ className, children, showCloseButton =
4564
4942
  ...props,
4565
4943
  children: [
4566
4944
  children,
4567
- showCloseButton ? /* @__PURE__ */ jsx6(
4945
+ showCloseButton ? /* @__PURE__ */ jsx11(
4568
4946
  DialogPrimitive.Close,
4569
4947
  {
4570
4948
  type: "button",
4571
4949
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
4572
4950
  "aria-label": "Close",
4573
- children: /* @__PURE__ */ jsx6(IconX, { "aria-hidden": true })
4951
+ children: /* @__PURE__ */ jsx11(IconX, { "aria-hidden": true })
4574
4952
  }
4575
4953
  ) : null
4576
4954
  ]
@@ -4580,12 +4958,12 @@ var DialogContent = React3.forwardRef(({ className, children, showCloseButton =
4580
4958
  });
4581
4959
  DialogContent.displayName = DialogPrimitive.Content.displayName;
4582
4960
  function DialogHeader({ className, ...props }) {
4583
- return /* @__PURE__ */ jsx6("div", { className: cn("flex flex-col gap-1.5", className), ...props });
4961
+ return /* @__PURE__ */ jsx11("div", { className: cn("flex flex-col gap-1.5", className), ...props });
4584
4962
  }
4585
4963
  function DialogFooter({ className, ...props }) {
4586
- return /* @__PURE__ */ jsx6("div", { className: cn("flex items-center justify-end gap-2", className), ...props });
4964
+ return /* @__PURE__ */ jsx11("div", { className: cn("flex items-center justify-end gap-2", className), ...props });
4587
4965
  }
4588
- var DialogTitle = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx6(
4966
+ var DialogTitle = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx11(
4589
4967
  DialogPrimitive.Title,
4590
4968
  {
4591
4969
  ref,
@@ -4594,7 +4972,7 @@ var DialogTitle = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE
4594
4972
  }
4595
4973
  ));
4596
4974
  DialogTitle.displayName = DialogPrimitive.Title.displayName;
4597
- var DialogDescription = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx6(
4975
+ var DialogDescription = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx11(
4598
4976
  DialogPrimitive.Description,
4599
4977
  {
4600
4978
  ref,
@@ -4606,9 +4984,9 @@ DialogDescription.displayName = DialogPrimitive.Description.displayName;
4606
4984
  var DialogClose = DialogPrimitive.Close;
4607
4985
 
4608
4986
  // src/ui/button.tsx
4609
- import * as React4 from "react";
4987
+ import * as React6 from "react";
4610
4988
  import { Slot } from "radix-ui";
4611
- import { jsx as jsx7 } from "react/jsx-runtime";
4989
+ import { jsx as jsx12 } from "react/jsx-runtime";
4612
4990
  var buttonVariants = cva(
4613
4991
  "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
4992
  {
@@ -4629,10 +5007,10 @@ var buttonVariants = cva(
4629
5007
  }
4630
5008
  }
4631
5009
  );
4632
- var Button = React4.forwardRef(
5010
+ var Button = React6.forwardRef(
4633
5011
  ({ className, variant, size, asChild = false, ...props }, ref) => {
4634
5012
  const Comp = asChild ? Slot.Root : "button";
4635
- return /* @__PURE__ */ jsx7(
5013
+ return /* @__PURE__ */ jsx12(
4636
5014
  Comp,
4637
5015
  {
4638
5016
  ref,
@@ -4646,37 +5024,37 @@ var Button = React4.forwardRef(
4646
5024
  Button.displayName = "Button";
4647
5025
 
4648
5026
  // src/ui/link-modal/DestinationBreadcrumb.tsx
4649
- import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
5027
+ import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
4650
5028
  function DestinationBreadcrumb({ pageTitle, sectionLabel }) {
4651
- 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" }),
4653
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-3", children: [
4654
- /* @__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 })
5029
+ return /* @__PURE__ */ jsxs7("div", { className: "flex w-full flex-col gap-2", children: [
5030
+ /* @__PURE__ */ jsx13("p", { className: "text-sm font-medium text-foreground", children: "Destination" }),
5031
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-3", children: [
5032
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
5033
+ /* @__PURE__ */ jsx13(IconFile, { className: "shrink-0 text-foreground", "aria-hidden": true }),
5034
+ /* @__PURE__ */ jsx13("span", { className: "text-sm font-medium leading-none text-foreground", children: pageTitle })
4657
5035
  ] }),
4658
- /* @__PURE__ */ jsx8(IconArrowRight, { className: "shrink-0 text-muted-foreground", "aria-hidden": true }),
4659
- /* @__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 })
5036
+ /* @__PURE__ */ jsx13(IconArrowRight, { className: "shrink-0 text-muted-foreground", "aria-hidden": true }),
5037
+ /* @__PURE__ */ jsxs7("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
5038
+ /* @__PURE__ */ jsx13(IconSection, { className: "shrink-0 text-foreground", "aria-hidden": true }),
5039
+ /* @__PURE__ */ jsx13("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
4662
5040
  ] })
4663
5041
  ] })
4664
5042
  ] });
4665
5043
  }
4666
5044
 
4667
5045
  // src/ui/link-modal/SectionTreeItem.tsx
4668
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
5046
+ import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
4669
5047
  function SectionTreeItem({ section, onSelect, selected }) {
4670
5048
  const interactive = Boolean(onSelect);
4671
- return /* @__PURE__ */ jsxs6("div", { className: "flex h-9 w-full items-end pl-3", children: [
4672
- /* @__PURE__ */ jsx9(
5049
+ return /* @__PURE__ */ jsxs8("div", { className: "flex h-9 w-full items-end pl-3", children: [
5050
+ /* @__PURE__ */ jsx14(
4673
5051
  "div",
4674
5052
  {
4675
5053
  className: "mr-[-1px] h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
4676
5054
  "aria-hidden": true
4677
5055
  }
4678
5056
  ),
4679
- /* @__PURE__ */ jsxs6(
5057
+ /* @__PURE__ */ jsxs8(
4680
5058
  "div",
4681
5059
  {
4682
5060
  role: interactive ? "button" : void 0,
@@ -4694,8 +5072,8 @@ function SectionTreeItem({ section, onSelect, selected }) {
4694
5072
  interactive && selected && "border-primary"
4695
5073
  ),
4696
5074
  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 })
5075
+ /* @__PURE__ */ jsx14(IconSection, { className: "shrink-0 text-foreground", "aria-hidden": true }),
5076
+ /* @__PURE__ */ jsx14("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
4699
5077
  ]
4700
5078
  }
4701
5079
  )
@@ -4703,11 +5081,11 @@ function SectionTreeItem({ section, onSelect, selected }) {
4703
5081
  }
4704
5082
  function SectionPickerList({ sections, onSelect }) {
4705
5083
  if (sections.length === 0) {
4706
- return /* @__PURE__ */ jsx9("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." });
5084
+ return /* @__PURE__ */ jsx14("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." });
4707
5085
  }
4708
- 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))
5086
+ return /* @__PURE__ */ jsxs8("div", { className: "flex flex-col gap-1", children: [
5087
+ /* @__PURE__ */ jsx14("p", { className: "text-sm text-muted-foreground", children: "Pick a section this link should scroll to." }),
5088
+ sections.map((section) => /* @__PURE__ */ jsx14(SectionTreeItem, { section, onSelect }, section.id))
4711
5089
  ] });
4712
5090
  }
4713
5091
 
@@ -4715,11 +5093,11 @@ function SectionPickerList({ sections, onSelect }) {
4715
5093
  import { useId as useId2, useRef as useRef2, useState as useState3 } from "react";
4716
5094
 
4717
5095
  // src/ui/input.tsx
4718
- import * as React5 from "react";
4719
- import { jsx as jsx10 } from "react/jsx-runtime";
4720
- var Input = React5.forwardRef(
5096
+ import * as React7 from "react";
5097
+ import { jsx as jsx15 } from "react/jsx-runtime";
5098
+ var Input = React7.forwardRef(
4721
5099
  ({ className, type, ...props }, ref) => {
4722
- return /* @__PURE__ */ jsx10(
5100
+ return /* @__PURE__ */ jsx15(
4723
5101
  "input",
4724
5102
  {
4725
5103
  type,
@@ -4738,9 +5116,9 @@ Input.displayName = "Input";
4738
5116
 
4739
5117
  // src/ui/label.tsx
4740
5118
  import { Label as LabelPrimitive } from "radix-ui";
4741
- import { jsx as jsx11 } from "react/jsx-runtime";
5119
+ import { jsx as jsx16 } from "react/jsx-runtime";
4742
5120
  function Label({ className, ...props }) {
4743
- return /* @__PURE__ */ jsx11(
5121
+ return /* @__PURE__ */ jsx16(
4744
5122
  LabelPrimitive.Root,
4745
5123
  {
4746
5124
  "data-slot": "label",
@@ -4751,9 +5129,9 @@ function Label({ className, ...props }) {
4751
5129
  }
4752
5130
 
4753
5131
  // src/ui/link-modal/UrlOrPageInput.tsx
4754
- import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
5132
+ import { jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
4755
5133
  function FieldChevron({ onClick }) {
4756
- return /* @__PURE__ */ jsx12(
5134
+ return /* @__PURE__ */ jsx17(
4757
5135
  "button",
4758
5136
  {
4759
5137
  type: "button",
@@ -4761,7 +5139,7 @@ function FieldChevron({ onClick }) {
4761
5139
  onClick,
4762
5140
  "aria-label": "Open page list",
4763
5141
  tabIndex: -1,
4764
- children: /* @__PURE__ */ jsx12(IconChevronDown, {})
5142
+ children: /* @__PURE__ */ jsx17(IconChevronDown, {})
4765
5143
  }
4766
5144
  );
4767
5145
  }
@@ -4800,12 +5178,12 @@ function UrlOrPageInput({
4800
5178
  "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]",
4801
5179
  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
5180
  );
4803
- 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" }),
4805
- /* @__PURE__ */ jsxs7("div", { className: "relative w-full", children: [
4806
- /* @__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(
5181
+ return /* @__PURE__ */ jsxs9("div", { className: "flex w-full flex-col gap-2 p-0", children: [
5182
+ /* @__PURE__ */ jsx17(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
5183
+ /* @__PURE__ */ jsxs9("div", { className: "relative w-full", children: [
5184
+ /* @__PURE__ */ jsxs9("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
5185
+ selectedPage ? /* @__PURE__ */ jsx17("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ jsx17(IconFile, { className: "text-foreground", "aria-hidden": true }) }) : null,
5186
+ readOnly ? /* @__PURE__ */ jsx17("span", { className: "min-w-0 flex-1 truncate text-sm leading-5 text-foreground", children: selectedPage?.title ?? value }) : /* @__PURE__ */ jsx17(
4809
5187
  Input,
4810
5188
  {
4811
5189
  ref: inputRef,
@@ -4824,7 +5202,7 @@ function UrlOrPageInput({
4824
5202
  )
4825
5203
  }
4826
5204
  ),
4827
- selectedPage && !readOnly ? /* @__PURE__ */ jsx12(
5205
+ selectedPage && !readOnly ? /* @__PURE__ */ jsx17(
4828
5206
  "button",
4829
5207
  {
4830
5208
  type: "button",
@@ -4832,26 +5210,26 @@ function UrlOrPageInput({
4832
5210
  onMouseDown: clearSelection,
4833
5211
  "aria-label": "Clear selected page",
4834
5212
  tabIndex: -1,
4835
- children: /* @__PURE__ */ jsx12(IconX, { "aria-hidden": true })
5213
+ children: /* @__PURE__ */ jsx17(IconX, { "aria-hidden": true })
4836
5214
  }
4837
5215
  ) : null,
4838
- !readOnly ? /* @__PURE__ */ jsx12(FieldChevron, { onClick: toggleDropdown }) : null
5216
+ !readOnly ? /* @__PURE__ */ jsx17(FieldChevron, { onClick: toggleDropdown }) : null
4839
5217
  ] }),
4840
- dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ jsx12(
5218
+ dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ jsx17(
4841
5219
  "div",
4842
5220
  {
4843
5221
  "data-ohw-link-page-dropdown": "",
4844
5222
  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",
4845
5223
  onMouseDown: (e) => e.preventDefault(),
4846
- children: filteredPages.map((page) => /* @__PURE__ */ jsxs7(
5224
+ children: filteredPages.map((page) => /* @__PURE__ */ jsxs9(
4847
5225
  "button",
4848
5226
  {
4849
5227
  type: "button",
4850
5228
  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
5229
  onClick: () => onPageSelect(page),
4852
5230
  children: [
4853
- /* @__PURE__ */ jsx12(IconFile, { className: "shrink-0", "aria-hidden": true }),
4854
- /* @__PURE__ */ jsx12("span", { className: "truncate", children: page.title })
5231
+ /* @__PURE__ */ jsx17(IconFile, { className: "shrink-0", "aria-hidden": true }),
5232
+ /* @__PURE__ */ jsx17("span", { className: "truncate", children: page.title })
4855
5233
  ]
4856
5234
  },
4857
5235
  page.path
@@ -4859,12 +5237,12 @@ function UrlOrPageInput({
4859
5237
  }
4860
5238
  ) : null
4861
5239
  ] }),
4862
- urlError ? /* @__PURE__ */ jsx12("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
5240
+ urlError ? /* @__PURE__ */ jsx17("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
4863
5241
  ] });
4864
5242
  }
4865
5243
 
4866
5244
  // src/ui/link-modal/useLinkModalState.ts
4867
- import { useCallback, useEffect as useEffect2, useMemo as useMemo2, useState as useState4 } from "react";
5245
+ import { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo2, useState as useState4 } from "react";
4868
5246
  function useLinkModalState({
4869
5247
  open,
4870
5248
  mode,
@@ -4886,7 +5264,7 @@ function useLinkModalState({
4886
5264
  const [step, setStep] = useState4("input");
4887
5265
  const [dropdownOpen, setDropdownOpen] = useState4(false);
4888
5266
  const [urlError, setUrlError] = useState4("");
4889
- const reset = useCallback(() => {
5267
+ const reset = useCallback2(() => {
4890
5268
  setSearchValue("");
4891
5269
  setSelectedPage(null);
4892
5270
  setSelectedSection(null);
@@ -5027,7 +5405,7 @@ function useLinkModalState({
5027
5405
  }
5028
5406
 
5029
5407
  // src/ui/link-modal/LinkEditorPanel.tsx
5030
- import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
5408
+ import { Fragment as Fragment2, jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
5031
5409
  function LinkEditorPanel({
5032
5410
  open = true,
5033
5411
  mode = "create",
@@ -5051,25 +5429,25 @@ function LinkEditorPanel({
5051
5429
  onSubmit
5052
5430
  });
5053
5431
  const isCancel = state.secondaryLabel === "Cancel";
5054
- return /* @__PURE__ */ jsxs8(Fragment2, { children: [
5055
- /* @__PURE__ */ jsx13(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx13(
5432
+ return /* @__PURE__ */ jsxs10(Fragment2, { children: [
5433
+ /* @__PURE__ */ jsx18(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx18(
5056
5434
  "button",
5057
5435
  {
5058
5436
  type: "button",
5059
5437
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
5060
5438
  "aria-label": "Close",
5061
- children: /* @__PURE__ */ jsx13(IconX, { "aria-hidden": true })
5439
+ children: /* @__PURE__ */ jsx18(IconX, { "aria-hidden": true })
5062
5440
  }
5063
5441
  ) }),
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 }) }),
5065
- /* @__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(
5442
+ /* @__PURE__ */ jsx18(DialogHeader, { className: "w-full gap-1.5 p-6 pr-12", children: /* @__PURE__ */ jsx18(DialogTitle, { className: "m-0 w-full break-words", children: state.title }) }),
5443
+ /* @__PURE__ */ jsxs10("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
5444
+ state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ jsx18(
5067
5445
  DestinationBreadcrumb,
5068
5446
  {
5069
5447
  pageTitle: state.selectedPage.title,
5070
5448
  sectionLabel: state.selectedSection.label
5071
5449
  }
5072
- ) : /* @__PURE__ */ jsx13(
5450
+ ) : /* @__PURE__ */ jsx18(
5073
5451
  UrlOrPageInput,
5074
5452
  {
5075
5453
  value: state.searchValue,
@@ -5082,18 +5460,18 @@ function LinkEditorPanel({
5082
5460
  urlError: state.urlError
5083
5461
  }
5084
5462
  ),
5085
- 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" }),
5087
- /* @__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." })
5463
+ state.showChooseSection ? /* @__PURE__ */ jsxs10("div", { className: "flex flex-col justify-center gap-2", children: [
5464
+ /* @__PURE__ */ jsx18(Button, { type: "button", variant: "outline", className: "w-fit cursor-pointer", size: "sm", onClick: state.handleChooseSection, children: "Choose a section" }),
5465
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
5466
+ /* @__PURE__ */ jsx18(IconInfo, { className: "shrink-0", "aria-hidden": true }),
5467
+ /* @__PURE__ */ jsx18("span", { children: "Pick a section this link should scroll to." })
5090
5468
  ] })
5091
5469
  ] }) : 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
5470
+ state.showSectionPicker ? /* @__PURE__ */ jsx18(SectionPickerList, { sections: state.activeSections, onSelect: state.handleSectionSelect }) : null,
5471
+ state.showSectionRow && state.selectedSection ? /* @__PURE__ */ jsx18(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
5094
5472
  ] }),
5095
- /* @__PURE__ */ jsxs8(DialogFooter, { className: "w-full px-6 pb-6", children: [
5096
- /* @__PURE__ */ jsx13(
5473
+ /* @__PURE__ */ jsxs10(DialogFooter, { className: "w-full px-6 pb-6", children: [
5474
+ /* @__PURE__ */ jsx18(
5097
5475
  Button,
5098
5476
  {
5099
5477
  type: "button",
@@ -5108,7 +5486,7 @@ function LinkEditorPanel({
5108
5486
  children: state.secondaryLabel
5109
5487
  }
5110
5488
  ),
5111
- /* @__PURE__ */ jsx13(
5489
+ /* @__PURE__ */ jsx18(
5112
5490
  Button,
5113
5491
  {
5114
5492
  type: "button",
@@ -5127,7 +5505,7 @@ function LinkEditorPanel({
5127
5505
  }
5128
5506
 
5129
5507
  // src/ui/link-modal/LinkPopover.tsx
5130
- import { jsx as jsx14 } from "react/jsx-runtime";
5508
+ import { jsx as jsx19 } from "react/jsx-runtime";
5131
5509
  function LinkPopover({
5132
5510
  open = true,
5133
5511
  panelRef,
@@ -5135,14 +5513,14 @@ function LinkPopover({
5135
5513
  onClose,
5136
5514
  ...editorProps
5137
5515
  }) {
5138
- return /* @__PURE__ */ jsx14(
5516
+ return /* @__PURE__ */ jsx19(
5139
5517
  Dialog2,
5140
5518
  {
5141
5519
  open,
5142
5520
  onOpenChange: (next) => {
5143
5521
  if (!next) onClose?.();
5144
5522
  },
5145
- children: /* @__PURE__ */ jsx14(
5523
+ children: /* @__PURE__ */ jsx19(
5146
5524
  DialogContent,
5147
5525
  {
5148
5526
  ref: panelRef,
@@ -5152,7 +5530,7 @@ function LinkPopover({
5152
5530
  "data-ohw-bridge": "",
5153
5531
  showCloseButton: false,
5154
5532
  className: "gap-0 p-0 w-full md:w-md pointer-events-auto",
5155
- children: /* @__PURE__ */ jsx14(LinkEditorPanel, { ...editorProps, open, onClose })
5533
+ children: /* @__PURE__ */ jsx19(LinkEditorPanel, { ...editorProps, open, onClose })
5156
5534
  }
5157
5535
  )
5158
5536
  }
@@ -5218,7 +5596,7 @@ function shouldUseDevFixtures() {
5218
5596
  }
5219
5597
 
5220
5598
  // src/ui/badge.tsx
5221
- import { jsx as jsx15 } from "react/jsx-runtime";
5599
+ import { jsx as jsx20 } from "react/jsx-runtime";
5222
5600
  var badgeVariants = cva(
5223
5601
  "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
5602
  {
@@ -5236,12 +5614,13 @@ var badgeVariants = cva(
5236
5614
  }
5237
5615
  );
5238
5616
  function Badge({ className, variant, ...props }) {
5239
- return /* @__PURE__ */ jsx15("div", { className: cn(badgeVariants({ variant }), className), ...props });
5617
+ return /* @__PURE__ */ jsx20("div", { className: cn(badgeVariants({ variant }), className), ...props });
5240
5618
  }
5241
5619
 
5242
5620
  // src/OhhwellsBridge.tsx
5243
- import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs9 } from "react/jsx-runtime";
5244
- var PRIMARY = "#0885FE";
5621
+ import { Link as Link2 } from "lucide-react";
5622
+ import { Fragment as Fragment3, jsx as jsx21, jsxs as jsxs11 } from "react/jsx-runtime";
5623
+ var PRIMARY2 = "#0885FE";
5245
5624
  var IMAGE_FADE_MS = 300;
5246
5625
  function runOpacityFade(el, onDone) {
5247
5626
  const anim = el.animate([{ opacity: 0 }, { opacity: 1 }], {
@@ -5414,7 +5793,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
5414
5793
  const root = createRoot(container);
5415
5794
  flushSync(() => {
5416
5795
  root.render(
5417
- /* @__PURE__ */ jsx16(
5796
+ /* @__PURE__ */ jsx21(
5418
5797
  SchedulingWidget,
5419
5798
  {
5420
5799
  notifyOnConnect,
@@ -5462,6 +5841,20 @@ function applyLinkHref(el, val) {
5462
5841
  const anchor = el instanceof HTMLAnchorElement ? el : el.querySelector("a");
5463
5842
  if (anchor) anchor.setAttribute("href", val);
5464
5843
  }
5844
+ function getEditMeasureEl(editable) {
5845
+ return editable.closest("[data-ohw-href-key]") ?? editable;
5846
+ }
5847
+ function isDragHandleDisabled(el) {
5848
+ const carriers = [
5849
+ el.closest("[data-ohw-href-key]"),
5850
+ el.closest("[data-ohw-editable]")
5851
+ ];
5852
+ return carriers.some((carrier) => {
5853
+ if (!carrier) return false;
5854
+ const raw = carrier.getAttribute("data-ohw-drag-disabled");
5855
+ return raw === "true" || raw === "";
5856
+ });
5857
+ }
5465
5858
  function collectEditableNodes() {
5466
5859
  const nodes = Array.from(document.querySelectorAll("[data-ohw-editable]")).map((el) => {
5467
5860
  if (el.dataset.ohwEditable === "image") {
@@ -5515,12 +5908,49 @@ function getHrefKeyFromElement(el) {
5515
5908
  function isNavbarButton(el) {
5516
5909
  return Boolean(el.closest('[data-ohw-role="navbar-button"]'));
5517
5910
  }
5911
+ function getNavigationItemAnchor(el) {
5912
+ const anchor = el.matches("[data-ohw-href-key]") ? el : el.closest("[data-ohw-href-key]");
5913
+ if (!anchor) return null;
5914
+ if (!anchor.querySelector('[data-ohw-editable="text"]')) return null;
5915
+ return anchor;
5916
+ }
5917
+ function isNavigationItem(el) {
5918
+ return getNavigationItemAnchor(el) !== null;
5919
+ }
5920
+ function getNavigationItemAddHintTarget(anchor) {
5921
+ const items = listNavigationItems();
5922
+ const idx = items.indexOf(anchor);
5923
+ if (idx >= 0 && idx < items.length - 1) return items[idx + 1];
5924
+ return anchor;
5925
+ }
5926
+ function listNavigationItems() {
5927
+ return Array.from(
5928
+ document.querySelectorAll("nav [data-ohw-href-key], footer [data-ohw-href-key]")
5929
+ ).filter((el) => isNavigationItem(el));
5930
+ }
5931
+ function getNavigationItemReorderState(anchor) {
5932
+ if (isNavbarButton(anchor)) return { key: null, disabled: false };
5933
+ return getReorderHandleStateFromAnchor(anchor);
5934
+ }
5935
+ function getReorderHandleState(el) {
5936
+ const linkEl = el.closest("[data-ohw-href-key]");
5937
+ if (!linkEl || getNavigationItemAnchor(linkEl)) return { key: null, disabled: false };
5938
+ return getReorderHandleStateFromAnchor(linkEl);
5939
+ }
5940
+ function getReorderHandleStateFromAnchor(anchor) {
5941
+ const key = anchor.getAttribute("data-ohw-href-key");
5942
+ if (!key) return { key: null, disabled: false };
5943
+ return { key, disabled: isDragHandleDisabled(anchor) };
5944
+ }
5518
5945
  function clearHrefKeyHover(anchor) {
5519
5946
  anchor.removeAttribute("data-ohw-hovered");
5520
5947
  anchor.querySelectorAll("[data-ohw-hovered]").forEach((el) => {
5521
5948
  el.removeAttribute("data-ohw-hovered");
5522
5949
  });
5523
5950
  }
5951
+ function isInsideNavigationItem(el) {
5952
+ return getNavigationItemAnchor(el) !== null;
5953
+ }
5524
5954
  function collectSections() {
5525
5955
  return collectSectionsFromDom();
5526
5956
  }
@@ -5644,6 +6074,8 @@ var ICONS = {
5644
6074
  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
6075
  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
6076
  };
6077
+ var TOOLBAR_PILL_PADDING = 2;
6078
+ var TOOLBAR_TOGGLE_GAP = 4;
5647
6079
  var TOOLBAR_GROUPS = [
5648
6080
  [
5649
6081
  { cmd: "bold", title: "Bold" },
@@ -5661,24 +6093,64 @@ var TOOLBAR_GROUPS = [
5661
6093
  { cmd: "insertOrderedList", title: "Numbered List" }
5662
6094
  ]
5663
6095
  ];
5664
- function GlowFrame({ rect, elRef }) {
6096
+ function EditGlowChrome({
6097
+ rect,
6098
+ elRef,
6099
+ reorderHrefKey,
6100
+ dragDisabled = false
6101
+ }) {
5665
6102
  const GAP = 6;
5666
- return /* @__PURE__ */ jsx16(
6103
+ return /* @__PURE__ */ jsxs11(
5667
6104
  "div",
5668
6105
  {
5669
6106
  ref: elRef,
6107
+ "data-ohw-edit-chrome": "",
5670
6108
  style: {
5671
6109
  position: "fixed",
5672
6110
  top: rect.top - GAP,
5673
6111
  left: rect.left - GAP,
5674
6112
  width: rect.width + GAP * 2,
5675
6113
  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
6114
  pointerEvents: "none",
5680
6115
  zIndex: 2147483646
5681
- }
6116
+ },
6117
+ children: [
6118
+ /* @__PURE__ */ jsx21(
6119
+ "div",
6120
+ {
6121
+ style: {
6122
+ position: "absolute",
6123
+ inset: 0,
6124
+ border: "2px solid var(--ohw-primary, #0885FE)",
6125
+ borderRadius: 8,
6126
+ boxShadow: "0 0 0 4px rgba(8, 133, 254, 0.12)",
6127
+ pointerEvents: "none"
6128
+ }
6129
+ }
6130
+ ),
6131
+ reorderHrefKey && /* @__PURE__ */ jsx21(
6132
+ "div",
6133
+ {
6134
+ "data-ohw-drag-handle-container": "",
6135
+ "data-ohw-drag-disabled": dragDisabled ? "" : void 0,
6136
+ style: {
6137
+ position: "absolute",
6138
+ left: 0,
6139
+ top: "50%",
6140
+ transform: "translate(calc(-100% - 7px), -50%)",
6141
+ pointerEvents: dragDisabled ? "none" : "auto"
6142
+ },
6143
+ children: /* @__PURE__ */ jsx21(
6144
+ DragHandle,
6145
+ {
6146
+ "aria-label": `Reorder ${reorderHrefKey}`,
6147
+ disabled: dragDisabled,
6148
+ "aria-disabled": dragDisabled
6149
+ }
6150
+ )
6151
+ }
6152
+ )
6153
+ ]
5682
6154
  }
5683
6155
  );
5684
6156
  }
@@ -5722,9 +6194,9 @@ function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
5722
6194
  const pinnedTop = Math.min(maxBottom - approxH, Math.max(minTop, clip.top + gap));
5723
6195
  return { top: pinnedTop + approxH, transform: "translateX(-50%) translateY(-100%)" };
5724
6196
  }
5725
- function calcToolbarPos(rect, parentScroll, approxW = 330) {
6197
+ function calcToolbarPos(rect, parentScroll, approxW = 306) {
5726
6198
  const GAP = 8;
5727
- const APPROX_H = 36;
6199
+ const APPROX_H = 32;
5728
6200
  const APPROX_W = approxW;
5729
6201
  const clip = getIframeVisibleClip(parentScroll);
5730
6202
  const clipTop = clip?.top ?? 0;
@@ -5758,119 +6230,24 @@ function calcToolbarPos(rect, parentScroll, approxW = 330) {
5758
6230
  const left = Math.max(GAP + APPROX_W / 2, Math.min(rawLeft, window.innerWidth - GAP - APPROX_W / 2));
5759
6231
  return { top, left, transform };
5760
6232
  }
5761
- 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" })
5764
- ] });
6233
+ function resolveItemInteractionState(rect, parentScroll) {
6234
+ const { transform } = calcToolbarPos(rect, parentScroll, 120);
6235
+ return transform.includes("translateY(-100%)") ? "active-top" : "active-bottom";
6236
+ }
5765
6237
  function FloatingToolbar({
5766
6238
  rect,
5767
6239
  parentScroll,
5768
6240
  elRef,
5769
- variant = "rich-text",
5770
6241
  onCommand,
5771
6242
  activeCommands,
5772
6243
  showEditLink,
5773
6244
  onEditLink
5774
6245
  }) {
5775
- const approxW = variant === "link-action" ? 120 : 330;
5776
- const { top, left, transform } = calcToolbarPos(rect, parentScroll, approxW);
5777
- if (variant === "link-action") {
5778
- return /* @__PURE__ */ jsxs9(
5779
- "div",
5780
- {
5781
- ref: elRef,
5782
- "data-ohw-toolbar": "",
5783
- style: {
5784
- position: "fixed",
5785
- top,
5786
- left,
5787
- transform,
5788
- zIndex: 2147483647,
5789
- background: "#fff",
5790
- border: "1px solid #E7E5E4",
5791
- borderRadius: 6,
5792
- boxShadow: "0px 2px 4px -2px rgba(0,0,0,.1),0px 4px 6px -1px rgba(0,0,0,.1)",
5793
- display: "flex",
5794
- alignItems: "center",
5795
- padding: 4,
5796
- gap: 6,
5797
- fontFamily: "sans-serif",
5798
- pointerEvents: "auto",
5799
- whiteSpace: "nowrap"
5800
- },
5801
- onMouseDown: (e) => e.stopPropagation(),
5802
- children: [
5803
- /* @__PURE__ */ jsx16(
5804
- "button",
5805
- {
5806
- type: "button",
5807
- title: "Edit link",
5808
- onMouseDown: (e) => {
5809
- e.preventDefault();
5810
- e.stopPropagation();
5811
- onEditLink?.();
5812
- },
5813
- onClick: (e) => {
5814
- e.preventDefault();
5815
- e.stopPropagation();
5816
- },
5817
- onMouseEnter: (e) => {
5818
- e.currentTarget.style.background = "#F5F5F4";
5819
- },
5820
- onMouseLeave: (e) => {
5821
- e.currentTarget.style.background = "transparent";
5822
- },
5823
- style: {
5824
- display: "flex",
5825
- alignItems: "center",
5826
- justifyContent: "center",
5827
- border: "none",
5828
- background: "transparent",
5829
- borderRadius: 4,
5830
- cursor: "pointer",
5831
- color: "#1C1917",
5832
- flexShrink: 0,
5833
- padding: 6
5834
- },
5835
- children: EDIT_LINK_ICON
5836
- }
5837
- ),
5838
- /* @__PURE__ */ jsx16("span", { style: { display: "block", width: 1, height: 24, background: "#E7E5E4", flexShrink: 0 } }),
5839
- /* @__PURE__ */ jsx16(
5840
- "button",
5841
- {
5842
- type: "button",
5843
- title: "Coming soon",
5844
- disabled: true,
5845
- style: {
5846
- display: "flex",
5847
- alignItems: "center",
5848
- justifyContent: "center",
5849
- border: "none",
5850
- background: "transparent",
5851
- borderRadius: 4,
5852
- cursor: "not-allowed",
5853
- color: "#A8A29E",
5854
- flexShrink: 0,
5855
- padding: 6,
5856
- opacity: 0.6
5857
- },
5858
- 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" })
5862
- ] })
5863
- }
5864
- )
5865
- ]
5866
- }
5867
- );
5868
- }
5869
- return /* @__PURE__ */ jsxs9(
6246
+ const { top, left, transform } = calcToolbarPos(rect, parentScroll, 330);
6247
+ return /* @__PURE__ */ jsx21(
5870
6248
  "div",
5871
6249
  {
5872
6250
  ref: elRef,
5873
- "data-ohw-toolbar": "",
5874
6251
  style: {
5875
6252
  position: "fixed",
5876
6253
  top,
@@ -5883,57 +6260,39 @@ function FloatingToolbar({
5883
6260
  boxShadow: "0px 2px 4px -2px rgba(0,0,0,.1),0px 4px 6px -1px rgba(0,0,0,.1)",
5884
6261
  display: "flex",
5885
6262
  alignItems: "center",
5886
- padding: 4,
5887
- gap: 6,
6263
+ padding: TOOLBAR_PILL_PADDING,
6264
+ gap: TOOLBAR_TOGGLE_GAP,
5888
6265
  fontFamily: "sans-serif",
5889
- pointerEvents: "auto",
5890
- whiteSpace: "nowrap"
6266
+ pointerEvents: "auto"
5891
6267
  },
5892
- onMouseDown: (e) => e.stopPropagation(),
5893
- 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 } }),
6268
+ children: /* @__PURE__ */ jsxs11(CustomToolbar, { children: [
6269
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs11(React8.Fragment, { children: [
6270
+ gi > 0 && /* @__PURE__ */ jsx21(CustomToolbarDivider, {}),
5896
6271
  btns.map((btn) => {
5897
6272
  const isActive = activeCommands.has(btn.cmd);
5898
- return /* @__PURE__ */ jsx16(
5899
- "button",
6273
+ return /* @__PURE__ */ jsx21(
6274
+ CustomToolbarButton,
5900
6275
  {
5901
6276
  title: btn.title,
6277
+ active: isActive,
5902
6278
  onMouseDown: (e) => {
5903
6279
  e.preventDefault();
5904
6280
  onCommand(btn.cmd);
5905
6281
  },
5906
- onMouseEnter: (e) => {
5907
- if (!isActive) e.currentTarget.style.background = "#F5F5F4";
5908
- },
5909
- onMouseLeave: (e) => {
5910
- if (!isActive) e.currentTarget.style.background = "transparent";
5911
- },
5912
- style: {
5913
- display: "flex",
5914
- alignItems: "center",
5915
- justifyContent: "center",
5916
- border: "none",
5917
- background: isActive ? PRIMARY : "transparent",
5918
- borderRadius: 4,
5919
- cursor: "pointer",
5920
- color: isActive ? "#FFFFFF" : "#1C1917",
5921
- flexShrink: 0,
5922
- padding: 6
5923
- },
5924
- children: /* @__PURE__ */ jsx16(
6282
+ children: /* @__PURE__ */ jsx21(
5925
6283
  "svg",
5926
6284
  {
5927
6285
  width: "16",
5928
6286
  height: "16",
5929
6287
  viewBox: "0 0 24 24",
5930
6288
  fill: "none",
5931
- stroke: isActive ? "#FFFFFF" : "#1C1917",
6289
+ stroke: "currentColor",
5932
6290
  strokeWidth: "2.5",
5933
6291
  strokeLinecap: "round",
5934
6292
  strokeLinejoin: "round",
5935
- style: isActive && gi > 0 ? { filter: "drop-shadow(0 0 0.5px #fff)" } : void 0,
5936
- dangerouslySetInnerHTML: { __html: ICONS[btn.cmd] }
6293
+ style: isActive && gi > 0 ? { filter: "drop-shadow(0 0 0.5px currentColor)" } : void 0,
6294
+ dangerouslySetInnerHTML: { __html: ICONS[btn.cmd] },
6295
+ "aria-hidden": true
5937
6296
  }
5938
6297
  )
5939
6298
  },
@@ -5941,8 +6300,8 @@ function FloatingToolbar({
5941
6300
  );
5942
6301
  })
5943
6302
  ] }, gi)),
5944
- showEditLink ? /* @__PURE__ */ jsx16(
5945
- "button",
6303
+ showEditLink ? /* @__PURE__ */ jsx21(
6304
+ CustomToolbarButton,
5946
6305
  {
5947
6306
  type: "button",
5948
6307
  title: "Edit link",
@@ -5955,28 +6314,10 @@ function FloatingToolbar({
5955
6314
  e.preventDefault();
5956
6315
  e.stopPropagation();
5957
6316
  },
5958
- onMouseEnter: (e) => {
5959
- e.currentTarget.style.background = "#F5F5F4";
5960
- },
5961
- onMouseLeave: (e) => {
5962
- e.currentTarget.style.background = "transparent";
5963
- },
5964
- style: {
5965
- display: "flex",
5966
- alignItems: "center",
5967
- justifyContent: "center",
5968
- border: "none",
5969
- background: "transparent",
5970
- borderRadius: 4,
5971
- cursor: "pointer",
5972
- color: "#1C1917",
5973
- flexShrink: 0,
5974
- padding: 6
5975
- },
5976
- children: EDIT_LINK_ICON
6317
+ children: /* @__PURE__ */ jsx21(Link2, { className: "size-4 shrink-0", "aria-hidden": true })
5977
6318
  }
5978
6319
  ) : null
5979
- ]
6320
+ ] })
5980
6321
  }
5981
6322
  );
5982
6323
  }
@@ -5990,7 +6331,7 @@ function StateToggle({
5990
6331
  states,
5991
6332
  onStateChange
5992
6333
  }) {
5993
- return /* @__PURE__ */ jsx16(
6334
+ return /* @__PURE__ */ jsx21(
5994
6335
  ToggleGroup,
5995
6336
  {
5996
6337
  "data-ohw-state-toggle": "",
@@ -6004,7 +6345,7 @@ function StateToggle({
6004
6345
  left: rect.right - 8,
6005
6346
  transform: "translateX(-100%)"
6006
6347
  },
6007
- children: states.map((state) => /* @__PURE__ */ jsx16(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
6348
+ children: states.map((state) => /* @__PURE__ */ jsx21(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
6008
6349
  }
6009
6350
  );
6010
6351
  }
@@ -6057,7 +6398,7 @@ function OhhwellsBridge() {
6057
6398
  const subdomainFromQuery = searchParams.get("subdomain");
6058
6399
  const subdomain = resolveSubdomain(subdomainFromQuery);
6059
6400
  useLinkHrefGuardian(pathname, subdomain, isEditMode);
6060
- const postToParent = useCallback2((data) => {
6401
+ const postToParent = useCallback3((data) => {
6061
6402
  if (typeof window !== "undefined" && window.parent !== window) {
6062
6403
  window.parent.postMessage(data, "*");
6063
6404
  }
@@ -6071,7 +6412,7 @@ function OhhwellsBridge() {
6071
6412
  const parentScrollRef = useRef3(null);
6072
6413
  const visibleViewportRef = useRef3(null);
6073
6414
  const [dialogPortalContainer, setDialogPortalContainer] = useState5(null);
6074
- const attachVisibleViewport = useCallback2((node) => {
6415
+ const attachVisibleViewport = useCallback3((node) => {
6075
6416
  visibleViewportRef.current = node;
6076
6417
  setDialogPortalContainer(node);
6077
6418
  if (node) applyVisibleViewport(node, parentScrollRef.current);
@@ -6092,6 +6433,10 @@ function OhhwellsBridge() {
6092
6433
  });
6093
6434
  const deselectRef = useRef3(() => {
6094
6435
  });
6436
+ const reselectNavigationItemRef = useRef3(() => {
6437
+ });
6438
+ const commitNavigationTextEditRef = useRef3(() => {
6439
+ });
6095
6440
  const refreshActiveCommandsRef = useRef3(() => {
6096
6441
  });
6097
6442
  const postToParentRef = useRef3(postToParent);
@@ -6102,11 +6447,18 @@ function OhhwellsBridge() {
6102
6447
  const [toolbarVariant, setToolbarVariant] = useState5("none");
6103
6448
  const toolbarVariantRef = useRef3("none");
6104
6449
  toolbarVariantRef.current = toolbarVariant;
6450
+ const [reorderHrefKey, setReorderHrefKey] = useState5(null);
6451
+ const [reorderDragDisabled, setReorderDragDisabled] = useState5(false);
6105
6452
  const [toggleState, setToggleState] = useState5(null);
6106
6453
  const [maxBadge, setMaxBadge] = useState5(null);
6107
6454
  const [activeCommands, setActiveCommands] = useState5(/* @__PURE__ */ new Set());
6108
6455
  const [sectionGap, setSectionGap] = useState5(null);
6109
6456
  const [toolbarShowEditLink, setToolbarShowEditLink] = useState5(false);
6457
+ const hoveredItemElRef = useRef3(null);
6458
+ const [hoveredItemRect, setHoveredItemRect] = useState5(null);
6459
+ const siblingHintElRef = useRef3(null);
6460
+ const [siblingHintRect, setSiblingHintRect] = useState5(null);
6461
+ const [isItemDragging, setIsItemDragging] = useState5(false);
6110
6462
  const [linkPopover, setLinkPopover] = useState5(null);
6111
6463
  const [sitePages, setSitePages] = useState5([]);
6112
6464
  const [sectionsByPath, setSectionsByPath] = useState5({});
@@ -6119,7 +6471,7 @@ function OhhwellsBridge() {
6119
6471
  const bumpLinkPopoverGrace = () => {
6120
6472
  linkPopoverGraceUntilRef.current = Date.now() + 350;
6121
6473
  };
6122
- const runSectionsPrefetch = useCallback2((pages) => {
6474
+ const runSectionsPrefetch = useCallback3((pages) => {
6123
6475
  if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
6124
6476
  const gen = ++sectionsPrefetchGenRef.current;
6125
6477
  const paths = pages.map((p) => p.path);
@@ -6208,7 +6560,7 @@ function OhhwellsBridge() {
6208
6560
  useEffect3(() => {
6209
6561
  const update = () => {
6210
6562
  const el = activeElRef.current ?? selectedElRef.current;
6211
- if (el) setToolbarRect(el.getBoundingClientRect());
6563
+ if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
6212
6564
  setToggleState((prev) => {
6213
6565
  if (!prev || !activeStateElRef.current) return prev;
6214
6566
  return { ...prev, rect: activeStateElRef.current.getBoundingClientRect() };
@@ -6229,10 +6581,10 @@ function OhhwellsBridge() {
6229
6581
  vvp.removeEventListener("resize", update);
6230
6582
  };
6231
6583
  }, []);
6232
- const refreshStateRules = useCallback2(() => {
6584
+ const refreshStateRules = useCallback3(() => {
6233
6585
  editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
6234
6586
  }, []);
6235
- const processConfigRequest = useCallback2((insertAfterVal) => {
6587
+ const processConfigRequest = useCallback3((insertAfterVal) => {
6236
6588
  const tracker = getSectionsTracker();
6237
6589
  let entries = [];
6238
6590
  try {
@@ -6255,7 +6607,7 @@ function OhhwellsBridge() {
6255
6607
  }
6256
6608
  window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
6257
6609
  }, [isEditMode]);
6258
- const deactivate = useCallback2(() => {
6610
+ const deactivate = useCallback3(() => {
6259
6611
  const el = activeElRef.current;
6260
6612
  if (!el) return;
6261
6613
  const key = el.dataset.ohwKey;
@@ -6275,6 +6627,8 @@ function OhhwellsBridge() {
6275
6627
  }
6276
6628
  el.removeAttribute("contenteditable");
6277
6629
  activeElRef.current = null;
6630
+ setReorderHrefKey(null);
6631
+ setReorderDragDisabled(false);
6278
6632
  if (!selectedElRef.current) {
6279
6633
  setToolbarRect(null);
6280
6634
  setToolbarVariant("none");
@@ -6284,24 +6638,90 @@ function OhhwellsBridge() {
6284
6638
  setToolbarShowEditLink(false);
6285
6639
  postToParent({ type: "ow:exit-edit" });
6286
6640
  }, [postToParent]);
6287
- const deselect = useCallback2(() => {
6641
+ const deselect = useCallback3(() => {
6288
6642
  selectedElRef.current = null;
6643
+ setReorderHrefKey(null);
6644
+ setReorderDragDisabled(false);
6645
+ siblingHintElRef.current = null;
6646
+ setSiblingHintRect(null);
6647
+ setIsItemDragging(false);
6289
6648
  if (!activeElRef.current) {
6290
6649
  setToolbarRect(null);
6291
6650
  setToolbarVariant("none");
6292
6651
  }
6293
6652
  }, []);
6294
- const select = useCallback2((anchor) => {
6295
- if (!isNavbarButton(anchor)) return;
6653
+ const reselectNavigationItem = useCallback3((navAnchor) => {
6654
+ selectedElRef.current = navAnchor;
6655
+ const { key, disabled } = getNavigationItemReorderState(navAnchor);
6656
+ setReorderHrefKey(key);
6657
+ setReorderDragDisabled(disabled);
6658
+ setToolbarVariant("link-action");
6659
+ setToolbarRect(navAnchor.getBoundingClientRect());
6660
+ setToolbarShowEditLink(false);
6661
+ setActiveCommands(/* @__PURE__ */ new Set());
6662
+ }, []);
6663
+ const commitNavigationTextEdit = useCallback3((navAnchor) => {
6664
+ const el = activeElRef.current;
6665
+ if (!el) return;
6666
+ const key = el.dataset.ohwKey;
6667
+ if (key) {
6668
+ const timer = autoSaveTimers.current.get(key);
6669
+ if (timer !== void 0) {
6670
+ clearTimeout(timer);
6671
+ autoSaveTimers.current.delete(key);
6672
+ }
6673
+ const html = sanitizeHtml(el.innerHTML);
6674
+ const original = originalContentRef.current ?? "";
6675
+ if (html !== sanitizeHtml(original)) {
6676
+ postToParent({ type: "ow:change", nodes: [{ key, text: html }] });
6677
+ const h = document.documentElement.scrollHeight;
6678
+ if (h > 50) postToParent({ type: "ow:height", height: h });
6679
+ }
6680
+ }
6681
+ el.removeAttribute("contenteditable");
6682
+ activeElRef.current = null;
6683
+ setMaxBadge(null);
6684
+ setActiveCommands(/* @__PURE__ */ new Set());
6685
+ setToolbarShowEditLink(false);
6686
+ postToParent({ type: "ow:exit-edit" });
6687
+ reselectNavigationItem(navAnchor);
6688
+ }, [postToParent, reselectNavigationItem]);
6689
+ const handleAddNavigationItem = useCallback3(() => {
6690
+ const selected = selectedElRef.current;
6691
+ if (!selected) return;
6692
+ const target = getNavigationItemAddHintTarget(selected);
6693
+ siblingHintElRef.current = target;
6694
+ setSiblingHintRect(target.getBoundingClientRect());
6695
+ }, []);
6696
+ const handleItemDragStart = useCallback3(() => {
6697
+ siblingHintElRef.current = null;
6698
+ setSiblingHintRect(null);
6699
+ setIsItemDragging(true);
6700
+ }, []);
6701
+ const handleItemDragEnd = useCallback3(() => {
6702
+ setIsItemDragging(false);
6703
+ }, []);
6704
+ reselectNavigationItemRef.current = reselectNavigationItem;
6705
+ commitNavigationTextEditRef.current = commitNavigationTextEdit;
6706
+ const select = useCallback3((anchor) => {
6707
+ if (!isNavigationItem(anchor)) return;
6296
6708
  if (activeElRef.current) deactivate();
6297
6709
  selectedElRef.current = anchor;
6298
6710
  clearHrefKeyHover(anchor);
6711
+ setHoveredItemRect(null);
6712
+ hoveredItemElRef.current = null;
6713
+ siblingHintElRef.current = null;
6714
+ setSiblingHintRect(null);
6715
+ setIsItemDragging(false);
6716
+ const { key, disabled } = getNavigationItemReorderState(anchor);
6717
+ setReorderHrefKey(key);
6718
+ setReorderDragDisabled(disabled);
6299
6719
  setToolbarVariant("link-action");
6300
6720
  setToolbarRect(anchor.getBoundingClientRect());
6301
6721
  setToolbarShowEditLink(false);
6302
6722
  setActiveCommands(/* @__PURE__ */ new Set());
6303
6723
  }, [deactivate]);
6304
- const activate = useCallback2((el) => {
6724
+ const activate = useCallback3((el) => {
6305
6725
  if (activeElRef.current === el) return;
6306
6726
  selectedElRef.current = null;
6307
6727
  deactivate();
@@ -6310,13 +6730,26 @@ function OhhwellsBridge() {
6310
6730
  postToParentRef.current({ type: "ow:image-unhover" });
6311
6731
  }
6312
6732
  setToolbarVariant("rich-text");
6733
+ siblingHintElRef.current = null;
6734
+ setSiblingHintRect(null);
6735
+ setIsItemDragging(false);
6313
6736
  el.setAttribute("contenteditable", "true");
6314
6737
  el.removeAttribute("data-ohw-hovered");
6738
+ el.closest("[data-ohw-href-key]")?.removeAttribute("data-ohw-hovered");
6315
6739
  activeElRef.current = el;
6316
6740
  originalContentRef.current = el.innerHTML;
6317
6741
  el.focus();
6318
- setToolbarRect(el.getBoundingClientRect());
6319
6742
  setToolbarShowEditLink(Boolean(getHrefKeyFromElement(el)));
6743
+ const navAnchor = getNavigationItemAnchor(el);
6744
+ if (navAnchor) {
6745
+ setReorderHrefKey(null);
6746
+ setReorderDragDisabled(false);
6747
+ } else {
6748
+ const { key: reorderKey, disabled: reorderDisabled } = getReorderHandleState(el);
6749
+ setReorderHrefKey(reorderKey);
6750
+ setReorderDragDisabled(reorderDisabled);
6751
+ }
6752
+ setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
6320
6753
  postToParent({ type: "ow:enter-edit", key: el.dataset.ohwKey });
6321
6754
  requestAnimationFrame(() => refreshActiveCommandsRef.current());
6322
6755
  }, [deactivate, postToParent]);
@@ -6508,18 +6941,25 @@ function OhhwellsBridge() {
6508
6941
  [data-ohw-editable="image"], [data-ohw-editable="image"] *,
6509
6942
  [data-ohw-editable="bg-image"], [data-ohw-editable="bg-image"] * { cursor: pointer !important; }
6510
6943
  [data-ohw-editable="link"], [data-ohw-editable="link"] * { cursor: pointer !important; }
6511
- [data-ohw-hovered]:not([contenteditable]) {
6512
- outline: 2px dashed ${PRIMARY} !important;
6944
+ [data-ohw-hovered]:not([contenteditable]):not([data-ohw-href-key]) {
6945
+ outline: 2px dashed ${PRIMARY2} !important;
6513
6946
  outline-offset: 4px;
6514
6947
  border-radius: 2px;
6515
6948
  }
6949
+ [data-ohw-href-key] [data-ohw-hovered],
6950
+ [data-ohw-href-key][data-ohw-hovered],
6951
+ nav [data-ohw-href-key] [data-ohw-hovered],
6952
+ footer [data-ohw-href-key] [data-ohw-hovered] {
6953
+ outline: none !important;
6954
+ outline-offset: 0 !important;
6955
+ }
6516
6956
  [data-ohw-editable][contenteditable] {
6517
6957
  outline: none !important;
6518
- caret-color: ${PRIMARY};
6958
+ caret-color: ${PRIMARY2};
6519
6959
  cursor: text !important;
6520
6960
  }
6521
6961
  [data-ohw-editable][contenteditable]::selection,
6522
- [data-ohw-editable][contenteditable] *::selection { background: ${PRIMARY}59 !important; }
6962
+ [data-ohw-editable][contenteditable] *::selection { background: ${PRIMARY2}59 !important; }
6523
6963
  [data-ohw-editable-state], [data-ohw-editable-state] * { pointer-events: none !important; }
6524
6964
  [data-ohw-editable-state][data-ohw-active-state] [data-ohw-editable] { pointer-events: auto !important; }
6525
6965
  [data-ohw-editable-state][data-ohw-active-state][data-ohw-editable] { pointer-events: auto !important; }
@@ -6531,7 +6971,7 @@ function OhhwellsBridge() {
6531
6971
  stateViews.textContent = `
6532
6972
  [data-ohw-state-view]:not([data-ohw-state-view="default"]) { display: none; }
6533
6973
  [data-ohw-state-view="default"] [data-ohw-editable] { pointer-events: auto !important; }
6534
- [data-ohw-state-hovered] { outline: 2px dashed ${PRIMARY} !important; outline-offset: 4px; border-radius: 2px; }
6974
+ [data-ohw-state-hovered] { outline: 2px dashed ${PRIMARY2} !important; outline-offset: 4px; border-radius: 2px; }
6535
6975
  [data-ohw-state-hovered]:has([data-ohw-hovered]) { outline: none !important; }
6536
6976
  `;
6537
6977
  document.head.appendChild(base);
@@ -6546,6 +6986,11 @@ function OhhwellsBridge() {
6546
6986
  if (target.closest("[data-ohw-state-toggle]")) return;
6547
6987
  if (target.closest("[data-ohw-max-badge]")) return;
6548
6988
  if (isInsideLinkEditor(target)) return;
6989
+ if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
6990
+ e.preventDefault();
6991
+ e.stopPropagation();
6992
+ return;
6993
+ }
6549
6994
  const editable = target.closest("[data-ohw-editable]");
6550
6995
  if (editable) {
6551
6996
  if (editable.dataset.ohwEditable === "link") {
@@ -6567,15 +7012,15 @@ function OhhwellsBridge() {
6567
7012
  return;
6568
7013
  }
6569
7014
  const hrefCtx = getHrefKeyFromElement(editable);
6570
- if (hrefCtx && isNavbarButton(hrefCtx.anchor)) {
7015
+ const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
7016
+ if (navAnchor) {
6571
7017
  e.preventDefault();
6572
7018
  e.stopPropagation();
6573
- const { anchor: anchor2 } = hrefCtx;
6574
- if (selectedElRef.current === anchor2) {
7019
+ if (selectedElRef.current === navAnchor) {
6575
7020
  activateRef.current(editable);
6576
7021
  return;
6577
7022
  }
6578
- selectRef.current(anchor2);
7023
+ selectRef.current(navAnchor);
6579
7024
  return;
6580
7025
  }
6581
7026
  e.preventDefault();
@@ -6583,8 +7028,8 @@ function OhhwellsBridge() {
6583
7028
  activateRef.current(editable);
6584
7029
  return;
6585
7030
  }
6586
- const hrefAnchor = target.closest("[data-ohw-href-key]");
6587
- if (hrefAnchor && isNavbarButton(hrefAnchor)) {
7031
+ const hrefAnchor = getNavigationItemAnchor(target);
7032
+ if (hrefAnchor) {
6588
7033
  e.preventDefault();
6589
7034
  e.stopPropagation();
6590
7035
  if (selectedElRef.current === hrefAnchor) return;
@@ -6617,19 +7062,58 @@ function OhhwellsBridge() {
6617
7062
  deactivateRef.current();
6618
7063
  };
6619
7064
  const handleMouseOver = (e) => {
6620
- const editable = e.target.closest("[data-ohw-editable]");
7065
+ const target = e.target;
7066
+ const navAnchor = getNavigationItemAnchor(target);
7067
+ if (navAnchor) {
7068
+ const selected2 = selectedElRef.current;
7069
+ if (selected2 === navAnchor || selected2?.contains(navAnchor)) return;
7070
+ clearHrefKeyHover(navAnchor);
7071
+ hoveredItemElRef.current = navAnchor;
7072
+ setHoveredItemRect(navAnchor.getBoundingClientRect());
7073
+ return;
7074
+ }
7075
+ const editable = target.closest("[data-ohw-editable]");
6621
7076
  if (!editable) return;
6622
7077
  const selected = selectedElRef.current;
6623
7078
  if (selected && (selected === editable || selected.contains(editable))) return;
6624
7079
  if (editable.dataset.ohwEditable !== "image" && editable.dataset.ohwEditable !== "bg-image" && !editable.hasAttribute("contenteditable")) {
6625
- editable.setAttribute("data-ohw-hovered", "");
7080
+ const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
7081
+ if (hoverTarget.hasAttribute("data-ohw-href-key")) {
7082
+ clearHrefKeyHover(hoverTarget);
7083
+ hoveredItemElRef.current = hoverTarget;
7084
+ setHoveredItemRect(hoverTarget.getBoundingClientRect());
7085
+ } else if (!isInsideNavigationItem(editable)) {
7086
+ hoverTarget.setAttribute("data-ohw-hovered", "");
7087
+ }
6626
7088
  }
6627
7089
  };
6628
7090
  const handleMouseOut = (e) => {
6629
- const editable = e.target.closest("[data-ohw-editable]");
7091
+ const target = e.target;
7092
+ const navAnchor = getNavigationItemAnchor(target);
7093
+ if (navAnchor) {
7094
+ const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
7095
+ if (related2?.closest("[data-ohw-drag-handle-container], [data-ohw-item-interaction]")) return;
7096
+ if (related2 && navAnchor.contains(related2)) return;
7097
+ if (hoveredItemElRef.current === navAnchor) {
7098
+ hoveredItemElRef.current = null;
7099
+ setHoveredItemRect(null);
7100
+ }
7101
+ return;
7102
+ }
7103
+ const editable = target.closest("[data-ohw-editable]");
6630
7104
  if (!editable) return;
7105
+ const related = e.relatedTarget instanceof Element ? e.relatedTarget : null;
7106
+ if (related?.closest("[data-ohw-drag-handle-container], [data-ohw-item-interaction]")) return;
6631
7107
  if (editable.dataset.ohwEditable !== "image" && editable.dataset.ohwEditable !== "bg-image") {
6632
- editable.removeAttribute("data-ohw-hovered");
7108
+ const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
7109
+ if (hoverTarget.hasAttribute("data-ohw-href-key")) {
7110
+ if (!related?.closest("[data-ohw-href-key]")) {
7111
+ hoveredItemElRef.current = null;
7112
+ setHoveredItemRect(null);
7113
+ }
7114
+ } else {
7115
+ hoverTarget.removeAttribute("data-ohw-hovered");
7116
+ }
6633
7117
  }
6634
7118
  };
6635
7119
  const toProbeCoords = (clientX, clientY, fromParentViewport) => {
@@ -6744,11 +7228,20 @@ function OhhwellsBridge() {
6744
7228
  return;
6745
7229
  }
6746
7230
  }
7231
+ if (activeElRef.current) {
7232
+ if (hoveredImageRef.current) {
7233
+ hoveredImageRef.current = null;
7234
+ hoveredImageHasTextOverlapRef.current = false;
7235
+ resumeAnimTracks();
7236
+ postToParentRef.current({ type: "ow:image-unhover" });
7237
+ }
7238
+ return;
7239
+ }
6747
7240
  const imgEl = findImageAtPoint(clientX, clientY, fromParentViewport);
6748
7241
  if (imgEl) {
6749
7242
  const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
6750
7243
  const topEl = document.elementFromPoint(x, y);
6751
- if (topEl?.closest("[data-ohw-toolbar]")) {
7244
+ if (topEl?.closest('[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
6752
7245
  if (hoveredImageRef.current) {
6753
7246
  hoveredImageRef.current = null;
6754
7247
  resumeAnimTracks();
@@ -6796,7 +7289,9 @@ function OhhwellsBridge() {
6796
7289
  postImageHover(imgEl, isDragOver, true);
6797
7290
  }
6798
7291
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
6799
- textEditable.setAttribute("data-ohw-hovered", "");
7292
+ if (textEditable && !isInsideNavigationItem(textEditable)) {
7293
+ textEditable.setAttribute("data-ohw-hovered", "");
7294
+ }
6800
7295
  return;
6801
7296
  }
6802
7297
  if (hoveredImageRef.current) {
@@ -6806,7 +7301,9 @@ function OhhwellsBridge() {
6806
7301
  postToParentRef.current({ type: "ow:image-unhover" });
6807
7302
  }
6808
7303
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
6809
- textEditable.setAttribute("data-ohw-hovered", "");
7304
+ if (textEditable && !isInsideNavigationItem(textEditable)) {
7305
+ textEditable.setAttribute("data-ohw-hovered", "");
7306
+ }
6810
7307
  return;
6811
7308
  }
6812
7309
  if (hoveredGapRef.current) {
@@ -6850,7 +7347,24 @@ function OhhwellsBridge() {
6850
7347
  return x >= er.left && x <= er.right && y >= er.top && y <= er.bottom;
6851
7348
  });
6852
7349
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
6853
- if (textEl && !textEl.hasAttribute("contenteditable")) textEl.setAttribute("data-ohw-hovered", "");
7350
+ if (textEl && !textEl.hasAttribute("contenteditable")) {
7351
+ const navAnchor = getNavigationItemAnchor(textEl);
7352
+ if (navAnchor) {
7353
+ const selected = selectedElRef.current;
7354
+ if (selected !== navAnchor && !selected?.contains(navAnchor)) {
7355
+ clearHrefKeyHover(navAnchor);
7356
+ hoveredItemElRef.current = navAnchor;
7357
+ setHoveredItemRect(navAnchor.getBoundingClientRect());
7358
+ }
7359
+ } else {
7360
+ hoveredItemElRef.current = null;
7361
+ setHoveredItemRect(null);
7362
+ textEl.setAttribute("data-ohw-hovered", "");
7363
+ }
7364
+ } else {
7365
+ hoveredItemElRef.current = null;
7366
+ setHoveredItemRect(null);
7367
+ }
6854
7368
  }
6855
7369
  };
6856
7370
  const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
@@ -7041,7 +7555,7 @@ function OhhwellsBridge() {
7041
7555
  const el = e.target;
7042
7556
  const key = el.dataset.ohwKey;
7043
7557
  if (!key) return;
7044
- if (el === activeElRef.current) setToolbarRect(el.getBoundingClientRect());
7558
+ if (el === activeElRef.current) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
7045
7559
  const maxLen = el.dataset.ohwMaxLength ? parseInt(el.dataset.ohwMaxLength, 10) : null;
7046
7560
  if (maxLen) {
7047
7561
  const current = el.innerText.replace(/\n$/, "").length;
@@ -7128,6 +7642,33 @@ function OhhwellsBridge() {
7128
7642
  deselectRef.current();
7129
7643
  return;
7130
7644
  }
7645
+ if (e.key === "Escape" && activeElRef.current) {
7646
+ const hrefCtx = getHrefKeyFromElement(activeElRef.current);
7647
+ const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
7648
+ if (navAnchor) {
7649
+ e.preventDefault();
7650
+ const el2 = activeElRef.current;
7651
+ if (originalContentRef.current !== null) {
7652
+ el2.innerHTML = originalContentRef.current;
7653
+ }
7654
+ el2.removeAttribute("contenteditable");
7655
+ activeElRef.current = null;
7656
+ setMaxBadge(null);
7657
+ setActiveCommands(/* @__PURE__ */ new Set());
7658
+ setToolbarShowEditLink(false);
7659
+ postToParentRef.current({ type: "ow:exit-edit" });
7660
+ reselectNavigationItemRef.current(navAnchor);
7661
+ return;
7662
+ }
7663
+ }
7664
+ if (e.key === "Enter" && !e.shiftKey && activeElRef.current) {
7665
+ const navAnchor = getNavigationItemAnchor(activeElRef.current);
7666
+ if (navAnchor) {
7667
+ e.preventDefault();
7668
+ commitNavigationTextEditRef.current(navAnchor);
7669
+ return;
7670
+ }
7671
+ }
7131
7672
  if (e.key !== "Escape") return;
7132
7673
  const el = activeElRef.current;
7133
7674
  if (el && originalContentRef.current !== null) {
@@ -7143,7 +7684,8 @@ function OhhwellsBridge() {
7143
7684
  const handleScroll = () => {
7144
7685
  const focusEl = activeElRef.current ?? selectedElRef.current;
7145
7686
  if (focusEl) {
7146
- const r2 = focusEl.getBoundingClientRect();
7687
+ const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : focusEl;
7688
+ const r2 = measureEl.getBoundingClientRect();
7147
7689
  applyToolbarPos(r2);
7148
7690
  setToolbarRect(r2);
7149
7691
  setMaxBadge((prev) => prev && activeElRef.current ? { ...prev, rect: r2 } : prev);
@@ -7152,6 +7694,12 @@ function OhhwellsBridge() {
7152
7694
  const rect = activeStateElRef.current.getBoundingClientRect();
7153
7695
  setToggleState((prev) => prev ? { ...prev, rect } : null);
7154
7696
  }
7697
+ if (hoveredItemElRef.current) {
7698
+ setHoveredItemRect(hoveredItemElRef.current.getBoundingClientRect());
7699
+ }
7700
+ if (siblingHintElRef.current) {
7701
+ setSiblingHintRect(siblingHintElRef.current.getBoundingClientRect());
7702
+ }
7155
7703
  if (hoveredImageRef.current) {
7156
7704
  const el = hoveredImageRef.current;
7157
7705
  const r2 = el.getBoundingClientRect();
@@ -7271,7 +7819,7 @@ function OhhwellsBridge() {
7271
7819
  };
7272
7820
  const applyToolbarPos = (rect) => {
7273
7821
  const ps = parentScrollRef.current;
7274
- const approxW = toolbarVariantRef.current === "link-action" ? 120 : 330;
7822
+ const approxW = 330;
7275
7823
  if (toolbarElRef.current) {
7276
7824
  const { top, left, transform } = calcToolbarPos(rect, ps, approxW);
7277
7825
  toolbarElRef.current.style.top = `${top}px`;
@@ -7282,6 +7830,8 @@ function OhhwellsBridge() {
7282
7830
  const GAP = 6;
7283
7831
  glowElRef.current.style.top = `${rect.top - GAP}px`;
7284
7832
  glowElRef.current.style.left = `${rect.left - GAP}px`;
7833
+ glowElRef.current.style.width = `${rect.width + GAP * 2}px`;
7834
+ glowElRef.current.style.height = `${rect.height + GAP * 2}px`;
7285
7835
  }
7286
7836
  };
7287
7837
  const handleParentScroll = (e) => {
@@ -7292,7 +7842,10 @@ function OhhwellsBridge() {
7292
7842
  applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
7293
7843
  }
7294
7844
  const focusEl = activeElRef.current ?? selectedElRef.current;
7295
- if (focusEl) applyToolbarPos(focusEl.getBoundingClientRect());
7845
+ if (focusEl) {
7846
+ const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : focusEl;
7847
+ applyToolbarPos(measureEl.getBoundingClientRect());
7848
+ }
7296
7849
  };
7297
7850
  const handleClickAt = (e) => {
7298
7851
  if (e.data?.type !== "ow:click-at") return;
@@ -7447,13 +8000,13 @@ function OhhwellsBridge() {
7447
8000
  window.addEventListener("hashchange", onHashChange);
7448
8001
  return () => window.removeEventListener("hashchange", onHashChange);
7449
8002
  }, [pathname]);
7450
- const handleCommand = useCallback2((cmd) => {
8003
+ const handleCommand = useCallback3((cmd) => {
7451
8004
  document.execCommand(cmd, false);
7452
8005
  activeElRef.current?.focus();
7453
- if (activeElRef.current) setToolbarRect(activeElRef.current.getBoundingClientRect());
8006
+ if (activeElRef.current) setToolbarRect(getEditMeasureEl(activeElRef.current).getBoundingClientRect());
7454
8007
  refreshActiveCommandsRef.current();
7455
8008
  }, []);
7456
- const handleStateChange = useCallback2((state) => {
8009
+ const handleStateChange = useCallback3((state) => {
7457
8010
  if (!activeStateElRef.current) return;
7458
8011
  const el = activeStateElRef.current;
7459
8012
  if (state === "Default") {
@@ -7466,8 +8019,8 @@ function OhhwellsBridge() {
7466
8019
  }
7467
8020
  setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
7468
8021
  }, [deactivate]);
7469
- const closeLinkPopover = useCallback2(() => setLinkPopover(null), []);
7470
- const openLinkPopoverForActive = useCallback2(() => {
8022
+ const closeLinkPopover = useCallback3(() => setLinkPopover(null), []);
8023
+ const openLinkPopoverForActive = useCallback3(() => {
7471
8024
  const hrefCtx = getHrefKeyFromElement(activeElRef.current);
7472
8025
  if (!hrefCtx) return;
7473
8026
  bumpLinkPopoverGrace();
@@ -7477,7 +8030,7 @@ function OhhwellsBridge() {
7477
8030
  });
7478
8031
  deactivate();
7479
8032
  }, [deactivate]);
7480
- const openLinkPopoverForSelected = useCallback2(() => {
8033
+ const openLinkPopoverForSelected = useCallback3(() => {
7481
8034
  const anchor = selectedElRef.current;
7482
8035
  if (!anchor) return;
7483
8036
  const key = anchor.getAttribute("data-ohw-href-key");
@@ -7489,7 +8042,7 @@ function OhhwellsBridge() {
7489
8042
  });
7490
8043
  deselect();
7491
8044
  }, [deselect]);
7492
- const handleLinkPopoverSubmit = useCallback2(
8045
+ const handleLinkPopoverSubmit = useCallback3(
7493
8046
  (target) => {
7494
8047
  if (!linkPopover) return;
7495
8048
  const { key } = linkPopover;
@@ -7503,37 +8056,55 @@ function OhhwellsBridge() {
7503
8056
  const currentSections = sectionsByPath[pathname] ?? [];
7504
8057
  linkPopoverOpenRef.current = linkPopover !== null;
7505
8058
  return bridgeRoot ? createPortal(
7506
- /* @__PURE__ */ jsxs9(Fragment3, { children: [
7507
- /* @__PURE__ */ jsx16("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
7508
- toolbarRect && /* @__PURE__ */ jsxs9(Fragment3, { children: [
7509
- /* @__PURE__ */ jsx16(GlowFrame, { rect: toolbarRect, elRef: glowElRef }),
7510
- toolbarVariant === "rich-text" && /* @__PURE__ */ jsx16(
7511
- FloatingToolbar,
8059
+ /* @__PURE__ */ jsxs11(Fragment3, { children: [
8060
+ /* @__PURE__ */ jsx21("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
8061
+ siblingHintRect && !isItemDragging && /* @__PURE__ */ jsx21(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
8062
+ hoveredItemRect && !siblingHintRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx21(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
8063
+ toolbarRect && toolbarVariant === "link-action" && /* @__PURE__ */ jsx21(
8064
+ ItemInteractionLayer,
8065
+ {
8066
+ rect: toolbarRect,
8067
+ elRef: glowElRef,
8068
+ state: isItemDragging ? "dragging" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
8069
+ showHandle: Boolean(reorderHrefKey),
8070
+ dragDisabled: reorderDragDisabled,
8071
+ dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
8072
+ onDragHandleDragStart: handleItemDragStart,
8073
+ onDragHandleDragEnd: handleItemDragEnd,
8074
+ toolbar: isItemDragging ? void 0 : /* @__PURE__ */ jsx21(
8075
+ ItemActionToolbar,
8076
+ {
8077
+ onEditLink: openLinkPopoverForSelected,
8078
+ onAddItem: handleAddNavigationItem,
8079
+ addItemDisabled: false
8080
+ }
8081
+ )
8082
+ }
8083
+ ),
8084
+ toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ jsxs11(Fragment3, { children: [
8085
+ /* @__PURE__ */ jsx21(
8086
+ EditGlowChrome,
7512
8087
  {
7513
- variant: "rich-text",
7514
8088
  rect: toolbarRect,
7515
- parentScroll: parentScrollRef.current,
7516
- elRef: toolbarElRef,
7517
- onCommand: handleCommand,
7518
- activeCommands,
7519
- showEditLink,
7520
- onEditLink: openLinkPopoverForActive
8089
+ elRef: glowElRef,
8090
+ reorderHrefKey,
8091
+ dragDisabled: reorderDragDisabled
7521
8092
  }
7522
8093
  ),
7523
- toolbarVariant === "link-action" && /* @__PURE__ */ jsx16(
8094
+ /* @__PURE__ */ jsx21(
7524
8095
  FloatingToolbar,
7525
8096
  {
7526
- variant: "link-action",
7527
8097
  rect: toolbarRect,
7528
8098
  parentScroll: parentScrollRef.current,
7529
8099
  elRef: toolbarElRef,
7530
8100
  onCommand: handleCommand,
7531
8101
  activeCommands,
7532
- onEditLink: openLinkPopoverForSelected
8102
+ showEditLink,
8103
+ onEditLink: openLinkPopoverForActive
7533
8104
  }
7534
8105
  )
7535
8106
  ] }),
7536
- maxBadge && /* @__PURE__ */ jsxs9(
8107
+ maxBadge && /* @__PURE__ */ jsxs11(
7537
8108
  "div",
7538
8109
  {
7539
8110
  "data-ohw-max-badge": "",
@@ -7559,7 +8130,7 @@ function OhhwellsBridge() {
7559
8130
  ]
7560
8131
  }
7561
8132
  ),
7562
- toggleState && /* @__PURE__ */ jsx16(
8133
+ toggleState && /* @__PURE__ */ jsx21(
7563
8134
  StateToggle,
7564
8135
  {
7565
8136
  rect: toggleState.rect,
@@ -7568,15 +8139,15 @@ function OhhwellsBridge() {
7568
8139
  onStateChange: handleStateChange
7569
8140
  }
7570
8141
  ),
7571
- sectionGap && /* @__PURE__ */ jsxs9(
8142
+ sectionGap && /* @__PURE__ */ jsxs11(
7572
8143
  "div",
7573
8144
  {
7574
8145
  "data-ohw-section-insert-line": "",
7575
8146
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
7576
8147
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
7577
8148
  children: [
7578
- /* @__PURE__ */ jsx16("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
7579
- /* @__PURE__ */ jsx16(
8149
+ /* @__PURE__ */ jsx21("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
8150
+ /* @__PURE__ */ jsx21(
7580
8151
  Badge,
7581
8152
  {
7582
8153
  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",
@@ -7589,11 +8160,11 @@ function OhhwellsBridge() {
7589
8160
  children: "Add Section"
7590
8161
  }
7591
8162
  ),
7592
- /* @__PURE__ */ jsx16("div", { className: "flex-1 bg-primary", style: { height: 3 } })
8163
+ /* @__PURE__ */ jsx21("div", { className: "flex-1 bg-primary", style: { height: 3 } })
7593
8164
  ]
7594
8165
  }
7595
8166
  ),
7596
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx16(
8167
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx21(
7597
8168
  LinkPopover,
7598
8169
  {
7599
8170
  panelRef: linkPopoverPanelRef,
@@ -7608,12 +8179,43 @@ function OhhwellsBridge() {
7608
8179
  onSubmit: handleLinkPopoverSubmit
7609
8180
  },
7610
8181
  `${linkPopover.key}-${pathname}`
7611
- ) : null
8182
+ ) : null,
8183
+ sectionGap && /* @__PURE__ */ jsxs11(
8184
+ "div",
8185
+ {
8186
+ "data-ohw-section-insert-line": "",
8187
+ className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
8188
+ style: { top: sectionGap.y, transform: "translateY(-50%)" },
8189
+ children: [
8190
+ /* @__PURE__ */ jsx21("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
8191
+ /* @__PURE__ */ jsx21(
8192
+ Badge,
8193
+ {
8194
+ 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",
8195
+ onClick: () => {
8196
+ window.parent.postMessage(
8197
+ { type: "ow:add-section", insertAfter: sectionGap.insertAfter, insertBefore: sectionGap.insertBefore },
8198
+ "*"
8199
+ );
8200
+ },
8201
+ children: "Add Section"
8202
+ }
8203
+ ),
8204
+ /* @__PURE__ */ jsx21("div", { className: "flex-1 bg-primary", style: { height: 3 } })
8205
+ ]
8206
+ }
8207
+ )
7612
8208
  ] }),
7613
8209
  bridgeRoot
7614
8210
  ) : null;
7615
8211
  }
7616
8212
  export {
8213
+ CustomToolbar,
8214
+ CustomToolbarButton,
8215
+ CustomToolbarDivider,
8216
+ DragHandle,
8217
+ ItemActionToolbar,
8218
+ ItemInteractionLayer,
7617
8219
  LinkEditorPanel,
7618
8220
  LinkPopover,
7619
8221
  OhhwellsBridge,
@@ -7621,9 +8223,14 @@ export {
7621
8223
  Toggle,
7622
8224
  ToggleGroup,
7623
8225
  ToggleGroupItem,
8226
+ Tooltip,
8227
+ TooltipContent,
8228
+ TooltipProvider,
8229
+ TooltipTrigger,
7624
8230
  buildTarget,
7625
8231
  filterAvailablePages,
7626
8232
  getEditModeInitialState,
8233
+ isEditSessionActive,
7627
8234
  isValidUrl,
7628
8235
  parseTarget,
7629
8236
  toggleVariants,