@ohhwells/bridge 0.1.34 → 0.1.36

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
 
@@ -4202,6 +4202,336 @@ function ToggleGroupItem({
4202
4202
  );
4203
4203
  }
4204
4204
 
4205
+ // src/ui/drag-handle.tsx
4206
+ import * as React3 from "react";
4207
+ import { GripVertical } from "lucide-react";
4208
+ import { jsx as jsx5 } from "react/jsx-runtime";
4209
+ var DragHandle = React3.forwardRef(
4210
+ ({ className, type = "button", ...props }, ref) => {
4211
+ return /* @__PURE__ */ jsx5(
4212
+ "button",
4213
+ {
4214
+ ref,
4215
+ type,
4216
+ "data-slot": "drag-handle",
4217
+ className: cn(
4218
+ "inline-flex h-7 w-4 shrink-0 items-center justify-center rounded-md transition-all duration-200 max-h-[30px]",
4219
+ "bg-white border border-transparent text-stone-500 shadow-md cursor-grab",
4220
+ "enabled:hover:border enabled:hover:border-stone-200 enabled:hover:text-stone-950",
4221
+ "enabled:active:border enabled:active:border-primary enabled:active:bg-primary-50 enabled:active:text-stone-950 enabled:active:shadow enabled:active:cursor-grabbing",
4222
+ "disabled:cursor-not-allowed disabled:opacity-40 disabled:text-stone-950 disabled:pointer-events-none",
4223
+ className
4224
+ ),
4225
+ ...props,
4226
+ children: /* @__PURE__ */ jsx5(GripVertical, { className: "size-4 shrink-0", "aria-hidden": "true" })
4227
+ }
4228
+ );
4229
+ }
4230
+ );
4231
+ DragHandle.displayName = "DragHandle";
4232
+
4233
+ // src/ui/custom-toolbar.tsx
4234
+ import * as React4 from "react";
4235
+ import { jsx as jsx6 } from "react/jsx-runtime";
4236
+ var CustomToolbar = React4.forwardRef(({ className, onMouseDown, ...props }, ref) => /* @__PURE__ */ jsx6(
4237
+ "div",
4238
+ {
4239
+ ref,
4240
+ "data-ohw-toolbar": "",
4241
+ className: cn(
4242
+ "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)]",
4243
+ className
4244
+ ),
4245
+ onMouseDown: (e) => {
4246
+ e.stopPropagation();
4247
+ onMouseDown?.(e);
4248
+ },
4249
+ ...props
4250
+ }
4251
+ ));
4252
+ CustomToolbar.displayName = "CustomToolbar";
4253
+ function CustomToolbarDivider({ className, ...props }) {
4254
+ return /* @__PURE__ */ jsx6(
4255
+ "span",
4256
+ {
4257
+ "aria-hidden": true,
4258
+ className: cn("block h-6 w-px shrink-0 bg-border", className),
4259
+ ...props
4260
+ }
4261
+ );
4262
+ }
4263
+ var CustomToolbarButton = React4.forwardRef(
4264
+ ({ className, active = false, type = "button", ...props }, ref) => /* @__PURE__ */ jsx6(
4265
+ "button",
4266
+ {
4267
+ ref,
4268
+ type,
4269
+ className: cn(
4270
+ "inline-flex shrink-0 items-center justify-center rounded p-1.5 transition-colors",
4271
+ active ? "bg-primary text-primary-foreground" : "bg-transparent text-foreground hover:bg-muted disabled:cursor-not-allowed disabled:text-muted-foreground disabled:opacity-60",
4272
+ className
4273
+ ),
4274
+ ...props
4275
+ }
4276
+ )
4277
+ );
4278
+ CustomToolbarButton.displayName = "CustomToolbarButton";
4279
+
4280
+ // src/ui/item-action-toolbar.tsx
4281
+ import { Link, MoreHorizontal, Plus } from "lucide-react";
4282
+
4283
+ // src/ui/tooltip.tsx
4284
+ import { Tooltip as TooltipPrimitive } from "radix-ui";
4285
+ import { jsx as jsx7 } from "react/jsx-runtime";
4286
+ function TooltipProvider({
4287
+ delayDuration = 0,
4288
+ ...props
4289
+ }) {
4290
+ return /* @__PURE__ */ jsx7(TooltipPrimitive.Provider, { "data-slot": "tooltip-provider", delayDuration, ...props });
4291
+ }
4292
+ function Tooltip({ ...props }) {
4293
+ return /* @__PURE__ */ jsx7(TooltipPrimitive.Root, { "data-slot": "tooltip", ...props });
4294
+ }
4295
+ function TooltipTrigger({ ...props }) {
4296
+ return /* @__PURE__ */ jsx7(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
4297
+ }
4298
+ var arrowClassBySide = {
4299
+ top: "before:bottom-0 before:left-1/2 before:-translate-x-1/2 before:translate-y-1/2",
4300
+ bottom: "before:top-0 before:left-1/2 before:-translate-x-1/2 before:-translate-y-1/2",
4301
+ left: "before:right-0 before:top-1/2 before:-translate-y-1/2 before:translate-x-1/2",
4302
+ right: "before:left-0 before:top-1/2 before:-translate-y-1/2 before:-translate-x-1/2"
4303
+ };
4304
+ function TooltipContent({
4305
+ className,
4306
+ sideOffset = 6,
4307
+ side = "bottom",
4308
+ children,
4309
+ ...props
4310
+ }) {
4311
+ const resolvedSide = side ?? "bottom";
4312
+ return /* @__PURE__ */ jsx7(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx7(
4313
+ TooltipPrimitive.Content,
4314
+ {
4315
+ "data-slot": "tooltip-content",
4316
+ side,
4317
+ sideOffset,
4318
+ className: cn(
4319
+ "relative z-[2147483647] w-fit max-w-xs rounded-md bg-foreground px-3 py-1.5 text-xs text-background shadow-md",
4320
+ 'before:pointer-events-none before:absolute before:size-2 before:rotate-45 before:bg-foreground before:content-[""]',
4321
+ arrowClassBySide[resolvedSide],
4322
+ "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",
4323
+ "data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2",
4324
+ "data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2",
4325
+ className
4326
+ ),
4327
+ ...props,
4328
+ children
4329
+ }
4330
+ ) });
4331
+ }
4332
+
4333
+ // src/ui/item-action-toolbar.tsx
4334
+ import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
4335
+ function ToolbarActionTooltip({
4336
+ label,
4337
+ side = "bottom",
4338
+ disabled = false,
4339
+ buttonProps,
4340
+ children
4341
+ }) {
4342
+ const button = /* @__PURE__ */ jsx8(CustomToolbarButton, { type: "button", "aria-label": label, disabled, ...buttonProps, children });
4343
+ return /* @__PURE__ */ jsxs3(Tooltip, { children: [
4344
+ /* @__PURE__ */ jsx8(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ jsx8("span", { className: "inline-flex", children: button }) : button }),
4345
+ /* @__PURE__ */ jsx8(TooltipContent, { side, children: label })
4346
+ ] });
4347
+ }
4348
+ function ItemActionToolbar({
4349
+ onEditLink,
4350
+ onAddItem,
4351
+ onMore,
4352
+ addItemDisabled = true,
4353
+ moreDisabled = true,
4354
+ tooltipSide = "bottom"
4355
+ }) {
4356
+ return /* @__PURE__ */ jsx8(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs3(CustomToolbar, { children: [
4357
+ /* @__PURE__ */ jsx8(
4358
+ ToolbarActionTooltip,
4359
+ {
4360
+ label: "Add link",
4361
+ side: tooltipSide,
4362
+ buttonProps: {
4363
+ onMouseDown: (e) => {
4364
+ e.preventDefault();
4365
+ e.stopPropagation();
4366
+ onEditLink?.();
4367
+ },
4368
+ onClick: (e) => {
4369
+ e.preventDefault();
4370
+ e.stopPropagation();
4371
+ }
4372
+ },
4373
+ children: /* @__PURE__ */ jsx8(Link, { className: "size-4 shrink-0", "aria-hidden": true })
4374
+ }
4375
+ ),
4376
+ /* @__PURE__ */ jsx8(CustomToolbarDivider, {}),
4377
+ /* @__PURE__ */ jsx8(
4378
+ ToolbarActionTooltip,
4379
+ {
4380
+ label: "Add item",
4381
+ side: tooltipSide,
4382
+ disabled: addItemDisabled,
4383
+ buttonProps: {
4384
+ onMouseDown: (e) => {
4385
+ if (addItemDisabled) return;
4386
+ e.preventDefault();
4387
+ e.stopPropagation();
4388
+ onAddItem?.();
4389
+ }
4390
+ },
4391
+ children: /* @__PURE__ */ jsx8(Plus, { className: "size-4 shrink-0", "aria-hidden": true })
4392
+ }
4393
+ ),
4394
+ /* @__PURE__ */ jsx8(CustomToolbarDivider, {}),
4395
+ /* @__PURE__ */ jsx8(
4396
+ ToolbarActionTooltip,
4397
+ {
4398
+ label: "More",
4399
+ side: tooltipSide,
4400
+ disabled: moreDisabled,
4401
+ buttonProps: {
4402
+ onMouseDown: (e) => {
4403
+ if (moreDisabled) return;
4404
+ e.preventDefault();
4405
+ e.stopPropagation();
4406
+ onMore?.();
4407
+ }
4408
+ },
4409
+ children: /* @__PURE__ */ jsx8(MoreHorizontal, { className: "size-4 shrink-0", "aria-hidden": true })
4410
+ }
4411
+ )
4412
+ ] }) });
4413
+ }
4414
+
4415
+ // src/ui/item-interaction-layer.tsx
4416
+ import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
4417
+ var PRIMARY = "var(--ohw-primary, #0885FE)";
4418
+ var FOCUS_RING = "0 0 0 4px rgba(8, 133, 254, 0.12)";
4419
+ var DRAG_SHADOW = "0px 4px 6px -1px rgba(0, 0, 0, 0.1), 0px 2px 4px -2px rgba(0, 0, 0, 0.1)";
4420
+ function getChromeStyle(state) {
4421
+ switch (state) {
4422
+ case "hover":
4423
+ return {
4424
+ border: `1.5px dashed ${PRIMARY}`,
4425
+ boxShadow: "none"
4426
+ };
4427
+ case "sibling-hint":
4428
+ return {
4429
+ border: `1.5px dashed color-mix(in srgb, ${PRIMARY} 30%, transparent)`,
4430
+ boxShadow: "none"
4431
+ };
4432
+ case "active-top":
4433
+ case "active-bottom":
4434
+ return {
4435
+ border: `2px solid ${PRIMARY}`,
4436
+ boxShadow: FOCUS_RING
4437
+ };
4438
+ case "dragging":
4439
+ return {
4440
+ border: `2px solid ${PRIMARY}`,
4441
+ boxShadow: DRAG_SHADOW
4442
+ };
4443
+ default:
4444
+ return {};
4445
+ }
4446
+ }
4447
+ function ItemInteractionLayer({
4448
+ rect,
4449
+ state,
4450
+ elRef,
4451
+ toolbar,
4452
+ showHandle = false,
4453
+ dragDisabled = false,
4454
+ dragHandleLabel = "Reorder item",
4455
+ onDragHandleDragStart,
4456
+ onDragHandleDragEnd,
4457
+ chromeGap = 6,
4458
+ className
4459
+ }) {
4460
+ if (state === "default") return null;
4461
+ const isActive = state === "active-top" || state === "active-bottom";
4462
+ const isDragging = state === "dragging";
4463
+ const showToolbar = isActive && toolbar;
4464
+ const showDragHandle = isActive && showHandle && !isDragging;
4465
+ return /* @__PURE__ */ jsxs4(
4466
+ "div",
4467
+ {
4468
+ ref: elRef,
4469
+ "data-ohw-item-interaction": "",
4470
+ "data-ohw-item-interaction-state": state,
4471
+ className: cn("pointer-events-none", className),
4472
+ style: {
4473
+ position: "fixed",
4474
+ top: rect.top - chromeGap,
4475
+ left: rect.left - chromeGap,
4476
+ width: rect.width + chromeGap * 2,
4477
+ height: rect.height + chromeGap * 2,
4478
+ zIndex: 2147483646
4479
+ },
4480
+ children: [
4481
+ /* @__PURE__ */ jsx9(
4482
+ "div",
4483
+ {
4484
+ "aria-hidden": true,
4485
+ className: "absolute inset-0 rounded-lg",
4486
+ style: getChromeStyle(state)
4487
+ }
4488
+ ),
4489
+ showDragHandle && /* @__PURE__ */ jsx9(
4490
+ "div",
4491
+ {
4492
+ "data-ohw-drag-handle-container": "",
4493
+ className: "pointer-events-auto absolute left-0 top-1/2 -translate-x-[calc(100%+7px)] -translate-y-1/2",
4494
+ children: /* @__PURE__ */ jsx9(
4495
+ DragHandle,
4496
+ {
4497
+ draggable: !dragDisabled,
4498
+ "aria-label": dragHandleLabel,
4499
+ disabled: dragDisabled,
4500
+ onDragStart: (e) => {
4501
+ if (dragDisabled) {
4502
+ e.preventDefault();
4503
+ return;
4504
+ }
4505
+ e.dataTransfer?.setData("text/plain", dragHandleLabel);
4506
+ e.dataTransfer.effectAllowed = "move";
4507
+ onDragHandleDragStart?.(e);
4508
+ },
4509
+ onDragEnd: onDragHandleDragEnd
4510
+ }
4511
+ )
4512
+ }
4513
+ ),
4514
+ showToolbar && state === "active-top" && /* @__PURE__ */ jsx9(
4515
+ "div",
4516
+ {
4517
+ className: "pointer-events-auto absolute bottom-full left-1/2 mb-2 -translate-x-1/2",
4518
+ "data-ohw-item-toolbar-anchor": "top",
4519
+ children: toolbar
4520
+ }
4521
+ ),
4522
+ showToolbar && state === "active-bottom" && /* @__PURE__ */ jsx9(
4523
+ "div",
4524
+ {
4525
+ className: "pointer-events-auto absolute left-1/2 top-full mt-2 -translate-x-1/2",
4526
+ "data-ohw-item-toolbar-anchor": "bottom",
4527
+ children: toolbar
4528
+ }
4529
+ )
4530
+ ]
4531
+ }
4532
+ );
4533
+ }
4534
+
4205
4535
  // src/OhhwellsBridge.tsx
4206
4536
  import { createPortal } from "react-dom";
4207
4537
  import { usePathname, useRouter, useSearchParams } from "next/navigation";
@@ -4481,60 +4811,60 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
4481
4811
  }
4482
4812
 
4483
4813
  // src/ui/dialog.tsx
4484
- import * as React3 from "react";
4814
+ import * as React5 from "react";
4485
4815
  import { Dialog as DialogPrimitive } from "radix-ui";
4486
4816
 
4487
4817
  // src/ui/icons.tsx
4488
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
4818
+ import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
4489
4819
  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" })
4820
+ 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: [
4821
+ /* @__PURE__ */ jsx10("path", { d: "M18 6 6 18" }),
4822
+ /* @__PURE__ */ jsx10("path", { d: "m6 6 12 12" })
4493
4823
  ] });
4494
4824
  }
4495
4825
  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" }) });
4826
+ 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
4827
  }
4498
4828
  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" })
4829
+ 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: [
4830
+ /* @__PURE__ */ jsx10("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }),
4831
+ /* @__PURE__ */ jsx10("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" })
4502
4832
  ] });
4503
4833
  }
4504
4834
  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" })
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("circle", { cx: "12", cy: "12", r: "10" }),
4837
+ /* @__PURE__ */ jsx10("path", { d: "M12 16v-4" }),
4838
+ /* @__PURE__ */ jsx10("path", { d: "M12 8h.01" })
4509
4839
  ] });
4510
4840
  }
4511
4841
  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" })
4842
+ 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: [
4843
+ /* @__PURE__ */ jsx10("path", { d: "M5 12h14" }),
4844
+ /* @__PURE__ */ jsx10("path", { d: "m12 5 7 7-7 7" })
4515
4845
  ] });
4516
4846
  }
4517
4847
  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" })
4848
+ 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: [
4849
+ /* @__PURE__ */ jsx10("rect", { width: "18", height: "7", x: "3", y: "3", rx: "1" }),
4850
+ /* @__PURE__ */ jsx10("rect", { width: "9", height: "7", x: "3", y: "14", rx: "1" }),
4851
+ /* @__PURE__ */ jsx10("rect", { width: "5", height: "7", x: "16", y: "14", rx: "1" })
4522
4852
  ] });
4523
4853
  }
4524
4854
 
4525
4855
  // src/ui/dialog.tsx
4526
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
4856
+ import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
4527
4857
  function Dialog2({ ...props }) {
4528
- return /* @__PURE__ */ jsx6(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
4858
+ return /* @__PURE__ */ jsx11(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
4529
4859
  }
4530
4860
  function DialogPortal({ ...props }) {
4531
- return /* @__PURE__ */ jsx6(DialogPrimitive.Portal, { ...props });
4861
+ return /* @__PURE__ */ jsx11(DialogPrimitive.Portal, { ...props });
4532
4862
  }
4533
4863
  function DialogOverlay({
4534
4864
  className,
4535
4865
  ...props
4536
4866
  }) {
4537
- return /* @__PURE__ */ jsx6(
4867
+ return /* @__PURE__ */ jsx11(
4538
4868
  DialogPrimitive.Overlay,
4539
4869
  {
4540
4870
  "data-slot": "dialog-overlay",
@@ -4544,11 +4874,11 @@ function DialogOverlay({
4544
4874
  }
4545
4875
  );
4546
4876
  }
4547
- var DialogContent = React3.forwardRef(({ className, children, showCloseButton = true, container, ...props }, ref) => {
4877
+ var DialogContent = React5.forwardRef(({ className, children, showCloseButton = true, container, ...props }, ref) => {
4548
4878
  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(
4879
+ return /* @__PURE__ */ jsxs6(DialogPortal, { container: container ?? void 0, children: [
4880
+ /* @__PURE__ */ jsx11(DialogOverlay, { className: cn(positionMode, "inset-0") }),
4881
+ /* @__PURE__ */ jsxs6(
4552
4882
  DialogPrimitive.Content,
4553
4883
  {
4554
4884
  ref,
@@ -4564,13 +4894,13 @@ var DialogContent = React3.forwardRef(({ className, children, showCloseButton =
4564
4894
  ...props,
4565
4895
  children: [
4566
4896
  children,
4567
- showCloseButton ? /* @__PURE__ */ jsx6(
4897
+ showCloseButton ? /* @__PURE__ */ jsx11(
4568
4898
  DialogPrimitive.Close,
4569
4899
  {
4570
4900
  type: "button",
4571
4901
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
4572
4902
  "aria-label": "Close",
4573
- children: /* @__PURE__ */ jsx6(IconX, { "aria-hidden": true })
4903
+ children: /* @__PURE__ */ jsx11(IconX, { "aria-hidden": true })
4574
4904
  }
4575
4905
  ) : null
4576
4906
  ]
@@ -4580,12 +4910,12 @@ var DialogContent = React3.forwardRef(({ className, children, showCloseButton =
4580
4910
  });
4581
4911
  DialogContent.displayName = DialogPrimitive.Content.displayName;
4582
4912
  function DialogHeader({ className, ...props }) {
4583
- return /* @__PURE__ */ jsx6("div", { className: cn("flex flex-col gap-1.5", className), ...props });
4913
+ return /* @__PURE__ */ jsx11("div", { className: cn("flex flex-col gap-1.5", className), ...props });
4584
4914
  }
4585
4915
  function DialogFooter({ className, ...props }) {
4586
- return /* @__PURE__ */ jsx6("div", { className: cn("flex items-center justify-end gap-2", className), ...props });
4916
+ return /* @__PURE__ */ jsx11("div", { className: cn("flex items-center justify-end gap-2", className), ...props });
4587
4917
  }
4588
- var DialogTitle = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx6(
4918
+ var DialogTitle = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx11(
4589
4919
  DialogPrimitive.Title,
4590
4920
  {
4591
4921
  ref,
@@ -4594,7 +4924,7 @@ var DialogTitle = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE
4594
4924
  }
4595
4925
  ));
4596
4926
  DialogTitle.displayName = DialogPrimitive.Title.displayName;
4597
- var DialogDescription = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx6(
4927
+ var DialogDescription = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx11(
4598
4928
  DialogPrimitive.Description,
4599
4929
  {
4600
4930
  ref,
@@ -4606,9 +4936,9 @@ DialogDescription.displayName = DialogPrimitive.Description.displayName;
4606
4936
  var DialogClose = DialogPrimitive.Close;
4607
4937
 
4608
4938
  // src/ui/button.tsx
4609
- import * as React4 from "react";
4939
+ import * as React6 from "react";
4610
4940
  import { Slot } from "radix-ui";
4611
- import { jsx as jsx7 } from "react/jsx-runtime";
4941
+ import { jsx as jsx12 } from "react/jsx-runtime";
4612
4942
  var buttonVariants = cva(
4613
4943
  "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
4944
  {
@@ -4629,10 +4959,10 @@ var buttonVariants = cva(
4629
4959
  }
4630
4960
  }
4631
4961
  );
4632
- var Button = React4.forwardRef(
4962
+ var Button = React6.forwardRef(
4633
4963
  ({ className, variant, size, asChild = false, ...props }, ref) => {
4634
4964
  const Comp = asChild ? Slot.Root : "button";
4635
- return /* @__PURE__ */ jsx7(
4965
+ return /* @__PURE__ */ jsx12(
4636
4966
  Comp,
4637
4967
  {
4638
4968
  ref,
@@ -4646,37 +4976,37 @@ var Button = React4.forwardRef(
4646
4976
  Button.displayName = "Button";
4647
4977
 
4648
4978
  // src/ui/link-modal/DestinationBreadcrumb.tsx
4649
- import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
4979
+ import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
4650
4980
  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 })
4981
+ return /* @__PURE__ */ jsxs7("div", { className: "flex w-full flex-col gap-2", children: [
4982
+ /* @__PURE__ */ jsx13("p", { className: "text-sm font-medium text-foreground", children: "Destination" }),
4983
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-3", children: [
4984
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
4985
+ /* @__PURE__ */ jsx13(IconFile, { className: "shrink-0 text-foreground", "aria-hidden": true }),
4986
+ /* @__PURE__ */ jsx13("span", { className: "text-sm font-medium leading-none text-foreground", children: pageTitle })
4657
4987
  ] }),
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 })
4988
+ /* @__PURE__ */ jsx13(IconArrowRight, { className: "shrink-0 text-muted-foreground", "aria-hidden": true }),
4989
+ /* @__PURE__ */ jsxs7("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
4990
+ /* @__PURE__ */ jsx13(IconSection, { className: "shrink-0 text-foreground", "aria-hidden": true }),
4991
+ /* @__PURE__ */ jsx13("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
4662
4992
  ] })
4663
4993
  ] })
4664
4994
  ] });
4665
4995
  }
4666
4996
 
4667
4997
  // src/ui/link-modal/SectionTreeItem.tsx
4668
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
4998
+ import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
4669
4999
  function SectionTreeItem({ section, onSelect, selected }) {
4670
5000
  const interactive = Boolean(onSelect);
4671
- return /* @__PURE__ */ jsxs6("div", { className: "flex h-9 w-full items-end pl-3", children: [
4672
- /* @__PURE__ */ jsx9(
5001
+ return /* @__PURE__ */ jsxs8("div", { className: "flex h-9 w-full items-end pl-3", children: [
5002
+ /* @__PURE__ */ jsx14(
4673
5003
  "div",
4674
5004
  {
4675
5005
  className: "mr-[-1px] h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
4676
5006
  "aria-hidden": true
4677
5007
  }
4678
5008
  ),
4679
- /* @__PURE__ */ jsxs6(
5009
+ /* @__PURE__ */ jsxs8(
4680
5010
  "div",
4681
5011
  {
4682
5012
  role: interactive ? "button" : void 0,
@@ -4694,8 +5024,8 @@ function SectionTreeItem({ section, onSelect, selected }) {
4694
5024
  interactive && selected && "border-primary"
4695
5025
  ),
4696
5026
  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 })
5027
+ /* @__PURE__ */ jsx14(IconSection, { className: "shrink-0 text-foreground", "aria-hidden": true }),
5028
+ /* @__PURE__ */ jsx14("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
4699
5029
  ]
4700
5030
  }
4701
5031
  )
@@ -4703,11 +5033,11 @@ function SectionTreeItem({ section, onSelect, selected }) {
4703
5033
  }
4704
5034
  function SectionPickerList({ sections, onSelect }) {
4705
5035
  if (sections.length === 0) {
4706
- return /* @__PURE__ */ jsx9("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." });
5036
+ return /* @__PURE__ */ jsx14("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." });
4707
5037
  }
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))
5038
+ return /* @__PURE__ */ jsxs8("div", { className: "flex flex-col gap-1", children: [
5039
+ /* @__PURE__ */ jsx14("p", { className: "text-sm text-muted-foreground", children: "Pick a section this link should scroll to." }),
5040
+ sections.map((section) => /* @__PURE__ */ jsx14(SectionTreeItem, { section, onSelect }, section.id))
4711
5041
  ] });
4712
5042
  }
4713
5043
 
@@ -4715,11 +5045,11 @@ function SectionPickerList({ sections, onSelect }) {
4715
5045
  import { useId as useId2, useRef as useRef2, useState as useState3 } from "react";
4716
5046
 
4717
5047
  // src/ui/input.tsx
4718
- import * as React5 from "react";
4719
- import { jsx as jsx10 } from "react/jsx-runtime";
4720
- var Input = React5.forwardRef(
5048
+ import * as React7 from "react";
5049
+ import { jsx as jsx15 } from "react/jsx-runtime";
5050
+ var Input = React7.forwardRef(
4721
5051
  ({ className, type, ...props }, ref) => {
4722
- return /* @__PURE__ */ jsx10(
5052
+ return /* @__PURE__ */ jsx15(
4723
5053
  "input",
4724
5054
  {
4725
5055
  type,
@@ -4738,9 +5068,9 @@ Input.displayName = "Input";
4738
5068
 
4739
5069
  // src/ui/label.tsx
4740
5070
  import { Label as LabelPrimitive } from "radix-ui";
4741
- import { jsx as jsx11 } from "react/jsx-runtime";
5071
+ import { jsx as jsx16 } from "react/jsx-runtime";
4742
5072
  function Label({ className, ...props }) {
4743
- return /* @__PURE__ */ jsx11(
5073
+ return /* @__PURE__ */ jsx16(
4744
5074
  LabelPrimitive.Root,
4745
5075
  {
4746
5076
  "data-slot": "label",
@@ -4751,9 +5081,9 @@ function Label({ className, ...props }) {
4751
5081
  }
4752
5082
 
4753
5083
  // src/ui/link-modal/UrlOrPageInput.tsx
4754
- import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
5084
+ import { jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
4755
5085
  function FieldChevron({ onClick }) {
4756
- return /* @__PURE__ */ jsx12(
5086
+ return /* @__PURE__ */ jsx17(
4757
5087
  "button",
4758
5088
  {
4759
5089
  type: "button",
@@ -4761,7 +5091,7 @@ function FieldChevron({ onClick }) {
4761
5091
  onClick,
4762
5092
  "aria-label": "Open page list",
4763
5093
  tabIndex: -1,
4764
- children: /* @__PURE__ */ jsx12(IconChevronDown, {})
5094
+ children: /* @__PURE__ */ jsx17(IconChevronDown, {})
4765
5095
  }
4766
5096
  );
4767
5097
  }
@@ -4800,12 +5130,12 @@ function UrlOrPageInput({
4800
5130
  "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
5131
  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
5132
  );
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(
5133
+ return /* @__PURE__ */ jsxs9("div", { className: "flex w-full flex-col gap-2 p-0", children: [
5134
+ /* @__PURE__ */ jsx17(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
5135
+ /* @__PURE__ */ jsxs9("div", { className: "relative w-full", children: [
5136
+ /* @__PURE__ */ jsxs9("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
5137
+ selectedPage ? /* @__PURE__ */ jsx17("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ jsx17(IconFile, { className: "text-foreground", "aria-hidden": true }) }) : null,
5138
+ readOnly ? /* @__PURE__ */ jsx17("span", { className: "min-w-0 flex-1 truncate text-sm leading-5 text-foreground", children: selectedPage?.title ?? value }) : /* @__PURE__ */ jsx17(
4809
5139
  Input,
4810
5140
  {
4811
5141
  ref: inputRef,
@@ -4824,7 +5154,7 @@ function UrlOrPageInput({
4824
5154
  )
4825
5155
  }
4826
5156
  ),
4827
- selectedPage && !readOnly ? /* @__PURE__ */ jsx12(
5157
+ selectedPage && !readOnly ? /* @__PURE__ */ jsx17(
4828
5158
  "button",
4829
5159
  {
4830
5160
  type: "button",
@@ -4832,26 +5162,26 @@ function UrlOrPageInput({
4832
5162
  onMouseDown: clearSelection,
4833
5163
  "aria-label": "Clear selected page",
4834
5164
  tabIndex: -1,
4835
- children: /* @__PURE__ */ jsx12(IconX, { "aria-hidden": true })
5165
+ children: /* @__PURE__ */ jsx17(IconX, { "aria-hidden": true })
4836
5166
  }
4837
5167
  ) : null,
4838
- !readOnly ? /* @__PURE__ */ jsx12(FieldChevron, { onClick: toggleDropdown }) : null
5168
+ !readOnly ? /* @__PURE__ */ jsx17(FieldChevron, { onClick: toggleDropdown }) : null
4839
5169
  ] }),
4840
- dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ jsx12(
5170
+ dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ jsx17(
4841
5171
  "div",
4842
5172
  {
4843
5173
  "data-ohw-link-page-dropdown": "",
4844
5174
  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
5175
  onMouseDown: (e) => e.preventDefault(),
4846
- children: filteredPages.map((page) => /* @__PURE__ */ jsxs7(
5176
+ children: filteredPages.map((page) => /* @__PURE__ */ jsxs9(
4847
5177
  "button",
4848
5178
  {
4849
5179
  type: "button",
4850
5180
  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
5181
  onClick: () => onPageSelect(page),
4852
5182
  children: [
4853
- /* @__PURE__ */ jsx12(IconFile, { className: "shrink-0", "aria-hidden": true }),
4854
- /* @__PURE__ */ jsx12("span", { className: "truncate", children: page.title })
5183
+ /* @__PURE__ */ jsx17(IconFile, { className: "shrink-0", "aria-hidden": true }),
5184
+ /* @__PURE__ */ jsx17("span", { className: "truncate", children: page.title })
4855
5185
  ]
4856
5186
  },
4857
5187
  page.path
@@ -4859,7 +5189,7 @@ function UrlOrPageInput({
4859
5189
  }
4860
5190
  ) : null
4861
5191
  ] }),
4862
- urlError ? /* @__PURE__ */ jsx12("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
5192
+ urlError ? /* @__PURE__ */ jsx17("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
4863
5193
  ] });
4864
5194
  }
4865
5195
 
@@ -5027,7 +5357,7 @@ function useLinkModalState({
5027
5357
  }
5028
5358
 
5029
5359
  // src/ui/link-modal/LinkEditorPanel.tsx
5030
- import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
5360
+ import { Fragment as Fragment2, jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
5031
5361
  function LinkEditorPanel({
5032
5362
  open = true,
5033
5363
  mode = "create",
@@ -5051,25 +5381,25 @@ function LinkEditorPanel({
5051
5381
  onSubmit
5052
5382
  });
5053
5383
  const isCancel = state.secondaryLabel === "Cancel";
5054
- return /* @__PURE__ */ jsxs8(Fragment2, { children: [
5055
- /* @__PURE__ */ jsx13(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx13(
5384
+ return /* @__PURE__ */ jsxs10(Fragment2, { children: [
5385
+ /* @__PURE__ */ jsx18(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx18(
5056
5386
  "button",
5057
5387
  {
5058
5388
  type: "button",
5059
5389
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
5060
5390
  "aria-label": "Close",
5061
- children: /* @__PURE__ */ jsx13(IconX, { "aria-hidden": true })
5391
+ children: /* @__PURE__ */ jsx18(IconX, { "aria-hidden": true })
5062
5392
  }
5063
5393
  ) }),
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(
5394
+ /* @__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 }) }),
5395
+ /* @__PURE__ */ jsxs10("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
5396
+ state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ jsx18(
5067
5397
  DestinationBreadcrumb,
5068
5398
  {
5069
5399
  pageTitle: state.selectedPage.title,
5070
5400
  sectionLabel: state.selectedSection.label
5071
5401
  }
5072
- ) : /* @__PURE__ */ jsx13(
5402
+ ) : /* @__PURE__ */ jsx18(
5073
5403
  UrlOrPageInput,
5074
5404
  {
5075
5405
  value: state.searchValue,
@@ -5082,18 +5412,18 @@ function LinkEditorPanel({
5082
5412
  urlError: state.urlError
5083
5413
  }
5084
5414
  ),
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." })
5415
+ state.showChooseSection ? /* @__PURE__ */ jsxs10("div", { className: "flex flex-col justify-center gap-2", children: [
5416
+ /* @__PURE__ */ jsx18(Button, { type: "button", variant: "outline", className: "w-fit cursor-pointer", size: "sm", onClick: state.handleChooseSection, children: "Choose a section" }),
5417
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
5418
+ /* @__PURE__ */ jsx18(IconInfo, { className: "shrink-0", "aria-hidden": true }),
5419
+ /* @__PURE__ */ jsx18("span", { children: "Pick a section this link should scroll to." })
5090
5420
  ] })
5091
5421
  ] }) : 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
5422
+ state.showSectionPicker ? /* @__PURE__ */ jsx18(SectionPickerList, { sections: state.activeSections, onSelect: state.handleSectionSelect }) : null,
5423
+ state.showSectionRow && state.selectedSection ? /* @__PURE__ */ jsx18(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
5094
5424
  ] }),
5095
- /* @__PURE__ */ jsxs8(DialogFooter, { className: "w-full px-6 pb-6", children: [
5096
- /* @__PURE__ */ jsx13(
5425
+ /* @__PURE__ */ jsxs10(DialogFooter, { className: "w-full px-6 pb-6", children: [
5426
+ /* @__PURE__ */ jsx18(
5097
5427
  Button,
5098
5428
  {
5099
5429
  type: "button",
@@ -5108,7 +5438,7 @@ function LinkEditorPanel({
5108
5438
  children: state.secondaryLabel
5109
5439
  }
5110
5440
  ),
5111
- /* @__PURE__ */ jsx13(
5441
+ /* @__PURE__ */ jsx18(
5112
5442
  Button,
5113
5443
  {
5114
5444
  type: "button",
@@ -5127,7 +5457,7 @@ function LinkEditorPanel({
5127
5457
  }
5128
5458
 
5129
5459
  // src/ui/link-modal/LinkPopover.tsx
5130
- import { jsx as jsx14 } from "react/jsx-runtime";
5460
+ import { jsx as jsx19 } from "react/jsx-runtime";
5131
5461
  function LinkPopover({
5132
5462
  open = true,
5133
5463
  panelRef,
@@ -5135,14 +5465,14 @@ function LinkPopover({
5135
5465
  onClose,
5136
5466
  ...editorProps
5137
5467
  }) {
5138
- return /* @__PURE__ */ jsx14(
5468
+ return /* @__PURE__ */ jsx19(
5139
5469
  Dialog2,
5140
5470
  {
5141
5471
  open,
5142
5472
  onOpenChange: (next) => {
5143
5473
  if (!next) onClose?.();
5144
5474
  },
5145
- children: /* @__PURE__ */ jsx14(
5475
+ children: /* @__PURE__ */ jsx19(
5146
5476
  DialogContent,
5147
5477
  {
5148
5478
  ref: panelRef,
@@ -5152,7 +5482,7 @@ function LinkPopover({
5152
5482
  "data-ohw-bridge": "",
5153
5483
  showCloseButton: false,
5154
5484
  className: "gap-0 p-0 w-full md:w-md pointer-events-auto",
5155
- children: /* @__PURE__ */ jsx14(LinkEditorPanel, { ...editorProps, open, onClose })
5485
+ children: /* @__PURE__ */ jsx19(LinkEditorPanel, { ...editorProps, open, onClose })
5156
5486
  }
5157
5487
  )
5158
5488
  }
@@ -5218,7 +5548,7 @@ function shouldUseDevFixtures() {
5218
5548
  }
5219
5549
 
5220
5550
  // src/ui/badge.tsx
5221
- import { jsx as jsx15 } from "react/jsx-runtime";
5551
+ import { jsx as jsx20 } from "react/jsx-runtime";
5222
5552
  var badgeVariants = cva(
5223
5553
  "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
5554
  {
@@ -5236,12 +5566,13 @@ var badgeVariants = cva(
5236
5566
  }
5237
5567
  );
5238
5568
  function Badge({ className, variant, ...props }) {
5239
- return /* @__PURE__ */ jsx15("div", { className: cn(badgeVariants({ variant }), className), ...props });
5569
+ return /* @__PURE__ */ jsx20("div", { className: cn(badgeVariants({ variant }), className), ...props });
5240
5570
  }
5241
5571
 
5242
5572
  // src/OhhwellsBridge.tsx
5243
- import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs9 } from "react/jsx-runtime";
5244
- var PRIMARY = "#0885FE";
5573
+ import { Link as Link2 } from "lucide-react";
5574
+ import { Fragment as Fragment3, jsx as jsx21, jsxs as jsxs11 } from "react/jsx-runtime";
5575
+ var PRIMARY2 = "#0885FE";
5245
5576
  var IMAGE_FADE_MS = 300;
5246
5577
  function runOpacityFade(el, onDone) {
5247
5578
  const anim = el.animate([{ opacity: 0 }, { opacity: 1 }], {
@@ -5414,7 +5745,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
5414
5745
  const root = createRoot(container);
5415
5746
  flushSync(() => {
5416
5747
  root.render(
5417
- /* @__PURE__ */ jsx16(
5748
+ /* @__PURE__ */ jsx21(
5418
5749
  SchedulingWidget,
5419
5750
  {
5420
5751
  notifyOnConnect,
@@ -5462,6 +5793,20 @@ function applyLinkHref(el, val) {
5462
5793
  const anchor = el instanceof HTMLAnchorElement ? el : el.querySelector("a");
5463
5794
  if (anchor) anchor.setAttribute("href", val);
5464
5795
  }
5796
+ function getEditMeasureEl(editable) {
5797
+ return editable.closest("[data-ohw-href-key]") ?? editable;
5798
+ }
5799
+ function isDragHandleDisabled(el) {
5800
+ const carriers = [
5801
+ el.closest("[data-ohw-href-key]"),
5802
+ el.closest("[data-ohw-editable]")
5803
+ ];
5804
+ return carriers.some((carrier) => {
5805
+ if (!carrier) return false;
5806
+ const raw = carrier.getAttribute("data-ohw-drag-disabled");
5807
+ return raw === "true" || raw === "";
5808
+ });
5809
+ }
5465
5810
  function collectEditableNodes() {
5466
5811
  const nodes = Array.from(document.querySelectorAll("[data-ohw-editable]")).map((el) => {
5467
5812
  if (el.dataset.ohwEditable === "image") {
@@ -5515,12 +5860,49 @@ function getHrefKeyFromElement(el) {
5515
5860
  function isNavbarButton(el) {
5516
5861
  return Boolean(el.closest('[data-ohw-role="navbar-button"]'));
5517
5862
  }
5863
+ function getNavigationItemAnchor(el) {
5864
+ const anchor = el.matches("[data-ohw-href-key]") ? el : el.closest("[data-ohw-href-key]");
5865
+ if (!anchor) return null;
5866
+ if (!anchor.querySelector('[data-ohw-editable="text"]')) return null;
5867
+ return anchor;
5868
+ }
5869
+ function isNavigationItem(el) {
5870
+ return getNavigationItemAnchor(el) !== null;
5871
+ }
5872
+ function getNavigationItemAddHintTarget(anchor) {
5873
+ const items = listNavigationItems();
5874
+ const idx = items.indexOf(anchor);
5875
+ if (idx >= 0 && idx < items.length - 1) return items[idx + 1];
5876
+ return anchor;
5877
+ }
5878
+ function listNavigationItems() {
5879
+ return Array.from(
5880
+ document.querySelectorAll("nav [data-ohw-href-key], footer [data-ohw-href-key]")
5881
+ ).filter((el) => isNavigationItem(el));
5882
+ }
5883
+ function getNavigationItemReorderState(anchor) {
5884
+ if (isNavbarButton(anchor)) return { key: null, disabled: false };
5885
+ return getReorderHandleStateFromAnchor(anchor);
5886
+ }
5887
+ function getReorderHandleState(el) {
5888
+ const linkEl = el.closest("[data-ohw-href-key]");
5889
+ if (!linkEl || getNavigationItemAnchor(linkEl)) return { key: null, disabled: false };
5890
+ return getReorderHandleStateFromAnchor(linkEl);
5891
+ }
5892
+ function getReorderHandleStateFromAnchor(anchor) {
5893
+ const key = anchor.getAttribute("data-ohw-href-key");
5894
+ if (!key) return { key: null, disabled: false };
5895
+ return { key, disabled: isDragHandleDisabled(anchor) };
5896
+ }
5518
5897
  function clearHrefKeyHover(anchor) {
5519
5898
  anchor.removeAttribute("data-ohw-hovered");
5520
5899
  anchor.querySelectorAll("[data-ohw-hovered]").forEach((el) => {
5521
5900
  el.removeAttribute("data-ohw-hovered");
5522
5901
  });
5523
5902
  }
5903
+ function isInsideNavigationItem(el) {
5904
+ return getNavigationItemAnchor(el) !== null;
5905
+ }
5524
5906
  function collectSections() {
5525
5907
  return collectSectionsFromDom();
5526
5908
  }
@@ -5661,24 +6043,64 @@ var TOOLBAR_GROUPS = [
5661
6043
  { cmd: "insertOrderedList", title: "Numbered List" }
5662
6044
  ]
5663
6045
  ];
5664
- function GlowFrame({ rect, elRef }) {
6046
+ function EditGlowChrome({
6047
+ rect,
6048
+ elRef,
6049
+ reorderHrefKey,
6050
+ dragDisabled = false
6051
+ }) {
5665
6052
  const GAP = 6;
5666
- return /* @__PURE__ */ jsx16(
6053
+ return /* @__PURE__ */ jsxs11(
5667
6054
  "div",
5668
6055
  {
5669
6056
  ref: elRef,
6057
+ "data-ohw-edit-chrome": "",
5670
6058
  style: {
5671
6059
  position: "fixed",
5672
6060
  top: rect.top - GAP,
5673
6061
  left: rect.left - GAP,
5674
6062
  width: rect.width + GAP * 2,
5675
6063
  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
6064
  pointerEvents: "none",
5680
6065
  zIndex: 2147483646
5681
- }
6066
+ },
6067
+ children: [
6068
+ /* @__PURE__ */ jsx21(
6069
+ "div",
6070
+ {
6071
+ style: {
6072
+ position: "absolute",
6073
+ inset: 0,
6074
+ border: "2px solid var(--ohw-primary, #0885FE)",
6075
+ borderRadius: 8,
6076
+ boxShadow: "0 0 0 4px rgba(8, 133, 254, 0.12)",
6077
+ pointerEvents: "none"
6078
+ }
6079
+ }
6080
+ ),
6081
+ reorderHrefKey && /* @__PURE__ */ jsx21(
6082
+ "div",
6083
+ {
6084
+ "data-ohw-drag-handle-container": "",
6085
+ "data-ohw-drag-disabled": dragDisabled ? "" : void 0,
6086
+ style: {
6087
+ position: "absolute",
6088
+ left: 0,
6089
+ top: "50%",
6090
+ transform: "translate(calc(-100% - 7px), -50%)",
6091
+ pointerEvents: dragDisabled ? "none" : "auto"
6092
+ },
6093
+ children: /* @__PURE__ */ jsx21(
6094
+ DragHandle,
6095
+ {
6096
+ "aria-label": `Reorder ${reorderHrefKey}`,
6097
+ disabled: dragDisabled,
6098
+ "aria-disabled": dragDisabled
6099
+ }
6100
+ )
6101
+ }
6102
+ )
6103
+ ]
5682
6104
  }
5683
6105
  );
5684
6106
  }
@@ -5722,9 +6144,9 @@ function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
5722
6144
  const pinnedTop = Math.min(maxBottom - approxH, Math.max(minTop, clip.top + gap));
5723
6145
  return { top: pinnedTop + approxH, transform: "translateX(-50%) translateY(-100%)" };
5724
6146
  }
5725
- function calcToolbarPos(rect, parentScroll, approxW = 330) {
6147
+ function calcToolbarPos(rect, parentScroll, approxW = 306) {
5726
6148
  const GAP = 8;
5727
- const APPROX_H = 36;
6149
+ const APPROX_H = 32;
5728
6150
  const APPROX_W = approxW;
5729
6151
  const clip = getIframeVisibleClip(parentScroll);
5730
6152
  const clipTop = clip?.top ?? 0;
@@ -5758,182 +6180,60 @@ function calcToolbarPos(rect, parentScroll, approxW = 330) {
5758
6180
  const left = Math.max(GAP + APPROX_W / 2, Math.min(rawLeft, window.innerWidth - GAP - APPROX_W / 2));
5759
6181
  return { top, left, transform };
5760
6182
  }
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
- ] });
6183
+ function resolveItemInteractionState(rect, parentScroll) {
6184
+ const { transform } = calcToolbarPos(rect, parentScroll, 120);
6185
+ return transform.includes("translateY(-100%)") ? "active-top" : "active-bottom";
6186
+ }
5765
6187
  function FloatingToolbar({
5766
6188
  rect,
5767
6189
  parentScroll,
5768
6190
  elRef,
5769
- variant = "rich-text",
5770
6191
  onCommand,
5771
6192
  activeCommands,
5772
6193
  showEditLink,
5773
6194
  onEditLink
5774
6195
  }) {
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(
6196
+ const { top, left, transform } = calcToolbarPos(rect, parentScroll, 330);
6197
+ return /* @__PURE__ */ jsx21(
5870
6198
  "div",
5871
6199
  {
5872
6200
  ref: elRef,
5873
- "data-ohw-toolbar": "",
5874
6201
  style: {
5875
6202
  position: "fixed",
5876
6203
  top,
5877
6204
  left,
5878
6205
  transform,
5879
6206
  zIndex: 2147483647,
5880
- background: "#fff",
5881
- border: "1px solid #E7E5E4",
5882
- borderRadius: 6,
5883
- boxShadow: "0px 2px 4px -2px rgba(0,0,0,.1),0px 4px 6px -1px rgba(0,0,0,.1)",
5884
- display: "flex",
5885
- alignItems: "center",
5886
- padding: 4,
5887
- gap: 6,
5888
- fontFamily: "sans-serif",
5889
- pointerEvents: "auto",
5890
- whiteSpace: "nowrap"
6207
+ pointerEvents: "auto"
5891
6208
  },
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 } }),
6209
+ children: /* @__PURE__ */ jsxs11(CustomToolbar, { children: [
6210
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs11(React8.Fragment, { children: [
6211
+ gi > 0 && /* @__PURE__ */ jsx21(CustomToolbarDivider, {}),
5896
6212
  btns.map((btn) => {
5897
6213
  const isActive = activeCommands.has(btn.cmd);
5898
- return /* @__PURE__ */ jsx16(
5899
- "button",
6214
+ return /* @__PURE__ */ jsx21(
6215
+ CustomToolbarButton,
5900
6216
  {
5901
6217
  title: btn.title,
6218
+ active: isActive,
5902
6219
  onMouseDown: (e) => {
5903
6220
  e.preventDefault();
5904
6221
  onCommand(btn.cmd);
5905
6222
  },
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(
6223
+ children: /* @__PURE__ */ jsx21(
5925
6224
  "svg",
5926
6225
  {
5927
6226
  width: "16",
5928
6227
  height: "16",
5929
6228
  viewBox: "0 0 24 24",
5930
6229
  fill: "none",
5931
- stroke: isActive ? "#FFFFFF" : "#1C1917",
6230
+ stroke: "currentColor",
5932
6231
  strokeWidth: "2.5",
5933
6232
  strokeLinecap: "round",
5934
6233
  strokeLinejoin: "round",
5935
- style: isActive && gi > 0 ? { filter: "drop-shadow(0 0 0.5px #fff)" } : void 0,
5936
- dangerouslySetInnerHTML: { __html: ICONS[btn.cmd] }
6234
+ style: isActive && gi > 0 ? { filter: "drop-shadow(0 0 0.5px currentColor)" } : void 0,
6235
+ dangerouslySetInnerHTML: { __html: ICONS[btn.cmd] },
6236
+ "aria-hidden": true
5937
6237
  }
5938
6238
  )
5939
6239
  },
@@ -5941,8 +6241,8 @@ function FloatingToolbar({
5941
6241
  );
5942
6242
  })
5943
6243
  ] }, gi)),
5944
- showEditLink ? /* @__PURE__ */ jsx16(
5945
- "button",
6244
+ showEditLink ? /* @__PURE__ */ jsx21(
6245
+ CustomToolbarButton,
5946
6246
  {
5947
6247
  type: "button",
5948
6248
  title: "Edit link",
@@ -5955,28 +6255,10 @@ function FloatingToolbar({
5955
6255
  e.preventDefault();
5956
6256
  e.stopPropagation();
5957
6257
  },
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
6258
+ children: /* @__PURE__ */ jsx21(Link2, { className: "size-4 shrink-0", "aria-hidden": true })
5977
6259
  }
5978
6260
  ) : null
5979
- ]
6261
+ ] })
5980
6262
  }
5981
6263
  );
5982
6264
  }
@@ -5990,7 +6272,7 @@ function StateToggle({
5990
6272
  states,
5991
6273
  onStateChange
5992
6274
  }) {
5993
- return /* @__PURE__ */ jsx16(
6275
+ return /* @__PURE__ */ jsx21(
5994
6276
  ToggleGroup,
5995
6277
  {
5996
6278
  "data-ohw-state-toggle": "",
@@ -6004,7 +6286,7 @@ function StateToggle({
6004
6286
  left: rect.right - 8,
6005
6287
  transform: "translateX(-100%)"
6006
6288
  },
6007
- children: states.map((state) => /* @__PURE__ */ jsx16(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
6289
+ children: states.map((state) => /* @__PURE__ */ jsx21(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
6008
6290
  }
6009
6291
  );
6010
6292
  }
@@ -6092,6 +6374,10 @@ function OhhwellsBridge() {
6092
6374
  });
6093
6375
  const deselectRef = useRef3(() => {
6094
6376
  });
6377
+ const reselectNavigationItemRef = useRef3(() => {
6378
+ });
6379
+ const commitNavigationTextEditRef = useRef3(() => {
6380
+ });
6095
6381
  const refreshActiveCommandsRef = useRef3(() => {
6096
6382
  });
6097
6383
  const postToParentRef = useRef3(postToParent);
@@ -6102,11 +6388,18 @@ function OhhwellsBridge() {
6102
6388
  const [toolbarVariant, setToolbarVariant] = useState5("none");
6103
6389
  const toolbarVariantRef = useRef3("none");
6104
6390
  toolbarVariantRef.current = toolbarVariant;
6391
+ const [reorderHrefKey, setReorderHrefKey] = useState5(null);
6392
+ const [reorderDragDisabled, setReorderDragDisabled] = useState5(false);
6105
6393
  const [toggleState, setToggleState] = useState5(null);
6106
6394
  const [maxBadge, setMaxBadge] = useState5(null);
6107
6395
  const [activeCommands, setActiveCommands] = useState5(/* @__PURE__ */ new Set());
6108
6396
  const [sectionGap, setSectionGap] = useState5(null);
6109
6397
  const [toolbarShowEditLink, setToolbarShowEditLink] = useState5(false);
6398
+ const hoveredItemElRef = useRef3(null);
6399
+ const [hoveredItemRect, setHoveredItemRect] = useState5(null);
6400
+ const siblingHintElRef = useRef3(null);
6401
+ const [siblingHintRect, setSiblingHintRect] = useState5(null);
6402
+ const [isItemDragging, setIsItemDragging] = useState5(false);
6110
6403
  const [linkPopover, setLinkPopover] = useState5(null);
6111
6404
  const [sitePages, setSitePages] = useState5([]);
6112
6405
  const [sectionsByPath, setSectionsByPath] = useState5({});
@@ -6208,7 +6501,7 @@ function OhhwellsBridge() {
6208
6501
  useEffect3(() => {
6209
6502
  const update = () => {
6210
6503
  const el = activeElRef.current ?? selectedElRef.current;
6211
- if (el) setToolbarRect(el.getBoundingClientRect());
6504
+ if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
6212
6505
  setToggleState((prev) => {
6213
6506
  if (!prev || !activeStateElRef.current) return prev;
6214
6507
  return { ...prev, rect: activeStateElRef.current.getBoundingClientRect() };
@@ -6275,6 +6568,8 @@ function OhhwellsBridge() {
6275
6568
  }
6276
6569
  el.removeAttribute("contenteditable");
6277
6570
  activeElRef.current = null;
6571
+ setReorderHrefKey(null);
6572
+ setReorderDragDisabled(false);
6278
6573
  if (!selectedElRef.current) {
6279
6574
  setToolbarRect(null);
6280
6575
  setToolbarVariant("none");
@@ -6286,16 +6581,82 @@ function OhhwellsBridge() {
6286
6581
  }, [postToParent]);
6287
6582
  const deselect = useCallback2(() => {
6288
6583
  selectedElRef.current = null;
6584
+ setReorderHrefKey(null);
6585
+ setReorderDragDisabled(false);
6586
+ siblingHintElRef.current = null;
6587
+ setSiblingHintRect(null);
6588
+ setIsItemDragging(false);
6289
6589
  if (!activeElRef.current) {
6290
6590
  setToolbarRect(null);
6291
6591
  setToolbarVariant("none");
6292
6592
  }
6293
6593
  }, []);
6594
+ const reselectNavigationItem = useCallback2((navAnchor) => {
6595
+ selectedElRef.current = navAnchor;
6596
+ const { key, disabled } = getNavigationItemReorderState(navAnchor);
6597
+ setReorderHrefKey(key);
6598
+ setReorderDragDisabled(disabled);
6599
+ setToolbarVariant("link-action");
6600
+ setToolbarRect(navAnchor.getBoundingClientRect());
6601
+ setToolbarShowEditLink(false);
6602
+ setActiveCommands(/* @__PURE__ */ new Set());
6603
+ }, []);
6604
+ const commitNavigationTextEdit = useCallback2((navAnchor) => {
6605
+ const el = activeElRef.current;
6606
+ if (!el) return;
6607
+ const key = el.dataset.ohwKey;
6608
+ if (key) {
6609
+ const timer = autoSaveTimers.current.get(key);
6610
+ if (timer !== void 0) {
6611
+ clearTimeout(timer);
6612
+ autoSaveTimers.current.delete(key);
6613
+ }
6614
+ const html = sanitizeHtml(el.innerHTML);
6615
+ const original = originalContentRef.current ?? "";
6616
+ if (html !== sanitizeHtml(original)) {
6617
+ postToParent({ type: "ow:change", nodes: [{ key, text: html }] });
6618
+ const h = document.documentElement.scrollHeight;
6619
+ if (h > 50) postToParent({ type: "ow:height", height: h });
6620
+ }
6621
+ }
6622
+ el.removeAttribute("contenteditable");
6623
+ activeElRef.current = null;
6624
+ setMaxBadge(null);
6625
+ setActiveCommands(/* @__PURE__ */ new Set());
6626
+ setToolbarShowEditLink(false);
6627
+ postToParent({ type: "ow:exit-edit" });
6628
+ reselectNavigationItem(navAnchor);
6629
+ }, [postToParent, reselectNavigationItem]);
6630
+ const handleAddNavigationItem = useCallback2(() => {
6631
+ const selected = selectedElRef.current;
6632
+ if (!selected) return;
6633
+ const target = getNavigationItemAddHintTarget(selected);
6634
+ siblingHintElRef.current = target;
6635
+ setSiblingHintRect(target.getBoundingClientRect());
6636
+ }, []);
6637
+ const handleItemDragStart = useCallback2(() => {
6638
+ siblingHintElRef.current = null;
6639
+ setSiblingHintRect(null);
6640
+ setIsItemDragging(true);
6641
+ }, []);
6642
+ const handleItemDragEnd = useCallback2(() => {
6643
+ setIsItemDragging(false);
6644
+ }, []);
6645
+ reselectNavigationItemRef.current = reselectNavigationItem;
6646
+ commitNavigationTextEditRef.current = commitNavigationTextEdit;
6294
6647
  const select = useCallback2((anchor) => {
6295
- if (!isNavbarButton(anchor)) return;
6648
+ if (!isNavigationItem(anchor)) return;
6296
6649
  if (activeElRef.current) deactivate();
6297
6650
  selectedElRef.current = anchor;
6298
6651
  clearHrefKeyHover(anchor);
6652
+ setHoveredItemRect(null);
6653
+ hoveredItemElRef.current = null;
6654
+ siblingHintElRef.current = null;
6655
+ setSiblingHintRect(null);
6656
+ setIsItemDragging(false);
6657
+ const { key, disabled } = getNavigationItemReorderState(anchor);
6658
+ setReorderHrefKey(key);
6659
+ setReorderDragDisabled(disabled);
6299
6660
  setToolbarVariant("link-action");
6300
6661
  setToolbarRect(anchor.getBoundingClientRect());
6301
6662
  setToolbarShowEditLink(false);
@@ -6310,13 +6671,26 @@ function OhhwellsBridge() {
6310
6671
  postToParentRef.current({ type: "ow:image-unhover" });
6311
6672
  }
6312
6673
  setToolbarVariant("rich-text");
6674
+ siblingHintElRef.current = null;
6675
+ setSiblingHintRect(null);
6676
+ setIsItemDragging(false);
6313
6677
  el.setAttribute("contenteditable", "true");
6314
6678
  el.removeAttribute("data-ohw-hovered");
6679
+ el.closest("[data-ohw-href-key]")?.removeAttribute("data-ohw-hovered");
6315
6680
  activeElRef.current = el;
6316
6681
  originalContentRef.current = el.innerHTML;
6317
6682
  el.focus();
6318
- setToolbarRect(el.getBoundingClientRect());
6319
6683
  setToolbarShowEditLink(Boolean(getHrefKeyFromElement(el)));
6684
+ const navAnchor = getNavigationItemAnchor(el);
6685
+ if (navAnchor) {
6686
+ setReorderHrefKey(null);
6687
+ setReorderDragDisabled(false);
6688
+ } else {
6689
+ const { key: reorderKey, disabled: reorderDisabled } = getReorderHandleState(el);
6690
+ setReorderHrefKey(reorderKey);
6691
+ setReorderDragDisabled(reorderDisabled);
6692
+ }
6693
+ setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
6320
6694
  postToParent({ type: "ow:enter-edit", key: el.dataset.ohwKey });
6321
6695
  requestAnimationFrame(() => refreshActiveCommandsRef.current());
6322
6696
  }, [deactivate, postToParent]);
@@ -6508,18 +6882,25 @@ function OhhwellsBridge() {
6508
6882
  [data-ohw-editable="image"], [data-ohw-editable="image"] *,
6509
6883
  [data-ohw-editable="bg-image"], [data-ohw-editable="bg-image"] * { cursor: pointer !important; }
6510
6884
  [data-ohw-editable="link"], [data-ohw-editable="link"] * { cursor: pointer !important; }
6511
- [data-ohw-hovered]:not([contenteditable]) {
6512
- outline: 2px dashed ${PRIMARY} !important;
6885
+ [data-ohw-hovered]:not([contenteditable]):not([data-ohw-href-key]) {
6886
+ outline: 2px dashed ${PRIMARY2} !important;
6513
6887
  outline-offset: 4px;
6514
6888
  border-radius: 2px;
6515
6889
  }
6890
+ [data-ohw-href-key] [data-ohw-hovered],
6891
+ [data-ohw-href-key][data-ohw-hovered],
6892
+ nav [data-ohw-href-key] [data-ohw-hovered],
6893
+ footer [data-ohw-href-key] [data-ohw-hovered] {
6894
+ outline: none !important;
6895
+ outline-offset: 0 !important;
6896
+ }
6516
6897
  [data-ohw-editable][contenteditable] {
6517
6898
  outline: none !important;
6518
- caret-color: ${PRIMARY};
6899
+ caret-color: ${PRIMARY2};
6519
6900
  cursor: text !important;
6520
6901
  }
6521
6902
  [data-ohw-editable][contenteditable]::selection,
6522
- [data-ohw-editable][contenteditable] *::selection { background: ${PRIMARY}59 !important; }
6903
+ [data-ohw-editable][contenteditable] *::selection { background: ${PRIMARY2}59 !important; }
6523
6904
  [data-ohw-editable-state], [data-ohw-editable-state] * { pointer-events: none !important; }
6524
6905
  [data-ohw-editable-state][data-ohw-active-state] [data-ohw-editable] { pointer-events: auto !important; }
6525
6906
  [data-ohw-editable-state][data-ohw-active-state][data-ohw-editable] { pointer-events: auto !important; }
@@ -6531,7 +6912,7 @@ function OhhwellsBridge() {
6531
6912
  stateViews.textContent = `
6532
6913
  [data-ohw-state-view]:not([data-ohw-state-view="default"]) { display: none; }
6533
6914
  [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; }
6915
+ [data-ohw-state-hovered] { outline: 2px dashed ${PRIMARY2} !important; outline-offset: 4px; border-radius: 2px; }
6535
6916
  [data-ohw-state-hovered]:has([data-ohw-hovered]) { outline: none !important; }
6536
6917
  `;
6537
6918
  document.head.appendChild(base);
@@ -6546,6 +6927,11 @@ function OhhwellsBridge() {
6546
6927
  if (target.closest("[data-ohw-state-toggle]")) return;
6547
6928
  if (target.closest("[data-ohw-max-badge]")) return;
6548
6929
  if (isInsideLinkEditor(target)) return;
6930
+ if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
6931
+ e.preventDefault();
6932
+ e.stopPropagation();
6933
+ return;
6934
+ }
6549
6935
  const editable = target.closest("[data-ohw-editable]");
6550
6936
  if (editable) {
6551
6937
  if (editable.dataset.ohwEditable === "link") {
@@ -6567,15 +6953,15 @@ function OhhwellsBridge() {
6567
6953
  return;
6568
6954
  }
6569
6955
  const hrefCtx = getHrefKeyFromElement(editable);
6570
- if (hrefCtx && isNavbarButton(hrefCtx.anchor)) {
6956
+ const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
6957
+ if (navAnchor) {
6571
6958
  e.preventDefault();
6572
6959
  e.stopPropagation();
6573
- const { anchor: anchor2 } = hrefCtx;
6574
- if (selectedElRef.current === anchor2) {
6960
+ if (selectedElRef.current === navAnchor) {
6575
6961
  activateRef.current(editable);
6576
6962
  return;
6577
6963
  }
6578
- selectRef.current(anchor2);
6964
+ selectRef.current(navAnchor);
6579
6965
  return;
6580
6966
  }
6581
6967
  e.preventDefault();
@@ -6583,8 +6969,8 @@ function OhhwellsBridge() {
6583
6969
  activateRef.current(editable);
6584
6970
  return;
6585
6971
  }
6586
- const hrefAnchor = target.closest("[data-ohw-href-key]");
6587
- if (hrefAnchor && isNavbarButton(hrefAnchor)) {
6972
+ const hrefAnchor = getNavigationItemAnchor(target);
6973
+ if (hrefAnchor) {
6588
6974
  e.preventDefault();
6589
6975
  e.stopPropagation();
6590
6976
  if (selectedElRef.current === hrefAnchor) return;
@@ -6617,19 +7003,58 @@ function OhhwellsBridge() {
6617
7003
  deactivateRef.current();
6618
7004
  };
6619
7005
  const handleMouseOver = (e) => {
6620
- const editable = e.target.closest("[data-ohw-editable]");
7006
+ const target = e.target;
7007
+ const navAnchor = getNavigationItemAnchor(target);
7008
+ if (navAnchor) {
7009
+ const selected2 = selectedElRef.current;
7010
+ if (selected2 === navAnchor || selected2?.contains(navAnchor)) return;
7011
+ clearHrefKeyHover(navAnchor);
7012
+ hoveredItemElRef.current = navAnchor;
7013
+ setHoveredItemRect(navAnchor.getBoundingClientRect());
7014
+ return;
7015
+ }
7016
+ const editable = target.closest("[data-ohw-editable]");
6621
7017
  if (!editable) return;
6622
7018
  const selected = selectedElRef.current;
6623
7019
  if (selected && (selected === editable || selected.contains(editable))) return;
6624
7020
  if (editable.dataset.ohwEditable !== "image" && editable.dataset.ohwEditable !== "bg-image" && !editable.hasAttribute("contenteditable")) {
6625
- editable.setAttribute("data-ohw-hovered", "");
7021
+ const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
7022
+ if (hoverTarget.hasAttribute("data-ohw-href-key")) {
7023
+ clearHrefKeyHover(hoverTarget);
7024
+ hoveredItemElRef.current = hoverTarget;
7025
+ setHoveredItemRect(hoverTarget.getBoundingClientRect());
7026
+ } else if (!isInsideNavigationItem(editable)) {
7027
+ hoverTarget.setAttribute("data-ohw-hovered", "");
7028
+ }
6626
7029
  }
6627
7030
  };
6628
7031
  const handleMouseOut = (e) => {
6629
- const editable = e.target.closest("[data-ohw-editable]");
7032
+ const target = e.target;
7033
+ const navAnchor = getNavigationItemAnchor(target);
7034
+ if (navAnchor) {
7035
+ const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
7036
+ if (related2?.closest("[data-ohw-drag-handle-container], [data-ohw-item-interaction]")) return;
7037
+ if (related2 && navAnchor.contains(related2)) return;
7038
+ if (hoveredItemElRef.current === navAnchor) {
7039
+ hoveredItemElRef.current = null;
7040
+ setHoveredItemRect(null);
7041
+ }
7042
+ return;
7043
+ }
7044
+ const editable = target.closest("[data-ohw-editable]");
6630
7045
  if (!editable) return;
7046
+ const related = e.relatedTarget instanceof Element ? e.relatedTarget : null;
7047
+ if (related?.closest("[data-ohw-drag-handle-container], [data-ohw-item-interaction]")) return;
6631
7048
  if (editable.dataset.ohwEditable !== "image" && editable.dataset.ohwEditable !== "bg-image") {
6632
- editable.removeAttribute("data-ohw-hovered");
7049
+ const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
7050
+ if (hoverTarget.hasAttribute("data-ohw-href-key")) {
7051
+ if (!related?.closest("[data-ohw-href-key]")) {
7052
+ hoveredItemElRef.current = null;
7053
+ setHoveredItemRect(null);
7054
+ }
7055
+ } else {
7056
+ hoverTarget.removeAttribute("data-ohw-hovered");
7057
+ }
6633
7058
  }
6634
7059
  };
6635
7060
  const toProbeCoords = (clientX, clientY, fromParentViewport) => {
@@ -6744,11 +7169,20 @@ function OhhwellsBridge() {
6744
7169
  return;
6745
7170
  }
6746
7171
  }
7172
+ if (activeElRef.current) {
7173
+ if (hoveredImageRef.current) {
7174
+ hoveredImageRef.current = null;
7175
+ hoveredImageHasTextOverlapRef.current = false;
7176
+ resumeAnimTracks();
7177
+ postToParentRef.current({ type: "ow:image-unhover" });
7178
+ }
7179
+ return;
7180
+ }
6747
7181
  const imgEl = findImageAtPoint(clientX, clientY, fromParentViewport);
6748
7182
  if (imgEl) {
6749
7183
  const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
6750
7184
  const topEl = document.elementFromPoint(x, y);
6751
- if (topEl?.closest("[data-ohw-toolbar]")) {
7185
+ if (topEl?.closest('[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
6752
7186
  if (hoveredImageRef.current) {
6753
7187
  hoveredImageRef.current = null;
6754
7188
  resumeAnimTracks();
@@ -6796,7 +7230,9 @@ function OhhwellsBridge() {
6796
7230
  postImageHover(imgEl, isDragOver, true);
6797
7231
  }
6798
7232
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
6799
- textEditable.setAttribute("data-ohw-hovered", "");
7233
+ if (textEditable && !isInsideNavigationItem(textEditable)) {
7234
+ textEditable.setAttribute("data-ohw-hovered", "");
7235
+ }
6800
7236
  return;
6801
7237
  }
6802
7238
  if (hoveredImageRef.current) {
@@ -6806,7 +7242,9 @@ function OhhwellsBridge() {
6806
7242
  postToParentRef.current({ type: "ow:image-unhover" });
6807
7243
  }
6808
7244
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
6809
- textEditable.setAttribute("data-ohw-hovered", "");
7245
+ if (textEditable && !isInsideNavigationItem(textEditable)) {
7246
+ textEditable.setAttribute("data-ohw-hovered", "");
7247
+ }
6810
7248
  return;
6811
7249
  }
6812
7250
  if (hoveredGapRef.current) {
@@ -6850,7 +7288,24 @@ function OhhwellsBridge() {
6850
7288
  return x >= er.left && x <= er.right && y >= er.top && y <= er.bottom;
6851
7289
  });
6852
7290
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
6853
- if (textEl && !textEl.hasAttribute("contenteditable")) textEl.setAttribute("data-ohw-hovered", "");
7291
+ if (textEl && !textEl.hasAttribute("contenteditable")) {
7292
+ const navAnchor = getNavigationItemAnchor(textEl);
7293
+ if (navAnchor) {
7294
+ const selected = selectedElRef.current;
7295
+ if (selected !== navAnchor && !selected?.contains(navAnchor)) {
7296
+ clearHrefKeyHover(navAnchor);
7297
+ hoveredItemElRef.current = navAnchor;
7298
+ setHoveredItemRect(navAnchor.getBoundingClientRect());
7299
+ }
7300
+ } else {
7301
+ hoveredItemElRef.current = null;
7302
+ setHoveredItemRect(null);
7303
+ textEl.setAttribute("data-ohw-hovered", "");
7304
+ }
7305
+ } else {
7306
+ hoveredItemElRef.current = null;
7307
+ setHoveredItemRect(null);
7308
+ }
6854
7309
  }
6855
7310
  };
6856
7311
  const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
@@ -7041,7 +7496,7 @@ function OhhwellsBridge() {
7041
7496
  const el = e.target;
7042
7497
  const key = el.dataset.ohwKey;
7043
7498
  if (!key) return;
7044
- if (el === activeElRef.current) setToolbarRect(el.getBoundingClientRect());
7499
+ if (el === activeElRef.current) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
7045
7500
  const maxLen = el.dataset.ohwMaxLength ? parseInt(el.dataset.ohwMaxLength, 10) : null;
7046
7501
  if (maxLen) {
7047
7502
  const current = el.innerText.replace(/\n$/, "").length;
@@ -7128,6 +7583,33 @@ function OhhwellsBridge() {
7128
7583
  deselectRef.current();
7129
7584
  return;
7130
7585
  }
7586
+ if (e.key === "Escape" && activeElRef.current) {
7587
+ const hrefCtx = getHrefKeyFromElement(activeElRef.current);
7588
+ const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
7589
+ if (navAnchor) {
7590
+ e.preventDefault();
7591
+ const el2 = activeElRef.current;
7592
+ if (originalContentRef.current !== null) {
7593
+ el2.innerHTML = originalContentRef.current;
7594
+ }
7595
+ el2.removeAttribute("contenteditable");
7596
+ activeElRef.current = null;
7597
+ setMaxBadge(null);
7598
+ setActiveCommands(/* @__PURE__ */ new Set());
7599
+ setToolbarShowEditLink(false);
7600
+ postToParentRef.current({ type: "ow:exit-edit" });
7601
+ reselectNavigationItemRef.current(navAnchor);
7602
+ return;
7603
+ }
7604
+ }
7605
+ if (e.key === "Enter" && !e.shiftKey && activeElRef.current) {
7606
+ const navAnchor = getNavigationItemAnchor(activeElRef.current);
7607
+ if (navAnchor) {
7608
+ e.preventDefault();
7609
+ commitNavigationTextEditRef.current(navAnchor);
7610
+ return;
7611
+ }
7612
+ }
7131
7613
  if (e.key !== "Escape") return;
7132
7614
  const el = activeElRef.current;
7133
7615
  if (el && originalContentRef.current !== null) {
@@ -7143,7 +7625,8 @@ function OhhwellsBridge() {
7143
7625
  const handleScroll = () => {
7144
7626
  const focusEl = activeElRef.current ?? selectedElRef.current;
7145
7627
  if (focusEl) {
7146
- const r2 = focusEl.getBoundingClientRect();
7628
+ const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : focusEl;
7629
+ const r2 = measureEl.getBoundingClientRect();
7147
7630
  applyToolbarPos(r2);
7148
7631
  setToolbarRect(r2);
7149
7632
  setMaxBadge((prev) => prev && activeElRef.current ? { ...prev, rect: r2 } : prev);
@@ -7152,6 +7635,12 @@ function OhhwellsBridge() {
7152
7635
  const rect = activeStateElRef.current.getBoundingClientRect();
7153
7636
  setToggleState((prev) => prev ? { ...prev, rect } : null);
7154
7637
  }
7638
+ if (hoveredItemElRef.current) {
7639
+ setHoveredItemRect(hoveredItemElRef.current.getBoundingClientRect());
7640
+ }
7641
+ if (siblingHintElRef.current) {
7642
+ setSiblingHintRect(siblingHintElRef.current.getBoundingClientRect());
7643
+ }
7155
7644
  if (hoveredImageRef.current) {
7156
7645
  const el = hoveredImageRef.current;
7157
7646
  const r2 = el.getBoundingClientRect();
@@ -7271,7 +7760,7 @@ function OhhwellsBridge() {
7271
7760
  };
7272
7761
  const applyToolbarPos = (rect) => {
7273
7762
  const ps = parentScrollRef.current;
7274
- const approxW = toolbarVariantRef.current === "link-action" ? 120 : 330;
7763
+ const approxW = 330;
7275
7764
  if (toolbarElRef.current) {
7276
7765
  const { top, left, transform } = calcToolbarPos(rect, ps, approxW);
7277
7766
  toolbarElRef.current.style.top = `${top}px`;
@@ -7282,6 +7771,8 @@ function OhhwellsBridge() {
7282
7771
  const GAP = 6;
7283
7772
  glowElRef.current.style.top = `${rect.top - GAP}px`;
7284
7773
  glowElRef.current.style.left = `${rect.left - GAP}px`;
7774
+ glowElRef.current.style.width = `${rect.width + GAP * 2}px`;
7775
+ glowElRef.current.style.height = `${rect.height + GAP * 2}px`;
7285
7776
  }
7286
7777
  };
7287
7778
  const handleParentScroll = (e) => {
@@ -7292,7 +7783,10 @@ function OhhwellsBridge() {
7292
7783
  applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
7293
7784
  }
7294
7785
  const focusEl = activeElRef.current ?? selectedElRef.current;
7295
- if (focusEl) applyToolbarPos(focusEl.getBoundingClientRect());
7786
+ if (focusEl) {
7787
+ const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : focusEl;
7788
+ applyToolbarPos(measureEl.getBoundingClientRect());
7789
+ }
7296
7790
  };
7297
7791
  const handleClickAt = (e) => {
7298
7792
  if (e.data?.type !== "ow:click-at") return;
@@ -7450,7 +7944,7 @@ function OhhwellsBridge() {
7450
7944
  const handleCommand = useCallback2((cmd) => {
7451
7945
  document.execCommand(cmd, false);
7452
7946
  activeElRef.current?.focus();
7453
- if (activeElRef.current) setToolbarRect(activeElRef.current.getBoundingClientRect());
7947
+ if (activeElRef.current) setToolbarRect(getEditMeasureEl(activeElRef.current).getBoundingClientRect());
7454
7948
  refreshActiveCommandsRef.current();
7455
7949
  }, []);
7456
7950
  const handleStateChange = useCallback2((state) => {
@@ -7503,37 +7997,55 @@ function OhhwellsBridge() {
7503
7997
  const currentSections = sectionsByPath[pathname] ?? [];
7504
7998
  linkPopoverOpenRef.current = linkPopover !== null;
7505
7999
  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,
8000
+ /* @__PURE__ */ jsxs11(Fragment3, { children: [
8001
+ /* @__PURE__ */ jsx21("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
8002
+ siblingHintRect && !isItemDragging && /* @__PURE__ */ jsx21(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
8003
+ hoveredItemRect && !siblingHintRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx21(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
8004
+ toolbarRect && toolbarVariant === "link-action" && /* @__PURE__ */ jsx21(
8005
+ ItemInteractionLayer,
8006
+ {
8007
+ rect: toolbarRect,
8008
+ elRef: glowElRef,
8009
+ state: isItemDragging ? "dragging" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
8010
+ showHandle: Boolean(reorderHrefKey),
8011
+ dragDisabled: reorderDragDisabled,
8012
+ dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
8013
+ onDragHandleDragStart: handleItemDragStart,
8014
+ onDragHandleDragEnd: handleItemDragEnd,
8015
+ toolbar: isItemDragging ? void 0 : /* @__PURE__ */ jsx21(
8016
+ ItemActionToolbar,
8017
+ {
8018
+ onEditLink: openLinkPopoverForSelected,
8019
+ onAddItem: handleAddNavigationItem,
8020
+ addItemDisabled: false
8021
+ }
8022
+ )
8023
+ }
8024
+ ),
8025
+ toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ jsxs11(Fragment3, { children: [
8026
+ /* @__PURE__ */ jsx21(
8027
+ EditGlowChrome,
7512
8028
  {
7513
- variant: "rich-text",
7514
8029
  rect: toolbarRect,
7515
- parentScroll: parentScrollRef.current,
7516
- elRef: toolbarElRef,
7517
- onCommand: handleCommand,
7518
- activeCommands,
7519
- showEditLink,
7520
- onEditLink: openLinkPopoverForActive
8030
+ elRef: glowElRef,
8031
+ reorderHrefKey,
8032
+ dragDisabled: reorderDragDisabled
7521
8033
  }
7522
8034
  ),
7523
- toolbarVariant === "link-action" && /* @__PURE__ */ jsx16(
8035
+ /* @__PURE__ */ jsx21(
7524
8036
  FloatingToolbar,
7525
8037
  {
7526
- variant: "link-action",
7527
8038
  rect: toolbarRect,
7528
8039
  parentScroll: parentScrollRef.current,
7529
8040
  elRef: toolbarElRef,
7530
8041
  onCommand: handleCommand,
7531
8042
  activeCommands,
7532
- onEditLink: openLinkPopoverForSelected
8043
+ showEditLink,
8044
+ onEditLink: openLinkPopoverForActive
7533
8045
  }
7534
8046
  )
7535
8047
  ] }),
7536
- maxBadge && /* @__PURE__ */ jsxs9(
8048
+ maxBadge && /* @__PURE__ */ jsxs11(
7537
8049
  "div",
7538
8050
  {
7539
8051
  "data-ohw-max-badge": "",
@@ -7559,7 +8071,7 @@ function OhhwellsBridge() {
7559
8071
  ]
7560
8072
  }
7561
8073
  ),
7562
- toggleState && /* @__PURE__ */ jsx16(
8074
+ toggleState && /* @__PURE__ */ jsx21(
7563
8075
  StateToggle,
7564
8076
  {
7565
8077
  rect: toggleState.rect,
@@ -7568,15 +8080,15 @@ function OhhwellsBridge() {
7568
8080
  onStateChange: handleStateChange
7569
8081
  }
7570
8082
  ),
7571
- sectionGap && /* @__PURE__ */ jsxs9(
8083
+ sectionGap && /* @__PURE__ */ jsxs11(
7572
8084
  "div",
7573
8085
  {
7574
8086
  "data-ohw-section-insert-line": "",
7575
8087
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
7576
8088
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
7577
8089
  children: [
7578
- /* @__PURE__ */ jsx16("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
7579
- /* @__PURE__ */ jsx16(
8090
+ /* @__PURE__ */ jsx21("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
8091
+ /* @__PURE__ */ jsx21(
7580
8092
  Badge,
7581
8093
  {
7582
8094
  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 +8101,11 @@ function OhhwellsBridge() {
7589
8101
  children: "Add Section"
7590
8102
  }
7591
8103
  ),
7592
- /* @__PURE__ */ jsx16("div", { className: "flex-1 bg-primary", style: { height: 3 } })
8104
+ /* @__PURE__ */ jsx21("div", { className: "flex-1 bg-primary", style: { height: 3 } })
7593
8105
  ]
7594
8106
  }
7595
8107
  ),
7596
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx16(
8108
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx21(
7597
8109
  LinkPopover,
7598
8110
  {
7599
8111
  panelRef: linkPopoverPanelRef,
@@ -7614,6 +8126,12 @@ function OhhwellsBridge() {
7614
8126
  ) : null;
7615
8127
  }
7616
8128
  export {
8129
+ CustomToolbar,
8130
+ CustomToolbarButton,
8131
+ CustomToolbarDivider,
8132
+ DragHandle,
8133
+ ItemActionToolbar,
8134
+ ItemInteractionLayer,
7617
8135
  LinkEditorPanel,
7618
8136
  LinkPopover,
7619
8137
  OhhwellsBridge,
@@ -7621,9 +8139,14 @@ export {
7621
8139
  Toggle,
7622
8140
  ToggleGroup,
7623
8141
  ToggleGroupItem,
8142
+ Tooltip,
8143
+ TooltipContent,
8144
+ TooltipProvider,
8145
+ TooltipTrigger,
7624
8146
  buildTarget,
7625
8147
  filterAvailablePages,
7626
8148
  getEditModeInitialState,
8149
+ isEditSessionActive,
7627
8150
  isValidUrl,
7628
8151
  parseTarget,
7629
8152
  toggleVariants,