@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.cjs
CHANGED
|
@@ -1350,15 +1350,25 @@ function readAssignments(content) {
|
|
|
1350
1350
|
function cssLength(style, prop) {
|
|
1351
1351
|
return style.getPropertyValue(prop) || "0px";
|
|
1352
1352
|
}
|
|
1353
|
+
function withTransitionsSettled(el, read) {
|
|
1354
|
+
const prior = el.style.getPropertyValue("transition");
|
|
1355
|
+
const priority = el.style.getPropertyPriority("transition");
|
|
1356
|
+
el.style.setProperty("transition", "none", "important");
|
|
1357
|
+
try {
|
|
1358
|
+
return read(getComputedStyle(el));
|
|
1359
|
+
} finally {
|
|
1360
|
+
if (prior) el.style.setProperty("transition", prior, priority);
|
|
1361
|
+
else el.style.removeProperty("transition");
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1353
1364
|
function readVariantSample(el) {
|
|
1354
|
-
|
|
1355
|
-
return {
|
|
1365
|
+
return withTransitionsSettled(el, (style) => ({
|
|
1356
1366
|
background: style.backgroundColor,
|
|
1357
1367
|
color: style.color,
|
|
1358
1368
|
borderColor: style.borderTopColor,
|
|
1359
1369
|
borderWidth: style.borderTopWidth,
|
|
1360
1370
|
className: el.className || ""
|
|
1361
|
-
};
|
|
1371
|
+
}));
|
|
1362
1372
|
}
|
|
1363
1373
|
function readSizeSample(el) {
|
|
1364
1374
|
const style = getComputedStyle(el);
|
|
@@ -5023,10 +5033,9 @@ function getLinkHref3(el) {
|
|
|
5023
5033
|
}
|
|
5024
5034
|
function collectEditableNodes(extraContent, root = document) {
|
|
5025
5035
|
const isScoped = root !== document;
|
|
5026
|
-
const
|
|
5027
|
-
|
|
5028
|
-
)
|
|
5029
|
-
if (isScoped && root instanceof HTMLElement && root.matches('[data-ohw-editable]:not([data-ohw-editable="form"])')) {
|
|
5036
|
+
const EDITABLE_SELECTOR = '[data-ohw-editable]:not([data-ohw-editable="form"]):not([data-ai-icon])';
|
|
5037
|
+
const editableEls = Array.from(root.querySelectorAll(EDITABLE_SELECTOR));
|
|
5038
|
+
if (isScoped && root instanceof HTMLElement && root.matches(EDITABLE_SELECTOR)) {
|
|
5030
5039
|
editableEls.unshift(root);
|
|
5031
5040
|
}
|
|
5032
5041
|
const nodes = editableEls.map((el) => {
|
|
@@ -6293,6 +6302,281 @@ function reapRemovedAiSections(state, store, removedIds, excludeIds = /* @__PURE
|
|
|
6293
6302
|
return { state: nextState, store: nextStore, reapedIds, slotPrefixes, changed: true };
|
|
6294
6303
|
}
|
|
6295
6304
|
|
|
6305
|
+
// src/lib/ai-pricing-tree.ts
|
|
6306
|
+
var PRICING_MIN_CARDS = 1;
|
|
6307
|
+
var PRICING_MAX_CARDS = 4;
|
|
6308
|
+
function isPricingCard(node) {
|
|
6309
|
+
return typeof node === "object" && node !== null && node.type === "card" && node.slots?.preset === "pricing";
|
|
6310
|
+
}
|
|
6311
|
+
function isPricingCollection(node) {
|
|
6312
|
+
return node.type === "collection" && Array.isArray(node.children) && node.children.length > 0 && isPricingCard(node.children[0]);
|
|
6313
|
+
}
|
|
6314
|
+
function findCollection(node) {
|
|
6315
|
+
if (isPricingCollection(node)) return node;
|
|
6316
|
+
for (const child of node.children ?? []) {
|
|
6317
|
+
const found = findCollection(child);
|
|
6318
|
+
if (found) return found;
|
|
6319
|
+
}
|
|
6320
|
+
return null;
|
|
6321
|
+
}
|
|
6322
|
+
function findPricingCollection(tree) {
|
|
6323
|
+
for (const row of tree.rows ?? []) {
|
|
6324
|
+
for (const block of row.blocks ?? []) {
|
|
6325
|
+
const found = findCollection(block);
|
|
6326
|
+
if (found) return found;
|
|
6327
|
+
}
|
|
6328
|
+
}
|
|
6329
|
+
return null;
|
|
6330
|
+
}
|
|
6331
|
+
function pricingCardCount(tree) {
|
|
6332
|
+
return findPricingCollection(tree)?.children?.length ?? 0;
|
|
6333
|
+
}
|
|
6334
|
+
function withPricingCollection(tree, mutate) {
|
|
6335
|
+
const next = JSON.parse(JSON.stringify(tree));
|
|
6336
|
+
const collection = findPricingCollection(next);
|
|
6337
|
+
if (!collection || !collection.children) return null;
|
|
6338
|
+
for (const card of collection.children) {
|
|
6339
|
+
if (isPricingCard(card)) upgradeLegacyPricingSlots(card);
|
|
6340
|
+
}
|
|
6341
|
+
return mutate(collection) ? next : null;
|
|
6342
|
+
}
|
|
6343
|
+
function upgradeLegacyPricingSlots(card) {
|
|
6344
|
+
const slots = card.slots = card.slots ?? {};
|
|
6345
|
+
if (typeof slots.features === "string") {
|
|
6346
|
+
const rows = pricingFeatureList(card);
|
|
6347
|
+
if (rows.length > 0) slots.features = rows.slice(0, PRICING_FEATURES_MAX);
|
|
6348
|
+
}
|
|
6349
|
+
if (slots.featured === true) slots.featured = { enabled: true };
|
|
6350
|
+
else if (slots.featured === false) delete slots.featured;
|
|
6351
|
+
}
|
|
6352
|
+
function addPricingTier(tree) {
|
|
6353
|
+
return withPricingCollection(tree, (collection) => {
|
|
6354
|
+
const children = collection.children;
|
|
6355
|
+
if (children.length >= PRICING_MAX_CARDS) return false;
|
|
6356
|
+
const clone = JSON.parse(JSON.stringify(children[children.length - 1]));
|
|
6357
|
+
clone.slots = clone.slots ?? {};
|
|
6358
|
+
delete clone.slots.featured;
|
|
6359
|
+
clone.slots.heading = "New tier";
|
|
6360
|
+
children.push(clone);
|
|
6361
|
+
collection.slots = { ...collection.slots, itemsPerRow: children.length };
|
|
6362
|
+
return true;
|
|
6363
|
+
});
|
|
6364
|
+
}
|
|
6365
|
+
function removePricingTier(tree, index) {
|
|
6366
|
+
return withPricingCollection(tree, (collection) => {
|
|
6367
|
+
const children = collection.children;
|
|
6368
|
+
if (children.length <= PRICING_MIN_CARDS) return false;
|
|
6369
|
+
if (index < 0 || index >= children.length) return false;
|
|
6370
|
+
children.splice(index, 1);
|
|
6371
|
+
collection.slots = { ...collection.slots, itemsPerRow: children.length };
|
|
6372
|
+
return true;
|
|
6373
|
+
});
|
|
6374
|
+
}
|
|
6375
|
+
var PRICING_CARD_STYLES = [
|
|
6376
|
+
{ value: "outline", label: "Outline", treatment: null },
|
|
6377
|
+
{ value: "lift", label: "Lift", treatment: "lifted" },
|
|
6378
|
+
{ value: "invert", label: "Invert", treatment: "inverted" },
|
|
6379
|
+
{ value: "header", label: "Header", treatment: "accent-header" }
|
|
6380
|
+
];
|
|
6381
|
+
var DEFAULT_FEATURED_BADGE = "Most popular";
|
|
6382
|
+
function featuredOf(target) {
|
|
6383
|
+
const raw = target?.slots?.featured;
|
|
6384
|
+
if (raw === true) return { enabled: true, treatment: "outlined" };
|
|
6385
|
+
return typeof raw === "object" && raw !== null ? raw : {};
|
|
6386
|
+
}
|
|
6387
|
+
function badgeOf(featured) {
|
|
6388
|
+
return typeof featured.badge === "string" ? featured.badge.trim() : "";
|
|
6389
|
+
}
|
|
6390
|
+
function pricingCardStyle(tree, index) {
|
|
6391
|
+
const featured = featuredOf(findPricingCollection(tree)?.children?.[index]);
|
|
6392
|
+
if (featured.enabled !== true) return "outline";
|
|
6393
|
+
return PRICING_CARD_STYLES.find((s) => s.treatment === featured.treatment)?.value ?? "outline";
|
|
6394
|
+
}
|
|
6395
|
+
function pricingCardFeaturedTag(tree, index) {
|
|
6396
|
+
const featured = featuredOf(findPricingCollection(tree)?.children?.[index]);
|
|
6397
|
+
return featured.enabled === true && badgeOf(featured).length > 0;
|
|
6398
|
+
}
|
|
6399
|
+
function composeFeatured(style, tagOn, badgeText) {
|
|
6400
|
+
const treatment = PRICING_CARD_STYLES.find((s) => s.value === style)?.treatment ?? null;
|
|
6401
|
+
if (tagOn) return { enabled: true, badge: badgeText || DEFAULT_FEATURED_BADGE, treatment: treatment ?? "outlined" };
|
|
6402
|
+
if (treatment) return { enabled: true, treatment };
|
|
6403
|
+
return badgeText.length > 0 ? { enabled: false, badge: badgeText } : { enabled: false };
|
|
6404
|
+
}
|
|
6405
|
+
function withPricingCard(tree, index, mutate) {
|
|
6406
|
+
return withPricingCollection(tree, (collection) => {
|
|
6407
|
+
const children = collection.children;
|
|
6408
|
+
if (index < 0 || index >= children.length) return false;
|
|
6409
|
+
const target = children[index];
|
|
6410
|
+
target.slots = target.slots ?? {};
|
|
6411
|
+
mutate(target);
|
|
6412
|
+
return true;
|
|
6413
|
+
});
|
|
6414
|
+
}
|
|
6415
|
+
function setPricingCardStyle(tree, index, style) {
|
|
6416
|
+
if (!PRICING_CARD_STYLES.some((s) => s.value === style)) return null;
|
|
6417
|
+
return withPricingCard(tree, index, (target) => {
|
|
6418
|
+
const prev = featuredOf(target);
|
|
6419
|
+
const tagOn = prev.enabled === true && badgeOf(prev).length > 0;
|
|
6420
|
+
target.slots.featured = composeFeatured(style, tagOn, badgeOf(prev));
|
|
6421
|
+
});
|
|
6422
|
+
}
|
|
6423
|
+
function setPricingCardFeaturedTag(tree, index, on) {
|
|
6424
|
+
return withPricingCollection(tree, (collection) => {
|
|
6425
|
+
const children = collection.children;
|
|
6426
|
+
if (index < 0 || index >= children.length) return false;
|
|
6427
|
+
if (on) {
|
|
6428
|
+
children.forEach((card, i) => {
|
|
6429
|
+
if (i === index) return;
|
|
6430
|
+
const prev2 = featuredOf(card);
|
|
6431
|
+
if (prev2.enabled !== true || badgeOf(prev2).length === 0) return;
|
|
6432
|
+
card.slots = card.slots ?? {};
|
|
6433
|
+
card.slots.featured = composeFeatured(pricingCardStyleOf(prev2), false, badgeOf(prev2));
|
|
6434
|
+
});
|
|
6435
|
+
}
|
|
6436
|
+
const target = children[index];
|
|
6437
|
+
target.slots = target.slots ?? {};
|
|
6438
|
+
const prev = featuredOf(target);
|
|
6439
|
+
target.slots.featured = composeFeatured(pricingCardStyleOf(prev), on, badgeOf(prev));
|
|
6440
|
+
return true;
|
|
6441
|
+
});
|
|
6442
|
+
}
|
|
6443
|
+
function pricingCardStyleOf(featured) {
|
|
6444
|
+
if (featured.enabled !== true) return "outline";
|
|
6445
|
+
return PRICING_CARD_STYLES.find((s) => s.treatment === featured.treatment)?.value ?? "outline";
|
|
6446
|
+
}
|
|
6447
|
+
function addPricingCardButton(tree, index, label) {
|
|
6448
|
+
return withPricingCollection(tree, (collection) => {
|
|
6449
|
+
const children = collection.children;
|
|
6450
|
+
if (index < 0 || index >= children.length) return false;
|
|
6451
|
+
const target = children[index];
|
|
6452
|
+
const buttons = (target.children ?? []).filter((c) => c.type === "button");
|
|
6453
|
+
if (buttons.length >= 2) return false;
|
|
6454
|
+
const hasPrimary = buttons.some((b) => b.slots?.variant === "primary");
|
|
6455
|
+
target.children = [
|
|
6456
|
+
...target.children ?? [],
|
|
6457
|
+
{ type: "button", span: 12, slots: { label, href: "#", variant: hasPrimary ? "secondary" : "primary" } }
|
|
6458
|
+
];
|
|
6459
|
+
return true;
|
|
6460
|
+
});
|
|
6461
|
+
}
|
|
6462
|
+
function removePricingCardButton(tree, index) {
|
|
6463
|
+
return withPricingCollection(tree, (collection) => {
|
|
6464
|
+
const children = collection.children;
|
|
6465
|
+
if (index < 0 || index >= children.length) return false;
|
|
6466
|
+
const target = children[index];
|
|
6467
|
+
const buttons = (target.children ?? []).filter((c) => c.type === "button");
|
|
6468
|
+
if (buttons.length === 0) return false;
|
|
6469
|
+
const lastButton = buttons[buttons.length - 1];
|
|
6470
|
+
target.children = (target.children ?? []).filter((c) => c !== lastButton);
|
|
6471
|
+
return true;
|
|
6472
|
+
});
|
|
6473
|
+
}
|
|
6474
|
+
var PRICING_FEATURES_MIN = 1;
|
|
6475
|
+
var PRICING_FEATURES_MAX = 10;
|
|
6476
|
+
var PRICING_FEATURE_ICONS = [
|
|
6477
|
+
"check",
|
|
6478
|
+
"check-circle",
|
|
6479
|
+
"x",
|
|
6480
|
+
"star",
|
|
6481
|
+
"zap",
|
|
6482
|
+
"shield",
|
|
6483
|
+
"clock",
|
|
6484
|
+
"users",
|
|
6485
|
+
"infinity"
|
|
6486
|
+
];
|
|
6487
|
+
function pricingFeatureList(target) {
|
|
6488
|
+
const raw = target.slots?.features;
|
|
6489
|
+
if (Array.isArray(raw)) {
|
|
6490
|
+
return raw.filter((item) => !!item && typeof item === "object" && typeof item.text === "string").map((item) => ({
|
|
6491
|
+
text: item.text,
|
|
6492
|
+
...typeof item.icon === "string" ? { icon: item.icon } : {},
|
|
6493
|
+
...typeof item.iconColor === "string" ? { iconColor: item.iconColor } : {}
|
|
6494
|
+
}));
|
|
6495
|
+
}
|
|
6496
|
+
if (typeof raw === "string") {
|
|
6497
|
+
return raw.split(/\n|<br\s*\/?>/i).map((line) => line.replace(/<[^>]+>/g, "").replace(/^[-*•]\s*/, "").trim().slice(0, 120)).filter(Boolean).map((text) => ({ text }));
|
|
6498
|
+
}
|
|
6499
|
+
return [];
|
|
6500
|
+
}
|
|
6501
|
+
function pricingCardFeatureCount(tree, index) {
|
|
6502
|
+
const target = findPricingCollection(tree)?.children?.[index];
|
|
6503
|
+
return target ? pricingFeatureList(target).length : 0;
|
|
6504
|
+
}
|
|
6505
|
+
function addPricingCardFeature(tree, index, text) {
|
|
6506
|
+
return withPricingCollection(tree, (collection) => {
|
|
6507
|
+
const children = collection.children;
|
|
6508
|
+
if (index < 0 || index >= children.length) return false;
|
|
6509
|
+
const target = children[index];
|
|
6510
|
+
const features = pricingFeatureList(target);
|
|
6511
|
+
if (features.length >= PRICING_FEATURES_MAX) return false;
|
|
6512
|
+
target.slots = target.slots ?? {};
|
|
6513
|
+
target.slots.features = [...features, { text }];
|
|
6514
|
+
return true;
|
|
6515
|
+
});
|
|
6516
|
+
}
|
|
6517
|
+
function setPricingCardFeatureIcon(tree, index, featureIndex, icon) {
|
|
6518
|
+
if (!PRICING_FEATURE_ICONS.includes(icon)) return null;
|
|
6519
|
+
return withPricingCollection(tree, (collection) => {
|
|
6520
|
+
const children = collection.children;
|
|
6521
|
+
if (index < 0 || index >= children.length) return false;
|
|
6522
|
+
const target = children[index];
|
|
6523
|
+
const features = pricingFeatureList(target);
|
|
6524
|
+
if (featureIndex < 0 || featureIndex >= features.length) return false;
|
|
6525
|
+
target.slots = target.slots ?? {};
|
|
6526
|
+
target.slots.features = features.map((row, i) => i === featureIndex ? { ...row, icon } : row);
|
|
6527
|
+
return true;
|
|
6528
|
+
});
|
|
6529
|
+
}
|
|
6530
|
+
function removePricingCardFeature(tree, index) {
|
|
6531
|
+
return withPricingCollection(tree, (collection) => {
|
|
6532
|
+
const children = collection.children;
|
|
6533
|
+
if (index < 0 || index >= children.length) return false;
|
|
6534
|
+
const target = children[index];
|
|
6535
|
+
const features = pricingFeatureList(target);
|
|
6536
|
+
if (features.length <= PRICING_FEATURES_MIN) return false;
|
|
6537
|
+
target.slots = target.slots ?? {};
|
|
6538
|
+
target.slots.features = features.slice(0, -1);
|
|
6539
|
+
return true;
|
|
6540
|
+
});
|
|
6541
|
+
}
|
|
6542
|
+
|
|
6543
|
+
// src/lib/ai-icon-edit.ts
|
|
6544
|
+
var FEATURE_ICON_PATH = /\.c(\d+)\.features\.(\d+)\.icon$/;
|
|
6545
|
+
var NODE_SEGMENT = /^[rbc]\d+$/;
|
|
6546
|
+
function nodeAtPath(tree, segments) {
|
|
6547
|
+
if (segments.length < 2 || segments.some((s) => !NODE_SEGMENT.test(s))) return null;
|
|
6548
|
+
if (!segments[0].startsWith("r") || !segments[1].startsWith("b")) return null;
|
|
6549
|
+
let node = tree.rows?.[Number(segments[0].slice(1))]?.blocks?.[Number(segments[1].slice(1))];
|
|
6550
|
+
for (const segment of segments.slice(2)) {
|
|
6551
|
+
if (!segment.startsWith("c")) return null;
|
|
6552
|
+
node = node?.children?.[Number(segment.slice(1))];
|
|
6553
|
+
}
|
|
6554
|
+
return node ?? null;
|
|
6555
|
+
}
|
|
6556
|
+
function applyIconNameToTree(tree, path, icon) {
|
|
6557
|
+
const feature = path.match(FEATURE_ICON_PATH);
|
|
6558
|
+
if (feature) {
|
|
6559
|
+
return setPricingCardFeatureIcon(tree, Number(feature[1]), Number(feature[2]), icon);
|
|
6560
|
+
}
|
|
6561
|
+
return rewriteIconSlot(tree, path, `lucide:${icon}`);
|
|
6562
|
+
}
|
|
6563
|
+
function applyIconUploadToTree(tree, path, mediaRef) {
|
|
6564
|
+
if (FEATURE_ICON_PATH.test(path)) return null;
|
|
6565
|
+
return rewriteIconSlot(tree, path, `icon:${mediaRef}`);
|
|
6566
|
+
}
|
|
6567
|
+
function rewriteIconSlot(tree, path, ref) {
|
|
6568
|
+
const segments = path.split(".");
|
|
6569
|
+
const slot = segments.pop();
|
|
6570
|
+
if (!slot || NODE_SEGMENT.test(slot)) return null;
|
|
6571
|
+
const next = JSON.parse(JSON.stringify(tree));
|
|
6572
|
+
const node = nodeAtPath(next, segments);
|
|
6573
|
+
if (!node) return null;
|
|
6574
|
+
const current = node.slots?.[slot];
|
|
6575
|
+
if (typeof current !== "string" || !/^(lucide|simple|icon):/.test(current)) return null;
|
|
6576
|
+
node.slots = { ...node.slots, [slot]: ref };
|
|
6577
|
+
return next;
|
|
6578
|
+
}
|
|
6579
|
+
|
|
6296
6580
|
// src/lib/ai-footer-tree.ts
|
|
6297
6581
|
var FOOTER_COLUMN_SPANS = [12, 6, 4, 3];
|
|
6298
6582
|
var FOOTER_COLUMN_BLOCKS = [
|
|
@@ -7649,7 +7933,7 @@ function MediaBox({
|
|
|
7649
7933
|
onError
|
|
7650
7934
|
}) {
|
|
7651
7935
|
const url = refValue ? ctx.resolveMedia(refValue) : null;
|
|
7652
|
-
const isIcon = /^(lucide|simple):/.test(refValue);
|
|
7936
|
+
const isIcon = /^(lucide|simple|icon):/.test(refValue);
|
|
7653
7937
|
const aspectRatio = aspect && /^\d+:\d+$/.test(aspect) ? aspect.replace(":", " / ") : void 0;
|
|
7654
7938
|
const editAttrs = ctx.keyFor && editPath && !isIcon ? {
|
|
7655
7939
|
"data-ohw-key": ctx.keyFor(editPath),
|
|
@@ -7657,10 +7941,13 @@ function MediaBox({
|
|
|
7657
7941
|
} : {};
|
|
7658
7942
|
if (isIcon) {
|
|
7659
7943
|
const Icon = refValue.startsWith("lucide:") ? lucideByName(refValue.slice(7)) : null;
|
|
7944
|
+
const uploadedIconUrl = refValue.startsWith("icon:") ? ctx.resolveMedia(refValue.slice(5)) : null;
|
|
7945
|
+
const iconEditAttrs = ctx.keyFor && editPath && genericImageEdit ? { "data-ohw-key": ctx.keyFor(editPath), "data-ohw-editable": "icon" } : {};
|
|
7660
7946
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
7661
7947
|
"span",
|
|
7662
7948
|
{
|
|
7663
7949
|
"data-ai-icon": refValue,
|
|
7950
|
+
...iconEditAttrs,
|
|
7664
7951
|
style: {
|
|
7665
7952
|
display: "inline-flex",
|
|
7666
7953
|
width: 48,
|
|
@@ -7669,7 +7956,7 @@ function MediaBox({
|
|
|
7669
7956
|
justifyContent: "center",
|
|
7670
7957
|
color: ctx.brand.palette.dark
|
|
7671
7958
|
},
|
|
7672
|
-
children: Icon ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { size: 48, color: ctx.brand.palette.dark, strokeWidth: 1.5 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: 24 }, children: "\u25C6" })
|
|
7959
|
+
children: uploadedIconUrl ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: uploadedIconUrl, alt: "", style: { width: 48, height: 48, objectFit: "contain" } }) : Icon ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { size: 48, color: ctx.brand.palette.dark, strokeWidth: 1.5 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: 24 }, children: "\u25C6" })
|
|
7673
7960
|
}
|
|
7674
7961
|
);
|
|
7675
7962
|
}
|
|
@@ -8157,8 +8444,20 @@ function PricingCard({ node, ctx, path }) {
|
|
|
8157
8444
|
/* @__PURE__ */ (0, import_jsx_runtime.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) => {
|
|
8158
8445
|
const Icon = lucideByName(item.icon || "check");
|
|
8159
8446
|
const iconColor = pricingIconColor(item.iconColor, ctx.brand, fg);
|
|
8447
|
+
const iconAttrs = ctx.keyFor && !item.html ? {
|
|
8448
|
+
"data-ohw-key": ctx.keyFor(`${path}.features.${i}.icon`),
|
|
8449
|
+
"data-ohw-editable": "icon"
|
|
8450
|
+
} : {};
|
|
8160
8451
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", alignItems: "flex-start", gap: AI_TREE_TOKENS.spacing3 }, children: [
|
|
8161
|
-
Icon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
8452
|
+
Icon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
8453
|
+
"span",
|
|
8454
|
+
{
|
|
8455
|
+
"data-ai-icon": `lucide:${item.icon || "check"}`,
|
|
8456
|
+
...iconAttrs,
|
|
8457
|
+
style: { display: "inline-flex", flexShrink: 0 },
|
|
8458
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { size: 20, color: iconColor })
|
|
8459
|
+
}
|
|
8460
|
+
),
|
|
8162
8461
|
item.html ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
8163
8462
|
"span",
|
|
8164
8463
|
{
|
|
@@ -10281,38 +10580,39 @@ function deriveTemplateButtonStyle() {
|
|
|
10281
10580
|
el.querySelectorAll("[data-ohw-editable]").length <= 1
|
|
10282
10581
|
);
|
|
10283
10582
|
const isFilled = (el) => {
|
|
10284
|
-
const bg =
|
|
10583
|
+
const bg = withTransitionsSettled(el, (s) => s.backgroundColor);
|
|
10285
10584
|
if (!bg || bg === "transparent") return false;
|
|
10286
10585
|
const alpha = bg.match(/rgba?\([^)]*,\s*([\d.]+)\)$/);
|
|
10287
10586
|
return !alpha || parseFloat(alpha[1]) > 0;
|
|
10288
10587
|
};
|
|
10289
10588
|
const btn = candidates.find(isFilled) ?? candidates[0];
|
|
10290
10589
|
if (!btn) return null;
|
|
10291
|
-
|
|
10292
|
-
|
|
10293
|
-
|
|
10294
|
-
|
|
10295
|
-
|
|
10296
|
-
|
|
10297
|
-
|
|
10298
|
-
|
|
10299
|
-
|
|
10300
|
-
|
|
10301
|
-
|
|
10302
|
-
|
|
10303
|
-
|
|
10304
|
-
|
|
10305
|
-
|
|
10306
|
-
|
|
10307
|
-
|
|
10308
|
-
|
|
10309
|
-
|
|
10310
|
-
|
|
10311
|
-
|
|
10312
|
-
|
|
10313
|
-
|
|
10314
|
-
|
|
10315
|
-
|
|
10590
|
+
return withTransitionsSettled(btn, (cs) => {
|
|
10591
|
+
const filled = isFilled(btn);
|
|
10592
|
+
const corners = [
|
|
10593
|
+
cs.borderTopLeftRadius,
|
|
10594
|
+
cs.borderTopRightRadius,
|
|
10595
|
+
cs.borderBottomRightRadius,
|
|
10596
|
+
cs.borderBottomLeftRadius
|
|
10597
|
+
].map((v) => v || "0px");
|
|
10598
|
+
const radius = corners.every((v) => v === corners[0]) ? corners[0] : corners.join(" ");
|
|
10599
|
+
const px2 = (v) => parseFloat(v) || 0;
|
|
10600
|
+
const lineHeight = px2(cs.lineHeight) || px2(cs.fontSize) * 1.2;
|
|
10601
|
+
const contentH = btn.getBoundingClientRect().height - px2(cs.borderTopWidth) - px2(cs.borderBottomWidth);
|
|
10602
|
+
const impliedY = Math.round(Math.max(0, (contentH - lineHeight) / 2));
|
|
10603
|
+
const padY = Math.max(px2(cs.paddingTop), px2(cs.paddingBottom), impliedY);
|
|
10604
|
+
const padX = Math.max(px2(cs.paddingLeft), px2(cs.paddingRight));
|
|
10605
|
+
return {
|
|
10606
|
+
radius: radius || "10px",
|
|
10607
|
+
padding: `${padY}px ${padX}px`,
|
|
10608
|
+
...filled ? { background: cs.backgroundColor, color: cs.color } : {},
|
|
10609
|
+
fontFamily: cs.fontFamily || "",
|
|
10610
|
+
fontSize: cs.fontSize || "",
|
|
10611
|
+
fontWeight: cs.fontWeight || "",
|
|
10612
|
+
letterSpacing: cs.letterSpacing || "",
|
|
10613
|
+
textTransform: cs.textTransform || ""
|
|
10614
|
+
};
|
|
10615
|
+
});
|
|
10316
10616
|
}
|
|
10317
10617
|
var mounted = /* @__PURE__ */ new Map();
|
|
10318
10618
|
function findTemplateSection(id) {
|
|
@@ -18400,222 +18700,6 @@ function AiMediaStripOverlay({
|
|
|
18400
18700
|
// src/ui/ai-section/AiPricingCardOverlay.tsx
|
|
18401
18701
|
var import_react11 = require("react");
|
|
18402
18702
|
var import_lucide_react9 = require("lucide-react");
|
|
18403
|
-
|
|
18404
|
-
// src/lib/ai-pricing-tree.ts
|
|
18405
|
-
var PRICING_MIN_CARDS = 1;
|
|
18406
|
-
var PRICING_MAX_CARDS = 4;
|
|
18407
|
-
function isPricingCard(node) {
|
|
18408
|
-
return typeof node === "object" && node !== null && node.type === "card" && node.slots?.preset === "pricing";
|
|
18409
|
-
}
|
|
18410
|
-
function isPricingCollection(node) {
|
|
18411
|
-
return node.type === "collection" && Array.isArray(node.children) && node.children.length > 0 && isPricingCard(node.children[0]);
|
|
18412
|
-
}
|
|
18413
|
-
function findCollection(node) {
|
|
18414
|
-
if (isPricingCollection(node)) return node;
|
|
18415
|
-
for (const child of node.children ?? []) {
|
|
18416
|
-
const found = findCollection(child);
|
|
18417
|
-
if (found) return found;
|
|
18418
|
-
}
|
|
18419
|
-
return null;
|
|
18420
|
-
}
|
|
18421
|
-
function findPricingCollection(tree) {
|
|
18422
|
-
for (const row of tree.rows ?? []) {
|
|
18423
|
-
for (const block of row.blocks ?? []) {
|
|
18424
|
-
const found = findCollection(block);
|
|
18425
|
-
if (found) return found;
|
|
18426
|
-
}
|
|
18427
|
-
}
|
|
18428
|
-
return null;
|
|
18429
|
-
}
|
|
18430
|
-
function pricingCardCount(tree) {
|
|
18431
|
-
return findPricingCollection(tree)?.children?.length ?? 0;
|
|
18432
|
-
}
|
|
18433
|
-
function withPricingCollection(tree, mutate) {
|
|
18434
|
-
const next = JSON.parse(JSON.stringify(tree));
|
|
18435
|
-
const collection = findPricingCollection(next);
|
|
18436
|
-
if (!collection || !collection.children) return null;
|
|
18437
|
-
for (const card of collection.children) {
|
|
18438
|
-
if (isPricingCard(card)) upgradeLegacyPricingSlots(card);
|
|
18439
|
-
}
|
|
18440
|
-
return mutate(collection) ? next : null;
|
|
18441
|
-
}
|
|
18442
|
-
function upgradeLegacyPricingSlots(card) {
|
|
18443
|
-
const slots = card.slots = card.slots ?? {};
|
|
18444
|
-
if (typeof slots.features === "string") {
|
|
18445
|
-
const rows = pricingFeatureList(card);
|
|
18446
|
-
if (rows.length > 0) slots.features = rows.slice(0, PRICING_FEATURES_MAX);
|
|
18447
|
-
}
|
|
18448
|
-
if (slots.featured === true) slots.featured = { enabled: true };
|
|
18449
|
-
else if (slots.featured === false) delete slots.featured;
|
|
18450
|
-
}
|
|
18451
|
-
function addPricingTier(tree) {
|
|
18452
|
-
return withPricingCollection(tree, (collection) => {
|
|
18453
|
-
const children = collection.children;
|
|
18454
|
-
if (children.length >= PRICING_MAX_CARDS) return false;
|
|
18455
|
-
const clone = JSON.parse(JSON.stringify(children[children.length - 1]));
|
|
18456
|
-
clone.slots = clone.slots ?? {};
|
|
18457
|
-
delete clone.slots.featured;
|
|
18458
|
-
clone.slots.heading = "New tier";
|
|
18459
|
-
children.push(clone);
|
|
18460
|
-
collection.slots = { ...collection.slots, itemsPerRow: children.length };
|
|
18461
|
-
return true;
|
|
18462
|
-
});
|
|
18463
|
-
}
|
|
18464
|
-
function removePricingTier(tree, index) {
|
|
18465
|
-
return withPricingCollection(tree, (collection) => {
|
|
18466
|
-
const children = collection.children;
|
|
18467
|
-
if (children.length <= PRICING_MIN_CARDS) return false;
|
|
18468
|
-
if (index < 0 || index >= children.length) return false;
|
|
18469
|
-
children.splice(index, 1);
|
|
18470
|
-
collection.slots = { ...collection.slots, itemsPerRow: children.length };
|
|
18471
|
-
return true;
|
|
18472
|
-
});
|
|
18473
|
-
}
|
|
18474
|
-
var PRICING_CARD_STYLES = [
|
|
18475
|
-
{ value: "outline", label: "Outline", treatment: null },
|
|
18476
|
-
{ value: "lift", label: "Lift", treatment: "lifted" },
|
|
18477
|
-
{ value: "invert", label: "Invert", treatment: "inverted" },
|
|
18478
|
-
{ value: "header", label: "Header", treatment: "accent-header" }
|
|
18479
|
-
];
|
|
18480
|
-
var DEFAULT_FEATURED_BADGE = "Most popular";
|
|
18481
|
-
function featuredOf(target) {
|
|
18482
|
-
const raw = target?.slots?.featured;
|
|
18483
|
-
if (raw === true) return { enabled: true, treatment: "outlined" };
|
|
18484
|
-
return typeof raw === "object" && raw !== null ? raw : {};
|
|
18485
|
-
}
|
|
18486
|
-
function badgeOf(featured) {
|
|
18487
|
-
return typeof featured.badge === "string" ? featured.badge.trim() : "";
|
|
18488
|
-
}
|
|
18489
|
-
function pricingCardStyle(tree, index) {
|
|
18490
|
-
const featured = featuredOf(findPricingCollection(tree)?.children?.[index]);
|
|
18491
|
-
if (featured.enabled !== true) return "outline";
|
|
18492
|
-
return PRICING_CARD_STYLES.find((s) => s.treatment === featured.treatment)?.value ?? "outline";
|
|
18493
|
-
}
|
|
18494
|
-
function pricingCardFeaturedTag(tree, index) {
|
|
18495
|
-
const featured = featuredOf(findPricingCollection(tree)?.children?.[index]);
|
|
18496
|
-
return featured.enabled === true && badgeOf(featured).length > 0;
|
|
18497
|
-
}
|
|
18498
|
-
function composeFeatured(style, tagOn, badgeText) {
|
|
18499
|
-
const treatment = PRICING_CARD_STYLES.find((s) => s.value === style)?.treatment ?? null;
|
|
18500
|
-
if (tagOn) return { enabled: true, badge: badgeText || DEFAULT_FEATURED_BADGE, treatment: treatment ?? "outlined" };
|
|
18501
|
-
if (treatment) return { enabled: true, treatment };
|
|
18502
|
-
return badgeText.length > 0 ? { enabled: false, badge: badgeText } : { enabled: false };
|
|
18503
|
-
}
|
|
18504
|
-
function withPricingCard(tree, index, mutate) {
|
|
18505
|
-
return withPricingCollection(tree, (collection) => {
|
|
18506
|
-
const children = collection.children;
|
|
18507
|
-
if (index < 0 || index >= children.length) return false;
|
|
18508
|
-
const target = children[index];
|
|
18509
|
-
target.slots = target.slots ?? {};
|
|
18510
|
-
mutate(target);
|
|
18511
|
-
return true;
|
|
18512
|
-
});
|
|
18513
|
-
}
|
|
18514
|
-
function setPricingCardStyle(tree, index, style) {
|
|
18515
|
-
if (!PRICING_CARD_STYLES.some((s) => s.value === style)) return null;
|
|
18516
|
-
return withPricingCard(tree, index, (target) => {
|
|
18517
|
-
const prev = featuredOf(target);
|
|
18518
|
-
const tagOn = prev.enabled === true && badgeOf(prev).length > 0;
|
|
18519
|
-
target.slots.featured = composeFeatured(style, tagOn, badgeOf(prev));
|
|
18520
|
-
});
|
|
18521
|
-
}
|
|
18522
|
-
function setPricingCardFeaturedTag(tree, index, on) {
|
|
18523
|
-
return withPricingCollection(tree, (collection) => {
|
|
18524
|
-
const children = collection.children;
|
|
18525
|
-
if (index < 0 || index >= children.length) return false;
|
|
18526
|
-
if (on) {
|
|
18527
|
-
children.forEach((card, i) => {
|
|
18528
|
-
if (i === index) return;
|
|
18529
|
-
const prev2 = featuredOf(card);
|
|
18530
|
-
if (prev2.enabled !== true || badgeOf(prev2).length === 0) return;
|
|
18531
|
-
card.slots = card.slots ?? {};
|
|
18532
|
-
card.slots.featured = composeFeatured(pricingCardStyleOf(prev2), false, badgeOf(prev2));
|
|
18533
|
-
});
|
|
18534
|
-
}
|
|
18535
|
-
const target = children[index];
|
|
18536
|
-
target.slots = target.slots ?? {};
|
|
18537
|
-
const prev = featuredOf(target);
|
|
18538
|
-
target.slots.featured = composeFeatured(pricingCardStyleOf(prev), on, badgeOf(prev));
|
|
18539
|
-
return true;
|
|
18540
|
-
});
|
|
18541
|
-
}
|
|
18542
|
-
function pricingCardStyleOf(featured) {
|
|
18543
|
-
if (featured.enabled !== true) return "outline";
|
|
18544
|
-
return PRICING_CARD_STYLES.find((s) => s.treatment === featured.treatment)?.value ?? "outline";
|
|
18545
|
-
}
|
|
18546
|
-
function addPricingCardButton(tree, index, label) {
|
|
18547
|
-
return withPricingCollection(tree, (collection) => {
|
|
18548
|
-
const children = collection.children;
|
|
18549
|
-
if (index < 0 || index >= children.length) return false;
|
|
18550
|
-
const target = children[index];
|
|
18551
|
-
const buttons = (target.children ?? []).filter((c) => c.type === "button");
|
|
18552
|
-
if (buttons.length >= 2) return false;
|
|
18553
|
-
const hasPrimary = buttons.some((b) => b.slots?.variant === "primary");
|
|
18554
|
-
target.children = [
|
|
18555
|
-
...target.children ?? [],
|
|
18556
|
-
{ type: "button", span: 12, slots: { label, href: "#", variant: hasPrimary ? "secondary" : "primary" } }
|
|
18557
|
-
];
|
|
18558
|
-
return true;
|
|
18559
|
-
});
|
|
18560
|
-
}
|
|
18561
|
-
function removePricingCardButton(tree, index) {
|
|
18562
|
-
return withPricingCollection(tree, (collection) => {
|
|
18563
|
-
const children = collection.children;
|
|
18564
|
-
if (index < 0 || index >= children.length) return false;
|
|
18565
|
-
const target = children[index];
|
|
18566
|
-
const buttons = (target.children ?? []).filter((c) => c.type === "button");
|
|
18567
|
-
if (buttons.length === 0) return false;
|
|
18568
|
-
const lastButton = buttons[buttons.length - 1];
|
|
18569
|
-
target.children = (target.children ?? []).filter((c) => c !== lastButton);
|
|
18570
|
-
return true;
|
|
18571
|
-
});
|
|
18572
|
-
}
|
|
18573
|
-
var PRICING_FEATURES_MIN = 1;
|
|
18574
|
-
var PRICING_FEATURES_MAX = 10;
|
|
18575
|
-
function pricingFeatureList(target) {
|
|
18576
|
-
const raw = target.slots?.features;
|
|
18577
|
-
if (Array.isArray(raw)) {
|
|
18578
|
-
return raw.filter((item) => !!item && typeof item === "object" && typeof item.text === "string").map((item) => ({
|
|
18579
|
-
text: item.text,
|
|
18580
|
-
...typeof item.icon === "string" ? { icon: item.icon } : {},
|
|
18581
|
-
...typeof item.iconColor === "string" ? { iconColor: item.iconColor } : {}
|
|
18582
|
-
}));
|
|
18583
|
-
}
|
|
18584
|
-
if (typeof raw === "string") {
|
|
18585
|
-
return raw.split(/\n|<br\s*\/?>/i).map((line) => line.replace(/<[^>]+>/g, "").replace(/^[-*•]\s*/, "").trim().slice(0, 120)).filter(Boolean).map((text) => ({ text }));
|
|
18586
|
-
}
|
|
18587
|
-
return [];
|
|
18588
|
-
}
|
|
18589
|
-
function pricingCardFeatureCount(tree, index) {
|
|
18590
|
-
const target = findPricingCollection(tree)?.children?.[index];
|
|
18591
|
-
return target ? pricingFeatureList(target).length : 0;
|
|
18592
|
-
}
|
|
18593
|
-
function addPricingCardFeature(tree, index, text) {
|
|
18594
|
-
return withPricingCollection(tree, (collection) => {
|
|
18595
|
-
const children = collection.children;
|
|
18596
|
-
if (index < 0 || index >= children.length) return false;
|
|
18597
|
-
const target = children[index];
|
|
18598
|
-
const features = pricingFeatureList(target);
|
|
18599
|
-
if (features.length >= PRICING_FEATURES_MAX) return false;
|
|
18600
|
-
target.slots = target.slots ?? {};
|
|
18601
|
-
target.slots.features = [...features, { text }];
|
|
18602
|
-
return true;
|
|
18603
|
-
});
|
|
18604
|
-
}
|
|
18605
|
-
function removePricingCardFeature(tree, index) {
|
|
18606
|
-
return withPricingCollection(tree, (collection) => {
|
|
18607
|
-
const children = collection.children;
|
|
18608
|
-
if (index < 0 || index >= children.length) return false;
|
|
18609
|
-
const target = children[index];
|
|
18610
|
-
const features = pricingFeatureList(target);
|
|
18611
|
-
if (features.length <= PRICING_FEATURES_MIN) return false;
|
|
18612
|
-
target.slots = target.slots ?? {};
|
|
18613
|
-
target.slots.features = features.slice(0, -1);
|
|
18614
|
-
return true;
|
|
18615
|
-
});
|
|
18616
|
-
}
|
|
18617
|
-
|
|
18618
|
-
// src/ui/ai-section/AiPricingCardOverlay.tsx
|
|
18619
18703
|
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
18620
18704
|
var PRIMARY4 = "var(--ohw-primary, #0885FE)";
|
|
18621
18705
|
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]";
|
|
@@ -23741,6 +23825,23 @@ function currentIconRef(el) {
|
|
|
23741
23825
|
);
|
|
23742
23826
|
return named ? `lucide:${named.slice("lucide-".length)}` : "";
|
|
23743
23827
|
}
|
|
23828
|
+
function requestValidateTree5(postToParent2, tree) {
|
|
23829
|
+
return new Promise((resolve) => {
|
|
23830
|
+
const id = `ai-validate-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
23831
|
+
const timeout = window.setTimeout(() => {
|
|
23832
|
+
window.removeEventListener("message", onMessage);
|
|
23833
|
+
resolve({ ok: false, reasons: ["Validation request timed out."] });
|
|
23834
|
+
}, 8e3);
|
|
23835
|
+
function onMessage(e) {
|
|
23836
|
+
if (e.data?.type !== "ow:ai-validate-tree-result" || e.data.id !== id) return;
|
|
23837
|
+
window.clearTimeout(timeout);
|
|
23838
|
+
window.removeEventListener("message", onMessage);
|
|
23839
|
+
resolve({ ok: e.data.ok === true, reasons: Array.isArray(e.data.reasons) ? e.data.reasons : [] });
|
|
23840
|
+
}
|
|
23841
|
+
window.addEventListener("message", onMessage);
|
|
23842
|
+
postToParent2({ type: "ow:ai-validate-tree-request", id, tree });
|
|
23843
|
+
});
|
|
23844
|
+
}
|
|
23744
23845
|
function getEditMeasureEl(editable) {
|
|
23745
23846
|
return editable.closest("[data-ohw-href-key]") ?? editable;
|
|
23746
23847
|
}
|
|
@@ -28092,10 +28193,14 @@ function OhhwellsBridge() {
|
|
|
28092
28193
|
e.preventDefault();
|
|
28093
28194
|
e.stopPropagation();
|
|
28094
28195
|
aiSectionApiRef.current?.selectFromElement(editable);
|
|
28196
|
+
const aiIcon = editable.hasAttribute("data-ai-icon");
|
|
28197
|
+
const featureIcon = aiIcon && /\.features\.\d+\.icon$/.test(editable.dataset.ohwKey ?? "");
|
|
28095
28198
|
postToParentRef.current({
|
|
28096
28199
|
type: "ow:icon-pick",
|
|
28097
28200
|
key: editable.dataset.ohwKey ?? "",
|
|
28098
|
-
current: currentIconRef(editable)
|
|
28201
|
+
current: currentIconRef(editable),
|
|
28202
|
+
...aiIcon ? { iconMode: "name" } : {},
|
|
28203
|
+
...featureIcon ? { options: [...PRICING_FEATURE_ICONS] } : {}
|
|
28099
28204
|
});
|
|
28100
28205
|
return;
|
|
28101
28206
|
}
|
|
@@ -29342,15 +29447,43 @@ function OhhwellsBridge() {
|
|
|
29342
29447
|
if (e.data?.type !== "ow:icon-markup") return;
|
|
29343
29448
|
const { key, markup } = e.data;
|
|
29344
29449
|
if (!key || typeof markup !== "string") return;
|
|
29345
|
-
const targets =
|
|
29346
|
-
`[data-ohw-key="${key}"][data-ohw-editable="icon"]`
|
|
29347
|
-
);
|
|
29450
|
+
const targets = Array.from(
|
|
29451
|
+
document.querySelectorAll(`[data-ohw-key="${key}"][data-ohw-editable="icon"]`)
|
|
29452
|
+
).filter((el) => !el.hasAttribute("data-ai-icon"));
|
|
29348
29453
|
if (!targets.length) return;
|
|
29349
29454
|
targets.forEach((el) => {
|
|
29350
29455
|
applyIconMarkup(el, markup);
|
|
29351
29456
|
});
|
|
29352
29457
|
postToParentRef.current({ type: "ow:change", nodes: [{ key, text: markup }], flush: true });
|
|
29353
29458
|
};
|
|
29459
|
+
const handleIconName = (e) => {
|
|
29460
|
+
if (e.data?.type !== "ow:icon-name") return;
|
|
29461
|
+
const { key, icon, url } = e.data;
|
|
29462
|
+
const isName = typeof icon === "string" && /^[a-z0-9-]+$/.test(icon);
|
|
29463
|
+
const isUpload = !isName && typeof url === "string" && /^https?:\/\/\S+$/i.test(url);
|
|
29464
|
+
if (!key || !isName && !isUpload) return;
|
|
29465
|
+
const state = parseAiSectionsState(aiSectionsRef.current);
|
|
29466
|
+
const entry = state.sections.find((s) => key.startsWith(aiSlotKeyPrefixFor(s.id)));
|
|
29467
|
+
if (!entry) return;
|
|
29468
|
+
const path = key.slice(aiSlotKeyPrefixFor(entry.id).length);
|
|
29469
|
+
const uploadRef = isUpload ? `icon-${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}` : null;
|
|
29470
|
+
const nextTree = uploadRef ? applyIconUploadToTree(entry.tree, path, uploadRef) : applyIconNameToTree(entry.tree, path, icon);
|
|
29471
|
+
if (!nextTree) return;
|
|
29472
|
+
void requestValidateTree5(postToParentRef.current, nextTree).then(({ ok }) => {
|
|
29473
|
+
if (!ok) return;
|
|
29474
|
+
applyTreeLocalRef.current?.({
|
|
29475
|
+
id: entry.id,
|
|
29476
|
+
mode: "replace",
|
|
29477
|
+
targetSectionId: entry.id,
|
|
29478
|
+
tree: nextTree,
|
|
29479
|
+
label: entry.label,
|
|
29480
|
+
media: uploadRef ? { ...entry.media, [uploadRef]: url } : entry.media,
|
|
29481
|
+
...entry.brand ? { brand: entry.brand } : {},
|
|
29482
|
+
// The user is looking at the icon they just changed — no need to recenter on it.
|
|
29483
|
+
skipScrollIntoView: true
|
|
29484
|
+
});
|
|
29485
|
+
});
|
|
29486
|
+
};
|
|
29354
29487
|
const handleImageUrl = (e) => {
|
|
29355
29488
|
if (e.data?.type !== "ow:image-url") return;
|
|
29356
29489
|
const { key, url } = e.data;
|
|
@@ -30799,6 +30932,7 @@ function OhhwellsBridge() {
|
|
|
30799
30932
|
window.addEventListener("message", handleSocialCancel);
|
|
30800
30933
|
window.addEventListener("message", handleSocialUpdate);
|
|
30801
30934
|
window.addEventListener("message", handleIconMarkup);
|
|
30935
|
+
window.addEventListener("message", handleIconName);
|
|
30802
30936
|
window.addEventListener("message", handleImageUrl);
|
|
30803
30937
|
window.addEventListener("message", handleImageUploading);
|
|
30804
30938
|
window.addEventListener("message", handleCarouselChange);
|
|
@@ -30883,6 +31017,7 @@ function OhhwellsBridge() {
|
|
|
30883
31017
|
window.removeEventListener("message", handleSocialCancel);
|
|
30884
31018
|
window.removeEventListener("message", handleSocialUpdate);
|
|
30885
31019
|
window.removeEventListener("message", handleIconMarkup);
|
|
31020
|
+
window.removeEventListener("message", handleIconName);
|
|
30886
31021
|
window.removeEventListener("message", handleImageUrl);
|
|
30887
31022
|
window.removeEventListener("message", handleImageUploading);
|
|
30888
31023
|
window.removeEventListener("message", handleCarouselChange);
|
|
@@ -31208,7 +31343,7 @@ function OhhwellsBridge() {
|
|
|
31208
31343
|
postToParent2({
|
|
31209
31344
|
type: "ow:ready",
|
|
31210
31345
|
version: "1",
|
|
31211
|
-
bridgeVersion: "0.1.
|
|
31346
|
+
bridgeVersion: "0.1.142",
|
|
31212
31347
|
path: pathname,
|
|
31213
31348
|
nodes: collectEditableNodes(editContentRef.current),
|
|
31214
31349
|
sections
|