@ohhwells/bridge 0.1.54-next.153 → 0.1.54

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 useCallback7, useEffect as useEffect12, useLayoutEffect as useLayoutEffect4, useRef as useRef9, useState as useState11 } from "react";
4
+ import React11, { useCallback as useCallback6, useEffect as useEffect11, useLayoutEffect as useLayoutEffect3, useRef as useRef8, useState as useState10 } from "react";
5
5
  import { createRoot as createRoot2 } from "react-dom/client";
6
6
  import { flushSync as flushSync2 } from "react-dom";
7
7
 
@@ -162,17 +162,13 @@ function MediaBox({
162
162
  const url = refValue ? ctx.resolveMedia(refValue) : null;
163
163
  const isIcon = /^(lucide|simple):/.test(refValue);
164
164
  const aspectRatio = aspect && /^\d+:\d+$/.test(aspect) ? aspect.replace(":", " / ") : void 0;
165
- const editAttrs = ctx.keyFor && editPath ? {
166
- "data-ohw-key": ctx.keyFor(editPath),
167
- "data-ohw-editable": isIcon ? "icon" : "image"
168
- } : {};
165
+ const editAttrs = ctx.keyFor && editPath && !isIcon ? { "data-ohw-key": ctx.keyFor(editPath), "data-ohw-editable": "image" } : {};
169
166
  if (isIcon) {
170
167
  const Icon = refValue.startsWith("lucide:") ? lucideByName(refValue.slice(7)) : null;
171
168
  return /* @__PURE__ */ jsx(
172
169
  "span",
173
170
  {
174
171
  "data-ai-icon": refValue,
175
- ...editAttrs,
176
172
  style: {
177
173
  display: "inline-flex",
178
174
  width: 48,
@@ -1957,7 +1953,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
1957
1953
  const autoId = useId();
1958
1954
  const insertAfter = insertAfterProp ?? autoId;
1959
1955
  const [schedule, setSchedule] = useState2(null);
1960
- const [loading, setLoading] = useState2(initialScheduleId !== null);
1956
+ const [loading, setLoading] = useState2(true);
1961
1957
  const [inEditor, setInEditor] = useState2(false);
1962
1958
  const [isHovered, setIsHovered] = useState2(false);
1963
1959
  const [modalState, setModalState] = useState2(null);
@@ -2131,10 +2127,8 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
2131
2127
  "*"
2132
2128
  );
2133
2129
  };
2130
+ if (!inEditor && !loading && !schedule) return null;
2134
2131
  const sectionId = `scheduling-${insertAfter}`;
2135
- if (!inEditor && !loading && !schedule) {
2136
- return /* @__PURE__ */ jsx4("section", { "data-ohw-section": sectionId, "data-ohw-scheduling-anchor": insertAfter, style: { display: "none" } });
2137
- }
2138
2132
  return /* @__PURE__ */ jsxs3(
2139
2133
  "section",
2140
2134
  {
@@ -9458,358 +9452,6 @@ function deleteNavbarItem(sourceAnchor) {
9458
9452
  };
9459
9453
  }
9460
9454
 
9461
- // src/lib/icon-markup.ts
9462
- var GLYPH_SELECTOR = "svg, img";
9463
- function referenceBox(slot) {
9464
- const row = slot.closest("[data-ohw-socials-row]") ?? slot.closest("a")?.parentElement ?? null;
9465
- const neighbour = row ? Array.from(row.querySelectorAll('[data-ohw-editable="icon"]')).find((el) => el !== slot) : null;
9466
- const source = (neighbour ?? slot).querySelector(GLYPH_SELECTOR);
9467
- const box = source?.getBoundingClientRect() ?? null;
9468
- return box?.width && box.height ? box : null;
9469
- }
9470
- function iconMarkupSizedFor(slot, markup) {
9471
- const box = referenceBox(slot);
9472
- if (!box) return markup;
9473
- const holder = document.createElement("div");
9474
- holder.innerHTML = markup;
9475
- const glyph = holder.querySelector(GLYPH_SELECTOR);
9476
- if (!glyph) return markup;
9477
- glyph.style.width = `${Math.round(box.width)}px`;
9478
- glyph.style.height = `${Math.round(box.height)}px`;
9479
- return holder.innerHTML;
9480
- }
9481
- function applyIconMarkup(slot, markup) {
9482
- if (!markup) return;
9483
- const coloured = iconMarkupInheritingColour(markup);
9484
- const sized = iconMarkupSizedFor(slot, coloured);
9485
- if (slot.innerHTML !== sized) slot.innerHTML = sized;
9486
- if (sized === coloured) {
9487
- requestAnimationFrame(() => {
9488
- if (!slot.isConnected) return;
9489
- const resized = iconMarkupSizedFor(slot, coloured);
9490
- if (resized !== coloured && slot.innerHTML !== resized) slot.innerHTML = resized;
9491
- });
9492
- }
9493
- }
9494
- function detectIconStyle(el) {
9495
- const row = el.closest("[data-ohw-socials-row]");
9496
- const glyphs = Array.from((row ?? el).querySelectorAll("svg"));
9497
- const outlined = glyphs.some((svg) => {
9498
- return Array.from(svg.querySelectorAll("*")).some((node) => {
9499
- return node.getAttribute("stroke") !== null && node.getAttribute("stroke") !== "none";
9500
- });
9501
- });
9502
- return outlined ? "outline" : "fill";
9503
- }
9504
- function iconMarkupInheritingColour(markup) {
9505
- const holder = document.createElement("div");
9506
- holder.innerHTML = markup;
9507
- holder.querySelectorAll("svg *").forEach((node) => {
9508
- if (node.getAttribute("fill") && node.getAttribute("fill") !== "none") {
9509
- node.setAttribute("fill", "currentColor");
9510
- }
9511
- if (node.getAttribute("stroke") && node.getAttribute("stroke") !== "none") {
9512
- node.setAttribute("stroke", "currentColor");
9513
- }
9514
- });
9515
- return holder.innerHTML;
9516
- }
9517
-
9518
- // src/lib/socials-items.ts
9519
- var ICON_SELECTOR = '[data-ohw-editable="icon"]';
9520
- var SOCIALS_ROW_ATTR = "data-ohw-socials-row";
9521
- var SOCIALS_ITEM_ATTR = "data-ohw-social-item";
9522
- function isSocialItem(el) {
9523
- if (!el) return false;
9524
- const anchor = el instanceof HTMLAnchorElement ? el : el.closest("a");
9525
- if (!anchor) return false;
9526
- return anchor.querySelectorAll(ICON_SELECTOR).length === 1;
9527
- }
9528
- function getSocialItem(el) {
9529
- const anchor = el.closest("a");
9530
- return isSocialItem(anchor) ? anchor : null;
9531
- }
9532
- function findSocialsRow(el) {
9533
- const item = getSocialItem(el);
9534
- if (!item) return null;
9535
- const row = item.parentElement;
9536
- if (!row) return null;
9537
- const anchors = Array.from(row.querySelectorAll("a"));
9538
- if (!anchors.length || !anchors.every((anchor) => isSocialItem(anchor))) return null;
9539
- return row;
9540
- }
9541
- function isSocialsRow(el) {
9542
- const anchors = Array.from(el.querySelectorAll("a"));
9543
- return anchors.length > 0 && anchors.every((anchor) => isSocialItem(anchor));
9544
- }
9545
- function listSocialItems(row) {
9546
- return Array.from(row.children).filter((child) => {
9547
- return child instanceof HTMLElement && isSocialItem(child);
9548
- });
9549
- }
9550
- function listSocialsRows(root = document) {
9551
- const rows = /* @__PURE__ */ new Set();
9552
- root.querySelectorAll(ICON_SELECTOR).forEach((icon) => {
9553
- const row = findSocialsRow(icon);
9554
- if (row) rows.add(row);
9555
- });
9556
- root.querySelectorAll(`[${SOCIALS_ROW_ATTR}]`).forEach((row) => rows.add(row));
9557
- return Array.from(rows);
9558
- }
9559
- var rowTemplates = /* @__PURE__ */ new Map();
9560
- function markSocialsRows(root = document) {
9561
- root.querySelectorAll(`[${SOCIALS_ITEM_ATTR}]`).forEach((item) => {
9562
- item.removeAttribute(SOCIALS_ITEM_ATTR);
9563
- });
9564
- listSocialsRows(root).forEach((row) => {
9565
- row.setAttribute(SOCIALS_ROW_ATTR, "");
9566
- const items = listSocialItems(row);
9567
- if (items[0]) rowTemplates.set(rowKeyOf(row), items[0].outerHTML);
9568
- items.forEach((item, index) => {
9569
- item.setAttribute(SOCIALS_ITEM_ATTR, String(index));
9570
- const iconKey = socialIconKey(item);
9571
- if (iconKey) ensureLabelSlot(item, iconKey);
9572
- });
9573
- });
9574
- }
9575
- var SOCIALS_LABEL_ATTR = "data-ohw-social-label";
9576
- function ensureLabelSlot(item, iconKey) {
9577
- if (item.querySelector(`[${SOCIALS_LABEL_ATTR}]`)) return;
9578
- const label = document.createElement("span");
9579
- label.setAttribute("data-ohw-key", `${iconKey}-label`);
9580
- label.setAttribute("data-ohw-editable", "text");
9581
- label.setAttribute(SOCIALS_LABEL_ATTR, "");
9582
- label.style.display = "none";
9583
- label.textContent = item.getAttribute("aria-label") ?? "";
9584
- item.appendChild(label);
9585
- }
9586
- function socialLabelKey(iconKey) {
9587
- return `${iconKey}-label`;
9588
- }
9589
- function applyStoredValues(item, content) {
9590
- const hrefKey = socialHrefKey(item);
9591
- const iconKey = socialIconKey(item);
9592
- if (hrefKey && content[hrefKey] !== void 0) item.setAttribute("href", content[hrefKey]);
9593
- if (iconKey) {
9594
- const glyph = item.querySelector(ICON_SELECTOR);
9595
- if (glyph && content[iconKey]) applyIconMarkup(glyph, content[iconKey]);
9596
- const label = item.querySelector(`[${SOCIALS_LABEL_ATTR}]`);
9597
- label?.setAttribute("data-ohw-key", socialLabelKey(iconKey));
9598
- const stored = content[socialLabelKey(iconKey)];
9599
- if (label && stored) label.textContent = stored;
9600
- }
9601
- }
9602
- function socialPlatformKey(iconKey) {
9603
- return `${iconKey}-platform`;
9604
- }
9605
- function socialHrefKey(item) {
9606
- return item.getAttribute("data-ohw-href-key");
9607
- }
9608
- function socialIconKey(item) {
9609
- return item.querySelector(ICON_SELECTOR)?.dataset.ohwKey ?? null;
9610
- }
9611
- var SOCIALS_ORDER_KEY = "__ohw_socials_order";
9612
- function fromMarkup(markup) {
9613
- const holder = document.createElement("div");
9614
- holder.innerHTML = markup;
9615
- return holder.firstElementChild instanceof HTMLElement ? holder.firstElementChild : null;
9616
- }
9617
- var rowKeys = /* @__PURE__ */ new WeakMap();
9618
- function rowKeyOf(row) {
9619
- const first = listSocialItems(row)[0];
9620
- const derived = first ? socialIconKey(first)?.replace(/-\d+$/, "") : null;
9621
- if (derived) rowKeys.set(row, derived);
9622
- return derived ?? rowKeys.get(row) ?? "social";
9623
- }
9624
- function getSocialsOrderFromDom(root = document) {
9625
- const order = {};
9626
- listSocialsRows(root).forEach((row) => {
9627
- order[rowKeyOf(row)] = listSocialItems(row).map((item) => socialHrefKey(item)).filter((key) => Boolean(key));
9628
- });
9629
- return order;
9630
- }
9631
- function hasStoredValue(content, hrefKey) {
9632
- const iconKey = hrefKey.replace(/-href$/, "");
9633
- return Boolean(content[hrefKey]) || Boolean(content[iconKey]);
9634
- }
9635
- function parseSocialsOrder(raw) {
9636
- if (!raw) return null;
9637
- try {
9638
- const parsed = JSON.parse(raw);
9639
- return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
9640
- } catch {
9641
- return null;
9642
- }
9643
- }
9644
- function nextSocialIndex(row, rowKey, content) {
9645
- const used = listSocialItems(row).map((item) => socialHrefKey(item)).concat(Object.keys(content)).map((key) => key?.match(new RegExp(`^${rowKey}-(\\d+)`))?.[1]).map((digits) => digits === void 0 ? -1 : Number(digits));
9646
- return Math.max(-1, ...used) + 1;
9647
- }
9648
- function insertSocialItem(row, after, content = {}) {
9649
- const rowKey = rowKeyOf(row);
9650
- const template = listSocialItems(row)[0];
9651
- const remembered = rowTemplates.get(rowKey);
9652
- if (!template && !remembered) return null;
9653
- const index = nextSocialIndex(row, rowKey, content);
9654
- const iconKey = `${rowKey}-${index}`;
9655
- const hrefKey = `${iconKey}-href`;
9656
- const item = template ? template.cloneNode(true) : fromMarkup(remembered);
9657
- if (!item) return null;
9658
- item.setAttribute("data-ohw-href-key", hrefKey);
9659
- item.setAttribute("href", "");
9660
- item.removeAttribute("aria-label");
9661
- item.querySelectorAll("[data-ohw-hovered], [data-ohw-selected]").forEach((el) => {
9662
- el.removeAttribute("data-ohw-hovered");
9663
- el.removeAttribute("data-ohw-selected");
9664
- });
9665
- const icon = item.querySelector(ICON_SELECTOR);
9666
- icon?.setAttribute("data-ohw-key", iconKey);
9667
- item.querySelector(`[${SOCIALS_LABEL_ATTR}]`)?.remove();
9668
- if (after && after.parentElement === row) after.insertAdjacentElement("afterend", item);
9669
- else row.appendChild(item);
9670
- markSocialsRows(row.ownerDocument);
9671
- return { item, hrefKey, iconKey, order: getSocialsOrderFromDom(row.ownerDocument) };
9672
- }
9673
- function duplicateSocialItem(item, content) {
9674
- const row = findSocialsRow(item);
9675
- const created = row ? insertSocialItem(row, item, content) : null;
9676
- if (!created) return null;
9677
- const sourceHref = socialHrefKey(item);
9678
- const sourceIcon = socialIconKey(item);
9679
- const link = created.item;
9680
- if (sourceHref) link.setAttribute("href", item.getAttribute("href") ?? "");
9681
- const glyph = item.querySelector(ICON_SELECTOR)?.innerHTML;
9682
- if (glyph) {
9683
- const slot = link.querySelector(ICON_SELECTOR);
9684
- if (slot) slot.innerHTML = glyph;
9685
- }
9686
- return {
9687
- ...created,
9688
- copiedFrom: { href: sourceHref, icon: sourceIcon }
9689
- };
9690
- }
9691
- function removeSocialItem(item, content) {
9692
- const row = findSocialsRow(item);
9693
- if (!row) return null;
9694
- const hrefKey = socialHrefKey(item);
9695
- const iconKey = socialIconKey(item);
9696
- const removedKeys = [hrefKey, iconKey].filter((key) => Boolean(key));
9697
- if (!removedKeys.length) return null;
9698
- const previousOrder = getSocialsOrderFromDom(row.ownerDocument);
9699
- const previousContent = Object.fromEntries(
9700
- removedKeys.filter((key) => key in content).map((key) => [key, content[key]])
9701
- );
9702
- const nextSibling = item.nextElementSibling;
9703
- item.remove();
9704
- markSocialsRows(row.ownerDocument);
9705
- return {
9706
- removedKeys,
9707
- previousContent,
9708
- order: getSocialsOrderFromDom(row.ownerDocument),
9709
- previousOrder,
9710
- undo: () => {
9711
- if (nextSibling) nextSibling.before(item);
9712
- else row.appendChild(item);
9713
- markSocialsRows(row.ownerDocument);
9714
- }
9715
- };
9716
- }
9717
- function applySocialsOrder(order, root = document) {
9718
- listSocialsRows(root).forEach((row) => {
9719
- const wanted = order[rowKeyOf(row)];
9720
- if (!wanted) return;
9721
- const byKey = new Map(listSocialItems(row).map((item) => [socialHrefKey(item), item]));
9722
- wanted.forEach((key) => {
9723
- const item = byKey.get(key);
9724
- if (item) row.appendChild(item);
9725
- });
9726
- });
9727
- markSocialsRows(root);
9728
- }
9729
- function reconcileSocialsFromContent(content, root = document) {
9730
- markSocialsRows(root);
9731
- const stored = parseSocialsOrder(content[SOCIALS_ORDER_KEY]);
9732
- if (!stored) return;
9733
- listSocialsRows(root).forEach((row) => {
9734
- const wanted = stored[rowKeyOf(row)];
9735
- if (!wanted) return;
9736
- if (!wanted.length) return;
9737
- wanted.forEach((key) => {
9738
- if (listSocialItems(row).some((item) => socialHrefKey(item) === key)) return;
9739
- if (!hasStoredValue(content, key)) return;
9740
- const created = insertSocialItem(row, null, content);
9741
- if (created) {
9742
- created.item.setAttribute("data-ohw-href-key", key);
9743
- created.item.querySelector(ICON_SELECTOR)?.setAttribute("data-ohw-key", key.replace(/-href$/, ""));
9744
- applyStoredValues(created.item, content);
9745
- }
9746
- });
9747
- const present = listSocialItems(row);
9748
- const surviving = present.filter((item) => {
9749
- const key = socialHrefKey(item);
9750
- return !key || wanted.includes(key);
9751
- });
9752
- if (surviving.length) {
9753
- present.forEach((item) => {
9754
- if (!surviving.includes(item)) item.remove();
9755
- });
9756
- }
9757
- });
9758
- applySocialsOrder(stored, root);
9759
- }
9760
- var DROP_BAR_THICKNESS = 3;
9761
- function buildSocialDropSlots(row) {
9762
- const items = listSocialItems(row);
9763
- if (!items.length) return [];
9764
- return items.concat(items[items.length - 1]).map((item, index) => {
9765
- const rect = item.getBoundingClientRect();
9766
- const left = (index === items.length ? rect.right : rect.left) - DROP_BAR_THICKNESS / 2;
9767
- return {
9768
- insertIndex: index,
9769
- columnIndex: -1,
9770
- left,
9771
- top: rect.top,
9772
- width: DROP_BAR_THICKNESS,
9773
- height: rect.height,
9774
- direction: "vertical"
9775
- };
9776
- });
9777
- }
9778
- function findSocialByHrefKey(hrefKey, root = document) {
9779
- const el = root.querySelector(`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`);
9780
- return el ? getSocialItem(el) : null;
9781
- }
9782
- function buildSocialDropSlotsForKey(hrefKey, root = document) {
9783
- const item = findSocialByHrefKey(hrefKey, root);
9784
- const row = item ? findSocialsRow(item) : null;
9785
- return row ? buildSocialDropSlots(row) : [];
9786
- }
9787
- function hitTestSocialDropSlot(clientX, clientY, draggedHrefKey, root = document) {
9788
- const distanceTo = (slot) => {
9789
- const dx = clientX - (slot.left + slot.width / 2);
9790
- const dy = clientY < slot.top ? slot.top - clientY : Math.max(0, clientY - (slot.top + slot.height));
9791
- return Math.hypot(dx, dy);
9792
- };
9793
- const slots = buildSocialDropSlotsForKey(draggedHrefKey, root);
9794
- return slots.reduce((best, slot) => {
9795
- return !best || distanceTo(slot) < distanceTo(best) ? slot : best;
9796
- }, null);
9797
- }
9798
- function planSocialMove(hrefKey, insertIndex, root = document) {
9799
- const item = findSocialByHrefKey(hrefKey, root);
9800
- const row = item ? findSocialsRow(item) : null;
9801
- if (!row) return null;
9802
- const order = getSocialsOrderFromDom(root);
9803
- const key = rowKeyOf(row);
9804
- const current = order[key];
9805
- if (!current) return null;
9806
- const from = current.indexOf(hrefKey);
9807
- if (from < 0) return null;
9808
- const next = current.filter((_, index) => index !== from);
9809
- next.splice(insertIndex > from ? insertIndex - 1 : insertIndex, 0, hrefKey);
9810
- return { ...order, [key]: next };
9811
- }
9812
-
9813
9455
  // src/lib/footer-items.ts
9814
9456
  var FOOTER_ORDER_KEY = "__ohw_footer_order";
9815
9457
  var MAX_FOOTER_COLUMNS = 18;
@@ -10654,329 +10296,6 @@ function deleteFooterColumn(column) {
10654
10296
  };
10655
10297
  }
10656
10298
 
10657
- // src/lib/logo-identity.ts
10658
- var LOGO_TEXT_KEYS = ["nav-logo-text", "footer-logo-text", "logo-text"];
10659
- var LOGO_IMAGE_KEYS = ["nav-logo-image", "footer-logo", "footer-logo-image"];
10660
- var LOGO_HREF_KEYS = ["nav-logo-href", "footer-logo-href", "logo-href"];
10661
- var LOGO_PLACEHOLDER_KEY = "logo-is-placeholder";
10662
- var LOGO_ALT_KEY = "logo-alt";
10663
- var LOGO_IMAGE_URL_KEY = "nav-logo-image";
10664
- var PLACEHOLDER_BUSINESS_NAME = "Business name";
10665
- function resolveLogoDisplayText(text) {
10666
- const trimmed = (text ?? "").trim();
10667
- return trimmed || PLACEHOLDER_BUSINESS_NAME;
10668
- }
10669
- function isFooterLogoRoot(root) {
10670
- return Boolean(root.closest("footer") || root.closest('[data-ohw-section="footer"]'));
10671
- }
10672
- function imageKeyForRoot(root) {
10673
- return isFooterLogoRoot(root) ? "footer-logo" : "nav-logo-image";
10674
- }
10675
- function textKeyForRoot(root) {
10676
- return isFooterLogoRoot(root) ? "footer-logo-text" : "nav-logo-text";
10677
- }
10678
- function ensureLogoHrefKey(root) {
10679
- if (!(root instanceof HTMLAnchorElement)) return;
10680
- if (root.hasAttribute("data-ohw-href-key")) return;
10681
- root.setAttribute("data-ohw-href-key", isFooterLogoRoot(root) ? "footer-logo-href" : "nav-logo-href");
10682
- }
10683
- function applyLogoIdentity(text, isPlaceholder) {
10684
- const display = resolveLogoDisplayText(text);
10685
- const placeholder = isPlaceholder || !text.trim() || display === PLACEHOLDER_BUSINESS_NAME;
10686
- for (const key of LOGO_TEXT_KEYS) {
10687
- document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
10688
- if (el.textContent !== display) el.textContent = display;
10689
- });
10690
- }
10691
- for (const key of LOGO_IMAGE_KEYS) {
10692
- document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
10693
- const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
10694
- if (img) img.alt = display;
10695
- });
10696
- }
10697
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((el) => {
10698
- if (placeholder) el.setAttribute("data-ohw-placeholder", "");
10699
- else el.removeAttribute("data-ohw-placeholder");
10700
- });
10701
- return display;
10702
- }
10703
- function applyLogoImage(url, alt) {
10704
- const displayAlt = resolveLogoDisplayText(alt);
10705
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
10706
- ensureLogoHrefKey(root);
10707
- const imageKey = imageKeyForRoot(root);
10708
- const textKey = textKeyForRoot(root);
10709
- let img = root.querySelector(`img[data-ohw-key="${imageKey}"]`) ?? (root.querySelector(`[data-ohw-key="${imageKey}"]`) instanceof HTMLImageElement ? root.querySelector(`[data-ohw-key="${imageKey}"]`) : null) ?? root.querySelector("img");
10710
- let textEl = root.querySelector(`[data-ohw-key="${textKey}"]`) ?? root.querySelector('[data-ohw-key="logo-text"]');
10711
- if (url) {
10712
- if (!img) {
10713
- img = document.createElement("img");
10714
- img.setAttribute("data-ohw-editable", "image");
10715
- img.setAttribute("data-ohw-key", imageKey);
10716
- img.alt = displayAlt;
10717
- img.style.height = "";
10718
- img.style.maxHeight = "none";
10719
- img.style.width = "auto";
10720
- img.style.display = "block";
10721
- img.style.objectFit = "contain";
10722
- root.insertBefore(img, root.firstChild);
10723
- } else {
10724
- img.setAttribute("data-ohw-editable", "image");
10725
- img.setAttribute("data-ohw-key", imageKey);
10726
- }
10727
- img.removeAttribute("srcset");
10728
- img.removeAttribute("sizes");
10729
- img.src = url;
10730
- img.alt = displayAlt;
10731
- img.style.display = "block";
10732
- if (textEl) textEl.style.display = "none";
10733
- root.removeAttribute("data-ohw-placeholder");
10734
- return;
10735
- }
10736
- if (img) {
10737
- img.removeAttribute("src");
10738
- img.removeAttribute("srcset");
10739
- img.removeAttribute("sizes");
10740
- img.alt = displayAlt;
10741
- img.style.display = "none";
10742
- }
10743
- if (!textEl) {
10744
- textEl = document.createElement("span");
10745
- textEl.setAttribute("data-ohw-editable", "plain");
10746
- textEl.setAttribute("data-ohw-key", textKey);
10747
- root.appendChild(textEl);
10748
- }
10749
- textEl.style.display = "";
10750
- if (textEl.textContent !== displayAlt) textEl.textContent = displayAlt;
10751
- if (!displayAlt.trim() || displayAlt === PLACEHOLDER_BUSINESS_NAME) {
10752
- root.setAttribute("data-ohw-placeholder", "");
10753
- } else {
10754
- root.removeAttribute("data-ohw-placeholder");
10755
- }
10756
- });
10757
- }
10758
- function applyLogoHref(href) {
10759
- const target = href.trim() || "/";
10760
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
10761
- ensureLogoHrefKey(root);
10762
- if (root instanceof HTMLAnchorElement) {
10763
- root.setAttribute("href", target);
10764
- }
10765
- });
10766
- for (const key of LOGO_HREF_KEYS) setStoredLinkHref(key, target);
10767
- }
10768
- function readLogoIdentityFromDom() {
10769
- let imageUrl = null;
10770
- for (const key of LOGO_IMAGE_KEYS) {
10771
- const el = document.querySelector(`[data-ohw-key="${key}"]`);
10772
- const img = el instanceof HTMLImageElement ? el : el?.querySelector("img");
10773
- const attrSrc = img?.getAttribute("src")?.trim() ?? "";
10774
- if (attrSrc && !attrSrc.startsWith("data:") && img && img.style.display !== "none") {
10775
- imageUrl = img.currentSrc || img.src;
10776
- break;
10777
- }
10778
- }
10779
- let text = PLACEHOLDER_BUSINESS_NAME;
10780
- let isPlaceholder = true;
10781
- for (const key of LOGO_TEXT_KEYS) {
10782
- const el = document.querySelector(`[data-ohw-key="${key}"]`);
10783
- if (el?.textContent?.trim()) {
10784
- text = el.textContent.trim();
10785
- const logoRoot2 = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
10786
- isPlaceholder = logoRoot2?.hasAttribute("data-ohw-placeholder") === true || text === PLACEHOLDER_BUSINESS_NAME;
10787
- break;
10788
- }
10789
- }
10790
- if (imageUrl) {
10791
- const logoImg = document.querySelector(
10792
- '[data-ohw-key="nav-logo-image"], [data-ohw-key="footer-logo"]'
10793
- );
10794
- const alt = logoImg?.alt?.trim() || text;
10795
- isPlaceholder = false;
10796
- const hrefEl = document.querySelector(
10797
- 'a[data-ohw-role="logo"], a[data-ohw-logo], [data-ohw-role="logo"]'
10798
- );
10799
- const href2 = (hrefEl instanceof HTMLAnchorElement ? hrefEl.getAttribute("href") : null) || hrefEl?.closest("a")?.getAttribute("href") || "/";
10800
- return { text, isPlaceholder, imageUrl, href: href2, alt };
10801
- }
10802
- const logoRoot = document.querySelector('[data-ohw-role="logo"], [data-ohw-logo]');
10803
- const href = (logoRoot instanceof HTMLAnchorElement ? logoRoot.getAttribute("href") : null) || logoRoot?.closest("a")?.getAttribute("href") || "/";
10804
- return { text, isPlaceholder, imageUrl: null, href, alt: text };
10805
- }
10806
- function applyLogoFromContent(content) {
10807
- const hasLogoIdentity = LOGO_PLACEHOLDER_KEY in content || LOGO_TEXT_KEYS.some((key) => key in content) || LOGO_IMAGE_KEYS.some((key) => key in content) || LOGO_ALT_KEY in content || LOGO_HREF_KEYS.some((key) => key in content);
10808
- if (!hasLogoIdentity) return false;
10809
- const logoText = content[LOGO_TEXT_KEYS[0]] ?? content[LOGO_TEXT_KEYS[1]] ?? readLogoIdentityFromDom().text;
10810
- const logoAlt = content[LOGO_ALT_KEY] ?? logoText;
10811
- const rawLogoImage = content[LOGO_IMAGE_URL_KEY] ?? content["footer-logo"] ?? content["footer-logo-image"] ?? null;
10812
- const logoImageUrl = typeof rawLogoImage === "string" && rawLogoImage.trim() ? rawLogoImage.trim() : null;
10813
- const imageExplicitlyCleared = LOGO_IMAGE_KEYS.some((key) => key in content) && !logoImageUrl;
10814
- const logoIsPlaceholder = LOGO_PLACEHOLDER_KEY in content ? content[LOGO_PLACEHOLDER_KEY] !== "false" : !logoImageUrl && (!logoText.trim() || logoText === PLACEHOLDER_BUSINESS_NAME);
10815
- if (logoImageUrl) {
10816
- applyLogoImage(logoImageUrl, logoAlt);
10817
- } else {
10818
- if (imageExplicitlyCleared) applyLogoImage(null, logoAlt);
10819
- applyLogoIdentity(logoText, logoIsPlaceholder);
10820
- }
10821
- const logoHref = content["nav-logo-href"] ?? content["footer-logo-href"] ?? content["logo-href"];
10822
- if (typeof logoHref === "string" && logoHref.trim()) {
10823
- applyLogoHref(logoHref);
10824
- }
10825
- return true;
10826
- }
10827
-
10828
- // src/lib/logo-size.ts
10829
- var LOGO_SIZE_DEFAULTS = {
10830
- navbar: 28,
10831
- footer: 32
10832
- };
10833
- var LOGO_SIZE_MIN = 16;
10834
- var LOGO_SIZE_MAX = 80;
10835
- var LOGO_SIZE_DESKTOP_KEYS = {
10836
- navbar: "nav-logo-size",
10837
- footer: "footer-logo-size"
10838
- };
10839
- var LOGO_SIZE_MOBILE_KEYS = {
10840
- navbar: "nav-logo-size-mobile",
10841
- footer: "footer-logo-size-mobile"
10842
- };
10843
- var LOGO_SIZE_KEYS = [
10844
- LOGO_SIZE_DESKTOP_KEYS.navbar,
10845
- LOGO_SIZE_DESKTOP_KEYS.footer,
10846
- LOGO_SIZE_MOBILE_KEYS.navbar,
10847
- LOGO_SIZE_MOBILE_KEYS.footer
10848
- ];
10849
- function isFooterLogoRoot2(root) {
10850
- return Boolean(root.closest("footer") || root.closest('[data-ohw-section="footer"]'));
10851
- }
10852
- function getLogoPlacement(root) {
10853
- return isFooterLogoRoot2(root) ? "footer" : "navbar";
10854
- }
10855
- function parseLogoSizePx(raw, fallback) {
10856
- if (raw == null || raw === "") return fallback;
10857
- const n = Number.parseFloat(raw);
10858
- if (!Number.isFinite(n)) return fallback;
10859
- return Math.min(LOGO_SIZE_MAX, Math.max(LOGO_SIZE_MIN, Math.round(n)));
10860
- }
10861
- function isMobileLogoSizeFollowing(content, placement) {
10862
- const raw = content[LOGO_SIZE_MOBILE_KEYS[placement]];
10863
- return raw == null || raw.trim() === "";
10864
- }
10865
- function resolveDesktopLogoSize(content, placement) {
10866
- return parseLogoSizePx(content[LOGO_SIZE_DESKTOP_KEYS[placement]], LOGO_SIZE_DEFAULTS[placement]);
10867
- }
10868
- function resolveMobileLogoSize(content, placement) {
10869
- if (isMobileLogoSizeFollowing(content, placement)) {
10870
- return resolveDesktopLogoSize(content, placement);
10871
- }
10872
- return parseLogoSizePx(
10873
- content[LOGO_SIZE_MOBILE_KEYS[placement]],
10874
- resolveDesktopLogoSize(content, placement)
10875
- );
10876
- }
10877
- function setRootSizeVars(root, desktopPx, mobilePx, following) {
10878
- root.style.setProperty("--ohw-logo-size", `${desktopPx}px`);
10879
- if (following) {
10880
- root.style.removeProperty("--ohw-logo-size-mobile");
10881
- } else {
10882
- root.style.setProperty("--ohw-logo-size-mobile", `${mobilePx}px`);
10883
- }
10884
- root.querySelectorAll("img").forEach((img) => {
10885
- img.style.height = "";
10886
- img.style.maxHeight = "none";
10887
- img.style.width = "auto";
10888
- img.style.objectFit = "contain";
10889
- });
10890
- }
10891
- function applyLogoSizes(content) {
10892
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
10893
- const placement = getLogoPlacement(root);
10894
- const desktop = resolveDesktopLogoSize(content, placement);
10895
- const following = isMobileLogoSizeFollowing(content, placement);
10896
- const mobile = following ? desktop : resolveMobileLogoSize(content, placement);
10897
- setRootSizeVars(root, desktop, mobile, following);
10898
- });
10899
- }
10900
- function applyLogoSizeToPlacement(placement, desktopPx, mobilePx, following) {
10901
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
10902
- if (getLogoPlacement(root) !== placement) return;
10903
- setRootSizeVars(root, desktopPx, mobilePx, following);
10904
- });
10905
- }
10906
- function logoHasUploadedImage(logoEl) {
10907
- if (logoEl.hasAttribute("data-ohw-placeholder")) return false;
10908
- const img = logoEl.querySelector('img[data-ohw-key="nav-logo-image"], img[data-ohw-key="footer-logo"], img[data-ohw-key="footer-logo-image"]') ?? logoEl.querySelector("img");
10909
- if (!img) return false;
10910
- const src = img.getAttribute("src")?.trim() ?? "";
10911
- if (!src || src.startsWith("data:")) return false;
10912
- if (img.style.display === "none") return false;
10913
- return true;
10914
- }
10915
- function getLogoInteractionRect(logoEl) {
10916
- if (logoHasUploadedImage(logoEl)) {
10917
- const img = logoEl.querySelector('img[data-ohw-key="nav-logo-image"], img[data-ohw-key="footer-logo"], img[data-ohw-key="footer-logo-image"]') ?? logoEl.querySelector("img");
10918
- if (img) {
10919
- const r2 = img.getBoundingClientRect();
10920
- if (r2.width > 0 && r2.height > 0) return r2;
10921
- }
10922
- }
10923
- const text = logoEl.querySelector(
10924
- '[data-ohw-key="nav-logo-text"], [data-ohw-key="footer-logo-text"]'
10925
- );
10926
- if (text) {
10927
- const style = window.getComputedStyle(text);
10928
- if (style.display !== "none" && style.visibility !== "hidden") {
10929
- const r2 = text.getBoundingClientRect();
10930
- if (r2.width > 0 && r2.height > 0) return r2;
10931
- }
10932
- }
10933
- return logoEl.getBoundingClientRect();
10934
- }
10935
- function readLogoSizeState(content, placement) {
10936
- const desktopPx = resolveDesktopLogoSize(content, placement);
10937
- const mobileFollowing = isMobileLogoSizeFollowing(content, placement);
10938
- const mobilePx = mobileFollowing ? desktopPx : resolveMobileLogoSize(content, placement);
10939
- return { desktopPx, mobilePx, mobileFollowing };
10940
- }
10941
-
10942
- // src/lib/site-wide-scope.ts
10943
- function getLogoElement(el) {
10944
- const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
10945
- if (marked) return marked;
10946
- if (el.closest('[data-ohw-editable="icon"]')) return null;
10947
- const root = el.closest("nav, [data-ohw-nav-root], footer");
10948
- if (!root) return null;
10949
- const anchor = el.closest("a");
10950
- if (anchor && root.contains(anchor) && !anchor.hasAttribute("data-ohw-href-key") && !anchor.closest("[data-ohw-nav-container]") && Boolean(anchor.querySelector("img") || anchor.matches("img"))) {
10951
- return anchor;
10952
- }
10953
- const img = el.matches("img") ? el : null;
10954
- if (img && !img.closest("[data-ohw-href-key]") && !img.closest("[data-ohw-nav-container]") && (img.closest("footer") || img.closest("nav, [data-ohw-nav-root]"))) {
10955
- return img;
10956
- }
10957
- return null;
10958
- }
10959
- function isInFooter(el) {
10960
- if (!el) return false;
10961
- return Boolean(el.closest("footer") || el.closest('[data-ohw-section="footer"]'));
10962
- }
10963
- function isSiteWideElement(el) {
10964
- if (!el) return false;
10965
- if (getLogoElement(el)) return true;
10966
- if (isInFooter(el)) return true;
10967
- if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-root")) {
10968
- return true;
10969
- }
10970
- if (el.hasAttribute("data-ohw-href-key") && el.closest("nav, [data-ohw-nav-root], [data-ohw-nav-drawer], aside")) {
10971
- return true;
10972
- }
10973
- if (el.closest('[data-ohw-role="navbar-button"]')) return true;
10974
- return false;
10975
- }
10976
- function isSiteWideScopeActive(args) {
10977
- return isSiteWideElement(args.selected) || isSiteWideElement(args.hoveredItem) || isSiteWideElement(args.hoveredNavContainer) || isSiteWideElement(args.active);
10978
- }
10979
-
10980
10299
  // src/lib/add-footer-column.ts
10981
10300
  function buildFooterColumnEditContentPatch(result) {
10982
10301
  return {
@@ -11009,323 +10328,30 @@ function addFooterColumnWithPersist({
11009
10328
  return result;
11010
10329
  }
11011
10330
 
11012
- // src/ui/FloatingPanel.tsx
11013
- import {
11014
- useCallback as useCallback5,
11015
- useEffect as useEffect9,
11016
- useLayoutEffect as useLayoutEffect3,
11017
- useRef as useRef7,
11018
- useState as useState8
11019
- } from "react";
11020
- import { X as X5 } from "lucide-react";
11021
- import { jsx as jsx26, jsxs as jsxs16 } from "react/jsx-runtime";
11022
- var PANEL_WIDTH = 256;
11023
- var EDGE_MARGIN = 16;
11024
- function getVisibleClip(parentScroll) {
11025
- const left = 0;
11026
- const right = window.innerWidth;
11027
- if (!parentScroll) {
11028
- return { top: 0, bottom: window.innerHeight, left, right };
10331
+ // src/lib/item-drag-interaction.ts
10332
+ function disableNativeHrefDrag(el) {
10333
+ if (el.draggable) el.draggable = false;
10334
+ if (el.getAttribute("draggable") !== "false") {
10335
+ el.setAttribute("draggable", "false");
11029
10336
  }
11030
- const { iframeOffsetTop, headerH: visibleCanvasTop, canvasH } = parentScroll;
11031
- const top = Math.max(0, visibleCanvasTop - iframeOffsetTop);
11032
- const bottom = Math.min(window.innerHeight, visibleCanvasTop + canvasH - iframeOffsetTop);
11033
- return { top, bottom: Math.max(top, bottom), left, right };
11034
10337
  }
11035
- function defaultFloatingPanelPosition(parentScroll, panelHeight = 280) {
11036
- const clip = getVisibleClip(parentScroll);
11037
- return {
11038
- x: Math.max(EDGE_MARGIN, clip.right - PANEL_WIDTH - EDGE_MARGIN),
11039
- y: Math.min(
11040
- Math.max(clip.top + EDGE_MARGIN, EDGE_MARGIN),
11041
- Math.max(clip.top + EDGE_MARGIN, clip.bottom - panelHeight - EDGE_MARGIN)
11042
- )
11043
- };
10338
+ function clearTextSelection() {
10339
+ const sel = window.getSelection();
10340
+ if (sel && !sel.isCollapsed) sel.removeAllRanges();
11044
10341
  }
11045
- function clampPosition(pos, parentScroll, panelW, panelH) {
11046
- const clip = getVisibleClip(parentScroll);
11047
- const maxX = Math.max(clip.left + EDGE_MARGIN, clip.right - panelW - EDGE_MARGIN);
11048
- const maxY = Math.max(clip.top + EDGE_MARGIN, clip.bottom - panelH - EDGE_MARGIN);
11049
- return {
11050
- x: Math.min(Math.max(pos.x, clip.left + EDGE_MARGIN), maxX),
11051
- y: Math.min(Math.max(pos.y, clip.top + EDGE_MARGIN), maxY)
11052
- };
10342
+ function armItemPressDrag() {
10343
+ document.documentElement.setAttribute("data-ohw-footer-press-drag", "");
11053
10344
  }
11054
- function FloatingPanel({
11055
- open,
11056
- title,
11057
- context,
11058
- icon,
11059
- onClose,
11060
- children,
11061
- position,
11062
- onPositionChange,
11063
- parentScroll = null,
11064
- className,
11065
- bodyClassName
11066
- }) {
11067
- const panelRef = useRef7(null);
11068
- const [measured, setMeasured] = useState8({ w: PANEL_WIDTH, h: 280 });
11069
- const dragRef = useRef7(null);
11070
- const resolved = position ?? defaultFloatingPanelPosition(parentScroll, measured.h);
11071
- const clamped = clampPosition(resolved, parentScroll, measured.w, measured.h);
11072
- useLayoutEffect3(() => {
11073
- if (!open || !panelRef.current) return;
11074
- const el = panelRef.current;
11075
- const next = { w: el.offsetWidth || PANEL_WIDTH, h: el.offsetHeight || 280 };
11076
- setMeasured((prev) => prev.w === next.w && prev.h === next.h ? prev : next);
11077
- }, [open, children, title, context]);
11078
- useEffect9(() => {
11079
- if (!open || !position || !onPositionChange) return;
11080
- const next = clampPosition(position, parentScroll, measured.w, measured.h);
11081
- if (next.x !== position.x || next.y !== position.y) onPositionChange(next);
11082
- }, [open, parentScroll, measured.w, measured.h, position, onPositionChange]);
11083
- const onHeaderPointerDown = useCallback5(
11084
- (e) => {
11085
- if (e.button !== 0) return;
11086
- if (e.target.closest("[data-ohw-floating-panel-close]")) return;
11087
- e.preventDefault();
11088
- e.stopPropagation();
11089
- const el = e.currentTarget;
11090
- el.setPointerCapture(e.pointerId);
11091
- dragRef.current = {
11092
- pointerId: e.pointerId,
11093
- startX: e.clientX,
11094
- startY: e.clientY,
11095
- originX: clamped.x,
11096
- originY: clamped.y
11097
- };
11098
- },
11099
- [clamped.x, clamped.y]
11100
- );
11101
- const onHeaderPointerMove = useCallback5(
11102
- (e) => {
11103
- const drag = dragRef.current;
11104
- if (!drag || drag.pointerId !== e.pointerId) return;
11105
- e.preventDefault();
11106
- const next = clampPosition(
11107
- {
11108
- x: drag.originX + (e.clientX - drag.startX),
11109
- y: drag.originY + (e.clientY - drag.startY)
11110
- },
11111
- parentScroll,
11112
- measured.w,
11113
- measured.h
11114
- );
11115
- onPositionChange?.(next);
11116
- },
11117
- [measured.h, measured.w, onPositionChange, parentScroll]
11118
- );
11119
- const endDrag = useCallback5((e) => {
11120
- const drag = dragRef.current;
11121
- if (!drag || drag.pointerId !== e.pointerId) return;
11122
- dragRef.current = null;
11123
- try {
11124
- e.currentTarget.releasePointerCapture(e.pointerId);
11125
- } catch {
11126
- }
11127
- }, []);
11128
- if (!open) return null;
11129
- return /* @__PURE__ */ jsxs16(
11130
- "div",
11131
- {
11132
- ref: panelRef,
11133
- "data-ohw-floating-panel": "",
11134
- role: "dialog",
11135
- "aria-label": title,
11136
- className: cn(
11137
- // Above MediaOverlay / item chrome (2147483646); link-modal content shares this tier.
11138
- "fixed z-[2147483647] flex w-64 flex-col overflow-hidden rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
11139
- className
11140
- ),
11141
- style: { left: clamped.x, top: clamped.y },
11142
- onMouseDown: (e) => e.stopPropagation(),
11143
- onPointerDown: (e) => e.stopPropagation(),
11144
- onClick: (e) => e.stopPropagation(),
11145
- children: [
11146
- /* @__PURE__ */ jsxs16(
11147
- "div",
11148
- {
11149
- "data-ohw-floating-panel-header": "",
11150
- className: "relative flex cursor-grab items-start gap-2 border-b border-border py-5 pl-5 pr-11 active:cursor-grabbing",
11151
- onPointerDown: onHeaderPointerDown,
11152
- onPointerMove: onHeaderPointerMove,
11153
- onPointerUp: endDrag,
11154
- onPointerCancel: endDrag,
11155
- children: [
11156
- /* @__PURE__ */ jsxs16("div", { className: "flex min-w-0 flex-1 flex-col gap-1.5", children: [
11157
- /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2", children: [
11158
- icon ? /* @__PURE__ */ jsx26("span", { className: "shrink-0 text-foreground", children: icon }) : null,
11159
- /* @__PURE__ */ jsx26("p", { className: "min-w-0 flex-1 text-lg font-semibold leading-7 text-foreground", children: title })
11160
- ] }),
11161
- context ? /* @__PURE__ */ jsx26("p", { className: "w-full text-sm leading-5 text-muted-foreground", children: context }) : null
11162
- ] }),
11163
- /* @__PURE__ */ jsx26(
11164
- "button",
11165
- {
11166
- type: "button",
11167
- "data-ohw-floating-panel-close": "",
11168
- "aria-label": "Close",
11169
- className: "absolute right-2.5 top-2.5 rounded-sm p-1.5 text-foreground hover:bg-muted/50",
11170
- onClick: (e) => {
11171
- e.stopPropagation();
11172
- onClose();
11173
- },
11174
- onPointerDown: (e) => e.stopPropagation(),
11175
- children: /* @__PURE__ */ jsx26(X5, { size: 16, "aria-hidden": true })
11176
- }
11177
- )
11178
- ]
11179
- }
11180
- ),
11181
- /* @__PURE__ */ jsx26(
11182
- "div",
11183
- {
11184
- "data-ohw-floating-panel-body": "",
11185
- className: cn("flex w-full flex-col gap-4 p-5", bodyClassName),
11186
- children
11187
- }
11188
- )
11189
- ]
11190
- }
11191
- );
10345
+ function lockItemDuringDrag() {
10346
+ document.documentElement.removeAttribute("data-ohw-footer-press-drag");
10347
+ document.documentElement.setAttribute("data-ohw-item-dragging", "");
10348
+ clearTextSelection();
11192
10349
  }
11193
-
11194
- // src/ui/logo-size-panel.tsx
11195
- import { ArrowUpRight, Link as Link2 } from "lucide-react";
11196
- import { jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
11197
- function SizeSlider({
11198
- value,
11199
- onChange
11200
- }) {
11201
- const pct = (value - LOGO_SIZE_MIN) / (LOGO_SIZE_MAX - LOGO_SIZE_MIN) * 100;
11202
- return /* @__PURE__ */ jsxs17("div", { className: "flex w-full flex-col gap-3", children: [
11203
- /* @__PURE__ */ jsxs17("div", { className: "flex w-full items-center gap-2 text-sm font-medium leading-5", children: [
11204
- /* @__PURE__ */ jsx27("span", { className: "min-w-0 flex-1 text-foreground", children: "Size" }),
11205
- /* @__PURE__ */ jsxs17("span", { className: "shrink-0 whitespace-nowrap text-muted-foreground", children: [
11206
- value,
11207
- " px"
11208
- ] })
11209
- ] }),
11210
- /* @__PURE__ */ jsxs17("div", { className: "relative h-2 w-full rounded-full bg-primary-50", children: [
11211
- /* @__PURE__ */ jsx27(
11212
- "div",
11213
- {
11214
- className: "absolute inset-y-0 left-0 rounded-full bg-primary",
11215
- style: { width: `${pct}%` }
11216
- }
11217
- ),
11218
- /* @__PURE__ */ jsx27(
11219
- "input",
11220
- {
11221
- type: "range",
11222
- min: LOGO_SIZE_MIN,
11223
- max: LOGO_SIZE_MAX,
11224
- step: 1,
11225
- value,
11226
- "aria-label": "Logo size",
11227
- className: cn(
11228
- "absolute inset-0 h-full w-full cursor-pointer appearance-none bg-transparent",
11229
- "[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:size-5",
11230
- "[&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-2",
11231
- "[&::-webkit-slider-thumb]:border-primary [&::-webkit-slider-thumb]:bg-background",
11232
- "[&::-moz-range-thumb]:size-5 [&::-moz-range-thumb]:rounded-full",
11233
- "[&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-primary",
11234
- "[&::-moz-range-thumb]:bg-background"
11235
- ),
11236
- onChange: (e) => onChange(Number(e.target.value))
11237
- }
11238
- )
11239
- ] })
11240
- ] });
11241
- }
11242
- function LogoSizePanel({
11243
- viewport,
11244
- sizePx,
11245
- mobileFollowing = true,
11246
- onSizeChange,
11247
- onCustomizeMobile,
11248
- onResetMobile,
11249
- onUpdateEverywhere,
11250
- className
11251
- }) {
11252
- const showFollowing = viewport === "mobile" && mobileFollowing;
11253
- const showMobileSlider = viewport === "mobile" && !mobileFollowing;
11254
- const showDesktopSlider = viewport === "desktop";
11255
- return /* @__PURE__ */ jsxs17("div", { className: cn("flex w-full flex-col gap-4", className), children: [
11256
- showFollowing ? /* @__PURE__ */ jsxs17("div", { className: "flex w-full flex-col gap-2", children: [
11257
- /* @__PURE__ */ jsxs17("div", { className: "flex items-start gap-1", children: [
11258
- /* @__PURE__ */ jsx27(Link2, { size: 16, className: "mt-0.5 shrink-0 text-foreground", "aria-hidden": true }),
11259
- /* @__PURE__ */ jsx27("p", { className: "text-sm font-semibold leading-5 text-foreground", children: "Following desktop size" })
11260
- ] }),
11261
- /* @__PURE__ */ jsx27("p", { className: "text-sm leading-5 text-muted-foreground", children: "Mobile uses the desktop size until you customize it. Change the desktop size and it follows automatically." }),
11262
- /* @__PURE__ */ jsx27(
11263
- Button,
11264
- {
11265
- type: "button",
11266
- variant: "outline",
11267
- size: "sm",
11268
- className: "h-9 w-full min-w-0 cursor-pointer",
11269
- onClick: onCustomizeMobile,
11270
- children: "Customize for mobile"
11271
- }
11272
- )
11273
- ] }) : null,
11274
- showDesktopSlider || showMobileSlider ? /* @__PURE__ */ jsx27(SizeSlider, { value: sizePx, onChange: onSizeChange }) : null,
11275
- showMobileSlider ? /* @__PURE__ */ jsx27(
11276
- Button,
11277
- {
11278
- type: "button",
11279
- variant: "outline",
11280
- size: "sm",
11281
- className: "h-9 w-full min-w-0 cursor-pointer",
11282
- onClick: onResetMobile,
11283
- children: "Reset to desktop size"
11284
- }
11285
- ) : null,
11286
- /* @__PURE__ */ jsx27("div", { className: "h-px w-full bg-border", role: "separator" }),
11287
- /* @__PURE__ */ jsxs17(
11288
- Button,
11289
- {
11290
- type: "button",
11291
- variant: "outline",
11292
- size: "sm",
11293
- className: "h-9 w-full min-w-0 cursor-pointer gap-1",
11294
- onClick: onUpdateEverywhere,
11295
- children: [
11296
- "Update logo everywhere",
11297
- /* @__PURE__ */ jsx27(ArrowUpRight, { size: 16, "aria-hidden": true })
11298
- ]
11299
- }
11300
- ),
11301
- /* @__PURE__ */ jsx27("p", { className: "text-sm leading-5 text-muted-foreground", children: "Matches the right version to your background." })
11302
- ] });
11303
- }
11304
-
11305
- // src/lib/item-drag-interaction.ts
11306
- function disableNativeHrefDrag(el) {
11307
- if (el.draggable) el.draggable = false;
11308
- if (el.getAttribute("draggable") !== "false") {
11309
- el.setAttribute("draggable", "false");
11310
- }
11311
- }
11312
- function clearTextSelection() {
11313
- const sel = window.getSelection();
11314
- if (sel && !sel.isCollapsed) sel.removeAllRanges();
11315
- }
11316
- function armItemPressDrag() {
11317
- document.documentElement.setAttribute("data-ohw-footer-press-drag", "");
11318
- }
11319
- function lockItemDuringDrag() {
11320
- document.documentElement.removeAttribute("data-ohw-footer-press-drag");
11321
- document.documentElement.setAttribute("data-ohw-item-dragging", "");
11322
- clearTextSelection();
11323
- }
11324
- function unlockItemDragInteraction() {
11325
- const wasDragging = document.documentElement.hasAttribute("data-ohw-item-dragging");
11326
- document.documentElement.removeAttribute("data-ohw-footer-press-drag");
11327
- document.documentElement.removeAttribute("data-ohw-item-dragging");
11328
- if (wasDragging) clearTextSelection();
10350
+ function unlockItemDragInteraction() {
10351
+ const wasDragging = document.documentElement.hasAttribute("data-ohw-item-dragging");
10352
+ document.documentElement.removeAttribute("data-ohw-footer-press-drag");
10353
+ document.documentElement.removeAttribute("data-ohw-item-dragging");
10354
+ if (wasDragging) clearTextSelection();
11329
10355
  }
11330
10356
  var armFooterPressDrag = armItemPressDrag;
11331
10357
  var lockFooterDuringDrag = lockItemDuringDrag;
@@ -11500,7 +10526,7 @@ function hitTestNavDropSlot(clientX, clientY, draggedHrefKey) {
11500
10526
  }
11501
10527
 
11502
10528
  // src/useNavItemDrag.ts
11503
- import { useCallback as useCallback6, useEffect as useEffect10, useRef as useRef8, useState as useState9 } from "react";
10529
+ import { useCallback as useCallback5, useEffect as useEffect9, useRef as useRef7, useState as useState8 } from "react";
11504
10530
  function useNavItemDrag({
11505
10531
  isEditMode,
11506
10532
  editContentRef,
@@ -11524,11 +10550,11 @@ function useNavItemDrag({
11524
10550
  getNavigationItemAnchor: getNavigationItemAnchor2,
11525
10551
  isDragHandleDisabled: isDragHandleDisabled2
11526
10552
  }) {
11527
- const navDragRef = useRef8(null);
11528
- const [navDropSlots, setNavDropSlots] = useState9([]);
11529
- const [activeNavDropIndex, setActiveNavDropIndex] = useState9(null);
11530
- const navPointerDragRef = useRef8(null);
11531
- const clearNavDragVisuals = useCallback6(() => {
10553
+ const navDragRef = useRef7(null);
10554
+ const [navDropSlots, setNavDropSlots] = useState8([]);
10555
+ const [activeNavDropIndex, setActiveNavDropIndex] = useState8(null);
10556
+ const navPointerDragRef = useRef7(null);
10557
+ const clearNavDragVisuals = useCallback5(() => {
11532
10558
  const session = navDragRef.current;
11533
10559
  const keepOpenEl = session?.draggedEl?.closest("[data-ohw-nav-children]") != null ? session.draggedEl : null;
11534
10560
  navDragRef.current = null;
@@ -11545,7 +10571,7 @@ function useNavItemDrag({
11545
10571
  document.documentElement.removeAttribute("data-ohw-nav-dragging-root");
11546
10572
  unlockItemDragInteraction();
11547
10573
  }, [setDraggedItemRect, setIsItemDragging, setSiblingHintRects]);
11548
- const refreshNavDragVisuals = useCallback6(
10574
+ const refreshNavDragVisuals = useCallback5(
11549
10575
  (session, activeSlot, clientX, clientY) => {
11550
10576
  setDraggedItemRect(session.draggedEl.getBoundingClientRect());
11551
10577
  if (typeof clientX === "number" && typeof clientY === "number") {
@@ -11563,13 +10589,13 @@ function useNavItemDrag({
11563
10589
  },
11564
10590
  [setDraggedItemRect, setSiblingHintRects]
11565
10591
  );
11566
- const refreshNavDragVisualsRef = useRef8(refreshNavDragVisuals);
10592
+ const refreshNavDragVisualsRef = useRef7(refreshNavDragVisuals);
11567
10593
  refreshNavDragVisualsRef.current = refreshNavDragVisuals;
11568
- const commitNavDragRef = useRef8(() => {
10594
+ const commitNavDragRef = useRef7(() => {
11569
10595
  });
11570
- const beginNavDragRef = useRef8(() => {
10596
+ const beginNavDragRef = useRef7(() => {
11571
10597
  });
11572
- const beginNavDrag = useCallback6(
10598
+ const beginNavDrag = useCallback5(
11573
10599
  (session) => {
11574
10600
  const rect = session.draggedEl.getBoundingClientRect();
11575
10601
  session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
@@ -11603,7 +10629,7 @@ function useNavItemDrag({
11603
10629
  ]
11604
10630
  );
11605
10631
  beginNavDragRef.current = beginNavDrag;
11606
- const commitNavDrag = useCallback6(
10632
+ const commitNavDrag = useCallback5(
11607
10633
  (clientX, clientY) => {
11608
10634
  const session = navDragRef.current;
11609
10635
  if (!session) {
@@ -11664,7 +10690,7 @@ function useNavItemDrag({
11664
10690
  [clearNavDragVisuals, deselectRef, editContentRef, postToParentRef, selectRef]
11665
10691
  );
11666
10692
  commitNavDragRef.current = commitNavDrag;
11667
- const startNavLinkDrag = useCallback6(
10693
+ const startNavLinkDrag = useCallback5(
11668
10694
  (anchor, clientX, clientY, wasSelected) => {
11669
10695
  if (footerDragRef.current) return false;
11670
10696
  const hrefKey = anchor.getAttribute("data-ohw-href-key");
@@ -11682,7 +10708,7 @@ function useNavItemDrag({
11682
10708
  },
11683
10709
  [beginNavDrag, footerDragRef, isDragHandleDisabled2, isCtaButton]
11684
10710
  );
11685
- const onNavDragOver = useCallback6(
10711
+ const onNavDragOver = useCallback5(
11686
10712
  (e) => {
11687
10713
  const session = navDragRef.current;
11688
10714
  if (!session) return false;
@@ -11694,7 +10720,7 @@ function useNavItemDrag({
11694
10720
  },
11695
10721
  []
11696
10722
  );
11697
- useEffect10(() => {
10723
+ useEffect9(() => {
11698
10724
  if (!isEditMode) return;
11699
10725
  const THRESHOLD = 10;
11700
10726
  const resolveWasSelected = (el) => {
@@ -11819,7 +10845,7 @@ function useNavItemDrag({
11819
10845
  setLinkPopover,
11820
10846
  suppressNextClickRef
11821
10847
  ]);
11822
- const armNavPressFromChrome = useCallback6(
10848
+ const armNavPressFromChrome = useCallback5(
11823
10849
  (selected, clientX, clientY, pointerId) => {
11824
10850
  const hrefKey = selected.getAttribute("data-ohw-href-key");
11825
10851
  if (!hrefKey || !isNavbarHrefKey(hrefKey)) return false;
@@ -11851,7 +10877,7 @@ function useNavItemDrag({
11851
10877
 
11852
10878
  // src/ui/footer-container-chrome.tsx
11853
10879
  import { Plus as Plus2 } from "lucide-react";
11854
- import { jsx as jsx28, jsxs as jsxs18 } from "react/jsx-runtime";
10880
+ import { jsx as jsx26, jsxs as jsxs16 } from "react/jsx-runtime";
11855
10881
  function FooterContainerChrome({
11856
10882
  rect,
11857
10883
  onAdd,
@@ -11859,7 +10885,7 @@ function FooterContainerChrome({
11859
10885
  }) {
11860
10886
  const chromeGap = 6;
11861
10887
  const buttonMargin = 7;
11862
- return /* @__PURE__ */ jsx28(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsx28(
10888
+ return /* @__PURE__ */ jsx26(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsx26(
11863
10889
  "div",
11864
10890
  {
11865
10891
  "data-ohw-footer-container-chrome": "",
@@ -11871,8 +10897,8 @@ function FooterContainerChrome({
11871
10897
  width: rect.width + chromeGap * 2,
11872
10898
  height: rect.height + chromeGap * 2
11873
10899
  },
11874
- children: /* @__PURE__ */ jsxs18(Tooltip, { children: [
11875
- /* @__PURE__ */ jsx28(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx28(
10900
+ children: /* @__PURE__ */ jsxs16(Tooltip, { children: [
10901
+ /* @__PURE__ */ jsx26(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx26(
11876
10902
  "button",
11877
10903
  {
11878
10904
  type: "button",
@@ -11891,17 +10917,17 @@ function FooterContainerChrome({
11891
10917
  if (addDisabled) return;
11892
10918
  onAdd();
11893
10919
  },
11894
- children: /* @__PURE__ */ jsx28(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
10920
+ children: /* @__PURE__ */ jsx26(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
11895
10921
  }
11896
10922
  ) }),
11897
- /* @__PURE__ */ jsx28(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
10923
+ /* @__PURE__ */ jsx26(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
11898
10924
  ] })
11899
10925
  }
11900
10926
  ) });
11901
10927
  }
11902
10928
 
11903
10929
  // src/lib/carousel.ts
11904
- import { useEffect as useEffect11, useState as useState10 } from "react";
10930
+ import { useEffect as useEffect10, useState as useState9 } from "react";
11905
10931
  var CAROUSEL_ATTR = "data-ohw-carousel";
11906
10932
  var CAROUSEL_VALUE_ATTR = "data-ohw-carousel-value";
11907
10933
  var CAROUSEL_SLIDE_ATTR = "data-ohw-carousel-slide";
@@ -11963,8 +10989,8 @@ function applyCarouselNode(key, val) {
11963
10989
  return true;
11964
10990
  }
11965
10991
  function useOhwCarousel(key, initial) {
11966
- const [images, setImages] = useState10(initial);
11967
- useEffect11(() => {
10992
+ const [images, setImages] = useState9(initial);
10993
+ useEffect10(() => {
11968
10994
  const el = document.querySelector(
11969
10995
  `[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`
11970
10996
  );
@@ -12077,18 +11103,6 @@ function collectEditableNodes(extraContent, root = document) {
12077
11103
  }
12078
11104
  if (extraContent && !isScoped) {
12079
11105
  applyNavFooterDeleteOverrides(byKey, extraContent);
12080
- for (const key of LOGO_IMAGE_KEYS) {
12081
- if (!(key in extraContent)) continue;
12082
- byKey.set(key, { key, type: "image", text: extraContent[key] ?? "" });
12083
- }
12084
- for (const key of [LOGO_PLACEHOLDER_KEY, LOGO_ALT_KEY]) {
12085
- if (!(key in extraContent)) continue;
12086
- byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
12087
- }
12088
- for (const key of LOGO_SIZE_KEYS) {
12089
- if (!(key in extraContent)) continue;
12090
- byKey.set(key, { key, type: "meta", text: extraContent[key] ?? "" });
12091
- }
12092
11106
  }
12093
11107
  return Array.from(byKey.values());
12094
11108
  }
@@ -12191,7 +11205,7 @@ function isNavbarLinksContainer(el) {
12191
11205
  function isNavigationItem(el) {
12192
11206
  const anchor = el.matches("[data-ohw-href-key]") ? el : el.closest("[data-ohw-href-key]");
12193
11207
  if (!anchor) return false;
12194
- return Boolean(anchor.querySelector('[data-ohw-editable="text"]')) || Boolean(getSocialItem(anchor));
11208
+ return Boolean(anchor.querySelector('[data-ohw-editable="text"]'));
12195
11209
  }
12196
11210
  function findFooterItemGroup(item) {
12197
11211
  const explicit = item.closest("[data-ohw-footer-col], [data-ohw-footer-column]");
@@ -12212,9 +11226,8 @@ function isInferredFooterGroup(el) {
12212
11226
  const footer = el.closest("footer");
12213
11227
  if (!footer || el === footer) return false;
12214
11228
  if (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column")) return true;
12215
- if (isSocialsRow(el)) return false;
12216
11229
  const count = Array.from(el.querySelectorAll("[data-ohw-href-key]")).filter(
12217
- (item) => isNavigationItem(item) && !getSocialItem(item)
11230
+ isNavigationItem
12218
11231
  ).length;
12219
11232
  return count >= 2;
12220
11233
  }
@@ -12258,8 +11271,7 @@ function deleteSelectedNavFooterItem(deps) {
12258
11271
  if (key.endsWith("-href")) applyLinkByKey2(key, text);
12259
11272
  else {
12260
11273
  document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`).forEach((el) => {
12261
- if (el.getAttribute("data-ohw-editable") === "icon") applyIconMarkup(el, text);
12262
- else el.textContent = text;
11274
+ el.textContent = text;
12263
11275
  });
12264
11276
  }
12265
11277
  }
@@ -12321,21 +11333,6 @@ function deleteSelectedNavFooterItem(deps) {
12321
11333
  });
12322
11334
  return true;
12323
11335
  }
12324
- const social = getSocialItem(selected);
12325
- if (social) {
12326
- const result = removeSocialItem(social, getEditContent());
12327
- if (!result) return false;
12328
- finishDelete({
12329
- toastTitle: "Social deleted",
12330
- removedKeys: result.removedKeys,
12331
- previousContent: result.previousContent,
12332
- orderKey: SOCIALS_ORDER_KEY,
12333
- orderJson: JSON.stringify(result.order),
12334
- previousOrderJson: JSON.stringify(result.previousOrder),
12335
- undoDom: result.undo
12336
- });
12337
- return true;
12338
- }
12339
11336
  if (isFooterHrefKey(hrefKey)) {
12340
11337
  const result = deleteFooterItem(selected);
12341
11338
  if (!result) return false;
@@ -12355,13 +11352,13 @@ function deleteSelectedNavFooterItem(deps) {
12355
11352
 
12356
11353
  // src/ui/navbar-container-chrome.tsx
12357
11354
  import { Plus as Plus3 } from "lucide-react";
12358
- import { jsx as jsx29 } from "react/jsx-runtime";
11355
+ import { jsx as jsx27 } from "react/jsx-runtime";
12359
11356
  function NavbarContainerChrome({
12360
11357
  rect,
12361
11358
  onAdd
12362
11359
  }) {
12363
11360
  const chromeGap = 6;
12364
- return /* @__PURE__ */ jsx29(
11361
+ return /* @__PURE__ */ jsx27(
12365
11362
  "div",
12366
11363
  {
12367
11364
  "data-ohw-navbar-container-chrome": "",
@@ -12373,7 +11370,7 @@ function NavbarContainerChrome({
12373
11370
  width: rect.width + chromeGap * 2,
12374
11371
  height: rect.height + chromeGap * 2
12375
11372
  },
12376
- children: /* @__PURE__ */ jsx29(
11373
+ children: /* @__PURE__ */ jsx27(
12377
11374
  "button",
12378
11375
  {
12379
11376
  type: "button",
@@ -12390,7 +11387,7 @@ function NavbarContainerChrome({
12390
11387
  e.stopPropagation();
12391
11388
  onAdd();
12392
11389
  },
12393
- children: /* @__PURE__ */ jsx29(Plus3, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
11390
+ children: /* @__PURE__ */ jsx27(Plus3, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
12394
11391
  }
12395
11392
  )
12396
11393
  }
@@ -12399,7 +11396,7 @@ function NavbarContainerChrome({
12399
11396
 
12400
11397
  // src/ui/drop-indicator.tsx
12401
11398
  import * as React10 from "react";
12402
- import { jsx as jsx30 } from "react/jsx-runtime";
11399
+ import { jsx as jsx28 } from "react/jsx-runtime";
12403
11400
  var dropIndicatorVariants = cva(
12404
11401
  "ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
12405
11402
  {
@@ -12423,7 +11420,7 @@ var dropIndicatorVariants = cva(
12423
11420
  );
12424
11421
  var DropIndicator = React10.forwardRef(
12425
11422
  ({ className, direction, state, ...props }, ref) => {
12426
- return /* @__PURE__ */ jsx30(
11423
+ return /* @__PURE__ */ jsx28(
12427
11424
  "div",
12428
11425
  {
12429
11426
  ref,
@@ -12440,7 +11437,7 @@ var DropIndicator = React10.forwardRef(
12440
11437
  DropIndicator.displayName = "DropIndicator";
12441
11438
 
12442
11439
  // src/ui/badge.tsx
12443
- import { jsx as jsx31 } from "react/jsx-runtime";
11440
+ import { jsx as jsx29 } from "react/jsx-runtime";
12444
11441
  var badgeVariants = cva(
12445
11442
  "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",
12446
11443
  {
@@ -12458,12 +11455,12 @@ var badgeVariants = cva(
12458
11455
  }
12459
11456
  );
12460
11457
  function Badge({ className, variant, ...props }) {
12461
- return /* @__PURE__ */ jsx31("div", { className: cn(badgeVariants({ variant }), className), ...props });
11458
+ return /* @__PURE__ */ jsx29("div", { className: cn(badgeVariants({ variant }), className), ...props });
12462
11459
  }
12463
11460
 
12464
11461
  // src/OhhwellsBridge.tsx
12465
- import { Link as Link3 } from "lucide-react";
12466
- import { Fragment as Fragment8, jsx as jsx32, jsxs as jsxs19 } from "react/jsx-runtime";
11462
+ import { Link as Link2 } from "lucide-react";
11463
+ import { Fragment as Fragment8, jsx as jsx30, jsxs as jsxs17 } from "react/jsx-runtime";
12467
11464
  var PRIMARY3 = "#0885FE";
12468
11465
  var IMAGE_FADE_MS = 300;
12469
11466
  function runOpacityFade(el, onDone) {
@@ -12557,10 +11554,21 @@ function parseSchedulingInsertAfter(insertAfter) {
12557
11554
  insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
12558
11555
  };
12559
11556
  }
12560
- function resolveEntryAnchor(entry) {
12561
- if (entry.anchorId !== void 0) return { anchorId: entry.anchorId, beforeId: entry.beforeId ?? null };
12562
- const parsed = parseSchedulingInsertAfter(entry.insertAfter);
12563
- return { anchorId: parsed.anchor, beforeId: parsed.insertBefore };
11557
+ function resolveSchedulingInsert(insertAfter, explicitInsertBefore) {
11558
+ const parsed = parseSchedulingInsertAfter(insertAfter);
11559
+ const insertBefore = explicitInsertBefore ?? parsed.insertBefore;
11560
+ const effectiveInsertAfter = insertBefore && parsed.insertBefore === null ? `${insertAfter}${INSERT_BEFORE_MARKER}${insertBefore}` : insertAfter;
11561
+ return { effectiveInsertAfter, insertBefore };
11562
+ }
11563
+ function getSchedulingMountPoint(insertAfter) {
11564
+ const { anchor } = parseSchedulingInsertAfter(insertAfter);
11565
+ let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
11566
+ if (!anchorEl && anchor === "scheduling") {
11567
+ const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
11568
+ anchorEl = widgets.at(-1) ?? null;
11569
+ }
11570
+ if (!anchorEl) return null;
11571
+ return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
12564
11572
  }
12565
11573
  function schedulingMountDepth(insertAfter) {
12566
11574
  if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
@@ -12577,7 +11585,8 @@ function getPageSchedulingEntries(raw) {
12577
11585
  }
12578
11586
  }
12579
11587
  function isSchedulingWidgetMissing(entry) {
12580
- return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
11588
+ const { effectiveInsertAfter } = resolveSchedulingInsert(entry.insertAfter);
11589
+ return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
12581
11590
  }
12582
11591
  function hasMissingSchedulingWidgets(entries) {
12583
11592
  return entries.some(isSchedulingWidgetMissing);
@@ -12607,17 +11616,16 @@ function initSectionsFromContent(content, removeExisting = false) {
12607
11616
  } catch {
12608
11617
  }
12609
11618
  }
12610
- function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, beforeId, existingWidgetId) {
12611
- const widgetId = existingWidgetId ?? (beforeId ? `${anchorId}${INSERT_BEFORE_MARKER}${beforeId}` : anchorId);
12612
- const sectionId = schedulingSectionId(widgetId);
11619
+ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId, explicitInsertBefore) {
11620
+ const { effectiveInsertAfter, insertBefore } = resolveSchedulingInsert(insertAfter, explicitInsertBefore);
11621
+ const sectionId = schedulingSectionId(effectiveInsertAfter);
12613
11622
  if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
12614
- const anchorEl = document.querySelector(`[data-ohw-section="${anchorId}"]`);
12615
- if (!anchorEl) return false;
12616
- const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
11623
+ const mountPoint = getSchedulingMountPoint(effectiveInsertAfter);
11624
+ if (!mountPoint) return false;
12617
11625
  const container = document.createElement("div");
12618
11626
  container.dataset.ohwSectionContainer = "scheduling";
12619
- if (beforeId) {
12620
- const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
11627
+ if (insertBefore) {
11628
+ const beforeAnchor = document.querySelector(`[data-ohw-section="${insertBefore}"]`);
12621
11629
  const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
12622
11630
  if (!beforePoint) return false;
12623
11631
  beforePoint.insertAdjacentElement("beforebegin", container);
@@ -12628,25 +11636,19 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
12628
11636
  }
12629
11637
  tail.insertAdjacentElement("afterend", container);
12630
11638
  }
12631
- try {
12632
- const root = createRoot2(container);
12633
- flushSync2(() => {
12634
- root.render(
12635
- /* @__PURE__ */ jsx32(
12636
- SchedulingWidget,
12637
- {
12638
- notifyOnConnect,
12639
- initialScheduleId: scheduleId,
12640
- insertAfter: widgetId
12641
- }
12642
- )
12643
- );
12644
- });
12645
- } catch (err) {
12646
- console.error("[ow:scheduling] render threw", err);
12647
- container.remove();
12648
- return false;
12649
- }
11639
+ const root = createRoot2(container);
11640
+ flushSync2(() => {
11641
+ root.render(
11642
+ /* @__PURE__ */ jsx30(
11643
+ SchedulingWidget,
11644
+ {
11645
+ notifyOnConnect,
11646
+ initialScheduleId: scheduleId,
11647
+ insertAfter: effectiveInsertAfter
11648
+ }
11649
+ )
11650
+ );
11651
+ });
12650
11652
  const tracker = getSectionsTracker();
12651
11653
  let sections = [];
12652
11654
  try {
@@ -12654,12 +11656,10 @@ function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, be
12654
11656
  } catch {
12655
11657
  }
12656
11658
  const inEditor = typeof window !== "undefined" && window.self !== window.top;
12657
- if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
11659
+ if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === effectiveInsertAfter)) {
12658
11660
  sections.push({
12659
11661
  type: "scheduling",
12660
- insertAfter: widgetId,
12661
- anchorId,
12662
- beforeId: beforeId ?? null,
11662
+ insertAfter: effectiveInsertAfter,
12663
11663
  pagePath: window.location.pathname,
12664
11664
  ...scheduleId ? { scheduleId } : {}
12665
11665
  });
@@ -12673,8 +11673,7 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
12673
11673
  for (let i = pending.length - 1; i >= 0; i--) {
12674
11674
  const entry = pending[i];
12675
11675
  const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
12676
- const { anchorId, beforeId } = resolveEntryAnchor(entry);
12677
- if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
11676
+ if (mountSchedulingWidget(entry.insertAfter, shouldNotify, entry.scheduleId)) {
12678
11677
  pending.splice(i, 1);
12679
11678
  }
12680
11679
  }
@@ -12688,17 +11687,6 @@ function applyLinkHref(el, val) {
12688
11687
  const anchor = el instanceof HTMLAnchorElement ? el : el.querySelector("a");
12689
11688
  if (anchor) anchor.setAttribute("href", val);
12690
11689
  }
12691
- function currentIconRef(el) {
12692
- const uploaded = el instanceof HTMLImageElement ? el : el.querySelector("img");
12693
- if (uploaded?.getAttribute("src")) {
12694
- return uploaded.getAttribute("src") ?? "";
12695
- }
12696
- const svg = el instanceof SVGElement ? el : el.querySelector("svg");
12697
- const named = Array.from(svg?.classList ?? []).find(
12698
- (c) => c.startsWith("lucide-") && c !== "lucide-icon"
12699
- );
12700
- return named ? `lucide:${named.slice("lucide-".length)}` : "";
12701
- }
12702
11690
  function getEditMeasureEl(editable) {
12703
11691
  return editable.closest("[data-ohw-href-key]") ?? editable;
12704
11692
  }
@@ -12743,11 +11731,8 @@ function isMediaEditable(el) {
12743
11731
  const t = el.dataset.ohwEditable;
12744
11732
  return t === "image" || t === "bg-image" || t === "video";
12745
11733
  }
12746
- function isIconEditable(el) {
12747
- return el.dataset.ohwEditable === "icon";
12748
- }
12749
11734
  var MEDIA_SELECTOR = '[data-ohw-editable="image"], [data-ohw-editable="bg-image"], [data-ohw-editable="video"]';
12750
- var NON_MEDIA_SELECTOR = '[data-ohw-editable]:not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]):not([data-ohw-editable="video"]):not([data-ohw-editable="icon"])';
11735
+ var NON_MEDIA_SELECTOR = '[data-ohw-editable]:not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]):not([data-ohw-editable="video"])';
12751
11736
  function getVideoEl2(el) {
12752
11737
  return el instanceof HTMLVideoElement ? el : el.querySelector("video");
12753
11738
  }
@@ -12818,13 +11803,6 @@ function isInsideLinkEditor(target) {
12818
11803
  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-ohw-more-menu]") || target.closest('[data-slot="dropdown-menu-content"]') || target.closest('[data-slot="popover-content"]') || target.closest('[data-slot="dialog-content"]') || target.closest('[data-slot="dialog-overlay"]')
12819
11804
  );
12820
11805
  }
12821
- function isInsideFloatingPanel(target) {
12822
- return Boolean(target.closest("[data-ohw-floating-panel]"));
12823
- }
12824
- function isPointOverFloatingPanel(clientX, clientY) {
12825
- const el = document.elementFromPoint(clientX, clientY);
12826
- return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
12827
- }
12828
11806
  function getHrefKeyFromElement(el) {
12829
11807
  if (!el) return null;
12830
11808
  const anchor = el.closest("[data-ohw-href-key]");
@@ -12872,29 +11850,13 @@ function isNavItemPointerTarget(el) {
12872
11850
  function getNavigationItemAnchor(el) {
12873
11851
  const anchor = el.matches("[data-ohw-href-key]") ? el : el.closest("[data-ohw-href-key]");
12874
11852
  if (!anchor) return null;
12875
- if (!anchor.querySelector('[data-ohw-editable="text"]') && !getSocialItem(anchor)) return null;
11853
+ if (!anchor.querySelector('[data-ohw-editable="text"]')) return null;
12876
11854
  if (!isNavItemPointerTarget(anchor)) return null;
12877
11855
  return anchor;
12878
11856
  }
12879
11857
  function isNavigationItem2(el) {
12880
11858
  return getNavigationItemAnchor(el) !== null;
12881
11859
  }
12882
- function requestSocialDialog(anchor, post, content) {
12883
- const item = getSocialItem(anchor);
12884
- if (!item) return false;
12885
- const iconKey = item.querySelector('[data-ohw-editable="icon"]')?.dataset.ohwKey ?? "";
12886
- post({
12887
- type: "ow:social-pick",
12888
- hrefKey: item.getAttribute("data-ohw-href-key") ?? "",
12889
- iconKey,
12890
- url: getLinkHref4(item),
12891
- iconStyle: detectIconStyle(item),
12892
- // What was chosen last time. Guessing from the address instead reads as "Website" for anything
12893
- // unrecognised, and for an item with no address at all — so a deliberate choice looked lost.
12894
- platformId: content[socialPlatformKey(iconKey)] ?? ""
12895
- });
12896
- return true;
12897
- }
12898
11860
  function listNavigationItems() {
12899
11861
  return Array.from(
12900
11862
  document.querySelectorAll("nav [data-ohw-href-key], footer [data-ohw-href-key]")
@@ -12929,7 +11891,7 @@ function getNavigationRoot(el) {
12929
11891
  return el.closest("nav, footer, aside");
12930
11892
  }
12931
11893
  function countFooterNavItems(el) {
12932
- return Array.from(el.querySelectorAll("[data-ohw-href-key]")).filter((item) => isNavigationItem2(item) && !getSocialItem(item)).length;
11894
+ return Array.from(el.querySelectorAll("[data-ohw-href-key]")).filter(isNavigationItem2).length;
12933
11895
  }
12934
11896
  function findFooterItemGroup2(item) {
12935
11897
  const explicit = item.closest("[data-ohw-footer-col], [data-ohw-footer-column]");
@@ -12950,11 +11912,10 @@ function isInferredFooterGroup2(el) {
12950
11912
  const footer = el.closest("footer");
12951
11913
  if (!footer || el === footer) return false;
12952
11914
  if (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column")) return true;
12953
- if (isSocialsRow(el)) return false;
12954
11915
  return countFooterNavItems(el) >= 2;
12955
11916
  }
12956
11917
  function isNavigationContainer(el) {
12957
- return el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el) || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isNavigationRoot(el) || isSocialsRow(el) || isInferredFooterGroup2(el);
11918
+ return el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el) || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isNavigationRoot(el) || isInferredFooterGroup2(el);
12958
11919
  }
12959
11920
  function isNavbarLinksContainer2(el) {
12960
11921
  return el.hasAttribute("data-ohw-nav-container");
@@ -13037,8 +11998,6 @@ function resolveNavContainerSelectionTarget(target, clientX, clientY) {
13037
11998
  return null;
13038
11999
  }
13039
12000
  function getNavigationSelectionParent(el) {
13040
- const socialsRow = findSocialsRow(el);
13041
- if (socialsRow) return socialsRow;
13042
12001
  if (isNavigationItem2(el)) {
13043
12002
  const childrenRoot = el.closest("[data-ohw-nav-children]");
13044
12003
  if (childrenRoot) {
@@ -13057,17 +12016,13 @@ function getNavigationSelectionParent(el) {
13057
12016
  if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
13058
12017
  return getFooterLinksContainer();
13059
12018
  }
13060
- if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isFooterLinksContainer(el) || isInferredFooterGroup2(el)) {
12019
+ if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
13061
12020
  return getNavigationRoot(el);
13062
12021
  }
13063
12022
  return null;
13064
12023
  }
13065
12024
  function collectNavigationItemSiblingHintRects(selected) {
13066
12025
  if (!isNavigationItem2(selected)) return [];
13067
- const socialsRow = findSocialsRow(selected);
13068
- if (socialsRow) {
13069
- return listSocialItems(socialsRow).filter((item) => item !== selected).map((item) => item.getBoundingClientRect());
13070
- }
13071
12026
  const footerColumn = getFooterColumn(selected);
13072
12027
  if (footerColumn) {
13073
12028
  return listFooterLinksInColumn(footerColumn).filter((link) => link !== selected).map((link) => link.getBoundingClientRect());
@@ -13300,7 +12255,7 @@ function EditGlowChrome({
13300
12255
  hideHandle = false
13301
12256
  }) {
13302
12257
  const GAP = SELECTION_CHROME_GAP2;
13303
- return /* @__PURE__ */ jsxs19(
12258
+ return /* @__PURE__ */ jsxs17(
13304
12259
  "div",
13305
12260
  {
13306
12261
  ref: elRef,
@@ -13315,7 +12270,7 @@ function EditGlowChrome({
13315
12270
  zIndex: 2147483646
13316
12271
  },
13317
12272
  children: [
13318
- /* @__PURE__ */ jsx32(
12273
+ /* @__PURE__ */ jsx30(
13319
12274
  "div",
13320
12275
  {
13321
12276
  style: {
@@ -13328,7 +12283,7 @@ function EditGlowChrome({
13328
12283
  }
13329
12284
  }
13330
12285
  ),
13331
- reorderHrefKey && !hideHandle && /* @__PURE__ */ jsx32(
12286
+ reorderHrefKey && !hideHandle && /* @__PURE__ */ jsx30(
13332
12287
  "div",
13333
12288
  {
13334
12289
  "data-ohw-drag-handle-container": "",
@@ -13340,7 +12295,7 @@ function EditGlowChrome({
13340
12295
  transform: "translate(calc(-100% - 7px), -50%)",
13341
12296
  pointerEvents: dragDisabled ? "none" : "auto"
13342
12297
  },
13343
- children: /* @__PURE__ */ jsx32(
12298
+ children: /* @__PURE__ */ jsx30(
13344
12299
  DragHandle,
13345
12300
  {
13346
12301
  "aria-label": `Reorder ${reorderHrefKey}`,
@@ -13550,7 +12505,7 @@ function FloatingToolbar({
13550
12505
  return () => ro.disconnect();
13551
12506
  }, [showEditLink, activeCommands]);
13552
12507
  const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
13553
- return /* @__PURE__ */ jsx32(
12508
+ return /* @__PURE__ */ jsx30(
13554
12509
  "div",
13555
12510
  {
13556
12511
  ref: setRefs,
@@ -13562,12 +12517,12 @@ function FloatingToolbar({
13562
12517
  zIndex: 2147483647,
13563
12518
  pointerEvents: "auto"
13564
12519
  },
13565
- children: /* @__PURE__ */ jsxs19(CustomToolbar, { children: [
13566
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs19(React11.Fragment, { children: [
13567
- gi > 0 && /* @__PURE__ */ jsx32(CustomToolbarDivider, {}),
12520
+ children: /* @__PURE__ */ jsxs17(CustomToolbar, { children: [
12521
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs17(React11.Fragment, { children: [
12522
+ gi > 0 && /* @__PURE__ */ jsx30(CustomToolbarDivider, {}),
13568
12523
  btns.map((btn) => {
13569
12524
  const isActive = activeCommands.has(btn.cmd);
13570
- return /* @__PURE__ */ jsx32(
12525
+ return /* @__PURE__ */ jsx30(
13571
12526
  CustomToolbarButton,
13572
12527
  {
13573
12528
  title: btn.title,
@@ -13576,7 +12531,7 @@ function FloatingToolbar({
13576
12531
  e.preventDefault();
13577
12532
  onCommand(btn.cmd);
13578
12533
  },
13579
- children: /* @__PURE__ */ jsx32(
12534
+ children: /* @__PURE__ */ jsx30(
13580
12535
  "svg",
13581
12536
  {
13582
12537
  width: "16",
@@ -13597,7 +12552,7 @@ function FloatingToolbar({
13597
12552
  );
13598
12553
  })
13599
12554
  ] }, gi)),
13600
- showEditLink ? /* @__PURE__ */ jsx32(
12555
+ showEditLink ? /* @__PURE__ */ jsx30(
13601
12556
  CustomToolbarButton,
13602
12557
  {
13603
12558
  type: "button",
@@ -13611,7 +12566,7 @@ function FloatingToolbar({
13611
12566
  e.preventDefault();
13612
12567
  e.stopPropagation();
13613
12568
  },
13614
- children: /* @__PURE__ */ jsx32(Link3, { className: "size-4 shrink-0", "aria-hidden": true })
12569
+ children: /* @__PURE__ */ jsx30(Link2, { className: "size-4 shrink-0", "aria-hidden": true })
13615
12570
  }
13616
12571
  ) : null
13617
12572
  ] })
@@ -13628,7 +12583,7 @@ function StateToggle({
13628
12583
  states,
13629
12584
  onStateChange
13630
12585
  }) {
13631
- return /* @__PURE__ */ jsx32(
12586
+ return /* @__PURE__ */ jsx30(
13632
12587
  ToggleGroup,
13633
12588
  {
13634
12589
  "data-ohw-state-toggle": "",
@@ -13642,12 +12597,11 @@ function StateToggle({
13642
12597
  left: rect.right - 8,
13643
12598
  transform: "translateX(-100%)"
13644
12599
  },
13645
- children: states.map((state) => /* @__PURE__ */ jsx32(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
12600
+ children: states.map((state) => /* @__PURE__ */ jsx30(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
13646
12601
  }
13647
12602
  );
13648
12603
  }
13649
12604
  var contentCache = /* @__PURE__ */ new Map();
13650
- var fetchedContentPaths = /* @__PURE__ */ new Set();
13651
12605
  function resolveSubdomain(subdomainFromQuery) {
13652
12606
  if (subdomainFromQuery) return subdomainFromQuery;
13653
12607
  if (typeof window !== "undefined") {
@@ -13670,8 +12624,8 @@ function OhhwellsBridge() {
13670
12624
  const router = useRouter3();
13671
12625
  const searchParams = useSearchParams();
13672
12626
  const isEditMode = isEditSessionActive();
13673
- const [bridgeRoot, setBridgeRoot] = useState11(null);
13674
- useEffect12(() => {
12627
+ const [bridgeRoot, setBridgeRoot] = useState10(null);
12628
+ useEffect11(() => {
13675
12629
  const figtreeFontId = "ohw-figtree-font";
13676
12630
  if (!document.getElementById(figtreeFontId)) {
13677
12631
  const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
@@ -13700,136 +12654,110 @@ function OhhwellsBridge() {
13700
12654
  const subdomain = resolveSubdomain(subdomainFromQuery);
13701
12655
  useLinkHrefGuardian(pathname, subdomain, isEditMode);
13702
12656
  useSavedLinkNavigation(isEditMode);
13703
- const postToParent2 = useCallback7((data) => {
12657
+ const postToParent2 = useCallback6((data) => {
13704
12658
  if (typeof window !== "undefined" && window.parent !== window) {
13705
12659
  window.parent.postMessage(data, "*");
13706
12660
  }
13707
12661
  }, []);
13708
- const [fetchState, setFetchState] = useState11("idle");
13709
- const autoSaveTimers = useRef9(/* @__PURE__ */ new Map());
13710
- const activeElRef = useRef9(null);
13711
- const pointerHeldRef = useRef9(false);
13712
- const selectedElRef = useRef9(null);
13713
- const selectedHrefKeyRef = useRef9(null);
13714
- const selectedFooterColAttrRef = useRef9(null);
13715
- const originalContentRef = useRef9(null);
13716
- const activeStateElRef = useRef9(null);
13717
- const parentScrollRef = useRef9(null);
13718
- const visibleViewportRef = useRef9(null);
13719
- const [dialogPortalContainer, setDialogPortalContainer] = useState11(null);
13720
- const attachVisibleViewport = useCallback7((node) => {
12662
+ const [fetchState, setFetchState] = useState10("idle");
12663
+ const autoSaveTimers = useRef8(/* @__PURE__ */ new Map());
12664
+ const activeElRef = useRef8(null);
12665
+ const pointerHeldRef = useRef8(false);
12666
+ const selectedElRef = useRef8(null);
12667
+ const selectedHrefKeyRef = useRef8(null);
12668
+ const selectedFooterColAttrRef = useRef8(null);
12669
+ const originalContentRef = useRef8(null);
12670
+ const activeStateElRef = useRef8(null);
12671
+ const parentScrollRef = useRef8(null);
12672
+ const visibleViewportRef = useRef8(null);
12673
+ const [dialogPortalContainer, setDialogPortalContainer] = useState10(null);
12674
+ const attachVisibleViewport = useCallback6((node) => {
13721
12675
  visibleViewportRef.current = node;
13722
12676
  setDialogPortalContainer(node);
13723
12677
  if (node) applyVisibleViewport(node, parentScrollRef.current);
13724
12678
  }, []);
13725
- const toolbarElRef = useRef9(null);
13726
- const glowElRef = useRef9(null);
13727
- const hoveredImageRef = useRef9(null);
13728
- const hoveredImageHasTextOverlapRef = useRef9(false);
13729
- const dragOverElRef = useRef9(null);
13730
- const [mediaHover, setMediaHover] = useState11(null);
13731
- const [carouselHover, setCarouselHover] = useState11(null);
13732
- const [uploadingRects, setUploadingRects] = useState11({});
13733
- const hoveredGapRef = useRef9(null);
13734
- const imageUnhoverTimerRef = useRef9(null);
13735
- const imageShowTimerRef = useRef9(null);
13736
- const editStylesRef = useRef9(null);
13737
- const activateRef = useRef9(() => {
13738
- });
13739
- const deactivateRef = useRef9(() => {
12679
+ const toolbarElRef = useRef8(null);
12680
+ const glowElRef = useRef8(null);
12681
+ const hoveredImageRef = useRef8(null);
12682
+ const hoveredImageHasTextOverlapRef = useRef8(false);
12683
+ const dragOverElRef = useRef8(null);
12684
+ const [mediaHover, setMediaHover] = useState10(null);
12685
+ const [carouselHover, setCarouselHover] = useState10(null);
12686
+ const [uploadingRects, setUploadingRects] = useState10({});
12687
+ const hoveredGapRef = useRef8(null);
12688
+ const imageUnhoverTimerRef = useRef8(null);
12689
+ const imageShowTimerRef = useRef8(null);
12690
+ const editStylesRef = useRef8(null);
12691
+ const activateRef = useRef8(() => {
13740
12692
  });
13741
- const selectRef = useRef9(() => {
12693
+ const deactivateRef = useRef8(() => {
13742
12694
  });
13743
- const selectFrameRef = useRef9(() => {
12695
+ const selectRef = useRef8(() => {
13744
12696
  });
13745
- const selectLogoRef = useRef9(() => {
12697
+ const selectFrameRef = useRef8(() => {
13746
12698
  });
13747
- const openLogoSizePanelRef = useRef9(() => {
12699
+ const deselectRef = useRef8(() => {
13748
12700
  });
13749
- const deselectRef = useRef9(() => {
12701
+ const reselectNavigationItemRef = useRef8(() => {
13750
12702
  });
13751
- const closeFloatingPanelOnlyRef = useRef9(() => {
12703
+ const commitNavigationTextEditRef = useRef8(() => {
13752
12704
  });
13753
- const reselectNavigationItemRef = useRef9(() => {
12705
+ const handleDeleteSelectedRef = useRef8(() => false);
12706
+ const runPendingDeleteUndoRef = useRef8(() => false);
12707
+ const isFooterFrameSelectionRef = useRef8(false);
12708
+ const refreshActiveCommandsRef = useRef8(() => {
13754
12709
  });
13755
- const commitNavigationTextEditRef = useRef9(() => {
13756
- });
13757
- const handleDeleteSelectedRef = useRef9(() => false);
13758
- const runPendingDeleteUndoRef = useRef9(() => false);
13759
- const isFooterFrameSelectionRef = useRef9(false);
13760
- const refreshActiveCommandsRef = useRef9(() => {
13761
- });
13762
- const postToParentRef = useRef9(postToParent2);
12710
+ const postToParentRef = useRef8(postToParent2);
13763
12711
  postToParentRef.current = postToParent2;
13764
- const aiSectionApiRef = useRef9(null);
13765
- const sectionsLoadedRef = useRef9(false);
13766
- const pendingScheduleConfigRequests = useRef9([]);
13767
- const [toolbarRect, setToolbarRect] = useState11(null);
13768
- const [toolbarVariant, setToolbarVariant] = useState11("none");
13769
- const toolbarVariantRef = useRef9("none");
12712
+ const aiSectionApiRef = useRef8(null);
12713
+ const sectionsLoadedRef = useRef8(false);
12714
+ const pendingScheduleConfigRequests = useRef8([]);
12715
+ const [toolbarRect, setToolbarRect] = useState10(null);
12716
+ const [toolbarVariant, setToolbarVariant] = useState10("none");
12717
+ const toolbarVariantRef = useRef8("none");
13770
12718
  toolbarVariantRef.current = toolbarVariant;
13771
- const [selectedIsCta, setSelectedIsCta] = useState11(false);
13772
- const [selectedIsSocial, setSelectedIsSocial] = useState11(false);
13773
- const [selectedIsSocialsRow, setSelectedIsSocialsRow] = useState11(false);
13774
- const [reorderHrefKey, setReorderHrefKey] = useState11(null);
13775
- const [reorderDragDisabled, setReorderDragDisabled] = useState11(false);
13776
- const [toggleState, setToggleState] = useState11(null);
13777
- const [maxBadge, setMaxBadge] = useState11(null);
13778
- const [activeCommands, setActiveCommands] = useState11(/* @__PURE__ */ new Set());
13779
- const [sectionGap, setSectionGap] = useState11(null);
13780
- const [toolbarShowEditLink, setToolbarShowEditLink] = useState11(false);
13781
- const hoveredNavContainerRef = useRef9(null);
13782
- const [hoveredNavContainerRect, setHoveredNavContainerRect] = useState11(null);
13783
- const hoveredItemElRef = useRef9(null);
13784
- const [hoveredItemRect, setHoveredItemRect] = useState11(null);
13785
- const siblingHintElRef = useRef9(null);
13786
- const [siblingHintRect, setSiblingHintRect] = useState11(null);
13787
- const [siblingHintRects, setSiblingHintRects] = useState11([]);
13788
- const [isItemDragging, setIsItemDragging] = useState11(false);
13789
- const [isFooterFrameSelection, setIsFooterFrameSelection] = useState11(false);
12719
+ const [selectedIsCta, setSelectedIsCta] = useState10(false);
12720
+ const [reorderHrefKey, setReorderHrefKey] = useState10(null);
12721
+ const [reorderDragDisabled, setReorderDragDisabled] = useState10(false);
12722
+ const [toggleState, setToggleState] = useState10(null);
12723
+ const [maxBadge, setMaxBadge] = useState10(null);
12724
+ const [activeCommands, setActiveCommands] = useState10(/* @__PURE__ */ new Set());
12725
+ const [sectionGap, setSectionGap] = useState10(null);
12726
+ const [toolbarShowEditLink, setToolbarShowEditLink] = useState10(false);
12727
+ const hoveredNavContainerRef = useRef8(null);
12728
+ const [hoveredNavContainerRect, setHoveredNavContainerRect] = useState10(null);
12729
+ const hoveredItemElRef = useRef8(null);
12730
+ const [hoveredItemRect, setHoveredItemRect] = useState10(null);
12731
+ const siblingHintElRef = useRef8(null);
12732
+ const [siblingHintRect, setSiblingHintRect] = useState10(null);
12733
+ const [siblingHintRects, setSiblingHintRects] = useState10([]);
12734
+ const [isItemDragging, setIsItemDragging] = useState10(false);
12735
+ const [isFooterFrameSelection, setIsFooterFrameSelection] = useState10(false);
13790
12736
  isFooterFrameSelectionRef.current = isFooterFrameSelection;
13791
- const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = useState11(null);
13792
- const [footerHeadingVisible, setFooterHeadingVisible] = useState11(null);
13793
- const footerDragRef = useRef9(null);
13794
- const [footerDropSlots, setFooterDropSlots] = useState11([]);
13795
- const [activeFooterDropIndex, setActiveFooterDropIndex] = useState11(null);
13796
- const [draggedItemRect, setDraggedItemRect] = useState11(null);
13797
- const footerPointerDragRef = useRef9(null);
13798
- const suppressNextClickRef = useRef9(false);
13799
- const suppressClickUntilRef = useRef9(0);
13800
- const [linkPopover, setLinkPopover] = useState11(null);
13801
- const linkPopoverSessionRef = useRef9(null);
13802
- const addNavAfterAnchorRef = useRef9(null);
13803
- const editContentRef = useRef9({});
13804
- const aiSectionsRef = useRef9("");
13805
- const pendingDeleteUndoRef = useRef9(null);
13806
- const [floatingPanel, setFloatingPanel] = useState11(null);
13807
- const floatingPanelOpenRef = useRef9(false);
13808
- const setFloatingPanelRef = useRef9(setFloatingPanel);
13809
- const [floatingPanelPos, setFloatingPanelPos] = useState11(null);
13810
- const [logoSizeDraft, setLogoSizeDraft] = useState11(null);
13811
- const [editorViewport, setEditorViewport] = useState11("desktop");
13812
- const [parentScrollSnap, setParentScrollSnap] = useState11(null);
13813
- const [sitePages, setSitePages] = useState11([]);
13814
- const [sectionsByPath, setSectionsByPath] = useState11({});
13815
- const sectionsPrefetchGenRef = useRef9(0);
13816
- const setLinkPopoverRef = useRef9(setLinkPopover);
13817
- const linkPopoverPanelRef = useRef9(null);
13818
- const linkPopoverOpenRef = useRef9(false);
13819
- const linkPopoverGraceUntilRef = useRef9(0);
12737
+ const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = useState10(null);
12738
+ const [footerHeadingVisible, setFooterHeadingVisible] = useState10(null);
12739
+ const footerDragRef = useRef8(null);
12740
+ const [footerDropSlots, setFooterDropSlots] = useState10([]);
12741
+ const [activeFooterDropIndex, setActiveFooterDropIndex] = useState10(null);
12742
+ const [draggedItemRect, setDraggedItemRect] = useState10(null);
12743
+ const footerPointerDragRef = useRef8(null);
12744
+ const suppressNextClickRef = useRef8(false);
12745
+ const suppressClickUntilRef = useRef8(0);
12746
+ const [linkPopover, setLinkPopover] = useState10(null);
12747
+ const linkPopoverSessionRef = useRef8(null);
12748
+ const addNavAfterAnchorRef = useRef8(null);
12749
+ const editContentRef = useRef8({});
12750
+ const aiSectionsRef = useRef8("");
12751
+ const pendingDeleteUndoRef = useRef8(null);
12752
+ const [sitePages, setSitePages] = useState10([]);
12753
+ const [sectionsByPath, setSectionsByPath] = useState10({});
12754
+ const sectionsPrefetchGenRef = useRef8(0);
12755
+ const setLinkPopoverRef = useRef8(setLinkPopover);
12756
+ const linkPopoverPanelRef = useRef8(null);
12757
+ const linkPopoverOpenRef = useRef8(false);
12758
+ const linkPopoverGraceUntilRef = useRef8(0);
13820
12759
  setLinkPopoverRef.current = setLinkPopover;
13821
- setFloatingPanelRef.current = setFloatingPanel;
13822
12760
  linkPopoverSessionRef.current = linkPopover;
13823
- floatingPanelOpenRef.current = Boolean(floatingPanel);
13824
- useEffect12(() => {
13825
- const syncViewport = () => {
13826
- const next = window.innerWidth <= 480 ? "mobile" : "desktop";
13827
- setEditorViewport((prev) => prev === next ? prev : next);
13828
- };
13829
- syncViewport();
13830
- window.addEventListener("resize", syncViewport);
13831
- return () => window.removeEventListener("resize", syncViewport);
13832
- }, []);
13833
12761
  const {
13834
12762
  navDragRef,
13835
12763
  navDropSlots,
@@ -13865,7 +12793,7 @@ function OhhwellsBridge() {
13865
12793
  const bumpLinkPopoverGrace = () => {
13866
12794
  linkPopoverGraceUntilRef.current = Date.now() + 350;
13867
12795
  };
13868
- const runSectionsPrefetch = useCallback7((pages) => {
12796
+ const runSectionsPrefetch = useCallback6((pages) => {
13869
12797
  if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
13870
12798
  const gen = ++sectionsPrefetchGenRef.current;
13871
12799
  const paths = pages.map((p) => p.path);
@@ -13884,9 +12812,9 @@ function OhhwellsBridge() {
13884
12812
  );
13885
12813
  });
13886
12814
  }, [isEditMode, pathname]);
13887
- const runSectionsPrefetchRef = useRef9(runSectionsPrefetch);
12815
+ const runSectionsPrefetchRef = useRef8(runSectionsPrefetch);
13888
12816
  runSectionsPrefetchRef.current = runSectionsPrefetch;
13889
- useEffect12(() => {
12817
+ useEffect11(() => {
13890
12818
  if (!linkPopover) {
13891
12819
  document.documentElement.removeAttribute("data-ohw-link-popover-open");
13892
12820
  return;
@@ -13914,7 +12842,7 @@ function OhhwellsBridge() {
13914
12842
  document.documentElement.removeAttribute("data-ohw-link-popover-open");
13915
12843
  };
13916
12844
  }, [linkPopover, postToParent2]);
13917
- useEffect12(() => {
12845
+ useEffect11(() => {
13918
12846
  if (!isEditMode) return;
13919
12847
  const useFixtures = shouldUseDevFixtures();
13920
12848
  if (useFixtures) {
@@ -13938,14 +12866,14 @@ function OhhwellsBridge() {
13938
12866
  if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
13939
12867
  return () => window.removeEventListener("message", onSitePages);
13940
12868
  }, [isEditMode, postToParent2]);
13941
- useEffect12(() => {
12869
+ useEffect11(() => {
13942
12870
  if (!isEditMode || shouldUseDevFixtures()) return;
13943
12871
  void loadAllSectionsManifest().then((manifest) => {
13944
12872
  if (Object.keys(manifest).length === 0) return;
13945
12873
  setSectionsByPath((prev) => ({ ...manifest, ...prev }));
13946
12874
  });
13947
12875
  }, [isEditMode]);
13948
- useEffect12(() => {
12876
+ useEffect11(() => {
13949
12877
  const update = () => {
13950
12878
  const el = activeElRef.current ?? selectedElRef.current;
13951
12879
  if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
@@ -13969,10 +12897,10 @@ function OhhwellsBridge() {
13969
12897
  vvp.removeEventListener("resize", update);
13970
12898
  };
13971
12899
  }, []);
13972
- const refreshStateRules = useCallback7(() => {
12900
+ const refreshStateRules = useCallback6(() => {
13973
12901
  editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
13974
12902
  }, []);
13975
- const processConfigRequest = useCallback7((insertAfterVal) => {
12903
+ const processConfigRequest = useCallback6((insertAfterVal) => {
13976
12904
  const tracker = getSectionsTracker();
13977
12905
  let entries = [];
13978
12906
  try {
@@ -13995,7 +12923,7 @@ function OhhwellsBridge() {
13995
12923
  }
13996
12924
  window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
13997
12925
  }, [isEditMode]);
13998
- const deactivate = useCallback7(() => {
12926
+ const deactivate = useCallback6(() => {
13999
12927
  const el = activeElRef.current;
14000
12928
  if (!el) return;
14001
12929
  const key = el.dataset.ohwKey;
@@ -14028,19 +12956,17 @@ function OhhwellsBridge() {
14028
12956
  setToolbarShowEditLink(false);
14029
12957
  postToParent2({ type: "ow:exit-edit" });
14030
12958
  }, [postToParent2]);
14031
- const clearSelectedAttr = useCallback7(() => {
12959
+ const clearSelectedAttr = useCallback6(() => {
14032
12960
  document.querySelectorAll("[data-ohw-selected]").forEach((el) => {
14033
12961
  el.removeAttribute("data-ohw-selected");
14034
12962
  });
14035
12963
  }, []);
14036
- const deselect = useCallback7(() => {
12964
+ const deselect = useCallback6(() => {
14037
12965
  clearSelectedAttr();
14038
12966
  selectedElRef.current = null;
14039
12967
  selectedHrefKeyRef.current = null;
14040
12968
  selectedFooterColAttrRef.current = null;
14041
12969
  setSelectedIsCta(false);
14042
- setSelectedIsSocial(false);
14043
- setSelectedIsSocialsRow(false);
14044
12970
  setReorderHrefKey(null);
14045
12971
  setReorderDragDisabled(false);
14046
12972
  setIsFooterFrameSelection(false);
@@ -14052,21 +12978,17 @@ function OhhwellsBridge() {
14052
12978
  setIsItemDragging(false);
14053
12979
  hoveredNavContainerRef.current = null;
14054
12980
  setHoveredNavContainerRect(null);
14055
- hoveredItemElRef.current = null;
14056
- setHoveredItemRect(null);
14057
- setFloatingPanel(null);
14058
- setLogoSizeDraft(null);
14059
12981
  if (!activeElRef.current) {
14060
12982
  setNavGroupForceOpen(null, false);
14061
12983
  setToolbarRect(null);
14062
12984
  setToolbarVariant("none");
14063
12985
  }
14064
12986
  }, [clearSelectedAttr]);
14065
- const markSelected = useCallback7((el) => {
12987
+ const markSelected = useCallback6((el) => {
14066
12988
  clearSelectedAttr();
14067
12989
  el.setAttribute("data-ohw-selected", "");
14068
12990
  }, [clearSelectedAttr]);
14069
- const resolveHrefKeyElement = useCallback7((hrefKey) => {
12991
+ const resolveHrefKeyElement = useCallback6((hrefKey) => {
14070
12992
  if (isFooterHrefKey(hrefKey)) {
14071
12993
  return document.querySelector(
14072
12994
  `footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
@@ -14081,7 +13003,7 @@ function OhhwellsBridge() {
14081
13003
  `[data-ohw-href-key="${CSS.escape(hrefKey)}"]`
14082
13004
  );
14083
13005
  }, []);
14084
- const resyncSelectedNavigationItem = useCallback7(() => {
13006
+ const resyncSelectedNavigationItem = useCallback6(() => {
14085
13007
  const hrefKey = selectedHrefKeyRef.current;
14086
13008
  if (hrefKey) {
14087
13009
  const link = resolveHrefKeyElement(hrefKey);
@@ -14119,14 +13041,12 @@ function OhhwellsBridge() {
14119
13041
  );
14120
13042
  }
14121
13043
  }, [resolveHrefKeyElement]);
14122
- const reselectNavigationItem = useCallback7((navAnchor) => {
13044
+ const reselectNavigationItem = useCallback6((navAnchor) => {
14123
13045
  selectedElRef.current = navAnchor;
14124
13046
  selectedHrefKeyRef.current = navAnchor.getAttribute("data-ohw-href-key");
14125
13047
  selectedFooterColAttrRef.current = null;
14126
13048
  markSelected(navAnchor);
14127
13049
  setSelectedIsCta(isCtaButton(navAnchor));
14128
- setSelectedIsSocial(Boolean(getSocialItem(navAnchor)));
14129
- setSelectedIsSocialsRow(false);
14130
13050
  const isDropdownTrigger = !isNestedNavChild(navAnchor) && (navItemHasDropdownChildren(navAnchor) || navItemOwnsDropdownPanel(navAnchor));
14131
13051
  if (isNestedNavChild(navAnchor)) {
14132
13052
  setNavGroupForceOpen(navAnchor, true);
@@ -14150,7 +13070,7 @@ function OhhwellsBridge() {
14150
13070
  setToolbarShowEditLink(false);
14151
13071
  setActiveCommands(/* @__PURE__ */ new Set());
14152
13072
  }, [markSelected]);
14153
- const commitNavigationTextEdit = useCallback7((navAnchor) => {
13073
+ const commitNavigationTextEdit = useCallback6((navAnchor) => {
14154
13074
  const el = activeElRef.current;
14155
13075
  if (!el) return;
14156
13076
  const key = el.dataset.ohwKey;
@@ -14177,7 +13097,7 @@ function OhhwellsBridge() {
14177
13097
  postToParent2({ type: "ow:exit-edit" });
14178
13098
  reselectNavigationItem(navAnchor);
14179
13099
  }, [postToParent2, reselectNavigationItem]);
14180
- const handleAddTopLevelNavItem = useCallback7(() => {
13100
+ const handleAddTopLevelNavItem = useCallback6(() => {
14181
13101
  const items = listNavbarRootItems();
14182
13102
  addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
14183
13103
  deselectRef.current();
@@ -14189,7 +13109,7 @@ function OhhwellsBridge() {
14189
13109
  intent: "add-nav"
14190
13110
  });
14191
13111
  }, []);
14192
- const maybeWarnNavLinkDropdownConflict = useCallback7(
13112
+ const maybeWarnNavLinkDropdownConflict = useCallback6(
14193
13113
  (anchor) => {
14194
13114
  if (!isNavbarHrefKey(anchor.getAttribute("data-ohw-href-key"))) return;
14195
13115
  if (!navDropdownsOpenOnClick()) return;
@@ -14202,7 +13122,7 @@ function OhhwellsBridge() {
14202
13122
  },
14203
13123
  [postToParent2]
14204
13124
  );
14205
- const handleNavDropdownOpenChange = useCallback7((open) => {
13125
+ const handleNavDropdownOpenChange = useCallback6((open) => {
14206
13126
  const selected = selectedElRef.current;
14207
13127
  if (!selected || !isNavigationItem2(selected)) return;
14208
13128
  setNavGroupForceOpen(selected, open);
@@ -14214,7 +13134,7 @@ function OhhwellsBridge() {
14214
13134
  }
14215
13135
  });
14216
13136
  }, []);
14217
- const handleFooterHeadingVisibleChange = useCallback7(
13137
+ const handleFooterHeadingVisibleChange = useCallback6(
14218
13138
  (visible) => {
14219
13139
  const selected = selectedElRef.current;
14220
13140
  if (!selected || !isFooterFrameSelectionRef.current) return;
@@ -14238,7 +13158,7 @@ function OhhwellsBridge() {
14238
13158
  },
14239
13159
  [postToParent2]
14240
13160
  );
14241
- const enterEditOnNewItem = useCallback7((anchor) => {
13161
+ const enterEditOnNewItem = useCallback6((anchor) => {
14242
13162
  const label = anchor.querySelector('[data-ohw-editable="text"]');
14243
13163
  if (!label) {
14244
13164
  selectRef.current(anchor);
@@ -14247,30 +13167,9 @@ function OhhwellsBridge() {
14247
13167
  setNavGroupForceOpen(anchor, true);
14248
13168
  activateRef.current(label);
14249
13169
  }, []);
14250
- const handleAddChildItem = useCallback7(() => {
13170
+ const handleAddChildItem = useCallback6(() => {
14251
13171
  const selected = selectedElRef.current;
14252
13172
  if (!selected) return;
14253
- const socialsRow = isSocialsRow(selected) ? selected : findSocialsRow(selected);
14254
- if (socialsRow) {
14255
- const after = getSocialItem(selected);
14256
- const result2 = insertSocialItem(socialsRow, after, editContentRef.current);
14257
- if (!result2) return;
14258
- const orderJson = JSON.stringify(result2.order);
14259
- editContentRef.current = { ...editContentRef.current, [SOCIALS_ORDER_KEY]: orderJson };
14260
- postToParent2({ type: "ow:change", nodes: [{ key: SOCIALS_ORDER_KEY, text: orderJson }] });
14261
- postToParentRef.current({
14262
- type: "ow:social-pick",
14263
- hrefKey: result2.hrefKey,
14264
- iconKey: result2.iconKey,
14265
- url: "",
14266
- iconStyle: detectIconStyle(result2.item),
14267
- platformId: "",
14268
- // Lets the editor undo the insert if the dialog is dismissed: an item that was never given
14269
- // an address should not survive a Cancel.
14270
- isNew: true
14271
- });
14272
- return;
14273
- }
14274
13173
  if (toolbarVariantRef.current === "select-frame" && isFooterFrameSelection) {
14275
13174
  if (!selected.hasAttribute("data-ohw-footer-col") && !selected.closest("[data-ohw-footer-col]")) {
14276
13175
  }
@@ -14344,7 +13243,7 @@ function OhhwellsBridge() {
14344
13243
  enterEditOnNewItem(result.anchor);
14345
13244
  });
14346
13245
  }, [enterEditOnNewItem, isFooterFrameSelection, maybeWarnNavLinkDropdownConflict, postToParent2]);
14347
- const handleAddFooterColumn = useCallback7(() => {
13246
+ const handleAddFooterColumn = useCallback6(() => {
14348
13247
  if (!canAddFooterColumn()) {
14349
13248
  postToParent2({
14350
13249
  type: "ow:toast",
@@ -14365,7 +13264,7 @@ function OhhwellsBridge() {
14365
13264
  selectRef.current(result.firstLink);
14366
13265
  });
14367
13266
  }, [postToParent2]);
14368
- const clearFooterDragVisuals = useCallback7(() => {
13267
+ const clearFooterDragVisuals = useCallback6(() => {
14369
13268
  footerDragRef.current = null;
14370
13269
  setSiblingHintRects([]);
14371
13270
  setFooterDropSlots([]);
@@ -14374,7 +13273,7 @@ function OhhwellsBridge() {
14374
13273
  setIsItemDragging(false);
14375
13274
  unlockFooterDragInteraction();
14376
13275
  }, []);
14377
- const refreshFooterDragVisuals = useCallback7((session, activeSlot, clientX, clientY) => {
13276
+ const refreshFooterDragVisuals = useCallback6((session, activeSlot, clientX, clientY) => {
14378
13277
  const dragged = session.draggedEl;
14379
13278
  setDraggedItemRect(dragged.getBoundingClientRect());
14380
13279
  if (typeof clientX === "number" && typeof clientY === "number") {
@@ -14383,13 +13282,6 @@ function OhhwellsBridge() {
14383
13282
  }
14384
13283
  session.activeSlot = activeSlot;
14385
13284
  setSiblingHintRects([]);
14386
- if (session.kind === "social") {
14387
- const slots2 = session.hrefKey ? buildSocialDropSlotsForKey(session.hrefKey) : [];
14388
- setFooterDropSlots(slots2);
14389
- const activeIdx2 = activeSlot ? slots2.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
14390
- setActiveFooterDropIndex(activeIdx2 >= 0 ? activeIdx2 : null);
14391
- return;
14392
- }
14393
13285
  if (session.kind === "link") {
14394
13286
  const columns = listFooterColumns();
14395
13287
  const slots2 = [];
@@ -14406,13 +13298,13 @@ function OhhwellsBridge() {
14406
13298
  const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
14407
13299
  setActiveFooterDropIndex(activeIdx >= 0 ? activeIdx : null);
14408
13300
  }, []);
14409
- const refreshFooterDragVisualsRef = useRef9(refreshFooterDragVisuals);
13301
+ const refreshFooterDragVisualsRef = useRef8(refreshFooterDragVisuals);
14410
13302
  refreshFooterDragVisualsRef.current = refreshFooterDragVisuals;
14411
- const commitFooterDragRef = useRef9(() => {
13303
+ const commitFooterDragRef = useRef8(() => {
14412
13304
  });
14413
- const beginFooterDragRef = useRef9(() => {
13305
+ const beginFooterDragRef = useRef8(() => {
14414
13306
  });
14415
- const beginFooterDrag = useCallback7(
13307
+ const beginFooterDrag = useCallback6(
14416
13308
  (session) => {
14417
13309
  const rect = session.draggedEl.getBoundingClientRect();
14418
13310
  session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
@@ -14426,13 +13318,13 @@ function OhhwellsBridge() {
14426
13318
  if (session.wasSelected && selectedElRef.current === session.draggedEl) {
14427
13319
  setToolbarRect(rect);
14428
13320
  }
14429
- const initialSlot = session.kind === "social" && session.hrefKey ? hitTestSocialDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
13321
+ const initialSlot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
14430
13322
  refreshFooterDragVisuals(session, initialSlot, session.lastClientX, session.lastClientY);
14431
13323
  },
14432
13324
  [refreshFooterDragVisuals]
14433
13325
  );
14434
13326
  beginFooterDragRef.current = beginFooterDrag;
14435
- const commitFooterDrag = useCallback7(
13327
+ const commitFooterDrag = useCallback6(
14436
13328
  (clientX, clientY) => {
14437
13329
  const session = footerDragRef.current;
14438
13330
  if (!session) {
@@ -14442,11 +13334,8 @@ function OhhwellsBridge() {
14442
13334
  const x = typeof clientX === "number" && (clientX !== 0 || clientY !== 0) ? clientX : session.lastClientX;
14443
13335
  const y = typeof clientY === "number" && (clientX !== 0 || clientY !== 0) ? clientY : session.lastClientY;
14444
13336
  let nextOrder = null;
14445
- let nextSocialsOrder = null;
14446
- const slot = session.activeSlot ?? (session.kind === "social" && session.hrefKey ? hitTestSocialDropSlot(x, y, session.hrefKey) : session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(x, y, session.hrefKey) : session.kind === "column" ? hitTestColumnDropSlot(x, y) : null);
14447
- if (session.kind === "social" && session.hrefKey && slot) {
14448
- nextSocialsOrder = planSocialMove(session.hrefKey, slot.insertIndex);
14449
- } else if (session.kind === "link" && session.hrefKey && slot) {
13337
+ const slot = session.activeSlot ?? (session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(x, y, session.hrefKey) : session.kind === "column" ? hitTestColumnDropSlot(x, y) : null);
13338
+ if (session.kind === "link" && session.hrefKey && slot) {
14450
13339
  nextOrder = planFooterLinkMove(session.hrefKey, slot.columnIndex, slot.insertIndex);
14451
13340
  } else if (session.kind === "column" && slot) {
14452
13341
  nextOrder = planFooterColumnMove(session.sourceColumnIndex, slot.insertIndex);
@@ -14504,27 +13393,6 @@ function OhhwellsBridge() {
14504
13393
  }
14505
13394
  deselectRef.current();
14506
13395
  };
14507
- if (nextSocialsOrder) {
14508
- const orderJson = JSON.stringify(nextSocialsOrder);
14509
- editContentRef.current = { ...editContentRef.current, [SOCIALS_ORDER_KEY]: orderJson };
14510
- applySocialsOrder(nextSocialsOrder);
14511
- postToParentRef.current({
14512
- type: "ow:change",
14513
- nodes: [{ key: SOCIALS_ORDER_KEY, text: orderJson }]
14514
- });
14515
- applySelectionAfterDrop();
14516
- clearFooterDragVisuals();
14517
- const reapply = nextSocialsOrder;
14518
- requestAnimationFrame(() => {
14519
- if (editContentRef.current[SOCIALS_ORDER_KEY] === orderJson) applySocialsOrder(reapply);
14520
- applySelectionAfterDrop();
14521
- requestAnimationFrame(() => {
14522
- if (editContentRef.current[SOCIALS_ORDER_KEY] === orderJson) applySocialsOrder(reapply);
14523
- resyncSelectedNavigationItem();
14524
- });
14525
- });
14526
- return;
14527
- }
14528
13396
  if (nextOrder) {
14529
13397
  const orderJson = JSON.stringify(nextOrder);
14530
13398
  editContentRef.current = {
@@ -14560,25 +13428,10 @@ function OhhwellsBridge() {
14560
13428
  [clearFooterDragVisuals, resolveHrefKeyElement, resyncSelectedNavigationItem]
14561
13429
  );
14562
13430
  commitFooterDragRef.current = commitFooterDrag;
14563
- const startFooterLinkDrag = useCallback7(
13431
+ const startFooterLinkDrag = useCallback6(
14564
13432
  (anchor, clientX, clientY, wasSelected) => {
14565
13433
  const hrefKey = anchor.getAttribute("data-ohw-href-key");
14566
- if (!hrefKey) return false;
14567
- if (getSocialItem(anchor)) {
14568
- beginFooterDrag({
14569
- kind: "social",
14570
- hrefKey,
14571
- columnEl: null,
14572
- sourceColumnIndex: 0,
14573
- wasSelected,
14574
- draggedEl: anchor,
14575
- lastClientX: clientX,
14576
- lastClientY: clientY,
14577
- activeSlot: null
14578
- });
14579
- return true;
14580
- }
14581
- if (!isFooterHrefKey(hrefKey)) return false;
13434
+ if (!hrefKey || !isFooterHrefKey(hrefKey)) return false;
14582
13435
  const column = findFooterColumnForLink(anchor);
14583
13436
  const columns = listFooterColumns();
14584
13437
  beginFooterDrag({
@@ -14596,7 +13449,7 @@ function OhhwellsBridge() {
14596
13449
  },
14597
13450
  [beginFooterDrag]
14598
13451
  );
14599
- const startFooterColumnDrag = useCallback7(
13452
+ const startFooterColumnDrag = useCallback6(
14600
13453
  (columnEl, clientX, clientY, wasSelected) => {
14601
13454
  const columns = listFooterColumns();
14602
13455
  const idx = columns.indexOf(columnEl);
@@ -14616,7 +13469,7 @@ function OhhwellsBridge() {
14616
13469
  },
14617
13470
  [beginFooterDrag]
14618
13471
  );
14619
- const handleItemDragStart = useCallback7(
13472
+ const handleItemDragStart = useCallback6(
14620
13473
  (e) => {
14621
13474
  const selected = selectedElRef.current;
14622
13475
  if (!selected) {
@@ -14636,7 +13489,7 @@ function OhhwellsBridge() {
14636
13489
  },
14637
13490
  [startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag]
14638
13491
  );
14639
- const handleItemDragEnd = useCallback7(
13492
+ const handleItemDragEnd = useCallback6(
14640
13493
  (e) => {
14641
13494
  if (footerDragRef.current) {
14642
13495
  const x = e?.clientX;
@@ -14662,7 +13515,7 @@ function OhhwellsBridge() {
14662
13515
  },
14663
13516
  [commitFooterDrag, commitNavDrag, navDragRef]
14664
13517
  );
14665
- const handleItemChromePointerDown = useCallback7((e) => {
13518
+ const handleItemChromePointerDown = useCallback6((e) => {
14666
13519
  if (e.button !== 0) return;
14667
13520
  const selected = selectedElRef.current;
14668
13521
  if (!selected) return;
@@ -14693,7 +13546,7 @@ function OhhwellsBridge() {
14693
13546
  }
14694
13547
  if (armNavPressFromChrome(selected, e.clientX, e.clientY, e.pointerId)) return;
14695
13548
  }, [armNavPressFromChrome]);
14696
- const handleItemChromeClick = useCallback7((clientX, clientY) => {
13549
+ const handleItemChromeClick = useCallback6((clientX, clientY) => {
14697
13550
  if (suppressNextClickRef.current || Date.now() < suppressClickUntilRef.current) {
14698
13551
  suppressNextClickRef.current = false;
14699
13552
  return;
@@ -14706,7 +13559,7 @@ function OhhwellsBridge() {
14706
13559
  }, []);
14707
13560
  reselectNavigationItemRef.current = reselectNavigationItem;
14708
13561
  commitNavigationTextEditRef.current = commitNavigationTextEdit;
14709
- const select = useCallback7((anchor) => {
13562
+ const select = useCallback6((anchor) => {
14710
13563
  if (!isNavigationItem2(anchor)) return;
14711
13564
  if (activeElRef.current) deactivate();
14712
13565
  aiSectionApiRef.current?.selectFromElement(anchor);
@@ -14715,8 +13568,6 @@ function OhhwellsBridge() {
14715
13568
  selectedFooterColAttrRef.current = null;
14716
13569
  markSelected(anchor);
14717
13570
  setSelectedIsCta(isCtaButton(anchor));
14718
- setSelectedIsSocial(Boolean(getSocialItem(anchor)));
14719
- setSelectedIsSocialsRow(false);
14720
13571
  clearHrefKeyHover(anchor);
14721
13572
  const isDropdownTrigger = !isNestedNavChild(anchor) && (navItemHasDropdownChildren(anchor) || navItemOwnsDropdownPanel(anchor));
14722
13573
  if (isNestedNavChild(anchor)) {
@@ -14746,10 +13597,8 @@ function OhhwellsBridge() {
14746
13597
  setToolbarRect(anchor.getBoundingClientRect());
14747
13598
  setToolbarShowEditLink(false);
14748
13599
  setActiveCommands(/* @__PURE__ */ new Set());
14749
- setFloatingPanel(null);
14750
- setLogoSizeDraft(null);
14751
13600
  }, [deactivate, markSelected]);
14752
- const selectFrame = useCallback7((el) => {
13601
+ const selectFrame = useCallback6((el) => {
14753
13602
  if (!isNavigationContainer(el)) return;
14754
13603
  if (activeElRef.current) deactivate();
14755
13604
  aiSectionApiRef.current?.selectFromElement(el);
@@ -14759,8 +13608,6 @@ function OhhwellsBridge() {
14759
13608
  selectedFooterColAttrRef.current = isFooterColumn ? el.getAttribute("data-ohw-footer-col") ?? String(listFooterColumns().indexOf(el)) : null;
14760
13609
  markSelected(el);
14761
13610
  setSelectedIsCta(false);
14762
- setSelectedIsSocial(false);
14763
- setSelectedIsSocialsRow(isSocialsRow(el));
14764
13611
  clearHrefKeyHover(el);
14765
13612
  setNavGroupForceOpen(null, false);
14766
13613
  hoveredNavContainerRef.current = null;
@@ -14797,112 +13644,14 @@ function OhhwellsBridge() {
14797
13644
  setToolbarRect(el.getBoundingClientRect());
14798
13645
  setToolbarShowEditLink(false);
14799
13646
  setActiveCommands(/* @__PURE__ */ new Set());
14800
- setFloatingPanel(null);
14801
- setLogoSizeDraft(null);
14802
13647
  }, [deactivate, markSelected, postToParent2]);
14803
- const selectLogo = useCallback7(
14804
- (logoEl) => {
14805
- if (activeElRef.current) deactivate();
14806
- selectedElRef.current = logoEl;
14807
- selectedHrefKeyRef.current = null;
14808
- selectedFooterColAttrRef.current = null;
14809
- markSelected(logoEl);
14810
- setSelectedIsCta(false);
14811
- setSelectedIsSocial(false);
14812
- setSelectedIsSocialsRow(false);
14813
- setSelectedIsSocialsRow(false);
14814
- clearHrefKeyHover(logoEl);
14815
- hoveredNavContainerRef.current = null;
14816
- setHoveredNavContainerRect(null);
14817
- setHoveredItemRect(null);
14818
- hoveredItemElRef.current = null;
14819
- siblingHintElRef.current = null;
14820
- setSiblingHintRect(null);
14821
- setSiblingHintRects([]);
14822
- setIsItemDragging(false);
14823
- setReorderHrefKey(null);
14824
- setReorderDragDisabled(false);
14825
- setIsFooterFrameSelection(false);
14826
- setToolbarVariant("logo");
14827
- setToolbarRect(getLogoInteractionRect(logoEl));
14828
- setToolbarShowEditLink(false);
14829
- setActiveCommands(/* @__PURE__ */ new Set());
14830
- },
14831
- [deactivate, markSelected]
14832
- );
14833
- const openLogoSizePanel = useCallback7((logoEl) => {
14834
- const placement = getLogoPlacement(logoEl);
14835
- const draft = readLogoSizeState(editContentRef.current, placement);
14836
- setLogoSizeDraft(draft);
14837
- setParentScrollSnap(parentScrollRef.current);
14838
- setFloatingPanel({
14839
- key: `logo-size:${placement}`,
14840
- title: "Logo",
14841
- context: placement === "navbar" ? "Navbar" : "Footer",
14842
- kind: "logo-size",
14843
- placement
14844
- });
14845
- }, []);
14846
- const closeFloatingPanelOnly = useCallback7(() => {
14847
- setFloatingPanel(null);
14848
- setLogoSizeDraft(null);
14849
- }, []);
14850
- const closeFloatingPanelAndDeselect = useCallback7(() => {
14851
- setFloatingPanel(null);
14852
- setLogoSizeDraft(null);
14853
- deselectRef.current();
14854
- }, []);
14855
- const persistLogoSizeDraft = useCallback7(
14856
- (placement, draft) => {
14857
- const desktopKey = LOGO_SIZE_DESKTOP_KEYS[placement];
14858
- const mobileKey = LOGO_SIZE_MOBILE_KEYS[placement];
14859
- const nodes = [
14860
- { key: desktopKey, text: String(draft.desktopPx) }
14861
- ];
14862
- if (draft.mobileFollowing) {
14863
- nodes.push({ key: mobileKey, text: "" });
14864
- } else {
14865
- nodes.push({ key: mobileKey, text: String(draft.mobilePx) });
14866
- }
14867
- editContentRef.current = {
14868
- ...editContentRef.current,
14869
- [desktopKey]: String(draft.desktopPx),
14870
- [mobileKey]: draft.mobileFollowing ? "" : String(draft.mobilePx)
14871
- };
14872
- applyLogoSizeToPlacement(
14873
- placement,
14874
- draft.desktopPx,
14875
- draft.mobileFollowing ? draft.desktopPx : draft.mobilePx,
14876
- draft.mobileFollowing
14877
- );
14878
- postToParent2({ type: "ow:change", nodes });
14879
- requestAnimationFrame(() => {
14880
- const selected = selectedElRef.current;
14881
- if (!selected || toolbarVariantRef.current !== "logo") return;
14882
- const rect = getLogoInteractionRect(selected);
14883
- setToolbarRect(rect);
14884
- if (glowElRef.current) {
14885
- const GAP = SELECTION_CHROME_GAP2;
14886
- glowElRef.current.style.top = `${rect.top - GAP}px`;
14887
- glowElRef.current.style.left = `${rect.left - GAP}px`;
14888
- glowElRef.current.style.width = `${rect.width + GAP * 2}px`;
14889
- glowElRef.current.style.height = `${rect.height + GAP * 2}px`;
14890
- }
14891
- });
14892
- },
14893
- [postToParent2]
14894
- );
14895
- const activate = useCallback7((el, options) => {
13648
+ const activate = useCallback6((el, options) => {
14896
13649
  if (activeElRef.current === el) return;
14897
- if (isIconEditable(el)) return;
14898
- if (el.hasAttribute("data-ohw-social-label")) return;
14899
13650
  clearSelectedAttr();
14900
13651
  selectedElRef.current = null;
14901
13652
  selectedHrefKeyRef.current = null;
14902
13653
  selectedFooterColAttrRef.current = null;
14903
13654
  setSelectedIsCta(false);
14904
- setSelectedIsSocial(false);
14905
- setSelectedIsSocialsRow(false);
14906
13655
  deactivate();
14907
13656
  if (hoveredImageRef.current) {
14908
13657
  hoveredImageRef.current = null;
@@ -14972,38 +13721,8 @@ function OhhwellsBridge() {
14972
13721
  deactivateRef.current = deactivate;
14973
13722
  selectRef.current = select;
14974
13723
  selectFrameRef.current = selectFrame;
14975
- selectLogoRef.current = selectLogo;
14976
- openLogoSizePanelRef.current = openLogoSizePanel;
14977
13724
  deselectRef.current = deselect;
14978
- closeFloatingPanelOnlyRef.current = closeFloatingPanelOnly;
14979
- const lastSiteWideScopeRef = useRef9(null);
14980
- useEffect12(() => {
14981
- if (!isEditMode) {
14982
- if (lastSiteWideScopeRef.current !== false) {
14983
- lastSiteWideScopeRef.current = false;
14984
- postToParent2({ type: "ow:site-wide-scope", active: false });
14985
- }
14986
- return;
14987
- }
14988
- const active = isSiteWideScopeActive({
14989
- selected: selectedElRef.current,
14990
- hoveredItem: hoveredItemElRef.current,
14991
- hoveredNavContainer: hoveredNavContainerRef.current,
14992
- active: activeElRef.current
14993
- });
14994
- if (lastSiteWideScopeRef.current === active) return;
14995
- lastSiteWideScopeRef.current = active;
14996
- postToParent2({ type: "ow:site-wide-scope", active });
14997
- }, [
14998
- isEditMode,
14999
- hoveredItemRect,
15000
- hoveredNavContainerRect,
15001
- toolbarVariant,
15002
- toolbarRect,
15003
- isFooterFrameSelection,
15004
- postToParent2
15005
- ]);
15006
- useLayoutEffect4(() => {
13725
+ useLayoutEffect3(() => {
15007
13726
  if (!subdomain || isEditMode) {
15008
13727
  setFetchState("done");
15009
13728
  return;
@@ -15017,8 +13736,6 @@ function OhhwellsBridge() {
15017
13736
  for (const [key, val] of Object.entries(content)) {
15018
13737
  if (key === "__ohw_sections") continue;
15019
13738
  if (key === AI_SECTIONS_KEY) continue;
15020
- if (key === LOGO_PLACEHOLDER_KEY) continue;
15021
- if (LOGO_IMAGE_KEYS.includes(key)) continue;
15022
13739
  if (applyVideoSettingNode(key, val)) continue;
15023
13740
  if (applyCarouselNode(key, val)) continue;
15024
13741
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -15045,19 +13762,14 @@ function OhhwellsBridge() {
15045
13762
  }
15046
13763
  } else if (el.dataset.ohwEditable === "link") {
15047
13764
  applyLinkHref(el, val);
15048
- } else if (el.dataset.ohwEditable === "icon") {
15049
- applyIconMarkup(el, val);
15050
13765
  } else if (el.innerHTML !== val) {
15051
13766
  el.innerHTML = val;
15052
13767
  }
15053
13768
  });
15054
13769
  applyLinkByKey(key, val);
15055
13770
  }
15056
- applyLogoFromContent(content);
15057
- applyLogoSizes(content);
15058
13771
  reconcileNavbarItemsFromContent(content);
15059
13772
  reconcileFooterOrderFromContent(content);
15060
- reconcileSocialsFromContent(content);
15061
13773
  enforceLinkHrefs();
15062
13774
  initSectionsFromContent(content, true);
15063
13775
  sectionsLoadedRef.current = true;
@@ -15073,9 +13785,7 @@ function OhhwellsBridge() {
15073
13785
  let cancelled = false;
15074
13786
  setFetchState("loading");
15075
13787
  const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
15076
- const initialPath = pathname;
15077
- fetchedContentPaths.add(`${subdomain}::${initialPath}`);
15078
- fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
13788
+ fetch(`${apiUrl}/api/public/sites/${subdomain}/content`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
15079
13789
  if (cancelled) return;
15080
13790
  const content = data?.content ?? {};
15081
13791
  contentCache.set(subdomain, content);
@@ -15088,7 +13798,7 @@ function OhhwellsBridge() {
15088
13798
  cancelled = true;
15089
13799
  };
15090
13800
  }, [subdomain, isEditMode]);
15091
- useEffect12(() => {
13801
+ useEffect11(() => {
15092
13802
  if (!subdomain || isEditMode) return;
15093
13803
  let debounceTimer = null;
15094
13804
  let observer = null;
@@ -15100,8 +13810,6 @@ function OhhwellsBridge() {
15100
13810
  try {
15101
13811
  for (const [key, val] of Object.entries(content)) {
15102
13812
  if (key === "__ohw_sections") continue;
15103
- if (key === LOGO_PLACEHOLDER_KEY) continue;
15104
- if (LOGO_IMAGE_KEYS.includes(key)) continue;
15105
13813
  if (applyVideoSettingNode(key, val)) continue;
15106
13814
  if (applyCarouselNode(key, val)) continue;
15107
13815
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -15122,10 +13830,8 @@ function OhhwellsBridge() {
15122
13830
  });
15123
13831
  applyLinkByKey(key, val);
15124
13832
  }
15125
- applyLogoFromContent(content);
15126
13833
  reconcileNavbarItemsFromContent(content);
15127
13834
  reconcileFooterOrderFromContent(content);
15128
- reconcileSocialsFromContent(content);
15129
13835
  } finally {
15130
13836
  observer?.observe(document.body, { childList: true, subtree: true });
15131
13837
  }
@@ -15136,17 +13842,6 @@ function OhhwellsBridge() {
15136
13842
  debounceTimer = setTimeout(applyFromCache, 150);
15137
13843
  };
15138
13844
  applyFromCache();
15139
- const pathCacheKey = `${subdomain}::${pathname}`;
15140
- if (!fetchedContentPaths.has(pathCacheKey)) {
15141
- fetchedContentPaths.add(pathCacheKey);
15142
- const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
15143
- fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
15144
- if (!data?.content) return;
15145
- contentCache.set(subdomain, data.content);
15146
- applyFromCache();
15147
- }).catch(() => {
15148
- });
15149
- }
15150
13845
  observer = new MutationObserver(scheduleApply);
15151
13846
  observer.observe(document.body, { childList: true, subtree: true });
15152
13847
  return () => {
@@ -15154,16 +13849,16 @@ function OhhwellsBridge() {
15154
13849
  if (debounceTimer) clearTimeout(debounceTimer);
15155
13850
  };
15156
13851
  }, [subdomain, isEditMode, pathname]);
15157
- useLayoutEffect4(() => {
13852
+ useLayoutEffect3(() => {
15158
13853
  const el = document.getElementById("ohw-loader");
15159
13854
  if (!el) return;
15160
13855
  const visible = Boolean(subdomain) && fetchState !== "done";
15161
13856
  el.style.display = visible ? "flex" : "none";
15162
13857
  }, [subdomain, fetchState]);
15163
- useEffect12(() => {
13858
+ useEffect11(() => {
15164
13859
  postToParent2({ type: "ow:navigation", path: pathname });
15165
13860
  }, [pathname, postToParent2]);
15166
- useEffect12(() => {
13861
+ useEffect11(() => {
15167
13862
  if (!isEditMode) return;
15168
13863
  if (linkPopoverSessionRef.current?.intent === "add-nav") return;
15169
13864
  if (document.querySelector("[data-ohw-section-picker]")) return;
@@ -15171,7 +13866,7 @@ function OhhwellsBridge() {
15171
13866
  deselectRef.current();
15172
13867
  deactivateRef.current();
15173
13868
  }, [pathname, isEditMode]);
15174
- useEffect12(() => {
13869
+ useEffect11(() => {
15175
13870
  const contentForNav = () => {
15176
13871
  if (isEditMode) return editContentRef.current;
15177
13872
  if (!subdomain) return {};
@@ -15203,7 +13898,6 @@ function OhhwellsBridge() {
15203
13898
  const content = contentForNav();
15204
13899
  reconcileNavbarItemsFromContent(content);
15205
13900
  reconcileFooterOrderFromContent(content);
15206
- reconcileSocialsFromContent(content);
15207
13901
  document.querySelectorAll("footer [data-ohw-href-key]").forEach((el) => {
15208
13902
  if (isFooterHrefKey(el.getAttribute("data-ohw-href-key"))) {
15209
13903
  disableNativeHrefDrag(el);
@@ -15237,7 +13931,7 @@ function OhhwellsBridge() {
15237
13931
  observer?.disconnect();
15238
13932
  };
15239
13933
  }, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
15240
- useEffect12(() => {
13934
+ useEffect11(() => {
15241
13935
  if (!isEditMode) return;
15242
13936
  const measure = () => {
15243
13937
  const h = document.body.scrollHeight;
@@ -15261,7 +13955,7 @@ function OhhwellsBridge() {
15261
13955
  window.removeEventListener("resize", handleResize);
15262
13956
  };
15263
13957
  }, [pathname, isEditMode, postToParent2]);
15264
- useEffect12(() => {
13958
+ useEffect11(() => {
15265
13959
  if (!subdomainFromQuery || isEditMode) return;
15266
13960
  const handleClick = (e) => {
15267
13961
  const anchor = e.target.closest("a");
@@ -15277,7 +13971,7 @@ function OhhwellsBridge() {
15277
13971
  document.addEventListener("click", handleClick, true);
15278
13972
  return () => document.removeEventListener("click", handleClick, true);
15279
13973
  }, [subdomainFromQuery, isEditMode, router]);
15280
- useEffect12(() => {
13974
+ useEffect11(() => {
15281
13975
  if (!isEditMode) {
15282
13976
  editStylesRef.current?.base.remove();
15283
13977
  editStylesRef.current?.forceHover.remove();
@@ -15406,7 +14100,6 @@ function OhhwellsBridge() {
15406
14100
  if (target.closest("[data-ohw-state-toggle]")) return;
15407
14101
  if (target.closest("[data-ohw-max-badge]")) return;
15408
14102
  if (isInsideLinkEditor(target)) return;
15409
- if (isInsideFloatingPanel(target)) return;
15410
14103
  if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
15411
14104
  const beneath = document.elementsFromPoint(e.clientX, e.clientY).find(
15412
14105
  (el) => el instanceof HTMLElement && !el.closest("[data-ohw-bridge-root]") && el.closest("[data-ohw-section]") != null
@@ -15470,21 +14163,6 @@ function OhhwellsBridge() {
15470
14163
  return;
15471
14164
  }
15472
14165
  }
15473
- const logoEl = getLogoElement(target);
15474
- if (logoEl) {
15475
- e.preventDefault();
15476
- e.stopPropagation();
15477
- if (!logoHasUploadedImage(logoEl)) {
15478
- deselectRef.current();
15479
- deactivateRef.current();
15480
- const identity = readLogoIdentityFromDom();
15481
- postToParentRef.current({ type: "ow:open-logo-settings", ...identity });
15482
- return;
15483
- }
15484
- selectLogoRef.current(logoEl);
15485
- openLogoSizePanelRef.current(logoEl);
15486
- return;
15487
- }
15488
14166
  const editable = target.closest("[data-ohw-editable]");
15489
14167
  if (editable) {
15490
14168
  if (editable.dataset.ohwEditable === "link") {
@@ -15501,17 +14179,6 @@ function OhhwellsBridge() {
15501
14179
  });
15502
14180
  return;
15503
14181
  }
15504
- if (isIconEditable(editable) && !getSocialItem(editable)) {
15505
- e.preventDefault();
15506
- e.stopPropagation();
15507
- aiSectionApiRef.current?.selectFromElement(editable);
15508
- postToParentRef.current({
15509
- type: "ow:icon-pick",
15510
- key: editable.dataset.ohwKey ?? "",
15511
- current: currentIconRef(editable)
15512
- });
15513
- return;
15514
- }
15515
14182
  if (isMediaEditable(editable)) {
15516
14183
  e.preventDefault();
15517
14184
  e.stopPropagation();
@@ -15526,7 +14193,6 @@ function OhhwellsBridge() {
15526
14193
  e.stopPropagation();
15527
14194
  if (selectedElRef.current === navAnchor) {
15528
14195
  if (e.detail >= 2) return;
15529
- if (requestSocialDialog(navAnchor, postToParentRef.current, editContentRef.current)) return;
15530
14196
  activateRef.current(editable, { caretX: e.clientX, caretY: e.clientY });
15531
14197
  return;
15532
14198
  }
@@ -15543,7 +14209,6 @@ function OhhwellsBridge() {
15543
14209
  e.preventDefault();
15544
14210
  e.stopPropagation();
15545
14211
  if (selectedElRef.current === hrefAnchor) {
15546
- if (requestSocialDialog(hrefAnchor, postToParentRef.current, editContentRef.current)) return;
15547
14212
  const textEditable = hrefAnchor.querySelector('[data-ohw-editable="text"]') ?? hrefAnchor.querySelector("[data-ohw-editable]");
15548
14213
  if (textEditable) {
15549
14214
  activateRef.current(textEditable, {
@@ -15582,13 +14247,6 @@ function OhhwellsBridge() {
15582
14247
  selectFrameRef.current(navContainerToSelect);
15583
14248
  return;
15584
14249
  }
15585
- const socialsRowToSelect = isSocialsRow(target) ? target : null;
15586
- if (socialsRowToSelect && !getSocialItem(target)) {
15587
- e.preventDefault();
15588
- e.stopPropagation();
15589
- selectFrameRef.current(socialsRowToSelect);
15590
- return;
15591
- }
15592
14250
  const footerColumnToSelect = resolveFooterColumnSelectionTarget(target, e.clientX, e.clientY);
15593
14251
  if (footerColumnToSelect) {
15594
14252
  e.preventDefault();
@@ -15637,11 +14295,9 @@ function OhhwellsBridge() {
15637
14295
  if (target.closest("[data-ohw-state-toggle]")) return;
15638
14296
  if (target.closest("[data-ohw-max-badge]")) return;
15639
14297
  if (isInsideLinkEditor(target)) return;
15640
- if (isInsideFloatingPanel(target)) return;
15641
14298
  if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
15642
14299
  return;
15643
14300
  }
15644
- if (getSocialItem(target)) return;
15645
14301
  const navLabel = getNavigationLabelEditable(target);
15646
14302
  const editable = navLabel?.editable ?? target.closest('[data-ohw-editable="text"], [data-ohw-editable="plain"]');
15647
14303
  if (!editable || isMediaEditable(editable) || editable.dataset.ohwEditable === "link") return;
@@ -15665,16 +14321,6 @@ function OhhwellsBridge() {
15665
14321
  setHoveredNavContainerRect(null);
15666
14322
  return;
15667
14323
  }
15668
- if (isInsideFloatingPanel(target) || isPointOverFloatingPanel(e.clientX, e.clientY)) {
15669
- hoveredItemElRef.current = null;
15670
- setHoveredItemRect(null);
15671
- hoveredNavContainerRef.current = null;
15672
- setHoveredNavContainerRect(null);
15673
- siblingHintElRef.current = null;
15674
- setSiblingHintRect(null);
15675
- setSiblingHintRects([]);
15676
- return;
15677
- }
15678
14324
  {
15679
14325
  const selected2 = selectedElRef.current;
15680
14326
  const selectedIsFooterColumn = Boolean(selected2) && !isFooterLinksContainer(selected2) && (selected2.hasAttribute("data-ohw-footer-col") || selected2.hasAttribute("data-ohw-footer-column") || Boolean(selected2.closest("footer") && isInferredFooterGroup2(selected2)));
@@ -15682,7 +14328,7 @@ function OhhwellsBridge() {
15682
14328
  const allowFooterLinksHover = toolbarVariantRef.current !== "select-frame" || selectedIsFooterColumn;
15683
14329
  if (allowNavContainerHover) {
15684
14330
  const navContainer = target.closest("[data-ohw-nav-container]");
15685
- if (navContainer && !getNavigationItemAnchor(target) && !getLogoElement(target)) {
14331
+ if (navContainer && !getNavigationItemAnchor(target)) {
15686
14332
  hoveredNavContainerRef.current = navContainer;
15687
14333
  setHoveredNavContainerRect(navContainer.getBoundingClientRect());
15688
14334
  hoveredItemElRef.current = null;
@@ -15711,15 +14357,6 @@ function OhhwellsBridge() {
15711
14357
  setHoveredNavContainerRect(null);
15712
14358
  }
15713
14359
  }
15714
- const logoEl = getLogoElement(target);
15715
- if (logoEl) {
15716
- hoveredNavContainerRef.current = null;
15717
- setHoveredNavContainerRect(null);
15718
- if (selectedElRef.current === logoEl) return;
15719
- hoveredItemElRef.current = logoEl;
15720
- setHoveredItemRect(getLogoInteractionRect(logoEl));
15721
- return;
15722
- }
15723
14360
  const navAnchor = getNavigationItemAnchor(target);
15724
14361
  if (navAnchor) {
15725
14362
  hoveredNavContainerRef.current = null;
@@ -15745,11 +14382,6 @@ function OhhwellsBridge() {
15745
14382
  const selected = selectedElRef.current;
15746
14383
  if (selected && (selected === editable || selected.contains(editable))) return;
15747
14384
  if (!isMediaEditable(editable) && !editable.hasAttribute("contenteditable")) {
15748
- if (isIconEditable(editable)) {
15749
- hoveredItemElRef.current = editable;
15750
- setHoveredItemRect(editable.getBoundingClientRect());
15751
- return;
15752
- }
15753
14385
  const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
15754
14386
  if (hoverTarget.hasAttribute("data-ohw-href-key")) {
15755
14387
  clearHrefKeyHover(hoverTarget);
@@ -15757,12 +14389,6 @@ function OhhwellsBridge() {
15757
14389
  setHoveredItemRect(hoverTarget.getBoundingClientRect());
15758
14390
  } else if (!isInsideNavigationItem(editable)) {
15759
14391
  hoverTarget.setAttribute("data-ohw-hovered", "");
15760
- if (editable.closest("footer") || editable.closest('[data-ohw-section="footer"]')) {
15761
- hoveredNavContainerRef.current = null;
15762
- setHoveredNavContainerRect(null);
15763
- hoveredItemElRef.current = editable;
15764
- setHoveredItemRect(editable.getBoundingClientRect());
15765
- }
15766
14392
  }
15767
14393
  }
15768
14394
  };
@@ -15798,30 +14424,11 @@ function OhhwellsBridge() {
15798
14424
  }
15799
14425
  return;
15800
14426
  }
15801
- const logoEl = getLogoElement(target);
15802
- if (logoEl) {
15803
- const related2 = e.relatedTarget instanceof Element ? e.relatedTarget : null;
15804
- if (related2 && (logoEl === related2 || logoEl.contains(related2) || related2.closest?.('[data-ohw-role="logo"], [data-ohw-logo]'))) {
15805
- return;
15806
- }
15807
- if (hoveredItemElRef.current === logoEl) {
15808
- hoveredItemElRef.current = null;
15809
- setHoveredItemRect(null);
15810
- }
15811
- return;
15812
- }
15813
14427
  const editable = target.closest("[data-ohw-editable]");
15814
14428
  if (!editable) return;
15815
14429
  const related = e.relatedTarget instanceof Element ? e.relatedTarget : null;
15816
14430
  if (related?.closest("[data-ohw-drag-handle-container], [data-ohw-item-interaction]")) return;
15817
14431
  if (!isMediaEditable(editable)) {
15818
- if (isIconEditable(editable) && hoveredItemElRef.current === editable) {
15819
- if (!related?.closest("[data-ohw-item-interaction]")) {
15820
- hoveredItemElRef.current = null;
15821
- setHoveredItemRect(null);
15822
- }
15823
- return;
15824
- }
15825
14432
  const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
15826
14433
  if (hoverTarget.hasAttribute("data-ohw-href-key")) {
15827
14434
  if (!related?.closest("[data-ohw-href-key]")) {
@@ -15830,13 +14437,6 @@ function OhhwellsBridge() {
15830
14437
  }
15831
14438
  } else {
15832
14439
  hoverTarget.removeAttribute("data-ohw-hovered");
15833
- if (hoveredItemElRef.current === editable) {
15834
- const stillOnEditable = related instanceof Element && related.closest("[data-ohw-editable]") === editable;
15835
- if (!stillOnEditable) {
15836
- hoveredItemElRef.current = null;
15837
- setHoveredItemRect(null);
15838
- }
15839
- }
15840
14440
  }
15841
14441
  }
15842
14442
  };
@@ -15953,26 +14553,6 @@ function OhhwellsBridge() {
15953
14553
  hoveredNavContainerRef.current = null;
15954
14554
  setHoveredNavContainerRect(null);
15955
14555
  }
15956
- const logoCandidates = [
15957
- ...document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]'),
15958
- ...document.querySelectorAll("nav a:not([data-ohw-href-key]), [data-ohw-nav-root] a:not([data-ohw-href-key])"),
15959
- ...document.querySelectorAll("footer img")
15960
- ];
15961
- const seenLogos = /* @__PURE__ */ new Set();
15962
- for (const candidate of logoCandidates) {
15963
- const logo = getLogoElement(candidate);
15964
- if (!logo || seenLogos.has(logo)) continue;
15965
- seenLogos.add(logo);
15966
- const r2 = logo.getBoundingClientRect();
15967
- if (x < r2.left || x > r2.right || y < r2.top || y > r2.bottom) continue;
15968
- hoveredNavContainerRef.current = null;
15969
- setHoveredNavContainerRect(null);
15970
- if (selectedElRef.current !== logo) {
15971
- hoveredItemElRef.current = logo;
15972
- setHoveredItemRect(getLogoInteractionRect(logo));
15973
- }
15974
- return;
15975
- }
15976
14556
  const navContainers = Array.from(
15977
14557
  document.querySelectorAll("[data-ohw-nav-container]")
15978
14558
  );
@@ -16058,7 +14638,7 @@ function OhhwellsBridge() {
16058
14638
  }
16059
14639
  };
16060
14640
  const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
16061
- if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
14641
+ if (linkPopoverOpenRef.current) {
16062
14642
  if (hoveredImageRef.current) {
16063
14643
  hoveredImageRef.current = null;
16064
14644
  hoveredImageHasTextOverlapRef.current = false;
@@ -16312,7 +14892,7 @@ function OhhwellsBridge() {
16312
14892
  }
16313
14893
  };
16314
14894
  const probeHoverCardsAt = (clientX, clientY, fromParentViewport = false) => {
16315
- if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || document.documentElement.hasAttribute("data-ohw-section-picking")) {
14895
+ if (linkPopoverOpenRef.current || document.documentElement.hasAttribute("data-ohw-section-picking")) {
16316
14896
  if (activeStateElRef.current) {
16317
14897
  activeStateElRef.current.removeAttribute("data-ohw-state-hovered");
16318
14898
  activeStateElRef.current = null;
@@ -16380,19 +14960,6 @@ function OhhwellsBridge() {
16380
14960
  };
16381
14961
  const handleMouseMove = (e) => {
16382
14962
  const { clientX, clientY } = e;
16383
- if (floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
16384
- hoveredItemElRef.current = null;
16385
- setHoveredItemRect(null);
16386
- hoveredNavContainerRef.current = null;
16387
- setHoveredNavContainerRect(null);
16388
- siblingHintElRef.current = null;
16389
- setSiblingHintRect(null);
16390
- setSiblingHintRects([]);
16391
- dismissImageHover();
16392
- clearImageHover();
16393
- setSectionGap(null);
16394
- return;
16395
- }
16396
14963
  probeSectionGapAt(clientX, clientY);
16397
14964
  probeImageAt(clientX, clientY);
16398
14965
  probeHoverCardsAt(clientX, clientY);
@@ -16401,11 +14968,6 @@ function OhhwellsBridge() {
16401
14968
  if (e.data?.type !== "ow:pointer-sync") return;
16402
14969
  const { clientX, clientY } = e.data;
16403
14970
  if (typeof clientX !== "number" || typeof clientY !== "number") return;
16404
- if (floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
16405
- dismissImageHover();
16406
- clearImageHover();
16407
- return;
16408
- }
16409
14971
  probeSectionGapAt(clientX, clientY);
16410
14972
  probeImageAt(clientX, clientY);
16411
14973
  probeHoverCardsAt(clientX, clientY);
@@ -16415,7 +14977,7 @@ function OhhwellsBridge() {
16415
14977
  if (footerSession) {
16416
14978
  e.preventDefault();
16417
14979
  if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
16418
- const slot = footerSession.kind === "social" && footerSession.hrefKey ? hitTestSocialDropSlot(e.clientX, e.clientY, footerSession.hrefKey) : footerSession.kind === "link" && footerSession.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, footerSession.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
14980
+ const slot = footerSession.kind === "link" && footerSession.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, footerSession.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
16419
14981
  refreshFooterDragVisualsRef.current(footerSession, slot, e.clientX, e.clientY);
16420
14982
  return;
16421
14983
  }
@@ -16467,60 +15029,6 @@ function OhhwellsBridge() {
16467
15029
  resumeAnimTracks();
16468
15030
  clearImageHover();
16469
15031
  };
16470
- const handleSocialCancel = (e) => {
16471
- if (e.data?.type !== "ow:social-cancel") return;
16472
- const { hrefKey } = e.data;
16473
- const item = hrefKey ? findSocialByHrefKey(hrefKey) : null;
16474
- if (!item) return;
16475
- const removed = removeSocialItem(item, editContentRef.current);
16476
- if (!removed) return;
16477
- const orderJson = JSON.stringify(removed.order);
16478
- editContentRef.current = { ...editContentRef.current, [SOCIALS_ORDER_KEY]: orderJson };
16479
- postToParentRef.current({ type: "ow:change", nodes: [{ key: SOCIALS_ORDER_KEY, text: orderJson }] });
16480
- deselectRef.current();
16481
- };
16482
- const handleSocialUpdate = (e) => {
16483
- if (e.data?.type !== "ow:social-update") return;
16484
- const { hrefKey, iconKey, url, iconMarkup, platformId, label } = e.data;
16485
- const nodes = [];
16486
- if (hrefKey) {
16487
- document.querySelectorAll(`[data-ohw-href-key="${hrefKey}"]`).forEach((el) => applyLinkHref(el, url));
16488
- nodes.push({ key: hrefKey, text: url });
16489
- }
16490
- if (iconKey && typeof iconMarkup === "string" && iconMarkup) {
16491
- document.querySelectorAll(`[data-ohw-key="${iconKey}"][data-ohw-editable="icon"]`).forEach((el) => {
16492
- applyIconMarkup(el, iconMarkup);
16493
- });
16494
- nodes.push({ key: iconKey, text: iconMarkup });
16495
- }
16496
- if (iconKey && platformId) nodes.push({ key: socialPlatformKey(iconKey), text: platformId });
16497
- if (iconKey && label) {
16498
- const labelKey = socialLabelKey(iconKey);
16499
- document.querySelectorAll(`[data-ohw-key="${labelKey}"]`).forEach((el) => {
16500
- el.textContent = label;
16501
- });
16502
- nodes.push({ key: labelKey, text: label });
16503
- }
16504
- if (!nodes.length) return;
16505
- editContentRef.current = {
16506
- ...editContentRef.current,
16507
- ...Object.fromEntries(nodes.map((node) => [node.key, node.text]))
16508
- };
16509
- postToParentRef.current({ type: "ow:change", nodes });
16510
- };
16511
- const handleIconMarkup = (e) => {
16512
- if (e.data?.type !== "ow:icon-markup") return;
16513
- const { key, markup } = e.data;
16514
- if (!key || typeof markup !== "string") return;
16515
- const targets = document.querySelectorAll(
16516
- `[data-ohw-key="${key}"][data-ohw-editable="icon"]`
16517
- );
16518
- if (!targets.length) return;
16519
- targets.forEach((el) => {
16520
- applyIconMarkup(el, markup);
16521
- });
16522
- postToParentRef.current({ type: "ow:change", nodes: [{ key, text: markup }] });
16523
- };
16524
15032
  const handleImageUrl = (e) => {
16525
15033
  if (e.data?.type !== "ow:image-url") return;
16526
15034
  const { key, url } = e.data;
@@ -16660,8 +15168,6 @@ function OhhwellsBridge() {
16660
15168
  continue;
16661
15169
  }
16662
15170
  if (key === AI_SECTIONS_KEY) continue;
16663
- if (key === LOGO_PLACEHOLDER_KEY) continue;
16664
- if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
16665
15171
  if (applyVideoSettingNode(key, val)) continue;
16666
15172
  if (applyCarouselNode(key, val)) continue;
16667
15173
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -16681,8 +15187,6 @@ function OhhwellsBridge() {
16681
15187
  });
16682
15188
  applyLinkByKey(key, val);
16683
15189
  }
16684
- applyLogoFromContent(content);
16685
- applyLogoSizes(content);
16686
15190
  if (sectionsJson) {
16687
15191
  initSectionsFromContent({ __ohw_sections: sectionsJson }, true);
16688
15192
  sectionsLoadedRef.current = true;
@@ -16697,58 +15201,6 @@ function OhhwellsBridge() {
16697
15201
  if (hydratedHeight > 50) postToParentRef.current({ type: "ow:height", height: hydratedHeight });
16698
15202
  postToParentRef.current({ type: "ow:hydrate-done" });
16699
15203
  };
16700
- const handleUpdateLogoIdentity = (e) => {
16701
- if (e.data?.type !== "ow:update-logo-identity") return;
16702
- const rawText = typeof e.data.text === "string" ? e.data.text : "";
16703
- const alt = typeof e.data.alt === "string" ? e.data.alt : rawText;
16704
- const href = typeof e.data.href === "string" ? e.data.href : void 0;
16705
- const imageProvided = "image" in e.data;
16706
- const imageUrl = imageProvided && typeof e.data.image === "string" && e.data.image.trim() ? e.data.image.trim() : imageProvided ? null : void 0;
16707
- let isPlaceholder = e.data.isPlaceholder !== false;
16708
- if (imageUrl) isPlaceholder = false;
16709
- else if (imageProvided && imageUrl === null) {
16710
- isPlaceholder = e.data.isPlaceholder === true || !rawText.trim() || resolveLogoDisplayText(rawText) === PLACEHOLDER_BUSINESS_NAME;
16711
- }
16712
- const display = applyLogoIdentity(rawText, isPlaceholder);
16713
- const displayAlt = resolveLogoDisplayText(alt || display);
16714
- if (imageUrl !== void 0) {
16715
- applyLogoImage(imageUrl, displayAlt);
16716
- } else {
16717
- for (const key of LOGO_IMAGE_KEYS) {
16718
- document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
16719
- const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
16720
- if (img) img.alt = displayAlt;
16721
- });
16722
- }
16723
- }
16724
- if (href !== void 0) {
16725
- applyLogoHref(href);
16726
- applyLinkByKey("nav-logo-href", href);
16727
- applyLinkByKey("footer-logo-href", href);
16728
- applyLinkByKey("logo-href", href);
16729
- }
16730
- const nodes = [
16731
- ...LOGO_TEXT_KEYS.map((key) => ({ key, text: display })),
16732
- { key: LOGO_PLACEHOLDER_KEY, text: isPlaceholder ? "true" : "false" },
16733
- { key: LOGO_ALT_KEY, text: displayAlt }
16734
- ];
16735
- if (imageUrl !== void 0) {
16736
- if (imageUrl) {
16737
- for (const key of LOGO_IMAGE_KEYS) nodes.push({ key, text: imageUrl });
16738
- } else {
16739
- for (const key of LOGO_IMAGE_KEYS) nodes.push({ key, text: "" });
16740
- }
16741
- }
16742
- if (href !== void 0) {
16743
- for (const key of LOGO_HREF_KEYS) nodes.push({ key, text: href.trim() || "/" });
16744
- }
16745
- editContentRef.current = {
16746
- ...editContentRef.current,
16747
- ...Object.fromEntries(nodes.map(({ key, text }) => [key, text]))
16748
- };
16749
- applyLogoSizes(editContentRef.current);
16750
- postToParentRef.current({ type: "ow:change", nodes });
16751
- };
16752
15204
  window.addEventListener("message", handleHydrate);
16753
15205
  const postAiSectionsChanged = () => {
16754
15206
  postToParentRef.current({
@@ -16813,12 +15265,6 @@ function OhhwellsBridge() {
16813
15265
  closeLinkPopoverRef.current();
16814
15266
  return;
16815
15267
  }
16816
- if (floatingPanelOpenRef.current) {
16817
- setFloatingPanelRef.current(null);
16818
- deselectRef.current();
16819
- deactivateRef.current();
16820
- return;
16821
- }
16822
15268
  deselectRef.current();
16823
15269
  deactivateRef.current();
16824
15270
  };
@@ -16838,10 +15284,6 @@ function OhhwellsBridge() {
16838
15284
  closeLinkPopoverRef.current();
16839
15285
  return;
16840
15286
  }
16841
- if (floatingPanelOpenRef.current) {
16842
- closeFloatingPanelOnlyRef.current();
16843
- return;
16844
- }
16845
15287
  if (activeElRef.current) {
16846
15288
  const hrefCtx = getHrefKeyFromElement(activeElRef.current);
16847
15289
  const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
@@ -16872,10 +15314,6 @@ function OhhwellsBridge() {
16872
15314
  return;
16873
15315
  }
16874
15316
  if (selectedElRef.current) {
16875
- if (toolbarVariantRef.current === "logo") {
16876
- deselectRef.current();
16877
- return;
16878
- }
16879
15317
  if (toolbarVariantRef.current === "select-frame") {
16880
15318
  const parent2 = getNavigationSelectionParent(selectedElRef.current);
16881
15319
  if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
@@ -16909,16 +15347,7 @@ function OhhwellsBridge() {
16909
15347
  closeLinkPopoverRef.current();
16910
15348
  return;
16911
15349
  }
16912
- if (e.key === "Escape" && floatingPanelOpenRef.current) {
16913
- e.preventDefault();
16914
- closeFloatingPanelOnlyRef.current();
16915
- return;
16916
- }
16917
15350
  if (e.key === "Escape" && selectedElRef.current && !activeElRef.current) {
16918
- if (toolbarVariantRef.current === "logo") {
16919
- deselectRef.current();
16920
- return;
16921
- }
16922
15351
  if (toolbarVariantRef.current === "select-frame") {
16923
15352
  const parent2 = getNavigationSelectionParent(selectedElRef.current);
16924
15353
  if (parent2 && isNavigationContainer(parent2) && isFooterLinksContainer(parent2) && !isFooterLinksContainer(selectedElRef.current)) {
@@ -16996,8 +15425,7 @@ function OhhwellsBridge() {
16996
15425
  const handleScroll = () => {
16997
15426
  const focusEl = activeElRef.current ?? selectedElRef.current;
16998
15427
  if (focusEl) {
16999
- const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : toolbarVariantRef.current === "logo" ? null : focusEl;
17000
- const r2 = measureEl ? measureEl.getBoundingClientRect() : toolbarVariantRef.current === "logo" ? getLogoInteractionRect(focusEl) : focusEl.getBoundingClientRect();
15428
+ const r2 = activeElRef.current ? getEditMeasureEl(activeElRef.current).getBoundingClientRect() : focusEl.getBoundingClientRect();
17001
15429
  applyToolbarPos(r2);
17002
15430
  setToolbarRect(r2);
17003
15431
  setMaxBadge((prev) => prev && activeElRef.current ? { ...prev, rect: r2 } : prev);
@@ -17007,9 +15435,7 @@ function OhhwellsBridge() {
17007
15435
  setToggleState((prev) => prev ? { ...prev, rect } : null);
17008
15436
  }
17009
15437
  if (hoveredItemElRef.current) {
17010
- const hoverEl = hoveredItemElRef.current;
17011
- const logo = getLogoElement(hoverEl);
17012
- setHoveredItemRect(logo ? getLogoInteractionRect(logo) : hoverEl.getBoundingClientRect());
15438
+ setHoveredItemRect(hoveredItemElRef.current.getBoundingClientRect());
17013
15439
  }
17014
15440
  if (hoveredNavContainerRef.current) {
17015
15441
  setHoveredNavContainerRect(hoveredNavContainerRef.current.getBoundingClientRect());
@@ -17029,7 +15455,7 @@ function OhhwellsBridge() {
17029
15455
  }
17030
15456
  if (footerDragRef.current) {
17031
15457
  const session = footerDragRef.current;
17032
- const slot = session.kind === "social" && session.hrefKey ? hitTestSocialDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
15458
+ const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
17033
15459
  refreshFooterDragVisualsRef.current(session, slot, session.lastClientX, session.lastClientY);
17034
15460
  }
17035
15461
  if (navDragRef.current) {
@@ -17063,12 +15489,8 @@ function OhhwellsBridge() {
17063
15489
  if (inserted) {
17064
15490
  const tracker = getSectionsTracker();
17065
15491
  postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
17066
- const reportHeight = () => {
17067
- const h = document.body.scrollHeight;
17068
- if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
17069
- };
17070
- reportHeight();
17071
- setTimeout(reportHeight, 500);
15492
+ const h = document.documentElement.scrollHeight;
15493
+ if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
17072
15494
  }
17073
15495
  };
17074
15496
  const handleSwitchSchedule = (e) => {
@@ -17261,17 +15683,13 @@ function OhhwellsBridge() {
17261
15683
  if (e.data?.type !== "ow:parent-scroll") return;
17262
15684
  const { iframeOffsetTop, headerH, canvasH } = e.data;
17263
15685
  parentScrollRef.current = { iframeOffsetTop, headerH, canvasH };
17264
- if (floatingPanelOpenRef.current) {
17265
- setParentScrollSnap({ iframeOffsetTop, headerH, canvasH });
17266
- }
17267
15686
  if (visibleViewportRef.current) {
17268
15687
  applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
17269
15688
  }
17270
15689
  const focusEl = activeElRef.current ?? selectedElRef.current;
17271
15690
  if (focusEl) {
17272
- const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : toolbarVariantRef.current === "logo" ? null : focusEl;
17273
- const r2 = measureEl ? measureEl.getBoundingClientRect() : toolbarVariantRef.current === "logo" ? getLogoInteractionRect(focusEl) : focusEl.getBoundingClientRect();
17274
- applyToolbarPos(r2);
15691
+ const measureEl = activeElRef.current ? getEditMeasureEl(activeElRef.current) : focusEl;
15692
+ applyToolbarPos(measureEl.getBoundingClientRect());
17275
15693
  }
17276
15694
  };
17277
15695
  const handleClickAt = (e) => {
@@ -17296,25 +15714,6 @@ function OhhwellsBridge() {
17296
15714
  postToParentRef.current({ type: "ow:image-pick", key: stateCardImage.dataset.ohwKey ?? "", elementType: stateCardImage.dataset.ohwEditable ?? "image" });
17297
15715
  return;
17298
15716
  }
17299
- const logoAtPoint = Array.from(
17300
- document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]')
17301
- ).map((el) => getLogoElement(el)).find((logo) => {
17302
- if (!logo) return false;
17303
- const r2 = logo.getBoundingClientRect();
17304
- return clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
17305
- });
17306
- if (logoAtPoint) {
17307
- if (!logoHasUploadedImage(logoAtPoint)) {
17308
- deselectRef.current();
17309
- deactivateRef.current();
17310
- const identity = readLogoIdentityFromDom();
17311
- postToParentRef.current({ type: "ow:open-logo-settings", ...identity });
17312
- return;
17313
- }
17314
- selectLogoRef.current(logoAtPoint);
17315
- openLogoSizePanelRef.current(logoAtPoint);
17316
- return;
17317
- }
17318
15717
  const textEditable = Array.from(
17319
15718
  document.querySelectorAll(NON_MEDIA_SELECTOR)
17320
15719
  ).find((el) => {
@@ -17376,9 +15775,6 @@ function OhhwellsBridge() {
17376
15775
  window.addEventListener("message", handleClearSchedulingWidget);
17377
15776
  window.addEventListener("message", handleRemoveSchedulingSection);
17378
15777
  window.addEventListener("message", handleCollectSection);
17379
- window.addEventListener("message", handleSocialCancel);
17380
- window.addEventListener("message", handleSocialUpdate);
17381
- window.addEventListener("message", handleIconMarkup);
17382
15778
  window.addEventListener("message", handleImageUrl);
17383
15779
  window.addEventListener("message", handleImageUploading);
17384
15780
  window.addEventListener("message", handleCarouselChange);
@@ -17386,14 +15782,6 @@ function OhhwellsBridge() {
17386
15782
  window.addEventListener("message", handleParentScroll);
17387
15783
  window.addEventListener("message", handlePointerSync);
17388
15784
  window.addEventListener("message", handleClickAt);
17389
- window.addEventListener("message", handleUpdateLogoIdentity);
17390
- const handleViewMode = (e) => {
17391
- if (e.data?.type !== "ow:view-mode") return;
17392
- const mode = e.data.mode === "Mobile" || e.data.mode === "mobile" ? "mobile" : "desktop";
17393
- setEditorViewport(mode);
17394
- applyLogoSizes(editContentRef.current);
17395
- };
17396
- window.addEventListener("message", handleViewMode);
17397
15785
  const handleViewportResize = () => {
17398
15786
  if (visibleViewportRef.current) {
17399
15787
  applyVisibleViewport(visibleViewportRef.current, parentScrollRef.current);
@@ -17438,9 +15826,6 @@ function OhhwellsBridge() {
17438
15826
  window.removeEventListener("message", handleClearSchedulingWidget);
17439
15827
  window.removeEventListener("message", handleRemoveSchedulingSection);
17440
15828
  window.removeEventListener("message", handleCollectSection);
17441
- window.removeEventListener("message", handleSocialCancel);
17442
- window.removeEventListener("message", handleSocialUpdate);
17443
- window.removeEventListener("message", handleIconMarkup);
17444
15829
  window.removeEventListener("message", handleImageUrl);
17445
15830
  window.removeEventListener("message", handleImageUploading);
17446
15831
  window.removeEventListener("message", handleCarouselChange);
@@ -17449,8 +15834,6 @@ function OhhwellsBridge() {
17449
15834
  window.removeEventListener("resize", handleViewportResize);
17450
15835
  window.removeEventListener("message", handlePointerSync);
17451
15836
  window.removeEventListener("message", handleClickAt);
17452
- window.removeEventListener("message", handleUpdateLogoIdentity);
17453
- window.removeEventListener("message", handleViewMode);
17454
15837
  window.removeEventListener("message", handleHydrate);
17455
15838
  window.removeEventListener("message", handleAiApplyTree);
17456
15839
  window.removeEventListener("message", handleAiDeleteSection);
@@ -17464,7 +15847,7 @@ function OhhwellsBridge() {
17464
15847
  if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
17465
15848
  };
17466
15849
  }, [isEditMode, refreshStateRules]);
17467
- useEffect12(() => {
15850
+ useEffect11(() => {
17468
15851
  if (!isEditMode) return;
17469
15852
  const THRESHOLD = 10;
17470
15853
  const resolveWasSelected = (el) => {
@@ -17519,7 +15902,7 @@ function OhhwellsBridge() {
17519
15902
  clearTextSelection();
17520
15903
  const session = footerDragRef.current;
17521
15904
  if (!session) return;
17522
- const slot = session.kind === "social" && session.hrefKey ? hitTestSocialDropSlot(e.clientX, e.clientY, session.hrefKey) : session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, session.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
15905
+ const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, session.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
17523
15906
  refreshFooterDragVisualsRef.current(session, slot, e.clientX, e.clientY);
17524
15907
  return;
17525
15908
  }
@@ -17618,7 +16001,7 @@ function OhhwellsBridge() {
17618
16001
  unlockFooterDragInteraction();
17619
16002
  };
17620
16003
  }, [isEditMode]);
17621
- useEffect12(() => {
16004
+ useEffect11(() => {
17622
16005
  const handler = (e) => {
17623
16006
  if (e.data?.type !== "ow:request-schedule-config") return;
17624
16007
  const insertAfterVal = e.data.insertAfter;
@@ -17634,7 +16017,7 @@ function OhhwellsBridge() {
17634
16017
  window.addEventListener("message", handler);
17635
16018
  return () => window.removeEventListener("message", handler);
17636
16019
  }, [processConfigRequest]);
17637
- useEffect12(() => {
16020
+ useEffect11(() => {
17638
16021
  if (!isEditMode) return;
17639
16022
  document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
17640
16023
  el.removeAttribute("data-ohw-active-state");
@@ -17670,13 +16053,13 @@ function OhhwellsBridge() {
17670
16053
  clearTimeout(timer);
17671
16054
  };
17672
16055
  }, [pathname, isEditMode, refreshStateRules, postToParent2]);
17673
- useEffect12(() => {
16056
+ useEffect11(() => {
17674
16057
  scrollToHashSectionWhenReady();
17675
16058
  const onHashChange = () => scrollToHashSectionWhenReady();
17676
16059
  window.addEventListener("hashchange", onHashChange);
17677
16060
  return () => window.removeEventListener("hashchange", onHashChange);
17678
16061
  }, [pathname]);
17679
- const handleCommand = useCallback7((cmd) => {
16062
+ const handleCommand = useCallback6((cmd) => {
17680
16063
  const el = activeElRef.current;
17681
16064
  const selBefore = window.getSelection();
17682
16065
  let savedOffsets = null;
@@ -17712,7 +16095,7 @@ function OhhwellsBridge() {
17712
16095
  if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
17713
16096
  refreshActiveCommandsRef.current();
17714
16097
  }, []);
17715
- const handleStateChange = useCallback7((state) => {
16098
+ const handleStateChange = useCallback6((state) => {
17716
16099
  if (!activeStateElRef.current) return;
17717
16100
  const el = activeStateElRef.current;
17718
16101
  if (state === "Default") {
@@ -17725,7 +16108,7 @@ function OhhwellsBridge() {
17725
16108
  }
17726
16109
  setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
17727
16110
  }, [deactivate]);
17728
- const reselectAfterLinkPopover = useCallback7(
16111
+ const reselectAfterLinkPopover = useCallback6(
17729
16112
  (hrefKey) => {
17730
16113
  requestAnimationFrame(() => {
17731
16114
  const el = resolveHrefKeyElement(hrefKey);
@@ -17734,7 +16117,7 @@ function OhhwellsBridge() {
17734
16117
  },
17735
16118
  [resolveHrefKeyElement]
17736
16119
  );
17737
- const closeLinkPopover = useCallback7(() => {
16120
+ const closeLinkPopover = useCallback6(() => {
17738
16121
  const session = linkPopoverSessionRef.current;
17739
16122
  addNavAfterAnchorRef.current = null;
17740
16123
  setLinkPopover(null);
@@ -17742,9 +16125,9 @@ function OhhwellsBridge() {
17742
16125
  reselectAfterLinkPopover(session.key);
17743
16126
  }
17744
16127
  }, [reselectAfterLinkPopover]);
17745
- const closeLinkPopoverRef = useRef9(closeLinkPopover);
16128
+ const closeLinkPopoverRef = useRef8(closeLinkPopover);
17746
16129
  closeLinkPopoverRef.current = closeLinkPopover;
17747
- const openLinkPopoverForActive = useCallback7(() => {
16130
+ const openLinkPopoverForActive = useCallback6(() => {
17748
16131
  const hrefCtx = getHrefKeyFromElement(activeElRef.current);
17749
16132
  if (!hrefCtx) return;
17750
16133
  bumpLinkPopoverGrace();
@@ -17755,15 +16138,11 @@ function OhhwellsBridge() {
17755
16138
  });
17756
16139
  deactivate();
17757
16140
  }, [deactivate]);
17758
- const openLinkPopoverForSelected = useCallback7(() => {
16141
+ const openLinkPopoverForSelected = useCallback6(() => {
17759
16142
  const anchor = selectedElRef.current;
17760
16143
  if (!anchor) return;
17761
16144
  const key = anchor.getAttribute("data-ohw-href-key");
17762
16145
  if (!key) return;
17763
- if (requestSocialDialog(anchor, postToParentRef.current, editContentRef.current)) {
17764
- deselect();
17765
- return;
17766
- }
17767
16146
  bumpLinkPopoverGrace();
17768
16147
  setLinkPopover({
17769
16148
  key,
@@ -17772,7 +16151,7 @@ function OhhwellsBridge() {
17772
16151
  });
17773
16152
  deselect();
17774
16153
  }, [deselect]);
17775
- const handleSelectParent = useCallback7(() => {
16154
+ const handleSelectParent = useCallback6(() => {
17776
16155
  const selected = selectedElRef.current;
17777
16156
  if (!selected) return;
17778
16157
  if (toolbarVariantRef.current === "select-frame") {
@@ -17799,35 +16178,11 @@ function OhhwellsBridge() {
17799
16178
  }
17800
16179
  deselectRef.current();
17801
16180
  }, []);
17802
- const handleDuplicateSelected = useCallback7(() => {
16181
+ const handleDuplicateSelected = useCallback6(() => {
17803
16182
  const selected = selectedElRef.current;
17804
16183
  if (!selected || !isNavigationItem2(selected)) return;
17805
16184
  const hrefKey = selected.getAttribute("data-ohw-href-key");
17806
16185
  if (!hrefKey) return;
17807
- const social = getSocialItem(selected);
17808
- if (social) {
17809
- const result = duplicateSocialItem(social, editContentRef.current);
17810
- if (!result) return;
17811
- const orderJson = JSON.stringify(result.order);
17812
- const carried = [
17813
- { from: result.copiedFrom?.href, to: result.hrefKey },
17814
- { from: result.copiedFrom?.icon, to: result.iconKey },
17815
- { from: result.copiedFrom?.icon ? socialPlatformKey(result.copiedFrom.icon) : null, to: socialPlatformKey(result.iconKey) }
17816
- ];
17817
- const nodes = [{ key: SOCIALS_ORDER_KEY, text: orderJson }];
17818
- for (const { from, to } of carried) {
17819
- const value = from ? editContentRef.current[from] : void 0;
17820
- if (value) nodes.push({ key: to, text: value });
17821
- }
17822
- editContentRef.current = {
17823
- ...editContentRef.current,
17824
- ...Object.fromEntries(nodes.map((node) => [node.key, node.text]))
17825
- };
17826
- postToParent2({ type: "ow:change", nodes });
17827
- enforceLinkHrefs();
17828
- requestAnimationFrame(() => selectRef.current(result.item));
17829
- return;
17830
- }
17831
16186
  if (isNavbarHrefKey(hrefKey)) {
17832
16187
  const result = duplicateNavbarItem(selected);
17833
16188
  if (!result) return;
@@ -17913,7 +16268,7 @@ function OhhwellsBridge() {
17913
16268
  });
17914
16269
  }
17915
16270
  }, [postToParent2]);
17916
- const runPendingDeleteUndo = useCallback7(() => {
16271
+ const runPendingDeleteUndo = useCallback6(() => {
17917
16272
  const pending = pendingDeleteUndoRef.current;
17918
16273
  if (!pending) return false;
17919
16274
  pendingDeleteUndoRef.current = null;
@@ -17921,7 +16276,7 @@ function OhhwellsBridge() {
17921
16276
  enforceLinkHrefs();
17922
16277
  return true;
17923
16278
  }, []);
17924
- const handleDeleteSelected = useCallback7(() => {
16279
+ const handleDeleteSelected = useCallback6(() => {
17925
16280
  const selected = selectedElRef.current;
17926
16281
  if (!selected) return false;
17927
16282
  return deleteSelectedNavFooterItem({
@@ -17942,7 +16297,7 @@ function OhhwellsBridge() {
17942
16297
  }, [postToParent2]);
17943
16298
  handleDeleteSelectedRef.current = handleDeleteSelected;
17944
16299
  runPendingDeleteUndoRef.current = runPendingDeleteUndo;
17945
- const handleLinkPopoverSubmit = useCallback7(
16300
+ const handleLinkPopoverSubmit = useCallback6(
17946
16301
  (target) => {
17947
16302
  const session = linkPopoverSessionRef.current;
17948
16303
  if (!session) return;
@@ -18008,19 +16363,19 @@ function OhhwellsBridge() {
18008
16363
  const showEditLink = toolbarShowEditLink;
18009
16364
  const currentSections = sectionsByPath[pathname] ?? [];
18010
16365
  linkPopoverOpenRef.current = linkPopover !== null;
18011
- const handleMediaReplace = useCallback7(
16366
+ const handleMediaReplace = useCallback6(
18012
16367
  (key) => {
18013
16368
  postToParent2({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
18014
16369
  },
18015
16370
  [postToParent2, mediaHover?.elementType]
18016
16371
  );
18017
- const handleEditCarousel = useCallback7(
16372
+ const handleEditCarousel = useCallback6(
18018
16373
  (key) => {
18019
16374
  postToParent2({ type: "ow:carousel-open", key, images: readCarouselValue(key) });
18020
16375
  },
18021
16376
  [postToParent2]
18022
16377
  );
18023
- const handleMediaFadeOutComplete = useCallback7((key) => {
16378
+ const handleMediaFadeOutComplete = useCallback6((key) => {
18024
16379
  setUploadingRects((prev) => {
18025
16380
  if (!(key in prev)) return prev;
18026
16381
  const next = { ...prev };
@@ -18028,7 +16383,7 @@ function OhhwellsBridge() {
18028
16383
  return next;
18029
16384
  });
18030
16385
  }, []);
18031
- const handleVideoSettingsChange = useCallback7(
16386
+ const handleVideoSettingsChange = useCallback6(
18032
16387
  (key, settings) => {
18033
16388
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
18034
16389
  const video = getVideoEl2(el);
@@ -18051,10 +16406,10 @@ function OhhwellsBridge() {
18051
16406
  [postToParent2]
18052
16407
  );
18053
16408
  return bridgeRoot ? createPortal2(
18054
- /* @__PURE__ */ jsxs19(Fragment8, { children: [
18055
- /* @__PURE__ */ jsx32("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
18056
- isEditMode && /* @__PURE__ */ jsx32(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
18057
- Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ jsx32(
16409
+ /* @__PURE__ */ jsxs17(Fragment8, { children: [
16410
+ /* @__PURE__ */ jsx30("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
16411
+ isEditMode && /* @__PURE__ */ jsx30(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
16412
+ Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ jsx30(
18058
16413
  MediaOverlay,
18059
16414
  {
18060
16415
  hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
@@ -18065,7 +16420,7 @@ function OhhwellsBridge() {
18065
16420
  },
18066
16421
  `uploading-${key}`
18067
16422
  )),
18068
- mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ jsx32(
16423
+ mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ jsx30(
18069
16424
  MediaOverlay,
18070
16425
  {
18071
16426
  hover: mediaHover,
@@ -18074,11 +16429,11 @@ function OhhwellsBridge() {
18074
16429
  onVideoSettingsChange: handleVideoSettingsChange
18075
16430
  }
18076
16431
  ),
18077
- carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx32(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
18078
- siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx32(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
18079
- siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx32(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
18080
- isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ jsx32(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
18081
- isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ jsx32(
16432
+ carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx30(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
16433
+ siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx30(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
16434
+ siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx30(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
16435
+ isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ jsx30(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
16436
+ isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ jsx30(
18082
16437
  "div",
18083
16438
  {
18084
16439
  className: "pointer-events-none fixed z-2147483646",
@@ -18088,7 +16443,7 @@ function OhhwellsBridge() {
18088
16443
  width: slot.width,
18089
16444
  height: slot.height
18090
16445
  },
18091
- children: /* @__PURE__ */ jsx32(
16446
+ children: /* @__PURE__ */ jsx30(
18092
16447
  DropIndicator,
18093
16448
  {
18094
16449
  direction: slot.direction,
@@ -18099,7 +16454,7 @@ function OhhwellsBridge() {
18099
16454
  },
18100
16455
  `footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
18101
16456
  )),
18102
- isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx32(
16457
+ isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx30(
18103
16458
  "div",
18104
16459
  {
18105
16460
  className: "pointer-events-none fixed z-2147483646",
@@ -18109,7 +16464,7 @@ function OhhwellsBridge() {
18109
16464
  width: slot.width,
18110
16465
  height: slot.height
18111
16466
  },
18112
- children: /* @__PURE__ */ jsx32(
16467
+ children: /* @__PURE__ */ jsx30(
18113
16468
  DropIndicator,
18114
16469
  {
18115
16470
  direction: slot.direction,
@@ -18120,10 +16475,10 @@ function OhhwellsBridge() {
18120
16475
  },
18121
16476
  `nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
18122
16477
  )),
18123
- hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx32(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
18124
- hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx32(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
18125
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ jsx32(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
18126
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx32(
16478
+ hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx30(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
16479
+ hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx30(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
16480
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ jsx30(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
16481
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx30(
18127
16482
  FooterContainerChrome,
18128
16483
  {
18129
16484
  rect: toolbarRect,
@@ -18131,7 +16486,7 @@ function OhhwellsBridge() {
18131
16486
  addDisabled: !canAddFooterColumn()
18132
16487
  }
18133
16488
  ),
18134
- toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame" || toolbarVariant === "logo") && /* @__PURE__ */ jsx32(
16489
+ toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ jsx30(
18135
16490
  ItemInteractionLayer,
18136
16491
  {
18137
16492
  rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
@@ -18143,10 +16498,10 @@ function OhhwellsBridge() {
18143
16498
  dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
18144
16499
  onDragHandleDragStart: handleItemDragStart,
18145
16500
  onDragHandleDragEnd: handleItemDragEnd,
18146
- onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
18147
- onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
18148
- itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
18149
- toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ jsx32(
16501
+ onItemPointerDown: handleItemChromePointerDown,
16502
+ onItemClick: handleItemChromeClick,
16503
+ itemDragSurface: !isFooterFrameSelection,
16504
+ toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && isFooterFrameSelection && !isItemDragging ? /* @__PURE__ */ jsx30(
18150
16505
  ItemActionToolbar,
18151
16506
  {
18152
16507
  onEditLink: openLinkPopoverForSelected,
@@ -18157,12 +16512,12 @@ function OhhwellsBridge() {
18157
16512
  addItemDisabled: false,
18158
16513
  editLinkDisabled: false,
18159
16514
  moreDisabled: false,
18160
- duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow,
18161
- showEditLink: !isFooterFrameSelection && !selectedIsSocialsRow && navDropdownPreviewOpen === null,
18162
- showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
16515
+ duplicateDisabled: isFooterFrameSelection,
16516
+ showEditLink: !isFooterFrameSelection && navDropdownPreviewOpen === null,
16517
+ showAddItem: isFooterFrameSelection || !selectedIsCta && Boolean(
18163
16518
  selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
18164
16519
  ),
18165
- showMore: (!selectedIsCta || isFooterFrameSelection) && !selectedIsSocialsRow,
16520
+ showMore: !selectedIsCta || isFooterFrameSelection,
18166
16521
  dropdownOpen: navDropdownPreviewOpen,
18167
16522
  onDropdownOpenChange: handleNavDropdownOpenChange,
18168
16523
  headingVisible: footerHeadingVisible,
@@ -18171,8 +16526,8 @@ function OhhwellsBridge() {
18171
16526
  ) : void 0
18172
16527
  }
18173
16528
  ),
18174
- toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ jsxs19(Fragment8, { children: [
18175
- /* @__PURE__ */ jsx32(
16529
+ toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ jsxs17(Fragment8, { children: [
16530
+ /* @__PURE__ */ jsx30(
18176
16531
  EditGlowChrome,
18177
16532
  {
18178
16533
  rect: toolbarRect,
@@ -18182,7 +16537,7 @@ function OhhwellsBridge() {
18182
16537
  hideHandle: isItemDragging
18183
16538
  }
18184
16539
  ),
18185
- /* @__PURE__ */ jsx32(
16540
+ /* @__PURE__ */ jsx30(
18186
16541
  FloatingToolbar,
18187
16542
  {
18188
16543
  rect: toolbarRect,
@@ -18195,7 +16550,7 @@ function OhhwellsBridge() {
18195
16550
  }
18196
16551
  )
18197
16552
  ] }),
18198
- maxBadge && /* @__PURE__ */ jsxs19(
16553
+ maxBadge && /* @__PURE__ */ jsxs17(
18199
16554
  "div",
18200
16555
  {
18201
16556
  "data-ohw-max-badge": "",
@@ -18221,7 +16576,7 @@ function OhhwellsBridge() {
18221
16576
  ]
18222
16577
  }
18223
16578
  ),
18224
- toggleState && !linkPopover && /* @__PURE__ */ jsx32(
16579
+ toggleState && !linkPopover && /* @__PURE__ */ jsx30(
18225
16580
  StateToggle,
18226
16581
  {
18227
16582
  rect: toggleState.rect,
@@ -18230,15 +16585,15 @@ function OhhwellsBridge() {
18230
16585
  onStateChange: handleStateChange
18231
16586
  }
18232
16587
  ),
18233
- sectionGap && !linkPopover && /* @__PURE__ */ jsxs19(
16588
+ sectionGap && !linkPopover && /* @__PURE__ */ jsxs17(
18234
16589
  "div",
18235
16590
  {
18236
16591
  "data-ohw-section-insert-line": "",
18237
16592
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
18238
16593
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
18239
16594
  children: [
18240
- /* @__PURE__ */ jsx32("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
18241
- /* @__PURE__ */ jsx32(
16595
+ /* @__PURE__ */ jsx30("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
16596
+ /* @__PURE__ */ jsx30(
18242
16597
  Badge,
18243
16598
  {
18244
16599
  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",
@@ -18255,11 +16610,11 @@ function OhhwellsBridge() {
18255
16610
  children: "Add Section"
18256
16611
  }
18257
16612
  ),
18258
- /* @__PURE__ */ jsx32("div", { className: "flex-1 bg-primary", style: { height: 3 } })
16613
+ /* @__PURE__ */ jsx30("div", { className: "flex-1 bg-primary", style: { height: 3 } })
18259
16614
  ]
18260
16615
  }
18261
16616
  ),
18262
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx32(
16617
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx30(
18263
16618
  LinkPopover,
18264
16619
  {
18265
16620
  panelRef: linkPopoverPanelRef,
@@ -18275,115 +16630,11 @@ function OhhwellsBridge() {
18275
16630
  onSubmit: handleLinkPopoverSubmit
18276
16631
  },
18277
16632
  linkPopover.key
18278
- ) : null,
18279
- floatingPanel && floatingPanel.kind === "logo-size" && logoSizeDraft ? /* @__PURE__ */ jsx32(
18280
- FloatingPanel,
18281
- {
18282
- open: true,
18283
- title: floatingPanel.title,
18284
- context: floatingPanel.context,
18285
- position: floatingPanelPos,
18286
- onPositionChange: setFloatingPanelPos,
18287
- parentScroll: parentScrollSnap ?? parentScrollRef.current,
18288
- onClose: closeFloatingPanelAndDeselect,
18289
- children: /* @__PURE__ */ jsx32(
18290
- LogoSizePanel,
18291
- {
18292
- viewport: editorViewport,
18293
- sizePx: editorViewport === "mobile" && !logoSizeDraft.mobileFollowing ? logoSizeDraft.mobilePx : logoSizeDraft.desktopPx,
18294
- mobileFollowing: logoSizeDraft.mobileFollowing,
18295
- onSizeChange: (px) => {
18296
- const next = editorViewport === "mobile" ? { ...logoSizeDraft, mobilePx: px, mobileFollowing: false } : {
18297
- ...logoSizeDraft,
18298
- desktopPx: px,
18299
- mobilePx: logoSizeDraft.mobileFollowing ? px : logoSizeDraft.mobilePx
18300
- };
18301
- setLogoSizeDraft(next);
18302
- persistLogoSizeDraft(floatingPanel.placement, next);
18303
- },
18304
- onCustomizeMobile: () => {
18305
- const next = {
18306
- ...logoSizeDraft,
18307
- mobileFollowing: false,
18308
- mobilePx: logoSizeDraft.desktopPx
18309
- };
18310
- setLogoSizeDraft(next);
18311
- persistLogoSizeDraft(floatingPanel.placement, next);
18312
- },
18313
- onResetMobile: () => {
18314
- const next = {
18315
- ...logoSizeDraft,
18316
- mobileFollowing: true,
18317
- mobilePx: logoSizeDraft.desktopPx
18318
- };
18319
- setLogoSizeDraft(next);
18320
- persistLogoSizeDraft(floatingPanel.placement, next);
18321
- },
18322
- onUpdateEverywhere: () => {
18323
- const identity = readLogoIdentityFromDom();
18324
- postToParent2({ type: "ow:open-logo-settings", ...identity });
18325
- }
18326
- }
18327
- )
18328
- }
18329
16633
  ) : null
18330
16634
  ] }),
18331
16635
  bridgeRoot
18332
16636
  ) : null;
18333
16637
  }
18334
-
18335
- // src/ui/EmptySection.tsx
18336
- import Link4 from "next/link";
18337
- import { Fragment as Fragment9, jsx as jsx33, jsxs as jsxs20 } from "react/jsx-runtime";
18338
- function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
18339
- return /* @__PURE__ */ jsxs20(Fragment9, { children: [
18340
- /* @__PURE__ */ jsx33(
18341
- "p",
18342
- {
18343
- style: {
18344
- fontFamily: "var(--brand-font-body)",
18345
- fontSize: "0.75rem",
18346
- fontWeight: 500,
18347
- letterSpacing: "0.15em",
18348
- textTransform: "uppercase",
18349
- color: "var(--brand-accent)",
18350
- marginBottom: "1.5rem"
18351
- },
18352
- children: /* @__PURE__ */ jsx33(Link4, { href: homeHref, style: { color: "inherit" }, children: /* @__PURE__ */ jsx33("span", { ...eyebrowKey ? { "data-ohw-editable": "text", "data-ohw-key": eyebrowKey } : {}, children: "Home" }) })
18353
- }
18354
- ),
18355
- /* @__PURE__ */ jsx33(
18356
- "h1",
18357
- {
18358
- style: {
18359
- fontFamily: "var(--brand-font-heading)",
18360
- fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
18361
- lineHeight: 1.1,
18362
- letterSpacing: "-0.025em",
18363
- color: "var(--brand-text)",
18364
- marginBottom: "1rem"
18365
- },
18366
- ...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
18367
- children: title
18368
- }
18369
- ),
18370
- /* @__PURE__ */ jsx33(
18371
- "p",
18372
- {
18373
- style: {
18374
- fontFamily: "var(--brand-font-body)",
18375
- fontSize: "1rem",
18376
- lineHeight: 1.7,
18377
- fontWeight: 300,
18378
- color: "var(--brand-text-muted)",
18379
- maxWidth: "340px"
18380
- },
18381
- ...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
18382
- children: "This page doesn't have any content yet."
18383
- }
18384
- )
18385
- ] });
18386
- }
18387
16638
  export {
18388
16639
  AI_DEFAULT_BRAND,
18389
16640
  AI_TREE_SCHEMA_VERSIONS,
@@ -18400,7 +16651,6 @@ export {
18400
16651
  DropdownMenuItem,
18401
16652
  DropdownMenuSeparator,
18402
16653
  DropdownMenuTrigger,
18403
- EmptySection,
18404
16654
  ItemActionToolbar,
18405
16655
  ItemInteractionLayer,
18406
16656
  LinkEditorPanel,