@ohhwells/bridge 0.1.42-next.97 → 0.1.43
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/README.md +0 -12
- package/dist/index.cjs +467 -2914
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -30
- package/dist/index.d.ts +4 -30
- package/dist/index.js +470 -2917
- package/dist/index.js.map +1 -1
- package/dist/styles.css +67 -68
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
// src/OhhwellsBridge.tsx
|
|
4
|
-
import
|
|
4
|
+
import React9, { useCallback as useCallback3, useEffect as useEffect7, useLayoutEffect as useLayoutEffect2, useRef as useRef5, useState as useState6 } from "react";
|
|
5
5
|
import { createRoot } from "react-dom/client";
|
|
6
6
|
import { flushSync } from "react-dom";
|
|
7
7
|
|
|
@@ -48,13 +48,12 @@ function useLinkHrefGuardian(...deps) {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
// src/ui/SchedulingWidget.tsx
|
|
51
|
-
import {
|
|
51
|
+
import { useEffect, useId, useMemo, useRef, useState as useState2 } from "react";
|
|
52
52
|
|
|
53
53
|
// src/ui/EmailCaptureModal.tsx
|
|
54
54
|
import { useState } from "react";
|
|
55
55
|
import { Dialog } from "radix-ui";
|
|
56
56
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
57
|
-
var isValidEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
58
57
|
function Spinner() {
|
|
59
58
|
return /* @__PURE__ */ jsxs(
|
|
60
59
|
"svg",
|
|
@@ -88,17 +87,12 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
|
|
|
88
87
|
const [error, setError] = useState(null);
|
|
89
88
|
const isBook = title === "Confirm your spot";
|
|
90
89
|
const handleSubmit = async () => {
|
|
91
|
-
|
|
92
|
-
if (!trimmed) return;
|
|
93
|
-
if (!isValidEmail(trimmed)) {
|
|
94
|
-
setError("Please enter a valid email address.");
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
90
|
+
if (!email.trim()) return;
|
|
97
91
|
setLoading(true);
|
|
98
92
|
setError(null);
|
|
99
93
|
try {
|
|
100
|
-
await onSubmit(
|
|
101
|
-
setSubmittedEmail(
|
|
94
|
+
await onSubmit(email.trim());
|
|
95
|
+
setSubmittedEmail(email.trim());
|
|
102
96
|
setSuccess(true);
|
|
103
97
|
} catch (e) {
|
|
104
98
|
setError(e instanceof Error ? e.message : "Something went wrong. Please try again.");
|
|
@@ -173,10 +167,7 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
|
|
|
173
167
|
{
|
|
174
168
|
type: "email",
|
|
175
169
|
value: email,
|
|
176
|
-
onChange: (e) =>
|
|
177
|
-
setEmail(e.target.value);
|
|
178
|
-
if (error) setError(null);
|
|
179
|
-
},
|
|
170
|
+
onChange: (e) => setEmail(e.target.value),
|
|
180
171
|
onKeyDown: handleKeyDown,
|
|
181
172
|
placeholder: "hello@gmail.com",
|
|
182
173
|
autoFocus: true,
|
|
@@ -233,20 +224,12 @@ function formatClassTime(cls) {
|
|
|
233
224
|
const em = endTotal % 60;
|
|
234
225
|
return `${h}:${cls.startTime.minutes}-${eh}:${String(em).padStart(2, "0")}`;
|
|
235
226
|
}
|
|
236
|
-
function formatBookingLabel(cls) {
|
|
237
|
-
const price = cls.price;
|
|
238
|
-
const isFree = price === null || price === void 0 || `${price}` === "" || `${price}` === "0";
|
|
239
|
-
return isFree ? "Book for free" : `Book for ${cls.currency ?? ""} ${price}`.trim();
|
|
240
|
-
}
|
|
241
227
|
function getBookingsOnDate(cls, date) {
|
|
242
228
|
if (!cls.bookings?.length) return 0;
|
|
243
|
-
const
|
|
244
|
-
target.setHours(0, 0, 0, 0);
|
|
229
|
+
const ds = date.toISOString().split("T")[0];
|
|
245
230
|
return cls.bookings.filter((b) => {
|
|
246
231
|
try {
|
|
247
|
-
|
|
248
|
-
bookingDate.setHours(0, 0, 0, 0);
|
|
249
|
-
return bookingDate.getTime() === target.getTime();
|
|
232
|
+
return new Date(b.classDate).toISOString().split("T")[0] === ds;
|
|
250
233
|
} catch {
|
|
251
234
|
return false;
|
|
252
235
|
}
|
|
@@ -511,7 +494,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
|
|
|
511
494
|
}
|
|
512
495
|
)
|
|
513
496
|
] }),
|
|
514
|
-
|
|
497
|
+
/* @__PURE__ */ jsx2("div", { className: "sm:hidden flex flex-col gap-px", children: isFull ? /* @__PURE__ */ jsx2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
515
498
|
/* @__PURE__ */ jsxs2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
|
|
516
499
|
available,
|
|
517
500
|
"/",
|
|
@@ -523,17 +506,9 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
|
|
|
523
506
|
/* @__PURE__ */ jsxs2("div", { className: "flex flex-1 flex-col gap-2 min-w-0 sm:contents", children: [
|
|
524
507
|
/* @__PURE__ */ jsxs2("div", { className: "flex-1 flex flex-col gap-2 min-w-0", children: [
|
|
525
508
|
/* @__PURE__ */ jsx2("span", { className: "font-body text-base font-bold text-(--color-dark,#200C02) block truncate", children: cls.name }),
|
|
526
|
-
cls.hostName && /* @__PURE__ */ jsx2("span", { className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block truncate", children: cls.hostName })
|
|
527
|
-
cls.description && /* @__PURE__ */ jsx2(
|
|
528
|
-
"span",
|
|
529
|
-
{
|
|
530
|
-
className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block",
|
|
531
|
-
style: { wordBreak: "break-word" },
|
|
532
|
-
children: cls.description
|
|
533
|
-
}
|
|
534
|
-
)
|
|
509
|
+
cls.hostName && /* @__PURE__ */ jsx2("span", { className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block truncate", children: cls.hostName })
|
|
535
510
|
] }),
|
|
536
|
-
|
|
511
|
+
/* @__PURE__ */ jsx2("div", { className: "hidden sm:flex w-14 shrink-0 flex-col gap-px", children: isFull ? /* @__PURE__ */ jsx2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
537
512
|
/* @__PURE__ */ jsxs2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
|
|
538
513
|
available,
|
|
539
514
|
"/",
|
|
@@ -558,7 +533,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
|
|
|
558
533
|
if (!cls.id) return;
|
|
559
534
|
onOpenModal?.(isFull ? "waitlist" : "book", cls.id, selectedDate);
|
|
560
535
|
},
|
|
561
|
-
children: isFull ? "Join Waitlist" :
|
|
536
|
+
children: isFull ? "Join Waitlist" : "Book Now"
|
|
562
537
|
}
|
|
563
538
|
)
|
|
564
539
|
] })
|
|
@@ -600,17 +575,6 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
600
575
|
const [isHovered, setIsHovered] = useState2(false);
|
|
601
576
|
const [modalState, setModalState] = useState2(null);
|
|
602
577
|
const switchScheduleIdRef = useRef(null);
|
|
603
|
-
const liveScheduleIdRef = useRef(null);
|
|
604
|
-
const refetchLiveSchedule = useCallback(async () => {
|
|
605
|
-
const id = liveScheduleIdRef.current;
|
|
606
|
-
if (!id) return;
|
|
607
|
-
try {
|
|
608
|
-
const res = await fetch(`${API_URL}/api/schedule/id/${id}`);
|
|
609
|
-
const data = await res.json();
|
|
610
|
-
if (data?.id) setSchedule(data);
|
|
611
|
-
} catch {
|
|
612
|
-
}
|
|
613
|
-
}, []);
|
|
614
578
|
const dates = useMemo(() => {
|
|
615
579
|
const today = /* @__PURE__ */ new Date();
|
|
616
580
|
today.setHours(0, 0, 0, 0);
|
|
@@ -630,18 +594,6 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
630
594
|
}
|
|
631
595
|
}
|
|
632
596
|
}, [schedule, dates]);
|
|
633
|
-
useEffect(() => {
|
|
634
|
-
if (typeof window === "undefined") return;
|
|
635
|
-
const onVisible = () => {
|
|
636
|
-
if (!document.hidden) void refetchLiveSchedule();
|
|
637
|
-
};
|
|
638
|
-
window.addEventListener("focus", refetchLiveSchedule);
|
|
639
|
-
document.addEventListener("visibilitychange", onVisible);
|
|
640
|
-
return () => {
|
|
641
|
-
window.removeEventListener("focus", refetchLiveSchedule);
|
|
642
|
-
document.removeEventListener("visibilitychange", onVisible);
|
|
643
|
-
};
|
|
644
|
-
}, [refetchLiveSchedule]);
|
|
645
597
|
useEffect(() => {
|
|
646
598
|
if (typeof window === "undefined") return;
|
|
647
599
|
const isInEditor = window.self !== window.top;
|
|
@@ -703,7 +655,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
703
655
|
setLoading(false);
|
|
704
656
|
return;
|
|
705
657
|
}
|
|
706
|
-
|
|
658
|
+
;
|
|
707
659
|
(async () => {
|
|
708
660
|
try {
|
|
709
661
|
const res = await fetch(`${API_URL}/api/schedule/id/${effectiveId}`);
|
|
@@ -760,14 +712,18 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
760
712
|
const data = await res.json().catch(() => ({}));
|
|
761
713
|
throw new Error(data?.message ?? "Something went wrong. Please try again.");
|
|
762
714
|
}
|
|
763
|
-
await refetchLiveSchedule();
|
|
764
715
|
};
|
|
765
716
|
const handleReplaceSchedule = () => {
|
|
766
717
|
setIsHovered(false);
|
|
767
|
-
|
|
768
|
-
{
|
|
769
|
-
|
|
770
|
-
|
|
718
|
+
if (schedule) {
|
|
719
|
+
window.parent.postMessage({
|
|
720
|
+
type: "ow:schedule-connected",
|
|
721
|
+
schedule: { id: schedule.id, name: schedule.name },
|
|
722
|
+
insertAfter
|
|
723
|
+
}, "*");
|
|
724
|
+
} else {
|
|
725
|
+
window.parent.postMessage({ type: "ow:scheduling-not-connected", insertAfter }, "*");
|
|
726
|
+
}
|
|
771
727
|
};
|
|
772
728
|
if (!inEditor && !loading && !schedule) return null;
|
|
773
729
|
const sectionId = `scheduling-${insertAfter}`;
|
|
@@ -810,19 +766,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
810
766
|
),
|
|
811
767
|
/* @__PURE__ */ jsxs2("div", { className: "max-w-[1280px] mx-auto flex flex-col items-center gap-16", children: [
|
|
812
768
|
/* @__PURE__ */ jsxs2("div", { className: "flex flex-col items-center gap-4", children: [
|
|
813
|
-
/* @__PURE__ */ jsx2(
|
|
814
|
-
"h2",
|
|
815
|
-
{
|
|
816
|
-
className: "font-display text-center m-0 text-(--color-dark,#200C02)",
|
|
817
|
-
style: {
|
|
818
|
-
fontSize: "var(--fs-section-h2, clamp(40px, 4.4vw, 64px))",
|
|
819
|
-
fontWeight: "var(--font-weight-heading, 400)",
|
|
820
|
-
lineHeight: 1.05,
|
|
821
|
-
letterSpacing: "-0.02em"
|
|
822
|
-
},
|
|
823
|
-
children: schedule?.name ?? "Book an appointment"
|
|
824
|
-
}
|
|
825
|
-
),
|
|
769
|
+
/* @__PURE__ */ jsx2("h2", { className: "font-display text-4xl sm:text-5xl font-bold text-center m-0 text-(--color-dark,#200C02)", children: schedule?.name ?? "Book an appointment" }),
|
|
826
770
|
schedule?.description && /* @__PURE__ */ jsx2("p", { className: "font-body text-body text-center m-0 text-(--color-accent,#A89B83)", children: schedule.description })
|
|
827
771
|
] }),
|
|
828
772
|
/* @__PURE__ */ jsxs2("div", { className: "w-full flex flex-col items-end gap-3", children: [
|
|
@@ -4298,8 +4242,7 @@ var CustomToolbar = React4.forwardRef(({ className, onMouseDown, ...props }, ref
|
|
|
4298
4242
|
ref,
|
|
4299
4243
|
"data-ohw-toolbar": "",
|
|
4300
4244
|
className: cn(
|
|
4301
|
-
|
|
4302
|
-
"inline-flex h-8 items-center gap-1 rounded-[var(--radius,0.5rem)] bg-background p-0.5 font-sans whitespace-nowrap shadow-md",
|
|
4245
|
+
"inline-flex items-center gap-1 rounded-lg border border-border bg-background p-0.5 font-sans whitespace-nowrap shadow-[0px_2px_4px_-2px_rgba(0,0,0,0.1),0px_4px_6px_-1px_rgba(0,0,0,0.1)]",
|
|
4303
4246
|
className
|
|
4304
4247
|
),
|
|
4305
4248
|
onMouseDown: (e) => {
|
|
@@ -4327,8 +4270,8 @@ var CustomToolbarButton = React4.forwardRef(
|
|
|
4327
4270
|
ref,
|
|
4328
4271
|
type,
|
|
4329
4272
|
className: cn(
|
|
4330
|
-
"inline-flex
|
|
4331
|
-
active ? "bg-primary text-primary-foreground" : "bg-transparent hover:bg-muted disabled:cursor-not-allowed disabled:text-muted-foreground disabled:opacity-60",
|
|
4273
|
+
"inline-flex shrink-0 items-center justify-center rounded p-1.5 transition-colors",
|
|
4274
|
+
active ? "bg-primary text-primary-foreground" : "bg-transparent text-foreground hover:bg-muted disabled:cursor-not-allowed disabled:text-muted-foreground disabled:opacity-60",
|
|
4332
4275
|
className
|
|
4333
4276
|
),
|
|
4334
4277
|
...props
|
|
@@ -4363,10 +4306,9 @@ var arrowClassBySide = {
|
|
|
4363
4306
|
};
|
|
4364
4307
|
function TooltipContent({
|
|
4365
4308
|
className,
|
|
4366
|
-
sideOffset =
|
|
4309
|
+
sideOffset = 6,
|
|
4367
4310
|
side = "bottom",
|
|
4368
4311
|
children,
|
|
4369
|
-
hideArrow,
|
|
4370
4312
|
...props
|
|
4371
4313
|
}) {
|
|
4372
4314
|
const resolvedSide = side ?? "bottom";
|
|
@@ -4377,13 +4319,12 @@ function TooltipContent({
|
|
|
4377
4319
|
side,
|
|
4378
4320
|
sideOffset,
|
|
4379
4321
|
className: cn(
|
|
4380
|
-
"relative z-[2147483647]
|
|
4381
|
-
|
|
4382
|
-
|
|
4322
|
+
"relative z-[2147483647] w-fit max-w-xs rounded-md bg-foreground px-3 py-1.5 text-xs text-background shadow-md",
|
|
4323
|
+
'before:pointer-events-none before:absolute before:size-2 before:rotate-45 before:bg-foreground before:content-[""]',
|
|
4324
|
+
arrowClassBySide[resolvedSide],
|
|
4325
|
+
"animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
4383
4326
|
"data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2",
|
|
4384
4327
|
"data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2",
|
|
4385
|
-
!hideArrow && 'before:pointer-events-none before:absolute before:size-2 before:rotate-45 before:bg-foreground before:content-[""]',
|
|
4386
|
-
!hideArrow && arrowClassBySide[resolvedSide],
|
|
4387
4328
|
className
|
|
4388
4329
|
),
|
|
4389
4330
|
...props,
|
|
@@ -4404,7 +4345,7 @@ function ToolbarActionTooltip({
|
|
|
4404
4345
|
const button = /* @__PURE__ */ jsx8(CustomToolbarButton, { type: "button", "aria-label": label, disabled, ...buttonProps, children });
|
|
4405
4346
|
return /* @__PURE__ */ jsxs3(Tooltip, { children: [
|
|
4406
4347
|
/* @__PURE__ */ jsx8(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ jsx8("span", { className: "inline-flex", children: button }) : button }),
|
|
4407
|
-
/* @__PURE__ */ jsx8(TooltipContent, { side,
|
|
4348
|
+
/* @__PURE__ */ jsx8(TooltipContent, { side, children: label })
|
|
4408
4349
|
] });
|
|
4409
4350
|
}
|
|
4410
4351
|
function ItemActionToolbar({
|
|
@@ -4414,8 +4355,6 @@ function ItemActionToolbar({
|
|
|
4414
4355
|
editLinkDisabled = false,
|
|
4415
4356
|
addItemDisabled = true,
|
|
4416
4357
|
moreDisabled = true,
|
|
4417
|
-
showAddItem = true,
|
|
4418
|
-
showMore = true,
|
|
4419
4358
|
tooltipSide = "bottom"
|
|
4420
4359
|
}) {
|
|
4421
4360
|
return /* @__PURE__ */ jsx8(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs3(CustomToolbar, { children: [
|
|
@@ -4440,7 +4379,8 @@ function ItemActionToolbar({
|
|
|
4440
4379
|
children: /* @__PURE__ */ jsx8(Link, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
4441
4380
|
}
|
|
4442
4381
|
),
|
|
4443
|
-
|
|
4382
|
+
/* @__PURE__ */ jsx8(CustomToolbarDivider, {}),
|
|
4383
|
+
/* @__PURE__ */ jsx8(
|
|
4444
4384
|
ToolbarActionTooltip,
|
|
4445
4385
|
{
|
|
4446
4386
|
label: "Add item",
|
|
@@ -4456,8 +4396,9 @@ function ItemActionToolbar({
|
|
|
4456
4396
|
},
|
|
4457
4397
|
children: /* @__PURE__ */ jsx8(Plus, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
4458
4398
|
}
|
|
4459
|
-
)
|
|
4460
|
-
|
|
4399
|
+
),
|
|
4400
|
+
/* @__PURE__ */ jsx8(CustomToolbarDivider, {}),
|
|
4401
|
+
/* @__PURE__ */ jsx8(
|
|
4461
4402
|
ToolbarActionTooltip,
|
|
4462
4403
|
{
|
|
4463
4404
|
label: "More",
|
|
@@ -4473,32 +4414,15 @@ function ItemActionToolbar({
|
|
|
4473
4414
|
},
|
|
4474
4415
|
children: /* @__PURE__ */ jsx8(MoreHorizontal, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
4475
4416
|
}
|
|
4476
|
-
)
|
|
4417
|
+
)
|
|
4477
4418
|
] }) });
|
|
4478
4419
|
}
|
|
4479
4420
|
|
|
4480
4421
|
// src/ui/item-interaction-layer.tsx
|
|
4481
|
-
import * as React5 from "react";
|
|
4482
4422
|
import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
4483
4423
|
var PRIMARY = "var(--ohw-primary, #0885FE)";
|
|
4484
|
-
var FOCUS_RING =
|
|
4424
|
+
var FOCUS_RING = "0 0 0 4px rgba(8, 133, 254, 0.12)";
|
|
4485
4425
|
var DRAG_SHADOW = "0px 4px 6px -1px rgba(0, 0, 0, 0.1), 0px 2px 4px -2px rgba(0, 0, 0, 0.1)";
|
|
4486
|
-
var TOOLBAR_EDGE_MARGIN = 4;
|
|
4487
|
-
var SELECTION_CHROME_GAP = 4;
|
|
4488
|
-
var TOOLBAR_STROKE_GAP = 4;
|
|
4489
|
-
function getChromeZIndex(state) {
|
|
4490
|
-
switch (state) {
|
|
4491
|
-
case "active-top":
|
|
4492
|
-
case "active-bottom":
|
|
4493
|
-
case "dragging":
|
|
4494
|
-
return 2147483644;
|
|
4495
|
-
case "hover":
|
|
4496
|
-
case "sibling-hint":
|
|
4497
|
-
return 2147483643;
|
|
4498
|
-
default:
|
|
4499
|
-
return 2147483642;
|
|
4500
|
-
}
|
|
4501
|
-
}
|
|
4502
4426
|
function getChromeStyle(state) {
|
|
4503
4427
|
switch (state) {
|
|
4504
4428
|
case "hover":
|
|
@@ -4520,65 +4444,12 @@ function getChromeStyle(state) {
|
|
|
4520
4444
|
case "dragging":
|
|
4521
4445
|
return {
|
|
4522
4446
|
border: `2px solid ${PRIMARY}`,
|
|
4523
|
-
boxShadow:
|
|
4447
|
+
boxShadow: DRAG_SHADOW
|
|
4524
4448
|
};
|
|
4525
4449
|
default:
|
|
4526
4450
|
return {};
|
|
4527
4451
|
}
|
|
4528
4452
|
}
|
|
4529
|
-
function ClampedToolbarSlot({
|
|
4530
|
-
placement,
|
|
4531
|
-
children
|
|
4532
|
-
}) {
|
|
4533
|
-
const slotRef = React5.useRef(null);
|
|
4534
|
-
React5.useLayoutEffect(() => {
|
|
4535
|
-
const slot = slotRef.current;
|
|
4536
|
-
if (!slot) return;
|
|
4537
|
-
const clamp = () => {
|
|
4538
|
-
const toolbar = slot.firstElementChild;
|
|
4539
|
-
if (!toolbar) return;
|
|
4540
|
-
const w = toolbar.offsetWidth;
|
|
4541
|
-
if (w <= 0) return;
|
|
4542
|
-
const parent = slot.offsetParent;
|
|
4543
|
-
if (!parent) return;
|
|
4544
|
-
const parentRect = parent.getBoundingClientRect();
|
|
4545
|
-
const centerX = parentRect.left + parentRect.width / 2;
|
|
4546
|
-
const half = w / 2;
|
|
4547
|
-
const clampedCenter = Math.max(
|
|
4548
|
-
TOOLBAR_EDGE_MARGIN + half,
|
|
4549
|
-
Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN - half)
|
|
4550
|
-
);
|
|
4551
|
-
const offsetX = clampedCenter - centerX;
|
|
4552
|
-
slot.style.transform = `translateX(calc(-50% + ${offsetX}px))`;
|
|
4553
|
-
};
|
|
4554
|
-
clamp();
|
|
4555
|
-
const ro = new ResizeObserver(clamp);
|
|
4556
|
-
ro.observe(slot);
|
|
4557
|
-
if (slot.firstElementChild) ro.observe(slot.firstElementChild);
|
|
4558
|
-
window.addEventListener("resize", clamp);
|
|
4559
|
-
return () => {
|
|
4560
|
-
ro.disconnect();
|
|
4561
|
-
window.removeEventListener("resize", clamp);
|
|
4562
|
-
};
|
|
4563
|
-
}, [placement, children]);
|
|
4564
|
-
return /* @__PURE__ */ jsx9(
|
|
4565
|
-
"div",
|
|
4566
|
-
{
|
|
4567
|
-
ref: slotRef,
|
|
4568
|
-
className: cn(
|
|
4569
|
-
"pointer-events-auto absolute left-1/2",
|
|
4570
|
-
placement === "top" ? "bottom-full" : "top-full"
|
|
4571
|
-
),
|
|
4572
|
-
style: {
|
|
4573
|
-
marginBottom: placement === "top" ? TOOLBAR_STROKE_GAP : void 0,
|
|
4574
|
-
marginTop: placement === "bottom" ? TOOLBAR_STROKE_GAP : void 0,
|
|
4575
|
-
transform: "translateX(-50%)"
|
|
4576
|
-
},
|
|
4577
|
-
"data-ohw-item-toolbar-anchor": placement,
|
|
4578
|
-
children
|
|
4579
|
-
}
|
|
4580
|
-
);
|
|
4581
|
-
}
|
|
4582
4453
|
function ItemInteractionLayer({
|
|
4583
4454
|
rect,
|
|
4584
4455
|
state,
|
|
@@ -4589,18 +4460,14 @@ function ItemInteractionLayer({
|
|
|
4589
4460
|
dragHandleLabel = "Reorder item",
|
|
4590
4461
|
onDragHandleDragStart,
|
|
4591
4462
|
onDragHandleDragEnd,
|
|
4592
|
-
|
|
4593
|
-
onItemClick,
|
|
4594
|
-
itemDragSurface = true,
|
|
4595
|
-
chromeGap = SELECTION_CHROME_GAP,
|
|
4463
|
+
chromeGap = 6,
|
|
4596
4464
|
className
|
|
4597
4465
|
}) {
|
|
4598
4466
|
if (state === "default") return null;
|
|
4599
4467
|
const isActive = state === "active-top" || state === "active-bottom";
|
|
4600
4468
|
const isDragging = state === "dragging";
|
|
4601
4469
|
const showToolbar = isActive && toolbar;
|
|
4602
|
-
const showDragHandle =
|
|
4603
|
-
const itemDragEnabled = itemDragSurface && isActive && showHandle && !isDragging && !dragDisabled;
|
|
4470
|
+
const showDragHandle = isActive && showHandle && !isDragging;
|
|
4604
4471
|
return /* @__PURE__ */ jsxs4(
|
|
4605
4472
|
"div",
|
|
4606
4473
|
{
|
|
@@ -4614,7 +4481,7 @@ function ItemInteractionLayer({
|
|
|
4614
4481
|
left: rect.left - chromeGap,
|
|
4615
4482
|
width: rect.width + chromeGap * 2,
|
|
4616
4483
|
height: rect.height + chromeGap * 2,
|
|
4617
|
-
zIndex:
|
|
4484
|
+
zIndex: 2147483646
|
|
4618
4485
|
},
|
|
4619
4486
|
children: [
|
|
4620
4487
|
/* @__PURE__ */ jsx9(
|
|
@@ -4625,29 +4492,11 @@ function ItemInteractionLayer({
|
|
|
4625
4492
|
style: getChromeStyle(state)
|
|
4626
4493
|
}
|
|
4627
4494
|
),
|
|
4628
|
-
itemDragEnabled && /* @__PURE__ */ jsx9(
|
|
4629
|
-
"div",
|
|
4630
|
-
{
|
|
4631
|
-
"data-ohw-item-drag-surface": "",
|
|
4632
|
-
className: "pointer-events-auto absolute inset-0 cursor-text rounded-lg",
|
|
4633
|
-
onPointerDown: (e) => {
|
|
4634
|
-
if (e.button !== 0) return;
|
|
4635
|
-
onItemPointerDown?.(e);
|
|
4636
|
-
},
|
|
4637
|
-
onClick: (e) => {
|
|
4638
|
-
e.preventDefault();
|
|
4639
|
-
e.stopPropagation();
|
|
4640
|
-
onItemClick?.(e.clientX, e.clientY);
|
|
4641
|
-
}
|
|
4642
|
-
}
|
|
4643
|
-
),
|
|
4644
4495
|
showDragHandle && /* @__PURE__ */ jsx9(
|
|
4645
4496
|
"div",
|
|
4646
4497
|
{
|
|
4647
4498
|
"data-ohw-drag-handle-container": "",
|
|
4648
|
-
className: "pointer-events-auto absolute left-0 top-1/2
|
|
4649
|
-
style: isDragging ? { opacity: 0 } : void 0,
|
|
4650
|
-
"aria-hidden": isDragging || void 0,
|
|
4499
|
+
className: "pointer-events-auto absolute left-0 top-1/2 -translate-x-[calc(100%+7px)] -translate-y-1/2",
|
|
4651
4500
|
children: /* @__PURE__ */ jsx9(
|
|
4652
4501
|
DragHandle,
|
|
4653
4502
|
{
|
|
@@ -4659,17 +4508,7 @@ function ItemInteractionLayer({
|
|
|
4659
4508
|
e.preventDefault();
|
|
4660
4509
|
return;
|
|
4661
4510
|
}
|
|
4662
|
-
|
|
4663
|
-
blank.width = 1;
|
|
4664
|
-
blank.height = 1;
|
|
4665
|
-
blank.style.cssText = "position:fixed;left:-9999px;top:-9999px;width:1px;height:1px;pointer-events:none";
|
|
4666
|
-
document.body.appendChild(blank);
|
|
4667
|
-
try {
|
|
4668
|
-
e.dataTransfer.setDragImage(blank, 0, 0);
|
|
4669
|
-
} finally {
|
|
4670
|
-
requestAnimationFrame(() => blank.remove());
|
|
4671
|
-
}
|
|
4672
|
-
e.dataTransfer.setData("text/plain", dragHandleLabel);
|
|
4511
|
+
e.dataTransfer?.setData("text/plain", dragHandleLabel);
|
|
4673
4512
|
e.dataTransfer.effectAllowed = "move";
|
|
4674
4513
|
onDragHandleDragStart?.(e);
|
|
4675
4514
|
},
|
|
@@ -4678,19 +4517,33 @@ function ItemInteractionLayer({
|
|
|
4678
4517
|
)
|
|
4679
4518
|
}
|
|
4680
4519
|
),
|
|
4681
|
-
showToolbar && state === "active-top" && /* @__PURE__ */ jsx9(
|
|
4682
|
-
|
|
4520
|
+
showToolbar && state === "active-top" && /* @__PURE__ */ jsx9(
|
|
4521
|
+
"div",
|
|
4522
|
+
{
|
|
4523
|
+
className: "pointer-events-auto absolute bottom-full left-1/2 mb-2 -translate-x-1/2",
|
|
4524
|
+
"data-ohw-item-toolbar-anchor": "top",
|
|
4525
|
+
children: toolbar
|
|
4526
|
+
}
|
|
4527
|
+
),
|
|
4528
|
+
showToolbar && state === "active-bottom" && /* @__PURE__ */ jsx9(
|
|
4529
|
+
"div",
|
|
4530
|
+
{
|
|
4531
|
+
className: "pointer-events-auto absolute left-1/2 top-full mt-2 -translate-x-1/2",
|
|
4532
|
+
"data-ohw-item-toolbar-anchor": "bottom",
|
|
4533
|
+
children: toolbar
|
|
4534
|
+
}
|
|
4535
|
+
)
|
|
4683
4536
|
]
|
|
4684
4537
|
}
|
|
4685
4538
|
);
|
|
4686
4539
|
}
|
|
4687
4540
|
|
|
4688
4541
|
// src/ui/MediaOverlay.tsx
|
|
4689
|
-
import * as
|
|
4542
|
+
import * as React6 from "react";
|
|
4690
4543
|
import { Film, ImageIcon, Pause, Play, Volume2, VolumeX } from "lucide-react";
|
|
4691
4544
|
|
|
4692
4545
|
// src/ui/button.tsx
|
|
4693
|
-
import * as
|
|
4546
|
+
import * as React5 from "react";
|
|
4694
4547
|
import { Slot } from "radix-ui";
|
|
4695
4548
|
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
4696
4549
|
var buttonVariants = cva(
|
|
@@ -4713,7 +4566,7 @@ var buttonVariants = cva(
|
|
|
4713
4566
|
}
|
|
4714
4567
|
}
|
|
4715
4568
|
);
|
|
4716
|
-
var Button =
|
|
4569
|
+
var Button = React5.forwardRef(
|
|
4717
4570
|
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
4718
4571
|
const Comp = asChild ? Slot.Root : "button";
|
|
4719
4572
|
return /* @__PURE__ */ jsx10(
|
|
@@ -4765,7 +4618,7 @@ function MediaOverlay({
|
|
|
4765
4618
|
onVideoSettingsChange
|
|
4766
4619
|
}) {
|
|
4767
4620
|
const { rect } = hover;
|
|
4768
|
-
const skeletonRef =
|
|
4621
|
+
const skeletonRef = React6.useRef(null);
|
|
4769
4622
|
const isVideo = hover.elementType === "video";
|
|
4770
4623
|
const autoplay = hover.videoAutoplay ?? true;
|
|
4771
4624
|
const muted = hover.videoMuted ?? true;
|
|
@@ -4777,7 +4630,7 @@ function MediaOverlay({
|
|
|
4777
4630
|
height: rect.height,
|
|
4778
4631
|
zIndex: 2147483646
|
|
4779
4632
|
};
|
|
4780
|
-
|
|
4633
|
+
React6.useEffect(() => {
|
|
4781
4634
|
if (!isUploading || !fadingOut || !skeletonRef.current) return;
|
|
4782
4635
|
const anim = skeletonRef.current.animate([{ opacity: 1 }, { opacity: 0 }], {
|
|
4783
4636
|
duration: MEDIA_UPLOAD_FADE_MS,
|
|
@@ -5182,7 +5035,7 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
|
|
|
5182
5035
|
import { useEffect as useEffect6 } from "react";
|
|
5183
5036
|
|
|
5184
5037
|
// src/ui/dialog.tsx
|
|
5185
|
-
import * as
|
|
5038
|
+
import * as React7 from "react";
|
|
5186
5039
|
import { Dialog as DialogPrimitive } from "radix-ui";
|
|
5187
5040
|
import { X } from "lucide-react";
|
|
5188
5041
|
import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
@@ -5210,7 +5063,7 @@ function DialogOverlay({
|
|
|
5210
5063
|
}
|
|
5211
5064
|
);
|
|
5212
5065
|
}
|
|
5213
|
-
var DialogContent =
|
|
5066
|
+
var DialogContent = React7.forwardRef(
|
|
5214
5067
|
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
5215
5068
|
const positionMode = container ? "absolute" : "fixed";
|
|
5216
5069
|
return /* @__PURE__ */ jsxs6(DialogPortal, { container: container ?? void 0, children: [
|
|
@@ -5265,7 +5118,7 @@ function DialogFooter({
|
|
|
5265
5118
|
}
|
|
5266
5119
|
);
|
|
5267
5120
|
}
|
|
5268
|
-
var DialogTitle =
|
|
5121
|
+
var DialogTitle = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx12(
|
|
5269
5122
|
DialogPrimitive.Title,
|
|
5270
5123
|
{
|
|
5271
5124
|
ref,
|
|
@@ -5277,7 +5130,7 @@ var DialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE
|
|
|
5277
5130
|
}
|
|
5278
5131
|
));
|
|
5279
5132
|
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
5280
|
-
var DialogDescription =
|
|
5133
|
+
var DialogDescription = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx12(
|
|
5281
5134
|
DialogPrimitive.Description,
|
|
5282
5135
|
{
|
|
5283
5136
|
ref,
|
|
@@ -5379,12 +5232,12 @@ function SectionTreeItem({
|
|
|
5379
5232
|
}
|
|
5380
5233
|
|
|
5381
5234
|
// src/ui/link-modal/UrlOrPageInput.tsx
|
|
5382
|
-
import { useEffect as useEffect3, useId as useId2, useRef as
|
|
5235
|
+
import { useEffect as useEffect3, useId as useId2, useRef as useRef3, useState as useState3 } from "react";
|
|
5383
5236
|
|
|
5384
5237
|
// src/ui/input.tsx
|
|
5385
|
-
import * as
|
|
5238
|
+
import * as React8 from "react";
|
|
5386
5239
|
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
5387
|
-
var Input =
|
|
5240
|
+
var Input = React8.forwardRef(
|
|
5388
5241
|
({ className, type, ...props }, ref) => {
|
|
5389
5242
|
return /* @__PURE__ */ jsx15(
|
|
5390
5243
|
"input",
|
|
@@ -5448,8 +5301,8 @@ function UrlOrPageInput({
|
|
|
5448
5301
|
urlError
|
|
5449
5302
|
}) {
|
|
5450
5303
|
const inputId = useId2();
|
|
5451
|
-
const inputRef =
|
|
5452
|
-
const rootRef =
|
|
5304
|
+
const inputRef = useRef3(null);
|
|
5305
|
+
const rootRef = useRef3(null);
|
|
5453
5306
|
const [isFocused, setIsFocused] = useState3(false);
|
|
5454
5307
|
useEffect3(() => {
|
|
5455
5308
|
if (!dropdownOpen) return;
|
|
@@ -5659,7 +5512,7 @@ function LinkEditorPanel({ state, onClose }) {
|
|
|
5659
5512
|
}
|
|
5660
5513
|
|
|
5661
5514
|
// src/ui/link-modal/SectionPickerOverlay.tsx
|
|
5662
|
-
import { useCallback
|
|
5515
|
+
import { useCallback, useEffect as useEffect4, useMemo as useMemo2, useRef as useRef4, useState as useState4 } from "react";
|
|
5663
5516
|
import { createPortal } from "react-dom";
|
|
5664
5517
|
import { ArrowLeft, Check } from "lucide-react";
|
|
5665
5518
|
import { usePathname, useRouter } from "next/navigation";
|
|
@@ -5744,10 +5597,10 @@ function SectionPickerOverlay({
|
|
|
5744
5597
|
const pathname = usePathname();
|
|
5745
5598
|
const [selectedId, setSelectedId] = useState4(null);
|
|
5746
5599
|
const [hoveredId, setHoveredId] = useState4(null);
|
|
5747
|
-
const pointerRef =
|
|
5748
|
-
const pointerScreenRef =
|
|
5749
|
-
const iframeOffsetTopRef =
|
|
5750
|
-
const sectionIdsRef =
|
|
5600
|
+
const pointerRef = useRef4(null);
|
|
5601
|
+
const pointerScreenRef = useRef4(null);
|
|
5602
|
+
const iframeOffsetTopRef = useRef4(null);
|
|
5603
|
+
const sectionIdsRef = useRef4([]);
|
|
5751
5604
|
const [chromeClip, setChromeClip] = useState4(
|
|
5752
5605
|
() => ({
|
|
5753
5606
|
top: 0,
|
|
@@ -5790,7 +5643,7 @@ function SectionPickerOverlay({
|
|
|
5790
5643
|
);
|
|
5791
5644
|
sectionIdsRef.current = sectionIds;
|
|
5792
5645
|
const rects = useSectionRects(sectionIdsKey, isOnTargetPage);
|
|
5793
|
-
const applyHoverAt =
|
|
5646
|
+
const applyHoverAt = useCallback(
|
|
5794
5647
|
(x, y, liveRects) => {
|
|
5795
5648
|
const ids = sectionIdsRef.current;
|
|
5796
5649
|
const map = liveRects ?? readSectionRects(ids);
|
|
@@ -5870,7 +5723,7 @@ function SectionPickerOverlay({
|
|
|
5870
5723
|
window.removeEventListener("message", onPointerSync);
|
|
5871
5724
|
};
|
|
5872
5725
|
}, [rects, applyHoverAt]);
|
|
5873
|
-
const handleSelect =
|
|
5726
|
+
const handleSelect = useCallback(
|
|
5874
5727
|
(section) => {
|
|
5875
5728
|
if (selectedId) return;
|
|
5876
5729
|
setSelectedId(section.id);
|
|
@@ -6001,7 +5854,7 @@ function SectionPickerOverlay({
|
|
|
6001
5854
|
}
|
|
6002
5855
|
|
|
6003
5856
|
// src/ui/link-modal/useLinkModalState.ts
|
|
6004
|
-
import { useCallback as
|
|
5857
|
+
import { useCallback as useCallback2, useEffect as useEffect5, useMemo as useMemo3, useState as useState5 } from "react";
|
|
6005
5858
|
function useLinkModalState({
|
|
6006
5859
|
open,
|
|
6007
5860
|
mode,
|
|
@@ -6020,7 +5873,7 @@ function useLinkModalState({
|
|
|
6020
5873
|
const [step, setStep] = useState5("input");
|
|
6021
5874
|
const [dropdownOpen, setDropdownOpen] = useState5(false);
|
|
6022
5875
|
const [urlError, setUrlError] = useState5("");
|
|
6023
|
-
const reset =
|
|
5876
|
+
const reset = useCallback2(() => {
|
|
6024
5877
|
setSearchValue("");
|
|
6025
5878
|
setSelectedPage(null);
|
|
6026
5879
|
setSelectedSection(null);
|
|
@@ -6365,155 +6218,9 @@ function shouldUseDevFixtures() {
|
|
|
6365
6218
|
return new URLSearchParams(q).get("ohw-fixtures") === "1";
|
|
6366
6219
|
}
|
|
6367
6220
|
|
|
6368
|
-
// src/lib/nav-tree.ts
|
|
6369
|
-
var MAX_LEVEL = { nav: 1 };
|
|
6370
|
-
var ROOT = null;
|
|
6371
|
-
function cloneForest(nodes) {
|
|
6372
|
-
return nodes.map((n) => ({ id: n.id, children: cloneForest(n.children) }));
|
|
6373
|
-
}
|
|
6374
|
-
function findNode(nodes, id, parentId = ROOT) {
|
|
6375
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
6376
|
-
const node = nodes[i];
|
|
6377
|
-
if (node.id === id) return { node, parentId, index: i, siblings: nodes };
|
|
6378
|
-
const nested = findNode(node.children, id, node.id);
|
|
6379
|
-
if (nested) return nested;
|
|
6380
|
-
}
|
|
6381
|
-
return null;
|
|
6382
|
-
}
|
|
6383
|
-
function getChildrenOf(nodes, parentId) {
|
|
6384
|
-
if (parentId === ROOT) return nodes;
|
|
6385
|
-
const found = findNode(nodes, parentId);
|
|
6386
|
-
return found ? found.node.children : null;
|
|
6387
|
-
}
|
|
6388
|
-
function isDescendant(nodes, ancestorId, maybeDescendantId) {
|
|
6389
|
-
const found = findNode(nodes, ancestorId);
|
|
6390
|
-
if (!found) return false;
|
|
6391
|
-
return findNode(found.node.children, maybeDescendantId) !== null;
|
|
6392
|
-
}
|
|
6393
|
-
function levelOf(nodes, id) {
|
|
6394
|
-
const loc = findNode(nodes, id);
|
|
6395
|
-
if (!loc) return -1;
|
|
6396
|
-
if (loc.parentId === ROOT) return 0;
|
|
6397
|
-
return 1 + Math.max(0, levelOf(nodes, loc.parentId));
|
|
6398
|
-
}
|
|
6399
|
-
function insertedLevel(nodes, parentId) {
|
|
6400
|
-
if (parentId === ROOT) return 0;
|
|
6401
|
-
const parentLevel = levelOf(nodes, parentId);
|
|
6402
|
-
if (parentLevel < 0) return -1;
|
|
6403
|
-
return parentLevel + 1;
|
|
6404
|
-
}
|
|
6405
|
-
function takeNode(nodes, id) {
|
|
6406
|
-
const forest = cloneForest(nodes);
|
|
6407
|
-
const loc = findNode(forest, id);
|
|
6408
|
-
if (!loc) return null;
|
|
6409
|
-
const [taken] = loc.siblings.splice(loc.index, 1);
|
|
6410
|
-
if (!taken) return null;
|
|
6411
|
-
return { forest, taken };
|
|
6412
|
-
}
|
|
6413
|
-
function insertInto(forest, node, parentId, index) {
|
|
6414
|
-
const siblings = getChildrenOf(forest, parentId);
|
|
6415
|
-
if (!siblings) return false;
|
|
6416
|
-
const clamped = Math.max(0, Math.min(index, siblings.length));
|
|
6417
|
-
siblings.splice(clamped, 0, node);
|
|
6418
|
-
return true;
|
|
6419
|
-
}
|
|
6420
|
-
function normalize(nodes) {
|
|
6421
|
-
const walk = (list) => list.map((n) => {
|
|
6422
|
-
const children = walk(n.children);
|
|
6423
|
-
return { id: n.id, children };
|
|
6424
|
-
});
|
|
6425
|
-
return walk(nodes);
|
|
6426
|
-
}
|
|
6427
|
-
function moveNode(model, draggedId, target) {
|
|
6428
|
-
const { parentId, index: targetIndex } = target;
|
|
6429
|
-
if (parentId === draggedId) return null;
|
|
6430
|
-
if (parentId !== ROOT && isDescendant(model, draggedId, parentId)) return null;
|
|
6431
|
-
const nextLevel = insertedLevel(model, parentId);
|
|
6432
|
-
if (nextLevel < 0 || nextLevel > MAX_LEVEL.nav) return null;
|
|
6433
|
-
const draggedLoc = findNode(model, draggedId);
|
|
6434
|
-
if (!draggedLoc) return null;
|
|
6435
|
-
if (parentId !== ROOT && draggedLoc.node.children.length > 0) return null;
|
|
6436
|
-
const taken = takeNode(model, draggedId);
|
|
6437
|
-
if (!taken) return null;
|
|
6438
|
-
let insertIndex = targetIndex;
|
|
6439
|
-
if (draggedLoc.parentId === parentId && draggedLoc.index < targetIndex) {
|
|
6440
|
-
insertIndex -= 1;
|
|
6441
|
-
}
|
|
6442
|
-
if (!insertInto(taken.forest, taken.taken, parentId, insertIndex)) return null;
|
|
6443
|
-
const next = normalize(taken.forest);
|
|
6444
|
-
if (forestsEqual(model, next)) return null;
|
|
6445
|
-
return next;
|
|
6446
|
-
}
|
|
6447
|
-
function forestsEqual(a, b) {
|
|
6448
|
-
if (a.length !== b.length) return false;
|
|
6449
|
-
for (let i = 0; i < a.length; i++) {
|
|
6450
|
-
const left = a[i];
|
|
6451
|
-
const right = b[i];
|
|
6452
|
-
if (left.id !== right.id) return false;
|
|
6453
|
-
if (!forestsEqual(left.children, right.children)) return false;
|
|
6454
|
-
}
|
|
6455
|
-
return true;
|
|
6456
|
-
}
|
|
6457
|
-
function forestFromFlatOrder(order) {
|
|
6458
|
-
return order.map((id) => ({ id, children: [] }));
|
|
6459
|
-
}
|
|
6460
|
-
function serializeNavOrder(nodes) {
|
|
6461
|
-
const hasNesting = nodes.some((n) => n.children.length > 0);
|
|
6462
|
-
if (!hasNesting) {
|
|
6463
|
-
return JSON.stringify(nodes.map((n) => n.id));
|
|
6464
|
-
}
|
|
6465
|
-
return JSON.stringify(nodes);
|
|
6466
|
-
}
|
|
6467
|
-
function parseNavOrderJson(raw) {
|
|
6468
|
-
if (!raw) return null;
|
|
6469
|
-
try {
|
|
6470
|
-
const parsed = JSON.parse(raw);
|
|
6471
|
-
if (!Array.isArray(parsed)) return null;
|
|
6472
|
-
if (parsed.every((x) => typeof x === "string")) {
|
|
6473
|
-
return forestFromFlatOrder(parsed.filter((x) => typeof x === "string" && x.length > 0));
|
|
6474
|
-
}
|
|
6475
|
-
return parseNavNodeList(parsed);
|
|
6476
|
-
} catch {
|
|
6477
|
-
return null;
|
|
6478
|
-
}
|
|
6479
|
-
}
|
|
6480
|
-
function parseNavNodeList(raw) {
|
|
6481
|
-
const out = [];
|
|
6482
|
-
for (const item of raw) {
|
|
6483
|
-
if (typeof item === "string" && item.length > 0) {
|
|
6484
|
-
out.push({ id: item, children: [] });
|
|
6485
|
-
continue;
|
|
6486
|
-
}
|
|
6487
|
-
if (!item || typeof item !== "object") return null;
|
|
6488
|
-
const rec = item;
|
|
6489
|
-
if (typeof rec.id !== "string" || !rec.id) return null;
|
|
6490
|
-
const children = Array.isArray(rec.children) ? parseNavNodeList(rec.children) : [];
|
|
6491
|
-
if (!children) return null;
|
|
6492
|
-
out.push({ id: rec.id, children });
|
|
6493
|
-
}
|
|
6494
|
-
return out;
|
|
6495
|
-
}
|
|
6496
|
-
function flattenNavOrder(nodes) {
|
|
6497
|
-
const out = [];
|
|
6498
|
-
const walk = (list) => {
|
|
6499
|
-
for (const n of list) {
|
|
6500
|
-
out.push(n.id);
|
|
6501
|
-
walk(n.children);
|
|
6502
|
-
}
|
|
6503
|
-
};
|
|
6504
|
-
walk(nodes);
|
|
6505
|
-
return out;
|
|
6506
|
-
}
|
|
6507
|
-
|
|
6508
6221
|
// src/lib/nav-items.ts
|
|
6509
6222
|
var NAV_COUNT_KEY = "__ohw_nav_count";
|
|
6510
6223
|
var NAV_ORDER_KEY = "__ohw_nav_order";
|
|
6511
|
-
var NAV_HREF_RE = /^nav-(\d+)-href$/;
|
|
6512
|
-
function isNavbarHrefKey(key) {
|
|
6513
|
-
if (!key) return false;
|
|
6514
|
-
if (key === "nav-book-href") return false;
|
|
6515
|
-
return NAV_HREF_RE.test(key);
|
|
6516
|
-
}
|
|
6517
6224
|
function getLinkHref(el) {
|
|
6518
6225
|
const key = el.getAttribute("data-ohw-href-key");
|
|
6519
6226
|
if (key) {
|
|
@@ -6550,7 +6257,7 @@ function listNavbarItems() {
|
|
|
6550
6257
|
}
|
|
6551
6258
|
function parseNavIndexFromKey(key) {
|
|
6552
6259
|
if (!key) return null;
|
|
6553
|
-
const match = key.match(
|
|
6260
|
+
const match = key.match(/^nav-(\d+)-href$/);
|
|
6554
6261
|
if (!match) return null;
|
|
6555
6262
|
return parseInt(match[1], 10);
|
|
6556
6263
|
}
|
|
@@ -6573,6 +6280,17 @@ function getNavbarExistingTargets() {
|
|
|
6573
6280
|
function getNavOrderFromDom() {
|
|
6574
6281
|
return listNavbarItems().map((el) => el.getAttribute("data-ohw-href-key")).filter((key) => Boolean(key));
|
|
6575
6282
|
}
|
|
6283
|
+
function parseNavOrder(content) {
|
|
6284
|
+
const raw = content[NAV_ORDER_KEY];
|
|
6285
|
+
if (!raw) return null;
|
|
6286
|
+
try {
|
|
6287
|
+
const parsed = JSON.parse(raw);
|
|
6288
|
+
if (!Array.isArray(parsed)) return null;
|
|
6289
|
+
return parsed.filter((key) => typeof key === "string" && key.length > 0);
|
|
6290
|
+
} catch {
|
|
6291
|
+
return null;
|
|
6292
|
+
}
|
|
6293
|
+
}
|
|
6576
6294
|
function findCounterpartByHrefKey(hrefKey, root) {
|
|
6577
6295
|
return root.querySelector(`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`);
|
|
6578
6296
|
}
|
|
@@ -6636,47 +6354,19 @@ function insertNavbarItemDom(index, href, label, afterAnchor) {
|
|
|
6636
6354
|
}
|
|
6637
6355
|
return primary;
|
|
6638
6356
|
}
|
|
6639
|
-
function navOrderKeysEqual(a, b) {
|
|
6640
|
-
if (a.length !== b.length) return false;
|
|
6641
|
-
for (let i = 0; i < a.length; i++) {
|
|
6642
|
-
if (a[i] !== b[i]) return false;
|
|
6643
|
-
}
|
|
6644
|
-
return true;
|
|
6645
|
-
}
|
|
6646
|
-
function getNavbarLinkKeysInContainer(container) {
|
|
6647
|
-
return Array.from(container.querySelectorAll("[data-ohw-href-key]")).filter(isNavbarLinkItem).map((el) => el.getAttribute("data-ohw-href-key")).filter((key) => Boolean(key));
|
|
6648
|
-
}
|
|
6649
6357
|
function applyNavOrderToContainer(container, order) {
|
|
6650
|
-
const desired = order.filter((key, i) => order.indexOf(key) === i);
|
|
6651
|
-
const current = getNavbarLinkKeysInContainer(container);
|
|
6652
|
-
const extras = current.filter((key) => !desired.includes(key));
|
|
6653
|
-
const expected = [...desired.filter((key) => current.includes(key)), ...extras];
|
|
6654
|
-
const orderedEls = [];
|
|
6655
|
-
if (navOrderKeysEqual(current, expected)) return;
|
|
6656
|
-
if (current.length === expected.length && current.every((key, i) => key === expected[i])) {
|
|
6657
|
-
return;
|
|
6658
|
-
}
|
|
6659
|
-
const lastCurrentLinkEl = current.length > 0 ? findCounterpartByHrefKey(current[current.length - 1], container) : null;
|
|
6660
|
-
const anchor = lastCurrentLinkEl?.parentElement === container ? lastCurrentLinkEl.nextElementSibling : null;
|
|
6661
6358
|
const seen = /* @__PURE__ */ new Set();
|
|
6662
|
-
for (const hrefKey of
|
|
6359
|
+
for (const hrefKey of order) {
|
|
6663
6360
|
if (seen.has(hrefKey)) continue;
|
|
6664
6361
|
seen.add(hrefKey);
|
|
6665
6362
|
const el = findCounterpartByHrefKey(hrefKey, container);
|
|
6666
|
-
if (el
|
|
6363
|
+
if (el) container.appendChild(el);
|
|
6667
6364
|
}
|
|
6668
6365
|
for (const el of container.querySelectorAll("[data-ohw-href-key]")) {
|
|
6669
6366
|
if (!isNavbarLinkItem(el)) continue;
|
|
6670
6367
|
const key = el.getAttribute("data-ohw-href-key");
|
|
6671
6368
|
if (!key || seen.has(key)) continue;
|
|
6672
|
-
|
|
6673
|
-
}
|
|
6674
|
-
for (const el of orderedEls) {
|
|
6675
|
-
if (anchor) {
|
|
6676
|
-
if (el.nextSibling !== anchor) container.insertBefore(el, anchor);
|
|
6677
|
-
} else if (container.lastElementChild !== el) {
|
|
6678
|
-
container.appendChild(el);
|
|
6679
|
-
}
|
|
6369
|
+
container.appendChild(el);
|
|
6680
6370
|
}
|
|
6681
6371
|
}
|
|
6682
6372
|
function applyNavOrder(order) {
|
|
@@ -6685,75 +6375,6 @@ function applyNavOrder(order) {
|
|
|
6685
6375
|
const drawer = getNavbarDrawerContainer();
|
|
6686
6376
|
if (drawer) applyNavOrderToContainer(drawer, order);
|
|
6687
6377
|
}
|
|
6688
|
-
function applyChildrenOrder(parentHrefKey, childKeys, root) {
|
|
6689
|
-
const parent = findCounterpartByHrefKey(parentHrefKey, root);
|
|
6690
|
-
if (!parent) return;
|
|
6691
|
-
const group = parent.closest("[data-ohw-nav-group]");
|
|
6692
|
-
const childrenRoot = group?.querySelector(":scope > [data-ohw-nav-children]");
|
|
6693
|
-
if (!childrenRoot) return;
|
|
6694
|
-
const current = Array.from(childrenRoot.querySelectorAll(":scope > [data-ohw-href-key]")).map((el) => el.getAttribute("data-ohw-href-key")).filter((key) => Boolean(key));
|
|
6695
|
-
if (navOrderKeysEqual(current, childKeys)) return;
|
|
6696
|
-
for (const key of childKeys) {
|
|
6697
|
-
const el = findCounterpartByHrefKey(key, root);
|
|
6698
|
-
if (!el) continue;
|
|
6699
|
-
if (childrenRoot.lastElementChild !== el) {
|
|
6700
|
-
childrenRoot.appendChild(el);
|
|
6701
|
-
}
|
|
6702
|
-
}
|
|
6703
|
-
}
|
|
6704
|
-
function applyNavForest(forest) {
|
|
6705
|
-
if (forestsEqual(forest, getNavForestFromDom())) return;
|
|
6706
|
-
const rootKeys = forest.map((n) => n.id);
|
|
6707
|
-
applyNavOrder(rootKeys);
|
|
6708
|
-
const desktop = getNavbarDesktopContainer();
|
|
6709
|
-
const drawer = getNavbarDrawerContainer();
|
|
6710
|
-
for (const node of forest) {
|
|
6711
|
-
if (node.children.length === 0) continue;
|
|
6712
|
-
const childKeys = node.children.map((c) => c.id);
|
|
6713
|
-
if (desktop) applyChildrenOrder(node.id, childKeys, desktop);
|
|
6714
|
-
if (drawer) applyChildrenOrder(node.id, childKeys, drawer);
|
|
6715
|
-
}
|
|
6716
|
-
}
|
|
6717
|
-
function getNavForestFromDom() {
|
|
6718
|
-
const items = listNavbarItems();
|
|
6719
|
-
const nestedChildKeys = /* @__PURE__ */ new Set();
|
|
6720
|
-
const roots = [];
|
|
6721
|
-
for (const item of items) {
|
|
6722
|
-
const key = item.getAttribute("data-ohw-href-key");
|
|
6723
|
-
if (!key || !isNavbarHrefKey(key)) continue;
|
|
6724
|
-
if (item.closest("[data-ohw-nav-children]")) continue;
|
|
6725
|
-
const group = item.closest("[data-ohw-nav-group]");
|
|
6726
|
-
const childrenRoot = group?.querySelector(":scope > [data-ohw-nav-children]");
|
|
6727
|
-
const children = [];
|
|
6728
|
-
if (childrenRoot) {
|
|
6729
|
-
for (const child of childrenRoot.querySelectorAll(":scope > [data-ohw-href-key]")) {
|
|
6730
|
-
if (!isNavbarLinkItem(child)) continue;
|
|
6731
|
-
const childKey = child.getAttribute("data-ohw-href-key");
|
|
6732
|
-
if (!childKey || !isNavbarHrefKey(childKey)) continue;
|
|
6733
|
-
nestedChildKeys.add(childKey);
|
|
6734
|
-
children.push({ id: childKey, children: [] });
|
|
6735
|
-
}
|
|
6736
|
-
}
|
|
6737
|
-
roots.push({ id: key, children });
|
|
6738
|
-
}
|
|
6739
|
-
if (roots.length === 0) {
|
|
6740
|
-
return forestFromFlatOrder(
|
|
6741
|
-
getNavOrderFromDom().filter((k) => isNavbarHrefKey(k) && !nestedChildKeys.has(k))
|
|
6742
|
-
);
|
|
6743
|
-
}
|
|
6744
|
-
return roots;
|
|
6745
|
-
}
|
|
6746
|
-
function planNavItemMove(hrefKey, parentId, insertIndex) {
|
|
6747
|
-
const model = getNavForestFromDom();
|
|
6748
|
-
const next = moveNode(model, hrefKey, { parentId, index: insertIndex });
|
|
6749
|
-
if (!next) return null;
|
|
6750
|
-
if (forestsEqual(model, next)) return null;
|
|
6751
|
-
return {
|
|
6752
|
-
forest: next,
|
|
6753
|
-
orderJson: serializeNavOrder(next),
|
|
6754
|
-
flatOrder: flattenNavOrder(next)
|
|
6755
|
-
};
|
|
6756
|
-
}
|
|
6757
6378
|
function collectNavbarIndicesFromContent(content) {
|
|
6758
6379
|
const indices = /* @__PURE__ */ new Set();
|
|
6759
6380
|
for (const key of Object.keys(content)) {
|
|
@@ -6781,10 +6402,8 @@ function reconcileNavbarItemsFromContent(content) {
|
|
|
6781
6402
|
if (!href && !label) continue;
|
|
6782
6403
|
insertNavbarItemDom(index, href ?? "/", label ?? "Untitled", null);
|
|
6783
6404
|
}
|
|
6784
|
-
const
|
|
6785
|
-
if (
|
|
6786
|
-
applyNavForest(orderForest);
|
|
6787
|
-
}
|
|
6405
|
+
const order = parseNavOrder(content);
|
|
6406
|
+
if (order?.length) applyNavOrder(order);
|
|
6788
6407
|
}
|
|
6789
6408
|
function buildNavOrderAfterInsert(afterAnchor, newHrefKey) {
|
|
6790
6409
|
const order = getNavOrderFromDom();
|
|
@@ -6824,982 +6443,75 @@ function insertNavbarItem(href, label, afterAnchor = null) {
|
|
|
6824
6443
|
};
|
|
6825
6444
|
}
|
|
6826
6445
|
|
|
6827
|
-
// src/
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
function
|
|
6831
|
-
|
|
6832
|
-
|
|
6833
|
-
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
|
|
6837
|
-
|
|
6838
|
-
|
|
6839
|
-
|
|
6840
|
-
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
|
|
6846
|
-
|
|
6847
|
-
|
|
6848
|
-
|
|
6849
|
-
|
|
6850
|
-
|
|
6851
|
-
|
|
6852
|
-
|
|
6853
|
-
|
|
6854
|
-
|
|
6855
|
-
|
|
6856
|
-
|
|
6857
|
-
|
|
6858
|
-
|
|
6859
|
-
|
|
6860
|
-
|
|
6861
|
-
|
|
6862
|
-
|
|
6863
|
-
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
function findFooterColumnForLink(anchor) {
|
|
6868
|
-
const columns = listFooterColumns();
|
|
6869
|
-
return columns.find((col) => col.contains(anchor)) ?? null;
|
|
6870
|
-
}
|
|
6871
|
-
function getFooterOrderFromDom() {
|
|
6872
|
-
return listFooterColumns().map(
|
|
6873
|
-
(col) => listFooterLinksInColumn(col).map((el) => el.getAttribute("data-ohw-href-key")).filter((key) => Boolean(key))
|
|
6874
|
-
);
|
|
6875
|
-
}
|
|
6876
|
-
function findFooterLinkByKey(hrefKey) {
|
|
6877
|
-
return document.querySelector(
|
|
6878
|
-
`footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
6879
|
-
);
|
|
6880
|
-
}
|
|
6881
|
-
function syncFooterColumnIndices(columns) {
|
|
6882
|
-
columns.forEach((col, index) => {
|
|
6883
|
-
const next = String(index);
|
|
6884
|
-
if (col.getAttribute("data-ohw-footer-col") !== next) {
|
|
6885
|
-
col.setAttribute("data-ohw-footer-col", next);
|
|
6446
|
+
// src/ui/navbar-container-chrome.tsx
|
|
6447
|
+
import { Plus as Plus2 } from "lucide-react";
|
|
6448
|
+
import { jsx as jsx21 } from "react/jsx-runtime";
|
|
6449
|
+
function NavbarContainerChrome({
|
|
6450
|
+
rect,
|
|
6451
|
+
onAdd
|
|
6452
|
+
}) {
|
|
6453
|
+
const chromeGap = 6;
|
|
6454
|
+
return /* @__PURE__ */ jsx21(
|
|
6455
|
+
"div",
|
|
6456
|
+
{
|
|
6457
|
+
"data-ohw-navbar-container-chrome": "",
|
|
6458
|
+
"data-ohw-bridge": "",
|
|
6459
|
+
className: "pointer-events-none fixed z-[2147483647]",
|
|
6460
|
+
style: {
|
|
6461
|
+
top: rect.top - chromeGap,
|
|
6462
|
+
left: rect.left - chromeGap,
|
|
6463
|
+
width: rect.width + chromeGap * 2,
|
|
6464
|
+
height: rect.height + chromeGap * 2
|
|
6465
|
+
},
|
|
6466
|
+
children: /* @__PURE__ */ jsx21(
|
|
6467
|
+
"button",
|
|
6468
|
+
{
|
|
6469
|
+
type: "button",
|
|
6470
|
+
"data-ohw-navbar-add-button": "",
|
|
6471
|
+
className: "pointer-events-auto absolute left-1/2 flex p-0.5 rounded-[10px] size-7 -translate-x-1/2 translate-y-1/2 items-center justify-center border border-border bg-background shadow-sm transition-colors hover:bg-muted/80",
|
|
6472
|
+
style: { top: "70%" },
|
|
6473
|
+
"aria-label": "Add item",
|
|
6474
|
+
onMouseDown: (e) => {
|
|
6475
|
+
e.preventDefault();
|
|
6476
|
+
e.stopPropagation();
|
|
6477
|
+
},
|
|
6478
|
+
onClick: (e) => {
|
|
6479
|
+
e.preventDefault();
|
|
6480
|
+
e.stopPropagation();
|
|
6481
|
+
onAdd();
|
|
6482
|
+
},
|
|
6483
|
+
children: /* @__PURE__ */ jsx21(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
6484
|
+
}
|
|
6485
|
+
)
|
|
6886
6486
|
}
|
|
6887
|
-
|
|
6888
|
-
}
|
|
6889
|
-
function appendChildIfNeeded(parent, child) {
|
|
6890
|
-
if (parent.lastElementChild !== child) {
|
|
6891
|
-
parent.appendChild(child);
|
|
6892
|
-
}
|
|
6487
|
+
);
|
|
6893
6488
|
}
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
|
|
6900
|
-
|
|
6901
|
-
|
|
6902
|
-
|
|
6903
|
-
|
|
6904
|
-
|
|
6905
|
-
|
|
6906
|
-
for (const colOrder of order) {
|
|
6907
|
-
let matched = null;
|
|
6908
|
-
for (const hrefKey of colOrder) {
|
|
6909
|
-
const link = findFooterLinkByKey(hrefKey);
|
|
6910
|
-
if (!link) continue;
|
|
6911
|
-
const owner = findFooterColumnForLink(link);
|
|
6912
|
-
if (owner && !used.has(owner)) {
|
|
6913
|
-
matched = owner;
|
|
6914
|
-
break;
|
|
6915
|
-
}
|
|
6916
|
-
}
|
|
6917
|
-
if (!matched) {
|
|
6918
|
-
matched = columns.find((col) => !used.has(col)) ?? null;
|
|
6919
|
-
}
|
|
6920
|
-
if (matched) {
|
|
6921
|
-
used.add(matched);
|
|
6922
|
-
orderedCols.push(matched);
|
|
6923
|
-
}
|
|
6924
|
-
}
|
|
6925
|
-
for (const col of columns) {
|
|
6926
|
-
if (!used.has(col)) orderedCols.push(col);
|
|
6927
|
-
}
|
|
6928
|
-
for (const col of orderedCols) {
|
|
6929
|
-
appendChildIfNeeded(container, col);
|
|
6930
|
-
}
|
|
6931
|
-
const freshColumns = listFooterColumns();
|
|
6932
|
-
syncFooterColumnIndices(freshColumns);
|
|
6933
|
-
for (let c = 0; c < order.length; c++) {
|
|
6934
|
-
const col = freshColumns[c];
|
|
6935
|
-
if (!col) continue;
|
|
6936
|
-
const colOrder = order[c];
|
|
6937
|
-
for (const hrefKey of colOrder) {
|
|
6938
|
-
const el = findFooterLinkByKey(hrefKey);
|
|
6939
|
-
if (!el) continue;
|
|
6940
|
-
if (el.parentElement !== col || col.lastElementChild !== el) {
|
|
6941
|
-
col.appendChild(el);
|
|
6489
|
+
|
|
6490
|
+
// src/ui/badge.tsx
|
|
6491
|
+
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
6492
|
+
var badgeVariants = cva(
|
|
6493
|
+
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
6494
|
+
{
|
|
6495
|
+
variants: {
|
|
6496
|
+
variant: {
|
|
6497
|
+
default: "border-transparent bg-primary text-primary-foreground",
|
|
6498
|
+
secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
6499
|
+
destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
|
|
6500
|
+
outline: "text-foreground"
|
|
6942
6501
|
}
|
|
6502
|
+
},
|
|
6503
|
+
defaultVariants: {
|
|
6504
|
+
variant: "default"
|
|
6943
6505
|
}
|
|
6944
6506
|
}
|
|
6945
|
-
|
|
6946
|
-
function
|
|
6947
|
-
|
|
6948
|
-
for (let i = 0; i < a.length; i++) {
|
|
6949
|
-
const left = a[i];
|
|
6950
|
-
const right = b[i];
|
|
6951
|
-
if (left.length !== right.length) return false;
|
|
6952
|
-
for (let j = 0; j < left.length; j++) {
|
|
6953
|
-
if (left[j] !== right[j]) return false;
|
|
6954
|
-
}
|
|
6955
|
-
}
|
|
6956
|
-
return true;
|
|
6957
|
-
}
|
|
6958
|
-
function planFooterLinkMove(hrefKey, targetColIndex, insertIndex) {
|
|
6959
|
-
const order = getFooterOrderFromDom();
|
|
6960
|
-
if (targetColIndex < 0 || targetColIndex >= order.length) return null;
|
|
6961
|
-
let fromCol = -1;
|
|
6962
|
-
let fromIdx = -1;
|
|
6963
|
-
for (let c = 0; c < order.length; c++) {
|
|
6964
|
-
const idx = order[c].indexOf(hrefKey);
|
|
6965
|
-
if (idx >= 0) {
|
|
6966
|
-
fromCol = c;
|
|
6967
|
-
fromIdx = idx;
|
|
6968
|
-
break;
|
|
6969
|
-
}
|
|
6970
|
-
}
|
|
6971
|
-
if (fromCol < 0) return null;
|
|
6972
|
-
const next = order.map((col) => [...col]);
|
|
6973
|
-
next[fromCol].splice(fromIdx, 1);
|
|
6974
|
-
let adjusted = insertIndex;
|
|
6975
|
-
if (fromCol === targetColIndex && fromIdx < insertIndex) adjusted -= 1;
|
|
6976
|
-
adjusted = Math.max(0, Math.min(adjusted, next[targetColIndex].length));
|
|
6977
|
-
next[targetColIndex].splice(adjusted, 0, hrefKey);
|
|
6978
|
-
if (ordersEqual(next, order)) return null;
|
|
6979
|
-
return next;
|
|
6980
|
-
}
|
|
6981
|
-
function planFooterColumnMove(fromIndex, toIndex) {
|
|
6982
|
-
const order = getFooterOrderFromDom();
|
|
6983
|
-
const columns = listFooterColumns();
|
|
6984
|
-
if (fromIndex < 0 || fromIndex >= columns.length || toIndex < 0 || toIndex > columns.length) {
|
|
6985
|
-
return null;
|
|
6986
|
-
}
|
|
6987
|
-
if (toIndex === fromIndex || toIndex === fromIndex + 1) return null;
|
|
6988
|
-
const nextOrder = order.map((col) => [...col]);
|
|
6989
|
-
const [movedOrder] = nextOrder.splice(fromIndex, 1);
|
|
6990
|
-
if (!movedOrder) return null;
|
|
6991
|
-
let adjusted = toIndex;
|
|
6992
|
-
if (fromIndex < toIndex) adjusted -= 1;
|
|
6993
|
-
adjusted = Math.max(0, Math.min(adjusted, nextOrder.length));
|
|
6994
|
-
nextOrder.splice(adjusted, 0, movedOrder);
|
|
6995
|
-
if (ordersEqual(nextOrder, order)) return null;
|
|
6996
|
-
return nextOrder;
|
|
6997
|
-
}
|
|
6998
|
-
function parseFooterOrder(content) {
|
|
6999
|
-
const raw = content[FOOTER_ORDER_KEY];
|
|
7000
|
-
if (!raw) return null;
|
|
7001
|
-
try {
|
|
7002
|
-
const parsed = JSON.parse(raw);
|
|
7003
|
-
if (!Array.isArray(parsed)) return null;
|
|
7004
|
-
return parsed.filter((col) => Array.isArray(col)).map((col) => col.filter((key) => typeof key === "string" && key.length > 0));
|
|
7005
|
-
} catch {
|
|
7006
|
-
return null;
|
|
7007
|
-
}
|
|
7008
|
-
}
|
|
7009
|
-
function reconcileFooterOrderFromContent(content) {
|
|
7010
|
-
const order = parseFooterOrder(content);
|
|
7011
|
-
if (!order?.length) return;
|
|
7012
|
-
const current = getFooterOrderFromDom();
|
|
7013
|
-
if (ordersEqual(order, current)) {
|
|
7014
|
-
syncFooterColumnIndices(listFooterColumns());
|
|
7015
|
-
return;
|
|
7016
|
-
}
|
|
7017
|
-
applyFooterOrder(order);
|
|
7018
|
-
}
|
|
7019
|
-
function isRowLayoutColumn(links) {
|
|
7020
|
-
if (links.length < 2) return false;
|
|
7021
|
-
const firstTop = links[0].getBoundingClientRect().top;
|
|
7022
|
-
return links.every((link) => Math.abs(link.getBoundingClientRect().top - firstTop) < 4);
|
|
7023
|
-
}
|
|
7024
|
-
function buildLinkDropSlots(column, columnIndex) {
|
|
7025
|
-
const links = listFooterLinksInColumn(column);
|
|
7026
|
-
const colRect = column.getBoundingClientRect();
|
|
7027
|
-
const slots = [];
|
|
7028
|
-
const barThickness = 3;
|
|
7029
|
-
if (links.length === 0) {
|
|
7030
|
-
slots.push({
|
|
7031
|
-
insertIndex: 0,
|
|
7032
|
-
columnIndex,
|
|
7033
|
-
left: colRect.left,
|
|
7034
|
-
top: colRect.top + colRect.height / 2 - barThickness / 2,
|
|
7035
|
-
width: colRect.width,
|
|
7036
|
-
height: barThickness,
|
|
7037
|
-
direction: "horizontal"
|
|
7038
|
-
});
|
|
7039
|
-
return slots;
|
|
7040
|
-
}
|
|
7041
|
-
if (isRowLayoutColumn(links)) {
|
|
7042
|
-
for (let i = 0; i <= links.length; i++) {
|
|
7043
|
-
let left;
|
|
7044
|
-
if (i === 0) {
|
|
7045
|
-
left = links[0].getBoundingClientRect().left - barThickness / 2;
|
|
7046
|
-
} else if (i === links.length) {
|
|
7047
|
-
const last = links[links.length - 1].getBoundingClientRect();
|
|
7048
|
-
left = last.right - barThickness / 2;
|
|
7049
|
-
} else {
|
|
7050
|
-
const prev = links[i - 1].getBoundingClientRect();
|
|
7051
|
-
const next = links[i].getBoundingClientRect();
|
|
7052
|
-
left = (prev.right + next.left) / 2 - barThickness / 2;
|
|
7053
|
-
}
|
|
7054
|
-
const heightRef = i === 0 ? links[0].getBoundingClientRect() : i === links.length ? links[links.length - 1].getBoundingClientRect() : links[i].getBoundingClientRect();
|
|
7055
|
-
slots.push({
|
|
7056
|
-
insertIndex: i,
|
|
7057
|
-
columnIndex,
|
|
7058
|
-
left,
|
|
7059
|
-
top: heightRef.top,
|
|
7060
|
-
width: barThickness,
|
|
7061
|
-
height: Math.max(heightRef.height, colRect.height * 0.8),
|
|
7062
|
-
direction: "vertical"
|
|
7063
|
-
});
|
|
7064
|
-
}
|
|
7065
|
-
return slots;
|
|
7066
|
-
}
|
|
7067
|
-
for (let i = 0; i <= links.length; i++) {
|
|
7068
|
-
let top;
|
|
7069
|
-
if (i === 0) {
|
|
7070
|
-
top = links[0].getBoundingClientRect().top - barThickness / 2;
|
|
7071
|
-
} else if (i === links.length) {
|
|
7072
|
-
const last = links[links.length - 1].getBoundingClientRect();
|
|
7073
|
-
top = last.bottom - barThickness / 2;
|
|
7074
|
-
} else {
|
|
7075
|
-
const prev = links[i - 1].getBoundingClientRect();
|
|
7076
|
-
const next = links[i].getBoundingClientRect();
|
|
7077
|
-
top = (prev.bottom + next.top) / 2 - barThickness / 2;
|
|
7078
|
-
}
|
|
7079
|
-
const widthRef = i === 0 ? links[0].getBoundingClientRect() : i === links.length ? links[links.length - 1].getBoundingClientRect() : links[i].getBoundingClientRect();
|
|
7080
|
-
slots.push({
|
|
7081
|
-
insertIndex: i,
|
|
7082
|
-
columnIndex,
|
|
7083
|
-
left: widthRef.left,
|
|
7084
|
-
top,
|
|
7085
|
-
width: Math.max(widthRef.width, colRect.width * 0.8),
|
|
7086
|
-
height: barThickness,
|
|
7087
|
-
direction: "horizontal"
|
|
7088
|
-
});
|
|
7089
|
-
}
|
|
7090
|
-
return slots;
|
|
7091
|
-
}
|
|
7092
|
-
function buildColumnDropSlots() {
|
|
7093
|
-
const columns = listFooterColumns();
|
|
7094
|
-
const slots = [];
|
|
7095
|
-
const barThickness = 3;
|
|
7096
|
-
if (columns.length === 0) return slots;
|
|
7097
|
-
for (let i = 0; i <= columns.length; i++) {
|
|
7098
|
-
let left;
|
|
7099
|
-
let height;
|
|
7100
|
-
let top;
|
|
7101
|
-
if (i === 0) {
|
|
7102
|
-
const first = columns[0].getBoundingClientRect();
|
|
7103
|
-
left = first.left - barThickness / 2;
|
|
7104
|
-
top = first.top;
|
|
7105
|
-
height = first.height;
|
|
7106
|
-
} else if (i === columns.length) {
|
|
7107
|
-
const last = columns[columns.length - 1].getBoundingClientRect();
|
|
7108
|
-
left = last.right - barThickness / 2;
|
|
7109
|
-
top = last.top;
|
|
7110
|
-
height = last.height;
|
|
7111
|
-
} else {
|
|
7112
|
-
const prev = columns[i - 1].getBoundingClientRect();
|
|
7113
|
-
const next = columns[i].getBoundingClientRect();
|
|
7114
|
-
left = (prev.right + next.left) / 2 - barThickness / 2;
|
|
7115
|
-
top = Math.min(prev.top, next.top);
|
|
7116
|
-
height = Math.max(prev.bottom, next.bottom) - top;
|
|
7117
|
-
}
|
|
7118
|
-
slots.push({
|
|
7119
|
-
insertIndex: i,
|
|
7120
|
-
columnIndex: i,
|
|
7121
|
-
left,
|
|
7122
|
-
top,
|
|
7123
|
-
width: barThickness,
|
|
7124
|
-
height: Math.max(height, 24),
|
|
7125
|
-
direction: "vertical"
|
|
7126
|
-
});
|
|
7127
|
-
}
|
|
7128
|
-
return slots;
|
|
7129
|
-
}
|
|
7130
|
-
function hitTestLinkDropSlot(clientX, clientY, draggedHrefKey) {
|
|
7131
|
-
const columns = listFooterColumns();
|
|
7132
|
-
let best = null;
|
|
7133
|
-
for (let c = 0; c < columns.length; c++) {
|
|
7134
|
-
const col = columns[c];
|
|
7135
|
-
const colRect = col.getBoundingClientRect();
|
|
7136
|
-
const inColX = clientX >= colRect.left - 24 && clientX <= colRect.right + 24;
|
|
7137
|
-
if (!inColX) continue;
|
|
7138
|
-
const slots = buildLinkDropSlots(col, c).filter((slot) => {
|
|
7139
|
-
const links = listFooterLinksInColumn(col);
|
|
7140
|
-
const fromIdx = links.findIndex(
|
|
7141
|
-
(el) => el.getAttribute("data-ohw-href-key") === draggedHrefKey
|
|
7142
|
-
);
|
|
7143
|
-
if (fromIdx < 0) return true;
|
|
7144
|
-
if (c === findColumnIndexForKey(draggedHrefKey) && (slot.insertIndex === fromIdx || slot.insertIndex === fromIdx + 1)) {
|
|
7145
|
-
return true;
|
|
7146
|
-
}
|
|
7147
|
-
return true;
|
|
7148
|
-
});
|
|
7149
|
-
for (const slot of slots) {
|
|
7150
|
-
const dist = slot.direction === "vertical" ? Math.abs(clientX - (slot.left + slot.width / 2)) : Math.abs(clientY - (slot.top + slot.height / 2));
|
|
7151
|
-
if (!best || dist < best.dist) best = { slot, dist };
|
|
7152
|
-
}
|
|
7153
|
-
}
|
|
7154
|
-
return best?.slot ?? null;
|
|
7155
|
-
}
|
|
7156
|
-
function findColumnIndexForKey(hrefKey) {
|
|
7157
|
-
const order = getFooterOrderFromDom();
|
|
7158
|
-
for (let c = 0; c < order.length; c++) {
|
|
7159
|
-
if (order[c].includes(hrefKey)) return c;
|
|
7160
|
-
}
|
|
7161
|
-
return -1;
|
|
7162
|
-
}
|
|
7163
|
-
function hitTestColumnDropSlot(clientX, _clientY) {
|
|
7164
|
-
const slots = buildColumnDropSlots();
|
|
7165
|
-
let best = null;
|
|
7166
|
-
for (const slot of slots) {
|
|
7167
|
-
const cx2 = slot.left + slot.width / 2;
|
|
7168
|
-
const dist = Math.abs(clientX - cx2);
|
|
7169
|
-
if (!best || dist < best.dist) best = { slot, dist };
|
|
7170
|
-
}
|
|
7171
|
-
return best?.slot ?? null;
|
|
7172
|
-
}
|
|
7173
|
-
|
|
7174
|
-
// src/lib/item-drag-interaction.ts
|
|
7175
|
-
function disableNativeHrefDrag(el) {
|
|
7176
|
-
if (el.draggable) el.draggable = false;
|
|
7177
|
-
if (el.getAttribute("draggable") !== "false") {
|
|
7178
|
-
el.setAttribute("draggable", "false");
|
|
7179
|
-
}
|
|
7180
|
-
}
|
|
7181
|
-
function clearTextSelection() {
|
|
7182
|
-
const sel = window.getSelection();
|
|
7183
|
-
if (sel && !sel.isCollapsed) sel.removeAllRanges();
|
|
7184
|
-
}
|
|
7185
|
-
function armItemPressDrag() {
|
|
7186
|
-
document.documentElement.setAttribute("data-ohw-footer-press-drag", "");
|
|
7187
|
-
}
|
|
7188
|
-
function lockItemDuringDrag() {
|
|
7189
|
-
document.documentElement.removeAttribute("data-ohw-footer-press-drag");
|
|
7190
|
-
document.documentElement.setAttribute("data-ohw-item-dragging", "");
|
|
7191
|
-
clearTextSelection();
|
|
7192
|
-
}
|
|
7193
|
-
function unlockItemDragInteraction() {
|
|
7194
|
-
document.documentElement.removeAttribute("data-ohw-footer-press-drag");
|
|
7195
|
-
document.documentElement.removeAttribute("data-ohw-item-dragging");
|
|
7196
|
-
clearTextSelection();
|
|
7197
|
-
}
|
|
7198
|
-
var armFooterPressDrag = armItemPressDrag;
|
|
7199
|
-
var lockFooterDuringDrag = lockItemDuringDrag;
|
|
7200
|
-
var unlockFooterDragInteraction = unlockItemDragInteraction;
|
|
7201
|
-
|
|
7202
|
-
// src/lib/nav-dnd.ts
|
|
7203
|
-
function listReorderableNavItems() {
|
|
7204
|
-
return listNavbarItems().filter((el) => {
|
|
7205
|
-
const key = el.getAttribute("data-ohw-href-key");
|
|
7206
|
-
return isNavbarHrefKey(key) && !el.closest("[data-ohw-nav-children]");
|
|
7207
|
-
});
|
|
7208
|
-
}
|
|
7209
|
-
function listNavChildren(parentHrefKey) {
|
|
7210
|
-
const items = listNavbarItems();
|
|
7211
|
-
const parent = items.find((el) => el.getAttribute("data-ohw-href-key") === parentHrefKey);
|
|
7212
|
-
if (!parent) return [];
|
|
7213
|
-
const group = parent.closest("[data-ohw-nav-group]");
|
|
7214
|
-
const childrenRoot = group?.querySelector(":scope > [data-ohw-nav-children]");
|
|
7215
|
-
if (!childrenRoot) return [];
|
|
7216
|
-
return Array.from(childrenRoot.querySelectorAll(":scope > [data-ohw-href-key]")).filter(
|
|
7217
|
-
(el) => isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))
|
|
7218
|
-
);
|
|
7219
|
-
}
|
|
7220
|
-
function activeNavListContainer() {
|
|
7221
|
-
const desktop = getNavbarDesktopContainer();
|
|
7222
|
-
if (desktop && desktop.getClientRects().length > 0) {
|
|
7223
|
-
const style = window.getComputedStyle(desktop);
|
|
7224
|
-
if (style.display !== "none" && style.visibility !== "hidden") return desktop;
|
|
7225
|
-
}
|
|
7226
|
-
return getNavbarDrawerContainer();
|
|
7227
|
-
}
|
|
7228
|
-
function buildRootNavDropSlots() {
|
|
7229
|
-
const items = listReorderableNavItems();
|
|
7230
|
-
const slots = [];
|
|
7231
|
-
const barThickness = 3;
|
|
7232
|
-
if (items.length === 0) {
|
|
7233
|
-
const container = activeNavListContainer();
|
|
7234
|
-
if (!container) return slots;
|
|
7235
|
-
const rect = container.getBoundingClientRect();
|
|
7236
|
-
slots.push({
|
|
7237
|
-
insertIndex: 0,
|
|
7238
|
-
parentId: null,
|
|
7239
|
-
left: rect.left + rect.width / 2 - barThickness / 2,
|
|
7240
|
-
top: rect.top,
|
|
7241
|
-
width: barThickness,
|
|
7242
|
-
height: Math.max(rect.height, 24),
|
|
7243
|
-
direction: "vertical"
|
|
7244
|
-
});
|
|
7245
|
-
return slots;
|
|
7246
|
-
}
|
|
7247
|
-
for (let i = 0; i <= items.length; i++) {
|
|
7248
|
-
let left;
|
|
7249
|
-
let top;
|
|
7250
|
-
let height;
|
|
7251
|
-
if (i === 0) {
|
|
7252
|
-
const first = items[0].getBoundingClientRect();
|
|
7253
|
-
left = first.left - barThickness / 2;
|
|
7254
|
-
top = first.top;
|
|
7255
|
-
height = first.height;
|
|
7256
|
-
} else if (i === items.length) {
|
|
7257
|
-
const last = items[items.length - 1].getBoundingClientRect();
|
|
7258
|
-
left = last.right - barThickness / 2;
|
|
7259
|
-
top = last.top;
|
|
7260
|
-
height = last.height;
|
|
7261
|
-
} else {
|
|
7262
|
-
const prev = items[i - 1].getBoundingClientRect();
|
|
7263
|
-
const next = items[i].getBoundingClientRect();
|
|
7264
|
-
left = (prev.right + next.left) / 2 - barThickness / 2;
|
|
7265
|
-
top = Math.min(prev.top, next.top);
|
|
7266
|
-
height = Math.max(prev.bottom, next.bottom) - top;
|
|
7267
|
-
}
|
|
7268
|
-
slots.push({
|
|
7269
|
-
insertIndex: i,
|
|
7270
|
-
parentId: null,
|
|
7271
|
-
left,
|
|
7272
|
-
top,
|
|
7273
|
-
width: barThickness,
|
|
7274
|
-
height: Math.max(height, 24),
|
|
7275
|
-
direction: "vertical"
|
|
7276
|
-
});
|
|
7277
|
-
}
|
|
7278
|
-
return slots;
|
|
7279
|
-
}
|
|
7280
|
-
function buildChildNavDropSlots(parentHrefKey) {
|
|
7281
|
-
const children = listNavChildren(parentHrefKey);
|
|
7282
|
-
const slots = [];
|
|
7283
|
-
const barThickness = 3;
|
|
7284
|
-
if (children.length === 0) return slots;
|
|
7285
|
-
for (let i = 0; i <= children.length; i++) {
|
|
7286
|
-
let top;
|
|
7287
|
-
let width;
|
|
7288
|
-
let left;
|
|
7289
|
-
if (i === 0) {
|
|
7290
|
-
const first = children[0].getBoundingClientRect();
|
|
7291
|
-
top = first.top - barThickness / 2;
|
|
7292
|
-
left = first.left;
|
|
7293
|
-
width = first.width;
|
|
7294
|
-
} else if (i === children.length) {
|
|
7295
|
-
const last = children[children.length - 1].getBoundingClientRect();
|
|
7296
|
-
top = last.bottom - barThickness / 2;
|
|
7297
|
-
left = last.left;
|
|
7298
|
-
width = last.width;
|
|
7299
|
-
} else {
|
|
7300
|
-
const prev = children[i - 1].getBoundingClientRect();
|
|
7301
|
-
const next = children[i].getBoundingClientRect();
|
|
7302
|
-
top = (prev.bottom + next.top) / 2 - barThickness / 2;
|
|
7303
|
-
left = Math.min(prev.left, next.left);
|
|
7304
|
-
width = Math.max(prev.right, next.right) - left;
|
|
7305
|
-
}
|
|
7306
|
-
slots.push({
|
|
7307
|
-
insertIndex: i,
|
|
7308
|
-
parentId: parentHrefKey,
|
|
7309
|
-
left,
|
|
7310
|
-
top,
|
|
7311
|
-
width: Math.max(width, 40),
|
|
7312
|
-
height: barThickness,
|
|
7313
|
-
direction: "horizontal"
|
|
7314
|
-
});
|
|
7315
|
-
}
|
|
7316
|
-
return slots;
|
|
7317
|
-
}
|
|
7318
|
-
function buildAllNavDropSlots(draggedHrefKey) {
|
|
7319
|
-
const slots = [...buildRootNavDropSlots()];
|
|
7320
|
-
for (const item of listReorderableNavItems()) {
|
|
7321
|
-
const key = item.getAttribute("data-ohw-href-key");
|
|
7322
|
-
if (!key || key === draggedHrefKey) continue;
|
|
7323
|
-
const group = item.closest("[data-ohw-nav-group]");
|
|
7324
|
-
if (!group?.querySelector(":scope > [data-ohw-nav-children]")) continue;
|
|
7325
|
-
slots.push(...buildChildNavDropSlots(key));
|
|
7326
|
-
}
|
|
7327
|
-
const dragged = listNavbarItems().find((el) => el.getAttribute("data-ohw-href-key") === draggedHrefKey);
|
|
7328
|
-
const parentGroup = dragged?.closest("[data-ohw-nav-children]")?.closest("[data-ohw-nav-group]");
|
|
7329
|
-
const parentTrigger = parentGroup?.querySelector(":scope > [data-ohw-href-key]");
|
|
7330
|
-
const parentKey = parentTrigger?.getAttribute("data-ohw-href-key");
|
|
7331
|
-
if (parentKey && isNavbarHrefKey(parentKey)) {
|
|
7332
|
-
const existing = slots.some((s) => s.parentId === parentKey);
|
|
7333
|
-
if (!existing) slots.push(...buildChildNavDropSlots(parentKey));
|
|
7334
|
-
}
|
|
7335
|
-
return slots;
|
|
7336
|
-
}
|
|
7337
|
-
function hitTestNavDropSlot(clientX, clientY, draggedHrefKey) {
|
|
7338
|
-
const slots = buildAllNavDropSlots(draggedHrefKey);
|
|
7339
|
-
let best = null;
|
|
7340
|
-
for (const slot of slots) {
|
|
7341
|
-
const cx2 = slot.left + slot.width / 2;
|
|
7342
|
-
const cy = slot.top + slot.height / 2;
|
|
7343
|
-
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;
|
|
7344
|
-
if (!best || dist < best.dist) best = { slot, dist };
|
|
7345
|
-
}
|
|
7346
|
-
return best?.slot ?? null;
|
|
7347
|
-
}
|
|
7348
|
-
function siblingRectsForNavDrag(draggedEl, activeParentId) {
|
|
7349
|
-
if (activeParentId) {
|
|
7350
|
-
return listNavChildren(activeParentId).filter((el) => el !== draggedEl).map((el) => el.getBoundingClientRect());
|
|
7351
|
-
}
|
|
7352
|
-
return listReorderableNavItems().filter((el) => el !== draggedEl).map((el) => el.getBoundingClientRect());
|
|
7353
|
-
}
|
|
7354
|
-
|
|
7355
|
-
// src/useNavItemDrag.ts
|
|
7356
|
-
import { useCallback as useCallback4, useEffect as useEffect7, useRef as useRef6, useState as useState6 } from "react";
|
|
7357
|
-
function useNavItemDrag({
|
|
7358
|
-
isEditMode,
|
|
7359
|
-
editContentRef,
|
|
7360
|
-
selectedElRef,
|
|
7361
|
-
activeElRef,
|
|
7362
|
-
footerDragRef,
|
|
7363
|
-
suppressNextClickRef,
|
|
7364
|
-
suppressClickUntilRef,
|
|
7365
|
-
siblingHintElRef,
|
|
7366
|
-
postToParentRef,
|
|
7367
|
-
deselectRef,
|
|
7368
|
-
selectRef,
|
|
7369
|
-
deactivateRef,
|
|
7370
|
-
setLinkPopover,
|
|
7371
|
-
linkPopoverOpenRef,
|
|
7372
|
-
setIsItemDragging,
|
|
7373
|
-
setDraggedItemRect,
|
|
7374
|
-
setSiblingHintRect,
|
|
7375
|
-
setSiblingHintRects,
|
|
7376
|
-
setToolbarRect,
|
|
7377
|
-
getNavigationItemAnchor: getNavigationItemAnchor2,
|
|
7378
|
-
isDragHandleDisabled: isDragHandleDisabled2,
|
|
7379
|
-
isNavbarButton: isNavbarButton3
|
|
7380
|
-
}) {
|
|
7381
|
-
const navDragRef = useRef6(null);
|
|
7382
|
-
const [navDropSlots, setNavDropSlots] = useState6([]);
|
|
7383
|
-
const [activeNavDropIndex, setActiveNavDropIndex] = useState6(null);
|
|
7384
|
-
const navPointerDragRef = useRef6(null);
|
|
7385
|
-
const clearNavDragVisuals = useCallback4(() => {
|
|
7386
|
-
navDragRef.current = null;
|
|
7387
|
-
setNavDropSlots([]);
|
|
7388
|
-
setActiveNavDropIndex(null);
|
|
7389
|
-
setDraggedItemRect(null);
|
|
7390
|
-
setSiblingHintRects([]);
|
|
7391
|
-
setIsItemDragging(false);
|
|
7392
|
-
unlockItemDragInteraction();
|
|
7393
|
-
}, [setDraggedItemRect, setIsItemDragging, setSiblingHintRects]);
|
|
7394
|
-
const refreshNavDragVisuals = useCallback4(
|
|
7395
|
-
(session, activeSlot, clientX, clientY) => {
|
|
7396
|
-
setDraggedItemRect(session.draggedEl.getBoundingClientRect());
|
|
7397
|
-
if (typeof clientX === "number" && typeof clientY === "number") {
|
|
7398
|
-
session.lastClientX = clientX;
|
|
7399
|
-
session.lastClientY = clientY;
|
|
7400
|
-
}
|
|
7401
|
-
session.activeSlot = activeSlot;
|
|
7402
|
-
const parentId = activeSlot?.parentId ?? null;
|
|
7403
|
-
setSiblingHintRects(siblingRectsForNavDrag(session.draggedEl, parentId));
|
|
7404
|
-
const slots = buildAllNavDropSlots(session.hrefKey);
|
|
7405
|
-
setNavDropSlots(slots);
|
|
7406
|
-
const activeIdx = activeSlot ? slots.findIndex(
|
|
7407
|
-
(s) => s.parentId === activeSlot.parentId && s.insertIndex === activeSlot.insertIndex
|
|
7408
|
-
) : -1;
|
|
7409
|
-
setActiveNavDropIndex(activeIdx >= 0 ? activeIdx : null);
|
|
7410
|
-
},
|
|
7411
|
-
[setDraggedItemRect, setSiblingHintRects]
|
|
7412
|
-
);
|
|
7413
|
-
const refreshNavDragVisualsRef = useRef6(refreshNavDragVisuals);
|
|
7414
|
-
refreshNavDragVisualsRef.current = refreshNavDragVisuals;
|
|
7415
|
-
const commitNavDragRef = useRef6(() => {
|
|
7416
|
-
});
|
|
7417
|
-
const beginNavDragRef = useRef6(() => {
|
|
7418
|
-
});
|
|
7419
|
-
const beginNavDrag = useCallback4(
|
|
7420
|
-
(session) => {
|
|
7421
|
-
const rect = session.draggedEl.getBoundingClientRect();
|
|
7422
|
-
session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
|
|
7423
|
-
session.lastClientY = session.lastClientY || rect.top + rect.height / 2;
|
|
7424
|
-
session.activeSlot = session.activeSlot ?? null;
|
|
7425
|
-
navDragRef.current = session;
|
|
7426
|
-
setIsItemDragging(true);
|
|
7427
|
-
lockItemDuringDrag();
|
|
7428
|
-
siblingHintElRef.current = null;
|
|
7429
|
-
setSiblingHintRect(null);
|
|
7430
|
-
if (session.wasSelected && selectedElRef.current === session.draggedEl) {
|
|
7431
|
-
setToolbarRect(rect);
|
|
7432
|
-
}
|
|
7433
|
-
const initialSlot = hitTestNavDropSlot(session.lastClientX, session.lastClientY, session.hrefKey);
|
|
7434
|
-
refreshNavDragVisuals(session, initialSlot, session.lastClientX, session.lastClientY);
|
|
7435
|
-
},
|
|
7436
|
-
[
|
|
7437
|
-
refreshNavDragVisuals,
|
|
7438
|
-
selectedElRef,
|
|
7439
|
-
setIsItemDragging,
|
|
7440
|
-
setSiblingHintRect,
|
|
7441
|
-
setToolbarRect,
|
|
7442
|
-
siblingHintElRef
|
|
7443
|
-
]
|
|
7444
|
-
);
|
|
7445
|
-
beginNavDragRef.current = beginNavDrag;
|
|
7446
|
-
const commitNavDrag = useCallback4(
|
|
7447
|
-
(clientX, clientY) => {
|
|
7448
|
-
const session = navDragRef.current;
|
|
7449
|
-
if (!session) {
|
|
7450
|
-
clearNavDragVisuals();
|
|
7451
|
-
return;
|
|
7452
|
-
}
|
|
7453
|
-
const x = typeof clientX === "number" && (clientX !== 0 || clientY !== 0) ? clientX : session.lastClientX;
|
|
7454
|
-
const y = typeof clientY === "number" && (clientX !== 0 || clientY !== 0) ? clientY : session.lastClientY;
|
|
7455
|
-
const slot = session.activeSlot ?? hitTestNavDropSlot(x, y, session.hrefKey);
|
|
7456
|
-
const planned = slot != null ? planNavItemMove(session.hrefKey, slot.parentId, slot.insertIndex) : null;
|
|
7457
|
-
const wasSelected = session.wasSelected;
|
|
7458
|
-
const hrefKey = session.hrefKey;
|
|
7459
|
-
const applySelectionAfterDrop = () => {
|
|
7460
|
-
if (!wasSelected) {
|
|
7461
|
-
deselectRef.current();
|
|
7462
|
-
return;
|
|
7463
|
-
}
|
|
7464
|
-
const desktop = document.querySelector("[data-ohw-nav-container]");
|
|
7465
|
-
const drawer = document.querySelector("[data-ohw-nav-drawer]");
|
|
7466
|
-
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)}"]`);
|
|
7467
|
-
if (link) {
|
|
7468
|
-
selectRef.current(link);
|
|
7469
|
-
return;
|
|
7470
|
-
}
|
|
7471
|
-
deselectRef.current();
|
|
7472
|
-
};
|
|
7473
|
-
if (planned) {
|
|
7474
|
-
editContentRef.current = {
|
|
7475
|
-
...editContentRef.current,
|
|
7476
|
-
[NAV_ORDER_KEY]: planned.orderJson
|
|
7477
|
-
};
|
|
7478
|
-
applyNavForest(planned.forest);
|
|
7479
|
-
document.querySelectorAll(
|
|
7480
|
-
"nav [data-ohw-href-key], [data-ohw-nav-container] [data-ohw-href-key], [data-ohw-nav-drawer] [data-ohw-href-key]"
|
|
7481
|
-
).forEach((el) => {
|
|
7482
|
-
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
7483
|
-
disableNativeHrefDrag(el);
|
|
7484
|
-
}
|
|
7485
|
-
});
|
|
7486
|
-
postToParentRef.current({
|
|
7487
|
-
type: "ow:change",
|
|
7488
|
-
nodes: [{ key: NAV_ORDER_KEY, text: planned.orderJson }]
|
|
7489
|
-
});
|
|
7490
|
-
applySelectionAfterDrop();
|
|
7491
|
-
clearNavDragVisuals();
|
|
7492
|
-
requestAnimationFrame(() => {
|
|
7493
|
-
if (editContentRef.current[NAV_ORDER_KEY] === planned.orderJson) {
|
|
7494
|
-
applyNavForest(planned.forest);
|
|
7495
|
-
}
|
|
7496
|
-
applySelectionAfterDrop();
|
|
7497
|
-
requestAnimationFrame(applySelectionAfterDrop);
|
|
7498
|
-
});
|
|
7499
|
-
return;
|
|
7500
|
-
}
|
|
7501
|
-
applySelectionAfterDrop();
|
|
7502
|
-
clearNavDragVisuals();
|
|
7503
|
-
},
|
|
7504
|
-
[clearNavDragVisuals, deselectRef, editContentRef, postToParentRef, selectRef]
|
|
7505
|
-
);
|
|
7506
|
-
commitNavDragRef.current = commitNavDrag;
|
|
7507
|
-
const startNavLinkDrag = useCallback4(
|
|
7508
|
-
(anchor, clientX, clientY, wasSelected) => {
|
|
7509
|
-
if (footerDragRef.current) return false;
|
|
7510
|
-
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
7511
|
-
if (!hrefKey || !isNavbarHrefKey(hrefKey)) return false;
|
|
7512
|
-
if (isNavbarButton3(anchor) || isDragHandleDisabled2(anchor)) return false;
|
|
7513
|
-
beginNavDrag({
|
|
7514
|
-
hrefKey,
|
|
7515
|
-
wasSelected,
|
|
7516
|
-
draggedEl: anchor,
|
|
7517
|
-
lastClientX: clientX,
|
|
7518
|
-
lastClientY: clientY,
|
|
7519
|
-
activeSlot: null
|
|
7520
|
-
});
|
|
7521
|
-
return true;
|
|
7522
|
-
},
|
|
7523
|
-
[beginNavDrag, footerDragRef, isDragHandleDisabled2, isNavbarButton3]
|
|
7524
|
-
);
|
|
7525
|
-
const onNavDragOver = useCallback4(
|
|
7526
|
-
(e) => {
|
|
7527
|
-
const session = navDragRef.current;
|
|
7528
|
-
if (!session) return false;
|
|
7529
|
-
e.preventDefault();
|
|
7530
|
-
if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
|
|
7531
|
-
const slot = hitTestNavDropSlot(e.clientX, e.clientY, session.hrefKey);
|
|
7532
|
-
refreshNavDragVisualsRef.current(session, slot, e.clientX, e.clientY);
|
|
7533
|
-
return true;
|
|
7534
|
-
},
|
|
7535
|
-
[]
|
|
7536
|
-
);
|
|
7537
|
-
useEffect7(() => {
|
|
7538
|
-
if (!isEditMode) return;
|
|
7539
|
-
const THRESHOLD = 10;
|
|
7540
|
-
const resolveWasSelected = (el) => {
|
|
7541
|
-
if (selectedElRef.current === el) return true;
|
|
7542
|
-
const activeAnchor = activeElRef.current ? getNavigationItemAnchor2(activeElRef.current) : null;
|
|
7543
|
-
return activeAnchor === el;
|
|
7544
|
-
};
|
|
7545
|
-
const onPointerDown = (e) => {
|
|
7546
|
-
if (e.button !== 0) return;
|
|
7547
|
-
if (navDragRef.current || footerDragRef.current) return;
|
|
7548
|
-
const target = e.target;
|
|
7549
|
-
if (!target) return;
|
|
7550
|
-
if (target.closest(
|
|
7551
|
-
'[data-ohw-drag-handle-container], [data-slot="drag-handle"], [data-ohw-toolbar], [data-ohw-item-toolbar-anchor], [data-ohw-link-popover-root]'
|
|
7552
|
-
)) {
|
|
7553
|
-
return;
|
|
7554
|
-
}
|
|
7555
|
-
if (target.closest("[data-ohw-item-drag-surface]")) return;
|
|
7556
|
-
const anchor = getNavigationItemAnchor2(target);
|
|
7557
|
-
const hrefKey = anchor?.getAttribute("data-ohw-href-key") ?? null;
|
|
7558
|
-
if (!anchor || !isNavbarHrefKey(hrefKey)) return;
|
|
7559
|
-
if (isNavbarButton3(anchor) || isDragHandleDisabled2(anchor)) return;
|
|
7560
|
-
navPointerDragRef.current = {
|
|
7561
|
-
el: anchor,
|
|
7562
|
-
startX: e.clientX,
|
|
7563
|
-
startY: e.clientY,
|
|
7564
|
-
pointerId: e.pointerId,
|
|
7565
|
-
wasSelected: resolveWasSelected(anchor),
|
|
7566
|
-
started: false
|
|
7567
|
-
};
|
|
7568
|
-
};
|
|
7569
|
-
const onPointerMove = (e) => {
|
|
7570
|
-
const pending = navPointerDragRef.current;
|
|
7571
|
-
if (!pending) return;
|
|
7572
|
-
if (pending.started) {
|
|
7573
|
-
e.preventDefault();
|
|
7574
|
-
clearTextSelection();
|
|
7575
|
-
const session = navDragRef.current;
|
|
7576
|
-
if (!session) return;
|
|
7577
|
-
const slot = hitTestNavDropSlot(e.clientX, e.clientY, session.hrefKey);
|
|
7578
|
-
refreshNavDragVisualsRef.current(session, slot, e.clientX, e.clientY);
|
|
7579
|
-
return;
|
|
7580
|
-
}
|
|
7581
|
-
const dx = e.clientX - pending.startX;
|
|
7582
|
-
const dy = e.clientY - pending.startY;
|
|
7583
|
-
if (dx * dx + dy * dy < THRESHOLD * THRESHOLD) return;
|
|
7584
|
-
e.preventDefault();
|
|
7585
|
-
pending.started = true;
|
|
7586
|
-
armItemPressDrag();
|
|
7587
|
-
clearTextSelection();
|
|
7588
|
-
try {
|
|
7589
|
-
document.body.setPointerCapture(pending.pointerId);
|
|
7590
|
-
} catch {
|
|
7591
|
-
}
|
|
7592
|
-
if (linkPopoverOpenRef.current) setLinkPopover(null);
|
|
7593
|
-
if (activeElRef.current) deactivateRef.current();
|
|
7594
|
-
const key = pending.el.getAttribute("data-ohw-href-key");
|
|
7595
|
-
if (!key) return;
|
|
7596
|
-
beginNavDragRef.current({
|
|
7597
|
-
hrefKey: key,
|
|
7598
|
-
wasSelected: pending.wasSelected,
|
|
7599
|
-
draggedEl: pending.el,
|
|
7600
|
-
lastClientX: e.clientX,
|
|
7601
|
-
lastClientY: e.clientY,
|
|
7602
|
-
activeSlot: null
|
|
7603
|
-
});
|
|
7604
|
-
};
|
|
7605
|
-
const endPointerDrag = (e) => {
|
|
7606
|
-
const pending = navPointerDragRef.current;
|
|
7607
|
-
navPointerDragRef.current = null;
|
|
7608
|
-
try {
|
|
7609
|
-
if (document.body.hasPointerCapture(e.pointerId)) {
|
|
7610
|
-
document.body.releasePointerCapture(e.pointerId);
|
|
7611
|
-
}
|
|
7612
|
-
} catch {
|
|
7613
|
-
}
|
|
7614
|
-
if (!pending) return;
|
|
7615
|
-
if (!pending.started) {
|
|
7616
|
-
unlockItemDragInteraction();
|
|
7617
|
-
return;
|
|
7618
|
-
}
|
|
7619
|
-
suppressNextClickRef.current = true;
|
|
7620
|
-
suppressClickUntilRef.current = Date.now() + 500;
|
|
7621
|
-
commitNavDragRef.current(e.clientX, e.clientY);
|
|
7622
|
-
};
|
|
7623
|
-
const blockSelectStart = (e) => {
|
|
7624
|
-
if (navDragRef.current || navPointerDragRef.current?.started || document.documentElement.hasAttribute("data-ohw-footer-press-drag")) {
|
|
7625
|
-
e.preventDefault();
|
|
7626
|
-
}
|
|
7627
|
-
};
|
|
7628
|
-
const onDragEnd = () => {
|
|
7629
|
-
if (!navDragRef.current) return;
|
|
7630
|
-
suppressNextClickRef.current = true;
|
|
7631
|
-
suppressClickUntilRef.current = Date.now() + 500;
|
|
7632
|
-
commitNavDragRef.current();
|
|
7633
|
-
};
|
|
7634
|
-
document.addEventListener("pointerdown", onPointerDown, true);
|
|
7635
|
-
document.addEventListener("pointermove", onPointerMove, true);
|
|
7636
|
-
document.addEventListener("pointerup", endPointerDrag, true);
|
|
7637
|
-
document.addEventListener("pointercancel", endPointerDrag, true);
|
|
7638
|
-
document.addEventListener("selectstart", blockSelectStart, true);
|
|
7639
|
-
document.addEventListener("dragend", onDragEnd, true);
|
|
7640
|
-
return () => {
|
|
7641
|
-
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
7642
|
-
document.removeEventListener("pointermove", onPointerMove, true);
|
|
7643
|
-
document.removeEventListener("pointerup", endPointerDrag, true);
|
|
7644
|
-
document.removeEventListener("pointercancel", endPointerDrag, true);
|
|
7645
|
-
document.removeEventListener("selectstart", blockSelectStart, true);
|
|
7646
|
-
document.removeEventListener("dragend", onDragEnd, true);
|
|
7647
|
-
unlockItemDragInteraction();
|
|
7648
|
-
};
|
|
7649
|
-
}, [
|
|
7650
|
-
activeElRef,
|
|
7651
|
-
deactivateRef,
|
|
7652
|
-
footerDragRef,
|
|
7653
|
-
getNavigationItemAnchor2,
|
|
7654
|
-
isDragHandleDisabled2,
|
|
7655
|
-
isEditMode,
|
|
7656
|
-
isNavbarButton3,
|
|
7657
|
-
linkPopoverOpenRef,
|
|
7658
|
-
selectedElRef,
|
|
7659
|
-
setLinkPopover,
|
|
7660
|
-
suppressNextClickRef
|
|
7661
|
-
]);
|
|
7662
|
-
const armNavPressFromChrome = useCallback4(
|
|
7663
|
-
(selected, clientX, clientY, pointerId) => {
|
|
7664
|
-
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
7665
|
-
if (!hrefKey || !isNavbarHrefKey(hrefKey)) return false;
|
|
7666
|
-
if (isNavbarButton3(selected) || isDragHandleDisabled2(selected)) return false;
|
|
7667
|
-
navPointerDragRef.current = {
|
|
7668
|
-
el: selected,
|
|
7669
|
-
startX: clientX,
|
|
7670
|
-
startY: clientY,
|
|
7671
|
-
pointerId,
|
|
7672
|
-
wasSelected: true,
|
|
7673
|
-
started: false
|
|
7674
|
-
};
|
|
7675
|
-
return true;
|
|
7676
|
-
},
|
|
7677
|
-
[isDragHandleDisabled2, isNavbarButton3]
|
|
7678
|
-
);
|
|
7679
|
-
return {
|
|
7680
|
-
navDragRef,
|
|
7681
|
-
navDropSlots,
|
|
7682
|
-
activeNavDropIndex,
|
|
7683
|
-
startNavLinkDrag,
|
|
7684
|
-
commitNavDrag,
|
|
7685
|
-
onNavDragOver,
|
|
7686
|
-
armNavPressFromChrome,
|
|
7687
|
-
clearNavDragVisuals,
|
|
7688
|
-
refreshNavDragVisualsRef
|
|
7689
|
-
};
|
|
7690
|
-
}
|
|
7691
|
-
|
|
7692
|
-
// src/ui/navbar-container-chrome.tsx
|
|
7693
|
-
import { Plus as Plus2 } from "lucide-react";
|
|
7694
|
-
import { jsx as jsx21 } from "react/jsx-runtime";
|
|
7695
|
-
function NavbarContainerChrome({
|
|
7696
|
-
rect,
|
|
7697
|
-
onAdd
|
|
7698
|
-
}) {
|
|
7699
|
-
const chromeGap = 6;
|
|
7700
|
-
return /* @__PURE__ */ jsx21(
|
|
7701
|
-
"div",
|
|
7702
|
-
{
|
|
7703
|
-
"data-ohw-navbar-container-chrome": "",
|
|
7704
|
-
"data-ohw-bridge": "",
|
|
7705
|
-
className: "pointer-events-none fixed z-[2147483647]",
|
|
7706
|
-
style: {
|
|
7707
|
-
top: rect.top - chromeGap,
|
|
7708
|
-
left: rect.left - chromeGap,
|
|
7709
|
-
width: rect.width + chromeGap * 2,
|
|
7710
|
-
height: rect.height + chromeGap * 2
|
|
7711
|
-
},
|
|
7712
|
-
children: /* @__PURE__ */ jsx21(
|
|
7713
|
-
"button",
|
|
7714
|
-
{
|
|
7715
|
-
type: "button",
|
|
7716
|
-
"data-ohw-navbar-add-button": "",
|
|
7717
|
-
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",
|
|
7718
|
-
style: { top: "70%" },
|
|
7719
|
-
"aria-label": "Add item",
|
|
7720
|
-
onMouseDown: (e) => {
|
|
7721
|
-
e.preventDefault();
|
|
7722
|
-
e.stopPropagation();
|
|
7723
|
-
},
|
|
7724
|
-
onClick: (e) => {
|
|
7725
|
-
e.preventDefault();
|
|
7726
|
-
e.stopPropagation();
|
|
7727
|
-
onAdd();
|
|
7728
|
-
},
|
|
7729
|
-
children: /* @__PURE__ */ jsx21(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
7730
|
-
}
|
|
7731
|
-
)
|
|
7732
|
-
}
|
|
7733
|
-
);
|
|
7734
|
-
}
|
|
7735
|
-
|
|
7736
|
-
// src/ui/drop-indicator.tsx
|
|
7737
|
-
import * as React10 from "react";
|
|
7738
|
-
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
7739
|
-
var dropIndicatorVariants = cva(
|
|
7740
|
-
"ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
|
|
7741
|
-
{
|
|
7742
|
-
variants: {
|
|
7743
|
-
direction: {
|
|
7744
|
-
vertical: "h-6 w-[3px]",
|
|
7745
|
-
horizontal: "h-[3px] w-[200px]"
|
|
7746
|
-
},
|
|
7747
|
-
state: {
|
|
7748
|
-
default: "opacity-0",
|
|
7749
|
-
hover: "opacity-100",
|
|
7750
|
-
dragIdle: "opacity-40",
|
|
7751
|
-
dragActive: "opacity-100"
|
|
7752
|
-
}
|
|
7753
|
-
},
|
|
7754
|
-
defaultVariants: {
|
|
7755
|
-
direction: "vertical",
|
|
7756
|
-
state: "default"
|
|
7757
|
-
}
|
|
7758
|
-
}
|
|
7759
|
-
);
|
|
7760
|
-
var DropIndicator = React10.forwardRef(
|
|
7761
|
-
({ className, direction, state, ...props }, ref) => {
|
|
7762
|
-
return /* @__PURE__ */ jsx22(
|
|
7763
|
-
"div",
|
|
7764
|
-
{
|
|
7765
|
-
ref,
|
|
7766
|
-
"data-slot": "drop-indicator",
|
|
7767
|
-
"data-direction": direction ?? "vertical",
|
|
7768
|
-
"data-state": state ?? "default",
|
|
7769
|
-
"aria-hidden": "true",
|
|
7770
|
-
className: cn(dropIndicatorVariants({ direction, state }), className),
|
|
7771
|
-
...props
|
|
7772
|
-
}
|
|
7773
|
-
);
|
|
7774
|
-
}
|
|
7775
|
-
);
|
|
7776
|
-
DropIndicator.displayName = "DropIndicator";
|
|
7777
|
-
|
|
7778
|
-
// src/ui/badge.tsx
|
|
7779
|
-
import { jsx as jsx23 } from "react/jsx-runtime";
|
|
7780
|
-
var badgeVariants = cva(
|
|
7781
|
-
"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",
|
|
7782
|
-
{
|
|
7783
|
-
variants: {
|
|
7784
|
-
variant: {
|
|
7785
|
-
default: "border-transparent bg-primary text-primary-foreground",
|
|
7786
|
-
secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
7787
|
-
destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
|
|
7788
|
-
outline: "text-foreground"
|
|
7789
|
-
}
|
|
7790
|
-
},
|
|
7791
|
-
defaultVariants: {
|
|
7792
|
-
variant: "default"
|
|
7793
|
-
}
|
|
7794
|
-
}
|
|
7795
|
-
);
|
|
7796
|
-
function Badge({ className, variant, ...props }) {
|
|
7797
|
-
return /* @__PURE__ */ jsx23("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
6507
|
+
);
|
|
6508
|
+
function Badge({ className, variant, ...props }) {
|
|
6509
|
+
return /* @__PURE__ */ jsx22("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
7798
6510
|
}
|
|
7799
6511
|
|
|
7800
6512
|
// src/OhhwellsBridge.tsx
|
|
7801
6513
|
import { Link as Link2 } from "lucide-react";
|
|
7802
|
-
import { Fragment as Fragment5, jsx as
|
|
6514
|
+
import { Fragment as Fragment5, jsx as jsx23, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
7803
6515
|
var PRIMARY2 = "#0885FE";
|
|
7804
6516
|
var IMAGE_FADE_MS = 300;
|
|
7805
6517
|
function runOpacityFade(el, onDone) {
|
|
@@ -7978,7 +6690,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
7978
6690
|
const root = createRoot(container);
|
|
7979
6691
|
flushSync(() => {
|
|
7980
6692
|
root.render(
|
|
7981
|
-
/* @__PURE__ */
|
|
6693
|
+
/* @__PURE__ */ jsx23(
|
|
7982
6694
|
SchedulingWidget,
|
|
7983
6695
|
{
|
|
7984
6696
|
notifyOnConnect,
|
|
@@ -8040,20 +6752,7 @@ function isDragHandleDisabled(el) {
|
|
|
8040
6752
|
return raw === "true" || raw === "";
|
|
8041
6753
|
});
|
|
8042
6754
|
}
|
|
8043
|
-
function
|
|
8044
|
-
const { key, disabled } = getNavigationItemReorderState(anchor);
|
|
8045
|
-
return Boolean(key) && !disabled;
|
|
8046
|
-
}
|
|
8047
|
-
function syncNavigationDragCursorAttrs() {
|
|
8048
|
-
document.querySelectorAll("nav [data-ohw-href-key], footer [data-ohw-href-key]").forEach((el) => {
|
|
8049
|
-
if (!isNavigationItem(el) || !canDragNavigationItem(el)) {
|
|
8050
|
-
el.removeAttribute("data-ohw-can-drag");
|
|
8051
|
-
return;
|
|
8052
|
-
}
|
|
8053
|
-
el.setAttribute("data-ohw-can-drag", "");
|
|
8054
|
-
});
|
|
8055
|
-
}
|
|
8056
|
-
function collectEditableNodes(extraContent) {
|
|
6755
|
+
function collectEditableNodes() {
|
|
8057
6756
|
const nodes = Array.from(document.querySelectorAll("[data-ohw-editable]")).map((el) => {
|
|
8058
6757
|
if (el.dataset.ohwEditable === "image") {
|
|
8059
6758
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
@@ -8081,14 +6780,6 @@ function collectEditableNodes(extraContent) {
|
|
|
8081
6780
|
if (!key) return;
|
|
8082
6781
|
nodes.push({ key, type: "link", text: getLinkHref2(el) });
|
|
8083
6782
|
});
|
|
8084
|
-
if (extraContent) {
|
|
8085
|
-
for (const key of [NAV_ORDER_KEY, FOOTER_ORDER_KEY, NAV_COUNT_KEY]) {
|
|
8086
|
-
const text = extraContent[key];
|
|
8087
|
-
if (typeof text === "string" && text.length > 0) {
|
|
8088
|
-
nodes.push({ key, type: "meta", text });
|
|
8089
|
-
}
|
|
8090
|
-
}
|
|
8091
|
-
}
|
|
8092
6783
|
document.querySelectorAll('[data-ohw-editable="video"]').forEach((el) => {
|
|
8093
6784
|
const key = el.dataset.ohwKey ?? "";
|
|
8094
6785
|
const video = getVideoEl(el);
|
|
@@ -8202,11 +6893,6 @@ function getNavigationItemAnchor(el) {
|
|
|
8202
6893
|
function isNavigationItem(el) {
|
|
8203
6894
|
return getNavigationItemAnchor(el) !== null;
|
|
8204
6895
|
}
|
|
8205
|
-
function listNavigationItems() {
|
|
8206
|
-
return Array.from(
|
|
8207
|
-
document.querySelectorAll("nav [data-ohw-href-key], footer [data-ohw-href-key]")
|
|
8208
|
-
).filter((el) => isNavigationItem(el));
|
|
8209
|
-
}
|
|
8210
6896
|
function getNavigationItemReorderState(anchor) {
|
|
8211
6897
|
if (isNavbarButton2(anchor)) return { key: null, disabled: false };
|
|
8212
6898
|
return getReorderHandleStateFromAnchor(anchor);
|
|
@@ -8235,20 +6921,18 @@ function getNavigationRoot(el) {
|
|
|
8235
6921
|
if (explicit) return explicit;
|
|
8236
6922
|
return el.closest("nav, footer, aside");
|
|
8237
6923
|
}
|
|
8238
|
-
function countFooterNavItems(el) {
|
|
8239
|
-
return Array.from(el.querySelectorAll("[data-ohw-href-key]")).filter(isNavigationItem).length;
|
|
8240
|
-
}
|
|
8241
6924
|
function findFooterItemGroup(item) {
|
|
8242
|
-
const explicit = item.closest("[data-ohw-footer-col], [data-ohw-footer-column]");
|
|
8243
|
-
if (explicit) return explicit;
|
|
8244
6925
|
const footer = item.closest("footer");
|
|
8245
6926
|
if (!footer) return null;
|
|
8246
6927
|
let node = item.parentElement;
|
|
8247
6928
|
while (node && node !== footer) {
|
|
8248
|
-
|
|
6929
|
+
const hasDirectNavItems = Array.from(
|
|
6930
|
+
node.querySelectorAll(":scope > [data-ohw-href-key]")
|
|
6931
|
+
).some(isNavigationItem);
|
|
6932
|
+
if (hasDirectNavItems) return node;
|
|
8249
6933
|
node = node.parentElement;
|
|
8250
6934
|
}
|
|
8251
|
-
return
|
|
6935
|
+
return null;
|
|
8252
6936
|
}
|
|
8253
6937
|
function isNavigationRoot(el) {
|
|
8254
6938
|
return el.hasAttribute("data-ohw-nav-root") || el.matches("nav, footer, aside");
|
|
@@ -8256,49 +6940,16 @@ function isNavigationRoot(el) {
|
|
|
8256
6940
|
function isInferredFooterGroup(el) {
|
|
8257
6941
|
const footer = el.closest("footer");
|
|
8258
6942
|
if (!footer || el === footer) return false;
|
|
8259
|
-
|
|
8260
|
-
return countFooterNavItems(el) >= 2;
|
|
6943
|
+
return Array.from(el.querySelectorAll(":scope > [data-ohw-href-key]")).some(isNavigationItem);
|
|
8261
6944
|
}
|
|
8262
6945
|
function isNavigationContainer(el) {
|
|
8263
|
-
return el.hasAttribute("data-ohw-nav-container") ||
|
|
8264
|
-
}
|
|
8265
|
-
function isNavbarLinksContainer(el) {
|
|
8266
|
-
return el.hasAttribute("data-ohw-nav-container");
|
|
8267
|
-
}
|
|
8268
|
-
function getFooterColumn(el) {
|
|
8269
|
-
return el.closest("[data-ohw-footer-col], [data-ohw-footer-column]");
|
|
8270
|
-
}
|
|
8271
|
-
function resolveFooterColumnSelectionTarget(target, clientX, clientY) {
|
|
8272
|
-
if (getNavigationItemAnchor(target)) return null;
|
|
8273
|
-
const column = getFooterColumn(target);
|
|
8274
|
-
if (!column) return null;
|
|
8275
|
-
if (isPointOverNavItem(column, clientX, clientY)) return null;
|
|
8276
|
-
return column;
|
|
6946
|
+
return el.hasAttribute("data-ohw-nav-container") || isNavigationRoot(el) || isInferredFooterGroup(el);
|
|
8277
6947
|
}
|
|
8278
6948
|
function isPointOverNavigation(x, y) {
|
|
8279
|
-
const roots = /* @__PURE__ */ new Set();
|
|
8280
6949
|
const navRoot = document.querySelector("[data-ohw-nav-root]") ?? document.querySelector("nav");
|
|
8281
|
-
if (navRoot)
|
|
8282
|
-
const
|
|
8283
|
-
|
|
8284
|
-
for (const root of roots) {
|
|
8285
|
-
const r2 = root.getBoundingClientRect();
|
|
8286
|
-
if (x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom) return true;
|
|
8287
|
-
}
|
|
8288
|
-
return false;
|
|
8289
|
-
}
|
|
8290
|
-
function findHoveredNavOrFooterContainer(x, y) {
|
|
8291
|
-
const candidates = [
|
|
8292
|
-
...document.querySelectorAll("[data-ohw-nav-container]"),
|
|
8293
|
-
...listFooterColumns()
|
|
8294
|
-
];
|
|
8295
|
-
for (const container of candidates) {
|
|
8296
|
-
const r2 = container.getBoundingClientRect();
|
|
8297
|
-
if (x < r2.left || x > r2.right || y < r2.top || y > r2.bottom) continue;
|
|
8298
|
-
if (isPointOverNavItem(container, x, y)) continue;
|
|
8299
|
-
return container;
|
|
8300
|
-
}
|
|
8301
|
-
return null;
|
|
6950
|
+
if (!navRoot) return false;
|
|
6951
|
+
const r2 = navRoot.getBoundingClientRect();
|
|
6952
|
+
return x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom;
|
|
8302
6953
|
}
|
|
8303
6954
|
function isPointOverNavItem(container, x, y) {
|
|
8304
6955
|
return Array.from(container.querySelectorAll("[data-ohw-href-key]")).some((el) => {
|
|
@@ -8331,63 +6982,36 @@ function getNavigationSelectionParent(el) {
|
|
|
8331
6982
|
if (isNavigationItem(el)) {
|
|
8332
6983
|
const explicit = el.closest("[data-ohw-nav-container]");
|
|
8333
6984
|
if (explicit) return explicit;
|
|
8334
|
-
const footerColumn = getFooterColumn(el);
|
|
8335
|
-
if (footerColumn) return footerColumn;
|
|
8336
6985
|
const footerGroup = findFooterItemGroup(el);
|
|
8337
6986
|
if (footerGroup) return footerGroup;
|
|
8338
6987
|
return getNavigationRoot(el);
|
|
8339
6988
|
}
|
|
8340
|
-
if (el.hasAttribute("data-ohw-nav-container") ||
|
|
6989
|
+
if (el.hasAttribute("data-ohw-nav-container") || isInferredFooterGroup(el)) {
|
|
8341
6990
|
return getNavigationRoot(el);
|
|
8342
6991
|
}
|
|
8343
6992
|
return null;
|
|
8344
6993
|
}
|
|
8345
|
-
function collectNavigationItemSiblingHintRects(selected) {
|
|
8346
|
-
if (!isNavigationItem(selected)) return [];
|
|
8347
|
-
const footerColumn = getFooterColumn(selected);
|
|
8348
|
-
if (footerColumn) {
|
|
8349
|
-
return listFooterLinksInColumn(footerColumn).filter((link) => link !== selected).map((link) => link.getBoundingClientRect());
|
|
8350
|
-
}
|
|
8351
|
-
const navContainer = selected.closest("[data-ohw-nav-container], [data-ohw-nav-drawer]");
|
|
8352
|
-
if (navContainer) {
|
|
8353
|
-
return Array.from(navContainer.querySelectorAll("[data-ohw-href-key]")).filter((el) => isNavigationItem(el) && el !== selected).map((el) => el.getBoundingClientRect());
|
|
8354
|
-
}
|
|
8355
|
-
return listNavigationItems().filter((el) => el !== selected).map((el) => el.getBoundingClientRect());
|
|
8356
|
-
}
|
|
8357
6994
|
function placeCaretAtPoint(el, x, y) {
|
|
8358
6995
|
const selection = window.getSelection();
|
|
8359
6996
|
if (!selection) return;
|
|
8360
|
-
|
|
8361
|
-
document.
|
|
8362
|
-
|
|
8363
|
-
|
|
8364
|
-
|
|
8365
|
-
|
|
8366
|
-
for (const node of overlays) node.style.pointerEvents = "none";
|
|
8367
|
-
try {
|
|
8368
|
-
if (typeof document.caretRangeFromPoint === "function") {
|
|
8369
|
-
const range = document.caretRangeFromPoint(x, y);
|
|
8370
|
-
if (range && el.contains(range.startContainer)) {
|
|
8371
|
-
selection.removeAllRanges();
|
|
8372
|
-
selection.addRange(range);
|
|
8373
|
-
return;
|
|
8374
|
-
}
|
|
6997
|
+
if (typeof document.caretRangeFromPoint === "function") {
|
|
6998
|
+
const range = document.caretRangeFromPoint(x, y);
|
|
6999
|
+
if (range && el.contains(range.startContainer)) {
|
|
7000
|
+
selection.removeAllRanges();
|
|
7001
|
+
selection.addRange(range);
|
|
7002
|
+
return;
|
|
8375
7003
|
}
|
|
8376
|
-
|
|
8377
|
-
|
|
8378
|
-
|
|
8379
|
-
|
|
8380
|
-
|
|
8381
|
-
|
|
8382
|
-
|
|
8383
|
-
|
|
8384
|
-
|
|
8385
|
-
|
|
7004
|
+
}
|
|
7005
|
+
const caretPositionFromPoint = document.caretPositionFromPoint;
|
|
7006
|
+
if (typeof caretPositionFromPoint === "function") {
|
|
7007
|
+
const position = caretPositionFromPoint(x, y);
|
|
7008
|
+
if (position && el.contains(position.offsetNode)) {
|
|
7009
|
+
const range = document.createRange();
|
|
7010
|
+
range.setStart(position.offsetNode, position.offset);
|
|
7011
|
+
range.collapse(true);
|
|
7012
|
+
selection.removeAllRanges();
|
|
7013
|
+
selection.addRange(range);
|
|
8386
7014
|
}
|
|
8387
|
-
} finally {
|
|
8388
|
-
overlays.forEach((node, i) => {
|
|
8389
|
-
node.style.pointerEvents = prevPointerEvents[i] ?? "";
|
|
8390
|
-
});
|
|
8391
7015
|
}
|
|
8392
7016
|
}
|
|
8393
7017
|
function selectAllTextInEditable(el) {
|
|
@@ -8529,9 +7153,6 @@ var ICONS = {
|
|
|
8529
7153
|
insertUnorderedList: '<line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/>',
|
|
8530
7154
|
insertOrderedList: '<line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"/>'
|
|
8531
7155
|
};
|
|
8532
|
-
var SELECTION_CHROME_GAP2 = 4;
|
|
8533
|
-
var TOOLBAR_STROKE_GAP2 = 4;
|
|
8534
|
-
var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
|
|
8535
7156
|
var TOOLBAR_GROUPS = [
|
|
8536
7157
|
[
|
|
8537
7158
|
{ cmd: "bold", title: "Bold" },
|
|
@@ -8553,10 +7174,9 @@ function EditGlowChrome({
|
|
|
8553
7174
|
rect,
|
|
8554
7175
|
elRef,
|
|
8555
7176
|
reorderHrefKey,
|
|
8556
|
-
dragDisabled = false
|
|
8557
|
-
hideHandle = false
|
|
7177
|
+
dragDisabled = false
|
|
8558
7178
|
}) {
|
|
8559
|
-
const GAP =
|
|
7179
|
+
const GAP = 6;
|
|
8560
7180
|
return /* @__PURE__ */ jsxs13(
|
|
8561
7181
|
"div",
|
|
8562
7182
|
{
|
|
@@ -8572,7 +7192,7 @@ function EditGlowChrome({
|
|
|
8572
7192
|
zIndex: 2147483646
|
|
8573
7193
|
},
|
|
8574
7194
|
children: [
|
|
8575
|
-
/* @__PURE__ */
|
|
7195
|
+
/* @__PURE__ */ jsx23(
|
|
8576
7196
|
"div",
|
|
8577
7197
|
{
|
|
8578
7198
|
style: {
|
|
@@ -8580,12 +7200,12 @@ function EditGlowChrome({
|
|
|
8580
7200
|
inset: 0,
|
|
8581
7201
|
border: "2px solid var(--ohw-primary, #0885FE)",
|
|
8582
7202
|
borderRadius: 8,
|
|
8583
|
-
boxShadow: "0 0 0 4px
|
|
7203
|
+
boxShadow: "0 0 0 4px rgba(8, 133, 254, 0.12)",
|
|
8584
7204
|
pointerEvents: "none"
|
|
8585
7205
|
}
|
|
8586
7206
|
}
|
|
8587
7207
|
),
|
|
8588
|
-
reorderHrefKey &&
|
|
7208
|
+
reorderHrefKey && /* @__PURE__ */ jsx23(
|
|
8589
7209
|
"div",
|
|
8590
7210
|
{
|
|
8591
7211
|
"data-ohw-drag-handle-container": "",
|
|
@@ -8597,7 +7217,7 @@ function EditGlowChrome({
|
|
|
8597
7217
|
transform: "translate(calc(-100% - 7px), -50%)",
|
|
8598
7218
|
pointerEvents: dragDisabled ? "none" : "auto"
|
|
8599
7219
|
},
|
|
8600
|
-
children: /* @__PURE__ */
|
|
7220
|
+
children: /* @__PURE__ */ jsx23(
|
|
8601
7221
|
DragHandle,
|
|
8602
7222
|
{
|
|
8603
7223
|
"aria-label": `Reorder ${reorderHrefKey}`,
|
|
@@ -8628,7 +7248,6 @@ function applyVisibleViewport(el, parentScroll) {
|
|
|
8628
7248
|
el.style.top = `${top}px`;
|
|
8629
7249
|
el.style.height = `${height}px`;
|
|
8630
7250
|
}
|
|
8631
|
-
var TOOLBAR_EDGE_MARGIN2 = 4;
|
|
8632
7251
|
function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
8633
7252
|
const isAbove = transform.includes("translateY(-100%)");
|
|
8634
7253
|
let visualTop = isAbove ? top - approxH : top;
|
|
@@ -8652,16 +7271,10 @@ function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
|
8652
7271
|
const pinnedTop = Math.min(maxBottom - approxH, Math.max(minTop, clip.top + gap));
|
|
8653
7272
|
return { top: pinnedTop + approxH, transform: "translateX(-50%) translateY(-100%)" };
|
|
8654
7273
|
}
|
|
8655
|
-
function
|
|
8656
|
-
const
|
|
8657
|
-
return Math.max(
|
|
8658
|
-
TOOLBAR_EDGE_MARGIN2 + half,
|
|
8659
|
-
Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN2 - half)
|
|
8660
|
-
);
|
|
8661
|
-
}
|
|
8662
|
-
function calcToolbarPos(rect, parentScroll, toolbarW = 306) {
|
|
8663
|
-
const GAP = TOOLBAR_OFFSET_FROM_ELEMENT;
|
|
7274
|
+
function calcToolbarPos(rect, parentScroll, approxW = 306) {
|
|
7275
|
+
const GAP = 8;
|
|
8664
7276
|
const APPROX_H = 32;
|
|
7277
|
+
const APPROX_W = approxW;
|
|
8665
7278
|
const clip = getIframeVisibleClip(parentScroll);
|
|
8666
7279
|
const clipTop = clip?.top ?? 0;
|
|
8667
7280
|
const canvasTopInIframe = parentScroll != null ? parentScroll.headerH - parentScroll.iframeOffsetTop : 0;
|
|
@@ -8691,7 +7304,7 @@ function calcToolbarPos(rect, parentScroll, toolbarW = 306) {
|
|
|
8691
7304
|
transform = clamped.transform;
|
|
8692
7305
|
}
|
|
8693
7306
|
const rawLeft = rect.left + rect.width / 2;
|
|
8694
|
-
const left =
|
|
7307
|
+
const left = Math.max(GAP + APPROX_W / 2, Math.min(rawLeft, window.innerWidth - GAP - APPROX_W / 2));
|
|
8695
7308
|
return { top, left, transform };
|
|
8696
7309
|
}
|
|
8697
7310
|
function resolveItemInteractionState(rect, parentScroll) {
|
|
@@ -8707,37 +7320,11 @@ function FloatingToolbar({
|
|
|
8707
7320
|
showEditLink,
|
|
8708
7321
|
onEditLink
|
|
8709
7322
|
}) {
|
|
8710
|
-
const
|
|
8711
|
-
|
|
8712
|
-
const setRefs = React11.useCallback(
|
|
8713
|
-
(node) => {
|
|
8714
|
-
localRef.current = node;
|
|
8715
|
-
if (typeof elRef === "function") elRef(node);
|
|
8716
|
-
else if (elRef) elRef.current = node;
|
|
8717
|
-
if (node) {
|
|
8718
|
-
const w = node.offsetWidth;
|
|
8719
|
-
if (w > 0) setMeasuredW(w);
|
|
8720
|
-
}
|
|
8721
|
-
},
|
|
8722
|
-
[elRef]
|
|
8723
|
-
);
|
|
8724
|
-
React11.useLayoutEffect(() => {
|
|
8725
|
-
const node = localRef.current;
|
|
8726
|
-
if (!node) return;
|
|
8727
|
-
const update = () => {
|
|
8728
|
-
const w = node.offsetWidth;
|
|
8729
|
-
if (w > 0) setMeasuredW(w);
|
|
8730
|
-
};
|
|
8731
|
-
update();
|
|
8732
|
-
const ro = new ResizeObserver(update);
|
|
8733
|
-
ro.observe(node);
|
|
8734
|
-
return () => ro.disconnect();
|
|
8735
|
-
}, [showEditLink, activeCommands]);
|
|
8736
|
-
const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
|
|
8737
|
-
return /* @__PURE__ */ jsx24(
|
|
7323
|
+
const { top, left, transform } = calcToolbarPos(rect, parentScroll, 330);
|
|
7324
|
+
return /* @__PURE__ */ jsx23(
|
|
8738
7325
|
"div",
|
|
8739
7326
|
{
|
|
8740
|
-
ref:
|
|
7327
|
+
ref: elRef,
|
|
8741
7328
|
style: {
|
|
8742
7329
|
position: "fixed",
|
|
8743
7330
|
top,
|
|
@@ -8747,11 +7334,11 @@ function FloatingToolbar({
|
|
|
8747
7334
|
pointerEvents: "auto"
|
|
8748
7335
|
},
|
|
8749
7336
|
children: /* @__PURE__ */ jsxs13(CustomToolbar, { children: [
|
|
8750
|
-
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs13(
|
|
8751
|
-
gi > 0 && /* @__PURE__ */
|
|
7337
|
+
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs13(React9.Fragment, { children: [
|
|
7338
|
+
gi > 0 && /* @__PURE__ */ jsx23(CustomToolbarDivider, {}),
|
|
8752
7339
|
btns.map((btn) => {
|
|
8753
7340
|
const isActive = activeCommands.has(btn.cmd);
|
|
8754
|
-
return /* @__PURE__ */
|
|
7341
|
+
return /* @__PURE__ */ jsx23(
|
|
8755
7342
|
CustomToolbarButton,
|
|
8756
7343
|
{
|
|
8757
7344
|
title: btn.title,
|
|
@@ -8760,7 +7347,7 @@ function FloatingToolbar({
|
|
|
8760
7347
|
e.preventDefault();
|
|
8761
7348
|
onCommand(btn.cmd);
|
|
8762
7349
|
},
|
|
8763
|
-
children: /* @__PURE__ */
|
|
7350
|
+
children: /* @__PURE__ */ jsx23(
|
|
8764
7351
|
"svg",
|
|
8765
7352
|
{
|
|
8766
7353
|
width: "16",
|
|
@@ -8781,7 +7368,7 @@ function FloatingToolbar({
|
|
|
8781
7368
|
);
|
|
8782
7369
|
})
|
|
8783
7370
|
] }, gi)),
|
|
8784
|
-
showEditLink ? /* @__PURE__ */
|
|
7371
|
+
showEditLink ? /* @__PURE__ */ jsx23(
|
|
8785
7372
|
CustomToolbarButton,
|
|
8786
7373
|
{
|
|
8787
7374
|
type: "button",
|
|
@@ -8795,7 +7382,7 @@ function FloatingToolbar({
|
|
|
8795
7382
|
e.preventDefault();
|
|
8796
7383
|
e.stopPropagation();
|
|
8797
7384
|
},
|
|
8798
|
-
children: /* @__PURE__ */
|
|
7385
|
+
children: /* @__PURE__ */ jsx23(Link2, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
8799
7386
|
}
|
|
8800
7387
|
) : null
|
|
8801
7388
|
] })
|
|
@@ -8812,7 +7399,7 @@ function StateToggle({
|
|
|
8812
7399
|
states,
|
|
8813
7400
|
onStateChange
|
|
8814
7401
|
}) {
|
|
8815
|
-
return /* @__PURE__ */
|
|
7402
|
+
return /* @__PURE__ */ jsx23(
|
|
8816
7403
|
ToggleGroup,
|
|
8817
7404
|
{
|
|
8818
7405
|
"data-ohw-state-toggle": "",
|
|
@@ -8826,7 +7413,7 @@ function StateToggle({
|
|
|
8826
7413
|
left: rect.right - 8,
|
|
8827
7414
|
transform: "translateX(-100%)"
|
|
8828
7415
|
},
|
|
8829
|
-
children: states.map((state) => /* @__PURE__ */
|
|
7416
|
+
children: states.map((state) => /* @__PURE__ */ jsx23(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
|
|
8830
7417
|
}
|
|
8831
7418
|
);
|
|
8832
7419
|
}
|
|
@@ -8853,8 +7440,8 @@ function OhhwellsBridge() {
|
|
|
8853
7440
|
const router = useRouter2();
|
|
8854
7441
|
const searchParams = useSearchParams();
|
|
8855
7442
|
const isEditMode = isEditSessionActive();
|
|
8856
|
-
const [bridgeRoot, setBridgeRoot] =
|
|
8857
|
-
|
|
7443
|
+
const [bridgeRoot, setBridgeRoot] = useState6(null);
|
|
7444
|
+
useEffect7(() => {
|
|
8858
7445
|
const figtreeFontId = "ohw-figtree-font";
|
|
8859
7446
|
if (!document.getElementById(figtreeFontId)) {
|
|
8860
7447
|
const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
|
|
@@ -8882,137 +7469,91 @@ function OhhwellsBridge() {
|
|
|
8882
7469
|
const subdomainFromQuery = searchParams.get("subdomain");
|
|
8883
7470
|
const subdomain = resolveSubdomain(subdomainFromQuery);
|
|
8884
7471
|
useLinkHrefGuardian(pathname, subdomain, isEditMode);
|
|
8885
|
-
const postToParent2 =
|
|
7472
|
+
const postToParent2 = useCallback3((data) => {
|
|
8886
7473
|
if (typeof window !== "undefined" && window.parent !== window) {
|
|
8887
7474
|
window.parent.postMessage(data, "*");
|
|
8888
7475
|
}
|
|
8889
7476
|
}, []);
|
|
8890
|
-
const [fetchState, setFetchState] =
|
|
8891
|
-
const autoSaveTimers =
|
|
8892
|
-
const activeElRef =
|
|
8893
|
-
const
|
|
8894
|
-
const
|
|
8895
|
-
const
|
|
8896
|
-
const
|
|
8897
|
-
const
|
|
8898
|
-
const
|
|
8899
|
-
const
|
|
8900
|
-
const visibleViewportRef = useRef7(null);
|
|
8901
|
-
const [dialogPortalContainer, setDialogPortalContainer] = useState7(null);
|
|
8902
|
-
const attachVisibleViewport = useCallback5((node) => {
|
|
7477
|
+
const [fetchState, setFetchState] = useState6("idle");
|
|
7478
|
+
const autoSaveTimers = useRef5(/* @__PURE__ */ new Map());
|
|
7479
|
+
const activeElRef = useRef5(null);
|
|
7480
|
+
const selectedElRef = useRef5(null);
|
|
7481
|
+
const originalContentRef = useRef5(null);
|
|
7482
|
+
const activeStateElRef = useRef5(null);
|
|
7483
|
+
const parentScrollRef = useRef5(null);
|
|
7484
|
+
const visibleViewportRef = useRef5(null);
|
|
7485
|
+
const [dialogPortalContainer, setDialogPortalContainer] = useState6(null);
|
|
7486
|
+
const attachVisibleViewport = useCallback3((node) => {
|
|
8903
7487
|
visibleViewportRef.current = node;
|
|
8904
7488
|
setDialogPortalContainer(node);
|
|
8905
7489
|
if (node) applyVisibleViewport(node, parentScrollRef.current);
|
|
8906
7490
|
}, []);
|
|
8907
|
-
const toolbarElRef =
|
|
8908
|
-
const glowElRef =
|
|
8909
|
-
const hoveredImageRef =
|
|
8910
|
-
const hoveredImageHasTextOverlapRef =
|
|
8911
|
-
const dragOverElRef =
|
|
8912
|
-
const [mediaHover, setMediaHover] =
|
|
8913
|
-
const [uploadingRects, setUploadingRects] =
|
|
8914
|
-
const hoveredGapRef =
|
|
8915
|
-
const imageUnhoverTimerRef =
|
|
8916
|
-
const imageShowTimerRef =
|
|
8917
|
-
const editStylesRef =
|
|
8918
|
-
const activateRef =
|
|
7491
|
+
const toolbarElRef = useRef5(null);
|
|
7492
|
+
const glowElRef = useRef5(null);
|
|
7493
|
+
const hoveredImageRef = useRef5(null);
|
|
7494
|
+
const hoveredImageHasTextOverlapRef = useRef5(false);
|
|
7495
|
+
const dragOverElRef = useRef5(null);
|
|
7496
|
+
const [mediaHover, setMediaHover] = useState6(null);
|
|
7497
|
+
const [uploadingRects, setUploadingRects] = useState6({});
|
|
7498
|
+
const hoveredGapRef = useRef5(null);
|
|
7499
|
+
const imageUnhoverTimerRef = useRef5(null);
|
|
7500
|
+
const imageShowTimerRef = useRef5(null);
|
|
7501
|
+
const editStylesRef = useRef5(null);
|
|
7502
|
+
const activateRef = useRef5(() => {
|
|
8919
7503
|
});
|
|
8920
|
-
const deactivateRef =
|
|
7504
|
+
const deactivateRef = useRef5(() => {
|
|
8921
7505
|
});
|
|
8922
|
-
const selectRef =
|
|
7506
|
+
const selectRef = useRef5(() => {
|
|
8923
7507
|
});
|
|
8924
|
-
const selectFrameRef =
|
|
7508
|
+
const selectFrameRef = useRef5(() => {
|
|
8925
7509
|
});
|
|
8926
|
-
const deselectRef =
|
|
7510
|
+
const deselectRef = useRef5(() => {
|
|
8927
7511
|
});
|
|
8928
|
-
const reselectNavigationItemRef =
|
|
7512
|
+
const reselectNavigationItemRef = useRef5(() => {
|
|
8929
7513
|
});
|
|
8930
|
-
const commitNavigationTextEditRef =
|
|
7514
|
+
const commitNavigationTextEditRef = useRef5(() => {
|
|
8931
7515
|
});
|
|
8932
|
-
const refreshActiveCommandsRef =
|
|
7516
|
+
const refreshActiveCommandsRef = useRef5(() => {
|
|
8933
7517
|
});
|
|
8934
|
-
const postToParentRef =
|
|
7518
|
+
const postToParentRef = useRef5(postToParent2);
|
|
8935
7519
|
postToParentRef.current = postToParent2;
|
|
8936
|
-
const sectionsLoadedRef =
|
|
8937
|
-
const pendingScheduleConfigRequests =
|
|
8938
|
-
const [toolbarRect, setToolbarRect] =
|
|
8939
|
-
const [toolbarVariant, setToolbarVariant] =
|
|
8940
|
-
const toolbarVariantRef =
|
|
7520
|
+
const sectionsLoadedRef = useRef5(false);
|
|
7521
|
+
const pendingScheduleConfigRequests = useRef5([]);
|
|
7522
|
+
const [toolbarRect, setToolbarRect] = useState6(null);
|
|
7523
|
+
const [toolbarVariant, setToolbarVariant] = useState6("none");
|
|
7524
|
+
const toolbarVariantRef = useRef5("none");
|
|
8941
7525
|
toolbarVariantRef.current = toolbarVariant;
|
|
8942
|
-
const [
|
|
8943
|
-
const [
|
|
8944
|
-
const [
|
|
8945
|
-
const [
|
|
8946
|
-
const [
|
|
8947
|
-
const [
|
|
8948
|
-
const [
|
|
8949
|
-
const
|
|
8950
|
-
const
|
|
8951
|
-
const
|
|
8952
|
-
const
|
|
8953
|
-
const
|
|
8954
|
-
const
|
|
8955
|
-
const [
|
|
8956
|
-
const [
|
|
8957
|
-
const
|
|
8958
|
-
const
|
|
8959
|
-
const
|
|
8960
|
-
const [
|
|
8961
|
-
const [
|
|
8962
|
-
const
|
|
8963
|
-
const
|
|
8964
|
-
const
|
|
8965
|
-
const
|
|
8966
|
-
const
|
|
8967
|
-
const linkPopoverSessionRef = useRef7(null);
|
|
8968
|
-
const addNavAfterAnchorRef = useRef7(null);
|
|
8969
|
-
const editContentRef = useRef7({});
|
|
8970
|
-
const [sitePages, setSitePages] = useState7([]);
|
|
8971
|
-
const [sectionsByPath, setSectionsByPath] = useState7({});
|
|
8972
|
-
const sectionsPrefetchGenRef = useRef7(0);
|
|
8973
|
-
const setLinkPopoverRef = useRef7(setLinkPopover);
|
|
8974
|
-
const linkPopoverPanelRef = useRef7(null);
|
|
8975
|
-
const linkPopoverOpenRef = useRef7(false);
|
|
8976
|
-
const linkPopoverGraceUntilRef = useRef7(0);
|
|
7526
|
+
const [reorderHrefKey, setReorderHrefKey] = useState6(null);
|
|
7527
|
+
const [reorderDragDisabled, setReorderDragDisabled] = useState6(false);
|
|
7528
|
+
const [toggleState, setToggleState] = useState6(null);
|
|
7529
|
+
const [maxBadge, setMaxBadge] = useState6(null);
|
|
7530
|
+
const [activeCommands, setActiveCommands] = useState6(/* @__PURE__ */ new Set());
|
|
7531
|
+
const [sectionGap, setSectionGap] = useState6(null);
|
|
7532
|
+
const [toolbarShowEditLink, setToolbarShowEditLink] = useState6(false);
|
|
7533
|
+
const hoveredNavContainerRef = useRef5(null);
|
|
7534
|
+
const [hoveredNavContainerRect, setHoveredNavContainerRect] = useState6(null);
|
|
7535
|
+
const hoveredItemElRef = useRef5(null);
|
|
7536
|
+
const [hoveredItemRect, setHoveredItemRect] = useState6(null);
|
|
7537
|
+
const siblingHintElRef = useRef5(null);
|
|
7538
|
+
const [siblingHintRect, setSiblingHintRect] = useState6(null);
|
|
7539
|
+
const [isItemDragging, setIsItemDragging] = useState6(false);
|
|
7540
|
+
const [linkPopover, setLinkPopover] = useState6(null);
|
|
7541
|
+
const linkPopoverSessionRef = useRef5(null);
|
|
7542
|
+
const addNavAfterAnchorRef = useRef5(null);
|
|
7543
|
+
const editContentRef = useRef5({});
|
|
7544
|
+
const [sitePages, setSitePages] = useState6([]);
|
|
7545
|
+
const [sectionsByPath, setSectionsByPath] = useState6({});
|
|
7546
|
+
const sectionsPrefetchGenRef = useRef5(0);
|
|
7547
|
+
const setLinkPopoverRef = useRef5(setLinkPopover);
|
|
7548
|
+
const linkPopoverPanelRef = useRef5(null);
|
|
7549
|
+
const linkPopoverOpenRef = useRef5(false);
|
|
7550
|
+
const linkPopoverGraceUntilRef = useRef5(0);
|
|
8977
7551
|
setLinkPopoverRef.current = setLinkPopover;
|
|
8978
7552
|
linkPopoverSessionRef.current = linkPopover;
|
|
8979
|
-
const {
|
|
8980
|
-
navDragRef,
|
|
8981
|
-
navDropSlots,
|
|
8982
|
-
activeNavDropIndex,
|
|
8983
|
-
startNavLinkDrag,
|
|
8984
|
-
commitNavDrag,
|
|
8985
|
-
onNavDragOver,
|
|
8986
|
-
armNavPressFromChrome,
|
|
8987
|
-
refreshNavDragVisualsRef
|
|
8988
|
-
} = useNavItemDrag({
|
|
8989
|
-
isEditMode,
|
|
8990
|
-
editContentRef,
|
|
8991
|
-
selectedElRef,
|
|
8992
|
-
activeElRef,
|
|
8993
|
-
footerDragRef,
|
|
8994
|
-
suppressNextClickRef,
|
|
8995
|
-
suppressClickUntilRef,
|
|
8996
|
-
siblingHintElRef,
|
|
8997
|
-
postToParentRef,
|
|
8998
|
-
deselectRef,
|
|
8999
|
-
selectRef,
|
|
9000
|
-
deactivateRef,
|
|
9001
|
-
setLinkPopover: () => setLinkPopover(null),
|
|
9002
|
-
linkPopoverOpenRef,
|
|
9003
|
-
setIsItemDragging,
|
|
9004
|
-
setDraggedItemRect,
|
|
9005
|
-
setSiblingHintRect,
|
|
9006
|
-
setSiblingHintRects,
|
|
9007
|
-
setToolbarRect,
|
|
9008
|
-
getNavigationItemAnchor,
|
|
9009
|
-
isDragHandleDisabled,
|
|
9010
|
-
isNavbarButton: isNavbarButton2
|
|
9011
|
-
});
|
|
9012
7553
|
const bumpLinkPopoverGrace = () => {
|
|
9013
7554
|
linkPopoverGraceUntilRef.current = Date.now() + 350;
|
|
9014
7555
|
};
|
|
9015
|
-
const runSectionsPrefetch =
|
|
7556
|
+
const runSectionsPrefetch = useCallback3((pages) => {
|
|
9016
7557
|
if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
|
|
9017
7558
|
const gen = ++sectionsPrefetchGenRef.current;
|
|
9018
7559
|
const paths = pages.map((p) => p.path);
|
|
@@ -9031,24 +7572,10 @@ function OhhwellsBridge() {
|
|
|
9031
7572
|
);
|
|
9032
7573
|
});
|
|
9033
7574
|
}, [isEditMode, pathname]);
|
|
9034
|
-
const runSectionsPrefetchRef =
|
|
7575
|
+
const runSectionsPrefetchRef = useRef5(runSectionsPrefetch);
|
|
9035
7576
|
runSectionsPrefetchRef.current = runSectionsPrefetch;
|
|
9036
|
-
|
|
9037
|
-
if (!linkPopover)
|
|
9038
|
-
document.documentElement.removeAttribute("data-ohw-link-popover-open");
|
|
9039
|
-
return;
|
|
9040
|
-
}
|
|
9041
|
-
document.documentElement.setAttribute("data-ohw-link-popover-open", "");
|
|
9042
|
-
hoveredItemElRef.current = null;
|
|
9043
|
-
setHoveredItemRect(null);
|
|
9044
|
-
hoveredNavContainerRef.current = null;
|
|
9045
|
-
setHoveredNavContainerRect(null);
|
|
9046
|
-
siblingHintElRef.current = null;
|
|
9047
|
-
setSiblingHintRect(null);
|
|
9048
|
-
setSiblingHintRects([]);
|
|
9049
|
-
if (selectedElRef.current || toolbarVariantRef.current !== "none") {
|
|
9050
|
-
deselectRef.current();
|
|
9051
|
-
}
|
|
7577
|
+
useEffect7(() => {
|
|
7578
|
+
if (!linkPopover) return;
|
|
9052
7579
|
if (hoveredImageRef.current) {
|
|
9053
7580
|
hoveredImageRef.current = null;
|
|
9054
7581
|
hoveredImageHasTextOverlapRef.current = false;
|
|
@@ -9082,7 +7609,7 @@ function OhhwellsBridge() {
|
|
|
9082
7609
|
document.removeEventListener("touchmove", preventBackgroundScroll, scrollOpts);
|
|
9083
7610
|
};
|
|
9084
7611
|
}, [linkPopover, postToParent2]);
|
|
9085
|
-
|
|
7612
|
+
useEffect7(() => {
|
|
9086
7613
|
if (!isEditMode) return;
|
|
9087
7614
|
const useFixtures = shouldUseDevFixtures();
|
|
9088
7615
|
if (useFixtures) {
|
|
@@ -9106,14 +7633,14 @@ function OhhwellsBridge() {
|
|
|
9106
7633
|
if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
|
|
9107
7634
|
return () => window.removeEventListener("message", onSitePages);
|
|
9108
7635
|
}, [isEditMode, postToParent2]);
|
|
9109
|
-
|
|
7636
|
+
useEffect7(() => {
|
|
9110
7637
|
if (!isEditMode || shouldUseDevFixtures()) return;
|
|
9111
7638
|
void loadAllSectionsManifest().then((manifest) => {
|
|
9112
7639
|
if (Object.keys(manifest).length === 0) return;
|
|
9113
7640
|
setSectionsByPath((prev) => ({ ...manifest, ...prev }));
|
|
9114
7641
|
});
|
|
9115
7642
|
}, [isEditMode]);
|
|
9116
|
-
|
|
7643
|
+
useEffect7(() => {
|
|
9117
7644
|
const update = () => {
|
|
9118
7645
|
const el = activeElRef.current ?? selectedElRef.current;
|
|
9119
7646
|
if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
@@ -9137,10 +7664,10 @@ function OhhwellsBridge() {
|
|
|
9137
7664
|
vvp.removeEventListener("resize", update);
|
|
9138
7665
|
};
|
|
9139
7666
|
}, []);
|
|
9140
|
-
const refreshStateRules =
|
|
7667
|
+
const refreshStateRules = useCallback3(() => {
|
|
9141
7668
|
editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
|
|
9142
7669
|
}, []);
|
|
9143
|
-
const processConfigRequest =
|
|
7670
|
+
const processConfigRequest = useCallback3((insertAfterVal) => {
|
|
9144
7671
|
const tracker = getSectionsTracker();
|
|
9145
7672
|
let entries = [];
|
|
9146
7673
|
try {
|
|
@@ -9163,7 +7690,7 @@ function OhhwellsBridge() {
|
|
|
9163
7690
|
}
|
|
9164
7691
|
window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
|
|
9165
7692
|
}, [isEditMode]);
|
|
9166
|
-
const deactivate =
|
|
7693
|
+
const deactivate = useCallback3(() => {
|
|
9167
7694
|
const el = activeElRef.current;
|
|
9168
7695
|
if (!el) return;
|
|
9169
7696
|
const key = el.dataset.ohwKey;
|
|
@@ -9182,7 +7709,6 @@ function OhhwellsBridge() {
|
|
|
9182
7709
|
}
|
|
9183
7710
|
}
|
|
9184
7711
|
el.removeAttribute("contenteditable");
|
|
9185
|
-
el.removeAttribute("data-ohw-editing");
|
|
9186
7712
|
activeElRef.current = null;
|
|
9187
7713
|
setReorderHrefKey(null);
|
|
9188
7714
|
setReorderDragDisabled(false);
|
|
@@ -9195,23 +7721,12 @@ function OhhwellsBridge() {
|
|
|
9195
7721
|
setToolbarShowEditLink(false);
|
|
9196
7722
|
postToParent2({ type: "ow:exit-edit" });
|
|
9197
7723
|
}, [postToParent2]);
|
|
9198
|
-
const
|
|
9199
|
-
document.querySelectorAll("[data-ohw-selected]").forEach((el) => {
|
|
9200
|
-
el.removeAttribute("data-ohw-selected");
|
|
9201
|
-
});
|
|
9202
|
-
}, []);
|
|
9203
|
-
const deselect = useCallback5(() => {
|
|
9204
|
-
clearSelectedAttr();
|
|
7724
|
+
const deselect = useCallback3(() => {
|
|
9205
7725
|
selectedElRef.current = null;
|
|
9206
|
-
selectedHrefKeyRef.current = null;
|
|
9207
|
-
selectedFooterColAttrRef.current = null;
|
|
9208
|
-
setSelectedIsCta(false);
|
|
9209
7726
|
setReorderHrefKey(null);
|
|
9210
7727
|
setReorderDragDisabled(false);
|
|
9211
|
-
setIsFooterFrameSelection(false);
|
|
9212
7728
|
siblingHintElRef.current = null;
|
|
9213
7729
|
setSiblingHintRect(null);
|
|
9214
|
-
setSiblingHintRects([]);
|
|
9215
7730
|
setIsItemDragging(false);
|
|
9216
7731
|
hoveredNavContainerRef.current = null;
|
|
9217
7732
|
setHoveredNavContainerRect(null);
|
|
@@ -9219,70 +7734,18 @@ function OhhwellsBridge() {
|
|
|
9219
7734
|
setToolbarRect(null);
|
|
9220
7735
|
setToolbarVariant("none");
|
|
9221
7736
|
}
|
|
9222
|
-
}, [clearSelectedAttr]);
|
|
9223
|
-
const markSelected = useCallback5((el) => {
|
|
9224
|
-
clearSelectedAttr();
|
|
9225
|
-
el.setAttribute("data-ohw-selected", "");
|
|
9226
|
-
}, [clearSelectedAttr]);
|
|
9227
|
-
const resolveHrefKeyElement = useCallback5((hrefKey) => {
|
|
9228
|
-
if (isFooterHrefKey(hrefKey)) {
|
|
9229
|
-
return document.querySelector(
|
|
9230
|
-
`footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
9231
|
-
);
|
|
9232
|
-
}
|
|
9233
|
-
if (isNavbarHrefKey(hrefKey)) {
|
|
9234
|
-
const desktop = document.querySelector("[data-ohw-nav-container]");
|
|
9235
|
-
const drawer = document.querySelector("[data-ohw-nav-drawer]");
|
|
9236
|
-
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)}"]`);
|
|
9237
|
-
}
|
|
9238
|
-
return document.querySelector(
|
|
9239
|
-
`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
9240
|
-
);
|
|
9241
7737
|
}, []);
|
|
9242
|
-
const
|
|
9243
|
-
const hrefKey = selectedHrefKeyRef.current;
|
|
9244
|
-
if (hrefKey) {
|
|
9245
|
-
const link = resolveHrefKeyElement(hrefKey);
|
|
9246
|
-
if (!link || !isNavigationItem(link)) return;
|
|
9247
|
-
selectedElRef.current = link;
|
|
9248
|
-
const { key, disabled } = getNavigationItemReorderState(link);
|
|
9249
|
-
setReorderHrefKey(key);
|
|
9250
|
-
setReorderDragDisabled(disabled);
|
|
9251
|
-
setIsFooterFrameSelection(false);
|
|
9252
|
-
setToolbarVariant("link-action");
|
|
9253
|
-
setToolbarRect(link.getBoundingClientRect());
|
|
9254
|
-
setSiblingHintRects(collectNavigationItemSiblingHintRects(link));
|
|
9255
|
-
return;
|
|
9256
|
-
}
|
|
9257
|
-
const colAttr = selectedFooterColAttrRef.current;
|
|
9258
|
-
if (colAttr != null) {
|
|
9259
|
-
const column = document.querySelector(`[data-ohw-footer-col="${CSS.escape(colAttr)}"]`) ?? listFooterColumns()[Number(colAttr)] ?? null;
|
|
9260
|
-
if (!column || !isNavigationContainer(column)) return;
|
|
9261
|
-
selectedElRef.current = column;
|
|
9262
|
-
setIsFooterFrameSelection(true);
|
|
9263
|
-
setToolbarVariant("select-frame");
|
|
9264
|
-
setToolbarRect(column.getBoundingClientRect());
|
|
9265
|
-
setSiblingHintRects(
|
|
9266
|
-
listFooterColumns().filter((c) => c !== column).map((c) => c.getBoundingClientRect())
|
|
9267
|
-
);
|
|
9268
|
-
}
|
|
9269
|
-
}, [resolveHrefKeyElement]);
|
|
9270
|
-
const reselectNavigationItem = useCallback5((navAnchor) => {
|
|
7738
|
+
const reselectNavigationItem = useCallback3((navAnchor) => {
|
|
9271
7739
|
selectedElRef.current = navAnchor;
|
|
9272
|
-
selectedHrefKeyRef.current = navAnchor.getAttribute("data-ohw-href-key");
|
|
9273
|
-
selectedFooterColAttrRef.current = null;
|
|
9274
|
-
markSelected(navAnchor);
|
|
9275
|
-
setSelectedIsCta(isNavbarButton2(navAnchor));
|
|
9276
7740
|
const { key, disabled } = getNavigationItemReorderState(navAnchor);
|
|
9277
7741
|
setReorderHrefKey(key);
|
|
9278
7742
|
setReorderDragDisabled(disabled);
|
|
9279
7743
|
setToolbarVariant("link-action");
|
|
9280
7744
|
setToolbarRect(navAnchor.getBoundingClientRect());
|
|
9281
|
-
setSiblingHintRects(collectNavigationItemSiblingHintRects(navAnchor));
|
|
9282
7745
|
setToolbarShowEditLink(false);
|
|
9283
7746
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
9284
|
-
}, [
|
|
9285
|
-
const commitNavigationTextEdit =
|
|
7747
|
+
}, []);
|
|
7748
|
+
const commitNavigationTextEdit = useCallback3((navAnchor) => {
|
|
9286
7749
|
const el = activeElRef.current;
|
|
9287
7750
|
if (!el) return;
|
|
9288
7751
|
const key = el.dataset.ohwKey;
|
|
@@ -9301,7 +7764,6 @@ function OhhwellsBridge() {
|
|
|
9301
7764
|
}
|
|
9302
7765
|
}
|
|
9303
7766
|
el.removeAttribute("contenteditable");
|
|
9304
|
-
el.removeAttribute("data-ohw-editing");
|
|
9305
7767
|
activeElRef.current = null;
|
|
9306
7768
|
setMaxBadge(null);
|
|
9307
7769
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
@@ -9309,7 +7771,7 @@ function OhhwellsBridge() {
|
|
|
9309
7771
|
postToParent2({ type: "ow:exit-edit" });
|
|
9310
7772
|
reselectNavigationItem(navAnchor);
|
|
9311
7773
|
}, [postToParent2, reselectNavigationItem]);
|
|
9312
|
-
const handleAddTopLevelNavItem =
|
|
7774
|
+
const handleAddTopLevelNavItem = useCallback3(() => {
|
|
9313
7775
|
const items = listNavbarItems();
|
|
9314
7776
|
addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
|
|
9315
7777
|
deselectRef.current();
|
|
@@ -9321,321 +7783,20 @@ function OhhwellsBridge() {
|
|
|
9321
7783
|
intent: "add-nav"
|
|
9322
7784
|
});
|
|
9323
7785
|
}, []);
|
|
9324
|
-
const
|
|
9325
|
-
|
|
9326
|
-
|
|
9327
|
-
|
|
9328
|
-
setActiveFooterDropIndex(null);
|
|
9329
|
-
setDraggedItemRect(null);
|
|
9330
|
-
setIsItemDragging(false);
|
|
9331
|
-
unlockFooterDragInteraction();
|
|
9332
|
-
}, []);
|
|
9333
|
-
const refreshFooterDragVisuals = useCallback5((session, activeSlot, clientX, clientY) => {
|
|
9334
|
-
const dragged = session.draggedEl;
|
|
9335
|
-
setDraggedItemRect(dragged.getBoundingClientRect());
|
|
9336
|
-
if (typeof clientX === "number" && typeof clientY === "number") {
|
|
9337
|
-
session.lastClientX = clientX;
|
|
9338
|
-
session.lastClientY = clientY;
|
|
9339
|
-
}
|
|
9340
|
-
session.activeSlot = activeSlot;
|
|
9341
|
-
if (session.kind === "link") {
|
|
9342
|
-
const columns2 = listFooterColumns();
|
|
9343
|
-
const focusCols = /* @__PURE__ */ new Set([session.sourceColumnIndex]);
|
|
9344
|
-
if (activeSlot) focusCols.add(activeSlot.columnIndex);
|
|
9345
|
-
const siblingRects = [];
|
|
9346
|
-
columns2.forEach((col, i) => {
|
|
9347
|
-
if (!focusCols.has(i)) return;
|
|
9348
|
-
for (const link of listFooterLinksInColumn(col)) {
|
|
9349
|
-
if (link === dragged) continue;
|
|
9350
|
-
siblingRects.push(link.getBoundingClientRect());
|
|
9351
|
-
}
|
|
9352
|
-
});
|
|
9353
|
-
setSiblingHintRects(siblingRects);
|
|
9354
|
-
const slots2 = [];
|
|
9355
|
-
columns2.forEach((col, i) => {
|
|
9356
|
-
slots2.push(...buildLinkDropSlots(col, i));
|
|
9357
|
-
});
|
|
9358
|
-
setFooterDropSlots(slots2);
|
|
9359
|
-
const activeIdx2 = activeSlot ? slots2.findIndex((s) => s.columnIndex === activeSlot.columnIndex && s.insertIndex === activeSlot.insertIndex) : -1;
|
|
9360
|
-
setActiveFooterDropIndex(activeIdx2 >= 0 ? activeIdx2 : null);
|
|
9361
|
-
return;
|
|
9362
|
-
}
|
|
9363
|
-
const columns = listFooterColumns();
|
|
9364
|
-
setSiblingHintRects(columns.filter((col) => col !== dragged).map((col) => col.getBoundingClientRect()));
|
|
9365
|
-
const slots = buildColumnDropSlots();
|
|
9366
|
-
setFooterDropSlots(slots);
|
|
9367
|
-
const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
|
|
9368
|
-
setActiveFooterDropIndex(activeIdx >= 0 ? activeIdx : null);
|
|
7786
|
+
const handleItemDragStart = useCallback3(() => {
|
|
7787
|
+
siblingHintElRef.current = null;
|
|
7788
|
+
setSiblingHintRect(null);
|
|
7789
|
+
setIsItemDragging(true);
|
|
9369
7790
|
}, []);
|
|
9370
|
-
const
|
|
9371
|
-
|
|
9372
|
-
const commitFooterDragRef = useRef7(() => {
|
|
9373
|
-
});
|
|
9374
|
-
const beginFooterDragRef = useRef7(() => {
|
|
9375
|
-
});
|
|
9376
|
-
const beginFooterDrag = useCallback5(
|
|
9377
|
-
(session) => {
|
|
9378
|
-
const rect = session.draggedEl.getBoundingClientRect();
|
|
9379
|
-
session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
|
|
9380
|
-
session.lastClientY = session.lastClientY || rect.top + rect.height / 2;
|
|
9381
|
-
session.activeSlot = session.activeSlot ?? null;
|
|
9382
|
-
footerDragRef.current = session;
|
|
9383
|
-
setIsItemDragging(true);
|
|
9384
|
-
lockFooterDuringDrag();
|
|
9385
|
-
siblingHintElRef.current = null;
|
|
9386
|
-
setSiblingHintRect(null);
|
|
9387
|
-
if (session.wasSelected && selectedElRef.current === session.draggedEl) {
|
|
9388
|
-
setToolbarRect(rect);
|
|
9389
|
-
}
|
|
9390
|
-
const initialSlot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
|
|
9391
|
-
refreshFooterDragVisuals(session, initialSlot, session.lastClientX, session.lastClientY);
|
|
9392
|
-
},
|
|
9393
|
-
[refreshFooterDragVisuals]
|
|
9394
|
-
);
|
|
9395
|
-
beginFooterDragRef.current = beginFooterDrag;
|
|
9396
|
-
const commitFooterDrag = useCallback5(
|
|
9397
|
-
(clientX, clientY) => {
|
|
9398
|
-
const session = footerDragRef.current;
|
|
9399
|
-
if (!session) {
|
|
9400
|
-
clearFooterDragVisuals();
|
|
9401
|
-
return;
|
|
9402
|
-
}
|
|
9403
|
-
const x = typeof clientX === "number" && (clientX !== 0 || clientY !== 0) ? clientX : session.lastClientX;
|
|
9404
|
-
const y = typeof clientY === "number" && (clientX !== 0 || clientY !== 0) ? clientY : session.lastClientY;
|
|
9405
|
-
let nextOrder = null;
|
|
9406
|
-
const slot = session.activeSlot ?? (session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(x, y, session.hrefKey) : session.kind === "column" ? hitTestColumnDropSlot(x, y) : null);
|
|
9407
|
-
if (session.kind === "link" && session.hrefKey && slot) {
|
|
9408
|
-
nextOrder = planFooterLinkMove(session.hrefKey, slot.columnIndex, slot.insertIndex);
|
|
9409
|
-
} else if (session.kind === "column" && slot) {
|
|
9410
|
-
nextOrder = planFooterColumnMove(session.sourceColumnIndex, slot.insertIndex);
|
|
9411
|
-
}
|
|
9412
|
-
const wasSelected = session.wasSelected;
|
|
9413
|
-
const draggedEl = session.draggedEl;
|
|
9414
|
-
const hrefKey = session.hrefKey;
|
|
9415
|
-
let movedColumnIndex = null;
|
|
9416
|
-
if (session.kind === "column" && slot && nextOrder) {
|
|
9417
|
-
let adjusted = slot.insertIndex;
|
|
9418
|
-
if (session.sourceColumnIndex < slot.insertIndex) adjusted -= 1;
|
|
9419
|
-
movedColumnIndex = Math.max(0, Math.min(adjusted, nextOrder.length - 1));
|
|
9420
|
-
}
|
|
9421
|
-
const applySelectionAfterDrop = () => {
|
|
9422
|
-
if (!wasSelected) {
|
|
9423
|
-
deselectRef.current();
|
|
9424
|
-
return;
|
|
9425
|
-
}
|
|
9426
|
-
if (hrefKey) {
|
|
9427
|
-
selectedHrefKeyRef.current = hrefKey;
|
|
9428
|
-
selectedFooterColAttrRef.current = null;
|
|
9429
|
-
const link = resolveHrefKeyElement(hrefKey);
|
|
9430
|
-
if (link && isNavigationItem(link)) {
|
|
9431
|
-
selectRef.current(link);
|
|
9432
|
-
return;
|
|
9433
|
-
}
|
|
9434
|
-
}
|
|
9435
|
-
if (movedColumnIndex !== null && nextOrder) {
|
|
9436
|
-
const colKeys = nextOrder[movedColumnIndex] ?? [];
|
|
9437
|
-
let column = null;
|
|
9438
|
-
for (const key of colKeys) {
|
|
9439
|
-
const link = document.querySelector(
|
|
9440
|
-
`footer [data-ohw-href-key="${CSS.escape(key)}"]`
|
|
9441
|
-
);
|
|
9442
|
-
if (link) {
|
|
9443
|
-
column = findFooterColumnForLink(link);
|
|
9444
|
-
if (column) break;
|
|
9445
|
-
}
|
|
9446
|
-
}
|
|
9447
|
-
if (!column) column = listFooterColumns()[movedColumnIndex] ?? null;
|
|
9448
|
-
if (column && isNavigationContainer(column)) {
|
|
9449
|
-
selectFrameRef.current(column);
|
|
9450
|
-
return;
|
|
9451
|
-
}
|
|
9452
|
-
}
|
|
9453
|
-
if (document.body.contains(draggedEl)) {
|
|
9454
|
-
if (isNavigationItem(draggedEl)) {
|
|
9455
|
-
selectRef.current(draggedEl);
|
|
9456
|
-
return;
|
|
9457
|
-
}
|
|
9458
|
-
if (isNavigationContainer(draggedEl)) {
|
|
9459
|
-
selectFrameRef.current(draggedEl);
|
|
9460
|
-
return;
|
|
9461
|
-
}
|
|
9462
|
-
}
|
|
9463
|
-
deselectRef.current();
|
|
9464
|
-
};
|
|
9465
|
-
if (nextOrder) {
|
|
9466
|
-
const orderJson = JSON.stringify(nextOrder);
|
|
9467
|
-
editContentRef.current = {
|
|
9468
|
-
...editContentRef.current,
|
|
9469
|
-
[FOOTER_ORDER_KEY]: orderJson
|
|
9470
|
-
};
|
|
9471
|
-
applyFooterOrder(nextOrder);
|
|
9472
|
-
document.querySelectorAll("footer [data-ohw-href-key]").forEach(disableNativeHrefDrag);
|
|
9473
|
-
postToParentRef.current({
|
|
9474
|
-
type: "ow:change",
|
|
9475
|
-
nodes: [{ key: FOOTER_ORDER_KEY, text: orderJson }]
|
|
9476
|
-
});
|
|
9477
|
-
applySelectionAfterDrop();
|
|
9478
|
-
clearFooterDragVisuals();
|
|
9479
|
-
requestAnimationFrame(() => {
|
|
9480
|
-
if (editContentRef.current[FOOTER_ORDER_KEY] === orderJson) {
|
|
9481
|
-
applyFooterOrder(nextOrder);
|
|
9482
|
-
document.querySelectorAll("footer [data-ohw-href-key]").forEach(disableNativeHrefDrag);
|
|
9483
|
-
}
|
|
9484
|
-
applySelectionAfterDrop();
|
|
9485
|
-
requestAnimationFrame(() => {
|
|
9486
|
-
if (editContentRef.current[FOOTER_ORDER_KEY] === orderJson) {
|
|
9487
|
-
applyFooterOrder(nextOrder);
|
|
9488
|
-
}
|
|
9489
|
-
resyncSelectedNavigationItem();
|
|
9490
|
-
});
|
|
9491
|
-
});
|
|
9492
|
-
return;
|
|
9493
|
-
}
|
|
9494
|
-
applySelectionAfterDrop();
|
|
9495
|
-
clearFooterDragVisuals();
|
|
9496
|
-
},
|
|
9497
|
-
[clearFooterDragVisuals, resolveHrefKeyElement, resyncSelectedNavigationItem]
|
|
9498
|
-
);
|
|
9499
|
-
commitFooterDragRef.current = commitFooterDrag;
|
|
9500
|
-
const startFooterLinkDrag = useCallback5(
|
|
9501
|
-
(anchor, clientX, clientY, wasSelected) => {
|
|
9502
|
-
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
9503
|
-
if (!hrefKey || !isFooterHrefKey(hrefKey)) return false;
|
|
9504
|
-
const column = findFooterColumnForLink(anchor);
|
|
9505
|
-
const columns = listFooterColumns();
|
|
9506
|
-
beginFooterDrag({
|
|
9507
|
-
kind: "link",
|
|
9508
|
-
hrefKey,
|
|
9509
|
-
columnEl: column,
|
|
9510
|
-
sourceColumnIndex: column ? columns.indexOf(column) : 0,
|
|
9511
|
-
wasSelected,
|
|
9512
|
-
draggedEl: anchor,
|
|
9513
|
-
lastClientX: clientX,
|
|
9514
|
-
lastClientY: clientY,
|
|
9515
|
-
activeSlot: null
|
|
9516
|
-
});
|
|
9517
|
-
return true;
|
|
9518
|
-
},
|
|
9519
|
-
[beginFooterDrag]
|
|
9520
|
-
);
|
|
9521
|
-
const startFooterColumnDrag = useCallback5(
|
|
9522
|
-
(columnEl, clientX, clientY, wasSelected) => {
|
|
9523
|
-
const columns = listFooterColumns();
|
|
9524
|
-
const idx = columns.indexOf(columnEl);
|
|
9525
|
-
if (idx < 0) return false;
|
|
9526
|
-
beginFooterDrag({
|
|
9527
|
-
kind: "column",
|
|
9528
|
-
hrefKey: null,
|
|
9529
|
-
columnEl,
|
|
9530
|
-
sourceColumnIndex: idx,
|
|
9531
|
-
wasSelected,
|
|
9532
|
-
draggedEl: columnEl,
|
|
9533
|
-
lastClientX: clientX,
|
|
9534
|
-
lastClientY: clientY,
|
|
9535
|
-
activeSlot: null
|
|
9536
|
-
});
|
|
9537
|
-
return true;
|
|
9538
|
-
},
|
|
9539
|
-
[beginFooterDrag]
|
|
9540
|
-
);
|
|
9541
|
-
const handleItemDragStart = useCallback5(
|
|
9542
|
-
(e) => {
|
|
9543
|
-
const selected = selectedElRef.current;
|
|
9544
|
-
if (!selected) {
|
|
9545
|
-
setIsItemDragging(true);
|
|
9546
|
-
return;
|
|
9547
|
-
}
|
|
9548
|
-
const clientX = e?.clientX ?? selected.getBoundingClientRect().left + 8;
|
|
9549
|
-
const clientY = e?.clientY ?? selected.getBoundingClientRect().top + 8;
|
|
9550
|
-
if (startFooterLinkDrag(selected, clientX, clientY, true)) return;
|
|
9551
|
-
if (selected.hasAttribute("data-ohw-footer-col") || isInferredFooterGroup(selected) && selected.closest("footer")) {
|
|
9552
|
-
if (startFooterColumnDrag(selected, clientX, clientY, true)) return;
|
|
9553
|
-
}
|
|
9554
|
-
if (startNavLinkDrag(selected, clientX, clientY, true)) return;
|
|
9555
|
-
siblingHintElRef.current = null;
|
|
9556
|
-
setSiblingHintRect(null);
|
|
9557
|
-
setIsItemDragging(true);
|
|
9558
|
-
},
|
|
9559
|
-
[startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag]
|
|
9560
|
-
);
|
|
9561
|
-
const handleItemDragEnd = useCallback5(
|
|
9562
|
-
(e) => {
|
|
9563
|
-
if (footerDragRef.current) {
|
|
9564
|
-
const x = e?.clientX;
|
|
9565
|
-
const y = e?.clientY;
|
|
9566
|
-
if (typeof x === "number" && typeof y === "number" && (x !== 0 || y !== 0)) {
|
|
9567
|
-
commitFooterDrag(x, y);
|
|
9568
|
-
} else {
|
|
9569
|
-
commitFooterDrag();
|
|
9570
|
-
}
|
|
9571
|
-
return;
|
|
9572
|
-
}
|
|
9573
|
-
if (navDragRef.current) {
|
|
9574
|
-
const x = e?.clientX;
|
|
9575
|
-
const y = e?.clientY;
|
|
9576
|
-
if (typeof x === "number" && typeof y === "number" && (x !== 0 || y !== 0)) {
|
|
9577
|
-
commitNavDrag(x, y);
|
|
9578
|
-
} else {
|
|
9579
|
-
commitNavDrag();
|
|
9580
|
-
}
|
|
9581
|
-
return;
|
|
9582
|
-
}
|
|
9583
|
-
setIsItemDragging(false);
|
|
9584
|
-
},
|
|
9585
|
-
[commitFooterDrag, commitNavDrag, navDragRef]
|
|
9586
|
-
);
|
|
9587
|
-
const handleItemChromePointerDown = useCallback5((e) => {
|
|
9588
|
-
if (e.button !== 0) return;
|
|
9589
|
-
const selected = selectedElRef.current;
|
|
9590
|
-
if (!selected) return;
|
|
9591
|
-
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
9592
|
-
if (hrefKey && isFooterHrefKey(hrefKey)) {
|
|
9593
|
-
footerPointerDragRef.current = {
|
|
9594
|
-
el: selected,
|
|
9595
|
-
kind: "link",
|
|
9596
|
-
startX: e.clientX,
|
|
9597
|
-
startY: e.clientY,
|
|
9598
|
-
pointerId: e.pointerId,
|
|
9599
|
-
wasSelected: true,
|
|
9600
|
-
started: false
|
|
9601
|
-
};
|
|
9602
|
-
return;
|
|
9603
|
-
}
|
|
9604
|
-
if (selected.hasAttribute("data-ohw-footer-col") || isInferredFooterGroup(selected) && selected.closest("footer")) {
|
|
9605
|
-
footerPointerDragRef.current = {
|
|
9606
|
-
el: selected,
|
|
9607
|
-
kind: "column",
|
|
9608
|
-
startX: e.clientX,
|
|
9609
|
-
startY: e.clientY,
|
|
9610
|
-
pointerId: e.pointerId,
|
|
9611
|
-
wasSelected: true,
|
|
9612
|
-
started: false
|
|
9613
|
-
};
|
|
9614
|
-
return;
|
|
9615
|
-
}
|
|
9616
|
-
if (armNavPressFromChrome(selected, e.clientX, e.clientY, e.pointerId)) return;
|
|
9617
|
-
}, [armNavPressFromChrome]);
|
|
9618
|
-
const handleItemChromeClick = useCallback5((clientX, clientY) => {
|
|
9619
|
-
if (suppressNextClickRef.current || Date.now() < suppressClickUntilRef.current) {
|
|
9620
|
-
suppressNextClickRef.current = false;
|
|
9621
|
-
return;
|
|
9622
|
-
}
|
|
9623
|
-
const selected = selectedElRef.current;
|
|
9624
|
-
if (!selected || !isNavigationItem(selected)) return;
|
|
9625
|
-
const editable = selected.querySelector('[data-ohw-editable="text"]') ?? selected.querySelector("[data-ohw-editable]");
|
|
9626
|
-
if (!editable) return;
|
|
9627
|
-
activateRef.current(editable, { caretX: clientX, caretY: clientY });
|
|
7791
|
+
const handleItemDragEnd = useCallback3(() => {
|
|
7792
|
+
setIsItemDragging(false);
|
|
9628
7793
|
}, []);
|
|
9629
7794
|
reselectNavigationItemRef.current = reselectNavigationItem;
|
|
9630
7795
|
commitNavigationTextEditRef.current = commitNavigationTextEdit;
|
|
9631
|
-
const select =
|
|
7796
|
+
const select = useCallback3((anchor) => {
|
|
9632
7797
|
if (!isNavigationItem(anchor)) return;
|
|
9633
7798
|
if (activeElRef.current) deactivate();
|
|
9634
7799
|
selectedElRef.current = anchor;
|
|
9635
|
-
selectedHrefKeyRef.current = anchor.getAttribute("data-ohw-href-key");
|
|
9636
|
-
selectedFooterColAttrRef.current = null;
|
|
9637
|
-
markSelected(anchor);
|
|
9638
|
-
setSelectedIsCta(isNavbarButton2(anchor));
|
|
9639
7800
|
clearHrefKeyHover(anchor);
|
|
9640
7801
|
hoveredNavContainerRef.current = null;
|
|
9641
7802
|
setHoveredNavContainerRect(null);
|
|
@@ -9643,26 +7804,19 @@ function OhhwellsBridge() {
|
|
|
9643
7804
|
hoveredItemElRef.current = null;
|
|
9644
7805
|
siblingHintElRef.current = null;
|
|
9645
7806
|
setSiblingHintRect(null);
|
|
9646
|
-
setSiblingHintRects(collectNavigationItemSiblingHintRects(anchor));
|
|
9647
7807
|
setIsItemDragging(false);
|
|
9648
7808
|
const { key, disabled } = getNavigationItemReorderState(anchor);
|
|
9649
7809
|
setReorderHrefKey(key);
|
|
9650
7810
|
setReorderDragDisabled(disabled);
|
|
9651
|
-
setIsFooterFrameSelection(false);
|
|
9652
7811
|
setToolbarVariant("link-action");
|
|
9653
7812
|
setToolbarRect(anchor.getBoundingClientRect());
|
|
9654
7813
|
setToolbarShowEditLink(false);
|
|
9655
7814
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
9656
|
-
}, [deactivate
|
|
9657
|
-
const selectFrame =
|
|
7815
|
+
}, [deactivate]);
|
|
7816
|
+
const selectFrame = useCallback3((el) => {
|
|
9658
7817
|
if (!isNavigationContainer(el)) return;
|
|
9659
7818
|
if (activeElRef.current) deactivate();
|
|
9660
|
-
const isFooterColumn = el.hasAttribute("data-ohw-footer-col") || Boolean(el.closest("footer") && isInferredFooterGroup(el));
|
|
9661
7819
|
selectedElRef.current = el;
|
|
9662
|
-
selectedHrefKeyRef.current = null;
|
|
9663
|
-
selectedFooterColAttrRef.current = isFooterColumn ? el.getAttribute("data-ohw-footer-col") ?? String(listFooterColumns().indexOf(el)) : null;
|
|
9664
|
-
markSelected(el);
|
|
9665
|
-
setSelectedIsCta(false);
|
|
9666
7820
|
clearHrefKeyHover(el);
|
|
9667
7821
|
hoveredNavContainerRef.current = null;
|
|
9668
7822
|
setHoveredNavContainerRect(null);
|
|
@@ -9670,25 +7824,17 @@ function OhhwellsBridge() {
|
|
|
9670
7824
|
hoveredItemElRef.current = null;
|
|
9671
7825
|
siblingHintElRef.current = null;
|
|
9672
7826
|
setSiblingHintRect(null);
|
|
9673
|
-
setSiblingHintRects(
|
|
9674
|
-
isFooterColumn ? listFooterColumns().filter((column) => column !== el).map((column) => column.getBoundingClientRect()) : []
|
|
9675
|
-
);
|
|
9676
7827
|
setIsItemDragging(false);
|
|
9677
7828
|
setReorderHrefKey(null);
|
|
9678
7829
|
setReorderDragDisabled(false);
|
|
9679
|
-
setIsFooterFrameSelection(isFooterColumn);
|
|
9680
7830
|
setToolbarVariant("select-frame");
|
|
9681
7831
|
setToolbarRect(el.getBoundingClientRect());
|
|
9682
7832
|
setToolbarShowEditLink(false);
|
|
9683
7833
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
9684
|
-
}, [deactivate
|
|
9685
|
-
const activate =
|
|
7834
|
+
}, [deactivate]);
|
|
7835
|
+
const activate = useCallback3((el, options) => {
|
|
9686
7836
|
if (activeElRef.current === el) return;
|
|
9687
|
-
clearSelectedAttr();
|
|
9688
7837
|
selectedElRef.current = null;
|
|
9689
|
-
selectedHrefKeyRef.current = null;
|
|
9690
|
-
selectedFooterColAttrRef.current = null;
|
|
9691
|
-
setSelectedIsCta(false);
|
|
9692
7838
|
deactivate();
|
|
9693
7839
|
if (hoveredImageRef.current) {
|
|
9694
7840
|
hoveredImageRef.current = null;
|
|
@@ -9698,34 +7844,14 @@ function OhhwellsBridge() {
|
|
|
9698
7844
|
siblingHintElRef.current = null;
|
|
9699
7845
|
setSiblingHintRect(null);
|
|
9700
7846
|
setIsItemDragging(false);
|
|
9701
|
-
const preActivationSelection = window.getSelection();
|
|
9702
|
-
const preservedRange = preActivationSelection && preActivationSelection.rangeCount > 0 && !preActivationSelection.isCollapsed && el.contains(preActivationSelection.getRangeAt(0).commonAncestorContainer) ? preActivationSelection.getRangeAt(0).cloneRange() : null;
|
|
9703
7847
|
el.setAttribute("contenteditable", "true");
|
|
9704
|
-
el.setAttribute("data-ohw-editing", "");
|
|
9705
7848
|
el.removeAttribute("data-ohw-hovered");
|
|
9706
7849
|
el.closest("[data-ohw-href-key]")?.removeAttribute("data-ohw-hovered");
|
|
9707
7850
|
activeElRef.current = el;
|
|
9708
7851
|
originalContentRef.current = el.innerHTML;
|
|
9709
|
-
el.focus(
|
|
9710
|
-
if (
|
|
9711
|
-
|
|
9712
|
-
selection?.removeAllRanges();
|
|
9713
|
-
selection?.addRange(preservedRange);
|
|
9714
|
-
} else if (options?.caretX !== void 0 && options?.caretY !== void 0) {
|
|
9715
|
-
const { caretX, caretY } = options;
|
|
9716
|
-
placeCaretAtPoint(el, caretX, caretY);
|
|
9717
|
-
requestAnimationFrame(() => {
|
|
9718
|
-
if (activeElRef.current === el) placeCaretAtPoint(el, caretX, caretY);
|
|
9719
|
-
});
|
|
9720
|
-
} else {
|
|
9721
|
-
const selection = window.getSelection();
|
|
9722
|
-
if (selection && selection.rangeCount === 0) {
|
|
9723
|
-
const range = document.createRange();
|
|
9724
|
-
range.selectNodeContents(el);
|
|
9725
|
-
range.collapse(false);
|
|
9726
|
-
selection.removeAllRanges();
|
|
9727
|
-
selection.addRange(range);
|
|
9728
|
-
}
|
|
7852
|
+
el.focus();
|
|
7853
|
+
if (options?.caretX !== void 0 && options?.caretY !== void 0) {
|
|
7854
|
+
placeCaretAtPoint(el, options.caretX, options.caretY);
|
|
9729
7855
|
}
|
|
9730
7856
|
setToolbarShowEditLink(Boolean(getHrefKeyFromElement(el)));
|
|
9731
7857
|
const navAnchor = getNavigationItemAnchor(el);
|
|
@@ -9740,13 +7866,13 @@ function OhhwellsBridge() {
|
|
|
9740
7866
|
setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
9741
7867
|
postToParent2({ type: "ow:enter-edit", key: el.dataset.ohwKey });
|
|
9742
7868
|
requestAnimationFrame(() => refreshActiveCommandsRef.current());
|
|
9743
|
-
}, [
|
|
7869
|
+
}, [deactivate, postToParent2]);
|
|
9744
7870
|
activateRef.current = activate;
|
|
9745
7871
|
deactivateRef.current = deactivate;
|
|
9746
7872
|
selectRef.current = select;
|
|
9747
7873
|
selectFrameRef.current = selectFrame;
|
|
9748
7874
|
deselectRef.current = deselect;
|
|
9749
|
-
|
|
7875
|
+
useLayoutEffect2(() => {
|
|
9750
7876
|
if (!subdomain || isEditMode) {
|
|
9751
7877
|
setFetchState("done");
|
|
9752
7878
|
return;
|
|
@@ -9787,7 +7913,6 @@ function OhhwellsBridge() {
|
|
|
9787
7913
|
applyLinkByKey(key, val);
|
|
9788
7914
|
}
|
|
9789
7915
|
reconcileNavbarItemsFromContent(content);
|
|
9790
|
-
reconcileFooterOrderFromContent(content);
|
|
9791
7916
|
enforceLinkHrefs();
|
|
9792
7917
|
initSectionsFromContent(content, true);
|
|
9793
7918
|
sectionsLoadedRef.current = true;
|
|
@@ -9816,7 +7941,7 @@ function OhhwellsBridge() {
|
|
|
9816
7941
|
cancelled = true;
|
|
9817
7942
|
};
|
|
9818
7943
|
}, [subdomain, isEditMode]);
|
|
9819
|
-
|
|
7944
|
+
useEffect7(() => {
|
|
9820
7945
|
if (!subdomain || isEditMode) return;
|
|
9821
7946
|
let debounceTimer = null;
|
|
9822
7947
|
let observer = null;
|
|
@@ -9848,7 +7973,6 @@ function OhhwellsBridge() {
|
|
|
9848
7973
|
applyLinkByKey(key, val);
|
|
9849
7974
|
}
|
|
9850
7975
|
reconcileNavbarItemsFromContent(content);
|
|
9851
|
-
reconcileFooterOrderFromContent(content);
|
|
9852
7976
|
} finally {
|
|
9853
7977
|
observer?.observe(document.body, { childList: true, subtree: true });
|
|
9854
7978
|
}
|
|
@@ -9866,16 +7990,16 @@ function OhhwellsBridge() {
|
|
|
9866
7990
|
if (debounceTimer) clearTimeout(debounceTimer);
|
|
9867
7991
|
};
|
|
9868
7992
|
}, [subdomain, isEditMode, pathname]);
|
|
9869
|
-
|
|
7993
|
+
useLayoutEffect2(() => {
|
|
9870
7994
|
const el = document.getElementById("ohw-loader");
|
|
9871
7995
|
if (!el) return;
|
|
9872
7996
|
const visible = Boolean(subdomain) && fetchState !== "done";
|
|
9873
7997
|
el.style.display = visible ? "flex" : "none";
|
|
9874
7998
|
}, [subdomain, fetchState]);
|
|
9875
|
-
|
|
7999
|
+
useEffect7(() => {
|
|
9876
8000
|
postToParent2({ type: "ow:navigation", path: pathname });
|
|
9877
8001
|
}, [pathname, postToParent2]);
|
|
9878
|
-
|
|
8002
|
+
useEffect7(() => {
|
|
9879
8003
|
if (!isEditMode) return;
|
|
9880
8004
|
if (linkPopoverSessionRef.current?.intent === "add-nav") return;
|
|
9881
8005
|
if (document.querySelector("[data-ohw-section-picker]")) return;
|
|
@@ -9883,72 +8007,23 @@ function OhhwellsBridge() {
|
|
|
9883
8007
|
deselectRef.current();
|
|
9884
8008
|
deactivateRef.current();
|
|
9885
8009
|
}, [pathname, isEditMode]);
|
|
9886
|
-
|
|
8010
|
+
useEffect7(() => {
|
|
9887
8011
|
const contentForNav = () => {
|
|
9888
8012
|
if (isEditMode) return editContentRef.current;
|
|
9889
8013
|
if (!subdomain) return {};
|
|
9890
8014
|
return contentCache.get(subdomain) ?? {};
|
|
9891
8015
|
};
|
|
9892
|
-
const
|
|
9893
|
-
(el) => Boolean(el)
|
|
9894
|
-
);
|
|
9895
|
-
const roots = observeRoots();
|
|
9896
|
-
if (roots.length === 0) {
|
|
9897
|
-
reconcileNavbarItemsFromContent(contentForNav());
|
|
9898
|
-
reconcileFooterOrderFromContent(contentForNav());
|
|
9899
|
-
if (isEditMode) syncNavigationDragCursorAttrs();
|
|
9900
|
-
return;
|
|
9901
|
-
}
|
|
9902
|
-
let rafId = null;
|
|
9903
|
-
let applying = false;
|
|
9904
|
-
let observer = null;
|
|
9905
|
-
const attach = () => {
|
|
9906
|
-
for (const root of observeRoots()) {
|
|
9907
|
-
observer?.observe(root, { childList: true, subtree: true });
|
|
9908
|
-
}
|
|
9909
|
-
};
|
|
9910
|
-
const run = () => {
|
|
9911
|
-
if (footerDragRef.current || navDragRef.current || applying) return;
|
|
9912
|
-
applying = true;
|
|
9913
|
-
observer?.disconnect();
|
|
9914
|
-
try {
|
|
9915
|
-
const content = contentForNav();
|
|
9916
|
-
reconcileNavbarItemsFromContent(content);
|
|
9917
|
-
reconcileFooterOrderFromContent(content);
|
|
9918
|
-
document.querySelectorAll("footer [data-ohw-href-key]").forEach((el) => {
|
|
9919
|
-
if (isFooterHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
9920
|
-
disableNativeHrefDrag(el);
|
|
9921
|
-
}
|
|
9922
|
-
});
|
|
9923
|
-
document.querySelectorAll(
|
|
9924
|
-
"nav [data-ohw-href-key], [data-ohw-nav-container] [data-ohw-href-key], [data-ohw-nav-drawer] [data-ohw-href-key]"
|
|
9925
|
-
).forEach((el) => {
|
|
9926
|
-
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
9927
|
-
disableNativeHrefDrag(el);
|
|
9928
|
-
}
|
|
9929
|
-
});
|
|
9930
|
-
resyncSelectedNavigationItem();
|
|
9931
|
-
if (isEditMode) syncNavigationDragCursorAttrs();
|
|
9932
|
-
} finally {
|
|
9933
|
-
applying = false;
|
|
9934
|
-
attach();
|
|
9935
|
-
}
|
|
9936
|
-
};
|
|
9937
|
-
const schedule = () => {
|
|
9938
|
-
if (applying || rafId != null) return;
|
|
9939
|
-
rafId = requestAnimationFrame(() => {
|
|
9940
|
-
rafId = null;
|
|
9941
|
-
run();
|
|
9942
|
-
});
|
|
9943
|
-
};
|
|
9944
|
-
observer = new MutationObserver(schedule);
|
|
8016
|
+
const run = () => reconcileNavbarItemsFromContent(contentForNav());
|
|
9945
8017
|
run();
|
|
9946
|
-
|
|
9947
|
-
|
|
9948
|
-
|
|
9949
|
-
|
|
9950
|
-
|
|
9951
|
-
|
|
8018
|
+
const nav = document.querySelector("nav");
|
|
8019
|
+
if (!nav) return;
|
|
8020
|
+
const observer = new MutationObserver(() => {
|
|
8021
|
+
requestAnimationFrame(run);
|
|
8022
|
+
});
|
|
8023
|
+
observer.observe(nav, { childList: true, subtree: true });
|
|
8024
|
+
return () => observer.disconnect();
|
|
8025
|
+
}, [isEditMode, pathname, subdomain, fetchState]);
|
|
8026
|
+
useEffect7(() => {
|
|
9952
8027
|
if (!isEditMode) return;
|
|
9953
8028
|
const measure = () => {
|
|
9954
8029
|
const h = document.body.scrollHeight;
|
|
@@ -9972,7 +8047,7 @@ function OhhwellsBridge() {
|
|
|
9972
8047
|
window.removeEventListener("resize", handleResize);
|
|
9973
8048
|
};
|
|
9974
8049
|
}, [pathname, isEditMode, postToParent2]);
|
|
9975
|
-
|
|
8050
|
+
useEffect7(() => {
|
|
9976
8051
|
if (!subdomainFromQuery || isEditMode) return;
|
|
9977
8052
|
const handleClick = (e) => {
|
|
9978
8053
|
const anchor = e.target.closest("a");
|
|
@@ -9988,24 +8063,19 @@ function OhhwellsBridge() {
|
|
|
9988
8063
|
document.addEventListener("click", handleClick, true);
|
|
9989
8064
|
return () => document.removeEventListener("click", handleClick, true);
|
|
9990
8065
|
}, [subdomainFromQuery, isEditMode, router]);
|
|
9991
|
-
|
|
8066
|
+
useEffect7(() => {
|
|
9992
8067
|
if (!isEditMode) {
|
|
9993
8068
|
editStylesRef.current?.base.remove();
|
|
9994
8069
|
editStylesRef.current?.forceHover.remove();
|
|
9995
8070
|
editStylesRef.current?.stateViews.remove();
|
|
9996
8071
|
editStylesRef.current = null;
|
|
9997
|
-
document.querySelectorAll("[data-ohw-can-drag]").forEach((el) => {
|
|
9998
|
-
el.removeAttribute("data-ohw-can-drag");
|
|
9999
|
-
});
|
|
10000
8072
|
return;
|
|
10001
8073
|
}
|
|
10002
|
-
|
|
10003
|
-
|
|
10004
|
-
|
|
10005
|
-
|
|
10006
|
-
|
|
10007
|
-
}
|
|
10008
|
-
const baseCss = `
|
|
8074
|
+
if (!editStylesRef.current) {
|
|
8075
|
+
const initialVh = window.innerHeight;
|
|
8076
|
+
const base = document.createElement("style");
|
|
8077
|
+
base.setAttribute("data-ohw-edit-style", "");
|
|
8078
|
+
base.textContent = `
|
|
10009
8079
|
html { height: auto !important; }
|
|
10010
8080
|
body { height: auto !important; min-height: 0 !important; overflow: hidden !important; }
|
|
10011
8081
|
.min-h-screen, .min-h-svh, .min-h-dvh { min-height: ${initialVh}px !important; }
|
|
@@ -10016,25 +8086,7 @@ function OhhwellsBridge() {
|
|
|
10016
8086
|
[data-ohw-editable] {
|
|
10017
8087
|
display: block;
|
|
10018
8088
|
}
|
|
10019
|
-
|
|
10020
|
-
Exclude select-first nav/footer labels so grab/default on [data-ohw-href-key] can win. */
|
|
10021
|
-
[data-ohw-editable]:not([contenteditable]):not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]):not([data-ohw-editable="video"]):not([data-ohw-editable="link"]):not(:is([data-ohw-href-key] *)) {
|
|
10022
|
-
cursor: text !important;
|
|
10023
|
-
}
|
|
10024
|
-
/* Select-first items: default arrow; grab only when drag-start is allowed (data-ohw-can-drag). */
|
|
10025
|
-
[data-ohw-href-key]:not([data-ohw-selected]),
|
|
10026
|
-
[data-ohw-href-key]:not([data-ohw-selected]) * {
|
|
10027
|
-
cursor: default !important;
|
|
10028
|
-
}
|
|
10029
|
-
[data-ohw-href-key][data-ohw-can-drag]:not([data-ohw-selected]),
|
|
10030
|
-
[data-ohw-href-key][data-ohw-can-drag]:not([data-ohw-selected]) * {
|
|
10031
|
-
cursor: grab !important;
|
|
10032
|
-
}
|
|
10033
|
-
/* Selected (action-toolbar) \u2014 next click enters text edit at caret. */
|
|
10034
|
-
[data-ohw-href-key][data-ohw-selected],
|
|
10035
|
-
[data-ohw-href-key][data-ohw-selected] * {
|
|
10036
|
-
cursor: text !important;
|
|
10037
|
-
}
|
|
8089
|
+
[data-ohw-editable]:not([contenteditable]):not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]):not([data-ohw-editable="video"]) { cursor: text !important; }
|
|
10038
8090
|
[data-ohw-editable="image"], [data-ohw-editable="image"] *,
|
|
10039
8091
|
[data-ohw-editable="video"], [data-ohw-editable="video"] *,
|
|
10040
8092
|
[data-ohw-editable="bg-image"], [data-ohw-editable="bg-image"] * { cursor: pointer !important; }
|
|
@@ -10050,32 +8102,9 @@ function OhhwellsBridge() {
|
|
|
10050
8102
|
outline: none !important;
|
|
10051
8103
|
outline-offset: 0 !important;
|
|
10052
8104
|
}
|
|
10053
|
-
|
|
10054
|
-
nav [data-ohw-href-key]:focus,
|
|
10055
|
-
nav [data-ohw-href-key]:focus-visible,
|
|
10056
|
-
nav [data-ohw-href-key]:focus-within,
|
|
10057
|
-
footer [data-ohw-href-key]:focus,
|
|
10058
|
-
footer [data-ohw-href-key]:focus-visible,
|
|
10059
|
-
footer [data-ohw-href-key]:focus-within,
|
|
10060
|
-
nav [data-ohw-href-key] [data-ohw-editable]:focus,
|
|
10061
|
-
nav [data-ohw-href-key] [data-ohw-editable]:focus-visible,
|
|
10062
|
-
footer [data-ohw-href-key] [data-ohw-editable]:focus,
|
|
10063
|
-
footer [data-ohw-href-key] [data-ohw-editable]:focus-visible {
|
|
10064
|
-
outline: none !important;
|
|
10065
|
-
outline-offset: 0 !important;
|
|
10066
|
-
box-shadow: none !important;
|
|
10067
|
-
}
|
|
10068
|
-
/* Text edit wins over grab/default (must beat [data-ohw-can-drag] *). */
|
|
10069
|
-
[data-ohw-editing],
|
|
10070
|
-
[data-ohw-editing] *,
|
|
10071
|
-
[data-ohw-editable][contenteditable],
|
|
10072
|
-
[data-ohw-editable][contenteditable] *,
|
|
10073
|
-
nav [data-ohw-href-key] [data-ohw-editable][contenteditable],
|
|
10074
|
-
nav [data-ohw-href-key] [data-ohw-editable][contenteditable] *,
|
|
10075
|
-
footer [data-ohw-href-key] [data-ohw-editable][contenteditable],
|
|
10076
|
-
footer [data-ohw-href-key] [data-ohw-editable][contenteditable] * {
|
|
8105
|
+
[data-ohw-editable][contenteditable] {
|
|
10077
8106
|
outline: none !important;
|
|
10078
|
-
caret-color: ${PRIMARY2}
|
|
8107
|
+
caret-color: ${PRIMARY2};
|
|
10079
8108
|
cursor: text !important;
|
|
10080
8109
|
}
|
|
10081
8110
|
[data-ohw-editable][contenteditable]::selection,
|
|
@@ -10084,9 +8113,6 @@ function OhhwellsBridge() {
|
|
|
10084
8113
|
[data-ohw-editable-state][data-ohw-active-state] [data-ohw-editable] { pointer-events: auto !important; }
|
|
10085
8114
|
[data-ohw-editable-state][data-ohw-active-state][data-ohw-editable] { pointer-events: auto !important; }
|
|
10086
8115
|
`;
|
|
10087
|
-
if (!existing) {
|
|
10088
|
-
const base = document.createElement("style");
|
|
10089
|
-
base.setAttribute("data-ohw-edit-style", "");
|
|
10090
8116
|
const forceHover = document.createElement("style");
|
|
10091
8117
|
forceHover.setAttribute("data-ohw-active-state-style", "");
|
|
10092
8118
|
const stateViews = document.createElement("style");
|
|
@@ -10102,43 +8128,14 @@ function OhhwellsBridge() {
|
|
|
10102
8128
|
document.head.appendChild(stateViews);
|
|
10103
8129
|
editStylesRef.current = { base, forceHover, stateViews };
|
|
10104
8130
|
}
|
|
10105
|
-
editStylesRef.current.base.textContent = baseCss;
|
|
10106
|
-
syncNavigationDragCursorAttrs();
|
|
10107
8131
|
refreshStateRules();
|
|
10108
8132
|
const handleClick = (e) => {
|
|
10109
|
-
if (suppressNextClickRef.current || Date.now() < suppressClickUntilRef.current) {
|
|
10110
|
-
suppressNextClickRef.current = false;
|
|
10111
|
-
e.preventDefault();
|
|
10112
|
-
e.stopPropagation();
|
|
10113
|
-
return;
|
|
10114
|
-
}
|
|
10115
8133
|
const target = e.target;
|
|
10116
8134
|
if (target.closest("[data-ohw-toolbar]")) return;
|
|
10117
8135
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
10118
8136
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
10119
8137
|
if (isInsideLinkEditor(target)) return;
|
|
10120
8138
|
if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
10121
|
-
if (target.closest("[data-ohw-item-drag-surface]")) {
|
|
10122
|
-
e.preventDefault();
|
|
10123
|
-
e.stopPropagation();
|
|
10124
|
-
const selected = selectedElRef.current;
|
|
10125
|
-
if (selected && isNavigationItem(selected)) {
|
|
10126
|
-
const editable2 = selected.querySelector('[data-ohw-editable="text"]') ?? selected.querySelector("[data-ohw-editable]");
|
|
10127
|
-
if (editable2) {
|
|
10128
|
-
activateRef.current(editable2, {
|
|
10129
|
-
caretX: e.clientX,
|
|
10130
|
-
caretY: e.clientY
|
|
10131
|
-
});
|
|
10132
|
-
}
|
|
10133
|
-
} else if (selected?.hasAttribute("data-ohw-footer-col")) {
|
|
10134
|
-
const link = listFooterLinksInColumn(selected).find((el) => {
|
|
10135
|
-
const r2 = el.getBoundingClientRect();
|
|
10136
|
-
return e.clientX >= r2.left && e.clientX <= r2.right && e.clientY >= r2.top && e.clientY <= r2.bottom;
|
|
10137
|
-
});
|
|
10138
|
-
if (link) selectRef.current(link);
|
|
10139
|
-
}
|
|
10140
|
-
return;
|
|
10141
|
-
}
|
|
10142
8139
|
const navFromChrome = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
|
|
10143
8140
|
if (navFromChrome) {
|
|
10144
8141
|
e.preventDefault();
|
|
@@ -10146,45 +8143,10 @@ function OhhwellsBridge() {
|
|
|
10146
8143
|
selectFrameRef.current(navFromChrome);
|
|
10147
8144
|
return;
|
|
10148
8145
|
}
|
|
10149
|
-
const footerFromChrome = resolveFooterColumnSelectionTarget(target, e.clientX, e.clientY);
|
|
10150
|
-
if (footerFromChrome) {
|
|
10151
|
-
e.preventDefault();
|
|
10152
|
-
e.stopPropagation();
|
|
10153
|
-
selectFrameRef.current(footerFromChrome);
|
|
10154
|
-
return;
|
|
10155
|
-
}
|
|
10156
8146
|
e.preventDefault();
|
|
10157
8147
|
e.stopPropagation();
|
|
10158
8148
|
return;
|
|
10159
8149
|
}
|
|
10160
|
-
if (activeElRef.current) {
|
|
10161
|
-
const active = activeElRef.current;
|
|
10162
|
-
const inActive = active === target || active.contains(target);
|
|
10163
|
-
const navAnchor = getNavigationItemAnchor(active);
|
|
10164
|
-
const inActiveNav = Boolean(
|
|
10165
|
-
navAnchor && (navAnchor === target || navAnchor.contains(target))
|
|
10166
|
-
);
|
|
10167
|
-
if (inActive || inActiveNav) {
|
|
10168
|
-
e.preventDefault();
|
|
10169
|
-
e.stopPropagation();
|
|
10170
|
-
const selection = window.getSelection();
|
|
10171
|
-
const hasRangeSelection = Boolean(selection && !selection.isCollapsed);
|
|
10172
|
-
console.log(
|
|
10173
|
-
"[OHW DEBUG handleClick] already-active branch",
|
|
10174
|
-
"detail=",
|
|
10175
|
-
e.detail,
|
|
10176
|
-
"hasRangeSelection=",
|
|
10177
|
-
hasRangeSelection,
|
|
10178
|
-
"willPlaceCaret=",
|
|
10179
|
-
e.detail < 2 && !hasRangeSelection
|
|
10180
|
-
);
|
|
10181
|
-
if (e.detail < 2 && !hasRangeSelection) {
|
|
10182
|
-
placeCaretAtPoint(active, e.clientX, e.clientY);
|
|
10183
|
-
refreshActiveCommandsRef.current();
|
|
10184
|
-
}
|
|
10185
|
-
return;
|
|
10186
|
-
}
|
|
10187
|
-
}
|
|
10188
8150
|
const editable = target.closest("[data-ohw-editable]");
|
|
10189
8151
|
if (editable) {
|
|
10190
8152
|
if (editable.dataset.ohwEditable === "link") {
|
|
@@ -10221,15 +8183,6 @@ function OhhwellsBridge() {
|
|
|
10221
8183
|
}
|
|
10222
8184
|
e.preventDefault();
|
|
10223
8185
|
e.stopPropagation();
|
|
10224
|
-
console.log(
|
|
10225
|
-
"[OHW DEBUG handleClick] first-activation branch",
|
|
10226
|
-
"detail=",
|
|
10227
|
-
e.detail,
|
|
10228
|
-
"selectionAtClick=",
|
|
10229
|
-
JSON.stringify(window.getSelection()?.toString() ?? ""),
|
|
10230
|
-
"collapsedAtClick=",
|
|
10231
|
-
window.getSelection()?.isCollapsed
|
|
10232
|
-
);
|
|
10233
8186
|
activateRef.current(editable);
|
|
10234
8187
|
return;
|
|
10235
8188
|
}
|
|
@@ -10237,26 +8190,10 @@ function OhhwellsBridge() {
|
|
|
10237
8190
|
if (hrefAnchor) {
|
|
10238
8191
|
e.preventDefault();
|
|
10239
8192
|
e.stopPropagation();
|
|
10240
|
-
if (selectedElRef.current === hrefAnchor)
|
|
10241
|
-
const textEditable = hrefAnchor.querySelector('[data-ohw-editable="text"]') ?? hrefAnchor.querySelector("[data-ohw-editable]");
|
|
10242
|
-
if (textEditable) {
|
|
10243
|
-
activateRef.current(textEditable, {
|
|
10244
|
-
caretX: e.clientX,
|
|
10245
|
-
caretY: e.clientY
|
|
10246
|
-
});
|
|
10247
|
-
}
|
|
10248
|
-
return;
|
|
10249
|
-
}
|
|
8193
|
+
if (selectedElRef.current === hrefAnchor) return;
|
|
10250
8194
|
selectRef.current(hrefAnchor);
|
|
10251
8195
|
return;
|
|
10252
8196
|
}
|
|
10253
|
-
const footerColClick = target.closest("[data-ohw-footer-col]");
|
|
10254
|
-
if (footerColClick) {
|
|
10255
|
-
e.preventDefault();
|
|
10256
|
-
e.stopPropagation();
|
|
10257
|
-
selectFrameRef.current(footerColClick);
|
|
10258
|
-
return;
|
|
10259
|
-
}
|
|
10260
8197
|
const navContainerToSelect = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
|
|
10261
8198
|
if (navContainerToSelect) {
|
|
10262
8199
|
e.preventDefault();
|
|
@@ -10264,13 +8201,6 @@ function OhhwellsBridge() {
|
|
|
10264
8201
|
selectFrameRef.current(navContainerToSelect);
|
|
10265
8202
|
return;
|
|
10266
8203
|
}
|
|
10267
|
-
const footerColumnToSelect = resolveFooterColumnSelectionTarget(target, e.clientX, e.clientY);
|
|
10268
|
-
if (footerColumnToSelect) {
|
|
10269
|
-
e.preventDefault();
|
|
10270
|
-
e.stopPropagation();
|
|
10271
|
-
selectFrameRef.current(footerColumnToSelect);
|
|
10272
|
-
return;
|
|
10273
|
-
}
|
|
10274
8204
|
const selectedContainer = selectedElRef.current;
|
|
10275
8205
|
if (selectedContainer && isNavigationContainer(selectedContainer)) {
|
|
10276
8206
|
const navItem = getNavigationItemAnchor(target);
|
|
@@ -10330,13 +8260,6 @@ function OhhwellsBridge() {
|
|
|
10330
8260
|
const handleMouseOver = (e) => {
|
|
10331
8261
|
if (document.documentElement.hasAttribute("data-ohw-section-picking")) return;
|
|
10332
8262
|
const target = e.target;
|
|
10333
|
-
if (linkPopoverOpenRef.current) {
|
|
10334
|
-
hoveredItemElRef.current = null;
|
|
10335
|
-
setHoveredItemRect(null);
|
|
10336
|
-
hoveredNavContainerRef.current = null;
|
|
10337
|
-
setHoveredNavContainerRect(null);
|
|
10338
|
-
return;
|
|
10339
|
-
}
|
|
10340
8263
|
if (toolbarVariantRef.current !== "select-frame") {
|
|
10341
8264
|
const navContainer = target.closest("[data-ohw-nav-container]");
|
|
10342
8265
|
if (navContainer && !getNavigationItemAnchor(target)) {
|
|
@@ -10356,21 +8279,12 @@ function OhhwellsBridge() {
|
|
|
10356
8279
|
hoveredNavContainerRef.current = null;
|
|
10357
8280
|
setHoveredNavContainerRect(null);
|
|
10358
8281
|
const selected2 = selectedElRef.current;
|
|
10359
|
-
if (selected2 === navAnchor) return;
|
|
8282
|
+
if (selected2 === navAnchor || selected2?.contains(navAnchor)) return;
|
|
10360
8283
|
clearHrefKeyHover(navAnchor);
|
|
10361
8284
|
hoveredItemElRef.current = navAnchor;
|
|
10362
8285
|
setHoveredItemRect(navAnchor.getBoundingClientRect());
|
|
10363
8286
|
return;
|
|
10364
8287
|
}
|
|
10365
|
-
const footerCol = target.closest("[data-ohw-footer-col]") ?? target.closest("[data-ohw-footer-column]");
|
|
10366
|
-
if (footerCol) {
|
|
10367
|
-
hoveredNavContainerRef.current = null;
|
|
10368
|
-
setHoveredNavContainerRect(null);
|
|
10369
|
-
if (selectedElRef.current === footerCol) return;
|
|
10370
|
-
hoveredItemElRef.current = footerCol;
|
|
10371
|
-
setHoveredItemRect(footerCol.getBoundingClientRect());
|
|
10372
|
-
return;
|
|
10373
|
-
}
|
|
10374
8288
|
const editable = target.closest("[data-ohw-editable]");
|
|
10375
8289
|
if (!editable) return;
|
|
10376
8290
|
const selected = selectedElRef.current;
|
|
@@ -10388,25 +8302,14 @@ function OhhwellsBridge() {
|
|
|
10388
8302
|
};
|
|
10389
8303
|
const handleMouseOut = (e) => {
|
|
10390
8304
|
const target = e.target;
|
|
10391
|
-
if (target.closest("[data-ohw-nav-container]
|
|
8305
|
+
if (target.closest("[data-ohw-nav-container]")) {
|
|
10392
8306
|
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
10393
|
-
if (related2?.closest("[data-ohw-nav-container], [data-ohw-
|
|
8307
|
+
if (related2?.closest("[data-ohw-nav-container], [data-ohw-navbar-container-chrome], [data-ohw-navbar-add-button]")) {
|
|
10394
8308
|
return;
|
|
10395
8309
|
}
|
|
10396
8310
|
hoveredNavContainerRef.current = null;
|
|
10397
8311
|
setHoveredNavContainerRect(null);
|
|
10398
8312
|
}
|
|
10399
|
-
const footerCol = target.closest("[data-ohw-footer-col]") ?? target.closest("[data-ohw-footer-column]");
|
|
10400
|
-
if (footerCol && hoveredItemElRef.current === footerCol) {
|
|
10401
|
-
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
10402
|
-
if (related2?.closest("[data-ohw-drag-handle-container], [data-ohw-item-interaction]")) return;
|
|
10403
|
-
if (related2?.closest("[data-ohw-footer-col], [data-ohw-footer-column]") === footerCol) {
|
|
10404
|
-
return;
|
|
10405
|
-
}
|
|
10406
|
-
hoveredItemElRef.current = null;
|
|
10407
|
-
setHoveredItemRect(null);
|
|
10408
|
-
return;
|
|
10409
|
-
}
|
|
10410
8313
|
const navAnchor = getNavigationItemAnchor(target);
|
|
10411
8314
|
if (navAnchor) {
|
|
10412
8315
|
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
@@ -10540,75 +8443,43 @@ function OhhwellsBridge() {
|
|
|
10540
8443
|
if (toolbarVariantRef.current === "select-frame") {
|
|
10541
8444
|
hoveredNavContainerRef.current = null;
|
|
10542
8445
|
setHoveredNavContainerRect(null);
|
|
8446
|
+
return;
|
|
10543
8447
|
}
|
|
10544
|
-
const
|
|
10545
|
-
|
|
10546
|
-
);
|
|
10547
|
-
const footerColumns = listFooterColumns();
|
|
10548
|
-
for (const container of [...navContainers, ...footerColumns]) {
|
|
10549
|
-
const containerRect = container.getBoundingClientRect();
|
|
10550
|
-
const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
|
|
10551
|
-
if (!overContainer) continue;
|
|
10552
|
-
const navItemHit = Array.from(
|
|
10553
|
-
container.querySelectorAll("[data-ohw-href-key]")
|
|
10554
|
-
).find((el) => {
|
|
10555
|
-
if (!isNavigationItem(el) || isNavbarButton2(el)) return false;
|
|
10556
|
-
const itemRect = el.getBoundingClientRect();
|
|
10557
|
-
return x >= itemRect.left && x <= itemRect.right && y >= itemRect.top && y <= itemRect.bottom;
|
|
10558
|
-
});
|
|
10559
|
-
if (navItemHit) {
|
|
10560
|
-
hoveredNavContainerRef.current = null;
|
|
10561
|
-
setHoveredNavContainerRect(null);
|
|
10562
|
-
const selected = selectedElRef.current;
|
|
10563
|
-
if (selected !== navItemHit) {
|
|
10564
|
-
clearHrefKeyHover(navItemHit);
|
|
10565
|
-
hoveredItemElRef.current = navItemHit;
|
|
10566
|
-
setHoveredItemRect(navItemHit.getBoundingClientRect());
|
|
10567
|
-
} else if (hoveredItemElRef.current === navItemHit) {
|
|
10568
|
-
hoveredItemElRef.current = null;
|
|
10569
|
-
setHoveredItemRect(null);
|
|
10570
|
-
}
|
|
10571
|
-
return;
|
|
10572
|
-
}
|
|
10573
|
-
}
|
|
10574
|
-
if (toolbarVariantRef.current !== "select-frame") {
|
|
10575
|
-
for (const container of navContainers) {
|
|
10576
|
-
const containerRect = container.getBoundingClientRect();
|
|
10577
|
-
const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
|
|
10578
|
-
if (!overContainer) continue;
|
|
10579
|
-
if (isPointOverNavItem(container, x, y)) continue;
|
|
10580
|
-
hoveredNavContainerRef.current = container;
|
|
10581
|
-
setHoveredNavContainerRect(container.getBoundingClientRect());
|
|
10582
|
-
hoveredItemElRef.current = null;
|
|
10583
|
-
setHoveredItemRect(null);
|
|
10584
|
-
return;
|
|
10585
|
-
}
|
|
8448
|
+
const navContainer = document.querySelector("[data-ohw-nav-container]");
|
|
8449
|
+
if (!navContainer) {
|
|
10586
8450
|
hoveredNavContainerRef.current = null;
|
|
10587
8451
|
setHoveredNavContainerRect(null);
|
|
10588
|
-
|
|
8452
|
+
return;
|
|
8453
|
+
}
|
|
8454
|
+
const containerRect = navContainer.getBoundingClientRect();
|
|
8455
|
+
const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
|
|
8456
|
+
if (!overContainer) {
|
|
10589
8457
|
hoveredNavContainerRef.current = null;
|
|
10590
8458
|
setHoveredNavContainerRect(null);
|
|
8459
|
+
return;
|
|
10591
8460
|
}
|
|
10592
|
-
|
|
10593
|
-
|
|
10594
|
-
|
|
10595
|
-
if (!
|
|
10596
|
-
|
|
10597
|
-
|
|
10598
|
-
|
|
10599
|
-
|
|
10600
|
-
|
|
10601
|
-
|
|
10602
|
-
|
|
8461
|
+
const navItemHit = Array.from(
|
|
8462
|
+
navContainer.querySelectorAll("[data-ohw-href-key]")
|
|
8463
|
+
).find((el) => {
|
|
8464
|
+
if (!isNavigationItem(el) || isNavbarButton2(el)) return false;
|
|
8465
|
+
const itemRect = el.getBoundingClientRect();
|
|
8466
|
+
return x >= itemRect.left && x <= itemRect.right && y >= itemRect.top && y <= itemRect.bottom;
|
|
8467
|
+
});
|
|
8468
|
+
if (navItemHit) {
|
|
8469
|
+
hoveredNavContainerRef.current = null;
|
|
8470
|
+
setHoveredNavContainerRect(null);
|
|
8471
|
+
const selected = selectedElRef.current;
|
|
8472
|
+
if (selected !== navItemHit && !selected?.contains(navItemHit)) {
|
|
8473
|
+
clearHrefKeyHover(navItemHit);
|
|
8474
|
+
hoveredItemElRef.current = navItemHit;
|
|
8475
|
+
setHoveredItemRect(navItemHit.getBoundingClientRect());
|
|
10603
8476
|
}
|
|
10604
|
-
hoveredItemElRef.current = column;
|
|
10605
|
-
setHoveredItemRect(column.getBoundingClientRect());
|
|
10606
8477
|
return;
|
|
10607
8478
|
}
|
|
10608
|
-
|
|
10609
|
-
|
|
10610
|
-
|
|
10611
|
-
|
|
8479
|
+
hoveredNavContainerRef.current = navContainer;
|
|
8480
|
+
setHoveredNavContainerRect(containerRect);
|
|
8481
|
+
hoveredItemElRef.current = null;
|
|
8482
|
+
setHoveredItemRect(null);
|
|
10612
8483
|
};
|
|
10613
8484
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
10614
8485
|
if (linkPopoverOpenRef.current) {
|
|
@@ -10629,10 +8500,6 @@ function OhhwellsBridge() {
|
|
|
10629
8500
|
}
|
|
10630
8501
|
hoveredNavContainerRef.current = null;
|
|
10631
8502
|
setHoveredNavContainerRect(null);
|
|
10632
|
-
if (hoveredItemElRef.current?.hasAttribute("data-ohw-footer-col") || hoveredItemElRef.current?.hasAttribute("data-ohw-footer-column")) {
|
|
10633
|
-
hoveredItemElRef.current = null;
|
|
10634
|
-
setHoveredItemRect(null);
|
|
10635
|
-
}
|
|
10636
8503
|
const toggleEl = document.querySelector("[data-ohw-state-toggle]");
|
|
10637
8504
|
if (toggleEl) {
|
|
10638
8505
|
const tr = toggleEl.getBoundingClientRect();
|
|
@@ -10880,15 +8747,6 @@ function OhhwellsBridge() {
|
|
|
10880
8747
|
probeHoverCardsAt(clientX, clientY);
|
|
10881
8748
|
};
|
|
10882
8749
|
const handleDragOver = (e) => {
|
|
10883
|
-
const footerSession = footerDragRef.current;
|
|
10884
|
-
if (footerSession) {
|
|
10885
|
-
e.preventDefault();
|
|
10886
|
-
if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
|
|
10887
|
-
const slot = footerSession.kind === "link" && footerSession.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, footerSession.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
|
|
10888
|
-
refreshFooterDragVisualsRef.current(footerSession, slot, e.clientX, e.clientY);
|
|
10889
|
-
return;
|
|
10890
|
-
}
|
|
10891
|
-
if (onNavDragOver(e)) return;
|
|
10892
8750
|
e.preventDefault();
|
|
10893
8751
|
const el = findImageAtPoint(e.clientX, e.clientY, false);
|
|
10894
8752
|
if (!el) {
|
|
@@ -11051,8 +8909,8 @@ function OhhwellsBridge() {
|
|
|
11051
8909
|
if (sibling !== el) sibling.innerHTML = html;
|
|
11052
8910
|
});
|
|
11053
8911
|
const timers = autoSaveTimers.current;
|
|
11054
|
-
const
|
|
11055
|
-
if (
|
|
8912
|
+
const existing = timers.get(key);
|
|
8913
|
+
if (existing) clearTimeout(existing);
|
|
11056
8914
|
timers.set(key, setTimeout(() => {
|
|
11057
8915
|
timers.delete(key);
|
|
11058
8916
|
postToParentRef.current({ type: "ow:change", nodes: [{ key, text: html }] });
|
|
@@ -11095,7 +8953,6 @@ function OhhwellsBridge() {
|
|
|
11095
8953
|
}
|
|
11096
8954
|
editContentRef.current = { ...editContentRef.current, ...content };
|
|
11097
8955
|
reconcileNavbarItemsFromContent(editContentRef.current);
|
|
11098
|
-
syncNavigationDragCursorAttrs();
|
|
11099
8956
|
enforceLinkHrefs();
|
|
11100
8957
|
postToParentRef.current({ type: "ow:hydrate-done" });
|
|
11101
8958
|
};
|
|
@@ -11116,48 +8973,6 @@ function OhhwellsBridge() {
|
|
|
11116
8973
|
if (e.data?.type !== "ui:escape") return;
|
|
11117
8974
|
if (linkPopoverOpenRef.current) {
|
|
11118
8975
|
setLinkPopoverRef.current(null);
|
|
11119
|
-
return;
|
|
11120
|
-
}
|
|
11121
|
-
if (activeElRef.current) {
|
|
11122
|
-
const hrefCtx = getHrefKeyFromElement(activeElRef.current);
|
|
11123
|
-
const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
|
|
11124
|
-
if (navAnchor) {
|
|
11125
|
-
const el = activeElRef.current;
|
|
11126
|
-
if (originalContentRef.current !== null) {
|
|
11127
|
-
el.innerHTML = originalContentRef.current;
|
|
11128
|
-
}
|
|
11129
|
-
el.removeAttribute("contenteditable");
|
|
11130
|
-
el.removeAttribute("data-ohw-editing");
|
|
11131
|
-
activeElRef.current = null;
|
|
11132
|
-
setMaxBadge(null);
|
|
11133
|
-
setActiveCommands(/* @__PURE__ */ new Set());
|
|
11134
|
-
setToolbarShowEditLink(false);
|
|
11135
|
-
postToParentRef.current({ type: "ow:exit-edit" });
|
|
11136
|
-
reselectNavigationItemRef.current(navAnchor);
|
|
11137
|
-
return;
|
|
11138
|
-
}
|
|
11139
|
-
if (originalContentRef.current !== null) {
|
|
11140
|
-
activeElRef.current.innerHTML = originalContentRef.current;
|
|
11141
|
-
const key = activeElRef.current.dataset.ohwKey;
|
|
11142
|
-
if (key) {
|
|
11143
|
-
postToParentRef.current({ type: "ow:change", nodes: [{ key, text: originalContentRef.current }] });
|
|
11144
|
-
}
|
|
11145
|
-
}
|
|
11146
|
-
deselectRef.current();
|
|
11147
|
-
deactivateRef.current();
|
|
11148
|
-
return;
|
|
11149
|
-
}
|
|
11150
|
-
if (selectedElRef.current) {
|
|
11151
|
-
if (toolbarVariantRef.current === "select-frame") {
|
|
11152
|
-
deselectRef.current();
|
|
11153
|
-
return;
|
|
11154
|
-
}
|
|
11155
|
-
const parent = getNavigationSelectionParent(selectedElRef.current);
|
|
11156
|
-
if (parent && isNavigationContainer(parent)) {
|
|
11157
|
-
selectFrameRef.current(parent);
|
|
11158
|
-
} else {
|
|
11159
|
-
deselectRef.current();
|
|
11160
|
-
}
|
|
11161
8976
|
}
|
|
11162
8977
|
};
|
|
11163
8978
|
window.addEventListener("message", handleUiEscape);
|
|
@@ -11182,7 +8997,7 @@ function OhhwellsBridge() {
|
|
|
11182
8997
|
return;
|
|
11183
8998
|
}
|
|
11184
8999
|
const parent = getNavigationSelectionParent(selectedElRef.current);
|
|
11185
|
-
if (parent
|
|
9000
|
+
if (parent) {
|
|
11186
9001
|
e.preventDefault();
|
|
11187
9002
|
selectFrameRef.current(parent);
|
|
11188
9003
|
} else {
|
|
@@ -11200,7 +9015,6 @@ function OhhwellsBridge() {
|
|
|
11200
9015
|
el2.innerHTML = originalContentRef.current;
|
|
11201
9016
|
}
|
|
11202
9017
|
el2.removeAttribute("contenteditable");
|
|
11203
|
-
el2.removeAttribute("data-ohw-editing");
|
|
11204
9018
|
activeElRef.current = null;
|
|
11205
9019
|
setMaxBadge(null);
|
|
11206
9020
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
@@ -11252,26 +9066,6 @@ function OhhwellsBridge() {
|
|
|
11252
9066
|
if (siblingHintElRef.current) {
|
|
11253
9067
|
setSiblingHintRect(siblingHintElRef.current.getBoundingClientRect());
|
|
11254
9068
|
}
|
|
11255
|
-
const selected = selectedElRef.current;
|
|
11256
|
-
if (selected && !footerDragRef.current && !navDragRef.current) {
|
|
11257
|
-
if (selected.hasAttribute("data-ohw-footer-col") || Boolean(selected.closest("footer") && isInferredFooterGroup(selected))) {
|
|
11258
|
-
setSiblingHintRects(
|
|
11259
|
-
listFooterColumns().filter((column) => column !== selected).map((column) => column.getBoundingClientRect())
|
|
11260
|
-
);
|
|
11261
|
-
} else if (isNavigationItem(selected)) {
|
|
11262
|
-
setSiblingHintRects(collectNavigationItemSiblingHintRects(selected));
|
|
11263
|
-
}
|
|
11264
|
-
}
|
|
11265
|
-
if (footerDragRef.current) {
|
|
11266
|
-
const session = footerDragRef.current;
|
|
11267
|
-
const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
|
|
11268
|
-
refreshFooterDragVisualsRef.current(session, slot, session.lastClientX, session.lastClientY);
|
|
11269
|
-
}
|
|
11270
|
-
if (navDragRef.current) {
|
|
11271
|
-
const session = navDragRef.current;
|
|
11272
|
-
const slot = hitTestNavDropSlot(session.lastClientX, session.lastClientY, session.hrefKey);
|
|
11273
|
-
refreshNavDragVisualsRef.current(session, slot, session.lastClientX, session.lastClientY);
|
|
11274
|
-
}
|
|
11275
9069
|
if (hoveredImageRef.current) {
|
|
11276
9070
|
const el = hoveredImageRef.current;
|
|
11277
9071
|
const r2 = el.getBoundingClientRect();
|
|
@@ -11282,7 +9076,7 @@ function OhhwellsBridge() {
|
|
|
11282
9076
|
};
|
|
11283
9077
|
const handleSave = (e) => {
|
|
11284
9078
|
if (e.data?.type !== "ow:save") return;
|
|
11285
|
-
const nodes = collectEditableNodes(
|
|
9079
|
+
const nodes = collectEditableNodes();
|
|
11286
9080
|
const tracker = document.querySelector("[data-ohw-sections-tracker]");
|
|
11287
9081
|
if (tracker?.textContent) nodes.push({ key: "__ohw_sections", type: "sections", text: tracker.textContent });
|
|
11288
9082
|
postToParentRef.current({ type: "ow:save-result", nodes });
|
|
@@ -11340,83 +9134,30 @@ function OhhwellsBridge() {
|
|
|
11340
9134
|
const h = document.documentElement.scrollHeight;
|
|
11341
9135
|
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
11342
9136
|
};
|
|
11343
|
-
|
|
11344
|
-
|
|
11345
|
-
selectionChangeRaf = null;
|
|
11346
|
-
const activeRoot = activeElRef.current;
|
|
11347
|
-
if (!activeRoot) return;
|
|
9137
|
+
const handleSelectionChange = () => {
|
|
9138
|
+
if (!activeElRef.current) return;
|
|
11348
9139
|
const next = /* @__PURE__ */ new Set();
|
|
11349
|
-
const
|
|
11350
|
-
|
|
11351
|
-
|
|
11352
|
-
|
|
11353
|
-
startNode = range.startContainer;
|
|
11354
|
-
if (startNode.nodeType === Node.ELEMENT_NODE) {
|
|
11355
|
-
const el = startNode;
|
|
11356
|
-
startNode = el.childNodes[range.startOffset] ?? el.childNodes[range.startOffset - 1] ?? el;
|
|
9140
|
+
for (const cmd of ["bold", "italic", "underline", "strikeThrough", "insertUnorderedList", "insertOrderedList"]) {
|
|
9141
|
+
try {
|
|
9142
|
+
if (document.queryCommandState(cmd)) next.add(cmd);
|
|
9143
|
+
} catch {
|
|
11357
9144
|
}
|
|
11358
9145
|
}
|
|
11359
|
-
const
|
|
11360
|
-
|
|
11361
|
-
|
|
11362
|
-
const
|
|
11363
|
-
|
|
11364
|
-
|
|
11365
|
-
|
|
11366
|
-
|
|
11367
|
-
|
|
11368
|
-
|
|
11369
|
-
for (let el = startEl; el; el = el.parentElement) {
|
|
11370
|
-
if (el.tagName === "B" || el.tagName === "STRONG") hasBold = true;
|
|
11371
|
-
if (el.tagName === "I" || el.tagName === "EM") hasItalic = true;
|
|
11372
|
-
const decoration = getComputedStyle(el).textDecorationLine;
|
|
11373
|
-
if (decoration.includes("underline") || el.tagName === "U" || el.tagName === "INS") hasUnderline = true;
|
|
11374
|
-
if (decoration.includes("line-through") || el.tagName === "S" || el.tagName === "STRIKE" || el.tagName === "DEL") hasStrike = true;
|
|
11375
|
-
if (el.tagName === "UL") hasUl = true;
|
|
11376
|
-
if (el.tagName === "OL") hasOl = true;
|
|
11377
|
-
if (el === activeRoot) break;
|
|
11378
|
-
}
|
|
11379
|
-
if (hasBold) next.add("bold");
|
|
11380
|
-
if (hasItalic) next.add("italic");
|
|
11381
|
-
if (hasUnderline) next.add("underline");
|
|
11382
|
-
if (hasStrike) next.add("strikeThrough");
|
|
11383
|
-
if (hasUl) next.add("insertUnorderedList");
|
|
11384
|
-
if (hasOl) next.add("insertOrderedList");
|
|
11385
|
-
const block = startEl.closest("div, p, h1, h2, h3, h4, h5, h6, li, td, th") ?? startEl;
|
|
11386
|
-
const align = getComputedStyle(block).textAlign;
|
|
11387
|
-
if (align === "center") next.add("justifyCenter");
|
|
11388
|
-
else if (align === "right" || align === "end") next.add("justifyRight");
|
|
11389
|
-
else next.add("justifyLeft");
|
|
11390
|
-
}
|
|
11391
|
-
setActiveCommands((prev) => {
|
|
11392
|
-
if (prev.size === next.size) {
|
|
11393
|
-
let same = true;
|
|
11394
|
-
for (const cmd of prev) {
|
|
11395
|
-
if (!next.has(cmd)) {
|
|
11396
|
-
same = false;
|
|
11397
|
-
break;
|
|
11398
|
-
}
|
|
11399
|
-
}
|
|
11400
|
-
if (same) return prev;
|
|
9146
|
+
const sel = window.getSelection();
|
|
9147
|
+
const anchor = sel?.anchorNode;
|
|
9148
|
+
if (anchor) {
|
|
9149
|
+
const el = anchor.nodeType === Node.TEXT_NODE ? anchor.parentElement : anchor;
|
|
9150
|
+
const block = el?.closest("div, p, h1, h2, h3, h4, h5, h6, li, td, th") ?? el;
|
|
9151
|
+
if (block) {
|
|
9152
|
+
const align = getComputedStyle(block).textAlign;
|
|
9153
|
+
if (align === "center") next.add("justifyCenter");
|
|
9154
|
+
else if (align === "right" || align === "end") next.add("justifyRight");
|
|
9155
|
+
else next.add("justifyLeft");
|
|
11401
9156
|
}
|
|
11402
|
-
|
|
11403
|
-
|
|
11404
|
-
};
|
|
11405
|
-
const handleSelectionChange = () => {
|
|
11406
|
-
if (pointerHeldRef.current) return;
|
|
11407
|
-
if (selectionChangeRaf !== null) return;
|
|
11408
|
-
selectionChangeRaf = requestAnimationFrame(runSelectionChange);
|
|
11409
|
-
};
|
|
11410
|
-
const markPointerHeld = (e) => {
|
|
11411
|
-
if (e.button !== 0) return;
|
|
11412
|
-
pointerHeldRef.current = true;
|
|
11413
|
-
};
|
|
11414
|
-
const markPointerReleased = () => {
|
|
11415
|
-
if (!pointerHeldRef.current) return;
|
|
11416
|
-
pointerHeldRef.current = false;
|
|
11417
|
-
handleSelectionChange();
|
|
9157
|
+
}
|
|
9158
|
+
setActiveCommands(next);
|
|
11418
9159
|
};
|
|
11419
|
-
refreshActiveCommandsRef.current =
|
|
9160
|
+
refreshActiveCommandsRef.current = handleSelectionChange;
|
|
11420
9161
|
const handleDocMouseLeave = () => {
|
|
11421
9162
|
hoveredImageRef.current = null;
|
|
11422
9163
|
setMediaHover(null);
|
|
@@ -11461,15 +9202,15 @@ function OhhwellsBridge() {
|
|
|
11461
9202
|
};
|
|
11462
9203
|
const applyToolbarPos = (rect) => {
|
|
11463
9204
|
const ps = parentScrollRef.current;
|
|
11464
|
-
const
|
|
9205
|
+
const approxW = 330;
|
|
11465
9206
|
if (toolbarElRef.current) {
|
|
11466
|
-
const { top, left, transform } = calcToolbarPos(rect, ps,
|
|
9207
|
+
const { top, left, transform } = calcToolbarPos(rect, ps, approxW);
|
|
11467
9208
|
toolbarElRef.current.style.top = `${top}px`;
|
|
11468
9209
|
toolbarElRef.current.style.left = `${left}px`;
|
|
11469
9210
|
toolbarElRef.current.style.transform = transform;
|
|
11470
9211
|
}
|
|
11471
9212
|
if (glowElRef.current) {
|
|
11472
|
-
const GAP =
|
|
9213
|
+
const GAP = 6;
|
|
11473
9214
|
glowElRef.current.style.top = `${rect.top - GAP}px`;
|
|
11474
9215
|
glowElRef.current.style.left = `${rect.left - GAP}px`;
|
|
11475
9216
|
glowElRef.current.style.width = `${rect.width + GAP * 2}px`;
|
|
@@ -11557,11 +9298,6 @@ function OhhwellsBridge() {
|
|
|
11557
9298
|
return;
|
|
11558
9299
|
}
|
|
11559
9300
|
}
|
|
11560
|
-
const footerColumn = findHoveredNavOrFooterContainer(clientX, clientY);
|
|
11561
|
-
if (footerColumn?.hasAttribute("data-ohw-footer-col") || footerColumn?.hasAttribute("data-ohw-footer-column")) {
|
|
11562
|
-
selectFrameRef.current(footerColumn);
|
|
11563
|
-
return;
|
|
11564
|
-
}
|
|
11565
9301
|
deactivateRef.current();
|
|
11566
9302
|
};
|
|
11567
9303
|
window.addEventListener("message", handleSave);
|
|
@@ -11633,177 +9369,7 @@ function OhhwellsBridge() {
|
|
|
11633
9369
|
if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
|
|
11634
9370
|
};
|
|
11635
9371
|
}, [isEditMode, refreshStateRules]);
|
|
11636
|
-
|
|
11637
|
-
if (!isEditMode) return;
|
|
11638
|
-
const THRESHOLD = 10;
|
|
11639
|
-
const resolveWasSelected = (el) => {
|
|
11640
|
-
if (selectedElRef.current === el) return true;
|
|
11641
|
-
const activeAnchor = activeElRef.current ? getNavigationItemAnchor(activeElRef.current) : null;
|
|
11642
|
-
return activeAnchor === el;
|
|
11643
|
-
};
|
|
11644
|
-
const onPointerDown = (e) => {
|
|
11645
|
-
if (e.button !== 0) return;
|
|
11646
|
-
if (suppressNextClickRef.current && Date.now() >= suppressClickUntilRef.current && !footerDragRef.current && !footerPointerDragRef.current?.started) {
|
|
11647
|
-
suppressNextClickRef.current = false;
|
|
11648
|
-
}
|
|
11649
|
-
if (footerDragRef.current) return;
|
|
11650
|
-
const target = e.target;
|
|
11651
|
-
if (!target) return;
|
|
11652
|
-
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]')) {
|
|
11653
|
-
return;
|
|
11654
|
-
}
|
|
11655
|
-
if (target.closest("[data-ohw-item-drag-surface]")) return;
|
|
11656
|
-
const anchor = getNavigationItemAnchor(target);
|
|
11657
|
-
const hrefKey = anchor?.getAttribute("data-ohw-href-key") ?? null;
|
|
11658
|
-
if (anchor && isFooterHrefKey(hrefKey)) {
|
|
11659
|
-
footerPointerDragRef.current = {
|
|
11660
|
-
el: anchor,
|
|
11661
|
-
kind: "link",
|
|
11662
|
-
startX: e.clientX,
|
|
11663
|
-
startY: e.clientY,
|
|
11664
|
-
pointerId: e.pointerId,
|
|
11665
|
-
wasSelected: resolveWasSelected(anchor),
|
|
11666
|
-
started: false
|
|
11667
|
-
};
|
|
11668
|
-
return;
|
|
11669
|
-
}
|
|
11670
|
-
const col = target.closest("[data-ohw-footer-col]");
|
|
11671
|
-
if (col && !getNavigationItemAnchor(target)) {
|
|
11672
|
-
footerPointerDragRef.current = {
|
|
11673
|
-
el: col,
|
|
11674
|
-
kind: "column",
|
|
11675
|
-
startX: e.clientX,
|
|
11676
|
-
startY: e.clientY,
|
|
11677
|
-
pointerId: e.pointerId,
|
|
11678
|
-
wasSelected: resolveWasSelected(col),
|
|
11679
|
-
started: false
|
|
11680
|
-
};
|
|
11681
|
-
}
|
|
11682
|
-
};
|
|
11683
|
-
const onPointerMove = (e) => {
|
|
11684
|
-
const pending = footerPointerDragRef.current;
|
|
11685
|
-
if (!pending) return;
|
|
11686
|
-
if (pending.started) {
|
|
11687
|
-
e.preventDefault();
|
|
11688
|
-
clearTextSelection();
|
|
11689
|
-
const session = footerDragRef.current;
|
|
11690
|
-
if (!session) return;
|
|
11691
|
-
const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, session.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
|
|
11692
|
-
refreshFooterDragVisualsRef.current(session, slot, e.clientX, e.clientY);
|
|
11693
|
-
return;
|
|
11694
|
-
}
|
|
11695
|
-
const dx = e.clientX - pending.startX;
|
|
11696
|
-
const dy = e.clientY - pending.startY;
|
|
11697
|
-
if (dx * dx + dy * dy < THRESHOLD * THRESHOLD) return;
|
|
11698
|
-
e.preventDefault();
|
|
11699
|
-
pending.started = true;
|
|
11700
|
-
armFooterPressDrag();
|
|
11701
|
-
clearTextSelection();
|
|
11702
|
-
try {
|
|
11703
|
-
document.body.setPointerCapture(pending.pointerId);
|
|
11704
|
-
} catch {
|
|
11705
|
-
}
|
|
11706
|
-
if (linkPopoverOpenRef.current) {
|
|
11707
|
-
setLinkPopoverRef.current(null);
|
|
11708
|
-
}
|
|
11709
|
-
if (activeElRef.current) {
|
|
11710
|
-
deactivateRef.current();
|
|
11711
|
-
}
|
|
11712
|
-
if (pending.kind === "link") {
|
|
11713
|
-
const key = pending.el.getAttribute("data-ohw-href-key");
|
|
11714
|
-
if (!key) return;
|
|
11715
|
-
const column = findFooterColumnForLink(pending.el);
|
|
11716
|
-
const columns2 = listFooterColumns();
|
|
11717
|
-
beginFooterDragRef.current({
|
|
11718
|
-
kind: "link",
|
|
11719
|
-
hrefKey: key,
|
|
11720
|
-
columnEl: column,
|
|
11721
|
-
sourceColumnIndex: column ? columns2.indexOf(column) : 0,
|
|
11722
|
-
wasSelected: pending.wasSelected,
|
|
11723
|
-
draggedEl: pending.el,
|
|
11724
|
-
lastClientX: e.clientX,
|
|
11725
|
-
lastClientY: e.clientY,
|
|
11726
|
-
activeSlot: null
|
|
11727
|
-
});
|
|
11728
|
-
return;
|
|
11729
|
-
}
|
|
11730
|
-
const columns = listFooterColumns();
|
|
11731
|
-
const idx = columns.indexOf(pending.el);
|
|
11732
|
-
if (idx < 0) return;
|
|
11733
|
-
beginFooterDragRef.current({
|
|
11734
|
-
kind: "column",
|
|
11735
|
-
hrefKey: null,
|
|
11736
|
-
columnEl: pending.el,
|
|
11737
|
-
sourceColumnIndex: idx,
|
|
11738
|
-
wasSelected: pending.wasSelected,
|
|
11739
|
-
draggedEl: pending.el,
|
|
11740
|
-
lastClientX: e.clientX,
|
|
11741
|
-
lastClientY: e.clientY,
|
|
11742
|
-
activeSlot: null
|
|
11743
|
-
});
|
|
11744
|
-
};
|
|
11745
|
-
const endPointerDrag = (e) => {
|
|
11746
|
-
const pending = footerPointerDragRef.current;
|
|
11747
|
-
footerPointerDragRef.current = null;
|
|
11748
|
-
try {
|
|
11749
|
-
if (document.body.hasPointerCapture(e.pointerId)) {
|
|
11750
|
-
document.body.releasePointerCapture(e.pointerId);
|
|
11751
|
-
}
|
|
11752
|
-
} catch {
|
|
11753
|
-
}
|
|
11754
|
-
if (!pending) return;
|
|
11755
|
-
if (!pending.started) {
|
|
11756
|
-
unlockFooterDragInteraction();
|
|
11757
|
-
return;
|
|
11758
|
-
}
|
|
11759
|
-
suppressNextClickRef.current = true;
|
|
11760
|
-
suppressClickUntilRef.current = Date.now() + 500;
|
|
11761
|
-
commitFooterDragRef.current(e.clientX, e.clientY);
|
|
11762
|
-
};
|
|
11763
|
-
const blockSelectStart = (e) => {
|
|
11764
|
-
if (footerDragRef.current || footerPointerDragRef.current?.started || document.documentElement.hasAttribute("data-ohw-footer-press-drag")) {
|
|
11765
|
-
e.preventDefault();
|
|
11766
|
-
}
|
|
11767
|
-
};
|
|
11768
|
-
const onDragEnd = (_e) => {
|
|
11769
|
-
if (!footerDragRef.current) return;
|
|
11770
|
-
suppressNextClickRef.current = true;
|
|
11771
|
-
suppressClickUntilRef.current = Date.now() + 500;
|
|
11772
|
-
commitFooterDragRef.current();
|
|
11773
|
-
};
|
|
11774
|
-
document.addEventListener("pointerdown", onPointerDown, true);
|
|
11775
|
-
document.addEventListener("pointermove", onPointerMove, true);
|
|
11776
|
-
document.addEventListener("pointerup", endPointerDrag, true);
|
|
11777
|
-
document.addEventListener("pointercancel", endPointerDrag, true);
|
|
11778
|
-
document.addEventListener("selectstart", blockSelectStart, true);
|
|
11779
|
-
document.addEventListener("dragend", onDragEnd, true);
|
|
11780
|
-
return () => {
|
|
11781
|
-
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
11782
|
-
document.removeEventListener("pointermove", onPointerMove, true);
|
|
11783
|
-
document.removeEventListener("pointerup", endPointerDrag, true);
|
|
11784
|
-
document.removeEventListener("pointercancel", endPointerDrag, true);
|
|
11785
|
-
document.removeEventListener("selectstart", blockSelectStart, true);
|
|
11786
|
-
document.removeEventListener("dragend", onDragEnd, true);
|
|
11787
|
-
unlockFooterDragInteraction();
|
|
11788
|
-
};
|
|
11789
|
-
}, [isEditMode]);
|
|
11790
|
-
useEffect8(() => {
|
|
11791
|
-
if (!isEditMode) return;
|
|
11792
|
-
const debugSelectionChange = () => {
|
|
11793
|
-
const sel = window.getSelection();
|
|
11794
|
-
console.log(
|
|
11795
|
-
"[OHW DEBUG selectionchange]",
|
|
11796
|
-
JSON.stringify(sel?.toString() ?? ""),
|
|
11797
|
-
"collapsed=",
|
|
11798
|
-
sel?.isCollapsed,
|
|
11799
|
-
"anchorNode=",
|
|
11800
|
-
sel?.anchorNode,
|
|
11801
|
-
"activeEl=",
|
|
11802
|
-
activeElRef.current
|
|
11803
|
-
);
|
|
11804
|
-
};
|
|
11805
|
-
}, [isEditMode]);
|
|
11806
|
-
useEffect8(() => {
|
|
9372
|
+
useEffect7(() => {
|
|
11807
9373
|
const handler = (e) => {
|
|
11808
9374
|
if (e.data?.type !== "ow:request-schedule-config") return;
|
|
11809
9375
|
const insertAfterVal = e.data.insertAfter;
|
|
@@ -11819,7 +9385,7 @@ function OhhwellsBridge() {
|
|
|
11819
9385
|
window.addEventListener("message", handler);
|
|
11820
9386
|
return () => window.removeEventListener("message", handler);
|
|
11821
9387
|
}, [processConfigRequest]);
|
|
11822
|
-
|
|
9388
|
+
useEffect7(() => {
|
|
11823
9389
|
if (!isEditMode) return;
|
|
11824
9390
|
document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
|
|
11825
9391
|
el.removeAttribute("data-ohw-active-state");
|
|
@@ -11840,13 +9406,7 @@ function OhhwellsBridge() {
|
|
|
11840
9406
|
const next = { ...prev, [pathKey]: sections };
|
|
11841
9407
|
return shouldUseDevFixtures() ? { ...DEV_SECTIONS_BY_PATH, ...next } : next;
|
|
11842
9408
|
});
|
|
11843
|
-
postToParent2({
|
|
11844
|
-
type: "ow:ready",
|
|
11845
|
-
version: "1",
|
|
11846
|
-
path: pathname,
|
|
11847
|
-
nodes: collectEditableNodes(editContentRef.current),
|
|
11848
|
-
sections
|
|
11849
|
-
});
|
|
9409
|
+
postToParent2({ type: "ow:ready", version: "1", path: pathname, nodes: collectEditableNodes(), sections });
|
|
11850
9410
|
postToParent2({ type: "ow:request-site-pages" });
|
|
11851
9411
|
}, 150);
|
|
11852
9412
|
return () => {
|
|
@@ -11854,20 +9414,19 @@ function OhhwellsBridge() {
|
|
|
11854
9414
|
clearTimeout(timer);
|
|
11855
9415
|
};
|
|
11856
9416
|
}, [pathname, isEditMode, refreshStateRules, postToParent2]);
|
|
11857
|
-
|
|
9417
|
+
useEffect7(() => {
|
|
11858
9418
|
scrollToHashSectionWhenReady();
|
|
11859
9419
|
const onHashChange = () => scrollToHashSectionWhenReady();
|
|
11860
9420
|
window.addEventListener("hashchange", onHashChange);
|
|
11861
9421
|
return () => window.removeEventListener("hashchange", onHashChange);
|
|
11862
9422
|
}, [pathname]);
|
|
11863
|
-
const handleCommand =
|
|
11864
|
-
document.execCommand("styleWithCSS", false, true);
|
|
9423
|
+
const handleCommand = useCallback3((cmd) => {
|
|
11865
9424
|
document.execCommand(cmd, false);
|
|
11866
9425
|
activeElRef.current?.focus();
|
|
11867
9426
|
if (activeElRef.current) setToolbarRect(getEditMeasureEl(activeElRef.current).getBoundingClientRect());
|
|
11868
9427
|
refreshActiveCommandsRef.current();
|
|
11869
9428
|
}, []);
|
|
11870
|
-
const handleStateChange =
|
|
9429
|
+
const handleStateChange = useCallback3((state) => {
|
|
11871
9430
|
if (!activeStateElRef.current) return;
|
|
11872
9431
|
const el = activeStateElRef.current;
|
|
11873
9432
|
if (state === "Default") {
|
|
@@ -11880,11 +9439,11 @@ function OhhwellsBridge() {
|
|
|
11880
9439
|
}
|
|
11881
9440
|
setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
|
|
11882
9441
|
}, [deactivate]);
|
|
11883
|
-
const closeLinkPopover =
|
|
9442
|
+
const closeLinkPopover = useCallback3(() => {
|
|
11884
9443
|
addNavAfterAnchorRef.current = null;
|
|
11885
9444
|
setLinkPopover(null);
|
|
11886
9445
|
}, []);
|
|
11887
|
-
const openLinkPopoverForActive =
|
|
9446
|
+
const openLinkPopoverForActive = useCallback3(() => {
|
|
11888
9447
|
const hrefCtx = getHrefKeyFromElement(activeElRef.current);
|
|
11889
9448
|
if (!hrefCtx) return;
|
|
11890
9449
|
bumpLinkPopoverGrace();
|
|
@@ -11895,7 +9454,7 @@ function OhhwellsBridge() {
|
|
|
11895
9454
|
});
|
|
11896
9455
|
deactivate();
|
|
11897
9456
|
}, [deactivate]);
|
|
11898
|
-
const openLinkPopoverForSelected =
|
|
9457
|
+
const openLinkPopoverForSelected = useCallback3(() => {
|
|
11899
9458
|
const anchor = selectedElRef.current;
|
|
11900
9459
|
if (!anchor) return;
|
|
11901
9460
|
const key = anchor.getAttribute("data-ohw-href-key");
|
|
@@ -11908,7 +9467,7 @@ function OhhwellsBridge() {
|
|
|
11908
9467
|
});
|
|
11909
9468
|
deselect();
|
|
11910
9469
|
}, [deselect]);
|
|
11911
|
-
const handleLinkPopoverSubmit =
|
|
9470
|
+
const handleLinkPopoverSubmit = useCallback3(
|
|
11912
9471
|
(target) => {
|
|
11913
9472
|
const session = linkPopoverSessionRef.current;
|
|
11914
9473
|
if (!session) return;
|
|
@@ -11967,13 +9526,13 @@ function OhhwellsBridge() {
|
|
|
11967
9526
|
const showEditLink = toolbarShowEditLink;
|
|
11968
9527
|
const currentSections = sectionsByPath[pathname] ?? [];
|
|
11969
9528
|
linkPopoverOpenRef.current = linkPopover !== null;
|
|
11970
|
-
const handleMediaReplace =
|
|
9529
|
+
const handleMediaReplace = useCallback3(
|
|
11971
9530
|
(key) => {
|
|
11972
9531
|
postToParent2({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
|
|
11973
9532
|
},
|
|
11974
9533
|
[postToParent2, mediaHover?.elementType]
|
|
11975
9534
|
);
|
|
11976
|
-
const handleMediaFadeOutComplete =
|
|
9535
|
+
const handleMediaFadeOutComplete = useCallback3((key) => {
|
|
11977
9536
|
setUploadingRects((prev) => {
|
|
11978
9537
|
if (!(key in prev)) return prev;
|
|
11979
9538
|
const next = { ...prev };
|
|
@@ -11981,7 +9540,7 @@ function OhhwellsBridge() {
|
|
|
11981
9540
|
return next;
|
|
11982
9541
|
});
|
|
11983
9542
|
}, []);
|
|
11984
|
-
const handleVideoSettingsChange =
|
|
9543
|
+
const handleVideoSettingsChange = useCallback3(
|
|
11985
9544
|
(key, settings) => {
|
|
11986
9545
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
11987
9546
|
const video = getVideoEl(el);
|
|
@@ -12005,8 +9564,8 @@ function OhhwellsBridge() {
|
|
|
12005
9564
|
);
|
|
12006
9565
|
return bridgeRoot ? createPortal2(
|
|
12007
9566
|
/* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
12008
|
-
/* @__PURE__ */
|
|
12009
|
-
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */
|
|
9567
|
+
/* @__PURE__ */ jsx23("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
9568
|
+
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ jsx23(
|
|
12010
9569
|
MediaOverlay,
|
|
12011
9570
|
{
|
|
12012
9571
|
hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
|
|
@@ -12017,7 +9576,7 @@ function OhhwellsBridge() {
|
|
|
12017
9576
|
},
|
|
12018
9577
|
`uploading-${key}`
|
|
12019
9578
|
)),
|
|
12020
|
-
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */
|
|
9579
|
+
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ jsx23(
|
|
12021
9580
|
MediaOverlay,
|
|
12022
9581
|
{
|
|
12023
9582
|
hover: mediaHover,
|
|
@@ -12026,93 +9585,49 @@ function OhhwellsBridge() {
|
|
|
12026
9585
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
12027
9586
|
}
|
|
12028
9587
|
),
|
|
12029
|
-
siblingHintRect && !
|
|
12030
|
-
|
|
12031
|
-
|
|
12032
|
-
|
|
12033
|
-
"div",
|
|
12034
|
-
{
|
|
12035
|
-
className: "pointer-events-none fixed z-2147483646",
|
|
12036
|
-
style: {
|
|
12037
|
-
left: slot.left,
|
|
12038
|
-
top: slot.top,
|
|
12039
|
-
width: slot.width,
|
|
12040
|
-
height: slot.height
|
|
12041
|
-
},
|
|
12042
|
-
children: /* @__PURE__ */ jsx24(
|
|
12043
|
-
DropIndicator,
|
|
12044
|
-
{
|
|
12045
|
-
direction: slot.direction,
|
|
12046
|
-
state: activeFooterDropIndex === i ? "dragActive" : "dragIdle",
|
|
12047
|
-
className: "!h-full !w-full"
|
|
12048
|
-
}
|
|
12049
|
-
)
|
|
12050
|
-
},
|
|
12051
|
-
`footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
|
|
12052
|
-
)),
|
|
12053
|
-
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx24(
|
|
12054
|
-
"div",
|
|
9588
|
+
siblingHintRect && !isItemDragging && /* @__PURE__ */ jsx23(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
9589
|
+
hoveredNavContainerRect && toolbarVariant !== "select-frame" && !linkPopover && !isItemDragging && !siblingHintRect && /* @__PURE__ */ jsx23(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
|
|
9590
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx23(
|
|
9591
|
+
NavbarContainerChrome,
|
|
12055
9592
|
{
|
|
12056
|
-
|
|
12057
|
-
|
|
12058
|
-
|
|
12059
|
-
|
|
12060
|
-
|
|
12061
|
-
|
|
12062
|
-
},
|
|
12063
|
-
children: /* @__PURE__ */ jsx24(
|
|
12064
|
-
DropIndicator,
|
|
12065
|
-
{
|
|
12066
|
-
direction: slot.direction,
|
|
12067
|
-
state: activeNavDropIndex === i ? "dragActive" : "dragIdle",
|
|
12068
|
-
className: "!h-full !w-full"
|
|
12069
|
-
}
|
|
12070
|
-
)
|
|
12071
|
-
},
|
|
12072
|
-
`nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
|
|
12073
|
-
)),
|
|
12074
|
-
hoveredNavContainerRect && toolbarVariant !== "select-frame" && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx24(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
|
|
12075
|
-
hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx24(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
12076
|
-
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx24(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
|
|
12077
|
-
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ jsx24(
|
|
9593
|
+
rect: toolbarRect,
|
|
9594
|
+
onAdd: handleAddTopLevelNavItem
|
|
9595
|
+
}
|
|
9596
|
+
),
|
|
9597
|
+
hoveredItemRect && !hoveredNavContainerRect && !siblingHintRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx23(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
9598
|
+
toolbarRect && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ jsx23(
|
|
12078
9599
|
ItemInteractionLayer,
|
|
12079
9600
|
{
|
|
12080
|
-
rect:
|
|
9601
|
+
rect: toolbarRect,
|
|
12081
9602
|
elRef: glowElRef,
|
|
12082
9603
|
state: isItemDragging ? "dragging" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
|
|
12083
|
-
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey)
|
|
9604
|
+
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey),
|
|
12084
9605
|
dragDisabled: reorderDragDisabled,
|
|
12085
9606
|
dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
|
|
12086
9607
|
onDragHandleDragStart: handleItemDragStart,
|
|
12087
9608
|
onDragHandleDragEnd: handleItemDragEnd,
|
|
12088
|
-
|
|
12089
|
-
onItemClick: handleItemChromeClick,
|
|
12090
|
-
itemDragSurface: !isFooterFrameSelection,
|
|
12091
|
-
toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ jsx24(
|
|
9609
|
+
toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ jsx23(
|
|
12092
9610
|
ItemActionToolbar,
|
|
12093
9611
|
{
|
|
12094
9612
|
onEditLink: openLinkPopoverForSelected,
|
|
12095
9613
|
addItemDisabled: true,
|
|
12096
9614
|
editLinkDisabled: false,
|
|
12097
|
-
moreDisabled: true
|
|
12098
|
-
showAddItem: !selectedIsCta,
|
|
12099
|
-
showMore: !selectedIsCta
|
|
9615
|
+
moreDisabled: true
|
|
12100
9616
|
}
|
|
12101
9617
|
) : void 0
|
|
12102
9618
|
}
|
|
12103
9619
|
),
|
|
12104
|
-
toolbarRect && toolbarVariant === "rich-text" &&
|
|
12105
|
-
/* @__PURE__ */
|
|
9620
|
+
toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ jsxs13(Fragment5, { children: [
|
|
9621
|
+
/* @__PURE__ */ jsx23(
|
|
12106
9622
|
EditGlowChrome,
|
|
12107
9623
|
{
|
|
12108
9624
|
rect: toolbarRect,
|
|
12109
9625
|
elRef: glowElRef,
|
|
12110
9626
|
reorderHrefKey,
|
|
12111
|
-
dragDisabled: reorderDragDisabled
|
|
12112
|
-
hideHandle: isItemDragging
|
|
9627
|
+
dragDisabled: reorderDragDisabled
|
|
12113
9628
|
}
|
|
12114
9629
|
),
|
|
12115
|
-
/* @__PURE__ */
|
|
9630
|
+
/* @__PURE__ */ jsx23(
|
|
12116
9631
|
FloatingToolbar,
|
|
12117
9632
|
{
|
|
12118
9633
|
rect: toolbarRect,
|
|
@@ -12151,7 +9666,7 @@ function OhhwellsBridge() {
|
|
|
12151
9666
|
]
|
|
12152
9667
|
}
|
|
12153
9668
|
),
|
|
12154
|
-
toggleState && !linkPopover && /* @__PURE__ */
|
|
9669
|
+
toggleState && !linkPopover && /* @__PURE__ */ jsx23(
|
|
12155
9670
|
StateToggle,
|
|
12156
9671
|
{
|
|
12157
9672
|
rect: toggleState.rect,
|
|
@@ -12167,29 +9682,25 @@ function OhhwellsBridge() {
|
|
|
12167
9682
|
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
12168
9683
|
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
12169
9684
|
children: [
|
|
12170
|
-
/* @__PURE__ */
|
|
12171
|
-
/* @__PURE__ */
|
|
9685
|
+
/* @__PURE__ */ jsx23("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
9686
|
+
/* @__PURE__ */ jsx23(
|
|
12172
9687
|
Badge,
|
|
12173
9688
|
{
|
|
12174
9689
|
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",
|
|
12175
9690
|
onClick: () => {
|
|
12176
9691
|
window.parent.postMessage(
|
|
12177
|
-
{
|
|
12178
|
-
type: "ow:add-section",
|
|
12179
|
-
insertAfter: sectionGap.insertAfter,
|
|
12180
|
-
insertBefore: sectionGap.insertBefore
|
|
12181
|
-
},
|
|
9692
|
+
{ type: "ow:add-section", insertAfter: sectionGap.insertAfter, insertBefore: sectionGap.insertBefore },
|
|
12182
9693
|
"*"
|
|
12183
9694
|
);
|
|
12184
9695
|
},
|
|
12185
9696
|
children: "Add Section"
|
|
12186
9697
|
}
|
|
12187
9698
|
),
|
|
12188
|
-
/* @__PURE__ */
|
|
9699
|
+
/* @__PURE__ */ jsx23("div", { className: "flex-1 bg-primary", style: { height: 3 } })
|
|
12189
9700
|
]
|
|
12190
9701
|
}
|
|
12191
9702
|
),
|
|
12192
|
-
linkPopover && dialogPortalContainer ? /* @__PURE__ */
|
|
9703
|
+
linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx23(
|
|
12193
9704
|
LinkPopover,
|
|
12194
9705
|
{
|
|
12195
9706
|
panelRef: linkPopoverPanelRef,
|
|
@@ -12210,6 +9721,48 @@ function OhhwellsBridge() {
|
|
|
12210
9721
|
bridgeRoot
|
|
12211
9722
|
) : null;
|
|
12212
9723
|
}
|
|
9724
|
+
|
|
9725
|
+
// src/ui/drop-indicator.tsx
|
|
9726
|
+
import * as React10 from "react";
|
|
9727
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
9728
|
+
var dropIndicatorVariants = cva(
|
|
9729
|
+
"ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
|
|
9730
|
+
{
|
|
9731
|
+
variants: {
|
|
9732
|
+
direction: {
|
|
9733
|
+
vertical: "h-6 w-[3px]",
|
|
9734
|
+
horizontal: "h-[3px] w-[200px]"
|
|
9735
|
+
},
|
|
9736
|
+
state: {
|
|
9737
|
+
default: "opacity-0",
|
|
9738
|
+
hover: "opacity-100",
|
|
9739
|
+
dragIdle: "opacity-40",
|
|
9740
|
+
dragActive: "opacity-100"
|
|
9741
|
+
}
|
|
9742
|
+
},
|
|
9743
|
+
defaultVariants: {
|
|
9744
|
+
direction: "vertical",
|
|
9745
|
+
state: "default"
|
|
9746
|
+
}
|
|
9747
|
+
}
|
|
9748
|
+
);
|
|
9749
|
+
var DropIndicator = React10.forwardRef(
|
|
9750
|
+
({ className, direction, state, ...props }, ref) => {
|
|
9751
|
+
return /* @__PURE__ */ jsx24(
|
|
9752
|
+
"div",
|
|
9753
|
+
{
|
|
9754
|
+
ref,
|
|
9755
|
+
"data-slot": "drop-indicator",
|
|
9756
|
+
"data-direction": direction ?? "vertical",
|
|
9757
|
+
"data-state": state ?? "default",
|
|
9758
|
+
"aria-hidden": "true",
|
|
9759
|
+
className: cn(dropIndicatorVariants({ direction, state }), className),
|
|
9760
|
+
...props
|
|
9761
|
+
}
|
|
9762
|
+
);
|
|
9763
|
+
}
|
|
9764
|
+
);
|
|
9765
|
+
DropIndicator.displayName = "DropIndicator";
|
|
12213
9766
|
export {
|
|
12214
9767
|
CustomToolbar,
|
|
12215
9768
|
CustomToolbarButton,
|