@ohhwells/bridge 0.1.70-next.209 → 0.1.70-next.210

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
@@ -10863,11 +10863,15 @@ function referenceBox(slot) {
10863
10863
  }
10864
10864
  function iconMarkupSizedFor(slot, markup) {
10865
10865
  const box = referenceBox(slot);
10866
- if (!box) return markup;
10867
10866
  const holder = document.createElement("div");
10868
10867
  holder.innerHTML = markup;
10869
10868
  const glyph = holder.querySelector(GLYPH_SELECTOR);
10870
10869
  if (!glyph) return markup;
10870
+ if (!box) {
10871
+ glyph.style.width = "1.5em";
10872
+ glyph.style.height = "1.5em";
10873
+ return holder.innerHTML;
10874
+ }
10871
10875
  glyph.style.width = `${Math.round(box.width)}px`;
10872
10876
  glyph.style.height = `${Math.round(box.height)}px`;
10873
10877
  return holder.innerHTML;
@@ -10911,39 +10915,58 @@ function iconMarkupInheritingColour(markup) {
10911
10915
 
10912
10916
  // src/lib/socials-items.ts
10913
10917
  var ICON_SELECTOR = '[data-ohw-editable="icon"]';
10918
+ var PLACEHOLDER_SOCIAL_ICON = '<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/><path d="M2 12h20"/></svg>';
10919
+ var PLACEHOLDER_SOCIAL_LABEL = "Social";
10914
10920
  var SOCIAL_KEY_RE = /(^|-)social(s)?(-|$)/i;
10921
+ var SOCIAL_PLATFORM_KEY_RE = /(^|-)(instagram|facebook|fb|linkedin|twitter|tiktok|youtube|threads|whatsapp|telegram|pinterest|snapchat|discord|behance|dribbble|vimeo|spotify|github|reddit|medium|twitch)(-|$)/i;
10915
10922
  var SOCIALS_ROW_ATTR = "data-ohw-socials-row";
10916
10923
  var SOCIALS_ITEM_ATTR = "data-ohw-social-item";
10917
10924
  function isSocialItem(el) {
10918
10925
  if (!el) return false;
10919
10926
  const anchor = el instanceof HTMLAnchorElement ? el : el.closest("a");
10920
10927
  if (!anchor) return false;
10921
- if (SOCIAL_KEY_RE.test(anchor.getAttribute("data-ohw-href-key") ?? "")) return true;
10928
+ const hrefKey = anchor.getAttribute("data-ohw-href-key") ?? "";
10929
+ if (SOCIAL_KEY_RE.test(hrefKey) || SOCIAL_PLATFORM_KEY_RE.test(hrefKey)) return true;
10922
10930
  return anchor.querySelectorAll(ICON_SELECTOR).length === 1;
10923
10931
  }
10924
10932
  function getSocialItem(el) {
10925
10933
  const anchor = el.closest("a");
10926
10934
  return isSocialItem(anchor) ? anchor : null;
10927
10935
  }
10936
+ function isPerItemWrapper(wrapper) {
10937
+ if (wrapper.matches("li")) return true;
10938
+ if (!wrapper.matches("div, span")) return false;
10939
+ const siblings = Array.from(wrapper.parentElement?.children ?? []).filter(
10940
+ (child) => child instanceof HTMLElement && child.querySelectorAll("a").length === 1
10941
+ );
10942
+ return siblings.length > 1;
10943
+ }
10928
10944
  function findSocialsRow(el) {
10929
10945
  const item = getSocialItem(el);
10930
10946
  if (!item) return null;
10947
+ const marked = item.closest(`[${SOCIALS_ROW_ATTR}]`);
10948
+ if (marked) return marked;
10931
10949
  const wrapper = item.parentElement;
10932
- const row = wrapper && wrapper.querySelectorAll("a").length === 1 && wrapper.matches("li, div, span") ? wrapper.parentElement : wrapper;
10950
+ const row = wrapper && isPerItemWrapper(wrapper) ? wrapper.parentElement : wrapper;
10933
10951
  if (!row) return null;
10934
10952
  const anchors = Array.from(row.querySelectorAll("a"));
10935
10953
  if (!anchors.length || !anchors.every((anchor) => isSocialItem(anchor))) return null;
10936
10954
  return row;
10937
10955
  }
10938
10956
  function isSocialsRow(el) {
10957
+ if (el.hasAttribute(SOCIALS_ROW_ATTR)) return true;
10939
10958
  const anchors = Array.from(el.querySelectorAll("a"));
10940
10959
  if (!anchors.length || !anchors.some((anchor) => isSocialItem(anchor))) return false;
10941
10960
  return findSocialsRow(anchors[0]) === el;
10942
10961
  }
10943
- var MAX_SOCIAL_ITEMS_PER_ROW = 7;
10962
+ var MAX_SOCIAL_ITEMS_PER_ROW = 14;
10944
10963
  function canAddSocialItem(row) {
10945
10964
  return listSocialItems(row).length < MAX_SOCIAL_ITEMS_PER_ROW;
10946
10965
  }
10966
+ function canRemoveSocialItem(item) {
10967
+ const row = findSocialsRow(item);
10968
+ return row ? listSocialItems(row).length > 1 : false;
10969
+ }
10947
10970
  function listSocialItems(row) {
10948
10971
  return Array.from(row.children).map((child) => {
10949
10972
  if (!(child instanceof HTMLElement)) return null;
@@ -11037,8 +11060,10 @@ function fromMarkup(markup) {
11037
11060
  var rowKeys = /* @__PURE__ */ new WeakMap();
11038
11061
  function rowKeyOf(row) {
11039
11062
  const first = listSocialItems(row)[0];
11040
- const itemKey = first ? socialIconKey(first) ?? socialHrefKey(first)?.replace(/-href$/, "") : null;
11041
- const derived = itemKey?.replace(/-[^-]+$/, "") || null;
11063
+ const itemKey = first ? socialIconKey(first)?.replace(/-icon$/, "") ?? socialHrefKey(first)?.replace(/-href$/, "") : null;
11064
+ const withoutItem = itemKey?.replace(/-[^-]+$/, "") || null;
11065
+ const lastSegment = itemKey?.match(/[^-]+$/)?.[0] ?? "";
11066
+ const derived = withoutItem ? SOCIAL_PLATFORM_KEY_RE.test(lastSegment) ? `${withoutItem}-socials` : withoutItem : null;
11042
11067
  if (derived) rowKeys.set(row, derived);
11043
11068
  return derived ?? rowKeys.get(row) ?? "social";
11044
11069
  }
@@ -11066,7 +11091,13 @@ function nextSocialIndex(row, rowKey, content) {
11066
11091
  const used = listSocialItems(row).map((item) => socialHrefKey(item)).concat(Object.keys(content)).map((key) => key?.match(new RegExp(`^${rowKey}-(\\d+)`))?.[1]).map((digits) => digits === void 0 ? -1 : Number(digits));
11067
11092
  return Math.max(-1, ...used) + 1;
11068
11093
  }
11069
- function insertSocialItem(row, after, content = {}) {
11094
+ function planSocialInsert(row, content = {}) {
11095
+ if (!canAddSocialItem(row)) return null;
11096
+ const rowKey = rowKeyOf(row);
11097
+ const iconKey = `${rowKey}-${nextSocialIndex(row, rowKey, content)}`;
11098
+ return { hrefKey: `${iconKey}-href`, iconKey };
11099
+ }
11100
+ function insertSocialItem(row, after, content = {}, { placeholder = true } = {}) {
11070
11101
  const rowKey = rowKeyOf(row);
11071
11102
  const template = listSocialItems(row)[0];
11072
11103
  const remembered = rowTemplates.get(rowKey);
@@ -11087,16 +11118,23 @@ function insertSocialItem(row, after, content = {}) {
11087
11118
  });
11088
11119
  const icon = item.querySelector(ICON_SELECTOR);
11089
11120
  icon?.setAttribute("data-ohw-key", iconKey);
11121
+ if (placeholder && icon) icon.innerHTML = PLACEHOLDER_SOCIAL_ICON;
11090
11122
  item.querySelector(`[${SOCIALS_LABEL_ATTR}]`)?.remove();
11091
11123
  const afterUnit = after ? socialRowUnit(after) : null;
11092
11124
  if (afterUnit && afterUnit.parentElement === row) afterUnit.insertAdjacentElement("afterend", unit);
11093
11125
  else row.appendChild(unit);
11094
11126
  markSocialsRows(row.ownerDocument);
11127
+ if (placeholder) {
11128
+ const label = socialLabelElement(item);
11129
+ if (label && !label.textContent?.trim()) label.textContent = PLACEHOLDER_SOCIAL_LABEL;
11130
+ }
11131
+ applySocialsDisplayToRow(row, socialsDisplayFor(row, content));
11095
11132
  return { item, hrefKey, iconKey, order: getSocialsOrderFromDom(row.ownerDocument) };
11096
11133
  }
11097
11134
  function duplicateSocialItem(item, content) {
11098
11135
  const row = findSocialsRow(item);
11099
- const created = row ? insertSocialItem(row, item, content) : null;
11136
+ if (row && !canAddSocialItem(row)) return null;
11137
+ const created = row ? insertSocialItem(row, item, content, { placeholder: false }) : null;
11100
11138
  if (!created) return null;
11101
11139
  const sourceHref = socialHrefKey(item);
11102
11140
  const sourceIcon = socialIconKey(item);
@@ -11107,14 +11145,19 @@ function duplicateSocialItem(item, content) {
11107
11145
  const slot = link.querySelector(ICON_SELECTOR);
11108
11146
  if (slot) slot.innerHTML = glyph;
11109
11147
  }
11148
+ const sourceLabel = socialLabelElement(item)?.textContent?.trim();
11149
+ const copyLabel = socialLabelElement(link);
11150
+ if (copyLabel && sourceLabel) copyLabel.textContent = sourceLabel;
11151
+ if (row) applySocialsDisplayToRow(row, socialsDisplayFor(row, content));
11110
11152
  return {
11111
11153
  ...created,
11112
11154
  copiedFrom: { href: sourceHref, icon: sourceIcon }
11113
11155
  };
11114
11156
  }
11115
- function removeSocialItem(item, content) {
11157
+ function removeSocialItem(item, content, { allowLast = false } = {}) {
11116
11158
  const row = findSocialsRow(item);
11117
11159
  if (!row) return null;
11160
+ if (!allowLast && !canRemoveSocialItem(item)) return null;
11118
11161
  const hrefKey = socialHrefKey(item);
11119
11162
  const iconKey = socialIconKey(item);
11120
11163
  const removedKeys = [hrefKey, iconKey].filter((key) => Boolean(key));
@@ -11312,14 +11355,19 @@ function applySocialsDisplayFromContent(content, root = document) {
11312
11355
  });
11313
11356
  }
11314
11357
  function socialsMissingIcons(row) {
11315
- return listSocialItems(row).filter((item) => !item.querySelector(ICON_SELECTOR)).map((item) => ({ hrefKey: socialHrefKey(item) ?? "", url: item.getAttribute("href") ?? "" })).filter((entry) => Boolean(entry.hrefKey));
11358
+ return listSocialItems(row).filter((item) => {
11359
+ const slot = item.querySelector(ICON_SELECTOR);
11360
+ return !slot || !slot.firstElementChild;
11361
+ }).map((item) => ({ hrefKey: socialHrefKey(item) ?? "", url: item.getAttribute("href") ?? "" })).filter((entry) => Boolean(entry.hrefKey));
11316
11362
  }
11317
11363
  function ensureIconSlot(item) {
11318
11364
  const existing = item.querySelector(ICON_SELECTOR);
11319
11365
  if (existing) return existing.dataset.ohwKey ?? null;
11320
11366
  const hrefKey = socialHrefKey(item);
11321
11367
  if (!hrefKey) return null;
11322
- const iconKey = hrefKey.replace(/-href$/, "");
11368
+ const base = hrefKey.replace(/-href$/, "");
11369
+ const taken = document.querySelector(`[data-ohw-key="${base}"]`);
11370
+ const iconKey = taken && taken !== item ? `${base}-icon` : base;
11323
11371
  const slot = document.createElement("span");
11324
11372
  slot.setAttribute("data-ohw-key", iconKey);
11325
11373
  slot.setAttribute("data-ohw-editable", "icon");
@@ -14601,6 +14649,9 @@ function isMediaEditable(el) {
14601
14649
  const t = el.dataset.ohwEditable;
14602
14650
  return t === "image" || t === "bg-image" || t === "video";
14603
14651
  }
14652
+ function isIconMarkupValue(value) {
14653
+ return /^\s*<(svg|img)\b/i.test(value);
14654
+ }
14604
14655
  function isIconEditable(el) {
14605
14656
  return el.dataset.ohwEditable === "icon";
14606
14657
  }
@@ -16452,6 +16503,7 @@ function OhhwellsBridge() {
16452
16503
  setNavGroupForceOpen(anchor, true);
16453
16504
  activateRef.current(label);
16454
16505
  }, []);
16506
+ const pendingSocialAddRef = (0, import_react17.useRef)(null);
16455
16507
  const handleAddChildItem = (0, import_react17.useCallback)(() => {
16456
16508
  const selected = selectedElRef.current;
16457
16509
  if (!selected) return;
@@ -16466,21 +16518,17 @@ function OhhwellsBridge() {
16466
16518
  return;
16467
16519
  }
16468
16520
  const after = getSocialItem(selected);
16469
- const result2 = insertSocialItem(socialsRow, after, editContentRef.current);
16470
- if (!result2) return;
16471
- const orderJson = JSON.stringify(result2.order);
16472
- applySocialsDisplayToRow(socialsRow, socialsDisplayFor(socialsRow, editContentRef.current));
16473
- editContentRef.current = { ...editContentRef.current, [SOCIALS_ORDER_KEY]: orderJson };
16474
- postToParent2({ type: "ow:change", nodes: [{ key: SOCIALS_ORDER_KEY, text: orderJson }] });
16521
+ const planned = planSocialInsert(socialsRow, editContentRef.current);
16522
+ if (!planned) return;
16523
+ pendingSocialAddRef.current = { row: socialsRow, after, ...planned };
16475
16524
  postToParentRef.current({
16476
16525
  type: "ow:social-pick",
16477
- hrefKey: result2.hrefKey,
16478
- iconKey: result2.iconKey,
16526
+ hrefKey: planned.hrefKey,
16527
+ iconKey: planned.iconKey,
16479
16528
  url: "",
16480
- iconStyle: detectIconStyle(result2.item),
16529
+ iconStyle: detectIconStyle(getSocialItem(selected) ?? socialsRow),
16481
16530
  platformId: "",
16482
- // Lets the editor undo the insert if the dialog is dismissed: an item that was never given
16483
- // an address should not survive a Cancel.
16531
+ // Tells the editor this one is not on the page yet, so dismissing means "never mind".
16484
16532
  isNew: true
16485
16533
  });
16486
16534
  return;
@@ -17072,6 +17120,19 @@ function OhhwellsBridge() {
17072
17120
  row
17073
17121
  });
17074
17122
  }, []);
17123
+ const isEditModeRef = (0, import_react17.useRef)(false);
17124
+ const requestMissingSocialIconsRef = (0, import_react17.useRef)(() => {
17125
+ });
17126
+ const requestMissingSocialIcons = (0, import_react17.useCallback)(() => {
17127
+ const items = Array.from(document.querySelectorAll(`[${SOCIALS_ROW_ATTR}]`)).filter((row) => socialsDisplayFor(row, editContentRef.current).icon).flatMap((row) => {
17128
+ const missing = socialsMissingIcons(row);
17129
+ listSocialItems(row).forEach((item) => ensureIconSlot(item));
17130
+ return missing;
17131
+ });
17132
+ if (items.length) postToParentRef.current({ type: "ow:social-icons-needed", items });
17133
+ }, []);
17134
+ requestMissingSocialIconsRef.current = requestMissingSocialIcons;
17135
+ isEditModeRef.current = isEditMode;
17075
17136
  const changeSocialsDisplay = (0, import_react17.useCallback)(
17076
17137
  (row, next) => {
17077
17138
  if (next.icon) {
@@ -17332,6 +17393,7 @@ function OhhwellsBridge() {
17332
17393
  } else if (el.dataset.ohwEditable === "icon") {
17333
17394
  applyIconMarkup(el, val);
17334
17395
  } else if (el.dataset.ohwEditable === "form") {
17396
+ } else if (isIconMarkupValue(val)) {
17335
17397
  } else if (el.innerHTML !== val) {
17336
17398
  el.innerHTML = val;
17337
17399
  }
@@ -17344,6 +17406,7 @@ function OhhwellsBridge() {
17344
17406
  reconcileFooterOrderFromContent(content);
17345
17407
  reconcileSocialsFromContent(content);
17346
17408
  applySocialsDisplayFromContent(content);
17409
+ if (isEditModeRef.current) requestMissingSocialIconsRef.current();
17347
17410
  enforceLinkHrefs();
17348
17411
  initSectionsFromContent(content, true);
17349
17412
  initSectionInstancesFromContent(content, window.location.pathname);
@@ -17516,6 +17579,7 @@ function OhhwellsBridge() {
17516
17579
  } else if (el.dataset.ohwEditable === "link") {
17517
17580
  applyLinkHref(el, val);
17518
17581
  } else if (el.dataset.ohwEditable === "form") {
17582
+ } else if (isIconMarkupValue(val)) {
17519
17583
  } else if (el.innerHTML !== val) {
17520
17584
  el.innerHTML = val;
17521
17585
  }
@@ -17527,6 +17591,7 @@ function OhhwellsBridge() {
17527
17591
  reconcileFooterOrderFromContent(content);
17528
17592
  reconcileSocialsFromContent(content);
17529
17593
  applySocialsDisplayFromContent(content);
17594
+ if (isEditModeRef.current) requestMissingSocialIconsRef.current();
17530
17595
  document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
17531
17596
  if (!form.querySelector("[data-ohw-form-success]")) {
17532
17597
  reconcileFieldsFromContent(form, content);
@@ -17612,6 +17677,7 @@ function OhhwellsBridge() {
17612
17677
  reconcileFooterOrderFromContent(content);
17613
17678
  reconcileSocialsFromContent(content);
17614
17679
  applySocialsDisplayFromContent(content);
17680
+ if (isEditModeRef.current) requestMissingSocialIconsRef.current();
17615
17681
  document.querySelectorAll("footer [data-ohw-href-key]").forEach((el) => {
17616
17682
  if (isFooterHrefKey(el.getAttribute("data-ohw-href-key")) || getSocialItem(el)) {
17617
17683
  disableNativeHrefDrag(el);
@@ -19065,9 +19131,14 @@ function OhhwellsBridge() {
19065
19131
  const handleSocialCancel = (e) => {
19066
19132
  if (e.data?.type !== "ow:social-cancel") return;
19067
19133
  const { hrefKey } = e.data;
19134
+ if (pendingSocialAddRef.current?.hrefKey === hrefKey) {
19135
+ pendingSocialAddRef.current = null;
19136
+ deselectRef.current();
19137
+ return;
19138
+ }
19068
19139
  const item = hrefKey ? findSocialByHrefKey(hrefKey) : null;
19069
19140
  if (!item) return;
19070
- const removed = removeSocialItem(item, editContentRef.current);
19141
+ const removed = removeSocialItem(item, editContentRef.current, { allowLast: true });
19071
19142
  if (!removed) return;
19072
19143
  const orderJson = JSON.stringify(removed.order);
19073
19144
  editContentRef.current = { ...editContentRef.current, [SOCIALS_ORDER_KEY]: orderJson };
@@ -19078,11 +19149,27 @@ function OhhwellsBridge() {
19078
19149
  if (e.data?.type !== "ow:social-update") return;
19079
19150
  const updates = Array.isArray(e.data.items) ? e.data.items : [e.data];
19080
19151
  const nodes = [];
19081
- for (const { hrefKey, iconKey, url, iconMarkup, platformId, label } of updates) {
19152
+ const pending = pendingSocialAddRef.current;
19153
+ if (pending && updates.some((update) => update.hrefKey === pending.hrefKey)) {
19154
+ pendingSocialAddRef.current = null;
19155
+ if (pending.row.isConnected) {
19156
+ const created = insertSocialItem(pending.row, pending.after, editContentRef.current);
19157
+ if (created) {
19158
+ const orderJson = JSON.stringify(created.order);
19159
+ editContentRef.current = { ...editContentRef.current, [SOCIALS_ORDER_KEY]: orderJson };
19160
+ nodes.push({ key: SOCIALS_ORDER_KEY, text: orderJson });
19161
+ }
19162
+ }
19163
+ }
19164
+ for (const { hrefKey, iconKey: requestedIconKey, url, iconMarkup, platformId, label } of updates) {
19082
19165
  if (hrefKey) {
19083
19166
  document.querySelectorAll(`[data-ohw-href-key="${hrefKey}"]`).forEach((el) => applyLinkHref(el, url));
19084
19167
  nodes.push({ key: hrefKey, text: url });
19085
19168
  }
19169
+ const slotFromItem = hrefKey ? findSocialByHrefKey(hrefKey)?.querySelector('[data-ohw-editable="icon"]') : null;
19170
+ const requestedIsIconSlot = Boolean(requestedIconKey) && Boolean(document.querySelector(`[data-ohw-key="${requestedIconKey}"][data-ohw-editable="icon"]`));
19171
+ const requestedIsFree = Boolean(requestedIconKey) && !document.querySelector(`[data-ohw-key="${requestedIconKey}"]`);
19172
+ const iconKey = requestedIsIconSlot ? requestedIconKey : slotFromItem?.dataset.ohwKey ?? (requestedIsFree ? requestedIconKey : void 0);
19086
19173
  if (iconKey && typeof iconMarkup === "string" && iconMarkup) {
19087
19174
  document.querySelectorAll(`[data-ohw-key="${iconKey}"][data-ohw-editable="icon"]`).forEach((el) => {
19088
19175
  applyIconMarkup(el, iconMarkup);
@@ -19286,6 +19373,7 @@ function OhhwellsBridge() {
19286
19373
  applyLinkHref(el, val);
19287
19374
  } else if (el.dataset.ohwEditable === "icon") {
19288
19375
  applyIconMarkup(el, val);
19376
+ } else if (isIconMarkupValue(val)) {
19289
19377
  } else {
19290
19378
  el.innerHTML = val;
19291
19379
  }
@@ -20556,6 +20644,15 @@ function OhhwellsBridge() {
20556
20644
  if (!hrefKey) return;
20557
20645
  const social = getSocialItem(selected);
20558
20646
  if (social) {
20647
+ const row = findSocialsRow(social);
20648
+ if (row && !canAddSocialItem(row)) {
20649
+ postToParent2({
20650
+ type: "ow:toast",
20651
+ title: `Maximum ${MAX_SOCIAL_ITEMS_PER_ROW} social icons`,
20652
+ toastType: "error"
20653
+ });
20654
+ return;
20655
+ }
20559
20656
  const result = duplicateSocialItem(social, editContentRef.current);
20560
20657
  if (!result) return;
20561
20658
  const orderJson = JSON.stringify(result.order);
@@ -20950,6 +21047,7 @@ function OhhwellsBridge() {
20950
21047
  type: "button",
20951
21048
  className: "flex h-7 items-center gap-1.5 whitespace-nowrap rounded-md px-2 text-[13px] font-semibold text-foreground transition-colors hover:bg-muted/80",
20952
21049
  onClick: () => {
21050
+ setFieldTypePickerOpen(false);
20953
21051
  const form = formPickElRef.current;
20954
21052
  if (!form) return;
20955
21053
  postToParent2({
@@ -20983,6 +21081,7 @@ function OhhwellsBridge() {
20983
21081
  "aria-pressed": formViewState === state,
20984
21082
  className: "rounded-md px-2.5 py-1 text-[13px] font-semibold capitalize transition-colors " + (formViewState === state ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"),
20985
21083
  onClick: () => {
21084
+ setFieldTypePickerOpen(false);
20986
21085
  const form = formPickElRef.current;
20987
21086
  const key = form ? formKeyOf(form) : null;
20988
21087
  if (!form || !key) return;
@@ -21115,7 +21214,15 @@ function OhhwellsBridge() {
21115
21214
  })(),
21116
21215
  editLinkDisabled: false,
21117
21216
  moreDisabled: false,
21118
- duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow,
21217
+ deleteDisabled: selectedElRef.current !== null && (() => {
21218
+ const social = getSocialItem(selectedElRef.current);
21219
+ return social ? !canRemoveSocialItem(social) : false;
21220
+ })(),
21221
+ duplicateDisabled: isFooterFrameSelection || selectedIsSocialsRow || selectedElRef.current !== null && (() => {
21222
+ const social = getSocialItem(selectedElRef.current);
21223
+ const row = social ? findSocialsRow(social) : null;
21224
+ return row ? !canAddSocialItem(row) : false;
21225
+ })(),
21119
21226
  showEditLink: !isFooterFrameSelection && !selectedIsSocialsRow && navDropdownPreviewOpen === null,
21120
21227
  showAddItem: isFooterFrameSelection || selectedIsSocialsRow || !selectedIsCta && Boolean(
21121
21228
  selectedElRef.current && isNavbarHrefKey(selectedElRef.current.getAttribute("data-ohw-href-key")) && !isNestedNavChild(selectedElRef.current)