@ohhwells/bridge 0.1.91 → 0.1.92-next.267
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 +1155 -397
- 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 +1154 -397
- 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,7 +2639,7 @@ 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"]);
|
|
1899
2645
|
function readRootVar(name) {
|
|
@@ -1917,13 +2663,13 @@ function deriveBrandOverride() {
|
|
|
1917
2663
|
};
|
|
1918
2664
|
}
|
|
1919
2665
|
function deriveTemplateBrand() {
|
|
1920
|
-
const
|
|
1921
|
-
const
|
|
1922
|
-
const light = readRootVar("--color-light");
|
|
2666
|
+
const primary = readRootVar("--brand-primary") || readRootVar("--color-primary");
|
|
2667
|
+
const dark = readRootVar("--brand-text") || readRootVar("--color-dark");
|
|
2668
|
+
const light = readRootVar("--brand-background") || readRootVar("--color-light");
|
|
1923
2669
|
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");
|
|
2670
|
+
const accent = readRootVar("--brand-accent") || readRootVar("--color-accent");
|
|
2671
|
+
const heading = readRootVar("--brand-font-heading") || readRootVar("--font-heading") || readRootVar("--font-display");
|
|
2672
|
+
const body = readRootVar("--brand-font-body") || readRootVar("--font-body");
|
|
1927
2673
|
return {
|
|
1928
2674
|
palette: { dark, primary, accent: accent || dark, light },
|
|
1929
2675
|
fonts: {
|
|
@@ -1932,12 +2678,32 @@ function deriveTemplateBrand() {
|
|
|
1932
2678
|
}
|
|
1933
2679
|
};
|
|
1934
2680
|
}
|
|
1935
|
-
function
|
|
2681
|
+
function deriveTemplateButtonStyle() {
|
|
1936
2682
|
if (typeof document === "undefined") return null;
|
|
1937
|
-
const btn = document.
|
|
2683
|
+
const btn = Array.from(document.querySelectorAll('[data-ohw-role="button"]')).find(
|
|
2684
|
+
(el) => !el.closest(`[${CONTAINER_ATTR}]`)
|
|
2685
|
+
);
|
|
1938
2686
|
if (!btn) return null;
|
|
1939
|
-
const
|
|
1940
|
-
|
|
2687
|
+
const cs = getComputedStyle(btn);
|
|
2688
|
+
const corners = [
|
|
2689
|
+
cs.borderTopLeftRadius,
|
|
2690
|
+
cs.borderTopRightRadius,
|
|
2691
|
+
cs.borderBottomRightRadius,
|
|
2692
|
+
cs.borderBottomLeftRadius
|
|
2693
|
+
].map((v) => v || "0px");
|
|
2694
|
+
const radius = corners.every((v) => v === corners[0]) ? corners[0] : corners.join(" ");
|
|
2695
|
+
const px = (v) => parseFloat(v) || 0;
|
|
2696
|
+
const padY = Math.max(px(cs.paddingTop), px(cs.paddingBottom));
|
|
2697
|
+
const padX = Math.max(px(cs.paddingLeft), px(cs.paddingRight));
|
|
2698
|
+
return {
|
|
2699
|
+
radius: radius || "10px",
|
|
2700
|
+
padding: `${padY}px ${padX}px`,
|
|
2701
|
+
fontFamily: cs.fontFamily || "",
|
|
2702
|
+
fontSize: cs.fontSize || "",
|
|
2703
|
+
fontWeight: cs.fontWeight || "",
|
|
2704
|
+
letterSpacing: cs.letterSpacing || "",
|
|
2705
|
+
textTransform: cs.textTransform || ""
|
|
2706
|
+
};
|
|
1941
2707
|
}
|
|
1942
2708
|
var mounted = /* @__PURE__ */ new Map();
|
|
1943
2709
|
function findTemplateSection(id) {
|
|
@@ -1988,18 +2754,18 @@ function placeContainer(container, entry) {
|
|
|
1988
2754
|
}
|
|
1989
2755
|
function syncRemovedSections(state) {
|
|
1990
2756
|
const removed = new Set(state.removed ?? []);
|
|
1991
|
-
for (const el of document.querySelectorAll(`[${
|
|
2757
|
+
for (const el of document.querySelectorAll(`[${REMOVED_ATTR2}]`)) {
|
|
1992
2758
|
const id = el.getAttribute("data-ohw-section") ?? "";
|
|
1993
2759
|
if (!removed.has(id)) {
|
|
1994
2760
|
el.style.removeProperty("display");
|
|
1995
|
-
el.removeAttribute(
|
|
2761
|
+
el.removeAttribute(REMOVED_ATTR2);
|
|
1996
2762
|
}
|
|
1997
2763
|
}
|
|
1998
2764
|
for (const id of removed) {
|
|
1999
2765
|
const section = findTemplateSection(id);
|
|
2000
2766
|
if (section && !section.hasAttribute(REPLACED_ATTR)) {
|
|
2001
2767
|
section.style.display = "none";
|
|
2002
|
-
section.setAttribute(
|
|
2768
|
+
section.setAttribute(REMOVED_ATTR2, "");
|
|
2003
2769
|
}
|
|
2004
2770
|
}
|
|
2005
2771
|
}
|
|
@@ -2016,7 +2782,7 @@ function syncTemplateHidden(state, pageHasSections) {
|
|
|
2016
2782
|
if (el.hasAttribute(CONTAINER_ATTR)) continue;
|
|
2017
2783
|
if (CHROME_SECTION_IDS.has(el.getAttribute("data-ohw-section") ?? "")) continue;
|
|
2018
2784
|
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
2019
|
-
if (el.hasAttribute(REPLACED_ATTR) || el.hasAttribute(
|
|
2785
|
+
if (el.hasAttribute(REPLACED_ATTR) || el.hasAttribute(REMOVED_ATTR2)) continue;
|
|
2020
2786
|
el.style.display = "none";
|
|
2021
2787
|
el.setAttribute(TEMPLATE_HIDDEN_ATTR, "");
|
|
2022
2788
|
}
|
|
@@ -2040,18 +2806,23 @@ function syncReplacedOriginals(state) {
|
|
|
2040
2806
|
}
|
|
2041
2807
|
}
|
|
2042
2808
|
var sectionOrderIndex = /* @__PURE__ */ new Map();
|
|
2809
|
+
var removedSectionIds = /* @__PURE__ */ new Set();
|
|
2043
2810
|
function setAiSectionOrder(raw, currentPath) {
|
|
2044
2811
|
const next = /* @__PURE__ */ new Map();
|
|
2812
|
+
const removed = /* @__PURE__ */ new Set();
|
|
2045
2813
|
if (raw) {
|
|
2046
2814
|
try {
|
|
2047
2815
|
const entries = JSON.parse(raw);
|
|
2048
2816
|
for (const entry of entries) {
|
|
2049
|
-
if (
|
|
2817
|
+
if (entry.pagePath && entry.pagePath !== currentPath) continue;
|
|
2818
|
+
next.set(entry.instanceId, entry.order);
|
|
2819
|
+
if (entry.removed) removed.add(entry.instanceId);
|
|
2050
2820
|
}
|
|
2051
2821
|
} catch {
|
|
2052
2822
|
}
|
|
2053
2823
|
}
|
|
2054
2824
|
sectionOrderIndex = next;
|
|
2825
|
+
removedSectionIds = removed;
|
|
2055
2826
|
}
|
|
2056
2827
|
function applyExplicitOrder(entries) {
|
|
2057
2828
|
if (sectionOrderIndex.size === 0) return entries;
|
|
@@ -2087,11 +2858,23 @@ function orderByChain(sections) {
|
|
|
2087
2858
|
for (const root of roots) visit(root);
|
|
2088
2859
|
return out.length === sections.length ? out : sections;
|
|
2089
2860
|
}
|
|
2861
|
+
function syncSoftRemovedGenerated() {
|
|
2862
|
+
for (const [id, section] of mounted) {
|
|
2863
|
+
const el = section.container;
|
|
2864
|
+
if (removedSectionIds.has(id)) {
|
|
2865
|
+
el.style.display = "none";
|
|
2866
|
+
el.setAttribute(REMOVED_ATTR, "");
|
|
2867
|
+
} else if (el.hasAttribute(REMOVED_ATTR)) {
|
|
2868
|
+
el.style.removeProperty("display");
|
|
2869
|
+
el.removeAttribute(REMOVED_ATTR);
|
|
2870
|
+
}
|
|
2871
|
+
}
|
|
2872
|
+
}
|
|
2090
2873
|
function applyAiSectionsToDom(state, options) {
|
|
2091
2874
|
if (typeof document === "undefined") return;
|
|
2092
2875
|
const brandOverride = deriveBrandOverride();
|
|
2093
2876
|
const templateBrand = deriveTemplateBrand();
|
|
2094
|
-
const
|
|
2877
|
+
const templateButtonStyle = deriveTemplateButtonStyle();
|
|
2095
2878
|
const brandKey = brandOverride ? JSON.stringify(brandOverride) : "";
|
|
2096
2879
|
const pagePath = window.location.pathname;
|
|
2097
2880
|
const pageSections = state.sections.filter((entry) => (entry.path ?? "/") === pagePath);
|
|
@@ -2131,7 +2914,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
2131
2914
|
{
|
|
2132
2915
|
tree: entry.tree,
|
|
2133
2916
|
brand: brandOverride ?? entry.brand ?? options?.brand ?? templateBrand ?? void 0,
|
|
2134
|
-
|
|
2917
|
+
buttonStyle: templateButtonStyle,
|
|
2135
2918
|
resolveMedia,
|
|
2136
2919
|
editKeyPrefix: `ai.${entry.id}`
|
|
2137
2920
|
}
|
|
@@ -2154,6 +2937,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
2154
2937
|
syncReplacedOriginals(state);
|
|
2155
2938
|
syncRemovedSections(state);
|
|
2156
2939
|
syncTemplateHidden(state, pageSections.length > 0);
|
|
2940
|
+
syncSoftRemovedGenerated();
|
|
2157
2941
|
}
|
|
2158
2942
|
|
|
2159
2943
|
// src/useLinkHrefGuardian.ts
|
|
@@ -7883,6 +8667,7 @@ function MediaOverlay({
|
|
|
7883
8667
|
(prev) => prev && prev.fullWidth === width && prev.height === height ? prev : { fullWidth: width, height }
|
|
7884
8668
|
);
|
|
7885
8669
|
}, [isVideo]);
|
|
8670
|
+
const replaceLabel = isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image";
|
|
7886
8671
|
const replaceMode = buttonSize ? replaceButtonMode({ width: rect.width, height: rect.height }, buttonSize) : "none";
|
|
7887
8672
|
const box = {
|
|
7888
8673
|
position: "fixed",
|
|
@@ -8012,17 +8797,17 @@ function MediaOverlay({
|
|
|
8012
8797
|
},
|
|
8013
8798
|
children: [
|
|
8014
8799
|
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
|
-
|
|
8800
|
+
replaceLabel
|
|
8016
8801
|
]
|
|
8017
8802
|
}
|
|
8018
8803
|
),
|
|
8019
|
-
replaceMode
|
|
8804
|
+
showChrome && replaceMode !== "none" && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
8020
8805
|
Button,
|
|
8021
8806
|
{
|
|
8022
8807
|
"data-ohw-media-overlay": "",
|
|
8023
8808
|
variant: "outline",
|
|
8024
8809
|
size: "sm",
|
|
8025
|
-
"aria-label":
|
|
8810
|
+
"aria-label": replaceLabel,
|
|
8026
8811
|
className: "gap-1.5 cursor-pointer hover:bg-background",
|
|
8027
8812
|
style: {
|
|
8028
8813
|
...OVERLAY_BUTTON_STYLE,
|
|
@@ -8045,7 +8830,7 @@ function MediaOverlay({
|
|
|
8045
8830
|
},
|
|
8046
8831
|
children: [
|
|
8047
8832
|
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" ?
|
|
8833
|
+
replaceMode === "full" ? replaceLabel : null
|
|
8049
8834
|
]
|
|
8050
8835
|
}
|
|
8051
8836
|
)
|
|
@@ -8098,235 +8883,23 @@ function CarouselOverlay({
|
|
|
8098
8883
|
onMouseDown: (e) => e.preventDefault(),
|
|
8099
8884
|
onClick: (e) => {
|
|
8100
8885
|
e.stopPropagation();
|
|
8101
|
-
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, "");
|
|
8886
|
+
onEdit(hover.key);
|
|
8887
|
+
},
|
|
8888
|
+
children: [
|
|
8889
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react6.GalleryHorizontal, { size: 14 }),
|
|
8890
|
+
"Edit gallery"
|
|
8891
|
+
]
|
|
8892
|
+
}
|
|
8893
|
+
)
|
|
8206
8894
|
}
|
|
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
8895
|
);
|
|
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
8896
|
}
|
|
8323
8897
|
|
|
8324
8898
|
// src/ui/ai-section/AiSectionOverlay.tsx
|
|
8899
|
+
var import_react8 = require("react");
|
|
8900
|
+
var import_lucide_react7 = require("lucide-react");
|
|
8325
8901
|
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
|
-
}
|
|
8902
|
+
var findSectionElement = findByInstanceId;
|
|
8330
8903
|
function readRect(instanceId) {
|
|
8331
8904
|
const el = findSectionElement(instanceId);
|
|
8332
8905
|
if (!el) return null;
|
|
@@ -8366,7 +8939,7 @@ function useLiveSectionRect(sectionId) {
|
|
|
8366
8939
|
}
|
|
8367
8940
|
function computeSectionBoundaryFlags(instanceId) {
|
|
8368
8941
|
const topLevel = topLevelSections();
|
|
8369
|
-
const index = topLevel.findIndex((el) => (el
|
|
8942
|
+
const index = topLevel.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
8370
8943
|
if (index === -1) return { isFirst: true, isLast: true };
|
|
8371
8944
|
return { isFirst: index === 0, isLast: index === topLevel.length - 1 };
|
|
8372
8945
|
}
|
|
@@ -8450,18 +9023,20 @@ function AiSectionOverlay({
|
|
|
8450
9023
|
selectedIdRef.current = selectedId;
|
|
8451
9024
|
const report = (0, import_react8.useCallback)(
|
|
8452
9025
|
(el) => {
|
|
9026
|
+
const labelSrc = el ? sectionElementOf(el) : null;
|
|
8453
9027
|
postToParent2({
|
|
8454
9028
|
type: "ow:section-selected",
|
|
8455
|
-
sectionId: el ? el
|
|
8456
|
-
sectionLabel:
|
|
9029
|
+
sectionId: el ? instanceIdOf(el) || null : null,
|
|
9030
|
+
sectionLabel: labelSrc ? labelSrc.dataset.ohwSectionLabel ?? titleCaseSectionId(labelSrc.dataset.ohwSection ?? "") : null
|
|
8457
9031
|
});
|
|
8458
9032
|
},
|
|
8459
9033
|
[postToParent2]
|
|
8460
9034
|
);
|
|
8461
9035
|
const selectFromElement = (0, import_react8.useCallback)(
|
|
8462
9036
|
(el, options) => {
|
|
8463
|
-
const
|
|
8464
|
-
const
|
|
9037
|
+
const inner = el?.closest("[data-ohw-section]") ?? null;
|
|
9038
|
+
const sectionEl = inner ? movableUnit(inner) : null;
|
|
9039
|
+
const id = sectionEl ? instanceIdOf(sectionEl) || null : null;
|
|
8465
9040
|
if (id === selectedIdRef.current) return;
|
|
8466
9041
|
setSelectedId(id);
|
|
8467
9042
|
if (options?.report !== false) report(sectionEl);
|
|
@@ -8527,7 +9102,8 @@ function AiSectionOverlay({
|
|
|
8527
9102
|
return;
|
|
8528
9103
|
}
|
|
8529
9104
|
const sec = t.closest("[data-ohw-section]");
|
|
8530
|
-
|
|
9105
|
+
const unit = sec ? movableUnit(sec) : null;
|
|
9106
|
+
setHoveredId(unit ? instanceIdOf(unit) || null : null);
|
|
8531
9107
|
};
|
|
8532
9108
|
const onLeave = () => setHoveredId(null);
|
|
8533
9109
|
document.addEventListener("mousemove", onMove, { passive: true });
|
|
@@ -13038,6 +13614,7 @@ function readLogoSizeState(content, placement) {
|
|
|
13038
13614
|
function getLogoElement(el) {
|
|
13039
13615
|
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
13040
13616
|
if (marked) return marked;
|
|
13617
|
+
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
13041
13618
|
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
13042
13619
|
if (!root) return null;
|
|
13043
13620
|
const anchor = el.closest("a");
|
|
@@ -14104,15 +14681,17 @@ function useSectionDrag({
|
|
|
14104
14681
|
clearSectionDragVisuals();
|
|
14105
14682
|
return;
|
|
14106
14683
|
}
|
|
14107
|
-
const orderJson = JSON.stringify(
|
|
14684
|
+
const orderJson = JSON.stringify(
|
|
14685
|
+
mergePageSectionOrder(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname, entries)
|
|
14686
|
+
);
|
|
14108
14687
|
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
14109
14688
|
setAiSectionOrder(orderJson, window.location.pathname);
|
|
14110
14689
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
14111
|
-
applyPersistedOrder(
|
|
14690
|
+
applyPersistedOrder(getPageSectionOrderEntries(orderJson, window.location.pathname));
|
|
14112
14691
|
clearSectionDragVisuals();
|
|
14113
14692
|
requestAnimationFrame(() => {
|
|
14114
14693
|
if (editContentRef.current[SECTION_ORDER_KEY] === orderJson) {
|
|
14115
|
-
applyPersistedOrder(
|
|
14694
|
+
applyPersistedOrder(getPageSectionOrderEntries(orderJson, window.location.pathname));
|
|
14116
14695
|
}
|
|
14117
14696
|
requestAnimationFrame(() => {
|
|
14118
14697
|
window.dispatchEvent(new Event("resize"));
|
|
@@ -14145,8 +14724,9 @@ function useSectionDrag({
|
|
|
14145
14724
|
const target = e.target;
|
|
14146
14725
|
if (!(target instanceof HTMLElement)) return;
|
|
14147
14726
|
if (target.closest(SECTION_DRAG_EXCLUDED_SELECTOR)) return;
|
|
14148
|
-
const
|
|
14149
|
-
if (!
|
|
14727
|
+
const inner = target.closest("[data-ohw-section]");
|
|
14728
|
+
if (!inner || isChromeSection(inner) || inner.dataset.ohwSection === "footer") return;
|
|
14729
|
+
const sectionEl = movableUnit(inner);
|
|
14150
14730
|
if (!topLevelSections().includes(sectionEl)) return;
|
|
14151
14731
|
startSectionPressDrag(sectionEl, e.clientX, e.clientY, e.pointerId);
|
|
14152
14732
|
};
|
|
@@ -14413,6 +14993,9 @@ function collectEditableNodes(extraContent, root = document) {
|
|
|
14413
14993
|
if (el.dataset.ohwEditable === "link") {
|
|
14414
14994
|
return { key: el.dataset.ohwKey ?? "", type: "link", text: getLinkHref3(el) };
|
|
14415
14995
|
}
|
|
14996
|
+
if (el.dataset.ohwEditable === "map") {
|
|
14997
|
+
return { key: el.dataset.ohwKey ?? "", type: "map", text: el.dataset.ohwMapQuery ?? "" };
|
|
14998
|
+
}
|
|
14416
14999
|
return {
|
|
14417
15000
|
key: el.dataset.ohwKey ?? "",
|
|
14418
15001
|
type: el.dataset.ohwEditable ?? "text",
|
|
@@ -14975,21 +15558,10 @@ function parseSchedulingInsertAfter(insertAfter) {
|
|
|
14975
15558
|
insertBefore: insertAfter.slice(idx + INSERT_BEFORE_MARKER.length)
|
|
14976
15559
|
};
|
|
14977
15560
|
}
|
|
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;
|
|
15561
|
+
function resolveEntryAnchor(entry) {
|
|
15562
|
+
if (entry.anchorId !== void 0) return { anchorId: entry.anchorId, beforeId: entry.beforeId ?? null };
|
|
15563
|
+
const parsed = parseSchedulingInsertAfter(entry.insertAfter);
|
|
15564
|
+
return { anchorId: parsed.anchor, beforeId: parsed.insertBefore };
|
|
14993
15565
|
}
|
|
14994
15566
|
function schedulingMountDepth(insertAfter) {
|
|
14995
15567
|
if (!insertAfter.includes(INSERT_BEFORE_MARKER)) return 0;
|
|
@@ -15006,8 +15578,7 @@ function getPageSchedulingEntries(raw) {
|
|
|
15006
15578
|
}
|
|
15007
15579
|
}
|
|
15008
15580
|
function isSchedulingWidgetMissing(entry) {
|
|
15009
|
-
|
|
15010
|
-
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(effectiveInsertAfter)}"]`);
|
|
15581
|
+
return !document.querySelector(`[data-ohw-section="${schedulingSectionId(entry.insertAfter)}"]`);
|
|
15011
15582
|
}
|
|
15012
15583
|
function hasMissingSchedulingWidgets(entries) {
|
|
15013
15584
|
return entries.some(isSchedulingWidgetMissing);
|
|
@@ -15045,18 +15616,18 @@ function initSectionsFromContent(content, removeExisting = false, currentPath =
|
|
|
15045
15616
|
} catch {
|
|
15046
15617
|
}
|
|
15047
15618
|
}
|
|
15048
|
-
function mountSchedulingWidget(
|
|
15049
|
-
const
|
|
15050
|
-
const sectionId = schedulingSectionId(
|
|
15619
|
+
function mountSchedulingWidget(anchorId, notifyOnConnect = false, scheduleId, beforeId, existingWidgetId) {
|
|
15620
|
+
const widgetId = existingWidgetId ?? (beforeId ? `${anchorId}${INSERT_BEFORE_MARKER}${beforeId}` : anchorId);
|
|
15621
|
+
const sectionId = schedulingSectionId(widgetId);
|
|
15051
15622
|
if (document.querySelector(`[data-ohw-section="${sectionId}"]`)) return false;
|
|
15052
|
-
const
|
|
15053
|
-
if (!
|
|
15623
|
+
const anchorEl = document.querySelector(`[data-ohw-section="${anchorId}"]`);
|
|
15624
|
+
if (!anchorEl) return false;
|
|
15625
|
+
const mountPoint = anchorEl.closest('[data-ohw-section-container="scheduling"]') ?? anchorEl;
|
|
15054
15626
|
const container = document.createElement("div");
|
|
15055
15627
|
container.dataset.ohwSectionContainer = "scheduling";
|
|
15056
|
-
container.dataset.ohwSection = sectionId;
|
|
15057
15628
|
container.dataset.ohwInstance = sectionId;
|
|
15058
|
-
if (
|
|
15059
|
-
const beforeAnchor = document.querySelector(`[data-ohw-section="${
|
|
15629
|
+
if (beforeId) {
|
|
15630
|
+
const beforeAnchor = document.querySelector(`[data-ohw-section="${beforeId}"]`);
|
|
15060
15631
|
const beforePoint = beforeAnchor?.closest('[data-ohw-section-container="scheduling"]') ?? beforeAnchor;
|
|
15061
15632
|
if (!beforePoint) return false;
|
|
15062
15633
|
beforePoint.insertAdjacentElement("beforebegin", container);
|
|
@@ -15067,20 +15638,26 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
15067
15638
|
}
|
|
15068
15639
|
tail.insertAdjacentElement("afterend", container);
|
|
15069
15640
|
}
|
|
15070
|
-
|
|
15071
|
-
|
|
15072
|
-
|
|
15073
|
-
|
|
15074
|
-
|
|
15075
|
-
|
|
15076
|
-
|
|
15077
|
-
|
|
15078
|
-
|
|
15079
|
-
|
|
15080
|
-
|
|
15081
|
-
|
|
15082
|
-
|
|
15083
|
-
|
|
15641
|
+
try {
|
|
15642
|
+
const root = (0, import_client2.createRoot)(container);
|
|
15643
|
+
schedulingRoots.set(container, root);
|
|
15644
|
+
(0, import_react_dom3.flushSync)(() => {
|
|
15645
|
+
root.render(
|
|
15646
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
15647
|
+
SchedulingWidget,
|
|
15648
|
+
{
|
|
15649
|
+
notifyOnConnect,
|
|
15650
|
+
initialScheduleId: scheduleId,
|
|
15651
|
+
insertAfter: widgetId
|
|
15652
|
+
}
|
|
15653
|
+
)
|
|
15654
|
+
);
|
|
15655
|
+
});
|
|
15656
|
+
} catch (err) {
|
|
15657
|
+
console.error("[ow:scheduling] render threw", err);
|
|
15658
|
+
container.remove();
|
|
15659
|
+
return false;
|
|
15660
|
+
}
|
|
15084
15661
|
const tracker = getSectionsTracker();
|
|
15085
15662
|
let sections = [];
|
|
15086
15663
|
try {
|
|
@@ -15088,10 +15665,12 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
|
|
|
15088
15665
|
} catch {
|
|
15089
15666
|
}
|
|
15090
15667
|
const inEditor = typeof window !== "undefined" && window.self !== window.top;
|
|
15091
|
-
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter ===
|
|
15668
|
+
if (inEditor && !sections.find((s) => s.type === "scheduling" && s.insertAfter === widgetId)) {
|
|
15092
15669
|
sections.push({
|
|
15093
15670
|
type: "scheduling",
|
|
15094
|
-
insertAfter:
|
|
15671
|
+
insertAfter: widgetId,
|
|
15672
|
+
anchorId,
|
|
15673
|
+
beforeId: beforeId ?? null,
|
|
15095
15674
|
pagePath: window.location.pathname,
|
|
15096
15675
|
...scheduleId ? { scheduleId } : {}
|
|
15097
15676
|
});
|
|
@@ -15105,7 +15684,8 @@ function mountSchedulingEntries(entries, notifyOnConnect = false) {
|
|
|
15105
15684
|
for (let i = pending.length - 1; i >= 0; i--) {
|
|
15106
15685
|
const entry = pending[i];
|
|
15107
15686
|
const shouldNotify = typeof notifyOnConnect === "function" ? notifyOnConnect(entry) : notifyOnConnect;
|
|
15108
|
-
|
|
15687
|
+
const { anchorId, beforeId } = resolveEntryAnchor(entry);
|
|
15688
|
+
if (mountSchedulingWidget(anchorId, shouldNotify, entry.scheduleId ?? null, beforeId, entry.insertAfter)) {
|
|
15109
15689
|
pending.splice(i, 1);
|
|
15110
15690
|
}
|
|
15111
15691
|
}
|
|
@@ -15197,7 +15777,7 @@ var EDITOR_CHROME_SELECTOR = '[data-ohw-toolbar], [data-ohw-form-toolbar], [data
|
|
|
15197
15777
|
function isOverEditorChrome(x, y) {
|
|
15198
15778
|
return document.elementsFromPoint(x, y).some((el) => el instanceof HTMLElement && el.matches(EDITOR_CHROME_SELECTOR));
|
|
15199
15779
|
}
|
|
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"])';
|
|
15780
|
+
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
15781
|
function getVideoEl2(el) {
|
|
15202
15782
|
return el instanceof HTMLVideoElement ? el : el.querySelector("video");
|
|
15203
15783
|
}
|
|
@@ -15253,6 +15833,12 @@ function applyVideoSettingNode(key, val) {
|
|
|
15253
15833
|
});
|
|
15254
15834
|
return true;
|
|
15255
15835
|
}
|
|
15836
|
+
function applyMapQuery(el, val) {
|
|
15837
|
+
if (!(el instanceof HTMLIFrameElement)) return;
|
|
15838
|
+
const nextSrc = `https://www.google.com/maps?q=${encodeURIComponent(val)}&output=embed`;
|
|
15839
|
+
if (el.src !== nextSrc) el.src = nextSrc;
|
|
15840
|
+
el.setAttribute("data-ohw-map-query", val);
|
|
15841
|
+
}
|
|
15256
15842
|
function applyLinkByKey(key, val) {
|
|
15257
15843
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
15258
15844
|
if (el.dataset.ohwEditable === "link") applyLinkHref(el, val);
|
|
@@ -15263,6 +15849,11 @@ function applyLinkByKey(key, val) {
|
|
|
15263
15849
|
hrefAnchors.forEach((el) => applyLinkHref(el, val));
|
|
15264
15850
|
}
|
|
15265
15851
|
}
|
|
15852
|
+
function isInsideLinkEditor(target) {
|
|
15853
|
+
return Boolean(
|
|
15854
|
+
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"]')
|
|
15855
|
+
);
|
|
15856
|
+
}
|
|
15266
15857
|
function isInsideFloatingPanel(target) {
|
|
15267
15858
|
return Boolean(target.closest("[data-ohw-floating-panel]"));
|
|
15268
15859
|
}
|
|
@@ -15270,11 +15861,6 @@ function isPointOverFloatingPanel(clientX, clientY) {
|
|
|
15270
15861
|
const el = document.elementFromPoint(clientX, clientY);
|
|
15271
15862
|
return Boolean(el instanceof Element && el.closest("[data-ohw-floating-panel]"));
|
|
15272
15863
|
}
|
|
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
15864
|
function getHrefKeyFromElement(el) {
|
|
15279
15865
|
if (!el) return null;
|
|
15280
15866
|
const anchor = el.closest("[data-ohw-href-key]");
|
|
@@ -15533,7 +16119,7 @@ function getNavigationSelectionParent(el) {
|
|
|
15533
16119
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
15534
16120
|
return getFooterLinksContainer();
|
|
15535
16121
|
}
|
|
15536
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
|
|
16122
|
+
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
16123
|
return getNavigationRoot(el);
|
|
15538
16124
|
}
|
|
15539
16125
|
return null;
|
|
@@ -15748,7 +16334,6 @@ var ICONS = {
|
|
|
15748
16334
|
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
16335
|
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
16336
|
};
|
|
15751
|
-
var HEIGHT_SETTLE_DELAYS = [150, 400, 800];
|
|
15752
16337
|
var SELECTION_CHROME_GAP2 = 4;
|
|
15753
16338
|
var TOOLBAR_STROKE_GAP2 = 4;
|
|
15754
16339
|
var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
|
|
@@ -16128,6 +16713,7 @@ function StateToggle({
|
|
|
16128
16713
|
);
|
|
16129
16714
|
}
|
|
16130
16715
|
var contentCache = /* @__PURE__ */ new Map();
|
|
16716
|
+
var fetchedContentPaths = /* @__PURE__ */ new Set();
|
|
16131
16717
|
var brandingCache = /* @__PURE__ */ new Map();
|
|
16132
16718
|
var OHW_LOADER_STYLE = {
|
|
16133
16719
|
position: "fixed",
|
|
@@ -16657,13 +17243,6 @@ function OhhwellsBridge() {
|
|
|
16657
17243
|
const [isItemDragging, setIsItemDragging] = (0, import_react17.useState)(false);
|
|
16658
17244
|
const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react17.useState)(false);
|
|
16659
17245
|
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
17246
|
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react17.useState)(null);
|
|
16668
17247
|
const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react17.useState)(null);
|
|
16669
17248
|
const footerDragRef = (0, import_react17.useRef)(null);
|
|
@@ -16681,6 +17260,13 @@ function OhhwellsBridge() {
|
|
|
16681
17260
|
const brandKitRef = (0, import_react17.useRef)("");
|
|
16682
17261
|
const stylesRef = (0, import_react17.useRef)("");
|
|
16683
17262
|
const pendingDeleteUndoRef = (0, import_react17.useRef)(null);
|
|
17263
|
+
const [floatingPanel, setFloatingPanel] = (0, import_react17.useState)(null);
|
|
17264
|
+
const floatingPanelOpenRef = (0, import_react17.useRef)(false);
|
|
17265
|
+
const setFloatingPanelRef = (0, import_react17.useRef)(setFloatingPanel);
|
|
17266
|
+
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react17.useState)(null);
|
|
17267
|
+
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react17.useState)(null);
|
|
17268
|
+
const [editorViewport, setEditorViewport] = (0, import_react17.useState)("desktop");
|
|
17269
|
+
const [parentScrollSnap, setParentScrollSnap] = (0, import_react17.useState)(null);
|
|
16684
17270
|
const [sitePages, setSitePages] = (0, import_react17.useState)([]);
|
|
16685
17271
|
const [sectionsByPath, setSectionsByPath] = (0, import_react17.useState)({});
|
|
16686
17272
|
const sectionsPrefetchGenRef = (0, import_react17.useRef)(0);
|
|
@@ -16689,7 +17275,18 @@ function OhhwellsBridge() {
|
|
|
16689
17275
|
const linkPopoverOpenRef = (0, import_react17.useRef)(false);
|
|
16690
17276
|
const linkPopoverGraceUntilRef = (0, import_react17.useRef)(0);
|
|
16691
17277
|
setLinkPopoverRef.current = setLinkPopover;
|
|
17278
|
+
setFloatingPanelRef.current = setFloatingPanel;
|
|
16692
17279
|
linkPopoverSessionRef.current = linkPopover;
|
|
17280
|
+
floatingPanelOpenRef.current = Boolean(floatingPanel);
|
|
17281
|
+
(0, import_react17.useEffect)(() => {
|
|
17282
|
+
const syncViewport = () => {
|
|
17283
|
+
const next = window.innerWidth <= 480 ? "mobile" : "desktop";
|
|
17284
|
+
setEditorViewport((prev) => prev === next ? prev : next);
|
|
17285
|
+
};
|
|
17286
|
+
syncViewport();
|
|
17287
|
+
window.addEventListener("resize", syncViewport);
|
|
17288
|
+
return () => window.removeEventListener("resize", syncViewport);
|
|
17289
|
+
}, []);
|
|
16693
17290
|
const {
|
|
16694
17291
|
navDragRef,
|
|
16695
17292
|
navDropSlots,
|
|
@@ -18014,6 +18611,7 @@ function OhhwellsBridge() {
|
|
|
18014
18611
|
}
|
|
18015
18612
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
18016
18613
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
18614
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
18017
18615
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
18018
18616
|
}
|
|
18019
18617
|
applyBrandChrome(content);
|
|
@@ -18021,11 +18619,11 @@ function OhhwellsBridge() {
|
|
|
18021
18619
|
for (const [key, val] of Object.entries(content)) {
|
|
18022
18620
|
if (key === "__ohw_sections") continue;
|
|
18023
18621
|
if (key === AI_SECTIONS_KEY) continue;
|
|
18622
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
18623
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
18024
18624
|
if (key === BRAND_KIT_KEY) continue;
|
|
18025
18625
|
if (key === STYLE_STORE_KEY) continue;
|
|
18026
18626
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
18027
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
18028
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
18029
18627
|
if (applyVideoSettingNode(key, val)) continue;
|
|
18030
18628
|
if (applyCarouselNode(key, val)) continue;
|
|
18031
18629
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -18053,6 +18651,8 @@ function OhhwellsBridge() {
|
|
|
18053
18651
|
}
|
|
18054
18652
|
} else if (el.dataset.ohwEditable === "link") {
|
|
18055
18653
|
applyLinkHref(el, val);
|
|
18654
|
+
} else if (el.dataset.ohwEditable === "map") {
|
|
18655
|
+
applyMapQuery(el, val);
|
|
18056
18656
|
} else if (el.dataset.ohwEditable === "icon") {
|
|
18057
18657
|
applyIconMarkup(el, val);
|
|
18058
18658
|
} else if (el.dataset.ohwEditable === "form") {
|
|
@@ -18091,7 +18691,9 @@ function OhhwellsBridge() {
|
|
|
18091
18691
|
let cancelled = false;
|
|
18092
18692
|
setFetchState("loading");
|
|
18093
18693
|
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
18094
|
-
|
|
18694
|
+
const initialPath = pathname;
|
|
18695
|
+
fetchedContentPaths.add(`${subdomain}::${initialPath}`);
|
|
18696
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(initialPath)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
18095
18697
|
if (cancelled) return;
|
|
18096
18698
|
const content = data?.content ?? {};
|
|
18097
18699
|
const branding = Boolean(data?.showBranding);
|
|
@@ -18210,10 +18812,10 @@ function OhhwellsBridge() {
|
|
|
18210
18812
|
const applyFromCache = () => {
|
|
18211
18813
|
const content = contentCache.get(subdomain);
|
|
18212
18814
|
if (!content) return;
|
|
18213
|
-
retryMissingSchedulingMounts(getPageSchedulingEntries(content["__ohw_sections"]), false);
|
|
18214
|
-
initSectionInstancesFromContent(content, window.location.pathname);
|
|
18215
18815
|
observer?.disconnect();
|
|
18216
18816
|
try {
|
|
18817
|
+
retryMissingSchedulingMounts(getPageSchedulingEntries(content["__ohw_sections"]), false);
|
|
18818
|
+
initSectionInstancesFromContent(content, window.location.pathname);
|
|
18217
18819
|
applyBrandChrome(content);
|
|
18218
18820
|
if (typeof content[BRAND_KIT_KEY] === "string") {
|
|
18219
18821
|
applyBrandToDom(parseBrandKit(content[BRAND_KIT_KEY]));
|
|
@@ -18225,16 +18827,17 @@ function OhhwellsBridge() {
|
|
|
18225
18827
|
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
18226
18828
|
}
|
|
18227
18829
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
18830
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
18228
18831
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
18229
18832
|
}
|
|
18230
18833
|
for (const [key, val] of Object.entries(content)) {
|
|
18231
18834
|
if (key === "__ohw_sections") continue;
|
|
18232
18835
|
if (key === AI_SECTIONS_KEY) continue;
|
|
18836
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
18837
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
18233
18838
|
if (key === BRAND_KIT_KEY) continue;
|
|
18234
18839
|
if (key === STYLE_STORE_KEY) continue;
|
|
18235
18840
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
18236
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
18237
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
18238
18841
|
if (applyVideoSettingNode(key, val)) continue;
|
|
18239
18842
|
if (applyCarouselNode(key, val)) continue;
|
|
18240
18843
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -18249,6 +18852,8 @@ function OhhwellsBridge() {
|
|
|
18249
18852
|
if (video && video.src !== val) applyVideoSrc(video, val);
|
|
18250
18853
|
} else if (el.dataset.ohwEditable === "link") {
|
|
18251
18854
|
applyLinkHref(el, val);
|
|
18855
|
+
} else if (el.dataset.ohwEditable === "map") {
|
|
18856
|
+
applyMapQuery(el, val);
|
|
18252
18857
|
} else if (el.dataset.ohwEditable === "form") {
|
|
18253
18858
|
} else if (isIconMarkupValue(val)) {
|
|
18254
18859
|
} else if (el.innerHTML !== val) {
|
|
@@ -18280,6 +18885,17 @@ function OhhwellsBridge() {
|
|
|
18280
18885
|
debounceTimer = setTimeout(applyFromCache, 150);
|
|
18281
18886
|
};
|
|
18282
18887
|
applyFromCache();
|
|
18888
|
+
const pathCacheKey = `${subdomain}::${pathname}`;
|
|
18889
|
+
if (!fetchedContentPaths.has(pathCacheKey)) {
|
|
18890
|
+
fetchedContentPaths.add(pathCacheKey);
|
|
18891
|
+
const apiUrl = process.env.NEXT_PUBLIC_FLOWOPS_API_URL ?? "https://flowops-backend-staging-2yfdh7pwpq-as.a.run.app";
|
|
18892
|
+
fetch(`${apiUrl}/api/public/sites/${subdomain}/content?path=${encodeURIComponent(pathname)}`, { cache: "no-store" }).then((r2) => r2.ok ? r2.json() : null).then((data) => {
|
|
18893
|
+
if (!data?.content) return;
|
|
18894
|
+
contentCache.set(subdomain, data.content);
|
|
18895
|
+
applyFromCache();
|
|
18896
|
+
}).catch(() => {
|
|
18897
|
+
});
|
|
18898
|
+
}
|
|
18283
18899
|
observer = new MutationObserver(scheduleApply);
|
|
18284
18900
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
18285
18901
|
return () => {
|
|
@@ -18304,6 +18920,10 @@ function OhhwellsBridge() {
|
|
|
18304
18920
|
deselectRef.current();
|
|
18305
18921
|
deactivateRef.current();
|
|
18306
18922
|
}, [pathname, isEditMode]);
|
|
18923
|
+
(0, import_react17.useEffect)(() => {
|
|
18924
|
+
if (!isEditMode) return;
|
|
18925
|
+
initSectionInstancesFromContent(editContentRef.current, pathname);
|
|
18926
|
+
}, [pathname, isEditMode]);
|
|
18307
18927
|
(0, import_react17.useEffect)(() => {
|
|
18308
18928
|
const contentForNav = () => {
|
|
18309
18929
|
if (isEditMode) return editContentRef.current;
|
|
@@ -18395,26 +19015,11 @@ function OhhwellsBridge() {
|
|
|
18395
19015
|
const t2 = setTimeout(measure, 500);
|
|
18396
19016
|
const ro = new ResizeObserver(schedule);
|
|
18397
19017
|
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
19018
|
return () => {
|
|
18412
19019
|
clearTimeout(t1);
|
|
18413
19020
|
clearTimeout(t2);
|
|
18414
19021
|
if (raf != null) cancelAnimationFrame(raf);
|
|
18415
19022
|
ro.disconnect();
|
|
18416
|
-
clearResizeTimers();
|
|
18417
|
-
window.removeEventListener("resize", handleResize);
|
|
18418
19023
|
};
|
|
18419
19024
|
}, [pathname, isEditMode, postToParent2]);
|
|
18420
19025
|
(0, import_react17.useEffect)(() => {
|
|
@@ -18669,9 +19274,6 @@ function OhhwellsBridge() {
|
|
|
18669
19274
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
18670
19275
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
18671
19276
|
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
19277
|
if (isInsideFloatingPanel(target)) return;
|
|
18676
19278
|
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
18677
19279
|
if (target.closest(
|
|
@@ -18679,6 +19281,9 @@ function OhhwellsBridge() {
|
|
|
18679
19281
|
)) {
|
|
18680
19282
|
return;
|
|
18681
19283
|
}
|
|
19284
|
+
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
19285
|
+
clearMediaSelectionRef.current();
|
|
19286
|
+
}
|
|
18682
19287
|
{
|
|
18683
19288
|
const formEl = getFormElement(target);
|
|
18684
19289
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
@@ -18830,14 +19435,6 @@ function OhhwellsBridge() {
|
|
|
18830
19435
|
}
|
|
18831
19436
|
const clickedButton = findClosestButtonLike(target);
|
|
18832
19437
|
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
19438
|
if (isMediaEditable(editable) && !buttonOnMedia) {
|
|
18842
19439
|
e.preventDefault();
|
|
18843
19440
|
e.stopPropagation();
|
|
@@ -18864,11 +19461,6 @@ function OhhwellsBridge() {
|
|
|
18864
19461
|
const hrefLookupTarget = buttonOnMedia ? clickedButton : editable;
|
|
18865
19462
|
const hrefCtx = getHrefKeyFromElement(hrefLookupTarget);
|
|
18866
19463
|
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
19464
|
if (navAnchor) {
|
|
18873
19465
|
e.preventDefault();
|
|
18874
19466
|
e.stopPropagation();
|
|
@@ -19038,6 +19630,9 @@ function OhhwellsBridge() {
|
|
|
19038
19630
|
setHoveredItemRect(null);
|
|
19039
19631
|
hoveredNavContainerRef.current = null;
|
|
19040
19632
|
setHoveredNavContainerRect(null);
|
|
19633
|
+
siblingHintElRef.current = null;
|
|
19634
|
+
setSiblingHintRect(null);
|
|
19635
|
+
setSiblingHintRects([]);
|
|
19041
19636
|
return;
|
|
19042
19637
|
}
|
|
19043
19638
|
{
|
|
@@ -19156,7 +19751,6 @@ function OhhwellsBridge() {
|
|
|
19156
19751
|
hoveredNavContainerRef.current = null;
|
|
19157
19752
|
setHoveredNavContainerRect(null);
|
|
19158
19753
|
hoveredItemElRef.current = editable;
|
|
19159
|
-
setHoveredItemRect(isSelectedForHoverRef.current(editable) ? null : editable.getBoundingClientRect());
|
|
19160
19754
|
}
|
|
19161
19755
|
}
|
|
19162
19756
|
}
|
|
@@ -19453,7 +20047,7 @@ function OhhwellsBridge() {
|
|
|
19453
20047
|
}
|
|
19454
20048
|
};
|
|
19455
20049
|
const probeImageAt = (clientX, clientY, isDragOver = false, fromParentViewport = false) => {
|
|
19456
|
-
if (linkPopoverOpenRef.current) {
|
|
20050
|
+
if (linkPopoverOpenRef.current || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
19457
20051
|
if (hoveredImageRef.current) {
|
|
19458
20052
|
hoveredImageRef.current = null;
|
|
19459
20053
|
hoveredImageHasTextOverlapRef.current = false;
|
|
@@ -19818,8 +20412,7 @@ function OhhwellsBridge() {
|
|
|
19818
20412
|
};
|
|
19819
20413
|
const handleMouseMove = (e) => {
|
|
19820
20414
|
const { clientX, clientY } = e;
|
|
19821
|
-
if (
|
|
19822
|
-
if (isOverEditorChrome(clientX, clientY)) {
|
|
20415
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY) || isOverEditorChrome(clientX, clientY)) {
|
|
19823
20416
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
19824
20417
|
formHoverElRef.current = null;
|
|
19825
20418
|
setFormHoverRect(null);
|
|
@@ -19827,6 +20420,12 @@ function OhhwellsBridge() {
|
|
|
19827
20420
|
setHoveredItemRect(null);
|
|
19828
20421
|
hoveredNavContainerRef.current = null;
|
|
19829
20422
|
setHoveredNavContainerRect(null);
|
|
20423
|
+
siblingHintElRef.current = null;
|
|
20424
|
+
setSiblingHintRect(null);
|
|
20425
|
+
setSiblingHintRects([]);
|
|
20426
|
+
dismissImageHover();
|
|
20427
|
+
clearImageHover();
|
|
20428
|
+
setSectionGap(null);
|
|
19830
20429
|
return;
|
|
19831
20430
|
}
|
|
19832
20431
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
@@ -19838,7 +20437,11 @@ function OhhwellsBridge() {
|
|
|
19838
20437
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
19839
20438
|
const { clientX, clientY } = e.data;
|
|
19840
20439
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
19841
|
-
if (
|
|
20440
|
+
if (document.documentElement.hasAttribute("data-ohw-panel-dragging") || floatingPanelOpenRef.current && isPointOverFloatingPanel(clientX, clientY)) {
|
|
20441
|
+
dismissImageHover();
|
|
20442
|
+
clearImageHover();
|
|
20443
|
+
return;
|
|
20444
|
+
}
|
|
19842
20445
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
19843
20446
|
probeSectionGapAt(clientX, clientY);
|
|
19844
20447
|
probeImageAt(clientX, clientY);
|
|
@@ -20117,6 +20720,44 @@ function OhhwellsBridge() {
|
|
|
20117
20720
|
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
20118
20721
|
}, 400));
|
|
20119
20722
|
};
|
|
20723
|
+
const reapCommittedAiSections = (excludeIds) => {
|
|
20724
|
+
const aiState = parseAiSectionsState(aiSectionsRef.current);
|
|
20725
|
+
if (aiState.sections.length === 0) return [];
|
|
20726
|
+
let orderEntries = [];
|
|
20727
|
+
try {
|
|
20728
|
+
const parsed = JSON.parse(editContentRef.current[SECTION_ORDER_KEY] ?? "[]");
|
|
20729
|
+
if (Array.isArray(parsed)) orderEntries = parsed;
|
|
20730
|
+
} catch {
|
|
20731
|
+
return [];
|
|
20732
|
+
}
|
|
20733
|
+
const removedIds = orderEntries.filter((entry) => entry && typeof entry.instanceId === "string" && entry.removed).map((entry) => entry.instanceId);
|
|
20734
|
+
if (removedIds.length === 0) return [];
|
|
20735
|
+
const result = reapRemovedAiSections(aiState, parseStyleStore(stylesRef.current), removedIds, excludeIds);
|
|
20736
|
+
if (!result.changed) return [];
|
|
20737
|
+
const nodes = [];
|
|
20738
|
+
aiSectionsRef.current = serializeAiSectionsState(result.state);
|
|
20739
|
+
nodes.push({ key: AI_SECTIONS_KEY, text: aiSectionsRef.current });
|
|
20740
|
+
const reaped = new Set(result.reapedIds);
|
|
20741
|
+
const nextOrderJson = JSON.stringify(orderEntries.filter((entry) => !reaped.has(entry.instanceId)));
|
|
20742
|
+
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: nextOrderJson };
|
|
20743
|
+
setAiSectionOrder(nextOrderJson, window.location.pathname);
|
|
20744
|
+
nodes.push({ key: SECTION_ORDER_KEY, text: nextOrderJson });
|
|
20745
|
+
if (result.store) {
|
|
20746
|
+
stylesRef.current = JSON.stringify(result.store);
|
|
20747
|
+
nodes.push({ key: STYLE_STORE_KEY, text: stylesRef.current });
|
|
20748
|
+
}
|
|
20749
|
+
const nextContent = { ...editContentRef.current };
|
|
20750
|
+
for (const key of Object.keys(nextContent)) {
|
|
20751
|
+
if (key.startsWith(AI_SLOT_KEY_PREFIX) && result.slotPrefixes.some((prefix) => key.startsWith(prefix)) && nextContent[key] !== "") {
|
|
20752
|
+
nextContent[key] = "";
|
|
20753
|
+
nodes.push({ key, text: "" });
|
|
20754
|
+
}
|
|
20755
|
+
}
|
|
20756
|
+
editContentRef.current = nextContent;
|
|
20757
|
+
applyAiSectionsToDom(result.state);
|
|
20758
|
+
applyStylesToDom(parseStyleStore(stylesRef.current));
|
|
20759
|
+
return nodes;
|
|
20760
|
+
};
|
|
20120
20761
|
const handleHydrate = (e) => {
|
|
20121
20762
|
if (e.data?.type !== "ow:hydrate") return;
|
|
20122
20763
|
const content = e.data.content;
|
|
@@ -20135,6 +20776,7 @@ function OhhwellsBridge() {
|
|
|
20135
20776
|
}
|
|
20136
20777
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
20137
20778
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
20779
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
20138
20780
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
20139
20781
|
}
|
|
20140
20782
|
applyBrandChrome(content);
|
|
@@ -20146,11 +20788,11 @@ function OhhwellsBridge() {
|
|
|
20146
20788
|
continue;
|
|
20147
20789
|
}
|
|
20148
20790
|
if (key === AI_SECTIONS_KEY) continue;
|
|
20791
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
20792
|
+
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
20149
20793
|
if (key === BRAND_KIT_KEY) continue;
|
|
20150
20794
|
if (key === STYLE_STORE_KEY) continue;
|
|
20151
20795
|
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
20796
|
if (applyVideoSettingNode(key, val)) continue;
|
|
20155
20797
|
if (applyCarouselNode(key, val)) continue;
|
|
20156
20798
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -20164,6 +20806,8 @@ function OhhwellsBridge() {
|
|
|
20164
20806
|
if (video && video.src !== val) applyVideoSrc(video, val);
|
|
20165
20807
|
} else if (el.dataset.ohwEditable === "link") {
|
|
20166
20808
|
applyLinkHref(el, val);
|
|
20809
|
+
} else if (el.dataset.ohwEditable === "map") {
|
|
20810
|
+
applyMapQuery(el, val);
|
|
20167
20811
|
} else if (el.dataset.ohwEditable === "icon") {
|
|
20168
20812
|
applyIconMarkup(el, val);
|
|
20169
20813
|
} else if (isIconMarkupValue(val)) {
|
|
@@ -20185,6 +20829,11 @@ function OhhwellsBridge() {
|
|
|
20185
20829
|
reconcileFooterOrderFromContent(editContentRef.current);
|
|
20186
20830
|
syncNavigationDragCursorAttrs();
|
|
20187
20831
|
enforceLinkHrefs();
|
|
20832
|
+
const hydrateReapExclude = /* @__PURE__ */ new Set();
|
|
20833
|
+
const hydratePendingUndo = pendingDeleteUndoRef.current;
|
|
20834
|
+
if (hydratePendingUndo?.sectionInstanceId) hydrateReapExclude.add(hydratePendingUndo.sectionInstanceId);
|
|
20835
|
+
const reapNodes = reapCommittedAiSections(hydrateReapExclude);
|
|
20836
|
+
if (reapNodes.length > 0) postToParentRef.current({ type: "ow:change", nodes: reapNodes });
|
|
20188
20837
|
const hydratedHeight = document.body.scrollHeight;
|
|
20189
20838
|
if (hydratedHeight > 50) postToParentRef.current({ type: "ow:height", height: hydratedHeight });
|
|
20190
20839
|
postToParentRef.current({ type: "ow:hydrate-done" });
|
|
@@ -20324,12 +20973,35 @@ function OhhwellsBridge() {
|
|
|
20324
20973
|
window.addEventListener("message", handleAiSetBrand);
|
|
20325
20974
|
const handleAiSetStyles = (e) => {
|
|
20326
20975
|
if (e.data?.type !== "ow:ai-set-styles") return;
|
|
20327
|
-
|
|
20976
|
+
let value = typeof e.data.value === "string" ? e.data.value : "";
|
|
20328
20977
|
const previous = stylesRef.current;
|
|
20978
|
+
let previousSections;
|
|
20979
|
+
const store = parseStyleStore(value);
|
|
20980
|
+
if (store) {
|
|
20981
|
+
const folded = foldAlignIntoTrees(parseAiSectionsState(aiSectionsRef.current), store);
|
|
20982
|
+
if (folded.changed) {
|
|
20983
|
+
const nextSections = serializeAiSectionsState(folded.state);
|
|
20984
|
+
if (nextSections !== aiSectionsRef.current) {
|
|
20985
|
+
previousSections = aiSectionsRef.current;
|
|
20986
|
+
aiSectionsRef.current = nextSections;
|
|
20987
|
+
applyAiSectionsToDom(folded.state);
|
|
20988
|
+
postToParentRef.current({
|
|
20989
|
+
type: "ow:change",
|
|
20990
|
+
nodes: [{ key: AI_SECTIONS_KEY, text: nextSections }]
|
|
20991
|
+
});
|
|
20992
|
+
}
|
|
20993
|
+
value = JSON.stringify(folded.store);
|
|
20994
|
+
}
|
|
20995
|
+
}
|
|
20329
20996
|
stylesRef.current = value;
|
|
20330
20997
|
applyStylesToDom(parseStyleStore(value));
|
|
20331
20998
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: STYLE_STORE_KEY, text: value }] });
|
|
20332
|
-
postToParentRef.current({
|
|
20999
|
+
postToParentRef.current({
|
|
21000
|
+
type: "ow:ai-styles-applied",
|
|
21001
|
+
previous,
|
|
21002
|
+
value,
|
|
21003
|
+
...previousSections !== void 0 ? { previousSections } : {}
|
|
21004
|
+
});
|
|
20333
21005
|
};
|
|
20334
21006
|
window.addEventListener("message", handleAiSetStyles);
|
|
20335
21007
|
const handleGetBrand = (e) => {
|
|
@@ -20346,8 +21018,11 @@ function OhhwellsBridge() {
|
|
|
20346
21018
|
if (!instanceId || !direction) return;
|
|
20347
21019
|
const entries = moveSectionInstance(instanceId, direction, window.location.pathname);
|
|
20348
21020
|
if (!entries) return;
|
|
20349
|
-
const orderJson = JSON.stringify(
|
|
21021
|
+
const orderJson = JSON.stringify(
|
|
21022
|
+
mergePageSectionOrder(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname, entries)
|
|
21023
|
+
);
|
|
20350
21024
|
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
21025
|
+
applyPersistedOrder(getPageSectionOrderEntries(orderJson, window.location.pathname));
|
|
20351
21026
|
setAiSectionOrder(orderJson, window.location.pathname);
|
|
20352
21027
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
20353
21028
|
window.dispatchEvent(new Event("resize"));
|
|
@@ -20393,8 +21068,11 @@ function OhhwellsBridge() {
|
|
|
20393
21068
|
const currentEntries = getPageSectionOrderEntries(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname);
|
|
20394
21069
|
const entries = deleteSectionInstance(instanceId, window.location.pathname, currentEntries);
|
|
20395
21070
|
if (!entries) return;
|
|
20396
|
-
const orderJson = JSON.stringify(
|
|
21071
|
+
const orderJson = JSON.stringify(
|
|
21072
|
+
mergePageSectionOrder(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname, entries)
|
|
21073
|
+
);
|
|
20397
21074
|
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
21075
|
+
setAiSectionOrder(orderJson, window.location.pathname);
|
|
20398
21076
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
20399
21077
|
aiSectionApiRef.current?.clear();
|
|
20400
21078
|
window.dispatchEvent(new Event("resize"));
|
|
@@ -20403,6 +21081,7 @@ function OhhwellsBridge() {
|
|
|
20403
21081
|
const actionId = newInstanceId();
|
|
20404
21082
|
pendingDeleteUndoRef.current = {
|
|
20405
21083
|
actionId,
|
|
21084
|
+
sectionInstanceId: instanceId,
|
|
20406
21085
|
restore: () => {
|
|
20407
21086
|
const restoredEntries = getPageSectionOrderEntries(
|
|
20408
21087
|
editContentRef.current[SECTION_ORDER_KEY],
|
|
@@ -20410,8 +21089,11 @@ function OhhwellsBridge() {
|
|
|
20410
21089
|
);
|
|
20411
21090
|
const restored = restoreSectionInstance(instanceId, window.location.pathname, restoredEntries);
|
|
20412
21091
|
if (!restored) return;
|
|
20413
|
-
const restoredJson = JSON.stringify(
|
|
21092
|
+
const restoredJson = JSON.stringify(
|
|
21093
|
+
mergePageSectionOrder(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname, restored)
|
|
21094
|
+
);
|
|
20414
21095
|
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: restoredJson };
|
|
21096
|
+
setAiSectionOrder(restoredJson, window.location.pathname);
|
|
20415
21097
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: restoredJson }] });
|
|
20416
21098
|
window.dispatchEvent(new Event("resize"));
|
|
20417
21099
|
const restoreHeight = document.body.scrollHeight;
|
|
@@ -20437,7 +21119,9 @@ function OhhwellsBridge() {
|
|
|
20437
21119
|
const result = duplicateSectionInstance(instanceId, newId, window.location.pathname, currentEntries);
|
|
20438
21120
|
if (!result) return;
|
|
20439
21121
|
const { entries, keyRekeys } = result;
|
|
20440
|
-
const orderJson = JSON.stringify(
|
|
21122
|
+
const orderJson = JSON.stringify(
|
|
21123
|
+
mergePageSectionOrder(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname, entries)
|
|
21124
|
+
);
|
|
20441
21125
|
const nodes = [{ key: SECTION_ORDER_KEY, text: orderJson }];
|
|
20442
21126
|
for (const { from, to } of keyRekeys) {
|
|
20443
21127
|
const inherited = editContentRef.current[from];
|
|
@@ -20447,6 +21131,7 @@ function OhhwellsBridge() {
|
|
|
20447
21131
|
...editContentRef.current,
|
|
20448
21132
|
...Object.fromEntries(nodes.map(({ key, text }) => [key, text]))
|
|
20449
21133
|
};
|
|
21134
|
+
applyPersistedOrder(getPageSectionOrderEntries(orderJson, window.location.pathname));
|
|
20450
21135
|
setAiSectionOrder(orderJson, window.location.pathname);
|
|
20451
21136
|
postToParentRef.current({ type: "ow:change", nodes });
|
|
20452
21137
|
window.dispatchEvent(new Event("resize"));
|
|
@@ -20465,6 +21150,12 @@ function OhhwellsBridge() {
|
|
|
20465
21150
|
closeLinkPopoverRef.current();
|
|
20466
21151
|
return;
|
|
20467
21152
|
}
|
|
21153
|
+
if (floatingPanelOpenRef.current) {
|
|
21154
|
+
setFloatingPanelRef.current(null);
|
|
21155
|
+
deselectRef.current();
|
|
21156
|
+
deactivateRef.current();
|
|
21157
|
+
return;
|
|
21158
|
+
}
|
|
20468
21159
|
deselectRef.current();
|
|
20469
21160
|
deactivateRef.current();
|
|
20470
21161
|
clearMediaSelectionRef.current();
|
|
@@ -20710,6 +21401,10 @@ function OhhwellsBridge() {
|
|
|
20710
21401
|
};
|
|
20711
21402
|
const handleSave = (e) => {
|
|
20712
21403
|
if (e.data?.type !== "ow:save") return;
|
|
21404
|
+
const pendingUndo = pendingDeleteUndoRef.current;
|
|
21405
|
+
const reapExclude = /* @__PURE__ */ new Set();
|
|
21406
|
+
if (pendingUndo?.sectionInstanceId) reapExclude.add(pendingUndo.sectionInstanceId);
|
|
21407
|
+
const reapNodes = reapCommittedAiSections(reapExclude);
|
|
20713
21408
|
const nodes = collectEditableNodes(editContentRef.current);
|
|
20714
21409
|
const tracker = document.querySelector("[data-ohw-sections-tracker]");
|
|
20715
21410
|
if (tracker?.textContent) nodes.push({ key: "__ohw_sections", type: "sections", text: tracker.textContent });
|
|
@@ -20729,6 +21424,11 @@ function OhhwellsBridge() {
|
|
|
20729
21424
|
const text = specs.length ? JSON.stringify(specs) : editContentRef.current[fieldsKey(formKey)];
|
|
20730
21425
|
if (text) nodes.push({ key: fieldsKey(formKey), type: "text", text });
|
|
20731
21426
|
});
|
|
21427
|
+
for (const reapNode of reapNodes) {
|
|
21428
|
+
if (reapNode.key.startsWith(AI_SLOT_KEY_PREFIX) && !nodes.some((n) => n.key === reapNode.key)) {
|
|
21429
|
+
nodes.push({ key: reapNode.key, type: "text", text: reapNode.text });
|
|
21430
|
+
}
|
|
21431
|
+
}
|
|
20732
21432
|
postToParentRef.current({ type: "ow:save-result", nodes });
|
|
20733
21433
|
};
|
|
20734
21434
|
const handleInsertSection = (e) => {
|
|
@@ -20739,8 +21439,12 @@ function OhhwellsBridge() {
|
|
|
20739
21439
|
if (inserted) {
|
|
20740
21440
|
const tracker = getSectionsTracker();
|
|
20741
21441
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent ?? "[]" }] });
|
|
20742
|
-
const
|
|
20743
|
-
|
|
21442
|
+
const reportHeight = () => {
|
|
21443
|
+
const h = document.body.scrollHeight;
|
|
21444
|
+
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
21445
|
+
};
|
|
21446
|
+
reportHeight();
|
|
21447
|
+
setTimeout(reportHeight, 500);
|
|
20744
21448
|
}
|
|
20745
21449
|
};
|
|
20746
21450
|
const handleSwitchSchedule = (e) => {
|
|
@@ -21144,10 +21848,10 @@ function OhhwellsBridge() {
|
|
|
21144
21848
|
window.removeEventListener("message", handleDeleteSection);
|
|
21145
21849
|
window.removeEventListener("message", handleDuplicateSection);
|
|
21146
21850
|
window.removeEventListener("message", handleDeactivate);
|
|
21147
|
-
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
21148
21851
|
window.removeEventListener("message", handleToastAction);
|
|
21149
21852
|
window.removeEventListener("message", handleFormCount);
|
|
21150
21853
|
window.removeEventListener("message", handleUiEscape);
|
|
21854
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
21151
21855
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
21152
21856
|
autoSaveTimers.current.clear();
|
|
21153
21857
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
@@ -21350,7 +22054,7 @@ function OhhwellsBridge() {
|
|
|
21350
22054
|
postToParent2({
|
|
21351
22055
|
type: "ow:ready",
|
|
21352
22056
|
version: "1",
|
|
21353
|
-
bridgeVersion: "0.1.
|
|
22057
|
+
bridgeVersion: "0.1.92",
|
|
21354
22058
|
path: pathname,
|
|
21355
22059
|
nodes: collectEditableNodes(editContentRef.current),
|
|
21356
22060
|
sections
|
|
@@ -22269,6 +22973,59 @@ function OhhwellsBridge() {
|
|
|
22269
22973
|
) : null
|
|
22270
22974
|
] });
|
|
22271
22975
|
}
|
|
22976
|
+
|
|
22977
|
+
// src/ui/EmptySection.tsx
|
|
22978
|
+
var import_link = __toESM(require("next/link"), 1);
|
|
22979
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
22980
|
+
function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey }) {
|
|
22981
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
|
|
22982
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
22983
|
+
"p",
|
|
22984
|
+
{
|
|
22985
|
+
style: {
|
|
22986
|
+
fontFamily: "var(--brand-font-body)",
|
|
22987
|
+
fontSize: "0.75rem",
|
|
22988
|
+
fontWeight: 500,
|
|
22989
|
+
letterSpacing: "0.15em",
|
|
22990
|
+
textTransform: "uppercase",
|
|
22991
|
+
color: "var(--brand-accent)",
|
|
22992
|
+
marginBottom: "1.5rem"
|
|
22993
|
+
},
|
|
22994
|
+
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" }) })
|
|
22995
|
+
}
|
|
22996
|
+
),
|
|
22997
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
22998
|
+
"h1",
|
|
22999
|
+
{
|
|
23000
|
+
style: {
|
|
23001
|
+
fontFamily: "var(--brand-font-heading)",
|
|
23002
|
+
fontSize: "clamp(2rem, 3.5vw, 2.75rem)",
|
|
23003
|
+
lineHeight: 1.1,
|
|
23004
|
+
letterSpacing: "-0.025em",
|
|
23005
|
+
color: "var(--brand-text)",
|
|
23006
|
+
marginBottom: "1rem"
|
|
23007
|
+
},
|
|
23008
|
+
...titleKey ? { "data-ohw-editable": "text", "data-ohw-key": titleKey, "data-ohw-max-length": 80 } : {},
|
|
23009
|
+
children: title
|
|
23010
|
+
}
|
|
23011
|
+
),
|
|
23012
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
23013
|
+
"p",
|
|
23014
|
+
{
|
|
23015
|
+
style: {
|
|
23016
|
+
fontFamily: "var(--brand-font-body)",
|
|
23017
|
+
fontSize: "1rem",
|
|
23018
|
+
lineHeight: 1.7,
|
|
23019
|
+
fontWeight: 300,
|
|
23020
|
+
color: "var(--brand-text-muted)",
|
|
23021
|
+
maxWidth: "340px"
|
|
23022
|
+
},
|
|
23023
|
+
...subtitleKey ? { "data-ohw-editable": "text", "data-ohw-key": subtitleKey, "data-ohw-max-length": 160 } : {},
|
|
23024
|
+
children: "This page doesn't have any content yet."
|
|
23025
|
+
}
|
|
23026
|
+
)
|
|
23027
|
+
] });
|
|
23028
|
+
}
|
|
22272
23029
|
// Annotate the CommonJS export names for ESM import in node:
|
|
22273
23030
|
0 && (module.exports = {
|
|
22274
23031
|
AI_DEFAULT_BRAND,
|
|
@@ -22286,6 +23043,7 @@ function OhhwellsBridge() {
|
|
|
22286
23043
|
DropdownMenuItem,
|
|
22287
23044
|
DropdownMenuSeparator,
|
|
22288
23045
|
DropdownMenuTrigger,
|
|
23046
|
+
EmptySection,
|
|
22289
23047
|
ItemActionToolbar,
|
|
22290
23048
|
ItemInteractionLayer,
|
|
22291
23049
|
LinkEditorPanel,
|