@ohhwells/bridge 0.1.46-next.109 → 0.1.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  // src/OhhwellsBridge.tsx
4
- import React11, { useCallback as useCallback5, useEffect as useEffect8, useLayoutEffect as useLayoutEffect3, useRef as useRef7, useState as useState7 } from "react";
4
+ import React11, { useCallback as useCallback4, useEffect as useEffect8, useLayoutEffect as useLayoutEffect3, useRef as useRef7, useState as useState7 } from "react";
5
5
  import { createRoot } from "react-dom/client";
6
6
  import { flushSync } from "react-dom";
7
7
 
@@ -48,13 +48,12 @@ function useLinkHrefGuardian(...deps) {
48
48
  }
49
49
 
50
50
  // src/ui/SchedulingWidget.tsx
51
- import { useCallback, useEffect, useId, useMemo, useRef, useState as useState2 } from "react";
51
+ import { useEffect, useId, useMemo, useRef, useState as useState2 } from "react";
52
52
 
53
53
  // src/ui/EmailCaptureModal.tsx
54
54
  import { useState } from "react";
55
55
  import { Dialog } from "radix-ui";
56
56
  import { jsx, jsxs } from "react/jsx-runtime";
57
- var isValidEmail = (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
58
57
  function Spinner() {
59
58
  return /* @__PURE__ */ jsxs(
60
59
  "svg",
@@ -88,17 +87,12 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
88
87
  const [error, setError] = useState(null);
89
88
  const isBook = title === "Confirm your spot";
90
89
  const handleSubmit = async () => {
91
- const trimmed = email.trim();
92
- if (!trimmed) return;
93
- if (!isValidEmail(trimmed)) {
94
- setError("Please enter a valid email address.");
95
- return;
96
- }
90
+ if (!email.trim()) return;
97
91
  setLoading(true);
98
92
  setError(null);
99
93
  try {
100
- await onSubmit(trimmed);
101
- setSubmittedEmail(trimmed);
94
+ await onSubmit(email.trim());
95
+ setSubmittedEmail(email.trim());
102
96
  setSuccess(true);
103
97
  } catch (e) {
104
98
  setError(e instanceof Error ? e.message : "Something went wrong. Please try again.");
@@ -173,10 +167,7 @@ function EmailCaptureModal({ title, subtitle, onSubmit, onClose }) {
173
167
  {
174
168
  type: "email",
175
169
  value: email,
176
- onChange: (e) => {
177
- setEmail(e.target.value);
178
- if (error) setError(null);
179
- },
170
+ onChange: (e) => setEmail(e.target.value),
180
171
  onKeyDown: handleKeyDown,
181
172
  placeholder: "hello@gmail.com",
182
173
  autoFocus: true,
@@ -233,20 +224,12 @@ function formatClassTime(cls) {
233
224
  const em = endTotal % 60;
234
225
  return `${h}:${cls.startTime.minutes}-${eh}:${String(em).padStart(2, "0")}`;
235
226
  }
236
- function formatBookingLabel(cls) {
237
- const price = cls.price;
238
- const isFree = price === null || price === void 0 || `${price}` === "" || `${price}` === "0";
239
- return isFree ? "Book for free" : `Book for ${cls.currency ?? ""} ${price}`.trim();
240
- }
241
227
  function getBookingsOnDate(cls, date) {
242
228
  if (!cls.bookings?.length) return 0;
243
- const target = new Date(date);
244
- target.setHours(0, 0, 0, 0);
229
+ const ds = date.toISOString().split("T")[0];
245
230
  return cls.bookings.filter((b) => {
246
231
  try {
247
- const bookingDate = new Date(b.classDate);
248
- bookingDate.setHours(0, 0, 0, 0);
249
- return bookingDate.getTime() === target.getTime();
232
+ return new Date(b.classDate).toISOString().split("T")[0] === ds;
250
233
  } catch {
251
234
  return false;
252
235
  }
@@ -511,7 +494,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
511
494
  }
512
495
  )
513
496
  ] }),
514
- cls.showAvailability !== false && /* @__PURE__ */ jsx2("div", { className: "sm:hidden flex flex-col gap-px", children: isFull ? /* @__PURE__ */ jsx2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
497
+ /* @__PURE__ */ jsx2("div", { className: "sm:hidden flex flex-col gap-px", children: isFull ? /* @__PURE__ */ jsx2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
515
498
  /* @__PURE__ */ jsxs2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
516
499
  available,
517
500
  "/",
@@ -523,17 +506,9 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
523
506
  /* @__PURE__ */ jsxs2("div", { className: "flex flex-1 flex-col gap-2 min-w-0 sm:contents", children: [
524
507
  /* @__PURE__ */ jsxs2("div", { className: "flex-1 flex flex-col gap-2 min-w-0", children: [
525
508
  /* @__PURE__ */ jsx2("span", { className: "font-body text-base font-bold text-(--color-dark,#200C02) block truncate", children: cls.name }),
526
- cls.hostName && /* @__PURE__ */ jsx2("span", { className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block truncate", children: cls.hostName }),
527
- cls.description && /* @__PURE__ */ jsx2(
528
- "span",
529
- {
530
- className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block",
531
- style: { wordBreak: "break-word" },
532
- children: cls.description
533
- }
534
- )
509
+ cls.hostName && /* @__PURE__ */ jsx2("span", { className: "font-body text-base font-normal text-(--color-dark,#200C02) opacity-80 block truncate", children: cls.hostName })
535
510
  ] }),
536
- cls.showAvailability !== false && /* @__PURE__ */ jsx2("div", { className: "hidden sm:flex w-14 shrink-0 flex-col gap-px", children: isFull ? /* @__PURE__ */ jsx2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
511
+ /* @__PURE__ */ jsx2("div", { className: "hidden sm:flex w-14 shrink-0 flex-col gap-px", children: isFull ? /* @__PURE__ */ jsx2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: "Full" }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
537
512
  /* @__PURE__ */ jsxs2("span", { className: "font-body text-sm text-(--color-dark,#200C02) opacity-80", children: [
538
513
  available,
539
514
  "/",
@@ -558,7 +533,7 @@ function ScheduleView({ schedule, dates, selectedIdx, onSelectDate, onOpenModal
558
533
  if (!cls.id) return;
559
534
  onOpenModal?.(isFull ? "waitlist" : "book", cls.id, selectedDate);
560
535
  },
561
- children: isFull ? "Join Waitlist" : formatBookingLabel(cls)
536
+ children: isFull ? "Join Waitlist" : "Book Now"
562
537
  }
563
538
  )
564
539
  ] })
@@ -600,17 +575,6 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
600
575
  const [isHovered, setIsHovered] = useState2(false);
601
576
  const [modalState, setModalState] = useState2(null);
602
577
  const switchScheduleIdRef = useRef(null);
603
- const liveScheduleIdRef = useRef(null);
604
- const refetchLiveSchedule = useCallback(async () => {
605
- const id = liveScheduleIdRef.current;
606
- if (!id) return;
607
- try {
608
- const res = await fetch(`${API_URL}/api/schedule/id/${id}`);
609
- const data = await res.json();
610
- if (data?.id) setSchedule(data);
611
- } catch {
612
- }
613
- }, []);
614
578
  const dates = useMemo(() => {
615
579
  const today = /* @__PURE__ */ new Date();
616
580
  today.setHours(0, 0, 0, 0);
@@ -630,18 +594,6 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
630
594
  }
631
595
  }
632
596
  }, [schedule, dates]);
633
- useEffect(() => {
634
- if (typeof window === "undefined") return;
635
- const onVisible = () => {
636
- if (!document.hidden) void refetchLiveSchedule();
637
- };
638
- window.addEventListener("focus", refetchLiveSchedule);
639
- document.addEventListener("visibilitychange", onVisible);
640
- return () => {
641
- window.removeEventListener("focus", refetchLiveSchedule);
642
- document.removeEventListener("visibilitychange", onVisible);
643
- };
644
- }, [refetchLiveSchedule]);
645
597
  useEffect(() => {
646
598
  if (typeof window === "undefined") return;
647
599
  const isInEditor = window.self !== window.top;
@@ -703,7 +655,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
703
655
  setLoading(false);
704
656
  return;
705
657
  }
706
- liveScheduleIdRef.current = effectiveId;
658
+ ;
707
659
  (async () => {
708
660
  try {
709
661
  const res = await fetch(`${API_URL}/api/schedule/id/${effectiveId}`);
@@ -760,14 +712,18 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
760
712
  const data = await res.json().catch(() => ({}));
761
713
  throw new Error(data?.message ?? "Something went wrong. Please try again.");
762
714
  }
763
- await refetchLiveSchedule();
764
715
  };
765
716
  const handleReplaceSchedule = () => {
766
717
  setIsHovered(false);
767
- window.parent.postMessage(
768
- { type: "ow:scheduling-not-connected", insertAfter, currentScheduleId: schedule?.id },
769
- "*"
770
- );
718
+ if (schedule) {
719
+ window.parent.postMessage({
720
+ type: "ow:schedule-connected",
721
+ schedule: { id: schedule.id, name: schedule.name },
722
+ insertAfter
723
+ }, "*");
724
+ } else {
725
+ window.parent.postMessage({ type: "ow:scheduling-not-connected", insertAfter }, "*");
726
+ }
771
727
  };
772
728
  if (!inEditor && !loading && !schedule) return null;
773
729
  const sectionId = `scheduling-${insertAfter}`;
@@ -810,19 +766,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
810
766
  ),
811
767
  /* @__PURE__ */ jsxs2("div", { className: "max-w-[1280px] mx-auto flex flex-col items-center gap-16", children: [
812
768
  /* @__PURE__ */ jsxs2("div", { className: "flex flex-col items-center gap-4", children: [
813
- /* @__PURE__ */ jsx2(
814
- "h2",
815
- {
816
- className: "font-display text-center m-0 text-(--color-dark,#200C02)",
817
- style: {
818
- fontSize: "var(--fs-section-h2, clamp(40px, 4.4vw, 64px))",
819
- fontWeight: "var(--font-weight-heading, 400)",
820
- lineHeight: 1.05,
821
- letterSpacing: "-0.02em"
822
- },
823
- children: schedule?.name ?? "Book an appointment"
824
- }
825
- ),
769
+ /* @__PURE__ */ jsx2("h2", { className: "font-display text-4xl sm:text-5xl font-bold text-center m-0 text-(--color-dark,#200C02)", children: schedule?.name ?? "Book an appointment" }),
826
770
  schedule?.description && /* @__PURE__ */ jsx2("p", { className: "font-body text-body text-center m-0 text-(--color-accent,#A89B83)", children: schedule.description })
827
771
  ] }),
828
772
  /* @__PURE__ */ jsxs2("div", { className: "w-full flex flex-col items-end gap-3", children: [
@@ -4882,11 +4826,7 @@ function MediaOverlay({
4882
4826
  variant: "outline",
4883
4827
  size: "sm",
4884
4828
  className: "gap-1.5 cursor-pointer hover:bg-background",
4885
- style: {
4886
- ...OVERLAY_BUTTON_STYLE,
4887
- // Don't let Replace steal clicks when text (e.g. nav) sits on top of this media.
4888
- pointerEvents: hover.hasTextOverlap ? "none" : "auto"
4889
- },
4829
+ style: OVERLAY_BUTTON_STYLE,
4890
4830
  onMouseDown: (e) => e.preventDefault(),
4891
4831
  onClick: (e) => {
4892
4832
  e.stopPropagation();
@@ -5663,7 +5603,7 @@ function LinkEditorPanel({ state, onClose }) {
5663
5603
  }
5664
5604
 
5665
5605
  // src/ui/link-modal/SectionPickerOverlay.tsx
5666
- import { useCallback as useCallback2, useEffect as useEffect4, useMemo as useMemo2, useRef as useRef5, useState as useState4 } from "react";
5606
+ import { useCallback, useEffect as useEffect4, useMemo as useMemo2, useRef as useRef5, useState as useState4 } from "react";
5667
5607
  import { createPortal } from "react-dom";
5668
5608
  import { ArrowLeft, Check } from "lucide-react";
5669
5609
  import { usePathname, useRouter } from "next/navigation";
@@ -5794,7 +5734,7 @@ function SectionPickerOverlay({
5794
5734
  );
5795
5735
  sectionIdsRef.current = sectionIds;
5796
5736
  const rects = useSectionRects(sectionIdsKey, isOnTargetPage);
5797
- const applyHoverAt = useCallback2(
5737
+ const applyHoverAt = useCallback(
5798
5738
  (x, y, liveRects) => {
5799
5739
  const ids = sectionIdsRef.current;
5800
5740
  const map = liveRects ?? readSectionRects(ids);
@@ -5874,7 +5814,7 @@ function SectionPickerOverlay({
5874
5814
  window.removeEventListener("message", onPointerSync);
5875
5815
  };
5876
5816
  }, [rects, applyHoverAt]);
5877
- const handleSelect = useCallback2(
5817
+ const handleSelect = useCallback(
5878
5818
  (section) => {
5879
5819
  if (selectedId) return;
5880
5820
  setSelectedId(section.id);
@@ -6005,7 +5945,7 @@ function SectionPickerOverlay({
6005
5945
  }
6006
5946
 
6007
5947
  // src/ui/link-modal/useLinkModalState.ts
6008
- import { useCallback as useCallback3, useEffect as useEffect5, useMemo as useMemo3, useState as useState5 } from "react";
5948
+ import { useCallback as useCallback2, useEffect as useEffect5, useMemo as useMemo3, useState as useState5 } from "react";
6009
5949
  function useLinkModalState({
6010
5950
  open,
6011
5951
  mode,
@@ -6024,7 +5964,7 @@ function useLinkModalState({
6024
5964
  const [step, setStep] = useState5("input");
6025
5965
  const [dropdownOpen, setDropdownOpen] = useState5(false);
6026
5966
  const [urlError, setUrlError] = useState5("");
6027
- const reset = useCallback3(() => {
5967
+ const reset = useCallback2(() => {
6028
5968
  setSearchValue("");
6029
5969
  setSelectedPage(null);
6030
5970
  setSelectedSection(null);
@@ -6660,8 +6600,6 @@ function applyNavOrderToContainer(container, order) {
6660
6600
  if (current.length === expected.length && current.every((key, i) => key === expected[i])) {
6661
6601
  return;
6662
6602
  }
6663
- const lastCurrentLinkEl = current.length > 0 ? findCounterpartByHrefKey(current[current.length - 1], container) : null;
6664
- const anchor = lastCurrentLinkEl?.parentElement === container ? lastCurrentLinkEl.nextElementSibling : null;
6665
6603
  const seen = /* @__PURE__ */ new Set();
6666
6604
  for (const hrefKey of desired) {
6667
6605
  if (seen.has(hrefKey)) continue;
@@ -6676,9 +6614,7 @@ function applyNavOrderToContainer(container, order) {
6676
6614
  orderedEls.push(el);
6677
6615
  }
6678
6616
  for (const el of orderedEls) {
6679
- if (anchor) {
6680
- if (el.nextSibling !== anchor) container.insertBefore(el, anchor);
6681
- } else if (container.lastElementChild !== el) {
6617
+ if (container.lastElementChild !== el) {
6682
6618
  container.appendChild(el);
6683
6619
  }
6684
6620
  }
@@ -7010,195 +6946,7 @@ function parseFooterOrder(content) {
7010
6946
  return null;
7011
6947
  }
7012
6948
  }
7013
- var FOOTER_HEADING_RE = /^footer-(\d+)-heading$/;
7014
- var FOOTER_LABEL_RE = /^footer-(\d+)-(\d+)-label$/;
7015
- var DEFAULT_FOOTER_COLUMN_HEADING = "New";
7016
- var DEFAULT_FOOTER_COLUMN_LINK_LABEL = "New link";
7017
- var DEFAULT_FOOTER_COLUMN_LINK_HREF = "";
7018
- function isFooterLinksContainer(el) {
7019
- return el.hasAttribute("data-ohw-footer-links") || el.classList.contains("rb-footer-links");
7020
- }
7021
- function getFooterColumnIndicesInDom() {
7022
- const indices = /* @__PURE__ */ new Set();
7023
- for (const col of listFooterColumns()) {
7024
- const attr = col.getAttribute("data-ohw-footer-col");
7025
- if (attr != null) {
7026
- const n = parseInt(attr, 10);
7027
- if (Number.isFinite(n)) indices.add(n);
7028
- }
7029
- for (const link of listFooterLinksInColumn(col)) {
7030
- const parsed = parseFooterHrefKey(link.getAttribute("data-ohw-href-key"));
7031
- if (parsed) indices.add(parsed.col);
7032
- }
7033
- const heading = col.querySelector('[data-ohw-key^="footer-"][data-ohw-key$="-heading"]');
7034
- const headingKey = heading?.getAttribute("data-ohw-key");
7035
- if (headingKey) {
7036
- const match = headingKey.match(FOOTER_HEADING_RE);
7037
- if (match) indices.add(parseInt(match[1], 10));
7038
- }
7039
- }
7040
- return [...indices].sort((a, b) => a - b);
7041
- }
7042
- function getNextFooterColumnIndex() {
7043
- const indices = getFooterColumnIndicesInDom();
7044
- if (indices.length === 0) return 0;
7045
- return Math.max(...indices) + 1;
7046
- }
7047
- function cloneFooterLinkShell(template) {
7048
- const anchor = document.createElement("a");
7049
- if (template) {
7050
- anchor.style.cssText = template.style.cssText;
7051
- if (template.className) anchor.className = template.className;
7052
- }
7053
- anchor.style.cursor = "pointer";
7054
- anchor.style.textDecoration = "none";
7055
- return anchor;
7056
- }
7057
- function buildFooterHeading(colIndex, text) {
7058
- const heading = document.createElement("p");
7059
- heading.setAttribute("data-ohw-editable", "text");
7060
- heading.setAttribute("data-ohw-key", `footer-${colIndex}-heading`);
7061
- heading.textContent = text;
7062
- heading.style.cssText = [
7063
- "color: var(--espresso, #3d312b)",
7064
- "font-size: 14px",
7065
- "font-weight: 800",
7066
- "opacity: 0.82",
7067
- "margin: 0 0 6px",
7068
- "padding: 0",
7069
- "line-height: 1.2"
7070
- ].join(";");
7071
- return heading;
7072
- }
7073
- function buildFooterLink(colIndex, itemIndex, href, label, template) {
7074
- const anchor = cloneFooterLinkShell(template);
7075
- anchor.setAttribute("href", href);
7076
- anchor.setAttribute("data-ohw-href-key", `footer-${colIndex}-${itemIndex}-href`);
7077
- const span = document.createElement("span");
7078
- span.setAttribute("data-ohw-editable", "text");
7079
- span.setAttribute("data-ohw-key", `footer-${colIndex}-${itemIndex}-label`);
7080
- span.textContent = label;
7081
- anchor.appendChild(span);
7082
- return anchor;
7083
- }
7084
- function footerColumnExistsInDom(colIndex) {
7085
- 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;
7086
- }
7087
- function getFooterLinkTemplate() {
7088
- for (const col of listFooterColumns()) {
7089
- const link = listFooterLinksInColumn(col)[0];
7090
- if (link) return link;
7091
- }
7092
- return null;
7093
- }
7094
- function getFooterColumnTemplate() {
7095
- return listFooterColumns()[0] ?? null;
7096
- }
7097
- function insertFooterColumnDom(colIndex, heading, items) {
7098
- const container = getFooterLinksContainer();
7099
- if (!container) return null;
7100
- const colTemplate = getFooterColumnTemplate();
7101
- const linkTemplate = getFooterLinkTemplate();
7102
- const column = document.createElement("div");
7103
- if (colTemplate?.className) column.className = colTemplate.className;
7104
- else column.className = "rb-footer-link-col";
7105
- column.setAttribute("data-ohw-footer-col", String(colIndex));
7106
- if (colTemplate) {
7107
- const gap = getComputedStyle(colTemplate).gap;
7108
- if (gap && gap !== "normal") column.style.gap = gap;
7109
- column.style.display = getComputedStyle(colTemplate).display || "flex";
7110
- column.style.flexDirection = "column";
7111
- }
7112
- column.appendChild(buildFooterHeading(colIndex, heading));
7113
- let firstLink = null;
7114
- items.forEach((item, itemIndex) => {
7115
- const link = buildFooterLink(colIndex, itemIndex, item.href, item.label, linkTemplate);
7116
- column.appendChild(link);
7117
- if (!firstLink) firstLink = link;
7118
- });
7119
- container.appendChild(column);
7120
- return { column, firstLink };
7121
- }
7122
- function insertFooterColumn(heading = DEFAULT_FOOTER_COLUMN_HEADING, linkLabel = DEFAULT_FOOTER_COLUMN_LINK_LABEL, linkHref = DEFAULT_FOOTER_COLUMN_LINK_HREF) {
7123
- const colIndex = getNextFooterColumnIndex();
7124
- const inserted = insertFooterColumnDom(colIndex, heading, [{ href: linkHref, label: linkLabel }]);
7125
- if (!inserted?.firstLink) throw new Error("Failed to insert footer column");
7126
- syncFooterColumnIndices(listFooterColumns());
7127
- return {
7128
- column: inserted.column,
7129
- firstLink: inserted.firstLink,
7130
- colIndex,
7131
- headingKey: `footer-${colIndex}-heading`,
7132
- hrefKey: `footer-${colIndex}-0-href`,
7133
- labelKey: `footer-${colIndex}-0-label`,
7134
- heading,
7135
- label: linkLabel,
7136
- href: linkHref,
7137
- order: getFooterOrderFromDom()
7138
- };
7139
- }
7140
- function collectFooterColumnIndicesFromContent(content) {
7141
- const indices = /* @__PURE__ */ new Set();
7142
- for (const key of Object.keys(content)) {
7143
- const href = parseFooterHrefKey(key);
7144
- if (href) indices.add(href.col);
7145
- const heading = key.match(FOOTER_HEADING_RE);
7146
- if (heading) indices.add(parseInt(heading[1], 10));
7147
- const label = key.match(FOOTER_LABEL_RE);
7148
- if (label) indices.add(parseInt(label[1], 10));
7149
- }
7150
- const order = parseFooterOrder(content);
7151
- if (order) {
7152
- for (const col of order) {
7153
- for (const hrefKey of col) {
7154
- const parsed = parseFooterHrefKey(hrefKey);
7155
- if (parsed) indices.add(parsed.col);
7156
- }
7157
- }
7158
- }
7159
- return [...indices].sort((a, b) => a - b);
7160
- }
7161
- function collectFooterItemsForColumn(content, colIndex) {
7162
- const itemIndices = /* @__PURE__ */ new Set();
7163
- for (const key of Object.keys(content)) {
7164
- const href = parseFooterHrefKey(key);
7165
- if (href?.col === colIndex) itemIndices.add(href.item);
7166
- const label = key.match(FOOTER_LABEL_RE);
7167
- if (label && parseInt(label[1], 10) === colIndex) {
7168
- itemIndices.add(parseInt(label[2], 10));
7169
- }
7170
- }
7171
- const sorted = [...itemIndices].sort((a, b) => a - b);
7172
- if (sorted.length === 0) {
7173
- return [
7174
- {
7175
- href: content[`footer-${colIndex}-0-href`] ?? DEFAULT_FOOTER_COLUMN_LINK_HREF,
7176
- label: content[`footer-${colIndex}-0-label`] ?? DEFAULT_FOOTER_COLUMN_LINK_LABEL
7177
- }
7178
- ];
7179
- }
7180
- return sorted.map((itemIndex) => ({
7181
- href: content[`footer-${colIndex}-${itemIndex}-href`] ?? DEFAULT_FOOTER_COLUMN_LINK_HREF,
7182
- label: content[`footer-${colIndex}-${itemIndex}-label`] ?? DEFAULT_FOOTER_COLUMN_LINK_LABEL
7183
- }));
7184
- }
7185
- function reconcileFooterColumnsFromContent(content) {
7186
- const indices = collectFooterColumnIndicesFromContent(content);
7187
- for (const colIndex of indices) {
7188
- if (footerColumnExistsInDom(colIndex)) continue;
7189
- const heading = content[`footer-${colIndex}-heading`] ?? DEFAULT_FOOTER_COLUMN_HEADING;
7190
- const items = collectFooterItemsForColumn(content, colIndex);
7191
- const hasPayload = Boolean(content[`footer-${colIndex}-heading`]) || items.some(
7192
- (_, i) => content[`footer-${colIndex}-${i}-href`] !== void 0 || content[`footer-${colIndex}-${i}-label`] !== void 0
7193
- ) || (parseFooterOrder(content)?.some(
7194
- (col) => col.some((k) => parseFooterHrefKey(k)?.col === colIndex)
7195
- ) ?? false);
7196
- if (!hasPayload) continue;
7197
- insertFooterColumnDom(colIndex, heading, items);
7198
- }
7199
- }
7200
6949
  function reconcileFooterOrderFromContent(content) {
7201
- reconcileFooterColumnsFromContent(content);
7202
6950
  const order = parseFooterOrder(content);
7203
6951
  if (!order?.length) return;
7204
6952
  const current = getFooterOrderFromDom();
@@ -7208,31 +6956,6 @@ function reconcileFooterOrderFromContent(content) {
7208
6956
  }
7209
6957
  applyFooterOrder(order);
7210
6958
  }
7211
- function resolveFooterLinksContainerSelectionTarget(target, clientX, clientY, isPointOverItem) {
7212
- const container = getFooterLinksContainer();
7213
- if (!container) return null;
7214
- const inContainer = target === container || container.contains(target) && Boolean(target.closest("[data-ohw-footer-links], .rb-footer-links"));
7215
- if (!inContainer && target !== container) {
7216
- const r2 = container.getBoundingClientRect();
7217
- const over = clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
7218
- if (!over) return null;
7219
- }
7220
- if (isPointOverItem(container, clientX, clientY)) return null;
7221
- const column = target.closest("[data-ohw-footer-col], [data-ohw-footer-column]") ?? null;
7222
- if (column && container.contains(column)) {
7223
- if (target === column || column.contains(target)) return null;
7224
- }
7225
- if (target === container || container.contains(target) || inContainer) {
7226
- if (target === container || isFooterLinksContainer(target)) return container;
7227
- if (!column) return container;
7228
- }
7229
- return null;
7230
- }
7231
- function isRowLayoutColumn(links) {
7232
- if (links.length < 2) return false;
7233
- const firstTop = links[0].getBoundingClientRect().top;
7234
- return links.every((link) => Math.abs(link.getBoundingClientRect().top - firstTop) < 4);
7235
- }
7236
6959
  function buildLinkDropSlots(column, columnIndex) {
7237
6960
  const links = listFooterLinksInColumn(column);
7238
6961
  const colRect = column.getBoundingClientRect();
@@ -7250,32 +6973,6 @@ function buildLinkDropSlots(column, columnIndex) {
7250
6973
  });
7251
6974
  return slots;
7252
6975
  }
7253
- if (isRowLayoutColumn(links)) {
7254
- for (let i = 0; i <= links.length; i++) {
7255
- let left;
7256
- if (i === 0) {
7257
- left = links[0].getBoundingClientRect().left - barThickness / 2;
7258
- } else if (i === links.length) {
7259
- const last = links[links.length - 1].getBoundingClientRect();
7260
- left = last.right - barThickness / 2;
7261
- } else {
7262
- const prev = links[i - 1].getBoundingClientRect();
7263
- const next = links[i].getBoundingClientRect();
7264
- left = (prev.right + next.left) / 2 - barThickness / 2;
7265
- }
7266
- const heightRef = i === 0 ? links[0].getBoundingClientRect() : i === links.length ? links[links.length - 1].getBoundingClientRect() : links[i].getBoundingClientRect();
7267
- slots.push({
7268
- insertIndex: i,
7269
- columnIndex,
7270
- left,
7271
- top: heightRef.top,
7272
- width: barThickness,
7273
- height: Math.max(heightRef.height, colRect.height * 0.8),
7274
- direction: "vertical"
7275
- });
7276
- }
7277
- return slots;
7278
- }
7279
6976
  for (let i = 0; i <= links.length; i++) {
7280
6977
  let top;
7281
6978
  if (i === 0) {
@@ -7359,7 +7056,8 @@ function hitTestLinkDropSlot(clientX, clientY, draggedHrefKey) {
7359
7056
  return true;
7360
7057
  });
7361
7058
  for (const slot of slots) {
7362
- const dist = slot.direction === "vertical" ? Math.abs(clientX - (slot.left + slot.width / 2)) : Math.abs(clientY - (slot.top + slot.height / 2));
7059
+ const cy = slot.top + slot.height / 2;
7060
+ const dist = Math.abs(clientY - cy) + (inColX ? 0 : 1e3);
7363
7061
  if (!best || dist < best.dist) best = { slot, dist };
7364
7062
  }
7365
7063
  }
@@ -7383,30 +7081,6 @@ function hitTestColumnDropSlot(clientX, _clientY) {
7383
7081
  return best?.slot ?? null;
7384
7082
  }
7385
7083
 
7386
- // src/lib/add-footer-column.ts
7387
- function buildFooterColumnEditContentPatch(result) {
7388
- return {
7389
- [result.headingKey]: result.heading,
7390
- [result.hrefKey]: result.href,
7391
- [result.labelKey]: result.label,
7392
- [FOOTER_ORDER_KEY]: JSON.stringify(result.order)
7393
- };
7394
- }
7395
- function addFooterColumnWithPersist({
7396
- postToParent: postToParent2
7397
- }) {
7398
- const result = insertFooterColumn();
7399
- const patch = buildFooterColumnEditContentPatch(result);
7400
- setStoredLinkHref(result.hrefKey, result.href);
7401
- postToParent2({
7402
- type: "ow:change",
7403
- nodes: Object.entries(patch).map(([key, text]) => ({ key, text }))
7404
- });
7405
- postToParent2({ type: "ow:toast", title: "Item added", toastType: "success" });
7406
- enforceLinkHrefs();
7407
- return result;
7408
- }
7409
-
7410
7084
  // src/lib/item-drag-interaction.ts
7411
7085
  function disableNativeHrefDrag(el) {
7412
7086
  if (el.draggable) el.draggable = false;
@@ -7427,10 +7101,9 @@ function lockItemDuringDrag() {
7427
7101
  clearTextSelection();
7428
7102
  }
7429
7103
  function unlockItemDragInteraction() {
7430
- const wasDragging = document.documentElement.hasAttribute("data-ohw-item-dragging");
7431
7104
  document.documentElement.removeAttribute("data-ohw-footer-press-drag");
7432
7105
  document.documentElement.removeAttribute("data-ohw-item-dragging");
7433
- if (wasDragging) clearTextSelection();
7106
+ clearTextSelection();
7434
7107
  }
7435
7108
  var armFooterPressDrag = armItemPressDrag;
7436
7109
  var lockFooterDuringDrag = lockItemDuringDrag;
@@ -7604,7 +7277,7 @@ function hitTestNavDropSlot(clientX, clientY, draggedHrefKey) {
7604
7277
  }
7605
7278
 
7606
7279
  // src/useNavItemDrag.ts
7607
- import { useCallback as useCallback4, useEffect as useEffect7, useRef as useRef6, useState as useState6 } from "react";
7280
+ import { useCallback as useCallback3, useEffect as useEffect7, useRef as useRef6, useState as useState6 } from "react";
7608
7281
  function useNavItemDrag({
7609
7282
  isEditMode,
7610
7283
  editContentRef,
@@ -7633,7 +7306,7 @@ function useNavItemDrag({
7633
7306
  const [navDropSlots, setNavDropSlots] = useState6([]);
7634
7307
  const [activeNavDropIndex, setActiveNavDropIndex] = useState6(null);
7635
7308
  const navPointerDragRef = useRef6(null);
7636
- const clearNavDragVisuals = useCallback4(() => {
7309
+ const clearNavDragVisuals = useCallback3(() => {
7637
7310
  navDragRef.current = null;
7638
7311
  setNavDropSlots([]);
7639
7312
  setActiveNavDropIndex(null);
@@ -7642,7 +7315,7 @@ function useNavItemDrag({
7642
7315
  setIsItemDragging(false);
7643
7316
  unlockItemDragInteraction();
7644
7317
  }, [setDraggedItemRect, setIsItemDragging, setSiblingHintRects]);
7645
- const refreshNavDragVisuals = useCallback4(
7318
+ const refreshNavDragVisuals = useCallback3(
7646
7319
  (session, activeSlot, clientX, clientY) => {
7647
7320
  setDraggedItemRect(session.draggedEl.getBoundingClientRect());
7648
7321
  if (typeof clientX === "number" && typeof clientY === "number") {
@@ -7666,7 +7339,7 @@ function useNavItemDrag({
7666
7339
  });
7667
7340
  const beginNavDragRef = useRef6(() => {
7668
7341
  });
7669
- const beginNavDrag = useCallback4(
7342
+ const beginNavDrag = useCallback3(
7670
7343
  (session) => {
7671
7344
  const rect = session.draggedEl.getBoundingClientRect();
7672
7345
  session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
@@ -7693,7 +7366,7 @@ function useNavItemDrag({
7693
7366
  ]
7694
7367
  );
7695
7368
  beginNavDragRef.current = beginNavDrag;
7696
- const commitNavDrag = useCallback4(
7369
+ const commitNavDrag = useCallback3(
7697
7370
  (clientX, clientY) => {
7698
7371
  const session = navDragRef.current;
7699
7372
  if (!session) {
@@ -7754,7 +7427,7 @@ function useNavItemDrag({
7754
7427
  [clearNavDragVisuals, deselectRef, editContentRef, postToParentRef, selectRef]
7755
7428
  );
7756
7429
  commitNavDragRef.current = commitNavDrag;
7757
- const startNavLinkDrag = useCallback4(
7430
+ const startNavLinkDrag = useCallback3(
7758
7431
  (anchor, clientX, clientY, wasSelected) => {
7759
7432
  if (footerDragRef.current) return false;
7760
7433
  const hrefKey = anchor.getAttribute("data-ohw-href-key");
@@ -7772,7 +7445,7 @@ function useNavItemDrag({
7772
7445
  },
7773
7446
  [beginNavDrag, footerDragRef, isDragHandleDisabled2, isNavbarButton3]
7774
7447
  );
7775
- const onNavDragOver = useCallback4(
7448
+ const onNavDragOver = useCallback3(
7776
7449
  (e) => {
7777
7450
  const session = navDragRef.current;
7778
7451
  if (!session) return false;
@@ -7807,6 +7480,7 @@ function useNavItemDrag({
7807
7480
  const hrefKey = anchor?.getAttribute("data-ohw-href-key") ?? null;
7808
7481
  if (!anchor || !isNavbarHrefKey(hrefKey)) return;
7809
7482
  if (isNavbarButton3(anchor) || isDragHandleDisabled2(anchor)) return;
7483
+ armItemPressDrag();
7810
7484
  navPointerDragRef.current = {
7811
7485
  el: anchor,
7812
7486
  startX: e.clientX,
@@ -7833,7 +7507,6 @@ function useNavItemDrag({
7833
7507
  if (dx * dx + dy * dy < THRESHOLD * THRESHOLD) return;
7834
7508
  e.preventDefault();
7835
7509
  pending.started = true;
7836
- armItemPressDrag();
7837
7510
  clearTextSelection();
7838
7511
  try {
7839
7512
  document.body.setPointerCapture(pending.pointerId);
@@ -7861,8 +7534,7 @@ function useNavItemDrag({
7861
7534
  }
7862
7535
  } catch {
7863
7536
  }
7864
- if (!pending) return;
7865
- if (!pending.started) {
7537
+ if (!pending?.started) {
7866
7538
  unlockItemDragInteraction();
7867
7539
  return;
7868
7540
  }
@@ -7909,11 +7581,12 @@ function useNavItemDrag({
7909
7581
  setLinkPopover,
7910
7582
  suppressNextClickRef
7911
7583
  ]);
7912
- const armNavPressFromChrome = useCallback4(
7584
+ const armNavPressFromChrome = useCallback3(
7913
7585
  (selected, clientX, clientY, pointerId) => {
7914
7586
  const hrefKey = selected.getAttribute("data-ohw-href-key");
7915
7587
  if (!hrefKey || !isNavbarHrefKey(hrefKey)) return false;
7916
7588
  if (isNavbarButton3(selected) || isDragHandleDisabled2(selected)) return false;
7589
+ armItemPressDrag();
7917
7590
  navPointerDragRef.current = {
7918
7591
  el: selected,
7919
7592
  startX: clientX,
@@ -7939,60 +7612,15 @@ function useNavItemDrag({
7939
7612
  };
7940
7613
  }
7941
7614
 
7942
- // src/ui/footer-container-chrome.tsx
7943
- import { Plus as Plus2 } from "lucide-react";
7944
- import { jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
7945
- function FooterContainerChrome({ rect, onAdd }) {
7946
- const chromeGap = 6;
7947
- const buttonMargin = 7;
7948
- return /* @__PURE__ */ jsx21(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsx21(
7949
- "div",
7950
- {
7951
- "data-ohw-footer-container-chrome": "",
7952
- "data-ohw-bridge": "",
7953
- className: "pointer-events-none fixed z-[2147483647]",
7954
- style: {
7955
- top: rect.top - chromeGap,
7956
- left: rect.left - chromeGap,
7957
- width: rect.width + chromeGap * 2,
7958
- height: rect.height + chromeGap * 2
7959
- },
7960
- children: /* @__PURE__ */ jsxs13(Tooltip, { children: [
7961
- /* @__PURE__ */ jsx21(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx21(
7962
- "button",
7963
- {
7964
- type: "button",
7965
- "data-ohw-footer-add-button": "",
7966
- 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",
7967
- style: { top: chromeGap - buttonMargin },
7968
- "aria-label": "Add item",
7969
- onMouseDown: (e) => {
7970
- e.preventDefault();
7971
- e.stopPropagation();
7972
- },
7973
- onClick: (e) => {
7974
- e.preventDefault();
7975
- e.stopPropagation();
7976
- onAdd();
7977
- },
7978
- children: /* @__PURE__ */ jsx21(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
7979
- }
7980
- ) }),
7981
- /* @__PURE__ */ jsx21(TooltipContent, { side: "bottom", sideOffset: 9, children: "Add item" })
7982
- ] })
7983
- }
7984
- ) });
7985
- }
7986
-
7987
7615
  // src/ui/navbar-container-chrome.tsx
7988
- import { Plus as Plus3 } from "lucide-react";
7989
- import { jsx as jsx22 } from "react/jsx-runtime";
7616
+ import { Plus as Plus2 } from "lucide-react";
7617
+ import { jsx as jsx21 } from "react/jsx-runtime";
7990
7618
  function NavbarContainerChrome({
7991
7619
  rect,
7992
7620
  onAdd
7993
7621
  }) {
7994
7622
  const chromeGap = 6;
7995
- return /* @__PURE__ */ jsx22(
7623
+ return /* @__PURE__ */ jsx21(
7996
7624
  "div",
7997
7625
  {
7998
7626
  "data-ohw-navbar-container-chrome": "",
@@ -8004,7 +7632,7 @@ function NavbarContainerChrome({
8004
7632
  width: rect.width + chromeGap * 2,
8005
7633
  height: rect.height + chromeGap * 2
8006
7634
  },
8007
- children: /* @__PURE__ */ jsx22(
7635
+ children: /* @__PURE__ */ jsx21(
8008
7636
  "button",
8009
7637
  {
8010
7638
  type: "button",
@@ -8021,7 +7649,7 @@ function NavbarContainerChrome({
8021
7649
  e.stopPropagation();
8022
7650
  onAdd();
8023
7651
  },
8024
- children: /* @__PURE__ */ jsx22(Plus3, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
7652
+ children: /* @__PURE__ */ jsx21(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
8025
7653
  }
8026
7654
  )
8027
7655
  }
@@ -8030,7 +7658,7 @@ function NavbarContainerChrome({
8030
7658
 
8031
7659
  // src/ui/drop-indicator.tsx
8032
7660
  import * as React10 from "react";
8033
- import { jsx as jsx23 } from "react/jsx-runtime";
7661
+ import { jsx as jsx22 } from "react/jsx-runtime";
8034
7662
  var dropIndicatorVariants = cva(
8035
7663
  "ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
8036
7664
  {
@@ -8054,7 +7682,7 @@ var dropIndicatorVariants = cva(
8054
7682
  );
8055
7683
  var DropIndicator = React10.forwardRef(
8056
7684
  ({ className, direction, state, ...props }, ref) => {
8057
- return /* @__PURE__ */ jsx23(
7685
+ return /* @__PURE__ */ jsx22(
8058
7686
  "div",
8059
7687
  {
8060
7688
  ref,
@@ -8071,7 +7699,7 @@ var DropIndicator = React10.forwardRef(
8071
7699
  DropIndicator.displayName = "DropIndicator";
8072
7700
 
8073
7701
  // src/ui/badge.tsx
8074
- import { jsx as jsx24 } from "react/jsx-runtime";
7702
+ import { jsx as jsx23 } from "react/jsx-runtime";
8075
7703
  var badgeVariants = cva(
8076
7704
  "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
8077
7705
  {
@@ -8089,12 +7717,12 @@ var badgeVariants = cva(
8089
7717
  }
8090
7718
  );
8091
7719
  function Badge({ className, variant, ...props }) {
8092
- return /* @__PURE__ */ jsx24("div", { className: cn(badgeVariants({ variant }), className), ...props });
7720
+ return /* @__PURE__ */ jsx23("div", { className: cn(badgeVariants({ variant }), className), ...props });
8093
7721
  }
8094
7722
 
8095
7723
  // src/OhhwellsBridge.tsx
8096
7724
  import { Link as Link2 } from "lucide-react";
8097
- import { Fragment as Fragment5, jsx as jsx25, jsxs as jsxs14 } from "react/jsx-runtime";
7725
+ import { Fragment as Fragment5, jsx as jsx24, jsxs as jsxs13 } from "react/jsx-runtime";
8098
7726
  var PRIMARY2 = "#0885FE";
8099
7727
  var IMAGE_FADE_MS = 300;
8100
7728
  function runOpacityFade(el, onDone) {
@@ -8273,7 +7901,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
8273
7901
  const root = createRoot(container);
8274
7902
  flushSync(() => {
8275
7903
  root.render(
8276
- /* @__PURE__ */ jsx25(
7904
+ /* @__PURE__ */ jsx24(
8277
7905
  SchedulingWidget,
8278
7906
  {
8279
7907
  notifyOnConnect,
@@ -8474,7 +8102,7 @@ function applyLinkByKey(key, val) {
8474
8102
  }
8475
8103
  function isInsideLinkEditor(target) {
8476
8104
  return Boolean(
8477
- 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"]')
8105
+ 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"]')
8478
8106
  );
8479
8107
  }
8480
8108
  function getHrefKeyFromElement(el) {
@@ -8555,7 +8183,7 @@ function isInferredFooterGroup(el) {
8555
8183
  return countFooterNavItems(el) >= 2;
8556
8184
  }
8557
8185
  function isNavigationContainer(el) {
8558
- 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);
8186
+ return el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isNavigationRoot(el) || isInferredFooterGroup(el);
8559
8187
  }
8560
8188
  function isNavbarLinksContainer(el) {
8561
8189
  return el.hasAttribute("data-ohw-nav-container");
@@ -8574,9 +8202,6 @@ function isPointOverNavigation(x, y) {
8574
8202
  const roots = /* @__PURE__ */ new Set();
8575
8203
  const navRoot = document.querySelector("[data-ohw-nav-root]") ?? document.querySelector("nav");
8576
8204
  if (navRoot) roots.add(navRoot);
8577
- document.querySelectorAll("[data-ohw-nav-drawer], [data-ohw-nav-container]").forEach((el) => {
8578
- roots.add(el);
8579
- });
8580
8205
  const footer = document.querySelector("footer");
8581
8206
  if (footer) roots.add(footer);
8582
8207
  for (const root of roots) {
@@ -8605,12 +8230,6 @@ function isPointOverNavItem(container, x, y) {
8605
8230
  return x >= itemRect.left && x <= itemRect.right && y >= itemRect.top && y <= itemRect.bottom;
8606
8231
  });
8607
8232
  }
8608
- function isPointOverFooterColumn(x, y) {
8609
- return listFooterColumns().some((col) => {
8610
- const r2 = col.getBoundingClientRect();
8611
- return x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom;
8612
- });
8613
- }
8614
8233
  function resolveNavContainerSelectionTarget(target, clientX, clientY) {
8615
8234
  if (getNavigationItemAnchor(target)) return null;
8616
8235
  if (target.closest('[data-ohw-role="navbar-button"]')) return null;
@@ -8641,10 +8260,7 @@ function getNavigationSelectionParent(el) {
8641
8260
  if (footerGroup) return footerGroup;
8642
8261
  return getNavigationRoot(el);
8643
8262
  }
8644
- if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup(el))) {
8645
- return getFooterLinksContainer();
8646
- }
8647
- if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isFooterLinksContainer(el) || isInferredFooterGroup(el)) {
8263
+ if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup(el)) {
8648
8264
  return getNavigationRoot(el);
8649
8265
  }
8650
8266
  return null;
@@ -8815,16 +8431,9 @@ function sanitizeHtml(html) {
8815
8431
  if (!SAFE_TAGS.has(el.tagName)) {
8816
8432
  parent.replaceChild(document.createTextNode(el.textContent ?? ""), el);
8817
8433
  } else {
8818
- const htmlEl = el;
8819
- const textAlign = htmlEl.style?.textAlign || el.getAttribute("align") || "";
8820
- const fontWeight = htmlEl.style?.fontWeight || "";
8821
- const fontStyle = htmlEl.style?.fontStyle || "";
8822
- const textDecorationLine = htmlEl.style?.textDecorationLine || htmlEl.style?.textDecoration || "";
8434
+ const textAlign = el.style?.textAlign || el.getAttribute("align") || "";
8823
8435
  for (const attr of Array.from(el.attributes)) el.removeAttribute(attr.name);
8824
- if (textAlign) htmlEl.style.textAlign = textAlign;
8825
- if (fontWeight) htmlEl.style.fontWeight = fontWeight;
8826
- if (fontStyle) htmlEl.style.fontStyle = fontStyle;
8827
- if (textDecorationLine) htmlEl.style.textDecorationLine = textDecorationLine;
8436
+ if (textAlign) el.style.textAlign = textAlign;
8828
8437
  walk(el);
8829
8438
  }
8830
8439
  }
@@ -8871,7 +8480,7 @@ function EditGlowChrome({
8871
8480
  hideHandle = false
8872
8481
  }) {
8873
8482
  const GAP = SELECTION_CHROME_GAP2;
8874
- return /* @__PURE__ */ jsxs14(
8483
+ return /* @__PURE__ */ jsxs13(
8875
8484
  "div",
8876
8485
  {
8877
8486
  ref: elRef,
@@ -8886,7 +8495,7 @@ function EditGlowChrome({
8886
8495
  zIndex: 2147483646
8887
8496
  },
8888
8497
  children: [
8889
- /* @__PURE__ */ jsx25(
8498
+ /* @__PURE__ */ jsx24(
8890
8499
  "div",
8891
8500
  {
8892
8501
  style: {
@@ -8899,7 +8508,7 @@ function EditGlowChrome({
8899
8508
  }
8900
8509
  }
8901
8510
  ),
8902
- reorderHrefKey && !hideHandle && /* @__PURE__ */ jsx25(
8511
+ reorderHrefKey && !hideHandle && /* @__PURE__ */ jsx24(
8903
8512
  "div",
8904
8513
  {
8905
8514
  "data-ohw-drag-handle-container": "",
@@ -8911,7 +8520,7 @@ function EditGlowChrome({
8911
8520
  transform: "translate(calc(-100% - 7px), -50%)",
8912
8521
  pointerEvents: dragDisabled ? "none" : "auto"
8913
8522
  },
8914
- children: /* @__PURE__ */ jsx25(
8523
+ children: /* @__PURE__ */ jsx24(
8915
8524
  DragHandle,
8916
8525
  {
8917
8526
  "aria-label": `Reorder ${reorderHrefKey}`,
@@ -9012,79 +8621,6 @@ function resolveItemInteractionState(rect, parentScroll) {
9012
8621
  const { transform } = calcToolbarPos(rect, parentScroll, 120);
9013
8622
  return transform.includes("translateY(-100%)") ? "active-top" : "active-bottom";
9014
8623
  }
9015
- function resolveSelectionStartElement(sel) {
9016
- if (!sel || sel.rangeCount === 0) return null;
9017
- const range = sel.getRangeAt(0);
9018
- let startNode = range.startContainer;
9019
- if (startNode.nodeType === Node.ELEMENT_NODE) {
9020
- const el = startNode;
9021
- startNode = el.childNodes[range.startOffset] ?? el.childNodes[range.startOffset - 1] ?? el;
9022
- }
9023
- return startNode.nodeType === Node.TEXT_NODE ? startNode.parentElement : startNode;
9024
- }
9025
- function detectActiveFormats(startEl, activeRoot) {
9026
- const formats = /* @__PURE__ */ new Set();
9027
- const cs = getComputedStyle(startEl);
9028
- const weight = parseInt(cs.fontWeight, 10);
9029
- let hasBold = cs.fontWeight === "bold" || !Number.isNaN(weight) && weight >= 600;
9030
- let hasItalic = cs.fontStyle === "italic" || cs.fontStyle === "oblique";
9031
- let hasUnderline = false;
9032
- let hasStrike = false;
9033
- let hasUl = false;
9034
- let hasOl = false;
9035
- for (let el = startEl; el; el = el.parentElement) {
9036
- if (el.tagName === "B" || el.tagName === "STRONG") hasBold = true;
9037
- if (el.tagName === "I" || el.tagName === "EM") hasItalic = true;
9038
- const decoration = getComputedStyle(el).textDecorationLine;
9039
- if (decoration.includes("underline") || el.tagName === "U" || el.tagName === "INS") hasUnderline = true;
9040
- if (decoration.includes("line-through") || el.tagName === "S" || el.tagName === "STRIKE" || el.tagName === "DEL") hasStrike = true;
9041
- if (el.tagName === "UL") hasUl = true;
9042
- if (el.tagName === "OL") hasOl = true;
9043
- if (el === activeRoot) break;
9044
- }
9045
- if (hasBold) formats.add("bold");
9046
- if (hasItalic) formats.add("italic");
9047
- if (hasUnderline) formats.add("underline");
9048
- if (hasStrike) formats.add("strikeThrough");
9049
- if (hasUl) formats.add("insertUnorderedList");
9050
- if (hasOl) formats.add("insertOrderedList");
9051
- const block = startEl.closest("div, p, h1, h2, h3, h4, h5, h6, li, td, th") ?? startEl;
9052
- const align = getComputedStyle(block).textAlign;
9053
- if (align === "center") formats.add("justifyCenter");
9054
- else if (align === "right" || align === "end") formats.add("justifyRight");
9055
- else formats.add("justifyLeft");
9056
- return formats;
9057
- }
9058
- function setsEqual(a, b) {
9059
- if (a.size !== b.size) return false;
9060
- for (const item of a) {
9061
- if (!b.has(item)) return false;
9062
- }
9063
- return true;
9064
- }
9065
- function textOffsetInRoot(root, node, offset) {
9066
- const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
9067
- let total = 0;
9068
- let current;
9069
- while (current = walker.nextNode()) {
9070
- if (current === node) return total + offset;
9071
- total += (current.textContent ?? "").length;
9072
- }
9073
- return total;
9074
- }
9075
- function pointAtTextOffset(root, targetOffset) {
9076
- const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
9077
- let total = 0;
9078
- let current;
9079
- let last = null;
9080
- while (current = walker.nextNode()) {
9081
- const len = (current.textContent ?? "").length;
9082
- if (total + len >= targetOffset) return { node: current, offset: targetOffset - total };
9083
- total += len;
9084
- last = current;
9085
- }
9086
- return last ? { node: last, offset: (last.textContent ?? "").length } : null;
9087
- }
9088
8624
  function FloatingToolbar({
9089
8625
  rect,
9090
8626
  parentScroll,
@@ -9121,7 +8657,7 @@ function FloatingToolbar({
9121
8657
  return () => ro.disconnect();
9122
8658
  }, [showEditLink, activeCommands]);
9123
8659
  const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
9124
- return /* @__PURE__ */ jsx25(
8660
+ return /* @__PURE__ */ jsx24(
9125
8661
  "div",
9126
8662
  {
9127
8663
  ref: setRefs,
@@ -9133,12 +8669,12 @@ function FloatingToolbar({
9133
8669
  zIndex: 2147483647,
9134
8670
  pointerEvents: "auto"
9135
8671
  },
9136
- children: /* @__PURE__ */ jsxs14(CustomToolbar, { children: [
9137
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs14(React11.Fragment, { children: [
9138
- gi > 0 && /* @__PURE__ */ jsx25(CustomToolbarDivider, {}),
8672
+ children: /* @__PURE__ */ jsxs13(CustomToolbar, { children: [
8673
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs13(React11.Fragment, { children: [
8674
+ gi > 0 && /* @__PURE__ */ jsx24(CustomToolbarDivider, {}),
9139
8675
  btns.map((btn) => {
9140
8676
  const isActive = activeCommands.has(btn.cmd);
9141
- return /* @__PURE__ */ jsx25(
8677
+ return /* @__PURE__ */ jsx24(
9142
8678
  CustomToolbarButton,
9143
8679
  {
9144
8680
  title: btn.title,
@@ -9147,7 +8683,7 @@ function FloatingToolbar({
9147
8683
  e.preventDefault();
9148
8684
  onCommand(btn.cmd);
9149
8685
  },
9150
- children: /* @__PURE__ */ jsx25(
8686
+ children: /* @__PURE__ */ jsx24(
9151
8687
  "svg",
9152
8688
  {
9153
8689
  width: "16",
@@ -9168,7 +8704,7 @@ function FloatingToolbar({
9168
8704
  );
9169
8705
  })
9170
8706
  ] }, gi)),
9171
- showEditLink ? /* @__PURE__ */ jsx25(
8707
+ showEditLink ? /* @__PURE__ */ jsx24(
9172
8708
  CustomToolbarButton,
9173
8709
  {
9174
8710
  type: "button",
@@ -9182,7 +8718,7 @@ function FloatingToolbar({
9182
8718
  e.preventDefault();
9183
8719
  e.stopPropagation();
9184
8720
  },
9185
- children: /* @__PURE__ */ jsx25(Link2, { className: "size-4 shrink-0", "aria-hidden": true })
8721
+ children: /* @__PURE__ */ jsx24(Link2, { className: "size-4 shrink-0", "aria-hidden": true })
9186
8722
  }
9187
8723
  ) : null
9188
8724
  ] })
@@ -9199,7 +8735,7 @@ function StateToggle({
9199
8735
  states,
9200
8736
  onStateChange
9201
8737
  }) {
9202
- return /* @__PURE__ */ jsx25(
8738
+ return /* @__PURE__ */ jsx24(
9203
8739
  ToggleGroup,
9204
8740
  {
9205
8741
  "data-ohw-state-toggle": "",
@@ -9213,7 +8749,7 @@ function StateToggle({
9213
8749
  left: rect.right - 8,
9214
8750
  transform: "translateX(-100%)"
9215
8751
  },
9216
- children: states.map((state) => /* @__PURE__ */ jsx25(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
8752
+ children: states.map((state) => /* @__PURE__ */ jsx24(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
9217
8753
  }
9218
8754
  );
9219
8755
  }
@@ -9269,7 +8805,7 @@ function OhhwellsBridge() {
9269
8805
  const subdomainFromQuery = searchParams.get("subdomain");
9270
8806
  const subdomain = resolveSubdomain(subdomainFromQuery);
9271
8807
  useLinkHrefGuardian(pathname, subdomain, isEditMode);
9272
- const postToParent2 = useCallback5((data) => {
8808
+ const postToParent2 = useCallback4((data) => {
9273
8809
  if (typeof window !== "undefined" && window.parent !== window) {
9274
8810
  window.parent.postMessage(data, "*");
9275
8811
  }
@@ -9277,7 +8813,6 @@ function OhhwellsBridge() {
9277
8813
  const [fetchState, setFetchState] = useState7("idle");
9278
8814
  const autoSaveTimers = useRef7(/* @__PURE__ */ new Map());
9279
8815
  const activeElRef = useRef7(null);
9280
- const pointerHeldRef = useRef7(false);
9281
8816
  const selectedElRef = useRef7(null);
9282
8817
  const selectedHrefKeyRef = useRef7(null);
9283
8818
  const selectedFooterColAttrRef = useRef7(null);
@@ -9286,7 +8821,7 @@ function OhhwellsBridge() {
9286
8821
  const parentScrollRef = useRef7(null);
9287
8822
  const visibleViewportRef = useRef7(null);
9288
8823
  const [dialogPortalContainer, setDialogPortalContainer] = useState7(null);
9289
- const attachVisibleViewport = useCallback5((node) => {
8824
+ const attachVisibleViewport = useCallback4((node) => {
9290
8825
  visibleViewportRef.current = node;
9291
8826
  setDialogPortalContainer(node);
9292
8827
  if (node) applyVisibleViewport(node, parentScrollRef.current);
@@ -9399,7 +8934,7 @@ function OhhwellsBridge() {
9399
8934
  const bumpLinkPopoverGrace = () => {
9400
8935
  linkPopoverGraceUntilRef.current = Date.now() + 350;
9401
8936
  };
9402
- const runSectionsPrefetch = useCallback5((pages) => {
8937
+ const runSectionsPrefetch = useCallback4((pages) => {
9403
8938
  if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
9404
8939
  const gen = ++sectionsPrefetchGenRef.current;
9405
8940
  const paths = pages.map((p) => p.path);
@@ -9525,10 +9060,10 @@ function OhhwellsBridge() {
9525
9060
  vvp.removeEventListener("resize", update);
9526
9061
  };
9527
9062
  }, []);
9528
- const refreshStateRules = useCallback5(() => {
9063
+ const refreshStateRules = useCallback4(() => {
9529
9064
  editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
9530
9065
  }, []);
9531
- const processConfigRequest = useCallback5((insertAfterVal) => {
9066
+ const processConfigRequest = useCallback4((insertAfterVal) => {
9532
9067
  const tracker = getSectionsTracker();
9533
9068
  let entries = [];
9534
9069
  try {
@@ -9551,7 +9086,7 @@ function OhhwellsBridge() {
9551
9086
  }
9552
9087
  window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
9553
9088
  }, [isEditMode]);
9554
- const deactivate = useCallback5(() => {
9089
+ const deactivate = useCallback4(() => {
9555
9090
  const el = activeElRef.current;
9556
9091
  if (!el) return;
9557
9092
  const key = el.dataset.ohwKey;
@@ -9583,12 +9118,12 @@ function OhhwellsBridge() {
9583
9118
  setToolbarShowEditLink(false);
9584
9119
  postToParent2({ type: "ow:exit-edit" });
9585
9120
  }, [postToParent2]);
9586
- const clearSelectedAttr = useCallback5(() => {
9121
+ const clearSelectedAttr = useCallback4(() => {
9587
9122
  document.querySelectorAll("[data-ohw-selected]").forEach((el) => {
9588
9123
  el.removeAttribute("data-ohw-selected");
9589
9124
  });
9590
9125
  }, []);
9591
- const deselect = useCallback5(() => {
9126
+ const deselect = useCallback4(() => {
9592
9127
  clearSelectedAttr();
9593
9128
  selectedElRef.current = null;
9594
9129
  selectedHrefKeyRef.current = null;
@@ -9608,11 +9143,11 @@ function OhhwellsBridge() {
9608
9143
  setToolbarVariant("none");
9609
9144
  }
9610
9145
  }, [clearSelectedAttr]);
9611
- const markSelected = useCallback5((el) => {
9146
+ const markSelected = useCallback4((el) => {
9612
9147
  clearSelectedAttr();
9613
9148
  el.setAttribute("data-ohw-selected", "");
9614
9149
  }, [clearSelectedAttr]);
9615
- const resolveHrefKeyElement = useCallback5((hrefKey) => {
9150
+ const resolveHrefKeyElement = useCallback4((hrefKey) => {
9616
9151
  if (isFooterHrefKey(hrefKey)) {
9617
9152
  return document.querySelector(
9618
9153
  `footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
@@ -9627,7 +9162,7 @@ function OhhwellsBridge() {
9627
9162
  `[data-ohw-href-key="${CSS.escape(hrefKey)}"]`
9628
9163
  );
9629
9164
  }, []);
9630
- const resyncSelectedNavigationItem = useCallback5(() => {
9165
+ const resyncSelectedNavigationItem = useCallback4(() => {
9631
9166
  const hrefKey = selectedHrefKeyRef.current;
9632
9167
  if (hrefKey) {
9633
9168
  const link = resolveHrefKeyElement(hrefKey);
@@ -9655,7 +9190,7 @@ function OhhwellsBridge() {
9655
9190
  );
9656
9191
  }
9657
9192
  }, [resolveHrefKeyElement]);
9658
- const reselectNavigationItem = useCallback5((navAnchor) => {
9193
+ const reselectNavigationItem = useCallback4((navAnchor) => {
9659
9194
  selectedElRef.current = navAnchor;
9660
9195
  selectedHrefKeyRef.current = navAnchor.getAttribute("data-ohw-href-key");
9661
9196
  selectedFooterColAttrRef.current = null;
@@ -9670,7 +9205,7 @@ function OhhwellsBridge() {
9670
9205
  setToolbarShowEditLink(false);
9671
9206
  setActiveCommands(/* @__PURE__ */ new Set());
9672
9207
  }, [markSelected]);
9673
- const commitNavigationTextEdit = useCallback5((navAnchor) => {
9208
+ const commitNavigationTextEdit = useCallback4((navAnchor) => {
9674
9209
  const el = activeElRef.current;
9675
9210
  if (!el) return;
9676
9211
  const key = el.dataset.ohwKey;
@@ -9697,7 +9232,7 @@ function OhhwellsBridge() {
9697
9232
  postToParent2({ type: "ow:exit-edit" });
9698
9233
  reselectNavigationItem(navAnchor);
9699
9234
  }, [postToParent2, reselectNavigationItem]);
9700
- const handleAddTopLevelNavItem = useCallback5(() => {
9235
+ const handleAddTopLevelNavItem = useCallback4(() => {
9701
9236
  const items = listNavbarItems();
9702
9237
  addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
9703
9238
  deselectRef.current();
@@ -9709,19 +9244,7 @@ function OhhwellsBridge() {
9709
9244
  intent: "add-nav"
9710
9245
  });
9711
9246
  }, []);
9712
- const handleAddFooterColumn = useCallback5(() => {
9713
- deselectRef.current();
9714
- deactivateRef.current();
9715
- const result = addFooterColumnWithPersist({ postToParent: postToParent2 });
9716
- editContentRef.current = {
9717
- ...editContentRef.current,
9718
- ...buildFooterColumnEditContentPatch(result)
9719
- };
9720
- requestAnimationFrame(() => {
9721
- selectRef.current(result.firstLink);
9722
- });
9723
- }, [postToParent2]);
9724
- const clearFooterDragVisuals = useCallback5(() => {
9247
+ const clearFooterDragVisuals = useCallback4(() => {
9725
9248
  footerDragRef.current = null;
9726
9249
  setSiblingHintRects([]);
9727
9250
  setFooterDropSlots([]);
@@ -9730,7 +9253,7 @@ function OhhwellsBridge() {
9730
9253
  setIsItemDragging(false);
9731
9254
  unlockFooterDragInteraction();
9732
9255
  }, []);
9733
- const refreshFooterDragVisuals = useCallback5((session, activeSlot, clientX, clientY) => {
9256
+ const refreshFooterDragVisuals = useCallback4((session, activeSlot, clientX, clientY) => {
9734
9257
  const dragged = session.draggedEl;
9735
9258
  setDraggedItemRect(dragged.getBoundingClientRect());
9736
9259
  if (typeof clientX === "number" && typeof clientY === "number") {
@@ -9761,7 +9284,7 @@ function OhhwellsBridge() {
9761
9284
  });
9762
9285
  const beginFooterDragRef = useRef7(() => {
9763
9286
  });
9764
- const beginFooterDrag = useCallback5(
9287
+ const beginFooterDrag = useCallback4(
9765
9288
  (session) => {
9766
9289
  const rect = session.draggedEl.getBoundingClientRect();
9767
9290
  session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
@@ -9781,7 +9304,7 @@ function OhhwellsBridge() {
9781
9304
  [refreshFooterDragVisuals]
9782
9305
  );
9783
9306
  beginFooterDragRef.current = beginFooterDrag;
9784
- const commitFooterDrag = useCallback5(
9307
+ const commitFooterDrag = useCallback4(
9785
9308
  (clientX, clientY) => {
9786
9309
  const session = footerDragRef.current;
9787
9310
  if (!session) {
@@ -9885,7 +9408,7 @@ function OhhwellsBridge() {
9885
9408
  [clearFooterDragVisuals, resolveHrefKeyElement, resyncSelectedNavigationItem]
9886
9409
  );
9887
9410
  commitFooterDragRef.current = commitFooterDrag;
9888
- const startFooterLinkDrag = useCallback5(
9411
+ const startFooterLinkDrag = useCallback4(
9889
9412
  (anchor, clientX, clientY, wasSelected) => {
9890
9413
  const hrefKey = anchor.getAttribute("data-ohw-href-key");
9891
9414
  if (!hrefKey || !isFooterHrefKey(hrefKey)) return false;
@@ -9906,7 +9429,7 @@ function OhhwellsBridge() {
9906
9429
  },
9907
9430
  [beginFooterDrag]
9908
9431
  );
9909
- const startFooterColumnDrag = useCallback5(
9432
+ const startFooterColumnDrag = useCallback4(
9910
9433
  (columnEl, clientX, clientY, wasSelected) => {
9911
9434
  const columns = listFooterColumns();
9912
9435
  const idx = columns.indexOf(columnEl);
@@ -9926,7 +9449,7 @@ function OhhwellsBridge() {
9926
9449
  },
9927
9450
  [beginFooterDrag]
9928
9451
  );
9929
- const handleItemDragStart = useCallback5(
9452
+ const handleItemDragStart = useCallback4(
9930
9453
  (e) => {
9931
9454
  const selected = selectedElRef.current;
9932
9455
  if (!selected) {
@@ -9946,7 +9469,7 @@ function OhhwellsBridge() {
9946
9469
  },
9947
9470
  [startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag]
9948
9471
  );
9949
- const handleItemDragEnd = useCallback5(
9472
+ const handleItemDragEnd = useCallback4(
9950
9473
  (e) => {
9951
9474
  if (footerDragRef.current) {
9952
9475
  const x = e?.clientX;
@@ -9972,10 +9495,11 @@ function OhhwellsBridge() {
9972
9495
  },
9973
9496
  [commitFooterDrag, commitNavDrag, navDragRef]
9974
9497
  );
9975
- const handleItemChromePointerDown = useCallback5((e) => {
9498
+ const handleItemChromePointerDown = useCallback4((e) => {
9976
9499
  if (e.button !== 0) return;
9977
9500
  const selected = selectedElRef.current;
9978
9501
  if (!selected) return;
9502
+ armFooterPressDrag();
9979
9503
  const hrefKey = selected.getAttribute("data-ohw-href-key");
9980
9504
  if (hrefKey && isFooterHrefKey(hrefKey)) {
9981
9505
  footerPointerDragRef.current = {
@@ -10003,7 +9527,7 @@ function OhhwellsBridge() {
10003
9527
  }
10004
9528
  if (armNavPressFromChrome(selected, e.clientX, e.clientY, e.pointerId)) return;
10005
9529
  }, [armNavPressFromChrome]);
10006
- const handleItemChromeClick = useCallback5((clientX, clientY) => {
9530
+ const handleItemChromeClick = useCallback4((clientX, clientY) => {
10007
9531
  if (suppressNextClickRef.current || Date.now() < suppressClickUntilRef.current) {
10008
9532
  suppressNextClickRef.current = false;
10009
9533
  return;
@@ -10016,7 +9540,7 @@ function OhhwellsBridge() {
10016
9540
  }, []);
10017
9541
  reselectNavigationItemRef.current = reselectNavigationItem;
10018
9542
  commitNavigationTextEditRef.current = commitNavigationTextEdit;
10019
- const select = useCallback5((anchor) => {
9543
+ const select = useCallback4((anchor) => {
10020
9544
  if (!isNavigationItem(anchor)) return;
10021
9545
  if (activeElRef.current) deactivate();
10022
9546
  selectedElRef.current = anchor;
@@ -10042,10 +9566,10 @@ function OhhwellsBridge() {
10042
9566
  setToolbarShowEditLink(false);
10043
9567
  setActiveCommands(/* @__PURE__ */ new Set());
10044
9568
  }, [deactivate, markSelected]);
10045
- const selectFrame = useCallback5((el) => {
9569
+ const selectFrame = useCallback4((el) => {
10046
9570
  if (!isNavigationContainer(el)) return;
10047
9571
  if (activeElRef.current) deactivate();
10048
- const isFooterColumn = !isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || Boolean(el.closest("footer") && isInferredFooterGroup(el)));
9572
+ const isFooterColumn = el.hasAttribute("data-ohw-footer-col") || Boolean(el.closest("footer") && isInferredFooterGroup(el));
10049
9573
  selectedElRef.current = el;
10050
9574
  selectedHrefKeyRef.current = null;
10051
9575
  selectedFooterColAttrRef.current = isFooterColumn ? el.getAttribute("data-ohw-footer-col") ?? String(listFooterColumns().indexOf(el)) : null;
@@ -10070,7 +9594,7 @@ function OhhwellsBridge() {
10070
9594
  setToolbarShowEditLink(false);
10071
9595
  setActiveCommands(/* @__PURE__ */ new Set());
10072
9596
  }, [deactivate, markSelected]);
10073
- const activate = useCallback5((el, options) => {
9597
+ const activate = useCallback4((el, options) => {
10074
9598
  if (activeElRef.current === el) return;
10075
9599
  clearSelectedAttr();
10076
9600
  selectedElRef.current = null;
@@ -10087,8 +9611,6 @@ function OhhwellsBridge() {
10087
9611
  setSiblingHintRect(null);
10088
9612
  setSiblingHintRects([]);
10089
9613
  setIsItemDragging(false);
10090
- const preActivationSelection = window.getSelection();
10091
- const preservedRange = preActivationSelection && preActivationSelection.rangeCount > 0 && !preActivationSelection.isCollapsed && el.contains(preActivationSelection.getRangeAt(0).commonAncestorContainer) ? preActivationSelection.getRangeAt(0).cloneRange() : null;
10092
9614
  el.setAttribute("contenteditable", "true");
10093
9615
  el.setAttribute("data-ohw-editing", "");
10094
9616
  el.removeAttribute("data-ohw-hovered");
@@ -10096,11 +9618,7 @@ function OhhwellsBridge() {
10096
9618
  activeElRef.current = el;
10097
9619
  originalContentRef.current = el.innerHTML;
10098
9620
  el.focus({ preventScroll: true });
10099
- if (preservedRange) {
10100
- const selection = window.getSelection();
10101
- selection?.removeAllRanges();
10102
- selection?.addRange(preservedRange);
10103
- } else if (options?.caretX !== void 0 && options?.caretY !== void 0) {
9621
+ if (options?.caretX !== void 0 && options?.caretY !== void 0) {
10104
9622
  const { caretX, caretY } = options;
10105
9623
  placeCaretAtPoint(el, caretX, caretY);
10106
9624
  requestAnimationFrame(() => {
@@ -10556,9 +10074,7 @@ function OhhwellsBridge() {
10556
10074
  if (inActive || inActiveNav) {
10557
10075
  e.preventDefault();
10558
10076
  e.stopPropagation();
10559
- const selection = window.getSelection();
10560
- const hasRangeSelection = Boolean(selection && !selection.isCollapsed);
10561
- if (e.detail < 2 && !hasRangeSelection) {
10077
+ if (e.detail < 2) {
10562
10078
  placeCaretAtPoint(active, e.clientX, e.clientY);
10563
10079
  refreshActiveCommandsRef.current();
10564
10080
  }
@@ -10601,7 +10117,7 @@ function OhhwellsBridge() {
10601
10117
  }
10602
10118
  e.preventDefault();
10603
10119
  e.stopPropagation();
10604
- activateRef.current(editable, { caretX: e.clientX, caretY: e.clientY });
10120
+ activateRef.current(editable);
10605
10121
  return;
10606
10122
  }
10607
10123
  const hrefAnchor = getNavigationItemAnchor(target);
@@ -10628,18 +10144,6 @@ function OhhwellsBridge() {
10628
10144
  selectFrameRef.current(footerColClick);
10629
10145
  return;
10630
10146
  }
10631
- const footerLinksToSelect = resolveFooterLinksContainerSelectionTarget(
10632
- target,
10633
- e.clientX,
10634
- e.clientY,
10635
- isPointOverNavItem
10636
- );
10637
- if (footerLinksToSelect) {
10638
- e.preventDefault();
10639
- e.stopPropagation();
10640
- selectFrameRef.current(footerLinksToSelect);
10641
- return;
10642
- }
10643
10147
  const navContainerToSelect = resolveNavContainerSelectionTarget(target, e.clientX, e.clientY);
10644
10148
  if (navContainerToSelect) {
10645
10149
  e.preventDefault();
@@ -10698,8 +10202,8 @@ function OhhwellsBridge() {
10698
10202
  return;
10699
10203
  }
10700
10204
  const navLabel = getNavigationLabelEditable(target);
10701
- const editable = navLabel?.editable ?? target.closest('[data-ohw-editable="text"], [data-ohw-editable="plain"]');
10702
- if (!editable || isMediaEditable(editable) || editable.dataset.ohwEditable === "link") return;
10205
+ if (!navLabel) return;
10206
+ const { editable } = navLabel;
10703
10207
  e.preventDefault();
10704
10208
  e.stopPropagation();
10705
10209
  if (activeElRef.current !== editable) {
@@ -10720,38 +10224,16 @@ function OhhwellsBridge() {
10720
10224
  setHoveredNavContainerRect(null);
10721
10225
  return;
10722
10226
  }
10723
- {
10724
- const selected2 = selectedElRef.current;
10725
- const selectedIsFooterColumn = Boolean(selected2) && !isFooterLinksContainer(selected2) && (selected2.hasAttribute("data-ohw-footer-col") || selected2.hasAttribute("data-ohw-footer-column") || Boolean(selected2.closest("footer") && isInferredFooterGroup(selected2)));
10726
- const allowNavContainerHover = toolbarVariantRef.current !== "select-frame";
10727
- const allowFooterLinksHover = toolbarVariantRef.current !== "select-frame" || selectedIsFooterColumn;
10728
- if (allowNavContainerHover) {
10729
- const navContainer = target.closest("[data-ohw-nav-container]");
10730
- if (navContainer && !getNavigationItemAnchor(target)) {
10731
- hoveredNavContainerRef.current = navContainer;
10732
- setHoveredNavContainerRect(navContainer.getBoundingClientRect());
10733
- hoveredItemElRef.current = null;
10734
- setHoveredItemRect(null);
10735
- return;
10736
- }
10227
+ if (toolbarVariantRef.current !== "select-frame") {
10228
+ const navContainer = target.closest("[data-ohw-nav-container]");
10229
+ if (navContainer && !getNavigationItemAnchor(target)) {
10230
+ hoveredNavContainerRef.current = navContainer;
10231
+ setHoveredNavContainerRect(navContainer.getBoundingClientRect());
10232
+ hoveredItemElRef.current = null;
10233
+ setHoveredItemRect(null);
10234
+ return;
10737
10235
  }
10738
- if (allowFooterLinksHover) {
10739
- const navContainer = target.closest("[data-ohw-nav-container]");
10740
- if (!navContainer) {
10741
- const footerLinks = target.closest("[data-ohw-footer-links], .rb-footer-links") ?? null;
10742
- if (footerLinks && selected2 !== footerLinks && !getNavigationItemAnchor(target) && !target.closest("[data-ohw-footer-col], [data-ohw-footer-column]")) {
10743
- hoveredNavContainerRef.current = footerLinks;
10744
- setHoveredNavContainerRect(footerLinks.getBoundingClientRect());
10745
- hoveredItemElRef.current = null;
10746
- setHoveredItemRect(null);
10747
- return;
10748
- }
10749
- if (!footerLinks) {
10750
- hoveredNavContainerRef.current = null;
10751
- setHoveredNavContainerRect(null);
10752
- }
10753
- }
10754
- } else if (toolbarVariantRef.current === "select-frame") {
10236
+ if (!target.closest("[data-ohw-nav-container]")) {
10755
10237
  hoveredNavContainerRef.current = null;
10756
10238
  setHoveredNavContainerRect(null);
10757
10239
  }
@@ -10793,9 +10275,9 @@ function OhhwellsBridge() {
10793
10275
  };
10794
10276
  const handleMouseOut = (e) => {
10795
10277
  const target = e.target;
10796
- if (target.closest("[data-ohw-nav-container], [data-ohw-footer-col], [data-ohw-footer-column], [data-ohw-footer-links], .rb-footer-links")) {
10278
+ if (target.closest("[data-ohw-nav-container], [data-ohw-footer-col], [data-ohw-footer-column]")) {
10797
10279
  const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
10798
- 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]")) {
10280
+ if (related2?.closest("[data-ohw-nav-container], [data-ohw-footer-col], [data-ohw-footer-column], [data-ohw-navbar-container-chrome], [data-ohw-navbar-add-button]")) {
10799
10281
  return;
10800
10282
  }
10801
10283
  hoveredNavContainerRef.current = null;
@@ -10890,15 +10372,6 @@ function OhhwellsBridge() {
10890
10372
  if (track) track.setAttribute("data-ohw-hover-paused", "");
10891
10373
  };
10892
10374
  const clearImageHover = () => setMediaHover(null);
10893
- const dismissImageHover = () => {
10894
- if (hoveredImageRef.current) {
10895
- hoveredImageRef.current = null;
10896
- hoveredImageHasTextOverlapRef.current = false;
10897
- resumeAnimTracks();
10898
- postToParentRef.current({ type: "ow:image-unhover" });
10899
- }
10900
- clearImageHover();
10901
- };
10902
10375
  const findImageAtPoint = (clientX, clientY, fromParentViewport) => {
10903
10376
  const { x, y } = toProbeCoords(clientX, clientY, fromParentViewport);
10904
10377
  const images = Array.from(document.querySelectorAll(MEDIA_SELECTOR));
@@ -10942,13 +10415,16 @@ function OhhwellsBridge() {
10942
10415
  }
10943
10416
  return smallest;
10944
10417
  };
10418
+ const dismissImageHover = () => {
10419
+ if (hoveredImageRef.current) {
10420
+ hoveredImageRef.current = null;
10421
+ hoveredImageHasTextOverlapRef.current = false;
10422
+ resumeAnimTracks();
10423
+ postToParentRef.current({ type: "ow:image-unhover" });
10424
+ }
10425
+ };
10945
10426
  const probeNavigationHoverAt = (x, y) => {
10946
- const selected = selectedElRef.current;
10947
- const selectedIsFooterColumn = Boolean(selected) && !isFooterLinksContainer(selected) && (selected.hasAttribute("data-ohw-footer-col") || selected.hasAttribute("data-ohw-footer-column") || Boolean(selected.closest("footer") && isInferredFooterGroup(selected)));
10948
- const selectedIsFooterLinks = Boolean(selected && isFooterLinksContainer(selected));
10949
- const allowNavContainerHover = toolbarVariantRef.current !== "select-frame";
10950
- const allowFooterLinksHover = (toolbarVariantRef.current !== "select-frame" || selectedIsFooterColumn) && !selectedIsFooterLinks;
10951
- if (toolbarVariantRef.current === "select-frame" && !allowFooterLinksHover) {
10427
+ if (toolbarVariantRef.current === "select-frame") {
10952
10428
  hoveredNavContainerRef.current = null;
10953
10429
  setHoveredNavContainerRect(null);
10954
10430
  }
@@ -10970,6 +10446,7 @@ function OhhwellsBridge() {
10970
10446
  if (navItemHit) {
10971
10447
  hoveredNavContainerRef.current = null;
10972
10448
  setHoveredNavContainerRect(null);
10449
+ const selected = selectedElRef.current;
10973
10450
  if (selected !== navItemHit) {
10974
10451
  clearHrefKeyHover(navItemHit);
10975
10452
  hoveredItemElRef.current = navItemHit;
@@ -10981,7 +10458,7 @@ function OhhwellsBridge() {
10981
10458
  return;
10982
10459
  }
10983
10460
  }
10984
- if (allowNavContainerHover) {
10461
+ if (toolbarVariantRef.current !== "select-frame") {
10985
10462
  for (const container of navContainers) {
10986
10463
  const containerRect = container.getBoundingClientRect();
10987
10464
  const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
@@ -10993,23 +10470,12 @@ function OhhwellsBridge() {
10993
10470
  setHoveredItemRect(null);
10994
10471
  return;
10995
10472
  }
10473
+ hoveredNavContainerRef.current = null;
10474
+ setHoveredNavContainerRect(null);
10475
+ } else {
10476
+ hoveredNavContainerRef.current = null;
10477
+ setHoveredNavContainerRect(null);
10996
10478
  }
10997
- if (allowFooterLinksHover) {
10998
- const footerLinks = getFooterLinksContainer();
10999
- if (footerLinks) {
11000
- const containerRect = footerLinks.getBoundingClientRect();
11001
- const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
11002
- if (overContainer && !isPointOverNavItem(footerLinks, x, y) && !isPointOverFooterColumn(x, y)) {
11003
- hoveredNavContainerRef.current = footerLinks;
11004
- setHoveredNavContainerRect(footerLinks.getBoundingClientRect());
11005
- hoveredItemElRef.current = null;
11006
- setHoveredItemRect(null);
11007
- return;
11008
- }
11009
- }
11010
- }
11011
- hoveredNavContainerRef.current = null;
11012
- setHoveredNavContainerRect(null);
11013
10479
  for (const column of footerColumns) {
11014
10480
  const containerRect = column.getBoundingClientRect();
11015
10481
  const overContainer = x >= containerRect.left && x <= containerRect.right && y >= containerRect.top && y <= containerRect.bottom;
@@ -11516,7 +10982,6 @@ function OhhwellsBridge() {
11516
10982
  }
11517
10983
  editContentRef.current = { ...editContentRef.current, ...content };
11518
10984
  reconcileNavbarItemsFromContent(editContentRef.current);
11519
- reconcileFooterOrderFromContent(editContentRef.current);
11520
10985
  syncNavigationDragCursorAttrs();
11521
10986
  enforceLinkHrefs();
11522
10987
  postToParentRef.current({ type: "ow:hydrate-done" });
@@ -11571,11 +11036,6 @@ function OhhwellsBridge() {
11571
11036
  }
11572
11037
  if (selectedElRef.current) {
11573
11038
  if (toolbarVariantRef.current === "select-frame") {
11574
- const parent2 = getNavigationSelectionParent(selectedElRef.current);
11575
- if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
11576
- selectFrameRef.current(parent2);
11577
- return;
11578
- }
11579
11039
  deselectRef.current();
11580
11040
  return;
11581
11041
  }
@@ -11591,10 +11051,13 @@ function OhhwellsBridge() {
11591
11051
  const handleKeyDown = (e) => {
11592
11052
  if (e.key === "Escape" && document.querySelector("[data-ohw-section-picker]")) return;
11593
11053
  if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "a" && activeElRef.current) {
11594
- e.preventDefault();
11595
- selectAllTextInEditable(activeElRef.current);
11596
- refreshActiveCommandsRef.current();
11597
- return;
11054
+ const navAnchor = getNavigationItemAnchor(activeElRef.current);
11055
+ if (navAnchor) {
11056
+ e.preventDefault();
11057
+ selectAllTextInEditable(activeElRef.current);
11058
+ refreshActiveCommandsRef.current();
11059
+ return;
11060
+ }
11598
11061
  }
11599
11062
  if (e.key === "Escape" && linkPopoverOpenRef.current) {
11600
11063
  setLinkPopoverRef.current(null);
@@ -11602,12 +11065,6 @@ function OhhwellsBridge() {
11602
11065
  }
11603
11066
  if (e.key === "Escape" && selectedElRef.current && !activeElRef.current) {
11604
11067
  if (toolbarVariantRef.current === "select-frame") {
11605
- const parent2 = getNavigationSelectionParent(selectedElRef.current);
11606
- if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
11607
- e.preventDefault();
11608
- selectFrameRef.current(parent2);
11609
- return;
11610
- }
11611
11068
  deselectRef.current();
11612
11069
  return;
11613
11070
  }
@@ -11770,30 +11227,30 @@ function OhhwellsBridge() {
11770
11227
  const h = document.documentElement.scrollHeight;
11771
11228
  if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
11772
11229
  };
11773
- let selectionChangeRaf = null;
11774
- const runSelectionChange = () => {
11775
- selectionChangeRaf = null;
11776
- const activeRoot = activeElRef.current;
11777
- if (!activeRoot) return;
11778
- const startEl = resolveSelectionStartElement(window.getSelection());
11779
- const next = startEl ? detectActiveFormats(startEl, activeRoot) : /* @__PURE__ */ new Set();
11780
- setActiveCommands((prev) => setsEqual(prev, next) ? prev : next);
11781
- };
11782
11230
  const handleSelectionChange = () => {
11783
- if (pointerHeldRef.current) return;
11784
- if (selectionChangeRaf !== null) return;
11785
- selectionChangeRaf = requestAnimationFrame(runSelectionChange);
11786
- };
11787
- const markPointerHeld = (e) => {
11788
- if (e.button !== 0) return;
11789
- pointerHeldRef.current = true;
11790
- };
11791
- const markPointerReleased = () => {
11792
- if (!pointerHeldRef.current) return;
11793
- pointerHeldRef.current = false;
11794
- handleSelectionChange();
11231
+ if (!activeElRef.current) return;
11232
+ const next = /* @__PURE__ */ new Set();
11233
+ for (const cmd of ["bold", "italic", "underline", "strikeThrough", "insertUnorderedList", "insertOrderedList"]) {
11234
+ try {
11235
+ if (document.queryCommandState(cmd)) next.add(cmd);
11236
+ } catch {
11237
+ }
11238
+ }
11239
+ const sel = window.getSelection();
11240
+ const anchor = sel?.anchorNode;
11241
+ if (anchor) {
11242
+ const el = anchor.nodeType === Node.TEXT_NODE ? anchor.parentElement : anchor;
11243
+ const block = el?.closest("div, p, h1, h2, h3, h4, h5, h6, li, td, th") ?? el;
11244
+ if (block) {
11245
+ const align = getComputedStyle(block).textAlign;
11246
+ if (align === "center") next.add("justifyCenter");
11247
+ else if (align === "right" || align === "end") next.add("justifyRight");
11248
+ else next.add("justifyLeft");
11249
+ }
11250
+ }
11251
+ setActiveCommands(next);
11795
11252
  };
11796
- refreshActiveCommandsRef.current = runSelectionChange;
11253
+ refreshActiveCommandsRef.current = handleSelectionChange;
11797
11254
  const handleDocMouseLeave = () => {
11798
11255
  hoveredImageRef.current = null;
11799
11256
  setMediaHover(null);
@@ -12033,6 +11490,7 @@ function OhhwellsBridge() {
12033
11490
  const anchor = getNavigationItemAnchor(target);
12034
11491
  const hrefKey = anchor?.getAttribute("data-ohw-href-key") ?? null;
12035
11492
  if (anchor && isFooterHrefKey(hrefKey)) {
11493
+ armFooterPressDrag();
12036
11494
  footerPointerDragRef.current = {
12037
11495
  el: anchor,
12038
11496
  kind: "link",
@@ -12046,6 +11504,7 @@ function OhhwellsBridge() {
12046
11504
  }
12047
11505
  const col = target.closest("[data-ohw-footer-col]");
12048
11506
  if (col && !getNavigationItemAnchor(target)) {
11507
+ armFooterPressDrag();
12049
11508
  footerPointerDragRef.current = {
12050
11509
  el: col,
12051
11510
  kind: "column",
@@ -12074,7 +11533,6 @@ function OhhwellsBridge() {
12074
11533
  if (dx * dx + dy * dy < THRESHOLD * THRESHOLD) return;
12075
11534
  e.preventDefault();
12076
11535
  pending.started = true;
12077
- armFooterPressDrag();
12078
11536
  clearTextSelection();
12079
11537
  try {
12080
11538
  document.body.setPointerCapture(pending.pointerId);
@@ -12128,8 +11586,7 @@ function OhhwellsBridge() {
12128
11586
  }
12129
11587
  } catch {
12130
11588
  }
12131
- if (!pending) return;
12132
- if (!pending.started) {
11589
+ if (!pending?.started) {
12133
11590
  unlockFooterDragInteraction();
12134
11591
  return;
12135
11592
  }
@@ -12221,43 +11678,13 @@ function OhhwellsBridge() {
12221
11678
  window.addEventListener("hashchange", onHashChange);
12222
11679
  return () => window.removeEventListener("hashchange", onHashChange);
12223
11680
  }, [pathname]);
12224
- const handleCommand = useCallback5((cmd) => {
12225
- const el = activeElRef.current;
12226
- const selBefore = window.getSelection();
12227
- let savedOffsets = null;
12228
- if (el && selBefore && selBefore.rangeCount > 0 && !selBefore.isCollapsed) {
12229
- const r2 = selBefore.getRangeAt(0);
12230
- if (el.contains(r2.commonAncestorContainer)) {
12231
- savedOffsets = {
12232
- start: textOffsetInRoot(el, r2.startContainer, r2.startOffset),
12233
- end: textOffsetInRoot(el, r2.endContainer, r2.endOffset)
12234
- };
12235
- }
12236
- }
12237
- document.execCommand("styleWithCSS", false, true);
11681
+ const handleCommand = useCallback4((cmd) => {
12238
11682
  document.execCommand(cmd, false);
12239
- if (el && document.activeElement !== el) {
12240
- el.focus();
12241
- }
12242
- const selAfter = window.getSelection();
12243
- if (el && savedOffsets && selAfter?.isCollapsed) {
12244
- const start = pointAtTextOffset(el, savedOffsets.start);
12245
- const end = pointAtTextOffset(el, savedOffsets.end);
12246
- if (start && end) {
12247
- try {
12248
- const range = document.createRange();
12249
- range.setStart(start.node, start.offset);
12250
- range.setEnd(end.node, end.offset);
12251
- selAfter.removeAllRanges();
12252
- selAfter.addRange(range);
12253
- } catch {
12254
- }
12255
- }
12256
- }
12257
- if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
11683
+ activeElRef.current?.focus();
11684
+ if (activeElRef.current) setToolbarRect(getEditMeasureEl(activeElRef.current).getBoundingClientRect());
12258
11685
  refreshActiveCommandsRef.current();
12259
11686
  }, []);
12260
- const handleStateChange = useCallback5((state) => {
11687
+ const handleStateChange = useCallback4((state) => {
12261
11688
  if (!activeStateElRef.current) return;
12262
11689
  const el = activeStateElRef.current;
12263
11690
  if (state === "Default") {
@@ -12270,11 +11697,11 @@ function OhhwellsBridge() {
12270
11697
  }
12271
11698
  setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
12272
11699
  }, [deactivate]);
12273
- const closeLinkPopover = useCallback5(() => {
11700
+ const closeLinkPopover = useCallback4(() => {
12274
11701
  addNavAfterAnchorRef.current = null;
12275
11702
  setLinkPopover(null);
12276
11703
  }, []);
12277
- const openLinkPopoverForActive = useCallback5(() => {
11704
+ const openLinkPopoverForActive = useCallback4(() => {
12278
11705
  const hrefCtx = getHrefKeyFromElement(activeElRef.current);
12279
11706
  if (!hrefCtx) return;
12280
11707
  bumpLinkPopoverGrace();
@@ -12285,7 +11712,7 @@ function OhhwellsBridge() {
12285
11712
  });
12286
11713
  deactivate();
12287
11714
  }, [deactivate]);
12288
- const openLinkPopoverForSelected = useCallback5(() => {
11715
+ const openLinkPopoverForSelected = useCallback4(() => {
12289
11716
  const anchor = selectedElRef.current;
12290
11717
  if (!anchor) return;
12291
11718
  const key = anchor.getAttribute("data-ohw-href-key");
@@ -12298,7 +11725,7 @@ function OhhwellsBridge() {
12298
11725
  });
12299
11726
  deselect();
12300
11727
  }, [deselect]);
12301
- const handleLinkPopoverSubmit = useCallback5(
11728
+ const handleLinkPopoverSubmit = useCallback4(
12302
11729
  (target) => {
12303
11730
  const session = linkPopoverSessionRef.current;
12304
11731
  if (!session) return;
@@ -12357,13 +11784,13 @@ function OhhwellsBridge() {
12357
11784
  const showEditLink = toolbarShowEditLink;
12358
11785
  const currentSections = sectionsByPath[pathname] ?? [];
12359
11786
  linkPopoverOpenRef.current = linkPopover !== null;
12360
- const handleMediaReplace = useCallback5(
11787
+ const handleMediaReplace = useCallback4(
12361
11788
  (key) => {
12362
11789
  postToParent2({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
12363
11790
  },
12364
11791
  [postToParent2, mediaHover?.elementType]
12365
11792
  );
12366
- const handleMediaFadeOutComplete = useCallback5((key) => {
11793
+ const handleMediaFadeOutComplete = useCallback4((key) => {
12367
11794
  setUploadingRects((prev) => {
12368
11795
  if (!(key in prev)) return prev;
12369
11796
  const next = { ...prev };
@@ -12371,7 +11798,7 @@ function OhhwellsBridge() {
12371
11798
  return next;
12372
11799
  });
12373
11800
  }, []);
12374
- const handleVideoSettingsChange = useCallback5(
11801
+ const handleVideoSettingsChange = useCallback4(
12375
11802
  (key, settings) => {
12376
11803
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
12377
11804
  const video = getVideoEl(el);
@@ -12394,9 +11821,9 @@ function OhhwellsBridge() {
12394
11821
  [postToParent2]
12395
11822
  );
12396
11823
  return bridgeRoot ? createPortal2(
12397
- /* @__PURE__ */ jsxs14(Fragment5, { children: [
12398
- /* @__PURE__ */ jsx25("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
12399
- Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ jsx25(
11824
+ /* @__PURE__ */ jsxs13(Fragment5, { children: [
11825
+ /* @__PURE__ */ jsx24("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
11826
+ Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ jsx24(
12400
11827
  MediaOverlay,
12401
11828
  {
12402
11829
  hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
@@ -12407,7 +11834,7 @@ function OhhwellsBridge() {
12407
11834
  },
12408
11835
  `uploading-${key}`
12409
11836
  )),
12410
- mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ jsx25(
11837
+ mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ jsx24(
12411
11838
  MediaOverlay,
12412
11839
  {
12413
11840
  hover: mediaHover,
@@ -12416,10 +11843,10 @@ function OhhwellsBridge() {
12416
11843
  onVideoSettingsChange: handleVideoSettingsChange
12417
11844
  }
12418
11845
  ),
12419
- siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
12420
- siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
12421
- isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
12422
- isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ jsx25(
11846
+ siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx24(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
11847
+ siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx24(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
11848
+ isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ jsx24(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
11849
+ isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ jsx24(
12423
11850
  "div",
12424
11851
  {
12425
11852
  className: "pointer-events-none fixed z-2147483646",
@@ -12429,7 +11856,7 @@ function OhhwellsBridge() {
12429
11856
  width: slot.width,
12430
11857
  height: slot.height
12431
11858
  },
12432
- children: /* @__PURE__ */ jsx25(
11859
+ children: /* @__PURE__ */ jsx24(
12433
11860
  DropIndicator,
12434
11861
  {
12435
11862
  direction: slot.direction,
@@ -12440,7 +11867,7 @@ function OhhwellsBridge() {
12440
11867
  },
12441
11868
  `footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
12442
11869
  )),
12443
- isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx25(
11870
+ isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx24(
12444
11871
  "div",
12445
11872
  {
12446
11873
  className: "pointer-events-none fixed z-2147483646",
@@ -12450,7 +11877,7 @@ function OhhwellsBridge() {
12450
11877
  width: slot.width,
12451
11878
  height: slot.height
12452
11879
  },
12453
- children: /* @__PURE__ */ jsx25(
11880
+ children: /* @__PURE__ */ jsx24(
12454
11881
  DropIndicator,
12455
11882
  {
12456
11883
  direction: slot.direction,
@@ -12461,11 +11888,10 @@ function OhhwellsBridge() {
12461
11888
  },
12462
11889
  `nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
12463
11890
  )),
12464
- hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
12465
- hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
12466
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx25(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
12467
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx25(FooterContainerChrome, { rect: toolbarRect, onAdd: handleAddFooterColumn }),
12468
- toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ jsx25(
11891
+ hoveredNavContainerRect && toolbarVariant !== "select-frame" && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx24(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
11892
+ hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx24(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
11893
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx24(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
11894
+ toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ jsx24(
12469
11895
  ItemInteractionLayer,
12470
11896
  {
12471
11897
  rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
@@ -12479,7 +11905,7 @@ function OhhwellsBridge() {
12479
11905
  onItemPointerDown: handleItemChromePointerDown,
12480
11906
  onItemClick: handleItemChromeClick,
12481
11907
  itemDragSurface: !isFooterFrameSelection,
12482
- toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ jsx25(
11908
+ toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ jsx24(
12483
11909
  ItemActionToolbar,
12484
11910
  {
12485
11911
  onEditLink: openLinkPopoverForSelected,
@@ -12492,8 +11918,8 @@ function OhhwellsBridge() {
12492
11918
  ) : void 0
12493
11919
  }
12494
11920
  ),
12495
- toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ jsxs14(Fragment5, { children: [
12496
- /* @__PURE__ */ jsx25(
11921
+ toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ jsxs13(Fragment5, { children: [
11922
+ /* @__PURE__ */ jsx24(
12497
11923
  EditGlowChrome,
12498
11924
  {
12499
11925
  rect: toolbarRect,
@@ -12503,7 +11929,7 @@ function OhhwellsBridge() {
12503
11929
  hideHandle: isItemDragging
12504
11930
  }
12505
11931
  ),
12506
- /* @__PURE__ */ jsx25(
11932
+ /* @__PURE__ */ jsx24(
12507
11933
  FloatingToolbar,
12508
11934
  {
12509
11935
  rect: toolbarRect,
@@ -12516,7 +11942,7 @@ function OhhwellsBridge() {
12516
11942
  }
12517
11943
  )
12518
11944
  ] }),
12519
- maxBadge && /* @__PURE__ */ jsxs14(
11945
+ maxBadge && /* @__PURE__ */ jsxs13(
12520
11946
  "div",
12521
11947
  {
12522
11948
  "data-ohw-max-badge": "",
@@ -12542,7 +11968,7 @@ function OhhwellsBridge() {
12542
11968
  ]
12543
11969
  }
12544
11970
  ),
12545
- toggleState && !linkPopover && /* @__PURE__ */ jsx25(
11971
+ toggleState && !linkPopover && /* @__PURE__ */ jsx24(
12546
11972
  StateToggle,
12547
11973
  {
12548
11974
  rect: toggleState.rect,
@@ -12551,15 +11977,15 @@ function OhhwellsBridge() {
12551
11977
  onStateChange: handleStateChange
12552
11978
  }
12553
11979
  ),
12554
- sectionGap && !linkPopover && /* @__PURE__ */ jsxs14(
11980
+ sectionGap && !linkPopover && /* @__PURE__ */ jsxs13(
12555
11981
  "div",
12556
11982
  {
12557
11983
  "data-ohw-section-insert-line": "",
12558
11984
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
12559
11985
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
12560
11986
  children: [
12561
- /* @__PURE__ */ jsx25("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
12562
- /* @__PURE__ */ jsx25(
11987
+ /* @__PURE__ */ jsx24("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
11988
+ /* @__PURE__ */ jsx24(
12563
11989
  Badge,
12564
11990
  {
12565
11991
  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",
@@ -12576,11 +12002,11 @@ function OhhwellsBridge() {
12576
12002
  children: "Add Section"
12577
12003
  }
12578
12004
  ),
12579
- /* @__PURE__ */ jsx25("div", { className: "flex-1 bg-primary", style: { height: 3 } })
12005
+ /* @__PURE__ */ jsx24("div", { className: "flex-1 bg-primary", style: { height: 3 } })
12580
12006
  ]
12581
12007
  }
12582
12008
  ),
12583
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx25(
12009
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx24(
12584
12010
  LinkPopover,
12585
12011
  {
12586
12012
  panelRef: linkPopoverPanelRef,