@ohhwells/bridge 0.1.44 → 0.1.46-next.109
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 +12 -0
- package/dist/index.cjs +3007 -492
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -3
- package/dist/index.d.ts +12 -3
- package/dist/index.js +3046 -531
- package/dist/index.js.map +1 -1
- package/dist/styles.css +131 -34
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -62,7 +62,7 @@ __export(index_exports, {
|
|
|
62
62
|
module.exports = __toCommonJS(index_exports);
|
|
63
63
|
|
|
64
64
|
// src/OhhwellsBridge.tsx
|
|
65
|
-
var
|
|
65
|
+
var import_react9 = __toESM(require("react"), 1);
|
|
66
66
|
var import_client = require("react-dom/client");
|
|
67
67
|
var import_react_dom2 = require("react-dom");
|
|
68
68
|
|
|
@@ -115,6 +115,7 @@ var import_react3 = require("react");
|
|
|
115
115
|
var import_react2 = require("react");
|
|
116
116
|
var import_radix_ui = require("radix-ui");
|
|
117
117
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
118
|
+
var isValidEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
|
|
118
119
|
function Spinner() {
|
|
119
120
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
120
121
|
"svg",
|
|
@@ -148,12 +149,17 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
|
|
|
148
149
|
const [error, setError] = (0, import_react2.useState)(null);
|
|
149
150
|
const isBook = title === "Confirm your spot";
|
|
150
151
|
const handleSubmit = async () => {
|
|
151
|
-
|
|
152
|
+
const trimmed = email.trim();
|
|
153
|
+
if (!trimmed) return;
|
|
154
|
+
if (!isValidEmail(trimmed)) {
|
|
155
|
+
setError("Please enter a valid email address.");
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
152
158
|
setLoading(true);
|
|
153
159
|
setError(null);
|
|
154
160
|
try {
|
|
155
|
-
await onSubmit(
|
|
156
|
-
setSubmittedEmail(
|
|
161
|
+
await onSubmit(trimmed);
|
|
162
|
+
setSubmittedEmail(trimmed);
|
|
157
163
|
setSuccess(true);
|
|
158
164
|
} catch (e) {
|
|
159
165
|
setError(e instanceof Error ? e.message : "Something went wrong. Please try again.");
|
|
@@ -228,7 +234,10 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
|
|
|
228
234
|
{
|
|
229
235
|
type: "email",
|
|
230
236
|
value: email,
|
|
231
|
-
onChange: (e) =>
|
|
237
|
+
onChange: (e) => {
|
|
238
|
+
setEmail(e.target.value);
|
|
239
|
+
if (error) setError(null);
|
|
240
|
+
},
|
|
232
241
|
onKeyDown: handleKeyDown,
|
|
233
242
|
placeholder: "hello@gmail.com",
|
|
234
243
|
autoFocus: true,
|
|
@@ -285,12 +294,20 @@ function formatClassTime(cls) {
|
|
|
285
294
|
const em = endTotal % 60;
|
|
286
295
|
return `${h}:${cls.startTime.minutes}-${eh}:${String(em).padStart(2, "0")}`;
|
|
287
296
|
}
|
|
297
|
+
function formatBookingLabel(cls) {
|
|
298
|
+
const price = cls.price;
|
|
299
|
+
const isFree = price === null || price === void 0 || `${price}` === "" || `${price}` === "0";
|
|
300
|
+
return isFree ? "Book for free" : `Book for ${cls.currency ?? ""} ${price}`.trim();
|
|
301
|
+
}
|
|
288
302
|
function getBookingsOnDate(cls, date) {
|
|
289
303
|
if (!cls.bookings?.length) return 0;
|
|
290
|
-
const
|
|
304
|
+
const target = new Date(date);
|
|
305
|
+
target.setHours(0, 0, 0, 0);
|
|
291
306
|
return cls.bookings.filter((b) => {
|
|
292
307
|
try {
|
|
293
|
-
|
|
308
|
+
const bookingDate = new Date(b.classDate);
|
|
309
|
+
bookingDate.setHours(0, 0, 0, 0);
|
|
310
|
+
return bookingDate.getTime() === target.getTime();
|
|
294
311
|
} catch {
|
|
295
312
|
return false;
|
|
296
313
|
}
|
|
@@ -555,7 +572,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
|
|
|
555
572
|
}
|
|
556
573
|
)
|
|
557
574
|
] }),
|
|
558
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "sm:hidden flex flex-col gap-px", children: isFull ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
575
|
+
cls.showAvailability !== false && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "sm:hidden flex flex-col gap-px", children: isFull ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
559
576
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
|
|
560
577
|
available,
|
|
561
578
|
"/",
|
|
@@ -567,9 +584,17 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
|
|
|
567
584
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-1 flex-col gap-2 min-w-0 sm:contents", children: [
|
|
568
585
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex-1 flex flex-col gap-2 min-w-0", children: [
|
|
569
586
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-base font-bold text-(--color-dark,#200C02) block truncate", children: cls.name }),
|
|
570
|
-
cls.hostName && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block truncate", children: cls.hostName })
|
|
587
|
+
cls.hostName && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block truncate", children: cls.hostName }),
|
|
588
|
+
cls.description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
589
|
+
"span",
|
|
590
|
+
{
|
|
591
|
+
className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block",
|
|
592
|
+
style: { wordBreak: "break-word" },
|
|
593
|
+
children: cls.description
|
|
594
|
+
}
|
|
595
|
+
)
|
|
571
596
|
] }),
|
|
572
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "hidden sm:flex w-14 shrink-0 flex-col gap-px", children: isFull ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
597
|
+
cls.showAvailability !== false && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "hidden sm:flex w-14 shrink-0 flex-col gap-px", children: isFull ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
573
598
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
|
|
574
599
|
available,
|
|
575
600
|
"/",
|
|
@@ -594,7 +619,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
|
|
|
594
619
|
if (!cls.id) return;
|
|
595
620
|
onOpenModal?.(isFull ? "waitlist" : "book", cls.id, selectedDate);
|
|
596
621
|
},
|
|
597
|
-
children: isFull ? "Join Waitlist" :
|
|
622
|
+
children: isFull ? "Join Waitlist" : formatBookingLabel(cls)
|
|
598
623
|
}
|
|
599
624
|
)
|
|
600
625
|
] })
|
|
@@ -636,6 +661,17 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
636
661
|
const [isHovered, setIsHovered] = (0, import_react3.useState)(false);
|
|
637
662
|
const [modalState, setModalState] = (0, import_react3.useState)(null);
|
|
638
663
|
const switchScheduleIdRef = (0, import_react3.useRef)(null);
|
|
664
|
+
const liveScheduleIdRef = (0, import_react3.useRef)(null);
|
|
665
|
+
const refetchLiveSchedule = (0, import_react3.useCallback)(async () => {
|
|
666
|
+
const id = liveScheduleIdRef.current;
|
|
667
|
+
if (!id) return;
|
|
668
|
+
try {
|
|
669
|
+
const res = await fetch(`${API_URL}/api/schedule/id/${id}`);
|
|
670
|
+
const data = await res.json();
|
|
671
|
+
if (data?.id) setSchedule(data);
|
|
672
|
+
} catch {
|
|
673
|
+
}
|
|
674
|
+
}, []);
|
|
639
675
|
const dates = (0, import_react3.useMemo)(() => {
|
|
640
676
|
const today = /* @__PURE__ */ new Date();
|
|
641
677
|
today.setHours(0, 0, 0, 0);
|
|
@@ -655,6 +691,18 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
655
691
|
}
|
|
656
692
|
}
|
|
657
693
|
}, [schedule, dates]);
|
|
694
|
+
(0, import_react3.useEffect)(() => {
|
|
695
|
+
if (typeof window === "undefined") return;
|
|
696
|
+
const onVisible = () => {
|
|
697
|
+
if (!document.hidden) void refetchLiveSchedule();
|
|
698
|
+
};
|
|
699
|
+
window.addEventListener("focus", refetchLiveSchedule);
|
|
700
|
+
document.addEventListener("visibilitychange", onVisible);
|
|
701
|
+
return () => {
|
|
702
|
+
window.removeEventListener("focus", refetchLiveSchedule);
|
|
703
|
+
document.removeEventListener("visibilitychange", onVisible);
|
|
704
|
+
};
|
|
705
|
+
}, [refetchLiveSchedule]);
|
|
658
706
|
(0, import_react3.useEffect)(() => {
|
|
659
707
|
if (typeof window === "undefined") return;
|
|
660
708
|
const isInEditor = window.self !== window.top;
|
|
@@ -716,7 +764,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
716
764
|
setLoading(false);
|
|
717
765
|
return;
|
|
718
766
|
}
|
|
719
|
-
;
|
|
767
|
+
liveScheduleIdRef.current = effectiveId;
|
|
720
768
|
(async () => {
|
|
721
769
|
try {
|
|
722
770
|
const res = await fetch(`${API_URL}/api/schedule/id/${effectiveId}`);
|
|
@@ -773,18 +821,14 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
773
821
|
const data = await res.json().catch(() => ({}));
|
|
774
822
|
throw new Error(data?.message ?? "Something went wrong. Please try again.");
|
|
775
823
|
}
|
|
824
|
+
await refetchLiveSchedule();
|
|
776
825
|
};
|
|
777
826
|
const handleReplaceSchedule = () => {
|
|
778
827
|
setIsHovered(false);
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
insertAfter
|
|
784
|
-
}, "*");
|
|
785
|
-
} else {
|
|
786
|
-
window.parent.postMessage({ type: "ow:scheduling-not-connected", insertAfter }, "*");
|
|
787
|
-
}
|
|
828
|
+
window.parent.postMessage(
|
|
829
|
+
{ type: "ow:scheduling-not-connected", insertAfter, currentScheduleId: schedule?.id },
|
|
830
|
+
"*"
|
|
831
|
+
);
|
|
788
832
|
};
|
|
789
833
|
if (!inEditor && !loading && !schedule) return null;
|
|
790
834
|
const sectionId = `scheduling-${insertAfter}`;
|
|
@@ -827,7 +871,19 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
827
871
|
),
|
|
828
872
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "max-w-[1280px] mx-auto flex flex-col items-center gap-16", children: [
|
|
829
873
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-col items-center gap-4", children: [
|
|
830
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
874
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
875
|
+
"h2",
|
|
876
|
+
{
|
|
877
|
+
className: "font-display text-center m-0 text-(--color-dark,#200C02)",
|
|
878
|
+
style: {
|
|
879
|
+
fontSize: "var(--fs-section-h2, clamp(40px, 4.4vw, 64px))",
|
|
880
|
+
fontWeight: "var(--font-weight-heading, 400)",
|
|
881
|
+
lineHeight: 1.05,
|
|
882
|
+
letterSpacing: "-0.02em"
|
|
883
|
+
},
|
|
884
|
+
children: schedule?.name ?? "Book an appointment"
|
|
885
|
+
}
|
|
886
|
+
),
|
|
831
887
|
schedule?.description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "font-body text-body text-center m-0 text-(--color-accent,#A89B83)", children: schedule.description })
|
|
832
888
|
] }),
|
|
833
889
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "w-full flex flex-col items-end gap-3", children: [
|
|
@@ -4360,33 +4416,39 @@ function Tooltip({ ...props }) {
|
|
|
4360
4416
|
function TooltipTrigger({ ...props }) {
|
|
4361
4417
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui3.Tooltip.Trigger, { "data-slot": "tooltip-trigger", ...props });
|
|
4362
4418
|
}
|
|
4419
|
+
var arrowClassBySide = {
|
|
4420
|
+
top: "before:bottom-0 before:left-1/2 before:-translate-x-1/2 before:translate-y-1/2",
|
|
4421
|
+
bottom: "before:top-0 before:left-1/2 before:-translate-x-1/2 before:-translate-y-1/2",
|
|
4422
|
+
left: "before:right-0 before:top-1/2 before:-translate-y-1/2 before:translate-x-1/2",
|
|
4423
|
+
right: "before:left-0 before:top-1/2 before:-translate-y-1/2 before:-translate-x-1/2"
|
|
4424
|
+
};
|
|
4363
4425
|
function TooltipContent({
|
|
4364
4426
|
className,
|
|
4365
|
-
sideOffset =
|
|
4427
|
+
sideOffset = 9,
|
|
4366
4428
|
side = "bottom",
|
|
4367
4429
|
children,
|
|
4368
4430
|
hideArrow,
|
|
4369
4431
|
...props
|
|
4370
4432
|
}) {
|
|
4371
|
-
|
|
4433
|
+
const resolvedSide = side ?? "bottom";
|
|
4434
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui3.Tooltip.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
4372
4435
|
import_radix_ui3.Tooltip.Content,
|
|
4373
4436
|
{
|
|
4374
4437
|
"data-slot": "tooltip-content",
|
|
4375
4438
|
side,
|
|
4376
4439
|
sideOffset,
|
|
4377
4440
|
className: cn(
|
|
4378
|
-
"z-[2147483647] inline-flex w-fit max-w-xs items-center rounded-md bg-foreground px-3 py-1.5 text-xs text-background",
|
|
4441
|
+
"relative z-[2147483647] inline-flex w-fit max-w-xs items-center rounded-md bg-foreground px-3 py-1.5 text-xs text-background",
|
|
4379
4442
|
"origin-[var(--radix-tooltip-content-transform-origin)] animate-in fade-in-0 zoom-in-95",
|
|
4380
4443
|
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
|
|
4381
4444
|
"data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2",
|
|
4382
4445
|
"data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2",
|
|
4446
|
+
!hideArrow && 'before:pointer-events-none before:absolute before:size-2 before:rotate-45 before:bg-foreground before:content-[""]',
|
|
4447
|
+
!hideArrow && arrowClassBySide[resolvedSide],
|
|
4383
4448
|
className
|
|
4384
4449
|
),
|
|
4385
4450
|
...props,
|
|
4386
|
-
children
|
|
4387
|
-
children,
|
|
4388
|
-
!hideArrow && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui3.Tooltip.Arrow, { className: "z-[2147483647] size-2.5 translate-y-[calc(-50%-2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground" })
|
|
4389
|
-
]
|
|
4451
|
+
children
|
|
4390
4452
|
}
|
|
4391
4453
|
) });
|
|
4392
4454
|
}
|
|
@@ -4403,7 +4465,7 @@ function ToolbarActionTooltip({
|
|
|
4403
4465
|
const button = /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CustomToolbarButton, { type: "button", "aria-label": label, disabled, ...buttonProps, children });
|
|
4404
4466
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Tooltip, { children: [
|
|
4405
4467
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "inline-flex", children: button }) : button }),
|
|
4406
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TooltipContent, { side, sideOffset:
|
|
4468
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TooltipContent, { side, sideOffset: 9, children: label })
|
|
4407
4469
|
] });
|
|
4408
4470
|
}
|
|
4409
4471
|
function ItemActionToolbar({
|
|
@@ -4485,6 +4547,19 @@ var DRAG_SHADOW = "0px 4px 6px -1px rgba(0, 0, 0, 0.1), 0px 2px 4px -2px rgba(0,
|
|
|
4485
4547
|
var TOOLBAR_EDGE_MARGIN = 4;
|
|
4486
4548
|
var SELECTION_CHROME_GAP = 4;
|
|
4487
4549
|
var TOOLBAR_STROKE_GAP = 4;
|
|
4550
|
+
function getChromeZIndex(state) {
|
|
4551
|
+
switch (state) {
|
|
4552
|
+
case "active-top":
|
|
4553
|
+
case "active-bottom":
|
|
4554
|
+
case "dragging":
|
|
4555
|
+
return 2147483644;
|
|
4556
|
+
case "hover":
|
|
4557
|
+
case "sibling-hint":
|
|
4558
|
+
return 2147483643;
|
|
4559
|
+
default:
|
|
4560
|
+
return 2147483642;
|
|
4561
|
+
}
|
|
4562
|
+
}
|
|
4488
4563
|
function getChromeStyle(state) {
|
|
4489
4564
|
switch (state) {
|
|
4490
4565
|
case "hover":
|
|
@@ -4506,7 +4581,7 @@ function getChromeStyle(state) {
|
|
|
4506
4581
|
case "dragging":
|
|
4507
4582
|
return {
|
|
4508
4583
|
border: `2px solid ${PRIMARY}`,
|
|
4509
|
-
boxShadow: DRAG_SHADOW
|
|
4584
|
+
boxShadow: `${FOCUS_RING}, ${DRAG_SHADOW}`
|
|
4510
4585
|
};
|
|
4511
4586
|
default:
|
|
4512
4587
|
return {};
|
|
@@ -4575,6 +4650,9 @@ function ItemInteractionLayer({
|
|
|
4575
4650
|
dragHandleLabel = "Reorder item",
|
|
4576
4651
|
onDragHandleDragStart,
|
|
4577
4652
|
onDragHandleDragEnd,
|
|
4653
|
+
onItemPointerDown,
|
|
4654
|
+
onItemClick,
|
|
4655
|
+
itemDragSurface = true,
|
|
4578
4656
|
chromeGap = SELECTION_CHROME_GAP,
|
|
4579
4657
|
className
|
|
4580
4658
|
}) {
|
|
@@ -4582,7 +4660,8 @@ function ItemInteractionLayer({
|
|
|
4582
4660
|
const isActive = state === "active-top" || state === "active-bottom";
|
|
4583
4661
|
const isDragging = state === "dragging";
|
|
4584
4662
|
const showToolbar = isActive && toolbar;
|
|
4585
|
-
const showDragHandle = isActive
|
|
4663
|
+
const showDragHandle = (isActive || isDragging) && showHandle;
|
|
4664
|
+
const itemDragEnabled = itemDragSurface && isActive && showHandle && !isDragging && !dragDisabled;
|
|
4586
4665
|
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
4587
4666
|
"div",
|
|
4588
4667
|
{
|
|
@@ -4596,7 +4675,7 @@ function ItemInteractionLayer({
|
|
|
4596
4675
|
left: rect.left - chromeGap,
|
|
4597
4676
|
width: rect.width + chromeGap * 2,
|
|
4598
4677
|
height: rect.height + chromeGap * 2,
|
|
4599
|
-
zIndex:
|
|
4678
|
+
zIndex: getChromeZIndex(state)
|
|
4600
4679
|
},
|
|
4601
4680
|
children: [
|
|
4602
4681
|
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
@@ -4607,11 +4686,29 @@ function ItemInteractionLayer({
|
|
|
4607
4686
|
style: getChromeStyle(state)
|
|
4608
4687
|
}
|
|
4609
4688
|
),
|
|
4689
|
+
itemDragEnabled && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4690
|
+
"div",
|
|
4691
|
+
{
|
|
4692
|
+
"data-ohw-item-drag-surface": "",
|
|
4693
|
+
className: "pointer-events-auto absolute inset-0 cursor-text rounded-lg",
|
|
4694
|
+
onPointerDown: (e) => {
|
|
4695
|
+
if (e.button !== 0) return;
|
|
4696
|
+
onItemPointerDown?.(e);
|
|
4697
|
+
},
|
|
4698
|
+
onClick: (e) => {
|
|
4699
|
+
e.preventDefault();
|
|
4700
|
+
e.stopPropagation();
|
|
4701
|
+
onItemClick?.(e.clientX, e.clientY);
|
|
4702
|
+
}
|
|
4703
|
+
}
|
|
4704
|
+
),
|
|
4610
4705
|
showDragHandle && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4611
4706
|
"div",
|
|
4612
4707
|
{
|
|
4613
4708
|
"data-ohw-drag-handle-container": "",
|
|
4614
|
-
className: "pointer-events-auto absolute left-0 top-1/2 -translate-x-[calc(100%+7px)] -translate-y-1/2",
|
|
4709
|
+
className: "pointer-events-auto absolute left-0 top-1/2 z-10 -translate-x-[calc(100%+7px)] -translate-y-1/2",
|
|
4710
|
+
style: isDragging ? { opacity: 0 } : void 0,
|
|
4711
|
+
"aria-hidden": isDragging || void 0,
|
|
4615
4712
|
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
4616
4713
|
DragHandle,
|
|
4617
4714
|
{
|
|
@@ -4623,7 +4720,17 @@ function ItemInteractionLayer({
|
|
|
4623
4720
|
e.preventDefault();
|
|
4624
4721
|
return;
|
|
4625
4722
|
}
|
|
4626
|
-
|
|
4723
|
+
const blank = document.createElement("canvas");
|
|
4724
|
+
blank.width = 1;
|
|
4725
|
+
blank.height = 1;
|
|
4726
|
+
blank.style.cssText = "position:fixed;left:-9999px;top:-9999px;width:1px;height:1px;pointer-events:none";
|
|
4727
|
+
document.body.appendChild(blank);
|
|
4728
|
+
try {
|
|
4729
|
+
e.dataTransfer.setDragImage(blank, 0, 0);
|
|
4730
|
+
} finally {
|
|
4731
|
+
requestAnimationFrame(() => blank.remove());
|
|
4732
|
+
}
|
|
4733
|
+
e.dataTransfer.setData("text/plain", dragHandleLabel);
|
|
4627
4734
|
e.dataTransfer.effectAllowed = "move";
|
|
4628
4735
|
onDragHandleDragStart?.(e);
|
|
4629
4736
|
},
|
|
@@ -4836,7 +4943,11 @@ function MediaOverlay({
|
|
|
4836
4943
|
variant: "outline",
|
|
4837
4944
|
size: "sm",
|
|
4838
4945
|
className: "gap-1.5 cursor-pointer hover:bg-background",
|
|
4839
|
-
style:
|
|
4946
|
+
style: {
|
|
4947
|
+
...OVERLAY_BUTTON_STYLE,
|
|
4948
|
+
// Don't let Replace steal clicks when text (e.g. nav) sits on top of this media.
|
|
4949
|
+
pointerEvents: hover.hasTextOverlap ? "none" : "auto"
|
|
4950
|
+
},
|
|
4840
4951
|
onMouseDown: (e) => e.preventDefault(),
|
|
4841
4952
|
onClick: (e) => {
|
|
4842
4953
|
e.stopPropagation();
|
|
@@ -6319,9 +6430,155 @@ function shouldUseDevFixtures() {
|
|
|
6319
6430
|
return new URLSearchParams(q).get("ohw-fixtures") === "1";
|
|
6320
6431
|
}
|
|
6321
6432
|
|
|
6433
|
+
// src/lib/nav-tree.ts
|
|
6434
|
+
var MAX_LEVEL = { nav: 1 };
|
|
6435
|
+
var ROOT = null;
|
|
6436
|
+
function cloneForest(nodes) {
|
|
6437
|
+
return nodes.map((n) => ({ id: n.id, children: cloneForest(n.children) }));
|
|
6438
|
+
}
|
|
6439
|
+
function findNode(nodes, id, parentId = ROOT) {
|
|
6440
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
6441
|
+
const node = nodes[i];
|
|
6442
|
+
if (node.id === id) return { node, parentId, index: i, siblings: nodes };
|
|
6443
|
+
const nested = findNode(node.children, id, node.id);
|
|
6444
|
+
if (nested) return nested;
|
|
6445
|
+
}
|
|
6446
|
+
return null;
|
|
6447
|
+
}
|
|
6448
|
+
function getChildrenOf(nodes, parentId) {
|
|
6449
|
+
if (parentId === ROOT) return nodes;
|
|
6450
|
+
const found = findNode(nodes, parentId);
|
|
6451
|
+
return found ? found.node.children : null;
|
|
6452
|
+
}
|
|
6453
|
+
function isDescendant(nodes, ancestorId, maybeDescendantId) {
|
|
6454
|
+
const found = findNode(nodes, ancestorId);
|
|
6455
|
+
if (!found) return false;
|
|
6456
|
+
return findNode(found.node.children, maybeDescendantId) !== null;
|
|
6457
|
+
}
|
|
6458
|
+
function levelOf(nodes, id) {
|
|
6459
|
+
const loc = findNode(nodes, id);
|
|
6460
|
+
if (!loc) return -1;
|
|
6461
|
+
if (loc.parentId === ROOT) return 0;
|
|
6462
|
+
return 1 + Math.max(0, levelOf(nodes, loc.parentId));
|
|
6463
|
+
}
|
|
6464
|
+
function insertedLevel(nodes, parentId) {
|
|
6465
|
+
if (parentId === ROOT) return 0;
|
|
6466
|
+
const parentLevel = levelOf(nodes, parentId);
|
|
6467
|
+
if (parentLevel < 0) return -1;
|
|
6468
|
+
return parentLevel + 1;
|
|
6469
|
+
}
|
|
6470
|
+
function takeNode(nodes, id) {
|
|
6471
|
+
const forest = cloneForest(nodes);
|
|
6472
|
+
const loc = findNode(forest, id);
|
|
6473
|
+
if (!loc) return null;
|
|
6474
|
+
const [taken] = loc.siblings.splice(loc.index, 1);
|
|
6475
|
+
if (!taken) return null;
|
|
6476
|
+
return { forest, taken };
|
|
6477
|
+
}
|
|
6478
|
+
function insertInto(forest, node, parentId, index) {
|
|
6479
|
+
const siblings = getChildrenOf(forest, parentId);
|
|
6480
|
+
if (!siblings) return false;
|
|
6481
|
+
const clamped = Math.max(0, Math.min(index, siblings.length));
|
|
6482
|
+
siblings.splice(clamped, 0, node);
|
|
6483
|
+
return true;
|
|
6484
|
+
}
|
|
6485
|
+
function normalize(nodes) {
|
|
6486
|
+
const walk = (list) => list.map((n) => {
|
|
6487
|
+
const children = walk(n.children);
|
|
6488
|
+
return { id: n.id, children };
|
|
6489
|
+
});
|
|
6490
|
+
return walk(nodes);
|
|
6491
|
+
}
|
|
6492
|
+
function moveNode(model, draggedId, target) {
|
|
6493
|
+
const { parentId, index: targetIndex } = target;
|
|
6494
|
+
if (parentId === draggedId) return null;
|
|
6495
|
+
if (parentId !== ROOT && isDescendant(model, draggedId, parentId)) return null;
|
|
6496
|
+
const nextLevel = insertedLevel(model, parentId);
|
|
6497
|
+
if (nextLevel < 0 || nextLevel > MAX_LEVEL.nav) return null;
|
|
6498
|
+
const draggedLoc = findNode(model, draggedId);
|
|
6499
|
+
if (!draggedLoc) return null;
|
|
6500
|
+
if (parentId !== ROOT && draggedLoc.node.children.length > 0) return null;
|
|
6501
|
+
const taken = takeNode(model, draggedId);
|
|
6502
|
+
if (!taken) return null;
|
|
6503
|
+
let insertIndex = targetIndex;
|
|
6504
|
+
if (draggedLoc.parentId === parentId && draggedLoc.index < targetIndex) {
|
|
6505
|
+
insertIndex -= 1;
|
|
6506
|
+
}
|
|
6507
|
+
if (!insertInto(taken.forest, taken.taken, parentId, insertIndex)) return null;
|
|
6508
|
+
const next = normalize(taken.forest);
|
|
6509
|
+
if (forestsEqual(model, next)) return null;
|
|
6510
|
+
return next;
|
|
6511
|
+
}
|
|
6512
|
+
function forestsEqual(a, b) {
|
|
6513
|
+
if (a.length !== b.length) return false;
|
|
6514
|
+
for (let i = 0; i < a.length; i++) {
|
|
6515
|
+
const left = a[i];
|
|
6516
|
+
const right = b[i];
|
|
6517
|
+
if (left.id !== right.id) return false;
|
|
6518
|
+
if (!forestsEqual(left.children, right.children)) return false;
|
|
6519
|
+
}
|
|
6520
|
+
return true;
|
|
6521
|
+
}
|
|
6522
|
+
function forestFromFlatOrder(order) {
|
|
6523
|
+
return order.map((id) => ({ id, children: [] }));
|
|
6524
|
+
}
|
|
6525
|
+
function serializeNavOrder(nodes) {
|
|
6526
|
+
const hasNesting = nodes.some((n) => n.children.length > 0);
|
|
6527
|
+
if (!hasNesting) {
|
|
6528
|
+
return JSON.stringify(nodes.map((n) => n.id));
|
|
6529
|
+
}
|
|
6530
|
+
return JSON.stringify(nodes);
|
|
6531
|
+
}
|
|
6532
|
+
function parseNavOrderJson(raw) {
|
|
6533
|
+
if (!raw) return null;
|
|
6534
|
+
try {
|
|
6535
|
+
const parsed = JSON.parse(raw);
|
|
6536
|
+
if (!Array.isArray(parsed)) return null;
|
|
6537
|
+
if (parsed.every((x) => typeof x === "string")) {
|
|
6538
|
+
return forestFromFlatOrder(parsed.filter((x) => typeof x === "string" && x.length > 0));
|
|
6539
|
+
}
|
|
6540
|
+
return parseNavNodeList(parsed);
|
|
6541
|
+
} catch {
|
|
6542
|
+
return null;
|
|
6543
|
+
}
|
|
6544
|
+
}
|
|
6545
|
+
function parseNavNodeList(raw) {
|
|
6546
|
+
const out = [];
|
|
6547
|
+
for (const item of raw) {
|
|
6548
|
+
if (typeof item === "string" && item.length > 0) {
|
|
6549
|
+
out.push({ id: item, children: [] });
|
|
6550
|
+
continue;
|
|
6551
|
+
}
|
|
6552
|
+
if (!item || typeof item !== "object") return null;
|
|
6553
|
+
const rec = item;
|
|
6554
|
+
if (typeof rec.id !== "string" || !rec.id) return null;
|
|
6555
|
+
const children = Array.isArray(rec.children) ? parseNavNodeList(rec.children) : [];
|
|
6556
|
+
if (!children) return null;
|
|
6557
|
+
out.push({ id: rec.id, children });
|
|
6558
|
+
}
|
|
6559
|
+
return out;
|
|
6560
|
+
}
|
|
6561
|
+
function flattenNavOrder(nodes) {
|
|
6562
|
+
const out = [];
|
|
6563
|
+
const walk = (list) => {
|
|
6564
|
+
for (const n of list) {
|
|
6565
|
+
out.push(n.id);
|
|
6566
|
+
walk(n.children);
|
|
6567
|
+
}
|
|
6568
|
+
};
|
|
6569
|
+
walk(nodes);
|
|
6570
|
+
return out;
|
|
6571
|
+
}
|
|
6572
|
+
|
|
6322
6573
|
// src/lib/nav-items.ts
|
|
6323
6574
|
var NAV_COUNT_KEY = "__ohw_nav_count";
|
|
6324
6575
|
var NAV_ORDER_KEY = "__ohw_nav_order";
|
|
6576
|
+
var NAV_HREF_RE = /^nav-(\d+)-href$/;
|
|
6577
|
+
function isNavbarHrefKey(key) {
|
|
6578
|
+
if (!key) return false;
|
|
6579
|
+
if (key === "nav-book-href") return false;
|
|
6580
|
+
return NAV_HREF_RE.test(key);
|
|
6581
|
+
}
|
|
6325
6582
|
function getLinkHref(el) {
|
|
6326
6583
|
const key = el.getAttribute("data-ohw-href-key");
|
|
6327
6584
|
if (key) {
|
|
@@ -6358,7 +6615,7 @@ function listNavbarItems() {
|
|
|
6358
6615
|
}
|
|
6359
6616
|
function parseNavIndexFromKey(key) {
|
|
6360
6617
|
if (!key) return null;
|
|
6361
|
-
const match = key.match(
|
|
6618
|
+
const match = key.match(NAV_HREF_RE);
|
|
6362
6619
|
if (!match) return null;
|
|
6363
6620
|
return parseInt(match[1], 10);
|
|
6364
6621
|
}
|
|
@@ -6381,17 +6638,6 @@ function getNavbarExistingTargets() {
|
|
|
6381
6638
|
function getNavOrderFromDom() {
|
|
6382
6639
|
return listNavbarItems().map((el) => el.getAttribute("data-ohw-href-key")).filter((key) => Boolean(key));
|
|
6383
6640
|
}
|
|
6384
|
-
function parseNavOrder(content) {
|
|
6385
|
-
const raw = content[NAV_ORDER_KEY];
|
|
6386
|
-
if (!raw) return null;
|
|
6387
|
-
try {
|
|
6388
|
-
const parsed = JSON.parse(raw);
|
|
6389
|
-
if (!Array.isArray(parsed)) return null;
|
|
6390
|
-
return parsed.filter((key) => typeof key === "string" && key.length > 0);
|
|
6391
|
-
} catch {
|
|
6392
|
-
return null;
|
|
6393
|
-
}
|
|
6394
|
-
}
|
|
6395
6641
|
function findCounterpartByHrefKey(hrefKey, root) {
|
|
6396
6642
|
return root.querySelector(`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`);
|
|
6397
6643
|
}
|
|
@@ -6455,6 +6701,13 @@ function insertNavbarItemDom(index, href, label, afterAnchor) {
|
|
|
6455
6701
|
}
|
|
6456
6702
|
return primary;
|
|
6457
6703
|
}
|
|
6704
|
+
function navOrderKeysEqual(a, b) {
|
|
6705
|
+
if (a.length !== b.length) return false;
|
|
6706
|
+
for (let i = 0; i < a.length; i++) {
|
|
6707
|
+
if (a[i] !== b[i]) return false;
|
|
6708
|
+
}
|
|
6709
|
+
return true;
|
|
6710
|
+
}
|
|
6458
6711
|
function getNavbarLinkKeysInContainer(container) {
|
|
6459
6712
|
return Array.from(container.querySelectorAll("[data-ohw-href-key]")).filter(isNavbarLinkItem).map((el) => el.getAttribute("data-ohw-href-key")).filter((key) => Boolean(key));
|
|
6460
6713
|
}
|
|
@@ -6463,21 +6716,32 @@ function applyNavOrderToContainer(container, order) {
|
|
|
6463
6716
|
const current = getNavbarLinkKeysInContainer(container);
|
|
6464
6717
|
const extras = current.filter((key) => !desired.includes(key));
|
|
6465
6718
|
const expected = [...desired.filter((key) => current.includes(key)), ...extras];
|
|
6719
|
+
const orderedEls = [];
|
|
6720
|
+
if (navOrderKeysEqual(current, expected)) return;
|
|
6466
6721
|
if (current.length === expected.length && current.every((key, i) => key === expected[i])) {
|
|
6467
6722
|
return;
|
|
6468
6723
|
}
|
|
6724
|
+
const lastCurrentLinkEl = current.length > 0 ? findCounterpartByHrefKey(current[current.length - 1], container) : null;
|
|
6725
|
+
const anchor = lastCurrentLinkEl?.parentElement === container ? lastCurrentLinkEl.nextElementSibling : null;
|
|
6469
6726
|
const seen = /* @__PURE__ */ new Set();
|
|
6470
6727
|
for (const hrefKey of desired) {
|
|
6471
6728
|
if (seen.has(hrefKey)) continue;
|
|
6472
6729
|
seen.add(hrefKey);
|
|
6473
6730
|
const el = findCounterpartByHrefKey(hrefKey, container);
|
|
6474
|
-
if (el)
|
|
6731
|
+
if (el && isNavbarLinkItem(el)) orderedEls.push(el);
|
|
6475
6732
|
}
|
|
6476
6733
|
for (const el of container.querySelectorAll("[data-ohw-href-key]")) {
|
|
6477
6734
|
if (!isNavbarLinkItem(el)) continue;
|
|
6478
6735
|
const key = el.getAttribute("data-ohw-href-key");
|
|
6479
6736
|
if (!key || seen.has(key)) continue;
|
|
6480
|
-
|
|
6737
|
+
orderedEls.push(el);
|
|
6738
|
+
}
|
|
6739
|
+
for (const el of orderedEls) {
|
|
6740
|
+
if (anchor) {
|
|
6741
|
+
if (el.nextSibling !== anchor) container.insertBefore(el, anchor);
|
|
6742
|
+
} else if (container.lastElementChild !== el) {
|
|
6743
|
+
container.appendChild(el);
|
|
6744
|
+
}
|
|
6481
6745
|
}
|
|
6482
6746
|
}
|
|
6483
6747
|
function applyNavOrder(order) {
|
|
@@ -6486,6 +6750,75 @@ function applyNavOrder(order) {
|
|
|
6486
6750
|
const drawer = getNavbarDrawerContainer();
|
|
6487
6751
|
if (drawer) applyNavOrderToContainer(drawer, order);
|
|
6488
6752
|
}
|
|
6753
|
+
function applyChildrenOrder(parentHrefKey, childKeys, root) {
|
|
6754
|
+
const parent = findCounterpartByHrefKey(parentHrefKey, root);
|
|
6755
|
+
if (!parent) return;
|
|
6756
|
+
const group = parent.closest("[data-ohw-nav-group]");
|
|
6757
|
+
const childrenRoot = group?.querySelector(":scope > [data-ohw-nav-children]");
|
|
6758
|
+
if (!childrenRoot) return;
|
|
6759
|
+
const current = Array.from(childrenRoot.querySelectorAll(":scope > [data-ohw-href-key]")).map((el) => el.getAttribute("data-ohw-href-key")).filter((key) => Boolean(key));
|
|
6760
|
+
if (navOrderKeysEqual(current, childKeys)) return;
|
|
6761
|
+
for (const key of childKeys) {
|
|
6762
|
+
const el = findCounterpartByHrefKey(key, root);
|
|
6763
|
+
if (!el) continue;
|
|
6764
|
+
if (childrenRoot.lastElementChild !== el) {
|
|
6765
|
+
childrenRoot.appendChild(el);
|
|
6766
|
+
}
|
|
6767
|
+
}
|
|
6768
|
+
}
|
|
6769
|
+
function applyNavForest(forest) {
|
|
6770
|
+
if (forestsEqual(forest, getNavForestFromDom())) return;
|
|
6771
|
+
const rootKeys = forest.map((n) => n.id);
|
|
6772
|
+
applyNavOrder(rootKeys);
|
|
6773
|
+
const desktop = getNavbarDesktopContainer();
|
|
6774
|
+
const drawer = getNavbarDrawerContainer();
|
|
6775
|
+
for (const node of forest) {
|
|
6776
|
+
if (node.children.length === 0) continue;
|
|
6777
|
+
const childKeys = node.children.map((c) => c.id);
|
|
6778
|
+
if (desktop) applyChildrenOrder(node.id, childKeys, desktop);
|
|
6779
|
+
if (drawer) applyChildrenOrder(node.id, childKeys, drawer);
|
|
6780
|
+
}
|
|
6781
|
+
}
|
|
6782
|
+
function getNavForestFromDom() {
|
|
6783
|
+
const items = listNavbarItems();
|
|
6784
|
+
const nestedChildKeys = /* @__PURE__ */ new Set();
|
|
6785
|
+
const roots = [];
|
|
6786
|
+
for (const item of items) {
|
|
6787
|
+
const key = item.getAttribute("data-ohw-href-key");
|
|
6788
|
+
if (!key || !isNavbarHrefKey(key)) continue;
|
|
6789
|
+
if (item.closest("[data-ohw-nav-children]")) continue;
|
|
6790
|
+
const group = item.closest("[data-ohw-nav-group]");
|
|
6791
|
+
const childrenRoot = group?.querySelector(":scope > [data-ohw-nav-children]");
|
|
6792
|
+
const children = [];
|
|
6793
|
+
if (childrenRoot) {
|
|
6794
|
+
for (const child of childrenRoot.querySelectorAll(":scope > [data-ohw-href-key]")) {
|
|
6795
|
+
if (!isNavbarLinkItem(child)) continue;
|
|
6796
|
+
const childKey = child.getAttribute("data-ohw-href-key");
|
|
6797
|
+
if (!childKey || !isNavbarHrefKey(childKey)) continue;
|
|
6798
|
+
nestedChildKeys.add(childKey);
|
|
6799
|
+
children.push({ id: childKey, children: [] });
|
|
6800
|
+
}
|
|
6801
|
+
}
|
|
6802
|
+
roots.push({ id: key, children });
|
|
6803
|
+
}
|
|
6804
|
+
if (roots.length === 0) {
|
|
6805
|
+
return forestFromFlatOrder(
|
|
6806
|
+
getNavOrderFromDom().filter((k) => isNavbarHrefKey(k) && !nestedChildKeys.has(k))
|
|
6807
|
+
);
|
|
6808
|
+
}
|
|
6809
|
+
return roots;
|
|
6810
|
+
}
|
|
6811
|
+
function planNavItemMove(hrefKey, parentId, insertIndex) {
|
|
6812
|
+
const model = getNavForestFromDom();
|
|
6813
|
+
const next = moveNode(model, hrefKey, { parentId, index: insertIndex });
|
|
6814
|
+
if (!next) return null;
|
|
6815
|
+
if (forestsEqual(model, next)) return null;
|
|
6816
|
+
return {
|
|
6817
|
+
forest: next,
|
|
6818
|
+
orderJson: serializeNavOrder(next),
|
|
6819
|
+
flatOrder: flattenNavOrder(next)
|
|
6820
|
+
};
|
|
6821
|
+
}
|
|
6489
6822
|
function collectNavbarIndicesFromContent(content) {
|
|
6490
6823
|
const indices = /* @__PURE__ */ new Set();
|
|
6491
6824
|
for (const key of Object.keys(content)) {
|
|
@@ -6513,8 +6846,10 @@ function reconcileNavbarItemsFromContent(content) {
|
|
|
6513
6846
|
if (!href && !label) continue;
|
|
6514
6847
|
insertNavbarItemDom(index, href ?? "/", label ?? "Untitled", null);
|
|
6515
6848
|
}
|
|
6516
|
-
const
|
|
6517
|
-
if (
|
|
6849
|
+
const orderForest = parseNavOrderJson(content[NAV_ORDER_KEY]);
|
|
6850
|
+
if (orderForest?.length) {
|
|
6851
|
+
applyNavForest(orderForest);
|
|
6852
|
+
}
|
|
6518
6853
|
}
|
|
6519
6854
|
function buildNavOrderAfterInsert(afterAnchor, newHrefKey) {
|
|
6520
6855
|
const order = getNavOrderFromDom();
|
|
@@ -6554,146 +6889,1344 @@ function insertNavbarItem(href, label, afterAnchor = null) {
|
|
|
6554
6889
|
};
|
|
6555
6890
|
}
|
|
6556
6891
|
|
|
6557
|
-
// src/
|
|
6558
|
-
var
|
|
6559
|
-
var
|
|
6560
|
-
function
|
|
6561
|
-
|
|
6562
|
-
|
|
6563
|
-
|
|
6564
|
-
|
|
6565
|
-
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6566
|
-
"div",
|
|
6567
|
-
{
|
|
6568
|
-
"data-ohw-navbar-container-chrome": "",
|
|
6569
|
-
"data-ohw-bridge": "",
|
|
6570
|
-
className: "pointer-events-none fixed z-[2147483647]",
|
|
6571
|
-
style: {
|
|
6572
|
-
top: rect.top - chromeGap,
|
|
6573
|
-
left: rect.left - chromeGap,
|
|
6574
|
-
width: rect.width + chromeGap * 2,
|
|
6575
|
-
height: rect.height + chromeGap * 2
|
|
6576
|
-
},
|
|
6577
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
6578
|
-
"button",
|
|
6579
|
-
{
|
|
6580
|
-
type: "button",
|
|
6581
|
-
"data-ohw-navbar-add-button": "",
|
|
6582
|
-
className: "pointer-events-auto absolute left-1/2 flex p-0.5 rounded-[10px] size-7 -translate-x-1/2 translate-y-1/2 items-center justify-center border border-border bg-background shadow-sm transition-colors hover:bg-muted/80",
|
|
6583
|
-
style: { top: "70%" },
|
|
6584
|
-
"aria-label": "Add item",
|
|
6585
|
-
onMouseDown: (e) => {
|
|
6586
|
-
e.preventDefault();
|
|
6587
|
-
e.stopPropagation();
|
|
6588
|
-
},
|
|
6589
|
-
onClick: (e) => {
|
|
6590
|
-
e.preventDefault();
|
|
6591
|
-
e.stopPropagation();
|
|
6592
|
-
onAdd();
|
|
6593
|
-
},
|
|
6594
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
6595
|
-
}
|
|
6596
|
-
)
|
|
6597
|
-
}
|
|
6598
|
-
);
|
|
6892
|
+
// src/lib/footer-items.ts
|
|
6893
|
+
var FOOTER_ORDER_KEY = "__ohw_footer_order";
|
|
6894
|
+
var FOOTER_HREF_RE = /^footer-(\d+)-(\d+)-href$/;
|
|
6895
|
+
function parseFooterHrefKey(key) {
|
|
6896
|
+
if (!key) return null;
|
|
6897
|
+
const match = key.match(FOOTER_HREF_RE);
|
|
6898
|
+
if (!match) return null;
|
|
6899
|
+
return { col: parseInt(match[1], 10), item: parseInt(match[2], 10) };
|
|
6599
6900
|
}
|
|
6600
|
-
|
|
6601
|
-
|
|
6602
|
-
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
6603
|
-
var badgeVariants = cva(
|
|
6604
|
-
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
6605
|
-
{
|
|
6606
|
-
variants: {
|
|
6607
|
-
variant: {
|
|
6608
|
-
default: "border-transparent bg-primary text-primary-foreground",
|
|
6609
|
-
secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
6610
|
-
destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
|
|
6611
|
-
outline: "text-foreground"
|
|
6612
|
-
}
|
|
6613
|
-
},
|
|
6614
|
-
defaultVariants: {
|
|
6615
|
-
variant: "default"
|
|
6616
|
-
}
|
|
6617
|
-
}
|
|
6618
|
-
);
|
|
6619
|
-
function Badge({ className, variant, ...props }) {
|
|
6620
|
-
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
6901
|
+
function isFooterHrefKey(key) {
|
|
6902
|
+
return parseFooterHrefKey(key) !== null;
|
|
6621
6903
|
}
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
var import_lucide_react11 = require("lucide-react");
|
|
6625
|
-
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
6626
|
-
var PRIMARY2 = "#0885FE";
|
|
6627
|
-
var IMAGE_FADE_MS = 300;
|
|
6628
|
-
function runOpacityFade(el, onDone) {
|
|
6629
|
-
const anim = el.animate([{ opacity: 0 }, { opacity: 1 }], {
|
|
6630
|
-
duration: IMAGE_FADE_MS,
|
|
6631
|
-
easing: "ease",
|
|
6632
|
-
fill: "forwards"
|
|
6633
|
-
});
|
|
6634
|
-
let finished = false;
|
|
6635
|
-
const finish = () => {
|
|
6636
|
-
if (finished) return;
|
|
6637
|
-
finished = true;
|
|
6638
|
-
anim.cancel();
|
|
6639
|
-
el.style.opacity = "";
|
|
6640
|
-
onDone();
|
|
6641
|
-
};
|
|
6642
|
-
anim.finished.then(finish).catch(finish);
|
|
6643
|
-
window.setTimeout(finish, IMAGE_FADE_MS + 100);
|
|
6904
|
+
function getFooterRoot() {
|
|
6905
|
+
return document.querySelector('footer[data-ohw-section="footer"], footer');
|
|
6644
6906
|
}
|
|
6645
|
-
function
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
|
|
6907
|
+
function getFooterLinksContainer() {
|
|
6908
|
+
return document.querySelector("[data-ohw-footer-links]") ?? document.querySelector(".rb-footer-links");
|
|
6909
|
+
}
|
|
6910
|
+
function isFooterLinkAnchor(el) {
|
|
6911
|
+
if (!el.matches("[data-ohw-href-key]")) return false;
|
|
6912
|
+
if (!isFooterHrefKey(el.getAttribute("data-ohw-href-key"))) return false;
|
|
6913
|
+
return Boolean(el.querySelector('[data-ohw-editable="text"]'));
|
|
6914
|
+
}
|
|
6915
|
+
function listFooterColumns() {
|
|
6916
|
+
const root = getFooterLinksContainer() ?? getFooterRoot()?.querySelector(".rb-footer-links") ?? null;
|
|
6917
|
+
if (!root) return [];
|
|
6918
|
+
const explicit = Array.from(root.querySelectorAll(":scope > [data-ohw-footer-col]"));
|
|
6919
|
+
if (explicit.length > 0) return explicit;
|
|
6920
|
+
return Array.from(root.children).filter((el) => {
|
|
6921
|
+
if (!(el instanceof HTMLElement)) return false;
|
|
6922
|
+
return Array.from(el.querySelectorAll(":scope > [data-ohw-href-key]")).some(
|
|
6923
|
+
isFooterLinkAnchor
|
|
6924
|
+
);
|
|
6650
6925
|
});
|
|
6651
6926
|
}
|
|
6652
|
-
function
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6927
|
+
function listFooterLinksInColumn(column) {
|
|
6928
|
+
return Array.from(column.querySelectorAll(":scope > [data-ohw-href-key]")).filter(
|
|
6929
|
+
isFooterLinkAnchor
|
|
6930
|
+
);
|
|
6656
6931
|
}
|
|
6657
|
-
function
|
|
6658
|
-
const
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
|
|
6667
|
-
|
|
6668
|
-
|
|
6669
|
-
|
|
6670
|
-
|
|
6671
|
-
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
|
|
6677
|
-
layer.remove();
|
|
6678
|
-
if (!prevPos || prevPos === "static") el.style.position = prevPos;
|
|
6932
|
+
function findFooterColumnForLink(anchor) {
|
|
6933
|
+
const columns = listFooterColumns();
|
|
6934
|
+
return columns.find((col) => col.contains(anchor)) ?? null;
|
|
6935
|
+
}
|
|
6936
|
+
function getFooterOrderFromDom() {
|
|
6937
|
+
return listFooterColumns().map(
|
|
6938
|
+
(col) => listFooterLinksInColumn(col).map((el) => el.getAttribute("data-ohw-href-key")).filter((key) => Boolean(key))
|
|
6939
|
+
);
|
|
6940
|
+
}
|
|
6941
|
+
function findFooterLinkByKey(hrefKey) {
|
|
6942
|
+
return document.querySelector(
|
|
6943
|
+
`footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
6944
|
+
);
|
|
6945
|
+
}
|
|
6946
|
+
function syncFooterColumnIndices(columns) {
|
|
6947
|
+
columns.forEach((col, index) => {
|
|
6948
|
+
const next = String(index);
|
|
6949
|
+
if (col.getAttribute("data-ohw-footer-col") !== next) {
|
|
6950
|
+
col.setAttribute("data-ohw-footer-col", next);
|
|
6951
|
+
}
|
|
6679
6952
|
});
|
|
6680
6953
|
}
|
|
6681
|
-
function
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
el = document.createElement("div");
|
|
6685
|
-
el.setAttribute("data-ohw-sections-tracker", "");
|
|
6686
|
-
el.style.display = "none";
|
|
6687
|
-
document.body.appendChild(el);
|
|
6954
|
+
function appendChildIfNeeded(parent, child) {
|
|
6955
|
+
if (parent.lastElementChild !== child) {
|
|
6956
|
+
parent.appendChild(child);
|
|
6688
6957
|
}
|
|
6689
|
-
return el;
|
|
6690
6958
|
}
|
|
6691
|
-
function
|
|
6692
|
-
const
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6959
|
+
function applyFooterOrder(order) {
|
|
6960
|
+
const container = getFooterLinksContainer();
|
|
6961
|
+
if (!container) return;
|
|
6962
|
+
const columns = listFooterColumns();
|
|
6963
|
+
if (columns.length === 0) return;
|
|
6964
|
+
const currentOrder = getFooterOrderFromDom();
|
|
6965
|
+
if (ordersEqual(order, currentOrder)) {
|
|
6966
|
+
syncFooterColumnIndices(columns);
|
|
6967
|
+
return;
|
|
6968
|
+
}
|
|
6969
|
+
const used = /* @__PURE__ */ new Set();
|
|
6970
|
+
const orderedCols = [];
|
|
6971
|
+
for (const colOrder of order) {
|
|
6972
|
+
let matched = null;
|
|
6973
|
+
for (const hrefKey of colOrder) {
|
|
6974
|
+
const link = findFooterLinkByKey(hrefKey);
|
|
6975
|
+
if (!link) continue;
|
|
6976
|
+
const owner = findFooterColumnForLink(link);
|
|
6977
|
+
if (owner && !used.has(owner)) {
|
|
6978
|
+
matched = owner;
|
|
6979
|
+
break;
|
|
6980
|
+
}
|
|
6981
|
+
}
|
|
6982
|
+
if (!matched) {
|
|
6983
|
+
matched = columns.find((col) => !used.has(col)) ?? null;
|
|
6984
|
+
}
|
|
6985
|
+
if (matched) {
|
|
6986
|
+
used.add(matched);
|
|
6987
|
+
orderedCols.push(matched);
|
|
6988
|
+
}
|
|
6989
|
+
}
|
|
6990
|
+
for (const col of columns) {
|
|
6991
|
+
if (!used.has(col)) orderedCols.push(col);
|
|
6992
|
+
}
|
|
6993
|
+
for (const col of orderedCols) {
|
|
6994
|
+
appendChildIfNeeded(container, col);
|
|
6995
|
+
}
|
|
6996
|
+
const freshColumns = listFooterColumns();
|
|
6997
|
+
syncFooterColumnIndices(freshColumns);
|
|
6998
|
+
for (let c = 0; c < order.length; c++) {
|
|
6999
|
+
const col = freshColumns[c];
|
|
7000
|
+
if (!col) continue;
|
|
7001
|
+
const colOrder = order[c];
|
|
7002
|
+
for (const hrefKey of colOrder) {
|
|
7003
|
+
const el = findFooterLinkByKey(hrefKey);
|
|
7004
|
+
if (!el) continue;
|
|
7005
|
+
if (el.parentElement !== col || col.lastElementChild !== el) {
|
|
7006
|
+
col.appendChild(el);
|
|
7007
|
+
}
|
|
7008
|
+
}
|
|
7009
|
+
}
|
|
7010
|
+
}
|
|
7011
|
+
function ordersEqual(a, b) {
|
|
7012
|
+
if (a.length !== b.length) return false;
|
|
7013
|
+
for (let i = 0; i < a.length; i++) {
|
|
7014
|
+
const left = a[i];
|
|
7015
|
+
const right = b[i];
|
|
7016
|
+
if (left.length !== right.length) return false;
|
|
7017
|
+
for (let j = 0; j < left.length; j++) {
|
|
7018
|
+
if (left[j] !== right[j]) return false;
|
|
7019
|
+
}
|
|
7020
|
+
}
|
|
7021
|
+
return true;
|
|
7022
|
+
}
|
|
7023
|
+
function planFooterLinkMove(hrefKey, targetColIndex, insertIndex) {
|
|
7024
|
+
const order = getFooterOrderFromDom();
|
|
7025
|
+
if (targetColIndex < 0 || targetColIndex >= order.length) return null;
|
|
7026
|
+
let fromCol = -1;
|
|
7027
|
+
let fromIdx = -1;
|
|
7028
|
+
for (let c = 0; c < order.length; c++) {
|
|
7029
|
+
const idx = order[c].indexOf(hrefKey);
|
|
7030
|
+
if (idx >= 0) {
|
|
7031
|
+
fromCol = c;
|
|
7032
|
+
fromIdx = idx;
|
|
7033
|
+
break;
|
|
7034
|
+
}
|
|
7035
|
+
}
|
|
7036
|
+
if (fromCol < 0) return null;
|
|
7037
|
+
const next = order.map((col) => [...col]);
|
|
7038
|
+
next[fromCol].splice(fromIdx, 1);
|
|
7039
|
+
let adjusted = insertIndex;
|
|
7040
|
+
if (fromCol === targetColIndex && fromIdx < insertIndex) adjusted -= 1;
|
|
7041
|
+
adjusted = Math.max(0, Math.min(adjusted, next[targetColIndex].length));
|
|
7042
|
+
next[targetColIndex].splice(adjusted, 0, hrefKey);
|
|
7043
|
+
if (ordersEqual(next, order)) return null;
|
|
7044
|
+
return next;
|
|
7045
|
+
}
|
|
7046
|
+
function planFooterColumnMove(fromIndex, toIndex) {
|
|
7047
|
+
const order = getFooterOrderFromDom();
|
|
7048
|
+
const columns = listFooterColumns();
|
|
7049
|
+
if (fromIndex < 0 || fromIndex >= columns.length || toIndex < 0 || toIndex > columns.length) {
|
|
7050
|
+
return null;
|
|
7051
|
+
}
|
|
7052
|
+
if (toIndex === fromIndex || toIndex === fromIndex + 1) return null;
|
|
7053
|
+
const nextOrder = order.map((col) => [...col]);
|
|
7054
|
+
const [movedOrder] = nextOrder.splice(fromIndex, 1);
|
|
7055
|
+
if (!movedOrder) return null;
|
|
7056
|
+
let adjusted = toIndex;
|
|
7057
|
+
if (fromIndex < toIndex) adjusted -= 1;
|
|
7058
|
+
adjusted = Math.max(0, Math.min(adjusted, nextOrder.length));
|
|
7059
|
+
nextOrder.splice(adjusted, 0, movedOrder);
|
|
7060
|
+
if (ordersEqual(nextOrder, order)) return null;
|
|
7061
|
+
return nextOrder;
|
|
7062
|
+
}
|
|
7063
|
+
function parseFooterOrder(content) {
|
|
7064
|
+
const raw = content[FOOTER_ORDER_KEY];
|
|
7065
|
+
if (!raw) return null;
|
|
7066
|
+
try {
|
|
7067
|
+
const parsed = JSON.parse(raw);
|
|
7068
|
+
if (!Array.isArray(parsed)) return null;
|
|
7069
|
+
return parsed.filter((col) => Array.isArray(col)).map((col) => col.filter((key) => typeof key === "string" && key.length > 0));
|
|
7070
|
+
} catch {
|
|
7071
|
+
return null;
|
|
7072
|
+
}
|
|
7073
|
+
}
|
|
7074
|
+
var FOOTER_HEADING_RE = /^footer-(\d+)-heading$/;
|
|
7075
|
+
var FOOTER_LABEL_RE = /^footer-(\d+)-(\d+)-label$/;
|
|
7076
|
+
var DEFAULT_FOOTER_COLUMN_HEADING = "New";
|
|
7077
|
+
var DEFAULT_FOOTER_COLUMN_LINK_LABEL = "New link";
|
|
7078
|
+
var DEFAULT_FOOTER_COLUMN_LINK_HREF = "";
|
|
7079
|
+
function isFooterLinksContainer(el) {
|
|
7080
|
+
return el.hasAttribute("data-ohw-footer-links") || el.classList.contains("rb-footer-links");
|
|
7081
|
+
}
|
|
7082
|
+
function getFooterColumnIndicesInDom() {
|
|
7083
|
+
const indices = /* @__PURE__ */ new Set();
|
|
7084
|
+
for (const col of listFooterColumns()) {
|
|
7085
|
+
const attr = col.getAttribute("data-ohw-footer-col");
|
|
7086
|
+
if (attr != null) {
|
|
7087
|
+
const n = parseInt(attr, 10);
|
|
7088
|
+
if (Number.isFinite(n)) indices.add(n);
|
|
7089
|
+
}
|
|
7090
|
+
for (const link of listFooterLinksInColumn(col)) {
|
|
7091
|
+
const parsed = parseFooterHrefKey(link.getAttribute("data-ohw-href-key"));
|
|
7092
|
+
if (parsed) indices.add(parsed.col);
|
|
7093
|
+
}
|
|
7094
|
+
const heading = col.querySelector('[data-ohw-key^="footer-"][data-ohw-key$="-heading"]');
|
|
7095
|
+
const headingKey = heading?.getAttribute("data-ohw-key");
|
|
7096
|
+
if (headingKey) {
|
|
7097
|
+
const match = headingKey.match(FOOTER_HEADING_RE);
|
|
7098
|
+
if (match) indices.add(parseInt(match[1], 10));
|
|
7099
|
+
}
|
|
7100
|
+
}
|
|
7101
|
+
return [...indices].sort((a, b) => a - b);
|
|
7102
|
+
}
|
|
7103
|
+
function getNextFooterColumnIndex() {
|
|
7104
|
+
const indices = getFooterColumnIndicesInDom();
|
|
7105
|
+
if (indices.length === 0) return 0;
|
|
7106
|
+
return Math.max(...indices) + 1;
|
|
7107
|
+
}
|
|
7108
|
+
function cloneFooterLinkShell(template) {
|
|
7109
|
+
const anchor = document.createElement("a");
|
|
7110
|
+
if (template) {
|
|
7111
|
+
anchor.style.cssText = template.style.cssText;
|
|
7112
|
+
if (template.className) anchor.className = template.className;
|
|
7113
|
+
}
|
|
7114
|
+
anchor.style.cursor = "pointer";
|
|
7115
|
+
anchor.style.textDecoration = "none";
|
|
7116
|
+
return anchor;
|
|
7117
|
+
}
|
|
7118
|
+
function buildFooterHeading(colIndex, text) {
|
|
7119
|
+
const heading = document.createElement("p");
|
|
7120
|
+
heading.setAttribute("data-ohw-editable", "text");
|
|
7121
|
+
heading.setAttribute("data-ohw-key", `footer-${colIndex}-heading`);
|
|
7122
|
+
heading.textContent = text;
|
|
7123
|
+
heading.style.cssText = [
|
|
7124
|
+
"color: var(--espresso, #3d312b)",
|
|
7125
|
+
"font-size: 14px",
|
|
7126
|
+
"font-weight: 800",
|
|
7127
|
+
"opacity: 0.82",
|
|
7128
|
+
"margin: 0 0 6px",
|
|
7129
|
+
"padding: 0",
|
|
7130
|
+
"line-height: 1.2"
|
|
7131
|
+
].join(";");
|
|
7132
|
+
return heading;
|
|
7133
|
+
}
|
|
7134
|
+
function buildFooterLink(colIndex, itemIndex, href, label, template) {
|
|
7135
|
+
const anchor = cloneFooterLinkShell(template);
|
|
7136
|
+
anchor.setAttribute("href", href);
|
|
7137
|
+
anchor.setAttribute("data-ohw-href-key", `footer-${colIndex}-${itemIndex}-href`);
|
|
7138
|
+
const span = document.createElement("span");
|
|
7139
|
+
span.setAttribute("data-ohw-editable", "text");
|
|
7140
|
+
span.setAttribute("data-ohw-key", `footer-${colIndex}-${itemIndex}-label`);
|
|
7141
|
+
span.textContent = label;
|
|
7142
|
+
anchor.appendChild(span);
|
|
7143
|
+
return anchor;
|
|
7144
|
+
}
|
|
7145
|
+
function footerColumnExistsInDom(colIndex) {
|
|
7146
|
+
return document.querySelector(`[data-ohw-footer-col="${colIndex}"]`) !== null || document.querySelector(`[data-ohw-href-key^="footer-${colIndex}-"]`) !== null || document.querySelector(`[data-ohw-key="footer-${colIndex}-heading"]`) !== null;
|
|
7147
|
+
}
|
|
7148
|
+
function getFooterLinkTemplate() {
|
|
7149
|
+
for (const col of listFooterColumns()) {
|
|
7150
|
+
const link = listFooterLinksInColumn(col)[0];
|
|
7151
|
+
if (link) return link;
|
|
7152
|
+
}
|
|
7153
|
+
return null;
|
|
7154
|
+
}
|
|
7155
|
+
function getFooterColumnTemplate() {
|
|
7156
|
+
return listFooterColumns()[0] ?? null;
|
|
7157
|
+
}
|
|
7158
|
+
function insertFooterColumnDom(colIndex, heading, items) {
|
|
7159
|
+
const container = getFooterLinksContainer();
|
|
7160
|
+
if (!container) return null;
|
|
7161
|
+
const colTemplate = getFooterColumnTemplate();
|
|
7162
|
+
const linkTemplate = getFooterLinkTemplate();
|
|
7163
|
+
const column = document.createElement("div");
|
|
7164
|
+
if (colTemplate?.className) column.className = colTemplate.className;
|
|
7165
|
+
else column.className = "rb-footer-link-col";
|
|
7166
|
+
column.setAttribute("data-ohw-footer-col", String(colIndex));
|
|
7167
|
+
if (colTemplate) {
|
|
7168
|
+
const gap = getComputedStyle(colTemplate).gap;
|
|
7169
|
+
if (gap && gap !== "normal") column.style.gap = gap;
|
|
7170
|
+
column.style.display = getComputedStyle(colTemplate).display || "flex";
|
|
7171
|
+
column.style.flexDirection = "column";
|
|
7172
|
+
}
|
|
7173
|
+
column.appendChild(buildFooterHeading(colIndex, heading));
|
|
7174
|
+
let firstLink = null;
|
|
7175
|
+
items.forEach((item, itemIndex) => {
|
|
7176
|
+
const link = buildFooterLink(colIndex, itemIndex, item.href, item.label, linkTemplate);
|
|
7177
|
+
column.appendChild(link);
|
|
7178
|
+
if (!firstLink) firstLink = link;
|
|
7179
|
+
});
|
|
7180
|
+
container.appendChild(column);
|
|
7181
|
+
return { column, firstLink };
|
|
7182
|
+
}
|
|
7183
|
+
function insertFooterColumn(heading = DEFAULT_FOOTER_COLUMN_HEADING, linkLabel = DEFAULT_FOOTER_COLUMN_LINK_LABEL, linkHref = DEFAULT_FOOTER_COLUMN_LINK_HREF) {
|
|
7184
|
+
const colIndex = getNextFooterColumnIndex();
|
|
7185
|
+
const inserted = insertFooterColumnDom(colIndex, heading, [{ href: linkHref, label: linkLabel }]);
|
|
7186
|
+
if (!inserted?.firstLink) throw new Error("Failed to insert footer column");
|
|
7187
|
+
syncFooterColumnIndices(listFooterColumns());
|
|
7188
|
+
return {
|
|
7189
|
+
column: inserted.column,
|
|
7190
|
+
firstLink: inserted.firstLink,
|
|
7191
|
+
colIndex,
|
|
7192
|
+
headingKey: `footer-${colIndex}-heading`,
|
|
7193
|
+
hrefKey: `footer-${colIndex}-0-href`,
|
|
7194
|
+
labelKey: `footer-${colIndex}-0-label`,
|
|
7195
|
+
heading,
|
|
7196
|
+
label: linkLabel,
|
|
7197
|
+
href: linkHref,
|
|
7198
|
+
order: getFooterOrderFromDom()
|
|
7199
|
+
};
|
|
7200
|
+
}
|
|
7201
|
+
function collectFooterColumnIndicesFromContent(content) {
|
|
7202
|
+
const indices = /* @__PURE__ */ new Set();
|
|
7203
|
+
for (const key of Object.keys(content)) {
|
|
7204
|
+
const href = parseFooterHrefKey(key);
|
|
7205
|
+
if (href) indices.add(href.col);
|
|
7206
|
+
const heading = key.match(FOOTER_HEADING_RE);
|
|
7207
|
+
if (heading) indices.add(parseInt(heading[1], 10));
|
|
7208
|
+
const label = key.match(FOOTER_LABEL_RE);
|
|
7209
|
+
if (label) indices.add(parseInt(label[1], 10));
|
|
7210
|
+
}
|
|
7211
|
+
const order = parseFooterOrder(content);
|
|
7212
|
+
if (order) {
|
|
7213
|
+
for (const col of order) {
|
|
7214
|
+
for (const hrefKey of col) {
|
|
7215
|
+
const parsed = parseFooterHrefKey(hrefKey);
|
|
7216
|
+
if (parsed) indices.add(parsed.col);
|
|
7217
|
+
}
|
|
7218
|
+
}
|
|
7219
|
+
}
|
|
7220
|
+
return [...indices].sort((a, b) => a - b);
|
|
7221
|
+
}
|
|
7222
|
+
function collectFooterItemsForColumn(content, colIndex) {
|
|
7223
|
+
const itemIndices = /* @__PURE__ */ new Set();
|
|
7224
|
+
for (const key of Object.keys(content)) {
|
|
7225
|
+
const href = parseFooterHrefKey(key);
|
|
7226
|
+
if (href?.col === colIndex) itemIndices.add(href.item);
|
|
7227
|
+
const label = key.match(FOOTER_LABEL_RE);
|
|
7228
|
+
if (label && parseInt(label[1], 10) === colIndex) {
|
|
7229
|
+
itemIndices.add(parseInt(label[2], 10));
|
|
7230
|
+
}
|
|
7231
|
+
}
|
|
7232
|
+
const sorted = [...itemIndices].sort((a, b) => a - b);
|
|
7233
|
+
if (sorted.length === 0) {
|
|
7234
|
+
return [
|
|
7235
|
+
{
|
|
7236
|
+
href: content[`footer-${colIndex}-0-href`] ?? DEFAULT_FOOTER_COLUMN_LINK_HREF,
|
|
7237
|
+
label: content[`footer-${colIndex}-0-label`] ?? DEFAULT_FOOTER_COLUMN_LINK_LABEL
|
|
7238
|
+
}
|
|
7239
|
+
];
|
|
7240
|
+
}
|
|
7241
|
+
return sorted.map((itemIndex) => ({
|
|
7242
|
+
href: content[`footer-${colIndex}-${itemIndex}-href`] ?? DEFAULT_FOOTER_COLUMN_LINK_HREF,
|
|
7243
|
+
label: content[`footer-${colIndex}-${itemIndex}-label`] ?? DEFAULT_FOOTER_COLUMN_LINK_LABEL
|
|
7244
|
+
}));
|
|
7245
|
+
}
|
|
7246
|
+
function reconcileFooterColumnsFromContent(content) {
|
|
7247
|
+
const indices = collectFooterColumnIndicesFromContent(content);
|
|
7248
|
+
for (const colIndex of indices) {
|
|
7249
|
+
if (footerColumnExistsInDom(colIndex)) continue;
|
|
7250
|
+
const heading = content[`footer-${colIndex}-heading`] ?? DEFAULT_FOOTER_COLUMN_HEADING;
|
|
7251
|
+
const items = collectFooterItemsForColumn(content, colIndex);
|
|
7252
|
+
const hasPayload = Boolean(content[`footer-${colIndex}-heading`]) || items.some(
|
|
7253
|
+
(_, i) => content[`footer-${colIndex}-${i}-href`] !== void 0 || content[`footer-${colIndex}-${i}-label`] !== void 0
|
|
7254
|
+
) || (parseFooterOrder(content)?.some(
|
|
7255
|
+
(col) => col.some((k) => parseFooterHrefKey(k)?.col === colIndex)
|
|
7256
|
+
) ?? false);
|
|
7257
|
+
if (!hasPayload) continue;
|
|
7258
|
+
insertFooterColumnDom(colIndex, heading, items);
|
|
7259
|
+
}
|
|
7260
|
+
}
|
|
7261
|
+
function reconcileFooterOrderFromContent(content) {
|
|
7262
|
+
reconcileFooterColumnsFromContent(content);
|
|
7263
|
+
const order = parseFooterOrder(content);
|
|
7264
|
+
if (!order?.length) return;
|
|
7265
|
+
const current = getFooterOrderFromDom();
|
|
7266
|
+
if (ordersEqual(order, current)) {
|
|
7267
|
+
syncFooterColumnIndices(listFooterColumns());
|
|
7268
|
+
return;
|
|
7269
|
+
}
|
|
7270
|
+
applyFooterOrder(order);
|
|
7271
|
+
}
|
|
7272
|
+
function resolveFooterLinksContainerSelectionTarget(target, clientX, clientY, isPointOverItem) {
|
|
7273
|
+
const container = getFooterLinksContainer();
|
|
7274
|
+
if (!container) return null;
|
|
7275
|
+
const inContainer = target === container || container.contains(target) && Boolean(target.closest("[data-ohw-footer-links], .rb-footer-links"));
|
|
7276
|
+
if (!inContainer && target !== container) {
|
|
7277
|
+
const r2 = container.getBoundingClientRect();
|
|
7278
|
+
const over = clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
|
|
7279
|
+
if (!over) return null;
|
|
7280
|
+
}
|
|
7281
|
+
if (isPointOverItem(container, clientX, clientY)) return null;
|
|
7282
|
+
const column = target.closest("[data-ohw-footer-col], [data-ohw-footer-column]") ?? null;
|
|
7283
|
+
if (column && container.contains(column)) {
|
|
7284
|
+
if (target === column || column.contains(target)) return null;
|
|
7285
|
+
}
|
|
7286
|
+
if (target === container || container.contains(target) || inContainer) {
|
|
7287
|
+
if (target === container || isFooterLinksContainer(target)) return container;
|
|
7288
|
+
if (!column) return container;
|
|
7289
|
+
}
|
|
7290
|
+
return null;
|
|
7291
|
+
}
|
|
7292
|
+
function isRowLayoutColumn(links) {
|
|
7293
|
+
if (links.length < 2) return false;
|
|
7294
|
+
const firstTop = links[0].getBoundingClientRect().top;
|
|
7295
|
+
return links.every((link) => Math.abs(link.getBoundingClientRect().top - firstTop) < 4);
|
|
7296
|
+
}
|
|
7297
|
+
function buildLinkDropSlots(column, columnIndex) {
|
|
7298
|
+
const links = listFooterLinksInColumn(column);
|
|
7299
|
+
const colRect = column.getBoundingClientRect();
|
|
7300
|
+
const slots = [];
|
|
7301
|
+
const barThickness = 3;
|
|
7302
|
+
if (links.length === 0) {
|
|
7303
|
+
slots.push({
|
|
7304
|
+
insertIndex: 0,
|
|
7305
|
+
columnIndex,
|
|
7306
|
+
left: colRect.left,
|
|
7307
|
+
top: colRect.top + colRect.height / 2 - barThickness / 2,
|
|
7308
|
+
width: colRect.width,
|
|
7309
|
+
height: barThickness,
|
|
7310
|
+
direction: "horizontal"
|
|
7311
|
+
});
|
|
7312
|
+
return slots;
|
|
7313
|
+
}
|
|
7314
|
+
if (isRowLayoutColumn(links)) {
|
|
7315
|
+
for (let i = 0; i <= links.length; i++) {
|
|
7316
|
+
let left;
|
|
7317
|
+
if (i === 0) {
|
|
7318
|
+
left = links[0].getBoundingClientRect().left - barThickness / 2;
|
|
7319
|
+
} else if (i === links.length) {
|
|
7320
|
+
const last = links[links.length - 1].getBoundingClientRect();
|
|
7321
|
+
left = last.right - barThickness / 2;
|
|
7322
|
+
} else {
|
|
7323
|
+
const prev = links[i - 1].getBoundingClientRect();
|
|
7324
|
+
const next = links[i].getBoundingClientRect();
|
|
7325
|
+
left = (prev.right + next.left) / 2 - barThickness / 2;
|
|
7326
|
+
}
|
|
7327
|
+
const heightRef = i === 0 ? links[0].getBoundingClientRect() : i === links.length ? links[links.length - 1].getBoundingClientRect() : links[i].getBoundingClientRect();
|
|
7328
|
+
slots.push({
|
|
7329
|
+
insertIndex: i,
|
|
7330
|
+
columnIndex,
|
|
7331
|
+
left,
|
|
7332
|
+
top: heightRef.top,
|
|
7333
|
+
width: barThickness,
|
|
7334
|
+
height: Math.max(heightRef.height, colRect.height * 0.8),
|
|
7335
|
+
direction: "vertical"
|
|
7336
|
+
});
|
|
7337
|
+
}
|
|
7338
|
+
return slots;
|
|
7339
|
+
}
|
|
7340
|
+
for (let i = 0; i <= links.length; i++) {
|
|
7341
|
+
let top;
|
|
7342
|
+
if (i === 0) {
|
|
7343
|
+
top = links[0].getBoundingClientRect().top - barThickness / 2;
|
|
7344
|
+
} else if (i === links.length) {
|
|
7345
|
+
const last = links[links.length - 1].getBoundingClientRect();
|
|
7346
|
+
top = last.bottom - barThickness / 2;
|
|
7347
|
+
} else {
|
|
7348
|
+
const prev = links[i - 1].getBoundingClientRect();
|
|
7349
|
+
const next = links[i].getBoundingClientRect();
|
|
7350
|
+
top = (prev.bottom + next.top) / 2 - barThickness / 2;
|
|
7351
|
+
}
|
|
7352
|
+
const widthRef = i === 0 ? links[0].getBoundingClientRect() : i === links.length ? links[links.length - 1].getBoundingClientRect() : links[i].getBoundingClientRect();
|
|
7353
|
+
slots.push({
|
|
7354
|
+
insertIndex: i,
|
|
7355
|
+
columnIndex,
|
|
7356
|
+
left: widthRef.left,
|
|
7357
|
+
top,
|
|
7358
|
+
width: Math.max(widthRef.width, colRect.width * 0.8),
|
|
7359
|
+
height: barThickness,
|
|
7360
|
+
direction: "horizontal"
|
|
7361
|
+
});
|
|
7362
|
+
}
|
|
7363
|
+
return slots;
|
|
7364
|
+
}
|
|
7365
|
+
function buildColumnDropSlots() {
|
|
7366
|
+
const columns = listFooterColumns();
|
|
7367
|
+
const slots = [];
|
|
7368
|
+
const barThickness = 3;
|
|
7369
|
+
if (columns.length === 0) return slots;
|
|
7370
|
+
for (let i = 0; i <= columns.length; i++) {
|
|
7371
|
+
let left;
|
|
7372
|
+
let height;
|
|
7373
|
+
let top;
|
|
7374
|
+
if (i === 0) {
|
|
7375
|
+
const first = columns[0].getBoundingClientRect();
|
|
7376
|
+
left = first.left - barThickness / 2;
|
|
7377
|
+
top = first.top;
|
|
7378
|
+
height = first.height;
|
|
7379
|
+
} else if (i === columns.length) {
|
|
7380
|
+
const last = columns[columns.length - 1].getBoundingClientRect();
|
|
7381
|
+
left = last.right - barThickness / 2;
|
|
7382
|
+
top = last.top;
|
|
7383
|
+
height = last.height;
|
|
7384
|
+
} else {
|
|
7385
|
+
const prev = columns[i - 1].getBoundingClientRect();
|
|
7386
|
+
const next = columns[i].getBoundingClientRect();
|
|
7387
|
+
left = (prev.right + next.left) / 2 - barThickness / 2;
|
|
7388
|
+
top = Math.min(prev.top, next.top);
|
|
7389
|
+
height = Math.max(prev.bottom, next.bottom) - top;
|
|
7390
|
+
}
|
|
7391
|
+
slots.push({
|
|
7392
|
+
insertIndex: i,
|
|
7393
|
+
columnIndex: i,
|
|
7394
|
+
left,
|
|
7395
|
+
top,
|
|
7396
|
+
width: barThickness,
|
|
7397
|
+
height: Math.max(height, 24),
|
|
7398
|
+
direction: "vertical"
|
|
7399
|
+
});
|
|
7400
|
+
}
|
|
7401
|
+
return slots;
|
|
7402
|
+
}
|
|
7403
|
+
function hitTestLinkDropSlot(clientX, clientY, draggedHrefKey) {
|
|
7404
|
+
const columns = listFooterColumns();
|
|
7405
|
+
let best = null;
|
|
7406
|
+
for (let c = 0; c < columns.length; c++) {
|
|
7407
|
+
const col = columns[c];
|
|
7408
|
+
const colRect = col.getBoundingClientRect();
|
|
7409
|
+
const inColX = clientX >= colRect.left - 24 && clientX <= colRect.right + 24;
|
|
7410
|
+
if (!inColX) continue;
|
|
7411
|
+
const slots = buildLinkDropSlots(col, c).filter((slot) => {
|
|
7412
|
+
const links = listFooterLinksInColumn(col);
|
|
7413
|
+
const fromIdx = links.findIndex(
|
|
7414
|
+
(el) => el.getAttribute("data-ohw-href-key") === draggedHrefKey
|
|
7415
|
+
);
|
|
7416
|
+
if (fromIdx < 0) return true;
|
|
7417
|
+
if (c === findColumnIndexForKey(draggedHrefKey) && (slot.insertIndex === fromIdx || slot.insertIndex === fromIdx + 1)) {
|
|
7418
|
+
return true;
|
|
7419
|
+
}
|
|
7420
|
+
return true;
|
|
7421
|
+
});
|
|
7422
|
+
for (const slot of slots) {
|
|
7423
|
+
const dist = slot.direction === "vertical" ? Math.abs(clientX - (slot.left + slot.width / 2)) : Math.abs(clientY - (slot.top + slot.height / 2));
|
|
7424
|
+
if (!best || dist < best.dist) best = { slot, dist };
|
|
7425
|
+
}
|
|
7426
|
+
}
|
|
7427
|
+
return best?.slot ?? null;
|
|
7428
|
+
}
|
|
7429
|
+
function findColumnIndexForKey(hrefKey) {
|
|
7430
|
+
const order = getFooterOrderFromDom();
|
|
7431
|
+
for (let c = 0; c < order.length; c++) {
|
|
7432
|
+
if (order[c].includes(hrefKey)) return c;
|
|
7433
|
+
}
|
|
7434
|
+
return -1;
|
|
7435
|
+
}
|
|
7436
|
+
function hitTestColumnDropSlot(clientX, _clientY) {
|
|
7437
|
+
const slots = buildColumnDropSlots();
|
|
7438
|
+
let best = null;
|
|
7439
|
+
for (const slot of slots) {
|
|
7440
|
+
const cx2 = slot.left + slot.width / 2;
|
|
7441
|
+
const dist = Math.abs(clientX - cx2);
|
|
7442
|
+
if (!best || dist < best.dist) best = { slot, dist };
|
|
7443
|
+
}
|
|
7444
|
+
return best?.slot ?? null;
|
|
7445
|
+
}
|
|
7446
|
+
|
|
7447
|
+
// src/lib/add-footer-column.ts
|
|
7448
|
+
function buildFooterColumnEditContentPatch(result) {
|
|
7449
|
+
return {
|
|
7450
|
+
[result.headingKey]: result.heading,
|
|
7451
|
+
[result.hrefKey]: result.href,
|
|
7452
|
+
[result.labelKey]: result.label,
|
|
7453
|
+
[FOOTER_ORDER_KEY]: JSON.stringify(result.order)
|
|
7454
|
+
};
|
|
7455
|
+
}
|
|
7456
|
+
function addFooterColumnWithPersist({
|
|
7457
|
+
postToParent: postToParent2
|
|
7458
|
+
}) {
|
|
7459
|
+
const result = insertFooterColumn();
|
|
7460
|
+
const patch = buildFooterColumnEditContentPatch(result);
|
|
7461
|
+
setStoredLinkHref(result.hrefKey, result.href);
|
|
7462
|
+
postToParent2({
|
|
7463
|
+
type: "ow:change",
|
|
7464
|
+
nodes: Object.entries(patch).map(([key, text]) => ({ key, text }))
|
|
7465
|
+
});
|
|
7466
|
+
postToParent2({ type: "ow:toast", title: "Item added", toastType: "success" });
|
|
7467
|
+
enforceLinkHrefs();
|
|
7468
|
+
return result;
|
|
7469
|
+
}
|
|
7470
|
+
|
|
7471
|
+
// src/lib/item-drag-interaction.ts
|
|
7472
|
+
function disableNativeHrefDrag(el) {
|
|
7473
|
+
if (el.draggable) el.draggable = false;
|
|
7474
|
+
if (el.getAttribute("draggable") !== "false") {
|
|
7475
|
+
el.setAttribute("draggable", "false");
|
|
7476
|
+
}
|
|
7477
|
+
}
|
|
7478
|
+
function clearTextSelection() {
|
|
7479
|
+
const sel = window.getSelection();
|
|
7480
|
+
if (sel && !sel.isCollapsed) sel.removeAllRanges();
|
|
7481
|
+
}
|
|
7482
|
+
function armItemPressDrag() {
|
|
7483
|
+
document.documentElement.setAttribute("data-ohw-footer-press-drag", "");
|
|
7484
|
+
}
|
|
7485
|
+
function lockItemDuringDrag() {
|
|
7486
|
+
document.documentElement.removeAttribute("data-ohw-footer-press-drag");
|
|
7487
|
+
document.documentElement.setAttribute("data-ohw-item-dragging", "");
|
|
7488
|
+
clearTextSelection();
|
|
7489
|
+
}
|
|
7490
|
+
function unlockItemDragInteraction() {
|
|
7491
|
+
const wasDragging = document.documentElement.hasAttribute("data-ohw-item-dragging");
|
|
7492
|
+
document.documentElement.removeAttribute("data-ohw-footer-press-drag");
|
|
7493
|
+
document.documentElement.removeAttribute("data-ohw-item-dragging");
|
|
7494
|
+
if (wasDragging) clearTextSelection();
|
|
7495
|
+
}
|
|
7496
|
+
var armFooterPressDrag = armItemPressDrag;
|
|
7497
|
+
var lockFooterDuringDrag = lockItemDuringDrag;
|
|
7498
|
+
var unlockFooterDragInteraction = unlockItemDragInteraction;
|
|
7499
|
+
|
|
7500
|
+
// src/lib/nav-dnd.ts
|
|
7501
|
+
function listReorderableNavItems() {
|
|
7502
|
+
return listNavbarItems().filter((el) => {
|
|
7503
|
+
const key = el.getAttribute("data-ohw-href-key");
|
|
7504
|
+
return isNavbarHrefKey(key) && !el.closest("[data-ohw-nav-children]");
|
|
7505
|
+
});
|
|
7506
|
+
}
|
|
7507
|
+
function listNavChildren(parentHrefKey) {
|
|
7508
|
+
const items = listNavbarItems();
|
|
7509
|
+
const parent = items.find((el) => el.getAttribute("data-ohw-href-key") === parentHrefKey);
|
|
7510
|
+
if (!parent) return [];
|
|
7511
|
+
const group = parent.closest("[data-ohw-nav-group]");
|
|
7512
|
+
const childrenRoot = group?.querySelector(":scope > [data-ohw-nav-children]");
|
|
7513
|
+
if (!childrenRoot) return [];
|
|
7514
|
+
return Array.from(childrenRoot.querySelectorAll(":scope > [data-ohw-href-key]")).filter(
|
|
7515
|
+
(el) => isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))
|
|
7516
|
+
);
|
|
7517
|
+
}
|
|
7518
|
+
function activeNavListContainer() {
|
|
7519
|
+
const desktop = getNavbarDesktopContainer();
|
|
7520
|
+
if (desktop && desktop.getClientRects().length > 0) {
|
|
7521
|
+
const style = window.getComputedStyle(desktop);
|
|
7522
|
+
if (style.display !== "none" && style.visibility !== "hidden") return desktop;
|
|
7523
|
+
}
|
|
7524
|
+
return getNavbarDrawerContainer();
|
|
7525
|
+
}
|
|
7526
|
+
function buildRootNavDropSlots() {
|
|
7527
|
+
const items = listReorderableNavItems();
|
|
7528
|
+
const slots = [];
|
|
7529
|
+
const barThickness = 3;
|
|
7530
|
+
if (items.length === 0) {
|
|
7531
|
+
const container = activeNavListContainer();
|
|
7532
|
+
if (!container) return slots;
|
|
7533
|
+
const rect = container.getBoundingClientRect();
|
|
7534
|
+
slots.push({
|
|
7535
|
+
insertIndex: 0,
|
|
7536
|
+
parentId: null,
|
|
7537
|
+
left: rect.left + rect.width / 2 - barThickness / 2,
|
|
7538
|
+
top: rect.top,
|
|
7539
|
+
width: barThickness,
|
|
7540
|
+
height: Math.max(rect.height, 24),
|
|
7541
|
+
direction: "vertical"
|
|
7542
|
+
});
|
|
7543
|
+
return slots;
|
|
7544
|
+
}
|
|
7545
|
+
const edgeGap = (() => {
|
|
7546
|
+
if (items.length < 2) return 32;
|
|
7547
|
+
const a = items[0].getBoundingClientRect();
|
|
7548
|
+
const b = items[1].getBoundingClientRect();
|
|
7549
|
+
return Math.max(0, b.left - a.right);
|
|
7550
|
+
})();
|
|
7551
|
+
for (let i = 0; i <= items.length; i++) {
|
|
7552
|
+
let left;
|
|
7553
|
+
let top;
|
|
7554
|
+
let height;
|
|
7555
|
+
if (i === 0) {
|
|
7556
|
+
const first = items[0].getBoundingClientRect();
|
|
7557
|
+
left = first.left - edgeGap / 2 - barThickness / 2;
|
|
7558
|
+
top = first.top;
|
|
7559
|
+
height = first.height;
|
|
7560
|
+
} else if (i === items.length) {
|
|
7561
|
+
const last = items[items.length - 1].getBoundingClientRect();
|
|
7562
|
+
const lastGap = items.length >= 2 ? Math.max(
|
|
7563
|
+
0,
|
|
7564
|
+
last.left - items[items.length - 2].getBoundingClientRect().right
|
|
7565
|
+
) : edgeGap;
|
|
7566
|
+
left = last.right + lastGap / 2 - barThickness / 2;
|
|
7567
|
+
top = last.top;
|
|
7568
|
+
height = last.height;
|
|
7569
|
+
} else {
|
|
7570
|
+
const prev = items[i - 1].getBoundingClientRect();
|
|
7571
|
+
const next = items[i].getBoundingClientRect();
|
|
7572
|
+
left = (prev.right + next.left) / 2 - barThickness / 2;
|
|
7573
|
+
top = Math.min(prev.top, next.top);
|
|
7574
|
+
height = Math.max(prev.bottom, next.bottom) - top;
|
|
7575
|
+
}
|
|
7576
|
+
slots.push({
|
|
7577
|
+
insertIndex: i,
|
|
7578
|
+
parentId: null,
|
|
7579
|
+
left,
|
|
7580
|
+
top,
|
|
7581
|
+
width: barThickness,
|
|
7582
|
+
height: Math.max(height, 24),
|
|
7583
|
+
direction: "vertical"
|
|
7584
|
+
});
|
|
7585
|
+
}
|
|
7586
|
+
return slots;
|
|
7587
|
+
}
|
|
7588
|
+
function buildChildNavDropSlots(parentHrefKey) {
|
|
7589
|
+
const children = listNavChildren(parentHrefKey);
|
|
7590
|
+
const slots = [];
|
|
7591
|
+
const barThickness = 3;
|
|
7592
|
+
if (children.length === 0) return slots;
|
|
7593
|
+
const edgeGap = (() => {
|
|
7594
|
+
if (children.length < 2) return 16;
|
|
7595
|
+
const a = children[0].getBoundingClientRect();
|
|
7596
|
+
const b = children[1].getBoundingClientRect();
|
|
7597
|
+
return Math.max(0, b.top - a.bottom);
|
|
7598
|
+
})();
|
|
7599
|
+
for (let i = 0; i <= children.length; i++) {
|
|
7600
|
+
let top;
|
|
7601
|
+
let width;
|
|
7602
|
+
let left;
|
|
7603
|
+
if (i === 0) {
|
|
7604
|
+
const first = children[0].getBoundingClientRect();
|
|
7605
|
+
top = first.top - edgeGap / 2 - barThickness / 2;
|
|
7606
|
+
left = first.left;
|
|
7607
|
+
width = first.width;
|
|
7608
|
+
} else if (i === children.length) {
|
|
7609
|
+
const last = children[children.length - 1].getBoundingClientRect();
|
|
7610
|
+
const lastGap = children.length >= 2 ? Math.max(
|
|
7611
|
+
0,
|
|
7612
|
+
last.top - children[children.length - 2].getBoundingClientRect().bottom
|
|
7613
|
+
) : edgeGap;
|
|
7614
|
+
top = last.bottom + lastGap / 2 - barThickness / 2;
|
|
7615
|
+
left = last.left;
|
|
7616
|
+
width = last.width;
|
|
7617
|
+
} else {
|
|
7618
|
+
const prev = children[i - 1].getBoundingClientRect();
|
|
7619
|
+
const next = children[i].getBoundingClientRect();
|
|
7620
|
+
top = (prev.bottom + next.top) / 2 - barThickness / 2;
|
|
7621
|
+
left = Math.min(prev.left, next.left);
|
|
7622
|
+
width = Math.max(prev.right, next.right) - left;
|
|
7623
|
+
}
|
|
7624
|
+
slots.push({
|
|
7625
|
+
insertIndex: i,
|
|
7626
|
+
parentId: parentHrefKey,
|
|
7627
|
+
left,
|
|
7628
|
+
top,
|
|
7629
|
+
width: Math.max(width, 40),
|
|
7630
|
+
height: barThickness,
|
|
7631
|
+
direction: "horizontal"
|
|
7632
|
+
});
|
|
7633
|
+
}
|
|
7634
|
+
return slots;
|
|
7635
|
+
}
|
|
7636
|
+
function buildAllNavDropSlots(draggedHrefKey) {
|
|
7637
|
+
const slots = [...buildRootNavDropSlots()];
|
|
7638
|
+
for (const item of listReorderableNavItems()) {
|
|
7639
|
+
const key = item.getAttribute("data-ohw-href-key");
|
|
7640
|
+
if (!key || key === draggedHrefKey) continue;
|
|
7641
|
+
const group = item.closest("[data-ohw-nav-group]");
|
|
7642
|
+
if (!group?.querySelector(":scope > [data-ohw-nav-children]")) continue;
|
|
7643
|
+
slots.push(...buildChildNavDropSlots(key));
|
|
7644
|
+
}
|
|
7645
|
+
const dragged = listNavbarItems().find((el) => el.getAttribute("data-ohw-href-key") === draggedHrefKey);
|
|
7646
|
+
const parentGroup = dragged?.closest("[data-ohw-nav-children]")?.closest("[data-ohw-nav-group]");
|
|
7647
|
+
const parentTrigger = parentGroup?.querySelector(":scope > [data-ohw-href-key]");
|
|
7648
|
+
const parentKey = parentTrigger?.getAttribute("data-ohw-href-key");
|
|
7649
|
+
if (parentKey && isNavbarHrefKey(parentKey)) {
|
|
7650
|
+
const existing = slots.some((s) => s.parentId === parentKey);
|
|
7651
|
+
if (!existing) slots.push(...buildChildNavDropSlots(parentKey));
|
|
7652
|
+
}
|
|
7653
|
+
return slots;
|
|
7654
|
+
}
|
|
7655
|
+
function hitTestNavDropSlot(clientX, clientY, draggedHrefKey) {
|
|
7656
|
+
const slots = buildAllNavDropSlots(draggedHrefKey);
|
|
7657
|
+
let best = null;
|
|
7658
|
+
for (const slot of slots) {
|
|
7659
|
+
const cx2 = slot.left + slot.width / 2;
|
|
7660
|
+
const cy = slot.top + slot.height / 2;
|
|
7661
|
+
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;
|
|
7662
|
+
if (!best || dist < best.dist) best = { slot, dist };
|
|
7663
|
+
}
|
|
7664
|
+
return best?.slot ?? null;
|
|
7665
|
+
}
|
|
7666
|
+
|
|
7667
|
+
// src/useNavItemDrag.ts
|
|
7668
|
+
var import_react8 = require("react");
|
|
7669
|
+
function useNavItemDrag({
|
|
7670
|
+
isEditMode,
|
|
7671
|
+
editContentRef,
|
|
7672
|
+
selectedElRef,
|
|
7673
|
+
activeElRef,
|
|
7674
|
+
footerDragRef,
|
|
7675
|
+
suppressNextClickRef,
|
|
7676
|
+
suppressClickUntilRef,
|
|
7677
|
+
siblingHintElRef,
|
|
7678
|
+
postToParentRef,
|
|
7679
|
+
deselectRef,
|
|
7680
|
+
selectRef,
|
|
7681
|
+
deactivateRef,
|
|
7682
|
+
setLinkPopover,
|
|
7683
|
+
linkPopoverOpenRef,
|
|
7684
|
+
setIsItemDragging,
|
|
7685
|
+
setDraggedItemRect,
|
|
7686
|
+
setSiblingHintRect,
|
|
7687
|
+
setSiblingHintRects,
|
|
7688
|
+
setToolbarRect,
|
|
7689
|
+
getNavigationItemAnchor: getNavigationItemAnchor2,
|
|
7690
|
+
isDragHandleDisabled: isDragHandleDisabled2,
|
|
7691
|
+
isNavbarButton: isNavbarButton3
|
|
7692
|
+
}) {
|
|
7693
|
+
const navDragRef = (0, import_react8.useRef)(null);
|
|
7694
|
+
const [navDropSlots, setNavDropSlots] = (0, import_react8.useState)([]);
|
|
7695
|
+
const [activeNavDropIndex, setActiveNavDropIndex] = (0, import_react8.useState)(null);
|
|
7696
|
+
const navPointerDragRef = (0, import_react8.useRef)(null);
|
|
7697
|
+
const clearNavDragVisuals = (0, import_react8.useCallback)(() => {
|
|
7698
|
+
navDragRef.current = null;
|
|
7699
|
+
setNavDropSlots([]);
|
|
7700
|
+
setActiveNavDropIndex(null);
|
|
7701
|
+
setDraggedItemRect(null);
|
|
7702
|
+
setSiblingHintRects([]);
|
|
7703
|
+
setIsItemDragging(false);
|
|
7704
|
+
unlockItemDragInteraction();
|
|
7705
|
+
}, [setDraggedItemRect, setIsItemDragging, setSiblingHintRects]);
|
|
7706
|
+
const refreshNavDragVisuals = (0, import_react8.useCallback)(
|
|
7707
|
+
(session, activeSlot, clientX, clientY) => {
|
|
7708
|
+
setDraggedItemRect(session.draggedEl.getBoundingClientRect());
|
|
7709
|
+
if (typeof clientX === "number" && typeof clientY === "number") {
|
|
7710
|
+
session.lastClientX = clientX;
|
|
7711
|
+
session.lastClientY = clientY;
|
|
7712
|
+
}
|
|
7713
|
+
session.activeSlot = activeSlot;
|
|
7714
|
+
setSiblingHintRects([]);
|
|
7715
|
+
const slots = buildAllNavDropSlots(session.hrefKey);
|
|
7716
|
+
setNavDropSlots(slots);
|
|
7717
|
+
const activeIdx = activeSlot ? slots.findIndex(
|
|
7718
|
+
(s) => s.parentId === activeSlot.parentId && s.insertIndex === activeSlot.insertIndex
|
|
7719
|
+
) : -1;
|
|
7720
|
+
setActiveNavDropIndex(activeIdx >= 0 ? activeIdx : null);
|
|
7721
|
+
},
|
|
7722
|
+
[setDraggedItemRect, setSiblingHintRects]
|
|
7723
|
+
);
|
|
7724
|
+
const refreshNavDragVisualsRef = (0, import_react8.useRef)(refreshNavDragVisuals);
|
|
7725
|
+
refreshNavDragVisualsRef.current = refreshNavDragVisuals;
|
|
7726
|
+
const commitNavDragRef = (0, import_react8.useRef)(() => {
|
|
7727
|
+
});
|
|
7728
|
+
const beginNavDragRef = (0, import_react8.useRef)(() => {
|
|
7729
|
+
});
|
|
7730
|
+
const beginNavDrag = (0, import_react8.useCallback)(
|
|
7731
|
+
(session) => {
|
|
7732
|
+
const rect = session.draggedEl.getBoundingClientRect();
|
|
7733
|
+
session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
|
|
7734
|
+
session.lastClientY = session.lastClientY || rect.top + rect.height / 2;
|
|
7735
|
+
session.activeSlot = session.activeSlot ?? null;
|
|
7736
|
+
navDragRef.current = session;
|
|
7737
|
+
setIsItemDragging(true);
|
|
7738
|
+
lockItemDuringDrag();
|
|
7739
|
+
siblingHintElRef.current = null;
|
|
7740
|
+
setSiblingHintRect(null);
|
|
7741
|
+
if (session.wasSelected && selectedElRef.current === session.draggedEl) {
|
|
7742
|
+
setToolbarRect(rect);
|
|
7743
|
+
}
|
|
7744
|
+
const initialSlot = hitTestNavDropSlot(session.lastClientX, session.lastClientY, session.hrefKey);
|
|
7745
|
+
refreshNavDragVisuals(session, initialSlot, session.lastClientX, session.lastClientY);
|
|
7746
|
+
},
|
|
7747
|
+
[
|
|
7748
|
+
refreshNavDragVisuals,
|
|
7749
|
+
selectedElRef,
|
|
7750
|
+
setIsItemDragging,
|
|
7751
|
+
setSiblingHintRect,
|
|
7752
|
+
setToolbarRect,
|
|
7753
|
+
siblingHintElRef
|
|
7754
|
+
]
|
|
7755
|
+
);
|
|
7756
|
+
beginNavDragRef.current = beginNavDrag;
|
|
7757
|
+
const commitNavDrag = (0, import_react8.useCallback)(
|
|
7758
|
+
(clientX, clientY) => {
|
|
7759
|
+
const session = navDragRef.current;
|
|
7760
|
+
if (!session) {
|
|
7761
|
+
clearNavDragVisuals();
|
|
7762
|
+
return;
|
|
7763
|
+
}
|
|
7764
|
+
const x = typeof clientX === "number" && (clientX !== 0 || clientY !== 0) ? clientX : session.lastClientX;
|
|
7765
|
+
const y = typeof clientY === "number" && (clientX !== 0 || clientY !== 0) ? clientY : session.lastClientY;
|
|
7766
|
+
const slot = session.activeSlot ?? hitTestNavDropSlot(x, y, session.hrefKey);
|
|
7767
|
+
const planned = slot != null ? planNavItemMove(session.hrefKey, slot.parentId, slot.insertIndex) : null;
|
|
7768
|
+
const wasSelected = session.wasSelected;
|
|
7769
|
+
const hrefKey = session.hrefKey;
|
|
7770
|
+
const applySelectionAfterDrop = () => {
|
|
7771
|
+
if (!wasSelected) {
|
|
7772
|
+
deselectRef.current();
|
|
7773
|
+
return;
|
|
7774
|
+
}
|
|
7775
|
+
const desktop = document.querySelector("[data-ohw-nav-container]");
|
|
7776
|
+
const drawer = document.querySelector("[data-ohw-nav-drawer]");
|
|
7777
|
+
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)}"]`);
|
|
7778
|
+
if (link) {
|
|
7779
|
+
selectRef.current(link);
|
|
7780
|
+
return;
|
|
7781
|
+
}
|
|
7782
|
+
deselectRef.current();
|
|
7783
|
+
};
|
|
7784
|
+
if (planned) {
|
|
7785
|
+
editContentRef.current = {
|
|
7786
|
+
...editContentRef.current,
|
|
7787
|
+
[NAV_ORDER_KEY]: planned.orderJson
|
|
7788
|
+
};
|
|
7789
|
+
applyNavForest(planned.forest);
|
|
7790
|
+
document.querySelectorAll(
|
|
7791
|
+
"nav [data-ohw-href-key], [data-ohw-nav-container] [data-ohw-href-key], [data-ohw-nav-drawer] [data-ohw-href-key]"
|
|
7792
|
+
).forEach((el) => {
|
|
7793
|
+
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
7794
|
+
disableNativeHrefDrag(el);
|
|
7795
|
+
}
|
|
7796
|
+
});
|
|
7797
|
+
postToParentRef.current({
|
|
7798
|
+
type: "ow:change",
|
|
7799
|
+
nodes: [{ key: NAV_ORDER_KEY, text: planned.orderJson }]
|
|
7800
|
+
});
|
|
7801
|
+
applySelectionAfterDrop();
|
|
7802
|
+
clearNavDragVisuals();
|
|
7803
|
+
requestAnimationFrame(() => {
|
|
7804
|
+
if (editContentRef.current[NAV_ORDER_KEY] === planned.orderJson) {
|
|
7805
|
+
applyNavForest(planned.forest);
|
|
7806
|
+
}
|
|
7807
|
+
applySelectionAfterDrop();
|
|
7808
|
+
requestAnimationFrame(applySelectionAfterDrop);
|
|
7809
|
+
});
|
|
7810
|
+
return;
|
|
7811
|
+
}
|
|
7812
|
+
applySelectionAfterDrop();
|
|
7813
|
+
clearNavDragVisuals();
|
|
7814
|
+
},
|
|
7815
|
+
[clearNavDragVisuals, deselectRef, editContentRef, postToParentRef, selectRef]
|
|
7816
|
+
);
|
|
7817
|
+
commitNavDragRef.current = commitNavDrag;
|
|
7818
|
+
const startNavLinkDrag = (0, import_react8.useCallback)(
|
|
7819
|
+
(anchor, clientX, clientY, wasSelected) => {
|
|
7820
|
+
if (footerDragRef.current) return false;
|
|
7821
|
+
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
7822
|
+
if (!hrefKey || !isNavbarHrefKey(hrefKey)) return false;
|
|
7823
|
+
if (isNavbarButton3(anchor) || isDragHandleDisabled2(anchor)) return false;
|
|
7824
|
+
beginNavDrag({
|
|
7825
|
+
hrefKey,
|
|
7826
|
+
wasSelected,
|
|
7827
|
+
draggedEl: anchor,
|
|
7828
|
+
lastClientX: clientX,
|
|
7829
|
+
lastClientY: clientY,
|
|
7830
|
+
activeSlot: null
|
|
7831
|
+
});
|
|
7832
|
+
return true;
|
|
7833
|
+
},
|
|
7834
|
+
[beginNavDrag, footerDragRef, isDragHandleDisabled2, isNavbarButton3]
|
|
7835
|
+
);
|
|
7836
|
+
const onNavDragOver = (0, import_react8.useCallback)(
|
|
7837
|
+
(e) => {
|
|
7838
|
+
const session = navDragRef.current;
|
|
7839
|
+
if (!session) return false;
|
|
7840
|
+
e.preventDefault();
|
|
7841
|
+
if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
|
|
7842
|
+
const slot = hitTestNavDropSlot(e.clientX, e.clientY, session.hrefKey);
|
|
7843
|
+
refreshNavDragVisualsRef.current(session, slot, e.clientX, e.clientY);
|
|
7844
|
+
return true;
|
|
7845
|
+
},
|
|
7846
|
+
[]
|
|
7847
|
+
);
|
|
7848
|
+
(0, import_react8.useEffect)(() => {
|
|
7849
|
+
if (!isEditMode) return;
|
|
7850
|
+
const THRESHOLD = 10;
|
|
7851
|
+
const resolveWasSelected = (el) => {
|
|
7852
|
+
if (selectedElRef.current === el) return true;
|
|
7853
|
+
const activeAnchor = activeElRef.current ? getNavigationItemAnchor2(activeElRef.current) : null;
|
|
7854
|
+
return activeAnchor === el;
|
|
7855
|
+
};
|
|
7856
|
+
const onPointerDown = (e) => {
|
|
7857
|
+
if (e.button !== 0) return;
|
|
7858
|
+
if (navDragRef.current || footerDragRef.current) return;
|
|
7859
|
+
const target = e.target;
|
|
7860
|
+
if (!target) return;
|
|
7861
|
+
if (target.closest(
|
|
7862
|
+
'[data-ohw-drag-handle-container], [data-slot="drag-handle"], [data-ohw-toolbar], [data-ohw-item-toolbar-anchor], [data-ohw-link-popover-root]'
|
|
7863
|
+
)) {
|
|
7864
|
+
return;
|
|
7865
|
+
}
|
|
7866
|
+
if (target.closest("[data-ohw-item-drag-surface]")) return;
|
|
7867
|
+
const anchor = getNavigationItemAnchor2(target);
|
|
7868
|
+
const hrefKey = anchor?.getAttribute("data-ohw-href-key") ?? null;
|
|
7869
|
+
if (!anchor || !isNavbarHrefKey(hrefKey)) return;
|
|
7870
|
+
if (isNavbarButton3(anchor) || isDragHandleDisabled2(anchor)) return;
|
|
7871
|
+
navPointerDragRef.current = {
|
|
7872
|
+
el: anchor,
|
|
7873
|
+
startX: e.clientX,
|
|
7874
|
+
startY: e.clientY,
|
|
7875
|
+
pointerId: e.pointerId,
|
|
7876
|
+
wasSelected: resolveWasSelected(anchor),
|
|
7877
|
+
started: false
|
|
7878
|
+
};
|
|
7879
|
+
};
|
|
7880
|
+
const onPointerMove = (e) => {
|
|
7881
|
+
const pending = navPointerDragRef.current;
|
|
7882
|
+
if (!pending) return;
|
|
7883
|
+
if (pending.started) {
|
|
7884
|
+
e.preventDefault();
|
|
7885
|
+
clearTextSelection();
|
|
7886
|
+
const session = navDragRef.current;
|
|
7887
|
+
if (!session) return;
|
|
7888
|
+
const slot = hitTestNavDropSlot(e.clientX, e.clientY, session.hrefKey);
|
|
7889
|
+
refreshNavDragVisualsRef.current(session, slot, e.clientX, e.clientY);
|
|
7890
|
+
return;
|
|
7891
|
+
}
|
|
7892
|
+
const dx = e.clientX - pending.startX;
|
|
7893
|
+
const dy = e.clientY - pending.startY;
|
|
7894
|
+
if (dx * dx + dy * dy < THRESHOLD * THRESHOLD) return;
|
|
7895
|
+
e.preventDefault();
|
|
7896
|
+
pending.started = true;
|
|
7897
|
+
armItemPressDrag();
|
|
7898
|
+
clearTextSelection();
|
|
7899
|
+
try {
|
|
7900
|
+
document.body.setPointerCapture(pending.pointerId);
|
|
7901
|
+
} catch {
|
|
7902
|
+
}
|
|
7903
|
+
if (linkPopoverOpenRef.current) setLinkPopover(null);
|
|
7904
|
+
if (activeElRef.current) deactivateRef.current();
|
|
7905
|
+
const key = pending.el.getAttribute("data-ohw-href-key");
|
|
7906
|
+
if (!key) return;
|
|
7907
|
+
beginNavDragRef.current({
|
|
7908
|
+
hrefKey: key,
|
|
7909
|
+
wasSelected: pending.wasSelected,
|
|
7910
|
+
draggedEl: pending.el,
|
|
7911
|
+
lastClientX: e.clientX,
|
|
7912
|
+
lastClientY: e.clientY,
|
|
7913
|
+
activeSlot: null
|
|
7914
|
+
});
|
|
7915
|
+
};
|
|
7916
|
+
const endPointerDrag = (e) => {
|
|
7917
|
+
const pending = navPointerDragRef.current;
|
|
7918
|
+
navPointerDragRef.current = null;
|
|
7919
|
+
try {
|
|
7920
|
+
if (document.body.hasPointerCapture(e.pointerId)) {
|
|
7921
|
+
document.body.releasePointerCapture(e.pointerId);
|
|
7922
|
+
}
|
|
7923
|
+
} catch {
|
|
7924
|
+
}
|
|
7925
|
+
if (!pending) return;
|
|
7926
|
+
if (!pending.started) {
|
|
7927
|
+
unlockItemDragInteraction();
|
|
7928
|
+
return;
|
|
7929
|
+
}
|
|
7930
|
+
suppressNextClickRef.current = true;
|
|
7931
|
+
suppressClickUntilRef.current = Date.now() + 500;
|
|
7932
|
+
commitNavDragRef.current(e.clientX, e.clientY);
|
|
7933
|
+
};
|
|
7934
|
+
const blockSelectStart = (e) => {
|
|
7935
|
+
if (navDragRef.current || navPointerDragRef.current?.started || document.documentElement.hasAttribute("data-ohw-footer-press-drag")) {
|
|
7936
|
+
e.preventDefault();
|
|
7937
|
+
}
|
|
7938
|
+
};
|
|
7939
|
+
const onDragEnd = () => {
|
|
7940
|
+
if (!navDragRef.current) return;
|
|
7941
|
+
suppressNextClickRef.current = true;
|
|
7942
|
+
suppressClickUntilRef.current = Date.now() + 500;
|
|
7943
|
+
commitNavDragRef.current();
|
|
7944
|
+
};
|
|
7945
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
7946
|
+
document.addEventListener("pointermove", onPointerMove, true);
|
|
7947
|
+
document.addEventListener("pointerup", endPointerDrag, true);
|
|
7948
|
+
document.addEventListener("pointercancel", endPointerDrag, true);
|
|
7949
|
+
document.addEventListener("selectstart", blockSelectStart, true);
|
|
7950
|
+
document.addEventListener("dragend", onDragEnd, true);
|
|
7951
|
+
return () => {
|
|
7952
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
7953
|
+
document.removeEventListener("pointermove", onPointerMove, true);
|
|
7954
|
+
document.removeEventListener("pointerup", endPointerDrag, true);
|
|
7955
|
+
document.removeEventListener("pointercancel", endPointerDrag, true);
|
|
7956
|
+
document.removeEventListener("selectstart", blockSelectStart, true);
|
|
7957
|
+
document.removeEventListener("dragend", onDragEnd, true);
|
|
7958
|
+
unlockItemDragInteraction();
|
|
7959
|
+
};
|
|
7960
|
+
}, [
|
|
7961
|
+
activeElRef,
|
|
7962
|
+
deactivateRef,
|
|
7963
|
+
footerDragRef,
|
|
7964
|
+
getNavigationItemAnchor2,
|
|
7965
|
+
isDragHandleDisabled2,
|
|
7966
|
+
isEditMode,
|
|
7967
|
+
isNavbarButton3,
|
|
7968
|
+
linkPopoverOpenRef,
|
|
7969
|
+
selectedElRef,
|
|
7970
|
+
setLinkPopover,
|
|
7971
|
+
suppressNextClickRef
|
|
7972
|
+
]);
|
|
7973
|
+
const armNavPressFromChrome = (0, import_react8.useCallback)(
|
|
7974
|
+
(selected, clientX, clientY, pointerId) => {
|
|
7975
|
+
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
7976
|
+
if (!hrefKey || !isNavbarHrefKey(hrefKey)) return false;
|
|
7977
|
+
if (isNavbarButton3(selected) || isDragHandleDisabled2(selected)) return false;
|
|
7978
|
+
navPointerDragRef.current = {
|
|
7979
|
+
el: selected,
|
|
7980
|
+
startX: clientX,
|
|
7981
|
+
startY: clientY,
|
|
7982
|
+
pointerId,
|
|
7983
|
+
wasSelected: true,
|
|
7984
|
+
started: false
|
|
7985
|
+
};
|
|
7986
|
+
return true;
|
|
7987
|
+
},
|
|
7988
|
+
[isDragHandleDisabled2, isNavbarButton3]
|
|
7989
|
+
);
|
|
7990
|
+
return {
|
|
7991
|
+
navDragRef,
|
|
7992
|
+
navDropSlots,
|
|
7993
|
+
activeNavDropIndex,
|
|
7994
|
+
startNavLinkDrag,
|
|
7995
|
+
commitNavDrag,
|
|
7996
|
+
onNavDragOver,
|
|
7997
|
+
armNavPressFromChrome,
|
|
7998
|
+
clearNavDragVisuals,
|
|
7999
|
+
refreshNavDragVisualsRef
|
|
8000
|
+
};
|
|
8001
|
+
}
|
|
8002
|
+
|
|
8003
|
+
// src/ui/footer-container-chrome.tsx
|
|
8004
|
+
var import_lucide_react10 = require("lucide-react");
|
|
8005
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
8006
|
+
function FooterContainerChrome({ rect, onAdd }) {
|
|
8007
|
+
const chromeGap = 6;
|
|
8008
|
+
const buttonMargin = 7;
|
|
8009
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
8010
|
+
"div",
|
|
8011
|
+
{
|
|
8012
|
+
"data-ohw-footer-container-chrome": "",
|
|
8013
|
+
"data-ohw-bridge": "",
|
|
8014
|
+
className: "pointer-events-none fixed z-[2147483647]",
|
|
8015
|
+
style: {
|
|
8016
|
+
top: rect.top - chromeGap,
|
|
8017
|
+
left: rect.left - chromeGap,
|
|
8018
|
+
width: rect.width + chromeGap * 2,
|
|
8019
|
+
height: rect.height + chromeGap * 2
|
|
8020
|
+
},
|
|
8021
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Tooltip, { children: [
|
|
8022
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
8023
|
+
"button",
|
|
8024
|
+
{
|
|
8025
|
+
type: "button",
|
|
8026
|
+
"data-ohw-footer-add-button": "",
|
|
8027
|
+
className: "pointer-events-auto absolute left-1/2 flex size-7 -translate-x-1/2 -translate-y-full items-center justify-center rounded-[10px] border border-border bg-background p-0.5 shadow-sm transition-colors hover:bg-muted/80",
|
|
8028
|
+
style: { top: chromeGap - buttonMargin },
|
|
8029
|
+
"aria-label": "Add item",
|
|
8030
|
+
onMouseDown: (e) => {
|
|
8031
|
+
e.preventDefault();
|
|
8032
|
+
e.stopPropagation();
|
|
8033
|
+
},
|
|
8034
|
+
onClick: (e) => {
|
|
8035
|
+
e.preventDefault();
|
|
8036
|
+
e.stopPropagation();
|
|
8037
|
+
onAdd();
|
|
8038
|
+
},
|
|
8039
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
8040
|
+
}
|
|
8041
|
+
) }),
|
|
8042
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: "Add item" })
|
|
8043
|
+
] })
|
|
8044
|
+
}
|
|
8045
|
+
) });
|
|
8046
|
+
}
|
|
8047
|
+
|
|
8048
|
+
// src/ui/navbar-container-chrome.tsx
|
|
8049
|
+
var import_lucide_react11 = require("lucide-react");
|
|
8050
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
8051
|
+
function NavbarContainerChrome({
|
|
8052
|
+
rect,
|
|
8053
|
+
onAdd
|
|
8054
|
+
}) {
|
|
8055
|
+
const chromeGap = 6;
|
|
8056
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
8057
|
+
"div",
|
|
8058
|
+
{
|
|
8059
|
+
"data-ohw-navbar-container-chrome": "",
|
|
8060
|
+
"data-ohw-bridge": "",
|
|
8061
|
+
className: "pointer-events-none fixed z-[2147483647]",
|
|
8062
|
+
style: {
|
|
8063
|
+
top: rect.top - chromeGap,
|
|
8064
|
+
left: rect.left - chromeGap,
|
|
8065
|
+
width: rect.width + chromeGap * 2,
|
|
8066
|
+
height: rect.height + chromeGap * 2
|
|
8067
|
+
},
|
|
8068
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
8069
|
+
"button",
|
|
8070
|
+
{
|
|
8071
|
+
type: "button",
|
|
8072
|
+
"data-ohw-navbar-add-button": "",
|
|
8073
|
+
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",
|
|
8074
|
+
style: { top: "70%" },
|
|
8075
|
+
"aria-label": "Add item",
|
|
8076
|
+
onMouseDown: (e) => {
|
|
8077
|
+
e.preventDefault();
|
|
8078
|
+
e.stopPropagation();
|
|
8079
|
+
},
|
|
8080
|
+
onClick: (e) => {
|
|
8081
|
+
e.preventDefault();
|
|
8082
|
+
e.stopPropagation();
|
|
8083
|
+
onAdd();
|
|
8084
|
+
},
|
|
8085
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react11.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
8086
|
+
}
|
|
8087
|
+
)
|
|
8088
|
+
}
|
|
8089
|
+
);
|
|
8090
|
+
}
|
|
8091
|
+
|
|
8092
|
+
// src/ui/drop-indicator.tsx
|
|
8093
|
+
var React10 = __toESM(require("react"), 1);
|
|
8094
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
8095
|
+
var dropIndicatorVariants = cva(
|
|
8096
|
+
"ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
|
|
8097
|
+
{
|
|
8098
|
+
variants: {
|
|
8099
|
+
direction: {
|
|
8100
|
+
vertical: "h-6 w-[3px]",
|
|
8101
|
+
horizontal: "h-[3px] w-[200px]"
|
|
8102
|
+
},
|
|
8103
|
+
state: {
|
|
8104
|
+
default: "opacity-0",
|
|
8105
|
+
hover: "opacity-100",
|
|
8106
|
+
dragIdle: "opacity-40",
|
|
8107
|
+
dragActive: "opacity-100"
|
|
8108
|
+
}
|
|
8109
|
+
},
|
|
8110
|
+
defaultVariants: {
|
|
8111
|
+
direction: "vertical",
|
|
8112
|
+
state: "default"
|
|
8113
|
+
}
|
|
8114
|
+
}
|
|
8115
|
+
);
|
|
8116
|
+
var DropIndicator = React10.forwardRef(
|
|
8117
|
+
({ className, direction, state, ...props }, ref) => {
|
|
8118
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
8119
|
+
"div",
|
|
8120
|
+
{
|
|
8121
|
+
ref,
|
|
8122
|
+
"data-slot": "drop-indicator",
|
|
8123
|
+
"data-direction": direction ?? "vertical",
|
|
8124
|
+
"data-state": state ?? "default",
|
|
8125
|
+
"aria-hidden": "true",
|
|
8126
|
+
className: cn(dropIndicatorVariants({ direction, state }), className),
|
|
8127
|
+
...props
|
|
8128
|
+
}
|
|
8129
|
+
);
|
|
8130
|
+
}
|
|
8131
|
+
);
|
|
8132
|
+
DropIndicator.displayName = "DropIndicator";
|
|
8133
|
+
|
|
8134
|
+
// src/ui/badge.tsx
|
|
8135
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
8136
|
+
var badgeVariants = cva(
|
|
8137
|
+
"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",
|
|
8138
|
+
{
|
|
8139
|
+
variants: {
|
|
8140
|
+
variant: {
|
|
8141
|
+
default: "border-transparent bg-primary text-primary-foreground",
|
|
8142
|
+
secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
8143
|
+
destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
|
|
8144
|
+
outline: "text-foreground"
|
|
8145
|
+
}
|
|
8146
|
+
},
|
|
8147
|
+
defaultVariants: {
|
|
8148
|
+
variant: "default"
|
|
8149
|
+
}
|
|
8150
|
+
}
|
|
8151
|
+
);
|
|
8152
|
+
function Badge({ className, variant, ...props }) {
|
|
8153
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
8154
|
+
}
|
|
8155
|
+
|
|
8156
|
+
// src/OhhwellsBridge.tsx
|
|
8157
|
+
var import_lucide_react12 = require("lucide-react");
|
|
8158
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
8159
|
+
var PRIMARY2 = "#0885FE";
|
|
8160
|
+
var IMAGE_FADE_MS = 300;
|
|
8161
|
+
function runOpacityFade(el, onDone) {
|
|
8162
|
+
const anim = el.animate([{ opacity: 0 }, { opacity: 1 }], {
|
|
8163
|
+
duration: IMAGE_FADE_MS,
|
|
8164
|
+
easing: "ease",
|
|
8165
|
+
fill: "forwards"
|
|
8166
|
+
});
|
|
8167
|
+
let finished = false;
|
|
8168
|
+
const finish = () => {
|
|
8169
|
+
if (finished) return;
|
|
8170
|
+
finished = true;
|
|
8171
|
+
anim.cancel();
|
|
8172
|
+
el.style.opacity = "";
|
|
8173
|
+
onDone();
|
|
8174
|
+
};
|
|
8175
|
+
anim.finished.then(finish).catch(finish);
|
|
8176
|
+
window.setTimeout(finish, IMAGE_FADE_MS + 100);
|
|
8177
|
+
}
|
|
8178
|
+
function fadeInImageElement(img, onReady) {
|
|
8179
|
+
onReady();
|
|
8180
|
+
img.style.opacity = "0";
|
|
8181
|
+
runOpacityFade(img, () => {
|
|
8182
|
+
img.style.opacity = "";
|
|
8183
|
+
});
|
|
8184
|
+
}
|
|
8185
|
+
function applyEditableImageSrc(img, url) {
|
|
8186
|
+
img.removeAttribute("srcset");
|
|
8187
|
+
img.removeAttribute("sizes");
|
|
8188
|
+
img.src = url;
|
|
8189
|
+
}
|
|
8190
|
+
function fadeInBgImage(el, url, onReady) {
|
|
8191
|
+
const prevPos = el.style.position;
|
|
8192
|
+
if (!prevPos || prevPos === "static") el.style.position = "relative";
|
|
8193
|
+
const layer = document.createElement("div");
|
|
8194
|
+
layer.setAttribute("data-ohw-bg-fade-layer", "");
|
|
8195
|
+
Object.assign(layer.style, {
|
|
8196
|
+
position: "absolute",
|
|
8197
|
+
inset: "0",
|
|
8198
|
+
zIndex: "0",
|
|
8199
|
+
backgroundImage: `url('${url}')`,
|
|
8200
|
+
backgroundSize: "cover",
|
|
8201
|
+
backgroundPosition: "center",
|
|
8202
|
+
backgroundRepeat: "no-repeat",
|
|
8203
|
+
opacity: "0",
|
|
8204
|
+
pointerEvents: "none"
|
|
8205
|
+
});
|
|
8206
|
+
el.prepend(layer);
|
|
8207
|
+
onReady();
|
|
8208
|
+
runOpacityFade(layer, () => {
|
|
8209
|
+
el.style.backgroundImage = `url('${url}')`;
|
|
8210
|
+
layer.remove();
|
|
8211
|
+
if (!prevPos || prevPos === "static") el.style.position = prevPos;
|
|
8212
|
+
});
|
|
8213
|
+
}
|
|
8214
|
+
function getSectionsTracker() {
|
|
8215
|
+
let el = document.querySelector("[data-ohw-sections-tracker]");
|
|
8216
|
+
if (!el) {
|
|
8217
|
+
el = document.createElement("div");
|
|
8218
|
+
el.setAttribute("data-ohw-sections-tracker", "");
|
|
8219
|
+
el.style.display = "none";
|
|
8220
|
+
document.body.appendChild(el);
|
|
8221
|
+
}
|
|
8222
|
+
return el;
|
|
8223
|
+
}
|
|
8224
|
+
function updateSectionScheduleId(insertAfter, scheduleId) {
|
|
8225
|
+
const tracker = getSectionsTracker();
|
|
8226
|
+
let sections = [];
|
|
8227
|
+
try {
|
|
8228
|
+
sections = JSON.parse(tracker.textContent || "[]");
|
|
8229
|
+
} catch {
|
|
6697
8230
|
}
|
|
6698
8231
|
const currentPath = window.location.pathname;
|
|
6699
8232
|
const updated = sections.map((s) => {
|
|
@@ -6801,7 +8334,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
6801
8334
|
const root = (0, import_client.createRoot)(container);
|
|
6802
8335
|
(0, import_react_dom2.flushSync)(() => {
|
|
6803
8336
|
root.render(
|
|
6804
|
-
/* @__PURE__ */ (0,
|
|
8337
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
6805
8338
|
SchedulingWidget,
|
|
6806
8339
|
{
|
|
6807
8340
|
notifyOnConnect,
|
|
@@ -6876,7 +8409,7 @@ function syncNavigationDragCursorAttrs() {
|
|
|
6876
8409
|
el.setAttribute("data-ohw-can-drag", "");
|
|
6877
8410
|
});
|
|
6878
8411
|
}
|
|
6879
|
-
function collectEditableNodes() {
|
|
8412
|
+
function collectEditableNodes(extraContent) {
|
|
6880
8413
|
const nodes = Array.from(document.querySelectorAll("[data-ohw-editable]")).map((el) => {
|
|
6881
8414
|
if (el.dataset.ohwEditable === "image") {
|
|
6882
8415
|
const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
|
|
@@ -6904,6 +8437,14 @@ function collectEditableNodes() {
|
|
|
6904
8437
|
if (!key) return;
|
|
6905
8438
|
nodes.push({ key, type: "link", text: getLinkHref2(el) });
|
|
6906
8439
|
});
|
|
8440
|
+
if (extraContent) {
|
|
8441
|
+
for (const key of [NAV_ORDER_KEY, FOOTER_ORDER_KEY, NAV_COUNT_KEY]) {
|
|
8442
|
+
const text = extraContent[key];
|
|
8443
|
+
if (typeof text === "string" && text.length > 0) {
|
|
8444
|
+
nodes.push({ key, type: "meta", text });
|
|
8445
|
+
}
|
|
8446
|
+
}
|
|
8447
|
+
}
|
|
6907
8448
|
document.querySelectorAll('[data-ohw-editable="video"]').forEach((el) => {
|
|
6908
8449
|
const key = el.dataset.ohwKey ?? "";
|
|
6909
8450
|
const video = getVideoEl(el);
|
|
@@ -6994,7 +8535,7 @@ function applyLinkByKey(key, val) {
|
|
|
6994
8535
|
}
|
|
6995
8536
|
function isInsideLinkEditor(target) {
|
|
6996
8537
|
return Boolean(
|
|
6997
|
-
target.closest("[data-ohw-link-popover-root]") || target.closest("[data-ohw-link-modal-root]") || target.closest("[data-ohw-link-page-dropdown]") || target.closest("[data-ohw-section-picker]") || target.closest("[data-ohw-navbar-container-chrome]") || target.closest("[data-ohw-navbar-add-button]") || target.closest('[data-slot="popover-content"]') || target.closest('[data-slot="dialog-content"]') || target.closest('[data-slot="dialog-overlay"]')
|
|
8538
|
+
target.closest("[data-ohw-link-popover-root]") || target.closest("[data-ohw-link-modal-root]") || target.closest("[data-ohw-link-page-dropdown]") || target.closest("[data-ohw-section-picker]") || target.closest("[data-ohw-navbar-container-chrome]") || target.closest("[data-ohw-navbar-add-button]") || target.closest("[data-ohw-footer-container-chrome]") || target.closest("[data-ohw-footer-add-button]") || target.closest('[data-slot="popover-content"]') || target.closest('[data-slot="dialog-content"]') || target.closest('[data-slot="dialog-overlay"]')
|
|
6998
8539
|
);
|
|
6999
8540
|
}
|
|
7000
8541
|
function getHrefKeyFromElement(el) {
|
|
@@ -7017,6 +8558,11 @@ function getNavigationItemAnchor(el) {
|
|
|
7017
8558
|
function isNavigationItem(el) {
|
|
7018
8559
|
return getNavigationItemAnchor(el) !== null;
|
|
7019
8560
|
}
|
|
8561
|
+
function listNavigationItems() {
|
|
8562
|
+
return Array.from(
|
|
8563
|
+
document.querySelectorAll("nav [data-ohw-href-key], footer [data-ohw-href-key]")
|
|
8564
|
+
).filter((el) => isNavigationItem(el));
|
|
8565
|
+
}
|
|
7020
8566
|
function getNavigationItemReorderState(anchor) {
|
|
7021
8567
|
if (isNavbarButton2(anchor)) return { key: null, disabled: false };
|
|
7022
8568
|
return getReorderHandleStateFromAnchor(anchor);
|
|
@@ -7049,7 +8595,7 @@ function countFooterNavItems(el) {
|
|
|
7049
8595
|
return Array.from(el.querySelectorAll("[data-ohw-href-key]")).filter(isNavigationItem).length;
|
|
7050
8596
|
}
|
|
7051
8597
|
function findFooterItemGroup(item) {
|
|
7052
|
-
const explicit = item.closest("[data-ohw-footer-column]");
|
|
8598
|
+
const explicit = item.closest("[data-ohw-footer-col], [data-ohw-footer-column]");
|
|
7053
8599
|
if (explicit) return explicit;
|
|
7054
8600
|
const footer = item.closest("footer");
|
|
7055
8601
|
if (!footer) return null;
|
|
@@ -7066,17 +8612,17 @@ function isNavigationRoot(el) {
|
|
|
7066
8612
|
function isInferredFooterGroup(el) {
|
|
7067
8613
|
const footer = el.closest("footer");
|
|
7068
8614
|
if (!footer || el === footer) return false;
|
|
7069
|
-
if (el.hasAttribute("data-ohw-footer-column")) return true;
|
|
8615
|
+
if (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column")) return true;
|
|
7070
8616
|
return countFooterNavItems(el) >= 2;
|
|
7071
8617
|
}
|
|
7072
8618
|
function isNavigationContainer(el) {
|
|
7073
|
-
return el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-footer-column") || isNavigationRoot(el) || isInferredFooterGroup(el);
|
|
8619
|
+
return el.hasAttribute("data-ohw-nav-container") || isFooterLinksContainer(el) || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isNavigationRoot(el) || isInferredFooterGroup(el);
|
|
7074
8620
|
}
|
|
7075
8621
|
function isNavbarLinksContainer(el) {
|
|
7076
8622
|
return el.hasAttribute("data-ohw-nav-container");
|
|
7077
8623
|
}
|
|
7078
8624
|
function getFooterColumn(el) {
|
|
7079
|
-
return el.closest("[data-ohw-footer-column]");
|
|
8625
|
+
return el.closest("[data-ohw-footer-col], [data-ohw-footer-column]");
|
|
7080
8626
|
}
|
|
7081
8627
|
function resolveFooterColumnSelectionTarget(target, clientX, clientY) {
|
|
7082
8628
|
if (getNavigationItemAnchor(target)) return null;
|
|
@@ -7089,6 +8635,9 @@ function isPointOverNavigation(x, y) {
|
|
|
7089
8635
|
const roots = /* @__PURE__ */ new Set();
|
|
7090
8636
|
const navRoot = document.querySelector("[data-ohw-nav-root]") ?? document.querySelector("nav");
|
|
7091
8637
|
if (navRoot) roots.add(navRoot);
|
|
8638
|
+
document.querySelectorAll("[data-ohw-nav-drawer], [data-ohw-nav-container]").forEach((el) => {
|
|
8639
|
+
roots.add(el);
|
|
8640
|
+
});
|
|
7092
8641
|
const footer = document.querySelector("footer");
|
|
7093
8642
|
if (footer) roots.add(footer);
|
|
7094
8643
|
for (const root of roots) {
|
|
@@ -7100,7 +8649,7 @@ function isPointOverNavigation(x, y) {
|
|
|
7100
8649
|
function findHoveredNavOrFooterContainer(x, y) {
|
|
7101
8650
|
const candidates = [
|
|
7102
8651
|
...document.querySelectorAll("[data-ohw-nav-container]"),
|
|
7103
|
-
...
|
|
8652
|
+
...listFooterColumns()
|
|
7104
8653
|
];
|
|
7105
8654
|
for (const container of candidates) {
|
|
7106
8655
|
const r2 = container.getBoundingClientRect();
|
|
@@ -7117,6 +8666,12 @@ function isPointOverNavItem(container, x, y) {
|
|
|
7117
8666
|
return x >= itemRect.left && x <= itemRect.right && y >= itemRect.top && y <= itemRect.bottom;
|
|
7118
8667
|
});
|
|
7119
8668
|
}
|
|
8669
|
+
function isPointOverFooterColumn(x, y) {
|
|
8670
|
+
return listFooterColumns().some((col) => {
|
|
8671
|
+
const r2 = col.getBoundingClientRect();
|
|
8672
|
+
return x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom;
|
|
8673
|
+
});
|
|
8674
|
+
}
|
|
7120
8675
|
function resolveNavContainerSelectionTarget(target, clientX, clientY) {
|
|
7121
8676
|
if (getNavigationItemAnchor(target)) return null;
|
|
7122
8677
|
if (target.closest('[data-ohw-role="navbar-button"]')) return null;
|
|
@@ -7147,32 +8702,60 @@ function getNavigationSelectionParent(el) {
|
|
|
7147
8702
|
if (footerGroup) return footerGroup;
|
|
7148
8703
|
return getNavigationRoot(el);
|
|
7149
8704
|
}
|
|
7150
|
-
if (el.hasAttribute("data-ohw-
|
|
8705
|
+
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup(el))) {
|
|
8706
|
+
return getFooterLinksContainer();
|
|
8707
|
+
}
|
|
8708
|
+
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isFooterLinksContainer(el) || isInferredFooterGroup(el)) {
|
|
7151
8709
|
return getNavigationRoot(el);
|
|
7152
8710
|
}
|
|
7153
8711
|
return null;
|
|
7154
8712
|
}
|
|
8713
|
+
function collectNavigationItemSiblingHintRects(selected) {
|
|
8714
|
+
if (!isNavigationItem(selected)) return [];
|
|
8715
|
+
const footerColumn = getFooterColumn(selected);
|
|
8716
|
+
if (footerColumn) {
|
|
8717
|
+
return listFooterLinksInColumn(footerColumn).filter((link) => link !== selected).map((link) => link.getBoundingClientRect());
|
|
8718
|
+
}
|
|
8719
|
+
const navContainer = selected.closest("[data-ohw-nav-container], [data-ohw-nav-drawer]");
|
|
8720
|
+
if (navContainer) {
|
|
8721
|
+
return Array.from(navContainer.querySelectorAll("[data-ohw-href-key]")).filter((el) => isNavigationItem(el) && el !== selected).map((el) => el.getBoundingClientRect());
|
|
8722
|
+
}
|
|
8723
|
+
return listNavigationItems().filter((el) => el !== selected).map((el) => el.getBoundingClientRect());
|
|
8724
|
+
}
|
|
7155
8725
|
function placeCaretAtPoint(el, x, y) {
|
|
7156
8726
|
const selection = window.getSelection();
|
|
7157
8727
|
if (!selection) return;
|
|
7158
|
-
|
|
7159
|
-
|
|
7160
|
-
|
|
7161
|
-
|
|
7162
|
-
|
|
7163
|
-
|
|
8728
|
+
const overlays = Array.from(
|
|
8729
|
+
document.querySelectorAll(
|
|
8730
|
+
"[data-ohw-item-drag-surface], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-ohw-item-toolbar-anchor]"
|
|
8731
|
+
)
|
|
8732
|
+
);
|
|
8733
|
+
const prevPointerEvents = overlays.map((node) => node.style.pointerEvents);
|
|
8734
|
+
for (const node of overlays) node.style.pointerEvents = "none";
|
|
8735
|
+
try {
|
|
8736
|
+
if (typeof document.caretRangeFromPoint === "function") {
|
|
8737
|
+
const range = document.caretRangeFromPoint(x, y);
|
|
8738
|
+
if (range && el.contains(range.startContainer)) {
|
|
8739
|
+
selection.removeAllRanges();
|
|
8740
|
+
selection.addRange(range);
|
|
8741
|
+
return;
|
|
8742
|
+
}
|
|
7164
8743
|
}
|
|
7165
|
-
|
|
7166
|
-
|
|
7167
|
-
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
|
-
|
|
8744
|
+
const caretPositionFromPoint = document.caretPositionFromPoint;
|
|
8745
|
+
if (typeof caretPositionFromPoint === "function") {
|
|
8746
|
+
const position = caretPositionFromPoint(x, y);
|
|
8747
|
+
if (position && el.contains(position.offsetNode)) {
|
|
8748
|
+
const range = document.createRange();
|
|
8749
|
+
range.setStart(position.offsetNode, position.offset);
|
|
8750
|
+
range.collapse(true);
|
|
8751
|
+
selection.removeAllRanges();
|
|
8752
|
+
selection.addRange(range);
|
|
8753
|
+
}
|
|
7175
8754
|
}
|
|
8755
|
+
} finally {
|
|
8756
|
+
overlays.forEach((node, i) => {
|
|
8757
|
+
node.style.pointerEvents = prevPointerEvents[i] ?? "";
|
|
8758
|
+
});
|
|
7176
8759
|
}
|
|
7177
8760
|
}
|
|
7178
8761
|
function selectAllTextInEditable(el) {
|
|
@@ -7293,9 +8876,16 @@ function sanitizeHtml(html) {
|
|
|
7293
8876
|
if (!SAFE_TAGS.has(el.tagName)) {
|
|
7294
8877
|
parent.replaceChild(document.createTextNode(el.textContent ?? ""), el);
|
|
7295
8878
|
} else {
|
|
7296
|
-
const
|
|
8879
|
+
const htmlEl = el;
|
|
8880
|
+
const textAlign = htmlEl.style?.textAlign || el.getAttribute("align") || "";
|
|
8881
|
+
const fontWeight = htmlEl.style?.fontWeight || "";
|
|
8882
|
+
const fontStyle = htmlEl.style?.fontStyle || "";
|
|
8883
|
+
const textDecorationLine = htmlEl.style?.textDecorationLine || htmlEl.style?.textDecoration || "";
|
|
7297
8884
|
for (const attr of Array.from(el.attributes)) el.removeAttribute(attr.name);
|
|
7298
|
-
if (textAlign)
|
|
8885
|
+
if (textAlign) htmlEl.style.textAlign = textAlign;
|
|
8886
|
+
if (fontWeight) htmlEl.style.fontWeight = fontWeight;
|
|
8887
|
+
if (fontStyle) htmlEl.style.fontStyle = fontStyle;
|
|
8888
|
+
if (textDecorationLine) htmlEl.style.textDecorationLine = textDecorationLine;
|
|
7299
8889
|
walk(el);
|
|
7300
8890
|
}
|
|
7301
8891
|
}
|
|
@@ -7338,10 +8928,11 @@ function EditGlowChrome({
|
|
|
7338
8928
|
rect,
|
|
7339
8929
|
elRef,
|
|
7340
8930
|
reorderHrefKey,
|
|
7341
|
-
dragDisabled = false
|
|
8931
|
+
dragDisabled = false,
|
|
8932
|
+
hideHandle = false
|
|
7342
8933
|
}) {
|
|
7343
8934
|
const GAP = SELECTION_CHROME_GAP2;
|
|
7344
|
-
return /* @__PURE__ */ (0,
|
|
8935
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
7345
8936
|
"div",
|
|
7346
8937
|
{
|
|
7347
8938
|
ref: elRef,
|
|
@@ -7356,7 +8947,7 @@ function EditGlowChrome({
|
|
|
7356
8947
|
zIndex: 2147483646
|
|
7357
8948
|
},
|
|
7358
8949
|
children: [
|
|
7359
|
-
/* @__PURE__ */ (0,
|
|
8950
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7360
8951
|
"div",
|
|
7361
8952
|
{
|
|
7362
8953
|
style: {
|
|
@@ -7369,7 +8960,7 @@ function EditGlowChrome({
|
|
|
7369
8960
|
}
|
|
7370
8961
|
}
|
|
7371
8962
|
),
|
|
7372
|
-
reorderHrefKey && /* @__PURE__ */ (0,
|
|
8963
|
+
reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7373
8964
|
"div",
|
|
7374
8965
|
{
|
|
7375
8966
|
"data-ohw-drag-handle-container": "",
|
|
@@ -7381,7 +8972,7 @@ function EditGlowChrome({
|
|
|
7381
8972
|
transform: "translate(calc(-100% - 7px), -50%)",
|
|
7382
8973
|
pointerEvents: dragDisabled ? "none" : "auto"
|
|
7383
8974
|
},
|
|
7384
|
-
children: /* @__PURE__ */ (0,
|
|
8975
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7385
8976
|
DragHandle,
|
|
7386
8977
|
{
|
|
7387
8978
|
"aria-label": `Reorder ${reorderHrefKey}`,
|
|
@@ -7482,6 +9073,79 @@ function resolveItemInteractionState(rect, parentScroll) {
|
|
|
7482
9073
|
const { transform } = calcToolbarPos(rect, parentScroll, 120);
|
|
7483
9074
|
return transform.includes("translateY(-100%)") ? "active-top" : "active-bottom";
|
|
7484
9075
|
}
|
|
9076
|
+
function resolveSelectionStartElement(sel) {
|
|
9077
|
+
if (!sel || sel.rangeCount === 0) return null;
|
|
9078
|
+
const range = sel.getRangeAt(0);
|
|
9079
|
+
let startNode = range.startContainer;
|
|
9080
|
+
if (startNode.nodeType === Node.ELEMENT_NODE) {
|
|
9081
|
+
const el = startNode;
|
|
9082
|
+
startNode = el.childNodes[range.startOffset] ?? el.childNodes[range.startOffset - 1] ?? el;
|
|
9083
|
+
}
|
|
9084
|
+
return startNode.nodeType === Node.TEXT_NODE ? startNode.parentElement : startNode;
|
|
9085
|
+
}
|
|
9086
|
+
function detectActiveFormats(startEl, activeRoot) {
|
|
9087
|
+
const formats = /* @__PURE__ */ new Set();
|
|
9088
|
+
const cs = getComputedStyle(startEl);
|
|
9089
|
+
const weight = parseInt(cs.fontWeight, 10);
|
|
9090
|
+
let hasBold = cs.fontWeight === "bold" || !Number.isNaN(weight) && weight >= 600;
|
|
9091
|
+
let hasItalic = cs.fontStyle === "italic" || cs.fontStyle === "oblique";
|
|
9092
|
+
let hasUnderline = false;
|
|
9093
|
+
let hasStrike = false;
|
|
9094
|
+
let hasUl = false;
|
|
9095
|
+
let hasOl = false;
|
|
9096
|
+
for (let el = startEl; el; el = el.parentElement) {
|
|
9097
|
+
if (el.tagName === "B" || el.tagName === "STRONG") hasBold = true;
|
|
9098
|
+
if (el.tagName === "I" || el.tagName === "EM") hasItalic = true;
|
|
9099
|
+
const decoration = getComputedStyle(el).textDecorationLine;
|
|
9100
|
+
if (decoration.includes("underline") || el.tagName === "U" || el.tagName === "INS") hasUnderline = true;
|
|
9101
|
+
if (decoration.includes("line-through") || el.tagName === "S" || el.tagName === "STRIKE" || el.tagName === "DEL") hasStrike = true;
|
|
9102
|
+
if (el.tagName === "UL") hasUl = true;
|
|
9103
|
+
if (el.tagName === "OL") hasOl = true;
|
|
9104
|
+
if (el === activeRoot) break;
|
|
9105
|
+
}
|
|
9106
|
+
if (hasBold) formats.add("bold");
|
|
9107
|
+
if (hasItalic) formats.add("italic");
|
|
9108
|
+
if (hasUnderline) formats.add("underline");
|
|
9109
|
+
if (hasStrike) formats.add("strikeThrough");
|
|
9110
|
+
if (hasUl) formats.add("insertUnorderedList");
|
|
9111
|
+
if (hasOl) formats.add("insertOrderedList");
|
|
9112
|
+
const block = startEl.closest("div, p, h1, h2, h3, h4, h5, h6, li, td, th") ?? startEl;
|
|
9113
|
+
const align = getComputedStyle(block).textAlign;
|
|
9114
|
+
if (align === "center") formats.add("justifyCenter");
|
|
9115
|
+
else if (align === "right" || align === "end") formats.add("justifyRight");
|
|
9116
|
+
else formats.add("justifyLeft");
|
|
9117
|
+
return formats;
|
|
9118
|
+
}
|
|
9119
|
+
function setsEqual(a, b) {
|
|
9120
|
+
if (a.size !== b.size) return false;
|
|
9121
|
+
for (const item of a) {
|
|
9122
|
+
if (!b.has(item)) return false;
|
|
9123
|
+
}
|
|
9124
|
+
return true;
|
|
9125
|
+
}
|
|
9126
|
+
function textOffsetInRoot(root, node, offset) {
|
|
9127
|
+
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
|
|
9128
|
+
let total = 0;
|
|
9129
|
+
let current;
|
|
9130
|
+
while (current = walker.nextNode()) {
|
|
9131
|
+
if (current === node) return total + offset;
|
|
9132
|
+
total += (current.textContent ?? "").length;
|
|
9133
|
+
}
|
|
9134
|
+
return total;
|
|
9135
|
+
}
|
|
9136
|
+
function pointAtTextOffset(root, targetOffset) {
|
|
9137
|
+
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
|
|
9138
|
+
let total = 0;
|
|
9139
|
+
let current;
|
|
9140
|
+
let last = null;
|
|
9141
|
+
while (current = walker.nextNode()) {
|
|
9142
|
+
const len = (current.textContent ?? "").length;
|
|
9143
|
+
if (total + len >= targetOffset) return { node: current, offset: targetOffset - total };
|
|
9144
|
+
total += len;
|
|
9145
|
+
last = current;
|
|
9146
|
+
}
|
|
9147
|
+
return last ? { node: last, offset: (last.textContent ?? "").length } : null;
|
|
9148
|
+
}
|
|
7485
9149
|
function FloatingToolbar({
|
|
7486
9150
|
rect,
|
|
7487
9151
|
parentScroll,
|
|
@@ -7491,9 +9155,9 @@ function FloatingToolbar({
|
|
|
7491
9155
|
showEditLink,
|
|
7492
9156
|
onEditLink
|
|
7493
9157
|
}) {
|
|
7494
|
-
const localRef =
|
|
7495
|
-
const [measuredW, setMeasuredW] =
|
|
7496
|
-
const setRefs =
|
|
9158
|
+
const localRef = import_react9.default.useRef(null);
|
|
9159
|
+
const [measuredW, setMeasuredW] = import_react9.default.useState(330);
|
|
9160
|
+
const setRefs = import_react9.default.useCallback(
|
|
7497
9161
|
(node) => {
|
|
7498
9162
|
localRef.current = node;
|
|
7499
9163
|
if (typeof elRef === "function") elRef(node);
|
|
@@ -7505,7 +9169,7 @@ function FloatingToolbar({
|
|
|
7505
9169
|
},
|
|
7506
9170
|
[elRef]
|
|
7507
9171
|
);
|
|
7508
|
-
|
|
9172
|
+
import_react9.default.useLayoutEffect(() => {
|
|
7509
9173
|
const node = localRef.current;
|
|
7510
9174
|
if (!node) return;
|
|
7511
9175
|
const update = () => {
|
|
@@ -7518,7 +9182,7 @@ function FloatingToolbar({
|
|
|
7518
9182
|
return () => ro.disconnect();
|
|
7519
9183
|
}, [showEditLink, activeCommands]);
|
|
7520
9184
|
const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
|
|
7521
|
-
return /* @__PURE__ */ (0,
|
|
9185
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7522
9186
|
"div",
|
|
7523
9187
|
{
|
|
7524
9188
|
ref: setRefs,
|
|
@@ -7530,12 +9194,12 @@ function FloatingToolbar({
|
|
|
7530
9194
|
zIndex: 2147483647,
|
|
7531
9195
|
pointerEvents: "auto"
|
|
7532
9196
|
},
|
|
7533
|
-
children: /* @__PURE__ */ (0,
|
|
7534
|
-
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0,
|
|
7535
|
-
gi > 0 && /* @__PURE__ */ (0,
|
|
9197
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(CustomToolbar, { children: [
|
|
9198
|
+
TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react9.default.Fragment, { children: [
|
|
9199
|
+
gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(CustomToolbarDivider, {}),
|
|
7536
9200
|
btns.map((btn) => {
|
|
7537
9201
|
const isActive = activeCommands.has(btn.cmd);
|
|
7538
|
-
return /* @__PURE__ */ (0,
|
|
9202
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7539
9203
|
CustomToolbarButton,
|
|
7540
9204
|
{
|
|
7541
9205
|
title: btn.title,
|
|
@@ -7544,7 +9208,7 @@ function FloatingToolbar({
|
|
|
7544
9208
|
e.preventDefault();
|
|
7545
9209
|
onCommand(btn.cmd);
|
|
7546
9210
|
},
|
|
7547
|
-
children: /* @__PURE__ */ (0,
|
|
9211
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7548
9212
|
"svg",
|
|
7549
9213
|
{
|
|
7550
9214
|
width: "16",
|
|
@@ -7565,7 +9229,7 @@ function FloatingToolbar({
|
|
|
7565
9229
|
);
|
|
7566
9230
|
})
|
|
7567
9231
|
] }, gi)),
|
|
7568
|
-
showEditLink ? /* @__PURE__ */ (0,
|
|
9232
|
+
showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7569
9233
|
CustomToolbarButton,
|
|
7570
9234
|
{
|
|
7571
9235
|
type: "button",
|
|
@@ -7579,7 +9243,7 @@ function FloatingToolbar({
|
|
|
7579
9243
|
e.preventDefault();
|
|
7580
9244
|
e.stopPropagation();
|
|
7581
9245
|
},
|
|
7582
|
-
children: /* @__PURE__ */ (0,
|
|
9246
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.Link, { className: "size-4 shrink-0", "aria-hidden": true })
|
|
7583
9247
|
}
|
|
7584
9248
|
) : null
|
|
7585
9249
|
] })
|
|
@@ -7596,7 +9260,7 @@ function StateToggle({
|
|
|
7596
9260
|
states,
|
|
7597
9261
|
onStateChange
|
|
7598
9262
|
}) {
|
|
7599
|
-
return /* @__PURE__ */ (0,
|
|
9263
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7600
9264
|
ToggleGroup,
|
|
7601
9265
|
{
|
|
7602
9266
|
"data-ohw-state-toggle": "",
|
|
@@ -7610,7 +9274,7 @@ function StateToggle({
|
|
|
7610
9274
|
left: rect.right - 8,
|
|
7611
9275
|
transform: "translateX(-100%)"
|
|
7612
9276
|
},
|
|
7613
|
-
children: states.map((state) => /* @__PURE__ */ (0,
|
|
9277
|
+
children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
|
|
7614
9278
|
}
|
|
7615
9279
|
);
|
|
7616
9280
|
}
|
|
@@ -7637,8 +9301,8 @@ function OhhwellsBridge() {
|
|
|
7637
9301
|
const router = (0, import_navigation2.useRouter)();
|
|
7638
9302
|
const searchParams = (0, import_navigation2.useSearchParams)();
|
|
7639
9303
|
const isEditMode = isEditSessionActive();
|
|
7640
|
-
const [bridgeRoot, setBridgeRoot] = (0,
|
|
7641
|
-
(0,
|
|
9304
|
+
const [bridgeRoot, setBridgeRoot] = (0, import_react9.useState)(null);
|
|
9305
|
+
(0, import_react9.useEffect)(() => {
|
|
7642
9306
|
const figtreeFontId = "ohw-figtree-font";
|
|
7643
9307
|
if (!document.getElementById(figtreeFontId)) {
|
|
7644
9308
|
const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
|
|
@@ -7666,92 +9330,137 @@ function OhhwellsBridge() {
|
|
|
7666
9330
|
const subdomainFromQuery = searchParams.get("subdomain");
|
|
7667
9331
|
const subdomain = resolveSubdomain(subdomainFromQuery);
|
|
7668
9332
|
useLinkHrefGuardian(pathname, subdomain, isEditMode);
|
|
7669
|
-
const postToParent2 = (0,
|
|
9333
|
+
const postToParent2 = (0, import_react9.useCallback)((data) => {
|
|
7670
9334
|
if (typeof window !== "undefined" && window.parent !== window) {
|
|
7671
9335
|
window.parent.postMessage(data, "*");
|
|
7672
9336
|
}
|
|
7673
9337
|
}, []);
|
|
7674
|
-
const [fetchState, setFetchState] = (0,
|
|
7675
|
-
const autoSaveTimers = (0,
|
|
7676
|
-
const activeElRef = (0,
|
|
7677
|
-
const
|
|
7678
|
-
const
|
|
7679
|
-
const
|
|
7680
|
-
const
|
|
7681
|
-
const
|
|
7682
|
-
const
|
|
7683
|
-
const
|
|
9338
|
+
const [fetchState, setFetchState] = (0, import_react9.useState)("idle");
|
|
9339
|
+
const autoSaveTimers = (0, import_react9.useRef)(/* @__PURE__ */ new Map());
|
|
9340
|
+
const activeElRef = (0, import_react9.useRef)(null);
|
|
9341
|
+
const pointerHeldRef = (0, import_react9.useRef)(false);
|
|
9342
|
+
const selectedElRef = (0, import_react9.useRef)(null);
|
|
9343
|
+
const selectedHrefKeyRef = (0, import_react9.useRef)(null);
|
|
9344
|
+
const selectedFooterColAttrRef = (0, import_react9.useRef)(null);
|
|
9345
|
+
const originalContentRef = (0, import_react9.useRef)(null);
|
|
9346
|
+
const activeStateElRef = (0, import_react9.useRef)(null);
|
|
9347
|
+
const parentScrollRef = (0, import_react9.useRef)(null);
|
|
9348
|
+
const visibleViewportRef = (0, import_react9.useRef)(null);
|
|
9349
|
+
const [dialogPortalContainer, setDialogPortalContainer] = (0, import_react9.useState)(null);
|
|
9350
|
+
const attachVisibleViewport = (0, import_react9.useCallback)((node) => {
|
|
7684
9351
|
visibleViewportRef.current = node;
|
|
7685
9352
|
setDialogPortalContainer(node);
|
|
7686
9353
|
if (node) applyVisibleViewport(node, parentScrollRef.current);
|
|
7687
9354
|
}, []);
|
|
7688
|
-
const toolbarElRef = (0,
|
|
7689
|
-
const glowElRef = (0,
|
|
7690
|
-
const hoveredImageRef = (0,
|
|
7691
|
-
const hoveredImageHasTextOverlapRef = (0,
|
|
7692
|
-
const dragOverElRef = (0,
|
|
7693
|
-
const [mediaHover, setMediaHover] = (0,
|
|
7694
|
-
const [uploadingRects, setUploadingRects] = (0,
|
|
7695
|
-
const hoveredGapRef = (0,
|
|
7696
|
-
const imageUnhoverTimerRef = (0,
|
|
7697
|
-
const imageShowTimerRef = (0,
|
|
7698
|
-
const editStylesRef = (0,
|
|
7699
|
-
const activateRef = (0,
|
|
9355
|
+
const toolbarElRef = (0, import_react9.useRef)(null);
|
|
9356
|
+
const glowElRef = (0, import_react9.useRef)(null);
|
|
9357
|
+
const hoveredImageRef = (0, import_react9.useRef)(null);
|
|
9358
|
+
const hoveredImageHasTextOverlapRef = (0, import_react9.useRef)(false);
|
|
9359
|
+
const dragOverElRef = (0, import_react9.useRef)(null);
|
|
9360
|
+
const [mediaHover, setMediaHover] = (0, import_react9.useState)(null);
|
|
9361
|
+
const [uploadingRects, setUploadingRects] = (0, import_react9.useState)({});
|
|
9362
|
+
const hoveredGapRef = (0, import_react9.useRef)(null);
|
|
9363
|
+
const imageUnhoverTimerRef = (0, import_react9.useRef)(null);
|
|
9364
|
+
const imageShowTimerRef = (0, import_react9.useRef)(null);
|
|
9365
|
+
const editStylesRef = (0, import_react9.useRef)(null);
|
|
9366
|
+
const activateRef = (0, import_react9.useRef)(() => {
|
|
7700
9367
|
});
|
|
7701
|
-
const deactivateRef = (0,
|
|
9368
|
+
const deactivateRef = (0, import_react9.useRef)(() => {
|
|
7702
9369
|
});
|
|
7703
|
-
const selectRef = (0,
|
|
9370
|
+
const selectRef = (0, import_react9.useRef)(() => {
|
|
7704
9371
|
});
|
|
7705
|
-
const selectFrameRef = (0,
|
|
9372
|
+
const selectFrameRef = (0, import_react9.useRef)(() => {
|
|
7706
9373
|
});
|
|
7707
|
-
const deselectRef = (0,
|
|
9374
|
+
const deselectRef = (0, import_react9.useRef)(() => {
|
|
7708
9375
|
});
|
|
7709
|
-
const reselectNavigationItemRef = (0,
|
|
9376
|
+
const reselectNavigationItemRef = (0, import_react9.useRef)(() => {
|
|
7710
9377
|
});
|
|
7711
|
-
const commitNavigationTextEditRef = (0,
|
|
9378
|
+
const commitNavigationTextEditRef = (0, import_react9.useRef)(() => {
|
|
7712
9379
|
});
|
|
7713
|
-
const refreshActiveCommandsRef = (0,
|
|
9380
|
+
const refreshActiveCommandsRef = (0, import_react9.useRef)(() => {
|
|
7714
9381
|
});
|
|
7715
|
-
const postToParentRef = (0,
|
|
9382
|
+
const postToParentRef = (0, import_react9.useRef)(postToParent2);
|
|
7716
9383
|
postToParentRef.current = postToParent2;
|
|
7717
|
-
const sectionsLoadedRef = (0,
|
|
7718
|
-
const pendingScheduleConfigRequests = (0,
|
|
7719
|
-
const [toolbarRect, setToolbarRect] = (0,
|
|
7720
|
-
const [toolbarVariant, setToolbarVariant] = (0,
|
|
7721
|
-
const toolbarVariantRef = (0,
|
|
9384
|
+
const sectionsLoadedRef = (0, import_react9.useRef)(false);
|
|
9385
|
+
const pendingScheduleConfigRequests = (0, import_react9.useRef)([]);
|
|
9386
|
+
const [toolbarRect, setToolbarRect] = (0, import_react9.useState)(null);
|
|
9387
|
+
const [toolbarVariant, setToolbarVariant] = (0, import_react9.useState)("none");
|
|
9388
|
+
const toolbarVariantRef = (0, import_react9.useRef)("none");
|
|
7722
9389
|
toolbarVariantRef.current = toolbarVariant;
|
|
7723
|
-
const [selectedIsCta, setSelectedIsCta] = (0,
|
|
7724
|
-
const [reorderHrefKey, setReorderHrefKey] = (0,
|
|
7725
|
-
const [reorderDragDisabled, setReorderDragDisabled] = (0,
|
|
7726
|
-
const [toggleState, setToggleState] = (0,
|
|
7727
|
-
const [maxBadge, setMaxBadge] = (0,
|
|
7728
|
-
const [activeCommands, setActiveCommands] = (0,
|
|
7729
|
-
const [sectionGap, setSectionGap] = (0,
|
|
7730
|
-
const [toolbarShowEditLink, setToolbarShowEditLink] = (0,
|
|
7731
|
-
const hoveredNavContainerRef = (0,
|
|
7732
|
-
const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0,
|
|
7733
|
-
const hoveredItemElRef = (0,
|
|
7734
|
-
const [hoveredItemRect, setHoveredItemRect] = (0,
|
|
7735
|
-
const siblingHintElRef = (0,
|
|
7736
|
-
const [siblingHintRect, setSiblingHintRect] = (0,
|
|
7737
|
-
const [
|
|
7738
|
-
const [
|
|
7739
|
-
const
|
|
7740
|
-
const
|
|
7741
|
-
const
|
|
7742
|
-
const [
|
|
7743
|
-
const [
|
|
7744
|
-
const
|
|
7745
|
-
const
|
|
7746
|
-
const
|
|
7747
|
-
const
|
|
7748
|
-
const
|
|
9390
|
+
const [selectedIsCta, setSelectedIsCta] = (0, import_react9.useState)(false);
|
|
9391
|
+
const [reorderHrefKey, setReorderHrefKey] = (0, import_react9.useState)(null);
|
|
9392
|
+
const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react9.useState)(false);
|
|
9393
|
+
const [toggleState, setToggleState] = (0, import_react9.useState)(null);
|
|
9394
|
+
const [maxBadge, setMaxBadge] = (0, import_react9.useState)(null);
|
|
9395
|
+
const [activeCommands, setActiveCommands] = (0, import_react9.useState)(/* @__PURE__ */ new Set());
|
|
9396
|
+
const [sectionGap, setSectionGap] = (0, import_react9.useState)(null);
|
|
9397
|
+
const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react9.useState)(false);
|
|
9398
|
+
const hoveredNavContainerRef = (0, import_react9.useRef)(null);
|
|
9399
|
+
const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0, import_react9.useState)(null);
|
|
9400
|
+
const hoveredItemElRef = (0, import_react9.useRef)(null);
|
|
9401
|
+
const [hoveredItemRect, setHoveredItemRect] = (0, import_react9.useState)(null);
|
|
9402
|
+
const siblingHintElRef = (0, import_react9.useRef)(null);
|
|
9403
|
+
const [siblingHintRect, setSiblingHintRect] = (0, import_react9.useState)(null);
|
|
9404
|
+
const [siblingHintRects, setSiblingHintRects] = (0, import_react9.useState)([]);
|
|
9405
|
+
const [isItemDragging, setIsItemDragging] = (0, import_react9.useState)(false);
|
|
9406
|
+
const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react9.useState)(false);
|
|
9407
|
+
const footerDragRef = (0, import_react9.useRef)(null);
|
|
9408
|
+
const [footerDropSlots, setFooterDropSlots] = (0, import_react9.useState)([]);
|
|
9409
|
+
const [activeFooterDropIndex, setActiveFooterDropIndex] = (0, import_react9.useState)(null);
|
|
9410
|
+
const [draggedItemRect, setDraggedItemRect] = (0, import_react9.useState)(null);
|
|
9411
|
+
const footerPointerDragRef = (0, import_react9.useRef)(null);
|
|
9412
|
+
const suppressNextClickRef = (0, import_react9.useRef)(false);
|
|
9413
|
+
const suppressClickUntilRef = (0, import_react9.useRef)(0);
|
|
9414
|
+
const [linkPopover, setLinkPopover] = (0, import_react9.useState)(null);
|
|
9415
|
+
const linkPopoverSessionRef = (0, import_react9.useRef)(null);
|
|
9416
|
+
const addNavAfterAnchorRef = (0, import_react9.useRef)(null);
|
|
9417
|
+
const editContentRef = (0, import_react9.useRef)({});
|
|
9418
|
+
const [sitePages, setSitePages] = (0, import_react9.useState)([]);
|
|
9419
|
+
const [sectionsByPath, setSectionsByPath] = (0, import_react9.useState)({});
|
|
9420
|
+
const sectionsPrefetchGenRef = (0, import_react9.useRef)(0);
|
|
9421
|
+
const setLinkPopoverRef = (0, import_react9.useRef)(setLinkPopover);
|
|
9422
|
+
const linkPopoverPanelRef = (0, import_react9.useRef)(null);
|
|
9423
|
+
const linkPopoverOpenRef = (0, import_react9.useRef)(false);
|
|
9424
|
+
const linkPopoverGraceUntilRef = (0, import_react9.useRef)(0);
|
|
7749
9425
|
setLinkPopoverRef.current = setLinkPopover;
|
|
7750
9426
|
linkPopoverSessionRef.current = linkPopover;
|
|
9427
|
+
const {
|
|
9428
|
+
navDragRef,
|
|
9429
|
+
navDropSlots,
|
|
9430
|
+
activeNavDropIndex,
|
|
9431
|
+
startNavLinkDrag,
|
|
9432
|
+
commitNavDrag,
|
|
9433
|
+
onNavDragOver,
|
|
9434
|
+
armNavPressFromChrome,
|
|
9435
|
+
refreshNavDragVisualsRef
|
|
9436
|
+
} = useNavItemDrag({
|
|
9437
|
+
isEditMode,
|
|
9438
|
+
editContentRef,
|
|
9439
|
+
selectedElRef,
|
|
9440
|
+
activeElRef,
|
|
9441
|
+
footerDragRef,
|
|
9442
|
+
suppressNextClickRef,
|
|
9443
|
+
suppressClickUntilRef,
|
|
9444
|
+
siblingHintElRef,
|
|
9445
|
+
postToParentRef,
|
|
9446
|
+
deselectRef,
|
|
9447
|
+
selectRef,
|
|
9448
|
+
deactivateRef,
|
|
9449
|
+
setLinkPopover: () => setLinkPopover(null),
|
|
9450
|
+
linkPopoverOpenRef,
|
|
9451
|
+
setIsItemDragging,
|
|
9452
|
+
setDraggedItemRect,
|
|
9453
|
+
setSiblingHintRect,
|
|
9454
|
+
setSiblingHintRects,
|
|
9455
|
+
setToolbarRect,
|
|
9456
|
+
getNavigationItemAnchor,
|
|
9457
|
+
isDragHandleDisabled,
|
|
9458
|
+
isNavbarButton: isNavbarButton2
|
|
9459
|
+
});
|
|
7751
9460
|
const bumpLinkPopoverGrace = () => {
|
|
7752
9461
|
linkPopoverGraceUntilRef.current = Date.now() + 350;
|
|
7753
9462
|
};
|
|
7754
|
-
const runSectionsPrefetch = (0,
|
|
9463
|
+
const runSectionsPrefetch = (0, import_react9.useCallback)((pages) => {
|
|
7755
9464
|
if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
|
|
7756
9465
|
const gen = ++sectionsPrefetchGenRef.current;
|
|
7757
9466
|
const paths = pages.map((p) => p.path);
|
|
@@ -7770,10 +9479,24 @@ function OhhwellsBridge() {
|
|
|
7770
9479
|
);
|
|
7771
9480
|
});
|
|
7772
9481
|
}, [isEditMode, pathname]);
|
|
7773
|
-
const runSectionsPrefetchRef = (0,
|
|
9482
|
+
const runSectionsPrefetchRef = (0, import_react9.useRef)(runSectionsPrefetch);
|
|
7774
9483
|
runSectionsPrefetchRef.current = runSectionsPrefetch;
|
|
7775
|
-
(0,
|
|
7776
|
-
if (!linkPopover)
|
|
9484
|
+
(0, import_react9.useEffect)(() => {
|
|
9485
|
+
if (!linkPopover) {
|
|
9486
|
+
document.documentElement.removeAttribute("data-ohw-link-popover-open");
|
|
9487
|
+
return;
|
|
9488
|
+
}
|
|
9489
|
+
document.documentElement.setAttribute("data-ohw-link-popover-open", "");
|
|
9490
|
+
hoveredItemElRef.current = null;
|
|
9491
|
+
setHoveredItemRect(null);
|
|
9492
|
+
hoveredNavContainerRef.current = null;
|
|
9493
|
+
setHoveredNavContainerRect(null);
|
|
9494
|
+
siblingHintElRef.current = null;
|
|
9495
|
+
setSiblingHintRect(null);
|
|
9496
|
+
setSiblingHintRects([]);
|
|
9497
|
+
if (selectedElRef.current || toolbarVariantRef.current !== "none") {
|
|
9498
|
+
deselectRef.current();
|
|
9499
|
+
}
|
|
7777
9500
|
if (hoveredImageRef.current) {
|
|
7778
9501
|
hoveredImageRef.current = null;
|
|
7779
9502
|
hoveredImageHasTextOverlapRef.current = false;
|
|
@@ -7800,6 +9523,7 @@ function OhhwellsBridge() {
|
|
|
7800
9523
|
document.addEventListener("touchmove", preventBackgroundScroll, scrollOpts);
|
|
7801
9524
|
postToParent2({ type: "ow:image-unhover" });
|
|
7802
9525
|
return () => {
|
|
9526
|
+
document.documentElement.removeAttribute("data-ohw-link-popover-open");
|
|
7803
9527
|
postToParent2({ type: "ow:link-modal-lock", locked: false });
|
|
7804
9528
|
html.style.overflow = prevHtmlOverflow;
|
|
7805
9529
|
body.style.overflow = prevBodyOverflow;
|
|
@@ -7807,7 +9531,7 @@ function OhhwellsBridge() {
|
|
|
7807
9531
|
document.removeEventListener("touchmove", preventBackgroundScroll, scrollOpts);
|
|
7808
9532
|
};
|
|
7809
9533
|
}, [linkPopover, postToParent2]);
|
|
7810
|
-
(0,
|
|
9534
|
+
(0, import_react9.useEffect)(() => {
|
|
7811
9535
|
if (!isEditMode) return;
|
|
7812
9536
|
const useFixtures = shouldUseDevFixtures();
|
|
7813
9537
|
if (useFixtures) {
|
|
@@ -7831,14 +9555,14 @@ function OhhwellsBridge() {
|
|
|
7831
9555
|
if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
|
|
7832
9556
|
return () => window.removeEventListener("message", onSitePages);
|
|
7833
9557
|
}, [isEditMode, postToParent2]);
|
|
7834
|
-
(0,
|
|
9558
|
+
(0, import_react9.useEffect)(() => {
|
|
7835
9559
|
if (!isEditMode || shouldUseDevFixtures()) return;
|
|
7836
9560
|
void loadAllSectionsManifest().then((manifest) => {
|
|
7837
9561
|
if (Object.keys(manifest).length === 0) return;
|
|
7838
9562
|
setSectionsByPath((prev) => ({ ...manifest, ...prev }));
|
|
7839
9563
|
});
|
|
7840
9564
|
}, [isEditMode]);
|
|
7841
|
-
(0,
|
|
9565
|
+
(0, import_react9.useEffect)(() => {
|
|
7842
9566
|
const update = () => {
|
|
7843
9567
|
const el = activeElRef.current ?? selectedElRef.current;
|
|
7844
9568
|
if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
@@ -7862,10 +9586,10 @@ function OhhwellsBridge() {
|
|
|
7862
9586
|
vvp.removeEventListener("resize", update);
|
|
7863
9587
|
};
|
|
7864
9588
|
}, []);
|
|
7865
|
-
const refreshStateRules = (0,
|
|
9589
|
+
const refreshStateRules = (0, import_react9.useCallback)(() => {
|
|
7866
9590
|
editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
|
|
7867
9591
|
}, []);
|
|
7868
|
-
const processConfigRequest = (0,
|
|
9592
|
+
const processConfigRequest = (0, import_react9.useCallback)((insertAfterVal) => {
|
|
7869
9593
|
const tracker = getSectionsTracker();
|
|
7870
9594
|
let entries = [];
|
|
7871
9595
|
try {
|
|
@@ -7888,7 +9612,7 @@ function OhhwellsBridge() {
|
|
|
7888
9612
|
}
|
|
7889
9613
|
window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
|
|
7890
9614
|
}, [isEditMode]);
|
|
7891
|
-
const deactivate = (0,
|
|
9615
|
+
const deactivate = (0, import_react9.useCallback)(() => {
|
|
7892
9616
|
const el = activeElRef.current;
|
|
7893
9617
|
if (!el) return;
|
|
7894
9618
|
const key = el.dataset.ohwKey;
|
|
@@ -7920,19 +9644,23 @@ function OhhwellsBridge() {
|
|
|
7920
9644
|
setToolbarShowEditLink(false);
|
|
7921
9645
|
postToParent2({ type: "ow:exit-edit" });
|
|
7922
9646
|
}, [postToParent2]);
|
|
7923
|
-
const clearSelectedAttr = (0,
|
|
9647
|
+
const clearSelectedAttr = (0, import_react9.useCallback)(() => {
|
|
7924
9648
|
document.querySelectorAll("[data-ohw-selected]").forEach((el) => {
|
|
7925
9649
|
el.removeAttribute("data-ohw-selected");
|
|
7926
9650
|
});
|
|
7927
9651
|
}, []);
|
|
7928
|
-
const deselect = (0,
|
|
9652
|
+
const deselect = (0, import_react9.useCallback)(() => {
|
|
7929
9653
|
clearSelectedAttr();
|
|
7930
9654
|
selectedElRef.current = null;
|
|
9655
|
+
selectedHrefKeyRef.current = null;
|
|
9656
|
+
selectedFooterColAttrRef.current = null;
|
|
7931
9657
|
setSelectedIsCta(false);
|
|
7932
9658
|
setReorderHrefKey(null);
|
|
7933
9659
|
setReorderDragDisabled(false);
|
|
9660
|
+
setIsFooterFrameSelection(false);
|
|
7934
9661
|
siblingHintElRef.current = null;
|
|
7935
9662
|
setSiblingHintRect(null);
|
|
9663
|
+
setSiblingHintRects([]);
|
|
7936
9664
|
setIsItemDragging(false);
|
|
7937
9665
|
hoveredNavContainerRef.current = null;
|
|
7938
9666
|
setHoveredNavContainerRect(null);
|
|
@@ -7941,12 +9669,57 @@ function OhhwellsBridge() {
|
|
|
7941
9669
|
setToolbarVariant("none");
|
|
7942
9670
|
}
|
|
7943
9671
|
}, [clearSelectedAttr]);
|
|
7944
|
-
const markSelected = (0,
|
|
9672
|
+
const markSelected = (0, import_react9.useCallback)((el) => {
|
|
7945
9673
|
clearSelectedAttr();
|
|
7946
9674
|
el.setAttribute("data-ohw-selected", "");
|
|
7947
9675
|
}, [clearSelectedAttr]);
|
|
7948
|
-
const
|
|
9676
|
+
const resolveHrefKeyElement = (0, import_react9.useCallback)((hrefKey) => {
|
|
9677
|
+
if (isFooterHrefKey(hrefKey)) {
|
|
9678
|
+
return document.querySelector(
|
|
9679
|
+
`footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
9680
|
+
);
|
|
9681
|
+
}
|
|
9682
|
+
if (isNavbarHrefKey(hrefKey)) {
|
|
9683
|
+
const desktop = document.querySelector("[data-ohw-nav-container]");
|
|
9684
|
+
const drawer = document.querySelector("[data-ohw-nav-drawer]");
|
|
9685
|
+
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)}"]`);
|
|
9686
|
+
}
|
|
9687
|
+
return document.querySelector(
|
|
9688
|
+
`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`
|
|
9689
|
+
);
|
|
9690
|
+
}, []);
|
|
9691
|
+
const resyncSelectedNavigationItem = (0, import_react9.useCallback)(() => {
|
|
9692
|
+
const hrefKey = selectedHrefKeyRef.current;
|
|
9693
|
+
if (hrefKey) {
|
|
9694
|
+
const link = resolveHrefKeyElement(hrefKey);
|
|
9695
|
+
if (!link || !isNavigationItem(link)) return;
|
|
9696
|
+
selectedElRef.current = link;
|
|
9697
|
+
const { key, disabled } = getNavigationItemReorderState(link);
|
|
9698
|
+
setReorderHrefKey(key);
|
|
9699
|
+
setReorderDragDisabled(disabled);
|
|
9700
|
+
setIsFooterFrameSelection(false);
|
|
9701
|
+
setToolbarVariant("link-action");
|
|
9702
|
+
setToolbarRect(link.getBoundingClientRect());
|
|
9703
|
+
setSiblingHintRects(collectNavigationItemSiblingHintRects(link));
|
|
9704
|
+
return;
|
|
9705
|
+
}
|
|
9706
|
+
const colAttr = selectedFooterColAttrRef.current;
|
|
9707
|
+
if (colAttr != null) {
|
|
9708
|
+
const column = document.querySelector(`[data-ohw-footer-col="${CSS.escape(colAttr)}"]`) ?? listFooterColumns()[Number(colAttr)] ?? null;
|
|
9709
|
+
if (!column || !isNavigationContainer(column)) return;
|
|
9710
|
+
selectedElRef.current = column;
|
|
9711
|
+
setIsFooterFrameSelection(true);
|
|
9712
|
+
setToolbarVariant("select-frame");
|
|
9713
|
+
setToolbarRect(column.getBoundingClientRect());
|
|
9714
|
+
setSiblingHintRects(
|
|
9715
|
+
listFooterColumns().filter((c) => c !== column).map((c) => c.getBoundingClientRect())
|
|
9716
|
+
);
|
|
9717
|
+
}
|
|
9718
|
+
}, [resolveHrefKeyElement]);
|
|
9719
|
+
const reselectNavigationItem = (0, import_react9.useCallback)((navAnchor) => {
|
|
7949
9720
|
selectedElRef.current = navAnchor;
|
|
9721
|
+
selectedHrefKeyRef.current = navAnchor.getAttribute("data-ohw-href-key");
|
|
9722
|
+
selectedFooterColAttrRef.current = null;
|
|
7950
9723
|
markSelected(navAnchor);
|
|
7951
9724
|
setSelectedIsCta(isNavbarButton2(navAnchor));
|
|
7952
9725
|
const { key, disabled } = getNavigationItemReorderState(navAnchor);
|
|
@@ -7954,10 +9727,11 @@ function OhhwellsBridge() {
|
|
|
7954
9727
|
setReorderDragDisabled(disabled);
|
|
7955
9728
|
setToolbarVariant("link-action");
|
|
7956
9729
|
setToolbarRect(navAnchor.getBoundingClientRect());
|
|
9730
|
+
setSiblingHintRects(collectNavigationItemSiblingHintRects(navAnchor));
|
|
7957
9731
|
setToolbarShowEditLink(false);
|
|
7958
9732
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
7959
9733
|
}, [markSelected]);
|
|
7960
|
-
const commitNavigationTextEdit = (0,
|
|
9734
|
+
const commitNavigationTextEdit = (0, import_react9.useCallback)((navAnchor) => {
|
|
7961
9735
|
const el = activeElRef.current;
|
|
7962
9736
|
if (!el) return;
|
|
7963
9737
|
const key = el.dataset.ohwKey;
|
|
@@ -7984,7 +9758,7 @@ function OhhwellsBridge() {
|
|
|
7984
9758
|
postToParent2({ type: "ow:exit-edit" });
|
|
7985
9759
|
reselectNavigationItem(navAnchor);
|
|
7986
9760
|
}, [postToParent2, reselectNavigationItem]);
|
|
7987
|
-
const handleAddTopLevelNavItem = (0,
|
|
9761
|
+
const handleAddTopLevelNavItem = (0, import_react9.useCallback)(() => {
|
|
7988
9762
|
const items = listNavbarItems();
|
|
7989
9763
|
addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
|
|
7990
9764
|
deselectRef.current();
|
|
@@ -7996,20 +9770,319 @@ function OhhwellsBridge() {
|
|
|
7996
9770
|
intent: "add-nav"
|
|
7997
9771
|
});
|
|
7998
9772
|
}, []);
|
|
7999
|
-
const
|
|
8000
|
-
|
|
8001
|
-
|
|
8002
|
-
|
|
8003
|
-
|
|
8004
|
-
|
|
9773
|
+
const handleAddFooterColumn = (0, import_react9.useCallback)(() => {
|
|
9774
|
+
deselectRef.current();
|
|
9775
|
+
deactivateRef.current();
|
|
9776
|
+
const result = addFooterColumnWithPersist({ postToParent: postToParent2 });
|
|
9777
|
+
editContentRef.current = {
|
|
9778
|
+
...editContentRef.current,
|
|
9779
|
+
...buildFooterColumnEditContentPatch(result)
|
|
9780
|
+
};
|
|
9781
|
+
requestAnimationFrame(() => {
|
|
9782
|
+
selectRef.current(result.firstLink);
|
|
9783
|
+
});
|
|
9784
|
+
}, [postToParent2]);
|
|
9785
|
+
const clearFooterDragVisuals = (0, import_react9.useCallback)(() => {
|
|
9786
|
+
footerDragRef.current = null;
|
|
9787
|
+
setSiblingHintRects([]);
|
|
9788
|
+
setFooterDropSlots([]);
|
|
9789
|
+
setActiveFooterDropIndex(null);
|
|
9790
|
+
setDraggedItemRect(null);
|
|
8005
9791
|
setIsItemDragging(false);
|
|
9792
|
+
unlockFooterDragInteraction();
|
|
9793
|
+
}, []);
|
|
9794
|
+
const refreshFooterDragVisuals = (0, import_react9.useCallback)((session, activeSlot, clientX, clientY) => {
|
|
9795
|
+
const dragged = session.draggedEl;
|
|
9796
|
+
setDraggedItemRect(dragged.getBoundingClientRect());
|
|
9797
|
+
if (typeof clientX === "number" && typeof clientY === "number") {
|
|
9798
|
+
session.lastClientX = clientX;
|
|
9799
|
+
session.lastClientY = clientY;
|
|
9800
|
+
}
|
|
9801
|
+
session.activeSlot = activeSlot;
|
|
9802
|
+
setSiblingHintRects([]);
|
|
9803
|
+
if (session.kind === "link") {
|
|
9804
|
+
const columns = listFooterColumns();
|
|
9805
|
+
const slots2 = [];
|
|
9806
|
+
columns.forEach((col, i) => {
|
|
9807
|
+
slots2.push(...buildLinkDropSlots(col, i));
|
|
9808
|
+
});
|
|
9809
|
+
setFooterDropSlots(slots2);
|
|
9810
|
+
const activeIdx2 = activeSlot ? slots2.findIndex((s) => s.columnIndex === activeSlot.columnIndex && s.insertIndex === activeSlot.insertIndex) : -1;
|
|
9811
|
+
setActiveFooterDropIndex(activeIdx2 >= 0 ? activeIdx2 : null);
|
|
9812
|
+
return;
|
|
9813
|
+
}
|
|
9814
|
+
const slots = buildColumnDropSlots();
|
|
9815
|
+
setFooterDropSlots(slots);
|
|
9816
|
+
const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
|
|
9817
|
+
setActiveFooterDropIndex(activeIdx >= 0 ? activeIdx : null);
|
|
9818
|
+
}, []);
|
|
9819
|
+
const refreshFooterDragVisualsRef = (0, import_react9.useRef)(refreshFooterDragVisuals);
|
|
9820
|
+
refreshFooterDragVisualsRef.current = refreshFooterDragVisuals;
|
|
9821
|
+
const commitFooterDragRef = (0, import_react9.useRef)(() => {
|
|
9822
|
+
});
|
|
9823
|
+
const beginFooterDragRef = (0, import_react9.useRef)(() => {
|
|
9824
|
+
});
|
|
9825
|
+
const beginFooterDrag = (0, import_react9.useCallback)(
|
|
9826
|
+
(session) => {
|
|
9827
|
+
const rect = session.draggedEl.getBoundingClientRect();
|
|
9828
|
+
session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
|
|
9829
|
+
session.lastClientY = session.lastClientY || rect.top + rect.height / 2;
|
|
9830
|
+
session.activeSlot = session.activeSlot ?? null;
|
|
9831
|
+
footerDragRef.current = session;
|
|
9832
|
+
setIsItemDragging(true);
|
|
9833
|
+
lockFooterDuringDrag();
|
|
9834
|
+
siblingHintElRef.current = null;
|
|
9835
|
+
setSiblingHintRect(null);
|
|
9836
|
+
if (session.wasSelected && selectedElRef.current === session.draggedEl) {
|
|
9837
|
+
setToolbarRect(rect);
|
|
9838
|
+
}
|
|
9839
|
+
const initialSlot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
|
|
9840
|
+
refreshFooterDragVisuals(session, initialSlot, session.lastClientX, session.lastClientY);
|
|
9841
|
+
},
|
|
9842
|
+
[refreshFooterDragVisuals]
|
|
9843
|
+
);
|
|
9844
|
+
beginFooterDragRef.current = beginFooterDrag;
|
|
9845
|
+
const commitFooterDrag = (0, import_react9.useCallback)(
|
|
9846
|
+
(clientX, clientY) => {
|
|
9847
|
+
const session = footerDragRef.current;
|
|
9848
|
+
if (!session) {
|
|
9849
|
+
clearFooterDragVisuals();
|
|
9850
|
+
return;
|
|
9851
|
+
}
|
|
9852
|
+
const x = typeof clientX === "number" && (clientX !== 0 || clientY !== 0) ? clientX : session.lastClientX;
|
|
9853
|
+
const y = typeof clientY === "number" && (clientX !== 0 || clientY !== 0) ? clientY : session.lastClientY;
|
|
9854
|
+
let nextOrder = null;
|
|
9855
|
+
const slot = session.activeSlot ?? (session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(x, y, session.hrefKey) : session.kind === "column" ? hitTestColumnDropSlot(x, y) : null);
|
|
9856
|
+
if (session.kind === "link" && session.hrefKey && slot) {
|
|
9857
|
+
nextOrder = planFooterLinkMove(session.hrefKey, slot.columnIndex, slot.insertIndex);
|
|
9858
|
+
} else if (session.kind === "column" && slot) {
|
|
9859
|
+
nextOrder = planFooterColumnMove(session.sourceColumnIndex, slot.insertIndex);
|
|
9860
|
+
}
|
|
9861
|
+
const wasSelected = session.wasSelected;
|
|
9862
|
+
const draggedEl = session.draggedEl;
|
|
9863
|
+
const hrefKey = session.hrefKey;
|
|
9864
|
+
let movedColumnIndex = null;
|
|
9865
|
+
if (session.kind === "column" && slot && nextOrder) {
|
|
9866
|
+
let adjusted = slot.insertIndex;
|
|
9867
|
+
if (session.sourceColumnIndex < slot.insertIndex) adjusted -= 1;
|
|
9868
|
+
movedColumnIndex = Math.max(0, Math.min(adjusted, nextOrder.length - 1));
|
|
9869
|
+
}
|
|
9870
|
+
const applySelectionAfterDrop = () => {
|
|
9871
|
+
if (!wasSelected) {
|
|
9872
|
+
deselectRef.current();
|
|
9873
|
+
return;
|
|
9874
|
+
}
|
|
9875
|
+
if (hrefKey) {
|
|
9876
|
+
selectedHrefKeyRef.current = hrefKey;
|
|
9877
|
+
selectedFooterColAttrRef.current = null;
|
|
9878
|
+
const link = resolveHrefKeyElement(hrefKey);
|
|
9879
|
+
if (link && isNavigationItem(link)) {
|
|
9880
|
+
selectRef.current(link);
|
|
9881
|
+
return;
|
|
9882
|
+
}
|
|
9883
|
+
}
|
|
9884
|
+
if (movedColumnIndex !== null && nextOrder) {
|
|
9885
|
+
const colKeys = nextOrder[movedColumnIndex] ?? [];
|
|
9886
|
+
let column = null;
|
|
9887
|
+
for (const key of colKeys) {
|
|
9888
|
+
const link = document.querySelector(
|
|
9889
|
+
`footer [data-ohw-href-key="${CSS.escape(key)}"]`
|
|
9890
|
+
);
|
|
9891
|
+
if (link) {
|
|
9892
|
+
column = findFooterColumnForLink(link);
|
|
9893
|
+
if (column) break;
|
|
9894
|
+
}
|
|
9895
|
+
}
|
|
9896
|
+
if (!column) column = listFooterColumns()[movedColumnIndex] ?? null;
|
|
9897
|
+
if (column && isNavigationContainer(column)) {
|
|
9898
|
+
selectFrameRef.current(column);
|
|
9899
|
+
return;
|
|
9900
|
+
}
|
|
9901
|
+
}
|
|
9902
|
+
if (document.body.contains(draggedEl)) {
|
|
9903
|
+
if (isNavigationItem(draggedEl)) {
|
|
9904
|
+
selectRef.current(draggedEl);
|
|
9905
|
+
return;
|
|
9906
|
+
}
|
|
9907
|
+
if (isNavigationContainer(draggedEl)) {
|
|
9908
|
+
selectFrameRef.current(draggedEl);
|
|
9909
|
+
return;
|
|
9910
|
+
}
|
|
9911
|
+
}
|
|
9912
|
+
deselectRef.current();
|
|
9913
|
+
};
|
|
9914
|
+
if (nextOrder) {
|
|
9915
|
+
const orderJson = JSON.stringify(nextOrder);
|
|
9916
|
+
editContentRef.current = {
|
|
9917
|
+
...editContentRef.current,
|
|
9918
|
+
[FOOTER_ORDER_KEY]: orderJson
|
|
9919
|
+
};
|
|
9920
|
+
applyFooterOrder(nextOrder);
|
|
9921
|
+
document.querySelectorAll("footer [data-ohw-href-key]").forEach(disableNativeHrefDrag);
|
|
9922
|
+
postToParentRef.current({
|
|
9923
|
+
type: "ow:change",
|
|
9924
|
+
nodes: [{ key: FOOTER_ORDER_KEY, text: orderJson }]
|
|
9925
|
+
});
|
|
9926
|
+
applySelectionAfterDrop();
|
|
9927
|
+
clearFooterDragVisuals();
|
|
9928
|
+
requestAnimationFrame(() => {
|
|
9929
|
+
if (editContentRef.current[FOOTER_ORDER_KEY] === orderJson) {
|
|
9930
|
+
applyFooterOrder(nextOrder);
|
|
9931
|
+
document.querySelectorAll("footer [data-ohw-href-key]").forEach(disableNativeHrefDrag);
|
|
9932
|
+
}
|
|
9933
|
+
applySelectionAfterDrop();
|
|
9934
|
+
requestAnimationFrame(() => {
|
|
9935
|
+
if (editContentRef.current[FOOTER_ORDER_KEY] === orderJson) {
|
|
9936
|
+
applyFooterOrder(nextOrder);
|
|
9937
|
+
}
|
|
9938
|
+
resyncSelectedNavigationItem();
|
|
9939
|
+
});
|
|
9940
|
+
});
|
|
9941
|
+
return;
|
|
9942
|
+
}
|
|
9943
|
+
applySelectionAfterDrop();
|
|
9944
|
+
clearFooterDragVisuals();
|
|
9945
|
+
},
|
|
9946
|
+
[clearFooterDragVisuals, resolveHrefKeyElement, resyncSelectedNavigationItem]
|
|
9947
|
+
);
|
|
9948
|
+
commitFooterDragRef.current = commitFooterDrag;
|
|
9949
|
+
const startFooterLinkDrag = (0, import_react9.useCallback)(
|
|
9950
|
+
(anchor, clientX, clientY, wasSelected) => {
|
|
9951
|
+
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
9952
|
+
if (!hrefKey || !isFooterHrefKey(hrefKey)) return false;
|
|
9953
|
+
const column = findFooterColumnForLink(anchor);
|
|
9954
|
+
const columns = listFooterColumns();
|
|
9955
|
+
beginFooterDrag({
|
|
9956
|
+
kind: "link",
|
|
9957
|
+
hrefKey,
|
|
9958
|
+
columnEl: column,
|
|
9959
|
+
sourceColumnIndex: column ? columns.indexOf(column) : 0,
|
|
9960
|
+
wasSelected,
|
|
9961
|
+
draggedEl: anchor,
|
|
9962
|
+
lastClientX: clientX,
|
|
9963
|
+
lastClientY: clientY,
|
|
9964
|
+
activeSlot: null
|
|
9965
|
+
});
|
|
9966
|
+
return true;
|
|
9967
|
+
},
|
|
9968
|
+
[beginFooterDrag]
|
|
9969
|
+
);
|
|
9970
|
+
const startFooterColumnDrag = (0, import_react9.useCallback)(
|
|
9971
|
+
(columnEl, clientX, clientY, wasSelected) => {
|
|
9972
|
+
const columns = listFooterColumns();
|
|
9973
|
+
const idx = columns.indexOf(columnEl);
|
|
9974
|
+
if (idx < 0) return false;
|
|
9975
|
+
beginFooterDrag({
|
|
9976
|
+
kind: "column",
|
|
9977
|
+
hrefKey: null,
|
|
9978
|
+
columnEl,
|
|
9979
|
+
sourceColumnIndex: idx,
|
|
9980
|
+
wasSelected,
|
|
9981
|
+
draggedEl: columnEl,
|
|
9982
|
+
lastClientX: clientX,
|
|
9983
|
+
lastClientY: clientY,
|
|
9984
|
+
activeSlot: null
|
|
9985
|
+
});
|
|
9986
|
+
return true;
|
|
9987
|
+
},
|
|
9988
|
+
[beginFooterDrag]
|
|
9989
|
+
);
|
|
9990
|
+
const handleItemDragStart = (0, import_react9.useCallback)(
|
|
9991
|
+
(e) => {
|
|
9992
|
+
const selected = selectedElRef.current;
|
|
9993
|
+
if (!selected) {
|
|
9994
|
+
setIsItemDragging(true);
|
|
9995
|
+
return;
|
|
9996
|
+
}
|
|
9997
|
+
const clientX = e?.clientX ?? selected.getBoundingClientRect().left + 8;
|
|
9998
|
+
const clientY = e?.clientY ?? selected.getBoundingClientRect().top + 8;
|
|
9999
|
+
if (startFooterLinkDrag(selected, clientX, clientY, true)) return;
|
|
10000
|
+
if (selected.hasAttribute("data-ohw-footer-col") || isInferredFooterGroup(selected) && selected.closest("footer")) {
|
|
10001
|
+
if (startFooterColumnDrag(selected, clientX, clientY, true)) return;
|
|
10002
|
+
}
|
|
10003
|
+
if (startNavLinkDrag(selected, clientX, clientY, true)) return;
|
|
10004
|
+
siblingHintElRef.current = null;
|
|
10005
|
+
setSiblingHintRect(null);
|
|
10006
|
+
setIsItemDragging(true);
|
|
10007
|
+
},
|
|
10008
|
+
[startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag]
|
|
10009
|
+
);
|
|
10010
|
+
const handleItemDragEnd = (0, import_react9.useCallback)(
|
|
10011
|
+
(e) => {
|
|
10012
|
+
if (footerDragRef.current) {
|
|
10013
|
+
const x = e?.clientX;
|
|
10014
|
+
const y = e?.clientY;
|
|
10015
|
+
if (typeof x === "number" && typeof y === "number" && (x !== 0 || y !== 0)) {
|
|
10016
|
+
commitFooterDrag(x, y);
|
|
10017
|
+
} else {
|
|
10018
|
+
commitFooterDrag();
|
|
10019
|
+
}
|
|
10020
|
+
return;
|
|
10021
|
+
}
|
|
10022
|
+
if (navDragRef.current) {
|
|
10023
|
+
const x = e?.clientX;
|
|
10024
|
+
const y = e?.clientY;
|
|
10025
|
+
if (typeof x === "number" && typeof y === "number" && (x !== 0 || y !== 0)) {
|
|
10026
|
+
commitNavDrag(x, y);
|
|
10027
|
+
} else {
|
|
10028
|
+
commitNavDrag();
|
|
10029
|
+
}
|
|
10030
|
+
return;
|
|
10031
|
+
}
|
|
10032
|
+
setIsItemDragging(false);
|
|
10033
|
+
},
|
|
10034
|
+
[commitFooterDrag, commitNavDrag, navDragRef]
|
|
10035
|
+
);
|
|
10036
|
+
const handleItemChromePointerDown = (0, import_react9.useCallback)((e) => {
|
|
10037
|
+
if (e.button !== 0) return;
|
|
10038
|
+
const selected = selectedElRef.current;
|
|
10039
|
+
if (!selected) return;
|
|
10040
|
+
const hrefKey = selected.getAttribute("data-ohw-href-key");
|
|
10041
|
+
if (hrefKey && isFooterHrefKey(hrefKey)) {
|
|
10042
|
+
footerPointerDragRef.current = {
|
|
10043
|
+
el: selected,
|
|
10044
|
+
kind: "link",
|
|
10045
|
+
startX: e.clientX,
|
|
10046
|
+
startY: e.clientY,
|
|
10047
|
+
pointerId: e.pointerId,
|
|
10048
|
+
wasSelected: true,
|
|
10049
|
+
started: false
|
|
10050
|
+
};
|
|
10051
|
+
return;
|
|
10052
|
+
}
|
|
10053
|
+
if (selected.hasAttribute("data-ohw-footer-col") || isInferredFooterGroup(selected) && selected.closest("footer")) {
|
|
10054
|
+
footerPointerDragRef.current = {
|
|
10055
|
+
el: selected,
|
|
10056
|
+
kind: "column",
|
|
10057
|
+
startX: e.clientX,
|
|
10058
|
+
startY: e.clientY,
|
|
10059
|
+
pointerId: e.pointerId,
|
|
10060
|
+
wasSelected: true,
|
|
10061
|
+
started: false
|
|
10062
|
+
};
|
|
10063
|
+
return;
|
|
10064
|
+
}
|
|
10065
|
+
if (armNavPressFromChrome(selected, e.clientX, e.clientY, e.pointerId)) return;
|
|
10066
|
+
}, [armNavPressFromChrome]);
|
|
10067
|
+
const handleItemChromeClick = (0, import_react9.useCallback)((clientX, clientY) => {
|
|
10068
|
+
if (suppressNextClickRef.current || Date.now() < suppressClickUntilRef.current) {
|
|
10069
|
+
suppressNextClickRef.current = false;
|
|
10070
|
+
return;
|
|
10071
|
+
}
|
|
10072
|
+
const selected = selectedElRef.current;
|
|
10073
|
+
if (!selected || !isNavigationItem(selected)) return;
|
|
10074
|
+
const editable = selected.querySelector('[data-ohw-editable="text"]') ?? selected.querySelector("[data-ohw-editable]");
|
|
10075
|
+
if (!editable) return;
|
|
10076
|
+
activateRef.current(editable, { caretX: clientX, caretY: clientY });
|
|
8006
10077
|
}, []);
|
|
8007
10078
|
reselectNavigationItemRef.current = reselectNavigationItem;
|
|
8008
10079
|
commitNavigationTextEditRef.current = commitNavigationTextEdit;
|
|
8009
|
-
const select = (0,
|
|
10080
|
+
const select = (0, import_react9.useCallback)((anchor) => {
|
|
8010
10081
|
if (!isNavigationItem(anchor)) return;
|
|
8011
10082
|
if (activeElRef.current) deactivate();
|
|
8012
10083
|
selectedElRef.current = anchor;
|
|
10084
|
+
selectedHrefKeyRef.current = anchor.getAttribute("data-ohw-href-key");
|
|
10085
|
+
selectedFooterColAttrRef.current = null;
|
|
8013
10086
|
markSelected(anchor);
|
|
8014
10087
|
setSelectedIsCta(isNavbarButton2(anchor));
|
|
8015
10088
|
clearHrefKeyHover(anchor);
|
|
@@ -8019,19 +10092,24 @@ function OhhwellsBridge() {
|
|
|
8019
10092
|
hoveredItemElRef.current = null;
|
|
8020
10093
|
siblingHintElRef.current = null;
|
|
8021
10094
|
setSiblingHintRect(null);
|
|
10095
|
+
setSiblingHintRects(collectNavigationItemSiblingHintRects(anchor));
|
|
8022
10096
|
setIsItemDragging(false);
|
|
8023
10097
|
const { key, disabled } = getNavigationItemReorderState(anchor);
|
|
8024
10098
|
setReorderHrefKey(key);
|
|
8025
10099
|
setReorderDragDisabled(disabled);
|
|
10100
|
+
setIsFooterFrameSelection(false);
|
|
8026
10101
|
setToolbarVariant("link-action");
|
|
8027
10102
|
setToolbarRect(anchor.getBoundingClientRect());
|
|
8028
10103
|
setToolbarShowEditLink(false);
|
|
8029
10104
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
8030
10105
|
}, [deactivate, markSelected]);
|
|
8031
|
-
const selectFrame = (0,
|
|
10106
|
+
const selectFrame = (0, import_react9.useCallback)((el) => {
|
|
8032
10107
|
if (!isNavigationContainer(el)) return;
|
|
8033
10108
|
if (activeElRef.current) deactivate();
|
|
10109
|
+
const isFooterColumn = !isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || Boolean(el.closest("footer") && isInferredFooterGroup(el)));
|
|
8034
10110
|
selectedElRef.current = el;
|
|
10111
|
+
selectedHrefKeyRef.current = null;
|
|
10112
|
+
selectedFooterColAttrRef.current = isFooterColumn ? el.getAttribute("data-ohw-footer-col") ?? String(listFooterColumns().indexOf(el)) : null;
|
|
8035
10113
|
markSelected(el);
|
|
8036
10114
|
setSelectedIsCta(false);
|
|
8037
10115
|
clearHrefKeyHover(el);
|
|
@@ -8041,18 +10119,24 @@ function OhhwellsBridge() {
|
|
|
8041
10119
|
hoveredItemElRef.current = null;
|
|
8042
10120
|
siblingHintElRef.current = null;
|
|
8043
10121
|
setSiblingHintRect(null);
|
|
10122
|
+
setSiblingHintRects(
|
|
10123
|
+
isFooterColumn ? listFooterColumns().filter((column) => column !== el).map((column) => column.getBoundingClientRect()) : []
|
|
10124
|
+
);
|
|
8044
10125
|
setIsItemDragging(false);
|
|
8045
10126
|
setReorderHrefKey(null);
|
|
8046
10127
|
setReorderDragDisabled(false);
|
|
10128
|
+
setIsFooterFrameSelection(isFooterColumn);
|
|
8047
10129
|
setToolbarVariant("select-frame");
|
|
8048
10130
|
setToolbarRect(el.getBoundingClientRect());
|
|
8049
10131
|
setToolbarShowEditLink(false);
|
|
8050
10132
|
setActiveCommands(/* @__PURE__ */ new Set());
|
|
8051
10133
|
}, [deactivate, markSelected]);
|
|
8052
|
-
const activate = (0,
|
|
10134
|
+
const activate = (0, import_react9.useCallback)((el, options) => {
|
|
8053
10135
|
if (activeElRef.current === el) return;
|
|
8054
10136
|
clearSelectedAttr();
|
|
8055
10137
|
selectedElRef.current = null;
|
|
10138
|
+
selectedHrefKeyRef.current = null;
|
|
10139
|
+
selectedFooterColAttrRef.current = null;
|
|
8056
10140
|
setSelectedIsCta(false);
|
|
8057
10141
|
deactivate();
|
|
8058
10142
|
if (hoveredImageRef.current) {
|
|
@@ -8062,7 +10146,10 @@ function OhhwellsBridge() {
|
|
|
8062
10146
|
setToolbarVariant("rich-text");
|
|
8063
10147
|
siblingHintElRef.current = null;
|
|
8064
10148
|
setSiblingHintRect(null);
|
|
10149
|
+
setSiblingHintRects([]);
|
|
8065
10150
|
setIsItemDragging(false);
|
|
10151
|
+
const preActivationSelection = window.getSelection();
|
|
10152
|
+
const preservedRange = preActivationSelection && preActivationSelection.rangeCount > 0 && !preActivationSelection.isCollapsed && el.contains(preActivationSelection.getRangeAt(0).commonAncestorContainer) ? preActivationSelection.getRangeAt(0).cloneRange() : null;
|
|
8066
10153
|
el.setAttribute("contenteditable", "true");
|
|
8067
10154
|
el.setAttribute("data-ohw-editing", "");
|
|
8068
10155
|
el.removeAttribute("data-ohw-hovered");
|
|
@@ -8070,8 +10157,16 @@ function OhhwellsBridge() {
|
|
|
8070
10157
|
activeElRef.current = el;
|
|
8071
10158
|
originalContentRef.current = el.innerHTML;
|
|
8072
10159
|
el.focus({ preventScroll: true });
|
|
8073
|
-
if (
|
|
8074
|
-
|
|
10160
|
+
if (preservedRange) {
|
|
10161
|
+
const selection = window.getSelection();
|
|
10162
|
+
selection?.removeAllRanges();
|
|
10163
|
+
selection?.addRange(preservedRange);
|
|
10164
|
+
} else if (options?.caretX !== void 0 && options?.caretY !== void 0) {
|
|
10165
|
+
const { caretX, caretY } = options;
|
|
10166
|
+
placeCaretAtPoint(el, caretX, caretY);
|
|
10167
|
+
requestAnimationFrame(() => {
|
|
10168
|
+
if (activeElRef.current === el) placeCaretAtPoint(el, caretX, caretY);
|
|
10169
|
+
});
|
|
8075
10170
|
} else {
|
|
8076
10171
|
const selection = window.getSelection();
|
|
8077
10172
|
if (selection && selection.rangeCount === 0) {
|
|
@@ -8101,7 +10196,7 @@ function OhhwellsBridge() {
|
|
|
8101
10196
|
selectRef.current = select;
|
|
8102
10197
|
selectFrameRef.current = selectFrame;
|
|
8103
10198
|
deselectRef.current = deselect;
|
|
8104
|
-
(0,
|
|
10199
|
+
(0, import_react9.useLayoutEffect)(() => {
|
|
8105
10200
|
if (!subdomain || isEditMode) {
|
|
8106
10201
|
setFetchState("done");
|
|
8107
10202
|
return;
|
|
@@ -8142,6 +10237,7 @@ function OhhwellsBridge() {
|
|
|
8142
10237
|
applyLinkByKey(key, val);
|
|
8143
10238
|
}
|
|
8144
10239
|
reconcileNavbarItemsFromContent(content);
|
|
10240
|
+
reconcileFooterOrderFromContent(content);
|
|
8145
10241
|
enforceLinkHrefs();
|
|
8146
10242
|
initSectionsFromContent(content, true);
|
|
8147
10243
|
sectionsLoadedRef.current = true;
|
|
@@ -8170,7 +10266,7 @@ function OhhwellsBridge() {
|
|
|
8170
10266
|
cancelled = true;
|
|
8171
10267
|
};
|
|
8172
10268
|
}, [subdomain, isEditMode]);
|
|
8173
|
-
(0,
|
|
10269
|
+
(0, import_react9.useEffect)(() => {
|
|
8174
10270
|
if (!subdomain || isEditMode) return;
|
|
8175
10271
|
let debounceTimer = null;
|
|
8176
10272
|
let observer = null;
|
|
@@ -8202,6 +10298,7 @@ function OhhwellsBridge() {
|
|
|
8202
10298
|
applyLinkByKey(key, val);
|
|
8203
10299
|
}
|
|
8204
10300
|
reconcileNavbarItemsFromContent(content);
|
|
10301
|
+
reconcileFooterOrderFromContent(content);
|
|
8205
10302
|
} finally {
|
|
8206
10303
|
observer?.observe(document.body, { childList: true, subtree: true });
|
|
8207
10304
|
}
|
|
@@ -8219,16 +10316,16 @@ function OhhwellsBridge() {
|
|
|
8219
10316
|
if (debounceTimer) clearTimeout(debounceTimer);
|
|
8220
10317
|
};
|
|
8221
10318
|
}, [subdomain, isEditMode, pathname]);
|
|
8222
|
-
(0,
|
|
10319
|
+
(0, import_react9.useLayoutEffect)(() => {
|
|
8223
10320
|
const el = document.getElementById("ohw-loader");
|
|
8224
10321
|
if (!el) return;
|
|
8225
10322
|
const visible = Boolean(subdomain) && fetchState !== "done";
|
|
8226
10323
|
el.style.display = visible ? "flex" : "none";
|
|
8227
10324
|
}, [subdomain, fetchState]);
|
|
8228
|
-
(0,
|
|
10325
|
+
(0, import_react9.useEffect)(() => {
|
|
8229
10326
|
postToParent2({ type: "ow:navigation", path: pathname });
|
|
8230
10327
|
}, [pathname, postToParent2]);
|
|
8231
|
-
(0,
|
|
10328
|
+
(0, import_react9.useEffect)(() => {
|
|
8232
10329
|
if (!isEditMode) return;
|
|
8233
10330
|
if (linkPopoverSessionRef.current?.intent === "add-nav") return;
|
|
8234
10331
|
if (document.querySelector("[data-ohw-section-picker]")) return;
|
|
@@ -8236,7 +10333,7 @@ function OhhwellsBridge() {
|
|
|
8236
10333
|
deselectRef.current();
|
|
8237
10334
|
deactivateRef.current();
|
|
8238
10335
|
}, [pathname, isEditMode]);
|
|
8239
|
-
(0,
|
|
10336
|
+
(0, import_react9.useEffect)(() => {
|
|
8240
10337
|
const contentForNav = () => {
|
|
8241
10338
|
if (isEditMode) return editContentRef.current;
|
|
8242
10339
|
if (!subdomain) return {};
|
|
@@ -8248,6 +10345,7 @@ function OhhwellsBridge() {
|
|
|
8248
10345
|
const roots = observeRoots();
|
|
8249
10346
|
if (roots.length === 0) {
|
|
8250
10347
|
reconcileNavbarItemsFromContent(contentForNav());
|
|
10348
|
+
reconcileFooterOrderFromContent(contentForNav());
|
|
8251
10349
|
if (isEditMode) syncNavigationDragCursorAttrs();
|
|
8252
10350
|
return;
|
|
8253
10351
|
}
|
|
@@ -8260,11 +10358,26 @@ function OhhwellsBridge() {
|
|
|
8260
10358
|
}
|
|
8261
10359
|
};
|
|
8262
10360
|
const run = () => {
|
|
8263
|
-
if (applying) return;
|
|
10361
|
+
if (footerDragRef.current || navDragRef.current || applying) return;
|
|
8264
10362
|
applying = true;
|
|
8265
10363
|
observer?.disconnect();
|
|
8266
10364
|
try {
|
|
8267
|
-
|
|
10365
|
+
const content = contentForNav();
|
|
10366
|
+
reconcileNavbarItemsFromContent(content);
|
|
10367
|
+
reconcileFooterOrderFromContent(content);
|
|
10368
|
+
document.querySelectorAll("footer [data-ohw-href-key]").forEach((el) => {
|
|
10369
|
+
if (isFooterHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
10370
|
+
disableNativeHrefDrag(el);
|
|
10371
|
+
}
|
|
10372
|
+
});
|
|
10373
|
+
document.querySelectorAll(
|
|
10374
|
+
"nav [data-ohw-href-key], [data-ohw-nav-container] [data-ohw-href-key], [data-ohw-nav-drawer] [data-ohw-href-key]"
|
|
10375
|
+
).forEach((el) => {
|
|
10376
|
+
if (isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))) {
|
|
10377
|
+
disableNativeHrefDrag(el);
|
|
10378
|
+
}
|
|
10379
|
+
});
|
|
10380
|
+
resyncSelectedNavigationItem();
|
|
8268
10381
|
if (isEditMode) syncNavigationDragCursorAttrs();
|
|
8269
10382
|
} finally {
|
|
8270
10383
|
applying = false;
|
|
@@ -8284,8 +10397,8 @@ function OhhwellsBridge() {
|
|
|
8284
10397
|
if (rafId != null) cancelAnimationFrame(rafId);
|
|
8285
10398
|
observer?.disconnect();
|
|
8286
10399
|
};
|
|
8287
|
-
}, [isEditMode, pathname, subdomain, fetchState]);
|
|
8288
|
-
(0,
|
|
10400
|
+
}, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
|
|
10401
|
+
(0, import_react9.useEffect)(() => {
|
|
8289
10402
|
if (!isEditMode) return;
|
|
8290
10403
|
const measure = () => {
|
|
8291
10404
|
const h = document.body.scrollHeight;
|
|
@@ -8309,7 +10422,7 @@ function OhhwellsBridge() {
|
|
|
8309
10422
|
window.removeEventListener("resize", handleResize);
|
|
8310
10423
|
};
|
|
8311
10424
|
}, [pathname, isEditMode, postToParent2]);
|
|
8312
|
-
(0,
|
|
10425
|
+
(0, import_react9.useEffect)(() => {
|
|
8313
10426
|
if (!subdomainFromQuery || isEditMode) return;
|
|
8314
10427
|
const handleClick = (e) => {
|
|
8315
10428
|
const anchor = e.target.closest("a");
|
|
@@ -8325,7 +10438,7 @@ function OhhwellsBridge() {
|
|
|
8325
10438
|
document.addEventListener("click", handleClick, true);
|
|
8326
10439
|
return () => document.removeEventListener("click", handleClick, true);
|
|
8327
10440
|
}, [subdomainFromQuery, isEditMode, router]);
|
|
8328
|
-
(0,
|
|
10441
|
+
(0, import_react9.useEffect)(() => {
|
|
8329
10442
|
if (!isEditMode) {
|
|
8330
10443
|
editStylesRef.current?.base.remove();
|
|
8331
10444
|
editStylesRef.current?.forceHover.remove();
|
|
@@ -8387,6 +10500,21 @@ function OhhwellsBridge() {
|
|
|
8387
10500
|
outline: none !important;
|
|
8388
10501
|
outline-offset: 0 !important;
|
|
8389
10502
|
}
|
|
10503
|
+
/* Editor chrome owns selection \u2014 suppress native focus rings on nav/footer items. */
|
|
10504
|
+
nav [data-ohw-href-key]:focus,
|
|
10505
|
+
nav [data-ohw-href-key]:focus-visible,
|
|
10506
|
+
nav [data-ohw-href-key]:focus-within,
|
|
10507
|
+
footer [data-ohw-href-key]:focus,
|
|
10508
|
+
footer [data-ohw-href-key]:focus-visible,
|
|
10509
|
+
footer [data-ohw-href-key]:focus-within,
|
|
10510
|
+
nav [data-ohw-href-key] [data-ohw-editable]:focus,
|
|
10511
|
+
nav [data-ohw-href-key] [data-ohw-editable]:focus-visible,
|
|
10512
|
+
footer [data-ohw-href-key] [data-ohw-editable]:focus,
|
|
10513
|
+
footer [data-ohw-href-key] [data-ohw-editable]:focus-visible {
|
|
10514
|
+
outline: none !important;
|
|
10515
|
+
outline-offset: 0 !important;
|
|
10516
|
+
box-shadow: none !important;
|
|
10517
|
+
}
|
|
8390
10518
|
/* Text edit wins over grab/default (must beat [data-ohw-can-drag] *). */
|
|
8391
10519
|
[data-ohw-editing],
|
|
8392
10520
|
[data-ohw-editing] *,
|
|
@@ -8428,12 +10556,39 @@ function OhhwellsBridge() {
|
|
|
8428
10556
|
syncNavigationDragCursorAttrs();
|
|
8429
10557
|
refreshStateRules();
|
|
8430
10558
|
const handleClick = (e) => {
|
|
10559
|
+
if (suppressNextClickRef.current || Date.now() < suppressClickUntilRef.current) {
|
|
10560
|
+
suppressNextClickRef.current = false;
|
|
10561
|
+
e.preventDefault();
|
|
10562
|
+
e.stopPropagation();
|
|
10563
|
+
return;
|
|
10564
|
+
}
|
|
8431
10565
|
const target = e.target;
|
|
8432
10566
|
if (target.closest("[data-ohw-toolbar]")) return;
|
|
8433
10567
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
8434
10568
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
8435
10569
|
if (isInsideLinkEditor(target)) return;
|
|
8436
10570
|
if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
|
|
10571
|
+
if (target.closest("[data-ohw-item-drag-surface]")) {
|
|
10572
|
+
e.preventDefault();
|
|
10573
|
+
e.stopPropagation();
|
|
10574
|
+
const selected = selectedElRef.current;
|
|
10575
|
+
if (selected && isNavigationItem(selected)) {
|
|
10576
|
+
const editable2 = selected.querySelector('[data-ohw-editable="text"]') ?? selected.querySelector("[data-ohw-editable]");
|
|
10577
|
+
if (editable2) {
|
|
10578
|
+
activateRef.current(editable2, {
|
|
10579
|
+
caretX: e.clientX,
|
|
10580
|
+
caretY: e.clientY
|
|
10581
|
+
});
|
|
10582
|
+
}
|
|
10583
|
+
} else if (selected?.hasAttribute("data-ohw-footer-col")) {
|
|
10584
|
+
const link = listFooterLinksInColumn(selected).find((el) => {
|
|
10585
|
+
const r2 = el.getBoundingClientRect();
|
|
10586
|
+
return e.clientX >= r2.left && e.clientX <= r2.right && e.clientY >= r2.top && e.clientY <= r2.bottom;
|
|
10587
|
+
});
|
|
10588
|
+
if (link) selectRef.current(link);
|
|
10589
|
+
}
|
|
10590
|
+
return;
|
|
10591
|
+
}
|
|
8437
10592
|
const navFromChrome = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
|
|
8438
10593
|
if (navFromChrome) {
|
|
8439
10594
|
e.preventDefault();
|
|
@@ -8462,7 +10617,9 @@ function OhhwellsBridge() {
|
|
|
8462
10617
|
if (inActive || inActiveNav) {
|
|
8463
10618
|
e.preventDefault();
|
|
8464
10619
|
e.stopPropagation();
|
|
8465
|
-
|
|
10620
|
+
const selection = window.getSelection();
|
|
10621
|
+
const hasRangeSelection = Boolean(selection && !selection.isCollapsed);
|
|
10622
|
+
if (e.detail < 2 && !hasRangeSelection) {
|
|
8466
10623
|
placeCaretAtPoint(active, e.clientX, e.clientY);
|
|
8467
10624
|
refreshActiveCommandsRef.current();
|
|
8468
10625
|
}
|
|
@@ -8505,17 +10662,45 @@ function OhhwellsBridge() {
|
|
|
8505
10662
|
}
|
|
8506
10663
|
e.preventDefault();
|
|
8507
10664
|
e.stopPropagation();
|
|
8508
|
-
activateRef.current(editable);
|
|
10665
|
+
activateRef.current(editable, { caretX: e.clientX, caretY: e.clientY });
|
|
8509
10666
|
return;
|
|
8510
10667
|
}
|
|
8511
10668
|
const hrefAnchor = getNavigationItemAnchor(target);
|
|
8512
10669
|
if (hrefAnchor) {
|
|
8513
10670
|
e.preventDefault();
|
|
8514
10671
|
e.stopPropagation();
|
|
8515
|
-
if (selectedElRef.current === hrefAnchor)
|
|
10672
|
+
if (selectedElRef.current === hrefAnchor) {
|
|
10673
|
+
const textEditable = hrefAnchor.querySelector('[data-ohw-editable="text"]') ?? hrefAnchor.querySelector("[data-ohw-editable]");
|
|
10674
|
+
if (textEditable) {
|
|
10675
|
+
activateRef.current(textEditable, {
|
|
10676
|
+
caretX: e.clientX,
|
|
10677
|
+
caretY: e.clientY
|
|
10678
|
+
});
|
|
10679
|
+
}
|
|
10680
|
+
return;
|
|
10681
|
+
}
|
|
8516
10682
|
selectRef.current(hrefAnchor);
|
|
8517
10683
|
return;
|
|
8518
10684
|
}
|
|
10685
|
+
const footerColClick = target.closest("[data-ohw-footer-col]");
|
|
10686
|
+
if (footerColClick) {
|
|
10687
|
+
e.preventDefault();
|
|
10688
|
+
e.stopPropagation();
|
|
10689
|
+
selectFrameRef.current(footerColClick);
|
|
10690
|
+
return;
|
|
10691
|
+
}
|
|
10692
|
+
const footerLinksToSelect = resolveFooterLinksContainerSelectionTarget(
|
|
10693
|
+
target,
|
|
10694
|
+
e.clientX,
|
|
10695
|
+
e.clientY,
|
|
10696
|
+
isPointOverNavItem
|
|
10697
|
+
);
|
|
10698
|
+
if (footerLinksToSelect) {
|
|
10699
|
+
e.preventDefault();
|
|
10700
|
+
e.stopPropagation();
|
|
10701
|
+
selectFrameRef.current(footerLinksToSelect);
|
|
10702
|
+
return;
|
|
10703
|
+
}
|
|
8519
10704
|
const navContainerToSelect = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
|
|
8520
10705
|
if (navContainerToSelect) {
|
|
8521
10706
|
e.preventDefault();
|
|
@@ -8574,8 +10759,8 @@ function OhhwellsBridge() {
|
|
|
8574
10759
|
return;
|
|
8575
10760
|
}
|
|
8576
10761
|
const navLabel = getNavigationLabelEditable(target);
|
|
8577
|
-
|
|
8578
|
-
|
|
10762
|
+
const editable = navLabel?.editable ?? target.closest('[data-ohw-editable="text"], [data-ohw-editable="plain"]');
|
|
10763
|
+
if (!editable || isMediaEditable(editable) || editable.dataset.ohwEditable === "link") return;
|
|
8579
10764
|
e.preventDefault();
|
|
8580
10765
|
e.stopPropagation();
|
|
8581
10766
|
if (activeElRef.current !== editable) {
|
|
@@ -8589,16 +10774,45 @@ function OhhwellsBridge() {
|
|
|
8589
10774
|
const handleMouseOver = (e) => {
|
|
8590
10775
|
if (document.documentElement.hasAttribute("data-ohw-section-picking")) return;
|
|
8591
10776
|
const target = e.target;
|
|
8592
|
-
if (
|
|
8593
|
-
|
|
8594
|
-
|
|
8595
|
-
|
|
8596
|
-
|
|
8597
|
-
|
|
8598
|
-
|
|
8599
|
-
|
|
10777
|
+
if (linkPopoverOpenRef.current) {
|
|
10778
|
+
hoveredItemElRef.current = null;
|
|
10779
|
+
setHoveredItemRect(null);
|
|
10780
|
+
hoveredNavContainerRef.current = null;
|
|
10781
|
+
setHoveredNavContainerRect(null);
|
|
10782
|
+
return;
|
|
10783
|
+
}
|
|
10784
|
+
{
|
|
10785
|
+
const selected2 = selectedElRef.current;
|
|
10786
|
+
const selectedIsFooterColumn = Boolean(selected2) && !isFooterLinksContainer(selected2) && (selected2.hasAttribute("data-ohw-footer-col") || selected2.hasAttribute("data-ohw-footer-column") || Boolean(selected2.closest("footer") && isInferredFooterGroup(selected2)));
|
|
10787
|
+
const allowNavContainerHover = toolbarVariantRef.current !== "select-frame";
|
|
10788
|
+
const allowFooterLinksHover = toolbarVariantRef.current !== "select-frame" || selectedIsFooterColumn;
|
|
10789
|
+
if (allowNavContainerHover) {
|
|
10790
|
+
const navContainer = target.closest("[data-ohw-nav-container]");
|
|
10791
|
+
if (navContainer && !getNavigationItemAnchor(target)) {
|
|
10792
|
+
hoveredNavContainerRef.current = navContainer;
|
|
10793
|
+
setHoveredNavContainerRect(navContainer.getBoundingClientRect());
|
|
10794
|
+
hoveredItemElRef.current = null;
|
|
10795
|
+
setHoveredItemRect(null);
|
|
10796
|
+
return;
|
|
10797
|
+
}
|
|
8600
10798
|
}
|
|
8601
|
-
if (
|
|
10799
|
+
if (allowFooterLinksHover) {
|
|
10800
|
+
const navContainer = target.closest("[data-ohw-nav-container]");
|
|
10801
|
+
if (!navContainer) {
|
|
10802
|
+
const footerLinks = target.closest("[data-ohw-footer-links], .rb-footer-links") ?? null;
|
|
10803
|
+
if (footerLinks && selected2 !== footerLinks && !getNavigationItemAnchor(target) && !target.closest("[data-ohw-footer-col], [data-ohw-footer-column]")) {
|
|
10804
|
+
hoveredNavContainerRef.current = footerLinks;
|
|
10805
|
+
setHoveredNavContainerRect(footerLinks.getBoundingClientRect());
|
|
10806
|
+
hoveredItemElRef.current = null;
|
|
10807
|
+
setHoveredItemRect(null);
|
|
10808
|
+
return;
|
|
10809
|
+
}
|
|
10810
|
+
if (!footerLinks) {
|
|
10811
|
+
hoveredNavContainerRef.current = null;
|
|
10812
|
+
setHoveredNavContainerRect(null);
|
|
10813
|
+
}
|
|
10814
|
+
}
|
|
10815
|
+
} else if (toolbarVariantRef.current === "select-frame") {
|
|
8602
10816
|
hoveredNavContainerRef.current = null;
|
|
8603
10817
|
setHoveredNavContainerRect(null);
|
|
8604
10818
|
}
|
|
@@ -8608,12 +10822,21 @@ function OhhwellsBridge() {
|
|
|
8608
10822
|
hoveredNavContainerRef.current = null;
|
|
8609
10823
|
setHoveredNavContainerRect(null);
|
|
8610
10824
|
const selected2 = selectedElRef.current;
|
|
8611
|
-
if (selected2 === navAnchor
|
|
10825
|
+
if (selected2 === navAnchor) return;
|
|
8612
10826
|
clearHrefKeyHover(navAnchor);
|
|
8613
10827
|
hoveredItemElRef.current = navAnchor;
|
|
8614
10828
|
setHoveredItemRect(navAnchor.getBoundingClientRect());
|
|
8615
10829
|
return;
|
|
8616
10830
|
}
|
|
10831
|
+
const footerCol = target.closest("[data-ohw-footer-col]") ?? target.closest("[data-ohw-footer-column]");
|
|
10832
|
+
if (footerCol) {
|
|
10833
|
+
hoveredNavContainerRef.current = null;
|
|
10834
|
+
setHoveredNavContainerRect(null);
|
|
10835
|
+
if (selectedElRef.current === footerCol) return;
|
|
10836
|
+
hoveredItemElRef.current = footerCol;
|
|
10837
|
+
setHoveredItemRect(footerCol.getBoundingClientRect());
|
|
10838
|
+
return;
|
|
10839
|
+
}
|
|
8617
10840
|
const editable = target.closest("[data-ohw-editable]");
|
|
8618
10841
|
if (!editable) return;
|
|
8619
10842
|
const selected = selectedElRef.current;
|
|
@@ -8631,14 +10854,25 @@ function OhhwellsBridge() {
|
|
|
8631
10854
|
};
|
|
8632
10855
|
const handleMouseOut = (e) => {
|
|
8633
10856
|
const target = e.target;
|
|
8634
|
-
if (target.closest("[data-ohw-nav-container], [data-ohw-footer-column]")) {
|
|
10857
|
+
if (target.closest("[data-ohw-nav-container], [data-ohw-footer-col], [data-ohw-footer-column], [data-ohw-footer-links], .rb-footer-links")) {
|
|
8635
10858
|
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
8636
|
-
if (related2?.closest("[data-ohw-nav-container], [data-ohw-footer-column], [data-ohw-navbar-container-chrome], [data-ohw-navbar-add-button]")) {
|
|
10859
|
+
if (related2?.closest("[data-ohw-nav-container], [data-ohw-footer-col], [data-ohw-footer-column], [data-ohw-footer-links], .rb-footer-links, [data-ohw-navbar-container-chrome], [data-ohw-navbar-add-button], [data-ohw-footer-container-chrome], [data-ohw-footer-add-button]")) {
|
|
8637
10860
|
return;
|
|
8638
10861
|
}
|
|
8639
10862
|
hoveredNavContainerRef.current = null;
|
|
8640
10863
|
setHoveredNavContainerRect(null);
|
|
8641
10864
|
}
|
|
10865
|
+
const footerCol = target.closest("[data-ohw-footer-col]") ?? target.closest("[data-ohw-footer-column]");
|
|
10866
|
+
if (footerCol && hoveredItemElRef.current === footerCol) {
|
|
10867
|
+
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
10868
|
+
if (related2?.closest("[data-ohw-drag-handle-container], [data-ohw-item-interaction]")) return;
|
|
10869
|
+
if (related2?.closest("[data-ohw-footer-col], [data-ohw-footer-column]") === footerCol) {
|
|
10870
|
+
return;
|
|
10871
|
+
}
|
|
10872
|
+
hoveredItemElRef.current = null;
|
|
10873
|
+
setHoveredItemRect(null);
|
|
10874
|
+
return;
|
|
10875
|
+
}
|
|
8642
10876
|
const navAnchor = getNavigationItemAnchor(target);
|
|
8643
10877
|
if (navAnchor) {
|
|
8644
10878
|
const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
|
|
@@ -8717,6 +10951,15 @@ function OhhwellsBridge() {
|
|
|
8717
10951
|
if (track) track.setAttribute("data-ohw-hover-paused", "");
|
|
8718
10952
|
};
|
|
8719
10953
|
const clearImageHover = () => setMediaHover(null);
|
|
10954
|
+
const dismissImageHover = () => {
|
|
10955
|
+
if (hoveredImageRef.current) {
|
|
10956
|
+
hoveredImageRef.current = null;
|
|
10957
|
+
hoveredImageHasTextOverlapRef.current = false;
|
|
10958
|
+
resumeAnimTracks();
|
|
10959
|
+
postToParentRef.current({ type: "ow:image-unhover" });
|
|
10960
|
+
}
|
|
10961
|
+
clearImageHover();
|
|
10962
|
+
};
|
|
8720
10963
|
const findImageAtPoint = (clientX, clientY, fromParentViewport) => {
|
|
8721
10964
|
const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
|
|
8722
10965
|
const images = Array.from(document.querySelectorAll(MEDIA_SELECTOR));
|
|
@@ -8760,26 +11003,21 @@ function OhhwellsBridge() {
|
|
|
8760
11003
|
}
|
|
8761
11004
|
return smallest;
|
|
8762
11005
|
};
|
|
8763
|
-
const dismissImageHover = () => {
|
|
8764
|
-
if (hoveredImageRef.current) {
|
|
8765
|
-
hoveredImageRef.current = null;
|
|
8766
|
-
hoveredImageHasTextOverlapRef.current = false;
|
|
8767
|
-
resumeAnimTracks();
|
|
8768
|
-
postToParentRef.current({ type: "ow:image-unhover" });
|
|
8769
|
-
}
|
|
8770
|
-
};
|
|
8771
11006
|
const probeNavigationHoverAt = (x, y) => {
|
|
8772
|
-
|
|
11007
|
+
const selected = selectedElRef.current;
|
|
11008
|
+
const selectedIsFooterColumn = Boolean(selected) && !isFooterLinksContainer(selected) && (selected.hasAttribute("data-ohw-footer-col") || selected.hasAttribute("data-ohw-footer-column") || Boolean(selected.closest("footer") && isInferredFooterGroup(selected)));
|
|
11009
|
+
const selectedIsFooterLinks = Boolean(selected && isFooterLinksContainer(selected));
|
|
11010
|
+
const allowNavContainerHover = toolbarVariantRef.current !== "select-frame";
|
|
11011
|
+
const allowFooterLinksHover = (toolbarVariantRef.current !== "select-frame" || selectedIsFooterColumn) && !selectedIsFooterLinks;
|
|
11012
|
+
if (toolbarVariantRef.current === "select-frame" && !allowFooterLinksHover) {
|
|
8773
11013
|
hoveredNavContainerRef.current = null;
|
|
8774
11014
|
setHoveredNavContainerRect(null);
|
|
8775
|
-
return;
|
|
8776
11015
|
}
|
|
8777
|
-
const
|
|
8778
|
-
|
|
8779
|
-
|
|
8780
|
-
|
|
8781
|
-
|
|
8782
|
-
for (const container of frameContainers) {
|
|
11016
|
+
const navContainers = Array.from(
|
|
11017
|
+
document.querySelectorAll("[data-ohw-nav-container]")
|
|
11018
|
+
);
|
|
11019
|
+
const footerColumns = listFooterColumns();
|
|
11020
|
+
for (const container of [...navContainers, ...footerColumns]) {
|
|
8783
11021
|
const containerRect = container.getBoundingClientRect();
|
|
8784
11022
|
const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
|
|
8785
11023
|
if (!overContainer) continue;
|
|
@@ -8793,26 +11031,66 @@ function OhhwellsBridge() {
|
|
|
8793
11031
|
if (navItemHit) {
|
|
8794
11032
|
hoveredNavContainerRef.current = null;
|
|
8795
11033
|
setHoveredNavContainerRect(null);
|
|
8796
|
-
|
|
8797
|
-
if (selected !== navItemHit && !selected?.contains(navItemHit)) {
|
|
11034
|
+
if (selected !== navItemHit) {
|
|
8798
11035
|
clearHrefKeyHover(navItemHit);
|
|
8799
11036
|
hoveredItemElRef.current = navItemHit;
|
|
8800
11037
|
setHoveredItemRect(navItemHit.getBoundingClientRect());
|
|
11038
|
+
} else if (hoveredItemElRef.current === navItemHit) {
|
|
11039
|
+
hoveredItemElRef.current = null;
|
|
11040
|
+
setHoveredItemRect(null);
|
|
8801
11041
|
}
|
|
8802
11042
|
return;
|
|
8803
11043
|
}
|
|
8804
|
-
overFrame = container;
|
|
8805
|
-
break;
|
|
8806
11044
|
}
|
|
8807
|
-
if (
|
|
8808
|
-
|
|
8809
|
-
|
|
11045
|
+
if (allowNavContainerHover) {
|
|
11046
|
+
for (const container of navContainers) {
|
|
11047
|
+
const containerRect = container.getBoundingClientRect();
|
|
11048
|
+
const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
|
|
11049
|
+
if (!overContainer) continue;
|
|
11050
|
+
if (isPointOverNavItem(container, x, y)) continue;
|
|
11051
|
+
hoveredNavContainerRef.current = container;
|
|
11052
|
+
setHoveredNavContainerRect(container.getBoundingClientRect());
|
|
11053
|
+
hoveredItemElRef.current = null;
|
|
11054
|
+
setHoveredItemRect(null);
|
|
11055
|
+
return;
|
|
11056
|
+
}
|
|
11057
|
+
}
|
|
11058
|
+
if (allowFooterLinksHover) {
|
|
11059
|
+
const footerLinks = getFooterLinksContainer();
|
|
11060
|
+
if (footerLinks) {
|
|
11061
|
+
const containerRect = footerLinks.getBoundingClientRect();
|
|
11062
|
+
const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
|
|
11063
|
+
if (overContainer && !isPointOverNavItem(footerLinks, x, y) && !isPointOverFooterColumn(x, y)) {
|
|
11064
|
+
hoveredNavContainerRef.current = footerLinks;
|
|
11065
|
+
setHoveredNavContainerRect(footerLinks.getBoundingClientRect());
|
|
11066
|
+
hoveredItemElRef.current = null;
|
|
11067
|
+
setHoveredItemRect(null);
|
|
11068
|
+
return;
|
|
11069
|
+
}
|
|
11070
|
+
}
|
|
11071
|
+
}
|
|
11072
|
+
hoveredNavContainerRef.current = null;
|
|
11073
|
+
setHoveredNavContainerRect(null);
|
|
11074
|
+
for (const column of footerColumns) {
|
|
11075
|
+
const containerRect = column.getBoundingClientRect();
|
|
11076
|
+
const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
|
|
11077
|
+
if (!overContainer) continue;
|
|
11078
|
+
if (isPointOverNavItem(column, x, y)) continue;
|
|
11079
|
+
if (selectedElRef.current === column) {
|
|
11080
|
+
if (hoveredItemElRef.current === column) {
|
|
11081
|
+
hoveredItemElRef.current = null;
|
|
11082
|
+
setHoveredItemRect(null);
|
|
11083
|
+
}
|
|
11084
|
+
return;
|
|
11085
|
+
}
|
|
11086
|
+
hoveredItemElRef.current = column;
|
|
11087
|
+
setHoveredItemRect(column.getBoundingClientRect());
|
|
8810
11088
|
return;
|
|
8811
11089
|
}
|
|
8812
|
-
|
|
8813
|
-
|
|
8814
|
-
|
|
8815
|
-
|
|
11090
|
+
if (hoveredItemElRef.current?.hasAttribute("data-ohw-footer-col") || hoveredItemElRef.current?.hasAttribute("data-ohw-footer-column")) {
|
|
11091
|
+
hoveredItemElRef.current = null;
|
|
11092
|
+
setHoveredItemRect(null);
|
|
11093
|
+
}
|
|
8816
11094
|
};
|
|
8817
11095
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
8818
11096
|
if (linkPopoverOpenRef.current) {
|
|
@@ -8833,6 +11111,10 @@ function OhhwellsBridge() {
|
|
|
8833
11111
|
}
|
|
8834
11112
|
hoveredNavContainerRef.current = null;
|
|
8835
11113
|
setHoveredNavContainerRect(null);
|
|
11114
|
+
if (hoveredItemElRef.current?.hasAttribute("data-ohw-footer-col") || hoveredItemElRef.current?.hasAttribute("data-ohw-footer-column")) {
|
|
11115
|
+
hoveredItemElRef.current = null;
|
|
11116
|
+
setHoveredItemRect(null);
|
|
11117
|
+
}
|
|
8836
11118
|
const toggleEl = document.querySelector("[data-ohw-state-toggle]");
|
|
8837
11119
|
if (toggleEl) {
|
|
8838
11120
|
const tr = toggleEl.getBoundingClientRect();
|
|
@@ -9080,6 +11362,15 @@ function OhhwellsBridge() {
|
|
|
9080
11362
|
probeHoverCardsAt(clientX, clientY);
|
|
9081
11363
|
};
|
|
9082
11364
|
const handleDragOver = (e) => {
|
|
11365
|
+
const footerSession = footerDragRef.current;
|
|
11366
|
+
if (footerSession) {
|
|
11367
|
+
e.preventDefault();
|
|
11368
|
+
if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
|
|
11369
|
+
const slot = footerSession.kind === "link" && footerSession.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, footerSession.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
|
|
11370
|
+
refreshFooterDragVisualsRef.current(footerSession, slot, e.clientX, e.clientY);
|
|
11371
|
+
return;
|
|
11372
|
+
}
|
|
11373
|
+
if (onNavDragOver(e)) return;
|
|
9083
11374
|
e.preventDefault();
|
|
9084
11375
|
const el = findImageAtPoint(e.clientX, e.clientY, false);
|
|
9085
11376
|
if (!el) {
|
|
@@ -9286,6 +11577,7 @@ function OhhwellsBridge() {
|
|
|
9286
11577
|
}
|
|
9287
11578
|
editContentRef.current = { ...editContentRef.current, ...content };
|
|
9288
11579
|
reconcileNavbarItemsFromContent(editContentRef.current);
|
|
11580
|
+
reconcileFooterOrderFromContent(editContentRef.current);
|
|
9289
11581
|
syncNavigationDragCursorAttrs();
|
|
9290
11582
|
enforceLinkHrefs();
|
|
9291
11583
|
postToParentRef.current({ type: "ow:hydrate-done" });
|
|
@@ -9340,6 +11632,11 @@ function OhhwellsBridge() {
|
|
|
9340
11632
|
}
|
|
9341
11633
|
if (selectedElRef.current) {
|
|
9342
11634
|
if (toolbarVariantRef.current === "select-frame") {
|
|
11635
|
+
const parent2 = getNavigationSelectionParent(selectedElRef.current);
|
|
11636
|
+
if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
|
|
11637
|
+
selectFrameRef.current(parent2);
|
|
11638
|
+
return;
|
|
11639
|
+
}
|
|
9343
11640
|
deselectRef.current();
|
|
9344
11641
|
return;
|
|
9345
11642
|
}
|
|
@@ -9355,13 +11652,10 @@ function OhhwellsBridge() {
|
|
|
9355
11652
|
const handleKeyDown = (e) => {
|
|
9356
11653
|
if (e.key === "Escape" && document.querySelector("[data-ohw-section-picker]")) return;
|
|
9357
11654
|
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "a" && activeElRef.current) {
|
|
9358
|
-
|
|
9359
|
-
|
|
9360
|
-
|
|
9361
|
-
|
|
9362
|
-
refreshActiveCommandsRef.current();
|
|
9363
|
-
return;
|
|
9364
|
-
}
|
|
11655
|
+
e.preventDefault();
|
|
11656
|
+
selectAllTextInEditable(activeElRef.current);
|
|
11657
|
+
refreshActiveCommandsRef.current();
|
|
11658
|
+
return;
|
|
9365
11659
|
}
|
|
9366
11660
|
if (e.key === "Escape" && linkPopoverOpenRef.current) {
|
|
9367
11661
|
setLinkPopoverRef.current(null);
|
|
@@ -9369,6 +11663,12 @@ function OhhwellsBridge() {
|
|
|
9369
11663
|
}
|
|
9370
11664
|
if (e.key === "Escape" && selectedElRef.current && !activeElRef.current) {
|
|
9371
11665
|
if (toolbarVariantRef.current === "select-frame") {
|
|
11666
|
+
const parent2 = getNavigationSelectionParent(selectedElRef.current);
|
|
11667
|
+
if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
|
|
11668
|
+
e.preventDefault();
|
|
11669
|
+
selectFrameRef.current(parent2);
|
|
11670
|
+
return;
|
|
11671
|
+
}
|
|
9372
11672
|
deselectRef.current();
|
|
9373
11673
|
return;
|
|
9374
11674
|
}
|
|
@@ -9443,6 +11743,26 @@ function OhhwellsBridge() {
|
|
|
9443
11743
|
if (siblingHintElRef.current) {
|
|
9444
11744
|
setSiblingHintRect(siblingHintElRef.current.getBoundingClientRect());
|
|
9445
11745
|
}
|
|
11746
|
+
const selected = selectedElRef.current;
|
|
11747
|
+
if (selected && !footerDragRef.current && !navDragRef.current) {
|
|
11748
|
+
if (selected.hasAttribute("data-ohw-footer-col") || Boolean(selected.closest("footer") && isInferredFooterGroup(selected))) {
|
|
11749
|
+
setSiblingHintRects(
|
|
11750
|
+
listFooterColumns().filter((column) => column !== selected).map((column) => column.getBoundingClientRect())
|
|
11751
|
+
);
|
|
11752
|
+
} else if (isNavigationItem(selected)) {
|
|
11753
|
+
setSiblingHintRects(collectNavigationItemSiblingHintRects(selected));
|
|
11754
|
+
}
|
|
11755
|
+
}
|
|
11756
|
+
if (footerDragRef.current) {
|
|
11757
|
+
const session = footerDragRef.current;
|
|
11758
|
+
const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
|
|
11759
|
+
refreshFooterDragVisualsRef.current(session, slot, session.lastClientX, session.lastClientY);
|
|
11760
|
+
}
|
|
11761
|
+
if (navDragRef.current) {
|
|
11762
|
+
const session = navDragRef.current;
|
|
11763
|
+
const slot = hitTestNavDropSlot(session.lastClientX, session.lastClientY, session.hrefKey);
|
|
11764
|
+
refreshNavDragVisualsRef.current(session, slot, session.lastClientX, session.lastClientY);
|
|
11765
|
+
}
|
|
9446
11766
|
if (hoveredImageRef.current) {
|
|
9447
11767
|
const el = hoveredImageRef.current;
|
|
9448
11768
|
const r2 = el.getBoundingClientRect();
|
|
@@ -9453,7 +11773,7 @@ function OhhwellsBridge() {
|
|
|
9453
11773
|
};
|
|
9454
11774
|
const handleSave = (e) => {
|
|
9455
11775
|
if (e.data?.type !== "ow:save") return;
|
|
9456
|
-
const nodes = collectEditableNodes();
|
|
11776
|
+
const nodes = collectEditableNodes(editContentRef.current);
|
|
9457
11777
|
const tracker = document.querySelector("[data-ohw-sections-tracker]");
|
|
9458
11778
|
if (tracker?.textContent) nodes.push({ key: "__ohw_sections", type: "sections", text: tracker.textContent });
|
|
9459
11779
|
postToParentRef.current({ type: "ow:save-result", nodes });
|
|
@@ -9511,30 +11831,30 @@ function OhhwellsBridge() {
|
|
|
9511
11831
|
const h = document.documentElement.scrollHeight;
|
|
9512
11832
|
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
9513
11833
|
};
|
|
11834
|
+
let selectionChangeRaf = null;
|
|
11835
|
+
const runSelectionChange = () => {
|
|
11836
|
+
selectionChangeRaf = null;
|
|
11837
|
+
const activeRoot = activeElRef.current;
|
|
11838
|
+
if (!activeRoot) return;
|
|
11839
|
+
const startEl = resolveSelectionStartElement(window.getSelection());
|
|
11840
|
+
const next = startEl ? detectActiveFormats(startEl, activeRoot) : /* @__PURE__ */ new Set();
|
|
11841
|
+
setActiveCommands((prev) => setsEqual(prev, next) ? prev : next);
|
|
11842
|
+
};
|
|
9514
11843
|
const handleSelectionChange = () => {
|
|
9515
|
-
if (
|
|
9516
|
-
|
|
9517
|
-
|
|
9518
|
-
|
|
9519
|
-
|
|
9520
|
-
|
|
9521
|
-
|
|
9522
|
-
|
|
9523
|
-
|
|
9524
|
-
|
|
9525
|
-
|
|
9526
|
-
|
|
9527
|
-
const block = el?.closest("div, p, h1, h2, h3, h4, h5, h6, li, td, th") ?? el;
|
|
9528
|
-
if (block) {
|
|
9529
|
-
const align = getComputedStyle(block).textAlign;
|
|
9530
|
-
if (align === "center") next.add("justifyCenter");
|
|
9531
|
-
else if (align === "right" || align === "end") next.add("justifyRight");
|
|
9532
|
-
else next.add("justifyLeft");
|
|
9533
|
-
}
|
|
9534
|
-
}
|
|
9535
|
-
setActiveCommands(next);
|
|
11844
|
+
if (pointerHeldRef.current) return;
|
|
11845
|
+
if (selectionChangeRaf !== null) return;
|
|
11846
|
+
selectionChangeRaf = requestAnimationFrame(runSelectionChange);
|
|
11847
|
+
};
|
|
11848
|
+
const markPointerHeld = (e) => {
|
|
11849
|
+
if (e.button !== 0) return;
|
|
11850
|
+
pointerHeldRef.current = true;
|
|
11851
|
+
};
|
|
11852
|
+
const markPointerReleased = () => {
|
|
11853
|
+
if (!pointerHeldRef.current) return;
|
|
11854
|
+
pointerHeldRef.current = false;
|
|
11855
|
+
handleSelectionChange();
|
|
9536
11856
|
};
|
|
9537
|
-
refreshActiveCommandsRef.current =
|
|
11857
|
+
refreshActiveCommandsRef.current = runSelectionChange;
|
|
9538
11858
|
const handleDocMouseLeave = () => {
|
|
9539
11859
|
hoveredImageRef.current = null;
|
|
9540
11860
|
setMediaHover(null);
|
|
@@ -9676,7 +11996,7 @@ function OhhwellsBridge() {
|
|
|
9676
11996
|
}
|
|
9677
11997
|
}
|
|
9678
11998
|
const footerColumn = findHoveredNavOrFooterContainer(clientX, clientY);
|
|
9679
|
-
if (footerColumn?.hasAttribute("data-ohw-footer-column")) {
|
|
11999
|
+
if (footerColumn?.hasAttribute("data-ohw-footer-col") || footerColumn?.hasAttribute("data-ohw-footer-column")) {
|
|
9680
12000
|
selectFrameRef.current(footerColumn);
|
|
9681
12001
|
return;
|
|
9682
12002
|
}
|
|
@@ -9751,7 +12071,161 @@ function OhhwellsBridge() {
|
|
|
9751
12071
|
if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
|
|
9752
12072
|
};
|
|
9753
12073
|
}, [isEditMode, refreshStateRules]);
|
|
9754
|
-
(0,
|
|
12074
|
+
(0, import_react9.useEffect)(() => {
|
|
12075
|
+
if (!isEditMode) return;
|
|
12076
|
+
const THRESHOLD = 10;
|
|
12077
|
+
const resolveWasSelected = (el) => {
|
|
12078
|
+
if (selectedElRef.current === el) return true;
|
|
12079
|
+
const activeAnchor = activeElRef.current ? getNavigationItemAnchor(activeElRef.current) : null;
|
|
12080
|
+
return activeAnchor === el;
|
|
12081
|
+
};
|
|
12082
|
+
const onPointerDown = (e) => {
|
|
12083
|
+
if (e.button !== 0) return;
|
|
12084
|
+
if (suppressNextClickRef.current && Date.now() >= suppressClickUntilRef.current && !footerDragRef.current && !footerPointerDragRef.current?.started) {
|
|
12085
|
+
suppressNextClickRef.current = false;
|
|
12086
|
+
}
|
|
12087
|
+
if (footerDragRef.current) return;
|
|
12088
|
+
const target = e.target;
|
|
12089
|
+
if (!target) return;
|
|
12090
|
+
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]')) {
|
|
12091
|
+
return;
|
|
12092
|
+
}
|
|
12093
|
+
if (target.closest("[data-ohw-item-drag-surface]")) return;
|
|
12094
|
+
const anchor = getNavigationItemAnchor(target);
|
|
12095
|
+
const hrefKey = anchor?.getAttribute("data-ohw-href-key") ?? null;
|
|
12096
|
+
if (anchor && isFooterHrefKey(hrefKey)) {
|
|
12097
|
+
footerPointerDragRef.current = {
|
|
12098
|
+
el: anchor,
|
|
12099
|
+
kind: "link",
|
|
12100
|
+
startX: e.clientX,
|
|
12101
|
+
startY: e.clientY,
|
|
12102
|
+
pointerId: e.pointerId,
|
|
12103
|
+
wasSelected: resolveWasSelected(anchor),
|
|
12104
|
+
started: false
|
|
12105
|
+
};
|
|
12106
|
+
return;
|
|
12107
|
+
}
|
|
12108
|
+
const col = target.closest("[data-ohw-footer-col]");
|
|
12109
|
+
if (col && !getNavigationItemAnchor(target)) {
|
|
12110
|
+
footerPointerDragRef.current = {
|
|
12111
|
+
el: col,
|
|
12112
|
+
kind: "column",
|
|
12113
|
+
startX: e.clientX,
|
|
12114
|
+
startY: e.clientY,
|
|
12115
|
+
pointerId: e.pointerId,
|
|
12116
|
+
wasSelected: resolveWasSelected(col),
|
|
12117
|
+
started: false
|
|
12118
|
+
};
|
|
12119
|
+
}
|
|
12120
|
+
};
|
|
12121
|
+
const onPointerMove = (e) => {
|
|
12122
|
+
const pending = footerPointerDragRef.current;
|
|
12123
|
+
if (!pending) return;
|
|
12124
|
+
if (pending.started) {
|
|
12125
|
+
e.preventDefault();
|
|
12126
|
+
clearTextSelection();
|
|
12127
|
+
const session = footerDragRef.current;
|
|
12128
|
+
if (!session) return;
|
|
12129
|
+
const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, session.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
|
|
12130
|
+
refreshFooterDragVisualsRef.current(session, slot, e.clientX, e.clientY);
|
|
12131
|
+
return;
|
|
12132
|
+
}
|
|
12133
|
+
const dx = e.clientX - pending.startX;
|
|
12134
|
+
const dy = e.clientY - pending.startY;
|
|
12135
|
+
if (dx * dx + dy * dy < THRESHOLD * THRESHOLD) return;
|
|
12136
|
+
e.preventDefault();
|
|
12137
|
+
pending.started = true;
|
|
12138
|
+
armFooterPressDrag();
|
|
12139
|
+
clearTextSelection();
|
|
12140
|
+
try {
|
|
12141
|
+
document.body.setPointerCapture(pending.pointerId);
|
|
12142
|
+
} catch {
|
|
12143
|
+
}
|
|
12144
|
+
if (linkPopoverOpenRef.current) {
|
|
12145
|
+
setLinkPopoverRef.current(null);
|
|
12146
|
+
}
|
|
12147
|
+
if (activeElRef.current) {
|
|
12148
|
+
deactivateRef.current();
|
|
12149
|
+
}
|
|
12150
|
+
if (pending.kind === "link") {
|
|
12151
|
+
const key = pending.el.getAttribute("data-ohw-href-key");
|
|
12152
|
+
if (!key) return;
|
|
12153
|
+
const column = findFooterColumnForLink(pending.el);
|
|
12154
|
+
const columns2 = listFooterColumns();
|
|
12155
|
+
beginFooterDragRef.current({
|
|
12156
|
+
kind: "link",
|
|
12157
|
+
hrefKey: key,
|
|
12158
|
+
columnEl: column,
|
|
12159
|
+
sourceColumnIndex: column ? columns2.indexOf(column) : 0,
|
|
12160
|
+
wasSelected: pending.wasSelected,
|
|
12161
|
+
draggedEl: pending.el,
|
|
12162
|
+
lastClientX: e.clientX,
|
|
12163
|
+
lastClientY: e.clientY,
|
|
12164
|
+
activeSlot: null
|
|
12165
|
+
});
|
|
12166
|
+
return;
|
|
12167
|
+
}
|
|
12168
|
+
const columns = listFooterColumns();
|
|
12169
|
+
const idx = columns.indexOf(pending.el);
|
|
12170
|
+
if (idx < 0) return;
|
|
12171
|
+
beginFooterDragRef.current({
|
|
12172
|
+
kind: "column",
|
|
12173
|
+
hrefKey: null,
|
|
12174
|
+
columnEl: pending.el,
|
|
12175
|
+
sourceColumnIndex: idx,
|
|
12176
|
+
wasSelected: pending.wasSelected,
|
|
12177
|
+
draggedEl: pending.el,
|
|
12178
|
+
lastClientX: e.clientX,
|
|
12179
|
+
lastClientY: e.clientY,
|
|
12180
|
+
activeSlot: null
|
|
12181
|
+
});
|
|
12182
|
+
};
|
|
12183
|
+
const endPointerDrag = (e) => {
|
|
12184
|
+
const pending = footerPointerDragRef.current;
|
|
12185
|
+
footerPointerDragRef.current = null;
|
|
12186
|
+
try {
|
|
12187
|
+
if (document.body.hasPointerCapture(e.pointerId)) {
|
|
12188
|
+
document.body.releasePointerCapture(e.pointerId);
|
|
12189
|
+
}
|
|
12190
|
+
} catch {
|
|
12191
|
+
}
|
|
12192
|
+
if (!pending) return;
|
|
12193
|
+
if (!pending.started) {
|
|
12194
|
+
unlockFooterDragInteraction();
|
|
12195
|
+
return;
|
|
12196
|
+
}
|
|
12197
|
+
suppressNextClickRef.current = true;
|
|
12198
|
+
suppressClickUntilRef.current = Date.now() + 500;
|
|
12199
|
+
commitFooterDragRef.current(e.clientX, e.clientY);
|
|
12200
|
+
};
|
|
12201
|
+
const blockSelectStart = (e) => {
|
|
12202
|
+
if (footerDragRef.current || footerPointerDragRef.current?.started || document.documentElement.hasAttribute("data-ohw-footer-press-drag")) {
|
|
12203
|
+
e.preventDefault();
|
|
12204
|
+
}
|
|
12205
|
+
};
|
|
12206
|
+
const onDragEnd = (_e) => {
|
|
12207
|
+
if (!footerDragRef.current) return;
|
|
12208
|
+
suppressNextClickRef.current = true;
|
|
12209
|
+
suppressClickUntilRef.current = Date.now() + 500;
|
|
12210
|
+
commitFooterDragRef.current();
|
|
12211
|
+
};
|
|
12212
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
12213
|
+
document.addEventListener("pointermove", onPointerMove, true);
|
|
12214
|
+
document.addEventListener("pointerup", endPointerDrag, true);
|
|
12215
|
+
document.addEventListener("pointercancel", endPointerDrag, true);
|
|
12216
|
+
document.addEventListener("selectstart", blockSelectStart, true);
|
|
12217
|
+
document.addEventListener("dragend", onDragEnd, true);
|
|
12218
|
+
return () => {
|
|
12219
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
12220
|
+
document.removeEventListener("pointermove", onPointerMove, true);
|
|
12221
|
+
document.removeEventListener("pointerup", endPointerDrag, true);
|
|
12222
|
+
document.removeEventListener("pointercancel", endPointerDrag, true);
|
|
12223
|
+
document.removeEventListener("selectstart", blockSelectStart, true);
|
|
12224
|
+
document.removeEventListener("dragend", onDragEnd, true);
|
|
12225
|
+
unlockFooterDragInteraction();
|
|
12226
|
+
};
|
|
12227
|
+
}, [isEditMode]);
|
|
12228
|
+
(0, import_react9.useEffect)(() => {
|
|
9755
12229
|
const handler = (e) => {
|
|
9756
12230
|
if (e.data?.type !== "ow:request-schedule-config") return;
|
|
9757
12231
|
const insertAfterVal = e.data.insertAfter;
|
|
@@ -9767,7 +12241,7 @@ function OhhwellsBridge() {
|
|
|
9767
12241
|
window.addEventListener("message", handler);
|
|
9768
12242
|
return () => window.removeEventListener("message", handler);
|
|
9769
12243
|
}, [processConfigRequest]);
|
|
9770
|
-
(0,
|
|
12244
|
+
(0, import_react9.useEffect)(() => {
|
|
9771
12245
|
if (!isEditMode) return;
|
|
9772
12246
|
document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
|
|
9773
12247
|
el.removeAttribute("data-ohw-active-state");
|
|
@@ -9788,7 +12262,13 @@ function OhhwellsBridge() {
|
|
|
9788
12262
|
const next = { ...prev, [pathKey]: sections };
|
|
9789
12263
|
return shouldUseDevFixtures() ? { ...DEV_SECTIONS_BY_PATH, ...next } : next;
|
|
9790
12264
|
});
|
|
9791
|
-
postToParent2({
|
|
12265
|
+
postToParent2({
|
|
12266
|
+
type: "ow:ready",
|
|
12267
|
+
version: "1",
|
|
12268
|
+
path: pathname,
|
|
12269
|
+
nodes: collectEditableNodes(editContentRef.current),
|
|
12270
|
+
sections
|
|
12271
|
+
});
|
|
9792
12272
|
postToParent2({ type: "ow:request-site-pages" });
|
|
9793
12273
|
}, 150);
|
|
9794
12274
|
return () => {
|
|
@@ -9796,19 +12276,49 @@ function OhhwellsBridge() {
|
|
|
9796
12276
|
clearTimeout(timer);
|
|
9797
12277
|
};
|
|
9798
12278
|
}, [pathname, isEditMode, refreshStateRules, postToParent2]);
|
|
9799
|
-
(0,
|
|
12279
|
+
(0, import_react9.useEffect)(() => {
|
|
9800
12280
|
scrollToHashSectionWhenReady();
|
|
9801
12281
|
const onHashChange = () => scrollToHashSectionWhenReady();
|
|
9802
12282
|
window.addEventListener("hashchange", onHashChange);
|
|
9803
12283
|
return () => window.removeEventListener("hashchange", onHashChange);
|
|
9804
12284
|
}, [pathname]);
|
|
9805
|
-
const handleCommand = (0,
|
|
12285
|
+
const handleCommand = (0, import_react9.useCallback)((cmd) => {
|
|
12286
|
+
const el = activeElRef.current;
|
|
12287
|
+
const selBefore = window.getSelection();
|
|
12288
|
+
let savedOffsets = null;
|
|
12289
|
+
if (el && selBefore && selBefore.rangeCount > 0 && !selBefore.isCollapsed) {
|
|
12290
|
+
const r2 = selBefore.getRangeAt(0);
|
|
12291
|
+
if (el.contains(r2.commonAncestorContainer)) {
|
|
12292
|
+
savedOffsets = {
|
|
12293
|
+
start: textOffsetInRoot(el, r2.startContainer, r2.startOffset),
|
|
12294
|
+
end: textOffsetInRoot(el, r2.endContainer, r2.endOffset)
|
|
12295
|
+
};
|
|
12296
|
+
}
|
|
12297
|
+
}
|
|
12298
|
+
document.execCommand("styleWithCSS", false, true);
|
|
9806
12299
|
document.execCommand(cmd, false);
|
|
9807
|
-
|
|
9808
|
-
|
|
12300
|
+
if (el && document.activeElement !== el) {
|
|
12301
|
+
el.focus();
|
|
12302
|
+
}
|
|
12303
|
+
const selAfter = window.getSelection();
|
|
12304
|
+
if (el && savedOffsets && selAfter?.isCollapsed) {
|
|
12305
|
+
const start = pointAtTextOffset(el, savedOffsets.start);
|
|
12306
|
+
const end = pointAtTextOffset(el, savedOffsets.end);
|
|
12307
|
+
if (start && end) {
|
|
12308
|
+
try {
|
|
12309
|
+
const range = document.createRange();
|
|
12310
|
+
range.setStart(start.node, start.offset);
|
|
12311
|
+
range.setEnd(end.node, end.offset);
|
|
12312
|
+
selAfter.removeAllRanges();
|
|
12313
|
+
selAfter.addRange(range);
|
|
12314
|
+
} catch {
|
|
12315
|
+
}
|
|
12316
|
+
}
|
|
12317
|
+
}
|
|
12318
|
+
if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
|
|
9809
12319
|
refreshActiveCommandsRef.current();
|
|
9810
12320
|
}, []);
|
|
9811
|
-
const handleStateChange = (0,
|
|
12321
|
+
const handleStateChange = (0, import_react9.useCallback)((state) => {
|
|
9812
12322
|
if (!activeStateElRef.current) return;
|
|
9813
12323
|
const el = activeStateElRef.current;
|
|
9814
12324
|
if (state === "Default") {
|
|
@@ -9821,11 +12331,11 @@ function OhhwellsBridge() {
|
|
|
9821
12331
|
}
|
|
9822
12332
|
setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
|
|
9823
12333
|
}, [deactivate]);
|
|
9824
|
-
const closeLinkPopover = (0,
|
|
12334
|
+
const closeLinkPopover = (0, import_react9.useCallback)(() => {
|
|
9825
12335
|
addNavAfterAnchorRef.current = null;
|
|
9826
12336
|
setLinkPopover(null);
|
|
9827
12337
|
}, []);
|
|
9828
|
-
const openLinkPopoverForActive = (0,
|
|
12338
|
+
const openLinkPopoverForActive = (0, import_react9.useCallback)(() => {
|
|
9829
12339
|
const hrefCtx = getHrefKeyFromElement(activeElRef.current);
|
|
9830
12340
|
if (!hrefCtx) return;
|
|
9831
12341
|
bumpLinkPopoverGrace();
|
|
@@ -9836,7 +12346,7 @@ function OhhwellsBridge() {
|
|
|
9836
12346
|
});
|
|
9837
12347
|
deactivate();
|
|
9838
12348
|
}, [deactivate]);
|
|
9839
|
-
const openLinkPopoverForSelected = (0,
|
|
12349
|
+
const openLinkPopoverForSelected = (0, import_react9.useCallback)(() => {
|
|
9840
12350
|
const anchor = selectedElRef.current;
|
|
9841
12351
|
if (!anchor) return;
|
|
9842
12352
|
const key = anchor.getAttribute("data-ohw-href-key");
|
|
@@ -9849,7 +12359,7 @@ function OhhwellsBridge() {
|
|
|
9849
12359
|
});
|
|
9850
12360
|
deselect();
|
|
9851
12361
|
}, [deselect]);
|
|
9852
|
-
const handleLinkPopoverSubmit = (0,
|
|
12362
|
+
const handleLinkPopoverSubmit = (0, import_react9.useCallback)(
|
|
9853
12363
|
(target) => {
|
|
9854
12364
|
const session = linkPopoverSessionRef.current;
|
|
9855
12365
|
if (!session) return;
|
|
@@ -9908,13 +12418,13 @@ function OhhwellsBridge() {
|
|
|
9908
12418
|
const showEditLink = toolbarShowEditLink;
|
|
9909
12419
|
const currentSections = sectionsByPath[pathname] ?? [];
|
|
9910
12420
|
linkPopoverOpenRef.current = linkPopover !== null;
|
|
9911
|
-
const handleMediaReplace = (0,
|
|
12421
|
+
const handleMediaReplace = (0, import_react9.useCallback)(
|
|
9912
12422
|
(key) => {
|
|
9913
12423
|
postToParent2({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
|
|
9914
12424
|
},
|
|
9915
12425
|
[postToParent2, mediaHover?.elementType]
|
|
9916
12426
|
);
|
|
9917
|
-
const handleMediaFadeOutComplete = (0,
|
|
12427
|
+
const handleMediaFadeOutComplete = (0, import_react9.useCallback)((key) => {
|
|
9918
12428
|
setUploadingRects((prev) => {
|
|
9919
12429
|
if (!(key in prev)) return prev;
|
|
9920
12430
|
const next = { ...prev };
|
|
@@ -9922,7 +12432,7 @@ function OhhwellsBridge() {
|
|
|
9922
12432
|
return next;
|
|
9923
12433
|
});
|
|
9924
12434
|
}, []);
|
|
9925
|
-
const handleVideoSettingsChange = (0,
|
|
12435
|
+
const handleVideoSettingsChange = (0, import_react9.useCallback)(
|
|
9926
12436
|
(key, settings) => {
|
|
9927
12437
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
9928
12438
|
const video = getVideoEl(el);
|
|
@@ -9945,9 +12455,9 @@ function OhhwellsBridge() {
|
|
|
9945
12455
|
[postToParent2]
|
|
9946
12456
|
);
|
|
9947
12457
|
return bridgeRoot ? (0, import_react_dom3.createPortal)(
|
|
9948
|
-
/* @__PURE__ */ (0,
|
|
9949
|
-
/* @__PURE__ */ (0,
|
|
9950
|
-
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0,
|
|
12458
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
12459
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
|
|
12460
|
+
Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
9951
12461
|
MediaOverlay,
|
|
9952
12462
|
{
|
|
9953
12463
|
hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
|
|
@@ -9958,7 +12468,7 @@ function OhhwellsBridge() {
|
|
|
9958
12468
|
},
|
|
9959
12469
|
`uploading-${key}`
|
|
9960
12470
|
)),
|
|
9961
|
-
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0,
|
|
12471
|
+
mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
9962
12472
|
MediaOverlay,
|
|
9963
12473
|
{
|
|
9964
12474
|
hover: mediaHover,
|
|
@@ -9967,28 +12477,70 @@ function OhhwellsBridge() {
|
|
|
9967
12477
|
onVideoSettingsChange: handleVideoSettingsChange
|
|
9968
12478
|
}
|
|
9969
12479
|
),
|
|
9970
|
-
siblingHintRect && !isItemDragging && /* @__PURE__ */ (0,
|
|
9971
|
-
|
|
9972
|
-
|
|
9973
|
-
|
|
12480
|
+
siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
|
|
12481
|
+
siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
|
|
12482
|
+
isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
|
|
12483
|
+
isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
12484
|
+
"div",
|
|
9974
12485
|
{
|
|
9975
|
-
|
|
9976
|
-
|
|
9977
|
-
|
|
9978
|
-
|
|
9979
|
-
|
|
9980
|
-
|
|
12486
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
12487
|
+
style: {
|
|
12488
|
+
left: slot.left,
|
|
12489
|
+
top: slot.top,
|
|
12490
|
+
width: slot.width,
|
|
12491
|
+
height: slot.height
|
|
12492
|
+
},
|
|
12493
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
12494
|
+
DropIndicator,
|
|
12495
|
+
{
|
|
12496
|
+
direction: slot.direction,
|
|
12497
|
+
state: activeFooterDropIndex === i ? "dragActive" : "dragIdle",
|
|
12498
|
+
className: "!h-full !w-full"
|
|
12499
|
+
}
|
|
12500
|
+
)
|
|
12501
|
+
},
|
|
12502
|
+
`footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
|
|
12503
|
+
)),
|
|
12504
|
+
isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
12505
|
+
"div",
|
|
12506
|
+
{
|
|
12507
|
+
className: "pointer-events-none fixed z-2147483646",
|
|
12508
|
+
style: {
|
|
12509
|
+
left: slot.left,
|
|
12510
|
+
top: slot.top,
|
|
12511
|
+
width: slot.width,
|
|
12512
|
+
height: slot.height
|
|
12513
|
+
},
|
|
12514
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
12515
|
+
DropIndicator,
|
|
12516
|
+
{
|
|
12517
|
+
direction: slot.direction,
|
|
12518
|
+
state: activeNavDropIndex === i ? "dragActive" : "dragIdle",
|
|
12519
|
+
className: "!h-full !w-full"
|
|
12520
|
+
}
|
|
12521
|
+
)
|
|
12522
|
+
},
|
|
12523
|
+
`nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
|
|
12524
|
+
)),
|
|
12525
|
+
hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
|
|
12526
|
+
hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
|
|
12527
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
|
|
12528
|
+
toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(FooterContainerChrome, { rect: toolbarRect, onAdd: handleAddFooterColumn }),
|
|
12529
|
+
toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
9981
12530
|
ItemInteractionLayer,
|
|
9982
12531
|
{
|
|
9983
|
-
rect: toolbarRect,
|
|
12532
|
+
rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
|
|
9984
12533
|
elRef: glowElRef,
|
|
9985
12534
|
state: isItemDragging ? "dragging" : resolveItemInteractionState(toolbarRect, parentScrollRef.current),
|
|
9986
|
-
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey),
|
|
12535
|
+
showHandle: toolbarVariant === "link-action" && Boolean(reorderHrefKey) || toolbarVariant === "select-frame" && isFooterFrameSelection,
|
|
9987
12536
|
dragDisabled: reorderDragDisabled,
|
|
9988
12537
|
dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
|
|
9989
12538
|
onDragHandleDragStart: handleItemDragStart,
|
|
9990
12539
|
onDragHandleDragEnd: handleItemDragEnd,
|
|
9991
|
-
|
|
12540
|
+
onItemPointerDown: handleItemChromePointerDown,
|
|
12541
|
+
onItemClick: handleItemChromeClick,
|
|
12542
|
+
itemDragSurface: !isFooterFrameSelection,
|
|
12543
|
+
toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
9992
12544
|
ItemActionToolbar,
|
|
9993
12545
|
{
|
|
9994
12546
|
onEditLink: openLinkPopoverForSelected,
|
|
@@ -10001,17 +12553,18 @@ function OhhwellsBridge() {
|
|
|
10001
12553
|
) : void 0
|
|
10002
12554
|
}
|
|
10003
12555
|
),
|
|
10004
|
-
toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ (0,
|
|
10005
|
-
/* @__PURE__ */ (0,
|
|
12556
|
+
toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
12557
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
10006
12558
|
EditGlowChrome,
|
|
10007
12559
|
{
|
|
10008
12560
|
rect: toolbarRect,
|
|
10009
12561
|
elRef: glowElRef,
|
|
10010
12562
|
reorderHrefKey,
|
|
10011
|
-
dragDisabled: reorderDragDisabled
|
|
12563
|
+
dragDisabled: reorderDragDisabled,
|
|
12564
|
+
hideHandle: isItemDragging
|
|
10012
12565
|
}
|
|
10013
12566
|
),
|
|
10014
|
-
/* @__PURE__ */ (0,
|
|
12567
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
10015
12568
|
FloatingToolbar,
|
|
10016
12569
|
{
|
|
10017
12570
|
rect: toolbarRect,
|
|
@@ -10024,7 +12577,7 @@ function OhhwellsBridge() {
|
|
|
10024
12577
|
}
|
|
10025
12578
|
)
|
|
10026
12579
|
] }),
|
|
10027
|
-
maxBadge && /* @__PURE__ */ (0,
|
|
12580
|
+
maxBadge && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
10028
12581
|
"div",
|
|
10029
12582
|
{
|
|
10030
12583
|
"data-ohw-max-badge": "",
|
|
@@ -10050,7 +12603,7 @@ function OhhwellsBridge() {
|
|
|
10050
12603
|
]
|
|
10051
12604
|
}
|
|
10052
12605
|
),
|
|
10053
|
-
toggleState && !linkPopover && /* @__PURE__ */ (0,
|
|
12606
|
+
toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
10054
12607
|
StateToggle,
|
|
10055
12608
|
{
|
|
10056
12609
|
rect: toggleState.rect,
|
|
@@ -10059,32 +12612,36 @@ function OhhwellsBridge() {
|
|
|
10059
12612
|
onStateChange: handleStateChange
|
|
10060
12613
|
}
|
|
10061
12614
|
),
|
|
10062
|
-
sectionGap && !linkPopover && /* @__PURE__ */ (0,
|
|
12615
|
+
sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
10063
12616
|
"div",
|
|
10064
12617
|
{
|
|
10065
12618
|
"data-ohw-section-insert-line": "",
|
|
10066
12619
|
className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
|
|
10067
12620
|
style: { top: sectionGap.y, transform: "translateY(-50%)" },
|
|
10068
12621
|
children: [
|
|
10069
|
-
/* @__PURE__ */ (0,
|
|
10070
|
-
/* @__PURE__ */ (0,
|
|
12622
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
|
|
12623
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
10071
12624
|
Badge,
|
|
10072
12625
|
{
|
|
10073
12626
|
className: "px-8 py-1 bg-primary hover:bg-primary text-primary-foreground text-xs font-medium shrink-0 rounded-full cursor-pointer pointer-events-auto",
|
|
10074
12627
|
onClick: () => {
|
|
10075
12628
|
window.parent.postMessage(
|
|
10076
|
-
{
|
|
12629
|
+
{
|
|
12630
|
+
type: "ow:add-section",
|
|
12631
|
+
insertAfter: sectionGap.insertAfter,
|
|
12632
|
+
insertBefore: sectionGap.insertBefore
|
|
12633
|
+
},
|
|
10077
12634
|
"*"
|
|
10078
12635
|
);
|
|
10079
12636
|
},
|
|
10080
12637
|
children: "Add Section"
|
|
10081
12638
|
}
|
|
10082
12639
|
),
|
|
10083
|
-
/* @__PURE__ */ (0,
|
|
12640
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
|
|
10084
12641
|
]
|
|
10085
12642
|
}
|
|
10086
12643
|
),
|
|
10087
|
-
linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0,
|
|
12644
|
+
linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
10088
12645
|
LinkPopover,
|
|
10089
12646
|
{
|
|
10090
12647
|
panelRef: linkPopoverPanelRef,
|
|
@@ -10105,48 +12662,6 @@ function OhhwellsBridge() {
|
|
|
10105
12662
|
bridgeRoot
|
|
10106
12663
|
) : null;
|
|
10107
12664
|
}
|
|
10108
|
-
|
|
10109
|
-
// src/ui/drop-indicator.tsx
|
|
10110
|
-
var React11 = __toESM(require("react"), 1);
|
|
10111
|
-
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
10112
|
-
var dropIndicatorVariants = cva(
|
|
10113
|
-
"ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
|
|
10114
|
-
{
|
|
10115
|
-
variants: {
|
|
10116
|
-
direction: {
|
|
10117
|
-
vertical: "h-6 w-[3px]",
|
|
10118
|
-
horizontal: "h-[3px] w-[200px]"
|
|
10119
|
-
},
|
|
10120
|
-
state: {
|
|
10121
|
-
default: "opacity-0",
|
|
10122
|
-
hover: "opacity-100",
|
|
10123
|
-
dragIdle: "opacity-40",
|
|
10124
|
-
dragActive: "opacity-100"
|
|
10125
|
-
}
|
|
10126
|
-
},
|
|
10127
|
-
defaultVariants: {
|
|
10128
|
-
direction: "vertical",
|
|
10129
|
-
state: "default"
|
|
10130
|
-
}
|
|
10131
|
-
}
|
|
10132
|
-
);
|
|
10133
|
-
var DropIndicator = React11.forwardRef(
|
|
10134
|
-
({ className, direction, state, ...props }, ref) => {
|
|
10135
|
-
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
10136
|
-
"div",
|
|
10137
|
-
{
|
|
10138
|
-
ref,
|
|
10139
|
-
"data-slot": "drop-indicator",
|
|
10140
|
-
"data-direction": direction ?? "vertical",
|
|
10141
|
-
"data-state": state ?? "default",
|
|
10142
|
-
"aria-hidden": "true",
|
|
10143
|
-
className: cn(dropIndicatorVariants({ direction, state }), className),
|
|
10144
|
-
...props
|
|
10145
|
-
}
|
|
10146
|
-
);
|
|
10147
|
-
}
|
|
10148
|
-
);
|
|
10149
|
-
DropIndicator.displayName = "DropIndicator";
|
|
10150
12665
|
// Annotate the CommonJS export names for ESM import in node:
|
|
10151
12666
|
0 && (module.exports = {
|
|
10152
12667
|
CustomToolbar,
|