@ohhwells/bridge 0.1.140 → 0.1.141

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 CHANGED
@@ -72,6 +72,7 @@ __export(index_exports, {
72
72
  dropIndicatorVariants: () => dropIndicatorVariants,
73
73
  ensureFooterTree: () => ensureFooterTree,
74
74
  filterAvailablePages: () => filterAvailablePages,
75
+ foldAlignIntoTrees: () => foldAlignIntoTrees,
75
76
  getEditModeInitialState: () => getEditModeInitialState,
76
77
  insertFooterHours: () => insertFooterHours,
77
78
  isEditSessionActive: () => isEditSessionActive,
@@ -80,6 +81,7 @@ __export(index_exports, {
80
81
  isValidUrl: () => isValidUrl,
81
82
  nextViableSlide: () => nextViableSlide,
82
83
  parseAiFooterState: () => parseAiFooterState,
84
+ parseAiSectionsState: () => parseAiSectionsState,
83
85
  parseTarget: () => parseTarget,
84
86
  removeFooterBlock: () => removeFooterBlock,
85
87
  resolveFooterCopyright: () => resolveFooterCopyright,
@@ -5296,19 +5298,21 @@ function findIndexSegment(keys) {
5296
5298
  if (len < 2 || tokenLists.some((t) => t.length !== len)) return null;
5297
5299
  let position = -1;
5298
5300
  for (let p = 0; p < len; p++) {
5299
- const values = tokenLists.map((t) => t[p]);
5300
- const allSame = values.every((v) => v === values[0]);
5301
+ const values2 = tokenLists.map((t) => t[p]);
5302
+ const allSame = values2.every((v) => v === values2[0]);
5301
5303
  if (allSame) continue;
5302
- const allNumeric = values.every((v) => /^\d+$/.test(v));
5303
- if (!allNumeric || position !== -1) return null;
5304
+ if (position !== -1) return null;
5304
5305
  position = p;
5305
5306
  }
5306
5307
  if (position === -1) return null;
5308
+ const values = tokenLists.map((t) => t[position]);
5309
+ const numericCount = values.filter((v) => /^\d+$/.test(v)).length;
5310
+ if (numericCount !== 0 && numericCount !== values.length) return null;
5311
+ if (numericCount === 0 && position === len - 1) return null;
5307
5312
  const group = tokenLists[0].slice(0, position).join("-");
5308
5313
  if (!group) return null;
5309
- const indices = tokenLists.map((t) => parseInt(t[position], 10));
5310
- if (new Set(indices).size !== indices.length) return null;
5311
- return { position, group };
5314
+ if (new Set(values).size !== values.length) return null;
5315
+ return numericCount === values.length ? { position, group } : { position, group, slug: true };
5312
5316
  }
5313
5317
  function singleIndexSegment(key) {
5314
5318
  const tokens = baseKey(key).split("-");
@@ -5354,7 +5358,19 @@ function detectItemGroups(sectionEl) {
5354
5358
  list.push(m);
5355
5359
  byShape.set(shape, list);
5356
5360
  }
5357
- clusters.push(...Array.from(byShape.values()));
5361
+ const shaped = Array.from(byShape.values());
5362
+ clusters.push(...shaped.filter((c) => c.length >= 2));
5363
+ const singles = shaped.filter((c) => c.length === 1).map((c) => c[0]);
5364
+ const bySlugShape = /* @__PURE__ */ new Map();
5365
+ for (const m of singles) {
5366
+ const primary = primaryKey(keyedDescendants(m));
5367
+ const tokens = baseKey(primary ?? "").split("-");
5368
+ const slugShape = `${tokens.length}|${tokens[0]}|${tokens[tokens.length - 1]}`;
5369
+ const list = bySlugShape.get(slugShape) ?? [];
5370
+ list.push(m);
5371
+ bySlugShape.set(slugShape, list);
5372
+ }
5373
+ clusters.push(...Array.from(bySlugShape.values()));
5358
5374
  }
5359
5375
  for (const members of clusters) {
5360
5376
  const keyedPerMember = members.map((m) => keyedDescendants(m));
@@ -5365,11 +5381,28 @@ function detectItemGroups(sectionEl) {
5365
5381
  const dedupeKey = `${segment.group}`;
5366
5382
  if (seenParents.has(dedupeKey)) continue;
5367
5383
  seenParents.add(dedupeKey);
5368
- const items = members.map((el, i) => ({
5369
- el,
5370
- index: indexFromKey(primaries[i], segment.position),
5371
- keyed: keyedPerMember[i]
5372
- }));
5384
+ let items;
5385
+ if (segment.slug) {
5386
+ const tokens = members.map((_, i) => baseKey(primaries[i]).split("-")[segment.position]);
5387
+ let nextOriginal = 1;
5388
+ const indices = tokens.map((t) => {
5389
+ const cloneMatch = t.match(/^x(\d+)$/);
5390
+ return cloneMatch ? parseInt(cloneMatch[1], 10) : nextOriginal++;
5391
+ });
5392
+ if (new Set(indices).size !== indices.length) continue;
5393
+ items = members.map((el, i) => ({
5394
+ el,
5395
+ index: indices[i],
5396
+ keyed: keyedPerMember[i],
5397
+ slugToken: tokens[i]
5398
+ }));
5399
+ } else {
5400
+ items = members.map((el, i) => ({
5401
+ el,
5402
+ index: indexFromKey(primaries[i], segment.position),
5403
+ keyed: keyedPerMember[i]
5404
+ }));
5405
+ }
5373
5406
  groups.push({ group: segment.group, parent, nested: false, items });
5374
5407
  }
5375
5408
  }
@@ -5493,6 +5526,18 @@ function rekeyItemClone(clone, source, sibling, group, newIndex) {
5493
5526
  const delta = newIndex - source.index;
5494
5527
  const cloneKeyed = keyedDescendants(clone);
5495
5528
  const pairs = [];
5529
+ if (source.slugToken) {
5530
+ source.keyed.forEach((src, i) => {
5531
+ const target = cloneKeyed[i];
5532
+ if (!target || target.attr !== src.attr) return;
5533
+ const tokens = baseKey(src.key).split("-");
5534
+ if (!tokens.includes(source.slugToken)) return;
5535
+ const next = tokens.map((t) => t === source.slugToken ? `x${newIndex}` : t).join("-") + keySuffix(src.key);
5536
+ target.el.setAttribute(src.attr, next);
5537
+ pairs.push({ from: src.key, to: next });
5538
+ });
5539
+ return pairs;
5540
+ }
5496
5541
  source.keyed.forEach((src, i) => {
5497
5542
  const target = cloneKeyed[i];
5498
5543
  if (!target || target.attr !== src.attr) return;
@@ -5536,7 +5581,12 @@ function syncGroup(detected, state) {
5536
5581
  clone.setAttribute(ITEM_ATTR, `${detected.group}:${entry.index}`);
5537
5582
  rekeyItemClone(clone, source, sibling, detected.group, entry.index);
5538
5583
  source.el.insertAdjacentElement("afterend", clone);
5539
- byIndex.set(entry.index, { el: clone, index: entry.index, keyed: keyedDescendants(clone) });
5584
+ byIndex.set(entry.index, {
5585
+ el: clone,
5586
+ index: entry.index,
5587
+ keyed: keyedDescendants(clone),
5588
+ ...source.slugToken ? { slugToken: `x${entry.index}` } : {}
5589
+ });
5540
5590
  }
5541
5591
  const listed = state.items.map((e) => byIndex.get(e.index)?.el).filter((el) => !!el);
5542
5592
  let prev = null;
@@ -5638,9 +5688,16 @@ function applyItemOps(store, ops, currentContent) {
5638
5688
  const nodes = [];
5639
5689
  const added = [];
5640
5690
  let elements = syncGroup(detected, state);
5691
+ const sluggy = detected.items.some((item) => item.slugToken);
5692
+ const slugTokenOf = (index) => detected.items.find((item) => item.index === index)?.slugToken ?? (sluggy ? `x${index}` : void 0);
5641
5693
  for (const add of ops.add ?? []) {
5642
5694
  const sourceEl = elements.get(add.cloneOf);
5643
- const source = sourceEl ? { el: sourceEl, index: add.cloneOf, keyed: keyedDescendants(sourceEl) } : void 0;
5695
+ const source = sourceEl ? {
5696
+ el: sourceEl,
5697
+ index: add.cloneOf,
5698
+ keyed: keyedDescendants(sourceEl),
5699
+ ...slugTokenOf(add.cloneOf) ? { slugToken: slugTokenOf(add.cloneOf) } : {}
5700
+ } : void 0;
5644
5701
  if (!source) continue;
5645
5702
  const newIndex = Math.max(...state.items.map((e) => e.index), ...detected.items.map((i) => i.index)) + 1;
5646
5703
  const sibling = detected.items.find((item) => item.index !== add.cloneOf && !item.el.hasAttribute(ITEM_CLONE_ATTR)) ?? null;
@@ -5667,7 +5724,12 @@ function applyItemOps(store, ops, currentContent) {
5667
5724
  if (anchor) anchor.insertAdjacentElement("afterend", clone);
5668
5725
  else source.el.insertAdjacentElement("afterend", clone);
5669
5726
  elements.set(newIndex, clone);
5670
- detected.items.push({ el: clone, index: newIndex, keyed: cloneKeyed });
5727
+ detected.items.push({
5728
+ el: clone,
5729
+ index: newIndex,
5730
+ keyed: cloneKeyed,
5731
+ ...sluggy ? { slugToken: `x${newIndex}` } : {}
5732
+ });
5671
5733
  added.push(newIndex);
5672
5734
  elements = syncGroup(detected, state);
5673
5735
  }
@@ -6110,16 +6172,25 @@ function foldAlignIntoTrees(state, store) {
6110
6172
  nextTrees.set(id, fresh);
6111
6173
  return fresh;
6112
6174
  };
6175
+ const stripChildAligns = (node) => node.children ? {
6176
+ ...node,
6177
+ children: node.children.map((child) => {
6178
+ const { align: _dropped, ...rest } = child;
6179
+ return stripChildAligns(rest);
6180
+ })
6181
+ } : node;
6113
6182
  const nodes = {};
6114
6183
  for (const [key, override] of Object.entries(store.nodes)) {
6115
6184
  const match = override.align !== void 0 && key.startsWith(AI_SLOT_KEY_PREFIX) ? key.match(/^ai\.(.+?)\.r(\d+)\.b(\d+)(?:\.|$)/) : null;
6116
6185
  const tree = match ? treeFor(match[1]) : void 0;
6117
- const block = match && tree ? tree.rows[Number(match[2])]?.blocks[Number(match[3])] : void 0;
6118
- if (!block) {
6186
+ const row = match && tree ? tree.rows[Number(match[2])] : void 0;
6187
+ const blockIdx = match ? Number(match[3]) : -1;
6188
+ const block = row?.blocks[blockIdx];
6189
+ if (!row || !block) {
6119
6190
  nodes[key] = override;
6120
6191
  continue;
6121
6192
  }
6122
- block.align = override.align;
6193
+ row.blocks[blockIdx] = { ...stripChildAligns(block), align: override.align };
6123
6194
  const rest = { ...override };
6124
6195
  delete rest.align;
6125
6196
  if (Object.keys(rest).length > 0) nodes[key] = rest;
@@ -6132,7 +6203,7 @@ function foldAlignIntoTrees(state, store) {
6132
6203
  continue;
6133
6204
  }
6134
6205
  for (const row of tree.rows) {
6135
- for (const block of row.blocks) block.align = override.align;
6206
+ row.blocks = row.blocks.map((block) => ({ ...stripChildAligns(block), align: override.align }));
6136
6207
  }
6137
6208
  const rest = { ...override };
6138
6209
  delete rest.align;
@@ -7293,6 +7364,7 @@ var blockAlignStyle = (blockAlign) => blockAlign ? {
7293
7364
  alignItems: blockAlign === "left" ? "flex-start" : blockAlign === "right" ? "flex-end" : "center",
7294
7365
  textAlign: blockAlign
7295
7366
  } : {};
7367
+ var fullBleedBlock = (block) => block.type === "carousel" || block.type === "group" && str(block.slots?.layout) === "overlap";
7296
7368
  var featureLines = (value) => value.split(/\n|<br\s*\/?>/i).map((line) => line.trim()).filter(Boolean);
7297
7369
  var AI_MOBILE_CSS = [
7298
7370
  // Unscoped (applies at every viewport, not just mobile): re-enables pointer-events for the
@@ -9358,8 +9430,8 @@ function renderNode(node, ctx, path, ambientAlign) {
9358
9430
  // layer (this group's i===0 sibling) can span edge-to-edge — reintroduced here,
9359
9431
  // scoped to just the overlay text, so a heading/copy/CTA stack doesn't stretch
9360
9432
  // the full section width instead of reading at the usual content width.
9361
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { maxWidth: AI_TREE_TOKENS.sectionMaxWidth, margin: "0 auto", padding: "0 40px", width: "100%", boxSizing: "border-box" }, children: renderNode(child, ctx, `${path}.c${i}`, child.align ?? "center") })
9362
- ) : renderNode(child, ctx, `${path}.c${i}`, i > 0 ? child.align ?? "center" : void 0),
9433
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { maxWidth: AI_TREE_TOKENS.sectionMaxWidth, margin: "0 auto", padding: "0 40px", width: "100%", boxSizing: "border-box" }, children: renderNode(child, ctx, `${path}.c${i}`, child.align ?? node.align ?? "center") })
9434
+ ) : renderNode(child, ctx, `${path}.c${i}`, i > 0 ? child.align ?? node.align ?? "center" : void 0),
9363
9435
  i === 0 && needsBaseScrim && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
9364
9436
  "div",
9365
9437
  {
@@ -9392,7 +9464,7 @@ function renderNode(node, ctx, path, ambientAlign) {
9392
9464
  // child otherwise stretches full-width (unchanged pre-existing behaviour).
9393
9465
  ...blockAlignStyle(child.align ?? ambientAlign)
9394
9466
  },
9395
- children: renderNode(child, ctx, `${path}.c${i}`, ambientAlign)
9467
+ children: renderNode(child, ctx, `${path}.c${i}`, node.align ?? ambientAlign)
9396
9468
  },
9397
9469
  i
9398
9470
  ));
@@ -9422,8 +9494,20 @@ function renderNode(node, ctx, path, ambientAlign) {
9422
9494
  }
9423
9495
  case "button":
9424
9496
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ButtonEl, { slots, ctx, path });
9425
- case "button-row":
9426
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", gap: AI_TREE_TOKENS.spacing6, justifyContent: "center" }, children: (node.children ?? []).map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ButtonEl, { slots: child.slots ?? {}, ctx, path: `${path}.c${i}` }, i)) });
9497
+ case "button-row": {
9498
+ const rowAlign = node.align ?? ambientAlign;
9499
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
9500
+ "div",
9501
+ {
9502
+ style: {
9503
+ display: "flex",
9504
+ gap: AI_TREE_TOKENS.spacing6,
9505
+ justifyContent: rowAlign === "left" ? "flex-start" : rowAlign === "right" ? "flex-end" : "center"
9506
+ },
9507
+ children: (node.children ?? []).map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ButtonEl, { slots: child.slots ?? {}, ctx, path: `${path}.c${i}` }, i))
9508
+ }
9509
+ );
9510
+ }
9427
9511
  case "media":
9428
9512
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
9429
9513
  MediaBox,
@@ -9802,7 +9886,7 @@ function AiTreeRenderer({
9802
9886
  // its own horizontal `align`, which takes priority for that block.
9803
9887
  ...fillHeight ? { display: "grid" } : {},
9804
9888
  // Horizontal placement of the block's content within its column.
9805
- ...cellAlignStyle(block.align),
9889
+ ...fullBleedBlock(block) ? {} : cellAlignStyle(block.align),
9806
9890
  // space-between: each column becomes a flex column whose content spreads over
9807
9891
  // the full row height instead of clumping at the top.
9808
9892
  ...distributed === "space-between" ? { display: "flex", flexDirection: "column", justifyContent: "space-between" } : {}
@@ -18436,10 +18520,23 @@ function setPricingCardStyle(tree, index, style) {
18436
18520
  });
18437
18521
  }
18438
18522
  function setPricingCardFeaturedTag(tree, index, on) {
18439
- return withPricingCard(tree, index, (target) => {
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 ?? {};
18440
18537
  const prev = featuredOf(target);
18441
- const style = pricingCardStyleOf(prev);
18442
- target.slots.featured = composeFeatured(style, on, badgeOf(prev));
18538
+ target.slots.featured = composeFeatured(pricingCardStyleOf(prev), on, badgeOf(prev));
18539
+ return true;
18443
18540
  });
18444
18541
  }
18445
18542
  function pricingCardStyleOf(featured) {
@@ -18689,25 +18786,40 @@ function ToolbarSeparator() {
18689
18786
  }
18690
18787
  function CardStyleMenu({
18691
18788
  value,
18692
- onChange
18789
+ onChange,
18790
+ disabled = false
18693
18791
  }) {
18694
18792
  const current = PRICING_CARD_STYLES.find((s) => s.value === value) ?? PRICING_CARD_STYLES[0];
18793
+ const trigger = /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
18794
+ "button",
18795
+ {
18796
+ type: "button",
18797
+ "aria-label": "Card style",
18798
+ disabled,
18799
+ className: cn(
18800
+ "inline-flex h-8 min-w-[110px] items-center gap-[7px] rounded-[6px] bg-transparent px-2 text-[13px] font-medium text-foreground transition-colors hover:bg-muted data-[state=open]:bg-muted",
18801
+ disabled && "cursor-not-allowed opacity-40 hover:bg-transparent"
18802
+ ),
18803
+ children: [
18804
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(StyleSwatch, { style: current.value }),
18805
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "flex-1 text-left", children: current.label }),
18806
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.ChevronDown, { size: 16, style: { pointerEvents: "none" } })
18807
+ ]
18808
+ }
18809
+ );
18810
+ if (disabled) {
18811
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
18812
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "text-xs text-muted-foreground opacity-50", children: "Card style" }),
18813
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Tooltip, { children: [
18814
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "inline-flex", children: trigger }) }),
18815
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: "Mark as featured to edit card style" })
18816
+ ] })
18817
+ ] });
18818
+ }
18695
18819
  return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
18696
18820
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "text-xs text-muted-foreground", children: "Card style" }),
18697
18821
  /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(DropdownMenu, { modal: false, children: [
18698
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
18699
- "button",
18700
- {
18701
- type: "button",
18702
- "aria-label": "Card style",
18703
- className: "inline-flex h-8 min-w-[110px] items-center gap-[7px] rounded-[6px] bg-transparent px-2 text-[13px] font-medium text-foreground transition-colors hover:bg-muted data-[state=open]:bg-muted",
18704
- children: [
18705
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(StyleSwatch, { style: current.value }),
18706
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "flex-1 text-left", children: current.label }),
18707
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.ChevronDown, { size: 16, style: { pointerEvents: "none" } })
18708
- ]
18709
- }
18710
- ) }),
18822
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DropdownMenuTrigger, { asChild: true, children: trigger }),
18711
18823
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DropdownMenuContent, { align: "end", sideOffset: 8, className: "w-[152px] min-w-[152px] p-1", children: PRICING_CARD_STYLES.map((style) => {
18712
18824
  const selected = style.value === value;
18713
18825
  return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
@@ -18771,23 +18883,35 @@ function PricingCardToolbar({
18771
18883
  mobile ? "flex-wrap justify-center" : "flex-nowrap"
18772
18884
  ),
18773
18885
  children: [
18774
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(CardStyleMenu, { value: style, onChange: onSetStyle }),
18775
18886
  /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Tooltip, { children: [
18776
18887
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
18777
18888
  CustomToolbarButton,
18778
18889
  {
18779
18890
  type: "button",
18780
- "aria-label": featuredTag ? "Remove featured tag" : "Add featured tag",
18891
+ "aria-label": featuredTag ? "Unmark as featured" : "Mark as featured",
18781
18892
  "aria-pressed": featuredTag,
18782
- active: featuredTag,
18783
18893
  onClick: () => onSetFeaturedTag(!featuredTag),
18784
- className: "size-8",
18785
- children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.Star, { size: 16, fill: featuredTag ? "currentColor" : "none", style: { pointerEvents: "none" } })
18894
+ className: "group size-8",
18895
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
18896
+ import_lucide_react9.Star,
18897
+ {
18898
+ size: 16,
18899
+ fill: "currentColor",
18900
+ strokeWidth: 0,
18901
+ className: cn(
18902
+ "transition-colors",
18903
+ featuredTag ? "text-[#f59e0b] group-hover:text-[#d97706]" : "text-[#d6d3d1] group-hover:text-[#fbbf24]"
18904
+ ),
18905
+ style: { pointerEvents: "none" }
18906
+ }
18907
+ )
18786
18908
  }
18787
18909
  ) }),
18788
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: featuredTag ? "Remove featured tag" : "Add featured tag" })
18910
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: featuredTag ? "Unmark featured" : "Mark as featured" })
18789
18911
  ] }),
18790
18912
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarSeparator, {}),
18913
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(CardStyleMenu, { value: style, onChange: onSetStyle, disabled: !featuredTag }),
18914
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarSeparator, {}),
18791
18915
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarAction, { label: "Add button", onClick: onAddButton, disabled: buttonCount >= 2, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ButtonGlyph, {}) }),
18792
18916
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarAction, { label: "Remove button", onClick: onRemoveButton, disabled: buttonCount === 0, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "relative inline-flex", children: [
18793
18917
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ButtonGlyph, {}),
@@ -18930,7 +19054,12 @@ function AiPricingCardOverlay({
18930
19054
  index: active.index,
18931
19055
  pending,
18932
19056
  error,
18933
- onAddTier: () => runMutation(active.sectionId, addPricingTier),
19057
+ onAddTier: () => {
19058
+ const newIndex = pricingCardCount(activeEntry.tree);
19059
+ void runMutation(active.sectionId, addPricingTier).then((applied) => {
19060
+ if (applied) setActive({ sectionId: active.sectionId, index: newIndex });
19061
+ });
19062
+ },
18934
19063
  onRemoveTier: () => {
18935
19064
  void runMutation(active.sectionId, (tree) => removePricingTier(tree, active.index)).then(
18936
19065
  (applied) => {
@@ -30337,9 +30466,10 @@ function OhhwellsBridge() {
30337
30466
  if (e.data?.type !== "ow:collect-section") return;
30338
30467
  const sectionId = e.data.sectionId;
30339
30468
  if (typeof sectionId !== "string" || !sectionId) return;
30340
- const sectionEl = document.querySelector(
30469
+ const foundEl = document.querySelector(
30341
30470
  `[data-ohw-section="${CSS.escape(sectionId)}"]`
30342
30471
  );
30472
+ const sectionEl = foundEl && !foundEl.hasAttribute("data-ohw-ai-template-hidden") && !foundEl.hasAttribute("data-ohw-ai-removed") && !foundEl.hasAttribute("data-ohw-ai-replaced-by") ? foundEl : null;
30343
30473
  const nodes = sectionEl ? collectEditableNodes(void 0, sectionEl).filter(
30344
30474
  (n) => n.key && !n.key.startsWith("__ohw_") && !["meta", "sections", "video-setting"].includes(n.type)
30345
30475
  ).map((n) => ({ ...n, text: n.text ?? "", type: normalizeAiNodeType(n.type) })) : [];
@@ -31078,7 +31208,7 @@ function OhhwellsBridge() {
31078
31208
  postToParent2({
31079
31209
  type: "ow:ready",
31080
31210
  version: "1",
31081
- bridgeVersion: "0.1.139",
31211
+ bridgeVersion: "0.1.140",
31082
31212
  path: pathname,
31083
31213
  nodes: collectEditableNodes(editContentRef.current),
31084
31214
  sections
@@ -32294,6 +32424,7 @@ function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey
32294
32424
  dropIndicatorVariants,
32295
32425
  ensureFooterTree,
32296
32426
  filterAvailablePages,
32427
+ foldAlignIntoTrees,
32297
32428
  getEditModeInitialState,
32298
32429
  insertFooterHours,
32299
32430
  isEditSessionActive,
@@ -32302,6 +32433,7 @@ function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey
32302
32433
  isValidUrl,
32303
32434
  nextViableSlide,
32304
32435
  parseAiFooterState,
32436
+ parseAiSectionsState,
32305
32437
  parseTarget,
32306
32438
  removeFooterBlock,
32307
32439
  resolveFooterCopyright,