@ohhwells/bridge 0.1.139-next.374 → 0.1.139-next.375

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
@@ -9386,8 +9458,8 @@ function renderNode(node, ctx, path, ambientAlign) {
9386
9458
  // layer (this group's i===0 sibling) can span edge-to-edge — reintroduced here,
9387
9459
  // scoped to just the overlay text, so a heading/copy/CTA stack doesn't stretch
9388
9460
  // the full section width instead of reading at the usual content width.
9389
- /* @__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") })
9390
- ) : renderNode(child, ctx, `${path}.c${i}`, i > 0 ? child.align ?? "center" : void 0),
9461
+ /* @__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") })
9462
+ ) : renderNode(child, ctx, `${path}.c${i}`, i > 0 ? child.align ?? node.align ?? "center" : void 0),
9391
9463
  i === 0 && needsBaseScrim && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
9392
9464
  "div",
9393
9465
  {
@@ -9420,7 +9492,7 @@ function renderNode(node, ctx, path, ambientAlign) {
9420
9492
  // child otherwise stretches full-width (unchanged pre-existing behaviour).
9421
9493
  ...blockAlignStyle(child.align ?? ambientAlign)
9422
9494
  },
9423
- children: renderNode(child, ctx, `${path}.c${i}`, ambientAlign)
9495
+ children: renderNode(child, ctx, `${path}.c${i}`, node.align ?? ambientAlign)
9424
9496
  },
9425
9497
  i
9426
9498
  ));
@@ -9450,8 +9522,20 @@ function renderNode(node, ctx, path, ambientAlign) {
9450
9522
  }
9451
9523
  case "button":
9452
9524
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ButtonEl, { slots, ctx, path });
9453
- case "button-row":
9454
- 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)) });
9525
+ case "button-row": {
9526
+ const rowAlign = node.align ?? ambientAlign;
9527
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
9528
+ "div",
9529
+ {
9530
+ style: {
9531
+ display: "flex",
9532
+ gap: AI_TREE_TOKENS.spacing6,
9533
+ justifyContent: rowAlign === "left" ? "flex-start" : rowAlign === "right" ? "flex-end" : "center"
9534
+ },
9535
+ children: (node.children ?? []).map((child, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ButtonEl, { slots: child.slots ?? {}, ctx, path: `${path}.c${i}` }, i))
9536
+ }
9537
+ );
9538
+ }
9455
9539
  case "media":
9456
9540
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
9457
9541
  MediaBox,
@@ -9832,7 +9916,7 @@ function AiTreeRenderer({
9832
9916
  // its own horizontal `align`, which takes priority for that block.
9833
9917
  ...fillHeight ? { display: "grid" } : {},
9834
9918
  // Horizontal placement of the block's content within its column.
9835
- ...cellAlignStyle(block.align),
9919
+ ...fullBleedBlock(block) ? {} : cellAlignStyle(block.align),
9836
9920
  // space-between: each column becomes a flex column whose content spreads over
9837
9921
  // the full row height instead of clumping at the top.
9838
9922
  ...distributed === "space-between" ? { display: "flex", flexDirection: "column", justifyContent: "space-between" } : {}
@@ -18467,10 +18551,23 @@ function setPricingCardStyle(tree, index, style) {
18467
18551
  });
18468
18552
  }
18469
18553
  function setPricingCardFeaturedTag(tree, index, on) {
18470
- return withPricingCard(tree, index, (target) => {
18554
+ return withPricingCollection(tree, (collection) => {
18555
+ const children = collection.children;
18556
+ if (index < 0 || index >= children.length) return false;
18557
+ if (on) {
18558
+ children.forEach((card, i) => {
18559
+ if (i === index) return;
18560
+ const prev2 = featuredOf(card);
18561
+ if (prev2.enabled !== true || badgeOf(prev2).length === 0) return;
18562
+ card.slots = card.slots ?? {};
18563
+ card.slots.featured = composeFeatured(pricingCardStyleOf(prev2), false, badgeOf(prev2));
18564
+ });
18565
+ }
18566
+ const target = children[index];
18567
+ target.slots = target.slots ?? {};
18471
18568
  const prev = featuredOf(target);
18472
- const style = pricingCardStyleOf(prev);
18473
- target.slots.featured = composeFeatured(style, on, badgeOf(prev));
18569
+ target.slots.featured = composeFeatured(pricingCardStyleOf(prev), on, badgeOf(prev));
18570
+ return true;
18474
18571
  });
18475
18572
  }
18476
18573
  function pricingCardStyleOf(featured) {
@@ -18720,25 +18817,40 @@ function ToolbarSeparator() {
18720
18817
  }
18721
18818
  function CardStyleMenu({
18722
18819
  value,
18723
- onChange
18820
+ onChange,
18821
+ disabled = false
18724
18822
  }) {
18725
18823
  const current = PRICING_CARD_STYLES.find((s) => s.value === value) ?? PRICING_CARD_STYLES[0];
18824
+ const trigger = /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
18825
+ "button",
18826
+ {
18827
+ type: "button",
18828
+ "aria-label": "Card style",
18829
+ disabled,
18830
+ className: cn(
18831
+ "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",
18832
+ disabled && "cursor-not-allowed opacity-40 hover:bg-transparent"
18833
+ ),
18834
+ children: [
18835
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(StyleSwatch, { style: current.value }),
18836
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "flex-1 text-left", children: current.label }),
18837
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.ChevronDown, { size: 16, style: { pointerEvents: "none" } })
18838
+ ]
18839
+ }
18840
+ );
18841
+ if (disabled) {
18842
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
18843
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "text-xs text-muted-foreground opacity-50", children: "Card style" }),
18844
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Tooltip, { children: [
18845
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "inline-flex", children: trigger }) }),
18846
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: "Mark as featured to edit card style" })
18847
+ ] })
18848
+ ] });
18849
+ }
18726
18850
  return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
18727
18851
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "text-xs text-muted-foreground", children: "Card style" }),
18728
18852
  /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(DropdownMenu, { modal: false, children: [
18729
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
18730
- "button",
18731
- {
18732
- type: "button",
18733
- "aria-label": "Card style",
18734
- 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",
18735
- children: [
18736
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(StyleSwatch, { style: current.value }),
18737
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "flex-1 text-left", children: current.label }),
18738
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.ChevronDown, { size: 16, style: { pointerEvents: "none" } })
18739
- ]
18740
- }
18741
- ) }),
18853
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DropdownMenuTrigger, { asChild: true, children: trigger }),
18742
18854
  /* @__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) => {
18743
18855
  const selected = style.value === value;
18744
18856
  return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
@@ -18802,23 +18914,35 @@ function PricingCardToolbar({
18802
18914
  mobile ? "flex-wrap justify-center" : "flex-nowrap"
18803
18915
  ),
18804
18916
  children: [
18805
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(CardStyleMenu, { value: style, onChange: onSetStyle }),
18806
18917
  /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Tooltip, { children: [
18807
18918
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
18808
18919
  CustomToolbarButton,
18809
18920
  {
18810
18921
  type: "button",
18811
- "aria-label": featuredTag ? "Remove featured tag" : "Add featured tag",
18922
+ "aria-label": featuredTag ? "Unmark as featured" : "Mark as featured",
18812
18923
  "aria-pressed": featuredTag,
18813
- active: featuredTag,
18814
18924
  onClick: () => onSetFeaturedTag(!featuredTag),
18815
- className: "size-8",
18816
- children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.Star, { size: 16, fill: featuredTag ? "currentColor" : "none", style: { pointerEvents: "none" } })
18925
+ className: "group size-8",
18926
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
18927
+ import_lucide_react9.Star,
18928
+ {
18929
+ size: 16,
18930
+ fill: "currentColor",
18931
+ strokeWidth: 0,
18932
+ className: cn(
18933
+ "transition-colors",
18934
+ featuredTag ? "text-[#f59e0b] group-hover:text-[#d97706]" : "text-[#d6d3d1] group-hover:text-[#fbbf24]"
18935
+ ),
18936
+ style: { pointerEvents: "none" }
18937
+ }
18938
+ )
18817
18939
  }
18818
18940
  ) }),
18819
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: featuredTag ? "Remove featured tag" : "Add featured tag" })
18941
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: featuredTag ? "Unmark featured" : "Mark as featured" })
18820
18942
  ] }),
18821
18943
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarSeparator, {}),
18944
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(CardStyleMenu, { value: style, onChange: onSetStyle, disabled: !featuredTag }),
18945
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarSeparator, {}),
18822
18946
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarAction, { label: "Add button", onClick: onAddButton, disabled: buttonCount >= 2, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ButtonGlyph, {}) }),
18823
18947
  /* @__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: [
18824
18948
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ButtonGlyph, {}),
@@ -30388,9 +30512,10 @@ function OhhwellsBridge() {
30388
30512
  if (e.data?.type !== "ow:collect-section") return;
30389
30513
  const sectionId = e.data.sectionId;
30390
30514
  if (typeof sectionId !== "string" || !sectionId) return;
30391
- const sectionEl = document.querySelector(
30515
+ const foundEl = document.querySelector(
30392
30516
  `[data-ohw-section="${CSS.escape(sectionId)}"]`
30393
30517
  );
30518
+ 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;
30394
30519
  const nodes = sectionEl ? collectEditableNodes(void 0, sectionEl).filter(
30395
30520
  (n) => n.key && !n.key.startsWith("__ohw_") && !["meta", "sections", "video-setting"].includes(n.type)
30396
30521
  ).map((n) => ({ ...n, text: n.text ?? "", type: normalizeAiNodeType(n.type) })) : [];
@@ -32345,6 +32470,7 @@ function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey
32345
32470
  dropIndicatorVariants,
32346
32471
  ensureFooterTree,
32347
32472
  filterAvailablePages,
32473
+ foldAlignIntoTrees,
32348
32474
  getEditModeInitialState,
32349
32475
  insertFooterHours,
32350
32476
  isEditSessionActive,
@@ -32353,6 +32479,7 @@ function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey
32353
32479
  isValidUrl,
32354
32480
  nextViableSlide,
32355
32481
  parseAiFooterState,
32482
+ parseAiSectionsState,
32356
32483
  parseTarget,
32357
32484
  removeFooterBlock,
32358
32485
  resolveFooterCopyright,