@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.cjs
CHANGED
|
@@ -143,6 +143,9 @@ function isRenderableTree(value) {
|
|
|
143
143
|
// src/lib/ai-sections-store.ts
|
|
144
144
|
var AI_SECTIONS_KEY = "__ohw_ai_sections";
|
|
145
145
|
var AI_SLOT_KEY_PREFIX = "ai.";
|
|
146
|
+
function aiSlotKeyPrefixFor(sectionId) {
|
|
147
|
+
return `${AI_SLOT_KEY_PREFIX}${sectionId}.`;
|
|
148
|
+
}
|
|
146
149
|
var EMPTY_AI_SECTIONS = { v: 1, sections: [] };
|
|
147
150
|
function parseAiSectionsState(raw) {
|
|
148
151
|
if (!raw) return EMPTY_AI_SECTIONS;
|
|
@@ -254,6 +257,33 @@ function deleteSectionFromState(state, sectionId) {
|
|
|
254
257
|
if (removed.includes(sectionId)) return state;
|
|
255
258
|
return { ...state, v: 1, sections: state.sections, removed: [...removed, sectionId] };
|
|
256
259
|
}
|
|
260
|
+
function reapRemovedAiSections(state, store, removedIds, excludeIds = /* @__PURE__ */ new Set()) {
|
|
261
|
+
const generated = new Set(state.sections.map((entry) => entry.id));
|
|
262
|
+
const reapedIds = [...new Set(removedIds)].filter((id) => generated.has(id) && !excludeIds.has(id));
|
|
263
|
+
if (reapedIds.length === 0) {
|
|
264
|
+
return { state, store, reapedIds: [], slotPrefixes: [], changed: false };
|
|
265
|
+
}
|
|
266
|
+
const reaped = new Set(reapedIds);
|
|
267
|
+
const slotPrefixes = reapedIds.map(aiSlotKeyPrefixFor);
|
|
268
|
+
const nextState = {
|
|
269
|
+
...state,
|
|
270
|
+
v: 1,
|
|
271
|
+
sections: state.sections.filter((entry) => !reaped.has(entry.id))
|
|
272
|
+
};
|
|
273
|
+
let nextStore = store;
|
|
274
|
+
if (store) {
|
|
275
|
+
const sections = {};
|
|
276
|
+
for (const [key, override] of Object.entries(store.sections)) {
|
|
277
|
+
if (!reaped.has(key)) sections[key] = override;
|
|
278
|
+
}
|
|
279
|
+
const nodes = {};
|
|
280
|
+
for (const [key, override] of Object.entries(store.nodes)) {
|
|
281
|
+
if (!slotPrefixes.some((prefix) => key.startsWith(prefix))) nodes[key] = override;
|
|
282
|
+
}
|
|
283
|
+
nextStore = { v: 1, sections, nodes };
|
|
284
|
+
}
|
|
285
|
+
return { state: nextState, store: nextStore, reapedIds, slotPrefixes, changed: true };
|
|
286
|
+
}
|
|
257
287
|
|
|
258
288
|
// src/lib/brand-chrome.ts
|
|
259
289
|
var BRAND_NAME_KEY = "__ohw_brand_name";
|
|
@@ -632,6 +662,254 @@ function applyStylesToDom(store) {
|
|
|
632
662
|
var import_react_dom = require("react-dom");
|
|
633
663
|
var import_client = require("react-dom/client");
|
|
634
664
|
|
|
665
|
+
// src/lib/sections.ts
|
|
666
|
+
var LINK_PICKER_EXCLUDED_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
|
|
667
|
+
function isChromeSection(el) {
|
|
668
|
+
return el.matches("header, nav, footer, aside");
|
|
669
|
+
}
|
|
670
|
+
function titleCaseSectionId(id) {
|
|
671
|
+
return id.split("-").filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
672
|
+
}
|
|
673
|
+
function parseSectionsFromRoot(root) {
|
|
674
|
+
const seen = /* @__PURE__ */ new Set();
|
|
675
|
+
const sections = [];
|
|
676
|
+
for (const el of root.querySelectorAll("[data-ohw-section]")) {
|
|
677
|
+
const id = el.getAttribute("data-ohw-section") ?? "";
|
|
678
|
+
if (!id || seen.has(id) || LINK_PICKER_EXCLUDED_IDS.has(id)) continue;
|
|
679
|
+
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
680
|
+
if (el.hasAttribute("data-ohw-ai-template-hidden") || el.hasAttribute("data-ohw-ai-removed") || el.hasAttribute("data-ohw-ai-replaced-by"))
|
|
681
|
+
continue;
|
|
682
|
+
seen.add(id);
|
|
683
|
+
const label = el.getAttribute("data-ohw-section-label") ?? titleCaseSectionId(id);
|
|
684
|
+
sections.push({ id, label });
|
|
685
|
+
}
|
|
686
|
+
return sections;
|
|
687
|
+
}
|
|
688
|
+
function collectSectionsFromDom() {
|
|
689
|
+
if (typeof document === "undefined") return [];
|
|
690
|
+
return parseSectionsFromRoot(document);
|
|
691
|
+
}
|
|
692
|
+
function parseSectionsFromHtml(html) {
|
|
693
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
694
|
+
return parseSectionsFromRoot(doc);
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
// src/lib/section-instances.ts
|
|
698
|
+
var SECTION_ORDER_KEY = "__ohw_section_order";
|
|
699
|
+
var REMOVED_ATTR = "data-ohw-section-removed";
|
|
700
|
+
function isRemovedSection(el) {
|
|
701
|
+
return el.hasAttribute(REMOVED_ATTR);
|
|
702
|
+
}
|
|
703
|
+
function movableUnit(el) {
|
|
704
|
+
return el.closest("[data-ohw-section-container]") ?? el;
|
|
705
|
+
}
|
|
706
|
+
function sectionTypeOf(el) {
|
|
707
|
+
return el.getAttribute("data-ohw-section") ?? el.querySelector("[data-ohw-section]")?.getAttribute("data-ohw-section") ?? "";
|
|
708
|
+
}
|
|
709
|
+
function sectionElementOf(el) {
|
|
710
|
+
return el.hasAttribute("data-ohw-section") ? el : el.querySelector("[data-ohw-section]") ?? el;
|
|
711
|
+
}
|
|
712
|
+
function collectTopLevelUnits(predicate) {
|
|
713
|
+
const seen = /* @__PURE__ */ new Set();
|
|
714
|
+
const result = [];
|
|
715
|
+
document.querySelectorAll("[data-ohw-section]").forEach((el) => {
|
|
716
|
+
if (!predicate(el)) return;
|
|
717
|
+
const unit = movableUnit(el);
|
|
718
|
+
if (unit.parentElement?.closest("[data-ohw-section],[data-ohw-section-container]")) return;
|
|
719
|
+
if (seen.has(unit)) return;
|
|
720
|
+
seen.add(unit);
|
|
721
|
+
result.push(unit);
|
|
722
|
+
});
|
|
723
|
+
return result;
|
|
724
|
+
}
|
|
725
|
+
function topLevelSections() {
|
|
726
|
+
return collectTopLevelUnits((el) => !isChromeSection(el) && !isRemovedSection(movableUnit(el)));
|
|
727
|
+
}
|
|
728
|
+
function instanceIdOf(el) {
|
|
729
|
+
return el.dataset.ohwInstance ?? el.dataset.ohwSection ?? "";
|
|
730
|
+
}
|
|
731
|
+
function findByInstanceId(instanceId) {
|
|
732
|
+
const escapedId = CSS.escape(instanceId);
|
|
733
|
+
const direct = document.querySelector(`[data-ohw-instance="${escapedId}"]`);
|
|
734
|
+
if (direct) return movableUnit(direct);
|
|
735
|
+
const bare = document.querySelector(`[data-ohw-section="${escapedId}"]:not([data-ohw-instance])`);
|
|
736
|
+
return bare ? movableUnit(bare) : null;
|
|
737
|
+
}
|
|
738
|
+
function planSectionMove(instanceId, targetIndex, currentPath) {
|
|
739
|
+
const sections = topLevelSections();
|
|
740
|
+
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
741
|
+
if (index === -1) return null;
|
|
742
|
+
const dragged = sections[index];
|
|
743
|
+
const others = sections.filter((_, i) => i !== index);
|
|
744
|
+
const clamped = Math.max(0, Math.min(targetIndex, others.length));
|
|
745
|
+
const reordered = [...others.slice(0, clamped), dragged, ...others.slice(clamped)];
|
|
746
|
+
return reordered.map((el, order) => ({
|
|
747
|
+
instanceId: instanceIdOf(el),
|
|
748
|
+
type: sectionTypeOf(el),
|
|
749
|
+
order,
|
|
750
|
+
pagePath: currentPath
|
|
751
|
+
}));
|
|
752
|
+
}
|
|
753
|
+
function moveSectionInstance(instanceId, direction, currentPath) {
|
|
754
|
+
const sections = topLevelSections();
|
|
755
|
+
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
756
|
+
if (index === -1) return null;
|
|
757
|
+
const siblingIndex = direction === "up" ? index - 1 : index + 1;
|
|
758
|
+
if (siblingIndex < 0 || siblingIndex >= sections.length) return null;
|
|
759
|
+
const entries = planSectionMove(instanceId, siblingIndex, currentPath);
|
|
760
|
+
if (!entries) return null;
|
|
761
|
+
applyPersistedOrder(entries);
|
|
762
|
+
return entries;
|
|
763
|
+
}
|
|
764
|
+
function syncRemovedFlags(entries) {
|
|
765
|
+
const removedIds = new Set(entries.filter((e) => e.removed).map((e) => e.instanceId));
|
|
766
|
+
document.querySelectorAll(`[${REMOVED_ATTR}]`).forEach((el) => {
|
|
767
|
+
if (!removedIds.has(instanceIdOf(el))) {
|
|
768
|
+
el.style.removeProperty("display");
|
|
769
|
+
el.removeAttribute(REMOVED_ATTR);
|
|
770
|
+
}
|
|
771
|
+
});
|
|
772
|
+
for (const id of removedIds) {
|
|
773
|
+
const el = findByInstanceId(id);
|
|
774
|
+
if (el) {
|
|
775
|
+
el.style.display = "none";
|
|
776
|
+
el.setAttribute(REMOVED_ATTR, "");
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
function applyPersistedOrder(entries) {
|
|
781
|
+
syncRemovedFlags(entries);
|
|
782
|
+
if (entries.length === 0) return;
|
|
783
|
+
const sections = topLevelSections();
|
|
784
|
+
if (sections.length === 0) return;
|
|
785
|
+
const orderIndex = new Map(entries.map((e) => [e.instanceId, e.order]));
|
|
786
|
+
const ordered = [...sections].sort((a, b) => {
|
|
787
|
+
const aOrder = orderIndex.get(instanceIdOf(a));
|
|
788
|
+
const bOrder = orderIndex.get(instanceIdOf(b));
|
|
789
|
+
if (aOrder === void 0 && bOrder === void 0) return 0;
|
|
790
|
+
if (aOrder === void 0) return 1;
|
|
791
|
+
if (bOrder === void 0) return -1;
|
|
792
|
+
return aOrder - bOrder;
|
|
793
|
+
});
|
|
794
|
+
let prev = null;
|
|
795
|
+
for (const el of ordered) {
|
|
796
|
+
if (prev) prev.after(el);
|
|
797
|
+
prev = el;
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
function setSectionRemoved(instanceId, currentPath, existingEntries, removed) {
|
|
801
|
+
if (!findByInstanceId(instanceId)) return null;
|
|
802
|
+
const byId = new Map(existingEntries.map((e) => [e.instanceId, e]));
|
|
803
|
+
const allSections = collectTopLevelUnits((el) => !isChromeSection(el));
|
|
804
|
+
allSections.forEach((el, order) => {
|
|
805
|
+
const id = instanceIdOf(el);
|
|
806
|
+
if (!byId.has(id)) {
|
|
807
|
+
byId.set(id, { instanceId: id, type: sectionTypeOf(el), order, pagePath: currentPath });
|
|
808
|
+
}
|
|
809
|
+
});
|
|
810
|
+
const target = byId.get(instanceId);
|
|
811
|
+
if (!target) return null;
|
|
812
|
+
byId.set(instanceId, { ...target, removed });
|
|
813
|
+
const entries = Array.from(byId.values());
|
|
814
|
+
applyPersistedOrder(entries);
|
|
815
|
+
return entries;
|
|
816
|
+
}
|
|
817
|
+
function deleteSectionInstance(instanceId, currentPath, existingEntries) {
|
|
818
|
+
return setSectionRemoved(instanceId, currentPath, existingEntries, true);
|
|
819
|
+
}
|
|
820
|
+
function restoreSectionInstance(instanceId, currentPath, existingEntries) {
|
|
821
|
+
return setSectionRemoved(instanceId, currentPath, existingEntries, false);
|
|
822
|
+
}
|
|
823
|
+
function duplicateSectionInstance(instanceId, newId, currentPath, existingEntries) {
|
|
824
|
+
const original = findByInstanceId(instanceId);
|
|
825
|
+
if (!original) return null;
|
|
826
|
+
const clone = original.cloneNode(true);
|
|
827
|
+
clone.setAttribute("data-ohw-instance", newId);
|
|
828
|
+
const keyRekeys = rekeySectionSubtree(clone, newId);
|
|
829
|
+
original.insertAdjacentElement("afterend", clone);
|
|
830
|
+
const byId = new Map(existingEntries.map((e) => [e.instanceId, e]));
|
|
831
|
+
const entries = topLevelSections().map((el, order) => {
|
|
832
|
+
const id = instanceIdOf(el);
|
|
833
|
+
return {
|
|
834
|
+
instanceId: id,
|
|
835
|
+
type: sectionTypeOf(el),
|
|
836
|
+
order,
|
|
837
|
+
pagePath: currentPath,
|
|
838
|
+
...byId.get(id)?.removed ? { removed: true } : {}
|
|
839
|
+
};
|
|
840
|
+
});
|
|
841
|
+
applyPersistedOrder(entries);
|
|
842
|
+
return { entries, keyRekeys };
|
|
843
|
+
}
|
|
844
|
+
function newInstanceId() {
|
|
845
|
+
return typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `instance-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
846
|
+
}
|
|
847
|
+
function getPageSectionOrderEntries(raw, currentPath) {
|
|
848
|
+
if (!raw) return [];
|
|
849
|
+
try {
|
|
850
|
+
const entries = JSON.parse(raw);
|
|
851
|
+
return entries.filter((e) => !e.pagePath || e.pagePath === currentPath);
|
|
852
|
+
} catch {
|
|
853
|
+
return [];
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
function mergePageSectionOrder(raw, currentPath, pageEntries) {
|
|
857
|
+
let all = [];
|
|
858
|
+
if (raw) {
|
|
859
|
+
try {
|
|
860
|
+
const parsed = JSON.parse(raw);
|
|
861
|
+
if (Array.isArray(parsed)) all = parsed;
|
|
862
|
+
} catch {
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
const otherPages = all.filter((e) => e && e.pagePath && e.pagePath !== currentPath);
|
|
866
|
+
const pageIds = new Set(pageEntries.map((e) => e.instanceId));
|
|
867
|
+
const removedHere = all.filter(
|
|
868
|
+
(e) => e && (!e.pagePath || e.pagePath === currentPath) && e.removed && !pageIds.has(e.instanceId)
|
|
869
|
+
);
|
|
870
|
+
return [...otherPages, ...removedHere, ...pageEntries];
|
|
871
|
+
}
|
|
872
|
+
function rekeySectionSubtree(root, instanceId) {
|
|
873
|
+
const suffix = `::${instanceId}`;
|
|
874
|
+
const pairs = [];
|
|
875
|
+
const rekey = (el, attr) => {
|
|
876
|
+
const current = el.getAttribute(attr);
|
|
877
|
+
if (!current) return;
|
|
878
|
+
const base = current.includes("::") ? current.slice(0, current.indexOf("::")) : current;
|
|
879
|
+
const next = `${base}${suffix}`;
|
|
880
|
+
el.setAttribute(attr, next);
|
|
881
|
+
pairs.push({ from: current, to: next });
|
|
882
|
+
};
|
|
883
|
+
if (root.hasAttribute("data-ohw-key")) rekey(root, "data-ohw-key");
|
|
884
|
+
if (root.hasAttribute("data-ohw-href-key")) rekey(root, "data-ohw-href-key");
|
|
885
|
+
root.querySelectorAll("[data-ohw-key]").forEach((el) => rekey(el, "data-ohw-key"));
|
|
886
|
+
root.querySelectorAll("[data-ohw-href-key]").forEach((el) => rekey(el, "data-ohw-href-key"));
|
|
887
|
+
return pairs;
|
|
888
|
+
}
|
|
889
|
+
function initSectionInstancesFromContent(content, currentPath) {
|
|
890
|
+
document.querySelectorAll("[data-ohw-section]:not([data-ohw-instance])").forEach((el) => {
|
|
891
|
+
el.setAttribute("data-ohw-instance", el.getAttribute("data-ohw-section") ?? "");
|
|
892
|
+
});
|
|
893
|
+
document.querySelectorAll("[data-ohw-section-container]:not([data-ohw-instance])").forEach((el) => {
|
|
894
|
+
const type = sectionTypeOf(el);
|
|
895
|
+
if (type) el.setAttribute("data-ohw-instance", type);
|
|
896
|
+
});
|
|
897
|
+
const entries = getPageSectionOrderEntries(content[SECTION_ORDER_KEY], currentPath);
|
|
898
|
+
for (const entry of entries) {
|
|
899
|
+
if (entry.instanceId === entry.type) continue;
|
|
900
|
+
if (document.querySelector(`[data-ohw-instance="${CSS.escape(entry.instanceId)}"]`)) continue;
|
|
901
|
+
const original = document.querySelector(
|
|
902
|
+
`[data-ohw-section="${CSS.escape(entry.type)}"][data-ohw-instance="${CSS.escape(entry.type)}"]`
|
|
903
|
+
);
|
|
904
|
+
if (!original) continue;
|
|
905
|
+
const clone = original.cloneNode(true);
|
|
906
|
+
clone.setAttribute("data-ohw-instance", entry.instanceId);
|
|
907
|
+
rekeySectionSubtree(clone, entry.instanceId);
|
|
908
|
+
original.insertAdjacentElement("afterend", clone);
|
|
909
|
+
}
|
|
910
|
+
applyPersistedOrder(entries);
|
|
911
|
+
}
|
|
912
|
+
|
|
635
913
|
// src/ui/ai-tree/AiTreeRenderer.tsx
|
|
636
914
|
var import_react = __toESM(require("react"), 1);
|
|
637
915
|
var import_lucide_react = require("lucide-react");
|
|
@@ -1999,7 +2277,7 @@ function AiTreeRenderer({
|
|
|
1999
2277
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
2000
2278
|
var CONTAINER_ATTR = "data-ohw-ai-generated";
|
|
2001
2279
|
var REPLACED_ATTR = "data-ohw-ai-replaced-by";
|
|
2002
|
-
var
|
|
2280
|
+
var REMOVED_ATTR2 = "data-ohw-ai-removed";
|
|
2003
2281
|
var TEMPLATE_HIDDEN_ATTR = "data-ohw-ai-template-hidden";
|
|
2004
2282
|
var CHROME_SECTION_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
|
|
2005
2283
|
function readRootVar(name) {
|
|
@@ -2094,18 +2372,18 @@ function placeContainer(container, entry) {
|
|
|
2094
2372
|
}
|
|
2095
2373
|
function syncRemovedSections(state) {
|
|
2096
2374
|
const removed = new Set(state.removed ?? []);
|
|
2097
|
-
for (const el of document.querySelectorAll(`[${
|
|
2375
|
+
for (const el of document.querySelectorAll(`[${REMOVED_ATTR2}]`)) {
|
|
2098
2376
|
const id = el.getAttribute("data-ohw-section") ?? "";
|
|
2099
2377
|
if (!removed.has(id)) {
|
|
2100
2378
|
el.style.removeProperty("display");
|
|
2101
|
-
el.removeAttribute(
|
|
2379
|
+
el.removeAttribute(REMOVED_ATTR2);
|
|
2102
2380
|
}
|
|
2103
2381
|
}
|
|
2104
2382
|
for (const id of removed) {
|
|
2105
2383
|
const section = findTemplateSection(id);
|
|
2106
2384
|
if (section && !section.hasAttribute(REPLACED_ATTR)) {
|
|
2107
2385
|
section.style.display = "none";
|
|
2108
|
-
section.setAttribute(
|
|
2386
|
+
section.setAttribute(REMOVED_ATTR2, "");
|
|
2109
2387
|
}
|
|
2110
2388
|
}
|
|
2111
2389
|
}
|
|
@@ -2122,7 +2400,7 @@ function syncTemplateHidden(state, pageHasSections) {
|
|
|
2122
2400
|
if (el.hasAttribute(CONTAINER_ATTR)) continue;
|
|
2123
2401
|
if (CHROME_SECTION_IDS.has(el.getAttribute("data-ohw-section") ?? "")) continue;
|
|
2124
2402
|
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
2125
|
-
if (el.hasAttribute(REPLACED_ATTR) || el.hasAttribute(
|
|
2403
|
+
if (el.hasAttribute(REPLACED_ATTR) || el.hasAttribute(REMOVED_ATTR2)) continue;
|
|
2126
2404
|
el.style.display = "none";
|
|
2127
2405
|
el.setAttribute(TEMPLATE_HIDDEN_ATTR, "");
|
|
2128
2406
|
}
|
|
@@ -2146,18 +2424,23 @@ function syncReplacedOriginals(state) {
|
|
|
2146
2424
|
}
|
|
2147
2425
|
}
|
|
2148
2426
|
var sectionOrderIndex = /* @__PURE__ */ new Map();
|
|
2427
|
+
var removedSectionIds = /* @__PURE__ */ new Set();
|
|
2149
2428
|
function setAiSectionOrder(raw, currentPath) {
|
|
2150
2429
|
const next = /* @__PURE__ */ new Map();
|
|
2430
|
+
const removed = /* @__PURE__ */ new Set();
|
|
2151
2431
|
if (raw) {
|
|
2152
2432
|
try {
|
|
2153
2433
|
const entries = JSON.parse(raw);
|
|
2154
2434
|
for (const entry of entries) {
|
|
2155
|
-
if (
|
|
2435
|
+
if (entry.pagePath && entry.pagePath !== currentPath) continue;
|
|
2436
|
+
next.set(entry.instanceId, entry.order);
|
|
2437
|
+
if (entry.removed) removed.add(entry.instanceId);
|
|
2156
2438
|
}
|
|
2157
2439
|
} catch {
|
|
2158
2440
|
}
|
|
2159
2441
|
}
|
|
2160
2442
|
sectionOrderIndex = next;
|
|
2443
|
+
removedSectionIds = removed;
|
|
2161
2444
|
}
|
|
2162
2445
|
function applyExplicitOrder(entries) {
|
|
2163
2446
|
if (sectionOrderIndex.size === 0) return entries;
|
|
@@ -2193,6 +2476,18 @@ function orderByChain(sections) {
|
|
|
2193
2476
|
for (const root of roots) visit(root);
|
|
2194
2477
|
return out.length === sections.length ? out : sections;
|
|
2195
2478
|
}
|
|
2479
|
+
function syncSoftRemovedGenerated() {
|
|
2480
|
+
for (const [id, section] of mounted) {
|
|
2481
|
+
const el = section.container;
|
|
2482
|
+
if (removedSectionIds.has(id)) {
|
|
2483
|
+
el.style.display = "none";
|
|
2484
|
+
el.setAttribute(REMOVED_ATTR, "");
|
|
2485
|
+
} else if (el.hasAttribute(REMOVED_ATTR)) {
|
|
2486
|
+
el.style.removeProperty("display");
|
|
2487
|
+
el.removeAttribute(REMOVED_ATTR);
|
|
2488
|
+
}
|
|
2489
|
+
}
|
|
2490
|
+
}
|
|
2196
2491
|
function applyAiSectionsToDom(state, options) {
|
|
2197
2492
|
if (typeof document === "undefined") return;
|
|
2198
2493
|
const brandOverride = deriveBrandOverride();
|
|
@@ -2260,6 +2555,23 @@ function applyAiSectionsToDom(state, options) {
|
|
|
2260
2555
|
syncReplacedOriginals(state);
|
|
2261
2556
|
syncRemovedSections(state);
|
|
2262
2557
|
syncTemplateHidden(state, pageSections.length > 0);
|
|
2558
|
+
syncSoftRemovedGenerated();
|
|
2559
|
+
}
|
|
2560
|
+
function unmountAllAiSections() {
|
|
2561
|
+
for (const [, section] of mounted) {
|
|
2562
|
+
section.root.unmount();
|
|
2563
|
+
section.container.remove();
|
|
2564
|
+
}
|
|
2565
|
+
mounted.clear();
|
|
2566
|
+
if (typeof document === "undefined") return;
|
|
2567
|
+
for (const el of document.querySelectorAll(`[${REPLACED_ATTR}]`)) {
|
|
2568
|
+
el.style.removeProperty("display");
|
|
2569
|
+
el.removeAttribute(REPLACED_ATTR);
|
|
2570
|
+
}
|
|
2571
|
+
for (const el of document.querySelectorAll(`[${REMOVED_ATTR2}]`)) {
|
|
2572
|
+
el.style.removeProperty("display");
|
|
2573
|
+
el.removeAttribute(REMOVED_ATTR2);
|
|
2574
|
+
}
|
|
2263
2575
|
}
|
|
2264
2576
|
|
|
2265
2577
|
// src/useLinkHrefGuardian.ts
|
|
@@ -8219,240 +8531,6 @@ function CarouselOverlay({
|
|
|
8219
8531
|
// src/ui/ai-section/AiSectionOverlay.tsx
|
|
8220
8532
|
var import_react8 = require("react");
|
|
8221
8533
|
var import_lucide_react7 = require("lucide-react");
|
|
8222
|
-
|
|
8223
|
-
// src/lib/sections.ts
|
|
8224
|
-
var LINK_PICKER_EXCLUDED_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
|
|
8225
|
-
function isChromeSection(el) {
|
|
8226
|
-
return el.matches("header, nav, footer, aside");
|
|
8227
|
-
}
|
|
8228
|
-
function titleCaseSectionId(id) {
|
|
8229
|
-
return id.split("-").filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
8230
|
-
}
|
|
8231
|
-
function parseSectionsFromRoot(root) {
|
|
8232
|
-
const seen = /* @__PURE__ */ new Set();
|
|
8233
|
-
const sections = [];
|
|
8234
|
-
for (const el of root.querySelectorAll("[data-ohw-section]")) {
|
|
8235
|
-
const id = el.getAttribute("data-ohw-section") ?? "";
|
|
8236
|
-
if (!id || seen.has(id) || LINK_PICKER_EXCLUDED_IDS.has(id)) continue;
|
|
8237
|
-
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
8238
|
-
if (el.hasAttribute("data-ohw-ai-template-hidden") || el.hasAttribute("data-ohw-ai-removed") || el.hasAttribute("data-ohw-ai-replaced-by"))
|
|
8239
|
-
continue;
|
|
8240
|
-
seen.add(id);
|
|
8241
|
-
const label = el.getAttribute("data-ohw-section-label") ?? titleCaseSectionId(id);
|
|
8242
|
-
sections.push({ id, label });
|
|
8243
|
-
}
|
|
8244
|
-
return sections;
|
|
8245
|
-
}
|
|
8246
|
-
function collectSectionsFromDom() {
|
|
8247
|
-
if (typeof document === "undefined") return [];
|
|
8248
|
-
return parseSectionsFromRoot(document);
|
|
8249
|
-
}
|
|
8250
|
-
function parseSectionsFromHtml(html) {
|
|
8251
|
-
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
8252
|
-
return parseSectionsFromRoot(doc);
|
|
8253
|
-
}
|
|
8254
|
-
|
|
8255
|
-
// src/lib/section-instances.ts
|
|
8256
|
-
var SECTION_ORDER_KEY = "__ohw_section_order";
|
|
8257
|
-
var REMOVED_ATTR2 = "data-ohw-section-removed";
|
|
8258
|
-
function isRemovedSection(el) {
|
|
8259
|
-
return el.hasAttribute(REMOVED_ATTR2);
|
|
8260
|
-
}
|
|
8261
|
-
function movableUnit(el) {
|
|
8262
|
-
return el.closest("[data-ohw-section-container]") ?? el;
|
|
8263
|
-
}
|
|
8264
|
-
function sectionTypeOf(el) {
|
|
8265
|
-
return el.getAttribute("data-ohw-section") ?? el.querySelector("[data-ohw-section]")?.getAttribute("data-ohw-section") ?? "";
|
|
8266
|
-
}
|
|
8267
|
-
function sectionElementOf(el) {
|
|
8268
|
-
return el.hasAttribute("data-ohw-section") ? el : el.querySelector("[data-ohw-section]") ?? el;
|
|
8269
|
-
}
|
|
8270
|
-
function collectTopLevelUnits(predicate) {
|
|
8271
|
-
const seen = /* @__PURE__ */ new Set();
|
|
8272
|
-
const result = [];
|
|
8273
|
-
document.querySelectorAll("[data-ohw-section]").forEach((el) => {
|
|
8274
|
-
if (!predicate(el)) return;
|
|
8275
|
-
const unit = movableUnit(el);
|
|
8276
|
-
if (unit.parentElement?.closest("[data-ohw-section],[data-ohw-section-container]")) return;
|
|
8277
|
-
if (seen.has(unit)) return;
|
|
8278
|
-
seen.add(unit);
|
|
8279
|
-
result.push(unit);
|
|
8280
|
-
});
|
|
8281
|
-
return result;
|
|
8282
|
-
}
|
|
8283
|
-
function topLevelSections() {
|
|
8284
|
-
return collectTopLevelUnits((el) => !isChromeSection(el) && !isRemovedSection(movableUnit(el)));
|
|
8285
|
-
}
|
|
8286
|
-
function instanceIdOf(el) {
|
|
8287
|
-
return el.dataset.ohwInstance ?? el.dataset.ohwSection ?? "";
|
|
8288
|
-
}
|
|
8289
|
-
function findByInstanceId(instanceId) {
|
|
8290
|
-
const escapedId = CSS.escape(instanceId);
|
|
8291
|
-
const direct = document.querySelector(`[data-ohw-instance="${escapedId}"]`);
|
|
8292
|
-
if (direct) return movableUnit(direct);
|
|
8293
|
-
const bare = document.querySelector(`[data-ohw-section="${escapedId}"]:not([data-ohw-instance])`);
|
|
8294
|
-
return bare ? movableUnit(bare) : null;
|
|
8295
|
-
}
|
|
8296
|
-
function planSectionMove(instanceId, targetIndex, currentPath) {
|
|
8297
|
-
const sections = topLevelSections();
|
|
8298
|
-
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
8299
|
-
if (index === -1) return null;
|
|
8300
|
-
const dragged = sections[index];
|
|
8301
|
-
const others = sections.filter((_, i) => i !== index);
|
|
8302
|
-
const clamped = Math.max(0, Math.min(targetIndex, others.length));
|
|
8303
|
-
const reordered = [...others.slice(0, clamped), dragged, ...others.slice(clamped)];
|
|
8304
|
-
return reordered.map((el, order) => ({
|
|
8305
|
-
instanceId: instanceIdOf(el),
|
|
8306
|
-
type: sectionTypeOf(el),
|
|
8307
|
-
order,
|
|
8308
|
-
pagePath: currentPath
|
|
8309
|
-
}));
|
|
8310
|
-
}
|
|
8311
|
-
function moveSectionInstance(instanceId, direction, currentPath) {
|
|
8312
|
-
const sections = topLevelSections();
|
|
8313
|
-
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
8314
|
-
if (index === -1) return null;
|
|
8315
|
-
const siblingIndex = direction === "up" ? index - 1 : index + 1;
|
|
8316
|
-
if (siblingIndex < 0 || siblingIndex >= sections.length) return null;
|
|
8317
|
-
const entries = planSectionMove(instanceId, siblingIndex, currentPath);
|
|
8318
|
-
if (!entries) return null;
|
|
8319
|
-
applyPersistedOrder(entries);
|
|
8320
|
-
return entries;
|
|
8321
|
-
}
|
|
8322
|
-
function syncRemovedFlags(entries) {
|
|
8323
|
-
const removedIds = new Set(entries.filter((e) => e.removed).map((e) => e.instanceId));
|
|
8324
|
-
document.querySelectorAll(`[${REMOVED_ATTR2}]`).forEach((el) => {
|
|
8325
|
-
if (!removedIds.has(instanceIdOf(el))) {
|
|
8326
|
-
el.style.removeProperty("display");
|
|
8327
|
-
el.removeAttribute(REMOVED_ATTR2);
|
|
8328
|
-
}
|
|
8329
|
-
});
|
|
8330
|
-
for (const id of removedIds) {
|
|
8331
|
-
const el = findByInstanceId(id);
|
|
8332
|
-
if (el) {
|
|
8333
|
-
el.style.display = "none";
|
|
8334
|
-
el.setAttribute(REMOVED_ATTR2, "");
|
|
8335
|
-
}
|
|
8336
|
-
}
|
|
8337
|
-
}
|
|
8338
|
-
function applyPersistedOrder(entries) {
|
|
8339
|
-
syncRemovedFlags(entries);
|
|
8340
|
-
if (entries.length === 0) return;
|
|
8341
|
-
const sections = topLevelSections();
|
|
8342
|
-
if (sections.length === 0) return;
|
|
8343
|
-
const orderIndex = new Map(entries.map((e) => [e.instanceId, e.order]));
|
|
8344
|
-
const ordered = [...sections].sort((a, b) => {
|
|
8345
|
-
const aOrder = orderIndex.get(instanceIdOf(a));
|
|
8346
|
-
const bOrder = orderIndex.get(instanceIdOf(b));
|
|
8347
|
-
if (aOrder === void 0 && bOrder === void 0) return 0;
|
|
8348
|
-
if (aOrder === void 0) return 1;
|
|
8349
|
-
if (bOrder === void 0) return -1;
|
|
8350
|
-
return aOrder - bOrder;
|
|
8351
|
-
});
|
|
8352
|
-
let prev = null;
|
|
8353
|
-
for (const el of ordered) {
|
|
8354
|
-
if (prev) prev.after(el);
|
|
8355
|
-
prev = el;
|
|
8356
|
-
}
|
|
8357
|
-
}
|
|
8358
|
-
function setSectionRemoved(instanceId, currentPath, existingEntries, removed) {
|
|
8359
|
-
if (!findByInstanceId(instanceId)) return null;
|
|
8360
|
-
const byId = new Map(existingEntries.map((e) => [e.instanceId, e]));
|
|
8361
|
-
const allSections = collectTopLevelUnits((el) => !isChromeSection(el));
|
|
8362
|
-
allSections.forEach((el, order) => {
|
|
8363
|
-
const id = instanceIdOf(el);
|
|
8364
|
-
if (!byId.has(id)) {
|
|
8365
|
-
byId.set(id, { instanceId: id, type: sectionTypeOf(el), order, pagePath: currentPath });
|
|
8366
|
-
}
|
|
8367
|
-
});
|
|
8368
|
-
const target = byId.get(instanceId);
|
|
8369
|
-
if (!target) return null;
|
|
8370
|
-
byId.set(instanceId, { ...target, removed });
|
|
8371
|
-
const entries = Array.from(byId.values());
|
|
8372
|
-
applyPersistedOrder(entries);
|
|
8373
|
-
return entries;
|
|
8374
|
-
}
|
|
8375
|
-
function deleteSectionInstance(instanceId, currentPath, existingEntries) {
|
|
8376
|
-
return setSectionRemoved(instanceId, currentPath, existingEntries, true);
|
|
8377
|
-
}
|
|
8378
|
-
function restoreSectionInstance(instanceId, currentPath, existingEntries) {
|
|
8379
|
-
return setSectionRemoved(instanceId, currentPath, existingEntries, false);
|
|
8380
|
-
}
|
|
8381
|
-
function duplicateSectionInstance(instanceId, newId, currentPath, existingEntries) {
|
|
8382
|
-
const original = findByInstanceId(instanceId);
|
|
8383
|
-
if (!original) return null;
|
|
8384
|
-
const clone = original.cloneNode(true);
|
|
8385
|
-
clone.setAttribute("data-ohw-instance", newId);
|
|
8386
|
-
const keyRekeys = rekeySectionSubtree(clone, newId);
|
|
8387
|
-
original.insertAdjacentElement("afterend", clone);
|
|
8388
|
-
const byId = new Map(existingEntries.map((e) => [e.instanceId, e]));
|
|
8389
|
-
const entries = topLevelSections().map((el, order) => {
|
|
8390
|
-
const id = instanceIdOf(el);
|
|
8391
|
-
return {
|
|
8392
|
-
instanceId: id,
|
|
8393
|
-
type: sectionTypeOf(el),
|
|
8394
|
-
order,
|
|
8395
|
-
pagePath: currentPath,
|
|
8396
|
-
...byId.get(id)?.removed ? { removed: true } : {}
|
|
8397
|
-
};
|
|
8398
|
-
});
|
|
8399
|
-
applyPersistedOrder(entries);
|
|
8400
|
-
return { entries, keyRekeys };
|
|
8401
|
-
}
|
|
8402
|
-
function newInstanceId() {
|
|
8403
|
-
return typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `instance-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
8404
|
-
}
|
|
8405
|
-
function getPageSectionOrderEntries(raw, currentPath) {
|
|
8406
|
-
if (!raw) return [];
|
|
8407
|
-
try {
|
|
8408
|
-
const entries = JSON.parse(raw);
|
|
8409
|
-
return entries.filter((e) => !e.pagePath || e.pagePath === currentPath);
|
|
8410
|
-
} catch {
|
|
8411
|
-
return [];
|
|
8412
|
-
}
|
|
8413
|
-
}
|
|
8414
|
-
function rekeySectionSubtree(root, instanceId) {
|
|
8415
|
-
const suffix = `::${instanceId}`;
|
|
8416
|
-
const pairs = [];
|
|
8417
|
-
const rekey = (el, attr) => {
|
|
8418
|
-
const current = el.getAttribute(attr);
|
|
8419
|
-
if (!current) return;
|
|
8420
|
-
const base = current.includes("::") ? current.slice(0, current.indexOf("::")) : current;
|
|
8421
|
-
const next = `${base}${suffix}`;
|
|
8422
|
-
el.setAttribute(attr, next);
|
|
8423
|
-
pairs.push({ from: current, to: next });
|
|
8424
|
-
};
|
|
8425
|
-
if (root.hasAttribute("data-ohw-key")) rekey(root, "data-ohw-key");
|
|
8426
|
-
if (root.hasAttribute("data-ohw-href-key")) rekey(root, "data-ohw-href-key");
|
|
8427
|
-
root.querySelectorAll("[data-ohw-key]").forEach((el) => rekey(el, "data-ohw-key"));
|
|
8428
|
-
root.querySelectorAll("[data-ohw-href-key]").forEach((el) => rekey(el, "data-ohw-href-key"));
|
|
8429
|
-
return pairs;
|
|
8430
|
-
}
|
|
8431
|
-
function initSectionInstancesFromContent(content, currentPath) {
|
|
8432
|
-
document.querySelectorAll("[data-ohw-section]:not([data-ohw-instance])").forEach((el) => {
|
|
8433
|
-
el.setAttribute("data-ohw-instance", el.getAttribute("data-ohw-section") ?? "");
|
|
8434
|
-
});
|
|
8435
|
-
document.querySelectorAll("[data-ohw-section-container]:not([data-ohw-instance])").forEach((el) => {
|
|
8436
|
-
const type = sectionTypeOf(el);
|
|
8437
|
-
if (type) el.setAttribute("data-ohw-instance", type);
|
|
8438
|
-
});
|
|
8439
|
-
const entries = getPageSectionOrderEntries(content[SECTION_ORDER_KEY], currentPath);
|
|
8440
|
-
for (const entry of entries) {
|
|
8441
|
-
if (entry.instanceId === entry.type) continue;
|
|
8442
|
-
if (document.querySelector(`[data-ohw-instance="${CSS.escape(entry.instanceId)}"]`)) continue;
|
|
8443
|
-
const original = document.querySelector(
|
|
8444
|
-
`[data-ohw-section="${CSS.escape(entry.type)}"][data-ohw-instance="${CSS.escape(entry.type)}"]`
|
|
8445
|
-
);
|
|
8446
|
-
if (!original) continue;
|
|
8447
|
-
const clone = original.cloneNode(true);
|
|
8448
|
-
clone.setAttribute("data-ohw-instance", entry.instanceId);
|
|
8449
|
-
rekeySectionSubtree(clone, entry.instanceId);
|
|
8450
|
-
original.insertAdjacentElement("afterend", clone);
|
|
8451
|
-
}
|
|
8452
|
-
applyPersistedOrder(entries);
|
|
8453
|
-
}
|
|
8454
|
-
|
|
8455
|
-
// src/ui/ai-section/AiSectionOverlay.tsx
|
|
8456
8534
|
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
8457
8535
|
var findSectionElement = findByInstanceId;
|
|
8458
8536
|
function readRect(instanceId) {
|
|
@@ -14235,15 +14313,17 @@ function useSectionDrag({
|
|
|
14235
14313
|
clearSectionDragVisuals();
|
|
14236
14314
|
return;
|
|
14237
14315
|
}
|
|
14238
|
-
const orderJson = JSON.stringify(
|
|
14316
|
+
const orderJson = JSON.stringify(
|
|
14317
|
+
mergePageSectionOrder(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname, entries)
|
|
14318
|
+
);
|
|
14239
14319
|
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
14240
14320
|
setAiSectionOrder(orderJson, window.location.pathname);
|
|
14241
14321
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
14242
|
-
applyPersistedOrder(
|
|
14322
|
+
applyPersistedOrder(getPageSectionOrderEntries(orderJson, window.location.pathname));
|
|
14243
14323
|
clearSectionDragVisuals();
|
|
14244
14324
|
requestAnimationFrame(() => {
|
|
14245
14325
|
if (editContentRef.current[SECTION_ORDER_KEY] === orderJson) {
|
|
14246
|
-
applyPersistedOrder(
|
|
14326
|
+
applyPersistedOrder(getPageSectionOrderEntries(orderJson, window.location.pathname));
|
|
14247
14327
|
}
|
|
14248
14328
|
requestAnimationFrame(() => {
|
|
14249
14329
|
window.dispatchEvent(new Event("resize"));
|
|
@@ -18427,6 +18507,22 @@ function OhhwellsBridge() {
|
|
|
18427
18507
|
(0, import_react17.useEffect)(() => {
|
|
18428
18508
|
postToParent2({ type: "ow:navigation", path: pathname });
|
|
18429
18509
|
}, [pathname, postToParent2]);
|
|
18510
|
+
(0, import_react17.useEffect)(() => {
|
|
18511
|
+
if (!subdomain || isEditMode) return;
|
|
18512
|
+
const content = contentCache.get(subdomain);
|
|
18513
|
+
if (!content) return;
|
|
18514
|
+
unmountAllAiSections();
|
|
18515
|
+
initSectionsFromContent(
|
|
18516
|
+
content,
|
|
18517
|
+
/*removeExisting*/
|
|
18518
|
+
true,
|
|
18519
|
+
pathname
|
|
18520
|
+
);
|
|
18521
|
+
if (typeof content[AI_SECTIONS_KEY] === "string") {
|
|
18522
|
+
setAiSectionOrder(content[SECTION_ORDER_KEY], pathname);
|
|
18523
|
+
applyAiSectionsToDom(parseAiSectionsState(content[AI_SECTIONS_KEY]));
|
|
18524
|
+
}
|
|
18525
|
+
}, [pathname, subdomain, isEditMode]);
|
|
18430
18526
|
(0, import_react17.useEffect)(() => {
|
|
18431
18527
|
if (!isEditMode) return;
|
|
18432
18528
|
if (linkPopoverSessionRef.current?.intent === "add-nav") return;
|
|
@@ -20252,6 +20348,44 @@ function OhhwellsBridge() {
|
|
|
20252
20348
|
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
20253
20349
|
}, 400));
|
|
20254
20350
|
};
|
|
20351
|
+
const reapCommittedAiSections = (excludeIds) => {
|
|
20352
|
+
const aiState = parseAiSectionsState(aiSectionsRef.current);
|
|
20353
|
+
if (aiState.sections.length === 0) return [];
|
|
20354
|
+
let orderEntries = [];
|
|
20355
|
+
try {
|
|
20356
|
+
const parsed = JSON.parse(editContentRef.current[SECTION_ORDER_KEY] ?? "[]");
|
|
20357
|
+
if (Array.isArray(parsed)) orderEntries = parsed;
|
|
20358
|
+
} catch {
|
|
20359
|
+
return [];
|
|
20360
|
+
}
|
|
20361
|
+
const removedIds = orderEntries.filter((entry) => entry && typeof entry.instanceId === "string" && entry.removed).map((entry) => entry.instanceId);
|
|
20362
|
+
if (removedIds.length === 0) return [];
|
|
20363
|
+
const result = reapRemovedAiSections(aiState, parseStyleStore(stylesRef.current), removedIds, excludeIds);
|
|
20364
|
+
if (!result.changed) return [];
|
|
20365
|
+
const nodes = [];
|
|
20366
|
+
aiSectionsRef.current = serializeAiSectionsState(result.state);
|
|
20367
|
+
nodes.push({ key: AI_SECTIONS_KEY, text: aiSectionsRef.current });
|
|
20368
|
+
const reaped = new Set(result.reapedIds);
|
|
20369
|
+
const nextOrderJson = JSON.stringify(orderEntries.filter((entry) => !reaped.has(entry.instanceId)));
|
|
20370
|
+
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: nextOrderJson };
|
|
20371
|
+
setAiSectionOrder(nextOrderJson, window.location.pathname);
|
|
20372
|
+
nodes.push({ key: SECTION_ORDER_KEY, text: nextOrderJson });
|
|
20373
|
+
if (result.store) {
|
|
20374
|
+
stylesRef.current = JSON.stringify(result.store);
|
|
20375
|
+
nodes.push({ key: STYLE_STORE_KEY, text: stylesRef.current });
|
|
20376
|
+
}
|
|
20377
|
+
const nextContent = { ...editContentRef.current };
|
|
20378
|
+
for (const key of Object.keys(nextContent)) {
|
|
20379
|
+
if (key.startsWith(AI_SLOT_KEY_PREFIX) && result.slotPrefixes.some((prefix) => key.startsWith(prefix)) && nextContent[key] !== "") {
|
|
20380
|
+
nextContent[key] = "";
|
|
20381
|
+
nodes.push({ key, text: "" });
|
|
20382
|
+
}
|
|
20383
|
+
}
|
|
20384
|
+
editContentRef.current = nextContent;
|
|
20385
|
+
applyAiSectionsToDom(result.state);
|
|
20386
|
+
applyStylesToDom(parseStyleStore(stylesRef.current));
|
|
20387
|
+
return nodes;
|
|
20388
|
+
};
|
|
20255
20389
|
const handleHydrate = (e) => {
|
|
20256
20390
|
if (e.data?.type !== "ow:hydrate") return;
|
|
20257
20391
|
const content = e.data.content;
|
|
@@ -20320,6 +20454,11 @@ function OhhwellsBridge() {
|
|
|
20320
20454
|
reconcileFooterOrderFromContent(editContentRef.current);
|
|
20321
20455
|
syncNavigationDragCursorAttrs();
|
|
20322
20456
|
enforceLinkHrefs();
|
|
20457
|
+
const hydrateReapExclude = /* @__PURE__ */ new Set();
|
|
20458
|
+
const hydratePendingUndo = pendingDeleteUndoRef.current;
|
|
20459
|
+
if (hydratePendingUndo?.sectionInstanceId) hydrateReapExclude.add(hydratePendingUndo.sectionInstanceId);
|
|
20460
|
+
const reapNodes = reapCommittedAiSections(hydrateReapExclude);
|
|
20461
|
+
if (reapNodes.length > 0) postToParentRef.current({ type: "ow:change", nodes: reapNodes });
|
|
20323
20462
|
const hydratedHeight = document.body.scrollHeight;
|
|
20324
20463
|
if (hydratedHeight > 50) postToParentRef.current({ type: "ow:height", height: hydratedHeight });
|
|
20325
20464
|
postToParentRef.current({ type: "ow:hydrate-done" });
|
|
@@ -20504,8 +20643,11 @@ function OhhwellsBridge() {
|
|
|
20504
20643
|
if (!instanceId || !direction) return;
|
|
20505
20644
|
const entries = moveSectionInstance(instanceId, direction, window.location.pathname);
|
|
20506
20645
|
if (!entries) return;
|
|
20507
|
-
const orderJson = JSON.stringify(
|
|
20646
|
+
const orderJson = JSON.stringify(
|
|
20647
|
+
mergePageSectionOrder(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname, entries)
|
|
20648
|
+
);
|
|
20508
20649
|
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
20650
|
+
applyPersistedOrder(getPageSectionOrderEntries(orderJson, window.location.pathname));
|
|
20509
20651
|
setAiSectionOrder(orderJson, window.location.pathname);
|
|
20510
20652
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
20511
20653
|
window.dispatchEvent(new Event("resize"));
|
|
@@ -20551,8 +20693,11 @@ function OhhwellsBridge() {
|
|
|
20551
20693
|
const currentEntries = getPageSectionOrderEntries(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname);
|
|
20552
20694
|
const entries = deleteSectionInstance(instanceId, window.location.pathname, currentEntries);
|
|
20553
20695
|
if (!entries) return;
|
|
20554
|
-
const orderJson = JSON.stringify(
|
|
20696
|
+
const orderJson = JSON.stringify(
|
|
20697
|
+
mergePageSectionOrder(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname, entries)
|
|
20698
|
+
);
|
|
20555
20699
|
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
20700
|
+
setAiSectionOrder(orderJson, window.location.pathname);
|
|
20556
20701
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
20557
20702
|
aiSectionApiRef.current?.clear();
|
|
20558
20703
|
window.dispatchEvent(new Event("resize"));
|
|
@@ -20561,6 +20706,7 @@ function OhhwellsBridge() {
|
|
|
20561
20706
|
const actionId = newInstanceId();
|
|
20562
20707
|
pendingDeleteUndoRef.current = {
|
|
20563
20708
|
actionId,
|
|
20709
|
+
sectionInstanceId: instanceId,
|
|
20564
20710
|
restore: () => {
|
|
20565
20711
|
const restoredEntries = getPageSectionOrderEntries(
|
|
20566
20712
|
editContentRef.current[SECTION_ORDER_KEY],
|
|
@@ -20568,8 +20714,11 @@ function OhhwellsBridge() {
|
|
|
20568
20714
|
);
|
|
20569
20715
|
const restored = restoreSectionInstance(instanceId, window.location.pathname, restoredEntries);
|
|
20570
20716
|
if (!restored) return;
|
|
20571
|
-
const restoredJson = JSON.stringify(
|
|
20717
|
+
const restoredJson = JSON.stringify(
|
|
20718
|
+
mergePageSectionOrder(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname, restored)
|
|
20719
|
+
);
|
|
20572
20720
|
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: restoredJson };
|
|
20721
|
+
setAiSectionOrder(restoredJson, window.location.pathname);
|
|
20573
20722
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: restoredJson }] });
|
|
20574
20723
|
window.dispatchEvent(new Event("resize"));
|
|
20575
20724
|
const restoreHeight = document.body.scrollHeight;
|
|
@@ -20595,7 +20744,9 @@ function OhhwellsBridge() {
|
|
|
20595
20744
|
const result = duplicateSectionInstance(instanceId, newId, window.location.pathname, currentEntries);
|
|
20596
20745
|
if (!result) return;
|
|
20597
20746
|
const { entries, keyRekeys } = result;
|
|
20598
|
-
const orderJson = JSON.stringify(
|
|
20747
|
+
const orderJson = JSON.stringify(
|
|
20748
|
+
mergePageSectionOrder(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname, entries)
|
|
20749
|
+
);
|
|
20599
20750
|
const nodes = [{ key: SECTION_ORDER_KEY, text: orderJson }];
|
|
20600
20751
|
for (const { from, to } of keyRekeys) {
|
|
20601
20752
|
const inherited = editContentRef.current[from];
|
|
@@ -20605,6 +20756,7 @@ function OhhwellsBridge() {
|
|
|
20605
20756
|
...editContentRef.current,
|
|
20606
20757
|
...Object.fromEntries(nodes.map(({ key, text }) => [key, text]))
|
|
20607
20758
|
};
|
|
20759
|
+
applyPersistedOrder(getPageSectionOrderEntries(orderJson, window.location.pathname));
|
|
20608
20760
|
setAiSectionOrder(orderJson, window.location.pathname);
|
|
20609
20761
|
postToParentRef.current({ type: "ow:change", nodes });
|
|
20610
20762
|
window.dispatchEvent(new Event("resize"));
|
|
@@ -20868,6 +21020,10 @@ function OhhwellsBridge() {
|
|
|
20868
21020
|
};
|
|
20869
21021
|
const handleSave = (e) => {
|
|
20870
21022
|
if (e.data?.type !== "ow:save") return;
|
|
21023
|
+
const pendingUndo = pendingDeleteUndoRef.current;
|
|
21024
|
+
const reapExclude = /* @__PURE__ */ new Set();
|
|
21025
|
+
if (pendingUndo?.sectionInstanceId) reapExclude.add(pendingUndo.sectionInstanceId);
|
|
21026
|
+
const reapNodes = reapCommittedAiSections(reapExclude);
|
|
20871
21027
|
const nodes = collectEditableNodes(editContentRef.current);
|
|
20872
21028
|
const tracker = document.querySelector("[data-ohw-sections-tracker]");
|
|
20873
21029
|
if (tracker?.textContent) nodes.push({ key: "__ohw_sections", type: "sections", text: tracker.textContent });
|
|
@@ -20887,6 +21043,11 @@ function OhhwellsBridge() {
|
|
|
20887
21043
|
const text = specs.length ? JSON.stringify(specs) : editContentRef.current[fieldsKey(formKey)];
|
|
20888
21044
|
if (text) nodes.push({ key: fieldsKey(formKey), type: "text", text });
|
|
20889
21045
|
});
|
|
21046
|
+
for (const reapNode of reapNodes) {
|
|
21047
|
+
if (reapNode.key.startsWith(AI_SLOT_KEY_PREFIX) && !nodes.some((n) => n.key === reapNode.key)) {
|
|
21048
|
+
nodes.push({ key: reapNode.key, type: "text", text: reapNode.text });
|
|
21049
|
+
}
|
|
21050
|
+
}
|
|
20890
21051
|
postToParentRef.current({ type: "ow:save-result", nodes });
|
|
20891
21052
|
};
|
|
20892
21053
|
const handleInsertSection = (e) => {
|
|
@@ -21508,7 +21669,7 @@ function OhhwellsBridge() {
|
|
|
21508
21669
|
postToParent2({
|
|
21509
21670
|
type: "ow:ready",
|
|
21510
21671
|
version: "1",
|
|
21511
|
-
bridgeVersion: "0.1.
|
|
21672
|
+
bridgeVersion: "0.1.94",
|
|
21512
21673
|
path: pathname,
|
|
21513
21674
|
nodes: collectEditableNodes(editContentRef.current),
|
|
21514
21675
|
sections
|