@ohhwells/bridge 0.1.129 → 0.1.130

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.js CHANGED
@@ -1814,6 +1814,29 @@ var typeStyle = (spec, font) => ({
1814
1814
  lineHeight: spec.line,
1815
1815
  fontWeight: spec.weight
1816
1816
  });
1817
+ function quotedFont(font) {
1818
+ const cleaned = font.replace(/["']/g, "").trim();
1819
+ return cleaned ? `"${cleaned}"` : "sans-serif";
1820
+ }
1821
+ function footerLogoStyle(fallbackFont, fallbackColor) {
1822
+ return {
1823
+ fontFamily: `var(--brand-font-heading, var(--font-heading, var(--font-display, ${quotedFont(fallbackFont)})))`,
1824
+ fontSize: "var(--text-h3, 1.75rem)",
1825
+ lineHeight: "var(--text-h3--line-height, 1.2)",
1826
+ letterSpacing: "-0.02em",
1827
+ fontWeight: 400,
1828
+ color: `var(--brand-primary, ${fallbackColor})`
1829
+ };
1830
+ }
1831
+ function footerBodyStyle(fallbackFont, color, weight = 500) {
1832
+ return {
1833
+ fontFamily: `var(--brand-font-body, var(--font-body, ${quotedFont(fallbackFont)}))`,
1834
+ fontSize: "var(--text-body-md, 16px)",
1835
+ lineHeight: 1.5,
1836
+ fontWeight: weight,
1837
+ color
1838
+ };
1839
+ }
1817
1840
  var str = (value) => typeof value === "string" ? value : "";
1818
1841
  var cardRadius = (slots) => slots.cornerStyle === "sharp" ? 0 : AI_TREE_TOKENS.radiusCard;
1819
1842
  var featureLines = (value) => value.split(/\n|<br\s*\/?>/i).map((line) => line.trim()).filter(Boolean);
@@ -1837,7 +1860,9 @@ var AI_FOOTER_MOBILE_CSS = [
1837
1860
  "@media (max-width: 768px){",
1838
1861
  "[data-ai-footer]{overflow-x:hidden}",
1839
1862
  "[data-ai-footer-top]{display:flex !important;flex-direction:column !important;gap:32px !important}",
1840
- "[data-ai-footer-brand],[data-ohw-footer-links]{width:100%;min-width:0}",
1863
+ // Column flex-basis (420px / 220px) is height once the row stacks — drop it so
1864
+ // the column is only as tall as its links.
1865
+ "[data-ai-footer-brand],[data-ohw-footer-links],[data-ai-footer-col]{flex:0 1 auto !important;width:100%;min-width:0}",
1841
1866
  "[data-ohw-footer-links]{display:flex !important;flex-direction:column !important;gap:24px !important}",
1842
1867
  "[data-ai-footer] img{max-width:100%}",
1843
1868
  "}"
@@ -3228,7 +3253,7 @@ function FooterLinkListBlock({
3228
3253
  "p",
3229
3254
  {
3230
3255
  ...textAttrs(ctx, `${path}.title`),
3231
- style: { ...typeStyle(AI_TREE_TOKENS.type.bodyMBold, ctx.brand.fonts.body), margin: 0, color: ctx.brand.palette.dark },
3256
+ style: { ...footerBodyStyle(ctx.brand.fonts.body, `var(--surface-fg, ${ctx.brand.palette.dark})`, 600), margin: 0 },
3232
3257
  children: title
3233
3258
  }
3234
3259
  ) : null,
@@ -3242,8 +3267,7 @@ function FooterLinkListBlock({
3242
3267
  href: footerLinkHref(href, ctx),
3243
3268
  ...ctx.keyFor ? { "data-ohw-href-key": ctx.keyFor(`${path}.items.${i}.href`) } : {},
3244
3269
  style: {
3245
- ...typeStyle(AI_TREE_TOKENS.type.bodyM, ctx.brand.fonts.body),
3246
- color: ctx.brand.palette.dark,
3270
+ ...footerBodyStyle(ctx.brand.fonts.body, `var(--surface-fg, ${ctx.brand.palette.dark})`),
3247
3271
  textDecoration: "none"
3248
3272
  },
3249
3273
  children: /* @__PURE__ */ jsx(
@@ -3274,7 +3298,7 @@ function FooterHoursBlock({
3274
3298
  "p",
3275
3299
  {
3276
3300
  ...textAttrs(ctx, `${path}.title`),
3277
- style: { ...typeStyle(AI_TREE_TOKENS.type.bodyMBold, ctx.brand.fonts.body), margin: 0, color: ctx.brand.palette.dark },
3301
+ style: { ...footerBodyStyle(ctx.brand.fonts.body, `var(--surface-fg, ${ctx.brand.palette.dark})`, 600), margin: 0 },
3278
3302
  children: title
3279
3303
  }
3280
3304
  ) : null,
@@ -3289,8 +3313,7 @@ function FooterHoursBlock({
3289
3313
  display: "flex",
3290
3314
  justifyContent: "space-between",
3291
3315
  gap: AI_TREE_TOKENS.spacing4,
3292
- ...typeStyle(AI_TREE_TOKENS.type.bodyM, ctx.brand.fonts.body),
3293
- color: ctx.brand.palette.dark
3316
+ ...footerBodyStyle(ctx.brand.fonts.body, `var(--surface-fg, ${ctx.brand.palette.dark})`)
3294
3317
  },
3295
3318
  children: [
3296
3319
  /* @__PURE__ */ jsx("dt", { ...textAttrs(ctx, `${path}.items.${i}.day`), style: { margin: 0 }, children: day }),
@@ -3314,15 +3337,17 @@ function FooterLogoBlock({
3314
3337
  {
3315
3338
  src: url,
3316
3339
  alt,
3317
- ...ctx.keyFor ? { "data-ohw-key": ctx.keyFor(`${path}.alt`), "data-ohw-role": "logo" } : { "data-ohw-role": "logo" },
3318
- style: { display: "block", maxHeight: 40, width: "auto", maxWidth: "100%" }
3340
+ "data-ohw-key": "footer-logo-img",
3341
+ "data-ohw-editable": "image",
3342
+ "data-ohw-role": "logo",
3343
+ style: { display: "block", height: "2.25rem", width: "auto", maxWidth: "100%" }
3319
3344
  }
3320
3345
  ) : /* @__PURE__ */ jsx(
3321
3346
  "span",
3322
3347
  {
3323
3348
  ...textAttrs(ctx, `${path}.alt`),
3324
3349
  "data-ohw-role": "logo",
3325
- style: { ...typeStyle(AI_TREE_TOKENS.type.h3, ctx.brand.fonts.heading), color: ctx.brand.palette.dark },
3350
+ style: footerLogoStyle(ctx.brand.fonts.heading, ctx.brand.palette.primary),
3326
3351
  children: alt
3327
3352
  }
3328
3353
  ) });
@@ -3955,9 +3980,8 @@ function AiFooterRenderer({
3955
3980
  "data-ohw-key": `footer-${colIndex}-heading`,
3956
3981
  "data-ohw-editable": "text",
3957
3982
  style: {
3958
- ...typeStyle(AI_TREE_TOKENS.type.bodyMBold, resolvedBrand.fonts.body),
3959
- margin: 0,
3960
- color: bandText
3983
+ ...footerBodyStyle(resolvedBrand.fonts.body, bandText, 600),
3984
+ margin: 0
3961
3985
  },
3962
3986
  children: title
3963
3987
  }
@@ -3972,8 +3996,7 @@ function AiFooterRenderer({
3972
3996
  href: footerLinkHref(href, ctx),
3973
3997
  "data-ohw-href-key": `footer-${colIndex}-${i}-href`,
3974
3998
  style: {
3975
- ...typeStyle(AI_TREE_TOKENS.type.bodyM, resolvedBrand.fonts.body),
3976
- color: bandText,
3999
+ ...footerBodyStyle(resolvedBrand.fonts.body, bandText),
3977
4000
  textDecoration: "none"
3978
4001
  },
3979
4002
  children: /* @__PURE__ */ jsx(
@@ -4019,9 +4042,8 @@ function AiFooterRenderer({
4019
4042
  "data-ohw-key": "footer-copyright",
4020
4043
  "data-ohw-editable": "text",
4021
4044
  style: {
4022
- ...typeStyle(AI_TREE_TOKENS.type.bodyM, resolvedBrand.fonts.body),
4023
- margin: 0,
4024
- color: `color-mix(in srgb, ${bandText} 75%, transparent)`
4045
+ ...footerBodyStyle(resolvedBrand.fonts.body, bandText),
4046
+ margin: 0
4025
4047
  },
4026
4048
  children: copyright
4027
4049
  }
@@ -4033,8 +4055,7 @@ function AiFooterRenderer({
4033
4055
  href: item.href,
4034
4056
  "data-ohw-footer-legal-link": item.key,
4035
4057
  style: {
4036
- ...typeStyle(AI_TREE_TOKENS.type.bodyM, resolvedBrand.fonts.body),
4037
- color: `color-mix(in srgb, ${bandText} 75%, transparent)`,
4058
+ ...footerBodyStyle(resolvedBrand.fonts.body, bandText),
4038
4059
  textDecoration: "none"
4039
4060
  },
4040
4061
  children: item.label
@@ -4047,8 +4068,7 @@ function AiFooterRenderer({
4047
4068
  "data-ohw-footer-legal-link": item.key,
4048
4069
  onClick: item.onClick,
4049
4070
  style: {
4050
- ...typeStyle(AI_TREE_TOKENS.type.bodyM, resolvedBrand.fonts.body),
4051
- color: `color-mix(in srgb, ${bandText} 75%, transparent)`,
4071
+ ...footerBodyStyle(resolvedBrand.fonts.body, bandText),
4052
4072
  background: "none",
4053
4073
  border: "none",
4054
4074
  padding: 0,
@@ -4803,8 +4823,32 @@ function defaultLegal() {
4803
4823
  }
4804
4824
  };
4805
4825
  }
4806
- function resolveLogoFromContent(content) {
4826
+ var FOOTER_LOGO_CONTENT_KEYS = ["footer-logo-img", "footer-logo-image", "footer-logo"];
4827
+ function logoSrcFromFooterDom(footer) {
4828
+ if (!footer) return null;
4829
+ const img = footer.querySelector(
4830
+ '[data-ohw-key="footer-logo-img"], [data-ohw-key="footer-logo-image"], [data-ohw-role="logo"] img'
4831
+ );
4832
+ const raw = (img?.currentSrc || img?.getAttribute("src") || "").trim();
4833
+ if (!raw) return null;
4834
+ try {
4835
+ const url = new URL(raw, window.location.href);
4836
+ const wrapped = url.pathname.endsWith("/_next/image") ? url.searchParams.get("url") : null;
4837
+ if (wrapped) return decodeURIComponent(wrapped);
4838
+ } catch {
4839
+ }
4840
+ return raw;
4841
+ }
4842
+ function resolveLogoFromContent(content, footer) {
4807
4843
  if (mountOptions.logoUrl) return mountOptions.logoUrl;
4844
+ if (content) {
4845
+ for (const key of FOOTER_LOGO_CONTENT_KEYS) {
4846
+ const value = content[key];
4847
+ if (typeof value === "string" && value.trim()) return value.trim();
4848
+ }
4849
+ }
4850
+ const fromDom = logoSrcFromFooterDom(footer);
4851
+ if (fromDom) return fromDom;
4808
4852
  if (!content) return null;
4809
4853
  const canonical = content[LOGO_IMAGE_URL_KEY];
4810
4854
  if (typeof canonical === "string" && canonical.trim()) return canonical.trim();
@@ -4827,11 +4871,11 @@ function applyAiFooterToDom(state, content) {
4827
4871
  unmountAiFooter();
4828
4872
  return;
4829
4873
  }
4830
- const brand = mountOptions.brand ?? deriveTemplateBrand();
4831
- const logoUrl = resolveLogoFromContent(content);
4832
4874
  const templateFooter = findTemplateFooter();
4833
4875
  captureTemplateFooterSurface(templateFooter);
4834
4876
  const surface = capturedSurface ?? null;
4877
+ const brand = mountOptions.brand ?? deriveTemplateBrand();
4878
+ const logoUrl = resolveLogoFromContent(content, templateFooter);
4835
4879
  const serialized = JSON.stringify(state) + JSON.stringify(brand ?? null) + (logoUrl ?? "") + JSON.stringify(surface) + JSON.stringify(defaultLegal());
4836
4880
  if (mounted2 && mounted2.serialized === serialized && mounted2.container.isConnected) {
4837
4881
  hideTemplateFooter(templateFooter);
@@ -29110,7 +29154,7 @@ function OhhwellsBridge() {
29110
29154
  postToParent2({
29111
29155
  type: "ow:ready",
29112
29156
  version: "1",
29113
- bridgeVersion: "0.1.128",
29157
+ bridgeVersion: "0.1.129",
29114
29158
  path: pathname,
29115
29159
  nodes: collectEditableNodes(editContentRef.current),
29116
29160
  sections