@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.cjs CHANGED
@@ -31,6 +31,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  // src/index.ts
32
32
  var index_exports = {};
33
33
  __export(index_exports, {
34
+ CustomToolbar: () => CustomToolbar,
35
+ CustomToolbarButton: () => CustomToolbarButton,
36
+ CustomToolbarDivider: () => CustomToolbarDivider,
37
+ DragHandle: () => DragHandle,
38
+ ItemActionToolbar: () => ItemActionToolbar,
39
+ ItemInteractionLayer: () => ItemInteractionLayer,
34
40
  LinkEditorPanel: () => LinkEditorPanel,
35
41
  LinkPopover: () => LinkPopover,
36
42
  OhhwellsBridge: () => OhhwellsBridge,
@@ -38,9 +44,14 @@ __export(index_exports, {
38
44
  Toggle: () => Toggle,
39
45
  ToggleGroup: () => ToggleGroup,
40
46
  ToggleGroupItem: () => ToggleGroupItem,
47
+ Tooltip: () => Tooltip,
48
+ TooltipContent: () => TooltipContent,
49
+ TooltipProvider: () => TooltipProvider,
50
+ TooltipTrigger: () => TooltipTrigger,
41
51
  buildTarget: () => buildTarget,
42
52
  filterAvailablePages: () => filterAvailablePages,
43
53
  getEditModeInitialState: () => getEditModeInitialState,
54
+ isEditSessionActive: () => isEditSessionActive,
44
55
  isValidUrl: () => isValidUrl,
45
56
  parseTarget: () => parseTarget,
46
57
  toggleVariants: () => toggleVariants,
@@ -4250,6 +4261,336 @@ function ToggleGroupItem({
4250
4261
  );
4251
4262
  }
4252
4263
 
4264
+ // src/ui/drag-handle.tsx
4265
+ var React3 = __toESM(require("react"), 1);
4266
+ var import_lucide_react = require("lucide-react");
4267
+ var import_jsx_runtime5 = require("react/jsx-runtime");
4268
+ var DragHandle = React3.forwardRef(
4269
+ ({ className, type = "button", ...props }, ref) => {
4270
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
4271
+ "button",
4272
+ {
4273
+ ref,
4274
+ type,
4275
+ "data-slot": "drag-handle",
4276
+ className: cn(
4277
+ "inline-flex h-7 w-4 shrink-0 items-center justify-center rounded-md transition-all duration-200 max-h-[30px]",
4278
+ "bg-white border border-transparent text-stone-500 shadow-md cursor-grab",
4279
+ "enabled:hover:border enabled:hover:border-stone-200 enabled:hover:text-stone-950",
4280
+ "enabled:active:border enabled:active:border-primary enabled:active:bg-primary-50 enabled:active:text-stone-950 enabled:active:shadow enabled:active:cursor-grabbing",
4281
+ "disabled:cursor-not-allowed disabled:opacity-40 disabled:text-stone-950 disabled:pointer-events-none",
4282
+ className
4283
+ ),
4284
+ ...props,
4285
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react.GripVertical, { className: "size-4 shrink-0", "aria-hidden": "true" })
4286
+ }
4287
+ );
4288
+ }
4289
+ );
4290
+ DragHandle.displayName = "DragHandle";
4291
+
4292
+ // src/ui/custom-toolbar.tsx
4293
+ var React4 = __toESM(require("react"), 1);
4294
+ var import_jsx_runtime6 = require("react/jsx-runtime");
4295
+ var CustomToolbar = React4.forwardRef(({ className, onMouseDown, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4296
+ "div",
4297
+ {
4298
+ ref,
4299
+ "data-ohw-toolbar": "",
4300
+ className: cn(
4301
+ "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)]",
4302
+ className
4303
+ ),
4304
+ onMouseDown: (e) => {
4305
+ e.stopPropagation();
4306
+ onMouseDown?.(e);
4307
+ },
4308
+ ...props
4309
+ }
4310
+ ));
4311
+ CustomToolbar.displayName = "CustomToolbar";
4312
+ function CustomToolbarDivider({ className, ...props }) {
4313
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4314
+ "span",
4315
+ {
4316
+ "aria-hidden": true,
4317
+ className: cn("block h-6 w-px shrink-0 bg-border", className),
4318
+ ...props
4319
+ }
4320
+ );
4321
+ }
4322
+ var CustomToolbarButton = React4.forwardRef(
4323
+ ({ className, active = false, type = "button", ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4324
+ "button",
4325
+ {
4326
+ ref,
4327
+ type,
4328
+ className: cn(
4329
+ "inline-flex shrink-0 items-center justify-center rounded p-1.5 transition-colors",
4330
+ active ? "bg-primary text-primary-foreground" : "bg-transparent text-foreground hover:bg-muted disabled:cursor-not-allowed disabled:text-muted-foreground disabled:opacity-60",
4331
+ className
4332
+ ),
4333
+ ...props
4334
+ }
4335
+ )
4336
+ );
4337
+ CustomToolbarButton.displayName = "CustomToolbarButton";
4338
+
4339
+ // src/ui/item-action-toolbar.tsx
4340
+ var import_lucide_react2 = require("lucide-react");
4341
+
4342
+ // src/ui/tooltip.tsx
4343
+ var import_radix_ui3 = require("radix-ui");
4344
+ var import_jsx_runtime7 = require("react/jsx-runtime");
4345
+ function TooltipProvider({
4346
+ delayDuration = 0,
4347
+ ...props
4348
+ }) {
4349
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui3.Tooltip.Provider, { "data-slot": "tooltip-provider", delayDuration, ...props });
4350
+ }
4351
+ function Tooltip({ ...props }) {
4352
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui3.Tooltip.Root, { "data-slot": "tooltip", ...props });
4353
+ }
4354
+ function TooltipTrigger({ ...props }) {
4355
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui3.Tooltip.Trigger, { "data-slot": "tooltip-trigger", ...props });
4356
+ }
4357
+ var arrowClassBySide = {
4358
+ top: "before:bottom-0 before:left-1/2 before:-translate-x-1/2 before:translate-y-1/2",
4359
+ bottom: "before:top-0 before:left-1/2 before:-translate-x-1/2 before:-translate-y-1/2",
4360
+ left: "before:right-0 before:top-1/2 before:-translate-y-1/2 before:translate-x-1/2",
4361
+ right: "before:left-0 before:top-1/2 before:-translate-y-1/2 before:-translate-x-1/2"
4362
+ };
4363
+ function TooltipContent({
4364
+ className,
4365
+ sideOffset = 6,
4366
+ side = "bottom",
4367
+ children,
4368
+ ...props
4369
+ }) {
4370
+ const resolvedSide = side ?? "bottom";
4371
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui3.Tooltip.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
4372
+ import_radix_ui3.Tooltip.Content,
4373
+ {
4374
+ "data-slot": "tooltip-content",
4375
+ side,
4376
+ sideOffset,
4377
+ className: cn(
4378
+ "relative z-[2147483647] w-fit max-w-xs rounded-md bg-foreground px-3 py-1.5 text-xs text-background shadow-md",
4379
+ 'before:pointer-events-none before:absolute before:size-2 before:rotate-45 before:bg-foreground before:content-[""]',
4380
+ arrowClassBySide[resolvedSide],
4381
+ "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",
4382
+ "data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2",
4383
+ "data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2",
4384
+ className
4385
+ ),
4386
+ ...props,
4387
+ children
4388
+ }
4389
+ ) });
4390
+ }
4391
+
4392
+ // src/ui/item-action-toolbar.tsx
4393
+ var import_jsx_runtime8 = require("react/jsx-runtime");
4394
+ function ToolbarActionTooltip({
4395
+ label,
4396
+ side = "bottom",
4397
+ disabled = false,
4398
+ buttonProps,
4399
+ children
4400
+ }) {
4401
+ const button = /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CustomToolbarButton, { type: "button", "aria-label": label, disabled, ...buttonProps, children });
4402
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Tooltip, { children: [
4403
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "inline-flex", children: button }) : button }),
4404
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TooltipContent, { side, children: label })
4405
+ ] });
4406
+ }
4407
+ function ItemActionToolbar({
4408
+ onEditLink,
4409
+ onAddItem,
4410
+ onMore,
4411
+ addItemDisabled = true,
4412
+ moreDisabled = true,
4413
+ tooltipSide = "bottom"
4414
+ }) {
4415
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(CustomToolbar, { children: [
4416
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4417
+ ToolbarActionTooltip,
4418
+ {
4419
+ label: "Add link",
4420
+ side: tooltipSide,
4421
+ buttonProps: {
4422
+ onMouseDown: (e) => {
4423
+ e.preventDefault();
4424
+ e.stopPropagation();
4425
+ onEditLink?.();
4426
+ },
4427
+ onClick: (e) => {
4428
+ e.preventDefault();
4429
+ e.stopPropagation();
4430
+ }
4431
+ },
4432
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react2.Link, { className: "size-4 shrink-0", "aria-hidden": true })
4433
+ }
4434
+ ),
4435
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CustomToolbarDivider, {}),
4436
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4437
+ ToolbarActionTooltip,
4438
+ {
4439
+ label: "Add item",
4440
+ side: tooltipSide,
4441
+ disabled: addItemDisabled,
4442
+ buttonProps: {
4443
+ onMouseDown: (e) => {
4444
+ if (addItemDisabled) return;
4445
+ e.preventDefault();
4446
+ e.stopPropagation();
4447
+ onAddItem?.();
4448
+ }
4449
+ },
4450
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react2.Plus, { className: "size-4 shrink-0", "aria-hidden": true })
4451
+ }
4452
+ ),
4453
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CustomToolbarDivider, {}),
4454
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
4455
+ ToolbarActionTooltip,
4456
+ {
4457
+ label: "More",
4458
+ side: tooltipSide,
4459
+ disabled: moreDisabled,
4460
+ buttonProps: {
4461
+ onMouseDown: (e) => {
4462
+ if (moreDisabled) return;
4463
+ e.preventDefault();
4464
+ e.stopPropagation();
4465
+ onMore?.();
4466
+ }
4467
+ },
4468
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react2.MoreHorizontal, { className: "size-4 shrink-0", "aria-hidden": true })
4469
+ }
4470
+ )
4471
+ ] }) });
4472
+ }
4473
+
4474
+ // src/ui/item-interaction-layer.tsx
4475
+ var import_jsx_runtime9 = require("react/jsx-runtime");
4476
+ var PRIMARY = "var(--ohw-primary, #0885FE)";
4477
+ var FOCUS_RING = "0 0 0 4px rgba(8, 133, 254, 0.12)";
4478
+ var DRAG_SHADOW = "0px 4px 6px -1px rgba(0, 0, 0, 0.1), 0px 2px 4px -2px rgba(0, 0, 0, 0.1)";
4479
+ function getChromeStyle(state) {
4480
+ switch (state) {
4481
+ case "hover":
4482
+ return {
4483
+ border: `1.5px dashed ${PRIMARY}`,
4484
+ boxShadow: "none"
4485
+ };
4486
+ case "sibling-hint":
4487
+ return {
4488
+ border: `1.5px dashed color-mix(in srgb, ${PRIMARY} 30%, transparent)`,
4489
+ boxShadow: "none"
4490
+ };
4491
+ case "active-top":
4492
+ case "active-bottom":
4493
+ return {
4494
+ border: `2px solid ${PRIMARY}`,
4495
+ boxShadow: FOCUS_RING
4496
+ };
4497
+ case "dragging":
4498
+ return {
4499
+ border: `2px solid ${PRIMARY}`,
4500
+ boxShadow: DRAG_SHADOW
4501
+ };
4502
+ default:
4503
+ return {};
4504
+ }
4505
+ }
4506
+ function ItemInteractionLayer({
4507
+ rect,
4508
+ state,
4509
+ elRef,
4510
+ toolbar,
4511
+ showHandle = false,
4512
+ dragDisabled = false,
4513
+ dragHandleLabel = "Reorder item",
4514
+ onDragHandleDragStart,
4515
+ onDragHandleDragEnd,
4516
+ chromeGap = 6,
4517
+ className
4518
+ }) {
4519
+ if (state === "default") return null;
4520
+ const isActive = state === "active-top" || state === "active-bottom";
4521
+ const isDragging = state === "dragging";
4522
+ const showToolbar = isActive && toolbar;
4523
+ const showDragHandle = isActive && showHandle && !isDragging;
4524
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
4525
+ "div",
4526
+ {
4527
+ ref: elRef,
4528
+ "data-ohw-item-interaction": "",
4529
+ "data-ohw-item-interaction-state": state,
4530
+ className: cn("pointer-events-none", className),
4531
+ style: {
4532
+ position: "fixed",
4533
+ top: rect.top - chromeGap,
4534
+ left: rect.left - chromeGap,
4535
+ width: rect.width + chromeGap * 2,
4536
+ height: rect.height + chromeGap * 2,
4537
+ zIndex: 2147483646
4538
+ },
4539
+ children: [
4540
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4541
+ "div",
4542
+ {
4543
+ "aria-hidden": true,
4544
+ className: "absolute inset-0 rounded-lg",
4545
+ style: getChromeStyle(state)
4546
+ }
4547
+ ),
4548
+ showDragHandle && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4549
+ "div",
4550
+ {
4551
+ "data-ohw-drag-handle-container": "",
4552
+ className: "pointer-events-auto absolute left-0 top-1/2 -translate-x-[calc(100%+7px)] -translate-y-1/2",
4553
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4554
+ DragHandle,
4555
+ {
4556
+ draggable: !dragDisabled,
4557
+ "aria-label": dragHandleLabel,
4558
+ disabled: dragDisabled,
4559
+ onDragStart: (e) => {
4560
+ if (dragDisabled) {
4561
+ e.preventDefault();
4562
+ return;
4563
+ }
4564
+ e.dataTransfer?.setData("text/plain", dragHandleLabel);
4565
+ e.dataTransfer.effectAllowed = "move";
4566
+ onDragHandleDragStart?.(e);
4567
+ },
4568
+ onDragEnd: onDragHandleDragEnd
4569
+ }
4570
+ )
4571
+ }
4572
+ ),
4573
+ showToolbar && state === "active-top" && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4574
+ "div",
4575
+ {
4576
+ className: "pointer-events-auto absolute bottom-full left-1/2 mb-2 -translate-x-1/2",
4577
+ "data-ohw-item-toolbar-anchor": "top",
4578
+ children: toolbar
4579
+ }
4580
+ ),
4581
+ showToolbar && state === "active-bottom" && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
4582
+ "div",
4583
+ {
4584
+ className: "pointer-events-auto absolute left-1/2 top-full mt-2 -translate-x-1/2",
4585
+ "data-ohw-item-toolbar-anchor": "bottom",
4586
+ children: toolbar
4587
+ }
4588
+ )
4589
+ ]
4590
+ }
4591
+ );
4592
+ }
4593
+
4253
4594
  // src/OhhwellsBridge.tsx
4254
4595
  var import_react_dom2 = require("react-dom");
4255
4596
  var import_navigation = require("next/navigation");
@@ -4529,61 +4870,61 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
4529
4870
  }
4530
4871
 
4531
4872
  // src/ui/dialog.tsx
4532
- var React3 = __toESM(require("react"), 1);
4533
- var import_radix_ui3 = require("radix-ui");
4873
+ var React5 = __toESM(require("react"), 1);
4874
+ var import_radix_ui4 = require("radix-ui");
4534
4875
 
4535
4876
  // src/ui/icons.tsx
4536
- var import_jsx_runtime5 = require("react/jsx-runtime");
4877
+ var import_jsx_runtime10 = require("react/jsx-runtime");
4537
4878
  function IconX({ className, ...props }) {
4538
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4539
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M18 6 6 18" }),
4540
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "m6 6 12 12" })
4879
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4880
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "M18 6 6 18" }),
4881
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "m6 6 12 12" })
4541
4882
  ] });
4542
4883
  }
4543
4884
  function IconChevronDown({ className, ...props }) {
4544
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "m6 9 6 6 6-6" }) });
4885
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "m6 9 6 6 6-6" }) });
4545
4886
  }
4546
4887
  function IconFile({ className, ...props }) {
4547
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4548
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }),
4549
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" })
4888
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4889
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }),
4890
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" })
4550
4891
  ] });
4551
4892
  }
4552
4893
  function IconInfo({ className, ...props }) {
4553
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4554
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
4555
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M12 16v-4" }),
4556
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M12 8h.01" })
4894
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4895
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
4896
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "M12 16v-4" }),
4897
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "M12 8h.01" })
4557
4898
  ] });
4558
4899
  }
4559
4900
  function IconArrowRight({ className, ...props }) {
4560
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4561
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M5 12h14" }),
4562
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "m12 5 7 7-7 7" })
4901
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4902
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "M5 12h14" }),
4903
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "m12 5 7 7-7 7" })
4563
4904
  ] });
4564
4905
  }
4565
4906
  function IconSection({ className, ...props }) {
4566
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4567
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("rect", { width: "18", height: "7", x: "3", y: "3", rx: "1" }),
4568
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("rect", { width: "9", height: "7", x: "3", y: "14", rx: "1" }),
4569
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("rect", { width: "5", height: "7", x: "16", y: "14", rx: "1" })
4907
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, ...props, children: [
4908
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("rect", { width: "18", height: "7", x: "3", y: "3", rx: "1" }),
4909
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("rect", { width: "9", height: "7", x: "3", y: "14", rx: "1" }),
4910
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("rect", { width: "5", height: "7", x: "16", y: "14", rx: "1" })
4570
4911
  ] });
4571
4912
  }
4572
4913
 
4573
4914
  // src/ui/dialog.tsx
4574
- var import_jsx_runtime6 = require("react/jsx-runtime");
4915
+ var import_jsx_runtime11 = require("react/jsx-runtime");
4575
4916
  function Dialog2({ ...props }) {
4576
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_radix_ui3.Dialog.Root, { "data-slot": "dialog", ...props });
4917
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_radix_ui4.Dialog.Root, { "data-slot": "dialog", ...props });
4577
4918
  }
4578
4919
  function DialogPortal({ ...props }) {
4579
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_radix_ui3.Dialog.Portal, { ...props });
4920
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_radix_ui4.Dialog.Portal, { ...props });
4580
4921
  }
4581
4922
  function DialogOverlay({
4582
4923
  className,
4583
4924
  ...props
4584
4925
  }) {
4585
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4586
- import_radix_ui3.Dialog.Overlay,
4926
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
4927
+ import_radix_ui4.Dialog.Overlay,
4587
4928
  {
4588
4929
  "data-slot": "dialog-overlay",
4589
4930
  "data-ohw-link-modal-root": "",
@@ -4592,12 +4933,12 @@ function DialogOverlay({
4592
4933
  }
4593
4934
  );
4594
4935
  }
4595
- var DialogContent = React3.forwardRef(({ className, children, showCloseButton = true, container, ...props }, ref) => {
4936
+ var DialogContent = React5.forwardRef(({ className, children, showCloseButton = true, container, ...props }, ref) => {
4596
4937
  const positionMode = container ? "absolute" : "fixed";
4597
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(DialogPortal, { container: container ?? void 0, children: [
4598
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
4599
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4600
- import_radix_ui3.Dialog.Content,
4938
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(DialogPortal, { container: container ?? void 0, children: [
4939
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
4940
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
4941
+ import_radix_ui4.Dialog.Content,
4601
4942
  {
4602
4943
  ref,
4603
4944
  "data-slot": "dialog-content",
@@ -4612,13 +4953,13 @@ var DialogContent = React3.forwardRef(({ className, children, showCloseButton =
4612
4953
  ...props,
4613
4954
  children: [
4614
4955
  children,
4615
- showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4616
- import_radix_ui3.Dialog.Close,
4956
+ showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
4957
+ import_radix_ui4.Dialog.Close,
4617
4958
  {
4618
4959
  type: "button",
4619
4960
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
4620
4961
  "aria-label": "Close",
4621
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(IconX, { "aria-hidden": true })
4962
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(IconX, { "aria-hidden": true })
4622
4963
  }
4623
4964
  ) : null
4624
4965
  ]
@@ -4626,37 +4967,37 @@ var DialogContent = React3.forwardRef(({ className, children, showCloseButton =
4626
4967
  )
4627
4968
  ] });
4628
4969
  });
4629
- DialogContent.displayName = import_radix_ui3.Dialog.Content.displayName;
4970
+ DialogContent.displayName = import_radix_ui4.Dialog.Content.displayName;
4630
4971
  function DialogHeader({ className, ...props }) {
4631
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
4972
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
4632
4973
  }
4633
4974
  function DialogFooter({ className, ...props }) {
4634
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: cn("flex items-center justify-end gap-2", className), ...props });
4975
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: cn("flex items-center justify-end gap-2", className), ...props });
4635
4976
  }
4636
- var DialogTitle = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4637
- import_radix_ui3.Dialog.Title,
4977
+ var DialogTitle = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
4978
+ import_radix_ui4.Dialog.Title,
4638
4979
  {
4639
4980
  ref,
4640
4981
  className: cn("text-lg font-semibold leading-none tracking-tight text-card-foreground", className),
4641
4982
  ...props
4642
4983
  }
4643
4984
  ));
4644
- DialogTitle.displayName = import_radix_ui3.Dialog.Title.displayName;
4645
- var DialogDescription = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4646
- import_radix_ui3.Dialog.Description,
4985
+ DialogTitle.displayName = import_radix_ui4.Dialog.Title.displayName;
4986
+ var DialogDescription = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
4987
+ import_radix_ui4.Dialog.Description,
4647
4988
  {
4648
4989
  ref,
4649
4990
  className: cn("text-sm text-muted-foreground", className),
4650
4991
  ...props
4651
4992
  }
4652
4993
  ));
4653
- DialogDescription.displayName = import_radix_ui3.Dialog.Description.displayName;
4654
- var DialogClose = import_radix_ui3.Dialog.Close;
4994
+ DialogDescription.displayName = import_radix_ui4.Dialog.Description.displayName;
4995
+ var DialogClose = import_radix_ui4.Dialog.Close;
4655
4996
 
4656
4997
  // src/ui/button.tsx
4657
- var React4 = __toESM(require("react"), 1);
4658
- var import_radix_ui4 = require("radix-ui");
4659
- var import_jsx_runtime7 = require("react/jsx-runtime");
4998
+ var React6 = __toESM(require("react"), 1);
4999
+ var import_radix_ui5 = require("radix-ui");
5000
+ var import_jsx_runtime12 = require("react/jsx-runtime");
4660
5001
  var buttonVariants = cva(
4661
5002
  "inline-flex items-center justify-center gap-1 whitespace-nowrap rounded-md text-sm font-medium transition-colors outline-none disabled:pointer-events-none disabled:opacity-50 min-w-[80px] px-3 py-2",
4662
5003
  {
@@ -4677,10 +5018,10 @@ var buttonVariants = cva(
4677
5018
  }
4678
5019
  }
4679
5020
  );
4680
- var Button = React4.forwardRef(
5021
+ var Button = React6.forwardRef(
4681
5022
  ({ className, variant, size, asChild = false, ...props }, ref) => {
4682
- const Comp = asChild ? import_radix_ui4.Slot.Root : "button";
4683
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
5023
+ const Comp = asChild ? import_radix_ui5.Slot.Root : "button";
5024
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4684
5025
  Comp,
4685
5026
  {
4686
5027
  ref,
@@ -4694,37 +5035,37 @@ var Button = React4.forwardRef(
4694
5035
  Button.displayName = "Button";
4695
5036
 
4696
5037
  // src/ui/link-modal/DestinationBreadcrumb.tsx
4697
- var import_jsx_runtime8 = require("react/jsx-runtime");
5038
+ var import_jsx_runtime13 = require("react/jsx-runtime");
4698
5039
  function DestinationBreadcrumb({ pageTitle, sectionLabel }) {
4699
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex w-full flex-col gap-2", children: [
4700
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-sm font-medium text-foreground", children: "Destination" }),
4701
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-3", children: [
4702
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-2", children: [
4703
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconFile, { className: "shrink-0 text-foreground", "aria-hidden": true }),
4704
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-sm font-medium leading-none text-foreground", children: pageTitle })
5040
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex w-full flex-col gap-2", children: [
5041
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "text-sm font-medium text-foreground", children: "Destination" }),
5042
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-3", children: [
5043
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-2", children: [
5044
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconFile, { className: "shrink-0 text-foreground", "aria-hidden": true }),
5045
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-sm font-medium leading-none text-foreground", children: pageTitle })
4705
5046
  ] }),
4706
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconArrowRight, { className: "shrink-0 text-muted-foreground", "aria-hidden": true }),
4707
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
4708
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconSection, { className: "shrink-0 text-foreground", "aria-hidden": true }),
4709
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
5047
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconArrowRight, { className: "shrink-0 text-muted-foreground", "aria-hidden": true }),
5048
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
5049
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconSection, { className: "shrink-0 text-foreground", "aria-hidden": true }),
5050
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
4710
5051
  ] })
4711
5052
  ] })
4712
5053
  ] });
4713
5054
  }
4714
5055
 
4715
5056
  // src/ui/link-modal/SectionTreeItem.tsx
4716
- var import_jsx_runtime9 = require("react/jsx-runtime");
5057
+ var import_jsx_runtime14 = require("react/jsx-runtime");
4717
5058
  function SectionTreeItem({ section, onSelect, selected }) {
4718
5059
  const interactive = Boolean(onSelect);
4719
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex h-9 w-full items-end pl-3", children: [
4720
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
5060
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex h-9 w-full items-end pl-3", children: [
5061
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4721
5062
  "div",
4722
5063
  {
4723
5064
  className: "mr-[-1px] h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
4724
5065
  "aria-hidden": true
4725
5066
  }
4726
5067
  ),
4727
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
5068
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
4728
5069
  "div",
4729
5070
  {
4730
5071
  role: interactive ? "button" : void 0,
@@ -4742,8 +5083,8 @@ function SectionTreeItem({ section, onSelect, selected }) {
4742
5083
  interactive && selected && "border-primary"
4743
5084
  ),
4744
5085
  children: [
4745
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconSection, { className: "shrink-0 text-foreground", "aria-hidden": true }),
4746
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
5086
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(IconSection, { className: "shrink-0 text-foreground", "aria-hidden": true }),
5087
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
4747
5088
  ]
4748
5089
  }
4749
5090
  )
@@ -4751,11 +5092,11 @@ function SectionTreeItem({ section, onSelect, selected }) {
4751
5092
  }
4752
5093
  function SectionPickerList({ sections, onSelect }) {
4753
5094
  if (sections.length === 0) {
4754
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." });
5095
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." });
4755
5096
  }
4756
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-col gap-1", children: [
4757
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-sm text-muted-foreground", children: "Pick a section this link should scroll to." }),
4758
- sections.map((section) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SectionTreeItem, { section, onSelect }, section.id))
5097
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex flex-col gap-1", children: [
5098
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-sm text-muted-foreground", children: "Pick a section this link should scroll to." }),
5099
+ sections.map((section) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(SectionTreeItem, { section, onSelect }, section.id))
4759
5100
  ] });
4760
5101
  }
4761
5102
 
@@ -4763,11 +5104,11 @@ function SectionPickerList({ sections, onSelect }) {
4763
5104
  var import_react4 = require("react");
4764
5105
 
4765
5106
  // src/ui/input.tsx
4766
- var React5 = __toESM(require("react"), 1);
4767
- var import_jsx_runtime10 = require("react/jsx-runtime");
4768
- var Input = React5.forwardRef(
5107
+ var React7 = __toESM(require("react"), 1);
5108
+ var import_jsx_runtime15 = require("react/jsx-runtime");
5109
+ var Input = React7.forwardRef(
4769
5110
  ({ className, type, ...props }, ref) => {
4770
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
5111
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
4771
5112
  "input",
4772
5113
  {
4773
5114
  type,
@@ -4785,11 +5126,11 @@ var Input = React5.forwardRef(
4785
5126
  Input.displayName = "Input";
4786
5127
 
4787
5128
  // src/ui/label.tsx
4788
- var import_radix_ui5 = require("radix-ui");
4789
- var import_jsx_runtime11 = require("react/jsx-runtime");
5129
+ var import_radix_ui6 = require("radix-ui");
5130
+ var import_jsx_runtime16 = require("react/jsx-runtime");
4790
5131
  function Label({ className, ...props }) {
4791
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
4792
- import_radix_ui5.Label.Root,
5132
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5133
+ import_radix_ui6.Label.Root,
4793
5134
  {
4794
5135
  "data-slot": "label",
4795
5136
  className: cn("text-sm font-medium leading-5 text-foreground", className),
@@ -4799,9 +5140,9 @@ function Label({ className, ...props }) {
4799
5140
  }
4800
5141
 
4801
5142
  // src/ui/link-modal/UrlOrPageInput.tsx
4802
- var import_jsx_runtime12 = require("react/jsx-runtime");
5143
+ var import_jsx_runtime17 = require("react/jsx-runtime");
4803
5144
  function FieldChevron({ onClick }) {
4804
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5145
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
4805
5146
  "button",
4806
5147
  {
4807
5148
  type: "button",
@@ -4809,7 +5150,7 @@ function FieldChevron({ onClick }) {
4809
5150
  onClick,
4810
5151
  "aria-label": "Open page list",
4811
5152
  tabIndex: -1,
4812
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconChevronDown, {})
5153
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(IconChevronDown, {})
4813
5154
  }
4814
5155
  );
4815
5156
  }
@@ -4848,12 +5189,12 @@ function UrlOrPageInput({
4848
5189
  "data-ohw-link-field flex h-10 w-full items-center overflow-hidden rounded-md border bg-background pl-3 pr-3 py-2 outline-none transition-[border-color,box-shadow]",
4849
5190
  urlError ? "border-destructive shadow-[0_0_0_1px_var(--ohw-destructive)]" : isFocused ? "border-primary shadow-[0_0_0_1px_var(--ohw-primary)]" : "border-input"
4850
5191
  );
4851
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex w-full flex-col gap-2 p-0", children: [
4852
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
4853
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "relative w-full", children: [
4854
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
4855
- selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconFile, { className: "text-foreground", "aria-hidden": true }) }) : null,
4856
- readOnly ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm leading-5 text-foreground", children: selectedPage?.title ?? value }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5192
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex w-full flex-col gap-2 p-0", children: [
5193
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
5194
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "relative w-full", children: [
5195
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
5196
+ selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(IconFile, { className: "text-foreground", "aria-hidden": true }) }) : null,
5197
+ readOnly ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm leading-5 text-foreground", children: selectedPage?.title ?? value }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
4857
5198
  Input,
4858
5199
  {
4859
5200
  ref: inputRef,
@@ -4872,7 +5213,7 @@ function UrlOrPageInput({
4872
5213
  )
4873
5214
  }
4874
5215
  ),
4875
- selectedPage && !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5216
+ selectedPage && !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
4876
5217
  "button",
4877
5218
  {
4878
5219
  type: "button",
@@ -4880,26 +5221,26 @@ function UrlOrPageInput({
4880
5221
  onMouseDown: clearSelection,
4881
5222
  "aria-label": "Clear selected page",
4882
5223
  tabIndex: -1,
4883
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconX, { "aria-hidden": true })
5224
+ children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(IconX, { "aria-hidden": true })
4884
5225
  }
4885
5226
  ) : null,
4886
- !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(FieldChevron, { onClick: toggleDropdown }) : null
5227
+ !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(FieldChevron, { onClick: toggleDropdown }) : null
4887
5228
  ] }),
4888
- dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5229
+ dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
4889
5230
  "div",
4890
5231
  {
4891
5232
  "data-ohw-link-page-dropdown": "",
4892
5233
  className: "absolute left-0 right-0 h-20 top-[calc(100%+4px)] z-10 max-h-48 overflow-auto rounded-lg border border-border bg-popover py-1 shadow-lg",
4893
5234
  onMouseDown: (e) => e.preventDefault(),
4894
- children: filteredPages.map((page) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
5235
+ children: filteredPages.map((page) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
4895
5236
  "button",
4896
5237
  {
4897
5238
  type: "button",
4898
5239
  className: "flex h-9 w-full items-center gap-2 border-0 bg-transparent px-3 text-left text-sm leading-5 text-foreground outline-none hover:bg-muted",
4899
5240
  onClick: () => onPageSelect(page),
4900
5241
  children: [
4901
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(IconFile, { className: "shrink-0", "aria-hidden": true }),
4902
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "truncate", children: page.title })
5242
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(IconFile, { className: "shrink-0", "aria-hidden": true }),
5243
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "truncate", children: page.title })
4903
5244
  ]
4904
5245
  },
4905
5246
  page.path
@@ -4907,7 +5248,7 @@ function UrlOrPageInput({
4907
5248
  }
4908
5249
  ) : null
4909
5250
  ] }),
4910
- urlError ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
5251
+ urlError ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
4911
5252
  ] });
4912
5253
  }
4913
5254
 
@@ -5075,7 +5416,7 @@ function useLinkModalState({
5075
5416
  }
5076
5417
 
5077
5418
  // src/ui/link-modal/LinkEditorPanel.tsx
5078
- var import_jsx_runtime13 = require("react/jsx-runtime");
5419
+ var import_jsx_runtime18 = require("react/jsx-runtime");
5079
5420
  function LinkEditorPanel({
5080
5421
  open = true,
5081
5422
  mode = "create",
@@ -5099,25 +5440,25 @@ function LinkEditorPanel({
5099
5440
  onSubmit
5100
5441
  });
5101
5442
  const isCancel = state.secondaryLabel === "Cancel";
5102
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
5103
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(DialogClose, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5443
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
5444
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DialogClose, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5104
5445
  "button",
5105
5446
  {
5106
5447
  type: "button",
5107
5448
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
5108
5449
  "aria-label": "Close",
5109
- children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconX, { "aria-hidden": true })
5450
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(IconX, { "aria-hidden": true })
5110
5451
  }
5111
5452
  ) }),
5112
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(DialogHeader, { className: "w-full gap-1.5 p-6 pr-12", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(DialogTitle, { className: "m-0 w-full break-words", children: state.title }) }),
5113
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
5114
- state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5453
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DialogHeader, { className: "w-full gap-1.5 p-6 pr-12", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DialogTitle, { className: "m-0 w-full break-words", children: state.title }) }),
5454
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
5455
+ state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5115
5456
  DestinationBreadcrumb,
5116
5457
  {
5117
5458
  pageTitle: state.selectedPage.title,
5118
5459
  sectionLabel: state.selectedSection.label
5119
5460
  }
5120
- ) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5461
+ ) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5121
5462
  UrlOrPageInput,
5122
5463
  {
5123
5464
  value: state.searchValue,
@@ -5130,18 +5471,18 @@ function LinkEditorPanel({
5130
5471
  urlError: state.urlError
5131
5472
  }
5132
5473
  ),
5133
- state.showChooseSection ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-col justify-center gap-2", children: [
5134
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Button, { type: "button", variant: "outline", className: "w-fit cursor-pointer", size: "sm", onClick: state.handleChooseSection, children: "Choose a section" }),
5135
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
5136
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(IconInfo, { className: "shrink-0", "aria-hidden": true }),
5137
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: "Pick a section this link should scroll to." })
5474
+ state.showChooseSection ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex flex-col justify-center gap-2", children: [
5475
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Button, { type: "button", variant: "outline", className: "w-fit cursor-pointer", size: "sm", onClick: state.handleChooseSection, children: "Choose a section" }),
5476
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
5477
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(IconInfo, { className: "shrink-0", "aria-hidden": true }),
5478
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: "Pick a section this link should scroll to." })
5138
5479
  ] })
5139
5480
  ] }) : null,
5140
- state.showSectionPicker ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SectionPickerList, { sections: state.activeSections, onSelect: state.handleSectionSelect }) : null,
5141
- state.showSectionRow && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
5481
+ state.showSectionPicker ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(SectionPickerList, { sections: state.activeSections, onSelect: state.handleSectionSelect }) : null,
5482
+ state.showSectionRow && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
5142
5483
  ] }),
5143
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(DialogFooter, { className: "w-full px-6 pb-6", children: [
5144
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5484
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(DialogFooter, { className: "w-full px-6 pb-6", children: [
5485
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5145
5486
  Button,
5146
5487
  {
5147
5488
  type: "button",
@@ -5156,7 +5497,7 @@ function LinkEditorPanel({
5156
5497
  children: state.secondaryLabel
5157
5498
  }
5158
5499
  ),
5159
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5500
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5160
5501
  Button,
5161
5502
  {
5162
5503
  type: "button",
@@ -5175,7 +5516,7 @@ function LinkEditorPanel({
5175
5516
  }
5176
5517
 
5177
5518
  // src/ui/link-modal/LinkPopover.tsx
5178
- var import_jsx_runtime14 = require("react/jsx-runtime");
5519
+ var import_jsx_runtime19 = require("react/jsx-runtime");
5179
5520
  function LinkPopover({
5180
5521
  open = true,
5181
5522
  panelRef,
@@ -5183,14 +5524,14 @@ function LinkPopover({
5183
5524
  onClose,
5184
5525
  ...editorProps
5185
5526
  }) {
5186
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5527
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5187
5528
  Dialog2,
5188
5529
  {
5189
5530
  open,
5190
5531
  onOpenChange: (next) => {
5191
5532
  if (!next) onClose?.();
5192
5533
  },
5193
- children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5534
+ children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5194
5535
  DialogContent,
5195
5536
  {
5196
5537
  ref: panelRef,
@@ -5200,7 +5541,7 @@ function LinkPopover({
5200
5541
  "data-ohw-bridge": "",
5201
5542
  showCloseButton: false,
5202
5543
  className: "gap-0 p-0 w-full md:w-md pointer-events-auto",
5203
- children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(LinkEditorPanel, { ...editorProps, open, onClose })
5544
+ children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(LinkEditorPanel, { ...editorProps, open, onClose })
5204
5545
  }
5205
5546
  )
5206
5547
  }
@@ -5266,7 +5607,7 @@ function shouldUseDevFixtures() {
5266
5607
  }
5267
5608
 
5268
5609
  // src/ui/badge.tsx
5269
- var import_jsx_runtime15 = require("react/jsx-runtime");
5610
+ var import_jsx_runtime20 = require("react/jsx-runtime");
5270
5611
  var badgeVariants = cva(
5271
5612
  "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
5272
5613
  {
@@ -5284,12 +5625,13 @@ var badgeVariants = cva(
5284
5625
  }
5285
5626
  );
5286
5627
  function Badge({ className, variant, ...props }) {
5287
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
5628
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
5288
5629
  }
5289
5630
 
5290
5631
  // src/OhhwellsBridge.tsx
5291
- var import_jsx_runtime16 = require("react/jsx-runtime");
5292
- var PRIMARY = "#0885FE";
5632
+ var import_lucide_react3 = require("lucide-react");
5633
+ var import_jsx_runtime21 = require("react/jsx-runtime");
5634
+ var PRIMARY2 = "#0885FE";
5293
5635
  var IMAGE_FADE_MS = 300;
5294
5636
  function runOpacityFade(el, onDone) {
5295
5637
  const anim = el.animate([{ opacity: 0 }, { opacity: 1 }], {
@@ -5462,7 +5804,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
5462
5804
  const root = (0, import_client.createRoot)(container);
5463
5805
  (0, import_react_dom.flushSync)(() => {
5464
5806
  root.render(
5465
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5807
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
5466
5808
  SchedulingWidget,
5467
5809
  {
5468
5810
  notifyOnConnect,
@@ -5510,6 +5852,20 @@ function applyLinkHref(el, val) {
5510
5852
  const anchor = el instanceof HTMLAnchorElement ? el : el.querySelector("a");
5511
5853
  if (anchor) anchor.setAttribute("href", val);
5512
5854
  }
5855
+ function getEditMeasureEl(editable) {
5856
+ return editable.closest("[data-ohw-href-key]") ?? editable;
5857
+ }
5858
+ function isDragHandleDisabled(el) {
5859
+ const carriers = [
5860
+ el.closest("[data-ohw-href-key]"),
5861
+ el.closest("[data-ohw-editable]")
5862
+ ];
5863
+ return carriers.some((carrier) => {
5864
+ if (!carrier) return false;
5865
+ const raw = carrier.getAttribute("data-ohw-drag-disabled");
5866
+ return raw === "true" || raw === "";
5867
+ });
5868
+ }
5513
5869
  function collectEditableNodes() {
5514
5870
  const nodes = Array.from(document.querySelectorAll("[data-ohw-editable]")).map((el) => {
5515
5871
  if (el.dataset.ohwEditable === "image") {
@@ -5563,12 +5919,49 @@ function getHrefKeyFromElement(el) {
5563
5919
  function isNavbarButton(el) {
5564
5920
  return Boolean(el.closest('[data-ohw-role="navbar-button"]'));
5565
5921
  }
5922
+ function getNavigationItemAnchor(el) {
5923
+ const anchor = el.matches("[data-ohw-href-key]") ? el : el.closest("[data-ohw-href-key]");
5924
+ if (!anchor) return null;
5925
+ if (!anchor.querySelector('[data-ohw-editable="text"]')) return null;
5926
+ return anchor;
5927
+ }
5928
+ function isNavigationItem(el) {
5929
+ return getNavigationItemAnchor(el) !== null;
5930
+ }
5931
+ function getNavigationItemAddHintTarget(anchor) {
5932
+ const items = listNavigationItems();
5933
+ const idx = items.indexOf(anchor);
5934
+ if (idx >= 0 && idx < items.length - 1) return items[idx + 1];
5935
+ return anchor;
5936
+ }
5937
+ function listNavigationItems() {
5938
+ return Array.from(
5939
+ document.querySelectorAll("nav [data-ohw-href-key], footer [data-ohw-href-key]")
5940
+ ).filter((el) => isNavigationItem(el));
5941
+ }
5942
+ function getNavigationItemReorderState(anchor) {
5943
+ if (isNavbarButton(anchor)) return { key: null, disabled: false };
5944
+ return getReorderHandleStateFromAnchor(anchor);
5945
+ }
5946
+ function getReorderHandleState(el) {
5947
+ const linkEl = el.closest("[data-ohw-href-key]");
5948
+ if (!linkEl || getNavigationItemAnchor(linkEl)) return { key: null, disabled: false };
5949
+ return getReorderHandleStateFromAnchor(linkEl);
5950
+ }
5951
+ function getReorderHandleStateFromAnchor(anchor) {
5952
+ const key = anchor.getAttribute("data-ohw-href-key");
5953
+ if (!key) return { key: null, disabled: false };
5954
+ return { key, disabled: isDragHandleDisabled(anchor) };
5955
+ }
5566
5956
  function clearHrefKeyHover(anchor) {
5567
5957
  anchor.removeAttribute("data-ohw-hovered");
5568
5958
  anchor.querySelectorAll("[data-ohw-hovered]").forEach((el) => {
5569
5959
  el.removeAttribute("data-ohw-hovered");
5570
5960
  });
5571
5961
  }
5962
+ function isInsideNavigationItem(el) {
5963
+ return getNavigationItemAnchor(el) !== null;
5964
+ }
5572
5965
  function collectSections() {
5573
5966
  return collectSectionsFromDom();
5574
5967
  }
@@ -5709,24 +6102,64 @@ var TOOLBAR_GROUPS = [
5709
6102
  { cmd: "insertOrderedList", title: "Numbered List" }
5710
6103
  ]
5711
6104
  ];
5712
- function GlowFrame({ rect, elRef }) {
6105
+ function EditGlowChrome({
6106
+ rect,
6107
+ elRef,
6108
+ reorderHrefKey,
6109
+ dragDisabled = false
6110
+ }) {
5713
6111
  const GAP = 6;
5714
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6112
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
5715
6113
  "div",
5716
6114
  {
5717
6115
  ref: elRef,
6116
+ "data-ohw-edit-chrome": "",
5718
6117
  style: {
5719
6118
  position: "fixed",
5720
6119
  top: rect.top - GAP,
5721
6120
  left: rect.left - GAP,
5722
6121
  width: rect.width + GAP * 2,
5723
6122
  height: rect.height + GAP * 2,
5724
- border: "2px solid #0885FE",
5725
- borderRadius: 8,
5726
- boxShadow: "0 0 0 4px rgba(8, 133, 254, 0.12)",
5727
6123
  pointerEvents: "none",
5728
6124
  zIndex: 2147483646
5729
- }
6125
+ },
6126
+ children: [
6127
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6128
+ "div",
6129
+ {
6130
+ style: {
6131
+ position: "absolute",
6132
+ inset: 0,
6133
+ border: "2px solid var(--ohw-primary, #0885FE)",
6134
+ borderRadius: 8,
6135
+ boxShadow: "0 0 0 4px rgba(8, 133, 254, 0.12)",
6136
+ pointerEvents: "none"
6137
+ }
6138
+ }
6139
+ ),
6140
+ reorderHrefKey && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6141
+ "div",
6142
+ {
6143
+ "data-ohw-drag-handle-container": "",
6144
+ "data-ohw-drag-disabled": dragDisabled ? "" : void 0,
6145
+ style: {
6146
+ position: "absolute",
6147
+ left: 0,
6148
+ top: "50%",
6149
+ transform: "translate(calc(-100% - 7px), -50%)",
6150
+ pointerEvents: dragDisabled ? "none" : "auto"
6151
+ },
6152
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6153
+ DragHandle,
6154
+ {
6155
+ "aria-label": `Reorder ${reorderHrefKey}`,
6156
+ disabled: dragDisabled,
6157
+ "aria-disabled": dragDisabled
6158
+ }
6159
+ )
6160
+ }
6161
+ )
6162
+ ]
5730
6163
  }
5731
6164
  );
5732
6165
  }
@@ -5770,9 +6203,9 @@ function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
5770
6203
  const pinnedTop = Math.min(maxBottom - approxH, Math.max(minTop, clip.top + gap));
5771
6204
  return { top: pinnedTop + approxH, transform: "translateX(-50%) translateY(-100%)" };
5772
6205
  }
5773
- function calcToolbarPos(rect, parentScroll, approxW = 330) {
6206
+ function calcToolbarPos(rect, parentScroll, approxW = 306) {
5774
6207
  const GAP = 8;
5775
- const APPROX_H = 36;
6208
+ const APPROX_H = 32;
5776
6209
  const APPROX_W = approxW;
5777
6210
  const clip = getIframeVisibleClip(parentScroll);
5778
6211
  const clipTop = clip?.top ?? 0;
@@ -5806,182 +6239,60 @@ function calcToolbarPos(rect, parentScroll, approxW = 330) {
5806
6239
  const left = Math.max(GAP + APPROX_W / 2, Math.min(rawLeft, window.innerWidth - GAP - APPROX_W / 2));
5807
6240
  return { top, left, transform };
5808
6241
  }
5809
- var EDIT_LINK_ICON = /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
5810
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }),
5811
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })
5812
- ] });
6242
+ function resolveItemInteractionState(rect, parentScroll) {
6243
+ const { transform } = calcToolbarPos(rect, parentScroll, 120);
6244
+ return transform.includes("translateY(-100%)") ? "active-top" : "active-bottom";
6245
+ }
5813
6246
  function FloatingToolbar({
5814
6247
  rect,
5815
6248
  parentScroll,
5816
6249
  elRef,
5817
- variant = "rich-text",
5818
6250
  onCommand,
5819
6251
  activeCommands,
5820
6252
  showEditLink,
5821
6253
  onEditLink
5822
6254
  }) {
5823
- const approxW = variant === "link-action" ? 120 : 330;
5824
- const { top, left, transform } = calcToolbarPos(rect, parentScroll, approxW);
5825
- if (variant === "link-action") {
5826
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
5827
- "div",
5828
- {
5829
- ref: elRef,
5830
- "data-ohw-toolbar": "",
5831
- style: {
5832
- position: "fixed",
5833
- top,
5834
- left,
5835
- transform,
5836
- zIndex: 2147483647,
5837
- background: "#fff",
5838
- border: "1px solid #E7E5E4",
5839
- borderRadius: 6,
5840
- boxShadow: "0px 2px 4px -2px rgba(0,0,0,.1),0px 4px 6px -1px rgba(0,0,0,.1)",
5841
- display: "flex",
5842
- alignItems: "center",
5843
- padding: 4,
5844
- gap: 6,
5845
- fontFamily: "sans-serif",
5846
- pointerEvents: "auto",
5847
- whiteSpace: "nowrap"
5848
- },
5849
- onMouseDown: (e) => e.stopPropagation(),
5850
- children: [
5851
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5852
- "button",
5853
- {
5854
- type: "button",
5855
- title: "Edit link",
5856
- onMouseDown: (e) => {
5857
- e.preventDefault();
5858
- e.stopPropagation();
5859
- onEditLink?.();
5860
- },
5861
- onClick: (e) => {
5862
- e.preventDefault();
5863
- e.stopPropagation();
5864
- },
5865
- onMouseEnter: (e) => {
5866
- e.currentTarget.style.background = "#F5F5F4";
5867
- },
5868
- onMouseLeave: (e) => {
5869
- e.currentTarget.style.background = "transparent";
5870
- },
5871
- style: {
5872
- display: "flex",
5873
- alignItems: "center",
5874
- justifyContent: "center",
5875
- border: "none",
5876
- background: "transparent",
5877
- borderRadius: 4,
5878
- cursor: "pointer",
5879
- color: "#1C1917",
5880
- flexShrink: 0,
5881
- padding: 6
5882
- },
5883
- children: EDIT_LINK_ICON
5884
- }
5885
- ),
5886
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { style: { display: "block", width: 1, height: 24, background: "#E7E5E4", flexShrink: 0 } }),
5887
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5888
- "button",
5889
- {
5890
- type: "button",
5891
- title: "Coming soon",
5892
- disabled: true,
5893
- style: {
5894
- display: "flex",
5895
- alignItems: "center",
5896
- justifyContent: "center",
5897
- border: "none",
5898
- background: "transparent",
5899
- borderRadius: 4,
5900
- cursor: "not-allowed",
5901
- color: "#A8A29E",
5902
- flexShrink: 0,
5903
- padding: 6,
5904
- opacity: 0.6
5905
- },
5906
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": true, children: [
5907
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("circle", { cx: "5", cy: "12", r: "1.5" }),
5908
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("circle", { cx: "12", cy: "12", r: "1.5" }),
5909
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("circle", { cx: "19", cy: "12", r: "1.5" })
5910
- ] })
5911
- }
5912
- )
5913
- ]
5914
- }
5915
- );
5916
- }
5917
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
6255
+ const { top, left, transform } = calcToolbarPos(rect, parentScroll, 330);
6256
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
5918
6257
  "div",
5919
6258
  {
5920
6259
  ref: elRef,
5921
- "data-ohw-toolbar": "",
5922
6260
  style: {
5923
6261
  position: "fixed",
5924
6262
  top,
5925
6263
  left,
5926
6264
  transform,
5927
6265
  zIndex: 2147483647,
5928
- background: "#fff",
5929
- border: "1px solid #E7E5E4",
5930
- borderRadius: 6,
5931
- boxShadow: "0px 2px 4px -2px rgba(0,0,0,.1),0px 4px 6px -1px rgba(0,0,0,.1)",
5932
- display: "flex",
5933
- alignItems: "center",
5934
- padding: 4,
5935
- gap: 6,
5936
- fontFamily: "sans-serif",
5937
- pointerEvents: "auto",
5938
- whiteSpace: "nowrap"
6266
+ pointerEvents: "auto"
5939
6267
  },
5940
- onMouseDown: (e) => e.stopPropagation(),
5941
- children: [
5942
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react6.default.Fragment, { children: [
5943
- gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { style: { display: "block", width: 1, height: 24, background: "#E7E5E4", flexShrink: 0 } }),
6268
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(CustomToolbar, { children: [
6269
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_react6.default.Fragment, { children: [
6270
+ gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CustomToolbarDivider, {}),
5944
6271
  btns.map((btn) => {
5945
6272
  const isActive = activeCommands.has(btn.cmd);
5946
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5947
- "button",
6273
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6274
+ CustomToolbarButton,
5948
6275
  {
5949
6276
  title: btn.title,
6277
+ active: isActive,
5950
6278
  onMouseDown: (e) => {
5951
6279
  e.preventDefault();
5952
6280
  onCommand(btn.cmd);
5953
6281
  },
5954
- onMouseEnter: (e) => {
5955
- if (!isActive) e.currentTarget.style.background = "#F5F5F4";
5956
- },
5957
- onMouseLeave: (e) => {
5958
- if (!isActive) e.currentTarget.style.background = "transparent";
5959
- },
5960
- style: {
5961
- display: "flex",
5962
- alignItems: "center",
5963
- justifyContent: "center",
5964
- border: "none",
5965
- background: isActive ? PRIMARY : "transparent",
5966
- borderRadius: 4,
5967
- cursor: "pointer",
5968
- color: isActive ? "#FFFFFF" : "#1C1917",
5969
- flexShrink: 0,
5970
- padding: 6
5971
- },
5972
- children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6282
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
5973
6283
  "svg",
5974
6284
  {
5975
6285
  width: "16",
5976
6286
  height: "16",
5977
6287
  viewBox: "0 0 24 24",
5978
6288
  fill: "none",
5979
- stroke: isActive ? "#FFFFFF" : "#1C1917",
6289
+ stroke: "currentColor",
5980
6290
  strokeWidth: "2.5",
5981
6291
  strokeLinecap: "round",
5982
6292
  strokeLinejoin: "round",
5983
- style: isActive && gi > 0 ? { filter: "drop-shadow(0 0 0.5px #fff)" } : void 0,
5984
- dangerouslySetInnerHTML: { __html: ICONS[btn.cmd] }
6293
+ style: isActive && gi > 0 ? { filter: "drop-shadow(0 0 0.5px currentColor)" } : void 0,
6294
+ dangerouslySetInnerHTML: { __html: ICONS[btn.cmd] },
6295
+ "aria-hidden": true
5985
6296
  }
5986
6297
  )
5987
6298
  },
@@ -5989,8 +6300,8 @@ function FloatingToolbar({
5989
6300
  );
5990
6301
  })
5991
6302
  ] }, gi)),
5992
- showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5993
- "button",
6303
+ showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6304
+ CustomToolbarButton,
5994
6305
  {
5995
6306
  type: "button",
5996
6307
  title: "Edit link",
@@ -6003,28 +6314,10 @@ function FloatingToolbar({
6003
6314
  e.preventDefault();
6004
6315
  e.stopPropagation();
6005
6316
  },
6006
- onMouseEnter: (e) => {
6007
- e.currentTarget.style.background = "#F5F5F4";
6008
- },
6009
- onMouseLeave: (e) => {
6010
- e.currentTarget.style.background = "transparent";
6011
- },
6012
- style: {
6013
- display: "flex",
6014
- alignItems: "center",
6015
- justifyContent: "center",
6016
- border: "none",
6017
- background: "transparent",
6018
- borderRadius: 4,
6019
- cursor: "pointer",
6020
- color: "#1C1917",
6021
- flexShrink: 0,
6022
- padding: 6
6023
- },
6024
- children: EDIT_LINK_ICON
6317
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react3.Link, { className: "size-4 shrink-0", "aria-hidden": true })
6025
6318
  }
6026
6319
  ) : null
6027
- ]
6320
+ ] })
6028
6321
  }
6029
6322
  );
6030
6323
  }
@@ -6038,7 +6331,7 @@ function StateToggle({
6038
6331
  states,
6039
6332
  onStateChange
6040
6333
  }) {
6041
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
6334
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6042
6335
  ToggleGroup,
6043
6336
  {
6044
6337
  "data-ohw-state-toggle": "",
@@ -6052,7 +6345,7 @@ function StateToggle({
6052
6345
  left: rect.right - 8,
6053
6346
  transform: "translateX(-100%)"
6054
6347
  },
6055
- children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
6348
+ children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
6056
6349
  }
6057
6350
  );
6058
6351
  }
@@ -6140,6 +6433,10 @@ function OhhwellsBridge() {
6140
6433
  });
6141
6434
  const deselectRef = (0, import_react6.useRef)(() => {
6142
6435
  });
6436
+ const reselectNavigationItemRef = (0, import_react6.useRef)(() => {
6437
+ });
6438
+ const commitNavigationTextEditRef = (0, import_react6.useRef)(() => {
6439
+ });
6143
6440
  const refreshActiveCommandsRef = (0, import_react6.useRef)(() => {
6144
6441
  });
6145
6442
  const postToParentRef = (0, import_react6.useRef)(postToParent);
@@ -6150,11 +6447,18 @@ function OhhwellsBridge() {
6150
6447
  const [toolbarVariant, setToolbarVariant] = (0, import_react6.useState)("none");
6151
6448
  const toolbarVariantRef = (0, import_react6.useRef)("none");
6152
6449
  toolbarVariantRef.current = toolbarVariant;
6450
+ const [reorderHrefKey, setReorderHrefKey] = (0, import_react6.useState)(null);
6451
+ const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react6.useState)(false);
6153
6452
  const [toggleState, setToggleState] = (0, import_react6.useState)(null);
6154
6453
  const [maxBadge, setMaxBadge] = (0, import_react6.useState)(null);
6155
6454
  const [activeCommands, setActiveCommands] = (0, import_react6.useState)(/* @__PURE__ */ new Set());
6156
6455
  const [sectionGap, setSectionGap] = (0, import_react6.useState)(null);
6157
6456
  const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react6.useState)(false);
6457
+ const hoveredItemElRef = (0, import_react6.useRef)(null);
6458
+ const [hoveredItemRect, setHoveredItemRect] = (0, import_react6.useState)(null);
6459
+ const siblingHintElRef = (0, import_react6.useRef)(null);
6460
+ const [siblingHintRect, setSiblingHintRect] = (0, import_react6.useState)(null);
6461
+ const [isItemDragging, setIsItemDragging] = (0, import_react6.useState)(false);
6158
6462
  const [linkPopover, setLinkPopover] = (0, import_react6.useState)(null);
6159
6463
  const [sitePages, setSitePages] = (0, import_react6.useState)([]);
6160
6464
  const [sectionsByPath, setSectionsByPath] = (0, import_react6.useState)({});
@@ -6256,7 +6560,7 @@ function OhhwellsBridge() {
6256
6560
  (0, import_react6.useEffect)(() => {
6257
6561
  const update = () => {
6258
6562
  const el = activeElRef.current ?? selectedElRef.current;
6259
- if (el) setToolbarRect(el.getBoundingClientRect());
6563
+ if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
6260
6564
  setToggleState((prev) => {
6261
6565
  if (!prev || !activeStateElRef.current) return prev;
6262
6566
  return { ...prev, rect: activeStateElRef.current.getBoundingClientRect() };
@@ -6323,6 +6627,8 @@ function OhhwellsBridge() {
6323
6627
  }
6324
6628
  el.removeAttribute("contenteditable");
6325
6629
  activeElRef.current = null;
6630
+ setReorderHrefKey(null);
6631
+ setReorderDragDisabled(false);
6326
6632
  if (!selectedElRef.current) {
6327
6633
  setToolbarRect(null);
6328
6634
  setToolbarVariant("none");
@@ -6334,16 +6640,82 @@ function OhhwellsBridge() {
6334
6640
  }, [postToParent]);
6335
6641
  const deselect = (0, import_react6.useCallback)(() => {
6336
6642
  selectedElRef.current = null;
6643
+ setReorderHrefKey(null);
6644
+ setReorderDragDisabled(false);
6645
+ siblingHintElRef.current = null;
6646
+ setSiblingHintRect(null);
6647
+ setIsItemDragging(false);
6337
6648
  if (!activeElRef.current) {
6338
6649
  setToolbarRect(null);
6339
6650
  setToolbarVariant("none");
6340
6651
  }
6341
6652
  }, []);
6653
+ const reselectNavigationItem = (0, import_react6.useCallback)((navAnchor) => {
6654
+ selectedElRef.current = navAnchor;
6655
+ const { key, disabled } = getNavigationItemReorderState(navAnchor);
6656
+ setReorderHrefKey(key);
6657
+ setReorderDragDisabled(disabled);
6658
+ setToolbarVariant("link-action");
6659
+ setToolbarRect(navAnchor.getBoundingClientRect());
6660
+ setToolbarShowEditLink(false);
6661
+ setActiveCommands(/* @__PURE__ */ new Set());
6662
+ }, []);
6663
+ const commitNavigationTextEdit = (0, import_react6.useCallback)((navAnchor) => {
6664
+ const el = activeElRef.current;
6665
+ if (!el) return;
6666
+ const key = el.dataset.ohwKey;
6667
+ if (key) {
6668
+ const timer = autoSaveTimers.current.get(key);
6669
+ if (timer !== void 0) {
6670
+ clearTimeout(timer);
6671
+ autoSaveTimers.current.delete(key);
6672
+ }
6673
+ const html = sanitizeHtml(el.innerHTML);
6674
+ const original = originalContentRef.current ?? "";
6675
+ if (html !== sanitizeHtml(original)) {
6676
+ postToParent({ type: "ow:change", nodes: [{ key, text: html }] });
6677
+ const h = document.documentElement.scrollHeight;
6678
+ if (h > 50) postToParent({ type: "ow:height", height: h });
6679
+ }
6680
+ }
6681
+ el.removeAttribute("contenteditable");
6682
+ activeElRef.current = null;
6683
+ setMaxBadge(null);
6684
+ setActiveCommands(/* @__PURE__ */ new Set());
6685
+ setToolbarShowEditLink(false);
6686
+ postToParent({ type: "ow:exit-edit" });
6687
+ reselectNavigationItem(navAnchor);
6688
+ }, [postToParent, reselectNavigationItem]);
6689
+ const handleAddNavigationItem = (0, import_react6.useCallback)(() => {
6690
+ const selected = selectedElRef.current;
6691
+ if (!selected) return;
6692
+ const target = getNavigationItemAddHintTarget(selected);
6693
+ siblingHintElRef.current = target;
6694
+ setSiblingHintRect(target.getBoundingClientRect());
6695
+ }, []);
6696
+ const handleItemDragStart = (0, import_react6.useCallback)(() => {
6697
+ siblingHintElRef.current = null;
6698
+ setSiblingHintRect(null);
6699
+ setIsItemDragging(true);
6700
+ }, []);
6701
+ const handleItemDragEnd = (0, import_react6.useCallback)(() => {
6702
+ setIsItemDragging(false);
6703
+ }, []);
6704
+ reselectNavigationItemRef.current = reselectNavigationItem;
6705
+ commitNavigationTextEditRef.current = commitNavigationTextEdit;
6342
6706
  const select = (0, import_react6.useCallback)((anchor) => {
6343
- if (!isNavbarButton(anchor)) return;
6707
+ if (!isNavigationItem(anchor)) return;
6344
6708
  if (activeElRef.current) deactivate();
6345
6709
  selectedElRef.current = anchor;
6346
6710
  clearHrefKeyHover(anchor);
6711
+ setHoveredItemRect(null);
6712
+ hoveredItemElRef.current = null;
6713
+ siblingHintElRef.current = null;
6714
+ setSiblingHintRect(null);
6715
+ setIsItemDragging(false);
6716
+ const { key, disabled } = getNavigationItemReorderState(anchor);
6717
+ setReorderHrefKey(key);
6718
+ setReorderDragDisabled(disabled);
6347
6719
  setToolbarVariant("link-action");
6348
6720
  setToolbarRect(anchor.getBoundingClientRect());
6349
6721
  setToolbarShowEditLink(false);
@@ -6358,13 +6730,26 @@ function OhhwellsBridge() {
6358
6730
  postToParentRef.current({ type: "ow:image-unhover" });
6359
6731
  }
6360
6732
  setToolbarVariant("rich-text");
6733
+ siblingHintElRef.current = null;
6734
+ setSiblingHintRect(null);
6735
+ setIsItemDragging(false);
6361
6736
  el.setAttribute("contenteditable", "true");
6362
6737
  el.removeAttribute("data-ohw-hovered");
6738
+ el.closest("[data-ohw-href-key]")?.removeAttribute("data-ohw-hovered");
6363
6739
  activeElRef.current = el;
6364
6740
  originalContentRef.current = el.innerHTML;
6365
6741
  el.focus();
6366
- setToolbarRect(el.getBoundingClientRect());
6367
6742
  setToolbarShowEditLink(Boolean(getHrefKeyFromElement(el)));
6743
+ const navAnchor = getNavigationItemAnchor(el);
6744
+ if (navAnchor) {
6745
+ setReorderHrefKey(null);
6746
+ setReorderDragDisabled(false);
6747
+ } else {
6748
+ const { key: reorderKey, disabled: reorderDisabled } = getReorderHandleState(el);
6749
+ setReorderHrefKey(reorderKey);
6750
+ setReorderDragDisabled(reorderDisabled);
6751
+ }
6752
+ setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
6368
6753
  postToParent({ type: "ow:enter-edit", key: el.dataset.ohwKey });
6369
6754
  requestAnimationFrame(() => refreshActiveCommandsRef.current());
6370
6755
  }, [deactivate, postToParent]);
@@ -6556,18 +6941,25 @@ function OhhwellsBridge() {
6556
6941
  [data-ohw-editable="image"], [data-ohw-editable="image"] *,
6557
6942
  [data-ohw-editable="bg-image"], [data-ohw-editable="bg-image"] * { cursor: pointer !important; }
6558
6943
  [data-ohw-editable="link"], [data-ohw-editable="link"] * { cursor: pointer !important; }
6559
- [data-ohw-hovered]:not([contenteditable]) {
6560
- outline: 2px dashed ${PRIMARY} !important;
6944
+ [data-ohw-hovered]:not([contenteditable]):not([data-ohw-href-key]) {
6945
+ outline: 2px dashed ${PRIMARY2} !important;
6561
6946
  outline-offset: 4px;
6562
6947
  border-radius: 2px;
6563
6948
  }
6949
+ [data-ohw-href-key] [data-ohw-hovered],
6950
+ [data-ohw-href-key][data-ohw-hovered],
6951
+ nav [data-ohw-href-key] [data-ohw-hovered],
6952
+ footer [data-ohw-href-key] [data-ohw-hovered] {
6953
+ outline: none !important;
6954
+ outline-offset: 0 !important;
6955
+ }
6564
6956
  [data-ohw-editable][contenteditable] {
6565
6957
  outline: none !important;
6566
- caret-color: ${PRIMARY};
6958
+ caret-color: ${PRIMARY2};
6567
6959
  cursor: text !important;
6568
6960
  }
6569
6961
  [data-ohw-editable][contenteditable]::selection,
6570
- [data-ohw-editable][contenteditable] *::selection { background: ${PRIMARY}59 !important; }
6962
+ [data-ohw-editable][contenteditable] *::selection { background: ${PRIMARY2}59 !important; }
6571
6963
  [data-ohw-editable-state], [data-ohw-editable-state] * { pointer-events: none !important; }
6572
6964
  [data-ohw-editable-state][data-ohw-active-state] [data-ohw-editable] { pointer-events: auto !important; }
6573
6965
  [data-ohw-editable-state][data-ohw-active-state][data-ohw-editable] { pointer-events: auto !important; }
@@ -6579,7 +6971,7 @@ function OhhwellsBridge() {
6579
6971
  stateViews.textContent = `
6580
6972
  [data-ohw-state-view]:not([data-ohw-state-view="default"]) { display: none; }
6581
6973
  [data-ohw-state-view="default"] [data-ohw-editable] { pointer-events: auto !important; }
6582
- [data-ohw-state-hovered] { outline: 2px dashed ${PRIMARY} !important; outline-offset: 4px; border-radius: 2px; }
6974
+ [data-ohw-state-hovered] { outline: 2px dashed ${PRIMARY2} !important; outline-offset: 4px; border-radius: 2px; }
6583
6975
  [data-ohw-state-hovered]:has([data-ohw-hovered]) { outline: none !important; }
6584
6976
  `;
6585
6977
  document.head.appendChild(base);
@@ -6594,6 +6986,11 @@ function OhhwellsBridge() {
6594
6986
  if (target.closest("[data-ohw-state-toggle]")) return;
6595
6987
  if (target.closest("[data-ohw-max-badge]")) return;
6596
6988
  if (isInsideLinkEditor(target)) return;
6989
+ if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
6990
+ e.preventDefault();
6991
+ e.stopPropagation();
6992
+ return;
6993
+ }
6597
6994
  const editable = target.closest("[data-ohw-editable]");
6598
6995
  if (editable) {
6599
6996
  if (editable.dataset.ohwEditable === "link") {
@@ -6615,15 +7012,15 @@ function OhhwellsBridge() {
6615
7012
  return;
6616
7013
  }
6617
7014
  const hrefCtx = getHrefKeyFromElement(editable);
6618
- if (hrefCtx && isNavbarButton(hrefCtx.anchor)) {
7015
+ const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
7016
+ if (navAnchor) {
6619
7017
  e.preventDefault();
6620
7018
  e.stopPropagation();
6621
- const { anchor: anchor2 } = hrefCtx;
6622
- if (selectedElRef.current === anchor2) {
7019
+ if (selectedElRef.current === navAnchor) {
6623
7020
  activateRef.current(editable);
6624
7021
  return;
6625
7022
  }
6626
- selectRef.current(anchor2);
7023
+ selectRef.current(navAnchor);
6627
7024
  return;
6628
7025
  }
6629
7026
  e.preventDefault();
@@ -6631,8 +7028,8 @@ function OhhwellsBridge() {
6631
7028
  activateRef.current(editable);
6632
7029
  return;
6633
7030
  }
6634
- const hrefAnchor = target.closest("[data-ohw-href-key]");
6635
- if (hrefAnchor && isNavbarButton(hrefAnchor)) {
7031
+ const hrefAnchor = getNavigationItemAnchor(target);
7032
+ if (hrefAnchor) {
6636
7033
  e.preventDefault();
6637
7034
  e.stopPropagation();
6638
7035
  if (selectedElRef.current === hrefAnchor) return;
@@ -6665,19 +7062,58 @@ function OhhwellsBridge() {
6665
7062
  deactivateRef.current();
6666
7063
  };
6667
7064
  const handleMouseOver = (e) => {
6668
- const editable = e.target.closest("[data-ohw-editable]");
7065
+ const target = e.target;
7066
+ const navAnchor = getNavigationItemAnchor(target);
7067
+ if (navAnchor) {
7068
+ const selected2 = selectedElRef.current;
7069
+ if (selected2 === navAnchor || selected2?.contains(navAnchor)) return;
7070
+ clearHrefKeyHover(navAnchor);
7071
+ hoveredItemElRef.current = navAnchor;
7072
+ setHoveredItemRect(navAnchor.getBoundingClientRect());
7073
+ return;
7074
+ }
7075
+ const editable = target.closest("[data-ohw-editable]");
6669
7076
  if (!editable) return;
6670
7077
  const selected = selectedElRef.current;
6671
7078
  if (selected && (selected === editable || selected.contains(editable))) return;
6672
7079
  if (editable.dataset.ohwEditable !== "image" && editable.dataset.ohwEditable !== "bg-image" && !editable.hasAttribute("contenteditable")) {
6673
- editable.setAttribute("data-ohw-hovered", "");
7080
+ const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
7081
+ if (hoverTarget.hasAttribute("data-ohw-href-key")) {
7082
+ clearHrefKeyHover(hoverTarget);
7083
+ hoveredItemElRef.current = hoverTarget;
7084
+ setHoveredItemRect(hoverTarget.getBoundingClientRect());
7085
+ } else if (!isInsideNavigationItem(editable)) {
7086
+ hoverTarget.setAttribute("data-ohw-hovered", "");
7087
+ }
6674
7088
  }
6675
7089
  };
6676
7090
  const handleMouseOut = (e) => {
6677
- const editable = e.target.closest("[data-ohw-editable]");
7091
+ const target = e.target;
7092
+ const navAnchor = getNavigationItemAnchor(target);
7093
+ if (navAnchor) {
7094
+ const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
7095
+ if (related2?.closest("[data-ohw-drag-handle-container], [data-ohw-item-interaction]")) return;
7096
+ if (related2 && navAnchor.contains(related2)) return;
7097
+ if (hoveredItemElRef.current === navAnchor) {
7098
+ hoveredItemElRef.current = null;
7099
+ setHoveredItemRect(null);
7100
+ }
7101
+ return;
7102
+ }
7103
+ const editable = target.closest("[data-ohw-editable]");
6678
7104
  if (!editable) return;
7105
+ const related = e.relatedTarget instanceof Element ? e.relatedTarget : null;
7106
+ if (related?.closest("[data-ohw-drag-handle-container], [data-ohw-item-interaction]")) return;
6679
7107
  if (editable.dataset.ohwEditable !== "image" && editable.dataset.ohwEditable !== "bg-image") {
6680
- editable.removeAttribute("data-ohw-hovered");
7108
+ const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
7109
+ if (hoverTarget.hasAttribute("data-ohw-href-key")) {
7110
+ if (!related?.closest("[data-ohw-href-key]")) {
7111
+ hoveredItemElRef.current = null;
7112
+ setHoveredItemRect(null);
7113
+ }
7114
+ } else {
7115
+ hoverTarget.removeAttribute("data-ohw-hovered");
7116
+ }
6681
7117
  }
6682
7118
  };
6683
7119
  const toProbeCoords = (clientX, clientY, fromParentViewport) => {
@@ -6792,11 +7228,20 @@ function OhhwellsBridge() {
6792
7228
  return;
6793
7229
  }
6794
7230
  }
7231
+ if (activeElRef.current) {
7232
+ if (hoveredImageRef.current) {
7233
+ hoveredImageRef.current = null;
7234
+ hoveredImageHasTextOverlapRef.current = false;
7235
+ resumeAnimTracks();
7236
+ postToParentRef.current({ type: "ow:image-unhover" });
7237
+ }
7238
+ return;
7239
+ }
6795
7240
  const imgEl = findImageAtPoint(clientX, clientY, fromParentViewport);
6796
7241
  if (imgEl) {
6797
7242
  const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
6798
7243
  const topEl = document.elementFromPoint(x, y);
6799
- if (topEl?.closest("[data-ohw-toolbar]")) {
7244
+ if (topEl?.closest('[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
6800
7245
  if (hoveredImageRef.current) {
6801
7246
  hoveredImageRef.current = null;
6802
7247
  resumeAnimTracks();
@@ -6844,7 +7289,9 @@ function OhhwellsBridge() {
6844
7289
  postImageHover(imgEl, isDragOver, true);
6845
7290
  }
6846
7291
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
6847
- textEditable.setAttribute("data-ohw-hovered", "");
7292
+ if (textEditable && !isInsideNavigationItem(textEditable)) {
7293
+ textEditable.setAttribute("data-ohw-hovered", "");
7294
+ }
6848
7295
  return;
6849
7296
  }
6850
7297
  if (hoveredImageRef.current) {
@@ -6854,7 +7301,9 @@ function OhhwellsBridge() {
6854
7301
  postToParentRef.current({ type: "ow:image-unhover" });
6855
7302
  }
6856
7303
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
6857
- textEditable.setAttribute("data-ohw-hovered", "");
7304
+ if (textEditable && !isInsideNavigationItem(textEditable)) {
7305
+ textEditable.setAttribute("data-ohw-hovered", "");
7306
+ }
6858
7307
  return;
6859
7308
  }
6860
7309
  if (hoveredGapRef.current) {
@@ -6898,7 +7347,24 @@ function OhhwellsBridge() {
6898
7347
  return x >= er.left && x <= er.right && y >= er.top && y <= er.bottom;
6899
7348
  });
6900
7349
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
6901
- if (textEl && !textEl.hasAttribute("contenteditable")) textEl.setAttribute("data-ohw-hovered", "");
7350
+ if (textEl && !textEl.hasAttribute("contenteditable")) {
7351
+ const navAnchor = getNavigationItemAnchor(textEl);
7352
+ if (navAnchor) {
7353
+ const selected = selectedElRef.current;
7354
+ if (selected !== navAnchor && !selected?.contains(navAnchor)) {
7355
+ clearHrefKeyHover(navAnchor);
7356
+ hoveredItemElRef.current = navAnchor;
7357
+ setHoveredItemRect(navAnchor.getBoundingClientRect());
7358
+ }
7359
+ } else {
7360
+ hoveredItemElRef.current = null;
7361
+ setHoveredItemRect(null);
7362
+ textEl.setAttribute("data-ohw-hovered", "");
7363
+ }
7364
+ } else {
7365
+ hoveredItemElRef.current = null;
7366
+ setHoveredItemRect(null);
7367
+ }
6902
7368
  }
6903
7369
  };
6904
7370
  const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
@@ -7089,7 +7555,7 @@ function OhhwellsBridge() {
7089
7555
  const el = e.target;
7090
7556
  const key = el.dataset.ohwKey;
7091
7557
  if (!key) return;
7092
- if (el === activeElRef.current) setToolbarRect(el.getBoundingClientRect());
7558
+ if (el === activeElRef.current) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
7093
7559
  const maxLen = el.dataset.ohwMaxLength ? parseInt(el.dataset.ohwMaxLength, 10) : null;
7094
7560
  if (maxLen) {
7095
7561
  const current = el.innerText.replace(/\n$/, "").length;
@@ -7176,6 +7642,33 @@ function OhhwellsBridge() {
7176
7642
  deselectRef.current();
7177
7643
  return;
7178
7644
  }
7645
+ if (e.key === "Escape" && activeElRef.current) {
7646
+ const hrefCtx = getHrefKeyFromElement(activeElRef.current);
7647
+ const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
7648
+ if (navAnchor) {
7649
+ e.preventDefault();
7650
+ const el2 = activeElRef.current;
7651
+ if (originalContentRef.current !== null) {
7652
+ el2.innerHTML = originalContentRef.current;
7653
+ }
7654
+ el2.removeAttribute("contenteditable");
7655
+ activeElRef.current = null;
7656
+ setMaxBadge(null);
7657
+ setActiveCommands(/* @__PURE__ */ new Set());
7658
+ setToolbarShowEditLink(false);
7659
+ postToParentRef.current({ type: "ow:exit-edit" });
7660
+ reselectNavigationItemRef.current(navAnchor);
7661
+ return;
7662
+ }
7663
+ }
7664
+ if (e.key === "Enter" && !e.shiftKey && activeElRef.current) {
7665
+ const navAnchor = getNavigationItemAnchor(activeElRef.current);
7666
+ if (navAnchor) {
7667
+ e.preventDefault();
7668
+ commitNavigationTextEditRef.current(navAnchor);
7669
+ return;
7670
+ }
7671
+ }
7179
7672
  if (e.key !== "Escape") return;
7180
7673
  const el = activeElRef.current;
7181
7674
  if (el && originalContentRef.current !== null) {
@@ -7191,7 +7684,8 @@ function OhhwellsBridge() {
7191
7684
  const handleScroll = () => {
7192
7685
  const focusEl = activeElRef.current ?? selectedElRef.current;
7193
7686
  if (focusEl) {
7194
- const r2 = focusEl.getBoundingClientRect();
7687
+ const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : focusEl;
7688
+ const r2 = measureEl.getBoundingClientRect();
7195
7689
  applyToolbarPos(r2);
7196
7690
  setToolbarRect(r2);
7197
7691
  setMaxBadge((prev) => prev && activeElRef.current ? { ...prev, rect: r2 } : prev);
@@ -7200,6 +7694,12 @@ function OhhwellsBridge() {
7200
7694
  const rect = activeStateElRef.current.getBoundingClientRect();
7201
7695
  setToggleState((prev) => prev ? { ...prev, rect } : null);
7202
7696
  }
7697
+ if (hoveredItemElRef.current) {
7698
+ setHoveredItemRect(hoveredItemElRef.current.getBoundingClientRect());
7699
+ }
7700
+ if (siblingHintElRef.current) {
7701
+ setSiblingHintRect(siblingHintElRef.current.getBoundingClientRect());
7702
+ }
7203
7703
  if (hoveredImageRef.current) {
7204
7704
  const el = hoveredImageRef.current;
7205
7705
  const r2 = el.getBoundingClientRect();
@@ -7319,7 +7819,7 @@ function OhhwellsBridge() {
7319
7819
  };
7320
7820
  const applyToolbarPos = (rect) => {
7321
7821
  const ps = parentScrollRef.current;
7322
- const approxW = toolbarVariantRef.current === "link-action" ? 120 : 330;
7822
+ const approxW = 330;
7323
7823
  if (toolbarElRef.current) {
7324
7824
  const { top, left, transform } = calcToolbarPos(rect, ps, approxW);
7325
7825
  toolbarElRef.current.style.top = `${top}px`;
@@ -7330,6 +7830,8 @@ function OhhwellsBridge() {
7330
7830
  const GAP = 6;
7331
7831
  glowElRef.current.style.top = `${rect.top - GAP}px`;
7332
7832
  glowElRef.current.style.left = `${rect.left - GAP}px`;
7833
+ glowElRef.current.style.width = `${rect.width + GAP * 2}px`;
7834
+ glowElRef.current.style.height = `${rect.height + GAP * 2}px`;
7333
7835
  }
7334
7836
  };
7335
7837
  const handleParentScroll = (e) => {
@@ -7340,7 +7842,10 @@ function OhhwellsBridge() {
7340
7842
  applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
7341
7843
  }
7342
7844
  const focusEl = activeElRef.current ?? selectedElRef.current;
7343
- if (focusEl) applyToolbarPos(focusEl.getBoundingClientRect());
7845
+ if (focusEl) {
7846
+ const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : focusEl;
7847
+ applyToolbarPos(measureEl.getBoundingClientRect());
7848
+ }
7344
7849
  };
7345
7850
  const handleClickAt = (e) => {
7346
7851
  if (e.data?.type !== "ow:click-at") return;
@@ -7498,7 +8003,7 @@ function OhhwellsBridge() {
7498
8003
  const handleCommand = (0, import_react6.useCallback)((cmd) => {
7499
8004
  document.execCommand(cmd, false);
7500
8005
  activeElRef.current?.focus();
7501
- if (activeElRef.current) setToolbarRect(activeElRef.current.getBoundingClientRect());
8006
+ if (activeElRef.current) setToolbarRect(getEditMeasureEl(activeElRef.current).getBoundingClientRect());
7502
8007
  refreshActiveCommandsRef.current();
7503
8008
  }, []);
7504
8009
  const handleStateChange = (0, import_react6.useCallback)((state) => {
@@ -7551,37 +8056,55 @@ function OhhwellsBridge() {
7551
8056
  const currentSections = sectionsByPath[pathname] ?? [];
7552
8057
  linkPopoverOpenRef.current = linkPopover !== null;
7553
8058
  return bridgeRoot ? (0, import_react_dom2.createPortal)(
7554
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
7555
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
7556
- toolbarRect && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
7557
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(GlowFrame, { rect: toolbarRect, elRef: glowElRef }),
7558
- toolbarVariant === "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
7559
- FloatingToolbar,
8059
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
8060
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
8061
+ siblingHintRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
8062
+ hoveredItemRect && !siblingHintRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
8063
+ toolbarRect && toolbarVariant === "link-action" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
8064
+ ItemInteractionLayer,
8065
+ {
8066
+ rect: toolbarRect,
8067
+ elRef: glowElRef,
8068
+ state: isItemDragging ? "dragging" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
8069
+ showHandle: Boolean(reorderHrefKey),
8070
+ dragDisabled: reorderDragDisabled,
8071
+ dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
8072
+ onDragHandleDragStart: handleItemDragStart,
8073
+ onDragHandleDragEnd: handleItemDragEnd,
8074
+ toolbar: isItemDragging ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
8075
+ ItemActionToolbar,
8076
+ {
8077
+ onEditLink: openLinkPopoverForSelected,
8078
+ onAddItem: handleAddNavigationItem,
8079
+ addItemDisabled: false
8080
+ }
8081
+ )
8082
+ }
8083
+ ),
8084
+ toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
8085
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
8086
+ EditGlowChrome,
7560
8087
  {
7561
- variant: "rich-text",
7562
8088
  rect: toolbarRect,
7563
- parentScroll: parentScrollRef.current,
7564
- elRef: toolbarElRef,
7565
- onCommand: handleCommand,
7566
- activeCommands,
7567
- showEditLink,
7568
- onEditLink: openLinkPopoverForActive
8089
+ elRef: glowElRef,
8090
+ reorderHrefKey,
8091
+ dragDisabled: reorderDragDisabled
7569
8092
  }
7570
8093
  ),
7571
- toolbarVariant === "link-action" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
8094
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7572
8095
  FloatingToolbar,
7573
8096
  {
7574
- variant: "link-action",
7575
8097
  rect: toolbarRect,
7576
8098
  parentScroll: parentScrollRef.current,
7577
8099
  elRef: toolbarElRef,
7578
8100
  onCommand: handleCommand,
7579
8101
  activeCommands,
7580
- onEditLink: openLinkPopoverForSelected
8102
+ showEditLink,
8103
+ onEditLink: openLinkPopoverForActive
7581
8104
  }
7582
8105
  )
7583
8106
  ] }),
7584
- maxBadge && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
8107
+ maxBadge && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
7585
8108
  "div",
7586
8109
  {
7587
8110
  "data-ohw-max-badge": "",
@@ -7607,7 +8130,7 @@ function OhhwellsBridge() {
7607
8130
  ]
7608
8131
  }
7609
8132
  ),
7610
- toggleState && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
8133
+ toggleState && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7611
8134
  StateToggle,
7612
8135
  {
7613
8136
  rect: toggleState.rect,
@@ -7616,15 +8139,15 @@ function OhhwellsBridge() {
7616
8139
  onStateChange: handleStateChange
7617
8140
  }
7618
8141
  ),
7619
- sectionGap && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
8142
+ sectionGap && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
7620
8143
  "div",
7621
8144
  {
7622
8145
  "data-ohw-section-insert-line": "",
7623
8146
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
7624
8147
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
7625
8148
  children: [
7626
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
7627
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
8149
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
8150
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7628
8151
  Badge,
7629
8152
  {
7630
8153
  className: "px-8 py-1 bg-primary hover:bg-primary text-primary-foreground text-xs font-medium shrink-0 rounded-full cursor-pointer pointer-events-auto",
@@ -7637,11 +8160,11 @@ function OhhwellsBridge() {
7637
8160
  children: "Add Section"
7638
8161
  }
7639
8162
  ),
7640
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
8163
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
7641
8164
  ]
7642
8165
  }
7643
8166
  ),
7644
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
8167
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7645
8168
  LinkPopover,
7646
8169
  {
7647
8170
  panelRef: linkPopoverPanelRef,
@@ -7663,6 +8186,12 @@ function OhhwellsBridge() {
7663
8186
  }
7664
8187
  // Annotate the CommonJS export names for ESM import in node:
7665
8188
  0 && (module.exports = {
8189
+ CustomToolbar,
8190
+ CustomToolbarButton,
8191
+ CustomToolbarDivider,
8192
+ DragHandle,
8193
+ ItemActionToolbar,
8194
+ ItemInteractionLayer,
7666
8195
  LinkEditorPanel,
7667
8196
  LinkPopover,
7668
8197
  OhhwellsBridge,
@@ -7670,9 +8199,14 @@ function OhhwellsBridge() {
7670
8199
  Toggle,
7671
8200
  ToggleGroup,
7672
8201
  ToggleGroupItem,
8202
+ Tooltip,
8203
+ TooltipContent,
8204
+ TooltipProvider,
8205
+ TooltipTrigger,
7673
8206
  buildTarget,
7674
8207
  filterAvailablePages,
7675
8208
  getEditModeInitialState,
8209
+ isEditSessionActive,
7676
8210
  isValidUrl,
7677
8211
  parseTarget,
7678
8212
  toggleVariants,