@ohhwells/bridge 0.1.83 → 0.1.85

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;
@@ -7432,6 +7458,9 @@ function applyFieldType(wrapper, type) {
7432
7458
  el.style.removeProperty("min-height");
7433
7459
  el.style.removeProperty("resize");
7434
7460
  el.removeAttribute("rows");
7461
+ if (el.className) {
7462
+ el.className = el.className.split(/\s+/).filter((token) => !/textarea/i.test(token)).join(" ");
7463
+ }
7435
7464
  };
7436
7465
  const applyDefaults = (el) => {
7437
7466
  el.setAttribute("placeholder", defaults.placeholder);
@@ -11682,7 +11711,7 @@ function applySocialsDisplayToRow(row, display) {
11682
11711
  const icon = item.querySelector(ICON_SELECTOR);
11683
11712
  if (label) label.style.display = display.text ? "" : "none";
11684
11713
  if (icon) icon.style.display = display.icon ? "" : "none";
11685
- layOutIconAndLabel(item, Boolean(display.text && display.icon));
11714
+ layOutIconAndLabel(item, Boolean(display.text));
11686
11715
  });
11687
11716
  allowRowToWrap(row);
11688
11717
  }
@@ -11694,6 +11723,9 @@ function layOutIconAndLabel(item, on) {
11694
11723
  item.style.gap = "";
11695
11724
  item.style.whiteSpace = "";
11696
11725
  item.style.flex = "";
11726
+ item.style.width = "";
11727
+ item.style.height = "";
11728
+ item.style.padding = "";
11697
11729
  return;
11698
11730
  }
11699
11731
  item.style.display = on ? "inline-flex" : "";
@@ -11701,6 +11733,9 @@ function layOutIconAndLabel(item, on) {
11701
11733
  item.style.gap = on ? "8px" : "";
11702
11734
  item.style.whiteSpace = on ? "nowrap" : "";
11703
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" : "";
11704
11739
  }
11705
11740
  function allowRowToWrap(row) {
11706
11741
  const display = row.ownerDocument.defaultView?.getComputedStyle(row).display ?? "";
@@ -12656,6 +12691,15 @@ function resolveLogoDisplayText(text) {
12656
12691
  function isFooterLogoRoot(root) {
12657
12692
  return Boolean(root.closest("footer") || root.closest('[data-ohw-section="footer"]'));
12658
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
+ }
12659
12703
  function imageKeyForRoot(root) {
12660
12704
  return isFooterLogoRoot(root) ? "footer-logo" : "nav-logo-image";
12661
12705
  }
@@ -12705,9 +12749,10 @@ function applyLogoIdentity(text, isPlaceholder) {
12705
12749
  });
12706
12750
  return display;
12707
12751
  }
12708
- function applyLogoImage(url, alt) {
12752
+ function applyLogoImage(url, alt, placement) {
12709
12753
  const displayAlt = resolveLogoDisplayText(alt);
12710
12754
  document.querySelectorAll('[data-ohw-role="logo"], [data-ohw-logo]').forEach((root) => {
12755
+ if (placement && (isFooterLogoRoot(root) ? "footer" : "navbar") !== placement) return;
12711
12756
  ensureLogoHrefKey(root);
12712
12757
  const imageKey = imageKeyForRoot(root);
12713
12758
  const textKey = textKeyForRoot(root);
@@ -12828,7 +12873,12 @@ function applyLogoFromContent(content) {
12828
12873
  const logoImageUrl = typeof rawLogoImage === "string" && rawLogoImage.trim() ? rawLogoImage.trim() : null;
12829
12874
  const imageExplicitlyCleared = LOGO_IMAGE_KEYS.some((key) => key in content) && !logoImageUrl;
12830
12875
  const logoIsPlaceholder = LOGO_PLACEHOLDER_KEY in content ? content[LOGO_PLACEHOLDER_KEY] !== "false" : !logoImageUrl && (!logoText.trim() || logoText === PLACEHOLDER_BUSINESS_NAME);
12831
- 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) {
12832
12882
  applyLogoImage(logoImageUrl, logoAlt);
12833
12883
  } else {
12834
12884
  if (imageExplicitlyCleared) applyLogoImage(null, logoAlt);
@@ -16029,6 +16079,7 @@ function StateToggle({
16029
16079
  );
16030
16080
  }
16031
16081
  var contentCache = /* @__PURE__ */ new Map();
16082
+ var brandingCache = /* @__PURE__ */ new Map();
16032
16083
  var OHW_LOADER_STYLE = {
16033
16084
  position: "fixed",
16034
16085
  inset: 0,
@@ -16066,6 +16117,89 @@ function OhwLoaderSpinner() {
16066
16117
  )
16067
16118
  ] });
16068
16119
  }
16120
+ function OhwBrandMark() {
16121
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
16122
+ "svg",
16123
+ {
16124
+ width: "16",
16125
+ height: "16",
16126
+ viewBox: "0 0 48 48",
16127
+ fill: "none",
16128
+ "aria-hidden": true,
16129
+ style: { display: "block", flexShrink: 0 },
16130
+ xmlns: "http://www.w3.org/2000/svg",
16131
+ children: [
16132
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
16133
+ "mask",
16134
+ {
16135
+ id: "ohw-badge-mark",
16136
+ style: { maskType: "luminance" },
16137
+ maskUnits: "userSpaceOnUse",
16138
+ x: "0",
16139
+ y: "0",
16140
+ width: "48",
16141
+ height: "48",
16142
+ children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("path", { d: "M23.8741 48C37.0594 48 47.7481 37.2548 47.7481 24C47.7481 10.7452 37.0594 0 23.8741 0C10.6888 0 0 10.7452 0 24C0 37.2548 10.6888 48 23.8741 48Z", fill: "white" })
16143
+ }
16144
+ ),
16145
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("g", { mask: "url(#ohw-badge-mark)", children: [
16146
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("path", { d: "M23.8731 48.0497C37.0584 48.0497 47.7472 37.3046 47.7472 24.0497C47.7472 10.7949 37.0584 0.0497208 23.8731 0.0497208C10.6878 0.0497208 -0.000976562 10.7949 -0.000976562 24.0497C-0.000976562 37.3046 10.6878 48.0497 23.8731 48.0497Z", fill: "#0078E5" }),
16147
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("path", { d: "M17.1307 14.7172C13.1687 14.7172 9.38102 18.1154 8.65114 22.34C8.38885 23.8488 8.5598 25.2581 9.06929 26.4451C6.20005 29.1677 1.77216 27.8721 -1.40212 26.1536C-2.73618 25.4317 -3.92695 27.4745 -2.59037 28.1981C1.33389 30.3226 6.86037 31.6621 10.4402 28.4188C11.4718 29.3859 12.867 29.9621 14.4894 29.9621C18.4161 29.9621 22.2038 26.5318 22.9337 22.34C23.6636 18.1162 21.0566 14.7172 17.1298 14.7172H17.1307ZM19.9798 22.34C19.5281 25.0399 17.2689 27.231 14.9754 27.231C12.6466 27.231 11.1877 25.0399 11.6394 22.34C12.1262 19.6401 14.3151 17.4482 16.6438 17.4482C18.9374 17.4482 20.4667 19.6401 19.9798 22.34Z", fill: "white" }),
16148
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("path", { d: "M40.0017 27.0262C39.1797 27.081 38.2721 26.995 37.4668 26.7415C37.3344 26.6993 37.28 26.5401 37.3529 26.4205C37.5959 26.0212 37.8255 25.6152 38.009 25.1889C38.1071 24.9918 38.2018 24.793 38.2897 24.5908C38.3274 24.5041 38.4163 24.451 38.5101 24.4619C38.63 24.4754 38.7054 24.4821 38.8881 24.4821L39.1529 24.4796L39.8283 24.4543C45.9229 24.0492 50.4765 20.4319 54.8466 16.9014C56.0172 15.9554 57.6932 17.6208 56.5116 18.5752C51.7687 22.4065 47.1966 26.5081 40.9319 26.9689", fill: "white" }),
16149
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("path", { d: "M37.9687 24.27C38.4472 23.1319 38.7656 21.9045 38.9609 20.6991C39.5927 16.76 38.5058 14.2193 36.1553 14.2193C34.1835 14.2193 33.1469 17.2427 32.9199 18.8694C32.743 19.9872 32.5914 22.1219 33.6028 23.9524C33.7553 24.259 34.15 24.7712 34.471 25.1259C34.5447 25.2067 34.6746 25.2 34.7349 25.1082C34.9528 24.7788 35.1615 24.4039 35.3584 24.0257C35.5444 23.6677 35.5888 23.6138 35.8587 23.0207C35.8838 22.966 35.8813 22.9002 35.8478 22.8505C35.5888 22.4597 35.2168 21.9787 35.1204 21.4614C34.9184 20.4455 34.9436 19.2257 35.2218 18.1078C35.4413 17.3118 35.7195 16.7844 35.9039 16.5106C35.9466 16.4466 36.0279 16.4129 36.0975 16.4449C36.369 16.5671 36.5827 16.8838 36.7385 17.396C37.0167 18.2089 37.0167 19.3782 36.814 20.6999C36.6991 21.5271 36.4771 22.3729 36.1746 23.1673C36.1293 23.308 36.0757 23.4461 36.0187 23.5826C36.0187 23.5868 36.0187 23.591 36.0187 23.5961C35.9911 23.6946 35.9207 23.8067 35.8846 23.901C35.5536 24.5497 35.2344 25.1697 34.8439 25.7838C34.8388 25.7863 34.8346 25.7914 34.8296 25.7931C34.6528 26.0525 34.4718 26.2901 34.2866 26.4965C34.2774 26.5099 34.2682 26.5234 34.2589 26.5369C34.2405 26.5638 34.2179 26.5815 34.1944 26.595C33.5064 27.3212 32.7665 27.6893 32.0123 27.6893C31.8606 27.6893 31.6838 27.664 31.507 27.4349C31.3042 27.1299 30.85 26.0879 31.2539 22.9112C31.4785 21.3949 31.8011 20.0268 31.931 19.5408C31.9579 19.4413 31.8908 19.3419 31.7886 19.3293L30.0062 19.1162C29.9241 19.1061 29.8478 19.1566 29.8252 19.2366C29.2704 21.1615 27.0305 27.6885 24.9599 27.6885C24.328 27.6885 24.1512 26.6211 24.1001 26.2909C23.775 23.6264 25.528 18.5492 29.5302 16.2267C29.6048 16.1838 29.635 16.0928 29.5998 16.0136L28.9042 14.467C28.8632 14.3752 28.7501 14.3389 28.6638 14.3886C25.8079 16.0414 24.1847 18.5231 23.2915 20.3436C22.2046 22.5793 21.6993 25.0189 21.9515 26.8738C22.1795 28.7794 23.1398 29.872 24.6054 29.872C26.0543 29.872 27.4369 28.9066 28.7098 27.0187C28.7953 26.8915 28.9889 26.9311 29.0149 27.0819C29.2646 28.5283 29.9811 29.872 31.6579 29.872C33.5282 29.872 35.3232 28.7288 36.7134 26.6447C36.7712 26.5874 36.7972 26.5411 36.8181 26.4906C36.8232 26.4931 36.8282 26.4948 36.8332 26.4973C37.01 26.2025 37.181 25.9051 37.3444 25.6027C37.4508 25.4005 37.5572 25.1992 37.6586 24.9945C37.7181 24.874 37.7743 24.7527 37.8262 24.6289C37.838 24.6002 37.8547 24.5665 37.8706 24.5337", fill: "white" }),
16150
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("path", { d: "M30.5839 31.6397C25.7546 34.8577 19.4773 34.7853 14.6907 31.5243C13.5368 30.7384 12.5044 32.6498 13.6474 33.4281C19.034 37.0985 26.3077 37.096 31.7218 33.488C32.8791 32.7172 31.7478 30.8639 30.5839 31.6397Z", fill: "white" })
16151
+ ] })
16152
+ ]
16153
+ }
16154
+ );
16155
+ }
16156
+ var OHW_BADGE_STYLE = {
16157
+ position: "fixed",
16158
+ left: 20,
16159
+ bottom: 20,
16160
+ zIndex: 2147483e3,
16161
+ boxSizing: "border-box",
16162
+ display: "inline-flex",
16163
+ alignItems: "center",
16164
+ gap: 0,
16165
+ padding: "6px 8px",
16166
+ margin: 0,
16167
+ background: "#ffffff",
16168
+ border: "1px solid #e7e5e4",
16169
+ borderRadius: 9999,
16170
+ boxShadow: "0 1px 3px rgba(0, 0, 0, 0.1)",
16171
+ color: "#0c0a09",
16172
+ textDecoration: "none",
16173
+ fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif"
16174
+ };
16175
+ var OHW_BADGE_LABEL_STYLE = {
16176
+ padding: "0 4px",
16177
+ fontSize: 14,
16178
+ lineHeight: "24px",
16179
+ fontWeight: 500,
16180
+ fontStyle: "normal",
16181
+ letterSpacing: "normal",
16182
+ textTransform: "none",
16183
+ color: "#0c0a09",
16184
+ whiteSpace: "nowrap"
16185
+ };
16186
+ function MadeWithOhhWells() {
16187
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
16188
+ "a",
16189
+ {
16190
+ href: "https://ohhwells.com",
16191
+ target: "_blank",
16192
+ rel: "noopener noreferrer",
16193
+ "aria-label": "Made with OhhWells",
16194
+ "data-ohw-badge": "",
16195
+ style: OHW_BADGE_STYLE,
16196
+ children: [
16197
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(OhwBrandMark, {}),
16198
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { style: OHW_BADGE_LABEL_STYLE, children: "Made with OhhWells" })
16199
+ ]
16200
+ }
16201
+ );
16202
+ }
16069
16203
  var OHW_LOADER_PREHYDRATE_SCRIPT = `(function(){try{var p=location.hostname.split(".");var fromHost=p.length>=3&&p[0]!=="www"?p[0]:"";var fromQuery=new URLSearchParams(location.search).get("subdomain")||"";if(!fromHost&&!fromQuery)return;var e=document.getElementById("ohw-loader");if(e)e.style.display="flex"}catch(e){}})();`;
16070
16204
  function resolveSubdomain(subdomainFromQuery) {
16071
16205
  if (subdomainFromQuery) return subdomainFromQuery;
@@ -16125,6 +16259,7 @@ function OhhwellsBridge() {
16125
16259
  }
16126
16260
  }, []);
16127
16261
  const [fetchState, setFetchState] = (0, import_react17.useState)("idle");
16262
+ const [showBranding, setShowBranding] = (0, import_react17.useState)(false);
16128
16263
  const autoSaveTimers = (0, import_react17.useRef)(/* @__PURE__ */ new Map());
16129
16264
  const activeElRef = (0, import_react17.useRef)(null);
16130
16265
  const pointerHeldRef = (0, import_react17.useRef)(false);
@@ -17900,6 +18035,7 @@ function OhhwellsBridge() {
17900
18035
  };
17901
18036
  const cached = contentCache.get(subdomain);
17902
18037
  if (cached) {
18038
+ setShowBranding(brandingCache.get(subdomain) ?? false);
17903
18039
  applyContent(cached).finally(() => setFetchState("done"));
17904
18040
  return;
17905
18041
  }
@@ -17909,7 +18045,10 @@ function OhhwellsBridge() {
17909
18045
  fetch(`${apiUrl}/api/public/sites/${subdomain}/content`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
17910
18046
  if (cancelled) return;
17911
18047
  const content = data?.content ?? {};
18048
+ const branding = Boolean(data?.showBranding);
17912
18049
  contentCache.set(subdomain, content);
18050
+ brandingCache.set(subdomain, branding);
18051
+ setShowBranding(branding);
17913
18052
  return applyContent(content);
17914
18053
  }).catch(() => {
17915
18054
  }).finally(() => {
@@ -18205,6 +18344,8 @@ function OhhwellsBridge() {
18205
18344
  };
18206
18345
  const t1 = setTimeout(measure, 50);
18207
18346
  const t2 = setTimeout(measure, 500);
18347
+ const ro = new ResizeObserver(schedule);
18348
+ ro.observe(document.body);
18208
18349
  let lastWidth = window.innerWidth;
18209
18350
  let resizeTimers = [];
18210
18351
  const clearResizeTimers = () => {
@@ -18222,6 +18363,7 @@ function OhhwellsBridge() {
18222
18363
  clearTimeout(t1);
18223
18364
  clearTimeout(t2);
18224
18365
  if (raf != null) cancelAnimationFrame(raf);
18366
+ ro.disconnect();
18225
18367
  clearResizeTimers();
18226
18368
  window.removeEventListener("resize", handleResize);
18227
18369
  };
@@ -21094,7 +21236,7 @@ function OhhwellsBridge() {
21094
21236
  postToParent2({
21095
21237
  type: "ow:ready",
21096
21238
  version: "1",
21097
- bridgeVersion: "0.1.82",
21239
+ bridgeVersion: "0.1.84",
21098
21240
  path: pathname,
21099
21241
  nodes: collectEditableNodes(editContentRef.current),
21100
21242
  sections
@@ -21557,6 +21699,7 @@ function OhhwellsBridge() {
21557
21699
  return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
21558
21700
  /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { id: "ohw-loader", suppressHydrationWarning: true, style: { ...OHW_LOADER_STYLE, display: "none" }, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(OhwLoaderSpinner, {}) }),
21559
21701
  /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("script", { suppressHydrationWarning: true, dangerouslySetInnerHTML: { __html: OHW_LOADER_PREHYDRATE_SCRIPT } }),
21702
+ subdomain && !isEditMode && showBranding && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(MadeWithOhhWells, {}),
21560
21703
  bridgeRoot ? (0, import_react_dom4.createPortal)(
21561
21704
  /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
21562
21705
  /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),