@ohhwells/bridge 0.1.117-next.324 → 0.1.117-next.327
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 +169 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +169 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -572,6 +572,40 @@ function applyBrandToDom(kit) {
|
|
|
572
572
|
}
|
|
573
573
|
}
|
|
574
574
|
|
|
575
|
+
// src/lib/custom-code.ts
|
|
576
|
+
var ALLOWED_HEAD_TAGS = /* @__PURE__ */ new Set(["style", "meta", "link", "script", "noscript", "base"]);
|
|
577
|
+
var CUSTOM_CODE_AFTER_HEAD_KEY = "__ohw_custom_code_after_head";
|
|
578
|
+
var CUSTOM_CODE_BEFORE_HEAD_KEY = "__ohw_custom_code_before_head";
|
|
579
|
+
function clearExisting(slot) {
|
|
580
|
+
document.querySelectorAll(`[data-ohw-custom-code="${slot}"]`).forEach((el) => el.remove());
|
|
581
|
+
}
|
|
582
|
+
function buildNodes(raw, slot) {
|
|
583
|
+
if (!raw || !raw.trim()) return [];
|
|
584
|
+
const parsed = new DOMParser().parseFromString(raw, "text/html");
|
|
585
|
+
const source = [...parsed.head.childNodes, ...parsed.body.childNodes];
|
|
586
|
+
const nodes = [];
|
|
587
|
+
for (const node of source) {
|
|
588
|
+
if (node.nodeType !== Node.ELEMENT_NODE) continue;
|
|
589
|
+
const el = node;
|
|
590
|
+
const tag = el.tagName.toLowerCase();
|
|
591
|
+
if (!ALLOWED_HEAD_TAGS.has(tag)) continue;
|
|
592
|
+
const built = document.createElement(tag);
|
|
593
|
+
for (const attr of Array.from(el.attributes)) built.setAttribute(attr.name, attr.value);
|
|
594
|
+
if (tag === "script" || tag === "style" || tag === "noscript") built.textContent = el.textContent;
|
|
595
|
+
built.dataset.ohwCustomCode = slot;
|
|
596
|
+
nodes.push(built);
|
|
597
|
+
}
|
|
598
|
+
return nodes;
|
|
599
|
+
}
|
|
600
|
+
function applyCustomCodeToHead(content) {
|
|
601
|
+
clearExisting("after");
|
|
602
|
+
clearExisting("before");
|
|
603
|
+
const afterNodes = buildNodes(content[CUSTOM_CODE_AFTER_HEAD_KEY], "after");
|
|
604
|
+
if (afterNodes.length > 0) document.head.prepend(...afterNodes);
|
|
605
|
+
const beforeNodes = buildNodes(content[CUSTOM_CODE_BEFORE_HEAD_KEY], "before");
|
|
606
|
+
if (beforeNodes.length > 0) document.head.append(...beforeNodes);
|
|
607
|
+
}
|
|
608
|
+
|
|
575
609
|
// src/lib/section-styles.ts
|
|
576
610
|
var STYLE_STORE_KEY = "__ohw_styles";
|
|
577
611
|
var STYLE_SHEET_ID = "ohw-section-styles";
|
|
@@ -2405,7 +2439,11 @@ function MediaStripBlock({ node, ctx, path }) {
|
|
|
2405
2439
|
const justify = align === "left" ? "flex-start" : align === "right" ? "flex-end" : "center";
|
|
2406
2440
|
const label = str(slots.label);
|
|
2407
2441
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { "data-ohw-media-strip": "", style: { display: "flex", flexDirection: "column", gap: AI_TREE_TOKENS.spacing6 }, children: [
|
|
2408
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", {
|
|
2442
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", {
|
|
2443
|
+
// Host sites often style `a:hover{opacity}` globally — that would fade every linked item
|
|
2444
|
+
// whatever preset is chosen, so the anchors here opt out and only the preset applies.
|
|
2445
|
+
children: '[data-ohw-media-strip] a,[data-ohw-media-strip] a:hover{opacity:1}[data-ohw-media-strip-item]{transition:transform 0.2s ease, opacity 0.2s ease}[data-ohw-media-strip-hover="lift"]:hover{transform:translateY(-4px)}[data-ohw-media-strip-hover="zoom"]:hover{transform:scale(1.05)}[data-ohw-media-strip-hover="fade"]:hover{opacity:0.75}'
|
|
2446
|
+
}),
|
|
2409
2447
|
label && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2410
2448
|
"div",
|
|
2411
2449
|
{
|
|
@@ -2430,7 +2468,7 @@ function MediaStripBlock({ node, ctx, path }) {
|
|
|
2430
2468
|
},
|
|
2431
2469
|
children: items.map((item, i) => {
|
|
2432
2470
|
const hasLink = typeof item.href === "string" && item.href.length > 0;
|
|
2433
|
-
const hoverPreset = slots.hover === "none" || slots.hover === "lift" || slots.hover === "zoom" || slots.hover === "fade" ? slots.hover :
|
|
2471
|
+
const hoverPreset = !hasLink ? "none" : slots.hover === "none" || slots.hover === "lift" || slots.hover === "zoom" || slots.hover === "fade" ? slots.hover : "lift";
|
|
2434
2472
|
const box = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2435
2473
|
"div",
|
|
2436
2474
|
{
|
|
@@ -2460,8 +2498,8 @@ function MediaStripBlock({ node, ctx, path }) {
|
|
|
2460
2498
|
"a",
|
|
2461
2499
|
{
|
|
2462
2500
|
href: item.href,
|
|
2463
|
-
target: item.linkTarget === "
|
|
2464
|
-
rel: item.linkTarget === "
|
|
2501
|
+
target: item.linkTarget === "same-tab" ? void 0 : "_blank",
|
|
2502
|
+
rel: item.linkTarget === "same-tab" ? void 0 : "noopener noreferrer",
|
|
2465
2503
|
style: { display: "block", textDecoration: "none" },
|
|
2466
2504
|
children: box
|
|
2467
2505
|
},
|
|
@@ -10163,6 +10201,22 @@ function setMediaStripItemAlt(tree, index, alt) {
|
|
|
10163
10201
|
return true;
|
|
10164
10202
|
});
|
|
10165
10203
|
}
|
|
10204
|
+
function setMediaStripItemLink(tree, index, link) {
|
|
10205
|
+
return withMediaStrip(tree, (block) => {
|
|
10206
|
+
const items = block.items;
|
|
10207
|
+
if (index < 0 || index >= items.length) return false;
|
|
10208
|
+
const item = { ...items[index] };
|
|
10209
|
+
if (link.href) {
|
|
10210
|
+
item.href = link.href;
|
|
10211
|
+
if (link.linkTarget) item.linkTarget = link.linkTarget;
|
|
10212
|
+
} else {
|
|
10213
|
+
delete item.href;
|
|
10214
|
+
delete item.linkTarget;
|
|
10215
|
+
}
|
|
10216
|
+
items[index] = item;
|
|
10217
|
+
return true;
|
|
10218
|
+
});
|
|
10219
|
+
}
|
|
10166
10220
|
|
|
10167
10221
|
// src/ui/ai-section/AiMediaStripOverlay.tsx
|
|
10168
10222
|
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
@@ -10368,6 +10422,88 @@ var TREATMENTS = [
|
|
|
10368
10422
|
{ value: "color", label: "Color" },
|
|
10369
10423
|
{ value: "grayscale", label: "Grayscale" }
|
|
10370
10424
|
];
|
|
10425
|
+
var HTTP_URL_RE = /^https?:\/\/\S+$/i;
|
|
10426
|
+
function LinkInput({ value, onCommit }) {
|
|
10427
|
+
const [draft, setDraft] = (0, import_react9.useState)(value);
|
|
10428
|
+
const [invalid, setInvalid] = (0, import_react9.useState)(false);
|
|
10429
|
+
(0, import_react9.useEffect)(() => {
|
|
10430
|
+
setDraft(value);
|
|
10431
|
+
setInvalid(false);
|
|
10432
|
+
}, [value]);
|
|
10433
|
+
const commit = () => {
|
|
10434
|
+
const next = draft.trim();
|
|
10435
|
+
if (next === value) return setInvalid(false);
|
|
10436
|
+
if (next && !HTTP_URL_RE.test(next)) return setInvalid(true);
|
|
10437
|
+
setInvalid(false);
|
|
10438
|
+
onCommit(next);
|
|
10439
|
+
};
|
|
10440
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
10441
|
+
"div",
|
|
10442
|
+
{
|
|
10443
|
+
style: {
|
|
10444
|
+
display: "flex",
|
|
10445
|
+
alignItems: "center",
|
|
10446
|
+
gap: 6,
|
|
10447
|
+
height: 28,
|
|
10448
|
+
padding: "0 12px",
|
|
10449
|
+
borderRadius: 999,
|
|
10450
|
+
background: "#ffffff",
|
|
10451
|
+
width: "100%",
|
|
10452
|
+
maxWidth: 260,
|
|
10453
|
+
boxSizing: "border-box",
|
|
10454
|
+
boxShadow: invalid ? "inset 0 0 0 1.5px #EF4444" : "none"
|
|
10455
|
+
},
|
|
10456
|
+
children: [
|
|
10457
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
10458
|
+
"span",
|
|
10459
|
+
{
|
|
10460
|
+
style: {
|
|
10461
|
+
flex: "0 0 auto",
|
|
10462
|
+
color: OHW_BLUE_DARK,
|
|
10463
|
+
fontSize: 10,
|
|
10464
|
+
fontWeight: 700,
|
|
10465
|
+
textTransform: "uppercase",
|
|
10466
|
+
letterSpacing: 0.4
|
|
10467
|
+
},
|
|
10468
|
+
children: "Link"
|
|
10469
|
+
}
|
|
10470
|
+
),
|
|
10471
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
10472
|
+
"input",
|
|
10473
|
+
{
|
|
10474
|
+
type: "text",
|
|
10475
|
+
inputMode: "url",
|
|
10476
|
+
value: draft,
|
|
10477
|
+
onChange: (e) => setDraft(e.target.value),
|
|
10478
|
+
onBlur: commit,
|
|
10479
|
+
onKeyDown: (e) => {
|
|
10480
|
+
if (e.key === "Enter") e.currentTarget.blur();
|
|
10481
|
+
if (e.key === "Escape") {
|
|
10482
|
+
setDraft(value);
|
|
10483
|
+
setInvalid(false);
|
|
10484
|
+
e.currentTarget.blur();
|
|
10485
|
+
}
|
|
10486
|
+
},
|
|
10487
|
+
placeholder: "https://example.com",
|
|
10488
|
+
"aria-label": "Image link URL",
|
|
10489
|
+
"aria-invalid": invalid,
|
|
10490
|
+
style: {
|
|
10491
|
+
flex: 1,
|
|
10492
|
+
minWidth: 0,
|
|
10493
|
+
border: "none",
|
|
10494
|
+
outline: "none",
|
|
10495
|
+
background: "transparent",
|
|
10496
|
+
fontSize: 12,
|
|
10497
|
+
lineHeight: "16px",
|
|
10498
|
+
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
10499
|
+
color: "#1f2937"
|
|
10500
|
+
}
|
|
10501
|
+
}
|
|
10502
|
+
)
|
|
10503
|
+
]
|
|
10504
|
+
}
|
|
10505
|
+
);
|
|
10506
|
+
}
|
|
10371
10507
|
function MediaStripToolbar({
|
|
10372
10508
|
entry,
|
|
10373
10509
|
index,
|
|
@@ -10379,6 +10515,7 @@ function MediaStripToolbar({
|
|
|
10379
10515
|
onSetTreatment,
|
|
10380
10516
|
onResize,
|
|
10381
10517
|
onSetAlt,
|
|
10518
|
+
onSetLink,
|
|
10382
10519
|
onAddItem,
|
|
10383
10520
|
onRemoveItem,
|
|
10384
10521
|
onChangeImage,
|
|
@@ -10388,10 +10525,12 @@ function MediaStripToolbar({
|
|
|
10388
10525
|
const items = mediaStripItems(entry.tree);
|
|
10389
10526
|
const itemCount = items.length;
|
|
10390
10527
|
const currentAlt = items[index]?.alt ?? "";
|
|
10528
|
+
const currentHref = items[index]?.href ?? "";
|
|
10529
|
+
const currentTarget = items[index]?.linkTarget === "same-tab" ? "same-tab" : "new-tab";
|
|
10391
10530
|
const slots = findMediaStripSlots(entry.tree);
|
|
10392
10531
|
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
10393
10532
|
const align = slots?.align === "left" || slots?.align === "right" ? slots.align : "center";
|
|
10394
|
-
const hover = slots?.hover === "none" || slots?.hover === "lift" || slots?.hover === "zoom" || slots?.hover === "fade" ? slots.hover : "
|
|
10533
|
+
const hover = slots?.hover === "none" || slots?.hover === "lift" || slots?.hover === "zoom" || slots?.hover === "fade" ? slots.hover : "lift";
|
|
10395
10534
|
const treatment = slots?.treatment === "color" || slots?.treatment === "grayscale" ? slots.treatment : variant === "logos" ? "grayscale" : "color";
|
|
10396
10535
|
const sizeValue = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
10397
10536
|
const isMobile = window.innerWidth <= 480;
|
|
@@ -10442,6 +10581,11 @@ function MediaStripToolbar({
|
|
|
10442
10581
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Pill, { label: "+", onClick: () => onResize(8) })
|
|
10443
10582
|
] }),
|
|
10444
10583
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { display: "flex", justifyContent: "center", width: "100%" }, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(AltInput, { value: currentAlt, onCommit: onSetAlt }) }),
|
|
10584
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { display: "flex", justifyContent: "center", width: "100%" }, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(LinkInput, { value: currentHref, onCommit: (href) => onSetLink(href, currentTarget) }) }),
|
|
10585
|
+
currentHref && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: rowStyle, children: [
|
|
10586
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Pill, { label: "New tab", active: currentTarget === "new-tab", onClick: () => onSetLink(currentHref, "new-tab") }),
|
|
10587
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Pill, { label: "Same tab", active: currentTarget === "same-tab", onClick: () => onSetLink(currentHref, "same-tab") })
|
|
10588
|
+
] }),
|
|
10445
10589
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: rowStyle, children: [
|
|
10446
10590
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Pill, { label: "Change Image", onClick: onChangeImage }),
|
|
10447
10591
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Pill, { label: "+ Item", onClick: onAddItem }),
|
|
@@ -10637,6 +10781,12 @@ function AiMediaStripOverlay({
|
|
|
10637
10781
|
onSetAlt: (alt) => {
|
|
10638
10782
|
void runMutation(active.sectionId, (tree) => setMediaStripItemAlt(tree, active.index, alt));
|
|
10639
10783
|
},
|
|
10784
|
+
onSetLink: (href, linkTarget) => {
|
|
10785
|
+
void runMutation(
|
|
10786
|
+
active.sectionId,
|
|
10787
|
+
(tree) => setMediaStripItemLink(tree, active.index, href ? { href, linkTarget } : {})
|
|
10788
|
+
);
|
|
10789
|
+
},
|
|
10640
10790
|
onAddItem: () => {
|
|
10641
10791
|
void requestAssetPick(postToParent2).then((picked) => {
|
|
10642
10792
|
if (!picked) return;
|
|
@@ -22206,6 +22356,7 @@ function OhhwellsBridge() {
|
|
|
22206
22356
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
22207
22357
|
}
|
|
22208
22358
|
applyBrandChrome(content);
|
|
22359
|
+
applyCustomCodeToHead(content);
|
|
22209
22360
|
initSectionInstancesFromContent(content, window.location.pathname);
|
|
22210
22361
|
for (const [key, val] of Object.entries(content)) {
|
|
22211
22362
|
if (key === "__ohw_sections") continue;
|
|
@@ -22215,6 +22366,7 @@ function OhhwellsBridge() {
|
|
|
22215
22366
|
if (key === BRAND_KIT_KEY) continue;
|
|
22216
22367
|
if (key === STYLE_STORE_KEY) continue;
|
|
22217
22368
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
22369
|
+
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
22218
22370
|
if (applyVideoSettingNode(key, val)) continue;
|
|
22219
22371
|
if (applyCarouselNode(key, val)) continue;
|
|
22220
22372
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -24626,6 +24778,7 @@ function OhhwellsBridge() {
|
|
|
24626
24778
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
24627
24779
|
}
|
|
24628
24780
|
applyBrandChrome(content);
|
|
24781
|
+
applyCustomCodeToHead(content);
|
|
24629
24782
|
initSectionInstancesFromContent(content, window.location.pathname);
|
|
24630
24783
|
let sectionsJson = null;
|
|
24631
24784
|
for (const [key, val] of Object.entries(content)) {
|
|
@@ -24639,6 +24792,7 @@ function OhhwellsBridge() {
|
|
|
24639
24792
|
if (key === BRAND_KIT_KEY) continue;
|
|
24640
24793
|
if (key === STYLE_STORE_KEY) continue;
|
|
24641
24794
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
24795
|
+
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
24642
24796
|
if (applyVideoSettingNode(key, val)) continue;
|
|
24643
24797
|
if (applyCarouselNode(key, val)) continue;
|
|
24644
24798
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -25356,6 +25510,16 @@ function OhhwellsBridge() {
|
|
|
25356
25510
|
if (brandKitRef.current) {
|
|
25357
25511
|
nodes.push({ key: BRAND_KIT_KEY, type: "brand", text: brandKitRef.current });
|
|
25358
25512
|
}
|
|
25513
|
+
nodes.push({
|
|
25514
|
+
key: CUSTOM_CODE_BEFORE_HEAD_KEY,
|
|
25515
|
+
type: "text",
|
|
25516
|
+
text: editContentRef.current[CUSTOM_CODE_BEFORE_HEAD_KEY] ?? ""
|
|
25517
|
+
});
|
|
25518
|
+
nodes.push({
|
|
25519
|
+
key: CUSTOM_CODE_AFTER_HEAD_KEY,
|
|
25520
|
+
type: "text",
|
|
25521
|
+
text: editContentRef.current[CUSTOM_CODE_AFTER_HEAD_KEY] ?? ""
|
|
25522
|
+
});
|
|
25359
25523
|
document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
|
|
25360
25524
|
const formKey = formKeyOf(form);
|
|
25361
25525
|
if (!formKey) return;
|