@ohhwells/bridge 0.1.55 → 0.1.56

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
@@ -74,7 +74,7 @@ __export(index_exports, {
74
74
  module.exports = __toCommonJS(index_exports);
75
75
 
76
76
  // src/OhhwellsBridge.tsx
77
- var import_react15 = __toESM(require("react"), 1);
77
+ var import_react16 = __toESM(require("react"), 1);
78
78
  var import_client2 = require("react-dom/client");
79
79
  var import_react_dom3 = require("react-dom");
80
80
 
@@ -235,13 +235,17 @@ function MediaBox({
235
235
  const url = refValue ? ctx.resolveMedia(refValue) : null;
236
236
  const isIcon = /^(lucide|simple):/.test(refValue);
237
237
  const aspectRatio = aspect && /^\d+:\d+$/.test(aspect) ? aspect.replace(":", " / ") : void 0;
238
- const editAttrs = ctx.keyFor && editPath && !isIcon ? { "data-ohw-key": ctx.keyFor(editPath), "data-ohw-editable": "image" } : {};
238
+ const editAttrs = ctx.keyFor && editPath ? {
239
+ "data-ohw-key": ctx.keyFor(editPath),
240
+ "data-ohw-editable": isIcon ? "icon" : "image"
241
+ } : {};
239
242
  if (isIcon) {
240
243
  const Icon = refValue.startsWith("lucide:") ? lucideByName(refValue.slice(7)) : null;
241
244
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
242
245
  "span",
243
246
  {
244
247
  "data-ai-icon": refValue,
248
+ ...editAttrs,
245
249
  style: {
246
250
  display: "inline-flex",
247
251
  width: 48,
@@ -5935,6 +5939,7 @@ function ToolbarActionTooltip({
5935
5939
  function ItemActionToolbar({
5936
5940
  onEditLink,
5937
5941
  onAddItem,
5942
+ onStyle,
5938
5943
  onSelectParent,
5939
5944
  onDuplicate,
5940
5945
  onDelete,
@@ -5946,6 +5951,8 @@ function ItemActionToolbar({
5946
5951
  deleteDisabled = false,
5947
5952
  showEditLink = true,
5948
5953
  showAddItem = true,
5954
+ showStyle = false,
5955
+ styleActive = false,
5949
5956
  showMore = true,
5950
5957
  tooltipSide = "bottom",
5951
5958
  dropdownOpen = null,
@@ -6019,6 +6026,22 @@ function ItemActionToolbar({
6019
6026
  children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.Link, { className: "size-4 shrink-0", "aria-hidden": true })
6020
6027
  }
6021
6028
  ) : null,
6029
+ showStyle ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
6030
+ ToolbarActionTooltip,
6031
+ {
6032
+ label: "Style",
6033
+ side: tooltipSide,
6034
+ buttonProps: {
6035
+ active: styleActive,
6036
+ onMouseDown: (e) => {
6037
+ e.preventDefault();
6038
+ e.stopPropagation();
6039
+ onStyle?.();
6040
+ }
6041
+ },
6042
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react3.Brush, { className: "size-4 shrink-0", "aria-hidden": true })
6043
+ }
6044
+ ) : null,
6022
6045
  showAddItem ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
6023
6046
  ToolbarActionTooltip,
6024
6047
  {
@@ -9525,6 +9548,449 @@ function deleteNavbarItem(sourceAnchor) {
9525
9548
  };
9526
9549
  }
9527
9550
 
9551
+ // src/lib/icon-markup.ts
9552
+ var GLYPH_SELECTOR = "svg, img";
9553
+ function referenceBox(slot) {
9554
+ const row = slot.closest("[data-ohw-socials-row]") ?? slot.closest("a")?.parentElement ?? null;
9555
+ const neighbour = row ? Array.from(row.querySelectorAll('[data-ohw-editable="icon"]')).find((el) => el !== slot) : null;
9556
+ const source = (neighbour ?? slot).querySelector(GLYPH_SELECTOR);
9557
+ const box = source?.getBoundingClientRect() ?? null;
9558
+ return box?.width && box.height ? box : null;
9559
+ }
9560
+ function iconMarkupSizedFor(slot, markup) {
9561
+ const box = referenceBox(slot);
9562
+ if (!box) return markup;
9563
+ const holder = document.createElement("div");
9564
+ holder.innerHTML = markup;
9565
+ const glyph = holder.querySelector(GLYPH_SELECTOR);
9566
+ if (!glyph) return markup;
9567
+ glyph.style.width = `${Math.round(box.width)}px`;
9568
+ glyph.style.height = `${Math.round(box.height)}px`;
9569
+ return holder.innerHTML;
9570
+ }
9571
+ function applyIconMarkup(slot, markup) {
9572
+ if (!markup) return;
9573
+ const coloured = iconMarkupInheritingColour(markup);
9574
+ const sized = iconMarkupSizedFor(slot, coloured);
9575
+ if (slot.innerHTML !== sized) slot.innerHTML = sized;
9576
+ if (sized === coloured) {
9577
+ requestAnimationFrame(() => {
9578
+ if (!slot.isConnected) return;
9579
+ const resized = iconMarkupSizedFor(slot, coloured);
9580
+ if (resized !== coloured && slot.innerHTML !== resized) slot.innerHTML = resized;
9581
+ });
9582
+ }
9583
+ }
9584
+ function detectIconStyle(el) {
9585
+ const row = el.closest("[data-ohw-socials-row]");
9586
+ const glyphs = Array.from((row ?? el).querySelectorAll("svg"));
9587
+ const outlined = glyphs.some((svg) => {
9588
+ return Array.from(svg.querySelectorAll("*")).some((node) => {
9589
+ return node.getAttribute("stroke") !== null && node.getAttribute("stroke") !== "none";
9590
+ });
9591
+ });
9592
+ return outlined ? "outline" : "fill";
9593
+ }
9594
+ function iconMarkupInheritingColour(markup) {
9595
+ const holder = document.createElement("div");
9596
+ holder.innerHTML = markup;
9597
+ holder.querySelectorAll("svg *").forEach((node) => {
9598
+ if (node.getAttribute("fill") && node.getAttribute("fill") !== "none") {
9599
+ node.setAttribute("fill", "currentColor");
9600
+ }
9601
+ if (node.getAttribute("stroke") && node.getAttribute("stroke") !== "none") {
9602
+ node.setAttribute("stroke", "currentColor");
9603
+ }
9604
+ });
9605
+ return holder.innerHTML;
9606
+ }
9607
+
9608
+ // src/lib/socials-items.ts
9609
+ var ICON_SELECTOR = '[data-ohw-editable="icon"]';
9610
+ var SOCIAL_KEY_RE = /(^|-)social(s)?(-|$)/i;
9611
+ var SOCIALS_ROW_ATTR = "data-ohw-socials-row";
9612
+ var SOCIALS_ITEM_ATTR = "data-ohw-social-item";
9613
+ function isSocialItem(el) {
9614
+ if (!el) return false;
9615
+ const anchor = el instanceof HTMLAnchorElement ? el : el.closest("a");
9616
+ if (!anchor) return false;
9617
+ if (SOCIAL_KEY_RE.test(anchor.getAttribute("data-ohw-href-key") ?? "")) return true;
9618
+ return anchor.querySelectorAll(ICON_SELECTOR).length === 1;
9619
+ }
9620
+ function getSocialItem(el) {
9621
+ const anchor = el.closest("a");
9622
+ return isSocialItem(anchor) ? anchor : null;
9623
+ }
9624
+ function findSocialsRow(el) {
9625
+ const item = getSocialItem(el);
9626
+ if (!item) return null;
9627
+ const wrapper = item.parentElement;
9628
+ const row = wrapper && wrapper.querySelectorAll("a").length === 1 && wrapper.matches("li, div, span") ? wrapper.parentElement : wrapper;
9629
+ if (!row) return null;
9630
+ const anchors = Array.from(row.querySelectorAll("a"));
9631
+ if (!anchors.length || !anchors.every((anchor) => isSocialItem(anchor))) return null;
9632
+ return row;
9633
+ }
9634
+ function isSocialsRow(el) {
9635
+ const anchors = Array.from(el.querySelectorAll("a"));
9636
+ return anchors.length > 0 && anchors.every((anchor) => isSocialItem(anchor));
9637
+ }
9638
+ function listSocialItems(row) {
9639
+ return Array.from(row.children).map((child) => {
9640
+ if (!(child instanceof HTMLElement)) return null;
9641
+ const anchor = child.matches("a") ? child : child.querySelector("a");
9642
+ return isSocialItem(anchor) ? anchor : null;
9643
+ }).filter((item) => item !== null);
9644
+ }
9645
+ function socialRowUnit(item) {
9646
+ const row = findSocialsRow(item);
9647
+ let node = item;
9648
+ while (node.parentElement && node.parentElement !== row) {
9649
+ node = node.parentElement;
9650
+ }
9651
+ return node;
9652
+ }
9653
+ function listSocialsRows(root = document) {
9654
+ const rows = /* @__PURE__ */ new Set();
9655
+ root.querySelectorAll(`${ICON_SELECTOR}, a[data-ohw-href-key]`).forEach((el) => {
9656
+ const row = findSocialsRow(el);
9657
+ if (row) rows.add(row);
9658
+ });
9659
+ root.querySelectorAll(`[${SOCIALS_ROW_ATTR}]`).forEach((row) => rows.add(row));
9660
+ return Array.from(rows);
9661
+ }
9662
+ var rowTemplates = /* @__PURE__ */ new Map();
9663
+ function markSocialsRows(root = document) {
9664
+ root.querySelectorAll(`[${SOCIALS_ITEM_ATTR}]`).forEach((item) => {
9665
+ item.removeAttribute(SOCIALS_ITEM_ATTR);
9666
+ });
9667
+ listSocialsRows(root).forEach((row) => {
9668
+ row.setAttribute(SOCIALS_ROW_ATTR, "");
9669
+ const items = listSocialItems(row);
9670
+ if (items[0]) rowTemplates.set(rowKeyOf(row), socialRowUnit(items[0]).outerHTML);
9671
+ items.forEach((item, index) => {
9672
+ item.setAttribute(SOCIALS_ITEM_ATTR, String(index));
9673
+ const iconKey = socialIconKey(item);
9674
+ if (iconKey) ensureLabelSlot(item, iconKey);
9675
+ });
9676
+ });
9677
+ }
9678
+ var SOCIALS_LABEL_ATTR = "data-ohw-social-label";
9679
+ function ensureLabelSlot(item, iconKey) {
9680
+ if (socialLabelElement(item)) return;
9681
+ const label = document.createElement("span");
9682
+ label.setAttribute("data-ohw-key", `${iconKey}-label`);
9683
+ label.setAttribute("data-ohw-editable", "text");
9684
+ label.setAttribute(SOCIALS_LABEL_ATTR, "");
9685
+ label.style.display = "none";
9686
+ label.textContent = item.getAttribute("aria-label") ?? "";
9687
+ item.appendChild(label);
9688
+ }
9689
+ function socialLabelElement(item) {
9690
+ return item.querySelector(
9691
+ `[${SOCIALS_LABEL_ATTR}], [data-ohw-editable="text"], [data-ohw-editable="plain"]`
9692
+ );
9693
+ }
9694
+ function socialLabelKey(iconKey) {
9695
+ return `${iconKey}-label`;
9696
+ }
9697
+ function applyStoredValues(item, content) {
9698
+ const hrefKey = socialHrefKey(item);
9699
+ const iconKey = socialIconKey(item);
9700
+ if (hrefKey && content[hrefKey] !== void 0) item.setAttribute("href", content[hrefKey]);
9701
+ if (iconKey) {
9702
+ const glyph = item.querySelector(ICON_SELECTOR);
9703
+ if (glyph && content[iconKey]) applyIconMarkup(glyph, content[iconKey]);
9704
+ const label = item.querySelector(`[${SOCIALS_LABEL_ATTR}]`);
9705
+ label?.setAttribute("data-ohw-key", socialLabelKey(iconKey));
9706
+ const stored = content[socialLabelKey(iconKey)];
9707
+ if (label && stored) label.textContent = stored;
9708
+ }
9709
+ }
9710
+ function socialPlatformKey(iconKey) {
9711
+ return `${iconKey}-platform`;
9712
+ }
9713
+ function socialHrefKey(item) {
9714
+ return item.getAttribute("data-ohw-href-key");
9715
+ }
9716
+ function socialIconKey(item) {
9717
+ return item.querySelector(ICON_SELECTOR)?.dataset.ohwKey ?? null;
9718
+ }
9719
+ var SOCIALS_ORDER_KEY = "__ohw_socials_order";
9720
+ function fromMarkup(markup) {
9721
+ const holder = document.createElement("div");
9722
+ holder.innerHTML = markup;
9723
+ return holder.firstElementChild instanceof HTMLElement ? holder.firstElementChild : null;
9724
+ }
9725
+ var rowKeys = /* @__PURE__ */ new WeakMap();
9726
+ function rowKeyOf(row) {
9727
+ const first = listSocialItems(row)[0];
9728
+ const itemKey = first ? socialIconKey(first) ?? socialHrefKey(first)?.replace(/-href$/, "") : null;
9729
+ const derived = itemKey?.replace(/-[^-]+$/, "") || null;
9730
+ if (derived) rowKeys.set(row, derived);
9731
+ return derived ?? rowKeys.get(row) ?? "social";
9732
+ }
9733
+ function getSocialsOrderFromDom(root = document) {
9734
+ const order = {};
9735
+ listSocialsRows(root).forEach((row) => {
9736
+ order[rowKeyOf(row)] = listSocialItems(row).map((item) => socialHrefKey(item)).filter((key) => Boolean(key));
9737
+ });
9738
+ return order;
9739
+ }
9740
+ function hasStoredValue(content, hrefKey) {
9741
+ const iconKey = hrefKey.replace(/-href$/, "");
9742
+ return Boolean(content[hrefKey]) || Boolean(content[iconKey]);
9743
+ }
9744
+ function parseSocialsOrder(raw) {
9745
+ if (!raw) return null;
9746
+ try {
9747
+ const parsed = JSON.parse(raw);
9748
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
9749
+ } catch {
9750
+ return null;
9751
+ }
9752
+ }
9753
+ function nextSocialIndex(row, rowKey, content) {
9754
+ 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));
9755
+ return Math.max(-1, ...used) + 1;
9756
+ }
9757
+ function insertSocialItem(row, after, content = {}) {
9758
+ const rowKey = rowKeyOf(row);
9759
+ const template = listSocialItems(row)[0];
9760
+ const remembered = rowTemplates.get(rowKey);
9761
+ if (!template && !remembered) return null;
9762
+ const index = nextSocialIndex(row, rowKey, content);
9763
+ const iconKey = `${rowKey}-${index}`;
9764
+ const hrefKey = `${iconKey}-href`;
9765
+ const templateUnit = template ? socialRowUnit(template) : null;
9766
+ const unit = templateUnit ? templateUnit.cloneNode(true) : fromMarkup(remembered);
9767
+ const item = unit && (unit.matches("a") ? unit : unit.querySelector("a"));
9768
+ if (!unit || !item) return null;
9769
+ item.setAttribute("data-ohw-href-key", hrefKey);
9770
+ item.setAttribute("href", "");
9771
+ item.removeAttribute("aria-label");
9772
+ item.querySelectorAll("[data-ohw-hovered], [data-ohw-selected]").forEach((el) => {
9773
+ el.removeAttribute("data-ohw-hovered");
9774
+ el.removeAttribute("data-ohw-selected");
9775
+ });
9776
+ const icon = item.querySelector(ICON_SELECTOR);
9777
+ icon?.setAttribute("data-ohw-key", iconKey);
9778
+ item.querySelector(`[${SOCIALS_LABEL_ATTR}]`)?.remove();
9779
+ const afterUnit = after ? socialRowUnit(after) : null;
9780
+ if (afterUnit && afterUnit.parentElement === row) afterUnit.insertAdjacentElement("afterend", unit);
9781
+ else row.appendChild(unit);
9782
+ markSocialsRows(row.ownerDocument);
9783
+ return { item, hrefKey, iconKey, order: getSocialsOrderFromDom(row.ownerDocument) };
9784
+ }
9785
+ function duplicateSocialItem(item, content) {
9786
+ const row = findSocialsRow(item);
9787
+ const created = row ? insertSocialItem(row, item, content) : null;
9788
+ if (!created) return null;
9789
+ const sourceHref = socialHrefKey(item);
9790
+ const sourceIcon = socialIconKey(item);
9791
+ const link = created.item;
9792
+ if (sourceHref) link.setAttribute("href", item.getAttribute("href") ?? "");
9793
+ const glyph = item.querySelector(ICON_SELECTOR)?.innerHTML;
9794
+ if (glyph) {
9795
+ const slot = link.querySelector(ICON_SELECTOR);
9796
+ if (slot) slot.innerHTML = glyph;
9797
+ }
9798
+ return {
9799
+ ...created,
9800
+ copiedFrom: { href: sourceHref, icon: sourceIcon }
9801
+ };
9802
+ }
9803
+ function removeSocialItem(item, content) {
9804
+ const row = findSocialsRow(item);
9805
+ if (!row) return null;
9806
+ const hrefKey = socialHrefKey(item);
9807
+ const iconKey = socialIconKey(item);
9808
+ const removedKeys = [hrefKey, iconKey].filter((key) => Boolean(key));
9809
+ if (!removedKeys.length) return null;
9810
+ const previousOrder = getSocialsOrderFromDom(row.ownerDocument);
9811
+ const previousContent = Object.fromEntries(
9812
+ removedKeys.filter((key) => key in content).map((key) => [key, content[key]])
9813
+ );
9814
+ const unit = socialRowUnit(item);
9815
+ const nextSibling = unit.nextElementSibling;
9816
+ unit.remove();
9817
+ markSocialsRows(row.ownerDocument);
9818
+ return {
9819
+ removedKeys,
9820
+ previousContent,
9821
+ order: getSocialsOrderFromDom(row.ownerDocument),
9822
+ previousOrder,
9823
+ undo: () => {
9824
+ if (nextSibling) nextSibling.before(unit);
9825
+ else row.appendChild(unit);
9826
+ markSocialsRows(row.ownerDocument);
9827
+ }
9828
+ };
9829
+ }
9830
+ function applySocialsOrder(order, root = document) {
9831
+ listSocialsRows(root).forEach((row) => {
9832
+ const wanted = order[rowKeyOf(row)];
9833
+ if (!wanted) return;
9834
+ const byKey = new Map(listSocialItems(row).map((item) => [socialHrefKey(item), item]));
9835
+ wanted.forEach((key) => {
9836
+ const item = byKey.get(key);
9837
+ if (item) row.appendChild(socialRowUnit(item));
9838
+ });
9839
+ });
9840
+ markSocialsRows(root);
9841
+ }
9842
+ function reconcileSocialsFromContent(content, root = document) {
9843
+ markSocialsRows(root);
9844
+ const stored = parseSocialsOrder(content[SOCIALS_ORDER_KEY]);
9845
+ if (!stored) return;
9846
+ listSocialsRows(root).forEach((row) => {
9847
+ const wanted = stored[rowKeyOf(row)];
9848
+ if (!wanted) return;
9849
+ if (!wanted.length) return;
9850
+ wanted.forEach((key) => {
9851
+ if (listSocialItems(row).some((item) => socialHrefKey(item) === key)) return;
9852
+ if (!hasStoredValue(content, key)) return;
9853
+ const created = insertSocialItem(row, null, content);
9854
+ if (created) {
9855
+ created.item.setAttribute("data-ohw-href-key", key);
9856
+ created.item.querySelector(ICON_SELECTOR)?.setAttribute("data-ohw-key", key.replace(/-href$/, ""));
9857
+ applyStoredValues(created.item, content);
9858
+ }
9859
+ });
9860
+ const present = listSocialItems(row);
9861
+ const surviving = present.filter((item) => {
9862
+ const key = socialHrefKey(item);
9863
+ return !key || wanted.includes(key);
9864
+ });
9865
+ if (surviving.length) {
9866
+ present.forEach((item) => {
9867
+ if (!surviving.includes(item)) socialRowUnit(item).remove();
9868
+ });
9869
+ }
9870
+ });
9871
+ applySocialsOrder(stored, root);
9872
+ }
9873
+ var DROP_BAR_THICKNESS = 3;
9874
+ var DROP_BAR_GAP = 8;
9875
+ function buildSocialDropSlots(row) {
9876
+ const items = listSocialItems(row);
9877
+ if (!items.length) return [];
9878
+ const rects = items.map((item) => item.getBoundingClientRect());
9879
+ return items.concat(items[items.length - 1]).map((_, index) => {
9880
+ const previous = rects[index - 1];
9881
+ const next = rects[index];
9882
+ const centre = previous && next ? (previous.right + next.left) / 2 : next ? next.left - DROP_BAR_GAP : previous.right + DROP_BAR_GAP;
9883
+ const rect = next ?? previous;
9884
+ return {
9885
+ insertIndex: index,
9886
+ columnIndex: -1,
9887
+ left: centre - DROP_BAR_THICKNESS / 2,
9888
+ top: rect.top,
9889
+ width: DROP_BAR_THICKNESS,
9890
+ height: rect.height,
9891
+ direction: "vertical"
9892
+ };
9893
+ });
9894
+ }
9895
+ function findSocialByHrefKey(hrefKey, root = document) {
9896
+ const el = root.querySelector(`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`);
9897
+ return el ? getSocialItem(el) : null;
9898
+ }
9899
+ function buildSocialDropSlotsForKey(hrefKey, root = document) {
9900
+ const item = findSocialByHrefKey(hrefKey, root);
9901
+ const row = item ? findSocialsRow(item) : null;
9902
+ return row ? buildSocialDropSlots(row) : [];
9903
+ }
9904
+ function hitTestSocialDropSlot(clientX, clientY, draggedHrefKey, root = document) {
9905
+ const distanceTo = (slot) => {
9906
+ const dx = clientX - (slot.left + slot.width / 2);
9907
+ const dy = clientY < slot.top ? slot.top - clientY : Math.max(0, clientY - (slot.top + slot.height));
9908
+ return Math.hypot(dx, dy);
9909
+ };
9910
+ const slots = buildSocialDropSlotsForKey(draggedHrefKey, root);
9911
+ return slots.reduce((best, slot) => {
9912
+ return !best || distanceTo(slot) < distanceTo(best) ? slot : best;
9913
+ }, null);
9914
+ }
9915
+ function planSocialMove(hrefKey, insertIndex, root = document) {
9916
+ const item = findSocialByHrefKey(hrefKey, root);
9917
+ const row = item ? findSocialsRow(item) : null;
9918
+ if (!row) return null;
9919
+ const order = getSocialsOrderFromDom(root);
9920
+ const key = rowKeyOf(row);
9921
+ const current = order[key];
9922
+ if (!current) return null;
9923
+ const from = current.indexOf(hrefKey);
9924
+ if (from < 0) return null;
9925
+ const next = current.filter((_, index) => index !== from);
9926
+ next.splice(insertIndex > from ? insertIndex - 1 : insertIndex, 0, hrefKey);
9927
+ return { ...order, [key]: next };
9928
+ }
9929
+ var SOCIALS_DISPLAY_KEY = "__ohw_socials_display";
9930
+ function readSocialsDisplay(row) {
9931
+ const items = listSocialItems(row);
9932
+ const visible = (el) => Boolean(el) && el.style.display !== "none" && el.getAttribute("data-ohw-hidden") === null;
9933
+ return {
9934
+ text: items.some((item) => visible(socialLabelElement(item))),
9935
+ icon: items.some((item) => visible(item.querySelector(ICON_SELECTOR)))
9936
+ };
9937
+ }
9938
+ function parseSocialsDisplay(raw) {
9939
+ if (!raw) return null;
9940
+ try {
9941
+ const parsed = JSON.parse(raw);
9942
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
9943
+ } catch {
9944
+ return null;
9945
+ }
9946
+ }
9947
+ function socialsDisplayFor(row, content) {
9948
+ return parseSocialsDisplay(content[SOCIALS_DISPLAY_KEY])?.[rowKeyOf(row)] ?? readSocialsDisplay(row);
9949
+ }
9950
+ function socialsDisplayWith(row, display, content) {
9951
+ return { ...parseSocialsDisplay(content[SOCIALS_DISPLAY_KEY]) ?? {}, [rowKeyOf(row)]: display };
9952
+ }
9953
+ function applySocialsDisplayToRow(row, display) {
9954
+ listSocialItems(row).forEach((item) => {
9955
+ const label = socialLabelElement(item);
9956
+ const icon = item.querySelector(ICON_SELECTOR);
9957
+ if (label) label.style.display = display.text ? "" : "none";
9958
+ if (icon) icon.style.display = display.icon ? "" : "none";
9959
+ });
9960
+ }
9961
+ function applySocialsDisplayFromContent(content, root = document) {
9962
+ const stored = parseSocialsDisplay(content[SOCIALS_DISPLAY_KEY]);
9963
+ if (!stored) return;
9964
+ listSocialsRows(root).forEach((row) => {
9965
+ const display = stored[rowKeyOf(row)];
9966
+ if (!display) return;
9967
+ if (display.icon) {
9968
+ listSocialItems(row).forEach((item) => {
9969
+ const iconKey = ensureIconSlot(item);
9970
+ const slot = item.querySelector(ICON_SELECTOR);
9971
+ if (iconKey && slot && content[iconKey]) applyIconMarkup(slot, content[iconKey]);
9972
+ });
9973
+ }
9974
+ applySocialsDisplayToRow(row, display);
9975
+ });
9976
+ }
9977
+ function socialsMissingIcons(row) {
9978
+ return listSocialItems(row).filter((item) => !item.querySelector(ICON_SELECTOR)).map((item) => ({ hrefKey: socialHrefKey(item) ?? "", url: item.getAttribute("href") ?? "" })).filter((entry) => Boolean(entry.hrefKey));
9979
+ }
9980
+ function ensureIconSlot(item) {
9981
+ const existing = item.querySelector(ICON_SELECTOR);
9982
+ if (existing) return existing.dataset.ohwKey ?? null;
9983
+ const hrefKey = socialHrefKey(item);
9984
+ if (!hrefKey) return null;
9985
+ const iconKey = hrefKey.replace(/-href$/, "");
9986
+ const slot = document.createElement("span");
9987
+ slot.setAttribute("data-ohw-key", iconKey);
9988
+ slot.setAttribute("data-ohw-editable", "icon");
9989
+ slot.style.display = "inline-flex";
9990
+ item.prepend(slot);
9991
+ return iconKey;
9992
+ }
9993
+
9528
9994
  // src/lib/footer-items.ts
9529
9995
  var FOOTER_ORDER_KEY = "__ohw_footer_order";
9530
9996
  var MAX_FOOTER_COLUMNS = 18;
@@ -10401,6 +10867,251 @@ function addFooterColumnWithPersist({
10401
10867
  return result;
10402
10868
  }
10403
10869
 
10870
+ // src/ui/FloatingPanel.tsx
10871
+ var import_react13 = require("react");
10872
+ var import_lucide_react13 = require("lucide-react");
10873
+ var import_jsx_runtime26 = require("react/jsx-runtime");
10874
+ var PANEL_WIDTH = 256;
10875
+ var EDGE_MARGIN = 16;
10876
+ function getVisibleClip(parentScroll) {
10877
+ const left = 0;
10878
+ const right = window.innerWidth;
10879
+ if (!parentScroll) {
10880
+ return { top: 0, bottom: window.innerHeight, left, right };
10881
+ }
10882
+ const { iframeOffsetTop, headerH: visibleCanvasTop, canvasH } = parentScroll;
10883
+ const top = Math.max(0, visibleCanvasTop - iframeOffsetTop);
10884
+ const bottom = Math.min(window.innerHeight, visibleCanvasTop + canvasH - iframeOffsetTop);
10885
+ return { top, bottom: Math.max(top, bottom), left, right };
10886
+ }
10887
+ function defaultFloatingPanelPosition(parentScroll, panelHeight = 280) {
10888
+ const clip = getVisibleClip(parentScroll);
10889
+ return {
10890
+ x: Math.max(EDGE_MARGIN, clip.right - PANEL_WIDTH - EDGE_MARGIN),
10891
+ y: Math.min(
10892
+ Math.max(clip.top + EDGE_MARGIN, EDGE_MARGIN),
10893
+ Math.max(clip.top + EDGE_MARGIN, clip.bottom - panelHeight - EDGE_MARGIN)
10894
+ )
10895
+ };
10896
+ }
10897
+ function clampPosition(pos, parentScroll, panelW, panelH) {
10898
+ const clip = getVisibleClip(parentScroll);
10899
+ const maxX = Math.max(clip.left + EDGE_MARGIN, clip.right - panelW - EDGE_MARGIN);
10900
+ const maxY = Math.max(clip.top + EDGE_MARGIN, clip.bottom - panelH - EDGE_MARGIN);
10901
+ return {
10902
+ x: Math.min(Math.max(pos.x, clip.left + EDGE_MARGIN), maxX),
10903
+ y: Math.min(Math.max(pos.y, clip.top + EDGE_MARGIN), maxY)
10904
+ };
10905
+ }
10906
+ function FloatingPanel({
10907
+ open,
10908
+ title,
10909
+ context,
10910
+ icon,
10911
+ onClose,
10912
+ children,
10913
+ position,
10914
+ onPositionChange,
10915
+ parentScroll = null,
10916
+ className,
10917
+ bodyClassName
10918
+ }) {
10919
+ const panelRef = (0, import_react13.useRef)(null);
10920
+ const [measured, setMeasured] = (0, import_react13.useState)({ w: PANEL_WIDTH, h: 280 });
10921
+ const dragRef = (0, import_react13.useRef)(null);
10922
+ const resolved = position ?? defaultFloatingPanelPosition(parentScroll, measured.h);
10923
+ const clamped = clampPosition(resolved, parentScroll, measured.w, measured.h);
10924
+ (0, import_react13.useLayoutEffect)(() => {
10925
+ if (!open || !panelRef.current) return;
10926
+ const el = panelRef.current;
10927
+ const next = { w: el.offsetWidth || PANEL_WIDTH, h: el.offsetHeight || 280 };
10928
+ setMeasured((prev) => prev.w === next.w && prev.h === next.h ? prev : next);
10929
+ }, [open, children, title, context]);
10930
+ (0, import_react13.useEffect)(() => {
10931
+ if (!open || !position || !onPositionChange) return;
10932
+ const next = clampPosition(position, parentScroll, measured.w, measured.h);
10933
+ if (next.x !== position.x || next.y !== position.y) onPositionChange(next);
10934
+ }, [open, parentScroll, measured.w, measured.h, position, onPositionChange]);
10935
+ const onHeaderPointerDown = (0, import_react13.useCallback)(
10936
+ (e) => {
10937
+ if (e.button !== 0) return;
10938
+ if (e.target.closest("[data-ohw-floating-panel-close]")) return;
10939
+ e.preventDefault();
10940
+ e.stopPropagation();
10941
+ const el = e.currentTarget;
10942
+ el.setPointerCapture(e.pointerId);
10943
+ dragRef.current = {
10944
+ pointerId: e.pointerId,
10945
+ startX: e.clientX,
10946
+ startY: e.clientY,
10947
+ originX: clamped.x,
10948
+ originY: clamped.y
10949
+ };
10950
+ },
10951
+ [clamped.x, clamped.y]
10952
+ );
10953
+ const onHeaderPointerMove = (0, import_react13.useCallback)(
10954
+ (e) => {
10955
+ const drag = dragRef.current;
10956
+ if (!drag || drag.pointerId !== e.pointerId) return;
10957
+ e.preventDefault();
10958
+ const next = clampPosition(
10959
+ {
10960
+ x: drag.originX + (e.clientX - drag.startX),
10961
+ y: drag.originY + (e.clientY - drag.startY)
10962
+ },
10963
+ parentScroll,
10964
+ measured.w,
10965
+ measured.h
10966
+ );
10967
+ onPositionChange?.(next);
10968
+ },
10969
+ [measured.h, measured.w, onPositionChange, parentScroll]
10970
+ );
10971
+ const endDrag = (0, import_react13.useCallback)((e) => {
10972
+ const drag = dragRef.current;
10973
+ if (!drag || drag.pointerId !== e.pointerId) return;
10974
+ dragRef.current = null;
10975
+ try {
10976
+ e.currentTarget.releasePointerCapture(e.pointerId);
10977
+ } catch {
10978
+ }
10979
+ }, []);
10980
+ if (!open) return null;
10981
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
10982
+ "div",
10983
+ {
10984
+ ref: panelRef,
10985
+ "data-ohw-floating-panel": "",
10986
+ role: "dialog",
10987
+ "aria-label": title,
10988
+ className: cn(
10989
+ // Above MediaOverlay / item chrome (2147483646); link-modal content shares this tier.
10990
+ "fixed z-[2147483647] flex w-64 flex-col overflow-hidden rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
10991
+ className
10992
+ ),
10993
+ style: { left: clamped.x, top: clamped.y },
10994
+ onMouseDown: (e) => e.stopPropagation(),
10995
+ onPointerDown: (e) => e.stopPropagation(),
10996
+ onClick: (e) => e.stopPropagation(),
10997
+ children: [
10998
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
10999
+ "div",
11000
+ {
11001
+ "data-ohw-floating-panel-header": "",
11002
+ className: "relative flex cursor-grab items-start gap-2 border-b border-border py-5 pl-5 pr-11 active:cursor-grabbing",
11003
+ onPointerDown: onHeaderPointerDown,
11004
+ onPointerMove: onHeaderPointerMove,
11005
+ onPointerUp: endDrag,
11006
+ onPointerCancel: endDrag,
11007
+ children: [
11008
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col gap-1.5", children: [
11009
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center gap-2", children: [
11010
+ icon ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "shrink-0 text-foreground", children: icon }) : null,
11011
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "min-w-0 flex-1 text-lg font-semibold leading-7 text-foreground", children: title })
11012
+ ] }),
11013
+ context ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "w-full text-sm leading-5 text-muted-foreground", children: context }) : null
11014
+ ] }),
11015
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
11016
+ "button",
11017
+ {
11018
+ type: "button",
11019
+ "data-ohw-floating-panel-close": "",
11020
+ "aria-label": "Close",
11021
+ className: "absolute right-2.5 top-2.5 rounded-sm p-1.5 text-foreground hover:bg-muted/50",
11022
+ onClick: (e) => {
11023
+ e.stopPropagation();
11024
+ onClose();
11025
+ },
11026
+ onPointerDown: (e) => e.stopPropagation(),
11027
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.X, { size: 16, "aria-hidden": true })
11028
+ }
11029
+ )
11030
+ ]
11031
+ }
11032
+ ),
11033
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
11034
+ "div",
11035
+ {
11036
+ "data-ohw-floating-panel-body": "",
11037
+ className: cn("flex w-full flex-col gap-4 p-5", bodyClassName),
11038
+ children
11039
+ }
11040
+ )
11041
+ ]
11042
+ }
11043
+ );
11044
+ }
11045
+
11046
+ // src/ui/socials-display-panel.tsx
11047
+ var import_jsx_runtime27 = require("react/jsx-runtime");
11048
+ function DisplaySwitch({
11049
+ label,
11050
+ checked,
11051
+ disabled,
11052
+ onChange
11053
+ }) {
11054
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex w-full items-center gap-2", children: [
11055
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11056
+ "span",
11057
+ {
11058
+ className: cn(
11059
+ "min-w-0 flex-1 text-sm font-medium leading-5",
11060
+ disabled ? "text-muted-foreground" : "text-foreground"
11061
+ ),
11062
+ children: label
11063
+ }
11064
+ ),
11065
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11066
+ "button",
11067
+ {
11068
+ type: "button",
11069
+ role: "switch",
11070
+ "aria-checked": checked,
11071
+ "aria-label": label,
11072
+ disabled,
11073
+ onClick: () => onChange(!checked),
11074
+ className: cn(
11075
+ "relative h-5 w-9 shrink-0 rounded-full transition-colors",
11076
+ checked ? "bg-primary" : "bg-primary-50",
11077
+ disabled ? "cursor-default opacity-50" : "cursor-pointer"
11078
+ ),
11079
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11080
+ "span",
11081
+ {
11082
+ className: cn(
11083
+ "absolute top-0.5 h-4 w-4 rounded-full bg-white transition-all",
11084
+ checked ? "left-[1.125rem]" : "left-0.5"
11085
+ )
11086
+ }
11087
+ )
11088
+ }
11089
+ )
11090
+ ] });
11091
+ }
11092
+ function SocialsDisplayPanel({ display, onChange, className }) {
11093
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: cn("flex w-full flex-col gap-3", className), children: [
11094
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11095
+ DisplaySwitch,
11096
+ {
11097
+ label: "Text",
11098
+ checked: display.text,
11099
+ disabled: display.text && !display.icon,
11100
+ onChange: (text) => onChange({ ...display, text })
11101
+ }
11102
+ ),
11103
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
11104
+ DisplaySwitch,
11105
+ {
11106
+ label: "Icon",
11107
+ checked: display.icon,
11108
+ disabled: display.icon && !display.text,
11109
+ onChange: (icon) => onChange({ ...display, icon })
11110
+ }
11111
+ )
11112
+ ] });
11113
+ }
11114
+
10404
11115
  // src/lib/item-drag-interaction.ts
10405
11116
  function disableNativeHrefDrag(el) {
10406
11117
  if (el.draggable) el.draggable = false;
@@ -10599,7 +11310,7 @@ function hitTestNavDropSlot(clientX, clientY, draggedHrefKey) {
10599
11310
  }
10600
11311
 
10601
11312
  // src/useNavItemDrag.ts
10602
- var import_react13 = require("react");
11313
+ var import_react14 = require("react");
10603
11314
  function useNavItemDrag({
10604
11315
  isEditMode,
10605
11316
  editContentRef,
@@ -10623,11 +11334,11 @@ function useNavItemDrag({
10623
11334
  getNavigationItemAnchor: getNavigationItemAnchor2,
10624
11335
  isDragHandleDisabled: isDragHandleDisabled2
10625
11336
  }) {
10626
- const navDragRef = (0, import_react13.useRef)(null);
10627
- const [navDropSlots, setNavDropSlots] = (0, import_react13.useState)([]);
10628
- const [activeNavDropIndex, setActiveNavDropIndex] = (0, import_react13.useState)(null);
10629
- const navPointerDragRef = (0, import_react13.useRef)(null);
10630
- const clearNavDragVisuals = (0, import_react13.useCallback)(() => {
11337
+ const navDragRef = (0, import_react14.useRef)(null);
11338
+ const [navDropSlots, setNavDropSlots] = (0, import_react14.useState)([]);
11339
+ const [activeNavDropIndex, setActiveNavDropIndex] = (0, import_react14.useState)(null);
11340
+ const navPointerDragRef = (0, import_react14.useRef)(null);
11341
+ const clearNavDragVisuals = (0, import_react14.useCallback)(() => {
10631
11342
  const session = navDragRef.current;
10632
11343
  const keepOpenEl = session?.draggedEl?.closest("[data-ohw-nav-children]") != null ? session.draggedEl : null;
10633
11344
  navDragRef.current = null;
@@ -10644,7 +11355,7 @@ function useNavItemDrag({
10644
11355
  document.documentElement.removeAttribute("data-ohw-nav-dragging-root");
10645
11356
  unlockItemDragInteraction();
10646
11357
  }, [setDraggedItemRect, setIsItemDragging, setSiblingHintRects]);
10647
- const refreshNavDragVisuals = (0, import_react13.useCallback)(
11358
+ const refreshNavDragVisuals = (0, import_react14.useCallback)(
10648
11359
  (session, activeSlot, clientX, clientY) => {
10649
11360
  setDraggedItemRect(session.draggedEl.getBoundingClientRect());
10650
11361
  if (typeof clientX === "number" && typeof clientY === "number") {
@@ -10662,13 +11373,13 @@ function useNavItemDrag({
10662
11373
  },
10663
11374
  [setDraggedItemRect, setSiblingHintRects]
10664
11375
  );
10665
- const refreshNavDragVisualsRef = (0, import_react13.useRef)(refreshNavDragVisuals);
11376
+ const refreshNavDragVisualsRef = (0, import_react14.useRef)(refreshNavDragVisuals);
10666
11377
  refreshNavDragVisualsRef.current = refreshNavDragVisuals;
10667
- const commitNavDragRef = (0, import_react13.useRef)(() => {
11378
+ const commitNavDragRef = (0, import_react14.useRef)(() => {
10668
11379
  });
10669
- const beginNavDragRef = (0, import_react13.useRef)(() => {
11380
+ const beginNavDragRef = (0, import_react14.useRef)(() => {
10670
11381
  });
10671
- const beginNavDrag = (0, import_react13.useCallback)(
11382
+ const beginNavDrag = (0, import_react14.useCallback)(
10672
11383
  (session) => {
10673
11384
  const rect = session.draggedEl.getBoundingClientRect();
10674
11385
  session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
@@ -10702,7 +11413,7 @@ function useNavItemDrag({
10702
11413
  ]
10703
11414
  );
10704
11415
  beginNavDragRef.current = beginNavDrag;
10705
- const commitNavDrag = (0, import_react13.useCallback)(
11416
+ const commitNavDrag = (0, import_react14.useCallback)(
10706
11417
  (clientX, clientY) => {
10707
11418
  const session = navDragRef.current;
10708
11419
  if (!session) {
@@ -10763,7 +11474,7 @@ function useNavItemDrag({
10763
11474
  [clearNavDragVisuals, deselectRef, editContentRef, postToParentRef, selectRef]
10764
11475
  );
10765
11476
  commitNavDragRef.current = commitNavDrag;
10766
- const startNavLinkDrag = (0, import_react13.useCallback)(
11477
+ const startNavLinkDrag = (0, import_react14.useCallback)(
10767
11478
  (anchor, clientX, clientY, wasSelected) => {
10768
11479
  if (footerDragRef.current) return false;
10769
11480
  const hrefKey = anchor.getAttribute("data-ohw-href-key");
@@ -10781,7 +11492,7 @@ function useNavItemDrag({
10781
11492
  },
10782
11493
  [beginNavDrag, footerDragRef, isDragHandleDisabled2, isCtaButton]
10783
11494
  );
10784
- const onNavDragOver = (0, import_react13.useCallback)(
11495
+ const onNavDragOver = (0, import_react14.useCallback)(
10785
11496
  (e) => {
10786
11497
  const session = navDragRef.current;
10787
11498
  if (!session) return false;
@@ -10793,7 +11504,7 @@ function useNavItemDrag({
10793
11504
  },
10794
11505
  []
10795
11506
  );
10796
- (0, import_react13.useEffect)(() => {
11507
+ (0, import_react14.useEffect)(() => {
10797
11508
  if (!isEditMode) return;
10798
11509
  const THRESHOLD = 10;
10799
11510
  const resolveWasSelected = (el) => {
@@ -10918,7 +11629,7 @@ function useNavItemDrag({
10918
11629
  setLinkPopover,
10919
11630
  suppressNextClickRef
10920
11631
  ]);
10921
- const armNavPressFromChrome = (0, import_react13.useCallback)(
11632
+ const armNavPressFromChrome = (0, import_react14.useCallback)(
10922
11633
  (selected, clientX, clientY, pointerId) => {
10923
11634
  const hrefKey = selected.getAttribute("data-ohw-href-key");
10924
11635
  if (!hrefKey || !isNavbarHrefKey(hrefKey)) return false;
@@ -10949,8 +11660,8 @@ function useNavItemDrag({
10949
11660
  }
10950
11661
 
10951
11662
  // src/ui/footer-container-chrome.tsx
10952
- var import_lucide_react13 = require("lucide-react");
10953
- var import_jsx_runtime26 = require("react/jsx-runtime");
11663
+ var import_lucide_react14 = require("lucide-react");
11664
+ var import_jsx_runtime28 = require("react/jsx-runtime");
10954
11665
  function FooterContainerChrome({
10955
11666
  rect,
10956
11667
  onAdd,
@@ -10958,7 +11669,7 @@ function FooterContainerChrome({
10958
11669
  }) {
10959
11670
  const chromeGap = 6;
10960
11671
  const buttonMargin = 7;
10961
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
11672
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
10962
11673
  "div",
10963
11674
  {
10964
11675
  "data-ohw-footer-container-chrome": "",
@@ -10970,8 +11681,8 @@ function FooterContainerChrome({
10970
11681
  width: rect.width + chromeGap * 2,
10971
11682
  height: rect.height + chromeGap * 2
10972
11683
  },
10973
- children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Tooltip, { children: [
10974
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
11684
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(Tooltip, { children: [
11685
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
10975
11686
  "button",
10976
11687
  {
10977
11688
  type: "button",
@@ -10990,17 +11701,17 @@ function FooterContainerChrome({
10990
11701
  if (addDisabled) return;
10991
11702
  onAdd();
10992
11703
  },
10993
- children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
11704
+ children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react14.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
10994
11705
  }
10995
11706
  ) }),
10996
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
11707
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
10997
11708
  ] })
10998
11709
  }
10999
11710
  ) });
11000
11711
  }
11001
11712
 
11002
11713
  // src/lib/carousel.ts
11003
- var import_react14 = require("react");
11714
+ var import_react15 = require("react");
11004
11715
  var CAROUSEL_ATTR = "data-ohw-carousel";
11005
11716
  var CAROUSEL_VALUE_ATTR = "data-ohw-carousel-value";
11006
11717
  var CAROUSEL_SLIDE_ATTR = "data-ohw-carousel-slide";
@@ -11062,8 +11773,8 @@ function applyCarouselNode(key, val) {
11062
11773
  return true;
11063
11774
  }
11064
11775
  function useOhwCarousel(key, initial) {
11065
- const [images, setImages] = (0, import_react14.useState)(initial);
11066
- (0, import_react14.useEffect)(() => {
11776
+ const [images, setImages] = (0, import_react15.useState)(initial);
11777
+ (0, import_react15.useEffect)(() => {
11067
11778
  const el = document.querySelector(
11068
11779
  `[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`
11069
11780
  );
@@ -11278,7 +11989,7 @@ function isNavbarLinksContainer(el) {
11278
11989
  function isNavigationItem(el) {
11279
11990
  const anchor = el.matches("[data-ohw-href-key]") ? el : el.closest("[data-ohw-href-key]");
11280
11991
  if (!anchor) return false;
11281
- return Boolean(anchor.querySelector('[data-ohw-editable="text"]'));
11992
+ return Boolean(anchor.querySelector('[data-ohw-editable="text"]')) || Boolean(getSocialItem(anchor));
11282
11993
  }
11283
11994
  function findFooterItemGroup(item) {
11284
11995
  const explicit = item.closest("[data-ohw-footer-col], [data-ohw-footer-column]");
@@ -11299,8 +12010,9 @@ function isInferredFooterGroup(el) {
11299
12010
  const footer = el.closest("footer");
11300
12011
  if (!footer || el === footer) return false;
11301
12012
  if (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column")) return true;
12013
+ if (isSocialsRow(el)) return false;
11302
12014
  const count = Array.from(el.querySelectorAll("[data-ohw-href-key]")).filter(
11303
- isNavigationItem
12015
+ (item) => isNavigationItem(item) && !getSocialItem(item)
11304
12016
  ).length;
11305
12017
  return count >= 2;
11306
12018
  }
@@ -11344,7 +12056,8 @@ function deleteSelectedNavFooterItem(deps) {
11344
12056
  if (key.endsWith("-href")) applyLinkByKey2(key, text);
11345
12057
  else {
11346
12058
  document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`).forEach((el) => {
11347
- el.textContent = text;
12059
+ if (el.getAttribute("data-ohw-editable") === "icon") applyIconMarkup(el, text);
12060
+ else el.textContent = text;
11348
12061
  });
11349
12062
  }
11350
12063
  }
@@ -11406,6 +12119,21 @@ function deleteSelectedNavFooterItem(deps) {
11406
12119
  });
11407
12120
  return true;
11408
12121
  }
12122
+ const social = getSocialItem(selected);
12123
+ if (social) {
12124
+ const result = removeSocialItem(social, getEditContent());
12125
+ if (!result) return false;
12126
+ finishDelete({
12127
+ toastTitle: "Social deleted",
12128
+ removedKeys: result.removedKeys,
12129
+ previousContent: result.previousContent,
12130
+ orderKey: SOCIALS_ORDER_KEY,
12131
+ orderJson: JSON.stringify(result.order),
12132
+ previousOrderJson: JSON.stringify(result.previousOrder),
12133
+ undoDom: result.undo
12134
+ });
12135
+ return true;
12136
+ }
11409
12137
  if (isFooterHrefKey(hrefKey)) {
11410
12138
  const result = deleteFooterItem(selected);
11411
12139
  if (!result) return false;
@@ -11424,14 +12152,14 @@ function deleteSelectedNavFooterItem(deps) {
11424
12152
  }
11425
12153
 
11426
12154
  // src/ui/navbar-container-chrome.tsx
11427
- var import_lucide_react14 = require("lucide-react");
11428
- var import_jsx_runtime27 = require("react/jsx-runtime");
12155
+ var import_lucide_react15 = require("lucide-react");
12156
+ var import_jsx_runtime29 = require("react/jsx-runtime");
11429
12157
  function NavbarContainerChrome({
11430
12158
  rect,
11431
12159
  onAdd
11432
12160
  }) {
11433
12161
  const chromeGap = 6;
11434
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
12162
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
11435
12163
  "div",
11436
12164
  {
11437
12165
  "data-ohw-navbar-container-chrome": "",
@@ -11443,7 +12171,7 @@ function NavbarContainerChrome({
11443
12171
  width: rect.width + chromeGap * 2,
11444
12172
  height: rect.height + chromeGap * 2
11445
12173
  },
11446
- children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
12174
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
11447
12175
  "button",
11448
12176
  {
11449
12177
  type: "button",
@@ -11460,7 +12188,7 @@ function NavbarContainerChrome({
11460
12188
  e.stopPropagation();
11461
12189
  onAdd();
11462
12190
  },
11463
- children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react14.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
12191
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react15.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
11464
12192
  }
11465
12193
  )
11466
12194
  }
@@ -11469,7 +12197,7 @@ function NavbarContainerChrome({
11469
12197
 
11470
12198
  // src/ui/drop-indicator.tsx
11471
12199
  var React10 = __toESM(require("react"), 1);
11472
- var import_jsx_runtime28 = require("react/jsx-runtime");
12200
+ var import_jsx_runtime30 = require("react/jsx-runtime");
11473
12201
  var dropIndicatorVariants = cva(
11474
12202
  "ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
11475
12203
  {
@@ -11493,7 +12221,7 @@ var dropIndicatorVariants = cva(
11493
12221
  );
11494
12222
  var DropIndicator = React10.forwardRef(
11495
12223
  ({ className, direction, state, ...props }, ref) => {
11496
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
12224
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
11497
12225
  "div",
11498
12226
  {
11499
12227
  ref,
@@ -11510,7 +12238,7 @@ var DropIndicator = React10.forwardRef(
11510
12238
  DropIndicator.displayName = "DropIndicator";
11511
12239
 
11512
12240
  // src/ui/badge.tsx
11513
- var import_jsx_runtime29 = require("react/jsx-runtime");
12241
+ var import_jsx_runtime31 = require("react/jsx-runtime");
11514
12242
  var badgeVariants = cva(
11515
12243
  "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
11516
12244
  {
@@ -11528,12 +12256,12 @@ var badgeVariants = cva(
11528
12256
  }
11529
12257
  );
11530
12258
  function Badge({ className, variant, ...props }) {
11531
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
12259
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
11532
12260
  }
11533
12261
 
11534
12262
  // src/OhhwellsBridge.tsx
11535
- var import_lucide_react15 = require("lucide-react");
11536
- var import_jsx_runtime30 = require("react/jsx-runtime");
12263
+ var import_lucide_react16 = require("lucide-react");
12264
+ var import_jsx_runtime32 = require("react/jsx-runtime");
11537
12265
  var PRIMARY3 = "#0885FE";
11538
12266
  var IMAGE_FADE_MS = 300;
11539
12267
  function runOpacityFade(el, onDone) {
@@ -11712,7 +12440,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
11712
12440
  const root = (0, import_client2.createRoot)(container);
11713
12441
  (0, import_react_dom3.flushSync)(() => {
11714
12442
  root.render(
11715
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
12443
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
11716
12444
  SchedulingWidget,
11717
12445
  {
11718
12446
  notifyOnConnect,
@@ -11760,6 +12488,17 @@ function applyLinkHref(el, val) {
11760
12488
  const anchor = el instanceof HTMLAnchorElement ? el : el.querySelector("a");
11761
12489
  if (anchor) anchor.setAttribute("href", val);
11762
12490
  }
12491
+ function currentIconRef(el) {
12492
+ const uploaded = el instanceof HTMLImageElement ? el : el.querySelector("img");
12493
+ if (uploaded?.getAttribute("src")) {
12494
+ return uploaded.getAttribute("src") ?? "";
12495
+ }
12496
+ const svg = el instanceof SVGElement ? el : el.querySelector("svg");
12497
+ const named = Array.from(svg?.classList ?? []).find(
12498
+ (c) => c.startsWith("lucide-") && c !== "lucide-icon"
12499
+ );
12500
+ return named ? `lucide:${named.slice("lucide-".length)}` : "";
12501
+ }
11763
12502
  function getEditMeasureEl(editable) {
11764
12503
  return editable.closest("[data-ohw-href-key]") ?? editable;
11765
12504
  }
@@ -11804,8 +12543,11 @@ function isMediaEditable(el) {
11804
12543
  const t = el.dataset.ohwEditable;
11805
12544
  return t === "image" || t === "bg-image" || t === "video";
11806
12545
  }
12546
+ function isIconEditable(el) {
12547
+ return el.dataset.ohwEditable === "icon";
12548
+ }
11807
12549
  var MEDIA_SELECTOR = '[data-ohw-editable="image"], [data-ohw-editable="bg-image"], [data-ohw-editable="video"]';
11808
- var NON_MEDIA_SELECTOR = '[data-ohw-editable]:not([data-ohw-editable="image"]):not([data-ohw-editable="bg-image"]):not([data-ohw-editable="video"])';
12550
+ 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"])';
11809
12551
  function getVideoEl2(el) {
11810
12552
  return el instanceof HTMLVideoElement ? el : el.querySelector("video");
11811
12553
  }
@@ -11923,13 +12665,29 @@ function isNavItemPointerTarget(el) {
11923
12665
  function getNavigationItemAnchor(el) {
11924
12666
  const anchor = el.matches("[data-ohw-href-key]") ? el : el.closest("[data-ohw-href-key]");
11925
12667
  if (!anchor) return null;
11926
- if (!anchor.querySelector('[data-ohw-editable="text"]')) return null;
12668
+ if (!anchor.querySelector('[data-ohw-editable="text"]') && !getSocialItem(anchor)) return null;
11927
12669
  if (!isNavItemPointerTarget(anchor)) return null;
11928
12670
  return anchor;
11929
12671
  }
11930
12672
  function isNavigationItem2(el) {
11931
12673
  return getNavigationItemAnchor(el) !== null;
11932
12674
  }
12675
+ function requestSocialDialog(anchor, post, content) {
12676
+ const item = getSocialItem(anchor);
12677
+ if (!item) return false;
12678
+ const iconKey = item.querySelector('[data-ohw-editable="icon"]')?.dataset.ohwKey ?? "";
12679
+ post({
12680
+ type: "ow:social-pick",
12681
+ hrefKey: item.getAttribute("data-ohw-href-key") ?? "",
12682
+ iconKey,
12683
+ url: getLinkHref4(item),
12684
+ iconStyle: detectIconStyle(item),
12685
+ // What was chosen last time. Guessing from the address instead reads as "Website" for anything
12686
+ // unrecognised, and for an item with no address at all — so a deliberate choice looked lost.
12687
+ platformId: content[socialPlatformKey(iconKey)] ?? ""
12688
+ });
12689
+ return true;
12690
+ }
11933
12691
  function listNavigationItems() {
11934
12692
  return Array.from(
11935
12693
  document.querySelectorAll("nav [data-ohw-href-key], footer [data-ohw-href-key]")
@@ -11964,7 +12722,7 @@ function getNavigationRoot(el) {
11964
12722
  return el.closest("nav, footer, aside");
11965
12723
  }
11966
12724
  function countFooterNavItems(el) {
11967
- return Array.from(el.querySelectorAll("[data-ohw-href-key]")).filter(isNavigationItem2).length;
12725
+ return Array.from(el.querySelectorAll("[data-ohw-href-key]")).filter((item) => isNavigationItem2(item) && !getSocialItem(item)).length;
11968
12726
  }
11969
12727
  function findFooterItemGroup2(item) {
11970
12728
  const explicit = item.closest("[data-ohw-footer-col], [data-ohw-footer-column]");
@@ -11985,10 +12743,11 @@ function isInferredFooterGroup2(el) {
11985
12743
  const footer = el.closest("footer");
11986
12744
  if (!footer || el === footer) return false;
11987
12745
  if (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column")) return true;
12746
+ if (isSocialsRow(el)) return false;
11988
12747
  return countFooterNavItems(el) >= 2;
11989
12748
  }
11990
12749
  function isNavigationContainer(el) {
11991
- 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);
12750
+ 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);
11992
12751
  }
11993
12752
  function isNavbarLinksContainer2(el) {
11994
12753
  return el.hasAttribute("data-ohw-nav-container");
@@ -12071,6 +12830,8 @@ function resolveNavContainerSelectionTarget(target, clientX, clientY) {
12071
12830
  return null;
12072
12831
  }
12073
12832
  function getNavigationSelectionParent(el) {
12833
+ const socialsRow = findSocialsRow(el);
12834
+ if (socialsRow) return socialsRow;
12074
12835
  if (isNavigationItem2(el)) {
12075
12836
  const childrenRoot = el.closest("[data-ohw-nav-children]");
12076
12837
  if (childrenRoot) {
@@ -12096,6 +12857,10 @@ function getNavigationSelectionParent(el) {
12096
12857
  }
12097
12858
  function collectNavigationItemSiblingHintRects(selected) {
12098
12859
  if (!isNavigationItem2(selected)) return [];
12860
+ const socialsRow = findSocialsRow(selected);
12861
+ if (socialsRow) {
12862
+ return listSocialItems(socialsRow).filter((item) => item !== selected).map((item) => item.getBoundingClientRect());
12863
+ }
12099
12864
  const footerColumn = getFooterColumn(selected);
12100
12865
  if (footerColumn) {
12101
12866
  return listFooterLinksInColumn(footerColumn).filter((link) => link !== selected).map((link) => link.getBoundingClientRect());
@@ -12328,7 +13093,7 @@ function EditGlowChrome({
12328
13093
  hideHandle = false
12329
13094
  }) {
12330
13095
  const GAP = SELECTION_CHROME_GAP2;
12331
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
13096
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
12332
13097
  "div",
12333
13098
  {
12334
13099
  ref: elRef,
@@ -12343,7 +13108,7 @@ function EditGlowChrome({
12343
13108
  zIndex: 2147483646
12344
13109
  },
12345
13110
  children: [
12346
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
13111
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
12347
13112
  "div",
12348
13113
  {
12349
13114
  style: {
@@ -12356,7 +13121,7 @@ function EditGlowChrome({
12356
13121
  }
12357
13122
  }
12358
13123
  ),
12359
- reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
13124
+ reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
12360
13125
  "div",
12361
13126
  {
12362
13127
  "data-ohw-drag-handle-container": "",
@@ -12368,7 +13133,7 @@ function EditGlowChrome({
12368
13133
  transform: "translate(calc(-100% - 7px), -50%)",
12369
13134
  pointerEvents: dragDisabled ? "none" : "auto"
12370
13135
  },
12371
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
13136
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
12372
13137
  DragHandle,
12373
13138
  {
12374
13139
  "aria-label": `Reorder ${reorderHrefKey}`,
@@ -12551,9 +13316,9 @@ function FloatingToolbar({
12551
13316
  showEditLink,
12552
13317
  onEditLink
12553
13318
  }) {
12554
- const localRef = import_react15.default.useRef(null);
12555
- const [measuredW, setMeasuredW] = import_react15.default.useState(330);
12556
- const setRefs = import_react15.default.useCallback(
13319
+ const localRef = import_react16.default.useRef(null);
13320
+ const [measuredW, setMeasuredW] = import_react16.default.useState(330);
13321
+ const setRefs = import_react16.default.useCallback(
12557
13322
  (node) => {
12558
13323
  localRef.current = node;
12559
13324
  if (typeof elRef === "function") elRef(node);
@@ -12565,7 +13330,7 @@ function FloatingToolbar({
12565
13330
  },
12566
13331
  [elRef]
12567
13332
  );
12568
- import_react15.default.useLayoutEffect(() => {
13333
+ import_react16.default.useLayoutEffect(() => {
12569
13334
  const node = localRef.current;
12570
13335
  if (!node) return;
12571
13336
  const update = () => {
@@ -12578,7 +13343,7 @@ function FloatingToolbar({
12578
13343
  return () => ro.disconnect();
12579
13344
  }, [showEditLink, activeCommands]);
12580
13345
  const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
12581
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
13346
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
12582
13347
  "div",
12583
13348
  {
12584
13349
  ref: setRefs,
@@ -12590,12 +13355,12 @@ function FloatingToolbar({
12590
13355
  zIndex: 2147483647,
12591
13356
  pointerEvents: "auto"
12592
13357
  },
12593
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(CustomToolbar, { children: [
12594
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_react15.default.Fragment, { children: [
12595
- gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(CustomToolbarDivider, {}),
13358
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(CustomToolbar, { children: [
13359
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_react16.default.Fragment, { children: [
13360
+ gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(CustomToolbarDivider, {}),
12596
13361
  btns.map((btn) => {
12597
13362
  const isActive = activeCommands.has(btn.cmd);
12598
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
13363
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
12599
13364
  CustomToolbarButton,
12600
13365
  {
12601
13366
  title: btn.title,
@@ -12604,7 +13369,7 @@ function FloatingToolbar({
12604
13369
  e.preventDefault();
12605
13370
  onCommand(btn.cmd);
12606
13371
  },
12607
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
13372
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
12608
13373
  "svg",
12609
13374
  {
12610
13375
  width: "16",
@@ -12625,7 +13390,7 @@ function FloatingToolbar({
12625
13390
  );
12626
13391
  })
12627
13392
  ] }, gi)),
12628
- showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
13393
+ showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
12629
13394
  CustomToolbarButton,
12630
13395
  {
12631
13396
  type: "button",
@@ -12639,7 +13404,7 @@ function FloatingToolbar({
12639
13404
  e.preventDefault();
12640
13405
  e.stopPropagation();
12641
13406
  },
12642
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react15.Link, { className: "size-4 shrink-0", "aria-hidden": true })
13407
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react16.Link, { className: "size-4 shrink-0", "aria-hidden": true })
12643
13408
  }
12644
13409
  ) : null
12645
13410
  ] })
@@ -12656,7 +13421,7 @@ function StateToggle({
12656
13421
  states,
12657
13422
  onStateChange
12658
13423
  }) {
12659
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
13424
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
12660
13425
  ToggleGroup,
12661
13426
  {
12662
13427
  "data-ohw-state-toggle": "",
@@ -12670,7 +13435,7 @@ function StateToggle({
12670
13435
  left: rect.right - 8,
12671
13436
  transform: "translateX(-100%)"
12672
13437
  },
12673
- children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
13438
+ children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
12674
13439
  }
12675
13440
  );
12676
13441
  }
@@ -12697,8 +13462,8 @@ function OhhwellsBridge() {
12697
13462
  const router = (0, import_navigation3.useRouter)();
12698
13463
  const searchParams = (0, import_navigation3.useSearchParams)();
12699
13464
  const isEditMode = isEditSessionActive();
12700
- const [bridgeRoot, setBridgeRoot] = (0, import_react15.useState)(null);
12701
- (0, import_react15.useEffect)(() => {
13465
+ const [bridgeRoot, setBridgeRoot] = (0, import_react16.useState)(null);
13466
+ (0, import_react16.useEffect)(() => {
12702
13467
  const figtreeFontId = "ohw-figtree-font";
12703
13468
  if (!document.getElementById(figtreeFontId)) {
12704
13469
  const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
@@ -12727,108 +13492,113 @@ function OhhwellsBridge() {
12727
13492
  const subdomain = resolveSubdomain(subdomainFromQuery);
12728
13493
  useLinkHrefGuardian(pathname, subdomain, isEditMode);
12729
13494
  useSavedLinkNavigation(isEditMode);
12730
- const postToParent2 = (0, import_react15.useCallback)((data) => {
13495
+ const postToParent2 = (0, import_react16.useCallback)((data) => {
12731
13496
  if (typeof window !== "undefined" && window.parent !== window) {
12732
13497
  window.parent.postMessage(data, "*");
12733
13498
  }
12734
13499
  }, []);
12735
- const [fetchState, setFetchState] = (0, import_react15.useState)("idle");
12736
- const autoSaveTimers = (0, import_react15.useRef)(/* @__PURE__ */ new Map());
12737
- const activeElRef = (0, import_react15.useRef)(null);
12738
- const pointerHeldRef = (0, import_react15.useRef)(false);
12739
- const selectedElRef = (0, import_react15.useRef)(null);
12740
- const selectedHrefKeyRef = (0, import_react15.useRef)(null);
12741
- const selectedFooterColAttrRef = (0, import_react15.useRef)(null);
12742
- const originalContentRef = (0, import_react15.useRef)(null);
12743
- const activeStateElRef = (0, import_react15.useRef)(null);
12744
- const parentScrollRef = (0, import_react15.useRef)(null);
12745
- const visibleViewportRef = (0, import_react15.useRef)(null);
12746
- const [dialogPortalContainer, setDialogPortalContainer] = (0, import_react15.useState)(null);
12747
- const attachVisibleViewport = (0, import_react15.useCallback)((node) => {
13500
+ const [fetchState, setFetchState] = (0, import_react16.useState)("idle");
13501
+ const autoSaveTimers = (0, import_react16.useRef)(/* @__PURE__ */ new Map());
13502
+ const activeElRef = (0, import_react16.useRef)(null);
13503
+ const pointerHeldRef = (0, import_react16.useRef)(false);
13504
+ const selectedElRef = (0, import_react16.useRef)(null);
13505
+ const selectedHrefKeyRef = (0, import_react16.useRef)(null);
13506
+ const selectedFooterColAttrRef = (0, import_react16.useRef)(null);
13507
+ const originalContentRef = (0, import_react16.useRef)(null);
13508
+ const activeStateElRef = (0, import_react16.useRef)(null);
13509
+ const parentScrollRef = (0, import_react16.useRef)(null);
13510
+ const visibleViewportRef = (0, import_react16.useRef)(null);
13511
+ const [dialogPortalContainer, setDialogPortalContainer] = (0, import_react16.useState)(null);
13512
+ const attachVisibleViewport = (0, import_react16.useCallback)((node) => {
12748
13513
  visibleViewportRef.current = node;
12749
13514
  setDialogPortalContainer(node);
12750
13515
  if (node) applyVisibleViewport(node, parentScrollRef.current);
12751
13516
  }, []);
12752
- const toolbarElRef = (0, import_react15.useRef)(null);
12753
- const glowElRef = (0, import_react15.useRef)(null);
12754
- const hoveredImageRef = (0, import_react15.useRef)(null);
12755
- const hoveredImageHasTextOverlapRef = (0, import_react15.useRef)(false);
12756
- const dragOverElRef = (0, import_react15.useRef)(null);
12757
- const [mediaHover, setMediaHover] = (0, import_react15.useState)(null);
12758
- const [carouselHover, setCarouselHover] = (0, import_react15.useState)(null);
12759
- const [uploadingRects, setUploadingRects] = (0, import_react15.useState)({});
12760
- const hoveredGapRef = (0, import_react15.useRef)(null);
12761
- const imageUnhoverTimerRef = (0, import_react15.useRef)(null);
12762
- const imageShowTimerRef = (0, import_react15.useRef)(null);
12763
- const editStylesRef = (0, import_react15.useRef)(null);
12764
- const activateRef = (0, import_react15.useRef)(() => {
13517
+ const toolbarElRef = (0, import_react16.useRef)(null);
13518
+ const glowElRef = (0, import_react16.useRef)(null);
13519
+ const hoveredImageRef = (0, import_react16.useRef)(null);
13520
+ const hoveredImageHasTextOverlapRef = (0, import_react16.useRef)(false);
13521
+ const dragOverElRef = (0, import_react16.useRef)(null);
13522
+ const [mediaHover, setMediaHover] = (0, import_react16.useState)(null);
13523
+ const [carouselHover, setCarouselHover] = (0, import_react16.useState)(null);
13524
+ const [uploadingRects, setUploadingRects] = (0, import_react16.useState)({});
13525
+ const hoveredGapRef = (0, import_react16.useRef)(null);
13526
+ const imageUnhoverTimerRef = (0, import_react16.useRef)(null);
13527
+ const imageShowTimerRef = (0, import_react16.useRef)(null);
13528
+ const editStylesRef = (0, import_react16.useRef)(null);
13529
+ const activateRef = (0, import_react16.useRef)(() => {
12765
13530
  });
12766
- const deactivateRef = (0, import_react15.useRef)(() => {
13531
+ const deactivateRef = (0, import_react16.useRef)(() => {
12767
13532
  });
12768
- const selectRef = (0, import_react15.useRef)(() => {
13533
+ const selectRef = (0, import_react16.useRef)(() => {
12769
13534
  });
12770
- const selectFrameRef = (0, import_react15.useRef)(() => {
13535
+ const selectFrameRef = (0, import_react16.useRef)(() => {
12771
13536
  });
12772
- const deselectRef = (0, import_react15.useRef)(() => {
13537
+ const deselectRef = (0, import_react16.useRef)(() => {
12773
13538
  });
12774
- const reselectNavigationItemRef = (0, import_react15.useRef)(() => {
13539
+ const reselectNavigationItemRef = (0, import_react16.useRef)(() => {
12775
13540
  });
12776
- const commitNavigationTextEditRef = (0, import_react15.useRef)(() => {
13541
+ const commitNavigationTextEditRef = (0, import_react16.useRef)(() => {
12777
13542
  });
12778
- const handleDeleteSelectedRef = (0, import_react15.useRef)(() => false);
12779
- const runPendingDeleteUndoRef = (0, import_react15.useRef)(() => false);
12780
- const isFooterFrameSelectionRef = (0, import_react15.useRef)(false);
12781
- const refreshActiveCommandsRef = (0, import_react15.useRef)(() => {
13543
+ const handleDeleteSelectedRef = (0, import_react16.useRef)(() => false);
13544
+ const runPendingDeleteUndoRef = (0, import_react16.useRef)(() => false);
13545
+ const isFooterFrameSelectionRef = (0, import_react16.useRef)(false);
13546
+ const refreshActiveCommandsRef = (0, import_react16.useRef)(() => {
12782
13547
  });
12783
- const postToParentRef = (0, import_react15.useRef)(postToParent2);
13548
+ const postToParentRef = (0, import_react16.useRef)(postToParent2);
12784
13549
  postToParentRef.current = postToParent2;
12785
- const aiSectionApiRef = (0, import_react15.useRef)(null);
12786
- const sectionsLoadedRef = (0, import_react15.useRef)(false);
12787
- const pendingScheduleConfigRequests = (0, import_react15.useRef)([]);
12788
- const [toolbarRect, setToolbarRect] = (0, import_react15.useState)(null);
12789
- const [toolbarVariant, setToolbarVariant] = (0, import_react15.useState)("none");
12790
- const toolbarVariantRef = (0, import_react15.useRef)("none");
13550
+ const aiSectionApiRef = (0, import_react16.useRef)(null);
13551
+ const sectionsLoadedRef = (0, import_react16.useRef)(false);
13552
+ const pendingScheduleConfigRequests = (0, import_react16.useRef)([]);
13553
+ const [toolbarRect, setToolbarRect] = (0, import_react16.useState)(null);
13554
+ const [toolbarVariant, setToolbarVariant] = (0, import_react16.useState)("none");
13555
+ const toolbarVariantRef = (0, import_react16.useRef)("none");
12791
13556
  toolbarVariantRef.current = toolbarVariant;
12792
- const [selectedIsCta, setSelectedIsCta] = (0, import_react15.useState)(false);
12793
- const [reorderHrefKey, setReorderHrefKey] = (0, import_react15.useState)(null);
12794
- const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react15.useState)(false);
12795
- const [toggleState, setToggleState] = (0, import_react15.useState)(null);
12796
- const [maxBadge, setMaxBadge] = (0, import_react15.useState)(null);
12797
- const [activeCommands, setActiveCommands] = (0, import_react15.useState)(/* @__PURE__ */ new Set());
12798
- const [sectionGap, setSectionGap] = (0, import_react15.useState)(null);
12799
- const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react15.useState)(false);
12800
- const hoveredNavContainerRef = (0, import_react15.useRef)(null);
12801
- const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0, import_react15.useState)(null);
12802
- const hoveredItemElRef = (0, import_react15.useRef)(null);
12803
- const [hoveredItemRect, setHoveredItemRect] = (0, import_react15.useState)(null);
12804
- const siblingHintElRef = (0, import_react15.useRef)(null);
12805
- const [siblingHintRect, setSiblingHintRect] = (0, import_react15.useState)(null);
12806
- const [siblingHintRects, setSiblingHintRects] = (0, import_react15.useState)([]);
12807
- const [isItemDragging, setIsItemDragging] = (0, import_react15.useState)(false);
12808
- const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react15.useState)(false);
13557
+ const [selectedIsCta, setSelectedIsCta] = (0, import_react16.useState)(false);
13558
+ const [selectedIsSocial, setSelectedIsSocial] = (0, import_react16.useState)(false);
13559
+ const [selectedIsSocialsRow, setSelectedIsSocialsRow] = (0, import_react16.useState)(false);
13560
+ const [reorderHrefKey, setReorderHrefKey] = (0, import_react16.useState)(null);
13561
+ const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react16.useState)(false);
13562
+ const [toggleState, setToggleState] = (0, import_react16.useState)(null);
13563
+ const [maxBadge, setMaxBadge] = (0, import_react16.useState)(null);
13564
+ const [activeCommands, setActiveCommands] = (0, import_react16.useState)(/* @__PURE__ */ new Set());
13565
+ const [sectionGap, setSectionGap] = (0, import_react16.useState)(null);
13566
+ const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react16.useState)(false);
13567
+ const hoveredNavContainerRef = (0, import_react16.useRef)(null);
13568
+ const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0, import_react16.useState)(null);
13569
+ const hoveredItemElRef = (0, import_react16.useRef)(null);
13570
+ const [hoveredItemRect, setHoveredItemRect] = (0, import_react16.useState)(null);
13571
+ const siblingHintElRef = (0, import_react16.useRef)(null);
13572
+ const [siblingHintRect, setSiblingHintRect] = (0, import_react16.useState)(null);
13573
+ const [siblingHintRects, setSiblingHintRects] = (0, import_react16.useState)([]);
13574
+ const [isItemDragging, setIsItemDragging] = (0, import_react16.useState)(false);
13575
+ const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react16.useState)(false);
12809
13576
  isFooterFrameSelectionRef.current = isFooterFrameSelection;
12810
- const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react15.useState)(null);
12811
- const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react15.useState)(null);
12812
- const footerDragRef = (0, import_react15.useRef)(null);
12813
- const [footerDropSlots, setFooterDropSlots] = (0, import_react15.useState)([]);
12814
- const [activeFooterDropIndex, setActiveFooterDropIndex] = (0, import_react15.useState)(null);
12815
- const [draggedItemRect, setDraggedItemRect] = (0, import_react15.useState)(null);
12816
- const footerPointerDragRef = (0, import_react15.useRef)(null);
12817
- const suppressNextClickRef = (0, import_react15.useRef)(false);
12818
- const suppressClickUntilRef = (0, import_react15.useRef)(0);
12819
- const [linkPopover, setLinkPopover] = (0, import_react15.useState)(null);
12820
- const linkPopoverSessionRef = (0, import_react15.useRef)(null);
12821
- const addNavAfterAnchorRef = (0, import_react15.useRef)(null);
12822
- const editContentRef = (0, import_react15.useRef)({});
12823
- const aiSectionsRef = (0, import_react15.useRef)("");
12824
- const pendingDeleteUndoRef = (0, import_react15.useRef)(null);
12825
- const [sitePages, setSitePages] = (0, import_react15.useState)([]);
12826
- const [sectionsByPath, setSectionsByPath] = (0, import_react15.useState)({});
12827
- const sectionsPrefetchGenRef = (0, import_react15.useRef)(0);
12828
- const setLinkPopoverRef = (0, import_react15.useRef)(setLinkPopover);
12829
- const linkPopoverPanelRef = (0, import_react15.useRef)(null);
12830
- const linkPopoverOpenRef = (0, import_react15.useRef)(false);
12831
- const linkPopoverGraceUntilRef = (0, import_react15.useRef)(0);
13577
+ const [floatingPanel, setFloatingPanel] = (0, import_react16.useState)(null);
13578
+ const [floatingPanelPos, setFloatingPanelPos] = (0, import_react16.useState)(null);
13579
+ const [parentScrollSnap, setParentScrollSnap] = (0, import_react16.useState)(null);
13580
+ const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react16.useState)(null);
13581
+ const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react16.useState)(null);
13582
+ const footerDragRef = (0, import_react16.useRef)(null);
13583
+ const [footerDropSlots, setFooterDropSlots] = (0, import_react16.useState)([]);
13584
+ const [activeFooterDropIndex, setActiveFooterDropIndex] = (0, import_react16.useState)(null);
13585
+ const [draggedItemRect, setDraggedItemRect] = (0, import_react16.useState)(null);
13586
+ const footerPointerDragRef = (0, import_react16.useRef)(null);
13587
+ const suppressNextClickRef = (0, import_react16.useRef)(false);
13588
+ const suppressClickUntilRef = (0, import_react16.useRef)(0);
13589
+ const [linkPopover, setLinkPopover] = (0, import_react16.useState)(null);
13590
+ const linkPopoverSessionRef = (0, import_react16.useRef)(null);
13591
+ const addNavAfterAnchorRef = (0, import_react16.useRef)(null);
13592
+ const editContentRef = (0, import_react16.useRef)({});
13593
+ const aiSectionsRef = (0, import_react16.useRef)("");
13594
+ const pendingDeleteUndoRef = (0, import_react16.useRef)(null);
13595
+ const [sitePages, setSitePages] = (0, import_react16.useState)([]);
13596
+ const [sectionsByPath, setSectionsByPath] = (0, import_react16.useState)({});
13597
+ const sectionsPrefetchGenRef = (0, import_react16.useRef)(0);
13598
+ const setLinkPopoverRef = (0, import_react16.useRef)(setLinkPopover);
13599
+ const linkPopoverPanelRef = (0, import_react16.useRef)(null);
13600
+ const linkPopoverOpenRef = (0, import_react16.useRef)(false);
13601
+ const linkPopoverGraceUntilRef = (0, import_react16.useRef)(0);
12832
13602
  setLinkPopoverRef.current = setLinkPopover;
12833
13603
  linkPopoverSessionRef.current = linkPopover;
12834
13604
  const {
@@ -12866,7 +13636,7 @@ function OhhwellsBridge() {
12866
13636
  const bumpLinkPopoverGrace = () => {
12867
13637
  linkPopoverGraceUntilRef.current = Date.now() + 350;
12868
13638
  };
12869
- const runSectionsPrefetch = (0, import_react15.useCallback)((pages) => {
13639
+ const runSectionsPrefetch = (0, import_react16.useCallback)((pages) => {
12870
13640
  if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
12871
13641
  const gen = ++sectionsPrefetchGenRef.current;
12872
13642
  const paths = pages.map((p) => p.path);
@@ -12885,9 +13655,9 @@ function OhhwellsBridge() {
12885
13655
  );
12886
13656
  });
12887
13657
  }, [isEditMode, pathname]);
12888
- const runSectionsPrefetchRef = (0, import_react15.useRef)(runSectionsPrefetch);
13658
+ const runSectionsPrefetchRef = (0, import_react16.useRef)(runSectionsPrefetch);
12889
13659
  runSectionsPrefetchRef.current = runSectionsPrefetch;
12890
- (0, import_react15.useEffect)(() => {
13660
+ (0, import_react16.useEffect)(() => {
12891
13661
  if (!linkPopover) {
12892
13662
  document.documentElement.removeAttribute("data-ohw-link-popover-open");
12893
13663
  return;
@@ -12915,7 +13685,7 @@ function OhhwellsBridge() {
12915
13685
  document.documentElement.removeAttribute("data-ohw-link-popover-open");
12916
13686
  };
12917
13687
  }, [linkPopover, postToParent2]);
12918
- (0, import_react15.useEffect)(() => {
13688
+ (0, import_react16.useEffect)(() => {
12919
13689
  if (!isEditMode) return;
12920
13690
  const useFixtures = shouldUseDevFixtures();
12921
13691
  if (useFixtures) {
@@ -12939,14 +13709,14 @@ function OhhwellsBridge() {
12939
13709
  if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
12940
13710
  return () => window.removeEventListener("message", onSitePages);
12941
13711
  }, [isEditMode, postToParent2]);
12942
- (0, import_react15.useEffect)(() => {
13712
+ (0, import_react16.useEffect)(() => {
12943
13713
  if (!isEditMode || shouldUseDevFixtures()) return;
12944
13714
  void loadAllSectionsManifest().then((manifest) => {
12945
13715
  if (Object.keys(manifest).length === 0) return;
12946
13716
  setSectionsByPath((prev) => ({ ...manifest, ...prev }));
12947
13717
  });
12948
13718
  }, [isEditMode]);
12949
- (0, import_react15.useEffect)(() => {
13719
+ (0, import_react16.useEffect)(() => {
12950
13720
  const update = () => {
12951
13721
  const el = activeElRef.current ?? selectedElRef.current;
12952
13722
  if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
@@ -12970,10 +13740,10 @@ function OhhwellsBridge() {
12970
13740
  vvp.removeEventListener("resize", update);
12971
13741
  };
12972
13742
  }, []);
12973
- const refreshStateRules = (0, import_react15.useCallback)(() => {
13743
+ const refreshStateRules = (0, import_react16.useCallback)(() => {
12974
13744
  editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
12975
13745
  }, []);
12976
- const processConfigRequest = (0, import_react15.useCallback)((insertAfterVal) => {
13746
+ const processConfigRequest = (0, import_react16.useCallback)((insertAfterVal) => {
12977
13747
  const tracker = getSectionsTracker();
12978
13748
  let entries = [];
12979
13749
  try {
@@ -12996,7 +13766,7 @@ function OhhwellsBridge() {
12996
13766
  }
12997
13767
  window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
12998
13768
  }, [isEditMode]);
12999
- const deactivate = (0, import_react15.useCallback)(() => {
13769
+ const deactivate = (0, import_react16.useCallback)(() => {
13000
13770
  const el = activeElRef.current;
13001
13771
  if (!el) return;
13002
13772
  const key = el.dataset.ohwKey;
@@ -13029,17 +13799,19 @@ function OhhwellsBridge() {
13029
13799
  setToolbarShowEditLink(false);
13030
13800
  postToParent2({ type: "ow:exit-edit" });
13031
13801
  }, [postToParent2]);
13032
- const clearSelectedAttr = (0, import_react15.useCallback)(() => {
13802
+ const clearSelectedAttr = (0, import_react16.useCallback)(() => {
13033
13803
  document.querySelectorAll("[data-ohw-selected]").forEach((el) => {
13034
13804
  el.removeAttribute("data-ohw-selected");
13035
13805
  });
13036
13806
  }, []);
13037
- const deselect = (0, import_react15.useCallback)(() => {
13807
+ const deselect = (0, import_react16.useCallback)(() => {
13038
13808
  clearSelectedAttr();
13039
13809
  selectedElRef.current = null;
13040
13810
  selectedHrefKeyRef.current = null;
13041
13811
  selectedFooterColAttrRef.current = null;
13042
13812
  setSelectedIsCta(false);
13813
+ setSelectedIsSocial(false);
13814
+ setSelectedIsSocialsRow(false);
13043
13815
  setReorderHrefKey(null);
13044
13816
  setReorderDragDisabled(false);
13045
13817
  setIsFooterFrameSelection(false);
@@ -13057,11 +13829,11 @@ function OhhwellsBridge() {
13057
13829
  setToolbarVariant("none");
13058
13830
  }
13059
13831
  }, [clearSelectedAttr]);
13060
- const markSelected = (0, import_react15.useCallback)((el) => {
13832
+ const markSelected = (0, import_react16.useCallback)((el) => {
13061
13833
  clearSelectedAttr();
13062
13834
  el.setAttribute("data-ohw-selected", "");
13063
13835
  }, [clearSelectedAttr]);
13064
- const resolveHrefKeyElement = (0, import_react15.useCallback)((hrefKey) => {
13836
+ const resolveHrefKeyElement = (0, import_react16.useCallback)((hrefKey) => {
13065
13837
  if (isFooterHrefKey(hrefKey)) {
13066
13838
  return document.querySelector(
13067
13839
  `footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
@@ -13076,7 +13848,7 @@ function OhhwellsBridge() {
13076
13848
  `[data-ohw-href-key="${CSS.escape(hrefKey)}"]`
13077
13849
  );
13078
13850
  }, []);
13079
- const resyncSelectedNavigationItem = (0, import_react15.useCallback)(() => {
13851
+ const resyncSelectedNavigationItem = (0, import_react16.useCallback)(() => {
13080
13852
  const hrefKey = selectedHrefKeyRef.current;
13081
13853
  if (hrefKey) {
13082
13854
  const link = resolveHrefKeyElement(hrefKey);
@@ -13114,12 +13886,14 @@ function OhhwellsBridge() {
13114
13886
  );
13115
13887
  }
13116
13888
  }, [resolveHrefKeyElement]);
13117
- const reselectNavigationItem = (0, import_react15.useCallback)((navAnchor) => {
13889
+ const reselectNavigationItem = (0, import_react16.useCallback)((navAnchor) => {
13118
13890
  selectedElRef.current = navAnchor;
13119
13891
  selectedHrefKeyRef.current = navAnchor.getAttribute("data-ohw-href-key");
13120
13892
  selectedFooterColAttrRef.current = null;
13121
13893
  markSelected(navAnchor);
13122
13894
  setSelectedIsCta(isCtaButton(navAnchor));
13895
+ setSelectedIsSocial(Boolean(getSocialItem(navAnchor)));
13896
+ setSelectedIsSocialsRow(false);
13123
13897
  const isDropdownTrigger = !isNestedNavChild(navAnchor) && (navItemHasDropdownChildren(navAnchor) || navItemOwnsDropdownPanel(navAnchor));
13124
13898
  if (isNestedNavChild(navAnchor)) {
13125
13899
  setNavGroupForceOpen(navAnchor, true);
@@ -13143,7 +13917,7 @@ function OhhwellsBridge() {
13143
13917
  setToolbarShowEditLink(false);
13144
13918
  setActiveCommands(/* @__PURE__ */ new Set());
13145
13919
  }, [markSelected]);
13146
- const commitNavigationTextEdit = (0, import_react15.useCallback)((navAnchor) => {
13920
+ const commitNavigationTextEdit = (0, import_react16.useCallback)((navAnchor) => {
13147
13921
  const el = activeElRef.current;
13148
13922
  if (!el) return;
13149
13923
  const key = el.dataset.ohwKey;
@@ -13170,7 +13944,7 @@ function OhhwellsBridge() {
13170
13944
  postToParent2({ type: "ow:exit-edit" });
13171
13945
  reselectNavigationItem(navAnchor);
13172
13946
  }, [postToParent2, reselectNavigationItem]);
13173
- const handleAddTopLevelNavItem = (0, import_react15.useCallback)(() => {
13947
+ const handleAddTopLevelNavItem = (0, import_react16.useCallback)(() => {
13174
13948
  const items = listNavbarRootItems();
13175
13949
  addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
13176
13950
  deselectRef.current();
@@ -13182,7 +13956,7 @@ function OhhwellsBridge() {
13182
13956
  intent: "add-nav"
13183
13957
  });
13184
13958
  }, []);
13185
- const maybeWarnNavLinkDropdownConflict = (0, import_react15.useCallback)(
13959
+ const maybeWarnNavLinkDropdownConflict = (0, import_react16.useCallback)(
13186
13960
  (anchor) => {
13187
13961
  if (!isNavbarHrefKey(anchor.getAttribute("data-ohw-href-key"))) return;
13188
13962
  if (!navDropdownsOpenOnClick()) return;
@@ -13195,7 +13969,7 @@ function OhhwellsBridge() {
13195
13969
  },
13196
13970
  [postToParent2]
13197
13971
  );
13198
- const handleNavDropdownOpenChange = (0, import_react15.useCallback)((open) => {
13972
+ const handleNavDropdownOpenChange = (0, import_react16.useCallback)((open) => {
13199
13973
  const selected = selectedElRef.current;
13200
13974
  if (!selected || !isNavigationItem2(selected)) return;
13201
13975
  setNavGroupForceOpen(selected, open);
@@ -13207,7 +13981,7 @@ function OhhwellsBridge() {
13207
13981
  }
13208
13982
  });
13209
13983
  }, []);
13210
- const handleFooterHeadingVisibleChange = (0, import_react15.useCallback)(
13984
+ const handleFooterHeadingVisibleChange = (0, import_react16.useCallback)(
13211
13985
  (visible) => {
13212
13986
  const selected = selectedElRef.current;
13213
13987
  if (!selected || !isFooterFrameSelectionRef.current) return;
@@ -13231,7 +14005,7 @@ function OhhwellsBridge() {
13231
14005
  },
13232
14006
  [postToParent2]
13233
14007
  );
13234
- const enterEditOnNewItem = (0, import_react15.useCallback)((anchor) => {
14008
+ const enterEditOnNewItem = (0, import_react16.useCallback)((anchor) => {
13235
14009
  const label = anchor.querySelector('[data-ohw-editable="text"]');
13236
14010
  if (!label) {
13237
14011
  selectRef.current(anchor);
@@ -13240,9 +14014,31 @@ function OhhwellsBridge() {
13240
14014
  setNavGroupForceOpen(anchor, true);
13241
14015
  activateRef.current(label);
13242
14016
  }, []);
13243
- const handleAddChildItem = (0, import_react15.useCallback)(() => {
14017
+ const handleAddChildItem = (0, import_react16.useCallback)(() => {
13244
14018
  const selected = selectedElRef.current;
13245
14019
  if (!selected) return;
14020
+ const socialsRow = isSocialsRow(selected) ? selected : findSocialsRow(selected);
14021
+ if (socialsRow) {
14022
+ const after = getSocialItem(selected);
14023
+ const result2 = insertSocialItem(socialsRow, after, editContentRef.current);
14024
+ if (!result2) return;
14025
+ const orderJson = JSON.stringify(result2.order);
14026
+ applySocialsDisplayToRow(socialsRow, socialsDisplayFor(socialsRow, editContentRef.current));
14027
+ editContentRef.current = { ...editContentRef.current, [SOCIALS_ORDER_KEY]: orderJson };
14028
+ postToParent2({ type: "ow:change", nodes: [{ key: SOCIALS_ORDER_KEY, text: orderJson }] });
14029
+ postToParentRef.current({
14030
+ type: "ow:social-pick",
14031
+ hrefKey: result2.hrefKey,
14032
+ iconKey: result2.iconKey,
14033
+ url: "",
14034
+ iconStyle: detectIconStyle(result2.item),
14035
+ platformId: "",
14036
+ // Lets the editor undo the insert if the dialog is dismissed: an item that was never given
14037
+ // an address should not survive a Cancel.
14038
+ isNew: true
14039
+ });
14040
+ return;
14041
+ }
13246
14042
  if (toolbarVariantRef.current === "select-frame" && isFooterFrameSelection) {
13247
14043
  if (!selected.hasAttribute("data-ohw-footer-col") && !selected.closest("[data-ohw-footer-col]")) {
13248
14044
  }
@@ -13316,7 +14112,7 @@ function OhhwellsBridge() {
13316
14112
  enterEditOnNewItem(result.anchor);
13317
14113
  });
13318
14114
  }, [enterEditOnNewItem, isFooterFrameSelection, maybeWarnNavLinkDropdownConflict, postToParent2]);
13319
- const handleAddFooterColumn = (0, import_react15.useCallback)(() => {
14115
+ const handleAddFooterColumn = (0, import_react16.useCallback)(() => {
13320
14116
  if (!canAddFooterColumn()) {
13321
14117
  postToParent2({
13322
14118
  type: "ow:toast",
@@ -13337,7 +14133,7 @@ function OhhwellsBridge() {
13337
14133
  selectRef.current(result.firstLink);
13338
14134
  });
13339
14135
  }, [postToParent2]);
13340
- const clearFooterDragVisuals = (0, import_react15.useCallback)(() => {
14136
+ const clearFooterDragVisuals = (0, import_react16.useCallback)(() => {
13341
14137
  footerDragRef.current = null;
13342
14138
  setSiblingHintRects([]);
13343
14139
  setFooterDropSlots([]);
@@ -13346,7 +14142,7 @@ function OhhwellsBridge() {
13346
14142
  setIsItemDragging(false);
13347
14143
  unlockFooterDragInteraction();
13348
14144
  }, []);
13349
- const refreshFooterDragVisuals = (0, import_react15.useCallback)((session, activeSlot, clientX, clientY) => {
14145
+ const refreshFooterDragVisuals = (0, import_react16.useCallback)((session, activeSlot, clientX, clientY) => {
13350
14146
  const dragged = session.draggedEl;
13351
14147
  setDraggedItemRect(dragged.getBoundingClientRect());
13352
14148
  if (typeof clientX === "number" && typeof clientY === "number") {
@@ -13355,6 +14151,13 @@ function OhhwellsBridge() {
13355
14151
  }
13356
14152
  session.activeSlot = activeSlot;
13357
14153
  setSiblingHintRects([]);
14154
+ if (session.kind === "social") {
14155
+ const slots2 = session.hrefKey ? buildSocialDropSlotsForKey(session.hrefKey) : [];
14156
+ setFooterDropSlots(slots2);
14157
+ const activeIdx2 = activeSlot ? slots2.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
14158
+ setActiveFooterDropIndex(activeIdx2 >= 0 ? activeIdx2 : null);
14159
+ return;
14160
+ }
13358
14161
  if (session.kind === "link") {
13359
14162
  const columns = listFooterColumns();
13360
14163
  const slots2 = [];
@@ -13371,13 +14174,13 @@ function OhhwellsBridge() {
13371
14174
  const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
13372
14175
  setActiveFooterDropIndex(activeIdx >= 0 ? activeIdx : null);
13373
14176
  }, []);
13374
- const refreshFooterDragVisualsRef = (0, import_react15.useRef)(refreshFooterDragVisuals);
14177
+ const refreshFooterDragVisualsRef = (0, import_react16.useRef)(refreshFooterDragVisuals);
13375
14178
  refreshFooterDragVisualsRef.current = refreshFooterDragVisuals;
13376
- const commitFooterDragRef = (0, import_react15.useRef)(() => {
14179
+ const commitFooterDragRef = (0, import_react16.useRef)(() => {
13377
14180
  });
13378
- const beginFooterDragRef = (0, import_react15.useRef)(() => {
14181
+ const beginFooterDragRef = (0, import_react16.useRef)(() => {
13379
14182
  });
13380
- const beginFooterDrag = (0, import_react15.useCallback)(
14183
+ const beginFooterDrag = (0, import_react16.useCallback)(
13381
14184
  (session) => {
13382
14185
  const rect = session.draggedEl.getBoundingClientRect();
13383
14186
  session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
@@ -13391,13 +14194,13 @@ function OhhwellsBridge() {
13391
14194
  if (session.wasSelected && selectedElRef.current === session.draggedEl) {
13392
14195
  setToolbarRect(rect);
13393
14196
  }
13394
- const initialSlot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
14197
+ 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);
13395
14198
  refreshFooterDragVisuals(session, initialSlot, session.lastClientX, session.lastClientY);
13396
14199
  },
13397
14200
  [refreshFooterDragVisuals]
13398
14201
  );
13399
14202
  beginFooterDragRef.current = beginFooterDrag;
13400
- const commitFooterDrag = (0, import_react15.useCallback)(
14203
+ const commitFooterDrag = (0, import_react16.useCallback)(
13401
14204
  (clientX, clientY) => {
13402
14205
  const session = footerDragRef.current;
13403
14206
  if (!session) {
@@ -13407,8 +14210,11 @@ function OhhwellsBridge() {
13407
14210
  const x = typeof clientX === "number" && (clientX !== 0 || clientY !== 0) ? clientX : session.lastClientX;
13408
14211
  const y = typeof clientY === "number" && (clientX !== 0 || clientY !== 0) ? clientY : session.lastClientY;
13409
14212
  let nextOrder = null;
13410
- const slot = session.activeSlot ?? (session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(x, y, session.hrefKey) : session.kind === "column" ? hitTestColumnDropSlot(x, y) : null);
13411
- if (session.kind === "link" && session.hrefKey && slot) {
14213
+ let nextSocialsOrder = null;
14214
+ 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);
14215
+ if (session.kind === "social" && session.hrefKey && slot) {
14216
+ nextSocialsOrder = planSocialMove(session.hrefKey, slot.insertIndex);
14217
+ } else if (session.kind === "link" && session.hrefKey && slot) {
13412
14218
  nextOrder = planFooterLinkMove(session.hrefKey, slot.columnIndex, slot.insertIndex);
13413
14219
  } else if (session.kind === "column" && slot) {
13414
14220
  nextOrder = planFooterColumnMove(session.sourceColumnIndex, slot.insertIndex);
@@ -13466,6 +14272,27 @@ function OhhwellsBridge() {
13466
14272
  }
13467
14273
  deselectRef.current();
13468
14274
  };
14275
+ if (nextSocialsOrder) {
14276
+ const orderJson = JSON.stringify(nextSocialsOrder);
14277
+ editContentRef.current = { ...editContentRef.current, [SOCIALS_ORDER_KEY]: orderJson };
14278
+ applySocialsOrder(nextSocialsOrder);
14279
+ postToParentRef.current({
14280
+ type: "ow:change",
14281
+ nodes: [{ key: SOCIALS_ORDER_KEY, text: orderJson }]
14282
+ });
14283
+ applySelectionAfterDrop();
14284
+ clearFooterDragVisuals();
14285
+ const reapply = nextSocialsOrder;
14286
+ requestAnimationFrame(() => {
14287
+ if (editContentRef.current[SOCIALS_ORDER_KEY] === orderJson) applySocialsOrder(reapply);
14288
+ applySelectionAfterDrop();
14289
+ requestAnimationFrame(() => {
14290
+ if (editContentRef.current[SOCIALS_ORDER_KEY] === orderJson) applySocialsOrder(reapply);
14291
+ resyncSelectedNavigationItem();
14292
+ });
14293
+ });
14294
+ return;
14295
+ }
13469
14296
  if (nextOrder) {
13470
14297
  const orderJson = JSON.stringify(nextOrder);
13471
14298
  editContentRef.current = {
@@ -13501,10 +14328,25 @@ function OhhwellsBridge() {
13501
14328
  [clearFooterDragVisuals, resolveHrefKeyElement, resyncSelectedNavigationItem]
13502
14329
  );
13503
14330
  commitFooterDragRef.current = commitFooterDrag;
13504
- const startFooterLinkDrag = (0, import_react15.useCallback)(
14331
+ const startFooterLinkDrag = (0, import_react16.useCallback)(
13505
14332
  (anchor, clientX, clientY, wasSelected) => {
13506
14333
  const hrefKey = anchor.getAttribute("data-ohw-href-key");
13507
- if (!hrefKey || !isFooterHrefKey(hrefKey)) return false;
14334
+ if (!hrefKey) return false;
14335
+ if (getSocialItem(anchor)) {
14336
+ beginFooterDrag({
14337
+ kind: "social",
14338
+ hrefKey,
14339
+ columnEl: null,
14340
+ sourceColumnIndex: 0,
14341
+ wasSelected,
14342
+ draggedEl: anchor,
14343
+ lastClientX: clientX,
14344
+ lastClientY: clientY,
14345
+ activeSlot: null
14346
+ });
14347
+ return true;
14348
+ }
14349
+ if (!isFooterHrefKey(hrefKey)) return false;
13508
14350
  const column = findFooterColumnForLink(anchor);
13509
14351
  const columns = listFooterColumns();
13510
14352
  beginFooterDrag({
@@ -13522,7 +14364,7 @@ function OhhwellsBridge() {
13522
14364
  },
13523
14365
  [beginFooterDrag]
13524
14366
  );
13525
- const startFooterColumnDrag = (0, import_react15.useCallback)(
14367
+ const startFooterColumnDrag = (0, import_react16.useCallback)(
13526
14368
  (columnEl, clientX, clientY, wasSelected) => {
13527
14369
  const columns = listFooterColumns();
13528
14370
  const idx = columns.indexOf(columnEl);
@@ -13542,7 +14384,7 @@ function OhhwellsBridge() {
13542
14384
  },
13543
14385
  [beginFooterDrag]
13544
14386
  );
13545
- const handleItemDragStart = (0, import_react15.useCallback)(
14387
+ const handleItemDragStart = (0, import_react16.useCallback)(
13546
14388
  (e) => {
13547
14389
  const selected = selectedElRef.current;
13548
14390
  if (!selected) {
@@ -13562,7 +14404,7 @@ function OhhwellsBridge() {
13562
14404
  },
13563
14405
  [startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag]
13564
14406
  );
13565
- const handleItemDragEnd = (0, import_react15.useCallback)(
14407
+ const handleItemDragEnd = (0, import_react16.useCallback)(
13566
14408
  (e) => {
13567
14409
  if (footerDragRef.current) {
13568
14410
  const x = e?.clientX;
@@ -13588,7 +14430,7 @@ function OhhwellsBridge() {
13588
14430
  },
13589
14431
  [commitFooterDrag, commitNavDrag, navDragRef]
13590
14432
  );
13591
- const handleItemChromePointerDown = (0, import_react15.useCallback)((e) => {
14433
+ const handleItemChromePointerDown = (0, import_react16.useCallback)((e) => {
13592
14434
  if (e.button !== 0) return;
13593
14435
  const selected = selectedElRef.current;
13594
14436
  if (!selected) return;
@@ -13619,7 +14461,7 @@ function OhhwellsBridge() {
13619
14461
  }
13620
14462
  if (armNavPressFromChrome(selected, e.clientX, e.clientY, e.pointerId)) return;
13621
14463
  }, [armNavPressFromChrome]);
13622
- const handleItemChromeClick = (0, import_react15.useCallback)((clientX, clientY) => {
14464
+ const handleItemChromeClick = (0, import_react16.useCallback)((clientX, clientY) => {
13623
14465
  if (suppressNextClickRef.current || Date.now() < suppressClickUntilRef.current) {
13624
14466
  suppressNextClickRef.current = false;
13625
14467
  return;
@@ -13632,7 +14474,7 @@ function OhhwellsBridge() {
13632
14474
  }, []);
13633
14475
  reselectNavigationItemRef.current = reselectNavigationItem;
13634
14476
  commitNavigationTextEditRef.current = commitNavigationTextEdit;
13635
- const select = (0, import_react15.useCallback)((anchor) => {
14477
+ const select = (0, import_react16.useCallback)((anchor) => {
13636
14478
  if (!isNavigationItem2(anchor)) return;
13637
14479
  if (activeElRef.current) deactivate();
13638
14480
  aiSectionApiRef.current?.selectFromElement(anchor);
@@ -13641,6 +14483,8 @@ function OhhwellsBridge() {
13641
14483
  selectedFooterColAttrRef.current = null;
13642
14484
  markSelected(anchor);
13643
14485
  setSelectedIsCta(isCtaButton(anchor));
14486
+ setSelectedIsSocial(Boolean(getSocialItem(anchor)));
14487
+ setSelectedIsSocialsRow(false);
13644
14488
  clearHrefKeyHover(anchor);
13645
14489
  const isDropdownTrigger = !isNestedNavChild(anchor) && (navItemHasDropdownChildren(anchor) || navItemOwnsDropdownPanel(anchor));
13646
14490
  if (isNestedNavChild(anchor)) {
@@ -13671,7 +14515,7 @@ function OhhwellsBridge() {
13671
14515
  setToolbarShowEditLink(false);
13672
14516
  setActiveCommands(/* @__PURE__ */ new Set());
13673
14517
  }, [deactivate, markSelected]);
13674
- const selectFrame = (0, import_react15.useCallback)((el) => {
14518
+ const selectFrame = (0, import_react16.useCallback)((el) => {
13675
14519
  if (!isNavigationContainer(el)) return;
13676
14520
  if (activeElRef.current) deactivate();
13677
14521
  aiSectionApiRef.current?.selectFromElement(el);
@@ -13681,6 +14525,8 @@ function OhhwellsBridge() {
13681
14525
  selectedFooterColAttrRef.current = isFooterColumn ? el.getAttribute("data-ohw-footer-col") ?? String(listFooterColumns().indexOf(el)) : null;
13682
14526
  markSelected(el);
13683
14527
  setSelectedIsCta(false);
14528
+ setSelectedIsSocial(false);
14529
+ setSelectedIsSocialsRow(isSocialsRow(el));
13684
14530
  clearHrefKeyHover(el);
13685
14531
  setNavGroupForceOpen(null, false);
13686
14532
  hoveredNavContainerRef.current = null;
@@ -13718,13 +14564,57 @@ function OhhwellsBridge() {
13718
14564
  setToolbarShowEditLink(false);
13719
14565
  setActiveCommands(/* @__PURE__ */ new Set());
13720
14566
  }, [deactivate, markSelected, postToParent2]);
13721
- const activate = (0, import_react15.useCallback)((el, options) => {
14567
+ const openSocialsDisplayPanel = (0, import_react16.useCallback)((row) => {
14568
+ setParentScrollSnap(parentScrollRef.current);
14569
+ setFloatingPanel({
14570
+ key: "socials-display",
14571
+ title: "Style",
14572
+ context: "Socials \xB7 Footer",
14573
+ kind: "socials-display",
14574
+ row
14575
+ });
14576
+ }, []);
14577
+ const changeSocialsDisplay = (0, import_react16.useCallback)(
14578
+ (row, next) => {
14579
+ if (next.icon) {
14580
+ const missing = socialsMissingIcons(row);
14581
+ listSocialItems(row).forEach((item) => ensureIconSlot(item));
14582
+ if (missing.length) {
14583
+ postToParentRef.current({ type: "ow:social-icons-needed", items: missing });
14584
+ }
14585
+ }
14586
+ applySocialsDisplayToRow(row, next);
14587
+ requestAnimationFrame(() => {
14588
+ if (selectedElRef.current === row && row.isConnected) setToolbarRect(row.getBoundingClientRect());
14589
+ });
14590
+ const displayJson = JSON.stringify(socialsDisplayWith(row, next, editContentRef.current));
14591
+ editContentRef.current = { ...editContentRef.current, [SOCIALS_DISPLAY_KEY]: displayJson };
14592
+ postToParentRef.current({
14593
+ type: "ow:change",
14594
+ nodes: [{ key: SOCIALS_DISPLAY_KEY, text: displayJson }],
14595
+ flush: true
14596
+ });
14597
+ },
14598
+ []
14599
+ );
14600
+ const closeFloatingPanelOnly = (0, import_react16.useCallback)(() => {
14601
+ setFloatingPanel(null);
14602
+ }, []);
14603
+ const closeFloatingPanelAndDeselect = (0, import_react16.useCallback)(() => {
14604
+ setFloatingPanel(null);
14605
+ deselectRef.current();
14606
+ }, []);
14607
+ const activate = (0, import_react16.useCallback)((el, options) => {
13722
14608
  if (activeElRef.current === el) return;
14609
+ if (isIconEditable(el)) return;
14610
+ if (el.hasAttribute("data-ohw-social-label")) return;
13723
14611
  clearSelectedAttr();
13724
14612
  selectedElRef.current = null;
13725
14613
  selectedHrefKeyRef.current = null;
13726
14614
  selectedFooterColAttrRef.current = null;
13727
14615
  setSelectedIsCta(false);
14616
+ setSelectedIsSocial(false);
14617
+ setSelectedIsSocialsRow(false);
13728
14618
  deactivate();
13729
14619
  if (hoveredImageRef.current) {
13730
14620
  hoveredImageRef.current = null;
@@ -13795,7 +14685,7 @@ function OhhwellsBridge() {
13795
14685
  selectRef.current = select;
13796
14686
  selectFrameRef.current = selectFrame;
13797
14687
  deselectRef.current = deselect;
13798
- (0, import_react15.useLayoutEffect)(() => {
14688
+ (0, import_react16.useLayoutEffect)(() => {
13799
14689
  if (!subdomain || isEditMode) {
13800
14690
  setFetchState("done");
13801
14691
  return;
@@ -13835,6 +14725,8 @@ function OhhwellsBridge() {
13835
14725
  }
13836
14726
  } else if (el.dataset.ohwEditable === "link") {
13837
14727
  applyLinkHref(el, val);
14728
+ } else if (el.dataset.ohwEditable === "icon") {
14729
+ applyIconMarkup(el, val);
13838
14730
  } else if (el.innerHTML !== val) {
13839
14731
  el.innerHTML = val;
13840
14732
  }
@@ -13843,6 +14735,8 @@ function OhhwellsBridge() {
13843
14735
  }
13844
14736
  reconcileNavbarItemsFromContent(content);
13845
14737
  reconcileFooterOrderFromContent(content);
14738
+ reconcileSocialsFromContent(content);
14739
+ applySocialsDisplayFromContent(content);
13846
14740
  enforceLinkHrefs();
13847
14741
  initSectionsFromContent(content, true);
13848
14742
  sectionsLoadedRef.current = true;
@@ -13871,7 +14765,7 @@ function OhhwellsBridge() {
13871
14765
  cancelled = true;
13872
14766
  };
13873
14767
  }, [subdomain, isEditMode]);
13874
- (0, import_react15.useEffect)(() => {
14768
+ (0, import_react16.useEffect)(() => {
13875
14769
  if (!subdomain || isEditMode) return;
13876
14770
  let debounceTimer = null;
13877
14771
  let observer = null;
@@ -13905,6 +14799,8 @@ function OhhwellsBridge() {
13905
14799
  }
13906
14800
  reconcileNavbarItemsFromContent(content);
13907
14801
  reconcileFooterOrderFromContent(content);
14802
+ reconcileSocialsFromContent(content);
14803
+ applySocialsDisplayFromContent(content);
13908
14804
  } finally {
13909
14805
  observer?.observe(document.body, { childList: true, subtree: true });
13910
14806
  }
@@ -13922,16 +14818,16 @@ function OhhwellsBridge() {
13922
14818
  if (debounceTimer) clearTimeout(debounceTimer);
13923
14819
  };
13924
14820
  }, [subdomain, isEditMode, pathname]);
13925
- (0, import_react15.useLayoutEffect)(() => {
14821
+ (0, import_react16.useLayoutEffect)(() => {
13926
14822
  const el = document.getElementById("ohw-loader");
13927
14823
  if (!el) return;
13928
14824
  const visible = Boolean(subdomain) && fetchState !== "done";
13929
14825
  el.style.display = visible ? "flex" : "none";
13930
14826
  }, [subdomain, fetchState]);
13931
- (0, import_react15.useEffect)(() => {
14827
+ (0, import_react16.useEffect)(() => {
13932
14828
  postToParent2({ type: "ow:navigation", path: pathname });
13933
14829
  }, [pathname, postToParent2]);
13934
- (0, import_react15.useEffect)(() => {
14830
+ (0, import_react16.useEffect)(() => {
13935
14831
  if (!isEditMode) return;
13936
14832
  if (linkPopoverSessionRef.current?.intent === "add-nav") return;
13937
14833
  if (document.querySelector("[data-ohw-section-picker]")) return;
@@ -13939,7 +14835,7 @@ function OhhwellsBridge() {
13939
14835
  deselectRef.current();
13940
14836
  deactivateRef.current();
13941
14837
  }, [pathname, isEditMode]);
13942
- (0, import_react15.useEffect)(() => {
14838
+ (0, import_react16.useEffect)(() => {
13943
14839
  const contentForNav = () => {
13944
14840
  if (isEditMode) return editContentRef.current;
13945
14841
  if (!subdomain) return {};
@@ -13971,8 +14867,10 @@ function OhhwellsBridge() {
13971
14867
  const content = contentForNav();
13972
14868
  reconcileNavbarItemsFromContent(content);
13973
14869
  reconcileFooterOrderFromContent(content);
14870
+ reconcileSocialsFromContent(content);
14871
+ applySocialsDisplayFromContent(content);
13974
14872
  document.querySelectorAll("footer [data-ohw-href-key]").forEach((el) => {
13975
- if (isFooterHrefKey(el.getAttribute("data-ohw-href-key"))) {
14873
+ if (isFooterHrefKey(el.getAttribute("data-ohw-href-key")) || getSocialItem(el)) {
13976
14874
  disableNativeHrefDrag(el);
13977
14875
  }
13978
14876
  });
@@ -14004,7 +14902,7 @@ function OhhwellsBridge() {
14004
14902
  observer?.disconnect();
14005
14903
  };
14006
14904
  }, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
14007
- (0, import_react15.useEffect)(() => {
14905
+ (0, import_react16.useEffect)(() => {
14008
14906
  if (!isEditMode) return;
14009
14907
  const measure = () => {
14010
14908
  const h = document.body.scrollHeight;
@@ -14028,7 +14926,7 @@ function OhhwellsBridge() {
14028
14926
  window.removeEventListener("resize", handleResize);
14029
14927
  };
14030
14928
  }, [pathname, isEditMode, postToParent2]);
14031
- (0, import_react15.useEffect)(() => {
14929
+ (0, import_react16.useEffect)(() => {
14032
14930
  if (!subdomainFromQuery || isEditMode) return;
14033
14931
  const handleClick = (e) => {
14034
14932
  const anchor = e.target.closest("a");
@@ -14044,7 +14942,7 @@ function OhhwellsBridge() {
14044
14942
  document.addEventListener("click", handleClick, true);
14045
14943
  return () => document.removeEventListener("click", handleClick, true);
14046
14944
  }, [subdomainFromQuery, isEditMode, router]);
14047
- (0, import_react15.useEffect)(() => {
14945
+ (0, import_react16.useEffect)(() => {
14048
14946
  if (!isEditMode) {
14049
14947
  editStylesRef.current?.base.remove();
14050
14948
  editStylesRef.current?.forceHover.remove();
@@ -14252,6 +15150,17 @@ function OhhwellsBridge() {
14252
15150
  });
14253
15151
  return;
14254
15152
  }
15153
+ if (isIconEditable(editable) && !getSocialItem(editable)) {
15154
+ e.preventDefault();
15155
+ e.stopPropagation();
15156
+ aiSectionApiRef.current?.selectFromElement(editable);
15157
+ postToParentRef.current({
15158
+ type: "ow:icon-pick",
15159
+ key: editable.dataset.ohwKey ?? "",
15160
+ current: currentIconRef(editable)
15161
+ });
15162
+ return;
15163
+ }
14255
15164
  if (isMediaEditable(editable)) {
14256
15165
  e.preventDefault();
14257
15166
  e.stopPropagation();
@@ -14266,6 +15175,7 @@ function OhhwellsBridge() {
14266
15175
  e.stopPropagation();
14267
15176
  if (selectedElRef.current === navAnchor) {
14268
15177
  if (e.detail >= 2) return;
15178
+ if (requestSocialDialog(navAnchor, postToParentRef.current, editContentRef.current)) return;
14269
15179
  activateRef.current(editable, { caretX: e.clientX, caretY: e.clientY });
14270
15180
  return;
14271
15181
  }
@@ -14282,6 +15192,7 @@ function OhhwellsBridge() {
14282
15192
  e.preventDefault();
14283
15193
  e.stopPropagation();
14284
15194
  if (selectedElRef.current === hrefAnchor) {
15195
+ if (requestSocialDialog(hrefAnchor, postToParentRef.current, editContentRef.current)) return;
14285
15196
  const textEditable = hrefAnchor.querySelector('[data-ohw-editable="text"]') ?? hrefAnchor.querySelector("[data-ohw-editable]");
14286
15197
  if (textEditable) {
14287
15198
  activateRef.current(textEditable, {
@@ -14320,6 +15231,13 @@ function OhhwellsBridge() {
14320
15231
  selectFrameRef.current(navContainerToSelect);
14321
15232
  return;
14322
15233
  }
15234
+ const socialsRowToSelect = isSocialsRow(target) ? target : null;
15235
+ if (socialsRowToSelect && !getSocialItem(target)) {
15236
+ e.preventDefault();
15237
+ e.stopPropagation();
15238
+ selectFrameRef.current(socialsRowToSelect);
15239
+ return;
15240
+ }
14323
15241
  const footerColumnToSelect = resolveFooterColumnSelectionTarget(target, e.clientX, e.clientY);
14324
15242
  if (footerColumnToSelect) {
14325
15243
  e.preventDefault();
@@ -14371,6 +15289,7 @@ function OhhwellsBridge() {
14371
15289
  if (target.closest('[data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-drag-handle-container], [data-slot="drag-handle"]')) {
14372
15290
  return;
14373
15291
  }
15292
+ if (getSocialItem(target)) return;
14374
15293
  const navLabel = getNavigationLabelEditable(target);
14375
15294
  const editable = navLabel?.editable ?? target.closest('[data-ohw-editable="text"], [data-ohw-editable="plain"]');
14376
15295
  if (!editable || isMediaEditable(editable) || editable.dataset.ohwEditable === "link") return;
@@ -14455,6 +15374,11 @@ function OhhwellsBridge() {
14455
15374
  const selected = selectedElRef.current;
14456
15375
  if (selected && (selected === editable || selected.contains(editable))) return;
14457
15376
  if (!isMediaEditable(editable) && !editable.hasAttribute("contenteditable")) {
15377
+ if (isIconEditable(editable) && !getSocialItem(editable)) {
15378
+ hoveredItemElRef.current = editable;
15379
+ setHoveredItemRect(editable.getBoundingClientRect());
15380
+ return;
15381
+ }
14458
15382
  const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
14459
15383
  if (hoverTarget.hasAttribute("data-ohw-href-key")) {
14460
15384
  clearHrefKeyHover(hoverTarget);
@@ -14502,6 +15426,13 @@ function OhhwellsBridge() {
14502
15426
  const related = e.relatedTarget instanceof Element ? e.relatedTarget : null;
14503
15427
  if (related?.closest("[data-ohw-drag-handle-container], [data-ohw-item-interaction]")) return;
14504
15428
  if (!isMediaEditable(editable)) {
15429
+ if (isIconEditable(editable) && !getSocialItem(editable) && hoveredItemElRef.current === editable) {
15430
+ if (!related?.closest("[data-ohw-item-interaction]")) {
15431
+ hoveredItemElRef.current = null;
15432
+ setHoveredItemRect(null);
15433
+ }
15434
+ return;
15435
+ }
14505
15436
  const hoverTarget = editable.closest("[data-ohw-href-key]") ?? editable;
14506
15437
  if (hoverTarget.hasAttribute("data-ohw-href-key")) {
14507
15438
  if (!related?.closest("[data-ohw-href-key]")) {
@@ -15050,7 +15981,7 @@ function OhhwellsBridge() {
15050
15981
  if (footerSession) {
15051
15982
  e.preventDefault();
15052
15983
  if (e.dataTransfer) e.dataTransfer.dropEffect = "move";
15053
- const slot = footerSession.kind === "link" && footerSession.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, footerSession.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
15984
+ 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);
15054
15985
  refreshFooterDragVisualsRef.current(footerSession, slot, e.clientX, e.clientY);
15055
15986
  return;
15056
15987
  }
@@ -15102,6 +16033,62 @@ function OhhwellsBridge() {
15102
16033
  resumeAnimTracks();
15103
16034
  clearImageHover();
15104
16035
  };
16036
+ const handleSocialCancel = (e) => {
16037
+ if (e.data?.type !== "ow:social-cancel") return;
16038
+ const { hrefKey } = e.data;
16039
+ const item = hrefKey ? findSocialByHrefKey(hrefKey) : null;
16040
+ if (!item) return;
16041
+ const removed = removeSocialItem(item, editContentRef.current);
16042
+ if (!removed) return;
16043
+ const orderJson = JSON.stringify(removed.order);
16044
+ editContentRef.current = { ...editContentRef.current, [SOCIALS_ORDER_KEY]: orderJson };
16045
+ postToParentRef.current({ type: "ow:change", nodes: [{ key: SOCIALS_ORDER_KEY, text: orderJson }] });
16046
+ deselectRef.current();
16047
+ };
16048
+ const handleSocialUpdate = (e) => {
16049
+ if (e.data?.type !== "ow:social-update") return;
16050
+ const updates = Array.isArray(e.data.items) ? e.data.items : [e.data];
16051
+ const nodes = [];
16052
+ for (const { hrefKey, iconKey, url, iconMarkup, platformId, label } of updates) {
16053
+ if (hrefKey) {
16054
+ document.querySelectorAll(`[data-ohw-href-key="${hrefKey}"]`).forEach((el) => applyLinkHref(el, url));
16055
+ nodes.push({ key: hrefKey, text: url });
16056
+ }
16057
+ if (iconKey && typeof iconMarkup === "string" && iconMarkup) {
16058
+ document.querySelectorAll(`[data-ohw-key="${iconKey}"][data-ohw-editable="icon"]`).forEach((el) => {
16059
+ applyIconMarkup(el, iconMarkup);
16060
+ });
16061
+ nodes.push({ key: iconKey, text: iconMarkup });
16062
+ }
16063
+ if (iconKey && platformId) nodes.push({ key: socialPlatformKey(iconKey), text: platformId });
16064
+ if (iconKey && label) {
16065
+ const labelKey = socialLabelKey(iconKey);
16066
+ document.querySelectorAll(`[data-ohw-key="${labelKey}"]`).forEach((el) => {
16067
+ el.textContent = label;
16068
+ });
16069
+ nodes.push({ key: labelKey, text: label });
16070
+ }
16071
+ }
16072
+ if (!nodes.length) return;
16073
+ editContentRef.current = {
16074
+ ...editContentRef.current,
16075
+ ...Object.fromEntries(nodes.map((node) => [node.key, node.text]))
16076
+ };
16077
+ postToParentRef.current({ type: "ow:change", nodes, flush: true });
16078
+ };
16079
+ const handleIconMarkup = (e) => {
16080
+ if (e.data?.type !== "ow:icon-markup") return;
16081
+ const { key, markup } = e.data;
16082
+ if (!key || typeof markup !== "string") return;
16083
+ const targets = document.querySelectorAll(
16084
+ `[data-ohw-key="${key}"][data-ohw-editable="icon"]`
16085
+ );
16086
+ if (!targets.length) return;
16087
+ targets.forEach((el) => {
16088
+ applyIconMarkup(el, markup);
16089
+ });
16090
+ postToParentRef.current({ type: "ow:change", nodes: [{ key, text: markup }], flush: true });
16091
+ };
15105
16092
  const handleImageUrl = (e) => {
15106
16093
  if (e.data?.type !== "ow:image-url") return;
15107
16094
  const { key, url } = e.data;
@@ -15528,7 +16515,7 @@ function OhhwellsBridge() {
15528
16515
  }
15529
16516
  if (footerDragRef.current) {
15530
16517
  const session = footerDragRef.current;
15531
- const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(session.lastClientX, session.lastClientY, session.hrefKey) : hitTestColumnDropSlot(session.lastClientX, session.lastClientY);
16518
+ 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);
15532
16519
  refreshFooterDragVisualsRef.current(session, slot, session.lastClientX, session.lastClientY);
15533
16520
  }
15534
16521
  if (navDragRef.current) {
@@ -15848,6 +16835,9 @@ function OhhwellsBridge() {
15848
16835
  window.addEventListener("message", handleClearSchedulingWidget);
15849
16836
  window.addEventListener("message", handleRemoveSchedulingSection);
15850
16837
  window.addEventListener("message", handleCollectSection);
16838
+ window.addEventListener("message", handleSocialCancel);
16839
+ window.addEventListener("message", handleSocialUpdate);
16840
+ window.addEventListener("message", handleIconMarkup);
15851
16841
  window.addEventListener("message", handleImageUrl);
15852
16842
  window.addEventListener("message", handleImageUploading);
15853
16843
  window.addEventListener("message", handleCarouselChange);
@@ -15899,6 +16889,9 @@ function OhhwellsBridge() {
15899
16889
  window.removeEventListener("message", handleClearSchedulingWidget);
15900
16890
  window.removeEventListener("message", handleRemoveSchedulingSection);
15901
16891
  window.removeEventListener("message", handleCollectSection);
16892
+ window.removeEventListener("message", handleSocialCancel);
16893
+ window.removeEventListener("message", handleSocialUpdate);
16894
+ window.removeEventListener("message", handleIconMarkup);
15902
16895
  window.removeEventListener("message", handleImageUrl);
15903
16896
  window.removeEventListener("message", handleImageUploading);
15904
16897
  window.removeEventListener("message", handleCarouselChange);
@@ -15920,7 +16913,7 @@ function OhhwellsBridge() {
15920
16913
  if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
15921
16914
  };
15922
16915
  }, [isEditMode, refreshStateRules]);
15923
- (0, import_react15.useEffect)(() => {
16916
+ (0, import_react16.useEffect)(() => {
15924
16917
  if (!isEditMode) return;
15925
16918
  const THRESHOLD = 10;
15926
16919
  const resolveWasSelected = (el) => {
@@ -15940,9 +16933,9 @@ function OhhwellsBridge() {
15940
16933
  return;
15941
16934
  }
15942
16935
  if (target.closest("[data-ohw-item-drag-surface]")) return;
15943
- const anchor = getNavigationItemAnchor(target);
16936
+ const anchor = getNavigationItemAnchor(target) ?? (document.elementsFromPoint(e.clientX, e.clientY).map((el) => el instanceof HTMLElement ? getNavigationItemAnchor(el) : null).find((found) => found !== null) ?? null);
15944
16937
  const hrefKey = anchor?.getAttribute("data-ohw-href-key") ?? null;
15945
- if (anchor && isFooterHrefKey(hrefKey)) {
16938
+ if (anchor && (isFooterHrefKey(hrefKey) || getSocialItem(anchor))) {
15946
16939
  footerPointerDragRef.current = {
15947
16940
  el: anchor,
15948
16941
  kind: "link",
@@ -15975,7 +16968,7 @@ function OhhwellsBridge() {
15975
16968
  clearTextSelection();
15976
16969
  const session = footerDragRef.current;
15977
16970
  if (!session) return;
15978
- const slot = session.kind === "link" && session.hrefKey ? hitTestLinkDropSlot(e.clientX, e.clientY, session.hrefKey) : hitTestColumnDropSlot(e.clientX, e.clientY);
16971
+ 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);
15979
16972
  refreshFooterDragVisualsRef.current(session, slot, e.clientX, e.clientY);
15980
16973
  return;
15981
16974
  }
@@ -16002,7 +16995,7 @@ function OhhwellsBridge() {
16002
16995
  const column = findFooterColumnForLink(pending.el);
16003
16996
  const columns2 = listFooterColumns();
16004
16997
  beginFooterDragRef.current({
16005
- kind: "link",
16998
+ kind: getSocialItem(pending.el) ? "social" : "link",
16006
16999
  hrefKey: key,
16007
17000
  columnEl: column,
16008
17001
  sourceColumnIndex: column ? columns2.indexOf(column) : 0,
@@ -16074,7 +17067,7 @@ function OhhwellsBridge() {
16074
17067
  unlockFooterDragInteraction();
16075
17068
  };
16076
17069
  }, [isEditMode]);
16077
- (0, import_react15.useEffect)(() => {
17070
+ (0, import_react16.useEffect)(() => {
16078
17071
  const handler = (e) => {
16079
17072
  if (e.data?.type !== "ow:request-schedule-config") return;
16080
17073
  const insertAfterVal = e.data.insertAfter;
@@ -16090,7 +17083,7 @@ function OhhwellsBridge() {
16090
17083
  window.addEventListener("message", handler);
16091
17084
  return () => window.removeEventListener("message", handler);
16092
17085
  }, [processConfigRequest]);
16093
- (0, import_react15.useEffect)(() => {
17086
+ (0, import_react16.useEffect)(() => {
16094
17087
  if (!isEditMode) return;
16095
17088
  document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
16096
17089
  el.removeAttribute("data-ohw-active-state");
@@ -16114,7 +17107,7 @@ function OhhwellsBridge() {
16114
17107
  postToParent2({
16115
17108
  type: "ow:ready",
16116
17109
  version: "1",
16117
- bridgeVersion: "0.1.54",
17110
+ bridgeVersion: "0.1.55",
16118
17111
  path: pathname,
16119
17112
  nodes: collectEditableNodes(editContentRef.current),
16120
17113
  sections
@@ -16126,13 +17119,13 @@ function OhhwellsBridge() {
16126
17119
  clearTimeout(timer);
16127
17120
  };
16128
17121
  }, [pathname, isEditMode, refreshStateRules, postToParent2]);
16129
- (0, import_react15.useEffect)(() => {
17122
+ (0, import_react16.useEffect)(() => {
16130
17123
  scrollToHashSectionWhenReady();
16131
17124
  const onHashChange = () => scrollToHashSectionWhenReady();
16132
17125
  window.addEventListener("hashchange", onHashChange);
16133
17126
  return () => window.removeEventListener("hashchange", onHashChange);
16134
17127
  }, [pathname]);
16135
- const handleCommand = (0, import_react15.useCallback)((cmd) => {
17128
+ const handleCommand = (0, import_react16.useCallback)((cmd) => {
16136
17129
  const el = activeElRef.current;
16137
17130
  const selBefore = window.getSelection();
16138
17131
  let savedOffsets = null;
@@ -16168,7 +17161,7 @@ function OhhwellsBridge() {
16168
17161
  if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
16169
17162
  refreshActiveCommandsRef.current();
16170
17163
  }, []);
16171
- const handleStateChange = (0, import_react15.useCallback)((state) => {
17164
+ const handleStateChange = (0, import_react16.useCallback)((state) => {
16172
17165
  if (!activeStateElRef.current) return;
16173
17166
  const el = activeStateElRef.current;
16174
17167
  if (state === "Default") {
@@ -16181,7 +17174,7 @@ function OhhwellsBridge() {
16181
17174
  }
16182
17175
  setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
16183
17176
  }, [deactivate]);
16184
- const reselectAfterLinkPopover = (0, import_react15.useCallback)(
17177
+ const reselectAfterLinkPopover = (0, import_react16.useCallback)(
16185
17178
  (hrefKey) => {
16186
17179
  requestAnimationFrame(() => {
16187
17180
  const el = resolveHrefKeyElement(hrefKey);
@@ -16190,7 +17183,7 @@ function OhhwellsBridge() {
16190
17183
  },
16191
17184
  [resolveHrefKeyElement]
16192
17185
  );
16193
- const closeLinkPopover = (0, import_react15.useCallback)(() => {
17186
+ const closeLinkPopover = (0, import_react16.useCallback)(() => {
16194
17187
  const session = linkPopoverSessionRef.current;
16195
17188
  addNavAfterAnchorRef.current = null;
16196
17189
  setLinkPopover(null);
@@ -16198,9 +17191,9 @@ function OhhwellsBridge() {
16198
17191
  reselectAfterLinkPopover(session.key);
16199
17192
  }
16200
17193
  }, [reselectAfterLinkPopover]);
16201
- const closeLinkPopoverRef = (0, import_react15.useRef)(closeLinkPopover);
17194
+ const closeLinkPopoverRef = (0, import_react16.useRef)(closeLinkPopover);
16202
17195
  closeLinkPopoverRef.current = closeLinkPopover;
16203
- const openLinkPopoverForActive = (0, import_react15.useCallback)(() => {
17196
+ const openLinkPopoverForActive = (0, import_react16.useCallback)(() => {
16204
17197
  const hrefCtx = getHrefKeyFromElement(activeElRef.current);
16205
17198
  if (!hrefCtx) return;
16206
17199
  bumpLinkPopoverGrace();
@@ -16211,11 +17204,15 @@ function OhhwellsBridge() {
16211
17204
  });
16212
17205
  deactivate();
16213
17206
  }, [deactivate]);
16214
- const openLinkPopoverForSelected = (0, import_react15.useCallback)(() => {
17207
+ const openLinkPopoverForSelected = (0, import_react16.useCallback)(() => {
16215
17208
  const anchor = selectedElRef.current;
16216
17209
  if (!anchor) return;
16217
17210
  const key = anchor.getAttribute("data-ohw-href-key");
16218
17211
  if (!key) return;
17212
+ if (requestSocialDialog(anchor, postToParentRef.current, editContentRef.current)) {
17213
+ deselect();
17214
+ return;
17215
+ }
16219
17216
  bumpLinkPopoverGrace();
16220
17217
  setLinkPopover({
16221
17218
  key,
@@ -16224,7 +17221,7 @@ function OhhwellsBridge() {
16224
17221
  });
16225
17222
  deselect();
16226
17223
  }, [deselect]);
16227
- const handleSelectParent = (0, import_react15.useCallback)(() => {
17224
+ const handleSelectParent = (0, import_react16.useCallback)(() => {
16228
17225
  const selected = selectedElRef.current;
16229
17226
  if (!selected) return;
16230
17227
  if (toolbarVariantRef.current === "select-frame") {
@@ -16251,11 +17248,37 @@ function OhhwellsBridge() {
16251
17248
  }
16252
17249
  deselectRef.current();
16253
17250
  }, []);
16254
- const handleDuplicateSelected = (0, import_react15.useCallback)(() => {
17251
+ const handleDuplicateSelected = (0, import_react16.useCallback)(() => {
16255
17252
  const selected = selectedElRef.current;
16256
17253
  if (!selected || !isNavigationItem2(selected)) return;
16257
17254
  const hrefKey = selected.getAttribute("data-ohw-href-key");
16258
17255
  if (!hrefKey) return;
17256
+ const social = getSocialItem(selected);
17257
+ if (social) {
17258
+ const result = duplicateSocialItem(social, editContentRef.current);
17259
+ if (!result) return;
17260
+ const orderJson = JSON.stringify(result.order);
17261
+ const carried = [
17262
+ { from: result.copiedFrom?.href, to: result.hrefKey },
17263
+ { from: result.copiedFrom?.icon, to: result.iconKey },
17264
+ { from: result.copiedFrom?.icon ? socialPlatformKey(result.copiedFrom.icon) : null, to: socialPlatformKey(result.iconKey) }
17265
+ ];
17266
+ const nodes = [{ key: SOCIALS_ORDER_KEY, text: orderJson }];
17267
+ for (const { from, to } of carried) {
17268
+ const value = from ? editContentRef.current[from] : void 0;
17269
+ if (value) nodes.push({ key: to, text: value });
17270
+ }
17271
+ editContentRef.current = {
17272
+ ...editContentRef.current,
17273
+ ...Object.fromEntries(nodes.map((node) => [node.key, node.text]))
17274
+ };
17275
+ postToParent2({ type: "ow:change", nodes });
17276
+ enforceLinkHrefs();
17277
+ const copyRow = findSocialsRow(result.item);
17278
+ if (copyRow) applySocialsDisplayToRow(copyRow, socialsDisplayFor(copyRow, editContentRef.current));
17279
+ requestAnimationFrame(() => selectRef.current(result.item));
17280
+ return;
17281
+ }
16259
17282
  if (isNavbarHrefKey(hrefKey)) {
16260
17283
  const result = duplicateNavbarItem(selected);
16261
17284
  if (!result) return;
@@ -16341,7 +17364,7 @@ function OhhwellsBridge() {
16341
17364
  });
16342
17365
  }
16343
17366
  }, [postToParent2]);
16344
- const runPendingDeleteUndo = (0, import_react15.useCallback)(() => {
17367
+ const runPendingDeleteUndo = (0, import_react16.useCallback)(() => {
16345
17368
  const pending = pendingDeleteUndoRef.current;
16346
17369
  if (!pending) return false;
16347
17370
  pendingDeleteUndoRef.current = null;
@@ -16349,7 +17372,7 @@ function OhhwellsBridge() {
16349
17372
  enforceLinkHrefs();
16350
17373
  return true;
16351
17374
  }, []);
16352
- const handleDeleteSelected = (0, import_react15.useCallback)(() => {
17375
+ const handleDeleteSelected = (0, import_react16.useCallback)(() => {
16353
17376
  const selected = selectedElRef.current;
16354
17377
  if (!selected) return false;
16355
17378
  return deleteSelectedNavFooterItem({
@@ -16370,7 +17393,7 @@ function OhhwellsBridge() {
16370
17393
  }, [postToParent2]);
16371
17394
  handleDeleteSelectedRef.current = handleDeleteSelected;
16372
17395
  runPendingDeleteUndoRef.current = runPendingDeleteUndo;
16373
- const handleLinkPopoverSubmit = (0, import_react15.useCallback)(
17396
+ const handleLinkPopoverSubmit = (0, import_react16.useCallback)(
16374
17397
  (target) => {
16375
17398
  const session = linkPopoverSessionRef.current;
16376
17399
  if (!session) return;
@@ -16436,19 +17459,19 @@ function OhhwellsBridge() {
16436
17459
  const showEditLink = toolbarShowEditLink;
16437
17460
  const currentSections = sectionsByPath[pathname] ?? [];
16438
17461
  linkPopoverOpenRef.current = linkPopover !== null;
16439
- const handleMediaReplace = (0, import_react15.useCallback)(
17462
+ const handleMediaReplace = (0, import_react16.useCallback)(
16440
17463
  (key) => {
16441
17464
  postToParent2({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
16442
17465
  },
16443
17466
  [postToParent2, mediaHover?.elementType]
16444
17467
  );
16445
- const handleEditCarousel = (0, import_react15.useCallback)(
17468
+ const handleEditCarousel = (0, import_react16.useCallback)(
16446
17469
  (key) => {
16447
17470
  postToParent2({ type: "ow:carousel-open", key, images: readCarouselValue(key) });
16448
17471
  },
16449
17472
  [postToParent2]
16450
17473
  );
16451
- const handleMediaFadeOutComplete = (0, import_react15.useCallback)((key) => {
17474
+ const handleMediaFadeOutComplete = (0, import_react16.useCallback)((key) => {
16452
17475
  setUploadingRects((prev) => {
16453
17476
  if (!(key in prev)) return prev;
16454
17477
  const next = { ...prev };
@@ -16456,7 +17479,7 @@ function OhhwellsBridge() {
16456
17479
  return next;
16457
17480
  });
16458
17481
  }, []);
16459
- const handleVideoSettingsChange = (0, import_react15.useCallback)(
17482
+ const handleVideoSettingsChange = (0, import_react16.useCallback)(
16460
17483
  (key, settings) => {
16461
17484
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
16462
17485
  const video = getVideoEl2(el);
@@ -16479,10 +17502,10 @@ function OhhwellsBridge() {
16479
17502
  [postToParent2]
16480
17503
  );
16481
17504
  return bridgeRoot ? (0, import_react_dom4.createPortal)(
16482
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
16483
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
16484
- isEditMode && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
16485
- Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
17505
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
17506
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
17507
+ isEditMode && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(AiSectionOverlay, { postToParent: postToParent2, apiRef: aiSectionApiRef }),
17508
+ Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
16486
17509
  MediaOverlay,
16487
17510
  {
16488
17511
  hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
@@ -16493,7 +17516,7 @@ function OhhwellsBridge() {
16493
17516
  },
16494
17517
  `uploading-${key}`
16495
17518
  )),
16496
- mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
17519
+ mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
16497
17520
  MediaOverlay,
16498
17521
  {
16499
17522
  hover: mediaHover,
@@ -16502,11 +17525,11 @@ function OhhwellsBridge() {
16502
17525
  onVideoSettingsChange: handleVideoSettingsChange
16503
17526
  }
16504
17527
  ),
16505
- carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
16506
- siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
16507
- siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
16508
- isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
16509
- isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
17528
+ carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
17529
+ siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
17530
+ siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
17531
+ isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
17532
+ isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
16510
17533
  "div",
16511
17534
  {
16512
17535
  className: "pointer-events-none fixed z-2147483646",
@@ -16516,7 +17539,7 @@ function OhhwellsBridge() {
16516
17539
  width: slot.width,
16517
17540
  height: slot.height
16518
17541
  },
16519
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
17542
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
16520
17543
  DropIndicator,
16521
17544
  {
16522
17545
  direction: slot.direction,
@@ -16527,7 +17550,7 @@ function OhhwellsBridge() {
16527
17550
  },
16528
17551
  `footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
16529
17552
  )),
16530
- isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
17553
+ isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
16531
17554
  "div",
16532
17555
  {
16533
17556
  className: "pointer-events-none fixed z-2147483646",
@@ -16537,7 +17560,7 @@ function OhhwellsBridge() {
16537
17560
  width: slot.width,
16538
17561
  height: slot.height
16539
17562
  },
16540
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
17563
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
16541
17564
  DropIndicator,
16542
17565
  {
16543
17566
  direction: slot.direction,
@@ -16548,10 +17571,10 @@ function OhhwellsBridge() {
16548
17571
  },
16549
17572
  `nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
16550
17573
  )),
16551
- hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
16552
- hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
16553
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
16554
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
17574
+ hoveredNavContainerRect && (toolbarVariant !== "select-frame" || isFooterFrameSelection) && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
17575
+ hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
17576
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer2(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
17577
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isFooterLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
16555
17578
  FooterContainerChrome,
16556
17579
  {
16557
17580
  rect: toolbarRect,
@@ -16559,7 +17582,7 @@ function OhhwellsBridge() {
16559
17582
  addDisabled: !canAddFooterColumn()
16560
17583
  }
16561
17584
  ),
16562
- toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
17585
+ toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
16563
17586
  ItemInteractionLayer,
16564
17587
  {
16565
17588
  rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
@@ -16574,10 +17597,18 @@ function OhhwellsBridge() {
16574
17597
  onItemPointerDown: handleItemChromePointerDown,
16575
17598
  onItemClick: handleItemChromeClick,
16576
17599
  itemDragSurface: !isFooterFrameSelection,
16577
- toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && isFooterFrameSelection && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
17600
+ toolbar: toolbarVariant === "link-action" && !isItemDragging || toolbarVariant === "select-frame" && (isFooterFrameSelection || selectedIsSocialsRow) && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
16578
17601
  ItemActionToolbar,
16579
17602
  {
16580
17603
  onEditLink: openLinkPopoverForSelected,
17604
+ onStyle: () => {
17605
+ const row = selectedElRef.current;
17606
+ if (!row) return;
17607
+ if (floatingPanel?.kind === "socials-display") closeFloatingPanelOnly();
17608
+ else openSocialsDisplayPanel(row);
17609
+ },
17610
+ showStyle: selectedIsSocialsRow,
17611
+ styleActive: floatingPanel?.kind === "socials-display",
16581
17612
  onAddItem: handleAddChildItem,
16582
17613
  onSelectParent: handleSelectParent,
16583
17614
  onDuplicate: handleDuplicateSelected,
@@ -16585,12 +17616,12 @@ function OhhwellsBridge() {
16585
17616
  addItemDisabled: false,
16586
17617
  editLinkDisabled: false,
16587
17618
  moreDisabled: false,
16588
- duplicateDisabled: isFooterFrameSelection,
16589
- showEditLink: !isFooterFrameSelection && navDropdownPreviewOpen === null,
16590
- showAddItem: isFooterFrameSelection || !selectedIsCta && Boolean(
17619
+ duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow,
17620
+ showEditLink: !isFooterFrameSelection && !selectedIsSocialsRow && navDropdownPreviewOpen === null,
17621
+ showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
16591
17622
  selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)
16592
17623
  ),
16593
- showMore: !selectedIsCta || isFooterFrameSelection,
17624
+ showMore: (!selectedIsCta || isFooterFrameSelection) && !selectedIsSocialsRow,
16594
17625
  dropdownOpen: navDropdownPreviewOpen,
16595
17626
  onDropdownOpenChange: handleNavDropdownOpenChange,
16596
17627
  headingVisible: footerHeadingVisible,
@@ -16599,8 +17630,8 @@ function OhhwellsBridge() {
16599
17630
  ) : void 0
16600
17631
  }
16601
17632
  ),
16602
- toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
16603
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
17633
+ toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
17634
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
16604
17635
  EditGlowChrome,
16605
17636
  {
16606
17637
  rect: toolbarRect,
@@ -16610,7 +17641,7 @@ function OhhwellsBridge() {
16610
17641
  hideHandle: isItemDragging
16611
17642
  }
16612
17643
  ),
16613
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
17644
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
16614
17645
  FloatingToolbar,
16615
17646
  {
16616
17647
  rect: toolbarRect,
@@ -16623,7 +17654,7 @@ function OhhwellsBridge() {
16623
17654
  }
16624
17655
  )
16625
17656
  ] }),
16626
- maxBadge && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
17657
+ maxBadge && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
16627
17658
  "div",
16628
17659
  {
16629
17660
  "data-ohw-max-badge": "",
@@ -16649,7 +17680,7 @@ function OhhwellsBridge() {
16649
17680
  ]
16650
17681
  }
16651
17682
  ),
16652
- toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
17683
+ toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
16653
17684
  StateToggle,
16654
17685
  {
16655
17686
  rect: toggleState.rect,
@@ -16658,15 +17689,15 @@ function OhhwellsBridge() {
16658
17689
  onStateChange: handleStateChange
16659
17690
  }
16660
17691
  ),
16661
- sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
17692
+ sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
16662
17693
  "div",
16663
17694
  {
16664
17695
  "data-ohw-section-insert-line": "",
16665
17696
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
16666
17697
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
16667
17698
  children: [
16668
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
16669
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
17699
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
17700
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
16670
17701
  Badge,
16671
17702
  {
16672
17703
  className: "px-8 py-1 bg-primary hover:bg-primary text-primary-foreground text-xs font-medium shrink-0 rounded-full cursor-pointer pointer-events-auto",
@@ -16683,11 +17714,11 @@ function OhhwellsBridge() {
16683
17714
  children: "Add Section"
16684
17715
  }
16685
17716
  ),
16686
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
17717
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
16687
17718
  ]
16688
17719
  }
16689
17720
  ),
16690
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
17721
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
16691
17722
  LinkPopover,
16692
17723
  {
16693
17724
  panelRef: linkPopoverPanelRef,
@@ -16703,6 +17734,28 @@ function OhhwellsBridge() {
16703
17734
  onSubmit: handleLinkPopoverSubmit
16704
17735
  },
16705
17736
  linkPopover.key
17737
+ ) : null,
17738
+ floatingPanel && floatingPanel.kind === "socials-display" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
17739
+ FloatingPanel,
17740
+ {
17741
+ open: true,
17742
+ title: floatingPanel.title,
17743
+ context: floatingPanel.context,
17744
+ position: floatingPanelPos,
17745
+ onPositionChange: setFloatingPanelPos,
17746
+ parentScroll: parentScrollSnap ?? parentScrollRef.current,
17747
+ onClose: closeFloatingPanelOnly,
17748
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
17749
+ SocialsDisplayPanel,
17750
+ {
17751
+ display: socialsDisplayFor(floatingPanel.row, editContentRef.current),
17752
+ onChange: (next) => {
17753
+ changeSocialsDisplay(floatingPanel.row, next);
17754
+ setFloatingPanel({ ...floatingPanel });
17755
+ }
17756
+ }
17757
+ )
17758
+ }
16706
17759
  ) : null
16707
17760
  ] }),
16708
17761
  bridgeRoot