@ohhwells/bridge 0.1.91 → 0.1.93

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.d.cts CHANGED
@@ -24,6 +24,8 @@ type AiBlockType = 'text' | 'button' | 'media' | 'media-list' | 'rating' | 'divi
24
24
  interface AiBlockNode {
25
25
  type: AiBlockType;
26
26
  span: number;
27
+ /** Horizontal alignment of the block's content within its column. */
28
+ align?: 'left' | 'center' | 'right';
27
29
  slots?: Record<string, unknown>;
28
30
  children?: AiBlockNode[];
29
31
  items?: Array<{
@@ -55,8 +57,10 @@ interface AiLayoutTree {
55
57
  scaffold: SectionScaffold;
56
58
  tag?: string;
57
59
  settings?: AiSectionSettings;
60
+ /** A row's `align` sets the vertical alignment of its columns; `stretch` equalises heights. */
58
61
  rows: Array<{
59
62
  blocks: AiBlockNode[];
63
+ align?: 'top' | 'center' | 'bottom' | 'stretch';
60
64
  }>;
61
65
  }
62
66
  /** The site brand kit the renderer styles from (editor Brand settings). */
package/dist/index.d.ts CHANGED
@@ -24,6 +24,8 @@ type AiBlockType = 'text' | 'button' | 'media' | 'media-list' | 'rating' | 'divi
24
24
  interface AiBlockNode {
25
25
  type: AiBlockType;
26
26
  span: number;
27
+ /** Horizontal alignment of the block's content within its column. */
28
+ align?: 'left' | 'center' | 'right';
27
29
  slots?: Record<string, unknown>;
28
30
  children?: AiBlockNode[];
29
31
  items?: Array<{
@@ -55,8 +57,10 @@ interface AiLayoutTree {
55
57
  scaffold: SectionScaffold;
56
58
  tag?: string;
57
59
  settings?: AiSectionSettings;
60
+ /** A row's `align` sets the vertical alignment of its columns; `stretch` equalises heights. */
58
61
  rows: Array<{
59
62
  blocks: AiBlockNode[];
63
+ align?: 'top' | 'center' | 'bottom' | 'stretch';
60
64
  }>;
61
65
  }
62
66
  /** The site brand kit the renderer styles from (editor Brand settings). */
package/dist/index.js CHANGED
@@ -69,6 +69,7 @@ function isRenderableTree(value) {
69
69
 
70
70
  // src/lib/ai-sections-store.ts
71
71
  var AI_SECTIONS_KEY = "__ohw_ai_sections";
72
+ var AI_SLOT_KEY_PREFIX = "ai.";
72
73
  var EMPTY_AI_SECTIONS = { v: 1, sections: [] };
73
74
  function parseAiSectionsState(raw) {
74
75
  if (!raw) return EMPTY_AI_SECTIONS;
@@ -112,6 +113,63 @@ function applyTreeToState(state, payload) {
112
113
  const others = state.sections.filter((existing) => existing.id !== entry.id);
113
114
  return { ...state, v: 1, sections: [...others, entry] };
114
115
  }
116
+ function foldAlignIntoTrees(state, store) {
117
+ const byId = new Map(state.sections.map((entry) => [entry.id, entry]));
118
+ const nextTrees = /* @__PURE__ */ new Map();
119
+ const treeFor = (id) => {
120
+ const cloned = nextTrees.get(id);
121
+ if (cloned) return cloned;
122
+ const entry = byId.get(id);
123
+ if (!entry) return void 0;
124
+ const fresh = {
125
+ ...entry.tree,
126
+ rows: entry.tree.rows.map((row) => ({ ...row, blocks: row.blocks.map((block) => ({ ...block })) }))
127
+ };
128
+ nextTrees.set(id, fresh);
129
+ return fresh;
130
+ };
131
+ const nodes = {};
132
+ for (const [key, override] of Object.entries(store.nodes)) {
133
+ const match = override.align !== void 0 && key.startsWith(AI_SLOT_KEY_PREFIX) ? key.match(/^ai\.(.+?)\.r(\d+)\.b(\d+)(?:\.|$)/) : null;
134
+ const tree = match ? treeFor(match[1]) : void 0;
135
+ const block = match && tree ? tree.rows[Number(match[2])]?.blocks[Number(match[3])] : void 0;
136
+ if (!block) {
137
+ nodes[key] = override;
138
+ continue;
139
+ }
140
+ block.align = override.align;
141
+ const rest = { ...override };
142
+ delete rest.align;
143
+ if (Object.keys(rest).length > 0) nodes[key] = rest;
144
+ }
145
+ const sections = {};
146
+ for (const [sectionId, override] of Object.entries(store.sections)) {
147
+ const tree = override.align !== void 0 ? treeFor(sectionId) : void 0;
148
+ if (!tree) {
149
+ sections[sectionId] = override;
150
+ continue;
151
+ }
152
+ for (const row of tree.rows) {
153
+ for (const block of row.blocks) block.align = override.align;
154
+ }
155
+ const rest = { ...override };
156
+ delete rest.align;
157
+ if (Object.keys(rest).length > 0) sections[sectionId] = rest;
158
+ }
159
+ if (nextTrees.size === 0) return { state, store, changed: false };
160
+ return {
161
+ state: {
162
+ ...state,
163
+ v: 1,
164
+ sections: state.sections.map((entry) => {
165
+ const tree = nextTrees.get(entry.id);
166
+ return tree ? { ...entry, tree } : entry;
167
+ })
168
+ },
169
+ store: { v: 1, sections, nodes },
170
+ changed: true
171
+ };
172
+ }
115
173
  function removeFromState(state, id) {
116
174
  return { ...state, v: 1, sections: state.sections.filter((entry) => entry.id !== id) };
117
175
  }
@@ -330,6 +388,9 @@ function styleSheetCss() {
330
388
  `[data-ohw-style-spacing="${spacing}"] { padding-top: ${px}px !important; padding-bottom: ${px}px !important; }`
331
389
  );
332
390
  }
391
+ for (const align of ["left", "center", "right"]) {
392
+ rules.push(`[data-ohw-style-align="${align}"] { text-align: ${align} !important; }`);
393
+ }
333
394
  return rules.join("\n");
334
395
  }
335
396
  var STYLE_FONT_LINK_ID = "ohw-style-fonts";
@@ -356,10 +417,24 @@ var SECTION_ATTRS = {
356
417
  textDistribution: "data-ohw-style-distribution",
357
418
  headlineScale: "data-ohw-style-headline",
358
419
  imageAspect: "data-ohw-style-aspect",
359
- spacing: "data-ohw-style-spacing"
420
+ spacing: "data-ohw-style-spacing",
421
+ align: "data-ohw-style-align"
360
422
  };
361
423
  var NODE_WROTE_ATTR = "data-ohw-style-node";
362
- var NODE_PROPS = ["color", "font-family", "font-size", "background"];
424
+ var NODE_PROPS = [
425
+ "color",
426
+ "font-family",
427
+ "font-size",
428
+ "background",
429
+ "text-align",
430
+ "justify-content",
431
+ "align-items"
432
+ ];
433
+ var ALIGN_JUSTIFY = {
434
+ left: "flex-start",
435
+ center: "center",
436
+ right: "flex-end"
437
+ };
363
438
  function saveInline(el, prop) {
364
439
  const attr = `data-ohw-style-prev-${prop}`;
365
440
  if (el.hasAttribute(attr)) return;
@@ -403,6 +478,10 @@ function clearNodeProps(root) {
403
478
  function buttonSurfaceOf(el) {
404
479
  return el.closest("a, button") ?? el;
405
480
  }
481
+ function alignSubjectOf(el) {
482
+ const button = el.closest('[data-ohw-role="button"]');
483
+ return button?.parentElement ?? el;
484
+ }
406
485
  function applyStylesToDom(store) {
407
486
  ensureStyleSheet();
408
487
  clearSectionAttrs(document);
@@ -448,6 +527,18 @@ function applyStylesToDom(store) {
448
527
  el.style.setProperty("font-size", `${override.fontSize}px`, "important");
449
528
  el.setAttribute(NODE_WROTE_ATTR, "");
450
529
  }
530
+ if (override.align !== void 0) {
531
+ const subject = alignSubjectOf(el);
532
+ saveInline(subject, "text-align");
533
+ saveInline(subject, "justify-content");
534
+ subject.style.setProperty("text-align", override.align, "important");
535
+ subject.style.setProperty(
536
+ "justify-content",
537
+ ALIGN_JUSTIFY[override.align] ?? "flex-start",
538
+ "important"
539
+ );
540
+ subject.setAttribute(NODE_WROTE_ATTR, "");
541
+ }
451
542
  if (override.buttonBackground !== void 0 || override.buttonText !== void 0) {
452
543
  const surface = buttonSurfaceOf(el);
453
544
  if (override.buttonBackground !== void 0) {
@@ -656,7 +747,7 @@ function TextBlock({ slots, ctx, path }) {
656
747
  }
657
748
  function SectionHeaderBlock({ node, ctx, path }) {
658
749
  const slots = node.slots ?? {};
659
- const align = slots.alignment === "center" ? "center" : "left";
750
+ const align = node.align ?? (slots.alignment === "center" ? "center" : "left");
660
751
  const children = node.children ?? [];
661
752
  const buttonRowIdx = children.findIndex((c) => c.type === "button-row");
662
753
  const buttonRow = buttonRowIdx >= 0 ? children[buttonRowIdx] : void 0;
@@ -700,7 +791,7 @@ function SectionHeaderBlock({ node, ctx, path }) {
700
791
  display: "flex",
701
792
  gap: AI_TREE_TOKENS.spacing6,
702
793
  marginTop: AI_TREE_TOKENS.spacing8,
703
- justifyContent: align === "center" ? "center" : "flex-start"
794
+ justifyContent: align === "center" ? "center" : align === "right" ? "flex-end" : "flex-start"
704
795
  },
705
796
  children: (buttonRow.children ?? []).map((button, i) => /* @__PURE__ */ jsx(
706
797
  ButtonEl,
@@ -1033,7 +1124,7 @@ function CardBlock({ node, ctx, path }) {
1033
1124
  editPath: `${path}.media`
1034
1125
  }
1035
1126
  ) : null;
1036
- const centered = slots.alignment === "center";
1127
+ const centered = (node.align ?? slots.alignment) === "center";
1037
1128
  const content = /* @__PURE__ */ jsxs(
1038
1129
  "div",
1039
1130
  {
@@ -1752,6 +1843,19 @@ function AiTreeRenderer({
1752
1843
  }
1753
1844
  })();
1754
1845
  const distributed = !isOverlay && settings.textDistribution;
1846
+ const rowAlignItems = (rowAlign) => {
1847
+ if (rowAlign === "top") return "start";
1848
+ if (rowAlign === "bottom") return "end";
1849
+ if (rowAlign === "center" || rowAlign === "stretch") return rowAlign;
1850
+ if (distributed === "space-between") return "stretch";
1851
+ return (distributed ?? settings.verticalPosition) === "top" ? "start" : "center";
1852
+ };
1853
+ const cellAlignStyle = (blockAlign) => blockAlign ? {
1854
+ display: "flex",
1855
+ flexDirection: "column",
1856
+ alignItems: blockAlign === "left" ? "flex-start" : blockAlign === "right" ? "flex-end" : "center",
1857
+ textAlign: blockAlign
1858
+ } : {};
1755
1859
  return /* @__PURE__ */ jsxs(
1756
1860
  "section",
1757
1861
  {
@@ -1788,7 +1892,7 @@ function AiTreeRenderer({
1788
1892
  display: "grid",
1789
1893
  gridTemplateColumns: "repeat(12, 1fr)",
1790
1894
  gap: AI_TREE_TOKENS.spacing6,
1791
- alignItems: distributed === "space-between" ? "stretch" : (distributed ?? settings.verticalPosition) === "top" ? "start" : "center",
1895
+ alignItems: rowAlignItems(row.align),
1792
1896
  marginTop: r2 > 0 ? AI_TREE_TOKENS.spacing8 : 0
1793
1897
  },
1794
1898
  children: (row.blocks ?? []).map((block, b) => /* @__PURE__ */ jsx(
@@ -1798,6 +1902,8 @@ function AiTreeRenderer({
1798
1902
  style: {
1799
1903
  gridColumn: `span ${Math.min(12, Math.max(1, block.span))}`,
1800
1904
  minWidth: 0,
1905
+ // Horizontal placement of the block's content within its column.
1906
+ ...cellAlignStyle(block.align),
1801
1907
  // space-between: each column becomes a flex column whose content spreads over
1802
1908
  // the full row height instead of clumping at the top.
1803
1909
  ...distributed === "space-between" ? { display: "flex", flexDirection: "column", justifyContent: "space-between" } : {}
@@ -8079,17 +8185,40 @@ var REMOVED_ATTR2 = "data-ohw-section-removed";
8079
8185
  function isRemovedSection(el) {
8080
8186
  return el.hasAttribute(REMOVED_ATTR2);
8081
8187
  }
8188
+ function movableUnit(el) {
8189
+ return el.closest("[data-ohw-section-container]") ?? el;
8190
+ }
8191
+ function sectionTypeOf(el) {
8192
+ return el.getAttribute("data-ohw-section") ?? el.querySelector("[data-ohw-section]")?.getAttribute("data-ohw-section") ?? "";
8193
+ }
8194
+ function sectionElementOf(el) {
8195
+ return el.hasAttribute("data-ohw-section") ? el : el.querySelector("[data-ohw-section]") ?? el;
8196
+ }
8197
+ function collectTopLevelUnits(predicate) {
8198
+ const seen = /* @__PURE__ */ new Set();
8199
+ const result = [];
8200
+ document.querySelectorAll("[data-ohw-section]").forEach((el) => {
8201
+ if (!predicate(el)) return;
8202
+ const unit = movableUnit(el);
8203
+ if (unit.parentElement?.closest("[data-ohw-section],[data-ohw-section-container]")) return;
8204
+ if (seen.has(unit)) return;
8205
+ seen.add(unit);
8206
+ result.push(unit);
8207
+ });
8208
+ return result;
8209
+ }
8082
8210
  function topLevelSections() {
8083
- return Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
8084
- (el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el) && !isRemovedSection(el)
8085
- );
8211
+ return collectTopLevelUnits((el) => !isChromeSection(el) && !isRemovedSection(movableUnit(el)));
8086
8212
  }
8087
8213
  function instanceIdOf(el) {
8088
8214
  return el.dataset.ohwInstance ?? el.dataset.ohwSection ?? "";
8089
8215
  }
8090
8216
  function findByInstanceId(instanceId) {
8091
8217
  const escapedId = CSS.escape(instanceId);
8092
- return document.querySelector(`[data-ohw-instance="${escapedId}"]`) ?? document.querySelector(`[data-ohw-section="${escapedId}"]:not([data-ohw-instance])`);
8218
+ const direct = document.querySelector(`[data-ohw-instance="${escapedId}"]`);
8219
+ if (direct) return movableUnit(direct);
8220
+ const bare = document.querySelector(`[data-ohw-section="${escapedId}"]:not([data-ohw-instance])`);
8221
+ return bare ? movableUnit(bare) : null;
8093
8222
  }
8094
8223
  function planSectionMove(instanceId, targetIndex, currentPath) {
8095
8224
  const sections = topLevelSections();
@@ -8101,7 +8230,7 @@ function planSectionMove(instanceId, targetIndex, currentPath) {
8101
8230
  const reordered = [...others.slice(0, clamped), dragged, ...others.slice(clamped)];
8102
8231
  return reordered.map((el, order) => ({
8103
8232
  instanceId: instanceIdOf(el),
8104
- type: el.getAttribute("data-ohw-section") ?? "",
8233
+ type: sectionTypeOf(el),
8105
8234
  order,
8106
8235
  pagePath: currentPath
8107
8236
  }));
@@ -8156,13 +8285,11 @@ function applyPersistedOrder(entries) {
8156
8285
  function setSectionRemoved(instanceId, currentPath, existingEntries, removed) {
8157
8286
  if (!findByInstanceId(instanceId)) return null;
8158
8287
  const byId = new Map(existingEntries.map((e) => [e.instanceId, e]));
8159
- const allSections = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
8160
- (el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el)
8161
- );
8288
+ const allSections = collectTopLevelUnits((el) => !isChromeSection(el));
8162
8289
  allSections.forEach((el, order) => {
8163
8290
  const id = instanceIdOf(el);
8164
8291
  if (!byId.has(id)) {
8165
- byId.set(id, { instanceId: id, type: el.getAttribute("data-ohw-section") ?? "", order, pagePath: currentPath });
8292
+ byId.set(id, { instanceId: id, type: sectionTypeOf(el), order, pagePath: currentPath });
8166
8293
  }
8167
8294
  });
8168
8295
  const target = byId.get(instanceId);
@@ -8190,7 +8317,7 @@ function duplicateSectionInstance(instanceId, newId, currentPath, existingEntrie
8190
8317
  const id = instanceIdOf(el);
8191
8318
  return {
8192
8319
  instanceId: id,
8193
- type: el.getAttribute("data-ohw-section") ?? "",
8320
+ type: sectionTypeOf(el),
8194
8321
  order,
8195
8322
  pagePath: currentPath,
8196
8323
  ...byId.get(id)?.removed ? { removed: true } : {}
@@ -8232,6 +8359,10 @@ function initSectionInstancesFromContent(content, currentPath) {
8232
8359
  document.querySelectorAll("[data-ohw-section]:not([data-ohw-instance])").forEach((el) => {
8233
8360
  el.setAttribute("data-ohw-instance", el.getAttribute("data-ohw-section") ?? "");
8234
8361
  });
8362
+ document.querySelectorAll("[data-ohw-section-container]:not([data-ohw-instance])").forEach((el) => {
8363
+ const type = sectionTypeOf(el);
8364
+ if (type) el.setAttribute("data-ohw-instance", type);
8365
+ });
8235
8366
  const entries = getPageSectionOrderEntries(content[SECTION_ORDER_KEY], currentPath);
8236
8367
  for (const entry of entries) {
8237
8368
  if (entry.instanceId === entry.type) continue;
@@ -8250,10 +8381,7 @@ function initSectionInstancesFromContent(content, currentPath) {
8250
8381
 
8251
8382
  // src/ui/ai-section/AiSectionOverlay.tsx
8252
8383
  import { Fragment as Fragment5, jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
8253
- function findSectionElement(instanceId) {
8254
- const escaped = CSS.escape(instanceId);
8255
- return document.querySelector(`[data-ohw-instance="${escaped}"]`) ?? document.querySelector(`[data-ohw-section="${escaped}"]:not([data-ohw-instance])`);
8256
- }
8384
+ var findSectionElement = findByInstanceId;
8257
8385
  function readRect(instanceId) {
8258
8386
  const el = findSectionElement(instanceId);
8259
8387
  if (!el) return null;
@@ -8293,7 +8421,7 @@ function useLiveSectionRect(sectionId) {
8293
8421
  }
8294
8422
  function computeSectionBoundaryFlags(instanceId) {
8295
8423
  const topLevel = topLevelSections();
8296
- const index = topLevel.findIndex((el) => (el.dataset.ohwInstance ?? el.dataset.ohwSection) === instanceId);
8424
+ const index = topLevel.findIndex((el) => instanceIdOf(el) === instanceId);
8297
8425
  if (index === -1) return { isFirst: true, isLast: true };
8298
8426
  return { isFirst: index === 0, isLast: index === topLevel.length - 1 };
8299
8427
  }
@@ -8377,18 +8505,20 @@ function AiSectionOverlay({
8377
8505
  selectedIdRef.current = selectedId;
8378
8506
  const report = useCallback2(
8379
8507
  (el) => {
8508
+ const labelSrc = el ? sectionElementOf(el) : null;
8380
8509
  postToParent2({
8381
8510
  type: "ow:section-selected",
8382
- sectionId: el ? el.dataset.ohwInstance ?? el.dataset.ohwSection ?? null : null,
8383
- sectionLabel: el ? el.dataset.ohwSectionLabel ?? titleCaseSectionId(el.dataset.ohwSection ?? "") : null
8511
+ sectionId: el ? instanceIdOf(el) || null : null,
8512
+ sectionLabel: labelSrc ? labelSrc.dataset.ohwSectionLabel ?? titleCaseSectionId(labelSrc.dataset.ohwSection ?? "") : null
8384
8513
  });
8385
8514
  },
8386
8515
  [postToParent2]
8387
8516
  );
8388
8517
  const selectFromElement = useCallback2(
8389
8518
  (el, options) => {
8390
- const sectionEl = el?.closest("[data-ohw-section]") ?? null;
8391
- const id = sectionEl ? sectionEl.dataset.ohwInstance ?? sectionEl.dataset.ohwSection ?? null : null;
8519
+ const inner = el?.closest("[data-ohw-section]") ?? null;
8520
+ const sectionEl = inner ? movableUnit(inner) : null;
8521
+ const id = sectionEl ? instanceIdOf(sectionEl) || null : null;
8392
8522
  if (id === selectedIdRef.current) return;
8393
8523
  setSelectedId(id);
8394
8524
  if (options?.report !== false) report(sectionEl);
@@ -8454,7 +8584,8 @@ function AiSectionOverlay({
8454
8584
  return;
8455
8585
  }
8456
8586
  const sec = t.closest("[data-ohw-section]");
8457
- setHoveredId(sec ? sec.dataset.ohwInstance ?? sec.dataset.ohwSection ?? null : null);
8587
+ const unit = sec ? movableUnit(sec) : null;
8588
+ setHoveredId(unit ? instanceIdOf(unit) || null : null);
8458
8589
  };
8459
8590
  const onLeave = () => setHoveredId(null);
8460
8591
  document.addEventListener("mousemove", onMove, { passive: true });
@@ -14078,8 +14209,9 @@ function useSectionDrag({
14078
14209
  const target = e.target;
14079
14210
  if (!(target instanceof HTMLElement)) return;
14080
14211
  if (target.closest(SECTION_DRAG_EXCLUDED_SELECTOR)) return;
14081
- const sectionEl = target.closest("[data-ohw-section]");
14082
- if (!sectionEl || isChromeSection(sectionEl) || sectionEl.dataset.ohwSection === "footer") return;
14212
+ const inner = target.closest("[data-ohw-section]");
14213
+ if (!inner || isChromeSection(inner) || inner.dataset.ohwSection === "footer") return;
14214
+ const sectionEl = movableUnit(inner);
14083
14215
  if (!topLevelSections().includes(sectionEl)) return;
14084
14216
  startSectionPressDrag(sectionEl, e.clientX, e.clientY, e.pointerId);
14085
14217
  };
@@ -14986,7 +15118,6 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
14986
15118
  if (!mountPoint) return false;
14987
15119
  const container = document.createElement("div");
14988
15120
  container.dataset.ohwSectionContainer = "scheduling";
14989
- container.dataset.ohwSection = sectionId;
14990
15121
  container.dataset.ohwInstance = sectionId;
14991
15122
  if (insertBefore) {
14992
15123
  const beforeAnchor = document.querySelector(`[data-ohw-section="${insertBefore}"]`);
@@ -18143,10 +18274,10 @@ function OhhwellsBridge() {
18143
18274
  const applyFromCache = () => {
18144
18275
  const content = contentCache.get(subdomain);
18145
18276
  if (!content) return;
18146
- retryMissingSchedulingMounts(getPageSchedulingEntries(content["__ohw_sections"]), false);
18147
- initSectionInstancesFromContent(content, window.location.pathname);
18148
18277
  observer?.disconnect();
18149
18278
  try {
18279
+ retryMissingSchedulingMounts(getPageSchedulingEntries(content["__ohw_sections"]), false);
18280
+ initSectionInstancesFromContent(content, window.location.pathname);
18150
18281
  applyBrandChrome(content);
18151
18282
  if (typeof content[BRAND_KIT_KEY] === "string") {
18152
18283
  applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
@@ -18237,6 +18368,10 @@ function OhhwellsBridge() {
18237
18368
  deselectRef.current();
18238
18369
  deactivateRef.current();
18239
18370
  }, [pathname, isEditMode]);
18371
+ useEffect13(() => {
18372
+ if (!isEditMode) return;
18373
+ initSectionInstancesFromContent(editContentRef.current, pathname);
18374
+ }, [pathname, isEditMode]);
18240
18375
  useEffect13(() => {
18241
18376
  const contentForNav = () => {
18242
18377
  if (isEditMode) return editContentRef.current;
@@ -20257,12 +20392,35 @@ function OhhwellsBridge() {
20257
20392
  window.addEventListener("message", handleAiSetBrand);
20258
20393
  const handleAiSetStyles = (e) => {
20259
20394
  if (e.data?.type !== "ow:ai-set-styles") return;
20260
- const value = typeof e.data.value === "string" ? e.data.value : "";
20395
+ let value = typeof e.data.value === "string" ? e.data.value : "";
20261
20396
  const previous = stylesRef.current;
20397
+ let previousSections;
20398
+ const store = parseStyleStore(value);
20399
+ if (store) {
20400
+ const folded = foldAlignIntoTrees(parseAiSectionsState(aiSectionsRef.current), store);
20401
+ if (folded.changed) {
20402
+ const nextSections = serializeAiSectionsState(folded.state);
20403
+ if (nextSections !== aiSectionsRef.current) {
20404
+ previousSections = aiSectionsRef.current;
20405
+ aiSectionsRef.current = nextSections;
20406
+ applyAiSectionsToDom(folded.state);
20407
+ postToParentRef.current({
20408
+ type: "ow:change",
20409
+ nodes: [{ key: AI_SECTIONS_KEY, text: nextSections }]
20410
+ });
20411
+ }
20412
+ value = JSON.stringify(folded.store);
20413
+ }
20414
+ }
20262
20415
  stylesRef.current = value;
20263
20416
  applyStylesToDom(parseStyleStore(value));
20264
20417
  postToParentRef.current({ type: "ow:change", nodes: [{ key: STYLE_STORE_KEY, text: value }] });
20265
- postToParentRef.current({ type: "ow:ai-styles-applied", previous, value });
20418
+ postToParentRef.current({
20419
+ type: "ow:ai-styles-applied",
20420
+ previous,
20421
+ value,
20422
+ ...previousSections !== void 0 ? { previousSections } : {}
20423
+ });
20266
20424
  };
20267
20425
  window.addEventListener("message", handleAiSetStyles);
20268
20426
  const handleGetBrand = (e) => {
@@ -21283,7 +21441,7 @@ function OhhwellsBridge() {
21283
21441
  postToParent2({
21284
21442
  type: "ow:ready",
21285
21443
  version: "1",
21286
- bridgeVersion: "0.1.90",
21444
+ bridgeVersion: "0.1.92",
21287
21445
  path: pathname,
21288
21446
  nodes: collectEditableNodes(editContentRef.current),
21289
21447
  sections