@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 +793 -115
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +793 -115
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
|
6890
|
-
afterEl
|
|
6891
|
-
|
|
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,
|
|
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
|
|
6930
|
-
|
|
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
|
|
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
|
-
|
|
6940
|
-
|
|
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
|
|
6949
|
-
if (
|
|
6980
|
+
const match = units.find((u) => u.key === hrefKey);
|
|
6981
|
+
if (match) orderedUnits.push(match.unit);
|
|
6950
6982
|
}
|
|
6951
|
-
for (const
|
|
6952
|
-
if (
|
|
6953
|
-
|
|
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
|
|
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
|
|
7063
|
-
const
|
|
7064
|
-
if (
|
|
7065
|
-
if (navbarIndexExistsInDom(
|
|
7066
|
-
|
|
7067
|
-
|
|
7068
|
-
|
|
7069
|
-
|
|
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 =
|
|
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(
|
|
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
|
-
|
|
7143
|
-
|
|
7144
|
-
|
|
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
|
-
|
|
7148
|
-
const
|
|
7149
|
-
const
|
|
7150
|
-
|
|
7151
|
-
|
|
7152
|
-
|
|
7153
|
-
|
|
7154
|
-
|
|
7155
|
-
|
|
7156
|
-
|
|
7157
|
-
|
|
7158
|
-
|
|
7159
|
-
|
|
7160
|
-
|
|
7161
|
-
let
|
|
7162
|
-
|
|
7163
|
-
const
|
|
7164
|
-
|
|
7165
|
-
|
|
7166
|
-
);
|
|
7167
|
-
const
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
|
-
|
|
7175
|
-
}
|
|
7176
|
-
|
|
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
|
-
|
|
7180
|
-
|
|
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
|
-
|
|
7197
|
-
|
|
7198
|
-
|
|
7199
|
-
|
|
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
|
|
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
|
-
|
|
8214
|
-
|
|
8215
|
-
|
|
8216
|
-
|
|
8217
|
-
|
|
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
|
|
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
|
|
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.
|
|
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 =
|
|
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
|
-
).
|
|
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 && !
|
|
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 && !
|
|
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 &&
|
|
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 &&
|
|
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
|
|
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
|
|
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 =
|
|
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(
|
|
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:
|
|
14416
|
+
addItemDisabled: false,
|
|
13741
14417
|
editLinkDisabled: false,
|
|
13742
14418
|
moreDisabled: false,
|
|
13743
14419
|
duplicateDisabled: isFooterFrameSelection,
|
|
13744
14420
|
showEditLink: !isFooterFrameSelection,
|
|
13745
|
-
showAddItem: !selectedIsCta &&
|
|
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
|