@ohhwells/bridge 0.1.157 → 0.1.158-next.422
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/README.md +1 -1
- package/dist/index.cjs +970 -714
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -1
- package/dist/index.d.ts +31 -1
- package/dist/index.js +1006 -736
- package/dist/index.js.map +1 -1
- package/dist/pages.cjs +10 -2
- package/dist/pages.cjs.map +1 -1
- package/dist/pages.d.cts +2 -0
- package/dist/pages.d.ts +2 -0
- package/dist/pages.js +10 -2
- package/dist/pages.js.map +1 -1
- package/dist/styles.css +116 -0
- package/package.json +4 -3
package/dist/index.cjs
CHANGED
|
@@ -64,6 +64,7 @@ __export(index_exports, {
|
|
|
64
64
|
OhwLoaderSurface: () => OhwLoaderSurface,
|
|
65
65
|
SITE_OG_IMAGE_KEY: () => SITE_OG_IMAGE_KEY,
|
|
66
66
|
SchedulingWidget: () => SchedulingWidget,
|
|
67
|
+
TEMPLATE_LOGO_ATTR: () => TEMPLATE_LOGO_ATTR,
|
|
67
68
|
Toggle: () => Toggle,
|
|
68
69
|
ToggleGroup: () => ToggleGroup,
|
|
69
70
|
ToggleGroupItem: () => ToggleGroupItem,
|
|
@@ -97,6 +98,7 @@ __export(index_exports, {
|
|
|
97
98
|
parseAiSectionsState: () => parseAiSectionsState,
|
|
98
99
|
parseTarget: () => parseTarget,
|
|
99
100
|
recordOverriddenPaths: () => recordOverriddenPaths,
|
|
101
|
+
releaseTemplateLogoIfReplaced: () => releaseTemplateLogoIfReplaced,
|
|
100
102
|
removeFooterBlock: () => removeFooterBlock,
|
|
101
103
|
resetOverriddenPathsCache: () => resetOverriddenPathsCache,
|
|
102
104
|
resolveFooterCopyright: () => resolveFooterCopyright,
|
|
@@ -518,11 +520,37 @@ function logoTextElement(root) {
|
|
|
518
520
|
);
|
|
519
521
|
return hasOwnText ? root : null;
|
|
520
522
|
}
|
|
523
|
+
var TEMPLATE_LOGO_ATTR = "data-ohw-template-logo";
|
|
524
|
+
function releaseTemplateLogoIfReplaced(img, url) {
|
|
525
|
+
if (!img.hasAttribute(TEMPLATE_LOGO_ATTR)) return;
|
|
526
|
+
let incoming = url;
|
|
527
|
+
try {
|
|
528
|
+
incoming = new URL(url, document.baseURI).href;
|
|
529
|
+
} catch {
|
|
530
|
+
}
|
|
531
|
+
if (incoming !== img.src) img.removeAttribute(TEMPLATE_LOGO_ATTR);
|
|
532
|
+
}
|
|
533
|
+
function logoImage(root, selector) {
|
|
534
|
+
if (root instanceof HTMLImageElement && root.matches(selector)) return root;
|
|
535
|
+
return root.querySelector(selector);
|
|
536
|
+
}
|
|
521
537
|
function logoRootImage(root) {
|
|
522
|
-
const img = root
|
|
538
|
+
const img = logoImage(root, `img:not([${TEMPLATE_LOGO_ATTR}])`);
|
|
523
539
|
const src = img?.getAttribute("src")?.trim() ?? "";
|
|
524
540
|
return img && src && img.style.display !== "none" ? img : null;
|
|
525
541
|
}
|
|
542
|
+
function templateLogoImage(root) {
|
|
543
|
+
const img = logoImage(root, `img[${TEMPLATE_LOGO_ATTR}]`);
|
|
544
|
+
return img && img.style.display !== "none" ? img : null;
|
|
545
|
+
}
|
|
546
|
+
function createWordmark(root) {
|
|
547
|
+
const el = document.createElement("span");
|
|
548
|
+
el.setAttribute("data-ohw-editable", "plain");
|
|
549
|
+
el.setAttribute("data-ohw-key", textKeyForRoot(root));
|
|
550
|
+
if (root instanceof HTMLImageElement) root.parentNode?.insertBefore(el, root.nextSibling);
|
|
551
|
+
else root.appendChild(el);
|
|
552
|
+
return el;
|
|
553
|
+
}
|
|
526
554
|
function applyLogoIdentity(text, isPlaceholder) {
|
|
527
555
|
const display = resolveLogoDisplayText(text);
|
|
528
556
|
const placeholder = isPlaceholder || !text.trim() || display === PLACEHOLDER_BUSINESS_NAME;
|
|
@@ -541,7 +569,9 @@ function applyLogoIdentity(text, isPlaceholder) {
|
|
|
541
569
|
if (placeholder) el.setAttribute("data-ohw-placeholder", "");
|
|
542
570
|
else el.removeAttribute("data-ohw-placeholder");
|
|
543
571
|
if (logoRootImage(el)) return;
|
|
544
|
-
const
|
|
572
|
+
const templateMark = placeholder ? null : templateLogoImage(el);
|
|
573
|
+
if (templateMark) templateMark.style.display = "none";
|
|
574
|
+
const textEl = logoTextElement(el) ?? (templateMark ? createWordmark(el) : null);
|
|
545
575
|
if (textEl && textEl.textContent !== display) textEl.textContent = display;
|
|
546
576
|
});
|
|
547
577
|
return display;
|
|
@@ -573,6 +603,7 @@ function applyLogoImage(url, alt, placement) {
|
|
|
573
603
|
}
|
|
574
604
|
img.removeAttribute("srcset");
|
|
575
605
|
img.removeAttribute("sizes");
|
|
606
|
+
img.removeAttribute(TEMPLATE_LOGO_ATTR);
|
|
576
607
|
img.src = url;
|
|
577
608
|
img.alt = displayAlt;
|
|
578
609
|
img.style.display = "block";
|
|
@@ -592,10 +623,7 @@ function applyLogoImage(url, alt, placement) {
|
|
|
592
623
|
img.style.display = "none";
|
|
593
624
|
}
|
|
594
625
|
if (!textEl) {
|
|
595
|
-
textEl =
|
|
596
|
-
textEl.setAttribute("data-ohw-editable", "plain");
|
|
597
|
-
textEl.setAttribute("data-ohw-key", textKey);
|
|
598
|
-
root.appendChild(textEl);
|
|
626
|
+
textEl = createWordmark(root);
|
|
599
627
|
}
|
|
600
628
|
textEl.style.display = "";
|
|
601
629
|
if (textEl.textContent !== displayAlt) textEl.textContent = displayAlt;
|
|
@@ -6654,6 +6682,21 @@ function pricingCardFeatureCount(tree, index) {
|
|
|
6654
6682
|
const target = findPricingCollection(tree)?.children?.[index];
|
|
6655
6683
|
return target ? pricingFeatureList(target).length : 0;
|
|
6656
6684
|
}
|
|
6685
|
+
function prevailingFeatureIcon(features) {
|
|
6686
|
+
const counts = /* @__PURE__ */ new Map();
|
|
6687
|
+
for (const row of features) {
|
|
6688
|
+
const key = `${row.icon ?? ""}|${row.iconColor ?? ""}`;
|
|
6689
|
+
const entry = counts.get(key) ?? { count: 0, ...row.icon ? { icon: row.icon } : {}, ...row.iconColor ? { iconColor: row.iconColor } : {} };
|
|
6690
|
+
entry.count += 1;
|
|
6691
|
+
counts.set(key, entry);
|
|
6692
|
+
}
|
|
6693
|
+
let best = null;
|
|
6694
|
+
for (const entry of counts.values()) {
|
|
6695
|
+
if (!best || entry.count > best.count) best = entry;
|
|
6696
|
+
}
|
|
6697
|
+
if (!best) return {};
|
|
6698
|
+
return { ...best.icon ? { icon: best.icon } : {}, ...best.iconColor ? { iconColor: best.iconColor } : {} };
|
|
6699
|
+
}
|
|
6657
6700
|
function addPricingCardFeature(tree, index, text) {
|
|
6658
6701
|
return withPricingCollection(tree, (collection) => {
|
|
6659
6702
|
const children = collection.children;
|
|
@@ -6662,7 +6705,7 @@ function addPricingCardFeature(tree, index, text) {
|
|
|
6662
6705
|
const features = pricingFeatureList(target);
|
|
6663
6706
|
if (features.length >= PRICING_FEATURES_MAX) return false;
|
|
6664
6707
|
target.slots = target.slots ?? {};
|
|
6665
|
-
target.slots.features = [...features, { text }];
|
|
6708
|
+
target.slots.features = [...features, { text, ...prevailingFeatureIcon(features) }];
|
|
6666
6709
|
return true;
|
|
6667
6710
|
});
|
|
6668
6711
|
}
|
|
@@ -6849,6 +6892,7 @@ function applyBrandChrome(content) {
|
|
|
6849
6892
|
if (el.textContent !== name) el.textContent = name;
|
|
6850
6893
|
if (el.getAttribute("title") !== name) el.setAttribute("title", name);
|
|
6851
6894
|
});
|
|
6895
|
+
applyLogoIdentity(name, false);
|
|
6852
6896
|
}
|
|
6853
6897
|
const title = content[BRAND_TITLE_KEY];
|
|
6854
6898
|
if (typeof title === "string" && title.length > 0) {
|
|
@@ -7861,7 +7905,7 @@ var AI_MOBILE_CSS = [
|
|
|
7861
7905
|
// page's first section. Top only (bottom needs no nav clearance); ~96px approximates the
|
|
7862
7906
|
// template nav's own height (measured ~94px) — there's no shared `--ohw-header-h` var to read
|
|
7863
7907
|
// an exact figure from (no live measurement exists), so this is a safe approximation, not a
|
|
7864
|
-
// pixel-exact fit. Horizontal spacing already comes from `data-ai-
|
|
7908
|
+
// pixel-exact fit. Horizontal spacing already comes from `data-ai-section-inner`.
|
|
7865
7909
|
'[data-ai-overlay-clearance] [data-ai-overlap-layer="overlay"]{padding-top:96px}',
|
|
7866
7910
|
// A full-bleed carousel's height is pure arithmetic: it spans the whole window, so 16/9 turns
|
|
7867
7911
|
// window width straight into height. Measured at 16/9 it came out ~90% of the viewport at EVERY
|
|
@@ -7877,8 +7921,10 @@ var AI_MOBILE_CSS = [
|
|
|
7877
7921
|
"[data-ai-section]{overflow-x:hidden}",
|
|
7878
7922
|
// `:not([data-ai-full-bleed])`: this `!important` gutter beat the inline `padding: 0` that a
|
|
7879
7923
|
// full-bleed section's container sets, so a carousel/media hero that is edge-to-edge on desktop
|
|
7880
|
-
// still got a 20px band of section background down both sides on a phone.
|
|
7881
|
-
|
|
7924
|
+
// still got a 20px band of section background down both sides on a phone. The footer's own
|
|
7925
|
+
// container keeps the unguarded rule below — `data-ai-full-bleed` can never appear on it.
|
|
7926
|
+
"[data-ai-section-inner]:not([data-ai-full-bleed]){padding:0 20px !important}",
|
|
7927
|
+
"[data-ai-container]{padding:0 20px !important}",
|
|
7882
7928
|
"[data-ai-row]{display:flex !important;flex-direction:column !important;align-items:stretch !important}",
|
|
7883
7929
|
"[data-ai-cell]{width:100%;min-width:0}",
|
|
7884
7930
|
// The rule above turns every row into a COLUMN flex container on phones, which silently breaks
|
|
@@ -8083,6 +8129,31 @@ function pricingCardEmphasis(featured, ctx, hasBg) {
|
|
|
8083
8129
|
function textAttrs(ctx, path) {
|
|
8084
8130
|
return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
|
|
8085
8131
|
}
|
|
8132
|
+
var AI_RESPONSIVE_CSS = [
|
|
8133
|
+
"@media (max-width: 960px) {",
|
|
8134
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: repeat(2, 1fr) !important; }",
|
|
8135
|
+
' [data-ai-responsive] [data-ai-grid="1"] { grid-template-columns: 1fr !important; }',
|
|
8136
|
+
"}",
|
|
8137
|
+
"@media (max-width: 640px) {",
|
|
8138
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
|
|
8139
|
+
" [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
|
|
8140
|
+
// Group containers flatten to a column on phones; span placements come along for free.
|
|
8141
|
+
// `:not([data-ai-group="overlap"])` for the same reason as the twin pair in AI_MOBILE_CSS — see
|
|
8142
|
+
// the comment there. This sheet's copy is the narrower selector, so without the exemption it
|
|
8143
|
+
// flattens an `overlap` hero below 640px even though the other rule stands down: measured a 390px
|
|
8144
|
+
// viewport with the heading/CTA in flow *under* the image, 219px of section background where the
|
|
8145
|
+
// layered text used to be.
|
|
8146
|
+
' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) { display: flex !important; flex-direction: column !important; }',
|
|
8147
|
+
' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) > * { grid-column: auto !important; }',
|
|
8148
|
+
// `:not([data-ai-full-bleed])` for the same reason as the twin rule in AI_MOBILE_CSS: this one
|
|
8149
|
+
// is narrower (0,2,0 vs 0,1,0) and also `!important`, so without the guard it wins outright and
|
|
8150
|
+
// a full-bleed hero gets its 20px side band back below 640px only — the one width where the
|
|
8151
|
+
// other rule had already been taught to stand down.
|
|
8152
|
+
" [data-ai-responsive] [data-ai-section-inner]:not([data-ai-full-bleed]) { padding-left: 20px !important; padding-right: 20px !important; }",
|
|
8153
|
+
" [data-ai-responsive] { overflow-x: hidden; }",
|
|
8154
|
+
" [data-ai-responsive] img { max-width: 100%; }",
|
|
8155
|
+
"}"
|
|
8156
|
+
].join("\n");
|
|
8086
8157
|
var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
8087
8158
|
function MediaBox({
|
|
8088
8159
|
refValue,
|
|
@@ -8137,7 +8208,7 @@ function MediaBox({
|
|
|
8137
8208
|
position: fill ? "absolute" : void 0,
|
|
8138
8209
|
inset: fill ? 0 : void 0,
|
|
8139
8210
|
width: fill ? "100%" : fixedSize ? "auto" : "100%",
|
|
8140
|
-
height: fill ? "100%" : void 0,
|
|
8211
|
+
height: fill ? "100%" : fixedSize ? height : void 0,
|
|
8141
8212
|
aspectRatio: fill ? void 0 : aspectRatio,
|
|
8142
8213
|
minHeight: fill || fixedSize ? void 0 : height ?? (aspectRatio ? void 0 : 180),
|
|
8143
8214
|
borderRadius: radius,
|
|
@@ -9633,7 +9704,7 @@ function CollectionBlock({ node, ctx, path }) {
|
|
|
9633
9704
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
9634
9705
|
"div",
|
|
9635
9706
|
{
|
|
9636
|
-
"data-ai-grid":
|
|
9707
|
+
"data-ai-grid": String(itemsPerRow),
|
|
9637
9708
|
"data-ohw-pricing-collection": isPricing ? "" : void 0,
|
|
9638
9709
|
style: {
|
|
9639
9710
|
display: "grid",
|
|
@@ -9935,7 +10006,7 @@ function renderNode(node, ctx, path, ambientAlign) {
|
|
|
9935
10006
|
},
|
|
9936
10007
|
children: [
|
|
9937
10008
|
i > 0 && ctx.heroOverlapFullBleed ? (
|
|
9938
|
-
// The section's `data-ai-
|
|
10009
|
+
// The section's `data-ai-section-inner` gave up its max-width/gutter so the base
|
|
9939
10010
|
// layer (this group's i===0 sibling) can span edge-to-edge — reintroduced here,
|
|
9940
10011
|
// scoped to just the overlay text, so a heading/copy/CTA stack doesn't stretch
|
|
9941
10012
|
// the full section width instead of reading at the usual content width.
|
|
@@ -10354,6 +10425,7 @@ function AiTreeRenderer({
|
|
|
10354
10425
|
...fillHeight ? { "data-ai-fill-height": "" } : {},
|
|
10355
10426
|
...needsOverlayClearance ? { "data-ai-overlay-clearance": "" } : {},
|
|
10356
10427
|
...bgAttrs,
|
|
10428
|
+
"data-ai-responsive": "",
|
|
10357
10429
|
style: {
|
|
10358
10430
|
position: "relative",
|
|
10359
10431
|
padding: `${padCss} 0`,
|
|
@@ -10367,12 +10439,13 @@ function AiTreeRenderer({
|
|
|
10367
10439
|
...fillHeight ? { display: "grid" } : {}
|
|
10368
10440
|
},
|
|
10369
10441
|
children: [
|
|
10370
|
-
|
|
10442
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_RESPONSIVE_CSS }),
|
|
10371
10443
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_MOBILE_CSS }),
|
|
10444
|
+
isOverlay && backgroundUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { position: "absolute", inset: 0, background: `rgba(255,255,255,${overlayAlpha})` } }),
|
|
10372
10445
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
10373
10446
|
"div",
|
|
10374
10447
|
{
|
|
10375
|
-
"data-ai-
|
|
10448
|
+
"data-ai-section-inner": "",
|
|
10376
10449
|
...fullBleedMedia ? { "data-ai-full-bleed": "" } : {},
|
|
10377
10450
|
style: {
|
|
10378
10451
|
position: "relative",
|
|
@@ -10389,7 +10462,7 @@ function AiTreeRenderer({
|
|
|
10389
10462
|
children: tree.rows.map((row, r2) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
10390
10463
|
"div",
|
|
10391
10464
|
{
|
|
10392
|
-
"data-ai-
|
|
10465
|
+
"data-ai-columns": "",
|
|
10393
10466
|
style: {
|
|
10394
10467
|
display: "grid",
|
|
10395
10468
|
gridTemplateColumns: "repeat(12, 1fr)",
|
|
@@ -11051,9 +11124,10 @@ function applyAiSectionsToDom(state, options) {
|
|
|
11051
11124
|
if (existing && existing.serialized === serialized && existing.container.isConnected) {
|
|
11052
11125
|
continue;
|
|
11053
11126
|
}
|
|
11054
|
-
const isNewMount = !existing || !existing.container.isConnected;
|
|
11055
11127
|
let container = existing?.container;
|
|
11128
|
+
let isNewMount = false;
|
|
11056
11129
|
if (!container || !container.isConnected) {
|
|
11130
|
+
isNewMount = true;
|
|
11057
11131
|
existing?.root.unmount();
|
|
11058
11132
|
container?.remove();
|
|
11059
11133
|
container = document.createElement("div");
|
|
@@ -17212,7 +17286,7 @@ function apiBase() {
|
|
|
17212
17286
|
function bridgeVersion() {
|
|
17213
17287
|
try {
|
|
17214
17288
|
if (true) {
|
|
17215
|
-
return "0.1.
|
|
17289
|
+
return "0.1.158-next.422";
|
|
17216
17290
|
}
|
|
17217
17291
|
} catch {
|
|
17218
17292
|
}
|
|
@@ -17226,7 +17300,7 @@ function stampBridgeVersionOnDocument() {
|
|
|
17226
17300
|
return;
|
|
17227
17301
|
}
|
|
17228
17302
|
try {
|
|
17229
|
-
const v = true ? "0.1.
|
|
17303
|
+
const v = true ? "0.1.158-next.422" : "";
|
|
17230
17304
|
if (v) {
|
|
17231
17305
|
document.documentElement.setAttribute("data-ohw-bridge-version", v);
|
|
17232
17306
|
window.__OHW_BRIDGE_VERSION__ = v;
|
|
@@ -17904,6 +17978,7 @@ function MediaOverlay({
|
|
|
17904
17978
|
(prev) => prev && prev.fullWidth === width && prev.height === height ? prev : { fullWidth: width, height }
|
|
17905
17979
|
);
|
|
17906
17980
|
}, [isVideo]);
|
|
17981
|
+
const replaceLabel = isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image";
|
|
17907
17982
|
const replaceMode = buttonSize ? replaceButtonMode({ width: rect.width, height: rect.height }, buttonSize) : "none";
|
|
17908
17983
|
const box = {
|
|
17909
17984
|
position: "fixed",
|
|
@@ -18002,11 +18077,10 @@ function MediaOverlay({
|
|
|
18002
18077
|
className: "flex items-center justify-center cursor-pointer",
|
|
18003
18078
|
style: {
|
|
18004
18079
|
...box,
|
|
18005
|
-
//
|
|
18006
|
-
//
|
|
18007
|
-
//
|
|
18008
|
-
|
|
18009
|
-
pointerEvents: hover.hasTextOverlap || cueOnly ? "none" : "auto",
|
|
18080
|
+
// Visual only. `pointer-events: auto` on this full-bleed rect covered the navbar
|
|
18081
|
+
// (hero bg includes the absolute TopNav) and swallowed CTA press-drag. Text overlay
|
|
18082
|
+
// and cueOnly also need clicks to fall through — Replace / video controls opt back in.
|
|
18083
|
+
pointerEvents: "none",
|
|
18010
18084
|
// Selected: a firm component ring with no wash, so the image reads as chosen rather
|
|
18011
18085
|
// than hovered. Hover keeps the existing tinted preview.
|
|
18012
18086
|
boxShadow: selected ? "inset 0 0 0 2px var(--color-bridge-primary)" : "inset 0 0 0 1.5px var(--color-bridge-primary)",
|
|
@@ -18033,17 +18107,17 @@ function MediaOverlay({
|
|
|
18033
18107
|
},
|
|
18034
18108
|
children: [
|
|
18035
18109
|
isVideo ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react5.Film, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react5.ImageIcon, { size: 14 }),
|
|
18036
|
-
|
|
18110
|
+
replaceLabel
|
|
18037
18111
|
]
|
|
18038
18112
|
}
|
|
18039
18113
|
),
|
|
18040
|
-
replaceMode
|
|
18114
|
+
showChrome && replaceMode !== "none" && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
18041
18115
|
Button,
|
|
18042
18116
|
{
|
|
18043
18117
|
"data-ohw-media-overlay": "",
|
|
18044
18118
|
variant: "outline",
|
|
18045
18119
|
size: "sm",
|
|
18046
|
-
"aria-label":
|
|
18120
|
+
"aria-label": replaceLabel,
|
|
18047
18121
|
className: "gap-1.5 cursor-pointer hover:bg-background",
|
|
18048
18122
|
style: {
|
|
18049
18123
|
...OVERLAY_BUTTON_STYLE,
|
|
@@ -18066,7 +18140,7 @@ function MediaOverlay({
|
|
|
18066
18140
|
},
|
|
18067
18141
|
children: [
|
|
18068
18142
|
isVideo ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react5.Film, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react5.ImageIcon, { size: 14 }),
|
|
18069
|
-
replaceMode === "full" ?
|
|
18143
|
+
replaceMode === "full" ? replaceLabel : null
|
|
18070
18144
|
]
|
|
18071
18145
|
}
|
|
18072
18146
|
)
|
|
@@ -18576,7 +18650,7 @@ function AiSectionOverlay({
|
|
|
18576
18650
|
|
|
18577
18651
|
// src/ui/ai-section/AiMediaStripOverlay.tsx
|
|
18578
18652
|
var import_react10 = require("react");
|
|
18579
|
-
var
|
|
18653
|
+
var import_lucide_react9 = require("lucide-react");
|
|
18580
18654
|
|
|
18581
18655
|
// src/lib/ai-media-strip-tree.ts
|
|
18582
18656
|
var MEDIA_STRIP_ITEM_MIN = 1;
|
|
@@ -18690,14 +18764,6 @@ function setMediaStripItemAsset(tree, index, assetId) {
|
|
|
18690
18764
|
return true;
|
|
18691
18765
|
});
|
|
18692
18766
|
}
|
|
18693
|
-
function setMediaStripItemAlt(tree, index, alt) {
|
|
18694
|
-
return withMediaStrip(tree, (block) => {
|
|
18695
|
-
const items = block.items;
|
|
18696
|
-
if (index < 0 || index >= items.length) return false;
|
|
18697
|
-
items[index] = { ...items[index], alt };
|
|
18698
|
-
return true;
|
|
18699
|
-
});
|
|
18700
|
-
}
|
|
18701
18767
|
function setMediaStripItemLink(tree, index, link) {
|
|
18702
18768
|
return withMediaStrip(tree, (block) => {
|
|
18703
18769
|
const items = block.items;
|
|
@@ -18715,11 +18781,117 @@ function setMediaStripItemLink(tree, index, link) {
|
|
|
18715
18781
|
});
|
|
18716
18782
|
}
|
|
18717
18783
|
|
|
18718
|
-
// src/ui/
|
|
18784
|
+
// src/ui/dialog.tsx
|
|
18785
|
+
var React9 = __toESM(require("react"), 1);
|
|
18786
|
+
var import_radix_ui6 = require("radix-ui");
|
|
18787
|
+
var import_lucide_react8 = require("lucide-react");
|
|
18719
18788
|
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
18720
|
-
|
|
18721
|
-
|
|
18722
|
-
|
|
18789
|
+
function Dialog2({
|
|
18790
|
+
...props
|
|
18791
|
+
}) {
|
|
18792
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_radix_ui6.Dialog.Root, { "data-slot": "dialog", ...props });
|
|
18793
|
+
}
|
|
18794
|
+
function DialogPortal({
|
|
18795
|
+
...props
|
|
18796
|
+
}) {
|
|
18797
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_radix_ui6.Dialog.Portal, { ...props });
|
|
18798
|
+
}
|
|
18799
|
+
function DialogOverlay({
|
|
18800
|
+
className,
|
|
18801
|
+
...props
|
|
18802
|
+
}) {
|
|
18803
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18804
|
+
import_radix_ui6.Dialog.Overlay,
|
|
18805
|
+
{
|
|
18806
|
+
"data-slot": "dialog-overlay",
|
|
18807
|
+
"data-ohw-link-modal-root": "",
|
|
18808
|
+
className: cn("fixed inset-0 z-[2147483646] bg-black/50", className),
|
|
18809
|
+
...props
|
|
18810
|
+
}
|
|
18811
|
+
);
|
|
18812
|
+
}
|
|
18813
|
+
var DialogContent = React9.forwardRef(
|
|
18814
|
+
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
18815
|
+
const positionMode = container ? "absolute" : "fixed";
|
|
18816
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(DialogPortal, { container: container ?? void 0, children: [
|
|
18817
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
18818
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
18819
|
+
import_radix_ui6.Dialog.Content,
|
|
18820
|
+
{
|
|
18821
|
+
ref,
|
|
18822
|
+
"data-slot": "dialog-content",
|
|
18823
|
+
className: cn(
|
|
18824
|
+
positionMode,
|
|
18825
|
+
"left-1/2 top-1/2 z-[2147483647] flex w-full max-w-[448px] -translate-x-1/2 -translate-y-1/2 flex-col overflow-visible",
|
|
18826
|
+
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
18827
|
+
container ? "max-h-[calc(100%-32px)]" : "max-h-[calc(100vh-32px)]",
|
|
18828
|
+
className
|
|
18829
|
+
),
|
|
18830
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
18831
|
+
...props,
|
|
18832
|
+
children: [
|
|
18833
|
+
children,
|
|
18834
|
+
showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18835
|
+
import_radix_ui6.Dialog.Close,
|
|
18836
|
+
{
|
|
18837
|
+
type: "button",
|
|
18838
|
+
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
18839
|
+
"aria-label": "Close",
|
|
18840
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react8.X, { size: 16, "aria-hidden": true })
|
|
18841
|
+
}
|
|
18842
|
+
) : null
|
|
18843
|
+
]
|
|
18844
|
+
}
|
|
18845
|
+
)
|
|
18846
|
+
] });
|
|
18847
|
+
}
|
|
18848
|
+
);
|
|
18849
|
+
DialogContent.displayName = import_radix_ui6.Dialog.Content.displayName;
|
|
18850
|
+
function DialogHeader({
|
|
18851
|
+
className,
|
|
18852
|
+
...props
|
|
18853
|
+
}) {
|
|
18854
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
18855
|
+
}
|
|
18856
|
+
function DialogFooter({
|
|
18857
|
+
className,
|
|
18858
|
+
...props
|
|
18859
|
+
}) {
|
|
18860
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18861
|
+
"div",
|
|
18862
|
+
{
|
|
18863
|
+
className: cn("flex items-center justify-end gap-2", className),
|
|
18864
|
+
...props
|
|
18865
|
+
}
|
|
18866
|
+
);
|
|
18867
|
+
}
|
|
18868
|
+
var DialogTitle = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18869
|
+
import_radix_ui6.Dialog.Title,
|
|
18870
|
+
{
|
|
18871
|
+
ref,
|
|
18872
|
+
className: cn(
|
|
18873
|
+
"text-lg font-semibold leading-none tracking-tight text-card-foreground",
|
|
18874
|
+
className
|
|
18875
|
+
),
|
|
18876
|
+
...props
|
|
18877
|
+
}
|
|
18878
|
+
));
|
|
18879
|
+
DialogTitle.displayName = import_radix_ui6.Dialog.Title.displayName;
|
|
18880
|
+
var DialogDescription = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18881
|
+
import_radix_ui6.Dialog.Description,
|
|
18882
|
+
{
|
|
18883
|
+
ref,
|
|
18884
|
+
className: cn("text-sm text-muted-foreground", className),
|
|
18885
|
+
...props
|
|
18886
|
+
}
|
|
18887
|
+
));
|
|
18888
|
+
DialogDescription.displayName = import_radix_ui6.Dialog.Description.displayName;
|
|
18889
|
+
var DialogClose = import_radix_ui6.Dialog.Close;
|
|
18890
|
+
|
|
18891
|
+
// src/ui/ai-section/AiMediaStripOverlay.tsx
|
|
18892
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
18893
|
+
var PRIMARY3 = "var(--ohw-primary, #0885FE)";
|
|
18894
|
+
var CHROME_SELECTOR = "[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-link-modal-root], [data-ohw-section-picker], [data-ohw-ai-review], [data-ohw-more-menu]";
|
|
18723
18895
|
function findMediaStripItemElement(sectionId, index) {
|
|
18724
18896
|
const sectionEl = findByInstanceId(sectionId);
|
|
18725
18897
|
if (!sectionEl) return null;
|
|
@@ -18729,14 +18901,35 @@ function findMediaStripItemElement(sectionId, index) {
|
|
|
18729
18901
|
}
|
|
18730
18902
|
return null;
|
|
18731
18903
|
}
|
|
18732
|
-
function
|
|
18733
|
-
|
|
18904
|
+
function itemRefFromTarget(target) {
|
|
18905
|
+
if (!(target instanceof Element)) return null;
|
|
18906
|
+
if (target.closest(CHROME_SELECTOR)) return null;
|
|
18907
|
+
const itemEl = target.closest("[data-ohw-media-strip-item]");
|
|
18908
|
+
if (!itemEl) return null;
|
|
18909
|
+
const sectionEl = itemEl.closest("[data-ohw-section]");
|
|
18910
|
+
const unit = sectionEl ? movableUnit(sectionEl) : null;
|
|
18911
|
+
const sectionId = unit ? instanceIdOf(unit) || null : null;
|
|
18912
|
+
const index = Number(itemEl.dataset.ohwMediaStripIndex);
|
|
18913
|
+
if (!sectionId || Number.isNaN(index)) return null;
|
|
18914
|
+
return { sectionId, index };
|
|
18915
|
+
}
|
|
18916
|
+
function sameRef(a, b) {
|
|
18917
|
+
return a?.sectionId === b?.sectionId && a?.index === b?.index;
|
|
18918
|
+
}
|
|
18919
|
+
function rectOf(el) {
|
|
18734
18920
|
if (!el) return null;
|
|
18735
18921
|
const r2 = el.getBoundingClientRect();
|
|
18736
18922
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
18737
18923
|
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
18738
18924
|
}
|
|
18739
|
-
function
|
|
18925
|
+
function readRect2(ref) {
|
|
18926
|
+
return rectOf(ref && findMediaStripItemElement(ref.sectionId, ref.index));
|
|
18927
|
+
}
|
|
18928
|
+
function readStripRect(ref) {
|
|
18929
|
+
const item = ref && findMediaStripItemElement(ref.sectionId, ref.index);
|
|
18930
|
+
return rectOf(item?.closest("[data-ohw-media-strip]") ?? item);
|
|
18931
|
+
}
|
|
18932
|
+
function useLiveItemRect(ref, strip = false) {
|
|
18740
18933
|
const [rect, setRect] = (0, import_react10.useState)(null);
|
|
18741
18934
|
(0, import_react10.useEffect)(() => {
|
|
18742
18935
|
if (!ref) {
|
|
@@ -18744,7 +18937,7 @@ function useLiveItemRect(ref) {
|
|
|
18744
18937
|
return;
|
|
18745
18938
|
}
|
|
18746
18939
|
const update = () => {
|
|
18747
|
-
const next = readRect2(ref);
|
|
18940
|
+
const next = strip ? readStripRect(ref) : readRect2(ref);
|
|
18748
18941
|
setRect(
|
|
18749
18942
|
(prev) => prev && next && prev.top === next.top && prev.left === next.left && prev.width === next.width && prev.height === next.height ? prev : next
|
|
18750
18943
|
);
|
|
@@ -18759,9 +18952,49 @@ function useLiveItemRect(ref) {
|
|
|
18759
18952
|
window.removeEventListener("resize", update);
|
|
18760
18953
|
clearInterval(interval);
|
|
18761
18954
|
};
|
|
18762
|
-
}, [ref?.sectionId, ref?.index]);
|
|
18955
|
+
}, [ref?.sectionId, ref?.index, strip]);
|
|
18763
18956
|
return rect;
|
|
18764
18957
|
}
|
|
18958
|
+
var TOOLBAR_STRIP_GAP = 52;
|
|
18959
|
+
var TOOLBAR_STRIP_GAP_MOBILE = 42;
|
|
18960
|
+
var TOOLBAR_EDGE_MARGIN2 = 4;
|
|
18961
|
+
function StripToolbarSlot({ stripRect, children }) {
|
|
18962
|
+
const slotRef = (0, import_react10.useRef)(null);
|
|
18963
|
+
const [shift, setShift] = (0, import_react10.useState)(0);
|
|
18964
|
+
const centerX = stripRect.left + stripRect.width / 2;
|
|
18965
|
+
(0, import_react10.useLayoutEffect)(() => {
|
|
18966
|
+
const slot = slotRef.current;
|
|
18967
|
+
if (!slot) return;
|
|
18968
|
+
const clamp = () => {
|
|
18969
|
+
const w = slot.offsetWidth;
|
|
18970
|
+
if (w <= 0) return;
|
|
18971
|
+
const half = w / 2;
|
|
18972
|
+
const clamped = Math.max(TOOLBAR_EDGE_MARGIN2 + half, Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN2 - half));
|
|
18973
|
+
setShift((prev) => Math.abs(prev - (clamped - centerX)) < 0.5 ? prev : clamped - centerX);
|
|
18974
|
+
};
|
|
18975
|
+
clamp();
|
|
18976
|
+
const ro = new ResizeObserver(clamp);
|
|
18977
|
+
ro.observe(slot);
|
|
18978
|
+
return () => ro.disconnect();
|
|
18979
|
+
}, [centerX, children]);
|
|
18980
|
+
const mobile = window.innerWidth <= 480;
|
|
18981
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
18982
|
+
"div",
|
|
18983
|
+
{
|
|
18984
|
+
ref: slotRef,
|
|
18985
|
+
"data-ohw-bridge": "",
|
|
18986
|
+
"data-ohw-item-interaction": "",
|
|
18987
|
+
className: "pointer-events-auto fixed",
|
|
18988
|
+
style: {
|
|
18989
|
+
top: stripRect.top - (mobile ? TOOLBAR_STRIP_GAP_MOBILE : TOOLBAR_STRIP_GAP),
|
|
18990
|
+
left: centerX + shift,
|
|
18991
|
+
transform: "translate(-50%, -100%)",
|
|
18992
|
+
zIndex: 2147483645
|
|
18993
|
+
},
|
|
18994
|
+
children
|
|
18995
|
+
}
|
|
18996
|
+
);
|
|
18997
|
+
}
|
|
18765
18998
|
function requestValidateTree(postToParent2, tree) {
|
|
18766
18999
|
return new Promise((resolve) => {
|
|
18767
19000
|
const id = `ai-validate-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
@@ -18798,116 +19031,72 @@ function requestAssetPick(postToParent2) {
|
|
|
18798
19031
|
postToParent2({ type: "ow:asset-pick", id });
|
|
18799
19032
|
});
|
|
18800
19033
|
}
|
|
18801
|
-
function
|
|
19034
|
+
function ToolbarAction({
|
|
18802
19035
|
label,
|
|
18803
19036
|
onClick,
|
|
18804
|
-
disabled,
|
|
18805
|
-
active
|
|
19037
|
+
disabled = false,
|
|
19038
|
+
active = false,
|
|
19039
|
+
children
|
|
18806
19040
|
}) {
|
|
18807
|
-
|
|
18808
|
-
|
|
18809
|
-
{
|
|
18810
|
-
|
|
18811
|
-
|
|
18812
|
-
disabled,
|
|
18813
|
-
style: {
|
|
18814
|
-
height: 28,
|
|
18815
|
-
padding: "0 10px",
|
|
18816
|
-
display: "inline-flex",
|
|
18817
|
-
alignItems: "center",
|
|
18818
|
-
gap: 4,
|
|
18819
|
-
borderRadius: 999,
|
|
18820
|
-
border: "none",
|
|
18821
|
-
cursor: disabled ? "default" : "pointer",
|
|
18822
|
-
background: active ? OHW_BLUE_DARK : "#ffffff",
|
|
18823
|
-
color: active ? "#ffffff" : OHW_BLUE_DARK,
|
|
18824
|
-
opacity: disabled ? 0.4 : 1,
|
|
18825
|
-
fontSize: 12,
|
|
18826
|
-
lineHeight: "16px",
|
|
18827
|
-
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
18828
|
-
whiteSpace: "nowrap",
|
|
18829
|
-
flex: "0 0 auto"
|
|
18830
|
-
},
|
|
18831
|
-
children: label
|
|
18832
|
-
}
|
|
18833
|
-
);
|
|
19041
|
+
const button = /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CustomToolbarButton, { type: "button", "aria-label": label, disabled, active, onClick, className: "size-8", children });
|
|
19042
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Tooltip, { children: [
|
|
19043
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "inline-flex", children: button }) : button }),
|
|
19044
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: label })
|
|
19045
|
+
] });
|
|
18834
19046
|
}
|
|
18835
|
-
function
|
|
18836
|
-
|
|
18837
|
-
|
|
18838
|
-
|
|
18839
|
-
|
|
18840
|
-
|
|
18841
|
-
|
|
18842
|
-
|
|
18843
|
-
|
|
18844
|
-
|
|
18845
|
-
|
|
18846
|
-
|
|
18847
|
-
|
|
18848
|
-
|
|
18849
|
-
|
|
18850
|
-
|
|
18851
|
-
|
|
18852
|
-
|
|
18853
|
-
|
|
18854
|
-
|
|
18855
|
-
|
|
18856
|
-
|
|
18857
|
-
|
|
18858
|
-
|
|
18859
|
-
|
|
18860
|
-
|
|
18861
|
-
|
|
18862
|
-
|
|
18863
|
-
|
|
18864
|
-
},
|
|
18865
|
-
children: "Alt"
|
|
18866
|
-
}
|
|
18867
|
-
),
|
|
18868
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18869
|
-
"input",
|
|
19047
|
+
function ToolbarSeparator() {
|
|
19048
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { "aria-hidden": true, className: "mx-0.5 block h-6 w-px shrink-0 bg-border" });
|
|
19049
|
+
}
|
|
19050
|
+
function OptionMenu({
|
|
19051
|
+
label,
|
|
19052
|
+
value,
|
|
19053
|
+
options,
|
|
19054
|
+
onChange
|
|
19055
|
+
}) {
|
|
19056
|
+
const current = options.find((o) => o.value === value) ?? options[0];
|
|
19057
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19058
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-xs text-muted-foreground", children: label }),
|
|
19059
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(DropdownMenu, { modal: false, children: [
|
|
19060
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
19061
|
+
"button",
|
|
19062
|
+
{
|
|
19063
|
+
type: "button",
|
|
19064
|
+
"aria-label": label,
|
|
19065
|
+
className: "inline-flex h-8 min-w-[76px] items-center gap-[7px] rounded-[6px] bg-transparent px-2 text-[13px] font-medium text-foreground transition-colors hover:bg-muted data-[state=open]:bg-muted",
|
|
19066
|
+
children: [
|
|
19067
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "flex-1 text-left", children: current.label }),
|
|
19068
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.ChevronDown, { size: 16, style: { pointerEvents: "none" } })
|
|
19069
|
+
]
|
|
19070
|
+
}
|
|
19071
|
+
) }),
|
|
19072
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DropdownMenuContent, { align: "end", sideOffset: 8, className: "w-[132px] min-w-[132px] p-1", children: options.map((option) => {
|
|
19073
|
+
const selected = option.value === value;
|
|
19074
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
19075
|
+
DropdownMenuItem,
|
|
18870
19076
|
{
|
|
18871
|
-
|
|
18872
|
-
|
|
18873
|
-
|
|
18874
|
-
|
|
18875
|
-
|
|
18876
|
-
|
|
18877
|
-
|
|
18878
|
-
|
|
18879
|
-
|
|
18880
|
-
|
|
18881
|
-
|
|
18882
|
-
|
|
18883
|
-
|
|
18884
|
-
|
|
18885
|
-
"aria-label": "Image alt text",
|
|
18886
|
-
style: {
|
|
18887
|
-
flex: 1,
|
|
18888
|
-
minWidth: 0,
|
|
18889
|
-
border: "none",
|
|
18890
|
-
outline: "none",
|
|
18891
|
-
background: "transparent",
|
|
18892
|
-
fontSize: 12,
|
|
18893
|
-
lineHeight: "16px",
|
|
18894
|
-
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
18895
|
-
color: "#1f2937"
|
|
18896
|
-
}
|
|
18897
|
-
}
|
|
18898
|
-
)
|
|
18899
|
-
]
|
|
18900
|
-
}
|
|
18901
|
-
);
|
|
19077
|
+
role: "menuitemradio",
|
|
19078
|
+
"aria-checked": selected,
|
|
19079
|
+
onSelect: () => onChange(option.value),
|
|
19080
|
+
className: cn("grid grid-cols-[1fr_16px] gap-2 py-2 pl-2 pr-2 text-[13px]", selected && "bg-muted"),
|
|
19081
|
+
children: [
|
|
19082
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: option.label }),
|
|
19083
|
+
selected && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Check, { size: 16, className: "text-bridge-primary" })
|
|
19084
|
+
]
|
|
19085
|
+
},
|
|
19086
|
+
option.value
|
|
19087
|
+
);
|
|
19088
|
+
}) })
|
|
19089
|
+
] })
|
|
19090
|
+
] });
|
|
18902
19091
|
}
|
|
18903
19092
|
var VARIANTS = [
|
|
18904
19093
|
{ value: "logos", label: "Logos" },
|
|
18905
19094
|
{ value: "reel", label: "Reel" }
|
|
18906
19095
|
];
|
|
18907
19096
|
var ALIGNS = [
|
|
18908
|
-
{ value: "left", label: "
|
|
18909
|
-
{ value: "center", label: "
|
|
18910
|
-
{ value: "right", label: "
|
|
19097
|
+
{ value: "left", label: "Align left", Icon: import_lucide_react9.AlignLeft },
|
|
19098
|
+
{ value: "center", label: "Align center", Icon: import_lucide_react9.AlignCenter },
|
|
19099
|
+
{ value: "right", label: "Align right", Icon: import_lucide_react9.AlignRight }
|
|
18911
19100
|
];
|
|
18912
19101
|
var HOVERS = [
|
|
18913
19102
|
{ value: "none", label: "None" },
|
|
@@ -18915,104 +19104,104 @@ var HOVERS = [
|
|
|
18915
19104
|
{ value: "zoom", label: "Zoom" },
|
|
18916
19105
|
{ value: "fade", label: "Fade" }
|
|
18917
19106
|
];
|
|
18918
|
-
var TREATMENTS = [
|
|
18919
|
-
{ value: "color", label: "Color" },
|
|
18920
|
-
{ value: "grayscale", label: "Grayscale" }
|
|
18921
|
-
];
|
|
18922
19107
|
var HTTP_URL_RE = /^https?:\/\/\S+$/i;
|
|
18923
|
-
function
|
|
18924
|
-
|
|
19108
|
+
function LinkModal({
|
|
19109
|
+
href,
|
|
19110
|
+
linkTarget,
|
|
19111
|
+
onClose,
|
|
19112
|
+
onSave
|
|
19113
|
+
}) {
|
|
19114
|
+
const [draft, setDraft] = (0, import_react10.useState)(href);
|
|
19115
|
+
const [newTab, setNewTab] = (0, import_react10.useState)(linkTarget !== "same-tab");
|
|
18925
19116
|
const [invalid, setInvalid] = (0, import_react10.useState)(false);
|
|
18926
|
-
|
|
18927
|
-
setDraft(value);
|
|
18928
|
-
setInvalid(false);
|
|
18929
|
-
}, [value]);
|
|
18930
|
-
const commit = () => {
|
|
19117
|
+
const save = () => {
|
|
18931
19118
|
const next = draft.trim();
|
|
18932
|
-
if (next
|
|
18933
|
-
|
|
18934
|
-
|
|
18935
|
-
onCommit(next);
|
|
18936
|
-
};
|
|
18937
|
-
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
18938
|
-
"div",
|
|
18939
|
-
{
|
|
18940
|
-
style: {
|
|
18941
|
-
display: "flex",
|
|
18942
|
-
alignItems: "center",
|
|
18943
|
-
gap: 6,
|
|
18944
|
-
height: 28,
|
|
18945
|
-
padding: "0 12px",
|
|
18946
|
-
borderRadius: 999,
|
|
18947
|
-
background: "#ffffff",
|
|
18948
|
-
width: "100%",
|
|
18949
|
-
maxWidth: 260,
|
|
18950
|
-
boxSizing: "border-box",
|
|
18951
|
-
boxShadow: invalid ? "inset 0 0 0 1.5px #EF4444" : "none"
|
|
18952
|
-
},
|
|
18953
|
-
children: [
|
|
18954
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18955
|
-
"span",
|
|
18956
|
-
{
|
|
18957
|
-
style: {
|
|
18958
|
-
flex: "0 0 auto",
|
|
18959
|
-
color: OHW_BLUE_DARK,
|
|
18960
|
-
fontSize: 10,
|
|
18961
|
-
fontWeight: 700,
|
|
18962
|
-
textTransform: "uppercase",
|
|
18963
|
-
letterSpacing: 0.4
|
|
18964
|
-
},
|
|
18965
|
-
children: "Link"
|
|
18966
|
-
}
|
|
18967
|
-
),
|
|
18968
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18969
|
-
"input",
|
|
18970
|
-
{
|
|
18971
|
-
type: "text",
|
|
18972
|
-
inputMode: "url",
|
|
18973
|
-
value: draft,
|
|
18974
|
-
onChange: (e) => setDraft(e.target.value),
|
|
18975
|
-
onBlur: commit,
|
|
18976
|
-
onKeyDown: (e) => {
|
|
18977
|
-
if (e.key === "Enter") e.currentTarget.blur();
|
|
18978
|
-
if (e.key === "Escape") {
|
|
18979
|
-
setDraft(value);
|
|
18980
|
-
setInvalid(false);
|
|
18981
|
-
e.currentTarget.blur();
|
|
18982
|
-
}
|
|
18983
|
-
},
|
|
18984
|
-
placeholder: "https://example.com",
|
|
18985
|
-
"aria-label": "Image link URL",
|
|
18986
|
-
"aria-invalid": invalid,
|
|
18987
|
-
style: {
|
|
18988
|
-
flex: 1,
|
|
18989
|
-
minWidth: 0,
|
|
18990
|
-
border: "none",
|
|
18991
|
-
outline: "none",
|
|
18992
|
-
background: "transparent",
|
|
18993
|
-
fontSize: 12,
|
|
18994
|
-
lineHeight: "16px",
|
|
18995
|
-
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
18996
|
-
color: "#1f2937"
|
|
18997
|
-
}
|
|
18998
|
-
}
|
|
18999
|
-
)
|
|
19000
|
-
]
|
|
19119
|
+
if (next && !HTTP_URL_RE.test(next)) {
|
|
19120
|
+
setInvalid(true);
|
|
19121
|
+
return;
|
|
19001
19122
|
}
|
|
19002
|
-
|
|
19123
|
+
onSave(next, newTab ? "new-tab" : "same-tab");
|
|
19124
|
+
onClose();
|
|
19125
|
+
};
|
|
19126
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Dialog2, { open: true, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(DialogContent, { "data-ohw-link-modal-root": "", className: "max-w-[400px] gap-4 p-5", children: [
|
|
19127
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DialogHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DialogTitle, { className: "text-base", children: "Image link" }) }),
|
|
19128
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-col gap-3", children: [
|
|
19129
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19130
|
+
"input",
|
|
19131
|
+
{
|
|
19132
|
+
autoFocus: true,
|
|
19133
|
+
type: "text",
|
|
19134
|
+
inputMode: "url",
|
|
19135
|
+
value: draft,
|
|
19136
|
+
onChange: (e) => {
|
|
19137
|
+
setDraft(e.target.value);
|
|
19138
|
+
setInvalid(false);
|
|
19139
|
+
},
|
|
19140
|
+
onKeyDown: (e) => {
|
|
19141
|
+
if (e.key === "Enter") save();
|
|
19142
|
+
},
|
|
19143
|
+
placeholder: "https://example.com",
|
|
19144
|
+
"aria-label": "Image link URL",
|
|
19145
|
+
"aria-invalid": invalid,
|
|
19146
|
+
className: cn(
|
|
19147
|
+
"h-9 w-full rounded-[6px] border border-border bg-background px-3 text-[13px] text-foreground outline-none placeholder:text-muted-foreground/70 focus:border-bridge-primary",
|
|
19148
|
+
invalid && "border-destructive focus:border-destructive"
|
|
19149
|
+
)
|
|
19150
|
+
}
|
|
19151
|
+
),
|
|
19152
|
+
invalid && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-xs text-destructive", children: "Enter a full URL starting with http:// or https://" }),
|
|
19153
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex items-center gap-2 text-[13px] text-foreground", children: [
|
|
19154
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("input", { type: "checkbox", checked: newTab, onChange: (e) => setNewTab(e.target.checked) }),
|
|
19155
|
+
"Open in new tab"
|
|
19156
|
+
] })
|
|
19157
|
+
] }),
|
|
19158
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(DialogFooter, { children: [
|
|
19159
|
+
href && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19160
|
+
"button",
|
|
19161
|
+
{
|
|
19162
|
+
type: "button",
|
|
19163
|
+
onClick: () => {
|
|
19164
|
+
onSave("", "new-tab");
|
|
19165
|
+
onClose();
|
|
19166
|
+
},
|
|
19167
|
+
className: "mr-auto rounded-[6px] px-3 py-2 text-[13px] font-medium text-destructive transition-colors hover:bg-muted",
|
|
19168
|
+
children: "Remove link"
|
|
19169
|
+
}
|
|
19170
|
+
),
|
|
19171
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19172
|
+
"button",
|
|
19173
|
+
{
|
|
19174
|
+
type: "button",
|
|
19175
|
+
onClick: onClose,
|
|
19176
|
+
className: "rounded-[6px] px-3 py-2 text-[13px] font-medium text-foreground transition-colors hover:bg-muted",
|
|
19177
|
+
children: "Cancel"
|
|
19178
|
+
}
|
|
19179
|
+
),
|
|
19180
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19181
|
+
"button",
|
|
19182
|
+
{
|
|
19183
|
+
type: "button",
|
|
19184
|
+
onClick: save,
|
|
19185
|
+
className: "rounded-[6px] bg-bridge-primary px-3 py-2 text-[13px] font-medium text-primary-foreground transition-opacity hover:opacity-90",
|
|
19186
|
+
children: "Save"
|
|
19187
|
+
}
|
|
19188
|
+
)
|
|
19189
|
+
] })
|
|
19190
|
+
] }) });
|
|
19003
19191
|
}
|
|
19004
19192
|
function MediaStripToolbar({
|
|
19005
19193
|
entry,
|
|
19006
19194
|
index,
|
|
19007
19195
|
pending,
|
|
19008
19196
|
error,
|
|
19197
|
+
itemEditOn,
|
|
19198
|
+
onToggleItemEdit,
|
|
19009
19199
|
onSetVariant,
|
|
19010
19200
|
onSetAlign,
|
|
19011
19201
|
onSetHover,
|
|
19012
19202
|
onSetTreatment,
|
|
19013
19203
|
onResize,
|
|
19014
|
-
|
|
19015
|
-
onSetLink,
|
|
19204
|
+
onOpenLink,
|
|
19016
19205
|
onAddItem,
|
|
19017
19206
|
onRemoveItem,
|
|
19018
19207
|
onChangeImage,
|
|
@@ -19021,81 +19210,102 @@ function MediaStripToolbar({
|
|
|
19021
19210
|
}) {
|
|
19022
19211
|
const items = mediaStripItems(entry.tree);
|
|
19023
19212
|
const itemCount = items.length;
|
|
19024
|
-
const currentAlt = items[index]?.alt ?? "";
|
|
19025
|
-
const currentHref = items[index]?.href ?? "";
|
|
19026
|
-
const currentTarget = items[index]?.linkTarget === "same-tab" ? "same-tab" : "new-tab";
|
|
19027
19213
|
const slots = findMediaStripSlots(entry.tree);
|
|
19028
19214
|
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
19029
19215
|
const align = slots?.align === "left" || slots?.align === "right" ? slots.align : "center";
|
|
19030
19216
|
const hover = slots?.hover === "none" || slots?.hover === "lift" || slots?.hover === "zoom" || slots?.hover === "fade" ? slots.hover : "lift";
|
|
19031
19217
|
const treatment = slots?.treatment === "color" || slots?.treatment === "grayscale" ? slots.treatment : variant === "logos" ? "grayscale" : "color";
|
|
19032
19218
|
const sizeValue = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
19033
|
-
const
|
|
19034
|
-
const
|
|
19035
|
-
|
|
19036
|
-
gap: 6,
|
|
19037
|
-
flexWrap: "nowrap",
|
|
19038
|
-
justifyContent: "center",
|
|
19039
|
-
overflowX: "auto",
|
|
19040
|
-
WebkitOverflowScrolling: "touch",
|
|
19041
|
-
width: "100%",
|
|
19042
|
-
scrollbarWidth: "none"
|
|
19043
|
-
} : { display: "flex", gap: 6, flexWrap: "nowrap", justifyContent: "center" };
|
|
19044
|
-
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
19219
|
+
const mobile = window.innerWidth <= 480;
|
|
19220
|
+
const gatedLabel = (label) => itemEditOn ? label : "Turn on the star to edit this image";
|
|
19221
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
19045
19222
|
"div",
|
|
19046
19223
|
{
|
|
19047
19224
|
"data-ohw-bridge": "",
|
|
19048
19225
|
"data-ohw-toolbar": "",
|
|
19049
19226
|
onMouseDown: (e) => e.stopPropagation(),
|
|
19050
|
-
|
|
19051
|
-
|
|
19052
|
-
flexDirection: "column",
|
|
19053
|
-
gap: 6,
|
|
19054
|
-
alignItems: "center",
|
|
19055
|
-
background: OHW_BLUE,
|
|
19056
|
-
padding: 8,
|
|
19057
|
-
borderRadius: 12,
|
|
19058
|
-
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
19059
|
-
pointerEvents: pending ? "none" : "auto",
|
|
19060
|
-
opacity: pending ? 0.6 : 1,
|
|
19061
|
-
maxWidth: isMobile ? "calc(100vw - 24px)" : "none"
|
|
19062
|
-
},
|
|
19227
|
+
className: cn("flex flex-col items-center gap-1.5 font-sans", pending && "pointer-events-none opacity-60"),
|
|
19228
|
+
style: { maxWidth: mobile ? "calc(100vw - 24px)" : void 0 },
|
|
19063
19229
|
children: [
|
|
19064
|
-
/* @__PURE__ */ (0,
|
|
19065
|
-
|
|
19066
|
-
|
|
19067
|
-
|
|
19068
|
-
|
|
19069
|
-
|
|
19070
|
-
|
|
19071
|
-
|
|
19072
|
-
|
|
19073
|
-
|
|
19074
|
-
|
|
19075
|
-
|
|
19076
|
-
|
|
19077
|
-
|
|
19078
|
-
|
|
19079
|
-
|
|
19080
|
-
|
|
19081
|
-
|
|
19082
|
-
|
|
19083
|
-
|
|
19084
|
-
|
|
19085
|
-
|
|
19086
|
-
|
|
19087
|
-
|
|
19088
|
-
|
|
19089
|
-
|
|
19090
|
-
|
|
19091
|
-
|
|
19092
|
-
|
|
19093
|
-
|
|
19094
|
-
|
|
19095
|
-
|
|
19230
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
19231
|
+
"div",
|
|
19232
|
+
{
|
|
19233
|
+
className: cn(
|
|
19234
|
+
"flex items-center gap-1 rounded-[10px] border border-border bg-background p-1 whitespace-nowrap",
|
|
19235
|
+
"shadow-[0px_10px_15px_-3px_rgba(0,0,0,0.1),0px_4px_6px_-4px_rgba(0,0,0,0.1)]",
|
|
19236
|
+
mobile ? "flex-wrap justify-center" : "flex-nowrap"
|
|
19237
|
+
),
|
|
19238
|
+
children: [
|
|
19239
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Tooltip, { children: [
|
|
19240
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19241
|
+
CustomToolbarButton,
|
|
19242
|
+
{
|
|
19243
|
+
type: "button",
|
|
19244
|
+
"aria-label": itemEditOn ? "Done editing this image" : "Edit this image",
|
|
19245
|
+
"aria-pressed": itemEditOn,
|
|
19246
|
+
onClick: onToggleItemEdit,
|
|
19247
|
+
className: "group size-8",
|
|
19248
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19249
|
+
import_lucide_react9.Star,
|
|
19250
|
+
{
|
|
19251
|
+
size: 16,
|
|
19252
|
+
fill: "currentColor",
|
|
19253
|
+
strokeWidth: 0,
|
|
19254
|
+
className: cn(
|
|
19255
|
+
"transition-colors",
|
|
19256
|
+
itemEditOn ? "text-[#f59e0b] group-hover:text-[#d97706]" : "text-[#d6d3d1] group-hover:text-[#fbbf24]"
|
|
19257
|
+
),
|
|
19258
|
+
style: { pointerEvents: "none" }
|
|
19259
|
+
}
|
|
19260
|
+
)
|
|
19261
|
+
}
|
|
19262
|
+
) }),
|
|
19263
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: itemEditOn ? "Done editing this image" : "Edit this image" })
|
|
19264
|
+
] }),
|
|
19265
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19266
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: gatedLabel("Change image"), onClick: onChangeImage, disabled: !itemEditOn, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Image, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19267
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: gatedLabel("Link"), onClick: onOpenLink, disabled: !itemEditOn, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Link, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19268
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: gatedLabel("Move left"), onClick: onMoveLeft, disabled: !itemEditOn || index <= 0, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.ArrowLeft, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19269
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19270
|
+
ToolbarAction,
|
|
19271
|
+
{
|
|
19272
|
+
label: gatedLabel("Move right"),
|
|
19273
|
+
onClick: onMoveRight,
|
|
19274
|
+
disabled: !itemEditOn || index >= itemCount - 1,
|
|
19275
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.ArrowRight, { size: 16, style: { pointerEvents: "none" } })
|
|
19276
|
+
}
|
|
19277
|
+
),
|
|
19278
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: gatedLabel("Remove image"), onClick: onRemoveItem, disabled: !itemEditOn || itemCount <= 1, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.ImageMinus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19279
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19280
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(OptionMenu, { label: "Layout", value: variant, options: VARIANTS, onChange: onSetVariant }),
|
|
19281
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(OptionMenu, { label: "Hover", value: hover, options: HOVERS, onChange: onSetHover }),
|
|
19282
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19283
|
+
ToolbarAction,
|
|
19284
|
+
{
|
|
19285
|
+
label: treatment === "grayscale" ? "Show in color" : "Show grayscale",
|
|
19286
|
+
active: treatment === "grayscale",
|
|
19287
|
+
onClick: () => onSetTreatment(treatment === "grayscale" ? "color" : "grayscale"),
|
|
19288
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Palette, { size: 16, style: { pointerEvents: "none" } })
|
|
19289
|
+
}
|
|
19290
|
+
),
|
|
19291
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19292
|
+
ALIGNS.map(({ value, label, Icon }) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label, active: align === value, onClick: () => onSetAlign(value), children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Icon, { size: 16, style: { pointerEvents: "none" } }) }, value)),
|
|
19293
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19294
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: "Smaller", onClick: () => onResize(-8), children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Minus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19295
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "min-w-[40px] text-center text-xs tabular-nums text-muted-foreground", children: [
|
|
19296
|
+
sizeValue,
|
|
19297
|
+
"px"
|
|
19298
|
+
] }),
|
|
19299
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: "Larger", onClick: () => onResize(8), children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Plus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19300
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19301
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: "Add image", onClick: onAddItem, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.ImagePlus, { size: 16, style: { pointerEvents: "none" } }) })
|
|
19302
|
+
]
|
|
19303
|
+
}
|
|
19304
|
+
),
|
|
19305
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "max-w-[260px] rounded-md bg-background px-2 py-1 text-center text-[11px] text-destructive shadow-sm", children: error })
|
|
19096
19306
|
]
|
|
19097
19307
|
}
|
|
19098
|
-
);
|
|
19308
|
+
) });
|
|
19099
19309
|
}
|
|
19100
19310
|
function findMediaStripSlots(tree) {
|
|
19101
19311
|
const stack = tree.rows.flatMap((row) => row.blocks);
|
|
@@ -19114,31 +19324,23 @@ function AiMediaStripOverlay({
|
|
|
19114
19324
|
}) {
|
|
19115
19325
|
const [hover, setHover] = (0, import_react10.useState)(null);
|
|
19116
19326
|
const [active, setActive] = (0, import_react10.useState)(null);
|
|
19327
|
+
const [itemEditOn, setItemEditOn] = (0, import_react10.useState)(false);
|
|
19328
|
+
const [linkOpen, setLinkOpen] = (0, import_react10.useState)(false);
|
|
19117
19329
|
const [pending, setPending] = (0, import_react10.useState)(false);
|
|
19118
19330
|
const [error, setError] = (0, import_react10.useState)(null);
|
|
19119
19331
|
const activeRef = (0, import_react10.useRef)(null);
|
|
19120
19332
|
activeRef.current = active;
|
|
19333
|
+
const linkOpenRef = (0, import_react10.useRef)(false);
|
|
19334
|
+
linkOpenRef.current = linkOpen;
|
|
19121
19335
|
(0, import_react10.useEffect)(() => {
|
|
19122
19336
|
const onMove = (e) => {
|
|
19337
|
+
const ref = itemRefFromTarget(e.target);
|
|
19123
19338
|
const t = e.target;
|
|
19124
|
-
|
|
19125
|
-
|
|
19126
|
-
|
|
19127
|
-
|
|
19128
|
-
|
|
19129
|
-
if (!itemEl) {
|
|
19130
|
-
setHover(null);
|
|
19131
|
-
return;
|
|
19132
|
-
}
|
|
19133
|
-
const sectionEl = itemEl.closest("[data-ohw-section]");
|
|
19134
|
-
const unit = sectionEl ? movableUnit(sectionEl) : null;
|
|
19135
|
-
const sectionId = unit ? instanceIdOf(unit) || null : null;
|
|
19136
|
-
const index = Number(itemEl.dataset.ohwMediaStripIndex);
|
|
19137
|
-
if (!sectionId || Number.isNaN(index)) {
|
|
19138
|
-
setHover(null);
|
|
19139
|
-
return;
|
|
19140
|
-
}
|
|
19141
|
-
setHover({ sectionId, index });
|
|
19339
|
+
const overEditable = Boolean(t?.closest?.("[data-ohw-editable]"));
|
|
19340
|
+
setHover((prev) => {
|
|
19341
|
+
const next = ref && !overEditable ? ref : null;
|
|
19342
|
+
return sameRef(prev, next) ? prev : next;
|
|
19343
|
+
});
|
|
19142
19344
|
};
|
|
19143
19345
|
const onLeave = () => setHover(null);
|
|
19144
19346
|
document.addEventListener("mousemove", onMove, { passive: true });
|
|
@@ -19150,23 +19352,25 @@ function AiMediaStripOverlay({
|
|
|
19150
19352
|
}, []);
|
|
19151
19353
|
(0, import_react10.useEffect)(() => {
|
|
19152
19354
|
const onClick = (e) => {
|
|
19153
|
-
const current = activeRef.current;
|
|
19154
|
-
if (!current) return;
|
|
19155
19355
|
const t = e.target;
|
|
19156
|
-
if (!(t instanceof
|
|
19157
|
-
if (t.closest(
|
|
19158
|
-
const
|
|
19159
|
-
if (
|
|
19160
|
-
|
|
19356
|
+
if (!(t instanceof Element)) return;
|
|
19357
|
+
if (t.closest(CHROME_SELECTOR)) return;
|
|
19358
|
+
const ref = itemRefFromTarget(t);
|
|
19359
|
+
if (sameRef(activeRef.current, ref)) return;
|
|
19360
|
+
if (ref) clearInteractionChromeRef.current();
|
|
19361
|
+
setItemEditOn(false);
|
|
19161
19362
|
setError(null);
|
|
19363
|
+
setActive(ref);
|
|
19162
19364
|
};
|
|
19163
19365
|
document.addEventListener("click", onClick, true);
|
|
19164
19366
|
return () => document.removeEventListener("click", onClick, true);
|
|
19165
|
-
}, []);
|
|
19367
|
+
}, [clearInteractionChromeRef]);
|
|
19166
19368
|
(0, import_react10.useEffect)(() => {
|
|
19167
19369
|
const onBlur = () => {
|
|
19168
19370
|
if (!activeRef.current) return;
|
|
19169
19371
|
setActive(null);
|
|
19372
|
+
setItemEditOn(false);
|
|
19373
|
+
setLinkOpen(false);
|
|
19170
19374
|
setError(null);
|
|
19171
19375
|
};
|
|
19172
19376
|
window.addEventListener("blur", onBlur);
|
|
@@ -19176,7 +19380,10 @@ function AiMediaStripOverlay({
|
|
|
19176
19380
|
const onKeyDown = (e) => {
|
|
19177
19381
|
if (e.key !== "Escape") return;
|
|
19178
19382
|
if (!activeRef.current) return;
|
|
19383
|
+
if (linkOpenRef.current) return;
|
|
19384
|
+
if (document.querySelector('[data-ohw-more-menu][data-state="open"]')) return;
|
|
19179
19385
|
setActive(null);
|
|
19386
|
+
setItemEditOn(false);
|
|
19180
19387
|
setError(null);
|
|
19181
19388
|
};
|
|
19182
19389
|
document.addEventListener("keydown", onKeyDown);
|
|
@@ -19210,137 +19417,133 @@ function AiMediaStripOverlay({
|
|
|
19210
19417
|
tree: nextTree,
|
|
19211
19418
|
label: entry.label,
|
|
19212
19419
|
media: extraMedia ? { ...entry.media, ...extraMedia } : entry.media,
|
|
19213
|
-
...entry.brand ? { brand: entry.brand } : {}
|
|
19420
|
+
...entry.brand ? { brand: entry.brand } : {},
|
|
19421
|
+
// The user is already looking at the strip they just edited — recentering the viewport
|
|
19422
|
+
// on every edit reads as the section jumping around.
|
|
19423
|
+
skipScrollIntoView: true
|
|
19214
19424
|
});
|
|
19215
19425
|
return true;
|
|
19216
19426
|
},
|
|
19217
19427
|
[findEntry, postToParent2, applyTreeLocalRef]
|
|
19218
19428
|
);
|
|
19219
19429
|
const activeEntry = active ? findEntry(active.sectionId) : null;
|
|
19220
|
-
const hoverHandleRect = useLiveItemRect(!active && hover ? hover : null);
|
|
19221
19430
|
const activeItemRect = useLiveItemRect(active);
|
|
19222
|
-
const
|
|
19223
|
-
const
|
|
19224
|
-
|
|
19225
|
-
|
|
19226
|
-
|
|
19227
|
-
|
|
19228
|
-
|
|
19229
|
-
|
|
19230
|
-
|
|
19231
|
-
|
|
19232
|
-
|
|
19233
|
-
|
|
19234
|
-
|
|
19235
|
-
|
|
19236
|
-
|
|
19237
|
-
|
|
19238
|
-
|
|
19239
|
-
|
|
19240
|
-
|
|
19241
|
-
|
|
19242
|
-
|
|
19243
|
-
|
|
19244
|
-
|
|
19245
|
-
|
|
19246
|
-
|
|
19247
|
-
|
|
19248
|
-
|
|
19249
|
-
|
|
19250
|
-
|
|
19251
|
-
|
|
19252
|
-
|
|
19253
|
-
|
|
19254
|
-
|
|
19255
|
-
|
|
19256
|
-
activeItemRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
19257
|
-
ItemInteractionLayer,
|
|
19258
|
-
{
|
|
19259
|
-
rect: activeItemRect,
|
|
19260
|
-
state: toolbarState,
|
|
19261
|
-
toolbar: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
19262
|
-
MediaStripToolbar,
|
|
19263
|
-
{
|
|
19264
|
-
entry: activeEntry,
|
|
19265
|
-
index: active.index,
|
|
19266
|
-
pending,
|
|
19267
|
-
error,
|
|
19268
|
-
onSetVariant: (variant) => runMutation(active.sectionId, (tree) => setMediaStripVariant(tree, variant)),
|
|
19269
|
-
onSetAlign: (align) => runMutation(active.sectionId, (tree) => setMediaStripAlign(tree, align)),
|
|
19270
|
-
onSetHover: (hoverPreset) => runMutation(active.sectionId, (tree) => setMediaStripHover(tree, hoverPreset)),
|
|
19271
|
-
onSetTreatment: (treatment) => runMutation(active.sectionId, (tree) => setMediaStripTreatment(tree, treatment)),
|
|
19272
|
-
onResize: (delta) => {
|
|
19273
|
-
const slots = findMediaStripSlots(activeEntry.tree);
|
|
19274
|
-
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
19275
|
-
const current = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
19276
|
-
void runMutation(active.sectionId, (tree) => setMediaStripSizing(tree, current + delta));
|
|
19277
|
-
},
|
|
19278
|
-
onSetAlt: (alt) => {
|
|
19279
|
-
void runMutation(active.sectionId, (tree) => setMediaStripItemAlt(tree, active.index, alt));
|
|
19280
|
-
},
|
|
19281
|
-
onSetLink: (href, linkTarget) => {
|
|
19431
|
+
const activeStripRect = useLiveItemRect(active, true);
|
|
19432
|
+
const hoverRect = useLiveItemRect(hover && !sameRef(hover, active) ? hover : null);
|
|
19433
|
+
const activeItems = activeEntry ? mediaStripItems(activeEntry.tree) : [];
|
|
19434
|
+
const activeItem = active ? activeItems[active.index] : void 0;
|
|
19435
|
+
const activeHref = activeItem?.href ?? "";
|
|
19436
|
+
const activeTarget = activeItem?.linkTarget === "same-tab" ? "same-tab" : "new-tab";
|
|
19437
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
19438
|
+
hoverRect && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ItemInteractionLayer, { rect: hoverRect, state: "hover" }),
|
|
19439
|
+
activeItemRect && activeStripRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
19440
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ItemInteractionLayer, { rect: activeItemRect, state: "active-top" }),
|
|
19441
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StripToolbarSlot, { stripRect: activeStripRect, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19442
|
+
MediaStripToolbar,
|
|
19443
|
+
{
|
|
19444
|
+
entry: activeEntry,
|
|
19445
|
+
index: active.index,
|
|
19446
|
+
pending,
|
|
19447
|
+
error,
|
|
19448
|
+
itemEditOn,
|
|
19449
|
+
onToggleItemEdit: () => setItemEditOn((on) => !on),
|
|
19450
|
+
onSetVariant: (variant) => runMutation(active.sectionId, (tree) => setMediaStripVariant(tree, variant)),
|
|
19451
|
+
onSetAlign: (align) => runMutation(active.sectionId, (tree) => setMediaStripAlign(tree, align)),
|
|
19452
|
+
onSetHover: (hoverPreset) => runMutation(active.sectionId, (tree) => setMediaStripHover(tree, hoverPreset)),
|
|
19453
|
+
onSetTreatment: (treatment) => runMutation(active.sectionId, (tree) => setMediaStripTreatment(tree, treatment)),
|
|
19454
|
+
onResize: (delta) => {
|
|
19455
|
+
const slots = findMediaStripSlots(activeEntry.tree);
|
|
19456
|
+
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
19457
|
+
const current = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
19458
|
+
void runMutation(active.sectionId, (tree) => setMediaStripSizing(tree, current + delta));
|
|
19459
|
+
},
|
|
19460
|
+
onOpenLink: () => setLinkOpen(true),
|
|
19461
|
+
onAddItem: () => {
|
|
19462
|
+
void requestAssetPick(postToParent2).then((picked) => {
|
|
19463
|
+
if (!picked) return;
|
|
19464
|
+
const item = { assetId: picked.assetId, alt: "Logo" };
|
|
19282
19465
|
void runMutation(
|
|
19283
19466
|
active.sectionId,
|
|
19284
|
-
(tree) =>
|
|
19285
|
-
|
|
19286
|
-
|
|
19287
|
-
|
|
19288
|
-
void requestAssetPick(postToParent2).then((picked) => {
|
|
19289
|
-
if (!picked) return;
|
|
19290
|
-
const item = { assetId: picked.assetId, alt: "Logo" };
|
|
19291
|
-
void runMutation(
|
|
19292
|
-
active.sectionId,
|
|
19293
|
-
(tree) => addMediaStripItem(tree, item, active.index),
|
|
19294
|
-
{ [picked.assetId]: picked.url }
|
|
19295
|
-
).then((applied) => {
|
|
19296
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19297
|
-
});
|
|
19298
|
-
});
|
|
19299
|
-
},
|
|
19300
|
-
onChangeImage: () => {
|
|
19301
|
-
void requestAssetPick(postToParent2).then((picked) => {
|
|
19302
|
-
if (!picked) return;
|
|
19303
|
-
void runMutation(
|
|
19304
|
-
active.sectionId,
|
|
19305
|
-
(tree) => setMediaStripItemAsset(tree, active.index, picked.assetId),
|
|
19306
|
-
{ [picked.assetId]: picked.url }
|
|
19307
|
-
);
|
|
19467
|
+
(tree) => addMediaStripItem(tree, item, active.index),
|
|
19468
|
+
{ [picked.assetId]: picked.url }
|
|
19469
|
+
).then((applied) => {
|
|
19470
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19308
19471
|
});
|
|
19309
|
-
}
|
|
19310
|
-
|
|
19311
|
-
|
|
19312
|
-
|
|
19313
|
-
|
|
19314
|
-
|
|
19315
|
-
|
|
19316
|
-
|
|
19317
|
-
|
|
19318
|
-
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, -1)).then(
|
|
19319
|
-
(applied) => {
|
|
19320
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index - 1 });
|
|
19321
|
-
}
|
|
19322
|
-
);
|
|
19323
|
-
},
|
|
19324
|
-
onMoveRight: () => {
|
|
19325
|
-
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, 1)).then(
|
|
19326
|
-
(applied) => {
|
|
19327
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19328
|
-
}
|
|
19472
|
+
});
|
|
19473
|
+
},
|
|
19474
|
+
onChangeImage: () => {
|
|
19475
|
+
void requestAssetPick(postToParent2).then((picked) => {
|
|
19476
|
+
if (!picked) return;
|
|
19477
|
+
void runMutation(
|
|
19478
|
+
active.sectionId,
|
|
19479
|
+
(tree) => setMediaStripItemAsset(tree, active.index, picked.assetId),
|
|
19480
|
+
{ [picked.assetId]: picked.url }
|
|
19329
19481
|
);
|
|
19330
|
-
}
|
|
19482
|
+
});
|
|
19483
|
+
},
|
|
19484
|
+
onRemoveItem: () => {
|
|
19485
|
+
void runMutation(active.sectionId, (tree) => removeMediaStripItem(tree, active.index)).then(
|
|
19486
|
+
(applied) => {
|
|
19487
|
+
if (applied) setActive(null);
|
|
19488
|
+
}
|
|
19489
|
+
);
|
|
19490
|
+
},
|
|
19491
|
+
onMoveLeft: () => {
|
|
19492
|
+
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, -1)).then(
|
|
19493
|
+
(applied) => {
|
|
19494
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index - 1 });
|
|
19495
|
+
}
|
|
19496
|
+
);
|
|
19497
|
+
},
|
|
19498
|
+
onMoveRight: () => {
|
|
19499
|
+
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, 1)).then(
|
|
19500
|
+
(applied) => {
|
|
19501
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19502
|
+
}
|
|
19503
|
+
);
|
|
19331
19504
|
}
|
|
19332
|
-
|
|
19333
|
-
}
|
|
19334
|
-
|
|
19505
|
+
}
|
|
19506
|
+
) }),
|
|
19507
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19508
|
+
"div",
|
|
19509
|
+
{
|
|
19510
|
+
"data-ohw-bridge": "",
|
|
19511
|
+
"data-ohw-item-interaction": "",
|
|
19512
|
+
"aria-hidden": true,
|
|
19513
|
+
className: "pointer-events-none fixed rounded-[4px] px-[7px] py-[3px] font-sans text-[11px] font-medium leading-none text-primary-foreground whitespace-nowrap",
|
|
19514
|
+
style: {
|
|
19515
|
+
top: activeItemRect.top + activeItemRect.height + 10,
|
|
19516
|
+
left: activeItemRect.left - 5,
|
|
19517
|
+
background: PRIMARY3,
|
|
19518
|
+
zIndex: 2147483644
|
|
19519
|
+
},
|
|
19520
|
+
children: "Media item"
|
|
19521
|
+
}
|
|
19522
|
+
),
|
|
19523
|
+
linkOpen && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19524
|
+
LinkModal,
|
|
19525
|
+
{
|
|
19526
|
+
href: activeHref,
|
|
19527
|
+
linkTarget: activeTarget,
|
|
19528
|
+
onClose: () => setLinkOpen(false),
|
|
19529
|
+
onSave: (href, linkTarget) => {
|
|
19530
|
+
void runMutation(
|
|
19531
|
+
active.sectionId,
|
|
19532
|
+
(tree) => setMediaStripItemLink(tree, active.index, href ? { href, linkTarget } : {})
|
|
19533
|
+
);
|
|
19534
|
+
}
|
|
19535
|
+
}
|
|
19536
|
+
)
|
|
19537
|
+
] })
|
|
19335
19538
|
] });
|
|
19336
19539
|
}
|
|
19337
19540
|
|
|
19338
19541
|
// src/ui/ai-section/AiPricingCardOverlay.tsx
|
|
19339
19542
|
var import_react11 = require("react");
|
|
19340
|
-
var
|
|
19341
|
-
var
|
|
19543
|
+
var import_lucide_react10 = require("lucide-react");
|
|
19544
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
19342
19545
|
var PRIMARY4 = "var(--ohw-primary, #0885FE)";
|
|
19343
|
-
var
|
|
19546
|
+
var CHROME_SELECTOR2 = "[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-link-modal-root], [data-ohw-section-picker], [data-ohw-ai-review], [data-ohw-more-menu]";
|
|
19344
19547
|
function findPricingCardElement(sectionId, index) {
|
|
19345
19548
|
const sectionEl = findByInstanceId(sectionId);
|
|
19346
19549
|
if (!sectionEl) return null;
|
|
@@ -19352,7 +19555,7 @@ function findPricingCardElement(sectionId, index) {
|
|
|
19352
19555
|
}
|
|
19353
19556
|
function cardRefFromTarget(target) {
|
|
19354
19557
|
if (!(target instanceof Element)) return null;
|
|
19355
|
-
if (target.closest(
|
|
19558
|
+
if (target.closest(CHROME_SELECTOR2)) return null;
|
|
19356
19559
|
const cardEl = target.closest("[data-ohw-pricing-card]");
|
|
19357
19560
|
if (!cardEl) return null;
|
|
19358
19561
|
const sectionEl = cardEl.closest("[data-ohw-section]");
|
|
@@ -19362,21 +19565,21 @@ function cardRefFromTarget(target) {
|
|
|
19362
19565
|
if (!sectionId || Number.isNaN(index)) return null;
|
|
19363
19566
|
return { sectionId, index };
|
|
19364
19567
|
}
|
|
19365
|
-
function
|
|
19568
|
+
function sameRef2(a, b) {
|
|
19366
19569
|
return a?.sectionId === b?.sectionId && a?.index === b?.index;
|
|
19367
19570
|
}
|
|
19368
|
-
function
|
|
19571
|
+
function rectOf2(el) {
|
|
19369
19572
|
if (!el) return null;
|
|
19370
19573
|
const r2 = el.getBoundingClientRect();
|
|
19371
19574
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
19372
19575
|
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
19373
19576
|
}
|
|
19374
19577
|
function readRect3(ref) {
|
|
19375
|
-
return
|
|
19578
|
+
return rectOf2(ref && findPricingCardElement(ref.sectionId, ref.index));
|
|
19376
19579
|
}
|
|
19377
19580
|
function readGridRect(ref) {
|
|
19378
19581
|
const card = ref && findPricingCardElement(ref.sectionId, ref.index);
|
|
19379
|
-
return
|
|
19582
|
+
return rectOf2(card?.closest("[data-ohw-pricing-collection]") ?? card);
|
|
19380
19583
|
}
|
|
19381
19584
|
function useLiveCardRect(ref, grid = false) {
|
|
19382
19585
|
const [rect, setRect] = (0, import_react11.useState)(null);
|
|
@@ -19406,7 +19609,7 @@ function useLiveCardRect(ref, grid = false) {
|
|
|
19406
19609
|
}
|
|
19407
19610
|
var TOOLBAR_GRID_GAP = 52;
|
|
19408
19611
|
var TOOLBAR_GRID_GAP_MOBILE = 42;
|
|
19409
|
-
var
|
|
19612
|
+
var TOOLBAR_EDGE_MARGIN3 = 4;
|
|
19410
19613
|
function GridToolbarSlot({ gridRect, children }) {
|
|
19411
19614
|
const slotRef = (0, import_react11.useRef)(null);
|
|
19412
19615
|
const [shift, setShift] = (0, import_react11.useState)(0);
|
|
@@ -19418,7 +19621,7 @@ function GridToolbarSlot({ gridRect, children }) {
|
|
|
19418
19621
|
const w = slot.offsetWidth;
|
|
19419
19622
|
if (w <= 0) return;
|
|
19420
19623
|
const half = w / 2;
|
|
19421
|
-
const clamped = Math.max(
|
|
19624
|
+
const clamped = Math.max(TOOLBAR_EDGE_MARGIN3 + half, Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN3 - half));
|
|
19422
19625
|
setShift((prev) => Math.abs(prev - (clamped - centerX)) < 0.5 ? prev : clamped - centerX);
|
|
19423
19626
|
};
|
|
19424
19627
|
clamp();
|
|
@@ -19427,7 +19630,7 @@ function GridToolbarSlot({ gridRect, children }) {
|
|
|
19427
19630
|
return () => ro.disconnect();
|
|
19428
19631
|
}, [centerX, children]);
|
|
19429
19632
|
const mobile = window.innerWidth <= 480;
|
|
19430
|
-
return /* @__PURE__ */ (0,
|
|
19633
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19431
19634
|
"div",
|
|
19432
19635
|
{
|
|
19433
19636
|
ref: slotRef,
|
|
@@ -19462,7 +19665,7 @@ function requestValidateTree2(postToParent2, tree) {
|
|
|
19462
19665
|
});
|
|
19463
19666
|
}
|
|
19464
19667
|
function StyleSwatch({ style }) {
|
|
19465
|
-
return /* @__PURE__ */ (0,
|
|
19668
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19466
19669
|
"span",
|
|
19467
19670
|
{
|
|
19468
19671
|
"aria-hidden": true,
|
|
@@ -19476,35 +19679,35 @@ function StyleSwatch({ style }) {
|
|
|
19476
19679
|
);
|
|
19477
19680
|
}
|
|
19478
19681
|
function ButtonGlyph() {
|
|
19479
|
-
return /* @__PURE__ */ (0,
|
|
19480
|
-
/* @__PURE__ */ (0,
|
|
19481
|
-
/* @__PURE__ */ (0,
|
|
19682
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("svg", { width: "18", height: "12", viewBox: "0 0 18 12", fill: "none", "aria-hidden": true, style: { pointerEvents: "none" }, children: [
|
|
19683
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("rect", { x: "0.75", y: "0.75", width: "16.5", height: "10.5", rx: "3", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
19684
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M5.5 6H12.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
|
|
19482
19685
|
] });
|
|
19483
19686
|
}
|
|
19484
19687
|
function FeatureGlyph({ mode }) {
|
|
19485
|
-
return /* @__PURE__ */ (0,
|
|
19486
|
-
/* @__PURE__ */ (0,
|
|
19487
|
-
/* @__PURE__ */ (0,
|
|
19488
|
-
/* @__PURE__ */ (0,
|
|
19489
|
-
/* @__PURE__ */ (0,
|
|
19490
|
-
/* @__PURE__ */ (0,
|
|
19491
|
-
mode === "add" && /* @__PURE__ */ (0,
|
|
19688
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "none", "aria-hidden": true, style: { pointerEvents: "none" }, children: [
|
|
19689
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("circle", { cx: "8", cy: "8", r: "7.25", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
19690
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M5 8.2L7.2 10.3L11 6", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
19691
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("circle", { cx: "13.5", cy: "13.5", r: "4.25", fill: "var(--ohw-background, #ffffff)", stroke: "var(--ohw-background, #ffffff)", strokeWidth: "1" }),
|
|
19692
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("circle", { cx: "13.5", cy: "13.5", r: "3.75", fill: "var(--ohw-background, #ffffff)", stroke: PRIMARY4, strokeWidth: "1" }),
|
|
19693
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M11.5 13.5H15.5", stroke: PRIMARY4, strokeWidth: "1.5", strokeLinecap: "round" }),
|
|
19694
|
+
mode === "add" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M13.5 11.5V15.5", stroke: PRIMARY4, strokeWidth: "1.5", strokeLinecap: "round" })
|
|
19492
19695
|
] });
|
|
19493
19696
|
}
|
|
19494
|
-
function
|
|
19697
|
+
function ToolbarAction2({
|
|
19495
19698
|
label,
|
|
19496
19699
|
onClick,
|
|
19497
19700
|
disabled = false,
|
|
19498
19701
|
children
|
|
19499
19702
|
}) {
|
|
19500
|
-
const button = /* @__PURE__ */ (0,
|
|
19501
|
-
return /* @__PURE__ */ (0,
|
|
19502
|
-
/* @__PURE__ */ (0,
|
|
19503
|
-
/* @__PURE__ */ (0,
|
|
19703
|
+
const button = /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CustomToolbarButton, { type: "button", "aria-label": label, disabled, onClick, className: "size-8", children });
|
|
19704
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Tooltip, { children: [
|
|
19705
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "inline-flex", children: button }) : button }),
|
|
19706
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: label })
|
|
19504
19707
|
] });
|
|
19505
19708
|
}
|
|
19506
|
-
function
|
|
19507
|
-
return /* @__PURE__ */ (0,
|
|
19709
|
+
function ToolbarSeparator2() {
|
|
19710
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { "aria-hidden": true, className: "mx-0.5 block h-6 w-px shrink-0 bg-border" });
|
|
19508
19711
|
}
|
|
19509
19712
|
function CardStyleMenu({
|
|
19510
19713
|
value,
|
|
@@ -19512,7 +19715,7 @@ function CardStyleMenu({
|
|
|
19512
19715
|
disabled = false
|
|
19513
19716
|
}) {
|
|
19514
19717
|
const current = PRICING_CARD_STYLES.find((s) => s.value === value) ?? PRICING_CARD_STYLES[0];
|
|
19515
|
-
const trigger = /* @__PURE__ */ (0,
|
|
19718
|
+
const trigger = /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
19516
19719
|
"button",
|
|
19517
19720
|
{
|
|
19518
19721
|
type: "button",
|
|
@@ -19523,28 +19726,28 @@ function CardStyleMenu({
|
|
|
19523
19726
|
disabled && "cursor-not-allowed opacity-40 hover:bg-transparent"
|
|
19524
19727
|
),
|
|
19525
19728
|
children: [
|
|
19526
|
-
/* @__PURE__ */ (0,
|
|
19527
|
-
/* @__PURE__ */ (0,
|
|
19528
|
-
/* @__PURE__ */ (0,
|
|
19729
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(StyleSwatch, { style: current.value }),
|
|
19730
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "flex-1 text-left", children: current.label }),
|
|
19731
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.ChevronDown, { size: 16, style: { pointerEvents: "none" } })
|
|
19529
19732
|
]
|
|
19530
19733
|
}
|
|
19531
19734
|
);
|
|
19532
19735
|
if (disabled) {
|
|
19533
|
-
return /* @__PURE__ */ (0,
|
|
19534
|
-
/* @__PURE__ */ (0,
|
|
19535
|
-
/* @__PURE__ */ (0,
|
|
19536
|
-
/* @__PURE__ */ (0,
|
|
19537
|
-
/* @__PURE__ */ (0,
|
|
19736
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19737
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-xs text-muted-foreground opacity-50", children: "Card style" }),
|
|
19738
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Tooltip, { children: [
|
|
19739
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "inline-flex", children: trigger }) }),
|
|
19740
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: "Mark as featured to edit card style" })
|
|
19538
19741
|
] })
|
|
19539
19742
|
] });
|
|
19540
19743
|
}
|
|
19541
|
-
return /* @__PURE__ */ (0,
|
|
19542
|
-
/* @__PURE__ */ (0,
|
|
19543
|
-
/* @__PURE__ */ (0,
|
|
19544
|
-
/* @__PURE__ */ (0,
|
|
19545
|
-
/* @__PURE__ */ (0,
|
|
19744
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19745
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-xs text-muted-foreground", children: "Card style" }),
|
|
19746
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(DropdownMenu, { modal: false, children: [
|
|
19747
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DropdownMenuTrigger, { asChild: true, children: trigger }),
|
|
19748
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DropdownMenuContent, { align: "end", sideOffset: 8, className: "w-[152px] min-w-[152px] p-1", children: PRICING_CARD_STYLES.map((style) => {
|
|
19546
19749
|
const selected = style.value === value;
|
|
19547
|
-
return /* @__PURE__ */ (0,
|
|
19750
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
19548
19751
|
DropdownMenuItem,
|
|
19549
19752
|
{
|
|
19550
19753
|
role: "menuitemradio",
|
|
@@ -19552,9 +19755,9 @@ function CardStyleMenu({
|
|
|
19552
19755
|
onSelect: () => onChange(style.value),
|
|
19553
19756
|
className: cn("grid grid-cols-[18px_1fr_16px] gap-2 py-2 pl-2 pr-2 text-[13px]", selected && "bg-muted"),
|
|
19554
19757
|
children: [
|
|
19555
|
-
/* @__PURE__ */ (0,
|
|
19556
|
-
/* @__PURE__ */ (0,
|
|
19557
|
-
selected && /* @__PURE__ */ (0,
|
|
19758
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(StyleSwatch, { style: style.value }),
|
|
19759
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { children: style.label }),
|
|
19760
|
+
selected && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Check, { size: 16, className: "text-bridge-primary" })
|
|
19558
19761
|
]
|
|
19559
19762
|
},
|
|
19560
19763
|
style.value
|
|
@@ -19584,7 +19787,7 @@ function PricingCardToolbar({
|
|
|
19584
19787
|
const style = pricingCardStyle(entry.tree, index);
|
|
19585
19788
|
const featuredTag = pricingCardFeaturedTag(entry.tree, index);
|
|
19586
19789
|
const mobile = window.innerWidth <= 480;
|
|
19587
|
-
return /* @__PURE__ */ (0,
|
|
19790
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
19588
19791
|
"div",
|
|
19589
19792
|
{
|
|
19590
19793
|
"data-ohw-bridge": "",
|
|
@@ -19596,7 +19799,7 @@ function PricingCardToolbar({
|
|
|
19596
19799
|
),
|
|
19597
19800
|
style: { maxWidth: mobile ? "calc(100vw - 24px)" : void 0 },
|
|
19598
19801
|
children: [
|
|
19599
|
-
/* @__PURE__ */ (0,
|
|
19802
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
19600
19803
|
"div",
|
|
19601
19804
|
{
|
|
19602
19805
|
className: cn(
|
|
@@ -19605,8 +19808,8 @@ function PricingCardToolbar({
|
|
|
19605
19808
|
mobile ? "flex-wrap justify-center" : "flex-nowrap"
|
|
19606
19809
|
),
|
|
19607
19810
|
children: [
|
|
19608
|
-
/* @__PURE__ */ (0,
|
|
19609
|
-
/* @__PURE__ */ (0,
|
|
19811
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Tooltip, { children: [
|
|
19812
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19610
19813
|
CustomToolbarButton,
|
|
19611
19814
|
{
|
|
19612
19815
|
type: "button",
|
|
@@ -19614,8 +19817,8 @@ function PricingCardToolbar({
|
|
|
19614
19817
|
"aria-pressed": featuredTag,
|
|
19615
19818
|
onClick: () => onSetFeaturedTag(!featuredTag),
|
|
19616
19819
|
className: "group size-8",
|
|
19617
|
-
children: /* @__PURE__ */ (0,
|
|
19618
|
-
|
|
19820
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19821
|
+
import_lucide_react10.Star,
|
|
19619
19822
|
{
|
|
19620
19823
|
size: 16,
|
|
19621
19824
|
fill: "currentColor",
|
|
@@ -19629,25 +19832,25 @@ function PricingCardToolbar({
|
|
|
19629
19832
|
)
|
|
19630
19833
|
}
|
|
19631
19834
|
) }),
|
|
19632
|
-
/* @__PURE__ */ (0,
|
|
19835
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: featuredTag ? "Unmark featured" : "Mark as featured" })
|
|
19633
19836
|
] }),
|
|
19634
|
-
/* @__PURE__ */ (0,
|
|
19635
|
-
/* @__PURE__ */ (0,
|
|
19636
|
-
/* @__PURE__ */ (0,
|
|
19637
|
-
/* @__PURE__ */ (0,
|
|
19638
|
-
/* @__PURE__ */ (0,
|
|
19639
|
-
/* @__PURE__ */ (0,
|
|
19640
|
-
/* @__PURE__ */ (0,
|
|
19837
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarSeparator2, {}),
|
|
19838
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CardStyleMenu, { value: style, onChange: onSetStyle, disabled: !featuredTag }),
|
|
19839
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarSeparator2, {}),
|
|
19840
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarAction2, { label: "Add button", onClick: onAddButton, disabled: buttonCount >= 2, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ButtonGlyph, {}) }),
|
|
19841
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarAction2, { label: "Remove button", onClick: onRemoveButton, disabled: buttonCount === 0, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { className: "relative inline-flex", children: [
|
|
19842
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ButtonGlyph, {}),
|
|
19843
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Minus, { size: 10, strokeWidth: 2.5, className: "absolute -right-1.5 -top-1.5 rounded-full bg-background text-bridge-primary" })
|
|
19641
19844
|
] }) }),
|
|
19642
|
-
/* @__PURE__ */ (0,
|
|
19643
|
-
/* @__PURE__ */ (0,
|
|
19644
|
-
/* @__PURE__ */ (0,
|
|
19645
|
-
/* @__PURE__ */ (0,
|
|
19646
|
-
/* @__PURE__ */ (0,
|
|
19845
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarAction2, { label: "Add feature", onClick: onAddFeature, disabled: featureCount >= 10, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(FeatureGlyph, { mode: "add" }) }),
|
|
19846
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarAction2, { label: "Remove feature", onClick: onRemoveFeature, disabled: featureCount <= 1, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(FeatureGlyph, { mode: "remove" }) }),
|
|
19847
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarSeparator2, {}),
|
|
19848
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarAction2, { label: "Add tier", onClick: onAddTier, disabled: collectionCount >= 4, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Plus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19849
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarAction2, { label: "Remove tier", onClick: onRemoveTier, disabled: collectionCount <= 1, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Minus, { size: 16, style: { pointerEvents: "none" } }) })
|
|
19647
19850
|
]
|
|
19648
19851
|
}
|
|
19649
19852
|
),
|
|
19650
|
-
error && /* @__PURE__ */ (0,
|
|
19853
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "max-w-[260px] rounded-md bg-background px-2 py-1 text-center text-[11px] text-destructive shadow-sm", children: error })
|
|
19651
19854
|
]
|
|
19652
19855
|
}
|
|
19653
19856
|
) });
|
|
@@ -19681,7 +19884,7 @@ function AiPricingCardOverlay({
|
|
|
19681
19884
|
const overEditable = Boolean(t?.closest?.("[data-ohw-editable], [data-ohw-role], a, button"));
|
|
19682
19885
|
setHover((prev) => {
|
|
19683
19886
|
const next = ref && !overEditable ? ref : null;
|
|
19684
|
-
return
|
|
19887
|
+
return sameRef2(prev, next) ? prev : next;
|
|
19685
19888
|
});
|
|
19686
19889
|
};
|
|
19687
19890
|
const onLeave = () => setHover(null);
|
|
@@ -19696,10 +19899,10 @@ function AiPricingCardOverlay({
|
|
|
19696
19899
|
const onClick = (e) => {
|
|
19697
19900
|
const t = e.target;
|
|
19698
19901
|
if (!(t instanceof Element)) return;
|
|
19699
|
-
if (t.closest(
|
|
19902
|
+
if (t.closest(CHROME_SELECTOR2)) return;
|
|
19700
19903
|
const ref = cardRefFromTarget(t);
|
|
19701
|
-
setActive((prev) =>
|
|
19702
|
-
if (!ref || !
|
|
19904
|
+
setActive((prev) => sameRef2(prev, ref) ? prev : ref);
|
|
19905
|
+
if (!ref || !sameRef2(activeRef.current, ref)) setError(null);
|
|
19703
19906
|
};
|
|
19704
19907
|
document.addEventListener("click", onClick, true);
|
|
19705
19908
|
return () => document.removeEventListener("click", onClick, true);
|
|
@@ -19764,12 +19967,12 @@ function AiPricingCardOverlay({
|
|
|
19764
19967
|
const activeEntry = active ? findEntry(active.sectionId) : null;
|
|
19765
19968
|
const activeCardRect = useLiveCardRect(active);
|
|
19766
19969
|
const activeGridRect = useLiveCardRect(active, true);
|
|
19767
|
-
const hoverRect = useLiveCardRect(hover && !
|
|
19768
|
-
return /* @__PURE__ */ (0,
|
|
19769
|
-
hoverRect && /* @__PURE__ */ (0,
|
|
19770
|
-
activeCardRect && activeGridRect && active && activeEntry && /* @__PURE__ */ (0,
|
|
19771
|
-
/* @__PURE__ */ (0,
|
|
19772
|
-
/* @__PURE__ */ (0,
|
|
19970
|
+
const hoverRect = useLiveCardRect(hover && !sameRef2(hover, active) ? hover : null);
|
|
19971
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
19972
|
+
hoverRect && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ItemInteractionLayer, { rect: hoverRect, state: "hover" }),
|
|
19973
|
+
activeCardRect && activeGridRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
19974
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ItemInteractionLayer, { rect: activeCardRect, state: "active-top" }),
|
|
19975
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(GridToolbarSlot, { gridRect: activeGridRect, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19773
19976
|
PricingCardToolbar,
|
|
19774
19977
|
{
|
|
19775
19978
|
entry: activeEntry,
|
|
@@ -19797,7 +20000,7 @@ function AiPricingCardOverlay({
|
|
|
19797
20000
|
onRemoveFeature: () => runMutation(active.sectionId, (tree) => removePricingCardFeature(tree, active.index))
|
|
19798
20001
|
}
|
|
19799
20002
|
) }),
|
|
19800
|
-
/* @__PURE__ */ (0,
|
|
20003
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19801
20004
|
"div",
|
|
19802
20005
|
{
|
|
19803
20006
|
"data-ohw-bridge": "",
|
|
@@ -19819,7 +20022,7 @@ function AiPricingCardOverlay({
|
|
|
19819
20022
|
|
|
19820
20023
|
// src/ui/ai-section/AiVideoOverlay.tsx
|
|
19821
20024
|
var import_react12 = require("react");
|
|
19822
|
-
var
|
|
20025
|
+
var import_lucide_react11 = require("lucide-react");
|
|
19823
20026
|
|
|
19824
20027
|
// src/lib/ai-video-tree.ts
|
|
19825
20028
|
function resolveVideoBlock(tree, path) {
|
|
@@ -19890,10 +20093,10 @@ function extractYouTubeId(input) {
|
|
|
19890
20093
|
}
|
|
19891
20094
|
|
|
19892
20095
|
// src/ui/ai-section/AiVideoOverlay.tsx
|
|
19893
|
-
var
|
|
20096
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
19894
20097
|
var PRIMARY5 = "#0885FE";
|
|
19895
|
-
var
|
|
19896
|
-
var
|
|
20098
|
+
var OHW_BLUE = `var(--ohw-primary, ${PRIMARY5})`;
|
|
20099
|
+
var OHW_BLUE_DARK = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY5}) 60%, #000000)`;
|
|
19897
20100
|
function findVideoBlockElement(sectionId, path) {
|
|
19898
20101
|
const sectionEl = findByInstanceId(sectionId);
|
|
19899
20102
|
if (!sectionEl) return null;
|
|
@@ -19953,12 +20156,12 @@ function requestValidateTree3(postToParent2, tree) {
|
|
|
19953
20156
|
postToParent2({ type: "ow:ai-validate-tree-request", id, tree });
|
|
19954
20157
|
});
|
|
19955
20158
|
}
|
|
19956
|
-
function
|
|
20159
|
+
function Pill({
|
|
19957
20160
|
label,
|
|
19958
20161
|
onClick,
|
|
19959
20162
|
disabled
|
|
19960
20163
|
}) {
|
|
19961
|
-
return /* @__PURE__ */ (0,
|
|
20164
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
19962
20165
|
"button",
|
|
19963
20166
|
{
|
|
19964
20167
|
type: "button",
|
|
@@ -19974,7 +20177,7 @@ function Pill2({
|
|
|
19974
20177
|
border: "none",
|
|
19975
20178
|
cursor: disabled ? "default" : "pointer",
|
|
19976
20179
|
background: "#ffffff",
|
|
19977
|
-
color:
|
|
20180
|
+
color: OHW_BLUE_DARK,
|
|
19978
20181
|
opacity: disabled ? 0.4 : 1,
|
|
19979
20182
|
fontSize: 12,
|
|
19980
20183
|
lineHeight: "16px",
|
|
@@ -19996,7 +20199,7 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
19996
20199
|
setDraft(value ? watchUrl(value) : "");
|
|
19997
20200
|
setInvalid(false);
|
|
19998
20201
|
}, [value]);
|
|
19999
|
-
const
|
|
20202
|
+
const commit2 = () => {
|
|
20000
20203
|
const next = draft.trim();
|
|
20001
20204
|
if (!next) {
|
|
20002
20205
|
setInvalid(false);
|
|
@@ -20017,8 +20220,8 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20017
20220
|
onCommit(id);
|
|
20018
20221
|
}
|
|
20019
20222
|
};
|
|
20020
|
-
return /* @__PURE__ */ (0,
|
|
20021
|
-
/* @__PURE__ */ (0,
|
|
20223
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 4, width: "100%", maxWidth: 280 }, children: [
|
|
20224
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
20022
20225
|
"div",
|
|
20023
20226
|
{
|
|
20024
20227
|
style: {
|
|
@@ -20034,12 +20237,12 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20034
20237
|
boxShadow: invalid ? "inset 0 0 0 1.5px #EF4444" : "none"
|
|
20035
20238
|
},
|
|
20036
20239
|
children: [
|
|
20037
|
-
/* @__PURE__ */ (0,
|
|
20240
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20038
20241
|
"span",
|
|
20039
20242
|
{
|
|
20040
20243
|
style: {
|
|
20041
20244
|
flex: "0 0 auto",
|
|
20042
|
-
color:
|
|
20245
|
+
color: OHW_BLUE_DARK,
|
|
20043
20246
|
fontSize: 10,
|
|
20044
20247
|
lineHeight: "16px",
|
|
20045
20248
|
fontWeight: 700,
|
|
@@ -20049,14 +20252,14 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20049
20252
|
children: "Video"
|
|
20050
20253
|
}
|
|
20051
20254
|
),
|
|
20052
|
-
/* @__PURE__ */ (0,
|
|
20255
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20053
20256
|
"input",
|
|
20054
20257
|
{
|
|
20055
20258
|
type: "text",
|
|
20056
20259
|
inputMode: "url",
|
|
20057
20260
|
value: draft,
|
|
20058
20261
|
onChange: (e) => handleChange(e.target.value),
|
|
20059
|
-
onBlur:
|
|
20262
|
+
onBlur: commit2,
|
|
20060
20263
|
onKeyDown: (e) => {
|
|
20061
20264
|
if (e.key === "Enter") e.currentTarget.blur();
|
|
20062
20265
|
if (e.key === "Escape") {
|
|
@@ -20086,7 +20289,7 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20086
20289
|
]
|
|
20087
20290
|
}
|
|
20088
20291
|
),
|
|
20089
|
-
invalid && /* @__PURE__ */ (0,
|
|
20292
|
+
invalid && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { color: "#FCA5A5", fontSize: 11, textAlign: "center" }, children: "That doesn't look like a YouTube link \u2014 try pasting the video URL again." })
|
|
20090
20293
|
] });
|
|
20091
20294
|
}
|
|
20092
20295
|
function VideoToolbar({
|
|
@@ -20096,7 +20299,7 @@ function VideoToolbar({
|
|
|
20096
20299
|
onSetVideoId,
|
|
20097
20300
|
onRemove
|
|
20098
20301
|
}) {
|
|
20099
|
-
return /* @__PURE__ */ (0,
|
|
20302
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
20100
20303
|
"div",
|
|
20101
20304
|
{
|
|
20102
20305
|
"data-ohw-bridge": "",
|
|
@@ -20108,7 +20311,7 @@ function VideoToolbar({
|
|
|
20108
20311
|
gap: 6,
|
|
20109
20312
|
alignItems: "center",
|
|
20110
20313
|
width: 280,
|
|
20111
|
-
background:
|
|
20314
|
+
background: OHW_BLUE,
|
|
20112
20315
|
padding: 8,
|
|
20113
20316
|
borderRadius: 12,
|
|
20114
20317
|
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
@@ -20116,9 +20319,9 @@ function VideoToolbar({
|
|
|
20116
20319
|
opacity: pending ? 0.6 : 1
|
|
20117
20320
|
},
|
|
20118
20321
|
children: [
|
|
20119
|
-
/* @__PURE__ */ (0,
|
|
20120
|
-
/* @__PURE__ */ (0,
|
|
20121
|
-
error && /* @__PURE__ */ (0,
|
|
20322
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(VideoUrlInput, { value: videoId, onCommit: onSetVideoId }),
|
|
20323
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Pill, { label: "Remove video", onClick: onRemove, disabled: !videoId }),
|
|
20324
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { color: "#FCA5A5", fontSize: 11, maxWidth: 220, textAlign: "center" }, children: error })
|
|
20122
20325
|
]
|
|
20123
20326
|
}
|
|
20124
20327
|
);
|
|
@@ -20238,8 +20441,8 @@ function AiVideoOverlay({
|
|
|
20238
20441
|
const activeBlockRect = useLiveBlockRect(active);
|
|
20239
20442
|
const TOOLBAR_APPROX_H = 90;
|
|
20240
20443
|
const toolbarState = activeBlockRect && activeBlockRect.top < TOOLBAR_APPROX_H ? "active-bottom" : "active-top";
|
|
20241
|
-
return /* @__PURE__ */ (0,
|
|
20242
|
-
hoverHandleRect && hover && /* @__PURE__ */ (0,
|
|
20444
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
20445
|
+
hoverHandleRect && hover && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20243
20446
|
"button",
|
|
20244
20447
|
{
|
|
20245
20448
|
type: "button",
|
|
@@ -20267,15 +20470,15 @@ function AiVideoOverlay({
|
|
|
20267
20470
|
fontSize: 14,
|
|
20268
20471
|
fontWeight: 700
|
|
20269
20472
|
},
|
|
20270
|
-
children: /* @__PURE__ */ (0,
|
|
20473
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.Star, { size: 14, style: { pointerEvents: "none" } })
|
|
20271
20474
|
}
|
|
20272
20475
|
),
|
|
20273
|
-
activeBlockRect && active && activeEntry && /* @__PURE__ */ (0,
|
|
20476
|
+
activeBlockRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20274
20477
|
ItemInteractionLayer,
|
|
20275
20478
|
{
|
|
20276
20479
|
rect: activeBlockRect,
|
|
20277
20480
|
state: toolbarState,
|
|
20278
|
-
toolbar: /* @__PURE__ */ (0,
|
|
20481
|
+
toolbar: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20279
20482
|
VideoToolbar,
|
|
20280
20483
|
{
|
|
20281
20484
|
videoId: videoIdAt(activeEntry.tree, active.path),
|
|
@@ -20299,7 +20502,7 @@ function AiVideoOverlay({
|
|
|
20299
20502
|
|
|
20300
20503
|
// src/ui/ai-section/AiFadeCarouselOverlay.tsx
|
|
20301
20504
|
var import_react13 = require("react");
|
|
20302
|
-
var
|
|
20505
|
+
var import_lucide_react12 = require("lucide-react");
|
|
20303
20506
|
|
|
20304
20507
|
// src/lib/ai-carousel-tree.ts
|
|
20305
20508
|
function isCarouselBlock(node) {
|
|
@@ -20350,10 +20553,10 @@ function setCarouselAutoplay(tree, on) {
|
|
|
20350
20553
|
}
|
|
20351
20554
|
|
|
20352
20555
|
// src/ui/ai-section/AiFadeCarouselOverlay.tsx
|
|
20353
|
-
var
|
|
20556
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
20354
20557
|
var PRIMARY6 = "#0885FE";
|
|
20355
|
-
var
|
|
20356
|
-
var
|
|
20558
|
+
var OHW_BLUE2 = `var(--ohw-primary, ${PRIMARY6})`;
|
|
20559
|
+
var OHW_BLUE_DARK2 = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY6}) 60%, #000000)`;
|
|
20357
20560
|
function findCarouselItemElement(sectionId, index) {
|
|
20358
20561
|
const sectionEl = findByInstanceId(sectionId);
|
|
20359
20562
|
if (!sectionEl) return null;
|
|
@@ -20432,8 +20635,8 @@ function requestAssetPick2(postToParent2) {
|
|
|
20432
20635
|
postToParent2({ type: "ow:asset-pick", id });
|
|
20433
20636
|
});
|
|
20434
20637
|
}
|
|
20435
|
-
function
|
|
20436
|
-
return /* @__PURE__ */ (0,
|
|
20638
|
+
function Pill2({ label, onClick, disabled }) {
|
|
20639
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20437
20640
|
"button",
|
|
20438
20641
|
{
|
|
20439
20642
|
type: "button",
|
|
@@ -20449,7 +20652,7 @@ function Pill3({ label, onClick, disabled }) {
|
|
|
20449
20652
|
border: "none",
|
|
20450
20653
|
cursor: disabled ? "default" : "pointer",
|
|
20451
20654
|
background: "#ffffff",
|
|
20452
|
-
color:
|
|
20655
|
+
color: OHW_BLUE_DARK2,
|
|
20453
20656
|
opacity: disabled ? 0.4 : 1,
|
|
20454
20657
|
fontSize: 12,
|
|
20455
20658
|
lineHeight: "16px",
|
|
@@ -20467,7 +20670,7 @@ function TogglePill({
|
|
|
20467
20670
|
onToggle,
|
|
20468
20671
|
disabled
|
|
20469
20672
|
}) {
|
|
20470
|
-
return /* @__PURE__ */ (0,
|
|
20673
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
20471
20674
|
"button",
|
|
20472
20675
|
{
|
|
20473
20676
|
type: "button",
|
|
@@ -20486,7 +20689,7 @@ function TogglePill({
|
|
|
20486
20689
|
border: "none",
|
|
20487
20690
|
cursor: disabled ? "default" : "pointer",
|
|
20488
20691
|
background: "#ffffff",
|
|
20489
|
-
color:
|
|
20692
|
+
color: OHW_BLUE_DARK2,
|
|
20490
20693
|
opacity: disabled ? 0.4 : 1,
|
|
20491
20694
|
fontSize: 12,
|
|
20492
20695
|
lineHeight: "16px",
|
|
@@ -20496,7 +20699,7 @@ function TogglePill({
|
|
|
20496
20699
|
},
|
|
20497
20700
|
children: [
|
|
20498
20701
|
label,
|
|
20499
|
-
/* @__PURE__ */ (0,
|
|
20702
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20500
20703
|
"span",
|
|
20501
20704
|
{
|
|
20502
20705
|
"aria-hidden": true,
|
|
@@ -20509,10 +20712,10 @@ function TogglePill({
|
|
|
20509
20712
|
// Off is a grey track, not a washed-out blue: the pill's own white background already
|
|
20510
20713
|
// carries the brand colour in the text, and a pale blue track next to it read as
|
|
20511
20714
|
// "disabled control" rather than "switch that is off".
|
|
20512
|
-
background: on ?
|
|
20715
|
+
background: on ? OHW_BLUE_DARK2 : "#CBD5E1",
|
|
20513
20716
|
transition: "background 120ms ease"
|
|
20514
20717
|
},
|
|
20515
|
-
children: /* @__PURE__ */ (0,
|
|
20718
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20516
20719
|
"span",
|
|
20517
20720
|
{
|
|
20518
20721
|
style: {
|
|
@@ -20541,7 +20744,7 @@ function CarouselSlideToolbar({
|
|
|
20541
20744
|
onChangeImage,
|
|
20542
20745
|
onToggleAutoplay
|
|
20543
20746
|
}) {
|
|
20544
|
-
return /* @__PURE__ */ (0,
|
|
20747
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
20545
20748
|
"div",
|
|
20546
20749
|
{
|
|
20547
20750
|
"data-ohw-bridge": "",
|
|
@@ -20552,7 +20755,7 @@ function CarouselSlideToolbar({
|
|
|
20552
20755
|
flexDirection: "column",
|
|
20553
20756
|
gap: 6,
|
|
20554
20757
|
alignItems: "center",
|
|
20555
|
-
background:
|
|
20758
|
+
background: OHW_BLUE2,
|
|
20556
20759
|
padding: 8,
|
|
20557
20760
|
borderRadius: 12,
|
|
20558
20761
|
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
@@ -20564,11 +20767,11 @@ function CarouselSlideToolbar({
|
|
|
20564
20767
|
pointerEvents: pending ? "none" : "auto"
|
|
20565
20768
|
},
|
|
20566
20769
|
children: [
|
|
20567
|
-
/* @__PURE__ */ (0,
|
|
20568
|
-
/* @__PURE__ */ (0,
|
|
20569
|
-
/* @__PURE__ */ (0,
|
|
20770
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { display: "flex", gap: 6, alignItems: "center" }, children: [
|
|
20771
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Pill2, { label: "Change Image", onClick: onChangeImage }),
|
|
20772
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(TogglePill, { label: "Autoplay", on: autoplay, onToggle: onToggleAutoplay })
|
|
20570
20773
|
] }),
|
|
20571
|
-
error && /* @__PURE__ */ (0,
|
|
20774
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { color: "#FCA5A5", fontSize: 11, maxWidth: 220, textAlign: "center" }, children: error })
|
|
20572
20775
|
]
|
|
20573
20776
|
}
|
|
20574
20777
|
);
|
|
@@ -20708,8 +20911,8 @@ function AiFadeCarouselOverlay({
|
|
|
20708
20911
|
const activeItemRect = useLiveItemRect2(active);
|
|
20709
20912
|
const TOOLBAR_APPROX_H = 90;
|
|
20710
20913
|
const toolbarState = activeItemRect && activeItemRect.top < TOOLBAR_APPROX_H ? "active-bottom" : "active-top";
|
|
20711
|
-
return /* @__PURE__ */ (0,
|
|
20712
|
-
hoverHandleRect && hover && /* @__PURE__ */ (0,
|
|
20914
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
20915
|
+
hoverHandleRect && hover && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20713
20916
|
"button",
|
|
20714
20917
|
{
|
|
20715
20918
|
type: "button",
|
|
@@ -20738,10 +20941,10 @@ function AiFadeCarouselOverlay({
|
|
|
20738
20941
|
fontSize: 14,
|
|
20739
20942
|
fontWeight: 700
|
|
20740
20943
|
},
|
|
20741
|
-
children: /* @__PURE__ */ (0,
|
|
20944
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react12.Star, { size: 14, style: { pointerEvents: "none" } })
|
|
20742
20945
|
}
|
|
20743
20946
|
),
|
|
20744
|
-
swapping && /* @__PURE__ */ (0,
|
|
20947
|
+
swapping && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20745
20948
|
"div",
|
|
20746
20949
|
{
|
|
20747
20950
|
ref: skeletonRef,
|
|
@@ -20759,15 +20962,15 @@ function AiFadeCarouselOverlay({
|
|
|
20759
20962
|
zIndex: 2147483646,
|
|
20760
20963
|
pointerEvents: "none"
|
|
20761
20964
|
},
|
|
20762
|
-
children: /* @__PURE__ */ (0,
|
|
20965
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("style", { children: MEDIA_SKELETON_CSS })
|
|
20763
20966
|
}
|
|
20764
20967
|
),
|
|
20765
|
-
activeItemRect && active && activeEntry && /* @__PURE__ */ (0,
|
|
20968
|
+
activeItemRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20766
20969
|
ItemInteractionLayer,
|
|
20767
20970
|
{
|
|
20768
20971
|
rect: activeItemRect,
|
|
20769
20972
|
state: toolbarState,
|
|
20770
|
-
toolbar: /* @__PURE__ */ (0,
|
|
20973
|
+
toolbar: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20771
20974
|
CarouselSlideToolbar,
|
|
20772
20975
|
{
|
|
20773
20976
|
pending,
|
|
@@ -20985,113 +21188,6 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
|
|
|
20985
21188
|
// src/ui/link-modal/LinkPopover.tsx
|
|
20986
21189
|
var import_react17 = require("react");
|
|
20987
21190
|
|
|
20988
|
-
// src/ui/dialog.tsx
|
|
20989
|
-
var React9 = __toESM(require("react"), 1);
|
|
20990
|
-
var import_radix_ui6 = require("radix-ui");
|
|
20991
|
-
var import_lucide_react12 = require("lucide-react");
|
|
20992
|
-
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
20993
|
-
function Dialog2({
|
|
20994
|
-
...props
|
|
20995
|
-
}) {
|
|
20996
|
-
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_radix_ui6.Dialog.Root, { "data-slot": "dialog", ...props });
|
|
20997
|
-
}
|
|
20998
|
-
function DialogPortal({
|
|
20999
|
-
...props
|
|
21000
|
-
}) {
|
|
21001
|
-
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_radix_ui6.Dialog.Portal, { ...props });
|
|
21002
|
-
}
|
|
21003
|
-
function DialogOverlay({
|
|
21004
|
-
className,
|
|
21005
|
-
...props
|
|
21006
|
-
}) {
|
|
21007
|
-
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
21008
|
-
import_radix_ui6.Dialog.Overlay,
|
|
21009
|
-
{
|
|
21010
|
-
"data-slot": "dialog-overlay",
|
|
21011
|
-
"data-ohw-link-modal-root": "",
|
|
21012
|
-
className: cn("fixed inset-0 z-[2147483646] bg-black/50", className),
|
|
21013
|
-
...props
|
|
21014
|
-
}
|
|
21015
|
-
);
|
|
21016
|
-
}
|
|
21017
|
-
var DialogContent = React9.forwardRef(
|
|
21018
|
-
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
21019
|
-
const positionMode = container ? "absolute" : "fixed";
|
|
21020
|
-
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(DialogPortal, { container: container ?? void 0, children: [
|
|
21021
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
21022
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
21023
|
-
import_radix_ui6.Dialog.Content,
|
|
21024
|
-
{
|
|
21025
|
-
ref,
|
|
21026
|
-
"data-slot": "dialog-content",
|
|
21027
|
-
className: cn(
|
|
21028
|
-
positionMode,
|
|
21029
|
-
"left-1/2 top-1/2 z-[2147483647] flex w-full max-w-[448px] -translate-x-1/2 -translate-y-1/2 flex-col overflow-visible",
|
|
21030
|
-
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
21031
|
-
container ? "max-h-[calc(100%-32px)]" : "max-h-[calc(100vh-32px)]",
|
|
21032
|
-
className
|
|
21033
|
-
),
|
|
21034
|
-
onMouseDown: (e) => e.stopPropagation(),
|
|
21035
|
-
...props,
|
|
21036
|
-
children: [
|
|
21037
|
-
children,
|
|
21038
|
-
showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
21039
|
-
import_radix_ui6.Dialog.Close,
|
|
21040
|
-
{
|
|
21041
|
-
type: "button",
|
|
21042
|
-
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
21043
|
-
"aria-label": "Close",
|
|
21044
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react12.X, { size: 16, "aria-hidden": true })
|
|
21045
|
-
}
|
|
21046
|
-
) : null
|
|
21047
|
-
]
|
|
21048
|
-
}
|
|
21049
|
-
)
|
|
21050
|
-
] });
|
|
21051
|
-
}
|
|
21052
|
-
);
|
|
21053
|
-
DialogContent.displayName = import_radix_ui6.Dialog.Content.displayName;
|
|
21054
|
-
function DialogHeader({
|
|
21055
|
-
className,
|
|
21056
|
-
...props
|
|
21057
|
-
}) {
|
|
21058
|
-
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
21059
|
-
}
|
|
21060
|
-
function DialogFooter({
|
|
21061
|
-
className,
|
|
21062
|
-
...props
|
|
21063
|
-
}) {
|
|
21064
|
-
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
21065
|
-
"div",
|
|
21066
|
-
{
|
|
21067
|
-
className: cn("flex items-center justify-end gap-2", className),
|
|
21068
|
-
...props
|
|
21069
|
-
}
|
|
21070
|
-
);
|
|
21071
|
-
}
|
|
21072
|
-
var DialogTitle = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
21073
|
-
import_radix_ui6.Dialog.Title,
|
|
21074
|
-
{
|
|
21075
|
-
ref,
|
|
21076
|
-
className: cn(
|
|
21077
|
-
"text-lg font-semibold leading-none tracking-tight text-card-foreground",
|
|
21078
|
-
className
|
|
21079
|
-
),
|
|
21080
|
-
...props
|
|
21081
|
-
}
|
|
21082
|
-
));
|
|
21083
|
-
DialogTitle.displayName = import_radix_ui6.Dialog.Title.displayName;
|
|
21084
|
-
var DialogDescription = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
21085
|
-
import_radix_ui6.Dialog.Description,
|
|
21086
|
-
{
|
|
21087
|
-
ref,
|
|
21088
|
-
className: cn("text-sm text-muted-foreground", className),
|
|
21089
|
-
...props
|
|
21090
|
-
}
|
|
21091
|
-
));
|
|
21092
|
-
DialogDescription.displayName = import_radix_ui6.Dialog.Description.displayName;
|
|
21093
|
-
var DialogClose = import_radix_ui6.Dialog.Close;
|
|
21094
|
-
|
|
21095
21191
|
// src/ui/link-modal/LinkEditorPanel.tsx
|
|
21096
21192
|
var import_lucide_react16 = require("lucide-react");
|
|
21097
21193
|
|
|
@@ -22195,6 +22291,7 @@ function shouldUseDevFixtures() {
|
|
|
22195
22291
|
function getLogoElement(el) {
|
|
22196
22292
|
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
22197
22293
|
if (marked) return marked;
|
|
22294
|
+
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
22198
22295
|
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
22199
22296
|
if (!root) return null;
|
|
22200
22297
|
const anchor = el.closest("a");
|
|
@@ -23889,6 +23986,102 @@ function deleteSelectedNavFooterItem(deps) {
|
|
|
23889
23986
|
return false;
|
|
23890
23987
|
}
|
|
23891
23988
|
|
|
23989
|
+
// src/lib/nav-page-sync.ts
|
|
23990
|
+
function labelKeyFor(hrefKey) {
|
|
23991
|
+
return hrefKey.replace(/-href$/, "-label");
|
|
23992
|
+
}
|
|
23993
|
+
function isPageLinkKey(key) {
|
|
23994
|
+
return isNavbarHrefKey(key) || isFooterHrefKey(key);
|
|
23995
|
+
}
|
|
23996
|
+
function currentHref(key, anchor, content) {
|
|
23997
|
+
const stored = content[key];
|
|
23998
|
+
if (typeof stored === "string" && stored.length > 0) return stored;
|
|
23999
|
+
return anchor.getAttribute("href") ?? "";
|
|
24000
|
+
}
|
|
24001
|
+
function normalizePath2(value) {
|
|
24002
|
+
if (value.length > 1 && value.endsWith("/")) return value.slice(0, -1);
|
|
24003
|
+
return value;
|
|
24004
|
+
}
|
|
24005
|
+
function pointsAt(href, path) {
|
|
24006
|
+
const normalized = normalizePath2(href);
|
|
24007
|
+
const target = normalizePath2(path);
|
|
24008
|
+
if (normalized === target) return true;
|
|
24009
|
+
return (normalized.startsWith(`${target}#`) || normalized.startsWith(`${target}?`)) && target !== "/";
|
|
24010
|
+
}
|
|
24011
|
+
function retargetHref(href, oldPath, newPath) {
|
|
24012
|
+
const normalized = normalizePath2(href);
|
|
24013
|
+
const target = normalizePath2(oldPath);
|
|
24014
|
+
if (normalized === target) return newPath;
|
|
24015
|
+
return `${newPath}${normalized.slice(target.length)}`;
|
|
24016
|
+
}
|
|
24017
|
+
function setLabelText(key, text) {
|
|
24018
|
+
document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`).forEach((el) => {
|
|
24019
|
+
el.textContent = text;
|
|
24020
|
+
});
|
|
24021
|
+
}
|
|
24022
|
+
function commit(delta, deps) {
|
|
24023
|
+
if (Object.keys(delta).length === 0) return;
|
|
24024
|
+
deps.setEditContent({ ...deps.getEditContent(), ...delta });
|
|
24025
|
+
deps.postToParent({
|
|
24026
|
+
type: "ow:change",
|
|
24027
|
+
nodes: Object.entries(delta).map(([key, text]) => ({ key, text }))
|
|
24028
|
+
});
|
|
24029
|
+
}
|
|
24030
|
+
function navLinksTo(path, content) {
|
|
24031
|
+
return Array.from(document.querySelectorAll("[data-ohw-href-key]")).filter((anchor) => {
|
|
24032
|
+
const key = anchor.getAttribute("data-ohw-href-key");
|
|
24033
|
+
return isNavbarHrefKey(key) && pointsAt(currentHref(key, anchor, content), path);
|
|
24034
|
+
}).map((anchor) => anchor.getAttribute("data-ohw-href-key"));
|
|
24035
|
+
}
|
|
24036
|
+
function addNavLinkForPage(page, deps) {
|
|
24037
|
+
const content = deps.getEditContent();
|
|
24038
|
+
if (navLinksTo(page.path, content).length > 0) return false;
|
|
24039
|
+
const roots = listNavbarRootItems();
|
|
24040
|
+
const afterAnchor = roots[roots.length - 1] ?? null;
|
|
24041
|
+
let inserted;
|
|
24042
|
+
try {
|
|
24043
|
+
inserted = insertNavbarItem(page.path, page.title, afterAnchor);
|
|
24044
|
+
} catch {
|
|
24045
|
+
return false;
|
|
24046
|
+
}
|
|
24047
|
+
const { hrefKey, labelKey, index } = inserted;
|
|
24048
|
+
deps.applyLinkByKey(hrefKey, page.path);
|
|
24049
|
+
setLabelText(labelKey, page.title);
|
|
24050
|
+
commit(
|
|
24051
|
+
{
|
|
24052
|
+
[hrefKey]: page.path,
|
|
24053
|
+
[labelKey]: page.title,
|
|
24054
|
+
[NAV_COUNT_KEY]: String(index + 1),
|
|
24055
|
+
[NAV_ORDER_KEY]: getNavbarOrderJson()
|
|
24056
|
+
},
|
|
24057
|
+
deps
|
|
24058
|
+
);
|
|
24059
|
+
return true;
|
|
24060
|
+
}
|
|
24061
|
+
function retargetPageLinks(change, deps) {
|
|
24062
|
+
const { oldPath, newPath, oldTitle, newTitle } = change;
|
|
24063
|
+
if (!oldPath || !newPath || normalizePath2(oldPath) === normalizePath2(newPath)) return 0;
|
|
24064
|
+
const content = deps.getEditContent();
|
|
24065
|
+
const delta = {};
|
|
24066
|
+
for (const anchor of Array.from(document.querySelectorAll("[data-ohw-href-key]"))) {
|
|
24067
|
+
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
24068
|
+
if (!isPageLinkKey(hrefKey)) continue;
|
|
24069
|
+
const href = currentHref(hrefKey, anchor, content);
|
|
24070
|
+
if (!pointsAt(href, oldPath)) continue;
|
|
24071
|
+
const nextHref = retargetHref(href, oldPath, newPath);
|
|
24072
|
+
deps.applyLinkByKey(hrefKey, nextHref);
|
|
24073
|
+
delta[hrefKey] = nextHref;
|
|
24074
|
+
if (!oldTitle || !newTitle) continue;
|
|
24075
|
+
const labelKey = labelKeyFor(hrefKey);
|
|
24076
|
+
const label = content[labelKey] ?? anchor.querySelector('[data-ohw-editable="text"]')?.textContent ?? "";
|
|
24077
|
+
if (label.trim() !== oldTitle) continue;
|
|
24078
|
+
setLabelText(labelKey, newTitle);
|
|
24079
|
+
delta[labelKey] = newTitle;
|
|
24080
|
+
}
|
|
24081
|
+
commit(delta, deps);
|
|
24082
|
+
return Object.keys(delta).filter((key) => key.endsWith("-href")).length;
|
|
24083
|
+
}
|
|
24084
|
+
|
|
23892
24085
|
// src/ui/navbar-container-chrome.tsx
|
|
23893
24086
|
var import_lucide_react21 = require("lucide-react");
|
|
23894
24087
|
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
@@ -24031,6 +24224,7 @@ function applyEditableImageSrc(img, url) {
|
|
|
24031
24224
|
img.removeAttribute("srcset");
|
|
24032
24225
|
img.removeAttribute("sizes");
|
|
24033
24226
|
if (img.loading === "lazy") img.loading = "eager";
|
|
24227
|
+
releaseTemplateLogoIfReplaced(img, url);
|
|
24034
24228
|
img.src = url;
|
|
24035
24229
|
}
|
|
24036
24230
|
function fadeInBgImage(el, url, onReady) {
|
|
@@ -24775,7 +24969,7 @@ function getNavigationSelectionParent(el) {
|
|
|
24775
24969
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
24776
24970
|
return resolveFooterLinksContainerFrom(el);
|
|
24777
24971
|
}
|
|
24778
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
|
|
24972
|
+
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isFooterLinksContainer(el) || isInferredFooterGroup2(el)) {
|
|
24779
24973
|
return getNavigationRoot(el);
|
|
24780
24974
|
}
|
|
24781
24975
|
return null;
|
|
@@ -24997,7 +25191,6 @@ var ICONS = {
|
|
|
24997
25191
|
insertUnorderedList: '<line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/>',
|
|
24998
25192
|
insertOrderedList: '<line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"/>'
|
|
24999
25193
|
};
|
|
25000
|
-
var HEIGHT_SETTLE_DELAYS = [150, 400, 800];
|
|
25001
25194
|
var SELECTION_CHROME_GAP2 = 4;
|
|
25002
25195
|
var TOOLBAR_STROKE_GAP2 = 4;
|
|
25003
25196
|
var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
|
|
@@ -25095,7 +25288,7 @@ function applyVisibleViewport(el, parentScroll) {
|
|
|
25095
25288
|
el.style.top = `${top}px`;
|
|
25096
25289
|
el.style.height = `${height}px`;
|
|
25097
25290
|
}
|
|
25098
|
-
var
|
|
25291
|
+
var TOOLBAR_EDGE_MARGIN4 = 4;
|
|
25099
25292
|
function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
25100
25293
|
const isAbove = transform.includes("translateY(-100%)");
|
|
25101
25294
|
let visualTop = isAbove ? top - approxH : top;
|
|
@@ -25122,8 +25315,8 @@ function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
|
25122
25315
|
function clampToolbarLeft(centerX, toolbarWidth) {
|
|
25123
25316
|
const half = toolbarWidth / 2;
|
|
25124
25317
|
return Math.max(
|
|
25125
|
-
|
|
25126
|
-
Math.min(centerX, window.innerWidth -
|
|
25318
|
+
TOOLBAR_EDGE_MARGIN4 + half,
|
|
25319
|
+
Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN4 - half)
|
|
25127
25320
|
);
|
|
25128
25321
|
}
|
|
25129
25322
|
function calcToolbarPos(rect, parentScroll, toolbarW = 306) {
|
|
@@ -26003,21 +26196,6 @@ function OhhwellsBridge() {
|
|
|
26003
26196
|
const [isItemDragging, setIsItemDragging] = (0, import_react21.useState)(false);
|
|
26004
26197
|
const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react21.useState)(false);
|
|
26005
26198
|
isFooterFrameSelectionRef.current = isFooterFrameSelection;
|
|
26006
|
-
const [floatingPanel, setFloatingPanel] = (0, import_react21.useState)(null);
|
|
26007
|
-
const floatingPanelOpenRef = (0, import_react21.useRef)(false);
|
|
26008
|
-
floatingPanelOpenRef.current = floatingPanel !== null;
|
|
26009
|
-
const floatingPanelRef = (0, import_react21.useRef)(null);
|
|
26010
|
-
floatingPanelRef.current = floatingPanel;
|
|
26011
|
-
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react21.useState)(null);
|
|
26012
|
-
const buttonCollectionDragRef = (0, import_react21.useRef)(null);
|
|
26013
|
-
const buttonDropInsertIndexRef = (0, import_react21.useRef)(null);
|
|
26014
|
-
const [buttonDropSlots, setButtonDropSlots] = (0, import_react21.useState)([]);
|
|
26015
|
-
const [activeButtonDropIndex, setActiveButtonDropIndex] = (0, import_react21.useState)(null);
|
|
26016
|
-
const buttonPointerDragRef = (0, import_react21.useRef)(null);
|
|
26017
|
-
const [buttonStyleTick, setButtonStyleTick] = (0, import_react21.useState)(0);
|
|
26018
|
-
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react21.useState)(null);
|
|
26019
|
-
const [editorViewport, setEditorViewport] = (0, import_react21.useState)("desktop");
|
|
26020
|
-
const [parentScrollSnap, setParentScrollSnap] = (0, import_react21.useState)(null);
|
|
26021
26199
|
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react21.useState)(null);
|
|
26022
26200
|
const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react21.useState)(null);
|
|
26023
26201
|
const footerDragRef = (0, import_react21.useRef)(null);
|
|
@@ -26043,6 +26221,21 @@ function OhhwellsBridge() {
|
|
|
26043
26221
|
const stylesRef = (0, import_react21.useRef)("");
|
|
26044
26222
|
const appliedDrawerRef = (0, import_react21.useRef)(null);
|
|
26045
26223
|
const pendingDeleteUndoRef = (0, import_react21.useRef)(null);
|
|
26224
|
+
const [floatingPanel, setFloatingPanel] = (0, import_react21.useState)(null);
|
|
26225
|
+
const floatingPanelOpenRef = (0, import_react21.useRef)(false);
|
|
26226
|
+
const floatingPanelRef = (0, import_react21.useRef)(null);
|
|
26227
|
+
floatingPanelRef.current = floatingPanel;
|
|
26228
|
+
const setFloatingPanelRef = (0, import_react21.useRef)(setFloatingPanel);
|
|
26229
|
+
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react21.useState)(null);
|
|
26230
|
+
const buttonCollectionDragRef = (0, import_react21.useRef)(null);
|
|
26231
|
+
const buttonDropInsertIndexRef = (0, import_react21.useRef)(null);
|
|
26232
|
+
const [buttonDropSlots, setButtonDropSlots] = (0, import_react21.useState)([]);
|
|
26233
|
+
const [activeButtonDropIndex, setActiveButtonDropIndex] = (0, import_react21.useState)(null);
|
|
26234
|
+
const buttonPointerDragRef = (0, import_react21.useRef)(null);
|
|
26235
|
+
const [buttonStyleTick, setButtonStyleTick] = (0, import_react21.useState)(0);
|
|
26236
|
+
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react21.useState)(null);
|
|
26237
|
+
const [editorViewport, setEditorViewport] = (0, import_react21.useState)("desktop");
|
|
26238
|
+
const [parentScrollSnap, setParentScrollSnap] = (0, import_react21.useState)(null);
|
|
26046
26239
|
const [sitePages, setSitePages] = (0, import_react21.useState)([]);
|
|
26047
26240
|
const collectionItemsRef = (0, import_react21.useRef)(/* @__PURE__ */ new Map());
|
|
26048
26241
|
const [sectionsByPath, setSectionsByPath] = (0, import_react21.useState)({});
|
|
@@ -26052,7 +26245,18 @@ function OhhwellsBridge() {
|
|
|
26052
26245
|
const linkPopoverOpenRef = (0, import_react21.useRef)(false);
|
|
26053
26246
|
const linkPopoverGraceUntilRef = (0, import_react21.useRef)(0);
|
|
26054
26247
|
setLinkPopoverRef.current = setLinkPopover;
|
|
26248
|
+
setFloatingPanelRef.current = setFloatingPanel;
|
|
26055
26249
|
linkPopoverSessionRef.current = linkPopover;
|
|
26250
|
+
floatingPanelOpenRef.current = Boolean(floatingPanel);
|
|
26251
|
+
(0, import_react21.useEffect)(() => {
|
|
26252
|
+
const syncViewport = () => {
|
|
26253
|
+
const next = window.innerWidth <= 480 ? "mobile" : "desktop";
|
|
26254
|
+
setEditorViewport((prev) => prev === next ? prev : next);
|
|
26255
|
+
};
|
|
26256
|
+
syncViewport();
|
|
26257
|
+
window.addEventListener("resize", syncViewport);
|
|
26258
|
+
return () => window.removeEventListener("resize", syncViewport);
|
|
26259
|
+
}, []);
|
|
26056
26260
|
(0, import_react21.useEffect)(() => {
|
|
26057
26261
|
setSectionOrderPersistHandler((entries) => {
|
|
26058
26262
|
const currentPath = window.location.pathname;
|
|
@@ -26201,6 +26405,43 @@ function OhhwellsBridge() {
|
|
|
26201
26405
|
if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
|
|
26202
26406
|
return () => window.removeEventListener("message", onSitePages);
|
|
26203
26407
|
}, [isEditMode, postToParent2]);
|
|
26408
|
+
(0, import_react21.useEffect)(() => {
|
|
26409
|
+
if (!isEditMode) return;
|
|
26410
|
+
const deps = {
|
|
26411
|
+
getEditContent: () => editContentRef.current,
|
|
26412
|
+
setEditContent: (next) => {
|
|
26413
|
+
editContentRef.current = next;
|
|
26414
|
+
},
|
|
26415
|
+
applyLinkByKey,
|
|
26416
|
+
postToParent: postToParent2
|
|
26417
|
+
};
|
|
26418
|
+
const onPageMessage = (e) => {
|
|
26419
|
+
if (e.data?.type === "ow:page-created") {
|
|
26420
|
+
const { path, title } = e.data;
|
|
26421
|
+
if (typeof path !== "string" || !path) return;
|
|
26422
|
+
if (addNavLinkForPage({ path, title: typeof title === "string" && title ? title : path }, deps)) {
|
|
26423
|
+
enforceLinkHrefs();
|
|
26424
|
+
}
|
|
26425
|
+
return;
|
|
26426
|
+
}
|
|
26427
|
+
if (e.data?.type === "ow:page-renamed") {
|
|
26428
|
+
const { oldPath, newPath, oldTitle, newTitle } = e.data;
|
|
26429
|
+
if (typeof oldPath !== "string" || typeof newPath !== "string") return;
|
|
26430
|
+
const moved = retargetPageLinks(
|
|
26431
|
+
{
|
|
26432
|
+
oldPath,
|
|
26433
|
+
newPath,
|
|
26434
|
+
oldTitle: typeof oldTitle === "string" ? oldTitle : void 0,
|
|
26435
|
+
newTitle: typeof newTitle === "string" ? newTitle : void 0
|
|
26436
|
+
},
|
|
26437
|
+
deps
|
|
26438
|
+
);
|
|
26439
|
+
if (moved > 0) enforceLinkHrefs();
|
|
26440
|
+
}
|
|
26441
|
+
};
|
|
26442
|
+
window.addEventListener("message", onPageMessage);
|
|
26443
|
+
return () => window.removeEventListener("message", onPageMessage);
|
|
26444
|
+
}, [isEditMode, postToParent2]);
|
|
26204
26445
|
(0, import_react21.useEffect)(() => {
|
|
26205
26446
|
if (!isEditMode || shouldUseDevFixtures()) return;
|
|
26206
26447
|
void loadAllSectionsManifest().then((manifest) => {
|
|
@@ -27749,6 +27990,7 @@ function OhhwellsBridge() {
|
|
|
27749
27990
|
applyAiFooterFromContent(content);
|
|
27750
27991
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
27751
27992
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
27993
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
27752
27994
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
27753
27995
|
}
|
|
27754
27996
|
applyBrandChrome(content);
|
|
@@ -27759,12 +28001,12 @@ function OhhwellsBridge() {
|
|
|
27759
28001
|
if (key === "__ohw_sections") continue;
|
|
27760
28002
|
if (key === AI_SECTIONS_KEY) continue;
|
|
27761
28003
|
if (key === AI_FOOTER_KEY) continue;
|
|
28004
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
28005
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27762
28006
|
if (key === BRAND_KIT_KEY) continue;
|
|
27763
28007
|
if (key === STYLE_STORE_KEY) continue;
|
|
27764
28008
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
27765
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
27766
28009
|
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
27767
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27768
28010
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
27769
28011
|
continue;
|
|
27770
28012
|
}
|
|
@@ -27995,17 +28237,18 @@ function OhhwellsBridge() {
|
|
|
27995
28237
|
}
|
|
27996
28238
|
applyAiFooterFromContent(content);
|
|
27997
28239
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
28240
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
27998
28241
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
27999
28242
|
}
|
|
28000
28243
|
for (const [key, val] of Object.entries(content)) {
|
|
28001
28244
|
if (key === "__ohw_sections") continue;
|
|
28002
28245
|
if (key === AI_SECTIONS_KEY) continue;
|
|
28003
28246
|
if (key === AI_FOOTER_KEY) continue;
|
|
28247
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
28248
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
28004
28249
|
if (key === BRAND_KIT_KEY) continue;
|
|
28005
28250
|
if (key === STYLE_STORE_KEY) continue;
|
|
28006
28251
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
28007
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
28008
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
28009
28252
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
28010
28253
|
continue;
|
|
28011
28254
|
}
|
|
@@ -28272,26 +28515,11 @@ function OhhwellsBridge() {
|
|
|
28272
28515
|
const t2 = setTimeout(measure, 500);
|
|
28273
28516
|
const ro = new ResizeObserver(schedule);
|
|
28274
28517
|
ro.observe(document.body);
|
|
28275
|
-
let lastWidth = window.innerWidth;
|
|
28276
|
-
let resizeTimers = [];
|
|
28277
|
-
const clearResizeTimers = () => {
|
|
28278
|
-
resizeTimers.forEach(clearTimeout);
|
|
28279
|
-
resizeTimers = [];
|
|
28280
|
-
};
|
|
28281
|
-
const handleResize = () => {
|
|
28282
|
-
if (window.innerWidth === lastWidth) return;
|
|
28283
|
-
lastWidth = window.innerWidth;
|
|
28284
|
-
clearResizeTimers();
|
|
28285
|
-
resizeTimers = HEIGHT_SETTLE_DELAYS.map((delay) => setTimeout(measure, delay));
|
|
28286
|
-
};
|
|
28287
|
-
window.addEventListener("resize", handleResize);
|
|
28288
28518
|
return () => {
|
|
28289
28519
|
clearTimeout(t1);
|
|
28290
28520
|
clearTimeout(t2);
|
|
28291
28521
|
if (raf != null) cancelAnimationFrame(raf);
|
|
28292
28522
|
ro.disconnect();
|
|
28293
|
-
clearResizeTimers();
|
|
28294
|
-
window.removeEventListener("resize", handleResize);
|
|
28295
28523
|
};
|
|
28296
28524
|
}, [pathname, isEditMode, postToParent2]);
|
|
28297
28525
|
(0, import_react21.useEffect)(() => {
|
|
@@ -28588,6 +28816,13 @@ function OhhwellsBridge() {
|
|
|
28588
28816
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
28589
28817
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
28590
28818
|
if (isInsideLinkEditor(target)) return;
|
|
28819
|
+
if (isInsideFloatingPanel(target)) return;
|
|
28820
|
+
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
28821
|
+
if (target.closest(
|
|
28822
|
+
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
28823
|
+
)) {
|
|
28824
|
+
return;
|
|
28825
|
+
}
|
|
28591
28826
|
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
28592
28827
|
clearMediaSelectionRef.current();
|
|
28593
28828
|
}
|
|
@@ -28611,8 +28846,6 @@ function OhhwellsBridge() {
|
|
|
28611
28846
|
return;
|
|
28612
28847
|
}
|
|
28613
28848
|
}
|
|
28614
|
-
if (isInsideFloatingPanel(target)) return;
|
|
28615
|
-
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
28616
28849
|
const collectionItem = matchCollectionItemClick(target, collectionItemsRef.current);
|
|
28617
28850
|
if (collectionItem) {
|
|
28618
28851
|
e.preventDefault();
|
|
@@ -28624,11 +28857,6 @@ function OhhwellsBridge() {
|
|
|
28624
28857
|
});
|
|
28625
28858
|
return;
|
|
28626
28859
|
}
|
|
28627
|
-
if (target.closest(
|
|
28628
|
-
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
28629
|
-
)) {
|
|
28630
|
-
return;
|
|
28631
|
-
}
|
|
28632
28860
|
{
|
|
28633
28861
|
const formEl = getFormElement(target);
|
|
28634
28862
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
@@ -28782,9 +29010,13 @@ function OhhwellsBridge() {
|
|
|
28782
29010
|
if (isIconEditable(editable) && !getSocialItem(editable)) {
|
|
28783
29011
|
e.preventDefault();
|
|
28784
29012
|
e.stopPropagation();
|
|
28785
|
-
selectIconElementRef.current(editable);
|
|
28786
29013
|
const aiIcon = editable.hasAttribute("data-ai-icon");
|
|
28787
29014
|
const featureIcon = aiIcon && /\.features\.\d+\.icon$/.test(editable.dataset.ohwKey ?? "");
|
|
29015
|
+
if (aiIcon) {
|
|
29016
|
+
aiSectionApiRef.current?.selectFromElement(editable);
|
|
29017
|
+
} else {
|
|
29018
|
+
selectIconElementRef.current(editable);
|
|
29019
|
+
}
|
|
28788
29020
|
postToParentRef.current({
|
|
28789
29021
|
type: "ow:icon-pick",
|
|
28790
29022
|
key: editable.dataset.ohwKey ?? "",
|
|
@@ -29012,6 +29244,9 @@ function OhhwellsBridge() {
|
|
|
29012
29244
|
setHoveredItemRect(null);
|
|
29013
29245
|
hoveredNavContainerRef.current = null;
|
|
29014
29246
|
setHoveredNavContainerRect(null);
|
|
29247
|
+
siblingHintElRef.current = null;
|
|
29248
|
+
setSiblingHintRect(null);
|
|
29249
|
+
setSiblingHintRects([]);
|
|
29015
29250
|
return;
|
|
29016
29251
|
}
|
|
29017
29252
|
{
|
|
@@ -29132,7 +29367,6 @@ function OhhwellsBridge() {
|
|
|
29132
29367
|
hoveredNavContainerRef.current = null;
|
|
29133
29368
|
setHoveredNavContainerRect(null);
|
|
29134
29369
|
hoveredItemElRef.current = editable;
|
|
29135
|
-
setHoveredItemRect(isSelectedForHoverRef.current(editable) ? null : editable.getBoundingClientRect());
|
|
29136
29370
|
}
|
|
29137
29371
|
}
|
|
29138
29372
|
}
|
|
@@ -29842,7 +30076,11 @@ function OhhwellsBridge() {
|
|
|
29842
30076
|
};
|
|
29843
30077
|
const handleMouseMove = (e) => {
|
|
29844
30078
|
const { clientX, clientY } = e;
|
|
29845
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
30079
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
30080
|
+
dismissImageHover();
|
|
30081
|
+
clearImageHover();
|
|
30082
|
+
return;
|
|
30083
|
+
}
|
|
29846
30084
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) {
|
|
29847
30085
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
29848
30086
|
formHoverElRef.current = null;
|
|
@@ -29871,7 +30109,12 @@ function OhhwellsBridge() {
|
|
|
29871
30109
|
setHoveredItemRect(null);
|
|
29872
30110
|
hoveredNavContainerRef.current = null;
|
|
29873
30111
|
setHoveredNavContainerRect(null);
|
|
30112
|
+
siblingHintElRef.current = null;
|
|
30113
|
+
setSiblingHintRect(null);
|
|
30114
|
+
setSiblingHintRects([]);
|
|
29874
30115
|
dismissImageHover();
|
|
30116
|
+
clearImageHover();
|
|
30117
|
+
setSectionGap(null);
|
|
29875
30118
|
return;
|
|
29876
30119
|
}
|
|
29877
30120
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
@@ -29883,7 +30126,11 @@ function OhhwellsBridge() {
|
|
|
29883
30126
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
29884
30127
|
const { clientX, clientY } = e.data;
|
|
29885
30128
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
29886
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
30129
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
30130
|
+
dismissImageHover();
|
|
30131
|
+
clearImageHover();
|
|
30132
|
+
return;
|
|
30133
|
+
}
|
|
29887
30134
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) return;
|
|
29888
30135
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
29889
30136
|
probeSectionGapAt(clientX, clientY);
|
|
@@ -30263,6 +30510,7 @@ function OhhwellsBridge() {
|
|
|
30263
30510
|
applyAiFooterFromContent(content);
|
|
30264
30511
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
30265
30512
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
30513
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
30266
30514
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
30267
30515
|
}
|
|
30268
30516
|
applyBrandChrome(content);
|
|
@@ -30277,12 +30525,12 @@ function OhhwellsBridge() {
|
|
|
30277
30525
|
}
|
|
30278
30526
|
if (key === AI_SECTIONS_KEY) continue;
|
|
30279
30527
|
if (key === AI_FOOTER_KEY) continue;
|
|
30528
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
30529
|
+
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
30280
30530
|
if (key === BRAND_KIT_KEY) continue;
|
|
30281
30531
|
if (key === STYLE_STORE_KEY) continue;
|
|
30282
30532
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
30283
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
30284
30533
|
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
30285
|
-
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
30286
30534
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
30287
30535
|
continue;
|
|
30288
30536
|
}
|
|
@@ -30918,6 +31166,12 @@ function OhhwellsBridge() {
|
|
|
30918
31166
|
closeLinkPopoverRef.current();
|
|
30919
31167
|
return;
|
|
30920
31168
|
}
|
|
31169
|
+
if (floatingPanelOpenRef.current) {
|
|
31170
|
+
setFloatingPanelRef.current(null);
|
|
31171
|
+
deselectRef.current();
|
|
31172
|
+
deactivateRef.current();
|
|
31173
|
+
return;
|
|
31174
|
+
}
|
|
30921
31175
|
deselectRef.current();
|
|
30922
31176
|
deactivateRef.current();
|
|
30923
31177
|
clearMediaSelectionRef.current();
|
|
@@ -31747,10 +32001,10 @@ function OhhwellsBridge() {
|
|
|
31747
32001
|
window.removeEventListener("message", handleDuplicateSection);
|
|
31748
32002
|
window.removeEventListener("message", handleDeactivate);
|
|
31749
32003
|
window.removeEventListener("message", handleSelectNav);
|
|
31750
|
-
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
31751
32004
|
window.removeEventListener("message", handleToastAction);
|
|
31752
32005
|
window.removeEventListener("message", handleFormCount);
|
|
31753
32006
|
window.removeEventListener("message", handleUiEscape);
|
|
32007
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
31754
32008
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
31755
32009
|
autoSaveTimers.current.clear();
|
|
31756
32010
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
@@ -32044,7 +32298,7 @@ function OhhwellsBridge() {
|
|
|
32044
32298
|
postToParent2({
|
|
32045
32299
|
type: "ow:ready",
|
|
32046
32300
|
version: "1",
|
|
32047
|
-
bridgeVersion: "0.1.
|
|
32301
|
+
bridgeVersion: "0.1.158-next.422",
|
|
32048
32302
|
path: pathname,
|
|
32049
32303
|
nodes: collectEditableNodes(editContentRef.current),
|
|
32050
32304
|
sections
|
|
@@ -33251,6 +33505,7 @@ function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey
|
|
|
33251
33505
|
OhwLoaderSurface,
|
|
33252
33506
|
SITE_OG_IMAGE_KEY,
|
|
33253
33507
|
SchedulingWidget,
|
|
33508
|
+
TEMPLATE_LOGO_ATTR,
|
|
33254
33509
|
Toggle,
|
|
33255
33510
|
ToggleGroup,
|
|
33256
33511
|
ToggleGroupItem,
|
|
@@ -33284,6 +33539,7 @@ function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey
|
|
|
33284
33539
|
parseAiSectionsState,
|
|
33285
33540
|
parseTarget,
|
|
33286
33541
|
recordOverriddenPaths,
|
|
33542
|
+
releaseTemplateLogoIfReplaced,
|
|
33287
33543
|
removeFooterBlock,
|
|
33288
33544
|
resetOverriddenPathsCache,
|
|
33289
33545
|
resolveFooterCopyright,
|