@ohhwells/bridge 0.1.122 → 0.1.124
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 +280 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +280 -44
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -104,6 +104,10 @@ function enforceLinkHrefs() {
|
|
|
104
104
|
|
|
105
105
|
// src/lib/ai-tree.ts
|
|
106
106
|
var AI_TREE_SCHEMA_VERSIONS = [1];
|
|
107
|
+
var BUTTON_FILL_TOKENS = ["dark", "primary", "accent", "light"];
|
|
108
|
+
var BUTTON_STYLES = ["solid", "outline", "ghost"];
|
|
109
|
+
var BUTTON_RADII = ["square", "rounded", "pill"];
|
|
110
|
+
var BUTTON_SIZES = ["s", "m", "l"];
|
|
107
111
|
var AI_DEFAULT_BRAND = {
|
|
108
112
|
palette: { dark: "#0C0A09", primary: "#0078E5", accent: "#747271", light: "#ECECEB" },
|
|
109
113
|
fonts: {
|
|
@@ -363,6 +367,118 @@ var FONT_VARS = {
|
|
|
363
367
|
var BRAND_FONT_LINK_ID = "ohw-brand-fonts";
|
|
364
368
|
var CUSTOM_FONT_STYLE_ID = "ohw-brand-custom-fonts";
|
|
365
369
|
var CUSTOM_FONT_FORMATS = /* @__PURE__ */ new Set(["woff2", "woff", "truetype", "opentype"]);
|
|
370
|
+
var BUTTON_RADIUS_PX = {
|
|
371
|
+
square: 0,
|
|
372
|
+
rounded: AI_TREE_TOKENS.radiusButton,
|
|
373
|
+
pill: 999
|
|
374
|
+
};
|
|
375
|
+
var BUTTON_SIZE_SPEC = {
|
|
376
|
+
s: {
|
|
377
|
+
paddingX: `${AI_TREE_TOKENS.spacing4}px`,
|
|
378
|
+
paddingY: `${AI_TREE_TOKENS.spacing2}px`,
|
|
379
|
+
fontSize: "14px"
|
|
380
|
+
},
|
|
381
|
+
m: {
|
|
382
|
+
paddingX: `${AI_TREE_TOKENS.spacing6}px`,
|
|
383
|
+
paddingY: `${AI_TREE_TOKENS.spacing3}px`,
|
|
384
|
+
fontSize: `${AI_TREE_TOKENS.type.button.size}px`
|
|
385
|
+
},
|
|
386
|
+
l: {
|
|
387
|
+
paddingX: `${AI_TREE_TOKENS.spacing8}px`,
|
|
388
|
+
paddingY: `${AI_TREE_TOKENS.spacing4}px`,
|
|
389
|
+
fontSize: "18px"
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
var BUTTON_SIZE_SCALE = { s: 0.85, m: 1, l: 1.25 };
|
|
393
|
+
var roundHalf = (n) => Math.round(n * 2) / 2;
|
|
394
|
+
function measureTemplateButton(variant) {
|
|
395
|
+
const root = document.documentElement;
|
|
396
|
+
const el = document.querySelector(`.btn--${variant}, .btn-${variant}`);
|
|
397
|
+
if (!el) return null;
|
|
398
|
+
const sheet = document.getElementById(BUTTON_RULES_STYLE_ID);
|
|
399
|
+
const rules = sheet?.textContent ?? "";
|
|
400
|
+
const saved = BUTTON_VAR_NAMES.map((name) => [name, root.style.getPropertyValue(name)]);
|
|
401
|
+
if (sheet) sheet.textContent = "";
|
|
402
|
+
for (const [name] of saved) root.style.removeProperty(name);
|
|
403
|
+
const cs = getComputedStyle(el);
|
|
404
|
+
const base = {
|
|
405
|
+
fontSize: parseFloat(cs.fontSize),
|
|
406
|
+
top: parseFloat(cs.paddingTop),
|
|
407
|
+
right: parseFloat(cs.paddingRight),
|
|
408
|
+
bottom: parseFloat(cs.paddingBottom),
|
|
409
|
+
left: parseFloat(cs.paddingLeft)
|
|
410
|
+
};
|
|
411
|
+
if (sheet) sheet.textContent = rules;
|
|
412
|
+
for (const [name, value] of saved) if (value) root.style.setProperty(name, value);
|
|
413
|
+
return Object.values(base).every(Number.isFinite) && base.fontSize > 0 ? base : null;
|
|
414
|
+
}
|
|
415
|
+
function scaledButtonSize(size, base) {
|
|
416
|
+
if (!base) return BUTTON_SIZE_SPEC[size];
|
|
417
|
+
const k = BUTTON_SIZE_SCALE[size];
|
|
418
|
+
const px2 = (n) => `${roundHalf(n * k)}px`;
|
|
419
|
+
return {
|
|
420
|
+
// Each side scaled on its own, so a button with uneven padding (say, room for an icon on one
|
|
421
|
+
// side) keeps its shape; the x/y vars are the averages for templates that read those instead.
|
|
422
|
+
padding: `${px2(base.top)} ${px2(base.right)} ${px2(base.bottom)} ${px2(base.left)}`,
|
|
423
|
+
paddingX: px2((base.left + base.right) / 2),
|
|
424
|
+
paddingY: px2((base.top + base.bottom) / 2),
|
|
425
|
+
fontSize: `${roundHalf(base.fontSize * k)}px`
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
var BUTTON_VAR_ROLES = ["bg", "text", "border", "radius", "padding-x", "padding-y", "padding", "font-size"];
|
|
429
|
+
var BUTTON_VAR_NAMES = ["primary", "secondary"].flatMap(
|
|
430
|
+
(variant) => BUTTON_VAR_ROLES.map((role) => `--brand-button-${variant}-${role}`)
|
|
431
|
+
);
|
|
432
|
+
var ROLES_BY_FIELD = {
|
|
433
|
+
fill: ["bg"],
|
|
434
|
+
style: ["bg", "border"],
|
|
435
|
+
textColor: ["text"],
|
|
436
|
+
radius: ["radius"],
|
|
437
|
+
size: ["padding-x", "padding-y", "padding", "font-size"]
|
|
438
|
+
};
|
|
439
|
+
function touchedButtonRoles(variant, kit) {
|
|
440
|
+
if (!kit.touched) return new Set(BUTTON_VAR_ROLES);
|
|
441
|
+
const fields = kit.touched.buttons?.[variant] ?? [];
|
|
442
|
+
const outline = fields.includes("style") && kit.buttons?.[variant]?.style === "outline";
|
|
443
|
+
return new Set(
|
|
444
|
+
fields.flatMap((f) => {
|
|
445
|
+
if (outline && (f === "fill" || f === "style")) return ["border"];
|
|
446
|
+
return ROLES_BY_FIELD[f] ?? [];
|
|
447
|
+
})
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
function buttonPalette(kit) {
|
|
451
|
+
return kit.palette ?? {
|
|
452
|
+
dark: "var(--brand-text)",
|
|
453
|
+
primary: "var(--brand-primary)",
|
|
454
|
+
accent: "var(--brand-accent)",
|
|
455
|
+
light: "var(--brand-background)"
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
function buttonVariantVars(variant, style, roles, palette) {
|
|
459
|
+
const fill = palette[style.fill];
|
|
460
|
+
const text = palette[style.textColor];
|
|
461
|
+
const size = scaledButtonSize(style.size, roles.has("font-size") ? measureTemplateButton(variant) : null);
|
|
462
|
+
const { bg, border } = !roles.has("border") ? { bg: fill, border: "transparent" } : style.style === "outline" ? { bg: "transparent", border: fill } : style.style === "ghost" ? { bg: "transparent", border: "transparent" } : { bg: fill, border: "transparent" };
|
|
463
|
+
const all = {
|
|
464
|
+
[`--brand-button-${variant}-bg`]: bg,
|
|
465
|
+
[`--brand-button-${variant}-text`]: text,
|
|
466
|
+
[`--brand-button-${variant}-border`]: border,
|
|
467
|
+
[`--brand-button-${variant}-radius`]: `${BUTTON_RADIUS_PX[style.radius]}px`,
|
|
468
|
+
[`--brand-button-${variant}-padding-x`]: size.paddingX,
|
|
469
|
+
[`--brand-button-${variant}-padding-y`]: size.paddingY,
|
|
470
|
+
...size.padding ? { [`--brand-button-${variant}-padding`]: size.padding } : {},
|
|
471
|
+
[`--brand-button-${variant}-font-size`]: size.fontSize
|
|
472
|
+
};
|
|
473
|
+
const prefix = `--brand-button-${variant}-`;
|
|
474
|
+
return Object.fromEntries(Object.entries(all).filter(([name]) => roles.has(name.slice(prefix.length))));
|
|
475
|
+
}
|
|
476
|
+
function buttonStyleVars(kit) {
|
|
477
|
+
return {
|
|
478
|
+
...buttonVariantVars("primary", kit.buttons.primary, touchedButtonRoles("primary", kit), buttonPalette(kit)),
|
|
479
|
+
...buttonVariantVars("secondary", kit.buttons.secondary, touchedButtonRoles("secondary", kit), buttonPalette(kit))
|
|
480
|
+
};
|
|
481
|
+
}
|
|
366
482
|
function brandColorVars(palette) {
|
|
367
483
|
const { dark, primary, accent, light } = palette;
|
|
368
484
|
const mix = (a, aPct, b) => `color-mix(in srgb, ${a} ${aPct}%, ${b})`;
|
|
@@ -390,6 +506,11 @@ function brandColorVars(palette) {
|
|
|
390
506
|
"--brand-on-primary": light
|
|
391
507
|
};
|
|
392
508
|
}
|
|
509
|
+
function isButtonStyle(value) {
|
|
510
|
+
if (!value || typeof value !== "object") return false;
|
|
511
|
+
const v = value;
|
|
512
|
+
return BUTTON_FILL_TOKENS.includes(v.fill) && BUTTON_FILL_TOKENS.includes(v.textColor) && BUTTON_STYLES.includes(v.style) && BUTTON_RADII.includes(v.radius) && BUTTON_SIZES.includes(v.size);
|
|
513
|
+
}
|
|
393
514
|
function parseCustomFontWeight(raw) {
|
|
394
515
|
if (typeof raw !== "object" || raw === null) return null;
|
|
395
516
|
const w = raw;
|
|
@@ -409,6 +530,15 @@ function parseCustomFont(raw) {
|
|
|
409
530
|
if (weights.length === 0) return null;
|
|
410
531
|
return { family: f.family, label: f.label, weights };
|
|
411
532
|
}
|
|
533
|
+
var BUTTON_FIELDS = Object.keys(ROLES_BY_FIELD);
|
|
534
|
+
function parseTouchedButtons(raw) {
|
|
535
|
+
const out = {};
|
|
536
|
+
for (const variant of ["primary", "secondary"]) {
|
|
537
|
+
const list = raw?.[variant];
|
|
538
|
+
if (Array.isArray(list)) out[variant] = BUTTON_FIELDS.filter((f) => list.includes(f));
|
|
539
|
+
}
|
|
540
|
+
return out;
|
|
541
|
+
}
|
|
412
542
|
function parseBrandKit(raw) {
|
|
413
543
|
if (!raw) return null;
|
|
414
544
|
try {
|
|
@@ -418,11 +548,21 @@ function parseBrandKit(raw) {
|
|
|
418
548
|
const palette = p && typeof p.dark === "string" && typeof p.primary === "string" && typeof p.accent === "string" && typeof p.light === "string" ? { dark: p.dark, primary: p.primary, accent: p.accent, light: p.light } : void 0;
|
|
419
549
|
const fonts = f && typeof f.heading === "string" && typeof f.body === "string" ? { heading: f.heading, body: f.body } : void 0;
|
|
420
550
|
const customFonts = Array.isArray(parsed?.customFonts) ? parsed.customFonts.map(parseCustomFont).filter((c) => c !== null) : void 0;
|
|
421
|
-
|
|
551
|
+
const b = parsed?.buttons;
|
|
552
|
+
const buttons = b && isButtonStyle(b.primary) && isButtonStyle(b.secondary) ? { primary: b.primary, secondary: b.secondary } : void 0;
|
|
553
|
+
if (!palette && !fonts && !customFonts && !buttons) return null;
|
|
422
554
|
return {
|
|
423
555
|
...palette ? { palette } : {},
|
|
424
556
|
...fonts ? { fonts } : {},
|
|
425
|
-
...customFonts ? { customFonts } : {}
|
|
557
|
+
...customFonts ? { customFonts } : {},
|
|
558
|
+
...buttons ? { buttons } : {},
|
|
559
|
+
...parsed.touched && typeof parsed.touched === "object" ? {
|
|
560
|
+
touched: {
|
|
561
|
+
palette: parsed.touched.palette === true,
|
|
562
|
+
fonts: parsed.touched.fonts === true,
|
|
563
|
+
buttons: parseTouchedButtons(parsed.touched.buttons)
|
|
564
|
+
}
|
|
565
|
+
} : {}
|
|
426
566
|
};
|
|
427
567
|
} catch {
|
|
428
568
|
return null;
|
|
@@ -451,6 +591,39 @@ function loadBrandFonts(families) {
|
|
|
451
591
|
}
|
|
452
592
|
if (link.href !== href) link.href = href;
|
|
453
593
|
}
|
|
594
|
+
var BUTTON_RULES_STYLE_ID = "ohw-brand-button-rules";
|
|
595
|
+
function buttonRulesCss(kit) {
|
|
596
|
+
const rule = (variant) => {
|
|
597
|
+
const roles = touchedButtonRoles(variant, kit);
|
|
598
|
+
const v = (role) => `var(--brand-button-${variant}-${role})`;
|
|
599
|
+
const decls = [];
|
|
600
|
+
if (roles.has("bg")) decls.push(`background:${v("bg")} !important`);
|
|
601
|
+
if (roles.has("text")) decls.push(`color:${v("text")} !important`);
|
|
602
|
+
if (roles.has("border")) decls.push(`border:1.5px solid ${v("border")} !important`);
|
|
603
|
+
if (roles.has("radius")) decls.push(`border-radius:${v("radius")} !important`);
|
|
604
|
+
if (roles.has("padding-x")) decls.push(`padding:var(--brand-button-${variant}-padding, ${v("padding-y")} ${v("padding-x")}) !important`);
|
|
605
|
+
if (roles.has("font-size")) decls.push(`font-size:${v("font-size")} !important`);
|
|
606
|
+
if (decls.length === 0) return "";
|
|
607
|
+
const selectors = [`html .btn--${variant}`, `html .btn-${variant}`];
|
|
608
|
+
const labelRule = roles.has("text") ? `${selectors.map((x) => `${x} *`).join(",")}{color:inherit !important}` : "";
|
|
609
|
+
return `${selectors.join(",")}{${decls.join(";")}}` + labelRule + (roles.has("bg") ? `${selectors.map((x) => `${x}:hover`).join(",")}{opacity:0.88}` : "");
|
|
610
|
+
};
|
|
611
|
+
return rule("primary") + rule("secondary");
|
|
612
|
+
}
|
|
613
|
+
function syncButtonRules(kit) {
|
|
614
|
+
let el = document.getElementById(BUTTON_RULES_STYLE_ID);
|
|
615
|
+
const css = kit ? buttonRulesCss(kit) : "";
|
|
616
|
+
if (!css) {
|
|
617
|
+
el?.remove();
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
if (!el) {
|
|
621
|
+
el = document.createElement("style");
|
|
622
|
+
el.id = BUTTON_RULES_STYLE_ID;
|
|
623
|
+
document.head.appendChild(el);
|
|
624
|
+
}
|
|
625
|
+
if (el.textContent !== css) el.textContent = css;
|
|
626
|
+
}
|
|
454
627
|
function escapeCssString(value) {
|
|
455
628
|
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
456
629
|
}
|
|
@@ -476,28 +649,47 @@ function loadCustomFonts(fonts) {
|
|
|
476
649
|
function applyBrandToDom(kit) {
|
|
477
650
|
const root = document.documentElement;
|
|
478
651
|
if (!kit) {
|
|
479
|
-
for (const name of [...BRAND_VAR_NAMES, ...LEGACY_BRAND_VAR_NAMES])
|
|
652
|
+
for (const name of [...BRAND_VAR_NAMES, ...LEGACY_BRAND_VAR_NAMES, ...BUTTON_VAR_NAMES]) {
|
|
653
|
+
root.style.removeProperty(name);
|
|
654
|
+
}
|
|
480
655
|
for (const name of [...FONT_VARS.heading, ...FONT_VARS.body]) root.style.removeProperty(name);
|
|
481
656
|
document.getElementById(BRAND_FONT_LINK_ID)?.remove();
|
|
482
657
|
document.getElementById(CUSTOM_FONT_STYLE_ID)?.remove();
|
|
658
|
+
syncButtonRules(null);
|
|
483
659
|
return;
|
|
484
660
|
}
|
|
661
|
+
const applyPalette = kit.touched ? kit.touched.palette === true : true;
|
|
662
|
+
const applyFonts = kit.touched ? kit.touched.fonts === true : true;
|
|
485
663
|
if (kit.palette) {
|
|
486
|
-
|
|
664
|
+
if (applyPalette) {
|
|
665
|
+
for (const [name, value] of Object.entries(brandColorVars(kit.palette))) root.style.setProperty(name, value);
|
|
666
|
+
} else {
|
|
667
|
+
for (const name of [...BRAND_VAR_NAMES, ...LEGACY_BRAND_VAR_NAMES]) root.style.removeProperty(name);
|
|
668
|
+
}
|
|
487
669
|
}
|
|
670
|
+
if (kit.buttons) {
|
|
671
|
+
for (const name of BUTTON_VAR_NAMES) root.style.removeProperty(name);
|
|
672
|
+
for (const [name, value] of Object.entries(buttonStyleVars({ ...kit, buttons: kit.buttons }))) root.style.setProperty(name, value);
|
|
673
|
+
}
|
|
674
|
+
syncButtonRules(kit.buttons ? kit : null);
|
|
488
675
|
if (kit.customFonts) {
|
|
489
676
|
loadCustomFonts(kit.customFonts);
|
|
490
677
|
}
|
|
491
678
|
if (kit.fonts) {
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
(
|
|
499
|
-
|
|
500
|
-
|
|
679
|
+
if (applyFonts) {
|
|
680
|
+
const heading = quoteFamily(kit.fonts.heading);
|
|
681
|
+
const body = quoteFamily(kit.fonts.body);
|
|
682
|
+
for (const name of FONT_VARS.heading) root.style.setProperty(name, heading);
|
|
683
|
+
for (const name of FONT_VARS.body) root.style.setProperty(name, body);
|
|
684
|
+
const customFamilies = new Set((kit.customFonts ?? []).map((f) => f.family));
|
|
685
|
+
const googleFamilies = [familyOf(kit.fonts.heading), familyOf(kit.fonts.body)].filter(
|
|
686
|
+
(f) => !customFamilies.has(f)
|
|
687
|
+
);
|
|
688
|
+
loadBrandFonts(googleFamilies);
|
|
689
|
+
} else {
|
|
690
|
+
for (const name of [...FONT_VARS.heading, ...FONT_VARS.body]) root.style.removeProperty(name);
|
|
691
|
+
document.getElementById(BRAND_FONT_LINK_ID)?.remove();
|
|
692
|
+
}
|
|
501
693
|
}
|
|
502
694
|
}
|
|
503
695
|
|
|
@@ -647,7 +839,6 @@ var NODE_PROPS = [
|
|
|
647
839
|
"color",
|
|
648
840
|
"font-family",
|
|
649
841
|
"font-size",
|
|
650
|
-
"background",
|
|
651
842
|
"text-align",
|
|
652
843
|
"justify-content",
|
|
653
844
|
"align-items"
|
|
@@ -697,9 +888,6 @@ function clearNodeProps(root) {
|
|
|
697
888
|
h.removeAttribute(NODE_WROTE_ATTR);
|
|
698
889
|
}
|
|
699
890
|
}
|
|
700
|
-
function buttonSurfaceOf(el) {
|
|
701
|
-
return el.closest("a, button") ?? el;
|
|
702
|
-
}
|
|
703
891
|
function alignSubjectOf(el) {
|
|
704
892
|
const button = el.closest('[data-ohw-role="button"]');
|
|
705
893
|
if (button?.parentElement) return button.parentElement;
|
|
@@ -817,18 +1005,6 @@ function applyStylesToDom(store) {
|
|
|
817
1005
|
);
|
|
818
1006
|
subject.setAttribute(NODE_WROTE_ATTR, "");
|
|
819
1007
|
}
|
|
820
|
-
if (override.buttonBackground !== void 0 || override.buttonText !== void 0) {
|
|
821
|
-
const surface = buttonSurfaceOf(el);
|
|
822
|
-
if (override.buttonBackground !== void 0) {
|
|
823
|
-
saveInline(surface, "background");
|
|
824
|
-
surface.style.setProperty("background", override.buttonBackground, "important");
|
|
825
|
-
}
|
|
826
|
-
if (override.buttonText !== void 0) {
|
|
827
|
-
saveInline(surface, "color");
|
|
828
|
-
surface.style.setProperty("color", override.buttonText, "important");
|
|
829
|
-
}
|
|
830
|
-
surface.setAttribute(NODE_WROTE_ATTR, "");
|
|
831
|
-
}
|
|
832
1008
|
}
|
|
833
1009
|
}
|
|
834
1010
|
for (const [sectionId, override] of Object.entries(store.sections)) {
|
|
@@ -1414,7 +1590,59 @@ var AI_MOBILE_CSS = [
|
|
|
1414
1590
|
"[data-ai-grid]{grid-template-columns:repeat(2, 1fr) !important}",
|
|
1415
1591
|
"}"
|
|
1416
1592
|
].join("");
|
|
1417
|
-
function
|
|
1593
|
+
function buttonSizeSpec(size) {
|
|
1594
|
+
switch (size) {
|
|
1595
|
+
case "s":
|
|
1596
|
+
return { padding: `${AI_TREE_TOKENS.spacing2}px ${AI_TREE_TOKENS.spacing4}px`, fontSize: 14 };
|
|
1597
|
+
case "l":
|
|
1598
|
+
return { padding: `${AI_TREE_TOKENS.spacing4}px ${AI_TREE_TOKENS.spacing8}px`, fontSize: 18 };
|
|
1599
|
+
case "m":
|
|
1600
|
+
default:
|
|
1601
|
+
return { padding: `${AI_TREE_TOKENS.spacing3}px ${AI_TREE_TOKENS.spacing6}px`, fontSize: AI_TREE_TOKENS.type.button.size };
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
function buttonRadiusPx(radius) {
|
|
1605
|
+
switch (radius) {
|
|
1606
|
+
case "square":
|
|
1607
|
+
return 0;
|
|
1608
|
+
case "pill":
|
|
1609
|
+
return 999;
|
|
1610
|
+
case "rounded":
|
|
1611
|
+
default:
|
|
1612
|
+
return AI_TREE_TOKENS.radiusButton;
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
function resolveButtonToken(brand, token) {
|
|
1616
|
+
return brand.palette[token];
|
|
1617
|
+
}
|
|
1618
|
+
function buttonColorStyle(ctx, variant) {
|
|
1619
|
+
const token = ctx.brand.buttons?.[variant];
|
|
1620
|
+
if (!token) return null;
|
|
1621
|
+
const fill = resolveButtonToken(ctx.brand, token.fill);
|
|
1622
|
+
const text = resolveButtonToken(ctx.brand, token.textColor);
|
|
1623
|
+
switch (token.style) {
|
|
1624
|
+
case "outline":
|
|
1625
|
+
return { background: "transparent", border: `1px solid ${fill}`, color: text };
|
|
1626
|
+
case "ghost":
|
|
1627
|
+
return { background: "transparent", border: "1px solid transparent", color: text };
|
|
1628
|
+
case "solid":
|
|
1629
|
+
default:
|
|
1630
|
+
return { background: fill, color: text };
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1633
|
+
function buttonShellStyle(ctx, variant, fullWidth) {
|
|
1634
|
+
const buttonToken = ctx.brand.buttons?.[variant];
|
|
1635
|
+
if (buttonToken) {
|
|
1636
|
+
const { padding, fontSize } = buttonSizeSpec(buttonToken.size);
|
|
1637
|
+
return {
|
|
1638
|
+
borderRadius: buttonRadiusPx(buttonToken.radius),
|
|
1639
|
+
padding,
|
|
1640
|
+
fontFamily: ctx.brand.fonts.body,
|
|
1641
|
+
fontSize,
|
|
1642
|
+
lineHeight: AI_TREE_TOKENS.type.button.line,
|
|
1643
|
+
fontWeight: AI_TREE_TOKENS.type.button.weight
|
|
1644
|
+
};
|
|
1645
|
+
}
|
|
1418
1646
|
const bs = ctx.buttonStyle;
|
|
1419
1647
|
if (bs) {
|
|
1420
1648
|
return {
|
|
@@ -1610,12 +1838,16 @@ function ButtonEl({
|
|
|
1610
1838
|
secondaryColor
|
|
1611
1839
|
}) {
|
|
1612
1840
|
const secondary = slots.variant === "secondary";
|
|
1841
|
+
const variant = secondary ? "secondary" : "primary";
|
|
1842
|
+
const tokenColorStyle = buttonColorStyle(ctx, variant);
|
|
1613
1843
|
const href = str(slots.href);
|
|
1614
1844
|
const linkAttrs = ctx.keyFor && path ? { "data-ohw-href-key": ctx.keyFor(`${path}.href`), "data-ohw-role": "button" } : {};
|
|
1615
1845
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1616
1846
|
"a",
|
|
1617
1847
|
{
|
|
1618
1848
|
href: href || void 0,
|
|
1849
|
+
className: `btn btn--${variant}`,
|
|
1850
|
+
"data-ohw-btn-variant": variant,
|
|
1619
1851
|
...linkAttrs,
|
|
1620
1852
|
style: {
|
|
1621
1853
|
display: fullWidth ? "flex" : "inline-flex",
|
|
@@ -1625,13 +1857,13 @@ function ButtonEl({
|
|
|
1625
1857
|
textDecoration: "none",
|
|
1626
1858
|
cursor: "pointer",
|
|
1627
1859
|
whiteSpace: "nowrap",
|
|
1628
|
-
...buttonShellStyle(ctx, fullWidth),
|
|
1629
|
-
...secondary ? { border: `1px solid ${secondaryColor ?? ctx.brand.palette.dark}`, color: secondaryColor ?? ctx.brand.palette.dark } : (
|
|
1860
|
+
...buttonShellStyle(ctx, variant, fullWidth),
|
|
1861
|
+
...tokenColorStyle ?? (secondary ? { border: `1px solid ${secondaryColor ?? ctx.brand.palette.dark}`, color: secondaryColor ?? ctx.brand.palette.dark } : (
|
|
1630
1862
|
// Off-band, prefer the template button's measured fill/label pair — a template may
|
|
1631
1863
|
// fill its CTAs with any token (hvac: accent bg, primary text). On an accent band
|
|
1632
1864
|
// the flipped palette keeps contrast, so the brand-driven colours stay.
|
|
1633
1865
|
!ctx.buttonLabel && ctx.buttonStyle?.background ? { background: ctx.buttonStyle.background, color: ctx.buttonStyle.color } : { background: ctx.brand.palette.primary, color: ctx.buttonLabel ?? primaryButtonLabel(ctx.brand) }
|
|
1634
|
-
)
|
|
1866
|
+
))
|
|
1635
1867
|
},
|
|
1636
1868
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...path ? textAttrs(ctx, `${path}.label`) : {}, children: str(slots.label) })
|
|
1637
1869
|
}
|
|
@@ -2853,18 +3085,21 @@ function renderNode(node, ctx, path) {
|
|
|
2853
3085
|
"button",
|
|
2854
3086
|
{
|
|
2855
3087
|
type: "submit",
|
|
3088
|
+
className: "btn btn--primary",
|
|
3089
|
+
"data-ohw-btn-variant": "primary",
|
|
3090
|
+
"data-ohw-role": "button",
|
|
2856
3091
|
style: {
|
|
2857
3092
|
alignSelf: submitAlign,
|
|
2858
3093
|
border: "none",
|
|
2859
3094
|
cursor: "pointer",
|
|
2860
3095
|
// Shape/padding/typography follow the host template's own buttons.
|
|
2861
|
-
...buttonShellStyle(ctx),
|
|
3096
|
+
...buttonShellStyle(ctx, "primary"),
|
|
2862
3097
|
// Brand-styled: the template button's measured fill/label pair off-band, else
|
|
2863
3098
|
// primary fill with a brand-derived label so it reads on custom palettes.
|
|
2864
|
-
|
|
3099
|
+
...buttonColorStyle(ctx, "primary") ?? (!ctx.buttonLabel && ctx.buttonStyle?.background ? { background: ctx.buttonStyle.background, color: ctx.buttonStyle.color } : {
|
|
2865
3100
|
background: ctx.brand.palette.primary,
|
|
2866
3101
|
color: ctx.buttonLabel ?? primaryButtonLabel(ctx.brand)
|
|
2867
|
-
}
|
|
3102
|
+
})
|
|
2868
3103
|
},
|
|
2869
3104
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...textAttrs(ctx, `${path}.c${i}.label`), children: str(cs.label) })
|
|
2870
3105
|
},
|
|
@@ -3782,6 +4017,7 @@ function EmptyState({ inEditor, insertAfter }) {
|
|
|
3782
4017
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3783
4018
|
"button",
|
|
3784
4019
|
{
|
|
4020
|
+
"data-ohw-bridge": true,
|
|
3785
4021
|
onClick: handleAddSchedule,
|
|
3786
4022
|
className: "h-9 px-2 py-1.5 flex items-center justify-center bg-white border border-[#E7E5E4] rounded-md font-body text-sm font-medium text-(--color-dark,#200C02) cursor-pointer",
|
|
3787
4023
|
children: "Add Schedule"
|
|
@@ -4199,7 +4435,7 @@ function SchedulingWidget({ notifyOnConnect = false, initialScheduleId, insertAf
|
|
|
4199
4435
|
const timer = setTimeout(() => {
|
|
4200
4436
|
if (!done) {
|
|
4201
4437
|
done = true;
|
|
4202
|
-
|
|
4438
|
+
innerCleanup = loadWithId(null);
|
|
4203
4439
|
}
|
|
4204
4440
|
}, 2e3);
|
|
4205
4441
|
const configHandler = (e) => {
|
|
@@ -16842,6 +17078,9 @@ function guardTemplateHover(el) {
|
|
|
16842
17078
|
observer.observe(el, { attributes: true, attributeFilter: ["style", "class"] });
|
|
16843
17079
|
paintObserverByEl.set(el, observer);
|
|
16844
17080
|
}
|
|
17081
|
+
function paintedTokensOf(el) {
|
|
17082
|
+
return paintLockByEl.get(el)?.tokens ?? null;
|
|
17083
|
+
}
|
|
16845
17084
|
function applyButtonStyle(el, assignment, tokens) {
|
|
16846
17085
|
paintLockByEl.set(el, { assignment, tokens });
|
|
16847
17086
|
paintingButton = true;
|
|
@@ -17180,12 +17419,9 @@ function duplicateButton(source, content) {
|
|
|
17180
17419
|
const label = buttonLabel(source);
|
|
17181
17420
|
if (href) copy.setAttribute("href", href);
|
|
17182
17421
|
const sourceAssignment = readAssignments(content)[sourceId] ?? assignmentFor(source, content, tokens);
|
|
17183
|
-
const copyAssignment = {
|
|
17184
|
-
|
|
17185
|
-
|
|
17186
|
-
};
|
|
17187
|
-
stampVariantClass(copy, "secondary");
|
|
17188
|
-
applyButtonStyle(copy, copyAssignment, tokens);
|
|
17422
|
+
const copyAssignment = { ...sourceAssignment };
|
|
17423
|
+
stampVariantClass(copy, copyAssignment.variant);
|
|
17424
|
+
applyButtonStyle(copy, copyAssignment, paintedTokensOf(source) ?? tokens);
|
|
17189
17425
|
const copyLabelEl = labelElement2(copy);
|
|
17190
17426
|
if (copyLabelEl) copyLabelEl.textContent = label;
|
|
17191
17427
|
let collection = buttonCollectionOf(source);
|
|
@@ -26636,7 +26872,7 @@ function OhhwellsBridge() {
|
|
|
26636
26872
|
postToParent2({
|
|
26637
26873
|
type: "ow:ready",
|
|
26638
26874
|
version: "1",
|
|
26639
|
-
bridgeVersion: "0.1.
|
|
26875
|
+
bridgeVersion: "0.1.123",
|
|
26640
26876
|
path: pathname,
|
|
26641
26877
|
nodes: collectEditableNodes(editContentRef.current),
|
|
26642
26878
|
sections
|