@ohhwells/bridge 0.1.85 → 0.1.86-next.255
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 +1057 -341
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -1
- package/dist/index.d.ts +15 -1
- package/dist/index.js +1056 -341
- package/dist/index.js.map +1 -1
- package/dist/pages.cjs +141 -0
- package/dist/pages.cjs.map +1 -0
- package/dist/pages.d.cts +45 -0
- package/dist/pages.d.ts +45 -0
- package/dist/pages.js +107 -0
- package/dist/pages.js.map +1 -0
- package/dist/styles.css +55 -0
- package/package.json +8 -3
package/dist/index.cjs
CHANGED
|
@@ -46,6 +46,7 @@ __export(index_exports, {
|
|
|
46
46
|
DropdownMenuItem: () => DropdownMenuItem,
|
|
47
47
|
DropdownMenuSeparator: () => DropdownMenuSeparator,
|
|
48
48
|
DropdownMenuTrigger: () => DropdownMenuTrigger,
|
|
49
|
+
EmptySection: () => EmptySection,
|
|
49
50
|
ItemActionToolbar: () => ItemActionToolbar,
|
|
50
51
|
ItemInteractionLayer: () => ItemInteractionLayer,
|
|
51
52
|
LinkEditorPanel: () => LinkEditorPanel,
|
|
@@ -142,6 +143,10 @@ function isRenderableTree(value) {
|
|
|
142
143
|
|
|
143
144
|
// src/lib/ai-sections-store.ts
|
|
144
145
|
var AI_SECTIONS_KEY = "__ohw_ai_sections";
|
|
146
|
+
var AI_SLOT_KEY_PREFIX = "ai.";
|
|
147
|
+
function aiSlotKeyPrefixFor(sectionId) {
|
|
148
|
+
return `${AI_SLOT_KEY_PREFIX}${sectionId}.`;
|
|
149
|
+
}
|
|
145
150
|
var EMPTY_AI_SECTIONS = { v: 1, sections: [] };
|
|
146
151
|
function parseAiSectionsState(raw) {
|
|
147
152
|
if (!raw) return EMPTY_AI_SECTIONS;
|
|
@@ -185,6 +190,63 @@ function applyTreeToState(state, payload) {
|
|
|
185
190
|
const others = state.sections.filter((existing) => existing.id !== entry.id);
|
|
186
191
|
return { ...state, v: 1, sections: [...others, entry] };
|
|
187
192
|
}
|
|
193
|
+
function foldAlignIntoTrees(state, store) {
|
|
194
|
+
const byId = new Map(state.sections.map((entry) => [entry.id, entry]));
|
|
195
|
+
const nextTrees = /* @__PURE__ */ new Map();
|
|
196
|
+
const treeFor = (id) => {
|
|
197
|
+
const cloned = nextTrees.get(id);
|
|
198
|
+
if (cloned) return cloned;
|
|
199
|
+
const entry = byId.get(id);
|
|
200
|
+
if (!entry) return void 0;
|
|
201
|
+
const fresh = {
|
|
202
|
+
...entry.tree,
|
|
203
|
+
rows: entry.tree.rows.map((row) => ({ ...row, blocks: row.blocks.map((block) => ({ ...block })) }))
|
|
204
|
+
};
|
|
205
|
+
nextTrees.set(id, fresh);
|
|
206
|
+
return fresh;
|
|
207
|
+
};
|
|
208
|
+
const nodes = {};
|
|
209
|
+
for (const [key, override] of Object.entries(store.nodes)) {
|
|
210
|
+
const match = override.align !== void 0 && key.startsWith(AI_SLOT_KEY_PREFIX) ? key.match(/^ai\.(.+?)\.r(\d+)\.b(\d+)(?:\.|$)/) : null;
|
|
211
|
+
const tree = match ? treeFor(match[1]) : void 0;
|
|
212
|
+
const block = match && tree ? tree.rows[Number(match[2])]?.blocks[Number(match[3])] : void 0;
|
|
213
|
+
if (!block) {
|
|
214
|
+
nodes[key] = override;
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
block.align = override.align;
|
|
218
|
+
const rest = { ...override };
|
|
219
|
+
delete rest.align;
|
|
220
|
+
if (Object.keys(rest).length > 0) nodes[key] = rest;
|
|
221
|
+
}
|
|
222
|
+
const sections = {};
|
|
223
|
+
for (const [sectionId, override] of Object.entries(store.sections)) {
|
|
224
|
+
const tree = override.align !== void 0 ? treeFor(sectionId) : void 0;
|
|
225
|
+
if (!tree) {
|
|
226
|
+
sections[sectionId] = override;
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
for (const row of tree.rows) {
|
|
230
|
+
for (const block of row.blocks) block.align = override.align;
|
|
231
|
+
}
|
|
232
|
+
const rest = { ...override };
|
|
233
|
+
delete rest.align;
|
|
234
|
+
if (Object.keys(rest).length > 0) sections[sectionId] = rest;
|
|
235
|
+
}
|
|
236
|
+
if (nextTrees.size === 0) return { state, store, changed: false };
|
|
237
|
+
return {
|
|
238
|
+
state: {
|
|
239
|
+
...state,
|
|
240
|
+
v: 1,
|
|
241
|
+
sections: state.sections.map((entry) => {
|
|
242
|
+
const tree = nextTrees.get(entry.id);
|
|
243
|
+
return tree ? { ...entry, tree } : entry;
|
|
244
|
+
})
|
|
245
|
+
},
|
|
246
|
+
store: { v: 1, sections, nodes },
|
|
247
|
+
changed: true
|
|
248
|
+
};
|
|
249
|
+
}
|
|
188
250
|
function removeFromState(state, id) {
|
|
189
251
|
return { ...state, v: 1, sections: state.sections.filter((entry) => entry.id !== id) };
|
|
190
252
|
}
|
|
@@ -196,6 +258,33 @@ function deleteSectionFromState(state, sectionId) {
|
|
|
196
258
|
if (removed.includes(sectionId)) return state;
|
|
197
259
|
return { ...state, v: 1, sections: state.sections, removed: [...removed, sectionId] };
|
|
198
260
|
}
|
|
261
|
+
function reapRemovedAiSections(state, store, removedIds, excludeIds = /* @__PURE__ */ new Set()) {
|
|
262
|
+
const generated = new Set(state.sections.map((entry) => entry.id));
|
|
263
|
+
const reapedIds = [...new Set(removedIds)].filter((id) => generated.has(id) && !excludeIds.has(id));
|
|
264
|
+
if (reapedIds.length === 0) {
|
|
265
|
+
return { state, store, reapedIds: [], slotPrefixes: [], changed: false };
|
|
266
|
+
}
|
|
267
|
+
const reaped = new Set(reapedIds);
|
|
268
|
+
const slotPrefixes = reapedIds.map(aiSlotKeyPrefixFor);
|
|
269
|
+
const nextState = {
|
|
270
|
+
...state,
|
|
271
|
+
v: 1,
|
|
272
|
+
sections: state.sections.filter((entry) => !reaped.has(entry.id))
|
|
273
|
+
};
|
|
274
|
+
let nextStore = store;
|
|
275
|
+
if (store) {
|
|
276
|
+
const sections = {};
|
|
277
|
+
for (const [key, override] of Object.entries(store.sections)) {
|
|
278
|
+
if (!reaped.has(key)) sections[key] = override;
|
|
279
|
+
}
|
|
280
|
+
const nodes = {};
|
|
281
|
+
for (const [key, override] of Object.entries(store.nodes)) {
|
|
282
|
+
if (!slotPrefixes.some((prefix) => key.startsWith(prefix))) nodes[key] = override;
|
|
283
|
+
}
|
|
284
|
+
nextStore = { v: 1, sections, nodes };
|
|
285
|
+
}
|
|
286
|
+
return { state: nextState, store: nextStore, reapedIds, slotPrefixes, changed: true };
|
|
287
|
+
}
|
|
199
288
|
|
|
200
289
|
// src/lib/brand-chrome.ts
|
|
201
290
|
var BRAND_NAME_KEY = "__ohw_brand_name";
|
|
@@ -403,6 +492,12 @@ function styleSheetCss() {
|
|
|
403
492
|
`[data-ohw-style-spacing="${spacing}"] { padding-top: ${px}px !important; padding-bottom: ${px}px !important; }`
|
|
404
493
|
);
|
|
405
494
|
}
|
|
495
|
+
rules.push(
|
|
496
|
+
`[data-ohw-style-corners="sharp"] :is(.card, [data-ohw-card]) { border-radius: 0 !important; }`
|
|
497
|
+
);
|
|
498
|
+
for (const align of ["left", "center", "right"]) {
|
|
499
|
+
rules.push(`[data-ohw-style-align="${align}"] { text-align: ${align} !important; }`);
|
|
500
|
+
}
|
|
406
501
|
return rules.join("\n");
|
|
407
502
|
}
|
|
408
503
|
var STYLE_FONT_LINK_ID = "ohw-style-fonts";
|
|
@@ -429,10 +524,25 @@ var SECTION_ATTRS = {
|
|
|
429
524
|
textDistribution: "data-ohw-style-distribution",
|
|
430
525
|
headlineScale: "data-ohw-style-headline",
|
|
431
526
|
imageAspect: "data-ohw-style-aspect",
|
|
432
|
-
spacing: "data-ohw-style-spacing"
|
|
527
|
+
spacing: "data-ohw-style-spacing",
|
|
528
|
+
cornerStyle: "data-ohw-style-corners",
|
|
529
|
+
align: "data-ohw-style-align"
|
|
433
530
|
};
|
|
434
531
|
var NODE_WROTE_ATTR = "data-ohw-style-node";
|
|
435
|
-
var NODE_PROPS = [
|
|
532
|
+
var NODE_PROPS = [
|
|
533
|
+
"color",
|
|
534
|
+
"font-family",
|
|
535
|
+
"font-size",
|
|
536
|
+
"background",
|
|
537
|
+
"text-align",
|
|
538
|
+
"justify-content",
|
|
539
|
+
"align-items"
|
|
540
|
+
];
|
|
541
|
+
var ALIGN_JUSTIFY = {
|
|
542
|
+
left: "flex-start",
|
|
543
|
+
center: "center",
|
|
544
|
+
right: "flex-end"
|
|
545
|
+
};
|
|
436
546
|
function saveInline(el, prop) {
|
|
437
547
|
const attr = `data-ohw-style-prev-${prop}`;
|
|
438
548
|
if (el.hasAttribute(attr)) return;
|
|
@@ -476,6 +586,10 @@ function clearNodeProps(root) {
|
|
|
476
586
|
function buttonSurfaceOf(el) {
|
|
477
587
|
return el.closest("a, button") ?? el;
|
|
478
588
|
}
|
|
589
|
+
function alignSubjectOf(el) {
|
|
590
|
+
const button = el.closest('[data-ohw-role="button"]');
|
|
591
|
+
return button?.parentElement ?? el;
|
|
592
|
+
}
|
|
479
593
|
function applyStylesToDom(store) {
|
|
480
594
|
ensureStyleSheet();
|
|
481
595
|
clearSectionAttrs(document);
|
|
@@ -521,6 +635,18 @@ function applyStylesToDom(store) {
|
|
|
521
635
|
el.style.setProperty("font-size", `${override.fontSize}px`, "important");
|
|
522
636
|
el.setAttribute(NODE_WROTE_ATTR, "");
|
|
523
637
|
}
|
|
638
|
+
if (override.align !== void 0) {
|
|
639
|
+
const subject = alignSubjectOf(el);
|
|
640
|
+
saveInline(subject, "text-align");
|
|
641
|
+
saveInline(subject, "justify-content");
|
|
642
|
+
subject.style.setProperty("text-align", override.align, "important");
|
|
643
|
+
subject.style.setProperty(
|
|
644
|
+
"justify-content",
|
|
645
|
+
ALIGN_JUSTIFY[override.align] ?? "flex-start",
|
|
646
|
+
"important"
|
|
647
|
+
);
|
|
648
|
+
subject.setAttribute(NODE_WROTE_ATTR, "");
|
|
649
|
+
}
|
|
524
650
|
if (override.buttonBackground !== void 0 || override.buttonText !== void 0) {
|
|
525
651
|
const surface = buttonSurfaceOf(el);
|
|
526
652
|
if (override.buttonBackground !== void 0) {
|
|
@@ -541,9 +667,494 @@ function applyStylesToDom(store) {
|
|
|
541
667
|
var import_react_dom = require("react-dom");
|
|
542
668
|
var import_client = require("react-dom/client");
|
|
543
669
|
|
|
670
|
+
// src/lib/sections.ts
|
|
671
|
+
var LINK_PICKER_EXCLUDED_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
|
|
672
|
+
function isChromeSection(el) {
|
|
673
|
+
return el.matches("header, nav, footer, aside");
|
|
674
|
+
}
|
|
675
|
+
function titleCaseSectionId(id) {
|
|
676
|
+
return id.split("-").filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
677
|
+
}
|
|
678
|
+
function parseSectionsFromRoot(root) {
|
|
679
|
+
const seen = /* @__PURE__ */ new Set();
|
|
680
|
+
const sections = [];
|
|
681
|
+
for (const el of root.querySelectorAll("[data-ohw-section]")) {
|
|
682
|
+
const id = el.getAttribute("data-ohw-section") ?? "";
|
|
683
|
+
if (!id || seen.has(id) || LINK_PICKER_EXCLUDED_IDS.has(id)) continue;
|
|
684
|
+
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
685
|
+
if (el.hasAttribute("data-ohw-ai-template-hidden") || el.hasAttribute("data-ohw-ai-removed") || el.hasAttribute("data-ohw-ai-replaced-by"))
|
|
686
|
+
continue;
|
|
687
|
+
seen.add(id);
|
|
688
|
+
const label = el.getAttribute("data-ohw-section-label") ?? titleCaseSectionId(id);
|
|
689
|
+
sections.push({ id, label });
|
|
690
|
+
}
|
|
691
|
+
return sections;
|
|
692
|
+
}
|
|
693
|
+
function collectSectionsFromDom() {
|
|
694
|
+
if (typeof document === "undefined") return [];
|
|
695
|
+
return parseSectionsFromRoot(document);
|
|
696
|
+
}
|
|
697
|
+
function parseSectionsFromHtml(html) {
|
|
698
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
699
|
+
return parseSectionsFromRoot(doc);
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// src/lib/section-instances.ts
|
|
703
|
+
var SECTION_ORDER_KEY = "__ohw_section_order";
|
|
704
|
+
var REMOVED_ATTR = "data-ohw-section-removed";
|
|
705
|
+
function isRemovedSection(el) {
|
|
706
|
+
return el.hasAttribute(REMOVED_ATTR);
|
|
707
|
+
}
|
|
708
|
+
function topLevelSections() {
|
|
709
|
+
return Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
|
|
710
|
+
(el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el) && !isRemovedSection(el)
|
|
711
|
+
);
|
|
712
|
+
}
|
|
713
|
+
function instanceIdOf(el) {
|
|
714
|
+
return el.dataset.ohwInstance ?? el.dataset.ohwSection ?? "";
|
|
715
|
+
}
|
|
716
|
+
function findByInstanceId(instanceId) {
|
|
717
|
+
const escapedId = CSS.escape(instanceId);
|
|
718
|
+
return document.querySelector(`[data-ohw-instance="${escapedId}"]`) ?? document.querySelector(`[data-ohw-section="${escapedId}"]:not([data-ohw-instance])`);
|
|
719
|
+
}
|
|
720
|
+
function planSectionMove(instanceId, targetIndex, currentPath) {
|
|
721
|
+
const sections = topLevelSections();
|
|
722
|
+
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
723
|
+
if (index === -1) return null;
|
|
724
|
+
const dragged = sections[index];
|
|
725
|
+
const others = sections.filter((_, i) => i !== index);
|
|
726
|
+
const clamped = Math.max(0, Math.min(targetIndex, others.length));
|
|
727
|
+
const reordered = [...others.slice(0, clamped), dragged, ...others.slice(clamped)];
|
|
728
|
+
return reordered.map((el, order) => ({
|
|
729
|
+
instanceId: instanceIdOf(el),
|
|
730
|
+
type: el.getAttribute("data-ohw-section") ?? "",
|
|
731
|
+
order,
|
|
732
|
+
pagePath: currentPath
|
|
733
|
+
}));
|
|
734
|
+
}
|
|
735
|
+
function moveSectionInstance(instanceId, direction, currentPath) {
|
|
736
|
+
const sections = topLevelSections();
|
|
737
|
+
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
738
|
+
if (index === -1) return null;
|
|
739
|
+
const siblingIndex = direction === "up" ? index - 1 : index + 1;
|
|
740
|
+
if (siblingIndex < 0 || siblingIndex >= sections.length) return null;
|
|
741
|
+
const entries = planSectionMove(instanceId, siblingIndex, currentPath);
|
|
742
|
+
if (!entries) return null;
|
|
743
|
+
applyPersistedOrder(entries);
|
|
744
|
+
return entries;
|
|
745
|
+
}
|
|
746
|
+
function syncRemovedFlags(entries) {
|
|
747
|
+
const removedIds = new Set(entries.filter((e) => e.removed).map((e) => e.instanceId));
|
|
748
|
+
document.querySelectorAll(`[${REMOVED_ATTR}]`).forEach((el) => {
|
|
749
|
+
if (!removedIds.has(instanceIdOf(el))) {
|
|
750
|
+
el.style.removeProperty("display");
|
|
751
|
+
el.removeAttribute(REMOVED_ATTR);
|
|
752
|
+
}
|
|
753
|
+
});
|
|
754
|
+
for (const id of removedIds) {
|
|
755
|
+
const el = findByInstanceId(id);
|
|
756
|
+
if (el) {
|
|
757
|
+
el.style.display = "none";
|
|
758
|
+
el.setAttribute(REMOVED_ATTR, "");
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
function applyPersistedOrder(entries) {
|
|
763
|
+
syncRemovedFlags(entries);
|
|
764
|
+
if (entries.length === 0) return;
|
|
765
|
+
const sections = topLevelSections();
|
|
766
|
+
if (sections.length === 0) return;
|
|
767
|
+
const orderIndex = new Map(entries.map((e) => [e.instanceId, e.order]));
|
|
768
|
+
const ordered = [...sections].sort((a, b) => {
|
|
769
|
+
const aOrder = orderIndex.get(instanceIdOf(a));
|
|
770
|
+
const bOrder = orderIndex.get(instanceIdOf(b));
|
|
771
|
+
if (aOrder === void 0 && bOrder === void 0) return 0;
|
|
772
|
+
if (aOrder === void 0) return 1;
|
|
773
|
+
if (bOrder === void 0) return -1;
|
|
774
|
+
return aOrder - bOrder;
|
|
775
|
+
});
|
|
776
|
+
let prev = null;
|
|
777
|
+
for (const el of ordered) {
|
|
778
|
+
if (prev) prev.after(el);
|
|
779
|
+
prev = el;
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
function setSectionRemoved(instanceId, currentPath, existingEntries, removed) {
|
|
783
|
+
if (!findByInstanceId(instanceId)) return null;
|
|
784
|
+
const byId = new Map(existingEntries.map((e) => [e.instanceId, e]));
|
|
785
|
+
const allSections = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
|
|
786
|
+
(el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el)
|
|
787
|
+
);
|
|
788
|
+
allSections.forEach((el, order) => {
|
|
789
|
+
const id = instanceIdOf(el);
|
|
790
|
+
if (!byId.has(id)) {
|
|
791
|
+
byId.set(id, { instanceId: id, type: el.getAttribute("data-ohw-section") ?? "", order, pagePath: currentPath });
|
|
792
|
+
}
|
|
793
|
+
});
|
|
794
|
+
const target = byId.get(instanceId);
|
|
795
|
+
if (!target) return null;
|
|
796
|
+
byId.set(instanceId, { ...target, removed });
|
|
797
|
+
const entries = Array.from(byId.values());
|
|
798
|
+
applyPersistedOrder(entries);
|
|
799
|
+
return entries;
|
|
800
|
+
}
|
|
801
|
+
function deleteSectionInstance(instanceId, currentPath, existingEntries) {
|
|
802
|
+
return setSectionRemoved(instanceId, currentPath, existingEntries, true);
|
|
803
|
+
}
|
|
804
|
+
function restoreSectionInstance(instanceId, currentPath, existingEntries) {
|
|
805
|
+
return setSectionRemoved(instanceId, currentPath, existingEntries, false);
|
|
806
|
+
}
|
|
807
|
+
function duplicateSectionInstance(instanceId, newId, currentPath, existingEntries) {
|
|
808
|
+
const original = findByInstanceId(instanceId);
|
|
809
|
+
if (!original) return null;
|
|
810
|
+
const clone = original.cloneNode(true);
|
|
811
|
+
clone.setAttribute("data-ohw-instance", newId);
|
|
812
|
+
const keyRekeys = rekeySectionSubtree(clone, newId);
|
|
813
|
+
original.insertAdjacentElement("afterend", clone);
|
|
814
|
+
const byId = new Map(existingEntries.map((e) => [e.instanceId, e]));
|
|
815
|
+
const entries = topLevelSections().map((el, order) => {
|
|
816
|
+
const id = instanceIdOf(el);
|
|
817
|
+
return {
|
|
818
|
+
instanceId: id,
|
|
819
|
+
type: el.getAttribute("data-ohw-section") ?? "",
|
|
820
|
+
order,
|
|
821
|
+
pagePath: currentPath,
|
|
822
|
+
...byId.get(id)?.removed ? { removed: true } : {}
|
|
823
|
+
};
|
|
824
|
+
});
|
|
825
|
+
applyPersistedOrder(entries);
|
|
826
|
+
return { entries, keyRekeys };
|
|
827
|
+
}
|
|
828
|
+
function newInstanceId() {
|
|
829
|
+
return typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `instance-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
830
|
+
}
|
|
831
|
+
function getPageSectionOrderEntries(raw, currentPath) {
|
|
832
|
+
if (!raw) return [];
|
|
833
|
+
try {
|
|
834
|
+
const entries = JSON.parse(raw);
|
|
835
|
+
return entries.filter((e) => !e.pagePath || e.pagePath === currentPath);
|
|
836
|
+
} catch {
|
|
837
|
+
return [];
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
function rekeySectionSubtree(root, instanceId) {
|
|
841
|
+
const suffix = `::${instanceId}`;
|
|
842
|
+
const pairs = [];
|
|
843
|
+
const rekey = (el, attr) => {
|
|
844
|
+
const current = el.getAttribute(attr);
|
|
845
|
+
if (!current) return;
|
|
846
|
+
const base = current.includes("::") ? current.slice(0, current.indexOf("::")) : current;
|
|
847
|
+
const next = `${base}${suffix}`;
|
|
848
|
+
el.setAttribute(attr, next);
|
|
849
|
+
pairs.push({ from: current, to: next });
|
|
850
|
+
};
|
|
851
|
+
if (root.hasAttribute("data-ohw-key")) rekey(root, "data-ohw-key");
|
|
852
|
+
if (root.hasAttribute("data-ohw-href-key")) rekey(root, "data-ohw-href-key");
|
|
853
|
+
root.querySelectorAll("[data-ohw-key]").forEach((el) => rekey(el, "data-ohw-key"));
|
|
854
|
+
root.querySelectorAll("[data-ohw-href-key]").forEach((el) => rekey(el, "data-ohw-href-key"));
|
|
855
|
+
return pairs;
|
|
856
|
+
}
|
|
857
|
+
function initSectionInstancesFromContent(content, currentPath) {
|
|
858
|
+
document.querySelectorAll("[data-ohw-section]:not([data-ohw-instance])").forEach((el) => {
|
|
859
|
+
el.setAttribute("data-ohw-instance", el.getAttribute("data-ohw-section") ?? "");
|
|
860
|
+
});
|
|
861
|
+
const entries = getPageSectionOrderEntries(content[SECTION_ORDER_KEY], currentPath);
|
|
862
|
+
for (const entry of entries) {
|
|
863
|
+
if (entry.instanceId === entry.type) continue;
|
|
864
|
+
if (document.querySelector(`[data-ohw-instance="${CSS.escape(entry.instanceId)}"]`)) continue;
|
|
865
|
+
const original = document.querySelector(
|
|
866
|
+
`[data-ohw-section="${CSS.escape(entry.type)}"][data-ohw-instance="${CSS.escape(entry.type)}"]`
|
|
867
|
+
);
|
|
868
|
+
if (!original) continue;
|
|
869
|
+
const clone = original.cloneNode(true);
|
|
870
|
+
clone.setAttribute("data-ohw-instance", entry.instanceId);
|
|
871
|
+
rekeySectionSubtree(clone, entry.instanceId);
|
|
872
|
+
original.insertAdjacentElement("afterend", clone);
|
|
873
|
+
}
|
|
874
|
+
applyPersistedOrder(entries);
|
|
875
|
+
}
|
|
876
|
+
|
|
544
877
|
// src/ui/ai-tree/AiTreeRenderer.tsx
|
|
545
878
|
var import_react = __toESM(require("react"), 1);
|
|
546
879
|
var import_lucide_react = require("lucide-react");
|
|
880
|
+
|
|
881
|
+
// src/lib/placeholder-imagery.ts
|
|
882
|
+
var U = (id) => `https://images.unsplash.com/photo-${id}?auto=format&fit=crop&w=1600&q=80`;
|
|
883
|
+
var GENERIC = [
|
|
884
|
+
U("1441986300917-64674bd600d8"),
|
|
885
|
+
U("1486406146926-c627a92ad1ab"),
|
|
886
|
+
U("1497032628192-86f99bcd76bc"),
|
|
887
|
+
U("1521737604893-d14cc237f11d"),
|
|
888
|
+
U("1522071820081-009f0129c71c"),
|
|
889
|
+
U("1519389950473-47ba0277781c"),
|
|
890
|
+
U("1460925895917-afdab827c52f"),
|
|
891
|
+
U("1504384308090-c894fdcc538d")
|
|
892
|
+
];
|
|
893
|
+
var PEOPLE = [
|
|
894
|
+
U("1500648767791-00dcc994a43e"),
|
|
895
|
+
U("1494790108377-be9c29b29330"),
|
|
896
|
+
U("1507003211169-0a1dd7228f2d"),
|
|
897
|
+
U("1438761681033-6461ffad8d80"),
|
|
898
|
+
U("1544005313-94ddf0286df2"),
|
|
899
|
+
U("1472099645785-5658abf4ff4e"),
|
|
900
|
+
U("1519085360753-af0119f7cbe7"),
|
|
901
|
+
U("1534528741775-53994a69daeb")
|
|
902
|
+
];
|
|
903
|
+
var THEMED = [
|
|
904
|
+
{
|
|
905
|
+
keywords: ["portrait", "headshot", "person", "people", "team", "staff", "avatar", "founder", "face"],
|
|
906
|
+
pool: PEOPLE
|
|
907
|
+
},
|
|
908
|
+
{
|
|
909
|
+
keywords: ["pet", "dog", "cat", "puppy", "kitten", "vet", "animal"],
|
|
910
|
+
pool: [
|
|
911
|
+
U("1548199973-03cce0bbc87b"),
|
|
912
|
+
U("1450778869180-41d0601e046e"),
|
|
913
|
+
U("1583511655857-d19b40a7a54e"),
|
|
914
|
+
U("1587300003388-59208cc962cb"),
|
|
915
|
+
U("1517849845537-4d257902454a"),
|
|
916
|
+
U("1601758228041-f3b2795255f1")
|
|
917
|
+
]
|
|
918
|
+
},
|
|
919
|
+
{
|
|
920
|
+
keywords: [
|
|
921
|
+
"baker",
|
|
922
|
+
"bakery",
|
|
923
|
+
"cafe",
|
|
924
|
+
"coffee",
|
|
925
|
+
"latte",
|
|
926
|
+
"restaurant",
|
|
927
|
+
"pastr",
|
|
928
|
+
"bread",
|
|
929
|
+
"cake",
|
|
930
|
+
"cater",
|
|
931
|
+
"chef",
|
|
932
|
+
"kitchen",
|
|
933
|
+
"food",
|
|
934
|
+
"pizza",
|
|
935
|
+
"dessert",
|
|
936
|
+
"brunch",
|
|
937
|
+
"bistro",
|
|
938
|
+
"deli",
|
|
939
|
+
"dish",
|
|
940
|
+
"menu"
|
|
941
|
+
],
|
|
942
|
+
pool: [
|
|
943
|
+
U("1509440159596-0249088772ff"),
|
|
944
|
+
U("1555507036-ab1f4038808a"),
|
|
945
|
+
U("1517433670267-08bbd4be890f"),
|
|
946
|
+
U("1486427944299-d1955d23e34d"),
|
|
947
|
+
U("1504754524776-8f4f37790ca0"),
|
|
948
|
+
U("1495474472287-4d71bcdd2085"),
|
|
949
|
+
U("1521017432531-fbd92d768814"),
|
|
950
|
+
U("1556909114-f6e7ad7d3136")
|
|
951
|
+
]
|
|
952
|
+
},
|
|
953
|
+
{
|
|
954
|
+
keywords: [
|
|
955
|
+
"shop",
|
|
956
|
+
"store",
|
|
957
|
+
"boutique",
|
|
958
|
+
"retail",
|
|
959
|
+
"clothing",
|
|
960
|
+
"fashion",
|
|
961
|
+
"jewel",
|
|
962
|
+
"gift",
|
|
963
|
+
"florist",
|
|
964
|
+
"market",
|
|
965
|
+
"grocer",
|
|
966
|
+
"product",
|
|
967
|
+
"storefront"
|
|
968
|
+
],
|
|
969
|
+
pool: [
|
|
970
|
+
U("1441984904996-e0b6ba687e04"),
|
|
971
|
+
U("1472851294608-062f824d29cc"),
|
|
972
|
+
U("1523381210434-271e8be1f52b"),
|
|
973
|
+
U("1534452203293-494d7ddbf7e0"),
|
|
974
|
+
U("1445205170230-053b83016050"),
|
|
975
|
+
U("1560243563-062bfc001d68")
|
|
976
|
+
]
|
|
977
|
+
},
|
|
978
|
+
{
|
|
979
|
+
keywords: [
|
|
980
|
+
"yoga",
|
|
981
|
+
"pilates",
|
|
982
|
+
"fitness",
|
|
983
|
+
"gym",
|
|
984
|
+
"workout",
|
|
985
|
+
"trainer",
|
|
986
|
+
"wellness",
|
|
987
|
+
"meditat",
|
|
988
|
+
"massage",
|
|
989
|
+
"therap",
|
|
990
|
+
"physio",
|
|
991
|
+
"chiro",
|
|
992
|
+
"nutrition",
|
|
993
|
+
"spa",
|
|
994
|
+
"studio"
|
|
995
|
+
],
|
|
996
|
+
pool: [
|
|
997
|
+
U("1544367567-0f2fcb009e0b"),
|
|
998
|
+
U("1506126613408-eca07ce68773"),
|
|
999
|
+
U("1545205597-3d9d02c29597"),
|
|
1000
|
+
U("1552196563-55cd4e45efb3"),
|
|
1001
|
+
U("1518611012118-696072aa579a"),
|
|
1002
|
+
U("1571019613454-1cb2f99b2d8b"),
|
|
1003
|
+
U("1540555700478-4be289fbecef"),
|
|
1004
|
+
U("1519824145371-296894a0daa9")
|
|
1005
|
+
]
|
|
1006
|
+
},
|
|
1007
|
+
{
|
|
1008
|
+
keywords: [
|
|
1009
|
+
"salon",
|
|
1010
|
+
"hairdress",
|
|
1011
|
+
"haircut",
|
|
1012
|
+
"barber",
|
|
1013
|
+
"manicure",
|
|
1014
|
+
"pedicure",
|
|
1015
|
+
"nails",
|
|
1016
|
+
"beauty",
|
|
1017
|
+
"makeup",
|
|
1018
|
+
"cosmetic",
|
|
1019
|
+
"eyelash",
|
|
1020
|
+
"eyebrow",
|
|
1021
|
+
"skincare",
|
|
1022
|
+
"esthetic",
|
|
1023
|
+
"waxing",
|
|
1024
|
+
"hair"
|
|
1025
|
+
],
|
|
1026
|
+
pool: [
|
|
1027
|
+
U("1560066984-138dadb4c035"),
|
|
1028
|
+
U("1522337660859-02fbefca4702"),
|
|
1029
|
+
U("1562322140-8baeececf3df"),
|
|
1030
|
+
U("1521590832167-7bcbfaa6381f"),
|
|
1031
|
+
U("1487412947147-5cebf100ffc2"),
|
|
1032
|
+
U("1526045478516-99145907023c")
|
|
1033
|
+
]
|
|
1034
|
+
},
|
|
1035
|
+
{
|
|
1036
|
+
keywords: [
|
|
1037
|
+
"cleaning",
|
|
1038
|
+
"plumb",
|
|
1039
|
+
"electric",
|
|
1040
|
+
"landscap",
|
|
1041
|
+
"contractor",
|
|
1042
|
+
"handyman",
|
|
1043
|
+
"renov",
|
|
1044
|
+
"hvac",
|
|
1045
|
+
"roofing",
|
|
1046
|
+
"painting",
|
|
1047
|
+
"carpentry",
|
|
1048
|
+
"flooring",
|
|
1049
|
+
"movers",
|
|
1050
|
+
"construction",
|
|
1051
|
+
"tools"
|
|
1052
|
+
],
|
|
1053
|
+
pool: [
|
|
1054
|
+
U("1581578731548-c64695cc6952"),
|
|
1055
|
+
U("1504307651254-35680f356dfd"),
|
|
1056
|
+
U("1581092160562-40aa08e78837"),
|
|
1057
|
+
U("1621905251189-08b45d6a269e"),
|
|
1058
|
+
U("1558618666-fcd25c85cd64"),
|
|
1059
|
+
U("1585128792020-803d29415281")
|
|
1060
|
+
]
|
|
1061
|
+
},
|
|
1062
|
+
{
|
|
1063
|
+
keywords: [
|
|
1064
|
+
"legal",
|
|
1065
|
+
"attorney",
|
|
1066
|
+
"lawyer",
|
|
1067
|
+
"account",
|
|
1068
|
+
"bookkeep",
|
|
1069
|
+
"consult",
|
|
1070
|
+
"coaching",
|
|
1071
|
+
"financ",
|
|
1072
|
+
"insurance",
|
|
1073
|
+
"realtor",
|
|
1074
|
+
"estate",
|
|
1075
|
+
"marketing",
|
|
1076
|
+
"agency",
|
|
1077
|
+
"office",
|
|
1078
|
+
"business",
|
|
1079
|
+
"desk"
|
|
1080
|
+
],
|
|
1081
|
+
pool: [
|
|
1082
|
+
U("1497366216548-37526070297c"),
|
|
1083
|
+
U("1497366811353-6870744d04b2"),
|
|
1084
|
+
U("1454165804606-c3d57bc86b40"),
|
|
1085
|
+
U("1521791136064-7986c2920216"),
|
|
1086
|
+
U("1556761175-b413da4baf72"),
|
|
1087
|
+
U("1542744173-8e7e53415bb0")
|
|
1088
|
+
]
|
|
1089
|
+
},
|
|
1090
|
+
{
|
|
1091
|
+
keywords: [
|
|
1092
|
+
"wedding",
|
|
1093
|
+
"event",
|
|
1094
|
+
"party",
|
|
1095
|
+
"celebrat",
|
|
1096
|
+
"venue",
|
|
1097
|
+
"community",
|
|
1098
|
+
"nonprofit",
|
|
1099
|
+
"charity",
|
|
1100
|
+
"workshop",
|
|
1101
|
+
"photograph",
|
|
1102
|
+
"concert"
|
|
1103
|
+
],
|
|
1104
|
+
pool: [
|
|
1105
|
+
U("1511578314322-379afb476865"),
|
|
1106
|
+
U("1501281668745-f7f57925c3b4"),
|
|
1107
|
+
U("1523580494863-6f3031224c94"),
|
|
1108
|
+
U("1540575467063-178a50c2df87"),
|
|
1109
|
+
U("1505236858219-8359eb29e329"),
|
|
1110
|
+
U("1528605248644-14dd04022da1")
|
|
1111
|
+
]
|
|
1112
|
+
}
|
|
1113
|
+
];
|
|
1114
|
+
function poolForSubject(subject) {
|
|
1115
|
+
for (const theme of THEMED) {
|
|
1116
|
+
if (theme.keywords.some((k) => subject.includes(k))) {
|
|
1117
|
+
return theme.pool;
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
return GENERIC;
|
|
1121
|
+
}
|
|
1122
|
+
function mixedHash(text) {
|
|
1123
|
+
let hash = 2166136261;
|
|
1124
|
+
for (let i = 0; i < text.length; i++) {
|
|
1125
|
+
hash ^= text.charCodeAt(i);
|
|
1126
|
+
hash = Math.imul(hash, 16777619);
|
|
1127
|
+
}
|
|
1128
|
+
return hash >>> 16 & 65535;
|
|
1129
|
+
}
|
|
1130
|
+
function resolvePlaceholderRef(ref) {
|
|
1131
|
+
const match = /^placeholder:([a-z0-9-]+)$/.exec(ref);
|
|
1132
|
+
if (!match) return null;
|
|
1133
|
+
const subject = match[1];
|
|
1134
|
+
const pool = poolForSubject(subject.replace(/-\d+$/, ""));
|
|
1135
|
+
return pool[mixedHash(ref) % pool.length];
|
|
1136
|
+
}
|
|
1137
|
+
function collectPlaceholderRefs(tree) {
|
|
1138
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1139
|
+
for (const match of JSON.stringify(tree ?? null).matchAll(/"(placeholder:[a-z0-9-]+)"/gu)) {
|
|
1140
|
+
seen.add(match[1]);
|
|
1141
|
+
}
|
|
1142
|
+
return [...seen];
|
|
1143
|
+
}
|
|
1144
|
+
function buildPlaceholderMap(tree) {
|
|
1145
|
+
const map = {};
|
|
1146
|
+
const cursor = /* @__PURE__ */ new Map();
|
|
1147
|
+
for (const ref of collectPlaceholderRefs(tree)) {
|
|
1148
|
+
const subject = ref.slice("placeholder:".length).replace(/-\d+$/, "");
|
|
1149
|
+
const pool = poolForSubject(subject);
|
|
1150
|
+
const start = cursor.get(pool) ?? mixedHash(ref) % pool.length;
|
|
1151
|
+
map[ref] = pool[start % pool.length];
|
|
1152
|
+
cursor.set(pool, start + 1);
|
|
1153
|
+
}
|
|
1154
|
+
return map;
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
// src/ui/ai-tree/AiTreeRenderer.tsx
|
|
547
1158
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
548
1159
|
function lucideByName(name) {
|
|
549
1160
|
const pascal = name.split("-").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
@@ -557,6 +1168,7 @@ var typeStyle = (spec, font) => ({
|
|
|
557
1168
|
fontWeight: spec.weight
|
|
558
1169
|
});
|
|
559
1170
|
var str = (value) => typeof value === "string" ? value : "";
|
|
1171
|
+
var cardRadius = (slots) => slots.cornerStyle === "sharp" ? 0 : AI_TREE_TOKENS.radiusCard;
|
|
560
1172
|
var featureLines = (value) => value.split(/\n|<br\s*\/?>/i).map((line) => line.trim()).filter(Boolean);
|
|
561
1173
|
var CHECK_MASK = `data:image/svg+xml,${encodeURIComponent(
|
|
562
1174
|
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>'
|
|
@@ -616,6 +1228,22 @@ function accentBandContext(brand) {
|
|
|
616
1228
|
function textAttrs(ctx, path) {
|
|
617
1229
|
return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
|
|
618
1230
|
}
|
|
1231
|
+
var AI_RESPONSIVE_CSS = [
|
|
1232
|
+
"@media (max-width: 960px) {",
|
|
1233
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: repeat(2, 1fr) !important; }",
|
|
1234
|
+
' [data-ai-responsive] [data-ai-grid="1"] { grid-template-columns: 1fr !important; }',
|
|
1235
|
+
"}",
|
|
1236
|
+
"@media (max-width: 640px) {",
|
|
1237
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
|
|
1238
|
+
" [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
|
|
1239
|
+
// Group containers flatten to a column on phones; span placements come along for free.
|
|
1240
|
+
" [data-ai-responsive] [data-ai-group] { display: flex !important; flex-direction: column !important; }",
|
|
1241
|
+
" [data-ai-responsive] [data-ai-group] > * { grid-column: auto !important; }",
|
|
1242
|
+
" [data-ai-responsive] [data-ai-section-inner] { padding-left: 20px !important; padding-right: 20px !important; }",
|
|
1243
|
+
" [data-ai-responsive] { overflow-x: hidden; }",
|
|
1244
|
+
" [data-ai-responsive] img { max-width: 100%; }",
|
|
1245
|
+
"}"
|
|
1246
|
+
].join("\n");
|
|
619
1247
|
var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
620
1248
|
function MediaBox({
|
|
621
1249
|
refValue,
|
|
@@ -628,13 +1256,17 @@ function MediaBox({
|
|
|
628
1256
|
const url = refValue ? ctx.resolveMedia(refValue) : null;
|
|
629
1257
|
const isIcon = /^(lucide|simple):/.test(refValue);
|
|
630
1258
|
const aspectRatio = aspect && /^\d+:\d+$/.test(aspect) ? aspect.replace(":", " / ") : void 0;
|
|
631
|
-
const editAttrs = ctx.keyFor && editPath
|
|
1259
|
+
const editAttrs = ctx.keyFor && editPath ? {
|
|
1260
|
+
"data-ohw-key": ctx.keyFor(editPath),
|
|
1261
|
+
"data-ohw-editable": isIcon ? "icon" : "image"
|
|
1262
|
+
} : {};
|
|
632
1263
|
if (isIcon) {
|
|
633
1264
|
const Icon = refValue.startsWith("lucide:") ? lucideByName(refValue.slice(7)) : null;
|
|
634
1265
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
635
1266
|
"span",
|
|
636
1267
|
{
|
|
637
1268
|
"data-ai-icon": refValue,
|
|
1269
|
+
...editAttrs,
|
|
638
1270
|
style: {
|
|
639
1271
|
display: "inline-flex",
|
|
640
1272
|
width: 48,
|
|
@@ -729,7 +1361,7 @@ function TextBlock({ slots, ctx, path }) {
|
|
|
729
1361
|
}
|
|
730
1362
|
function SectionHeaderBlock({ node, ctx, path }) {
|
|
731
1363
|
const slots = node.slots ?? {};
|
|
732
|
-
const align = slots.alignment === "center" ? "center" : "left";
|
|
1364
|
+
const align = node.align ?? (slots.alignment === "center" ? "center" : "left");
|
|
733
1365
|
const children = node.children ?? [];
|
|
734
1366
|
const buttonRowIdx = children.findIndex((c) => c.type === "button-row");
|
|
735
1367
|
const buttonRow = buttonRowIdx >= 0 ? children[buttonRowIdx] : void 0;
|
|
@@ -773,7 +1405,7 @@ function SectionHeaderBlock({ node, ctx, path }) {
|
|
|
773
1405
|
display: "flex",
|
|
774
1406
|
gap: AI_TREE_TOKENS.spacing6,
|
|
775
1407
|
marginTop: AI_TREE_TOKENS.spacing8,
|
|
776
|
-
justifyContent: align === "center" ? "center" : "flex-start"
|
|
1408
|
+
justifyContent: align === "center" ? "center" : align === "right" ? "flex-end" : "flex-start"
|
|
777
1409
|
},
|
|
778
1410
|
children: (buttonRow.children ?? []).map((button, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
779
1411
|
ButtonEl,
|
|
@@ -879,10 +1511,11 @@ function PricingCard({ node, ctx, path }) {
|
|
|
879
1511
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
880
1512
|
"div",
|
|
881
1513
|
{
|
|
1514
|
+
"data-ohw-card": "",
|
|
882
1515
|
style: {
|
|
883
1516
|
background: hasBg ? ctx.brand.palette.light : "transparent",
|
|
884
1517
|
border: `1px solid ${dark}`,
|
|
885
|
-
borderRadius:
|
|
1518
|
+
borderRadius: cardRadius(slots),
|
|
886
1519
|
padding: AI_TREE_TOKENS.paddingBlock,
|
|
887
1520
|
display: "flex",
|
|
888
1521
|
flexDirection: "column",
|
|
@@ -987,10 +1620,11 @@ function TestimonialCard({ node, ctx, path }) {
|
|
|
987
1620
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
988
1621
|
"div",
|
|
989
1622
|
{
|
|
1623
|
+
"data-ohw-card": "",
|
|
990
1624
|
"data-ai-avatar-pos": avatarPos ?? void 0,
|
|
991
1625
|
style: {
|
|
992
1626
|
background: hasBg ? ctx.cardSurface : "transparent",
|
|
993
|
-
borderRadius: hasBg ?
|
|
1627
|
+
borderRadius: hasBg ? cardRadius(slots) : 0,
|
|
994
1628
|
overflow: "hidden",
|
|
995
1629
|
outline: slots.featured === true ? `2px solid ${ctx.brand.palette.primary}` : void 0,
|
|
996
1630
|
minWidth: 0
|
|
@@ -1025,10 +1659,11 @@ function TeamCard({ node, ctx, path }) {
|
|
|
1025
1659
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1026
1660
|
"div",
|
|
1027
1661
|
{
|
|
1662
|
+
"data-ohw-card": "",
|
|
1028
1663
|
"data-ai-avatar-pos": avatarPos ?? void 0,
|
|
1029
1664
|
style: {
|
|
1030
1665
|
background: hasBg ? ctx.cardSurface : "transparent",
|
|
1031
|
-
borderRadius: hasBg ?
|
|
1666
|
+
borderRadius: hasBg ? cardRadius(slots) : 0,
|
|
1032
1667
|
overflow: "hidden",
|
|
1033
1668
|
outline: slots.featured === true ? `2px solid ${ctx.brand.palette.primary}` : void 0,
|
|
1034
1669
|
minWidth: 0,
|
|
@@ -1106,7 +1741,7 @@ function CardBlock({ node, ctx, path }) {
|
|
|
1106
1741
|
editPath: `${path}.media`
|
|
1107
1742
|
}
|
|
1108
1743
|
) : null;
|
|
1109
|
-
const centered = slots.alignment === "center";
|
|
1744
|
+
const centered = (node.align ?? slots.alignment) === "center";
|
|
1110
1745
|
const content = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1111
1746
|
"div",
|
|
1112
1747
|
{
|
|
@@ -1199,9 +1834,10 @@ function CardBlock({ node, ctx, path }) {
|
|
|
1199
1834
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1200
1835
|
"div",
|
|
1201
1836
|
{
|
|
1837
|
+
"data-ohw-card": "",
|
|
1202
1838
|
style: {
|
|
1203
1839
|
background: hasBg ? ctx.cardSurface : "transparent",
|
|
1204
|
-
borderRadius: hasBg ?
|
|
1840
|
+
borderRadius: hasBg ? cardRadius(slots) : 0,
|
|
1205
1841
|
overflow: "hidden",
|
|
1206
1842
|
outline: slots.featured === true ? `2px solid ${ctx.brand.palette.primary}` : void 0,
|
|
1207
1843
|
display: horizontal ? "flex" : "block",
|
|
@@ -1229,7 +1865,7 @@ function CardBlock({ node, ctx, path }) {
|
|
|
1229
1865
|
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1230
1866
|
"div",
|
|
1231
1867
|
{
|
|
1232
|
-
style: /^(lucide|simple):/.test(mediaRef) ? { padding: `${AI_TREE_TOKENS.paddingBlock}px ${AI_TREE_TOKENS.paddingBlock}px 0` } : hasBg ? void 0 : { borderRadius:
|
|
1868
|
+
style: /^(lucide|simple):/.test(mediaRef) ? { padding: `${AI_TREE_TOKENS.paddingBlock}px ${AI_TREE_TOKENS.paddingBlock}px 0` } : hasBg ? void 0 : { borderRadius: cardRadius(slots), overflow: "hidden" },
|
|
1233
1869
|
children: media
|
|
1234
1870
|
}
|
|
1235
1871
|
)),
|
|
@@ -1520,7 +2156,7 @@ function CollectionBlock({ node, ctx, path }) {
|
|
|
1520
2156
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1521
2157
|
"div",
|
|
1522
2158
|
{
|
|
1523
|
-
"data-ai-grid":
|
|
2159
|
+
"data-ai-grid": String(itemsPerRow),
|
|
1524
2160
|
style: {
|
|
1525
2161
|
display: "grid",
|
|
1526
2162
|
gridTemplateColumns: `repeat(${itemsPerRow}, 1fr)`,
|
|
@@ -1640,6 +2276,32 @@ function renderNode(node, ctx, path) {
|
|
|
1640
2276
|
if (child) {
|
|
1641
2277
|
return renderNode(child, ctx, `${path}.c0`);
|
|
1642
2278
|
}
|
|
2279
|
+
if (str(slots.provider) === "map" && str(slots.query)) {
|
|
2280
|
+
const query = str(slots.query);
|
|
2281
|
+
const mapAttrs = ctx.keyFor ? {
|
|
2282
|
+
"data-ohw-key": ctx.keyFor(`${path}.query`),
|
|
2283
|
+
"data-ohw-editable": "map",
|
|
2284
|
+
"data-ohw-map-query": query
|
|
2285
|
+
} : {};
|
|
2286
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2287
|
+
"iframe",
|
|
2288
|
+
{
|
|
2289
|
+
...mapAttrs,
|
|
2290
|
+
"data-ai-embed": "map",
|
|
2291
|
+
title: str(slots.title) || "Map",
|
|
2292
|
+
src: `https://www.google.com/maps?q=${encodeURIComponent(query)}&output=embed`,
|
|
2293
|
+
loading: "lazy",
|
|
2294
|
+
referrerPolicy: "no-referrer-when-downgrade",
|
|
2295
|
+
style: {
|
|
2296
|
+
width: "100%",
|
|
2297
|
+
minHeight: 320,
|
|
2298
|
+
border: 0,
|
|
2299
|
+
borderRadius: AI_TREE_TOKENS.radiusCard,
|
|
2300
|
+
display: "block"
|
|
2301
|
+
}
|
|
2302
|
+
}
|
|
2303
|
+
);
|
|
2304
|
+
}
|
|
1643
2305
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1644
2306
|
"div",
|
|
1645
2307
|
{
|
|
@@ -1796,9 +2458,14 @@ function AiTreeRenderer({
|
|
|
1796
2458
|
const resolvedBrand = brand ?? AI_DEFAULT_BRAND;
|
|
1797
2459
|
const band = (tree.settings ?? {}).sectionBackground === "accent" ? accentBandContext(resolvedBrand) : null;
|
|
1798
2460
|
const blockBrand = band?.brand ?? resolvedBrand;
|
|
2461
|
+
const placeholderMap = buildPlaceholderMap(tree);
|
|
1799
2462
|
const ctx = {
|
|
1800
2463
|
brand: blockBrand,
|
|
1801
|
-
|
|
2464
|
+
// An owner/library ref resolves through the host resolver; a `placeholder:<subject>` ref the
|
|
2465
|
+
// host cannot resolve falls back to real stock photography (the per-section map first, then a
|
|
2466
|
+
// standalone resolve), so generated galleries, image rows, and overlay backgrounds arrive with
|
|
2467
|
+
// photos instead of grey boxes.
|
|
2468
|
+
resolveMedia: (ref) => resolveMedia?.(ref) ?? placeholderMap[ref] ?? resolvePlaceholderRef(ref),
|
|
1802
2469
|
cardSurface: blockBrand.palette.light.toUpperCase() === AI_DEFAULT_BRAND.palette.light.toUpperCase() ? "#ECECEB" : `color-mix(in srgb, ${blockBrand.palette.light} 90%, ${blockBrand.palette.dark})`,
|
|
1803
2470
|
keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null,
|
|
1804
2471
|
sectionAlignment: (tree.settings ?? {}).alignment === "center" ? "center" : "left",
|
|
@@ -1825,11 +2492,25 @@ function AiTreeRenderer({
|
|
|
1825
2492
|
}
|
|
1826
2493
|
})();
|
|
1827
2494
|
const distributed = !isOverlay && settings.textDistribution;
|
|
2495
|
+
const rowAlignItems = (rowAlign) => {
|
|
2496
|
+
if (rowAlign === "top") return "start";
|
|
2497
|
+
if (rowAlign === "bottom") return "end";
|
|
2498
|
+
if (rowAlign === "center" || rowAlign === "stretch") return rowAlign;
|
|
2499
|
+
if (distributed === "space-between") return "stretch";
|
|
2500
|
+
return (distributed ?? settings.verticalPosition) === "top" ? "start" : "center";
|
|
2501
|
+
};
|
|
2502
|
+
const cellAlignStyle = (blockAlign) => blockAlign ? {
|
|
2503
|
+
display: "flex",
|
|
2504
|
+
flexDirection: "column",
|
|
2505
|
+
alignItems: blockAlign === "left" ? "flex-start" : blockAlign === "right" ? "flex-end" : "center",
|
|
2506
|
+
textAlign: blockAlign
|
|
2507
|
+
} : {};
|
|
1828
2508
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1829
2509
|
"section",
|
|
1830
2510
|
{
|
|
1831
2511
|
"data-ai-section": tree.tag ?? "",
|
|
1832
2512
|
...bgAttrs,
|
|
2513
|
+
"data-ai-responsive": "",
|
|
1833
2514
|
style: {
|
|
1834
2515
|
position: "relative",
|
|
1835
2516
|
padding: `${pad}px 0`,
|
|
@@ -1840,12 +2521,13 @@ function AiTreeRenderer({
|
|
|
1840
2521
|
color: settings.sectionBackground === "accent" ? blockBrand.palette.dark : void 0
|
|
1841
2522
|
},
|
|
1842
2523
|
children: [
|
|
1843
|
-
|
|
2524
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_RESPONSIVE_CSS }),
|
|
1844
2525
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_MOBILE_CSS }),
|
|
2526
|
+
isOverlay && backgroundUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { position: "absolute", inset: 0, background: `rgba(255,255,255,${overlayAlpha})` } }),
|
|
1845
2527
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1846
2528
|
"div",
|
|
1847
2529
|
{
|
|
1848
|
-
"data-ai-
|
|
2530
|
+
"data-ai-section-inner": "",
|
|
1849
2531
|
style: {
|
|
1850
2532
|
position: "relative",
|
|
1851
2533
|
maxWidth: AI_TREE_TOKENS.sectionMaxWidth,
|
|
@@ -1856,12 +2538,12 @@ function AiTreeRenderer({
|
|
|
1856
2538
|
children: tree.rows.map((row, r2) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1857
2539
|
"div",
|
|
1858
2540
|
{
|
|
1859
|
-
"data-ai-
|
|
2541
|
+
"data-ai-columns": "",
|
|
1860
2542
|
style: {
|
|
1861
2543
|
display: "grid",
|
|
1862
2544
|
gridTemplateColumns: "repeat(12, 1fr)",
|
|
1863
2545
|
gap: AI_TREE_TOKENS.spacing6,
|
|
1864
|
-
alignItems:
|
|
2546
|
+
alignItems: rowAlignItems(row.align),
|
|
1865
2547
|
marginTop: r2 > 0 ? AI_TREE_TOKENS.spacing8 : 0
|
|
1866
2548
|
},
|
|
1867
2549
|
children: (row.blocks ?? []).map((block, b) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -1871,6 +2553,8 @@ function AiTreeRenderer({
|
|
|
1871
2553
|
style: {
|
|
1872
2554
|
gridColumn: `span ${Math.min(12, Math.max(1, block.span))}`,
|
|
1873
2555
|
minWidth: 0,
|
|
2556
|
+
// Horizontal placement of the block's content within its column.
|
|
2557
|
+
...cellAlignStyle(block.align),
|
|
1874
2558
|
// space-between: each column becomes a flex column whose content spreads over
|
|
1875
2559
|
// the full row height instead of clumping at the top.
|
|
1876
2560
|
...distributed === "space-between" ? { display: "flex", flexDirection: "column", justifyContent: "space-between" } : {}
|
|
@@ -1893,7 +2577,7 @@ function AiTreeRenderer({
|
|
|
1893
2577
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1894
2578
|
var CONTAINER_ATTR = "data-ohw-ai-generated";
|
|
1895
2579
|
var REPLACED_ATTR = "data-ohw-ai-replaced-by";
|
|
1896
|
-
var
|
|
2580
|
+
var REMOVED_ATTR2 = "data-ohw-ai-removed";
|
|
1897
2581
|
var TEMPLATE_HIDDEN_ATTR = "data-ohw-ai-template-hidden";
|
|
1898
2582
|
var CHROME_SECTION_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
|
|
1899
2583
|
function readRootVar(name) {
|
|
@@ -1987,18 +2671,18 @@ function placeContainer(container, entry) {
|
|
|
1987
2671
|
}
|
|
1988
2672
|
function syncRemovedSections(state) {
|
|
1989
2673
|
const removed = new Set(state.removed ?? []);
|
|
1990
|
-
for (const el of document.querySelectorAll(`[${
|
|
2674
|
+
for (const el of document.querySelectorAll(`[${REMOVED_ATTR2}]`)) {
|
|
1991
2675
|
const id = el.getAttribute("data-ohw-section") ?? "";
|
|
1992
2676
|
if (!removed.has(id)) {
|
|
1993
2677
|
el.style.removeProperty("display");
|
|
1994
|
-
el.removeAttribute(
|
|
2678
|
+
el.removeAttribute(REMOVED_ATTR2);
|
|
1995
2679
|
}
|
|
1996
2680
|
}
|
|
1997
2681
|
for (const id of removed) {
|
|
1998
2682
|
const section = findTemplateSection(id);
|
|
1999
2683
|
if (section && !section.hasAttribute(REPLACED_ATTR)) {
|
|
2000
2684
|
section.style.display = "none";
|
|
2001
|
-
section.setAttribute(
|
|
2685
|
+
section.setAttribute(REMOVED_ATTR2, "");
|
|
2002
2686
|
}
|
|
2003
2687
|
}
|
|
2004
2688
|
}
|
|
@@ -2015,7 +2699,7 @@ function syncTemplateHidden(state, pageHasSections) {
|
|
|
2015
2699
|
if (el.hasAttribute(CONTAINER_ATTR)) continue;
|
|
2016
2700
|
if (CHROME_SECTION_IDS.has(el.getAttribute("data-ohw-section") ?? "")) continue;
|
|
2017
2701
|
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
2018
|
-
if (el.hasAttribute(REPLACED_ATTR) || el.hasAttribute(
|
|
2702
|
+
if (el.hasAttribute(REPLACED_ATTR) || el.hasAttribute(REMOVED_ATTR2)) continue;
|
|
2019
2703
|
el.style.display = "none";
|
|
2020
2704
|
el.setAttribute(TEMPLATE_HIDDEN_ATTR, "");
|
|
2021
2705
|
}
|
|
@@ -2039,18 +2723,23 @@ function syncReplacedOriginals(state) {
|
|
|
2039
2723
|
}
|
|
2040
2724
|
}
|
|
2041
2725
|
var sectionOrderIndex = /* @__PURE__ */ new Map();
|
|
2726
|
+
var removedSectionIds = /* @__PURE__ */ new Set();
|
|
2042
2727
|
function setAiSectionOrder(raw, currentPath) {
|
|
2043
2728
|
const next = /* @__PURE__ */ new Map();
|
|
2729
|
+
const removed = /* @__PURE__ */ new Set();
|
|
2044
2730
|
if (raw) {
|
|
2045
2731
|
try {
|
|
2046
2732
|
const entries = JSON.parse(raw);
|
|
2047
2733
|
for (const entry of entries) {
|
|
2048
|
-
if (
|
|
2734
|
+
if (entry.pagePath && entry.pagePath !== currentPath) continue;
|
|
2735
|
+
next.set(entry.instanceId, entry.order);
|
|
2736
|
+
if (entry.removed) removed.add(entry.instanceId);
|
|
2049
2737
|
}
|
|
2050
2738
|
} catch {
|
|
2051
2739
|
}
|
|
2052
2740
|
}
|
|
2053
2741
|
sectionOrderIndex = next;
|
|
2742
|
+
removedSectionIds = removed;
|
|
2054
2743
|
}
|
|
2055
2744
|
function applyExplicitOrder(entries) {
|
|
2056
2745
|
if (sectionOrderIndex.size === 0) return entries;
|
|
@@ -2086,6 +2775,18 @@ function orderByChain(sections) {
|
|
|
2086
2775
|
for (const root of roots) visit(root);
|
|
2087
2776
|
return out.length === sections.length ? out : sections;
|
|
2088
2777
|
}
|
|
2778
|
+
function syncSoftRemovedGenerated() {
|
|
2779
|
+
for (const [id, section] of mounted) {
|
|
2780
|
+
const el = section.container;
|
|
2781
|
+
if (removedSectionIds.has(id)) {
|
|
2782
|
+
el.style.display = "none";
|
|
2783
|
+
el.setAttribute(REMOVED_ATTR, "");
|
|
2784
|
+
} else if (el.hasAttribute(REMOVED_ATTR)) {
|
|
2785
|
+
el.style.removeProperty("display");
|
|
2786
|
+
el.removeAttribute(REMOVED_ATTR);
|
|
2787
|
+
}
|
|
2788
|
+
}
|
|
2789
|
+
}
|
|
2089
2790
|
function applyAiSectionsToDom(state, options) {
|
|
2090
2791
|
if (typeof document === "undefined") return;
|
|
2091
2792
|
const brandOverride = deriveBrandOverride();
|
|
@@ -2153,6 +2854,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
2153
2854
|
syncReplacedOriginals(state);
|
|
2154
2855
|
syncRemovedSections(state);
|
|
2155
2856
|
syncTemplateHidden(state, pageSections.length > 0);
|
|
2857
|
+
syncSoftRemovedGenerated();
|
|
2156
2858
|
}
|
|
2157
2859
|
|
|
2158
2860
|
// src/useLinkHrefGuardian.ts
|
|
@@ -7882,6 +8584,7 @@ function MediaOverlay({
|
|
|
7882
8584
|
(prev) => prev && prev.fullWidth === width && prev.height === height ? prev : { fullWidth: width, height }
|
|
7883
8585
|
);
|
|
7884
8586
|
}, [isVideo]);
|
|
8587
|
+
const replaceLabel = isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image";
|
|
7885
8588
|
const replaceMode = buttonSize ? replaceButtonMode({ width: rect.width, height: rect.height }, buttonSize) : "none";
|
|
7886
8589
|
const box = {
|
|
7887
8590
|
position: "fixed",
|
|
@@ -8011,17 +8714,17 @@ function MediaOverlay({
|
|
|
8011
8714
|
},
|
|
8012
8715
|
children: [
|
|
8013
8716
|
isVideo ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react5.Film, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react5.ImageIcon, { size: 14 }),
|
|
8014
|
-
|
|
8717
|
+
replaceLabel
|
|
8015
8718
|
]
|
|
8016
8719
|
}
|
|
8017
8720
|
),
|
|
8018
|
-
replaceMode
|
|
8721
|
+
showChrome && replaceMode !== "none" && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
8019
8722
|
Button,
|
|
8020
8723
|
{
|
|
8021
8724
|
"data-ohw-media-overlay": "",
|
|
8022
8725
|
variant: "outline",
|
|
8023
8726
|
size: "sm",
|
|
8024
|
-
"aria-label":
|
|
8727
|
+
"aria-label": replaceLabel,
|
|
8025
8728
|
className: "gap-1.5 cursor-pointer hover:bg-background",
|
|
8026
8729
|
style: {
|
|
8027
8730
|
...OVERLAY_BUTTON_STYLE,
|
|
@@ -8044,7 +8747,7 @@ function MediaOverlay({
|
|
|
8044
8747
|
},
|
|
8045
8748
|
children: [
|
|
8046
8749
|
isVideo ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react5.Film, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react5.ImageIcon, { size: 14 }),
|
|
8047
|
-
replaceMode === "full" ?
|
|
8750
|
+
replaceMode === "full" ? replaceLabel : null
|
|
8048
8751
|
]
|
|
8049
8752
|
}
|
|
8050
8753
|
)
|
|
@@ -8081,219 +8784,37 @@ function CarouselOverlay({
|
|
|
8081
8784
|
width: rect.width,
|
|
8082
8785
|
height: rect.height,
|
|
8083
8786
|
zIndex: 2147483646,
|
|
8084
|
-
pointerEvents: "auto",
|
|
8085
|
-
boxShadow: "inset 0 0 0 1.5px var(--color-primary)",
|
|
8086
|
-
background: "color-mix(in srgb, var(--color-primary) 20%, transparent)"
|
|
8087
|
-
},
|
|
8088
|
-
onClick: () => onEdit(hover.key),
|
|
8089
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
8090
|
-
Button,
|
|
8091
|
-
{
|
|
8092
|
-
"data-ohw-carousel-overlay": "",
|
|
8093
|
-
variant: "outline",
|
|
8094
|
-
size: "sm",
|
|
8095
|
-
className: "cursor-pointer gap-1.5 hover:bg-background",
|
|
8096
|
-
style: OVERLAY_BUTTON_STYLE2,
|
|
8097
|
-
onMouseDown: (e) => e.preventDefault(),
|
|
8098
|
-
onClick: (e) => {
|
|
8099
|
-
e.stopPropagation();
|
|
8100
|
-
onEdit(hover.key);
|
|
8101
|
-
},
|
|
8102
|
-
children: [
|
|
8103
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react6.GalleryHorizontal, { size: 14 }),
|
|
8104
|
-
"Edit gallery"
|
|
8105
|
-
]
|
|
8106
|
-
}
|
|
8107
|
-
)
|
|
8108
|
-
}
|
|
8109
|
-
);
|
|
8110
|
-
}
|
|
8111
|
-
|
|
8112
|
-
// src/ui/ai-section/AiSectionOverlay.tsx
|
|
8113
|
-
var import_react8 = require("react");
|
|
8114
|
-
var import_lucide_react7 = require("lucide-react");
|
|
8115
|
-
|
|
8116
|
-
// src/lib/sections.ts
|
|
8117
|
-
var LINK_PICKER_EXCLUDED_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
|
|
8118
|
-
function isChromeSection(el) {
|
|
8119
|
-
return el.matches("header, nav, footer, aside");
|
|
8120
|
-
}
|
|
8121
|
-
function titleCaseSectionId(id) {
|
|
8122
|
-
return id.split("-").filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
8123
|
-
}
|
|
8124
|
-
function parseSectionsFromRoot(root) {
|
|
8125
|
-
const seen = /* @__PURE__ */ new Set();
|
|
8126
|
-
const sections = [];
|
|
8127
|
-
for (const el of root.querySelectorAll("[data-ohw-section]")) {
|
|
8128
|
-
const id = el.getAttribute("data-ohw-section") ?? "";
|
|
8129
|
-
if (!id || seen.has(id) || LINK_PICKER_EXCLUDED_IDS.has(id)) continue;
|
|
8130
|
-
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
8131
|
-
if (el.hasAttribute("data-ohw-ai-template-hidden") || el.hasAttribute("data-ohw-ai-removed") || el.hasAttribute("data-ohw-ai-replaced-by"))
|
|
8132
|
-
continue;
|
|
8133
|
-
seen.add(id);
|
|
8134
|
-
const label = el.getAttribute("data-ohw-section-label") ?? titleCaseSectionId(id);
|
|
8135
|
-
sections.push({ id, label });
|
|
8136
|
-
}
|
|
8137
|
-
return sections;
|
|
8138
|
-
}
|
|
8139
|
-
function collectSectionsFromDom() {
|
|
8140
|
-
if (typeof document === "undefined") return [];
|
|
8141
|
-
return parseSectionsFromRoot(document);
|
|
8142
|
-
}
|
|
8143
|
-
function parseSectionsFromHtml(html) {
|
|
8144
|
-
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
8145
|
-
return parseSectionsFromRoot(doc);
|
|
8146
|
-
}
|
|
8147
|
-
|
|
8148
|
-
// src/lib/section-instances.ts
|
|
8149
|
-
var SECTION_ORDER_KEY = "__ohw_section_order";
|
|
8150
|
-
var REMOVED_ATTR2 = "data-ohw-section-removed";
|
|
8151
|
-
function isRemovedSection(el) {
|
|
8152
|
-
return el.hasAttribute(REMOVED_ATTR2);
|
|
8153
|
-
}
|
|
8154
|
-
function topLevelSections() {
|
|
8155
|
-
return Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
|
|
8156
|
-
(el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el) && !isRemovedSection(el)
|
|
8157
|
-
);
|
|
8158
|
-
}
|
|
8159
|
-
function instanceIdOf(el) {
|
|
8160
|
-
return el.dataset.ohwInstance ?? el.dataset.ohwSection ?? "";
|
|
8161
|
-
}
|
|
8162
|
-
function findByInstanceId(instanceId) {
|
|
8163
|
-
const escapedId = CSS.escape(instanceId);
|
|
8164
|
-
return document.querySelector(`[data-ohw-instance="${escapedId}"]`) ?? document.querySelector(`[data-ohw-section="${escapedId}"]:not([data-ohw-instance])`);
|
|
8165
|
-
}
|
|
8166
|
-
function planSectionMove(instanceId, targetIndex, currentPath) {
|
|
8167
|
-
const sections = topLevelSections();
|
|
8168
|
-
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
8169
|
-
if (index === -1) return null;
|
|
8170
|
-
const dragged = sections[index];
|
|
8171
|
-
const others = sections.filter((_, i) => i !== index);
|
|
8172
|
-
const clamped = Math.max(0, Math.min(targetIndex, others.length));
|
|
8173
|
-
const reordered = [...others.slice(0, clamped), dragged, ...others.slice(clamped)];
|
|
8174
|
-
return reordered.map((el, order) => ({
|
|
8175
|
-
instanceId: instanceIdOf(el),
|
|
8176
|
-
type: el.getAttribute("data-ohw-section") ?? "",
|
|
8177
|
-
order,
|
|
8178
|
-
pagePath: currentPath
|
|
8179
|
-
}));
|
|
8180
|
-
}
|
|
8181
|
-
function moveSectionInstance(instanceId, direction, currentPath) {
|
|
8182
|
-
const sections = topLevelSections();
|
|
8183
|
-
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
8184
|
-
if (index === -1) return null;
|
|
8185
|
-
const siblingIndex = direction === "up" ? index - 1 : index + 1;
|
|
8186
|
-
if (siblingIndex < 0 || siblingIndex >= sections.length) return null;
|
|
8187
|
-
const entries = planSectionMove(instanceId, siblingIndex, currentPath);
|
|
8188
|
-
if (!entries) return null;
|
|
8189
|
-
applyPersistedOrder(entries);
|
|
8190
|
-
return entries;
|
|
8191
|
-
}
|
|
8192
|
-
function syncRemovedFlags(entries) {
|
|
8193
|
-
const removedIds = new Set(entries.filter((e) => e.removed).map((e) => e.instanceId));
|
|
8194
|
-
document.querySelectorAll(`[${REMOVED_ATTR2}]`).forEach((el) => {
|
|
8195
|
-
if (!removedIds.has(instanceIdOf(el))) {
|
|
8196
|
-
el.style.removeProperty("display");
|
|
8197
|
-
el.removeAttribute(REMOVED_ATTR2);
|
|
8198
|
-
}
|
|
8199
|
-
});
|
|
8200
|
-
for (const id of removedIds) {
|
|
8201
|
-
const el = findByInstanceId(id);
|
|
8202
|
-
if (el) {
|
|
8203
|
-
el.style.display = "none";
|
|
8204
|
-
el.setAttribute(REMOVED_ATTR2, "");
|
|
8787
|
+
pointerEvents: "auto",
|
|
8788
|
+
boxShadow: "inset 0 0 0 1.5px var(--color-primary)",
|
|
8789
|
+
background: "color-mix(in srgb, var(--color-primary) 20%, transparent)"
|
|
8790
|
+
},
|
|
8791
|
+
onClick: () => onEdit(hover.key),
|
|
8792
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
8793
|
+
Button,
|
|
8794
|
+
{
|
|
8795
|
+
"data-ohw-carousel-overlay": "",
|
|
8796
|
+
variant: "outline",
|
|
8797
|
+
size: "sm",
|
|
8798
|
+
className: "cursor-pointer gap-1.5 hover:bg-background",
|
|
8799
|
+
style: OVERLAY_BUTTON_STYLE2,
|
|
8800
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
8801
|
+
onClick: (e) => {
|
|
8802
|
+
e.stopPropagation();
|
|
8803
|
+
onEdit(hover.key);
|
|
8804
|
+
},
|
|
8805
|
+
children: [
|
|
8806
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react6.GalleryHorizontal, { size: 14 }),
|
|
8807
|
+
"Edit gallery"
|
|
8808
|
+
]
|
|
8809
|
+
}
|
|
8810
|
+
)
|
|
8205
8811
|
}
|
|
8206
|
-
}
|
|
8207
|
-
}
|
|
8208
|
-
function applyPersistedOrder(entries) {
|
|
8209
|
-
syncRemovedFlags(entries);
|
|
8210
|
-
if (entries.length === 0) return;
|
|
8211
|
-
const sections = topLevelSections();
|
|
8212
|
-
if (sections.length === 0) return;
|
|
8213
|
-
const orderIndex = new Map(entries.map((e) => [e.instanceId, e.order]));
|
|
8214
|
-
const ordered = [...sections].sort((a, b) => {
|
|
8215
|
-
const aOrder = orderIndex.get(instanceIdOf(a));
|
|
8216
|
-
const bOrder = orderIndex.get(instanceIdOf(b));
|
|
8217
|
-
if (aOrder === void 0 && bOrder === void 0) return 0;
|
|
8218
|
-
if (aOrder === void 0) return 1;
|
|
8219
|
-
if (bOrder === void 0) return -1;
|
|
8220
|
-
return aOrder - bOrder;
|
|
8221
|
-
});
|
|
8222
|
-
let prev = null;
|
|
8223
|
-
for (const el of ordered) {
|
|
8224
|
-
if (prev) prev.after(el);
|
|
8225
|
-
prev = el;
|
|
8226
|
-
}
|
|
8227
|
-
}
|
|
8228
|
-
function setSectionRemoved(instanceId, currentPath, existingEntries, removed) {
|
|
8229
|
-
if (!findByInstanceId(instanceId)) return null;
|
|
8230
|
-
const byId = new Map(existingEntries.map((e) => [e.instanceId, e]));
|
|
8231
|
-
const allSections = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
|
|
8232
|
-
(el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el)
|
|
8233
8812
|
);
|
|
8234
|
-
allSections.forEach((el, order) => {
|
|
8235
|
-
const id = instanceIdOf(el);
|
|
8236
|
-
if (!byId.has(id)) {
|
|
8237
|
-
byId.set(id, { instanceId: id, type: el.getAttribute("data-ohw-section") ?? "", order, pagePath: currentPath });
|
|
8238
|
-
}
|
|
8239
|
-
});
|
|
8240
|
-
const target = byId.get(instanceId);
|
|
8241
|
-
if (!target) return null;
|
|
8242
|
-
byId.set(instanceId, { ...target, removed });
|
|
8243
|
-
const entries = Array.from(byId.values());
|
|
8244
|
-
applyPersistedOrder(entries);
|
|
8245
|
-
return entries;
|
|
8246
|
-
}
|
|
8247
|
-
function deleteSectionInstance(instanceId, currentPath, existingEntries) {
|
|
8248
|
-
return setSectionRemoved(instanceId, currentPath, existingEntries, true);
|
|
8249
|
-
}
|
|
8250
|
-
function restoreSectionInstance(instanceId, currentPath, existingEntries) {
|
|
8251
|
-
return setSectionRemoved(instanceId, currentPath, existingEntries, false);
|
|
8252
|
-
}
|
|
8253
|
-
function newInstanceId() {
|
|
8254
|
-
return typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `instance-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
8255
|
-
}
|
|
8256
|
-
function getPageSectionOrderEntries(raw, currentPath) {
|
|
8257
|
-
if (!raw) return [];
|
|
8258
|
-
try {
|
|
8259
|
-
const entries = JSON.parse(raw);
|
|
8260
|
-
return entries.filter((e) => !e.pagePath || e.pagePath === currentPath);
|
|
8261
|
-
} catch {
|
|
8262
|
-
return [];
|
|
8263
|
-
}
|
|
8264
|
-
}
|
|
8265
|
-
function rekeySectionSubtree(root, instanceId) {
|
|
8266
|
-
const suffix = `::${instanceId}`;
|
|
8267
|
-
const rekey = (el, attr) => {
|
|
8268
|
-
const current = el.getAttribute(attr);
|
|
8269
|
-
if (current) el.setAttribute(attr, `${current}${suffix}`);
|
|
8270
|
-
};
|
|
8271
|
-
if (root.hasAttribute("data-ohw-key")) rekey(root, "data-ohw-key");
|
|
8272
|
-
if (root.hasAttribute("data-ohw-href-key")) rekey(root, "data-ohw-href-key");
|
|
8273
|
-
root.querySelectorAll("[data-ohw-key]").forEach((el) => rekey(el, "data-ohw-key"));
|
|
8274
|
-
root.querySelectorAll("[data-ohw-href-key]").forEach((el) => rekey(el, "data-ohw-href-key"));
|
|
8275
|
-
}
|
|
8276
|
-
function initSectionInstancesFromContent(content, currentPath) {
|
|
8277
|
-
document.querySelectorAll("[data-ohw-section]:not([data-ohw-instance])").forEach((el) => {
|
|
8278
|
-
el.setAttribute("data-ohw-instance", el.getAttribute("data-ohw-section") ?? "");
|
|
8279
|
-
});
|
|
8280
|
-
const entries = getPageSectionOrderEntries(content[SECTION_ORDER_KEY], currentPath);
|
|
8281
|
-
for (const entry of entries) {
|
|
8282
|
-
if (entry.instanceId === entry.type) continue;
|
|
8283
|
-
if (document.querySelector(`[data-ohw-instance="${CSS.escape(entry.instanceId)}"]`)) continue;
|
|
8284
|
-
const original = document.querySelector(
|
|
8285
|
-
`[data-ohw-section="${CSS.escape(entry.type)}"][data-ohw-instance="${CSS.escape(entry.type)}"]`
|
|
8286
|
-
);
|
|
8287
|
-
if (!original) continue;
|
|
8288
|
-
const clone = original.cloneNode(true);
|
|
8289
|
-
clone.setAttribute("data-ohw-instance", entry.instanceId);
|
|
8290
|
-
rekeySectionSubtree(clone, entry.instanceId);
|
|
8291
|
-
original.insertAdjacentElement("afterend", clone);
|
|
8292
|
-
}
|
|
8293
|
-
applyPersistedOrder(entries);
|
|
8294
8813
|
}
|
|
8295
8814
|
|
|
8296
8815
|
// src/ui/ai-section/AiSectionOverlay.tsx
|
|
8816
|
+
var import_react8 = require("react");
|
|
8817
|
+
var import_lucide_react7 = require("lucide-react");
|
|
8297
8818
|
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
8298
8819
|
function findSectionElement(instanceId) {
|
|
8299
8820
|
const escaped = CSS.escape(instanceId);
|
|
@@ -13009,6 +13530,7 @@ function readLogoSizeState(content, placement) {
|
|
|
13009
13530
|
function getLogoElement(el) {
|
|
13010
13531
|
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
13011
13532
|
if (marked) return marked;
|
|
13533
|
+
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
13012
13534
|
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
13013
13535
|
if (!root) return null;
|
|
13014
13536
|
const anchor = el.closest("a");
|
|
@@ -14384,6 +14906,9 @@ function collectEditableNodes(extraContent, root = document) {
|
|
|
14384
14906
|
if (el.dataset.ohwEditable === "link") {
|
|
14385
14907
|
return { key: el.dataset.ohwKey ?? "", type: "link", text: getLinkHref3(el) };
|
|
14386
14908
|
}
|
|
14909
|
+
if (el.dataset.ohwEditable === "map") {
|
|
14910
|
+
return { key: el.dataset.ohwKey ?? "", type: "map", text: el.dataset.ohwMapQuery ?? "" };
|
|
14911
|
+
}
|
|
14387
14912
|
return {
|
|
14388
14913
|
key: el.dataset.ohwKey ?? "",
|
|
14389
14914
|
type: el.dataset.ohwEditable ?? "text",
|
|
@@ -14937,21 +15462,10 @@ function parseSchedulingInsertAfter(insertAfter) {
|
|
|
14937
15462
|
insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
|
|
14938
15463
|
};
|
|
14939
15464
|
}
|
|
14940
|
-
function
|
|
14941
|
-
|
|
14942
|
-
const
|
|
14943
|
-
|
|
14944
|
-
return { effectiveInsertAfter, insertBefore };
|
|
14945
|
-
}
|
|
14946
|
-
function getSchedulingMountPoint(insertAfter) {
|
|
14947
|
-
const { anchor } = parseSchedulingInsertAfter(insertAfter);
|
|
14948
|
-
let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
|
|
14949
|
-
if (!anchorEl && anchor === "scheduling") {
|
|
14950
|
-
const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
|
|
14951
|
-
anchorEl = widgets.at(-1) ?? null;
|
|
14952
|
-
}
|
|
14953
|
-
if (!anchorEl) return null;
|
|
14954
|
-
return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
15465
|
+
function resolveEntryAnchor(entry) {
|
|
15466
|
+
if (entry.anchorId !== void 0) return { anchorId: entry.anchorId, beforeId: entry.beforeId ?? null };
|
|
15467
|
+
const parsed = parseSchedulingInsertAfter(entry.insertAfter);
|
|
15468
|
+
return { anchorId: parsed.anchor, beforeId: parsed.insertBefore };
|
|
14955
15469
|
}
|
|
14956
15470
|
function schedulingMountDepth(insertAfter) {
|
|
14957
15471
|
if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
|
|
@@ -14968,8 +15482,7 @@ function getPageSchedulingEntries(raw) {
|
|
|
14968
15482
|
}
|
|
14969
15483
|
}
|
|
14970
15484
|
function isSchedulingWidgetMissing(entry) {
|
|
14971
|
-
|
|
14972
|
-
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
|
|
15485
|
+
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
|
|
14973
15486
|
}
|
|
14974
15487
|
function hasMissingSchedulingWidgets(entries) {
|
|
14975
15488
|
return entries.some(isSchedulingWidgetMissing);
|
|
@@ -14999,16 +15512,17 @@ function initSectionsFromContent(content, removeExisting = false) {
|
|
|
14999
15512
|
} catch {
|
|
15000
15513
|
}
|
|
15001
15514
|
}
|
|
15002
|
-
function mountSchedulingWidget(
|
|
15003
|
-
const
|
|
15004
|
-
const sectionId = schedulingSectionId(
|
|
15515
|
+
function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, beforeId, existingWidgetId) {
|
|
15516
|
+
const widgetId = existingWidgetId ?? (beforeId ? `${anchorId}${INSERT_BEFORE_MARKER}${beforeId}` : anchorId);
|
|
15517
|
+
const sectionId = schedulingSectionId(widgetId);
|
|
15005
15518
|
if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
|
|
15006
|
-
const
|
|
15007
|
-
if (!
|
|
15519
|
+
const anchorEl = document.querySelector(`[data-ohw-section="${anchorId}"]`);
|
|
15520
|
+
if (!anchorEl) return false;
|
|
15521
|
+
const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
15008
15522
|
const container = document.createElement("div");
|
|
15009
15523
|
container.dataset.ohwSectionContainer = "scheduling";
|
|
15010
|
-
if (
|
|
15011
|
-
const beforeAnchor = document.querySelector(`[data-ohw-section="${
|
|
15524
|
+
if (beforeId) {
|
|
15525
|
+
const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
|
|
15012
15526
|
const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
|
|
15013
15527
|
if (!beforePoint) return false;
|
|
15014
15528
|
beforePoint.insertAdjacentElement("beforebegin", container);
|
|
@@ -15019,19 +15533,25 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
15019
15533
|
}
|
|
15020
15534
|
tail.insertAdjacentElement("afterend", container);
|
|
15021
15535
|
}
|
|
15022
|
-
|
|
15023
|
-
|
|
15024
|
-
|
|
15025
|
-
|
|
15026
|
-
|
|
15027
|
-
|
|
15028
|
-
|
|
15029
|
-
|
|
15030
|
-
|
|
15031
|
-
|
|
15032
|
-
|
|
15033
|
-
|
|
15034
|
-
|
|
15536
|
+
try {
|
|
15537
|
+
const root = (0, import_client2.createRoot)(container);
|
|
15538
|
+
(0, import_react_dom3.flushSync)(() => {
|
|
15539
|
+
root.render(
|
|
15540
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
15541
|
+
SchedulingWidget,
|
|
15542
|
+
{
|
|
15543
|
+
notifyOnConnect,
|
|
15544
|
+
initialScheduleId: scheduleId,
|
|
15545
|
+
insertAfter: widgetId
|
|
15546
|
+
}
|
|
15547
|
+
)
|
|
15548
|
+
);
|
|
15549
|
+
});
|
|
15550
|
+
} catch (err) {
|
|
15551
|
+
console.error("[ow:scheduling] render threw", err);
|
|
15552
|
+
container.remove();
|
|
15553
|
+
return false;
|
|
15554
|
+
}
|
|
15035
15555
|
const tracker = getSectionsTracker();
|
|
15036
15556
|
let sections = [];
|
|
15037
15557
|
try {
|
|
@@ -15039,10 +15559,12 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
15039
15559
|
} catch {
|
|
15040
15560
|
}
|
|
15041
15561
|
const inEditor = typeof window !== "undefined" && window.self !== window.top;
|
|
15042
|
-
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter ===
|
|
15562
|
+
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
|
|
15043
15563
|
sections.push({
|
|
15044
15564
|
type: "scheduling",
|
|
15045
|
-
insertAfter:
|
|
15565
|
+
insertAfter: widgetId,
|
|
15566
|
+
anchorId,
|
|
15567
|
+
beforeId: beforeId ?? null,
|
|
15046
15568
|
pagePath: window.location.pathname,
|
|
15047
15569
|
...scheduleId ? { scheduleId } : {}
|
|
15048
15570
|
});
|
|
@@ -15056,7 +15578,8 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
|
|
|
15056
15578
|
for (let i = pending.length - 1; i >= 0; i--) {
|
|
15057
15579
|
const entry = pending[i];
|
|
15058
15580
|
const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
|
|
15059
|
-
|
|
15581
|
+
const { anchorId, beforeId } = resolveEntryAnchor(entry);
|
|
15582
|
+
if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
|
|
15060
15583
|
pending.splice(i, 1);
|
|
15061
15584
|
}
|
|
15062
15585
|
}
|
|
@@ -15148,7 +15671,7 @@ var EDITOR_CHROME_SELECTOR = '[data-ohw-toolbar], [data-ohw-form-toolbar], [data
|
|
|
15148
15671
|
function isOverEditorChrome(x, y) {
|
|
15149
15672
|
return document.elementsFromPoint(x, y).some((el) => el instanceof HTMLElement && el.matches(EDITOR_CHROME_SELECTOR));
|
|
15150
15673
|
}
|
|
15151
|
-
var NON_MEDIA_SELECTOR = '[data-ohw-editable]:not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]):not([data-ohw-editable="video"]):not([data-ohw-editable="icon"]):not([data-ohw-editable="form"])';
|
|
15674
|
+
var NON_MEDIA_SELECTOR = '[data-ohw-editable]:not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]):not([data-ohw-editable="video"]):not([data-ohw-editable="icon"]):not([data-ohw-editable="form"]):not([data-ohw-editable="map"])';
|
|
15152
15675
|
function getVideoEl2(el) {
|
|
15153
15676
|
return el instanceof HTMLVideoElement ? el : el.querySelector("video");
|
|
15154
15677
|
}
|
|
@@ -15204,6 +15727,12 @@ function applyVideoSettingNode(key, val) {
|
|
|
15204
15727
|
});
|
|
15205
15728
|
return true;
|
|
15206
15729
|
}
|
|
15730
|
+
function applyMapQuery(el, val) {
|
|
15731
|
+
if (!(el instanceof HTMLIFrameElement)) return;
|
|
15732
|
+
const nextSrc = `https://www.google.com/maps?q=${encodeURIComponent(val)}&output=embed`;
|
|
15733
|
+
if (el.src !== nextSrc) el.src = nextSrc;
|
|
15734
|
+
el.setAttribute("data-ohw-map-query", val);
|
|
15735
|
+
}
|
|
15207
15736
|
function applyLinkByKey(key, val) {
|
|
15208
15737
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
15209
15738
|
if (el.dataset.ohwEditable === "link") applyLinkHref(el, val);
|
|
@@ -15214,6 +15743,11 @@ function applyLinkByKey(key, val) {
|
|
|
15214
15743
|
hrefAnchors.forEach((el) => applyLinkHref(el, val));
|
|
15215
15744
|
}
|
|
15216
15745
|
}
|
|
15746
|
+
function isInsideLinkEditor(target) {
|
|
15747
|
+
return Boolean(
|
|
15748
|
+
target.closest("[data-ohw-link-popover-root]") || target.closest("[data-ohw-link-modal-root]") || target.closest("[data-ohw-link-page-dropdown]") || target.closest("[data-ohw-section-picker]") || target.closest("[data-ohw-navbar-container-chrome]") || target.closest("[data-ohw-navbar-add-button]") || target.closest("[data-ohw-footer-container-chrome]") || target.closest("[data-ohw-footer-add-button]") || target.closest("[data-ohw-more-menu]") || target.closest('[data-slot="dropdown-menu-content"]') || target.closest('[data-slot="popover-content"]') || target.closest('[data-slot="dialog-content"]') || target.closest('[data-slot="dialog-overlay"]')
|
|
15749
|
+
);
|
|
15750
|
+
}
|
|
15217
15751
|
function isInsideFloatingPanel(target) {
|
|
15218
15752
|
return Boolean(target.closest("[data-ohw-floating-panel]"));
|
|
15219
15753
|
}
|
|
@@ -15221,11 +15755,6 @@ function isPointOverFloatingPanel(clientX, clientY) {
|
|
|
15221
15755
|
const el = document.elementFromPoint(clientX, clientY);
|
|
15222
15756
|
return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
|
|
15223
15757
|
}
|
|
15224
|
-
function isInsideLinkEditor(target) {
|
|
15225
|
-
return Boolean(
|
|
15226
|
-
target.closest("[data-ohw-link-popover-root]") || target.closest("[data-ohw-link-modal-root]") || target.closest("[data-ohw-link-page-dropdown]") || target.closest("[data-ohw-section-picker]") || target.closest("[data-ohw-navbar-container-chrome]") || target.closest("[data-ohw-navbar-add-button]") || target.closest("[data-ohw-footer-container-chrome]") || target.closest("[data-ohw-footer-add-button]") || target.closest("[data-ohw-more-menu]") || target.closest('[data-slot="dropdown-menu-content"]') || target.closest('[data-slot="popover-content"]') || target.closest('[data-slot="dialog-content"]') || target.closest('[data-slot="dialog-overlay"]')
|
|
15227
|
-
);
|
|
15228
|
-
}
|
|
15229
15758
|
function getHrefKeyFromElement(el) {
|
|
15230
15759
|
if (!el) return null;
|
|
15231
15760
|
const anchor = el.closest("[data-ohw-href-key]");
|
|
@@ -15484,7 +16013,7 @@ function getNavigationSelectionParent(el) {
|
|
|
15484
16013
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
15485
16014
|
return getFooterLinksContainer();
|
|
15486
16015
|
}
|
|
15487
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
|
|
16016
|
+
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isFooterLinksContainer(el) || isInferredFooterGroup2(el)) {
|
|
15488
16017
|
return getNavigationRoot(el);
|
|
15489
16018
|
}
|
|
15490
16019
|
return null;
|
|
@@ -15699,7 +16228,6 @@ var ICONS = {
|
|
|
15699
16228
|
insertUnorderedList: '<line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/>',
|
|
15700
16229
|
insertOrderedList: '<line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"/>'
|
|
15701
16230
|
};
|
|
15702
|
-
var HEIGHT_SETTLE_DELAYS = [150, 400, 800];
|
|
15703
16231
|
var SELECTION_CHROME_GAP2 = 4;
|
|
15704
16232
|
var TOOLBAR_STROKE_GAP2 = 4;
|
|
15705
16233
|
var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
|
|
@@ -16079,6 +16607,7 @@ function StateToggle({
|
|
|
16079
16607
|
);
|
|
16080
16608
|
}
|
|
16081
16609
|
var contentCache = /* @__PURE__ */ new Map();
|
|
16610
|
+
var fetchedContentPaths = /* @__PURE__ */ new Set();
|
|
16082
16611
|
var brandingCache = /* @__PURE__ */ new Map();
|
|
16083
16612
|
var OHW_LOADER_STYLE = {
|
|
16084
16613
|
position: "fixed",
|
|
@@ -16608,13 +17137,6 @@ function OhhwellsBridge() {
|
|
|
16608
17137
|
const [isItemDragging, setIsItemDragging] = (0, import_react17.useState)(false);
|
|
16609
17138
|
const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react17.useState)(false);
|
|
16610
17139
|
isFooterFrameSelectionRef.current = isFooterFrameSelection;
|
|
16611
|
-
const [floatingPanel, setFloatingPanel] = (0, import_react17.useState)(null);
|
|
16612
|
-
const floatingPanelOpenRef = (0, import_react17.useRef)(false);
|
|
16613
|
-
floatingPanelOpenRef.current = floatingPanel !== null;
|
|
16614
|
-
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react17.useState)(null);
|
|
16615
|
-
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react17.useState)(null);
|
|
16616
|
-
const [editorViewport, setEditorViewport] = (0, import_react17.useState)("desktop");
|
|
16617
|
-
const [parentScrollSnap, setParentScrollSnap] = (0, import_react17.useState)(null);
|
|
16618
17140
|
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react17.useState)(null);
|
|
16619
17141
|
const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react17.useState)(null);
|
|
16620
17142
|
const footerDragRef = (0, import_react17.useRef)(null);
|
|
@@ -16632,6 +17154,13 @@ function OhhwellsBridge() {
|
|
|
16632
17154
|
const brandKitRef = (0, import_react17.useRef)("");
|
|
16633
17155
|
const stylesRef = (0, import_react17.useRef)("");
|
|
16634
17156
|
const pendingDeleteUndoRef = (0, import_react17.useRef)(null);
|
|
17157
|
+
const [floatingPanel, setFloatingPanel] = (0, import_react17.useState)(null);
|
|
17158
|
+
const floatingPanelOpenRef = (0, import_react17.useRef)(false);
|
|
17159
|
+
const setFloatingPanelRef = (0, import_react17.useRef)(setFloatingPanel);
|
|
17160
|
+
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react17.useState)(null);
|
|
17161
|
+
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react17.useState)(null);
|
|
17162
|
+
const [editorViewport, setEditorViewport] = (0, import_react17.useState)("desktop");
|
|
17163
|
+
const [parentScrollSnap, setParentScrollSnap] = (0, import_react17.useState)(null);
|
|
16635
17164
|
const [sitePages, setSitePages] = (0, import_react17.useState)([]);
|
|
16636
17165
|
const [sectionsByPath, setSectionsByPath] = (0, import_react17.useState)({});
|
|
16637
17166
|
const sectionsPrefetchGenRef = (0, import_react17.useRef)(0);
|
|
@@ -16640,7 +17169,18 @@ function OhhwellsBridge() {
|
|
|
16640
17169
|
const linkPopoverOpenRef = (0, import_react17.useRef)(false);
|
|
16641
17170
|
const linkPopoverGraceUntilRef = (0, import_react17.useRef)(0);
|
|
16642
17171
|
setLinkPopoverRef.current = setLinkPopover;
|
|
17172
|
+
setFloatingPanelRef.current = setFloatingPanel;
|
|
16643
17173
|
linkPopoverSessionRef.current = linkPopover;
|
|
17174
|
+
floatingPanelOpenRef.current = Boolean(floatingPanel);
|
|
17175
|
+
(0, import_react17.useEffect)(() => {
|
|
17176
|
+
const syncViewport = () => {
|
|
17177
|
+
const next = window.innerWidth <= 480 ? "mobile" : "desktop";
|
|
17178
|
+
setEditorViewport((prev) => prev === next ? prev : next);
|
|
17179
|
+
};
|
|
17180
|
+
syncViewport();
|
|
17181
|
+
window.addEventListener("resize", syncViewport);
|
|
17182
|
+
return () => window.removeEventListener("resize", syncViewport);
|
|
17183
|
+
}, []);
|
|
16644
17184
|
const {
|
|
16645
17185
|
navDragRef,
|
|
16646
17186
|
navDropSlots,
|
|
@@ -17965,17 +18505,19 @@ function OhhwellsBridge() {
|
|
|
17965
18505
|
}
|
|
17966
18506
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
17967
18507
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
18508
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
17968
18509
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
17969
18510
|
}
|
|
17970
18511
|
applyBrandChrome(content);
|
|
18512
|
+
initSectionInstancesFromContent(content, window.location.pathname);
|
|
17971
18513
|
for (const [key, val] of Object.entries(content)) {
|
|
17972
18514
|
if (key === "__ohw_sections") continue;
|
|
17973
18515
|
if (key === AI_SECTIONS_KEY) continue;
|
|
18516
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
18517
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
17974
18518
|
if (key === BRAND_KIT_KEY) continue;
|
|
17975
18519
|
if (key === STYLE_STORE_KEY) continue;
|
|
17976
18520
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
17977
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
17978
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
17979
18521
|
if (applyVideoSettingNode(key, val)) continue;
|
|
17980
18522
|
if (applyCarouselNode(key, val)) continue;
|
|
17981
18523
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -18003,6 +18545,8 @@ function OhhwellsBridge() {
|
|
|
18003
18545
|
}
|
|
18004
18546
|
} else if (el.dataset.ohwEditable === "link") {
|
|
18005
18547
|
applyLinkHref(el, val);
|
|
18548
|
+
} else if (el.dataset.ohwEditable === "map") {
|
|
18549
|
+
applyMapQuery(el, val);
|
|
18006
18550
|
} else if (el.dataset.ohwEditable === "icon") {
|
|
18007
18551
|
applyIconMarkup(el, val);
|
|
18008
18552
|
} else if (el.dataset.ohwEditable === "form") {
|
|
@@ -18023,7 +18567,6 @@ function OhhwellsBridge() {
|
|
|
18023
18567
|
if (isEditModeRef.current) requestMissingSocialIconsRef.current();
|
|
18024
18568
|
enforceLinkHrefs();
|
|
18025
18569
|
initSectionsFromContent(content, true);
|
|
18026
|
-
initSectionInstancesFromContent(content, window.location.pathname);
|
|
18027
18570
|
sectionsLoadedRef.current = true;
|
|
18028
18571
|
pendingScheduleConfigRequests.current.splice(0).forEach(processConfigRequest);
|
|
18029
18572
|
if (imageLoads.length === 0) return Promise.resolve();
|
|
@@ -18042,7 +18585,9 @@ function OhhwellsBridge() {
|
|
|
18042
18585
|
let cancelled = false;
|
|
18043
18586
|
setFetchState("loading");
|
|
18044
18587
|
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
18045
|
-
|
|
18588
|
+
const initialPath = pathname;
|
|
18589
|
+
fetchedContentPaths.add(`${subdomain}::${initialPath}`);
|
|
18590
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
18046
18591
|
if (cancelled) return;
|
|
18047
18592
|
const content = data?.content ?? {};
|
|
18048
18593
|
const branding = Boolean(data?.showBranding);
|
|
@@ -18176,16 +18721,17 @@ function OhhwellsBridge() {
|
|
|
18176
18721
|
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
18177
18722
|
}
|
|
18178
18723
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
18724
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
18179
18725
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
18180
18726
|
}
|
|
18181
18727
|
for (const [key, val] of Object.entries(content)) {
|
|
18182
18728
|
if (key === "__ohw_sections") continue;
|
|
18183
18729
|
if (key === AI_SECTIONS_KEY) continue;
|
|
18730
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
18731
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
18184
18732
|
if (key === BRAND_KIT_KEY) continue;
|
|
18185
18733
|
if (key === STYLE_STORE_KEY) continue;
|
|
18186
18734
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
18187
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
18188
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
18189
18735
|
if (applyVideoSettingNode(key, val)) continue;
|
|
18190
18736
|
if (applyCarouselNode(key, val)) continue;
|
|
18191
18737
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -18200,6 +18746,8 @@ function OhhwellsBridge() {
|
|
|
18200
18746
|
if (video && video.src !== val) applyVideoSrc(video, val);
|
|
18201
18747
|
} else if (el.dataset.ohwEditable === "link") {
|
|
18202
18748
|
applyLinkHref(el, val);
|
|
18749
|
+
} else if (el.dataset.ohwEditable === "map") {
|
|
18750
|
+
applyMapQuery(el, val);
|
|
18203
18751
|
} else if (el.dataset.ohwEditable === "form") {
|
|
18204
18752
|
} else if (isIconMarkupValue(val)) {
|
|
18205
18753
|
} else if (el.innerHTML !== val) {
|
|
@@ -18231,6 +18779,17 @@ function OhhwellsBridge() {
|
|
|
18231
18779
|
debounceTimer = setTimeout(applyFromCache, 150);
|
|
18232
18780
|
};
|
|
18233
18781
|
applyFromCache();
|
|
18782
|
+
const pathCacheKey = `${subdomain}::${pathname}`;
|
|
18783
|
+
if (!fetchedContentPaths.has(pathCacheKey)) {
|
|
18784
|
+
fetchedContentPaths.add(pathCacheKey);
|
|
18785
|
+
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
18786
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
18787
|
+
if (!data?.content) return;
|
|
18788
|
+
contentCache.set(subdomain, data.content);
|
|
18789
|
+
applyFromCache();
|
|
18790
|
+
}).catch(() => {
|
|
18791
|
+
});
|
|
18792
|
+
}
|
|
18234
18793
|
observer = new MutationObserver(scheduleApply);
|
|
18235
18794
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
18236
18795
|
return () => {
|
|
@@ -18346,26 +18905,11 @@ function OhhwellsBridge() {
|
|
|
18346
18905
|
const t2 = setTimeout(measure, 500);
|
|
18347
18906
|
const ro = new ResizeObserver(schedule);
|
|
18348
18907
|
ro.observe(document.body);
|
|
18349
|
-
let lastWidth = window.innerWidth;
|
|
18350
|
-
let resizeTimers = [];
|
|
18351
|
-
const clearResizeTimers = () => {
|
|
18352
|
-
resizeTimers.forEach(clearTimeout);
|
|
18353
|
-
resizeTimers = [];
|
|
18354
|
-
};
|
|
18355
|
-
const handleResize = () => {
|
|
18356
|
-
if (window.innerWidth === lastWidth) return;
|
|
18357
|
-
lastWidth = window.innerWidth;
|
|
18358
|
-
clearResizeTimers();
|
|
18359
|
-
resizeTimers = HEIGHT_SETTLE_DELAYS.map((delay) => setTimeout(measure, delay));
|
|
18360
|
-
};
|
|
18361
|
-
window.addEventListener("resize", handleResize);
|
|
18362
18908
|
return () => {
|
|
18363
18909
|
clearTimeout(t1);
|
|
18364
18910
|
clearTimeout(t2);
|
|
18365
18911
|
if (raf != null) cancelAnimationFrame(raf);
|
|
18366
18912
|
ro.disconnect();
|
|
18367
|
-
clearResizeTimers();
|
|
18368
|
-
window.removeEventListener("resize", handleResize);
|
|
18369
18913
|
};
|
|
18370
18914
|
}, [pathname, isEditMode, postToParent2]);
|
|
18371
18915
|
(0, import_react17.useEffect)(() => {
|
|
@@ -18611,9 +19155,6 @@ function OhhwellsBridge() {
|
|
|
18611
19155
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
18612
19156
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
18613
19157
|
if (isInsideLinkEditor(target)) return;
|
|
18614
|
-
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
18615
|
-
clearMediaSelectionRef.current();
|
|
18616
|
-
}
|
|
18617
19158
|
if (isInsideFloatingPanel(target)) return;
|
|
18618
19159
|
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
18619
19160
|
if (target.closest(
|
|
@@ -18621,6 +19162,9 @@ function OhhwellsBridge() {
|
|
|
18621
19162
|
)) {
|
|
18622
19163
|
return;
|
|
18623
19164
|
}
|
|
19165
|
+
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
19166
|
+
clearMediaSelectionRef.current();
|
|
19167
|
+
}
|
|
18624
19168
|
{
|
|
18625
19169
|
const formEl = getFormElement(target);
|
|
18626
19170
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
@@ -18772,14 +19316,6 @@ function OhhwellsBridge() {
|
|
|
18772
19316
|
}
|
|
18773
19317
|
const clickedButton = findClosestButtonLike(target);
|
|
18774
19318
|
const buttonOnMedia = Boolean(clickedButton && isMediaEditable(editable) && editable.contains(clickedButton));
|
|
18775
|
-
console.log("[click-debug]", {
|
|
18776
|
-
editableType: editable.dataset.ohwEditable,
|
|
18777
|
-
editableTag: editable.tagName,
|
|
18778
|
-
targetTag: target.tagName,
|
|
18779
|
-
clickedButtonTag: clickedButton?.tagName ?? null,
|
|
18780
|
-
buttonOnMedia,
|
|
18781
|
-
isMediaEditableEditable: isMediaEditable(editable)
|
|
18782
|
-
});
|
|
18783
19319
|
if (isMediaEditable(editable) && !buttonOnMedia) {
|
|
18784
19320
|
e.preventDefault();
|
|
18785
19321
|
e.stopPropagation();
|
|
@@ -18806,11 +19342,6 @@ function OhhwellsBridge() {
|
|
|
18806
19342
|
const hrefLookupTarget = buttonOnMedia ? clickedButton : editable;
|
|
18807
19343
|
const hrefCtx = getHrefKeyFromElement(hrefLookupTarget);
|
|
18808
19344
|
const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
|
|
18809
|
-
console.log("[click-debug 2]", {
|
|
18810
|
-
hrefLookupTargetTag: hrefLookupTarget.tagName,
|
|
18811
|
-
hrefCtx: hrefCtx ? { key: hrefCtx.key } : null,
|
|
18812
|
-
navAnchorTag: navAnchor?.tagName ?? null
|
|
18813
|
-
});
|
|
18814
19345
|
if (navAnchor) {
|
|
18815
19346
|
e.preventDefault();
|
|
18816
19347
|
e.stopPropagation();
|
|
@@ -18980,6 +19511,9 @@ function OhhwellsBridge() {
|
|
|
18980
19511
|
setHoveredItemRect(null);
|
|
18981
19512
|
hoveredNavContainerRef.current = null;
|
|
18982
19513
|
setHoveredNavContainerRect(null);
|
|
19514
|
+
siblingHintElRef.current = null;
|
|
19515
|
+
setSiblingHintRect(null);
|
|
19516
|
+
setSiblingHintRects([]);
|
|
18983
19517
|
return;
|
|
18984
19518
|
}
|
|
18985
19519
|
{
|
|
@@ -19098,7 +19632,6 @@ function OhhwellsBridge() {
|
|
|
19098
19632
|
hoveredNavContainerRef.current = null;
|
|
19099
19633
|
setHoveredNavContainerRect(null);
|
|
19100
19634
|
hoveredItemElRef.current = editable;
|
|
19101
|
-
setHoveredItemRect(isSelectedForHoverRef.current(editable) ? null : editable.getBoundingClientRect());
|
|
19102
19635
|
}
|
|
19103
19636
|
}
|
|
19104
19637
|
}
|
|
@@ -19395,7 +19928,7 @@ function OhhwellsBridge() {
|
|
|
19395
19928
|
}
|
|
19396
19929
|
};
|
|
19397
19930
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
19398
|
-
if (linkPopoverOpenRef.current) {
|
|
19931
|
+
if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
19399
19932
|
if (hoveredImageRef.current) {
|
|
19400
19933
|
hoveredImageRef.current = null;
|
|
19401
19934
|
hoveredImageHasTextOverlapRef.current = false;
|
|
@@ -19760,8 +20293,7 @@ function OhhwellsBridge() {
|
|
|
19760
20293
|
};
|
|
19761
20294
|
const handleMouseMove = (e) => {
|
|
19762
20295
|
const { clientX, clientY } = e;
|
|
19763
|
-
if (
|
|
19764
|
-
if (isOverEditorChrome(clientX, clientY)) {
|
|
20296
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || isOverEditorChrome(clientX, clientY)) {
|
|
19765
20297
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
19766
20298
|
formHoverElRef.current = null;
|
|
19767
20299
|
setFormHoverRect(null);
|
|
@@ -19769,6 +20301,12 @@ function OhhwellsBridge() {
|
|
|
19769
20301
|
setHoveredItemRect(null);
|
|
19770
20302
|
hoveredNavContainerRef.current = null;
|
|
19771
20303
|
setHoveredNavContainerRect(null);
|
|
20304
|
+
siblingHintElRef.current = null;
|
|
20305
|
+
setSiblingHintRect(null);
|
|
20306
|
+
setSiblingHintRects([]);
|
|
20307
|
+
dismissImageHover();
|
|
20308
|
+
clearImageHover();
|
|
20309
|
+
setSectionGap(null);
|
|
19772
20310
|
return;
|
|
19773
20311
|
}
|
|
19774
20312
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
@@ -19780,7 +20318,11 @@ function OhhwellsBridge() {
|
|
|
19780
20318
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
19781
20319
|
const { clientX, clientY } = e.data;
|
|
19782
20320
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
19783
|
-
if (
|
|
20321
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
20322
|
+
dismissImageHover();
|
|
20323
|
+
clearImageHover();
|
|
20324
|
+
return;
|
|
20325
|
+
}
|
|
19784
20326
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
19785
20327
|
probeSectionGapAt(clientX, clientY);
|
|
19786
20328
|
probeImageAt(clientX, clientY);
|
|
@@ -20059,6 +20601,44 @@ function OhhwellsBridge() {
|
|
|
20059
20601
|
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
20060
20602
|
}, 400));
|
|
20061
20603
|
};
|
|
20604
|
+
const reapCommittedAiSections = (excludeIds) => {
|
|
20605
|
+
const aiState = parseAiSectionsState(aiSectionsRef.current);
|
|
20606
|
+
if (aiState.sections.length === 0) return [];
|
|
20607
|
+
let orderEntries = [];
|
|
20608
|
+
try {
|
|
20609
|
+
const parsed = JSON.parse(editContentRef.current[SECTION_ORDER_KEY] ?? "[]");
|
|
20610
|
+
if (Array.isArray(parsed)) orderEntries = parsed;
|
|
20611
|
+
} catch {
|
|
20612
|
+
return [];
|
|
20613
|
+
}
|
|
20614
|
+
const removedIds = orderEntries.filter((entry) => entry && typeof entry.instanceId === "string" && entry.removed).map((entry) => entry.instanceId);
|
|
20615
|
+
if (removedIds.length === 0) return [];
|
|
20616
|
+
const result = reapRemovedAiSections(aiState, parseStyleStore(stylesRef.current), removedIds, excludeIds);
|
|
20617
|
+
if (!result.changed) return [];
|
|
20618
|
+
const nodes = [];
|
|
20619
|
+
aiSectionsRef.current = serializeAiSectionsState(result.state);
|
|
20620
|
+
nodes.push({ key: AI_SECTIONS_KEY, text: aiSectionsRef.current });
|
|
20621
|
+
const reaped = new Set(result.reapedIds);
|
|
20622
|
+
const nextOrderJson = JSON.stringify(orderEntries.filter((entry) => !reaped.has(entry.instanceId)));
|
|
20623
|
+
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: nextOrderJson };
|
|
20624
|
+
setAiSectionOrder(nextOrderJson, window.location.pathname);
|
|
20625
|
+
nodes.push({ key: SECTION_ORDER_KEY, text: nextOrderJson });
|
|
20626
|
+
if (result.store) {
|
|
20627
|
+
stylesRef.current = JSON.stringify(result.store);
|
|
20628
|
+
nodes.push({ key: STYLE_STORE_KEY, text: stylesRef.current });
|
|
20629
|
+
}
|
|
20630
|
+
const nextContent = { ...editContentRef.current };
|
|
20631
|
+
for (const key of Object.keys(nextContent)) {
|
|
20632
|
+
if (key.startsWith(AI_SLOT_KEY_PREFIX) && result.slotPrefixes.some((prefix) => key.startsWith(prefix)) && nextContent[key] !== "") {
|
|
20633
|
+
nextContent[key] = "";
|
|
20634
|
+
nodes.push({ key, text: "" });
|
|
20635
|
+
}
|
|
20636
|
+
}
|
|
20637
|
+
editContentRef.current = nextContent;
|
|
20638
|
+
applyAiSectionsToDom(result.state);
|
|
20639
|
+
applyStylesToDom(parseStyleStore(stylesRef.current));
|
|
20640
|
+
return nodes;
|
|
20641
|
+
};
|
|
20062
20642
|
const handleHydrate = (e) => {
|
|
20063
20643
|
if (e.data?.type !== "ow:hydrate") return;
|
|
20064
20644
|
const content = e.data.content;
|
|
@@ -20077,9 +20657,11 @@ function OhhwellsBridge() {
|
|
|
20077
20657
|
}
|
|
20078
20658
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
20079
20659
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
20660
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
20080
20661
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
20081
20662
|
}
|
|
20082
20663
|
applyBrandChrome(content);
|
|
20664
|
+
initSectionInstancesFromContent(content, window.location.pathname);
|
|
20083
20665
|
let sectionsJson = null;
|
|
20084
20666
|
for (const [key, val] of Object.entries(content)) {
|
|
20085
20667
|
if (key === "__ohw_sections") {
|
|
@@ -20087,11 +20669,11 @@ function OhhwellsBridge() {
|
|
|
20087
20669
|
continue;
|
|
20088
20670
|
}
|
|
20089
20671
|
if (key === AI_SECTIONS_KEY) continue;
|
|
20672
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
20673
|
+
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
20090
20674
|
if (key === BRAND_KIT_KEY) continue;
|
|
20091
20675
|
if (key === STYLE_STORE_KEY) continue;
|
|
20092
20676
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
20093
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
20094
|
-
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
20095
20677
|
if (applyVideoSettingNode(key, val)) continue;
|
|
20096
20678
|
if (applyCarouselNode(key, val)) continue;
|
|
20097
20679
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -20105,6 +20687,8 @@ function OhhwellsBridge() {
|
|
|
20105
20687
|
if (video && video.src !== val) applyVideoSrc(video, val);
|
|
20106
20688
|
} else if (el.dataset.ohwEditable === "link") {
|
|
20107
20689
|
applyLinkHref(el, val);
|
|
20690
|
+
} else if (el.dataset.ohwEditable === "map") {
|
|
20691
|
+
applyMapQuery(el, val);
|
|
20108
20692
|
} else if (el.dataset.ohwEditable === "icon") {
|
|
20109
20693
|
applyIconMarkup(el, val);
|
|
20110
20694
|
} else if (isIconMarkupValue(val)) {
|
|
@@ -20121,12 +20705,16 @@ function OhhwellsBridge() {
|
|
|
20121
20705
|
sectionsLoadedRef.current = true;
|
|
20122
20706
|
pendingScheduleConfigRequests.current.splice(0).forEach(processConfigRequest);
|
|
20123
20707
|
}
|
|
20124
|
-
initSectionInstancesFromContent(content, window.location.pathname);
|
|
20125
20708
|
editContentRef.current = { ...editContentRef.current, ...content };
|
|
20126
20709
|
reconcileNavbarItemsFromContent(editContentRef.current);
|
|
20127
20710
|
reconcileFooterOrderFromContent(editContentRef.current);
|
|
20128
20711
|
syncNavigationDragCursorAttrs();
|
|
20129
20712
|
enforceLinkHrefs();
|
|
20713
|
+
const hydrateReapExclude = /* @__PURE__ */ new Set();
|
|
20714
|
+
const hydratePendingUndo = pendingDeleteUndoRef.current;
|
|
20715
|
+
if (hydratePendingUndo?.sectionInstanceId) hydrateReapExclude.add(hydratePendingUndo.sectionInstanceId);
|
|
20716
|
+
const reapNodes = reapCommittedAiSections(hydrateReapExclude);
|
|
20717
|
+
if (reapNodes.length > 0) postToParentRef.current({ type: "ow:change", nodes: reapNodes });
|
|
20130
20718
|
const hydratedHeight = document.body.scrollHeight;
|
|
20131
20719
|
if (hydratedHeight > 50) postToParentRef.current({ type: "ow:height", height: hydratedHeight });
|
|
20132
20720
|
postToParentRef.current({ type: "ow:hydrate-done" });
|
|
@@ -20266,12 +20854,35 @@ function OhhwellsBridge() {
|
|
|
20266
20854
|
window.addEventListener("message", handleAiSetBrand);
|
|
20267
20855
|
const handleAiSetStyles = (e) => {
|
|
20268
20856
|
if (e.data?.type !== "ow:ai-set-styles") return;
|
|
20269
|
-
|
|
20857
|
+
let value = typeof e.data.value === "string" ? e.data.value : "";
|
|
20270
20858
|
const previous = stylesRef.current;
|
|
20859
|
+
let previousSections;
|
|
20860
|
+
const store = parseStyleStore(value);
|
|
20861
|
+
if (store) {
|
|
20862
|
+
const folded = foldAlignIntoTrees(parseAiSectionsState(aiSectionsRef.current), store);
|
|
20863
|
+
if (folded.changed) {
|
|
20864
|
+
const nextSections = serializeAiSectionsState(folded.state);
|
|
20865
|
+
if (nextSections !== aiSectionsRef.current) {
|
|
20866
|
+
previousSections = aiSectionsRef.current;
|
|
20867
|
+
aiSectionsRef.current = nextSections;
|
|
20868
|
+
applyAiSectionsToDom(folded.state);
|
|
20869
|
+
postToParentRef.current({
|
|
20870
|
+
type: "ow:change",
|
|
20871
|
+
nodes: [{ key: AI_SECTIONS_KEY, text: nextSections }]
|
|
20872
|
+
});
|
|
20873
|
+
}
|
|
20874
|
+
value = JSON.stringify(folded.store);
|
|
20875
|
+
}
|
|
20876
|
+
}
|
|
20271
20877
|
stylesRef.current = value;
|
|
20272
20878
|
applyStylesToDom(parseStyleStore(value));
|
|
20273
20879
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: STYLE_STORE_KEY, text: value }] });
|
|
20274
|
-
postToParentRef.current({
|
|
20880
|
+
postToParentRef.current({
|
|
20881
|
+
type: "ow:ai-styles-applied",
|
|
20882
|
+
previous,
|
|
20883
|
+
value,
|
|
20884
|
+
...previousSections !== void 0 ? { previousSections } : {}
|
|
20885
|
+
});
|
|
20275
20886
|
};
|
|
20276
20887
|
window.addEventListener("message", handleAiSetStyles);
|
|
20277
20888
|
const handleGetBrand = (e) => {
|
|
@@ -20310,6 +20921,7 @@ function OhhwellsBridge() {
|
|
|
20310
20921
|
if (!entries) return;
|
|
20311
20922
|
const orderJson = JSON.stringify(entries);
|
|
20312
20923
|
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
20924
|
+
setAiSectionOrder(orderJson, window.location.pathname);
|
|
20313
20925
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
20314
20926
|
aiSectionApiRef.current?.clear();
|
|
20315
20927
|
window.dispatchEvent(new Event("resize"));
|
|
@@ -20318,6 +20930,7 @@ function OhhwellsBridge() {
|
|
|
20318
20930
|
const actionId = newInstanceId();
|
|
20319
20931
|
pendingDeleteUndoRef.current = {
|
|
20320
20932
|
actionId,
|
|
20933
|
+
sectionInstanceId: instanceId,
|
|
20321
20934
|
restore: () => {
|
|
20322
20935
|
const restoredEntries = getPageSectionOrderEntries(
|
|
20323
20936
|
editContentRef.current[SECTION_ORDER_KEY],
|
|
@@ -20327,6 +20940,7 @@ function OhhwellsBridge() {
|
|
|
20327
20940
|
if (!restored) return;
|
|
20328
20941
|
const restoredJson = JSON.stringify(restored);
|
|
20329
20942
|
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: restoredJson };
|
|
20943
|
+
setAiSectionOrder(restoredJson, window.location.pathname);
|
|
20330
20944
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: restoredJson }] });
|
|
20331
20945
|
window.dispatchEvent(new Event("resize"));
|
|
20332
20946
|
const restoreHeight = document.body.scrollHeight;
|
|
@@ -20343,6 +20957,34 @@ function OhhwellsBridge() {
|
|
|
20343
20957
|
});
|
|
20344
20958
|
};
|
|
20345
20959
|
window.addEventListener("message", handleDeleteSection);
|
|
20960
|
+
const handleDuplicateSection = (e) => {
|
|
20961
|
+
if (e.data?.type !== "ow:duplicate-section") return;
|
|
20962
|
+
const instanceId = typeof e.data.instanceId === "string" ? e.data.instanceId : "";
|
|
20963
|
+
if (!instanceId) return;
|
|
20964
|
+
const newId = newInstanceId();
|
|
20965
|
+
const currentEntries = getPageSectionOrderEntries(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname);
|
|
20966
|
+
const result = duplicateSectionInstance(instanceId, newId, window.location.pathname, currentEntries);
|
|
20967
|
+
if (!result) return;
|
|
20968
|
+
const { entries, keyRekeys } = result;
|
|
20969
|
+
const orderJson = JSON.stringify(entries);
|
|
20970
|
+
const nodes = [{ key: SECTION_ORDER_KEY, text: orderJson }];
|
|
20971
|
+
for (const { from, to } of keyRekeys) {
|
|
20972
|
+
const inherited = editContentRef.current[from];
|
|
20973
|
+
if (inherited !== void 0) nodes.push({ key: to, text: inherited });
|
|
20974
|
+
}
|
|
20975
|
+
editContentRef.current = {
|
|
20976
|
+
...editContentRef.current,
|
|
20977
|
+
...Object.fromEntries(nodes.map(({ key, text }) => [key, text]))
|
|
20978
|
+
};
|
|
20979
|
+
setAiSectionOrder(orderJson, window.location.pathname);
|
|
20980
|
+
postToParentRef.current({ type: "ow:change", nodes });
|
|
20981
|
+
window.dispatchEvent(new Event("resize"));
|
|
20982
|
+
const duplicateHeight = document.body.scrollHeight;
|
|
20983
|
+
if (duplicateHeight > 50) postToParentRef.current({ type: "ow:height", height: duplicateHeight });
|
|
20984
|
+
const clone = document.querySelector(`[data-ohw-instance="${CSS.escape(newId)}"]`);
|
|
20985
|
+
if (clone) aiSectionApiRef.current?.selectFromElement(clone);
|
|
20986
|
+
};
|
|
20987
|
+
window.addEventListener("message", handleDuplicateSection);
|
|
20346
20988
|
const handleDeactivate = (e) => {
|
|
20347
20989
|
if (e.data?.type !== "ow:deactivate") return;
|
|
20348
20990
|
if (document.documentElement.hasAttribute("data-ohw-panel-dragging")) return;
|
|
@@ -20352,6 +20994,12 @@ function OhhwellsBridge() {
|
|
|
20352
20994
|
closeLinkPopoverRef.current();
|
|
20353
20995
|
return;
|
|
20354
20996
|
}
|
|
20997
|
+
if (floatingPanelOpenRef.current) {
|
|
20998
|
+
setFloatingPanelRef.current(null);
|
|
20999
|
+
deselectRef.current();
|
|
21000
|
+
deactivateRef.current();
|
|
21001
|
+
return;
|
|
21002
|
+
}
|
|
20355
21003
|
deselectRef.current();
|
|
20356
21004
|
deactivateRef.current();
|
|
20357
21005
|
clearMediaSelectionRef.current();
|
|
@@ -20597,6 +21245,10 @@ function OhhwellsBridge() {
|
|
|
20597
21245
|
};
|
|
20598
21246
|
const handleSave = (e) => {
|
|
20599
21247
|
if (e.data?.type !== "ow:save") return;
|
|
21248
|
+
const pendingUndo = pendingDeleteUndoRef.current;
|
|
21249
|
+
const reapExclude = /* @__PURE__ */ new Set();
|
|
21250
|
+
if (pendingUndo?.sectionInstanceId) reapExclude.add(pendingUndo.sectionInstanceId);
|
|
21251
|
+
const reapNodes = reapCommittedAiSections(reapExclude);
|
|
20600
21252
|
const nodes = collectEditableNodes(editContentRef.current);
|
|
20601
21253
|
const tracker = document.querySelector("[data-ohw-sections-tracker]");
|
|
20602
21254
|
if (tracker?.textContent) nodes.push({ key: "__ohw_sections", type: "sections", text: tracker.textContent });
|
|
@@ -20616,6 +21268,11 @@ function OhhwellsBridge() {
|
|
|
20616
21268
|
const text = specs.length ? JSON.stringify(specs) : editContentRef.current[fieldsKey(formKey)];
|
|
20617
21269
|
if (text) nodes.push({ key: fieldsKey(formKey), type: "text", text });
|
|
20618
21270
|
});
|
|
21271
|
+
for (const reapNode of reapNodes) {
|
|
21272
|
+
if (reapNode.key.startsWith(AI_SLOT_KEY_PREFIX) && !nodes.some((n) => n.key === reapNode.key)) {
|
|
21273
|
+
nodes.push({ key: reapNode.key, type: "text", text: reapNode.text });
|
|
21274
|
+
}
|
|
21275
|
+
}
|
|
20619
21276
|
postToParentRef.current({ type: "ow:save-result", nodes });
|
|
20620
21277
|
};
|
|
20621
21278
|
const handleInsertSection = (e) => {
|
|
@@ -20626,8 +21283,12 @@ function OhhwellsBridge() {
|
|
|
20626
21283
|
if (inserted) {
|
|
20627
21284
|
const tracker = getSectionsTracker();
|
|
20628
21285
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
|
|
20629
|
-
const
|
|
20630
|
-
|
|
21286
|
+
const reportHeight = () => {
|
|
21287
|
+
const h = document.body.scrollHeight;
|
|
21288
|
+
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
21289
|
+
};
|
|
21290
|
+
reportHeight();
|
|
21291
|
+
setTimeout(reportHeight, 500);
|
|
20631
21292
|
}
|
|
20632
21293
|
};
|
|
20633
21294
|
const handleSwitchSchedule = (e) => {
|
|
@@ -21029,11 +21690,12 @@ function OhhwellsBridge() {
|
|
|
21029
21690
|
window.removeEventListener("message", handleMoveSection);
|
|
21030
21691
|
window.removeEventListener("message", handlePanelDragging);
|
|
21031
21692
|
window.removeEventListener("message", handleDeleteSection);
|
|
21693
|
+
window.removeEventListener("message", handleDuplicateSection);
|
|
21032
21694
|
window.removeEventListener("message", handleDeactivate);
|
|
21033
|
-
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
21034
21695
|
window.removeEventListener("message", handleToastAction);
|
|
21035
21696
|
window.removeEventListener("message", handleFormCount);
|
|
21036
21697
|
window.removeEventListener("message", handleUiEscape);
|
|
21698
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
21037
21699
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
21038
21700
|
autoSaveTimers.current.clear();
|
|
21039
21701
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
@@ -21236,7 +21898,7 @@ function OhhwellsBridge() {
|
|
|
21236
21898
|
postToParent2({
|
|
21237
21899
|
type: "ow:ready",
|
|
21238
21900
|
version: "1",
|
|
21239
|
-
bridgeVersion: "0.1.
|
|
21901
|
+
bridgeVersion: "0.1.86",
|
|
21240
21902
|
path: pathname,
|
|
21241
21903
|
nodes: collectEditableNodes(editContentRef.current),
|
|
21242
21904
|
sections
|
|
@@ -22155,6 +22817,59 @@ function OhhwellsBridge() {
|
|
|
22155
22817
|
) : null
|
|
22156
22818
|
] });
|
|
22157
22819
|
}
|
|
22820
|
+
|
|
22821
|
+
// src/ui/EmptySection.tsx
|
|
22822
|
+
var import_link = __toESM(require("next/link"), 1);
|
|
22823
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
22824
|
+
function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
|
|
22825
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
|
|
22826
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
22827
|
+
"p",
|
|
22828
|
+
{
|
|
22829
|
+
style: {
|
|
22830
|
+
fontFamily: "var(--brand-font-body)",
|
|
22831
|
+
fontSize: "0.75rem",
|
|
22832
|
+
fontWeight: 500,
|
|
22833
|
+
letterSpacing: "0.15em",
|
|
22834
|
+
textTransform: "uppercase",
|
|
22835
|
+
color: "var(--brand-accent)",
|
|
22836
|
+
marginBottom: "1.5rem"
|
|
22837
|
+
},
|
|
22838
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_link.default, { href: homeHref, style: { color: "inherit" }, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { ...eyebrowKey ? { "data-ohw-editable": "text", "data-ohw-key": eyebrowKey } : {}, children: "Home" }) })
|
|
22839
|
+
}
|
|
22840
|
+
),
|
|
22841
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
22842
|
+
"h1",
|
|
22843
|
+
{
|
|
22844
|
+
style: {
|
|
22845
|
+
fontFamily: "var(--brand-font-heading)",
|
|
22846
|
+
fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
|
|
22847
|
+
lineHeight: 1.1,
|
|
22848
|
+
letterSpacing: "-0.025em",
|
|
22849
|
+
color: "var(--brand-text)",
|
|
22850
|
+
marginBottom: "1rem"
|
|
22851
|
+
},
|
|
22852
|
+
...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
|
|
22853
|
+
children: title
|
|
22854
|
+
}
|
|
22855
|
+
),
|
|
22856
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
22857
|
+
"p",
|
|
22858
|
+
{
|
|
22859
|
+
style: {
|
|
22860
|
+
fontFamily: "var(--brand-font-body)",
|
|
22861
|
+
fontSize: "1rem",
|
|
22862
|
+
lineHeight: 1.7,
|
|
22863
|
+
fontWeight: 300,
|
|
22864
|
+
color: "var(--brand-text-muted)",
|
|
22865
|
+
maxWidth: "340px"
|
|
22866
|
+
},
|
|
22867
|
+
...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
|
|
22868
|
+
children: "This page doesn't have any content yet."
|
|
22869
|
+
}
|
|
22870
|
+
)
|
|
22871
|
+
] });
|
|
22872
|
+
}
|
|
22158
22873
|
// Annotate the CommonJS export names for ESM import in node:
|
|
22159
22874
|
0 && (module.exports = {
|
|
22160
22875
|
AI_DEFAULT_BRAND,
|
|
@@ -22172,6 +22887,7 @@ function OhhwellsBridge() {
|
|
|
22172
22887
|
DropdownMenuItem,
|
|
22173
22888
|
DropdownMenuSeparator,
|
|
22174
22889
|
DropdownMenuTrigger,
|
|
22890
|
+
EmptySection,
|
|
22175
22891
|
ItemActionToolbar,
|
|
22176
22892
|
ItemInteractionLayer,
|
|
22177
22893
|
LinkEditorPanel,
|