@ohhwells/bridge 0.1.94 → 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 +379 -250
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +379 -250
- 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,7 @@ function applyAiSectionsToDom(state, options) {
|
|
|
2260
2555
|
syncReplacedOriginals(state);
|
|
2261
2556
|
syncRemovedSections(state);
|
|
2262
2557
|
syncTemplateHidden(state, pageSections.length > 0);
|
|
2558
|
+
syncSoftRemovedGenerated();
|
|
2263
2559
|
}
|
|
2264
2560
|
function unmountAllAiSections() {
|
|
2265
2561
|
for (const [, section] of mounted) {
|
|
@@ -2272,9 +2568,9 @@ function unmountAllAiSections() {
|
|
|
2272
2568
|
el.style.removeProperty("display");
|
|
2273
2569
|
el.removeAttribute(REPLACED_ATTR);
|
|
2274
2570
|
}
|
|
2275
|
-
for (const el of document.querySelectorAll(`[${
|
|
2571
|
+
for (const el of document.querySelectorAll(`[${REMOVED_ATTR2}]`)) {
|
|
2276
2572
|
el.style.removeProperty("display");
|
|
2277
|
-
el.removeAttribute(
|
|
2573
|
+
el.removeAttribute(REMOVED_ATTR2);
|
|
2278
2574
|
}
|
|
2279
2575
|
}
|
|
2280
2576
|
|
|
@@ -8235,240 +8531,6 @@ function CarouselOverlay({
|
|
|
8235
8531
|
// src/ui/ai-section/AiSectionOverlay.tsx
|
|
8236
8532
|
var import_react8 = require("react");
|
|
8237
8533
|
var import_lucide_react7 = require("lucide-react");
|
|
8238
|
-
|
|
8239
|
-
// src/lib/sections.ts
|
|
8240
|
-
var LINK_PICKER_EXCLUDED_IDS = /* @__PURE__ */ new Set(["navbar", "footer"]);
|
|
8241
|
-
function isChromeSection(el) {
|
|
8242
|
-
return el.matches("header, nav, footer, aside");
|
|
8243
|
-
}
|
|
8244
|
-
function titleCaseSectionId(id) {
|
|
8245
|
-
return id.split("-").filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
8246
|
-
}
|
|
8247
|
-
function parseSectionsFromRoot(root) {
|
|
8248
|
-
const seen = /* @__PURE__ */ new Set();
|
|
8249
|
-
const sections = [];
|
|
8250
|
-
for (const el of root.querySelectorAll("[data-ohw-section]")) {
|
|
8251
|
-
const id = el.getAttribute("data-ohw-section") ?? "";
|
|
8252
|
-
if (!id || seen.has(id) || LINK_PICKER_EXCLUDED_IDS.has(id)) continue;
|
|
8253
|
-
if (el.parentElement?.closest("[data-ohw-section]")) continue;
|
|
8254
|
-
if (el.hasAttribute("data-ohw-ai-template-hidden") || el.hasAttribute("data-ohw-ai-removed") || el.hasAttribute("data-ohw-ai-replaced-by"))
|
|
8255
|
-
continue;
|
|
8256
|
-
seen.add(id);
|
|
8257
|
-
const label = el.getAttribute("data-ohw-section-label") ?? titleCaseSectionId(id);
|
|
8258
|
-
sections.push({ id, label });
|
|
8259
|
-
}
|
|
8260
|
-
return sections;
|
|
8261
|
-
}
|
|
8262
|
-
function collectSectionsFromDom() {
|
|
8263
|
-
if (typeof document === "undefined") return [];
|
|
8264
|
-
return parseSectionsFromRoot(document);
|
|
8265
|
-
}
|
|
8266
|
-
function parseSectionsFromHtml(html) {
|
|
8267
|
-
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
8268
|
-
return parseSectionsFromRoot(doc);
|
|
8269
|
-
}
|
|
8270
|
-
|
|
8271
|
-
// src/lib/section-instances.ts
|
|
8272
|
-
var SECTION_ORDER_KEY = "__ohw_section_order";
|
|
8273
|
-
var REMOVED_ATTR2 = "data-ohw-section-removed";
|
|
8274
|
-
function isRemovedSection(el) {
|
|
8275
|
-
return el.hasAttribute(REMOVED_ATTR2);
|
|
8276
|
-
}
|
|
8277
|
-
function movableUnit(el) {
|
|
8278
|
-
return el.closest("[data-ohw-section-container]") ?? el;
|
|
8279
|
-
}
|
|
8280
|
-
function sectionTypeOf(el) {
|
|
8281
|
-
return el.getAttribute("data-ohw-section") ?? el.querySelector("[data-ohw-section]")?.getAttribute("data-ohw-section") ?? "";
|
|
8282
|
-
}
|
|
8283
|
-
function sectionElementOf(el) {
|
|
8284
|
-
return el.hasAttribute("data-ohw-section") ? el : el.querySelector("[data-ohw-section]") ?? el;
|
|
8285
|
-
}
|
|
8286
|
-
function collectTopLevelUnits(predicate) {
|
|
8287
|
-
const seen = /* @__PURE__ */ new Set();
|
|
8288
|
-
const result = [];
|
|
8289
|
-
document.querySelectorAll("[data-ohw-section]").forEach((el) => {
|
|
8290
|
-
if (!predicate(el)) return;
|
|
8291
|
-
const unit = movableUnit(el);
|
|
8292
|
-
if (unit.parentElement?.closest("[data-ohw-section],[data-ohw-section-container]")) return;
|
|
8293
|
-
if (seen.has(unit)) return;
|
|
8294
|
-
seen.add(unit);
|
|
8295
|
-
result.push(unit);
|
|
8296
|
-
});
|
|
8297
|
-
return result;
|
|
8298
|
-
}
|
|
8299
|
-
function topLevelSections() {
|
|
8300
|
-
return collectTopLevelUnits((el) => !isChromeSection(el) && !isRemovedSection(movableUnit(el)));
|
|
8301
|
-
}
|
|
8302
|
-
function instanceIdOf(el) {
|
|
8303
|
-
return el.dataset.ohwInstance ?? el.dataset.ohwSection ?? "";
|
|
8304
|
-
}
|
|
8305
|
-
function findByInstanceId(instanceId) {
|
|
8306
|
-
const escapedId = CSS.escape(instanceId);
|
|
8307
|
-
const direct = document.querySelector(`[data-ohw-instance="${escapedId}"]`);
|
|
8308
|
-
if (direct) return movableUnit(direct);
|
|
8309
|
-
const bare = document.querySelector(`[data-ohw-section="${escapedId}"]:not([data-ohw-instance])`);
|
|
8310
|
-
return bare ? movableUnit(bare) : null;
|
|
8311
|
-
}
|
|
8312
|
-
function planSectionMove(instanceId, targetIndex, currentPath) {
|
|
8313
|
-
const sections = topLevelSections();
|
|
8314
|
-
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
8315
|
-
if (index === -1) return null;
|
|
8316
|
-
const dragged = sections[index];
|
|
8317
|
-
const others = sections.filter((_, i) => i !== index);
|
|
8318
|
-
const clamped = Math.max(0, Math.min(targetIndex, others.length));
|
|
8319
|
-
const reordered = [...others.slice(0, clamped), dragged, ...others.slice(clamped)];
|
|
8320
|
-
return reordered.map((el, order) => ({
|
|
8321
|
-
instanceId: instanceIdOf(el),
|
|
8322
|
-
type: sectionTypeOf(el),
|
|
8323
|
-
order,
|
|
8324
|
-
pagePath: currentPath
|
|
8325
|
-
}));
|
|
8326
|
-
}
|
|
8327
|
-
function moveSectionInstance(instanceId, direction, currentPath) {
|
|
8328
|
-
const sections = topLevelSections();
|
|
8329
|
-
const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
|
|
8330
|
-
if (index === -1) return null;
|
|
8331
|
-
const siblingIndex = direction === "up" ? index - 1 : index + 1;
|
|
8332
|
-
if (siblingIndex < 0 || siblingIndex >= sections.length) return null;
|
|
8333
|
-
const entries = planSectionMove(instanceId, siblingIndex, currentPath);
|
|
8334
|
-
if (!entries) return null;
|
|
8335
|
-
applyPersistedOrder(entries);
|
|
8336
|
-
return entries;
|
|
8337
|
-
}
|
|
8338
|
-
function syncRemovedFlags(entries) {
|
|
8339
|
-
const removedIds = new Set(entries.filter((e) => e.removed).map((e) => e.instanceId));
|
|
8340
|
-
document.querySelectorAll(`[${REMOVED_ATTR2}]`).forEach((el) => {
|
|
8341
|
-
if (!removedIds.has(instanceIdOf(el))) {
|
|
8342
|
-
el.style.removeProperty("display");
|
|
8343
|
-
el.removeAttribute(REMOVED_ATTR2);
|
|
8344
|
-
}
|
|
8345
|
-
});
|
|
8346
|
-
for (const id of removedIds) {
|
|
8347
|
-
const el = findByInstanceId(id);
|
|
8348
|
-
if (el) {
|
|
8349
|
-
el.style.display = "none";
|
|
8350
|
-
el.setAttribute(REMOVED_ATTR2, "");
|
|
8351
|
-
}
|
|
8352
|
-
}
|
|
8353
|
-
}
|
|
8354
|
-
function applyPersistedOrder(entries) {
|
|
8355
|
-
syncRemovedFlags(entries);
|
|
8356
|
-
if (entries.length === 0) return;
|
|
8357
|
-
const sections = topLevelSections();
|
|
8358
|
-
if (sections.length === 0) return;
|
|
8359
|
-
const orderIndex = new Map(entries.map((e) => [e.instanceId, e.order]));
|
|
8360
|
-
const ordered = [...sections].sort((a, b) => {
|
|
8361
|
-
const aOrder = orderIndex.get(instanceIdOf(a));
|
|
8362
|
-
const bOrder = orderIndex.get(instanceIdOf(b));
|
|
8363
|
-
if (aOrder === void 0 && bOrder === void 0) return 0;
|
|
8364
|
-
if (aOrder === void 0) return 1;
|
|
8365
|
-
if (bOrder === void 0) return -1;
|
|
8366
|
-
return aOrder - bOrder;
|
|
8367
|
-
});
|
|
8368
|
-
let prev = null;
|
|
8369
|
-
for (const el of ordered) {
|
|
8370
|
-
if (prev) prev.after(el);
|
|
8371
|
-
prev = el;
|
|
8372
|
-
}
|
|
8373
|
-
}
|
|
8374
|
-
function setSectionRemoved(instanceId, currentPath, existingEntries, removed) {
|
|
8375
|
-
if (!findByInstanceId(instanceId)) return null;
|
|
8376
|
-
const byId = new Map(existingEntries.map((e) => [e.instanceId, e]));
|
|
8377
|
-
const allSections = collectTopLevelUnits((el) => !isChromeSection(el));
|
|
8378
|
-
allSections.forEach((el, order) => {
|
|
8379
|
-
const id = instanceIdOf(el);
|
|
8380
|
-
if (!byId.has(id)) {
|
|
8381
|
-
byId.set(id, { instanceId: id, type: sectionTypeOf(el), order, pagePath: currentPath });
|
|
8382
|
-
}
|
|
8383
|
-
});
|
|
8384
|
-
const target = byId.get(instanceId);
|
|
8385
|
-
if (!target) return null;
|
|
8386
|
-
byId.set(instanceId, { ...target, removed });
|
|
8387
|
-
const entries = Array.from(byId.values());
|
|
8388
|
-
applyPersistedOrder(entries);
|
|
8389
|
-
return entries;
|
|
8390
|
-
}
|
|
8391
|
-
function deleteSectionInstance(instanceId, currentPath, existingEntries) {
|
|
8392
|
-
return setSectionRemoved(instanceId, currentPath, existingEntries, true);
|
|
8393
|
-
}
|
|
8394
|
-
function restoreSectionInstance(instanceId, currentPath, existingEntries) {
|
|
8395
|
-
return setSectionRemoved(instanceId, currentPath, existingEntries, false);
|
|
8396
|
-
}
|
|
8397
|
-
function duplicateSectionInstance(instanceId, newId, currentPath, existingEntries) {
|
|
8398
|
-
const original = findByInstanceId(instanceId);
|
|
8399
|
-
if (!original) return null;
|
|
8400
|
-
const clone = original.cloneNode(true);
|
|
8401
|
-
clone.setAttribute("data-ohw-instance", newId);
|
|
8402
|
-
const keyRekeys = rekeySectionSubtree(clone, newId);
|
|
8403
|
-
original.insertAdjacentElement("afterend", clone);
|
|
8404
|
-
const byId = new Map(existingEntries.map((e) => [e.instanceId, e]));
|
|
8405
|
-
const entries = topLevelSections().map((el, order) => {
|
|
8406
|
-
const id = instanceIdOf(el);
|
|
8407
|
-
return {
|
|
8408
|
-
instanceId: id,
|
|
8409
|
-
type: sectionTypeOf(el),
|
|
8410
|
-
order,
|
|
8411
|
-
pagePath: currentPath,
|
|
8412
|
-
...byId.get(id)?.removed ? { removed: true } : {}
|
|
8413
|
-
};
|
|
8414
|
-
});
|
|
8415
|
-
applyPersistedOrder(entries);
|
|
8416
|
-
return { entries, keyRekeys };
|
|
8417
|
-
}
|
|
8418
|
-
function newInstanceId() {
|
|
8419
|
-
return typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `instance-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
8420
|
-
}
|
|
8421
|
-
function getPageSectionOrderEntries(raw, currentPath) {
|
|
8422
|
-
if (!raw) return [];
|
|
8423
|
-
try {
|
|
8424
|
-
const entries = JSON.parse(raw);
|
|
8425
|
-
return entries.filter((e) => !e.pagePath || e.pagePath === currentPath);
|
|
8426
|
-
} catch {
|
|
8427
|
-
return [];
|
|
8428
|
-
}
|
|
8429
|
-
}
|
|
8430
|
-
function rekeySectionSubtree(root, instanceId) {
|
|
8431
|
-
const suffix = `::${instanceId}`;
|
|
8432
|
-
const pairs = [];
|
|
8433
|
-
const rekey = (el, attr) => {
|
|
8434
|
-
const current = el.getAttribute(attr);
|
|
8435
|
-
if (!current) return;
|
|
8436
|
-
const base = current.includes("::") ? current.slice(0, current.indexOf("::")) : current;
|
|
8437
|
-
const next = `${base}${suffix}`;
|
|
8438
|
-
el.setAttribute(attr, next);
|
|
8439
|
-
pairs.push({ from: current, to: next });
|
|
8440
|
-
};
|
|
8441
|
-
if (root.hasAttribute("data-ohw-key")) rekey(root, "data-ohw-key");
|
|
8442
|
-
if (root.hasAttribute("data-ohw-href-key")) rekey(root, "data-ohw-href-key");
|
|
8443
|
-
root.querySelectorAll("[data-ohw-key]").forEach((el) => rekey(el, "data-ohw-key"));
|
|
8444
|
-
root.querySelectorAll("[data-ohw-href-key]").forEach((el) => rekey(el, "data-ohw-href-key"));
|
|
8445
|
-
return pairs;
|
|
8446
|
-
}
|
|
8447
|
-
function initSectionInstancesFromContent(content, currentPath) {
|
|
8448
|
-
document.querySelectorAll("[data-ohw-section]:not([data-ohw-instance])").forEach((el) => {
|
|
8449
|
-
el.setAttribute("data-ohw-instance", el.getAttribute("data-ohw-section") ?? "");
|
|
8450
|
-
});
|
|
8451
|
-
document.querySelectorAll("[data-ohw-section-container]:not([data-ohw-instance])").forEach((el) => {
|
|
8452
|
-
const type = sectionTypeOf(el);
|
|
8453
|
-
if (type) el.setAttribute("data-ohw-instance", type);
|
|
8454
|
-
});
|
|
8455
|
-
const entries = getPageSectionOrderEntries(content[SECTION_ORDER_KEY], currentPath);
|
|
8456
|
-
for (const entry of entries) {
|
|
8457
|
-
if (entry.instanceId === entry.type) continue;
|
|
8458
|
-
if (document.querySelector(`[data-ohw-instance="${CSS.escape(entry.instanceId)}"]`)) continue;
|
|
8459
|
-
const original = document.querySelector(
|
|
8460
|
-
`[data-ohw-section="${CSS.escape(entry.type)}"][data-ohw-instance="${CSS.escape(entry.type)}"]`
|
|
8461
|
-
);
|
|
8462
|
-
if (!original) continue;
|
|
8463
|
-
const clone = original.cloneNode(true);
|
|
8464
|
-
clone.setAttribute("data-ohw-instance", entry.instanceId);
|
|
8465
|
-
rekeySectionSubtree(clone, entry.instanceId);
|
|
8466
|
-
original.insertAdjacentElement("afterend", clone);
|
|
8467
|
-
}
|
|
8468
|
-
applyPersistedOrder(entries);
|
|
8469
|
-
}
|
|
8470
|
-
|
|
8471
|
-
// src/ui/ai-section/AiSectionOverlay.tsx
|
|
8472
8534
|
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
8473
8535
|
var findSectionElement = findByInstanceId;
|
|
8474
8536
|
function readRect(instanceId) {
|
|
@@ -14251,15 +14313,17 @@ function useSectionDrag({
|
|
|
14251
14313
|
clearSectionDragVisuals();
|
|
14252
14314
|
return;
|
|
14253
14315
|
}
|
|
14254
|
-
const orderJson = JSON.stringify(
|
|
14316
|
+
const orderJson = JSON.stringify(
|
|
14317
|
+
mergePageSectionOrder(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname, entries)
|
|
14318
|
+
);
|
|
14255
14319
|
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
14256
14320
|
setAiSectionOrder(orderJson, window.location.pathname);
|
|
14257
14321
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
14258
|
-
applyPersistedOrder(
|
|
14322
|
+
applyPersistedOrder(getPageSectionOrderEntries(orderJson, window.location.pathname));
|
|
14259
14323
|
clearSectionDragVisuals();
|
|
14260
14324
|
requestAnimationFrame(() => {
|
|
14261
14325
|
if (editContentRef.current[SECTION_ORDER_KEY] === orderJson) {
|
|
14262
|
-
applyPersistedOrder(
|
|
14326
|
+
applyPersistedOrder(getPageSectionOrderEntries(orderJson, window.location.pathname));
|
|
14263
14327
|
}
|
|
14264
14328
|
requestAnimationFrame(() => {
|
|
14265
14329
|
window.dispatchEvent(new Event("resize"));
|
|
@@ -20284,6 +20348,44 @@ function OhhwellsBridge() {
|
|
|
20284
20348
|
if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
|
|
20285
20349
|
}, 400));
|
|
20286
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
|
+
};
|
|
20287
20389
|
const handleHydrate = (e) => {
|
|
20288
20390
|
if (e.data?.type !== "ow:hydrate") return;
|
|
20289
20391
|
const content = e.data.content;
|
|
@@ -20352,6 +20454,11 @@ function OhhwellsBridge() {
|
|
|
20352
20454
|
reconcileFooterOrderFromContent(editContentRef.current);
|
|
20353
20455
|
syncNavigationDragCursorAttrs();
|
|
20354
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 });
|
|
20355
20462
|
const hydratedHeight = document.body.scrollHeight;
|
|
20356
20463
|
if (hydratedHeight > 50) postToParentRef.current({ type: "ow:height", height: hydratedHeight });
|
|
20357
20464
|
postToParentRef.current({ type: "ow:hydrate-done" });
|
|
@@ -20536,8 +20643,11 @@ function OhhwellsBridge() {
|
|
|
20536
20643
|
if (!instanceId || !direction) return;
|
|
20537
20644
|
const entries = moveSectionInstance(instanceId, direction, window.location.pathname);
|
|
20538
20645
|
if (!entries) return;
|
|
20539
|
-
const orderJson = JSON.stringify(
|
|
20646
|
+
const orderJson = JSON.stringify(
|
|
20647
|
+
mergePageSectionOrder(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname, entries)
|
|
20648
|
+
);
|
|
20540
20649
|
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
20650
|
+
applyPersistedOrder(getPageSectionOrderEntries(orderJson, window.location.pathname));
|
|
20541
20651
|
setAiSectionOrder(orderJson, window.location.pathname);
|
|
20542
20652
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
20543
20653
|
window.dispatchEvent(new Event("resize"));
|
|
@@ -20583,8 +20693,11 @@ function OhhwellsBridge() {
|
|
|
20583
20693
|
const currentEntries = getPageSectionOrderEntries(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname);
|
|
20584
20694
|
const entries = deleteSectionInstance(instanceId, window.location.pathname, currentEntries);
|
|
20585
20695
|
if (!entries) return;
|
|
20586
|
-
const orderJson = JSON.stringify(
|
|
20696
|
+
const orderJson = JSON.stringify(
|
|
20697
|
+
mergePageSectionOrder(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname, entries)
|
|
20698
|
+
);
|
|
20587
20699
|
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
|
|
20700
|
+
setAiSectionOrder(orderJson, window.location.pathname);
|
|
20588
20701
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
|
|
20589
20702
|
aiSectionApiRef.current?.clear();
|
|
20590
20703
|
window.dispatchEvent(new Event("resize"));
|
|
@@ -20593,6 +20706,7 @@ function OhhwellsBridge() {
|
|
|
20593
20706
|
const actionId = newInstanceId();
|
|
20594
20707
|
pendingDeleteUndoRef.current = {
|
|
20595
20708
|
actionId,
|
|
20709
|
+
sectionInstanceId: instanceId,
|
|
20596
20710
|
restore: () => {
|
|
20597
20711
|
const restoredEntries = getPageSectionOrderEntries(
|
|
20598
20712
|
editContentRef.current[SECTION_ORDER_KEY],
|
|
@@ -20600,8 +20714,11 @@ function OhhwellsBridge() {
|
|
|
20600
20714
|
);
|
|
20601
20715
|
const restored = restoreSectionInstance(instanceId, window.location.pathname, restoredEntries);
|
|
20602
20716
|
if (!restored) return;
|
|
20603
|
-
const restoredJson = JSON.stringify(
|
|
20717
|
+
const restoredJson = JSON.stringify(
|
|
20718
|
+
mergePageSectionOrder(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname, restored)
|
|
20719
|
+
);
|
|
20604
20720
|
editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: restoredJson };
|
|
20721
|
+
setAiSectionOrder(restoredJson, window.location.pathname);
|
|
20605
20722
|
postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: restoredJson }] });
|
|
20606
20723
|
window.dispatchEvent(new Event("resize"));
|
|
20607
20724
|
const restoreHeight = document.body.scrollHeight;
|
|
@@ -20627,7 +20744,9 @@ function OhhwellsBridge() {
|
|
|
20627
20744
|
const result = duplicateSectionInstance(instanceId, newId, window.location.pathname, currentEntries);
|
|
20628
20745
|
if (!result) return;
|
|
20629
20746
|
const { entries, keyRekeys } = result;
|
|
20630
|
-
const orderJson = JSON.stringify(
|
|
20747
|
+
const orderJson = JSON.stringify(
|
|
20748
|
+
mergePageSectionOrder(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname, entries)
|
|
20749
|
+
);
|
|
20631
20750
|
const nodes = [{ key: SECTION_ORDER_KEY, text: orderJson }];
|
|
20632
20751
|
for (const { from, to } of keyRekeys) {
|
|
20633
20752
|
const inherited = editContentRef.current[from];
|
|
@@ -20637,6 +20756,7 @@ function OhhwellsBridge() {
|
|
|
20637
20756
|
...editContentRef.current,
|
|
20638
20757
|
...Object.fromEntries(nodes.map(({ key, text }) => [key, text]))
|
|
20639
20758
|
};
|
|
20759
|
+
applyPersistedOrder(getPageSectionOrderEntries(orderJson, window.location.pathname));
|
|
20640
20760
|
setAiSectionOrder(orderJson, window.location.pathname);
|
|
20641
20761
|
postToParentRef.current({ type: "ow:change", nodes });
|
|
20642
20762
|
window.dispatchEvent(new Event("resize"));
|
|
@@ -20900,6 +21020,10 @@ function OhhwellsBridge() {
|
|
|
20900
21020
|
};
|
|
20901
21021
|
const handleSave = (e) => {
|
|
20902
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);
|
|
20903
21027
|
const nodes = collectEditableNodes(editContentRef.current);
|
|
20904
21028
|
const tracker = document.querySelector("[data-ohw-sections-tracker]");
|
|
20905
21029
|
if (tracker?.textContent) nodes.push({ key: "__ohw_sections", type: "sections", text: tracker.textContent });
|
|
@@ -20919,6 +21043,11 @@ function OhhwellsBridge() {
|
|
|
20919
21043
|
const text = specs.length ? JSON.stringify(specs) : editContentRef.current[fieldsKey(formKey)];
|
|
20920
21044
|
if (text) nodes.push({ key: fieldsKey(formKey), type: "text", text });
|
|
20921
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
|
+
}
|
|
20922
21051
|
postToParentRef.current({ type: "ow:save-result", nodes });
|
|
20923
21052
|
};
|
|
20924
21053
|
const handleInsertSection = (e) => {
|
|
@@ -21540,7 +21669,7 @@ function OhhwellsBridge() {
|
|
|
21540
21669
|
postToParent2({
|
|
21541
21670
|
type: "ow:ready",
|
|
21542
21671
|
version: "1",
|
|
21543
|
-
bridgeVersion: "0.1.
|
|
21672
|
+
bridgeVersion: "0.1.94",
|
|
21544
21673
|
path: pathname,
|
|
21545
21674
|
nodes: collectEditableNodes(editContentRef.current),
|
|
21546
21675
|
sections
|