@ohhwells/bridge 0.1.52-next.134 → 0.1.52-next.137

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
@@ -9047,12 +9047,29 @@ function deleteFooterColumn(column) {
9047
9047
  // src/lib/logo-identity.ts
9048
9048
  var LOGO_TEXT_KEYS = ["nav-logo-text", "footer-logo-text", "logo-text"];
9049
9049
  var LOGO_IMAGE_KEYS = ["nav-logo-image", "footer-logo", "footer-logo-image"];
9050
+ var LOGO_HREF_KEYS = ["nav-logo-href", "footer-logo-href", "logo-href"];
9050
9051
  var LOGO_PLACEHOLDER_KEY = "logo-is-placeholder";
9052
+ var LOGO_ALT_KEY = "logo-alt";
9053
+ var LOGO_IMAGE_URL_KEY = "nav-logo-image";
9051
9054
  var PLACEHOLDER_BUSINESS_NAME = "Business name";
9052
9055
  function resolveLogoDisplayText(text) {
9053
9056
  const trimmed = (text ?? "").trim();
9054
9057
  return trimmed || PLACEHOLDER_BUSINESS_NAME;
9055
9058
  }
9059
+ function isFooterLogoRoot(root) {
9060
+ return Boolean(root.closest("footer") || root.closest('[data-ohw-section="footer"]'));
9061
+ }
9062
+ function imageKeyForRoot(root) {
9063
+ return isFooterLogoRoot(root) ? "footer-logo" : "nav-logo-image";
9064
+ }
9065
+ function textKeyForRoot(root) {
9066
+ return isFooterLogoRoot(root) ? "footer-logo-text" : "nav-logo-text";
9067
+ }
9068
+ function ensureLogoHrefKey(root) {
9069
+ if (!(root instanceof HTMLAnchorElement)) return;
9070
+ if (root.hasAttribute("data-ohw-href-key")) return;
9071
+ root.setAttribute("data-ohw-href-key", isFooterLogoRoot(root) ? "footer-logo-href" : "nav-logo-href");
9072
+ }
9056
9073
  function applyLogoIdentity(text, isPlaceholder) {
9057
9074
  const display = resolveLogoDisplayText(text);
9058
9075
  const placeholder = isPlaceholder || !text.trim() || display === PLACEHOLDER_BUSINESS_NAME;
@@ -9073,26 +9090,101 @@ function applyLogoIdentity(text, isPlaceholder) {
9073
9090
  });
9074
9091
  return display;
9075
9092
  }
9093
+ function applyLogoImage(url, alt) {
9094
+ const displayAlt = resolveLogoDisplayText(alt);
9095
+ document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
9096
+ ensureLogoHrefKey(root);
9097
+ const imageKey = imageKeyForRoot(root);
9098
+ const textKey = textKeyForRoot(root);
9099
+ let img = root.querySelector(`img[data-ohw-key="${imageKey}"]`) ?? (root.querySelector(`[data-ohw-key="${imageKey}"]`) instanceof HTMLImageElement ? root.querySelector(`[data-ohw-key="${imageKey}"]`) : null) ?? root.querySelector("img");
9100
+ let textEl = root.querySelector(`[data-ohw-key="${textKey}"]`) ?? root.querySelector('[data-ohw-key="logo-text"]');
9101
+ if (url) {
9102
+ if (!img) {
9103
+ img = document.createElement("img");
9104
+ img.setAttribute("data-ohw-editable", "image");
9105
+ img.setAttribute("data-ohw-key", imageKey);
9106
+ img.alt = displayAlt;
9107
+ img.style.maxHeight = "40px";
9108
+ img.style.width = "auto";
9109
+ img.style.display = "block";
9110
+ img.style.objectFit = "contain";
9111
+ root.insertBefore(img, root.firstChild);
9112
+ } else {
9113
+ img.setAttribute("data-ohw-editable", "image");
9114
+ img.setAttribute("data-ohw-key", imageKey);
9115
+ }
9116
+ img.removeAttribute("srcset");
9117
+ img.removeAttribute("sizes");
9118
+ img.src = url;
9119
+ img.alt = displayAlt;
9120
+ img.style.display = "";
9121
+ if (textEl) textEl.style.display = "none";
9122
+ root.removeAttribute("data-ohw-placeholder");
9123
+ return;
9124
+ }
9125
+ if (img) {
9126
+ img.remove();
9127
+ }
9128
+ if (!textEl) {
9129
+ textEl = document.createElement("span");
9130
+ textEl.setAttribute("data-ohw-editable", "plain");
9131
+ textEl.setAttribute("data-ohw-key", textKey);
9132
+ root.appendChild(textEl);
9133
+ }
9134
+ textEl.style.display = "";
9135
+ if (textEl.textContent !== displayAlt) textEl.textContent = displayAlt;
9136
+ if (!displayAlt.trim() || displayAlt === PLACEHOLDER_BUSINESS_NAME) {
9137
+ root.setAttribute("data-ohw-placeholder", "");
9138
+ } else {
9139
+ root.removeAttribute("data-ohw-placeholder");
9140
+ }
9141
+ });
9142
+ }
9143
+ function applyLogoHref(href) {
9144
+ const target = href.trim() || "/";
9145
+ document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
9146
+ ensureLogoHrefKey(root);
9147
+ if (root instanceof HTMLAnchorElement) {
9148
+ root.setAttribute("href", target);
9149
+ }
9150
+ });
9151
+ }
9076
9152
  function readLogoIdentityFromDom() {
9153
+ let imageUrl = null;
9154
+ for (const key of LOGO_IMAGE_KEYS) {
9155
+ const el = document.querySelector(`[data-ohw-key="${key}"]`);
9156
+ const img = el instanceof HTMLImageElement ? el : el?.querySelector("img");
9157
+ if (img?.src && !img.src.startsWith("data:") && img.style.display !== "none") {
9158
+ imageUrl = img.currentSrc || img.src;
9159
+ break;
9160
+ }
9161
+ }
9162
+ let text = PLACEHOLDER_BUSINESS_NAME;
9163
+ let isPlaceholder = true;
9077
9164
  for (const key of LOGO_TEXT_KEYS) {
9078
9165
  const el = document.querySelector(`[data-ohw-key="${key}"]`);
9079
9166
  if (el?.textContent?.trim()) {
9080
- const text = el.textContent.trim();
9081
- const logoRoot = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
9082
- const isPlaceholder = logoRoot?.hasAttribute("data-ohw-placeholder") === true || text === PLACEHOLDER_BUSINESS_NAME;
9083
- return { text, isPlaceholder };
9167
+ text = el.textContent.trim();
9168
+ const logoRoot2 = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
9169
+ isPlaceholder = logoRoot2?.hasAttribute("data-ohw-placeholder") === true || text === PLACEHOLDER_BUSINESS_NAME;
9170
+ break;
9084
9171
  }
9085
9172
  }
9086
- const logoImg = document.querySelector(
9087
- '[data-ohw-key="nav-logo-image"], [data-ohw-key="footer-logo"]'
9088
- );
9089
- if (logoImg?.alt?.trim()) {
9090
- const text = logoImg.alt.trim();
9091
- const logoRoot = logoImg.closest('[data-ohw-role="logo"], [data-ohw-logo]');
9092
- const isPlaceholder = logoRoot?.hasAttribute("data-ohw-placeholder") === true || text === PLACEHOLDER_BUSINESS_NAME;
9093
- return { text, isPlaceholder };
9173
+ if (imageUrl) {
9174
+ const logoImg = document.querySelector(
9175
+ '[data-ohw-key="nav-logo-image"], [data-ohw-key="footer-logo"]'
9176
+ );
9177
+ const alt = logoImg?.alt?.trim() || text;
9178
+ isPlaceholder = false;
9179
+ const hrefEl = document.querySelector(
9180
+ 'a[data-ohw-role="logo"], a[data-ohw-logo], [data-ohw-role="logo"]'
9181
+ );
9182
+ const href2 = (hrefEl instanceof HTMLAnchorElement ? hrefEl.getAttribute("href") : null) || hrefEl?.closest("a")?.getAttribute("href") || "/";
9183
+ return { text, isPlaceholder, imageUrl, href: href2, alt };
9094
9184
  }
9095
- return { text: PLACEHOLDER_BUSINESS_NAME, isPlaceholder: true };
9185
+ const logoRoot = document.querySelector('[data-ohw-role="logo"], [data-ohw-logo]');
9186
+ const href = (logoRoot instanceof HTMLAnchorElement ? logoRoot.getAttribute("href") : null) || logoRoot?.closest("a")?.getAttribute("href") || "/";
9187
+ return { text, isPlaceholder, imageUrl: null, href, alt: text };
9096
9188
  }
9097
9189
 
9098
9190
  // src/lib/site-wide-scope.ts
@@ -14075,6 +14167,7 @@ function OhhwellsBridge() {
14075
14167
  continue;
14076
14168
  }
14077
14169
  if (key === LOGO_PLACEHOLDER_KEY) continue;
14170
+ if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
14078
14171
  if (applyVideoSettingNode(key, val)) continue;
14079
14172
  if (applyCarouselNode(key, val)) continue;
14080
14173
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -14094,11 +14187,27 @@ function OhhwellsBridge() {
14094
14187
  });
14095
14188
  applyLinkByKey(key, val);
14096
14189
  }
14097
- const hasLogoIdentity = LOGO_PLACEHOLDER_KEY in content || LOGO_TEXT_KEYS.some((key) => key in content);
14190
+ const hasLogoIdentity = LOGO_PLACEHOLDER_KEY in content || LOGO_TEXT_KEYS.some((key) => key in content) || LOGO_IMAGE_KEYS.some((key) => key in content) || LOGO_ALT_KEY in content || LOGO_HREF_KEYS.some((key) => key in content);
14098
14191
  if (hasLogoIdentity) {
14099
14192
  const logoText = content[LOGO_TEXT_KEYS[0]] ?? content[LOGO_TEXT_KEYS[1]] ?? readLogoIdentityFromDom().text;
14100
- const logoIsPlaceholder = LOGO_PLACEHOLDER_KEY in content ? content[LOGO_PLACEHOLDER_KEY] !== "false" : !logoText.trim() || logoText === PLACEHOLDER_BUSINESS_NAME;
14101
- applyLogoIdentity(logoText, logoIsPlaceholder);
14193
+ const logoAlt = content[LOGO_ALT_KEY] ?? logoText;
14194
+ const rawLogoImage = content[LOGO_IMAGE_URL_KEY] ?? content["footer-logo"] ?? content["footer-logo-image"] ?? null;
14195
+ const logoImageUrl = typeof rawLogoImage === "string" && rawLogoImage.trim() ? rawLogoImage.trim() : null;
14196
+ const imageExplicitlyCleared = LOGO_IMAGE_KEYS.some((key) => key in content) && !logoImageUrl;
14197
+ const logoIsPlaceholder = LOGO_PLACEHOLDER_KEY in content ? content[LOGO_PLACEHOLDER_KEY] !== "false" : !logoImageUrl && (!logoText.trim() || logoText === PLACEHOLDER_BUSINESS_NAME);
14198
+ if (logoImageUrl) {
14199
+ applyLogoImage(logoImageUrl, logoAlt);
14200
+ } else {
14201
+ if (imageExplicitlyCleared) applyLogoImage(null, logoAlt);
14202
+ applyLogoIdentity(logoText, logoIsPlaceholder);
14203
+ }
14204
+ const logoHref = content["nav-logo-href"] ?? content["footer-logo-href"] ?? content["logo-href"];
14205
+ if (typeof logoHref === "string" && logoHref.trim()) {
14206
+ applyLogoHref(logoHref);
14207
+ applyLinkByKey("nav-logo-href", logoHref);
14208
+ applyLinkByKey("footer-logo-href", logoHref);
14209
+ applyLinkByKey("logo-href", logoHref);
14210
+ }
14102
14211
  }
14103
14212
  if (sectionsJson) {
14104
14213
  initSectionsFromContent({ __ohw_sections: sectionsJson }, true);
@@ -14115,12 +14224,48 @@ function OhhwellsBridge() {
14115
14224
  const handleUpdateLogoIdentity = (e) => {
14116
14225
  if (e.data?.type !== "ow:update-logo-identity") return;
14117
14226
  const rawText = typeof e.data.text === "string" ? e.data.text : "";
14118
- const isPlaceholder = e.data.isPlaceholder !== false;
14227
+ const alt = typeof e.data.alt === "string" ? e.data.alt : rawText;
14228
+ const href = typeof e.data.href === "string" ? e.data.href : void 0;
14229
+ const imageProvided = "image" in e.data;
14230
+ const imageUrl = imageProvided && typeof e.data.image === "string" && e.data.image.trim() ? e.data.image.trim() : imageProvided ? null : void 0;
14231
+ let isPlaceholder = e.data.isPlaceholder !== false;
14232
+ if (imageUrl) isPlaceholder = false;
14233
+ else if (imageProvided && imageUrl === null) {
14234
+ isPlaceholder = e.data.isPlaceholder === true || !rawText.trim() || resolveLogoDisplayText(rawText) === PLACEHOLDER_BUSINESS_NAME;
14235
+ }
14119
14236
  const display = applyLogoIdentity(rawText, isPlaceholder);
14237
+ const displayAlt = resolveLogoDisplayText(alt || display);
14238
+ if (imageUrl !== void 0) {
14239
+ applyLogoImage(imageUrl, displayAlt);
14240
+ } else {
14241
+ for (const key of LOGO_IMAGE_KEYS) {
14242
+ document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
14243
+ const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
14244
+ if (img) img.alt = displayAlt;
14245
+ });
14246
+ }
14247
+ }
14248
+ if (href !== void 0) {
14249
+ applyLogoHref(href);
14250
+ applyLinkByKey("nav-logo-href", href);
14251
+ applyLinkByKey("footer-logo-href", href);
14252
+ applyLinkByKey("logo-href", href);
14253
+ }
14120
14254
  const nodes = [
14121
14255
  ...LOGO_TEXT_KEYS.map((key) => ({ key, text: display })),
14122
- { key: LOGO_PLACEHOLDER_KEY, text: isPlaceholder || !rawText.trim() ? "true" : "false" }
14256
+ { key: LOGO_PLACEHOLDER_KEY, text: isPlaceholder ? "true" : "false" },
14257
+ { key: LOGO_ALT_KEY, text: displayAlt }
14123
14258
  ];
14259
+ if (imageUrl !== void 0) {
14260
+ if (imageUrl) {
14261
+ for (const key of LOGO_IMAGE_KEYS) nodes.push({ key, text: imageUrl });
14262
+ } else {
14263
+ for (const key of LOGO_IMAGE_KEYS) nodes.push({ key, text: "" });
14264
+ }
14265
+ }
14266
+ if (href !== void 0) {
14267
+ for (const key of LOGO_HREF_KEYS) nodes.push({ key, text: href.trim() || "/" });
14268
+ }
14124
14269
  editContentRef.current = {
14125
14270
  ...editContentRef.current,
14126
14271
  ...Object.fromEntries(nodes.map(({ key, text }) => [key, text]))