@ohhwells/bridge 0.1.33 → 0.1.34-next.41

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 useCallback2, useEffect as useEffect3, useLayoutEffect as useLayoutEffect2, useRef as useRef3, useState as useState5 } from "react";
5
5
  import { createRoot } from "react-dom/client";
6
6
  import { flushSync } from "react-dom";
7
7
 
@@ -221,12 +221,20 @@ function formatClassTime(cls) {
221
221
  const em = endTotal % 60;
222
222
  return `${h}:${cls.startTime.minutes}-${eh}:${String(em).padStart(2, "0")}`;
223
223
  }
224
+ function formatBookingLabel(cls) {
225
+ const price = cls.price;
226
+ const isFree = price === null || price === void 0 || `${price}` === "" || `${price}` === "0";
227
+ return isFree ? "Book for free" : `Book for ${cls.currency ?? ""} ${price}`.trim();
228
+ }
224
229
  function getBookingsOnDate(cls, date) {
225
230
  if (!cls.bookings?.length) return 0;
226
- const ds = date.toISOString().split("T")[0];
231
+ const target = new Date(date);
232
+ target.setHours(0, 0, 0, 0);
227
233
  return cls.bookings.filter((b) => {
228
234
  try {
229
- return new Date(b.classDate).toISOString().split("T")[0] === ds;
235
+ const bookingDate = new Date(b.classDate);
236
+ bookingDate.setHours(0, 0, 0, 0);
237
+ return bookingDate.getTime() === target.getTime();
230
238
  } catch {
231
239
  return false;
232
240
  }
@@ -530,7 +538,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
530
538
  if (!cls.id) return;
531
539
  onOpenModal?.(isFull ? "waitlist" : "book", cls.id, selectedDate);
532
540
  },
533
- children: isFull ? "Join Waitlist" : "Book Now"
541
+ children: isFull ? "Join Waitlist" : formatBookingLabel(cls)
534
542
  }
535
543
  )
536
544
  ] })
@@ -712,15 +720,10 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
712
720
  };
713
721
  const handleReplaceSchedule = () => {
714
722
  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
- }
723
+ window.parent.postMessage(
724
+ { type: "ow:scheduling-not-connected", insertAfter, currentScheduleId: schedule?.id },
725
+ "*"
726
+ );
724
727
  };
725
728
  if (!inEditor && !loading && !schedule) return null;
726
729
  const sectionId = `scheduling-${insertAfter}`;
@@ -763,7 +766,19 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
763
766
  ),
764
767
  /* @__PURE__ */ jsxs2("div", { className: "max-w-[1280px] mx-auto flex flex-col items-center gap-16", children: [
765
768
  /* @__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" }),
769
+ /* @__PURE__ */ jsx2(
770
+ "h2",
771
+ {
772
+ className: "font-display text-center m-0 text-(--color-dark,#200C02)",
773
+ style: {
774
+ fontSize: "var(--fs-section-h2, clamp(40px, 4.4vw, 64px))",
775
+ fontWeight: "var(--font-weight-heading, 400)",
776
+ lineHeight: 1.05,
777
+ letterSpacing: "-0.02em"
778
+ },
779
+ children: schedule?.name ?? "Book an appointment"
780
+ }
781
+ ),
767
782
  schedule?.description && /* @__PURE__ */ jsx2("p", { className: "font-body text-body text-center m-0 text-(--color-accent,#A89B83)", children: schedule.description })
768
783
  ] }),
769
784
  /* @__PURE__ */ jsxs2("div", { className: "w-full flex flex-col items-end gap-3", children: [
@@ -4202,6 +4217,336 @@ function ToggleGroupItem({
4202
4217
  );
4203
4218
  }
4204
4219
 
4220
+ // src/ui/drag-handle.tsx
4221
+ import * as React3 from "react";
4222
+ import { GripVertical } from "lucide-react";
4223
+ import { jsx as jsx5 } from "react/jsx-runtime";
4224
+ var DragHandle = React3.forwardRef(
4225
+ ({ className, type = "button", ...props }, ref) => {
4226
+ return /* @__PURE__ */ jsx5(
4227
+ "button",
4228
+ {
4229
+ ref,
4230
+ type,
4231
+ "data-slot": "drag-handle",
4232
+ className: cn(
4233
+ "inline-flex h-7 w-4 shrink-0 items-center justify-center rounded-md transition-all duration-200 max-h-[30px]",
4234
+ "bg-white border border-transparent text-stone-500 shadow-md cursor-grab",
4235
+ "enabled:hover:border enabled:hover:border-stone-200 enabled:hover:text-stone-950",
4236
+ "enabled:active:border enabled:active:border-primary enabled:active:bg-primary-50 enabled:active:text-stone-950 enabled:active:shadow enabled:active:cursor-grabbing",
4237
+ "disabled:cursor-not-allowed disabled:opacity-40 disabled:text-stone-950 disabled:pointer-events-none",
4238
+ className
4239
+ ),
4240
+ ...props,
4241
+ children: /* @__PURE__ */ jsx5(GripVertical, { className: "size-4 shrink-0", "aria-hidden": "true" })
4242
+ }
4243
+ );
4244
+ }
4245
+ );
4246
+ DragHandle.displayName = "DragHandle";
4247
+
4248
+ // src/ui/custom-toolbar.tsx
4249
+ import * as React4 from "react";
4250
+ import { jsx as jsx6 } from "react/jsx-runtime";
4251
+ var CustomToolbar = React4.forwardRef(({ className, onMouseDown, ...props }, ref) => /* @__PURE__ */ jsx6(
4252
+ "div",
4253
+ {
4254
+ ref,
4255
+ "data-ohw-toolbar": "",
4256
+ className: cn(
4257
+ "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)]",
4258
+ className
4259
+ ),
4260
+ onMouseDown: (e) => {
4261
+ e.stopPropagation();
4262
+ onMouseDown?.(e);
4263
+ },
4264
+ ...props
4265
+ }
4266
+ ));
4267
+ CustomToolbar.displayName = "CustomToolbar";
4268
+ function CustomToolbarDivider({ className, ...props }) {
4269
+ return /* @__PURE__ */ jsx6(
4270
+ "span",
4271
+ {
4272
+ "aria-hidden": true,
4273
+ className: cn("block h-6 w-px shrink-0 bg-border", className),
4274
+ ...props
4275
+ }
4276
+ );
4277
+ }
4278
+ var CustomToolbarButton = React4.forwardRef(
4279
+ ({ className, active = false, type = "button", ...props }, ref) => /* @__PURE__ */ jsx6(
4280
+ "button",
4281
+ {
4282
+ ref,
4283
+ type,
4284
+ className: cn(
4285
+ "inline-flex shrink-0 items-center justify-center rounded p-1.5 transition-colors",
4286
+ active ? "bg-primary text-primary-foreground" : "bg-transparent text-foreground hover:bg-muted disabled:cursor-not-allowed disabled:text-muted-foreground disabled:opacity-60",
4287
+ className
4288
+ ),
4289
+ ...props
4290
+ }
4291
+ )
4292
+ );
4293
+ CustomToolbarButton.displayName = "CustomToolbarButton";
4294
+
4295
+ // src/ui/item-action-toolbar.tsx
4296
+ import { Link, MoreHorizontal, Plus } from "lucide-react";
4297
+
4298
+ // src/ui/tooltip.tsx
4299
+ import { Tooltip as TooltipPrimitive } from "radix-ui";
4300
+ import { jsx as jsx7 } from "react/jsx-runtime";
4301
+ function TooltipProvider({
4302
+ delayDuration = 0,
4303
+ ...props
4304
+ }) {
4305
+ return /* @__PURE__ */ jsx7(TooltipPrimitive.Provider, { "data-slot": "tooltip-provider", delayDuration, ...props });
4306
+ }
4307
+ function Tooltip({ ...props }) {
4308
+ return /* @__PURE__ */ jsx7(TooltipPrimitive.Root, { "data-slot": "tooltip", ...props });
4309
+ }
4310
+ function TooltipTrigger({ ...props }) {
4311
+ return /* @__PURE__ */ jsx7(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
4312
+ }
4313
+ var arrowClassBySide = {
4314
+ top: "before:bottom-0 before:left-1/2 before:-translate-x-1/2 before:translate-y-1/2",
4315
+ bottom: "before:top-0 before:left-1/2 before:-translate-x-1/2 before:-translate-y-1/2",
4316
+ left: "before:right-0 before:top-1/2 before:-translate-y-1/2 before:translate-x-1/2",
4317
+ right: "before:left-0 before:top-1/2 before:-translate-y-1/2 before:-translate-x-1/2"
4318
+ };
4319
+ function TooltipContent({
4320
+ className,
4321
+ sideOffset = 6,
4322
+ side = "bottom",
4323
+ children,
4324
+ ...props
4325
+ }) {
4326
+ const resolvedSide = side ?? "bottom";
4327
+ return /* @__PURE__ */ jsx7(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx7(
4328
+ TooltipPrimitive.Content,
4329
+ {
4330
+ "data-slot": "tooltip-content",
4331
+ side,
4332
+ sideOffset,
4333
+ className: cn(
4334
+ "relative z-[2147483647] w-fit max-w-xs rounded-md bg-foreground px-3 py-1.5 text-xs text-background shadow-md",
4335
+ 'before:pointer-events-none before:absolute before:size-2 before:rotate-45 before:bg-foreground before:content-[""]',
4336
+ arrowClassBySide[resolvedSide],
4337
+ "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",
4338
+ "data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2",
4339
+ "data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2",
4340
+ className
4341
+ ),
4342
+ ...props,
4343
+ children
4344
+ }
4345
+ ) });
4346
+ }
4347
+
4348
+ // src/ui/item-action-toolbar.tsx
4349
+ import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
4350
+ function ToolbarActionTooltip({
4351
+ label,
4352
+ side = "bottom",
4353
+ disabled = false,
4354
+ buttonProps,
4355
+ children
4356
+ }) {
4357
+ const button = /* @__PURE__ */ jsx8(CustomToolbarButton, { type: "button", "aria-label": label, disabled, ...buttonProps, children });
4358
+ return /* @__PURE__ */ jsxs3(Tooltip, { children: [
4359
+ /* @__PURE__ */ jsx8(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ jsx8("span", { className: "inline-flex", children: button }) : button }),
4360
+ /* @__PURE__ */ jsx8(TooltipContent, { side, children: label })
4361
+ ] });
4362
+ }
4363
+ function ItemActionToolbar({
4364
+ onEditLink,
4365
+ onAddItem,
4366
+ onMore,
4367
+ addItemDisabled = true,
4368
+ moreDisabled = true,
4369
+ tooltipSide = "bottom"
4370
+ }) {
4371
+ return /* @__PURE__ */ jsx8(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs3(CustomToolbar, { children: [
4372
+ /* @__PURE__ */ jsx8(
4373
+ ToolbarActionTooltip,
4374
+ {
4375
+ label: "Add link",
4376
+ side: tooltipSide,
4377
+ buttonProps: {
4378
+ onMouseDown: (e) => {
4379
+ e.preventDefault();
4380
+ e.stopPropagation();
4381
+ onEditLink?.();
4382
+ },
4383
+ onClick: (e) => {
4384
+ e.preventDefault();
4385
+ e.stopPropagation();
4386
+ }
4387
+ },
4388
+ children: /* @__PURE__ */ jsx8(Link, { className: "size-4 shrink-0", "aria-hidden": true })
4389
+ }
4390
+ ),
4391
+ /* @__PURE__ */ jsx8(CustomToolbarDivider, {}),
4392
+ /* @__PURE__ */ jsx8(
4393
+ ToolbarActionTooltip,
4394
+ {
4395
+ label: "Add item",
4396
+ side: tooltipSide,
4397
+ disabled: addItemDisabled,
4398
+ buttonProps: {
4399
+ onMouseDown: (e) => {
4400
+ if (addItemDisabled) return;
4401
+ e.preventDefault();
4402
+ e.stopPropagation();
4403
+ onAddItem?.();
4404
+ }
4405
+ },
4406
+ children: /* @__PURE__ */ jsx8(Plus, { className: "size-4 shrink-0", "aria-hidden": true })
4407
+ }
4408
+ ),
4409
+ /* @__PURE__ */ jsx8(CustomToolbarDivider, {}),
4410
+ /* @__PURE__ */ jsx8(
4411
+ ToolbarActionTooltip,
4412
+ {
4413
+ label: "More",
4414
+ side: tooltipSide,
4415
+ disabled: moreDisabled,
4416
+ buttonProps: {
4417
+ onMouseDown: (e) => {
4418
+ if (moreDisabled) return;
4419
+ e.preventDefault();
4420
+ e.stopPropagation();
4421
+ onMore?.();
4422
+ }
4423
+ },
4424
+ children: /* @__PURE__ */ jsx8(MoreHorizontal, { className: "size-4 shrink-0", "aria-hidden": true })
4425
+ }
4426
+ )
4427
+ ] }) });
4428
+ }
4429
+
4430
+ // src/ui/item-interaction-layer.tsx
4431
+ import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
4432
+ var PRIMARY = "var(--ohw-primary, #0885FE)";
4433
+ var FOCUS_RING = "0 0 0 4px rgba(8, 133, 254, 0.12)";
4434
+ var DRAG_SHADOW = "0px 4px 6px -1px rgba(0, 0, 0, 0.1), 0px 2px 4px -2px rgba(0, 0, 0, 0.1)";
4435
+ function getChromeStyle(state) {
4436
+ switch (state) {
4437
+ case "hover":
4438
+ return {
4439
+ border: `1.5px dashed ${PRIMARY}`,
4440
+ boxShadow: "none"
4441
+ };
4442
+ case "sibling-hint":
4443
+ return {
4444
+ border: `1.5px dashed color-mix(in srgb, ${PRIMARY} 30%, transparent)`,
4445
+ boxShadow: "none"
4446
+ };
4447
+ case "active-top":
4448
+ case "active-bottom":
4449
+ return {
4450
+ border: `2px solid ${PRIMARY}`,
4451
+ boxShadow: FOCUS_RING
4452
+ };
4453
+ case "dragging":
4454
+ return {
4455
+ border: `2px solid ${PRIMARY}`,
4456
+ boxShadow: DRAG_SHADOW
4457
+ };
4458
+ default:
4459
+ return {};
4460
+ }
4461
+ }
4462
+ function ItemInteractionLayer({
4463
+ rect,
4464
+ state,
4465
+ elRef,
4466
+ toolbar,
4467
+ showHandle = false,
4468
+ dragDisabled = false,
4469
+ dragHandleLabel = "Reorder item",
4470
+ onDragHandleDragStart,
4471
+ onDragHandleDragEnd,
4472
+ chromeGap = 6,
4473
+ className
4474
+ }) {
4475
+ if (state === "default") return null;
4476
+ const isActive = state === "active-top" || state === "active-bottom";
4477
+ const isDragging = state === "dragging";
4478
+ const showToolbar = isActive && toolbar;
4479
+ const showDragHandle = isActive && showHandle && !isDragging;
4480
+ return /* @__PURE__ */ jsxs4(
4481
+ "div",
4482
+ {
4483
+ ref: elRef,
4484
+ "data-ohw-item-interaction": "",
4485
+ "data-ohw-item-interaction-state": state,
4486
+ className: cn("pointer-events-none", className),
4487
+ style: {
4488
+ position: "fixed",
4489
+ top: rect.top - chromeGap,
4490
+ left: rect.left - chromeGap,
4491
+ width: rect.width + chromeGap * 2,
4492
+ height: rect.height + chromeGap * 2,
4493
+ zIndex: 2147483646
4494
+ },
4495
+ children: [
4496
+ /* @__PURE__ */ jsx9(
4497
+ "div",
4498
+ {
4499
+ "aria-hidden": true,
4500
+ className: "absolute inset-0 rounded-lg",
4501
+ style: getChromeStyle(state)
4502
+ }
4503
+ ),
4504
+ showDragHandle && /* @__PURE__ */ jsx9(
4505
+ "div",
4506
+ {
4507
+ "data-ohw-drag-handle-container": "",
4508
+ className: "pointer-events-auto absolute left-0 top-1/2 -translate-x-[calc(100%+7px)] -translate-y-1/2",
4509
+ children: /* @__PURE__ */ jsx9(
4510
+ DragHandle,
4511
+ {
4512
+ draggable: !dragDisabled,
4513
+ "aria-label": dragHandleLabel,
4514
+ disabled: dragDisabled,
4515
+ onDragStart: (e) => {
4516
+ if (dragDisabled) {
4517
+ e.preventDefault();
4518
+ return;
4519
+ }
4520
+ e.dataTransfer?.setData("text/plain", dragHandleLabel);
4521
+ e.dataTransfer.effectAllowed = "move";
4522
+ onDragHandleDragStart?.(e);
4523
+ },
4524
+ onDragEnd: onDragHandleDragEnd
4525
+ }
4526
+ )
4527
+ }
4528
+ ),
4529
+ showToolbar && state === "active-top" && /* @__PURE__ */ jsx9(
4530
+ "div",
4531
+ {
4532
+ className: "pointer-events-auto absolute bottom-full left-1/2 mb-2 -translate-x-1/2",
4533
+ "data-ohw-item-toolbar-anchor": "top",
4534
+ children: toolbar
4535
+ }
4536
+ ),
4537
+ showToolbar && state === "active-bottom" && /* @__PURE__ */ jsx9(
4538
+ "div",
4539
+ {
4540
+ className: "pointer-events-auto absolute left-1/2 top-full mt-2 -translate-x-1/2",
4541
+ "data-ohw-item-toolbar-anchor": "bottom",
4542
+ children: toolbar
4543
+ }
4544
+ )
4545
+ ]
4546
+ }
4547
+ );
4548
+ }
4549
+
4205
4550
  // src/OhhwellsBridge.tsx
4206
4551
  import { createPortal } from "react-dom";
4207
4552
  import { usePathname, useRouter, useSearchParams } from "next/navigation";
@@ -4481,60 +4826,60 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
4481
4826
  }
4482
4827
 
4483
4828
  // src/ui/dialog.tsx
4484
- import * as React3 from "react";
4829
+ import * as React5 from "react";
4485
4830
  import { Dialog as DialogPrimitive } from "radix-ui";
4486
4831
 
4487
4832
  // src/ui/icons.tsx
4488
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
4833
+ import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
4489
4834
  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" })
4835
+ 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: [
4836
+ /* @__PURE__ */ jsx10("path", { d: "M18 6 6 18" }),
4837
+ /* @__PURE__ */ jsx10("path", { d: "m6 6 12 12" })
4493
4838
  ] });
4494
4839
  }
4495
4840
  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" }) });
4841
+ 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
4842
  }
4498
4843
  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" })
4844
+ 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: [
4845
+ /* @__PURE__ */ jsx10("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }),
4846
+ /* @__PURE__ */ jsx10("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" })
4502
4847
  ] });
4503
4848
  }
4504
4849
  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" })
4850
+ 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: [
4851
+ /* @__PURE__ */ jsx10("circle", { cx: "12", cy: "12", r: "10" }),
4852
+ /* @__PURE__ */ jsx10("path", { d: "M12 16v-4" }),
4853
+ /* @__PURE__ */ jsx10("path", { d: "M12 8h.01" })
4509
4854
  ] });
4510
4855
  }
4511
4856
  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" })
4857
+ 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: [
4858
+ /* @__PURE__ */ jsx10("path", { d: "M5 12h14" }),
4859
+ /* @__PURE__ */ jsx10("path", { d: "m12 5 7 7-7 7" })
4515
4860
  ] });
4516
4861
  }
4517
4862
  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" })
4863
+ 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: [
4864
+ /* @__PURE__ */ jsx10("rect", { width: "18", height: "7", x: "3", y: "3", rx: "1" }),
4865
+ /* @__PURE__ */ jsx10("rect", { width: "9", height: "7", x: "3", y: "14", rx: "1" }),
4866
+ /* @__PURE__ */ jsx10("rect", { width: "5", height: "7", x: "16", y: "14", rx: "1" })
4522
4867
  ] });
4523
4868
  }
4524
4869
 
4525
4870
  // src/ui/dialog.tsx
4526
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
4871
+ import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
4527
4872
  function Dialog2({ ...props }) {
4528
- return /* @__PURE__ */ jsx6(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
4873
+ return /* @__PURE__ */ jsx11(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
4529
4874
  }
4530
4875
  function DialogPortal({ ...props }) {
4531
- return /* @__PURE__ */ jsx6(DialogPrimitive.Portal, { ...props });
4876
+ return /* @__PURE__ */ jsx11(DialogPrimitive.Portal, { ...props });
4532
4877
  }
4533
4878
  function DialogOverlay({
4534
4879
  className,
4535
4880
  ...props
4536
4881
  }) {
4537
- return /* @__PURE__ */ jsx6(
4882
+ return /* @__PURE__ */ jsx11(
4538
4883
  DialogPrimitive.Overlay,
4539
4884
  {
4540
4885
  "data-slot": "dialog-overlay",
@@ -4544,11 +4889,11 @@ function DialogOverlay({
4544
4889
  }
4545
4890
  );
4546
4891
  }
4547
- var DialogContent = React3.forwardRef(({ className, children, showCloseButton = true, container, ...props }, ref) => {
4892
+ var DialogContent = React5.forwardRef(({ className, children, showCloseButton = true, container, ...props }, ref) => {
4548
4893
  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(
4894
+ return /* @__PURE__ */ jsxs6(DialogPortal, { container: container ?? void 0, children: [
4895
+ /* @__PURE__ */ jsx11(DialogOverlay, { className: cn(positionMode, "inset-0") }),
4896
+ /* @__PURE__ */ jsxs6(
4552
4897
  DialogPrimitive.Content,
4553
4898
  {
4554
4899
  ref,
@@ -4564,13 +4909,13 @@ var DialogContent = React3.forwardRef(({ className, children, showCloseButton =
4564
4909
  ...props,
4565
4910
  children: [
4566
4911
  children,
4567
- showCloseButton ? /* @__PURE__ */ jsx6(
4912
+ showCloseButton ? /* @__PURE__ */ jsx11(
4568
4913
  DialogPrimitive.Close,
4569
4914
  {
4570
4915
  type: "button",
4571
4916
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
4572
4917
  "aria-label": "Close",
4573
- children: /* @__PURE__ */ jsx6(IconX, { "aria-hidden": true })
4918
+ children: /* @__PURE__ */ jsx11(IconX, { "aria-hidden": true })
4574
4919
  }
4575
4920
  ) : null
4576
4921
  ]
@@ -4580,12 +4925,12 @@ var DialogContent = React3.forwardRef(({ className, children, showCloseButton =
4580
4925
  });
4581
4926
  DialogContent.displayName = DialogPrimitive.Content.displayName;
4582
4927
  function DialogHeader({ className, ...props }) {
4583
- return /* @__PURE__ */ jsx6("div", { className: cn("flex flex-col gap-1.5", className), ...props });
4928
+ return /* @__PURE__ */ jsx11("div", { className: cn("flex flex-col gap-1.5", className), ...props });
4584
4929
  }
4585
4930
  function DialogFooter({ className, ...props }) {
4586
- return /* @__PURE__ */ jsx6("div", { className: cn("flex items-center justify-end gap-2", className), ...props });
4931
+ return /* @__PURE__ */ jsx11("div", { className: cn("flex items-center justify-end gap-2", className), ...props });
4587
4932
  }
4588
- var DialogTitle = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx6(
4933
+ var DialogTitle = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx11(
4589
4934
  DialogPrimitive.Title,
4590
4935
  {
4591
4936
  ref,
@@ -4594,7 +4939,7 @@ var DialogTitle = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE
4594
4939
  }
4595
4940
  ));
4596
4941
  DialogTitle.displayName = DialogPrimitive.Title.displayName;
4597
- var DialogDescription = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx6(
4942
+ var DialogDescription = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx11(
4598
4943
  DialogPrimitive.Description,
4599
4944
  {
4600
4945
  ref,
@@ -4606,9 +4951,9 @@ DialogDescription.displayName = DialogPrimitive.Description.displayName;
4606
4951
  var DialogClose = DialogPrimitive.Close;
4607
4952
 
4608
4953
  // src/ui/button.tsx
4609
- import * as React4 from "react";
4954
+ import * as React6 from "react";
4610
4955
  import { Slot } from "radix-ui";
4611
- import { jsx as jsx7 } from "react/jsx-runtime";
4956
+ import { jsx as jsx12 } from "react/jsx-runtime";
4612
4957
  var buttonVariants = cva(
4613
4958
  "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
4959
  {
@@ -4629,10 +4974,10 @@ var buttonVariants = cva(
4629
4974
  }
4630
4975
  }
4631
4976
  );
4632
- var Button = React4.forwardRef(
4977
+ var Button = React6.forwardRef(
4633
4978
  ({ className, variant, size, asChild = false, ...props }, ref) => {
4634
4979
  const Comp = asChild ? Slot.Root : "button";
4635
- return /* @__PURE__ */ jsx7(
4980
+ return /* @__PURE__ */ jsx12(
4636
4981
  Comp,
4637
4982
  {
4638
4983
  ref,
@@ -4646,37 +4991,37 @@ var Button = React4.forwardRef(
4646
4991
  Button.displayName = "Button";
4647
4992
 
4648
4993
  // src/ui/link-modal/DestinationBreadcrumb.tsx
4649
- import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
4994
+ import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
4650
4995
  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 })
4996
+ return /* @__PURE__ */ jsxs7("div", { className: "flex w-full flex-col gap-2", children: [
4997
+ /* @__PURE__ */ jsx13("p", { className: "text-sm font-medium text-foreground", children: "Destination" }),
4998
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-3", children: [
4999
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
5000
+ /* @__PURE__ */ jsx13(IconFile, { className: "shrink-0 text-foreground", "aria-hidden": true }),
5001
+ /* @__PURE__ */ jsx13("span", { className: "text-sm font-medium leading-none text-foreground", children: pageTitle })
4657
5002
  ] }),
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 })
5003
+ /* @__PURE__ */ jsx13(IconArrowRight, { className: "shrink-0 text-muted-foreground", "aria-hidden": true }),
5004
+ /* @__PURE__ */ jsxs7("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
5005
+ /* @__PURE__ */ jsx13(IconSection, { className: "shrink-0 text-foreground", "aria-hidden": true }),
5006
+ /* @__PURE__ */ jsx13("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
4662
5007
  ] })
4663
5008
  ] })
4664
5009
  ] });
4665
5010
  }
4666
5011
 
4667
5012
  // src/ui/link-modal/SectionTreeItem.tsx
4668
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
5013
+ import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
4669
5014
  function SectionTreeItem({ section, onSelect, selected }) {
4670
5015
  const interactive = Boolean(onSelect);
4671
- return /* @__PURE__ */ jsxs6("div", { className: "flex h-9 w-full items-end pl-3", children: [
4672
- /* @__PURE__ */ jsx9(
5016
+ return /* @__PURE__ */ jsxs8("div", { className: "flex h-9 w-full items-end pl-3", children: [
5017
+ /* @__PURE__ */ jsx14(
4673
5018
  "div",
4674
5019
  {
4675
5020
  className: "mr-[-1px] h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
4676
5021
  "aria-hidden": true
4677
5022
  }
4678
5023
  ),
4679
- /* @__PURE__ */ jsxs6(
5024
+ /* @__PURE__ */ jsxs8(
4680
5025
  "div",
4681
5026
  {
4682
5027
  role: interactive ? "button" : void 0,
@@ -4694,8 +5039,8 @@ function SectionTreeItem({ section, onSelect, selected }) {
4694
5039
  interactive && selected && "border-primary"
4695
5040
  ),
4696
5041
  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 })
5042
+ /* @__PURE__ */ jsx14(IconSection, { className: "shrink-0 text-foreground", "aria-hidden": true }),
5043
+ /* @__PURE__ */ jsx14("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
4699
5044
  ]
4700
5045
  }
4701
5046
  )
@@ -4703,11 +5048,11 @@ function SectionTreeItem({ section, onSelect, selected }) {
4703
5048
  }
4704
5049
  function SectionPickerList({ sections, onSelect }) {
4705
5050
  if (sections.length === 0) {
4706
- return /* @__PURE__ */ jsx9("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." });
5051
+ return /* @__PURE__ */ jsx14("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." });
4707
5052
  }
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))
5053
+ return /* @__PURE__ */ jsxs8("div", { className: "flex flex-col gap-1", children: [
5054
+ /* @__PURE__ */ jsx14("p", { className: "text-sm text-muted-foreground", children: "Pick a section this link should scroll to." }),
5055
+ sections.map((section) => /* @__PURE__ */ jsx14(SectionTreeItem, { section, onSelect }, section.id))
4711
5056
  ] });
4712
5057
  }
4713
5058
 
@@ -4715,11 +5060,11 @@ function SectionPickerList({ sections, onSelect }) {
4715
5060
  import { useId as useId2, useRef as useRef2, useState as useState3 } from "react";
4716
5061
 
4717
5062
  // src/ui/input.tsx
4718
- import * as React5 from "react";
4719
- import { jsx as jsx10 } from "react/jsx-runtime";
4720
- var Input = React5.forwardRef(
5063
+ import * as React7 from "react";
5064
+ import { jsx as jsx15 } from "react/jsx-runtime";
5065
+ var Input = React7.forwardRef(
4721
5066
  ({ className, type, ...props }, ref) => {
4722
- return /* @__PURE__ */ jsx10(
5067
+ return /* @__PURE__ */ jsx15(
4723
5068
  "input",
4724
5069
  {
4725
5070
  type,
@@ -4738,9 +5083,9 @@ Input.displayName = "Input";
4738
5083
 
4739
5084
  // src/ui/label.tsx
4740
5085
  import { Label as LabelPrimitive } from "radix-ui";
4741
- import { jsx as jsx11 } from "react/jsx-runtime";
5086
+ import { jsx as jsx16 } from "react/jsx-runtime";
4742
5087
  function Label({ className, ...props }) {
4743
- return /* @__PURE__ */ jsx11(
5088
+ return /* @__PURE__ */ jsx16(
4744
5089
  LabelPrimitive.Root,
4745
5090
  {
4746
5091
  "data-slot": "label",
@@ -4751,9 +5096,9 @@ function Label({ className, ...props }) {
4751
5096
  }
4752
5097
 
4753
5098
  // src/ui/link-modal/UrlOrPageInput.tsx
4754
- import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
5099
+ import { jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
4755
5100
  function FieldChevron({ onClick }) {
4756
- return /* @__PURE__ */ jsx12(
5101
+ return /* @__PURE__ */ jsx17(
4757
5102
  "button",
4758
5103
  {
4759
5104
  type: "button",
@@ -4761,7 +5106,7 @@ function FieldChevron({ onClick }) {
4761
5106
  onClick,
4762
5107
  "aria-label": "Open page list",
4763
5108
  tabIndex: -1,
4764
- children: /* @__PURE__ */ jsx12(IconChevronDown, {})
5109
+ children: /* @__PURE__ */ jsx17(IconChevronDown, {})
4765
5110
  }
4766
5111
  );
4767
5112
  }
@@ -4800,12 +5145,12 @@ function UrlOrPageInput({
4800
5145
  "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
5146
  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
5147
  );
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(
5148
+ return /* @__PURE__ */ jsxs9("div", { className: "flex w-full flex-col gap-2 p-0", children: [
5149
+ /* @__PURE__ */ jsx17(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
5150
+ /* @__PURE__ */ jsxs9("div", { className: "relative w-full", children: [
5151
+ /* @__PURE__ */ jsxs9("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
5152
+ selectedPage ? /* @__PURE__ */ jsx17("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ jsx17(IconFile, { className: "text-foreground", "aria-hidden": true }) }) : null,
5153
+ readOnly ? /* @__PURE__ */ jsx17("span", { className: "min-w-0 flex-1 truncate text-sm leading-5 text-foreground", children: selectedPage?.title ?? value }) : /* @__PURE__ */ jsx17(
4809
5154
  Input,
4810
5155
  {
4811
5156
  ref: inputRef,
@@ -4824,7 +5169,7 @@ function UrlOrPageInput({
4824
5169
  )
4825
5170
  }
4826
5171
  ),
4827
- selectedPage && !readOnly ? /* @__PURE__ */ jsx12(
5172
+ selectedPage && !readOnly ? /* @__PURE__ */ jsx17(
4828
5173
  "button",
4829
5174
  {
4830
5175
  type: "button",
@@ -4832,26 +5177,26 @@ function UrlOrPageInput({
4832
5177
  onMouseDown: clearSelection,
4833
5178
  "aria-label": "Clear selected page",
4834
5179
  tabIndex: -1,
4835
- children: /* @__PURE__ */ jsx12(IconX, { "aria-hidden": true })
5180
+ children: /* @__PURE__ */ jsx17(IconX, { "aria-hidden": true })
4836
5181
  }
4837
5182
  ) : null,
4838
- !readOnly ? /* @__PURE__ */ jsx12(FieldChevron, { onClick: toggleDropdown }) : null
5183
+ !readOnly ? /* @__PURE__ */ jsx17(FieldChevron, { onClick: toggleDropdown }) : null
4839
5184
  ] }),
4840
- dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ jsx12(
5185
+ dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ jsx17(
4841
5186
  "div",
4842
5187
  {
4843
5188
  "data-ohw-link-page-dropdown": "",
4844
5189
  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
5190
  onMouseDown: (e) => e.preventDefault(),
4846
- children: filteredPages.map((page) => /* @__PURE__ */ jsxs7(
5191
+ children: filteredPages.map((page) => /* @__PURE__ */ jsxs9(
4847
5192
  "button",
4848
5193
  {
4849
5194
  type: "button",
4850
5195
  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
5196
  onClick: () => onPageSelect(page),
4852
5197
  children: [
4853
- /* @__PURE__ */ jsx12(IconFile, { className: "shrink-0", "aria-hidden": true }),
4854
- /* @__PURE__ */ jsx12("span", { className: "truncate", children: page.title })
5198
+ /* @__PURE__ */ jsx17(IconFile, { className: "shrink-0", "aria-hidden": true }),
5199
+ /* @__PURE__ */ jsx17("span", { className: "truncate", children: page.title })
4855
5200
  ]
4856
5201
  },
4857
5202
  page.path
@@ -4859,7 +5204,7 @@ function UrlOrPageInput({
4859
5204
  }
4860
5205
  ) : null
4861
5206
  ] }),
4862
- urlError ? /* @__PURE__ */ jsx12("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
5207
+ urlError ? /* @__PURE__ */ jsx17("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
4863
5208
  ] });
4864
5209
  }
4865
5210
 
@@ -5027,7 +5372,7 @@ function useLinkModalState({
5027
5372
  }
5028
5373
 
5029
5374
  // src/ui/link-modal/LinkEditorPanel.tsx
5030
- import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
5375
+ import { Fragment as Fragment2, jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
5031
5376
  function LinkEditorPanel({
5032
5377
  open = true,
5033
5378
  mode = "create",
@@ -5051,25 +5396,25 @@ function LinkEditorPanel({
5051
5396
  onSubmit
5052
5397
  });
5053
5398
  const isCancel = state.secondaryLabel === "Cancel";
5054
- return /* @__PURE__ */ jsxs8(Fragment2, { children: [
5055
- /* @__PURE__ */ jsx13(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx13(
5399
+ return /* @__PURE__ */ jsxs10(Fragment2, { children: [
5400
+ /* @__PURE__ */ jsx18(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx18(
5056
5401
  "button",
5057
5402
  {
5058
5403
  type: "button",
5059
5404
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
5060
5405
  "aria-label": "Close",
5061
- children: /* @__PURE__ */ jsx13(IconX, { "aria-hidden": true })
5406
+ children: /* @__PURE__ */ jsx18(IconX, { "aria-hidden": true })
5062
5407
  }
5063
5408
  ) }),
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(
5409
+ /* @__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 }) }),
5410
+ /* @__PURE__ */ jsxs10("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
5411
+ state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ jsx18(
5067
5412
  DestinationBreadcrumb,
5068
5413
  {
5069
5414
  pageTitle: state.selectedPage.title,
5070
5415
  sectionLabel: state.selectedSection.label
5071
5416
  }
5072
- ) : /* @__PURE__ */ jsx13(
5417
+ ) : /* @__PURE__ */ jsx18(
5073
5418
  UrlOrPageInput,
5074
5419
  {
5075
5420
  value: state.searchValue,
@@ -5082,18 +5427,18 @@ function LinkEditorPanel({
5082
5427
  urlError: state.urlError
5083
5428
  }
5084
5429
  ),
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." })
5430
+ state.showChooseSection ? /* @__PURE__ */ jsxs10("div", { className: "flex flex-col justify-center gap-2", children: [
5431
+ /* @__PURE__ */ jsx18(Button, { type: "button", variant: "outline", className: "w-fit cursor-pointer", size: "sm", onClick: state.handleChooseSection, children: "Choose a section" }),
5432
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
5433
+ /* @__PURE__ */ jsx18(IconInfo, { className: "shrink-0", "aria-hidden": true }),
5434
+ /* @__PURE__ */ jsx18("span", { children: "Pick a section this link should scroll to." })
5090
5435
  ] })
5091
5436
  ] }) : 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
5437
+ state.showSectionPicker ? /* @__PURE__ */ jsx18(SectionPickerList, { sections: state.activeSections, onSelect: state.handleSectionSelect }) : null,
5438
+ state.showSectionRow && state.selectedSection ? /* @__PURE__ */ jsx18(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
5094
5439
  ] }),
5095
- /* @__PURE__ */ jsxs8(DialogFooter, { className: "w-full px-6 pb-6", children: [
5096
- /* @__PURE__ */ jsx13(
5440
+ /* @__PURE__ */ jsxs10(DialogFooter, { className: "w-full px-6 pb-6", children: [
5441
+ /* @__PURE__ */ jsx18(
5097
5442
  Button,
5098
5443
  {
5099
5444
  type: "button",
@@ -5108,7 +5453,7 @@ function LinkEditorPanel({
5108
5453
  children: state.secondaryLabel
5109
5454
  }
5110
5455
  ),
5111
- /* @__PURE__ */ jsx13(
5456
+ /* @__PURE__ */ jsx18(
5112
5457
  Button,
5113
5458
  {
5114
5459
  type: "button",
@@ -5127,7 +5472,7 @@ function LinkEditorPanel({
5127
5472
  }
5128
5473
 
5129
5474
  // src/ui/link-modal/LinkPopover.tsx
5130
- import { jsx as jsx14 } from "react/jsx-runtime";
5475
+ import { jsx as jsx19 } from "react/jsx-runtime";
5131
5476
  function LinkPopover({
5132
5477
  open = true,
5133
5478
  panelRef,
@@ -5135,14 +5480,14 @@ function LinkPopover({
5135
5480
  onClose,
5136
5481
  ...editorProps
5137
5482
  }) {
5138
- return /* @__PURE__ */ jsx14(
5483
+ return /* @__PURE__ */ jsx19(
5139
5484
  Dialog2,
5140
5485
  {
5141
5486
  open,
5142
5487
  onOpenChange: (next) => {
5143
5488
  if (!next) onClose?.();
5144
5489
  },
5145
- children: /* @__PURE__ */ jsx14(
5490
+ children: /* @__PURE__ */ jsx19(
5146
5491
  DialogContent,
5147
5492
  {
5148
5493
  ref: panelRef,
@@ -5152,7 +5497,7 @@ function LinkPopover({
5152
5497
  "data-ohw-bridge": "",
5153
5498
  showCloseButton: false,
5154
5499
  className: "gap-0 p-0 w-full md:w-md pointer-events-auto",
5155
- children: /* @__PURE__ */ jsx14(LinkEditorPanel, { ...editorProps, open, onClose })
5500
+ children: /* @__PURE__ */ jsx19(LinkEditorPanel, { ...editorProps, open, onClose })
5156
5501
  }
5157
5502
  )
5158
5503
  }
@@ -5218,7 +5563,7 @@ function shouldUseDevFixtures() {
5218
5563
  }
5219
5564
 
5220
5565
  // src/ui/badge.tsx
5221
- import { jsx as jsx15 } from "react/jsx-runtime";
5566
+ import { jsx as jsx20 } from "react/jsx-runtime";
5222
5567
  var badgeVariants = cva(
5223
5568
  "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
5569
  {
@@ -5236,12 +5581,13 @@ var badgeVariants = cva(
5236
5581
  }
5237
5582
  );
5238
5583
  function Badge({ className, variant, ...props }) {
5239
- return /* @__PURE__ */ jsx15("div", { className: cn(badgeVariants({ variant }), className), ...props });
5584
+ return /* @__PURE__ */ jsx20("div", { className: cn(badgeVariants({ variant }), className), ...props });
5240
5585
  }
5241
5586
 
5242
5587
  // src/OhhwellsBridge.tsx
5243
- import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs9 } from "react/jsx-runtime";
5244
- var PRIMARY = "#0885FE";
5588
+ import { Link as Link2 } from "lucide-react";
5589
+ import { Fragment as Fragment3, jsx as jsx21, jsxs as jsxs11 } from "react/jsx-runtime";
5590
+ var PRIMARY2 = "#0885FE";
5245
5591
  var IMAGE_FADE_MS = 300;
5246
5592
  function runOpacityFade(el, onDone) {
5247
5593
  const anim = el.animate([{ opacity: 0 }, { opacity: 1 }], {
@@ -5414,7 +5760,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
5414
5760
  const root = createRoot(container);
5415
5761
  flushSync(() => {
5416
5762
  root.render(
5417
- /* @__PURE__ */ jsx16(
5763
+ /* @__PURE__ */ jsx21(
5418
5764
  SchedulingWidget,
5419
5765
  {
5420
5766
  notifyOnConnect,
@@ -5462,6 +5808,20 @@ function applyLinkHref(el, val) {
5462
5808
  const anchor = el instanceof HTMLAnchorElement ? el : el.querySelector("a");
5463
5809
  if (anchor) anchor.setAttribute("href", val);
5464
5810
  }
5811
+ function getEditMeasureEl(editable) {
5812
+ return editable.closest("[data-ohw-href-key]") ?? editable;
5813
+ }
5814
+ function isDragHandleDisabled(el) {
5815
+ const carriers = [
5816
+ el.closest("[data-ohw-href-key]"),
5817
+ el.closest("[data-ohw-editable]")
5818
+ ];
5819
+ return carriers.some((carrier) => {
5820
+ if (!carrier) return false;
5821
+ const raw = carrier.getAttribute("data-ohw-drag-disabled");
5822
+ return raw === "true" || raw === "";
5823
+ });
5824
+ }
5465
5825
  function collectEditableNodes() {
5466
5826
  const nodes = Array.from(document.querySelectorAll("[data-ohw-editable]")).map((el) => {
5467
5827
  if (el.dataset.ohwEditable === "image") {
@@ -5515,12 +5875,49 @@ function getHrefKeyFromElement(el) {
5515
5875
  function isNavbarButton(el) {
5516
5876
  return Boolean(el.closest('[data-ohw-role="navbar-button"]'));
5517
5877
  }
5878
+ function getNavigationItemAnchor(el) {
5879
+ const anchor = el.matches("[data-ohw-href-key]") ? el : el.closest("[data-ohw-href-key]");
5880
+ if (!anchor) return null;
5881
+ if (!anchor.querySelector('[data-ohw-editable="text"]')) return null;
5882
+ return anchor;
5883
+ }
5884
+ function isNavigationItem(el) {
5885
+ return getNavigationItemAnchor(el) !== null;
5886
+ }
5887
+ function getNavigationItemAddHintTarget(anchor) {
5888
+ const items = listNavigationItems();
5889
+ const idx = items.indexOf(anchor);
5890
+ if (idx >= 0 && idx < items.length - 1) return items[idx + 1];
5891
+ return anchor;
5892
+ }
5893
+ function listNavigationItems() {
5894
+ return Array.from(
5895
+ document.querySelectorAll("nav [data-ohw-href-key], footer [data-ohw-href-key]")
5896
+ ).filter((el) => isNavigationItem(el));
5897
+ }
5898
+ function getNavigationItemReorderState(anchor) {
5899
+ if (isNavbarButton(anchor)) return { key: null, disabled: false };
5900
+ return getReorderHandleStateFromAnchor(anchor);
5901
+ }
5902
+ function getReorderHandleState(el) {
5903
+ const linkEl = el.closest("[data-ohw-href-key]");
5904
+ if (!linkEl || getNavigationItemAnchor(linkEl)) return { key: null, disabled: false };
5905
+ return getReorderHandleStateFromAnchor(linkEl);
5906
+ }
5907
+ function getReorderHandleStateFromAnchor(anchor) {
5908
+ const key = anchor.getAttribute("data-ohw-href-key");
5909
+ if (!key) return { key: null, disabled: false };
5910
+ return { key, disabled: isDragHandleDisabled(anchor) };
5911
+ }
5518
5912
  function clearHrefKeyHover(anchor) {
5519
5913
  anchor.removeAttribute("data-ohw-hovered");
5520
5914
  anchor.querySelectorAll("[data-ohw-hovered]").forEach((el) => {
5521
5915
  el.removeAttribute("data-ohw-hovered");
5522
5916
  });
5523
5917
  }
5918
+ function isInsideNavigationItem(el) {
5919
+ return getNavigationItemAnchor(el) !== null;
5920
+ }
5524
5921
  function collectSections() {
5525
5922
  return collectSectionsFromDom();
5526
5923
  }
@@ -5644,6 +6041,8 @@ var ICONS = {
5644
6041
  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
6042
  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
6043
  };
6044
+ var TOOLBAR_PILL_PADDING = 2;
6045
+ var TOOLBAR_TOGGLE_GAP = 4;
5647
6046
  var TOOLBAR_GROUPS = [
5648
6047
  [
5649
6048
  { cmd: "bold", title: "Bold" },
@@ -5661,24 +6060,64 @@ var TOOLBAR_GROUPS = [
5661
6060
  { cmd: "insertOrderedList", title: "Numbered List" }
5662
6061
  ]
5663
6062
  ];
5664
- function GlowFrame({ rect, elRef }) {
6063
+ function EditGlowChrome({
6064
+ rect,
6065
+ elRef,
6066
+ reorderHrefKey,
6067
+ dragDisabled = false
6068
+ }) {
5665
6069
  const GAP = 6;
5666
- return /* @__PURE__ */ jsx16(
6070
+ return /* @__PURE__ */ jsxs11(
5667
6071
  "div",
5668
6072
  {
5669
6073
  ref: elRef,
6074
+ "data-ohw-edit-chrome": "",
5670
6075
  style: {
5671
6076
  position: "fixed",
5672
6077
  top: rect.top - GAP,
5673
6078
  left: rect.left - GAP,
5674
6079
  width: rect.width + GAP * 2,
5675
6080
  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
6081
  pointerEvents: "none",
5680
6082
  zIndex: 2147483646
5681
- }
6083
+ },
6084
+ children: [
6085
+ /* @__PURE__ */ jsx21(
6086
+ "div",
6087
+ {
6088
+ style: {
6089
+ position: "absolute",
6090
+ inset: 0,
6091
+ border: "2px solid var(--ohw-primary, #0885FE)",
6092
+ borderRadius: 8,
6093
+ boxShadow: "0 0 0 4px rgba(8, 133, 254, 0.12)",
6094
+ pointerEvents: "none"
6095
+ }
6096
+ }
6097
+ ),
6098
+ reorderHrefKey && /* @__PURE__ */ jsx21(
6099
+ "div",
6100
+ {
6101
+ "data-ohw-drag-handle-container": "",
6102
+ "data-ohw-drag-disabled": dragDisabled ? "" : void 0,
6103
+ style: {
6104
+ position: "absolute",
6105
+ left: 0,
6106
+ top: "50%",
6107
+ transform: "translate(calc(-100% - 7px), -50%)",
6108
+ pointerEvents: dragDisabled ? "none" : "auto"
6109
+ },
6110
+ children: /* @__PURE__ */ jsx21(
6111
+ DragHandle,
6112
+ {
6113
+ "aria-label": `Reorder ${reorderHrefKey}`,
6114
+ disabled: dragDisabled,
6115
+ "aria-disabled": dragDisabled
6116
+ }
6117
+ )
6118
+ }
6119
+ )
6120
+ ]
5682
6121
  }
5683
6122
  );
5684
6123
  }
@@ -5722,9 +6161,9 @@ function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
5722
6161
  const pinnedTop = Math.min(maxBottom - approxH, Math.max(minTop, clip.top + gap));
5723
6162
  return { top: pinnedTop + approxH, transform: "translateX(-50%) translateY(-100%)" };
5724
6163
  }
5725
- function calcToolbarPos(rect, parentScroll, approxW = 330) {
6164
+ function calcToolbarPos(rect, parentScroll, approxW = 306) {
5726
6165
  const GAP = 8;
5727
- const APPROX_H = 36;
6166
+ const APPROX_H = 32;
5728
6167
  const APPROX_W = approxW;
5729
6168
  const clip = getIframeVisibleClip(parentScroll);
5730
6169
  const clipTop = clip?.top ?? 0;
@@ -5758,119 +6197,24 @@ function calcToolbarPos(rect, parentScroll, approxW = 330) {
5758
6197
  const left = Math.max(GAP + APPROX_W / 2, Math.min(rawLeft, window.innerWidth - GAP - APPROX_W / 2));
5759
6198
  return { top, left, transform };
5760
6199
  }
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
- ] });
6200
+ function resolveItemInteractionState(rect, parentScroll) {
6201
+ const { transform } = calcToolbarPos(rect, parentScroll, 120);
6202
+ return transform.includes("translateY(-100%)") ? "active-top" : "active-bottom";
6203
+ }
5765
6204
  function FloatingToolbar({
5766
6205
  rect,
5767
6206
  parentScroll,
5768
6207
  elRef,
5769
- variant = "rich-text",
5770
6208
  onCommand,
5771
6209
  activeCommands,
5772
6210
  showEditLink,
5773
6211
  onEditLink
5774
6212
  }) {
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(
6213
+ const { top, left, transform } = calcToolbarPos(rect, parentScroll, 330);
6214
+ return /* @__PURE__ */ jsx21(
5870
6215
  "div",
5871
6216
  {
5872
6217
  ref: elRef,
5873
- "data-ohw-toolbar": "",
5874
6218
  style: {
5875
6219
  position: "fixed",
5876
6220
  top,
@@ -5883,57 +6227,39 @@ function FloatingToolbar({
5883
6227
  boxShadow: "0px 2px 4px -2px rgba(0,0,0,.1),0px 4px 6px -1px rgba(0,0,0,.1)",
5884
6228
  display: "flex",
5885
6229
  alignItems: "center",
5886
- padding: 4,
5887
- gap: 6,
6230
+ padding: TOOLBAR_PILL_PADDING,
6231
+ gap: TOOLBAR_TOGGLE_GAP,
5888
6232
  fontFamily: "sans-serif",
5889
- pointerEvents: "auto",
5890
- whiteSpace: "nowrap"
6233
+ pointerEvents: "auto"
5891
6234
  },
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 } }),
6235
+ children: /* @__PURE__ */ jsxs11(CustomToolbar, { children: [
6236
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs11(React8.Fragment, { children: [
6237
+ gi > 0 && /* @__PURE__ */ jsx21(CustomToolbarDivider, {}),
5896
6238
  btns.map((btn) => {
5897
6239
  const isActive = activeCommands.has(btn.cmd);
5898
- return /* @__PURE__ */ jsx16(
5899
- "button",
6240
+ return /* @__PURE__ */ jsx21(
6241
+ CustomToolbarButton,
5900
6242
  {
5901
6243
  title: btn.title,
6244
+ active: isActive,
5902
6245
  onMouseDown: (e) => {
5903
6246
  e.preventDefault();
5904
6247
  onCommand(btn.cmd);
5905
6248
  },
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(
6249
+ children: /* @__PURE__ */ jsx21(
5925
6250
  "svg",
5926
6251
  {
5927
6252
  width: "16",
5928
6253
  height: "16",
5929
6254
  viewBox: "0 0 24 24",
5930
6255
  fill: "none",
5931
- stroke: isActive ? "#FFFFFF" : "#1C1917",
6256
+ stroke: "currentColor",
5932
6257
  strokeWidth: "2.5",
5933
6258
  strokeLinecap: "round",
5934
6259
  strokeLinejoin: "round",
5935
- style: isActive && gi > 0 ? { filter: "drop-shadow(0 0 0.5px #fff)" } : void 0,
5936
- dangerouslySetInnerHTML: { __html: ICONS[btn.cmd] }
6260
+ style: isActive && gi > 0 ? { filter: "drop-shadow(0 0 0.5px currentColor)" } : void 0,
6261
+ dangerouslySetInnerHTML: { __html: ICONS[btn.cmd] },
6262
+ "aria-hidden": true
5937
6263
  }
5938
6264
  )
5939
6265
  },
@@ -5941,8 +6267,8 @@ function FloatingToolbar({
5941
6267
  );
5942
6268
  })
5943
6269
  ] }, gi)),
5944
- showEditLink ? /* @__PURE__ */ jsx16(
5945
- "button",
6270
+ showEditLink ? /* @__PURE__ */ jsx21(
6271
+ CustomToolbarButton,
5946
6272
  {
5947
6273
  type: "button",
5948
6274
  title: "Edit link",
@@ -5955,28 +6281,10 @@ function FloatingToolbar({
5955
6281
  e.preventDefault();
5956
6282
  e.stopPropagation();
5957
6283
  },
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
6284
+ children: /* @__PURE__ */ jsx21(Link2, { className: "size-4 shrink-0", "aria-hidden": true })
5977
6285
  }
5978
6286
  ) : null
5979
- ]
6287
+ ] })
5980
6288
  }
5981
6289
  );
5982
6290
  }
@@ -5990,7 +6298,7 @@ function StateToggle({
5990
6298
  states,
5991
6299
  onStateChange
5992
6300
  }) {
5993
- return /* @__PURE__ */ jsx16(
6301
+ return /* @__PURE__ */ jsx21(
5994
6302
  ToggleGroup,
5995
6303
  {
5996
6304
  "data-ohw-state-toggle": "",
@@ -6004,7 +6312,7 @@ function StateToggle({
6004
6312
  left: rect.right - 8,
6005
6313
  transform: "translateX(-100%)"
6006
6314
  },
6007
- children: states.map((state) => /* @__PURE__ */ jsx16(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
6315
+ children: states.map((state) => /* @__PURE__ */ jsx21(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
6008
6316
  }
6009
6317
  );
6010
6318
  }
@@ -6092,6 +6400,10 @@ function OhhwellsBridge() {
6092
6400
  });
6093
6401
  const deselectRef = useRef3(() => {
6094
6402
  });
6403
+ const reselectNavigationItemRef = useRef3(() => {
6404
+ });
6405
+ const commitNavigationTextEditRef = useRef3(() => {
6406
+ });
6095
6407
  const refreshActiveCommandsRef = useRef3(() => {
6096
6408
  });
6097
6409
  const postToParentRef = useRef3(postToParent);
@@ -6102,11 +6414,18 @@ function OhhwellsBridge() {
6102
6414
  const [toolbarVariant, setToolbarVariant] = useState5("none");
6103
6415
  const toolbarVariantRef = useRef3("none");
6104
6416
  toolbarVariantRef.current = toolbarVariant;
6417
+ const [reorderHrefKey, setReorderHrefKey] = useState5(null);
6418
+ const [reorderDragDisabled, setReorderDragDisabled] = useState5(false);
6105
6419
  const [toggleState, setToggleState] = useState5(null);
6106
6420
  const [maxBadge, setMaxBadge] = useState5(null);
6107
6421
  const [activeCommands, setActiveCommands] = useState5(/* @__PURE__ */ new Set());
6108
6422
  const [sectionGap, setSectionGap] = useState5(null);
6109
6423
  const [toolbarShowEditLink, setToolbarShowEditLink] = useState5(false);
6424
+ const hoveredItemElRef = useRef3(null);
6425
+ const [hoveredItemRect, setHoveredItemRect] = useState5(null);
6426
+ const siblingHintElRef = useRef3(null);
6427
+ const [siblingHintRect, setSiblingHintRect] = useState5(null);
6428
+ const [isItemDragging, setIsItemDragging] = useState5(false);
6110
6429
  const [linkPopover, setLinkPopover] = useState5(null);
6111
6430
  const [sitePages, setSitePages] = useState5([]);
6112
6431
  const [sectionsByPath, setSectionsByPath] = useState5({});
@@ -6208,7 +6527,7 @@ function OhhwellsBridge() {
6208
6527
  useEffect3(() => {
6209
6528
  const update = () => {
6210
6529
  const el = activeElRef.current ?? selectedElRef.current;
6211
- if (el) setToolbarRect(el.getBoundingClientRect());
6530
+ if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
6212
6531
  setToggleState((prev) => {
6213
6532
  if (!prev || !activeStateElRef.current) return prev;
6214
6533
  return { ...prev, rect: activeStateElRef.current.getBoundingClientRect() };
@@ -6275,6 +6594,8 @@ function OhhwellsBridge() {
6275
6594
  }
6276
6595
  el.removeAttribute("contenteditable");
6277
6596
  activeElRef.current = null;
6597
+ setReorderHrefKey(null);
6598
+ setReorderDragDisabled(false);
6278
6599
  if (!selectedElRef.current) {
6279
6600
  setToolbarRect(null);
6280
6601
  setToolbarVariant("none");
@@ -6286,16 +6607,82 @@ function OhhwellsBridge() {
6286
6607
  }, [postToParent]);
6287
6608
  const deselect = useCallback2(() => {
6288
6609
  selectedElRef.current = null;
6610
+ setReorderHrefKey(null);
6611
+ setReorderDragDisabled(false);
6612
+ siblingHintElRef.current = null;
6613
+ setSiblingHintRect(null);
6614
+ setIsItemDragging(false);
6289
6615
  if (!activeElRef.current) {
6290
6616
  setToolbarRect(null);
6291
6617
  setToolbarVariant("none");
6292
6618
  }
6293
6619
  }, []);
6620
+ const reselectNavigationItem = useCallback2((navAnchor) => {
6621
+ selectedElRef.current = navAnchor;
6622
+ const { key, disabled } = getNavigationItemReorderState(navAnchor);
6623
+ setReorderHrefKey(key);
6624
+ setReorderDragDisabled(disabled);
6625
+ setToolbarVariant("link-action");
6626
+ setToolbarRect(navAnchor.getBoundingClientRect());
6627
+ setToolbarShowEditLink(false);
6628
+ setActiveCommands(/* @__PURE__ */ new Set());
6629
+ }, []);
6630
+ const commitNavigationTextEdit = useCallback2((navAnchor) => {
6631
+ const el = activeElRef.current;
6632
+ if (!el) return;
6633
+ const key = el.dataset.ohwKey;
6634
+ if (key) {
6635
+ const timer = autoSaveTimers.current.get(key);
6636
+ if (timer !== void 0) {
6637
+ clearTimeout(timer);
6638
+ autoSaveTimers.current.delete(key);
6639
+ }
6640
+ const html = sanitizeHtml(el.innerHTML);
6641
+ const original = originalContentRef.current ?? "";
6642
+ if (html !== sanitizeHtml(original)) {
6643
+ postToParent({ type: "ow:change", nodes: [{ key, text: html }] });
6644
+ const h = document.documentElement.scrollHeight;
6645
+ if (h > 50) postToParent({ type: "ow:height", height: h });
6646
+ }
6647
+ }
6648
+ el.removeAttribute("contenteditable");
6649
+ activeElRef.current = null;
6650
+ setMaxBadge(null);
6651
+ setActiveCommands(/* @__PURE__ */ new Set());
6652
+ setToolbarShowEditLink(false);
6653
+ postToParent({ type: "ow:exit-edit" });
6654
+ reselectNavigationItem(navAnchor);
6655
+ }, [postToParent, reselectNavigationItem]);
6656
+ const handleAddNavigationItem = useCallback2(() => {
6657
+ const selected = selectedElRef.current;
6658
+ if (!selected) return;
6659
+ const target = getNavigationItemAddHintTarget(selected);
6660
+ siblingHintElRef.current = target;
6661
+ setSiblingHintRect(target.getBoundingClientRect());
6662
+ }, []);
6663
+ const handleItemDragStart = useCallback2(() => {
6664
+ siblingHintElRef.current = null;
6665
+ setSiblingHintRect(null);
6666
+ setIsItemDragging(true);
6667
+ }, []);
6668
+ const handleItemDragEnd = useCallback2(() => {
6669
+ setIsItemDragging(false);
6670
+ }, []);
6671
+ reselectNavigationItemRef.current = reselectNavigationItem;
6672
+ commitNavigationTextEditRef.current = commitNavigationTextEdit;
6294
6673
  const select = useCallback2((anchor) => {
6295
- if (!isNavbarButton(anchor)) return;
6674
+ if (!isNavigationItem(anchor)) return;
6296
6675
  if (activeElRef.current) deactivate();
6297
6676
  selectedElRef.current = anchor;
6298
6677
  clearHrefKeyHover(anchor);
6678
+ setHoveredItemRect(null);
6679
+ hoveredItemElRef.current = null;
6680
+ siblingHintElRef.current = null;
6681
+ setSiblingHintRect(null);
6682
+ setIsItemDragging(false);
6683
+ const { key, disabled } = getNavigationItemReorderState(anchor);
6684
+ setReorderHrefKey(key);
6685
+ setReorderDragDisabled(disabled);
6299
6686
  setToolbarVariant("link-action");
6300
6687
  setToolbarRect(anchor.getBoundingClientRect());
6301
6688
  setToolbarShowEditLink(false);
@@ -6310,13 +6697,26 @@ function OhhwellsBridge() {
6310
6697
  postToParentRef.current({ type: "ow:image-unhover" });
6311
6698
  }
6312
6699
  setToolbarVariant("rich-text");
6700
+ siblingHintElRef.current = null;
6701
+ setSiblingHintRect(null);
6702
+ setIsItemDragging(false);
6313
6703
  el.setAttribute("contenteditable", "true");
6314
6704
  el.removeAttribute("data-ohw-hovered");
6705
+ el.closest("[data-ohw-href-key]")?.removeAttribute("data-ohw-hovered");
6315
6706
  activeElRef.current = el;
6316
6707
  originalContentRef.current = el.innerHTML;
6317
6708
  el.focus();
6318
- setToolbarRect(el.getBoundingClientRect());
6319
6709
  setToolbarShowEditLink(Boolean(getHrefKeyFromElement(el)));
6710
+ const navAnchor = getNavigationItemAnchor(el);
6711
+ if (navAnchor) {
6712
+ setReorderHrefKey(null);
6713
+ setReorderDragDisabled(false);
6714
+ } else {
6715
+ const { key: reorderKey, disabled: reorderDisabled } = getReorderHandleState(el);
6716
+ setReorderHrefKey(reorderKey);
6717
+ setReorderDragDisabled(reorderDisabled);
6718
+ }
6719
+ setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
6320
6720
  postToParent({ type: "ow:enter-edit", key: el.dataset.ohwKey });
6321
6721
  requestAnimationFrame(() => refreshActiveCommandsRef.current());
6322
6722
  }, [deactivate, postToParent]);
@@ -6381,7 +6781,7 @@ function OhhwellsBridge() {
6381
6781
  return () => {
6382
6782
  cancelled = true;
6383
6783
  };
6384
- }, [subdomain, isEditMode, pathname]);
6784
+ }, [subdomain, isEditMode]);
6385
6785
  useEffect3(() => {
6386
6786
  if (!subdomain || isEditMode) return;
6387
6787
  let debounceTimer = null;
@@ -6418,7 +6818,7 @@ function OhhwellsBridge() {
6418
6818
  if (debounceTimer) clearTimeout(debounceTimer);
6419
6819
  debounceTimer = setTimeout(applyFromCache, 150);
6420
6820
  };
6421
- scheduleApply();
6821
+ applyFromCache();
6422
6822
  observer = new MutationObserver(scheduleApply);
6423
6823
  observer.observe(document.body, { childList: true, subtree: true });
6424
6824
  return () => {
@@ -6508,18 +6908,25 @@ function OhhwellsBridge() {
6508
6908
  [data-ohw-editable="image"], [data-ohw-editable="image"] *,
6509
6909
  [data-ohw-editable="bg-image"], [data-ohw-editable="bg-image"] * { cursor: pointer !important; }
6510
6910
  [data-ohw-editable="link"], [data-ohw-editable="link"] * { cursor: pointer !important; }
6511
- [data-ohw-hovered]:not([contenteditable]) {
6512
- outline: 2px dashed ${PRIMARY} !important;
6911
+ [data-ohw-hovered]:not([contenteditable]):not([data-ohw-href-key]) {
6912
+ outline: 2px dashed ${PRIMARY2} !important;
6513
6913
  outline-offset: 4px;
6514
6914
  border-radius: 2px;
6515
6915
  }
6916
+ [data-ohw-href-key] [data-ohw-hovered],
6917
+ [data-ohw-href-key][data-ohw-hovered],
6918
+ nav [data-ohw-href-key] [data-ohw-hovered],
6919
+ footer [data-ohw-href-key] [data-ohw-hovered] {
6920
+ outline: none !important;
6921
+ outline-offset: 0 !important;
6922
+ }
6516
6923
  [data-ohw-editable][contenteditable] {
6517
6924
  outline: none !important;
6518
- caret-color: ${PRIMARY};
6925
+ caret-color: ${PRIMARY2};
6519
6926
  cursor: text !important;
6520
6927
  }
6521
6928
  [data-ohw-editable][contenteditable]::selection,
6522
- [data-ohw-editable][contenteditable] *::selection { background: ${PRIMARY}59 !important; }
6929
+ [data-ohw-editable][contenteditable] *::selection { background: ${PRIMARY2}59 !important; }
6523
6930
  [data-ohw-editable-state], [data-ohw-editable-state] * { pointer-events: none !important; }
6524
6931
  [data-ohw-editable-state][data-ohw-active-state] [data-ohw-editable] { pointer-events: auto !important; }
6525
6932
  [data-ohw-editable-state][data-ohw-active-state][data-ohw-editable] { pointer-events: auto !important; }
@@ -6531,7 +6938,7 @@ function OhhwellsBridge() {
6531
6938
  stateViews.textContent = `
6532
6939
  [data-ohw-state-view]:not([data-ohw-state-view="default"]) { display: none; }
6533
6940
  [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; }
6941
+ [data-ohw-state-hovered] { outline: 2px dashed ${PRIMARY2} !important; outline-offset: 4px; border-radius: 2px; }
6535
6942
  [data-ohw-state-hovered]:has([data-ohw-hovered]) { outline: none !important; }
6536
6943
  `;
6537
6944
  document.head.appendChild(base);
@@ -6546,6 +6953,11 @@ function OhhwellsBridge() {
6546
6953
  if (target.closest("[data-ohw-state-toggle]")) return;
6547
6954
  if (target.closest("[data-ohw-max-badge]")) return;
6548
6955
  if (isInsideLinkEditor(target)) return;
6956
+ if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
6957
+ e.preventDefault();
6958
+ e.stopPropagation();
6959
+ return;
6960
+ }
6549
6961
  const editable = target.closest("[data-ohw-editable]");
6550
6962
  if (editable) {
6551
6963
  if (editable.dataset.ohwEditable === "link") {
@@ -6567,15 +6979,15 @@ function OhhwellsBridge() {
6567
6979
  return;
6568
6980
  }
6569
6981
  const hrefCtx = getHrefKeyFromElement(editable);
6570
- if (hrefCtx && isNavbarButton(hrefCtx.anchor)) {
6982
+ const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
6983
+ if (navAnchor) {
6571
6984
  e.preventDefault();
6572
6985
  e.stopPropagation();
6573
- const { anchor: anchor2 } = hrefCtx;
6574
- if (selectedElRef.current === anchor2) {
6986
+ if (selectedElRef.current === navAnchor) {
6575
6987
  activateRef.current(editable);
6576
6988
  return;
6577
6989
  }
6578
- selectRef.current(anchor2);
6990
+ selectRef.current(navAnchor);
6579
6991
  return;
6580
6992
  }
6581
6993
  e.preventDefault();
@@ -6583,8 +6995,8 @@ function OhhwellsBridge() {
6583
6995
  activateRef.current(editable);
6584
6996
  return;
6585
6997
  }
6586
- const hrefAnchor = target.closest("[data-ohw-href-key]");
6587
- if (hrefAnchor && isNavbarButton(hrefAnchor)) {
6998
+ const hrefAnchor = getNavigationItemAnchor(target);
6999
+ if (hrefAnchor) {
6588
7000
  e.preventDefault();
6589
7001
  e.stopPropagation();
6590
7002
  if (selectedElRef.current === hrefAnchor) return;
@@ -6617,19 +7029,58 @@ function OhhwellsBridge() {
6617
7029
  deactivateRef.current();
6618
7030
  };
6619
7031
  const handleMouseOver = (e) => {
6620
- const editable = e.target.closest("[data-ohw-editable]");
7032
+ const target = e.target;
7033
+ const navAnchor = getNavigationItemAnchor(target);
7034
+ if (navAnchor) {
7035
+ const selected2 = selectedElRef.current;
7036
+ if (selected2 === navAnchor || selected2?.contains(navAnchor)) return;
7037
+ clearHrefKeyHover(navAnchor);
7038
+ hoveredItemElRef.current = navAnchor;
7039
+ setHoveredItemRect(navAnchor.getBoundingClientRect());
7040
+ return;
7041
+ }
7042
+ const editable = target.closest("[data-ohw-editable]");
6621
7043
  if (!editable) return;
6622
7044
  const selected = selectedElRef.current;
6623
7045
  if (selected && (selected === editable || selected.contains(editable))) return;
6624
7046
  if (editable.dataset.ohwEditable !== "image" && editable.dataset.ohwEditable !== "bg-image" && !editable.hasAttribute("contenteditable")) {
6625
- editable.setAttribute("data-ohw-hovered", "");
7047
+ const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
7048
+ if (hoverTarget.hasAttribute("data-ohw-href-key")) {
7049
+ clearHrefKeyHover(hoverTarget);
7050
+ hoveredItemElRef.current = hoverTarget;
7051
+ setHoveredItemRect(hoverTarget.getBoundingClientRect());
7052
+ } else if (!isInsideNavigationItem(editable)) {
7053
+ hoverTarget.setAttribute("data-ohw-hovered", "");
7054
+ }
6626
7055
  }
6627
7056
  };
6628
7057
  const handleMouseOut = (e) => {
6629
- const editable = e.target.closest("[data-ohw-editable]");
7058
+ const target = e.target;
7059
+ const navAnchor = getNavigationItemAnchor(target);
7060
+ if (navAnchor) {
7061
+ const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
7062
+ if (related2?.closest("[data-ohw-drag-handle-container], [data-ohw-item-interaction]")) return;
7063
+ if (related2 && navAnchor.contains(related2)) return;
7064
+ if (hoveredItemElRef.current === navAnchor) {
7065
+ hoveredItemElRef.current = null;
7066
+ setHoveredItemRect(null);
7067
+ }
7068
+ return;
7069
+ }
7070
+ const editable = target.closest("[data-ohw-editable]");
6630
7071
  if (!editable) return;
7072
+ const related = e.relatedTarget instanceof Element ? e.relatedTarget : null;
7073
+ if (related?.closest("[data-ohw-drag-handle-container], [data-ohw-item-interaction]")) return;
6631
7074
  if (editable.dataset.ohwEditable !== "image" && editable.dataset.ohwEditable !== "bg-image") {
6632
- editable.removeAttribute("data-ohw-hovered");
7075
+ const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
7076
+ if (hoverTarget.hasAttribute("data-ohw-href-key")) {
7077
+ if (!related?.closest("[data-ohw-href-key]")) {
7078
+ hoveredItemElRef.current = null;
7079
+ setHoveredItemRect(null);
7080
+ }
7081
+ } else {
7082
+ hoverTarget.removeAttribute("data-ohw-hovered");
7083
+ }
6633
7084
  }
6634
7085
  };
6635
7086
  const toProbeCoords = (clientX, clientY, fromParentViewport) => {
@@ -6744,11 +7195,20 @@ function OhhwellsBridge() {
6744
7195
  return;
6745
7196
  }
6746
7197
  }
7198
+ if (activeElRef.current) {
7199
+ if (hoveredImageRef.current) {
7200
+ hoveredImageRef.current = null;
7201
+ hoveredImageHasTextOverlapRef.current = false;
7202
+ resumeAnimTracks();
7203
+ postToParentRef.current({ type: "ow:image-unhover" });
7204
+ }
7205
+ return;
7206
+ }
6747
7207
  const imgEl = findImageAtPoint(clientX, clientY, fromParentViewport);
6748
7208
  if (imgEl) {
6749
7209
  const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
6750
7210
  const topEl = document.elementFromPoint(x, y);
6751
- if (topEl?.closest("[data-ohw-toolbar]")) {
7211
+ if (topEl?.closest('[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
6752
7212
  if (hoveredImageRef.current) {
6753
7213
  hoveredImageRef.current = null;
6754
7214
  resumeAnimTracks();
@@ -6796,7 +7256,9 @@ function OhhwellsBridge() {
6796
7256
  postImageHover(imgEl, isDragOver, true);
6797
7257
  }
6798
7258
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
6799
- textEditable.setAttribute("data-ohw-hovered", "");
7259
+ if (textEditable && !isInsideNavigationItem(textEditable)) {
7260
+ textEditable.setAttribute("data-ohw-hovered", "");
7261
+ }
6800
7262
  return;
6801
7263
  }
6802
7264
  if (hoveredImageRef.current) {
@@ -6806,7 +7268,9 @@ function OhhwellsBridge() {
6806
7268
  postToParentRef.current({ type: "ow:image-unhover" });
6807
7269
  }
6808
7270
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
6809
- textEditable.setAttribute("data-ohw-hovered", "");
7271
+ if (textEditable && !isInsideNavigationItem(textEditable)) {
7272
+ textEditable.setAttribute("data-ohw-hovered", "");
7273
+ }
6810
7274
  return;
6811
7275
  }
6812
7276
  if (hoveredGapRef.current) {
@@ -6850,7 +7314,24 @@ function OhhwellsBridge() {
6850
7314
  return x >= er.left && x <= er.right && y >= er.top && y <= er.bottom;
6851
7315
  });
6852
7316
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
6853
- if (textEl && !textEl.hasAttribute("contenteditable")) textEl.setAttribute("data-ohw-hovered", "");
7317
+ if (textEl && !textEl.hasAttribute("contenteditable")) {
7318
+ const navAnchor = getNavigationItemAnchor(textEl);
7319
+ if (navAnchor) {
7320
+ const selected = selectedElRef.current;
7321
+ if (selected !== navAnchor && !selected?.contains(navAnchor)) {
7322
+ clearHrefKeyHover(navAnchor);
7323
+ hoveredItemElRef.current = navAnchor;
7324
+ setHoveredItemRect(navAnchor.getBoundingClientRect());
7325
+ }
7326
+ } else {
7327
+ hoveredItemElRef.current = null;
7328
+ setHoveredItemRect(null);
7329
+ textEl.setAttribute("data-ohw-hovered", "");
7330
+ }
7331
+ } else {
7332
+ hoveredItemElRef.current = null;
7333
+ setHoveredItemRect(null);
7334
+ }
6854
7335
  }
6855
7336
  };
6856
7337
  const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
@@ -7041,7 +7522,7 @@ function OhhwellsBridge() {
7041
7522
  const el = e.target;
7042
7523
  const key = el.dataset.ohwKey;
7043
7524
  if (!key) return;
7044
- if (el === activeElRef.current) setToolbarRect(el.getBoundingClientRect());
7525
+ if (el === activeElRef.current) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
7045
7526
  const maxLen = el.dataset.ohwMaxLength ? parseInt(el.dataset.ohwMaxLength, 10) : null;
7046
7527
  if (maxLen) {
7047
7528
  const current = el.innerText.replace(/\n$/, "").length;
@@ -7128,6 +7609,33 @@ function OhhwellsBridge() {
7128
7609
  deselectRef.current();
7129
7610
  return;
7130
7611
  }
7612
+ if (e.key === "Escape" && activeElRef.current) {
7613
+ const hrefCtx = getHrefKeyFromElement(activeElRef.current);
7614
+ const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
7615
+ if (navAnchor) {
7616
+ e.preventDefault();
7617
+ const el2 = activeElRef.current;
7618
+ if (originalContentRef.current !== null) {
7619
+ el2.innerHTML = originalContentRef.current;
7620
+ }
7621
+ el2.removeAttribute("contenteditable");
7622
+ activeElRef.current = null;
7623
+ setMaxBadge(null);
7624
+ setActiveCommands(/* @__PURE__ */ new Set());
7625
+ setToolbarShowEditLink(false);
7626
+ postToParentRef.current({ type: "ow:exit-edit" });
7627
+ reselectNavigationItemRef.current(navAnchor);
7628
+ return;
7629
+ }
7630
+ }
7631
+ if (e.key === "Enter" && !e.shiftKey && activeElRef.current) {
7632
+ const navAnchor = getNavigationItemAnchor(activeElRef.current);
7633
+ if (navAnchor) {
7634
+ e.preventDefault();
7635
+ commitNavigationTextEditRef.current(navAnchor);
7636
+ return;
7637
+ }
7638
+ }
7131
7639
  if (e.key !== "Escape") return;
7132
7640
  const el = activeElRef.current;
7133
7641
  if (el && originalContentRef.current !== null) {
@@ -7143,7 +7651,8 @@ function OhhwellsBridge() {
7143
7651
  const handleScroll = () => {
7144
7652
  const focusEl = activeElRef.current ?? selectedElRef.current;
7145
7653
  if (focusEl) {
7146
- const r2 = focusEl.getBoundingClientRect();
7654
+ const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : focusEl;
7655
+ const r2 = measureEl.getBoundingClientRect();
7147
7656
  applyToolbarPos(r2);
7148
7657
  setToolbarRect(r2);
7149
7658
  setMaxBadge((prev) => prev && activeElRef.current ? { ...prev, rect: r2 } : prev);
@@ -7152,6 +7661,12 @@ function OhhwellsBridge() {
7152
7661
  const rect = activeStateElRef.current.getBoundingClientRect();
7153
7662
  setToggleState((prev) => prev ? { ...prev, rect } : null);
7154
7663
  }
7664
+ if (hoveredItemElRef.current) {
7665
+ setHoveredItemRect(hoveredItemElRef.current.getBoundingClientRect());
7666
+ }
7667
+ if (siblingHintElRef.current) {
7668
+ setSiblingHintRect(siblingHintElRef.current.getBoundingClientRect());
7669
+ }
7155
7670
  if (hoveredImageRef.current) {
7156
7671
  const el = hoveredImageRef.current;
7157
7672
  const r2 = el.getBoundingClientRect();
@@ -7271,7 +7786,7 @@ function OhhwellsBridge() {
7271
7786
  };
7272
7787
  const applyToolbarPos = (rect) => {
7273
7788
  const ps = parentScrollRef.current;
7274
- const approxW = toolbarVariantRef.current === "link-action" ? 120 : 330;
7789
+ const approxW = 330;
7275
7790
  if (toolbarElRef.current) {
7276
7791
  const { top, left, transform } = calcToolbarPos(rect, ps, approxW);
7277
7792
  toolbarElRef.current.style.top = `${top}px`;
@@ -7282,6 +7797,8 @@ function OhhwellsBridge() {
7282
7797
  const GAP = 6;
7283
7798
  glowElRef.current.style.top = `${rect.top - GAP}px`;
7284
7799
  glowElRef.current.style.left = `${rect.left - GAP}px`;
7800
+ glowElRef.current.style.width = `${rect.width + GAP * 2}px`;
7801
+ glowElRef.current.style.height = `${rect.height + GAP * 2}px`;
7285
7802
  }
7286
7803
  };
7287
7804
  const handleParentScroll = (e) => {
@@ -7292,7 +7809,10 @@ function OhhwellsBridge() {
7292
7809
  applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
7293
7810
  }
7294
7811
  const focusEl = activeElRef.current ?? selectedElRef.current;
7295
- if (focusEl) applyToolbarPos(focusEl.getBoundingClientRect());
7812
+ if (focusEl) {
7813
+ const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : focusEl;
7814
+ applyToolbarPos(measureEl.getBoundingClientRect());
7815
+ }
7296
7816
  };
7297
7817
  const handleClickAt = (e) => {
7298
7818
  if (e.data?.type !== "ow:click-at") return;
@@ -7450,7 +7970,7 @@ function OhhwellsBridge() {
7450
7970
  const handleCommand = useCallback2((cmd) => {
7451
7971
  document.execCommand(cmd, false);
7452
7972
  activeElRef.current?.focus();
7453
- if (activeElRef.current) setToolbarRect(activeElRef.current.getBoundingClientRect());
7973
+ if (activeElRef.current) setToolbarRect(getEditMeasureEl(activeElRef.current).getBoundingClientRect());
7454
7974
  refreshActiveCommandsRef.current();
7455
7975
  }, []);
7456
7976
  const handleStateChange = useCallback2((state) => {
@@ -7503,37 +8023,55 @@ function OhhwellsBridge() {
7503
8023
  const currentSections = sectionsByPath[pathname] ?? [];
7504
8024
  linkPopoverOpenRef.current = linkPopover !== null;
7505
8025
  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,
8026
+ /* @__PURE__ */ jsxs11(Fragment3, { children: [
8027
+ /* @__PURE__ */ jsx21("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
8028
+ siblingHintRect && !isItemDragging && /* @__PURE__ */ jsx21(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
8029
+ hoveredItemRect && !siblingHintRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx21(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
8030
+ toolbarRect && toolbarVariant === "link-action" && /* @__PURE__ */ jsx21(
8031
+ ItemInteractionLayer,
8032
+ {
8033
+ rect: toolbarRect,
8034
+ elRef: glowElRef,
8035
+ state: isItemDragging ? "dragging" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
8036
+ showHandle: Boolean(reorderHrefKey),
8037
+ dragDisabled: reorderDragDisabled,
8038
+ dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
8039
+ onDragHandleDragStart: handleItemDragStart,
8040
+ onDragHandleDragEnd: handleItemDragEnd,
8041
+ toolbar: isItemDragging ? void 0 : /* @__PURE__ */ jsx21(
8042
+ ItemActionToolbar,
8043
+ {
8044
+ onEditLink: openLinkPopoverForSelected,
8045
+ onAddItem: handleAddNavigationItem,
8046
+ addItemDisabled: false
8047
+ }
8048
+ )
8049
+ }
8050
+ ),
8051
+ toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ jsxs11(Fragment3, { children: [
8052
+ /* @__PURE__ */ jsx21(
8053
+ EditGlowChrome,
7512
8054
  {
7513
- variant: "rich-text",
7514
8055
  rect: toolbarRect,
7515
- parentScroll: parentScrollRef.current,
7516
- elRef: toolbarElRef,
7517
- onCommand: handleCommand,
7518
- activeCommands,
7519
- showEditLink,
7520
- onEditLink: openLinkPopoverForActive
8056
+ elRef: glowElRef,
8057
+ reorderHrefKey,
8058
+ dragDisabled: reorderDragDisabled
7521
8059
  }
7522
8060
  ),
7523
- toolbarVariant === "link-action" && /* @__PURE__ */ jsx16(
8061
+ /* @__PURE__ */ jsx21(
7524
8062
  FloatingToolbar,
7525
8063
  {
7526
- variant: "link-action",
7527
8064
  rect: toolbarRect,
7528
8065
  parentScroll: parentScrollRef.current,
7529
8066
  elRef: toolbarElRef,
7530
8067
  onCommand: handleCommand,
7531
8068
  activeCommands,
7532
- onEditLink: openLinkPopoverForSelected
8069
+ showEditLink,
8070
+ onEditLink: openLinkPopoverForActive
7533
8071
  }
7534
8072
  )
7535
8073
  ] }),
7536
- maxBadge && /* @__PURE__ */ jsxs9(
8074
+ maxBadge && /* @__PURE__ */ jsxs11(
7537
8075
  "div",
7538
8076
  {
7539
8077
  "data-ohw-max-badge": "",
@@ -7559,7 +8097,7 @@ function OhhwellsBridge() {
7559
8097
  ]
7560
8098
  }
7561
8099
  ),
7562
- toggleState && /* @__PURE__ */ jsx16(
8100
+ toggleState && /* @__PURE__ */ jsx21(
7563
8101
  StateToggle,
7564
8102
  {
7565
8103
  rect: toggleState.rect,
@@ -7568,15 +8106,15 @@ function OhhwellsBridge() {
7568
8106
  onStateChange: handleStateChange
7569
8107
  }
7570
8108
  ),
7571
- sectionGap && /* @__PURE__ */ jsxs9(
8109
+ sectionGap && /* @__PURE__ */ jsxs11(
7572
8110
  "div",
7573
8111
  {
7574
8112
  "data-ohw-section-insert-line": "",
7575
8113
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
7576
8114
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
7577
8115
  children: [
7578
- /* @__PURE__ */ jsx16("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
7579
- /* @__PURE__ */ jsx16(
8116
+ /* @__PURE__ */ jsx21("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
8117
+ /* @__PURE__ */ jsx21(
7580
8118
  Badge,
7581
8119
  {
7582
8120
  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 +8127,11 @@ function OhhwellsBridge() {
7589
8127
  children: "Add Section"
7590
8128
  }
7591
8129
  ),
7592
- /* @__PURE__ */ jsx16("div", { className: "flex-1 bg-primary", style: { height: 3 } })
8130
+ /* @__PURE__ */ jsx21("div", { className: "flex-1 bg-primary", style: { height: 3 } })
7593
8131
  ]
7594
8132
  }
7595
8133
  ),
7596
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx16(
8134
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx21(
7597
8135
  LinkPopover,
7598
8136
  {
7599
8137
  panelRef: linkPopoverPanelRef,
@@ -7608,12 +8146,43 @@ function OhhwellsBridge() {
7608
8146
  onSubmit: handleLinkPopoverSubmit
7609
8147
  },
7610
8148
  `${linkPopover.key}-${pathname}`
7611
- ) : null
8149
+ ) : null,
8150
+ sectionGap && /* @__PURE__ */ jsxs11(
8151
+ "div",
8152
+ {
8153
+ "data-ohw-section-insert-line": "",
8154
+ className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
8155
+ style: { top: sectionGap.y, transform: "translateY(-50%)" },
8156
+ children: [
8157
+ /* @__PURE__ */ jsx21("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
8158
+ /* @__PURE__ */ jsx21(
8159
+ Badge,
8160
+ {
8161
+ 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",
8162
+ onClick: () => {
8163
+ window.parent.postMessage(
8164
+ { type: "ow:add-section", insertAfter: sectionGap.insertAfter, insertBefore: sectionGap.insertBefore },
8165
+ "*"
8166
+ );
8167
+ },
8168
+ children: "Add Section"
8169
+ }
8170
+ ),
8171
+ /* @__PURE__ */ jsx21("div", { className: "flex-1 bg-primary", style: { height: 3 } })
8172
+ ]
8173
+ }
8174
+ )
7612
8175
  ] }),
7613
8176
  bridgeRoot
7614
8177
  ) : null;
7615
8178
  }
7616
8179
  export {
8180
+ CustomToolbar,
8181
+ CustomToolbarButton,
8182
+ CustomToolbarDivider,
8183
+ DragHandle,
8184
+ ItemActionToolbar,
8185
+ ItemInteractionLayer,
7617
8186
  LinkEditorPanel,
7618
8187
  LinkPopover,
7619
8188
  OhhwellsBridge,
@@ -7621,9 +8190,14 @@ export {
7621
8190
  Toggle,
7622
8191
  ToggleGroup,
7623
8192
  ToggleGroupItem,
8193
+ Tooltip,
8194
+ TooltipContent,
8195
+ TooltipProvider,
8196
+ TooltipTrigger,
7624
8197
  buildTarget,
7625
8198
  filterAvailablePages,
7626
8199
  getEditModeInitialState,
8200
+ isEditSessionActive,
7627
8201
  isValidUrl,
7628
8202
  parseTarget,
7629
8203
  toggleVariants,