@ohhwells/bridge 0.1.82 → 0.1.84

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
@@ -256,6 +256,17 @@ var BRAND_VAR_PREFIX = "--ohw-brand-";
256
256
  var BRAND_VAR_NAMES = ["primary", "accent", "light", "dark", "surface", "border", "muted"].map(
257
257
  (role) => `${BRAND_VAR_PREFIX}${role}`
258
258
  );
259
+ var LEGACY_BRAND_VAR_NAMES = [
260
+ "primary",
261
+ "accent",
262
+ "background",
263
+ "text",
264
+ "text-muted",
265
+ "surface",
266
+ "border",
267
+ "on-primary",
268
+ "navbar-background"
269
+ ].map((role) => `--brand-${role}`);
259
270
  var FONT_VARS = {
260
271
  heading: ["--font-heading", "--font-display", "--brand-font-heading"],
261
272
  body: ["--font-body", "--brand-font-body"]
@@ -264,14 +275,29 @@ var BRAND_FONT_LINK_ID = "ohw-brand-fonts";
264
275
  function brandColorVars(kit) {
265
276
  const { dark, primary, accent, light } = kit.palette;
266
277
  const mix = (a, aPct, b) => `color-mix(in srgb, ${a} ${aPct}%, ${b})`;
278
+ const surface = mix(light, 95, dark);
279
+ const border = mix(light, 85, dark);
280
+ const muted = mix(dark, 62, light);
267
281
  return {
268
282
  [`${BRAND_VAR_PREFIX}primary`]: primary,
269
283
  [`${BRAND_VAR_PREFIX}accent`]: accent,
270
284
  [`${BRAND_VAR_PREFIX}light`]: light,
271
285
  [`${BRAND_VAR_PREFIX}dark`]: dark,
272
- [`${BRAND_VAR_PREFIX}surface`]: mix(light, 95, dark),
273
- [`${BRAND_VAR_PREFIX}border`]: mix(light, 85, dark),
274
- [`${BRAND_VAR_PREFIX}muted`]: mix(dark, 62, light)
286
+ [`${BRAND_VAR_PREFIX}surface`]: surface,
287
+ [`${BRAND_VAR_PREFIX}border`]: border,
288
+ [`${BRAND_VAR_PREFIX}muted`]: muted,
289
+ // The BrandProvider contract every template actually renders from (see LEGACY_BRAND_VAR_NAMES).
290
+ "--brand-primary": primary,
291
+ "--brand-accent": accent,
292
+ "--brand-background": light,
293
+ "--brand-text": dark,
294
+ "--brand-text-muted": muted,
295
+ "--brand-surface": surface,
296
+ "--brand-border": border,
297
+ // Buttons/bands painted in the primary colour assume it's dark/saturated enough to need
298
+ // light text on top — the same assumption LOGO_IMAGE's light-on-dark navbar mark makes.
299
+ "--brand-on-primary": light,
300
+ "--brand-navbar-background": dark
275
301
  };
276
302
  }
277
303
  function parseBrandKit(raw) {
@@ -312,7 +338,7 @@ function loadBrandFonts(families) {
312
338
  function applyBrandToDom(kit) {
313
339
  const root = document.documentElement;
314
340
  if (!kit) {
315
- for (const name of BRAND_VAR_NAMES) root.style.removeProperty(name);
341
+ for (const name of [...BRAND_VAR_NAMES, ...LEGACY_BRAND_VAR_NAMES]) root.style.removeProperty(name);
316
342
  for (const name of [...FONT_VARS.heading, ...FONT_VARS.body]) root.style.removeProperty(name);
317
343
  document.getElementById(BRAND_FONT_LINK_ID)?.remove();
318
344
  return;
@@ -409,7 +435,9 @@ var NODE_WROTE_ATTR = "data-ohw-style-node";
409
435
  var NODE_PROPS = ["color", "font-family", "font-size", "background"];
410
436
  function saveInline(el, prop) {
411
437
  const attr = `data-ohw-style-prev-${prop}`;
412
- if (!el.hasAttribute(attr)) el.setAttribute(attr, el.style.getPropertyValue(prop));
438
+ if (el.hasAttribute(attr)) return;
439
+ const value = el.style.getPropertyValue(prop) || (prop === "background" ? el.style.getPropertyValue("background-color") : "");
440
+ el.setAttribute(attr, value);
413
441
  }
414
442
  function restoreInline(el, prop) {
415
443
  const attr = `data-ohw-style-prev-${prop}`;
@@ -460,7 +488,8 @@ function applyStylesToDom(store) {
460
488
  const sections = document.querySelectorAll(
461
489
  `[data-ohw-section="${CSS.escape(sectionId)}"]`
462
490
  );
463
- for (const section of Array.from(sections)) {
491
+ for (const marker of Array.from(sections)) {
492
+ const section = marker.querySelector(":scope > [data-ai-section]") ?? marker;
464
493
  for (const [prop, attr] of Object.entries(SECTION_ATTRS)) {
465
494
  const value = override[prop];
466
495
  if (value === void 0) continue;
@@ -7429,6 +7458,9 @@ function applyFieldType(wrapper, type) {
7429
7458
  el.style.removeProperty("min-height");
7430
7459
  el.style.removeProperty("resize");
7431
7460
  el.removeAttribute("rows");
7461
+ if (el.className) {
7462
+ el.className = el.className.split(/\s+/).filter((token) => !/textarea/i.test(token)).join(" ");
7463
+ }
7432
7464
  };
7433
7465
  const applyDefaults = (el) => {
7434
7466
  el.setAttribute("placeholder", defaults.placeholder);
@@ -11679,7 +11711,7 @@ function applySocialsDisplayToRow(row, display) {
11679
11711
  const icon = item.querySelector(ICON_SELECTOR);
11680
11712
  if (label) label.style.display = display.text ? "" : "none";
11681
11713
  if (icon) icon.style.display = display.icon ? "" : "none";
11682
- layOutIconAndLabel(item, Boolean(display.text && display.icon));
11714
+ layOutIconAndLabel(item, Boolean(display.text));
11683
11715
  });
11684
11716
  allowRowToWrap(row);
11685
11717
  }
@@ -11691,6 +11723,9 @@ function layOutIconAndLabel(item, on) {
11691
11723
  item.style.gap = "";
11692
11724
  item.style.whiteSpace = "";
11693
11725
  item.style.flex = "";
11726
+ item.style.width = "";
11727
+ item.style.height = "";
11728
+ item.style.padding = "";
11694
11729
  return;
11695
11730
  }
11696
11731
  item.style.display = on ? "inline-flex" : "";
@@ -11698,6 +11733,9 @@ function layOutIconAndLabel(item, on) {
11698
11733
  item.style.gap = on ? "8px" : "";
11699
11734
  item.style.whiteSpace = on ? "nowrap" : "";
11700
11735
  item.style.flex = on ? "0 0 auto" : "";
11736
+ item.style.width = on ? "auto" : "";
11737
+ item.style.height = on ? "auto" : "";
11738
+ item.style.padding = on ? "0 12px" : "";
11701
11739
  }
11702
11740
  function allowRowToWrap(row) {
11703
11741
  const display = row.ownerDocument.defaultView?.getComputedStyle(row).display ?? "";
@@ -12653,6 +12691,15 @@ function resolveLogoDisplayText(text) {
12653
12691
  function isFooterLogoRoot(root) {
12654
12692
  return Boolean(root.closest("footer") || root.closest('[data-ohw-section="footer"]'));
12655
12693
  }
12694
+ var NAV_IMAGE_KEYS = ["nav-logo-image", "logo-image"];
12695
+ var FOOTER_IMAGE_KEYS = ["footer-logo", "footer-logo-image", "footer-logo-img"];
12696
+ function firstNonEmptyContentValue(content, keys) {
12697
+ for (const key of keys) {
12698
+ const value = content[key];
12699
+ if (typeof value === "string" && value.trim()) return value.trim();
12700
+ }
12701
+ return null;
12702
+ }
12656
12703
  function imageKeyForRoot(root) {
12657
12704
  return isFooterLogoRoot(root) ? "footer-logo" : "nav-logo-image";
12658
12705
  }
@@ -12702,9 +12749,10 @@ function applyLogoIdentity(text, isPlaceholder) {
12702
12749
  });
12703
12750
  return display;
12704
12751
  }
12705
- function applyLogoImage(url, alt) {
12752
+ function applyLogoImage(url, alt, placement) {
12706
12753
  const displayAlt = resolveLogoDisplayText(alt);
12707
12754
  document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
12755
+ if (placement && (isFooterLogoRoot(root) ? "footer" : "navbar") !== placement) return;
12708
12756
  ensureLogoHrefKey(root);
12709
12757
  const imageKey = imageKeyForRoot(root);
12710
12758
  const textKey = textKeyForRoot(root);
@@ -12825,7 +12873,12 @@ function applyLogoFromContent(content) {
12825
12873
  const logoImageUrl = typeof rawLogoImage === "string" && rawLogoImage.trim() ? rawLogoImage.trim() : null;
12826
12874
  const imageExplicitlyCleared = LOGO_IMAGE_KEYS.some((key) => key in content) && !logoImageUrl;
12827
12875
  const logoIsPlaceholder = LOGO_PLACEHOLDER_KEY in content ? content[LOGO_PLACEHOLDER_KEY] !== "false" : !logoImageUrl && (!logoText.trim() || logoText === PLACEHOLDER_BUSINESS_NAME);
12828
- if (logoImageUrl) {
12876
+ const navImageUrl = firstNonEmptyContentValue(content, NAV_IMAGE_KEYS);
12877
+ const footerImageUrl = firstNonEmptyContentValue(content, FOOTER_IMAGE_KEYS);
12878
+ if (navImageUrl && footerImageUrl && navImageUrl !== footerImageUrl) {
12879
+ applyLogoImage(navImageUrl, logoAlt, "navbar");
12880
+ applyLogoImage(footerImageUrl, logoAlt, "footer");
12881
+ } else if (logoImageUrl) {
12829
12882
  applyLogoImage(logoImageUrl, logoAlt);
12830
12883
  } else {
12831
12884
  if (imageExplicitlyCleared) applyLogoImage(null, logoAlt);
@@ -18202,6 +18255,8 @@ function OhhwellsBridge() {
18202
18255
  };
18203
18256
  const t1 = setTimeout(measure, 50);
18204
18257
  const t2 = setTimeout(measure, 500);
18258
+ const ro = new ResizeObserver(schedule);
18259
+ ro.observe(document.body);
18205
18260
  let lastWidth = window.innerWidth;
18206
18261
  let resizeTimers = [];
18207
18262
  const clearResizeTimers = () => {
@@ -18219,6 +18274,7 @@ function OhhwellsBridge() {
18219
18274
  clearTimeout(t1);
18220
18275
  clearTimeout(t2);
18221
18276
  if (raf != null) cancelAnimationFrame(raf);
18277
+ ro.disconnect();
18222
18278
  clearResizeTimers();
18223
18279
  window.removeEventListener("resize", handleResize);
18224
18280
  };
@@ -21091,7 +21147,7 @@ function OhhwellsBridge() {
21091
21147
  postToParent2({
21092
21148
  type: "ow:ready",
21093
21149
  version: "1",
21094
- bridgeVersion: "0.1.81",
21150
+ bridgeVersion: "0.1.83",
21095
21151
  path: pathname,
21096
21152
  nodes: collectEditableNodes(editContentRef.current),
21097
21153
  sections