@ohhwells/bridge 0.1.54-next.151 → 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;
@@ -11903,7 +12259,7 @@ function isNavbarLinksContainer(el) {
11903
12259
  function isNavigationItem(el) {
11904
12260
  const anchor = el.matches("[data-ohw-href-key]") ? el : el.closest("[data-ohw-href-key]");
11905
12261
  if (!anchor) return false;
11906
- return Boolean(anchor.querySelector('[data-ohw-editable="text"]'));
12262
+ return Boolean(anchor.querySelector('[data-ohw-editable="text"]')) || Boolean(getSocialItem(anchor));
11907
12263
  }
11908
12264
  function findFooterItemGroup(item) {
11909
12265
  const explicit = item.closest("[data-ohw-footer-col], [data-ohw-footer-column]");
@@ -11924,8 +12280,9 @@ function isInferredFooterGroup(el) {
11924
12280
  const footer = el.closest("footer");
11925
12281
  if (!footer || el === footer) return false;
11926
12282
  if (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column")) return true;
12283
+ if (isSocialsRow(el)) return false;
11927
12284
  const count = Array.from(el.querySelectorAll("[data-ohw-href-key]")).filter(
11928
- isNavigationItem
12285
+ (item) => isNavigationItem(item) && !getSocialItem(item)
11929
12286
  ).length;
11930
12287
  return count >= 2;
11931
12288
  }
@@ -11969,7 +12326,8 @@ function deleteSelectedNavFooterItem(deps) {
11969
12326
  if (key.endsWith("-href")) applyLinkByKey2(key, text);
11970
12327
  else {
11971
12328
  document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`).forEach((el) => {
11972
- el.textContent = text;
12329
+ if (el.getAttribute("data-ohw-editable") === "icon") applyIconMarkup(el, text);
12330
+ else el.textContent = text;
11973
12331
  });
11974
12332
  }
11975
12333
  }
@@ -12031,6 +12389,21 @@ function deleteSelectedNavFooterItem(deps) {
12031
12389
  });
12032
12390
  return true;
12033
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
+ }
12034
12407
  if (isFooterHrefKey(hrefKey)) {
12035
12408
  const result = deleteFooterItem(selected);
12036
12409
  if (!result) return false;
@@ -12567,13 +12940,29 @@ function isNavItemPointerTarget(el) {
12567
12940
  function getNavigationItemAnchor(el) {
12568
12941
  const anchor = el.matches("[data-ohw-href-key]") ? el : el.closest("[data-ohw-href-key]");
12569
12942
  if (!anchor) return null;
12570
- if (!anchor.querySelector('[data-ohw-editable="text"]')) return null;
12943
+ if (!anchor.querySelector('[data-ohw-editable="text"]') && !getSocialItem(anchor)) return null;
12571
12944
  if (!isNavItemPointerTarget(anchor)) return null;
12572
12945
  return anchor;
12573
12946
  }
12574
12947
  function isNavigationItem2(el) {
12575
12948
  return getNavigationItemAnchor(el) !== null;
12576
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
+ }
12577
12966
  function listNavigationItems() {
12578
12967
  return Array.from(
12579
12968
  document.querySelectorAll("nav [data-ohw-href-key], footer [data-ohw-href-key]")
@@ -12608,7 +12997,7 @@ function getNavigationRoot(el) {
12608
12997
  return el.closest("nav, footer, aside");
12609
12998
  }
12610
12999
  function countFooterNavItems(el) {
12611
- 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;
12612
13001
  }
12613
13002
  function findFooterItemGroup2(item) {
12614
13003
  const explicit = item.closest("[data-ohw-footer-col], [data-ohw-footer-column]");
@@ -12629,10 +13018,11 @@ function isInferredFooterGroup2(el) {
12629
13018
  const footer = el.closest("footer");
12630
13019
  if (!footer || el === footer) return false;
12631
13020
  if (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column")) return true;
13021
+ if (isSocialsRow(el)) return false;
12632
13022
  return countFooterNavItems(el) >= 2;
12633
13023
  }
12634
13024
  function isNavigationContainer(el) {
12635
- 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);
12636
13026
  }
12637
13027
  function isNavbarLinksContainer2(el) {
12638
13028
  return el.hasAttribute("data-ohw-nav-container");
@@ -12715,6 +13105,8 @@ function resolveNavContainerSelectionTarget(target, clientX, clientY) {
12715
13105
  return null;
12716
13106
  }
12717
13107
  function getNavigationSelectionParent(el) {
13108
+ const socialsRow = findSocialsRow(el);
13109
+ if (socialsRow) return socialsRow;
12718
13110
  if (isNavigationItem2(el)) {
12719
13111
  const childrenRoot = el.closest("[data-ohw-nav-children]");
12720
13112
  if (childrenRoot) {
@@ -12740,6 +13132,10 @@ function getNavigationSelectionParent(el) {
12740
13132
  }
12741
13133
  function collectNavigationItemSiblingHintRects(selected) {
12742
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
+ }
12743
13139
  const footerColumn = getFooterColumn(selected);
12744
13140
  if (footerColumn) {
12745
13141
  return listFooterLinksInColumn(footerColumn).filter((link) => link !== selected).map((link) => link.getBoundingClientRect());
@@ -13441,6 +13837,8 @@ function OhhwellsBridge() {
13441
13837
  const toolbarVariantRef = (0, import_react16.useRef)("none");
13442
13838
  toolbarVariantRef.current = toolbarVariant;
13443
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);
13444
13842
  const [reorderHrefKey, setReorderHrefKey] = (0, import_react16.useState)(null);
13445
13843
  const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react16.useState)(false);
13446
13844
  const [toggleState, setToggleState] = (0, import_react16.useState)(null);
@@ -13709,6 +14107,8 @@ function OhhwellsBridge() {
13709
14107
  selectedHrefKeyRef.current = null;
13710
14108
  selectedFooterColAttrRef.current = null;
13711
14109
  setSelectedIsCta(false);
14110
+ setSelectedIsSocial(false);
14111
+ setSelectedIsSocialsRow(false);
13712
14112
  setReorderHrefKey(null);
13713
14113
  setReorderDragDisabled(false);
13714
14114
  setIsFooterFrameSelection(false);
@@ -13793,6 +14193,8 @@ function OhhwellsBridge() {
13793
14193
  selectedFooterColAttrRef.current = null;
13794
14194
  markSelected(navAnchor);
13795
14195
  setSelectedIsCta(isCtaButton(navAnchor));
14196
+ setSelectedIsSocial(Boolean(getSocialItem(navAnchor)));
14197
+ setSelectedIsSocialsRow(false);
13796
14198
  const isDropdownTrigger = !isNestedNavChild(navAnchor) && (navItemHasDropdownChildren(navAnchor) || navItemOwnsDropdownPanel(navAnchor));
13797
14199
  if (isNestedNavChild(navAnchor)) {
13798
14200
  setNavGroupForceOpen(navAnchor, true);
@@ -13916,6 +14318,27 @@ function OhhwellsBridge() {
13916
14318
  const handleAddChildItem = (0, import_react16.useCallback)(() => {
13917
14319
  const selected = selectedElRef.current;
13918
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
+ }
13919
14342
  if (toolbarVariantRef.current === "select-frame" && isFooterFrameSelection) {
13920
14343
  if (!selected.hasAttribute("data-ohw-footer-col") && !selected.closest("[data-ohw-footer-col]")) {
13921
14344
  }
@@ -14028,6 +14451,13 @@ function OhhwellsBridge() {
14028
14451
  }
14029
14452
  session.activeSlot = activeSlot;
14030
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
+ }
14031
14461
  if (session.kind === "link") {
14032
14462
  const columns = listFooterColumns();
14033
14463
  const slots2 = [];
@@ -14064,7 +14494,7 @@ function OhhwellsBridge() {
14064
14494
  if (session.wasSelected && selectedElRef.current === session.draggedEl) {
14065
14495
  setToolbarRect(rect);
14066
14496
  }
14067
- 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);
14068
14498
  refreshFooterDragVisuals(session, initialSlot, session.lastClientX, session.lastClientY);
14069
14499
  },
14070
14500
  [refreshFooterDragVisuals]
@@ -14080,8 +14510,11 @@ function OhhwellsBridge() {
14080
14510
  const x = typeof clientX === "number" && (clientX !== 0 || clientY !== 0) ? clientX : session.lastClientX;
14081
14511
  const y = typeof clientY === "number" && (clientX !== 0 || clientY !== 0) ? clientY : session.lastClientY;
14082
14512
  let nextOrder = null;
14083
- const slot = session.activeSlot ?? (session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(x, y, session.hrefKey) : session.kind === "column" ? hitTestColumnDropSlot(x, y) : null);
14084
- 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) {
14085
14518
  nextOrder = planFooterLinkMove(session.hrefKey, slot.columnIndex, slot.insertIndex);
14086
14519
  } else if (session.kind === "column" && slot) {
14087
14520
  nextOrder = planFooterColumnMove(session.sourceColumnIndex, slot.insertIndex);
@@ -14139,6 +14572,27 @@ function OhhwellsBridge() {
14139
14572
  }
14140
14573
  deselectRef.current();
14141
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
+ }
14142
14596
  if (nextOrder) {
14143
14597
  const orderJson = JSON.stringify(nextOrder);
14144
14598
  editContentRef.current = {
@@ -14177,7 +14631,22 @@ function OhhwellsBridge() {
14177
14631
  const startFooterLinkDrag = (0, import_react16.useCallback)(
14178
14632
  (anchor, clientX, clientY, wasSelected) => {
14179
14633
  const hrefKey = anchor.getAttribute("data-ohw-href-key");
14180
- 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;
14181
14650
  const column = findFooterColumnForLink(anchor);
14182
14651
  const columns = listFooterColumns();
14183
14652
  beginFooterDrag({
@@ -14314,6 +14783,8 @@ function OhhwellsBridge() {
14314
14783
  selectedFooterColAttrRef.current = null;
14315
14784
  markSelected(anchor);
14316
14785
  setSelectedIsCta(isCtaButton(anchor));
14786
+ setSelectedIsSocial(Boolean(getSocialItem(anchor)));
14787
+ setSelectedIsSocialsRow(false);
14317
14788
  clearHrefKeyHover(anchor);
14318
14789
  const isDropdownTrigger = !isNestedNavChild(anchor) && (navItemHasDropdownChildren(anchor) || navItemOwnsDropdownPanel(anchor));
14319
14790
  if (isNestedNavChild(anchor)) {
@@ -14356,6 +14827,8 @@ function OhhwellsBridge() {
14356
14827
  selectedFooterColAttrRef.current = isFooterColumn ? el.getAttribute("data-ohw-footer-col") ?? String(listFooterColumns().indexOf(el)) : null;
14357
14828
  markSelected(el);
14358
14829
  setSelectedIsCta(false);
14830
+ setSelectedIsSocial(false);
14831
+ setSelectedIsSocialsRow(isSocialsRow(el));
14359
14832
  clearHrefKeyHover(el);
14360
14833
  setNavGroupForceOpen(null, false);
14361
14834
  hoveredNavContainerRef.current = null;
@@ -14403,6 +14876,9 @@ function OhhwellsBridge() {
14403
14876
  selectedFooterColAttrRef.current = null;
14404
14877
  markSelected(logoEl);
14405
14878
  setSelectedIsCta(false);
14879
+ setSelectedIsSocial(false);
14880
+ setSelectedIsSocialsRow(false);
14881
+ setSelectedIsSocialsRow(false);
14406
14882
  clearHrefKeyHover(logoEl);
14407
14883
  hoveredNavContainerRef.current = null;
14408
14884
  setHoveredNavContainerRect(null);
@@ -14486,11 +14962,15 @@ function OhhwellsBridge() {
14486
14962
  );
14487
14963
  const activate = (0, import_react16.useCallback)((el, options) => {
14488
14964
  if (activeElRef.current === el) return;
14965
+ if (isIconEditable(el)) return;
14966
+ if (el.hasAttribute("data-ohw-social-label")) return;
14489
14967
  clearSelectedAttr();
14490
14968
  selectedElRef.current = null;
14491
14969
  selectedHrefKeyRef.current = null;
14492
14970
  selectedFooterColAttrRef.current = null;
14493
14971
  setSelectedIsCta(false);
14972
+ setSelectedIsSocial(false);
14973
+ setSelectedIsSocialsRow(false);
14494
14974
  deactivate();
14495
14975
  if (hoveredImageRef.current) {
14496
14976
  hoveredImageRef.current = null;
@@ -14634,7 +15114,7 @@ function OhhwellsBridge() {
14634
15114
  } else if (el.dataset.ohwEditable === "link") {
14635
15115
  applyLinkHref(el, val);
14636
15116
  } else if (el.dataset.ohwEditable === "icon") {
14637
- if (el.innerHTML !== val) el.innerHTML = val;
15117
+ applyIconMarkup(el, val);
14638
15118
  } else if (el.innerHTML !== val) {
14639
15119
  el.innerHTML = val;
14640
15120
  }
@@ -14645,6 +15125,7 @@ function OhhwellsBridge() {
14645
15125
  applyLogoSizes(content);
14646
15126
  reconcileNavbarItemsFromContent(content);
14647
15127
  reconcileFooterOrderFromContent(content);
15128
+ reconcileSocialsFromContent(content);
14648
15129
  enforceLinkHrefs();
14649
15130
  initSectionsFromContent(content, true);
14650
15131
  sectionsLoadedRef.current = true;
@@ -14712,6 +15193,7 @@ function OhhwellsBridge() {
14712
15193
  applyLogoFromContent(content);
14713
15194
  reconcileNavbarItemsFromContent(content);
14714
15195
  reconcileFooterOrderFromContent(content);
15196
+ reconcileSocialsFromContent(content);
14715
15197
  } finally {
14716
15198
  observer?.observe(document.body, { childList: true, subtree: true });
14717
15199
  }
@@ -14789,6 +15271,7 @@ function OhhwellsBridge() {
14789
15271
  const content = contentForNav();
14790
15272
  reconcileNavbarItemsFromContent(content);
14791
15273
  reconcileFooterOrderFromContent(content);
15274
+ reconcileSocialsFromContent(content);
14792
15275
  document.querySelectorAll("footer [data-ohw-href-key]").forEach((el) => {
14793
15276
  if (isFooterHrefKey(el.getAttribute("data-ohw-href-key"))) {
14794
15277
  disableNativeHrefDrag(el);
@@ -15086,7 +15569,7 @@ function OhhwellsBridge() {
15086
15569
  });
15087
15570
  return;
15088
15571
  }
15089
- if (isIconEditable(editable)) {
15572
+ if (isIconEditable(editable) && !getSocialItem(editable)) {
15090
15573
  e.preventDefault();
15091
15574
  e.stopPropagation();
15092
15575
  aiSectionApiRef.current?.selectFromElement(editable);
@@ -15111,6 +15594,7 @@ function OhhwellsBridge() {
15111
15594
  e.stopPropagation();
15112
15595
  if (selectedElRef.current === navAnchor) {
15113
15596
  if (e.detail >= 2) return;
15597
+ if (requestSocialDialog(navAnchor, postToParentRef.current, editContentRef.current)) return;
15114
15598
  activateRef.current(editable, { caretX: e.clientX, caretY: e.clientY });
15115
15599
  return;
15116
15600
  }
@@ -15127,6 +15611,7 @@ function OhhwellsBridge() {
15127
15611
  e.preventDefault();
15128
15612
  e.stopPropagation();
15129
15613
  if (selectedElRef.current === hrefAnchor) {
15614
+ if (requestSocialDialog(hrefAnchor, postToParentRef.current, editContentRef.current)) return;
15130
15615
  const textEditable = hrefAnchor.querySelector('[data-ohw-editable="text"]') ?? hrefAnchor.querySelector("[data-ohw-editable]");
15131
15616
  if (textEditable) {
15132
15617
  activateRef.current(textEditable, {
@@ -15165,6 +15650,13 @@ function OhhwellsBridge() {
15165
15650
  selectFrameRef.current(navContainerToSelect);
15166
15651
  return;
15167
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
+ }
15168
15660
  const footerColumnToSelect = resolveFooterColumnSelectionTarget(target, e.clientX, e.clientY);
15169
15661
  if (footerColumnToSelect) {
15170
15662
  e.preventDefault();
@@ -15217,6 +15709,7 @@ function OhhwellsBridge() {
15217
15709
  if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
15218
15710
  return;
15219
15711
  }
15712
+ if (getSocialItem(target)) return;
15220
15713
  const navLabel = getNavigationLabelEditable(target);
15221
15714
  const editable = navLabel?.editable ?? target.closest('[data-ohw-editable="text"], [data-ohw-editable="plain"]');
15222
15715
  if (!editable || isMediaEditable(editable) || editable.dataset.ohwEditable === "link") return;
@@ -15990,7 +16483,7 @@ function OhhwellsBridge() {
15990
16483
  if (footerSession) {
15991
16484
  e.preventDefault();
15992
16485
  if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
15993
- 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);
15994
16487
  refreshFooterDragVisualsRef.current(footerSession, slot, e.clientX, e.clientY);
15995
16488
  return;
15996
16489
  }
@@ -16042,6 +16535,47 @@ function OhhwellsBridge() {
16042
16535
  resumeAnimTracks();
16043
16536
  clearImageHover();
16044
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
+ };
16045
16579
  const handleIconMarkup = (e) => {
16046
16580
  if (e.data?.type !== "ow:icon-markup") return;
16047
16581
  const { key, markup } = e.data;
@@ -16051,7 +16585,7 @@ function OhhwellsBridge() {
16051
16585
  );
16052
16586
  if (!targets.length) return;
16053
16587
  targets.forEach((el) => {
16054
- el.innerHTML = markup;
16588
+ applyIconMarkup(el, markup);
16055
16589
  });
16056
16590
  postToParentRef.current({ type: "ow:change", nodes: [{ key, text: markup }] });
16057
16591
  };
@@ -16563,7 +17097,7 @@ function OhhwellsBridge() {
16563
17097
  }
16564
17098
  if (footerDragRef.current) {
16565
17099
  const session = footerDragRef.current;
16566
- 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);
16567
17101
  refreshFooterDragVisualsRef.current(session, slot, session.lastClientX, session.lastClientY);
16568
17102
  }
16569
17103
  if (navDragRef.current) {
@@ -16910,6 +17444,8 @@ function OhhwellsBridge() {
16910
17444
  window.addEventListener("message", handleClearSchedulingWidget);
16911
17445
  window.addEventListener("message", handleRemoveSchedulingSection);
16912
17446
  window.addEventListener("message", handleCollectSection);
17447
+ window.addEventListener("message", handleSocialCancel);
17448
+ window.addEventListener("message", handleSocialUpdate);
16913
17449
  window.addEventListener("message", handleIconMarkup);
16914
17450
  window.addEventListener("message", handleImageUrl);
16915
17451
  window.addEventListener("message", handleImageUploading);
@@ -16970,6 +17506,8 @@ function OhhwellsBridge() {
16970
17506
  window.removeEventListener("message", handleClearSchedulingWidget);
16971
17507
  window.removeEventListener("message", handleRemoveSchedulingSection);
16972
17508
  window.removeEventListener("message", handleCollectSection);
17509
+ window.removeEventListener("message", handleSocialCancel);
17510
+ window.removeEventListener("message", handleSocialUpdate);
16973
17511
  window.removeEventListener("message", handleIconMarkup);
16974
17512
  window.removeEventListener("message", handleImageUrl);
16975
17513
  window.removeEventListener("message", handleImageUploading);
@@ -17049,7 +17587,7 @@ function OhhwellsBridge() {
17049
17587
  clearTextSelection();
17050
17588
  const session = footerDragRef.current;
17051
17589
  if (!session) return;
17052
- 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);
17053
17591
  refreshFooterDragVisualsRef.current(session, slot, e.clientX, e.clientY);
17054
17592
  return;
17055
17593
  }
@@ -17290,6 +17828,10 @@ function OhhwellsBridge() {
17290
17828
  if (!anchor) return;
17291
17829
  const key = anchor.getAttribute("data-ohw-href-key");
17292
17830
  if (!key) return;
17831
+ if (requestSocialDialog(anchor, postToParentRef.current, editContentRef.current)) {
17832
+ deselect();
17833
+ return;
17834
+ }
17293
17835
  bumpLinkPopoverGrace();
17294
17836
  setLinkPopover({
17295
17837
  key,
@@ -17330,6 +17872,30 @@ function OhhwellsBridge() {
17330
17872
  if (!selected || !isNavigationItem2(selected)) return;
17331
17873
  const hrefKey = selected.getAttribute("data-ohw-href-key");
17332
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
+ }
17333
17899
  if (isNavbarHrefKey(hrefKey)) {
17334
17900
  const result = duplicateNavbarItem(selected);
17335
17901
  if (!result) return;
@@ -17648,7 +18214,7 @@ function OhhwellsBridge() {
17648
18214
  onItemPointerDown: toolbarVariant === "logo" ? void 0 : handleItemChromePointerDown,
17649
18215
  onItemClick: toolbarVariant === "logo" ? void 0 : handleItemChromeClick,
17650
18216
  itemDragSurface: toolbarVariant !== "logo" && !isFooterFrameSelection,
17651
- 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)(
17652
18218
  ItemActionToolbar,
17653
18219
  {
17654
18220
  onEditLink: openLinkPopoverForSelected,
@@ -17659,12 +18225,12 @@ function OhhwellsBridge() {
17659
18225
  addItemDisabled: false,
17660
18226
  editLinkDisabled: false,
17661
18227
  moreDisabled: false,
17662
- duplicateDisabled: isFooterFrameSelection,
17663
- showEditLink: !isFooterFrameSelection && navDropdownPreviewOpen === null,
17664
- showAddItem: isFooterFrameSelection || !selectedIsCta && Boolean(
18228
+ duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow,
18229
+ showEditLink: !isFooterFrameSelection && !selectedIsSocialsRow && navDropdownPreviewOpen === null,
18230
+ showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
17665
18231
  selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
17666
18232
  ),
17667
- showMore: !selectedIsCta || isFooterFrameSelection,
18233
+ showMore: (!selectedIsCta || isFooterFrameSelection) && !selectedIsSocialsRow,
17668
18234
  dropdownOpen: navDropdownPreviewOpen,
17669
18235
  onDropdownOpenChange: handleNavDropdownOpenChange,
17670
18236
  headingVisible: footerHeadingVisible,