@ohhwells/bridge 0.1.134-next.362 → 0.1.135

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
@@ -2648,7 +2648,7 @@ var AI_MOBILE_CSS = [
2648
2648
  // page's first section. Top only (bottom needs no nav clearance); ~96px approximates the
2649
2649
  // template nav's own height (measured ~94px) — there's no shared `--ohw-header-h` var to read
2650
2650
  // an exact figure from (no live measurement exists), so this is a safe approximation, not a
2651
- // pixel-exact fit. Horizontal spacing already comes from `data-ai-section-inner`.
2651
+ // pixel-exact fit. Horizontal spacing already comes from `data-ai-container`.
2652
2652
  '[data-ai-overlay-clearance] [data-ai-overlap-layer="overlay"]{padding-top:96px}',
2653
2653
  // A full-bleed carousel's height is pure arithmetic: it spans the whole window, so 16/9 turns
2654
2654
  // window width straight into height. Measured at 16/9 it came out ~90% of the viewport at EVERY
@@ -2664,10 +2664,8 @@ var AI_MOBILE_CSS = [
2664
2664
  "[data-ai-section]{overflow-x:hidden}",
2665
2665
  // `:not([data-ai-full-bleed])`: this `!important` gutter beat the inline `padding: 0` that a
2666
2666
  // full-bleed section's container sets, so a carousel/media hero that is edge-to-edge on desktop
2667
- // still got a 20px band of section background down both sides on a phone. The footer's own
2668
- // container keeps the unguarded rule below — `data-ai-full-bleed` can never appear on it.
2669
- "[data-ai-section-inner]:not([data-ai-full-bleed]){padding:0 20px !important}",
2670
- "[data-ai-container]{padding:0 20px !important}",
2667
+ // still got a 20px band of section background down both sides on a phone.
2668
+ "[data-ai-container]:not([data-ai-full-bleed]){padding:0 20px !important}",
2671
2669
  "[data-ai-row]{display:flex !important;flex-direction:column !important;align-items:stretch !important}",
2672
2670
  "[data-ai-cell]{width:100%;min-width:0}",
2673
2671
  // The rule above turns every row into a COLUMN flex container on phones, which silently breaks
@@ -2868,31 +2866,6 @@ function pricingCardEmphasis(featured, ctx, hasBg) {
2868
2866
  function textAttrs(ctx, path) {
2869
2867
  return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
2870
2868
  }
2871
- var AI_RESPONSIVE_CSS = [
2872
- "@media (max-width: 960px) {",
2873
- " [data-ai-responsive] [data-ai-grid] { grid-template-columns: repeat(2, 1fr) !important; }",
2874
- ' [data-ai-responsive] [data-ai-grid="1"] { grid-template-columns: 1fr !important; }',
2875
- "}",
2876
- "@media (max-width: 640px) {",
2877
- " [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
2878
- " [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
2879
- // Group containers flatten to a column on phones; span placements come along for free.
2880
- // `:not([data-ai-group="overlap"])` for the same reason as the twin pair in AI_MOBILE_CSS — see
2881
- // the comment there. This sheet's copy is the narrower selector, so without the exemption it
2882
- // flattens an `overlap` hero below 640px even though the other rule stands down: measured a 390px
2883
- // viewport with the heading/CTA in flow *under* the image, 219px of section background where the
2884
- // layered text used to be.
2885
- ' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) { display: flex !important; flex-direction: column !important; }',
2886
- ' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) > * { grid-column: auto !important; }',
2887
- // `:not([data-ai-full-bleed])` for the same reason as the twin rule in AI_MOBILE_CSS: this one
2888
- // is narrower (0,2,0 vs 0,1,0) and also `!important`, so without the guard it wins outright and
2889
- // a full-bleed hero gets its 20px side band back below 640px only — the one width where the
2890
- // other rule had already been taught to stand down.
2891
- " [data-ai-responsive] [data-ai-section-inner]:not([data-ai-full-bleed]) { padding-left: 20px !important; padding-right: 20px !important; }",
2892
- " [data-ai-responsive] { overflow-x: hidden; }",
2893
- " [data-ai-responsive] img { max-width: 100%; }",
2894
- "}"
2895
- ].join("\n");
2896
2869
  var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
2897
2870
  function MediaBox({
2898
2871
  refValue,
@@ -2913,9 +2886,9 @@ function MediaBox({
2913
2886
  const url = refValue ? ctx.resolveMedia(refValue) : null;
2914
2887
  const isIcon = /^(lucide|simple):/.test(refValue);
2915
2888
  const aspectRatio = aspect && /^\d+:\d+$/.test(aspect) ? aspect.replace(":", " / ") : void 0;
2916
- const editAttrs = ctx.keyFor && editPath ? {
2889
+ const editAttrs = ctx.keyFor && editPath && !isIcon ? {
2917
2890
  "data-ohw-key": ctx.keyFor(editPath),
2918
- ...isIcon ? { "data-ohw-editable": "icon" } : genericImageEdit ? { "data-ohw-editable": "image" } : {}
2891
+ ...genericImageEdit ? { "data-ohw-editable": "image" } : {}
2919
2892
  } : {};
2920
2893
  if (isIcon) {
2921
2894
  const Icon = refValue.startsWith("lucide:") ? lucideByName(refValue.slice(7)) : null;
@@ -2923,7 +2896,6 @@ function MediaBox({
2923
2896
  "span",
2924
2897
  {
2925
2898
  "data-ai-icon": refValue,
2926
- ...editAttrs,
2927
2899
  style: {
2928
2900
  display: "inline-flex",
2929
2901
  width: 48,
@@ -4417,7 +4389,7 @@ function CollectionBlock({ node, ctx, path }) {
4417
4389
  return /* @__PURE__ */ jsx(
4418
4390
  "div",
4419
4391
  {
4420
- "data-ai-grid": String(itemsPerRow),
4392
+ "data-ai-grid": "",
4421
4393
  "data-ohw-pricing-collection": isPricing ? "" : void 0,
4422
4394
  style: {
4423
4395
  display: "grid",
@@ -4677,7 +4649,7 @@ function renderNode(node, ctx, path, ambientAlign) {
4677
4649
  },
4678
4650
  children: [
4679
4651
  i > 0 && ctx.heroOverlapFullBleed ? (
4680
- // The section's `data-ai-section-inner` gave up its max-width/gutter so the base
4652
+ // The section's `data-ai-container` gave up its max-width/gutter so the base
4681
4653
  // layer (this group's i===0 sibling) can span edge-to-edge — reintroduced here,
4682
4654
  // scoped to just the overlay text, so a heading/copy/CTA stack doesn't stretch
4683
4655
  // the full section width instead of reading at the usual content width.
@@ -5070,7 +5042,6 @@ function AiTreeRenderer({
5070
5042
  ...fillHeight ? { "data-ai-fill-height": "" } : {},
5071
5043
  ...needsOverlayClearance ? { "data-ai-overlay-clearance": "" } : {},
5072
5044
  ...bgAttrs,
5073
- "data-ai-responsive": "",
5074
5045
  style: {
5075
5046
  position: "relative",
5076
5047
  padding: `${padCss} 0`,
@@ -5084,13 +5055,12 @@ function AiTreeRenderer({
5084
5055
  ...fillHeight ? { display: "grid" } : {}
5085
5056
  },
5086
5057
  children: [
5087
- /* @__PURE__ */ jsx("style", { children: AI_RESPONSIVE_CSS }),
5088
- /* @__PURE__ */ jsx("style", { children: AI_MOBILE_CSS }),
5089
5058
  isOverlay && backgroundUrl && /* @__PURE__ */ jsx("div", { style: { position: "absolute", inset: 0, background: `rgba(255,255,255,${overlayAlpha})` } }),
5059
+ /* @__PURE__ */ jsx("style", { children: AI_MOBILE_CSS }),
5090
5060
  /* @__PURE__ */ jsx(
5091
5061
  "div",
5092
5062
  {
5093
- "data-ai-section-inner": "",
5063
+ "data-ai-container": "",
5094
5064
  ...fullBleedMedia ? { "data-ai-full-bleed": "" } : {},
5095
5065
  style: {
5096
5066
  position: "relative",
@@ -5107,7 +5077,7 @@ function AiTreeRenderer({
5107
5077
  children: tree.rows.map((row, r2) => /* @__PURE__ */ jsx(
5108
5078
  "div",
5109
5079
  {
5110
- "data-ai-columns": "",
5080
+ "data-ai-row": "",
5111
5081
  style: {
5112
5082
  display: "grid",
5113
5083
  gridTemplateColumns: "repeat(12, 1fr)",
@@ -5763,10 +5733,9 @@ function applyAiSectionsToDom(state, options) {
5763
5733
  if (existing && existing.serialized === serialized && existing.container.isConnected) {
5764
5734
  continue;
5765
5735
  }
5736
+ const isNewMount = !existing || !existing.container.isConnected;
5766
5737
  let container = existing?.container;
5767
- let isNewMount = false;
5768
5738
  if (!container || !container.isConnected) {
5769
- isNewMount = true;
5770
5739
  existing?.root.unmount();
5771
5740
  container?.remove();
5772
5741
  container = document.createElement("div");
@@ -13401,7 +13370,6 @@ function MediaOverlay({
13401
13370
  (prev) => prev && prev.fullWidth === width && prev.height === height ? prev : { fullWidth: width, height }
13402
13371
  );
13403
13372
  }, [isVideo]);
13404
- const replaceLabel = isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image";
13405
13373
  const replaceMode = buttonSize ? replaceButtonMode({ width: rect.width, height: rect.height }, buttonSize) : "none";
13406
13374
  const box = {
13407
13375
  position: "fixed",
@@ -13500,10 +13468,11 @@ function MediaOverlay({
13500
13468
  className: "flex items-center justify-center cursor-pointer",
13501
13469
  style: {
13502
13470
  ...box,
13503
- // Visual only. `pointer-events: auto` on this full-bleed rect covered the navbar
13504
- // (hero bg includes the absolute TopNav) and swallowed CTA press-drag. Text overlay
13505
- // and cueOnly also need clicks to fall through — Replace / video controls opt back in.
13506
- pointerEvents: "none",
13471
+ // When text overlays this media, let clicks fall THROUGH to the text underneath. In the
13472
+ // parent this needed a whole `ow:click-at` round-trip to re-hit-test inside the iframe;
13473
+ // in-document, pointer-events does it natively. The button below opts back in, so
13474
+ // Replace still works.
13475
+ pointerEvents: hover.hasTextOverlap || cueOnly ? "none" : "auto",
13507
13476
  // Selected: a firm component ring with no wash, so the image reads as chosen rather
13508
13477
  // than hovered. Hover keeps the existing tinted preview.
13509
13478
  boxShadow: selected ? "inset 0 0 0 2px var(--color-bridge-primary)" : "inset 0 0 0 1.5px var(--color-bridge-primary)",
@@ -13530,17 +13499,17 @@ function MediaOverlay({
13530
13499
  },
13531
13500
  children: [
13532
13501
  isVideo ? /* @__PURE__ */ jsx16(Film, { size: 14 }) : /* @__PURE__ */ jsx16(ImageIcon, { size: 14 }),
13533
- replaceLabel
13502
+ isVideo ? "Replace video" : "Replace image"
13534
13503
  ]
13535
13504
  }
13536
13505
  ),
13537
- showChrome && replaceMode !== "none" && /* @__PURE__ */ jsxs7(
13506
+ replaceMode === "none" || cueOnly ? null : /* @__PURE__ */ jsxs7(
13538
13507
  Button,
13539
13508
  {
13540
13509
  "data-ohw-media-overlay": "",
13541
13510
  variant: "outline",
13542
13511
  size: "sm",
13543
- "aria-label": replaceLabel,
13512
+ "aria-label": isVideo ? "Replace video" : "Replace image",
13544
13513
  className: "gap-1.5 cursor-pointer hover:bg-background",
13545
13514
  style: {
13546
13515
  ...OVERLAY_BUTTON_STYLE,
@@ -13563,7 +13532,7 @@ function MediaOverlay({
13563
13532
  },
13564
13533
  children: [
13565
13534
  isVideo ? /* @__PURE__ */ jsx16(Film, { size: 14 }) : /* @__PURE__ */ jsx16(ImageIcon, { size: 14 }),
13566
- replaceMode === "full" ? replaceLabel : null
13535
+ replaceMode === "full" ? isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image" : null
13567
13536
  ]
13568
13537
  }
13569
13538
  )
@@ -19795,7 +19764,6 @@ function readLogoSizeState(content, placement) {
19795
19764
  function getLogoElement(el) {
19796
19765
  const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
19797
19766
  if (marked) return marked;
19798
- if (el.closest('[data-ohw-editable="icon"]')) return null;
19799
19767
  const root = el.closest("nav, [data-ohw-nav-root], footer");
19800
19768
  if (!root) return null;
19801
19769
  const anchor = el.closest("a");
@@ -23293,7 +23261,7 @@ function getNavigationSelectionParent(el) {
23293
23261
  if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
23294
23262
  return resolveFooterLinksContainerFrom(el);
23295
23263
  }
23296
- 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)) {
23264
+ if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
23297
23265
  return getNavigationRoot(el);
23298
23266
  }
23299
23267
  return null;
@@ -23515,6 +23483,7 @@ var ICONS = {
23515
23483
  insertUnorderedList: '<line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/>',
23516
23484
  insertOrderedList: '<line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"/>'
23517
23485
  };
23486
+ var HEIGHT_SETTLE_DELAYS = [150, 400, 800];
23518
23487
  var SELECTION_CHROME_GAP2 = 4;
23519
23488
  var TOOLBAR_STROKE_GAP2 = 4;
23520
23489
  var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
@@ -24494,6 +24463,21 @@ function OhhwellsBridge() {
24494
24463
  const [isItemDragging, setIsItemDragging] = useState18(false);
24495
24464
  const [isFooterFrameSelection, setIsFooterFrameSelection] = useState18(false);
24496
24465
  isFooterFrameSelectionRef.current = isFooterFrameSelection;
24466
+ const [floatingPanel, setFloatingPanel] = useState18(null);
24467
+ const floatingPanelOpenRef = useRef14(false);
24468
+ floatingPanelOpenRef.current = floatingPanel !== null;
24469
+ const floatingPanelRef = useRef14(null);
24470
+ floatingPanelRef.current = floatingPanel;
24471
+ const [floatingPanelPos, setFloatingPanelPos] = useState18(null);
24472
+ const buttonCollectionDragRef = useRef14(null);
24473
+ const buttonDropInsertIndexRef = useRef14(null);
24474
+ const [buttonDropSlots, setButtonDropSlots] = useState18([]);
24475
+ const [activeButtonDropIndex, setActiveButtonDropIndex] = useState18(null);
24476
+ const buttonPointerDragRef = useRef14(null);
24477
+ const [buttonStyleTick, setButtonStyleTick] = useState18(0);
24478
+ const [logoSizeDraft, setLogoSizeDraft] = useState18(null);
24479
+ const [editorViewport, setEditorViewport] = useState18("desktop");
24480
+ const [parentScrollSnap, setParentScrollSnap] = useState18(null);
24497
24481
  const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = useState18(null);
24498
24482
  const [footerHeadingVisible, setFooterHeadingVisible] = useState18(null);
24499
24483
  const footerDragRef = useRef14(null);
@@ -24519,21 +24503,6 @@ function OhhwellsBridge() {
24519
24503
  const stylesRef = useRef14("");
24520
24504
  const appliedDrawerRef = useRef14(null);
24521
24505
  const pendingDeleteUndoRef = useRef14(null);
24522
- const [floatingPanel, setFloatingPanel] = useState18(null);
24523
- const floatingPanelOpenRef = useRef14(false);
24524
- const floatingPanelRef = useRef14(null);
24525
- floatingPanelRef.current = floatingPanel;
24526
- const setFloatingPanelRef = useRef14(setFloatingPanel);
24527
- const [floatingPanelPos, setFloatingPanelPos] = useState18(null);
24528
- const buttonCollectionDragRef = useRef14(null);
24529
- const buttonDropInsertIndexRef = useRef14(null);
24530
- const [buttonDropSlots, setButtonDropSlots] = useState18([]);
24531
- const [activeButtonDropIndex, setActiveButtonDropIndex] = useState18(null);
24532
- const buttonPointerDragRef = useRef14(null);
24533
- const [buttonStyleTick, setButtonStyleTick] = useState18(0);
24534
- const [logoSizeDraft, setLogoSizeDraft] = useState18(null);
24535
- const [editorViewport, setEditorViewport] = useState18("desktop");
24536
- const [parentScrollSnap, setParentScrollSnap] = useState18(null);
24537
24506
  const [sitePages, setSitePages] = useState18([]);
24538
24507
  const [sectionsByPath, setSectionsByPath] = useState18({});
24539
24508
  const sectionsPrefetchGenRef = useRef14(0);
@@ -24542,18 +24511,7 @@ function OhhwellsBridge() {
24542
24511
  const linkPopoverOpenRef = useRef14(false);
24543
24512
  const linkPopoverGraceUntilRef = useRef14(0);
24544
24513
  setLinkPopoverRef.current = setLinkPopover;
24545
- setFloatingPanelRef.current = setFloatingPanel;
24546
24514
  linkPopoverSessionRef.current = linkPopover;
24547
- floatingPanelOpenRef.current = Boolean(floatingPanel);
24548
- useEffect17(() => {
24549
- const syncViewport = () => {
24550
- const next = window.innerWidth <= 480 ? "mobile" : "desktop";
24551
- setEditorViewport((prev) => prev === next ? prev : next);
24552
- };
24553
- syncViewport();
24554
- window.addEventListener("resize", syncViewport);
24555
- return () => window.removeEventListener("resize", syncViewport);
24556
- }, []);
24557
24515
  useEffect17(() => {
24558
24516
  setSectionOrderPersistHandler((entries) => {
24559
24517
  const currentPath = window.location.pathname;
@@ -26232,7 +26190,6 @@ function OhhwellsBridge() {
26232
26190
  applyAiFooterFromContent(content);
26233
26191
  if (typeof content[STYLE_STORE_KEY] === "string") {
26234
26192
  stylesRef.current = content[STYLE_STORE_KEY];
26235
- document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
26236
26193
  applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
26237
26194
  }
26238
26195
  applyBrandChrome(content);
@@ -26242,12 +26199,12 @@ function OhhwellsBridge() {
26242
26199
  if (key === "__ohw_sections") continue;
26243
26200
  if (key === AI_SECTIONS_KEY) continue;
26244
26201
  if (key === AI_FOOTER_KEY) continue;
26245
- if (key === LOGO_PLACEHOLDER_KEY) continue;
26246
- if (LOGO_IMAGE_KEYS.includes(key)) continue;
26247
26202
  if (key === BRAND_KIT_KEY) continue;
26248
26203
  if (key === STYLE_STORE_KEY) continue;
26249
26204
  if (BRAND_CHROME_KEYS.has(key)) continue;
26205
+ if (key === LOGO_PLACEHOLDER_KEY) continue;
26250
26206
  if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
26207
+ if (LOGO_IMAGE_KEYS.includes(key)) continue;
26251
26208
  if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
26252
26209
  continue;
26253
26210
  }
@@ -26461,18 +26418,17 @@ function OhhwellsBridge() {
26461
26418
  }
26462
26419
  applyAiFooterFromContent(content);
26463
26420
  if (typeof content[STYLE_STORE_KEY] === "string") {
26464
- document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
26465
26421
  applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
26466
26422
  }
26467
26423
  for (const [key, val] of Object.entries(content)) {
26468
26424
  if (key === "__ohw_sections") continue;
26469
26425
  if (key === AI_SECTIONS_KEY) continue;
26470
26426
  if (key === AI_FOOTER_KEY) continue;
26471
- if (key === LOGO_PLACEHOLDER_KEY) continue;
26472
- if (LOGO_IMAGE_KEYS.includes(key)) continue;
26473
26427
  if (key === BRAND_KIT_KEY) continue;
26474
26428
  if (key === STYLE_STORE_KEY) continue;
26475
26429
  if (BRAND_CHROME_KEYS.has(key)) continue;
26430
+ if (key === LOGO_PLACEHOLDER_KEY) continue;
26431
+ if (LOGO_IMAGE_KEYS.includes(key)) continue;
26476
26432
  if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
26477
26433
  continue;
26478
26434
  }
@@ -26728,11 +26684,26 @@ function OhhwellsBridge() {
26728
26684
  const t2 = setTimeout(measure, 500);
26729
26685
  const ro = new ResizeObserver(schedule);
26730
26686
  ro.observe(document.body);
26687
+ let lastWidth = window.innerWidth;
26688
+ let resizeTimers = [];
26689
+ const clearResizeTimers = () => {
26690
+ resizeTimers.forEach(clearTimeout);
26691
+ resizeTimers = [];
26692
+ };
26693
+ const handleResize = () => {
26694
+ if (window.innerWidth === lastWidth) return;
26695
+ lastWidth = window.innerWidth;
26696
+ clearResizeTimers();
26697
+ resizeTimers = HEIGHT_SETTLE_DELAYS.map((delay) => setTimeout(measure, delay));
26698
+ };
26699
+ window.addEventListener("resize", handleResize);
26731
26700
  return () => {
26732
26701
  clearTimeout(t1);
26733
26702
  clearTimeout(t2);
26734
26703
  if (raf != null) cancelAnimationFrame(raf);
26735
26704
  ro.disconnect();
26705
+ clearResizeTimers();
26706
+ window.removeEventListener("resize", handleResize);
26736
26707
  };
26737
26708
  }, [pathname, isEditMode, postToParent2]);
26738
26709
  useEffect17(() => {
@@ -27027,13 +26998,6 @@ function OhhwellsBridge() {
27027
26998
  if (target.closest("[data-ohw-state-toggle]")) return;
27028
26999
  if (target.closest("[data-ohw-max-badge]")) return;
27029
27000
  if (isInsideLinkEditor(target)) return;
27030
- if (isInsideFloatingPanel(target)) return;
27031
- if (target.closest("[data-ohw-form-toolbar]")) return;
27032
- if (target.closest(
27033
- '[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
27034
- )) {
27035
- return;
27036
- }
27037
27001
  if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
27038
27002
  clearMediaSelectionRef.current();
27039
27003
  }
@@ -27054,6 +27018,13 @@ function OhhwellsBridge() {
27054
27018
  return;
27055
27019
  }
27056
27020
  }
27021
+ if (isInsideFloatingPanel(target)) return;
27022
+ if (target.closest("[data-ohw-form-toolbar]")) return;
27023
+ if (target.closest(
27024
+ '[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
27025
+ )) {
27026
+ return;
27027
+ }
27057
27028
  {
27058
27029
  const formEl = getFormElement(target);
27059
27030
  const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
@@ -27433,9 +27404,6 @@ function OhhwellsBridge() {
27433
27404
  setHoveredItemRect(null);
27434
27405
  hoveredNavContainerRef.current = null;
27435
27406
  setHoveredNavContainerRect(null);
27436
- siblingHintElRef.current = null;
27437
- setSiblingHintRect(null);
27438
- setSiblingHintRects([]);
27439
27407
  return;
27440
27408
  }
27441
27409
  {
@@ -27556,6 +27524,7 @@ function OhhwellsBridge() {
27556
27524
  hoveredNavContainerRef.current = null;
27557
27525
  setHoveredNavContainerRect(null);
27558
27526
  hoveredItemElRef.current = editable;
27527
+ setHoveredItemRect(isSelectedForHoverRef.current(editable) ? null : editable.getBoundingClientRect());
27559
27528
  }
27560
27529
  }
27561
27530
  }
@@ -28265,11 +28234,7 @@ function OhhwellsBridge() {
28265
28234
  };
28266
28235
  const handleMouseMove = (e) => {
28267
28236
  const { clientX, clientY } = e;
28268
- if (pointOwnedByFloatingPanel(clientX, clientY)) {
28269
- dismissImageHover();
28270
- clearImageHover();
28271
- return;
28272
- }
28237
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
28273
28238
  if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) {
28274
28239
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
28275
28240
  formHoverElRef.current = null;
@@ -28298,12 +28263,7 @@ function OhhwellsBridge() {
28298
28263
  setHoveredItemRect(null);
28299
28264
  hoveredNavContainerRef.current = null;
28300
28265
  setHoveredNavContainerRect(null);
28301
- siblingHintElRef.current = null;
28302
- setSiblingHintRect(null);
28303
- setSiblingHintRects([]);
28304
28266
  dismissImageHover();
28305
- clearImageHover();
28306
- setSectionGap(null);
28307
28267
  return;
28308
28268
  }
28309
28269
  if (probeSocialsRowAt(clientX, clientY)) return;
@@ -28315,11 +28275,7 @@ function OhhwellsBridge() {
28315
28275
  if (e.data?.type !== "ow:pointer-sync") return;
28316
28276
  const { clientX, clientY } = e.data;
28317
28277
  if (typeof clientX !== "number" || typeof clientY !== "number") return;
28318
- if (pointOwnedByFloatingPanel(clientX, clientY)) {
28319
- dismissImageHover();
28320
- clearImageHover();
28321
- return;
28322
- }
28278
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
28323
28279
  if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) return;
28324
28280
  if (probeSocialsRowAt(clientX, clientY)) return;
28325
28281
  probeSectionGapAt(clientX, clientY);
@@ -28671,7 +28627,6 @@ function OhhwellsBridge() {
28671
28627
  applyAiFooterFromContent(content);
28672
28628
  if (typeof content[STYLE_STORE_KEY] === "string") {
28673
28629
  stylesRef.current = content[STYLE_STORE_KEY];
28674
- document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
28675
28630
  applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
28676
28631
  }
28677
28632
  applyBrandChrome(content);
@@ -28685,12 +28640,12 @@ function OhhwellsBridge() {
28685
28640
  }
28686
28641
  if (key === AI_SECTIONS_KEY) continue;
28687
28642
  if (key === AI_FOOTER_KEY) continue;
28688
- if (key === LOGO_PLACEHOLDER_KEY) continue;
28689
- if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
28690
28643
  if (key === BRAND_KIT_KEY) continue;
28691
28644
  if (key === STYLE_STORE_KEY) continue;
28692
28645
  if (BRAND_CHROME_KEYS.has(key)) continue;
28646
+ if (key === LOGO_PLACEHOLDER_KEY) continue;
28693
28647
  if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
28648
+ if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
28694
28649
  if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
28695
28650
  continue;
28696
28651
  }
@@ -29227,12 +29182,6 @@ function OhhwellsBridge() {
29227
29182
  closeLinkPopoverRef.current();
29228
29183
  return;
29229
29184
  }
29230
- if (floatingPanelOpenRef.current) {
29231
- setFloatingPanelRef.current(null);
29232
- deselectRef.current();
29233
- deactivateRef.current();
29234
- return;
29235
- }
29236
29185
  deselectRef.current();
29237
29186
  deactivateRef.current();
29238
29187
  clearMediaSelectionRef.current();
@@ -29995,10 +29944,10 @@ function OhhwellsBridge() {
29995
29944
  window.removeEventListener("message", handleDeleteSection);
29996
29945
  window.removeEventListener("message", handleDuplicateSection);
29997
29946
  window.removeEventListener("message", handleDeactivate);
29947
+ document.documentElement.removeAttribute("data-ohw-panel-dragging");
29998
29948
  window.removeEventListener("message", handleToastAction);
29999
29949
  window.removeEventListener("message", handleFormCount);
30000
29950
  window.removeEventListener("message", handleUiEscape);
30001
- document.documentElement.removeAttribute("data-ohw-panel-dragging");
30002
29951
  autoSaveTimers.current.forEach(clearTimeout);
30003
29952
  autoSaveTimers.current.clear();
30004
29953
  if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);