@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.js
CHANGED
|
@@ -418,6 +418,10 @@ function styleSheetCss() {
|
|
|
418
418
|
`[data-ohw-style-spacing="${spacing}"] { padding-top: ${px}px !important; padding-bottom: ${px}px !important; }`
|
|
419
419
|
);
|
|
420
420
|
}
|
|
421
|
+
rules.push(
|
|
422
|
+
`[data-ohw-style-corners="sharp"] :is(.card, [data-ohw-card], img, picture, figure, [data-ohw-editable="bg-image"]) { border-radius: 0 !important; }`,
|
|
423
|
+
`[data-ohw-style-corners="sharp"] :has(> img) { border-radius: 0 !important; }`
|
|
424
|
+
);
|
|
421
425
|
for (const align of ["left", "center", "right"]) {
|
|
422
426
|
rules.push(`[data-ohw-style-align="${align}"] { text-align: ${align} !important; }`);
|
|
423
427
|
}
|
|
@@ -448,6 +452,7 @@ var SECTION_ATTRS = {
|
|
|
448
452
|
headlineScale: "data-ohw-style-headline",
|
|
449
453
|
imageAspect: "data-ohw-style-aspect",
|
|
450
454
|
spacing: "data-ohw-style-spacing",
|
|
455
|
+
cornerStyle: "data-ohw-style-corners",
|
|
451
456
|
align: "data-ohw-style-align"
|
|
452
457
|
};
|
|
453
458
|
var NODE_WROTE_ATTR = "data-ohw-style-node";
|
|
@@ -840,6 +845,284 @@ function initSectionInstancesFromContent(content, currentPath) {
|
|
|
840
845
|
// src/ui/ai-tree/AiTreeRenderer.tsx
|
|
841
846
|
import React from "react";
|
|
842
847
|
import { ArrowLeft, ArrowRight, ChevronDown, icons as lucideIcons } from "lucide-react";
|
|
848
|
+
|
|
849
|
+
// src/lib/placeholder-imagery.ts
|
|
850
|
+
var U = (id) => `https://images.unsplash.com/photo-${id}?auto=format&fit=crop&w=1600&q=80`;
|
|
851
|
+
var GENERIC = [
|
|
852
|
+
U("1441986300917-64674bd600d8"),
|
|
853
|
+
U("1486406146926-c627a92ad1ab"),
|
|
854
|
+
U("1497032628192-86f99bcd76bc"),
|
|
855
|
+
U("1521737604893-d14cc237f11d"),
|
|
856
|
+
U("1522071820081-009f0129c71c"),
|
|
857
|
+
U("1519389950473-47ba0277781c"),
|
|
858
|
+
U("1460925895917-afdab827c52f"),
|
|
859
|
+
U("1504384308090-c894fdcc538d")
|
|
860
|
+
];
|
|
861
|
+
var PEOPLE = [
|
|
862
|
+
U("1500648767791-00dcc994a43e"),
|
|
863
|
+
U("1494790108377-be9c29b29330"),
|
|
864
|
+
U("1507003211169-0a1dd7228f2d"),
|
|
865
|
+
U("1438761681033-6461ffad8d80"),
|
|
866
|
+
U("1544005313-94ddf0286df2"),
|
|
867
|
+
U("1472099645785-5658abf4ff4e"),
|
|
868
|
+
U("1519085360753-af0119f7cbe7"),
|
|
869
|
+
U("1534528741775-53994a69daeb")
|
|
870
|
+
];
|
|
871
|
+
var THEMED = [
|
|
872
|
+
{
|
|
873
|
+
keywords: ["portrait", "headshot", "person", "people", "team", "staff", "avatar", "founder", "face"],
|
|
874
|
+
pool: PEOPLE
|
|
875
|
+
},
|
|
876
|
+
{
|
|
877
|
+
keywords: ["pet", "dog", "cat", "puppy", "kitten", "vet", "animal"],
|
|
878
|
+
pool: [
|
|
879
|
+
U("1548199973-03cce0bbc87b"),
|
|
880
|
+
U("1450778869180-41d0601e046e"),
|
|
881
|
+
U("1583511655857-d19b40a7a54e"),
|
|
882
|
+
U("1587300003388-59208cc962cb"),
|
|
883
|
+
U("1517849845537-4d257902454a"),
|
|
884
|
+
U("1601758228041-f3b2795255f1")
|
|
885
|
+
]
|
|
886
|
+
},
|
|
887
|
+
{
|
|
888
|
+
keywords: [
|
|
889
|
+
"baker",
|
|
890
|
+
"bakery",
|
|
891
|
+
"cafe",
|
|
892
|
+
"coffee",
|
|
893
|
+
"latte",
|
|
894
|
+
"restaurant",
|
|
895
|
+
"pastr",
|
|
896
|
+
"bread",
|
|
897
|
+
"cake",
|
|
898
|
+
"cater",
|
|
899
|
+
"chef",
|
|
900
|
+
"kitchen",
|
|
901
|
+
"food",
|
|
902
|
+
"pizza",
|
|
903
|
+
"dessert",
|
|
904
|
+
"brunch",
|
|
905
|
+
"bistro",
|
|
906
|
+
"deli",
|
|
907
|
+
"dish",
|
|
908
|
+
"menu"
|
|
909
|
+
],
|
|
910
|
+
pool: [
|
|
911
|
+
U("1509440159596-0249088772ff"),
|
|
912
|
+
U("1555507036-ab1f4038808a"),
|
|
913
|
+
U("1517433670267-08bbd4be890f"),
|
|
914
|
+
U("1486427944299-d1955d23e34d"),
|
|
915
|
+
U("1504754524776-8f4f37790ca0"),
|
|
916
|
+
U("1495474472287-4d71bcdd2085"),
|
|
917
|
+
U("1521017432531-fbd92d768814"),
|
|
918
|
+
U("1556909114-f6e7ad7d3136")
|
|
919
|
+
]
|
|
920
|
+
},
|
|
921
|
+
{
|
|
922
|
+
keywords: [
|
|
923
|
+
"shop",
|
|
924
|
+
"store",
|
|
925
|
+
"boutique",
|
|
926
|
+
"retail",
|
|
927
|
+
"clothing",
|
|
928
|
+
"fashion",
|
|
929
|
+
"jewel",
|
|
930
|
+
"gift",
|
|
931
|
+
"florist",
|
|
932
|
+
"market",
|
|
933
|
+
"grocer",
|
|
934
|
+
"product",
|
|
935
|
+
"storefront"
|
|
936
|
+
],
|
|
937
|
+
pool: [
|
|
938
|
+
U("1441984904996-e0b6ba687e04"),
|
|
939
|
+
U("1472851294608-062f824d29cc"),
|
|
940
|
+
U("1523381210434-271e8be1f52b"),
|
|
941
|
+
U("1534452203293-494d7ddbf7e0"),
|
|
942
|
+
U("1445205170230-053b83016050"),
|
|
943
|
+
U("1560243563-062bfc001d68")
|
|
944
|
+
]
|
|
945
|
+
},
|
|
946
|
+
{
|
|
947
|
+
keywords: [
|
|
948
|
+
"yoga",
|
|
949
|
+
"pilates",
|
|
950
|
+
"fitness",
|
|
951
|
+
"gym",
|
|
952
|
+
"workout",
|
|
953
|
+
"trainer",
|
|
954
|
+
"wellness",
|
|
955
|
+
"meditat",
|
|
956
|
+
"massage",
|
|
957
|
+
"therap",
|
|
958
|
+
"physio",
|
|
959
|
+
"chiro",
|
|
960
|
+
"nutrition",
|
|
961
|
+
"spa",
|
|
962
|
+
"studio"
|
|
963
|
+
],
|
|
964
|
+
pool: [
|
|
965
|
+
U("1544367567-0f2fcb009e0b"),
|
|
966
|
+
U("1506126613408-eca07ce68773"),
|
|
967
|
+
U("1545205597-3d9d02c29597"),
|
|
968
|
+
U("1552196563-55cd4e45efb3"),
|
|
969
|
+
U("1518611012118-696072aa579a"),
|
|
970
|
+
U("1571019613454-1cb2f99b2d8b"),
|
|
971
|
+
U("1540555700478-4be289fbecef"),
|
|
972
|
+
U("1519824145371-296894a0daa9")
|
|
973
|
+
]
|
|
974
|
+
},
|
|
975
|
+
{
|
|
976
|
+
keywords: [
|
|
977
|
+
"salon",
|
|
978
|
+
"hairdress",
|
|
979
|
+
"haircut",
|
|
980
|
+
"barber",
|
|
981
|
+
"manicure",
|
|
982
|
+
"pedicure",
|
|
983
|
+
"nails",
|
|
984
|
+
"beauty",
|
|
985
|
+
"makeup",
|
|
986
|
+
"cosmetic",
|
|
987
|
+
"eyelash",
|
|
988
|
+
"eyebrow",
|
|
989
|
+
"skincare",
|
|
990
|
+
"esthetic",
|
|
991
|
+
"waxing",
|
|
992
|
+
"hair"
|
|
993
|
+
],
|
|
994
|
+
pool: [
|
|
995
|
+
U("1560066984-138dadb4c035"),
|
|
996
|
+
U("1522337660859-02fbefca4702"),
|
|
997
|
+
U("1562322140-8baeececf3df"),
|
|
998
|
+
U("1521590832167-7bcbfaa6381f"),
|
|
999
|
+
U("1487412947147-5cebf100ffc2"),
|
|
1000
|
+
U("1526045478516-99145907023c")
|
|
1001
|
+
]
|
|
1002
|
+
},
|
|
1003
|
+
{
|
|
1004
|
+
keywords: [
|
|
1005
|
+
"cleaning",
|
|
1006
|
+
"plumb",
|
|
1007
|
+
"electric",
|
|
1008
|
+
"landscap",
|
|
1009
|
+
"contractor",
|
|
1010
|
+
"handyman",
|
|
1011
|
+
"renov",
|
|
1012
|
+
"hvac",
|
|
1013
|
+
"roofing",
|
|
1014
|
+
"painting",
|
|
1015
|
+
"carpentry",
|
|
1016
|
+
"flooring",
|
|
1017
|
+
"movers",
|
|
1018
|
+
"construction",
|
|
1019
|
+
"tools"
|
|
1020
|
+
],
|
|
1021
|
+
pool: [
|
|
1022
|
+
U("1581578731548-c64695cc6952"),
|
|
1023
|
+
U("1504307651254-35680f356dfd"),
|
|
1024
|
+
U("1581092160562-40aa08e78837"),
|
|
1025
|
+
U("1621905251189-08b45d6a269e"),
|
|
1026
|
+
U("1558618666-fcd25c85cd64"),
|
|
1027
|
+
U("1585128792020-803d29415281")
|
|
1028
|
+
]
|
|
1029
|
+
},
|
|
1030
|
+
{
|
|
1031
|
+
keywords: [
|
|
1032
|
+
"legal",
|
|
1033
|
+
"attorney",
|
|
1034
|
+
"lawyer",
|
|
1035
|
+
"account",
|
|
1036
|
+
"bookkeep",
|
|
1037
|
+
"consult",
|
|
1038
|
+
"coaching",
|
|
1039
|
+
"financ",
|
|
1040
|
+
"insurance",
|
|
1041
|
+
"realtor",
|
|
1042
|
+
"estate",
|
|
1043
|
+
"marketing",
|
|
1044
|
+
"agency",
|
|
1045
|
+
"office",
|
|
1046
|
+
"business",
|
|
1047
|
+
"desk"
|
|
1048
|
+
],
|
|
1049
|
+
pool: [
|
|
1050
|
+
U("1497366216548-37526070297c"),
|
|
1051
|
+
U("1497366811353-6870744d04b2"),
|
|
1052
|
+
U("1454165804606-c3d57bc86b40"),
|
|
1053
|
+
U("1521791136064-7986c2920216"),
|
|
1054
|
+
U("1556761175-b413da4baf72"),
|
|
1055
|
+
U("1542744173-8e7e53415bb0")
|
|
1056
|
+
]
|
|
1057
|
+
},
|
|
1058
|
+
{
|
|
1059
|
+
keywords: [
|
|
1060
|
+
"wedding",
|
|
1061
|
+
"event",
|
|
1062
|
+
"party",
|
|
1063
|
+
"celebrat",
|
|
1064
|
+
"venue",
|
|
1065
|
+
"community",
|
|
1066
|
+
"nonprofit",
|
|
1067
|
+
"charity",
|
|
1068
|
+
"workshop",
|
|
1069
|
+
"photograph",
|
|
1070
|
+
"concert"
|
|
1071
|
+
],
|
|
1072
|
+
pool: [
|
|
1073
|
+
U("1511578314322-379afb476865"),
|
|
1074
|
+
U("1501281668745-f7f57925c3b4"),
|
|
1075
|
+
U("1523580494863-6f3031224c94"),
|
|
1076
|
+
U("1540575467063-178a50c2df87"),
|
|
1077
|
+
U("1505236858219-8359eb29e329"),
|
|
1078
|
+
U("1528605248644-14dd04022da1")
|
|
1079
|
+
]
|
|
1080
|
+
}
|
|
1081
|
+
];
|
|
1082
|
+
function poolForSubject(subject) {
|
|
1083
|
+
for (const theme of THEMED) {
|
|
1084
|
+
if (theme.keywords.some((k) => subject.includes(k))) {
|
|
1085
|
+
return theme.pool;
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
return GENERIC;
|
|
1089
|
+
}
|
|
1090
|
+
function mixedHash(text) {
|
|
1091
|
+
let hash = 2166136261;
|
|
1092
|
+
for (let i = 0; i < text.length; i++) {
|
|
1093
|
+
hash ^= text.charCodeAt(i);
|
|
1094
|
+
hash = Math.imul(hash, 16777619);
|
|
1095
|
+
}
|
|
1096
|
+
return hash >>> 16 & 65535;
|
|
1097
|
+
}
|
|
1098
|
+
function resolvePlaceholderRef(ref) {
|
|
1099
|
+
const match = /^placeholder:([a-z0-9-]+)$/.exec(ref);
|
|
1100
|
+
if (!match) return null;
|
|
1101
|
+
const subject = match[1];
|
|
1102
|
+
const pool = poolForSubject(subject.replace(/-\d+$/, ""));
|
|
1103
|
+
return pool[mixedHash(ref) % pool.length];
|
|
1104
|
+
}
|
|
1105
|
+
function collectPlaceholderRefs(tree) {
|
|
1106
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1107
|
+
for (const match of JSON.stringify(tree ?? null).matchAll(/"(placeholder:[a-z0-9-]+)"/gu)) {
|
|
1108
|
+
seen.add(match[1]);
|
|
1109
|
+
}
|
|
1110
|
+
return [...seen];
|
|
1111
|
+
}
|
|
1112
|
+
function buildPlaceholderMap(tree) {
|
|
1113
|
+
const map = {};
|
|
1114
|
+
const cursor = /* @__PURE__ */ new Map();
|
|
1115
|
+
for (const ref of collectPlaceholderRefs(tree)) {
|
|
1116
|
+
const subject = ref.slice("placeholder:".length).replace(/-\d+$/, "");
|
|
1117
|
+
const pool = poolForSubject(subject);
|
|
1118
|
+
const start = cursor.get(pool) ?? mixedHash(ref) % pool.length;
|
|
1119
|
+
map[ref] = pool[start % pool.length];
|
|
1120
|
+
cursor.set(pool, start + 1);
|
|
1121
|
+
}
|
|
1122
|
+
return map;
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
// src/ui/ai-tree/AiTreeRenderer.tsx
|
|
843
1126
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
844
1127
|
function lucideByName(name) {
|
|
845
1128
|
const pascal = name.split("-").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
@@ -853,6 +1136,7 @@ var typeStyle = (spec, font) => ({
|
|
|
853
1136
|
fontWeight: spec.weight
|
|
854
1137
|
});
|
|
855
1138
|
var str = (value) => typeof value === "string" ? value : "";
|
|
1139
|
+
var cardRadius = (slots) => slots.cornerStyle === "sharp" ? 0 : AI_TREE_TOKENS.radiusCard;
|
|
856
1140
|
var featureLines = (value) => value.split(/\n|<br\s*\/?>/i).map((line) => line.trim()).filter(Boolean);
|
|
857
1141
|
var CHECK_MASK = `data:image/svg+xml,${encodeURIComponent(
|
|
858
1142
|
'<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>'
|
|
@@ -879,6 +1163,25 @@ var FEATURE_LINE_CSS = [
|
|
|
879
1163
|
`background-color:currentColor;-webkit-mask:url("${CHECK_MASK}") no-repeat 0 0/24px 24px;`,
|
|
880
1164
|
`mask:url("${CHECK_MASK}") no-repeat 0 0/24px 24px}`
|
|
881
1165
|
].join("");
|
|
1166
|
+
function buttonShellStyle(ctx, fullWidth) {
|
|
1167
|
+
const bs = ctx.buttonStyle;
|
|
1168
|
+
if (bs) {
|
|
1169
|
+
return {
|
|
1170
|
+
borderRadius: bs.radius,
|
|
1171
|
+
...bs.padding ? { padding: bs.padding } : {},
|
|
1172
|
+
...bs.fontFamily ? { fontFamily: bs.fontFamily } : { fontFamily: ctx.brand.fonts.body },
|
|
1173
|
+
...bs.fontSize ? { fontSize: bs.fontSize } : {},
|
|
1174
|
+
...bs.fontWeight ? { fontWeight: bs.fontWeight } : {},
|
|
1175
|
+
...bs.letterSpacing && bs.letterSpacing !== "normal" ? { letterSpacing: bs.letterSpacing } : {},
|
|
1176
|
+
...bs.textTransform && bs.textTransform !== "none" ? { textTransform: bs.textTransform } : {}
|
|
1177
|
+
};
|
|
1178
|
+
}
|
|
1179
|
+
return {
|
|
1180
|
+
borderRadius: AI_TREE_TOKENS.radiusButton,
|
|
1181
|
+
padding: fullWidth ? `${AI_TREE_TOKENS.spacing2}px ${AI_TREE_TOKENS.spacing4}px` : `${AI_TREE_TOKENS.spacing3}px ${AI_TREE_TOKENS.spacing6}px`,
|
|
1182
|
+
...typeStyle(AI_TREE_TOKENS.type.button, ctx.brand.fonts.body)
|
|
1183
|
+
};
|
|
1184
|
+
}
|
|
882
1185
|
function hexLuminance(color) {
|
|
883
1186
|
const m = /^#([0-9a-f]{6})$/i.exec(color.trim());
|
|
884
1187
|
if (!m) return null;
|
|
@@ -895,6 +1198,12 @@ function hexContrast(a, b) {
|
|
|
895
1198
|
const [hi, lo] = la > lb ? [la, lb] : [lb, la];
|
|
896
1199
|
return (hi + 0.05) / (lo + 0.05);
|
|
897
1200
|
}
|
|
1201
|
+
function primaryButtonLabel(brand) {
|
|
1202
|
+
const darkC = hexContrast(brand.palette.primary, brand.palette.dark);
|
|
1203
|
+
const lightC = hexContrast(brand.palette.primary, AI_TREE_TOKENS.textPrimaryForeground);
|
|
1204
|
+
if (darkC === null || lightC === null) return AI_TREE_TOKENS.textPrimaryForeground;
|
|
1205
|
+
return darkC > lightC ? brand.palette.dark : AI_TREE_TOKENS.textPrimaryForeground;
|
|
1206
|
+
}
|
|
898
1207
|
function accentBandContext(brand) {
|
|
899
1208
|
const p = brand.palette;
|
|
900
1209
|
const lightWins = (hexContrast(p.light, p.primary) ?? 99) >= (hexContrast(p.dark, p.primary) ?? 0);
|
|
@@ -994,12 +1303,10 @@ function ButtonEl({
|
|
|
994
1303
|
width: fullWidth ? "100%" : void 0,
|
|
995
1304
|
alignItems: "center",
|
|
996
1305
|
justifyContent: "center",
|
|
997
|
-
padding: fullWidth ? `${AI_TREE_TOKENS.spacing2}px ${AI_TREE_TOKENS.spacing4}px` : `${AI_TREE_TOKENS.spacing3}px ${AI_TREE_TOKENS.spacing6}px`,
|
|
998
|
-
borderRadius: AI_TREE_TOKENS.radiusButton,
|
|
999
1306
|
textDecoration: "none",
|
|
1000
1307
|
cursor: "pointer",
|
|
1001
|
-
...
|
|
1002
|
-
...secondary ? { border: `1px solid ${ctx.brand.palette.dark}`, color: ctx.brand.palette.dark } : { background: ctx.brand.palette.primary, color: ctx.buttonLabel ??
|
|
1308
|
+
...buttonShellStyle(ctx, fullWidth),
|
|
1309
|
+
...secondary ? { border: `1px solid ${ctx.brand.palette.dark}`, color: ctx.brand.palette.dark } : { background: ctx.brand.palette.primary, color: ctx.buttonLabel ?? primaryButtonLabel(ctx.brand) }
|
|
1003
1310
|
},
|
|
1004
1311
|
children: /* @__PURE__ */ jsx("span", { ...path ? textAttrs(ctx, `${path}.label`) : {}, children: str(slots.label) })
|
|
1005
1312
|
}
|
|
@@ -1175,10 +1482,11 @@ function PricingCard({ node, ctx, path }) {
|
|
|
1175
1482
|
return /* @__PURE__ */ jsxs(
|
|
1176
1483
|
"div",
|
|
1177
1484
|
{
|
|
1485
|
+
"data-ohw-card": "",
|
|
1178
1486
|
style: {
|
|
1179
1487
|
background: hasBg ? ctx.brand.palette.light : "transparent",
|
|
1180
1488
|
border: `1px solid ${dark}`,
|
|
1181
|
-
borderRadius:
|
|
1489
|
+
borderRadius: cardRadius(slots),
|
|
1182
1490
|
padding: AI_TREE_TOKENS.paddingBlock,
|
|
1183
1491
|
display: "flex",
|
|
1184
1492
|
flexDirection: "column",
|
|
@@ -1283,10 +1591,11 @@ function TestimonialCard({ node, ctx, path }) {
|
|
|
1283
1591
|
return /* @__PURE__ */ jsx(
|
|
1284
1592
|
"div",
|
|
1285
1593
|
{
|
|
1594
|
+
"data-ohw-card": "",
|
|
1286
1595
|
"data-ai-avatar-pos": avatarPos ?? void 0,
|
|
1287
1596
|
style: {
|
|
1288
1597
|
background: hasBg ? ctx.cardSurface : "transparent",
|
|
1289
|
-
borderRadius: hasBg ?
|
|
1598
|
+
borderRadius: hasBg ? cardRadius(slots) : 0,
|
|
1290
1599
|
overflow: "hidden",
|
|
1291
1600
|
outline: slots.featured === true ? `2px solid ${ctx.brand.palette.primary}` : void 0,
|
|
1292
1601
|
minWidth: 0
|
|
@@ -1321,10 +1630,11 @@ function TeamCard({ node, ctx, path }) {
|
|
|
1321
1630
|
return /* @__PURE__ */ jsxs(
|
|
1322
1631
|
"div",
|
|
1323
1632
|
{
|
|
1633
|
+
"data-ohw-card": "",
|
|
1324
1634
|
"data-ai-avatar-pos": avatarPos ?? void 0,
|
|
1325
1635
|
style: {
|
|
1326
1636
|
background: hasBg ? ctx.cardSurface : "transparent",
|
|
1327
|
-
borderRadius: hasBg ?
|
|
1637
|
+
borderRadius: hasBg ? cardRadius(slots) : 0,
|
|
1328
1638
|
overflow: "hidden",
|
|
1329
1639
|
outline: slots.featured === true ? `2px solid ${ctx.brand.palette.primary}` : void 0,
|
|
1330
1640
|
minWidth: 0,
|
|
@@ -1495,9 +1805,10 @@ function CardBlock({ node, ctx, path }) {
|
|
|
1495
1805
|
return /* @__PURE__ */ jsxs(
|
|
1496
1806
|
"div",
|
|
1497
1807
|
{
|
|
1808
|
+
"data-ohw-card": "",
|
|
1498
1809
|
style: {
|
|
1499
1810
|
background: hasBg ? ctx.cardSurface : "transparent",
|
|
1500
|
-
borderRadius: hasBg ?
|
|
1811
|
+
borderRadius: hasBg ? cardRadius(slots) : 0,
|
|
1501
1812
|
overflow: "hidden",
|
|
1502
1813
|
outline: slots.featured === true ? `2px solid ${ctx.brand.palette.primary}` : void 0,
|
|
1503
1814
|
display: horizontal ? "flex" : "block",
|
|
@@ -1525,7 +1836,7 @@ function CardBlock({ node, ctx, path }) {
|
|
|
1525
1836
|
) : /* @__PURE__ */ jsx(
|
|
1526
1837
|
"div",
|
|
1527
1838
|
{
|
|
1528
|
-
style: /^(lucide|simple):/.test(mediaRef) ? { padding: `${AI_TREE_TOKENS.paddingBlock}px ${AI_TREE_TOKENS.paddingBlock}px 0` } : hasBg ? void 0 : { borderRadius:
|
|
1839
|
+
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" },
|
|
1529
1840
|
children: media
|
|
1530
1841
|
}
|
|
1531
1842
|
)),
|
|
@@ -1936,6 +2247,32 @@ function renderNode(node, ctx, path) {
|
|
|
1936
2247
|
if (child) {
|
|
1937
2248
|
return renderNode(child, ctx, `${path}.c0`);
|
|
1938
2249
|
}
|
|
2250
|
+
if (str(slots.provider) === "map" && str(slots.query)) {
|
|
2251
|
+
const query = str(slots.query);
|
|
2252
|
+
const mapAttrs = ctx.keyFor ? {
|
|
2253
|
+
"data-ohw-key": ctx.keyFor(`${path}.query`),
|
|
2254
|
+
"data-ohw-editable": "map",
|
|
2255
|
+
"data-ohw-map-query": query
|
|
2256
|
+
} : {};
|
|
2257
|
+
return /* @__PURE__ */ jsx(
|
|
2258
|
+
"iframe",
|
|
2259
|
+
{
|
|
2260
|
+
...mapAttrs,
|
|
2261
|
+
"data-ai-embed": "map",
|
|
2262
|
+
title: str(slots.title) || "Map",
|
|
2263
|
+
src: `https://www.google.com/maps?q=${encodeURIComponent(query)}&output=embed`,
|
|
2264
|
+
loading: "lazy",
|
|
2265
|
+
referrerPolicy: "no-referrer-when-downgrade",
|
|
2266
|
+
style: {
|
|
2267
|
+
width: "100%",
|
|
2268
|
+
minHeight: 320,
|
|
2269
|
+
border: 0,
|
|
2270
|
+
borderRadius: AI_TREE_TOKENS.radiusCard,
|
|
2271
|
+
display: "block"
|
|
2272
|
+
}
|
|
2273
|
+
}
|
|
2274
|
+
);
|
|
2275
|
+
}
|
|
1939
2276
|
return /* @__PURE__ */ jsx(
|
|
1940
2277
|
"div",
|
|
1941
2278
|
{
|
|
@@ -2039,15 +2376,12 @@ function renderNode(node, ctx, path) {
|
|
|
2039
2376
|
alignSelf: submitAlign,
|
|
2040
2377
|
border: "none",
|
|
2041
2378
|
cursor: "pointer",
|
|
2042
|
-
padding
|
|
2043
|
-
|
|
2044
|
-
// CTA); 8px only when the page has no template button to match.
|
|
2045
|
-
borderRadius: ctx.buttonRadius ?? 8,
|
|
2379
|
+
// Shape/padding/typography follow the host template's own buttons.
|
|
2380
|
+
...buttonShellStyle(ctx),
|
|
2046
2381
|
// Brand-styled: primary fill, brand-derived label colour (not a fixed token) so it
|
|
2047
2382
|
// reads correctly on custom palettes.
|
|
2048
2383
|
background: ctx.brand.palette.primary,
|
|
2049
|
-
color: ctx.buttonLabel ?? ctx.brand
|
|
2050
|
-
...typeStyle(AI_TREE_TOKENS.type.button, ctx.brand.fonts.body)
|
|
2384
|
+
color: ctx.buttonLabel ?? primaryButtonLabel(ctx.brand)
|
|
2051
2385
|
},
|
|
2052
2386
|
children: /* @__PURE__ */ jsx("span", { ...textAttrs(ctx, `${path}.c${i}.label`), children: str(cs.label) })
|
|
2053
2387
|
},
|
|
@@ -2082,7 +2416,7 @@ function renderNode(node, ctx, path) {
|
|
|
2082
2416
|
function AiTreeRenderer({
|
|
2083
2417
|
tree,
|
|
2084
2418
|
brand,
|
|
2085
|
-
|
|
2419
|
+
buttonStyle,
|
|
2086
2420
|
resolveMedia,
|
|
2087
2421
|
editKeyPrefix
|
|
2088
2422
|
}) {
|
|
@@ -2092,13 +2426,18 @@ function AiTreeRenderer({
|
|
|
2092
2426
|
const resolvedBrand = brand ?? AI_DEFAULT_BRAND;
|
|
2093
2427
|
const band = (tree.settings ?? {}).sectionBackground === "accent" ? accentBandContext(resolvedBrand) : null;
|
|
2094
2428
|
const blockBrand = band?.brand ?? resolvedBrand;
|
|
2429
|
+
const placeholderMap = buildPlaceholderMap(tree);
|
|
2095
2430
|
const ctx = {
|
|
2096
2431
|
brand: blockBrand,
|
|
2097
|
-
|
|
2432
|
+
// An owner/library ref resolves through the host resolver; a `placeholder:<subject>` ref the
|
|
2433
|
+
// host cannot resolve falls back to real stock photography (the per-section map first, then a
|
|
2434
|
+
// standalone resolve), so generated galleries, image rows, and overlay backgrounds arrive with
|
|
2435
|
+
// photos instead of grey boxes.
|
|
2436
|
+
resolveMedia: (ref) => resolveMedia?.(ref) ?? placeholderMap[ref] ?? resolvePlaceholderRef(ref),
|
|
2098
2437
|
cardSurface: blockBrand.palette.light.toUpperCase() === AI_DEFAULT_BRAND.palette.light.toUpperCase() ? "#ECECEB" : `color-mix(in srgb, ${blockBrand.palette.light} 90%, ${blockBrand.palette.dark})`,
|
|
2099
2438
|
keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null,
|
|
2100
2439
|
sectionAlignment: (tree.settings ?? {}).alignment === "center" ? "center" : "left",
|
|
2101
|
-
|
|
2440
|
+
buttonStyle,
|
|
2102
2441
|
...band ? { buttonLabel: band.buttonLabel } : {}
|
|
2103
2442
|
};
|
|
2104
2443
|
const settings = tree.settings ?? {};
|
|
@@ -2228,13 +2567,13 @@ function deriveBrandOverride() {
|
|
|
2228
2567
|
};
|
|
2229
2568
|
}
|
|
2230
2569
|
function deriveTemplateBrand() {
|
|
2231
|
-
const
|
|
2232
|
-
const
|
|
2233
|
-
const light = readRootVar("--color-light");
|
|
2570
|
+
const primary = readRootVar("--brand-primary") || readRootVar("--color-primary");
|
|
2571
|
+
const dark = readRootVar("--brand-text") || readRootVar("--color-dark");
|
|
2572
|
+
const light = readRootVar("--brand-background") || readRootVar("--color-light");
|
|
2234
2573
|
if (!dark || !primary || !light) return null;
|
|
2235
|
-
const accent = readRootVar("--color-accent");
|
|
2236
|
-
const heading = readRootVar("--font-heading") || readRootVar("--font-display");
|
|
2237
|
-
const body = readRootVar("--font-body");
|
|
2574
|
+
const accent = readRootVar("--brand-accent") || readRootVar("--color-accent");
|
|
2575
|
+
const heading = readRootVar("--brand-font-heading") || readRootVar("--font-heading") || readRootVar("--font-display");
|
|
2576
|
+
const body = readRootVar("--brand-font-body") || readRootVar("--font-body");
|
|
2238
2577
|
return {
|
|
2239
2578
|
palette: { dark, primary, accent: accent || dark, light },
|
|
2240
2579
|
fonts: {
|
|
@@ -2243,12 +2582,32 @@ function deriveTemplateBrand() {
|
|
|
2243
2582
|
}
|
|
2244
2583
|
};
|
|
2245
2584
|
}
|
|
2246
|
-
function
|
|
2585
|
+
function deriveTemplateButtonStyle() {
|
|
2247
2586
|
if (typeof document === "undefined") return null;
|
|
2248
|
-
const btn = document.
|
|
2587
|
+
const btn = Array.from(document.querySelectorAll('[data-ohw-role="button"]')).find(
|
|
2588
|
+
(el) => !el.closest(`[${CONTAINER_ATTR}]`)
|
|
2589
|
+
);
|
|
2249
2590
|
if (!btn) return null;
|
|
2250
|
-
const
|
|
2251
|
-
|
|
2591
|
+
const cs = getComputedStyle(btn);
|
|
2592
|
+
const corners = [
|
|
2593
|
+
cs.borderTopLeftRadius,
|
|
2594
|
+
cs.borderTopRightRadius,
|
|
2595
|
+
cs.borderBottomRightRadius,
|
|
2596
|
+
cs.borderBottomLeftRadius
|
|
2597
|
+
].map((v) => v || "0px");
|
|
2598
|
+
const radius = corners.every((v) => v === corners[0]) ? corners[0] : corners.join(" ");
|
|
2599
|
+
const px = (v) => parseFloat(v) || 0;
|
|
2600
|
+
const padY = Math.max(px(cs.paddingTop), px(cs.paddingBottom));
|
|
2601
|
+
const padX = Math.max(px(cs.paddingLeft), px(cs.paddingRight));
|
|
2602
|
+
return {
|
|
2603
|
+
radius: radius || "10px",
|
|
2604
|
+
padding: `${padY}px ${padX}px`,
|
|
2605
|
+
fontFamily: cs.fontFamily || "",
|
|
2606
|
+
fontSize: cs.fontSize || "",
|
|
2607
|
+
fontWeight: cs.fontWeight || "",
|
|
2608
|
+
letterSpacing: cs.letterSpacing || "",
|
|
2609
|
+
textTransform: cs.textTransform || ""
|
|
2610
|
+
};
|
|
2252
2611
|
}
|
|
2253
2612
|
var mounted = /* @__PURE__ */ new Map();
|
|
2254
2613
|
function findTemplateSection(id) {
|
|
@@ -2419,7 +2778,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
2419
2778
|
if (typeof document === "undefined") return;
|
|
2420
2779
|
const brandOverride = deriveBrandOverride();
|
|
2421
2780
|
const templateBrand = deriveTemplateBrand();
|
|
2422
|
-
const
|
|
2781
|
+
const templateButtonStyle = deriveTemplateButtonStyle();
|
|
2423
2782
|
const brandKey = brandOverride ? JSON.stringify(brandOverride) : "";
|
|
2424
2783
|
const pagePath = window.location.pathname;
|
|
2425
2784
|
const pageSections = state.sections.filter((entry) => (entry.path ?? "/") === pagePath);
|
|
@@ -2459,7 +2818,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
2459
2818
|
{
|
|
2460
2819
|
tree: entry.tree,
|
|
2461
2820
|
brand: brandOverride ?? entry.brand ?? options?.brand ?? templateBrand ?? void 0,
|
|
2462
|
-
|
|
2821
|
+
buttonStyle: templateButtonStyle,
|
|
2463
2822
|
resolveMedia,
|
|
2464
2823
|
editKeyPrefix: `ai.${entry.id}`
|
|
2465
2824
|
}
|
|
@@ -14558,6 +14917,9 @@ function collectEditableNodes(extraContent, root = document) {
|
|
|
14558
14917
|
if (el.dataset.ohwEditable === "link") {
|
|
14559
14918
|
return { key: el.dataset.ohwKey ?? "", type: "link", text: getLinkHref3(el) };
|
|
14560
14919
|
}
|
|
14920
|
+
if (el.dataset.ohwEditable === "map") {
|
|
14921
|
+
return { key: el.dataset.ohwKey ?? "", type: "map", text: el.dataset.ohwMapQuery ?? "" };
|
|
14922
|
+
}
|
|
14561
14923
|
return {
|
|
14562
14924
|
key: el.dataset.ohwKey ?? "",
|
|
14563
14925
|
type: el.dataset.ohwEditable ?? "text",
|
|
@@ -15341,7 +15703,7 @@ var EDITOR_CHROME_SELECTOR = '[data-ohw-toolbar], [data-ohw-form-toolbar], [data
|
|
|
15341
15703
|
function isOverEditorChrome(x, y) {
|
|
15342
15704
|
return document.elementsFromPoint(x, y).some((el) => el instanceof HTMLElement && el.matches(EDITOR_CHROME_SELECTOR));
|
|
15343
15705
|
}
|
|
15344
|
-
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"])';
|
|
15706
|
+
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"])';
|
|
15345
15707
|
function getVideoEl2(el) {
|
|
15346
15708
|
return el instanceof HTMLVideoElement ? el : el.querySelector("video");
|
|
15347
15709
|
}
|
|
@@ -15397,6 +15759,12 @@ function applyVideoSettingNode(key, val) {
|
|
|
15397
15759
|
});
|
|
15398
15760
|
return true;
|
|
15399
15761
|
}
|
|
15762
|
+
function applyMapQuery(el, val) {
|
|
15763
|
+
if (!(el instanceof HTMLIFrameElement)) return;
|
|
15764
|
+
const nextSrc = `https://www.google.com/maps?q=${encodeURIComponent(val)}&output=embed`;
|
|
15765
|
+
if (el.src !== nextSrc) el.src = nextSrc;
|
|
15766
|
+
el.setAttribute("data-ohw-map-query", val);
|
|
15767
|
+
}
|
|
15400
15768
|
function applyLinkByKey(key, val) {
|
|
15401
15769
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
15402
15770
|
if (el.dataset.ohwEditable === "link") applyLinkHref(el, val);
|
|
@@ -18197,6 +18565,8 @@ function OhhwellsBridge() {
|
|
|
18197
18565
|
}
|
|
18198
18566
|
} else if (el.dataset.ohwEditable === "link") {
|
|
18199
18567
|
applyLinkHref(el, val);
|
|
18568
|
+
} else if (el.dataset.ohwEditable === "map") {
|
|
18569
|
+
applyMapQuery(el, val);
|
|
18200
18570
|
} else if (el.dataset.ohwEditable === "icon") {
|
|
18201
18571
|
applyIconMarkup(el, val);
|
|
18202
18572
|
} else if (el.dataset.ohwEditable === "form") {
|
|
@@ -18393,6 +18763,8 @@ function OhhwellsBridge() {
|
|
|
18393
18763
|
if (video && video.src !== val) applyVideoSrc(video, val);
|
|
18394
18764
|
} else if (el.dataset.ohwEditable === "link") {
|
|
18395
18765
|
applyLinkHref(el, val);
|
|
18766
|
+
} else if (el.dataset.ohwEditable === "map") {
|
|
18767
|
+
applyMapQuery(el, val);
|
|
18396
18768
|
} else if (el.dataset.ohwEditable === "form") {
|
|
18397
18769
|
} else if (isIconMarkupValue(val)) {
|
|
18398
18770
|
} else if (el.innerHTML !== val) {
|
|
@@ -20366,6 +20738,8 @@ function OhhwellsBridge() {
|
|
|
20366
20738
|
if (video && video.src !== val) applyVideoSrc(video, val);
|
|
20367
20739
|
} else if (el.dataset.ohwEditable === "link") {
|
|
20368
20740
|
applyLinkHref(el, val);
|
|
20741
|
+
} else if (el.dataset.ohwEditable === "map") {
|
|
20742
|
+
applyMapQuery(el, val);
|
|
20369
20743
|
} else if (el.dataset.ohwEditable === "icon") {
|
|
20370
20744
|
applyIconMarkup(el, val);
|
|
20371
20745
|
} else if (isIconMarkupValue(val)) {
|
|
@@ -21602,7 +21976,7 @@ function OhhwellsBridge() {
|
|
|
21602
21976
|
postToParent2({
|
|
21603
21977
|
type: "ow:ready",
|
|
21604
21978
|
version: "1",
|
|
21605
|
-
bridgeVersion: "0.1.
|
|
21979
|
+
bridgeVersion: "0.1.96",
|
|
21606
21980
|
path: pathname,
|
|
21607
21981
|
nodes: collectEditableNodes(editContentRef.current),
|
|
21608
21982
|
sections
|