@ohhwells/bridge 0.1.145 → 0.1.147
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 +158 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -1
- package/dist/index.d.ts +16 -1
- package/dist/index.js +157 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -28,6 +28,14 @@ interface AiBlockNode {
|
|
|
28
28
|
align?: 'left' | 'center' | 'right';
|
|
29
29
|
slots?: Record<string, unknown>;
|
|
30
30
|
children?: AiBlockNode[];
|
|
31
|
+
/** Stable id for ordered insertion. Omitted on trees saved before slots. */
|
|
32
|
+
ref?: string;
|
|
33
|
+
/** Fixed slot inside a split (`left`/`right`) or grid (`cell-N`). Omit to keep index order. */
|
|
34
|
+
slot?: string;
|
|
35
|
+
/** Unfilled fixed slots on a group. The published page draws none of these. */
|
|
36
|
+
emptySlots?: string[];
|
|
37
|
+
/** Stack wrapped around a slot that was filled a second time. */
|
|
38
|
+
promoted?: true;
|
|
31
39
|
/** Shape is per-block-type, defined by the backend's `BlockDef.itemFields` (accordion's
|
|
32
40
|
* question/answer, media-strip's assetId/alt/href/linkTarget, footer link-list/hours/social-row). */
|
|
33
41
|
items?: Array<Record<string, unknown>>;
|
|
@@ -461,6 +469,13 @@ interface AiSectionsState {
|
|
|
461
469
|
}
|
|
462
470
|
/** Parse a persisted value defensively — malformed state renders nothing, never throws. */
|
|
463
471
|
declare function parseAiSectionsState(raw: string | null | undefined): AiSectionsState;
|
|
472
|
+
/**
|
|
473
|
+
* Drop every `text-align` declaration from the inline style attributes in one content string,
|
|
474
|
+
* removing a style attribute that carried nothing else. Regex rather than DOMParser so the fold
|
|
475
|
+
* stays pure and usable outside a browser; the only authors of these attributes are the bridge's
|
|
476
|
+
* own `sanitizeHtml` and the model's alignment wraps, which both emit double-quoted attributes.
|
|
477
|
+
*/
|
|
478
|
+
declare function stripTextAlignCss(html: string): string;
|
|
464
479
|
/**
|
|
465
480
|
* Fold alignment overrides that target GENERATED sections into their trees, where alignment is
|
|
466
481
|
* first-class data (block.align) that persists with the rest of the tree. A node override
|
|
@@ -859,4 +874,4 @@ declare function useOhwCarousel(key: string, initial: CarouselSlide[]): {
|
|
|
859
874
|
bind: Record<string, string>;
|
|
860
875
|
};
|
|
861
876
|
|
|
862
|
-
export { AI_DEFAULT_BRAND, AI_FOOTER_KEY, AI_TREE_SCHEMA_VERSIONS, AI_TREE_TOKENS, type AiBlockNode, type AiBrandKit, type AiFooterBottomBar, type AiFooterColumn, type AiFooterLayoutTree, AiFooterRenderer, type AiFooterRendererProps, type AiLayoutTree, AiTreeRenderer, type AiTreeRendererProps, type CarouselSlide, CustomToolbar, CustomToolbarButton, CustomToolbarDivider, DragHandle, DropIndicator, type DropIndicatorProps, DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, EmptySection, type EmptySectionProps, FOOTER_COLUMN_BLOCKS, FOOTER_COLUMN_SPANS, FOOTER_SOCIAL_PLATFORMS, ItemActionToolbar, type ItemActionToolbarProps, ItemInteractionLayer, type ItemInteractionLayerProps, type ItemInteractionState, LinkEditorPanel, type LinkModalMode, type LinkModalProps, type LinkPage, LinkPopover, type LinkSection, OhhwellsBridge, SchedulingWidget, type SectionScaffold, type SiteLegalLinks, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, addFooterLinkColumn, appendFooterSocial, buildDefaultFooterTree, buildTarget, dropIndicatorVariants, ensureFooterTree, filterAvailablePages, foldAlignIntoTrees, getEditModeInitialState, insertFooterHours, isEditSessionActive, isRenderableFooterTree, isRenderableTree, isValidUrl, nextViableSlide, parseAiFooterState, parseAiSectionsState, parseTarget, removeFooterBlock, resolveFooterCopyright, serializeAiFooterState, stepViableSlide, toggleVariants, useOhwCarousel, validateUrlInput, viableSlides };
|
|
877
|
+
export { AI_DEFAULT_BRAND, AI_FOOTER_KEY, AI_TREE_SCHEMA_VERSIONS, AI_TREE_TOKENS, type AiBlockNode, type AiBrandKit, type AiFooterBottomBar, type AiFooterColumn, type AiFooterLayoutTree, AiFooterRenderer, type AiFooterRendererProps, type AiLayoutTree, AiTreeRenderer, type AiTreeRendererProps, type CarouselSlide, CustomToolbar, CustomToolbarButton, CustomToolbarDivider, DragHandle, DropIndicator, type DropIndicatorProps, DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, EmptySection, type EmptySectionProps, FOOTER_COLUMN_BLOCKS, FOOTER_COLUMN_SPANS, FOOTER_SOCIAL_PLATFORMS, ItemActionToolbar, type ItemActionToolbarProps, ItemInteractionLayer, type ItemInteractionLayerProps, type ItemInteractionState, LinkEditorPanel, type LinkModalMode, type LinkModalProps, type LinkPage, LinkPopover, type LinkSection, OhhwellsBridge, SchedulingWidget, type SectionScaffold, type SiteLegalLinks, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, addFooterLinkColumn, appendFooterSocial, buildDefaultFooterTree, buildTarget, dropIndicatorVariants, ensureFooterTree, filterAvailablePages, foldAlignIntoTrees, getEditModeInitialState, insertFooterHours, isEditSessionActive, isRenderableFooterTree, isRenderableTree, isValidUrl, nextViableSlide, parseAiFooterState, parseAiSectionsState, parseTarget, removeFooterBlock, resolveFooterCopyright, serializeAiFooterState, stepViableSlide, stripTextAlignCss, toggleVariants, useOhwCarousel, validateUrlInput, viableSlides };
|
package/dist/index.d.ts
CHANGED
|
@@ -28,6 +28,14 @@ interface AiBlockNode {
|
|
|
28
28
|
align?: 'left' | 'center' | 'right';
|
|
29
29
|
slots?: Record<string, unknown>;
|
|
30
30
|
children?: AiBlockNode[];
|
|
31
|
+
/** Stable id for ordered insertion. Omitted on trees saved before slots. */
|
|
32
|
+
ref?: string;
|
|
33
|
+
/** Fixed slot inside a split (`left`/`right`) or grid (`cell-N`). Omit to keep index order. */
|
|
34
|
+
slot?: string;
|
|
35
|
+
/** Unfilled fixed slots on a group. The published page draws none of these. */
|
|
36
|
+
emptySlots?: string[];
|
|
37
|
+
/** Stack wrapped around a slot that was filled a second time. */
|
|
38
|
+
promoted?: true;
|
|
31
39
|
/** Shape is per-block-type, defined by the backend's `BlockDef.itemFields` (accordion's
|
|
32
40
|
* question/answer, media-strip's assetId/alt/href/linkTarget, footer link-list/hours/social-row). */
|
|
33
41
|
items?: Array<Record<string, unknown>>;
|
|
@@ -461,6 +469,13 @@ interface AiSectionsState {
|
|
|
461
469
|
}
|
|
462
470
|
/** Parse a persisted value defensively — malformed state renders nothing, never throws. */
|
|
463
471
|
declare function parseAiSectionsState(raw: string | null | undefined): AiSectionsState;
|
|
472
|
+
/**
|
|
473
|
+
* Drop every `text-align` declaration from the inline style attributes in one content string,
|
|
474
|
+
* removing a style attribute that carried nothing else. Regex rather than DOMParser so the fold
|
|
475
|
+
* stays pure and usable outside a browser; the only authors of these attributes are the bridge's
|
|
476
|
+
* own `sanitizeHtml` and the model's alignment wraps, which both emit double-quoted attributes.
|
|
477
|
+
*/
|
|
478
|
+
declare function stripTextAlignCss(html: string): string;
|
|
464
479
|
/**
|
|
465
480
|
* Fold alignment overrides that target GENERATED sections into their trees, where alignment is
|
|
466
481
|
* first-class data (block.align) that persists with the rest of the tree. A node override
|
|
@@ -859,4 +874,4 @@ declare function useOhwCarousel(key: string, initial: CarouselSlide[]): {
|
|
|
859
874
|
bind: Record<string, string>;
|
|
860
875
|
};
|
|
861
876
|
|
|
862
|
-
export { AI_DEFAULT_BRAND, AI_FOOTER_KEY, AI_TREE_SCHEMA_VERSIONS, AI_TREE_TOKENS, type AiBlockNode, type AiBrandKit, type AiFooterBottomBar, type AiFooterColumn, type AiFooterLayoutTree, AiFooterRenderer, type AiFooterRendererProps, type AiLayoutTree, AiTreeRenderer, type AiTreeRendererProps, type CarouselSlide, CustomToolbar, CustomToolbarButton, CustomToolbarDivider, DragHandle, DropIndicator, type DropIndicatorProps, DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, EmptySection, type EmptySectionProps, FOOTER_COLUMN_BLOCKS, FOOTER_COLUMN_SPANS, FOOTER_SOCIAL_PLATFORMS, ItemActionToolbar, type ItemActionToolbarProps, ItemInteractionLayer, type ItemInteractionLayerProps, type ItemInteractionState, LinkEditorPanel, type LinkModalMode, type LinkModalProps, type LinkPage, LinkPopover, type LinkSection, OhhwellsBridge, SchedulingWidget, type SectionScaffold, type SiteLegalLinks, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, addFooterLinkColumn, appendFooterSocial, buildDefaultFooterTree, buildTarget, dropIndicatorVariants, ensureFooterTree, filterAvailablePages, foldAlignIntoTrees, getEditModeInitialState, insertFooterHours, isEditSessionActive, isRenderableFooterTree, isRenderableTree, isValidUrl, nextViableSlide, parseAiFooterState, parseAiSectionsState, parseTarget, removeFooterBlock, resolveFooterCopyright, serializeAiFooterState, stepViableSlide, toggleVariants, useOhwCarousel, validateUrlInput, viableSlides };
|
|
877
|
+
export { AI_DEFAULT_BRAND, AI_FOOTER_KEY, AI_TREE_SCHEMA_VERSIONS, AI_TREE_TOKENS, type AiBlockNode, type AiBrandKit, type AiFooterBottomBar, type AiFooterColumn, type AiFooterLayoutTree, AiFooterRenderer, type AiFooterRendererProps, type AiLayoutTree, AiTreeRenderer, type AiTreeRendererProps, type CarouselSlide, CustomToolbar, CustomToolbarButton, CustomToolbarDivider, DragHandle, DropIndicator, type DropIndicatorProps, DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, EmptySection, type EmptySectionProps, FOOTER_COLUMN_BLOCKS, FOOTER_COLUMN_SPANS, FOOTER_SOCIAL_PLATFORMS, ItemActionToolbar, type ItemActionToolbarProps, ItemInteractionLayer, type ItemInteractionLayerProps, type ItemInteractionState, LinkEditorPanel, type LinkModalMode, type LinkModalProps, type LinkPage, LinkPopover, type LinkSection, OhhwellsBridge, SchedulingWidget, type SectionScaffold, type SiteLegalLinks, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, addFooterLinkColumn, appendFooterSocial, buildDefaultFooterTree, buildTarget, dropIndicatorVariants, ensureFooterTree, filterAvailablePages, foldAlignIntoTrees, getEditModeInitialState, insertFooterHours, isEditSessionActive, isRenderableFooterTree, isRenderableTree, isValidUrl, nextViableSlide, parseAiFooterState, parseAiSectionsState, parseTarget, removeFooterBlock, resolveFooterCopyright, serializeAiFooterState, stepViableSlide, stripTextAlignCss, toggleVariants, useOhwCarousel, validateUrlInput, viableSlides };
|
package/dist/index.js
CHANGED
|
@@ -6164,12 +6164,34 @@ function applyTreeToState(state, payload) {
|
|
|
6164
6164
|
...selfEdit ? priorEntry?.beforeSection ? { beforeSection: priorEntry.beforeSection } : {} : insertBefore && payload.targetSectionId ? { beforeSection: payload.targetSectionId } : {},
|
|
6165
6165
|
...selfEdit ? priorEntry?.replaces ? { replaces: priorEntry.replaces } : {} : payload.mode === "replace" && payload.targetSectionId ? { replaces: payload.targetSectionId } : {},
|
|
6166
6166
|
tree: payload.tree,
|
|
6167
|
-
media
|
|
6167
|
+
// A column insert rebuilds the media map from the live DOM keys. The photo
|
|
6168
|
+
// still points at the ref it was generated with. Keep that ref.
|
|
6169
|
+
media: { ...priorEntry?.media ?? {}, ...payload.media ?? {} },
|
|
6168
6170
|
...payload.brand && typeof payload.brand === "object" ? { brand: payload.brand } : {}
|
|
6169
6171
|
};
|
|
6170
6172
|
const others = state.sections.filter((existing) => existing.id !== entry.id);
|
|
6171
6173
|
return { ...state, v: 1, sections: [...others, entry] };
|
|
6172
6174
|
}
|
|
6175
|
+
function stripTextAlignCss(html) {
|
|
6176
|
+
return html.replace(/\sstyle="([^"]*)"/gi, (whole, value) => {
|
|
6177
|
+
if (!/text-align\s*:/i.test(value)) return whole;
|
|
6178
|
+
const kept = value.split(";").map((decl) => decl.trim()).filter((decl) => decl && !/^text-align\s*:/i.test(decl)).join("; ");
|
|
6179
|
+
return kept ? ` style="${kept}"` : "";
|
|
6180
|
+
});
|
|
6181
|
+
}
|
|
6182
|
+
function stripTextAlignInValue(value) {
|
|
6183
|
+
if (typeof value === "string") return stripTextAlignCss(value);
|
|
6184
|
+
if (Array.isArray(value)) return value.map(stripTextAlignInValue);
|
|
6185
|
+
if (value && typeof value === "object") {
|
|
6186
|
+
return Object.fromEntries(
|
|
6187
|
+
Object.entries(value).map(([key, inner]) => [
|
|
6188
|
+
key,
|
|
6189
|
+
stripTextAlignInValue(inner)
|
|
6190
|
+
])
|
|
6191
|
+
);
|
|
6192
|
+
}
|
|
6193
|
+
return value;
|
|
6194
|
+
}
|
|
6173
6195
|
function foldAlignIntoTrees(state, store) {
|
|
6174
6196
|
const byId = new Map(state.sections.map((entry) => [entry.id, entry]));
|
|
6175
6197
|
const nextTrees = /* @__PURE__ */ new Map();
|
|
@@ -6192,6 +6214,12 @@ function foldAlignIntoTrees(state, store) {
|
|
|
6192
6214
|
return stripChildAligns(rest);
|
|
6193
6215
|
})
|
|
6194
6216
|
} : node;
|
|
6217
|
+
const stripContentAligns = (node) => ({
|
|
6218
|
+
...node,
|
|
6219
|
+
...node.slots ? { slots: stripTextAlignInValue(node.slots) } : {},
|
|
6220
|
+
...node.children ? { children: node.children.map(stripContentAligns) } : {}
|
|
6221
|
+
});
|
|
6222
|
+
const authoritative = (block) => stripChildAligns(stripContentAligns(block));
|
|
6195
6223
|
const nodes = {};
|
|
6196
6224
|
for (const [key, override] of Object.entries(store.nodes)) {
|
|
6197
6225
|
const match = override.align !== void 0 && key.startsWith(AI_SLOT_KEY_PREFIX) ? key.match(/^ai\.(.+?)\.r(\d+)\.b(\d+)(?:\.|$)/) : null;
|
|
@@ -6203,7 +6231,7 @@ function foldAlignIntoTrees(state, store) {
|
|
|
6203
6231
|
nodes[key] = override;
|
|
6204
6232
|
continue;
|
|
6205
6233
|
}
|
|
6206
|
-
row.blocks[blockIdx] = { ...
|
|
6234
|
+
row.blocks[blockIdx] = { ...authoritative(block), align: override.align };
|
|
6207
6235
|
const rest = { ...override };
|
|
6208
6236
|
delete rest.align;
|
|
6209
6237
|
if (Object.keys(rest).length > 0) nodes[key] = rest;
|
|
@@ -6216,7 +6244,7 @@ function foldAlignIntoTrees(state, store) {
|
|
|
6216
6244
|
continue;
|
|
6217
6245
|
}
|
|
6218
6246
|
for (const row of tree.rows) {
|
|
6219
|
-
row.blocks = row.blocks.map((block) => ({ ...
|
|
6247
|
+
row.blocks = row.blocks.map((block) => ({ ...authoritative(block), align: override.align }));
|
|
6220
6248
|
}
|
|
6221
6249
|
const rest = { ...override };
|
|
6222
6250
|
delete rest.align;
|
|
@@ -9665,6 +9693,46 @@ function FooterSocialRowBlock({
|
|
|
9665
9693
|
}
|
|
9666
9694
|
);
|
|
9667
9695
|
}
|
|
9696
|
+
function EmptySlotPlaceholder({ name }) {
|
|
9697
|
+
return /* @__PURE__ */ jsx(
|
|
9698
|
+
"div",
|
|
9699
|
+
{
|
|
9700
|
+
"data-ai-slot": name,
|
|
9701
|
+
"data-ai-slot-empty": "",
|
|
9702
|
+
"aria-hidden": "true",
|
|
9703
|
+
style: {
|
|
9704
|
+
minHeight: 88,
|
|
9705
|
+
borderRadius: 12,
|
|
9706
|
+
border: "1px dashed #D6D3D1",
|
|
9707
|
+
display: "flex",
|
|
9708
|
+
alignItems: "center",
|
|
9709
|
+
justifyContent: "center",
|
|
9710
|
+
padding: 16,
|
|
9711
|
+
color: "#A8A29E",
|
|
9712
|
+
fontSize: 13,
|
|
9713
|
+
lineHeight: 1.4,
|
|
9714
|
+
textAlign: "center",
|
|
9715
|
+
pointerEvents: "none"
|
|
9716
|
+
},
|
|
9717
|
+
children: "Ask AI to add something here"
|
|
9718
|
+
}
|
|
9719
|
+
);
|
|
9720
|
+
}
|
|
9721
|
+
function splitSides(node) {
|
|
9722
|
+
const named = /* @__PURE__ */ new Map();
|
|
9723
|
+
const unnamed = [];
|
|
9724
|
+
(node.children ?? []).forEach((child, index) => {
|
|
9725
|
+
if (child.slot === "left" || child.slot === "right") {
|
|
9726
|
+
named.set(child.slot, { node: child, index });
|
|
9727
|
+
} else {
|
|
9728
|
+
unnamed.push({ node: child, index });
|
|
9729
|
+
}
|
|
9730
|
+
});
|
|
9731
|
+
return {
|
|
9732
|
+
left: named.get("left") ?? unnamed.shift() ?? null,
|
|
9733
|
+
right: named.get("right") ?? unnamed.shift() ?? null
|
|
9734
|
+
};
|
|
9735
|
+
}
|
|
9668
9736
|
function renderNode(node, ctx, path, ambientAlign) {
|
|
9669
9737
|
const slots = node.slots ?? {};
|
|
9670
9738
|
switch (node.type) {
|
|
@@ -9672,9 +9740,11 @@ function renderNode(node, ctx, path, ambientAlign) {
|
|
|
9672
9740
|
return /* @__PURE__ */ jsx(TextBlock, { slots, ctx, path, align: node.align ?? ambientAlign });
|
|
9673
9741
|
// Layout container: arranges child blocks, contributes no content of its own. `grid` is a
|
|
9674
9742
|
// nested 12-column grid the children span (a collage is 3–5 media on it, bottom-aligned so
|
|
9675
|
-
// mixed aspects read as a composition); `split` is
|
|
9676
|
-
// is a column.
|
|
9677
|
-
//
|
|
9743
|
+
// mixed aspects read as a composition); `split` is left and right (index order when `slot`
|
|
9744
|
+
// is omitted); `stack` is a column. A missing split side is a canvas placeholder only when
|
|
9745
|
+
// `emptySlots` names it. A one-child split used to keep a row at span 12 (a testimonial
|
|
9746
|
+
// under a heading) sits centered at half the row width. Children render through this same
|
|
9747
|
+
// dispatcher, so edit markers, media resolution, and copy paths all work unchanged.
|
|
9678
9748
|
case "group": {
|
|
9679
9749
|
const layout = str(slots.layout);
|
|
9680
9750
|
const gap = slots.spacing === "tight" ? AI_TREE_TOKENS.spacing3 : slots.spacing === "airy" ? AI_TREE_TOKENS.spacing8 : AI_TREE_TOKENS.spacing6;
|
|
@@ -9772,24 +9842,38 @@ function renderNode(node, ctx, path, ambientAlign) {
|
|
|
9772
9842
|
i
|
|
9773
9843
|
));
|
|
9774
9844
|
if (layout === "grid") {
|
|
9775
|
-
|
|
9845
|
+
const holes = ctx.keyFor ? node.emptySlots ?? [] : [];
|
|
9846
|
+
return /* @__PURE__ */ jsxs(
|
|
9776
9847
|
"div",
|
|
9777
9848
|
{
|
|
9778
9849
|
"data-ai-group": "grid",
|
|
9779
9850
|
style: { display: "grid", gridTemplateColumns: "repeat(12, 1fr)", gap, alignItems: "end" },
|
|
9780
|
-
children:
|
|
9851
|
+
children: [
|
|
9852
|
+
kids,
|
|
9853
|
+
holes.map((name) => /* @__PURE__ */ jsx("div", { style: { gridColumn: "span 6", minWidth: 0 }, children: /* @__PURE__ */ jsx(EmptySlotPlaceholder, { name }) }, name))
|
|
9854
|
+
]
|
|
9781
9855
|
}
|
|
9782
9856
|
);
|
|
9783
9857
|
}
|
|
9784
9858
|
if (layout === "split") {
|
|
9859
|
+
const { left, right } = splitSides(node);
|
|
9860
|
+
const open = new Set(ctx.keyFor ? node.emptySlots ?? [] : []);
|
|
9861
|
+
const side = (entry, name) => entry ? /* @__PURE__ */ jsx("div", { style: { minWidth: 0 }, children: renderNode(entry.node, ctx, `${path}.c${entry.index}`) }, name) : open.has(name) ? /* @__PURE__ */ jsx(EmptySlotPlaceholder, { name }, name) : null;
|
|
9862
|
+
if (!left && !open.has("left") || !right && !open.has("right")) {
|
|
9863
|
+
const only = left ?? right;
|
|
9864
|
+
return only ? /* @__PURE__ */ jsx("div", { "data-ai-group": "split", style: { display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ jsx("div", { style: { width: "50%", minWidth: 0 }, children: renderNode(only.node, ctx, `${path}.c${only.index}`) }) }) : null;
|
|
9865
|
+
}
|
|
9785
9866
|
const ratio = str(slots.ratio);
|
|
9786
9867
|
const cols = ratio === "3:5" ? "3fr 5fr" : ratio === "5:3" ? "5fr 3fr" : "1fr 1fr";
|
|
9787
|
-
return /* @__PURE__ */
|
|
9868
|
+
return /* @__PURE__ */ jsxs(
|
|
9788
9869
|
"div",
|
|
9789
9870
|
{
|
|
9790
9871
|
"data-ai-group": "split",
|
|
9791
9872
|
style: { display: "grid", gridTemplateColumns: cols, gap, alignItems: "center" },
|
|
9792
|
-
children:
|
|
9873
|
+
children: [
|
|
9874
|
+
side(left, "left"),
|
|
9875
|
+
side(right, "right")
|
|
9876
|
+
]
|
|
9793
9877
|
}
|
|
9794
9878
|
);
|
|
9795
9879
|
}
|
|
@@ -30066,14 +30150,73 @@ function OhhwellsBridge() {
|
|
|
30066
30150
|
value = JSON.stringify(foldedHeight.store);
|
|
30067
30151
|
}
|
|
30068
30152
|
}
|
|
30153
|
+
const restoreNodes = e.data.restoreNodes;
|
|
30154
|
+
const restored = [];
|
|
30155
|
+
if (restoreNodes && typeof restoreNodes === "object") {
|
|
30156
|
+
for (const [key, html] of Object.entries(restoreNodes)) {
|
|
30157
|
+
if (typeof html !== "string") continue;
|
|
30158
|
+
const els = document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`);
|
|
30159
|
+
if (els.length === 0) continue;
|
|
30160
|
+
for (const el of Array.from(els)) el.innerHTML = html;
|
|
30161
|
+
editContentRef.current = { ...editContentRef.current, [key]: html };
|
|
30162
|
+
restored.push({ key, text: html });
|
|
30163
|
+
}
|
|
30164
|
+
}
|
|
30165
|
+
const previousNodes = {};
|
|
30166
|
+
const strippedNodes = [];
|
|
30167
|
+
if (!restoreNodes) {
|
|
30168
|
+
const aligned = parseStyleStore(value);
|
|
30169
|
+
const prior = parseStyleStore(previous);
|
|
30170
|
+
const keys = /* @__PURE__ */ new Set();
|
|
30171
|
+
if (aligned) {
|
|
30172
|
+
for (const [key, override] of Object.entries(aligned.nodes)) {
|
|
30173
|
+
if (override.align === void 0) continue;
|
|
30174
|
+
if (prior?.nodes[key]?.align === override.align) continue;
|
|
30175
|
+
keys.add(key);
|
|
30176
|
+
}
|
|
30177
|
+
for (const [sectionId, override] of Object.entries(aligned.sections)) {
|
|
30178
|
+
if (override.align === void 0) continue;
|
|
30179
|
+
if (prior?.sections[sectionId]?.align === override.align) continue;
|
|
30180
|
+
const escaped = CSS.escape(sectionId);
|
|
30181
|
+
const markers = document.querySelectorAll(
|
|
30182
|
+
`[data-ohw-instance="${escaped}"], [data-ohw-section="${escaped}"]`
|
|
30183
|
+
);
|
|
30184
|
+
for (const marker of Array.from(markers)) {
|
|
30185
|
+
const editables = marker.querySelectorAll(
|
|
30186
|
+
'[data-ohw-key][data-ohw-editable="text"], [data-ohw-key][data-ohw-editable="plain"]'
|
|
30187
|
+
);
|
|
30188
|
+
for (const el of Array.from(editables)) {
|
|
30189
|
+
const key = el.getAttribute("data-ohw-key");
|
|
30190
|
+
if (key) keys.add(key);
|
|
30191
|
+
}
|
|
30192
|
+
}
|
|
30193
|
+
}
|
|
30194
|
+
}
|
|
30195
|
+
for (const key of keys) {
|
|
30196
|
+
if (key.startsWith(AI_SLOT_KEY_PREFIX) || key.startsWith("__ohw_")) continue;
|
|
30197
|
+
const els = document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`);
|
|
30198
|
+
if (els.length === 0) continue;
|
|
30199
|
+
const before = sanitizeHtml(els[0].innerHTML);
|
|
30200
|
+
const after = stripTextAlignCss(before);
|
|
30201
|
+
if (after === before) continue;
|
|
30202
|
+
for (const el of Array.from(els)) el.innerHTML = after;
|
|
30203
|
+
previousNodes[key] = before;
|
|
30204
|
+
editContentRef.current = { ...editContentRef.current, [key]: after };
|
|
30205
|
+
strippedNodes.push({ key, text: after });
|
|
30206
|
+
}
|
|
30207
|
+
}
|
|
30069
30208
|
stylesRef.current = value;
|
|
30070
30209
|
applyStylesToDom(parseStyleStore(value));
|
|
30071
|
-
postToParentRef.current({
|
|
30210
|
+
postToParentRef.current({
|
|
30211
|
+
type: "ow:change",
|
|
30212
|
+
nodes: [{ key: STYLE_STORE_KEY, text: value }, ...strippedNodes, ...restored]
|
|
30213
|
+
});
|
|
30072
30214
|
postToParentRef.current({
|
|
30073
30215
|
type: "ow:ai-styles-applied",
|
|
30074
30216
|
previous,
|
|
30075
30217
|
value,
|
|
30076
|
-
...previousSections !== void 0 ? { previousSections } : {}
|
|
30218
|
+
...previousSections !== void 0 ? { previousSections } : {},
|
|
30219
|
+
...Object.keys(previousNodes).length > 0 ? { previousNodes } : {}
|
|
30077
30220
|
});
|
|
30078
30221
|
};
|
|
30079
30222
|
window.addEventListener("message", handleAiSetStyles);
|
|
@@ -31418,7 +31561,7 @@ function OhhwellsBridge() {
|
|
|
31418
31561
|
postToParent2({
|
|
31419
31562
|
type: "ow:ready",
|
|
31420
31563
|
version: "1",
|
|
31421
|
-
bridgeVersion: "0.1.
|
|
31564
|
+
bridgeVersion: "0.1.146",
|
|
31422
31565
|
path: pathname,
|
|
31423
31566
|
nodes: collectEditableNodes(editContentRef.current),
|
|
31424
31567
|
sections
|
|
@@ -32648,6 +32791,7 @@ export {
|
|
|
32648
32791
|
resolveFooterCopyright,
|
|
32649
32792
|
serializeAiFooterState,
|
|
32650
32793
|
stepViableSlide,
|
|
32794
|
+
stripTextAlignCss,
|
|
32651
32795
|
toggleVariants,
|
|
32652
32796
|
useOhwCarousel,
|
|
32653
32797
|
validateUrlInput,
|