@ohhwells/bridge 0.1.139-next.383 → 0.1.139-next.386
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 +151 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +151 -31
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2479,6 +2479,49 @@ function socialHrefKey(item) {
|
|
|
2479
2479
|
function socialIconKey(item) {
|
|
2480
2480
|
return item.querySelector(ICON_SELECTOR)?.dataset.ohwKey ?? null;
|
|
2481
2481
|
}
|
|
2482
|
+
var SOCIAL_PLATFORM_LABELS = {
|
|
2483
|
+
instagram: "Instagram",
|
|
2484
|
+
facebook: "Facebook",
|
|
2485
|
+
x: "X",
|
|
2486
|
+
twitter: "X",
|
|
2487
|
+
tiktok: "TikTok",
|
|
2488
|
+
youtube: "YouTube",
|
|
2489
|
+
linkedin: "LinkedIn",
|
|
2490
|
+
pinterest: "Pinterest",
|
|
2491
|
+
whatsapp: "WhatsApp",
|
|
2492
|
+
telegram: "Telegram",
|
|
2493
|
+
spotify: "Spotify",
|
|
2494
|
+
threads: "Threads",
|
|
2495
|
+
vimeo: "Vimeo",
|
|
2496
|
+
discord: "Discord",
|
|
2497
|
+
medium: "Medium",
|
|
2498
|
+
website: "Website"
|
|
2499
|
+
};
|
|
2500
|
+
function socialPlatformLabel(item, content) {
|
|
2501
|
+
const iconKey = socialIconKey(item);
|
|
2502
|
+
const chosen = iconKey ? (content[socialPlatformKey(iconKey)] ?? "").trim().toLowerCase() : "";
|
|
2503
|
+
if (chosen) return SOCIAL_PLATFORM_LABELS[chosen] ?? chosen.charAt(0).toUpperCase() + chosen.slice(1);
|
|
2504
|
+
const label = socialLabelElement(item);
|
|
2505
|
+
const words = label && !label.hasAttribute(SOCIALS_EMPTY_LABEL_ATTR) ? (label.textContent ?? "").replace(/\s+/g, " ").trim() : "";
|
|
2506
|
+
if (words) return words;
|
|
2507
|
+
const link = item.matches("a") ? item : item.querySelector("a");
|
|
2508
|
+
const aria = (link?.getAttribute("aria-label") ?? item.getAttribute("aria-label") ?? "").trim();
|
|
2509
|
+
if (aria) return aria;
|
|
2510
|
+
const href = (link?.getAttribute("href") ?? "").trim();
|
|
2511
|
+
if (/^https?:\/\//i.test(href)) {
|
|
2512
|
+
let host = "";
|
|
2513
|
+
try {
|
|
2514
|
+
host = new URL(href).hostname.replace(/^www\./i, "").toLowerCase();
|
|
2515
|
+
} catch {
|
|
2516
|
+
host = "";
|
|
2517
|
+
}
|
|
2518
|
+
if (host.includes("x.com") || host.includes("twitter.com")) return "X";
|
|
2519
|
+
for (const [id, name] of Object.entries(SOCIAL_PLATFORM_LABELS)) {
|
|
2520
|
+
if (host.includes(id)) return name;
|
|
2521
|
+
}
|
|
2522
|
+
}
|
|
2523
|
+
return "Social";
|
|
2524
|
+
}
|
|
2482
2525
|
var SOCIALS_ORDER_KEY = "__ohw_socials_order";
|
|
2483
2526
|
function fromMarkup(markup) {
|
|
2484
2527
|
const holder = document.createElement("div");
|
|
@@ -6558,6 +6601,13 @@ function applyIconNameToTree(tree, path, icon) {
|
|
|
6558
6601
|
if (feature) {
|
|
6559
6602
|
return setPricingCardFeatureIcon(tree, Number(feature[1]), Number(feature[2]), icon);
|
|
6560
6603
|
}
|
|
6604
|
+
return rewriteIconSlot(tree, path, `lucide:${icon}`);
|
|
6605
|
+
}
|
|
6606
|
+
function applyIconUploadToTree(tree, path, mediaRef) {
|
|
6607
|
+
if (FEATURE_ICON_PATH.test(path)) return null;
|
|
6608
|
+
return rewriteIconSlot(tree, path, `icon:${mediaRef}`);
|
|
6609
|
+
}
|
|
6610
|
+
function rewriteIconSlot(tree, path, ref) {
|
|
6561
6611
|
const segments = path.split(".");
|
|
6562
6612
|
const slot = segments.pop();
|
|
6563
6613
|
if (!slot || NODE_SEGMENT.test(slot)) return null;
|
|
@@ -6565,8 +6615,8 @@ function applyIconNameToTree(tree, path, icon) {
|
|
|
6565
6615
|
const node = nodeAtPath(next, segments);
|
|
6566
6616
|
if (!node) return null;
|
|
6567
6617
|
const current = node.slots?.[slot];
|
|
6568
|
-
if (typeof current !== "string" || !/^(lucide|simple):/.test(current)) return null;
|
|
6569
|
-
node.slots = { ...node.slots, [slot]:
|
|
6618
|
+
if (typeof current !== "string" || !/^(lucide|simple|icon):/.test(current)) return null;
|
|
6619
|
+
node.slots = { ...node.slots, [slot]: ref };
|
|
6570
6620
|
return next;
|
|
6571
6621
|
}
|
|
6572
6622
|
|
|
@@ -7953,7 +8003,7 @@ function MediaBox({
|
|
|
7953
8003
|
onError
|
|
7954
8004
|
}) {
|
|
7955
8005
|
const url = refValue ? ctx.resolveMedia(refValue) : null;
|
|
7956
|
-
const isIcon = /^(lucide|simple):/.test(refValue);
|
|
8006
|
+
const isIcon = /^(lucide|simple|icon):/.test(refValue);
|
|
7957
8007
|
const aspectRatio = aspect && /^\d+:\d+$/.test(aspect) ? aspect.replace(":", " / ") : void 0;
|
|
7958
8008
|
const editAttrs = ctx.keyFor && editPath && !isIcon ? {
|
|
7959
8009
|
"data-ohw-key": ctx.keyFor(editPath),
|
|
@@ -7961,6 +8011,7 @@ function MediaBox({
|
|
|
7961
8011
|
} : {};
|
|
7962
8012
|
if (isIcon) {
|
|
7963
8013
|
const Icon = refValue.startsWith("lucide:") ? lucideByName(refValue.slice(7)) : null;
|
|
8014
|
+
const uploadedIconUrl = refValue.startsWith("icon:") ? ctx.resolveMedia(refValue.slice(5)) : null;
|
|
7964
8015
|
const iconEditAttrs = ctx.keyFor && editPath && genericImageEdit ? { "data-ohw-key": ctx.keyFor(editPath), "data-ohw-editable": "icon" } : {};
|
|
7965
8016
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
7966
8017
|
"span",
|
|
@@ -7975,7 +8026,7 @@ function MediaBox({
|
|
|
7975
8026
|
justifyContent: "center",
|
|
7976
8027
|
color: ctx.brand.palette.dark
|
|
7977
8028
|
},
|
|
7978
|
-
children: Icon ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { size: 48, color: ctx.brand.palette.dark, strokeWidth: 1.5 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: 24 }, children: "\u25C6" })
|
|
8029
|
+
children: uploadedIconUrl ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: uploadedIconUrl, alt: "", style: { width: 48, height: 48, objectFit: "contain" } }) : Icon ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { size: 48, color: ctx.brand.palette.dark, strokeWidth: 1.5 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: 24 }, children: "\u25C6" })
|
|
7979
8030
|
}
|
|
7980
8031
|
);
|
|
7981
8032
|
}
|
|
@@ -25164,36 +25215,72 @@ function OhhwellsBridge() {
|
|
|
25164
25215
|
const [selectedMedia, setSelectedMedia] = (0, import_react21.useState)(null);
|
|
25165
25216
|
const selectedMediaElRef = (0, import_react21.useRef)(null);
|
|
25166
25217
|
const mediaKeyDropTokenRef = (0, import_react21.useRef)(0);
|
|
25218
|
+
const selectedIconElRef = (0, import_react21.useRef)(null);
|
|
25219
|
+
const selectedSocialElRef = (0, import_react21.useRef)(null);
|
|
25220
|
+
const queueSectionKeyDrop = (0, import_react21.useCallback)((prev) => {
|
|
25221
|
+
const sectionEl = prev?.closest("[data-ohw-section]") ?? null;
|
|
25222
|
+
if (!sectionEl) return;
|
|
25223
|
+
const sectionInstanceId = instanceIdOf(movableUnit(sectionEl)) || null;
|
|
25224
|
+
if (!sectionInstanceId) return;
|
|
25225
|
+
const token = ++mediaKeyDropTokenRef.current;
|
|
25226
|
+
const onQueueDrained = (e) => {
|
|
25227
|
+
if (e.source !== window || e.data?.type !== "ow:media-key-drop" || e.data.token !== token) return;
|
|
25228
|
+
window.removeEventListener("message", onQueueDrained);
|
|
25229
|
+
if (aiSectionApiRef.current?.getSelectedId() !== sectionInstanceId) return;
|
|
25230
|
+
if (selectedMediaElRef.current || selectedIconElRef.current || selectedSocialElRef.current) return;
|
|
25231
|
+
postToParentRef.current({
|
|
25232
|
+
type: "ow:section-selected",
|
|
25233
|
+
sectionId: sectionEl.dataset.ohwSection ?? null,
|
|
25234
|
+
sectionLabel: sectionEl.dataset.ohwSectionLabel ?? titleCaseSectionId(sectionEl.dataset.ohwSection ?? ""),
|
|
25235
|
+
key: null
|
|
25236
|
+
});
|
|
25237
|
+
};
|
|
25238
|
+
window.addEventListener("message", onQueueDrained);
|
|
25239
|
+
window.postMessage({ type: "ow:media-key-drop", token }, "*");
|
|
25240
|
+
}, []);
|
|
25167
25241
|
const clearMediaSelection = (0, import_react21.useCallback)(() => {
|
|
25168
25242
|
const prev = selectedMediaElRef.current;
|
|
25169
25243
|
selectedMediaElRef.current = null;
|
|
25170
25244
|
setSelectedMedia(null);
|
|
25171
|
-
|
|
25172
|
-
|
|
25173
|
-
const sectionInstanceId = instanceIdOf(movableUnit(sectionEl)) || null;
|
|
25174
|
-
if (!sectionInstanceId) return;
|
|
25175
|
-
const token = ++mediaKeyDropTokenRef.current;
|
|
25176
|
-
const onQueueDrained = (e) => {
|
|
25177
|
-
if (e.source !== window || e.data?.type !== "ow:media-key-drop" || e.data.token !== token) return;
|
|
25178
|
-
window.removeEventListener("message", onQueueDrained);
|
|
25179
|
-
if (aiSectionApiRef.current?.getSelectedId() !== sectionInstanceId) return;
|
|
25180
|
-
if (selectedMediaElRef.current) return;
|
|
25181
|
-
postToParentRef.current({
|
|
25182
|
-
type: "ow:section-selected",
|
|
25183
|
-
sectionId: sectionEl.dataset.ohwSection ?? null,
|
|
25184
|
-
sectionLabel: sectionEl.dataset.ohwSectionLabel ?? titleCaseSectionId(sectionEl.dataset.ohwSection ?? ""),
|
|
25185
|
-
key: null
|
|
25186
|
-
});
|
|
25187
|
-
};
|
|
25188
|
-
window.addEventListener("message", onQueueDrained);
|
|
25189
|
-
window.postMessage({ type: "ow:media-key-drop", token }, "*");
|
|
25190
|
-
}
|
|
25191
|
-
}, []);
|
|
25245
|
+
queueSectionKeyDrop(prev);
|
|
25246
|
+
}, [queueSectionKeyDrop]);
|
|
25192
25247
|
const clearMediaSelectionRef = (0, import_react21.useRef)(clearMediaSelection);
|
|
25193
25248
|
clearMediaSelectionRef.current = clearMediaSelection;
|
|
25249
|
+
const clearIconSelection = (0, import_react21.useCallback)(() => {
|
|
25250
|
+
const prev = selectedIconElRef.current;
|
|
25251
|
+
if (!prev) return;
|
|
25252
|
+
selectedIconElRef.current = null;
|
|
25253
|
+
queueSectionKeyDrop(prev);
|
|
25254
|
+
}, [queueSectionKeyDrop]);
|
|
25255
|
+
const clearIconSelectionRef = (0, import_react21.useRef)(clearIconSelection);
|
|
25256
|
+
clearIconSelectionRef.current = clearIconSelection;
|
|
25257
|
+
const clearSocialSelection = (0, import_react21.useCallback)(() => {
|
|
25258
|
+
const prev = selectedSocialElRef.current;
|
|
25259
|
+
if (!prev) return;
|
|
25260
|
+
selectedSocialElRef.current = null;
|
|
25261
|
+
queueSectionKeyDrop(prev);
|
|
25262
|
+
}, [queueSectionKeyDrop]);
|
|
25263
|
+
const clearSocialSelectionRef = (0, import_react21.useRef)(clearSocialSelection);
|
|
25264
|
+
clearSocialSelectionRef.current = clearSocialSelection;
|
|
25265
|
+
const selectIconElement = (0, import_react21.useCallback)((el) => {
|
|
25266
|
+
if (selectedMediaElRef.current) clearMediaSelectionRef.current();
|
|
25267
|
+
selectedIconElRef.current = el;
|
|
25268
|
+
const sectionEl = el.closest("[data-ohw-section]");
|
|
25269
|
+
aiSectionApiRef.current?.selectFromElement(el, { report: false });
|
|
25270
|
+
postToParentRef.current({
|
|
25271
|
+
type: "ow:section-selected",
|
|
25272
|
+
sectionId: sectionEl?.dataset.ohwSection ?? null,
|
|
25273
|
+
sectionLabel: sectionEl ? sectionEl.dataset.ohwSectionLabel ?? titleCaseSectionId(sectionEl.dataset.ohwSection ?? "") : null,
|
|
25274
|
+
key: el.dataset.ohwKey ?? null,
|
|
25275
|
+
keyLabel: "Icon"
|
|
25276
|
+
});
|
|
25277
|
+
}, []);
|
|
25278
|
+
const selectIconElementRef = (0, import_react21.useRef)(selectIconElement);
|
|
25279
|
+
selectIconElementRef.current = selectIconElement;
|
|
25194
25280
|
const selectMediaElement = (0, import_react21.useCallback)((el) => {
|
|
25195
25281
|
const r2 = el.getBoundingClientRect();
|
|
25196
25282
|
const video = el.dataset.ohwEditable === "video" ? el.querySelector("video") : null;
|
|
25283
|
+
selectedIconElRef.current = null;
|
|
25197
25284
|
selectedMediaElRef.current = el;
|
|
25198
25285
|
setSelectedMedia({
|
|
25199
25286
|
key: el.dataset.ohwKey ?? "",
|
|
@@ -25858,6 +25945,7 @@ function OhhwellsBridge() {
|
|
|
25858
25945
|
selectedElRef.current = null;
|
|
25859
25946
|
selectedHrefKeyRef.current = null;
|
|
25860
25947
|
selectedFooterColAttrRef.current = null;
|
|
25948
|
+
clearSocialSelectionRef.current();
|
|
25861
25949
|
setSelectedIsCta(false);
|
|
25862
25950
|
setSelectedIsSocial(false);
|
|
25863
25951
|
setSelectedIsSocialsRow(false);
|
|
@@ -26759,7 +26847,22 @@ function OhhwellsBridge() {
|
|
|
26759
26847
|
const select = (0, import_react21.useCallback)((anchor) => {
|
|
26760
26848
|
if (!isNavigationItem2(anchor)) return;
|
|
26761
26849
|
if (activeElRef.current) deactivate();
|
|
26762
|
-
|
|
26850
|
+
clearSocialSelectionRef.current();
|
|
26851
|
+
const socialItem = getSocialItem(anchor);
|
|
26852
|
+
if (socialItem) {
|
|
26853
|
+
selectedSocialElRef.current = socialItem;
|
|
26854
|
+
const sectionEl = socialItem.closest("[data-ohw-section]");
|
|
26855
|
+
aiSectionApiRef.current?.selectFromElement(anchor, { report: false });
|
|
26856
|
+
postToParentRef.current({
|
|
26857
|
+
type: "ow:section-selected",
|
|
26858
|
+
sectionId: sectionEl?.dataset.ohwSection ?? null,
|
|
26859
|
+
sectionLabel: sectionEl ? sectionEl.dataset.ohwSectionLabel ?? titleCaseSectionId(sectionEl.dataset.ohwSection ?? "") : null,
|
|
26860
|
+
key: socialIconKey(socialItem) ?? socialItem.getAttribute("data-ohw-href-key"),
|
|
26861
|
+
keyLabel: socialPlatformLabel(socialItem, editContentRef.current)
|
|
26862
|
+
});
|
|
26863
|
+
} else {
|
|
26864
|
+
aiSectionApiRef.current?.selectFromElement(anchor);
|
|
26865
|
+
}
|
|
26763
26866
|
selectedElRef.current = anchor;
|
|
26764
26867
|
selectedHrefKeyRef.current = anchor.getAttribute("data-ohw-href-key");
|
|
26765
26868
|
selectedFooterColAttrRef.current = null;
|
|
@@ -28068,6 +28171,9 @@ function OhhwellsBridge() {
|
|
|
28068
28171
|
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
28069
28172
|
clearMediaSelectionRef.current();
|
|
28070
28173
|
}
|
|
28174
|
+
if (selectedIconElRef.current && !selectedIconElRef.current.contains(target)) {
|
|
28175
|
+
clearIconSelectionRef.current();
|
|
28176
|
+
}
|
|
28071
28177
|
if (selectedMediaElRef.current && target.closest("[data-ohw-media-overlay]") && !findClosestButtonLike(target)) {
|
|
28072
28178
|
const hit = findImageAtPoint(e.clientX, e.clientY, false);
|
|
28073
28179
|
if (hit && hit !== selectedMediaElRef.current) {
|
|
@@ -28238,9 +28344,13 @@ function OhhwellsBridge() {
|
|
|
28238
28344
|
if (isIconEditable(editable) && !getSocialItem(editable)) {
|
|
28239
28345
|
e.preventDefault();
|
|
28240
28346
|
e.stopPropagation();
|
|
28241
|
-
aiSectionApiRef.current?.selectFromElement(editable);
|
|
28242
28347
|
const aiIcon = editable.hasAttribute("data-ai-icon");
|
|
28243
28348
|
const featureIcon = aiIcon && /\.features\.\d+\.icon$/.test(editable.dataset.ohwKey ?? "");
|
|
28349
|
+
if (aiIcon) {
|
|
28350
|
+
aiSectionApiRef.current?.selectFromElement(editable);
|
|
28351
|
+
} else {
|
|
28352
|
+
selectIconElementRef.current(editable);
|
|
28353
|
+
}
|
|
28244
28354
|
postToParentRef.current({
|
|
28245
28355
|
type: "ow:icon-pick",
|
|
28246
28356
|
key: editable.dataset.ohwKey ?? "",
|
|
@@ -29519,12 +29629,16 @@ function OhhwellsBridge() {
|
|
|
29519
29629
|
};
|
|
29520
29630
|
const handleIconName = (e) => {
|
|
29521
29631
|
if (e.data?.type !== "ow:icon-name") return;
|
|
29522
|
-
const { key, icon } = e.data;
|
|
29523
|
-
|
|
29632
|
+
const { key, icon, url } = e.data;
|
|
29633
|
+
const isName = typeof icon === "string" && /^[a-z0-9-]+$/.test(icon);
|
|
29634
|
+
const isUpload = !isName && typeof url === "string" && /^https?:\/\/\S+$/i.test(url);
|
|
29635
|
+
if (!key || !isName && !isUpload) return;
|
|
29524
29636
|
const state = parseAiSectionsState(aiSectionsRef.current);
|
|
29525
29637
|
const entry = state.sections.find((s) => key.startsWith(aiSlotKeyPrefixFor(s.id)));
|
|
29526
29638
|
if (!entry) return;
|
|
29527
|
-
const
|
|
29639
|
+
const path = key.slice(aiSlotKeyPrefixFor(entry.id).length);
|
|
29640
|
+
const uploadRef = isUpload ? `icon-${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}` : null;
|
|
29641
|
+
const nextTree = uploadRef ? applyIconUploadToTree(entry.tree, path, uploadRef) : applyIconNameToTree(entry.tree, path, icon);
|
|
29528
29642
|
if (!nextTree) return;
|
|
29529
29643
|
void requestValidateTree5(postToParentRef.current, nextTree).then(({ ok }) => {
|
|
29530
29644
|
if (!ok) return;
|
|
@@ -29534,7 +29648,7 @@ function OhhwellsBridge() {
|
|
|
29534
29648
|
targetSectionId: entry.id,
|
|
29535
29649
|
tree: nextTree,
|
|
29536
29650
|
label: entry.label,
|
|
29537
|
-
media: entry.media,
|
|
29651
|
+
media: uploadRef ? { ...entry.media, [uploadRef]: url } : entry.media,
|
|
29538
29652
|
...entry.brand ? { brand: entry.brand } : {},
|
|
29539
29653
|
// The user is looking at the icon they just changed — no need to recenter on it.
|
|
29540
29654
|
skipScrollIntoView: true
|
|
@@ -29874,6 +29988,7 @@ function OhhwellsBridge() {
|
|
|
29874
29988
|
deactivateRef.current();
|
|
29875
29989
|
deselectRef.current();
|
|
29876
29990
|
clearMediaSelectionRef.current();
|
|
29991
|
+
clearIconSelectionRef.current();
|
|
29877
29992
|
};
|
|
29878
29993
|
clearInteractionChromeRef.current = clearInteractionChrome;
|
|
29879
29994
|
const applyTreeToLocalState = (payload) => {
|
|
@@ -30297,6 +30412,7 @@ function OhhwellsBridge() {
|
|
|
30297
30412
|
deselectRef.current();
|
|
30298
30413
|
deactivateRef.current();
|
|
30299
30414
|
clearMediaSelectionRef.current();
|
|
30415
|
+
clearIconSelectionRef.current();
|
|
30300
30416
|
};
|
|
30301
30417
|
window.addEventListener("message", handleDeactivate);
|
|
30302
30418
|
const handleToastAction = (e) => {
|
|
@@ -30386,6 +30502,10 @@ function OhhwellsBridge() {
|
|
|
30386
30502
|
clearMediaSelectionRef.current();
|
|
30387
30503
|
return;
|
|
30388
30504
|
}
|
|
30505
|
+
if (e.key === "Escape" && selectedIconElRef.current) {
|
|
30506
|
+
clearIconSelectionRef.current();
|
|
30507
|
+
return;
|
|
30508
|
+
}
|
|
30389
30509
|
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "a" && activeElRef.current) {
|
|
30390
30510
|
e.preventDefault();
|
|
30391
30511
|
selectAllTextInEditable(activeElRef.current);
|