@ohhwells/bridge 0.1.70-next.211 → 0.1.70-next.215

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
@@ -6296,16 +6296,14 @@ var import_react6 = require("react");
6296
6296
  var import_lucide_react3 = require("lucide-react");
6297
6297
 
6298
6298
  // src/ui/dropdown-menu.tsx
6299
+ var React6 = __toESM(require("react"), 1);
6299
6300
  var import_radix_ui3 = require("radix-ui");
6300
6301
  var import_jsx_runtime9 = require("react/jsx-runtime");
6301
6302
  function DropdownMenu({ ...props }) {
6302
6303
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_radix_ui3.DropdownMenu.Root, { "data-slot": "dropdown-menu", ...props });
6303
6304
  }
6304
- function DropdownMenuTrigger({
6305
- ...props
6306
- }) {
6307
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_radix_ui3.DropdownMenu.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
6308
- }
6305
+ var DropdownMenuTrigger = React6.forwardRef((props, ref) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_radix_ui3.DropdownMenu.Trigger, { ref, "data-slot": "dropdown-menu-trigger", ...props }));
6306
+ DropdownMenuTrigger.displayName = "DropdownMenuTrigger";
6309
6307
  function DropdownMenuGroup({
6310
6308
  className,
6311
6309
  ...props
@@ -7558,11 +7556,11 @@ function FieldTypePicker({ onPick }) {
7558
7556
  }
7559
7557
 
7560
7558
  // src/ui/MediaOverlay.tsx
7561
- var React7 = __toESM(require("react"), 1);
7559
+ var React8 = __toESM(require("react"), 1);
7562
7560
  var import_lucide_react5 = require("lucide-react");
7563
7561
 
7564
7562
  // src/ui/button.tsx
7565
- var React6 = __toESM(require("react"), 1);
7563
+ var React7 = __toESM(require("react"), 1);
7566
7564
  var import_radix_ui5 = require("radix-ui");
7567
7565
  var import_jsx_runtime14 = require("react/jsx-runtime");
7568
7566
  var buttonVariants = cva(
@@ -7585,7 +7583,7 @@ var buttonVariants = cva(
7585
7583
  }
7586
7584
  }
7587
7585
  );
7588
- var Button = React6.forwardRef(
7586
+ var Button = React7.forwardRef(
7589
7587
  ({ className, variant, size, asChild = false, ...props }, ref) => {
7590
7588
  const Comp = asChild ? import_radix_ui5.Slot.Root : "button";
7591
7589
  return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
@@ -7640,7 +7638,7 @@ function MediaOverlay({
7640
7638
  onVideoSettingsChange
7641
7639
  }) {
7642
7640
  const { rect } = hover;
7643
- const skeletonRef = React7.useRef(null);
7641
+ const skeletonRef = React8.useRef(null);
7644
7642
  const isVideo = hover.elementType === "video";
7645
7643
  const showChrome = !selected || hovered;
7646
7644
  const autoplay = hover.videoAutoplay ?? true;
@@ -7653,7 +7651,7 @@ function MediaOverlay({
7653
7651
  height: rect.height,
7654
7652
  zIndex: 2147483646
7655
7653
  };
7656
- React7.useEffect(() => {
7654
+ React8.useEffect(() => {
7657
7655
  if (!isUploading || !fadingOut || !skeletonRef.current) return;
7658
7656
  const anim = skeletonRef.current.animate([{ opacity: 1 }, { opacity: 0 }], {
7659
7657
  duration: MEDIA_UPLOAD_FADE_MS,
@@ -7872,6 +7870,150 @@ function parseSectionsFromHtml(html) {
7872
7870
  return parseSectionsFromRoot(doc);
7873
7871
  }
7874
7872
 
7873
+ // src/lib/section-instances.ts
7874
+ var SECTION_ORDER_KEY = "__ohw_section_order";
7875
+ var REMOVED_ATTR2 = "data-ohw-section-removed";
7876
+ function isRemovedSection(el) {
7877
+ return el.hasAttribute(REMOVED_ATTR2);
7878
+ }
7879
+ function topLevelSections() {
7880
+ return Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
7881
+ (el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el) && !isRemovedSection(el)
7882
+ );
7883
+ }
7884
+ function instanceIdOf(el) {
7885
+ return el.dataset.ohwInstance ?? el.dataset.ohwSection ?? "";
7886
+ }
7887
+ function planSectionMove(instanceId, targetIndex, currentPath) {
7888
+ const sections = topLevelSections();
7889
+ const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
7890
+ if (index === -1) return null;
7891
+ const dragged = sections[index];
7892
+ const others = sections.filter((_, i) => i !== index);
7893
+ const clamped = Math.max(0, Math.min(targetIndex, others.length));
7894
+ const reordered = [...others.slice(0, clamped), dragged, ...others.slice(clamped)];
7895
+ return reordered.map((el, order) => ({
7896
+ instanceId: instanceIdOf(el),
7897
+ type: el.getAttribute("data-ohw-section") ?? "",
7898
+ order,
7899
+ pagePath: currentPath
7900
+ }));
7901
+ }
7902
+ function moveSectionInstance(instanceId, direction, currentPath) {
7903
+ const sections = topLevelSections();
7904
+ const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
7905
+ if (index === -1) return null;
7906
+ const siblingIndex = direction === "up" ? index - 1 : index + 1;
7907
+ if (siblingIndex < 0 || siblingIndex >= sections.length) return null;
7908
+ const entries = planSectionMove(instanceId, siblingIndex, currentPath);
7909
+ if (!entries) return null;
7910
+ applyPersistedOrder(entries);
7911
+ return entries;
7912
+ }
7913
+ function syncRemovedFlags(entries) {
7914
+ const removedIds = new Set(entries.filter((e) => e.removed).map((e) => e.instanceId));
7915
+ document.querySelectorAll(`[${REMOVED_ATTR2}]`).forEach((el) => {
7916
+ if (!removedIds.has(instanceIdOf(el))) {
7917
+ el.style.removeProperty("display");
7918
+ el.removeAttribute(REMOVED_ATTR2);
7919
+ }
7920
+ });
7921
+ for (const id of removedIds) {
7922
+ const el = document.querySelector(`[data-ohw-instance="${CSS.escape(id)}"]`);
7923
+ if (el) {
7924
+ el.style.display = "none";
7925
+ el.setAttribute(REMOVED_ATTR2, "");
7926
+ }
7927
+ }
7928
+ }
7929
+ function applyPersistedOrder(entries) {
7930
+ syncRemovedFlags(entries);
7931
+ if (entries.length === 0) return;
7932
+ const sections = topLevelSections();
7933
+ if (sections.length === 0) return;
7934
+ const orderIndex = new Map(entries.map((e) => [e.instanceId, e.order]));
7935
+ const ordered = [...sections].sort((a, b) => {
7936
+ const aOrder = orderIndex.get(instanceIdOf(a));
7937
+ const bOrder = orderIndex.get(instanceIdOf(b));
7938
+ if (aOrder === void 0 && bOrder === void 0) return 0;
7939
+ if (aOrder === void 0) return 1;
7940
+ if (bOrder === void 0) return -1;
7941
+ return aOrder - bOrder;
7942
+ });
7943
+ let prev = null;
7944
+ for (const el of ordered) {
7945
+ if (prev) prev.after(el);
7946
+ prev = el;
7947
+ }
7948
+ }
7949
+ function setSectionRemoved(instanceId, currentPath, existingEntries, removed) {
7950
+ if (!document.querySelector(`[data-ohw-instance="${CSS.escape(instanceId)}"]`)) return null;
7951
+ const byId = new Map(existingEntries.map((e) => [e.instanceId, e]));
7952
+ const allSections = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
7953
+ (el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el)
7954
+ );
7955
+ allSections.forEach((el, order) => {
7956
+ const id = instanceIdOf(el);
7957
+ if (!byId.has(id)) {
7958
+ byId.set(id, { instanceId: id, type: el.getAttribute("data-ohw-section") ?? "", order, pagePath: currentPath });
7959
+ }
7960
+ });
7961
+ const target = byId.get(instanceId);
7962
+ if (!target) return null;
7963
+ byId.set(instanceId, { ...target, removed });
7964
+ const entries = Array.from(byId.values());
7965
+ applyPersistedOrder(entries);
7966
+ return entries;
7967
+ }
7968
+ function deleteSectionInstance(instanceId, currentPath, existingEntries) {
7969
+ return setSectionRemoved(instanceId, currentPath, existingEntries, true);
7970
+ }
7971
+ function restoreSectionInstance(instanceId, currentPath, existingEntries) {
7972
+ return setSectionRemoved(instanceId, currentPath, existingEntries, false);
7973
+ }
7974
+ function newInstanceId() {
7975
+ return typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `instance-${Date.now()}-${Math.random().toString(36).slice(2)}`;
7976
+ }
7977
+ function getPageSectionOrderEntries(raw, currentPath) {
7978
+ if (!raw) return [];
7979
+ try {
7980
+ const entries = JSON.parse(raw);
7981
+ return entries.filter((e) => !e.pagePath || e.pagePath === currentPath);
7982
+ } catch {
7983
+ return [];
7984
+ }
7985
+ }
7986
+ function rekeySectionSubtree(root, instanceId) {
7987
+ const suffix = `::${instanceId}`;
7988
+ const rekey = (el, attr) => {
7989
+ const current = el.getAttribute(attr);
7990
+ if (current) el.setAttribute(attr, `${current}${suffix}`);
7991
+ };
7992
+ if (root.hasAttribute("data-ohw-key")) rekey(root, "data-ohw-key");
7993
+ if (root.hasAttribute("data-ohw-href-key")) rekey(root, "data-ohw-href-key");
7994
+ root.querySelectorAll("[data-ohw-key]").forEach((el) => rekey(el, "data-ohw-key"));
7995
+ root.querySelectorAll("[data-ohw-href-key]").forEach((el) => rekey(el, "data-ohw-href-key"));
7996
+ }
7997
+ function initSectionInstancesFromContent(content, currentPath) {
7998
+ document.querySelectorAll("[data-ohw-section]:not([data-ohw-instance])").forEach((el) => {
7999
+ el.setAttribute("data-ohw-instance", el.getAttribute("data-ohw-section") ?? "");
8000
+ });
8001
+ const entries = getPageSectionOrderEntries(content[SECTION_ORDER_KEY], currentPath);
8002
+ for (const entry of entries) {
8003
+ if (entry.instanceId === entry.type) continue;
8004
+ if (document.querySelector(`[data-ohw-instance="${CSS.escape(entry.instanceId)}"]`)) continue;
8005
+ const original = document.querySelector(
8006
+ `[data-ohw-section="${CSS.escape(entry.type)}"][data-ohw-instance="${CSS.escape(entry.type)}"]`
8007
+ );
8008
+ if (!original) continue;
8009
+ const clone = original.cloneNode(true);
8010
+ clone.setAttribute("data-ohw-instance", entry.instanceId);
8011
+ rekeySectionSubtree(clone, entry.instanceId);
8012
+ original.insertAdjacentElement("afterend", clone);
8013
+ }
8014
+ applyPersistedOrder(entries);
8015
+ }
8016
+
7875
8017
  // src/ui/ai-section/AiSectionOverlay.tsx
7876
8018
  var import_jsx_runtime17 = require("react/jsx-runtime");
7877
8019
  function findSectionElement(instanceId) {
@@ -7916,9 +8058,7 @@ function useLiveSectionRect(sectionId) {
7916
8058
  return rect;
7917
8059
  }
7918
8060
  function computeSectionBoundaryFlags(instanceId) {
7919
- const topLevel = Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
7920
- (el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el)
7921
- );
8061
+ const topLevel = topLevelSections();
7922
8062
  const index = topLevel.findIndex((el) => (el.dataset.ohwInstance ?? el.dataset.ohwSection) === instanceId);
7923
8063
  if (index === -1) return { isFirst: true, isLast: true };
7924
8064
  return { isFirst: index === 0, isLast: index === topLevel.length - 1 };
@@ -8035,12 +8175,15 @@ function AiSectionOverlay({
8035
8175
  selectFromElement(sectionEl);
8036
8176
  return sectionEl != null;
8037
8177
  },
8038
- clear: () => setSelectedId(null)
8178
+ clear: () => {
8179
+ setSelectedId(null);
8180
+ report(null);
8181
+ }
8039
8182
  };
8040
8183
  return () => {
8041
8184
  apiRef.current = null;
8042
8185
  };
8043
- }, [apiRef, selectFromElement]);
8186
+ }, [apiRef, selectFromElement, report]);
8044
8187
  (0, import_react8.useEffect)(() => {
8045
8188
  const onMessage = (e) => {
8046
8189
  if (e.data?.type === "ow:ai-select" && e.data.sectionId === null) {
@@ -8215,101 +8358,6 @@ function AiSectionOverlay({
8215
8358
  ] });
8216
8359
  }
8217
8360
 
8218
- // src/lib/section-instances.ts
8219
- var SECTION_ORDER_KEY = "__ohw_section_order";
8220
- function topLevelSections() {
8221
- return Array.from(document.querySelectorAll("[data-ohw-section]")).filter(
8222
- (el) => !el.parentElement?.closest("[data-ohw-section]") && !isChromeSection(el)
8223
- );
8224
- }
8225
- function instanceIdOf(el) {
8226
- return el.dataset.ohwInstance ?? el.dataset.ohwSection ?? "";
8227
- }
8228
- function planSectionMove(instanceId, targetIndex, currentPath) {
8229
- const sections = topLevelSections();
8230
- const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
8231
- if (index === -1) return null;
8232
- const dragged = sections[index];
8233
- const others = sections.filter((_, i) => i !== index);
8234
- const clamped = Math.max(0, Math.min(targetIndex, others.length));
8235
- const reordered = [...others.slice(0, clamped), dragged, ...others.slice(clamped)];
8236
- return reordered.map((el, order) => ({
8237
- instanceId: instanceIdOf(el),
8238
- type: el.getAttribute("data-ohw-section") ?? "",
8239
- order,
8240
- pagePath: currentPath
8241
- }));
8242
- }
8243
- function moveSectionInstance(instanceId, direction, currentPath) {
8244
- const sections = topLevelSections();
8245
- const index = sections.findIndex((el) => instanceIdOf(el) === instanceId);
8246
- if (index === -1) return null;
8247
- const siblingIndex = direction === "up" ? index - 1 : index + 1;
8248
- if (siblingIndex < 0 || siblingIndex >= sections.length) return null;
8249
- const entries = planSectionMove(instanceId, siblingIndex, currentPath);
8250
- if (!entries) return null;
8251
- applyPersistedOrder(entries);
8252
- return entries;
8253
- }
8254
- function applyPersistedOrder(entries) {
8255
- if (entries.length === 0) return;
8256
- const sections = topLevelSections();
8257
- if (sections.length === 0) return;
8258
- const orderIndex = new Map(entries.map((e) => [e.instanceId, e.order]));
8259
- const ordered = [...sections].sort((a, b) => {
8260
- const aOrder = orderIndex.get(instanceIdOf(a));
8261
- const bOrder = orderIndex.get(instanceIdOf(b));
8262
- if (aOrder === void 0 && bOrder === void 0) return 0;
8263
- if (aOrder === void 0) return 1;
8264
- if (bOrder === void 0) return -1;
8265
- return aOrder - bOrder;
8266
- });
8267
- let prev = null;
8268
- for (const el of ordered) {
8269
- if (prev) prev.after(el);
8270
- prev = el;
8271
- }
8272
- }
8273
- function getPageSectionOrderEntries(raw, currentPath) {
8274
- if (!raw) return [];
8275
- try {
8276
- const entries = JSON.parse(raw);
8277
- return entries.filter((e) => !e.pagePath || e.pagePath === currentPath);
8278
- } catch {
8279
- return [];
8280
- }
8281
- }
8282
- function rekeySectionSubtree(root, instanceId) {
8283
- const suffix = `::${instanceId}`;
8284
- const rekey = (el, attr) => {
8285
- const current = el.getAttribute(attr);
8286
- if (current) el.setAttribute(attr, `${current}${suffix}`);
8287
- };
8288
- if (root.hasAttribute("data-ohw-key")) rekey(root, "data-ohw-key");
8289
- if (root.hasAttribute("data-ohw-href-key")) rekey(root, "data-ohw-href-key");
8290
- root.querySelectorAll("[data-ohw-key]").forEach((el) => rekey(el, "data-ohw-key"));
8291
- root.querySelectorAll("[data-ohw-href-key]").forEach((el) => rekey(el, "data-ohw-href-key"));
8292
- }
8293
- function initSectionInstancesFromContent(content, currentPath) {
8294
- document.querySelectorAll("[data-ohw-section]:not([data-ohw-instance])").forEach((el) => {
8295
- el.setAttribute("data-ohw-instance", el.getAttribute("data-ohw-section") ?? "");
8296
- });
8297
- const entries = getPageSectionOrderEntries(content[SECTION_ORDER_KEY], currentPath);
8298
- for (const entry of entries) {
8299
- if (entry.instanceId === entry.type) continue;
8300
- if (document.querySelector(`[data-ohw-instance="${CSS.escape(entry.instanceId)}"]`)) continue;
8301
- const original = document.querySelector(
8302
- `[data-ohw-section="${CSS.escape(entry.type)}"][data-ohw-instance="${CSS.escape(entry.type)}"]`
8303
- );
8304
- if (!original) continue;
8305
- const clone = original.cloneNode(true);
8306
- clone.setAttribute("data-ohw-instance", entry.instanceId);
8307
- rekeySectionSubtree(clone, entry.instanceId);
8308
- original.insertAdjacentElement("afterend", clone);
8309
- }
8310
- applyPersistedOrder(entries);
8311
- }
8312
-
8313
8361
  // src/OhhwellsBridge.tsx
8314
8362
  var import_react_dom4 = require("react-dom");
8315
8363
  var import_navigation3 = require("next/navigation");
@@ -8617,7 +8665,7 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
8617
8665
  var import_react12 = require("react");
8618
8666
 
8619
8667
  // src/ui/dialog.tsx
8620
- var React8 = __toESM(require("react"), 1);
8668
+ var React9 = __toESM(require("react"), 1);
8621
8669
  var import_radix_ui6 = require("radix-ui");
8622
8670
  var import_lucide_react8 = require("lucide-react");
8623
8671
  var import_jsx_runtime18 = require("react/jsx-runtime");
@@ -8645,7 +8693,7 @@ function DialogOverlay({
8645
8693
  }
8646
8694
  );
8647
8695
  }
8648
- var DialogContent = React8.forwardRef(
8696
+ var DialogContent = React9.forwardRef(
8649
8697
  ({ className, children, showCloseButton = true, container, ...props }, ref) => {
8650
8698
  const positionMode = container ? "absolute" : "fixed";
8651
8699
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(DialogPortal, { container: container ?? void 0, children: [
@@ -8700,7 +8748,7 @@ function DialogFooter({
8700
8748
  }
8701
8749
  );
8702
8750
  }
8703
- var DialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
8751
+ var DialogTitle = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
8704
8752
  import_radix_ui6.Dialog.Title,
8705
8753
  {
8706
8754
  ref,
@@ -8712,7 +8760,7 @@ var DialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE
8712
8760
  }
8713
8761
  ));
8714
8762
  DialogTitle.displayName = import_radix_ui6.Dialog.Title.displayName;
8715
- var DialogDescription = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
8763
+ var DialogDescription = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
8716
8764
  import_radix_ui6.Dialog.Description,
8717
8765
  {
8718
8766
  ref,
@@ -8817,9 +8865,9 @@ function SectionTreeItem({
8817
8865
  var import_react9 = require("react");
8818
8866
 
8819
8867
  // src/ui/input.tsx
8820
- var React9 = __toESM(require("react"), 1);
8868
+ var React10 = __toESM(require("react"), 1);
8821
8869
  var import_jsx_runtime21 = require("react/jsx-runtime");
8822
- var Input = React9.forwardRef(
8870
+ var Input = React10.forwardRef(
8823
8871
  ({ className, type, ...props }, ref) => {
8824
8872
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
8825
8873
  "input",
@@ -10851,7 +10899,9 @@ function deleteNavbarItem(sourceAnchor) {
10851
10899
  var GLYPH_SELECTOR = "svg, img";
10852
10900
  function referenceBox(slot) {
10853
10901
  const row = slot.closest("[data-ohw-socials-row]") ?? slot.closest("a")?.parentElement ?? null;
10854
- const neighbour = row ? Array.from(row.querySelectorAll('[data-ohw-editable="icon"]')).find((el) => el !== slot) : null;
10902
+ const neighbour = row ? Array.from(row.querySelectorAll('[data-ohw-editable="icon"]')).find(
10903
+ (el) => el !== slot && !el.hasAttribute("data-ohw-social-icon-placeholder")
10904
+ ) : null;
10855
10905
  if (neighbour) {
10856
10906
  const box2 = neighbour.querySelector(GLYPH_SELECTOR)?.getBoundingClientRect();
10857
10907
  if (box2?.width && box2.height) return box2;
@@ -10876,11 +10926,14 @@ function iconMarkupSizedFor(slot, markup) {
10876
10926
  glyph.style.height = `${Math.round(box.height)}px`;
10877
10927
  return holder.innerHTML;
10878
10928
  }
10929
+ var ICON_SOURCE_ATTR = "data-ohw-icon-source";
10879
10930
  function applyIconMarkup(slot, markup) {
10880
10931
  if (!markup) return;
10932
+ if (slot.getAttribute(ICON_SOURCE_ATTR) === markup) return;
10881
10933
  const coloured = iconMarkupInheritingColour(markup);
10882
10934
  const sized = iconMarkupSizedFor(slot, coloured);
10883
10935
  if (slot.innerHTML !== sized) slot.innerHTML = sized;
10936
+ slot.setAttribute(ICON_SOURCE_ATTR, markup);
10884
10937
  if (sized === coloured) {
10885
10938
  requestAnimationFrame(() => {
10886
10939
  if (!slot.isConnected) return;
@@ -10915,7 +10968,7 @@ function iconMarkupInheritingColour(markup) {
10915
10968
 
10916
10969
  // src/lib/socials-items.ts
10917
10970
  var ICON_SELECTOR = '[data-ohw-editable="icon"]';
10918
- var PLACEHOLDER_SOCIAL_ICON = '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/><path d="M2 12h20"/></svg>';
10971
+ var PLACEHOLDER_SOCIAL_ICON = '<svg xmlns="http://www.w3.org/2000/svg" width="1.5em" height="1.5em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/><path d="M2 12h20"/></svg>';
10919
10972
  var PLACEHOLDER_SOCIAL_LABEL = "Social";
10920
10973
  var SOCIAL_KEY_RE = /(^|-)social(s)?(-|$)/i;
10921
10974
  var SOCIAL_PLATFORM_KEY_RE = /(^|-)(instagram|facebook|fb|linkedin|twitter|tiktok|youtube|threads|whatsapp|telegram|pinterest|snapchat|discord|behance|dribbble|vimeo|spotify|github|reddit|medium|twitch)(-|$)/i;
@@ -10994,31 +11047,71 @@ function listSocialsRows(root = document) {
10994
11047
  }
10995
11048
  var rowTemplates = /* @__PURE__ */ new Map();
10996
11049
  function markSocialsRows(root = document) {
10997
- root.querySelectorAll(`[${SOCIALS_ITEM_ATTR}]`).forEach((item) => {
10998
- item.removeAttribute(SOCIALS_ITEM_ATTR);
10999
- });
11050
+ const stillInARow = /* @__PURE__ */ new Set();
11000
11051
  listSocialsRows(root).forEach((row) => {
11001
- row.setAttribute(SOCIALS_ROW_ATTR, "");
11052
+ if (row.getAttribute(SOCIALS_ROW_ATTR) === null) row.setAttribute(SOCIALS_ROW_ATTR, "");
11053
+ queueMicrotask(
11054
+ () => markEmptySocialLabels(row.ownerDocument, row.ownerDocument.activeElement)
11055
+ );
11002
11056
  allowRowToWrap(row);
11003
11057
  const items = listSocialItems(row);
11004
11058
  const firstUnit = items[0] ? socialRowUnit(items[0], row) : null;
11005
11059
  if (firstUnit) rowTemplates.set(rowKeyOf(row), firstUnit.outerHTML);
11006
11060
  items.forEach((item, index) => {
11007
- item.setAttribute(SOCIALS_ITEM_ATTR, String(index));
11008
- const iconKey = socialIconKey(item);
11061
+ stillInARow.add(item);
11062
+ if (item.getAttribute(SOCIALS_ITEM_ATTR) !== String(index)) {
11063
+ item.setAttribute(SOCIALS_ITEM_ATTR, String(index));
11064
+ }
11065
+ const iconKey = socialIconKey(item) ?? socialHrefKey(item)?.replace(/-href$/, "");
11066
+ if (iconKey && !item.querySelector(ICON_SELECTOR)) {
11067
+ const drawn = item.querySelector("svg, img");
11068
+ if (drawn) adoptAsIconSlot(drawn, iconKey);
11069
+ }
11009
11070
  if (iconKey) ensureLabelSlot(item, iconKey);
11010
11071
  });
11011
11072
  });
11073
+ root.querySelectorAll(`[${SOCIALS_ITEM_ATTR}]`).forEach((item) => {
11074
+ if (!stillInARow.has(item)) item.removeAttribute(SOCIALS_ITEM_ATTR);
11075
+ });
11012
11076
  }
11013
11077
  var SOCIALS_LABEL_ATTR = "data-ohw-social-label";
11078
+ var SOCIALS_ICON_PLACEHOLDER_ATTR = "data-ohw-social-icon-placeholder";
11079
+ var SOCIALS_EMPTY_LABEL_ATTR = "data-ohw-empty-label";
11080
+ var EMPTY_LABEL_WIDTH = "8ch";
11081
+ function markEmptySocialLabels(root = document, skip) {
11082
+ root.querySelectorAll(`[${SOCIALS_ROW_ATTR}]`).forEach((row) => {
11083
+ listSocialItems(row).forEach((item) => {
11084
+ const label = socialLabelElement(item);
11085
+ if (!label || label === skip) return;
11086
+ const empty = !label.textContent?.trim();
11087
+ if (empty === label.hasAttribute(SOCIALS_EMPTY_LABEL_ATTR)) return;
11088
+ if (empty) {
11089
+ label.setAttribute(SOCIALS_EMPTY_LABEL_ATTR, "");
11090
+ label.style.display = "inline-block";
11091
+ label.style.minWidth = EMPTY_LABEL_WIDTH;
11092
+ label.style.minHeight = "1.4em";
11093
+ } else {
11094
+ label.removeAttribute(SOCIALS_EMPTY_LABEL_ATTR);
11095
+ label.style.display = "";
11096
+ label.style.minWidth = "";
11097
+ label.style.minHeight = "";
11098
+ }
11099
+ });
11100
+ });
11101
+ }
11014
11102
  function ensureLabelSlot(item, iconKey) {
11015
11103
  if (socialLabelElement(item)) return;
11016
11104
  const label = document.createElement("span");
11017
11105
  label.setAttribute("data-ohw-key", `${iconKey}-label`);
11018
11106
  label.setAttribute("data-ohw-editable", "text");
11019
11107
  label.setAttribute(SOCIALS_LABEL_ATTR, "");
11020
- label.style.display = "none";
11021
- label.textContent = item.getAttribute("aria-label") ?? "";
11108
+ const ownText = Array.from(item.childNodes).filter(
11109
+ (node) => node.nodeType === Node.TEXT_NODE && node.textContent?.trim()
11110
+ );
11111
+ const carried = ownText.map((node) => node.textContent?.trim()).join(" ");
11112
+ ownText.forEach((node) => node.remove());
11113
+ label.textContent = carried || item.getAttribute("aria-label") || "";
11114
+ label.style.display = carried ? "" : "none";
11022
11115
  item.appendChild(label);
11023
11116
  }
11024
11117
  function socialLabelElement(item) {
@@ -11029,17 +11122,26 @@ function socialLabelElement(item) {
11029
11122
  function socialLabelKey(iconKey) {
11030
11123
  return `${iconKey}-label`;
11031
11124
  }
11125
+ function isEmptyLabelValue(value) {
11126
+ return !value.replace(/<br\s*\/?>/gi, "").replace(/&nbsp;/gi, " ").trim();
11127
+ }
11032
11128
  function applyStoredValues(item, content) {
11033
11129
  const hrefKey = socialHrefKey(item);
11034
11130
  const iconKey = socialIconKey(item);
11035
11131
  if (hrefKey && content[hrefKey] !== void 0) item.setAttribute("href", content[hrefKey]);
11036
11132
  if (iconKey) {
11037
11133
  const glyph = item.querySelector(ICON_SELECTOR);
11038
- if (glyph && content[iconKey]) applyIconMarkup(glyph, content[iconKey]);
11134
+ if (glyph && content[iconKey]) {
11135
+ applyIconMarkup(glyph, content[iconKey]);
11136
+ glyph.removeAttribute(SOCIALS_ICON_PLACEHOLDER_ATTR);
11137
+ }
11039
11138
  const label = item.querySelector(`[${SOCIALS_LABEL_ATTR}]`);
11040
11139
  label?.setAttribute("data-ohw-key", socialLabelKey(iconKey));
11041
11140
  const stored = content[socialLabelKey(iconKey)];
11042
- if (label && stored) label.textContent = stored;
11141
+ if (label && stored !== void 0) {
11142
+ const words = isEmptyLabelValue(stored) ? "" : stored;
11143
+ if (label.innerHTML !== words) label.innerHTML = words;
11144
+ }
11043
11145
  }
11044
11146
  }
11045
11147
  function socialPlatformKey(iconKey) {
@@ -11076,7 +11178,7 @@ function getSocialsOrderFromDom(root = document) {
11076
11178
  }
11077
11179
  function hasStoredValue(content, hrefKey) {
11078
11180
  const iconKey = hrefKey.replace(/-href$/, "");
11079
- return Boolean(content[hrefKey]) || Boolean(content[iconKey]);
11181
+ return Boolean(content[hrefKey]) || Boolean(content[iconKey]) || Boolean(content[socialLabelKey(iconKey)]);
11080
11182
  }
11081
11183
  function parseSocialsOrder(raw) {
11082
11184
  if (!raw) return null;
@@ -11087,24 +11189,24 @@ function parseSocialsOrder(raw) {
11087
11189
  return null;
11088
11190
  }
11089
11191
  }
11090
- function nextSocialIndex(row, rowKey, content) {
11091
- const used = listSocialItems(row).map((item) => socialHrefKey(item)).concat(Object.keys(content)).map((key) => key?.match(new RegExp(`^${rowKey}-(\\d+)`))?.[1]).map((digits) => digits === void 0 ? -1 : Number(digits));
11192
+ function nextSocialIndex(row, rowKey, content, reserved = []) {
11193
+ const used = listSocialItems(row).map((item) => socialHrefKey(item)).concat(Object.keys(content)).concat(reserved).map((key) => key?.match(new RegExp(`^${rowKey}-(\\d+)`))?.[1]).map((digits) => digits === void 0 ? -1 : Number(digits));
11092
11194
  return Math.max(-1, ...used) + 1;
11093
11195
  }
11094
- function planSocialInsert(row, content = {}) {
11196
+ function planSocialInsert(row, content = {}, reserved = []) {
11095
11197
  if (!canAddSocialItem(row)) return null;
11096
11198
  const rowKey = rowKeyOf(row);
11097
- const iconKey = `${rowKey}-${nextSocialIndex(row, rowKey, content)}`;
11199
+ const iconKey = `${rowKey}-${nextSocialIndex(row, rowKey, content, reserved)}`;
11098
11200
  return { hrefKey: `${iconKey}-href`, iconKey };
11099
11201
  }
11100
- function insertSocialItem(row, after, content = {}, { placeholder = true } = {}) {
11202
+ function insertSocialItem(row, after, content = {}, { placeholder = true, keys } = {}) {
11101
11203
  const rowKey = rowKeyOf(row);
11102
11204
  const template = listSocialItems(row)[0];
11103
11205
  const remembered = rowTemplates.get(rowKey);
11104
11206
  if (!template && !remembered) return null;
11105
- const index = nextSocialIndex(row, rowKey, content);
11106
- const iconKey = `${rowKey}-${index}`;
11107
- const hrefKey = `${iconKey}-href`;
11207
+ const display = socialsDisplayFor(row, content);
11208
+ const iconKey = keys?.iconKey ?? `${rowKey}-${nextSocialIndex(row, rowKey, content)}`;
11209
+ const hrefKey = keys?.hrefKey ?? `${iconKey}-href`;
11108
11210
  const templateUnit = template ? socialRowUnit(template) : null;
11109
11211
  const unit = templateUnit ? templateUnit.cloneNode(true) : fromMarkup(remembered);
11110
11212
  const item = unit && (unit.matches("a") ? unit : unit.querySelector("a"));
@@ -11119,6 +11221,7 @@ function insertSocialItem(row, after, content = {}, { placeholder = true } = {})
11119
11221
  const icon = item.querySelector(ICON_SELECTOR);
11120
11222
  icon?.setAttribute("data-ohw-key", iconKey);
11121
11223
  if (placeholder && icon) icon.innerHTML = PLACEHOLDER_SOCIAL_ICON;
11224
+ socialLabelElement(item)?.setAttribute("data-ohw-key", socialLabelKey(iconKey));
11122
11225
  item.querySelector(`[${SOCIALS_LABEL_ATTR}]`)?.remove();
11123
11226
  const afterUnit = after ? socialRowUnit(after) : null;
11124
11227
  if (afterUnit && afterUnit.parentElement === row) afterUnit.insertAdjacentElement("afterend", unit);
@@ -11128,7 +11231,7 @@ function insertSocialItem(row, after, content = {}, { placeholder = true } = {})
11128
11231
  const label = socialLabelElement(item);
11129
11232
  if (label) label.textContent = PLACEHOLDER_SOCIAL_LABEL;
11130
11233
  }
11131
- applySocialsDisplayToRow(row, socialsDisplayFor(row, content));
11234
+ applySocialsDisplayToRow(row, display);
11132
11235
  return { item, hrefKey, iconKey, order: getSocialsOrderFromDom(row.ownerDocument) };
11133
11236
  }
11134
11237
  function duplicateSocialItem(item, content) {
@@ -11145,9 +11248,9 @@ function duplicateSocialItem(item, content) {
11145
11248
  const slot = link.querySelector(ICON_SELECTOR);
11146
11249
  if (slot) slot.innerHTML = glyph;
11147
11250
  }
11148
- const sourceLabel = socialLabelElement(item)?.textContent?.trim();
11251
+ const sourceLabel = socialLabelElement(item);
11149
11252
  const copyLabel = socialLabelElement(link);
11150
- if (copyLabel && sourceLabel) copyLabel.textContent = sourceLabel;
11253
+ if (copyLabel && sourceLabel) copyLabel.innerHTML = sourceLabel.innerHTML;
11151
11254
  if (row) applySocialsDisplayToRow(row, socialsDisplayFor(row, content));
11152
11255
  return {
11153
11256
  ...created,
@@ -11188,17 +11291,32 @@ function applySocialsOrder(order, root = document) {
11188
11291
  const wanted = order[rowKeyOf(row)];
11189
11292
  if (!wanted) return;
11190
11293
  const byKey = new Map(listSocialItems(row).map((item) => [socialHrefKey(item), item]));
11191
- wanted.forEach((key) => {
11192
- const item = byKey.get(key);
11193
- if (!item) return;
11194
- const unit = socialRowUnit(item, row);
11195
- if (unit) row.appendChild(unit);
11196
- });
11294
+ const units = wanted.map((key) => byKey.get(key)).filter((item) => Boolean(item)).map((item) => socialRowUnit(item, row)).filter((unit) => Boolean(unit));
11295
+ const tail = Array.from(row.children).slice(-units.length);
11296
+ const inPlace = units.length > 0 && tail.length === units.length && units.every((unit, i) => tail[i] === unit);
11297
+ if (inPlace) return;
11298
+ units.forEach((unit) => row.appendChild(unit));
11197
11299
  });
11198
11300
  markSocialsRows(root);
11199
11301
  }
11200
11302
  function reconcileSocialsFromContent(content, root = document) {
11201
11303
  markSocialsRows(root);
11304
+ listSocialsRows(root).forEach((row) => {
11305
+ const rowDisplay = socialsDisplayFor(row, content);
11306
+ listSocialItems(row).forEach((item) => {
11307
+ const key = socialIconKey(item) ?? socialHrefKey(item)?.replace(/-href$/, "");
11308
+ const stored2 = key ? content[key] : void 0;
11309
+ if (!stored2?.trim()) return;
11310
+ const existing = item.querySelector(ICON_SELECTOR);
11311
+ if (existing && existing.innerHTML.trim() && !existing.hasAttribute(SOCIALS_ICON_PLACEHOLDER_ATTR)) return;
11312
+ ensureIconSlot(item);
11313
+ const slot = item.querySelector(ICON_SELECTOR);
11314
+ if (!slot) return;
11315
+ applyIconMarkup(slot, stored2);
11316
+ slot.removeAttribute(SOCIALS_ICON_PLACEHOLDER_ATTR);
11317
+ if (!rowDisplay.icon) slot.style.display = "none";
11318
+ });
11319
+ });
11202
11320
  const stored = parseSocialsOrder(content[SOCIALS_ORDER_KEY]);
11203
11321
  if (!stored) return;
11204
11322
  listSocialsRows(root).forEach((row) => {
@@ -11208,12 +11326,11 @@ function reconcileSocialsFromContent(content, root = document) {
11208
11326
  wanted.forEach((key) => {
11209
11327
  if (listSocialItems(row).some((item) => socialHrefKey(item) === key)) return;
11210
11328
  if (!hasStoredValue(content, key)) return;
11211
- const created = insertSocialItem(row, null, content);
11212
- if (created) {
11213
- created.item.setAttribute("data-ohw-href-key", key);
11214
- created.item.querySelector(ICON_SELECTOR)?.setAttribute("data-ohw-key", key.replace(/-href$/, ""));
11215
- applyStoredValues(created.item, content);
11216
- }
11329
+ const created = insertSocialItem(row, null, content, {
11330
+ placeholder: false,
11331
+ keys: { hrefKey: key, iconKey: key.replace(/-href$/, "") }
11332
+ });
11333
+ if (created) applyStoredValues(created.item, content);
11217
11334
  });
11218
11335
  const present = listSocialItems(row);
11219
11336
  const surviving = present.filter((item) => {
@@ -11288,9 +11405,10 @@ var SOCIALS_DISPLAY_KEY = "__ohw_socials_display";
11288
11405
  function readSocialsDisplay(row) {
11289
11406
  const items = listSocialItems(row);
11290
11407
  const visible = (el) => Boolean(el) && el.style.display !== "none" && el.getAttribute("data-ohw-hidden") === null;
11408
+ const drawn = (el) => Boolean(el && visible(el) && el.innerHTML.trim());
11291
11409
  return {
11292
11410
  text: items.some((item) => visible(socialLabelElement(item))),
11293
- icon: items.some((item) => visible(item.querySelector(ICON_SELECTOR)))
11411
+ icon: items.some((item) => drawn(item.querySelector(ICON_SELECTOR)))
11294
11412
  };
11295
11413
  }
11296
11414
  function parseSocialsDisplay(raw) {
@@ -11338,6 +11456,20 @@ function allowRowToWrap(row) {
11338
11456
  const display = row.ownerDocument.defaultView?.getComputedStyle(row).display ?? "";
11339
11457
  if (display === "flex" || display === "inline-flex") row.style.flexWrap = "wrap";
11340
11458
  }
11459
+ function applySocialsLabelsFromContent(content, root = document, { fillEmptyOnly = false } = {}) {
11460
+ const focused = root.activeElement ?? document.activeElement;
11461
+ listSocialsRows(root).forEach((row) => {
11462
+ listSocialItems(row).forEach((item) => {
11463
+ const label = socialLabelElement(item);
11464
+ const key = label?.getAttribute("data-ohw-key");
11465
+ const stored = key ? content[key] : void 0;
11466
+ if (!label || !stored || label === focused) return;
11467
+ if (fillEmptyOnly && label.textContent?.trim()) return;
11468
+ if (!stored.replace(/<br\s*\/?>/gi, "").trim()) return;
11469
+ if (label.innerHTML !== stored) label.innerHTML = stored;
11470
+ });
11471
+ });
11472
+ }
11341
11473
  function applySocialsDisplayFromContent(content, root = document) {
11342
11474
  const stored = parseSocialsDisplay(content[SOCIALS_DISPLAY_KEY]);
11343
11475
  if (!stored) return;
@@ -11357,8 +11489,27 @@ function applySocialsDisplayFromContent(content, root = document) {
11357
11489
  function socialsMissingIcons(row) {
11358
11490
  return listSocialItems(row).filter((item) => {
11359
11491
  const slot = item.querySelector(ICON_SELECTOR);
11360
- return !slot || !slot.firstElementChild;
11361
- }).map((item) => ({ hrefKey: socialHrefKey(item) ?? "", url: item.getAttribute("href") ?? "" })).filter((entry) => Boolean(entry.hrefKey));
11492
+ return !slot || !slot.firstElementChild || slot.hasAttribute(SOCIALS_ICON_PLACEHOLDER_ATTR);
11493
+ }).map((item) => ({
11494
+ hrefKey: socialHrefKey(item) ?? "",
11495
+ url: item.getAttribute("href") ?? "",
11496
+ // Templates ship placeholder addresses — serene-oasis writes "[INSTAGRAM URL]" — and then the
11497
+ // words are the only thing naming the network.
11498
+ label: (socialLabelElement(item)?.textContent ?? item.getAttribute("aria-label") ?? "").trim()
11499
+ })).filter((entry) => Boolean(entry.hrefKey));
11500
+ }
11501
+ function adoptAsIconSlot(drawn, base) {
11502
+ const parent = drawn.parentElement;
11503
+ if (!parent) return null;
11504
+ const taken = drawn.ownerDocument.querySelector(`[data-ohw-key="${base}"]`);
11505
+ const iconKey = taken ? `${base}-icon` : base;
11506
+ const slot = drawn.ownerDocument.createElement("span");
11507
+ slot.setAttribute("data-ohw-key", iconKey);
11508
+ slot.setAttribute("data-ohw-editable", "icon");
11509
+ slot.style.display = "inline-flex";
11510
+ parent.insertBefore(slot, drawn);
11511
+ slot.appendChild(drawn);
11512
+ return iconKey;
11362
11513
  }
11363
11514
  function ensureIconSlot(item) {
11364
11515
  const existing = item.querySelector(ICON_SELECTOR);
@@ -11366,12 +11517,19 @@ function ensureIconSlot(item) {
11366
11517
  const hrefKey = socialHrefKey(item);
11367
11518
  if (!hrefKey) return null;
11368
11519
  const base = hrefKey.replace(/-href$/, "");
11520
+ const drawn = item.querySelector("svg, img");
11521
+ if (drawn) {
11522
+ const adopted = adoptAsIconSlot(drawn, base);
11523
+ if (adopted) return adopted;
11524
+ }
11369
11525
  const taken = document.querySelector(`[data-ohw-key="${base}"]`);
11370
11526
  const iconKey = taken && taken !== item ? `${base}-icon` : base;
11371
11527
  const slot = document.createElement("span");
11372
11528
  slot.setAttribute("data-ohw-key", iconKey);
11373
11529
  slot.setAttribute("data-ohw-editable", "icon");
11374
11530
  slot.style.display = "inline-flex";
11531
+ slot.innerHTML = PLACEHOLDER_SOCIAL_ICON;
11532
+ slot.setAttribute(SOCIALS_ICON_PLACEHOLDER_ATTR, "");
11375
11533
  item.prepend(slot);
11376
11534
  return iconKey;
11377
11535
  }
@@ -13945,12 +14103,27 @@ function collectEditableNodes(extraContent, root = document) {
13945
14103
  nodes.push({ key, type: "link", text: href });
13946
14104
  }
13947
14105
  if (extraContent) {
13948
- for (const key of [NAV_ORDER_KEY, FOOTER_ORDER_KEY, NAV_COUNT_KEY, SECTION_ORDER_KEY]) {
14106
+ for (const key of [
14107
+ NAV_ORDER_KEY,
14108
+ FOOTER_ORDER_KEY,
14109
+ NAV_COUNT_KEY,
14110
+ SECTION_ORDER_KEY,
14111
+ // A socials row's order and its icons-vs-words setting live under keys no element carries,
14112
+ // so collecting the DOM alone left them behind: the draft knew the row was showing icons and
14113
+ // had gained an item, and the published page went back to the template's own (OHH-736).
14114
+ SOCIALS_ORDER_KEY,
14115
+ SOCIALS_DISPLAY_KEY
14116
+ ]) {
13949
14117
  const text = extraContent[key];
13950
14118
  if (typeof text === "string" && text.length > 0) {
13951
14119
  nodes.push({ key, type: "meta", text });
13952
14120
  }
13953
14121
  }
14122
+ for (const [key, text] of Object.entries(extraContent)) {
14123
+ if (key.endsWith("-platform") && typeof text === "string" && text.length > 0) {
14124
+ nodes.push({ key, type: "meta", text });
14125
+ }
14126
+ }
13954
14127
  }
13955
14128
  if (!isScoped) {
13956
14129
  document.querySelectorAll('[data-ohw-editable="video"]').forEach((el) => {
@@ -14303,7 +14476,7 @@ function NavbarContainerChrome({
14303
14476
  }
14304
14477
 
14305
14478
  // src/ui/drop-indicator.tsx
14306
- var React10 = __toESM(require("react"), 1);
14479
+ var React11 = __toESM(require("react"), 1);
14307
14480
  var import_jsx_runtime31 = require("react/jsx-runtime");
14308
14481
  var dropIndicatorVariants = cva(
14309
14482
  "ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
@@ -14326,7 +14499,7 @@ var dropIndicatorVariants = cva(
14326
14499
  }
14327
14500
  }
14328
14501
  );
14329
- var DropIndicator = React10.forwardRef(
14502
+ var DropIndicator = React11.forwardRef(
14330
14503
  ({ className, direction, state, ...props }, ref) => {
14331
14504
  return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
14332
14505
  "div",
@@ -14940,6 +15113,15 @@ function isPointOverNavItem(container, x, y) {
14940
15113
  return x >= itemRect.left && x <= itemRect.right && y >= itemRect.top && y <= itemRect.bottom;
14941
15114
  });
14942
15115
  }
15116
+ function socialsRowAtPoint(x, y) {
15117
+ const inside = (el) => {
15118
+ const r2 = el.getBoundingClientRect();
15119
+ return x >= r2.left && x <= r2.right && y >= r2.top && y <= r2.bottom;
15120
+ };
15121
+ return Array.from(document.querySelectorAll(`[${SOCIALS_ROW_ATTR}]`)).find(
15122
+ (row) => inside(row) && !listSocialItems(row).some(inside)
15123
+ ) ?? null;
15124
+ }
14943
15125
  function isPointOverFooterColumn(x, y) {
14944
15126
  return listFooterColumns().some((col) => {
14945
15127
  const r2 = col.getBoundingClientRect();
@@ -16256,7 +16438,7 @@ function OhhwellsBridge() {
16256
16438
  const original = originalContentRef.current ?? "";
16257
16439
  if (html !== sanitizeHtml(original)) {
16258
16440
  postToParentRef.current({ type: "ow:change", nodes: [{ key, text: html }] });
16259
- const h = document.documentElement.scrollHeight;
16441
+ const h = document.body.scrollHeight;
16260
16442
  if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
16261
16443
  }
16262
16444
  }
@@ -16418,7 +16600,7 @@ function OhhwellsBridge() {
16418
16600
  const original = originalContentRef.current ?? "";
16419
16601
  if (html !== sanitizeHtml(original)) {
16420
16602
  postToParent2({ type: "ow:change", nodes: [{ key, text: html }] });
16421
- const h = document.documentElement.scrollHeight;
16603
+ const h = document.body.scrollHeight;
16422
16604
  if (h > 50) postToParent2({ type: "ow:height", height: h });
16423
16605
  }
16424
16606
  }
@@ -16522,7 +16704,8 @@ function OhhwellsBridge() {
16522
16704
  return;
16523
16705
  }
16524
16706
  const after = getSocialItem(selected);
16525
- const planned = planSocialInsert(socialsRow, editContentRef.current);
16707
+ const stillPromised = pendingSocialAddRef.current ? [pendingSocialAddRef.current.iconKey] : [];
16708
+ const planned = planSocialInsert(socialsRow, editContentRef.current, stillPromised);
16526
16709
  if (!planned) return;
16527
16710
  pendingSocialAddRef.current = { row: socialsRow, after, ...planned };
16528
16711
  postToParentRef.current({
@@ -16782,7 +16965,8 @@ function OhhwellsBridge() {
16782
16965
  applySocialsOrder(nextSocialsOrder);
16783
16966
  postToParentRef.current({
16784
16967
  type: "ow:change",
16785
- nodes: [{ key: SOCIALS_ORDER_KEY, text: orderJson }]
16968
+ nodes: [{ key: SOCIALS_ORDER_KEY, text: orderJson }],
16969
+ flush: true
16786
16970
  });
16787
16971
  applySelectionAfterDrop();
16788
16972
  clearFooterDragVisuals();
@@ -16972,7 +17156,7 @@ function OhhwellsBridge() {
16972
17156
  }
16973
17157
  const selected = selectedElRef.current;
16974
17158
  if (!selected || !isNavigationItem2(selected)) return;
16975
- const editable = selected.querySelector('[data-ohw-editable="text"]') ?? selected.querySelector("[data-ohw-editable]");
17159
+ const editable = selected.querySelector('[data-ohw-editable="text"], [data-ohw-editable="plain"]') ?? selected.querySelector('[data-ohw-editable]:not([data-ohw-editable="icon"])');
16976
17160
  if (!editable) return;
16977
17161
  activateRef.current(editable, { caretX: clientX, caretY: clientY });
16978
17162
  }, []);
@@ -17127,13 +17311,16 @@ function OhhwellsBridge() {
17127
17311
  const isEditModeRef = (0, import_react17.useRef)(false);
17128
17312
  const requestMissingSocialIconsRef = (0, import_react17.useRef)(() => {
17129
17313
  });
17314
+ const askedSocialIconsRef = (0, import_react17.useRef)(/* @__PURE__ */ new Set());
17130
17315
  const requestMissingSocialIcons = (0, import_react17.useCallback)(() => {
17131
17316
  const items = Array.from(document.querySelectorAll(`[${SOCIALS_ROW_ATTR}]`)).filter((row) => socialsDisplayFor(row, editContentRef.current).icon).flatMap((row) => {
17132
17317
  const missing = socialsMissingIcons(row);
17133
17318
  listSocialItems(row).forEach((item) => ensureIconSlot(item));
17134
17319
  return missing;
17135
17320
  });
17136
- if (items.length) postToParentRef.current({ type: "ow:social-icons-needed", items });
17321
+ const fresh = items.filter((item) => !askedSocialIconsRef.current.has(`${item.hrefKey}|${item.url}`));
17322
+ fresh.forEach((item) => askedSocialIconsRef.current.add(`${item.hrefKey}|${item.url}`));
17323
+ if (fresh.length) postToParentRef.current({ type: "ow:social-icons-needed", items: fresh });
17137
17324
  }, []);
17138
17325
  requestMissingSocialIconsRef.current = requestMissingSocialIcons;
17139
17326
  isEditModeRef.current = isEditMode;
@@ -17142,6 +17329,7 @@ function OhhwellsBridge() {
17142
17329
  if (next.icon) {
17143
17330
  const missing = socialsMissingIcons(row);
17144
17331
  listSocialItems(row).forEach((item) => ensureIconSlot(item));
17332
+ missing.forEach((item) => askedSocialIconsRef.current.delete(`${item.hrefKey}|${item.url}`));
17145
17333
  if (missing.length) {
17146
17334
  postToParentRef.current({ type: "ow:social-icons-needed", items: missing });
17147
17335
  }
@@ -17231,7 +17419,15 @@ function OhhwellsBridge() {
17231
17419
  );
17232
17420
  const activate = (0, import_react17.useCallback)((el, options) => {
17233
17421
  if (activeElRef.current === el) return;
17234
- if (isIconEditable(el)) return;
17422
+ if (isIconEditable(el)) {
17423
+ const social = getSocialItem(el);
17424
+ const words = social ? social.querySelector('[data-ohw-editable="text"], [data-ohw-editable="plain"]') : null;
17425
+ if (words && words.offsetParent !== null) {
17426
+ if (social && selectedElRef.current !== social) selectRef.current(social);
17427
+ activateRef.current(words, options);
17428
+ }
17429
+ return;
17430
+ }
17235
17431
  if (el.hasAttribute("data-ohw-social-label") && el.offsetParent === null) return;
17236
17432
  clearSelectedAttr();
17237
17433
  selectedElRef.current = null;
@@ -17410,6 +17606,7 @@ function OhhwellsBridge() {
17410
17606
  reconcileFooterOrderFromContent(content);
17411
17607
  reconcileSocialsFromContent(content);
17412
17608
  applySocialsDisplayFromContent(content);
17609
+ applySocialsLabelsFromContent(content, document, { fillEmptyOnly: isEditModeRef.current });
17413
17610
  if (isEditModeRef.current) requestMissingSocialIconsRef.current();
17414
17611
  enforceLinkHrefs();
17415
17612
  initSectionsFromContent(content, true);
@@ -17595,6 +17792,7 @@ function OhhwellsBridge() {
17595
17792
  reconcileFooterOrderFromContent(content);
17596
17793
  reconcileSocialsFromContent(content);
17597
17794
  applySocialsDisplayFromContent(content);
17795
+ applySocialsLabelsFromContent(content, document, { fillEmptyOnly: isEditModeRef.current });
17598
17796
  if (isEditModeRef.current) requestMissingSocialIconsRef.current();
17599
17797
  document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
17600
17798
  if (!form.querySelector("[data-ohw-form-success]")) {
@@ -17681,6 +17879,7 @@ function OhhwellsBridge() {
17681
17879
  reconcileFooterOrderFromContent(content);
17682
17880
  reconcileSocialsFromContent(content);
17683
17881
  applySocialsDisplayFromContent(content);
17882
+ applySocialsLabelsFromContent(content, document, { fillEmptyOnly: isEditModeRef.current });
17684
17883
  if (isEditModeRef.current) requestMissingSocialIconsRef.current();
17685
17884
  document.querySelectorAll("footer [data-ohw-href-key]").forEach((el) => {
17686
17885
  if (isFooterHrefKey(el.getAttribute("data-ohw-href-key")) || getSocialItem(el)) {
@@ -17785,6 +17984,66 @@ function OhhwellsBridge() {
17785
17984
  [style*="100vh"] { min-height: ${initialVh}px !important; height: ${initialVh}px !important; }
17786
17985
  [style*="100svh"] { min-height: ${initialVh}px !important; height: ${initialVh}px !important; }
17787
17986
  [style*="100dvh"] { min-height: ${initialVh}px !important; height: ${initialVh}px !important; }
17987
+ /* Emptied text keeps somewhere to click. A label typed down to nothing collapses to a
17988
+ couple of pixels, and getting back into it meant hunting for the caret with the mouse.
17989
+ Edit mode only \u2014 the published page shows nothing where there is nothing (OHH-736). */
17990
+ [data-ohw-editable="text"]:empty,
17991
+ [data-ohw-editable="plain"]:empty,
17992
+ [data-ohw-editable="text"]:has(> br:only-child),
17993
+ [data-ohw-editable="plain"]:has(> br:only-child) {
17994
+ min-width: 8ch;
17995
+ min-height: 1.4em;
17996
+ padding: 0 4px;
17997
+ }
17998
+ /* A social left deliberately wordless is a choice, not a mistake, so its empty label takes no
17999
+ room at rest \u2014 the row stays as tight as the site draws it. The box appears only while that
18000
+ row is being worked on: pointer over it, or the item selected (OHH-736). */
18001
+ /* The room itself is kept by the element in both modes \u2014 see markEmptySocialLabels. Left
18002
+ here is only what belongs to editing: something to aim at inside that room. */
18003
+ [data-ohw-socials-row] [data-ohw-empty-label] {
18004
+ padding: 0 4px;
18005
+ }
18006
+ [data-ohw-editable="text"]:empty::before,
18007
+ [data-ohw-editable="plain"]:empty::before {
18008
+ content: '';
18009
+ display: inline-block;
18010
+ width: 100%;
18011
+ height: 1.4em;
18012
+ }
18013
+ /* Not inside a socials row. A stand-in the width of its container is right for a paragraph
18014
+ that has been emptied, but beside an icon it opened a gap as wide as the row would allow:
18015
+ the editor showed the icons strewn across three lines while the published page \u2014 which
18016
+ carries no editing chrome at all \u2014 packed them together, and the two looked nothing alike
18017
+ (OHH-736). The box is given its width on hover and selection instead, which is when it is
18018
+ there to be clicked into. */
18019
+ [data-ohw-socials-row] [data-ohw-editable="text"]:empty::before,
18020
+ [data-ohw-socials-row] [data-ohw-editable="plain"]:empty::before {
18021
+ width: 0;
18022
+ }
18023
+ /* Room inside a socials row so the row itself can be clicked. Without it the items fill their
18024
+ own frame edge to edge and the only way to the row was through an icon and Select parent. */
18025
+ [data-ohw-socials-row] {
18026
+ padding: 6px;
18027
+ }
18028
+ /* A row of socials stays a row. The blanket block above is for body text; applied to the
18029
+ words inside a social it stacked every item on its own line, so instead of wrapping the
18030
+ row grew downwards and pushed the footer with it (OHH-736). */
18031
+ [data-ohw-socials-row] [data-ohw-editable="text"],
18032
+ [data-ohw-socials-row] [data-ohw-editable="plain"] {
18033
+ display: inline-block;
18034
+ }
18035
+ /* The glyph too, and this one mattered most: as a block it filled the whole width of its
18036
+ link and sat over the words, so every click meant for the text landed on the icon. */
18037
+ [data-ohw-socials-row] [data-ohw-editable="icon"] {
18038
+ display: inline-flex;
18039
+ flex: 0 0 auto;
18040
+ align-items: center;
18041
+ }
18042
+ [data-ohw-socials-row] a {
18043
+ display: inline-flex;
18044
+ align-items: center;
18045
+ gap: 6px;
18046
+ }
17788
18047
  /* Not the form: it is a layout container (flex/grid with gaps), and forcing block
17789
18048
  crushed its fields together (OHH-490). */
17790
18049
  [data-ohw-editable]:not([data-ohw-editable="form"]) {
@@ -18037,6 +18296,13 @@ function OhhwellsBridge() {
18037
18296
  return;
18038
18297
  }
18039
18298
  }
18299
+ const socialsRowUnderPoint = socialsRowAtPoint(e.clientX, e.clientY);
18300
+ if (socialsRowUnderPoint) {
18301
+ e.preventDefault();
18302
+ e.stopPropagation();
18303
+ selectFrameRef.current(socialsRowUnderPoint);
18304
+ return;
18305
+ }
18040
18306
  const logoEl = getLogoElement(target);
18041
18307
  if (logoEl) {
18042
18308
  e.preventDefault();
@@ -18091,6 +18357,19 @@ function OhhwellsBridge() {
18091
18357
  }
18092
18358
  return;
18093
18359
  }
18360
+ const socialItem = getSocialItem(editable);
18361
+ const isVisibleWords = (editable.dataset.ohwEditable === "text" || editable.dataset.ohwEditable === "plain") && editable.offsetParent !== null;
18362
+ if (socialItem && isVisibleWords) {
18363
+ e.preventDefault();
18364
+ e.stopPropagation();
18365
+ if (activeElRef.current === editable) return;
18366
+ if (selectedElRef.current === socialItem) {
18367
+ activateRef.current(editable, { caretX: e.clientX, caretY: e.clientY });
18368
+ return;
18369
+ }
18370
+ selectRef.current(socialItem);
18371
+ return;
18372
+ }
18094
18373
  const hrefLookupTarget = buttonOnMedia ? clickedButton : editable;
18095
18374
  const hrefCtx = getHrefKeyFromElement(hrefLookupTarget);
18096
18375
  const navAnchor = hrefCtx ? getNavigationItemAnchor(hrefCtx.anchor) : null;
@@ -18160,7 +18439,7 @@ function OhhwellsBridge() {
18160
18439
  selectFrameRef.current(navContainerToSelect);
18161
18440
  return;
18162
18441
  }
18163
- const socialsRowToSelect = isSocialsRow(target) ? target : null;
18442
+ const socialsRowToSelect = isSocialsRow(target) ? target : findSocialsRow(target);
18164
18443
  if (socialsRowToSelect && !getSocialItem(target)) {
18165
18444
  e.preventDefault();
18166
18445
  e.stopPropagation();
@@ -19162,15 +19441,25 @@ function OhhwellsBridge() {
19162
19441
  if (pending && updates.some((update) => update.hrefKey === pending.hrefKey)) {
19163
19442
  pendingSocialAddRef.current = null;
19164
19443
  if (pending.row.isConnected) {
19165
- const created = insertSocialItem(pending.row, pending.after, editContentRef.current);
19444
+ const created = insertSocialItem(pending.row, pending.after, editContentRef.current, {
19445
+ keys: { hrefKey: pending.hrefKey, iconKey: pending.iconKey }
19446
+ });
19166
19447
  if (created) {
19167
19448
  const orderJson = JSON.stringify(created.order);
19168
19449
  editContentRef.current = { ...editContentRef.current, [SOCIALS_ORDER_KEY]: orderJson };
19169
19450
  nodes.push({ key: SOCIALS_ORDER_KEY, text: orderJson });
19451
+ const words = created.item.querySelector(
19452
+ '[data-ohw-social-label], [data-ohw-editable="text"], [data-ohw-editable="plain"]'
19453
+ );
19454
+ const labelKey = words?.getAttribute("data-ohw-key");
19455
+ const labelText = words?.textContent?.trim();
19456
+ if (labelKey && labelText && !editContentRef.current[labelKey]) {
19457
+ nodes.push({ key: labelKey, text: labelText });
19458
+ }
19170
19459
  }
19171
19460
  }
19172
19461
  }
19173
- for (const { hrefKey, iconKey: requestedIconKey, url, iconMarkup, platformId, label } of updates) {
19462
+ for (const { hrefKey, iconKey: requestedIconKey, url, iconMarkup, platformId, label, keepLabel } of updates) {
19174
19463
  if (hrefKey) {
19175
19464
  document.querySelectorAll(`[data-ohw-href-key="${hrefKey}"]`).forEach((el) => applyLinkHref(el, url));
19176
19465
  nodes.push({ key: hrefKey, text: url });
@@ -19182,6 +19471,7 @@ function OhhwellsBridge() {
19182
19471
  if (iconKey && typeof iconMarkup === "string" && iconMarkup) {
19183
19472
  document.querySelectorAll(`[data-ohw-key="${iconKey}"][data-ohw-editable="icon"]`).forEach((el) => {
19184
19473
  applyIconMarkup(el, iconMarkup);
19474
+ el.removeAttribute(SOCIALS_ICON_PLACEHOLDER_ATTR);
19185
19475
  });
19186
19476
  nodes.push({ key: iconKey, text: iconMarkup });
19187
19477
  }
@@ -19189,9 +19479,10 @@ function OhhwellsBridge() {
19189
19479
  if (iconKey && label) {
19190
19480
  const labelKey = socialLabelKey(iconKey);
19191
19481
  document.querySelectorAll(`[data-ohw-key="${labelKey}"]`).forEach((el) => {
19482
+ if (keepLabel && el.textContent?.trim()) return;
19192
19483
  el.textContent = label;
19193
19484
  });
19194
- nodes.push({ key: labelKey, text: label });
19485
+ if (!keepLabel) nodes.push({ key: labelKey, text: label });
19195
19486
  }
19196
19487
  }
19197
19488
  if (!nodes.length) return;
@@ -19324,8 +19615,11 @@ function OhhwellsBridge() {
19324
19615
  }
19325
19616
  setMaxBadge({ rect: el.getBoundingClientRect(), current: Math.min(current, maxLen), max: maxLen });
19326
19617
  }
19618
+ if (el.closest(`[${SOCIALS_ROW_ATTR}]`)) markEmptySocialLabels(document, el);
19327
19619
  const html = sanitizeHtml(el.innerHTML);
19328
- document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((sibling) => {
19620
+ editContentRef.current = { ...editContentRef.current, [key]: html };
19621
+ const sharing = document.querySelectorAll(`[data-ohw-key="${key}"]`);
19622
+ sharing.forEach((sibling) => {
19329
19623
  if (sibling !== el) sibling.innerHTML = html;
19330
19624
  });
19331
19625
  const timers = autoSaveTimers.current;
@@ -19334,7 +19628,7 @@ function OhhwellsBridge() {
19334
19628
  timers.set(key, setTimeout(() => {
19335
19629
  timers.delete(key);
19336
19630
  postToParentRef.current({ type: "ow:change", nodes: [{ key, text: html }] });
19337
- const h = document.documentElement.scrollHeight;
19631
+ const h = document.body.scrollHeight;
19338
19632
  if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
19339
19633
  }, 400));
19340
19634
  };
@@ -19402,7 +19696,7 @@ function OhhwellsBridge() {
19402
19696
  reconcileFooterOrderFromContent(editContentRef.current);
19403
19697
  syncNavigationDragCursorAttrs();
19404
19698
  enforceLinkHrefs();
19405
- const hydratedHeight = document.documentElement.scrollHeight;
19699
+ const hydratedHeight = document.body.scrollHeight;
19406
19700
  if (hydratedHeight > 50) postToParentRef.current({ type: "ow:height", height: hydratedHeight });
19407
19701
  postToParentRef.current({ type: "ow:hydrate-done" });
19408
19702
  };
@@ -19484,7 +19778,7 @@ function OhhwellsBridge() {
19484
19778
  const nextValue = serializeAiSectionsState(nextState);
19485
19779
  aiSectionsRef.current = nextValue;
19486
19780
  applyAiSectionsToDom(nextState);
19487
- const newHeight = document.documentElement.scrollHeight;
19781
+ const newHeight = document.body.scrollHeight;
19488
19782
  if (newHeight > 50) postToParentRef.current({ type: "ow:height", height: newHeight });
19489
19783
  postToParentRef.current({ type: "ow:change", nodes: [{ key: AI_SECTIONS_KEY, text: nextValue }] });
19490
19784
  const appliedEl = document.querySelector(`[data-ohw-section="${CSS.escape(payload.id)}"]`);
@@ -19506,7 +19800,7 @@ function OhhwellsBridge() {
19506
19800
  const nextValue = serializeAiSectionsState(nextState);
19507
19801
  aiSectionsRef.current = nextValue;
19508
19802
  applyAiSectionsToDom(nextState);
19509
- const newHeight = document.documentElement.scrollHeight;
19803
+ const newHeight = document.body.scrollHeight;
19510
19804
  if (newHeight > 50) postToParentRef.current({ type: "ow:height", height: newHeight });
19511
19805
  postToParentRef.current({ type: "ow:change", nodes: [{ key: AI_SECTIONS_KEY, text: nextValue }] });
19512
19806
  postToParentRef.current({ type: "ow:ai-section-deleted", sectionId, previous, value: nextValue });
@@ -19520,7 +19814,7 @@ function OhhwellsBridge() {
19520
19814
  aiSectionsRef.current = value;
19521
19815
  applyAiSectionsToDom(parseAiSectionsState(value));
19522
19816
  applyStylesToDom(parseStyleStore(stylesRef.current));
19523
- const restoredHeight = document.documentElement.scrollHeight;
19817
+ const restoredHeight = document.body.scrollHeight;
19524
19818
  if (restoredHeight > 50) postToParentRef.current({ type: "ow:height", height: restoredHeight });
19525
19819
  postToParentRef.current({ type: "ow:change", nodes: [{ key: AI_SECTIONS_KEY, text: value }] });
19526
19820
  postAiSectionsChanged();
@@ -19574,6 +19868,48 @@ function OhhwellsBridge() {
19574
19868
  else document.documentElement.removeAttribute("data-ohw-panel-dragging");
19575
19869
  };
19576
19870
  window.addEventListener("message", handlePanelDragging);
19871
+ const handleDeleteSection = (e) => {
19872
+ if (e.data?.type !== "ow:delete-section") return;
19873
+ const instanceId = typeof e.data.instanceId === "string" ? e.data.instanceId : "";
19874
+ if (!instanceId) return;
19875
+ const currentEntries = getPageSectionOrderEntries(editContentRef.current[SECTION_ORDER_KEY], window.location.pathname);
19876
+ const entries = deleteSectionInstance(instanceId, window.location.pathname, currentEntries);
19877
+ if (!entries) return;
19878
+ const orderJson = JSON.stringify(entries);
19879
+ editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: orderJson };
19880
+ postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: orderJson }] });
19881
+ aiSectionApiRef.current?.clear();
19882
+ window.dispatchEvent(new Event("resize"));
19883
+ const deleteHeight = document.body.scrollHeight;
19884
+ if (deleteHeight > 50) postToParentRef.current({ type: "ow:height", height: deleteHeight });
19885
+ const actionId = newInstanceId();
19886
+ pendingDeleteUndoRef.current = {
19887
+ actionId,
19888
+ restore: () => {
19889
+ const restoredEntries = getPageSectionOrderEntries(
19890
+ editContentRef.current[SECTION_ORDER_KEY],
19891
+ window.location.pathname
19892
+ );
19893
+ const restored = restoreSectionInstance(instanceId, window.location.pathname, restoredEntries);
19894
+ if (!restored) return;
19895
+ const restoredJson = JSON.stringify(restored);
19896
+ editContentRef.current = { ...editContentRef.current, [SECTION_ORDER_KEY]: restoredJson };
19897
+ postToParentRef.current({ type: "ow:change", nodes: [{ key: SECTION_ORDER_KEY, text: restoredJson }] });
19898
+ window.dispatchEvent(new Event("resize"));
19899
+ const restoreHeight = document.body.scrollHeight;
19900
+ if (restoreHeight > 50) postToParentRef.current({ type: "ow:height", height: restoreHeight });
19901
+ }
19902
+ };
19903
+ postToParentRef.current({
19904
+ type: "ow:toast",
19905
+ title: "Section deleted",
19906
+ toastType: "success",
19907
+ actionLabel: "Undo",
19908
+ actionId,
19909
+ duration: 6e3
19910
+ });
19911
+ };
19912
+ window.addEventListener("message", handleDeleteSection);
19577
19913
  const handleDeactivate = (e) => {
19578
19914
  if (e.data?.type !== "ow:deactivate") return;
19579
19915
  if (document.documentElement.hasAttribute("data-ohw-panel-dragging")) return;
@@ -19909,7 +20245,7 @@ function OhhwellsBridge() {
19909
20245
  const updated = sections.filter((s) => !(s.type === "scheduling" && s.pagePath === currentPath));
19910
20246
  tracker.textContent = JSON.stringify(updated);
19911
20247
  postToParentRef.current({ type: "ow:change", nodes: [{ key: "__ohw_sections", text: tracker.textContent }] });
19912
- const h = document.documentElement.scrollHeight;
20248
+ const h = document.body.scrollHeight;
19913
20249
  if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
19914
20250
  };
19915
20251
  const handleCollectSection = (e) => {
@@ -20260,6 +20596,7 @@ function OhhwellsBridge() {
20260
20596
  window.removeEventListener("message", handleAiSetStyles);
20261
20597
  window.removeEventListener("message", handleGetBrand);
20262
20598
  window.removeEventListener("message", handlePanelDragging);
20599
+ window.removeEventListener("message", handleDeleteSection);
20263
20600
  window.removeEventListener("message", handleDeactivate);
20264
20601
  window.removeEventListener("message", handleToastAction);
20265
20602
  window.removeEventListener("message", handleFormCount);
@@ -20665,15 +21002,23 @@ function OhhwellsBridge() {
20665
21002
  const result = duplicateSocialItem(social, editContentRef.current);
20666
21003
  if (!result) return;
20667
21004
  const orderJson = JSON.stringify(result.order);
21005
+ const copyIcon = result.item.querySelector('[data-ohw-editable="icon"]');
21006
+ const copyLabel = result.item.querySelector(
21007
+ '[data-ohw-social-label], [data-ohw-editable="text"], [data-ohw-editable="plain"]'
21008
+ );
21009
+ const storedOf = (key) => key ? editContentRef.current[key] : void 0;
20668
21010
  const carried = [
20669
- { from: result.copiedFrom?.href, to: result.hrefKey },
20670
- { from: result.copiedFrom?.icon, to: result.iconKey },
20671
- { from: result.copiedFrom?.icon ? socialPlatformKey(result.copiedFrom.icon) : null, to: socialPlatformKey(result.iconKey) }
21011
+ { key: result.hrefKey, text: storedOf(result.copiedFrom?.href) ?? result.item.getAttribute("href") },
21012
+ { key: result.iconKey, text: storedOf(result.copiedFrom?.icon) ?? copyIcon?.innerHTML },
21013
+ {
21014
+ key: socialPlatformKey(result.iconKey),
21015
+ text: storedOf(result.copiedFrom?.icon ? socialPlatformKey(result.copiedFrom.icon) : null)
21016
+ },
21017
+ { key: copyLabel?.getAttribute("data-ohw-key"), text: copyLabel?.textContent?.trim() }
20672
21018
  ];
20673
21019
  const nodes = [{ key: SOCIALS_ORDER_KEY, text: orderJson }];
20674
- for (const { from, to } of carried) {
20675
- const value = from ? editContentRef.current[from] : void 0;
20676
- if (value) nodes.push({ key: to, text: value });
21020
+ for (const { key, text } of carried) {
21021
+ if (key && text) nodes.push({ key, text });
20677
21022
  }
20678
21023
  editContentRef.current = {
20679
21024
  ...editContentRef.current,
@@ -21200,7 +21545,7 @@ function OhhwellsBridge() {
21200
21545
  onDragHandleDragEnd: handleItemDragEnd,
21201
21546
  onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
21202
21547
  onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
21203
- itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
21548
+ itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection && !selectedIsSocialsRow,
21204
21549
  toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
21205
21550
  ItemActionToolbar,
21206
21551
  {