@ohhwells/bridge 0.1.95 → 0.1.97
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 +406 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -3
- package/dist/index.d.ts +17 -3
- package/dist/index.js +406 -32
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -491,6 +491,10 @@ function styleSheetCss() {
|
|
|
491
491
|
`[data-ohw-style-spacing="${spacing}"] { padding-top: ${px}px !important; padding-bottom: ${px}px !important; }`
|
|
492
492
|
);
|
|
493
493
|
}
|
|
494
|
+
rules.push(
|
|
495
|
+
`[data-ohw-style-corners="sharp"] :is(.card, [data-ohw-card], img, picture, figure, [data-ohw-editable="bg-image"]) { border-radius: 0 !important; }`,
|
|
496
|
+
`[data-ohw-style-corners="sharp"] :has(> img) { border-radius: 0 !important; }`
|
|
497
|
+
);
|
|
494
498
|
for (const align of ["left", "center", "right"]) {
|
|
495
499
|
rules.push(`[data-ohw-style-align="${align}"] { text-align: ${align} !important; }`);
|
|
496
500
|
}
|
|
@@ -521,6 +525,7 @@ var SECTION_ATTRS = {
|
|
|
521
525
|
headlineScale: "data-ohw-style-headline",
|
|
522
526
|
imageAspect: "data-ohw-style-aspect",
|
|
523
527
|
spacing: "data-ohw-style-spacing",
|
|
528
|
+
cornerStyle: "data-ohw-style-corners",
|
|
524
529
|
align: "data-ohw-style-align"
|
|
525
530
|
};
|
|
526
531
|
var NODE_WROTE_ATTR = "data-ohw-style-node";
|
|
@@ -913,6 +918,284 @@ function initSectionInstancesFromContent(content, currentPath) {
|
|
|
913
918
|
// src/ui/ai-tree/AiTreeRenderer.tsx
|
|
914
919
|
var import_react = __toESM(require("react"), 1);
|
|
915
920
|
var import_lucide_react = require("lucide-react");
|
|
921
|
+
|
|
922
|
+
// src/lib/placeholder-imagery.ts
|
|
923
|
+
var U = (id) => `https://images.unsplash.com/photo-${id}?auto=format&fit=crop&w=1600&q=80`;
|
|
924
|
+
var GENERIC = [
|
|
925
|
+
U("1441986300917-64674bd600d8"),
|
|
926
|
+
U("1486406146926-c627a92ad1ab"),
|
|
927
|
+
U("1497032628192-86f99bcd76bc"),
|
|
928
|
+
U("1521737604893-d14cc237f11d"),
|
|
929
|
+
U("1522071820081-009f0129c71c"),
|
|
930
|
+
U("1519389950473-47ba0277781c"),
|
|
931
|
+
U("1460925895917-afdab827c52f"),
|
|
932
|
+
U("1504384308090-c894fdcc538d")
|
|
933
|
+
];
|
|
934
|
+
var PEOPLE = [
|
|
935
|
+
U("1500648767791-00dcc994a43e"),
|
|
936
|
+
U("1494790108377-be9c29b29330"),
|
|
937
|
+
U("1507003211169-0a1dd7228f2d"),
|
|
938
|
+
U("1438761681033-6461ffad8d80"),
|
|
939
|
+
U("1544005313-94ddf0286df2"),
|
|
940
|
+
U("1472099645785-5658abf4ff4e"),
|
|
941
|
+
U("1519085360753-af0119f7cbe7"),
|
|
942
|
+
U("1534528741775-53994a69daeb")
|
|
943
|
+
];
|
|
944
|
+
var THEMED = [
|
|
945
|
+
{
|
|
946
|
+
keywords: ["portrait", "headshot", "person", "people", "team", "staff", "avatar", "founder", "face"],
|
|
947
|
+
pool: PEOPLE
|
|
948
|
+
},
|
|
949
|
+
{
|
|
950
|
+
keywords: ["pet", "dog", "cat", "puppy", "kitten", "vet", "animal"],
|
|
951
|
+
pool: [
|
|
952
|
+
U("1548199973-03cce0bbc87b"),
|
|
953
|
+
U("1450778869180-41d0601e046e"),
|
|
954
|
+
U("1583511655857-d19b40a7a54e"),
|
|
955
|
+
U("1587300003388-59208cc962cb"),
|
|
956
|
+
U("1517849845537-4d257902454a"),
|
|
957
|
+
U("1601758228041-f3b2795255f1")
|
|
958
|
+
]
|
|
959
|
+
},
|
|
960
|
+
{
|
|
961
|
+
keywords: [
|
|
962
|
+
"baker",
|
|
963
|
+
"bakery",
|
|
964
|
+
"cafe",
|
|
965
|
+
"coffee",
|
|
966
|
+
"latte",
|
|
967
|
+
"restaurant",
|
|
968
|
+
"pastr",
|
|
969
|
+
"bread",
|
|
970
|
+
"cake",
|
|
971
|
+
"cater",
|
|
972
|
+
"chef",
|
|
973
|
+
"kitchen",
|
|
974
|
+
"food",
|
|
975
|
+
"pizza",
|
|
976
|
+
"dessert",
|
|
977
|
+
"brunch",
|
|
978
|
+
"bistro",
|
|
979
|
+
"deli",
|
|
980
|
+
"dish",
|
|
981
|
+
"menu"
|
|
982
|
+
],
|
|
983
|
+
pool: [
|
|
984
|
+
U("1509440159596-0249088772ff"),
|
|
985
|
+
U("1555507036-ab1f4038808a"),
|
|
986
|
+
U("1517433670267-08bbd4be890f"),
|
|
987
|
+
U("1486427944299-d1955d23e34d"),
|
|
988
|
+
U("1504754524776-8f4f37790ca0"),
|
|
989
|
+
U("1495474472287-4d71bcdd2085"),
|
|
990
|
+
U("1521017432531-fbd92d768814"),
|
|
991
|
+
U("1556909114-f6e7ad7d3136")
|
|
992
|
+
]
|
|
993
|
+
},
|
|
994
|
+
{
|
|
995
|
+
keywords: [
|
|
996
|
+
"shop",
|
|
997
|
+
"store",
|
|
998
|
+
"boutique",
|
|
999
|
+
"retail",
|
|
1000
|
+
"clothing",
|
|
1001
|
+
"fashion",
|
|
1002
|
+
"jewel",
|
|
1003
|
+
"gift",
|
|
1004
|
+
"florist",
|
|
1005
|
+
"market",
|
|
1006
|
+
"grocer",
|
|
1007
|
+
"product",
|
|
1008
|
+
"storefront"
|
|
1009
|
+
],
|
|
1010
|
+
pool: [
|
|
1011
|
+
U("1441984904996-e0b6ba687e04"),
|
|
1012
|
+
U("1472851294608-062f824d29cc"),
|
|
1013
|
+
U("1523381210434-271e8be1f52b"),
|
|
1014
|
+
U("1534452203293-494d7ddbf7e0"),
|
|
1015
|
+
U("1445205170230-053b83016050"),
|
|
1016
|
+
U("1560243563-062bfc001d68")
|
|
1017
|
+
]
|
|
1018
|
+
},
|
|
1019
|
+
{
|
|
1020
|
+
keywords: [
|
|
1021
|
+
"yoga",
|
|
1022
|
+
"pilates",
|
|
1023
|
+
"fitness",
|
|
1024
|
+
"gym",
|
|
1025
|
+
"workout",
|
|
1026
|
+
"trainer",
|
|
1027
|
+
"wellness",
|
|
1028
|
+
"meditat",
|
|
1029
|
+
"massage",
|
|
1030
|
+
"therap",
|
|
1031
|
+
"physio",
|
|
1032
|
+
"chiro",
|
|
1033
|
+
"nutrition",
|
|
1034
|
+
"spa",
|
|
1035
|
+
"studio"
|
|
1036
|
+
],
|
|
1037
|
+
pool: [
|
|
1038
|
+
U("1544367567-0f2fcb009e0b"),
|
|
1039
|
+
U("1506126613408-eca07ce68773"),
|
|
1040
|
+
U("1545205597-3d9d02c29597"),
|
|
1041
|
+
U("1552196563-55cd4e45efb3"),
|
|
1042
|
+
U("1518611012118-696072aa579a"),
|
|
1043
|
+
U("1571019613454-1cb2f99b2d8b"),
|
|
1044
|
+
U("1540555700478-4be289fbecef"),
|
|
1045
|
+
U("1519824145371-296894a0daa9")
|
|
1046
|
+
]
|
|
1047
|
+
},
|
|
1048
|
+
{
|
|
1049
|
+
keywords: [
|
|
1050
|
+
"salon",
|
|
1051
|
+
"hairdress",
|
|
1052
|
+
"haircut",
|
|
1053
|
+
"barber",
|
|
1054
|
+
"manicure",
|
|
1055
|
+
"pedicure",
|
|
1056
|
+
"nails",
|
|
1057
|
+
"beauty",
|
|
1058
|
+
"makeup",
|
|
1059
|
+
"cosmetic",
|
|
1060
|
+
"eyelash",
|
|
1061
|
+
"eyebrow",
|
|
1062
|
+
"skincare",
|
|
1063
|
+
"esthetic",
|
|
1064
|
+
"waxing",
|
|
1065
|
+
"hair"
|
|
1066
|
+
],
|
|
1067
|
+
pool: [
|
|
1068
|
+
U("1560066984-138dadb4c035"),
|
|
1069
|
+
U("1522337660859-02fbefca4702"),
|
|
1070
|
+
U("1562322140-8baeececf3df"),
|
|
1071
|
+
U("1521590832167-7bcbfaa6381f"),
|
|
1072
|
+
U("1487412947147-5cebf100ffc2"),
|
|
1073
|
+
U("1526045478516-99145907023c")
|
|
1074
|
+
]
|
|
1075
|
+
},
|
|
1076
|
+
{
|
|
1077
|
+
keywords: [
|
|
1078
|
+
"cleaning",
|
|
1079
|
+
"plumb",
|
|
1080
|
+
"electric",
|
|
1081
|
+
"landscap",
|
|
1082
|
+
"contractor",
|
|
1083
|
+
"handyman",
|
|
1084
|
+
"renov",
|
|
1085
|
+
"hvac",
|
|
1086
|
+
"roofing",
|
|
1087
|
+
"painting",
|
|
1088
|
+
"carpentry",
|
|
1089
|
+
"flooring",
|
|
1090
|
+
"movers",
|
|
1091
|
+
"construction",
|
|
1092
|
+
"tools"
|
|
1093
|
+
],
|
|
1094
|
+
pool: [
|
|
1095
|
+
U("1581578731548-c64695cc6952"),
|
|
1096
|
+
U("1504307651254-35680f356dfd"),
|
|
1097
|
+
U("1581092160562-40aa08e78837"),
|
|
1098
|
+
U("1621905251189-08b45d6a269e"),
|
|
1099
|
+
U("1558618666-fcd25c85cd64"),
|
|
1100
|
+
U("1585128792020-803d29415281")
|
|
1101
|
+
]
|
|
1102
|
+
},
|
|
1103
|
+
{
|
|
1104
|
+
keywords: [
|
|
1105
|
+
"legal",
|
|
1106
|
+
"attorney",
|
|
1107
|
+
"lawyer",
|
|
1108
|
+
"account",
|
|
1109
|
+
"bookkeep",
|
|
1110
|
+
"consult",
|
|
1111
|
+
"coaching",
|
|
1112
|
+
"financ",
|
|
1113
|
+
"insurance",
|
|
1114
|
+
"realtor",
|
|
1115
|
+
"estate",
|
|
1116
|
+
"marketing",
|
|
1117
|
+
"agency",
|
|
1118
|
+
"office",
|
|
1119
|
+
"business",
|
|
1120
|
+
"desk"
|
|
1121
|
+
],
|
|
1122
|
+
pool: [
|
|
1123
|
+
U("1497366216548-37526070297c"),
|
|
1124
|
+
U("1497366811353-6870744d04b2"),
|
|
1125
|
+
U("1454165804606-c3d57bc86b40"),
|
|
1126
|
+
U("1521791136064-7986c2920216"),
|
|
1127
|
+
U("1556761175-b413da4baf72"),
|
|
1128
|
+
U("1542744173-8e7e53415bb0")
|
|
1129
|
+
]
|
|
1130
|
+
},
|
|
1131
|
+
{
|
|
1132
|
+
keywords: [
|
|
1133
|
+
"wedding",
|
|
1134
|
+
"event",
|
|
1135
|
+
"party",
|
|
1136
|
+
"celebrat",
|
|
1137
|
+
"venue",
|
|
1138
|
+
"community",
|
|
1139
|
+
"nonprofit",
|
|
1140
|
+
"charity",
|
|
1141
|
+
"workshop",
|
|
1142
|
+
"photograph",
|
|
1143
|
+
"concert"
|
|
1144
|
+
],
|
|
1145
|
+
pool: [
|
|
1146
|
+
U("1511578314322-379afb476865"),
|
|
1147
|
+
U("1501281668745-f7f57925c3b4"),
|
|
1148
|
+
U("1523580494863-6f3031224c94"),
|
|
1149
|
+
U("1540575467063-178a50c2df87"),
|
|
1150
|
+
U("1505236858219-8359eb29e329"),
|
|
1151
|
+
U("1528605248644-14dd04022da1")
|
|
1152
|
+
]
|
|
1153
|
+
}
|
|
1154
|
+
];
|
|
1155
|
+
function poolForSubject(subject) {
|
|
1156
|
+
for (const theme of THEMED) {
|
|
1157
|
+
if (theme.keywords.some((k) => subject.includes(k))) {
|
|
1158
|
+
return theme.pool;
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
return GENERIC;
|
|
1162
|
+
}
|
|
1163
|
+
function mixedHash(text) {
|
|
1164
|
+
let hash = 2166136261;
|
|
1165
|
+
for (let i = 0; i < text.length; i++) {
|
|
1166
|
+
hash ^= text.charCodeAt(i);
|
|
1167
|
+
hash = Math.imul(hash, 16777619);
|
|
1168
|
+
}
|
|
1169
|
+
return hash >>> 16 & 65535;
|
|
1170
|
+
}
|
|
1171
|
+
function resolvePlaceholderRef(ref) {
|
|
1172
|
+
const match = /^placeholder:([a-z0-9-]+)$/.exec(ref);
|
|
1173
|
+
if (!match) return null;
|
|
1174
|
+
const subject = match[1];
|
|
1175
|
+
const pool = poolForSubject(subject.replace(/-\d+$/, ""));
|
|
1176
|
+
return pool[mixedHash(ref) % pool.length];
|
|
1177
|
+
}
|
|
1178
|
+
function collectPlaceholderRefs(tree) {
|
|
1179
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1180
|
+
for (const match of JSON.stringify(tree ?? null).matchAll(/"(placeholder:[a-z0-9-]+)"/gu)) {
|
|
1181
|
+
seen.add(match[1]);
|
|
1182
|
+
}
|
|
1183
|
+
return [...seen];
|
|
1184
|
+
}
|
|
1185
|
+
function buildPlaceholderMap(tree) {
|
|
1186
|
+
const map = {};
|
|
1187
|
+
const cursor = /* @__PURE__ */ new Map();
|
|
1188
|
+
for (const ref of collectPlaceholderRefs(tree)) {
|
|
1189
|
+
const subject = ref.slice("placeholder:".length).replace(/-\d+$/, "");
|
|
1190
|
+
const pool = poolForSubject(subject);
|
|
1191
|
+
const start = cursor.get(pool) ?? mixedHash(ref) % pool.length;
|
|
1192
|
+
map[ref] = pool[start % pool.length];
|
|
1193
|
+
cursor.set(pool, start + 1);
|
|
1194
|
+
}
|
|
1195
|
+
return map;
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
// src/ui/ai-tree/AiTreeRenderer.tsx
|
|
916
1199
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
917
1200
|
function lucideByName(name) {
|
|
918
1201
|
const pascal = name.split("-").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
@@ -926,6 +1209,7 @@ var typeStyle = (spec, font) => ({
|
|
|
926
1209
|
fontWeight: spec.weight
|
|
927
1210
|
});
|
|
928
1211
|
var str = (value) => typeof value === "string" ? value : "";
|
|
1212
|
+
var cardRadius = (slots) => slots.cornerStyle === "sharp" ? 0 : AI_TREE_TOKENS.radiusCard;
|
|
929
1213
|
var featureLines = (value) => value.split(/\n|<br\s*\/?>/i).map((line) => line.trim()).filter(Boolean);
|
|
930
1214
|
var CHECK_MASK = `data:image/svg+xml,${encodeURIComponent(
|
|
931
1215
|
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>'
|
|
@@ -952,6 +1236,25 @@ var FEATURE_LINE_CSS = [
|
|
|
952
1236
|
`background-color:currentColor;-webkit-mask:url("${CHECK_MASK}") no-repeat 0 0/24px 24px;`,
|
|
953
1237
|
`mask:url("${CHECK_MASK}") no-repeat 0 0/24px 24px}`
|
|
954
1238
|
].join("");
|
|
1239
|
+
function buttonShellStyle(ctx, fullWidth) {
|
|
1240
|
+
const bs = ctx.buttonStyle;
|
|
1241
|
+
if (bs) {
|
|
1242
|
+
return {
|
|
1243
|
+
borderRadius: bs.radius,
|
|
1244
|
+
...bs.padding ? { padding: bs.padding } : {},
|
|
1245
|
+
...bs.fontFamily ? { fontFamily: bs.fontFamily } : { fontFamily: ctx.brand.fonts.body },
|
|
1246
|
+
...bs.fontSize ? { fontSize: bs.fontSize } : {},
|
|
1247
|
+
...bs.fontWeight ? { fontWeight: bs.fontWeight } : {},
|
|
1248
|
+
...bs.letterSpacing && bs.letterSpacing !== "normal" ? { letterSpacing: bs.letterSpacing } : {},
|
|
1249
|
+
...bs.textTransform && bs.textTransform !== "none" ? { textTransform: bs.textTransform } : {}
|
|
1250
|
+
};
|
|
1251
|
+
}
|
|
1252
|
+
return {
|
|
1253
|
+
borderRadius: AI_TREE_TOKENS.radiusButton,
|
|
1254
|
+
padding: fullWidth ? `${AI_TREE_TOKENS.spacing2}px ${AI_TREE_TOKENS.spacing4}px` : `${AI_TREE_TOKENS.spacing3}px ${AI_TREE_TOKENS.spacing6}px`,
|
|
1255
|
+
...typeStyle(AI_TREE_TOKENS.type.button, ctx.brand.fonts.body)
|
|
1256
|
+
};
|
|
1257
|
+
}
|
|
955
1258
|
function hexLuminance(color) {
|
|
956
1259
|
const m = /^#([0-9a-f]{6})$/i.exec(color.trim());
|
|
957
1260
|
if (!m) return null;
|
|
@@ -968,6 +1271,12 @@ function hexContrast(a, b) {
|
|
|
968
1271
|
const [hi, lo] = la > lb ? [la, lb] : [lb, la];
|
|
969
1272
|
return (hi + 0.05) / (lo + 0.05);
|
|
970
1273
|
}
|
|
1274
|
+
function primaryButtonLabel(brand) {
|
|
1275
|
+
const darkC = hexContrast(brand.palette.primary, brand.palette.dark);
|
|
1276
|
+
const lightC = hexContrast(brand.palette.primary, AI_TREE_TOKENS.textPrimaryForeground);
|
|
1277
|
+
if (darkC === null || lightC === null) return AI_TREE_TOKENS.textPrimaryForeground;
|
|
1278
|
+
return darkC > lightC ? brand.palette.dark : AI_TREE_TOKENS.textPrimaryForeground;
|
|
1279
|
+
}
|
|
971
1280
|
function accentBandContext(brand) {
|
|
972
1281
|
const p = brand.palette;
|
|
973
1282
|
const lightWins = (hexContrast(p.light, p.primary) ?? 99) >= (hexContrast(p.dark, p.primary) ?? 0);
|
|
@@ -1067,12 +1376,10 @@ function ButtonEl({
|
|
|
1067
1376
|
width: fullWidth ? "100%" : void 0,
|
|
1068
1377
|
alignItems: "center",
|
|
1069
1378
|
justifyContent: "center",
|
|
1070
|
-
padding: fullWidth ? `${AI_TREE_TOKENS.spacing2}px ${AI_TREE_TOKENS.spacing4}px` : `${AI_TREE_TOKENS.spacing3}px ${AI_TREE_TOKENS.spacing6}px`,
|
|
1071
|
-
borderRadius: AI_TREE_TOKENS.radiusButton,
|
|
1072
1379
|
textDecoration: "none",
|
|
1073
1380
|
cursor: "pointer",
|
|
1074
|
-
...
|
|
1075
|
-
...secondary ? { border: `1px solid ${ctx.brand.palette.dark}`, color: ctx.brand.palette.dark } : { background: ctx.brand.palette.primary, color: ctx.buttonLabel ??
|
|
1381
|
+
...buttonShellStyle(ctx, fullWidth),
|
|
1382
|
+
...secondary ? { border: `1px solid ${ctx.brand.palette.dark}`, color: ctx.brand.palette.dark } : { background: ctx.brand.palette.primary, color: ctx.buttonLabel ?? primaryButtonLabel(ctx.brand) }
|
|
1076
1383
|
},
|
|
1077
1384
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...path ? textAttrs(ctx, `${path}.label`) : {}, children: str(slots.label) })
|
|
1078
1385
|
}
|
|
@@ -1248,10 +1555,11 @@ function PricingCard({ node, ctx, path }) {
|
|
|
1248
1555
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1249
1556
|
"div",
|
|
1250
1557
|
{
|
|
1558
|
+
"data-ohw-card": "",
|
|
1251
1559
|
style: {
|
|
1252
1560
|
background: hasBg ? ctx.brand.palette.light : "transparent",
|
|
1253
1561
|
border: `1px solid ${dark}`,
|
|
1254
|
-
borderRadius:
|
|
1562
|
+
borderRadius: cardRadius(slots),
|
|
1255
1563
|
padding: AI_TREE_TOKENS.paddingBlock,
|
|
1256
1564
|
display: "flex",
|
|
1257
1565
|
flexDirection: "column",
|
|
@@ -1356,10 +1664,11 @@ function TestimonialCard({ node, ctx, path }) {
|
|
|
1356
1664
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1357
1665
|
"div",
|
|
1358
1666
|
{
|
|
1667
|
+
"data-ohw-card": "",
|
|
1359
1668
|
"data-ai-avatar-pos": avatarPos ?? void 0,
|
|
1360
1669
|
style: {
|
|
1361
1670
|
background: hasBg ? ctx.cardSurface : "transparent",
|
|
1362
|
-
borderRadius: hasBg ?
|
|
1671
|
+
borderRadius: hasBg ? cardRadius(slots) : 0,
|
|
1363
1672
|
overflow: "hidden",
|
|
1364
1673
|
outline: slots.featured === true ? `2px solid ${ctx.brand.palette.primary}` : void 0,
|
|
1365
1674
|
minWidth: 0
|
|
@@ -1394,10 +1703,11 @@ function TeamCard({ node, ctx, path }) {
|
|
|
1394
1703
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1395
1704
|
"div",
|
|
1396
1705
|
{
|
|
1706
|
+
"data-ohw-card": "",
|
|
1397
1707
|
"data-ai-avatar-pos": avatarPos ?? void 0,
|
|
1398
1708
|
style: {
|
|
1399
1709
|
background: hasBg ? ctx.cardSurface : "transparent",
|
|
1400
|
-
borderRadius: hasBg ?
|
|
1710
|
+
borderRadius: hasBg ? cardRadius(slots) : 0,
|
|
1401
1711
|
overflow: "hidden",
|
|
1402
1712
|
outline: slots.featured === true ? `2px solid ${ctx.brand.palette.primary}` : void 0,
|
|
1403
1713
|
minWidth: 0,
|
|
@@ -1568,9 +1878,10 @@ function CardBlock({ node, ctx, path }) {
|
|
|
1568
1878
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1569
1879
|
"div",
|
|
1570
1880
|
{
|
|
1881
|
+
"data-ohw-card": "",
|
|
1571
1882
|
style: {
|
|
1572
1883
|
background: hasBg ? ctx.cardSurface : "transparent",
|
|
1573
|
-
borderRadius: hasBg ?
|
|
1884
|
+
borderRadius: hasBg ? cardRadius(slots) : 0,
|
|
1574
1885
|
overflow: "hidden",
|
|
1575
1886
|
outline: slots.featured === true ? `2px solid ${ctx.brand.palette.primary}` : void 0,
|
|
1576
1887
|
display: horizontal ? "flex" : "block",
|
|
@@ -1598,7 +1909,7 @@ function CardBlock({ node, ctx, path }) {
|
|
|
1598
1909
|
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1599
1910
|
"div",
|
|
1600
1911
|
{
|
|
1601
|
-
style: /^(lucide|simple):/.test(mediaRef) ? { padding: `${AI_TREE_TOKENS.paddingBlock}px ${AI_TREE_TOKENS.paddingBlock}px 0` } : hasBg ? void 0 : { borderRadius:
|
|
1912
|
+
style: /^(lucide|simple):/.test(mediaRef) ? { padding: `${AI_TREE_TOKENS.paddingBlock}px ${AI_TREE_TOKENS.paddingBlock}px 0` } : hasBg ? void 0 : { borderRadius: cardRadius(slots), overflow: "hidden" },
|
|
1602
1913
|
children: media
|
|
1603
1914
|
}
|
|
1604
1915
|
)),
|
|
@@ -2009,6 +2320,32 @@ function renderNode(node, ctx, path) {
|
|
|
2009
2320
|
if (child) {
|
|
2010
2321
|
return renderNode(child, ctx, `${path}.c0`);
|
|
2011
2322
|
}
|
|
2323
|
+
if (str(slots.provider) === "map" && str(slots.query)) {
|
|
2324
|
+
const query = str(slots.query);
|
|
2325
|
+
const mapAttrs = ctx.keyFor ? {
|
|
2326
|
+
"data-ohw-key": ctx.keyFor(`${path}.query`),
|
|
2327
|
+
"data-ohw-editable": "map",
|
|
2328
|
+
"data-ohw-map-query": query
|
|
2329
|
+
} : {};
|
|
2330
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2331
|
+
"iframe",
|
|
2332
|
+
{
|
|
2333
|
+
...mapAttrs,
|
|
2334
|
+
"data-ai-embed": "map",
|
|
2335
|
+
title: str(slots.title) || "Map",
|
|
2336
|
+
src: `https://www.google.com/maps?q=${encodeURIComponent(query)}&output=embed`,
|
|
2337
|
+
loading: "lazy",
|
|
2338
|
+
referrerPolicy: "no-referrer-when-downgrade",
|
|
2339
|
+
style: {
|
|
2340
|
+
width: "100%",
|
|
2341
|
+
minHeight: 320,
|
|
2342
|
+
border: 0,
|
|
2343
|
+
borderRadius: AI_TREE_TOKENS.radiusCard,
|
|
2344
|
+
display: "block"
|
|
2345
|
+
}
|
|
2346
|
+
}
|
|
2347
|
+
);
|
|
2348
|
+
}
|
|
2012
2349
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2013
2350
|
"div",
|
|
2014
2351
|
{
|
|
@@ -2112,15 +2449,12 @@ function renderNode(node, ctx, path) {
|
|
|
2112
2449
|
alignSelf: submitAlign,
|
|
2113
2450
|
border: "none",
|
|
2114
2451
|
cursor: "pointer",
|
|
2115
|
-
padding
|
|
2116
|
-
|
|
2117
|
-
// CTA); 8px only when the page has no template button to match.
|
|
2118
|
-
borderRadius: ctx.buttonRadius ?? 8,
|
|
2452
|
+
// Shape/padding/typography follow the host template's own buttons.
|
|
2453
|
+
...buttonShellStyle(ctx),
|
|
2119
2454
|
// Brand-styled: primary fill, brand-derived label colour (not a fixed token) so it
|
|
2120
2455
|
// reads correctly on custom palettes.
|
|
2121
2456
|
background: ctx.brand.palette.primary,
|
|
2122
|
-
color: ctx.buttonLabel ?? ctx.brand
|
|
2123
|
-
...typeStyle(AI_TREE_TOKENS.type.button, ctx.brand.fonts.body)
|
|
2457
|
+
color: ctx.buttonLabel ?? primaryButtonLabel(ctx.brand)
|
|
2124
2458
|
},
|
|
2125
2459
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...textAttrs(ctx, `${path}.c${i}.label`), children: str(cs.label) })
|
|
2126
2460
|
},
|
|
@@ -2155,7 +2489,7 @@ function renderNode(node, ctx, path) {
|
|
|
2155
2489
|
function AiTreeRenderer({
|
|
2156
2490
|
tree,
|
|
2157
2491
|
brand,
|
|
2158
|
-
|
|
2492
|
+
buttonStyle,
|
|
2159
2493
|
resolveMedia,
|
|
2160
2494
|
editKeyPrefix
|
|
2161
2495
|
}) {
|
|
@@ -2165,13 +2499,18 @@ function AiTreeRenderer({
|
|
|
2165
2499
|
const resolvedBrand = brand ?? AI_DEFAULT_BRAND;
|
|
2166
2500
|
const band = (tree.settings ?? {}).sectionBackground === "accent" ? accentBandContext(resolvedBrand) : null;
|
|
2167
2501
|
const blockBrand = band?.brand ?? resolvedBrand;
|
|
2502
|
+
const placeholderMap = buildPlaceholderMap(tree);
|
|
2168
2503
|
const ctx = {
|
|
2169
2504
|
brand: blockBrand,
|
|
2170
|
-
|
|
2505
|
+
// An owner/library ref resolves through the host resolver; a `placeholder:<subject>` ref the
|
|
2506
|
+
// host cannot resolve falls back to real stock photography (the per-section map first, then a
|
|
2507
|
+
// standalone resolve), so generated galleries, image rows, and overlay backgrounds arrive with
|
|
2508
|
+
// photos instead of grey boxes.
|
|
2509
|
+
resolveMedia: (ref) => resolveMedia?.(ref) ?? placeholderMap[ref] ?? resolvePlaceholderRef(ref),
|
|
2171
2510
|
cardSurface: blockBrand.palette.light.toUpperCase() === AI_DEFAULT_BRAND.palette.light.toUpperCase() ? "#ECECEB" : `color-mix(in srgb, ${blockBrand.palette.light} 90%, ${blockBrand.palette.dark})`,
|
|
2172
2511
|
keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null,
|
|
2173
2512
|
sectionAlignment: (tree.settings ?? {}).alignment === "center" ? "center" : "left",
|
|
2174
|
-
|
|
2513
|
+
buttonStyle,
|
|
2175
2514
|
...band ? { buttonLabel: band.buttonLabel } : {}
|
|
2176
2515
|
};
|
|
2177
2516
|
const settings = tree.settings ?? {};
|
|
@@ -2301,13 +2640,13 @@ function deriveBrandOverride() {
|
|
|
2301
2640
|
};
|
|
2302
2641
|
}
|
|
2303
2642
|
function deriveTemplateBrand() {
|
|
2304
|
-
const
|
|
2305
|
-
const
|
|
2306
|
-
const light = readRootVar("--color-light");
|
|
2643
|
+
const primary = readRootVar("--brand-primary") || readRootVar("--color-primary");
|
|
2644
|
+
const dark = readRootVar("--brand-text") || readRootVar("--color-dark");
|
|
2645
|
+
const light = readRootVar("--brand-background") || readRootVar("--color-light");
|
|
2307
2646
|
if (!dark || !primary || !light) return null;
|
|
2308
|
-
const accent = readRootVar("--color-accent");
|
|
2309
|
-
const heading = readRootVar("--font-heading") || readRootVar("--font-display");
|
|
2310
|
-
const body = readRootVar("--font-body");
|
|
2647
|
+
const accent = readRootVar("--brand-accent") || readRootVar("--color-accent");
|
|
2648
|
+
const heading = readRootVar("--brand-font-heading") || readRootVar("--font-heading") || readRootVar("--font-display");
|
|
2649
|
+
const body = readRootVar("--brand-font-body") || readRootVar("--font-body");
|
|
2311
2650
|
return {
|
|
2312
2651
|
palette: { dark, primary, accent: accent || dark, light },
|
|
2313
2652
|
fonts: {
|
|
@@ -2316,12 +2655,32 @@ function deriveTemplateBrand() {
|
|
|
2316
2655
|
}
|
|
2317
2656
|
};
|
|
2318
2657
|
}
|
|
2319
|
-
function
|
|
2658
|
+
function deriveTemplateButtonStyle() {
|
|
2320
2659
|
if (typeof document === "undefined") return null;
|
|
2321
|
-
const btn = document.
|
|
2660
|
+
const btn = Array.from(document.querySelectorAll('[data-ohw-role="button"]')).find(
|
|
2661
|
+
(el) => !el.closest(`[${CONTAINER_ATTR}]`)
|
|
2662
|
+
);
|
|
2322
2663
|
if (!btn) return null;
|
|
2323
|
-
const
|
|
2324
|
-
|
|
2664
|
+
const cs = getComputedStyle(btn);
|
|
2665
|
+
const corners = [
|
|
2666
|
+
cs.borderTopLeftRadius,
|
|
2667
|
+
cs.borderTopRightRadius,
|
|
2668
|
+
cs.borderBottomRightRadius,
|
|
2669
|
+
cs.borderBottomLeftRadius
|
|
2670
|
+
].map((v) => v || "0px");
|
|
2671
|
+
const radius = corners.every((v) => v === corners[0]) ? corners[0] : corners.join(" ");
|
|
2672
|
+
const px = (v) => parseFloat(v) || 0;
|
|
2673
|
+
const padY = Math.max(px(cs.paddingTop), px(cs.paddingBottom));
|
|
2674
|
+
const padX = Math.max(px(cs.paddingLeft), px(cs.paddingRight));
|
|
2675
|
+
return {
|
|
2676
|
+
radius: radius || "10px",
|
|
2677
|
+
padding: `${padY}px ${padX}px`,
|
|
2678
|
+
fontFamily: cs.fontFamily || "",
|
|
2679
|
+
fontSize: cs.fontSize || "",
|
|
2680
|
+
fontWeight: cs.fontWeight || "",
|
|
2681
|
+
letterSpacing: cs.letterSpacing || "",
|
|
2682
|
+
textTransform: cs.textTransform || ""
|
|
2683
|
+
};
|
|
2325
2684
|
}
|
|
2326
2685
|
var mounted = /* @__PURE__ */ new Map();
|
|
2327
2686
|
function findTemplateSection(id) {
|
|
@@ -2492,7 +2851,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
2492
2851
|
if (typeof document === "undefined") return;
|
|
2493
2852
|
const brandOverride = deriveBrandOverride();
|
|
2494
2853
|
const templateBrand = deriveTemplateBrand();
|
|
2495
|
-
const
|
|
2854
|
+
const templateButtonStyle = deriveTemplateButtonStyle();
|
|
2496
2855
|
const brandKey = brandOverride ? JSON.stringify(brandOverride) : "";
|
|
2497
2856
|
const pagePath = window.location.pathname;
|
|
2498
2857
|
const pageSections = state.sections.filter((entry) => (entry.path ?? "/") === pagePath);
|
|
@@ -2532,7 +2891,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
2532
2891
|
{
|
|
2533
2892
|
tree: entry.tree,
|
|
2534
2893
|
brand: brandOverride ?? entry.brand ?? options?.brand ?? templateBrand ?? void 0,
|
|
2535
|
-
|
|
2894
|
+
buttonStyle: templateButtonStyle,
|
|
2536
2895
|
resolveMedia,
|
|
2537
2896
|
editKeyPrefix: `ai.${entry.id}`
|
|
2538
2897
|
}
|
|
@@ -14625,6 +14984,9 @@ function collectEditableNodes(extraContent, root = document) {
|
|
|
14625
14984
|
if (el.dataset.ohwEditable === "link") {
|
|
14626
14985
|
return { key: el.dataset.ohwKey ?? "", type: "link", text: getLinkHref3(el) };
|
|
14627
14986
|
}
|
|
14987
|
+
if (el.dataset.ohwEditable === "map") {
|
|
14988
|
+
return { key: el.dataset.ohwKey ?? "", type: "map", text: el.dataset.ohwMapQuery ?? "" };
|
|
14989
|
+
}
|
|
14628
14990
|
return {
|
|
14629
14991
|
key: el.dataset.ohwKey ?? "",
|
|
14630
14992
|
type: el.dataset.ohwEditable ?? "text",
|
|
@@ -15408,7 +15770,7 @@ var EDITOR_CHROME_SELECTOR = '[data-ohw-toolbar], [data-ohw-form-toolbar], [data
|
|
|
15408
15770
|
function isOverEditorChrome(x, y) {
|
|
15409
15771
|
return document.elementsFromPoint(x, y).some((el) => el instanceof HTMLElement && el.matches(EDITOR_CHROME_SELECTOR));
|
|
15410
15772
|
}
|
|
15411
|
-
var NON_MEDIA_SELECTOR = '[data-ohw-editable]:not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]):not([data-ohw-editable="video"]):not([data-ohw-editable="icon"]):not([data-ohw-editable="form"])';
|
|
15773
|
+
var NON_MEDIA_SELECTOR = '[data-ohw-editable]:not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]):not([data-ohw-editable="video"]):not([data-ohw-editable="icon"]):not([data-ohw-editable="form"]):not([data-ohw-editable="map"])';
|
|
15412
15774
|
function getVideoEl2(el) {
|
|
15413
15775
|
return el instanceof HTMLVideoElement ? el : el.querySelector("video");
|
|
15414
15776
|
}
|
|
@@ -15464,6 +15826,12 @@ function applyVideoSettingNode(key, val) {
|
|
|
15464
15826
|
});
|
|
15465
15827
|
return true;
|
|
15466
15828
|
}
|
|
15829
|
+
function applyMapQuery(el, val) {
|
|
15830
|
+
if (!(el instanceof HTMLIFrameElement)) return;
|
|
15831
|
+
const nextSrc = `https://www.google.com/maps?q=${encodeURIComponent(val)}&output=embed`;
|
|
15832
|
+
if (el.src !== nextSrc) el.src = nextSrc;
|
|
15833
|
+
el.setAttribute("data-ohw-map-query", val);
|
|
15834
|
+
}
|
|
15467
15835
|
function applyLinkByKey(key, val) {
|
|
15468
15836
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
15469
15837
|
if (el.dataset.ohwEditable === "link") applyLinkHref(el, val);
|
|
@@ -18264,6 +18632,8 @@ function OhhwellsBridge() {
|
|
|
18264
18632
|
}
|
|
18265
18633
|
} else if (el.dataset.ohwEditable === "link") {
|
|
18266
18634
|
applyLinkHref(el, val);
|
|
18635
|
+
} else if (el.dataset.ohwEditable === "map") {
|
|
18636
|
+
applyMapQuery(el, val);
|
|
18267
18637
|
} else if (el.dataset.ohwEditable === "icon") {
|
|
18268
18638
|
applyIconMarkup(el, val);
|
|
18269
18639
|
} else if (el.dataset.ohwEditable === "form") {
|
|
@@ -18460,6 +18830,8 @@ function OhhwellsBridge() {
|
|
|
18460
18830
|
if (video && video.src !== val) applyVideoSrc(video, val);
|
|
18461
18831
|
} else if (el.dataset.ohwEditable === "link") {
|
|
18462
18832
|
applyLinkHref(el, val);
|
|
18833
|
+
} else if (el.dataset.ohwEditable === "map") {
|
|
18834
|
+
applyMapQuery(el, val);
|
|
18463
18835
|
} else if (el.dataset.ohwEditable === "form") {
|
|
18464
18836
|
} else if (isIconMarkupValue(val)) {
|
|
18465
18837
|
} else if (el.innerHTML !== val) {
|
|
@@ -20433,6 +20805,8 @@ function OhhwellsBridge() {
|
|
|
20433
20805
|
if (video && video.src !== val) applyVideoSrc(video, val);
|
|
20434
20806
|
} else if (el.dataset.ohwEditable === "link") {
|
|
20435
20807
|
applyLinkHref(el, val);
|
|
20808
|
+
} else if (el.dataset.ohwEditable === "map") {
|
|
20809
|
+
applyMapQuery(el, val);
|
|
20436
20810
|
} else if (el.dataset.ohwEditable === "icon") {
|
|
20437
20811
|
applyIconMarkup(el, val);
|
|
20438
20812
|
} else if (isIconMarkupValue(val)) {
|
|
@@ -21669,7 +22043,7 @@ function OhhwellsBridge() {
|
|
|
21669
22043
|
postToParent2({
|
|
21670
22044
|
type: "ow:ready",
|
|
21671
22045
|
version: "1",
|
|
21672
|
-
bridgeVersion: "0.1.
|
|
22046
|
+
bridgeVersion: "0.1.96",
|
|
21673
22047
|
path: pathname,
|
|
21674
22048
|
nodes: collectEditableNodes(editContentRef.current),
|
|
21675
22049
|
sections
|