@ohhwells/bridge 0.1.93 → 0.1.95
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 +409 -248
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +409 -248
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -70,6 +70,9 @@ function isRenderableTree(value) {
|
|
|
70
70
|
// src/lib/ai-sections-store.ts
|
|
71
71
|
var AI_SECTIONS_KEY = "__ohw_ai_sections";
|
|
72
72
|
var AI_SLOT_KEY_PREFIX = "ai.";
|
|
73
|
+
function aiSlotKeyPrefixFor(sectionId) {
|
|
74
|
+
return `${AI_SLOT_KEY_PREFIX}${sectionId}.`;
|
|
75
|
+
}
|
|
73
76
|
var EMPTY_AI_SECTIONS = { v: 1, sections: [] };
|
|
74
77
|
function parseAiSectionsState(raw) {
|
|
75
78
|
if (!raw) return EMPTY_AI_SECTIONS;
|
|
@@ -181,6 +184,33 @@ function deleteSectionFromState(state, sectionId) {
|
|
|
181
184
|
if (removed.includes(sectionId)) return state;
|
|
182
185
|
return { ...state, v: 1, sections: state.sections, removed: [...removed, sectionId] };
|
|
183
186
|
}
|
|
187
|
+
function reapRemovedAiSections(state, store, removedIds, excludeIds = /* @__PURE__ */ new Set()) {
|
|
188
|
+
const generated = new Set(state.sections.map((entry) => entry.id));
|
|
189
|
+
const reapedIds = [...new Set(removedIds)].filter((id) => generated.has(id) && !excludeIds.has(id));
|
|
190
|
+
if (reapedIds.length === 0) {
|
|
191
|
+
return { state, store, reapedIds: [], slotPrefixes: [], changed: false };
|
|
192
|
+
}
|
|
193
|
+
const reaped = new Set(reapedIds);
|
|
194
|
+
const slotPrefixes = reapedIds.map(aiSlotKeyPrefixFor);
|
|
195
|
+
const nextState = {
|
|
196
|
+
...state,
|
|
197
|
+
v: 1,
|
|
198
|
+
sections: state.sections.filter((entry) => !reaped.has(entry.id))
|
|
199
|
+
};
|
|
200
|
+
let nextStore = store;
|
|
201
|
+
if (store) {
|
|
202
|
+
const sections = {};
|
|
203
|
+
for (const [key, override] of Object.entries(store.sections)) {
|
|
204
|
+
if (!reaped.has(key)) sections[key] = override;
|
|
205
|
+
}
|
|
206
|
+
const nodes = {};
|
|
207
|
+
for (const [key, override] of Object.entries(store.nodes)) {
|
|
208
|
+
if (!slotPrefixes.some((prefix) => key.startsWith(prefix))) nodes[key] = override;
|
|
209
|
+
}
|
|
210
|
+
nextStore = { v: 1, sections, nodes };
|
|
211
|
+
}
|
|
212
|
+
return { state: nextState, store: nextStore, reapedIds, slotPrefixes, changed: true };
|
|
213
|
+
}
|
|
184
214
|
|
|
185
215
|
// src/lib/brand-chrome.ts
|
|
186
216
|
var BRAND_NAME_KEY = "__ohw_brand_name";
|
|
@@ -559,6 +589,254 @@ function applyStylesToDom(store) {
|
|
|
559
589
|
import { flushSync } from "react-dom";
|
|
560
590
|
import { createRoot } from "react-dom/client";
|
|
561
591
|
|
|
592
|
+
// src/lib/sections.ts
|
|
593
|
+
var LINK_PICKER_EXCLUDED_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
|
|
594
|
+
function isChromeSection(el) {
|
|
595
|
+
return el.matches("header, nav, footer, aside");
|
|
596
|
+
}
|
|
597
|
+
function titleCaseSectionId(id) {
|
|
598
|
+
return id.split("-").filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
599
|
+
}
|
|
600
|
+
function parseSectionsFromRoot(root) {
|
|
601
|
+
const seen = /* @__PURE__ */ new Set();
|
|
602
|
+
const sections = [];
|
|
603
|
+
for (const el of root.querySelectorAll("[data-ohw-section]")) {
|
|
604
|
+
const id = el.getAttribute("data-ohw-section") ?? "";
|
|
605
|
+
if (!id || seen.has(id) || LINK_PICKER_EXCLUDED_IDS.has(id)) continue;
|
|
606
|
+
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
607
|
+
if (el.hasAttribute("data-ohw-ai-template-hidden") || el.hasAttribute("data-ohw-ai-removed") || el.hasAttribute("data-ohw-ai-replaced-by"))
|
|
608
|
+
continue;
|
|
609
|
+
seen.add(id);
|
|
610
|
+
const label = el.getAttribute("data-ohw-section-label") ?? titleCaseSectionId(id);
|
|
611
|
+
sections.push({ id, label });
|
|
612
|
+
}
|
|
613
|
+
return sections;
|
|
614
|
+
}
|
|
615
|
+
function collectSectionsFromDom() {
|
|
616
|
+
if (typeof document === "undefined") return [];
|
|
617
|
+
return parseSectionsFromRoot(document);
|
|
618
|
+
}
|
|
619
|
+
function parseSectionsFromHtml(html) {
|
|
620
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
621
|
+
return parseSectionsFromRoot(doc);
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
// src/lib/section-instances.ts
|
|
625
|
+
var SECTION_ORDER_KEY = "__ohw_section_order";
|
|
626
|
+
var REMOVED_ATTR = "data-ohw-section-removed";
|
|
627
|
+
function isRemovedSection(el) {
|
|
628
|
+
return el.hasAttribute(REMOVED_ATTR);
|
|
629
|
+
}
|
|
630
|
+
function movableUnit(el) {
|
|
631
|
+
return el.closest("[data-ohw-section-container]") ?? el;
|
|
632
|
+
}
|
|
633
|
+
function sectionTypeOf(el) {
|
|
634
|
+
return el.getAttribute("data-ohw-section") ?? el.querySelector("[data-ohw-section]")?.getAttribute("data-ohw-section") ?? "";
|
|
635
|
+
}
|
|
636
|
+
function sectionElementOf(el) {
|
|
637
|
+
return el.hasAttribute("data-ohw-section") ? el : el.querySelector("[data-ohw-section]") ?? el;
|
|
638
|
+
}
|
|
639
|
+
function collectTopLevelUnits(predicate) {
|
|
640
|
+
const seen = /* @__PURE__ */ new Set();
|
|
641
|
+
const result = [];
|
|
642
|
+
document.querySelectorAll("[data-ohw-section]").forEach((el) => {
|
|
643
|
+
if (!predicate(el)) return;
|
|
644
|
+
const unit = movableUnit(el);
|
|
645
|
+
if (unit.parentElement?.closest("[data-ohw-section],[data-ohw-section-container]")) return;
|
|
646
|
+
if (seen.has(unit)) return;
|
|
647
|
+
seen.add(unit);
|
|
648
|
+
result.push(unit);
|
|
649
|
+
});
|
|
650
|
+
return result;
|
|
651
|
+
}
|
|
652
|
+
function topLevelSections() {
|
|
653
|
+
return collectTopLevelUnits((el) => !isChromeSection(el) && !isRemovedSection(movableUnit(el)));
|
|
654
|
+
}
|
|
655
|
+
function instanceIdOf(el) {
|
|
656
|
+
return el.dataset.ohwInstance ?? el.dataset.ohwSection ?? "";
|
|
657
|
+
}
|
|
658
|
+
function findByInstanceId(instanceId) {
|
|
659
|
+
const escapedId = CSS.escape(instanceId);
|
|
660
|
+
const direct = document.querySelector(`[data-ohw-instance="${escapedId}"]`);
|
|
661
|
+
if (direct) return movableUnit(direct);
|
|
662
|
+
const bare = document.querySelector(`[data-ohw-section="${escapedId}"]:not([data-ohw-instance])`);
|
|
663
|
+
return bare ? movableUnit(bare) : null;
|
|
664
|
+
}
|
|
665
|
+
function planSectionMove(instanceId, targetIndex, currentPath) {
|
|
666
|
+
const sections = topLevelSections();
|
|
667
|
+
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
668
|
+
if (index === -1) return null;
|
|
669
|
+
const dragged = sections[index];
|
|
670
|
+
const others = sections.filter((_, i) => i !== index);
|
|
671
|
+
const clamped = Math.max(0, Math.min(targetIndex, others.length));
|
|
672
|
+
const reordered = [...others.slice(0, clamped), dragged, ...others.slice(clamped)];
|
|
673
|
+
return reordered.map((el, order) => ({
|
|
674
|
+
instanceId: instanceIdOf(el),
|
|
675
|
+
type: sectionTypeOf(el),
|
|
676
|
+
order,
|
|
677
|
+
pagePath: currentPath
|
|
678
|
+
}));
|
|
679
|
+
}
|
|
680
|
+
function moveSectionInstance(instanceId, direction, currentPath) {
|
|
681
|
+
const sections = topLevelSections();
|
|
682
|
+
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
683
|
+
if (index === -1) return null;
|
|
684
|
+
const siblingIndex = direction === "up" ? index - 1 : index + 1;
|
|
685
|
+
if (siblingIndex < 0 || siblingIndex >= sections.length) return null;
|
|
686
|
+
const entries = planSectionMove(instanceId, siblingIndex, currentPath);
|
|
687
|
+
if (!entries) return null;
|
|
688
|
+
applyPersistedOrder(entries);
|
|
689
|
+
return entries;
|
|
690
|
+
}
|
|
691
|
+
function syncRemovedFlags(entries) {
|
|
692
|
+
const removedIds = new Set(entries.filter((e) => e.removed).map((e) => e.instanceId));
|
|
693
|
+
document.querySelectorAll(`[${REMOVED_ATTR}]`).forEach((el) => {
|
|
694
|
+
if (!removedIds.has(instanceIdOf(el))) {
|
|
695
|
+
el.style.removeProperty("display");
|
|
696
|
+
el.removeAttribute(REMOVED_ATTR);
|
|
697
|
+
}
|
|
698
|
+
});
|
|
699
|
+
for (const id of removedIds) {
|
|
700
|
+
const el = findByInstanceId(id);
|
|
701
|
+
if (el) {
|
|
702
|
+
el.style.display = "none";
|
|
703
|
+
el.setAttribute(REMOVED_ATTR, "");
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
function applyPersistedOrder(entries) {
|
|
708
|
+
syncRemovedFlags(entries);
|
|
709
|
+
if (entries.length === 0) return;
|
|
710
|
+
const sections = topLevelSections();
|
|
711
|
+
if (sections.length === 0) return;
|
|
712
|
+
const orderIndex = new Map(entries.map((e) => [e.instanceId, e.order]));
|
|
713
|
+
const ordered = [...sections].sort((a, b) => {
|
|
714
|
+
const aOrder = orderIndex.get(instanceIdOf(a));
|
|
715
|
+
const bOrder = orderIndex.get(instanceIdOf(b));
|
|
716
|
+
if (aOrder === void 0 && bOrder === void 0) return 0;
|
|
717
|
+
if (aOrder === void 0) return 1;
|
|
718
|
+
if (bOrder === void 0) return -1;
|
|
719
|
+
return aOrder - bOrder;
|
|
720
|
+
});
|
|
721
|
+
let prev = null;
|
|
722
|
+
for (const el of ordered) {
|
|
723
|
+
if (prev) prev.after(el);
|
|
724
|
+
prev = el;
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
function setSectionRemoved(instanceId, currentPath, existingEntries, removed) {
|
|
728
|
+
if (!findByInstanceId(instanceId)) return null;
|
|
729
|
+
const byId = new Map(existingEntries.map((e) => [e.instanceId, e]));
|
|
730
|
+
const allSections = collectTopLevelUnits((el) => !isChromeSection(el));
|
|
731
|
+
allSections.forEach((el, order) => {
|
|
732
|
+
const id = instanceIdOf(el);
|
|
733
|
+
if (!byId.has(id)) {
|
|
734
|
+
byId.set(id, { instanceId: id, type: sectionTypeOf(el), order, pagePath: currentPath });
|
|
735
|
+
}
|
|
736
|
+
});
|
|
737
|
+
const target = byId.get(instanceId);
|
|
738
|
+
if (!target) return null;
|
|
739
|
+
byId.set(instanceId, { ...target, removed });
|
|
740
|
+
const entries = Array.from(byId.values());
|
|
741
|
+
applyPersistedOrder(entries);
|
|
742
|
+
return entries;
|
|
743
|
+
}
|
|
744
|
+
function deleteSectionInstance(instanceId, currentPath, existingEntries) {
|
|
745
|
+
return setSectionRemoved(instanceId, currentPath, existingEntries, true);
|
|
746
|
+
}
|
|
747
|
+
function restoreSectionInstance(instanceId, currentPath, existingEntries) {
|
|
748
|
+
return setSectionRemoved(instanceId, currentPath, existingEntries, false);
|
|
749
|
+
}
|
|
750
|
+
function duplicateSectionInstance(instanceId, newId, currentPath, existingEntries) {
|
|
751
|
+
const original = findByInstanceId(instanceId);
|
|
752
|
+
if (!original) return null;
|
|
753
|
+
const clone = original.cloneNode(true);
|
|
754
|
+
clone.setAttribute("data-ohw-instance", newId);
|
|
755
|
+
const keyRekeys = rekeySectionSubtree(clone, newId);
|
|
756
|
+
original.insertAdjacentElement("afterend", clone);
|
|
757
|
+
const byId = new Map(existingEntries.map((e) => [e.instanceId, e]));
|
|
758
|
+
const entries = topLevelSections().map((el, order) => {
|
|
759
|
+
const id = instanceIdOf(el);
|
|
760
|
+
return {
|
|
761
|
+
instanceId: id,
|
|
762
|
+
type: sectionTypeOf(el),
|
|
763
|
+
order,
|
|
764
|
+
pagePath: currentPath,
|
|
765
|
+
...byId.get(id)?.removed ? { removed: true } : {}
|
|
766
|
+
};
|
|
767
|
+
});
|
|
768
|
+
applyPersistedOrder(entries);
|
|
769
|
+
return { entries, keyRekeys };
|
|
770
|
+
}
|
|
771
|
+
function newInstanceId() {
|
|
772
|
+
return typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `instance-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
773
|
+
}
|
|
774
|
+
function getPageSectionOrderEntries(raw, currentPath) {
|
|
775
|
+
if (!raw) return [];
|
|
776
|
+
try {
|
|
777
|
+
const entries = JSON.parse(raw);
|
|
778
|
+
return entries.filter((e) => !e.pagePath || e.pagePath === currentPath);
|
|
779
|
+
} catch {
|
|
780
|
+
return [];
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
function mergePageSectionOrder(raw, currentPath, pageEntries) {
|
|
784
|
+
let all = [];
|
|
785
|
+
if (raw) {
|
|
786
|
+
try {
|
|
787
|
+
const parsed = JSON.parse(raw);
|
|
788
|
+
if (Array.isArray(parsed)) all = parsed;
|
|
789
|
+
} catch {
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
const otherPages = all.filter((e) => e && e.pagePath && e.pagePath !== currentPath);
|
|
793
|
+
const pageIds = new Set(pageEntries.map((e) => e.instanceId));
|
|
794
|
+
const removedHere = all.filter(
|
|
795
|
+
(e) => e && (!e.pagePath || e.pagePath === currentPath) && e.removed && !pageIds.has(e.instanceId)
|
|
796
|
+
);
|
|
797
|
+
return [...otherPages, ...removedHere, ...pageEntries];
|
|
798
|
+
}
|
|
799
|
+
function rekeySectionSubtree(root, instanceId) {
|
|
800
|
+
const suffix = `::${instanceId}`;
|
|
801
|
+
const pairs = [];
|
|
802
|
+
const rekey = (el, attr) => {
|
|
803
|
+
const current = el.getAttribute(attr);
|
|
804
|
+
if (!current) return;
|
|
805
|
+
const base = current.includes("::") ? current.slice(0, current.indexOf("::")) : current;
|
|
806
|
+
const next = `${base}${suffix}`;
|
|
807
|
+
el.setAttribute(attr, next);
|
|
808
|
+
pairs.push({ from: current, to: next });
|
|
809
|
+
};
|
|
810
|
+
if (root.hasAttribute("data-ohw-key")) rekey(root, "data-ohw-key");
|
|
811
|
+
if (root.hasAttribute("data-ohw-href-key")) rekey(root, "data-ohw-href-key");
|
|
812
|
+
root.querySelectorAll("[data-ohw-key]").forEach((el) => rekey(el, "data-ohw-key"));
|
|
813
|
+
root.querySelectorAll("[data-ohw-href-key]").forEach((el) => rekey(el, "data-ohw-href-key"));
|
|
814
|
+
return pairs;
|
|
815
|
+
}
|
|
816
|
+
function initSectionInstancesFromContent(content, currentPath) {
|
|
817
|
+
document.querySelectorAll("[data-ohw-section]:not([data-ohw-instance])").forEach((el) => {
|
|
818
|
+
el.setAttribute("data-ohw-instance", el.getAttribute("data-ohw-section") ?? "");
|
|
819
|
+
});
|
|
820
|
+
document.querySelectorAll("[data-ohw-section-container]:not([data-ohw-instance])").forEach((el) => {
|
|
821
|
+
const type = sectionTypeOf(el);
|
|
822
|
+
if (type) el.setAttribute("data-ohw-instance", type);
|
|
823
|
+
});
|
|
824
|
+
const entries = getPageSectionOrderEntries(content[SECTION_ORDER_KEY], currentPath);
|
|
825
|
+
for (const entry of entries) {
|
|
826
|
+
if (entry.instanceId === entry.type) continue;
|
|
827
|
+
if (document.querySelector(`[data-ohw-instance="${CSS.escape(entry.instanceId)}"]`)) continue;
|
|
828
|
+
const original = document.querySelector(
|
|
829
|
+
`[data-ohw-section="${CSS.escape(entry.type)}"][data-ohw-instance="${CSS.escape(entry.type)}"]`
|
|
830
|
+
);
|
|
831
|
+
if (!original) continue;
|
|
832
|
+
const clone = original.cloneNode(true);
|
|
833
|
+
clone.setAttribute("data-ohw-instance", entry.instanceId);
|
|
834
|
+
rekeySectionSubtree(clone, entry.instanceId);
|
|
835
|
+
original.insertAdjacentElement("afterend", clone);
|
|
836
|
+
}
|
|
837
|
+
applyPersistedOrder(entries);
|
|
838
|
+
}
|
|
839
|
+
|
|
562
840
|
// src/ui/ai-tree/AiTreeRenderer.tsx
|
|
563
841
|
import React from "react";
|
|
564
842
|
import { ArrowLeft, ArrowRight, ChevronDown, icons as lucideIcons } from "lucide-react";
|
|
@@ -1926,7 +2204,7 @@ function AiTreeRenderer({
|
|
|
1926
2204
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
1927
2205
|
var CONTAINER_ATTR = "data-ohw-ai-generated";
|
|
1928
2206
|
var REPLACED_ATTR = "data-ohw-ai-replaced-by";
|
|
1929
|
-
var
|
|
2207
|
+
var REMOVED_ATTR2 = "data-ohw-ai-removed";
|
|
1930
2208
|
var TEMPLATE_HIDDEN_ATTR = "data-ohw-ai-template-hidden";
|
|
1931
2209
|
var CHROME_SECTION_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
|
|
1932
2210
|
function readRootVar(name) {
|
|
@@ -2021,18 +2299,18 @@ function placeContainer(container, entry) {
|
|
|
2021
2299
|
}
|
|
2022
2300
|
function syncRemovedSections(state) {
|
|
2023
2301
|
const removed = new Set(state.removed ?? []);
|
|
2024
|
-
for (const el of document.querySelectorAll(`[${
|
|
2302
|
+
for (const el of document.querySelectorAll(`[${REMOVED_ATTR2}]`)) {
|
|
2025
2303
|
const id = el.getAttribute("data-ohw-section") ?? "";
|
|
2026
2304
|
if (!removed.has(id)) {
|
|
2027
2305
|
el.style.removeProperty("display");
|
|
2028
|
-
el.removeAttribute(
|
|
2306
|
+
el.removeAttribute(REMOVED_ATTR2);
|
|
2029
2307
|
}
|
|
2030
2308
|
}
|
|
2031
2309
|
for (const id of removed) {
|
|
2032
2310
|
const section = findTemplateSection(id);
|
|
2033
2311
|
if (section && !section.hasAttribute(REPLACED_ATTR)) {
|
|
2034
2312
|
section.style.display = "none";
|
|
2035
|
-
section.setAttribute(
|
|
2313
|
+
section.setAttribute(REMOVED_ATTR2, "");
|
|
2036
2314
|
}
|
|
2037
2315
|
}
|
|
2038
2316
|
}
|
|
@@ -2049,7 +2327,7 @@ function syncTemplateHidden(state, pageHasSections) {
|
|
|
2049
2327
|
if (el.hasAttribute(CONTAINER_ATTR)) continue;
|
|
2050
2328
|
if (CHROME_SECTION_IDS.has(el.getAttribute("data-ohw-section") ?? "")) continue;
|
|
2051
2329
|
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
2052
|
-
if (el.hasAttribute(REPLACED_ATTR) || el.hasAttribute(
|
|
2330
|
+
if (el.hasAttribute(REPLACED_ATTR) || el.hasAttribute(REMOVED_ATTR2)) continue;
|
|
2053
2331
|
el.style.display = "none";
|
|
2054
2332
|
el.setAttribute(TEMPLATE_HIDDEN_ATTR, "");
|
|
2055
2333
|
}
|
|
@@ -2073,18 +2351,23 @@ function syncReplacedOriginals(state) {
|
|
|
2073
2351
|
}
|
|
2074
2352
|
}
|
|
2075
2353
|
var sectionOrderIndex = /* @__PURE__ */ new Map();
|
|
2354
|
+
var removedSectionIds = /* @__PURE__ */ new Set();
|
|
2076
2355
|
function setAiSectionOrder(raw, currentPath) {
|
|
2077
2356
|
const next = /* @__PURE__ */ new Map();
|
|
2357
|
+
const removed = /* @__PURE__ */ new Set();
|
|
2078
2358
|
if (raw) {
|
|
2079
2359
|
try {
|
|
2080
2360
|
const entries = JSON.parse(raw);
|
|
2081
2361
|
for (const entry of entries) {
|
|
2082
|
-
if (
|
|
2362
|
+
if (entry.pagePath && entry.pagePath !== currentPath) continue;
|
|
2363
|
+
next.set(entry.instanceId, entry.order);
|
|
2364
|
+
if (entry.removed) removed.add(entry.instanceId);
|
|
2083
2365
|
}
|
|
2084
2366
|
} catch {
|
|
2085
2367
|
}
|
|
2086
2368
|
}
|
|
2087
2369
|
sectionOrderIndex = next;
|
|
2370
|
+
removedSectionIds = removed;
|
|
2088
2371
|
}
|
|
2089
2372
|
function applyExplicitOrder(entries) {
|
|
2090
2373
|
if (sectionOrderIndex.size === 0) return entries;
|
|
@@ -2120,6 +2403,18 @@ function orderByChain(sections) {
|
|
|
2120
2403
|
for (const root of roots) visit(root);
|
|
2121
2404
|
return out.length === sections.length ? out : sections;
|
|
2122
2405
|
}
|
|
2406
|
+
function syncSoftRemovedGenerated() {
|
|
2407
|
+
for (const [id, section] of mounted) {
|
|
2408
|
+
const el = section.container;
|
|
2409
|
+
if (removedSectionIds.has(id)) {
|
|
2410
|
+
el.style.display = "none";
|
|
2411
|
+
el.setAttribute(REMOVED_ATTR, "");
|
|
2412
|
+
} else if (el.hasAttribute(REMOVED_ATTR)) {
|
|
2413
|
+
el.style.removeProperty("display");
|
|
2414
|
+
el.removeAttribute(REMOVED_ATTR);
|
|
2415
|
+
}
|
|
2416
|
+
}
|
|
2417
|
+
}
|
|
2123
2418
|
function applyAiSectionsToDom(state, options) {
|
|
2124
2419
|
if (typeof document === "undefined") return;
|
|
2125
2420
|
const brandOverride = deriveBrandOverride();
|
|
@@ -2187,6 +2482,23 @@ function applyAiSectionsToDom(state, options) {
|
|
|
2187
2482
|
syncReplacedOriginals(state);
|
|
2188
2483
|
syncRemovedSections(state);
|
|
2189
2484
|
syncTemplateHidden(state, pageSections.length > 0);
|
|
2485
|
+
syncSoftRemovedGenerated();
|
|
2486
|
+
}
|
|
2487
|
+
function unmountAllAiSections() {
|
|
2488
|
+
for (const [, section] of mounted) {
|
|
2489
|
+
section.root.unmount();
|
|
2490
|
+
section.container.remove();
|
|
2491
|
+
}
|
|
2492
|
+
mounted.clear();
|
|
2493
|
+
if (typeof document === "undefined") return;
|
|
2494
|
+
for (const el of document.querySelectorAll(`[${REPLACED_ATTR}]`)) {
|
|
2495
|
+
el.style.removeProperty("display");
|
|
2496
|
+
el.removeAttribute(REPLACED_ATTR);
|
|
2497
|
+
}
|
|
2498
|
+
for (const el of document.querySelectorAll(`[${REMOVED_ATTR2}]`)) {
|
|
2499
|
+
el.style.removeProperty("display");
|
|
2500
|
+
el.removeAttribute(REMOVED_ATTR2);
|
|
2501
|
+
}
|
|
2190
2502
|
}
|
|
2191
2503
|
|
|
2192
2504
|
// src/useLinkHrefGuardian.ts
|
|
@@ -8146,240 +8458,6 @@ function CarouselOverlay({
|
|
|
8146
8458
|
// src/ui/ai-section/AiSectionOverlay.tsx
|
|
8147
8459
|
import { useCallback as useCallback2, useEffect as useEffect4, useRef as useRef4, useState as useState5 } from "react";
|
|
8148
8460
|
import { Check, X } from "lucide-react";
|
|
8149
|
-
|
|
8150
|
-
// src/lib/sections.ts
|
|
8151
|
-
var LINK_PICKER_EXCLUDED_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
|
|
8152
|
-
function isChromeSection(el) {
|
|
8153
|
-
return el.matches("header, nav, footer, aside");
|
|
8154
|
-
}
|
|
8155
|
-
function titleCaseSectionId(id) {
|
|
8156
|
-
return id.split("-").filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
8157
|
-
}
|
|
8158
|
-
function parseSectionsFromRoot(root) {
|
|
8159
|
-
const seen = /* @__PURE__ */ new Set();
|
|
8160
|
-
const sections = [];
|
|
8161
|
-
for (const el of root.querySelectorAll("[data-ohw-section]")) {
|
|
8162
|
-
const id = el.getAttribute("data-ohw-section") ?? "";
|
|
8163
|
-
if (!id || seen.has(id) || LINK_PICKER_EXCLUDED_IDS.has(id)) continue;
|
|
8164
|
-
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
8165
|
-
if (el.hasAttribute("data-ohw-ai-template-hidden") || el.hasAttribute("data-ohw-ai-removed") || el.hasAttribute("data-ohw-ai-replaced-by"))
|
|
8166
|
-
continue;
|
|
8167
|
-
seen.add(id);
|
|
8168
|
-
const label = el.getAttribute("data-ohw-section-label") ?? titleCaseSectionId(id);
|
|
8169
|
-
sections.push({ id, label });
|
|
8170
|
-
}
|
|
8171
|
-
return sections;
|
|
8172
|
-
}
|
|
8173
|
-
function collectSectionsFromDom() {
|
|
8174
|
-
if (typeof document === "undefined") return [];
|
|
8175
|
-
return parseSectionsFromRoot(document);
|
|
8176
|
-
}
|
|
8177
|
-
function parseSectionsFromHtml(html) {
|
|
8178
|
-
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
8179
|
-
return parseSectionsFromRoot(doc);
|
|
8180
|
-
}
|
|
8181
|
-
|
|
8182
|
-
// src/lib/section-instances.ts
|
|
8183
|
-
var SECTION_ORDER_KEY = "__ohw_section_order";
|
|
8184
|
-
var REMOVED_ATTR2 = "data-ohw-section-removed";
|
|
8185
|
-
function isRemovedSection(el) {
|
|
8186
|
-
return el.hasAttribute(REMOVED_ATTR2);
|
|
8187
|
-
}
|
|
8188
|
-
function movableUnit(el) {
|
|
8189
|
-
return el.closest("[data-ohw-section-container]") ?? el;
|
|
8190
|
-
}
|
|
8191
|
-
function sectionTypeOf(el) {
|
|
8192
|
-
return el.getAttribute("data-ohw-section") ?? el.querySelector("[data-ohw-section]")?.getAttribute("data-ohw-section") ?? "";
|
|
8193
|
-
}
|
|
8194
|
-
function sectionElementOf(el) {
|
|
8195
|
-
return el.hasAttribute("data-ohw-section") ? el : el.querySelector("[data-ohw-section]") ?? el;
|
|
8196
|
-
}
|
|
8197
|
-
function collectTopLevelUnits(predicate) {
|
|
8198
|
-
const seen = /* @__PURE__ */ new Set();
|
|
8199
|
-
const result = [];
|
|
8200
|
-
document.querySelectorAll("[data-ohw-section]").forEach((el) => {
|
|
8201
|
-
if (!predicate(el)) return;
|
|
8202
|
-
const unit = movableUnit(el);
|
|
8203
|
-
if (unit.parentElement?.closest("[data-ohw-section],[data-ohw-section-container]")) return;
|
|
8204
|
-
if (seen.has(unit)) return;
|
|
8205
|
-
seen.add(unit);
|
|
8206
|
-
result.push(unit);
|
|
8207
|
-
});
|
|
8208
|
-
return result;
|
|
8209
|
-
}
|
|
8210
|
-
function topLevelSections() {
|
|
8211
|
-
return collectTopLevelUnits((el) => !isChromeSection(el) && !isRemovedSection(movableUnit(el)));
|
|
8212
|
-
}
|
|
8213
|
-
function instanceIdOf(el) {
|
|
8214
|
-
return el.dataset.ohwInstance ?? el.dataset.ohwSection ?? "";
|
|
8215
|
-
}
|
|
8216
|
-
function findByInstanceId(instanceId) {
|
|
8217
|
-
const escapedId = CSS.escape(instanceId);
|
|
8218
|
-
const direct = document.querySelector(`[data-ohw-instance="${escapedId}"]`);
|
|
8219
|
-
if (direct) return movableUnit(direct);
|
|
8220
|
-
const bare = document.querySelector(`[data-ohw-section="${escapedId}"]:not([data-ohw-instance])`);
|
|
8221
|
-
return bare ? movableUnit(bare) : null;
|
|
8222
|
-
}
|
|
8223
|
-
function planSectionMove(instanceId, targetIndex, currentPath) {
|
|
8224
|
-
const sections = topLevelSections();
|
|
8225
|
-
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
8226
|
-
if (index === -1) return null;
|
|
8227
|
-
const dragged = sections[index];
|
|
8228
|
-
const others = sections.filter((_, i) => i !== index);
|
|
8229
|
-
const clamped = Math.max(0, Math.min(targetIndex, others.length));
|
|
8230
|
-
const reordered = [...others.slice(0, clamped), dragged, ...others.slice(clamped)];
|
|
8231
|
-
return reordered.map((el, order) => ({
|
|
8232
|
-
instanceId: instanceIdOf(el),
|
|
8233
|
-
type: sectionTypeOf(el),
|
|
8234
|
-
order,
|
|
8235
|
-
pagePath: currentPath
|
|
8236
|
-
}));
|
|
8237
|
-
}
|
|
8238
|
-
function moveSectionInstance(instanceId, direction, currentPath) {
|
|
8239
|
-
const sections = topLevelSections();
|
|
8240
|
-
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
8241
|
-
if (index === -1) return null;
|
|
8242
|
-
const siblingIndex = direction === "up" ? index - 1 : index + 1;
|
|
8243
|
-
if (siblingIndex < 0 || siblingIndex >= sections.length) return null;
|
|
8244
|
-
const entries = planSectionMove(instanceId, siblingIndex, currentPath);
|
|
8245
|
-
if (!entries) return null;
|
|
8246
|
-
applyPersistedOrder(entries);
|
|
8247
|
-
return entries;
|
|
8248
|
-
}
|
|
8249
|
-
function syncRemovedFlags(entries) {
|
|
8250
|
-
const removedIds = new Set(entries.filter((e) => e.removed).map((e) => e.instanceId));
|
|
8251
|
-
document.querySelectorAll(`[${REMOVED_ATTR2}]`).forEach((el) => {
|
|
8252
|
-
if (!removedIds.has(instanceIdOf(el))) {
|
|
8253
|
-
el.style.removeProperty("display");
|
|
8254
|
-
el.removeAttribute(REMOVED_ATTR2);
|
|
8255
|
-
}
|
|
8256
|
-
});
|
|
8257
|
-
for (const id of removedIds) {
|
|
8258
|
-
const el = findByInstanceId(id);
|
|
8259
|
-
if (el) {
|
|
8260
|
-
el.style.display = "none";
|
|
8261
|
-
el.setAttribute(REMOVED_ATTR2, "");
|
|
8262
|
-
}
|
|
8263
|
-
}
|
|
8264
|
-
}
|
|
8265
|
-
function applyPersistedOrder(entries) {
|
|
8266
|
-
syncRemovedFlags(entries);
|
|
8267
|
-
if (entries.length === 0) return;
|
|
8268
|
-
const sections = topLevelSections();
|
|
8269
|
-
if (sections.length === 0) return;
|
|
8270
|
-
const orderIndex = new Map(entries.map((e) => [e.instanceId, e.order]));
|
|
8271
|
-
const ordered = [...sections].sort((a, b) => {
|
|
8272
|
-
const aOrder = orderIndex.get(instanceIdOf(a));
|
|
8273
|
-
const bOrder = orderIndex.get(instanceIdOf(b));
|
|
8274
|
-
if (aOrder === void 0 && bOrder === void 0) return 0;
|
|
8275
|
-
if (aOrder === void 0) return 1;
|
|
8276
|
-
if (bOrder === void 0) return -1;
|
|
8277
|
-
return aOrder - bOrder;
|
|
8278
|
-
});
|
|
8279
|
-
let prev = null;
|
|
8280
|
-
for (const el of ordered) {
|
|
8281
|
-
if (prev) prev.after(el);
|
|
8282
|
-
prev = el;
|
|
8283
|
-
}
|
|
8284
|
-
}
|
|
8285
|
-
function setSectionRemoved(instanceId, currentPath, existingEntries, removed) {
|
|
8286
|
-
if (!findByInstanceId(instanceId)) return null;
|
|
8287
|
-
const byId = new Map(existingEntries.map((e) => [e.instanceId, e]));
|
|
8288
|
-
const allSections = collectTopLevelUnits((el) => !isChromeSection(el));
|
|
8289
|
-
allSections.forEach((el, order) => {
|
|
8290
|
-
const id = instanceIdOf(el);
|
|
8291
|
-
if (!byId.has(id)) {
|
|
8292
|
-
byId.set(id, { instanceId: id, type: sectionTypeOf(el), order, pagePath: currentPath });
|
|
8293
|
-
}
|
|
8294
|
-
});
|
|
8295
|
-
const target = byId.get(instanceId);
|
|
8296
|
-
if (!target) return null;
|
|
8297
|
-
byId.set(instanceId, { ...target, removed });
|
|
8298
|
-
const entries = Array.from(byId.values());
|
|
8299
|
-
applyPersistedOrder(entries);
|
|
8300
|
-
return entries;
|
|
8301
|
-
}
|
|
8302
|
-
function deleteSectionInstance(instanceId, currentPath, existingEntries) {
|
|
8303
|
-
return setSectionRemoved(instanceId, currentPath, existingEntries, true);
|
|
8304
|
-
}
|
|
8305
|
-
function restoreSectionInstance(instanceId, currentPath, existingEntries) {
|
|
8306
|
-
return setSectionRemoved(instanceId, currentPath, existingEntries, false);
|
|
8307
|
-
}
|
|
8308
|
-
function duplicateSectionInstance(instanceId, newId, currentPath, existingEntries) {
|
|
8309
|
-
const original = findByInstanceId(instanceId);
|
|
8310
|
-
if (!original) return null;
|
|
8311
|
-
const clone = original.cloneNode(true);
|
|
8312
|
-
clone.setAttribute("data-ohw-instance", newId);
|
|
8313
|
-
const keyRekeys = rekeySectionSubtree(clone, newId);
|
|
8314
|
-
original.insertAdjacentElement("afterend", clone);
|
|
8315
|
-
const byId = new Map(existingEntries.map((e) => [e.instanceId, e]));
|
|
8316
|
-
const entries = topLevelSections().map((el, order) => {
|
|
8317
|
-
const id = instanceIdOf(el);
|
|
8318
|
-
return {
|
|
8319
|
-
instanceId: id,
|
|
8320
|
-
type: sectionTypeOf(el),
|
|
8321
|
-
order,
|
|
8322
|
-
pagePath: currentPath,
|
|
8323
|
-
...byId.get(id)?.removed ? { removed: true } : {}
|
|
8324
|
-
};
|
|
8325
|
-
});
|
|
8326
|
-
applyPersistedOrder(entries);
|
|
8327
|
-
return { entries, keyRekeys };
|
|
8328
|
-
}
|
|
8329
|
-
function newInstanceId() {
|
|
8330
|
-
return typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `instance-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
8331
|
-
}
|
|
8332
|
-
function getPageSectionOrderEntries(raw, currentPath) {
|
|
8333
|
-
if (!raw) return [];
|
|
8334
|
-
try {
|
|
8335
|
-
const entries = JSON.parse(raw);
|
|
8336
|
-
return entries.filter((e) => !e.pagePath || e.pagePath === currentPath);
|
|
8337
|
-
} catch {
|
|
8338
|
-
return [];
|
|
8339
|
-
}
|
|
8340
|
-
}
|
|
8341
|
-
function rekeySectionSubtree(root, instanceId) {
|
|
8342
|
-
const suffix = `::${instanceId}`;
|
|
8343
|
-
const pairs = [];
|
|
8344
|
-
const rekey = (el, attr) => {
|
|
8345
|
-
const current = el.getAttribute(attr);
|
|
8346
|
-
if (!current) return;
|
|
8347
|
-
const base = current.includes("::") ? current.slice(0, current.indexOf("::")) : current;
|
|
8348
|
-
const next = `${base}${suffix}`;
|
|
8349
|
-
el.setAttribute(attr, next);
|
|
8350
|
-
pairs.push({ from: current, to: next });
|
|
8351
|
-
};
|
|
8352
|
-
if (root.hasAttribute("data-ohw-key")) rekey(root, "data-ohw-key");
|
|
8353
|
-
if (root.hasAttribute("data-ohw-href-key")) rekey(root, "data-ohw-href-key");
|
|
8354
|
-
root.querySelectorAll("[data-ohw-key]").forEach((el) => rekey(el, "data-ohw-key"));
|
|
8355
|
-
root.querySelectorAll("[data-ohw-href-key]").forEach((el) => rekey(el, "data-ohw-href-key"));
|
|
8356
|
-
return pairs;
|
|
8357
|
-
}
|
|
8358
|
-
function initSectionInstancesFromContent(content, currentPath) {
|
|
8359
|
-
document.querySelectorAll("[data-ohw-section]:not([data-ohw-instance])").forEach((el) => {
|
|
8360
|
-
el.setAttribute("data-ohw-instance", el.getAttribute("data-ohw-section") ?? "");
|
|
8361
|
-
});
|
|
8362
|
-
document.querySelectorAll("[data-ohw-section-container]:not([data-ohw-instance])").forEach((el) => {
|
|
8363
|
-
const type = sectionTypeOf(el);
|
|
8364
|
-
if (type) el.setAttribute("data-ohw-instance", type);
|
|
8365
|
-
});
|
|
8366
|
-
const entries = getPageSectionOrderEntries(content[SECTION_ORDER_KEY], currentPath);
|
|
8367
|
-
for (const entry of entries) {
|
|
8368
|
-
if (entry.instanceId === entry.type) continue;
|
|
8369
|
-
if (document.querySelector(`[data-ohw-instance="${CSS.escape(entry.instanceId)}"]`)) continue;
|
|
8370
|
-
const original = document.querySelector(
|
|
8371
|
-
`[data-ohw-section="${CSS.escape(entry.type)}"][data-ohw-instance="${CSS.escape(entry.type)}"]`
|
|
8372
|
-
);
|
|
8373
|
-
if (!original) continue;
|
|
8374
|
-
const clone = original.cloneNode(true);
|
|
8375
|
-
clone.setAttribute("data-ohw-instance", entry.instanceId);
|
|
8376
|
-
rekeySectionSubtree(clone, entry.instanceId);
|
|
8377
|
-
original.insertAdjacentElement("afterend", clone);
|
|
8378
|
-
}
|
|
8379
|
-
applyPersistedOrder(entries);
|
|
8380
|
-
}
|
|
8381
|
-
|
|
8382
|
-
// src/ui/ai-section/AiSectionOverlay.tsx
|
|
8383
8461
|
import { Fragment as Fragment5, jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
8384
8462
|
var findSectionElement = findByInstanceId;
|
|
8385
8463
|
function readRect(instanceId) {
|
|
@@ -14168,15 +14246,17 @@ function useSectionDrag({
|
|
|
14168
14246
|
clearSectionDragVisuals();
|
|
14169
14247
|
return;
|
|
14170
14248
|
}
|
|
14171
|
-
const orderJson = JSON.stringify(
|
|
14249
|
+
const orderJson = JSON.stringify(
|
|
14250
|
+
mergePageSectionOrder(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname, entries)
|
|
14251
|
+
);
|
|
14172
14252
|
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
14173
14253
|
setAiSectionOrder(orderJson, window.location.pathname);
|
|
14174
14254
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
14175
|
-
applyPersistedOrder(
|
|
14255
|
+
applyPersistedOrder(getPageSectionOrderEntries(orderJson, window.location.pathname));
|
|
14176
14256
|
clearSectionDragVisuals();
|
|
14177
14257
|
requestAnimationFrame(() => {
|
|
14178
14258
|
if (editContentRef.current[SECTION_ORDER_KEY] === orderJson) {
|
|
14179
|
-
applyPersistedOrder(
|
|
14259
|
+
applyPersistedOrder(getPageSectionOrderEntries(orderJson, window.location.pathname));
|
|
14180
14260
|
}
|
|
14181
14261
|
requestAnimationFrame(() => {
|
|
14182
14262
|
window.dispatchEvent(new Event("resize"));
|
|
@@ -18360,6 +18440,22 @@ function OhhwellsBridge() {
|
|
|
18360
18440
|
useEffect13(() => {
|
|
18361
18441
|
postToParent2({ type: "ow:navigation", path: pathname });
|
|
18362
18442
|
}, [pathname, postToParent2]);
|
|
18443
|
+
useEffect13(() => {
|
|
18444
|
+
if (!subdomain || isEditMode) return;
|
|
18445
|
+
const content = contentCache.get(subdomain);
|
|
18446
|
+
if (!content) return;
|
|
18447
|
+
unmountAllAiSections();
|
|
18448
|
+
initSectionsFromContent(
|
|
18449
|
+
content,
|
|
18450
|
+
/*removeExisting*/
|
|
18451
|
+
true,
|
|
18452
|
+
pathname
|
|
18453
|
+
);
|
|
18454
|
+
if (typeof content[AI_SECTIONS_KEY] === "string") {
|
|
18455
|
+
setAiSectionOrder(content[SECTION_ORDER_KEY], pathname);
|
|
18456
|
+
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
18457
|
+
}
|
|
18458
|
+
}, [pathname, subdomain, isEditMode]);
|
|
18363
18459
|
useEffect13(() => {
|
|
18364
18460
|
if (!isEditMode) return;
|
|
18365
18461
|
if (linkPopoverSessionRef.current?.intent === "add-nav") return;
|
|
@@ -20185,6 +20281,44 @@ function OhhwellsBridge() {
|
|
|
20185
20281
|
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
20186
20282
|
}, 400));
|
|
20187
20283
|
};
|
|
20284
|
+
const reapCommittedAiSections = (excludeIds) => {
|
|
20285
|
+
const aiState = parseAiSectionsState(aiSectionsRef.current);
|
|
20286
|
+
if (aiState.sections.length === 0) return [];
|
|
20287
|
+
let orderEntries = [];
|
|
20288
|
+
try {
|
|
20289
|
+
const parsed = JSON.parse(editContentRef.current[SECTION_ORDER_KEY] ?? "[]");
|
|
20290
|
+
if (Array.isArray(parsed)) orderEntries = parsed;
|
|
20291
|
+
} catch {
|
|
20292
|
+
return [];
|
|
20293
|
+
}
|
|
20294
|
+
const removedIds = orderEntries.filter((entry) => entry && typeof entry.instanceId === "string" && entry.removed).map((entry) => entry.instanceId);
|
|
20295
|
+
if (removedIds.length === 0) return [];
|
|
20296
|
+
const result = reapRemovedAiSections(aiState, parseStyleStore(stylesRef.current), removedIds, excludeIds);
|
|
20297
|
+
if (!result.changed) return [];
|
|
20298
|
+
const nodes = [];
|
|
20299
|
+
aiSectionsRef.current = serializeAiSectionsState(result.state);
|
|
20300
|
+
nodes.push({ key: AI_SECTIONS_KEY, text: aiSectionsRef.current });
|
|
20301
|
+
const reaped = new Set(result.reapedIds);
|
|
20302
|
+
const nextOrderJson = JSON.stringify(orderEntries.filter((entry) => !reaped.has(entry.instanceId)));
|
|
20303
|
+
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: nextOrderJson };
|
|
20304
|
+
setAiSectionOrder(nextOrderJson, window.location.pathname);
|
|
20305
|
+
nodes.push({ key: SECTION_ORDER_KEY, text: nextOrderJson });
|
|
20306
|
+
if (result.store) {
|
|
20307
|
+
stylesRef.current = JSON.stringify(result.store);
|
|
20308
|
+
nodes.push({ key: STYLE_STORE_KEY, text: stylesRef.current });
|
|
20309
|
+
}
|
|
20310
|
+
const nextContent = { ...editContentRef.current };
|
|
20311
|
+
for (const key of Object.keys(nextContent)) {
|
|
20312
|
+
if (key.startsWith(AI_SLOT_KEY_PREFIX) && result.slotPrefixes.some((prefix) => key.startsWith(prefix)) && nextContent[key] !== "") {
|
|
20313
|
+
nextContent[key] = "";
|
|
20314
|
+
nodes.push({ key, text: "" });
|
|
20315
|
+
}
|
|
20316
|
+
}
|
|
20317
|
+
editContentRef.current = nextContent;
|
|
20318
|
+
applyAiSectionsToDom(result.state);
|
|
20319
|
+
applyStylesToDom(parseStyleStore(stylesRef.current));
|
|
20320
|
+
return nodes;
|
|
20321
|
+
};
|
|
20188
20322
|
const handleHydrate = (e) => {
|
|
20189
20323
|
if (e.data?.type !== "ow:hydrate") return;
|
|
20190
20324
|
const content = e.data.content;
|
|
@@ -20253,6 +20387,11 @@ function OhhwellsBridge() {
|
|
|
20253
20387
|
reconcileFooterOrderFromContent(editContentRef.current);
|
|
20254
20388
|
syncNavigationDragCursorAttrs();
|
|
20255
20389
|
enforceLinkHrefs();
|
|
20390
|
+
const hydrateReapExclude = /* @__PURE__ */ new Set();
|
|
20391
|
+
const hydratePendingUndo = pendingDeleteUndoRef.current;
|
|
20392
|
+
if (hydratePendingUndo?.sectionInstanceId) hydrateReapExclude.add(hydratePendingUndo.sectionInstanceId);
|
|
20393
|
+
const reapNodes = reapCommittedAiSections(hydrateReapExclude);
|
|
20394
|
+
if (reapNodes.length > 0) postToParentRef.current({ type: "ow:change", nodes: reapNodes });
|
|
20256
20395
|
const hydratedHeight = document.body.scrollHeight;
|
|
20257
20396
|
if (hydratedHeight > 50) postToParentRef.current({ type: "ow:height", height: hydratedHeight });
|
|
20258
20397
|
postToParentRef.current({ type: "ow:hydrate-done" });
|
|
@@ -20437,8 +20576,11 @@ function OhhwellsBridge() {
|
|
|
20437
20576
|
if (!instanceId || !direction) return;
|
|
20438
20577
|
const entries = moveSectionInstance(instanceId, direction, window.location.pathname);
|
|
20439
20578
|
if (!entries) return;
|
|
20440
|
-
const orderJson = JSON.stringify(
|
|
20579
|
+
const orderJson = JSON.stringify(
|
|
20580
|
+
mergePageSectionOrder(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname, entries)
|
|
20581
|
+
);
|
|
20441
20582
|
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
20583
|
+
applyPersistedOrder(getPageSectionOrderEntries(orderJson, window.location.pathname));
|
|
20442
20584
|
setAiSectionOrder(orderJson, window.location.pathname);
|
|
20443
20585
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
20444
20586
|
window.dispatchEvent(new Event("resize"));
|
|
@@ -20484,8 +20626,11 @@ function OhhwellsBridge() {
|
|
|
20484
20626
|
const currentEntries = getPageSectionOrderEntries(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname);
|
|
20485
20627
|
const entries = deleteSectionInstance(instanceId, window.location.pathname, currentEntries);
|
|
20486
20628
|
if (!entries) return;
|
|
20487
|
-
const orderJson = JSON.stringify(
|
|
20629
|
+
const orderJson = JSON.stringify(
|
|
20630
|
+
mergePageSectionOrder(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname, entries)
|
|
20631
|
+
);
|
|
20488
20632
|
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
20633
|
+
setAiSectionOrder(orderJson, window.location.pathname);
|
|
20489
20634
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
20490
20635
|
aiSectionApiRef.current?.clear();
|
|
20491
20636
|
window.dispatchEvent(new Event("resize"));
|
|
@@ -20494,6 +20639,7 @@ function OhhwellsBridge() {
|
|
|
20494
20639
|
const actionId = newInstanceId();
|
|
20495
20640
|
pendingDeleteUndoRef.current = {
|
|
20496
20641
|
actionId,
|
|
20642
|
+
sectionInstanceId: instanceId,
|
|
20497
20643
|
restore: () => {
|
|
20498
20644
|
const restoredEntries = getPageSectionOrderEntries(
|
|
20499
20645
|
editContentRef.current[SECTION_ORDER_KEY],
|
|
@@ -20501,8 +20647,11 @@ function OhhwellsBridge() {
|
|
|
20501
20647
|
);
|
|
20502
20648
|
const restored = restoreSectionInstance(instanceId, window.location.pathname, restoredEntries);
|
|
20503
20649
|
if (!restored) return;
|
|
20504
|
-
const restoredJson = JSON.stringify(
|
|
20650
|
+
const restoredJson = JSON.stringify(
|
|
20651
|
+
mergePageSectionOrder(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname, restored)
|
|
20652
|
+
);
|
|
20505
20653
|
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: restoredJson };
|
|
20654
|
+
setAiSectionOrder(restoredJson, window.location.pathname);
|
|
20506
20655
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: restoredJson }] });
|
|
20507
20656
|
window.dispatchEvent(new Event("resize"));
|
|
20508
20657
|
const restoreHeight = document.body.scrollHeight;
|
|
@@ -20528,7 +20677,9 @@ function OhhwellsBridge() {
|
|
|
20528
20677
|
const result = duplicateSectionInstance(instanceId, newId, window.location.pathname, currentEntries);
|
|
20529
20678
|
if (!result) return;
|
|
20530
20679
|
const { entries, keyRekeys } = result;
|
|
20531
|
-
const orderJson = JSON.stringify(
|
|
20680
|
+
const orderJson = JSON.stringify(
|
|
20681
|
+
mergePageSectionOrder(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname, entries)
|
|
20682
|
+
);
|
|
20532
20683
|
const nodes = [{ key: SECTION_ORDER_KEY, text: orderJson }];
|
|
20533
20684
|
for (const { from, to } of keyRekeys) {
|
|
20534
20685
|
const inherited = editContentRef.current[from];
|
|
@@ -20538,6 +20689,7 @@ function OhhwellsBridge() {
|
|
|
20538
20689
|
...editContentRef.current,
|
|
20539
20690
|
...Object.fromEntries(nodes.map(({ key, text }) => [key, text]))
|
|
20540
20691
|
};
|
|
20692
|
+
applyPersistedOrder(getPageSectionOrderEntries(orderJson, window.location.pathname));
|
|
20541
20693
|
setAiSectionOrder(orderJson, window.location.pathname);
|
|
20542
20694
|
postToParentRef.current({ type: "ow:change", nodes });
|
|
20543
20695
|
window.dispatchEvent(new Event("resize"));
|
|
@@ -20801,6 +20953,10 @@ function OhhwellsBridge() {
|
|
|
20801
20953
|
};
|
|
20802
20954
|
const handleSave = (e) => {
|
|
20803
20955
|
if (e.data?.type !== "ow:save") return;
|
|
20956
|
+
const pendingUndo = pendingDeleteUndoRef.current;
|
|
20957
|
+
const reapExclude = /* @__PURE__ */ new Set();
|
|
20958
|
+
if (pendingUndo?.sectionInstanceId) reapExclude.add(pendingUndo.sectionInstanceId);
|
|
20959
|
+
const reapNodes = reapCommittedAiSections(reapExclude);
|
|
20804
20960
|
const nodes = collectEditableNodes(editContentRef.current);
|
|
20805
20961
|
const tracker = document.querySelector("[data-ohw-sections-tracker]");
|
|
20806
20962
|
if (tracker?.textContent) nodes.push({ key: "__ohw_sections", type: "sections", text: tracker.textContent });
|
|
@@ -20820,6 +20976,11 @@ function OhhwellsBridge() {
|
|
|
20820
20976
|
const text = specs.length ? JSON.stringify(specs) : editContentRef.current[fieldsKey(formKey)];
|
|
20821
20977
|
if (text) nodes.push({ key: fieldsKey(formKey), type: "text", text });
|
|
20822
20978
|
});
|
|
20979
|
+
for (const reapNode of reapNodes) {
|
|
20980
|
+
if (reapNode.key.startsWith(AI_SLOT_KEY_PREFIX) && !nodes.some((n) => n.key === reapNode.key)) {
|
|
20981
|
+
nodes.push({ key: reapNode.key, type: "text", text: reapNode.text });
|
|
20982
|
+
}
|
|
20983
|
+
}
|
|
20823
20984
|
postToParentRef.current({ type: "ow:save-result", nodes });
|
|
20824
20985
|
};
|
|
20825
20986
|
const handleInsertSection = (e) => {
|
|
@@ -21441,7 +21602,7 @@ function OhhwellsBridge() {
|
|
|
21441
21602
|
postToParent2({
|
|
21442
21603
|
type: "ow:ready",
|
|
21443
21604
|
version: "1",
|
|
21444
|
-
bridgeVersion: "0.1.
|
|
21605
|
+
bridgeVersion: "0.1.94",
|
|
21445
21606
|
path: pathname,
|
|
21446
21607
|
nodes: collectEditableNodes(editContentRef.current),
|
|
21447
21608
|
sections
|