@ohhwells/bridge 0.1.139 → 0.1.140
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 +86 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +86 -25
- 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)})))`,
|
|
@@ -7425,7 +7483,7 @@ function hexContrast(a, b) {
|
|
|
7425
7483
|
function primaryButtonLabel(brand) {
|
|
7426
7484
|
const darkC = hexContrast(brand.palette.primary, brand.palette.dark);
|
|
7427
7485
|
const lightC = hexContrast(brand.palette.primary, AI_TREE_TOKENS.textPrimaryForeground);
|
|
7428
|
-
if (darkC === null || lightC === null) return AI_TREE_TOKENS.textPrimaryForeground
|
|
7486
|
+
if (darkC === null || lightC === null) return `var(--brand-on-primary, ${AI_TREE_TOKENS.textPrimaryForeground})`;
|
|
7429
7487
|
return darkC > lightC ? brand.palette.dark : AI_TREE_TOKENS.textPrimaryForeground;
|
|
7430
7488
|
}
|
|
7431
7489
|
function accentBandContext(brand) {
|
|
@@ -7449,7 +7507,11 @@ function readableForeground(bg, brand) {
|
|
|
7449
7507
|
return darkC > lightC ? brand.palette.dark : AI_TREE_TOKENS.textPrimaryForeground;
|
|
7450
7508
|
}
|
|
7451
7509
|
function hexWithAlpha(hex, alpha) {
|
|
7452
|
-
const
|
|
7510
|
+
const value = hex.trim();
|
|
7511
|
+
if (value.startsWith("var(") || value.startsWith("color-mix(")) {
|
|
7512
|
+
return `color-mix(in srgb, ${value} ${Math.round(alpha * 100)}%, transparent)`;
|
|
7513
|
+
}
|
|
7514
|
+
const m = /^#([0-9a-f]{6})$/i.exec(value);
|
|
7453
7515
|
if (!m) return hex;
|
|
7454
7516
|
const r2 = parseInt(m[1].slice(0, 2), 16);
|
|
7455
7517
|
const g = parseInt(m[1].slice(2, 4), 16);
|
|
@@ -7722,12 +7784,10 @@ function ButtonEl({
|
|
|
7722
7784
|
cursor: "pointer",
|
|
7723
7785
|
whiteSpace: "nowrap",
|
|
7724
7786
|
...buttonShellStyle(ctx, variant, fullWidth),
|
|
7725
|
-
...tokenColorStyle ?? (secondary ? { border: `1px solid ${secondaryColor ?? ctx.brand.palette.dark}`, color: secondaryColor ?? ctx.brand.palette.dark } :
|
|
7726
|
-
|
|
7727
|
-
|
|
7728
|
-
|
|
7729
|
-
!ctx.buttonLabel && ctx.buttonStyle?.background ? { background: ctx.buttonStyle.background, color: ctx.buttonStyle.color } : { background: ctx.brand.palette.primary, color: ctx.buttonLabel ?? primaryButtonLabel(ctx.brand) }
|
|
7730
|
-
))
|
|
7787
|
+
...tokenColorStyle ?? (secondary ? { border: `1px solid ${secondaryColor ?? ctx.brand.palette.dark}`, color: secondaryColor ?? ctx.brand.palette.dark } : {
|
|
7788
|
+
background: ctx.brand.palette.primary,
|
|
7789
|
+
color: ctx.buttonLabel ?? primaryButtonLabel(ctx.brand)
|
|
7790
|
+
})
|
|
7731
7791
|
},
|
|
7732
7792
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...path ? textAttrs(ctx, `${path}.label`) : {}, children: str(slots.label) })
|
|
7733
7793
|
}
|
|
@@ -9572,10 +9632,10 @@ function renderNode(node, ctx, path, ambientAlign) {
|
|
|
9572
9632
|
...buttonShellStyle(ctx, "primary"),
|
|
9573
9633
|
// Brand-styled: the template button's measured fill/label pair off-band, else
|
|
9574
9634
|
// primary fill with a brand-derived label so it reads on custom palettes.
|
|
9575
|
-
...buttonColorStyle(ctx, "primary") ??
|
|
9635
|
+
...buttonColorStyle(ctx, "primary") ?? {
|
|
9576
9636
|
background: ctx.brand.palette.primary,
|
|
9577
9637
|
color: ctx.buttonLabel ?? primaryButtonLabel(ctx.brand)
|
|
9578
|
-
}
|
|
9638
|
+
}
|
|
9579
9639
|
},
|
|
9580
9640
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...textAttrs(ctx, `${path}.c${i}.label`), children: str(cs.label) })
|
|
9581
9641
|
},
|
|
@@ -9619,7 +9679,7 @@ function AiTreeRenderer({
|
|
|
9619
9679
|
}
|
|
9620
9680
|
const resolvedBrand = withThemeFonts(brand ?? AI_DEFAULT_BRAND);
|
|
9621
9681
|
const band = (tree.settings ?? {}).sectionBackground === "accent" ? accentBandContext(resolvedBrand) : null;
|
|
9622
|
-
const blockBrand = band?.brand ?? resolvedBrand;
|
|
9682
|
+
const blockBrand = withLivePalette(band?.brand ?? resolvedBrand, resolvedBrand);
|
|
9623
9683
|
const placeholderMap = buildPlaceholderMap(tree);
|
|
9624
9684
|
const hasOverlapBackground = tree.scaffold === "overlay" && tree.rows.some(
|
|
9625
9685
|
(row) => (row.blocks ?? []).some((b) => b.type === "group" && str(b.slots?.layout) === "overlap")
|
|
@@ -9635,7 +9695,7 @@ function AiTreeRenderer({
|
|
|
9635
9695
|
// standalone resolve), so generated galleries, image rows, and overlay backgrounds arrive with
|
|
9636
9696
|
// photos instead of grey boxes.
|
|
9637
9697
|
resolveMedia: (ref) => resolveMedia?.(ref) ?? placeholderMap[ref] ?? resolvePlaceholderRef(ref),
|
|
9638
|
-
cardSurface:
|
|
9698
|
+
cardSurface: resolvedBrand.palette.light.toUpperCase() === AI_DEFAULT_BRAND.palette.light.toUpperCase() ? "#ECECEB" : `color-mix(in srgb, ${blockBrand.palette.light} 90%, ${blockBrand.palette.dark})`,
|
|
9639
9699
|
keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null,
|
|
9640
9700
|
sectionAlignment: (tree.settings ?? {}).alignment === "center" ? "center" : "left",
|
|
9641
9701
|
buttonStyle,
|
|
@@ -9652,7 +9712,7 @@ function AiTreeRenderer({
|
|
|
9652
9712
|
const backgroundUrl = isOverlay && settings.backgroundMedia ? ctx.resolveMedia(settings.backgroundMedia) : null;
|
|
9653
9713
|
const bgAttrs = ctx.keyFor && isOverlay && settings.backgroundMedia ? { "data-ohw-key": ctx.keyFor("settings.backgroundMedia"), "data-ohw-editable": "bg-image" } : {};
|
|
9654
9714
|
const toneBackground = (() => {
|
|
9655
|
-
const { dark, primary, light } =
|
|
9715
|
+
const { dark, primary, light } = blockBrand.palette;
|
|
9656
9716
|
switch (settings.sectionBackground) {
|
|
9657
9717
|
case "surface":
|
|
9658
9718
|
return `color-mix(in srgb, ${light} 94%, ${dark})`;
|
|
@@ -9773,14 +9833,15 @@ function AiFooterRenderer({
|
|
|
9773
9833
|
if (!isRenderableFooterTree(tree)) {
|
|
9774
9834
|
return null;
|
|
9775
9835
|
}
|
|
9776
|
-
const
|
|
9836
|
+
const hexBrand = withThemeFonts(brand ?? AI_DEFAULT_BRAND);
|
|
9837
|
+
const resolvedBrand = withLivePalette(hexBrand, brand ?? AI_DEFAULT_BRAND);
|
|
9777
9838
|
const bandBg = surface?.background ?? resolvedBrand.palette.dark;
|
|
9778
9839
|
const bandText = surface?.text ?? resolvedBrand.palette.light;
|
|
9779
9840
|
const onDark = surface ? isDarkColor(surface.background) : true;
|
|
9780
9841
|
const ctx = {
|
|
9781
9842
|
brand: resolvedBrand,
|
|
9782
9843
|
resolveMedia: (ref) => resolveMedia?.(ref) ?? resolvePlaceholderRef(ref),
|
|
9783
|
-
cardSurface:
|
|
9844
|
+
cardSurface: hexBrand.palette.light.toUpperCase() === AI_DEFAULT_BRAND.palette.light.toUpperCase() ? "#ECECEB" : `color-mix(in srgb, ${resolvedBrand.palette.light} 90%, ${resolvedBrand.palette.dark})`,
|
|
9784
9845
|
keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null,
|
|
9785
9846
|
logoUrl: logoUrl ?? null,
|
|
9786
9847
|
resolvePageHref
|
|
@@ -10356,10 +10417,9 @@ function syncSoftRemovedGenerated() {
|
|
|
10356
10417
|
}
|
|
10357
10418
|
function applyAiSectionsToDom(state, options) {
|
|
10358
10419
|
if (typeof document === "undefined") return;
|
|
10359
|
-
const brandOverride = deriveBrandOverride();
|
|
10360
10420
|
const templateBrand = deriveTemplateBrand();
|
|
10361
10421
|
const templateButtonStyle = deriveTemplateButtonStyle();
|
|
10362
|
-
const brandKey =
|
|
10422
|
+
const brandKey = JSON.stringify(getAppliedBrand() ?? deriveBrandOverride() ?? null);
|
|
10363
10423
|
const pagePath = window.location.pathname;
|
|
10364
10424
|
const pageSections = state.sections.filter((entry) => (entry.path ?? "/") === pagePath);
|
|
10365
10425
|
const activeIds = new Set(pageSections.map((entry) => entry.id));
|
|
@@ -10402,7 +10462,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
10402
10462
|
AiTreeRenderer,
|
|
10403
10463
|
{
|
|
10404
10464
|
tree: entry.tree,
|
|
10405
|
-
brand:
|
|
10465
|
+
brand: brandForGenerated(deriveBrandOverride() ?? entry.brand ?? options?.brand ?? templateBrand),
|
|
10406
10466
|
buttonStyle: templateButtonStyle,
|
|
10407
10467
|
resolveMedia,
|
|
10408
10468
|
editKeyPrefix: `ai.${entry.id}`
|
|
@@ -10568,7 +10628,7 @@ function applyAiFooterToDom(state, content) {
|
|
|
10568
10628
|
const templateFooter = findTemplateFooter();
|
|
10569
10629
|
captureTemplateFooterSurface(templateFooter);
|
|
10570
10630
|
const surface = capturedSurface ?? null;
|
|
10571
|
-
const brand = mountOptions.brand ?? deriveTemplateBrand();
|
|
10631
|
+
const brand = brandForGenerated(mountOptions.brand ?? deriveTemplateBrand());
|
|
10572
10632
|
const logoUrl = resolveLogoFromContent(content, templateFooter);
|
|
10573
10633
|
const serialized = JSON.stringify(state) + JSON.stringify(brand ?? null) + (logoUrl ?? "") + JSON.stringify(surface) + JSON.stringify(defaultLegal());
|
|
10574
10634
|
if (mounted2 && mounted2.serialized === serialized && mounted2.container.isConnected) {
|
|
@@ -27281,7 +27341,7 @@ function OhhwellsBridge() {
|
|
|
27281
27341
|
if (!subdomain) return {};
|
|
27282
27342
|
return contentCache.get(subdomain) ?? {};
|
|
27283
27343
|
};
|
|
27284
|
-
const observeRoots = () => [document.querySelector("nav"),
|
|
27344
|
+
const observeRoots = () => [document.querySelector("nav"), getFooterRoot()].filter(
|
|
27285
27345
|
(el) => Boolean(el)
|
|
27286
27346
|
);
|
|
27287
27347
|
const roots = observeRoots();
|
|
@@ -27752,7 +27812,7 @@ function OhhwellsBridge() {
|
|
|
27752
27812
|
{
|
|
27753
27813
|
const formEl = getFormElement(target);
|
|
27754
27814
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
27755
|
-
if (formEl && formKeyOf(formEl) && !onSuccessText) {
|
|
27815
|
+
if (formEl && formKeyOf(formEl) && !onSuccessText && !isCtaButton(target)) {
|
|
27756
27816
|
const fieldEl = getFieldWrapper(target);
|
|
27757
27817
|
if (fieldEl) {
|
|
27758
27818
|
const label = target.closest("label");
|
|
@@ -29645,6 +29705,7 @@ function OhhwellsBridge() {
|
|
|
29645
29705
|
brandKitRef.current = value;
|
|
29646
29706
|
applyBrandToDom(parseBrandKit(value));
|
|
29647
29707
|
if (aiSectionsRef.current) applyAiSectionsToDom(parseAiSectionsState(aiSectionsRef.current));
|
|
29708
|
+
applyAiFooterFromContent(editContentRef.current);
|
|
29648
29709
|
applyStylesToDom(parseStyleStore(stylesRef.current));
|
|
29649
29710
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: BRAND_KIT_KEY, text: value }] });
|
|
29650
29711
|
postToParentRef.current({ type: "ow:ai-brand-applied", previous, value });
|
|
@@ -31017,7 +31078,7 @@ function OhhwellsBridge() {
|
|
|
31017
31078
|
postToParent2({
|
|
31018
31079
|
type: "ow:ready",
|
|
31019
31080
|
version: "1",
|
|
31020
|
-
bridgeVersion: "0.1.
|
|
31081
|
+
bridgeVersion: "0.1.139",
|
|
31021
31082
|
path: pathname,
|
|
31022
31083
|
nodes: collectEditableNodes(editContentRef.current),
|
|
31023
31084
|
sections
|