@ohhwells/bridge 0.1.51-next.120 → 0.1.51-next.121

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
@@ -6831,6 +6831,9 @@ function listNavbarItems() {
6831
6831
  }
6832
6832
  return Array.from(document.querySelectorAll("nav [data-ohw-href-key]")).filter(isNavbarLinkItem);
6833
6833
  }
6834
+ function listNavbarRootItems() {
6835
+ return listNavbarItems().filter((el) => !isNestedNavChild(el));
6836
+ }
6834
6837
  function parseNavIndexFromKey(key) {
6835
6838
  if (!key) return null;
6836
6839
  const match = key.match(NAV_HREF_RE);
@@ -6859,6 +6862,12 @@ function getNavOrderFromDom() {
6859
6862
  function findCounterpartByHrefKey(hrefKey, root) {
6860
6863
  return root.querySelector(`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`);
6861
6864
  }
6865
+ function resolveNavRootUnit(anchor) {
6866
+ if (anchor.closest("[data-ohw-nav-children]")) return anchor;
6867
+ const group = anchor.closest("[data-ohw-nav-group]");
6868
+ if (group?.querySelector(":scope > [data-ohw-nav-children]")) return group;
6869
+ return anchor;
6870
+ }
6862
6871
  function cloneNavLinkShell(template) {
6863
6872
  const anchor = document.createElement("a");
6864
6873
  if (template) {
@@ -6882,37 +6891,47 @@ function buildNavLink(index, href, label, template) {
6882
6891
  }
6883
6892
  function insertNavLinkInContainer(container, anchor, afterHrefKey) {
6884
6893
  if (!afterHrefKey) {
6894
+ const cta = container.querySelector('[data-ohw-role="navbar-button"]');
6895
+ if (cta && cta.parentElement === container) {
6896
+ container.insertBefore(anchor, cta);
6897
+ return;
6898
+ }
6885
6899
  container.appendChild(anchor);
6886
6900
  return;
6887
6901
  }
6888
6902
  const afterEl = findCounterpartByHrefKey(afterHrefKey, container);
6889
- if (afterEl?.parentElement === container) {
6890
- afterEl.insertAdjacentElement("afterend", anchor);
6891
- return;
6903
+ if (afterEl) {
6904
+ const insertAfter = resolveNavRootUnit(afterEl);
6905
+ if (insertAfter.parentElement === container || insertAfter.parentElement === afterEl.parentElement) {
6906
+ insertAfter.insertAdjacentElement("afterend", anchor);
6907
+ return;
6908
+ }
6892
6909
  }
6893
6910
  container.appendChild(anchor);
6894
6911
  }
6895
6912
  function insertNavbarItemDom(index, href, label, afterAnchor) {
6896
6913
  const afterHrefKey = afterAnchor?.getAttribute("data-ohw-href-key") ?? null;
6897
- const desktopItems = getNavbarDesktopContainer()?.querySelectorAll("[data-ohw-href-key]") ?? [];
6898
- const drawerItems = getNavbarDrawerContainer()?.querySelectorAll("[data-ohw-href-key]") ?? [];
6899
- const desktopTemplate = Array.from(desktopItems).find(isNavbarLinkItem) ?? null;
6900
- const drawerTemplate = Array.from(drawerItems).find(isNavbarLinkItem) ?? null;
6901
- let primary = null;
6902
6914
  const desktopContainer = getNavbarDesktopContainer();
6915
+ const drawerContainer = getNavbarDrawerContainer();
6916
+ const desktopTemplate = (desktopContainer ? Array.from(desktopContainer.querySelectorAll("[data-ohw-href-key]")).find(
6917
+ (el) => isNavbarLinkItem(el) && !el.closest("[data-ohw-nav-children]")
6918
+ ) : null) ?? null;
6919
+ const drawerTemplate = (drawerContainer ? Array.from(drawerContainer.querySelectorAll("[data-ohw-href-key]")).find(
6920
+ (el) => isNavbarLinkItem(el) && !el.closest("[data-ohw-nav-children]")
6921
+ ) : null) ?? null;
6922
+ let primary = null;
6903
6923
  if (desktopContainer) {
6904
6924
  const desktopAnchor = buildNavLink(index, href, label, desktopTemplate);
6905
6925
  insertNavLinkInContainer(desktopContainer, desktopAnchor, afterHrefKey);
6906
6926
  primary = desktopAnchor;
6907
6927
  }
6908
- const drawerContainer = getNavbarDrawerContainer();
6909
6928
  if (drawerContainer) {
6910
6929
  const drawerAnchor = buildNavLink(index, href, label, drawerTemplate);
6911
6930
  insertNavLinkInContainer(drawerContainer, drawerAnchor, afterHrefKey);
6912
6931
  if (!primary) primary = drawerAnchor;
6913
6932
  }
6914
6933
  if (!primary) {
6915
- const fallback = buildNavLink(index, href, label, listNavbarItems()[0] ?? null);
6934
+ const fallback = buildNavLink(index, href, label, listNavbarRootItems()[0] ?? null);
6916
6935
  const nav = document.querySelector("nav");
6917
6936
  nav?.appendChild(fallback);
6918
6937
  primary = fallback;
@@ -6926,35 +6945,46 @@ function navOrderKeysEqual(a, b) {
6926
6945
  }
6927
6946
  return true;
6928
6947
  }
6929
- function getNavbarLinkKeysInContainer(container) {
6930
- return Array.from(container.querySelectorAll("[data-ohw-href-key]")).filter(isNavbarLinkItem).map((el) => el.getAttribute("data-ohw-href-key")).filter((key) => Boolean(key));
6948
+ function getNavbarRootUnitsInContainer(container) {
6949
+ const result = [];
6950
+ for (const child of Array.from(container.children)) {
6951
+ if (!(child instanceof HTMLElement)) continue;
6952
+ if (child.hasAttribute("data-ohw-nav-group")) {
6953
+ const trigger = child.querySelector(":scope > [data-ohw-href-key]");
6954
+ if (!trigger || !isNavbarLinkItem(trigger)) continue;
6955
+ const key = trigger.getAttribute("data-ohw-href-key");
6956
+ if (key) result.push({ key, unit: child });
6957
+ continue;
6958
+ }
6959
+ if (child.matches("[data-ohw-href-key]") && isNavbarLinkItem(child)) {
6960
+ const key = child.getAttribute("data-ohw-href-key");
6961
+ if (key) result.push({ key, unit: child });
6962
+ }
6963
+ }
6964
+ return result;
6931
6965
  }
6932
6966
  function applyNavOrderToContainer(container, order) {
6933
6967
  const desired = order.filter((key, i) => order.indexOf(key) === i);
6934
- const current = getNavbarLinkKeysInContainer(container);
6968
+ const units = getNavbarRootUnitsInContainer(container);
6969
+ const current = units.map((u) => u.key);
6935
6970
  const extras = current.filter((key) => !desired.includes(key));
6936
6971
  const expected = [...desired.filter((key) => current.includes(key)), ...extras];
6937
- const orderedEls = [];
6938
6972
  if (navOrderKeysEqual(current, expected)) return;
6939
- if (current.length === expected.length && current.every((key, i) => key === expected[i])) {
6940
- return;
6941
- }
6942
- const lastCurrentLinkEl = current.length > 0 ? findCounterpartByHrefKey(current[current.length - 1], container) : null;
6943
- const anchor = lastCurrentLinkEl?.parentElement === container ? lastCurrentLinkEl.nextElementSibling : null;
6973
+ const lastUnit = units[units.length - 1]?.unit ?? null;
6974
+ const anchor = lastUnit?.parentElement === container ? lastUnit.nextElementSibling : null;
6975
+ const orderedUnits = [];
6944
6976
  const seen = /* @__PURE__ */ new Set();
6945
6977
  for (const hrefKey of desired) {
6946
6978
  if (seen.has(hrefKey)) continue;
6947
6979
  seen.add(hrefKey);
6948
- const el = findCounterpartByHrefKey(hrefKey, container);
6949
- if (el && isNavbarLinkItem(el)) orderedEls.push(el);
6980
+ const match = units.find((u) => u.key === hrefKey);
6981
+ if (match) orderedUnits.push(match.unit);
6950
6982
  }
6951
- for (const el of container.querySelectorAll("[data-ohw-href-key]")) {
6952
- if (!isNavbarLinkItem(el)) continue;
6953
- const key = el.getAttribute("data-ohw-href-key");
6954
- if (!key || seen.has(key)) continue;
6955
- orderedEls.push(el);
6983
+ for (const unit of units) {
6984
+ if (seen.has(unit.key)) continue;
6985
+ orderedUnits.push(unit.unit);
6956
6986
  }
6957
- for (const el of orderedEls) {
6987
+ for (const el of orderedUnits) {
6958
6988
  if (anchor) {
6959
6989
  if (el.nextSibling !== anchor) container.insertBefore(el, anchor);
6960
6990
  } else if (container.lastElementChild !== el) {
@@ -7028,6 +7058,20 @@ function getNavForestFromDom() {
7028
7058
  }
7029
7059
  function planNavItemMove(hrefKey, parentId, insertIndex) {
7030
7060
  const model = getNavForestFromDom();
7061
+ let currentParent;
7062
+ for (const root of model) {
7063
+ if (root.id === hrefKey) {
7064
+ currentParent = null;
7065
+ break;
7066
+ }
7067
+ if (root.children.some((c) => c.id === hrefKey)) {
7068
+ currentParent = root.id;
7069
+ break;
7070
+ }
7071
+ }
7072
+ if (currentParent === void 0) return null;
7073
+ if (currentParent === null && parentId !== null) return null;
7074
+ if (currentParent !== null && parentId !== currentParent) return null;
7031
7075
  const next = moveNode(model, hrefKey, { parentId, index: insertIndex });
7032
7076
  if (!next) return null;
7033
7077
  if (forestsEqual(model, next)) return null;
@@ -7055,18 +7099,246 @@ function collectNavbarIndicesFromContent(content) {
7055
7099
  function navbarIndexExistsInDom(index) {
7056
7100
  return document.querySelector(`[data-ohw-href-key="nav-${index}-href"]`) !== null;
7057
7101
  }
7102
+ function findReferenceNavGroup(options) {
7103
+ const templates = Array.from(
7104
+ document.querySelectorAll("[data-ohw-nav-dropdown-template][data-ohw-nav-group]")
7105
+ ).filter((el) => el.querySelector(":scope > [data-ohw-nav-children]"));
7106
+ if (options?.drawer) {
7107
+ const drawerTpl = templates.find((el) => el.closest("[data-ohw-nav-drawer]"));
7108
+ if (drawerTpl) return drawerTpl;
7109
+ } else {
7110
+ const desktopTpl = templates.find((el) => !el.closest("[data-ohw-nav-drawer]"));
7111
+ if (desktopTpl) return desktopTpl;
7112
+ }
7113
+ if (templates[0]) return templates[0];
7114
+ const roots = [getNavbarDesktopContainer(), getNavbarDrawerContainer()].filter(
7115
+ (el) => Boolean(el)
7116
+ );
7117
+ const searchRoots = roots.length > 0 ? roots : [document.body];
7118
+ for (const root of searchRoots) {
7119
+ for (const group of root.querySelectorAll("[data-ohw-nav-group]")) {
7120
+ if (group.hasAttribute("data-ohw-nav-dropdown-template")) continue;
7121
+ if (group.querySelector(":scope > [data-ohw-nav-children]")) {
7122
+ return group;
7123
+ }
7124
+ }
7125
+ }
7126
+ return null;
7127
+ }
7128
+ function navDropdownsOpenOnClick() {
7129
+ const container = getNavbarDesktopContainer();
7130
+ const mode = container?.getAttribute("data-ohw-nav-open") ?? findReferenceNavGroup()?.getAttribute("data-ohw-nav-open") ?? document.querySelector("[data-ohw-nav-dropdown-template][data-ohw-nav-group]")?.getAttribute("data-ohw-nav-open") ?? document.querySelector("[data-ohw-nav-group]")?.getAttribute("data-ohw-nav-open");
7131
+ return mode !== "hover";
7132
+ }
7133
+ function navItemHasOwnUrl(anchor) {
7134
+ const href = getLinkHref(anchor).trim();
7135
+ if (!href || href === "#" || href.toLowerCase().startsWith("javascript:")) return false;
7136
+ return true;
7137
+ }
7138
+ function navItemHasDropdownChildren(anchor) {
7139
+ const key = anchor.getAttribute("data-ohw-href-key");
7140
+ if (!key) return false;
7141
+ const node = getNavForestFromDom().find((n) => n.id === key);
7142
+ return Boolean(node && node.children.length > 0);
7143
+ }
7144
+ function isNestedNavChild(anchor) {
7145
+ return Boolean(anchor.closest("[data-ohw-nav-children]"));
7146
+ }
7147
+ function navItemOwnsDropdownPanel(anchor) {
7148
+ if (isNestedNavChild(anchor)) return true;
7149
+ const group = anchor.closest("[data-ohw-nav-group]");
7150
+ return Boolean(group?.querySelector(":scope > [data-ohw-nav-children]"));
7151
+ }
7152
+ function setNavGroupForceOpen(anchor, open) {
7153
+ document.querySelectorAll("[data-ohw-nav-force-open]").forEach((el) => {
7154
+ el.removeAttribute("data-ohw-nav-force-open");
7155
+ });
7156
+ if (!open || !anchor) return;
7157
+ const group = anchor.closest("[data-ohw-nav-group]");
7158
+ group?.setAttribute("data-ohw-nav-force-open", "");
7159
+ }
7160
+ function cloneChildrenShell(referenceChildren) {
7161
+ const childrenRoot = document.createElement(referenceChildren.tagName.toLowerCase() || "div");
7162
+ childrenRoot.setAttribute("data-ohw-nav-children", "");
7163
+ if (referenceChildren.className) childrenRoot.className = referenceChildren.className;
7164
+ return childrenRoot;
7165
+ }
7166
+ function ensureCaretOnTrigger(trigger, referenceGroup) {
7167
+ if (trigger.querySelector("[data-ohw-nav-caret], .navbar__caret, .topnav__caret, .mobile-menu__caret")) {
7168
+ return;
7169
+ }
7170
+ const refCaret = referenceGroup?.querySelector(
7171
+ "[data-ohw-nav-caret], .navbar__caret, .topnav__caret, .mobile-menu__caret"
7172
+ ) ?? null;
7173
+ if (refCaret) {
7174
+ trigger.appendChild(refCaret.cloneNode(true));
7175
+ return;
7176
+ }
7177
+ const caret = document.createElement("span");
7178
+ caret.setAttribute("data-ohw-nav-caret", "");
7179
+ caret.setAttribute("aria-hidden", "true");
7180
+ trigger.appendChild(caret);
7181
+ }
7182
+ function ensureNavDropdownForParent(parentAnchor) {
7183
+ const parentHrefKey = parentAnchor.getAttribute("data-ohw-href-key");
7184
+ if (!parentHrefKey) return null;
7185
+ const containers = [getNavbarDesktopContainer(), getNavbarDrawerContainer()].filter(
7186
+ (el) => Boolean(el)
7187
+ );
7188
+ const searchRoots = containers.length > 0 ? containers : [document.body];
7189
+ let primaryGroup = null;
7190
+ for (const root of searchRoots) {
7191
+ const trigger = findCounterpartByHrefKey(parentHrefKey, root);
7192
+ if (!trigger || !isNavbarLinkItem(trigger)) continue;
7193
+ const existing = trigger.closest("[data-ohw-nav-group]");
7194
+ if (existing?.querySelector(":scope > [data-ohw-nav-children]")) {
7195
+ if (!primaryGroup) primaryGroup = existing;
7196
+ continue;
7197
+ }
7198
+ const parent = trigger.parentElement;
7199
+ if (!parent) continue;
7200
+ const isDrawer = Boolean(root.closest("[data-ohw-nav-drawer]")) || root.hasAttribute("data-ohw-nav-drawer");
7201
+ const reference = findReferenceNavGroup({ drawer: isDrawer });
7202
+ if (!reference) continue;
7203
+ const refChildren = reference.querySelector(":scope > [data-ohw-nav-children]");
7204
+ if (!refChildren) continue;
7205
+ const group = document.createElement(reference.tagName.toLowerCase() || "div");
7206
+ group.setAttribute("data-ohw-nav-group", "");
7207
+ if (reference.className) group.className = reference.className;
7208
+ const openMode = reference.getAttribute("data-ohw-nav-open");
7209
+ if (openMode) group.setAttribute("data-ohw-nav-open", openMode);
7210
+ const childrenRoot = cloneChildrenShell(refChildren);
7211
+ parent.insertBefore(group, trigger);
7212
+ group.appendChild(trigger);
7213
+ ensureCaretOnTrigger(trigger, reference);
7214
+ const refTrigger = reference.querySelector(
7215
+ ":scope > a, :scope > [data-ohw-href-key], :scope > .navbar__link, :scope > .topnav__link"
7216
+ );
7217
+ if (refTrigger?.className && !trigger.className) {
7218
+ trigger.className = refTrigger.className;
7219
+ }
7220
+ group.appendChild(childrenRoot);
7221
+ if (!primaryGroup) primaryGroup = group;
7222
+ }
7223
+ return primaryGroup;
7224
+ }
7225
+ function insertChildLinkInChildrenRoot(childrenRoot, anchor) {
7226
+ childrenRoot.appendChild(anchor);
7227
+ }
7228
+ function resolveChildNavLinkTemplate(childrenRoot, parentTrigger) {
7229
+ const sibling = childrenRoot.querySelector(":scope > [data-ohw-href-key]");
7230
+ if (sibling && isNavbarLinkItem(sibling)) return sibling;
7231
+ const isDrawer = Boolean(childrenRoot.closest("[data-ohw-nav-drawer]"));
7232
+ const refChild = findReferenceNavGroup({ drawer: isDrawer })?.querySelector(
7233
+ ":scope > [data-ohw-nav-children] > a, :scope > [data-ohw-nav-children] > [data-ohw-href-key]"
7234
+ );
7235
+ if (refChild) return refChild;
7236
+ if (parentTrigger && isNavbarLinkItem(parentTrigger)) return parentTrigger;
7237
+ const container = childrenRoot.closest("[data-ohw-nav-container], [data-ohw-nav-drawer]") ?? null;
7238
+ if (container) {
7239
+ const local = Array.from(container.querySelectorAll("[data-ohw-href-key]")).find(
7240
+ (el) => isNavbarLinkItem(el) && !el.closest("[data-ohw-nav-children]")
7241
+ );
7242
+ if (local) return local;
7243
+ }
7244
+ return listNavbarRootItems()[0] ?? null;
7245
+ }
7246
+ function buildChildNavLink(index, href, label, childrenRoot, parentTrigger = null) {
7247
+ const template = resolveChildNavLinkTemplate(childrenRoot, parentTrigger);
7248
+ return buildNavLink(index, href, label, template);
7249
+ }
7250
+ function addNavbarSubitem(parentAnchor, href = "/", label = "New") {
7251
+ if (!isNavbarLinkItem(parentAnchor) || isNestedNavChild(parentAnchor)) return null;
7252
+ const parentHrefKey = parentAnchor.getAttribute("data-ohw-href-key");
7253
+ if (!parentHrefKey || !isNavbarHrefKey(parentHrefKey)) return null;
7254
+ const group = ensureNavDropdownForParent(parentAnchor);
7255
+ if (!group) return null;
7256
+ const index = getNextNavbarIndex();
7257
+ const hrefKey = `nav-${index}-href`;
7258
+ const labelKey = `nav-${index}-label`;
7259
+ let primary = null;
7260
+ const containers = [getNavbarDesktopContainer(), getNavbarDrawerContainer()].filter(
7261
+ (el) => Boolean(el)
7262
+ );
7263
+ const searchRoots = containers.length > 0 ? containers : [document.body];
7264
+ for (const root of searchRoots) {
7265
+ const trigger = findCounterpartByHrefKey(parentHrefKey, root);
7266
+ const parentGroup = trigger?.closest("[data-ohw-nav-group]");
7267
+ const childrenRoot = parentGroup?.querySelector(":scope > [data-ohw-nav-children]");
7268
+ if (!childrenRoot) continue;
7269
+ const childAnchor = buildChildNavLink(index, href, label, childrenRoot, trigger);
7270
+ insertChildLinkInChildrenRoot(childrenRoot, childAnchor);
7271
+ if (!primary) primary = childAnchor;
7272
+ }
7273
+ if (!primary) return null;
7274
+ const forest = getNavForestFromDom();
7275
+ applyNavForest(forest);
7276
+ const orderJson = serializeNavOrder(forest);
7277
+ return {
7278
+ anchor: primary,
7279
+ index,
7280
+ hrefKey,
7281
+ labelKey,
7282
+ href,
7283
+ label,
7284
+ order: flattenNavOrder(forest),
7285
+ orderJson,
7286
+ parentHrefKey
7287
+ };
7288
+ }
7058
7289
  function reconcileNavbarItemsFromContent(content) {
7059
7290
  const orderForest = parseNavOrderJson(content[NAV_ORDER_KEY]);
7060
7291
  if (orderForest?.length) {
7061
7292
  const allowed = new Set(flattenNavOrder(orderForest));
7062
- for (const hrefKey of allowed) {
7063
- const index = parseNavIndexFromKey(hrefKey);
7064
- if (index === null) continue;
7065
- if (navbarIndexExistsInDom(index)) continue;
7066
- const href = content[`nav-${index}-href`];
7067
- const label = content[`nav-${index}-label`];
7068
- if (!href && !label) continue;
7069
- insertNavbarItemDom(index, href ?? "/", label ?? "Untitled", null);
7293
+ for (const node of orderForest) {
7294
+ const parentIndex = parseNavIndexFromKey(node.id);
7295
+ if (parentIndex === null) continue;
7296
+ if (!navbarIndexExistsInDom(parentIndex)) {
7297
+ const href = content[`nav-${parentIndex}-href`];
7298
+ const label = content[`nav-${parentIndex}-label`];
7299
+ if (!href && !label) continue;
7300
+ insertNavbarItemDom(parentIndex, href ?? "/", label ?? "Untitled", null);
7301
+ }
7302
+ if (node.children.length > 0) {
7303
+ const parentEl = document.querySelector(`[data-ohw-href-key="${CSS.escape(node.id)}"]`) ?? null;
7304
+ if (parentEl && isNavbarLinkItem(parentEl) && !isNestedNavChild(parentEl)) {
7305
+ ensureNavDropdownForParent(parentEl);
7306
+ }
7307
+ }
7308
+ for (const child of node.children) {
7309
+ const childIndex = parseNavIndexFromKey(child.id);
7310
+ if (childIndex === null) continue;
7311
+ if (navbarIndexExistsInDom(childIndex)) continue;
7312
+ const href = content[`nav-${childIndex}-href`];
7313
+ const label = content[`nav-${childIndex}-label`];
7314
+ if (!href && !label) continue;
7315
+ const parentEl = document.querySelector(`[data-ohw-href-key="${CSS.escape(node.id)}"]`) ?? null;
7316
+ if (parentEl && isNavbarLinkItem(parentEl)) {
7317
+ ensureNavDropdownForParent(parentEl);
7318
+ const group = parentEl.closest("[data-ohw-nav-group]");
7319
+ const childrenRoot = group?.querySelector(":scope > [data-ohw-nav-children]");
7320
+ if (childrenRoot) {
7321
+ const desktop = getNavbarDesktopContainer();
7322
+ const drawer = getNavbarDrawerContainer();
7323
+ for (const root of [desktop, drawer].filter((el) => Boolean(el))) {
7324
+ const trigger = findCounterpartByHrefKey(node.id, root);
7325
+ const rootChildren = trigger?.closest("[data-ohw-nav-group]")?.querySelector(":scope > [data-ohw-nav-children]");
7326
+ if (!rootChildren) continue;
7327
+ if (findCounterpartByHrefKey(child.id, root)) continue;
7328
+ const childAnchor = buildChildNavLink(
7329
+ childIndex,
7330
+ href ?? "/",
7331
+ label ?? "Untitled",
7332
+ rootChildren,
7333
+ trigger ?? null
7334
+ );
7335
+ insertChildLinkInChildrenRoot(rootChildren, childAnchor);
7336
+ }
7337
+ continue;
7338
+ }
7339
+ }
7340
+ insertNavbarItemDom(childIndex, href ?? "/", label ?? "Untitled", null);
7341
+ }
7070
7342
  }
7071
7343
  pruneNavbarItemsNotInOrder(allowed);
7072
7344
  applyNavForest(orderForest);
@@ -7099,7 +7371,7 @@ function pruneNavbarItemsNotInOrder(allowed) {
7099
7371
  }
7100
7372
  }
7101
7373
  function buildNavOrderAfterInsert(afterAnchor, newHrefKey) {
7102
- const order = getNavOrderFromDom();
7374
+ const order = getNavForestFromDom().map((n) => n.id);
7103
7375
  if (!afterAnchor) {
7104
7376
  if (!order.includes(newHrefKey)) order.push(newHrefKey);
7105
7377
  return order;
@@ -7109,8 +7381,18 @@ function buildNavOrderAfterInsert(afterAnchor, newHrefKey) {
7109
7381
  if (!order.includes(newHrefKey)) order.push(newHrefKey);
7110
7382
  return order;
7111
7383
  }
7384
+ let rootAfterKey = afterKey;
7385
+ if (isNestedNavChild(afterAnchor)) {
7386
+ const parent = getNavForestFromDom().find((n) => n.children.some((c) => c.id === afterKey));
7387
+ if (parent) rootAfterKey = parent.id;
7388
+ } else {
7389
+ const group = afterAnchor.closest("[data-ohw-nav-group]");
7390
+ const trigger = group?.querySelector(":scope > [data-ohw-href-key]");
7391
+ const triggerKey = trigger?.getAttribute("data-ohw-href-key");
7392
+ if (triggerKey) rootAfterKey = triggerKey;
7393
+ }
7112
7394
  const withoutNew = order.filter((key) => key !== newHrefKey);
7113
- const pos = withoutNew.indexOf(afterKey);
7395
+ const pos = withoutNew.indexOf(rootAfterKey);
7114
7396
  if (pos >= 0) {
7115
7397
  withoutNew.splice(pos + 1, 0, newHrefKey);
7116
7398
  return withoutNew;
@@ -7135,49 +7417,163 @@ function insertNavbarItem(href, label, afterAnchor = null) {
7135
7417
  order
7136
7418
  };
7137
7419
  }
7420
+ function getNavbarOrderJson() {
7421
+ return serializeNavOrder(getNavForestFromDom());
7422
+ }
7423
+ function allocateNavKeyRemap(hrefKeys) {
7424
+ let nextIndex = getNextNavbarIndex();
7425
+ const map = /* @__PURE__ */ new Map();
7426
+ for (const oldHrefKey of hrefKeys) {
7427
+ const index = nextIndex++;
7428
+ map.set(oldHrefKey, {
7429
+ index,
7430
+ hrefKey: `nav-${index}-href`,
7431
+ labelKey: `nav-${index}-label`
7432
+ });
7433
+ }
7434
+ return map;
7435
+ }
7436
+ function clearTransientNavAttrs(root) {
7437
+ const clear = (el) => {
7438
+ el.removeAttribute("data-ohw-selected");
7439
+ el.removeAttribute("data-ohw-hovered");
7440
+ el.removeAttribute("data-ohw-editing");
7441
+ el.removeAttribute("data-ohw-nav-force-open");
7442
+ el.removeAttribute("contenteditable");
7443
+ };
7444
+ clear(root);
7445
+ root.querySelectorAll(
7446
+ "[data-ohw-selected], [data-ohw-hovered], [data-ohw-editing], [data-ohw-nav-force-open], [contenteditable]"
7447
+ ).forEach(clear);
7448
+ }
7449
+ function remapNavKeysInSubtree(root, keyMap) {
7450
+ const remapAnchor = (el) => {
7451
+ const oldHrefKey = el.getAttribute("data-ohw-href-key");
7452
+ if (!oldHrefKey) return;
7453
+ const mapped = keyMap.get(oldHrefKey);
7454
+ if (!mapped) return;
7455
+ el.setAttribute("data-ohw-href-key", mapped.hrefKey);
7456
+ const labelEl = el.querySelector(':scope > [data-ohw-editable="text"][data-ohw-key]') ?? el.querySelector('[data-ohw-editable="text"][data-ohw-key]');
7457
+ if (labelEl) labelEl.setAttribute("data-ohw-key", mapped.labelKey);
7458
+ };
7459
+ if (root.matches("[data-ohw-href-key]")) remapAnchor(root);
7460
+ root.querySelectorAll("[data-ohw-href-key]").forEach(remapAnchor);
7461
+ }
7462
+ function readNavLinkSnapshot(hrefKey) {
7463
+ const el = findCounterpartByHrefKey(hrefKey, document) ?? document.querySelector(`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`);
7464
+ if (!el) return { href: "/", label: "Untitled" };
7465
+ const labelEl = el.querySelector('[data-ohw-editable="text"]');
7466
+ return {
7467
+ href: getLinkHref(el),
7468
+ label: (labelEl?.textContent ?? "").trim() || "Untitled"
7469
+ };
7470
+ }
7471
+ function findClonedNavAnchor(unit, hrefKey) {
7472
+ if (unit.getAttribute("data-ohw-href-key") === hrefKey && isNavbarLinkItem(unit)) return unit;
7473
+ return unit.querySelector(`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`) ?? null;
7474
+ }
7475
+ function duplicateNestedNavChild(sourceAnchor) {
7476
+ const sourceHrefKey = sourceAnchor.getAttribute("data-ohw-href-key");
7477
+ if (!sourceHrefKey || !isNavbarHrefKey(sourceHrefKey)) return null;
7478
+ const parentGroup = sourceAnchor.closest("[data-ohw-nav-group]");
7479
+ const parentTrigger = parentGroup?.querySelector(":scope > [data-ohw-href-key]");
7480
+ const parentHrefKey = parentTrigger?.getAttribute("data-ohw-href-key");
7481
+ if (!parentHrefKey || !isNavbarHrefKey(parentHrefKey)) return null;
7482
+ const snapshot = readNavLinkSnapshot(sourceHrefKey);
7483
+ const keyMap = allocateNavKeyRemap([sourceHrefKey]);
7484
+ const mapped = keyMap.get(sourceHrefKey);
7485
+ const containers = [getNavbarDesktopContainer(), getNavbarDrawerContainer()].filter(
7486
+ (el) => Boolean(el)
7487
+ );
7488
+ const searchRoots = containers.length > 0 ? containers : [document.body];
7489
+ let primary = null;
7490
+ for (const root of searchRoots) {
7491
+ const sourceEl = findCounterpartByHrefKey(sourceHrefKey, root);
7492
+ if (!sourceEl || !isNavbarLinkItem(sourceEl)) continue;
7493
+ const childrenRoot = sourceEl.closest("[data-ohw-nav-children]");
7494
+ if (!childrenRoot) continue;
7495
+ const clone = sourceEl.cloneNode(true);
7496
+ clearTransientNavAttrs(clone);
7497
+ remapNavKeysInSubtree(clone, keyMap);
7498
+ sourceEl.insertAdjacentElement("afterend", clone);
7499
+ if (!primary) primary = clone;
7500
+ }
7501
+ if (!primary) return null;
7502
+ const orderJson = serializeNavOrder(getNavForestFromDom());
7503
+ return {
7504
+ anchor: primary,
7505
+ index: mapped.index,
7506
+ hrefKey: mapped.hrefKey,
7507
+ labelKey: mapped.labelKey,
7508
+ href: snapshot.href,
7509
+ label: snapshot.label,
7510
+ order: flattenNavOrder(getNavForestFromDom()),
7511
+ childResults: [],
7512
+ orderJson
7513
+ };
7514
+ }
7138
7515
  function duplicateNavbarItem(sourceAnchor) {
7139
7516
  if (!isNavbarLinkItem(sourceAnchor)) return null;
7140
7517
  const sourceHrefKey = sourceAnchor.getAttribute("data-ohw-href-key");
7141
7518
  if (!sourceHrefKey || !isNavbarHrefKey(sourceHrefKey)) return null;
7142
- const href = getLinkHref(sourceAnchor);
7143
- const labelEl = sourceAnchor.querySelector('[data-ohw-editable="text"]');
7144
- const label = (labelEl?.textContent ?? "").trim() || "Untitled";
7519
+ if (isNestedNavChild(sourceAnchor)) {
7520
+ return duplicateNestedNavChild(sourceAnchor);
7521
+ }
7145
7522
  const forest = getNavForestFromDom();
7146
7523
  const sourceNode = forest.find((n) => n.id === sourceHrefKey);
7147
- const childIds = sourceNode?.children.map((c) => c.id) ?? [];
7148
- const primary = insertNavbarItem(href, label, sourceAnchor);
7149
- const childResults = [];
7150
- let after = primary.anchor;
7151
- for (const childId of childIds) {
7152
- const childEl = findCounterpartByHrefKey(childId, document) ?? document.querySelector(`[data-ohw-href-key="${CSS.escape(childId)}"]`);
7153
- if (!childEl || !isNavbarLinkItem(childEl)) continue;
7154
- const childHref = getLinkHref(childEl);
7155
- const childLabelEl = childEl.querySelector('[data-ohw-editable="text"]');
7156
- const childLabel = (childLabelEl?.textContent ?? "").trim() || "Untitled";
7157
- const inserted = insertNavbarItem(childHref, childLabel, after);
7158
- childResults.push(inserted);
7159
- after = inserted.anchor;
7160
- }
7161
- let orderJson;
7162
- if (childResults.length > 0) {
7163
- const nextForest = getNavForestFromDom();
7164
- const withoutNew = nextForest.filter(
7165
- (n) => n.id !== primary.hrefKey && !childResults.some((c) => c.hrefKey === n.id)
7166
- );
7167
- const sourceIdx = withoutNew.findIndex((n) => n.id === sourceHrefKey);
7168
- const insertAt = sourceIdx >= 0 ? sourceIdx + 1 : withoutNew.length;
7169
- withoutNew.splice(insertAt, 0, {
7170
- id: primary.hrefKey,
7171
- children: childResults.map((c) => ({ id: c.hrefKey, children: [] }))
7172
- });
7173
- applyNavForest(withoutNew);
7174
- orderJson = serializeNavOrder(withoutNew);
7175
- } else {
7176
- orderJson = serializeNavOrder(getNavForestFromDom());
7177
- }
7524
+ if (!sourceNode) return null;
7525
+ const hrefKeys = collectSubtreeHrefKeys(sourceNode);
7526
+ const keyMap = allocateNavKeyRemap(hrefKeys);
7527
+ const primaryMap = keyMap.get(sourceHrefKey);
7528
+ if (!primaryMap) return null;
7529
+ const primarySnapshot = readNavLinkSnapshot(sourceHrefKey);
7530
+ const childSnapshots = sourceNode.children.map((child) => ({
7531
+ oldKey: child.id,
7532
+ ...readNavLinkSnapshot(child.id)
7533
+ }));
7534
+ const containers = [getNavbarDesktopContainer(), getNavbarDrawerContainer()].filter(
7535
+ (el) => Boolean(el)
7536
+ );
7537
+ const searchRoots = containers.length > 0 ? containers : [document.body];
7538
+ let primaryAnchor = null;
7539
+ for (const root of searchRoots) {
7540
+ const sourceEl = findCounterpartByHrefKey(sourceHrefKey, root);
7541
+ if (!sourceEl || !isNavbarLinkItem(sourceEl)) continue;
7542
+ const sourceUnit = resolveNavRootUnit(sourceEl);
7543
+ if (!sourceUnit.parentElement) continue;
7544
+ const clone = sourceUnit.cloneNode(true);
7545
+ clearTransientNavAttrs(clone);
7546
+ remapNavKeysInSubtree(clone, keyMap);
7547
+ sourceUnit.insertAdjacentElement("afterend", clone);
7548
+ const clonedPrimary = findClonedNavAnchor(clone, primaryMap.hrefKey);
7549
+ if (!primaryAnchor && clonedPrimary && isNavbarLinkItem(clonedPrimary)) {
7550
+ primaryAnchor = clonedPrimary;
7551
+ }
7552
+ }
7553
+ if (!primaryAnchor) return null;
7554
+ const liveForest = getNavForestFromDom();
7555
+ applyNavForest(liveForest);
7556
+ const orderJson = serializeNavOrder(liveForest);
7557
+ const childResults = childSnapshots.map((child) => {
7558
+ const mapped = keyMap.get(child.oldKey);
7559
+ return {
7560
+ anchor: findCounterpartByHrefKey(mapped.hrefKey, document) ?? primaryAnchor,
7561
+ index: mapped.index,
7562
+ hrefKey: mapped.hrefKey,
7563
+ labelKey: mapped.labelKey,
7564
+ href: child.href,
7565
+ label: child.label,
7566
+ order: flattenNavOrder(liveForest)
7567
+ };
7568
+ });
7178
7569
  return {
7179
- ...primary,
7180
- order: flattenNavOrder(parseNavOrderJson(orderJson) ?? getNavForestFromDom()),
7570
+ anchor: primaryAnchor,
7571
+ index: primaryMap.index,
7572
+ hrefKey: primaryMap.hrefKey,
7573
+ labelKey: primaryMap.labelKey,
7574
+ href: primarySnapshot.href,
7575
+ label: primarySnapshot.label,
7576
+ order: flattenNavOrder(liveForest),
7181
7577
  childResults,
7182
7578
  orderJson
7183
7579
  };
@@ -7193,10 +7589,51 @@ function labelKeyFromHrefKey(hrefKey) {
7193
7589
  return hrefKey.replace(/-href$/, "-label");
7194
7590
  }
7195
7591
  function resolveRemovableNavUnit(anchor) {
7196
- if (anchor.closest("[data-ohw-nav-children]")) return anchor;
7197
- const group = anchor.closest("[data-ohw-nav-group]");
7198
- if (group?.querySelector(":scope > [data-ohw-nav-children]")) return group;
7199
- return anchor;
7592
+ return resolveNavRootUnit(anchor);
7593
+ }
7594
+ function collapseEmptyNavDropdownForParent(parentHrefKey) {
7595
+ const roots = [getNavbarDesktopContainer(), getNavbarDrawerContainer()].filter(
7596
+ (el) => Boolean(el)
7597
+ );
7598
+ const searchRoots = roots.length > 0 ? roots : [document.body];
7599
+ const collapsed = [];
7600
+ for (const root of searchRoots) {
7601
+ const trigger = findCounterpartByHrefKey(parentHrefKey, root);
7602
+ if (!trigger || !isNavbarLinkItem(trigger) || isNestedNavChild(trigger)) continue;
7603
+ const group = trigger.closest("[data-ohw-nav-group]");
7604
+ if (!group || group.hasAttribute("data-ohw-nav-dropdown-template")) continue;
7605
+ const childrenRoot = group.querySelector(":scope > [data-ohw-nav-children]");
7606
+ if (!childrenRoot) continue;
7607
+ const remaining = Array.from(
7608
+ childrenRoot.querySelectorAll(":scope > [data-ohw-href-key]")
7609
+ ).filter(isNavbarLinkItem);
7610
+ if (remaining.length > 0) continue;
7611
+ const container = group.parentElement;
7612
+ if (!container) continue;
7613
+ const caret = trigger.querySelector(
7614
+ "[data-ohw-nav-caret], .navbar__caret, .topnav__caret, .mobile-menu__caret"
7615
+ ) ?? null;
7616
+ collapsed.push({
7617
+ group,
7618
+ container,
7619
+ nextSibling: group.nextSibling,
7620
+ trigger,
7621
+ caret
7622
+ });
7623
+ group.removeAttribute("data-ohw-nav-force-open");
7624
+ container.insertBefore(trigger, group);
7625
+ caret?.remove();
7626
+ group.remove();
7627
+ }
7628
+ if (collapsed.length === 0) return null;
7629
+ return () => {
7630
+ for (const entry of collapsed) {
7631
+ entry.container.insertBefore(entry.group, entry.nextSibling);
7632
+ const childrenRoot = entry.group.querySelector(":scope > [data-ohw-nav-children]");
7633
+ entry.group.insertBefore(entry.trigger, childrenRoot);
7634
+ if (entry.caret) entry.trigger.appendChild(entry.caret);
7635
+ }
7636
+ };
7200
7637
  }
7201
7638
  function deleteNavbarItem(sourceAnchor) {
7202
7639
  if (!isNavbarLinkItem(sourceAnchor)) return null;
@@ -7206,6 +7643,7 @@ function deleteNavbarItem(sourceAnchor) {
7206
7643
  const label = (labelEl?.textContent ?? "").trim() || "Untitled";
7207
7644
  const previousForest = getNavForestFromDom();
7208
7645
  const previousOrderJson = serializeNavOrder(previousForest);
7646
+ const parentHrefKey = previousForest.find((n) => n.children.some((c) => c.id === sourceHrefKey))?.id ?? null;
7209
7647
  const taken = takeNode(previousForest, sourceHrefKey);
7210
7648
  if (!taken) return null;
7211
7649
  const removedHrefKeys = collectSubtreeHrefKeys(taken.taken);
@@ -7235,6 +7673,13 @@ function deleteNavbarItem(sourceAnchor) {
7235
7673
  unit.remove();
7236
7674
  }
7237
7675
  applyNavForest(taken.forest);
7676
+ let restoreCollapsedDropdown = null;
7677
+ if (parentHrefKey) {
7678
+ const parentNode = taken.forest.find((n) => n.id === parentHrefKey);
7679
+ if (parentNode && parentNode.children.length === 0) {
7680
+ restoreCollapsedDropdown = collapseEmptyNavDropdownForParent(parentHrefKey);
7681
+ }
7682
+ }
7238
7683
  const orderJson = serializeNavOrder(taken.forest);
7239
7684
  return {
7240
7685
  label,
@@ -7244,6 +7689,7 @@ function deleteNavbarItem(sourceAnchor) {
7244
7689
  orderJson,
7245
7690
  previousOrderJson,
7246
7691
  undo: () => {
7692
+ restoreCollapsedDropdown?.();
7247
7693
  for (const placement of placements) {
7248
7694
  placement.parent.insertBefore(placement.node, placement.nextSibling);
7249
7695
  }
@@ -8068,9 +8514,19 @@ var unlockFooterDragInteraction = unlockItemDragInteraction;
8068
8514
  function listReorderableNavItems() {
8069
8515
  return listNavbarItems().filter((el) => {
8070
8516
  const key = el.getAttribute("data-ohw-href-key");
8071
- return isNavbarHrefKey(key) && !el.closest("[data-ohw-nav-children]");
8517
+ return isNavbarHrefKey(key) && !isNestedNavChild(el);
8072
8518
  });
8073
8519
  }
8520
+ function resolveParentNavHrefKey(child) {
8521
+ const childrenRoot = child.closest("[data-ohw-nav-children]");
8522
+ const group = childrenRoot?.closest("[data-ohw-nav-group]");
8523
+ if (!group) return null;
8524
+ const trigger = group.querySelector(":scope > [data-ohw-href-key]") ?? Array.from(group.querySelectorAll("[data-ohw-href-key]")).find(
8525
+ (el) => !el.closest("[data-ohw-nav-children]")
8526
+ ) ?? null;
8527
+ const key = trigger?.getAttribute("data-ohw-href-key");
8528
+ return key && isNavbarHrefKey(key) ? key : null;
8529
+ }
8074
8530
  function listNavChildren(parentHrefKey) {
8075
8531
  const items = listNavbarItems();
8076
8532
  const parent = items.find((el) => el.getAttribute("data-ohw-href-key") === parentHrefKey);
@@ -8201,23 +8657,14 @@ function buildChildNavDropSlots(parentHrefKey) {
8201
8657
  return slots;
8202
8658
  }
8203
8659
  function buildAllNavDropSlots(draggedHrefKey) {
8204
- const slots = [...buildRootNavDropSlots()];
8205
- for (const item of listReorderableNavItems()) {
8206
- const key = item.getAttribute("data-ohw-href-key");
8207
- if (!key || key === draggedHrefKey) continue;
8208
- const group = item.closest("[data-ohw-nav-group]");
8209
- if (!group?.querySelector(":scope > [data-ohw-nav-children]")) continue;
8210
- slots.push(...buildChildNavDropSlots(key));
8211
- }
8212
8660
  const dragged = listNavbarItems().find((el) => el.getAttribute("data-ohw-href-key") === draggedHrefKey);
8213
- const parentGroup = dragged?.closest("[data-ohw-nav-children]")?.closest("[data-ohw-nav-group]");
8214
- const parentTrigger = parentGroup?.querySelector(":scope > [data-ohw-href-key]");
8215
- const parentKey = parentTrigger?.getAttribute("data-ohw-href-key");
8216
- if (parentKey && isNavbarHrefKey(parentKey)) {
8217
- const existing = slots.some((s) => s.parentId === parentKey);
8218
- if (!existing) slots.push(...buildChildNavDropSlots(parentKey));
8661
+ if (!dragged) return buildRootNavDropSlots();
8662
+ if (isNestedNavChild(dragged)) {
8663
+ const parentKey = resolveParentNavHrefKey(dragged);
8664
+ if (!parentKey) return [];
8665
+ return buildChildNavDropSlots(parentKey);
8219
8666
  }
8220
- return slots;
8667
+ return buildRootNavDropSlots();
8221
8668
  }
8222
8669
  function hitTestNavDropSlot(clientX, clientY, draggedHrefKey) {
8223
8670
  const slots = buildAllNavDropSlots(draggedHrefKey);
@@ -8268,6 +8715,8 @@ function useNavItemDrag({
8268
8715
  setDraggedItemRect(null);
8269
8716
  setSiblingHintRects([]);
8270
8717
  setIsItemDragging(false);
8718
+ setNavGroupForceOpen(null, false);
8719
+ document.documentElement.removeAttribute("data-ohw-nav-dragging-root");
8271
8720
  unlockItemDragInteraction();
8272
8721
  }, [setDraggedItemRect, setIsItemDragging, setSiblingHintRects]);
8273
8722
  const refreshNavDragVisuals = (0, import_react9.useCallback)(
@@ -8305,6 +8754,13 @@ function useNavItemDrag({
8305
8754
  lockItemDuringDrag();
8306
8755
  siblingHintElRef.current = null;
8307
8756
  setSiblingHintRect(null);
8757
+ if (session.draggedEl.closest("[data-ohw-nav-children]")) {
8758
+ document.documentElement.removeAttribute("data-ohw-nav-dragging-root");
8759
+ setNavGroupForceOpen(session.draggedEl, true);
8760
+ } else {
8761
+ document.documentElement.setAttribute("data-ohw-nav-dragging-root", "");
8762
+ setNavGroupForceOpen(null, false);
8763
+ }
8308
8764
  if (session.wasSelected && selectedElRef.current === session.draggedEl) {
8309
8765
  setToolbarRect(rect);
8310
8766
  }
@@ -9491,10 +9947,38 @@ function getHrefKeyFromElement(el) {
9491
9947
  function isNavbarButton2(el) {
9492
9948
  return Boolean(el.closest('[data-ohw-role="navbar-button"]'));
9493
9949
  }
9950
+ function isNavDropdownPanelOpen(childrenRoot) {
9951
+ if (childrenRoot.closest("[data-ohw-nav-drawer]")) return true;
9952
+ const group = childrenRoot.closest("[data-ohw-nav-group]");
9953
+ if (group?.hasAttribute("data-ohw-nav-force-open")) return true;
9954
+ if (childrenRoot.clientHeight < 2 || childrenRoot.clientWidth < 2) return false;
9955
+ const style = window.getComputedStyle(childrenRoot);
9956
+ if (style.display === "none" || style.visibility === "hidden") return false;
9957
+ if (style.pointerEvents === "none") return false;
9958
+ if (Number.parseFloat(style.opacity || "1") === 0) return false;
9959
+ if (typeof childrenRoot.checkVisibility === "function") {
9960
+ try {
9961
+ if (!childrenRoot.checkVisibility({
9962
+ checkOpacity: true,
9963
+ checkVisibilityCSS: true
9964
+ })) {
9965
+ return false;
9966
+ }
9967
+ } catch {
9968
+ }
9969
+ }
9970
+ return true;
9971
+ }
9972
+ function isNavItemPointerTarget(el) {
9973
+ const childrenRoot = el.closest("[data-ohw-nav-children]");
9974
+ if (!childrenRoot) return true;
9975
+ return isNavDropdownPanelOpen(childrenRoot);
9976
+ }
9494
9977
  function getNavigationItemAnchor(el) {
9495
9978
  const anchor = el.matches("[data-ohw-href-key]") ? el : el.closest("[data-ohw-href-key]");
9496
9979
  if (!anchor) return null;
9497
9980
  if (!anchor.querySelector('[data-ohw-editable="text"]')) return null;
9981
+ if (!isNavItemPointerTarget(anchor)) return null;
9498
9982
  return anchor;
9499
9983
  }
9500
9984
  function isNavigationItem2(el) {
@@ -9558,7 +10042,7 @@ function isInferredFooterGroup2(el) {
9558
10042
  return countFooterNavItems(el) >= 2;
9559
10043
  }
9560
10044
  function isNavigationContainer(el) {
9561
- return el.hasAttribute("data-ohw-nav-container") || isFooterLinksContainer(el) || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isNavigationRoot(el) || isInferredFooterGroup2(el);
10045
+ return el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el) || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isNavigationRoot(el) || isInferredFooterGroup2(el);
9562
10046
  }
9563
10047
  function isNavbarLinksContainer2(el) {
9564
10048
  return el.hasAttribute("data-ohw-nav-container");
@@ -9586,6 +10070,11 @@ function isPointOverNavigation(x, y) {
9586
10070
  const r2 = root.getBoundingClientRect();
9587
10071
  if (x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom) return true;
9588
10072
  }
10073
+ for (const panel of document.querySelectorAll("[data-ohw-nav-children]")) {
10074
+ if (!isNavDropdownPanelOpen(panel)) continue;
10075
+ const r2 = panel.getBoundingClientRect();
10076
+ if (x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom) return true;
10077
+ }
9589
10078
  return false;
9590
10079
  }
9591
10080
  function findHoveredNavOrFooterContainer(x, y) {
@@ -9604,6 +10093,7 @@ function findHoveredNavOrFooterContainer(x, y) {
9604
10093
  function isPointOverNavItem(container, x, y) {
9605
10094
  return Array.from(container.querySelectorAll("[data-ohw-href-key]")).some((el) => {
9606
10095
  if (!isNavigationItem2(el) || isNavbarButton2(el)) return false;
10096
+ if (!isNavItemPointerTarget(el)) return false;
9607
10097
  const itemRect = el.getBoundingClientRect();
9608
10098
  return x >= itemRect.left && x <= itemRect.right && y >= itemRect.top && y <= itemRect.bottom;
9609
10099
  });
@@ -9636,7 +10126,13 @@ function resolveNavContainerSelectionTarget(target, clientX, clientY) {
9636
10126
  }
9637
10127
  function getNavigationSelectionParent(el) {
9638
10128
  if (isNavigationItem2(el)) {
9639
- const explicit = el.closest("[data-ohw-nav-container]");
10129
+ const childrenRoot = el.closest("[data-ohw-nav-children]");
10130
+ if (childrenRoot) {
10131
+ const group = childrenRoot.closest("[data-ohw-nav-group]");
10132
+ const trigger = group?.querySelector(":scope > [data-ohw-href-key]");
10133
+ if (trigger && trigger !== el && isNavigationItem2(trigger)) return trigger;
10134
+ }
10135
+ const explicit = el.closest("[data-ohw-nav-container], [data-ohw-nav-drawer]");
9640
10136
  if (explicit) return explicit;
9641
10137
  const footerColumn = getFooterColumn(el);
9642
10138
  if (footerColumn) return footerColumn;
@@ -9647,7 +10143,7 @@ function getNavigationSelectionParent(el) {
9647
10143
  if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
9648
10144
  return getFooterLinksContainer();
9649
10145
  }
9650
- if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isFooterLinksContainer(el) || isInferredFooterGroup2(el)) {
10146
+ 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)) {
9651
10147
  return getNavigationRoot(el);
9652
10148
  }
9653
10149
  return null;
@@ -9658,11 +10154,23 @@ function collectNavigationItemSiblingHintRects(selected) {
9658
10154
  if (footerColumn) {
9659
10155
  return listFooterLinksInColumn(footerColumn).filter((link) => link !== selected).map((link) => link.getBoundingClientRect());
9660
10156
  }
10157
+ const childrenRoot = selected.closest("[data-ohw-nav-children]");
10158
+ if (childrenRoot) {
10159
+ return Array.from(childrenRoot.querySelectorAll(":scope > [data-ohw-href-key]")).filter((el) => isNavigationItem2(el) && el !== selected).map((el) => el.getBoundingClientRect());
10160
+ }
9661
10161
  const navContainer = selected.closest("[data-ohw-nav-container], [data-ohw-nav-drawer]");
9662
10162
  if (navContainer) {
9663
- return Array.from(navContainer.querySelectorAll("[data-ohw-href-key]")).filter((el) => isNavigationItem2(el) && el !== selected).map((el) => el.getBoundingClientRect());
10163
+ return Array.from(navContainer.children).flatMap((child) => {
10164
+ if (!(child instanceof HTMLElement)) return [];
10165
+ if (child.hasAttribute("data-ohw-nav-group")) {
10166
+ const trigger = child.querySelector(":scope > [data-ohw-href-key]");
10167
+ return trigger ? [trigger] : [];
10168
+ }
10169
+ if (child.matches("[data-ohw-href-key]")) return [child];
10170
+ return [];
10171
+ }).filter((el) => isNavigationItem2(el) && el !== selected).map((el) => el.getBoundingClientRect());
9664
10172
  }
9665
- return listNavigationItems().filter((el) => el !== selected).map((el) => el.getBoundingClientRect());
10173
+ return listNavigationItems().filter((el) => el !== selected && !el.closest("[data-ohw-nav-children]")).map((el) => el.getBoundingClientRect());
9666
10174
  }
9667
10175
  function placeCaretAtPoint(el, x, y) {
9668
10176
  const selection = window.getSelection();
@@ -10559,6 +11067,7 @@ function OhhwellsBridge() {
10559
11067
  el.removeAttribute("contenteditable");
10560
11068
  el.removeAttribute("data-ohw-editing");
10561
11069
  activeElRef.current = null;
11070
+ setNavGroupForceOpen(null, false);
10562
11071
  setReorderHrefKey(null);
10563
11072
  setReorderDragDisabled(false);
10564
11073
  if (!selectedElRef.current) {
@@ -10591,6 +11100,7 @@ function OhhwellsBridge() {
10591
11100
  hoveredNavContainerRef.current = null;
10592
11101
  setHoveredNavContainerRect(null);
10593
11102
  if (!activeElRef.current) {
11103
+ setNavGroupForceOpen(null, false);
10594
11104
  setToolbarRect(null);
10595
11105
  setToolbarVariant("none");
10596
11106
  }
@@ -10648,6 +11158,7 @@ function OhhwellsBridge() {
10648
11158
  selectedFooterColAttrRef.current = null;
10649
11159
  markSelected(navAnchor);
10650
11160
  setSelectedIsCta(isNavbarButton2(navAnchor));
11161
+ setNavGroupForceOpen(navAnchor, navItemOwnsDropdownPanel(navAnchor));
10651
11162
  const { key, disabled } = getNavigationItemReorderState(navAnchor);
10652
11163
  setReorderHrefKey(key);
10653
11164
  setReorderDragDisabled(disabled);
@@ -10685,7 +11196,7 @@ function OhhwellsBridge() {
10685
11196
  reselectNavigationItem(navAnchor);
10686
11197
  }, [postToParent2, reselectNavigationItem]);
10687
11198
  const handleAddTopLevelNavItem = (0, import_react11.useCallback)(() => {
10688
- const items = listNavbarItems();
11199
+ const items = listNavbarRootItems();
10689
11200
  addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
10690
11201
  deselectRef.current();
10691
11202
  deactivateRef.current();
@@ -10696,6 +11207,100 @@ function OhhwellsBridge() {
10696
11207
  intent: "add-nav"
10697
11208
  });
10698
11209
  }, []);
11210
+ const maybeWarnNavLinkDropdownConflict = (0, import_react11.useCallback)(
11211
+ (anchor) => {
11212
+ if (!isNavbarHrefKey(anchor.getAttribute("data-ohw-href-key"))) return;
11213
+ if (!navDropdownsOpenOnClick()) return;
11214
+ if (!navItemHasOwnUrl(anchor) || !navItemHasDropdownChildren(anchor)) return;
11215
+ postToParent2({
11216
+ type: "ow:toast",
11217
+ title: "This link won't work while it has dropdown items",
11218
+ toastType: "warning"
11219
+ });
11220
+ },
11221
+ [postToParent2]
11222
+ );
11223
+ const enterEditOnNewItem = (0, import_react11.useCallback)((anchor) => {
11224
+ const label = anchor.querySelector('[data-ohw-editable="text"]');
11225
+ if (!label) {
11226
+ selectRef.current(anchor);
11227
+ return;
11228
+ }
11229
+ setNavGroupForceOpen(anchor, true);
11230
+ activateRef.current(label);
11231
+ }, []);
11232
+ const handleAddChildItem = (0, import_react11.useCallback)(() => {
11233
+ const selected = selectedElRef.current;
11234
+ if (!selected) return;
11235
+ if (toolbarVariantRef.current === "select-frame" && isFooterFrameSelection) {
11236
+ if (!selected.hasAttribute("data-ohw-footer-col") && !selected.closest("[data-ohw-footer-col]")) {
11237
+ }
11238
+ const column = (selected.hasAttribute("data-ohw-footer-col") ? selected : null) ?? selected.closest("[data-ohw-footer-col]") ?? (listFooterColumns().includes(selected) ? selected : null);
11239
+ if (!column) return;
11240
+ const result2 = insertFooterItem(column, "/", "New link", null);
11241
+ applyLinkByKey(result2.hrefKey, result2.href);
11242
+ document.querySelectorAll(`[data-ohw-key="${result2.labelKey}"]`).forEach((el) => {
11243
+ el.textContent = result2.label;
11244
+ });
11245
+ const orderJson = JSON.stringify(result2.order);
11246
+ editContentRef.current = {
11247
+ ...editContentRef.current,
11248
+ [result2.hrefKey]: result2.href,
11249
+ [result2.labelKey]: result2.label,
11250
+ [FOOTER_ORDER_KEY]: orderJson
11251
+ };
11252
+ postToParent2({
11253
+ type: "ow:change",
11254
+ nodes: [
11255
+ { key: result2.hrefKey, text: result2.href },
11256
+ { key: result2.labelKey, text: result2.label },
11257
+ { key: FOOTER_ORDER_KEY, text: orderJson }
11258
+ ]
11259
+ });
11260
+ enforceLinkHrefs();
11261
+ requestAnimationFrame(() => {
11262
+ enterEditOnNewItem(result2.anchor);
11263
+ });
11264
+ return;
11265
+ }
11266
+ if (!isNavbarHrefKey(selected.getAttribute("data-ohw-href-key"))) return;
11267
+ if (isNestedNavChild(selected)) return;
11268
+ const hadUrl = navItemHasOwnUrl(selected);
11269
+ const result = addNavbarSubitem(selected);
11270
+ if (!result) return;
11271
+ applyLinkByKey(result.hrefKey, result.href);
11272
+ document.querySelectorAll(`[data-ohw-key="${result.labelKey}"]`).forEach((el) => {
11273
+ el.textContent = result.label;
11274
+ });
11275
+ const navCount = String(result.index + 1);
11276
+ editContentRef.current = {
11277
+ ...editContentRef.current,
11278
+ [result.hrefKey]: result.href,
11279
+ [result.labelKey]: result.label,
11280
+ [NAV_COUNT_KEY]: navCount,
11281
+ [NAV_ORDER_KEY]: result.orderJson
11282
+ };
11283
+ postToParent2({
11284
+ type: "ow:change",
11285
+ nodes: [
11286
+ { key: result.hrefKey, text: result.href },
11287
+ { key: result.labelKey, text: result.label },
11288
+ { key: NAV_COUNT_KEY, text: navCount },
11289
+ { key: NAV_ORDER_KEY, text: result.orderJson }
11290
+ ]
11291
+ });
11292
+ if (hadUrl) {
11293
+ maybeWarnNavLinkDropdownConflict(
11294
+ document.querySelector(
11295
+ `[data-ohw-href-key="${CSS.escape(result.parentHrefKey)}"]`
11296
+ ) ?? selected
11297
+ );
11298
+ }
11299
+ enforceLinkHrefs();
11300
+ requestAnimationFrame(() => {
11301
+ enterEditOnNewItem(result.anchor);
11302
+ });
11303
+ }, [enterEditOnNewItem, isFooterFrameSelection, maybeWarnNavLinkDropdownConflict, postToParent2]);
10699
11304
  const handleAddFooterColumn = (0, import_react11.useCallback)(() => {
10700
11305
  if (!canAddFooterColumn()) {
10701
11306
  postToParent2({
@@ -11021,6 +11626,7 @@ function OhhwellsBridge() {
11021
11626
  markSelected(anchor);
11022
11627
  setSelectedIsCta(isNavbarButton2(anchor));
11023
11628
  clearHrefKeyHover(anchor);
11629
+ setNavGroupForceOpen(anchor, navItemOwnsDropdownPanel(anchor));
11024
11630
  hoveredNavContainerRef.current = null;
11025
11631
  setHoveredNavContainerRect(null);
11026
11632
  setHoveredItemRect(null);
@@ -11048,6 +11654,7 @@ function OhhwellsBridge() {
11048
11654
  markSelected(el);
11049
11655
  setSelectedIsCta(false);
11050
11656
  clearHrefKeyHover(el);
11657
+ setNavGroupForceOpen(null, false);
11051
11658
  hoveredNavContainerRef.current = null;
11052
11659
  setHoveredNavContainerRect(null);
11053
11660
  setHoveredItemRect(null);
@@ -11115,9 +11722,11 @@ function OhhwellsBridge() {
11115
11722
  setToolbarShowEditLink(Boolean(getHrefKeyFromElement(el)));
11116
11723
  const navAnchor = getNavigationItemAnchor(el);
11117
11724
  if (navAnchor) {
11725
+ setNavGroupForceOpen(navAnchor, navItemOwnsDropdownPanel(navAnchor));
11118
11726
  setReorderHrefKey(null);
11119
11727
  setReorderDragDisabled(false);
11120
11728
  } else {
11729
+ setNavGroupForceOpen(null, false);
11121
11730
  const { key: reorderKey, disabled: reorderDisabled } = getReorderHandleState(el);
11122
11731
  setReorderHrefKey(reorderKey);
11123
11732
  setReorderDragDisabled(reorderDisabled);
@@ -11967,11 +12576,16 @@ function OhhwellsBridge() {
11967
12576
  if (!overContainer) continue;
11968
12577
  const navItemHit = Array.from(
11969
12578
  container.querySelectorAll("[data-ohw-href-key]")
11970
- ).find((el) => {
12579
+ ).filter((el) => {
11971
12580
  if (!isNavigationItem2(el) || isNavbarButton2(el)) return false;
12581
+ if (!isNavItemPointerTarget(el)) return false;
11972
12582
  const itemRect = el.getBoundingClientRect();
11973
12583
  return x >= itemRect.left && x <= itemRect.right && y >= itemRect.top && y <= itemRect.bottom;
11974
- });
12584
+ }).sort((a, b) => {
12585
+ const ar = a.getBoundingClientRect();
12586
+ const br = b.getBoundingClientRect();
12587
+ return ar.width * ar.height - br.width * br.height;
12588
+ })[0];
11975
12589
  if (navItemHit) {
11976
12590
  hoveredNavContainerRef.current = null;
11977
12591
  setHoveredNavContainerRect(null);
@@ -12127,6 +12741,7 @@ function OhhwellsBridge() {
12127
12741
  const textEditable = Array.from(
12128
12742
  document.querySelectorAll(NON_MEDIA_SELECTOR)
12129
12743
  ).find((el) => {
12744
+ if (el.closest("[data-ohw-nav-children]") && !getNavigationItemAnchor(el)) return false;
12130
12745
  const er = el.getBoundingClientRect();
12131
12746
  return x2 >= er.left && x2 <= er.right && y2 >= er.top && y2 <= er.bottom;
12132
12747
  });
@@ -12139,6 +12754,25 @@ function OhhwellsBridge() {
12139
12754
  imageShowTimerRef.current = null;
12140
12755
  }
12141
12756
  if (textEditable) {
12757
+ const navAnchor = getNavigationItemAnchor(textEditable);
12758
+ if (navAnchor && !textEditable.hasAttribute("contenteditable")) {
12759
+ if (hoveredImageRef.current) {
12760
+ hoveredImageRef.current = null;
12761
+ hoveredImageHasTextOverlapRef.current = false;
12762
+ resumeAnimTracks();
12763
+ clearImageHover();
12764
+ }
12765
+ document.querySelectorAll("[data-ohw-hovered]").forEach(
12766
+ (el) => el.removeAttribute("data-ohw-hovered")
12767
+ );
12768
+ const selected = selectedElRef.current;
12769
+ if (selected !== navAnchor && !selected?.contains(navAnchor)) {
12770
+ clearHrefKeyHover(navAnchor);
12771
+ hoveredItemElRef.current = navAnchor;
12772
+ setHoveredItemRect(navAnchor.getBoundingClientRect());
12773
+ }
12774
+ return;
12775
+ }
12142
12776
  if (textEditable.hasAttribute("contenteditable")) {
12143
12777
  if (hoveredImageRef.current) {
12144
12778
  hoveredImageRef.current = null;
@@ -12154,7 +12788,7 @@ function OhhwellsBridge() {
12154
12788
  showImageHover(imgEl, isDragOver, true);
12155
12789
  }
12156
12790
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
12157
- if (textEditable && !isInsideNavigationItem(textEditable)) {
12791
+ if (textEditable && !textEditable.closest("[data-ohw-href-key]")) {
12158
12792
  textEditable.setAttribute("data-ohw-hovered", "");
12159
12793
  }
12160
12794
  return;
@@ -12166,7 +12800,7 @@ function OhhwellsBridge() {
12166
12800
  clearImageHover();
12167
12801
  }
12168
12802
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
12169
- if (textEditable && !isInsideNavigationItem(textEditable)) {
12803
+ if (textEditable && !textEditable.closest("[data-ohw-href-key]")) {
12170
12804
  textEditable.setAttribute("data-ohw-hovered", "");
12171
12805
  }
12172
12806
  return;
@@ -12205,9 +12839,28 @@ function OhhwellsBridge() {
12205
12839
  clearImageHover();
12206
12840
  }
12207
12841
  const { x: x2, y: y2 } = toProbeCoords(clientX, clientY, fromParentViewport);
12842
+ const navLinkHit = Array.from(
12843
+ document.querySelectorAll("nav [data-ohw-href-key], footer [data-ohw-href-key]")
12844
+ ).find((el) => {
12845
+ if (!isNavigationItem2(el) || isNavbarButton2(el)) return false;
12846
+ if (!isNavItemPointerTarget(el)) return false;
12847
+ const er = el.getBoundingClientRect();
12848
+ return x2 >= er.left && x2 <= er.right && y2 >= er.top && y2 <= er.bottom;
12849
+ });
12850
+ if (navLinkHit) {
12851
+ document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
12852
+ const selected = selectedElRef.current;
12853
+ if (selected !== navLinkHit && !selected?.contains(navLinkHit)) {
12854
+ clearHrefKeyHover(navLinkHit);
12855
+ hoveredItemElRef.current = navLinkHit;
12856
+ setHoveredItemRect(navLinkHit.getBoundingClientRect());
12857
+ }
12858
+ return;
12859
+ }
12208
12860
  const textEl = Array.from(
12209
12861
  document.querySelectorAll(NON_MEDIA_SELECTOR)
12210
12862
  ).find((el) => {
12863
+ if (el.closest("[data-ohw-nav-children]") && !getNavigationItemAnchor(el)) return false;
12211
12864
  const er = el.getBoundingClientRect();
12212
12865
  return x2 >= er.left && x2 <= er.right && y2 >= er.top && y2 <= er.bottom;
12213
12866
  });
@@ -12221,10 +12874,13 @@ function OhhwellsBridge() {
12221
12874
  hoveredItemElRef.current = navAnchor;
12222
12875
  setHoveredItemRect(navAnchor.getBoundingClientRect());
12223
12876
  }
12224
- } else {
12877
+ } else if (!textEl.closest("[data-ohw-href-key]")) {
12225
12878
  hoveredItemElRef.current = null;
12226
12879
  setHoveredItemRect(null);
12227
12880
  textEl.setAttribute("data-ohw-hovered", "");
12881
+ } else {
12882
+ hoveredItemElRef.current = null;
12883
+ setHoveredItemRect(null);
12228
12884
  }
12229
12885
  } else {
12230
12886
  hoveredItemElRef.current = null;
@@ -12603,7 +13259,9 @@ function OhhwellsBridge() {
12603
13259
  return;
12604
13260
  }
12605
13261
  const parent = getNavigationSelectionParent(selectedElRef.current);
12606
- if (parent && isNavigationContainer(parent)) {
13262
+ if (parent && isNavigationItem2(parent)) {
13263
+ selectRef.current(parent);
13264
+ } else if (parent && isNavigationContainer(parent)) {
12607
13265
  selectFrameRef.current(parent);
12608
13266
  } else {
12609
13267
  deselectRef.current();
@@ -12636,7 +13294,10 @@ function OhhwellsBridge() {
12636
13294
  return;
12637
13295
  }
12638
13296
  const parent = getNavigationSelectionParent(selectedElRef.current);
12639
- if (parent && isNavigationContainer(parent)) {
13297
+ if (parent && isNavigationItem2(parent)) {
13298
+ e.preventDefault();
13299
+ selectRef.current(parent);
13300
+ } else if (parent && isNavigationContainer(parent)) {
12640
13301
  e.preventDefault();
12641
13302
  selectFrameRef.current(parent);
12642
13303
  } else {
@@ -13417,11 +14078,19 @@ function OhhwellsBridge() {
13417
14078
  return;
13418
14079
  }
13419
14080
  const parent = getNavigationSelectionParent(selected);
13420
- if (parent && isNavigationContainer(parent)) {
13421
- selectFrameRef.current(parent);
13422
- } else {
14081
+ if (!parent) {
13423
14082
  deselectRef.current();
14083
+ return;
14084
+ }
14085
+ if (isNavigationItem2(parent)) {
14086
+ selectRef.current(parent);
14087
+ return;
14088
+ }
14089
+ if (isNavigationContainer(parent)) {
14090
+ selectFrameRef.current(parent);
14091
+ return;
13424
14092
  }
14093
+ deselectRef.current();
13425
14094
  }, []);
13426
14095
  const handleDuplicateSelected = (0, import_react11.useCallback)(() => {
13427
14096
  const selected = selectedElRef.current;
@@ -13552,13 +14221,13 @@ function OhhwellsBridge() {
13552
14221
  href = trimmed;
13553
14222
  }
13554
14223
  const afterAnchor = addNavAfterAnchorRef.current;
13555
- const { anchor, hrefKey, labelKey, index, order } = insertNavbarItem(href, label, afterAnchor);
14224
+ const { anchor: anchor2, hrefKey, labelKey, index } = insertNavbarItem(href, label, afterAnchor);
13556
14225
  applyLinkByKey(hrefKey, href);
13557
14226
  document.querySelectorAll(`[data-ohw-key="${labelKey}"]`).forEach((el) => {
13558
14227
  el.textContent = label;
13559
14228
  });
13560
14229
  const navCount = String(index + 1);
13561
- const orderJson = JSON.stringify(order);
14230
+ const orderJson = getNavbarOrderJson();
13562
14231
  editContentRef.current = {
13563
14232
  ...editContentRef.current,
13564
14233
  [hrefKey]: href,
@@ -13580,16 +14249,22 @@ function OhhwellsBridge() {
13580
14249
  setLinkPopover(null);
13581
14250
  enforceLinkHrefs();
13582
14251
  requestAnimationFrame(() => {
13583
- selectRef.current(anchor);
14252
+ selectRef.current(anchor2);
13584
14253
  });
13585
14254
  return;
13586
14255
  }
13587
14256
  const { key } = session;
13588
14257
  applyLinkByKey(key, target);
14258
+ editContentRef.current = { ...editContentRef.current, [key]: target };
13589
14259
  postToParent2({ type: "ow:change", nodes: [{ key, text: target }] });
14260
+ const anchor = document.querySelector(`[data-ohw-href-key="${CSS.escape(key)}"]`) ?? null;
14261
+ if (target.trim()) {
14262
+ if (anchor) maybeWarnNavLinkDropdownConflict(anchor);
14263
+ postToParent2({ type: "ow:toast", title: "Link added", toastType: "success" });
14264
+ }
13590
14265
  setLinkPopover(null);
13591
14266
  },
13592
- [postToParent2, sitePages, sectionsByPath]
14267
+ [maybeWarnNavLinkDropdownConflict, postToParent2, sitePages, sectionsByPath]
13593
14268
  );
13594
14269
  const showEditLink = toolbarShowEditLink;
13595
14270
  const currentSections = sectionsByPath[pathname] ?? [];
@@ -13734,15 +14409,18 @@ function OhhwellsBridge() {
13734
14409
  ItemActionToolbar,
13735
14410
  {
13736
14411
  onEditLink: openLinkPopoverForSelected,
14412
+ onAddItem: handleAddChildItem,
13737
14413
  onSelectParent: handleSelectParent,
13738
14414
  onDuplicate: handleDuplicateSelected,
13739
14415
  onDelete: handleDeleteSelected,
13740
- addItemDisabled: true,
14416
+ addItemDisabled: false,
13741
14417
  editLinkDisabled: false,
13742
14418
  moreDisabled: false,
13743
14419
  duplicateDisabled: isFooterFrameSelection,
13744
14420
  showEditLink: !isFooterFrameSelection,
13745
- showAddItem: !selectedIsCta && !isFooterFrameSelection,
14421
+ showAddItem: isFooterFrameSelection || !selectedIsCta && Boolean(
14422
+ selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
14423
+ ),
13746
14424
  showMore: !selectedIsCta || isFooterFrameSelection
13747
14425
  }
13748
14426
  ) : void 0