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

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,106 @@ 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 = "block";
9121
+ if (textEl) textEl.style.display = "none";
9122
+ root.removeAttribute("data-ohw-placeholder");
9123
+ return;
9124
+ }
9125
+ if (img) {
9126
+ img.removeAttribute("src");
9127
+ img.removeAttribute("srcset");
9128
+ img.removeAttribute("sizes");
9129
+ img.alt = displayAlt;
9130
+ img.style.display = "none";
9131
+ }
9132
+ if (!textEl) {
9133
+ textEl = document.createElement("span");
9134
+ textEl.setAttribute("data-ohw-editable", "plain");
9135
+ textEl.setAttribute("data-ohw-key", textKey);
9136
+ root.appendChild(textEl);
9137
+ }
9138
+ textEl.style.display = "";
9139
+ if (textEl.textContent !== displayAlt) textEl.textContent = displayAlt;
9140
+ if (!displayAlt.trim() || displayAlt === PLACEHOLDER_BUSINESS_NAME) {
9141
+ root.setAttribute("data-ohw-placeholder", "");
9142
+ } else {
9143
+ root.removeAttribute("data-ohw-placeholder");
9144
+ }
9145
+ });
9146
+ }
9147
+ function applyLogoHref(href) {
9148
+ const target = href.trim() || "/";
9149
+ document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
9150
+ ensureLogoHrefKey(root);
9151
+ if (root instanceof HTMLAnchorElement) {
9152
+ root.setAttribute("href", target);
9153
+ }
9154
+ });
9155
+ }
9076
9156
  function readLogoIdentityFromDom() {
9157
+ let imageUrl = null;
9158
+ for (const key of LOGO_IMAGE_KEYS) {
9159
+ const el = document.querySelector(`[data-ohw-key="${key}"]`);
9160
+ const img = el instanceof HTMLImageElement ? el : el?.querySelector("img");
9161
+ const attrSrc = img?.getAttribute("src")?.trim() ?? "";
9162
+ if (attrSrc && !attrSrc.startsWith("data:") && img && img.style.display !== "none") {
9163
+ imageUrl = img.currentSrc || img.src;
9164
+ break;
9165
+ }
9166
+ }
9167
+ let text = PLACEHOLDER_BUSINESS_NAME;
9168
+ let isPlaceholder = true;
9077
9169
  for (const key of LOGO_TEXT_KEYS) {
9078
9170
  const el = document.querySelector(`[data-ohw-key="${key}"]`);
9079
9171
  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 };
9172
+ text = el.textContent.trim();
9173
+ const logoRoot2 = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
9174
+ isPlaceholder = logoRoot2?.hasAttribute("data-ohw-placeholder") === true || text === PLACEHOLDER_BUSINESS_NAME;
9175
+ break;
9084
9176
  }
9085
9177
  }
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 };
9178
+ if (imageUrl) {
9179
+ const logoImg = document.querySelector(
9180
+ '[data-ohw-key="nav-logo-image"], [data-ohw-key="footer-logo"]'
9181
+ );
9182
+ const alt = logoImg?.alt?.trim() || text;
9183
+ isPlaceholder = false;
9184
+ const hrefEl = document.querySelector(
9185
+ 'a[data-ohw-role="logo"], a[data-ohw-logo], [data-ohw-role="logo"]'
9186
+ );
9187
+ const href2 = (hrefEl instanceof HTMLAnchorElement ? hrefEl.getAttribute("href") : null) || hrefEl?.closest("a")?.getAttribute("href") || "/";
9188
+ return { text, isPlaceholder, imageUrl, href: href2, alt };
9094
9189
  }
9095
- return { text: PLACEHOLDER_BUSINESS_NAME, isPlaceholder: true };
9190
+ const logoRoot = document.querySelector('[data-ohw-role="logo"], [data-ohw-logo]');
9191
+ const href = (logoRoot instanceof HTMLAnchorElement ? logoRoot.getAttribute("href") : null) || logoRoot?.closest("a")?.getAttribute("href") || "/";
9192
+ return { text, isPlaceholder, imageUrl: null, href, alt: text };
9096
9193
  }
9097
9194
 
9098
9195
  // src/lib/site-wide-scope.ts
@@ -14075,6 +14172,7 @@ function OhhwellsBridge() {
14075
14172
  continue;
14076
14173
  }
14077
14174
  if (key === LOGO_PLACEHOLDER_KEY) continue;
14175
+ if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
14078
14176
  if (applyVideoSettingNode(key, val)) continue;
14079
14177
  if (applyCarouselNode(key, val)) continue;
14080
14178
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
@@ -14094,11 +14192,27 @@ function OhhwellsBridge() {
14094
14192
  });
14095
14193
  applyLinkByKey(key, val);
14096
14194
  }
14097
- const hasLogoIdentity = LOGO_PLACEHOLDER_KEY in content || LOGO_TEXT_KEYS.some((key) => key in content);
14195
+ 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
14196
  if (hasLogoIdentity) {
14099
14197
  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);
14198
+ const logoAlt = content[LOGO_ALT_KEY] ?? logoText;
14199
+ const rawLogoImage = content[LOGO_IMAGE_URL_KEY] ?? content["footer-logo"] ?? content["footer-logo-image"] ?? null;
14200
+ const logoImageUrl = typeof rawLogoImage === "string" && rawLogoImage.trim() ? rawLogoImage.trim() : null;
14201
+ const imageExplicitlyCleared = LOGO_IMAGE_KEYS.some((key) => key in content) && !logoImageUrl;
14202
+ const logoIsPlaceholder = LOGO_PLACEHOLDER_KEY in content ? content[LOGO_PLACEHOLDER_KEY] !== "false" : !logoImageUrl && (!logoText.trim() || logoText === PLACEHOLDER_BUSINESS_NAME);
14203
+ if (logoImageUrl) {
14204
+ applyLogoImage(logoImageUrl, logoAlt);
14205
+ } else {
14206
+ if (imageExplicitlyCleared) applyLogoImage(null, logoAlt);
14207
+ applyLogoIdentity(logoText, logoIsPlaceholder);
14208
+ }
14209
+ const logoHref = content["nav-logo-href"] ?? content["footer-logo-href"] ?? content["logo-href"];
14210
+ if (typeof logoHref === "string" && logoHref.trim()) {
14211
+ applyLogoHref(logoHref);
14212
+ applyLinkByKey("nav-logo-href", logoHref);
14213
+ applyLinkByKey("footer-logo-href", logoHref);
14214
+ applyLinkByKey("logo-href", logoHref);
14215
+ }
14102
14216
  }
14103
14217
  if (sectionsJson) {
14104
14218
  initSectionsFromContent({ __ohw_sections: sectionsJson }, true);
@@ -14115,12 +14229,48 @@ function OhhwellsBridge() {
14115
14229
  const handleUpdateLogoIdentity = (e) => {
14116
14230
  if (e.data?.type !== "ow:update-logo-identity") return;
14117
14231
  const rawText = typeof e.data.text === "string" ? e.data.text : "";
14118
- const isPlaceholder = e.data.isPlaceholder !== false;
14232
+ const alt = typeof e.data.alt === "string" ? e.data.alt : rawText;
14233
+ const href = typeof e.data.href === "string" ? e.data.href : void 0;
14234
+ const imageProvided = "image" in e.data;
14235
+ const imageUrl = imageProvided && typeof e.data.image === "string" && e.data.image.trim() ? e.data.image.trim() : imageProvided ? null : void 0;
14236
+ let isPlaceholder = e.data.isPlaceholder !== false;
14237
+ if (imageUrl) isPlaceholder = false;
14238
+ else if (imageProvided && imageUrl === null) {
14239
+ isPlaceholder = e.data.isPlaceholder === true || !rawText.trim() || resolveLogoDisplayText(rawText) === PLACEHOLDER_BUSINESS_NAME;
14240
+ }
14119
14241
  const display = applyLogoIdentity(rawText, isPlaceholder);
14242
+ const displayAlt = resolveLogoDisplayText(alt || display);
14243
+ if (imageUrl !== void 0) {
14244
+ applyLogoImage(imageUrl, displayAlt);
14245
+ } else {
14246
+ for (const key of LOGO_IMAGE_KEYS) {
14247
+ document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
14248
+ const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
14249
+ if (img) img.alt = displayAlt;
14250
+ });
14251
+ }
14252
+ }
14253
+ if (href !== void 0) {
14254
+ applyLogoHref(href);
14255
+ applyLinkByKey("nav-logo-href", href);
14256
+ applyLinkByKey("footer-logo-href", href);
14257
+ applyLinkByKey("logo-href", href);
14258
+ }
14120
14259
  const nodes = [
14121
14260
  ...LOGO_TEXT_KEYS.map((key) => ({ key, text: display })),
14122
- { key: LOGO_PLACEHOLDER_KEY, text: isPlaceholder || !rawText.trim() ? "true" : "false" }
14261
+ { key: LOGO_PLACEHOLDER_KEY, text: isPlaceholder ? "true" : "false" },
14262
+ { key: LOGO_ALT_KEY, text: displayAlt }
14123
14263
  ];
14264
+ if (imageUrl !== void 0) {
14265
+ if (imageUrl) {
14266
+ for (const key of LOGO_IMAGE_KEYS) nodes.push({ key, text: imageUrl });
14267
+ } else {
14268
+ for (const key of LOGO_IMAGE_KEYS) nodes.push({ key, text: "" });
14269
+ }
14270
+ }
14271
+ if (href !== void 0) {
14272
+ for (const key of LOGO_HREF_KEYS) nodes.push({ key, text: href.trim() || "/" });
14273
+ }
14124
14274
  editContentRef.current = {
14125
14275
  ...editContentRef.current,
14126
14276
  ...Object.fromEntries(nodes.map(({ key, text }) => [key, text]))