@ohhwells/bridge 0.1.141 → 0.1.143
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 +392 -257
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +392 -257
- package/dist/index.js.map +1 -1
- package/dist/styles.css +4 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1256,15 +1256,25 @@ function readAssignments(content) {
|
|
|
1256
1256
|
function cssLength(style, prop) {
|
|
1257
1257
|
return style.getPropertyValue(prop) || "0px";
|
|
1258
1258
|
}
|
|
1259
|
+
function withTransitionsSettled(el, read) {
|
|
1260
|
+
const prior = el.style.getPropertyValue("transition");
|
|
1261
|
+
const priority = el.style.getPropertyPriority("transition");
|
|
1262
|
+
el.style.setProperty("transition", "none", "important");
|
|
1263
|
+
try {
|
|
1264
|
+
return read(getComputedStyle(el));
|
|
1265
|
+
} finally {
|
|
1266
|
+
if (prior) el.style.setProperty("transition", prior, priority);
|
|
1267
|
+
else el.style.removeProperty("transition");
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1259
1270
|
function readVariantSample(el) {
|
|
1260
|
-
|
|
1261
|
-
return {
|
|
1271
|
+
return withTransitionsSettled(el, (style) => ({
|
|
1262
1272
|
background: style.backgroundColor,
|
|
1263
1273
|
color: style.color,
|
|
1264
1274
|
borderColor: style.borderTopColor,
|
|
1265
1275
|
borderWidth: style.borderTopWidth,
|
|
1266
1276
|
className: el.className || ""
|
|
1267
|
-
};
|
|
1277
|
+
}));
|
|
1268
1278
|
}
|
|
1269
1279
|
function readSizeSample(el) {
|
|
1270
1280
|
const style = getComputedStyle(el);
|
|
@@ -4929,10 +4939,9 @@ function getLinkHref3(el) {
|
|
|
4929
4939
|
}
|
|
4930
4940
|
function collectEditableNodes(extraContent, root = document) {
|
|
4931
4941
|
const isScoped = root !== document;
|
|
4932
|
-
const
|
|
4933
|
-
|
|
4934
|
-
)
|
|
4935
|
-
if (isScoped && root instanceof HTMLElement && root.matches('[data-ohw-editable]:not([data-ohw-editable="form"])')) {
|
|
4942
|
+
const EDITABLE_SELECTOR = '[data-ohw-editable]:not([data-ohw-editable="form"]):not([data-ai-icon])';
|
|
4943
|
+
const editableEls = Array.from(root.querySelectorAll(EDITABLE_SELECTOR));
|
|
4944
|
+
if (isScoped && root instanceof HTMLElement && root.matches(EDITABLE_SELECTOR)) {
|
|
4936
4945
|
editableEls.unshift(root);
|
|
4937
4946
|
}
|
|
4938
4947
|
const nodes = editableEls.map((el) => {
|
|
@@ -6199,6 +6208,281 @@ function reapRemovedAiSections(state, store, removedIds, excludeIds = /* @__PURE
|
|
|
6199
6208
|
return { state: nextState, store: nextStore, reapedIds, slotPrefixes, changed: true };
|
|
6200
6209
|
}
|
|
6201
6210
|
|
|
6211
|
+
// src/lib/ai-pricing-tree.ts
|
|
6212
|
+
var PRICING_MIN_CARDS = 1;
|
|
6213
|
+
var PRICING_MAX_CARDS = 4;
|
|
6214
|
+
function isPricingCard(node) {
|
|
6215
|
+
return typeof node === "object" && node !== null && node.type === "card" && node.slots?.preset === "pricing";
|
|
6216
|
+
}
|
|
6217
|
+
function isPricingCollection(node) {
|
|
6218
|
+
return node.type === "collection" && Array.isArray(node.children) && node.children.length > 0 && isPricingCard(node.children[0]);
|
|
6219
|
+
}
|
|
6220
|
+
function findCollection(node) {
|
|
6221
|
+
if (isPricingCollection(node)) return node;
|
|
6222
|
+
for (const child of node.children ?? []) {
|
|
6223
|
+
const found = findCollection(child);
|
|
6224
|
+
if (found) return found;
|
|
6225
|
+
}
|
|
6226
|
+
return null;
|
|
6227
|
+
}
|
|
6228
|
+
function findPricingCollection(tree) {
|
|
6229
|
+
for (const row of tree.rows ?? []) {
|
|
6230
|
+
for (const block of row.blocks ?? []) {
|
|
6231
|
+
const found = findCollection(block);
|
|
6232
|
+
if (found) return found;
|
|
6233
|
+
}
|
|
6234
|
+
}
|
|
6235
|
+
return null;
|
|
6236
|
+
}
|
|
6237
|
+
function pricingCardCount(tree) {
|
|
6238
|
+
return findPricingCollection(tree)?.children?.length ?? 0;
|
|
6239
|
+
}
|
|
6240
|
+
function withPricingCollection(tree, mutate) {
|
|
6241
|
+
const next = JSON.parse(JSON.stringify(tree));
|
|
6242
|
+
const collection = findPricingCollection(next);
|
|
6243
|
+
if (!collection || !collection.children) return null;
|
|
6244
|
+
for (const card of collection.children) {
|
|
6245
|
+
if (isPricingCard(card)) upgradeLegacyPricingSlots(card);
|
|
6246
|
+
}
|
|
6247
|
+
return mutate(collection) ? next : null;
|
|
6248
|
+
}
|
|
6249
|
+
function upgradeLegacyPricingSlots(card) {
|
|
6250
|
+
const slots = card.slots = card.slots ?? {};
|
|
6251
|
+
if (typeof slots.features === "string") {
|
|
6252
|
+
const rows = pricingFeatureList(card);
|
|
6253
|
+
if (rows.length > 0) slots.features = rows.slice(0, PRICING_FEATURES_MAX);
|
|
6254
|
+
}
|
|
6255
|
+
if (slots.featured === true) slots.featured = { enabled: true };
|
|
6256
|
+
else if (slots.featured === false) delete slots.featured;
|
|
6257
|
+
}
|
|
6258
|
+
function addPricingTier(tree) {
|
|
6259
|
+
return withPricingCollection(tree, (collection) => {
|
|
6260
|
+
const children = collection.children;
|
|
6261
|
+
if (children.length >= PRICING_MAX_CARDS) return false;
|
|
6262
|
+
const clone = JSON.parse(JSON.stringify(children[children.length - 1]));
|
|
6263
|
+
clone.slots = clone.slots ?? {};
|
|
6264
|
+
delete clone.slots.featured;
|
|
6265
|
+
clone.slots.heading = "New tier";
|
|
6266
|
+
children.push(clone);
|
|
6267
|
+
collection.slots = { ...collection.slots, itemsPerRow: children.length };
|
|
6268
|
+
return true;
|
|
6269
|
+
});
|
|
6270
|
+
}
|
|
6271
|
+
function removePricingTier(tree, index) {
|
|
6272
|
+
return withPricingCollection(tree, (collection) => {
|
|
6273
|
+
const children = collection.children;
|
|
6274
|
+
if (children.length <= PRICING_MIN_CARDS) return false;
|
|
6275
|
+
if (index < 0 || index >= children.length) return false;
|
|
6276
|
+
children.splice(index, 1);
|
|
6277
|
+
collection.slots = { ...collection.slots, itemsPerRow: children.length };
|
|
6278
|
+
return true;
|
|
6279
|
+
});
|
|
6280
|
+
}
|
|
6281
|
+
var PRICING_CARD_STYLES = [
|
|
6282
|
+
{ value: "outline", label: "Outline", treatment: null },
|
|
6283
|
+
{ value: "lift", label: "Lift", treatment: "lifted" },
|
|
6284
|
+
{ value: "invert", label: "Invert", treatment: "inverted" },
|
|
6285
|
+
{ value: "header", label: "Header", treatment: "accent-header" }
|
|
6286
|
+
];
|
|
6287
|
+
var DEFAULT_FEATURED_BADGE = "Most popular";
|
|
6288
|
+
function featuredOf(target) {
|
|
6289
|
+
const raw = target?.slots?.featured;
|
|
6290
|
+
if (raw === true) return { enabled: true, treatment: "outlined" };
|
|
6291
|
+
return typeof raw === "object" && raw !== null ? raw : {};
|
|
6292
|
+
}
|
|
6293
|
+
function badgeOf(featured) {
|
|
6294
|
+
return typeof featured.badge === "string" ? featured.badge.trim() : "";
|
|
6295
|
+
}
|
|
6296
|
+
function pricingCardStyle(tree, index) {
|
|
6297
|
+
const featured = featuredOf(findPricingCollection(tree)?.children?.[index]);
|
|
6298
|
+
if (featured.enabled !== true) return "outline";
|
|
6299
|
+
return PRICING_CARD_STYLES.find((s) => s.treatment === featured.treatment)?.value ?? "outline";
|
|
6300
|
+
}
|
|
6301
|
+
function pricingCardFeaturedTag(tree, index) {
|
|
6302
|
+
const featured = featuredOf(findPricingCollection(tree)?.children?.[index]);
|
|
6303
|
+
return featured.enabled === true && badgeOf(featured).length > 0;
|
|
6304
|
+
}
|
|
6305
|
+
function composeFeatured(style, tagOn, badgeText) {
|
|
6306
|
+
const treatment = PRICING_CARD_STYLES.find((s) => s.value === style)?.treatment ?? null;
|
|
6307
|
+
if (tagOn) return { enabled: true, badge: badgeText || DEFAULT_FEATURED_BADGE, treatment: treatment ?? "outlined" };
|
|
6308
|
+
if (treatment) return { enabled: true, treatment };
|
|
6309
|
+
return badgeText.length > 0 ? { enabled: false, badge: badgeText } : { enabled: false };
|
|
6310
|
+
}
|
|
6311
|
+
function withPricingCard(tree, index, mutate) {
|
|
6312
|
+
return withPricingCollection(tree, (collection) => {
|
|
6313
|
+
const children = collection.children;
|
|
6314
|
+
if (index < 0 || index >= children.length) return false;
|
|
6315
|
+
const target = children[index];
|
|
6316
|
+
target.slots = target.slots ?? {};
|
|
6317
|
+
mutate(target);
|
|
6318
|
+
return true;
|
|
6319
|
+
});
|
|
6320
|
+
}
|
|
6321
|
+
function setPricingCardStyle(tree, index, style) {
|
|
6322
|
+
if (!PRICING_CARD_STYLES.some((s) => s.value === style)) return null;
|
|
6323
|
+
return withPricingCard(tree, index, (target) => {
|
|
6324
|
+
const prev = featuredOf(target);
|
|
6325
|
+
const tagOn = prev.enabled === true && badgeOf(prev).length > 0;
|
|
6326
|
+
target.slots.featured = composeFeatured(style, tagOn, badgeOf(prev));
|
|
6327
|
+
});
|
|
6328
|
+
}
|
|
6329
|
+
function setPricingCardFeaturedTag(tree, index, on) {
|
|
6330
|
+
return withPricingCollection(tree, (collection) => {
|
|
6331
|
+
const children = collection.children;
|
|
6332
|
+
if (index < 0 || index >= children.length) return false;
|
|
6333
|
+
if (on) {
|
|
6334
|
+
children.forEach((card, i) => {
|
|
6335
|
+
if (i === index) return;
|
|
6336
|
+
const prev2 = featuredOf(card);
|
|
6337
|
+
if (prev2.enabled !== true || badgeOf(prev2).length === 0) return;
|
|
6338
|
+
card.slots = card.slots ?? {};
|
|
6339
|
+
card.slots.featured = composeFeatured(pricingCardStyleOf(prev2), false, badgeOf(prev2));
|
|
6340
|
+
});
|
|
6341
|
+
}
|
|
6342
|
+
const target = children[index];
|
|
6343
|
+
target.slots = target.slots ?? {};
|
|
6344
|
+
const prev = featuredOf(target);
|
|
6345
|
+
target.slots.featured = composeFeatured(pricingCardStyleOf(prev), on, badgeOf(prev));
|
|
6346
|
+
return true;
|
|
6347
|
+
});
|
|
6348
|
+
}
|
|
6349
|
+
function pricingCardStyleOf(featured) {
|
|
6350
|
+
if (featured.enabled !== true) return "outline";
|
|
6351
|
+
return PRICING_CARD_STYLES.find((s) => s.treatment === featured.treatment)?.value ?? "outline";
|
|
6352
|
+
}
|
|
6353
|
+
function addPricingCardButton(tree, index, label) {
|
|
6354
|
+
return withPricingCollection(tree, (collection) => {
|
|
6355
|
+
const children = collection.children;
|
|
6356
|
+
if (index < 0 || index >= children.length) return false;
|
|
6357
|
+
const target = children[index];
|
|
6358
|
+
const buttons = (target.children ?? []).filter((c) => c.type === "button");
|
|
6359
|
+
if (buttons.length >= 2) return false;
|
|
6360
|
+
const hasPrimary = buttons.some((b) => b.slots?.variant === "primary");
|
|
6361
|
+
target.children = [
|
|
6362
|
+
...target.children ?? [],
|
|
6363
|
+
{ type: "button", span: 12, slots: { label, href: "#", variant: hasPrimary ? "secondary" : "primary" } }
|
|
6364
|
+
];
|
|
6365
|
+
return true;
|
|
6366
|
+
});
|
|
6367
|
+
}
|
|
6368
|
+
function removePricingCardButton(tree, index) {
|
|
6369
|
+
return withPricingCollection(tree, (collection) => {
|
|
6370
|
+
const children = collection.children;
|
|
6371
|
+
if (index < 0 || index >= children.length) return false;
|
|
6372
|
+
const target = children[index];
|
|
6373
|
+
const buttons = (target.children ?? []).filter((c) => c.type === "button");
|
|
6374
|
+
if (buttons.length === 0) return false;
|
|
6375
|
+
const lastButton = buttons[buttons.length - 1];
|
|
6376
|
+
target.children = (target.children ?? []).filter((c) => c !== lastButton);
|
|
6377
|
+
return true;
|
|
6378
|
+
});
|
|
6379
|
+
}
|
|
6380
|
+
var PRICING_FEATURES_MIN = 1;
|
|
6381
|
+
var PRICING_FEATURES_MAX = 10;
|
|
6382
|
+
var PRICING_FEATURE_ICONS = [
|
|
6383
|
+
"check",
|
|
6384
|
+
"check-circle",
|
|
6385
|
+
"x",
|
|
6386
|
+
"star",
|
|
6387
|
+
"zap",
|
|
6388
|
+
"shield",
|
|
6389
|
+
"clock",
|
|
6390
|
+
"users",
|
|
6391
|
+
"infinity"
|
|
6392
|
+
];
|
|
6393
|
+
function pricingFeatureList(target) {
|
|
6394
|
+
const raw = target.slots?.features;
|
|
6395
|
+
if (Array.isArray(raw)) {
|
|
6396
|
+
return raw.filter((item) => !!item && typeof item === "object" && typeof item.text === "string").map((item) => ({
|
|
6397
|
+
text: item.text,
|
|
6398
|
+
...typeof item.icon === "string" ? { icon: item.icon } : {},
|
|
6399
|
+
...typeof item.iconColor === "string" ? { iconColor: item.iconColor } : {}
|
|
6400
|
+
}));
|
|
6401
|
+
}
|
|
6402
|
+
if (typeof raw === "string") {
|
|
6403
|
+
return raw.split(/\n|<br\s*\/?>/i).map((line) => line.replace(/<[^>]+>/g, "").replace(/^[-*•]\s*/, "").trim().slice(0, 120)).filter(Boolean).map((text) => ({ text }));
|
|
6404
|
+
}
|
|
6405
|
+
return [];
|
|
6406
|
+
}
|
|
6407
|
+
function pricingCardFeatureCount(tree, index) {
|
|
6408
|
+
const target = findPricingCollection(tree)?.children?.[index];
|
|
6409
|
+
return target ? pricingFeatureList(target).length : 0;
|
|
6410
|
+
}
|
|
6411
|
+
function addPricingCardFeature(tree, index, text) {
|
|
6412
|
+
return withPricingCollection(tree, (collection) => {
|
|
6413
|
+
const children = collection.children;
|
|
6414
|
+
if (index < 0 || index >= children.length) return false;
|
|
6415
|
+
const target = children[index];
|
|
6416
|
+
const features = pricingFeatureList(target);
|
|
6417
|
+
if (features.length >= PRICING_FEATURES_MAX) return false;
|
|
6418
|
+
target.slots = target.slots ?? {};
|
|
6419
|
+
target.slots.features = [...features, { text }];
|
|
6420
|
+
return true;
|
|
6421
|
+
});
|
|
6422
|
+
}
|
|
6423
|
+
function setPricingCardFeatureIcon(tree, index, featureIndex, icon) {
|
|
6424
|
+
if (!PRICING_FEATURE_ICONS.includes(icon)) return null;
|
|
6425
|
+
return withPricingCollection(tree, (collection) => {
|
|
6426
|
+
const children = collection.children;
|
|
6427
|
+
if (index < 0 || index >= children.length) return false;
|
|
6428
|
+
const target = children[index];
|
|
6429
|
+
const features = pricingFeatureList(target);
|
|
6430
|
+
if (featureIndex < 0 || featureIndex >= features.length) return false;
|
|
6431
|
+
target.slots = target.slots ?? {};
|
|
6432
|
+
target.slots.features = features.map((row, i) => i === featureIndex ? { ...row, icon } : row);
|
|
6433
|
+
return true;
|
|
6434
|
+
});
|
|
6435
|
+
}
|
|
6436
|
+
function removePricingCardFeature(tree, index) {
|
|
6437
|
+
return withPricingCollection(tree, (collection) => {
|
|
6438
|
+
const children = collection.children;
|
|
6439
|
+
if (index < 0 || index >= children.length) return false;
|
|
6440
|
+
const target = children[index];
|
|
6441
|
+
const features = pricingFeatureList(target);
|
|
6442
|
+
if (features.length <= PRICING_FEATURES_MIN) return false;
|
|
6443
|
+
target.slots = target.slots ?? {};
|
|
6444
|
+
target.slots.features = features.slice(0, -1);
|
|
6445
|
+
return true;
|
|
6446
|
+
});
|
|
6447
|
+
}
|
|
6448
|
+
|
|
6449
|
+
// src/lib/ai-icon-edit.ts
|
|
6450
|
+
var FEATURE_ICON_PATH = /\.c(\d+)\.features\.(\d+)\.icon$/;
|
|
6451
|
+
var NODE_SEGMENT = /^[rbc]\d+$/;
|
|
6452
|
+
function nodeAtPath(tree, segments) {
|
|
6453
|
+
if (segments.length < 2 || segments.some((s) => !NODE_SEGMENT.test(s))) return null;
|
|
6454
|
+
if (!segments[0].startsWith("r") || !segments[1].startsWith("b")) return null;
|
|
6455
|
+
let node = tree.rows?.[Number(segments[0].slice(1))]?.blocks?.[Number(segments[1].slice(1))];
|
|
6456
|
+
for (const segment of segments.slice(2)) {
|
|
6457
|
+
if (!segment.startsWith("c")) return null;
|
|
6458
|
+
node = node?.children?.[Number(segment.slice(1))];
|
|
6459
|
+
}
|
|
6460
|
+
return node ?? null;
|
|
6461
|
+
}
|
|
6462
|
+
function applyIconNameToTree(tree, path, icon) {
|
|
6463
|
+
const feature = path.match(FEATURE_ICON_PATH);
|
|
6464
|
+
if (feature) {
|
|
6465
|
+
return setPricingCardFeatureIcon(tree, Number(feature[1]), Number(feature[2]), icon);
|
|
6466
|
+
}
|
|
6467
|
+
return rewriteIconSlot(tree, path, `lucide:${icon}`);
|
|
6468
|
+
}
|
|
6469
|
+
function applyIconUploadToTree(tree, path, mediaRef) {
|
|
6470
|
+
if (FEATURE_ICON_PATH.test(path)) return null;
|
|
6471
|
+
return rewriteIconSlot(tree, path, `icon:${mediaRef}`);
|
|
6472
|
+
}
|
|
6473
|
+
function rewriteIconSlot(tree, path, ref) {
|
|
6474
|
+
const segments = path.split(".");
|
|
6475
|
+
const slot = segments.pop();
|
|
6476
|
+
if (!slot || NODE_SEGMENT.test(slot)) return null;
|
|
6477
|
+
const next = JSON.parse(JSON.stringify(tree));
|
|
6478
|
+
const node = nodeAtPath(next, segments);
|
|
6479
|
+
if (!node) return null;
|
|
6480
|
+
const current = node.slots?.[slot];
|
|
6481
|
+
if (typeof current !== "string" || !/^(lucide|simple|icon):/.test(current)) return null;
|
|
6482
|
+
node.slots = { ...node.slots, [slot]: ref };
|
|
6483
|
+
return next;
|
|
6484
|
+
}
|
|
6485
|
+
|
|
6202
6486
|
// src/lib/ai-footer-tree.ts
|
|
6203
6487
|
var FOOTER_COLUMN_SPANS = [12, 6, 4, 3];
|
|
6204
6488
|
var FOOTER_COLUMN_BLOCKS = [
|
|
@@ -7555,7 +7839,7 @@ function MediaBox({
|
|
|
7555
7839
|
onError
|
|
7556
7840
|
}) {
|
|
7557
7841
|
const url = refValue ? ctx.resolveMedia(refValue) : null;
|
|
7558
|
-
const isIcon = /^(lucide|simple):/.test(refValue);
|
|
7842
|
+
const isIcon = /^(lucide|simple|icon):/.test(refValue);
|
|
7559
7843
|
const aspectRatio = aspect && /^\d+:\d+$/.test(aspect) ? aspect.replace(":", " / ") : void 0;
|
|
7560
7844
|
const editAttrs = ctx.keyFor && editPath && !isIcon ? {
|
|
7561
7845
|
"data-ohw-key": ctx.keyFor(editPath),
|
|
@@ -7563,10 +7847,13 @@ function MediaBox({
|
|
|
7563
7847
|
} : {};
|
|
7564
7848
|
if (isIcon) {
|
|
7565
7849
|
const Icon = refValue.startsWith("lucide:") ? lucideByName(refValue.slice(7)) : null;
|
|
7850
|
+
const uploadedIconUrl = refValue.startsWith("icon:") ? ctx.resolveMedia(refValue.slice(5)) : null;
|
|
7851
|
+
const iconEditAttrs = ctx.keyFor && editPath && genericImageEdit ? { "data-ohw-key": ctx.keyFor(editPath), "data-ohw-editable": "icon" } : {};
|
|
7566
7852
|
return /* @__PURE__ */ jsx(
|
|
7567
7853
|
"span",
|
|
7568
7854
|
{
|
|
7569
7855
|
"data-ai-icon": refValue,
|
|
7856
|
+
...iconEditAttrs,
|
|
7570
7857
|
style: {
|
|
7571
7858
|
display: "inline-flex",
|
|
7572
7859
|
width: 48,
|
|
@@ -7575,7 +7862,7 @@ function MediaBox({
|
|
|
7575
7862
|
justifyContent: "center",
|
|
7576
7863
|
color: ctx.brand.palette.dark
|
|
7577
7864
|
},
|
|
7578
|
-
children: Icon ? /* @__PURE__ */ jsx(Icon, { size: 48, color: ctx.brand.palette.dark, strokeWidth: 1.5 }) : /* @__PURE__ */ jsx("span", { style: { fontSize: 24 }, children: "\u25C6" })
|
|
7865
|
+
children: uploadedIconUrl ? /* @__PURE__ */ jsx("img", { src: uploadedIconUrl, alt: "", style: { width: 48, height: 48, objectFit: "contain" } }) : Icon ? /* @__PURE__ */ jsx(Icon, { size: 48, color: ctx.brand.palette.dark, strokeWidth: 1.5 }) : /* @__PURE__ */ jsx("span", { style: { fontSize: 24 }, children: "\u25C6" })
|
|
7579
7866
|
}
|
|
7580
7867
|
);
|
|
7581
7868
|
}
|
|
@@ -8063,8 +8350,20 @@ function PricingCard({ node, ctx, path }) {
|
|
|
8063
8350
|
/* @__PURE__ */ jsx("div", { "data-ai-features": "", style: { display: "flex", flexDirection: "column", gap: AI_TREE_TOKENS.spacing4, padding: `${AI_TREE_TOKENS.spacing2}px 0` }, children: features.map((item, i) => {
|
|
8064
8351
|
const Icon = lucideByName(item.icon || "check");
|
|
8065
8352
|
const iconColor = pricingIconColor(item.iconColor, ctx.brand, fg);
|
|
8353
|
+
const iconAttrs = ctx.keyFor && !item.html ? {
|
|
8354
|
+
"data-ohw-key": ctx.keyFor(`${path}.features.${i}.icon`),
|
|
8355
|
+
"data-ohw-editable": "icon"
|
|
8356
|
+
} : {};
|
|
8066
8357
|
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "flex-start", gap: AI_TREE_TOKENS.spacing3 }, children: [
|
|
8067
|
-
Icon && /* @__PURE__ */ jsx(
|
|
8358
|
+
Icon && /* @__PURE__ */ jsx(
|
|
8359
|
+
"span",
|
|
8360
|
+
{
|
|
8361
|
+
"data-ai-icon": `lucide:${item.icon || "check"}`,
|
|
8362
|
+
...iconAttrs,
|
|
8363
|
+
style: { display: "inline-flex", flexShrink: 0 },
|
|
8364
|
+
children: /* @__PURE__ */ jsx(Icon, { size: 20, color: iconColor })
|
|
8365
|
+
}
|
|
8366
|
+
),
|
|
8068
8367
|
item.html ? /* @__PURE__ */ jsx(
|
|
8069
8368
|
"span",
|
|
8070
8369
|
{
|
|
@@ -10187,38 +10486,39 @@ function deriveTemplateButtonStyle() {
|
|
|
10187
10486
|
el.querySelectorAll("[data-ohw-editable]").length <= 1
|
|
10188
10487
|
);
|
|
10189
10488
|
const isFilled = (el) => {
|
|
10190
|
-
const bg =
|
|
10489
|
+
const bg = withTransitionsSettled(el, (s) => s.backgroundColor);
|
|
10191
10490
|
if (!bg || bg === "transparent") return false;
|
|
10192
10491
|
const alpha = bg.match(/rgba?\([^)]*,\s*([\d.]+)\)$/);
|
|
10193
10492
|
return !alpha || parseFloat(alpha[1]) > 0;
|
|
10194
10493
|
};
|
|
10195
10494
|
const btn = candidates.find(isFilled) ?? candidates[0];
|
|
10196
10495
|
if (!btn) return null;
|
|
10197
|
-
|
|
10198
|
-
|
|
10199
|
-
|
|
10200
|
-
|
|
10201
|
-
|
|
10202
|
-
|
|
10203
|
-
|
|
10204
|
-
|
|
10205
|
-
|
|
10206
|
-
|
|
10207
|
-
|
|
10208
|
-
|
|
10209
|
-
|
|
10210
|
-
|
|
10211
|
-
|
|
10212
|
-
|
|
10213
|
-
|
|
10214
|
-
|
|
10215
|
-
|
|
10216
|
-
|
|
10217
|
-
|
|
10218
|
-
|
|
10219
|
-
|
|
10220
|
-
|
|
10221
|
-
|
|
10496
|
+
return withTransitionsSettled(btn, (cs) => {
|
|
10497
|
+
const filled = isFilled(btn);
|
|
10498
|
+
const corners = [
|
|
10499
|
+
cs.borderTopLeftRadius,
|
|
10500
|
+
cs.borderTopRightRadius,
|
|
10501
|
+
cs.borderBottomRightRadius,
|
|
10502
|
+
cs.borderBottomLeftRadius
|
|
10503
|
+
].map((v) => v || "0px");
|
|
10504
|
+
const radius = corners.every((v) => v === corners[0]) ? corners[0] : corners.join(" ");
|
|
10505
|
+
const px2 = (v) => parseFloat(v) || 0;
|
|
10506
|
+
const lineHeight = px2(cs.lineHeight) || px2(cs.fontSize) * 1.2;
|
|
10507
|
+
const contentH = btn.getBoundingClientRect().height - px2(cs.borderTopWidth) - px2(cs.borderBottomWidth);
|
|
10508
|
+
const impliedY = Math.round(Math.max(0, (contentH - lineHeight) / 2));
|
|
10509
|
+
const padY = Math.max(px2(cs.paddingTop), px2(cs.paddingBottom), impliedY);
|
|
10510
|
+
const padX = Math.max(px2(cs.paddingLeft), px2(cs.paddingRight));
|
|
10511
|
+
return {
|
|
10512
|
+
radius: radius || "10px",
|
|
10513
|
+
padding: `${padY}px ${padX}px`,
|
|
10514
|
+
...filled ? { background: cs.backgroundColor, color: cs.color } : {},
|
|
10515
|
+
fontFamily: cs.fontFamily || "",
|
|
10516
|
+
fontSize: cs.fontSize || "",
|
|
10517
|
+
fontWeight: cs.fontWeight || "",
|
|
10518
|
+
letterSpacing: cs.letterSpacing || "",
|
|
10519
|
+
textTransform: cs.textTransform || ""
|
|
10520
|
+
};
|
|
10521
|
+
});
|
|
10222
10522
|
}
|
|
10223
10523
|
var mounted = /* @__PURE__ */ new Map();
|
|
10224
10524
|
function findTemplateSection(id) {
|
|
@@ -18306,222 +18606,6 @@ function AiMediaStripOverlay({
|
|
|
18306
18606
|
// src/ui/ai-section/AiPricingCardOverlay.tsx
|
|
18307
18607
|
import { useCallback as useCallback4, useEffect as useEffect7, useLayoutEffect as useLayoutEffect4, useRef as useRef6, useState as useState9 } from "react";
|
|
18308
18608
|
import { Check as Check2, ChevronDown as ChevronDown3, Minus, Plus as Plus2, Star as Star2 } from "lucide-react";
|
|
18309
|
-
|
|
18310
|
-
// src/lib/ai-pricing-tree.ts
|
|
18311
|
-
var PRICING_MIN_CARDS = 1;
|
|
18312
|
-
var PRICING_MAX_CARDS = 4;
|
|
18313
|
-
function isPricingCard(node) {
|
|
18314
|
-
return typeof node === "object" && node !== null && node.type === "card" && node.slots?.preset === "pricing";
|
|
18315
|
-
}
|
|
18316
|
-
function isPricingCollection(node) {
|
|
18317
|
-
return node.type === "collection" && Array.isArray(node.children) && node.children.length > 0 && isPricingCard(node.children[0]);
|
|
18318
|
-
}
|
|
18319
|
-
function findCollection(node) {
|
|
18320
|
-
if (isPricingCollection(node)) return node;
|
|
18321
|
-
for (const child of node.children ?? []) {
|
|
18322
|
-
const found = findCollection(child);
|
|
18323
|
-
if (found) return found;
|
|
18324
|
-
}
|
|
18325
|
-
return null;
|
|
18326
|
-
}
|
|
18327
|
-
function findPricingCollection(tree) {
|
|
18328
|
-
for (const row of tree.rows ?? []) {
|
|
18329
|
-
for (const block of row.blocks ?? []) {
|
|
18330
|
-
const found = findCollection(block);
|
|
18331
|
-
if (found) return found;
|
|
18332
|
-
}
|
|
18333
|
-
}
|
|
18334
|
-
return null;
|
|
18335
|
-
}
|
|
18336
|
-
function pricingCardCount(tree) {
|
|
18337
|
-
return findPricingCollection(tree)?.children?.length ?? 0;
|
|
18338
|
-
}
|
|
18339
|
-
function withPricingCollection(tree, mutate) {
|
|
18340
|
-
const next = JSON.parse(JSON.stringify(tree));
|
|
18341
|
-
const collection = findPricingCollection(next);
|
|
18342
|
-
if (!collection || !collection.children) return null;
|
|
18343
|
-
for (const card of collection.children) {
|
|
18344
|
-
if (isPricingCard(card)) upgradeLegacyPricingSlots(card);
|
|
18345
|
-
}
|
|
18346
|
-
return mutate(collection) ? next : null;
|
|
18347
|
-
}
|
|
18348
|
-
function upgradeLegacyPricingSlots(card) {
|
|
18349
|
-
const slots = card.slots = card.slots ?? {};
|
|
18350
|
-
if (typeof slots.features === "string") {
|
|
18351
|
-
const rows = pricingFeatureList(card);
|
|
18352
|
-
if (rows.length > 0) slots.features = rows.slice(0, PRICING_FEATURES_MAX);
|
|
18353
|
-
}
|
|
18354
|
-
if (slots.featured === true) slots.featured = { enabled: true };
|
|
18355
|
-
else if (slots.featured === false) delete slots.featured;
|
|
18356
|
-
}
|
|
18357
|
-
function addPricingTier(tree) {
|
|
18358
|
-
return withPricingCollection(tree, (collection) => {
|
|
18359
|
-
const children = collection.children;
|
|
18360
|
-
if (children.length >= PRICING_MAX_CARDS) return false;
|
|
18361
|
-
const clone = JSON.parse(JSON.stringify(children[children.length - 1]));
|
|
18362
|
-
clone.slots = clone.slots ?? {};
|
|
18363
|
-
delete clone.slots.featured;
|
|
18364
|
-
clone.slots.heading = "New tier";
|
|
18365
|
-
children.push(clone);
|
|
18366
|
-
collection.slots = { ...collection.slots, itemsPerRow: children.length };
|
|
18367
|
-
return true;
|
|
18368
|
-
});
|
|
18369
|
-
}
|
|
18370
|
-
function removePricingTier(tree, index) {
|
|
18371
|
-
return withPricingCollection(tree, (collection) => {
|
|
18372
|
-
const children = collection.children;
|
|
18373
|
-
if (children.length <= PRICING_MIN_CARDS) return false;
|
|
18374
|
-
if (index < 0 || index >= children.length) return false;
|
|
18375
|
-
children.splice(index, 1);
|
|
18376
|
-
collection.slots = { ...collection.slots, itemsPerRow: children.length };
|
|
18377
|
-
return true;
|
|
18378
|
-
});
|
|
18379
|
-
}
|
|
18380
|
-
var PRICING_CARD_STYLES = [
|
|
18381
|
-
{ value: "outline", label: "Outline", treatment: null },
|
|
18382
|
-
{ value: "lift", label: "Lift", treatment: "lifted" },
|
|
18383
|
-
{ value: "invert", label: "Invert", treatment: "inverted" },
|
|
18384
|
-
{ value: "header", label: "Header", treatment: "accent-header" }
|
|
18385
|
-
];
|
|
18386
|
-
var DEFAULT_FEATURED_BADGE = "Most popular";
|
|
18387
|
-
function featuredOf(target) {
|
|
18388
|
-
const raw = target?.slots?.featured;
|
|
18389
|
-
if (raw === true) return { enabled: true, treatment: "outlined" };
|
|
18390
|
-
return typeof raw === "object" && raw !== null ? raw : {};
|
|
18391
|
-
}
|
|
18392
|
-
function badgeOf(featured) {
|
|
18393
|
-
return typeof featured.badge === "string" ? featured.badge.trim() : "";
|
|
18394
|
-
}
|
|
18395
|
-
function pricingCardStyle(tree, index) {
|
|
18396
|
-
const featured = featuredOf(findPricingCollection(tree)?.children?.[index]);
|
|
18397
|
-
if (featured.enabled !== true) return "outline";
|
|
18398
|
-
return PRICING_CARD_STYLES.find((s) => s.treatment === featured.treatment)?.value ?? "outline";
|
|
18399
|
-
}
|
|
18400
|
-
function pricingCardFeaturedTag(tree, index) {
|
|
18401
|
-
const featured = featuredOf(findPricingCollection(tree)?.children?.[index]);
|
|
18402
|
-
return featured.enabled === true && badgeOf(featured).length > 0;
|
|
18403
|
-
}
|
|
18404
|
-
function composeFeatured(style, tagOn, badgeText) {
|
|
18405
|
-
const treatment = PRICING_CARD_STYLES.find((s) => s.value === style)?.treatment ?? null;
|
|
18406
|
-
if (tagOn) return { enabled: true, badge: badgeText || DEFAULT_FEATURED_BADGE, treatment: treatment ?? "outlined" };
|
|
18407
|
-
if (treatment) return { enabled: true, treatment };
|
|
18408
|
-
return badgeText.length > 0 ? { enabled: false, badge: badgeText } : { enabled: false };
|
|
18409
|
-
}
|
|
18410
|
-
function withPricingCard(tree, index, mutate) {
|
|
18411
|
-
return withPricingCollection(tree, (collection) => {
|
|
18412
|
-
const children = collection.children;
|
|
18413
|
-
if (index < 0 || index >= children.length) return false;
|
|
18414
|
-
const target = children[index];
|
|
18415
|
-
target.slots = target.slots ?? {};
|
|
18416
|
-
mutate(target);
|
|
18417
|
-
return true;
|
|
18418
|
-
});
|
|
18419
|
-
}
|
|
18420
|
-
function setPricingCardStyle(tree, index, style) {
|
|
18421
|
-
if (!PRICING_CARD_STYLES.some((s) => s.value === style)) return null;
|
|
18422
|
-
return withPricingCard(tree, index, (target) => {
|
|
18423
|
-
const prev = featuredOf(target);
|
|
18424
|
-
const tagOn = prev.enabled === true && badgeOf(prev).length > 0;
|
|
18425
|
-
target.slots.featured = composeFeatured(style, tagOn, badgeOf(prev));
|
|
18426
|
-
});
|
|
18427
|
-
}
|
|
18428
|
-
function setPricingCardFeaturedTag(tree, index, on) {
|
|
18429
|
-
return withPricingCollection(tree, (collection) => {
|
|
18430
|
-
const children = collection.children;
|
|
18431
|
-
if (index < 0 || index >= children.length) return false;
|
|
18432
|
-
if (on) {
|
|
18433
|
-
children.forEach((card, i) => {
|
|
18434
|
-
if (i === index) return;
|
|
18435
|
-
const prev2 = featuredOf(card);
|
|
18436
|
-
if (prev2.enabled !== true || badgeOf(prev2).length === 0) return;
|
|
18437
|
-
card.slots = card.slots ?? {};
|
|
18438
|
-
card.slots.featured = composeFeatured(pricingCardStyleOf(prev2), false, badgeOf(prev2));
|
|
18439
|
-
});
|
|
18440
|
-
}
|
|
18441
|
-
const target = children[index];
|
|
18442
|
-
target.slots = target.slots ?? {};
|
|
18443
|
-
const prev = featuredOf(target);
|
|
18444
|
-
target.slots.featured = composeFeatured(pricingCardStyleOf(prev), on, badgeOf(prev));
|
|
18445
|
-
return true;
|
|
18446
|
-
});
|
|
18447
|
-
}
|
|
18448
|
-
function pricingCardStyleOf(featured) {
|
|
18449
|
-
if (featured.enabled !== true) return "outline";
|
|
18450
|
-
return PRICING_CARD_STYLES.find((s) => s.treatment === featured.treatment)?.value ?? "outline";
|
|
18451
|
-
}
|
|
18452
|
-
function addPricingCardButton(tree, index, label) {
|
|
18453
|
-
return withPricingCollection(tree, (collection) => {
|
|
18454
|
-
const children = collection.children;
|
|
18455
|
-
if (index < 0 || index >= children.length) return false;
|
|
18456
|
-
const target = children[index];
|
|
18457
|
-
const buttons = (target.children ?? []).filter((c) => c.type === "button");
|
|
18458
|
-
if (buttons.length >= 2) return false;
|
|
18459
|
-
const hasPrimary = buttons.some((b) => b.slots?.variant === "primary");
|
|
18460
|
-
target.children = [
|
|
18461
|
-
...target.children ?? [],
|
|
18462
|
-
{ type: "button", span: 12, slots: { label, href: "#", variant: hasPrimary ? "secondary" : "primary" } }
|
|
18463
|
-
];
|
|
18464
|
-
return true;
|
|
18465
|
-
});
|
|
18466
|
-
}
|
|
18467
|
-
function removePricingCardButton(tree, index) {
|
|
18468
|
-
return withPricingCollection(tree, (collection) => {
|
|
18469
|
-
const children = collection.children;
|
|
18470
|
-
if (index < 0 || index >= children.length) return false;
|
|
18471
|
-
const target = children[index];
|
|
18472
|
-
const buttons = (target.children ?? []).filter((c) => c.type === "button");
|
|
18473
|
-
if (buttons.length === 0) return false;
|
|
18474
|
-
const lastButton = buttons[buttons.length - 1];
|
|
18475
|
-
target.children = (target.children ?? []).filter((c) => c !== lastButton);
|
|
18476
|
-
return true;
|
|
18477
|
-
});
|
|
18478
|
-
}
|
|
18479
|
-
var PRICING_FEATURES_MIN = 1;
|
|
18480
|
-
var PRICING_FEATURES_MAX = 10;
|
|
18481
|
-
function pricingFeatureList(target) {
|
|
18482
|
-
const raw = target.slots?.features;
|
|
18483
|
-
if (Array.isArray(raw)) {
|
|
18484
|
-
return raw.filter((item) => !!item && typeof item === "object" && typeof item.text === "string").map((item) => ({
|
|
18485
|
-
text: item.text,
|
|
18486
|
-
...typeof item.icon === "string" ? { icon: item.icon } : {},
|
|
18487
|
-
...typeof item.iconColor === "string" ? { iconColor: item.iconColor } : {}
|
|
18488
|
-
}));
|
|
18489
|
-
}
|
|
18490
|
-
if (typeof raw === "string") {
|
|
18491
|
-
return raw.split(/\n|<br\s*\/?>/i).map((line) => line.replace(/<[^>]+>/g, "").replace(/^[-*•]\s*/, "").trim().slice(0, 120)).filter(Boolean).map((text) => ({ text }));
|
|
18492
|
-
}
|
|
18493
|
-
return [];
|
|
18494
|
-
}
|
|
18495
|
-
function pricingCardFeatureCount(tree, index) {
|
|
18496
|
-
const target = findPricingCollection(tree)?.children?.[index];
|
|
18497
|
-
return target ? pricingFeatureList(target).length : 0;
|
|
18498
|
-
}
|
|
18499
|
-
function addPricingCardFeature(tree, index, text) {
|
|
18500
|
-
return withPricingCollection(tree, (collection) => {
|
|
18501
|
-
const children = collection.children;
|
|
18502
|
-
if (index < 0 || index >= children.length) return false;
|
|
18503
|
-
const target = children[index];
|
|
18504
|
-
const features = pricingFeatureList(target);
|
|
18505
|
-
if (features.length >= PRICING_FEATURES_MAX) return false;
|
|
18506
|
-
target.slots = target.slots ?? {};
|
|
18507
|
-
target.slots.features = [...features, { text }];
|
|
18508
|
-
return true;
|
|
18509
|
-
});
|
|
18510
|
-
}
|
|
18511
|
-
function removePricingCardFeature(tree, index) {
|
|
18512
|
-
return withPricingCollection(tree, (collection) => {
|
|
18513
|
-
const children = collection.children;
|
|
18514
|
-
if (index < 0 || index >= children.length) return false;
|
|
18515
|
-
const target = children[index];
|
|
18516
|
-
const features = pricingFeatureList(target);
|
|
18517
|
-
if (features.length <= PRICING_FEATURES_MIN) return false;
|
|
18518
|
-
target.slots = target.slots ?? {};
|
|
18519
|
-
target.slots.features = features.slice(0, -1);
|
|
18520
|
-
return true;
|
|
18521
|
-
});
|
|
18522
|
-
}
|
|
18523
|
-
|
|
18524
|
-
// src/ui/ai-section/AiPricingCardOverlay.tsx
|
|
18525
18609
|
import { Fragment as Fragment7, jsx as jsx20, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
18526
18610
|
var PRIMARY4 = "var(--ohw-primary, #0885FE)";
|
|
18527
18611
|
var CHROME_SELECTOR = "[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-link-modal-root], [data-ohw-section-picker], [data-ohw-ai-review], [data-ohw-more-menu]";
|
|
@@ -23653,6 +23737,23 @@ function currentIconRef(el) {
|
|
|
23653
23737
|
);
|
|
23654
23738
|
return named ? `lucide:${named.slice("lucide-".length)}` : "";
|
|
23655
23739
|
}
|
|
23740
|
+
function requestValidateTree5(postToParent2, tree) {
|
|
23741
|
+
return new Promise((resolve) => {
|
|
23742
|
+
const id = `ai-validate-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
23743
|
+
const timeout = window.setTimeout(() => {
|
|
23744
|
+
window.removeEventListener("message", onMessage);
|
|
23745
|
+
resolve({ ok: false, reasons: ["Validation request timed out."] });
|
|
23746
|
+
}, 8e3);
|
|
23747
|
+
function onMessage(e) {
|
|
23748
|
+
if (e.data?.type !== "ow:ai-validate-tree-result" || e.data.id !== id) return;
|
|
23749
|
+
window.clearTimeout(timeout);
|
|
23750
|
+
window.removeEventListener("message", onMessage);
|
|
23751
|
+
resolve({ ok: e.data.ok === true, reasons: Array.isArray(e.data.reasons) ? e.data.reasons : [] });
|
|
23752
|
+
}
|
|
23753
|
+
window.addEventListener("message", onMessage);
|
|
23754
|
+
postToParent2({ type: "ow:ai-validate-tree-request", id, tree });
|
|
23755
|
+
});
|
|
23756
|
+
}
|
|
23656
23757
|
function getEditMeasureEl(editable) {
|
|
23657
23758
|
return editable.closest("[data-ohw-href-key]") ?? editable;
|
|
23658
23759
|
}
|
|
@@ -28004,10 +28105,14 @@ function OhhwellsBridge() {
|
|
|
28004
28105
|
e.preventDefault();
|
|
28005
28106
|
e.stopPropagation();
|
|
28006
28107
|
aiSectionApiRef.current?.selectFromElement(editable);
|
|
28108
|
+
const aiIcon = editable.hasAttribute("data-ai-icon");
|
|
28109
|
+
const featureIcon = aiIcon && /\.features\.\d+\.icon$/.test(editable.dataset.ohwKey ?? "");
|
|
28007
28110
|
postToParentRef.current({
|
|
28008
28111
|
type: "ow:icon-pick",
|
|
28009
28112
|
key: editable.dataset.ohwKey ?? "",
|
|
28010
|
-
current: currentIconRef(editable)
|
|
28113
|
+
current: currentIconRef(editable),
|
|
28114
|
+
...aiIcon ? { iconMode: "name" } : {},
|
|
28115
|
+
...featureIcon ? { options: [...PRICING_FEATURE_ICONS] } : {}
|
|
28011
28116
|
});
|
|
28012
28117
|
return;
|
|
28013
28118
|
}
|
|
@@ -29254,15 +29359,43 @@ function OhhwellsBridge() {
|
|
|
29254
29359
|
if (e.data?.type !== "ow:icon-markup") return;
|
|
29255
29360
|
const { key, markup } = e.data;
|
|
29256
29361
|
if (!key || typeof markup !== "string") return;
|
|
29257
|
-
const targets =
|
|
29258
|
-
`[data-ohw-key="${key}"][data-ohw-editable="icon"]`
|
|
29259
|
-
);
|
|
29362
|
+
const targets = Array.from(
|
|
29363
|
+
document.querySelectorAll(`[data-ohw-key="${key}"][data-ohw-editable="icon"]`)
|
|
29364
|
+
).filter((el) => !el.hasAttribute("data-ai-icon"));
|
|
29260
29365
|
if (!targets.length) return;
|
|
29261
29366
|
targets.forEach((el) => {
|
|
29262
29367
|
applyIconMarkup(el, markup);
|
|
29263
29368
|
});
|
|
29264
29369
|
postToParentRef.current({ type: "ow:change", nodes: [{ key, text: markup }], flush: true });
|
|
29265
29370
|
};
|
|
29371
|
+
const handleIconName = (e) => {
|
|
29372
|
+
if (e.data?.type !== "ow:icon-name") return;
|
|
29373
|
+
const { key, icon, url } = e.data;
|
|
29374
|
+
const isName = typeof icon === "string" && /^[a-z0-9-]+$/.test(icon);
|
|
29375
|
+
const isUpload = !isName && typeof url === "string" && /^https?:\/\/\S+$/i.test(url);
|
|
29376
|
+
if (!key || !isName && !isUpload) return;
|
|
29377
|
+
const state = parseAiSectionsState(aiSectionsRef.current);
|
|
29378
|
+
const entry = state.sections.find((s) => key.startsWith(aiSlotKeyPrefixFor(s.id)));
|
|
29379
|
+
if (!entry) return;
|
|
29380
|
+
const path = key.slice(aiSlotKeyPrefixFor(entry.id).length);
|
|
29381
|
+
const uploadRef = isUpload ? `icon-${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}` : null;
|
|
29382
|
+
const nextTree = uploadRef ? applyIconUploadToTree(entry.tree, path, uploadRef) : applyIconNameToTree(entry.tree, path, icon);
|
|
29383
|
+
if (!nextTree) return;
|
|
29384
|
+
void requestValidateTree5(postToParentRef.current, nextTree).then(({ ok }) => {
|
|
29385
|
+
if (!ok) return;
|
|
29386
|
+
applyTreeLocalRef.current?.({
|
|
29387
|
+
id: entry.id,
|
|
29388
|
+
mode: "replace",
|
|
29389
|
+
targetSectionId: entry.id,
|
|
29390
|
+
tree: nextTree,
|
|
29391
|
+
label: entry.label,
|
|
29392
|
+
media: uploadRef ? { ...entry.media, [uploadRef]: url } : entry.media,
|
|
29393
|
+
...entry.brand ? { brand: entry.brand } : {},
|
|
29394
|
+
// The user is looking at the icon they just changed — no need to recenter on it.
|
|
29395
|
+
skipScrollIntoView: true
|
|
29396
|
+
});
|
|
29397
|
+
});
|
|
29398
|
+
};
|
|
29266
29399
|
const handleImageUrl = (e) => {
|
|
29267
29400
|
if (e.data?.type !== "ow:image-url") return;
|
|
29268
29401
|
const { key, url } = e.data;
|
|
@@ -30711,6 +30844,7 @@ function OhhwellsBridge() {
|
|
|
30711
30844
|
window.addEventListener("message", handleSocialCancel);
|
|
30712
30845
|
window.addEventListener("message", handleSocialUpdate);
|
|
30713
30846
|
window.addEventListener("message", handleIconMarkup);
|
|
30847
|
+
window.addEventListener("message", handleIconName);
|
|
30714
30848
|
window.addEventListener("message", handleImageUrl);
|
|
30715
30849
|
window.addEventListener("message", handleImageUploading);
|
|
30716
30850
|
window.addEventListener("message", handleCarouselChange);
|
|
@@ -30795,6 +30929,7 @@ function OhhwellsBridge() {
|
|
|
30795
30929
|
window.removeEventListener("message", handleSocialCancel);
|
|
30796
30930
|
window.removeEventListener("message", handleSocialUpdate);
|
|
30797
30931
|
window.removeEventListener("message", handleIconMarkup);
|
|
30932
|
+
window.removeEventListener("message", handleIconName);
|
|
30798
30933
|
window.removeEventListener("message", handleImageUrl);
|
|
30799
30934
|
window.removeEventListener("message", handleImageUploading);
|
|
30800
30935
|
window.removeEventListener("message", handleCarouselChange);
|
|
@@ -31120,7 +31255,7 @@ function OhhwellsBridge() {
|
|
|
31120
31255
|
postToParent2({
|
|
31121
31256
|
type: "ow:ready",
|
|
31122
31257
|
version: "1",
|
|
31123
|
-
bridgeVersion: "0.1.
|
|
31258
|
+
bridgeVersion: "0.1.142",
|
|
31124
31259
|
path: pathname,
|
|
31125
31260
|
nodes: collectEditableNodes(editContentRef.current),
|
|
31126
31261
|
sections
|