@ohhwells/bridge 0.1.132-next.357 → 0.1.132

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.cjs CHANGED
@@ -2727,7 +2727,7 @@ var AI_MOBILE_CSS = [
2727
2727
  // page's first section. Top only (bottom needs no nav clearance); ~96px approximates the
2728
2728
  // template nav's own height (measured ~94px) — there's no shared `--ohw-header-h` var to read
2729
2729
  // an exact figure from (no live measurement exists), so this is a safe approximation, not a
2730
- // pixel-exact fit. Horizontal spacing already comes from `data-ai-section-inner`.
2730
+ // pixel-exact fit. Horizontal spacing already comes from `data-ai-container`.
2731
2731
  '[data-ai-overlay-clearance] [data-ai-overlap-layer="overlay"]{padding-top:96px}',
2732
2732
  // A full-bleed carousel's height is pure arithmetic: it spans the whole window, so 16/9 turns
2733
2733
  // window width straight into height. Measured at 16/9 it came out ~90% of the viewport at EVERY
@@ -2743,10 +2743,8 @@ var AI_MOBILE_CSS = [
2743
2743
  "[data-ai-section]{overflow-x:hidden}",
2744
2744
  // `:not([data-ai-full-bleed])`: this `!important` gutter beat the inline `padding: 0` that a
2745
2745
  // full-bleed section's container sets, so a carousel/media hero that is edge-to-edge on desktop
2746
- // still got a 20px band of section background down both sides on a phone. The footer's own
2747
- // container keeps the unguarded rule below — `data-ai-full-bleed` can never appear on it.
2748
- "[data-ai-section-inner]:not([data-ai-full-bleed]){padding:0 20px !important}",
2749
- "[data-ai-container]{padding:0 20px !important}",
2746
+ // still got a 20px band of section background down both sides on a phone.
2747
+ "[data-ai-container]:not([data-ai-full-bleed]){padding:0 20px !important}",
2750
2748
  "[data-ai-row]{display:flex !important;flex-direction:column !important;align-items:stretch !important}",
2751
2749
  "[data-ai-cell]{width:100%;min-width:0}",
2752
2750
  // The rule above turns every row into a COLUMN flex container on phones, which silently breaks
@@ -2947,31 +2945,6 @@ function pricingCardEmphasis(featured, ctx, hasBg) {
2947
2945
  function textAttrs(ctx, path) {
2948
2946
  return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
2949
2947
  }
2950
- var AI_RESPONSIVE_CSS = [
2951
- "@media (max-width: 960px) {",
2952
- " [data-ai-responsive] [data-ai-grid] { grid-template-columns: repeat(2, 1fr) !important; }",
2953
- ' [data-ai-responsive] [data-ai-grid="1"] { grid-template-columns: 1fr !important; }',
2954
- "}",
2955
- "@media (max-width: 640px) {",
2956
- " [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
2957
- " [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
2958
- // Group containers flatten to a column on phones; span placements come along for free.
2959
- // `:not([data-ai-group="overlap"])` for the same reason as the twin pair in AI_MOBILE_CSS — see
2960
- // the comment there. This sheet's copy is the narrower selector, so without the exemption it
2961
- // flattens an `overlap` hero below 640px even though the other rule stands down: measured a 390px
2962
- // viewport with the heading/CTA in flow *under* the image, 219px of section background where the
2963
- // layered text used to be.
2964
- ' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) { display: flex !important; flex-direction: column !important; }',
2965
- ' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) > * { grid-column: auto !important; }',
2966
- // `:not([data-ai-full-bleed])` for the same reason as the twin rule in AI_MOBILE_CSS: this one
2967
- // is narrower (0,2,0 vs 0,1,0) and also `!important`, so without the guard it wins outright and
2968
- // a full-bleed hero gets its 20px side band back below 640px only — the one width where the
2969
- // other rule had already been taught to stand down.
2970
- " [data-ai-responsive] [data-ai-section-inner]:not([data-ai-full-bleed]) { padding-left: 20px !important; padding-right: 20px !important; }",
2971
- " [data-ai-responsive] { overflow-x: hidden; }",
2972
- " [data-ai-responsive] img { max-width: 100%; }",
2973
- "}"
2974
- ].join("\n");
2975
2948
  var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
2976
2949
  function MediaBox({
2977
2950
  refValue,
@@ -2992,9 +2965,9 @@ function MediaBox({
2992
2965
  const url = refValue ? ctx.resolveMedia(refValue) : null;
2993
2966
  const isIcon = /^(lucide|simple):/.test(refValue);
2994
2967
  const aspectRatio = aspect && /^\d+:\d+$/.test(aspect) ? aspect.replace(":", " / ") : void 0;
2995
- const editAttrs = ctx.keyFor && editPath ? {
2968
+ const editAttrs = ctx.keyFor && editPath && !isIcon ? {
2996
2969
  "data-ohw-key": ctx.keyFor(editPath),
2997
- ...isIcon ? { "data-ohw-editable": "icon" } : genericImageEdit ? { "data-ohw-editable": "image" } : {}
2970
+ ...genericImageEdit ? { "data-ohw-editable": "image" } : {}
2998
2971
  } : {};
2999
2972
  if (isIcon) {
3000
2973
  const Icon = refValue.startsWith("lucide:") ? lucideByName(refValue.slice(7)) : null;
@@ -3002,7 +2975,6 @@ function MediaBox({
3002
2975
  "span",
3003
2976
  {
3004
2977
  "data-ai-icon": refValue,
3005
- ...editAttrs,
3006
2978
  style: {
3007
2979
  display: "inline-flex",
3008
2980
  width: 48,
@@ -4489,7 +4461,7 @@ function CollectionBlock({ node, ctx, path }) {
4489
4461
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
4490
4462
  "div",
4491
4463
  {
4492
- "data-ai-grid": String(itemsPerRow),
4464
+ "data-ai-grid": "",
4493
4465
  "data-ohw-pricing-collection": isPricing ? "" : void 0,
4494
4466
  style: {
4495
4467
  display: "grid",
@@ -4749,7 +4721,7 @@ function renderNode(node, ctx, path, ambientAlign) {
4749
4721
  },
4750
4722
  children: [
4751
4723
  i > 0 && ctx.heroOverlapFullBleed ? (
4752
- // The section's `data-ai-section-inner` gave up its max-width/gutter so the base
4724
+ // The section's `data-ai-container` gave up its max-width/gutter so the base
4753
4725
  // layer (this group's i===0 sibling) can span edge-to-edge — reintroduced here,
4754
4726
  // scoped to just the overlay text, so a heading/copy/CTA stack doesn't stretch
4755
4727
  // the full section width instead of reading at the usual content width.
@@ -5142,7 +5114,6 @@ function AiTreeRenderer({
5142
5114
  ...fillHeight ? { "data-ai-fill-height": "" } : {},
5143
5115
  ...needsOverlayClearance ? { "data-ai-overlay-clearance": "" } : {},
5144
5116
  ...bgAttrs,
5145
- "data-ai-responsive": "",
5146
5117
  style: {
5147
5118
  position: "relative",
5148
5119
  padding: `${padCss} 0`,
@@ -5156,13 +5127,12 @@ function AiTreeRenderer({
5156
5127
  ...fillHeight ? { display: "grid" } : {}
5157
5128
  },
5158
5129
  children: [
5159
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_RESPONSIVE_CSS }),
5160
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_MOBILE_CSS }),
5161
5130
  isOverlay && backgroundUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { position: "absolute", inset: 0, background: `rgba(255,255,255,${overlayAlpha})` } }),
5131
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_MOBILE_CSS }),
5162
5132
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5163
5133
  "div",
5164
5134
  {
5165
- "data-ai-section-inner": "",
5135
+ "data-ai-container": "",
5166
5136
  ...fullBleedMedia ? { "data-ai-full-bleed": "" } : {},
5167
5137
  style: {
5168
5138
  position: "relative",
@@ -5179,7 +5149,7 @@ function AiTreeRenderer({
5179
5149
  children: tree.rows.map((row, r2) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
5180
5150
  "div",
5181
5151
  {
5182
- "data-ai-columns": "",
5152
+ "data-ai-row": "",
5183
5153
  style: {
5184
5154
  display: "grid",
5185
5155
  gridTemplateColumns: "repeat(12, 1fr)",
@@ -5835,10 +5805,9 @@ function applyAiSectionsToDom(state, options) {
5835
5805
  if (existing && existing.serialized === serialized && existing.container.isConnected) {
5836
5806
  continue;
5837
5807
  }
5808
+ const isNewMount = !existing || !existing.container.isConnected;
5838
5809
  let container = existing?.container;
5839
- let isNewMount = false;
5840
5810
  if (!container || !container.isConnected) {
5841
- isNewMount = true;
5842
5811
  existing?.root.unmount();
5843
5812
  container?.remove();
5844
5813
  container = document.createElement("div");
@@ -13471,7 +13440,6 @@ function MediaOverlay({
13471
13440
  (prev) => prev && prev.fullWidth === width && prev.height === height ? prev : { fullWidth: width, height }
13472
13441
  );
13473
13442
  }, [isVideo]);
13474
- const replaceLabel = isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image";
13475
13443
  const replaceMode = buttonSize ? replaceButtonMode({ width: rect.width, height: rect.height }, buttonSize) : "none";
13476
13444
  const box = {
13477
13445
  position: "fixed",
@@ -13570,10 +13538,11 @@ function MediaOverlay({
13570
13538
  className: "flex items-center justify-center cursor-pointer",
13571
13539
  style: {
13572
13540
  ...box,
13573
- // Visual only. `pointer-events: auto` on this full-bleed rect covered the navbar
13574
- // (hero bg includes the absolute TopNav) and swallowed CTA press-drag. Text overlay
13575
- // and cueOnly also need clicks to fall through — Replace / video controls opt back in.
13576
- pointerEvents: "none",
13541
+ // When text overlays this media, let clicks fall THROUGH to the text underneath. In the
13542
+ // parent this needed a whole `ow:click-at` round-trip to re-hit-test inside the iframe;
13543
+ // in-document, pointer-events does it natively. The button below opts back in, so
13544
+ // Replace still works.
13545
+ pointerEvents: hover.hasTextOverlap || cueOnly ? "none" : "auto",
13577
13546
  // Selected: a firm component ring with no wash, so the image reads as chosen rather
13578
13547
  // than hovered. Hover keeps the existing tinted preview.
13579
13548
  boxShadow: selected ? "inset 0 0 0 2px var(--color-bridge-primary)" : "inset 0 0 0 1.5px var(--color-bridge-primary)",
@@ -13600,17 +13569,17 @@ function MediaOverlay({
13600
13569
  },
13601
13570
  children: [
13602
13571
  isVideo ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react5.Film, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react5.ImageIcon, { size: 14 }),
13603
- replaceLabel
13572
+ isVideo ? "Replace video" : "Replace image"
13604
13573
  ]
13605
13574
  }
13606
13575
  ),
13607
- showChrome && replaceMode !== "none" && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
13576
+ replaceMode === "none" || cueOnly ? null : /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
13608
13577
  Button,
13609
13578
  {
13610
13579
  "data-ohw-media-overlay": "",
13611
13580
  variant: "outline",
13612
13581
  size: "sm",
13613
- "aria-label": replaceLabel,
13582
+ "aria-label": isVideo ? "Replace video" : "Replace image",
13614
13583
  className: "gap-1.5 cursor-pointer hover:bg-background",
13615
13584
  style: {
13616
13585
  ...OVERLAY_BUTTON_STYLE,
@@ -13633,7 +13602,7 @@ function MediaOverlay({
13633
13602
  },
13634
13603
  children: [
13635
13604
  isVideo ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react5.Film, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react5.ImageIcon, { size: 14 }),
13636
- replaceMode === "full" ? replaceLabel : null
13605
+ replaceMode === "full" ? isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image" : null
13637
13606
  ]
13638
13607
  }
13639
13608
  )
@@ -19713,7 +19682,6 @@ function readLogoSizeState(content, placement) {
19713
19682
  function getLogoElement(el) {
19714
19683
  const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
19715
19684
  if (marked) return marked;
19716
- if (el.closest('[data-ohw-editable="icon"]')) return null;
19717
19685
  const root = el.closest("nav, [data-ohw-nav-root], footer");
19718
19686
  if (!root) return null;
19719
19687
  const anchor = el.closest("a");
@@ -23205,7 +23173,7 @@ function getNavigationSelectionParent(el) {
23205
23173
  if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
23206
23174
  return resolveFooterLinksContainerFrom(el);
23207
23175
  }
23208
- 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)) {
23176
+ if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
23209
23177
  return getNavigationRoot(el);
23210
23178
  }
23211
23179
  return null;
@@ -23427,6 +23395,7 @@ var ICONS = {
23427
23395
  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"/>',
23428
23396
  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"/>'
23429
23397
  };
23398
+ var HEIGHT_SETTLE_DELAYS = [150, 400, 800];
23430
23399
  var SELECTION_CHROME_GAP2 = 4;
23431
23400
  var TOOLBAR_STROKE_GAP2 = 4;
23432
23401
  var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
@@ -24406,6 +24375,21 @@ function OhhwellsBridge() {
24406
24375
  const [isItemDragging, setIsItemDragging] = (0, import_react21.useState)(false);
24407
24376
  const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react21.useState)(false);
24408
24377
  isFooterFrameSelectionRef.current = isFooterFrameSelection;
24378
+ const [floatingPanel, setFloatingPanel] = (0, import_react21.useState)(null);
24379
+ const floatingPanelOpenRef = (0, import_react21.useRef)(false);
24380
+ floatingPanelOpenRef.current = floatingPanel !== null;
24381
+ const floatingPanelRef = (0, import_react21.useRef)(null);
24382
+ floatingPanelRef.current = floatingPanel;
24383
+ const [floatingPanelPos, setFloatingPanelPos] = (0, import_react21.useState)(null);
24384
+ const buttonCollectionDragRef = (0, import_react21.useRef)(null);
24385
+ const buttonDropInsertIndexRef = (0, import_react21.useRef)(null);
24386
+ const [buttonDropSlots, setButtonDropSlots] = (0, import_react21.useState)([]);
24387
+ const [activeButtonDropIndex, setActiveButtonDropIndex] = (0, import_react21.useState)(null);
24388
+ const buttonPointerDragRef = (0, import_react21.useRef)(null);
24389
+ const [buttonStyleTick, setButtonStyleTick] = (0, import_react21.useState)(0);
24390
+ const [logoSizeDraft, setLogoSizeDraft] = (0, import_react21.useState)(null);
24391
+ const [editorViewport, setEditorViewport] = (0, import_react21.useState)("desktop");
24392
+ const [parentScrollSnap, setParentScrollSnap] = (0, import_react21.useState)(null);
24409
24393
  const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react21.useState)(null);
24410
24394
  const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react21.useState)(null);
24411
24395
  const footerDragRef = (0, import_react21.useRef)(null);
@@ -24431,21 +24415,6 @@ function OhhwellsBridge() {
24431
24415
  const stylesRef = (0, import_react21.useRef)("");
24432
24416
  const appliedDrawerRef = (0, import_react21.useRef)(null);
24433
24417
  const pendingDeleteUndoRef = (0, import_react21.useRef)(null);
24434
- const [floatingPanel, setFloatingPanel] = (0, import_react21.useState)(null);
24435
- const floatingPanelOpenRef = (0, import_react21.useRef)(false);
24436
- const floatingPanelRef = (0, import_react21.useRef)(null);
24437
- floatingPanelRef.current = floatingPanel;
24438
- const setFloatingPanelRef = (0, import_react21.useRef)(setFloatingPanel);
24439
- const [floatingPanelPos, setFloatingPanelPos] = (0, import_react21.useState)(null);
24440
- const buttonCollectionDragRef = (0, import_react21.useRef)(null);
24441
- const buttonDropInsertIndexRef = (0, import_react21.useRef)(null);
24442
- const [buttonDropSlots, setButtonDropSlots] = (0, import_react21.useState)([]);
24443
- const [activeButtonDropIndex, setActiveButtonDropIndex] = (0, import_react21.useState)(null);
24444
- const buttonPointerDragRef = (0, import_react21.useRef)(null);
24445
- const [buttonStyleTick, setButtonStyleTick] = (0, import_react21.useState)(0);
24446
- const [logoSizeDraft, setLogoSizeDraft] = (0, import_react21.useState)(null);
24447
- const [editorViewport, setEditorViewport] = (0, import_react21.useState)("desktop");
24448
- const [parentScrollSnap, setParentScrollSnap] = (0, import_react21.useState)(null);
24449
24418
  const [sitePages, setSitePages] = (0, import_react21.useState)([]);
24450
24419
  const [sectionsByPath, setSectionsByPath] = (0, import_react21.useState)({});
24451
24420
  const sectionsPrefetchGenRef = (0, import_react21.useRef)(0);
@@ -24454,18 +24423,7 @@ function OhhwellsBridge() {
24454
24423
  const linkPopoverOpenRef = (0, import_react21.useRef)(false);
24455
24424
  const linkPopoverGraceUntilRef = (0, import_react21.useRef)(0);
24456
24425
  setLinkPopoverRef.current = setLinkPopover;
24457
- setFloatingPanelRef.current = setFloatingPanel;
24458
24426
  linkPopoverSessionRef.current = linkPopover;
24459
- floatingPanelOpenRef.current = Boolean(floatingPanel);
24460
- (0, import_react21.useEffect)(() => {
24461
- const syncViewport = () => {
24462
- const next = window.innerWidth <= 480 ? "mobile" : "desktop";
24463
- setEditorViewport((prev) => prev === next ? prev : next);
24464
- };
24465
- syncViewport();
24466
- window.addEventListener("resize", syncViewport);
24467
- return () => window.removeEventListener("resize", syncViewport);
24468
- }, []);
24469
24427
  (0, import_react21.useEffect)(() => {
24470
24428
  setSectionOrderPersistHandler((entries) => {
24471
24429
  const currentPath = window.location.pathname;
@@ -26144,7 +26102,6 @@ function OhhwellsBridge() {
26144
26102
  applyAiFooterFromContent(content);
26145
26103
  if (typeof content[STYLE_STORE_KEY] === "string") {
26146
26104
  stylesRef.current = content[STYLE_STORE_KEY];
26147
- document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
26148
26105
  applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
26149
26106
  }
26150
26107
  applyBrandChrome(content);
@@ -26154,12 +26111,12 @@ function OhhwellsBridge() {
26154
26111
  if (key === "__ohw_sections") continue;
26155
26112
  if (key === AI_SECTIONS_KEY) continue;
26156
26113
  if (key === AI_FOOTER_KEY) continue;
26157
- if (key === LOGO_PLACEHOLDER_KEY) continue;
26158
- if (LOGO_IMAGE_KEYS.includes(key)) continue;
26159
26114
  if (key === BRAND_KIT_KEY) continue;
26160
26115
  if (key === STYLE_STORE_KEY) continue;
26161
26116
  if (BRAND_CHROME_KEYS.has(key)) continue;
26117
+ if (key === LOGO_PLACEHOLDER_KEY) continue;
26162
26118
  if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
26119
+ if (LOGO_IMAGE_KEYS.includes(key)) continue;
26163
26120
  if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
26164
26121
  continue;
26165
26122
  }
@@ -26373,18 +26330,17 @@ function OhhwellsBridge() {
26373
26330
  }
26374
26331
  applyAiFooterFromContent(content);
26375
26332
  if (typeof content[STYLE_STORE_KEY] === "string") {
26376
- document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
26377
26333
  applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
26378
26334
  }
26379
26335
  for (const [key, val] of Object.entries(content)) {
26380
26336
  if (key === "__ohw_sections") continue;
26381
26337
  if (key === AI_SECTIONS_KEY) continue;
26382
26338
  if (key === AI_FOOTER_KEY) continue;
26383
- if (key === LOGO_PLACEHOLDER_KEY) continue;
26384
- if (LOGO_IMAGE_KEYS.includes(key)) continue;
26385
26339
  if (key === BRAND_KIT_KEY) continue;
26386
26340
  if (key === STYLE_STORE_KEY) continue;
26387
26341
  if (BRAND_CHROME_KEYS.has(key)) continue;
26342
+ if (key === LOGO_PLACEHOLDER_KEY) continue;
26343
+ if (LOGO_IMAGE_KEYS.includes(key)) continue;
26388
26344
  if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
26389
26345
  continue;
26390
26346
  }
@@ -26640,11 +26596,26 @@ function OhhwellsBridge() {
26640
26596
  const t2 = setTimeout(measure, 500);
26641
26597
  const ro = new ResizeObserver(schedule);
26642
26598
  ro.observe(document.body);
26599
+ let lastWidth = window.innerWidth;
26600
+ let resizeTimers = [];
26601
+ const clearResizeTimers = () => {
26602
+ resizeTimers.forEach(clearTimeout);
26603
+ resizeTimers = [];
26604
+ };
26605
+ const handleResize = () => {
26606
+ if (window.innerWidth === lastWidth) return;
26607
+ lastWidth = window.innerWidth;
26608
+ clearResizeTimers();
26609
+ resizeTimers = HEIGHT_SETTLE_DELAYS.map((delay) => setTimeout(measure, delay));
26610
+ };
26611
+ window.addEventListener("resize", handleResize);
26643
26612
  return () => {
26644
26613
  clearTimeout(t1);
26645
26614
  clearTimeout(t2);
26646
26615
  if (raf != null) cancelAnimationFrame(raf);
26647
26616
  ro.disconnect();
26617
+ clearResizeTimers();
26618
+ window.removeEventListener("resize", handleResize);
26648
26619
  };
26649
26620
  }, [pathname, isEditMode, postToParent2]);
26650
26621
  (0, import_react21.useEffect)(() => {
@@ -26939,13 +26910,6 @@ function OhhwellsBridge() {
26939
26910
  if (target.closest("[data-ohw-state-toggle]")) return;
26940
26911
  if (target.closest("[data-ohw-max-badge]")) return;
26941
26912
  if (isInsideLinkEditor(target)) return;
26942
- if (isInsideFloatingPanel(target)) return;
26943
- if (target.closest("[data-ohw-form-toolbar]")) return;
26944
- if (target.closest(
26945
- '[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
26946
- )) {
26947
- return;
26948
- }
26949
26913
  if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
26950
26914
  clearMediaSelectionRef.current();
26951
26915
  }
@@ -26966,6 +26930,13 @@ function OhhwellsBridge() {
26966
26930
  return;
26967
26931
  }
26968
26932
  }
26933
+ if (isInsideFloatingPanel(target)) return;
26934
+ if (target.closest("[data-ohw-form-toolbar]")) return;
26935
+ if (target.closest(
26936
+ '[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
26937
+ )) {
26938
+ return;
26939
+ }
26969
26940
  {
26970
26941
  const formEl = getFormElement(target);
26971
26942
  const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
@@ -27345,9 +27316,6 @@ function OhhwellsBridge() {
27345
27316
  setHoveredItemRect(null);
27346
27317
  hoveredNavContainerRef.current = null;
27347
27318
  setHoveredNavContainerRect(null);
27348
- siblingHintElRef.current = null;
27349
- setSiblingHintRect(null);
27350
- setSiblingHintRects([]);
27351
27319
  return;
27352
27320
  }
27353
27321
  {
@@ -27468,6 +27436,7 @@ function OhhwellsBridge() {
27468
27436
  hoveredNavContainerRef.current = null;
27469
27437
  setHoveredNavContainerRect(null);
27470
27438
  hoveredItemElRef.current = editable;
27439
+ setHoveredItemRect(isSelectedForHoverRef.current(editable) ? null : editable.getBoundingClientRect());
27471
27440
  }
27472
27441
  }
27473
27442
  }
@@ -28177,11 +28146,7 @@ function OhhwellsBridge() {
28177
28146
  };
28178
28147
  const handleMouseMove = (e) => {
28179
28148
  const { clientX, clientY } = e;
28180
- if (pointOwnedByFloatingPanel(clientX, clientY)) {
28181
- dismissImageHover();
28182
- clearImageHover();
28183
- return;
28184
- }
28149
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
28185
28150
  if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) {
28186
28151
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
28187
28152
  formHoverElRef.current = null;
@@ -28210,12 +28175,7 @@ function OhhwellsBridge() {
28210
28175
  setHoveredItemRect(null);
28211
28176
  hoveredNavContainerRef.current = null;
28212
28177
  setHoveredNavContainerRect(null);
28213
- siblingHintElRef.current = null;
28214
- setSiblingHintRect(null);
28215
- setSiblingHintRects([]);
28216
28178
  dismissImageHover();
28217
- clearImageHover();
28218
- setSectionGap(null);
28219
28179
  return;
28220
28180
  }
28221
28181
  if (probeSocialsRowAt(clientX, clientY)) return;
@@ -28227,11 +28187,7 @@ function OhhwellsBridge() {
28227
28187
  if (e.data?.type !== "ow:pointer-sync") return;
28228
28188
  const { clientX, clientY } = e.data;
28229
28189
  if (typeof clientX !== "number" || typeof clientY !== "number") return;
28230
- if (pointOwnedByFloatingPanel(clientX, clientY)) {
28231
- dismissImageHover();
28232
- clearImageHover();
28233
- return;
28234
- }
28190
+ if (pointOwnedByFloatingPanel(clientX, clientY)) return;
28235
28191
  if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) return;
28236
28192
  if (probeSocialsRowAt(clientX, clientY)) return;
28237
28193
  probeSectionGapAt(clientX, clientY);
@@ -28583,7 +28539,6 @@ function OhhwellsBridge() {
28583
28539
  applyAiFooterFromContent(content);
28584
28540
  if (typeof content[STYLE_STORE_KEY] === "string") {
28585
28541
  stylesRef.current = content[STYLE_STORE_KEY];
28586
- document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
28587
28542
  applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
28588
28543
  }
28589
28544
  applyBrandChrome(content);
@@ -28597,12 +28552,12 @@ function OhhwellsBridge() {
28597
28552
  }
28598
28553
  if (key === AI_SECTIONS_KEY) continue;
28599
28554
  if (key === AI_FOOTER_KEY) continue;
28600
- if (key === LOGO_PLACEHOLDER_KEY) continue;
28601
- if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
28602
28555
  if (key === BRAND_KIT_KEY) continue;
28603
28556
  if (key === STYLE_STORE_KEY) continue;
28604
28557
  if (BRAND_CHROME_KEYS.has(key)) continue;
28558
+ if (key === LOGO_PLACEHOLDER_KEY) continue;
28605
28559
  if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
28560
+ if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
28606
28561
  if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
28607
28562
  continue;
28608
28563
  }
@@ -29139,12 +29094,6 @@ function OhhwellsBridge() {
29139
29094
  closeLinkPopoverRef.current();
29140
29095
  return;
29141
29096
  }
29142
- if (floatingPanelOpenRef.current) {
29143
- setFloatingPanelRef.current(null);
29144
- deselectRef.current();
29145
- deactivateRef.current();
29146
- return;
29147
- }
29148
29097
  deselectRef.current();
29149
29098
  deactivateRef.current();
29150
29099
  clearMediaSelectionRef.current();
@@ -29907,10 +29856,10 @@ function OhhwellsBridge() {
29907
29856
  window.removeEventListener("message", handleDeleteSection);
29908
29857
  window.removeEventListener("message", handleDuplicateSection);
29909
29858
  window.removeEventListener("message", handleDeactivate);
29859
+ document.documentElement.removeAttribute("data-ohw-panel-dragging");
29910
29860
  window.removeEventListener("message", handleToastAction);
29911
29861
  window.removeEventListener("message", handleFormCount);
29912
29862
  window.removeEventListener("message", handleUiEscape);
29913
- document.documentElement.removeAttribute("data-ohw-panel-dragging");
29914
29863
  autoSaveTimers.current.forEach(clearTimeout);
29915
29864
  autoSaveTimers.current.clear();
29916
29865
  if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
@@ -30204,7 +30153,7 @@ function OhhwellsBridge() {
30204
30153
  postToParent2({
30205
30154
  type: "ow:ready",
30206
30155
  version: "1",
30207
- bridgeVersion: "0.1.132",
30156
+ bridgeVersion: "0.1.130",
30208
30157
  path: pathname,
30209
30158
  nodes: collectEditableNodes(editContentRef.current),
30210
30159
  sections