@ohhwells/bridge 0.1.104 → 0.1.106
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 +246 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +246 -40
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -10984,9 +10984,18 @@ function getNavbarDrawerContainer() {
|
|
|
10984
10984
|
}
|
|
10985
10985
|
function isNavbarListContainerVisible(el) {
|
|
10986
10986
|
if (el.hasAttribute("hidden")) return false;
|
|
10987
|
+
if (el.closest("[hidden]")) return false;
|
|
10987
10988
|
if (el.getClientRects().length === 0) return false;
|
|
10988
10989
|
const style = window.getComputedStyle(el);
|
|
10989
|
-
|
|
10990
|
+
if (style.display === "none" || style.visibility === "hidden") return false;
|
|
10991
|
+
let parent = el.parentElement;
|
|
10992
|
+
while (parent && parent !== document.documentElement) {
|
|
10993
|
+
if (parent.hasAttribute("hidden")) return false;
|
|
10994
|
+
const ps = window.getComputedStyle(parent);
|
|
10995
|
+
if (ps.display === "none" || ps.visibility === "hidden") return false;
|
|
10996
|
+
parent = parent.parentElement;
|
|
10997
|
+
}
|
|
10998
|
+
return true;
|
|
10990
10999
|
}
|
|
10991
11000
|
function getActiveNavbarListContainer(draggedEl) {
|
|
10992
11001
|
const desktop = getNavbarDesktopContainer();
|
|
@@ -10997,6 +11006,7 @@ function getActiveNavbarListContainer(draggedEl) {
|
|
|
10997
11006
|
}
|
|
10998
11007
|
if (desktop && isNavbarListContainerVisible(desktop)) return desktop;
|
|
10999
11008
|
if (drawer && isNavbarListContainerVisible(drawer)) return drawer;
|
|
11009
|
+
if (drawer && !drawer.closest("[hidden]")) return drawer;
|
|
11000
11010
|
return desktop ?? drawer;
|
|
11001
11011
|
}
|
|
11002
11012
|
function listActiveNavbarItems(draggedEl) {
|
|
@@ -11009,6 +11019,12 @@ function listActiveNavbarItems(draggedEl) {
|
|
|
11009
11019
|
return listNavbarItems();
|
|
11010
11020
|
}
|
|
11011
11021
|
function listNavbarItems() {
|
|
11022
|
+
const active = getActiveNavbarListContainer();
|
|
11023
|
+
if (active) {
|
|
11024
|
+
return Array.from(active.querySelectorAll("[data-ohw-href-key]")).filter(
|
|
11025
|
+
isNavbarLinkItem
|
|
11026
|
+
);
|
|
11027
|
+
}
|
|
11012
11028
|
const desktop = getNavbarDesktopContainer();
|
|
11013
11029
|
if (desktop) {
|
|
11014
11030
|
return Array.from(desktop.querySelectorAll("[data-ohw-href-key]")).filter(isNavbarLinkItem);
|
|
@@ -11078,24 +11094,25 @@ function buildNavLink(index, href, label, template) {
|
|
|
11078
11094
|
return anchor;
|
|
11079
11095
|
}
|
|
11080
11096
|
function insertNavLinkInContainer(container, anchor, afterHrefKey) {
|
|
11097
|
+
const listParent = resolveNavbarReorderParent(container);
|
|
11081
11098
|
if (!afterHrefKey) {
|
|
11082
|
-
const cta =
|
|
11083
|
-
if (cta && cta.parentElement ===
|
|
11084
|
-
|
|
11099
|
+
const cta = listParent.querySelector(CTA_BUTTON_SELECTOR);
|
|
11100
|
+
if (cta && cta.parentElement === listParent) {
|
|
11101
|
+
listParent.insertBefore(anchor, cta);
|
|
11085
11102
|
return;
|
|
11086
11103
|
}
|
|
11087
|
-
|
|
11104
|
+
listParent.appendChild(anchor);
|
|
11088
11105
|
return;
|
|
11089
11106
|
}
|
|
11090
|
-
const afterEl = findCounterpartByHrefKey(afterHrefKey,
|
|
11107
|
+
const afterEl = findCounterpartByHrefKey(afterHrefKey, listParent);
|
|
11091
11108
|
if (afterEl) {
|
|
11092
11109
|
const insertAfter = resolveNavRootUnit(afterEl);
|
|
11093
|
-
if (insertAfter.parentElement ===
|
|
11110
|
+
if (insertAfter.parentElement === listParent || insertAfter.parentElement === afterEl.parentElement) {
|
|
11094
11111
|
insertAfter.insertAdjacentElement("afterend", anchor);
|
|
11095
11112
|
return;
|
|
11096
11113
|
}
|
|
11097
11114
|
}
|
|
11098
|
-
|
|
11115
|
+
listParent.appendChild(anchor);
|
|
11099
11116
|
}
|
|
11100
11117
|
function insertNavbarItemDom(index, href, label, afterAnchor) {
|
|
11101
11118
|
const afterHrefKey = afterAnchor?.getAttribute("data-ohw-href-key") ?? null;
|
|
@@ -11151,15 +11168,25 @@ function getNavbarRootUnitsInContainer(container) {
|
|
|
11151
11168
|
}
|
|
11152
11169
|
return result;
|
|
11153
11170
|
}
|
|
11171
|
+
function resolveNavbarReorderParent(container) {
|
|
11172
|
+
if (getNavbarRootUnitsInContainer(container).length > 0) return container;
|
|
11173
|
+
for (const child of Array.from(container.children)) {
|
|
11174
|
+
if (!(child instanceof HTMLElement)) continue;
|
|
11175
|
+
if (child.hasAttribute("data-ohw-nav-dropdown-template")) continue;
|
|
11176
|
+
if (getNavbarRootUnitsInContainer(child).length > 0) return child;
|
|
11177
|
+
}
|
|
11178
|
+
return container;
|
|
11179
|
+
}
|
|
11154
11180
|
function applyNavOrderToContainer(container, order) {
|
|
11181
|
+
const listParent = resolveNavbarReorderParent(container);
|
|
11155
11182
|
const desired = order.filter((key, i) => order.indexOf(key) === i);
|
|
11156
|
-
const units = getNavbarRootUnitsInContainer(
|
|
11183
|
+
const units = getNavbarRootUnitsInContainer(listParent);
|
|
11157
11184
|
const current = units.map((u) => u.key);
|
|
11158
11185
|
const extras = current.filter((key) => !desired.includes(key));
|
|
11159
11186
|
const expected = [...desired.filter((key) => current.includes(key)), ...extras];
|
|
11160
11187
|
if (navOrderKeysEqual(current, expected)) return;
|
|
11161
11188
|
const lastUnit = units[units.length - 1]?.unit ?? null;
|
|
11162
|
-
const anchor = lastUnit?.parentElement ===
|
|
11189
|
+
const anchor = lastUnit?.parentElement === listParent ? lastUnit.nextElementSibling : null;
|
|
11163
11190
|
const orderedUnits = [];
|
|
11164
11191
|
const seen = /* @__PURE__ */ new Set();
|
|
11165
11192
|
for (const hrefKey of desired) {
|
|
@@ -11174,9 +11201,9 @@ function applyNavOrderToContainer(container, order) {
|
|
|
11174
11201
|
}
|
|
11175
11202
|
for (const el of orderedUnits) {
|
|
11176
11203
|
if (anchor) {
|
|
11177
|
-
if (el.nextSibling !== anchor)
|
|
11178
|
-
} else if (
|
|
11179
|
-
|
|
11204
|
+
if (el.nextSibling !== anchor) listParent.insertBefore(el, anchor);
|
|
11205
|
+
} else if (listParent.lastElementChild !== el) {
|
|
11206
|
+
listParent.appendChild(el);
|
|
11180
11207
|
}
|
|
11181
11208
|
}
|
|
11182
11209
|
}
|
|
@@ -12766,26 +12793,48 @@ function resolveFooterColumnForAdd(selected) {
|
|
|
12766
12793
|
if (selected.hasAttribute("data-ohw-footer-col")) return selected;
|
|
12767
12794
|
return selected.closest("[data-ohw-footer-col]") ?? (listFooterColumns().includes(selected) ? selected : null);
|
|
12768
12795
|
}
|
|
12769
|
-
function buildFooterHeading(colIndex, text) {
|
|
12770
|
-
const heading = document.createElement("p");
|
|
12771
|
-
heading.setAttribute("data-ohw-editable", "text");
|
|
12772
|
-
heading.setAttribute("data-ohw-key", `footer-${colIndex}-heading`);
|
|
12773
|
-
heading.textContent = text;
|
|
12774
|
-
heading.style.cssText = [
|
|
12775
|
-
"color: var(--espresso, #3d312b)",
|
|
12776
|
-
"font-size: 14px",
|
|
12777
|
-
"font-weight: 800",
|
|
12778
|
-
"opacity: 0.82",
|
|
12779
|
-
"margin: 0 0 6px",
|
|
12780
|
-
"padding: 0",
|
|
12781
|
-
"line-height: 1.2"
|
|
12782
|
-
].join(";");
|
|
12783
|
-
return heading;
|
|
12784
|
-
}
|
|
12785
12796
|
var FOOTER_HEADING_CACHE_ATTR = "data-ohw-heading-cache";
|
|
12797
|
+
var FOOTER_HEADING_CLASS_CACHE_ATTR = "data-ohw-heading-class";
|
|
12786
12798
|
function getFooterColumnHeadingEl(column) {
|
|
12787
12799
|
return column.querySelector('[data-ohw-key^="footer-"][data-ohw-key$="-heading"]') ?? null;
|
|
12788
12800
|
}
|
|
12801
|
+
function getFooterHeadingTemplate(excludeColumn) {
|
|
12802
|
+
for (const col of listFooterColumns()) {
|
|
12803
|
+
if (excludeColumn && col === excludeColumn) continue;
|
|
12804
|
+
const heading = getFooterColumnHeadingEl(col);
|
|
12805
|
+
if (heading) return heading;
|
|
12806
|
+
}
|
|
12807
|
+
return null;
|
|
12808
|
+
}
|
|
12809
|
+
function footerHeadingLooksLikeHtml(value) {
|
|
12810
|
+
return /<[a-z][\s\S]*>/i.test(value);
|
|
12811
|
+
}
|
|
12812
|
+
function applyFooterHeadingContent(el, value) {
|
|
12813
|
+
if (footerHeadingLooksLikeHtml(value)) {
|
|
12814
|
+
if (el.innerHTML !== value) el.innerHTML = value;
|
|
12815
|
+
return;
|
|
12816
|
+
}
|
|
12817
|
+
const plain = (el.textContent ?? "").trim();
|
|
12818
|
+
if (plain !== value.trim() || footerHeadingLooksLikeHtml(el.innerHTML)) {
|
|
12819
|
+
el.textContent = value;
|
|
12820
|
+
}
|
|
12821
|
+
}
|
|
12822
|
+
function buildFooterHeading(colIndex, text, opts) {
|
|
12823
|
+
const column = opts?.column ?? null;
|
|
12824
|
+
const template = opts?.template ?? getFooterHeadingTemplate(column) ?? null;
|
|
12825
|
+
const tagName = template?.tagName?.toLowerCase() || "p";
|
|
12826
|
+
const heading = document.createElement(tagName);
|
|
12827
|
+
heading.setAttribute("data-ohw-editable", "text");
|
|
12828
|
+
heading.setAttribute("data-ohw-key", `footer-${colIndex}-heading`);
|
|
12829
|
+
applyFooterHeadingContent(heading, text);
|
|
12830
|
+
const cachedClass = column?.getAttribute(FOOTER_HEADING_CLASS_CACHE_ATTR);
|
|
12831
|
+
if (template?.className) {
|
|
12832
|
+
heading.className = template.className;
|
|
12833
|
+
} else if (cachedClass) {
|
|
12834
|
+
heading.className = cachedClass;
|
|
12835
|
+
}
|
|
12836
|
+
return heading;
|
|
12837
|
+
}
|
|
12789
12838
|
function getFooterColumnHeadingKey(column) {
|
|
12790
12839
|
const attr = column.getAttribute("data-ohw-footer-col");
|
|
12791
12840
|
if (attr != null) {
|
|
@@ -12809,8 +12858,11 @@ function setFooterColumnHeadingVisible(column, visible) {
|
|
|
12809
12858
|
if (!Number.isFinite(colIndex)) return null;
|
|
12810
12859
|
const existing = getFooterColumnHeadingEl(column);
|
|
12811
12860
|
if (!visible) {
|
|
12812
|
-
const text2 = (existing
|
|
12861
|
+
const text2 = (existing ? existing.innerHTML.trim() || (existing.textContent ?? "").trim() : "") || column.getAttribute(FOOTER_HEADING_CACHE_ATTR) || DEFAULT_FOOTER_COLUMN_HEADING;
|
|
12813
12862
|
column.setAttribute(FOOTER_HEADING_CACHE_ATTR, text2);
|
|
12863
|
+
if (existing?.className) {
|
|
12864
|
+
column.setAttribute(FOOTER_HEADING_CLASS_CACHE_ATTR, existing.className);
|
|
12865
|
+
}
|
|
12814
12866
|
existing?.remove();
|
|
12815
12867
|
return { headingKey, text: "", visible: false };
|
|
12816
12868
|
}
|
|
@@ -12822,7 +12874,7 @@ function setFooterColumnHeadingVisible(column, visible) {
|
|
|
12822
12874
|
};
|
|
12823
12875
|
}
|
|
12824
12876
|
const text = column.getAttribute(FOOTER_HEADING_CACHE_ATTR) || DEFAULT_FOOTER_COLUMN_HEADING;
|
|
12825
|
-
const heading = buildFooterHeading(colIndex, text);
|
|
12877
|
+
const heading = buildFooterHeading(colIndex, text, { column });
|
|
12826
12878
|
const firstLink = listFooterLinksInColumn(column)[0];
|
|
12827
12879
|
if (firstLink) column.insertBefore(heading, firstLink);
|
|
12828
12880
|
else column.prepend(heading);
|
|
@@ -12846,21 +12898,24 @@ function reconcileFooterHeadingVisibility(content) {
|
|
|
12846
12898
|
if (raw === "") {
|
|
12847
12899
|
const existing2 = getFooterColumnHeadingEl(column);
|
|
12848
12900
|
if (existing2) {
|
|
12849
|
-
const cached = (existing2.textContent ?? "").trim();
|
|
12901
|
+
const cached = existing2.innerHTML.trim() || (existing2.textContent ?? "").trim();
|
|
12850
12902
|
if (cached) column.setAttribute(FOOTER_HEADING_CACHE_ATTR, cached);
|
|
12903
|
+
if (existing2.className) {
|
|
12904
|
+
column.setAttribute(FOOTER_HEADING_CLASS_CACHE_ATTR, existing2.className);
|
|
12905
|
+
}
|
|
12851
12906
|
existing2.remove();
|
|
12852
12907
|
}
|
|
12853
12908
|
continue;
|
|
12854
12909
|
}
|
|
12855
12910
|
const existing = getFooterColumnHeadingEl(column);
|
|
12856
12911
|
if (existing) {
|
|
12857
|
-
|
|
12912
|
+
applyFooterHeadingContent(existing, raw);
|
|
12858
12913
|
continue;
|
|
12859
12914
|
}
|
|
12860
12915
|
const colMatch = headingKey.match(FOOTER_HEADING_RE);
|
|
12861
12916
|
const colIndex = colMatch ? parseInt(colMatch[1], 10) : NaN;
|
|
12862
12917
|
if (!Number.isFinite(colIndex)) continue;
|
|
12863
|
-
const heading = buildFooterHeading(colIndex, raw);
|
|
12918
|
+
const heading = buildFooterHeading(colIndex, raw, { column });
|
|
12864
12919
|
const firstLink = listFooterLinksInColumn(column)[0];
|
|
12865
12920
|
if (firstLink) column.insertBefore(heading, firstLink);
|
|
12866
12921
|
else column.prepend(heading);
|
|
@@ -12906,9 +12961,13 @@ function insertFooterColumnDom(colIndex, heading, items) {
|
|
|
12906
12961
|
column.style.flexDirection = "column";
|
|
12907
12962
|
}
|
|
12908
12963
|
if (heading != null && heading !== "") {
|
|
12909
|
-
column.appendChild(buildFooterHeading(colIndex, heading));
|
|
12964
|
+
column.appendChild(buildFooterHeading(colIndex, heading, { column }));
|
|
12910
12965
|
} else if (heading === "") {
|
|
12911
12966
|
column.setAttribute(FOOTER_HEADING_CACHE_ATTR, DEFAULT_FOOTER_COLUMN_HEADING);
|
|
12967
|
+
const classFromSibling = getFooterHeadingTemplate()?.className;
|
|
12968
|
+
if (classFromSibling) {
|
|
12969
|
+
column.setAttribute(FOOTER_HEADING_CLASS_CACHE_ATTR, classFromSibling);
|
|
12970
|
+
}
|
|
12912
12971
|
}
|
|
12913
12972
|
let firstLink = null;
|
|
12914
12973
|
items.forEach((item, itemIndex) => {
|
|
@@ -15752,6 +15811,66 @@ function unmountSchedulingWrapper(wrapper) {
|
|
|
15752
15811
|
function schedulingSectionId(insertAfter) {
|
|
15753
15812
|
return `scheduling-${insertAfter}`;
|
|
15754
15813
|
}
|
|
15814
|
+
function duplicateSchedulingWidget(instanceId, scheduleId) {
|
|
15815
|
+
const escaped = CSS.escape(instanceId);
|
|
15816
|
+
const sourceEl = document.querySelector(
|
|
15817
|
+
`[data-ohw-section-container="scheduling"][data-ohw-instance="${escaped}"]`
|
|
15818
|
+
) ?? document.querySelector(
|
|
15819
|
+
`[data-ohw-section-container="scheduling"][data-ohw-section="${escaped}"]`
|
|
15820
|
+
) ?? document.querySelector(`[data-ohw-instance="${escaped}"]`) ?? document.querySelector(`[data-ohw-section="${escaped}"]`);
|
|
15821
|
+
if (!sourceEl) return null;
|
|
15822
|
+
const sourceWrapper = sourceEl.closest('[data-ohw-section-container="scheduling"]') ?? sourceEl;
|
|
15823
|
+
let insertAfter = instanceId;
|
|
15824
|
+
let sectionId = schedulingSectionId(insertAfter);
|
|
15825
|
+
for (let n = 0; n < 20 && document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`); n++) {
|
|
15826
|
+
insertAfter = `${instanceId}--${n + 1}`;
|
|
15827
|
+
sectionId = schedulingSectionId(insertAfter);
|
|
15828
|
+
}
|
|
15829
|
+
if (document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`)) return null;
|
|
15830
|
+
const container = document.createElement("div");
|
|
15831
|
+
container.dataset.ohwSectionContainer = "scheduling";
|
|
15832
|
+
container.dataset.ohwSection = sectionId;
|
|
15833
|
+
container.dataset.ohwInstance = sectionId;
|
|
15834
|
+
sourceWrapper.insertAdjacentElement("afterend", container);
|
|
15835
|
+
try {
|
|
15836
|
+
const root = (0, import_client2.createRoot)(container);
|
|
15837
|
+
schedulingRoots.set(container, root);
|
|
15838
|
+
(0, import_react_dom3.flushSync)(() => {
|
|
15839
|
+
root.render(
|
|
15840
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
15841
|
+
SchedulingWidget,
|
|
15842
|
+
{
|
|
15843
|
+
notifyOnConnect: false,
|
|
15844
|
+
initialScheduleId: scheduleId ?? null,
|
|
15845
|
+
insertAfter
|
|
15846
|
+
}
|
|
15847
|
+
)
|
|
15848
|
+
);
|
|
15849
|
+
});
|
|
15850
|
+
} catch {
|
|
15851
|
+
container.remove();
|
|
15852
|
+
return null;
|
|
15853
|
+
}
|
|
15854
|
+
const tracker = getSectionsTracker();
|
|
15855
|
+
let sections = [];
|
|
15856
|
+
try {
|
|
15857
|
+
sections = JSON.parse(tracker.textContent || "[]");
|
|
15858
|
+
} catch {
|
|
15859
|
+
}
|
|
15860
|
+
const currentPath = window.location.pathname;
|
|
15861
|
+
if (!sections.find(
|
|
15862
|
+
(s) => s.type === "scheduling" && s.insertAfter === insertAfter && (!s.pagePath || s.pagePath === currentPath)
|
|
15863
|
+
)) {
|
|
15864
|
+
sections.push({
|
|
15865
|
+
type: "scheduling",
|
|
15866
|
+
insertAfter,
|
|
15867
|
+
pagePath: currentPath,
|
|
15868
|
+
...scheduleId ? { scheduleId } : {}
|
|
15869
|
+
});
|
|
15870
|
+
tracker.textContent = JSON.stringify(sections);
|
|
15871
|
+
}
|
|
15872
|
+
return { sectionId, insertAfter };
|
|
15873
|
+
}
|
|
15755
15874
|
var INSERT_BEFORE_MARKER = ":before:";
|
|
15756
15875
|
function parseSchedulingInsertAfter(insertAfter) {
|
|
15757
15876
|
const idx = insertAfter.indexOf(INSERT_BEFORE_MARKER);
|
|
@@ -19382,10 +19501,21 @@ function OhhwellsBridge() {
|
|
|
19382
19501
|
gap: 6px;
|
|
19383
19502
|
}
|
|
19384
19503
|
/* Not the form: it is a layout container (flex/grid with gaps), and forcing block
|
|
19385
|
-
crushed its fields together (OHH-490).
|
|
19386
|
-
|
|
19504
|
+
crushed its fields together (OHH-490). Not media (image/bg-image/video/icon/map)
|
|
19505
|
+
either: those can be their own flex containers centering fallback content (a
|
|
19506
|
+
placeholder label, a mascot emoji) \u2014 forcing block broke that centering while the
|
|
19507
|
+
image was unset (OHH-758-ish). */
|
|
19508
|
+
[data-ohw-editable]:not([data-ohw-editable="form"]):not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]):not([data-ohw-editable="video"]):not([data-ohw-editable="icon"]):not([data-ohw-editable="map"]) {
|
|
19387
19509
|
display: block;
|
|
19388
19510
|
}
|
|
19511
|
+
/* The block-force above is an author rule, so it beats the browser's own
|
|
19512
|
+
details-not-open child-display-none UA rule \u2014 origin always wins over specificity.
|
|
19513
|
+
Left alone, a closed FAQ's answer became a real, hoverable box that overflowed past
|
|
19514
|
+
the collapsed <details> into the gap before the next item. Restore the native
|
|
19515
|
+
collapse for editable content once it isn't the summary. */
|
|
19516
|
+
details:not([open]) > [data-ohw-editable]:not(summary) {
|
|
19517
|
+
display: none !important;
|
|
19518
|
+
}
|
|
19389
19519
|
/* Body text (no item-action toolbar) \u2014 first click enters text edit \u2192 I-beam.
|
|
19390
19520
|
Exclude select-first nav/footer labels so grab/default on [data-ohw-href-key] can win. */
|
|
19391
19521
|
[data-ohw-editable]:not([contenteditable]):not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]):not([data-ohw-editable="video"]):not([data-ohw-editable="link"]):not(:is([data-ohw-href-key] *)) {
|
|
@@ -19409,6 +19539,14 @@ function OhhwellsBridge() {
|
|
|
19409
19539
|
[data-ohw-editable="video"], [data-ohw-editable="video"] *,
|
|
19410
19540
|
[data-ohw-editable="bg-image"], [data-ohw-editable="bg-image"] * { cursor: pointer !important; }
|
|
19411
19541
|
[data-ohw-editable="link"], [data-ohw-editable="link"] * { cursor: pointer !important; }
|
|
19542
|
+
/* A text/plain editable nested inside a media editable (e.g. a placeholder's fallback
|
|
19543
|
+
label inside its bg-image box) is its own click target, not the media picker \u2014 the
|
|
19544
|
+
blanket media cursor rule above would otherwise show pointer where a click actually
|
|
19545
|
+
opens text edit. */
|
|
19546
|
+
[data-ohw-editable="bg-image"] [data-ohw-editable="text"],
|
|
19547
|
+
[data-ohw-editable="bg-image"] [data-ohw-editable="text"] *,
|
|
19548
|
+
[data-ohw-editable="image"] [data-ohw-editable="text"],
|
|
19549
|
+
[data-ohw-editable="image"] [data-ohw-editable="text"] * { cursor: text !important; }
|
|
19412
19550
|
/* A form field is a design surface in the editor: its input takes the pointer so the
|
|
19413
19551
|
field can be picked and hovered from anywhere inside it (OHH-642). */
|
|
19414
19552
|
[data-ohw-editable="form"] [data-ohw-form-field] input,
|
|
@@ -19995,6 +20133,8 @@ function OhhwellsBridge() {
|
|
|
19995
20133
|
setFormHoverRect(null);
|
|
19996
20134
|
}
|
|
19997
20135
|
if (!editable) return;
|
|
20136
|
+
const editableRect = editable.getBoundingClientRect();
|
|
20137
|
+
if (editableRect.width <= 0 || editableRect.height <= 0) return;
|
|
19998
20138
|
const selected = selectedElRef.current;
|
|
19999
20139
|
if (selected && (selected === editable || selected.contains(editable))) return;
|
|
20000
20140
|
if (!isMediaEditable(editable) && !editable.hasAttribute("contenteditable")) {
|
|
@@ -21377,9 +21517,62 @@ function OhhwellsBridge() {
|
|
|
21377
21517
|
if (e.data?.type !== "ow:duplicate-section") return;
|
|
21378
21518
|
const instanceId = typeof e.data.instanceId === "string" ? e.data.instanceId : "";
|
|
21379
21519
|
if (!instanceId) return;
|
|
21520
|
+
const currentPath = window.location.pathname;
|
|
21521
|
+
if (instanceId.startsWith("scheduling-")) {
|
|
21522
|
+
const sourceInsertAfter = instanceId.slice("scheduling-".length);
|
|
21523
|
+
const tracker = getSectionsTracker();
|
|
21524
|
+
let sections = [];
|
|
21525
|
+
try {
|
|
21526
|
+
sections = JSON.parse(tracker.textContent || "[]");
|
|
21527
|
+
} catch {
|
|
21528
|
+
}
|
|
21529
|
+
const source = sections.find(
|
|
21530
|
+
(s) => s.type === "scheduling" && s.insertAfter === sourceInsertAfter && (!s.pagePath || s.pagePath === currentPath)
|
|
21531
|
+
);
|
|
21532
|
+
const duplicated = duplicateSchedulingWidget(instanceId, source?.scheduleId ?? null);
|
|
21533
|
+
if (!duplicated) return;
|
|
21534
|
+
const currentEntries2 = getPageSectionOrderEntries(
|
|
21535
|
+
editContentRef.current[SECTION_ORDER_KEY],
|
|
21536
|
+
currentPath
|
|
21537
|
+
);
|
|
21538
|
+
const byId = new Map(currentEntries2.map((entry) => [entry.instanceId, entry]));
|
|
21539
|
+
const entries2 = topLevelSections().map((el, order) => {
|
|
21540
|
+
const id = instanceIdOf(el);
|
|
21541
|
+
return {
|
|
21542
|
+
instanceId: id,
|
|
21543
|
+
type: el.getAttribute("data-ohw-section") ?? "",
|
|
21544
|
+
order,
|
|
21545
|
+
pagePath: currentPath,
|
|
21546
|
+
...byId.get(id)?.removed ? { removed: true } : {}
|
|
21547
|
+
};
|
|
21548
|
+
});
|
|
21549
|
+
const orderJson2 = JSON.stringify(entries2);
|
|
21550
|
+
const nodes2 = [
|
|
21551
|
+
{ key: "__ohw_sections", text: tracker.textContent ?? "[]" },
|
|
21552
|
+
{ key: SECTION_ORDER_KEY, text: orderJson2 }
|
|
21553
|
+
];
|
|
21554
|
+
editContentRef.current = {
|
|
21555
|
+
...editContentRef.current,
|
|
21556
|
+
...Object.fromEntries(nodes2.map(({ key, text }) => [key, text]))
|
|
21557
|
+
};
|
|
21558
|
+
setAiSectionOrder(orderJson2, currentPath);
|
|
21559
|
+
postToParentRef.current({ type: "ow:change", nodes: nodes2 });
|
|
21560
|
+
window.dispatchEvent(new Event("resize"));
|
|
21561
|
+
const duplicateHeight2 = document.body.scrollHeight;
|
|
21562
|
+
if (duplicateHeight2 > 50) postToParentRef.current({ type: "ow:height", height: duplicateHeight2 });
|
|
21563
|
+
const selectDuplicate = () => {
|
|
21564
|
+
const clone2 = document.querySelector(
|
|
21565
|
+
`[data-ohw-section-container="scheduling"][data-ohw-instance="${CSS.escape(duplicated.sectionId)}"]`
|
|
21566
|
+
);
|
|
21567
|
+
if (clone2) aiSectionApiRef.current?.selectFromElement(clone2);
|
|
21568
|
+
};
|
|
21569
|
+
selectDuplicate();
|
|
21570
|
+
requestAnimationFrame(selectDuplicate);
|
|
21571
|
+
return;
|
|
21572
|
+
}
|
|
21380
21573
|
const newId = newInstanceId();
|
|
21381
|
-
const currentEntries = getPageSectionOrderEntries(editContentRef.current[SECTION_ORDER_KEY],
|
|
21382
|
-
const result = duplicateSectionInstance(instanceId, newId,
|
|
21574
|
+
const currentEntries = getPageSectionOrderEntries(editContentRef.current[SECTION_ORDER_KEY], currentPath);
|
|
21575
|
+
const result = duplicateSectionInstance(instanceId, newId, currentPath, currentEntries);
|
|
21383
21576
|
if (!result) return;
|
|
21384
21577
|
const { entries, keyRekeys } = result;
|
|
21385
21578
|
const orderJson = JSON.stringify(
|
|
@@ -22045,6 +22238,18 @@ function OhhwellsBridge() {
|
|
|
22045
22238
|
hoveredNavContainerRef.current = null;
|
|
22046
22239
|
setHoveredNavContainerRect(null);
|
|
22047
22240
|
};
|
|
22241
|
+
const handleDetailsToggle = (e) => {
|
|
22242
|
+
if (e.target?.tagName !== "DETAILS") return;
|
|
22243
|
+
document.querySelectorAll("[data-ohw-hovered]").forEach((hovered) => {
|
|
22244
|
+
hovered.removeAttribute("data-ohw-hovered");
|
|
22245
|
+
});
|
|
22246
|
+
setHoveredTextRect(null);
|
|
22247
|
+
hoveredItemElRef.current = null;
|
|
22248
|
+
setHoveredItemRect(null);
|
|
22249
|
+
hoveredNavContainerRef.current = null;
|
|
22250
|
+
setHoveredNavContainerRect(null);
|
|
22251
|
+
};
|
|
22252
|
+
document.addEventListener("toggle", handleDetailsToggle, true);
|
|
22048
22253
|
window.addEventListener("resize", handleViewportResize, { passive: true });
|
|
22049
22254
|
document.addEventListener("click", handleClick, true);
|
|
22050
22255
|
document.addEventListener("dblclick", handleDblClick, true);
|
|
@@ -22062,6 +22267,7 @@ function OhhwellsBridge() {
|
|
|
22062
22267
|
document.addEventListener("selectionchange", handleSelectionChange);
|
|
22063
22268
|
window.addEventListener("scroll", handleScroll, true);
|
|
22064
22269
|
return () => {
|
|
22270
|
+
document.removeEventListener("toggle", handleDetailsToggle, true);
|
|
22065
22271
|
document.removeEventListener("click", handleClick, true);
|
|
22066
22272
|
document.removeEventListener("dblclick", handleDblClick, true);
|
|
22067
22273
|
document.removeEventListener("paste", handlePaste, true);
|
|
@@ -22315,7 +22521,7 @@ function OhhwellsBridge() {
|
|
|
22315
22521
|
postToParent2({
|
|
22316
22522
|
type: "ow:ready",
|
|
22317
22523
|
version: "1",
|
|
22318
|
-
bridgeVersion: "0.1.
|
|
22524
|
+
bridgeVersion: "0.1.105",
|
|
22319
22525
|
path: pathname,
|
|
22320
22526
|
nodes: collectEditableNodes(editContentRef.current),
|
|
22321
22527
|
sections
|