@ohhwells/bridge 0.1.139-next.373 → 0.1.139-next.374
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 +85 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +85 -24
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2919,14 +2919,22 @@ function isInactiveFooterChrome(el) {
|
|
|
2919
2919
|
if (footer && footer.style.display === "none") return true;
|
|
2920
2920
|
return false;
|
|
2921
2921
|
}
|
|
2922
|
+
function isIncidentalFooter(el) {
|
|
2923
|
+
return Boolean(el.closest("blockquote, article, figure"));
|
|
2924
|
+
}
|
|
2922
2925
|
function getFooterRoot() {
|
|
2923
2926
|
const ai = document.querySelector("footer[data-ai-footer]");
|
|
2924
2927
|
if (ai) return ai;
|
|
2925
2928
|
for (const el of Array.from(
|
|
2926
|
-
document.querySelectorAll('footer[data-ohw-section="footer"]
|
|
2929
|
+
document.querySelectorAll('footer[data-ohw-section="footer"]')
|
|
2927
2930
|
)) {
|
|
2931
|
+
if (isInactiveFooterChrome(el)) continue;
|
|
2932
|
+
return el;
|
|
2933
|
+
}
|
|
2934
|
+
for (const el of Array.from(document.querySelectorAll("footer"))) {
|
|
2928
2935
|
if (el.hasAttribute("data-ai-footer")) continue;
|
|
2929
2936
|
if (isInactiveFooterChrome(el)) continue;
|
|
2937
|
+
if (isIncidentalFooter(el)) continue;
|
|
2930
2938
|
return el;
|
|
2931
2939
|
}
|
|
2932
2940
|
return null;
|
|
@@ -3337,8 +3345,8 @@ function buildFooterLink(colIndex, itemIndex, href, label, template) {
|
|
|
3337
3345
|
return anchor;
|
|
3338
3346
|
}
|
|
3339
3347
|
function footerColumnExistsInDom(colIndex) {
|
|
3340
|
-
const
|
|
3341
|
-
return
|
|
3348
|
+
const scope = getFooterLinksContainer() ?? getFooterRoot() ?? document;
|
|
3349
|
+
return scope.querySelector(`[data-ohw-footer-col="${colIndex}"]`) !== null || scope.querySelector(`[data-ohw-href-key^="footer-${colIndex}-"]`) !== null || scope.querySelector(`[data-ohw-key="footer-${colIndex}-heading"]`) !== null;
|
|
3342
3350
|
}
|
|
3343
3351
|
function getFooterLinkTemplate() {
|
|
3344
3352
|
for (const col of listFooterColumns()) {
|
|
@@ -6355,6 +6363,20 @@ function applyBrandChrome(content) {
|
|
|
6355
6363
|
|
|
6356
6364
|
// src/lib/brand-kit.ts
|
|
6357
6365
|
var BRAND_KIT_KEY = "__ohw_brand";
|
|
6366
|
+
var appliedPalette = null;
|
|
6367
|
+
var appliedFonts = null;
|
|
6368
|
+
function getAppliedBrand() {
|
|
6369
|
+
if (!appliedPalette) return null;
|
|
6370
|
+
return appliedFonts ? { palette: appliedPalette, fonts: appliedFonts } : { palette: appliedPalette };
|
|
6371
|
+
}
|
|
6372
|
+
function brandForGenerated(fallback) {
|
|
6373
|
+
const applied = getAppliedBrand();
|
|
6374
|
+
if (!applied) return fallback ?? void 0;
|
|
6375
|
+
return {
|
|
6376
|
+
palette: applied.palette,
|
|
6377
|
+
fonts: applied.fonts ?? fallback?.fonts ?? AI_DEFAULT_BRAND.fonts
|
|
6378
|
+
};
|
|
6379
|
+
}
|
|
6358
6380
|
var BRAND_VAR_PREFIX = "--ohw-brand-";
|
|
6359
6381
|
var BRAND_VAR_NAMES = ["primary", "accent", "light", "dark", "surface", "border", "muted"].map(
|
|
6360
6382
|
(role) => `${BRAND_VAR_PREFIX}${role}`
|
|
@@ -6658,6 +6680,8 @@ function loadCustomFonts(fonts) {
|
|
|
6658
6680
|
function applyBrandToDom(kit) {
|
|
6659
6681
|
const root = document.documentElement;
|
|
6660
6682
|
if (!kit) {
|
|
6683
|
+
appliedPalette = null;
|
|
6684
|
+
appliedFonts = null;
|
|
6661
6685
|
for (const name of [...BRAND_VAR_NAMES, ...LEGACY_BRAND_VAR_NAMES, ...BUTTON_VAR_NAMES]) {
|
|
6662
6686
|
root.style.removeProperty(name);
|
|
6663
6687
|
}
|
|
@@ -6671,11 +6695,16 @@ function applyBrandToDom(kit) {
|
|
|
6671
6695
|
const applyFonts = kit.touched ? kit.touched.fonts === true : true;
|
|
6672
6696
|
if (kit.palette) {
|
|
6673
6697
|
if (applyPalette) {
|
|
6698
|
+
appliedPalette = kit.palette;
|
|
6674
6699
|
for (const [name, value] of Object.entries(brandColorVars(kit.palette))) root.style.setProperty(name, value);
|
|
6675
6700
|
} else {
|
|
6701
|
+
appliedPalette = null;
|
|
6676
6702
|
for (const name of [...BRAND_VAR_NAMES, ...LEGACY_BRAND_VAR_NAMES]) root.style.removeProperty(name);
|
|
6677
6703
|
}
|
|
6678
6704
|
}
|
|
6705
|
+
if (kit.fonts) {
|
|
6706
|
+
appliedFonts = applyFonts ? kit.fonts : null;
|
|
6707
|
+
}
|
|
6679
6708
|
if (kit.buttons) {
|
|
6680
6709
|
for (const name of BUTTON_VAR_NAMES) root.style.removeProperty(name);
|
|
6681
6710
|
for (const [name, value] of Object.entries(buttonStyleVars({ ...kit, buttons: kit.buttons }))) root.style.setProperty(name, value);
|
|
@@ -7208,6 +7237,35 @@ function withThemeFonts(brand) {
|
|
|
7208
7237
|
}
|
|
7209
7238
|
};
|
|
7210
7239
|
}
|
|
7240
|
+
function liveBrandColor(role, fallback) {
|
|
7241
|
+
if (role === "dark") {
|
|
7242
|
+
return `var(--brand-text, var(--ohw-brand-dark, var(--color-dark, ${fallback})))`;
|
|
7243
|
+
}
|
|
7244
|
+
if (role === "light") {
|
|
7245
|
+
return `var(--brand-background, var(--ohw-brand-light, var(--color-light, ${fallback})))`;
|
|
7246
|
+
}
|
|
7247
|
+
return `var(--brand-${role}, var(--ohw-brand-${role}, var(--color-${role}, ${fallback})))`;
|
|
7248
|
+
}
|
|
7249
|
+
function withLivePalette(brand, source) {
|
|
7250
|
+
const sourceOf = (color) => {
|
|
7251
|
+
const value = color.trim().toLowerCase();
|
|
7252
|
+
const entries = Object.entries(source.palette);
|
|
7253
|
+
return entries.find(([, hex]) => hex.trim().toLowerCase() === value)?.[0] ?? null;
|
|
7254
|
+
};
|
|
7255
|
+
const map = (color) => {
|
|
7256
|
+
const role = sourceOf(color);
|
|
7257
|
+
return role ? liveBrandColor(role, source.palette[role]) : color;
|
|
7258
|
+
};
|
|
7259
|
+
return {
|
|
7260
|
+
...brand,
|
|
7261
|
+
palette: {
|
|
7262
|
+
dark: map(brand.palette.dark),
|
|
7263
|
+
primary: map(brand.palette.primary),
|
|
7264
|
+
accent: map(brand.palette.accent),
|
|
7265
|
+
light: map(brand.palette.light)
|
|
7266
|
+
}
|
|
7267
|
+
};
|
|
7268
|
+
}
|
|
7211
7269
|
function footerLogoStyle(fallbackFont, fallbackColor) {
|
|
7212
7270
|
return {
|
|
7213
7271
|
fontFamily: `var(--brand-font-heading, var(--font-heading, var(--font-display, ${quotedFont(fallbackFont)})))`,
|
|
@@ -7427,7 +7485,7 @@ function hexContrast(a, b) {
|
|
|
7427
7485
|
function primaryButtonLabel(brand) {
|
|
7428
7486
|
const darkC = hexContrast(brand.palette.primary, brand.palette.dark);
|
|
7429
7487
|
const lightC = hexContrast(brand.palette.primary, AI_TREE_TOKENS.textPrimaryForeground);
|
|
7430
|
-
if (darkC === null || lightC === null) return AI_TREE_TOKENS.textPrimaryForeground
|
|
7488
|
+
if (darkC === null || lightC === null) return `var(--brand-on-primary, ${AI_TREE_TOKENS.textPrimaryForeground})`;
|
|
7431
7489
|
return darkC > lightC ? brand.palette.dark : AI_TREE_TOKENS.textPrimaryForeground;
|
|
7432
7490
|
}
|
|
7433
7491
|
function accentBandContext(brand) {
|
|
@@ -7451,7 +7509,11 @@ function readableForeground(bg, brand) {
|
|
|
7451
7509
|
return darkC > lightC ? brand.palette.dark : AI_TREE_TOKENS.textPrimaryForeground;
|
|
7452
7510
|
}
|
|
7453
7511
|
function hexWithAlpha(hex, alpha) {
|
|
7454
|
-
const
|
|
7512
|
+
const value = hex.trim();
|
|
7513
|
+
if (value.startsWith("var(") || value.startsWith("color-mix(")) {
|
|
7514
|
+
return `color-mix(in srgb, ${value} ${Math.round(alpha * 100)}%, transparent)`;
|
|
7515
|
+
}
|
|
7516
|
+
const m = /^#([0-9a-f]{6})$/i.exec(value);
|
|
7455
7517
|
if (!m) return hex;
|
|
7456
7518
|
const r2 = parseInt(m[1].slice(0, 2), 16);
|
|
7457
7519
|
const g = parseInt(m[1].slice(2, 4), 16);
|
|
@@ -7750,12 +7812,10 @@ function ButtonEl({
|
|
|
7750
7812
|
cursor: "pointer",
|
|
7751
7813
|
whiteSpace: "nowrap",
|
|
7752
7814
|
...buttonShellStyle(ctx, variant, fullWidth),
|
|
7753
|
-
...tokenColorStyle ?? (secondary ? { border: `1px solid ${secondaryColor ?? ctx.brand.palette.dark}`, color: secondaryColor ?? ctx.brand.palette.dark } :
|
|
7754
|
-
|
|
7755
|
-
|
|
7756
|
-
|
|
7757
|
-
!ctx.buttonLabel && ctx.buttonStyle?.background ? { background: ctx.buttonStyle.background, color: ctx.buttonStyle.color } : { background: ctx.brand.palette.primary, color: ctx.buttonLabel ?? primaryButtonLabel(ctx.brand) }
|
|
7758
|
-
))
|
|
7815
|
+
...tokenColorStyle ?? (secondary ? { border: `1px solid ${secondaryColor ?? ctx.brand.palette.dark}`, color: secondaryColor ?? ctx.brand.palette.dark } : {
|
|
7816
|
+
background: ctx.brand.palette.primary,
|
|
7817
|
+
color: ctx.buttonLabel ?? primaryButtonLabel(ctx.brand)
|
|
7818
|
+
})
|
|
7759
7819
|
},
|
|
7760
7820
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...path ? textAttrs(ctx, `${path}.label`) : {}, children: str(slots.label) })
|
|
7761
7821
|
}
|
|
@@ -9600,10 +9660,10 @@ function renderNode(node, ctx, path, ambientAlign) {
|
|
|
9600
9660
|
...buttonShellStyle(ctx, "primary"),
|
|
9601
9661
|
// Brand-styled: the template button's measured fill/label pair off-band, else
|
|
9602
9662
|
// primary fill with a brand-derived label so it reads on custom palettes.
|
|
9603
|
-
...buttonColorStyle(ctx, "primary") ??
|
|
9663
|
+
...buttonColorStyle(ctx, "primary") ?? {
|
|
9604
9664
|
background: ctx.brand.palette.primary,
|
|
9605
9665
|
color: ctx.buttonLabel ?? primaryButtonLabel(ctx.brand)
|
|
9606
|
-
}
|
|
9666
|
+
}
|
|
9607
9667
|
},
|
|
9608
9668
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...textAttrs(ctx, `${path}.c${i}.label`), children: str(cs.label) })
|
|
9609
9669
|
},
|
|
@@ -9647,7 +9707,7 @@ function AiTreeRenderer({
|
|
|
9647
9707
|
}
|
|
9648
9708
|
const resolvedBrand = withThemeFonts(brand ?? AI_DEFAULT_BRAND);
|
|
9649
9709
|
const band = (tree.settings ?? {}).sectionBackground === "accent" ? accentBandContext(resolvedBrand) : null;
|
|
9650
|
-
const blockBrand = band?.brand ?? resolvedBrand;
|
|
9710
|
+
const blockBrand = withLivePalette(band?.brand ?? resolvedBrand, resolvedBrand);
|
|
9651
9711
|
const placeholderMap = buildPlaceholderMap(tree);
|
|
9652
9712
|
const hasOverlapBackground = tree.scaffold === "overlay" && tree.rows.some(
|
|
9653
9713
|
(row) => (row.blocks ?? []).some((b) => b.type === "group" && str(b.slots?.layout) === "overlap")
|
|
@@ -9663,7 +9723,7 @@ function AiTreeRenderer({
|
|
|
9663
9723
|
// standalone resolve), so generated galleries, image rows, and overlay backgrounds arrive with
|
|
9664
9724
|
// photos instead of grey boxes.
|
|
9665
9725
|
resolveMedia: (ref) => resolveMedia?.(ref) ?? placeholderMap[ref] ?? resolvePlaceholderRef(ref),
|
|
9666
|
-
cardSurface:
|
|
9726
|
+
cardSurface: resolvedBrand.palette.light.toUpperCase() === AI_DEFAULT_BRAND.palette.light.toUpperCase() ? "#ECECEB" : `color-mix(in srgb, ${blockBrand.palette.light} 90%, ${blockBrand.palette.dark})`,
|
|
9667
9727
|
keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null,
|
|
9668
9728
|
sectionAlignment: (tree.settings ?? {}).alignment === "center" ? "center" : "left",
|
|
9669
9729
|
buttonStyle,
|
|
@@ -9680,7 +9740,7 @@ function AiTreeRenderer({
|
|
|
9680
9740
|
const backgroundUrl = isOverlay && settings.backgroundMedia ? ctx.resolveMedia(settings.backgroundMedia) : null;
|
|
9681
9741
|
const bgAttrs = ctx.keyFor && isOverlay && settings.backgroundMedia ? { "data-ohw-key": ctx.keyFor("settings.backgroundMedia"), "data-ohw-editable": "bg-image" } : {};
|
|
9682
9742
|
const toneBackground = (() => {
|
|
9683
|
-
const { dark, primary, light } =
|
|
9743
|
+
const { dark, primary, light } = blockBrand.palette;
|
|
9684
9744
|
switch (settings.sectionBackground) {
|
|
9685
9745
|
case "surface":
|
|
9686
9746
|
return `color-mix(in srgb, ${light} 94%, ${dark})`;
|
|
@@ -9803,14 +9863,15 @@ function AiFooterRenderer({
|
|
|
9803
9863
|
if (!isRenderableFooterTree(tree)) {
|
|
9804
9864
|
return null;
|
|
9805
9865
|
}
|
|
9806
|
-
const
|
|
9866
|
+
const hexBrand = withThemeFonts(brand ?? AI_DEFAULT_BRAND);
|
|
9867
|
+
const resolvedBrand = withLivePalette(hexBrand, brand ?? AI_DEFAULT_BRAND);
|
|
9807
9868
|
const bandBg = surface?.background ?? resolvedBrand.palette.dark;
|
|
9808
9869
|
const bandText = surface?.text ?? resolvedBrand.palette.light;
|
|
9809
9870
|
const onDark = surface ? isDarkColor(surface.background) : true;
|
|
9810
9871
|
const ctx = {
|
|
9811
9872
|
brand: resolvedBrand,
|
|
9812
9873
|
resolveMedia: (ref) => resolveMedia?.(ref) ?? resolvePlaceholderRef(ref),
|
|
9813
|
-
cardSurface:
|
|
9874
|
+
cardSurface: hexBrand.palette.light.toUpperCase() === AI_DEFAULT_BRAND.palette.light.toUpperCase() ? "#ECECEB" : `color-mix(in srgb, ${resolvedBrand.palette.light} 90%, ${resolvedBrand.palette.dark})`,
|
|
9814
9875
|
keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null,
|
|
9815
9876
|
logoUrl: logoUrl ?? null,
|
|
9816
9877
|
resolvePageHref
|
|
@@ -10386,10 +10447,9 @@ function syncSoftRemovedGenerated() {
|
|
|
10386
10447
|
}
|
|
10387
10448
|
function applyAiSectionsToDom(state, options) {
|
|
10388
10449
|
if (typeof document === "undefined") return;
|
|
10389
|
-
const brandOverride = deriveBrandOverride();
|
|
10390
10450
|
const templateBrand = deriveTemplateBrand();
|
|
10391
10451
|
const templateButtonStyle = deriveTemplateButtonStyle();
|
|
10392
|
-
const brandKey =
|
|
10452
|
+
const brandKey = JSON.stringify(getAppliedBrand() ?? deriveBrandOverride() ?? null);
|
|
10393
10453
|
const pagePath = window.location.pathname;
|
|
10394
10454
|
const pageSections = state.sections.filter((entry) => (entry.path ?? "/") === pagePath);
|
|
10395
10455
|
const activeIds = new Set(pageSections.map((entry) => entry.id));
|
|
@@ -10433,7 +10493,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
10433
10493
|
AiTreeRenderer,
|
|
10434
10494
|
{
|
|
10435
10495
|
tree: entry.tree,
|
|
10436
|
-
brand:
|
|
10496
|
+
brand: brandForGenerated(deriveBrandOverride() ?? entry.brand ?? options?.brand ?? templateBrand),
|
|
10437
10497
|
buttonStyle: templateButtonStyle,
|
|
10438
10498
|
resolveMedia,
|
|
10439
10499
|
editKeyPrefix: `ai.${entry.id}`
|
|
@@ -10599,7 +10659,7 @@ function applyAiFooterToDom(state, content) {
|
|
|
10599
10659
|
const templateFooter = findTemplateFooter();
|
|
10600
10660
|
captureTemplateFooterSurface(templateFooter);
|
|
10601
10661
|
const surface = capturedSurface ?? null;
|
|
10602
|
-
const brand = mountOptions.brand ?? deriveTemplateBrand();
|
|
10662
|
+
const brand = brandForGenerated(mountOptions.brand ?? deriveTemplateBrand());
|
|
10603
10663
|
const logoUrl = resolveLogoFromContent(content, templateFooter);
|
|
10604
10664
|
const serialized = JSON.stringify(state) + JSON.stringify(brand ?? null) + (logoUrl ?? "") + JSON.stringify(surface) + JSON.stringify(defaultLegal());
|
|
10605
10665
|
if (mounted2 && mounted2.serialized === serialized && mounted2.container.isConnected) {
|
|
@@ -27325,7 +27385,7 @@ function OhhwellsBridge() {
|
|
|
27325
27385
|
if (!subdomain) return {};
|
|
27326
27386
|
return contentCache.get(subdomain) ?? {};
|
|
27327
27387
|
};
|
|
27328
|
-
const observeRoots = () => [document.querySelector("nav"),
|
|
27388
|
+
const observeRoots = () => [document.querySelector("nav"), getFooterRoot()].filter(
|
|
27329
27389
|
(el) => Boolean(el)
|
|
27330
27390
|
);
|
|
27331
27391
|
const roots = observeRoots();
|
|
@@ -27781,7 +27841,7 @@ function OhhwellsBridge() {
|
|
|
27781
27841
|
{
|
|
27782
27842
|
const formEl = getFormElement(target);
|
|
27783
27843
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
27784
|
-
if (formEl && formKeyOf(formEl) && !onSuccessText) {
|
|
27844
|
+
if (formEl && formKeyOf(formEl) && !onSuccessText && !isCtaButton(target)) {
|
|
27785
27845
|
const fieldEl = getFieldWrapper(target);
|
|
27786
27846
|
if (fieldEl) {
|
|
27787
27847
|
const label = target.closest("label");
|
|
@@ -29690,6 +29750,7 @@ function OhhwellsBridge() {
|
|
|
29690
29750
|
brandKitRef.current = value;
|
|
29691
29751
|
applyBrandToDom(parseBrandKit(value));
|
|
29692
29752
|
if (aiSectionsRef.current) applyAiSectionsToDom(parseAiSectionsState(aiSectionsRef.current));
|
|
29753
|
+
applyAiFooterFromContent(editContentRef.current);
|
|
29693
29754
|
applyStylesToDom(parseStyleStore(stylesRef.current));
|
|
29694
29755
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: BRAND_KIT_KEY, text: value }] });
|
|
29695
29756
|
postToParentRef.current({ type: "ow:ai-brand-applied", previous, value });
|