@ohhwells/bridge 0.1.44 → 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 +2392 -453
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -3
- package/dist/index.d.ts +12 -3
- package/dist/index.js +2429 -490
- package/dist/index.js.map +1 -1
- package/dist/styles.css +116 -17
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -62,7 +62,7 @@ __export(index_exports, {
|
|
|
62
62
|
module.exports = __toCommonJS(index_exports);
|
|
63
63
|
|
|
64
64
|
// src/OhhwellsBridge.tsx
|
|
65
|
-
var
|
|
65
|
+
var import_react9 = __toESM(require("react"), 1);
|
|
66
66
|
var import_client = require("react-dom/client");
|
|
67
67
|
var import_react_dom2 = require("react-dom");
|
|
68
68
|
|
|
@@ -4360,33 +4360,39 @@ function Tooltip({ ...props }) {
|
|
|
4360
4360
|
function TooltipTrigger({ ...props }) {
|
|
4361
4361
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui3.Tooltip.Trigger, { "data-slot": "tooltip-trigger", ...props });
|
|
4362
4362
|
}
|
|
4363
|
+
var arrowClassBySide = {
|
|
4364
|
+
top: "before:bottom-0 before:left-1/2 before:-translate-x-1/2 before:translate-y-1/2",
|
|
4365
|
+
bottom: "before:top-0 before:left-1/2 before:-translate-x-1/2 before:-translate-y-1/2",
|
|
4366
|
+
left: "before:right-0 before:top-1/2 before:-translate-y-1/2 before:translate-x-1/2",
|
|
4367
|
+
right: "before:left-0 before:top-1/2 before:-translate-y-1/2 before:-translate-x-1/2"
|
|
4368
|
+
};
|
|
4363
4369
|
function TooltipContent({
|
|
4364
4370
|
className,
|
|
4365
|
-
sideOffset =
|
|
4371
|
+
sideOffset = 9,
|
|
4366
4372
|
side = "bottom",
|
|
4367
4373
|
children,
|
|
4368
4374
|
hideArrow,
|
|
4369
4375
|
...props
|
|
4370
4376
|
}) {
|
|
4371
|
-
|
|
4377
|
+
const resolvedSide = side ?? "bottom";
|
|
4378
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui3.Tooltip.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
4372
4379
|
import_radix_ui3.Tooltip.Content,
|
|
4373
4380
|
{
|
|
4374
4381
|
"data-slot": "tooltip-content",
|
|
4375
4382
|
side,
|
|
4376
4383
|
sideOffset,
|
|
4377
4384
|
className: cn(
|
|
4378
|
-
"z-[2147483647] inline-flex w-fit max-w-xs items-center rounded-md bg-foreground px-3 py-1.5 text-xs text-background",
|
|
4385
|
+
"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",
|
|
4379
4386
|
"origin-[var(--radix-tooltip-content-transform-origin)] animate-in fade-in-0 zoom-in-95",
|
|
4380
4387
|
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
4381
4388
|
"data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2",
|
|
4382
4389
|
"data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2",
|
|
4390
|
+
!hideArrow && 'before:pointer-events-none before:absolute before:size-2 before:rotate-45 before:bg-foreground before:content-[""]',
|
|
4391
|
+
!hideArrow && arrowClassBySide[resolvedSide],
|
|
4383
4392
|
className
|
|
4384
4393
|
),
|
|
4385
4394
|
...props,
|
|
4386
|
-
children
|
|
4387
|
-
children,
|
|
4388
|
-
!hideArrow && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui3.Tooltip.Arrow, { className: "z-[2147483647] size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground" })
|
|
4389
|
-
]
|
|
4395
|
+
children
|
|
4390
4396
|
}
|
|
4391
4397
|
) });
|
|
4392
4398
|
}
|
|
@@ -4403,7 +4409,7 @@ function ToolbarActionTooltip({
|
|
|
4403
4409
|
const button = /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CustomToolbarButton, { type: "button", "aria-label": label, disabled, ...buttonProps, children });
|
|
4404
4410
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Tooltip, { children: [
|
|
4405
4411
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "inline-flex", children: button }) : button }),
|
|
4406
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TooltipContent, { side, sideOffset:
|
|
4412
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TooltipContent, { side, sideOffset: 9, children: label })
|
|
4407
4413
|
] });
|
|
4408
4414
|
}
|
|
4409
4415
|
function ItemActionToolbar({
|
|
@@ -4485,6 +4491,19 @@ var DRAG_SHADOW = "0px 4px 6px -1px rgba(0, 0, 0, 0.1), 0px 2px 4px -2px rgba(0,
|
|
|
4485
4491
|
var TOOLBAR_EDGE_MARGIN = 4;
|
|
4486
4492
|
var SELECTION_CHROME_GAP = 4;
|
|
4487
4493
|
var TOOLBAR_STROKE_GAP = 4;
|
|
4494
|
+
function getChromeZIndex(state) {
|
|
4495
|
+
switch (state) {
|
|
4496
|
+
case "active-top":
|
|
4497
|
+
case "active-bottom":
|
|
4498
|
+
case "dragging":
|
|
4499
|
+
return 2147483644;
|
|
4500
|
+
case "hover":
|
|
4501
|
+
case "sibling-hint":
|
|
4502
|
+
return 2147483643;
|
|
4503
|
+
default:
|
|
4504
|
+
return 2147483642;
|
|
4505
|
+
}
|
|
4506
|
+
}
|
|
4488
4507
|
function getChromeStyle(state) {
|
|
4489
4508
|
switch (state) {
|
|
4490
4509
|
case "hover":
|
|
@@ -4506,7 +4525,7 @@ function getChromeStyle(state) {
|
|
|
4506
4525
|
case "dragging":
|
|
4507
4526
|
return {
|
|
4508
4527
|
border: `2px solid ${PRIMARY}`,
|
|
4509
|
-
boxShadow: DRAG_SHADOW
|
|
4528
|
+
boxShadow: `${FOCUS_RING}, ${DRAG_SHADOW}`
|
|
4510
4529
|
};
|
|
4511
4530
|
default:
|
|
4512
4531
|
return {};
|
|
@@ -4575,6 +4594,9 @@ function ItemInteractionLayer({
|
|
|
4575
4594
|
dragHandleLabel = "Reorder item",
|
|
4576
4595
|
onDragHandleDragStart,
|
|
4577
4596
|
onDragHandleDragEnd,
|
|
4597
|
+
onItemPointerDown,
|
|
4598
|
+
onItemClick,
|
|
4599
|
+
itemDragSurface = true,
|
|
4578
4600
|
chromeGap = SELECTION_CHROME_GAP,
|
|
4579
4601
|
className
|
|
4580
4602
|
}) {
|
|
@@ -4582,7 +4604,8 @@ function ItemInteractionLayer({
|
|
|
4582
4604
|
const isActive = state === "active-top" || state === "active-bottom";
|
|
4583
4605
|
const isDragging = state === "dragging";
|
|
4584
4606
|
const showToolbar = isActive && toolbar;
|
|
4585
|
-
const showDragHandle = isActive
|
|
4607
|
+
const showDragHandle = (isActive || isDragging) && showHandle;
|
|
4608
|
+
const itemDragEnabled = itemDragSurface && isActive && showHandle && !isDragging && !dragDisabled;
|
|
4586
4609
|
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
4587
4610
|
"div",
|
|
4588
4611
|
{
|
|
@@ -4596,7 +4619,7 @@ function ItemInteractionLayer({
|
|
|
4596
4619
|
left: rect.left - chromeGap,
|
|
4597
4620
|
width: rect.width + chromeGap * 2,
|
|
4598
4621
|
height: rect.height + chromeGap * 2,
|
|
4599
|
-
zIndex:
|
|
4622
|
+
zIndex: getChromeZIndex(state)
|
|
4600
4623
|
},
|
|
4601
4624
|
children: [
|
|
4602
4625
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
@@ -4607,11 +4630,29 @@ function ItemInteractionLayer({
|
|
|
4607
4630
|
style: getChromeStyle(state)
|
|
4608
4631
|
}
|
|
4609
4632
|
),
|
|
4633
|
+
itemDragEnabled && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4634
|
+
"div",
|
|
4635
|
+
{
|
|
4636
|
+
"data-ohw-item-drag-surface": "",
|
|
4637
|
+
className: "pointer-events-auto absolute inset-0 cursor-text rounded-lg",
|
|
4638
|
+
onPointerDown: (e) => {
|
|
4639
|
+
if (e.button !== 0) return;
|
|
4640
|
+
onItemPointerDown?.(e);
|
|
4641
|
+
},
|
|
4642
|
+
onClick: (e) => {
|
|
4643
|
+
e.preventDefault();
|
|
4644
|
+
e.stopPropagation();
|
|
4645
|
+
onItemClick?.(e.clientX, e.clientY);
|
|
4646
|
+
}
|
|
4647
|
+
}
|
|
4648
|
+
),
|
|
4610
4649
|
showDragHandle && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4611
4650
|
"div",
|
|
4612
4651
|
{
|
|
4613
4652
|
"data-ohw-drag-handle-container": "",
|
|
4614
|
-
className: "pointer-events-auto absolute left-0 top-1/2 -translate-x-[calc(100%+7px)] -translate-y-1/2",
|
|
4653
|
+
className: "pointer-events-auto absolute left-0 top-1/2 z-10 -translate-x-[calc(100%+7px)] -translate-y-1/2",
|
|
4654
|
+
style: isDragging ? { opacity: 0 } : void 0,
|
|
4655
|
+
"aria-hidden": isDragging || void 0,
|
|
4615
4656
|
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4616
4657
|
DragHandle,
|
|
4617
4658
|
{
|
|
@@ -4623,7 +4664,17 @@ function ItemInteractionLayer({
|
|
|
4623
4664
|
e.preventDefault();
|
|
4624
4665
|
return;
|
|
4625
4666
|
}
|
|
4626
|
-
|
|
4667
|
+
const blank = document.createElement("canvas");
|
|
4668
|
+
blank.width = 1;
|
|
4669
|
+
blank.height = 1;
|
|
4670
|
+
blank.style.cssText = "position:fixed;left:-9999px;top:-9999px;width:1px;height:1px;pointer-events:none";
|
|
4671
|
+
document.body.appendChild(blank);
|
|
4672
|
+
try {
|
|
4673
|
+
e.dataTransfer.setDragImage(blank, 0, 0);
|
|
4674
|
+
} finally {
|
|
4675
|
+
requestAnimationFrame(() => blank.remove());
|
|
4676
|
+
}
|
|
4677
|
+
e.dataTransfer.setData("text/plain", dragHandleLabel);
|
|
4627
4678
|
e.dataTransfer.effectAllowed = "move";
|
|
4628
4679
|
onDragHandleDragStart?.(e);
|
|
4629
4680
|
},
|
|
@@ -6319,9 +6370,155 @@ function shouldUseDevFixtures() {
|
|
|
6319
6370
|
return new URLSearchParams(q).get("ohw-fixtures") === "1";
|
|
6320
6371
|
}
|
|
6321
6372
|
|
|
6373
|
+
// src/lib/nav-tree.ts
|
|
6374
|
+
var MAX_LEVEL = { nav: 1 };
|
|
6375
|
+
var ROOT = null;
|
|
6376
|
+
function cloneForest(nodes) {
|
|
6377
|
+
return nodes.map((n) => ({ id: n.id, children: cloneForest(n.children) }));
|
|
6378
|
+
}
|
|
6379
|
+
function findNode(nodes, id, parentId = ROOT) {
|
|
6380
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
6381
|
+
const node = nodes[i];
|
|
6382
|
+
if (node.id === id) return { node, parentId, index: i, siblings: nodes };
|
|
6383
|
+
const nested = findNode(node.children, id, node.id);
|
|
6384
|
+
if (nested) return nested;
|
|
6385
|
+
}
|
|
6386
|
+
return null;
|
|
6387
|
+
}
|
|
6388
|
+
function getChildrenOf(nodes, parentId) {
|
|
6389
|
+
if (parentId === ROOT) return nodes;
|
|
6390
|
+
const found = findNode(nodes, parentId);
|
|
6391
|
+
return found ? found.node.children : null;
|
|
6392
|
+
}
|
|
6393
|
+
function isDescendant(nodes, ancestorId, maybeDescendantId) {
|
|
6394
|
+
const found = findNode(nodes, ancestorId);
|
|
6395
|
+
if (!found) return false;
|
|
6396
|
+
return findNode(found.node.children, maybeDescendantId) !== null;
|
|
6397
|
+
}
|
|
6398
|
+
function levelOf(nodes, id) {
|
|
6399
|
+
const loc = findNode(nodes, id);
|
|
6400
|
+
if (!loc) return -1;
|
|
6401
|
+
if (loc.parentId === ROOT) return 0;
|
|
6402
|
+
return 1 + Math.max(0, levelOf(nodes, loc.parentId));
|
|
6403
|
+
}
|
|
6404
|
+
function insertedLevel(nodes, parentId) {
|
|
6405
|
+
if (parentId === ROOT) return 0;
|
|
6406
|
+
const parentLevel = levelOf(nodes, parentId);
|
|
6407
|
+
if (parentLevel < 0) return -1;
|
|
6408
|
+
return parentLevel + 1;
|
|
6409
|
+
}
|
|
6410
|
+
function takeNode(nodes, id) {
|
|
6411
|
+
const forest = cloneForest(nodes);
|
|
6412
|
+
const loc = findNode(forest, id);
|
|
6413
|
+
if (!loc) return null;
|
|
6414
|
+
const [taken] = loc.siblings.splice(loc.index, 1);
|
|
6415
|
+
if (!taken) return null;
|
|
6416
|
+
return { forest, taken };
|
|
6417
|
+
}
|
|
6418
|
+
function insertInto(forest, node, parentId, index) {
|
|
6419
|
+
const siblings = getChildrenOf(forest, parentId);
|
|
6420
|
+
if (!siblings) return false;
|
|
6421
|
+
const clamped = Math.max(0, Math.min(index, siblings.length));
|
|
6422
|
+
siblings.splice(clamped, 0, node);
|
|
6423
|
+
return true;
|
|
6424
|
+
}
|
|
6425
|
+
function normalize(nodes) {
|
|
6426
|
+
const walk = (list) => list.map((n) => {
|
|
6427
|
+
const children = walk(n.children);
|
|
6428
|
+
return { id: n.id, children };
|
|
6429
|
+
});
|
|
6430
|
+
return walk(nodes);
|
|
6431
|
+
}
|
|
6432
|
+
function moveNode(model, draggedId, target) {
|
|
6433
|
+
const { parentId, index: targetIndex } = target;
|
|
6434
|
+
if (parentId === draggedId) return null;
|
|
6435
|
+
if (parentId !== ROOT && isDescendant(model, draggedId, parentId)) return null;
|
|
6436
|
+
const nextLevel = insertedLevel(model, parentId);
|
|
6437
|
+
if (nextLevel < 0 || nextLevel > MAX_LEVEL.nav) return null;
|
|
6438
|
+
const draggedLoc = findNode(model, draggedId);
|
|
6439
|
+
if (!draggedLoc) return null;
|
|
6440
|
+
if (parentId !== ROOT && draggedLoc.node.children.length > 0) return null;
|
|
6441
|
+
const taken = takeNode(model, draggedId);
|
|
6442
|
+
if (!taken) return null;
|
|
6443
|
+
let insertIndex = targetIndex;
|
|
6444
|
+
if (draggedLoc.parentId === parentId && draggedLoc.index < targetIndex) {
|
|
6445
|
+
insertIndex -= 1;
|
|
6446
|
+
}
|
|
6447
|
+
if (!insertInto(taken.forest, taken.taken, parentId, insertIndex)) return null;
|
|
6448
|
+
const next = normalize(taken.forest);
|
|
6449
|
+
if (forestsEqual(model, next)) return null;
|
|
6450
|
+
return next;
|
|
6451
|
+
}
|
|
6452
|
+
function forestsEqual(a, b) {
|
|
6453
|
+
if (a.length !== b.length) return false;
|
|
6454
|
+
for (let i = 0; i < a.length; i++) {
|
|
6455
|
+
const left = a[i];
|
|
6456
|
+
const right = b[i];
|
|
6457
|
+
if (left.id !== right.id) return false;
|
|
6458
|
+
if (!forestsEqual(left.children, right.children)) return false;
|
|
6459
|
+
}
|
|
6460
|
+
return true;
|
|
6461
|
+
}
|
|
6462
|
+
function forestFromFlatOrder(order) {
|
|
6463
|
+
return order.map((id) => ({ id, children: [] }));
|
|
6464
|
+
}
|
|
6465
|
+
function serializeNavOrder(nodes) {
|
|
6466
|
+
const hasNesting = nodes.some((n) => n.children.length > 0);
|
|
6467
|
+
if (!hasNesting) {
|
|
6468
|
+
return JSON.stringify(nodes.map((n) => n.id));
|
|
6469
|
+
}
|
|
6470
|
+
return JSON.stringify(nodes);
|
|
6471
|
+
}
|
|
6472
|
+
function parseNavOrderJson(raw) {
|
|
6473
|
+
if (!raw) return null;
|
|
6474
|
+
try {
|
|
6475
|
+
const parsed = JSON.parse(raw);
|
|
6476
|
+
if (!Array.isArray(parsed)) return null;
|
|
6477
|
+
if (parsed.every((x) => typeof x === "string")) {
|
|
6478
|
+
return forestFromFlatOrder(parsed.filter((x) => typeof x === "string" && x.length > 0));
|
|
6479
|
+
}
|
|
6480
|
+
return parseNavNodeList(parsed);
|
|
6481
|
+
} catch {
|
|
6482
|
+
return null;
|
|
6483
|
+
}
|
|
6484
|
+
}
|
|
6485
|
+
function parseNavNodeList(raw) {
|
|
6486
|
+
const out = [];
|
|
6487
|
+
for (const item of raw) {
|
|
6488
|
+
if (typeof item === "string" && item.length > 0) {
|
|
6489
|
+
out.push({ id: item, children: [] });
|
|
6490
|
+
continue;
|
|
6491
|
+
}
|
|
6492
|
+
if (!item || typeof item !== "object") return null;
|
|
6493
|
+
const rec = item;
|
|
6494
|
+
if (typeof rec.id !== "string" || !rec.id) return null;
|
|
6495
|
+
const children = Array.isArray(rec.children) ? parseNavNodeList(rec.children) : [];
|
|
6496
|
+
if (!children) return null;
|
|
6497
|
+
out.push({ id: rec.id, children });
|
|
6498
|
+
}
|
|
6499
|
+
return out;
|
|
6500
|
+
}
|
|
6501
|
+
function flattenNavOrder(nodes) {
|
|
6502
|
+
const out = [];
|
|
6503
|
+
const walk = (list) => {
|
|
6504
|
+
for (const n of list) {
|
|
6505
|
+
out.push(n.id);
|
|
6506
|
+
walk(n.children);
|
|
6507
|
+
}
|
|
6508
|
+
};
|
|
6509
|
+
walk(nodes);
|
|
6510
|
+
return out;
|
|
6511
|
+
}
|
|
6512
|
+
|
|
6322
6513
|
// src/lib/nav-items.ts
|
|
6323
6514
|
var NAV_COUNT_KEY = "__ohw_nav_count";
|
|
6324
6515
|
var NAV_ORDER_KEY = "__ohw_nav_order";
|
|
6516
|
+
var NAV_HREF_RE = /^nav-(\d+)-href$/;
|
|
6517
|
+
function isNavbarHrefKey(key) {
|
|
6518
|
+
if (!key) return false;
|
|
6519
|
+
if (key === "nav-book-href") return false;
|
|
6520
|
+
return NAV_HREF_RE.test(key);
|
|
6521
|
+
}
|
|
6325
6522
|
function getLinkHref(el) {
|
|
6326
6523
|
const key = el.getAttribute("data-ohw-href-key");
|
|
6327
6524
|
if (key) {
|
|
@@ -6358,7 +6555,7 @@ function listNavbarItems() {
|
|
|
6358
6555
|
}
|
|
6359
6556
|
function parseNavIndexFromKey(key) {
|
|
6360
6557
|
if (!key) return null;
|
|
6361
|
-
const match = key.match(
|
|
6558
|
+
const match = key.match(NAV_HREF_RE);
|
|
6362
6559
|
if (!match) return null;
|
|
6363
6560
|
return parseInt(match[1], 10);
|
|
6364
6561
|
}
|
|
@@ -6381,17 +6578,6 @@ function getNavbarExistingTargets() {
|
|
|
6381
6578
|
function getNavOrderFromDom() {
|
|
6382
6579
|
return listNavbarItems().map((el) => el.getAttribute("data-ohw-href-key")).filter((key) => Boolean(key));
|
|
6383
6580
|
}
|
|
6384
|
-
function parseNavOrder(content) {
|
|
6385
|
-
const raw = content[NAV_ORDER_KEY];
|
|
6386
|
-
if (!raw) return null;
|
|
6387
|
-
try {
|
|
6388
|
-
const parsed = JSON.parse(raw);
|
|
6389
|
-
if (!Array.isArray(parsed)) return null;
|
|
6390
|
-
return parsed.filter((key) => typeof key === "string" && key.length > 0);
|
|
6391
|
-
} catch {
|
|
6392
|
-
return null;
|
|
6393
|
-
}
|
|
6394
|
-
}
|
|
6395
6581
|
function findCounterpartByHrefKey(hrefKey, root) {
|
|
6396
6582
|
return root.querySelector(`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`);
|
|
6397
6583
|
}
|
|
@@ -6455,6 +6641,13 @@ function insertNavbarItemDom(index, href, label, afterAnchor) {
|
|
|
6455
6641
|
}
|
|
6456
6642
|
return primary;
|
|
6457
6643
|
}
|
|
6644
|
+
function navOrderKeysEqual(a, b) {
|
|
6645
|
+
if (a.length !== b.length) return false;
|
|
6646
|
+
for (let i = 0; i < a.length; i++) {
|
|
6647
|
+
if (a[i] !== b[i]) return false;
|
|
6648
|
+
}
|
|
6649
|
+
return true;
|
|
6650
|
+
}
|
|
6458
6651
|
function getNavbarLinkKeysInContainer(container) {
|
|
6459
6652
|
return Array.from(container.querySelectorAll("[data-ohw-href-key]")).filter(isNavbarLinkItem).map((el) => el.getAttribute("data-ohw-href-key")).filter((key) => Boolean(key));
|
|
6460
6653
|
}
|
|
@@ -6463,6 +6656,8 @@ function applyNavOrderToContainer(container, order) {
|
|
|
6463
6656
|
const current = getNavbarLinkKeysInContainer(container);
|
|
6464
6657
|
const extras = current.filter((key) => !desired.includes(key));
|
|
6465
6658
|
const expected = [...desired.filter((key) => current.includes(key)), ...extras];
|
|
6659
|
+
const orderedEls = [];
|
|
6660
|
+
if (navOrderKeysEqual(current, expected)) return;
|
|
6466
6661
|
if (current.length === expected.length && current.every((key, i) => key === expected[i])) {
|
|
6467
6662
|
return;
|
|
6468
6663
|
}
|
|
@@ -6471,13 +6666,18 @@ function applyNavOrderToContainer(container, order) {
|
|
|
6471
6666
|
if (seen.has(hrefKey)) continue;
|
|
6472
6667
|
seen.add(hrefKey);
|
|
6473
6668
|
const el = findCounterpartByHrefKey(hrefKey, container);
|
|
6474
|
-
if (el)
|
|
6669
|
+
if (el && isNavbarLinkItem(el)) orderedEls.push(el);
|
|
6475
6670
|
}
|
|
6476
6671
|
for (const el of container.querySelectorAll("[data-ohw-href-key]")) {
|
|
6477
6672
|
if (!isNavbarLinkItem(el)) continue;
|
|
6478
6673
|
const key = el.getAttribute("data-ohw-href-key");
|
|
6479
6674
|
if (!key || seen.has(key)) continue;
|
|
6480
|
-
|
|
6675
|
+
orderedEls.push(el);
|
|
6676
|
+
}
|
|
6677
|
+
for (const el of orderedEls) {
|
|
6678
|
+
if (container.lastElementChild !== el) {
|
|
6679
|
+
container.appendChild(el);
|
|
6680
|
+
}
|
|
6481
6681
|
}
|
|
6482
6682
|
}
|
|
6483
6683
|
function applyNavOrder(order) {
|
|
@@ -6486,6 +6686,75 @@ function applyNavOrder(order) {
|
|
|
6486
6686
|
const drawer = getNavbarDrawerContainer();
|
|
6487
6687
|
if (drawer) applyNavOrderToContainer(drawer, order);
|
|
6488
6688
|
}
|
|
6689
|
+
function applyChildrenOrder(parentHrefKey, childKeys, root) {
|
|
6690
|
+
const parent = findCounterpartByHrefKey(parentHrefKey, root);
|
|
6691
|
+
if (!parent) return;
|
|
6692
|
+
const group = parent.closest("[data-ohw-nav-group]");
|
|
6693
|
+
const childrenRoot = group?.querySelector(":scope > [data-ohw-nav-children]");
|
|
6694
|
+
if (!childrenRoot) return;
|
|
6695
|
+
const current = Array.from(childrenRoot.querySelectorAll(":scope > [data-ohw-href-key]")).map((el) => el.getAttribute("data-ohw-href-key")).filter((key) => Boolean(key));
|
|
6696
|
+
if (navOrderKeysEqual(current, childKeys)) return;
|
|
6697
|
+
for (const key of childKeys) {
|
|
6698
|
+
const el = findCounterpartByHrefKey(key, root);
|
|
6699
|
+
if (!el) continue;
|
|
6700
|
+
if (childrenRoot.lastElementChild !== el) {
|
|
6701
|
+
childrenRoot.appendChild(el);
|
|
6702
|
+
}
|
|
6703
|
+
}
|
|
6704
|
+
}
|
|
6705
|
+
function applyNavForest(forest) {
|
|
6706
|
+
if (forestsEqual(forest, getNavForestFromDom())) return;
|
|
6707
|
+
const rootKeys = forest.map((n) => n.id);
|
|
6708
|
+
applyNavOrder(rootKeys);
|
|
6709
|
+
const desktop = getNavbarDesktopContainer();
|
|
6710
|
+
const drawer = getNavbarDrawerContainer();
|
|
6711
|
+
for (const node of forest) {
|
|
6712
|
+
if (node.children.length === 0) continue;
|
|
6713
|
+
const childKeys = node.children.map((c) => c.id);
|
|
6714
|
+
if (desktop) applyChildrenOrder(node.id, childKeys, desktop);
|
|
6715
|
+
if (drawer) applyChildrenOrder(node.id, childKeys, drawer);
|
|
6716
|
+
}
|
|
6717
|
+
}
|
|
6718
|
+
function getNavForestFromDom() {
|
|
6719
|
+
const items = listNavbarItems();
|
|
6720
|
+
const nestedChildKeys = /* @__PURE__ */ new Set();
|
|
6721
|
+
const roots = [];
|
|
6722
|
+
for (const item of items) {
|
|
6723
|
+
const key = item.getAttribute("data-ohw-href-key");
|
|
6724
|
+
if (!key || !isNavbarHrefKey(key)) continue;
|
|
6725
|
+
if (item.closest("[data-ohw-nav-children]")) continue;
|
|
6726
|
+
const group = item.closest("[data-ohw-nav-group]");
|
|
6727
|
+
const childrenRoot = group?.querySelector(":scope > [data-ohw-nav-children]");
|
|
6728
|
+
const children = [];
|
|
6729
|
+
if (childrenRoot) {
|
|
6730
|
+
for (const child of childrenRoot.querySelectorAll(":scope > [data-ohw-href-key]")) {
|
|
6731
|
+
if (!isNavbarLinkItem(child)) continue;
|
|
6732
|
+
const childKey = child.getAttribute("data-ohw-href-key");
|
|
6733
|
+
if (!childKey || !isNavbarHrefKey(childKey)) continue;
|
|
6734
|
+
nestedChildKeys.add(childKey);
|
|
6735
|
+
children.push({ id: childKey, children: [] });
|
|
6736
|
+
}
|
|
6737
|
+
}
|
|
6738
|
+
roots.push({ id: key, children });
|
|
6739
|
+
}
|
|
6740
|
+
if (roots.length === 0) {
|
|
6741
|
+
return forestFromFlatOrder(
|
|
6742
|
+
getNavOrderFromDom().filter((k) => isNavbarHrefKey(k) && !nestedChildKeys.has(k))
|
|
6743
|
+
);
|
|
6744
|
+
}
|
|
6745
|
+
return roots;
|
|
6746
|
+
}
|
|
6747
|
+
function planNavItemMove(hrefKey, parentId, insertIndex) {
|
|
6748
|
+
const model = getNavForestFromDom();
|
|
6749
|
+
const next = moveNode(model, hrefKey, { parentId, index: insertIndex });
|
|
6750
|
+
if (!next) return null;
|
|
6751
|
+
if (forestsEqual(model, next)) return null;
|
|
6752
|
+
return {
|
|
6753
|
+
forest: next,
|
|
6754
|
+
orderJson: serializeNavOrder(next),
|
|
6755
|
+
flatOrder: flattenNavOrder(next)
|
|
6756
|
+
};
|
|
6757
|
+
}
|
|
6489
6758
|
function collectNavbarIndicesFromContent(content) {
|
|
6490
6759
|
const indices = /* @__PURE__ */ new Set();
|
|
6491
6760
|
for (const key of Object.keys(content)) {
|
|
@@ -6513,8 +6782,10 @@ function reconcileNavbarItemsFromContent(content) {
|
|
|
6513
6782
|
if (!href && !label) continue;
|
|
6514
6783
|
insertNavbarItemDom(index, href ?? "/", label ?? "Untitled", null);
|
|
6515
6784
|
}
|
|
6516
|
-
const
|
|
6517
|
-
if (
|
|
6785
|
+
const orderForest = parseNavOrderJson(content[NAV_ORDER_KEY]);
|
|
6786
|
+
if (orderForest?.length) {
|
|
6787
|
+
applyNavForest(orderForest);
|
|
6788
|
+
}
|
|
6518
6789
|
}
|
|
6519
6790
|
function buildNavOrderAfterInsert(afterAnchor, newHrefKey) {
|
|
6520
6791
|
const order = getNavOrderFromDom();
|
|
@@ -6554,160 +6825,1050 @@ function insertNavbarItem(href, label, afterAnchor = null) {
|
|
|
6554
6825
|
};
|
|
6555
6826
|
}
|
|
6556
6827
|
|
|
6557
|
-
// src/
|
|
6558
|
-
var
|
|
6559
|
-
var
|
|
6560
|
-
function
|
|
6561
|
-
|
|
6562
|
-
|
|
6563
|
-
|
|
6564
|
-
|
|
6565
|
-
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6566
|
-
"div",
|
|
6567
|
-
{
|
|
6568
|
-
"data-ohw-navbar-container-chrome": "",
|
|
6569
|
-
"data-ohw-bridge": "",
|
|
6570
|
-
className: "pointer-events-none fixed z-[2147483647]",
|
|
6571
|
-
style: {
|
|
6572
|
-
top: rect.top - chromeGap,
|
|
6573
|
-
left: rect.left - chromeGap,
|
|
6574
|
-
width: rect.width + chromeGap * 2,
|
|
6575
|
-
height: rect.height + chromeGap * 2
|
|
6576
|
-
},
|
|
6577
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6578
|
-
"button",
|
|
6579
|
-
{
|
|
6580
|
-
type: "button",
|
|
6581
|
-
"data-ohw-navbar-add-button": "",
|
|
6582
|
-
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",
|
|
6583
|
-
style: { top: "70%" },
|
|
6584
|
-
"aria-label": "Add item",
|
|
6585
|
-
onMouseDown: (e) => {
|
|
6586
|
-
e.preventDefault();
|
|
6587
|
-
e.stopPropagation();
|
|
6588
|
-
},
|
|
6589
|
-
onClick: (e) => {
|
|
6590
|
-
e.preventDefault();
|
|
6591
|
-
e.stopPropagation();
|
|
6592
|
-
onAdd();
|
|
6593
|
-
},
|
|
6594
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
6595
|
-
}
|
|
6596
|
-
)
|
|
6597
|
-
}
|
|
6598
|
-
);
|
|
6828
|
+
// src/lib/footer-items.ts
|
|
6829
|
+
var FOOTER_ORDER_KEY = "__ohw_footer_order";
|
|
6830
|
+
var FOOTER_HREF_RE = /^footer-(\d+)-(\d+)-href$/;
|
|
6831
|
+
function parseFooterHrefKey(key) {
|
|
6832
|
+
if (!key) return null;
|
|
6833
|
+
const match = key.match(FOOTER_HREF_RE);
|
|
6834
|
+
if (!match) return null;
|
|
6835
|
+
return { col: parseInt(match[1], 10), item: parseInt(match[2], 10) };
|
|
6599
6836
|
}
|
|
6600
|
-
|
|
6601
|
-
|
|
6602
|
-
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
6603
|
-
var badgeVariants = cva(
|
|
6604
|
-
"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",
|
|
6605
|
-
{
|
|
6606
|
-
variants: {
|
|
6607
|
-
variant: {
|
|
6608
|
-
default: "border-transparent bg-primary text-primary-foreground",
|
|
6609
|
-
secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
6610
|
-
destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
|
|
6611
|
-
outline: "text-foreground"
|
|
6612
|
-
}
|
|
6613
|
-
},
|
|
6614
|
-
defaultVariants: {
|
|
6615
|
-
variant: "default"
|
|
6616
|
-
}
|
|
6617
|
-
}
|
|
6618
|
-
);
|
|
6619
|
-
function Badge({ className, variant, ...props }) {
|
|
6620
|
-
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
6837
|
+
function isFooterHrefKey(key) {
|
|
6838
|
+
return parseFooterHrefKey(key) !== null;
|
|
6621
6839
|
}
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
var import_lucide_react11 = require("lucide-react");
|
|
6625
|
-
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
6626
|
-
var PRIMARY2 = "#0885FE";
|
|
6627
|
-
var IMAGE_FADE_MS = 300;
|
|
6628
|
-
function runOpacityFade(el, onDone) {
|
|
6629
|
-
const anim = el.animate([{ opacity: 0 }, { opacity: 1 }], {
|
|
6630
|
-
duration: IMAGE_FADE_MS,
|
|
6631
|
-
easing: "ease",
|
|
6632
|
-
fill: "forwards"
|
|
6633
|
-
});
|
|
6634
|
-
let finished = false;
|
|
6635
|
-
const finish = () => {
|
|
6636
|
-
if (finished) return;
|
|
6637
|
-
finished = true;
|
|
6638
|
-
anim.cancel();
|
|
6639
|
-
el.style.opacity = "";
|
|
6640
|
-
onDone();
|
|
6641
|
-
};
|
|
6642
|
-
anim.finished.then(finish).catch(finish);
|
|
6643
|
-
window.setTimeout(finish, IMAGE_FADE_MS + 100);
|
|
6840
|
+
function getFooterRoot() {
|
|
6841
|
+
return document.querySelector('footer[data-ohw-section="footer"], footer');
|
|
6644
6842
|
}
|
|
6645
|
-
function
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
|
|
6843
|
+
function getFooterLinksContainer() {
|
|
6844
|
+
return document.querySelector("[data-ohw-footer-links]") ?? document.querySelector(".rb-footer-links");
|
|
6845
|
+
}
|
|
6846
|
+
function isFooterLinkAnchor(el) {
|
|
6847
|
+
if (!el.matches("[data-ohw-href-key]")) return false;
|
|
6848
|
+
if (!isFooterHrefKey(el.getAttribute("data-ohw-href-key"))) return false;
|
|
6849
|
+
return Boolean(el.querySelector('[data-ohw-editable="text"]'));
|
|
6850
|
+
}
|
|
6851
|
+
function listFooterColumns() {
|
|
6852
|
+
const root = getFooterLinksContainer() ?? getFooterRoot()?.querySelector(".rb-footer-links") ?? null;
|
|
6853
|
+
if (!root) return [];
|
|
6854
|
+
const explicit = Array.from(root.querySelectorAll(":scope > [data-ohw-footer-col]"));
|
|
6855
|
+
if (explicit.length > 0) return explicit;
|
|
6856
|
+
return Array.from(root.children).filter((el) => {
|
|
6857
|
+
if (!(el instanceof HTMLElement)) return false;
|
|
6858
|
+
return Array.from(el.querySelectorAll(":scope > [data-ohw-href-key]")).some(
|
|
6859
|
+
isFooterLinkAnchor
|
|
6860
|
+
);
|
|
6650
6861
|
});
|
|
6651
6862
|
}
|
|
6652
|
-
function
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6863
|
+
function listFooterLinksInColumn(column) {
|
|
6864
|
+
return Array.from(column.querySelectorAll(":scope > [data-ohw-href-key]")).filter(
|
|
6865
|
+
isFooterLinkAnchor
|
|
6866
|
+
);
|
|
6656
6867
|
}
|
|
6657
|
-
function
|
|
6658
|
-
const
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
|
|
6667
|
-
|
|
6668
|
-
|
|
6669
|
-
|
|
6670
|
-
|
|
6671
|
-
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
|
|
6677
|
-
layer.remove();
|
|
6678
|
-
if (!prevPos || prevPos === "static") el.style.position = prevPos;
|
|
6868
|
+
function findFooterColumnForLink(anchor) {
|
|
6869
|
+
const columns = listFooterColumns();
|
|
6870
|
+
return columns.find((col) => col.contains(anchor)) ?? null;
|
|
6871
|
+
}
|
|
6872
|
+
function getFooterOrderFromDom() {
|
|
6873
|
+
return listFooterColumns().map(
|
|
6874
|
+
(col) => listFooterLinksInColumn(col).map((el) => el.getAttribute("data-ohw-href-key")).filter((key) => Boolean(key))
|
|
6875
|
+
);
|
|
6876
|
+
}
|
|
6877
|
+
function findFooterLinkByKey(hrefKey) {
|
|
6878
|
+
return document.querySelector(
|
|
6879
|
+
`footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
6880
|
+
);
|
|
6881
|
+
}
|
|
6882
|
+
function syncFooterColumnIndices(columns) {
|
|
6883
|
+
columns.forEach((col, index) => {
|
|
6884
|
+
const next = String(index);
|
|
6885
|
+
if (col.getAttribute("data-ohw-footer-col") !== next) {
|
|
6886
|
+
col.setAttribute("data-ohw-footer-col", next);
|
|
6887
|
+
}
|
|
6679
6888
|
});
|
|
6680
6889
|
}
|
|
6681
|
-
function
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
el = document.createElement("div");
|
|
6685
|
-
el.setAttribute("data-ohw-sections-tracker", "");
|
|
6686
|
-
el.style.display = "none";
|
|
6687
|
-
document.body.appendChild(el);
|
|
6890
|
+
function appendChildIfNeeded(parent, child) {
|
|
6891
|
+
if (parent.lastElementChild !== child) {
|
|
6892
|
+
parent.appendChild(child);
|
|
6688
6893
|
}
|
|
6689
|
-
return el;
|
|
6690
6894
|
}
|
|
6691
|
-
function
|
|
6692
|
-
const
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6895
|
+
function applyFooterOrder(order) {
|
|
6896
|
+
const container = getFooterLinksContainer();
|
|
6897
|
+
if (!container) return;
|
|
6898
|
+
const columns = listFooterColumns();
|
|
6899
|
+
if (columns.length === 0) return;
|
|
6900
|
+
const currentOrder = getFooterOrderFromDom();
|
|
6901
|
+
if (ordersEqual(order, currentOrder)) {
|
|
6902
|
+
syncFooterColumnIndices(columns);
|
|
6903
|
+
return;
|
|
6904
|
+
}
|
|
6905
|
+
const used = /* @__PURE__ */ new Set();
|
|
6906
|
+
const orderedCols = [];
|
|
6907
|
+
for (const colOrder of order) {
|
|
6908
|
+
let matched = null;
|
|
6909
|
+
for (const hrefKey of colOrder) {
|
|
6910
|
+
const link = findFooterLinkByKey(hrefKey);
|
|
6911
|
+
if (!link) continue;
|
|
6912
|
+
const owner = findFooterColumnForLink(link);
|
|
6913
|
+
if (owner && !used.has(owner)) {
|
|
6914
|
+
matched = owner;
|
|
6915
|
+
break;
|
|
6916
|
+
}
|
|
6917
|
+
}
|
|
6918
|
+
if (!matched) {
|
|
6919
|
+
matched = columns.find((col) => !used.has(col)) ?? null;
|
|
6920
|
+
}
|
|
6921
|
+
if (matched) {
|
|
6922
|
+
used.add(matched);
|
|
6923
|
+
orderedCols.push(matched);
|
|
6924
|
+
}
|
|
6925
|
+
}
|
|
6926
|
+
for (const col of columns) {
|
|
6927
|
+
if (!used.has(col)) orderedCols.push(col);
|
|
6928
|
+
}
|
|
6929
|
+
for (const col of orderedCols) {
|
|
6930
|
+
appendChildIfNeeded(container, col);
|
|
6931
|
+
}
|
|
6932
|
+
const freshColumns = listFooterColumns();
|
|
6933
|
+
syncFooterColumnIndices(freshColumns);
|
|
6934
|
+
for (let c = 0; c < order.length; c++) {
|
|
6935
|
+
const col = freshColumns[c];
|
|
6936
|
+
if (!col) continue;
|
|
6937
|
+
const colOrder = order[c];
|
|
6938
|
+
for (const hrefKey of colOrder) {
|
|
6939
|
+
const el = findFooterLinkByKey(hrefKey);
|
|
6940
|
+
if (!el) continue;
|
|
6941
|
+
if (el.parentElement !== col || col.lastElementChild !== el) {
|
|
6942
|
+
col.appendChild(el);
|
|
6943
|
+
}
|
|
6944
|
+
}
|
|
6697
6945
|
}
|
|
6698
|
-
const currentPath = window.location.pathname;
|
|
6699
|
-
const updated = sections.map((s) => {
|
|
6700
|
-
if (s.type !== "scheduling" || s.insertAfter !== insertAfter) return s;
|
|
6701
|
-
if (s.pagePath && s.pagePath !== currentPath) return s;
|
|
6702
|
-
return { ...s, scheduleId };
|
|
6703
|
-
});
|
|
6704
|
-
tracker.textContent = JSON.stringify(updated);
|
|
6705
|
-
return tracker.textContent ?? "[]";
|
|
6706
6946
|
}
|
|
6707
|
-
function
|
|
6708
|
-
return
|
|
6947
|
+
function ordersEqual(a, b) {
|
|
6948
|
+
if (a.length !== b.length) return false;
|
|
6949
|
+
for (let i = 0; i < a.length; i++) {
|
|
6950
|
+
const left = a[i];
|
|
6951
|
+
const right = b[i];
|
|
6952
|
+
if (left.length !== right.length) return false;
|
|
6953
|
+
for (let j = 0; j < left.length; j++) {
|
|
6954
|
+
if (left[j] !== right[j]) return false;
|
|
6955
|
+
}
|
|
6956
|
+
}
|
|
6957
|
+
return true;
|
|
6709
6958
|
}
|
|
6710
|
-
|
|
6959
|
+
function planFooterLinkMove(hrefKey, targetColIndex, insertIndex) {
|
|
6960
|
+
const order = getFooterOrderFromDom();
|
|
6961
|
+
if (targetColIndex < 0 || targetColIndex >= order.length) return null;
|
|
6962
|
+
let fromCol = -1;
|
|
6963
|
+
let fromIdx = -1;
|
|
6964
|
+
for (let c = 0; c < order.length; c++) {
|
|
6965
|
+
const idx = order[c].indexOf(hrefKey);
|
|
6966
|
+
if (idx >= 0) {
|
|
6967
|
+
fromCol = c;
|
|
6968
|
+
fromIdx = idx;
|
|
6969
|
+
break;
|
|
6970
|
+
}
|
|
6971
|
+
}
|
|
6972
|
+
if (fromCol < 0) return null;
|
|
6973
|
+
const next = order.map((col) => [...col]);
|
|
6974
|
+
next[fromCol].splice(fromIdx, 1);
|
|
6975
|
+
let adjusted = insertIndex;
|
|
6976
|
+
if (fromCol === targetColIndex && fromIdx < insertIndex) adjusted -= 1;
|
|
6977
|
+
adjusted = Math.max(0, Math.min(adjusted, next[targetColIndex].length));
|
|
6978
|
+
next[targetColIndex].splice(adjusted, 0, hrefKey);
|
|
6979
|
+
if (ordersEqual(next, order)) return null;
|
|
6980
|
+
return next;
|
|
6981
|
+
}
|
|
6982
|
+
function planFooterColumnMove(fromIndex, toIndex) {
|
|
6983
|
+
const order = getFooterOrderFromDom();
|
|
6984
|
+
const columns = listFooterColumns();
|
|
6985
|
+
if (fromIndex < 0 || fromIndex >= columns.length || toIndex < 0 || toIndex > columns.length) {
|
|
6986
|
+
return null;
|
|
6987
|
+
}
|
|
6988
|
+
if (toIndex === fromIndex || toIndex === fromIndex + 1) return null;
|
|
6989
|
+
const nextOrder = order.map((col) => [...col]);
|
|
6990
|
+
const [movedOrder] = nextOrder.splice(fromIndex, 1);
|
|
6991
|
+
if (!movedOrder) return null;
|
|
6992
|
+
let adjusted = toIndex;
|
|
6993
|
+
if (fromIndex < toIndex) adjusted -= 1;
|
|
6994
|
+
adjusted = Math.max(0, Math.min(adjusted, nextOrder.length));
|
|
6995
|
+
nextOrder.splice(adjusted, 0, movedOrder);
|
|
6996
|
+
if (ordersEqual(nextOrder, order)) return null;
|
|
6997
|
+
return nextOrder;
|
|
6998
|
+
}
|
|
6999
|
+
function parseFooterOrder(content) {
|
|
7000
|
+
const raw = content[FOOTER_ORDER_KEY];
|
|
7001
|
+
if (!raw) return null;
|
|
7002
|
+
try {
|
|
7003
|
+
const parsed = JSON.parse(raw);
|
|
7004
|
+
if (!Array.isArray(parsed)) return null;
|
|
7005
|
+
return parsed.filter((col) => Array.isArray(col)).map((col) => col.filter((key) => typeof key === "string" && key.length > 0));
|
|
7006
|
+
} catch {
|
|
7007
|
+
return null;
|
|
7008
|
+
}
|
|
7009
|
+
}
|
|
7010
|
+
function reconcileFooterOrderFromContent(content) {
|
|
7011
|
+
const order = parseFooterOrder(content);
|
|
7012
|
+
if (!order?.length) return;
|
|
7013
|
+
const current = getFooterOrderFromDom();
|
|
7014
|
+
if (ordersEqual(order, current)) {
|
|
7015
|
+
syncFooterColumnIndices(listFooterColumns());
|
|
7016
|
+
return;
|
|
7017
|
+
}
|
|
7018
|
+
applyFooterOrder(order);
|
|
7019
|
+
}
|
|
7020
|
+
function buildLinkDropSlots(column, columnIndex) {
|
|
7021
|
+
const links = listFooterLinksInColumn(column);
|
|
7022
|
+
const colRect = column.getBoundingClientRect();
|
|
7023
|
+
const slots = [];
|
|
7024
|
+
const barThickness = 3;
|
|
7025
|
+
if (links.length === 0) {
|
|
7026
|
+
slots.push({
|
|
7027
|
+
insertIndex: 0,
|
|
7028
|
+
columnIndex,
|
|
7029
|
+
left: colRect.left,
|
|
7030
|
+
top: colRect.top + colRect.height / 2 - barThickness / 2,
|
|
7031
|
+
width: colRect.width,
|
|
7032
|
+
height: barThickness,
|
|
7033
|
+
direction: "horizontal"
|
|
7034
|
+
});
|
|
7035
|
+
return slots;
|
|
7036
|
+
}
|
|
7037
|
+
for (let i = 0; i <= links.length; i++) {
|
|
7038
|
+
let top;
|
|
7039
|
+
if (i === 0) {
|
|
7040
|
+
top = links[0].getBoundingClientRect().top - barThickness / 2;
|
|
7041
|
+
} else if (i === links.length) {
|
|
7042
|
+
const last = links[links.length - 1].getBoundingClientRect();
|
|
7043
|
+
top = last.bottom - barThickness / 2;
|
|
7044
|
+
} else {
|
|
7045
|
+
const prev = links[i - 1].getBoundingClientRect();
|
|
7046
|
+
const next = links[i].getBoundingClientRect();
|
|
7047
|
+
top = (prev.bottom + next.top) / 2 - barThickness / 2;
|
|
7048
|
+
}
|
|
7049
|
+
const widthRef = i === 0 ? links[0].getBoundingClientRect() : i === links.length ? links[links.length - 1].getBoundingClientRect() : links[i].getBoundingClientRect();
|
|
7050
|
+
slots.push({
|
|
7051
|
+
insertIndex: i,
|
|
7052
|
+
columnIndex,
|
|
7053
|
+
left: widthRef.left,
|
|
7054
|
+
top,
|
|
7055
|
+
width: Math.max(widthRef.width, colRect.width * 0.8),
|
|
7056
|
+
height: barThickness,
|
|
7057
|
+
direction: "horizontal"
|
|
7058
|
+
});
|
|
7059
|
+
}
|
|
7060
|
+
return slots;
|
|
7061
|
+
}
|
|
7062
|
+
function buildColumnDropSlots() {
|
|
7063
|
+
const columns = listFooterColumns();
|
|
7064
|
+
const slots = [];
|
|
7065
|
+
const barThickness = 3;
|
|
7066
|
+
if (columns.length === 0) return slots;
|
|
7067
|
+
for (let i = 0; i <= columns.length; i++) {
|
|
7068
|
+
let left;
|
|
7069
|
+
let height;
|
|
7070
|
+
let top;
|
|
7071
|
+
if (i === 0) {
|
|
7072
|
+
const first = columns[0].getBoundingClientRect();
|
|
7073
|
+
left = first.left - barThickness / 2;
|
|
7074
|
+
top = first.top;
|
|
7075
|
+
height = first.height;
|
|
7076
|
+
} else if (i === columns.length) {
|
|
7077
|
+
const last = columns[columns.length - 1].getBoundingClientRect();
|
|
7078
|
+
left = last.right - barThickness / 2;
|
|
7079
|
+
top = last.top;
|
|
7080
|
+
height = last.height;
|
|
7081
|
+
} else {
|
|
7082
|
+
const prev = columns[i - 1].getBoundingClientRect();
|
|
7083
|
+
const next = columns[i].getBoundingClientRect();
|
|
7084
|
+
left = (prev.right + next.left) / 2 - barThickness / 2;
|
|
7085
|
+
top = Math.min(prev.top, next.top);
|
|
7086
|
+
height = Math.max(prev.bottom, next.bottom) - top;
|
|
7087
|
+
}
|
|
7088
|
+
slots.push({
|
|
7089
|
+
insertIndex: i,
|
|
7090
|
+
columnIndex: i,
|
|
7091
|
+
left,
|
|
7092
|
+
top,
|
|
7093
|
+
width: barThickness,
|
|
7094
|
+
height: Math.max(height, 24),
|
|
7095
|
+
direction: "vertical"
|
|
7096
|
+
});
|
|
7097
|
+
}
|
|
7098
|
+
return slots;
|
|
7099
|
+
}
|
|
7100
|
+
function hitTestLinkDropSlot(clientX, clientY, draggedHrefKey) {
|
|
7101
|
+
const columns = listFooterColumns();
|
|
7102
|
+
let best = null;
|
|
7103
|
+
for (let c = 0; c < columns.length; c++) {
|
|
7104
|
+
const col = columns[c];
|
|
7105
|
+
const colRect = col.getBoundingClientRect();
|
|
7106
|
+
const inColX = clientX >= colRect.left - 24 && clientX <= colRect.right + 24;
|
|
7107
|
+
if (!inColX) continue;
|
|
7108
|
+
const slots = buildLinkDropSlots(col, c).filter((slot) => {
|
|
7109
|
+
const links = listFooterLinksInColumn(col);
|
|
7110
|
+
const fromIdx = links.findIndex(
|
|
7111
|
+
(el) => el.getAttribute("data-ohw-href-key") === draggedHrefKey
|
|
7112
|
+
);
|
|
7113
|
+
if (fromIdx < 0) return true;
|
|
7114
|
+
if (c === findColumnIndexForKey(draggedHrefKey) && (slot.insertIndex === fromIdx || slot.insertIndex === fromIdx + 1)) {
|
|
7115
|
+
return true;
|
|
7116
|
+
}
|
|
7117
|
+
return true;
|
|
7118
|
+
});
|
|
7119
|
+
for (const slot of slots) {
|
|
7120
|
+
const cy = slot.top + slot.height / 2;
|
|
7121
|
+
const dist = Math.abs(clientY - cy) + (inColX ? 0 : 1e3);
|
|
7122
|
+
if (!best || dist < best.dist) best = { slot, dist };
|
|
7123
|
+
}
|
|
7124
|
+
}
|
|
7125
|
+
return best?.slot ?? null;
|
|
7126
|
+
}
|
|
7127
|
+
function findColumnIndexForKey(hrefKey) {
|
|
7128
|
+
const order = getFooterOrderFromDom();
|
|
7129
|
+
for (let c = 0; c < order.length; c++) {
|
|
7130
|
+
if (order[c].includes(hrefKey)) return c;
|
|
7131
|
+
}
|
|
7132
|
+
return -1;
|
|
7133
|
+
}
|
|
7134
|
+
function hitTestColumnDropSlot(clientX, _clientY) {
|
|
7135
|
+
const slots = buildColumnDropSlots();
|
|
7136
|
+
let best = null;
|
|
7137
|
+
for (const slot of slots) {
|
|
7138
|
+
const cx2 = slot.left + slot.width / 2;
|
|
7139
|
+
const dist = Math.abs(clientX - cx2);
|
|
7140
|
+
if (!best || dist < best.dist) best = { slot, dist };
|
|
7141
|
+
}
|
|
7142
|
+
return best?.slot ?? null;
|
|
7143
|
+
}
|
|
7144
|
+
|
|
7145
|
+
// src/lib/item-drag-interaction.ts
|
|
7146
|
+
function disableNativeHrefDrag(el) {
|
|
7147
|
+
if (el.draggable) el.draggable = false;
|
|
7148
|
+
if (el.getAttribute("draggable") !== "false") {
|
|
7149
|
+
el.setAttribute("draggable", "false");
|
|
7150
|
+
}
|
|
7151
|
+
}
|
|
7152
|
+
function clearTextSelection() {
|
|
7153
|
+
const sel = window.getSelection();
|
|
7154
|
+
if (sel && !sel.isCollapsed) sel.removeAllRanges();
|
|
7155
|
+
}
|
|
7156
|
+
function armItemPressDrag() {
|
|
7157
|
+
document.documentElement.setAttribute("data-ohw-footer-press-drag", "");
|
|
7158
|
+
}
|
|
7159
|
+
function lockItemDuringDrag() {
|
|
7160
|
+
document.documentElement.removeAttribute("data-ohw-footer-press-drag");
|
|
7161
|
+
document.documentElement.setAttribute("data-ohw-item-dragging", "");
|
|
7162
|
+
clearTextSelection();
|
|
7163
|
+
}
|
|
7164
|
+
function unlockItemDragInteraction() {
|
|
7165
|
+
document.documentElement.removeAttribute("data-ohw-footer-press-drag");
|
|
7166
|
+
document.documentElement.removeAttribute("data-ohw-item-dragging");
|
|
7167
|
+
clearTextSelection();
|
|
7168
|
+
}
|
|
7169
|
+
var armFooterPressDrag = armItemPressDrag;
|
|
7170
|
+
var lockFooterDuringDrag = lockItemDuringDrag;
|
|
7171
|
+
var unlockFooterDragInteraction = unlockItemDragInteraction;
|
|
7172
|
+
|
|
7173
|
+
// src/lib/nav-dnd.ts
|
|
7174
|
+
function listReorderableNavItems() {
|
|
7175
|
+
return listNavbarItems().filter((el) => {
|
|
7176
|
+
const key = el.getAttribute("data-ohw-href-key");
|
|
7177
|
+
return isNavbarHrefKey(key) && !el.closest("[data-ohw-nav-children]");
|
|
7178
|
+
});
|
|
7179
|
+
}
|
|
7180
|
+
function listNavChildren(parentHrefKey) {
|
|
7181
|
+
const items = listNavbarItems();
|
|
7182
|
+
const parent = items.find((el) => el.getAttribute("data-ohw-href-key") === parentHrefKey);
|
|
7183
|
+
if (!parent) return [];
|
|
7184
|
+
const group = parent.closest("[data-ohw-nav-group]");
|
|
7185
|
+
const childrenRoot = group?.querySelector(":scope > [data-ohw-nav-children]");
|
|
7186
|
+
if (!childrenRoot) return [];
|
|
7187
|
+
return Array.from(childrenRoot.querySelectorAll(":scope > [data-ohw-href-key]")).filter(
|
|
7188
|
+
(el) => isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))
|
|
7189
|
+
);
|
|
7190
|
+
}
|
|
7191
|
+
function activeNavListContainer() {
|
|
7192
|
+
const desktop = getNavbarDesktopContainer();
|
|
7193
|
+
if (desktop && desktop.getClientRects().length > 0) {
|
|
7194
|
+
const style = window.getComputedStyle(desktop);
|
|
7195
|
+
if (style.display !== "none" && style.visibility !== "hidden") return desktop;
|
|
7196
|
+
}
|
|
7197
|
+
return getNavbarDrawerContainer();
|
|
7198
|
+
}
|
|
7199
|
+
function buildRootNavDropSlots() {
|
|
7200
|
+
const items = listReorderableNavItems();
|
|
7201
|
+
const slots = [];
|
|
7202
|
+
const barThickness = 3;
|
|
7203
|
+
if (items.length === 0) {
|
|
7204
|
+
const container = activeNavListContainer();
|
|
7205
|
+
if (!container) return slots;
|
|
7206
|
+
const rect = container.getBoundingClientRect();
|
|
7207
|
+
slots.push({
|
|
7208
|
+
insertIndex: 0,
|
|
7209
|
+
parentId: null,
|
|
7210
|
+
left: rect.left + rect.width / 2 - barThickness / 2,
|
|
7211
|
+
top: rect.top,
|
|
7212
|
+
width: barThickness,
|
|
7213
|
+
height: Math.max(rect.height, 24),
|
|
7214
|
+
direction: "vertical"
|
|
7215
|
+
});
|
|
7216
|
+
return slots;
|
|
7217
|
+
}
|
|
7218
|
+
const edgeGap = (() => {
|
|
7219
|
+
if (items.length < 2) return 32;
|
|
7220
|
+
const a = items[0].getBoundingClientRect();
|
|
7221
|
+
const b = items[1].getBoundingClientRect();
|
|
7222
|
+
return Math.max(0, b.left - a.right);
|
|
7223
|
+
})();
|
|
7224
|
+
for (let i = 0; i <= items.length; i++) {
|
|
7225
|
+
let left;
|
|
7226
|
+
let top;
|
|
7227
|
+
let height;
|
|
7228
|
+
if (i === 0) {
|
|
7229
|
+
const first = items[0].getBoundingClientRect();
|
|
7230
|
+
left = first.left - edgeGap / 2 - barThickness / 2;
|
|
7231
|
+
top = first.top;
|
|
7232
|
+
height = first.height;
|
|
7233
|
+
} else if (i === items.length) {
|
|
7234
|
+
const last = items[items.length - 1].getBoundingClientRect();
|
|
7235
|
+
const lastGap = items.length >= 2 ? Math.max(
|
|
7236
|
+
0,
|
|
7237
|
+
last.left - items[items.length - 2].getBoundingClientRect().right
|
|
7238
|
+
) : edgeGap;
|
|
7239
|
+
left = last.right + lastGap / 2 - barThickness / 2;
|
|
7240
|
+
top = last.top;
|
|
7241
|
+
height = last.height;
|
|
7242
|
+
} else {
|
|
7243
|
+
const prev = items[i - 1].getBoundingClientRect();
|
|
7244
|
+
const next = items[i].getBoundingClientRect();
|
|
7245
|
+
left = (prev.right + next.left) / 2 - barThickness / 2;
|
|
7246
|
+
top = Math.min(prev.top, next.top);
|
|
7247
|
+
height = Math.max(prev.bottom, next.bottom) - top;
|
|
7248
|
+
}
|
|
7249
|
+
slots.push({
|
|
7250
|
+
insertIndex: i,
|
|
7251
|
+
parentId: null,
|
|
7252
|
+
left,
|
|
7253
|
+
top,
|
|
7254
|
+
width: barThickness,
|
|
7255
|
+
height: Math.max(height, 24),
|
|
7256
|
+
direction: "vertical"
|
|
7257
|
+
});
|
|
7258
|
+
}
|
|
7259
|
+
return slots;
|
|
7260
|
+
}
|
|
7261
|
+
function buildChildNavDropSlots(parentHrefKey) {
|
|
7262
|
+
const children = listNavChildren(parentHrefKey);
|
|
7263
|
+
const slots = [];
|
|
7264
|
+
const barThickness = 3;
|
|
7265
|
+
if (children.length === 0) return slots;
|
|
7266
|
+
const edgeGap = (() => {
|
|
7267
|
+
if (children.length < 2) return 16;
|
|
7268
|
+
const a = children[0].getBoundingClientRect();
|
|
7269
|
+
const b = children[1].getBoundingClientRect();
|
|
7270
|
+
return Math.max(0, b.top - a.bottom);
|
|
7271
|
+
})();
|
|
7272
|
+
for (let i = 0; i <= children.length; i++) {
|
|
7273
|
+
let top;
|
|
7274
|
+
let width;
|
|
7275
|
+
let left;
|
|
7276
|
+
if (i === 0) {
|
|
7277
|
+
const first = children[0].getBoundingClientRect();
|
|
7278
|
+
top = first.top - edgeGap / 2 - barThickness / 2;
|
|
7279
|
+
left = first.left;
|
|
7280
|
+
width = first.width;
|
|
7281
|
+
} else if (i === children.length) {
|
|
7282
|
+
const last = children[children.length - 1].getBoundingClientRect();
|
|
7283
|
+
const lastGap = children.length >= 2 ? Math.max(
|
|
7284
|
+
0,
|
|
7285
|
+
last.top - children[children.length - 2].getBoundingClientRect().bottom
|
|
7286
|
+
) : edgeGap;
|
|
7287
|
+
top = last.bottom + lastGap / 2 - barThickness / 2;
|
|
7288
|
+
left = last.left;
|
|
7289
|
+
width = last.width;
|
|
7290
|
+
} else {
|
|
7291
|
+
const prev = children[i - 1].getBoundingClientRect();
|
|
7292
|
+
const next = children[i].getBoundingClientRect();
|
|
7293
|
+
top = (prev.bottom + next.top) / 2 - barThickness / 2;
|
|
7294
|
+
left = Math.min(prev.left, next.left);
|
|
7295
|
+
width = Math.max(prev.right, next.right) - left;
|
|
7296
|
+
}
|
|
7297
|
+
slots.push({
|
|
7298
|
+
insertIndex: i,
|
|
7299
|
+
parentId: parentHrefKey,
|
|
7300
|
+
left,
|
|
7301
|
+
top,
|
|
7302
|
+
width: Math.max(width, 40),
|
|
7303
|
+
height: barThickness,
|
|
7304
|
+
direction: "horizontal"
|
|
7305
|
+
});
|
|
7306
|
+
}
|
|
7307
|
+
return slots;
|
|
7308
|
+
}
|
|
7309
|
+
function buildAllNavDropSlots(draggedHrefKey) {
|
|
7310
|
+
const slots = [...buildRootNavDropSlots()];
|
|
7311
|
+
for (const item of listReorderableNavItems()) {
|
|
7312
|
+
const key = item.getAttribute("data-ohw-href-key");
|
|
7313
|
+
if (!key || key === draggedHrefKey) continue;
|
|
7314
|
+
const group = item.closest("[data-ohw-nav-group]");
|
|
7315
|
+
if (!group?.querySelector(":scope > [data-ohw-nav-children]")) continue;
|
|
7316
|
+
slots.push(...buildChildNavDropSlots(key));
|
|
7317
|
+
}
|
|
7318
|
+
const dragged = listNavbarItems().find((el) => el.getAttribute("data-ohw-href-key") === draggedHrefKey);
|
|
7319
|
+
const parentGroup = dragged?.closest("[data-ohw-nav-children]")?.closest("[data-ohw-nav-group]");
|
|
7320
|
+
const parentTrigger = parentGroup?.querySelector(":scope > [data-ohw-href-key]");
|
|
7321
|
+
const parentKey = parentTrigger?.getAttribute("data-ohw-href-key");
|
|
7322
|
+
if (parentKey && isNavbarHrefKey(parentKey)) {
|
|
7323
|
+
const existing = slots.some((s) => s.parentId === parentKey);
|
|
7324
|
+
if (!existing) slots.push(...buildChildNavDropSlots(parentKey));
|
|
7325
|
+
}
|
|
7326
|
+
return slots;
|
|
7327
|
+
}
|
|
7328
|
+
function hitTestNavDropSlot(clientX, clientY, draggedHrefKey) {
|
|
7329
|
+
const slots = buildAllNavDropSlots(draggedHrefKey);
|
|
7330
|
+
let best = null;
|
|
7331
|
+
for (const slot of slots) {
|
|
7332
|
+
const cx2 = slot.left + slot.width / 2;
|
|
7333
|
+
const cy = slot.top + slot.height / 2;
|
|
7334
|
+
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;
|
|
7335
|
+
if (!best || dist < best.dist) best = { slot, dist };
|
|
7336
|
+
}
|
|
7337
|
+
return best?.slot ?? null;
|
|
7338
|
+
}
|
|
7339
|
+
|
|
7340
|
+
// src/useNavItemDrag.ts
|
|
7341
|
+
var import_react8 = require("react");
|
|
7342
|
+
function useNavItemDrag({
|
|
7343
|
+
isEditMode,
|
|
7344
|
+
editContentRef,
|
|
7345
|
+
selectedElRef,
|
|
7346
|
+
activeElRef,
|
|
7347
|
+
footerDragRef,
|
|
7348
|
+
suppressNextClickRef,
|
|
7349
|
+
suppressClickUntilRef,
|
|
7350
|
+
siblingHintElRef,
|
|
7351
|
+
postToParentRef,
|
|
7352
|
+
deselectRef,
|
|
7353
|
+
selectRef,
|
|
7354
|
+
deactivateRef,
|
|
7355
|
+
setLinkPopover,
|
|
7356
|
+
linkPopoverOpenRef,
|
|
7357
|
+
setIsItemDragging,
|
|
7358
|
+
setDraggedItemRect,
|
|
7359
|
+
setSiblingHintRect,
|
|
7360
|
+
setSiblingHintRects,
|
|
7361
|
+
setToolbarRect,
|
|
7362
|
+
getNavigationItemAnchor: getNavigationItemAnchor2,
|
|
7363
|
+
isDragHandleDisabled: isDragHandleDisabled2,
|
|
7364
|
+
isNavbarButton: isNavbarButton3
|
|
7365
|
+
}) {
|
|
7366
|
+
const navDragRef = (0, import_react8.useRef)(null);
|
|
7367
|
+
const [navDropSlots, setNavDropSlots] = (0, import_react8.useState)([]);
|
|
7368
|
+
const [activeNavDropIndex, setActiveNavDropIndex] = (0, import_react8.useState)(null);
|
|
7369
|
+
const navPointerDragRef = (0, import_react8.useRef)(null);
|
|
7370
|
+
const clearNavDragVisuals = (0, import_react8.useCallback)(() => {
|
|
7371
|
+
navDragRef.current = null;
|
|
7372
|
+
setNavDropSlots([]);
|
|
7373
|
+
setActiveNavDropIndex(null);
|
|
7374
|
+
setDraggedItemRect(null);
|
|
7375
|
+
setSiblingHintRects([]);
|
|
7376
|
+
setIsItemDragging(false);
|
|
7377
|
+
unlockItemDragInteraction();
|
|
7378
|
+
}, [setDraggedItemRect, setIsItemDragging, setSiblingHintRects]);
|
|
7379
|
+
const refreshNavDragVisuals = (0, import_react8.useCallback)(
|
|
7380
|
+
(session, activeSlot, clientX, clientY) => {
|
|
7381
|
+
setDraggedItemRect(session.draggedEl.getBoundingClientRect());
|
|
7382
|
+
if (typeof clientX === "number" && typeof clientY === "number") {
|
|
7383
|
+
session.lastClientX = clientX;
|
|
7384
|
+
session.lastClientY = clientY;
|
|
7385
|
+
}
|
|
7386
|
+
session.activeSlot = activeSlot;
|
|
7387
|
+
setSiblingHintRects([]);
|
|
7388
|
+
const slots = buildAllNavDropSlots(session.hrefKey);
|
|
7389
|
+
setNavDropSlots(slots);
|
|
7390
|
+
const activeIdx = activeSlot ? slots.findIndex(
|
|
7391
|
+
(s) => s.parentId === activeSlot.parentId && s.insertIndex === activeSlot.insertIndex
|
|
7392
|
+
) : -1;
|
|
7393
|
+
setActiveNavDropIndex(activeIdx >= 0 ? activeIdx : null);
|
|
7394
|
+
},
|
|
7395
|
+
[setDraggedItemRect, setSiblingHintRects]
|
|
7396
|
+
);
|
|
7397
|
+
const refreshNavDragVisualsRef = (0, import_react8.useRef)(refreshNavDragVisuals);
|
|
7398
|
+
refreshNavDragVisualsRef.current = refreshNavDragVisuals;
|
|
7399
|
+
const commitNavDragRef = (0, import_react8.useRef)(() => {
|
|
7400
|
+
});
|
|
7401
|
+
const beginNavDragRef = (0, import_react8.useRef)(() => {
|
|
7402
|
+
});
|
|
7403
|
+
const beginNavDrag = (0, import_react8.useCallback)(
|
|
7404
|
+
(session) => {
|
|
7405
|
+
const rect = session.draggedEl.getBoundingClientRect();
|
|
7406
|
+
session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
|
|
7407
|
+
session.lastClientY = session.lastClientY || rect.top + rect.height / 2;
|
|
7408
|
+
session.activeSlot = session.activeSlot ?? null;
|
|
7409
|
+
navDragRef.current = session;
|
|
7410
|
+
setIsItemDragging(true);
|
|
7411
|
+
lockItemDuringDrag();
|
|
7412
|
+
siblingHintElRef.current = null;
|
|
7413
|
+
setSiblingHintRect(null);
|
|
7414
|
+
if (session.wasSelected && selectedElRef.current === session.draggedEl) {
|
|
7415
|
+
setToolbarRect(rect);
|
|
7416
|
+
}
|
|
7417
|
+
const initialSlot = hitTestNavDropSlot(session.lastClientX, session.lastClientY, session.hrefKey);
|
|
7418
|
+
refreshNavDragVisuals(session, initialSlot, session.lastClientX, session.lastClientY);
|
|
7419
|
+
},
|
|
7420
|
+
[
|
|
7421
|
+
refreshNavDragVisuals,
|
|
7422
|
+
selectedElRef,
|
|
7423
|
+
setIsItemDragging,
|
|
7424
|
+
setSiblingHintRect,
|
|
7425
|
+
setToolbarRect,
|
|
7426
|
+
siblingHintElRef
|
|
7427
|
+
]
|
|
7428
|
+
);
|
|
7429
|
+
beginNavDragRef.current = beginNavDrag;
|
|
7430
|
+
const commitNavDrag = (0, import_react8.useCallback)(
|
|
7431
|
+
(clientX, clientY) => {
|
|
7432
|
+
const session = navDragRef.current;
|
|
7433
|
+
if (!session) {
|
|
7434
|
+
clearNavDragVisuals();
|
|
7435
|
+
return;
|
|
7436
|
+
}
|
|
7437
|
+
const x = typeof clientX === "number" && (clientX !== 0 || clientY !== 0) ? clientX : session.lastClientX;
|
|
7438
|
+
const y = typeof clientY === "number" && (clientX !== 0 || clientY !== 0) ? clientY : session.lastClientY;
|
|
7439
|
+
const slot = session.activeSlot ?? hitTestNavDropSlot(x, y, session.hrefKey);
|
|
7440
|
+
const planned = slot != null ? planNavItemMove(session.hrefKey, slot.parentId, slot.insertIndex) : null;
|
|
7441
|
+
const wasSelected = session.wasSelected;
|
|
7442
|
+
const hrefKey = session.hrefKey;
|
|
7443
|
+
const applySelectionAfterDrop = () => {
|
|
7444
|
+
if (!wasSelected) {
|
|
7445
|
+
deselectRef.current();
|
|
7446
|
+
return;
|
|
7447
|
+
}
|
|
7448
|
+
const desktop = document.querySelector("[data-ohw-nav-container]");
|
|
7449
|
+
const drawer = document.querySelector("[data-ohw-nav-drawer]");
|
|
7450
|
+
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)}"]`);
|
|
7451
|
+
if (link) {
|
|
7452
|
+
selectRef.current(link);
|
|
7453
|
+
return;
|
|
7454
|
+
}
|
|
7455
|
+
deselectRef.current();
|
|
7456
|
+
};
|
|
7457
|
+
if (planned) {
|
|
7458
|
+
editContentRef.current = {
|
|
7459
|
+
...editContentRef.current,
|
|
7460
|
+
[NAV_ORDER_KEY]: planned.orderJson
|
|
7461
|
+
};
|
|
7462
|
+
applyNavForest(planned.forest);
|
|
7463
|
+
document.querySelectorAll(
|
|
7464
|
+
"nav [data-ohw-href-key], [data-ohw-nav-container] [data-ohw-href-key], [data-ohw-nav-drawer] [data-ohw-href-key]"
|
|
7465
|
+
).forEach((el) => {
|
|
7466
|
+
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
7467
|
+
disableNativeHrefDrag(el);
|
|
7468
|
+
}
|
|
7469
|
+
});
|
|
7470
|
+
postToParentRef.current({
|
|
7471
|
+
type: "ow:change",
|
|
7472
|
+
nodes: [{ key: NAV_ORDER_KEY, text: planned.orderJson }]
|
|
7473
|
+
});
|
|
7474
|
+
applySelectionAfterDrop();
|
|
7475
|
+
clearNavDragVisuals();
|
|
7476
|
+
requestAnimationFrame(() => {
|
|
7477
|
+
if (editContentRef.current[NAV_ORDER_KEY] === planned.orderJson) {
|
|
7478
|
+
applyNavForest(planned.forest);
|
|
7479
|
+
}
|
|
7480
|
+
applySelectionAfterDrop();
|
|
7481
|
+
requestAnimationFrame(applySelectionAfterDrop);
|
|
7482
|
+
});
|
|
7483
|
+
return;
|
|
7484
|
+
}
|
|
7485
|
+
applySelectionAfterDrop();
|
|
7486
|
+
clearNavDragVisuals();
|
|
7487
|
+
},
|
|
7488
|
+
[clearNavDragVisuals, deselectRef, editContentRef, postToParentRef, selectRef]
|
|
7489
|
+
);
|
|
7490
|
+
commitNavDragRef.current = commitNavDrag;
|
|
7491
|
+
const startNavLinkDrag = (0, import_react8.useCallback)(
|
|
7492
|
+
(anchor, clientX, clientY, wasSelected) => {
|
|
7493
|
+
if (footerDragRef.current) return false;
|
|
7494
|
+
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
7495
|
+
if (!hrefKey || !isNavbarHrefKey(hrefKey)) return false;
|
|
7496
|
+
if (isNavbarButton3(anchor) || isDragHandleDisabled2(anchor)) return false;
|
|
7497
|
+
beginNavDrag({
|
|
7498
|
+
hrefKey,
|
|
7499
|
+
wasSelected,
|
|
7500
|
+
draggedEl: anchor,
|
|
7501
|
+
lastClientX: clientX,
|
|
7502
|
+
lastClientY: clientY,
|
|
7503
|
+
activeSlot: null
|
|
7504
|
+
});
|
|
7505
|
+
return true;
|
|
7506
|
+
},
|
|
7507
|
+
[beginNavDrag, footerDragRef, isDragHandleDisabled2, isNavbarButton3]
|
|
7508
|
+
);
|
|
7509
|
+
const onNavDragOver = (0, import_react8.useCallback)(
|
|
7510
|
+
(e) => {
|
|
7511
|
+
const session = navDragRef.current;
|
|
7512
|
+
if (!session) return false;
|
|
7513
|
+
e.preventDefault();
|
|
7514
|
+
if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
|
|
7515
|
+
const slot = hitTestNavDropSlot(e.clientX, e.clientY, session.hrefKey);
|
|
7516
|
+
refreshNavDragVisualsRef.current(session, slot, e.clientX, e.clientY);
|
|
7517
|
+
return true;
|
|
7518
|
+
},
|
|
7519
|
+
[]
|
|
7520
|
+
);
|
|
7521
|
+
(0, import_react8.useEffect)(() => {
|
|
7522
|
+
if (!isEditMode) return;
|
|
7523
|
+
const THRESHOLD = 10;
|
|
7524
|
+
const resolveWasSelected = (el) => {
|
|
7525
|
+
if (selectedElRef.current === el) return true;
|
|
7526
|
+
const activeAnchor = activeElRef.current ? getNavigationItemAnchor2(activeElRef.current) : null;
|
|
7527
|
+
return activeAnchor === el;
|
|
7528
|
+
};
|
|
7529
|
+
const onPointerDown = (e) => {
|
|
7530
|
+
if (e.button !== 0) return;
|
|
7531
|
+
if (navDragRef.current || footerDragRef.current) return;
|
|
7532
|
+
const target = e.target;
|
|
7533
|
+
if (!target) return;
|
|
7534
|
+
if (target.closest(
|
|
7535
|
+
'[data-ohw-drag-handle-container], [data-slot="drag-handle"], [data-ohw-toolbar], [data-ohw-item-toolbar-anchor], [data-ohw-link-popover-root]'
|
|
7536
|
+
)) {
|
|
7537
|
+
return;
|
|
7538
|
+
}
|
|
7539
|
+
if (target.closest("[data-ohw-item-drag-surface]")) return;
|
|
7540
|
+
const anchor = getNavigationItemAnchor2(target);
|
|
7541
|
+
const hrefKey = anchor?.getAttribute("data-ohw-href-key") ?? null;
|
|
7542
|
+
if (!anchor || !isNavbarHrefKey(hrefKey)) return;
|
|
7543
|
+
if (isNavbarButton3(anchor) || isDragHandleDisabled2(anchor)) return;
|
|
7544
|
+
armItemPressDrag();
|
|
7545
|
+
navPointerDragRef.current = {
|
|
7546
|
+
el: anchor,
|
|
7547
|
+
startX: e.clientX,
|
|
7548
|
+
startY: e.clientY,
|
|
7549
|
+
pointerId: e.pointerId,
|
|
7550
|
+
wasSelected: resolveWasSelected(anchor),
|
|
7551
|
+
started: false
|
|
7552
|
+
};
|
|
7553
|
+
};
|
|
7554
|
+
const onPointerMove = (e) => {
|
|
7555
|
+
const pending = navPointerDragRef.current;
|
|
7556
|
+
if (!pending) return;
|
|
7557
|
+
if (pending.started) {
|
|
7558
|
+
e.preventDefault();
|
|
7559
|
+
clearTextSelection();
|
|
7560
|
+
const session = navDragRef.current;
|
|
7561
|
+
if (!session) return;
|
|
7562
|
+
const slot = hitTestNavDropSlot(e.clientX, e.clientY, session.hrefKey);
|
|
7563
|
+
refreshNavDragVisualsRef.current(session, slot, e.clientX, e.clientY);
|
|
7564
|
+
return;
|
|
7565
|
+
}
|
|
7566
|
+
const dx = e.clientX - pending.startX;
|
|
7567
|
+
const dy = e.clientY - pending.startY;
|
|
7568
|
+
if (dx * dx + dy * dy < THRESHOLD * THRESHOLD) return;
|
|
7569
|
+
e.preventDefault();
|
|
7570
|
+
pending.started = true;
|
|
7571
|
+
clearTextSelection();
|
|
7572
|
+
try {
|
|
7573
|
+
document.body.setPointerCapture(pending.pointerId);
|
|
7574
|
+
} catch {
|
|
7575
|
+
}
|
|
7576
|
+
if (linkPopoverOpenRef.current) setLinkPopover(null);
|
|
7577
|
+
if (activeElRef.current) deactivateRef.current();
|
|
7578
|
+
const key = pending.el.getAttribute("data-ohw-href-key");
|
|
7579
|
+
if (!key) return;
|
|
7580
|
+
beginNavDragRef.current({
|
|
7581
|
+
hrefKey: key,
|
|
7582
|
+
wasSelected: pending.wasSelected,
|
|
7583
|
+
draggedEl: pending.el,
|
|
7584
|
+
lastClientX: e.clientX,
|
|
7585
|
+
lastClientY: e.clientY,
|
|
7586
|
+
activeSlot: null
|
|
7587
|
+
});
|
|
7588
|
+
};
|
|
7589
|
+
const endPointerDrag = (e) => {
|
|
7590
|
+
const pending = navPointerDragRef.current;
|
|
7591
|
+
navPointerDragRef.current = null;
|
|
7592
|
+
try {
|
|
7593
|
+
if (document.body.hasPointerCapture(e.pointerId)) {
|
|
7594
|
+
document.body.releasePointerCapture(e.pointerId);
|
|
7595
|
+
}
|
|
7596
|
+
} catch {
|
|
7597
|
+
}
|
|
7598
|
+
if (!pending?.started) {
|
|
7599
|
+
unlockItemDragInteraction();
|
|
7600
|
+
return;
|
|
7601
|
+
}
|
|
7602
|
+
suppressNextClickRef.current = true;
|
|
7603
|
+
suppressClickUntilRef.current = Date.now() + 500;
|
|
7604
|
+
commitNavDragRef.current(e.clientX, e.clientY);
|
|
7605
|
+
};
|
|
7606
|
+
const blockSelectStart = (e) => {
|
|
7607
|
+
if (navDragRef.current || navPointerDragRef.current?.started || document.documentElement.hasAttribute("data-ohw-footer-press-drag")) {
|
|
7608
|
+
e.preventDefault();
|
|
7609
|
+
}
|
|
7610
|
+
};
|
|
7611
|
+
const onDragEnd = () => {
|
|
7612
|
+
if (!navDragRef.current) return;
|
|
7613
|
+
suppressNextClickRef.current = true;
|
|
7614
|
+
suppressClickUntilRef.current = Date.now() + 500;
|
|
7615
|
+
commitNavDragRef.current();
|
|
7616
|
+
};
|
|
7617
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
7618
|
+
document.addEventListener("pointermove", onPointerMove, true);
|
|
7619
|
+
document.addEventListener("pointerup", endPointerDrag, true);
|
|
7620
|
+
document.addEventListener("pointercancel", endPointerDrag, true);
|
|
7621
|
+
document.addEventListener("selectstart", blockSelectStart, true);
|
|
7622
|
+
document.addEventListener("dragend", onDragEnd, true);
|
|
7623
|
+
return () => {
|
|
7624
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
7625
|
+
document.removeEventListener("pointermove", onPointerMove, true);
|
|
7626
|
+
document.removeEventListener("pointerup", endPointerDrag, true);
|
|
7627
|
+
document.removeEventListener("pointercancel", endPointerDrag, true);
|
|
7628
|
+
document.removeEventListener("selectstart", blockSelectStart, true);
|
|
7629
|
+
document.removeEventListener("dragend", onDragEnd, true);
|
|
7630
|
+
unlockItemDragInteraction();
|
|
7631
|
+
};
|
|
7632
|
+
}, [
|
|
7633
|
+
activeElRef,
|
|
7634
|
+
deactivateRef,
|
|
7635
|
+
footerDragRef,
|
|
7636
|
+
getNavigationItemAnchor2,
|
|
7637
|
+
isDragHandleDisabled2,
|
|
7638
|
+
isEditMode,
|
|
7639
|
+
isNavbarButton3,
|
|
7640
|
+
linkPopoverOpenRef,
|
|
7641
|
+
selectedElRef,
|
|
7642
|
+
setLinkPopover,
|
|
7643
|
+
suppressNextClickRef
|
|
7644
|
+
]);
|
|
7645
|
+
const armNavPressFromChrome = (0, import_react8.useCallback)(
|
|
7646
|
+
(selected, clientX, clientY, pointerId) => {
|
|
7647
|
+
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
7648
|
+
if (!hrefKey || !isNavbarHrefKey(hrefKey)) return false;
|
|
7649
|
+
if (isNavbarButton3(selected) || isDragHandleDisabled2(selected)) return false;
|
|
7650
|
+
armItemPressDrag();
|
|
7651
|
+
navPointerDragRef.current = {
|
|
7652
|
+
el: selected,
|
|
7653
|
+
startX: clientX,
|
|
7654
|
+
startY: clientY,
|
|
7655
|
+
pointerId,
|
|
7656
|
+
wasSelected: true,
|
|
7657
|
+
started: false
|
|
7658
|
+
};
|
|
7659
|
+
return true;
|
|
7660
|
+
},
|
|
7661
|
+
[isDragHandleDisabled2, isNavbarButton3]
|
|
7662
|
+
);
|
|
7663
|
+
return {
|
|
7664
|
+
navDragRef,
|
|
7665
|
+
navDropSlots,
|
|
7666
|
+
activeNavDropIndex,
|
|
7667
|
+
startNavLinkDrag,
|
|
7668
|
+
commitNavDrag,
|
|
7669
|
+
onNavDragOver,
|
|
7670
|
+
armNavPressFromChrome,
|
|
7671
|
+
clearNavDragVisuals,
|
|
7672
|
+
refreshNavDragVisualsRef
|
|
7673
|
+
};
|
|
7674
|
+
}
|
|
7675
|
+
|
|
7676
|
+
// src/ui/navbar-container-chrome.tsx
|
|
7677
|
+
var import_lucide_react10 = require("lucide-react");
|
|
7678
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
7679
|
+
function NavbarContainerChrome({
|
|
7680
|
+
rect,
|
|
7681
|
+
onAdd
|
|
7682
|
+
}) {
|
|
7683
|
+
const chromeGap = 6;
|
|
7684
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
7685
|
+
"div",
|
|
7686
|
+
{
|
|
7687
|
+
"data-ohw-navbar-container-chrome": "",
|
|
7688
|
+
"data-ohw-bridge": "",
|
|
7689
|
+
className: "pointer-events-none fixed z-[2147483647]",
|
|
7690
|
+
style: {
|
|
7691
|
+
top: rect.top - chromeGap,
|
|
7692
|
+
left: rect.left - chromeGap,
|
|
7693
|
+
width: rect.width + chromeGap * 2,
|
|
7694
|
+
height: rect.height + chromeGap * 2
|
|
7695
|
+
},
|
|
7696
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
7697
|
+
"button",
|
|
7698
|
+
{
|
|
7699
|
+
type: "button",
|
|
7700
|
+
"data-ohw-navbar-add-button": "",
|
|
7701
|
+
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",
|
|
7702
|
+
style: { top: "70%" },
|
|
7703
|
+
"aria-label": "Add item",
|
|
7704
|
+
onMouseDown: (e) => {
|
|
7705
|
+
e.preventDefault();
|
|
7706
|
+
e.stopPropagation();
|
|
7707
|
+
},
|
|
7708
|
+
onClick: (e) => {
|
|
7709
|
+
e.preventDefault();
|
|
7710
|
+
e.stopPropagation();
|
|
7711
|
+
onAdd();
|
|
7712
|
+
},
|
|
7713
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
7714
|
+
}
|
|
7715
|
+
)
|
|
7716
|
+
}
|
|
7717
|
+
);
|
|
7718
|
+
}
|
|
7719
|
+
|
|
7720
|
+
// src/ui/drop-indicator.tsx
|
|
7721
|
+
var React10 = __toESM(require("react"), 1);
|
|
7722
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
7723
|
+
var dropIndicatorVariants = cva(
|
|
7724
|
+
"ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
|
|
7725
|
+
{
|
|
7726
|
+
variants: {
|
|
7727
|
+
direction: {
|
|
7728
|
+
vertical: "h-6 w-[3px]",
|
|
7729
|
+
horizontal: "h-[3px] w-[200px]"
|
|
7730
|
+
},
|
|
7731
|
+
state: {
|
|
7732
|
+
default: "opacity-0",
|
|
7733
|
+
hover: "opacity-100",
|
|
7734
|
+
dragIdle: "opacity-40",
|
|
7735
|
+
dragActive: "opacity-100"
|
|
7736
|
+
}
|
|
7737
|
+
},
|
|
7738
|
+
defaultVariants: {
|
|
7739
|
+
direction: "vertical",
|
|
7740
|
+
state: "default"
|
|
7741
|
+
}
|
|
7742
|
+
}
|
|
7743
|
+
);
|
|
7744
|
+
var DropIndicator = React10.forwardRef(
|
|
7745
|
+
({ className, direction, state, ...props }, ref) => {
|
|
7746
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
7747
|
+
"div",
|
|
7748
|
+
{
|
|
7749
|
+
ref,
|
|
7750
|
+
"data-slot": "drop-indicator",
|
|
7751
|
+
"data-direction": direction ?? "vertical",
|
|
7752
|
+
"data-state": state ?? "default",
|
|
7753
|
+
"aria-hidden": "true",
|
|
7754
|
+
className: cn(dropIndicatorVariants({ direction, state }), className),
|
|
7755
|
+
...props
|
|
7756
|
+
}
|
|
7757
|
+
);
|
|
7758
|
+
}
|
|
7759
|
+
);
|
|
7760
|
+
DropIndicator.displayName = "DropIndicator";
|
|
7761
|
+
|
|
7762
|
+
// src/ui/badge.tsx
|
|
7763
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
7764
|
+
var badgeVariants = cva(
|
|
7765
|
+
"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",
|
|
7766
|
+
{
|
|
7767
|
+
variants: {
|
|
7768
|
+
variant: {
|
|
7769
|
+
default: "border-transparent bg-primary text-primary-foreground",
|
|
7770
|
+
secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
7771
|
+
destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
|
|
7772
|
+
outline: "text-foreground"
|
|
7773
|
+
}
|
|
7774
|
+
},
|
|
7775
|
+
defaultVariants: {
|
|
7776
|
+
variant: "default"
|
|
7777
|
+
}
|
|
7778
|
+
}
|
|
7779
|
+
);
|
|
7780
|
+
function Badge({ className, variant, ...props }) {
|
|
7781
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
7782
|
+
}
|
|
7783
|
+
|
|
7784
|
+
// src/OhhwellsBridge.tsx
|
|
7785
|
+
var import_lucide_react11 = require("lucide-react");
|
|
7786
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
7787
|
+
var PRIMARY2 = "#0885FE";
|
|
7788
|
+
var IMAGE_FADE_MS = 300;
|
|
7789
|
+
function runOpacityFade(el, onDone) {
|
|
7790
|
+
const anim = el.animate([{ opacity: 0 }, { opacity: 1 }], {
|
|
7791
|
+
duration: IMAGE_FADE_MS,
|
|
7792
|
+
easing: "ease",
|
|
7793
|
+
fill: "forwards"
|
|
7794
|
+
});
|
|
7795
|
+
let finished = false;
|
|
7796
|
+
const finish = () => {
|
|
7797
|
+
if (finished) return;
|
|
7798
|
+
finished = true;
|
|
7799
|
+
anim.cancel();
|
|
7800
|
+
el.style.opacity = "";
|
|
7801
|
+
onDone();
|
|
7802
|
+
};
|
|
7803
|
+
anim.finished.then(finish).catch(finish);
|
|
7804
|
+
window.setTimeout(finish, IMAGE_FADE_MS + 100);
|
|
7805
|
+
}
|
|
7806
|
+
function fadeInImageElement(img, onReady) {
|
|
7807
|
+
onReady();
|
|
7808
|
+
img.style.opacity = "0";
|
|
7809
|
+
runOpacityFade(img, () => {
|
|
7810
|
+
img.style.opacity = "";
|
|
7811
|
+
});
|
|
7812
|
+
}
|
|
7813
|
+
function applyEditableImageSrc(img, url) {
|
|
7814
|
+
img.removeAttribute("srcset");
|
|
7815
|
+
img.removeAttribute("sizes");
|
|
7816
|
+
img.src = url;
|
|
7817
|
+
}
|
|
7818
|
+
function fadeInBgImage(el, url, onReady) {
|
|
7819
|
+
const prevPos = el.style.position;
|
|
7820
|
+
if (!prevPos || prevPos === "static") el.style.position = "relative";
|
|
7821
|
+
const layer = document.createElement("div");
|
|
7822
|
+
layer.setAttribute("data-ohw-bg-fade-layer", "");
|
|
7823
|
+
Object.assign(layer.style, {
|
|
7824
|
+
position: "absolute",
|
|
7825
|
+
inset: "0",
|
|
7826
|
+
zIndex: "0",
|
|
7827
|
+
backgroundImage: `url('${url}')`,
|
|
7828
|
+
backgroundSize: "cover",
|
|
7829
|
+
backgroundPosition: "center",
|
|
7830
|
+
backgroundRepeat: "no-repeat",
|
|
7831
|
+
opacity: "0",
|
|
7832
|
+
pointerEvents: "none"
|
|
7833
|
+
});
|
|
7834
|
+
el.prepend(layer);
|
|
7835
|
+
onReady();
|
|
7836
|
+
runOpacityFade(layer, () => {
|
|
7837
|
+
el.style.backgroundImage = `url('${url}')`;
|
|
7838
|
+
layer.remove();
|
|
7839
|
+
if (!prevPos || prevPos === "static") el.style.position = prevPos;
|
|
7840
|
+
});
|
|
7841
|
+
}
|
|
7842
|
+
function getSectionsTracker() {
|
|
7843
|
+
let el = document.querySelector("[data-ohw-sections-tracker]");
|
|
7844
|
+
if (!el) {
|
|
7845
|
+
el = document.createElement("div");
|
|
7846
|
+
el.setAttribute("data-ohw-sections-tracker", "");
|
|
7847
|
+
el.style.display = "none";
|
|
7848
|
+
document.body.appendChild(el);
|
|
7849
|
+
}
|
|
7850
|
+
return el;
|
|
7851
|
+
}
|
|
7852
|
+
function updateSectionScheduleId(insertAfter, scheduleId) {
|
|
7853
|
+
const tracker = getSectionsTracker();
|
|
7854
|
+
let sections = [];
|
|
7855
|
+
try {
|
|
7856
|
+
sections = JSON.parse(tracker.textContent || "[]");
|
|
7857
|
+
} catch {
|
|
7858
|
+
}
|
|
7859
|
+
const currentPath = window.location.pathname;
|
|
7860
|
+
const updated = sections.map((s) => {
|
|
7861
|
+
if (s.type !== "scheduling" || s.insertAfter !== insertAfter) return s;
|
|
7862
|
+
if (s.pagePath && s.pagePath !== currentPath) return s;
|
|
7863
|
+
return { ...s, scheduleId };
|
|
7864
|
+
});
|
|
7865
|
+
tracker.textContent = JSON.stringify(updated);
|
|
7866
|
+
return tracker.textContent ?? "[]";
|
|
7867
|
+
}
|
|
7868
|
+
function schedulingSectionId(insertAfter) {
|
|
7869
|
+
return `scheduling-${insertAfter}`;
|
|
7870
|
+
}
|
|
7871
|
+
var INSERT_BEFORE_MARKER = ":before:";
|
|
6711
7872
|
function parseSchedulingInsertAfter(insertAfter) {
|
|
6712
7873
|
const idx = insertAfter.indexOf(INSERT_BEFORE_MARKER);
|
|
6713
7874
|
if (idx < 0) return { anchor: insertAfter, insertBefore: null };
|
|
@@ -6801,7 +7962,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
6801
7962
|
const root = (0, import_client.createRoot)(container);
|
|
6802
7963
|
(0, import_react_dom2.flushSync)(() => {
|
|
6803
7964
|
root.render(
|
|
6804
|
-
/* @__PURE__ */ (0,
|
|
7965
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
6805
7966
|
SchedulingWidget,
|
|
6806
7967
|
{
|
|
6807
7968
|
notifyOnConnect,
|
|
@@ -6876,7 +8037,7 @@ function syncNavigationDragCursorAttrs() {
|
|
|
6876
8037
|
el.setAttribute("data-ohw-can-drag", "");
|
|
6877
8038
|
});
|
|
6878
8039
|
}
|
|
6879
|
-
function collectEditableNodes() {
|
|
8040
|
+
function collectEditableNodes(extraContent) {
|
|
6880
8041
|
const nodes = Array.from(document.querySelectorAll("[data-ohw-editable]")).map((el) => {
|
|
6881
8042
|
if (el.dataset.ohwEditable === "image") {
|
|
6882
8043
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
@@ -6904,6 +8065,14 @@ function collectEditableNodes() {
|
|
|
6904
8065
|
if (!key) return;
|
|
6905
8066
|
nodes.push({ key, type: "link", text: getLinkHref2(el) });
|
|
6906
8067
|
});
|
|
8068
|
+
if (extraContent) {
|
|
8069
|
+
for (const key of [NAV_ORDER_KEY, FOOTER_ORDER_KEY, NAV_COUNT_KEY]) {
|
|
8070
|
+
const text = extraContent[key];
|
|
8071
|
+
if (typeof text === "string" && text.length > 0) {
|
|
8072
|
+
nodes.push({ key, type: "meta", text });
|
|
8073
|
+
}
|
|
8074
|
+
}
|
|
8075
|
+
}
|
|
6907
8076
|
document.querySelectorAll('[data-ohw-editable="video"]').forEach((el) => {
|
|
6908
8077
|
const key = el.dataset.ohwKey ?? "";
|
|
6909
8078
|
const video = getVideoEl(el);
|
|
@@ -7017,6 +8186,11 @@ function getNavigationItemAnchor(el) {
|
|
|
7017
8186
|
function isNavigationItem(el) {
|
|
7018
8187
|
return getNavigationItemAnchor(el) !== null;
|
|
7019
8188
|
}
|
|
8189
|
+
function listNavigationItems() {
|
|
8190
|
+
return Array.from(
|
|
8191
|
+
document.querySelectorAll("nav [data-ohw-href-key], footer [data-ohw-href-key]")
|
|
8192
|
+
).filter((el) => isNavigationItem(el));
|
|
8193
|
+
}
|
|
7020
8194
|
function getNavigationItemReorderState(anchor) {
|
|
7021
8195
|
if (isNavbarButton2(anchor)) return { key: null, disabled: false };
|
|
7022
8196
|
return getReorderHandleStateFromAnchor(anchor);
|
|
@@ -7049,7 +8223,7 @@ function countFooterNavItems(el) {
|
|
|
7049
8223
|
return Array.from(el.querySelectorAll("[data-ohw-href-key]")).filter(isNavigationItem).length;
|
|
7050
8224
|
}
|
|
7051
8225
|
function findFooterItemGroup(item) {
|
|
7052
|
-
const explicit = item.closest("[data-ohw-footer-column]");
|
|
8226
|
+
const explicit = item.closest("[data-ohw-footer-col], [data-ohw-footer-column]");
|
|
7053
8227
|
if (explicit) return explicit;
|
|
7054
8228
|
const footer = item.closest("footer");
|
|
7055
8229
|
if (!footer) return null;
|
|
@@ -7066,17 +8240,17 @@ function isNavigationRoot(el) {
|
|
|
7066
8240
|
function isInferredFooterGroup(el) {
|
|
7067
8241
|
const footer = el.closest("footer");
|
|
7068
8242
|
if (!footer || el === footer) return false;
|
|
7069
|
-
if (el.hasAttribute("data-ohw-footer-column")) return true;
|
|
8243
|
+
if (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column")) return true;
|
|
7070
8244
|
return countFooterNavItems(el) >= 2;
|
|
7071
8245
|
}
|
|
7072
8246
|
function isNavigationContainer(el) {
|
|
7073
|
-
return el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-footer-column") || isNavigationRoot(el) || isInferredFooterGroup(el);
|
|
8247
|
+
return el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isNavigationRoot(el) || isInferredFooterGroup(el);
|
|
7074
8248
|
}
|
|
7075
8249
|
function isNavbarLinksContainer(el) {
|
|
7076
8250
|
return el.hasAttribute("data-ohw-nav-container");
|
|
7077
8251
|
}
|
|
7078
8252
|
function getFooterColumn(el) {
|
|
7079
|
-
return el.closest("[data-ohw-footer-column]");
|
|
8253
|
+
return el.closest("[data-ohw-footer-col], [data-ohw-footer-column]");
|
|
7080
8254
|
}
|
|
7081
8255
|
function resolveFooterColumnSelectionTarget(target, clientX, clientY) {
|
|
7082
8256
|
if (getNavigationItemAnchor(target)) return null;
|
|
@@ -7100,7 +8274,7 @@ function isPointOverNavigation(x, y) {
|
|
|
7100
8274
|
function findHoveredNavOrFooterContainer(x, y) {
|
|
7101
8275
|
const candidates = [
|
|
7102
8276
|
...document.querySelectorAll("[data-ohw-nav-container]"),
|
|
7103
|
-
...
|
|
8277
|
+
...listFooterColumns()
|
|
7104
8278
|
];
|
|
7105
8279
|
for (const container of candidates) {
|
|
7106
8280
|
const r2 = container.getBoundingClientRect();
|
|
@@ -7147,32 +8321,57 @@ function getNavigationSelectionParent(el) {
|
|
|
7147
8321
|
if (footerGroup) return footerGroup;
|
|
7148
8322
|
return getNavigationRoot(el);
|
|
7149
8323
|
}
|
|
7150
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup(el)) {
|
|
8324
|
+
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup(el)) {
|
|
7151
8325
|
return getNavigationRoot(el);
|
|
7152
8326
|
}
|
|
7153
8327
|
return null;
|
|
7154
8328
|
}
|
|
8329
|
+
function collectNavigationItemSiblingHintRects(selected) {
|
|
8330
|
+
if (!isNavigationItem(selected)) return [];
|
|
8331
|
+
const footerColumn = getFooterColumn(selected);
|
|
8332
|
+
if (footerColumn) {
|
|
8333
|
+
return listFooterLinksInColumn(footerColumn).filter((link) => link !== selected).map((link) => link.getBoundingClientRect());
|
|
8334
|
+
}
|
|
8335
|
+
const navContainer = selected.closest("[data-ohw-nav-container], [data-ohw-nav-drawer]");
|
|
8336
|
+
if (navContainer) {
|
|
8337
|
+
return Array.from(navContainer.querySelectorAll("[data-ohw-href-key]")).filter((el) => isNavigationItem(el) && el !== selected).map((el) => el.getBoundingClientRect());
|
|
8338
|
+
}
|
|
8339
|
+
return listNavigationItems().filter((el) => el !== selected).map((el) => el.getBoundingClientRect());
|
|
8340
|
+
}
|
|
7155
8341
|
function placeCaretAtPoint(el, x, y) {
|
|
7156
8342
|
const selection = window.getSelection();
|
|
7157
8343
|
if (!selection) return;
|
|
7158
|
-
|
|
7159
|
-
|
|
7160
|
-
|
|
7161
|
-
|
|
7162
|
-
|
|
7163
|
-
|
|
8344
|
+
const overlays = Array.from(
|
|
8345
|
+
document.querySelectorAll(
|
|
8346
|
+
"[data-ohw-item-drag-surface], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-ohw-item-toolbar-anchor]"
|
|
8347
|
+
)
|
|
8348
|
+
);
|
|
8349
|
+
const prevPointerEvents = overlays.map((node) => node.style.pointerEvents);
|
|
8350
|
+
for (const node of overlays) node.style.pointerEvents = "none";
|
|
8351
|
+
try {
|
|
8352
|
+
if (typeof document.caretRangeFromPoint === "function") {
|
|
8353
|
+
const range = document.caretRangeFromPoint(x, y);
|
|
8354
|
+
if (range && el.contains(range.startContainer)) {
|
|
8355
|
+
selection.removeAllRanges();
|
|
8356
|
+
selection.addRange(range);
|
|
8357
|
+
return;
|
|
8358
|
+
}
|
|
7164
8359
|
}
|
|
7165
|
-
|
|
7166
|
-
|
|
7167
|
-
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
|
-
|
|
8360
|
+
const caretPositionFromPoint = document.caretPositionFromPoint;
|
|
8361
|
+
if (typeof caretPositionFromPoint === "function") {
|
|
8362
|
+
const position = caretPositionFromPoint(x, y);
|
|
8363
|
+
if (position && el.contains(position.offsetNode)) {
|
|
8364
|
+
const range = document.createRange();
|
|
8365
|
+
range.setStart(position.offsetNode, position.offset);
|
|
8366
|
+
range.collapse(true);
|
|
8367
|
+
selection.removeAllRanges();
|
|
8368
|
+
selection.addRange(range);
|
|
8369
|
+
}
|
|
7175
8370
|
}
|
|
8371
|
+
} finally {
|
|
8372
|
+
overlays.forEach((node, i) => {
|
|
8373
|
+
node.style.pointerEvents = prevPointerEvents[i] ?? "";
|
|
8374
|
+
});
|
|
7176
8375
|
}
|
|
7177
8376
|
}
|
|
7178
8377
|
function selectAllTextInEditable(el) {
|
|
@@ -7338,10 +8537,11 @@ function EditGlowChrome({
|
|
|
7338
8537
|
rect,
|
|
7339
8538
|
elRef,
|
|
7340
8539
|
reorderHrefKey,
|
|
7341
|
-
dragDisabled = false
|
|
8540
|
+
dragDisabled = false,
|
|
8541
|
+
hideHandle = false
|
|
7342
8542
|
}) {
|
|
7343
8543
|
const GAP = SELECTION_CHROME_GAP2;
|
|
7344
|
-
return /* @__PURE__ */ (0,
|
|
8544
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
7345
8545
|
"div",
|
|
7346
8546
|
{
|
|
7347
8547
|
ref: elRef,
|
|
@@ -7356,7 +8556,7 @@ function EditGlowChrome({
|
|
|
7356
8556
|
zIndex: 2147483646
|
|
7357
8557
|
},
|
|
7358
8558
|
children: [
|
|
7359
|
-
/* @__PURE__ */ (0,
|
|
8559
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
7360
8560
|
"div",
|
|
7361
8561
|
{
|
|
7362
8562
|
style: {
|
|
@@ -7369,7 +8569,7 @@ function EditGlowChrome({
|
|
|
7369
8569
|
}
|
|
7370
8570
|
}
|
|
7371
8571
|
),
|
|
7372
|
-
reorderHrefKey && /* @__PURE__ */ (0,
|
|
8572
|
+
reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
7373
8573
|
"div",
|
|
7374
8574
|
{
|
|
7375
8575
|
"data-ohw-drag-handle-container": "",
|
|
@@ -7381,7 +8581,7 @@ function EditGlowChrome({
|
|
|
7381
8581
|
transform: "translate(calc(-100% - 7px), -50%)",
|
|
7382
8582
|
pointerEvents: dragDisabled ? "none" : "auto"
|
|
7383
8583
|
},
|
|
7384
|
-
children: /* @__PURE__ */ (0,
|
|
8584
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
7385
8585
|
DragHandle,
|
|
7386
8586
|
{
|
|
7387
8587
|
"aria-label": `Reorder ${reorderHrefKey}`,
|
|
@@ -7491,9 +8691,9 @@ function FloatingToolbar({
|
|
|
7491
8691
|
showEditLink,
|
|
7492
8692
|
onEditLink
|
|
7493
8693
|
}) {
|
|
7494
|
-
const localRef =
|
|
7495
|
-
const [measuredW, setMeasuredW] =
|
|
7496
|
-
const setRefs =
|
|
8694
|
+
const localRef = import_react9.default.useRef(null);
|
|
8695
|
+
const [measuredW, setMeasuredW] = import_react9.default.useState(330);
|
|
8696
|
+
const setRefs = import_react9.default.useCallback(
|
|
7497
8697
|
(node) => {
|
|
7498
8698
|
localRef.current = node;
|
|
7499
8699
|
if (typeof elRef === "function") elRef(node);
|
|
@@ -7505,7 +8705,7 @@ function FloatingToolbar({
|
|
|
7505
8705
|
},
|
|
7506
8706
|
[elRef]
|
|
7507
8707
|
);
|
|
7508
|
-
|
|
8708
|
+
import_react9.default.useLayoutEffect(() => {
|
|
7509
8709
|
const node = localRef.current;
|
|
7510
8710
|
if (!node) return;
|
|
7511
8711
|
const update = () => {
|
|
@@ -7518,7 +8718,7 @@ function FloatingToolbar({
|
|
|
7518
8718
|
return () => ro.disconnect();
|
|
7519
8719
|
}, [showEditLink, activeCommands]);
|
|
7520
8720
|
const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
|
|
7521
|
-
return /* @__PURE__ */ (0,
|
|
8721
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
7522
8722
|
"div",
|
|
7523
8723
|
{
|
|
7524
8724
|
ref: setRefs,
|
|
@@ -7530,12 +8730,12 @@ function FloatingToolbar({
|
|
|
7530
8730
|
zIndex: 2147483647,
|
|
7531
8731
|
pointerEvents: "auto"
|
|
7532
8732
|
},
|
|
7533
|
-
children: /* @__PURE__ */ (0,
|
|
7534
|
-
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0,
|
|
7535
|
-
gi > 0 && /* @__PURE__ */ (0,
|
|
8733
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(CustomToolbar, { children: [
|
|
8734
|
+
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react9.default.Fragment, { children: [
|
|
8735
|
+
gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(CustomToolbarDivider, {}),
|
|
7536
8736
|
btns.map((btn) => {
|
|
7537
8737
|
const isActive = activeCommands.has(btn.cmd);
|
|
7538
|
-
return /* @__PURE__ */ (0,
|
|
8738
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
7539
8739
|
CustomToolbarButton,
|
|
7540
8740
|
{
|
|
7541
8741
|
title: btn.title,
|
|
@@ -7544,7 +8744,7 @@ function FloatingToolbar({
|
|
|
7544
8744
|
e.preventDefault();
|
|
7545
8745
|
onCommand(btn.cmd);
|
|
7546
8746
|
},
|
|
7547
|
-
children: /* @__PURE__ */ (0,
|
|
8747
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
7548
8748
|
"svg",
|
|
7549
8749
|
{
|
|
7550
8750
|
width: "16",
|
|
@@ -7565,7 +8765,7 @@ function FloatingToolbar({
|
|
|
7565
8765
|
);
|
|
7566
8766
|
})
|
|
7567
8767
|
] }, gi)),
|
|
7568
|
-
showEditLink ? /* @__PURE__ */ (0,
|
|
8768
|
+
showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
7569
8769
|
CustomToolbarButton,
|
|
7570
8770
|
{
|
|
7571
8771
|
type: "button",
|
|
@@ -7579,7 +8779,7 @@ function FloatingToolbar({
|
|
|
7579
8779
|
e.preventDefault();
|
|
7580
8780
|
e.stopPropagation();
|
|
7581
8781
|
},
|
|
7582
|
-
children: /* @__PURE__ */ (0,
|
|
8782
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Link, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
7583
8783
|
}
|
|
7584
8784
|
) : null
|
|
7585
8785
|
] })
|
|
@@ -7596,7 +8796,7 @@ function StateToggle({
|
|
|
7596
8796
|
states,
|
|
7597
8797
|
onStateChange
|
|
7598
8798
|
}) {
|
|
7599
|
-
return /* @__PURE__ */ (0,
|
|
8799
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
7600
8800
|
ToggleGroup,
|
|
7601
8801
|
{
|
|
7602
8802
|
"data-ohw-state-toggle": "",
|
|
@@ -7610,7 +8810,7 @@ function StateToggle({
|
|
|
7610
8810
|
left: rect.right - 8,
|
|
7611
8811
|
transform: "translateX(-100%)"
|
|
7612
8812
|
},
|
|
7613
|
-
children: states.map((state) => /* @__PURE__ */ (0,
|
|
8813
|
+
children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
|
|
7614
8814
|
}
|
|
7615
8815
|
);
|
|
7616
8816
|
}
|
|
@@ -7637,8 +8837,8 @@ function OhhwellsBridge() {
|
|
|
7637
8837
|
const router = (0, import_navigation2.useRouter)();
|
|
7638
8838
|
const searchParams = (0, import_navigation2.useSearchParams)();
|
|
7639
8839
|
const isEditMode = isEditSessionActive();
|
|
7640
|
-
const [bridgeRoot, setBridgeRoot] = (0,
|
|
7641
|
-
(0,
|
|
8840
|
+
const [bridgeRoot, setBridgeRoot] = (0, import_react9.useState)(null);
|
|
8841
|
+
(0, import_react9.useEffect)(() => {
|
|
7642
8842
|
const figtreeFontId = "ohw-figtree-font";
|
|
7643
8843
|
if (!document.getElementById(figtreeFontId)) {
|
|
7644
8844
|
const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
|
|
@@ -7666,92 +8866,136 @@ function OhhwellsBridge() {
|
|
|
7666
8866
|
const subdomainFromQuery = searchParams.get("subdomain");
|
|
7667
8867
|
const subdomain = resolveSubdomain(subdomainFromQuery);
|
|
7668
8868
|
useLinkHrefGuardian(pathname, subdomain, isEditMode);
|
|
7669
|
-
const postToParent2 = (0,
|
|
8869
|
+
const postToParent2 = (0, import_react9.useCallback)((data) => {
|
|
7670
8870
|
if (typeof window !== "undefined" && window.parent !== window) {
|
|
7671
8871
|
window.parent.postMessage(data, "*");
|
|
7672
8872
|
}
|
|
7673
8873
|
}, []);
|
|
7674
|
-
const [fetchState, setFetchState] = (0,
|
|
7675
|
-
const autoSaveTimers = (0,
|
|
7676
|
-
const activeElRef = (0,
|
|
7677
|
-
const selectedElRef = (0,
|
|
7678
|
-
const
|
|
7679
|
-
const
|
|
7680
|
-
const
|
|
7681
|
-
const
|
|
7682
|
-
const
|
|
7683
|
-
const
|
|
8874
|
+
const [fetchState, setFetchState] = (0, import_react9.useState)("idle");
|
|
8875
|
+
const autoSaveTimers = (0, import_react9.useRef)(/* @__PURE__ */ new Map());
|
|
8876
|
+
const activeElRef = (0, import_react9.useRef)(null);
|
|
8877
|
+
const selectedElRef = (0, import_react9.useRef)(null);
|
|
8878
|
+
const selectedHrefKeyRef = (0, import_react9.useRef)(null);
|
|
8879
|
+
const selectedFooterColAttrRef = (0, import_react9.useRef)(null);
|
|
8880
|
+
const originalContentRef = (0, import_react9.useRef)(null);
|
|
8881
|
+
const activeStateElRef = (0, import_react9.useRef)(null);
|
|
8882
|
+
const parentScrollRef = (0, import_react9.useRef)(null);
|
|
8883
|
+
const visibleViewportRef = (0, import_react9.useRef)(null);
|
|
8884
|
+
const [dialogPortalContainer, setDialogPortalContainer] = (0, import_react9.useState)(null);
|
|
8885
|
+
const attachVisibleViewport = (0, import_react9.useCallback)((node) => {
|
|
7684
8886
|
visibleViewportRef.current = node;
|
|
7685
8887
|
setDialogPortalContainer(node);
|
|
7686
8888
|
if (node) applyVisibleViewport(node, parentScrollRef.current);
|
|
7687
8889
|
}, []);
|
|
7688
|
-
const toolbarElRef = (0,
|
|
7689
|
-
const glowElRef = (0,
|
|
7690
|
-
const hoveredImageRef = (0,
|
|
7691
|
-
const hoveredImageHasTextOverlapRef = (0,
|
|
7692
|
-
const dragOverElRef = (0,
|
|
7693
|
-
const [mediaHover, setMediaHover] = (0,
|
|
7694
|
-
const [uploadingRects, setUploadingRects] = (0,
|
|
7695
|
-
const hoveredGapRef = (0,
|
|
7696
|
-
const imageUnhoverTimerRef = (0,
|
|
7697
|
-
const imageShowTimerRef = (0,
|
|
7698
|
-
const editStylesRef = (0,
|
|
7699
|
-
const activateRef = (0,
|
|
8890
|
+
const toolbarElRef = (0, import_react9.useRef)(null);
|
|
8891
|
+
const glowElRef = (0, import_react9.useRef)(null);
|
|
8892
|
+
const hoveredImageRef = (0, import_react9.useRef)(null);
|
|
8893
|
+
const hoveredImageHasTextOverlapRef = (0, import_react9.useRef)(false);
|
|
8894
|
+
const dragOverElRef = (0, import_react9.useRef)(null);
|
|
8895
|
+
const [mediaHover, setMediaHover] = (0, import_react9.useState)(null);
|
|
8896
|
+
const [uploadingRects, setUploadingRects] = (0, import_react9.useState)({});
|
|
8897
|
+
const hoveredGapRef = (0, import_react9.useRef)(null);
|
|
8898
|
+
const imageUnhoverTimerRef = (0, import_react9.useRef)(null);
|
|
8899
|
+
const imageShowTimerRef = (0, import_react9.useRef)(null);
|
|
8900
|
+
const editStylesRef = (0, import_react9.useRef)(null);
|
|
8901
|
+
const activateRef = (0, import_react9.useRef)(() => {
|
|
7700
8902
|
});
|
|
7701
|
-
const deactivateRef = (0,
|
|
8903
|
+
const deactivateRef = (0, import_react9.useRef)(() => {
|
|
7702
8904
|
});
|
|
7703
|
-
const selectRef = (0,
|
|
8905
|
+
const selectRef = (0, import_react9.useRef)(() => {
|
|
7704
8906
|
});
|
|
7705
|
-
const selectFrameRef = (0,
|
|
8907
|
+
const selectFrameRef = (0, import_react9.useRef)(() => {
|
|
7706
8908
|
});
|
|
7707
|
-
const deselectRef = (0,
|
|
8909
|
+
const deselectRef = (0, import_react9.useRef)(() => {
|
|
7708
8910
|
});
|
|
7709
|
-
const reselectNavigationItemRef = (0,
|
|
8911
|
+
const reselectNavigationItemRef = (0, import_react9.useRef)(() => {
|
|
7710
8912
|
});
|
|
7711
|
-
const commitNavigationTextEditRef = (0,
|
|
8913
|
+
const commitNavigationTextEditRef = (0, import_react9.useRef)(() => {
|
|
7712
8914
|
});
|
|
7713
|
-
const refreshActiveCommandsRef = (0,
|
|
8915
|
+
const refreshActiveCommandsRef = (0, import_react9.useRef)(() => {
|
|
7714
8916
|
});
|
|
7715
|
-
const postToParentRef = (0,
|
|
8917
|
+
const postToParentRef = (0, import_react9.useRef)(postToParent2);
|
|
7716
8918
|
postToParentRef.current = postToParent2;
|
|
7717
|
-
const sectionsLoadedRef = (0,
|
|
7718
|
-
const pendingScheduleConfigRequests = (0,
|
|
7719
|
-
const [toolbarRect, setToolbarRect] = (0,
|
|
7720
|
-
const [toolbarVariant, setToolbarVariant] = (0,
|
|
7721
|
-
const toolbarVariantRef = (0,
|
|
8919
|
+
const sectionsLoadedRef = (0, import_react9.useRef)(false);
|
|
8920
|
+
const pendingScheduleConfigRequests = (0, import_react9.useRef)([]);
|
|
8921
|
+
const [toolbarRect, setToolbarRect] = (0, import_react9.useState)(null);
|
|
8922
|
+
const [toolbarVariant, setToolbarVariant] = (0, import_react9.useState)("none");
|
|
8923
|
+
const toolbarVariantRef = (0, import_react9.useRef)("none");
|
|
7722
8924
|
toolbarVariantRef.current = toolbarVariant;
|
|
7723
|
-
const [selectedIsCta, setSelectedIsCta] = (0,
|
|
7724
|
-
const [reorderHrefKey, setReorderHrefKey] = (0,
|
|
7725
|
-
const [reorderDragDisabled, setReorderDragDisabled] = (0,
|
|
7726
|
-
const [toggleState, setToggleState] = (0,
|
|
7727
|
-
const [maxBadge, setMaxBadge] = (0,
|
|
7728
|
-
const [activeCommands, setActiveCommands] = (0,
|
|
7729
|
-
const [sectionGap, setSectionGap] = (0,
|
|
7730
|
-
const [toolbarShowEditLink, setToolbarShowEditLink] = (0,
|
|
7731
|
-
const hoveredNavContainerRef = (0,
|
|
7732
|
-
const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0,
|
|
7733
|
-
const hoveredItemElRef = (0,
|
|
7734
|
-
const [hoveredItemRect, setHoveredItemRect] = (0,
|
|
7735
|
-
const siblingHintElRef = (0,
|
|
7736
|
-
const [siblingHintRect, setSiblingHintRect] = (0,
|
|
7737
|
-
const [
|
|
7738
|
-
const [
|
|
7739
|
-
const
|
|
7740
|
-
const
|
|
7741
|
-
const
|
|
7742
|
-
const [
|
|
7743
|
-
const [
|
|
7744
|
-
const
|
|
7745
|
-
const
|
|
7746
|
-
const
|
|
7747
|
-
const
|
|
7748
|
-
const
|
|
8925
|
+
const [selectedIsCta, setSelectedIsCta] = (0, import_react9.useState)(false);
|
|
8926
|
+
const [reorderHrefKey, setReorderHrefKey] = (0, import_react9.useState)(null);
|
|
8927
|
+
const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react9.useState)(false);
|
|
8928
|
+
const [toggleState, setToggleState] = (0, import_react9.useState)(null);
|
|
8929
|
+
const [maxBadge, setMaxBadge] = (0, import_react9.useState)(null);
|
|
8930
|
+
const [activeCommands, setActiveCommands] = (0, import_react9.useState)(/* @__PURE__ */ new Set());
|
|
8931
|
+
const [sectionGap, setSectionGap] = (0, import_react9.useState)(null);
|
|
8932
|
+
const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react9.useState)(false);
|
|
8933
|
+
const hoveredNavContainerRef = (0, import_react9.useRef)(null);
|
|
8934
|
+
const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0, import_react9.useState)(null);
|
|
8935
|
+
const hoveredItemElRef = (0, import_react9.useRef)(null);
|
|
8936
|
+
const [hoveredItemRect, setHoveredItemRect] = (0, import_react9.useState)(null);
|
|
8937
|
+
const siblingHintElRef = (0, import_react9.useRef)(null);
|
|
8938
|
+
const [siblingHintRect, setSiblingHintRect] = (0, import_react9.useState)(null);
|
|
8939
|
+
const [siblingHintRects, setSiblingHintRects] = (0, import_react9.useState)([]);
|
|
8940
|
+
const [isItemDragging, setIsItemDragging] = (0, import_react9.useState)(false);
|
|
8941
|
+
const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react9.useState)(false);
|
|
8942
|
+
const footerDragRef = (0, import_react9.useRef)(null);
|
|
8943
|
+
const [footerDropSlots, setFooterDropSlots] = (0, import_react9.useState)([]);
|
|
8944
|
+
const [activeFooterDropIndex, setActiveFooterDropIndex] = (0, import_react9.useState)(null);
|
|
8945
|
+
const [draggedItemRect, setDraggedItemRect] = (0, import_react9.useState)(null);
|
|
8946
|
+
const footerPointerDragRef = (0, import_react9.useRef)(null);
|
|
8947
|
+
const suppressNextClickRef = (0, import_react9.useRef)(false);
|
|
8948
|
+
const suppressClickUntilRef = (0, import_react9.useRef)(0);
|
|
8949
|
+
const [linkPopover, setLinkPopover] = (0, import_react9.useState)(null);
|
|
8950
|
+
const linkPopoverSessionRef = (0, import_react9.useRef)(null);
|
|
8951
|
+
const addNavAfterAnchorRef = (0, import_react9.useRef)(null);
|
|
8952
|
+
const editContentRef = (0, import_react9.useRef)({});
|
|
8953
|
+
const [sitePages, setSitePages] = (0, import_react9.useState)([]);
|
|
8954
|
+
const [sectionsByPath, setSectionsByPath] = (0, import_react9.useState)({});
|
|
8955
|
+
const sectionsPrefetchGenRef = (0, import_react9.useRef)(0);
|
|
8956
|
+
const setLinkPopoverRef = (0, import_react9.useRef)(setLinkPopover);
|
|
8957
|
+
const linkPopoverPanelRef = (0, import_react9.useRef)(null);
|
|
8958
|
+
const linkPopoverOpenRef = (0, import_react9.useRef)(false);
|
|
8959
|
+
const linkPopoverGraceUntilRef = (0, import_react9.useRef)(0);
|
|
7749
8960
|
setLinkPopoverRef.current = setLinkPopover;
|
|
7750
8961
|
linkPopoverSessionRef.current = linkPopover;
|
|
8962
|
+
const {
|
|
8963
|
+
navDragRef,
|
|
8964
|
+
navDropSlots,
|
|
8965
|
+
activeNavDropIndex,
|
|
8966
|
+
startNavLinkDrag,
|
|
8967
|
+
commitNavDrag,
|
|
8968
|
+
onNavDragOver,
|
|
8969
|
+
armNavPressFromChrome,
|
|
8970
|
+
refreshNavDragVisualsRef
|
|
8971
|
+
} = useNavItemDrag({
|
|
8972
|
+
isEditMode,
|
|
8973
|
+
editContentRef,
|
|
8974
|
+
selectedElRef,
|
|
8975
|
+
activeElRef,
|
|
8976
|
+
footerDragRef,
|
|
8977
|
+
suppressNextClickRef,
|
|
8978
|
+
suppressClickUntilRef,
|
|
8979
|
+
siblingHintElRef,
|
|
8980
|
+
postToParentRef,
|
|
8981
|
+
deselectRef,
|
|
8982
|
+
selectRef,
|
|
8983
|
+
deactivateRef,
|
|
8984
|
+
setLinkPopover: () => setLinkPopover(null),
|
|
8985
|
+
linkPopoverOpenRef,
|
|
8986
|
+
setIsItemDragging,
|
|
8987
|
+
setDraggedItemRect,
|
|
8988
|
+
setSiblingHintRect,
|
|
8989
|
+
setSiblingHintRects,
|
|
8990
|
+
setToolbarRect,
|
|
8991
|
+
getNavigationItemAnchor,
|
|
8992
|
+
isDragHandleDisabled,
|
|
8993
|
+
isNavbarButton: isNavbarButton2
|
|
8994
|
+
});
|
|
7751
8995
|
const bumpLinkPopoverGrace = () => {
|
|
7752
8996
|
linkPopoverGraceUntilRef.current = Date.now() + 350;
|
|
7753
8997
|
};
|
|
7754
|
-
const runSectionsPrefetch = (0,
|
|
8998
|
+
const runSectionsPrefetch = (0, import_react9.useCallback)((pages) => {
|
|
7755
8999
|
if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
|
|
7756
9000
|
const gen = ++sectionsPrefetchGenRef.current;
|
|
7757
9001
|
const paths = pages.map((p) => p.path);
|
|
@@ -7770,10 +9014,24 @@ function OhhwellsBridge() {
|
|
|
7770
9014
|
);
|
|
7771
9015
|
});
|
|
7772
9016
|
}, [isEditMode, pathname]);
|
|
7773
|
-
const runSectionsPrefetchRef = (0,
|
|
9017
|
+
const runSectionsPrefetchRef = (0, import_react9.useRef)(runSectionsPrefetch);
|
|
7774
9018
|
runSectionsPrefetchRef.current = runSectionsPrefetch;
|
|
7775
|
-
(0,
|
|
7776
|
-
if (!linkPopover)
|
|
9019
|
+
(0, import_react9.useEffect)(() => {
|
|
9020
|
+
if (!linkPopover) {
|
|
9021
|
+
document.documentElement.removeAttribute("data-ohw-link-popover-open");
|
|
9022
|
+
return;
|
|
9023
|
+
}
|
|
9024
|
+
document.documentElement.setAttribute("data-ohw-link-popover-open", "");
|
|
9025
|
+
hoveredItemElRef.current = null;
|
|
9026
|
+
setHoveredItemRect(null);
|
|
9027
|
+
hoveredNavContainerRef.current = null;
|
|
9028
|
+
setHoveredNavContainerRect(null);
|
|
9029
|
+
siblingHintElRef.current = null;
|
|
9030
|
+
setSiblingHintRect(null);
|
|
9031
|
+
setSiblingHintRects([]);
|
|
9032
|
+
if (selectedElRef.current || toolbarVariantRef.current !== "none") {
|
|
9033
|
+
deselectRef.current();
|
|
9034
|
+
}
|
|
7777
9035
|
if (hoveredImageRef.current) {
|
|
7778
9036
|
hoveredImageRef.current = null;
|
|
7779
9037
|
hoveredImageHasTextOverlapRef.current = false;
|
|
@@ -7807,7 +9065,7 @@ function OhhwellsBridge() {
|
|
|
7807
9065
|
document.removeEventListener("touchmove", preventBackgroundScroll, scrollOpts);
|
|
7808
9066
|
};
|
|
7809
9067
|
}, [linkPopover, postToParent2]);
|
|
7810
|
-
(0,
|
|
9068
|
+
(0, import_react9.useEffect)(() => {
|
|
7811
9069
|
if (!isEditMode) return;
|
|
7812
9070
|
const useFixtures = shouldUseDevFixtures();
|
|
7813
9071
|
if (useFixtures) {
|
|
@@ -7831,14 +9089,14 @@ function OhhwellsBridge() {
|
|
|
7831
9089
|
if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
|
|
7832
9090
|
return () => window.removeEventListener("message", onSitePages);
|
|
7833
9091
|
}, [isEditMode, postToParent2]);
|
|
7834
|
-
(0,
|
|
9092
|
+
(0, import_react9.useEffect)(() => {
|
|
7835
9093
|
if (!isEditMode || shouldUseDevFixtures()) return;
|
|
7836
9094
|
void loadAllSectionsManifest().then((manifest) => {
|
|
7837
9095
|
if (Object.keys(manifest).length === 0) return;
|
|
7838
9096
|
setSectionsByPath((prev) => ({ ...manifest, ...prev }));
|
|
7839
9097
|
});
|
|
7840
9098
|
}, [isEditMode]);
|
|
7841
|
-
(0,
|
|
9099
|
+
(0, import_react9.useEffect)(() => {
|
|
7842
9100
|
const update = () => {
|
|
7843
9101
|
const el = activeElRef.current ?? selectedElRef.current;
|
|
7844
9102
|
if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
@@ -7862,10 +9120,10 @@ function OhhwellsBridge() {
|
|
|
7862
9120
|
vvp.removeEventListener("resize", update);
|
|
7863
9121
|
};
|
|
7864
9122
|
}, []);
|
|
7865
|
-
const refreshStateRules = (0,
|
|
9123
|
+
const refreshStateRules = (0, import_react9.useCallback)(() => {
|
|
7866
9124
|
editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
|
|
7867
9125
|
}, []);
|
|
7868
|
-
const processConfigRequest = (0,
|
|
9126
|
+
const processConfigRequest = (0, import_react9.useCallback)((insertAfterVal) => {
|
|
7869
9127
|
const tracker = getSectionsTracker();
|
|
7870
9128
|
let entries = [];
|
|
7871
9129
|
try {
|
|
@@ -7888,7 +9146,7 @@ function OhhwellsBridge() {
|
|
|
7888
9146
|
}
|
|
7889
9147
|
window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
|
|
7890
9148
|
}, [isEditMode]);
|
|
7891
|
-
const deactivate = (0,
|
|
9149
|
+
const deactivate = (0, import_react9.useCallback)(() => {
|
|
7892
9150
|
const el = activeElRef.current;
|
|
7893
9151
|
if (!el) return;
|
|
7894
9152
|
const key = el.dataset.ohwKey;
|
|
@@ -7920,19 +9178,23 @@ function OhhwellsBridge() {
|
|
|
7920
9178
|
setToolbarShowEditLink(false);
|
|
7921
9179
|
postToParent2({ type: "ow:exit-edit" });
|
|
7922
9180
|
}, [postToParent2]);
|
|
7923
|
-
const clearSelectedAttr = (0,
|
|
9181
|
+
const clearSelectedAttr = (0, import_react9.useCallback)(() => {
|
|
7924
9182
|
document.querySelectorAll("[data-ohw-selected]").forEach((el) => {
|
|
7925
9183
|
el.removeAttribute("data-ohw-selected");
|
|
7926
9184
|
});
|
|
7927
9185
|
}, []);
|
|
7928
|
-
const deselect = (0,
|
|
9186
|
+
const deselect = (0, import_react9.useCallback)(() => {
|
|
7929
9187
|
clearSelectedAttr();
|
|
7930
9188
|
selectedElRef.current = null;
|
|
9189
|
+
selectedHrefKeyRef.current = null;
|
|
9190
|
+
selectedFooterColAttrRef.current = null;
|
|
7931
9191
|
setSelectedIsCta(false);
|
|
7932
9192
|
setReorderHrefKey(null);
|
|
7933
9193
|
setReorderDragDisabled(false);
|
|
9194
|
+
setIsFooterFrameSelection(false);
|
|
7934
9195
|
siblingHintElRef.current = null;
|
|
7935
9196
|
setSiblingHintRect(null);
|
|
9197
|
+
setSiblingHintRects([]);
|
|
7936
9198
|
setIsItemDragging(false);
|
|
7937
9199
|
hoveredNavContainerRef.current = null;
|
|
7938
9200
|
setHoveredNavContainerRect(null);
|
|
@@ -7941,12 +9203,57 @@ function OhhwellsBridge() {
|
|
|
7941
9203
|
setToolbarVariant("none");
|
|
7942
9204
|
}
|
|
7943
9205
|
}, [clearSelectedAttr]);
|
|
7944
|
-
const markSelected = (0,
|
|
9206
|
+
const markSelected = (0, import_react9.useCallback)((el) => {
|
|
7945
9207
|
clearSelectedAttr();
|
|
7946
9208
|
el.setAttribute("data-ohw-selected", "");
|
|
7947
9209
|
}, [clearSelectedAttr]);
|
|
7948
|
-
const
|
|
9210
|
+
const resolveHrefKeyElement = (0, import_react9.useCallback)((hrefKey) => {
|
|
9211
|
+
if (isFooterHrefKey(hrefKey)) {
|
|
9212
|
+
return document.querySelector(
|
|
9213
|
+
`footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
9214
|
+
);
|
|
9215
|
+
}
|
|
9216
|
+
if (isNavbarHrefKey(hrefKey)) {
|
|
9217
|
+
const desktop = document.querySelector("[data-ohw-nav-container]");
|
|
9218
|
+
const drawer = document.querySelector("[data-ohw-nav-drawer]");
|
|
9219
|
+
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)}"]`);
|
|
9220
|
+
}
|
|
9221
|
+
return document.querySelector(
|
|
9222
|
+
`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
9223
|
+
);
|
|
9224
|
+
}, []);
|
|
9225
|
+
const resyncSelectedNavigationItem = (0, import_react9.useCallback)(() => {
|
|
9226
|
+
const hrefKey = selectedHrefKeyRef.current;
|
|
9227
|
+
if (hrefKey) {
|
|
9228
|
+
const link = resolveHrefKeyElement(hrefKey);
|
|
9229
|
+
if (!link || !isNavigationItem(link)) return;
|
|
9230
|
+
selectedElRef.current = link;
|
|
9231
|
+
const { key, disabled } = getNavigationItemReorderState(link);
|
|
9232
|
+
setReorderHrefKey(key);
|
|
9233
|
+
setReorderDragDisabled(disabled);
|
|
9234
|
+
setIsFooterFrameSelection(false);
|
|
9235
|
+
setToolbarVariant("link-action");
|
|
9236
|
+
setToolbarRect(link.getBoundingClientRect());
|
|
9237
|
+
setSiblingHintRects(collectNavigationItemSiblingHintRects(link));
|
|
9238
|
+
return;
|
|
9239
|
+
}
|
|
9240
|
+
const colAttr = selectedFooterColAttrRef.current;
|
|
9241
|
+
if (colAttr != null) {
|
|
9242
|
+
const column = document.querySelector(`[data-ohw-footer-col="${CSS.escape(colAttr)}"]`) ?? listFooterColumns()[Number(colAttr)] ?? null;
|
|
9243
|
+
if (!column || !isNavigationContainer(column)) return;
|
|
9244
|
+
selectedElRef.current = column;
|
|
9245
|
+
setIsFooterFrameSelection(true);
|
|
9246
|
+
setToolbarVariant("select-frame");
|
|
9247
|
+
setToolbarRect(column.getBoundingClientRect());
|
|
9248
|
+
setSiblingHintRects(
|
|
9249
|
+
listFooterColumns().filter((c) => c !== column).map((c) => c.getBoundingClientRect())
|
|
9250
|
+
);
|
|
9251
|
+
}
|
|
9252
|
+
}, [resolveHrefKeyElement]);
|
|
9253
|
+
const reselectNavigationItem = (0, import_react9.useCallback)((navAnchor) => {
|
|
7949
9254
|
selectedElRef.current = navAnchor;
|
|
9255
|
+
selectedHrefKeyRef.current = navAnchor.getAttribute("data-ohw-href-key");
|
|
9256
|
+
selectedFooterColAttrRef.current = null;
|
|
7950
9257
|
markSelected(navAnchor);
|
|
7951
9258
|
setSelectedIsCta(isNavbarButton2(navAnchor));
|
|
7952
9259
|
const { key, disabled } = getNavigationItemReorderState(navAnchor);
|
|
@@ -7954,10 +9261,11 @@ function OhhwellsBridge() {
|
|
|
7954
9261
|
setReorderDragDisabled(disabled);
|
|
7955
9262
|
setToolbarVariant("link-action");
|
|
7956
9263
|
setToolbarRect(navAnchor.getBoundingClientRect());
|
|
9264
|
+
setSiblingHintRects(collectNavigationItemSiblingHintRects(navAnchor));
|
|
7957
9265
|
setToolbarShowEditLink(false);
|
|
7958
9266
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
7959
9267
|
}, [markSelected]);
|
|
7960
|
-
const commitNavigationTextEdit = (0,
|
|
9268
|
+
const commitNavigationTextEdit = (0, import_react9.useCallback)((navAnchor) => {
|
|
7961
9269
|
const el = activeElRef.current;
|
|
7962
9270
|
if (!el) return;
|
|
7963
9271
|
const key = el.dataset.ohwKey;
|
|
@@ -7967,49 +9275,337 @@ function OhhwellsBridge() {
|
|
|
7967
9275
|
clearTimeout(timer);
|
|
7968
9276
|
autoSaveTimers.current.delete(key);
|
|
7969
9277
|
}
|
|
7970
|
-
const html = sanitizeHtml(el.innerHTML);
|
|
7971
|
-
const original = originalContentRef.current ?? "";
|
|
7972
|
-
if (html !== sanitizeHtml(original)) {
|
|
7973
|
-
postToParent2({ type: "ow:change", nodes: [{ key, text: html }] });
|
|
7974
|
-
const h = document.documentElement.scrollHeight;
|
|
7975
|
-
if (h > 50) postToParent2({ type: "ow:height", height: h });
|
|
9278
|
+
const html = sanitizeHtml(el.innerHTML);
|
|
9279
|
+
const original = originalContentRef.current ?? "";
|
|
9280
|
+
if (html !== sanitizeHtml(original)) {
|
|
9281
|
+
postToParent2({ type: "ow:change", nodes: [{ key, text: html }] });
|
|
9282
|
+
const h = document.documentElement.scrollHeight;
|
|
9283
|
+
if (h > 50) postToParent2({ type: "ow:height", height: h });
|
|
9284
|
+
}
|
|
9285
|
+
}
|
|
9286
|
+
el.removeAttribute("contenteditable");
|
|
9287
|
+
el.removeAttribute("data-ohw-editing");
|
|
9288
|
+
activeElRef.current = null;
|
|
9289
|
+
setMaxBadge(null);
|
|
9290
|
+
setActiveCommands(/* @__PURE__ */ new Set());
|
|
9291
|
+
setToolbarShowEditLink(false);
|
|
9292
|
+
postToParent2({ type: "ow:exit-edit" });
|
|
9293
|
+
reselectNavigationItem(navAnchor);
|
|
9294
|
+
}, [postToParent2, reselectNavigationItem]);
|
|
9295
|
+
const handleAddTopLevelNavItem = (0, import_react9.useCallback)(() => {
|
|
9296
|
+
const items = listNavbarItems();
|
|
9297
|
+
addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
|
|
9298
|
+
deselectRef.current();
|
|
9299
|
+
deactivateRef.current();
|
|
9300
|
+
bumpLinkPopoverGrace();
|
|
9301
|
+
setLinkPopover({
|
|
9302
|
+
key: "__add-nav__",
|
|
9303
|
+
mode: "create",
|
|
9304
|
+
intent: "add-nav"
|
|
9305
|
+
});
|
|
9306
|
+
}, []);
|
|
9307
|
+
const clearFooterDragVisuals = (0, import_react9.useCallback)(() => {
|
|
9308
|
+
footerDragRef.current = null;
|
|
9309
|
+
setSiblingHintRects([]);
|
|
9310
|
+
setFooterDropSlots([]);
|
|
9311
|
+
setActiveFooterDropIndex(null);
|
|
9312
|
+
setDraggedItemRect(null);
|
|
9313
|
+
setIsItemDragging(false);
|
|
9314
|
+
unlockFooterDragInteraction();
|
|
9315
|
+
}, []);
|
|
9316
|
+
const refreshFooterDragVisuals = (0, import_react9.useCallback)((session, activeSlot, clientX, clientY) => {
|
|
9317
|
+
const dragged = session.draggedEl;
|
|
9318
|
+
setDraggedItemRect(dragged.getBoundingClientRect());
|
|
9319
|
+
if (typeof clientX === "number" && typeof clientY === "number") {
|
|
9320
|
+
session.lastClientX = clientX;
|
|
9321
|
+
session.lastClientY = clientY;
|
|
9322
|
+
}
|
|
9323
|
+
session.activeSlot = activeSlot;
|
|
9324
|
+
setSiblingHintRects([]);
|
|
9325
|
+
if (session.kind === "link") {
|
|
9326
|
+
const columns = listFooterColumns();
|
|
9327
|
+
const slots2 = [];
|
|
9328
|
+
columns.forEach((col, i) => {
|
|
9329
|
+
slots2.push(...buildLinkDropSlots(col, i));
|
|
9330
|
+
});
|
|
9331
|
+
setFooterDropSlots(slots2);
|
|
9332
|
+
const activeIdx2 = activeSlot ? slots2.findIndex((s) => s.columnIndex === activeSlot.columnIndex && s.insertIndex === activeSlot.insertIndex) : -1;
|
|
9333
|
+
setActiveFooterDropIndex(activeIdx2 >= 0 ? activeIdx2 : null);
|
|
9334
|
+
return;
|
|
9335
|
+
}
|
|
9336
|
+
const slots = buildColumnDropSlots();
|
|
9337
|
+
setFooterDropSlots(slots);
|
|
9338
|
+
const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
|
|
9339
|
+
setActiveFooterDropIndex(activeIdx >= 0 ? activeIdx : null);
|
|
9340
|
+
}, []);
|
|
9341
|
+
const refreshFooterDragVisualsRef = (0, import_react9.useRef)(refreshFooterDragVisuals);
|
|
9342
|
+
refreshFooterDragVisualsRef.current = refreshFooterDragVisuals;
|
|
9343
|
+
const commitFooterDragRef = (0, import_react9.useRef)(() => {
|
|
9344
|
+
});
|
|
9345
|
+
const beginFooterDragRef = (0, import_react9.useRef)(() => {
|
|
9346
|
+
});
|
|
9347
|
+
const beginFooterDrag = (0, import_react9.useCallback)(
|
|
9348
|
+
(session) => {
|
|
9349
|
+
const rect = session.draggedEl.getBoundingClientRect();
|
|
9350
|
+
session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
|
|
9351
|
+
session.lastClientY = session.lastClientY || rect.top + rect.height / 2;
|
|
9352
|
+
session.activeSlot = session.activeSlot ?? null;
|
|
9353
|
+
footerDragRef.current = session;
|
|
9354
|
+
setIsItemDragging(true);
|
|
9355
|
+
lockFooterDuringDrag();
|
|
9356
|
+
siblingHintElRef.current = null;
|
|
9357
|
+
setSiblingHintRect(null);
|
|
9358
|
+
if (session.wasSelected && selectedElRef.current === session.draggedEl) {
|
|
9359
|
+
setToolbarRect(rect);
|
|
9360
|
+
}
|
|
9361
|
+
const initialSlot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
|
|
9362
|
+
refreshFooterDragVisuals(session, initialSlot, session.lastClientX, session.lastClientY);
|
|
9363
|
+
},
|
|
9364
|
+
[refreshFooterDragVisuals]
|
|
9365
|
+
);
|
|
9366
|
+
beginFooterDragRef.current = beginFooterDrag;
|
|
9367
|
+
const commitFooterDrag = (0, import_react9.useCallback)(
|
|
9368
|
+
(clientX, clientY) => {
|
|
9369
|
+
const session = footerDragRef.current;
|
|
9370
|
+
if (!session) {
|
|
9371
|
+
clearFooterDragVisuals();
|
|
9372
|
+
return;
|
|
9373
|
+
}
|
|
9374
|
+
const x = typeof clientX === "number" && (clientX !== 0 || clientY !== 0) ? clientX : session.lastClientX;
|
|
9375
|
+
const y = typeof clientY === "number" && (clientX !== 0 || clientY !== 0) ? clientY : session.lastClientY;
|
|
9376
|
+
let nextOrder = null;
|
|
9377
|
+
const slot = session.activeSlot ?? (session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(x, y, session.hrefKey) : session.kind === "column" ? hitTestColumnDropSlot(x, y) : null);
|
|
9378
|
+
if (session.kind === "link" && session.hrefKey && slot) {
|
|
9379
|
+
nextOrder = planFooterLinkMove(session.hrefKey, slot.columnIndex, slot.insertIndex);
|
|
9380
|
+
} else if (session.kind === "column" && slot) {
|
|
9381
|
+
nextOrder = planFooterColumnMove(session.sourceColumnIndex, slot.insertIndex);
|
|
9382
|
+
}
|
|
9383
|
+
const wasSelected = session.wasSelected;
|
|
9384
|
+
const draggedEl = session.draggedEl;
|
|
9385
|
+
const hrefKey = session.hrefKey;
|
|
9386
|
+
let movedColumnIndex = null;
|
|
9387
|
+
if (session.kind === "column" && slot && nextOrder) {
|
|
9388
|
+
let adjusted = slot.insertIndex;
|
|
9389
|
+
if (session.sourceColumnIndex < slot.insertIndex) adjusted -= 1;
|
|
9390
|
+
movedColumnIndex = Math.max(0, Math.min(adjusted, nextOrder.length - 1));
|
|
9391
|
+
}
|
|
9392
|
+
const applySelectionAfterDrop = () => {
|
|
9393
|
+
if (!wasSelected) {
|
|
9394
|
+
deselectRef.current();
|
|
9395
|
+
return;
|
|
9396
|
+
}
|
|
9397
|
+
if (hrefKey) {
|
|
9398
|
+
selectedHrefKeyRef.current = hrefKey;
|
|
9399
|
+
selectedFooterColAttrRef.current = null;
|
|
9400
|
+
const link = resolveHrefKeyElement(hrefKey);
|
|
9401
|
+
if (link && isNavigationItem(link)) {
|
|
9402
|
+
selectRef.current(link);
|
|
9403
|
+
return;
|
|
9404
|
+
}
|
|
9405
|
+
}
|
|
9406
|
+
if (movedColumnIndex !== null && nextOrder) {
|
|
9407
|
+
const colKeys = nextOrder[movedColumnIndex] ?? [];
|
|
9408
|
+
let column = null;
|
|
9409
|
+
for (const key of colKeys) {
|
|
9410
|
+
const link = document.querySelector(
|
|
9411
|
+
`footer [data-ohw-href-key="${CSS.escape(key)}"]`
|
|
9412
|
+
);
|
|
9413
|
+
if (link) {
|
|
9414
|
+
column = findFooterColumnForLink(link);
|
|
9415
|
+
if (column) break;
|
|
9416
|
+
}
|
|
9417
|
+
}
|
|
9418
|
+
if (!column) column = listFooterColumns()[movedColumnIndex] ?? null;
|
|
9419
|
+
if (column && isNavigationContainer(column)) {
|
|
9420
|
+
selectFrameRef.current(column);
|
|
9421
|
+
return;
|
|
9422
|
+
}
|
|
9423
|
+
}
|
|
9424
|
+
if (document.body.contains(draggedEl)) {
|
|
9425
|
+
if (isNavigationItem(draggedEl)) {
|
|
9426
|
+
selectRef.current(draggedEl);
|
|
9427
|
+
return;
|
|
9428
|
+
}
|
|
9429
|
+
if (isNavigationContainer(draggedEl)) {
|
|
9430
|
+
selectFrameRef.current(draggedEl);
|
|
9431
|
+
return;
|
|
9432
|
+
}
|
|
9433
|
+
}
|
|
9434
|
+
deselectRef.current();
|
|
9435
|
+
};
|
|
9436
|
+
if (nextOrder) {
|
|
9437
|
+
const orderJson = JSON.stringify(nextOrder);
|
|
9438
|
+
editContentRef.current = {
|
|
9439
|
+
...editContentRef.current,
|
|
9440
|
+
[FOOTER_ORDER_KEY]: orderJson
|
|
9441
|
+
};
|
|
9442
|
+
applyFooterOrder(nextOrder);
|
|
9443
|
+
document.querySelectorAll("footer [data-ohw-href-key]").forEach(disableNativeHrefDrag);
|
|
9444
|
+
postToParentRef.current({
|
|
9445
|
+
type: "ow:change",
|
|
9446
|
+
nodes: [{ key: FOOTER_ORDER_KEY, text: orderJson }]
|
|
9447
|
+
});
|
|
9448
|
+
applySelectionAfterDrop();
|
|
9449
|
+
clearFooterDragVisuals();
|
|
9450
|
+
requestAnimationFrame(() => {
|
|
9451
|
+
if (editContentRef.current[FOOTER_ORDER_KEY] === orderJson) {
|
|
9452
|
+
applyFooterOrder(nextOrder);
|
|
9453
|
+
document.querySelectorAll("footer [data-ohw-href-key]").forEach(disableNativeHrefDrag);
|
|
9454
|
+
}
|
|
9455
|
+
applySelectionAfterDrop();
|
|
9456
|
+
requestAnimationFrame(() => {
|
|
9457
|
+
if (editContentRef.current[FOOTER_ORDER_KEY] === orderJson) {
|
|
9458
|
+
applyFooterOrder(nextOrder);
|
|
9459
|
+
}
|
|
9460
|
+
resyncSelectedNavigationItem();
|
|
9461
|
+
});
|
|
9462
|
+
});
|
|
9463
|
+
return;
|
|
9464
|
+
}
|
|
9465
|
+
applySelectionAfterDrop();
|
|
9466
|
+
clearFooterDragVisuals();
|
|
9467
|
+
},
|
|
9468
|
+
[clearFooterDragVisuals, resolveHrefKeyElement, resyncSelectedNavigationItem]
|
|
9469
|
+
);
|
|
9470
|
+
commitFooterDragRef.current = commitFooterDrag;
|
|
9471
|
+
const startFooterLinkDrag = (0, import_react9.useCallback)(
|
|
9472
|
+
(anchor, clientX, clientY, wasSelected) => {
|
|
9473
|
+
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
9474
|
+
if (!hrefKey || !isFooterHrefKey(hrefKey)) return false;
|
|
9475
|
+
const column = findFooterColumnForLink(anchor);
|
|
9476
|
+
const columns = listFooterColumns();
|
|
9477
|
+
beginFooterDrag({
|
|
9478
|
+
kind: "link",
|
|
9479
|
+
hrefKey,
|
|
9480
|
+
columnEl: column,
|
|
9481
|
+
sourceColumnIndex: column ? columns.indexOf(column) : 0,
|
|
9482
|
+
wasSelected,
|
|
9483
|
+
draggedEl: anchor,
|
|
9484
|
+
lastClientX: clientX,
|
|
9485
|
+
lastClientY: clientY,
|
|
9486
|
+
activeSlot: null
|
|
9487
|
+
});
|
|
9488
|
+
return true;
|
|
9489
|
+
},
|
|
9490
|
+
[beginFooterDrag]
|
|
9491
|
+
);
|
|
9492
|
+
const startFooterColumnDrag = (0, import_react9.useCallback)(
|
|
9493
|
+
(columnEl, clientX, clientY, wasSelected) => {
|
|
9494
|
+
const columns = listFooterColumns();
|
|
9495
|
+
const idx = columns.indexOf(columnEl);
|
|
9496
|
+
if (idx < 0) return false;
|
|
9497
|
+
beginFooterDrag({
|
|
9498
|
+
kind: "column",
|
|
9499
|
+
hrefKey: null,
|
|
9500
|
+
columnEl,
|
|
9501
|
+
sourceColumnIndex: idx,
|
|
9502
|
+
wasSelected,
|
|
9503
|
+
draggedEl: columnEl,
|
|
9504
|
+
lastClientX: clientX,
|
|
9505
|
+
lastClientY: clientY,
|
|
9506
|
+
activeSlot: null
|
|
9507
|
+
});
|
|
9508
|
+
return true;
|
|
9509
|
+
},
|
|
9510
|
+
[beginFooterDrag]
|
|
9511
|
+
);
|
|
9512
|
+
const handleItemDragStart = (0, import_react9.useCallback)(
|
|
9513
|
+
(e) => {
|
|
9514
|
+
const selected = selectedElRef.current;
|
|
9515
|
+
if (!selected) {
|
|
9516
|
+
setIsItemDragging(true);
|
|
9517
|
+
return;
|
|
9518
|
+
}
|
|
9519
|
+
const clientX = e?.clientX ?? selected.getBoundingClientRect().left + 8;
|
|
9520
|
+
const clientY = e?.clientY ?? selected.getBoundingClientRect().top + 8;
|
|
9521
|
+
if (startFooterLinkDrag(selected, clientX, clientY, true)) return;
|
|
9522
|
+
if (selected.hasAttribute("data-ohw-footer-col") || isInferredFooterGroup(selected) && selected.closest("footer")) {
|
|
9523
|
+
if (startFooterColumnDrag(selected, clientX, clientY, true)) return;
|
|
9524
|
+
}
|
|
9525
|
+
if (startNavLinkDrag(selected, clientX, clientY, true)) return;
|
|
9526
|
+
siblingHintElRef.current = null;
|
|
9527
|
+
setSiblingHintRect(null);
|
|
9528
|
+
setIsItemDragging(true);
|
|
9529
|
+
},
|
|
9530
|
+
[startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag]
|
|
9531
|
+
);
|
|
9532
|
+
const handleItemDragEnd = (0, import_react9.useCallback)(
|
|
9533
|
+
(e) => {
|
|
9534
|
+
if (footerDragRef.current) {
|
|
9535
|
+
const x = e?.clientX;
|
|
9536
|
+
const y = e?.clientY;
|
|
9537
|
+
if (typeof x === "number" && typeof y === "number" && (x !== 0 || y !== 0)) {
|
|
9538
|
+
commitFooterDrag(x, y);
|
|
9539
|
+
} else {
|
|
9540
|
+
commitFooterDrag();
|
|
9541
|
+
}
|
|
9542
|
+
return;
|
|
9543
|
+
}
|
|
9544
|
+
if (navDragRef.current) {
|
|
9545
|
+
const x = e?.clientX;
|
|
9546
|
+
const y = e?.clientY;
|
|
9547
|
+
if (typeof x === "number" && typeof y === "number" && (x !== 0 || y !== 0)) {
|
|
9548
|
+
commitNavDrag(x, y);
|
|
9549
|
+
} else {
|
|
9550
|
+
commitNavDrag();
|
|
9551
|
+
}
|
|
9552
|
+
return;
|
|
7976
9553
|
}
|
|
9554
|
+
setIsItemDragging(false);
|
|
9555
|
+
},
|
|
9556
|
+
[commitFooterDrag, commitNavDrag, navDragRef]
|
|
9557
|
+
);
|
|
9558
|
+
const handleItemChromePointerDown = (0, import_react9.useCallback)((e) => {
|
|
9559
|
+
if (e.button !== 0) return;
|
|
9560
|
+
const selected = selectedElRef.current;
|
|
9561
|
+
if (!selected) return;
|
|
9562
|
+
armFooterPressDrag();
|
|
9563
|
+
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
9564
|
+
if (hrefKey && isFooterHrefKey(hrefKey)) {
|
|
9565
|
+
footerPointerDragRef.current = {
|
|
9566
|
+
el: selected,
|
|
9567
|
+
kind: "link",
|
|
9568
|
+
startX: e.clientX,
|
|
9569
|
+
startY: e.clientY,
|
|
9570
|
+
pointerId: e.pointerId,
|
|
9571
|
+
wasSelected: true,
|
|
9572
|
+
started: false
|
|
9573
|
+
};
|
|
9574
|
+
return;
|
|
7977
9575
|
}
|
|
7978
|
-
|
|
7979
|
-
|
|
7980
|
-
|
|
7981
|
-
|
|
7982
|
-
|
|
7983
|
-
|
|
7984
|
-
|
|
7985
|
-
|
|
7986
|
-
|
|
7987
|
-
|
|
7988
|
-
|
|
7989
|
-
|
|
7990
|
-
|
|
7991
|
-
|
|
7992
|
-
|
|
7993
|
-
|
|
7994
|
-
|
|
7995
|
-
|
|
7996
|
-
|
|
7997
|
-
|
|
7998
|
-
|
|
7999
|
-
|
|
8000
|
-
|
|
8001
|
-
|
|
8002
|
-
setIsItemDragging(true);
|
|
8003
|
-
}, []);
|
|
8004
|
-
const handleItemDragEnd = (0, import_react8.useCallback)(() => {
|
|
8005
|
-
setIsItemDragging(false);
|
|
9576
|
+
if (selected.hasAttribute("data-ohw-footer-col") || isInferredFooterGroup(selected) && selected.closest("footer")) {
|
|
9577
|
+
footerPointerDragRef.current = {
|
|
9578
|
+
el: selected,
|
|
9579
|
+
kind: "column",
|
|
9580
|
+
startX: e.clientX,
|
|
9581
|
+
startY: e.clientY,
|
|
9582
|
+
pointerId: e.pointerId,
|
|
9583
|
+
wasSelected: true,
|
|
9584
|
+
started: false
|
|
9585
|
+
};
|
|
9586
|
+
return;
|
|
9587
|
+
}
|
|
9588
|
+
if (armNavPressFromChrome(selected, e.clientX, e.clientY, e.pointerId)) return;
|
|
9589
|
+
}, [armNavPressFromChrome]);
|
|
9590
|
+
const handleItemChromeClick = (0, import_react9.useCallback)((clientX, clientY) => {
|
|
9591
|
+
if (suppressNextClickRef.current || Date.now() < suppressClickUntilRef.current) {
|
|
9592
|
+
suppressNextClickRef.current = false;
|
|
9593
|
+
return;
|
|
9594
|
+
}
|
|
9595
|
+
const selected = selectedElRef.current;
|
|
9596
|
+
if (!selected || !isNavigationItem(selected)) return;
|
|
9597
|
+
const editable = selected.querySelector('[data-ohw-editable="text"]') ?? selected.querySelector("[data-ohw-editable]");
|
|
9598
|
+
if (!editable) return;
|
|
9599
|
+
activateRef.current(editable, { caretX: clientX, caretY: clientY });
|
|
8006
9600
|
}, []);
|
|
8007
9601
|
reselectNavigationItemRef.current = reselectNavigationItem;
|
|
8008
9602
|
commitNavigationTextEditRef.current = commitNavigationTextEdit;
|
|
8009
|
-
const select = (0,
|
|
9603
|
+
const select = (0, import_react9.useCallback)((anchor) => {
|
|
8010
9604
|
if (!isNavigationItem(anchor)) return;
|
|
8011
9605
|
if (activeElRef.current) deactivate();
|
|
8012
9606
|
selectedElRef.current = anchor;
|
|
9607
|
+
selectedHrefKeyRef.current = anchor.getAttribute("data-ohw-href-key");
|
|
9608
|
+
selectedFooterColAttrRef.current = null;
|
|
8013
9609
|
markSelected(anchor);
|
|
8014
9610
|
setSelectedIsCta(isNavbarButton2(anchor));
|
|
8015
9611
|
clearHrefKeyHover(anchor);
|
|
@@ -8019,19 +9615,24 @@ function OhhwellsBridge() {
|
|
|
8019
9615
|
hoveredItemElRef.current = null;
|
|
8020
9616
|
siblingHintElRef.current = null;
|
|
8021
9617
|
setSiblingHintRect(null);
|
|
9618
|
+
setSiblingHintRects(collectNavigationItemSiblingHintRects(anchor));
|
|
8022
9619
|
setIsItemDragging(false);
|
|
8023
9620
|
const { key, disabled } = getNavigationItemReorderState(anchor);
|
|
8024
9621
|
setReorderHrefKey(key);
|
|
8025
9622
|
setReorderDragDisabled(disabled);
|
|
9623
|
+
setIsFooterFrameSelection(false);
|
|
8026
9624
|
setToolbarVariant("link-action");
|
|
8027
9625
|
setToolbarRect(anchor.getBoundingClientRect());
|
|
8028
9626
|
setToolbarShowEditLink(false);
|
|
8029
9627
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
8030
9628
|
}, [deactivate, markSelected]);
|
|
8031
|
-
const selectFrame = (0,
|
|
9629
|
+
const selectFrame = (0, import_react9.useCallback)((el) => {
|
|
8032
9630
|
if (!isNavigationContainer(el)) return;
|
|
8033
9631
|
if (activeElRef.current) deactivate();
|
|
9632
|
+
const isFooterColumn = el.hasAttribute("data-ohw-footer-col") || Boolean(el.closest("footer") && isInferredFooterGroup(el));
|
|
8034
9633
|
selectedElRef.current = el;
|
|
9634
|
+
selectedHrefKeyRef.current = null;
|
|
9635
|
+
selectedFooterColAttrRef.current = isFooterColumn ? el.getAttribute("data-ohw-footer-col") ?? String(listFooterColumns().indexOf(el)) : null;
|
|
8035
9636
|
markSelected(el);
|
|
8036
9637
|
setSelectedIsCta(false);
|
|
8037
9638
|
clearHrefKeyHover(el);
|
|
@@ -8041,18 +9642,24 @@ function OhhwellsBridge() {
|
|
|
8041
9642
|
hoveredItemElRef.current = null;
|
|
8042
9643
|
siblingHintElRef.current = null;
|
|
8043
9644
|
setSiblingHintRect(null);
|
|
9645
|
+
setSiblingHintRects(
|
|
9646
|
+
isFooterColumn ? listFooterColumns().filter((column) => column !== el).map((column) => column.getBoundingClientRect()) : []
|
|
9647
|
+
);
|
|
8044
9648
|
setIsItemDragging(false);
|
|
8045
9649
|
setReorderHrefKey(null);
|
|
8046
9650
|
setReorderDragDisabled(false);
|
|
9651
|
+
setIsFooterFrameSelection(isFooterColumn);
|
|
8047
9652
|
setToolbarVariant("select-frame");
|
|
8048
9653
|
setToolbarRect(el.getBoundingClientRect());
|
|
8049
9654
|
setToolbarShowEditLink(false);
|
|
8050
9655
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
8051
9656
|
}, [deactivate, markSelected]);
|
|
8052
|
-
const activate = (0,
|
|
9657
|
+
const activate = (0, import_react9.useCallback)((el, options) => {
|
|
8053
9658
|
if (activeElRef.current === el) return;
|
|
8054
9659
|
clearSelectedAttr();
|
|
8055
9660
|
selectedElRef.current = null;
|
|
9661
|
+
selectedHrefKeyRef.current = null;
|
|
9662
|
+
selectedFooterColAttrRef.current = null;
|
|
8056
9663
|
setSelectedIsCta(false);
|
|
8057
9664
|
deactivate();
|
|
8058
9665
|
if (hoveredImageRef.current) {
|
|
@@ -8071,7 +9678,11 @@ function OhhwellsBridge() {
|
|
|
8071
9678
|
originalContentRef.current = el.innerHTML;
|
|
8072
9679
|
el.focus({ preventScroll: true });
|
|
8073
9680
|
if (options?.caretX !== void 0 && options?.caretY !== void 0) {
|
|
8074
|
-
|
|
9681
|
+
const { caretX, caretY } = options;
|
|
9682
|
+
placeCaretAtPoint(el, caretX, caretY);
|
|
9683
|
+
requestAnimationFrame(() => {
|
|
9684
|
+
if (activeElRef.current === el) placeCaretAtPoint(el, caretX, caretY);
|
|
9685
|
+
});
|
|
8075
9686
|
} else {
|
|
8076
9687
|
const selection = window.getSelection();
|
|
8077
9688
|
if (selection && selection.rangeCount === 0) {
|
|
@@ -8101,7 +9712,7 @@ function OhhwellsBridge() {
|
|
|
8101
9712
|
selectRef.current = select;
|
|
8102
9713
|
selectFrameRef.current = selectFrame;
|
|
8103
9714
|
deselectRef.current = deselect;
|
|
8104
|
-
(0,
|
|
9715
|
+
(0, import_react9.useLayoutEffect)(() => {
|
|
8105
9716
|
if (!subdomain || isEditMode) {
|
|
8106
9717
|
setFetchState("done");
|
|
8107
9718
|
return;
|
|
@@ -8142,6 +9753,7 @@ function OhhwellsBridge() {
|
|
|
8142
9753
|
applyLinkByKey(key, val);
|
|
8143
9754
|
}
|
|
8144
9755
|
reconcileNavbarItemsFromContent(content);
|
|
9756
|
+
reconcileFooterOrderFromContent(content);
|
|
8145
9757
|
enforceLinkHrefs();
|
|
8146
9758
|
initSectionsFromContent(content, true);
|
|
8147
9759
|
sectionsLoadedRef.current = true;
|
|
@@ -8170,7 +9782,7 @@ function OhhwellsBridge() {
|
|
|
8170
9782
|
cancelled = true;
|
|
8171
9783
|
};
|
|
8172
9784
|
}, [subdomain, isEditMode]);
|
|
8173
|
-
(0,
|
|
9785
|
+
(0, import_react9.useEffect)(() => {
|
|
8174
9786
|
if (!subdomain || isEditMode) return;
|
|
8175
9787
|
let debounceTimer = null;
|
|
8176
9788
|
let observer = null;
|
|
@@ -8202,6 +9814,7 @@ function OhhwellsBridge() {
|
|
|
8202
9814
|
applyLinkByKey(key, val);
|
|
8203
9815
|
}
|
|
8204
9816
|
reconcileNavbarItemsFromContent(content);
|
|
9817
|
+
reconcileFooterOrderFromContent(content);
|
|
8205
9818
|
} finally {
|
|
8206
9819
|
observer?.observe(document.body, { childList: true, subtree: true });
|
|
8207
9820
|
}
|
|
@@ -8219,16 +9832,16 @@ function OhhwellsBridge() {
|
|
|
8219
9832
|
if (debounceTimer) clearTimeout(debounceTimer);
|
|
8220
9833
|
};
|
|
8221
9834
|
}, [subdomain, isEditMode, pathname]);
|
|
8222
|
-
(0,
|
|
9835
|
+
(0, import_react9.useLayoutEffect)(() => {
|
|
8223
9836
|
const el = document.getElementById("ohw-loader");
|
|
8224
9837
|
if (!el) return;
|
|
8225
9838
|
const visible = Boolean(subdomain) && fetchState !== "done";
|
|
8226
9839
|
el.style.display = visible ? "flex" : "none";
|
|
8227
9840
|
}, [subdomain, fetchState]);
|
|
8228
|
-
(0,
|
|
9841
|
+
(0, import_react9.useEffect)(() => {
|
|
8229
9842
|
postToParent2({ type: "ow:navigation", path: pathname });
|
|
8230
9843
|
}, [pathname, postToParent2]);
|
|
8231
|
-
(0,
|
|
9844
|
+
(0, import_react9.useEffect)(() => {
|
|
8232
9845
|
if (!isEditMode) return;
|
|
8233
9846
|
if (linkPopoverSessionRef.current?.intent === "add-nav") return;
|
|
8234
9847
|
if (document.querySelector("[data-ohw-section-picker]")) return;
|
|
@@ -8236,7 +9849,7 @@ function OhhwellsBridge() {
|
|
|
8236
9849
|
deselectRef.current();
|
|
8237
9850
|
deactivateRef.current();
|
|
8238
9851
|
}, [pathname, isEditMode]);
|
|
8239
|
-
(0,
|
|
9852
|
+
(0, import_react9.useEffect)(() => {
|
|
8240
9853
|
const contentForNav = () => {
|
|
8241
9854
|
if (isEditMode) return editContentRef.current;
|
|
8242
9855
|
if (!subdomain) return {};
|
|
@@ -8248,6 +9861,7 @@ function OhhwellsBridge() {
|
|
|
8248
9861
|
const roots = observeRoots();
|
|
8249
9862
|
if (roots.length === 0) {
|
|
8250
9863
|
reconcileNavbarItemsFromContent(contentForNav());
|
|
9864
|
+
reconcileFooterOrderFromContent(contentForNav());
|
|
8251
9865
|
if (isEditMode) syncNavigationDragCursorAttrs();
|
|
8252
9866
|
return;
|
|
8253
9867
|
}
|
|
@@ -8260,11 +9874,26 @@ function OhhwellsBridge() {
|
|
|
8260
9874
|
}
|
|
8261
9875
|
};
|
|
8262
9876
|
const run = () => {
|
|
8263
|
-
if (applying) return;
|
|
9877
|
+
if (footerDragRef.current || navDragRef.current || applying) return;
|
|
8264
9878
|
applying = true;
|
|
8265
9879
|
observer?.disconnect();
|
|
8266
9880
|
try {
|
|
8267
|
-
|
|
9881
|
+
const content = contentForNav();
|
|
9882
|
+
reconcileNavbarItemsFromContent(content);
|
|
9883
|
+
reconcileFooterOrderFromContent(content);
|
|
9884
|
+
document.querySelectorAll("footer [data-ohw-href-key]").forEach((el) => {
|
|
9885
|
+
if (isFooterHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
9886
|
+
disableNativeHrefDrag(el);
|
|
9887
|
+
}
|
|
9888
|
+
});
|
|
9889
|
+
document.querySelectorAll(
|
|
9890
|
+
"nav [data-ohw-href-key], [data-ohw-nav-container] [data-ohw-href-key], [data-ohw-nav-drawer] [data-ohw-href-key]"
|
|
9891
|
+
).forEach((el) => {
|
|
9892
|
+
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
9893
|
+
disableNativeHrefDrag(el);
|
|
9894
|
+
}
|
|
9895
|
+
});
|
|
9896
|
+
resyncSelectedNavigationItem();
|
|
8268
9897
|
if (isEditMode) syncNavigationDragCursorAttrs();
|
|
8269
9898
|
} finally {
|
|
8270
9899
|
applying = false;
|
|
@@ -8284,8 +9913,8 @@ function OhhwellsBridge() {
|
|
|
8284
9913
|
if (rafId != null) cancelAnimationFrame(rafId);
|
|
8285
9914
|
observer?.disconnect();
|
|
8286
9915
|
};
|
|
8287
|
-
}, [isEditMode, pathname, subdomain, fetchState]);
|
|
8288
|
-
(0,
|
|
9916
|
+
}, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
|
|
9917
|
+
(0, import_react9.useEffect)(() => {
|
|
8289
9918
|
if (!isEditMode) return;
|
|
8290
9919
|
const measure = () => {
|
|
8291
9920
|
const h = document.body.scrollHeight;
|
|
@@ -8309,7 +9938,7 @@ function OhhwellsBridge() {
|
|
|
8309
9938
|
window.removeEventListener("resize", handleResize);
|
|
8310
9939
|
};
|
|
8311
9940
|
}, [pathname, isEditMode, postToParent2]);
|
|
8312
|
-
(0,
|
|
9941
|
+
(0, import_react9.useEffect)(() => {
|
|
8313
9942
|
if (!subdomainFromQuery || isEditMode) return;
|
|
8314
9943
|
const handleClick = (e) => {
|
|
8315
9944
|
const anchor = e.target.closest("a");
|
|
@@ -8325,7 +9954,7 @@ function OhhwellsBridge() {
|
|
|
8325
9954
|
document.addEventListener("click", handleClick, true);
|
|
8326
9955
|
return () => document.removeEventListener("click", handleClick, true);
|
|
8327
9956
|
}, [subdomainFromQuery, isEditMode, router]);
|
|
8328
|
-
(0,
|
|
9957
|
+
(0, import_react9.useEffect)(() => {
|
|
8329
9958
|
if (!isEditMode) {
|
|
8330
9959
|
editStylesRef.current?.base.remove();
|
|
8331
9960
|
editStylesRef.current?.forceHover.remove();
|
|
@@ -8387,6 +10016,21 @@ function OhhwellsBridge() {
|
|
|
8387
10016
|
outline: none !important;
|
|
8388
10017
|
outline-offset: 0 !important;
|
|
8389
10018
|
}
|
|
10019
|
+
/* Editor chrome owns selection \u2014 suppress native focus rings on nav/footer items. */
|
|
10020
|
+
nav [data-ohw-href-key]:focus,
|
|
10021
|
+
nav [data-ohw-href-key]:focus-visible,
|
|
10022
|
+
nav [data-ohw-href-key]:focus-within,
|
|
10023
|
+
footer [data-ohw-href-key]:focus,
|
|
10024
|
+
footer [data-ohw-href-key]:focus-visible,
|
|
10025
|
+
footer [data-ohw-href-key]:focus-within,
|
|
10026
|
+
nav [data-ohw-href-key] [data-ohw-editable]:focus,
|
|
10027
|
+
nav [data-ohw-href-key] [data-ohw-editable]:focus-visible,
|
|
10028
|
+
footer [data-ohw-href-key] [data-ohw-editable]:focus,
|
|
10029
|
+
footer [data-ohw-href-key] [data-ohw-editable]:focus-visible {
|
|
10030
|
+
outline: none !important;
|
|
10031
|
+
outline-offset: 0 !important;
|
|
10032
|
+
box-shadow: none !important;
|
|
10033
|
+
}
|
|
8390
10034
|
/* Text edit wins over grab/default (must beat [data-ohw-can-drag] *). */
|
|
8391
10035
|
[data-ohw-editing],
|
|
8392
10036
|
[data-ohw-editing] *,
|
|
@@ -8428,12 +10072,39 @@ function OhhwellsBridge() {
|
|
|
8428
10072
|
syncNavigationDragCursorAttrs();
|
|
8429
10073
|
refreshStateRules();
|
|
8430
10074
|
const handleClick = (e) => {
|
|
10075
|
+
if (suppressNextClickRef.current || Date.now() < suppressClickUntilRef.current) {
|
|
10076
|
+
suppressNextClickRef.current = false;
|
|
10077
|
+
e.preventDefault();
|
|
10078
|
+
e.stopPropagation();
|
|
10079
|
+
return;
|
|
10080
|
+
}
|
|
8431
10081
|
const target = e.target;
|
|
8432
10082
|
if (target.closest("[data-ohw-toolbar]")) return;
|
|
8433
10083
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
8434
10084
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
8435
10085
|
if (isInsideLinkEditor(target)) return;
|
|
8436
10086
|
if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
10087
|
+
if (target.closest("[data-ohw-item-drag-surface]")) {
|
|
10088
|
+
e.preventDefault();
|
|
10089
|
+
e.stopPropagation();
|
|
10090
|
+
const selected = selectedElRef.current;
|
|
10091
|
+
if (selected && isNavigationItem(selected)) {
|
|
10092
|
+
const editable2 = selected.querySelector('[data-ohw-editable="text"]') ?? selected.querySelector("[data-ohw-editable]");
|
|
10093
|
+
if (editable2) {
|
|
10094
|
+
activateRef.current(editable2, {
|
|
10095
|
+
caretX: e.clientX,
|
|
10096
|
+
caretY: e.clientY
|
|
10097
|
+
});
|
|
10098
|
+
}
|
|
10099
|
+
} else if (selected?.hasAttribute("data-ohw-footer-col")) {
|
|
10100
|
+
const link = listFooterLinksInColumn(selected).find((el) => {
|
|
10101
|
+
const r2 = el.getBoundingClientRect();
|
|
10102
|
+
return e.clientX >= r2.left && e.clientX <= r2.right && e.clientY >= r2.top && e.clientY <= r2.bottom;
|
|
10103
|
+
});
|
|
10104
|
+
if (link) selectRef.current(link);
|
|
10105
|
+
}
|
|
10106
|
+
return;
|
|
10107
|
+
}
|
|
8437
10108
|
const navFromChrome = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
|
|
8438
10109
|
if (navFromChrome) {
|
|
8439
10110
|
e.preventDefault();
|
|
@@ -8512,10 +10183,26 @@ function OhhwellsBridge() {
|
|
|
8512
10183
|
if (hrefAnchor) {
|
|
8513
10184
|
e.preventDefault();
|
|
8514
10185
|
e.stopPropagation();
|
|
8515
|
-
if (selectedElRef.current === hrefAnchor)
|
|
10186
|
+
if (selectedElRef.current === hrefAnchor) {
|
|
10187
|
+
const textEditable = hrefAnchor.querySelector('[data-ohw-editable="text"]') ?? hrefAnchor.querySelector("[data-ohw-editable]");
|
|
10188
|
+
if (textEditable) {
|
|
10189
|
+
activateRef.current(textEditable, {
|
|
10190
|
+
caretX: e.clientX,
|
|
10191
|
+
caretY: e.clientY
|
|
10192
|
+
});
|
|
10193
|
+
}
|
|
10194
|
+
return;
|
|
10195
|
+
}
|
|
8516
10196
|
selectRef.current(hrefAnchor);
|
|
8517
10197
|
return;
|
|
8518
10198
|
}
|
|
10199
|
+
const footerColClick = target.closest("[data-ohw-footer-col]");
|
|
10200
|
+
if (footerColClick) {
|
|
10201
|
+
e.preventDefault();
|
|
10202
|
+
e.stopPropagation();
|
|
10203
|
+
selectFrameRef.current(footerColClick);
|
|
10204
|
+
return;
|
|
10205
|
+
}
|
|
8519
10206
|
const navContainerToSelect = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
|
|
8520
10207
|
if (navContainerToSelect) {
|
|
8521
10208
|
e.preventDefault();
|
|
@@ -8589,16 +10276,23 @@ function OhhwellsBridge() {
|
|
|
8589
10276
|
const handleMouseOver = (e) => {
|
|
8590
10277
|
if (document.documentElement.hasAttribute("data-ohw-section-picking")) return;
|
|
8591
10278
|
const target = e.target;
|
|
10279
|
+
if (linkPopoverOpenRef.current) {
|
|
10280
|
+
hoveredItemElRef.current = null;
|
|
10281
|
+
setHoveredItemRect(null);
|
|
10282
|
+
hoveredNavContainerRef.current = null;
|
|
10283
|
+
setHoveredNavContainerRect(null);
|
|
10284
|
+
return;
|
|
10285
|
+
}
|
|
8592
10286
|
if (toolbarVariantRef.current !== "select-frame") {
|
|
8593
|
-
const
|
|
8594
|
-
if (
|
|
8595
|
-
hoveredNavContainerRef.current =
|
|
8596
|
-
setHoveredNavContainerRect(
|
|
10287
|
+
const navContainer = target.closest("[data-ohw-nav-container]");
|
|
10288
|
+
if (navContainer && !getNavigationItemAnchor(target)) {
|
|
10289
|
+
hoveredNavContainerRef.current = navContainer;
|
|
10290
|
+
setHoveredNavContainerRect(navContainer.getBoundingClientRect());
|
|
8597
10291
|
hoveredItemElRef.current = null;
|
|
8598
10292
|
setHoveredItemRect(null);
|
|
8599
10293
|
return;
|
|
8600
10294
|
}
|
|
8601
|
-
if (!target.closest("[data-ohw-nav-container]
|
|
10295
|
+
if (!target.closest("[data-ohw-nav-container]")) {
|
|
8602
10296
|
hoveredNavContainerRef.current = null;
|
|
8603
10297
|
setHoveredNavContainerRect(null);
|
|
8604
10298
|
}
|
|
@@ -8608,12 +10302,21 @@ function OhhwellsBridge() {
|
|
|
8608
10302
|
hoveredNavContainerRef.current = null;
|
|
8609
10303
|
setHoveredNavContainerRect(null);
|
|
8610
10304
|
const selected2 = selectedElRef.current;
|
|
8611
|
-
if (selected2 === navAnchor
|
|
10305
|
+
if (selected2 === navAnchor) return;
|
|
8612
10306
|
clearHrefKeyHover(navAnchor);
|
|
8613
10307
|
hoveredItemElRef.current = navAnchor;
|
|
8614
10308
|
setHoveredItemRect(navAnchor.getBoundingClientRect());
|
|
8615
10309
|
return;
|
|
8616
10310
|
}
|
|
10311
|
+
const footerCol = target.closest("[data-ohw-footer-col]") ?? target.closest("[data-ohw-footer-column]");
|
|
10312
|
+
if (footerCol) {
|
|
10313
|
+
hoveredNavContainerRef.current = null;
|
|
10314
|
+
setHoveredNavContainerRect(null);
|
|
10315
|
+
if (selectedElRef.current === footerCol) return;
|
|
10316
|
+
hoveredItemElRef.current = footerCol;
|
|
10317
|
+
setHoveredItemRect(footerCol.getBoundingClientRect());
|
|
10318
|
+
return;
|
|
10319
|
+
}
|
|
8617
10320
|
const editable = target.closest("[data-ohw-editable]");
|
|
8618
10321
|
if (!editable) return;
|
|
8619
10322
|
const selected = selectedElRef.current;
|
|
@@ -8631,14 +10334,25 @@ function OhhwellsBridge() {
|
|
|
8631
10334
|
};
|
|
8632
10335
|
const handleMouseOut = (e) => {
|
|
8633
10336
|
const target = e.target;
|
|
8634
|
-
if (target.closest("[data-ohw-nav-container], [data-ohw-footer-column]")) {
|
|
10337
|
+
if (target.closest("[data-ohw-nav-container], [data-ohw-footer-col], [data-ohw-footer-column]")) {
|
|
8635
10338
|
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
8636
|
-
if (related2?.closest("[data-ohw-nav-container], [data-ohw-footer-column], [data-ohw-navbar-container-chrome], [data-ohw-navbar-add-button]")) {
|
|
10339
|
+
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]")) {
|
|
8637
10340
|
return;
|
|
8638
10341
|
}
|
|
8639
10342
|
hoveredNavContainerRef.current = null;
|
|
8640
10343
|
setHoveredNavContainerRect(null);
|
|
8641
10344
|
}
|
|
10345
|
+
const footerCol = target.closest("[data-ohw-footer-col]") ?? target.closest("[data-ohw-footer-column]");
|
|
10346
|
+
if (footerCol && hoveredItemElRef.current === footerCol) {
|
|
10347
|
+
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
10348
|
+
if (related2?.closest("[data-ohw-drag-handle-container], [data-ohw-item-interaction]")) return;
|
|
10349
|
+
if (related2?.closest("[data-ohw-footer-col], [data-ohw-footer-column]") === footerCol) {
|
|
10350
|
+
return;
|
|
10351
|
+
}
|
|
10352
|
+
hoveredItemElRef.current = null;
|
|
10353
|
+
setHoveredItemRect(null);
|
|
10354
|
+
return;
|
|
10355
|
+
}
|
|
8642
10356
|
const navAnchor = getNavigationItemAnchor(target);
|
|
8643
10357
|
if (navAnchor) {
|
|
8644
10358
|
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
@@ -8772,14 +10486,12 @@ function OhhwellsBridge() {
|
|
|
8772
10486
|
if (toolbarVariantRef.current === "select-frame") {
|
|
8773
10487
|
hoveredNavContainerRef.current = null;
|
|
8774
10488
|
setHoveredNavContainerRect(null);
|
|
8775
|
-
return;
|
|
8776
10489
|
}
|
|
8777
|
-
const
|
|
8778
|
-
|
|
8779
|
-
|
|
8780
|
-
|
|
8781
|
-
|
|
8782
|
-
for (const container of frameContainers) {
|
|
10490
|
+
const navContainers = Array.from(
|
|
10491
|
+
document.querySelectorAll("[data-ohw-nav-container]")
|
|
10492
|
+
);
|
|
10493
|
+
const footerColumns = listFooterColumns();
|
|
10494
|
+
for (const container of [...navContainers, ...footerColumns]) {
|
|
8783
10495
|
const containerRect = container.getBoundingClientRect();
|
|
8784
10496
|
const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
|
|
8785
10497
|
if (!overContainer) continue;
|
|
@@ -8794,25 +10506,55 @@ function OhhwellsBridge() {
|
|
|
8794
10506
|
hoveredNavContainerRef.current = null;
|
|
8795
10507
|
setHoveredNavContainerRect(null);
|
|
8796
10508
|
const selected = selectedElRef.current;
|
|
8797
|
-
if (selected !== navItemHit
|
|
10509
|
+
if (selected !== navItemHit) {
|
|
8798
10510
|
clearHrefKeyHover(navItemHit);
|
|
8799
10511
|
hoveredItemElRef.current = navItemHit;
|
|
8800
10512
|
setHoveredItemRect(navItemHit.getBoundingClientRect());
|
|
10513
|
+
} else if (hoveredItemElRef.current === navItemHit) {
|
|
10514
|
+
hoveredItemElRef.current = null;
|
|
10515
|
+
setHoveredItemRect(null);
|
|
8801
10516
|
}
|
|
8802
10517
|
return;
|
|
8803
10518
|
}
|
|
8804
|
-
overFrame = container;
|
|
8805
|
-
break;
|
|
8806
10519
|
}
|
|
8807
|
-
if (
|
|
10520
|
+
if (toolbarVariantRef.current !== "select-frame") {
|
|
10521
|
+
for (const container of navContainers) {
|
|
10522
|
+
const containerRect = container.getBoundingClientRect();
|
|
10523
|
+
const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
|
|
10524
|
+
if (!overContainer) continue;
|
|
10525
|
+
if (isPointOverNavItem(container, x, y)) continue;
|
|
10526
|
+
hoveredNavContainerRef.current = container;
|
|
10527
|
+
setHoveredNavContainerRect(container.getBoundingClientRect());
|
|
10528
|
+
hoveredItemElRef.current = null;
|
|
10529
|
+
setHoveredItemRect(null);
|
|
10530
|
+
return;
|
|
10531
|
+
}
|
|
10532
|
+
hoveredNavContainerRef.current = null;
|
|
10533
|
+
setHoveredNavContainerRect(null);
|
|
10534
|
+
} else {
|
|
8808
10535
|
hoveredNavContainerRef.current = null;
|
|
8809
10536
|
setHoveredNavContainerRect(null);
|
|
10537
|
+
}
|
|
10538
|
+
for (const column of footerColumns) {
|
|
10539
|
+
const containerRect = column.getBoundingClientRect();
|
|
10540
|
+
const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
|
|
10541
|
+
if (!overContainer) continue;
|
|
10542
|
+
if (isPointOverNavItem(column, x, y)) continue;
|
|
10543
|
+
if (selectedElRef.current === column) {
|
|
10544
|
+
if (hoveredItemElRef.current === column) {
|
|
10545
|
+
hoveredItemElRef.current = null;
|
|
10546
|
+
setHoveredItemRect(null);
|
|
10547
|
+
}
|
|
10548
|
+
return;
|
|
10549
|
+
}
|
|
10550
|
+
hoveredItemElRef.current = column;
|
|
10551
|
+
setHoveredItemRect(column.getBoundingClientRect());
|
|
8810
10552
|
return;
|
|
8811
10553
|
}
|
|
8812
|
-
|
|
8813
|
-
|
|
8814
|
-
|
|
8815
|
-
|
|
10554
|
+
if (hoveredItemElRef.current?.hasAttribute("data-ohw-footer-col") || hoveredItemElRef.current?.hasAttribute("data-ohw-footer-column")) {
|
|
10555
|
+
hoveredItemElRef.current = null;
|
|
10556
|
+
setHoveredItemRect(null);
|
|
10557
|
+
}
|
|
8816
10558
|
};
|
|
8817
10559
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
8818
10560
|
if (linkPopoverOpenRef.current) {
|
|
@@ -8833,6 +10575,10 @@ function OhhwellsBridge() {
|
|
|
8833
10575
|
}
|
|
8834
10576
|
hoveredNavContainerRef.current = null;
|
|
8835
10577
|
setHoveredNavContainerRect(null);
|
|
10578
|
+
if (hoveredItemElRef.current?.hasAttribute("data-ohw-footer-col") || hoveredItemElRef.current?.hasAttribute("data-ohw-footer-column")) {
|
|
10579
|
+
hoveredItemElRef.current = null;
|
|
10580
|
+
setHoveredItemRect(null);
|
|
10581
|
+
}
|
|
8836
10582
|
const toggleEl = document.querySelector("[data-ohw-state-toggle]");
|
|
8837
10583
|
if (toggleEl) {
|
|
8838
10584
|
const tr = toggleEl.getBoundingClientRect();
|
|
@@ -9080,6 +10826,15 @@ function OhhwellsBridge() {
|
|
|
9080
10826
|
probeHoverCardsAt(clientX, clientY);
|
|
9081
10827
|
};
|
|
9082
10828
|
const handleDragOver = (e) => {
|
|
10829
|
+
const footerSession = footerDragRef.current;
|
|
10830
|
+
if (footerSession) {
|
|
10831
|
+
e.preventDefault();
|
|
10832
|
+
if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
|
|
10833
|
+
const slot = footerSession.kind === "link" && footerSession.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, footerSession.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
|
|
10834
|
+
refreshFooterDragVisualsRef.current(footerSession, slot, e.clientX, e.clientY);
|
|
10835
|
+
return;
|
|
10836
|
+
}
|
|
10837
|
+
if (onNavDragOver(e)) return;
|
|
9083
10838
|
e.preventDefault();
|
|
9084
10839
|
const el = findImageAtPoint(e.clientX, e.clientY, false);
|
|
9085
10840
|
if (!el) {
|
|
@@ -9443,6 +11198,26 @@ function OhhwellsBridge() {
|
|
|
9443
11198
|
if (siblingHintElRef.current) {
|
|
9444
11199
|
setSiblingHintRect(siblingHintElRef.current.getBoundingClientRect());
|
|
9445
11200
|
}
|
|
11201
|
+
const selected = selectedElRef.current;
|
|
11202
|
+
if (selected && !footerDragRef.current && !navDragRef.current) {
|
|
11203
|
+
if (selected.hasAttribute("data-ohw-footer-col") || Boolean(selected.closest("footer") && isInferredFooterGroup(selected))) {
|
|
11204
|
+
setSiblingHintRects(
|
|
11205
|
+
listFooterColumns().filter((column) => column !== selected).map((column) => column.getBoundingClientRect())
|
|
11206
|
+
);
|
|
11207
|
+
} else if (isNavigationItem(selected)) {
|
|
11208
|
+
setSiblingHintRects(collectNavigationItemSiblingHintRects(selected));
|
|
11209
|
+
}
|
|
11210
|
+
}
|
|
11211
|
+
if (footerDragRef.current) {
|
|
11212
|
+
const session = footerDragRef.current;
|
|
11213
|
+
const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
|
|
11214
|
+
refreshFooterDragVisualsRef.current(session, slot, session.lastClientX, session.lastClientY);
|
|
11215
|
+
}
|
|
11216
|
+
if (navDragRef.current) {
|
|
11217
|
+
const session = navDragRef.current;
|
|
11218
|
+
const slot = hitTestNavDropSlot(session.lastClientX, session.lastClientY, session.hrefKey);
|
|
11219
|
+
refreshNavDragVisualsRef.current(session, slot, session.lastClientX, session.lastClientY);
|
|
11220
|
+
}
|
|
9446
11221
|
if (hoveredImageRef.current) {
|
|
9447
11222
|
const el = hoveredImageRef.current;
|
|
9448
11223
|
const r2 = el.getBoundingClientRect();
|
|
@@ -9453,7 +11228,7 @@ function OhhwellsBridge() {
|
|
|
9453
11228
|
};
|
|
9454
11229
|
const handleSave = (e) => {
|
|
9455
11230
|
if (e.data?.type !== "ow:save") return;
|
|
9456
|
-
const nodes = collectEditableNodes();
|
|
11231
|
+
const nodes = collectEditableNodes(editContentRef.current);
|
|
9457
11232
|
const tracker = document.querySelector("[data-ohw-sections-tracker]");
|
|
9458
11233
|
if (tracker?.textContent) nodes.push({ key: "__ohw_sections", type: "sections", text: tracker.textContent });
|
|
9459
11234
|
postToParentRef.current({ type: "ow:save-result", nodes });
|
|
@@ -9676,7 +11451,7 @@ function OhhwellsBridge() {
|
|
|
9676
11451
|
}
|
|
9677
11452
|
}
|
|
9678
11453
|
const footerColumn = findHoveredNavOrFooterContainer(clientX, clientY);
|
|
9679
|
-
if (footerColumn?.hasAttribute("data-ohw-footer-column")) {
|
|
11454
|
+
if (footerColumn?.hasAttribute("data-ohw-footer-col") || footerColumn?.hasAttribute("data-ohw-footer-column")) {
|
|
9680
11455
|
selectFrameRef.current(footerColumn);
|
|
9681
11456
|
return;
|
|
9682
11457
|
}
|
|
@@ -9751,7 +11526,161 @@ function OhhwellsBridge() {
|
|
|
9751
11526
|
if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
|
|
9752
11527
|
};
|
|
9753
11528
|
}, [isEditMode, refreshStateRules]);
|
|
9754
|
-
(0,
|
|
11529
|
+
(0, import_react9.useEffect)(() => {
|
|
11530
|
+
if (!isEditMode) return;
|
|
11531
|
+
const THRESHOLD = 10;
|
|
11532
|
+
const resolveWasSelected = (el) => {
|
|
11533
|
+
if (selectedElRef.current === el) return true;
|
|
11534
|
+
const activeAnchor = activeElRef.current ? getNavigationItemAnchor(activeElRef.current) : null;
|
|
11535
|
+
return activeAnchor === el;
|
|
11536
|
+
};
|
|
11537
|
+
const onPointerDown = (e) => {
|
|
11538
|
+
if (e.button !== 0) return;
|
|
11539
|
+
if (suppressNextClickRef.current && Date.now() >= suppressClickUntilRef.current && !footerDragRef.current && !footerPointerDragRef.current?.started) {
|
|
11540
|
+
suppressNextClickRef.current = false;
|
|
11541
|
+
}
|
|
11542
|
+
if (footerDragRef.current) return;
|
|
11543
|
+
const target = e.target;
|
|
11544
|
+
if (!target) return;
|
|
11545
|
+
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]')) {
|
|
11546
|
+
return;
|
|
11547
|
+
}
|
|
11548
|
+
if (target.closest("[data-ohw-item-drag-surface]")) return;
|
|
11549
|
+
const anchor = getNavigationItemAnchor(target);
|
|
11550
|
+
const hrefKey = anchor?.getAttribute("data-ohw-href-key") ?? null;
|
|
11551
|
+
if (anchor && isFooterHrefKey(hrefKey)) {
|
|
11552
|
+
armFooterPressDrag();
|
|
11553
|
+
footerPointerDragRef.current = {
|
|
11554
|
+
el: anchor,
|
|
11555
|
+
kind: "link",
|
|
11556
|
+
startX: e.clientX,
|
|
11557
|
+
startY: e.clientY,
|
|
11558
|
+
pointerId: e.pointerId,
|
|
11559
|
+
wasSelected: resolveWasSelected(anchor),
|
|
11560
|
+
started: false
|
|
11561
|
+
};
|
|
11562
|
+
return;
|
|
11563
|
+
}
|
|
11564
|
+
const col = target.closest("[data-ohw-footer-col]");
|
|
11565
|
+
if (col && !getNavigationItemAnchor(target)) {
|
|
11566
|
+
armFooterPressDrag();
|
|
11567
|
+
footerPointerDragRef.current = {
|
|
11568
|
+
el: col,
|
|
11569
|
+
kind: "column",
|
|
11570
|
+
startX: e.clientX,
|
|
11571
|
+
startY: e.clientY,
|
|
11572
|
+
pointerId: e.pointerId,
|
|
11573
|
+
wasSelected: resolveWasSelected(col),
|
|
11574
|
+
started: false
|
|
11575
|
+
};
|
|
11576
|
+
}
|
|
11577
|
+
};
|
|
11578
|
+
const onPointerMove = (e) => {
|
|
11579
|
+
const pending = footerPointerDragRef.current;
|
|
11580
|
+
if (!pending) return;
|
|
11581
|
+
if (pending.started) {
|
|
11582
|
+
e.preventDefault();
|
|
11583
|
+
clearTextSelection();
|
|
11584
|
+
const session = footerDragRef.current;
|
|
11585
|
+
if (!session) return;
|
|
11586
|
+
const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, session.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
|
|
11587
|
+
refreshFooterDragVisualsRef.current(session, slot, e.clientX, e.clientY);
|
|
11588
|
+
return;
|
|
11589
|
+
}
|
|
11590
|
+
const dx = e.clientX - pending.startX;
|
|
11591
|
+
const dy = e.clientY - pending.startY;
|
|
11592
|
+
if (dx * dx + dy * dy < THRESHOLD * THRESHOLD) return;
|
|
11593
|
+
e.preventDefault();
|
|
11594
|
+
pending.started = true;
|
|
11595
|
+
clearTextSelection();
|
|
11596
|
+
try {
|
|
11597
|
+
document.body.setPointerCapture(pending.pointerId);
|
|
11598
|
+
} catch {
|
|
11599
|
+
}
|
|
11600
|
+
if (linkPopoverOpenRef.current) {
|
|
11601
|
+
setLinkPopoverRef.current(null);
|
|
11602
|
+
}
|
|
11603
|
+
if (activeElRef.current) {
|
|
11604
|
+
deactivateRef.current();
|
|
11605
|
+
}
|
|
11606
|
+
if (pending.kind === "link") {
|
|
11607
|
+
const key = pending.el.getAttribute("data-ohw-href-key");
|
|
11608
|
+
if (!key) return;
|
|
11609
|
+
const column = findFooterColumnForLink(pending.el);
|
|
11610
|
+
const columns2 = listFooterColumns();
|
|
11611
|
+
beginFooterDragRef.current({
|
|
11612
|
+
kind: "link",
|
|
11613
|
+
hrefKey: key,
|
|
11614
|
+
columnEl: column,
|
|
11615
|
+
sourceColumnIndex: column ? columns2.indexOf(column) : 0,
|
|
11616
|
+
wasSelected: pending.wasSelected,
|
|
11617
|
+
draggedEl: pending.el,
|
|
11618
|
+
lastClientX: e.clientX,
|
|
11619
|
+
lastClientY: e.clientY,
|
|
11620
|
+
activeSlot: null
|
|
11621
|
+
});
|
|
11622
|
+
return;
|
|
11623
|
+
}
|
|
11624
|
+
const columns = listFooterColumns();
|
|
11625
|
+
const idx = columns.indexOf(pending.el);
|
|
11626
|
+
if (idx < 0) return;
|
|
11627
|
+
beginFooterDragRef.current({
|
|
11628
|
+
kind: "column",
|
|
11629
|
+
hrefKey: null,
|
|
11630
|
+
columnEl: pending.el,
|
|
11631
|
+
sourceColumnIndex: idx,
|
|
11632
|
+
wasSelected: pending.wasSelected,
|
|
11633
|
+
draggedEl: pending.el,
|
|
11634
|
+
lastClientX: e.clientX,
|
|
11635
|
+
lastClientY: e.clientY,
|
|
11636
|
+
activeSlot: null
|
|
11637
|
+
});
|
|
11638
|
+
};
|
|
11639
|
+
const endPointerDrag = (e) => {
|
|
11640
|
+
const pending = footerPointerDragRef.current;
|
|
11641
|
+
footerPointerDragRef.current = null;
|
|
11642
|
+
try {
|
|
11643
|
+
if (document.body.hasPointerCapture(e.pointerId)) {
|
|
11644
|
+
document.body.releasePointerCapture(e.pointerId);
|
|
11645
|
+
}
|
|
11646
|
+
} catch {
|
|
11647
|
+
}
|
|
11648
|
+
if (!pending?.started) {
|
|
11649
|
+
unlockFooterDragInteraction();
|
|
11650
|
+
return;
|
|
11651
|
+
}
|
|
11652
|
+
suppressNextClickRef.current = true;
|
|
11653
|
+
suppressClickUntilRef.current = Date.now() + 500;
|
|
11654
|
+
commitFooterDragRef.current(e.clientX, e.clientY);
|
|
11655
|
+
};
|
|
11656
|
+
const blockSelectStart = (e) => {
|
|
11657
|
+
if (footerDragRef.current || footerPointerDragRef.current?.started || document.documentElement.hasAttribute("data-ohw-footer-press-drag")) {
|
|
11658
|
+
e.preventDefault();
|
|
11659
|
+
}
|
|
11660
|
+
};
|
|
11661
|
+
const onDragEnd = (_e) => {
|
|
11662
|
+
if (!footerDragRef.current) return;
|
|
11663
|
+
suppressNextClickRef.current = true;
|
|
11664
|
+
suppressClickUntilRef.current = Date.now() + 500;
|
|
11665
|
+
commitFooterDragRef.current();
|
|
11666
|
+
};
|
|
11667
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
11668
|
+
document.addEventListener("pointermove", onPointerMove, true);
|
|
11669
|
+
document.addEventListener("pointerup", endPointerDrag, true);
|
|
11670
|
+
document.addEventListener("pointercancel", endPointerDrag, true);
|
|
11671
|
+
document.addEventListener("selectstart", blockSelectStart, true);
|
|
11672
|
+
document.addEventListener("dragend", onDragEnd, true);
|
|
11673
|
+
return () => {
|
|
11674
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
11675
|
+
document.removeEventListener("pointermove", onPointerMove, true);
|
|
11676
|
+
document.removeEventListener("pointerup", endPointerDrag, true);
|
|
11677
|
+
document.removeEventListener("pointercancel", endPointerDrag, true);
|
|
11678
|
+
document.removeEventListener("selectstart", blockSelectStart, true);
|
|
11679
|
+
document.removeEventListener("dragend", onDragEnd, true);
|
|
11680
|
+
unlockFooterDragInteraction();
|
|
11681
|
+
};
|
|
11682
|
+
}, [isEditMode]);
|
|
11683
|
+
(0, import_react9.useEffect)(() => {
|
|
9755
11684
|
const handler = (e) => {
|
|
9756
11685
|
if (e.data?.type !== "ow:request-schedule-config") return;
|
|
9757
11686
|
const insertAfterVal = e.data.insertAfter;
|
|
@@ -9767,7 +11696,7 @@ function OhhwellsBridge() {
|
|
|
9767
11696
|
window.addEventListener("message", handler);
|
|
9768
11697
|
return () => window.removeEventListener("message", handler);
|
|
9769
11698
|
}, [processConfigRequest]);
|
|
9770
|
-
(0,
|
|
11699
|
+
(0, import_react9.useEffect)(() => {
|
|
9771
11700
|
if (!isEditMode) return;
|
|
9772
11701
|
document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
|
|
9773
11702
|
el.removeAttribute("data-ohw-active-state");
|
|
@@ -9788,7 +11717,13 @@ function OhhwellsBridge() {
|
|
|
9788
11717
|
const next = { ...prev, [pathKey]: sections };
|
|
9789
11718
|
return shouldUseDevFixtures() ? { ...DEV_SECTIONS_BY_PATH, ...next } : next;
|
|
9790
11719
|
});
|
|
9791
|
-
postToParent2({
|
|
11720
|
+
postToParent2({
|
|
11721
|
+
type: "ow:ready",
|
|
11722
|
+
version: "1",
|
|
11723
|
+
path: pathname,
|
|
11724
|
+
nodes: collectEditableNodes(editContentRef.current),
|
|
11725
|
+
sections
|
|
11726
|
+
});
|
|
9792
11727
|
postToParent2({ type: "ow:request-site-pages" });
|
|
9793
11728
|
}, 150);
|
|
9794
11729
|
return () => {
|
|
@@ -9796,19 +11731,19 @@ function OhhwellsBridge() {
|
|
|
9796
11731
|
clearTimeout(timer);
|
|
9797
11732
|
};
|
|
9798
11733
|
}, [pathname, isEditMode, refreshStateRules, postToParent2]);
|
|
9799
|
-
(0,
|
|
11734
|
+
(0, import_react9.useEffect)(() => {
|
|
9800
11735
|
scrollToHashSectionWhenReady();
|
|
9801
11736
|
const onHashChange = () => scrollToHashSectionWhenReady();
|
|
9802
11737
|
window.addEventListener("hashchange", onHashChange);
|
|
9803
11738
|
return () => window.removeEventListener("hashchange", onHashChange);
|
|
9804
11739
|
}, [pathname]);
|
|
9805
|
-
const handleCommand = (0,
|
|
11740
|
+
const handleCommand = (0, import_react9.useCallback)((cmd) => {
|
|
9806
11741
|
document.execCommand(cmd, false);
|
|
9807
11742
|
activeElRef.current?.focus();
|
|
9808
11743
|
if (activeElRef.current) setToolbarRect(getEditMeasureEl(activeElRef.current).getBoundingClientRect());
|
|
9809
11744
|
refreshActiveCommandsRef.current();
|
|
9810
11745
|
}, []);
|
|
9811
|
-
const handleStateChange = (0,
|
|
11746
|
+
const handleStateChange = (0, import_react9.useCallback)((state) => {
|
|
9812
11747
|
if (!activeStateElRef.current) return;
|
|
9813
11748
|
const el = activeStateElRef.current;
|
|
9814
11749
|
if (state === "Default") {
|
|
@@ -9821,11 +11756,11 @@ function OhhwellsBridge() {
|
|
|
9821
11756
|
}
|
|
9822
11757
|
setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
|
|
9823
11758
|
}, [deactivate]);
|
|
9824
|
-
const closeLinkPopover = (0,
|
|
11759
|
+
const closeLinkPopover = (0, import_react9.useCallback)(() => {
|
|
9825
11760
|
addNavAfterAnchorRef.current = null;
|
|
9826
11761
|
setLinkPopover(null);
|
|
9827
11762
|
}, []);
|
|
9828
|
-
const openLinkPopoverForActive = (0,
|
|
11763
|
+
const openLinkPopoverForActive = (0, import_react9.useCallback)(() => {
|
|
9829
11764
|
const hrefCtx = getHrefKeyFromElement(activeElRef.current);
|
|
9830
11765
|
if (!hrefCtx) return;
|
|
9831
11766
|
bumpLinkPopoverGrace();
|
|
@@ -9836,7 +11771,7 @@ function OhhwellsBridge() {
|
|
|
9836
11771
|
});
|
|
9837
11772
|
deactivate();
|
|
9838
11773
|
}, [deactivate]);
|
|
9839
|
-
const openLinkPopoverForSelected = (0,
|
|
11774
|
+
const openLinkPopoverForSelected = (0, import_react9.useCallback)(() => {
|
|
9840
11775
|
const anchor = selectedElRef.current;
|
|
9841
11776
|
if (!anchor) return;
|
|
9842
11777
|
const key = anchor.getAttribute("data-ohw-href-key");
|
|
@@ -9849,7 +11784,7 @@ function OhhwellsBridge() {
|
|
|
9849
11784
|
});
|
|
9850
11785
|
deselect();
|
|
9851
11786
|
}, [deselect]);
|
|
9852
|
-
const handleLinkPopoverSubmit = (0,
|
|
11787
|
+
const handleLinkPopoverSubmit = (0, import_react9.useCallback)(
|
|
9853
11788
|
(target) => {
|
|
9854
11789
|
const session = linkPopoverSessionRef.current;
|
|
9855
11790
|
if (!session) return;
|
|
@@ -9908,13 +11843,13 @@ function OhhwellsBridge() {
|
|
|
9908
11843
|
const showEditLink = toolbarShowEditLink;
|
|
9909
11844
|
const currentSections = sectionsByPath[pathname] ?? [];
|
|
9910
11845
|
linkPopoverOpenRef.current = linkPopover !== null;
|
|
9911
|
-
const handleMediaReplace = (0,
|
|
11846
|
+
const handleMediaReplace = (0, import_react9.useCallback)(
|
|
9912
11847
|
(key) => {
|
|
9913
11848
|
postToParent2({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
|
|
9914
11849
|
},
|
|
9915
11850
|
[postToParent2, mediaHover?.elementType]
|
|
9916
11851
|
);
|
|
9917
|
-
const handleMediaFadeOutComplete = (0,
|
|
11852
|
+
const handleMediaFadeOutComplete = (0, import_react9.useCallback)((key) => {
|
|
9918
11853
|
setUploadingRects((prev) => {
|
|
9919
11854
|
if (!(key in prev)) return prev;
|
|
9920
11855
|
const next = { ...prev };
|
|
@@ -9922,7 +11857,7 @@ function OhhwellsBridge() {
|
|
|
9922
11857
|
return next;
|
|
9923
11858
|
});
|
|
9924
11859
|
}, []);
|
|
9925
|
-
const handleVideoSettingsChange = (0,
|
|
11860
|
+
const handleVideoSettingsChange = (0, import_react9.useCallback)(
|
|
9926
11861
|
(key, settings) => {
|
|
9927
11862
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
9928
11863
|
const video = getVideoEl(el);
|
|
@@ -9945,9 +11880,9 @@ function OhhwellsBridge() {
|
|
|
9945
11880
|
[postToParent2]
|
|
9946
11881
|
);
|
|
9947
11882
|
return bridgeRoot ? (0, import_react_dom3.createPortal)(
|
|
9948
|
-
/* @__PURE__ */ (0,
|
|
9949
|
-
/* @__PURE__ */ (0,
|
|
9950
|
-
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0,
|
|
11883
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
11884
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
11885
|
+
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
9951
11886
|
MediaOverlay,
|
|
9952
11887
|
{
|
|
9953
11888
|
hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
|
|
@@ -9958,7 +11893,7 @@ function OhhwellsBridge() {
|
|
|
9958
11893
|
},
|
|
9959
11894
|
`uploading-${key}`
|
|
9960
11895
|
)),
|
|
9961
|
-
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0,
|
|
11896
|
+
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
9962
11897
|
MediaOverlay,
|
|
9963
11898
|
{
|
|
9964
11899
|
hover: mediaHover,
|
|
@@ -9967,28 +11902,69 @@ function OhhwellsBridge() {
|
|
|
9967
11902
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
9968
11903
|
}
|
|
9969
11904
|
),
|
|
9970
|
-
siblingHintRect && !isItemDragging && /* @__PURE__ */ (0,
|
|
9971
|
-
|
|
9972
|
-
|
|
9973
|
-
|
|
11905
|
+
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
11906
|
+
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
|
|
11907
|
+
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
|
|
11908
|
+
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
11909
|
+
"div",
|
|
9974
11910
|
{
|
|
9975
|
-
|
|
9976
|
-
|
|
9977
|
-
|
|
9978
|
-
|
|
9979
|
-
|
|
9980
|
-
|
|
11911
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
11912
|
+
style: {
|
|
11913
|
+
left: slot.left,
|
|
11914
|
+
top: slot.top,
|
|
11915
|
+
width: slot.width,
|
|
11916
|
+
height: slot.height
|
|
11917
|
+
},
|
|
11918
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
11919
|
+
DropIndicator,
|
|
11920
|
+
{
|
|
11921
|
+
direction: slot.direction,
|
|
11922
|
+
state: activeFooterDropIndex === i ? "dragActive" : "dragIdle",
|
|
11923
|
+
className: "!h-full !w-full"
|
|
11924
|
+
}
|
|
11925
|
+
)
|
|
11926
|
+
},
|
|
11927
|
+
`footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
|
|
11928
|
+
)),
|
|
11929
|
+
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
11930
|
+
"div",
|
|
11931
|
+
{
|
|
11932
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
11933
|
+
style: {
|
|
11934
|
+
left: slot.left,
|
|
11935
|
+
top: slot.top,
|
|
11936
|
+
width: slot.width,
|
|
11937
|
+
height: slot.height
|
|
11938
|
+
},
|
|
11939
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
11940
|
+
DropIndicator,
|
|
11941
|
+
{
|
|
11942
|
+
direction: slot.direction,
|
|
11943
|
+
state: activeNavDropIndex === i ? "dragActive" : "dragIdle",
|
|
11944
|
+
className: "!h-full !w-full"
|
|
11945
|
+
}
|
|
11946
|
+
)
|
|
11947
|
+
},
|
|
11948
|
+
`nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
|
|
11949
|
+
)),
|
|
11950
|
+
hoveredNavContainerRect && toolbarVariant !== "select-frame" && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
|
|
11951
|
+
hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
11952
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
|
|
11953
|
+
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
9981
11954
|
ItemInteractionLayer,
|
|
9982
11955
|
{
|
|
9983
|
-
rect: toolbarRect,
|
|
11956
|
+
rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
|
|
9984
11957
|
elRef: glowElRef,
|
|
9985
11958
|
state: isItemDragging ? "dragging" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
|
|
9986
|
-
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey),
|
|
11959
|
+
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey) || toolbarVariant === "select-frame" && isFooterFrameSelection,
|
|
9987
11960
|
dragDisabled: reorderDragDisabled,
|
|
9988
11961
|
dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
|
|
9989
11962
|
onDragHandleDragStart: handleItemDragStart,
|
|
9990
11963
|
onDragHandleDragEnd: handleItemDragEnd,
|
|
9991
|
-
|
|
11964
|
+
onItemPointerDown: handleItemChromePointerDown,
|
|
11965
|
+
onItemClick: handleItemChromeClick,
|
|
11966
|
+
itemDragSurface: !isFooterFrameSelection,
|
|
11967
|
+
toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
9992
11968
|
ItemActionToolbar,
|
|
9993
11969
|
{
|
|
9994
11970
|
onEditLink: openLinkPopoverForSelected,
|
|
@@ -10001,17 +11977,18 @@ function OhhwellsBridge() {
|
|
|
10001
11977
|
) : void 0
|
|
10002
11978
|
}
|
|
10003
11979
|
),
|
|
10004
|
-
toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ (0,
|
|
10005
|
-
/* @__PURE__ */ (0,
|
|
11980
|
+
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
11981
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
10006
11982
|
EditGlowChrome,
|
|
10007
11983
|
{
|
|
10008
11984
|
rect: toolbarRect,
|
|
10009
11985
|
elRef: glowElRef,
|
|
10010
11986
|
reorderHrefKey,
|
|
10011
|
-
dragDisabled: reorderDragDisabled
|
|
11987
|
+
dragDisabled: reorderDragDisabled,
|
|
11988
|
+
hideHandle: isItemDragging
|
|
10012
11989
|
}
|
|
10013
11990
|
),
|
|
10014
|
-
/* @__PURE__ */ (0,
|
|
11991
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
10015
11992
|
FloatingToolbar,
|
|
10016
11993
|
{
|
|
10017
11994
|
rect: toolbarRect,
|
|
@@ -10024,7 +12001,7 @@ function OhhwellsBridge() {
|
|
|
10024
12001
|
}
|
|
10025
12002
|
)
|
|
10026
12003
|
] }),
|
|
10027
|
-
maxBadge && /* @__PURE__ */ (0,
|
|
12004
|
+
maxBadge && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
10028
12005
|
"div",
|
|
10029
12006
|
{
|
|
10030
12007
|
"data-ohw-max-badge": "",
|
|
@@ -10050,7 +12027,7 @@ function OhhwellsBridge() {
|
|
|
10050
12027
|
]
|
|
10051
12028
|
}
|
|
10052
12029
|
),
|
|
10053
|
-
toggleState && !linkPopover && /* @__PURE__ */ (0,
|
|
12030
|
+
toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
10054
12031
|
StateToggle,
|
|
10055
12032
|
{
|
|
10056
12033
|
rect: toggleState.rect,
|
|
@@ -10059,32 +12036,36 @@ function OhhwellsBridge() {
|
|
|
10059
12036
|
onStateChange: handleStateChange
|
|
10060
12037
|
}
|
|
10061
12038
|
),
|
|
10062
|
-
sectionGap && !linkPopover && /* @__PURE__ */ (0,
|
|
12039
|
+
sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
10063
12040
|
"div",
|
|
10064
12041
|
{
|
|
10065
12042
|
"data-ohw-section-insert-line": "",
|
|
10066
12043
|
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
10067
12044
|
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
10068
12045
|
children: [
|
|
10069
|
-
/* @__PURE__ */ (0,
|
|
10070
|
-
/* @__PURE__ */ (0,
|
|
12046
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
12047
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
10071
12048
|
Badge,
|
|
10072
12049
|
{
|
|
10073
12050
|
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",
|
|
10074
12051
|
onClick: () => {
|
|
10075
12052
|
window.parent.postMessage(
|
|
10076
|
-
{
|
|
12053
|
+
{
|
|
12054
|
+
type: "ow:add-section",
|
|
12055
|
+
insertAfter: sectionGap.insertAfter,
|
|
12056
|
+
insertBefore: sectionGap.insertBefore
|
|
12057
|
+
},
|
|
10077
12058
|
"*"
|
|
10078
12059
|
);
|
|
10079
12060
|
},
|
|
10080
12061
|
children: "Add Section"
|
|
10081
12062
|
}
|
|
10082
12063
|
),
|
|
10083
|
-
/* @__PURE__ */ (0,
|
|
12064
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
|
|
10084
12065
|
]
|
|
10085
12066
|
}
|
|
10086
12067
|
),
|
|
10087
|
-
linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0,
|
|
12068
|
+
linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
10088
12069
|
LinkPopover,
|
|
10089
12070
|
{
|
|
10090
12071
|
panelRef: linkPopoverPanelRef,
|
|
@@ -10105,48 +12086,6 @@ function OhhwellsBridge() {
|
|
|
10105
12086
|
bridgeRoot
|
|
10106
12087
|
) : null;
|
|
10107
12088
|
}
|
|
10108
|
-
|
|
10109
|
-
// src/ui/drop-indicator.tsx
|
|
10110
|
-
var React11 = __toESM(require("react"), 1);
|
|
10111
|
-
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
10112
|
-
var dropIndicatorVariants = cva(
|
|
10113
|
-
"ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
|
|
10114
|
-
{
|
|
10115
|
-
variants: {
|
|
10116
|
-
direction: {
|
|
10117
|
-
vertical: "h-6 w-[3px]",
|
|
10118
|
-
horizontal: "h-[3px] w-[200px]"
|
|
10119
|
-
},
|
|
10120
|
-
state: {
|
|
10121
|
-
default: "opacity-0",
|
|
10122
|
-
hover: "opacity-100",
|
|
10123
|
-
dragIdle: "opacity-40",
|
|
10124
|
-
dragActive: "opacity-100"
|
|
10125
|
-
}
|
|
10126
|
-
},
|
|
10127
|
-
defaultVariants: {
|
|
10128
|
-
direction: "vertical",
|
|
10129
|
-
state: "default"
|
|
10130
|
-
}
|
|
10131
|
-
}
|
|
10132
|
-
);
|
|
10133
|
-
var DropIndicator = React11.forwardRef(
|
|
10134
|
-
({ className, direction, state, ...props }, ref) => {
|
|
10135
|
-
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
10136
|
-
"div",
|
|
10137
|
-
{
|
|
10138
|
-
ref,
|
|
10139
|
-
"data-slot": "drop-indicator",
|
|
10140
|
-
"data-direction": direction ?? "vertical",
|
|
10141
|
-
"data-state": state ?? "default",
|
|
10142
|
-
"aria-hidden": "true",
|
|
10143
|
-
className: cn(dropIndicatorVariants({ direction, state }), className),
|
|
10144
|
-
...props
|
|
10145
|
-
}
|
|
10146
|
-
);
|
|
10147
|
-
}
|
|
10148
|
-
);
|
|
10149
|
-
DropIndicator.displayName = "DropIndicator";
|
|
10150
12089
|
// Annotate the CommonJS export names for ESM import in node:
|
|
10151
12090
|
0 && (module.exports = {
|
|
10152
12091
|
CustomToolbar,
|