@ohhwells/bridge 0.1.43 → 0.1.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +2742 -480
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +30 -4
- package/dist/index.d.ts +30 -4
- package/dist/index.js +2746 -484
- package/dist/index.js.map +1 -1
- package/dist/styles.css +56 -49
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
// src/OhhwellsBridge.tsx
|
|
4
|
-
import
|
|
4
|
+
import React11, { useCallback as useCallback4, useEffect as useEffect8, useLayoutEffect as useLayoutEffect3, useRef as useRef7, useState as useState7 } from "react";
|
|
5
5
|
import { createRoot } from "react-dom/client";
|
|
6
6
|
import { flushSync } from "react-dom";
|
|
7
7
|
|
|
@@ -4242,7 +4242,8 @@ var CustomToolbar = React4.forwardRef(({ className, onMouseDown, ...props }, ref
|
|
|
4242
4242
|
ref,
|
|
4243
4243
|
"data-ohw-toolbar": "",
|
|
4244
4244
|
className: cn(
|
|
4245
|
-
|
|
4245
|
+
// Figma: bg background, radius 8, gap-1, p-0.5, shadow-md — no border
|
|
4246
|
+
"inline-flex h-8 items-center gap-1 rounded-[var(--radius,0.5rem)] bg-background p-0.5 font-sans whitespace-nowrap shadow-md",
|
|
4246
4247
|
className
|
|
4247
4248
|
),
|
|
4248
4249
|
onMouseDown: (e) => {
|
|
@@ -4270,8 +4271,8 @@ var CustomToolbarButton = React4.forwardRef(
|
|
|
4270
4271
|
ref,
|
|
4271
4272
|
type,
|
|
4272
4273
|
className: cn(
|
|
4273
|
-
"inline-flex shrink-0 items-center justify-center rounded
|
|
4274
|
-
active ? "bg-primary text-primary-foreground" : "bg-transparent
|
|
4274
|
+
"inline-flex size-7 shrink-0 items-center justify-center rounded-[calc(var(--radius,0.5rem)-2px)] text-foreground transition-colors",
|
|
4275
|
+
active ? "bg-primary text-primary-foreground" : "bg-transparent hover:bg-muted disabled:cursor-not-allowed disabled:text-muted-foreground disabled:opacity-60",
|
|
4275
4276
|
className
|
|
4276
4277
|
),
|
|
4277
4278
|
...props
|
|
@@ -4306,9 +4307,10 @@ var arrowClassBySide = {
|
|
|
4306
4307
|
};
|
|
4307
4308
|
function TooltipContent({
|
|
4308
4309
|
className,
|
|
4309
|
-
sideOffset =
|
|
4310
|
+
sideOffset = 9,
|
|
4310
4311
|
side = "bottom",
|
|
4311
4312
|
children,
|
|
4313
|
+
hideArrow,
|
|
4312
4314
|
...props
|
|
4313
4315
|
}) {
|
|
4314
4316
|
const resolvedSide = side ?? "bottom";
|
|
@@ -4319,12 +4321,13 @@ function TooltipContent({
|
|
|
4319
4321
|
side,
|
|
4320
4322
|
sideOffset,
|
|
4321
4323
|
className: cn(
|
|
4322
|
-
"relative z-[2147483647] w-fit max-w-xs rounded-md bg-foreground px-3 py-1.5 text-xs text-background
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
"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",
|
|
4324
|
+
"relative z-[2147483647] inline-flex w-fit max-w-xs items-center rounded-md bg-foreground px-3 py-1.5 text-xs text-background",
|
|
4325
|
+
"origin-[var(--radix-tooltip-content-transform-origin)] animate-in fade-in-0 zoom-in-95",
|
|
4326
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
4326
4327
|
"data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2",
|
|
4327
4328
|
"data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2",
|
|
4329
|
+
!hideArrow && 'before:pointer-events-none before:absolute before:size-2 before:rotate-45 before:bg-foreground before:content-[""]',
|
|
4330
|
+
!hideArrow && arrowClassBySide[resolvedSide],
|
|
4328
4331
|
className
|
|
4329
4332
|
),
|
|
4330
4333
|
...props,
|
|
@@ -4345,7 +4348,7 @@ function ToolbarActionTooltip({
|
|
|
4345
4348
|
const button = /* @__PURE__ */ jsx8(CustomToolbarButton, { type: "button", "aria-label": label, disabled, ...buttonProps, children });
|
|
4346
4349
|
return /* @__PURE__ */ jsxs3(Tooltip, { children: [
|
|
4347
4350
|
/* @__PURE__ */ jsx8(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ jsx8("span", { className: "inline-flex", children: button }) : button }),
|
|
4348
|
-
/* @__PURE__ */ jsx8(TooltipContent, { side, children: label })
|
|
4351
|
+
/* @__PURE__ */ jsx8(TooltipContent, { side, sideOffset: 9, children: label })
|
|
4349
4352
|
] });
|
|
4350
4353
|
}
|
|
4351
4354
|
function ItemActionToolbar({
|
|
@@ -4355,6 +4358,8 @@ function ItemActionToolbar({
|
|
|
4355
4358
|
editLinkDisabled = false,
|
|
4356
4359
|
addItemDisabled = true,
|
|
4357
4360
|
moreDisabled = true,
|
|
4361
|
+
showAddItem = true,
|
|
4362
|
+
showMore = true,
|
|
4358
4363
|
tooltipSide = "bottom"
|
|
4359
4364
|
}) {
|
|
4360
4365
|
return /* @__PURE__ */ jsx8(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs3(CustomToolbar, { children: [
|
|
@@ -4379,8 +4384,7 @@ function ItemActionToolbar({
|
|
|
4379
4384
|
children: /* @__PURE__ */ jsx8(Link, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
4380
4385
|
}
|
|
4381
4386
|
),
|
|
4382
|
-
/* @__PURE__ */ jsx8(
|
|
4383
|
-
/* @__PURE__ */ jsx8(
|
|
4387
|
+
showAddItem ? /* @__PURE__ */ jsx8(
|
|
4384
4388
|
ToolbarActionTooltip,
|
|
4385
4389
|
{
|
|
4386
4390
|
label: "Add item",
|
|
@@ -4396,9 +4400,8 @@ function ItemActionToolbar({
|
|
|
4396
4400
|
},
|
|
4397
4401
|
children: /* @__PURE__ */ jsx8(Plus, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
4398
4402
|
}
|
|
4399
|
-
),
|
|
4400
|
-
/* @__PURE__ */ jsx8(
|
|
4401
|
-
/* @__PURE__ */ jsx8(
|
|
4403
|
+
) : null,
|
|
4404
|
+
showMore ? /* @__PURE__ */ jsx8(
|
|
4402
4405
|
ToolbarActionTooltip,
|
|
4403
4406
|
{
|
|
4404
4407
|
label: "More",
|
|
@@ -4414,15 +4417,32 @@ function ItemActionToolbar({
|
|
|
4414
4417
|
},
|
|
4415
4418
|
children: /* @__PURE__ */ jsx8(MoreHorizontal, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
4416
4419
|
}
|
|
4417
|
-
)
|
|
4420
|
+
) : null
|
|
4418
4421
|
] }) });
|
|
4419
4422
|
}
|
|
4420
4423
|
|
|
4421
4424
|
// src/ui/item-interaction-layer.tsx
|
|
4425
|
+
import * as React5 from "react";
|
|
4422
4426
|
import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
4423
4427
|
var PRIMARY = "var(--ohw-primary, #0885FE)";
|
|
4424
|
-
var FOCUS_RING =
|
|
4428
|
+
var FOCUS_RING = `0 0 0 4px color-mix(in srgb, ${PRIMARY} 12%, transparent)`;
|
|
4425
4429
|
var DRAG_SHADOW = "0px 4px 6px -1px rgba(0, 0, 0, 0.1), 0px 2px 4px -2px rgba(0, 0, 0, 0.1)";
|
|
4430
|
+
var TOOLBAR_EDGE_MARGIN = 4;
|
|
4431
|
+
var SELECTION_CHROME_GAP = 4;
|
|
4432
|
+
var TOOLBAR_STROKE_GAP = 4;
|
|
4433
|
+
function getChromeZIndex(state) {
|
|
4434
|
+
switch (state) {
|
|
4435
|
+
case "active-top":
|
|
4436
|
+
case "active-bottom":
|
|
4437
|
+
case "dragging":
|
|
4438
|
+
return 2147483644;
|
|
4439
|
+
case "hover":
|
|
4440
|
+
case "sibling-hint":
|
|
4441
|
+
return 2147483643;
|
|
4442
|
+
default:
|
|
4443
|
+
return 2147483642;
|
|
4444
|
+
}
|
|
4445
|
+
}
|
|
4426
4446
|
function getChromeStyle(state) {
|
|
4427
4447
|
switch (state) {
|
|
4428
4448
|
case "hover":
|
|
@@ -4444,12 +4464,65 @@ function getChromeStyle(state) {
|
|
|
4444
4464
|
case "dragging":
|
|
4445
4465
|
return {
|
|
4446
4466
|
border: `2px solid ${PRIMARY}`,
|
|
4447
|
-
boxShadow: DRAG_SHADOW
|
|
4467
|
+
boxShadow: `${FOCUS_RING}, ${DRAG_SHADOW}`
|
|
4448
4468
|
};
|
|
4449
4469
|
default:
|
|
4450
4470
|
return {};
|
|
4451
4471
|
}
|
|
4452
4472
|
}
|
|
4473
|
+
function ClampedToolbarSlot({
|
|
4474
|
+
placement,
|
|
4475
|
+
children
|
|
4476
|
+
}) {
|
|
4477
|
+
const slotRef = React5.useRef(null);
|
|
4478
|
+
React5.useLayoutEffect(() => {
|
|
4479
|
+
const slot = slotRef.current;
|
|
4480
|
+
if (!slot) return;
|
|
4481
|
+
const clamp = () => {
|
|
4482
|
+
const toolbar = slot.firstElementChild;
|
|
4483
|
+
if (!toolbar) return;
|
|
4484
|
+
const w = toolbar.offsetWidth;
|
|
4485
|
+
if (w <= 0) return;
|
|
4486
|
+
const parent = slot.offsetParent;
|
|
4487
|
+
if (!parent) return;
|
|
4488
|
+
const parentRect = parent.getBoundingClientRect();
|
|
4489
|
+
const centerX = parentRect.left + parentRect.width / 2;
|
|
4490
|
+
const half = w / 2;
|
|
4491
|
+
const clampedCenter = Math.max(
|
|
4492
|
+
TOOLBAR_EDGE_MARGIN + half,
|
|
4493
|
+
Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN - half)
|
|
4494
|
+
);
|
|
4495
|
+
const offsetX = clampedCenter - centerX;
|
|
4496
|
+
slot.style.transform = `translateX(calc(-50% + ${offsetX}px))`;
|
|
4497
|
+
};
|
|
4498
|
+
clamp();
|
|
4499
|
+
const ro = new ResizeObserver(clamp);
|
|
4500
|
+
ro.observe(slot);
|
|
4501
|
+
if (slot.firstElementChild) ro.observe(slot.firstElementChild);
|
|
4502
|
+
window.addEventListener("resize", clamp);
|
|
4503
|
+
return () => {
|
|
4504
|
+
ro.disconnect();
|
|
4505
|
+
window.removeEventListener("resize", clamp);
|
|
4506
|
+
};
|
|
4507
|
+
}, [placement, children]);
|
|
4508
|
+
return /* @__PURE__ */ jsx9(
|
|
4509
|
+
"div",
|
|
4510
|
+
{
|
|
4511
|
+
ref: slotRef,
|
|
4512
|
+
className: cn(
|
|
4513
|
+
"pointer-events-auto absolute left-1/2",
|
|
4514
|
+
placement === "top" ? "bottom-full" : "top-full"
|
|
4515
|
+
),
|
|
4516
|
+
style: {
|
|
4517
|
+
marginBottom: placement === "top" ? TOOLBAR_STROKE_GAP : void 0,
|
|
4518
|
+
marginTop: placement === "bottom" ? TOOLBAR_STROKE_GAP : void 0,
|
|
4519
|
+
transform: "translateX(-50%)"
|
|
4520
|
+
},
|
|
4521
|
+
"data-ohw-item-toolbar-anchor": placement,
|
|
4522
|
+
children
|
|
4523
|
+
}
|
|
4524
|
+
);
|
|
4525
|
+
}
|
|
4453
4526
|
function ItemInteractionLayer({
|
|
4454
4527
|
rect,
|
|
4455
4528
|
state,
|
|
@@ -4460,14 +4533,18 @@ function ItemInteractionLayer({
|
|
|
4460
4533
|
dragHandleLabel = "Reorder item",
|
|
4461
4534
|
onDragHandleDragStart,
|
|
4462
4535
|
onDragHandleDragEnd,
|
|
4463
|
-
|
|
4536
|
+
onItemPointerDown,
|
|
4537
|
+
onItemClick,
|
|
4538
|
+
itemDragSurface = true,
|
|
4539
|
+
chromeGap = SELECTION_CHROME_GAP,
|
|
4464
4540
|
className
|
|
4465
4541
|
}) {
|
|
4466
4542
|
if (state === "default") return null;
|
|
4467
4543
|
const isActive = state === "active-top" || state === "active-bottom";
|
|
4468
4544
|
const isDragging = state === "dragging";
|
|
4469
4545
|
const showToolbar = isActive && toolbar;
|
|
4470
|
-
const showDragHandle = isActive
|
|
4546
|
+
const showDragHandle = (isActive || isDragging) && showHandle;
|
|
4547
|
+
const itemDragEnabled = itemDragSurface && isActive && showHandle && !isDragging && !dragDisabled;
|
|
4471
4548
|
return /* @__PURE__ */ jsxs4(
|
|
4472
4549
|
"div",
|
|
4473
4550
|
{
|
|
@@ -4481,7 +4558,7 @@ function ItemInteractionLayer({
|
|
|
4481
4558
|
left: rect.left - chromeGap,
|
|
4482
4559
|
width: rect.width + chromeGap * 2,
|
|
4483
4560
|
height: rect.height + chromeGap * 2,
|
|
4484
|
-
zIndex:
|
|
4561
|
+
zIndex: getChromeZIndex(state)
|
|
4485
4562
|
},
|
|
4486
4563
|
children: [
|
|
4487
4564
|
/* @__PURE__ */ jsx9(
|
|
@@ -4492,11 +4569,29 @@ function ItemInteractionLayer({
|
|
|
4492
4569
|
style: getChromeStyle(state)
|
|
4493
4570
|
}
|
|
4494
4571
|
),
|
|
4572
|
+
itemDragEnabled && /* @__PURE__ */ jsx9(
|
|
4573
|
+
"div",
|
|
4574
|
+
{
|
|
4575
|
+
"data-ohw-item-drag-surface": "",
|
|
4576
|
+
className: "pointer-events-auto absolute inset-0 cursor-text rounded-lg",
|
|
4577
|
+
onPointerDown: (e) => {
|
|
4578
|
+
if (e.button !== 0) return;
|
|
4579
|
+
onItemPointerDown?.(e);
|
|
4580
|
+
},
|
|
4581
|
+
onClick: (e) => {
|
|
4582
|
+
e.preventDefault();
|
|
4583
|
+
e.stopPropagation();
|
|
4584
|
+
onItemClick?.(e.clientX, e.clientY);
|
|
4585
|
+
}
|
|
4586
|
+
}
|
|
4587
|
+
),
|
|
4495
4588
|
showDragHandle && /* @__PURE__ */ jsx9(
|
|
4496
4589
|
"div",
|
|
4497
4590
|
{
|
|
4498
4591
|
"data-ohw-drag-handle-container": "",
|
|
4499
|
-
className: "pointer-events-auto absolute left-0 top-1/2 -translate-x-[calc(100%+7px)] -translate-y-1/2",
|
|
4592
|
+
className: "pointer-events-auto absolute left-0 top-1/2 z-10 -translate-x-[calc(100%+7px)] -translate-y-1/2",
|
|
4593
|
+
style: isDragging ? { opacity: 0 } : void 0,
|
|
4594
|
+
"aria-hidden": isDragging || void 0,
|
|
4500
4595
|
children: /* @__PURE__ */ jsx9(
|
|
4501
4596
|
DragHandle,
|
|
4502
4597
|
{
|
|
@@ -4508,7 +4603,17 @@ function ItemInteractionLayer({
|
|
|
4508
4603
|
e.preventDefault();
|
|
4509
4604
|
return;
|
|
4510
4605
|
}
|
|
4511
|
-
|
|
4606
|
+
const blank = document.createElement("canvas");
|
|
4607
|
+
blank.width = 1;
|
|
4608
|
+
blank.height = 1;
|
|
4609
|
+
blank.style.cssText = "position:fixed;left:-9999px;top:-9999px;width:1px;height:1px;pointer-events:none";
|
|
4610
|
+
document.body.appendChild(blank);
|
|
4611
|
+
try {
|
|
4612
|
+
e.dataTransfer.setDragImage(blank, 0, 0);
|
|
4613
|
+
} finally {
|
|
4614
|
+
requestAnimationFrame(() => blank.remove());
|
|
4615
|
+
}
|
|
4616
|
+
e.dataTransfer.setData("text/plain", dragHandleLabel);
|
|
4512
4617
|
e.dataTransfer.effectAllowed = "move";
|
|
4513
4618
|
onDragHandleDragStart?.(e);
|
|
4514
4619
|
},
|
|
@@ -4517,33 +4622,19 @@ function ItemInteractionLayer({
|
|
|
4517
4622
|
)
|
|
4518
4623
|
}
|
|
4519
4624
|
),
|
|
4520
|
-
showToolbar && state === "active-top" && /* @__PURE__ */ jsx9(
|
|
4521
|
-
|
|
4522
|
-
{
|
|
4523
|
-
className: "pointer-events-auto absolute bottom-full left-1/2 mb-2 -translate-x-1/2",
|
|
4524
|
-
"data-ohw-item-toolbar-anchor": "top",
|
|
4525
|
-
children: toolbar
|
|
4526
|
-
}
|
|
4527
|
-
),
|
|
4528
|
-
showToolbar && state === "active-bottom" && /* @__PURE__ */ jsx9(
|
|
4529
|
-
"div",
|
|
4530
|
-
{
|
|
4531
|
-
className: "pointer-events-auto absolute left-1/2 top-full mt-2 -translate-x-1/2",
|
|
4532
|
-
"data-ohw-item-toolbar-anchor": "bottom",
|
|
4533
|
-
children: toolbar
|
|
4534
|
-
}
|
|
4535
|
-
)
|
|
4625
|
+
showToolbar && state === "active-top" && /* @__PURE__ */ jsx9(ClampedToolbarSlot, { placement: "top", children: toolbar }),
|
|
4626
|
+
showToolbar && state === "active-bottom" && /* @__PURE__ */ jsx9(ClampedToolbarSlot, { placement: "bottom", children: toolbar })
|
|
4536
4627
|
]
|
|
4537
4628
|
}
|
|
4538
4629
|
);
|
|
4539
4630
|
}
|
|
4540
4631
|
|
|
4541
4632
|
// src/ui/MediaOverlay.tsx
|
|
4542
|
-
import * as
|
|
4633
|
+
import * as React7 from "react";
|
|
4543
4634
|
import { Film, ImageIcon, Pause, Play, Volume2, VolumeX } from "lucide-react";
|
|
4544
4635
|
|
|
4545
4636
|
// src/ui/button.tsx
|
|
4546
|
-
import * as
|
|
4637
|
+
import * as React6 from "react";
|
|
4547
4638
|
import { Slot } from "radix-ui";
|
|
4548
4639
|
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
4549
4640
|
var buttonVariants = cva(
|
|
@@ -4566,7 +4657,7 @@ var buttonVariants = cva(
|
|
|
4566
4657
|
}
|
|
4567
4658
|
}
|
|
4568
4659
|
);
|
|
4569
|
-
var Button =
|
|
4660
|
+
var Button = React6.forwardRef(
|
|
4570
4661
|
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
4571
4662
|
const Comp = asChild ? Slot.Root : "button";
|
|
4572
4663
|
return /* @__PURE__ */ jsx10(
|
|
@@ -4618,7 +4709,7 @@ function MediaOverlay({
|
|
|
4618
4709
|
onVideoSettingsChange
|
|
4619
4710
|
}) {
|
|
4620
4711
|
const { rect } = hover;
|
|
4621
|
-
const skeletonRef =
|
|
4712
|
+
const skeletonRef = React7.useRef(null);
|
|
4622
4713
|
const isVideo = hover.elementType === "video";
|
|
4623
4714
|
const autoplay = hover.videoAutoplay ?? true;
|
|
4624
4715
|
const muted = hover.videoMuted ?? true;
|
|
@@ -4630,7 +4721,7 @@ function MediaOverlay({
|
|
|
4630
4721
|
height: rect.height,
|
|
4631
4722
|
zIndex: 2147483646
|
|
4632
4723
|
};
|
|
4633
|
-
|
|
4724
|
+
React7.useEffect(() => {
|
|
4634
4725
|
if (!isUploading || !fadingOut || !skeletonRef.current) return;
|
|
4635
4726
|
const anim = skeletonRef.current.animate([{ opacity: 1 }, { opacity: 0 }], {
|
|
4636
4727
|
duration: MEDIA_UPLOAD_FADE_MS,
|
|
@@ -5035,7 +5126,7 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
|
|
|
5035
5126
|
import { useEffect as useEffect6 } from "react";
|
|
5036
5127
|
|
|
5037
5128
|
// src/ui/dialog.tsx
|
|
5038
|
-
import * as
|
|
5129
|
+
import * as React8 from "react";
|
|
5039
5130
|
import { Dialog as DialogPrimitive } from "radix-ui";
|
|
5040
5131
|
import { X } from "lucide-react";
|
|
5041
5132
|
import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
@@ -5063,7 +5154,7 @@ function DialogOverlay({
|
|
|
5063
5154
|
}
|
|
5064
5155
|
);
|
|
5065
5156
|
}
|
|
5066
|
-
var DialogContent =
|
|
5157
|
+
var DialogContent = React8.forwardRef(
|
|
5067
5158
|
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
5068
5159
|
const positionMode = container ? "absolute" : "fixed";
|
|
5069
5160
|
return /* @__PURE__ */ jsxs6(DialogPortal, { container: container ?? void 0, children: [
|
|
@@ -5118,7 +5209,7 @@ function DialogFooter({
|
|
|
5118
5209
|
}
|
|
5119
5210
|
);
|
|
5120
5211
|
}
|
|
5121
|
-
var DialogTitle =
|
|
5212
|
+
var DialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx12(
|
|
5122
5213
|
DialogPrimitive.Title,
|
|
5123
5214
|
{
|
|
5124
5215
|
ref,
|
|
@@ -5130,7 +5221,7 @@ var DialogTitle = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE
|
|
|
5130
5221
|
}
|
|
5131
5222
|
));
|
|
5132
5223
|
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
5133
|
-
var DialogDescription =
|
|
5224
|
+
var DialogDescription = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx12(
|
|
5134
5225
|
DialogPrimitive.Description,
|
|
5135
5226
|
{
|
|
5136
5227
|
ref,
|
|
@@ -5232,12 +5323,12 @@ function SectionTreeItem({
|
|
|
5232
5323
|
}
|
|
5233
5324
|
|
|
5234
5325
|
// src/ui/link-modal/UrlOrPageInput.tsx
|
|
5235
|
-
import { useEffect as useEffect3, useId as useId2, useRef as
|
|
5326
|
+
import { useEffect as useEffect3, useId as useId2, useRef as useRef4, useState as useState3 } from "react";
|
|
5236
5327
|
|
|
5237
5328
|
// src/ui/input.tsx
|
|
5238
|
-
import * as
|
|
5329
|
+
import * as React9 from "react";
|
|
5239
5330
|
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
5240
|
-
var Input =
|
|
5331
|
+
var Input = React9.forwardRef(
|
|
5241
5332
|
({ className, type, ...props }, ref) => {
|
|
5242
5333
|
return /* @__PURE__ */ jsx15(
|
|
5243
5334
|
"input",
|
|
@@ -5301,8 +5392,8 @@ function UrlOrPageInput({
|
|
|
5301
5392
|
urlError
|
|
5302
5393
|
}) {
|
|
5303
5394
|
const inputId = useId2();
|
|
5304
|
-
const inputRef =
|
|
5305
|
-
const rootRef =
|
|
5395
|
+
const inputRef = useRef4(null);
|
|
5396
|
+
const rootRef = useRef4(null);
|
|
5306
5397
|
const [isFocused, setIsFocused] = useState3(false);
|
|
5307
5398
|
useEffect3(() => {
|
|
5308
5399
|
if (!dropdownOpen) return;
|
|
@@ -5512,7 +5603,7 @@ function LinkEditorPanel({ state, onClose }) {
|
|
|
5512
5603
|
}
|
|
5513
5604
|
|
|
5514
5605
|
// src/ui/link-modal/SectionPickerOverlay.tsx
|
|
5515
|
-
import { useCallback, useEffect as useEffect4, useMemo as useMemo2, useRef as
|
|
5606
|
+
import { useCallback, useEffect as useEffect4, useMemo as useMemo2, useRef as useRef5, useState as useState4 } from "react";
|
|
5516
5607
|
import { createPortal } from "react-dom";
|
|
5517
5608
|
import { ArrowLeft, Check } from "lucide-react";
|
|
5518
5609
|
import { usePathname, useRouter } from "next/navigation";
|
|
@@ -5597,10 +5688,10 @@ function SectionPickerOverlay({
|
|
|
5597
5688
|
const pathname = usePathname();
|
|
5598
5689
|
const [selectedId, setSelectedId] = useState4(null);
|
|
5599
5690
|
const [hoveredId, setHoveredId] = useState4(null);
|
|
5600
|
-
const pointerRef =
|
|
5601
|
-
const pointerScreenRef =
|
|
5602
|
-
const iframeOffsetTopRef =
|
|
5603
|
-
const sectionIdsRef =
|
|
5691
|
+
const pointerRef = useRef5(null);
|
|
5692
|
+
const pointerScreenRef = useRef5(null);
|
|
5693
|
+
const iframeOffsetTopRef = useRef5(null);
|
|
5694
|
+
const sectionIdsRef = useRef5([]);
|
|
5604
5695
|
const [chromeClip, setChromeClip] = useState4(
|
|
5605
5696
|
() => ({
|
|
5606
5697
|
top: 0,
|
|
@@ -6218,9 +6309,155 @@ function shouldUseDevFixtures() {
|
|
|
6218
6309
|
return new URLSearchParams(q).get("ohw-fixtures") === "1";
|
|
6219
6310
|
}
|
|
6220
6311
|
|
|
6312
|
+
// src/lib/nav-tree.ts
|
|
6313
|
+
var MAX_LEVEL = { nav: 1 };
|
|
6314
|
+
var ROOT = null;
|
|
6315
|
+
function cloneForest(nodes) {
|
|
6316
|
+
return nodes.map((n) => ({ id: n.id, children: cloneForest(n.children) }));
|
|
6317
|
+
}
|
|
6318
|
+
function findNode(nodes, id, parentId = ROOT) {
|
|
6319
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
6320
|
+
const node = nodes[i];
|
|
6321
|
+
if (node.id === id) return { node, parentId, index: i, siblings: nodes };
|
|
6322
|
+
const nested = findNode(node.children, id, node.id);
|
|
6323
|
+
if (nested) return nested;
|
|
6324
|
+
}
|
|
6325
|
+
return null;
|
|
6326
|
+
}
|
|
6327
|
+
function getChildrenOf(nodes, parentId) {
|
|
6328
|
+
if (parentId === ROOT) return nodes;
|
|
6329
|
+
const found = findNode(nodes, parentId);
|
|
6330
|
+
return found ? found.node.children : null;
|
|
6331
|
+
}
|
|
6332
|
+
function isDescendant(nodes, ancestorId, maybeDescendantId) {
|
|
6333
|
+
const found = findNode(nodes, ancestorId);
|
|
6334
|
+
if (!found) return false;
|
|
6335
|
+
return findNode(found.node.children, maybeDescendantId) !== null;
|
|
6336
|
+
}
|
|
6337
|
+
function levelOf(nodes, id) {
|
|
6338
|
+
const loc = findNode(nodes, id);
|
|
6339
|
+
if (!loc) return -1;
|
|
6340
|
+
if (loc.parentId === ROOT) return 0;
|
|
6341
|
+
return 1 + Math.max(0, levelOf(nodes, loc.parentId));
|
|
6342
|
+
}
|
|
6343
|
+
function insertedLevel(nodes, parentId) {
|
|
6344
|
+
if (parentId === ROOT) return 0;
|
|
6345
|
+
const parentLevel = levelOf(nodes, parentId);
|
|
6346
|
+
if (parentLevel < 0) return -1;
|
|
6347
|
+
return parentLevel + 1;
|
|
6348
|
+
}
|
|
6349
|
+
function takeNode(nodes, id) {
|
|
6350
|
+
const forest = cloneForest(nodes);
|
|
6351
|
+
const loc = findNode(forest, id);
|
|
6352
|
+
if (!loc) return null;
|
|
6353
|
+
const [taken] = loc.siblings.splice(loc.index, 1);
|
|
6354
|
+
if (!taken) return null;
|
|
6355
|
+
return { forest, taken };
|
|
6356
|
+
}
|
|
6357
|
+
function insertInto(forest, node, parentId, index) {
|
|
6358
|
+
const siblings = getChildrenOf(forest, parentId);
|
|
6359
|
+
if (!siblings) return false;
|
|
6360
|
+
const clamped = Math.max(0, Math.min(index, siblings.length));
|
|
6361
|
+
siblings.splice(clamped, 0, node);
|
|
6362
|
+
return true;
|
|
6363
|
+
}
|
|
6364
|
+
function normalize(nodes) {
|
|
6365
|
+
const walk = (list) => list.map((n) => {
|
|
6366
|
+
const children = walk(n.children);
|
|
6367
|
+
return { id: n.id, children };
|
|
6368
|
+
});
|
|
6369
|
+
return walk(nodes);
|
|
6370
|
+
}
|
|
6371
|
+
function moveNode(model, draggedId, target) {
|
|
6372
|
+
const { parentId, index: targetIndex } = target;
|
|
6373
|
+
if (parentId === draggedId) return null;
|
|
6374
|
+
if (parentId !== ROOT && isDescendant(model, draggedId, parentId)) return null;
|
|
6375
|
+
const nextLevel = insertedLevel(model, parentId);
|
|
6376
|
+
if (nextLevel < 0 || nextLevel > MAX_LEVEL.nav) return null;
|
|
6377
|
+
const draggedLoc = findNode(model, draggedId);
|
|
6378
|
+
if (!draggedLoc) return null;
|
|
6379
|
+
if (parentId !== ROOT && draggedLoc.node.children.length > 0) return null;
|
|
6380
|
+
const taken = takeNode(model, draggedId);
|
|
6381
|
+
if (!taken) return null;
|
|
6382
|
+
let insertIndex = targetIndex;
|
|
6383
|
+
if (draggedLoc.parentId === parentId && draggedLoc.index < targetIndex) {
|
|
6384
|
+
insertIndex -= 1;
|
|
6385
|
+
}
|
|
6386
|
+
if (!insertInto(taken.forest, taken.taken, parentId, insertIndex)) return null;
|
|
6387
|
+
const next = normalize(taken.forest);
|
|
6388
|
+
if (forestsEqual(model, next)) return null;
|
|
6389
|
+
return next;
|
|
6390
|
+
}
|
|
6391
|
+
function forestsEqual(a, b) {
|
|
6392
|
+
if (a.length !== b.length) return false;
|
|
6393
|
+
for (let i = 0; i < a.length; i++) {
|
|
6394
|
+
const left = a[i];
|
|
6395
|
+
const right = b[i];
|
|
6396
|
+
if (left.id !== right.id) return false;
|
|
6397
|
+
if (!forestsEqual(left.children, right.children)) return false;
|
|
6398
|
+
}
|
|
6399
|
+
return true;
|
|
6400
|
+
}
|
|
6401
|
+
function forestFromFlatOrder(order) {
|
|
6402
|
+
return order.map((id) => ({ id, children: [] }));
|
|
6403
|
+
}
|
|
6404
|
+
function serializeNavOrder(nodes) {
|
|
6405
|
+
const hasNesting = nodes.some((n) => n.children.length > 0);
|
|
6406
|
+
if (!hasNesting) {
|
|
6407
|
+
return JSON.stringify(nodes.map((n) => n.id));
|
|
6408
|
+
}
|
|
6409
|
+
return JSON.stringify(nodes);
|
|
6410
|
+
}
|
|
6411
|
+
function parseNavOrderJson(raw) {
|
|
6412
|
+
if (!raw) return null;
|
|
6413
|
+
try {
|
|
6414
|
+
const parsed = JSON.parse(raw);
|
|
6415
|
+
if (!Array.isArray(parsed)) return null;
|
|
6416
|
+
if (parsed.every((x) => typeof x === "string")) {
|
|
6417
|
+
return forestFromFlatOrder(parsed.filter((x) => typeof x === "string" && x.length > 0));
|
|
6418
|
+
}
|
|
6419
|
+
return parseNavNodeList(parsed);
|
|
6420
|
+
} catch {
|
|
6421
|
+
return null;
|
|
6422
|
+
}
|
|
6423
|
+
}
|
|
6424
|
+
function parseNavNodeList(raw) {
|
|
6425
|
+
const out = [];
|
|
6426
|
+
for (const item of raw) {
|
|
6427
|
+
if (typeof item === "string" && item.length > 0) {
|
|
6428
|
+
out.push({ id: item, children: [] });
|
|
6429
|
+
continue;
|
|
6430
|
+
}
|
|
6431
|
+
if (!item || typeof item !== "object") return null;
|
|
6432
|
+
const rec = item;
|
|
6433
|
+
if (typeof rec.id !== "string" || !rec.id) return null;
|
|
6434
|
+
const children = Array.isArray(rec.children) ? parseNavNodeList(rec.children) : [];
|
|
6435
|
+
if (!children) return null;
|
|
6436
|
+
out.push({ id: rec.id, children });
|
|
6437
|
+
}
|
|
6438
|
+
return out;
|
|
6439
|
+
}
|
|
6440
|
+
function flattenNavOrder(nodes) {
|
|
6441
|
+
const out = [];
|
|
6442
|
+
const walk = (list) => {
|
|
6443
|
+
for (const n of list) {
|
|
6444
|
+
out.push(n.id);
|
|
6445
|
+
walk(n.children);
|
|
6446
|
+
}
|
|
6447
|
+
};
|
|
6448
|
+
walk(nodes);
|
|
6449
|
+
return out;
|
|
6450
|
+
}
|
|
6451
|
+
|
|
6221
6452
|
// src/lib/nav-items.ts
|
|
6222
6453
|
var NAV_COUNT_KEY = "__ohw_nav_count";
|
|
6223
6454
|
var NAV_ORDER_KEY = "__ohw_nav_order";
|
|
6455
|
+
var NAV_HREF_RE = /^nav-(\d+)-href$/;
|
|
6456
|
+
function isNavbarHrefKey(key) {
|
|
6457
|
+
if (!key) return false;
|
|
6458
|
+
if (key === "nav-book-href") return false;
|
|
6459
|
+
return NAV_HREF_RE.test(key);
|
|
6460
|
+
}
|
|
6224
6461
|
function getLinkHref(el) {
|
|
6225
6462
|
const key = el.getAttribute("data-ohw-href-key");
|
|
6226
6463
|
if (key) {
|
|
@@ -6257,7 +6494,7 @@ function listNavbarItems() {
|
|
|
6257
6494
|
}
|
|
6258
6495
|
function parseNavIndexFromKey(key) {
|
|
6259
6496
|
if (!key) return null;
|
|
6260
|
-
const match = key.match(
|
|
6497
|
+
const match = key.match(NAV_HREF_RE);
|
|
6261
6498
|
if (!match) return null;
|
|
6262
6499
|
return parseInt(match[1], 10);
|
|
6263
6500
|
}
|
|
@@ -6280,17 +6517,6 @@ function getNavbarExistingTargets() {
|
|
|
6280
6517
|
function getNavOrderFromDom() {
|
|
6281
6518
|
return listNavbarItems().map((el) => el.getAttribute("data-ohw-href-key")).filter((key) => Boolean(key));
|
|
6282
6519
|
}
|
|
6283
|
-
function parseNavOrder(content) {
|
|
6284
|
-
const raw = content[NAV_ORDER_KEY];
|
|
6285
|
-
if (!raw) return null;
|
|
6286
|
-
try {
|
|
6287
|
-
const parsed = JSON.parse(raw);
|
|
6288
|
-
if (!Array.isArray(parsed)) return null;
|
|
6289
|
-
return parsed.filter((key) => typeof key === "string" && key.length > 0);
|
|
6290
|
-
} catch {
|
|
6291
|
-
return null;
|
|
6292
|
-
}
|
|
6293
|
-
}
|
|
6294
6520
|
function findCounterpartByHrefKey(hrefKey, root) {
|
|
6295
6521
|
return root.querySelector(`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`);
|
|
6296
6522
|
}
|
|
@@ -6354,19 +6580,43 @@ function insertNavbarItemDom(index, href, label, afterAnchor) {
|
|
|
6354
6580
|
}
|
|
6355
6581
|
return primary;
|
|
6356
6582
|
}
|
|
6583
|
+
function navOrderKeysEqual(a, b) {
|
|
6584
|
+
if (a.length !== b.length) return false;
|
|
6585
|
+
for (let i = 0; i < a.length; i++) {
|
|
6586
|
+
if (a[i] !== b[i]) return false;
|
|
6587
|
+
}
|
|
6588
|
+
return true;
|
|
6589
|
+
}
|
|
6590
|
+
function getNavbarLinkKeysInContainer(container) {
|
|
6591
|
+
return Array.from(container.querySelectorAll("[data-ohw-href-key]")).filter(isNavbarLinkItem).map((el) => el.getAttribute("data-ohw-href-key")).filter((key) => Boolean(key));
|
|
6592
|
+
}
|
|
6357
6593
|
function applyNavOrderToContainer(container, order) {
|
|
6594
|
+
const desired = order.filter((key, i) => order.indexOf(key) === i);
|
|
6595
|
+
const current = getNavbarLinkKeysInContainer(container);
|
|
6596
|
+
const extras = current.filter((key) => !desired.includes(key));
|
|
6597
|
+
const expected = [...desired.filter((key) => current.includes(key)), ...extras];
|
|
6598
|
+
const orderedEls = [];
|
|
6599
|
+
if (navOrderKeysEqual(current, expected)) return;
|
|
6600
|
+
if (current.length === expected.length && current.every((key, i) => key === expected[i])) {
|
|
6601
|
+
return;
|
|
6602
|
+
}
|
|
6358
6603
|
const seen = /* @__PURE__ */ new Set();
|
|
6359
|
-
for (const hrefKey of
|
|
6604
|
+
for (const hrefKey of desired) {
|
|
6360
6605
|
if (seen.has(hrefKey)) continue;
|
|
6361
6606
|
seen.add(hrefKey);
|
|
6362
6607
|
const el = findCounterpartByHrefKey(hrefKey, container);
|
|
6363
|
-
if (el)
|
|
6608
|
+
if (el && isNavbarLinkItem(el)) orderedEls.push(el);
|
|
6364
6609
|
}
|
|
6365
6610
|
for (const el of container.querySelectorAll("[data-ohw-href-key]")) {
|
|
6366
6611
|
if (!isNavbarLinkItem(el)) continue;
|
|
6367
6612
|
const key = el.getAttribute("data-ohw-href-key");
|
|
6368
6613
|
if (!key || seen.has(key)) continue;
|
|
6369
|
-
|
|
6614
|
+
orderedEls.push(el);
|
|
6615
|
+
}
|
|
6616
|
+
for (const el of orderedEls) {
|
|
6617
|
+
if (container.lastElementChild !== el) {
|
|
6618
|
+
container.appendChild(el);
|
|
6619
|
+
}
|
|
6370
6620
|
}
|
|
6371
6621
|
}
|
|
6372
6622
|
function applyNavOrder(order) {
|
|
@@ -6375,6 +6625,75 @@ function applyNavOrder(order) {
|
|
|
6375
6625
|
const drawer = getNavbarDrawerContainer();
|
|
6376
6626
|
if (drawer) applyNavOrderToContainer(drawer, order);
|
|
6377
6627
|
}
|
|
6628
|
+
function applyChildrenOrder(parentHrefKey, childKeys, root) {
|
|
6629
|
+
const parent = findCounterpartByHrefKey(parentHrefKey, root);
|
|
6630
|
+
if (!parent) return;
|
|
6631
|
+
const group = parent.closest("[data-ohw-nav-group]");
|
|
6632
|
+
const childrenRoot = group?.querySelector(":scope > [data-ohw-nav-children]");
|
|
6633
|
+
if (!childrenRoot) return;
|
|
6634
|
+
const current = Array.from(childrenRoot.querySelectorAll(":scope > [data-ohw-href-key]")).map((el) => el.getAttribute("data-ohw-href-key")).filter((key) => Boolean(key));
|
|
6635
|
+
if (navOrderKeysEqual(current, childKeys)) return;
|
|
6636
|
+
for (const key of childKeys) {
|
|
6637
|
+
const el = findCounterpartByHrefKey(key, root);
|
|
6638
|
+
if (!el) continue;
|
|
6639
|
+
if (childrenRoot.lastElementChild !== el) {
|
|
6640
|
+
childrenRoot.appendChild(el);
|
|
6641
|
+
}
|
|
6642
|
+
}
|
|
6643
|
+
}
|
|
6644
|
+
function applyNavForest(forest) {
|
|
6645
|
+
if (forestsEqual(forest, getNavForestFromDom())) return;
|
|
6646
|
+
const rootKeys = forest.map((n) => n.id);
|
|
6647
|
+
applyNavOrder(rootKeys);
|
|
6648
|
+
const desktop = getNavbarDesktopContainer();
|
|
6649
|
+
const drawer = getNavbarDrawerContainer();
|
|
6650
|
+
for (const node of forest) {
|
|
6651
|
+
if (node.children.length === 0) continue;
|
|
6652
|
+
const childKeys = node.children.map((c) => c.id);
|
|
6653
|
+
if (desktop) applyChildrenOrder(node.id, childKeys, desktop);
|
|
6654
|
+
if (drawer) applyChildrenOrder(node.id, childKeys, drawer);
|
|
6655
|
+
}
|
|
6656
|
+
}
|
|
6657
|
+
function getNavForestFromDom() {
|
|
6658
|
+
const items = listNavbarItems();
|
|
6659
|
+
const nestedChildKeys = /* @__PURE__ */ new Set();
|
|
6660
|
+
const roots = [];
|
|
6661
|
+
for (const item of items) {
|
|
6662
|
+
const key = item.getAttribute("data-ohw-href-key");
|
|
6663
|
+
if (!key || !isNavbarHrefKey(key)) continue;
|
|
6664
|
+
if (item.closest("[data-ohw-nav-children]")) continue;
|
|
6665
|
+
const group = item.closest("[data-ohw-nav-group]");
|
|
6666
|
+
const childrenRoot = group?.querySelector(":scope > [data-ohw-nav-children]");
|
|
6667
|
+
const children = [];
|
|
6668
|
+
if (childrenRoot) {
|
|
6669
|
+
for (const child of childrenRoot.querySelectorAll(":scope > [data-ohw-href-key]")) {
|
|
6670
|
+
if (!isNavbarLinkItem(child)) continue;
|
|
6671
|
+
const childKey = child.getAttribute("data-ohw-href-key");
|
|
6672
|
+
if (!childKey || !isNavbarHrefKey(childKey)) continue;
|
|
6673
|
+
nestedChildKeys.add(childKey);
|
|
6674
|
+
children.push({ id: childKey, children: [] });
|
|
6675
|
+
}
|
|
6676
|
+
}
|
|
6677
|
+
roots.push({ id: key, children });
|
|
6678
|
+
}
|
|
6679
|
+
if (roots.length === 0) {
|
|
6680
|
+
return forestFromFlatOrder(
|
|
6681
|
+
getNavOrderFromDom().filter((k) => isNavbarHrefKey(k) && !nestedChildKeys.has(k))
|
|
6682
|
+
);
|
|
6683
|
+
}
|
|
6684
|
+
return roots;
|
|
6685
|
+
}
|
|
6686
|
+
function planNavItemMove(hrefKey, parentId, insertIndex) {
|
|
6687
|
+
const model = getNavForestFromDom();
|
|
6688
|
+
const next = moveNode(model, hrefKey, { parentId, index: insertIndex });
|
|
6689
|
+
if (!next) return null;
|
|
6690
|
+
if (forestsEqual(model, next)) return null;
|
|
6691
|
+
return {
|
|
6692
|
+
forest: next,
|
|
6693
|
+
orderJson: serializeNavOrder(next),
|
|
6694
|
+
flatOrder: flattenNavOrder(next)
|
|
6695
|
+
};
|
|
6696
|
+
}
|
|
6378
6697
|
function collectNavbarIndicesFromContent(content) {
|
|
6379
6698
|
const indices = /* @__PURE__ */ new Set();
|
|
6380
6699
|
for (const key of Object.keys(content)) {
|
|
@@ -6402,8 +6721,10 @@ function reconcileNavbarItemsFromContent(content) {
|
|
|
6402
6721
|
if (!href && !label) continue;
|
|
6403
6722
|
insertNavbarItemDom(index, href ?? "/", label ?? "Untitled", null);
|
|
6404
6723
|
}
|
|
6405
|
-
const
|
|
6406
|
-
if (
|
|
6724
|
+
const orderForest = parseNavOrderJson(content[NAV_ORDER_KEY]);
|
|
6725
|
+
if (orderForest?.length) {
|
|
6726
|
+
applyNavForest(orderForest);
|
|
6727
|
+
}
|
|
6407
6728
|
}
|
|
6408
6729
|
function buildNavOrderAfterInsert(afterAnchor, newHrefKey) {
|
|
6409
6730
|
const order = getNavOrderFromDom();
|
|
@@ -6443,134 +6764,1024 @@ function insertNavbarItem(href, label, afterAnchor = null) {
|
|
|
6443
6764
|
};
|
|
6444
6765
|
}
|
|
6445
6766
|
|
|
6446
|
-
// src/
|
|
6447
|
-
|
|
6448
|
-
|
|
6449
|
-
function
|
|
6450
|
-
|
|
6451
|
-
|
|
6452
|
-
|
|
6453
|
-
|
|
6454
|
-
return /* @__PURE__ */ jsx21(
|
|
6455
|
-
"div",
|
|
6456
|
-
{
|
|
6457
|
-
"data-ohw-navbar-container-chrome": "",
|
|
6458
|
-
"data-ohw-bridge": "",
|
|
6459
|
-
className: "pointer-events-none fixed z-[2147483647]",
|
|
6460
|
-
style: {
|
|
6461
|
-
top: rect.top - chromeGap,
|
|
6462
|
-
left: rect.left - chromeGap,
|
|
6463
|
-
width: rect.width + chromeGap * 2,
|
|
6464
|
-
height: rect.height + chromeGap * 2
|
|
6465
|
-
},
|
|
6466
|
-
children: /* @__PURE__ */ jsx21(
|
|
6467
|
-
"button",
|
|
6468
|
-
{
|
|
6469
|
-
type: "button",
|
|
6470
|
-
"data-ohw-navbar-add-button": "",
|
|
6471
|
-
className: "pointer-events-auto absolute left-1/2 flex p-0.5 rounded-[10px] size-7 -translate-x-1/2 translate-y-1/2 items-center justify-center border border-border bg-background shadow-sm transition-colors hover:bg-muted/80",
|
|
6472
|
-
style: { top: "70%" },
|
|
6473
|
-
"aria-label": "Add item",
|
|
6474
|
-
onMouseDown: (e) => {
|
|
6475
|
-
e.preventDefault();
|
|
6476
|
-
e.stopPropagation();
|
|
6477
|
-
},
|
|
6478
|
-
onClick: (e) => {
|
|
6479
|
-
e.preventDefault();
|
|
6480
|
-
e.stopPropagation();
|
|
6481
|
-
onAdd();
|
|
6482
|
-
},
|
|
6483
|
-
children: /* @__PURE__ */ jsx21(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
6484
|
-
}
|
|
6485
|
-
)
|
|
6486
|
-
}
|
|
6487
|
-
);
|
|
6767
|
+
// src/lib/footer-items.ts
|
|
6768
|
+
var FOOTER_ORDER_KEY = "__ohw_footer_order";
|
|
6769
|
+
var FOOTER_HREF_RE = /^footer-(\d+)-(\d+)-href$/;
|
|
6770
|
+
function parseFooterHrefKey(key) {
|
|
6771
|
+
if (!key) return null;
|
|
6772
|
+
const match = key.match(FOOTER_HREF_RE);
|
|
6773
|
+
if (!match) return null;
|
|
6774
|
+
return { col: parseInt(match[1], 10), item: parseInt(match[2], 10) };
|
|
6488
6775
|
}
|
|
6489
|
-
|
|
6490
|
-
|
|
6491
|
-
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
6492
|
-
var badgeVariants = cva(
|
|
6493
|
-
"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",
|
|
6494
|
-
{
|
|
6495
|
-
variants: {
|
|
6496
|
-
variant: {
|
|
6497
|
-
default: "border-transparent bg-primary text-primary-foreground",
|
|
6498
|
-
secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
6499
|
-
destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
|
|
6500
|
-
outline: "text-foreground"
|
|
6501
|
-
}
|
|
6502
|
-
},
|
|
6503
|
-
defaultVariants: {
|
|
6504
|
-
variant: "default"
|
|
6505
|
-
}
|
|
6506
|
-
}
|
|
6507
|
-
);
|
|
6508
|
-
function Badge({ className, variant, ...props }) {
|
|
6509
|
-
return /* @__PURE__ */ jsx22("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
6776
|
+
function isFooterHrefKey(key) {
|
|
6777
|
+
return parseFooterHrefKey(key) !== null;
|
|
6510
6778
|
}
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
import { Link as Link2 } from "lucide-react";
|
|
6514
|
-
import { Fragment as Fragment5, jsx as jsx23, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
6515
|
-
var PRIMARY2 = "#0885FE";
|
|
6516
|
-
var IMAGE_FADE_MS = 300;
|
|
6517
|
-
function runOpacityFade(el, onDone) {
|
|
6518
|
-
const anim = el.animate([{ opacity: 0 }, { opacity: 1 }], {
|
|
6519
|
-
duration: IMAGE_FADE_MS,
|
|
6520
|
-
easing: "ease",
|
|
6521
|
-
fill: "forwards"
|
|
6522
|
-
});
|
|
6523
|
-
let finished = false;
|
|
6524
|
-
const finish = () => {
|
|
6525
|
-
if (finished) return;
|
|
6526
|
-
finished = true;
|
|
6527
|
-
anim.cancel();
|
|
6528
|
-
el.style.opacity = "";
|
|
6529
|
-
onDone();
|
|
6530
|
-
};
|
|
6531
|
-
anim.finished.then(finish).catch(finish);
|
|
6532
|
-
window.setTimeout(finish, IMAGE_FADE_MS + 100);
|
|
6779
|
+
function getFooterRoot() {
|
|
6780
|
+
return document.querySelector('footer[data-ohw-section="footer"], footer');
|
|
6533
6781
|
}
|
|
6534
|
-
function
|
|
6535
|
-
|
|
6536
|
-
|
|
6537
|
-
|
|
6538
|
-
|
|
6782
|
+
function getFooterLinksContainer() {
|
|
6783
|
+
return document.querySelector("[data-ohw-footer-links]") ?? document.querySelector(".rb-footer-links");
|
|
6784
|
+
}
|
|
6785
|
+
function isFooterLinkAnchor(el) {
|
|
6786
|
+
if (!el.matches("[data-ohw-href-key]")) return false;
|
|
6787
|
+
if (!isFooterHrefKey(el.getAttribute("data-ohw-href-key"))) return false;
|
|
6788
|
+
return Boolean(el.querySelector('[data-ohw-editable="text"]'));
|
|
6789
|
+
}
|
|
6790
|
+
function listFooterColumns() {
|
|
6791
|
+
const root = getFooterLinksContainer() ?? getFooterRoot()?.querySelector(".rb-footer-links") ?? null;
|
|
6792
|
+
if (!root) return [];
|
|
6793
|
+
const explicit = Array.from(root.querySelectorAll(":scope > [data-ohw-footer-col]"));
|
|
6794
|
+
if (explicit.length > 0) return explicit;
|
|
6795
|
+
return Array.from(root.children).filter((el) => {
|
|
6796
|
+
if (!(el instanceof HTMLElement)) return false;
|
|
6797
|
+
return Array.from(el.querySelectorAll(":scope > [data-ohw-href-key]")).some(
|
|
6798
|
+
isFooterLinkAnchor
|
|
6799
|
+
);
|
|
6539
6800
|
});
|
|
6540
6801
|
}
|
|
6541
|
-
function
|
|
6542
|
-
|
|
6543
|
-
|
|
6544
|
-
|
|
6802
|
+
function listFooterLinksInColumn(column) {
|
|
6803
|
+
return Array.from(column.querySelectorAll(":scope > [data-ohw-href-key]")).filter(
|
|
6804
|
+
isFooterLinkAnchor
|
|
6805
|
+
);
|
|
6545
6806
|
}
|
|
6546
|
-
function
|
|
6547
|
-
const
|
|
6548
|
-
|
|
6549
|
-
|
|
6550
|
-
|
|
6551
|
-
|
|
6552
|
-
|
|
6553
|
-
|
|
6554
|
-
|
|
6555
|
-
|
|
6556
|
-
|
|
6557
|
-
|
|
6558
|
-
|
|
6559
|
-
|
|
6560
|
-
|
|
6561
|
-
|
|
6562
|
-
|
|
6563
|
-
|
|
6564
|
-
|
|
6565
|
-
|
|
6566
|
-
layer.remove();
|
|
6567
|
-
if (!prevPos || prevPos === "static") el.style.position = prevPos;
|
|
6807
|
+
function findFooterColumnForLink(anchor) {
|
|
6808
|
+
const columns = listFooterColumns();
|
|
6809
|
+
return columns.find((col) => col.contains(anchor)) ?? null;
|
|
6810
|
+
}
|
|
6811
|
+
function getFooterOrderFromDom() {
|
|
6812
|
+
return listFooterColumns().map(
|
|
6813
|
+
(col) => listFooterLinksInColumn(col).map((el) => el.getAttribute("data-ohw-href-key")).filter((key) => Boolean(key))
|
|
6814
|
+
);
|
|
6815
|
+
}
|
|
6816
|
+
function findFooterLinkByKey(hrefKey) {
|
|
6817
|
+
return document.querySelector(
|
|
6818
|
+
`footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
6819
|
+
);
|
|
6820
|
+
}
|
|
6821
|
+
function syncFooterColumnIndices(columns) {
|
|
6822
|
+
columns.forEach((col, index) => {
|
|
6823
|
+
const next = String(index);
|
|
6824
|
+
if (col.getAttribute("data-ohw-footer-col") !== next) {
|
|
6825
|
+
col.setAttribute("data-ohw-footer-col", next);
|
|
6826
|
+
}
|
|
6568
6827
|
});
|
|
6569
6828
|
}
|
|
6570
|
-
function
|
|
6571
|
-
|
|
6572
|
-
|
|
6573
|
-
|
|
6829
|
+
function appendChildIfNeeded(parent, child) {
|
|
6830
|
+
if (parent.lastElementChild !== child) {
|
|
6831
|
+
parent.appendChild(child);
|
|
6832
|
+
}
|
|
6833
|
+
}
|
|
6834
|
+
function applyFooterOrder(order) {
|
|
6835
|
+
const container = getFooterLinksContainer();
|
|
6836
|
+
if (!container) return;
|
|
6837
|
+
const columns = listFooterColumns();
|
|
6838
|
+
if (columns.length === 0) return;
|
|
6839
|
+
const currentOrder = getFooterOrderFromDom();
|
|
6840
|
+
if (ordersEqual(order, currentOrder)) {
|
|
6841
|
+
syncFooterColumnIndices(columns);
|
|
6842
|
+
return;
|
|
6843
|
+
}
|
|
6844
|
+
const used = /* @__PURE__ */ new Set();
|
|
6845
|
+
const orderedCols = [];
|
|
6846
|
+
for (const colOrder of order) {
|
|
6847
|
+
let matched = null;
|
|
6848
|
+
for (const hrefKey of colOrder) {
|
|
6849
|
+
const link = findFooterLinkByKey(hrefKey);
|
|
6850
|
+
if (!link) continue;
|
|
6851
|
+
const owner = findFooterColumnForLink(link);
|
|
6852
|
+
if (owner && !used.has(owner)) {
|
|
6853
|
+
matched = owner;
|
|
6854
|
+
break;
|
|
6855
|
+
}
|
|
6856
|
+
}
|
|
6857
|
+
if (!matched) {
|
|
6858
|
+
matched = columns.find((col) => !used.has(col)) ?? null;
|
|
6859
|
+
}
|
|
6860
|
+
if (matched) {
|
|
6861
|
+
used.add(matched);
|
|
6862
|
+
orderedCols.push(matched);
|
|
6863
|
+
}
|
|
6864
|
+
}
|
|
6865
|
+
for (const col of columns) {
|
|
6866
|
+
if (!used.has(col)) orderedCols.push(col);
|
|
6867
|
+
}
|
|
6868
|
+
for (const col of orderedCols) {
|
|
6869
|
+
appendChildIfNeeded(container, col);
|
|
6870
|
+
}
|
|
6871
|
+
const freshColumns = listFooterColumns();
|
|
6872
|
+
syncFooterColumnIndices(freshColumns);
|
|
6873
|
+
for (let c = 0; c < order.length; c++) {
|
|
6874
|
+
const col = freshColumns[c];
|
|
6875
|
+
if (!col) continue;
|
|
6876
|
+
const colOrder = order[c];
|
|
6877
|
+
for (const hrefKey of colOrder) {
|
|
6878
|
+
const el = findFooterLinkByKey(hrefKey);
|
|
6879
|
+
if (!el) continue;
|
|
6880
|
+
if (el.parentElement !== col || col.lastElementChild !== el) {
|
|
6881
|
+
col.appendChild(el);
|
|
6882
|
+
}
|
|
6883
|
+
}
|
|
6884
|
+
}
|
|
6885
|
+
}
|
|
6886
|
+
function ordersEqual(a, b) {
|
|
6887
|
+
if (a.length !== b.length) return false;
|
|
6888
|
+
for (let i = 0; i < a.length; i++) {
|
|
6889
|
+
const left = a[i];
|
|
6890
|
+
const right = b[i];
|
|
6891
|
+
if (left.length !== right.length) return false;
|
|
6892
|
+
for (let j = 0; j < left.length; j++) {
|
|
6893
|
+
if (left[j] !== right[j]) return false;
|
|
6894
|
+
}
|
|
6895
|
+
}
|
|
6896
|
+
return true;
|
|
6897
|
+
}
|
|
6898
|
+
function planFooterLinkMove(hrefKey, targetColIndex, insertIndex) {
|
|
6899
|
+
const order = getFooterOrderFromDom();
|
|
6900
|
+
if (targetColIndex < 0 || targetColIndex >= order.length) return null;
|
|
6901
|
+
let fromCol = -1;
|
|
6902
|
+
let fromIdx = -1;
|
|
6903
|
+
for (let c = 0; c < order.length; c++) {
|
|
6904
|
+
const idx = order[c].indexOf(hrefKey);
|
|
6905
|
+
if (idx >= 0) {
|
|
6906
|
+
fromCol = c;
|
|
6907
|
+
fromIdx = idx;
|
|
6908
|
+
break;
|
|
6909
|
+
}
|
|
6910
|
+
}
|
|
6911
|
+
if (fromCol < 0) return null;
|
|
6912
|
+
const next = order.map((col) => [...col]);
|
|
6913
|
+
next[fromCol].splice(fromIdx, 1);
|
|
6914
|
+
let adjusted = insertIndex;
|
|
6915
|
+
if (fromCol === targetColIndex && fromIdx < insertIndex) adjusted -= 1;
|
|
6916
|
+
adjusted = Math.max(0, Math.min(adjusted, next[targetColIndex].length));
|
|
6917
|
+
next[targetColIndex].splice(adjusted, 0, hrefKey);
|
|
6918
|
+
if (ordersEqual(next, order)) return null;
|
|
6919
|
+
return next;
|
|
6920
|
+
}
|
|
6921
|
+
function planFooterColumnMove(fromIndex, toIndex) {
|
|
6922
|
+
const order = getFooterOrderFromDom();
|
|
6923
|
+
const columns = listFooterColumns();
|
|
6924
|
+
if (fromIndex < 0 || fromIndex >= columns.length || toIndex < 0 || toIndex > columns.length) {
|
|
6925
|
+
return null;
|
|
6926
|
+
}
|
|
6927
|
+
if (toIndex === fromIndex || toIndex === fromIndex + 1) return null;
|
|
6928
|
+
const nextOrder = order.map((col) => [...col]);
|
|
6929
|
+
const [movedOrder] = nextOrder.splice(fromIndex, 1);
|
|
6930
|
+
if (!movedOrder) return null;
|
|
6931
|
+
let adjusted = toIndex;
|
|
6932
|
+
if (fromIndex < toIndex) adjusted -= 1;
|
|
6933
|
+
adjusted = Math.max(0, Math.min(adjusted, nextOrder.length));
|
|
6934
|
+
nextOrder.splice(adjusted, 0, movedOrder);
|
|
6935
|
+
if (ordersEqual(nextOrder, order)) return null;
|
|
6936
|
+
return nextOrder;
|
|
6937
|
+
}
|
|
6938
|
+
function parseFooterOrder(content) {
|
|
6939
|
+
const raw = content[FOOTER_ORDER_KEY];
|
|
6940
|
+
if (!raw) return null;
|
|
6941
|
+
try {
|
|
6942
|
+
const parsed = JSON.parse(raw);
|
|
6943
|
+
if (!Array.isArray(parsed)) return null;
|
|
6944
|
+
return parsed.filter((col) => Array.isArray(col)).map((col) => col.filter((key) => typeof key === "string" && key.length > 0));
|
|
6945
|
+
} catch {
|
|
6946
|
+
return null;
|
|
6947
|
+
}
|
|
6948
|
+
}
|
|
6949
|
+
function reconcileFooterOrderFromContent(content) {
|
|
6950
|
+
const order = parseFooterOrder(content);
|
|
6951
|
+
if (!order?.length) return;
|
|
6952
|
+
const current = getFooterOrderFromDom();
|
|
6953
|
+
if (ordersEqual(order, current)) {
|
|
6954
|
+
syncFooterColumnIndices(listFooterColumns());
|
|
6955
|
+
return;
|
|
6956
|
+
}
|
|
6957
|
+
applyFooterOrder(order);
|
|
6958
|
+
}
|
|
6959
|
+
function buildLinkDropSlots(column, columnIndex) {
|
|
6960
|
+
const links = listFooterLinksInColumn(column);
|
|
6961
|
+
const colRect = column.getBoundingClientRect();
|
|
6962
|
+
const slots = [];
|
|
6963
|
+
const barThickness = 3;
|
|
6964
|
+
if (links.length === 0) {
|
|
6965
|
+
slots.push({
|
|
6966
|
+
insertIndex: 0,
|
|
6967
|
+
columnIndex,
|
|
6968
|
+
left: colRect.left,
|
|
6969
|
+
top: colRect.top + colRect.height / 2 - barThickness / 2,
|
|
6970
|
+
width: colRect.width,
|
|
6971
|
+
height: barThickness,
|
|
6972
|
+
direction: "horizontal"
|
|
6973
|
+
});
|
|
6974
|
+
return slots;
|
|
6975
|
+
}
|
|
6976
|
+
for (let i = 0; i <= links.length; i++) {
|
|
6977
|
+
let top;
|
|
6978
|
+
if (i === 0) {
|
|
6979
|
+
top = links[0].getBoundingClientRect().top - barThickness / 2;
|
|
6980
|
+
} else if (i === links.length) {
|
|
6981
|
+
const last = links[links.length - 1].getBoundingClientRect();
|
|
6982
|
+
top = last.bottom - barThickness / 2;
|
|
6983
|
+
} else {
|
|
6984
|
+
const prev = links[i - 1].getBoundingClientRect();
|
|
6985
|
+
const next = links[i].getBoundingClientRect();
|
|
6986
|
+
top = (prev.bottom + next.top) / 2 - barThickness / 2;
|
|
6987
|
+
}
|
|
6988
|
+
const widthRef = i === 0 ? links[0].getBoundingClientRect() : i === links.length ? links[links.length - 1].getBoundingClientRect() : links[i].getBoundingClientRect();
|
|
6989
|
+
slots.push({
|
|
6990
|
+
insertIndex: i,
|
|
6991
|
+
columnIndex,
|
|
6992
|
+
left: widthRef.left,
|
|
6993
|
+
top,
|
|
6994
|
+
width: Math.max(widthRef.width, colRect.width * 0.8),
|
|
6995
|
+
height: barThickness,
|
|
6996
|
+
direction: "horizontal"
|
|
6997
|
+
});
|
|
6998
|
+
}
|
|
6999
|
+
return slots;
|
|
7000
|
+
}
|
|
7001
|
+
function buildColumnDropSlots() {
|
|
7002
|
+
const columns = listFooterColumns();
|
|
7003
|
+
const slots = [];
|
|
7004
|
+
const barThickness = 3;
|
|
7005
|
+
if (columns.length === 0) return slots;
|
|
7006
|
+
for (let i = 0; i <= columns.length; i++) {
|
|
7007
|
+
let left;
|
|
7008
|
+
let height;
|
|
7009
|
+
let top;
|
|
7010
|
+
if (i === 0) {
|
|
7011
|
+
const first = columns[0].getBoundingClientRect();
|
|
7012
|
+
left = first.left - barThickness / 2;
|
|
7013
|
+
top = first.top;
|
|
7014
|
+
height = first.height;
|
|
7015
|
+
} else if (i === columns.length) {
|
|
7016
|
+
const last = columns[columns.length - 1].getBoundingClientRect();
|
|
7017
|
+
left = last.right - barThickness / 2;
|
|
7018
|
+
top = last.top;
|
|
7019
|
+
height = last.height;
|
|
7020
|
+
} else {
|
|
7021
|
+
const prev = columns[i - 1].getBoundingClientRect();
|
|
7022
|
+
const next = columns[i].getBoundingClientRect();
|
|
7023
|
+
left = (prev.right + next.left) / 2 - barThickness / 2;
|
|
7024
|
+
top = Math.min(prev.top, next.top);
|
|
7025
|
+
height = Math.max(prev.bottom, next.bottom) - top;
|
|
7026
|
+
}
|
|
7027
|
+
slots.push({
|
|
7028
|
+
insertIndex: i,
|
|
7029
|
+
columnIndex: i,
|
|
7030
|
+
left,
|
|
7031
|
+
top,
|
|
7032
|
+
width: barThickness,
|
|
7033
|
+
height: Math.max(height, 24),
|
|
7034
|
+
direction: "vertical"
|
|
7035
|
+
});
|
|
7036
|
+
}
|
|
7037
|
+
return slots;
|
|
7038
|
+
}
|
|
7039
|
+
function hitTestLinkDropSlot(clientX, clientY, draggedHrefKey) {
|
|
7040
|
+
const columns = listFooterColumns();
|
|
7041
|
+
let best = null;
|
|
7042
|
+
for (let c = 0; c < columns.length; c++) {
|
|
7043
|
+
const col = columns[c];
|
|
7044
|
+
const colRect = col.getBoundingClientRect();
|
|
7045
|
+
const inColX = clientX >= colRect.left - 24 && clientX <= colRect.right + 24;
|
|
7046
|
+
if (!inColX) continue;
|
|
7047
|
+
const slots = buildLinkDropSlots(col, c).filter((slot) => {
|
|
7048
|
+
const links = listFooterLinksInColumn(col);
|
|
7049
|
+
const fromIdx = links.findIndex(
|
|
7050
|
+
(el) => el.getAttribute("data-ohw-href-key") === draggedHrefKey
|
|
7051
|
+
);
|
|
7052
|
+
if (fromIdx < 0) return true;
|
|
7053
|
+
if (c === findColumnIndexForKey(draggedHrefKey) && (slot.insertIndex === fromIdx || slot.insertIndex === fromIdx + 1)) {
|
|
7054
|
+
return true;
|
|
7055
|
+
}
|
|
7056
|
+
return true;
|
|
7057
|
+
});
|
|
7058
|
+
for (const slot of slots) {
|
|
7059
|
+
const cy = slot.top + slot.height / 2;
|
|
7060
|
+
const dist = Math.abs(clientY - cy) + (inColX ? 0 : 1e3);
|
|
7061
|
+
if (!best || dist < best.dist) best = { slot, dist };
|
|
7062
|
+
}
|
|
7063
|
+
}
|
|
7064
|
+
return best?.slot ?? null;
|
|
7065
|
+
}
|
|
7066
|
+
function findColumnIndexForKey(hrefKey) {
|
|
7067
|
+
const order = getFooterOrderFromDom();
|
|
7068
|
+
for (let c = 0; c < order.length; c++) {
|
|
7069
|
+
if (order[c].includes(hrefKey)) return c;
|
|
7070
|
+
}
|
|
7071
|
+
return -1;
|
|
7072
|
+
}
|
|
7073
|
+
function hitTestColumnDropSlot(clientX, _clientY) {
|
|
7074
|
+
const slots = buildColumnDropSlots();
|
|
7075
|
+
let best = null;
|
|
7076
|
+
for (const slot of slots) {
|
|
7077
|
+
const cx2 = slot.left + slot.width / 2;
|
|
7078
|
+
const dist = Math.abs(clientX - cx2);
|
|
7079
|
+
if (!best || dist < best.dist) best = { slot, dist };
|
|
7080
|
+
}
|
|
7081
|
+
return best?.slot ?? null;
|
|
7082
|
+
}
|
|
7083
|
+
|
|
7084
|
+
// src/lib/item-drag-interaction.ts
|
|
7085
|
+
function disableNativeHrefDrag(el) {
|
|
7086
|
+
if (el.draggable) el.draggable = false;
|
|
7087
|
+
if (el.getAttribute("draggable") !== "false") {
|
|
7088
|
+
el.setAttribute("draggable", "false");
|
|
7089
|
+
}
|
|
7090
|
+
}
|
|
7091
|
+
function clearTextSelection() {
|
|
7092
|
+
const sel = window.getSelection();
|
|
7093
|
+
if (sel && !sel.isCollapsed) sel.removeAllRanges();
|
|
7094
|
+
}
|
|
7095
|
+
function armItemPressDrag() {
|
|
7096
|
+
document.documentElement.setAttribute("data-ohw-footer-press-drag", "");
|
|
7097
|
+
}
|
|
7098
|
+
function lockItemDuringDrag() {
|
|
7099
|
+
document.documentElement.removeAttribute("data-ohw-footer-press-drag");
|
|
7100
|
+
document.documentElement.setAttribute("data-ohw-item-dragging", "");
|
|
7101
|
+
clearTextSelection();
|
|
7102
|
+
}
|
|
7103
|
+
function unlockItemDragInteraction() {
|
|
7104
|
+
document.documentElement.removeAttribute("data-ohw-footer-press-drag");
|
|
7105
|
+
document.documentElement.removeAttribute("data-ohw-item-dragging");
|
|
7106
|
+
clearTextSelection();
|
|
7107
|
+
}
|
|
7108
|
+
var armFooterPressDrag = armItemPressDrag;
|
|
7109
|
+
var lockFooterDuringDrag = lockItemDuringDrag;
|
|
7110
|
+
var unlockFooterDragInteraction = unlockItemDragInteraction;
|
|
7111
|
+
|
|
7112
|
+
// src/lib/nav-dnd.ts
|
|
7113
|
+
function listReorderableNavItems() {
|
|
7114
|
+
return listNavbarItems().filter((el) => {
|
|
7115
|
+
const key = el.getAttribute("data-ohw-href-key");
|
|
7116
|
+
return isNavbarHrefKey(key) && !el.closest("[data-ohw-nav-children]");
|
|
7117
|
+
});
|
|
7118
|
+
}
|
|
7119
|
+
function listNavChildren(parentHrefKey) {
|
|
7120
|
+
const items = listNavbarItems();
|
|
7121
|
+
const parent = items.find((el) => el.getAttribute("data-ohw-href-key") === parentHrefKey);
|
|
7122
|
+
if (!parent) return [];
|
|
7123
|
+
const group = parent.closest("[data-ohw-nav-group]");
|
|
7124
|
+
const childrenRoot = group?.querySelector(":scope > [data-ohw-nav-children]");
|
|
7125
|
+
if (!childrenRoot) return [];
|
|
7126
|
+
return Array.from(childrenRoot.querySelectorAll(":scope > [data-ohw-href-key]")).filter(
|
|
7127
|
+
(el) => isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))
|
|
7128
|
+
);
|
|
7129
|
+
}
|
|
7130
|
+
function activeNavListContainer() {
|
|
7131
|
+
const desktop = getNavbarDesktopContainer();
|
|
7132
|
+
if (desktop && desktop.getClientRects().length > 0) {
|
|
7133
|
+
const style = window.getComputedStyle(desktop);
|
|
7134
|
+
if (style.display !== "none" && style.visibility !== "hidden") return desktop;
|
|
7135
|
+
}
|
|
7136
|
+
return getNavbarDrawerContainer();
|
|
7137
|
+
}
|
|
7138
|
+
function buildRootNavDropSlots() {
|
|
7139
|
+
const items = listReorderableNavItems();
|
|
7140
|
+
const slots = [];
|
|
7141
|
+
const barThickness = 3;
|
|
7142
|
+
if (items.length === 0) {
|
|
7143
|
+
const container = activeNavListContainer();
|
|
7144
|
+
if (!container) return slots;
|
|
7145
|
+
const rect = container.getBoundingClientRect();
|
|
7146
|
+
slots.push({
|
|
7147
|
+
insertIndex: 0,
|
|
7148
|
+
parentId: null,
|
|
7149
|
+
left: rect.left + rect.width / 2 - barThickness / 2,
|
|
7150
|
+
top: rect.top,
|
|
7151
|
+
width: barThickness,
|
|
7152
|
+
height: Math.max(rect.height, 24),
|
|
7153
|
+
direction: "vertical"
|
|
7154
|
+
});
|
|
7155
|
+
return slots;
|
|
7156
|
+
}
|
|
7157
|
+
const edgeGap = (() => {
|
|
7158
|
+
if (items.length < 2) return 32;
|
|
7159
|
+
const a = items[0].getBoundingClientRect();
|
|
7160
|
+
const b = items[1].getBoundingClientRect();
|
|
7161
|
+
return Math.max(0, b.left - a.right);
|
|
7162
|
+
})();
|
|
7163
|
+
for (let i = 0; i <= items.length; i++) {
|
|
7164
|
+
let left;
|
|
7165
|
+
let top;
|
|
7166
|
+
let height;
|
|
7167
|
+
if (i === 0) {
|
|
7168
|
+
const first = items[0].getBoundingClientRect();
|
|
7169
|
+
left = first.left - edgeGap / 2 - barThickness / 2;
|
|
7170
|
+
top = first.top;
|
|
7171
|
+
height = first.height;
|
|
7172
|
+
} else if (i === items.length) {
|
|
7173
|
+
const last = items[items.length - 1].getBoundingClientRect();
|
|
7174
|
+
const lastGap = items.length >= 2 ? Math.max(
|
|
7175
|
+
0,
|
|
7176
|
+
last.left - items[items.length - 2].getBoundingClientRect().right
|
|
7177
|
+
) : edgeGap;
|
|
7178
|
+
left = last.right + lastGap / 2 - barThickness / 2;
|
|
7179
|
+
top = last.top;
|
|
7180
|
+
height = last.height;
|
|
7181
|
+
} else {
|
|
7182
|
+
const prev = items[i - 1].getBoundingClientRect();
|
|
7183
|
+
const next = items[i].getBoundingClientRect();
|
|
7184
|
+
left = (prev.right + next.left) / 2 - barThickness / 2;
|
|
7185
|
+
top = Math.min(prev.top, next.top);
|
|
7186
|
+
height = Math.max(prev.bottom, next.bottom) - top;
|
|
7187
|
+
}
|
|
7188
|
+
slots.push({
|
|
7189
|
+
insertIndex: i,
|
|
7190
|
+
parentId: null,
|
|
7191
|
+
left,
|
|
7192
|
+
top,
|
|
7193
|
+
width: barThickness,
|
|
7194
|
+
height: Math.max(height, 24),
|
|
7195
|
+
direction: "vertical"
|
|
7196
|
+
});
|
|
7197
|
+
}
|
|
7198
|
+
return slots;
|
|
7199
|
+
}
|
|
7200
|
+
function buildChildNavDropSlots(parentHrefKey) {
|
|
7201
|
+
const children = listNavChildren(parentHrefKey);
|
|
7202
|
+
const slots = [];
|
|
7203
|
+
const barThickness = 3;
|
|
7204
|
+
if (children.length === 0) return slots;
|
|
7205
|
+
const edgeGap = (() => {
|
|
7206
|
+
if (children.length < 2) return 16;
|
|
7207
|
+
const a = children[0].getBoundingClientRect();
|
|
7208
|
+
const b = children[1].getBoundingClientRect();
|
|
7209
|
+
return Math.max(0, b.top - a.bottom);
|
|
7210
|
+
})();
|
|
7211
|
+
for (let i = 0; i <= children.length; i++) {
|
|
7212
|
+
let top;
|
|
7213
|
+
let width;
|
|
7214
|
+
let left;
|
|
7215
|
+
if (i === 0) {
|
|
7216
|
+
const first = children[0].getBoundingClientRect();
|
|
7217
|
+
top = first.top - edgeGap / 2 - barThickness / 2;
|
|
7218
|
+
left = first.left;
|
|
7219
|
+
width = first.width;
|
|
7220
|
+
} else if (i === children.length) {
|
|
7221
|
+
const last = children[children.length - 1].getBoundingClientRect();
|
|
7222
|
+
const lastGap = children.length >= 2 ? Math.max(
|
|
7223
|
+
0,
|
|
7224
|
+
last.top - children[children.length - 2].getBoundingClientRect().bottom
|
|
7225
|
+
) : edgeGap;
|
|
7226
|
+
top = last.bottom + lastGap / 2 - barThickness / 2;
|
|
7227
|
+
left = last.left;
|
|
7228
|
+
width = last.width;
|
|
7229
|
+
} else {
|
|
7230
|
+
const prev = children[i - 1].getBoundingClientRect();
|
|
7231
|
+
const next = children[i].getBoundingClientRect();
|
|
7232
|
+
top = (prev.bottom + next.top) / 2 - barThickness / 2;
|
|
7233
|
+
left = Math.min(prev.left, next.left);
|
|
7234
|
+
width = Math.max(prev.right, next.right) - left;
|
|
7235
|
+
}
|
|
7236
|
+
slots.push({
|
|
7237
|
+
insertIndex: i,
|
|
7238
|
+
parentId: parentHrefKey,
|
|
7239
|
+
left,
|
|
7240
|
+
top,
|
|
7241
|
+
width: Math.max(width, 40),
|
|
7242
|
+
height: barThickness,
|
|
7243
|
+
direction: "horizontal"
|
|
7244
|
+
});
|
|
7245
|
+
}
|
|
7246
|
+
return slots;
|
|
7247
|
+
}
|
|
7248
|
+
function buildAllNavDropSlots(draggedHrefKey) {
|
|
7249
|
+
const slots = [...buildRootNavDropSlots()];
|
|
7250
|
+
for (const item of listReorderableNavItems()) {
|
|
7251
|
+
const key = item.getAttribute("data-ohw-href-key");
|
|
7252
|
+
if (!key || key === draggedHrefKey) continue;
|
|
7253
|
+
const group = item.closest("[data-ohw-nav-group]");
|
|
7254
|
+
if (!group?.querySelector(":scope > [data-ohw-nav-children]")) continue;
|
|
7255
|
+
slots.push(...buildChildNavDropSlots(key));
|
|
7256
|
+
}
|
|
7257
|
+
const dragged = listNavbarItems().find((el) => el.getAttribute("data-ohw-href-key") === draggedHrefKey);
|
|
7258
|
+
const parentGroup = dragged?.closest("[data-ohw-nav-children]")?.closest("[data-ohw-nav-group]");
|
|
7259
|
+
const parentTrigger = parentGroup?.querySelector(":scope > [data-ohw-href-key]");
|
|
7260
|
+
const parentKey = parentTrigger?.getAttribute("data-ohw-href-key");
|
|
7261
|
+
if (parentKey && isNavbarHrefKey(parentKey)) {
|
|
7262
|
+
const existing = slots.some((s) => s.parentId === parentKey);
|
|
7263
|
+
if (!existing) slots.push(...buildChildNavDropSlots(parentKey));
|
|
7264
|
+
}
|
|
7265
|
+
return slots;
|
|
7266
|
+
}
|
|
7267
|
+
function hitTestNavDropSlot(clientX, clientY, draggedHrefKey) {
|
|
7268
|
+
const slots = buildAllNavDropSlots(draggedHrefKey);
|
|
7269
|
+
let best = null;
|
|
7270
|
+
for (const slot of slots) {
|
|
7271
|
+
const cx2 = slot.left + slot.width / 2;
|
|
7272
|
+
const cy = slot.top + slot.height / 2;
|
|
7273
|
+
const dist = slot.direction === "vertical" ? Math.abs(clientX - cx2) + Math.abs(clientY - cy) * 0.25 : Math.abs(clientY - cy) + Math.abs(clientX - cx2) * 0.25;
|
|
7274
|
+
if (!best || dist < best.dist) best = { slot, dist };
|
|
7275
|
+
}
|
|
7276
|
+
return best?.slot ?? null;
|
|
7277
|
+
}
|
|
7278
|
+
|
|
7279
|
+
// src/useNavItemDrag.ts
|
|
7280
|
+
import { useCallback as useCallback3, useEffect as useEffect7, useRef as useRef6, useState as useState6 } from "react";
|
|
7281
|
+
function useNavItemDrag({
|
|
7282
|
+
isEditMode,
|
|
7283
|
+
editContentRef,
|
|
7284
|
+
selectedElRef,
|
|
7285
|
+
activeElRef,
|
|
7286
|
+
footerDragRef,
|
|
7287
|
+
suppressNextClickRef,
|
|
7288
|
+
suppressClickUntilRef,
|
|
7289
|
+
siblingHintElRef,
|
|
7290
|
+
postToParentRef,
|
|
7291
|
+
deselectRef,
|
|
7292
|
+
selectRef,
|
|
7293
|
+
deactivateRef,
|
|
7294
|
+
setLinkPopover,
|
|
7295
|
+
linkPopoverOpenRef,
|
|
7296
|
+
setIsItemDragging,
|
|
7297
|
+
setDraggedItemRect,
|
|
7298
|
+
setSiblingHintRect,
|
|
7299
|
+
setSiblingHintRects,
|
|
7300
|
+
setToolbarRect,
|
|
7301
|
+
getNavigationItemAnchor: getNavigationItemAnchor2,
|
|
7302
|
+
isDragHandleDisabled: isDragHandleDisabled2,
|
|
7303
|
+
isNavbarButton: isNavbarButton3
|
|
7304
|
+
}) {
|
|
7305
|
+
const navDragRef = useRef6(null);
|
|
7306
|
+
const [navDropSlots, setNavDropSlots] = useState6([]);
|
|
7307
|
+
const [activeNavDropIndex, setActiveNavDropIndex] = useState6(null);
|
|
7308
|
+
const navPointerDragRef = useRef6(null);
|
|
7309
|
+
const clearNavDragVisuals = useCallback3(() => {
|
|
7310
|
+
navDragRef.current = null;
|
|
7311
|
+
setNavDropSlots([]);
|
|
7312
|
+
setActiveNavDropIndex(null);
|
|
7313
|
+
setDraggedItemRect(null);
|
|
7314
|
+
setSiblingHintRects([]);
|
|
7315
|
+
setIsItemDragging(false);
|
|
7316
|
+
unlockItemDragInteraction();
|
|
7317
|
+
}, [setDraggedItemRect, setIsItemDragging, setSiblingHintRects]);
|
|
7318
|
+
const refreshNavDragVisuals = useCallback3(
|
|
7319
|
+
(session, activeSlot, clientX, clientY) => {
|
|
7320
|
+
setDraggedItemRect(session.draggedEl.getBoundingClientRect());
|
|
7321
|
+
if (typeof clientX === "number" && typeof clientY === "number") {
|
|
7322
|
+
session.lastClientX = clientX;
|
|
7323
|
+
session.lastClientY = clientY;
|
|
7324
|
+
}
|
|
7325
|
+
session.activeSlot = activeSlot;
|
|
7326
|
+
setSiblingHintRects([]);
|
|
7327
|
+
const slots = buildAllNavDropSlots(session.hrefKey);
|
|
7328
|
+
setNavDropSlots(slots);
|
|
7329
|
+
const activeIdx = activeSlot ? slots.findIndex(
|
|
7330
|
+
(s) => s.parentId === activeSlot.parentId && s.insertIndex === activeSlot.insertIndex
|
|
7331
|
+
) : -1;
|
|
7332
|
+
setActiveNavDropIndex(activeIdx >= 0 ? activeIdx : null);
|
|
7333
|
+
},
|
|
7334
|
+
[setDraggedItemRect, setSiblingHintRects]
|
|
7335
|
+
);
|
|
7336
|
+
const refreshNavDragVisualsRef = useRef6(refreshNavDragVisuals);
|
|
7337
|
+
refreshNavDragVisualsRef.current = refreshNavDragVisuals;
|
|
7338
|
+
const commitNavDragRef = useRef6(() => {
|
|
7339
|
+
});
|
|
7340
|
+
const beginNavDragRef = useRef6(() => {
|
|
7341
|
+
});
|
|
7342
|
+
const beginNavDrag = useCallback3(
|
|
7343
|
+
(session) => {
|
|
7344
|
+
const rect = session.draggedEl.getBoundingClientRect();
|
|
7345
|
+
session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
|
|
7346
|
+
session.lastClientY = session.lastClientY || rect.top + rect.height / 2;
|
|
7347
|
+
session.activeSlot = session.activeSlot ?? null;
|
|
7348
|
+
navDragRef.current = session;
|
|
7349
|
+
setIsItemDragging(true);
|
|
7350
|
+
lockItemDuringDrag();
|
|
7351
|
+
siblingHintElRef.current = null;
|
|
7352
|
+
setSiblingHintRect(null);
|
|
7353
|
+
if (session.wasSelected && selectedElRef.current === session.draggedEl) {
|
|
7354
|
+
setToolbarRect(rect);
|
|
7355
|
+
}
|
|
7356
|
+
const initialSlot = hitTestNavDropSlot(session.lastClientX, session.lastClientY, session.hrefKey);
|
|
7357
|
+
refreshNavDragVisuals(session, initialSlot, session.lastClientX, session.lastClientY);
|
|
7358
|
+
},
|
|
7359
|
+
[
|
|
7360
|
+
refreshNavDragVisuals,
|
|
7361
|
+
selectedElRef,
|
|
7362
|
+
setIsItemDragging,
|
|
7363
|
+
setSiblingHintRect,
|
|
7364
|
+
setToolbarRect,
|
|
7365
|
+
siblingHintElRef
|
|
7366
|
+
]
|
|
7367
|
+
);
|
|
7368
|
+
beginNavDragRef.current = beginNavDrag;
|
|
7369
|
+
const commitNavDrag = useCallback3(
|
|
7370
|
+
(clientX, clientY) => {
|
|
7371
|
+
const session = navDragRef.current;
|
|
7372
|
+
if (!session) {
|
|
7373
|
+
clearNavDragVisuals();
|
|
7374
|
+
return;
|
|
7375
|
+
}
|
|
7376
|
+
const x = typeof clientX === "number" && (clientX !== 0 || clientY !== 0) ? clientX : session.lastClientX;
|
|
7377
|
+
const y = typeof clientY === "number" && (clientX !== 0 || clientY !== 0) ? clientY : session.lastClientY;
|
|
7378
|
+
const slot = session.activeSlot ?? hitTestNavDropSlot(x, y, session.hrefKey);
|
|
7379
|
+
const planned = slot != null ? planNavItemMove(session.hrefKey, slot.parentId, slot.insertIndex) : null;
|
|
7380
|
+
const wasSelected = session.wasSelected;
|
|
7381
|
+
const hrefKey = session.hrefKey;
|
|
7382
|
+
const applySelectionAfterDrop = () => {
|
|
7383
|
+
if (!wasSelected) {
|
|
7384
|
+
deselectRef.current();
|
|
7385
|
+
return;
|
|
7386
|
+
}
|
|
7387
|
+
const desktop = document.querySelector("[data-ohw-nav-container]");
|
|
7388
|
+
const drawer = document.querySelector("[data-ohw-nav-drawer]");
|
|
7389
|
+
const link = desktop?.querySelector(`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`) ?? drawer?.querySelector(`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`) ?? document.querySelector(`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`);
|
|
7390
|
+
if (link) {
|
|
7391
|
+
selectRef.current(link);
|
|
7392
|
+
return;
|
|
7393
|
+
}
|
|
7394
|
+
deselectRef.current();
|
|
7395
|
+
};
|
|
7396
|
+
if (planned) {
|
|
7397
|
+
editContentRef.current = {
|
|
7398
|
+
...editContentRef.current,
|
|
7399
|
+
[NAV_ORDER_KEY]: planned.orderJson
|
|
7400
|
+
};
|
|
7401
|
+
applyNavForest(planned.forest);
|
|
7402
|
+
document.querySelectorAll(
|
|
7403
|
+
"nav [data-ohw-href-key], [data-ohw-nav-container] [data-ohw-href-key], [data-ohw-nav-drawer] [data-ohw-href-key]"
|
|
7404
|
+
).forEach((el) => {
|
|
7405
|
+
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
7406
|
+
disableNativeHrefDrag(el);
|
|
7407
|
+
}
|
|
7408
|
+
});
|
|
7409
|
+
postToParentRef.current({
|
|
7410
|
+
type: "ow:change",
|
|
7411
|
+
nodes: [{ key: NAV_ORDER_KEY, text: planned.orderJson }]
|
|
7412
|
+
});
|
|
7413
|
+
applySelectionAfterDrop();
|
|
7414
|
+
clearNavDragVisuals();
|
|
7415
|
+
requestAnimationFrame(() => {
|
|
7416
|
+
if (editContentRef.current[NAV_ORDER_KEY] === planned.orderJson) {
|
|
7417
|
+
applyNavForest(planned.forest);
|
|
7418
|
+
}
|
|
7419
|
+
applySelectionAfterDrop();
|
|
7420
|
+
requestAnimationFrame(applySelectionAfterDrop);
|
|
7421
|
+
});
|
|
7422
|
+
return;
|
|
7423
|
+
}
|
|
7424
|
+
applySelectionAfterDrop();
|
|
7425
|
+
clearNavDragVisuals();
|
|
7426
|
+
},
|
|
7427
|
+
[clearNavDragVisuals, deselectRef, editContentRef, postToParentRef, selectRef]
|
|
7428
|
+
);
|
|
7429
|
+
commitNavDragRef.current = commitNavDrag;
|
|
7430
|
+
const startNavLinkDrag = useCallback3(
|
|
7431
|
+
(anchor, clientX, clientY, wasSelected) => {
|
|
7432
|
+
if (footerDragRef.current) return false;
|
|
7433
|
+
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
7434
|
+
if (!hrefKey || !isNavbarHrefKey(hrefKey)) return false;
|
|
7435
|
+
if (isNavbarButton3(anchor) || isDragHandleDisabled2(anchor)) return false;
|
|
7436
|
+
beginNavDrag({
|
|
7437
|
+
hrefKey,
|
|
7438
|
+
wasSelected,
|
|
7439
|
+
draggedEl: anchor,
|
|
7440
|
+
lastClientX: clientX,
|
|
7441
|
+
lastClientY: clientY,
|
|
7442
|
+
activeSlot: null
|
|
7443
|
+
});
|
|
7444
|
+
return true;
|
|
7445
|
+
},
|
|
7446
|
+
[beginNavDrag, footerDragRef, isDragHandleDisabled2, isNavbarButton3]
|
|
7447
|
+
);
|
|
7448
|
+
const onNavDragOver = useCallback3(
|
|
7449
|
+
(e) => {
|
|
7450
|
+
const session = navDragRef.current;
|
|
7451
|
+
if (!session) return false;
|
|
7452
|
+
e.preventDefault();
|
|
7453
|
+
if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
|
|
7454
|
+
const slot = hitTestNavDropSlot(e.clientX, e.clientY, session.hrefKey);
|
|
7455
|
+
refreshNavDragVisualsRef.current(session, slot, e.clientX, e.clientY);
|
|
7456
|
+
return true;
|
|
7457
|
+
},
|
|
7458
|
+
[]
|
|
7459
|
+
);
|
|
7460
|
+
useEffect7(() => {
|
|
7461
|
+
if (!isEditMode) return;
|
|
7462
|
+
const THRESHOLD = 10;
|
|
7463
|
+
const resolveWasSelected = (el) => {
|
|
7464
|
+
if (selectedElRef.current === el) return true;
|
|
7465
|
+
const activeAnchor = activeElRef.current ? getNavigationItemAnchor2(activeElRef.current) : null;
|
|
7466
|
+
return activeAnchor === el;
|
|
7467
|
+
};
|
|
7468
|
+
const onPointerDown = (e) => {
|
|
7469
|
+
if (e.button !== 0) return;
|
|
7470
|
+
if (navDragRef.current || footerDragRef.current) return;
|
|
7471
|
+
const target = e.target;
|
|
7472
|
+
if (!target) return;
|
|
7473
|
+
if (target.closest(
|
|
7474
|
+
'[data-ohw-drag-handle-container], [data-slot="drag-handle"], [data-ohw-toolbar], [data-ohw-item-toolbar-anchor], [data-ohw-link-popover-root]'
|
|
7475
|
+
)) {
|
|
7476
|
+
return;
|
|
7477
|
+
}
|
|
7478
|
+
if (target.closest("[data-ohw-item-drag-surface]")) return;
|
|
7479
|
+
const anchor = getNavigationItemAnchor2(target);
|
|
7480
|
+
const hrefKey = anchor?.getAttribute("data-ohw-href-key") ?? null;
|
|
7481
|
+
if (!anchor || !isNavbarHrefKey(hrefKey)) return;
|
|
7482
|
+
if (isNavbarButton3(anchor) || isDragHandleDisabled2(anchor)) return;
|
|
7483
|
+
armItemPressDrag();
|
|
7484
|
+
navPointerDragRef.current = {
|
|
7485
|
+
el: anchor,
|
|
7486
|
+
startX: e.clientX,
|
|
7487
|
+
startY: e.clientY,
|
|
7488
|
+
pointerId: e.pointerId,
|
|
7489
|
+
wasSelected: resolveWasSelected(anchor),
|
|
7490
|
+
started: false
|
|
7491
|
+
};
|
|
7492
|
+
};
|
|
7493
|
+
const onPointerMove = (e) => {
|
|
7494
|
+
const pending = navPointerDragRef.current;
|
|
7495
|
+
if (!pending) return;
|
|
7496
|
+
if (pending.started) {
|
|
7497
|
+
e.preventDefault();
|
|
7498
|
+
clearTextSelection();
|
|
7499
|
+
const session = navDragRef.current;
|
|
7500
|
+
if (!session) return;
|
|
7501
|
+
const slot = hitTestNavDropSlot(e.clientX, e.clientY, session.hrefKey);
|
|
7502
|
+
refreshNavDragVisualsRef.current(session, slot, e.clientX, e.clientY);
|
|
7503
|
+
return;
|
|
7504
|
+
}
|
|
7505
|
+
const dx = e.clientX - pending.startX;
|
|
7506
|
+
const dy = e.clientY - pending.startY;
|
|
7507
|
+
if (dx * dx + dy * dy < THRESHOLD * THRESHOLD) return;
|
|
7508
|
+
e.preventDefault();
|
|
7509
|
+
pending.started = true;
|
|
7510
|
+
clearTextSelection();
|
|
7511
|
+
try {
|
|
7512
|
+
document.body.setPointerCapture(pending.pointerId);
|
|
7513
|
+
} catch {
|
|
7514
|
+
}
|
|
7515
|
+
if (linkPopoverOpenRef.current) setLinkPopover(null);
|
|
7516
|
+
if (activeElRef.current) deactivateRef.current();
|
|
7517
|
+
const key = pending.el.getAttribute("data-ohw-href-key");
|
|
7518
|
+
if (!key) return;
|
|
7519
|
+
beginNavDragRef.current({
|
|
7520
|
+
hrefKey: key,
|
|
7521
|
+
wasSelected: pending.wasSelected,
|
|
7522
|
+
draggedEl: pending.el,
|
|
7523
|
+
lastClientX: e.clientX,
|
|
7524
|
+
lastClientY: e.clientY,
|
|
7525
|
+
activeSlot: null
|
|
7526
|
+
});
|
|
7527
|
+
};
|
|
7528
|
+
const endPointerDrag = (e) => {
|
|
7529
|
+
const pending = navPointerDragRef.current;
|
|
7530
|
+
navPointerDragRef.current = null;
|
|
7531
|
+
try {
|
|
7532
|
+
if (document.body.hasPointerCapture(e.pointerId)) {
|
|
7533
|
+
document.body.releasePointerCapture(e.pointerId);
|
|
7534
|
+
}
|
|
7535
|
+
} catch {
|
|
7536
|
+
}
|
|
7537
|
+
if (!pending?.started) {
|
|
7538
|
+
unlockItemDragInteraction();
|
|
7539
|
+
return;
|
|
7540
|
+
}
|
|
7541
|
+
suppressNextClickRef.current = true;
|
|
7542
|
+
suppressClickUntilRef.current = Date.now() + 500;
|
|
7543
|
+
commitNavDragRef.current(e.clientX, e.clientY);
|
|
7544
|
+
};
|
|
7545
|
+
const blockSelectStart = (e) => {
|
|
7546
|
+
if (navDragRef.current || navPointerDragRef.current?.started || document.documentElement.hasAttribute("data-ohw-footer-press-drag")) {
|
|
7547
|
+
e.preventDefault();
|
|
7548
|
+
}
|
|
7549
|
+
};
|
|
7550
|
+
const onDragEnd = () => {
|
|
7551
|
+
if (!navDragRef.current) return;
|
|
7552
|
+
suppressNextClickRef.current = true;
|
|
7553
|
+
suppressClickUntilRef.current = Date.now() + 500;
|
|
7554
|
+
commitNavDragRef.current();
|
|
7555
|
+
};
|
|
7556
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
7557
|
+
document.addEventListener("pointermove", onPointerMove, true);
|
|
7558
|
+
document.addEventListener("pointerup", endPointerDrag, true);
|
|
7559
|
+
document.addEventListener("pointercancel", endPointerDrag, true);
|
|
7560
|
+
document.addEventListener("selectstart", blockSelectStart, true);
|
|
7561
|
+
document.addEventListener("dragend", onDragEnd, true);
|
|
7562
|
+
return () => {
|
|
7563
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
7564
|
+
document.removeEventListener("pointermove", onPointerMove, true);
|
|
7565
|
+
document.removeEventListener("pointerup", endPointerDrag, true);
|
|
7566
|
+
document.removeEventListener("pointercancel", endPointerDrag, true);
|
|
7567
|
+
document.removeEventListener("selectstart", blockSelectStart, true);
|
|
7568
|
+
document.removeEventListener("dragend", onDragEnd, true);
|
|
7569
|
+
unlockItemDragInteraction();
|
|
7570
|
+
};
|
|
7571
|
+
}, [
|
|
7572
|
+
activeElRef,
|
|
7573
|
+
deactivateRef,
|
|
7574
|
+
footerDragRef,
|
|
7575
|
+
getNavigationItemAnchor2,
|
|
7576
|
+
isDragHandleDisabled2,
|
|
7577
|
+
isEditMode,
|
|
7578
|
+
isNavbarButton3,
|
|
7579
|
+
linkPopoverOpenRef,
|
|
7580
|
+
selectedElRef,
|
|
7581
|
+
setLinkPopover,
|
|
7582
|
+
suppressNextClickRef
|
|
7583
|
+
]);
|
|
7584
|
+
const armNavPressFromChrome = useCallback3(
|
|
7585
|
+
(selected, clientX, clientY, pointerId) => {
|
|
7586
|
+
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
7587
|
+
if (!hrefKey || !isNavbarHrefKey(hrefKey)) return false;
|
|
7588
|
+
if (isNavbarButton3(selected) || isDragHandleDisabled2(selected)) return false;
|
|
7589
|
+
armItemPressDrag();
|
|
7590
|
+
navPointerDragRef.current = {
|
|
7591
|
+
el: selected,
|
|
7592
|
+
startX: clientX,
|
|
7593
|
+
startY: clientY,
|
|
7594
|
+
pointerId,
|
|
7595
|
+
wasSelected: true,
|
|
7596
|
+
started: false
|
|
7597
|
+
};
|
|
7598
|
+
return true;
|
|
7599
|
+
},
|
|
7600
|
+
[isDragHandleDisabled2, isNavbarButton3]
|
|
7601
|
+
);
|
|
7602
|
+
return {
|
|
7603
|
+
navDragRef,
|
|
7604
|
+
navDropSlots,
|
|
7605
|
+
activeNavDropIndex,
|
|
7606
|
+
startNavLinkDrag,
|
|
7607
|
+
commitNavDrag,
|
|
7608
|
+
onNavDragOver,
|
|
7609
|
+
armNavPressFromChrome,
|
|
7610
|
+
clearNavDragVisuals,
|
|
7611
|
+
refreshNavDragVisualsRef
|
|
7612
|
+
};
|
|
7613
|
+
}
|
|
7614
|
+
|
|
7615
|
+
// src/ui/navbar-container-chrome.tsx
|
|
7616
|
+
import { Plus as Plus2 } from "lucide-react";
|
|
7617
|
+
import { jsx as jsx21 } from "react/jsx-runtime";
|
|
7618
|
+
function NavbarContainerChrome({
|
|
7619
|
+
rect,
|
|
7620
|
+
onAdd
|
|
7621
|
+
}) {
|
|
7622
|
+
const chromeGap = 6;
|
|
7623
|
+
return /* @__PURE__ */ jsx21(
|
|
7624
|
+
"div",
|
|
7625
|
+
{
|
|
7626
|
+
"data-ohw-navbar-container-chrome": "",
|
|
7627
|
+
"data-ohw-bridge": "",
|
|
7628
|
+
className: "pointer-events-none fixed z-[2147483647]",
|
|
7629
|
+
style: {
|
|
7630
|
+
top: rect.top - chromeGap,
|
|
7631
|
+
left: rect.left - chromeGap,
|
|
7632
|
+
width: rect.width + chromeGap * 2,
|
|
7633
|
+
height: rect.height + chromeGap * 2
|
|
7634
|
+
},
|
|
7635
|
+
children: /* @__PURE__ */ jsx21(
|
|
7636
|
+
"button",
|
|
7637
|
+
{
|
|
7638
|
+
type: "button",
|
|
7639
|
+
"data-ohw-navbar-add-button": "",
|
|
7640
|
+
className: "pointer-events-auto absolute left-1/2 flex p-0.5 rounded-[10px] size-7 -translate-x-1/2 translate-y-1/2 items-center justify-center border border-border bg-background shadow-sm transition-colors hover:bg-muted/80",
|
|
7641
|
+
style: { top: "70%" },
|
|
7642
|
+
"aria-label": "Add item",
|
|
7643
|
+
onMouseDown: (e) => {
|
|
7644
|
+
e.preventDefault();
|
|
7645
|
+
e.stopPropagation();
|
|
7646
|
+
},
|
|
7647
|
+
onClick: (e) => {
|
|
7648
|
+
e.preventDefault();
|
|
7649
|
+
e.stopPropagation();
|
|
7650
|
+
onAdd();
|
|
7651
|
+
},
|
|
7652
|
+
children: /* @__PURE__ */ jsx21(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
7653
|
+
}
|
|
7654
|
+
)
|
|
7655
|
+
}
|
|
7656
|
+
);
|
|
7657
|
+
}
|
|
7658
|
+
|
|
7659
|
+
// src/ui/drop-indicator.tsx
|
|
7660
|
+
import * as React10 from "react";
|
|
7661
|
+
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
7662
|
+
var dropIndicatorVariants = cva(
|
|
7663
|
+
"ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
|
|
7664
|
+
{
|
|
7665
|
+
variants: {
|
|
7666
|
+
direction: {
|
|
7667
|
+
vertical: "h-6 w-[3px]",
|
|
7668
|
+
horizontal: "h-[3px] w-[200px]"
|
|
7669
|
+
},
|
|
7670
|
+
state: {
|
|
7671
|
+
default: "opacity-0",
|
|
7672
|
+
hover: "opacity-100",
|
|
7673
|
+
dragIdle: "opacity-40",
|
|
7674
|
+
dragActive: "opacity-100"
|
|
7675
|
+
}
|
|
7676
|
+
},
|
|
7677
|
+
defaultVariants: {
|
|
7678
|
+
direction: "vertical",
|
|
7679
|
+
state: "default"
|
|
7680
|
+
}
|
|
7681
|
+
}
|
|
7682
|
+
);
|
|
7683
|
+
var DropIndicator = React10.forwardRef(
|
|
7684
|
+
({ className, direction, state, ...props }, ref) => {
|
|
7685
|
+
return /* @__PURE__ */ jsx22(
|
|
7686
|
+
"div",
|
|
7687
|
+
{
|
|
7688
|
+
ref,
|
|
7689
|
+
"data-slot": "drop-indicator",
|
|
7690
|
+
"data-direction": direction ?? "vertical",
|
|
7691
|
+
"data-state": state ?? "default",
|
|
7692
|
+
"aria-hidden": "true",
|
|
7693
|
+
className: cn(dropIndicatorVariants({ direction, state }), className),
|
|
7694
|
+
...props
|
|
7695
|
+
}
|
|
7696
|
+
);
|
|
7697
|
+
}
|
|
7698
|
+
);
|
|
7699
|
+
DropIndicator.displayName = "DropIndicator";
|
|
7700
|
+
|
|
7701
|
+
// src/ui/badge.tsx
|
|
7702
|
+
import { jsx as jsx23 } from "react/jsx-runtime";
|
|
7703
|
+
var badgeVariants = cva(
|
|
7704
|
+
"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",
|
|
7705
|
+
{
|
|
7706
|
+
variants: {
|
|
7707
|
+
variant: {
|
|
7708
|
+
default: "border-transparent bg-primary text-primary-foreground",
|
|
7709
|
+
secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
7710
|
+
destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
|
|
7711
|
+
outline: "text-foreground"
|
|
7712
|
+
}
|
|
7713
|
+
},
|
|
7714
|
+
defaultVariants: {
|
|
7715
|
+
variant: "default"
|
|
7716
|
+
}
|
|
7717
|
+
}
|
|
7718
|
+
);
|
|
7719
|
+
function Badge({ className, variant, ...props }) {
|
|
7720
|
+
return /* @__PURE__ */ jsx23("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
7721
|
+
}
|
|
7722
|
+
|
|
7723
|
+
// src/OhhwellsBridge.tsx
|
|
7724
|
+
import { Link as Link2 } from "lucide-react";
|
|
7725
|
+
import { Fragment as Fragment5, jsx as jsx24, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
7726
|
+
var PRIMARY2 = "#0885FE";
|
|
7727
|
+
var IMAGE_FADE_MS = 300;
|
|
7728
|
+
function runOpacityFade(el, onDone) {
|
|
7729
|
+
const anim = el.animate([{ opacity: 0 }, { opacity: 1 }], {
|
|
7730
|
+
duration: IMAGE_FADE_MS,
|
|
7731
|
+
easing: "ease",
|
|
7732
|
+
fill: "forwards"
|
|
7733
|
+
});
|
|
7734
|
+
let finished = false;
|
|
7735
|
+
const finish = () => {
|
|
7736
|
+
if (finished) return;
|
|
7737
|
+
finished = true;
|
|
7738
|
+
anim.cancel();
|
|
7739
|
+
el.style.opacity = "";
|
|
7740
|
+
onDone();
|
|
7741
|
+
};
|
|
7742
|
+
anim.finished.then(finish).catch(finish);
|
|
7743
|
+
window.setTimeout(finish, IMAGE_FADE_MS + 100);
|
|
7744
|
+
}
|
|
7745
|
+
function fadeInImageElement(img, onReady) {
|
|
7746
|
+
onReady();
|
|
7747
|
+
img.style.opacity = "0";
|
|
7748
|
+
runOpacityFade(img, () => {
|
|
7749
|
+
img.style.opacity = "";
|
|
7750
|
+
});
|
|
7751
|
+
}
|
|
7752
|
+
function applyEditableImageSrc(img, url) {
|
|
7753
|
+
img.removeAttribute("srcset");
|
|
7754
|
+
img.removeAttribute("sizes");
|
|
7755
|
+
img.src = url;
|
|
7756
|
+
}
|
|
7757
|
+
function fadeInBgImage(el, url, onReady) {
|
|
7758
|
+
const prevPos = el.style.position;
|
|
7759
|
+
if (!prevPos || prevPos === "static") el.style.position = "relative";
|
|
7760
|
+
const layer = document.createElement("div");
|
|
7761
|
+
layer.setAttribute("data-ohw-bg-fade-layer", "");
|
|
7762
|
+
Object.assign(layer.style, {
|
|
7763
|
+
position: "absolute",
|
|
7764
|
+
inset: "0",
|
|
7765
|
+
zIndex: "0",
|
|
7766
|
+
backgroundImage: `url('${url}')`,
|
|
7767
|
+
backgroundSize: "cover",
|
|
7768
|
+
backgroundPosition: "center",
|
|
7769
|
+
backgroundRepeat: "no-repeat",
|
|
7770
|
+
opacity: "0",
|
|
7771
|
+
pointerEvents: "none"
|
|
7772
|
+
});
|
|
7773
|
+
el.prepend(layer);
|
|
7774
|
+
onReady();
|
|
7775
|
+
runOpacityFade(layer, () => {
|
|
7776
|
+
el.style.backgroundImage = `url('${url}')`;
|
|
7777
|
+
layer.remove();
|
|
7778
|
+
if (!prevPos || prevPos === "static") el.style.position = prevPos;
|
|
7779
|
+
});
|
|
7780
|
+
}
|
|
7781
|
+
function getSectionsTracker() {
|
|
7782
|
+
let el = document.querySelector("[data-ohw-sections-tracker]");
|
|
7783
|
+
if (!el) {
|
|
7784
|
+
el = document.createElement("div");
|
|
6574
7785
|
el.setAttribute("data-ohw-sections-tracker", "");
|
|
6575
7786
|
el.style.display = "none";
|
|
6576
7787
|
document.body.appendChild(el);
|
|
@@ -6690,7 +7901,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
6690
7901
|
const root = createRoot(container);
|
|
6691
7902
|
flushSync(() => {
|
|
6692
7903
|
root.render(
|
|
6693
|
-
/* @__PURE__ */
|
|
7904
|
+
/* @__PURE__ */ jsx24(
|
|
6694
7905
|
SchedulingWidget,
|
|
6695
7906
|
{
|
|
6696
7907
|
notifyOnConnect,
|
|
@@ -6752,7 +7963,20 @@ function isDragHandleDisabled(el) {
|
|
|
6752
7963
|
return raw === "true" || raw === "";
|
|
6753
7964
|
});
|
|
6754
7965
|
}
|
|
6755
|
-
function
|
|
7966
|
+
function canDragNavigationItem(anchor) {
|
|
7967
|
+
const { key, disabled } = getNavigationItemReorderState(anchor);
|
|
7968
|
+
return Boolean(key) && !disabled;
|
|
7969
|
+
}
|
|
7970
|
+
function syncNavigationDragCursorAttrs() {
|
|
7971
|
+
document.querySelectorAll("nav [data-ohw-href-key], footer [data-ohw-href-key]").forEach((el) => {
|
|
7972
|
+
if (!isNavigationItem(el) || !canDragNavigationItem(el)) {
|
|
7973
|
+
el.removeAttribute("data-ohw-can-drag");
|
|
7974
|
+
return;
|
|
7975
|
+
}
|
|
7976
|
+
el.setAttribute("data-ohw-can-drag", "");
|
|
7977
|
+
});
|
|
7978
|
+
}
|
|
7979
|
+
function collectEditableNodes(extraContent) {
|
|
6756
7980
|
const nodes = Array.from(document.querySelectorAll("[data-ohw-editable]")).map((el) => {
|
|
6757
7981
|
if (el.dataset.ohwEditable === "image") {
|
|
6758
7982
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
@@ -6780,6 +8004,14 @@ function collectEditableNodes() {
|
|
|
6780
8004
|
if (!key) return;
|
|
6781
8005
|
nodes.push({ key, type: "link", text: getLinkHref2(el) });
|
|
6782
8006
|
});
|
|
8007
|
+
if (extraContent) {
|
|
8008
|
+
for (const key of [NAV_ORDER_KEY, FOOTER_ORDER_KEY, NAV_COUNT_KEY]) {
|
|
8009
|
+
const text = extraContent[key];
|
|
8010
|
+
if (typeof text === "string" && text.length > 0) {
|
|
8011
|
+
nodes.push({ key, type: "meta", text });
|
|
8012
|
+
}
|
|
8013
|
+
}
|
|
8014
|
+
}
|
|
6783
8015
|
document.querySelectorAll('[data-ohw-editable="video"]').forEach((el) => {
|
|
6784
8016
|
const key = el.dataset.ohwKey ?? "";
|
|
6785
8017
|
const video = getVideoEl(el);
|
|
@@ -6893,6 +8125,11 @@ function getNavigationItemAnchor(el) {
|
|
|
6893
8125
|
function isNavigationItem(el) {
|
|
6894
8126
|
return getNavigationItemAnchor(el) !== null;
|
|
6895
8127
|
}
|
|
8128
|
+
function listNavigationItems() {
|
|
8129
|
+
return Array.from(
|
|
8130
|
+
document.querySelectorAll("nav [data-ohw-href-key], footer [data-ohw-href-key]")
|
|
8131
|
+
).filter((el) => isNavigationItem(el));
|
|
8132
|
+
}
|
|
6896
8133
|
function getNavigationItemReorderState(anchor) {
|
|
6897
8134
|
if (isNavbarButton2(anchor)) return { key: null, disabled: false };
|
|
6898
8135
|
return getReorderHandleStateFromAnchor(anchor);
|
|
@@ -6921,18 +8158,20 @@ function getNavigationRoot(el) {
|
|
|
6921
8158
|
if (explicit) return explicit;
|
|
6922
8159
|
return el.closest("nav, footer, aside");
|
|
6923
8160
|
}
|
|
8161
|
+
function countFooterNavItems(el) {
|
|
8162
|
+
return Array.from(el.querySelectorAll("[data-ohw-href-key]")).filter(isNavigationItem).length;
|
|
8163
|
+
}
|
|
6924
8164
|
function findFooterItemGroup(item) {
|
|
8165
|
+
const explicit = item.closest("[data-ohw-footer-col], [data-ohw-footer-column]");
|
|
8166
|
+
if (explicit) return explicit;
|
|
6925
8167
|
const footer = item.closest("footer");
|
|
6926
8168
|
if (!footer) return null;
|
|
6927
8169
|
let node = item.parentElement;
|
|
6928
8170
|
while (node && node !== footer) {
|
|
6929
|
-
|
|
6930
|
-
node.querySelectorAll(":scope > [data-ohw-href-key]")
|
|
6931
|
-
).some(isNavigationItem);
|
|
6932
|
-
if (hasDirectNavItems) return node;
|
|
8171
|
+
if (countFooterNavItems(node) >= 2) return node;
|
|
6933
8172
|
node = node.parentElement;
|
|
6934
8173
|
}
|
|
6935
|
-
return
|
|
8174
|
+
return footer;
|
|
6936
8175
|
}
|
|
6937
8176
|
function isNavigationRoot(el) {
|
|
6938
8177
|
return el.hasAttribute("data-ohw-nav-root") || el.matches("nav, footer, aside");
|
|
@@ -6940,16 +8179,49 @@ function isNavigationRoot(el) {
|
|
|
6940
8179
|
function isInferredFooterGroup(el) {
|
|
6941
8180
|
const footer = el.closest("footer");
|
|
6942
8181
|
if (!footer || el === footer) return false;
|
|
6943
|
-
|
|
8182
|
+
if (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column")) return true;
|
|
8183
|
+
return countFooterNavItems(el) >= 2;
|
|
6944
8184
|
}
|
|
6945
8185
|
function isNavigationContainer(el) {
|
|
6946
|
-
return el.hasAttribute("data-ohw-nav-container") || isNavigationRoot(el) || isInferredFooterGroup(el);
|
|
8186
|
+
return el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isNavigationRoot(el) || isInferredFooterGroup(el);
|
|
8187
|
+
}
|
|
8188
|
+
function isNavbarLinksContainer(el) {
|
|
8189
|
+
return el.hasAttribute("data-ohw-nav-container");
|
|
8190
|
+
}
|
|
8191
|
+
function getFooterColumn(el) {
|
|
8192
|
+
return el.closest("[data-ohw-footer-col], [data-ohw-footer-column]");
|
|
8193
|
+
}
|
|
8194
|
+
function resolveFooterColumnSelectionTarget(target, clientX, clientY) {
|
|
8195
|
+
if (getNavigationItemAnchor(target)) return null;
|
|
8196
|
+
const column = getFooterColumn(target);
|
|
8197
|
+
if (!column) return null;
|
|
8198
|
+
if (isPointOverNavItem(column, clientX, clientY)) return null;
|
|
8199
|
+
return column;
|
|
6947
8200
|
}
|
|
6948
8201
|
function isPointOverNavigation(x, y) {
|
|
8202
|
+
const roots = /* @__PURE__ */ new Set();
|
|
6949
8203
|
const navRoot = document.querySelector("[data-ohw-nav-root]") ?? document.querySelector("nav");
|
|
6950
|
-
if (
|
|
6951
|
-
const
|
|
6952
|
-
|
|
8204
|
+
if (navRoot) roots.add(navRoot);
|
|
8205
|
+
const footer = document.querySelector("footer");
|
|
8206
|
+
if (footer) roots.add(footer);
|
|
8207
|
+
for (const root of roots) {
|
|
8208
|
+
const r2 = root.getBoundingClientRect();
|
|
8209
|
+
if (x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom) return true;
|
|
8210
|
+
}
|
|
8211
|
+
return false;
|
|
8212
|
+
}
|
|
8213
|
+
function findHoveredNavOrFooterContainer(x, y) {
|
|
8214
|
+
const candidates = [
|
|
8215
|
+
...document.querySelectorAll("[data-ohw-nav-container]"),
|
|
8216
|
+
...listFooterColumns()
|
|
8217
|
+
];
|
|
8218
|
+
for (const container of candidates) {
|
|
8219
|
+
const r2 = container.getBoundingClientRect();
|
|
8220
|
+
if (x < r2.left || x > r2.right || y < r2.top || y > r2.bottom) continue;
|
|
8221
|
+
if (isPointOverNavItem(container, x, y)) continue;
|
|
8222
|
+
return container;
|
|
8223
|
+
}
|
|
8224
|
+
return null;
|
|
6953
8225
|
}
|
|
6954
8226
|
function isPointOverNavItem(container, x, y) {
|
|
6955
8227
|
return Array.from(container.querySelectorAll("[data-ohw-href-key]")).some((el) => {
|
|
@@ -6982,36 +8254,63 @@ function getNavigationSelectionParent(el) {
|
|
|
6982
8254
|
if (isNavigationItem(el)) {
|
|
6983
8255
|
const explicit = el.closest("[data-ohw-nav-container]");
|
|
6984
8256
|
if (explicit) return explicit;
|
|
8257
|
+
const footerColumn = getFooterColumn(el);
|
|
8258
|
+
if (footerColumn) return footerColumn;
|
|
6985
8259
|
const footerGroup = findFooterItemGroup(el);
|
|
6986
8260
|
if (footerGroup) return footerGroup;
|
|
6987
8261
|
return getNavigationRoot(el);
|
|
6988
8262
|
}
|
|
6989
|
-
if (el.hasAttribute("data-ohw-nav-container") || isInferredFooterGroup(el)) {
|
|
8263
|
+
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup(el)) {
|
|
6990
8264
|
return getNavigationRoot(el);
|
|
6991
8265
|
}
|
|
6992
8266
|
return null;
|
|
6993
8267
|
}
|
|
8268
|
+
function collectNavigationItemSiblingHintRects(selected) {
|
|
8269
|
+
if (!isNavigationItem(selected)) return [];
|
|
8270
|
+
const footerColumn = getFooterColumn(selected);
|
|
8271
|
+
if (footerColumn) {
|
|
8272
|
+
return listFooterLinksInColumn(footerColumn).filter((link) => link !== selected).map((link) => link.getBoundingClientRect());
|
|
8273
|
+
}
|
|
8274
|
+
const navContainer = selected.closest("[data-ohw-nav-container], [data-ohw-nav-drawer]");
|
|
8275
|
+
if (navContainer) {
|
|
8276
|
+
return Array.from(navContainer.querySelectorAll("[data-ohw-href-key]")).filter((el) => isNavigationItem(el) && el !== selected).map((el) => el.getBoundingClientRect());
|
|
8277
|
+
}
|
|
8278
|
+
return listNavigationItems().filter((el) => el !== selected).map((el) => el.getBoundingClientRect());
|
|
8279
|
+
}
|
|
6994
8280
|
function placeCaretAtPoint(el, x, y) {
|
|
6995
8281
|
const selection = window.getSelection();
|
|
6996
8282
|
if (!selection) return;
|
|
6997
|
-
|
|
6998
|
-
|
|
6999
|
-
|
|
7000
|
-
|
|
7001
|
-
|
|
7002
|
-
|
|
8283
|
+
const overlays = Array.from(
|
|
8284
|
+
document.querySelectorAll(
|
|
8285
|
+
"[data-ohw-item-drag-surface], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-ohw-item-toolbar-anchor]"
|
|
8286
|
+
)
|
|
8287
|
+
);
|
|
8288
|
+
const prevPointerEvents = overlays.map((node) => node.style.pointerEvents);
|
|
8289
|
+
for (const node of overlays) node.style.pointerEvents = "none";
|
|
8290
|
+
try {
|
|
8291
|
+
if (typeof document.caretRangeFromPoint === "function") {
|
|
8292
|
+
const range = document.caretRangeFromPoint(x, y);
|
|
8293
|
+
if (range && el.contains(range.startContainer)) {
|
|
8294
|
+
selection.removeAllRanges();
|
|
8295
|
+
selection.addRange(range);
|
|
8296
|
+
return;
|
|
8297
|
+
}
|
|
7003
8298
|
}
|
|
7004
|
-
|
|
7005
|
-
|
|
7006
|
-
|
|
7007
|
-
|
|
7008
|
-
|
|
7009
|
-
|
|
7010
|
-
|
|
7011
|
-
|
|
7012
|
-
|
|
7013
|
-
|
|
8299
|
+
const caretPositionFromPoint = document.caretPositionFromPoint;
|
|
8300
|
+
if (typeof caretPositionFromPoint === "function") {
|
|
8301
|
+
const position = caretPositionFromPoint(x, y);
|
|
8302
|
+
if (position && el.contains(position.offsetNode)) {
|
|
8303
|
+
const range = document.createRange();
|
|
8304
|
+
range.setStart(position.offsetNode, position.offset);
|
|
8305
|
+
range.collapse(true);
|
|
8306
|
+
selection.removeAllRanges();
|
|
8307
|
+
selection.addRange(range);
|
|
8308
|
+
}
|
|
7014
8309
|
}
|
|
8310
|
+
} finally {
|
|
8311
|
+
overlays.forEach((node, i) => {
|
|
8312
|
+
node.style.pointerEvents = prevPointerEvents[i] ?? "";
|
|
8313
|
+
});
|
|
7015
8314
|
}
|
|
7016
8315
|
}
|
|
7017
8316
|
function selectAllTextInEditable(el) {
|
|
@@ -7153,6 +8452,9 @@ var ICONS = {
|
|
|
7153
8452
|
insertUnorderedList: '<line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/>',
|
|
7154
8453
|
insertOrderedList: '<line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"/>'
|
|
7155
8454
|
};
|
|
8455
|
+
var SELECTION_CHROME_GAP2 = 4;
|
|
8456
|
+
var TOOLBAR_STROKE_GAP2 = 4;
|
|
8457
|
+
var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
|
|
7156
8458
|
var TOOLBAR_GROUPS = [
|
|
7157
8459
|
[
|
|
7158
8460
|
{ cmd: "bold", title: "Bold" },
|
|
@@ -7174,9 +8476,10 @@ function EditGlowChrome({
|
|
|
7174
8476
|
rect,
|
|
7175
8477
|
elRef,
|
|
7176
8478
|
reorderHrefKey,
|
|
7177
|
-
dragDisabled = false
|
|
8479
|
+
dragDisabled = false,
|
|
8480
|
+
hideHandle = false
|
|
7178
8481
|
}) {
|
|
7179
|
-
const GAP =
|
|
8482
|
+
const GAP = SELECTION_CHROME_GAP2;
|
|
7180
8483
|
return /* @__PURE__ */ jsxs13(
|
|
7181
8484
|
"div",
|
|
7182
8485
|
{
|
|
@@ -7192,7 +8495,7 @@ function EditGlowChrome({
|
|
|
7192
8495
|
zIndex: 2147483646
|
|
7193
8496
|
},
|
|
7194
8497
|
children: [
|
|
7195
|
-
/* @__PURE__ */
|
|
8498
|
+
/* @__PURE__ */ jsx24(
|
|
7196
8499
|
"div",
|
|
7197
8500
|
{
|
|
7198
8501
|
style: {
|
|
@@ -7200,12 +8503,12 @@ function EditGlowChrome({
|
|
|
7200
8503
|
inset: 0,
|
|
7201
8504
|
border: "2px solid var(--ohw-primary, #0885FE)",
|
|
7202
8505
|
borderRadius: 8,
|
|
7203
|
-
boxShadow: "0 0 0 4px
|
|
8506
|
+
boxShadow: "0 0 0 4px color-mix(in srgb, var(--ohw-primary, #0885FE) 12%, transparent)",
|
|
7204
8507
|
pointerEvents: "none"
|
|
7205
8508
|
}
|
|
7206
8509
|
}
|
|
7207
8510
|
),
|
|
7208
|
-
reorderHrefKey && /* @__PURE__ */
|
|
8511
|
+
reorderHrefKey && !hideHandle && /* @__PURE__ */ jsx24(
|
|
7209
8512
|
"div",
|
|
7210
8513
|
{
|
|
7211
8514
|
"data-ohw-drag-handle-container": "",
|
|
@@ -7217,7 +8520,7 @@ function EditGlowChrome({
|
|
|
7217
8520
|
transform: "translate(calc(-100% - 7px), -50%)",
|
|
7218
8521
|
pointerEvents: dragDisabled ? "none" : "auto"
|
|
7219
8522
|
},
|
|
7220
|
-
children: /* @__PURE__ */
|
|
8523
|
+
children: /* @__PURE__ */ jsx24(
|
|
7221
8524
|
DragHandle,
|
|
7222
8525
|
{
|
|
7223
8526
|
"aria-label": `Reorder ${reorderHrefKey}`,
|
|
@@ -7248,6 +8551,7 @@ function applyVisibleViewport(el, parentScroll) {
|
|
|
7248
8551
|
el.style.top = `${top}px`;
|
|
7249
8552
|
el.style.height = `${height}px`;
|
|
7250
8553
|
}
|
|
8554
|
+
var TOOLBAR_EDGE_MARGIN2 = 4;
|
|
7251
8555
|
function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
7252
8556
|
const isAbove = transform.includes("translateY(-100%)");
|
|
7253
8557
|
let visualTop = isAbove ? top - approxH : top;
|
|
@@ -7271,10 +8575,16 @@ function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
|
7271
8575
|
const pinnedTop = Math.min(maxBottom - approxH, Math.max(minTop, clip.top + gap));
|
|
7272
8576
|
return { top: pinnedTop + approxH, transform: "translateX(-50%) translateY(-100%)" };
|
|
7273
8577
|
}
|
|
7274
|
-
function
|
|
7275
|
-
const
|
|
8578
|
+
function clampToolbarLeft(centerX, toolbarWidth) {
|
|
8579
|
+
const half = toolbarWidth / 2;
|
|
8580
|
+
return Math.max(
|
|
8581
|
+
TOOLBAR_EDGE_MARGIN2 + half,
|
|
8582
|
+
Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN2 - half)
|
|
8583
|
+
);
|
|
8584
|
+
}
|
|
8585
|
+
function calcToolbarPos(rect, parentScroll, toolbarW = 306) {
|
|
8586
|
+
const GAP = TOOLBAR_OFFSET_FROM_ELEMENT;
|
|
7276
8587
|
const APPROX_H = 32;
|
|
7277
|
-
const APPROX_W = approxW;
|
|
7278
8588
|
const clip = getIframeVisibleClip(parentScroll);
|
|
7279
8589
|
const clipTop = clip?.top ?? 0;
|
|
7280
8590
|
const canvasTopInIframe = parentScroll != null ? parentScroll.headerH - parentScroll.iframeOffsetTop : 0;
|
|
@@ -7304,7 +8614,7 @@ function calcToolbarPos(rect, parentScroll, approxW = 306) {
|
|
|
7304
8614
|
transform = clamped.transform;
|
|
7305
8615
|
}
|
|
7306
8616
|
const rawLeft = rect.left + rect.width / 2;
|
|
7307
|
-
const left =
|
|
8617
|
+
const left = clampToolbarLeft(rawLeft, toolbarW);
|
|
7308
8618
|
return { top, left, transform };
|
|
7309
8619
|
}
|
|
7310
8620
|
function resolveItemInteractionState(rect, parentScroll) {
|
|
@@ -7320,11 +8630,37 @@ function FloatingToolbar({
|
|
|
7320
8630
|
showEditLink,
|
|
7321
8631
|
onEditLink
|
|
7322
8632
|
}) {
|
|
7323
|
-
const
|
|
7324
|
-
|
|
8633
|
+
const localRef = React11.useRef(null);
|
|
8634
|
+
const [measuredW, setMeasuredW] = React11.useState(330);
|
|
8635
|
+
const setRefs = React11.useCallback(
|
|
8636
|
+
(node) => {
|
|
8637
|
+
localRef.current = node;
|
|
8638
|
+
if (typeof elRef === "function") elRef(node);
|
|
8639
|
+
else if (elRef) elRef.current = node;
|
|
8640
|
+
if (node) {
|
|
8641
|
+
const w = node.offsetWidth;
|
|
8642
|
+
if (w > 0) setMeasuredW(w);
|
|
8643
|
+
}
|
|
8644
|
+
},
|
|
8645
|
+
[elRef]
|
|
8646
|
+
);
|
|
8647
|
+
React11.useLayoutEffect(() => {
|
|
8648
|
+
const node = localRef.current;
|
|
8649
|
+
if (!node) return;
|
|
8650
|
+
const update = () => {
|
|
8651
|
+
const w = node.offsetWidth;
|
|
8652
|
+
if (w > 0) setMeasuredW(w);
|
|
8653
|
+
};
|
|
8654
|
+
update();
|
|
8655
|
+
const ro = new ResizeObserver(update);
|
|
8656
|
+
ro.observe(node);
|
|
8657
|
+
return () => ro.disconnect();
|
|
8658
|
+
}, [showEditLink, activeCommands]);
|
|
8659
|
+
const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
|
|
8660
|
+
return /* @__PURE__ */ jsx24(
|
|
7325
8661
|
"div",
|
|
7326
8662
|
{
|
|
7327
|
-
ref:
|
|
8663
|
+
ref: setRefs,
|
|
7328
8664
|
style: {
|
|
7329
8665
|
position: "fixed",
|
|
7330
8666
|
top,
|
|
@@ -7334,11 +8670,11 @@ function FloatingToolbar({
|
|
|
7334
8670
|
pointerEvents: "auto"
|
|
7335
8671
|
},
|
|
7336
8672
|
children: /* @__PURE__ */ jsxs13(CustomToolbar, { children: [
|
|
7337
|
-
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs13(
|
|
7338
|
-
gi > 0 && /* @__PURE__ */
|
|
8673
|
+
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs13(React11.Fragment, { children: [
|
|
8674
|
+
gi > 0 && /* @__PURE__ */ jsx24(CustomToolbarDivider, {}),
|
|
7339
8675
|
btns.map((btn) => {
|
|
7340
8676
|
const isActive = activeCommands.has(btn.cmd);
|
|
7341
|
-
return /* @__PURE__ */
|
|
8677
|
+
return /* @__PURE__ */ jsx24(
|
|
7342
8678
|
CustomToolbarButton,
|
|
7343
8679
|
{
|
|
7344
8680
|
title: btn.title,
|
|
@@ -7347,7 +8683,7 @@ function FloatingToolbar({
|
|
|
7347
8683
|
e.preventDefault();
|
|
7348
8684
|
onCommand(btn.cmd);
|
|
7349
8685
|
},
|
|
7350
|
-
children: /* @__PURE__ */
|
|
8686
|
+
children: /* @__PURE__ */ jsx24(
|
|
7351
8687
|
"svg",
|
|
7352
8688
|
{
|
|
7353
8689
|
width: "16",
|
|
@@ -7368,7 +8704,7 @@ function FloatingToolbar({
|
|
|
7368
8704
|
);
|
|
7369
8705
|
})
|
|
7370
8706
|
] }, gi)),
|
|
7371
|
-
showEditLink ? /* @__PURE__ */
|
|
8707
|
+
showEditLink ? /* @__PURE__ */ jsx24(
|
|
7372
8708
|
CustomToolbarButton,
|
|
7373
8709
|
{
|
|
7374
8710
|
type: "button",
|
|
@@ -7382,7 +8718,7 @@ function FloatingToolbar({
|
|
|
7382
8718
|
e.preventDefault();
|
|
7383
8719
|
e.stopPropagation();
|
|
7384
8720
|
},
|
|
7385
|
-
children: /* @__PURE__ */
|
|
8721
|
+
children: /* @__PURE__ */ jsx24(Link2, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
7386
8722
|
}
|
|
7387
8723
|
) : null
|
|
7388
8724
|
] })
|
|
@@ -7399,7 +8735,7 @@ function StateToggle({
|
|
|
7399
8735
|
states,
|
|
7400
8736
|
onStateChange
|
|
7401
8737
|
}) {
|
|
7402
|
-
return /* @__PURE__ */
|
|
8738
|
+
return /* @__PURE__ */ jsx24(
|
|
7403
8739
|
ToggleGroup,
|
|
7404
8740
|
{
|
|
7405
8741
|
"data-ohw-state-toggle": "",
|
|
@@ -7413,7 +8749,7 @@ function StateToggle({
|
|
|
7413
8749
|
left: rect.right - 8,
|
|
7414
8750
|
transform: "translateX(-100%)"
|
|
7415
8751
|
},
|
|
7416
|
-
children: states.map((state) => /* @__PURE__ */
|
|
8752
|
+
children: states.map((state) => /* @__PURE__ */ jsx24(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
|
|
7417
8753
|
}
|
|
7418
8754
|
);
|
|
7419
8755
|
}
|
|
@@ -7440,8 +8776,8 @@ function OhhwellsBridge() {
|
|
|
7440
8776
|
const router = useRouter2();
|
|
7441
8777
|
const searchParams = useSearchParams();
|
|
7442
8778
|
const isEditMode = isEditSessionActive();
|
|
7443
|
-
const [bridgeRoot, setBridgeRoot] =
|
|
7444
|
-
|
|
8779
|
+
const [bridgeRoot, setBridgeRoot] = useState7(null);
|
|
8780
|
+
useEffect8(() => {
|
|
7445
8781
|
const figtreeFontId = "ohw-figtree-font";
|
|
7446
8782
|
if (!document.getElementById(figtreeFontId)) {
|
|
7447
8783
|
const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
|
|
@@ -7469,91 +8805,136 @@ function OhhwellsBridge() {
|
|
|
7469
8805
|
const subdomainFromQuery = searchParams.get("subdomain");
|
|
7470
8806
|
const subdomain = resolveSubdomain(subdomainFromQuery);
|
|
7471
8807
|
useLinkHrefGuardian(pathname, subdomain, isEditMode);
|
|
7472
|
-
const postToParent2 =
|
|
8808
|
+
const postToParent2 = useCallback4((data) => {
|
|
7473
8809
|
if (typeof window !== "undefined" && window.parent !== window) {
|
|
7474
8810
|
window.parent.postMessage(data, "*");
|
|
7475
8811
|
}
|
|
7476
8812
|
}, []);
|
|
7477
|
-
const [fetchState, setFetchState] =
|
|
7478
|
-
const autoSaveTimers =
|
|
7479
|
-
const activeElRef =
|
|
7480
|
-
const selectedElRef =
|
|
7481
|
-
const
|
|
7482
|
-
const
|
|
7483
|
-
const
|
|
7484
|
-
const
|
|
7485
|
-
const
|
|
7486
|
-
const
|
|
8813
|
+
const [fetchState, setFetchState] = useState7("idle");
|
|
8814
|
+
const autoSaveTimers = useRef7(/* @__PURE__ */ new Map());
|
|
8815
|
+
const activeElRef = useRef7(null);
|
|
8816
|
+
const selectedElRef = useRef7(null);
|
|
8817
|
+
const selectedHrefKeyRef = useRef7(null);
|
|
8818
|
+
const selectedFooterColAttrRef = useRef7(null);
|
|
8819
|
+
const originalContentRef = useRef7(null);
|
|
8820
|
+
const activeStateElRef = useRef7(null);
|
|
8821
|
+
const parentScrollRef = useRef7(null);
|
|
8822
|
+
const visibleViewportRef = useRef7(null);
|
|
8823
|
+
const [dialogPortalContainer, setDialogPortalContainer] = useState7(null);
|
|
8824
|
+
const attachVisibleViewport = useCallback4((node) => {
|
|
7487
8825
|
visibleViewportRef.current = node;
|
|
7488
8826
|
setDialogPortalContainer(node);
|
|
7489
8827
|
if (node) applyVisibleViewport(node, parentScrollRef.current);
|
|
7490
8828
|
}, []);
|
|
7491
|
-
const toolbarElRef =
|
|
7492
|
-
const glowElRef =
|
|
7493
|
-
const hoveredImageRef =
|
|
7494
|
-
const hoveredImageHasTextOverlapRef =
|
|
7495
|
-
const dragOverElRef =
|
|
7496
|
-
const [mediaHover, setMediaHover] =
|
|
7497
|
-
const [uploadingRects, setUploadingRects] =
|
|
7498
|
-
const hoveredGapRef =
|
|
7499
|
-
const imageUnhoverTimerRef =
|
|
7500
|
-
const imageShowTimerRef =
|
|
7501
|
-
const editStylesRef =
|
|
7502
|
-
const activateRef =
|
|
8829
|
+
const toolbarElRef = useRef7(null);
|
|
8830
|
+
const glowElRef = useRef7(null);
|
|
8831
|
+
const hoveredImageRef = useRef7(null);
|
|
8832
|
+
const hoveredImageHasTextOverlapRef = useRef7(false);
|
|
8833
|
+
const dragOverElRef = useRef7(null);
|
|
8834
|
+
const [mediaHover, setMediaHover] = useState7(null);
|
|
8835
|
+
const [uploadingRects, setUploadingRects] = useState7({});
|
|
8836
|
+
const hoveredGapRef = useRef7(null);
|
|
8837
|
+
const imageUnhoverTimerRef = useRef7(null);
|
|
8838
|
+
const imageShowTimerRef = useRef7(null);
|
|
8839
|
+
const editStylesRef = useRef7(null);
|
|
8840
|
+
const activateRef = useRef7(() => {
|
|
7503
8841
|
});
|
|
7504
|
-
const deactivateRef =
|
|
8842
|
+
const deactivateRef = useRef7(() => {
|
|
7505
8843
|
});
|
|
7506
|
-
const selectRef =
|
|
8844
|
+
const selectRef = useRef7(() => {
|
|
7507
8845
|
});
|
|
7508
|
-
const selectFrameRef =
|
|
8846
|
+
const selectFrameRef = useRef7(() => {
|
|
7509
8847
|
});
|
|
7510
|
-
const deselectRef =
|
|
8848
|
+
const deselectRef = useRef7(() => {
|
|
7511
8849
|
});
|
|
7512
|
-
const reselectNavigationItemRef =
|
|
8850
|
+
const reselectNavigationItemRef = useRef7(() => {
|
|
7513
8851
|
});
|
|
7514
|
-
const commitNavigationTextEditRef =
|
|
8852
|
+
const commitNavigationTextEditRef = useRef7(() => {
|
|
7515
8853
|
});
|
|
7516
|
-
const refreshActiveCommandsRef =
|
|
8854
|
+
const refreshActiveCommandsRef = useRef7(() => {
|
|
7517
8855
|
});
|
|
7518
|
-
const postToParentRef =
|
|
8856
|
+
const postToParentRef = useRef7(postToParent2);
|
|
7519
8857
|
postToParentRef.current = postToParent2;
|
|
7520
|
-
const sectionsLoadedRef =
|
|
7521
|
-
const pendingScheduleConfigRequests =
|
|
7522
|
-
const [toolbarRect, setToolbarRect] =
|
|
7523
|
-
const [toolbarVariant, setToolbarVariant] =
|
|
7524
|
-
const toolbarVariantRef =
|
|
8858
|
+
const sectionsLoadedRef = useRef7(false);
|
|
8859
|
+
const pendingScheduleConfigRequests = useRef7([]);
|
|
8860
|
+
const [toolbarRect, setToolbarRect] = useState7(null);
|
|
8861
|
+
const [toolbarVariant, setToolbarVariant] = useState7("none");
|
|
8862
|
+
const toolbarVariantRef = useRef7("none");
|
|
7525
8863
|
toolbarVariantRef.current = toolbarVariant;
|
|
7526
|
-
const [
|
|
7527
|
-
const [
|
|
7528
|
-
const [
|
|
7529
|
-
const [
|
|
7530
|
-
const [
|
|
7531
|
-
const [
|
|
7532
|
-
const [
|
|
7533
|
-
const
|
|
7534
|
-
const
|
|
7535
|
-
const
|
|
7536
|
-
const
|
|
7537
|
-
const
|
|
7538
|
-
const
|
|
7539
|
-
const [
|
|
7540
|
-
const [
|
|
7541
|
-
const
|
|
7542
|
-
const
|
|
7543
|
-
const
|
|
7544
|
-
const [
|
|
7545
|
-
const [
|
|
7546
|
-
const
|
|
7547
|
-
const
|
|
7548
|
-
const
|
|
7549
|
-
const
|
|
7550
|
-
const
|
|
8864
|
+
const [selectedIsCta, setSelectedIsCta] = useState7(false);
|
|
8865
|
+
const [reorderHrefKey, setReorderHrefKey] = useState7(null);
|
|
8866
|
+
const [reorderDragDisabled, setReorderDragDisabled] = useState7(false);
|
|
8867
|
+
const [toggleState, setToggleState] = useState7(null);
|
|
8868
|
+
const [maxBadge, setMaxBadge] = useState7(null);
|
|
8869
|
+
const [activeCommands, setActiveCommands] = useState7(/* @__PURE__ */ new Set());
|
|
8870
|
+
const [sectionGap, setSectionGap] = useState7(null);
|
|
8871
|
+
const [toolbarShowEditLink, setToolbarShowEditLink] = useState7(false);
|
|
8872
|
+
const hoveredNavContainerRef = useRef7(null);
|
|
8873
|
+
const [hoveredNavContainerRect, setHoveredNavContainerRect] = useState7(null);
|
|
8874
|
+
const hoveredItemElRef = useRef7(null);
|
|
8875
|
+
const [hoveredItemRect, setHoveredItemRect] = useState7(null);
|
|
8876
|
+
const siblingHintElRef = useRef7(null);
|
|
8877
|
+
const [siblingHintRect, setSiblingHintRect] = useState7(null);
|
|
8878
|
+
const [siblingHintRects, setSiblingHintRects] = useState7([]);
|
|
8879
|
+
const [isItemDragging, setIsItemDragging] = useState7(false);
|
|
8880
|
+
const [isFooterFrameSelection, setIsFooterFrameSelection] = useState7(false);
|
|
8881
|
+
const footerDragRef = useRef7(null);
|
|
8882
|
+
const [footerDropSlots, setFooterDropSlots] = useState7([]);
|
|
8883
|
+
const [activeFooterDropIndex, setActiveFooterDropIndex] = useState7(null);
|
|
8884
|
+
const [draggedItemRect, setDraggedItemRect] = useState7(null);
|
|
8885
|
+
const footerPointerDragRef = useRef7(null);
|
|
8886
|
+
const suppressNextClickRef = useRef7(false);
|
|
8887
|
+
const suppressClickUntilRef = useRef7(0);
|
|
8888
|
+
const [linkPopover, setLinkPopover] = useState7(null);
|
|
8889
|
+
const linkPopoverSessionRef = useRef7(null);
|
|
8890
|
+
const addNavAfterAnchorRef = useRef7(null);
|
|
8891
|
+
const editContentRef = useRef7({});
|
|
8892
|
+
const [sitePages, setSitePages] = useState7([]);
|
|
8893
|
+
const [sectionsByPath, setSectionsByPath] = useState7({});
|
|
8894
|
+
const sectionsPrefetchGenRef = useRef7(0);
|
|
8895
|
+
const setLinkPopoverRef = useRef7(setLinkPopover);
|
|
8896
|
+
const linkPopoverPanelRef = useRef7(null);
|
|
8897
|
+
const linkPopoverOpenRef = useRef7(false);
|
|
8898
|
+
const linkPopoverGraceUntilRef = useRef7(0);
|
|
7551
8899
|
setLinkPopoverRef.current = setLinkPopover;
|
|
7552
8900
|
linkPopoverSessionRef.current = linkPopover;
|
|
8901
|
+
const {
|
|
8902
|
+
navDragRef,
|
|
8903
|
+
navDropSlots,
|
|
8904
|
+
activeNavDropIndex,
|
|
8905
|
+
startNavLinkDrag,
|
|
8906
|
+
commitNavDrag,
|
|
8907
|
+
onNavDragOver,
|
|
8908
|
+
armNavPressFromChrome,
|
|
8909
|
+
refreshNavDragVisualsRef
|
|
8910
|
+
} = useNavItemDrag({
|
|
8911
|
+
isEditMode,
|
|
8912
|
+
editContentRef,
|
|
8913
|
+
selectedElRef,
|
|
8914
|
+
activeElRef,
|
|
8915
|
+
footerDragRef,
|
|
8916
|
+
suppressNextClickRef,
|
|
8917
|
+
suppressClickUntilRef,
|
|
8918
|
+
siblingHintElRef,
|
|
8919
|
+
postToParentRef,
|
|
8920
|
+
deselectRef,
|
|
8921
|
+
selectRef,
|
|
8922
|
+
deactivateRef,
|
|
8923
|
+
setLinkPopover: () => setLinkPopover(null),
|
|
8924
|
+
linkPopoverOpenRef,
|
|
8925
|
+
setIsItemDragging,
|
|
8926
|
+
setDraggedItemRect,
|
|
8927
|
+
setSiblingHintRect,
|
|
8928
|
+
setSiblingHintRects,
|
|
8929
|
+
setToolbarRect,
|
|
8930
|
+
getNavigationItemAnchor,
|
|
8931
|
+
isDragHandleDisabled,
|
|
8932
|
+
isNavbarButton: isNavbarButton2
|
|
8933
|
+
});
|
|
7553
8934
|
const bumpLinkPopoverGrace = () => {
|
|
7554
8935
|
linkPopoverGraceUntilRef.current = Date.now() + 350;
|
|
7555
8936
|
};
|
|
7556
|
-
const runSectionsPrefetch =
|
|
8937
|
+
const runSectionsPrefetch = useCallback4((pages) => {
|
|
7557
8938
|
if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
|
|
7558
8939
|
const gen = ++sectionsPrefetchGenRef.current;
|
|
7559
8940
|
const paths = pages.map((p) => p.path);
|
|
@@ -7572,10 +8953,24 @@ function OhhwellsBridge() {
|
|
|
7572
8953
|
);
|
|
7573
8954
|
});
|
|
7574
8955
|
}, [isEditMode, pathname]);
|
|
7575
|
-
const runSectionsPrefetchRef =
|
|
8956
|
+
const runSectionsPrefetchRef = useRef7(runSectionsPrefetch);
|
|
7576
8957
|
runSectionsPrefetchRef.current = runSectionsPrefetch;
|
|
7577
|
-
|
|
7578
|
-
if (!linkPopover)
|
|
8958
|
+
useEffect8(() => {
|
|
8959
|
+
if (!linkPopover) {
|
|
8960
|
+
document.documentElement.removeAttribute("data-ohw-link-popover-open");
|
|
8961
|
+
return;
|
|
8962
|
+
}
|
|
8963
|
+
document.documentElement.setAttribute("data-ohw-link-popover-open", "");
|
|
8964
|
+
hoveredItemElRef.current = null;
|
|
8965
|
+
setHoveredItemRect(null);
|
|
8966
|
+
hoveredNavContainerRef.current = null;
|
|
8967
|
+
setHoveredNavContainerRect(null);
|
|
8968
|
+
siblingHintElRef.current = null;
|
|
8969
|
+
setSiblingHintRect(null);
|
|
8970
|
+
setSiblingHintRects([]);
|
|
8971
|
+
if (selectedElRef.current || toolbarVariantRef.current !== "none") {
|
|
8972
|
+
deselectRef.current();
|
|
8973
|
+
}
|
|
7579
8974
|
if (hoveredImageRef.current) {
|
|
7580
8975
|
hoveredImageRef.current = null;
|
|
7581
8976
|
hoveredImageHasTextOverlapRef.current = false;
|
|
@@ -7609,7 +9004,7 @@ function OhhwellsBridge() {
|
|
|
7609
9004
|
document.removeEventListener("touchmove", preventBackgroundScroll, scrollOpts);
|
|
7610
9005
|
};
|
|
7611
9006
|
}, [linkPopover, postToParent2]);
|
|
7612
|
-
|
|
9007
|
+
useEffect8(() => {
|
|
7613
9008
|
if (!isEditMode) return;
|
|
7614
9009
|
const useFixtures = shouldUseDevFixtures();
|
|
7615
9010
|
if (useFixtures) {
|
|
@@ -7633,14 +9028,14 @@ function OhhwellsBridge() {
|
|
|
7633
9028
|
if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
|
|
7634
9029
|
return () => window.removeEventListener("message", onSitePages);
|
|
7635
9030
|
}, [isEditMode, postToParent2]);
|
|
7636
|
-
|
|
9031
|
+
useEffect8(() => {
|
|
7637
9032
|
if (!isEditMode || shouldUseDevFixtures()) return;
|
|
7638
9033
|
void loadAllSectionsManifest().then((manifest) => {
|
|
7639
9034
|
if (Object.keys(manifest).length === 0) return;
|
|
7640
9035
|
setSectionsByPath((prev) => ({ ...manifest, ...prev }));
|
|
7641
9036
|
});
|
|
7642
9037
|
}, [isEditMode]);
|
|
7643
|
-
|
|
9038
|
+
useEffect8(() => {
|
|
7644
9039
|
const update = () => {
|
|
7645
9040
|
const el = activeElRef.current ?? selectedElRef.current;
|
|
7646
9041
|
if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
@@ -7664,10 +9059,10 @@ function OhhwellsBridge() {
|
|
|
7664
9059
|
vvp.removeEventListener("resize", update);
|
|
7665
9060
|
};
|
|
7666
9061
|
}, []);
|
|
7667
|
-
const refreshStateRules =
|
|
9062
|
+
const refreshStateRules = useCallback4(() => {
|
|
7668
9063
|
editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
|
|
7669
9064
|
}, []);
|
|
7670
|
-
const processConfigRequest =
|
|
9065
|
+
const processConfigRequest = useCallback4((insertAfterVal) => {
|
|
7671
9066
|
const tracker = getSectionsTracker();
|
|
7672
9067
|
let entries = [];
|
|
7673
9068
|
try {
|
|
@@ -7690,7 +9085,7 @@ function OhhwellsBridge() {
|
|
|
7690
9085
|
}
|
|
7691
9086
|
window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
|
|
7692
9087
|
}, [isEditMode]);
|
|
7693
|
-
const deactivate =
|
|
9088
|
+
const deactivate = useCallback4(() => {
|
|
7694
9089
|
const el = activeElRef.current;
|
|
7695
9090
|
if (!el) return;
|
|
7696
9091
|
const key = el.dataset.ohwKey;
|
|
@@ -7709,6 +9104,7 @@ function OhhwellsBridge() {
|
|
|
7709
9104
|
}
|
|
7710
9105
|
}
|
|
7711
9106
|
el.removeAttribute("contenteditable");
|
|
9107
|
+
el.removeAttribute("data-ohw-editing");
|
|
7712
9108
|
activeElRef.current = null;
|
|
7713
9109
|
setReorderHrefKey(null);
|
|
7714
9110
|
setReorderDragDisabled(false);
|
|
@@ -7721,12 +9117,23 @@ function OhhwellsBridge() {
|
|
|
7721
9117
|
setToolbarShowEditLink(false);
|
|
7722
9118
|
postToParent2({ type: "ow:exit-edit" });
|
|
7723
9119
|
}, [postToParent2]);
|
|
7724
|
-
const
|
|
9120
|
+
const clearSelectedAttr = useCallback4(() => {
|
|
9121
|
+
document.querySelectorAll("[data-ohw-selected]").forEach((el) => {
|
|
9122
|
+
el.removeAttribute("data-ohw-selected");
|
|
9123
|
+
});
|
|
9124
|
+
}, []);
|
|
9125
|
+
const deselect = useCallback4(() => {
|
|
9126
|
+
clearSelectedAttr();
|
|
7725
9127
|
selectedElRef.current = null;
|
|
9128
|
+
selectedHrefKeyRef.current = null;
|
|
9129
|
+
selectedFooterColAttrRef.current = null;
|
|
9130
|
+
setSelectedIsCta(false);
|
|
7726
9131
|
setReorderHrefKey(null);
|
|
7727
9132
|
setReorderDragDisabled(false);
|
|
9133
|
+
setIsFooterFrameSelection(false);
|
|
7728
9134
|
siblingHintElRef.current = null;
|
|
7729
9135
|
setSiblingHintRect(null);
|
|
9136
|
+
setSiblingHintRects([]);
|
|
7730
9137
|
setIsItemDragging(false);
|
|
7731
9138
|
hoveredNavContainerRef.current = null;
|
|
7732
9139
|
setHoveredNavContainerRect(null);
|
|
@@ -7734,18 +9141,70 @@ function OhhwellsBridge() {
|
|
|
7734
9141
|
setToolbarRect(null);
|
|
7735
9142
|
setToolbarVariant("none");
|
|
7736
9143
|
}
|
|
9144
|
+
}, [clearSelectedAttr]);
|
|
9145
|
+
const markSelected = useCallback4((el) => {
|
|
9146
|
+
clearSelectedAttr();
|
|
9147
|
+
el.setAttribute("data-ohw-selected", "");
|
|
9148
|
+
}, [clearSelectedAttr]);
|
|
9149
|
+
const resolveHrefKeyElement = useCallback4((hrefKey) => {
|
|
9150
|
+
if (isFooterHrefKey(hrefKey)) {
|
|
9151
|
+
return document.querySelector(
|
|
9152
|
+
`footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
9153
|
+
);
|
|
9154
|
+
}
|
|
9155
|
+
if (isNavbarHrefKey(hrefKey)) {
|
|
9156
|
+
const desktop = document.querySelector("[data-ohw-nav-container]");
|
|
9157
|
+
const drawer = document.querySelector("[data-ohw-nav-drawer]");
|
|
9158
|
+
return desktop?.querySelector(`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`) ?? drawer?.querySelector(`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`) ?? document.querySelector(`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`);
|
|
9159
|
+
}
|
|
9160
|
+
return document.querySelector(
|
|
9161
|
+
`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
9162
|
+
);
|
|
7737
9163
|
}, []);
|
|
7738
|
-
const
|
|
9164
|
+
const resyncSelectedNavigationItem = useCallback4(() => {
|
|
9165
|
+
const hrefKey = selectedHrefKeyRef.current;
|
|
9166
|
+
if (hrefKey) {
|
|
9167
|
+
const link = resolveHrefKeyElement(hrefKey);
|
|
9168
|
+
if (!link || !isNavigationItem(link)) return;
|
|
9169
|
+
selectedElRef.current = link;
|
|
9170
|
+
const { key, disabled } = getNavigationItemReorderState(link);
|
|
9171
|
+
setReorderHrefKey(key);
|
|
9172
|
+
setReorderDragDisabled(disabled);
|
|
9173
|
+
setIsFooterFrameSelection(false);
|
|
9174
|
+
setToolbarVariant("link-action");
|
|
9175
|
+
setToolbarRect(link.getBoundingClientRect());
|
|
9176
|
+
setSiblingHintRects(collectNavigationItemSiblingHintRects(link));
|
|
9177
|
+
return;
|
|
9178
|
+
}
|
|
9179
|
+
const colAttr = selectedFooterColAttrRef.current;
|
|
9180
|
+
if (colAttr != null) {
|
|
9181
|
+
const column = document.querySelector(`[data-ohw-footer-col="${CSS.escape(colAttr)}"]`) ?? listFooterColumns()[Number(colAttr)] ?? null;
|
|
9182
|
+
if (!column || !isNavigationContainer(column)) return;
|
|
9183
|
+
selectedElRef.current = column;
|
|
9184
|
+
setIsFooterFrameSelection(true);
|
|
9185
|
+
setToolbarVariant("select-frame");
|
|
9186
|
+
setToolbarRect(column.getBoundingClientRect());
|
|
9187
|
+
setSiblingHintRects(
|
|
9188
|
+
listFooterColumns().filter((c) => c !== column).map((c) => c.getBoundingClientRect())
|
|
9189
|
+
);
|
|
9190
|
+
}
|
|
9191
|
+
}, [resolveHrefKeyElement]);
|
|
9192
|
+
const reselectNavigationItem = useCallback4((navAnchor) => {
|
|
7739
9193
|
selectedElRef.current = navAnchor;
|
|
9194
|
+
selectedHrefKeyRef.current = navAnchor.getAttribute("data-ohw-href-key");
|
|
9195
|
+
selectedFooterColAttrRef.current = null;
|
|
9196
|
+
markSelected(navAnchor);
|
|
9197
|
+
setSelectedIsCta(isNavbarButton2(navAnchor));
|
|
7740
9198
|
const { key, disabled } = getNavigationItemReorderState(navAnchor);
|
|
7741
9199
|
setReorderHrefKey(key);
|
|
7742
9200
|
setReorderDragDisabled(disabled);
|
|
7743
9201
|
setToolbarVariant("link-action");
|
|
7744
9202
|
setToolbarRect(navAnchor.getBoundingClientRect());
|
|
9203
|
+
setSiblingHintRects(collectNavigationItemSiblingHintRects(navAnchor));
|
|
7745
9204
|
setToolbarShowEditLink(false);
|
|
7746
9205
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
7747
|
-
}, []);
|
|
7748
|
-
const commitNavigationTextEdit =
|
|
9206
|
+
}, [markSelected]);
|
|
9207
|
+
const commitNavigationTextEdit = useCallback4((navAnchor) => {
|
|
7749
9208
|
const el = activeElRef.current;
|
|
7750
9209
|
if (!el) return;
|
|
7751
9210
|
const key = el.dataset.ohwKey;
|
|
@@ -7764,6 +9223,7 @@ function OhhwellsBridge() {
|
|
|
7764
9223
|
}
|
|
7765
9224
|
}
|
|
7766
9225
|
el.removeAttribute("contenteditable");
|
|
9226
|
+
el.removeAttribute("data-ohw-editing");
|
|
7767
9227
|
activeElRef.current = null;
|
|
7768
9228
|
setMaxBadge(null);
|
|
7769
9229
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
@@ -7771,7 +9231,7 @@ function OhhwellsBridge() {
|
|
|
7771
9231
|
postToParent2({ type: "ow:exit-edit" });
|
|
7772
9232
|
reselectNavigationItem(navAnchor);
|
|
7773
9233
|
}, [postToParent2, reselectNavigationItem]);
|
|
7774
|
-
const handleAddTopLevelNavItem =
|
|
9234
|
+
const handleAddTopLevelNavItem = useCallback4(() => {
|
|
7775
9235
|
const items = listNavbarItems();
|
|
7776
9236
|
addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
|
|
7777
9237
|
deselectRef.current();
|
|
@@ -7783,20 +9243,310 @@ function OhhwellsBridge() {
|
|
|
7783
9243
|
intent: "add-nav"
|
|
7784
9244
|
});
|
|
7785
9245
|
}, []);
|
|
7786
|
-
const
|
|
7787
|
-
|
|
7788
|
-
|
|
7789
|
-
|
|
7790
|
-
|
|
7791
|
-
|
|
9246
|
+
const clearFooterDragVisuals = useCallback4(() => {
|
|
9247
|
+
footerDragRef.current = null;
|
|
9248
|
+
setSiblingHintRects([]);
|
|
9249
|
+
setFooterDropSlots([]);
|
|
9250
|
+
setActiveFooterDropIndex(null);
|
|
9251
|
+
setDraggedItemRect(null);
|
|
7792
9252
|
setIsItemDragging(false);
|
|
9253
|
+
unlockFooterDragInteraction();
|
|
9254
|
+
}, []);
|
|
9255
|
+
const refreshFooterDragVisuals = useCallback4((session, activeSlot, clientX, clientY) => {
|
|
9256
|
+
const dragged = session.draggedEl;
|
|
9257
|
+
setDraggedItemRect(dragged.getBoundingClientRect());
|
|
9258
|
+
if (typeof clientX === "number" && typeof clientY === "number") {
|
|
9259
|
+
session.lastClientX = clientX;
|
|
9260
|
+
session.lastClientY = clientY;
|
|
9261
|
+
}
|
|
9262
|
+
session.activeSlot = activeSlot;
|
|
9263
|
+
setSiblingHintRects([]);
|
|
9264
|
+
if (session.kind === "link") {
|
|
9265
|
+
const columns = listFooterColumns();
|
|
9266
|
+
const slots2 = [];
|
|
9267
|
+
columns.forEach((col, i) => {
|
|
9268
|
+
slots2.push(...buildLinkDropSlots(col, i));
|
|
9269
|
+
});
|
|
9270
|
+
setFooterDropSlots(slots2);
|
|
9271
|
+
const activeIdx2 = activeSlot ? slots2.findIndex((s) => s.columnIndex === activeSlot.columnIndex && s.insertIndex === activeSlot.insertIndex) : -1;
|
|
9272
|
+
setActiveFooterDropIndex(activeIdx2 >= 0 ? activeIdx2 : null);
|
|
9273
|
+
return;
|
|
9274
|
+
}
|
|
9275
|
+
const slots = buildColumnDropSlots();
|
|
9276
|
+
setFooterDropSlots(slots);
|
|
9277
|
+
const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
|
|
9278
|
+
setActiveFooterDropIndex(activeIdx >= 0 ? activeIdx : null);
|
|
9279
|
+
}, []);
|
|
9280
|
+
const refreshFooterDragVisualsRef = useRef7(refreshFooterDragVisuals);
|
|
9281
|
+
refreshFooterDragVisualsRef.current = refreshFooterDragVisuals;
|
|
9282
|
+
const commitFooterDragRef = useRef7(() => {
|
|
9283
|
+
});
|
|
9284
|
+
const beginFooterDragRef = useRef7(() => {
|
|
9285
|
+
});
|
|
9286
|
+
const beginFooterDrag = useCallback4(
|
|
9287
|
+
(session) => {
|
|
9288
|
+
const rect = session.draggedEl.getBoundingClientRect();
|
|
9289
|
+
session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
|
|
9290
|
+
session.lastClientY = session.lastClientY || rect.top + rect.height / 2;
|
|
9291
|
+
session.activeSlot = session.activeSlot ?? null;
|
|
9292
|
+
footerDragRef.current = session;
|
|
9293
|
+
setIsItemDragging(true);
|
|
9294
|
+
lockFooterDuringDrag();
|
|
9295
|
+
siblingHintElRef.current = null;
|
|
9296
|
+
setSiblingHintRect(null);
|
|
9297
|
+
if (session.wasSelected && selectedElRef.current === session.draggedEl) {
|
|
9298
|
+
setToolbarRect(rect);
|
|
9299
|
+
}
|
|
9300
|
+
const initialSlot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
|
|
9301
|
+
refreshFooterDragVisuals(session, initialSlot, session.lastClientX, session.lastClientY);
|
|
9302
|
+
},
|
|
9303
|
+
[refreshFooterDragVisuals]
|
|
9304
|
+
);
|
|
9305
|
+
beginFooterDragRef.current = beginFooterDrag;
|
|
9306
|
+
const commitFooterDrag = useCallback4(
|
|
9307
|
+
(clientX, clientY) => {
|
|
9308
|
+
const session = footerDragRef.current;
|
|
9309
|
+
if (!session) {
|
|
9310
|
+
clearFooterDragVisuals();
|
|
9311
|
+
return;
|
|
9312
|
+
}
|
|
9313
|
+
const x = typeof clientX === "number" && (clientX !== 0 || clientY !== 0) ? clientX : session.lastClientX;
|
|
9314
|
+
const y = typeof clientY === "number" && (clientX !== 0 || clientY !== 0) ? clientY : session.lastClientY;
|
|
9315
|
+
let nextOrder = null;
|
|
9316
|
+
const slot = session.activeSlot ?? (session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(x, y, session.hrefKey) : session.kind === "column" ? hitTestColumnDropSlot(x, y) : null);
|
|
9317
|
+
if (session.kind === "link" && session.hrefKey && slot) {
|
|
9318
|
+
nextOrder = planFooterLinkMove(session.hrefKey, slot.columnIndex, slot.insertIndex);
|
|
9319
|
+
} else if (session.kind === "column" && slot) {
|
|
9320
|
+
nextOrder = planFooterColumnMove(session.sourceColumnIndex, slot.insertIndex);
|
|
9321
|
+
}
|
|
9322
|
+
const wasSelected = session.wasSelected;
|
|
9323
|
+
const draggedEl = session.draggedEl;
|
|
9324
|
+
const hrefKey = session.hrefKey;
|
|
9325
|
+
let movedColumnIndex = null;
|
|
9326
|
+
if (session.kind === "column" && slot && nextOrder) {
|
|
9327
|
+
let adjusted = slot.insertIndex;
|
|
9328
|
+
if (session.sourceColumnIndex < slot.insertIndex) adjusted -= 1;
|
|
9329
|
+
movedColumnIndex = Math.max(0, Math.min(adjusted, nextOrder.length - 1));
|
|
9330
|
+
}
|
|
9331
|
+
const applySelectionAfterDrop = () => {
|
|
9332
|
+
if (!wasSelected) {
|
|
9333
|
+
deselectRef.current();
|
|
9334
|
+
return;
|
|
9335
|
+
}
|
|
9336
|
+
if (hrefKey) {
|
|
9337
|
+
selectedHrefKeyRef.current = hrefKey;
|
|
9338
|
+
selectedFooterColAttrRef.current = null;
|
|
9339
|
+
const link = resolveHrefKeyElement(hrefKey);
|
|
9340
|
+
if (link && isNavigationItem(link)) {
|
|
9341
|
+
selectRef.current(link);
|
|
9342
|
+
return;
|
|
9343
|
+
}
|
|
9344
|
+
}
|
|
9345
|
+
if (movedColumnIndex !== null && nextOrder) {
|
|
9346
|
+
const colKeys = nextOrder[movedColumnIndex] ?? [];
|
|
9347
|
+
let column = null;
|
|
9348
|
+
for (const key of colKeys) {
|
|
9349
|
+
const link = document.querySelector(
|
|
9350
|
+
`footer [data-ohw-href-key="${CSS.escape(key)}"]`
|
|
9351
|
+
);
|
|
9352
|
+
if (link) {
|
|
9353
|
+
column = findFooterColumnForLink(link);
|
|
9354
|
+
if (column) break;
|
|
9355
|
+
}
|
|
9356
|
+
}
|
|
9357
|
+
if (!column) column = listFooterColumns()[movedColumnIndex] ?? null;
|
|
9358
|
+
if (column && isNavigationContainer(column)) {
|
|
9359
|
+
selectFrameRef.current(column);
|
|
9360
|
+
return;
|
|
9361
|
+
}
|
|
9362
|
+
}
|
|
9363
|
+
if (document.body.contains(draggedEl)) {
|
|
9364
|
+
if (isNavigationItem(draggedEl)) {
|
|
9365
|
+
selectRef.current(draggedEl);
|
|
9366
|
+
return;
|
|
9367
|
+
}
|
|
9368
|
+
if (isNavigationContainer(draggedEl)) {
|
|
9369
|
+
selectFrameRef.current(draggedEl);
|
|
9370
|
+
return;
|
|
9371
|
+
}
|
|
9372
|
+
}
|
|
9373
|
+
deselectRef.current();
|
|
9374
|
+
};
|
|
9375
|
+
if (nextOrder) {
|
|
9376
|
+
const orderJson = JSON.stringify(nextOrder);
|
|
9377
|
+
editContentRef.current = {
|
|
9378
|
+
...editContentRef.current,
|
|
9379
|
+
[FOOTER_ORDER_KEY]: orderJson
|
|
9380
|
+
};
|
|
9381
|
+
applyFooterOrder(nextOrder);
|
|
9382
|
+
document.querySelectorAll("footer [data-ohw-href-key]").forEach(disableNativeHrefDrag);
|
|
9383
|
+
postToParentRef.current({
|
|
9384
|
+
type: "ow:change",
|
|
9385
|
+
nodes: [{ key: FOOTER_ORDER_KEY, text: orderJson }]
|
|
9386
|
+
});
|
|
9387
|
+
applySelectionAfterDrop();
|
|
9388
|
+
clearFooterDragVisuals();
|
|
9389
|
+
requestAnimationFrame(() => {
|
|
9390
|
+
if (editContentRef.current[FOOTER_ORDER_KEY] === orderJson) {
|
|
9391
|
+
applyFooterOrder(nextOrder);
|
|
9392
|
+
document.querySelectorAll("footer [data-ohw-href-key]").forEach(disableNativeHrefDrag);
|
|
9393
|
+
}
|
|
9394
|
+
applySelectionAfterDrop();
|
|
9395
|
+
requestAnimationFrame(() => {
|
|
9396
|
+
if (editContentRef.current[FOOTER_ORDER_KEY] === orderJson) {
|
|
9397
|
+
applyFooterOrder(nextOrder);
|
|
9398
|
+
}
|
|
9399
|
+
resyncSelectedNavigationItem();
|
|
9400
|
+
});
|
|
9401
|
+
});
|
|
9402
|
+
return;
|
|
9403
|
+
}
|
|
9404
|
+
applySelectionAfterDrop();
|
|
9405
|
+
clearFooterDragVisuals();
|
|
9406
|
+
},
|
|
9407
|
+
[clearFooterDragVisuals, resolveHrefKeyElement, resyncSelectedNavigationItem]
|
|
9408
|
+
);
|
|
9409
|
+
commitFooterDragRef.current = commitFooterDrag;
|
|
9410
|
+
const startFooterLinkDrag = useCallback4(
|
|
9411
|
+
(anchor, clientX, clientY, wasSelected) => {
|
|
9412
|
+
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
9413
|
+
if (!hrefKey || !isFooterHrefKey(hrefKey)) return false;
|
|
9414
|
+
const column = findFooterColumnForLink(anchor);
|
|
9415
|
+
const columns = listFooterColumns();
|
|
9416
|
+
beginFooterDrag({
|
|
9417
|
+
kind: "link",
|
|
9418
|
+
hrefKey,
|
|
9419
|
+
columnEl: column,
|
|
9420
|
+
sourceColumnIndex: column ? columns.indexOf(column) : 0,
|
|
9421
|
+
wasSelected,
|
|
9422
|
+
draggedEl: anchor,
|
|
9423
|
+
lastClientX: clientX,
|
|
9424
|
+
lastClientY: clientY,
|
|
9425
|
+
activeSlot: null
|
|
9426
|
+
});
|
|
9427
|
+
return true;
|
|
9428
|
+
},
|
|
9429
|
+
[beginFooterDrag]
|
|
9430
|
+
);
|
|
9431
|
+
const startFooterColumnDrag = useCallback4(
|
|
9432
|
+
(columnEl, clientX, clientY, wasSelected) => {
|
|
9433
|
+
const columns = listFooterColumns();
|
|
9434
|
+
const idx = columns.indexOf(columnEl);
|
|
9435
|
+
if (idx < 0) return false;
|
|
9436
|
+
beginFooterDrag({
|
|
9437
|
+
kind: "column",
|
|
9438
|
+
hrefKey: null,
|
|
9439
|
+
columnEl,
|
|
9440
|
+
sourceColumnIndex: idx,
|
|
9441
|
+
wasSelected,
|
|
9442
|
+
draggedEl: columnEl,
|
|
9443
|
+
lastClientX: clientX,
|
|
9444
|
+
lastClientY: clientY,
|
|
9445
|
+
activeSlot: null
|
|
9446
|
+
});
|
|
9447
|
+
return true;
|
|
9448
|
+
},
|
|
9449
|
+
[beginFooterDrag]
|
|
9450
|
+
);
|
|
9451
|
+
const handleItemDragStart = useCallback4(
|
|
9452
|
+
(e) => {
|
|
9453
|
+
const selected = selectedElRef.current;
|
|
9454
|
+
if (!selected) {
|
|
9455
|
+
setIsItemDragging(true);
|
|
9456
|
+
return;
|
|
9457
|
+
}
|
|
9458
|
+
const clientX = e?.clientX ?? selected.getBoundingClientRect().left + 8;
|
|
9459
|
+
const clientY = e?.clientY ?? selected.getBoundingClientRect().top + 8;
|
|
9460
|
+
if (startFooterLinkDrag(selected, clientX, clientY, true)) return;
|
|
9461
|
+
if (selected.hasAttribute("data-ohw-footer-col") || isInferredFooterGroup(selected) && selected.closest("footer")) {
|
|
9462
|
+
if (startFooterColumnDrag(selected, clientX, clientY, true)) return;
|
|
9463
|
+
}
|
|
9464
|
+
if (startNavLinkDrag(selected, clientX, clientY, true)) return;
|
|
9465
|
+
siblingHintElRef.current = null;
|
|
9466
|
+
setSiblingHintRect(null);
|
|
9467
|
+
setIsItemDragging(true);
|
|
9468
|
+
},
|
|
9469
|
+
[startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag]
|
|
9470
|
+
);
|
|
9471
|
+
const handleItemDragEnd = useCallback4(
|
|
9472
|
+
(e) => {
|
|
9473
|
+
if (footerDragRef.current) {
|
|
9474
|
+
const x = e?.clientX;
|
|
9475
|
+
const y = e?.clientY;
|
|
9476
|
+
if (typeof x === "number" && typeof y === "number" && (x !== 0 || y !== 0)) {
|
|
9477
|
+
commitFooterDrag(x, y);
|
|
9478
|
+
} else {
|
|
9479
|
+
commitFooterDrag();
|
|
9480
|
+
}
|
|
9481
|
+
return;
|
|
9482
|
+
}
|
|
9483
|
+
if (navDragRef.current) {
|
|
9484
|
+
const x = e?.clientX;
|
|
9485
|
+
const y = e?.clientY;
|
|
9486
|
+
if (typeof x === "number" && typeof y === "number" && (x !== 0 || y !== 0)) {
|
|
9487
|
+
commitNavDrag(x, y);
|
|
9488
|
+
} else {
|
|
9489
|
+
commitNavDrag();
|
|
9490
|
+
}
|
|
9491
|
+
return;
|
|
9492
|
+
}
|
|
9493
|
+
setIsItemDragging(false);
|
|
9494
|
+
},
|
|
9495
|
+
[commitFooterDrag, commitNavDrag, navDragRef]
|
|
9496
|
+
);
|
|
9497
|
+
const handleItemChromePointerDown = useCallback4((e) => {
|
|
9498
|
+
if (e.button !== 0) return;
|
|
9499
|
+
const selected = selectedElRef.current;
|
|
9500
|
+
if (!selected) return;
|
|
9501
|
+
armFooterPressDrag();
|
|
9502
|
+
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
9503
|
+
if (hrefKey && isFooterHrefKey(hrefKey)) {
|
|
9504
|
+
footerPointerDragRef.current = {
|
|
9505
|
+
el: selected,
|
|
9506
|
+
kind: "link",
|
|
9507
|
+
startX: e.clientX,
|
|
9508
|
+
startY: e.clientY,
|
|
9509
|
+
pointerId: e.pointerId,
|
|
9510
|
+
wasSelected: true,
|
|
9511
|
+
started: false
|
|
9512
|
+
};
|
|
9513
|
+
return;
|
|
9514
|
+
}
|
|
9515
|
+
if (selected.hasAttribute("data-ohw-footer-col") || isInferredFooterGroup(selected) && selected.closest("footer")) {
|
|
9516
|
+
footerPointerDragRef.current = {
|
|
9517
|
+
el: selected,
|
|
9518
|
+
kind: "column",
|
|
9519
|
+
startX: e.clientX,
|
|
9520
|
+
startY: e.clientY,
|
|
9521
|
+
pointerId: e.pointerId,
|
|
9522
|
+
wasSelected: true,
|
|
9523
|
+
started: false
|
|
9524
|
+
};
|
|
9525
|
+
return;
|
|
9526
|
+
}
|
|
9527
|
+
if (armNavPressFromChrome(selected, e.clientX, e.clientY, e.pointerId)) return;
|
|
9528
|
+
}, [armNavPressFromChrome]);
|
|
9529
|
+
const handleItemChromeClick = useCallback4((clientX, clientY) => {
|
|
9530
|
+
if (suppressNextClickRef.current || Date.now() < suppressClickUntilRef.current) {
|
|
9531
|
+
suppressNextClickRef.current = false;
|
|
9532
|
+
return;
|
|
9533
|
+
}
|
|
9534
|
+
const selected = selectedElRef.current;
|
|
9535
|
+
if (!selected || !isNavigationItem(selected)) return;
|
|
9536
|
+
const editable = selected.querySelector('[data-ohw-editable="text"]') ?? selected.querySelector("[data-ohw-editable]");
|
|
9537
|
+
if (!editable) return;
|
|
9538
|
+
activateRef.current(editable, { caretX: clientX, caretY: clientY });
|
|
7793
9539
|
}, []);
|
|
7794
9540
|
reselectNavigationItemRef.current = reselectNavigationItem;
|
|
7795
9541
|
commitNavigationTextEditRef.current = commitNavigationTextEdit;
|
|
7796
|
-
const select =
|
|
9542
|
+
const select = useCallback4((anchor) => {
|
|
7797
9543
|
if (!isNavigationItem(anchor)) return;
|
|
7798
9544
|
if (activeElRef.current) deactivate();
|
|
7799
9545
|
selectedElRef.current = anchor;
|
|
9546
|
+
selectedHrefKeyRef.current = anchor.getAttribute("data-ohw-href-key");
|
|
9547
|
+
selectedFooterColAttrRef.current = null;
|
|
9548
|
+
markSelected(anchor);
|
|
9549
|
+
setSelectedIsCta(isNavbarButton2(anchor));
|
|
7800
9550
|
clearHrefKeyHover(anchor);
|
|
7801
9551
|
hoveredNavContainerRef.current = null;
|
|
7802
9552
|
setHoveredNavContainerRect(null);
|
|
@@ -7804,19 +9554,26 @@ function OhhwellsBridge() {
|
|
|
7804
9554
|
hoveredItemElRef.current = null;
|
|
7805
9555
|
siblingHintElRef.current = null;
|
|
7806
9556
|
setSiblingHintRect(null);
|
|
9557
|
+
setSiblingHintRects(collectNavigationItemSiblingHintRects(anchor));
|
|
7807
9558
|
setIsItemDragging(false);
|
|
7808
9559
|
const { key, disabled } = getNavigationItemReorderState(anchor);
|
|
7809
9560
|
setReorderHrefKey(key);
|
|
7810
9561
|
setReorderDragDisabled(disabled);
|
|
9562
|
+
setIsFooterFrameSelection(false);
|
|
7811
9563
|
setToolbarVariant("link-action");
|
|
7812
9564
|
setToolbarRect(anchor.getBoundingClientRect());
|
|
7813
9565
|
setToolbarShowEditLink(false);
|
|
7814
9566
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
7815
|
-
}, [deactivate]);
|
|
7816
|
-
const selectFrame =
|
|
9567
|
+
}, [deactivate, markSelected]);
|
|
9568
|
+
const selectFrame = useCallback4((el) => {
|
|
7817
9569
|
if (!isNavigationContainer(el)) return;
|
|
7818
9570
|
if (activeElRef.current) deactivate();
|
|
9571
|
+
const isFooterColumn = el.hasAttribute("data-ohw-footer-col") || Boolean(el.closest("footer") && isInferredFooterGroup(el));
|
|
7819
9572
|
selectedElRef.current = el;
|
|
9573
|
+
selectedHrefKeyRef.current = null;
|
|
9574
|
+
selectedFooterColAttrRef.current = isFooterColumn ? el.getAttribute("data-ohw-footer-col") ?? String(listFooterColumns().indexOf(el)) : null;
|
|
9575
|
+
markSelected(el);
|
|
9576
|
+
setSelectedIsCta(false);
|
|
7820
9577
|
clearHrefKeyHover(el);
|
|
7821
9578
|
hoveredNavContainerRef.current = null;
|
|
7822
9579
|
setHoveredNavContainerRect(null);
|
|
@@ -7824,17 +9581,25 @@ function OhhwellsBridge() {
|
|
|
7824
9581
|
hoveredItemElRef.current = null;
|
|
7825
9582
|
siblingHintElRef.current = null;
|
|
7826
9583
|
setSiblingHintRect(null);
|
|
9584
|
+
setSiblingHintRects(
|
|
9585
|
+
isFooterColumn ? listFooterColumns().filter((column) => column !== el).map((column) => column.getBoundingClientRect()) : []
|
|
9586
|
+
);
|
|
7827
9587
|
setIsItemDragging(false);
|
|
7828
9588
|
setReorderHrefKey(null);
|
|
7829
9589
|
setReorderDragDisabled(false);
|
|
9590
|
+
setIsFooterFrameSelection(isFooterColumn);
|
|
7830
9591
|
setToolbarVariant("select-frame");
|
|
7831
9592
|
setToolbarRect(el.getBoundingClientRect());
|
|
7832
9593
|
setToolbarShowEditLink(false);
|
|
7833
9594
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
7834
|
-
}, [deactivate]);
|
|
7835
|
-
const activate =
|
|
9595
|
+
}, [deactivate, markSelected]);
|
|
9596
|
+
const activate = useCallback4((el, options) => {
|
|
7836
9597
|
if (activeElRef.current === el) return;
|
|
9598
|
+
clearSelectedAttr();
|
|
7837
9599
|
selectedElRef.current = null;
|
|
9600
|
+
selectedHrefKeyRef.current = null;
|
|
9601
|
+
selectedFooterColAttrRef.current = null;
|
|
9602
|
+
setSelectedIsCta(false);
|
|
7838
9603
|
deactivate();
|
|
7839
9604
|
if (hoveredImageRef.current) {
|
|
7840
9605
|
hoveredImageRef.current = null;
|
|
@@ -7845,13 +9610,27 @@ function OhhwellsBridge() {
|
|
|
7845
9610
|
setSiblingHintRect(null);
|
|
7846
9611
|
setIsItemDragging(false);
|
|
7847
9612
|
el.setAttribute("contenteditable", "true");
|
|
9613
|
+
el.setAttribute("data-ohw-editing", "");
|
|
7848
9614
|
el.removeAttribute("data-ohw-hovered");
|
|
7849
9615
|
el.closest("[data-ohw-href-key]")?.removeAttribute("data-ohw-hovered");
|
|
7850
9616
|
activeElRef.current = el;
|
|
7851
9617
|
originalContentRef.current = el.innerHTML;
|
|
7852
|
-
el.focus();
|
|
9618
|
+
el.focus({ preventScroll: true });
|
|
7853
9619
|
if (options?.caretX !== void 0 && options?.caretY !== void 0) {
|
|
7854
|
-
|
|
9620
|
+
const { caretX, caretY } = options;
|
|
9621
|
+
placeCaretAtPoint(el, caretX, caretY);
|
|
9622
|
+
requestAnimationFrame(() => {
|
|
9623
|
+
if (activeElRef.current === el) placeCaretAtPoint(el, caretX, caretY);
|
|
9624
|
+
});
|
|
9625
|
+
} else {
|
|
9626
|
+
const selection = window.getSelection();
|
|
9627
|
+
if (selection && selection.rangeCount === 0) {
|
|
9628
|
+
const range = document.createRange();
|
|
9629
|
+
range.selectNodeContents(el);
|
|
9630
|
+
range.collapse(false);
|
|
9631
|
+
selection.removeAllRanges();
|
|
9632
|
+
selection.addRange(range);
|
|
9633
|
+
}
|
|
7855
9634
|
}
|
|
7856
9635
|
setToolbarShowEditLink(Boolean(getHrefKeyFromElement(el)));
|
|
7857
9636
|
const navAnchor = getNavigationItemAnchor(el);
|
|
@@ -7866,13 +9645,13 @@ function OhhwellsBridge() {
|
|
|
7866
9645
|
setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
7867
9646
|
postToParent2({ type: "ow:enter-edit", key: el.dataset.ohwKey });
|
|
7868
9647
|
requestAnimationFrame(() => refreshActiveCommandsRef.current());
|
|
7869
|
-
}, [deactivate, postToParent2]);
|
|
9648
|
+
}, [clearSelectedAttr, deactivate, postToParent2]);
|
|
7870
9649
|
activateRef.current = activate;
|
|
7871
9650
|
deactivateRef.current = deactivate;
|
|
7872
9651
|
selectRef.current = select;
|
|
7873
9652
|
selectFrameRef.current = selectFrame;
|
|
7874
9653
|
deselectRef.current = deselect;
|
|
7875
|
-
|
|
9654
|
+
useLayoutEffect3(() => {
|
|
7876
9655
|
if (!subdomain || isEditMode) {
|
|
7877
9656
|
setFetchState("done");
|
|
7878
9657
|
return;
|
|
@@ -7913,6 +9692,7 @@ function OhhwellsBridge() {
|
|
|
7913
9692
|
applyLinkByKey(key, val);
|
|
7914
9693
|
}
|
|
7915
9694
|
reconcileNavbarItemsFromContent(content);
|
|
9695
|
+
reconcileFooterOrderFromContent(content);
|
|
7916
9696
|
enforceLinkHrefs();
|
|
7917
9697
|
initSectionsFromContent(content, true);
|
|
7918
9698
|
sectionsLoadedRef.current = true;
|
|
@@ -7941,7 +9721,7 @@ function OhhwellsBridge() {
|
|
|
7941
9721
|
cancelled = true;
|
|
7942
9722
|
};
|
|
7943
9723
|
}, [subdomain, isEditMode]);
|
|
7944
|
-
|
|
9724
|
+
useEffect8(() => {
|
|
7945
9725
|
if (!subdomain || isEditMode) return;
|
|
7946
9726
|
let debounceTimer = null;
|
|
7947
9727
|
let observer = null;
|
|
@@ -7973,6 +9753,7 @@ function OhhwellsBridge() {
|
|
|
7973
9753
|
applyLinkByKey(key, val);
|
|
7974
9754
|
}
|
|
7975
9755
|
reconcileNavbarItemsFromContent(content);
|
|
9756
|
+
reconcileFooterOrderFromContent(content);
|
|
7976
9757
|
} finally {
|
|
7977
9758
|
observer?.observe(document.body, { childList: true, subtree: true });
|
|
7978
9759
|
}
|
|
@@ -7990,16 +9771,16 @@ function OhhwellsBridge() {
|
|
|
7990
9771
|
if (debounceTimer) clearTimeout(debounceTimer);
|
|
7991
9772
|
};
|
|
7992
9773
|
}, [subdomain, isEditMode, pathname]);
|
|
7993
|
-
|
|
9774
|
+
useLayoutEffect3(() => {
|
|
7994
9775
|
const el = document.getElementById("ohw-loader");
|
|
7995
9776
|
if (!el) return;
|
|
7996
9777
|
const visible = Boolean(subdomain) && fetchState !== "done";
|
|
7997
9778
|
el.style.display = visible ? "flex" : "none";
|
|
7998
9779
|
}, [subdomain, fetchState]);
|
|
7999
|
-
|
|
9780
|
+
useEffect8(() => {
|
|
8000
9781
|
postToParent2({ type: "ow:navigation", path: pathname });
|
|
8001
9782
|
}, [pathname, postToParent2]);
|
|
8002
|
-
|
|
9783
|
+
useEffect8(() => {
|
|
8003
9784
|
if (!isEditMode) return;
|
|
8004
9785
|
if (linkPopoverSessionRef.current?.intent === "add-nav") return;
|
|
8005
9786
|
if (document.querySelector("[data-ohw-section-picker]")) return;
|
|
@@ -8007,23 +9788,72 @@ function OhhwellsBridge() {
|
|
|
8007
9788
|
deselectRef.current();
|
|
8008
9789
|
deactivateRef.current();
|
|
8009
9790
|
}, [pathname, isEditMode]);
|
|
8010
|
-
|
|
9791
|
+
useEffect8(() => {
|
|
8011
9792
|
const contentForNav = () => {
|
|
8012
9793
|
if (isEditMode) return editContentRef.current;
|
|
8013
9794
|
if (!subdomain) return {};
|
|
8014
9795
|
return contentCache.get(subdomain) ?? {};
|
|
8015
9796
|
};
|
|
8016
|
-
const
|
|
9797
|
+
const observeRoots = () => [document.querySelector("nav"), document.querySelector("footer")].filter(
|
|
9798
|
+
(el) => Boolean(el)
|
|
9799
|
+
);
|
|
9800
|
+
const roots = observeRoots();
|
|
9801
|
+
if (roots.length === 0) {
|
|
9802
|
+
reconcileNavbarItemsFromContent(contentForNav());
|
|
9803
|
+
reconcileFooterOrderFromContent(contentForNav());
|
|
9804
|
+
if (isEditMode) syncNavigationDragCursorAttrs();
|
|
9805
|
+
return;
|
|
9806
|
+
}
|
|
9807
|
+
let rafId = null;
|
|
9808
|
+
let applying = false;
|
|
9809
|
+
let observer = null;
|
|
9810
|
+
const attach = () => {
|
|
9811
|
+
for (const root of observeRoots()) {
|
|
9812
|
+
observer?.observe(root, { childList: true, subtree: true });
|
|
9813
|
+
}
|
|
9814
|
+
};
|
|
9815
|
+
const run = () => {
|
|
9816
|
+
if (footerDragRef.current || navDragRef.current || applying) return;
|
|
9817
|
+
applying = true;
|
|
9818
|
+
observer?.disconnect();
|
|
9819
|
+
try {
|
|
9820
|
+
const content = contentForNav();
|
|
9821
|
+
reconcileNavbarItemsFromContent(content);
|
|
9822
|
+
reconcileFooterOrderFromContent(content);
|
|
9823
|
+
document.querySelectorAll("footer [data-ohw-href-key]").forEach((el) => {
|
|
9824
|
+
if (isFooterHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
9825
|
+
disableNativeHrefDrag(el);
|
|
9826
|
+
}
|
|
9827
|
+
});
|
|
9828
|
+
document.querySelectorAll(
|
|
9829
|
+
"nav [data-ohw-href-key], [data-ohw-nav-container] [data-ohw-href-key], [data-ohw-nav-drawer] [data-ohw-href-key]"
|
|
9830
|
+
).forEach((el) => {
|
|
9831
|
+
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
9832
|
+
disableNativeHrefDrag(el);
|
|
9833
|
+
}
|
|
9834
|
+
});
|
|
9835
|
+
resyncSelectedNavigationItem();
|
|
9836
|
+
if (isEditMode) syncNavigationDragCursorAttrs();
|
|
9837
|
+
} finally {
|
|
9838
|
+
applying = false;
|
|
9839
|
+
attach();
|
|
9840
|
+
}
|
|
9841
|
+
};
|
|
9842
|
+
const schedule = () => {
|
|
9843
|
+
if (applying || rafId != null) return;
|
|
9844
|
+
rafId = requestAnimationFrame(() => {
|
|
9845
|
+
rafId = null;
|
|
9846
|
+
run();
|
|
9847
|
+
});
|
|
9848
|
+
};
|
|
9849
|
+
observer = new MutationObserver(schedule);
|
|
8017
9850
|
run();
|
|
8018
|
-
|
|
8019
|
-
|
|
8020
|
-
|
|
8021
|
-
|
|
8022
|
-
|
|
8023
|
-
|
|
8024
|
-
return () => observer.disconnect();
|
|
8025
|
-
}, [isEditMode, pathname, subdomain, fetchState]);
|
|
8026
|
-
useEffect7(() => {
|
|
9851
|
+
return () => {
|
|
9852
|
+
if (rafId != null) cancelAnimationFrame(rafId);
|
|
9853
|
+
observer?.disconnect();
|
|
9854
|
+
};
|
|
9855
|
+
}, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
|
|
9856
|
+
useEffect8(() => {
|
|
8027
9857
|
if (!isEditMode) return;
|
|
8028
9858
|
const measure = () => {
|
|
8029
9859
|
const h = document.body.scrollHeight;
|
|
@@ -8047,7 +9877,7 @@ function OhhwellsBridge() {
|
|
|
8047
9877
|
window.removeEventListener("resize", handleResize);
|
|
8048
9878
|
};
|
|
8049
9879
|
}, [pathname, isEditMode, postToParent2]);
|
|
8050
|
-
|
|
9880
|
+
useEffect8(() => {
|
|
8051
9881
|
if (!subdomainFromQuery || isEditMode) return;
|
|
8052
9882
|
const handleClick = (e) => {
|
|
8053
9883
|
const anchor = e.target.closest("a");
|
|
@@ -8063,19 +9893,24 @@ function OhhwellsBridge() {
|
|
|
8063
9893
|
document.addEventListener("click", handleClick, true);
|
|
8064
9894
|
return () => document.removeEventListener("click", handleClick, true);
|
|
8065
9895
|
}, [subdomainFromQuery, isEditMode, router]);
|
|
8066
|
-
|
|
9896
|
+
useEffect8(() => {
|
|
8067
9897
|
if (!isEditMode) {
|
|
8068
9898
|
editStylesRef.current?.base.remove();
|
|
8069
9899
|
editStylesRef.current?.forceHover.remove();
|
|
8070
9900
|
editStylesRef.current?.stateViews.remove();
|
|
8071
9901
|
editStylesRef.current = null;
|
|
9902
|
+
document.querySelectorAll("[data-ohw-can-drag]").forEach((el) => {
|
|
9903
|
+
el.removeAttribute("data-ohw-can-drag");
|
|
9904
|
+
});
|
|
8072
9905
|
return;
|
|
8073
9906
|
}
|
|
8074
|
-
|
|
8075
|
-
|
|
8076
|
-
|
|
8077
|
-
base.
|
|
8078
|
-
|
|
9907
|
+
const existing = editStylesRef.current;
|
|
9908
|
+
let initialVh = window.innerHeight;
|
|
9909
|
+
if (existing?.base.textContent) {
|
|
9910
|
+
const match = existing.base.textContent.match(/\.min-h-screen[^{]*\{[^}]*min-height:\s*(\d+)px/);
|
|
9911
|
+
if (match) initialVh = parseInt(match[1], 10);
|
|
9912
|
+
}
|
|
9913
|
+
const baseCss = `
|
|
8079
9914
|
html { height: auto !important; }
|
|
8080
9915
|
body { height: auto !important; min-height: 0 !important; overflow: hidden !important; }
|
|
8081
9916
|
.min-h-screen, .min-h-svh, .min-h-dvh { min-height: ${initialVh}px !important; }
|
|
@@ -8086,7 +9921,25 @@ function OhhwellsBridge() {
|
|
|
8086
9921
|
[data-ohw-editable] {
|
|
8087
9922
|
display: block;
|
|
8088
9923
|
}
|
|
8089
|
-
|
|
9924
|
+
/* Body text (no item-action toolbar) \u2014 first click enters text edit \u2192 I-beam.
|
|
9925
|
+
Exclude select-first nav/footer labels so grab/default on [data-ohw-href-key] can win. */
|
|
9926
|
+
[data-ohw-editable]:not([contenteditable]):not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]):not([data-ohw-editable="video"]):not([data-ohw-editable="link"]):not(:is([data-ohw-href-key] *)) {
|
|
9927
|
+
cursor: text !important;
|
|
9928
|
+
}
|
|
9929
|
+
/* Select-first items: default arrow; grab only when drag-start is allowed (data-ohw-can-drag). */
|
|
9930
|
+
[data-ohw-href-key]:not([data-ohw-selected]),
|
|
9931
|
+
[data-ohw-href-key]:not([data-ohw-selected]) * {
|
|
9932
|
+
cursor: default !important;
|
|
9933
|
+
}
|
|
9934
|
+
[data-ohw-href-key][data-ohw-can-drag]:not([data-ohw-selected]),
|
|
9935
|
+
[data-ohw-href-key][data-ohw-can-drag]:not([data-ohw-selected]) * {
|
|
9936
|
+
cursor: grab !important;
|
|
9937
|
+
}
|
|
9938
|
+
/* Selected (action-toolbar) \u2014 next click enters text edit at caret. */
|
|
9939
|
+
[data-ohw-href-key][data-ohw-selected],
|
|
9940
|
+
[data-ohw-href-key][data-ohw-selected] * {
|
|
9941
|
+
cursor: text !important;
|
|
9942
|
+
}
|
|
8090
9943
|
[data-ohw-editable="image"], [data-ohw-editable="image"] *,
|
|
8091
9944
|
[data-ohw-editable="video"], [data-ohw-editable="video"] *,
|
|
8092
9945
|
[data-ohw-editable="bg-image"], [data-ohw-editable="bg-image"] * { cursor: pointer !important; }
|
|
@@ -8102,9 +9955,32 @@ function OhhwellsBridge() {
|
|
|
8102
9955
|
outline: none !important;
|
|
8103
9956
|
outline-offset: 0 !important;
|
|
8104
9957
|
}
|
|
8105
|
-
|
|
9958
|
+
/* Editor chrome owns selection \u2014 suppress native focus rings on nav/footer items. */
|
|
9959
|
+
nav [data-ohw-href-key]:focus,
|
|
9960
|
+
nav [data-ohw-href-key]:focus-visible,
|
|
9961
|
+
nav [data-ohw-href-key]:focus-within,
|
|
9962
|
+
footer [data-ohw-href-key]:focus,
|
|
9963
|
+
footer [data-ohw-href-key]:focus-visible,
|
|
9964
|
+
footer [data-ohw-href-key]:focus-within,
|
|
9965
|
+
nav [data-ohw-href-key] [data-ohw-editable]:focus,
|
|
9966
|
+
nav [data-ohw-href-key] [data-ohw-editable]:focus-visible,
|
|
9967
|
+
footer [data-ohw-href-key] [data-ohw-editable]:focus,
|
|
9968
|
+
footer [data-ohw-href-key] [data-ohw-editable]:focus-visible {
|
|
9969
|
+
outline: none !important;
|
|
9970
|
+
outline-offset: 0 !important;
|
|
9971
|
+
box-shadow: none !important;
|
|
9972
|
+
}
|
|
9973
|
+
/* Text edit wins over grab/default (must beat [data-ohw-can-drag] *). */
|
|
9974
|
+
[data-ohw-editing],
|
|
9975
|
+
[data-ohw-editing] *,
|
|
9976
|
+
[data-ohw-editable][contenteditable],
|
|
9977
|
+
[data-ohw-editable][contenteditable] *,
|
|
9978
|
+
nav [data-ohw-href-key] [data-ohw-editable][contenteditable],
|
|
9979
|
+
nav [data-ohw-href-key] [data-ohw-editable][contenteditable] *,
|
|
9980
|
+
footer [data-ohw-href-key] [data-ohw-editable][contenteditable],
|
|
9981
|
+
footer [data-ohw-href-key] [data-ohw-editable][contenteditable] * {
|
|
8106
9982
|
outline: none !important;
|
|
8107
|
-
caret-color: ${PRIMARY2};
|
|
9983
|
+
caret-color: ${PRIMARY2} !important;
|
|
8108
9984
|
cursor: text !important;
|
|
8109
9985
|
}
|
|
8110
9986
|
[data-ohw-editable][contenteditable]::selection,
|
|
@@ -8113,6 +9989,9 @@ function OhhwellsBridge() {
|
|
|
8113
9989
|
[data-ohw-editable-state][data-ohw-active-state] [data-ohw-editable] { pointer-events: auto !important; }
|
|
8114
9990
|
[data-ohw-editable-state][data-ohw-active-state][data-ohw-editable] { pointer-events: auto !important; }
|
|
8115
9991
|
`;
|
|
9992
|
+
if (!existing) {
|
|
9993
|
+
const base = document.createElement("style");
|
|
9994
|
+
base.setAttribute("data-ohw-edit-style", "");
|
|
8116
9995
|
const forceHover = document.createElement("style");
|
|
8117
9996
|
forceHover.setAttribute("data-ohw-active-state-style", "");
|
|
8118
9997
|
const stateViews = document.createElement("style");
|
|
@@ -8128,14 +10007,43 @@ function OhhwellsBridge() {
|
|
|
8128
10007
|
document.head.appendChild(stateViews);
|
|
8129
10008
|
editStylesRef.current = { base, forceHover, stateViews };
|
|
8130
10009
|
}
|
|
10010
|
+
editStylesRef.current.base.textContent = baseCss;
|
|
10011
|
+
syncNavigationDragCursorAttrs();
|
|
8131
10012
|
refreshStateRules();
|
|
8132
10013
|
const handleClick = (e) => {
|
|
10014
|
+
if (suppressNextClickRef.current || Date.now() < suppressClickUntilRef.current) {
|
|
10015
|
+
suppressNextClickRef.current = false;
|
|
10016
|
+
e.preventDefault();
|
|
10017
|
+
e.stopPropagation();
|
|
10018
|
+
return;
|
|
10019
|
+
}
|
|
8133
10020
|
const target = e.target;
|
|
8134
10021
|
if (target.closest("[data-ohw-toolbar]")) return;
|
|
8135
10022
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
8136
10023
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
8137
10024
|
if (isInsideLinkEditor(target)) return;
|
|
8138
10025
|
if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
10026
|
+
if (target.closest("[data-ohw-item-drag-surface]")) {
|
|
10027
|
+
e.preventDefault();
|
|
10028
|
+
e.stopPropagation();
|
|
10029
|
+
const selected = selectedElRef.current;
|
|
10030
|
+
if (selected && isNavigationItem(selected)) {
|
|
10031
|
+
const editable2 = selected.querySelector('[data-ohw-editable="text"]') ?? selected.querySelector("[data-ohw-editable]");
|
|
10032
|
+
if (editable2) {
|
|
10033
|
+
activateRef.current(editable2, {
|
|
10034
|
+
caretX: e.clientX,
|
|
10035
|
+
caretY: e.clientY
|
|
10036
|
+
});
|
|
10037
|
+
}
|
|
10038
|
+
} else if (selected?.hasAttribute("data-ohw-footer-col")) {
|
|
10039
|
+
const link = listFooterLinksInColumn(selected).find((el) => {
|
|
10040
|
+
const r2 = el.getBoundingClientRect();
|
|
10041
|
+
return e.clientX >= r2.left && e.clientX <= r2.right && e.clientY >= r2.top && e.clientY <= r2.bottom;
|
|
10042
|
+
});
|
|
10043
|
+
if (link) selectRef.current(link);
|
|
10044
|
+
}
|
|
10045
|
+
return;
|
|
10046
|
+
}
|
|
8139
10047
|
const navFromChrome = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
|
|
8140
10048
|
if (navFromChrome) {
|
|
8141
10049
|
e.preventDefault();
|
|
@@ -8143,10 +10051,34 @@ function OhhwellsBridge() {
|
|
|
8143
10051
|
selectFrameRef.current(navFromChrome);
|
|
8144
10052
|
return;
|
|
8145
10053
|
}
|
|
10054
|
+
const footerFromChrome = resolveFooterColumnSelectionTarget(target, e.clientX, e.clientY);
|
|
10055
|
+
if (footerFromChrome) {
|
|
10056
|
+
e.preventDefault();
|
|
10057
|
+
e.stopPropagation();
|
|
10058
|
+
selectFrameRef.current(footerFromChrome);
|
|
10059
|
+
return;
|
|
10060
|
+
}
|
|
8146
10061
|
e.preventDefault();
|
|
8147
10062
|
e.stopPropagation();
|
|
8148
10063
|
return;
|
|
8149
10064
|
}
|
|
10065
|
+
if (activeElRef.current) {
|
|
10066
|
+
const active = activeElRef.current;
|
|
10067
|
+
const inActive = active === target || active.contains(target);
|
|
10068
|
+
const navAnchor = getNavigationItemAnchor(active);
|
|
10069
|
+
const inActiveNav = Boolean(
|
|
10070
|
+
navAnchor && (navAnchor === target || navAnchor.contains(target))
|
|
10071
|
+
);
|
|
10072
|
+
if (inActive || inActiveNav) {
|
|
10073
|
+
e.preventDefault();
|
|
10074
|
+
e.stopPropagation();
|
|
10075
|
+
if (e.detail < 2) {
|
|
10076
|
+
placeCaretAtPoint(active, e.clientX, e.clientY);
|
|
10077
|
+
refreshActiveCommandsRef.current();
|
|
10078
|
+
}
|
|
10079
|
+
return;
|
|
10080
|
+
}
|
|
10081
|
+
}
|
|
8150
10082
|
const editable = target.closest("[data-ohw-editable]");
|
|
8151
10083
|
if (editable) {
|
|
8152
10084
|
if (editable.dataset.ohwEditable === "link") {
|
|
@@ -8190,10 +10122,26 @@ function OhhwellsBridge() {
|
|
|
8190
10122
|
if (hrefAnchor) {
|
|
8191
10123
|
e.preventDefault();
|
|
8192
10124
|
e.stopPropagation();
|
|
8193
|
-
if (selectedElRef.current === hrefAnchor)
|
|
10125
|
+
if (selectedElRef.current === hrefAnchor) {
|
|
10126
|
+
const textEditable = hrefAnchor.querySelector('[data-ohw-editable="text"]') ?? hrefAnchor.querySelector("[data-ohw-editable]");
|
|
10127
|
+
if (textEditable) {
|
|
10128
|
+
activateRef.current(textEditable, {
|
|
10129
|
+
caretX: e.clientX,
|
|
10130
|
+
caretY: e.clientY
|
|
10131
|
+
});
|
|
10132
|
+
}
|
|
10133
|
+
return;
|
|
10134
|
+
}
|
|
8194
10135
|
selectRef.current(hrefAnchor);
|
|
8195
10136
|
return;
|
|
8196
10137
|
}
|
|
10138
|
+
const footerColClick = target.closest("[data-ohw-footer-col]");
|
|
10139
|
+
if (footerColClick) {
|
|
10140
|
+
e.preventDefault();
|
|
10141
|
+
e.stopPropagation();
|
|
10142
|
+
selectFrameRef.current(footerColClick);
|
|
10143
|
+
return;
|
|
10144
|
+
}
|
|
8197
10145
|
const navContainerToSelect = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
|
|
8198
10146
|
if (navContainerToSelect) {
|
|
8199
10147
|
e.preventDefault();
|
|
@@ -8201,6 +10149,13 @@ function OhhwellsBridge() {
|
|
|
8201
10149
|
selectFrameRef.current(navContainerToSelect);
|
|
8202
10150
|
return;
|
|
8203
10151
|
}
|
|
10152
|
+
const footerColumnToSelect = resolveFooterColumnSelectionTarget(target, e.clientX, e.clientY);
|
|
10153
|
+
if (footerColumnToSelect) {
|
|
10154
|
+
e.preventDefault();
|
|
10155
|
+
e.stopPropagation();
|
|
10156
|
+
selectFrameRef.current(footerColumnToSelect);
|
|
10157
|
+
return;
|
|
10158
|
+
}
|
|
8204
10159
|
const selectedContainer = selectedElRef.current;
|
|
8205
10160
|
if (selectedContainer && isNavigationContainer(selectedContainer)) {
|
|
8206
10161
|
const navItem = getNavigationItemAnchor(target);
|
|
@@ -8260,6 +10215,13 @@ function OhhwellsBridge() {
|
|
|
8260
10215
|
const handleMouseOver = (e) => {
|
|
8261
10216
|
if (document.documentElement.hasAttribute("data-ohw-section-picking")) return;
|
|
8262
10217
|
const target = e.target;
|
|
10218
|
+
if (linkPopoverOpenRef.current) {
|
|
10219
|
+
hoveredItemElRef.current = null;
|
|
10220
|
+
setHoveredItemRect(null);
|
|
10221
|
+
hoveredNavContainerRef.current = null;
|
|
10222
|
+
setHoveredNavContainerRect(null);
|
|
10223
|
+
return;
|
|
10224
|
+
}
|
|
8263
10225
|
if (toolbarVariantRef.current !== "select-frame") {
|
|
8264
10226
|
const navContainer = target.closest("[data-ohw-nav-container]");
|
|
8265
10227
|
if (navContainer && !getNavigationItemAnchor(target)) {
|
|
@@ -8279,12 +10241,21 @@ function OhhwellsBridge() {
|
|
|
8279
10241
|
hoveredNavContainerRef.current = null;
|
|
8280
10242
|
setHoveredNavContainerRect(null);
|
|
8281
10243
|
const selected2 = selectedElRef.current;
|
|
8282
|
-
if (selected2 === navAnchor
|
|
10244
|
+
if (selected2 === navAnchor) return;
|
|
8283
10245
|
clearHrefKeyHover(navAnchor);
|
|
8284
10246
|
hoveredItemElRef.current = navAnchor;
|
|
8285
10247
|
setHoveredItemRect(navAnchor.getBoundingClientRect());
|
|
8286
10248
|
return;
|
|
8287
10249
|
}
|
|
10250
|
+
const footerCol = target.closest("[data-ohw-footer-col]") ?? target.closest("[data-ohw-footer-column]");
|
|
10251
|
+
if (footerCol) {
|
|
10252
|
+
hoveredNavContainerRef.current = null;
|
|
10253
|
+
setHoveredNavContainerRect(null);
|
|
10254
|
+
if (selectedElRef.current === footerCol) return;
|
|
10255
|
+
hoveredItemElRef.current = footerCol;
|
|
10256
|
+
setHoveredItemRect(footerCol.getBoundingClientRect());
|
|
10257
|
+
return;
|
|
10258
|
+
}
|
|
8288
10259
|
const editable = target.closest("[data-ohw-editable]");
|
|
8289
10260
|
if (!editable) return;
|
|
8290
10261
|
const selected = selectedElRef.current;
|
|
@@ -8302,14 +10273,25 @@ function OhhwellsBridge() {
|
|
|
8302
10273
|
};
|
|
8303
10274
|
const handleMouseOut = (e) => {
|
|
8304
10275
|
const target = e.target;
|
|
8305
|
-
if (target.closest("[data-ohw-nav-container]")) {
|
|
10276
|
+
if (target.closest("[data-ohw-nav-container], [data-ohw-footer-col], [data-ohw-footer-column]")) {
|
|
8306
10277
|
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
8307
|
-
if (related2?.closest("[data-ohw-nav-container], [data-ohw-navbar-container-chrome], [data-ohw-navbar-add-button]")) {
|
|
10278
|
+
if (related2?.closest("[data-ohw-nav-container], [data-ohw-footer-col], [data-ohw-footer-column], [data-ohw-navbar-container-chrome], [data-ohw-navbar-add-button]")) {
|
|
8308
10279
|
return;
|
|
8309
10280
|
}
|
|
8310
10281
|
hoveredNavContainerRef.current = null;
|
|
8311
10282
|
setHoveredNavContainerRect(null);
|
|
8312
10283
|
}
|
|
10284
|
+
const footerCol = target.closest("[data-ohw-footer-col]") ?? target.closest("[data-ohw-footer-column]");
|
|
10285
|
+
if (footerCol && hoveredItemElRef.current === footerCol) {
|
|
10286
|
+
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
10287
|
+
if (related2?.closest("[data-ohw-drag-handle-container], [data-ohw-item-interaction]")) return;
|
|
10288
|
+
if (related2?.closest("[data-ohw-footer-col], [data-ohw-footer-column]") === footerCol) {
|
|
10289
|
+
return;
|
|
10290
|
+
}
|
|
10291
|
+
hoveredItemElRef.current = null;
|
|
10292
|
+
setHoveredItemRect(null);
|
|
10293
|
+
return;
|
|
10294
|
+
}
|
|
8313
10295
|
const navAnchor = getNavigationItemAnchor(target);
|
|
8314
10296
|
if (navAnchor) {
|
|
8315
10297
|
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
@@ -8443,43 +10425,75 @@ function OhhwellsBridge() {
|
|
|
8443
10425
|
if (toolbarVariantRef.current === "select-frame") {
|
|
8444
10426
|
hoveredNavContainerRef.current = null;
|
|
8445
10427
|
setHoveredNavContainerRect(null);
|
|
8446
|
-
return;
|
|
8447
10428
|
}
|
|
8448
|
-
const
|
|
8449
|
-
|
|
8450
|
-
|
|
8451
|
-
|
|
8452
|
-
|
|
10429
|
+
const navContainers = Array.from(
|
|
10430
|
+
document.querySelectorAll("[data-ohw-nav-container]")
|
|
10431
|
+
);
|
|
10432
|
+
const footerColumns = listFooterColumns();
|
|
10433
|
+
for (const container of [...navContainers, ...footerColumns]) {
|
|
10434
|
+
const containerRect = container.getBoundingClientRect();
|
|
10435
|
+
const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
|
|
10436
|
+
if (!overContainer) continue;
|
|
10437
|
+
const navItemHit = Array.from(
|
|
10438
|
+
container.querySelectorAll("[data-ohw-href-key]")
|
|
10439
|
+
).find((el) => {
|
|
10440
|
+
if (!isNavigationItem(el) || isNavbarButton2(el)) return false;
|
|
10441
|
+
const itemRect = el.getBoundingClientRect();
|
|
10442
|
+
return x >= itemRect.left && x <= itemRect.right && y >= itemRect.top && y <= itemRect.bottom;
|
|
10443
|
+
});
|
|
10444
|
+
if (navItemHit) {
|
|
10445
|
+
hoveredNavContainerRef.current = null;
|
|
10446
|
+
setHoveredNavContainerRect(null);
|
|
10447
|
+
const selected = selectedElRef.current;
|
|
10448
|
+
if (selected !== navItemHit) {
|
|
10449
|
+
clearHrefKeyHover(navItemHit);
|
|
10450
|
+
hoveredItemElRef.current = navItemHit;
|
|
10451
|
+
setHoveredItemRect(navItemHit.getBoundingClientRect());
|
|
10452
|
+
} else if (hoveredItemElRef.current === navItemHit) {
|
|
10453
|
+
hoveredItemElRef.current = null;
|
|
10454
|
+
setHoveredItemRect(null);
|
|
10455
|
+
}
|
|
10456
|
+
return;
|
|
10457
|
+
}
|
|
8453
10458
|
}
|
|
8454
|
-
|
|
8455
|
-
|
|
8456
|
-
|
|
10459
|
+
if (toolbarVariantRef.current !== "select-frame") {
|
|
10460
|
+
for (const container of navContainers) {
|
|
10461
|
+
const containerRect = container.getBoundingClientRect();
|
|
10462
|
+
const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
|
|
10463
|
+
if (!overContainer) continue;
|
|
10464
|
+
if (isPointOverNavItem(container, x, y)) continue;
|
|
10465
|
+
hoveredNavContainerRef.current = container;
|
|
10466
|
+
setHoveredNavContainerRect(container.getBoundingClientRect());
|
|
10467
|
+
hoveredItemElRef.current = null;
|
|
10468
|
+
setHoveredItemRect(null);
|
|
10469
|
+
return;
|
|
10470
|
+
}
|
|
8457
10471
|
hoveredNavContainerRef.current = null;
|
|
8458
10472
|
setHoveredNavContainerRect(null);
|
|
8459
|
-
|
|
8460
|
-
}
|
|
8461
|
-
const navItemHit = Array.from(
|
|
8462
|
-
navContainer.querySelectorAll("[data-ohw-href-key]")
|
|
8463
|
-
).find((el) => {
|
|
8464
|
-
if (!isNavigationItem(el) || isNavbarButton2(el)) return false;
|
|
8465
|
-
const itemRect = el.getBoundingClientRect();
|
|
8466
|
-
return x >= itemRect.left && x <= itemRect.right && y >= itemRect.top && y <= itemRect.bottom;
|
|
8467
|
-
});
|
|
8468
|
-
if (navItemHit) {
|
|
10473
|
+
} else {
|
|
8469
10474
|
hoveredNavContainerRef.current = null;
|
|
8470
10475
|
setHoveredNavContainerRect(null);
|
|
8471
|
-
|
|
8472
|
-
|
|
8473
|
-
|
|
8474
|
-
|
|
8475
|
-
|
|
10476
|
+
}
|
|
10477
|
+
for (const column of footerColumns) {
|
|
10478
|
+
const containerRect = column.getBoundingClientRect();
|
|
10479
|
+
const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
|
|
10480
|
+
if (!overContainer) continue;
|
|
10481
|
+
if (isPointOverNavItem(column, x, y)) continue;
|
|
10482
|
+
if (selectedElRef.current === column) {
|
|
10483
|
+
if (hoveredItemElRef.current === column) {
|
|
10484
|
+
hoveredItemElRef.current = null;
|
|
10485
|
+
setHoveredItemRect(null);
|
|
10486
|
+
}
|
|
10487
|
+
return;
|
|
8476
10488
|
}
|
|
10489
|
+
hoveredItemElRef.current = column;
|
|
10490
|
+
setHoveredItemRect(column.getBoundingClientRect());
|
|
8477
10491
|
return;
|
|
8478
10492
|
}
|
|
8479
|
-
|
|
8480
|
-
|
|
8481
|
-
|
|
8482
|
-
|
|
10493
|
+
if (hoveredItemElRef.current?.hasAttribute("data-ohw-footer-col") || hoveredItemElRef.current?.hasAttribute("data-ohw-footer-column")) {
|
|
10494
|
+
hoveredItemElRef.current = null;
|
|
10495
|
+
setHoveredItemRect(null);
|
|
10496
|
+
}
|
|
8483
10497
|
};
|
|
8484
10498
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
8485
10499
|
if (linkPopoverOpenRef.current) {
|
|
@@ -8500,6 +10514,10 @@ function OhhwellsBridge() {
|
|
|
8500
10514
|
}
|
|
8501
10515
|
hoveredNavContainerRef.current = null;
|
|
8502
10516
|
setHoveredNavContainerRect(null);
|
|
10517
|
+
if (hoveredItemElRef.current?.hasAttribute("data-ohw-footer-col") || hoveredItemElRef.current?.hasAttribute("data-ohw-footer-column")) {
|
|
10518
|
+
hoveredItemElRef.current = null;
|
|
10519
|
+
setHoveredItemRect(null);
|
|
10520
|
+
}
|
|
8503
10521
|
const toggleEl = document.querySelector("[data-ohw-state-toggle]");
|
|
8504
10522
|
if (toggleEl) {
|
|
8505
10523
|
const tr = toggleEl.getBoundingClientRect();
|
|
@@ -8747,6 +10765,15 @@ function OhhwellsBridge() {
|
|
|
8747
10765
|
probeHoverCardsAt(clientX, clientY);
|
|
8748
10766
|
};
|
|
8749
10767
|
const handleDragOver = (e) => {
|
|
10768
|
+
const footerSession = footerDragRef.current;
|
|
10769
|
+
if (footerSession) {
|
|
10770
|
+
e.preventDefault();
|
|
10771
|
+
if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
|
|
10772
|
+
const slot = footerSession.kind === "link" && footerSession.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, footerSession.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
|
|
10773
|
+
refreshFooterDragVisualsRef.current(footerSession, slot, e.clientX, e.clientY);
|
|
10774
|
+
return;
|
|
10775
|
+
}
|
|
10776
|
+
if (onNavDragOver(e)) return;
|
|
8750
10777
|
e.preventDefault();
|
|
8751
10778
|
const el = findImageAtPoint(e.clientX, e.clientY, false);
|
|
8752
10779
|
if (!el) {
|
|
@@ -8909,8 +10936,8 @@ function OhhwellsBridge() {
|
|
|
8909
10936
|
if (sibling !== el) sibling.innerHTML = html;
|
|
8910
10937
|
});
|
|
8911
10938
|
const timers = autoSaveTimers.current;
|
|
8912
|
-
const
|
|
8913
|
-
if (
|
|
10939
|
+
const existing2 = timers.get(key);
|
|
10940
|
+
if (existing2) clearTimeout(existing2);
|
|
8914
10941
|
timers.set(key, setTimeout(() => {
|
|
8915
10942
|
timers.delete(key);
|
|
8916
10943
|
postToParentRef.current({ type: "ow:change", nodes: [{ key, text: html }] });
|
|
@@ -8953,6 +10980,7 @@ function OhhwellsBridge() {
|
|
|
8953
10980
|
}
|
|
8954
10981
|
editContentRef.current = { ...editContentRef.current, ...content };
|
|
8955
10982
|
reconcileNavbarItemsFromContent(editContentRef.current);
|
|
10983
|
+
syncNavigationDragCursorAttrs();
|
|
8956
10984
|
enforceLinkHrefs();
|
|
8957
10985
|
postToParentRef.current({ type: "ow:hydrate-done" });
|
|
8958
10986
|
};
|
|
@@ -8973,6 +11001,48 @@ function OhhwellsBridge() {
|
|
|
8973
11001
|
if (e.data?.type !== "ui:escape") return;
|
|
8974
11002
|
if (linkPopoverOpenRef.current) {
|
|
8975
11003
|
setLinkPopoverRef.current(null);
|
|
11004
|
+
return;
|
|
11005
|
+
}
|
|
11006
|
+
if (activeElRef.current) {
|
|
11007
|
+
const hrefCtx = getHrefKeyFromElement(activeElRef.current);
|
|
11008
|
+
const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
|
|
11009
|
+
if (navAnchor) {
|
|
11010
|
+
const el = activeElRef.current;
|
|
11011
|
+
if (originalContentRef.current !== null) {
|
|
11012
|
+
el.innerHTML = originalContentRef.current;
|
|
11013
|
+
}
|
|
11014
|
+
el.removeAttribute("contenteditable");
|
|
11015
|
+
el.removeAttribute("data-ohw-editing");
|
|
11016
|
+
activeElRef.current = null;
|
|
11017
|
+
setMaxBadge(null);
|
|
11018
|
+
setActiveCommands(/* @__PURE__ */ new Set());
|
|
11019
|
+
setToolbarShowEditLink(false);
|
|
11020
|
+
postToParentRef.current({ type: "ow:exit-edit" });
|
|
11021
|
+
reselectNavigationItemRef.current(navAnchor);
|
|
11022
|
+
return;
|
|
11023
|
+
}
|
|
11024
|
+
if (originalContentRef.current !== null) {
|
|
11025
|
+
activeElRef.current.innerHTML = originalContentRef.current;
|
|
11026
|
+
const key = activeElRef.current.dataset.ohwKey;
|
|
11027
|
+
if (key) {
|
|
11028
|
+
postToParentRef.current({ type: "ow:change", nodes: [{ key, text: originalContentRef.current }] });
|
|
11029
|
+
}
|
|
11030
|
+
}
|
|
11031
|
+
deselectRef.current();
|
|
11032
|
+
deactivateRef.current();
|
|
11033
|
+
return;
|
|
11034
|
+
}
|
|
11035
|
+
if (selectedElRef.current) {
|
|
11036
|
+
if (toolbarVariantRef.current === "select-frame") {
|
|
11037
|
+
deselectRef.current();
|
|
11038
|
+
return;
|
|
11039
|
+
}
|
|
11040
|
+
const parent = getNavigationSelectionParent(selectedElRef.current);
|
|
11041
|
+
if (parent && isNavigationContainer(parent)) {
|
|
11042
|
+
selectFrameRef.current(parent);
|
|
11043
|
+
} else {
|
|
11044
|
+
deselectRef.current();
|
|
11045
|
+
}
|
|
8976
11046
|
}
|
|
8977
11047
|
};
|
|
8978
11048
|
window.addEventListener("message", handleUiEscape);
|
|
@@ -8997,7 +11067,7 @@ function OhhwellsBridge() {
|
|
|
8997
11067
|
return;
|
|
8998
11068
|
}
|
|
8999
11069
|
const parent = getNavigationSelectionParent(selectedElRef.current);
|
|
9000
|
-
if (parent) {
|
|
11070
|
+
if (parent && isNavigationContainer(parent)) {
|
|
9001
11071
|
e.preventDefault();
|
|
9002
11072
|
selectFrameRef.current(parent);
|
|
9003
11073
|
} else {
|
|
@@ -9015,6 +11085,7 @@ function OhhwellsBridge() {
|
|
|
9015
11085
|
el2.innerHTML = originalContentRef.current;
|
|
9016
11086
|
}
|
|
9017
11087
|
el2.removeAttribute("contenteditable");
|
|
11088
|
+
el2.removeAttribute("data-ohw-editing");
|
|
9018
11089
|
activeElRef.current = null;
|
|
9019
11090
|
setMaxBadge(null);
|
|
9020
11091
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
@@ -9066,6 +11137,26 @@ function OhhwellsBridge() {
|
|
|
9066
11137
|
if (siblingHintElRef.current) {
|
|
9067
11138
|
setSiblingHintRect(siblingHintElRef.current.getBoundingClientRect());
|
|
9068
11139
|
}
|
|
11140
|
+
const selected = selectedElRef.current;
|
|
11141
|
+
if (selected && !footerDragRef.current && !navDragRef.current) {
|
|
11142
|
+
if (selected.hasAttribute("data-ohw-footer-col") || Boolean(selected.closest("footer") && isInferredFooterGroup(selected))) {
|
|
11143
|
+
setSiblingHintRects(
|
|
11144
|
+
listFooterColumns().filter((column) => column !== selected).map((column) => column.getBoundingClientRect())
|
|
11145
|
+
);
|
|
11146
|
+
} else if (isNavigationItem(selected)) {
|
|
11147
|
+
setSiblingHintRects(collectNavigationItemSiblingHintRects(selected));
|
|
11148
|
+
}
|
|
11149
|
+
}
|
|
11150
|
+
if (footerDragRef.current) {
|
|
11151
|
+
const session = footerDragRef.current;
|
|
11152
|
+
const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
|
|
11153
|
+
refreshFooterDragVisualsRef.current(session, slot, session.lastClientX, session.lastClientY);
|
|
11154
|
+
}
|
|
11155
|
+
if (navDragRef.current) {
|
|
11156
|
+
const session = navDragRef.current;
|
|
11157
|
+
const slot = hitTestNavDropSlot(session.lastClientX, session.lastClientY, session.hrefKey);
|
|
11158
|
+
refreshNavDragVisualsRef.current(session, slot, session.lastClientX, session.lastClientY);
|
|
11159
|
+
}
|
|
9069
11160
|
if (hoveredImageRef.current) {
|
|
9070
11161
|
const el = hoveredImageRef.current;
|
|
9071
11162
|
const r2 = el.getBoundingClientRect();
|
|
@@ -9076,7 +11167,7 @@ function OhhwellsBridge() {
|
|
|
9076
11167
|
};
|
|
9077
11168
|
const handleSave = (e) => {
|
|
9078
11169
|
if (e.data?.type !== "ow:save") return;
|
|
9079
|
-
const nodes = collectEditableNodes();
|
|
11170
|
+
const nodes = collectEditableNodes(editContentRef.current);
|
|
9080
11171
|
const tracker = document.querySelector("[data-ohw-sections-tracker]");
|
|
9081
11172
|
if (tracker?.textContent) nodes.push({ key: "__ohw_sections", type: "sections", text: tracker.textContent });
|
|
9082
11173
|
postToParentRef.current({ type: "ow:save-result", nodes });
|
|
@@ -9202,15 +11293,15 @@ function OhhwellsBridge() {
|
|
|
9202
11293
|
};
|
|
9203
11294
|
const applyToolbarPos = (rect) => {
|
|
9204
11295
|
const ps = parentScrollRef.current;
|
|
9205
|
-
const
|
|
11296
|
+
const measuredW = toolbarElRef.current?.offsetWidth || 330;
|
|
9206
11297
|
if (toolbarElRef.current) {
|
|
9207
|
-
const { top, left, transform } = calcToolbarPos(rect, ps,
|
|
11298
|
+
const { top, left, transform } = calcToolbarPos(rect, ps, measuredW);
|
|
9208
11299
|
toolbarElRef.current.style.top = `${top}px`;
|
|
9209
11300
|
toolbarElRef.current.style.left = `${left}px`;
|
|
9210
11301
|
toolbarElRef.current.style.transform = transform;
|
|
9211
11302
|
}
|
|
9212
11303
|
if (glowElRef.current) {
|
|
9213
|
-
const GAP =
|
|
11304
|
+
const GAP = SELECTION_CHROME_GAP2;
|
|
9214
11305
|
glowElRef.current.style.top = `${rect.top - GAP}px`;
|
|
9215
11306
|
glowElRef.current.style.left = `${rect.left - GAP}px`;
|
|
9216
11307
|
glowElRef.current.style.width = `${rect.width + GAP * 2}px`;
|
|
@@ -9298,6 +11389,11 @@ function OhhwellsBridge() {
|
|
|
9298
11389
|
return;
|
|
9299
11390
|
}
|
|
9300
11391
|
}
|
|
11392
|
+
const footerColumn = findHoveredNavOrFooterContainer(clientX, clientY);
|
|
11393
|
+
if (footerColumn?.hasAttribute("data-ohw-footer-col") || footerColumn?.hasAttribute("data-ohw-footer-column")) {
|
|
11394
|
+
selectFrameRef.current(footerColumn);
|
|
11395
|
+
return;
|
|
11396
|
+
}
|
|
9301
11397
|
deactivateRef.current();
|
|
9302
11398
|
};
|
|
9303
11399
|
window.addEventListener("message", handleSave);
|
|
@@ -9369,7 +11465,161 @@ function OhhwellsBridge() {
|
|
|
9369
11465
|
if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
|
|
9370
11466
|
};
|
|
9371
11467
|
}, [isEditMode, refreshStateRules]);
|
|
9372
|
-
|
|
11468
|
+
useEffect8(() => {
|
|
11469
|
+
if (!isEditMode) return;
|
|
11470
|
+
const THRESHOLD = 10;
|
|
11471
|
+
const resolveWasSelected = (el) => {
|
|
11472
|
+
if (selectedElRef.current === el) return true;
|
|
11473
|
+
const activeAnchor = activeElRef.current ? getNavigationItemAnchor(activeElRef.current) : null;
|
|
11474
|
+
return activeAnchor === el;
|
|
11475
|
+
};
|
|
11476
|
+
const onPointerDown = (e) => {
|
|
11477
|
+
if (e.button !== 0) return;
|
|
11478
|
+
if (suppressNextClickRef.current && Date.now() >= suppressClickUntilRef.current && !footerDragRef.current && !footerPointerDragRef.current?.started) {
|
|
11479
|
+
suppressNextClickRef.current = false;
|
|
11480
|
+
}
|
|
11481
|
+
if (footerDragRef.current) return;
|
|
11482
|
+
const target = e.target;
|
|
11483
|
+
if (!target) return;
|
|
11484
|
+
if (target.closest('[data-ohw-drag-handle-container], [data-slot="drag-handle"], [data-ohw-toolbar], [data-ohw-item-toolbar-anchor], [data-ohw-link-popover-root]')) {
|
|
11485
|
+
return;
|
|
11486
|
+
}
|
|
11487
|
+
if (target.closest("[data-ohw-item-drag-surface]")) return;
|
|
11488
|
+
const anchor = getNavigationItemAnchor(target);
|
|
11489
|
+
const hrefKey = anchor?.getAttribute("data-ohw-href-key") ?? null;
|
|
11490
|
+
if (anchor && isFooterHrefKey(hrefKey)) {
|
|
11491
|
+
armFooterPressDrag();
|
|
11492
|
+
footerPointerDragRef.current = {
|
|
11493
|
+
el: anchor,
|
|
11494
|
+
kind: "link",
|
|
11495
|
+
startX: e.clientX,
|
|
11496
|
+
startY: e.clientY,
|
|
11497
|
+
pointerId: e.pointerId,
|
|
11498
|
+
wasSelected: resolveWasSelected(anchor),
|
|
11499
|
+
started: false
|
|
11500
|
+
};
|
|
11501
|
+
return;
|
|
11502
|
+
}
|
|
11503
|
+
const col = target.closest("[data-ohw-footer-col]");
|
|
11504
|
+
if (col && !getNavigationItemAnchor(target)) {
|
|
11505
|
+
armFooterPressDrag();
|
|
11506
|
+
footerPointerDragRef.current = {
|
|
11507
|
+
el: col,
|
|
11508
|
+
kind: "column",
|
|
11509
|
+
startX: e.clientX,
|
|
11510
|
+
startY: e.clientY,
|
|
11511
|
+
pointerId: e.pointerId,
|
|
11512
|
+
wasSelected: resolveWasSelected(col),
|
|
11513
|
+
started: false
|
|
11514
|
+
};
|
|
11515
|
+
}
|
|
11516
|
+
};
|
|
11517
|
+
const onPointerMove = (e) => {
|
|
11518
|
+
const pending = footerPointerDragRef.current;
|
|
11519
|
+
if (!pending) return;
|
|
11520
|
+
if (pending.started) {
|
|
11521
|
+
e.preventDefault();
|
|
11522
|
+
clearTextSelection();
|
|
11523
|
+
const session = footerDragRef.current;
|
|
11524
|
+
if (!session) return;
|
|
11525
|
+
const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, session.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
|
|
11526
|
+
refreshFooterDragVisualsRef.current(session, slot, e.clientX, e.clientY);
|
|
11527
|
+
return;
|
|
11528
|
+
}
|
|
11529
|
+
const dx = e.clientX - pending.startX;
|
|
11530
|
+
const dy = e.clientY - pending.startY;
|
|
11531
|
+
if (dx * dx + dy * dy < THRESHOLD * THRESHOLD) return;
|
|
11532
|
+
e.preventDefault();
|
|
11533
|
+
pending.started = true;
|
|
11534
|
+
clearTextSelection();
|
|
11535
|
+
try {
|
|
11536
|
+
document.body.setPointerCapture(pending.pointerId);
|
|
11537
|
+
} catch {
|
|
11538
|
+
}
|
|
11539
|
+
if (linkPopoverOpenRef.current) {
|
|
11540
|
+
setLinkPopoverRef.current(null);
|
|
11541
|
+
}
|
|
11542
|
+
if (activeElRef.current) {
|
|
11543
|
+
deactivateRef.current();
|
|
11544
|
+
}
|
|
11545
|
+
if (pending.kind === "link") {
|
|
11546
|
+
const key = pending.el.getAttribute("data-ohw-href-key");
|
|
11547
|
+
if (!key) return;
|
|
11548
|
+
const column = findFooterColumnForLink(pending.el);
|
|
11549
|
+
const columns2 = listFooterColumns();
|
|
11550
|
+
beginFooterDragRef.current({
|
|
11551
|
+
kind: "link",
|
|
11552
|
+
hrefKey: key,
|
|
11553
|
+
columnEl: column,
|
|
11554
|
+
sourceColumnIndex: column ? columns2.indexOf(column) : 0,
|
|
11555
|
+
wasSelected: pending.wasSelected,
|
|
11556
|
+
draggedEl: pending.el,
|
|
11557
|
+
lastClientX: e.clientX,
|
|
11558
|
+
lastClientY: e.clientY,
|
|
11559
|
+
activeSlot: null
|
|
11560
|
+
});
|
|
11561
|
+
return;
|
|
11562
|
+
}
|
|
11563
|
+
const columns = listFooterColumns();
|
|
11564
|
+
const idx = columns.indexOf(pending.el);
|
|
11565
|
+
if (idx < 0) return;
|
|
11566
|
+
beginFooterDragRef.current({
|
|
11567
|
+
kind: "column",
|
|
11568
|
+
hrefKey: null,
|
|
11569
|
+
columnEl: pending.el,
|
|
11570
|
+
sourceColumnIndex: idx,
|
|
11571
|
+
wasSelected: pending.wasSelected,
|
|
11572
|
+
draggedEl: pending.el,
|
|
11573
|
+
lastClientX: e.clientX,
|
|
11574
|
+
lastClientY: e.clientY,
|
|
11575
|
+
activeSlot: null
|
|
11576
|
+
});
|
|
11577
|
+
};
|
|
11578
|
+
const endPointerDrag = (e) => {
|
|
11579
|
+
const pending = footerPointerDragRef.current;
|
|
11580
|
+
footerPointerDragRef.current = null;
|
|
11581
|
+
try {
|
|
11582
|
+
if (document.body.hasPointerCapture(e.pointerId)) {
|
|
11583
|
+
document.body.releasePointerCapture(e.pointerId);
|
|
11584
|
+
}
|
|
11585
|
+
} catch {
|
|
11586
|
+
}
|
|
11587
|
+
if (!pending?.started) {
|
|
11588
|
+
unlockFooterDragInteraction();
|
|
11589
|
+
return;
|
|
11590
|
+
}
|
|
11591
|
+
suppressNextClickRef.current = true;
|
|
11592
|
+
suppressClickUntilRef.current = Date.now() + 500;
|
|
11593
|
+
commitFooterDragRef.current(e.clientX, e.clientY);
|
|
11594
|
+
};
|
|
11595
|
+
const blockSelectStart = (e) => {
|
|
11596
|
+
if (footerDragRef.current || footerPointerDragRef.current?.started || document.documentElement.hasAttribute("data-ohw-footer-press-drag")) {
|
|
11597
|
+
e.preventDefault();
|
|
11598
|
+
}
|
|
11599
|
+
};
|
|
11600
|
+
const onDragEnd = (_e) => {
|
|
11601
|
+
if (!footerDragRef.current) return;
|
|
11602
|
+
suppressNextClickRef.current = true;
|
|
11603
|
+
suppressClickUntilRef.current = Date.now() + 500;
|
|
11604
|
+
commitFooterDragRef.current();
|
|
11605
|
+
};
|
|
11606
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
11607
|
+
document.addEventListener("pointermove", onPointerMove, true);
|
|
11608
|
+
document.addEventListener("pointerup", endPointerDrag, true);
|
|
11609
|
+
document.addEventListener("pointercancel", endPointerDrag, true);
|
|
11610
|
+
document.addEventListener("selectstart", blockSelectStart, true);
|
|
11611
|
+
document.addEventListener("dragend", onDragEnd, true);
|
|
11612
|
+
return () => {
|
|
11613
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
11614
|
+
document.removeEventListener("pointermove", onPointerMove, true);
|
|
11615
|
+
document.removeEventListener("pointerup", endPointerDrag, true);
|
|
11616
|
+
document.removeEventListener("pointercancel", endPointerDrag, true);
|
|
11617
|
+
document.removeEventListener("selectstart", blockSelectStart, true);
|
|
11618
|
+
document.removeEventListener("dragend", onDragEnd, true);
|
|
11619
|
+
unlockFooterDragInteraction();
|
|
11620
|
+
};
|
|
11621
|
+
}, [isEditMode]);
|
|
11622
|
+
useEffect8(() => {
|
|
9373
11623
|
const handler = (e) => {
|
|
9374
11624
|
if (e.data?.type !== "ow:request-schedule-config") return;
|
|
9375
11625
|
const insertAfterVal = e.data.insertAfter;
|
|
@@ -9385,7 +11635,7 @@ function OhhwellsBridge() {
|
|
|
9385
11635
|
window.addEventListener("message", handler);
|
|
9386
11636
|
return () => window.removeEventListener("message", handler);
|
|
9387
11637
|
}, [processConfigRequest]);
|
|
9388
|
-
|
|
11638
|
+
useEffect8(() => {
|
|
9389
11639
|
if (!isEditMode) return;
|
|
9390
11640
|
document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
|
|
9391
11641
|
el.removeAttribute("data-ohw-active-state");
|
|
@@ -9406,7 +11656,13 @@ function OhhwellsBridge() {
|
|
|
9406
11656
|
const next = { ...prev, [pathKey]: sections };
|
|
9407
11657
|
return shouldUseDevFixtures() ? { ...DEV_SECTIONS_BY_PATH, ...next } : next;
|
|
9408
11658
|
});
|
|
9409
|
-
postToParent2({
|
|
11659
|
+
postToParent2({
|
|
11660
|
+
type: "ow:ready",
|
|
11661
|
+
version: "1",
|
|
11662
|
+
path: pathname,
|
|
11663
|
+
nodes: collectEditableNodes(editContentRef.current),
|
|
11664
|
+
sections
|
|
11665
|
+
});
|
|
9410
11666
|
postToParent2({ type: "ow:request-site-pages" });
|
|
9411
11667
|
}, 150);
|
|
9412
11668
|
return () => {
|
|
@@ -9414,19 +11670,19 @@ function OhhwellsBridge() {
|
|
|
9414
11670
|
clearTimeout(timer);
|
|
9415
11671
|
};
|
|
9416
11672
|
}, [pathname, isEditMode, refreshStateRules, postToParent2]);
|
|
9417
|
-
|
|
11673
|
+
useEffect8(() => {
|
|
9418
11674
|
scrollToHashSectionWhenReady();
|
|
9419
11675
|
const onHashChange = () => scrollToHashSectionWhenReady();
|
|
9420
11676
|
window.addEventListener("hashchange", onHashChange);
|
|
9421
11677
|
return () => window.removeEventListener("hashchange", onHashChange);
|
|
9422
11678
|
}, [pathname]);
|
|
9423
|
-
const handleCommand =
|
|
11679
|
+
const handleCommand = useCallback4((cmd) => {
|
|
9424
11680
|
document.execCommand(cmd, false);
|
|
9425
11681
|
activeElRef.current?.focus();
|
|
9426
11682
|
if (activeElRef.current) setToolbarRect(getEditMeasureEl(activeElRef.current).getBoundingClientRect());
|
|
9427
11683
|
refreshActiveCommandsRef.current();
|
|
9428
11684
|
}, []);
|
|
9429
|
-
const handleStateChange =
|
|
11685
|
+
const handleStateChange = useCallback4((state) => {
|
|
9430
11686
|
if (!activeStateElRef.current) return;
|
|
9431
11687
|
const el = activeStateElRef.current;
|
|
9432
11688
|
if (state === "Default") {
|
|
@@ -9439,11 +11695,11 @@ function OhhwellsBridge() {
|
|
|
9439
11695
|
}
|
|
9440
11696
|
setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
|
|
9441
11697
|
}, [deactivate]);
|
|
9442
|
-
const closeLinkPopover =
|
|
11698
|
+
const closeLinkPopover = useCallback4(() => {
|
|
9443
11699
|
addNavAfterAnchorRef.current = null;
|
|
9444
11700
|
setLinkPopover(null);
|
|
9445
11701
|
}, []);
|
|
9446
|
-
const openLinkPopoverForActive =
|
|
11702
|
+
const openLinkPopoverForActive = useCallback4(() => {
|
|
9447
11703
|
const hrefCtx = getHrefKeyFromElement(activeElRef.current);
|
|
9448
11704
|
if (!hrefCtx) return;
|
|
9449
11705
|
bumpLinkPopoverGrace();
|
|
@@ -9454,7 +11710,7 @@ function OhhwellsBridge() {
|
|
|
9454
11710
|
});
|
|
9455
11711
|
deactivate();
|
|
9456
11712
|
}, [deactivate]);
|
|
9457
|
-
const openLinkPopoverForSelected =
|
|
11713
|
+
const openLinkPopoverForSelected = useCallback4(() => {
|
|
9458
11714
|
const anchor = selectedElRef.current;
|
|
9459
11715
|
if (!anchor) return;
|
|
9460
11716
|
const key = anchor.getAttribute("data-ohw-href-key");
|
|
@@ -9467,7 +11723,7 @@ function OhhwellsBridge() {
|
|
|
9467
11723
|
});
|
|
9468
11724
|
deselect();
|
|
9469
11725
|
}, [deselect]);
|
|
9470
|
-
const handleLinkPopoverSubmit =
|
|
11726
|
+
const handleLinkPopoverSubmit = useCallback4(
|
|
9471
11727
|
(target) => {
|
|
9472
11728
|
const session = linkPopoverSessionRef.current;
|
|
9473
11729
|
if (!session) return;
|
|
@@ -9526,13 +11782,13 @@ function OhhwellsBridge() {
|
|
|
9526
11782
|
const showEditLink = toolbarShowEditLink;
|
|
9527
11783
|
const currentSections = sectionsByPath[pathname] ?? [];
|
|
9528
11784
|
linkPopoverOpenRef.current = linkPopover !== null;
|
|
9529
|
-
const handleMediaReplace =
|
|
11785
|
+
const handleMediaReplace = useCallback4(
|
|
9530
11786
|
(key) => {
|
|
9531
11787
|
postToParent2({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
|
|
9532
11788
|
},
|
|
9533
11789
|
[postToParent2, mediaHover?.elementType]
|
|
9534
11790
|
);
|
|
9535
|
-
const handleMediaFadeOutComplete =
|
|
11791
|
+
const handleMediaFadeOutComplete = useCallback4((key) => {
|
|
9536
11792
|
setUploadingRects((prev) => {
|
|
9537
11793
|
if (!(key in prev)) return prev;
|
|
9538
11794
|
const next = { ...prev };
|
|
@@ -9540,7 +11796,7 @@ function OhhwellsBridge() {
|
|
|
9540
11796
|
return next;
|
|
9541
11797
|
});
|
|
9542
11798
|
}, []);
|
|
9543
|
-
const handleVideoSettingsChange =
|
|
11799
|
+
const handleVideoSettingsChange = useCallback4(
|
|
9544
11800
|
(key, settings) => {
|
|
9545
11801
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
9546
11802
|
const video = getVideoEl(el);
|
|
@@ -9564,8 +11820,8 @@ function OhhwellsBridge() {
|
|
|
9564
11820
|
);
|
|
9565
11821
|
return bridgeRoot ? createPortal2(
|
|
9566
11822
|
/* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
9567
|
-
/* @__PURE__ */
|
|
9568
|
-
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */
|
|
11823
|
+
/* @__PURE__ */ jsx24("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
11824
|
+
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ jsx24(
|
|
9569
11825
|
MediaOverlay,
|
|
9570
11826
|
{
|
|
9571
11827
|
hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
|
|
@@ -9576,7 +11832,7 @@ function OhhwellsBridge() {
|
|
|
9576
11832
|
},
|
|
9577
11833
|
`uploading-${key}`
|
|
9578
11834
|
)),
|
|
9579
|
-
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */
|
|
11835
|
+
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ jsx24(
|
|
9580
11836
|
MediaOverlay,
|
|
9581
11837
|
{
|
|
9582
11838
|
hover: mediaHover,
|
|
@@ -9585,49 +11841,93 @@ function OhhwellsBridge() {
|
|
|
9585
11841
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
9586
11842
|
}
|
|
9587
11843
|
),
|
|
9588
|
-
siblingHintRect && !isItemDragging && /* @__PURE__ */
|
|
9589
|
-
|
|
9590
|
-
|
|
9591
|
-
|
|
11844
|
+
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx24(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
11845
|
+
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx24(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
|
|
11846
|
+
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ jsx24(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
|
|
11847
|
+
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ jsx24(
|
|
11848
|
+
"div",
|
|
9592
11849
|
{
|
|
9593
|
-
|
|
9594
|
-
|
|
9595
|
-
|
|
9596
|
-
|
|
9597
|
-
|
|
9598
|
-
|
|
11850
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
11851
|
+
style: {
|
|
11852
|
+
left: slot.left,
|
|
11853
|
+
top: slot.top,
|
|
11854
|
+
width: slot.width,
|
|
11855
|
+
height: slot.height
|
|
11856
|
+
},
|
|
11857
|
+
children: /* @__PURE__ */ jsx24(
|
|
11858
|
+
DropIndicator,
|
|
11859
|
+
{
|
|
11860
|
+
direction: slot.direction,
|
|
11861
|
+
state: activeFooterDropIndex === i ? "dragActive" : "dragIdle",
|
|
11862
|
+
className: "!h-full !w-full"
|
|
11863
|
+
}
|
|
11864
|
+
)
|
|
11865
|
+
},
|
|
11866
|
+
`footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
|
|
11867
|
+
)),
|
|
11868
|
+
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx24(
|
|
11869
|
+
"div",
|
|
11870
|
+
{
|
|
11871
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
11872
|
+
style: {
|
|
11873
|
+
left: slot.left,
|
|
11874
|
+
top: slot.top,
|
|
11875
|
+
width: slot.width,
|
|
11876
|
+
height: slot.height
|
|
11877
|
+
},
|
|
11878
|
+
children: /* @__PURE__ */ jsx24(
|
|
11879
|
+
DropIndicator,
|
|
11880
|
+
{
|
|
11881
|
+
direction: slot.direction,
|
|
11882
|
+
state: activeNavDropIndex === i ? "dragActive" : "dragIdle",
|
|
11883
|
+
className: "!h-full !w-full"
|
|
11884
|
+
}
|
|
11885
|
+
)
|
|
11886
|
+
},
|
|
11887
|
+
`nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
|
|
11888
|
+
)),
|
|
11889
|
+
hoveredNavContainerRect && toolbarVariant !== "select-frame" && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx24(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
|
|
11890
|
+
hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx24(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
11891
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx24(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
|
|
11892
|
+
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ jsx24(
|
|
9599
11893
|
ItemInteractionLayer,
|
|
9600
11894
|
{
|
|
9601
|
-
rect: toolbarRect,
|
|
11895
|
+
rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
|
|
9602
11896
|
elRef: glowElRef,
|
|
9603
11897
|
state: isItemDragging ? "dragging" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
|
|
9604
|
-
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey),
|
|
11898
|
+
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey) || toolbarVariant === "select-frame" && isFooterFrameSelection,
|
|
9605
11899
|
dragDisabled: reorderDragDisabled,
|
|
9606
11900
|
dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
|
|
9607
11901
|
onDragHandleDragStart: handleItemDragStart,
|
|
9608
11902
|
onDragHandleDragEnd: handleItemDragEnd,
|
|
9609
|
-
|
|
11903
|
+
onItemPointerDown: handleItemChromePointerDown,
|
|
11904
|
+
onItemClick: handleItemChromeClick,
|
|
11905
|
+
itemDragSurface: !isFooterFrameSelection,
|
|
11906
|
+
toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ jsx24(
|
|
9610
11907
|
ItemActionToolbar,
|
|
9611
11908
|
{
|
|
9612
11909
|
onEditLink: openLinkPopoverForSelected,
|
|
9613
11910
|
addItemDisabled: true,
|
|
9614
11911
|
editLinkDisabled: false,
|
|
9615
|
-
moreDisabled: true
|
|
11912
|
+
moreDisabled: true,
|
|
11913
|
+
showAddItem: !selectedIsCta,
|
|
11914
|
+
showMore: !selectedIsCta
|
|
9616
11915
|
}
|
|
9617
11916
|
) : void 0
|
|
9618
11917
|
}
|
|
9619
11918
|
),
|
|
9620
|
-
toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
9621
|
-
/* @__PURE__ */
|
|
11919
|
+
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
11920
|
+
/* @__PURE__ */ jsx24(
|
|
9622
11921
|
EditGlowChrome,
|
|
9623
11922
|
{
|
|
9624
11923
|
rect: toolbarRect,
|
|
9625
11924
|
elRef: glowElRef,
|
|
9626
11925
|
reorderHrefKey,
|
|
9627
|
-
dragDisabled: reorderDragDisabled
|
|
11926
|
+
dragDisabled: reorderDragDisabled,
|
|
11927
|
+
hideHandle: isItemDragging
|
|
9628
11928
|
}
|
|
9629
11929
|
),
|
|
9630
|
-
/* @__PURE__ */
|
|
11930
|
+
/* @__PURE__ */ jsx24(
|
|
9631
11931
|
FloatingToolbar,
|
|
9632
11932
|
{
|
|
9633
11933
|
rect: toolbarRect,
|
|
@@ -9666,7 +11966,7 @@ function OhhwellsBridge() {
|
|
|
9666
11966
|
]
|
|
9667
11967
|
}
|
|
9668
11968
|
),
|
|
9669
|
-
toggleState && !linkPopover && /* @__PURE__ */
|
|
11969
|
+
toggleState && !linkPopover && /* @__PURE__ */ jsx24(
|
|
9670
11970
|
StateToggle,
|
|
9671
11971
|
{
|
|
9672
11972
|
rect: toggleState.rect,
|
|
@@ -9682,25 +11982,29 @@ function OhhwellsBridge() {
|
|
|
9682
11982
|
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
9683
11983
|
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
9684
11984
|
children: [
|
|
9685
|
-
/* @__PURE__ */
|
|
9686
|
-
/* @__PURE__ */
|
|
11985
|
+
/* @__PURE__ */ jsx24("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
11986
|
+
/* @__PURE__ */ jsx24(
|
|
9687
11987
|
Badge,
|
|
9688
11988
|
{
|
|
9689
11989
|
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",
|
|
9690
11990
|
onClick: () => {
|
|
9691
11991
|
window.parent.postMessage(
|
|
9692
|
-
{
|
|
11992
|
+
{
|
|
11993
|
+
type: "ow:add-section",
|
|
11994
|
+
insertAfter: sectionGap.insertAfter,
|
|
11995
|
+
insertBefore: sectionGap.insertBefore
|
|
11996
|
+
},
|
|
9693
11997
|
"*"
|
|
9694
11998
|
);
|
|
9695
11999
|
},
|
|
9696
12000
|
children: "Add Section"
|
|
9697
12001
|
}
|
|
9698
12002
|
),
|
|
9699
|
-
/* @__PURE__ */
|
|
12003
|
+
/* @__PURE__ */ jsx24("div", { className: "flex-1 bg-primary", style: { height: 3 } })
|
|
9700
12004
|
]
|
|
9701
12005
|
}
|
|
9702
12006
|
),
|
|
9703
|
-
linkPopover && dialogPortalContainer ? /* @__PURE__ */
|
|
12007
|
+
linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx24(
|
|
9704
12008
|
LinkPopover,
|
|
9705
12009
|
{
|
|
9706
12010
|
panelRef: linkPopoverPanelRef,
|
|
@@ -9721,48 +12025,6 @@ function OhhwellsBridge() {
|
|
|
9721
12025
|
bridgeRoot
|
|
9722
12026
|
) : null;
|
|
9723
12027
|
}
|
|
9724
|
-
|
|
9725
|
-
// src/ui/drop-indicator.tsx
|
|
9726
|
-
import * as React10 from "react";
|
|
9727
|
-
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
9728
|
-
var dropIndicatorVariants = cva(
|
|
9729
|
-
"ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
|
|
9730
|
-
{
|
|
9731
|
-
variants: {
|
|
9732
|
-
direction: {
|
|
9733
|
-
vertical: "h-6 w-[3px]",
|
|
9734
|
-
horizontal: "h-[3px] w-[200px]"
|
|
9735
|
-
},
|
|
9736
|
-
state: {
|
|
9737
|
-
default: "opacity-0",
|
|
9738
|
-
hover: "opacity-100",
|
|
9739
|
-
dragIdle: "opacity-40",
|
|
9740
|
-
dragActive: "opacity-100"
|
|
9741
|
-
}
|
|
9742
|
-
},
|
|
9743
|
-
defaultVariants: {
|
|
9744
|
-
direction: "vertical",
|
|
9745
|
-
state: "default"
|
|
9746
|
-
}
|
|
9747
|
-
}
|
|
9748
|
-
);
|
|
9749
|
-
var DropIndicator = React10.forwardRef(
|
|
9750
|
-
({ className, direction, state, ...props }, ref) => {
|
|
9751
|
-
return /* @__PURE__ */ jsx24(
|
|
9752
|
-
"div",
|
|
9753
|
-
{
|
|
9754
|
-
ref,
|
|
9755
|
-
"data-slot": "drop-indicator",
|
|
9756
|
-
"data-direction": direction ?? "vertical",
|
|
9757
|
-
"data-state": state ?? "default",
|
|
9758
|
-
"aria-hidden": "true",
|
|
9759
|
-
className: cn(dropIndicatorVariants({ direction, state }), className),
|
|
9760
|
-
...props
|
|
9761
|
-
}
|
|
9762
|
-
);
|
|
9763
|
-
}
|
|
9764
|
-
);
|
|
9765
|
-
DropIndicator.displayName = "DropIndicator";
|
|
9766
12028
|
export {
|
|
9767
12029
|
CustomToolbar,
|
|
9768
12030
|
CustomToolbarButton,
|