@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 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
- return style.display !== "none" && style.visibility !== "hidden";
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 = container.querySelector(CTA_BUTTON_SELECTOR);
11083
- if (cta && cta.parentElement === container) {
11084
- container.insertBefore(anchor, cta);
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
- container.appendChild(anchor);
11104
+ listParent.appendChild(anchor);
11088
11105
  return;
11089
11106
  }
11090
- const afterEl = findCounterpartByHrefKey(afterHrefKey, container);
11107
+ const afterEl = findCounterpartByHrefKey(afterHrefKey, listParent);
11091
11108
  if (afterEl) {
11092
11109
  const insertAfter = resolveNavRootUnit(afterEl);
11093
- if (insertAfter.parentElement === container || insertAfter.parentElement === afterEl.parentElement) {
11110
+ if (insertAfter.parentElement === listParent || insertAfter.parentElement === afterEl.parentElement) {
11094
11111
  insertAfter.insertAdjacentElement("afterend", anchor);
11095
11112
  return;
11096
11113
  }
11097
11114
  }
11098
- container.appendChild(anchor);
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(container);
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 === container ? lastUnit.nextElementSibling : null;
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) container.insertBefore(el, anchor);
11178
- } else if (container.lastElementChild !== el) {
11179
- container.appendChild(el);
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?.textContent ?? "").trim() || column.getAttribute(FOOTER_HEADING_CACHE_ATTR) || DEFAULT_FOOTER_COLUMN_HEADING;
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
- if (existing.textContent !== raw) existing.textContent = raw;
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
- [data-ohw-editable]:not([data-ohw-editable="form"]) {
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], window.location.pathname);
21382
- const result = duplicateSectionInstance(instanceId, newId, window.location.pathname, currentEntries);
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.103",
22524
+ bridgeVersion: "0.1.105",
22319
22525
  path: pathname,
22320
22526
  nodes: collectEditableNodes(editContentRef.current),
22321
22527
  sections