@ohhwells/bridge 0.1.92-next.269 → 0.1.92-next.272

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
@@ -7506,9 +7506,7 @@ function ItemActionToolbar({
7506
7506
  ToggleGroup,
7507
7507
  {
7508
7508
  value: dropdownOpen ? "open" : "closed",
7509
- onValueChange: (value) => {
7510
- if (value !== "open" && value !== "closed") return;
7511
- onDropdownOpenChange?.(value === "open");
7509
+ onValueChange: () => {
7512
7510
  },
7513
7511
  className: "h-7 gap-0.5 rounded-[calc(var(--radius,0.5rem)-2px)] bg-muted p-0.5",
7514
7512
  onMouseDown: (e) => {
@@ -7523,6 +7521,11 @@ function ItemActionToolbar({
7523
7521
  size: "sm",
7524
7522
  "aria-label": "Closed",
7525
7523
  className: "h-6 min-w-0 px-2 text-xs font-medium",
7524
+ onMouseDown: (e) => {
7525
+ e.preventDefault();
7526
+ e.stopPropagation();
7527
+ if (dropdownOpen !== false) onDropdownOpenChange?.(false);
7528
+ },
7526
7529
  children: "Closed"
7527
7530
  }
7528
7531
  ),
@@ -7533,6 +7536,11 @@ function ItemActionToolbar({
7533
7536
  size: "sm",
7534
7537
  "aria-label": "Open",
7535
7538
  className: "h-6 min-w-0 px-2 text-xs font-medium",
7539
+ onMouseDown: (e) => {
7540
+ e.preventDefault();
7541
+ e.stopPropagation();
7542
+ if (dropdownOpen !== true) onDropdownOpenChange?.(true);
7543
+ },
7536
7544
  children: "Open"
7537
7545
  }
7538
7546
  )
@@ -8558,7 +8566,7 @@ function FieldTypePicker({ onPick }) {
8558
8566
  "div",
8559
8567
  {
8560
8568
  "data-ohw-field-type-picker": "",
8561
- className: "pointer-events-auto grid w-[420px] grid-cols-3 gap-3 rounded-xl border border-border bg-background p-4 shadow-lg",
8569
+ className: "pointer-events-auto grid w-[280px] grid-cols-2 gap-2 rounded-xl border border-border bg-background p-3 shadow-lg",
8562
8570
  children: FIELD_TYPES.map((entry) => {
8563
8571
  const Icon = TYPE_ICONS[entry.type];
8564
8572
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
@@ -8566,7 +8574,7 @@ function FieldTypePicker({ onPick }) {
8566
8574
  {
8567
8575
  type: "button",
8568
8576
  onClick: () => onPick(entry.type),
8569
- className: "flex h-[104px] flex-col items-center justify-center gap-3 rounded-xl border border-border text-[15px] font-medium text-foreground transition-colors hover:border-primary hover:bg-primary/5",
8577
+ className: "flex h-[76px] flex-col items-center justify-center gap-2 rounded-xl border border-border text-[15px] font-medium text-foreground transition-colors hover:border-primary hover:bg-primary/5",
8570
8578
  children: [
8571
8579
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Icon, { size: 26, strokeWidth: 1.5, "aria-hidden": true }),
8572
8580
  entry.label
@@ -10920,6 +10928,32 @@ function getNavbarDesktopContainer() {
10920
10928
  function getNavbarDrawerContainer() {
10921
10929
  return document.querySelector("[data-ohw-nav-drawer]");
10922
10930
  }
10931
+ function isNavbarListContainerVisible(el) {
10932
+ if (el.hasAttribute("hidden")) return false;
10933
+ if (el.getClientRects().length === 0) return false;
10934
+ const style = window.getComputedStyle(el);
10935
+ return style.display !== "none" && style.visibility !== "hidden";
10936
+ }
10937
+ function getActiveNavbarListContainer(draggedEl) {
10938
+ const desktop = getNavbarDesktopContainer();
10939
+ const drawer = getNavbarDrawerContainer();
10940
+ if (draggedEl) {
10941
+ if (drawer?.contains(draggedEl)) return drawer;
10942
+ if (desktop?.contains(draggedEl)) return desktop;
10943
+ }
10944
+ if (desktop && isNavbarListContainerVisible(desktop)) return desktop;
10945
+ if (drawer && isNavbarListContainerVisible(drawer)) return drawer;
10946
+ return desktop ?? drawer;
10947
+ }
10948
+ function listActiveNavbarItems(draggedEl) {
10949
+ const container = getActiveNavbarListContainer(draggedEl);
10950
+ if (container) {
10951
+ return Array.from(container.querySelectorAll("[data-ohw-href-key]")).filter(
10952
+ isNavbarLinkItem
10953
+ );
10954
+ }
10955
+ return listNavbarItems();
10956
+ }
10923
10957
  function listNavbarItems() {
10924
10958
  const desktop = getNavbarDesktopContainer();
10925
10959
  if (desktop) {
@@ -12032,20 +12066,23 @@ function isEmptyLabelValue(value) {
12032
12066
  function applyStoredValues(item, content) {
12033
12067
  const hrefKey = socialHrefKey(item);
12034
12068
  const iconKey = socialIconKey(item);
12069
+ const baseKey = hrefKey?.replace(/-href$/, "");
12035
12070
  if (hrefKey && content[hrefKey] !== void 0) item.setAttribute("href", content[hrefKey]);
12036
- if (iconKey) {
12071
+ const glyphKey = iconKey ?? baseKey ?? null;
12072
+ const glyphStored = glyphKey ? content[glyphKey]?.trim() : void 0;
12073
+ if (glyphStored) {
12074
+ ensureIconSlot(item);
12037
12075
  const glyph = item.querySelector(ICON_SELECTOR);
12038
- if (glyph && content[iconKey]) {
12039
- applyIconMarkup(glyph, content[iconKey]);
12076
+ if (glyph) {
12077
+ applyIconMarkup(glyph, glyphStored);
12040
12078
  glyph.removeAttribute(SOCIALS_ICON_PLACEHOLDER_ATTR);
12041
12079
  }
12042
- const label = item.querySelector(`[${SOCIALS_LABEL_ATTR}]`);
12043
- label?.setAttribute("data-ohw-key", socialLabelKey(iconKey));
12044
- const stored = content[socialLabelKey(iconKey)];
12045
- if (label && stored !== void 0) {
12046
- const words = isEmptyLabelValue(stored) ? "" : stored;
12047
- if (label.innerHTML !== words) label.innerHTML = words;
12048
- }
12080
+ }
12081
+ const label = socialLabelElement(item);
12082
+ const labelKey = label?.getAttribute("data-ohw-key");
12083
+ if (label && labelKey && content[labelKey] !== void 0) {
12084
+ const words = isEmptyLabelValue(content[labelKey]) ? "" : content[labelKey];
12085
+ if (label.innerHTML !== words) label.innerHTML = words;
12049
12086
  }
12050
12087
  }
12051
12088
  function socialPlatformKey(iconKey) {
@@ -12134,6 +12171,9 @@ function insertSocialItem(row, after, content = {}, { placeholder = true, keys }
12134
12171
  if (placeholder) {
12135
12172
  const label = socialLabelElement(item);
12136
12173
  if (label) label.textContent = PLACEHOLDER_SOCIAL_LABEL;
12174
+ } else if (keys) {
12175
+ const label = socialLabelElement(item);
12176
+ if (label) label.textContent = "";
12137
12177
  }
12138
12178
  applySocialsDisplayToRow(row, display);
12139
12179
  return { item, hrefKey, iconKey, order: getSocialsOrderFromDom(row.ownerDocument) };
@@ -13991,8 +14031,8 @@ var lockFooterDuringDrag = lockItemDuringDrag;
13991
14031
  var unlockFooterDragInteraction = unlockItemDragInteraction;
13992
14032
 
13993
14033
  // src/lib/nav-dnd.ts
13994
- function listReorderableNavItems() {
13995
- return listNavbarItems().filter((el) => {
14034
+ function listReorderableNavItems(draggedEl) {
14035
+ return listActiveNavbarItems(draggedEl).filter((el) => {
13996
14036
  const key = el.getAttribute("data-ohw-href-key");
13997
14037
  return isNavbarHrefKey(key) && !isNestedNavChild(el);
13998
14038
  });
@@ -14007,8 +14047,8 @@ function resolveParentNavHrefKey(child) {
14007
14047
  const key = trigger?.getAttribute("data-ohw-href-key");
14008
14048
  return key && isNavbarHrefKey(key) ? key : null;
14009
14049
  }
14010
- function listNavChildren(parentHrefKey) {
14011
- const items = listNavbarItems();
14050
+ function listNavChildren(parentHrefKey, draggedEl) {
14051
+ const items = listActiveNavbarItems(draggedEl);
14012
14052
  const parent = items.find((el) => el.getAttribute("data-ohw-href-key") === parentHrefKey);
14013
14053
  if (!parent) return [];
14014
14054
  const group = parent.closest("[data-ohw-nav-group]");
@@ -14018,20 +14058,83 @@ function listNavChildren(parentHrefKey) {
14018
14058
  (el) => isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))
14019
14059
  );
14020
14060
  }
14021
- function activeNavListContainer() {
14022
- const desktop = getNavbarDesktopContainer();
14023
- if (desktop && desktop.getClientRects().length > 0) {
14024
- const style = window.getComputedStyle(desktop);
14025
- if (style.display !== "none" && style.visibility !== "hidden") return desktop;
14061
+ function isVerticalNavLayout(items, draggedEl) {
14062
+ const visible = items.filter((el) => el.getClientRects().length > 0);
14063
+ if (visible.length >= 2) {
14064
+ const a = visible[0].getBoundingClientRect();
14065
+ const b = visible[1].getBoundingClientRect();
14066
+ const verticalGap = b.top - a.bottom;
14067
+ const horizontalGap = b.left - a.right;
14068
+ return verticalGap > horizontalGap;
14069
+ }
14070
+ const container = getActiveNavbarListContainer(draggedEl);
14071
+ if (!container) return false;
14072
+ const style = window.getComputedStyle(container);
14073
+ return style.flexDirection === "column" || style.flexDirection === "column-reverse";
14074
+ }
14075
+ function buildVerticalRootNavDropSlots(items, draggedEl) {
14076
+ const slots = [];
14077
+ const barThickness = 3;
14078
+ if (items.length === 0) {
14079
+ const container = getActiveNavbarListContainer(draggedEl);
14080
+ if (!container) return slots;
14081
+ const rect = container.getBoundingClientRect();
14082
+ slots.push({
14083
+ insertIndex: 0,
14084
+ parentId: null,
14085
+ left: rect.left,
14086
+ top: rect.top + rect.height / 2 - barThickness / 2,
14087
+ width: Math.max(rect.width, 40),
14088
+ height: barThickness,
14089
+ direction: "horizontal"
14090
+ });
14091
+ return slots;
14026
14092
  }
14027
- return getNavbarDrawerContainer();
14093
+ const edgeGap = (() => {
14094
+ if (items.length < 2) return 16;
14095
+ const a = items[0].getBoundingClientRect();
14096
+ const b = items[1].getBoundingClientRect();
14097
+ return Math.max(0, b.top - a.bottom);
14098
+ })();
14099
+ for (let i = 0; i <= items.length; i++) {
14100
+ let top;
14101
+ let width;
14102
+ let left;
14103
+ if (i === 0) {
14104
+ const first = items[0].getBoundingClientRect();
14105
+ top = first.top - edgeGap / 2 - barThickness / 2;
14106
+ left = first.left;
14107
+ width = first.width;
14108
+ } else if (i === items.length) {
14109
+ const last = items[items.length - 1].getBoundingClientRect();
14110
+ const lastGap = items.length >= 2 ? Math.max(0, last.top - items[items.length - 2].getBoundingClientRect().bottom) : edgeGap;
14111
+ top = last.bottom + lastGap / 2 - barThickness / 2;
14112
+ left = last.left;
14113
+ width = last.width;
14114
+ } else {
14115
+ const prev = items[i - 1].getBoundingClientRect();
14116
+ const next = items[i].getBoundingClientRect();
14117
+ top = (prev.bottom + next.top) / 2 - barThickness / 2;
14118
+ left = Math.min(prev.left, next.left);
14119
+ width = Math.max(prev.right, next.right) - left;
14120
+ }
14121
+ slots.push({
14122
+ insertIndex: i,
14123
+ parentId: null,
14124
+ left,
14125
+ top,
14126
+ width: Math.max(width, 40),
14127
+ height: barThickness,
14128
+ direction: "horizontal"
14129
+ });
14130
+ }
14131
+ return slots;
14028
14132
  }
14029
- function buildRootNavDropSlots() {
14030
- const items = listReorderableNavItems();
14133
+ function buildHorizontalRootNavDropSlots(items, draggedEl) {
14031
14134
  const slots = [];
14032
14135
  const barThickness = 3;
14033
14136
  if (items.length === 0) {
14034
- const container = activeNavListContainer();
14137
+ const container = getActiveNavbarListContainer(draggedEl);
14035
14138
  if (!container) return slots;
14036
14139
  const rect = container.getBoundingClientRect();
14037
14140
  slots.push({
@@ -14062,10 +14165,7 @@ function buildRootNavDropSlots() {
14062
14165
  height = first.height;
14063
14166
  } else if (i === items.length) {
14064
14167
  const last = items[items.length - 1].getBoundingClientRect();
14065
- const lastGap = items.length >= 2 ? Math.max(
14066
- 0,
14067
- last.left - items[items.length - 2].getBoundingClientRect().right
14068
- ) : edgeGap;
14168
+ const lastGap = items.length >= 2 ? Math.max(0, last.left - items[items.length - 2].getBoundingClientRect().right) : edgeGap;
14069
14169
  left = last.right + lastGap / 2 - barThickness / 2;
14070
14170
  top = last.top;
14071
14171
  height = last.height;
@@ -14088,8 +14188,15 @@ function buildRootNavDropSlots() {
14088
14188
  }
14089
14189
  return slots;
14090
14190
  }
14091
- function buildChildNavDropSlots(parentHrefKey) {
14092
- const children = listNavChildren(parentHrefKey);
14191
+ function buildRootNavDropSlots(draggedEl) {
14192
+ const items = listReorderableNavItems(draggedEl);
14193
+ if (isVerticalNavLayout(items, draggedEl)) {
14194
+ return buildVerticalRootNavDropSlots(items, draggedEl);
14195
+ }
14196
+ return buildHorizontalRootNavDropSlots(items, draggedEl);
14197
+ }
14198
+ function buildChildNavDropSlots(parentHrefKey, draggedEl) {
14199
+ const children = listNavChildren(parentHrefKey, draggedEl);
14093
14200
  const slots = [];
14094
14201
  const barThickness = 3;
14095
14202
  if (children.length === 0) return slots;
@@ -14110,10 +14217,7 @@ function buildChildNavDropSlots(parentHrefKey) {
14110
14217
  width = first.width;
14111
14218
  } else if (i === children.length) {
14112
14219
  const last = children[children.length - 1].getBoundingClientRect();
14113
- const lastGap = children.length >= 2 ? Math.max(
14114
- 0,
14115
- last.top - children[children.length - 2].getBoundingClientRect().bottom
14116
- ) : edgeGap;
14220
+ const lastGap = children.length >= 2 ? Math.max(0, last.top - children[children.length - 2].getBoundingClientRect().bottom) : edgeGap;
14117
14221
  top = last.bottom + lastGap / 2 - barThickness / 2;
14118
14222
  left = last.left;
14119
14223
  width = last.width;
@@ -14136,18 +14240,19 @@ function buildChildNavDropSlots(parentHrefKey) {
14136
14240
  }
14137
14241
  return slots;
14138
14242
  }
14139
- function buildAllNavDropSlots(draggedHrefKey) {
14140
- const dragged = listNavbarItems().find((el) => el.getAttribute("data-ohw-href-key") === draggedHrefKey);
14141
- if (!dragged) return buildRootNavDropSlots();
14243
+ function buildAllNavDropSlots(draggedHrefKey, draggedEl) {
14244
+ const activeItems = listActiveNavbarItems(draggedEl);
14245
+ const dragged = (draggedEl && activeItems.includes(draggedEl) ? draggedEl : null) ?? activeItems.find((el) => el.getAttribute("data-ohw-href-key") === draggedHrefKey) ?? listNavbarItems().find((el) => el.getAttribute("data-ohw-href-key") === draggedHrefKey);
14246
+ if (!dragged) return buildRootNavDropSlots(draggedEl);
14142
14247
  if (isNestedNavChild(dragged)) {
14143
14248
  const parentKey = resolveParentNavHrefKey(dragged);
14144
14249
  if (!parentKey) return [];
14145
- return buildChildNavDropSlots(parentKey);
14250
+ return buildChildNavDropSlots(parentKey, draggedEl);
14146
14251
  }
14147
- return buildRootNavDropSlots();
14252
+ return buildRootNavDropSlots(draggedEl);
14148
14253
  }
14149
- function hitTestNavDropSlot(clientX, clientY, draggedHrefKey) {
14150
- const slots = buildAllNavDropSlots(draggedHrefKey);
14254
+ function hitTestNavDropSlot(clientX, clientY, draggedHrefKey, draggedEl) {
14255
+ const slots = buildAllNavDropSlots(draggedHrefKey, draggedEl);
14151
14256
  let best = null;
14152
14257
  for (const slot of slots) {
14153
14258
  const cx2 = slot.left + slot.width / 2;
@@ -14198,6 +14303,12 @@ function useNavItemDrag({
14198
14303
  setIsItemDragging(false);
14199
14304
  if (keepOpenEl?.isConnected) {
14200
14305
  setNavGroupForceOpen(keepOpenEl, true);
14306
+ requestAnimationFrame(() => {
14307
+ if (keepOpenEl.isConnected) setNavGroupForceOpen(keepOpenEl, true);
14308
+ requestAnimationFrame(() => {
14309
+ if (keepOpenEl.isConnected) setNavGroupForceOpen(keepOpenEl, true);
14310
+ });
14311
+ });
14201
14312
  } else {
14202
14313
  setNavGroupForceOpen(null, false);
14203
14314
  }
@@ -14213,7 +14324,7 @@ function useNavItemDrag({
14213
14324
  }
14214
14325
  session.activeSlot = activeSlot;
14215
14326
  setSiblingHintRects([]);
14216
- const slots = buildAllNavDropSlots(session.hrefKey);
14327
+ const slots = buildAllNavDropSlots(session.hrefKey, session.draggedEl);
14217
14328
  setNavDropSlots(slots);
14218
14329
  const activeIdx = activeSlot ? slots.findIndex(
14219
14330
  (s) => s.parentId === activeSlot.parentId && s.insertIndex === activeSlot.insertIndex
@@ -14249,7 +14360,12 @@ function useNavItemDrag({
14249
14360
  if (session.wasSelected && selectedElRef.current === session.draggedEl) {
14250
14361
  setToolbarRect(rect);
14251
14362
  }
14252
- const initialSlot = hitTestNavDropSlot(session.lastClientX, session.lastClientY, session.hrefKey);
14363
+ const initialSlot = hitTestNavDropSlot(
14364
+ session.lastClientX,
14365
+ session.lastClientY,
14366
+ session.hrefKey,
14367
+ session.draggedEl
14368
+ );
14253
14369
  refreshNavDragVisuals(session, initialSlot, session.lastClientX, session.lastClientY);
14254
14370
  },
14255
14371
  [
@@ -14271,10 +14387,11 @@ function useNavItemDrag({
14271
14387
  }
14272
14388
  const x = typeof clientX === "number" && (clientX !== 0 || clientY !== 0) ? clientX : session.lastClientX;
14273
14389
  const y = typeof clientY === "number" && (clientX !== 0 || clientY !== 0) ? clientY : session.lastClientY;
14274
- const slot = session.activeSlot ?? hitTestNavDropSlot(x, y, session.hrefKey);
14390
+ const slot = session.activeSlot ?? hitTestNavDropSlot(x, y, session.hrefKey, session.draggedEl);
14275
14391
  const planned = slot != null ? planNavItemMove(session.hrefKey, slot.parentId, slot.insertIndex) : null;
14276
14392
  const wasSelected = session.wasSelected;
14277
14393
  const hrefKey = session.hrefKey;
14394
+ const keepDropdownOpen = Boolean(session.draggedEl.closest("[data-ohw-nav-children]"));
14278
14395
  const applySelectionAfterDrop = () => {
14279
14396
  if (!wasSelected) {
14280
14397
  deselectRef.current();
@@ -14308,6 +14425,14 @@ function useNavItemDrag({
14308
14425
  });
14309
14426
  applySelectionAfterDrop();
14310
14427
  clearNavDragVisuals();
14428
+ if (keepDropdownOpen) {
14429
+ requestAnimationFrame(() => {
14430
+ const desktop = document.querySelector("[data-ohw-nav-container]");
14431
+ const drawer = document.querySelector("[data-ohw-nav-drawer]");
14432
+ const link = desktop?.querySelector(`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`) ?? drawer?.querySelector(`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`) ?? document.querySelector(`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`);
14433
+ if (link) setNavGroupForceOpen(link, true);
14434
+ });
14435
+ }
14311
14436
  requestAnimationFrame(() => {
14312
14437
  if (editContentRef.current[NAV_ORDER_KEY] === planned.orderJson) {
14313
14438
  applyNavForest(planned.forest);
@@ -14347,7 +14472,7 @@ function useNavItemDrag({
14347
14472
  if (!session) return false;
14348
14473
  e.preventDefault();
14349
14474
  if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
14350
- const slot = hitTestNavDropSlot(e.clientX, e.clientY, session.hrefKey);
14475
+ const slot = hitTestNavDropSlot(e.clientX, e.clientY, session.hrefKey, session.draggedEl);
14351
14476
  refreshNavDragVisualsRef.current(session, slot, e.clientX, e.clientY);
14352
14477
  return true;
14353
14478
  },
@@ -14393,7 +14518,7 @@ function useNavItemDrag({
14393
14518
  clearTextSelection();
14394
14519
  const session = navDragRef.current;
14395
14520
  if (!session) return;
14396
- const slot = hitTestNavDropSlot(e.clientX, e.clientY, session.hrefKey);
14521
+ const slot = hitTestNavDropSlot(e.clientX, e.clientY, session.hrefKey, session.draggedEl);
14397
14522
  refreshNavDragVisualsRef.current(session, slot, e.clientX, e.clientY);
14398
14523
  return;
14399
14524
  }
@@ -14409,7 +14534,8 @@ function useNavItemDrag({
14409
14534
  } catch {
14410
14535
  }
14411
14536
  if (linkPopoverOpenRef.current) setLinkPopover(null);
14412
- if (activeElRef.current) deactivateRef.current();
14537
+ const isNestedDrag = Boolean(pending.el.closest("[data-ohw-nav-children]"));
14538
+ if (activeElRef.current && !isNestedDrag) deactivateRef.current();
14413
14539
  const key = pending.el.getAttribute("data-ohw-href-key");
14414
14540
  if (!key) return;
14415
14541
  beginNavDragRef.current({
@@ -14420,6 +14546,9 @@ function useNavItemDrag({
14420
14546
  lastClientY: e.clientY,
14421
14547
  activeSlot: null
14422
14548
  });
14549
+ if (activeElRef.current && isNestedDrag) {
14550
+ deactivateRef.current();
14551
+ }
14423
14552
  };
14424
14553
  const endPointerDrag = (e) => {
14425
14554
  const pending = navPointerDragRef.current;
@@ -14497,6 +14626,7 @@ function useNavItemDrag({
14497
14626
  );
14498
14627
  return {
14499
14628
  navDragRef,
14629
+ navPointerDragRef,
14500
14630
  navDropSlots,
14501
14631
  activeNavDropIndex,
14502
14632
  startNavLinkDrag,
@@ -15893,6 +16023,7 @@ function isNavDropdownPanelOpen(childrenRoot) {
15893
16023
  if (childrenRoot.closest("[data-ohw-nav-drawer]")) return true;
15894
16024
  const group = childrenRoot.closest("[data-ohw-nav-group]");
15895
16025
  if (group?.hasAttribute("data-ohw-nav-force-open")) return true;
16026
+ if (navDropdownsOpenOnClick()) return false;
15896
16027
  if (childrenRoot.clientHeight < 2 || childrenRoot.clientWidth < 2) return false;
15897
16028
  const style = window.getComputedStyle(childrenRoot);
15898
16029
  if (style.display === "none" || style.visibility === "hidden") return false;
@@ -15936,6 +16067,11 @@ function getNavigationItemAnchor(el) {
15936
16067
  function isNavigationItem2(el) {
15937
16068
  return getNavigationItemAnchor(el) !== null;
15938
16069
  }
16070
+ function isNavFooterScopedNavigationItem(el) {
16071
+ return Boolean(
16072
+ el.closest("nav, footer, [data-ohw-nav-container], [data-ohw-nav-drawer]")
16073
+ );
16074
+ }
15939
16075
  function socialWordsClicked(target, item) {
15940
16076
  const text = target.closest('[data-ohw-editable="text"], [data-ohw-editable="plain"]');
15941
16077
  return Boolean(text && item.contains(text));
@@ -16146,6 +16282,7 @@ function getNavigationSelectionParent(el) {
16146
16282
  }
16147
16283
  function collectNavigationItemSiblingHintRects(selected) {
16148
16284
  if (!isNavigationItem2(selected)) return [];
16285
+ if (!isNavFooterScopedNavigationItem(selected)) return [];
16149
16286
  const socialsRow = findSocialsRow(selected);
16150
16287
  if (socialsRow) {
16151
16288
  return listSocialItems(socialsRow).filter((item) => item !== selected).map((item) => item.getBoundingClientRect());
@@ -17309,6 +17446,7 @@ function OhhwellsBridge() {
17309
17446
  }, []);
17310
17447
  const {
17311
17448
  navDragRef,
17449
+ navPointerDragRef,
17312
17450
  navDropSlots,
17313
17451
  activeNavDropIndex,
17314
17452
  startNavLinkDrag,
@@ -17511,7 +17649,12 @@ function OhhwellsBridge() {
17511
17649
  if (owner) persistFieldsRef.current(owner);
17512
17650
  }
17513
17651
  activeElRef.current = null;
17514
- setNavGroupForceOpen(null, false);
17652
+ const preserveNavDropdown = Boolean(navPointerDragRef.current?.el?.closest("[data-ohw-nav-children]")) || Boolean(navDragRef.current?.draggedEl?.closest("[data-ohw-nav-children]")) || Boolean(
17653
+ selectedElRef.current?.closest("[data-ohw-nav-children]") && selectedElRef.current?.closest("[data-ohw-nav-group]")?.hasAttribute("data-ohw-nav-force-open")
17654
+ );
17655
+ if (!preserveNavDropdown) {
17656
+ setNavGroupForceOpen(null, false);
17657
+ }
17515
17658
  setReorderHrefKey(null);
17516
17659
  setReorderDragDisabled(false);
17517
17660
  if (!selectedElRef.current) {
@@ -17633,7 +17776,10 @@ function OhhwellsBridge() {
17633
17776
  setSelectedIsSocialsRow(false);
17634
17777
  const isDropdownTrigger = !isNestedNavChild(navAnchor) && (navItemHasDropdownChildren(navAnchor) || navItemOwnsDropdownPanel(navAnchor));
17635
17778
  if (isNestedNavChild(navAnchor)) {
17636
- setNavGroupForceOpen(navAnchor, true);
17779
+ const group = navAnchor.closest("[data-ohw-nav-group]");
17780
+ if (group?.hasAttribute("data-ohw-nav-force-open")) {
17781
+ setNavGroupForceOpen(navAnchor, true);
17782
+ }
17637
17783
  setNavDropdownPreviewOpen(null);
17638
17784
  } else if (isDropdownTrigger) {
17639
17785
  const group = navAnchor.closest("[data-ohw-nav-group]");
@@ -17715,6 +17861,10 @@ function OhhwellsBridge() {
17715
17861
  const handleNavDropdownOpenChange = (0, import_react17.useCallback)((open) => {
17716
17862
  const selected = selectedElRef.current;
17717
17863
  if (!selected || !isNavigationItem2(selected)) return;
17864
+ if (isNestedNavChild(selected)) return;
17865
+ const group = selected.closest("[data-ohw-nav-group]");
17866
+ const domOpen = Boolean(group?.hasAttribute("data-ohw-nav-force-open"));
17867
+ if (open === domOpen) return;
17718
17868
  setNavGroupForceOpen(selected, open);
17719
17869
  setNavDropdownPreviewOpen(open);
17720
17870
  requestAnimationFrame(() => {
@@ -18244,7 +18394,10 @@ function OhhwellsBridge() {
18244
18394
  clearHrefKeyHover(anchor);
18245
18395
  const isDropdownTrigger = !isNestedNavChild(anchor) && (navItemHasDropdownChildren(anchor) || navItemOwnsDropdownPanel(anchor));
18246
18396
  if (isNestedNavChild(anchor)) {
18247
- setNavGroupForceOpen(anchor, true);
18397
+ const group = anchor.closest("[data-ohw-nav-group]");
18398
+ if (group?.hasAttribute("data-ohw-nav-force-open")) {
18399
+ setNavGroupForceOpen(anchor, true);
18400
+ }
18248
18401
  setNavDropdownPreviewOpen(null);
18249
18402
  } else if (isDropdownTrigger) {
18250
18403
  setNavGroupForceOpen(null, false);
@@ -19070,28 +19223,19 @@ function OhhwellsBridge() {
19070
19223
  return;
19071
19224
  }
19072
19225
  const existing = editStylesRef.current;
19073
- let initialVh = window.innerHeight;
19074
- if (existing?.base.textContent) {
19075
- const match = existing.base.textContent.match(/\.min-h-screen[^{]*\{[^}]*min-height:\s*(\d+)px/);
19076
- if (match) initialVh = parseInt(match[1], 10);
19077
- }
19226
+ const canvasHeight = "var(--ohw-canvas-h, 852px)";
19078
19227
  const baseCss = `
19079
19228
  html { height: auto !important; }
19080
19229
  body { height: auto !important; min-height: 0 !important; overflow: hidden !important; }
19081
- .min-h-screen, .min-h-svh, .min-h-dvh { min-height: ${initialVh}px !important; }
19082
- .h-screen, .h-svh, .h-dvh { height: ${initialVh}px !important; }
19083
- [style*="100vh"] { min-height: ${initialVh}px !important; height: ${initialVh}px !important; }
19084
- [style*="100svh"] { min-height: ${initialVh}px !important; height: ${initialVh}px !important; }
19085
- [style*="100dvh"] { min-height: ${initialVh}px !important; height: ${initialVh}px !important; }
19086
- /* A section written as min-height: var(--ohw-canvas-h, 100svh) \u2014 the documented way to
19087
- build a full-viewport section that still grows for its own content \u2014 matches the three
19088
- rules above on substring alone, since the fallback text contains "100svh" too. Forcing
19089
- a literal height on top of that turns "at least one screen" into "exactly one screen",
19090
- so content taller than one screen (a long mobile hero, say) overflows a centered flex
19091
- column upward, under whatever sits above it. Only the min-height half belongs to it. */
19092
- [style*="min-height"][style*="100vh"],
19093
- [style*="min-height"][style*="100svh"],
19094
- [style*="min-height"][style*="100dvh"] { height: auto !important; }
19230
+ .min-h-screen, .min-h-svh, .min-h-dvh { min-height: ${canvasHeight} !important; }
19231
+ .h-screen, .h-svh, .h-dvh { height: ${canvasHeight} !important; }
19232
+ /* Literal inline viewport units only \u2014 skip R11 sections that already reference --ohw-canvas-h
19233
+ (their style attribute contains "100svh" only as a var() fallback string). */
19234
+ [style*="100vh"]:not([style*="--ohw-canvas-h"]) { min-height: ${canvasHeight} !important; height: ${canvasHeight} !important; }
19235
+ [style*="100svh"]:not([style*="--ohw-canvas-h"]) { min-height: ${canvasHeight} !important; height: ${canvasHeight} !important; }
19236
+ [style*="100dvh"]:not([style*="--ohw-canvas-h"]) { min-height: ${canvasHeight} !important; height: ${canvasHeight} !important; }
19237
+ /* R11: min-height via --ohw-canvas-h; height must grow with content taller than one screen. */
19238
+ [style*="min-height"][style*="--ohw-canvas-h"] { height: auto !important; }
19095
19239
  /* Emptied text keeps somewhere to click. A label typed down to nothing collapses to a
19096
19240
  couple of pixels, and getting back into it meant hunting for the caret with the mouse.
19097
19241
  Edit mode only \u2014 the published page shows nothing where there is nothing (OHH-736). */
@@ -19238,6 +19382,10 @@ function OhhwellsBridge() {
19238
19382
  outline-offset: 0 !important;
19239
19383
  box-shadow: none !important;
19240
19384
  }
19385
+ /* Open nav dropdown panels paint above AI section selection chrome (2147483000). */
19386
+ [data-ohw-nav-group][data-ohw-nav-force-open] > [data-ohw-nav-children] {
19387
+ z-index: 2147483100 !important;
19388
+ }
19241
19389
  /* Text edit wins over grab/default (must beat [data-ohw-can-drag] *). */
19242
19390
  [data-ohw-editing],
19243
19391
  [data-ohw-editing] *,
@@ -20575,7 +20723,11 @@ function OhhwellsBridge() {
20575
20723
  const slotFromItem = hrefKey ? findSocialByHrefKey(hrefKey)?.querySelector('[data-ohw-editable="icon"]') : null;
20576
20724
  const requestedIsIconSlot = Boolean(requestedIconKey) && Boolean(document.querySelector(`[data-ohw-key="${requestedIconKey}"][data-ohw-editable="icon"]`));
20577
20725
  const requestedIsFree = Boolean(requestedIconKey) && !document.querySelector(`[data-ohw-key="${requestedIconKey}"]`);
20578
- const iconKey = requestedIsIconSlot ? requestedIconKey : slotFromItem?.dataset.ohwKey ?? (requestedIsFree ? requestedIconKey : void 0);
20726
+ let iconKey = requestedIsIconSlot ? requestedIconKey : slotFromItem?.dataset.ohwKey ?? (requestedIsFree ? requestedIconKey : void 0);
20727
+ const item = hrefKey ? findSocialByHrefKey(hrefKey) : null;
20728
+ if (item && typeof iconMarkup === "string" && iconMarkup) {
20729
+ iconKey = ensureIconSlot(item) ?? iconKey;
20730
+ }
20579
20731
  if (iconKey && typeof iconMarkup === "string" && iconMarkup) {
20580
20732
  document.querySelectorAll(`[data-ohw-key="${iconKey}"][data-ohw-editable="icon"]`).forEach((el) => {
20581
20733
  applyIconMarkup(el, iconMarkup);
@@ -20585,7 +20737,7 @@ function OhhwellsBridge() {
20585
20737
  }
20586
20738
  if (iconKey && platformId) nodes.push({ key: socialPlatformKey(iconKey), text: platformId });
20587
20739
  if (iconKey && label) {
20588
- const labelKey = socialLabelKey(iconKey);
20740
+ const labelKey = (item ? socialLabelElement(item)?.getAttribute("data-ohw-key") : null) ?? socialLabelKey(iconKey);
20589
20741
  document.querySelectorAll(`[data-ohw-key="${labelKey}"]`).forEach((el) => {
20590
20742
  if (keepLabel && el.textContent?.trim()) return;
20591
20743
  el.textContent = label;
@@ -21411,7 +21563,12 @@ function OhhwellsBridge() {
21411
21563
  }
21412
21564
  if (navDragRef.current) {
21413
21565
  const session = navDragRef.current;
21414
- const slot = hitTestNavDropSlot(session.lastClientX, session.lastClientY, session.hrefKey);
21566
+ const slot = hitTestNavDropSlot(
21567
+ session.lastClientX,
21568
+ session.lastClientY,
21569
+ session.hrefKey,
21570
+ session.draggedEl
21571
+ );
21415
21572
  refreshNavDragVisualsRef.current(session, slot, session.lastClientX, session.lastClientY);
21416
21573
  }
21417
21574
  if (hoveredImageRef.current) {
@@ -21617,18 +21774,21 @@ function OhhwellsBridge() {
21617
21774
  }
21618
21775
  return null;
21619
21776
  };
21777
+ const isPointInRect = (el, clientX, clientY) => {
21778
+ const r2 = el.getBoundingClientRect();
21779
+ return clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
21780
+ };
21620
21781
  const isPointOverEditable = (scope, clientX, clientY) => {
21621
21782
  const editables = scope.querySelectorAll("[data-ohw-editable], [data-ohw-href-key]");
21622
21783
  for (const el of editables) {
21623
- const r2 = el.getBoundingClientRect();
21624
- if (clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom) return true;
21784
+ if (isPointInRect(el, clientX, clientY)) return true;
21625
21785
  }
21626
21786
  return false;
21627
21787
  };
21628
21788
  const handleCarouselHover = (e) => {
21629
21789
  const container = findCarouselAtPoint(e.clientX, e.clientY);
21630
21790
  const scope = container?.closest("[data-ohw-section]") ?? container?.parentElement ?? null;
21631
- if (!container || !scope || isPointOverEditable(scope, e.clientX, e.clientY)) {
21791
+ if (!container || !scope || isPointOverEditable(scope, e.clientX, e.clientY) || isPointOverNavigation(e.clientX, e.clientY) || isPointOverBridgeChrome(e.clientX, e.clientY)) {
21632
21792
  setCarouselHover((prev) => prev ? null : prev);
21633
21793
  return;
21634
21794
  }