@ohhwells/bridge 0.1.54-next.150 → 0.1.54-next.153

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
@@ -236,13 +236,17 @@ function MediaBox({
236
236
  const url = refValue ? ctx.resolveMedia(refValue) : null;
237
237
  const isIcon = /^(lucide|simple):/.test(refValue);
238
238
  const aspectRatio = aspect && /^\d+:\d+$/.test(aspect) ? aspect.replace(":", " / ") : void 0;
239
- const editAttrs = ctx.keyFor && editPath && !isIcon ? { "data-ohw-key": ctx.keyFor(editPath), "data-ohw-editable": "image" } : {};
239
+ const editAttrs = ctx.keyFor && editPath ? {
240
+ "data-ohw-key": ctx.keyFor(editPath),
241
+ "data-ohw-editable": isIcon ? "icon" : "image"
242
+ } : {};
240
243
  if (isIcon) {
241
244
  const Icon = refValue.startsWith("lucide:") ? lucideByName(refValue.slice(7)) : null;
242
245
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
243
246
  "span",
244
247
  {
245
248
  "data-ai-icon": refValue,
249
+ ...editAttrs,
246
250
  style: {
247
251
  display: "inline-flex",
248
252
  width: 48,
@@ -9528,6 +9532,358 @@ function deleteNavbarItem(sourceAnchor) {
9528
9532
  };
9529
9533
  }
9530
9534
 
9535
+ // src/lib/icon-markup.ts
9536
+ var GLYPH_SELECTOR = "svg, img";
9537
+ function referenceBox(slot) {
9538
+ const row = slot.closest("[data-ohw-socials-row]") ?? slot.closest("a")?.parentElement ?? null;
9539
+ const neighbour = row ? Array.from(row.querySelectorAll('[data-ohw-editable="icon"]')).find((el) => el !== slot) : null;
9540
+ const source = (neighbour ?? slot).querySelector(GLYPH_SELECTOR);
9541
+ const box = source?.getBoundingClientRect() ?? null;
9542
+ return box?.width && box.height ? box : null;
9543
+ }
9544
+ function iconMarkupSizedFor(slot, markup) {
9545
+ const box = referenceBox(slot);
9546
+ if (!box) return markup;
9547
+ const holder = document.createElement("div");
9548
+ holder.innerHTML = markup;
9549
+ const glyph = holder.querySelector(GLYPH_SELECTOR);
9550
+ if (!glyph) return markup;
9551
+ glyph.style.width = `${Math.round(box.width)}px`;
9552
+ glyph.style.height = `${Math.round(box.height)}px`;
9553
+ return holder.innerHTML;
9554
+ }
9555
+ function applyIconMarkup(slot, markup) {
9556
+ if (!markup) return;
9557
+ const coloured = iconMarkupInheritingColour(markup);
9558
+ const sized = iconMarkupSizedFor(slot, coloured);
9559
+ if (slot.innerHTML !== sized) slot.innerHTML = sized;
9560
+ if (sized === coloured) {
9561
+ requestAnimationFrame(() => {
9562
+ if (!slot.isConnected) return;
9563
+ const resized = iconMarkupSizedFor(slot, coloured);
9564
+ if (resized !== coloured && slot.innerHTML !== resized) slot.innerHTML = resized;
9565
+ });
9566
+ }
9567
+ }
9568
+ function detectIconStyle(el) {
9569
+ const row = el.closest("[data-ohw-socials-row]");
9570
+ const glyphs = Array.from((row ?? el).querySelectorAll("svg"));
9571
+ const outlined = glyphs.some((svg) => {
9572
+ return Array.from(svg.querySelectorAll("*")).some((node) => {
9573
+ return node.getAttribute("stroke") !== null && node.getAttribute("stroke") !== "none";
9574
+ });
9575
+ });
9576
+ return outlined ? "outline" : "fill";
9577
+ }
9578
+ function iconMarkupInheritingColour(markup) {
9579
+ const holder = document.createElement("div");
9580
+ holder.innerHTML = markup;
9581
+ holder.querySelectorAll("svg *").forEach((node) => {
9582
+ if (node.getAttribute("fill") && node.getAttribute("fill") !== "none") {
9583
+ node.setAttribute("fill", "currentColor");
9584
+ }
9585
+ if (node.getAttribute("stroke") && node.getAttribute("stroke") !== "none") {
9586
+ node.setAttribute("stroke", "currentColor");
9587
+ }
9588
+ });
9589
+ return holder.innerHTML;
9590
+ }
9591
+
9592
+ // src/lib/socials-items.ts
9593
+ var ICON_SELECTOR = '[data-ohw-editable="icon"]';
9594
+ var SOCIALS_ROW_ATTR = "data-ohw-socials-row";
9595
+ var SOCIALS_ITEM_ATTR = "data-ohw-social-item";
9596
+ function isSocialItem(el) {
9597
+ if (!el) return false;
9598
+ const anchor = el instanceof HTMLAnchorElement ? el : el.closest("a");
9599
+ if (!anchor) return false;
9600
+ return anchor.querySelectorAll(ICON_SELECTOR).length === 1;
9601
+ }
9602
+ function getSocialItem(el) {
9603
+ const anchor = el.closest("a");
9604
+ return isSocialItem(anchor) ? anchor : null;
9605
+ }
9606
+ function findSocialsRow(el) {
9607
+ const item = getSocialItem(el);
9608
+ if (!item) return null;
9609
+ const row = item.parentElement;
9610
+ if (!row) return null;
9611
+ const anchors = Array.from(row.querySelectorAll("a"));
9612
+ if (!anchors.length || !anchors.every((anchor) => isSocialItem(anchor))) return null;
9613
+ return row;
9614
+ }
9615
+ function isSocialsRow(el) {
9616
+ const anchors = Array.from(el.querySelectorAll("a"));
9617
+ return anchors.length > 0 && anchors.every((anchor) => isSocialItem(anchor));
9618
+ }
9619
+ function listSocialItems(row) {
9620
+ return Array.from(row.children).filter((child) => {
9621
+ return child instanceof HTMLElement && isSocialItem(child);
9622
+ });
9623
+ }
9624
+ function listSocialsRows(root = document) {
9625
+ const rows = /* @__PURE__ */ new Set();
9626
+ root.querySelectorAll(ICON_SELECTOR).forEach((icon) => {
9627
+ const row = findSocialsRow(icon);
9628
+ if (row) rows.add(row);
9629
+ });
9630
+ root.querySelectorAll(`[${SOCIALS_ROW_ATTR}]`).forEach((row) => rows.add(row));
9631
+ return Array.from(rows);
9632
+ }
9633
+ var rowTemplates = /* @__PURE__ */ new Map();
9634
+ function markSocialsRows(root = document) {
9635
+ root.querySelectorAll(`[${SOCIALS_ITEM_ATTR}]`).forEach((item) => {
9636
+ item.removeAttribute(SOCIALS_ITEM_ATTR);
9637
+ });
9638
+ listSocialsRows(root).forEach((row) => {
9639
+ row.setAttribute(SOCIALS_ROW_ATTR, "");
9640
+ const items = listSocialItems(row);
9641
+ if (items[0]) rowTemplates.set(rowKeyOf(row), items[0].outerHTML);
9642
+ items.forEach((item, index) => {
9643
+ item.setAttribute(SOCIALS_ITEM_ATTR, String(index));
9644
+ const iconKey = socialIconKey(item);
9645
+ if (iconKey) ensureLabelSlot(item, iconKey);
9646
+ });
9647
+ });
9648
+ }
9649
+ var SOCIALS_LABEL_ATTR = "data-ohw-social-label";
9650
+ function ensureLabelSlot(item, iconKey) {
9651
+ if (item.querySelector(`[${SOCIALS_LABEL_ATTR}]`)) return;
9652
+ const label = document.createElement("span");
9653
+ label.setAttribute("data-ohw-key", `${iconKey}-label`);
9654
+ label.setAttribute("data-ohw-editable", "text");
9655
+ label.setAttribute(SOCIALS_LABEL_ATTR, "");
9656
+ label.style.display = "none";
9657
+ label.textContent = item.getAttribute("aria-label") ?? "";
9658
+ item.appendChild(label);
9659
+ }
9660
+ function socialLabelKey(iconKey) {
9661
+ return `${iconKey}-label`;
9662
+ }
9663
+ function applyStoredValues(item, content) {
9664
+ const hrefKey = socialHrefKey(item);
9665
+ const iconKey = socialIconKey(item);
9666
+ if (hrefKey && content[hrefKey] !== void 0) item.setAttribute("href", content[hrefKey]);
9667
+ if (iconKey) {
9668
+ const glyph = item.querySelector(ICON_SELECTOR);
9669
+ if (glyph && content[iconKey]) applyIconMarkup(glyph, content[iconKey]);
9670
+ const label = item.querySelector(`[${SOCIALS_LABEL_ATTR}]`);
9671
+ label?.setAttribute("data-ohw-key", socialLabelKey(iconKey));
9672
+ const stored = content[socialLabelKey(iconKey)];
9673
+ if (label && stored) label.textContent = stored;
9674
+ }
9675
+ }
9676
+ function socialPlatformKey(iconKey) {
9677
+ return `${iconKey}-platform`;
9678
+ }
9679
+ function socialHrefKey(item) {
9680
+ return item.getAttribute("data-ohw-href-key");
9681
+ }
9682
+ function socialIconKey(item) {
9683
+ return item.querySelector(ICON_SELECTOR)?.dataset.ohwKey ?? null;
9684
+ }
9685
+ var SOCIALS_ORDER_KEY = "__ohw_socials_order";
9686
+ function fromMarkup(markup) {
9687
+ const holder = document.createElement("div");
9688
+ holder.innerHTML = markup;
9689
+ return holder.firstElementChild instanceof HTMLElement ? holder.firstElementChild : null;
9690
+ }
9691
+ var rowKeys = /* @__PURE__ */ new WeakMap();
9692
+ function rowKeyOf(row) {
9693
+ const first = listSocialItems(row)[0];
9694
+ const derived = first ? socialIconKey(first)?.replace(/-\d+$/, "") : null;
9695
+ if (derived) rowKeys.set(row, derived);
9696
+ return derived ?? rowKeys.get(row) ?? "social";
9697
+ }
9698
+ function getSocialsOrderFromDom(root = document) {
9699
+ const order = {};
9700
+ listSocialsRows(root).forEach((row) => {
9701
+ order[rowKeyOf(row)] = listSocialItems(row).map((item) => socialHrefKey(item)).filter((key) => Boolean(key));
9702
+ });
9703
+ return order;
9704
+ }
9705
+ function hasStoredValue(content, hrefKey) {
9706
+ const iconKey = hrefKey.replace(/-href$/, "");
9707
+ return Boolean(content[hrefKey]) || Boolean(content[iconKey]);
9708
+ }
9709
+ function parseSocialsOrder(raw) {
9710
+ if (!raw) return null;
9711
+ try {
9712
+ const parsed = JSON.parse(raw);
9713
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
9714
+ } catch {
9715
+ return null;
9716
+ }
9717
+ }
9718
+ function nextSocialIndex(row, rowKey, content) {
9719
+ 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));
9720
+ return Math.max(-1, ...used) + 1;
9721
+ }
9722
+ function insertSocialItem(row, after, content = {}) {
9723
+ const rowKey = rowKeyOf(row);
9724
+ const template = listSocialItems(row)[0];
9725
+ const remembered = rowTemplates.get(rowKey);
9726
+ if (!template && !remembered) return null;
9727
+ const index = nextSocialIndex(row, rowKey, content);
9728
+ const iconKey = `${rowKey}-${index}`;
9729
+ const hrefKey = `${iconKey}-href`;
9730
+ const item = template ? template.cloneNode(true) : fromMarkup(remembered);
9731
+ if (!item) return null;
9732
+ item.setAttribute("data-ohw-href-key", hrefKey);
9733
+ item.setAttribute("href", "");
9734
+ item.removeAttribute("aria-label");
9735
+ item.querySelectorAll("[data-ohw-hovered], [data-ohw-selected]").forEach((el) => {
9736
+ el.removeAttribute("data-ohw-hovered");
9737
+ el.removeAttribute("data-ohw-selected");
9738
+ });
9739
+ const icon = item.querySelector(ICON_SELECTOR);
9740
+ icon?.setAttribute("data-ohw-key", iconKey);
9741
+ item.querySelector(`[${SOCIALS_LABEL_ATTR}]`)?.remove();
9742
+ if (after && after.parentElement === row) after.insertAdjacentElement("afterend", item);
9743
+ else row.appendChild(item);
9744
+ markSocialsRows(row.ownerDocument);
9745
+ return { item, hrefKey, iconKey, order: getSocialsOrderFromDom(row.ownerDocument) };
9746
+ }
9747
+ function duplicateSocialItem(item, content) {
9748
+ const row = findSocialsRow(item);
9749
+ const created = row ? insertSocialItem(row, item, content) : null;
9750
+ if (!created) return null;
9751
+ const sourceHref = socialHrefKey(item);
9752
+ const sourceIcon = socialIconKey(item);
9753
+ const link = created.item;
9754
+ if (sourceHref) link.setAttribute("href", item.getAttribute("href") ?? "");
9755
+ const glyph = item.querySelector(ICON_SELECTOR)?.innerHTML;
9756
+ if (glyph) {
9757
+ const slot = link.querySelector(ICON_SELECTOR);
9758
+ if (slot) slot.innerHTML = glyph;
9759
+ }
9760
+ return {
9761
+ ...created,
9762
+ copiedFrom: { href: sourceHref, icon: sourceIcon }
9763
+ };
9764
+ }
9765
+ function removeSocialItem(item, content) {
9766
+ const row = findSocialsRow(item);
9767
+ if (!row) return null;
9768
+ const hrefKey = socialHrefKey(item);
9769
+ const iconKey = socialIconKey(item);
9770
+ const removedKeys = [hrefKey, iconKey].filter((key) => Boolean(key));
9771
+ if (!removedKeys.length) return null;
9772
+ const previousOrder = getSocialsOrderFromDom(row.ownerDocument);
9773
+ const previousContent = Object.fromEntries(
9774
+ removedKeys.filter((key) => key in content).map((key) => [key, content[key]])
9775
+ );
9776
+ const nextSibling = item.nextElementSibling;
9777
+ item.remove();
9778
+ markSocialsRows(row.ownerDocument);
9779
+ return {
9780
+ removedKeys,
9781
+ previousContent,
9782
+ order: getSocialsOrderFromDom(row.ownerDocument),
9783
+ previousOrder,
9784
+ undo: () => {
9785
+ if (nextSibling) nextSibling.before(item);
9786
+ else row.appendChild(item);
9787
+ markSocialsRows(row.ownerDocument);
9788
+ }
9789
+ };
9790
+ }
9791
+ function applySocialsOrder(order, root = document) {
9792
+ listSocialsRows(root).forEach((row) => {
9793
+ const wanted = order[rowKeyOf(row)];
9794
+ if (!wanted) return;
9795
+ const byKey = new Map(listSocialItems(row).map((item) => [socialHrefKey(item), item]));
9796
+ wanted.forEach((key) => {
9797
+ const item = byKey.get(key);
9798
+ if (item) row.appendChild(item);
9799
+ });
9800
+ });
9801
+ markSocialsRows(root);
9802
+ }
9803
+ function reconcileSocialsFromContent(content, root = document) {
9804
+ markSocialsRows(root);
9805
+ const stored = parseSocialsOrder(content[SOCIALS_ORDER_KEY]);
9806
+ if (!stored) return;
9807
+ listSocialsRows(root).forEach((row) => {
9808
+ const wanted = stored[rowKeyOf(row)];
9809
+ if (!wanted) return;
9810
+ if (!wanted.length) return;
9811
+ wanted.forEach((key) => {
9812
+ if (listSocialItems(row).some((item) => socialHrefKey(item) === key)) return;
9813
+ if (!hasStoredValue(content, key)) return;
9814
+ const created = insertSocialItem(row, null, content);
9815
+ if (created) {
9816
+ created.item.setAttribute("data-ohw-href-key", key);
9817
+ created.item.querySelector(ICON_SELECTOR)?.setAttribute("data-ohw-key", key.replace(/-href$/, ""));
9818
+ applyStoredValues(created.item, content);
9819
+ }
9820
+ });
9821
+ const present = listSocialItems(row);
9822
+ const surviving = present.filter((item) => {
9823
+ const key = socialHrefKey(item);
9824
+ return !key || wanted.includes(key);
9825
+ });
9826
+ if (surviving.length) {
9827
+ present.forEach((item) => {
9828
+ if (!surviving.includes(item)) item.remove();
9829
+ });
9830
+ }
9831
+ });
9832
+ applySocialsOrder(stored, root);
9833
+ }
9834
+ var DROP_BAR_THICKNESS = 3;
9835
+ function buildSocialDropSlots(row) {
9836
+ const items = listSocialItems(row);
9837
+ if (!items.length) return [];
9838
+ return items.concat(items[items.length - 1]).map((item, index) => {
9839
+ const rect = item.getBoundingClientRect();
9840
+ const left = (index === items.length ? rect.right : rect.left) - DROP_BAR_THICKNESS / 2;
9841
+ return {
9842
+ insertIndex: index,
9843
+ columnIndex: -1,
9844
+ left,
9845
+ top: rect.top,
9846
+ width: DROP_BAR_THICKNESS,
9847
+ height: rect.height,
9848
+ direction: "vertical"
9849
+ };
9850
+ });
9851
+ }
9852
+ function findSocialByHrefKey(hrefKey, root = document) {
9853
+ const el = root.querySelector(`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`);
9854
+ return el ? getSocialItem(el) : null;
9855
+ }
9856
+ function buildSocialDropSlotsForKey(hrefKey, root = document) {
9857
+ const item = findSocialByHrefKey(hrefKey, root);
9858
+ const row = item ? findSocialsRow(item) : null;
9859
+ return row ? buildSocialDropSlots(row) : [];
9860
+ }
9861
+ function hitTestSocialDropSlot(clientX, clientY, draggedHrefKey, root = document) {
9862
+ const distanceTo = (slot) => {
9863
+ const dx = clientX - (slot.left + slot.width / 2);
9864
+ const dy = clientY < slot.top ? slot.top - clientY : Math.max(0, clientY - (slot.top + slot.height));
9865
+ return Math.hypot(dx, dy);
9866
+ };
9867
+ const slots = buildSocialDropSlotsForKey(draggedHrefKey, root);
9868
+ return slots.reduce((best, slot) => {
9869
+ return !best || distanceTo(slot) < distanceTo(best) ? slot : best;
9870
+ }, null);
9871
+ }
9872
+ function planSocialMove(hrefKey, insertIndex, root = document) {
9873
+ const item = findSocialByHrefKey(hrefKey, root);
9874
+ const row = item ? findSocialsRow(item) : null;
9875
+ if (!row) return null;
9876
+ const order = getSocialsOrderFromDom(root);
9877
+ const key = rowKeyOf(row);
9878
+ const current = order[key];
9879
+ if (!current) return null;
9880
+ const from = current.indexOf(hrefKey);
9881
+ if (from < 0) return null;
9882
+ const next = current.filter((_, index) => index !== from);
9883
+ next.splice(insertIndex > from ? insertIndex - 1 : insertIndex, 0, hrefKey);
9884
+ return { ...order, [key]: next };
9885
+ }
9886
+
9531
9887
  // src/lib/footer-items.ts
9532
9888
  var FOOTER_ORDER_KEY = "__ohw_footer_order";
9533
9889
  var MAX_FOOTER_COLUMNS = 18;
@@ -10661,6 +11017,7 @@ function readLogoSizeState(content, placement) {
10661
11017
  function getLogoElement(el) {
10662
11018
  const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
10663
11019
  if (marked) return marked;
11020
+ if (el.closest('[data-ohw-editable="icon"]')) return null;
10664
11021
  const root = el.closest("nav, [data-ohw-nav-root], footer");
10665
11022
  if (!root) return null;
10666
11023
  const anchor = el.closest("a");
@@ -11902,7 +12259,7 @@ function isNavbarLinksContainer(el) {
11902
12259
  function isNavigationItem(el) {
11903
12260
  const anchor = el.matches("[data-ohw-href-key]") ? el : el.closest("[data-ohw-href-key]");
11904
12261
  if (!anchor) return false;
11905
- return Boolean(anchor.querySelector('[data-ohw-editable="text"]'));
12262
+ return Boolean(anchor.querySelector('[data-ohw-editable="text"]')) || Boolean(getSocialItem(anchor));
11906
12263
  }
11907
12264
  function findFooterItemGroup(item) {
11908
12265
  const explicit = item.closest("[data-ohw-footer-col], [data-ohw-footer-column]");
@@ -11923,8 +12280,9 @@ function isInferredFooterGroup(el) {
11923
12280
  const footer = el.closest("footer");
11924
12281
  if (!footer || el === footer) return false;
11925
12282
  if (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column")) return true;
12283
+ if (isSocialsRow(el)) return false;
11926
12284
  const count = Array.from(el.querySelectorAll("[data-ohw-href-key]")).filter(
11927
- isNavigationItem
12285
+ (item) => isNavigationItem(item) && !getSocialItem(item)
11928
12286
  ).length;
11929
12287
  return count >= 2;
11930
12288
  }
@@ -11968,7 +12326,8 @@ function deleteSelectedNavFooterItem(deps) {
11968
12326
  if (key.endsWith("-href")) applyLinkByKey2(key, text);
11969
12327
  else {
11970
12328
  document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`).forEach((el) => {
11971
- el.textContent = text;
12329
+ if (el.getAttribute("data-ohw-editable") === "icon") applyIconMarkup(el, text);
12330
+ else el.textContent = text;
11972
12331
  });
11973
12332
  }
11974
12333
  }
@@ -12030,6 +12389,21 @@ function deleteSelectedNavFooterItem(deps) {
12030
12389
  });
12031
12390
  return true;
12032
12391
  }
12392
+ const social = getSocialItem(selected);
12393
+ if (social) {
12394
+ const result = removeSocialItem(social, getEditContent());
12395
+ if (!result) return false;
12396
+ finishDelete({
12397
+ toastTitle: "Social deleted",
12398
+ removedKeys: result.removedKeys,
12399
+ previousContent: result.previousContent,
12400
+ orderKey: SOCIALS_ORDER_KEY,
12401
+ orderJson: JSON.stringify(result.order),
12402
+ previousOrderJson: JSON.stringify(result.previousOrder),
12403
+ undoDom: result.undo
12404
+ });
12405
+ return true;
12406
+ }
12033
12407
  if (isFooterHrefKey(hrefKey)) {
12034
12408
  const result = deleteFooterItem(selected);
12035
12409
  if (!result) return false;
@@ -12382,6 +12756,17 @@ function applyLinkHref(el, val) {
12382
12756
  const anchor = el instanceof HTMLAnchorElement ? el : el.querySelector("a");
12383
12757
  if (anchor) anchor.setAttribute("href", val);
12384
12758
  }
12759
+ function currentIconRef(el) {
12760
+ const uploaded = el instanceof HTMLImageElement ? el : el.querySelector("img");
12761
+ if (uploaded?.getAttribute("src")) {
12762
+ return uploaded.getAttribute("src") ?? "";
12763
+ }
12764
+ const svg = el instanceof SVGElement ? el : el.querySelector("svg");
12765
+ const named = Array.from(svg?.classList ?? []).find(
12766
+ (c) => c.startsWith("lucide-") && c !== "lucide-icon"
12767
+ );
12768
+ return named ? `lucide:${named.slice("lucide-".length)}` : "";
12769
+ }
12385
12770
  function getEditMeasureEl(editable) {
12386
12771
  return editable.closest("[data-ohw-href-key]") ?? editable;
12387
12772
  }
@@ -12426,8 +12811,11 @@ function isMediaEditable(el) {
12426
12811
  const t = el.dataset.ohwEditable;
12427
12812
  return t === "image" || t === "bg-image" || t === "video";
12428
12813
  }
12814
+ function isIconEditable(el) {
12815
+ return el.dataset.ohwEditable === "icon";
12816
+ }
12429
12817
  var MEDIA_SELECTOR = '[data-ohw-editable="image"], [data-ohw-editable="bg-image"], [data-ohw-editable="video"]';
12430
- var NON_MEDIA_SELECTOR = '[data-ohw-editable]:not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]):not([data-ohw-editable="video"])';
12818
+ var NON_MEDIA_SELECTOR = '[data-ohw-editable]:not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]):not([data-ohw-editable="video"]):not([data-ohw-editable="icon"])';
12431
12819
  function getVideoEl2(el) {
12432
12820
  return el instanceof HTMLVideoElement ? el : el.querySelector("video");
12433
12821
  }
@@ -12552,13 +12940,29 @@ function isNavItemPointerTarget(el) {
12552
12940
  function getNavigationItemAnchor(el) {
12553
12941
  const anchor = el.matches("[data-ohw-href-key]") ? el : el.closest("[data-ohw-href-key]");
12554
12942
  if (!anchor) return null;
12555
- if (!anchor.querySelector('[data-ohw-editable="text"]')) return null;
12943
+ if (!anchor.querySelector('[data-ohw-editable="text"]') && !getSocialItem(anchor)) return null;
12556
12944
  if (!isNavItemPointerTarget(anchor)) return null;
12557
12945
  return anchor;
12558
12946
  }
12559
12947
  function isNavigationItem2(el) {
12560
12948
  return getNavigationItemAnchor(el) !== null;
12561
12949
  }
12950
+ function requestSocialDialog(anchor, post, content) {
12951
+ const item = getSocialItem(anchor);
12952
+ if (!item) return false;
12953
+ const iconKey = item.querySelector('[data-ohw-editable="icon"]')?.dataset.ohwKey ?? "";
12954
+ post({
12955
+ type: "ow:social-pick",
12956
+ hrefKey: item.getAttribute("data-ohw-href-key") ?? "",
12957
+ iconKey,
12958
+ url: getLinkHref4(item),
12959
+ iconStyle: detectIconStyle(item),
12960
+ // What was chosen last time. Guessing from the address instead reads as "Website" for anything
12961
+ // unrecognised, and for an item with no address at all — so a deliberate choice looked lost.
12962
+ platformId: content[socialPlatformKey(iconKey)] ?? ""
12963
+ });
12964
+ return true;
12965
+ }
12562
12966
  function listNavigationItems() {
12563
12967
  return Array.from(
12564
12968
  document.querySelectorAll("nav [data-ohw-href-key], footer [data-ohw-href-key]")
@@ -12593,7 +12997,7 @@ function getNavigationRoot(el) {
12593
12997
  return el.closest("nav, footer, aside");
12594
12998
  }
12595
12999
  function countFooterNavItems(el) {
12596
- return Array.from(el.querySelectorAll("[data-ohw-href-key]")).filter(isNavigationItem2).length;
13000
+ return Array.from(el.querySelectorAll("[data-ohw-href-key]")).filter((item) => isNavigationItem2(item) && !getSocialItem(item)).length;
12597
13001
  }
12598
13002
  function findFooterItemGroup2(item) {
12599
13003
  const explicit = item.closest("[data-ohw-footer-col], [data-ohw-footer-column]");
@@ -12614,10 +13018,11 @@ function isInferredFooterGroup2(el) {
12614
13018
  const footer = el.closest("footer");
12615
13019
  if (!footer || el === footer) return false;
12616
13020
  if (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column")) return true;
13021
+ if (isSocialsRow(el)) return false;
12617
13022
  return countFooterNavItems(el) >= 2;
12618
13023
  }
12619
13024
  function isNavigationContainer(el) {
12620
- return el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el) || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isNavigationRoot(el) || isInferredFooterGroup2(el);
13025
+ return el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el) || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isNavigationRoot(el) || isSocialsRow(el) || isInferredFooterGroup2(el);
12621
13026
  }
12622
13027
  function isNavbarLinksContainer2(el) {
12623
13028
  return el.hasAttribute("data-ohw-nav-container");
@@ -12700,6 +13105,8 @@ function resolveNavContainerSelectionTarget(target, clientX, clientY) {
12700
13105
  return null;
12701
13106
  }
12702
13107
  function getNavigationSelectionParent(el) {
13108
+ const socialsRow = findSocialsRow(el);
13109
+ if (socialsRow) return socialsRow;
12703
13110
  if (isNavigationItem2(el)) {
12704
13111
  const childrenRoot = el.closest("[data-ohw-nav-children]");
12705
13112
  if (childrenRoot) {
@@ -12725,6 +13132,10 @@ function getNavigationSelectionParent(el) {
12725
13132
  }
12726
13133
  function collectNavigationItemSiblingHintRects(selected) {
12727
13134
  if (!isNavigationItem2(selected)) return [];
13135
+ const socialsRow = findSocialsRow(selected);
13136
+ if (socialsRow) {
13137
+ return listSocialItems(socialsRow).filter((item) => item !== selected).map((item) => item.getBoundingClientRect());
13138
+ }
12728
13139
  const footerColumn = getFooterColumn(selected);
12729
13140
  if (footerColumn) {
12730
13141
  return listFooterLinksInColumn(footerColumn).filter((link) => link !== selected).map((link) => link.getBoundingClientRect());
@@ -13426,6 +13837,8 @@ function OhhwellsBridge() {
13426
13837
  const toolbarVariantRef = (0, import_react16.useRef)("none");
13427
13838
  toolbarVariantRef.current = toolbarVariant;
13428
13839
  const [selectedIsCta, setSelectedIsCta] = (0, import_react16.useState)(false);
13840
+ const [selectedIsSocial, setSelectedIsSocial] = (0, import_react16.useState)(false);
13841
+ const [selectedIsSocialsRow, setSelectedIsSocialsRow] = (0, import_react16.useState)(false);
13429
13842
  const [reorderHrefKey, setReorderHrefKey] = (0, import_react16.useState)(null);
13430
13843
  const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react16.useState)(false);
13431
13844
  const [toggleState, setToggleState] = (0, import_react16.useState)(null);
@@ -13694,6 +14107,8 @@ function OhhwellsBridge() {
13694
14107
  selectedHrefKeyRef.current = null;
13695
14108
  selectedFooterColAttrRef.current = null;
13696
14109
  setSelectedIsCta(false);
14110
+ setSelectedIsSocial(false);
14111
+ setSelectedIsSocialsRow(false);
13697
14112
  setReorderHrefKey(null);
13698
14113
  setReorderDragDisabled(false);
13699
14114
  setIsFooterFrameSelection(false);
@@ -13778,6 +14193,8 @@ function OhhwellsBridge() {
13778
14193
  selectedFooterColAttrRef.current = null;
13779
14194
  markSelected(navAnchor);
13780
14195
  setSelectedIsCta(isCtaButton(navAnchor));
14196
+ setSelectedIsSocial(Boolean(getSocialItem(navAnchor)));
14197
+ setSelectedIsSocialsRow(false);
13781
14198
  const isDropdownTrigger = !isNestedNavChild(navAnchor) && (navItemHasDropdownChildren(navAnchor) || navItemOwnsDropdownPanel(navAnchor));
13782
14199
  if (isNestedNavChild(navAnchor)) {
13783
14200
  setNavGroupForceOpen(navAnchor, true);
@@ -13901,6 +14318,27 @@ function OhhwellsBridge() {
13901
14318
  const handleAddChildItem = (0, import_react16.useCallback)(() => {
13902
14319
  const selected = selectedElRef.current;
13903
14320
  if (!selected) return;
14321
+ const socialsRow = isSocialsRow(selected) ? selected : findSocialsRow(selected);
14322
+ if (socialsRow) {
14323
+ const after = getSocialItem(selected);
14324
+ const result2 = insertSocialItem(socialsRow, after, editContentRef.current);
14325
+ if (!result2) return;
14326
+ const orderJson = JSON.stringify(result2.order);
14327
+ editContentRef.current = { ...editContentRef.current, [SOCIALS_ORDER_KEY]: orderJson };
14328
+ postToParent2({ type: "ow:change", nodes: [{ key: SOCIALS_ORDER_KEY, text: orderJson }] });
14329
+ postToParentRef.current({
14330
+ type: "ow:social-pick",
14331
+ hrefKey: result2.hrefKey,
14332
+ iconKey: result2.iconKey,
14333
+ url: "",
14334
+ iconStyle: detectIconStyle(result2.item),
14335
+ platformId: "",
14336
+ // Lets the editor undo the insert if the dialog is dismissed: an item that was never given
14337
+ // an address should not survive a Cancel.
14338
+ isNew: true
14339
+ });
14340
+ return;
14341
+ }
13904
14342
  if (toolbarVariantRef.current === "select-frame" && isFooterFrameSelection) {
13905
14343
  if (!selected.hasAttribute("data-ohw-footer-col") && !selected.closest("[data-ohw-footer-col]")) {
13906
14344
  }
@@ -14013,6 +14451,13 @@ function OhhwellsBridge() {
14013
14451
  }
14014
14452
  session.activeSlot = activeSlot;
14015
14453
  setSiblingHintRects([]);
14454
+ if (session.kind === "social") {
14455
+ const slots2 = session.hrefKey ? buildSocialDropSlotsForKey(session.hrefKey) : [];
14456
+ setFooterDropSlots(slots2);
14457
+ const activeIdx2 = activeSlot ? slots2.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
14458
+ setActiveFooterDropIndex(activeIdx2 >= 0 ? activeIdx2 : null);
14459
+ return;
14460
+ }
14016
14461
  if (session.kind === "link") {
14017
14462
  const columns = listFooterColumns();
14018
14463
  const slots2 = [];
@@ -14049,7 +14494,7 @@ function OhhwellsBridge() {
14049
14494
  if (session.wasSelected && selectedElRef.current === session.draggedEl) {
14050
14495
  setToolbarRect(rect);
14051
14496
  }
14052
- const initialSlot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
14497
+ const initialSlot = session.kind === "social" && session.hrefKey ? hitTestSocialDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
14053
14498
  refreshFooterDragVisuals(session, initialSlot, session.lastClientX, session.lastClientY);
14054
14499
  },
14055
14500
  [refreshFooterDragVisuals]
@@ -14065,8 +14510,11 @@ function OhhwellsBridge() {
14065
14510
  const x = typeof clientX === "number" && (clientX !== 0 || clientY !== 0) ? clientX : session.lastClientX;
14066
14511
  const y = typeof clientY === "number" && (clientX !== 0 || clientY !== 0) ? clientY : session.lastClientY;
14067
14512
  let nextOrder = null;
14068
- const slot = session.activeSlot ?? (session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(x, y, session.hrefKey) : session.kind === "column" ? hitTestColumnDropSlot(x, y) : null);
14069
- if (session.kind === "link" && session.hrefKey && slot) {
14513
+ let nextSocialsOrder = null;
14514
+ const slot = session.activeSlot ?? (session.kind === "social" && session.hrefKey ? hitTestSocialDropSlot(x, y, session.hrefKey) : session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(x, y, session.hrefKey) : session.kind === "column" ? hitTestColumnDropSlot(x, y) : null);
14515
+ if (session.kind === "social" && session.hrefKey && slot) {
14516
+ nextSocialsOrder = planSocialMove(session.hrefKey, slot.insertIndex);
14517
+ } else if (session.kind === "link" && session.hrefKey && slot) {
14070
14518
  nextOrder = planFooterLinkMove(session.hrefKey, slot.columnIndex, slot.insertIndex);
14071
14519
  } else if (session.kind === "column" && slot) {
14072
14520
  nextOrder = planFooterColumnMove(session.sourceColumnIndex, slot.insertIndex);
@@ -14124,6 +14572,27 @@ function OhhwellsBridge() {
14124
14572
  }
14125
14573
  deselectRef.current();
14126
14574
  };
14575
+ if (nextSocialsOrder) {
14576
+ const orderJson = JSON.stringify(nextSocialsOrder);
14577
+ editContentRef.current = { ...editContentRef.current, [SOCIALS_ORDER_KEY]: orderJson };
14578
+ applySocialsOrder(nextSocialsOrder);
14579
+ postToParentRef.current({
14580
+ type: "ow:change",
14581
+ nodes: [{ key: SOCIALS_ORDER_KEY, text: orderJson }]
14582
+ });
14583
+ applySelectionAfterDrop();
14584
+ clearFooterDragVisuals();
14585
+ const reapply = nextSocialsOrder;
14586
+ requestAnimationFrame(() => {
14587
+ if (editContentRef.current[SOCIALS_ORDER_KEY] === orderJson) applySocialsOrder(reapply);
14588
+ applySelectionAfterDrop();
14589
+ requestAnimationFrame(() => {
14590
+ if (editContentRef.current[SOCIALS_ORDER_KEY] === orderJson) applySocialsOrder(reapply);
14591
+ resyncSelectedNavigationItem();
14592
+ });
14593
+ });
14594
+ return;
14595
+ }
14127
14596
  if (nextOrder) {
14128
14597
  const orderJson = JSON.stringify(nextOrder);
14129
14598
  editContentRef.current = {
@@ -14162,7 +14631,22 @@ function OhhwellsBridge() {
14162
14631
  const startFooterLinkDrag = (0, import_react16.useCallback)(
14163
14632
  (anchor, clientX, clientY, wasSelected) => {
14164
14633
  const hrefKey = anchor.getAttribute("data-ohw-href-key");
14165
- if (!hrefKey || !isFooterHrefKey(hrefKey)) return false;
14634
+ if (!hrefKey) return false;
14635
+ if (getSocialItem(anchor)) {
14636
+ beginFooterDrag({
14637
+ kind: "social",
14638
+ hrefKey,
14639
+ columnEl: null,
14640
+ sourceColumnIndex: 0,
14641
+ wasSelected,
14642
+ draggedEl: anchor,
14643
+ lastClientX: clientX,
14644
+ lastClientY: clientY,
14645
+ activeSlot: null
14646
+ });
14647
+ return true;
14648
+ }
14649
+ if (!isFooterHrefKey(hrefKey)) return false;
14166
14650
  const column = findFooterColumnForLink(anchor);
14167
14651
  const columns = listFooterColumns();
14168
14652
  beginFooterDrag({
@@ -14299,6 +14783,8 @@ function OhhwellsBridge() {
14299
14783
  selectedFooterColAttrRef.current = null;
14300
14784
  markSelected(anchor);
14301
14785
  setSelectedIsCta(isCtaButton(anchor));
14786
+ setSelectedIsSocial(Boolean(getSocialItem(anchor)));
14787
+ setSelectedIsSocialsRow(false);
14302
14788
  clearHrefKeyHover(anchor);
14303
14789
  const isDropdownTrigger = !isNestedNavChild(anchor) && (navItemHasDropdownChildren(anchor) || navItemOwnsDropdownPanel(anchor));
14304
14790
  if (isNestedNavChild(anchor)) {
@@ -14341,6 +14827,8 @@ function OhhwellsBridge() {
14341
14827
  selectedFooterColAttrRef.current = isFooterColumn ? el.getAttribute("data-ohw-footer-col") ?? String(listFooterColumns().indexOf(el)) : null;
14342
14828
  markSelected(el);
14343
14829
  setSelectedIsCta(false);
14830
+ setSelectedIsSocial(false);
14831
+ setSelectedIsSocialsRow(isSocialsRow(el));
14344
14832
  clearHrefKeyHover(el);
14345
14833
  setNavGroupForceOpen(null, false);
14346
14834
  hoveredNavContainerRef.current = null;
@@ -14388,6 +14876,9 @@ function OhhwellsBridge() {
14388
14876
  selectedFooterColAttrRef.current = null;
14389
14877
  markSelected(logoEl);
14390
14878
  setSelectedIsCta(false);
14879
+ setSelectedIsSocial(false);
14880
+ setSelectedIsSocialsRow(false);
14881
+ setSelectedIsSocialsRow(false);
14391
14882
  clearHrefKeyHover(logoEl);
14392
14883
  hoveredNavContainerRef.current = null;
14393
14884
  setHoveredNavContainerRect(null);
@@ -14471,11 +14962,15 @@ function OhhwellsBridge() {
14471
14962
  );
14472
14963
  const activate = (0, import_react16.useCallback)((el, options) => {
14473
14964
  if (activeElRef.current === el) return;
14965
+ if (isIconEditable(el)) return;
14966
+ if (el.hasAttribute("data-ohw-social-label")) return;
14474
14967
  clearSelectedAttr();
14475
14968
  selectedElRef.current = null;
14476
14969
  selectedHrefKeyRef.current = null;
14477
14970
  selectedFooterColAttrRef.current = null;
14478
14971
  setSelectedIsCta(false);
14972
+ setSelectedIsSocial(false);
14973
+ setSelectedIsSocialsRow(false);
14479
14974
  deactivate();
14480
14975
  if (hoveredImageRef.current) {
14481
14976
  hoveredImageRef.current = null;
@@ -14618,6 +15113,8 @@ function OhhwellsBridge() {
14618
15113
  }
14619
15114
  } else if (el.dataset.ohwEditable === "link") {
14620
15115
  applyLinkHref(el, val);
15116
+ } else if (el.dataset.ohwEditable === "icon") {
15117
+ applyIconMarkup(el, val);
14621
15118
  } else if (el.innerHTML !== val) {
14622
15119
  el.innerHTML = val;
14623
15120
  }
@@ -14628,6 +15125,7 @@ function OhhwellsBridge() {
14628
15125
  applyLogoSizes(content);
14629
15126
  reconcileNavbarItemsFromContent(content);
14630
15127
  reconcileFooterOrderFromContent(content);
15128
+ reconcileSocialsFromContent(content);
14631
15129
  enforceLinkHrefs();
14632
15130
  initSectionsFromContent(content, true);
14633
15131
  sectionsLoadedRef.current = true;
@@ -14695,6 +15193,7 @@ function OhhwellsBridge() {
14695
15193
  applyLogoFromContent(content);
14696
15194
  reconcileNavbarItemsFromContent(content);
14697
15195
  reconcileFooterOrderFromContent(content);
15196
+ reconcileSocialsFromContent(content);
14698
15197
  } finally {
14699
15198
  observer?.observe(document.body, { childList: true, subtree: true });
14700
15199
  }
@@ -14772,6 +15271,7 @@ function OhhwellsBridge() {
14772
15271
  const content = contentForNav();
14773
15272
  reconcileNavbarItemsFromContent(content);
14774
15273
  reconcileFooterOrderFromContent(content);
15274
+ reconcileSocialsFromContent(content);
14775
15275
  document.querySelectorAll("footer [data-ohw-href-key]").forEach((el) => {
14776
15276
  if (isFooterHrefKey(el.getAttribute("data-ohw-href-key"))) {
14777
15277
  disableNativeHrefDrag(el);
@@ -15069,6 +15569,17 @@ function OhhwellsBridge() {
15069
15569
  });
15070
15570
  return;
15071
15571
  }
15572
+ if (isIconEditable(editable) && !getSocialItem(editable)) {
15573
+ e.preventDefault();
15574
+ e.stopPropagation();
15575
+ aiSectionApiRef.current?.selectFromElement(editable);
15576
+ postToParentRef.current({
15577
+ type: "ow:icon-pick",
15578
+ key: editable.dataset.ohwKey ?? "",
15579
+ current: currentIconRef(editable)
15580
+ });
15581
+ return;
15582
+ }
15072
15583
  if (isMediaEditable(editable)) {
15073
15584
  e.preventDefault();
15074
15585
  e.stopPropagation();
@@ -15083,6 +15594,7 @@ function OhhwellsBridge() {
15083
15594
  e.stopPropagation();
15084
15595
  if (selectedElRef.current === navAnchor) {
15085
15596
  if (e.detail >= 2) return;
15597
+ if (requestSocialDialog(navAnchor, postToParentRef.current, editContentRef.current)) return;
15086
15598
  activateRef.current(editable, { caretX: e.clientX, caretY: e.clientY });
15087
15599
  return;
15088
15600
  }
@@ -15099,6 +15611,7 @@ function OhhwellsBridge() {
15099
15611
  e.preventDefault();
15100
15612
  e.stopPropagation();
15101
15613
  if (selectedElRef.current === hrefAnchor) {
15614
+ if (requestSocialDialog(hrefAnchor, postToParentRef.current, editContentRef.current)) return;
15102
15615
  const textEditable = hrefAnchor.querySelector('[data-ohw-editable="text"]') ?? hrefAnchor.querySelector("[data-ohw-editable]");
15103
15616
  if (textEditable) {
15104
15617
  activateRef.current(textEditable, {
@@ -15137,6 +15650,13 @@ function OhhwellsBridge() {
15137
15650
  selectFrameRef.current(navContainerToSelect);
15138
15651
  return;
15139
15652
  }
15653
+ const socialsRowToSelect = isSocialsRow(target) ? target : null;
15654
+ if (socialsRowToSelect && !getSocialItem(target)) {
15655
+ e.preventDefault();
15656
+ e.stopPropagation();
15657
+ selectFrameRef.current(socialsRowToSelect);
15658
+ return;
15659
+ }
15140
15660
  const footerColumnToSelect = resolveFooterColumnSelectionTarget(target, e.clientX, e.clientY);
15141
15661
  if (footerColumnToSelect) {
15142
15662
  e.preventDefault();
@@ -15189,6 +15709,7 @@ function OhhwellsBridge() {
15189
15709
  if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
15190
15710
  return;
15191
15711
  }
15712
+ if (getSocialItem(target)) return;
15192
15713
  const navLabel = getNavigationLabelEditable(target);
15193
15714
  const editable = navLabel?.editable ?? target.closest('[data-ohw-editable="text"], [data-ohw-editable="plain"]');
15194
15715
  if (!editable || isMediaEditable(editable) || editable.dataset.ohwEditable === "link") return;
@@ -15292,6 +15813,11 @@ function OhhwellsBridge() {
15292
15813
  const selected = selectedElRef.current;
15293
15814
  if (selected && (selected === editable || selected.contains(editable))) return;
15294
15815
  if (!isMediaEditable(editable) && !editable.hasAttribute("contenteditable")) {
15816
+ if (isIconEditable(editable)) {
15817
+ hoveredItemElRef.current = editable;
15818
+ setHoveredItemRect(editable.getBoundingClientRect());
15819
+ return;
15820
+ }
15295
15821
  const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
15296
15822
  if (hoverTarget.hasAttribute("data-ohw-href-key")) {
15297
15823
  clearHrefKeyHover(hoverTarget);
@@ -15357,6 +15883,13 @@ function OhhwellsBridge() {
15357
15883
  const related = e.relatedTarget instanceof Element ? e.relatedTarget : null;
15358
15884
  if (related?.closest("[data-ohw-drag-handle-container], [data-ohw-item-interaction]")) return;
15359
15885
  if (!isMediaEditable(editable)) {
15886
+ if (isIconEditable(editable) && hoveredItemElRef.current === editable) {
15887
+ if (!related?.closest("[data-ohw-item-interaction]")) {
15888
+ hoveredItemElRef.current = null;
15889
+ setHoveredItemRect(null);
15890
+ }
15891
+ return;
15892
+ }
15360
15893
  const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
15361
15894
  if (hoverTarget.hasAttribute("data-ohw-href-key")) {
15362
15895
  if (!related?.closest("[data-ohw-href-key]")) {
@@ -15950,7 +16483,7 @@ function OhhwellsBridge() {
15950
16483
  if (footerSession) {
15951
16484
  e.preventDefault();
15952
16485
  if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
15953
- const slot = footerSession.kind === "link" && footerSession.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, footerSession.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
16486
+ const slot = footerSession.kind === "social" && footerSession.hrefKey ? hitTestSocialDropSlot(e.clientX, e.clientY, footerSession.hrefKey) : footerSession.kind === "link" && footerSession.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, footerSession.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
15954
16487
  refreshFooterDragVisualsRef.current(footerSession, slot, e.clientX, e.clientY);
15955
16488
  return;
15956
16489
  }
@@ -16002,6 +16535,60 @@ function OhhwellsBridge() {
16002
16535
  resumeAnimTracks();
16003
16536
  clearImageHover();
16004
16537
  };
16538
+ const handleSocialCancel = (e) => {
16539
+ if (e.data?.type !== "ow:social-cancel") return;
16540
+ const { hrefKey } = e.data;
16541
+ const item = hrefKey ? findSocialByHrefKey(hrefKey) : null;
16542
+ if (!item) return;
16543
+ const removed = removeSocialItem(item, editContentRef.current);
16544
+ if (!removed) return;
16545
+ const orderJson = JSON.stringify(removed.order);
16546
+ editContentRef.current = { ...editContentRef.current, [SOCIALS_ORDER_KEY]: orderJson };
16547
+ postToParentRef.current({ type: "ow:change", nodes: [{ key: SOCIALS_ORDER_KEY, text: orderJson }] });
16548
+ deselectRef.current();
16549
+ };
16550
+ const handleSocialUpdate = (e) => {
16551
+ if (e.data?.type !== "ow:social-update") return;
16552
+ const { hrefKey, iconKey, url, iconMarkup, platformId, label } = e.data;
16553
+ const nodes = [];
16554
+ if (hrefKey) {
16555
+ document.querySelectorAll(`[data-ohw-href-key="${hrefKey}"]`).forEach((el) => applyLinkHref(el, url));
16556
+ nodes.push({ key: hrefKey, text: url });
16557
+ }
16558
+ if (iconKey && typeof iconMarkup === "string" && iconMarkup) {
16559
+ document.querySelectorAll(`[data-ohw-key="${iconKey}"][data-ohw-editable="icon"]`).forEach((el) => {
16560
+ applyIconMarkup(el, iconMarkup);
16561
+ });
16562
+ nodes.push({ key: iconKey, text: iconMarkup });
16563
+ }
16564
+ if (iconKey && platformId) nodes.push({ key: socialPlatformKey(iconKey), text: platformId });
16565
+ if (iconKey && label) {
16566
+ const labelKey = socialLabelKey(iconKey);
16567
+ document.querySelectorAll(`[data-ohw-key="${labelKey}"]`).forEach((el) => {
16568
+ el.textContent = label;
16569
+ });
16570
+ nodes.push({ key: labelKey, text: label });
16571
+ }
16572
+ if (!nodes.length) return;
16573
+ editContentRef.current = {
16574
+ ...editContentRef.current,
16575
+ ...Object.fromEntries(nodes.map((node) => [node.key, node.text]))
16576
+ };
16577
+ postToParentRef.current({ type: "ow:change", nodes });
16578
+ };
16579
+ const handleIconMarkup = (e) => {
16580
+ if (e.data?.type !== "ow:icon-markup") return;
16581
+ const { key, markup } = e.data;
16582
+ if (!key || typeof markup !== "string") return;
16583
+ const targets = document.querySelectorAll(
16584
+ `[data-ohw-key="${key}"][data-ohw-editable="icon"]`
16585
+ );
16586
+ if (!targets.length) return;
16587
+ targets.forEach((el) => {
16588
+ applyIconMarkup(el, markup);
16589
+ });
16590
+ postToParentRef.current({ type: "ow:change", nodes: [{ key, text: markup }] });
16591
+ };
16005
16592
  const handleImageUrl = (e) => {
16006
16593
  if (e.data?.type !== "ow:image-url") return;
16007
16594
  const { key, url } = e.data;
@@ -16510,7 +17097,7 @@ function OhhwellsBridge() {
16510
17097
  }
16511
17098
  if (footerDragRef.current) {
16512
17099
  const session = footerDragRef.current;
16513
- const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
17100
+ const slot = session.kind === "social" && session.hrefKey ? hitTestSocialDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
16514
17101
  refreshFooterDragVisualsRef.current(session, slot, session.lastClientX, session.lastClientY);
16515
17102
  }
16516
17103
  if (navDragRef.current) {
@@ -16857,6 +17444,9 @@ function OhhwellsBridge() {
16857
17444
  window.addEventListener("message", handleClearSchedulingWidget);
16858
17445
  window.addEventListener("message", handleRemoveSchedulingSection);
16859
17446
  window.addEventListener("message", handleCollectSection);
17447
+ window.addEventListener("message", handleSocialCancel);
17448
+ window.addEventListener("message", handleSocialUpdate);
17449
+ window.addEventListener("message", handleIconMarkup);
16860
17450
  window.addEventListener("message", handleImageUrl);
16861
17451
  window.addEventListener("message", handleImageUploading);
16862
17452
  window.addEventListener("message", handleCarouselChange);
@@ -16916,6 +17506,9 @@ function OhhwellsBridge() {
16916
17506
  window.removeEventListener("message", handleClearSchedulingWidget);
16917
17507
  window.removeEventListener("message", handleRemoveSchedulingSection);
16918
17508
  window.removeEventListener("message", handleCollectSection);
17509
+ window.removeEventListener("message", handleSocialCancel);
17510
+ window.removeEventListener("message", handleSocialUpdate);
17511
+ window.removeEventListener("message", handleIconMarkup);
16919
17512
  window.removeEventListener("message", handleImageUrl);
16920
17513
  window.removeEventListener("message", handleImageUploading);
16921
17514
  window.removeEventListener("message", handleCarouselChange);
@@ -16994,7 +17587,7 @@ function OhhwellsBridge() {
16994
17587
  clearTextSelection();
16995
17588
  const session = footerDragRef.current;
16996
17589
  if (!session) return;
16997
- const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, session.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
17590
+ const slot = session.kind === "social" && session.hrefKey ? hitTestSocialDropSlot(e.clientX, e.clientY, session.hrefKey) : session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, session.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
16998
17591
  refreshFooterDragVisualsRef.current(session, slot, e.clientX, e.clientY);
16999
17592
  return;
17000
17593
  }
@@ -17235,6 +17828,10 @@ function OhhwellsBridge() {
17235
17828
  if (!anchor) return;
17236
17829
  const key = anchor.getAttribute("data-ohw-href-key");
17237
17830
  if (!key) return;
17831
+ if (requestSocialDialog(anchor, postToParentRef.current, editContentRef.current)) {
17832
+ deselect();
17833
+ return;
17834
+ }
17238
17835
  bumpLinkPopoverGrace();
17239
17836
  setLinkPopover({
17240
17837
  key,
@@ -17275,6 +17872,30 @@ function OhhwellsBridge() {
17275
17872
  if (!selected || !isNavigationItem2(selected)) return;
17276
17873
  const hrefKey = selected.getAttribute("data-ohw-href-key");
17277
17874
  if (!hrefKey) return;
17875
+ const social = getSocialItem(selected);
17876
+ if (social) {
17877
+ const result = duplicateSocialItem(social, editContentRef.current);
17878
+ if (!result) return;
17879
+ const orderJson = JSON.stringify(result.order);
17880
+ const carried = [
17881
+ { from: result.copiedFrom?.href, to: result.hrefKey },
17882
+ { from: result.copiedFrom?.icon, to: result.iconKey },
17883
+ { from: result.copiedFrom?.icon ? socialPlatformKey(result.copiedFrom.icon) : null, to: socialPlatformKey(result.iconKey) }
17884
+ ];
17885
+ const nodes = [{ key: SOCIALS_ORDER_KEY, text: orderJson }];
17886
+ for (const { from, to } of carried) {
17887
+ const value = from ? editContentRef.current[from] : void 0;
17888
+ if (value) nodes.push({ key: to, text: value });
17889
+ }
17890
+ editContentRef.current = {
17891
+ ...editContentRef.current,
17892
+ ...Object.fromEntries(nodes.map((node) => [node.key, node.text]))
17893
+ };
17894
+ postToParent2({ type: "ow:change", nodes });
17895
+ enforceLinkHrefs();
17896
+ requestAnimationFrame(() => selectRef.current(result.item));
17897
+ return;
17898
+ }
17278
17899
  if (isNavbarHrefKey(hrefKey)) {
17279
17900
  const result = duplicateNavbarItem(selected);
17280
17901
  if (!result) return;
@@ -17593,7 +18214,7 @@ function OhhwellsBridge() {
17593
18214
  onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
17594
18215
  onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
17595
18216
  itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
17596
- toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && isFooterFrameSelection && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
18217
+ toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
17597
18218
  ItemActionToolbar,
17598
18219
  {
17599
18220
  onEditLink: openLinkPopoverForSelected,
@@ -17604,12 +18225,12 @@ function OhhwellsBridge() {
17604
18225
  addItemDisabled: false,
17605
18226
  editLinkDisabled: false,
17606
18227
  moreDisabled: false,
17607
- duplicateDisabled: isFooterFrameSelection,
17608
- showEditLink: !isFooterFrameSelection && navDropdownPreviewOpen === null,
17609
- showAddItem: isFooterFrameSelection || !selectedIsCta && Boolean(
18228
+ duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow,
18229
+ showEditLink: !isFooterFrameSelection && !selectedIsSocialsRow && navDropdownPreviewOpen === null,
18230
+ showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
17610
18231
  selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
17611
18232
  ),
17612
- showMore: !selectedIsCta || isFooterFrameSelection,
18233
+ showMore: (!selectedIsCta || isFooterFrameSelection) && !selectedIsSocialsRow,
17613
18234
  dropdownOpen: navDropdownPreviewOpen,
17614
18235
  onDropdownOpenChange: handleNavDropdownOpenChange,
17615
18236
  headingVisible: footerHeadingVisible,