@ohhwells/bridge 0.1.91 → 0.1.92-next.269
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 +1179 -398
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -4
- package/dist/index.d.ts +32 -4
- package/dist/index.js +1178 -398
- 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,13 @@ 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], img, picture, figure, [data-ohw-editable="bg-image"]) { border-radius: 0 !important; }`,
|
|
497
|
+
`[data-ohw-style-corners="sharp"] :has(> img) { border-radius: 0 !important; }`
|
|
498
|
+
);
|
|
499
|
+
for (const align of ["left", "center", "right"]) {
|
|
500
|
+
rules.push(`[data-ohw-style-align="${align}"] { text-align: ${align} !important; }`);
|
|
501
|
+
}
|
|
406
502
|
return rules.join("\n");
|
|
407
503
|
}
|
|
408
504
|
var STYLE_FONT_LINK_ID = "ohw-style-fonts";
|
|
@@ -429,10 +525,25 @@ var SECTION_ATTRS = {
|
|
|
429
525
|
textDistribution: "data-ohw-style-distribution",
|
|
430
526
|
headlineScale: "data-ohw-style-headline",
|
|
431
527
|
imageAspect: "data-ohw-style-aspect",
|
|
432
|
-
spacing: "data-ohw-style-spacing"
|
|
528
|
+
spacing: "data-ohw-style-spacing",
|
|
529
|
+
cornerStyle: "data-ohw-style-corners",
|
|
530
|
+
align: "data-ohw-style-align"
|
|
433
531
|
};
|
|
434
532
|
var NODE_WROTE_ATTR = "data-ohw-style-node";
|
|
435
|
-
var NODE_PROPS = [
|
|
533
|
+
var NODE_PROPS = [
|
|
534
|
+
"color",
|
|
535
|
+
"font-family",
|
|
536
|
+
"font-size",
|
|
537
|
+
"background",
|
|
538
|
+
"text-align",
|
|
539
|
+
"justify-content",
|
|
540
|
+
"align-items"
|
|
541
|
+
];
|
|
542
|
+
var ALIGN_JUSTIFY = {
|
|
543
|
+
left: "flex-start",
|
|
544
|
+
center: "center",
|
|
545
|
+
right: "flex-end"
|
|
546
|
+
};
|
|
436
547
|
function saveInline(el, prop) {
|
|
437
548
|
const attr = `data-ohw-style-prev-${prop}`;
|
|
438
549
|
if (el.hasAttribute(attr)) return;
|
|
@@ -476,6 +587,10 @@ function clearNodeProps(root) {
|
|
|
476
587
|
function buttonSurfaceOf(el) {
|
|
477
588
|
return el.closest("a, button") ?? el;
|
|
478
589
|
}
|
|
590
|
+
function alignSubjectOf(el) {
|
|
591
|
+
const button = el.closest('[data-ohw-role="button"]');
|
|
592
|
+
return button?.parentElement ?? el;
|
|
593
|
+
}
|
|
479
594
|
function applyStylesToDom(store) {
|
|
480
595
|
ensureStyleSheet();
|
|
481
596
|
clearSectionAttrs(document);
|
|
@@ -521,6 +636,18 @@ function applyStylesToDom(store) {
|
|
|
521
636
|
el.style.setProperty("font-size", `${override.fontSize}px`, "important");
|
|
522
637
|
el.setAttribute(NODE_WROTE_ATTR, "");
|
|
523
638
|
}
|
|
639
|
+
if (override.align !== void 0) {
|
|
640
|
+
const subject = alignSubjectOf(el);
|
|
641
|
+
saveInline(subject, "text-align");
|
|
642
|
+
saveInline(subject, "justify-content");
|
|
643
|
+
subject.style.setProperty("text-align", override.align, "important");
|
|
644
|
+
subject.style.setProperty(
|
|
645
|
+
"justify-content",
|
|
646
|
+
ALIGN_JUSTIFY[override.align] ?? "flex-start",
|
|
647
|
+
"important"
|
|
648
|
+
);
|
|
649
|
+
subject.setAttribute(NODE_WROTE_ATTR, "");
|
|
650
|
+
}
|
|
524
651
|
if (override.buttonBackground !== void 0 || override.buttonText !== void 0) {
|
|
525
652
|
const surface = buttonSurfaceOf(el);
|
|
526
653
|
if (override.buttonBackground !== void 0) {
|
|
@@ -541,9 +668,535 @@ function applyStylesToDom(store) {
|
|
|
541
668
|
var import_react_dom = require("react-dom");
|
|
542
669
|
var import_client = require("react-dom/client");
|
|
543
670
|
|
|
671
|
+
// src/lib/sections.ts
|
|
672
|
+
var LINK_PICKER_EXCLUDED_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
|
|
673
|
+
function isChromeSection(el) {
|
|
674
|
+
return el.matches("header, nav, footer, aside");
|
|
675
|
+
}
|
|
676
|
+
function titleCaseSectionId(id) {
|
|
677
|
+
return id.split("-").filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
678
|
+
}
|
|
679
|
+
function parseSectionsFromRoot(root) {
|
|
680
|
+
const seen = /* @__PURE__ */ new Set();
|
|
681
|
+
const sections = [];
|
|
682
|
+
for (const el of root.querySelectorAll("[data-ohw-section]")) {
|
|
683
|
+
const id = el.getAttribute("data-ohw-section") ?? "";
|
|
684
|
+
if (!id || seen.has(id) || LINK_PICKER_EXCLUDED_IDS.has(id)) continue;
|
|
685
|
+
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
686
|
+
if (el.hasAttribute("data-ohw-ai-template-hidden") || el.hasAttribute("data-ohw-ai-removed") || el.hasAttribute("data-ohw-ai-replaced-by"))
|
|
687
|
+
continue;
|
|
688
|
+
seen.add(id);
|
|
689
|
+
const label = el.getAttribute("data-ohw-section-label") ?? titleCaseSectionId(id);
|
|
690
|
+
sections.push({ id, label });
|
|
691
|
+
}
|
|
692
|
+
return sections;
|
|
693
|
+
}
|
|
694
|
+
function collectSectionsFromDom() {
|
|
695
|
+
if (typeof document === "undefined") return [];
|
|
696
|
+
return parseSectionsFromRoot(document);
|
|
697
|
+
}
|
|
698
|
+
function parseSectionsFromHtml(html) {
|
|
699
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
700
|
+
return parseSectionsFromRoot(doc);
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// src/lib/section-instances.ts
|
|
704
|
+
var SECTION_ORDER_KEY = "__ohw_section_order";
|
|
705
|
+
var REMOVED_ATTR = "data-ohw-section-removed";
|
|
706
|
+
function isRemovedSection(el) {
|
|
707
|
+
return el.hasAttribute(REMOVED_ATTR);
|
|
708
|
+
}
|
|
709
|
+
function movableUnit(el) {
|
|
710
|
+
return el.closest("[data-ohw-section-container]") ?? el;
|
|
711
|
+
}
|
|
712
|
+
function sectionTypeOf(el) {
|
|
713
|
+
return el.getAttribute("data-ohw-section") ?? el.querySelector("[data-ohw-section]")?.getAttribute("data-ohw-section") ?? "";
|
|
714
|
+
}
|
|
715
|
+
function sectionElementOf(el) {
|
|
716
|
+
return el.hasAttribute("data-ohw-section") ? el : el.querySelector("[data-ohw-section]") ?? el;
|
|
717
|
+
}
|
|
718
|
+
function collectTopLevelUnits(predicate) {
|
|
719
|
+
const seen = /* @__PURE__ */ new Set();
|
|
720
|
+
const result = [];
|
|
721
|
+
document.querySelectorAll("[data-ohw-section]").forEach((el) => {
|
|
722
|
+
if (!predicate(el)) return;
|
|
723
|
+
const unit = movableUnit(el);
|
|
724
|
+
if (unit.parentElement?.closest("[data-ohw-section],[data-ohw-section-container]")) return;
|
|
725
|
+
if (seen.has(unit)) return;
|
|
726
|
+
seen.add(unit);
|
|
727
|
+
result.push(unit);
|
|
728
|
+
});
|
|
729
|
+
return result;
|
|
730
|
+
}
|
|
731
|
+
function topLevelSections() {
|
|
732
|
+
return collectTopLevelUnits((el) => !isChromeSection(el) && !isRemovedSection(movableUnit(el)));
|
|
733
|
+
}
|
|
734
|
+
function instanceIdOf(el) {
|
|
735
|
+
return el.dataset.ohwInstance ?? el.dataset.ohwSection ?? "";
|
|
736
|
+
}
|
|
737
|
+
function findByInstanceId(instanceId) {
|
|
738
|
+
const escapedId = CSS.escape(instanceId);
|
|
739
|
+
const direct = document.querySelector(`[data-ohw-instance="${escapedId}"]`);
|
|
740
|
+
if (direct) return movableUnit(direct);
|
|
741
|
+
const bare = document.querySelector(`[data-ohw-section="${escapedId}"]:not([data-ohw-instance])`);
|
|
742
|
+
return bare ? movableUnit(bare) : null;
|
|
743
|
+
}
|
|
744
|
+
function planSectionMove(instanceId, targetIndex, currentPath) {
|
|
745
|
+
const sections = topLevelSections();
|
|
746
|
+
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
747
|
+
if (index === -1) return null;
|
|
748
|
+
const dragged = sections[index];
|
|
749
|
+
const others = sections.filter((_, i) => i !== index);
|
|
750
|
+
const clamped = Math.max(0, Math.min(targetIndex, others.length));
|
|
751
|
+
const reordered = [...others.slice(0, clamped), dragged, ...others.slice(clamped)];
|
|
752
|
+
return reordered.map((el, order) => ({
|
|
753
|
+
instanceId: instanceIdOf(el),
|
|
754
|
+
type: sectionTypeOf(el),
|
|
755
|
+
order,
|
|
756
|
+
pagePath: currentPath
|
|
757
|
+
}));
|
|
758
|
+
}
|
|
759
|
+
function moveSectionInstance(instanceId, direction, currentPath) {
|
|
760
|
+
const sections = topLevelSections();
|
|
761
|
+
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
762
|
+
if (index === -1) return null;
|
|
763
|
+
const siblingIndex = direction === "up" ? index - 1 : index + 1;
|
|
764
|
+
if (siblingIndex < 0 || siblingIndex >= sections.length) return null;
|
|
765
|
+
const entries = planSectionMove(instanceId, siblingIndex, currentPath);
|
|
766
|
+
if (!entries) return null;
|
|
767
|
+
applyPersistedOrder(entries);
|
|
768
|
+
return entries;
|
|
769
|
+
}
|
|
770
|
+
function syncRemovedFlags(entries) {
|
|
771
|
+
const removedIds = new Set(entries.filter((e) => e.removed).map((e) => e.instanceId));
|
|
772
|
+
document.querySelectorAll(`[${REMOVED_ATTR}]`).forEach((el) => {
|
|
773
|
+
if (!removedIds.has(instanceIdOf(el))) {
|
|
774
|
+
el.style.removeProperty("display");
|
|
775
|
+
el.removeAttribute(REMOVED_ATTR);
|
|
776
|
+
}
|
|
777
|
+
});
|
|
778
|
+
for (const id of removedIds) {
|
|
779
|
+
const el = findByInstanceId(id);
|
|
780
|
+
if (el) {
|
|
781
|
+
el.style.display = "none";
|
|
782
|
+
el.setAttribute(REMOVED_ATTR, "");
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
function applyPersistedOrder(entries) {
|
|
787
|
+
syncRemovedFlags(entries);
|
|
788
|
+
if (entries.length === 0) return;
|
|
789
|
+
const sections = topLevelSections();
|
|
790
|
+
if (sections.length === 0) return;
|
|
791
|
+
const orderIndex = new Map(entries.map((e) => [e.instanceId, e.order]));
|
|
792
|
+
const ordered = [...sections].sort((a, b) => {
|
|
793
|
+
const aOrder = orderIndex.get(instanceIdOf(a));
|
|
794
|
+
const bOrder = orderIndex.get(instanceIdOf(b));
|
|
795
|
+
if (aOrder === void 0 && bOrder === void 0) return 0;
|
|
796
|
+
if (aOrder === void 0) return 1;
|
|
797
|
+
if (bOrder === void 0) return -1;
|
|
798
|
+
return aOrder - bOrder;
|
|
799
|
+
});
|
|
800
|
+
let prev = null;
|
|
801
|
+
for (const el of ordered) {
|
|
802
|
+
if (prev) prev.after(el);
|
|
803
|
+
prev = el;
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
function setSectionRemoved(instanceId, currentPath, existingEntries, removed) {
|
|
807
|
+
if (!findByInstanceId(instanceId)) return null;
|
|
808
|
+
const byId = new Map(existingEntries.map((e) => [e.instanceId, e]));
|
|
809
|
+
const allSections = collectTopLevelUnits((el) => !isChromeSection(el));
|
|
810
|
+
allSections.forEach((el, order) => {
|
|
811
|
+
const id = instanceIdOf(el);
|
|
812
|
+
if (!byId.has(id)) {
|
|
813
|
+
byId.set(id, { instanceId: id, type: sectionTypeOf(el), order, pagePath: currentPath });
|
|
814
|
+
}
|
|
815
|
+
});
|
|
816
|
+
const target = byId.get(instanceId);
|
|
817
|
+
if (!target) return null;
|
|
818
|
+
byId.set(instanceId, { ...target, removed });
|
|
819
|
+
const entries = Array.from(byId.values());
|
|
820
|
+
applyPersistedOrder(entries);
|
|
821
|
+
return entries;
|
|
822
|
+
}
|
|
823
|
+
function deleteSectionInstance(instanceId, currentPath, existingEntries) {
|
|
824
|
+
return setSectionRemoved(instanceId, currentPath, existingEntries, true);
|
|
825
|
+
}
|
|
826
|
+
function restoreSectionInstance(instanceId, currentPath, existingEntries) {
|
|
827
|
+
return setSectionRemoved(instanceId, currentPath, existingEntries, false);
|
|
828
|
+
}
|
|
829
|
+
function duplicateSectionInstance(instanceId, newId, currentPath, existingEntries) {
|
|
830
|
+
const original = findByInstanceId(instanceId);
|
|
831
|
+
if (!original) return null;
|
|
832
|
+
const clone = original.cloneNode(true);
|
|
833
|
+
clone.setAttribute("data-ohw-instance", newId);
|
|
834
|
+
const keyRekeys = rekeySectionSubtree(clone, newId);
|
|
835
|
+
original.insertAdjacentElement("afterend", clone);
|
|
836
|
+
const byId = new Map(existingEntries.map((e) => [e.instanceId, e]));
|
|
837
|
+
const entries = topLevelSections().map((el, order) => {
|
|
838
|
+
const id = instanceIdOf(el);
|
|
839
|
+
return {
|
|
840
|
+
instanceId: id,
|
|
841
|
+
type: sectionTypeOf(el),
|
|
842
|
+
order,
|
|
843
|
+
pagePath: currentPath,
|
|
844
|
+
...byId.get(id)?.removed ? { removed: true } : {}
|
|
845
|
+
};
|
|
846
|
+
});
|
|
847
|
+
applyPersistedOrder(entries);
|
|
848
|
+
return { entries, keyRekeys };
|
|
849
|
+
}
|
|
850
|
+
function newInstanceId() {
|
|
851
|
+
return typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `instance-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
852
|
+
}
|
|
853
|
+
function getPageSectionOrderEntries(raw, currentPath) {
|
|
854
|
+
if (!raw) return [];
|
|
855
|
+
try {
|
|
856
|
+
const entries = JSON.parse(raw);
|
|
857
|
+
return entries.filter((e) => !e.pagePath || e.pagePath === currentPath);
|
|
858
|
+
} catch {
|
|
859
|
+
return [];
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
function mergePageSectionOrder(raw, currentPath, pageEntries) {
|
|
863
|
+
let all = [];
|
|
864
|
+
if (raw) {
|
|
865
|
+
try {
|
|
866
|
+
const parsed = JSON.parse(raw);
|
|
867
|
+
if (Array.isArray(parsed)) all = parsed;
|
|
868
|
+
} catch {
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
const otherPages = all.filter((e) => e && e.pagePath && e.pagePath !== currentPath);
|
|
872
|
+
const pageIds = new Set(pageEntries.map((e) => e.instanceId));
|
|
873
|
+
const removedHere = all.filter(
|
|
874
|
+
(e) => e && (!e.pagePath || e.pagePath === currentPath) && e.removed && !pageIds.has(e.instanceId)
|
|
875
|
+
);
|
|
876
|
+
return [...otherPages, ...removedHere, ...pageEntries];
|
|
877
|
+
}
|
|
878
|
+
function rekeySectionSubtree(root, instanceId) {
|
|
879
|
+
const suffix = `::${instanceId}`;
|
|
880
|
+
const pairs = [];
|
|
881
|
+
const rekey = (el, attr) => {
|
|
882
|
+
const current = el.getAttribute(attr);
|
|
883
|
+
if (!current) return;
|
|
884
|
+
const base = current.includes("::") ? current.slice(0, current.indexOf("::")) : current;
|
|
885
|
+
const next = `${base}${suffix}`;
|
|
886
|
+
el.setAttribute(attr, next);
|
|
887
|
+
pairs.push({ from: current, to: next });
|
|
888
|
+
};
|
|
889
|
+
if (root.hasAttribute("data-ohw-key")) rekey(root, "data-ohw-key");
|
|
890
|
+
if (root.hasAttribute("data-ohw-href-key")) rekey(root, "data-ohw-href-key");
|
|
891
|
+
root.querySelectorAll("[data-ohw-key]").forEach((el) => rekey(el, "data-ohw-key"));
|
|
892
|
+
root.querySelectorAll("[data-ohw-href-key]").forEach((el) => rekey(el, "data-ohw-href-key"));
|
|
893
|
+
return pairs;
|
|
894
|
+
}
|
|
895
|
+
function initSectionInstancesFromContent(content, currentPath) {
|
|
896
|
+
document.querySelectorAll("[data-ohw-section]:not([data-ohw-instance])").forEach((el) => {
|
|
897
|
+
el.setAttribute("data-ohw-instance", el.getAttribute("data-ohw-section") ?? "");
|
|
898
|
+
});
|
|
899
|
+
document.querySelectorAll("[data-ohw-section-container]:not([data-ohw-instance])").forEach((el) => {
|
|
900
|
+
const type = sectionTypeOf(el);
|
|
901
|
+
if (type) el.setAttribute("data-ohw-instance", type);
|
|
902
|
+
});
|
|
903
|
+
const entries = getPageSectionOrderEntries(content[SECTION_ORDER_KEY], currentPath);
|
|
904
|
+
for (const entry of entries) {
|
|
905
|
+
if (entry.instanceId === entry.type) continue;
|
|
906
|
+
if (document.querySelector(`[data-ohw-instance="${CSS.escape(entry.instanceId)}"]`)) continue;
|
|
907
|
+
const original = document.querySelector(
|
|
908
|
+
`[data-ohw-section="${CSS.escape(entry.type)}"][data-ohw-instance="${CSS.escape(entry.type)}"]`
|
|
909
|
+
);
|
|
910
|
+
if (!original) continue;
|
|
911
|
+
const clone = original.cloneNode(true);
|
|
912
|
+
clone.setAttribute("data-ohw-instance", entry.instanceId);
|
|
913
|
+
rekeySectionSubtree(clone, entry.instanceId);
|
|
914
|
+
original.insertAdjacentElement("afterend", clone);
|
|
915
|
+
}
|
|
916
|
+
applyPersistedOrder(entries);
|
|
917
|
+
}
|
|
918
|
+
|
|
544
919
|
// src/ui/ai-tree/AiTreeRenderer.tsx
|
|
545
920
|
var import_react = __toESM(require("react"), 1);
|
|
546
921
|
var import_lucide_react = require("lucide-react");
|
|
922
|
+
|
|
923
|
+
// src/lib/placeholder-imagery.ts
|
|
924
|
+
var U = (id) => `https://images.unsplash.com/photo-${id}?auto=format&fit=crop&w=1600&q=80`;
|
|
925
|
+
var GENERIC = [
|
|
926
|
+
U("1441986300917-64674bd600d8"),
|
|
927
|
+
U("1486406146926-c627a92ad1ab"),
|
|
928
|
+
U("1497032628192-86f99bcd76bc"),
|
|
929
|
+
U("1521737604893-d14cc237f11d"),
|
|
930
|
+
U("1522071820081-009f0129c71c"),
|
|
931
|
+
U("1519389950473-47ba0277781c"),
|
|
932
|
+
U("1460925895917-afdab827c52f"),
|
|
933
|
+
U("1504384308090-c894fdcc538d")
|
|
934
|
+
];
|
|
935
|
+
var PEOPLE = [
|
|
936
|
+
U("1500648767791-00dcc994a43e"),
|
|
937
|
+
U("1494790108377-be9c29b29330"),
|
|
938
|
+
U("1507003211169-0a1dd7228f2d"),
|
|
939
|
+
U("1438761681033-6461ffad8d80"),
|
|
940
|
+
U("1544005313-94ddf0286df2"),
|
|
941
|
+
U("1472099645785-5658abf4ff4e"),
|
|
942
|
+
U("1519085360753-af0119f7cbe7"),
|
|
943
|
+
U("1534528741775-53994a69daeb")
|
|
944
|
+
];
|
|
945
|
+
var THEMED = [
|
|
946
|
+
{
|
|
947
|
+
keywords: ["portrait", "headshot", "person", "people", "team", "staff", "avatar", "founder", "face"],
|
|
948
|
+
pool: PEOPLE
|
|
949
|
+
},
|
|
950
|
+
{
|
|
951
|
+
keywords: ["pet", "dog", "cat", "puppy", "kitten", "vet", "animal"],
|
|
952
|
+
pool: [
|
|
953
|
+
U("1548199973-03cce0bbc87b"),
|
|
954
|
+
U("1450778869180-41d0601e046e"),
|
|
955
|
+
U("1583511655857-d19b40a7a54e"),
|
|
956
|
+
U("1587300003388-59208cc962cb"),
|
|
957
|
+
U("1517849845537-4d257902454a"),
|
|
958
|
+
U("1601758228041-f3b2795255f1")
|
|
959
|
+
]
|
|
960
|
+
},
|
|
961
|
+
{
|
|
962
|
+
keywords: [
|
|
963
|
+
"baker",
|
|
964
|
+
"bakery",
|
|
965
|
+
"cafe",
|
|
966
|
+
"coffee",
|
|
967
|
+
"latte",
|
|
968
|
+
"restaurant",
|
|
969
|
+
"pastr",
|
|
970
|
+
"bread",
|
|
971
|
+
"cake",
|
|
972
|
+
"cater",
|
|
973
|
+
"chef",
|
|
974
|
+
"kitchen",
|
|
975
|
+
"food",
|
|
976
|
+
"pizza",
|
|
977
|
+
"dessert",
|
|
978
|
+
"brunch",
|
|
979
|
+
"bistro",
|
|
980
|
+
"deli",
|
|
981
|
+
"dish",
|
|
982
|
+
"menu"
|
|
983
|
+
],
|
|
984
|
+
pool: [
|
|
985
|
+
U("1509440159596-0249088772ff"),
|
|
986
|
+
U("1555507036-ab1f4038808a"),
|
|
987
|
+
U("1517433670267-08bbd4be890f"),
|
|
988
|
+
U("1486427944299-d1955d23e34d"),
|
|
989
|
+
U("1504754524776-8f4f37790ca0"),
|
|
990
|
+
U("1495474472287-4d71bcdd2085"),
|
|
991
|
+
U("1521017432531-fbd92d768814"),
|
|
992
|
+
U("1556909114-f6e7ad7d3136")
|
|
993
|
+
]
|
|
994
|
+
},
|
|
995
|
+
{
|
|
996
|
+
keywords: [
|
|
997
|
+
"shop",
|
|
998
|
+
"store",
|
|
999
|
+
"boutique",
|
|
1000
|
+
"retail",
|
|
1001
|
+
"clothing",
|
|
1002
|
+
"fashion",
|
|
1003
|
+
"jewel",
|
|
1004
|
+
"gift",
|
|
1005
|
+
"florist",
|
|
1006
|
+
"market",
|
|
1007
|
+
"grocer",
|
|
1008
|
+
"product",
|
|
1009
|
+
"storefront"
|
|
1010
|
+
],
|
|
1011
|
+
pool: [
|
|
1012
|
+
U("1441984904996-e0b6ba687e04"),
|
|
1013
|
+
U("1472851294608-062f824d29cc"),
|
|
1014
|
+
U("1523381210434-271e8be1f52b"),
|
|
1015
|
+
U("1534452203293-494d7ddbf7e0"),
|
|
1016
|
+
U("1445205170230-053b83016050"),
|
|
1017
|
+
U("1560243563-062bfc001d68")
|
|
1018
|
+
]
|
|
1019
|
+
},
|
|
1020
|
+
{
|
|
1021
|
+
keywords: [
|
|
1022
|
+
"yoga",
|
|
1023
|
+
"pilates",
|
|
1024
|
+
"fitness",
|
|
1025
|
+
"gym",
|
|
1026
|
+
"workout",
|
|
1027
|
+
"trainer",
|
|
1028
|
+
"wellness",
|
|
1029
|
+
"meditat",
|
|
1030
|
+
"massage",
|
|
1031
|
+
"therap",
|
|
1032
|
+
"physio",
|
|
1033
|
+
"chiro",
|
|
1034
|
+
"nutrition",
|
|
1035
|
+
"spa",
|
|
1036
|
+
"studio"
|
|
1037
|
+
],
|
|
1038
|
+
pool: [
|
|
1039
|
+
U("1544367567-0f2fcb009e0b"),
|
|
1040
|
+
U("1506126613408-eca07ce68773"),
|
|
1041
|
+
U("1545205597-3d9d02c29597"),
|
|
1042
|
+
U("1552196563-55cd4e45efb3"),
|
|
1043
|
+
U("1518611012118-696072aa579a"),
|
|
1044
|
+
U("1571019613454-1cb2f99b2d8b"),
|
|
1045
|
+
U("1540555700478-4be289fbecef"),
|
|
1046
|
+
U("1519824145371-296894a0daa9")
|
|
1047
|
+
]
|
|
1048
|
+
},
|
|
1049
|
+
{
|
|
1050
|
+
keywords: [
|
|
1051
|
+
"salon",
|
|
1052
|
+
"hairdress",
|
|
1053
|
+
"haircut",
|
|
1054
|
+
"barber",
|
|
1055
|
+
"manicure",
|
|
1056
|
+
"pedicure",
|
|
1057
|
+
"nails",
|
|
1058
|
+
"beauty",
|
|
1059
|
+
"makeup",
|
|
1060
|
+
"cosmetic",
|
|
1061
|
+
"eyelash",
|
|
1062
|
+
"eyebrow",
|
|
1063
|
+
"skincare",
|
|
1064
|
+
"esthetic",
|
|
1065
|
+
"waxing",
|
|
1066
|
+
"hair"
|
|
1067
|
+
],
|
|
1068
|
+
pool: [
|
|
1069
|
+
U("1560066984-138dadb4c035"),
|
|
1070
|
+
U("1522337660859-02fbefca4702"),
|
|
1071
|
+
U("1562322140-8baeececf3df"),
|
|
1072
|
+
U("1521590832167-7bcbfaa6381f"),
|
|
1073
|
+
U("1487412947147-5cebf100ffc2"),
|
|
1074
|
+
U("1526045478516-99145907023c")
|
|
1075
|
+
]
|
|
1076
|
+
},
|
|
1077
|
+
{
|
|
1078
|
+
keywords: [
|
|
1079
|
+
"cleaning",
|
|
1080
|
+
"plumb",
|
|
1081
|
+
"electric",
|
|
1082
|
+
"landscap",
|
|
1083
|
+
"contractor",
|
|
1084
|
+
"handyman",
|
|
1085
|
+
"renov",
|
|
1086
|
+
"hvac",
|
|
1087
|
+
"roofing",
|
|
1088
|
+
"painting",
|
|
1089
|
+
"carpentry",
|
|
1090
|
+
"flooring",
|
|
1091
|
+
"movers",
|
|
1092
|
+
"construction",
|
|
1093
|
+
"tools"
|
|
1094
|
+
],
|
|
1095
|
+
pool: [
|
|
1096
|
+
U("1581578731548-c64695cc6952"),
|
|
1097
|
+
U("1504307651254-35680f356dfd"),
|
|
1098
|
+
U("1581092160562-40aa08e78837"),
|
|
1099
|
+
U("1621905251189-08b45d6a269e"),
|
|
1100
|
+
U("1558618666-fcd25c85cd64"),
|
|
1101
|
+
U("1585128792020-803d29415281")
|
|
1102
|
+
]
|
|
1103
|
+
},
|
|
1104
|
+
{
|
|
1105
|
+
keywords: [
|
|
1106
|
+
"legal",
|
|
1107
|
+
"attorney",
|
|
1108
|
+
"lawyer",
|
|
1109
|
+
"account",
|
|
1110
|
+
"bookkeep",
|
|
1111
|
+
"consult",
|
|
1112
|
+
"coaching",
|
|
1113
|
+
"financ",
|
|
1114
|
+
"insurance",
|
|
1115
|
+
"realtor",
|
|
1116
|
+
"estate",
|
|
1117
|
+
"marketing",
|
|
1118
|
+
"agency",
|
|
1119
|
+
"office",
|
|
1120
|
+
"business",
|
|
1121
|
+
"desk"
|
|
1122
|
+
],
|
|
1123
|
+
pool: [
|
|
1124
|
+
U("1497366216548-37526070297c"),
|
|
1125
|
+
U("1497366811353-6870744d04b2"),
|
|
1126
|
+
U("1454165804606-c3d57bc86b40"),
|
|
1127
|
+
U("1521791136064-7986c2920216"),
|
|
1128
|
+
U("1556761175-b413da4baf72"),
|
|
1129
|
+
U("1542744173-8e7e53415bb0")
|
|
1130
|
+
]
|
|
1131
|
+
},
|
|
1132
|
+
{
|
|
1133
|
+
keywords: [
|
|
1134
|
+
"wedding",
|
|
1135
|
+
"event",
|
|
1136
|
+
"party",
|
|
1137
|
+
"celebrat",
|
|
1138
|
+
"venue",
|
|
1139
|
+
"community",
|
|
1140
|
+
"nonprofit",
|
|
1141
|
+
"charity",
|
|
1142
|
+
"workshop",
|
|
1143
|
+
"photograph",
|
|
1144
|
+
"concert"
|
|
1145
|
+
],
|
|
1146
|
+
pool: [
|
|
1147
|
+
U("1511578314322-379afb476865"),
|
|
1148
|
+
U("1501281668745-f7f57925c3b4"),
|
|
1149
|
+
U("1523580494863-6f3031224c94"),
|
|
1150
|
+
U("1540575467063-178a50c2df87"),
|
|
1151
|
+
U("1505236858219-8359eb29e329"),
|
|
1152
|
+
U("1528605248644-14dd04022da1")
|
|
1153
|
+
]
|
|
1154
|
+
}
|
|
1155
|
+
];
|
|
1156
|
+
function poolForSubject(subject) {
|
|
1157
|
+
for (const theme of THEMED) {
|
|
1158
|
+
if (theme.keywords.some((k) => subject.includes(k))) {
|
|
1159
|
+
return theme.pool;
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
return GENERIC;
|
|
1163
|
+
}
|
|
1164
|
+
function mixedHash(text) {
|
|
1165
|
+
let hash = 2166136261;
|
|
1166
|
+
for (let i = 0; i < text.length; i++) {
|
|
1167
|
+
hash ^= text.charCodeAt(i);
|
|
1168
|
+
hash = Math.imul(hash, 16777619);
|
|
1169
|
+
}
|
|
1170
|
+
return hash >>> 16 & 65535;
|
|
1171
|
+
}
|
|
1172
|
+
function resolvePlaceholderRef(ref) {
|
|
1173
|
+
const match = /^placeholder:([a-z0-9-]+)$/.exec(ref);
|
|
1174
|
+
if (!match) return null;
|
|
1175
|
+
const subject = match[1];
|
|
1176
|
+
const pool = poolForSubject(subject.replace(/-\d+$/, ""));
|
|
1177
|
+
return pool[mixedHash(ref) % pool.length];
|
|
1178
|
+
}
|
|
1179
|
+
function collectPlaceholderRefs(tree) {
|
|
1180
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1181
|
+
for (const match of JSON.stringify(tree ?? null).matchAll(/"(placeholder:[a-z0-9-]+)"/gu)) {
|
|
1182
|
+
seen.add(match[1]);
|
|
1183
|
+
}
|
|
1184
|
+
return [...seen];
|
|
1185
|
+
}
|
|
1186
|
+
function buildPlaceholderMap(tree) {
|
|
1187
|
+
const map = {};
|
|
1188
|
+
const cursor = /* @__PURE__ */ new Map();
|
|
1189
|
+
for (const ref of collectPlaceholderRefs(tree)) {
|
|
1190
|
+
const subject = ref.slice("placeholder:".length).replace(/-\d+$/, "");
|
|
1191
|
+
const pool = poolForSubject(subject);
|
|
1192
|
+
const start = cursor.get(pool) ?? mixedHash(ref) % pool.length;
|
|
1193
|
+
map[ref] = pool[start % pool.length];
|
|
1194
|
+
cursor.set(pool, start + 1);
|
|
1195
|
+
}
|
|
1196
|
+
return map;
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
// src/ui/ai-tree/AiTreeRenderer.tsx
|
|
547
1200
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
548
1201
|
function lucideByName(name) {
|
|
549
1202
|
const pascal = name.split("-").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
@@ -557,6 +1210,7 @@ var typeStyle = (spec, font) => ({
|
|
|
557
1210
|
fontWeight: spec.weight
|
|
558
1211
|
});
|
|
559
1212
|
var str = (value) => typeof value === "string" ? value : "";
|
|
1213
|
+
var cardRadius = (slots) => slots.cornerStyle === "sharp" ? 0 : AI_TREE_TOKENS.radiusCard;
|
|
560
1214
|
var featureLines = (value) => value.split(/\n|<br\s*\/?>/i).map((line) => line.trim()).filter(Boolean);
|
|
561
1215
|
var CHECK_MASK = `data:image/svg+xml,${encodeURIComponent(
|
|
562
1216
|
'<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>'
|
|
@@ -583,6 +1237,25 @@ var FEATURE_LINE_CSS = [
|
|
|
583
1237
|
`background-color:currentColor;-webkit-mask:url("${CHECK_MASK}") no-repeat 0 0/24px 24px;`,
|
|
584
1238
|
`mask:url("${CHECK_MASK}") no-repeat 0 0/24px 24px}`
|
|
585
1239
|
].join("");
|
|
1240
|
+
function buttonShellStyle(ctx, fullWidth) {
|
|
1241
|
+
const bs = ctx.buttonStyle;
|
|
1242
|
+
if (bs) {
|
|
1243
|
+
return {
|
|
1244
|
+
borderRadius: bs.radius,
|
|
1245
|
+
...bs.padding ? { padding: bs.padding } : {},
|
|
1246
|
+
...bs.fontFamily ? { fontFamily: bs.fontFamily } : { fontFamily: ctx.brand.fonts.body },
|
|
1247
|
+
...bs.fontSize ? { fontSize: bs.fontSize } : {},
|
|
1248
|
+
...bs.fontWeight ? { fontWeight: bs.fontWeight } : {},
|
|
1249
|
+
...bs.letterSpacing && bs.letterSpacing !== "normal" ? { letterSpacing: bs.letterSpacing } : {},
|
|
1250
|
+
...bs.textTransform && bs.textTransform !== "none" ? { textTransform: bs.textTransform } : {}
|
|
1251
|
+
};
|
|
1252
|
+
}
|
|
1253
|
+
return {
|
|
1254
|
+
borderRadius: AI_TREE_TOKENS.radiusButton,
|
|
1255
|
+
padding: fullWidth ? `${AI_TREE_TOKENS.spacing2}px ${AI_TREE_TOKENS.spacing4}px` : `${AI_TREE_TOKENS.spacing3}px ${AI_TREE_TOKENS.spacing6}px`,
|
|
1256
|
+
...typeStyle(AI_TREE_TOKENS.type.button, ctx.brand.fonts.body)
|
|
1257
|
+
};
|
|
1258
|
+
}
|
|
586
1259
|
function hexLuminance(color) {
|
|
587
1260
|
const m = /^#([0-9a-f]{6})$/i.exec(color.trim());
|
|
588
1261
|
if (!m) return null;
|
|
@@ -599,6 +1272,12 @@ function hexContrast(a, b) {
|
|
|
599
1272
|
const [hi, lo] = la > lb ? [la, lb] : [lb, la];
|
|
600
1273
|
return (hi + 0.05) / (lo + 0.05);
|
|
601
1274
|
}
|
|
1275
|
+
function primaryButtonLabel(brand) {
|
|
1276
|
+
const darkC = hexContrast(brand.palette.primary, brand.palette.dark);
|
|
1277
|
+
const lightC = hexContrast(brand.palette.primary, AI_TREE_TOKENS.textPrimaryForeground);
|
|
1278
|
+
if (darkC === null || lightC === null) return AI_TREE_TOKENS.textPrimaryForeground;
|
|
1279
|
+
return darkC > lightC ? brand.palette.dark : AI_TREE_TOKENS.textPrimaryForeground;
|
|
1280
|
+
}
|
|
602
1281
|
function accentBandContext(brand) {
|
|
603
1282
|
const p = brand.palette;
|
|
604
1283
|
const lightWins = (hexContrast(p.light, p.primary) ?? 99) >= (hexContrast(p.dark, p.primary) ?? 0);
|
|
@@ -616,6 +1295,22 @@ function accentBandContext(brand) {
|
|
|
616
1295
|
function textAttrs(ctx, path) {
|
|
617
1296
|
return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
|
|
618
1297
|
}
|
|
1298
|
+
var AI_RESPONSIVE_CSS = [
|
|
1299
|
+
"@media (max-width: 960px) {",
|
|
1300
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: repeat(2, 1fr) !important; }",
|
|
1301
|
+
' [data-ai-responsive] [data-ai-grid="1"] { grid-template-columns: 1fr !important; }',
|
|
1302
|
+
"}",
|
|
1303
|
+
"@media (max-width: 640px) {",
|
|
1304
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
|
|
1305
|
+
" [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
|
|
1306
|
+
// Group containers flatten to a column on phones; span placements come along for free.
|
|
1307
|
+
" [data-ai-responsive] [data-ai-group] { display: flex !important; flex-direction: column !important; }",
|
|
1308
|
+
" [data-ai-responsive] [data-ai-group] > * { grid-column: auto !important; }",
|
|
1309
|
+
" [data-ai-responsive] [data-ai-section-inner] { padding-left: 20px !important; padding-right: 20px !important; }",
|
|
1310
|
+
" [data-ai-responsive] { overflow-x: hidden; }",
|
|
1311
|
+
" [data-ai-responsive] img { max-width: 100%; }",
|
|
1312
|
+
"}"
|
|
1313
|
+
].join("\n");
|
|
619
1314
|
var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
620
1315
|
function MediaBox({
|
|
621
1316
|
refValue,
|
|
@@ -628,13 +1323,17 @@ function MediaBox({
|
|
|
628
1323
|
const url = refValue ? ctx.resolveMedia(refValue) : null;
|
|
629
1324
|
const isIcon = /^(lucide|simple):/.test(refValue);
|
|
630
1325
|
const aspectRatio = aspect && /^\d+:\d+$/.test(aspect) ? aspect.replace(":", " / ") : void 0;
|
|
631
|
-
const editAttrs = ctx.keyFor && editPath
|
|
1326
|
+
const editAttrs = ctx.keyFor && editPath ? {
|
|
1327
|
+
"data-ohw-key": ctx.keyFor(editPath),
|
|
1328
|
+
"data-ohw-editable": isIcon ? "icon" : "image"
|
|
1329
|
+
} : {};
|
|
632
1330
|
if (isIcon) {
|
|
633
1331
|
const Icon = refValue.startsWith("lucide:") ? lucideByName(refValue.slice(7)) : null;
|
|
634
1332
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
635
1333
|
"span",
|
|
636
1334
|
{
|
|
637
1335
|
"data-ai-icon": refValue,
|
|
1336
|
+
...editAttrs,
|
|
638
1337
|
style: {
|
|
639
1338
|
display: "inline-flex",
|
|
640
1339
|
width: 48,
|
|
@@ -698,12 +1397,10 @@ function ButtonEl({
|
|
|
698
1397
|
width: fullWidth ? "100%" : void 0,
|
|
699
1398
|
alignItems: "center",
|
|
700
1399
|
justifyContent: "center",
|
|
701
|
-
padding: fullWidth ? `${AI_TREE_TOKENS.spacing2}px ${AI_TREE_TOKENS.spacing4}px` : `${AI_TREE_TOKENS.spacing3}px ${AI_TREE_TOKENS.spacing6}px`,
|
|
702
|
-
borderRadius: AI_TREE_TOKENS.radiusButton,
|
|
703
1400
|
textDecoration: "none",
|
|
704
1401
|
cursor: "pointer",
|
|
705
|
-
...
|
|
706
|
-
...secondary ? { border: `1px solid ${ctx.brand.palette.dark}`, color: ctx.brand.palette.dark } : { background: ctx.brand.palette.primary, color: ctx.buttonLabel ??
|
|
1402
|
+
...buttonShellStyle(ctx, fullWidth),
|
|
1403
|
+
...secondary ? { border: `1px solid ${ctx.brand.palette.dark}`, color: ctx.brand.palette.dark } : { background: ctx.brand.palette.primary, color: ctx.buttonLabel ?? primaryButtonLabel(ctx.brand) }
|
|
707
1404
|
},
|
|
708
1405
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...path ? textAttrs(ctx, `${path}.label`) : {}, children: str(slots.label) })
|
|
709
1406
|
}
|
|
@@ -729,7 +1426,7 @@ function TextBlock({ slots, ctx, path }) {
|
|
|
729
1426
|
}
|
|
730
1427
|
function SectionHeaderBlock({ node, ctx, path }) {
|
|
731
1428
|
const slots = node.slots ?? {};
|
|
732
|
-
const align = slots.alignment === "center" ? "center" : "left";
|
|
1429
|
+
const align = node.align ?? (slots.alignment === "center" ? "center" : "left");
|
|
733
1430
|
const children = node.children ?? [];
|
|
734
1431
|
const buttonRowIdx = children.findIndex((c) => c.type === "button-row");
|
|
735
1432
|
const buttonRow = buttonRowIdx >= 0 ? children[buttonRowIdx] : void 0;
|
|
@@ -773,7 +1470,7 @@ function SectionHeaderBlock({ node, ctx, path }) {
|
|
|
773
1470
|
display: "flex",
|
|
774
1471
|
gap: AI_TREE_TOKENS.spacing6,
|
|
775
1472
|
marginTop: AI_TREE_TOKENS.spacing8,
|
|
776
|
-
justifyContent: align === "center" ? "center" : "flex-start"
|
|
1473
|
+
justifyContent: align === "center" ? "center" : align === "right" ? "flex-end" : "flex-start"
|
|
777
1474
|
},
|
|
778
1475
|
children: (buttonRow.children ?? []).map((button, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
779
1476
|
ButtonEl,
|
|
@@ -879,10 +1576,11 @@ function PricingCard({ node, ctx, path }) {
|
|
|
879
1576
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
880
1577
|
"div",
|
|
881
1578
|
{
|
|
1579
|
+
"data-ohw-card": "",
|
|
882
1580
|
style: {
|
|
883
1581
|
background: hasBg ? ctx.brand.palette.light : "transparent",
|
|
884
1582
|
border: `1px solid ${dark}`,
|
|
885
|
-
borderRadius:
|
|
1583
|
+
borderRadius: cardRadius(slots),
|
|
886
1584
|
padding: AI_TREE_TOKENS.paddingBlock,
|
|
887
1585
|
display: "flex",
|
|
888
1586
|
flexDirection: "column",
|
|
@@ -987,10 +1685,11 @@ function TestimonialCard({ node, ctx, path }) {
|
|
|
987
1685
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
988
1686
|
"div",
|
|
989
1687
|
{
|
|
1688
|
+
"data-ohw-card": "",
|
|
990
1689
|
"data-ai-avatar-pos": avatarPos ?? void 0,
|
|
991
1690
|
style: {
|
|
992
1691
|
background: hasBg ? ctx.cardSurface : "transparent",
|
|
993
|
-
borderRadius: hasBg ?
|
|
1692
|
+
borderRadius: hasBg ? cardRadius(slots) : 0,
|
|
994
1693
|
overflow: "hidden",
|
|
995
1694
|
outline: slots.featured === true ? `2px solid ${ctx.brand.palette.primary}` : void 0,
|
|
996
1695
|
minWidth: 0
|
|
@@ -1025,10 +1724,11 @@ function TeamCard({ node, ctx, path }) {
|
|
|
1025
1724
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1026
1725
|
"div",
|
|
1027
1726
|
{
|
|
1727
|
+
"data-ohw-card": "",
|
|
1028
1728
|
"data-ai-avatar-pos": avatarPos ?? void 0,
|
|
1029
1729
|
style: {
|
|
1030
1730
|
background: hasBg ? ctx.cardSurface : "transparent",
|
|
1031
|
-
borderRadius: hasBg ?
|
|
1731
|
+
borderRadius: hasBg ? cardRadius(slots) : 0,
|
|
1032
1732
|
overflow: "hidden",
|
|
1033
1733
|
outline: slots.featured === true ? `2px solid ${ctx.brand.palette.primary}` : void 0,
|
|
1034
1734
|
minWidth: 0,
|
|
@@ -1106,7 +1806,7 @@ function CardBlock({ node, ctx, path }) {
|
|
|
1106
1806
|
editPath: `${path}.media`
|
|
1107
1807
|
}
|
|
1108
1808
|
) : null;
|
|
1109
|
-
const centered = slots.alignment === "center";
|
|
1809
|
+
const centered = (node.align ?? slots.alignment) === "center";
|
|
1110
1810
|
const content = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1111
1811
|
"div",
|
|
1112
1812
|
{
|
|
@@ -1199,9 +1899,10 @@ function CardBlock({ node, ctx, path }) {
|
|
|
1199
1899
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1200
1900
|
"div",
|
|
1201
1901
|
{
|
|
1902
|
+
"data-ohw-card": "",
|
|
1202
1903
|
style: {
|
|
1203
1904
|
background: hasBg ? ctx.cardSurface : "transparent",
|
|
1204
|
-
borderRadius: hasBg ?
|
|
1905
|
+
borderRadius: hasBg ? cardRadius(slots) : 0,
|
|
1205
1906
|
overflow: "hidden",
|
|
1206
1907
|
outline: slots.featured === true ? `2px solid ${ctx.brand.palette.primary}` : void 0,
|
|
1207
1908
|
display: horizontal ? "flex" : "block",
|
|
@@ -1229,7 +1930,7 @@ function CardBlock({ node, ctx, path }) {
|
|
|
1229
1930
|
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1230
1931
|
"div",
|
|
1231
1932
|
{
|
|
1232
|
-
style: /^(lucide|simple):/.test(mediaRef) ? { padding: `${AI_TREE_TOKENS.paddingBlock}px ${AI_TREE_TOKENS.paddingBlock}px 0` } : hasBg ? void 0 : { borderRadius:
|
|
1933
|
+
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
1934
|
children: media
|
|
1234
1935
|
}
|
|
1235
1936
|
)),
|
|
@@ -1520,7 +2221,7 @@ function CollectionBlock({ node, ctx, path }) {
|
|
|
1520
2221
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1521
2222
|
"div",
|
|
1522
2223
|
{
|
|
1523
|
-
"data-ai-grid":
|
|
2224
|
+
"data-ai-grid": String(itemsPerRow),
|
|
1524
2225
|
style: {
|
|
1525
2226
|
display: "grid",
|
|
1526
2227
|
gridTemplateColumns: `repeat(${itemsPerRow}, 1fr)`,
|
|
@@ -1640,6 +2341,32 @@ function renderNode(node, ctx, path) {
|
|
|
1640
2341
|
if (child) {
|
|
1641
2342
|
return renderNode(child, ctx, `${path}.c0`);
|
|
1642
2343
|
}
|
|
2344
|
+
if (str(slots.provider) === "map" && str(slots.query)) {
|
|
2345
|
+
const query = str(slots.query);
|
|
2346
|
+
const mapAttrs = ctx.keyFor ? {
|
|
2347
|
+
"data-ohw-key": ctx.keyFor(`${path}.query`),
|
|
2348
|
+
"data-ohw-editable": "map",
|
|
2349
|
+
"data-ohw-map-query": query
|
|
2350
|
+
} : {};
|
|
2351
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2352
|
+
"iframe",
|
|
2353
|
+
{
|
|
2354
|
+
...mapAttrs,
|
|
2355
|
+
"data-ai-embed": "map",
|
|
2356
|
+
title: str(slots.title) || "Map",
|
|
2357
|
+
src: `https://www.google.com/maps?q=${encodeURIComponent(query)}&output=embed`,
|
|
2358
|
+
loading: "lazy",
|
|
2359
|
+
referrerPolicy: "no-referrer-when-downgrade",
|
|
2360
|
+
style: {
|
|
2361
|
+
width: "100%",
|
|
2362
|
+
minHeight: 320,
|
|
2363
|
+
border: 0,
|
|
2364
|
+
borderRadius: AI_TREE_TOKENS.radiusCard,
|
|
2365
|
+
display: "block"
|
|
2366
|
+
}
|
|
2367
|
+
}
|
|
2368
|
+
);
|
|
2369
|
+
}
|
|
1643
2370
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1644
2371
|
"div",
|
|
1645
2372
|
{
|
|
@@ -1743,15 +2470,12 @@ function renderNode(node, ctx, path) {
|
|
|
1743
2470
|
alignSelf: submitAlign,
|
|
1744
2471
|
border: "none",
|
|
1745
2472
|
cursor: "pointer",
|
|
1746
|
-
padding
|
|
1747
|
-
|
|
1748
|
-
// CTA); 8px only when the page has no template button to match.
|
|
1749
|
-
borderRadius: ctx.buttonRadius ?? 8,
|
|
2473
|
+
// Shape/padding/typography follow the host template's own buttons.
|
|
2474
|
+
...buttonShellStyle(ctx),
|
|
1750
2475
|
// Brand-styled: primary fill, brand-derived label colour (not a fixed token) so it
|
|
1751
2476
|
// reads correctly on custom palettes.
|
|
1752
2477
|
background: ctx.brand.palette.primary,
|
|
1753
|
-
color: ctx.buttonLabel ?? ctx.brand
|
|
1754
|
-
...typeStyle(AI_TREE_TOKENS.type.button, ctx.brand.fonts.body)
|
|
2478
|
+
color: ctx.buttonLabel ?? primaryButtonLabel(ctx.brand)
|
|
1755
2479
|
},
|
|
1756
2480
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { ...textAttrs(ctx, `${path}.c${i}.label`), children: str(cs.label) })
|
|
1757
2481
|
},
|
|
@@ -1786,7 +2510,7 @@ function renderNode(node, ctx, path) {
|
|
|
1786
2510
|
function AiTreeRenderer({
|
|
1787
2511
|
tree,
|
|
1788
2512
|
brand,
|
|
1789
|
-
|
|
2513
|
+
buttonStyle,
|
|
1790
2514
|
resolveMedia,
|
|
1791
2515
|
editKeyPrefix
|
|
1792
2516
|
}) {
|
|
@@ -1796,13 +2520,18 @@ function AiTreeRenderer({
|
|
|
1796
2520
|
const resolvedBrand = brand ?? AI_DEFAULT_BRAND;
|
|
1797
2521
|
const band = (tree.settings ?? {}).sectionBackground === "accent" ? accentBandContext(resolvedBrand) : null;
|
|
1798
2522
|
const blockBrand = band?.brand ?? resolvedBrand;
|
|
2523
|
+
const placeholderMap = buildPlaceholderMap(tree);
|
|
1799
2524
|
const ctx = {
|
|
1800
2525
|
brand: blockBrand,
|
|
1801
|
-
|
|
2526
|
+
// An owner/library ref resolves through the host resolver; a `placeholder:<subject>` ref the
|
|
2527
|
+
// host cannot resolve falls back to real stock photography (the per-section map first, then a
|
|
2528
|
+
// standalone resolve), so generated galleries, image rows, and overlay backgrounds arrive with
|
|
2529
|
+
// photos instead of grey boxes.
|
|
2530
|
+
resolveMedia: (ref) => resolveMedia?.(ref) ?? placeholderMap[ref] ?? resolvePlaceholderRef(ref),
|
|
1802
2531
|
cardSurface: blockBrand.palette.light.toUpperCase() === AI_DEFAULT_BRAND.palette.light.toUpperCase() ? "#ECECEB" : `color-mix(in srgb, ${blockBrand.palette.light} 90%, ${blockBrand.palette.dark})`,
|
|
1803
2532
|
keyFor: editKeyPrefix ? (path) => `${editKeyPrefix}.${path}` : null,
|
|
1804
2533
|
sectionAlignment: (tree.settings ?? {}).alignment === "center" ? "center" : "left",
|
|
1805
|
-
|
|
2534
|
+
buttonStyle,
|
|
1806
2535
|
...band ? { buttonLabel: band.buttonLabel } : {}
|
|
1807
2536
|
};
|
|
1808
2537
|
const settings = tree.settings ?? {};
|
|
@@ -1825,11 +2554,25 @@ function AiTreeRenderer({
|
|
|
1825
2554
|
}
|
|
1826
2555
|
})();
|
|
1827
2556
|
const distributed = !isOverlay && settings.textDistribution;
|
|
2557
|
+
const rowAlignItems = (rowAlign) => {
|
|
2558
|
+
if (rowAlign === "top") return "start";
|
|
2559
|
+
if (rowAlign === "bottom") return "end";
|
|
2560
|
+
if (rowAlign === "center" || rowAlign === "stretch") return rowAlign;
|
|
2561
|
+
if (distributed === "space-between") return "stretch";
|
|
2562
|
+
return (distributed ?? settings.verticalPosition) === "top" ? "start" : "center";
|
|
2563
|
+
};
|
|
2564
|
+
const cellAlignStyle = (blockAlign) => blockAlign ? {
|
|
2565
|
+
display: "flex",
|
|
2566
|
+
flexDirection: "column",
|
|
2567
|
+
alignItems: blockAlign === "left" ? "flex-start" : blockAlign === "right" ? "flex-end" : "center",
|
|
2568
|
+
textAlign: blockAlign
|
|
2569
|
+
} : {};
|
|
1828
2570
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1829
2571
|
"section",
|
|
1830
2572
|
{
|
|
1831
2573
|
"data-ai-section": tree.tag ?? "",
|
|
1832
2574
|
...bgAttrs,
|
|
2575
|
+
"data-ai-responsive": "",
|
|
1833
2576
|
style: {
|
|
1834
2577
|
position: "relative",
|
|
1835
2578
|
padding: `${pad}px 0`,
|
|
@@ -1840,12 +2583,13 @@ function AiTreeRenderer({
|
|
|
1840
2583
|
color: settings.sectionBackground === "accent" ? blockBrand.palette.dark : void 0
|
|
1841
2584
|
},
|
|
1842
2585
|
children: [
|
|
1843
|
-
|
|
2586
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_RESPONSIVE_CSS }),
|
|
1844
2587
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_MOBILE_CSS }),
|
|
2588
|
+
isOverlay && backgroundUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { position: "absolute", inset: 0, background: `rgba(255,255,255,${overlayAlpha})` } }),
|
|
1845
2589
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1846
2590
|
"div",
|
|
1847
2591
|
{
|
|
1848
|
-
"data-ai-
|
|
2592
|
+
"data-ai-section-inner": "",
|
|
1849
2593
|
style: {
|
|
1850
2594
|
position: "relative",
|
|
1851
2595
|
maxWidth: AI_TREE_TOKENS.sectionMaxWidth,
|
|
@@ -1856,12 +2600,12 @@ function AiTreeRenderer({
|
|
|
1856
2600
|
children: tree.rows.map((row, r2) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1857
2601
|
"div",
|
|
1858
2602
|
{
|
|
1859
|
-
"data-ai-
|
|
2603
|
+
"data-ai-columns": "",
|
|
1860
2604
|
style: {
|
|
1861
2605
|
display: "grid",
|
|
1862
2606
|
gridTemplateColumns: "repeat(12, 1fr)",
|
|
1863
2607
|
gap: AI_TREE_TOKENS.spacing6,
|
|
1864
|
-
alignItems:
|
|
2608
|
+
alignItems: rowAlignItems(row.align),
|
|
1865
2609
|
marginTop: r2 > 0 ? AI_TREE_TOKENS.spacing8 : 0
|
|
1866
2610
|
},
|
|
1867
2611
|
children: (row.blocks ?? []).map((block, b) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -1871,6 +2615,8 @@ function AiTreeRenderer({
|
|
|
1871
2615
|
style: {
|
|
1872
2616
|
gridColumn: `span ${Math.min(12, Math.max(1, block.span))}`,
|
|
1873
2617
|
minWidth: 0,
|
|
2618
|
+
// Horizontal placement of the block's content within its column.
|
|
2619
|
+
...cellAlignStyle(block.align),
|
|
1874
2620
|
// space-between: each column becomes a flex column whose content spreads over
|
|
1875
2621
|
// the full row height instead of clumping at the top.
|
|
1876
2622
|
...distributed === "space-between" ? { display: "flex", flexDirection: "column", justifyContent: "space-between" } : {}
|
|
@@ -1893,9 +2639,13 @@ function AiTreeRenderer({
|
|
|
1893
2639
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1894
2640
|
var CONTAINER_ATTR = "data-ohw-ai-generated";
|
|
1895
2641
|
var REPLACED_ATTR = "data-ohw-ai-replaced-by";
|
|
1896
|
-
var
|
|
2642
|
+
var REMOVED_ATTR2 = "data-ohw-ai-removed";
|
|
1897
2643
|
var TEMPLATE_HIDDEN_ATTR = "data-ohw-ai-template-hidden";
|
|
1898
2644
|
var CHROME_SECTION_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
|
|
2645
|
+
function isChromeSection2(el) {
|
|
2646
|
+
if (CHROME_SECTION_IDS.has(el.getAttribute("data-ohw-section") ?? "")) return true;
|
|
2647
|
+
return el.tagName === "HEADER" || el.tagName === "FOOTER";
|
|
2648
|
+
}
|
|
1899
2649
|
function readRootVar(name) {
|
|
1900
2650
|
if (typeof document === "undefined") return "";
|
|
1901
2651
|
return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
|
|
@@ -1917,13 +2667,13 @@ function deriveBrandOverride() {
|
|
|
1917
2667
|
};
|
|
1918
2668
|
}
|
|
1919
2669
|
function deriveTemplateBrand() {
|
|
1920
|
-
const
|
|
1921
|
-
const
|
|
1922
|
-
const light = readRootVar("--color-light");
|
|
2670
|
+
const primary = readRootVar("--brand-primary") || readRootVar("--color-primary");
|
|
2671
|
+
const dark = readRootVar("--brand-text") || readRootVar("--color-dark");
|
|
2672
|
+
const light = readRootVar("--brand-background") || readRootVar("--color-light");
|
|
1923
2673
|
if (!dark || !primary || !light) return null;
|
|
1924
|
-
const accent = readRootVar("--color-accent");
|
|
1925
|
-
const heading = readRootVar("--font-heading") || readRootVar("--font-display");
|
|
1926
|
-
const body = readRootVar("--font-body");
|
|
2674
|
+
const accent = readRootVar("--brand-accent") || readRootVar("--color-accent");
|
|
2675
|
+
const heading = readRootVar("--brand-font-heading") || readRootVar("--font-heading") || readRootVar("--font-display");
|
|
2676
|
+
const body = readRootVar("--brand-font-body") || readRootVar("--font-body");
|
|
1927
2677
|
return {
|
|
1928
2678
|
palette: { dark, primary, accent: accent || dark, light },
|
|
1929
2679
|
fonts: {
|
|
@@ -1932,12 +2682,35 @@ function deriveTemplateBrand() {
|
|
|
1932
2682
|
}
|
|
1933
2683
|
};
|
|
1934
2684
|
}
|
|
1935
|
-
function
|
|
2685
|
+
function deriveTemplateButtonStyle() {
|
|
1936
2686
|
if (typeof document === "undefined") return null;
|
|
1937
|
-
const btn = document.
|
|
2687
|
+
const btn = Array.from(document.querySelectorAll('[data-ohw-role="button"]')).find(
|
|
2688
|
+
(el) => !el.closest(`[${CONTAINER_ATTR}]`)
|
|
2689
|
+
);
|
|
1938
2690
|
if (!btn) return null;
|
|
1939
|
-
const
|
|
1940
|
-
|
|
2691
|
+
const cs = getComputedStyle(btn);
|
|
2692
|
+
const corners = [
|
|
2693
|
+
cs.borderTopLeftRadius,
|
|
2694
|
+
cs.borderTopRightRadius,
|
|
2695
|
+
cs.borderBottomRightRadius,
|
|
2696
|
+
cs.borderBottomLeftRadius
|
|
2697
|
+
].map((v) => v || "0px");
|
|
2698
|
+
const radius = corners.every((v) => v === corners[0]) ? corners[0] : corners.join(" ");
|
|
2699
|
+
const px = (v) => parseFloat(v) || 0;
|
|
2700
|
+
const lineHeight = px(cs.lineHeight) || px(cs.fontSize) * 1.2;
|
|
2701
|
+
const contentH = btn.getBoundingClientRect().height - px(cs.borderTopWidth) - px(cs.borderBottomWidth);
|
|
2702
|
+
const impliedY = Math.round(Math.max(0, (contentH - lineHeight) / 2));
|
|
2703
|
+
const padY = Math.max(px(cs.paddingTop), px(cs.paddingBottom), impliedY);
|
|
2704
|
+
const padX = Math.max(px(cs.paddingLeft), px(cs.paddingRight));
|
|
2705
|
+
return {
|
|
2706
|
+
radius: radius || "10px",
|
|
2707
|
+
padding: `${padY}px ${padX}px`,
|
|
2708
|
+
fontFamily: cs.fontFamily || "",
|
|
2709
|
+
fontSize: cs.fontSize || "",
|
|
2710
|
+
fontWeight: cs.fontWeight || "",
|
|
2711
|
+
letterSpacing: cs.letterSpacing || "",
|
|
2712
|
+
textTransform: cs.textTransform || ""
|
|
2713
|
+
};
|
|
1941
2714
|
}
|
|
1942
2715
|
var mounted = /* @__PURE__ */ new Map();
|
|
1943
2716
|
function findTemplateSection(id) {
|
|
@@ -1953,6 +2726,19 @@ function findPlacementAnchor(id, exclude) {
|
|
|
1953
2726
|
for (const el of document.querySelectorAll(`[data-ohw-section="${CSS.escape(id)}"]`)) {
|
|
1954
2727
|
if (el === exclude) continue;
|
|
1955
2728
|
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
2729
|
+
if (isChromeSection2(el)) return null;
|
|
2730
|
+
return el;
|
|
2731
|
+
}
|
|
2732
|
+
return null;
|
|
2733
|
+
}
|
|
2734
|
+
function findFooterSection() {
|
|
2735
|
+
const byId = findTemplateSection("footer");
|
|
2736
|
+
if (byId) return byId;
|
|
2737
|
+
for (const el of Array.from(
|
|
2738
|
+
document.querySelectorAll("footer[data-ohw-section]")
|
|
2739
|
+
).reverse()) {
|
|
2740
|
+
if (el.hasAttribute(CONTAINER_ATTR)) continue;
|
|
2741
|
+
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
1956
2742
|
return el;
|
|
1957
2743
|
}
|
|
1958
2744
|
return null;
|
|
@@ -1979,7 +2765,7 @@ function placeContainer(container, entry) {
|
|
|
1979
2765
|
return;
|
|
1980
2766
|
}
|
|
1981
2767
|
}
|
|
1982
|
-
const footer =
|
|
2768
|
+
const footer = findFooterSection();
|
|
1983
2769
|
if (footer) {
|
|
1984
2770
|
footer.insertAdjacentElement("beforebegin", container);
|
|
1985
2771
|
} else {
|
|
@@ -1988,18 +2774,18 @@ function placeContainer(container, entry) {
|
|
|
1988
2774
|
}
|
|
1989
2775
|
function syncRemovedSections(state) {
|
|
1990
2776
|
const removed = new Set(state.removed ?? []);
|
|
1991
|
-
for (const el of document.querySelectorAll(`[${
|
|
2777
|
+
for (const el of document.querySelectorAll(`[${REMOVED_ATTR2}]`)) {
|
|
1992
2778
|
const id = el.getAttribute("data-ohw-section") ?? "";
|
|
1993
2779
|
if (!removed.has(id)) {
|
|
1994
2780
|
el.style.removeProperty("display");
|
|
1995
|
-
el.removeAttribute(
|
|
2781
|
+
el.removeAttribute(REMOVED_ATTR2);
|
|
1996
2782
|
}
|
|
1997
2783
|
}
|
|
1998
2784
|
for (const id of removed) {
|
|
1999
2785
|
const section = findTemplateSection(id);
|
|
2000
2786
|
if (section && !section.hasAttribute(REPLACED_ATTR)) {
|
|
2001
2787
|
section.style.display = "none";
|
|
2002
|
-
section.setAttribute(
|
|
2788
|
+
section.setAttribute(REMOVED_ATTR2, "");
|
|
2003
2789
|
}
|
|
2004
2790
|
}
|
|
2005
2791
|
}
|
|
@@ -2014,9 +2800,9 @@ function syncTemplateHidden(state, pageHasSections) {
|
|
|
2014
2800
|
if (!hide) return;
|
|
2015
2801
|
for (const el of Array.from(document.querySelectorAll("[data-ohw-section]"))) {
|
|
2016
2802
|
if (el.hasAttribute(CONTAINER_ATTR)) continue;
|
|
2017
|
-
if (
|
|
2803
|
+
if (isChromeSection2(el)) continue;
|
|
2018
2804
|
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
2019
|
-
if (el.hasAttribute(REPLACED_ATTR) || el.hasAttribute(
|
|
2805
|
+
if (el.hasAttribute(REPLACED_ATTR) || el.hasAttribute(REMOVED_ATTR2)) continue;
|
|
2020
2806
|
el.style.display = "none";
|
|
2021
2807
|
el.setAttribute(TEMPLATE_HIDDEN_ATTR, "");
|
|
2022
2808
|
}
|
|
@@ -2040,18 +2826,23 @@ function syncReplacedOriginals(state) {
|
|
|
2040
2826
|
}
|
|
2041
2827
|
}
|
|
2042
2828
|
var sectionOrderIndex = /* @__PURE__ */ new Map();
|
|
2829
|
+
var removedSectionIds = /* @__PURE__ */ new Set();
|
|
2043
2830
|
function setAiSectionOrder(raw, currentPath) {
|
|
2044
2831
|
const next = /* @__PURE__ */ new Map();
|
|
2832
|
+
const removed = /* @__PURE__ */ new Set();
|
|
2045
2833
|
if (raw) {
|
|
2046
2834
|
try {
|
|
2047
2835
|
const entries = JSON.parse(raw);
|
|
2048
2836
|
for (const entry of entries) {
|
|
2049
|
-
if (
|
|
2837
|
+
if (entry.pagePath && entry.pagePath !== currentPath) continue;
|
|
2838
|
+
next.set(entry.instanceId, entry.order);
|
|
2839
|
+
if (entry.removed) removed.add(entry.instanceId);
|
|
2050
2840
|
}
|
|
2051
2841
|
} catch {
|
|
2052
2842
|
}
|
|
2053
2843
|
}
|
|
2054
2844
|
sectionOrderIndex = next;
|
|
2845
|
+
removedSectionIds = removed;
|
|
2055
2846
|
}
|
|
2056
2847
|
function applyExplicitOrder(entries) {
|
|
2057
2848
|
if (sectionOrderIndex.size === 0) return entries;
|
|
@@ -2087,11 +2878,23 @@ function orderByChain(sections) {
|
|
|
2087
2878
|
for (const root of roots) visit(root);
|
|
2088
2879
|
return out.length === sections.length ? out : sections;
|
|
2089
2880
|
}
|
|
2881
|
+
function syncSoftRemovedGenerated() {
|
|
2882
|
+
for (const [id, section] of mounted) {
|
|
2883
|
+
const el = section.container;
|
|
2884
|
+
if (removedSectionIds.has(id)) {
|
|
2885
|
+
el.style.display = "none";
|
|
2886
|
+
el.setAttribute(REMOVED_ATTR, "");
|
|
2887
|
+
} else if (el.hasAttribute(REMOVED_ATTR)) {
|
|
2888
|
+
el.style.removeProperty("display");
|
|
2889
|
+
el.removeAttribute(REMOVED_ATTR);
|
|
2890
|
+
}
|
|
2891
|
+
}
|
|
2892
|
+
}
|
|
2090
2893
|
function applyAiSectionsToDom(state, options) {
|
|
2091
2894
|
if (typeof document === "undefined") return;
|
|
2092
2895
|
const brandOverride = deriveBrandOverride();
|
|
2093
2896
|
const templateBrand = deriveTemplateBrand();
|
|
2094
|
-
const
|
|
2897
|
+
const templateButtonStyle = deriveTemplateButtonStyle();
|
|
2095
2898
|
const brandKey = brandOverride ? JSON.stringify(brandOverride) : "";
|
|
2096
2899
|
const pagePath = window.location.pathname;
|
|
2097
2900
|
const pageSections = state.sections.filter((entry) => (entry.path ?? "/") === pagePath);
|
|
@@ -2131,7 +2934,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
2131
2934
|
{
|
|
2132
2935
|
tree: entry.tree,
|
|
2133
2936
|
brand: brandOverride ?? entry.brand ?? options?.brand ?? templateBrand ?? void 0,
|
|
2134
|
-
|
|
2937
|
+
buttonStyle: templateButtonStyle,
|
|
2135
2938
|
resolveMedia,
|
|
2136
2939
|
editKeyPrefix: `ai.${entry.id}`
|
|
2137
2940
|
}
|
|
@@ -2154,6 +2957,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
2154
2957
|
syncReplacedOriginals(state);
|
|
2155
2958
|
syncRemovedSections(state);
|
|
2156
2959
|
syncTemplateHidden(state, pageSections.length > 0);
|
|
2960
|
+
syncSoftRemovedGenerated();
|
|
2157
2961
|
}
|
|
2158
2962
|
|
|
2159
2963
|
// src/useLinkHrefGuardian.ts
|
|
@@ -7883,6 +8687,7 @@ function MediaOverlay({
|
|
|
7883
8687
|
(prev) => prev && prev.fullWidth === width && prev.height === height ? prev : { fullWidth: width, height }
|
|
7884
8688
|
);
|
|
7885
8689
|
}, [isVideo]);
|
|
8690
|
+
const replaceLabel = isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image";
|
|
7886
8691
|
const replaceMode = buttonSize ? replaceButtonMode({ width: rect.width, height: rect.height }, buttonSize) : "none";
|
|
7887
8692
|
const box = {
|
|
7888
8693
|
position: "fixed",
|
|
@@ -8012,17 +8817,17 @@ function MediaOverlay({
|
|
|
8012
8817
|
},
|
|
8013
8818
|
children: [
|
|
8014
8819
|
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 }),
|
|
8015
|
-
|
|
8820
|
+
replaceLabel
|
|
8016
8821
|
]
|
|
8017
8822
|
}
|
|
8018
8823
|
),
|
|
8019
|
-
replaceMode
|
|
8824
|
+
showChrome && replaceMode !== "none" && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
8020
8825
|
Button,
|
|
8021
8826
|
{
|
|
8022
8827
|
"data-ohw-media-overlay": "",
|
|
8023
8828
|
variant: "outline",
|
|
8024
8829
|
size: "sm",
|
|
8025
|
-
"aria-label":
|
|
8830
|
+
"aria-label": replaceLabel,
|
|
8026
8831
|
className: "gap-1.5 cursor-pointer hover:bg-background",
|
|
8027
8832
|
style: {
|
|
8028
8833
|
...OVERLAY_BUTTON_STYLE,
|
|
@@ -8045,7 +8850,7 @@ function MediaOverlay({
|
|
|
8045
8850
|
},
|
|
8046
8851
|
children: [
|
|
8047
8852
|
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 }),
|
|
8048
|
-
replaceMode === "full" ?
|
|
8853
|
+
replaceMode === "full" ? replaceLabel : null
|
|
8049
8854
|
]
|
|
8050
8855
|
}
|
|
8051
8856
|
)
|
|
@@ -8099,234 +8904,22 @@ function CarouselOverlay({
|
|
|
8099
8904
|
onClick: (e) => {
|
|
8100
8905
|
e.stopPropagation();
|
|
8101
8906
|
onEdit(hover.key);
|
|
8102
|
-
},
|
|
8103
|
-
children: [
|
|
8104
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react6.GalleryHorizontal, { size: 14 }),
|
|
8105
|
-
"Edit gallery"
|
|
8106
|
-
]
|
|
8107
|
-
}
|
|
8108
|
-
)
|
|
8109
|
-
}
|
|
8110
|
-
);
|
|
8111
|
-
}
|
|
8112
|
-
|
|
8113
|
-
// src/ui/ai-section/AiSectionOverlay.tsx
|
|
8114
|
-
var import_react8 = require("react");
|
|
8115
|
-
var import_lucide_react7 = require("lucide-react");
|
|
8116
|
-
|
|
8117
|
-
// src/lib/sections.ts
|
|
8118
|
-
var LINK_PICKER_EXCLUDED_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
|
|
8119
|
-
function isChromeSection(el) {
|
|
8120
|
-
return el.matches("header, nav, footer, aside");
|
|
8121
|
-
}
|
|
8122
|
-
function titleCaseSectionId(id) {
|
|
8123
|
-
return id.split("-").filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
8124
|
-
}
|
|
8125
|
-
function parseSectionsFromRoot(root) {
|
|
8126
|
-
const seen = /* @__PURE__ */ new Set();
|
|
8127
|
-
const sections = [];
|
|
8128
|
-
for (const el of root.querySelectorAll("[data-ohw-section]")) {
|
|
8129
|
-
const id = el.getAttribute("data-ohw-section") ?? "";
|
|
8130
|
-
if (!id || seen.has(id) || LINK_PICKER_EXCLUDED_IDS.has(id)) continue;
|
|
8131
|
-
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
8132
|
-
if (el.hasAttribute("data-ohw-ai-template-hidden") || el.hasAttribute("data-ohw-ai-removed") || el.hasAttribute("data-ohw-ai-replaced-by"))
|
|
8133
|
-
continue;
|
|
8134
|
-
seen.add(id);
|
|
8135
|
-
const label = el.getAttribute("data-ohw-section-label") ?? titleCaseSectionId(id);
|
|
8136
|
-
sections.push({ id, label });
|
|
8137
|
-
}
|
|
8138
|
-
return sections;
|
|
8139
|
-
}
|
|
8140
|
-
function collectSectionsFromDom() {
|
|
8141
|
-
if (typeof document === "undefined") return [];
|
|
8142
|
-
return parseSectionsFromRoot(document);
|
|
8143
|
-
}
|
|
8144
|
-
function parseSectionsFromHtml(html) {
|
|
8145
|
-
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
8146
|
-
return parseSectionsFromRoot(doc);
|
|
8147
|
-
}
|
|
8148
|
-
|
|
8149
|
-
// src/lib/section-instances.ts
|
|
8150
|
-
var SECTION_ORDER_KEY = "__ohw_section_order";
|
|
8151
|
-
var REMOVED_ATTR2 = "data-ohw-section-removed";
|
|
8152
|
-
function isRemovedSection(el) {
|
|
8153
|
-
return el.hasAttribute(REMOVED_ATTR2);
|
|
8154
|
-
}
|
|
8155
|
-
function topLevelSections() {
|
|
8156
|
-
return Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
|
|
8157
|
-
(el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el) && !isRemovedSection(el)
|
|
8158
|
-
);
|
|
8159
|
-
}
|
|
8160
|
-
function instanceIdOf(el) {
|
|
8161
|
-
return el.dataset.ohwInstance ?? el.dataset.ohwSection ?? "";
|
|
8162
|
-
}
|
|
8163
|
-
function findByInstanceId(instanceId) {
|
|
8164
|
-
const escapedId = CSS.escape(instanceId);
|
|
8165
|
-
return document.querySelector(`[data-ohw-instance="${escapedId}"]`) ?? document.querySelector(`[data-ohw-section="${escapedId}"]:not([data-ohw-instance])`);
|
|
8166
|
-
}
|
|
8167
|
-
function planSectionMove(instanceId, targetIndex, currentPath) {
|
|
8168
|
-
const sections = topLevelSections();
|
|
8169
|
-
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
8170
|
-
if (index === -1) return null;
|
|
8171
|
-
const dragged = sections[index];
|
|
8172
|
-
const others = sections.filter((_, i) => i !== index);
|
|
8173
|
-
const clamped = Math.max(0, Math.min(targetIndex, others.length));
|
|
8174
|
-
const reordered = [...others.slice(0, clamped), dragged, ...others.slice(clamped)];
|
|
8175
|
-
return reordered.map((el, order) => ({
|
|
8176
|
-
instanceId: instanceIdOf(el),
|
|
8177
|
-
type: el.getAttribute("data-ohw-section") ?? "",
|
|
8178
|
-
order,
|
|
8179
|
-
pagePath: currentPath
|
|
8180
|
-
}));
|
|
8181
|
-
}
|
|
8182
|
-
function moveSectionInstance(instanceId, direction, currentPath) {
|
|
8183
|
-
const sections = topLevelSections();
|
|
8184
|
-
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
8185
|
-
if (index === -1) return null;
|
|
8186
|
-
const siblingIndex = direction === "up" ? index - 1 : index + 1;
|
|
8187
|
-
if (siblingIndex < 0 || siblingIndex >= sections.length) return null;
|
|
8188
|
-
const entries = planSectionMove(instanceId, siblingIndex, currentPath);
|
|
8189
|
-
if (!entries) return null;
|
|
8190
|
-
applyPersistedOrder(entries);
|
|
8191
|
-
return entries;
|
|
8192
|
-
}
|
|
8193
|
-
function syncRemovedFlags(entries) {
|
|
8194
|
-
const removedIds = new Set(entries.filter((e) => e.removed).map((e) => e.instanceId));
|
|
8195
|
-
document.querySelectorAll(`[${REMOVED_ATTR2}]`).forEach((el) => {
|
|
8196
|
-
if (!removedIds.has(instanceIdOf(el))) {
|
|
8197
|
-
el.style.removeProperty("display");
|
|
8198
|
-
el.removeAttribute(REMOVED_ATTR2);
|
|
8199
|
-
}
|
|
8200
|
-
});
|
|
8201
|
-
for (const id of removedIds) {
|
|
8202
|
-
const el = findByInstanceId(id);
|
|
8203
|
-
if (el) {
|
|
8204
|
-
el.style.display = "none";
|
|
8205
|
-
el.setAttribute(REMOVED_ATTR2, "");
|
|
8907
|
+
},
|
|
8908
|
+
children: [
|
|
8909
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react6.GalleryHorizontal, { size: 14 }),
|
|
8910
|
+
"Edit gallery"
|
|
8911
|
+
]
|
|
8912
|
+
}
|
|
8913
|
+
)
|
|
8206
8914
|
}
|
|
8207
|
-
}
|
|
8208
|
-
}
|
|
8209
|
-
function applyPersistedOrder(entries) {
|
|
8210
|
-
syncRemovedFlags(entries);
|
|
8211
|
-
if (entries.length === 0) return;
|
|
8212
|
-
const sections = topLevelSections();
|
|
8213
|
-
if (sections.length === 0) return;
|
|
8214
|
-
const orderIndex = new Map(entries.map((e) => [e.instanceId, e.order]));
|
|
8215
|
-
const ordered = [...sections].sort((a, b) => {
|
|
8216
|
-
const aOrder = orderIndex.get(instanceIdOf(a));
|
|
8217
|
-
const bOrder = orderIndex.get(instanceIdOf(b));
|
|
8218
|
-
if (aOrder === void 0 && bOrder === void 0) return 0;
|
|
8219
|
-
if (aOrder === void 0) return 1;
|
|
8220
|
-
if (bOrder === void 0) return -1;
|
|
8221
|
-
return aOrder - bOrder;
|
|
8222
|
-
});
|
|
8223
|
-
let prev = null;
|
|
8224
|
-
for (const el of ordered) {
|
|
8225
|
-
if (prev) prev.after(el);
|
|
8226
|
-
prev = el;
|
|
8227
|
-
}
|
|
8228
|
-
}
|
|
8229
|
-
function setSectionRemoved(instanceId, currentPath, existingEntries, removed) {
|
|
8230
|
-
if (!findByInstanceId(instanceId)) return null;
|
|
8231
|
-
const byId = new Map(existingEntries.map((e) => [e.instanceId, e]));
|
|
8232
|
-
const allSections = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
|
|
8233
|
-
(el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el)
|
|
8234
8915
|
);
|
|
8235
|
-
allSections.forEach((el, order) => {
|
|
8236
|
-
const id = instanceIdOf(el);
|
|
8237
|
-
if (!byId.has(id)) {
|
|
8238
|
-
byId.set(id, { instanceId: id, type: el.getAttribute("data-ohw-section") ?? "", order, pagePath: currentPath });
|
|
8239
|
-
}
|
|
8240
|
-
});
|
|
8241
|
-
const target = byId.get(instanceId);
|
|
8242
|
-
if (!target) return null;
|
|
8243
|
-
byId.set(instanceId, { ...target, removed });
|
|
8244
|
-
const entries = Array.from(byId.values());
|
|
8245
|
-
applyPersistedOrder(entries);
|
|
8246
|
-
return entries;
|
|
8247
|
-
}
|
|
8248
|
-
function deleteSectionInstance(instanceId, currentPath, existingEntries) {
|
|
8249
|
-
return setSectionRemoved(instanceId, currentPath, existingEntries, true);
|
|
8250
|
-
}
|
|
8251
|
-
function restoreSectionInstance(instanceId, currentPath, existingEntries) {
|
|
8252
|
-
return setSectionRemoved(instanceId, currentPath, existingEntries, false);
|
|
8253
|
-
}
|
|
8254
|
-
function duplicateSectionInstance(instanceId, newId, currentPath, existingEntries) {
|
|
8255
|
-
const original = findByInstanceId(instanceId);
|
|
8256
|
-
if (!original) return null;
|
|
8257
|
-
const clone = original.cloneNode(true);
|
|
8258
|
-
clone.setAttribute("data-ohw-instance", newId);
|
|
8259
|
-
const keyRekeys = rekeySectionSubtree(clone, newId);
|
|
8260
|
-
original.insertAdjacentElement("afterend", clone);
|
|
8261
|
-
const byId = new Map(existingEntries.map((e) => [e.instanceId, e]));
|
|
8262
|
-
const entries = topLevelSections().map((el, order) => {
|
|
8263
|
-
const id = instanceIdOf(el);
|
|
8264
|
-
return {
|
|
8265
|
-
instanceId: id,
|
|
8266
|
-
type: el.getAttribute("data-ohw-section") ?? "",
|
|
8267
|
-
order,
|
|
8268
|
-
pagePath: currentPath,
|
|
8269
|
-
...byId.get(id)?.removed ? { removed: true } : {}
|
|
8270
|
-
};
|
|
8271
|
-
});
|
|
8272
|
-
applyPersistedOrder(entries);
|
|
8273
|
-
return { entries, keyRekeys };
|
|
8274
|
-
}
|
|
8275
|
-
function newInstanceId() {
|
|
8276
|
-
return typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `instance-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
8277
|
-
}
|
|
8278
|
-
function getPageSectionOrderEntries(raw, currentPath) {
|
|
8279
|
-
if (!raw) return [];
|
|
8280
|
-
try {
|
|
8281
|
-
const entries = JSON.parse(raw);
|
|
8282
|
-
return entries.filter((e) => !e.pagePath || e.pagePath === currentPath);
|
|
8283
|
-
} catch {
|
|
8284
|
-
return [];
|
|
8285
|
-
}
|
|
8286
|
-
}
|
|
8287
|
-
function rekeySectionSubtree(root, instanceId) {
|
|
8288
|
-
const suffix = `::${instanceId}`;
|
|
8289
|
-
const pairs = [];
|
|
8290
|
-
const rekey = (el, attr) => {
|
|
8291
|
-
const current = el.getAttribute(attr);
|
|
8292
|
-
if (!current) return;
|
|
8293
|
-
const base = current.includes("::") ? current.slice(0, current.indexOf("::")) : current;
|
|
8294
|
-
const next = `${base}${suffix}`;
|
|
8295
|
-
el.setAttribute(attr, next);
|
|
8296
|
-
pairs.push({ from: current, to: next });
|
|
8297
|
-
};
|
|
8298
|
-
if (root.hasAttribute("data-ohw-key")) rekey(root, "data-ohw-key");
|
|
8299
|
-
if (root.hasAttribute("data-ohw-href-key")) rekey(root, "data-ohw-href-key");
|
|
8300
|
-
root.querySelectorAll("[data-ohw-key]").forEach((el) => rekey(el, "data-ohw-key"));
|
|
8301
|
-
root.querySelectorAll("[data-ohw-href-key]").forEach((el) => rekey(el, "data-ohw-href-key"));
|
|
8302
|
-
return pairs;
|
|
8303
|
-
}
|
|
8304
|
-
function initSectionInstancesFromContent(content, currentPath) {
|
|
8305
|
-
document.querySelectorAll("[data-ohw-section]:not([data-ohw-instance])").forEach((el) => {
|
|
8306
|
-
el.setAttribute("data-ohw-instance", el.getAttribute("data-ohw-section") ?? "");
|
|
8307
|
-
});
|
|
8308
|
-
const entries = getPageSectionOrderEntries(content[SECTION_ORDER_KEY], currentPath);
|
|
8309
|
-
for (const entry of entries) {
|
|
8310
|
-
if (entry.instanceId === entry.type) continue;
|
|
8311
|
-
if (document.querySelector(`[data-ohw-instance="${CSS.escape(entry.instanceId)}"]`)) continue;
|
|
8312
|
-
const original = document.querySelector(
|
|
8313
|
-
`[data-ohw-section="${CSS.escape(entry.type)}"][data-ohw-instance="${CSS.escape(entry.type)}"]`
|
|
8314
|
-
);
|
|
8315
|
-
if (!original) continue;
|
|
8316
|
-
const clone = original.cloneNode(true);
|
|
8317
|
-
clone.setAttribute("data-ohw-instance", entry.instanceId);
|
|
8318
|
-
rekeySectionSubtree(clone, entry.instanceId);
|
|
8319
|
-
original.insertAdjacentElement("afterend", clone);
|
|
8320
|
-
}
|
|
8321
|
-
applyPersistedOrder(entries);
|
|
8322
8916
|
}
|
|
8323
8917
|
|
|
8324
8918
|
// src/ui/ai-section/AiSectionOverlay.tsx
|
|
8919
|
+
var import_react8 = require("react");
|
|
8920
|
+
var import_lucide_react7 = require("lucide-react");
|
|
8325
8921
|
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
8326
|
-
|
|
8327
|
-
const escaped = CSS.escape(instanceId);
|
|
8328
|
-
return document.querySelector(`[data-ohw-instance="${escaped}"]`) ?? document.querySelector(`[data-ohw-section="${escaped}"]:not([data-ohw-instance])`);
|
|
8329
|
-
}
|
|
8922
|
+
var findSectionElement = findByInstanceId;
|
|
8330
8923
|
function readRect(instanceId) {
|
|
8331
8924
|
const el = findSectionElement(instanceId);
|
|
8332
8925
|
if (!el) return null;
|
|
@@ -8366,7 +8959,7 @@ function useLiveSectionRect(sectionId) {
|
|
|
8366
8959
|
}
|
|
8367
8960
|
function computeSectionBoundaryFlags(instanceId) {
|
|
8368
8961
|
const topLevel = topLevelSections();
|
|
8369
|
-
const index = topLevel.findIndex((el) => (el
|
|
8962
|
+
const index = topLevel.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
8370
8963
|
if (index === -1) return { isFirst: true, isLast: true };
|
|
8371
8964
|
return { isFirst: index === 0, isLast: index === topLevel.length - 1 };
|
|
8372
8965
|
}
|
|
@@ -8450,18 +9043,20 @@ function AiSectionOverlay({
|
|
|
8450
9043
|
selectedIdRef.current = selectedId;
|
|
8451
9044
|
const report = (0, import_react8.useCallback)(
|
|
8452
9045
|
(el) => {
|
|
9046
|
+
const labelSrc = el ? sectionElementOf(el) : null;
|
|
8453
9047
|
postToParent2({
|
|
8454
9048
|
type: "ow:section-selected",
|
|
8455
|
-
sectionId: el ? el
|
|
8456
|
-
sectionLabel:
|
|
9049
|
+
sectionId: el ? instanceIdOf(el) || null : null,
|
|
9050
|
+
sectionLabel: labelSrc ? labelSrc.dataset.ohwSectionLabel ?? titleCaseSectionId(labelSrc.dataset.ohwSection ?? "") : null
|
|
8457
9051
|
});
|
|
8458
9052
|
},
|
|
8459
9053
|
[postToParent2]
|
|
8460
9054
|
);
|
|
8461
9055
|
const selectFromElement = (0, import_react8.useCallback)(
|
|
8462
9056
|
(el, options) => {
|
|
8463
|
-
const
|
|
8464
|
-
const
|
|
9057
|
+
const inner = el?.closest("[data-ohw-section]") ?? null;
|
|
9058
|
+
const sectionEl = inner ? movableUnit(inner) : null;
|
|
9059
|
+
const id = sectionEl ? instanceIdOf(sectionEl) || null : null;
|
|
8465
9060
|
if (id === selectedIdRef.current) return;
|
|
8466
9061
|
setSelectedId(id);
|
|
8467
9062
|
if (options?.report !== false) report(sectionEl);
|
|
@@ -8527,7 +9122,8 @@ function AiSectionOverlay({
|
|
|
8527
9122
|
return;
|
|
8528
9123
|
}
|
|
8529
9124
|
const sec = t.closest("[data-ohw-section]");
|
|
8530
|
-
|
|
9125
|
+
const unit = sec ? movableUnit(sec) : null;
|
|
9126
|
+
setHoveredId(unit ? instanceIdOf(unit) || null : null);
|
|
8531
9127
|
};
|
|
8532
9128
|
const onLeave = () => setHoveredId(null);
|
|
8533
9129
|
document.addEventListener("mousemove", onMove, { passive: true });
|
|
@@ -13038,6 +13634,7 @@ function readLogoSizeState(content, placement) {
|
|
|
13038
13634
|
function getLogoElement(el) {
|
|
13039
13635
|
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
13040
13636
|
if (marked) return marked;
|
|
13637
|
+
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
13041
13638
|
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
13042
13639
|
if (!root) return null;
|
|
13043
13640
|
const anchor = el.closest("a");
|
|
@@ -14104,15 +14701,17 @@ function useSectionDrag({
|
|
|
14104
14701
|
clearSectionDragVisuals();
|
|
14105
14702
|
return;
|
|
14106
14703
|
}
|
|
14107
|
-
const orderJson = JSON.stringify(
|
|
14704
|
+
const orderJson = JSON.stringify(
|
|
14705
|
+
mergePageSectionOrder(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname, entries)
|
|
14706
|
+
);
|
|
14108
14707
|
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
14109
14708
|
setAiSectionOrder(orderJson, window.location.pathname);
|
|
14110
14709
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
14111
|
-
applyPersistedOrder(
|
|
14710
|
+
applyPersistedOrder(getPageSectionOrderEntries(orderJson, window.location.pathname));
|
|
14112
14711
|
clearSectionDragVisuals();
|
|
14113
14712
|
requestAnimationFrame(() => {
|
|
14114
14713
|
if (editContentRef.current[SECTION_ORDER_KEY] === orderJson) {
|
|
14115
|
-
applyPersistedOrder(
|
|
14714
|
+
applyPersistedOrder(getPageSectionOrderEntries(orderJson, window.location.pathname));
|
|
14116
14715
|
}
|
|
14117
14716
|
requestAnimationFrame(() => {
|
|
14118
14717
|
window.dispatchEvent(new Event("resize"));
|
|
@@ -14145,8 +14744,9 @@ function useSectionDrag({
|
|
|
14145
14744
|
const target = e.target;
|
|
14146
14745
|
if (!(target instanceof HTMLElement)) return;
|
|
14147
14746
|
if (target.closest(SECTION_DRAG_EXCLUDED_SELECTOR)) return;
|
|
14148
|
-
const
|
|
14149
|
-
if (!
|
|
14747
|
+
const inner = target.closest("[data-ohw-section]");
|
|
14748
|
+
if (!inner || isChromeSection(inner) || inner.dataset.ohwSection === "footer") return;
|
|
14749
|
+
const sectionEl = movableUnit(inner);
|
|
14150
14750
|
if (!topLevelSections().includes(sectionEl)) return;
|
|
14151
14751
|
startSectionPressDrag(sectionEl, e.clientX, e.clientY, e.pointerId);
|
|
14152
14752
|
};
|
|
@@ -14413,6 +15013,9 @@ function collectEditableNodes(extraContent, root = document) {
|
|
|
14413
15013
|
if (el.dataset.ohwEditable === "link") {
|
|
14414
15014
|
return { key: el.dataset.ohwKey ?? "", type: "link", text: getLinkHref3(el) };
|
|
14415
15015
|
}
|
|
15016
|
+
if (el.dataset.ohwEditable === "map") {
|
|
15017
|
+
return { key: el.dataset.ohwKey ?? "", type: "map", text: el.dataset.ohwMapQuery ?? "" };
|
|
15018
|
+
}
|
|
14416
15019
|
return {
|
|
14417
15020
|
key: el.dataset.ohwKey ?? "",
|
|
14418
15021
|
type: el.dataset.ohwEditable ?? "text",
|
|
@@ -14975,21 +15578,10 @@ function parseSchedulingInsertAfter(insertAfter) {
|
|
|
14975
15578
|
insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
|
|
14976
15579
|
};
|
|
14977
15580
|
}
|
|
14978
|
-
function
|
|
14979
|
-
|
|
14980
|
-
const
|
|
14981
|
-
|
|
14982
|
-
return { effectiveInsertAfter, insertBefore };
|
|
14983
|
-
}
|
|
14984
|
-
function getSchedulingMountPoint(insertAfter) {
|
|
14985
|
-
const { anchor } = parseSchedulingInsertAfter(insertAfter);
|
|
14986
|
-
let anchorEl = document.querySelector(`[data-ohw-section="${anchor}"]`);
|
|
14987
|
-
if (!anchorEl && anchor === "scheduling") {
|
|
14988
|
-
const widgets = Array.from(document.querySelectorAll('[data-ohw-section^="scheduling-"]'));
|
|
14989
|
-
anchorEl = widgets.at(-1) ?? null;
|
|
14990
|
-
}
|
|
14991
|
-
if (!anchorEl) return null;
|
|
14992
|
-
return anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
15581
|
+
function resolveEntryAnchor(entry) {
|
|
15582
|
+
if (entry.anchorId !== void 0) return { anchorId: entry.anchorId, beforeId: entry.beforeId ?? null };
|
|
15583
|
+
const parsed = parseSchedulingInsertAfter(entry.insertAfter);
|
|
15584
|
+
return { anchorId: parsed.anchor, beforeId: parsed.insertBefore };
|
|
14993
15585
|
}
|
|
14994
15586
|
function schedulingMountDepth(insertAfter) {
|
|
14995
15587
|
if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
|
|
@@ -15006,8 +15598,7 @@ function getPageSchedulingEntries(raw) {
|
|
|
15006
15598
|
}
|
|
15007
15599
|
}
|
|
15008
15600
|
function isSchedulingWidgetMissing(entry) {
|
|
15009
|
-
|
|
15010
|
-
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
|
|
15601
|
+
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
|
|
15011
15602
|
}
|
|
15012
15603
|
function hasMissingSchedulingWidgets(entries) {
|
|
15013
15604
|
return entries.some(isSchedulingWidgetMissing);
|
|
@@ -15045,18 +15636,18 @@ function initSectionsFromContent(content, removeExisting = false, currentPath =
|
|
|
15045
15636
|
} catch {
|
|
15046
15637
|
}
|
|
15047
15638
|
}
|
|
15048
|
-
function mountSchedulingWidget(
|
|
15049
|
-
const
|
|
15050
|
-
const sectionId = schedulingSectionId(
|
|
15639
|
+
function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, beforeId, existingWidgetId) {
|
|
15640
|
+
const widgetId = existingWidgetId ?? (beforeId ? `${anchorId}${INSERT_BEFORE_MARKER}${beforeId}` : anchorId);
|
|
15641
|
+
const sectionId = schedulingSectionId(widgetId);
|
|
15051
15642
|
if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
|
|
15052
|
-
const
|
|
15053
|
-
if (!
|
|
15643
|
+
const anchorEl = document.querySelector(`[data-ohw-section="${anchorId}"]`);
|
|
15644
|
+
if (!anchorEl) return false;
|
|
15645
|
+
const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
15054
15646
|
const container = document.createElement("div");
|
|
15055
15647
|
container.dataset.ohwSectionContainer = "scheduling";
|
|
15056
|
-
container.dataset.ohwSection = sectionId;
|
|
15057
15648
|
container.dataset.ohwInstance = sectionId;
|
|
15058
|
-
if (
|
|
15059
|
-
const beforeAnchor = document.querySelector(`[data-ohw-section="${
|
|
15649
|
+
if (beforeId) {
|
|
15650
|
+
const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
|
|
15060
15651
|
const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
|
|
15061
15652
|
if (!beforePoint) return false;
|
|
15062
15653
|
beforePoint.insertAdjacentElement("beforebegin", container);
|
|
@@ -15067,20 +15658,26 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
15067
15658
|
}
|
|
15068
15659
|
tail.insertAdjacentElement("afterend", container);
|
|
15069
15660
|
}
|
|
15070
|
-
|
|
15071
|
-
|
|
15072
|
-
|
|
15073
|
-
|
|
15074
|
-
|
|
15075
|
-
|
|
15076
|
-
|
|
15077
|
-
|
|
15078
|
-
|
|
15079
|
-
|
|
15080
|
-
|
|
15081
|
-
|
|
15082
|
-
|
|
15083
|
-
|
|
15661
|
+
try {
|
|
15662
|
+
const root = (0, import_client2.createRoot)(container);
|
|
15663
|
+
schedulingRoots.set(container, root);
|
|
15664
|
+
(0, import_react_dom3.flushSync)(() => {
|
|
15665
|
+
root.render(
|
|
15666
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
15667
|
+
SchedulingWidget,
|
|
15668
|
+
{
|
|
15669
|
+
notifyOnConnect,
|
|
15670
|
+
initialScheduleId: scheduleId,
|
|
15671
|
+
insertAfter: widgetId
|
|
15672
|
+
}
|
|
15673
|
+
)
|
|
15674
|
+
);
|
|
15675
|
+
});
|
|
15676
|
+
} catch (err) {
|
|
15677
|
+
console.error("[ow:scheduling] render threw", err);
|
|
15678
|
+
container.remove();
|
|
15679
|
+
return false;
|
|
15680
|
+
}
|
|
15084
15681
|
const tracker = getSectionsTracker();
|
|
15085
15682
|
let sections = [];
|
|
15086
15683
|
try {
|
|
@@ -15088,10 +15685,12 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
15088
15685
|
} catch {
|
|
15089
15686
|
}
|
|
15090
15687
|
const inEditor = typeof window !== "undefined" && window.self !== window.top;
|
|
15091
|
-
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter ===
|
|
15688
|
+
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
|
|
15092
15689
|
sections.push({
|
|
15093
15690
|
type: "scheduling",
|
|
15094
|
-
insertAfter:
|
|
15691
|
+
insertAfter: widgetId,
|
|
15692
|
+
anchorId,
|
|
15693
|
+
beforeId: beforeId ?? null,
|
|
15095
15694
|
pagePath: window.location.pathname,
|
|
15096
15695
|
...scheduleId ? { scheduleId } : {}
|
|
15097
15696
|
});
|
|
@@ -15105,7 +15704,8 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
|
|
|
15105
15704
|
for (let i = pending.length - 1; i >= 0; i--) {
|
|
15106
15705
|
const entry = pending[i];
|
|
15107
15706
|
const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
|
|
15108
|
-
|
|
15707
|
+
const { anchorId, beforeId } = resolveEntryAnchor(entry);
|
|
15708
|
+
if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
|
|
15109
15709
|
pending.splice(i, 1);
|
|
15110
15710
|
}
|
|
15111
15711
|
}
|
|
@@ -15197,7 +15797,7 @@ var EDITOR_CHROME_SELECTOR = '[data-ohw-toolbar], [data-ohw-form-toolbar], [data
|
|
|
15197
15797
|
function isOverEditorChrome(x, y) {
|
|
15198
15798
|
return document.elementsFromPoint(x, y).some((el) => el instanceof HTMLElement && el.matches(EDITOR_CHROME_SELECTOR));
|
|
15199
15799
|
}
|
|
15200
|
-
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"])';
|
|
15800
|
+
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"])';
|
|
15201
15801
|
function getVideoEl2(el) {
|
|
15202
15802
|
return el instanceof HTMLVideoElement ? el : el.querySelector("video");
|
|
15203
15803
|
}
|
|
@@ -15253,6 +15853,12 @@ function applyVideoSettingNode(key, val) {
|
|
|
15253
15853
|
});
|
|
15254
15854
|
return true;
|
|
15255
15855
|
}
|
|
15856
|
+
function applyMapQuery(el, val) {
|
|
15857
|
+
if (!(el instanceof HTMLIFrameElement)) return;
|
|
15858
|
+
const nextSrc = `https://www.google.com/maps?q=${encodeURIComponent(val)}&output=embed`;
|
|
15859
|
+
if (el.src !== nextSrc) el.src = nextSrc;
|
|
15860
|
+
el.setAttribute("data-ohw-map-query", val);
|
|
15861
|
+
}
|
|
15256
15862
|
function applyLinkByKey(key, val) {
|
|
15257
15863
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
15258
15864
|
if (el.dataset.ohwEditable === "link") applyLinkHref(el, val);
|
|
@@ -15263,6 +15869,11 @@ function applyLinkByKey(key, val) {
|
|
|
15263
15869
|
hrefAnchors.forEach((el) => applyLinkHref(el, val));
|
|
15264
15870
|
}
|
|
15265
15871
|
}
|
|
15872
|
+
function isInsideLinkEditor(target) {
|
|
15873
|
+
return Boolean(
|
|
15874
|
+
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"]')
|
|
15875
|
+
);
|
|
15876
|
+
}
|
|
15266
15877
|
function isInsideFloatingPanel(target) {
|
|
15267
15878
|
return Boolean(target.closest("[data-ohw-floating-panel]"));
|
|
15268
15879
|
}
|
|
@@ -15270,11 +15881,6 @@ function isPointOverFloatingPanel(clientX, clientY) {
|
|
|
15270
15881
|
const el = document.elementFromPoint(clientX, clientY);
|
|
15271
15882
|
return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
|
|
15272
15883
|
}
|
|
15273
|
-
function isInsideLinkEditor(target) {
|
|
15274
|
-
return Boolean(
|
|
15275
|
-
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"]')
|
|
15276
|
-
);
|
|
15277
|
-
}
|
|
15278
15884
|
function getHrefKeyFromElement(el) {
|
|
15279
15885
|
if (!el) return null;
|
|
15280
15886
|
const anchor = el.closest("[data-ohw-href-key]");
|
|
@@ -15533,7 +16139,7 @@ function getNavigationSelectionParent(el) {
|
|
|
15533
16139
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
15534
16140
|
return getFooterLinksContainer();
|
|
15535
16141
|
}
|
|
15536
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
|
|
16142
|
+
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)) {
|
|
15537
16143
|
return getNavigationRoot(el);
|
|
15538
16144
|
}
|
|
15539
16145
|
return null;
|
|
@@ -15748,7 +16354,6 @@ var ICONS = {
|
|
|
15748
16354
|
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"/>',
|
|
15749
16355
|
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"/>'
|
|
15750
16356
|
};
|
|
15751
|
-
var HEIGHT_SETTLE_DELAYS = [150, 400, 800];
|
|
15752
16357
|
var SELECTION_CHROME_GAP2 = 4;
|
|
15753
16358
|
var TOOLBAR_STROKE_GAP2 = 4;
|
|
15754
16359
|
var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
|
|
@@ -16128,6 +16733,7 @@ function StateToggle({
|
|
|
16128
16733
|
);
|
|
16129
16734
|
}
|
|
16130
16735
|
var contentCache = /* @__PURE__ */ new Map();
|
|
16736
|
+
var fetchedContentPaths = /* @__PURE__ */ new Set();
|
|
16131
16737
|
var brandingCache = /* @__PURE__ */ new Map();
|
|
16132
16738
|
var OHW_LOADER_STYLE = {
|
|
16133
16739
|
position: "fixed",
|
|
@@ -16657,13 +17263,6 @@ function OhhwellsBridge() {
|
|
|
16657
17263
|
const [isItemDragging, setIsItemDragging] = (0, import_react17.useState)(false);
|
|
16658
17264
|
const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react17.useState)(false);
|
|
16659
17265
|
isFooterFrameSelectionRef.current = isFooterFrameSelection;
|
|
16660
|
-
const [floatingPanel, setFloatingPanel] = (0, import_react17.useState)(null);
|
|
16661
|
-
const floatingPanelOpenRef = (0, import_react17.useRef)(false);
|
|
16662
|
-
floatingPanelOpenRef.current = floatingPanel !== null;
|
|
16663
|
-
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react17.useState)(null);
|
|
16664
|
-
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react17.useState)(null);
|
|
16665
|
-
const [editorViewport, setEditorViewport] = (0, import_react17.useState)("desktop");
|
|
16666
|
-
const [parentScrollSnap, setParentScrollSnap] = (0, import_react17.useState)(null);
|
|
16667
17266
|
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react17.useState)(null);
|
|
16668
17267
|
const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react17.useState)(null);
|
|
16669
17268
|
const footerDragRef = (0, import_react17.useRef)(null);
|
|
@@ -16681,6 +17280,13 @@ function OhhwellsBridge() {
|
|
|
16681
17280
|
const brandKitRef = (0, import_react17.useRef)("");
|
|
16682
17281
|
const stylesRef = (0, import_react17.useRef)("");
|
|
16683
17282
|
const pendingDeleteUndoRef = (0, import_react17.useRef)(null);
|
|
17283
|
+
const [floatingPanel, setFloatingPanel] = (0, import_react17.useState)(null);
|
|
17284
|
+
const floatingPanelOpenRef = (0, import_react17.useRef)(false);
|
|
17285
|
+
const setFloatingPanelRef = (0, import_react17.useRef)(setFloatingPanel);
|
|
17286
|
+
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react17.useState)(null);
|
|
17287
|
+
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react17.useState)(null);
|
|
17288
|
+
const [editorViewport, setEditorViewport] = (0, import_react17.useState)("desktop");
|
|
17289
|
+
const [parentScrollSnap, setParentScrollSnap] = (0, import_react17.useState)(null);
|
|
16684
17290
|
const [sitePages, setSitePages] = (0, import_react17.useState)([]);
|
|
16685
17291
|
const [sectionsByPath, setSectionsByPath] = (0, import_react17.useState)({});
|
|
16686
17292
|
const sectionsPrefetchGenRef = (0, import_react17.useRef)(0);
|
|
@@ -16689,7 +17295,18 @@ function OhhwellsBridge() {
|
|
|
16689
17295
|
const linkPopoverOpenRef = (0, import_react17.useRef)(false);
|
|
16690
17296
|
const linkPopoverGraceUntilRef = (0, import_react17.useRef)(0);
|
|
16691
17297
|
setLinkPopoverRef.current = setLinkPopover;
|
|
17298
|
+
setFloatingPanelRef.current = setFloatingPanel;
|
|
16692
17299
|
linkPopoverSessionRef.current = linkPopover;
|
|
17300
|
+
floatingPanelOpenRef.current = Boolean(floatingPanel);
|
|
17301
|
+
(0, import_react17.useEffect)(() => {
|
|
17302
|
+
const syncViewport = () => {
|
|
17303
|
+
const next = window.innerWidth <= 480 ? "mobile" : "desktop";
|
|
17304
|
+
setEditorViewport((prev) => prev === next ? prev : next);
|
|
17305
|
+
};
|
|
17306
|
+
syncViewport();
|
|
17307
|
+
window.addEventListener("resize", syncViewport);
|
|
17308
|
+
return () => window.removeEventListener("resize", syncViewport);
|
|
17309
|
+
}, []);
|
|
16693
17310
|
const {
|
|
16694
17311
|
navDragRef,
|
|
16695
17312
|
navDropSlots,
|
|
@@ -18014,6 +18631,7 @@ function OhhwellsBridge() {
|
|
|
18014
18631
|
}
|
|
18015
18632
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
18016
18633
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
18634
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
18017
18635
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
18018
18636
|
}
|
|
18019
18637
|
applyBrandChrome(content);
|
|
@@ -18021,11 +18639,11 @@ function OhhwellsBridge() {
|
|
|
18021
18639
|
for (const [key, val] of Object.entries(content)) {
|
|
18022
18640
|
if (key === "__ohw_sections") continue;
|
|
18023
18641
|
if (key === AI_SECTIONS_KEY) continue;
|
|
18642
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
18643
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
18024
18644
|
if (key === BRAND_KIT_KEY) continue;
|
|
18025
18645
|
if (key === STYLE_STORE_KEY) continue;
|
|
18026
18646
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
18027
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
18028
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
18029
18647
|
if (applyVideoSettingNode(key, val)) continue;
|
|
18030
18648
|
if (applyCarouselNode(key, val)) continue;
|
|
18031
18649
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -18053,6 +18671,8 @@ function OhhwellsBridge() {
|
|
|
18053
18671
|
}
|
|
18054
18672
|
} else if (el.dataset.ohwEditable === "link") {
|
|
18055
18673
|
applyLinkHref(el, val);
|
|
18674
|
+
} else if (el.dataset.ohwEditable === "map") {
|
|
18675
|
+
applyMapQuery(el, val);
|
|
18056
18676
|
} else if (el.dataset.ohwEditable === "icon") {
|
|
18057
18677
|
applyIconMarkup(el, val);
|
|
18058
18678
|
} else if (el.dataset.ohwEditable === "form") {
|
|
@@ -18091,7 +18711,9 @@ function OhhwellsBridge() {
|
|
|
18091
18711
|
let cancelled = false;
|
|
18092
18712
|
setFetchState("loading");
|
|
18093
18713
|
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
18094
|
-
|
|
18714
|
+
const initialPath = pathname;
|
|
18715
|
+
fetchedContentPaths.add(`${subdomain}::${initialPath}`);
|
|
18716
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
18095
18717
|
if (cancelled) return;
|
|
18096
18718
|
const content = data?.content ?? {};
|
|
18097
18719
|
const branding = Boolean(data?.showBranding);
|
|
@@ -18210,10 +18832,10 @@ function OhhwellsBridge() {
|
|
|
18210
18832
|
const applyFromCache = () => {
|
|
18211
18833
|
const content = contentCache.get(subdomain);
|
|
18212
18834
|
if (!content) return;
|
|
18213
|
-
retryMissingSchedulingMounts(getPageSchedulingEntries(content["__ohw_sections"]), false);
|
|
18214
|
-
initSectionInstancesFromContent(content, window.location.pathname);
|
|
18215
18835
|
observer?.disconnect();
|
|
18216
18836
|
try {
|
|
18837
|
+
retryMissingSchedulingMounts(getPageSchedulingEntries(content["__ohw_sections"]), false);
|
|
18838
|
+
initSectionInstancesFromContent(content, window.location.pathname);
|
|
18217
18839
|
applyBrandChrome(content);
|
|
18218
18840
|
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
18219
18841
|
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
@@ -18225,16 +18847,17 @@ function OhhwellsBridge() {
|
|
|
18225
18847
|
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
18226
18848
|
}
|
|
18227
18849
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
18850
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
18228
18851
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
18229
18852
|
}
|
|
18230
18853
|
for (const [key, val] of Object.entries(content)) {
|
|
18231
18854
|
if (key === "__ohw_sections") continue;
|
|
18232
18855
|
if (key === AI_SECTIONS_KEY) continue;
|
|
18856
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
18857
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
18233
18858
|
if (key === BRAND_KIT_KEY) continue;
|
|
18234
18859
|
if (key === STYLE_STORE_KEY) continue;
|
|
18235
18860
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
18236
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
18237
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
18238
18861
|
if (applyVideoSettingNode(key, val)) continue;
|
|
18239
18862
|
if (applyCarouselNode(key, val)) continue;
|
|
18240
18863
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -18249,6 +18872,8 @@ function OhhwellsBridge() {
|
|
|
18249
18872
|
if (video && video.src !== val) applyVideoSrc(video, val);
|
|
18250
18873
|
} else if (el.dataset.ohwEditable === "link") {
|
|
18251
18874
|
applyLinkHref(el, val);
|
|
18875
|
+
} else if (el.dataset.ohwEditable === "map") {
|
|
18876
|
+
applyMapQuery(el, val);
|
|
18252
18877
|
} else if (el.dataset.ohwEditable === "form") {
|
|
18253
18878
|
} else if (isIconMarkupValue(val)) {
|
|
18254
18879
|
} else if (el.innerHTML !== val) {
|
|
@@ -18280,6 +18905,17 @@ function OhhwellsBridge() {
|
|
|
18280
18905
|
debounceTimer = setTimeout(applyFromCache, 150);
|
|
18281
18906
|
};
|
|
18282
18907
|
applyFromCache();
|
|
18908
|
+
const pathCacheKey = `${subdomain}::${pathname}`;
|
|
18909
|
+
if (!fetchedContentPaths.has(pathCacheKey)) {
|
|
18910
|
+
fetchedContentPaths.add(pathCacheKey);
|
|
18911
|
+
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
18912
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
18913
|
+
if (!data?.content) return;
|
|
18914
|
+
contentCache.set(subdomain, data.content);
|
|
18915
|
+
applyFromCache();
|
|
18916
|
+
}).catch(() => {
|
|
18917
|
+
});
|
|
18918
|
+
}
|
|
18283
18919
|
observer = new MutationObserver(scheduleApply);
|
|
18284
18920
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
18285
18921
|
return () => {
|
|
@@ -18304,6 +18940,10 @@ function OhhwellsBridge() {
|
|
|
18304
18940
|
deselectRef.current();
|
|
18305
18941
|
deactivateRef.current();
|
|
18306
18942
|
}, [pathname, isEditMode]);
|
|
18943
|
+
(0, import_react17.useEffect)(() => {
|
|
18944
|
+
if (!isEditMode) return;
|
|
18945
|
+
initSectionInstancesFromContent(editContentRef.current, pathname);
|
|
18946
|
+
}, [pathname, isEditMode]);
|
|
18307
18947
|
(0, import_react17.useEffect)(() => {
|
|
18308
18948
|
const contentForNav = () => {
|
|
18309
18949
|
if (isEditMode) return editContentRef.current;
|
|
@@ -18395,26 +19035,11 @@ function OhhwellsBridge() {
|
|
|
18395
19035
|
const t2 = setTimeout(measure, 500);
|
|
18396
19036
|
const ro = new ResizeObserver(schedule);
|
|
18397
19037
|
ro.observe(document.body);
|
|
18398
|
-
let lastWidth = window.innerWidth;
|
|
18399
|
-
let resizeTimers = [];
|
|
18400
|
-
const clearResizeTimers = () => {
|
|
18401
|
-
resizeTimers.forEach(clearTimeout);
|
|
18402
|
-
resizeTimers = [];
|
|
18403
|
-
};
|
|
18404
|
-
const handleResize = () => {
|
|
18405
|
-
if (window.innerWidth === lastWidth) return;
|
|
18406
|
-
lastWidth = window.innerWidth;
|
|
18407
|
-
clearResizeTimers();
|
|
18408
|
-
resizeTimers = HEIGHT_SETTLE_DELAYS.map((delay) => setTimeout(measure, delay));
|
|
18409
|
-
};
|
|
18410
|
-
window.addEventListener("resize", handleResize);
|
|
18411
19038
|
return () => {
|
|
18412
19039
|
clearTimeout(t1);
|
|
18413
19040
|
clearTimeout(t2);
|
|
18414
19041
|
if (raf != null) cancelAnimationFrame(raf);
|
|
18415
19042
|
ro.disconnect();
|
|
18416
|
-
clearResizeTimers();
|
|
18417
|
-
window.removeEventListener("resize", handleResize);
|
|
18418
19043
|
};
|
|
18419
19044
|
}, [pathname, isEditMode, postToParent2]);
|
|
18420
19045
|
(0, import_react17.useEffect)(() => {
|
|
@@ -18669,9 +19294,6 @@ function OhhwellsBridge() {
|
|
|
18669
19294
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
18670
19295
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
18671
19296
|
if (isInsideLinkEditor(target)) return;
|
|
18672
|
-
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
18673
|
-
clearMediaSelectionRef.current();
|
|
18674
|
-
}
|
|
18675
19297
|
if (isInsideFloatingPanel(target)) return;
|
|
18676
19298
|
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
18677
19299
|
if (target.closest(
|
|
@@ -18679,6 +19301,9 @@ function OhhwellsBridge() {
|
|
|
18679
19301
|
)) {
|
|
18680
19302
|
return;
|
|
18681
19303
|
}
|
|
19304
|
+
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
19305
|
+
clearMediaSelectionRef.current();
|
|
19306
|
+
}
|
|
18682
19307
|
{
|
|
18683
19308
|
const formEl = getFormElement(target);
|
|
18684
19309
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
@@ -18830,14 +19455,6 @@ function OhhwellsBridge() {
|
|
|
18830
19455
|
}
|
|
18831
19456
|
const clickedButton = findClosestButtonLike(target);
|
|
18832
19457
|
const buttonOnMedia = Boolean(clickedButton && isMediaEditable(editable) && editable.contains(clickedButton));
|
|
18833
|
-
console.log("[click-debug]", {
|
|
18834
|
-
editableType: editable.dataset.ohwEditable,
|
|
18835
|
-
editableTag: editable.tagName,
|
|
18836
|
-
targetTag: target.tagName,
|
|
18837
|
-
clickedButtonTag: clickedButton?.tagName ?? null,
|
|
18838
|
-
buttonOnMedia,
|
|
18839
|
-
isMediaEditableEditable: isMediaEditable(editable)
|
|
18840
|
-
});
|
|
18841
19458
|
if (isMediaEditable(editable) && !buttonOnMedia) {
|
|
18842
19459
|
e.preventDefault();
|
|
18843
19460
|
e.stopPropagation();
|
|
@@ -18864,11 +19481,6 @@ function OhhwellsBridge() {
|
|
|
18864
19481
|
const hrefLookupTarget = buttonOnMedia ? clickedButton : editable;
|
|
18865
19482
|
const hrefCtx = getHrefKeyFromElement(hrefLookupTarget);
|
|
18866
19483
|
const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
|
|
18867
|
-
console.log("[click-debug 2]", {
|
|
18868
|
-
hrefLookupTargetTag: hrefLookupTarget.tagName,
|
|
18869
|
-
hrefCtx: hrefCtx ? { key: hrefCtx.key } : null,
|
|
18870
|
-
navAnchorTag: navAnchor?.tagName ?? null
|
|
18871
|
-
});
|
|
18872
19484
|
if (navAnchor) {
|
|
18873
19485
|
e.preventDefault();
|
|
18874
19486
|
e.stopPropagation();
|
|
@@ -19038,6 +19650,9 @@ function OhhwellsBridge() {
|
|
|
19038
19650
|
setHoveredItemRect(null);
|
|
19039
19651
|
hoveredNavContainerRef.current = null;
|
|
19040
19652
|
setHoveredNavContainerRect(null);
|
|
19653
|
+
siblingHintElRef.current = null;
|
|
19654
|
+
setSiblingHintRect(null);
|
|
19655
|
+
setSiblingHintRects([]);
|
|
19041
19656
|
return;
|
|
19042
19657
|
}
|
|
19043
19658
|
{
|
|
@@ -19156,7 +19771,6 @@ function OhhwellsBridge() {
|
|
|
19156
19771
|
hoveredNavContainerRef.current = null;
|
|
19157
19772
|
setHoveredNavContainerRect(null);
|
|
19158
19773
|
hoveredItemElRef.current = editable;
|
|
19159
|
-
setHoveredItemRect(isSelectedForHoverRef.current(editable) ? null : editable.getBoundingClientRect());
|
|
19160
19774
|
}
|
|
19161
19775
|
}
|
|
19162
19776
|
}
|
|
@@ -19453,7 +20067,7 @@ function OhhwellsBridge() {
|
|
|
19453
20067
|
}
|
|
19454
20068
|
};
|
|
19455
20069
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
19456
|
-
if (linkPopoverOpenRef.current) {
|
|
20070
|
+
if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
19457
20071
|
if (hoveredImageRef.current) {
|
|
19458
20072
|
hoveredImageRef.current = null;
|
|
19459
20073
|
hoveredImageHasTextOverlapRef.current = false;
|
|
@@ -19818,8 +20432,7 @@ function OhhwellsBridge() {
|
|
|
19818
20432
|
};
|
|
19819
20433
|
const handleMouseMove = (e) => {
|
|
19820
20434
|
const { clientX, clientY } = e;
|
|
19821
|
-
if (
|
|
19822
|
-
if (isOverEditorChrome(clientX, clientY)) {
|
|
20435
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || isOverEditorChrome(clientX, clientY)) {
|
|
19823
20436
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
19824
20437
|
formHoverElRef.current = null;
|
|
19825
20438
|
setFormHoverRect(null);
|
|
@@ -19827,6 +20440,12 @@ function OhhwellsBridge() {
|
|
|
19827
20440
|
setHoveredItemRect(null);
|
|
19828
20441
|
hoveredNavContainerRef.current = null;
|
|
19829
20442
|
setHoveredNavContainerRect(null);
|
|
20443
|
+
siblingHintElRef.current = null;
|
|
20444
|
+
setSiblingHintRect(null);
|
|
20445
|
+
setSiblingHintRects([]);
|
|
20446
|
+
dismissImageHover();
|
|
20447
|
+
clearImageHover();
|
|
20448
|
+
setSectionGap(null);
|
|
19830
20449
|
return;
|
|
19831
20450
|
}
|
|
19832
20451
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
@@ -19838,7 +20457,11 @@ function OhhwellsBridge() {
|
|
|
19838
20457
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
19839
20458
|
const { clientX, clientY } = e.data;
|
|
19840
20459
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
19841
|
-
if (
|
|
20460
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
20461
|
+
dismissImageHover();
|
|
20462
|
+
clearImageHover();
|
|
20463
|
+
return;
|
|
20464
|
+
}
|
|
19842
20465
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
19843
20466
|
probeSectionGapAt(clientX, clientY);
|
|
19844
20467
|
probeImageAt(clientX, clientY);
|
|
@@ -20117,6 +20740,44 @@ function OhhwellsBridge() {
|
|
|
20117
20740
|
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
20118
20741
|
}, 400));
|
|
20119
20742
|
};
|
|
20743
|
+
const reapCommittedAiSections = (excludeIds) => {
|
|
20744
|
+
const aiState = parseAiSectionsState(aiSectionsRef.current);
|
|
20745
|
+
if (aiState.sections.length === 0) return [];
|
|
20746
|
+
let orderEntries = [];
|
|
20747
|
+
try {
|
|
20748
|
+
const parsed = JSON.parse(editContentRef.current[SECTION_ORDER_KEY] ?? "[]");
|
|
20749
|
+
if (Array.isArray(parsed)) orderEntries = parsed;
|
|
20750
|
+
} catch {
|
|
20751
|
+
return [];
|
|
20752
|
+
}
|
|
20753
|
+
const removedIds = orderEntries.filter((entry) => entry && typeof entry.instanceId === "string" && entry.removed).map((entry) => entry.instanceId);
|
|
20754
|
+
if (removedIds.length === 0) return [];
|
|
20755
|
+
const result = reapRemovedAiSections(aiState, parseStyleStore(stylesRef.current), removedIds, excludeIds);
|
|
20756
|
+
if (!result.changed) return [];
|
|
20757
|
+
const nodes = [];
|
|
20758
|
+
aiSectionsRef.current = serializeAiSectionsState(result.state);
|
|
20759
|
+
nodes.push({ key: AI_SECTIONS_KEY, text: aiSectionsRef.current });
|
|
20760
|
+
const reaped = new Set(result.reapedIds);
|
|
20761
|
+
const nextOrderJson = JSON.stringify(orderEntries.filter((entry) => !reaped.has(entry.instanceId)));
|
|
20762
|
+
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: nextOrderJson };
|
|
20763
|
+
setAiSectionOrder(nextOrderJson, window.location.pathname);
|
|
20764
|
+
nodes.push({ key: SECTION_ORDER_KEY, text: nextOrderJson });
|
|
20765
|
+
if (result.store) {
|
|
20766
|
+
stylesRef.current = JSON.stringify(result.store);
|
|
20767
|
+
nodes.push({ key: STYLE_STORE_KEY, text: stylesRef.current });
|
|
20768
|
+
}
|
|
20769
|
+
const nextContent = { ...editContentRef.current };
|
|
20770
|
+
for (const key of Object.keys(nextContent)) {
|
|
20771
|
+
if (key.startsWith(AI_SLOT_KEY_PREFIX) && result.slotPrefixes.some((prefix) => key.startsWith(prefix)) && nextContent[key] !== "") {
|
|
20772
|
+
nextContent[key] = "";
|
|
20773
|
+
nodes.push({ key, text: "" });
|
|
20774
|
+
}
|
|
20775
|
+
}
|
|
20776
|
+
editContentRef.current = nextContent;
|
|
20777
|
+
applyAiSectionsToDom(result.state);
|
|
20778
|
+
applyStylesToDom(parseStyleStore(stylesRef.current));
|
|
20779
|
+
return nodes;
|
|
20780
|
+
};
|
|
20120
20781
|
const handleHydrate = (e) => {
|
|
20121
20782
|
if (e.data?.type !== "ow:hydrate") return;
|
|
20122
20783
|
const content = e.data.content;
|
|
@@ -20135,6 +20796,7 @@ function OhhwellsBridge() {
|
|
|
20135
20796
|
}
|
|
20136
20797
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
20137
20798
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
20799
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
20138
20800
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
20139
20801
|
}
|
|
20140
20802
|
applyBrandChrome(content);
|
|
@@ -20146,11 +20808,11 @@ function OhhwellsBridge() {
|
|
|
20146
20808
|
continue;
|
|
20147
20809
|
}
|
|
20148
20810
|
if (key === AI_SECTIONS_KEY) continue;
|
|
20811
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
20812
|
+
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
20149
20813
|
if (key === BRAND_KIT_KEY) continue;
|
|
20150
20814
|
if (key === STYLE_STORE_KEY) continue;
|
|
20151
20815
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
20152
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
20153
|
-
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
20154
20816
|
if (applyVideoSettingNode(key, val)) continue;
|
|
20155
20817
|
if (applyCarouselNode(key, val)) continue;
|
|
20156
20818
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -20164,6 +20826,8 @@ function OhhwellsBridge() {
|
|
|
20164
20826
|
if (video && video.src !== val) applyVideoSrc(video, val);
|
|
20165
20827
|
} else if (el.dataset.ohwEditable === "link") {
|
|
20166
20828
|
applyLinkHref(el, val);
|
|
20829
|
+
} else if (el.dataset.ohwEditable === "map") {
|
|
20830
|
+
applyMapQuery(el, val);
|
|
20167
20831
|
} else if (el.dataset.ohwEditable === "icon") {
|
|
20168
20832
|
applyIconMarkup(el, val);
|
|
20169
20833
|
} else if (isIconMarkupValue(val)) {
|
|
@@ -20185,8 +20849,16 @@ function OhhwellsBridge() {
|
|
|
20185
20849
|
reconcileFooterOrderFromContent(editContentRef.current);
|
|
20186
20850
|
syncNavigationDragCursorAttrs();
|
|
20187
20851
|
enforceLinkHrefs();
|
|
20852
|
+
const hydrateReapExclude = /* @__PURE__ */ new Set();
|
|
20853
|
+
const hydratePendingUndo = pendingDeleteUndoRef.current;
|
|
20854
|
+
if (hydratePendingUndo?.sectionInstanceId) hydrateReapExclude.add(hydratePendingUndo.sectionInstanceId);
|
|
20855
|
+
const reapNodes = reapCommittedAiSections(hydrateReapExclude);
|
|
20856
|
+
if (reapNodes.length > 0) postToParentRef.current({ type: "ow:change", nodes: reapNodes });
|
|
20188
20857
|
const hydratedHeight = document.body.scrollHeight;
|
|
20189
20858
|
if (hydratedHeight > 50) postToParentRef.current({ type: "ow:height", height: hydratedHeight });
|
|
20859
|
+
if (parseAiSectionsState(aiSectionsRef.current).sections.length > 0) {
|
|
20860
|
+
postAiSectionsChanged();
|
|
20861
|
+
}
|
|
20190
20862
|
postToParentRef.current({ type: "ow:hydrate-done" });
|
|
20191
20863
|
};
|
|
20192
20864
|
const handleUpdateLogoIdentity = (e) => {
|
|
@@ -20324,12 +20996,35 @@ function OhhwellsBridge() {
|
|
|
20324
20996
|
window.addEventListener("message", handleAiSetBrand);
|
|
20325
20997
|
const handleAiSetStyles = (e) => {
|
|
20326
20998
|
if (e.data?.type !== "ow:ai-set-styles") return;
|
|
20327
|
-
|
|
20999
|
+
let value = typeof e.data.value === "string" ? e.data.value : "";
|
|
20328
21000
|
const previous = stylesRef.current;
|
|
21001
|
+
let previousSections;
|
|
21002
|
+
const store = parseStyleStore(value);
|
|
21003
|
+
if (store) {
|
|
21004
|
+
const folded = foldAlignIntoTrees(parseAiSectionsState(aiSectionsRef.current), store);
|
|
21005
|
+
if (folded.changed) {
|
|
21006
|
+
const nextSections = serializeAiSectionsState(folded.state);
|
|
21007
|
+
if (nextSections !== aiSectionsRef.current) {
|
|
21008
|
+
previousSections = aiSectionsRef.current;
|
|
21009
|
+
aiSectionsRef.current = nextSections;
|
|
21010
|
+
applyAiSectionsToDom(folded.state);
|
|
21011
|
+
postToParentRef.current({
|
|
21012
|
+
type: "ow:change",
|
|
21013
|
+
nodes: [{ key: AI_SECTIONS_KEY, text: nextSections }]
|
|
21014
|
+
});
|
|
21015
|
+
}
|
|
21016
|
+
value = JSON.stringify(folded.store);
|
|
21017
|
+
}
|
|
21018
|
+
}
|
|
20329
21019
|
stylesRef.current = value;
|
|
20330
21020
|
applyStylesToDom(parseStyleStore(value));
|
|
20331
21021
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: STYLE_STORE_KEY, text: value }] });
|
|
20332
|
-
postToParentRef.current({
|
|
21022
|
+
postToParentRef.current({
|
|
21023
|
+
type: "ow:ai-styles-applied",
|
|
21024
|
+
previous,
|
|
21025
|
+
value,
|
|
21026
|
+
...previousSections !== void 0 ? { previousSections } : {}
|
|
21027
|
+
});
|
|
20333
21028
|
};
|
|
20334
21029
|
window.addEventListener("message", handleAiSetStyles);
|
|
20335
21030
|
const handleGetBrand = (e) => {
|
|
@@ -20346,8 +21041,11 @@ function OhhwellsBridge() {
|
|
|
20346
21041
|
if (!instanceId || !direction) return;
|
|
20347
21042
|
const entries = moveSectionInstance(instanceId, direction, window.location.pathname);
|
|
20348
21043
|
if (!entries) return;
|
|
20349
|
-
const orderJson = JSON.stringify(
|
|
21044
|
+
const orderJson = JSON.stringify(
|
|
21045
|
+
mergePageSectionOrder(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname, entries)
|
|
21046
|
+
);
|
|
20350
21047
|
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
21048
|
+
applyPersistedOrder(getPageSectionOrderEntries(orderJson, window.location.pathname));
|
|
20351
21049
|
setAiSectionOrder(orderJson, window.location.pathname);
|
|
20352
21050
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
20353
21051
|
window.dispatchEvent(new Event("resize"));
|
|
@@ -20393,8 +21091,11 @@ function OhhwellsBridge() {
|
|
|
20393
21091
|
const currentEntries = getPageSectionOrderEntries(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname);
|
|
20394
21092
|
const entries = deleteSectionInstance(instanceId, window.location.pathname, currentEntries);
|
|
20395
21093
|
if (!entries) return;
|
|
20396
|
-
const orderJson = JSON.stringify(
|
|
21094
|
+
const orderJson = JSON.stringify(
|
|
21095
|
+
mergePageSectionOrder(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname, entries)
|
|
21096
|
+
);
|
|
20397
21097
|
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
21098
|
+
setAiSectionOrder(orderJson, window.location.pathname);
|
|
20398
21099
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
20399
21100
|
aiSectionApiRef.current?.clear();
|
|
20400
21101
|
window.dispatchEvent(new Event("resize"));
|
|
@@ -20403,6 +21104,7 @@ function OhhwellsBridge() {
|
|
|
20403
21104
|
const actionId = newInstanceId();
|
|
20404
21105
|
pendingDeleteUndoRef.current = {
|
|
20405
21106
|
actionId,
|
|
21107
|
+
sectionInstanceId: instanceId,
|
|
20406
21108
|
restore: () => {
|
|
20407
21109
|
const restoredEntries = getPageSectionOrderEntries(
|
|
20408
21110
|
editContentRef.current[SECTION_ORDER_KEY],
|
|
@@ -20410,8 +21112,11 @@ function OhhwellsBridge() {
|
|
|
20410
21112
|
);
|
|
20411
21113
|
const restored = restoreSectionInstance(instanceId, window.location.pathname, restoredEntries);
|
|
20412
21114
|
if (!restored) return;
|
|
20413
|
-
const restoredJson = JSON.stringify(
|
|
21115
|
+
const restoredJson = JSON.stringify(
|
|
21116
|
+
mergePageSectionOrder(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname, restored)
|
|
21117
|
+
);
|
|
20414
21118
|
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: restoredJson };
|
|
21119
|
+
setAiSectionOrder(restoredJson, window.location.pathname);
|
|
20415
21120
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: restoredJson }] });
|
|
20416
21121
|
window.dispatchEvent(new Event("resize"));
|
|
20417
21122
|
const restoreHeight = document.body.scrollHeight;
|
|
@@ -20437,7 +21142,9 @@ function OhhwellsBridge() {
|
|
|
20437
21142
|
const result = duplicateSectionInstance(instanceId, newId, window.location.pathname, currentEntries);
|
|
20438
21143
|
if (!result) return;
|
|
20439
21144
|
const { entries, keyRekeys } = result;
|
|
20440
|
-
const orderJson = JSON.stringify(
|
|
21145
|
+
const orderJson = JSON.stringify(
|
|
21146
|
+
mergePageSectionOrder(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname, entries)
|
|
21147
|
+
);
|
|
20441
21148
|
const nodes = [{ key: SECTION_ORDER_KEY, text: orderJson }];
|
|
20442
21149
|
for (const { from, to } of keyRekeys) {
|
|
20443
21150
|
const inherited = editContentRef.current[from];
|
|
@@ -20447,6 +21154,7 @@ function OhhwellsBridge() {
|
|
|
20447
21154
|
...editContentRef.current,
|
|
20448
21155
|
...Object.fromEntries(nodes.map(({ key, text }) => [key, text]))
|
|
20449
21156
|
};
|
|
21157
|
+
applyPersistedOrder(getPageSectionOrderEntries(orderJson, window.location.pathname));
|
|
20450
21158
|
setAiSectionOrder(orderJson, window.location.pathname);
|
|
20451
21159
|
postToParentRef.current({ type: "ow:change", nodes });
|
|
20452
21160
|
window.dispatchEvent(new Event("resize"));
|
|
@@ -20465,6 +21173,12 @@ function OhhwellsBridge() {
|
|
|
20465
21173
|
closeLinkPopoverRef.current();
|
|
20466
21174
|
return;
|
|
20467
21175
|
}
|
|
21176
|
+
if (floatingPanelOpenRef.current) {
|
|
21177
|
+
setFloatingPanelRef.current(null);
|
|
21178
|
+
deselectRef.current();
|
|
21179
|
+
deactivateRef.current();
|
|
21180
|
+
return;
|
|
21181
|
+
}
|
|
20468
21182
|
deselectRef.current();
|
|
20469
21183
|
deactivateRef.current();
|
|
20470
21184
|
clearMediaSelectionRef.current();
|
|
@@ -20710,6 +21424,10 @@ function OhhwellsBridge() {
|
|
|
20710
21424
|
};
|
|
20711
21425
|
const handleSave = (e) => {
|
|
20712
21426
|
if (e.data?.type !== "ow:save") return;
|
|
21427
|
+
const pendingUndo = pendingDeleteUndoRef.current;
|
|
21428
|
+
const reapExclude = /* @__PURE__ */ new Set();
|
|
21429
|
+
if (pendingUndo?.sectionInstanceId) reapExclude.add(pendingUndo.sectionInstanceId);
|
|
21430
|
+
const reapNodes = reapCommittedAiSections(reapExclude);
|
|
20713
21431
|
const nodes = collectEditableNodes(editContentRef.current);
|
|
20714
21432
|
const tracker = document.querySelector("[data-ohw-sections-tracker]");
|
|
20715
21433
|
if (tracker?.textContent) nodes.push({ key: "__ohw_sections", type: "sections", text: tracker.textContent });
|
|
@@ -20729,6 +21447,11 @@ function OhhwellsBridge() {
|
|
|
20729
21447
|
const text = specs.length ? JSON.stringify(specs) : editContentRef.current[fieldsKey(formKey)];
|
|
20730
21448
|
if (text) nodes.push({ key: fieldsKey(formKey), type: "text", text });
|
|
20731
21449
|
});
|
|
21450
|
+
for (const reapNode of reapNodes) {
|
|
21451
|
+
if (reapNode.key.startsWith(AI_SLOT_KEY_PREFIX) && !nodes.some((n) => n.key === reapNode.key)) {
|
|
21452
|
+
nodes.push({ key: reapNode.key, type: "text", text: reapNode.text });
|
|
21453
|
+
}
|
|
21454
|
+
}
|
|
20732
21455
|
postToParentRef.current({ type: "ow:save-result", nodes });
|
|
20733
21456
|
};
|
|
20734
21457
|
const handleInsertSection = (e) => {
|
|
@@ -20739,8 +21462,12 @@ function OhhwellsBridge() {
|
|
|
20739
21462
|
if (inserted) {
|
|
20740
21463
|
const tracker = getSectionsTracker();
|
|
20741
21464
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
|
|
20742
|
-
const
|
|
20743
|
-
|
|
21465
|
+
const reportHeight = () => {
|
|
21466
|
+
const h = document.body.scrollHeight;
|
|
21467
|
+
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
21468
|
+
};
|
|
21469
|
+
reportHeight();
|
|
21470
|
+
setTimeout(reportHeight, 500);
|
|
20744
21471
|
}
|
|
20745
21472
|
};
|
|
20746
21473
|
const handleSwitchSchedule = (e) => {
|
|
@@ -21144,10 +21871,10 @@ function OhhwellsBridge() {
|
|
|
21144
21871
|
window.removeEventListener("message", handleDeleteSection);
|
|
21145
21872
|
window.removeEventListener("message", handleDuplicateSection);
|
|
21146
21873
|
window.removeEventListener("message", handleDeactivate);
|
|
21147
|
-
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
21148
21874
|
window.removeEventListener("message", handleToastAction);
|
|
21149
21875
|
window.removeEventListener("message", handleFormCount);
|
|
21150
21876
|
window.removeEventListener("message", handleUiEscape);
|
|
21877
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
21151
21878
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
21152
21879
|
autoSaveTimers.current.clear();
|
|
21153
21880
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
@@ -21350,7 +22077,7 @@ function OhhwellsBridge() {
|
|
|
21350
22077
|
postToParent2({
|
|
21351
22078
|
type: "ow:ready",
|
|
21352
22079
|
version: "1",
|
|
21353
|
-
bridgeVersion: "0.1.
|
|
22080
|
+
bridgeVersion: "0.1.92",
|
|
21354
22081
|
path: pathname,
|
|
21355
22082
|
nodes: collectEditableNodes(editContentRef.current),
|
|
21356
22083
|
sections
|
|
@@ -22269,6 +22996,59 @@ function OhhwellsBridge() {
|
|
|
22269
22996
|
) : null
|
|
22270
22997
|
] });
|
|
22271
22998
|
}
|
|
22999
|
+
|
|
23000
|
+
// src/ui/EmptySection.tsx
|
|
23001
|
+
var import_link = __toESM(require("next/link"), 1);
|
|
23002
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
23003
|
+
function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
|
|
23004
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
|
|
23005
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
23006
|
+
"p",
|
|
23007
|
+
{
|
|
23008
|
+
style: {
|
|
23009
|
+
fontFamily: "var(--brand-font-body)",
|
|
23010
|
+
fontSize: "0.75rem",
|
|
23011
|
+
fontWeight: 500,
|
|
23012
|
+
letterSpacing: "0.15em",
|
|
23013
|
+
textTransform: "uppercase",
|
|
23014
|
+
color: "var(--brand-accent)",
|
|
23015
|
+
marginBottom: "1.5rem"
|
|
23016
|
+
},
|
|
23017
|
+
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" }) })
|
|
23018
|
+
}
|
|
23019
|
+
),
|
|
23020
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
23021
|
+
"h1",
|
|
23022
|
+
{
|
|
23023
|
+
style: {
|
|
23024
|
+
fontFamily: "var(--brand-font-heading)",
|
|
23025
|
+
fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
|
|
23026
|
+
lineHeight: 1.1,
|
|
23027
|
+
letterSpacing: "-0.025em",
|
|
23028
|
+
color: "var(--brand-text)",
|
|
23029
|
+
marginBottom: "1rem"
|
|
23030
|
+
},
|
|
23031
|
+
...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
|
|
23032
|
+
children: title
|
|
23033
|
+
}
|
|
23034
|
+
),
|
|
23035
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
23036
|
+
"p",
|
|
23037
|
+
{
|
|
23038
|
+
style: {
|
|
23039
|
+
fontFamily: "var(--brand-font-body)",
|
|
23040
|
+
fontSize: "1rem",
|
|
23041
|
+
lineHeight: 1.7,
|
|
23042
|
+
fontWeight: 300,
|
|
23043
|
+
color: "var(--brand-text-muted)",
|
|
23044
|
+
maxWidth: "340px"
|
|
23045
|
+
},
|
|
23046
|
+
...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
|
|
23047
|
+
children: "This page doesn't have any content yet."
|
|
23048
|
+
}
|
|
23049
|
+
)
|
|
23050
|
+
] });
|
|
23051
|
+
}
|
|
22272
23052
|
// Annotate the CommonJS export names for ESM import in node:
|
|
22273
23053
|
0 && (module.exports = {
|
|
22274
23054
|
AI_DEFAULT_BRAND,
|
|
@@ -22286,6 +23066,7 @@ function OhhwellsBridge() {
|
|
|
22286
23066
|
DropdownMenuItem,
|
|
22287
23067
|
DropdownMenuSeparator,
|
|
22288
23068
|
DropdownMenuTrigger,
|
|
23069
|
+
EmptySection,
|
|
22289
23070
|
ItemActionToolbar,
|
|
22290
23071
|
ItemInteractionLayer,
|
|
22291
23072
|
LinkEditorPanel,
|