@ohhwells/bridge 0.1.100 → 0.1.101

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
@@ -7427,9 +7427,7 @@ function ItemActionToolbar({
7427
7427
  ToggleGroup,
7428
7428
  {
7429
7429
  value: dropdownOpen ? "open" : "closed",
7430
- onValueChange: (value) => {
7431
- if (value !== "open" && value !== "closed") return;
7432
- onDropdownOpenChange?.(value === "open");
7430
+ onValueChange: () => {
7433
7431
  },
7434
7432
  className: "h-7 gap-0.5 rounded-[calc(var(--radius,0.5rem)-2px)] bg-muted p-0.5",
7435
7433
  onMouseDown: (e) => {
@@ -7444,6 +7442,11 @@ function ItemActionToolbar({
7444
7442
  size: "sm",
7445
7443
  "aria-label": "Closed",
7446
7444
  className: "h-6 min-w-0 px-2 text-xs font-medium",
7445
+ onMouseDown: (e) => {
7446
+ e.preventDefault();
7447
+ e.stopPropagation();
7448
+ if (dropdownOpen !== false) onDropdownOpenChange?.(false);
7449
+ },
7447
7450
  children: "Closed"
7448
7451
  }
7449
7452
  ),
@@ -7454,6 +7457,11 @@ function ItemActionToolbar({
7454
7457
  size: "sm",
7455
7458
  "aria-label": "Open",
7456
7459
  className: "h-6 min-w-0 px-2 text-xs font-medium",
7460
+ onMouseDown: (e) => {
7461
+ e.preventDefault();
7462
+ e.stopPropagation();
7463
+ if (dropdownOpen !== true) onDropdownOpenChange?.(true);
7464
+ },
7457
7465
  children: "Open"
7458
7466
  }
7459
7467
  )
@@ -8479,7 +8487,7 @@ function FieldTypePicker({ onPick }) {
8479
8487
  "div",
8480
8488
  {
8481
8489
  "data-ohw-field-type-picker": "",
8482
- className: "pointer-events-auto grid w-[420px] grid-cols-3 gap-3 rounded-xl border border-border bg-background p-4 shadow-lg",
8490
+ className: "pointer-events-auto grid w-[280px] grid-cols-2 gap-2 rounded-xl border border-border bg-background p-3 shadow-lg",
8483
8491
  children: FIELD_TYPES.map((entry) => {
8484
8492
  const Icon = TYPE_ICONS[entry.type];
8485
8493
  return /* @__PURE__ */ jsxs6(
@@ -8487,7 +8495,7 @@ function FieldTypePicker({ onPick }) {
8487
8495
  {
8488
8496
  type: "button",
8489
8497
  onClick: () => onPick(entry.type),
8490
- 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",
8498
+ 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",
8491
8499
  children: [
8492
8500
  /* @__PURE__ */ jsx13(Icon, { size: 26, strokeWidth: 1.5, "aria-hidden": true }),
8493
8501
  entry.label
@@ -10840,6 +10848,32 @@ function getNavbarDesktopContainer() {
10840
10848
  function getNavbarDrawerContainer() {
10841
10849
  return document.querySelector("[data-ohw-nav-drawer]");
10842
10850
  }
10851
+ function isNavbarListContainerVisible(el) {
10852
+ if (el.hasAttribute("hidden")) return false;
10853
+ if (el.getClientRects().length === 0) return false;
10854
+ const style = window.getComputedStyle(el);
10855
+ return style.display !== "none" && style.visibility !== "hidden";
10856
+ }
10857
+ function getActiveNavbarListContainer(draggedEl) {
10858
+ const desktop = getNavbarDesktopContainer();
10859
+ const drawer = getNavbarDrawerContainer();
10860
+ if (draggedEl) {
10861
+ if (drawer?.contains(draggedEl)) return drawer;
10862
+ if (desktop?.contains(draggedEl)) return desktop;
10863
+ }
10864
+ if (desktop && isNavbarListContainerVisible(desktop)) return desktop;
10865
+ if (drawer && isNavbarListContainerVisible(drawer)) return drawer;
10866
+ return desktop ?? drawer;
10867
+ }
10868
+ function listActiveNavbarItems(draggedEl) {
10869
+ const container = getActiveNavbarListContainer(draggedEl);
10870
+ if (container) {
10871
+ return Array.from(container.querySelectorAll("[data-ohw-href-key]")).filter(
10872
+ isNavbarLinkItem
10873
+ );
10874
+ }
10875
+ return listNavbarItems();
10876
+ }
10843
10877
  function listNavbarItems() {
10844
10878
  const desktop = getNavbarDesktopContainer();
10845
10879
  if (desktop) {
@@ -11952,20 +11986,23 @@ function isEmptyLabelValue(value) {
11952
11986
  function applyStoredValues(item, content) {
11953
11987
  const hrefKey = socialHrefKey(item);
11954
11988
  const iconKey = socialIconKey(item);
11989
+ const baseKey = hrefKey?.replace(/-href$/, "");
11955
11990
  if (hrefKey && content[hrefKey] !== void 0) item.setAttribute("href", content[hrefKey]);
11956
- if (iconKey) {
11991
+ const glyphKey = iconKey ?? baseKey ?? null;
11992
+ const glyphStored = glyphKey ? content[glyphKey]?.trim() : void 0;
11993
+ if (glyphStored) {
11994
+ ensureIconSlot(item);
11957
11995
  const glyph = item.querySelector(ICON_SELECTOR);
11958
- if (glyph && content[iconKey]) {
11959
- applyIconMarkup(glyph, content[iconKey]);
11996
+ if (glyph) {
11997
+ applyIconMarkup(glyph, glyphStored);
11960
11998
  glyph.removeAttribute(SOCIALS_ICON_PLACEHOLDER_ATTR);
11961
11999
  }
11962
- const label = item.querySelector(`[${SOCIALS_LABEL_ATTR}]`);
11963
- label?.setAttribute("data-ohw-key", socialLabelKey(iconKey));
11964
- const stored = content[socialLabelKey(iconKey)];
11965
- if (label && stored !== void 0) {
11966
- const words = isEmptyLabelValue(stored) ? "" : stored;
11967
- if (label.innerHTML !== words) label.innerHTML = words;
11968
- }
12000
+ }
12001
+ const label = socialLabelElement(item);
12002
+ const labelKey = label?.getAttribute("data-ohw-key");
12003
+ if (label && labelKey && content[labelKey] !== void 0) {
12004
+ const words = isEmptyLabelValue(content[labelKey]) ? "" : content[labelKey];
12005
+ if (label.innerHTML !== words) label.innerHTML = words;
11969
12006
  }
11970
12007
  }
11971
12008
  function socialPlatformKey(iconKey) {
@@ -12054,6 +12091,9 @@ function insertSocialItem(row, after, content = {}, { placeholder = true, keys }
12054
12091
  if (placeholder) {
12055
12092
  const label = socialLabelElement(item);
12056
12093
  if (label) label.textContent = PLACEHOLDER_SOCIAL_LABEL;
12094
+ } else if (keys) {
12095
+ const label = socialLabelElement(item);
12096
+ if (label) label.textContent = "";
12057
12097
  }
12058
12098
  applySocialsDisplayToRow(row, display);
12059
12099
  return { item, hrefKey, iconKey, order: getSocialsOrderFromDom(row.ownerDocument) };
@@ -13916,8 +13956,8 @@ var lockFooterDuringDrag = lockItemDuringDrag;
13916
13956
  var unlockFooterDragInteraction = unlockItemDragInteraction;
13917
13957
 
13918
13958
  // src/lib/nav-dnd.ts
13919
- function listReorderableNavItems() {
13920
- return listNavbarItems().filter((el) => {
13959
+ function listReorderableNavItems(draggedEl) {
13960
+ return listActiveNavbarItems(draggedEl).filter((el) => {
13921
13961
  const key = el.getAttribute("data-ohw-href-key");
13922
13962
  return isNavbarHrefKey(key) && !isNestedNavChild(el);
13923
13963
  });
@@ -13932,8 +13972,8 @@ function resolveParentNavHrefKey(child) {
13932
13972
  const key = trigger?.getAttribute("data-ohw-href-key");
13933
13973
  return key && isNavbarHrefKey(key) ? key : null;
13934
13974
  }
13935
- function listNavChildren(parentHrefKey) {
13936
- const items = listNavbarItems();
13975
+ function listNavChildren(parentHrefKey, draggedEl) {
13976
+ const items = listActiveNavbarItems(draggedEl);
13937
13977
  const parent = items.find((el) => el.getAttribute("data-ohw-href-key") === parentHrefKey);
13938
13978
  if (!parent) return [];
13939
13979
  const group = parent.closest("[data-ohw-nav-group]");
@@ -13943,20 +13983,83 @@ function listNavChildren(parentHrefKey) {
13943
13983
  (el) => isNavbarHrefKey(el.getAttribute("data-ohw-href-key"))
13944
13984
  );
13945
13985
  }
13946
- function activeNavListContainer() {
13947
- const desktop = getNavbarDesktopContainer();
13948
- if (desktop && desktop.getClientRects().length > 0) {
13949
- const style = window.getComputedStyle(desktop);
13950
- if (style.display !== "none" && style.visibility !== "hidden") return desktop;
13986
+ function isVerticalNavLayout(items, draggedEl) {
13987
+ const visible = items.filter((el) => el.getClientRects().length > 0);
13988
+ if (visible.length >= 2) {
13989
+ const a = visible[0].getBoundingClientRect();
13990
+ const b = visible[1].getBoundingClientRect();
13991
+ const verticalGap = b.top - a.bottom;
13992
+ const horizontalGap = b.left - a.right;
13993
+ return verticalGap > horizontalGap;
13994
+ }
13995
+ const container = getActiveNavbarListContainer(draggedEl);
13996
+ if (!container) return false;
13997
+ const style = window.getComputedStyle(container);
13998
+ return style.flexDirection === "column" || style.flexDirection === "column-reverse";
13999
+ }
14000
+ function buildVerticalRootNavDropSlots(items, draggedEl) {
14001
+ const slots = [];
14002
+ const barThickness = 3;
14003
+ if (items.length === 0) {
14004
+ const container = getActiveNavbarListContainer(draggedEl);
14005
+ if (!container) return slots;
14006
+ const rect = container.getBoundingClientRect();
14007
+ slots.push({
14008
+ insertIndex: 0,
14009
+ parentId: null,
14010
+ left: rect.left,
14011
+ top: rect.top + rect.height / 2 - barThickness / 2,
14012
+ width: Math.max(rect.width, 40),
14013
+ height: barThickness,
14014
+ direction: "horizontal"
14015
+ });
14016
+ return slots;
13951
14017
  }
13952
- return getNavbarDrawerContainer();
14018
+ const edgeGap = (() => {
14019
+ if (items.length < 2) return 16;
14020
+ const a = items[0].getBoundingClientRect();
14021
+ const b = items[1].getBoundingClientRect();
14022
+ return Math.max(0, b.top - a.bottom);
14023
+ })();
14024
+ for (let i = 0; i <= items.length; i++) {
14025
+ let top;
14026
+ let width;
14027
+ let left;
14028
+ if (i === 0) {
14029
+ const first = items[0].getBoundingClientRect();
14030
+ top = first.top - edgeGap / 2 - barThickness / 2;
14031
+ left = first.left;
14032
+ width = first.width;
14033
+ } else if (i === items.length) {
14034
+ const last = items[items.length - 1].getBoundingClientRect();
14035
+ const lastGap = items.length >= 2 ? Math.max(0, last.top - items[items.length - 2].getBoundingClientRect().bottom) : edgeGap;
14036
+ top = last.bottom + lastGap / 2 - barThickness / 2;
14037
+ left = last.left;
14038
+ width = last.width;
14039
+ } else {
14040
+ const prev = items[i - 1].getBoundingClientRect();
14041
+ const next = items[i].getBoundingClientRect();
14042
+ top = (prev.bottom + next.top) / 2 - barThickness / 2;
14043
+ left = Math.min(prev.left, next.left);
14044
+ width = Math.max(prev.right, next.right) - left;
14045
+ }
14046
+ slots.push({
14047
+ insertIndex: i,
14048
+ parentId: null,
14049
+ left,
14050
+ top,
14051
+ width: Math.max(width, 40),
14052
+ height: barThickness,
14053
+ direction: "horizontal"
14054
+ });
14055
+ }
14056
+ return slots;
13953
14057
  }
13954
- function buildRootNavDropSlots() {
13955
- const items = listReorderableNavItems();
14058
+ function buildHorizontalRootNavDropSlots(items, draggedEl) {
13956
14059
  const slots = [];
13957
14060
  const barThickness = 3;
13958
14061
  if (items.length === 0) {
13959
- const container = activeNavListContainer();
14062
+ const container = getActiveNavbarListContainer(draggedEl);
13960
14063
  if (!container) return slots;
13961
14064
  const rect = container.getBoundingClientRect();
13962
14065
  slots.push({
@@ -13987,10 +14090,7 @@ function buildRootNavDropSlots() {
13987
14090
  height = first.height;
13988
14091
  } else if (i === items.length) {
13989
14092
  const last = items[items.length - 1].getBoundingClientRect();
13990
- const lastGap = items.length >= 2 ? Math.max(
13991
- 0,
13992
- last.left - items[items.length - 2].getBoundingClientRect().right
13993
- ) : edgeGap;
14093
+ const lastGap = items.length >= 2 ? Math.max(0, last.left - items[items.length - 2].getBoundingClientRect().right) : edgeGap;
13994
14094
  left = last.right + lastGap / 2 - barThickness / 2;
13995
14095
  top = last.top;
13996
14096
  height = last.height;
@@ -14013,8 +14113,15 @@ function buildRootNavDropSlots() {
14013
14113
  }
14014
14114
  return slots;
14015
14115
  }
14016
- function buildChildNavDropSlots(parentHrefKey) {
14017
- const children = listNavChildren(parentHrefKey);
14116
+ function buildRootNavDropSlots(draggedEl) {
14117
+ const items = listReorderableNavItems(draggedEl);
14118
+ if (isVerticalNavLayout(items, draggedEl)) {
14119
+ return buildVerticalRootNavDropSlots(items, draggedEl);
14120
+ }
14121
+ return buildHorizontalRootNavDropSlots(items, draggedEl);
14122
+ }
14123
+ function buildChildNavDropSlots(parentHrefKey, draggedEl) {
14124
+ const children = listNavChildren(parentHrefKey, draggedEl);
14018
14125
  const slots = [];
14019
14126
  const barThickness = 3;
14020
14127
  if (children.length === 0) return slots;
@@ -14035,10 +14142,7 @@ function buildChildNavDropSlots(parentHrefKey) {
14035
14142
  width = first.width;
14036
14143
  } else if (i === children.length) {
14037
14144
  const last = children[children.length - 1].getBoundingClientRect();
14038
- const lastGap = children.length >= 2 ? Math.max(
14039
- 0,
14040
- last.top - children[children.length - 2].getBoundingClientRect().bottom
14041
- ) : edgeGap;
14145
+ const lastGap = children.length >= 2 ? Math.max(0, last.top - children[children.length - 2].getBoundingClientRect().bottom) : edgeGap;
14042
14146
  top = last.bottom + lastGap / 2 - barThickness / 2;
14043
14147
  left = last.left;
14044
14148
  width = last.width;
@@ -14061,18 +14165,19 @@ function buildChildNavDropSlots(parentHrefKey) {
14061
14165
  }
14062
14166
  return slots;
14063
14167
  }
14064
- function buildAllNavDropSlots(draggedHrefKey) {
14065
- const dragged = listNavbarItems().find((el) => el.getAttribute("data-ohw-href-key") === draggedHrefKey);
14066
- if (!dragged) return buildRootNavDropSlots();
14168
+ function buildAllNavDropSlots(draggedHrefKey, draggedEl) {
14169
+ const activeItems = listActiveNavbarItems(draggedEl);
14170
+ 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);
14171
+ if (!dragged) return buildRootNavDropSlots(draggedEl);
14067
14172
  if (isNestedNavChild(dragged)) {
14068
14173
  const parentKey = resolveParentNavHrefKey(dragged);
14069
14174
  if (!parentKey) return [];
14070
- return buildChildNavDropSlots(parentKey);
14175
+ return buildChildNavDropSlots(parentKey, draggedEl);
14071
14176
  }
14072
- return buildRootNavDropSlots();
14177
+ return buildRootNavDropSlots(draggedEl);
14073
14178
  }
14074
- function hitTestNavDropSlot(clientX, clientY, draggedHrefKey) {
14075
- const slots = buildAllNavDropSlots(draggedHrefKey);
14179
+ function hitTestNavDropSlot(clientX, clientY, draggedHrefKey, draggedEl) {
14180
+ const slots = buildAllNavDropSlots(draggedHrefKey, draggedEl);
14076
14181
  let best = null;
14077
14182
  for (const slot of slots) {
14078
14183
  const cx2 = slot.left + slot.width / 2;
@@ -14123,6 +14228,12 @@ function useNavItemDrag({
14123
14228
  setIsItemDragging(false);
14124
14229
  if (keepOpenEl?.isConnected) {
14125
14230
  setNavGroupForceOpen(keepOpenEl, true);
14231
+ requestAnimationFrame(() => {
14232
+ if (keepOpenEl.isConnected) setNavGroupForceOpen(keepOpenEl, true);
14233
+ requestAnimationFrame(() => {
14234
+ if (keepOpenEl.isConnected) setNavGroupForceOpen(keepOpenEl, true);
14235
+ });
14236
+ });
14126
14237
  } else {
14127
14238
  setNavGroupForceOpen(null, false);
14128
14239
  }
@@ -14138,7 +14249,7 @@ function useNavItemDrag({
14138
14249
  }
14139
14250
  session.activeSlot = activeSlot;
14140
14251
  setSiblingHintRects([]);
14141
- const slots = buildAllNavDropSlots(session.hrefKey);
14252
+ const slots = buildAllNavDropSlots(session.hrefKey, session.draggedEl);
14142
14253
  setNavDropSlots(slots);
14143
14254
  const activeIdx = activeSlot ? slots.findIndex(
14144
14255
  (s) => s.parentId === activeSlot.parentId && s.insertIndex === activeSlot.insertIndex
@@ -14174,7 +14285,12 @@ function useNavItemDrag({
14174
14285
  if (session.wasSelected && selectedElRef.current === session.draggedEl) {
14175
14286
  setToolbarRect(rect);
14176
14287
  }
14177
- const initialSlot = hitTestNavDropSlot(session.lastClientX, session.lastClientY, session.hrefKey);
14288
+ const initialSlot = hitTestNavDropSlot(
14289
+ session.lastClientX,
14290
+ session.lastClientY,
14291
+ session.hrefKey,
14292
+ session.draggedEl
14293
+ );
14178
14294
  refreshNavDragVisuals(session, initialSlot, session.lastClientX, session.lastClientY);
14179
14295
  },
14180
14296
  [
@@ -14196,10 +14312,11 @@ function useNavItemDrag({
14196
14312
  }
14197
14313
  const x = typeof clientX === "number" && (clientX !== 0 || clientY !== 0) ? clientX : session.lastClientX;
14198
14314
  const y = typeof clientY === "number" && (clientX !== 0 || clientY !== 0) ? clientY : session.lastClientY;
14199
- const slot = session.activeSlot ?? hitTestNavDropSlot(x, y, session.hrefKey);
14315
+ const slot = session.activeSlot ?? hitTestNavDropSlot(x, y, session.hrefKey, session.draggedEl);
14200
14316
  const planned = slot != null ? planNavItemMove(session.hrefKey, slot.parentId, slot.insertIndex) : null;
14201
14317
  const wasSelected = session.wasSelected;
14202
14318
  const hrefKey = session.hrefKey;
14319
+ const keepDropdownOpen = Boolean(session.draggedEl.closest("[data-ohw-nav-children]"));
14203
14320
  const applySelectionAfterDrop = () => {
14204
14321
  if (!wasSelected) {
14205
14322
  deselectRef.current();
@@ -14233,6 +14350,14 @@ function useNavItemDrag({
14233
14350
  });
14234
14351
  applySelectionAfterDrop();
14235
14352
  clearNavDragVisuals();
14353
+ if (keepDropdownOpen) {
14354
+ requestAnimationFrame(() => {
14355
+ const desktop = document.querySelector("[data-ohw-nav-container]");
14356
+ const drawer = document.querySelector("[data-ohw-nav-drawer]");
14357
+ 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)}"]`);
14358
+ if (link) setNavGroupForceOpen(link, true);
14359
+ });
14360
+ }
14236
14361
  requestAnimationFrame(() => {
14237
14362
  if (editContentRef.current[NAV_ORDER_KEY] === planned.orderJson) {
14238
14363
  applyNavForest(planned.forest);
@@ -14272,7 +14397,7 @@ function useNavItemDrag({
14272
14397
  if (!session) return false;
14273
14398
  e.preventDefault();
14274
14399
  if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
14275
- const slot = hitTestNavDropSlot(e.clientX, e.clientY, session.hrefKey);
14400
+ const slot = hitTestNavDropSlot(e.clientX, e.clientY, session.hrefKey, session.draggedEl);
14276
14401
  refreshNavDragVisualsRef.current(session, slot, e.clientX, e.clientY);
14277
14402
  return true;
14278
14403
  },
@@ -14318,7 +14443,7 @@ function useNavItemDrag({
14318
14443
  clearTextSelection();
14319
14444
  const session = navDragRef.current;
14320
14445
  if (!session) return;
14321
- const slot = hitTestNavDropSlot(e.clientX, e.clientY, session.hrefKey);
14446
+ const slot = hitTestNavDropSlot(e.clientX, e.clientY, session.hrefKey, session.draggedEl);
14322
14447
  refreshNavDragVisualsRef.current(session, slot, e.clientX, e.clientY);
14323
14448
  return;
14324
14449
  }
@@ -14334,7 +14459,8 @@ function useNavItemDrag({
14334
14459
  } catch {
14335
14460
  }
14336
14461
  if (linkPopoverOpenRef.current) setLinkPopover(null);
14337
- if (activeElRef.current) deactivateRef.current();
14462
+ const isNestedDrag = Boolean(pending.el.closest("[data-ohw-nav-children]"));
14463
+ if (activeElRef.current && !isNestedDrag) deactivateRef.current();
14338
14464
  const key = pending.el.getAttribute("data-ohw-href-key");
14339
14465
  if (!key) return;
14340
14466
  beginNavDragRef.current({
@@ -14345,6 +14471,9 @@ function useNavItemDrag({
14345
14471
  lastClientY: e.clientY,
14346
14472
  activeSlot: null
14347
14473
  });
14474
+ if (activeElRef.current && isNestedDrag) {
14475
+ deactivateRef.current();
14476
+ }
14348
14477
  };
14349
14478
  const endPointerDrag = (e) => {
14350
14479
  const pending = navPointerDragRef.current;
@@ -14422,6 +14551,7 @@ function useNavItemDrag({
14422
14551
  );
14423
14552
  return {
14424
14553
  navDragRef,
14554
+ navPointerDragRef,
14425
14555
  navDropSlots,
14426
14556
  activeNavDropIndex,
14427
14557
  startNavLinkDrag,
@@ -15820,6 +15950,7 @@ function isNavDropdownPanelOpen(childrenRoot) {
15820
15950
  if (childrenRoot.closest("[data-ohw-nav-drawer]")) return true;
15821
15951
  const group = childrenRoot.closest("[data-ohw-nav-group]");
15822
15952
  if (group?.hasAttribute("data-ohw-nav-force-open")) return true;
15953
+ if (navDropdownsOpenOnClick()) return false;
15823
15954
  if (childrenRoot.clientHeight < 2 || childrenRoot.clientWidth < 2) return false;
15824
15955
  const style = window.getComputedStyle(childrenRoot);
15825
15956
  if (style.display === "none" || style.visibility === "hidden") return false;
@@ -15863,6 +15994,11 @@ function getNavigationItemAnchor(el) {
15863
15994
  function isNavigationItem2(el) {
15864
15995
  return getNavigationItemAnchor(el) !== null;
15865
15996
  }
15997
+ function isNavFooterScopedNavigationItem(el) {
15998
+ return Boolean(
15999
+ el.closest("nav, footer, [data-ohw-nav-container], [data-ohw-nav-drawer]")
16000
+ );
16001
+ }
15866
16002
  function socialWordsClicked(target, item) {
15867
16003
  const text = target.closest('[data-ohw-editable="text"], [data-ohw-editable="plain"]');
15868
16004
  return Boolean(text && item.contains(text));
@@ -16073,6 +16209,7 @@ function getNavigationSelectionParent(el) {
16073
16209
  }
16074
16210
  function collectNavigationItemSiblingHintRects(selected) {
16075
16211
  if (!isNavigationItem2(selected)) return [];
16212
+ if (!isNavFooterScopedNavigationItem(selected)) return [];
16076
16213
  const socialsRow = findSocialsRow(selected);
16077
16214
  if (socialsRow) {
16078
16215
  return listSocialItems(socialsRow).filter((item) => item !== selected).map((item) => item.getBoundingClientRect());
@@ -17244,6 +17381,7 @@ function OhhwellsBridge() {
17244
17381
  linkPopoverSessionRef.current = linkPopover;
17245
17382
  const {
17246
17383
  navDragRef,
17384
+ navPointerDragRef,
17247
17385
  navDropSlots,
17248
17386
  activeNavDropIndex,
17249
17387
  startNavLinkDrag,
@@ -17446,7 +17584,12 @@ function OhhwellsBridge() {
17446
17584
  if (owner) persistFieldsRef.current(owner);
17447
17585
  }
17448
17586
  activeElRef.current = null;
17449
- setNavGroupForceOpen(null, false);
17587
+ const preserveNavDropdown = Boolean(navPointerDragRef.current?.el?.closest("[data-ohw-nav-children]")) || Boolean(navDragRef.current?.draggedEl?.closest("[data-ohw-nav-children]")) || Boolean(
17588
+ selectedElRef.current?.closest("[data-ohw-nav-children]") && selectedElRef.current?.closest("[data-ohw-nav-group]")?.hasAttribute("data-ohw-nav-force-open")
17589
+ );
17590
+ if (!preserveNavDropdown) {
17591
+ setNavGroupForceOpen(null, false);
17592
+ }
17450
17593
  setReorderHrefKey(null);
17451
17594
  setReorderDragDisabled(false);
17452
17595
  if (!selectedElRef.current) {
@@ -17568,7 +17711,10 @@ function OhhwellsBridge() {
17568
17711
  setSelectedIsSocialsRow(false);
17569
17712
  const isDropdownTrigger = !isNestedNavChild(navAnchor) && (navItemHasDropdownChildren(navAnchor) || navItemOwnsDropdownPanel(navAnchor));
17570
17713
  if (isNestedNavChild(navAnchor)) {
17571
- setNavGroupForceOpen(navAnchor, true);
17714
+ const group = navAnchor.closest("[data-ohw-nav-group]");
17715
+ if (group?.hasAttribute("data-ohw-nav-force-open")) {
17716
+ setNavGroupForceOpen(navAnchor, true);
17717
+ }
17572
17718
  setNavDropdownPreviewOpen(null);
17573
17719
  } else if (isDropdownTrigger) {
17574
17720
  const group = navAnchor.closest("[data-ohw-nav-group]");
@@ -17650,6 +17796,10 @@ function OhhwellsBridge() {
17650
17796
  const handleNavDropdownOpenChange = useCallback8((open) => {
17651
17797
  const selected = selectedElRef.current;
17652
17798
  if (!selected || !isNavigationItem2(selected)) return;
17799
+ if (isNestedNavChild(selected)) return;
17800
+ const group = selected.closest("[data-ohw-nav-group]");
17801
+ const domOpen = Boolean(group?.hasAttribute("data-ohw-nav-force-open"));
17802
+ if (open === domOpen) return;
17653
17803
  setNavGroupForceOpen(selected, open);
17654
17804
  setNavDropdownPreviewOpen(open);
17655
17805
  requestAnimationFrame(() => {
@@ -18179,7 +18329,10 @@ function OhhwellsBridge() {
18179
18329
  clearHrefKeyHover(anchor);
18180
18330
  const isDropdownTrigger = !isNestedNavChild(anchor) && (navItemHasDropdownChildren(anchor) || navItemOwnsDropdownPanel(anchor));
18181
18331
  if (isNestedNavChild(anchor)) {
18182
- setNavGroupForceOpen(anchor, true);
18332
+ const group = anchor.closest("[data-ohw-nav-group]");
18333
+ if (group?.hasAttribute("data-ohw-nav-force-open")) {
18334
+ setNavGroupForceOpen(anchor, true);
18335
+ }
18183
18336
  setNavDropdownPreviewOpen(null);
18184
18337
  } else if (isDropdownTrigger) {
18185
18338
  setNavGroupForceOpen(null, false);
@@ -19021,28 +19174,19 @@ function OhhwellsBridge() {
19021
19174
  return;
19022
19175
  }
19023
19176
  const existing = editStylesRef.current;
19024
- let initialVh = window.innerHeight;
19025
- if (existing?.base.textContent) {
19026
- const match = existing.base.textContent.match(/\.min-h-screen[^{]*\{[^}]*min-height:\s*(\d+)px/);
19027
- if (match) initialVh = parseInt(match[1], 10);
19028
- }
19177
+ const canvasHeight = "var(--ohw-canvas-h, 852px)";
19029
19178
  const baseCss = `
19030
19179
  html { height: auto !important; }
19031
19180
  body { height: auto !important; min-height: 0 !important; overflow: hidden !important; }
19032
- .min-h-screen, .min-h-svh, .min-h-dvh { min-height: ${initialVh}px !important; }
19033
- .h-screen, .h-svh, .h-dvh { height: ${initialVh}px !important; }
19034
- [style*="100vh"] { min-height: ${initialVh}px !important; height: ${initialVh}px !important; }
19035
- [style*="100svh"] { min-height: ${initialVh}px !important; height: ${initialVh}px !important; }
19036
- [style*="100dvh"] { min-height: ${initialVh}px !important; height: ${initialVh}px !important; }
19037
- /* A section written as min-height: var(--ohw-canvas-h, 100svh) \u2014 the documented way to
19038
- build a full-viewport section that still grows for its own content \u2014 matches the three
19039
- rules above on substring alone, since the fallback text contains "100svh" too. Forcing
19040
- a literal height on top of that turns "at least one screen" into "exactly one screen",
19041
- so content taller than one screen (a long mobile hero, say) overflows a centered flex
19042
- column upward, under whatever sits above it. Only the min-height half belongs to it. */
19043
- [style*="min-height"][style*="100vh"],
19044
- [style*="min-height"][style*="100svh"],
19045
- [style*="min-height"][style*="100dvh"] { height: auto !important; }
19181
+ .min-h-screen, .min-h-svh, .min-h-dvh { min-height: ${canvasHeight} !important; }
19182
+ .h-screen, .h-svh, .h-dvh { height: ${canvasHeight} !important; }
19183
+ /* Literal inline viewport units only \u2014 skip R11 sections that already reference --ohw-canvas-h
19184
+ (their style attribute contains "100svh" only as a var() fallback string). */
19185
+ [style*="100vh"]:not([style*="--ohw-canvas-h"]) { min-height: ${canvasHeight} !important; height: ${canvasHeight} !important; }
19186
+ [style*="100svh"]:not([style*="--ohw-canvas-h"]) { min-height: ${canvasHeight} !important; height: ${canvasHeight} !important; }
19187
+ [style*="100dvh"]:not([style*="--ohw-canvas-h"]) { min-height: ${canvasHeight} !important; height: ${canvasHeight} !important; }
19188
+ /* R11: min-height via --ohw-canvas-h; height must grow with content taller than one screen. */
19189
+ [style*="min-height"][style*="--ohw-canvas-h"] { height: auto !important; }
19046
19190
  /* Emptied text keeps somewhere to click. A label typed down to nothing collapses to a
19047
19191
  couple of pixels, and getting back into it meant hunting for the caret with the mouse.
19048
19192
  Edit mode only \u2014 the published page shows nothing where there is nothing (OHH-736). */
@@ -19189,6 +19333,10 @@ function OhhwellsBridge() {
19189
19333
  outline-offset: 0 !important;
19190
19334
  box-shadow: none !important;
19191
19335
  }
19336
+ /* Open nav dropdown panels paint above AI section selection chrome (2147483000). */
19337
+ [data-ohw-nav-group][data-ohw-nav-force-open] > [data-ohw-nav-children] {
19338
+ z-index: 2147483100 !important;
19339
+ }
19192
19340
  /* Text edit wins over grab/default (must beat [data-ohw-can-drag] *). */
19193
19341
  [data-ohw-editing],
19194
19342
  [data-ohw-editing] *,
@@ -20527,7 +20675,11 @@ function OhhwellsBridge() {
20527
20675
  const slotFromItem = hrefKey ? findSocialByHrefKey(hrefKey)?.querySelector('[data-ohw-editable="icon"]') : null;
20528
20676
  const requestedIsIconSlot = Boolean(requestedIconKey) && Boolean(document.querySelector(`[data-ohw-key="${requestedIconKey}"][data-ohw-editable="icon"]`));
20529
20677
  const requestedIsFree = Boolean(requestedIconKey) && !document.querySelector(`[data-ohw-key="${requestedIconKey}"]`);
20530
- const iconKey = requestedIsIconSlot ? requestedIconKey : slotFromItem?.dataset.ohwKey ?? (requestedIsFree ? requestedIconKey : void 0);
20678
+ let iconKey = requestedIsIconSlot ? requestedIconKey : slotFromItem?.dataset.ohwKey ?? (requestedIsFree ? requestedIconKey : void 0);
20679
+ const item = hrefKey ? findSocialByHrefKey(hrefKey) : null;
20680
+ if (item && typeof iconMarkup === "string" && iconMarkup) {
20681
+ iconKey = ensureIconSlot(item) ?? iconKey;
20682
+ }
20531
20683
  if (iconKey && typeof iconMarkup === "string" && iconMarkup) {
20532
20684
  document.querySelectorAll(`[data-ohw-key="${iconKey}"][data-ohw-editable="icon"]`).forEach((el) => {
20533
20685
  applyIconMarkup(el, iconMarkup);
@@ -20537,7 +20689,7 @@ function OhhwellsBridge() {
20537
20689
  }
20538
20690
  if (iconKey && platformId) nodes.push({ key: socialPlatformKey(iconKey), text: platformId });
20539
20691
  if (iconKey && label) {
20540
- const labelKey = socialLabelKey(iconKey);
20692
+ const labelKey = (item ? socialLabelElement(item)?.getAttribute("data-ohw-key") : null) ?? socialLabelKey(iconKey);
20541
20693
  document.querySelectorAll(`[data-ohw-key="${labelKey}"]`).forEach((el) => {
20542
20694
  if (keepLabel && el.textContent?.trim()) return;
20543
20695
  el.textContent = label;
@@ -21356,7 +21508,12 @@ function OhhwellsBridge() {
21356
21508
  }
21357
21509
  if (navDragRef.current) {
21358
21510
  const session = navDragRef.current;
21359
- const slot = hitTestNavDropSlot(session.lastClientX, session.lastClientY, session.hrefKey);
21511
+ const slot = hitTestNavDropSlot(
21512
+ session.lastClientX,
21513
+ session.lastClientY,
21514
+ session.hrefKey,
21515
+ session.draggedEl
21516
+ );
21360
21517
  refreshNavDragVisualsRef.current(session, slot, session.lastClientX, session.lastClientY);
21361
21518
  }
21362
21519
  if (hoveredImageRef.current) {
@@ -21558,18 +21715,21 @@ function OhhwellsBridge() {
21558
21715
  }
21559
21716
  return null;
21560
21717
  };
21718
+ const isPointInRect = (el, clientX, clientY) => {
21719
+ const r2 = el.getBoundingClientRect();
21720
+ return clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom;
21721
+ };
21561
21722
  const isPointOverEditable = (scope, clientX, clientY) => {
21562
21723
  const editables = scope.querySelectorAll("[data-ohw-editable], [data-ohw-href-key]");
21563
21724
  for (const el of editables) {
21564
- const r2 = el.getBoundingClientRect();
21565
- if (clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom) return true;
21725
+ if (isPointInRect(el, clientX, clientY)) return true;
21566
21726
  }
21567
21727
  return false;
21568
21728
  };
21569
21729
  const handleCarouselHover = (e) => {
21570
21730
  const container = findCarouselAtPoint(e.clientX, e.clientY);
21571
21731
  const scope = container?.closest("[data-ohw-section]") ?? container?.parentElement ?? null;
21572
- if (!container || !scope || isPointOverEditable(scope, e.clientX, e.clientY)) {
21732
+ if (!container || !scope || isPointOverEditable(scope, e.clientX, e.clientY) || isPointOverNavigation(e.clientX, e.clientY) || isPointOverBridgeChrome(e.clientX, e.clientY)) {
21573
21733
  setCarouselHover((prev) => prev ? null : prev);
21574
21734
  return;
21575
21735
  }
@@ -22018,7 +22178,7 @@ function OhhwellsBridge() {
22018
22178
  postToParent2({
22019
22179
  type: "ow:ready",
22020
22180
  version: "1",
22021
- bridgeVersion: "0.1.99",
22181
+ bridgeVersion: "0.1.100",
22022
22182
  path: pathname,
22023
22183
  nodes: collectEditableNodes(editContentRef.current),
22024
22184
  sections