@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.js
CHANGED
|
@@ -2827,14 +2827,22 @@ function isInactiveFooterChrome(el) {
|
|
|
2827
2827
|
if (footer && footer.style.display === "none") return true;
|
|
2828
2828
|
return false;
|
|
2829
2829
|
}
|
|
2830
|
+
function isIncidentalFooter(el) {
|
|
2831
|
+
return Boolean(el.closest("blockquote, article, figure"));
|
|
2832
|
+
}
|
|
2830
2833
|
function getFooterRoot() {
|
|
2831
2834
|
const ai = document.querySelector("footer[data-ai-footer]");
|
|
2832
2835
|
if (ai) return ai;
|
|
2833
2836
|
for (const el of Array.from(
|
|
2834
|
-
document.querySelectorAll('footer[data-ohw-section="footer"]
|
|
2837
|
+
document.querySelectorAll('footer[data-ohw-section="footer"]')
|
|
2835
2838
|
)) {
|
|
2839
|
+
if (isInactiveFooterChrome(el)) continue;
|
|
2840
|
+
return el;
|
|
2841
|
+
}
|
|
2842
|
+
for (const el of Array.from(document.querySelectorAll("footer"))) {
|
|
2836
2843
|
if (el.hasAttribute("data-ai-footer")) continue;
|
|
2837
2844
|
if (isInactiveFooterChrome(el)) continue;
|
|
2845
|
+
if (isIncidentalFooter(el)) continue;
|
|
2838
2846
|
return el;
|
|
2839
2847
|
}
|
|
2840
2848
|
return null;
|
|
@@ -3245,8 +3253,8 @@ function buildFooterLink(colIndex, itemIndex, href, label, template) {
|
|
|
3245
3253
|
return anchor;
|
|
3246
3254
|
}
|
|
3247
3255
|
function footerColumnExistsInDom(colIndex) {
|
|
3248
|
-
const
|
|
3249
|
-
return
|
|
3256
|
+
const scope = getFooterLinksContainer() ?? getFooterRoot() ?? document;
|
|
3257
|
+
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;
|
|
3250
3258
|
}
|
|
3251
3259
|
function getFooterLinkTemplate() {
|
|
3252
3260
|
for (const col of listFooterColumns()) {
|
|
@@ -6263,6 +6271,20 @@ function applyBrandChrome(content) {
|
|
|
6263
6271
|
|
|
6264
6272
|
// src/lib/brand-kit.ts
|
|
6265
6273
|
var BRAND_KIT_KEY = "__ohw_brand";
|
|
6274
|
+
var appliedPalette = null;
|
|
6275
|
+
var appliedFonts = null;
|
|
6276
|
+
function getAppliedBrand() {
|
|
6277
|
+
if (!appliedPalette) return null;
|
|
6278
|
+
return appliedFonts ? { palette: appliedPalette, fonts: appliedFonts } : { palette: appliedPalette };
|
|
6279
|
+
}
|
|
6280
|
+
function brandForGenerated(fallback) {
|
|
6281
|
+
const applied = getAppliedBrand();
|
|
6282
|
+
if (!applied) return fallback ?? void 0;
|
|
6283
|
+
return {
|
|
6284
|
+
palette: applied.palette,
|
|
6285
|
+
fonts: applied.fonts ?? fallback?.fonts ?? AI_DEFAULT_BRAND.fonts
|
|
6286
|
+
};
|
|
6287
|
+
}
|
|
6266
6288
|
var BRAND_VAR_PREFIX = "--ohw-brand-";
|
|
6267
6289
|
var BRAND_VAR_NAMES = ["primary", "accent", "light", "dark", "surface", "border", "muted"].map(
|
|
6268
6290
|
(role) => `${BRAND_VAR_PREFIX}${role}`
|
|
@@ -6566,6 +6588,8 @@ function loadCustomFonts(fonts) {
|
|
|
6566
6588
|
function applyBrandToDom(kit) {
|
|
6567
6589
|
const root = document.documentElement;
|
|
6568
6590
|
if (!kit) {
|
|
6591
|
+
appliedPalette = null;
|
|
6592
|
+
appliedFonts = null;
|
|
6569
6593
|
for (const name of [...BRAND_VAR_NAMES, ...LEGACY_BRAND_VAR_NAMES, ...BUTTON_VAR_NAMES]) {
|
|
6570
6594
|
root.style.removeProperty(name);
|
|
6571
6595
|
}
|
|
@@ -6579,11 +6603,16 @@ function applyBrandToDom(kit) {
|
|
|
6579
6603
|
const applyFonts = kit.touched ? kit.touched.fonts === true : true;
|
|
6580
6604
|
if (kit.palette) {
|
|
6581
6605
|
if (applyPalette) {
|
|
6606
|
+
appliedPalette = kit.palette;
|
|
6582
6607
|
for (const [name, value] of Object.entries(brandColorVars(kit.palette))) root.style.setProperty(name, value);
|
|
6583
6608
|
} else {
|
|
6609
|
+
appliedPalette = null;
|
|
6584
6610
|
for (const name of [...BRAND_VAR_NAMES, ...LEGACY_BRAND_VAR_NAMES]) root.style.removeProperty(name);
|
|
6585
6611
|
}
|
|
6586
6612
|
}
|
|
6613
|
+
if (kit.fonts) {
|
|
6614
|
+
appliedFonts = applyFonts ? kit.fonts : null;
|
|
6615
|
+
}
|
|
6587
6616
|
if (kit.buttons) {
|
|
6588
6617
|
for (const name of BUTTON_VAR_NAMES) root.style.removeProperty(name);
|
|
6589
6618
|
for (const [name, value] of Object.entries(buttonStyleVars({ ...kit, buttons: kit.buttons }))) root.style.setProperty(name, value);
|
|
@@ -7116,6 +7145,35 @@ function withThemeFonts(brand) {
|
|
|
7116
7145
|
}
|
|
7117
7146
|
};
|
|
7118
7147
|
}
|
|
7148
|
+
function liveBrandColor(role, fallback) {
|
|
7149
|
+
if (role === "dark") {
|
|
7150
|
+
return `var(--brand-text, var(--ohw-brand-dark, var(--color-dark, ${fallback})))`;
|
|
7151
|
+
}
|
|
7152
|
+
if (role === "light") {
|
|
7153
|
+
return `var(--brand-background, var(--ohw-brand-light, var(--color-light, ${fallback})))`;
|
|
7154
|
+
}
|
|
7155
|
+
return `var(--brand-${role}, var(--ohw-brand-${role}, var(--color-${role}, ${fallback})))`;
|
|
7156
|
+
}
|
|
7157
|
+
function withLivePalette(brand, source) {
|
|
7158
|
+
const sourceOf = (color) => {
|
|
7159
|
+
const value = color.trim().toLowerCase();
|
|
7160
|
+
const entries = Object.entries(source.palette);
|
|
7161
|
+
return entries.find(([, hex]) => hex.trim().toLowerCase() === value)?.[0] ?? null;
|
|
7162
|
+
};
|
|
7163
|
+
const map = (color) => {
|
|
7164
|
+
const role = sourceOf(color);
|
|
7165
|
+
return role ? liveBrandColor(role, source.palette[role]) : color;
|
|
7166
|
+
};
|
|
7167
|
+
return {
|
|
7168
|
+
...brand,
|
|
7169
|
+
palette: {
|
|
7170
|
+
dark: map(brand.palette.dark),
|
|
7171
|
+
primary: map(brand.palette.primary),
|
|
7172
|
+
accent: map(brand.palette.accent),
|
|
7173
|
+
light: map(brand.palette.light)
|
|
7174
|
+
}
|
|
7175
|
+
};
|
|
7176
|
+
}
|
|
7119
7177
|
function footerLogoStyle(fallbackFont, fallbackColor) {
|
|
7120
7178
|
return {
|
|
7121
7179
|
fontFamily: `var(--brand-font-heading, var(--font-heading, var(--font-display, ${quotedFont(fallbackFont)})))`,
|
|
@@ -7333,7 +7391,7 @@ function hexContrast(a, b) {
|
|
|
7333
7391
|
function primaryButtonLabel(brand) {
|
|
7334
7392
|
const darkC = hexContrast(brand.palette.primary, brand.palette.dark);
|
|
7335
7393
|
const lightC = hexContrast(brand.palette.primary, AI_TREE_TOKENS.textPrimaryForeground);
|
|
7336
|
-
if (darkC === null || lightC === null) return AI_TREE_TOKENS.textPrimaryForeground
|
|
7394
|
+
if (darkC === null || lightC === null) return `var(--brand-on-primary, ${AI_TREE_TOKENS.textPrimaryForeground})`;
|
|
7337
7395
|
return darkC > lightC ? brand.palette.dark : AI_TREE_TOKENS.textPrimaryForeground;
|
|
7338
7396
|
}
|
|
7339
7397
|
function accentBandContext(brand) {
|
|
@@ -7357,7 +7415,11 @@ function readableForeground(bg, brand) {
|
|
|
7357
7415
|
return darkC > lightC ? brand.palette.dark : AI_TREE_TOKENS.textPrimaryForeground;
|
|
7358
7416
|
}
|
|
7359
7417
|
function hexWithAlpha(hex, alpha) {
|
|
7360
|
-
const
|
|
7418
|
+
const value = hex.trim();
|
|
7419
|
+
if (value.startsWith("var(") || value.startsWith("color-mix(")) {
|
|
7420
|
+
return `color-mix(in srgb, ${value} ${Math.round(alpha * 100)}%, transparent)`;
|
|
7421
|
+
}
|
|
7422
|
+
const m = /^#([0-9a-f]{6})$/i.exec(value);
|
|
7361
7423
|
if (!m) return hex;
|
|
7362
7424
|
const r2 = parseInt(m[1].slice(0, 2), 16);
|
|
7363
7425
|
const g = parseInt(m[1].slice(2, 4), 16);
|
|
@@ -7630,12 +7692,10 @@ function ButtonEl({
|
|
|
7630
7692
|
cursor: "pointer",
|
|
7631
7693
|
whiteSpace: "nowrap",
|
|
7632
7694
|
...buttonShellStyle(ctx, variant, fullWidth),
|
|
7633
|
-
...tokenColorStyle ?? (secondary ? { border: `1px solid ${secondaryColor ?? ctx.brand.palette.dark}`, color: secondaryColor ?? ctx.brand.palette.dark } :
|
|
7634
|
-
|
|
7635
|
-
|
|
7636
|
-
|
|
7637
|
-
!ctx.buttonLabel && ctx.buttonStyle?.background ? { background: ctx.buttonStyle.background, color: ctx.buttonStyle.color } : { background: ctx.brand.palette.primary, color: ctx.buttonLabel ?? primaryButtonLabel(ctx.brand) }
|
|
7638
|
-
))
|
|
7695
|
+
...tokenColorStyle ?? (secondary ? { border: `1px solid ${secondaryColor ?? ctx.brand.palette.dark}`, color: secondaryColor ?? ctx.brand.palette.dark } : {
|
|
7696
|
+
background: ctx.brand.palette.primary,
|
|
7697
|
+
color: ctx.buttonLabel ?? primaryButtonLabel(ctx.brand)
|
|
7698
|
+
})
|
|
7639
7699
|
},
|
|
7640
7700
|
children: /* @__PURE__ */ jsx("span", { ...path ? textAttrs(ctx, `${path}.label`) : {}, children: str(slots.label) })
|
|
7641
7701
|
}
|
|
@@ -9480,10 +9540,10 @@ function renderNode(node, ctx, path, ambientAlign) {
|
|
|
9480
9540
|
...buttonShellStyle(ctx, "primary"),
|
|
9481
9541
|
// Brand-styled: the template button's measured fill/label pair off-band, else
|
|
9482
9542
|
// primary fill with a brand-derived label so it reads on custom palettes.
|
|
9483
|
-
...buttonColorStyle(ctx, "primary") ??
|
|
9543
|
+
...buttonColorStyle(ctx, "primary") ?? {
|
|
9484
9544
|
background: ctx.brand.palette.primary,
|
|
9485
9545
|
color: ctx.buttonLabel ?? primaryButtonLabel(ctx.brand)
|
|
9486
|
-
}
|
|
9546
|
+
}
|
|
9487
9547
|
},
|
|
9488
9548
|
children: /* @__PURE__ */ jsx("span", { ...textAttrs(ctx, `${path}.c${i}.label`), children: str(cs.label) })
|
|
9489
9549
|
},
|
|
@@ -9527,7 +9587,7 @@ function AiTreeRenderer({
|
|
|
9527
9587
|
}
|
|
9528
9588
|
const resolvedBrand = withThemeFonts(brand ?? AI_DEFAULT_BRAND);
|
|
9529
9589
|
const band = (tree.settings ?? {}).sectionBackground === "accent" ? accentBandContext(resolvedBrand) : null;
|
|
9530
|
-
const blockBrand = band?.brand ?? resolvedBrand;
|
|
9590
|
+
const blockBrand = withLivePalette(band?.brand ?? resolvedBrand, resolvedBrand);
|
|
9531
9591
|
const placeholderMap = buildPlaceholderMap(tree);
|
|
9532
9592
|
const hasOverlapBackground = tree.scaffold === "overlay" && tree.rows.some(
|
|
9533
9593
|
(row) => (row.blocks ?? []).some((b) => b.type === "group" && str(b.slots?.layout) === "overlap")
|
|
@@ -9543,7 +9603,7 @@ function AiTreeRenderer({
|
|
|
9543
9603
|
// standalone resolve), so generated galleries, image rows, and overlay backgrounds arrive with
|
|
9544
9604
|
// photos instead of grey boxes.
|
|
9545
9605
|
resolveMedia: (ref) => resolveMedia?.(ref) ?? placeholderMap[ref] ?? resolvePlaceholderRef(ref),
|
|
9546
|
-
cardSurface:
|
|
9606
|
+
cardSurface: resolvedBrand.palette.light.toUpperCase() === AI_DEFAULT_BRAND.palette.light.toUpperCase() ? "#ECECEB" : `color-mix(in srgb, ${blockBrand.palette.light} 90%, ${blockBrand.palette.dark})`,
|
|
9547
9607
|
keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null,
|
|
9548
9608
|
sectionAlignment: (tree.settings ?? {}).alignment === "center" ? "center" : "left",
|
|
9549
9609
|
buttonStyle,
|
|
@@ -9560,7 +9620,7 @@ function AiTreeRenderer({
|
|
|
9560
9620
|
const backgroundUrl = isOverlay && settings.backgroundMedia ? ctx.resolveMedia(settings.backgroundMedia) : null;
|
|
9561
9621
|
const bgAttrs = ctx.keyFor && isOverlay && settings.backgroundMedia ? { "data-ohw-key": ctx.keyFor("settings.backgroundMedia"), "data-ohw-editable": "bg-image" } : {};
|
|
9562
9622
|
const toneBackground = (() => {
|
|
9563
|
-
const { dark, primary, light } =
|
|
9623
|
+
const { dark, primary, light } = blockBrand.palette;
|
|
9564
9624
|
switch (settings.sectionBackground) {
|
|
9565
9625
|
case "surface":
|
|
9566
9626
|
return `color-mix(in srgb, ${light} 94%, ${dark})`;
|
|
@@ -9681,14 +9741,15 @@ function AiFooterRenderer({
|
|
|
9681
9741
|
if (!isRenderableFooterTree(tree)) {
|
|
9682
9742
|
return null;
|
|
9683
9743
|
}
|
|
9684
|
-
const
|
|
9744
|
+
const hexBrand = withThemeFonts(brand ?? AI_DEFAULT_BRAND);
|
|
9745
|
+
const resolvedBrand = withLivePalette(hexBrand, brand ?? AI_DEFAULT_BRAND);
|
|
9685
9746
|
const bandBg = surface?.background ?? resolvedBrand.palette.dark;
|
|
9686
9747
|
const bandText = surface?.text ?? resolvedBrand.palette.light;
|
|
9687
9748
|
const onDark = surface ? isDarkColor(surface.background) : true;
|
|
9688
9749
|
const ctx = {
|
|
9689
9750
|
brand: resolvedBrand,
|
|
9690
9751
|
resolveMedia: (ref) => resolveMedia?.(ref) ?? resolvePlaceholderRef(ref),
|
|
9691
|
-
cardSurface:
|
|
9752
|
+
cardSurface: hexBrand.palette.light.toUpperCase() === AI_DEFAULT_BRAND.palette.light.toUpperCase() ? "#ECECEB" : `color-mix(in srgb, ${resolvedBrand.palette.light} 90%, ${resolvedBrand.palette.dark})`,
|
|
9692
9753
|
keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null,
|
|
9693
9754
|
logoUrl: logoUrl ?? null,
|
|
9694
9755
|
resolvePageHref
|
|
@@ -10264,10 +10325,9 @@ function syncSoftRemovedGenerated() {
|
|
|
10264
10325
|
}
|
|
10265
10326
|
function applyAiSectionsToDom(state, options) {
|
|
10266
10327
|
if (typeof document === "undefined") return;
|
|
10267
|
-
const brandOverride = deriveBrandOverride();
|
|
10268
10328
|
const templateBrand = deriveTemplateBrand();
|
|
10269
10329
|
const templateButtonStyle = deriveTemplateButtonStyle();
|
|
10270
|
-
const brandKey =
|
|
10330
|
+
const brandKey = JSON.stringify(getAppliedBrand() ?? deriveBrandOverride() ?? null);
|
|
10271
10331
|
const pagePath = window.location.pathname;
|
|
10272
10332
|
const pageSections = state.sections.filter((entry) => (entry.path ?? "/") === pagePath);
|
|
10273
10333
|
const activeIds = new Set(pageSections.map((entry) => entry.id));
|
|
@@ -10310,7 +10370,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
10310
10370
|
AiTreeRenderer,
|
|
10311
10371
|
{
|
|
10312
10372
|
tree: entry.tree,
|
|
10313
|
-
brand:
|
|
10373
|
+
brand: brandForGenerated(deriveBrandOverride() ?? entry.brand ?? options?.brand ?? templateBrand),
|
|
10314
10374
|
buttonStyle: templateButtonStyle,
|
|
10315
10375
|
resolveMedia,
|
|
10316
10376
|
editKeyPrefix: `ai.${entry.id}`
|
|
@@ -10476,7 +10536,7 @@ function applyAiFooterToDom(state, content) {
|
|
|
10476
10536
|
const templateFooter = findTemplateFooter();
|
|
10477
10537
|
captureTemplateFooterSurface(templateFooter);
|
|
10478
10538
|
const surface = capturedSurface ?? null;
|
|
10479
|
-
const brand = mountOptions.brand ?? deriveTemplateBrand();
|
|
10539
|
+
const brand = brandForGenerated(mountOptions.brand ?? deriveTemplateBrand());
|
|
10480
10540
|
const logoUrl = resolveLogoFromContent(content, templateFooter);
|
|
10481
10541
|
const serialized = JSON.stringify(state) + JSON.stringify(brand ?? null) + (logoUrl ?? "") + JSON.stringify(surface) + JSON.stringify(defaultLegal());
|
|
10482
10542
|
if (mounted2 && mounted2.serialized === serialized && mounted2.container.isConnected) {
|
|
@@ -27195,7 +27255,7 @@ function OhhwellsBridge() {
|
|
|
27195
27255
|
if (!subdomain) return {};
|
|
27196
27256
|
return contentCache.get(subdomain) ?? {};
|
|
27197
27257
|
};
|
|
27198
|
-
const observeRoots = () => [document.querySelector("nav"),
|
|
27258
|
+
const observeRoots = () => [document.querySelector("nav"), getFooterRoot()].filter(
|
|
27199
27259
|
(el) => Boolean(el)
|
|
27200
27260
|
);
|
|
27201
27261
|
const roots = observeRoots();
|
|
@@ -27666,7 +27726,7 @@ function OhhwellsBridge() {
|
|
|
27666
27726
|
{
|
|
27667
27727
|
const formEl = getFormElement(target);
|
|
27668
27728
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
27669
|
-
if (formEl && formKeyOf(formEl) && !onSuccessText) {
|
|
27729
|
+
if (formEl && formKeyOf(formEl) && !onSuccessText && !isCtaButton(target)) {
|
|
27670
27730
|
const fieldEl = getFieldWrapper(target);
|
|
27671
27731
|
if (fieldEl) {
|
|
27672
27732
|
const label = target.closest("label");
|
|
@@ -29559,6 +29619,7 @@ function OhhwellsBridge() {
|
|
|
29559
29619
|
brandKitRef.current = value;
|
|
29560
29620
|
applyBrandToDom(parseBrandKit(value));
|
|
29561
29621
|
if (aiSectionsRef.current) applyAiSectionsToDom(parseAiSectionsState(aiSectionsRef.current));
|
|
29622
|
+
applyAiFooterFromContent(editContentRef.current);
|
|
29562
29623
|
applyStylesToDom(parseStyleStore(stylesRef.current));
|
|
29563
29624
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: BRAND_KIT_KEY, text: value }] });
|
|
29564
29625
|
postToParentRef.current({ type: "ow:ai-brand-applied", previous, value });
|
|
@@ -30931,7 +30992,7 @@ function OhhwellsBridge() {
|
|
|
30931
30992
|
postToParent2({
|
|
30932
30993
|
type: "ow:ready",
|
|
30933
30994
|
version: "1",
|
|
30934
|
-
bridgeVersion: "0.1.
|
|
30995
|
+
bridgeVersion: "0.1.139",
|
|
30935
30996
|
path: pathname,
|
|
30936
30997
|
nodes: collectEditableNodes(editContentRef.current),
|
|
30937
30998
|
sections
|