@ohhwells/bridge 0.1.138 → 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 +219 -95
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +219 -95
- package/dist/index.js.map +1 -1
- package/dist/pages.cjs +1 -1
- package/dist/pages.cjs.map +1 -1
- package/dist/pages.js +1 -1
- package/dist/pages.js.map +1 -1
- package/dist/styles.css +43 -0
- package/package.json +3 -3
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)})))`,
|
|
@@ -7279,7 +7337,7 @@ var AI_MOBILE_CSS = [
|
|
|
7279
7337
|
// page's first section. Top only (bottom needs no nav clearance); ~96px approximates the
|
|
7280
7338
|
// template nav's own height (measured ~94px) — there's no shared `--ohw-header-h` var to read
|
|
7281
7339
|
// an exact figure from (no live measurement exists), so this is a safe approximation, not a
|
|
7282
|
-
// pixel-exact fit. Horizontal spacing already comes from `data-ai-
|
|
7340
|
+
// pixel-exact fit. Horizontal spacing already comes from `data-ai-section-inner`.
|
|
7283
7341
|
'[data-ai-overlay-clearance] [data-ai-overlap-layer="overlay"]{padding-top:96px}',
|
|
7284
7342
|
// A full-bleed carousel's height is pure arithmetic: it spans the whole window, so 16/9 turns
|
|
7285
7343
|
// window width straight into height. Measured at 16/9 it came out ~90% of the viewport at EVERY
|
|
@@ -7295,8 +7353,10 @@ var AI_MOBILE_CSS = [
|
|
|
7295
7353
|
"[data-ai-section]{overflow-x:hidden}",
|
|
7296
7354
|
// `:not([data-ai-full-bleed])`: this `!important` gutter beat the inline `padding: 0` that a
|
|
7297
7355
|
// full-bleed section's container sets, so a carousel/media hero that is edge-to-edge on desktop
|
|
7298
|
-
// still got a 20px band of section background down both sides on a phone.
|
|
7299
|
-
|
|
7356
|
+
// still got a 20px band of section background down both sides on a phone. The footer's own
|
|
7357
|
+
// container keeps the unguarded rule below — `data-ai-full-bleed` can never appear on it.
|
|
7358
|
+
"[data-ai-section-inner]:not([data-ai-full-bleed]){padding:0 20px !important}",
|
|
7359
|
+
"[data-ai-container]{padding:0 20px !important}",
|
|
7300
7360
|
"[data-ai-row]{display:flex !important;flex-direction:column !important;align-items:stretch !important}",
|
|
7301
7361
|
"[data-ai-cell]{width:100%;min-width:0}",
|
|
7302
7362
|
// The rule above turns every row into a COLUMN flex container on phones, which silently breaks
|
|
@@ -7425,7 +7485,7 @@ function hexContrast(a, b) {
|
|
|
7425
7485
|
function primaryButtonLabel(brand) {
|
|
7426
7486
|
const darkC = hexContrast(brand.palette.primary, brand.palette.dark);
|
|
7427
7487
|
const lightC = hexContrast(brand.palette.primary, AI_TREE_TOKENS.textPrimaryForeground);
|
|
7428
|
-
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})`;
|
|
7429
7489
|
return darkC > lightC ? brand.palette.dark : AI_TREE_TOKENS.textPrimaryForeground;
|
|
7430
7490
|
}
|
|
7431
7491
|
function accentBandContext(brand) {
|
|
@@ -7449,7 +7509,11 @@ function readableForeground(bg, brand) {
|
|
|
7449
7509
|
return darkC > lightC ? brand.palette.dark : AI_TREE_TOKENS.textPrimaryForeground;
|
|
7450
7510
|
}
|
|
7451
7511
|
function hexWithAlpha(hex, alpha) {
|
|
7452
|
-
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);
|
|
7453
7517
|
if (!m) return hex;
|
|
7454
7518
|
const r2 = parseInt(m[1].slice(0, 2), 16);
|
|
7455
7519
|
const g = parseInt(m[1].slice(2, 4), 16);
|
|
@@ -7497,6 +7561,31 @@ function pricingCardEmphasis(featured, ctx, hasBg) {
|
|
|
7497
7561
|
function textAttrs(ctx, path) {
|
|
7498
7562
|
return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
|
|
7499
7563
|
}
|
|
7564
|
+
var AI_RESPONSIVE_CSS = [
|
|
7565
|
+
"@media (max-width: 960px) {",
|
|
7566
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: repeat(2, 1fr) !important; }",
|
|
7567
|
+
' [data-ai-responsive] [data-ai-grid="1"] { grid-template-columns: 1fr !important; }',
|
|
7568
|
+
"}",
|
|
7569
|
+
"@media (max-width: 640px) {",
|
|
7570
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
|
|
7571
|
+
" [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
|
|
7572
|
+
// Group containers flatten to a column on phones; span placements come along for free.
|
|
7573
|
+
// `:not([data-ai-group="overlap"])` for the same reason as the twin pair in AI_MOBILE_CSS — see
|
|
7574
|
+
// the comment there. This sheet's copy is the narrower selector, so without the exemption it
|
|
7575
|
+
// flattens an `overlap` hero below 640px even though the other rule stands down: measured a 390px
|
|
7576
|
+
// viewport with the heading/CTA in flow *under* the image, 219px of section background where the
|
|
7577
|
+
// layered text used to be.
|
|
7578
|
+
' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) { display: flex !important; flex-direction: column !important; }',
|
|
7579
|
+
' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) > * { grid-column: auto !important; }',
|
|
7580
|
+
// `:not([data-ai-full-bleed])` for the same reason as the twin rule in AI_MOBILE_CSS: this one
|
|
7581
|
+
// is narrower (0,2,0 vs 0,1,0) and also `!important`, so without the guard it wins outright and
|
|
7582
|
+
// a full-bleed hero gets its 20px side band back below 640px only — the one width where the
|
|
7583
|
+
// other rule had already been taught to stand down.
|
|
7584
|
+
" [data-ai-responsive] [data-ai-section-inner]:not([data-ai-full-bleed]) { padding-left: 20px !important; padding-right: 20px !important; }",
|
|
7585
|
+
" [data-ai-responsive] { overflow-x: hidden; }",
|
|
7586
|
+
" [data-ai-responsive] img { max-width: 100%; }",
|
|
7587
|
+
"}"
|
|
7588
|
+
].join("\n");
|
|
7500
7589
|
var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
7501
7590
|
function MediaBox({
|
|
7502
7591
|
refValue,
|
|
@@ -7517,9 +7606,9 @@ function MediaBox({
|
|
|
7517
7606
|
const url = refValue ? ctx.resolveMedia(refValue) : null;
|
|
7518
7607
|
const isIcon = /^(lucide|simple):/.test(refValue);
|
|
7519
7608
|
const aspectRatio = aspect && /^\d+:\d+$/.test(aspect) ? aspect.replace(":", " / ") : void 0;
|
|
7520
|
-
const editAttrs = ctx.keyFor && editPath
|
|
7609
|
+
const editAttrs = ctx.keyFor && editPath ? {
|
|
7521
7610
|
"data-ohw-key": ctx.keyFor(editPath),
|
|
7522
|
-
...genericImageEdit ? { "data-ohw-editable": "image" } : {}
|
|
7611
|
+
...isIcon ? { "data-ohw-editable": "icon" } : genericImageEdit ? { "data-ohw-editable": "image" } : {}
|
|
7523
7612
|
} : {};
|
|
7524
7613
|
if (isIcon) {
|
|
7525
7614
|
const Icon = refValue.startsWith("lucide:") ? lucideByName(refValue.slice(7)) : null;
|
|
@@ -7527,6 +7616,7 @@ function MediaBox({
|
|
|
7527
7616
|
"span",
|
|
7528
7617
|
{
|
|
7529
7618
|
"data-ai-icon": refValue,
|
|
7619
|
+
...editAttrs,
|
|
7530
7620
|
style: {
|
|
7531
7621
|
display: "inline-flex",
|
|
7532
7622
|
width: 48,
|
|
@@ -7722,12 +7812,10 @@ function ButtonEl({
|
|
|
7722
7812
|
cursor: "pointer",
|
|
7723
7813
|
whiteSpace: "nowrap",
|
|
7724
7814
|
...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
|
-
))
|
|
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
|
+
})
|
|
7731
7819
|
},
|
|
7732
7820
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...path ? textAttrs(ctx, `${path}.label`) : {}, children: str(slots.label) })
|
|
7733
7821
|
}
|
|
@@ -9034,7 +9122,7 @@ function CollectionBlock({ node, ctx, path }) {
|
|
|
9034
9122
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
9035
9123
|
"div",
|
|
9036
9124
|
{
|
|
9037
|
-
"data-ai-grid":
|
|
9125
|
+
"data-ai-grid": String(itemsPerRow),
|
|
9038
9126
|
"data-ohw-pricing-collection": isPricing ? "" : void 0,
|
|
9039
9127
|
style: {
|
|
9040
9128
|
display: "grid",
|
|
@@ -9294,7 +9382,7 @@ function renderNode(node, ctx, path, ambientAlign) {
|
|
|
9294
9382
|
},
|
|
9295
9383
|
children: [
|
|
9296
9384
|
i > 0 && ctx.heroOverlapFullBleed ? (
|
|
9297
|
-
// The section's `data-ai-
|
|
9385
|
+
// The section's `data-ai-section-inner` gave up its max-width/gutter so the base
|
|
9298
9386
|
// layer (this group's i===0 sibling) can span edge-to-edge — reintroduced here,
|
|
9299
9387
|
// scoped to just the overlay text, so a heading/copy/CTA stack doesn't stretch
|
|
9300
9388
|
// the full section width instead of reading at the usual content width.
|
|
@@ -9572,10 +9660,10 @@ function renderNode(node, ctx, path, ambientAlign) {
|
|
|
9572
9660
|
...buttonShellStyle(ctx, "primary"),
|
|
9573
9661
|
// Brand-styled: the template button's measured fill/label pair off-band, else
|
|
9574
9662
|
// primary fill with a brand-derived label so it reads on custom palettes.
|
|
9575
|
-
...buttonColorStyle(ctx, "primary") ??
|
|
9663
|
+
...buttonColorStyle(ctx, "primary") ?? {
|
|
9576
9664
|
background: ctx.brand.palette.primary,
|
|
9577
9665
|
color: ctx.buttonLabel ?? primaryButtonLabel(ctx.brand)
|
|
9578
|
-
}
|
|
9666
|
+
}
|
|
9579
9667
|
},
|
|
9580
9668
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...textAttrs(ctx, `${path}.c${i}.label`), children: str(cs.label) })
|
|
9581
9669
|
},
|
|
@@ -9619,7 +9707,7 @@ function AiTreeRenderer({
|
|
|
9619
9707
|
}
|
|
9620
9708
|
const resolvedBrand = withThemeFonts(brand ?? AI_DEFAULT_BRAND);
|
|
9621
9709
|
const band = (tree.settings ?? {}).sectionBackground === "accent" ? accentBandContext(resolvedBrand) : null;
|
|
9622
|
-
const blockBrand = band?.brand ?? resolvedBrand;
|
|
9710
|
+
const blockBrand = withLivePalette(band?.brand ?? resolvedBrand, resolvedBrand);
|
|
9623
9711
|
const placeholderMap = buildPlaceholderMap(tree);
|
|
9624
9712
|
const hasOverlapBackground = tree.scaffold === "overlay" && tree.rows.some(
|
|
9625
9713
|
(row) => (row.blocks ?? []).some((b) => b.type === "group" && str(b.slots?.layout) === "overlap")
|
|
@@ -9635,7 +9723,7 @@ function AiTreeRenderer({
|
|
|
9635
9723
|
// standalone resolve), so generated galleries, image rows, and overlay backgrounds arrive with
|
|
9636
9724
|
// photos instead of grey boxes.
|
|
9637
9725
|
resolveMedia: (ref) => resolveMedia?.(ref) ?? placeholderMap[ref] ?? resolvePlaceholderRef(ref),
|
|
9638
|
-
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})`,
|
|
9639
9727
|
keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null,
|
|
9640
9728
|
sectionAlignment: (tree.settings ?? {}).alignment === "center" ? "center" : "left",
|
|
9641
9729
|
buttonStyle,
|
|
@@ -9652,7 +9740,7 @@ function AiTreeRenderer({
|
|
|
9652
9740
|
const backgroundUrl = isOverlay && settings.backgroundMedia ? ctx.resolveMedia(settings.backgroundMedia) : null;
|
|
9653
9741
|
const bgAttrs = ctx.keyFor && isOverlay && settings.backgroundMedia ? { "data-ohw-key": ctx.keyFor("settings.backgroundMedia"), "data-ohw-editable": "bg-image" } : {};
|
|
9654
9742
|
const toneBackground = (() => {
|
|
9655
|
-
const { dark, primary, light } =
|
|
9743
|
+
const { dark, primary, light } = blockBrand.palette;
|
|
9656
9744
|
switch (settings.sectionBackground) {
|
|
9657
9745
|
case "surface":
|
|
9658
9746
|
return `color-mix(in srgb, ${light} 94%, ${dark})`;
|
|
@@ -9687,6 +9775,7 @@ function AiTreeRenderer({
|
|
|
9687
9775
|
...fillHeight ? { "data-ai-fill-height": "" } : {},
|
|
9688
9776
|
...needsOverlayClearance ? { "data-ai-overlay-clearance": "" } : {},
|
|
9689
9777
|
...bgAttrs,
|
|
9778
|
+
"data-ai-responsive": "",
|
|
9690
9779
|
style: {
|
|
9691
9780
|
position: "relative",
|
|
9692
9781
|
padding: `${padCss} 0`,
|
|
@@ -9700,12 +9789,13 @@ function AiTreeRenderer({
|
|
|
9700
9789
|
...fillHeight ? { display: "grid" } : {}
|
|
9701
9790
|
},
|
|
9702
9791
|
children: [
|
|
9703
|
-
|
|
9792
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_RESPONSIVE_CSS }),
|
|
9704
9793
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_MOBILE_CSS }),
|
|
9794
|
+
isOverlay && backgroundUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { position: "absolute", inset: 0, background: `rgba(255,255,255,${overlayAlpha})` } }),
|
|
9705
9795
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
9706
9796
|
"div",
|
|
9707
9797
|
{
|
|
9708
|
-
"data-ai-
|
|
9798
|
+
"data-ai-section-inner": "",
|
|
9709
9799
|
...fullBleedMedia ? { "data-ai-full-bleed": "" } : {},
|
|
9710
9800
|
style: {
|
|
9711
9801
|
position: "relative",
|
|
@@ -9722,7 +9812,7 @@ function AiTreeRenderer({
|
|
|
9722
9812
|
children: tree.rows.map((row, r2) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
9723
9813
|
"div",
|
|
9724
9814
|
{
|
|
9725
|
-
"data-ai-
|
|
9815
|
+
"data-ai-columns": "",
|
|
9726
9816
|
style: {
|
|
9727
9817
|
display: "grid",
|
|
9728
9818
|
gridTemplateColumns: "repeat(12, 1fr)",
|
|
@@ -9773,14 +9863,15 @@ function AiFooterRenderer({
|
|
|
9773
9863
|
if (!isRenderableFooterTree(tree)) {
|
|
9774
9864
|
return null;
|
|
9775
9865
|
}
|
|
9776
|
-
const
|
|
9866
|
+
const hexBrand = withThemeFonts(brand ?? AI_DEFAULT_BRAND);
|
|
9867
|
+
const resolvedBrand = withLivePalette(hexBrand, brand ?? AI_DEFAULT_BRAND);
|
|
9777
9868
|
const bandBg = surface?.background ?? resolvedBrand.palette.dark;
|
|
9778
9869
|
const bandText = surface?.text ?? resolvedBrand.palette.light;
|
|
9779
9870
|
const onDark = surface ? isDarkColor(surface.background) : true;
|
|
9780
9871
|
const ctx = {
|
|
9781
9872
|
brand: resolvedBrand,
|
|
9782
9873
|
resolveMedia: (ref) => resolveMedia?.(ref) ?? resolvePlaceholderRef(ref),
|
|
9783
|
-
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})`,
|
|
9784
9875
|
keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null,
|
|
9785
9876
|
logoUrl: logoUrl ?? null,
|
|
9786
9877
|
resolvePageHref
|
|
@@ -10356,10 +10447,9 @@ function syncSoftRemovedGenerated() {
|
|
|
10356
10447
|
}
|
|
10357
10448
|
function applyAiSectionsToDom(state, options) {
|
|
10358
10449
|
if (typeof document === "undefined") return;
|
|
10359
|
-
const brandOverride = deriveBrandOverride();
|
|
10360
10450
|
const templateBrand = deriveTemplateBrand();
|
|
10361
10451
|
const templateButtonStyle = deriveTemplateButtonStyle();
|
|
10362
|
-
const brandKey =
|
|
10452
|
+
const brandKey = JSON.stringify(getAppliedBrand() ?? deriveBrandOverride() ?? null);
|
|
10363
10453
|
const pagePath = window.location.pathname;
|
|
10364
10454
|
const pageSections = state.sections.filter((entry) => (entry.path ?? "/") === pagePath);
|
|
10365
10455
|
const activeIds = new Set(pageSections.map((entry) => entry.id));
|
|
@@ -10378,9 +10468,10 @@ function applyAiSectionsToDom(state, options) {
|
|
|
10378
10468
|
if (existing && existing.serialized === serialized && existing.container.isConnected) {
|
|
10379
10469
|
continue;
|
|
10380
10470
|
}
|
|
10381
|
-
const isNewMount = !existing || !existing.container.isConnected;
|
|
10382
10471
|
let container = existing?.container;
|
|
10472
|
+
let isNewMount = false;
|
|
10383
10473
|
if (!container || !container.isConnected) {
|
|
10474
|
+
isNewMount = true;
|
|
10384
10475
|
existing?.root.unmount();
|
|
10385
10476
|
container?.remove();
|
|
10386
10477
|
container = document.createElement("div");
|
|
@@ -10402,7 +10493,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
10402
10493
|
AiTreeRenderer,
|
|
10403
10494
|
{
|
|
10404
10495
|
tree: entry.tree,
|
|
10405
|
-
brand:
|
|
10496
|
+
brand: brandForGenerated(deriveBrandOverride() ?? entry.brand ?? options?.brand ?? templateBrand),
|
|
10406
10497
|
buttonStyle: templateButtonStyle,
|
|
10407
10498
|
resolveMedia,
|
|
10408
10499
|
editKeyPrefix: `ai.${entry.id}`
|
|
@@ -10568,7 +10659,7 @@ function applyAiFooterToDom(state, content) {
|
|
|
10568
10659
|
const templateFooter = findTemplateFooter();
|
|
10569
10660
|
captureTemplateFooterSurface(templateFooter);
|
|
10570
10661
|
const surface = capturedSurface ?? null;
|
|
10571
|
-
const brand = mountOptions.brand ?? deriveTemplateBrand();
|
|
10662
|
+
const brand = brandForGenerated(mountOptions.brand ?? deriveTemplateBrand());
|
|
10572
10663
|
const logoUrl = resolveLogoFromContent(content, templateFooter);
|
|
10573
10664
|
const serialized = JSON.stringify(state) + JSON.stringify(brand ?? null) + (logoUrl ?? "") + JSON.stringify(surface) + JSON.stringify(defaultLegal());
|
|
10574
10665
|
if (mounted2 && mounted2.serialized === serialized && mounted2.container.isConnected) {
|
|
@@ -16822,6 +16913,7 @@ function MediaOverlay({
|
|
|
16822
16913
|
(prev) => prev && prev.fullWidth === width && prev.height === height ? prev : { fullWidth: width, height }
|
|
16823
16914
|
);
|
|
16824
16915
|
}, [isVideo]);
|
|
16916
|
+
const replaceLabel = isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image";
|
|
16825
16917
|
const replaceMode = buttonSize ? replaceButtonMode({ width: rect.width, height: rect.height }, buttonSize) : "none";
|
|
16826
16918
|
const box = {
|
|
16827
16919
|
position: "fixed",
|
|
@@ -16920,11 +17012,10 @@ function MediaOverlay({
|
|
|
16920
17012
|
className: "flex items-center justify-center cursor-pointer",
|
|
16921
17013
|
style: {
|
|
16922
17014
|
...box,
|
|
16923
|
-
//
|
|
16924
|
-
//
|
|
16925
|
-
//
|
|
16926
|
-
|
|
16927
|
-
pointerEvents: hover.hasTextOverlap || cueOnly ? "none" : "auto",
|
|
17015
|
+
// Visual only. `pointer-events: auto` on this full-bleed rect covered the navbar
|
|
17016
|
+
// (hero bg includes the absolute TopNav) and swallowed CTA press-drag. Text overlay
|
|
17017
|
+
// and cueOnly also need clicks to fall through — Replace / video controls opt back in.
|
|
17018
|
+
pointerEvents: "none",
|
|
16928
17019
|
// Selected: a firm component ring with no wash, so the image reads as chosen rather
|
|
16929
17020
|
// than hovered. Hover keeps the existing tinted preview.
|
|
16930
17021
|
boxShadow: selected ? "inset 0 0 0 2px var(--color-bridge-primary)" : "inset 0 0 0 1.5px var(--color-bridge-primary)",
|
|
@@ -16951,17 +17042,17 @@ function MediaOverlay({
|
|
|
16951
17042
|
},
|
|
16952
17043
|
children: [
|
|
16953
17044
|
isVideo ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react5.Film, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react5.ImageIcon, { size: 14 }),
|
|
16954
|
-
|
|
17045
|
+
replaceLabel
|
|
16955
17046
|
]
|
|
16956
17047
|
}
|
|
16957
17048
|
),
|
|
16958
|
-
replaceMode
|
|
17049
|
+
showChrome && replaceMode !== "none" && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
16959
17050
|
Button,
|
|
16960
17051
|
{
|
|
16961
17052
|
"data-ohw-media-overlay": "",
|
|
16962
17053
|
variant: "outline",
|
|
16963
17054
|
size: "sm",
|
|
16964
|
-
"aria-label":
|
|
17055
|
+
"aria-label": replaceLabel,
|
|
16965
17056
|
className: "gap-1.5 cursor-pointer hover:bg-background",
|
|
16966
17057
|
style: {
|
|
16967
17058
|
...OVERLAY_BUTTON_STYLE,
|
|
@@ -16984,7 +17075,7 @@ function MediaOverlay({
|
|
|
16984
17075
|
},
|
|
16985
17076
|
children: [
|
|
16986
17077
|
isVideo ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react5.Film, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react5.ImageIcon, { size: 14 }),
|
|
16987
|
-
replaceMode === "full" ?
|
|
17078
|
+
replaceMode === "full" ? replaceLabel : null
|
|
16988
17079
|
]
|
|
16989
17080
|
}
|
|
16990
17081
|
)
|
|
@@ -18290,8 +18381,20 @@ function withPricingCollection(tree, mutate) {
|
|
|
18290
18381
|
const next = JSON.parse(JSON.stringify(tree));
|
|
18291
18382
|
const collection = findPricingCollection(next);
|
|
18292
18383
|
if (!collection || !collection.children) return null;
|
|
18384
|
+
for (const card of collection.children) {
|
|
18385
|
+
if (isPricingCard(card)) upgradeLegacyPricingSlots(card);
|
|
18386
|
+
}
|
|
18293
18387
|
return mutate(collection) ? next : null;
|
|
18294
18388
|
}
|
|
18389
|
+
function upgradeLegacyPricingSlots(card) {
|
|
18390
|
+
const slots = card.slots = card.slots ?? {};
|
|
18391
|
+
if (typeof slots.features === "string") {
|
|
18392
|
+
const rows = pricingFeatureList(card);
|
|
18393
|
+
if (rows.length > 0) slots.features = rows.slice(0, PRICING_FEATURES_MAX);
|
|
18394
|
+
}
|
|
18395
|
+
if (slots.featured === true) slots.featured = { enabled: true };
|
|
18396
|
+
else if (slots.featured === false) delete slots.featured;
|
|
18397
|
+
}
|
|
18295
18398
|
function addPricingTier(tree) {
|
|
18296
18399
|
return withPricingCollection(tree, (collection) => {
|
|
18297
18400
|
const children = collection.children;
|
|
@@ -18413,7 +18516,7 @@ function pricingFeatureList(target) {
|
|
|
18413
18516
|
}));
|
|
18414
18517
|
}
|
|
18415
18518
|
if (typeof raw === "string") {
|
|
18416
|
-
return raw.split(
|
|
18519
|
+
return raw.split(/\n|<br\s*\/?>/i).map((line) => line.replace(/<[^>]+>/g, "").replace(/^[-*•]\s*/, "").trim().slice(0, 120)).filter(Boolean).map((text) => ({ text }));
|
|
18417
18520
|
}
|
|
18418
18521
|
return [];
|
|
18419
18522
|
}
|
|
@@ -21407,6 +21510,7 @@ function shouldUseDevFixtures() {
|
|
|
21407
21510
|
function getLogoElement(el) {
|
|
21408
21511
|
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
21409
21512
|
if (marked) return marked;
|
|
21513
|
+
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
21410
21514
|
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
21411
21515
|
if (!root) return null;
|
|
21412
21516
|
const anchor = el.closest("a");
|
|
@@ -23970,7 +24074,7 @@ function getNavigationSelectionParent(el) {
|
|
|
23970
24074
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
23971
24075
|
return resolveFooterLinksContainerFrom(el);
|
|
23972
24076
|
}
|
|
23973
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
|
|
24077
|
+
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isFooterLinksContainer(el) || isInferredFooterGroup2(el)) {
|
|
23974
24078
|
return getNavigationRoot(el);
|
|
23975
24079
|
}
|
|
23976
24080
|
return null;
|
|
@@ -24192,7 +24296,6 @@ var ICONS = {
|
|
|
24192
24296
|
insertUnorderedList: '<line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/>',
|
|
24193
24297
|
insertOrderedList: '<line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"/>'
|
|
24194
24298
|
};
|
|
24195
|
-
var HEIGHT_SETTLE_DELAYS = [150, 400, 800];
|
|
24196
24299
|
var SELECTION_CHROME_GAP2 = 4;
|
|
24197
24300
|
var TOOLBAR_STROKE_GAP2 = 4;
|
|
24198
24301
|
var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
|
|
@@ -25172,21 +25275,6 @@ function OhhwellsBridge() {
|
|
|
25172
25275
|
const [isItemDragging, setIsItemDragging] = (0, import_react21.useState)(false);
|
|
25173
25276
|
const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react21.useState)(false);
|
|
25174
25277
|
isFooterFrameSelectionRef.current = isFooterFrameSelection;
|
|
25175
|
-
const [floatingPanel, setFloatingPanel] = (0, import_react21.useState)(null);
|
|
25176
|
-
const floatingPanelOpenRef = (0, import_react21.useRef)(false);
|
|
25177
|
-
floatingPanelOpenRef.current = floatingPanel !== null;
|
|
25178
|
-
const floatingPanelRef = (0, import_react21.useRef)(null);
|
|
25179
|
-
floatingPanelRef.current = floatingPanel;
|
|
25180
|
-
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react21.useState)(null);
|
|
25181
|
-
const buttonCollectionDragRef = (0, import_react21.useRef)(null);
|
|
25182
|
-
const buttonDropInsertIndexRef = (0, import_react21.useRef)(null);
|
|
25183
|
-
const [buttonDropSlots, setButtonDropSlots] = (0, import_react21.useState)([]);
|
|
25184
|
-
const [activeButtonDropIndex, setActiveButtonDropIndex] = (0, import_react21.useState)(null);
|
|
25185
|
-
const buttonPointerDragRef = (0, import_react21.useRef)(null);
|
|
25186
|
-
const [buttonStyleTick, setButtonStyleTick] = (0, import_react21.useState)(0);
|
|
25187
|
-
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react21.useState)(null);
|
|
25188
|
-
const [editorViewport, setEditorViewport] = (0, import_react21.useState)("desktop");
|
|
25189
|
-
const [parentScrollSnap, setParentScrollSnap] = (0, import_react21.useState)(null);
|
|
25190
25278
|
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react21.useState)(null);
|
|
25191
25279
|
const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react21.useState)(null);
|
|
25192
25280
|
const footerDragRef = (0, import_react21.useRef)(null);
|
|
@@ -25212,6 +25300,21 @@ function OhhwellsBridge() {
|
|
|
25212
25300
|
const stylesRef = (0, import_react21.useRef)("");
|
|
25213
25301
|
const appliedDrawerRef = (0, import_react21.useRef)(null);
|
|
25214
25302
|
const pendingDeleteUndoRef = (0, import_react21.useRef)(null);
|
|
25303
|
+
const [floatingPanel, setFloatingPanel] = (0, import_react21.useState)(null);
|
|
25304
|
+
const floatingPanelOpenRef = (0, import_react21.useRef)(false);
|
|
25305
|
+
const floatingPanelRef = (0, import_react21.useRef)(null);
|
|
25306
|
+
floatingPanelRef.current = floatingPanel;
|
|
25307
|
+
const setFloatingPanelRef = (0, import_react21.useRef)(setFloatingPanel);
|
|
25308
|
+
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react21.useState)(null);
|
|
25309
|
+
const buttonCollectionDragRef = (0, import_react21.useRef)(null);
|
|
25310
|
+
const buttonDropInsertIndexRef = (0, import_react21.useRef)(null);
|
|
25311
|
+
const [buttonDropSlots, setButtonDropSlots] = (0, import_react21.useState)([]);
|
|
25312
|
+
const [activeButtonDropIndex, setActiveButtonDropIndex] = (0, import_react21.useState)(null);
|
|
25313
|
+
const buttonPointerDragRef = (0, import_react21.useRef)(null);
|
|
25314
|
+
const [buttonStyleTick, setButtonStyleTick] = (0, import_react21.useState)(0);
|
|
25315
|
+
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react21.useState)(null);
|
|
25316
|
+
const [editorViewport, setEditorViewport] = (0, import_react21.useState)("desktop");
|
|
25317
|
+
const [parentScrollSnap, setParentScrollSnap] = (0, import_react21.useState)(null);
|
|
25215
25318
|
const [sitePages, setSitePages] = (0, import_react21.useState)([]);
|
|
25216
25319
|
const [sectionsByPath, setSectionsByPath] = (0, import_react21.useState)({});
|
|
25217
25320
|
const sectionsPrefetchGenRef = (0, import_react21.useRef)(0);
|
|
@@ -25220,7 +25323,18 @@ function OhhwellsBridge() {
|
|
|
25220
25323
|
const linkPopoverOpenRef = (0, import_react21.useRef)(false);
|
|
25221
25324
|
const linkPopoverGraceUntilRef = (0, import_react21.useRef)(0);
|
|
25222
25325
|
setLinkPopoverRef.current = setLinkPopover;
|
|
25326
|
+
setFloatingPanelRef.current = setFloatingPanel;
|
|
25223
25327
|
linkPopoverSessionRef.current = linkPopover;
|
|
25328
|
+
floatingPanelOpenRef.current = Boolean(floatingPanel);
|
|
25329
|
+
(0, import_react21.useEffect)(() => {
|
|
25330
|
+
const syncViewport = () => {
|
|
25331
|
+
const next = window.innerWidth <= 480 ? "mobile" : "desktop";
|
|
25332
|
+
setEditorViewport((prev) => prev === next ? prev : next);
|
|
25333
|
+
};
|
|
25334
|
+
syncViewport();
|
|
25335
|
+
window.addEventListener("resize", syncViewport);
|
|
25336
|
+
return () => window.removeEventListener("resize", syncViewport);
|
|
25337
|
+
}, []);
|
|
25224
25338
|
(0, import_react21.useEffect)(() => {
|
|
25225
25339
|
setSectionOrderPersistHandler((entries) => {
|
|
25226
25340
|
const currentPath = window.location.pathname;
|
|
@@ -26899,6 +27013,7 @@ function OhhwellsBridge() {
|
|
|
26899
27013
|
applyAiFooterFromContent(content);
|
|
26900
27014
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
26901
27015
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
27016
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
26902
27017
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
26903
27018
|
}
|
|
26904
27019
|
applyBrandChrome(content);
|
|
@@ -26909,12 +27024,12 @@ function OhhwellsBridge() {
|
|
|
26909
27024
|
if (key === "__ohw_sections") continue;
|
|
26910
27025
|
if (key === AI_SECTIONS_KEY) continue;
|
|
26911
27026
|
if (key === AI_FOOTER_KEY) continue;
|
|
27027
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
27028
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
26912
27029
|
if (key === BRAND_KIT_KEY) continue;
|
|
26913
27030
|
if (key === STYLE_STORE_KEY) continue;
|
|
26914
27031
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
26915
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
26916
27032
|
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
26917
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
26918
27033
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
26919
27034
|
continue;
|
|
26920
27035
|
}
|
|
@@ -27129,17 +27244,18 @@ function OhhwellsBridge() {
|
|
|
27129
27244
|
}
|
|
27130
27245
|
applyAiFooterFromContent(content);
|
|
27131
27246
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
27247
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
27132
27248
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
27133
27249
|
}
|
|
27134
27250
|
for (const [key, val] of Object.entries(content)) {
|
|
27135
27251
|
if (key === "__ohw_sections") continue;
|
|
27136
27252
|
if (key === AI_SECTIONS_KEY) continue;
|
|
27137
27253
|
if (key === AI_FOOTER_KEY) continue;
|
|
27254
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
27255
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27138
27256
|
if (key === BRAND_KIT_KEY) continue;
|
|
27139
27257
|
if (key === STYLE_STORE_KEY) continue;
|
|
27140
27258
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
27141
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
27142
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27143
27259
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
27144
27260
|
continue;
|
|
27145
27261
|
}
|
|
@@ -27269,7 +27385,7 @@ function OhhwellsBridge() {
|
|
|
27269
27385
|
if (!subdomain) return {};
|
|
27270
27386
|
return contentCache.get(subdomain) ?? {};
|
|
27271
27387
|
};
|
|
27272
|
-
const observeRoots = () => [document.querySelector("nav"),
|
|
27388
|
+
const observeRoots = () => [document.querySelector("nav"), getFooterRoot()].filter(
|
|
27273
27389
|
(el) => Boolean(el)
|
|
27274
27390
|
);
|
|
27275
27391
|
const roots = observeRoots();
|
|
@@ -27396,26 +27512,11 @@ function OhhwellsBridge() {
|
|
|
27396
27512
|
const t2 = setTimeout(measure, 500);
|
|
27397
27513
|
const ro = new ResizeObserver(schedule);
|
|
27398
27514
|
ro.observe(document.body);
|
|
27399
|
-
let lastWidth = window.innerWidth;
|
|
27400
|
-
let resizeTimers = [];
|
|
27401
|
-
const clearResizeTimers = () => {
|
|
27402
|
-
resizeTimers.forEach(clearTimeout);
|
|
27403
|
-
resizeTimers = [];
|
|
27404
|
-
};
|
|
27405
|
-
const handleResize = () => {
|
|
27406
|
-
if (window.innerWidth === lastWidth) return;
|
|
27407
|
-
lastWidth = window.innerWidth;
|
|
27408
|
-
clearResizeTimers();
|
|
27409
|
-
resizeTimers = HEIGHT_SETTLE_DELAYS.map((delay) => setTimeout(measure, delay));
|
|
27410
|
-
};
|
|
27411
|
-
window.addEventListener("resize", handleResize);
|
|
27412
27515
|
return () => {
|
|
27413
27516
|
clearTimeout(t1);
|
|
27414
27517
|
clearTimeout(t2);
|
|
27415
27518
|
if (raf != null) cancelAnimationFrame(raf);
|
|
27416
27519
|
ro.disconnect();
|
|
27417
|
-
clearResizeTimers();
|
|
27418
|
-
window.removeEventListener("resize", handleResize);
|
|
27419
27520
|
};
|
|
27420
27521
|
}, [pathname, isEditMode, postToParent2]);
|
|
27421
27522
|
(0, import_react21.useEffect)(() => {
|
|
@@ -27710,6 +27811,13 @@ function OhhwellsBridge() {
|
|
|
27710
27811
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
27711
27812
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
27712
27813
|
if (isInsideLinkEditor(target)) return;
|
|
27814
|
+
if (isInsideFloatingPanel(target)) return;
|
|
27815
|
+
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
27816
|
+
if (target.closest(
|
|
27817
|
+
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
27818
|
+
)) {
|
|
27819
|
+
return;
|
|
27820
|
+
}
|
|
27713
27821
|
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
27714
27822
|
clearMediaSelectionRef.current();
|
|
27715
27823
|
}
|
|
@@ -27730,17 +27838,10 @@ function OhhwellsBridge() {
|
|
|
27730
27838
|
return;
|
|
27731
27839
|
}
|
|
27732
27840
|
}
|
|
27733
|
-
if (isInsideFloatingPanel(target)) return;
|
|
27734
|
-
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
27735
|
-
if (target.closest(
|
|
27736
|
-
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
27737
|
-
)) {
|
|
27738
|
-
return;
|
|
27739
|
-
}
|
|
27740
27841
|
{
|
|
27741
27842
|
const formEl = getFormElement(target);
|
|
27742
27843
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
27743
|
-
if (formEl && formKeyOf(formEl) && !onSuccessText) {
|
|
27844
|
+
if (formEl && formKeyOf(formEl) && !onSuccessText && !isCtaButton(target)) {
|
|
27744
27845
|
const fieldEl = getFieldWrapper(target);
|
|
27745
27846
|
if (fieldEl) {
|
|
27746
27847
|
const label = target.closest("label");
|
|
@@ -28116,6 +28217,9 @@ function OhhwellsBridge() {
|
|
|
28116
28217
|
setHoveredItemRect(null);
|
|
28117
28218
|
hoveredNavContainerRef.current = null;
|
|
28118
28219
|
setHoveredNavContainerRect(null);
|
|
28220
|
+
siblingHintElRef.current = null;
|
|
28221
|
+
setSiblingHintRect(null);
|
|
28222
|
+
setSiblingHintRects([]);
|
|
28119
28223
|
return;
|
|
28120
28224
|
}
|
|
28121
28225
|
{
|
|
@@ -28236,7 +28340,6 @@ function OhhwellsBridge() {
|
|
|
28236
28340
|
hoveredNavContainerRef.current = null;
|
|
28237
28341
|
setHoveredNavContainerRect(null);
|
|
28238
28342
|
hoveredItemElRef.current = editable;
|
|
28239
|
-
setHoveredItemRect(isSelectedForHoverRef.current(editable) ? null : editable.getBoundingClientRect());
|
|
28240
28343
|
}
|
|
28241
28344
|
}
|
|
28242
28345
|
}
|
|
@@ -28946,7 +29049,11 @@ function OhhwellsBridge() {
|
|
|
28946
29049
|
};
|
|
28947
29050
|
const handleMouseMove = (e) => {
|
|
28948
29051
|
const { clientX, clientY } = e;
|
|
28949
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
29052
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
29053
|
+
dismissImageHover();
|
|
29054
|
+
clearImageHover();
|
|
29055
|
+
return;
|
|
29056
|
+
}
|
|
28950
29057
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) {
|
|
28951
29058
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
28952
29059
|
formHoverElRef.current = null;
|
|
@@ -28975,7 +29082,12 @@ function OhhwellsBridge() {
|
|
|
28975
29082
|
setHoveredItemRect(null);
|
|
28976
29083
|
hoveredNavContainerRef.current = null;
|
|
28977
29084
|
setHoveredNavContainerRect(null);
|
|
29085
|
+
siblingHintElRef.current = null;
|
|
29086
|
+
setSiblingHintRect(null);
|
|
29087
|
+
setSiblingHintRects([]);
|
|
28978
29088
|
dismissImageHover();
|
|
29089
|
+
clearImageHover();
|
|
29090
|
+
setSectionGap(null);
|
|
28979
29091
|
return;
|
|
28980
29092
|
}
|
|
28981
29093
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
@@ -28987,7 +29099,11 @@ function OhhwellsBridge() {
|
|
|
28987
29099
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
28988
29100
|
const { clientX, clientY } = e.data;
|
|
28989
29101
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
28990
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
29102
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
29103
|
+
dismissImageHover();
|
|
29104
|
+
clearImageHover();
|
|
29105
|
+
return;
|
|
29106
|
+
}
|
|
28991
29107
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) return;
|
|
28992
29108
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
28993
29109
|
probeSectionGapAt(clientX, clientY);
|
|
@@ -29339,6 +29455,7 @@ function OhhwellsBridge() {
|
|
|
29339
29455
|
applyAiFooterFromContent(content);
|
|
29340
29456
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
29341
29457
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
29458
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
29342
29459
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
29343
29460
|
}
|
|
29344
29461
|
applyBrandChrome(content);
|
|
@@ -29353,12 +29470,12 @@ function OhhwellsBridge() {
|
|
|
29353
29470
|
}
|
|
29354
29471
|
if (key === AI_SECTIONS_KEY) continue;
|
|
29355
29472
|
if (key === AI_FOOTER_KEY) continue;
|
|
29473
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
29474
|
+
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
29356
29475
|
if (key === BRAND_KIT_KEY) continue;
|
|
29357
29476
|
if (key === STYLE_STORE_KEY) continue;
|
|
29358
29477
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
29359
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
29360
29478
|
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
29361
|
-
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
29362
29479
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
29363
29480
|
continue;
|
|
29364
29481
|
}
|
|
@@ -29633,6 +29750,7 @@ function OhhwellsBridge() {
|
|
|
29633
29750
|
brandKitRef.current = value;
|
|
29634
29751
|
applyBrandToDom(parseBrandKit(value));
|
|
29635
29752
|
if (aiSectionsRef.current) applyAiSectionsToDom(parseAiSectionsState(aiSectionsRef.current));
|
|
29753
|
+
applyAiFooterFromContent(editContentRef.current);
|
|
29636
29754
|
applyStylesToDom(parseStyleStore(stylesRef.current));
|
|
29637
29755
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: BRAND_KIT_KEY, text: value }] });
|
|
29638
29756
|
postToParentRef.current({ type: "ow:ai-brand-applied", previous, value });
|
|
@@ -29895,6 +30013,12 @@ function OhhwellsBridge() {
|
|
|
29895
30013
|
closeLinkPopoverRef.current();
|
|
29896
30014
|
return;
|
|
29897
30015
|
}
|
|
30016
|
+
if (floatingPanelOpenRef.current) {
|
|
30017
|
+
setFloatingPanelRef.current(null);
|
|
30018
|
+
deselectRef.current();
|
|
30019
|
+
deactivateRef.current();
|
|
30020
|
+
return;
|
|
30021
|
+
}
|
|
29898
30022
|
deselectRef.current();
|
|
29899
30023
|
deactivateRef.current();
|
|
29900
30024
|
clearMediaSelectionRef.current();
|
|
@@ -30708,10 +30832,10 @@ function OhhwellsBridge() {
|
|
|
30708
30832
|
window.removeEventListener("message", handleDeleteSection);
|
|
30709
30833
|
window.removeEventListener("message", handleDuplicateSection);
|
|
30710
30834
|
window.removeEventListener("message", handleDeactivate);
|
|
30711
|
-
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
30712
30835
|
window.removeEventListener("message", handleToastAction);
|
|
30713
30836
|
window.removeEventListener("message", handleFormCount);
|
|
30714
30837
|
window.removeEventListener("message", handleUiEscape);
|
|
30838
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
30715
30839
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
30716
30840
|
autoSaveTimers.current.clear();
|
|
30717
30841
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
@@ -31005,7 +31129,7 @@ function OhhwellsBridge() {
|
|
|
31005
31129
|
postToParent2({
|
|
31006
31130
|
type: "ow:ready",
|
|
31007
31131
|
version: "1",
|
|
31008
|
-
bridgeVersion: "0.1.
|
|
31132
|
+
bridgeVersion: "0.1.139",
|
|
31009
31133
|
path: pathname,
|
|
31010
31134
|
nodes: collectEditableNodes(editContentRef.current),
|
|
31011
31135
|
sections
|