@ohhwells/bridge 0.1.87 → 0.1.89

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
@@ -1949,6 +1949,7 @@ function findTemplateSection(id) {
1949
1949
  return null;
1950
1950
  }
1951
1951
  function findPlacementAnchor(id, exclude) {
1952
+ if (CHROME_SECTION_IDS.has(id)) return null;
1952
1953
  for (const el of document.querySelectorAll(`[data-ohw-section="${CSS.escape(id)}"]`)) {
1953
1954
  if (el === exclude) continue;
1954
1955
  if (el.parentElement?.closest("[data-ohw-section]")) continue;
@@ -8250,6 +8251,27 @@ function deleteSectionInstance(instanceId, currentPath, existingEntries) {
8250
8251
  function restoreSectionInstance(instanceId, currentPath, existingEntries) {
8251
8252
  return setSectionRemoved(instanceId, currentPath, existingEntries, false);
8252
8253
  }
8254
+ function duplicateSectionInstance(instanceId, newId, currentPath, existingEntries) {
8255
+ const original = findByInstanceId(instanceId);
8256
+ if (!original) return null;
8257
+ const clone = original.cloneNode(true);
8258
+ clone.setAttribute("data-ohw-instance", newId);
8259
+ const keyRekeys = rekeySectionSubtree(clone, newId);
8260
+ original.insertAdjacentElement("afterend", clone);
8261
+ const byId = new Map(existingEntries.map((e) => [e.instanceId, e]));
8262
+ const entries = topLevelSections().map((el, order) => {
8263
+ const id = instanceIdOf(el);
8264
+ return {
8265
+ instanceId: id,
8266
+ type: el.getAttribute("data-ohw-section") ?? "",
8267
+ order,
8268
+ pagePath: currentPath,
8269
+ ...byId.get(id)?.removed ? { removed: true } : {}
8270
+ };
8271
+ });
8272
+ applyPersistedOrder(entries);
8273
+ return { entries, keyRekeys };
8274
+ }
8253
8275
  function newInstanceId() {
8254
8276
  return typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `instance-${Date.now()}-${Math.random().toString(36).slice(2)}`;
8255
8277
  }
@@ -8264,14 +8286,20 @@ function getPageSectionOrderEntries(raw, currentPath) {
8264
8286
  }
8265
8287
  function rekeySectionSubtree(root, instanceId) {
8266
8288
  const suffix = `::${instanceId}`;
8289
+ const pairs = [];
8267
8290
  const rekey = (el, attr) => {
8268
8291
  const current = el.getAttribute(attr);
8269
- if (current) el.setAttribute(attr, `${current}${suffix}`);
8292
+ if (!current) return;
8293
+ const base = current.includes("::") ? current.slice(0, current.indexOf("::")) : current;
8294
+ const next = `${base}${suffix}`;
8295
+ el.setAttribute(attr, next);
8296
+ pairs.push({ from: current, to: next });
8270
8297
  };
8271
8298
  if (root.hasAttribute("data-ohw-key")) rekey(root, "data-ohw-key");
8272
8299
  if (root.hasAttribute("data-ohw-href-key")) rekey(root, "data-ohw-href-key");
8273
8300
  root.querySelectorAll("[data-ohw-key]").forEach((el) => rekey(el, "data-ohw-key"));
8274
8301
  root.querySelectorAll("[data-ohw-href-key]").forEach((el) => rekey(el, "data-ohw-href-key"));
8302
+ return pairs;
8275
8303
  }
8276
8304
  function initSectionInstancesFromContent(content, currentPath) {
8277
8305
  document.querySelectorAll("[data-ohw-section]:not([data-ohw-instance])").forEach((el) => {
@@ -17969,6 +17997,7 @@ function OhhwellsBridge() {
17969
17997
  applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
17970
17998
  }
17971
17999
  applyBrandChrome(content);
18000
+ initSectionInstancesFromContent(content, window.location.pathname);
17972
18001
  for (const [key, val] of Object.entries(content)) {
17973
18002
  if (key === "__ohw_sections") continue;
17974
18003
  if (key === AI_SECTIONS_KEY) continue;
@@ -18024,7 +18053,6 @@ function OhhwellsBridge() {
18024
18053
  if (isEditModeRef.current) requestMissingSocialIconsRef.current();
18025
18054
  enforceLinkHrefs();
18026
18055
  initSectionsFromContent(content, true);
18027
- initSectionInstancesFromContent(content, window.location.pathname);
18028
18056
  sectionsLoadedRef.current = true;
18029
18057
  pendingScheduleConfigRequests.current.splice(0).forEach(processConfigRequest);
18030
18058
  if (imageLoads.length === 0) return Promise.resolve();
@@ -20090,6 +20118,7 @@ function OhhwellsBridge() {
20090
20118
  applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
20091
20119
  }
20092
20120
  applyBrandChrome(content);
20121
+ initSectionInstancesFromContent(content, window.location.pathname);
20093
20122
  let sectionsJson = null;
20094
20123
  for (const [key, val] of Object.entries(content)) {
20095
20124
  if (key === "__ohw_sections") {
@@ -20131,7 +20160,6 @@ function OhhwellsBridge() {
20131
20160
  sectionsLoadedRef.current = true;
20132
20161
  pendingScheduleConfigRequests.current.splice(0).forEach(processConfigRequest);
20133
20162
  }
20134
- initSectionInstancesFromContent(content, window.location.pathname);
20135
20163
  editContentRef.current = { ...editContentRef.current, ...content };
20136
20164
  reconcileNavbarItemsFromContent(editContentRef.current);
20137
20165
  reconcileFooterOrderFromContent(editContentRef.current);
@@ -20353,6 +20381,34 @@ function OhhwellsBridge() {
20353
20381
  });
20354
20382
  };
20355
20383
  window.addEventListener("message", handleDeleteSection);
20384
+ const handleDuplicateSection = (e) => {
20385
+ if (e.data?.type !== "ow:duplicate-section") return;
20386
+ const instanceId = typeof e.data.instanceId === "string" ? e.data.instanceId : "";
20387
+ if (!instanceId) return;
20388
+ const newId = newInstanceId();
20389
+ const currentEntries = getPageSectionOrderEntries(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname);
20390
+ const result = duplicateSectionInstance(instanceId, newId, window.location.pathname, currentEntries);
20391
+ if (!result) return;
20392
+ const { entries, keyRekeys } = result;
20393
+ const orderJson = JSON.stringify(entries);
20394
+ const nodes = [{ key: SECTION_ORDER_KEY, text: orderJson }];
20395
+ for (const { from, to } of keyRekeys) {
20396
+ const inherited = editContentRef.current[from];
20397
+ if (inherited !== void 0) nodes.push({ key: to, text: inherited });
20398
+ }
20399
+ editContentRef.current = {
20400
+ ...editContentRef.current,
20401
+ ...Object.fromEntries(nodes.map(({ key, text }) => [key, text]))
20402
+ };
20403
+ setAiSectionOrder(orderJson, window.location.pathname);
20404
+ postToParentRef.current({ type: "ow:change", nodes });
20405
+ window.dispatchEvent(new Event("resize"));
20406
+ const duplicateHeight = document.body.scrollHeight;
20407
+ if (duplicateHeight > 50) postToParentRef.current({ type: "ow:height", height: duplicateHeight });
20408
+ const clone = document.querySelector(`[data-ohw-instance="${CSS.escape(newId)}"]`);
20409
+ if (clone) aiSectionApiRef.current?.selectFromElement(clone);
20410
+ };
20411
+ window.addEventListener("message", handleDuplicateSection);
20356
20412
  const handleDeactivate = (e) => {
20357
20413
  if (e.data?.type !== "ow:deactivate") return;
20358
20414
  if (document.documentElement.hasAttribute("data-ohw-panel-dragging")) return;
@@ -21039,6 +21095,7 @@ function OhhwellsBridge() {
21039
21095
  window.removeEventListener("message", handleMoveSection);
21040
21096
  window.removeEventListener("message", handlePanelDragging);
21041
21097
  window.removeEventListener("message", handleDeleteSection);
21098
+ window.removeEventListener("message", handleDuplicateSection);
21042
21099
  window.removeEventListener("message", handleDeactivate);
21043
21100
  document.documentElement.removeAttribute("data-ohw-panel-dragging");
21044
21101
  window.removeEventListener("message", handleToastAction);
@@ -21246,7 +21303,7 @@ function OhhwellsBridge() {
21246
21303
  postToParent2({
21247
21304
  type: "ow:ready",
21248
21305
  version: "1",
21249
- bridgeVersion: "0.1.86",
21306
+ bridgeVersion: "0.1.88",
21250
21307
  path: pathname,
21251
21308
  nodes: collectEditableNodes(editContentRef.current),
21252
21309
  sections