@ohhwells/bridge 0.1.80-next.242 → 0.1.80-next.244

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
@@ -143,6 +143,7 @@ function isRenderableTree(value) {
143
143
 
144
144
  // src/lib/ai-sections-store.ts
145
145
  var AI_SECTIONS_KEY = "__ohw_ai_sections";
146
+ var AI_SLOT_KEY_PREFIX = "ai.";
146
147
  var EMPTY_AI_SECTIONS = { v: 1, sections: [] };
147
148
  function parseAiSectionsState(raw) {
148
149
  if (!raw) return EMPTY_AI_SECTIONS;
@@ -186,6 +187,63 @@ function applyTreeToState(state, payload) {
186
187
  const others = state.sections.filter((existing) => existing.id !== entry.id);
187
188
  return { ...state, v: 1, sections: [...others, entry] };
188
189
  }
190
+ function foldAlignIntoTrees(state, store) {
191
+ const byId = new Map(state.sections.map((entry) => [entry.id, entry]));
192
+ const nextTrees = /* @__PURE__ */ new Map();
193
+ const treeFor = (id) => {
194
+ const cloned = nextTrees.get(id);
195
+ if (cloned) return cloned;
196
+ const entry = byId.get(id);
197
+ if (!entry) return void 0;
198
+ const fresh = {
199
+ ...entry.tree,
200
+ rows: entry.tree.rows.map((row) => ({ ...row, blocks: row.blocks.map((block) => ({ ...block })) }))
201
+ };
202
+ nextTrees.set(id, fresh);
203
+ return fresh;
204
+ };
205
+ const nodes = {};
206
+ for (const [key, override] of Object.entries(store.nodes)) {
207
+ const match = override.align !== void 0 && key.startsWith(AI_SLOT_KEY_PREFIX) ? key.match(/^ai\.(.+?)\.r(\d+)\.b(\d+)(?:\.|$)/) : null;
208
+ const tree = match ? treeFor(match[1]) : void 0;
209
+ const block = match && tree ? tree.rows[Number(match[2])]?.blocks[Number(match[3])] : void 0;
210
+ if (!block) {
211
+ nodes[key] = override;
212
+ continue;
213
+ }
214
+ block.align = override.align;
215
+ const rest = { ...override };
216
+ delete rest.align;
217
+ if (Object.keys(rest).length > 0) nodes[key] = rest;
218
+ }
219
+ const sections = {};
220
+ for (const [sectionId, override] of Object.entries(store.sections)) {
221
+ const tree = override.align !== void 0 ? treeFor(sectionId) : void 0;
222
+ if (!tree) {
223
+ sections[sectionId] = override;
224
+ continue;
225
+ }
226
+ for (const row of tree.rows) {
227
+ for (const block of row.blocks) block.align = override.align;
228
+ }
229
+ const rest = { ...override };
230
+ delete rest.align;
231
+ if (Object.keys(rest).length > 0) sections[sectionId] = rest;
232
+ }
233
+ if (nextTrees.size === 0) return { state, store, changed: false };
234
+ return {
235
+ state: {
236
+ ...state,
237
+ v: 1,
238
+ sections: state.sections.map((entry) => {
239
+ const tree = nextTrees.get(entry.id);
240
+ return tree ? { ...entry, tree } : entry;
241
+ })
242
+ },
243
+ store: { v: 1, sections, nodes },
244
+ changed: true
245
+ };
246
+ }
189
247
  function removeFromState(state, id) {
190
248
  return { ...state, v: 1, sections: state.sections.filter((entry) => entry.id !== id) };
191
249
  }
@@ -378,6 +436,9 @@ function styleSheetCss() {
378
436
  `[data-ohw-style-spacing="${spacing}"] { padding-top: ${px}px !important; padding-bottom: ${px}px !important; }`
379
437
  );
380
438
  }
439
+ for (const align of ["left", "center", "right"]) {
440
+ rules.push(`[data-ohw-style-align="${align}"] { text-align: ${align} !important; }`);
441
+ }
381
442
  return rules.join("\n");
382
443
  }
383
444
  var STYLE_FONT_LINK_ID = "ohw-style-fonts";
@@ -404,7 +465,8 @@ var SECTION_ATTRS = {
404
465
  textDistribution: "data-ohw-style-distribution",
405
466
  headlineScale: "data-ohw-style-headline",
406
467
  imageAspect: "data-ohw-style-aspect",
407
- spacing: "data-ohw-style-spacing"
468
+ spacing: "data-ohw-style-spacing",
469
+ align: "data-ohw-style-align"
408
470
  };
409
471
  var NODE_WROTE_ATTR = "data-ohw-style-node";
410
472
  var NODE_PROPS = [
@@ -413,7 +475,8 @@ var NODE_PROPS = [
413
475
  "font-size",
414
476
  "background",
415
477
  "text-align",
416
- "justify-content"
478
+ "justify-content",
479
+ "align-items"
417
480
  ];
418
481
  var ALIGN_JUSTIFY = {
419
482
  left: "flex-start",
@@ -463,6 +526,13 @@ function clearNodeProps(root) {
463
526
  function buttonSurfaceOf(el) {
464
527
  return el.closest("a, button") ?? el;
465
528
  }
529
+ function alignSubjectOf(el) {
530
+ const button = el.closest('[data-ohw-role="button"]');
531
+ return button?.parentElement ?? el;
532
+ }
533
+ function horizontalFlexProp(el) {
534
+ return getComputedStyle(el).flexDirection.startsWith("column") ? "align-items" : "justify-content";
535
+ }
466
536
  function applyStylesToDom(store) {
467
537
  ensureStyleSheet();
468
538
  clearSectionAttrs(document);
@@ -509,11 +579,13 @@ function applyStylesToDom(store) {
509
579
  el.setAttribute(NODE_WROTE_ATTR, "");
510
580
  }
511
581
  if (override.align !== void 0) {
512
- saveInline(el, "text-align");
513
- saveInline(el, "justify-content");
514
- el.style.setProperty("text-align", override.align, "important");
515
- el.style.setProperty("justify-content", ALIGN_JUSTIFY[override.align] ?? "flex-start", "important");
516
- el.setAttribute(NODE_WROTE_ATTR, "");
582
+ const subject = alignSubjectOf(el);
583
+ const flexProp = horizontalFlexProp(subject);
584
+ saveInline(subject, "text-align");
585
+ saveInline(subject, flexProp);
586
+ subject.style.setProperty("text-align", override.align, "important");
587
+ subject.style.setProperty(flexProp, ALIGN_JUSTIFY[override.align] ?? "flex-start", "important");
588
+ subject.setAttribute(NODE_WROTE_ATTR, "");
517
589
  }
518
590
  if (override.buttonBackground !== void 0 || override.buttonText !== void 0) {
519
591
  const surface = buttonSurfaceOf(el);
@@ -743,7 +815,7 @@ function TextBlock({ slots, ctx, path }) {
743
815
  }
744
816
  function SectionHeaderBlock({ node, ctx, path }) {
745
817
  const slots = node.slots ?? {};
746
- const align = slots.alignment === "center" ? "center" : "left";
818
+ const align = node.align ?? (slots.alignment === "center" ? "center" : "left");
747
819
  const children = node.children ?? [];
748
820
  const buttonRowIdx = children.findIndex((c) => c.type === "button-row");
749
821
  const buttonRow = buttonRowIdx >= 0 ? children[buttonRowIdx] : void 0;
@@ -787,7 +859,7 @@ function SectionHeaderBlock({ node, ctx, path }) {
787
859
  display: "flex",
788
860
  gap: AI_TREE_TOKENS.spacing6,
789
861
  marginTop: AI_TREE_TOKENS.spacing8,
790
- justifyContent: align === "center" ? "center" : "flex-start"
862
+ justifyContent: align === "center" ? "center" : align === "right" ? "flex-end" : "flex-start"
791
863
  },
792
864
  children: (buttonRow.children ?? []).map((button, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
793
865
  ButtonEl,
@@ -1120,7 +1192,7 @@ function CardBlock({ node, ctx, path }) {
1120
1192
  editPath: `${path}.media`
1121
1193
  }
1122
1194
  ) : null;
1123
- const centered = slots.alignment === "center";
1195
+ const centered = (node.align ?? slots.alignment) === "center";
1124
1196
  const content = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1125
1197
  "div",
1126
1198
  {
@@ -20295,12 +20367,35 @@ function OhhwellsBridge() {
20295
20367
  window.addEventListener("message", handleAiSetBrand);
20296
20368
  const handleAiSetStyles = (e) => {
20297
20369
  if (e.data?.type !== "ow:ai-set-styles") return;
20298
- const value = typeof e.data.value === "string" ? e.data.value : "";
20370
+ let value = typeof e.data.value === "string" ? e.data.value : "";
20299
20371
  const previous = stylesRef.current;
20372
+ let previousSections;
20373
+ const store = parseStyleStore(value);
20374
+ if (store) {
20375
+ const folded = foldAlignIntoTrees(parseAiSectionsState(aiSectionsRef.current), store);
20376
+ if (folded.changed) {
20377
+ const nextSections = serializeAiSectionsState(folded.state);
20378
+ if (nextSections !== aiSectionsRef.current) {
20379
+ previousSections = aiSectionsRef.current;
20380
+ aiSectionsRef.current = nextSections;
20381
+ applyAiSectionsToDom(folded.state);
20382
+ postToParentRef.current({
20383
+ type: "ow:change",
20384
+ nodes: [{ key: AI_SECTIONS_KEY, text: nextSections }]
20385
+ });
20386
+ }
20387
+ value = JSON.stringify(folded.store);
20388
+ }
20389
+ }
20300
20390
  stylesRef.current = value;
20301
20391
  applyStylesToDom(parseStyleStore(value));
20302
20392
  postToParentRef.current({ type: "ow:change", nodes: [{ key: STYLE_STORE_KEY, text: value }] });
20303
- postToParentRef.current({ type: "ow:ai-styles-applied", previous, value });
20393
+ postToParentRef.current({
20394
+ type: "ow:ai-styles-applied",
20395
+ previous,
20396
+ value,
20397
+ ...previousSections !== void 0 ? { previousSections } : {}
20398
+ });
20304
20399
  };
20305
20400
  window.addEventListener("message", handleAiSetStyles);
20306
20401
  const handleGetBrand = (e) => {