@ohhwells/bridge 0.1.157 → 0.1.158-next.423
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 +1068 -714
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +37 -1
- package/dist/index.d.ts +37 -1
- package/dist/index.js +1104 -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;
|
|
@@ -6220,6 +6248,20 @@ function applyStylesToDom(store) {
|
|
|
6220
6248
|
}
|
|
6221
6249
|
}
|
|
6222
6250
|
}
|
|
6251
|
+
for (const [sectionId, override] of Object.entries(store.sections)) {
|
|
6252
|
+
if (override.iconColor === void 0) continue;
|
|
6253
|
+
const escaped = CSS.escape(sectionId);
|
|
6254
|
+
const byInstance = document.querySelectorAll(`[data-ohw-instance="${escaped}"]`);
|
|
6255
|
+
const sections = byInstance.length ? byInstance : document.querySelectorAll(`[data-ohw-section="${escaped}"]`);
|
|
6256
|
+
for (const marker of Array.from(sections)) {
|
|
6257
|
+
const icons = marker.querySelectorAll('[data-ohw-editable="icon"]');
|
|
6258
|
+
for (const el of Array.from(icons)) {
|
|
6259
|
+
saveInline(el, "color");
|
|
6260
|
+
el.style.setProperty("color", override.iconColor, "important");
|
|
6261
|
+
el.setAttribute(NODE_WROTE_ATTR, "");
|
|
6262
|
+
}
|
|
6263
|
+
}
|
|
6264
|
+
}
|
|
6223
6265
|
}
|
|
6224
6266
|
|
|
6225
6267
|
// src/lib/ai-sections-store.ts
|
|
@@ -6654,6 +6696,21 @@ function pricingCardFeatureCount(tree, index) {
|
|
|
6654
6696
|
const target = findPricingCollection(tree)?.children?.[index];
|
|
6655
6697
|
return target ? pricingFeatureList(target).length : 0;
|
|
6656
6698
|
}
|
|
6699
|
+
function prevailingFeatureIcon(features) {
|
|
6700
|
+
const counts = /* @__PURE__ */ new Map();
|
|
6701
|
+
for (const row of features) {
|
|
6702
|
+
const key = `${row.icon ?? ""}|${row.iconColor ?? ""}`;
|
|
6703
|
+
const entry = counts.get(key) ?? { count: 0, ...row.icon ? { icon: row.icon } : {}, ...row.iconColor ? { iconColor: row.iconColor } : {} };
|
|
6704
|
+
entry.count += 1;
|
|
6705
|
+
counts.set(key, entry);
|
|
6706
|
+
}
|
|
6707
|
+
let best = null;
|
|
6708
|
+
for (const entry of counts.values()) {
|
|
6709
|
+
if (!best || entry.count > best.count) best = entry;
|
|
6710
|
+
}
|
|
6711
|
+
if (!best) return {};
|
|
6712
|
+
return { ...best.icon ? { icon: best.icon } : {}, ...best.iconColor ? { iconColor: best.iconColor } : {} };
|
|
6713
|
+
}
|
|
6657
6714
|
function addPricingCardFeature(tree, index, text) {
|
|
6658
6715
|
return withPricingCollection(tree, (collection) => {
|
|
6659
6716
|
const children = collection.children;
|
|
@@ -6662,7 +6719,7 @@ function addPricingCardFeature(tree, index, text) {
|
|
|
6662
6719
|
const features = pricingFeatureList(target);
|
|
6663
6720
|
if (features.length >= PRICING_FEATURES_MAX) return false;
|
|
6664
6721
|
target.slots = target.slots ?? {};
|
|
6665
|
-
target.slots.features = [...features, { text }];
|
|
6722
|
+
target.slots.features = [...features, { text, ...prevailingFeatureIcon(features) }];
|
|
6666
6723
|
return true;
|
|
6667
6724
|
});
|
|
6668
6725
|
}
|
|
@@ -6849,6 +6906,7 @@ function applyBrandChrome(content) {
|
|
|
6849
6906
|
if (el.textContent !== name) el.textContent = name;
|
|
6850
6907
|
if (el.getAttribute("title") !== name) el.setAttribute("title", name);
|
|
6851
6908
|
});
|
|
6909
|
+
applyLogoIdentity(name, false);
|
|
6852
6910
|
}
|
|
6853
6911
|
const title = content[BRAND_TITLE_KEY];
|
|
6854
6912
|
if (typeof title === "string" && title.length > 0) {
|
|
@@ -7861,7 +7919,7 @@ var AI_MOBILE_CSS = [
|
|
|
7861
7919
|
// page's first section. Top only (bottom needs no nav clearance); ~96px approximates the
|
|
7862
7920
|
// template nav's own height (measured ~94px) — there's no shared `--ohw-header-h` var to read
|
|
7863
7921
|
// 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-
|
|
7922
|
+
// pixel-exact fit. Horizontal spacing already comes from `data-ai-section-inner`.
|
|
7865
7923
|
'[data-ai-overlay-clearance] [data-ai-overlap-layer="overlay"]{padding-top:96px}',
|
|
7866
7924
|
// A full-bleed carousel's height is pure arithmetic: it spans the whole window, so 16/9 turns
|
|
7867
7925
|
// window width straight into height. Measured at 16/9 it came out ~90% of the viewport at EVERY
|
|
@@ -7877,8 +7935,10 @@ var AI_MOBILE_CSS = [
|
|
|
7877
7935
|
"[data-ai-section]{overflow-x:hidden}",
|
|
7878
7936
|
// `:not([data-ai-full-bleed])`: this `!important` gutter beat the inline `padding: 0` that a
|
|
7879
7937
|
// 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
|
-
|
|
7938
|
+
// still got a 20px band of section background down both sides on a phone. The footer's own
|
|
7939
|
+
// container keeps the unguarded rule below — `data-ai-full-bleed` can never appear on it.
|
|
7940
|
+
"[data-ai-section-inner]:not([data-ai-full-bleed]){padding:0 20px !important}",
|
|
7941
|
+
"[data-ai-container]{padding:0 20px !important}",
|
|
7882
7942
|
"[data-ai-row]{display:flex !important;flex-direction:column !important;align-items:stretch !important}",
|
|
7883
7943
|
"[data-ai-cell]{width:100%;min-width:0}",
|
|
7884
7944
|
// The rule above turns every row into a COLUMN flex container on phones, which silently breaks
|
|
@@ -8083,6 +8143,31 @@ function pricingCardEmphasis(featured, ctx, hasBg) {
|
|
|
8083
8143
|
function textAttrs(ctx, path) {
|
|
8084
8144
|
return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
|
|
8085
8145
|
}
|
|
8146
|
+
var AI_RESPONSIVE_CSS = [
|
|
8147
|
+
"@media (max-width: 960px) {",
|
|
8148
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: repeat(2, 1fr) !important; }",
|
|
8149
|
+
' [data-ai-responsive] [data-ai-grid="1"] { grid-template-columns: 1fr !important; }',
|
|
8150
|
+
"}",
|
|
8151
|
+
"@media (max-width: 640px) {",
|
|
8152
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
|
|
8153
|
+
" [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
|
|
8154
|
+
// Group containers flatten to a column on phones; span placements come along for free.
|
|
8155
|
+
// `:not([data-ai-group="overlap"])` for the same reason as the twin pair in AI_MOBILE_CSS — see
|
|
8156
|
+
// the comment there. This sheet's copy is the narrower selector, so without the exemption it
|
|
8157
|
+
// flattens an `overlap` hero below 640px even though the other rule stands down: measured a 390px
|
|
8158
|
+
// viewport with the heading/CTA in flow *under* the image, 219px of section background where the
|
|
8159
|
+
// layered text used to be.
|
|
8160
|
+
' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) { display: flex !important; flex-direction: column !important; }',
|
|
8161
|
+
' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) > * { grid-column: auto !important; }',
|
|
8162
|
+
// `:not([data-ai-full-bleed])` for the same reason as the twin rule in AI_MOBILE_CSS: this one
|
|
8163
|
+
// is narrower (0,2,0 vs 0,1,0) and also `!important`, so without the guard it wins outright and
|
|
8164
|
+
// a full-bleed hero gets its 20px side band back below 640px only — the one width where the
|
|
8165
|
+
// other rule had already been taught to stand down.
|
|
8166
|
+
" [data-ai-responsive] [data-ai-section-inner]:not([data-ai-full-bleed]) { padding-left: 20px !important; padding-right: 20px !important; }",
|
|
8167
|
+
" [data-ai-responsive] { overflow-x: hidden; }",
|
|
8168
|
+
" [data-ai-responsive] img { max-width: 100%; }",
|
|
8169
|
+
"}"
|
|
8170
|
+
].join("\n");
|
|
8086
8171
|
var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
8087
8172
|
function MediaBox({
|
|
8088
8173
|
refValue,
|
|
@@ -8137,7 +8222,7 @@ function MediaBox({
|
|
|
8137
8222
|
position: fill ? "absolute" : void 0,
|
|
8138
8223
|
inset: fill ? 0 : void 0,
|
|
8139
8224
|
width: fill ? "100%" : fixedSize ? "auto" : "100%",
|
|
8140
|
-
height: fill ? "100%" : void 0,
|
|
8225
|
+
height: fill ? "100%" : fixedSize ? height : void 0,
|
|
8141
8226
|
aspectRatio: fill ? void 0 : aspectRatio,
|
|
8142
8227
|
minHeight: fill || fixedSize ? void 0 : height ?? (aspectRatio ? void 0 : 180),
|
|
8143
8228
|
borderRadius: radius,
|
|
@@ -9633,7 +9718,7 @@ function CollectionBlock({ node, ctx, path }) {
|
|
|
9633
9718
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
9634
9719
|
"div",
|
|
9635
9720
|
{
|
|
9636
|
-
"data-ai-grid":
|
|
9721
|
+
"data-ai-grid": String(itemsPerRow),
|
|
9637
9722
|
"data-ohw-pricing-collection": isPricing ? "" : void 0,
|
|
9638
9723
|
style: {
|
|
9639
9724
|
display: "grid",
|
|
@@ -9935,7 +10020,7 @@ function renderNode(node, ctx, path, ambientAlign) {
|
|
|
9935
10020
|
},
|
|
9936
10021
|
children: [
|
|
9937
10022
|
i > 0 && ctx.heroOverlapFullBleed ? (
|
|
9938
|
-
// The section's `data-ai-
|
|
10023
|
+
// The section's `data-ai-section-inner` gave up its max-width/gutter so the base
|
|
9939
10024
|
// layer (this group's i===0 sibling) can span edge-to-edge — reintroduced here,
|
|
9940
10025
|
// scoped to just the overlay text, so a heading/copy/CTA stack doesn't stretch
|
|
9941
10026
|
// the full section width instead of reading at the usual content width.
|
|
@@ -10354,6 +10439,7 @@ function AiTreeRenderer({
|
|
|
10354
10439
|
...fillHeight ? { "data-ai-fill-height": "" } : {},
|
|
10355
10440
|
...needsOverlayClearance ? { "data-ai-overlay-clearance": "" } : {},
|
|
10356
10441
|
...bgAttrs,
|
|
10442
|
+
"data-ai-responsive": "",
|
|
10357
10443
|
style: {
|
|
10358
10444
|
position: "relative",
|
|
10359
10445
|
padding: `${padCss} 0`,
|
|
@@ -10367,12 +10453,13 @@ function AiTreeRenderer({
|
|
|
10367
10453
|
...fillHeight ? { display: "grid" } : {}
|
|
10368
10454
|
},
|
|
10369
10455
|
children: [
|
|
10370
|
-
|
|
10456
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_RESPONSIVE_CSS }),
|
|
10371
10457
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_MOBILE_CSS }),
|
|
10458
|
+
isOverlay && backgroundUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { position: "absolute", inset: 0, background: `rgba(255,255,255,${overlayAlpha})` } }),
|
|
10372
10459
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
10373
10460
|
"div",
|
|
10374
10461
|
{
|
|
10375
|
-
"data-ai-
|
|
10462
|
+
"data-ai-section-inner": "",
|
|
10376
10463
|
...fullBleedMedia ? { "data-ai-full-bleed": "" } : {},
|
|
10377
10464
|
style: {
|
|
10378
10465
|
position: "relative",
|
|
@@ -10389,7 +10476,7 @@ function AiTreeRenderer({
|
|
|
10389
10476
|
children: tree.rows.map((row, r2) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
10390
10477
|
"div",
|
|
10391
10478
|
{
|
|
10392
|
-
"data-ai-
|
|
10479
|
+
"data-ai-columns": "",
|
|
10393
10480
|
style: {
|
|
10394
10481
|
display: "grid",
|
|
10395
10482
|
gridTemplateColumns: "repeat(12, 1fr)",
|
|
@@ -11051,9 +11138,10 @@ function applyAiSectionsToDom(state, options) {
|
|
|
11051
11138
|
if (existing && existing.serialized === serialized && existing.container.isConnected) {
|
|
11052
11139
|
continue;
|
|
11053
11140
|
}
|
|
11054
|
-
const isNewMount = !existing || !existing.container.isConnected;
|
|
11055
11141
|
let container = existing?.container;
|
|
11142
|
+
let isNewMount = false;
|
|
11056
11143
|
if (!container || !container.isConnected) {
|
|
11144
|
+
isNewMount = true;
|
|
11057
11145
|
existing?.root.unmount();
|
|
11058
11146
|
container?.remove();
|
|
11059
11147
|
container = document.createElement("div");
|
|
@@ -17212,7 +17300,7 @@ function apiBase() {
|
|
|
17212
17300
|
function bridgeVersion() {
|
|
17213
17301
|
try {
|
|
17214
17302
|
if (true) {
|
|
17215
|
-
return "0.1.
|
|
17303
|
+
return "0.1.158-next.423";
|
|
17216
17304
|
}
|
|
17217
17305
|
} catch {
|
|
17218
17306
|
}
|
|
@@ -17226,7 +17314,7 @@ function stampBridgeVersionOnDocument() {
|
|
|
17226
17314
|
return;
|
|
17227
17315
|
}
|
|
17228
17316
|
try {
|
|
17229
|
-
const v = true ? "0.1.
|
|
17317
|
+
const v = true ? "0.1.158-next.423" : "";
|
|
17230
17318
|
if (v) {
|
|
17231
17319
|
document.documentElement.setAttribute("data-ohw-bridge-version", v);
|
|
17232
17320
|
window.__OHW_BRIDGE_VERSION__ = v;
|
|
@@ -17904,6 +17992,7 @@ function MediaOverlay({
|
|
|
17904
17992
|
(prev) => prev && prev.fullWidth === width && prev.height === height ? prev : { fullWidth: width, height }
|
|
17905
17993
|
);
|
|
17906
17994
|
}, [isVideo]);
|
|
17995
|
+
const replaceLabel = isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image";
|
|
17907
17996
|
const replaceMode = buttonSize ? replaceButtonMode({ width: rect.width, height: rect.height }, buttonSize) : "none";
|
|
17908
17997
|
const box = {
|
|
17909
17998
|
position: "fixed",
|
|
@@ -18002,11 +18091,10 @@ function MediaOverlay({
|
|
|
18002
18091
|
className: "flex items-center justify-center cursor-pointer",
|
|
18003
18092
|
style: {
|
|
18004
18093
|
...box,
|
|
18005
|
-
//
|
|
18006
|
-
//
|
|
18007
|
-
//
|
|
18008
|
-
|
|
18009
|
-
pointerEvents: hover.hasTextOverlap || cueOnly ? "none" : "auto",
|
|
18094
|
+
// Visual only. `pointer-events: auto` on this full-bleed rect covered the navbar
|
|
18095
|
+
// (hero bg includes the absolute TopNav) and swallowed CTA press-drag. Text overlay
|
|
18096
|
+
// and cueOnly also need clicks to fall through — Replace / video controls opt back in.
|
|
18097
|
+
pointerEvents: "none",
|
|
18010
18098
|
// Selected: a firm component ring with no wash, so the image reads as chosen rather
|
|
18011
18099
|
// than hovered. Hover keeps the existing tinted preview.
|
|
18012
18100
|
boxShadow: selected ? "inset 0 0 0 2px var(--color-bridge-primary)" : "inset 0 0 0 1.5px var(--color-bridge-primary)",
|
|
@@ -18033,17 +18121,17 @@ function MediaOverlay({
|
|
|
18033
18121
|
},
|
|
18034
18122
|
children: [
|
|
18035
18123
|
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
|
-
|
|
18124
|
+
replaceLabel
|
|
18037
18125
|
]
|
|
18038
18126
|
}
|
|
18039
18127
|
),
|
|
18040
|
-
replaceMode
|
|
18128
|
+
showChrome && replaceMode !== "none" && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
18041
18129
|
Button,
|
|
18042
18130
|
{
|
|
18043
18131
|
"data-ohw-media-overlay": "",
|
|
18044
18132
|
variant: "outline",
|
|
18045
18133
|
size: "sm",
|
|
18046
|
-
"aria-label":
|
|
18134
|
+
"aria-label": replaceLabel,
|
|
18047
18135
|
className: "gap-1.5 cursor-pointer hover:bg-background",
|
|
18048
18136
|
style: {
|
|
18049
18137
|
...OVERLAY_BUTTON_STYLE,
|
|
@@ -18066,7 +18154,7 @@ function MediaOverlay({
|
|
|
18066
18154
|
},
|
|
18067
18155
|
children: [
|
|
18068
18156
|
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" ?
|
|
18157
|
+
replaceMode === "full" ? replaceLabel : null
|
|
18070
18158
|
]
|
|
18071
18159
|
}
|
|
18072
18160
|
)
|
|
@@ -18135,6 +18223,89 @@ function CarouselOverlay({
|
|
|
18135
18223
|
// src/ui/ai-section/AiSectionOverlay.tsx
|
|
18136
18224
|
var import_react9 = require("react");
|
|
18137
18225
|
var import_lucide_react7 = require("lucide-react");
|
|
18226
|
+
|
|
18227
|
+
// src/lib/ai-change-highlight.ts
|
|
18228
|
+
var STYLE_ID = "ohw-ai-changed-style";
|
|
18229
|
+
var MARK_ATTR = "data-ohw-ai-changed";
|
|
18230
|
+
var HIGHLIGHT_MS = 2200;
|
|
18231
|
+
var HIGHLIGHT_CSS = `
|
|
18232
|
+
@keyframes ohw-ai-changed-pulse {
|
|
18233
|
+
0% { outline-color: rgba(0, 120, 229, 0.95); box-shadow: 0 0 0 5px rgba(0, 120, 229, 0.20); }
|
|
18234
|
+
72% { outline-color: rgba(0, 120, 229, 0.95); box-shadow: 0 0 0 5px rgba(0, 120, 229, 0.12); }
|
|
18235
|
+
100% { outline-color: rgba(0, 120, 229, 0); box-shadow: 0 0 0 5px rgba(0, 120, 229, 0); }
|
|
18236
|
+
}
|
|
18237
|
+
[${MARK_ATTR}] {
|
|
18238
|
+
outline: 2px solid rgba(0, 120, 229, 0.95) !important;
|
|
18239
|
+
outline-offset: 3px !important;
|
|
18240
|
+
animation: ohw-ai-changed-pulse ${HIGHLIGHT_MS}ms ease-out forwards !important;
|
|
18241
|
+
}
|
|
18242
|
+
@media (prefers-reduced-motion: reduce) {
|
|
18243
|
+
[${MARK_ATTR}] { animation: none !important; }
|
|
18244
|
+
}
|
|
18245
|
+
`;
|
|
18246
|
+
function ensureStyleSheet2() {
|
|
18247
|
+
if (document.getElementById(STYLE_ID)) return;
|
|
18248
|
+
const el = document.createElement("style");
|
|
18249
|
+
el.id = STYLE_ID;
|
|
18250
|
+
el.textContent = HIGHLIGHT_CSS;
|
|
18251
|
+
document.head.appendChild(el);
|
|
18252
|
+
}
|
|
18253
|
+
function targetsFor(keys, item) {
|
|
18254
|
+
const out = /* @__PURE__ */ new Set();
|
|
18255
|
+
for (const key of keys) {
|
|
18256
|
+
if (!key) continue;
|
|
18257
|
+
for (const el of Array.from(
|
|
18258
|
+
document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`)
|
|
18259
|
+
)) {
|
|
18260
|
+
out.add(el);
|
|
18261
|
+
}
|
|
18262
|
+
}
|
|
18263
|
+
if (item) {
|
|
18264
|
+
const section = document.querySelector(`[data-ohw-instance="${CSS.escape(item.sectionId)}"]`) ?? document.querySelector(`[data-ohw-section="${CSS.escape(item.sectionId)}"]`);
|
|
18265
|
+
const stamp = `${item.group}:${item.index}`;
|
|
18266
|
+
const el = section?.querySelector(`[data-ohw-item="${CSS.escape(stamp)}"]`);
|
|
18267
|
+
if (el) out.add(el);
|
|
18268
|
+
}
|
|
18269
|
+
return [...out];
|
|
18270
|
+
}
|
|
18271
|
+
var clearTimer = null;
|
|
18272
|
+
function clearChangeHighlight() {
|
|
18273
|
+
if (clearTimer !== null) {
|
|
18274
|
+
clearTimeout(clearTimer);
|
|
18275
|
+
clearTimer = null;
|
|
18276
|
+
}
|
|
18277
|
+
for (const el of Array.from(document.querySelectorAll(`[${MARK_ATTR}]`))) {
|
|
18278
|
+
el.removeAttribute(MARK_ATTR);
|
|
18279
|
+
}
|
|
18280
|
+
}
|
|
18281
|
+
function highlightChangedElements(keys, item) {
|
|
18282
|
+
clearChangeHighlight();
|
|
18283
|
+
const targets = targetsFor(keys, item);
|
|
18284
|
+
if (targets.length === 0) return 0;
|
|
18285
|
+
ensureStyleSheet2();
|
|
18286
|
+
for (const el of targets) el.setAttribute(MARK_ATTR, "");
|
|
18287
|
+
const rect = targets[0].getBoundingClientRect();
|
|
18288
|
+
if (rect.bottom < 0 || rect.top > window.innerHeight) {
|
|
18289
|
+
targets[0].scrollIntoView({ behavior: "smooth", block: "center" });
|
|
18290
|
+
}
|
|
18291
|
+
clearTimer = setTimeout(clearChangeHighlight, HIGHLIGHT_MS);
|
|
18292
|
+
return targets.length;
|
|
18293
|
+
}
|
|
18294
|
+
function installAiChangeHighlight() {
|
|
18295
|
+
const onMessage = (e) => {
|
|
18296
|
+
const data = e.data;
|
|
18297
|
+
if (data?.type !== "ow:ai-highlight") return;
|
|
18298
|
+
const keys = Array.isArray(data.keys) ? data.keys.filter((k) => typeof k === "string") : [];
|
|
18299
|
+
const raw = data.item;
|
|
18300
|
+
const item = raw && typeof raw.sectionId === "string" && typeof raw.group === "string" && typeof raw.index === "number" ? { sectionId: raw.sectionId, group: raw.group, index: raw.index } : void 0;
|
|
18301
|
+
const found = highlightChangedElements(keys, item);
|
|
18302
|
+
window.parent?.postMessage({ type: "ow:ai-highlight-done", found }, "*");
|
|
18303
|
+
};
|
|
18304
|
+
window.addEventListener("message", onMessage);
|
|
18305
|
+
return () => window.removeEventListener("message", onMessage);
|
|
18306
|
+
}
|
|
18307
|
+
|
|
18308
|
+
// src/ui/ai-section/AiSectionOverlay.tsx
|
|
18138
18309
|
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
18139
18310
|
var findSectionElement = findByInstanceId;
|
|
18140
18311
|
function readRect(instanceId) {
|
|
@@ -18386,6 +18557,7 @@ function AiSectionOverlay({
|
|
|
18386
18557
|
window.addEventListener("message", onMessage);
|
|
18387
18558
|
return () => window.removeEventListener("message", onMessage);
|
|
18388
18559
|
}, [postToParent2]);
|
|
18560
|
+
(0, import_react9.useEffect)(() => installAiChangeHighlight(), []);
|
|
18389
18561
|
const [hoveredId, setHoveredId] = (0, import_react9.useState)(null);
|
|
18390
18562
|
(0, import_react9.useEffect)(() => {
|
|
18391
18563
|
const onMove = (e) => {
|
|
@@ -18576,7 +18748,7 @@ function AiSectionOverlay({
|
|
|
18576
18748
|
|
|
18577
18749
|
// src/ui/ai-section/AiMediaStripOverlay.tsx
|
|
18578
18750
|
var import_react10 = require("react");
|
|
18579
|
-
var
|
|
18751
|
+
var import_lucide_react9 = require("lucide-react");
|
|
18580
18752
|
|
|
18581
18753
|
// src/lib/ai-media-strip-tree.ts
|
|
18582
18754
|
var MEDIA_STRIP_ITEM_MIN = 1;
|
|
@@ -18690,14 +18862,6 @@ function setMediaStripItemAsset(tree, index, assetId) {
|
|
|
18690
18862
|
return true;
|
|
18691
18863
|
});
|
|
18692
18864
|
}
|
|
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
18865
|
function setMediaStripItemLink(tree, index, link) {
|
|
18702
18866
|
return withMediaStrip(tree, (block) => {
|
|
18703
18867
|
const items = block.items;
|
|
@@ -18715,11 +18879,117 @@ function setMediaStripItemLink(tree, index, link) {
|
|
|
18715
18879
|
});
|
|
18716
18880
|
}
|
|
18717
18881
|
|
|
18718
|
-
// src/ui/
|
|
18882
|
+
// src/ui/dialog.tsx
|
|
18883
|
+
var React9 = __toESM(require("react"), 1);
|
|
18884
|
+
var import_radix_ui6 = require("radix-ui");
|
|
18885
|
+
var import_lucide_react8 = require("lucide-react");
|
|
18719
18886
|
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
18720
|
-
|
|
18721
|
-
|
|
18722
|
-
|
|
18887
|
+
function Dialog2({
|
|
18888
|
+
...props
|
|
18889
|
+
}) {
|
|
18890
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_radix_ui6.Dialog.Root, { "data-slot": "dialog", ...props });
|
|
18891
|
+
}
|
|
18892
|
+
function DialogPortal({
|
|
18893
|
+
...props
|
|
18894
|
+
}) {
|
|
18895
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_radix_ui6.Dialog.Portal, { ...props });
|
|
18896
|
+
}
|
|
18897
|
+
function DialogOverlay({
|
|
18898
|
+
className,
|
|
18899
|
+
...props
|
|
18900
|
+
}) {
|
|
18901
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18902
|
+
import_radix_ui6.Dialog.Overlay,
|
|
18903
|
+
{
|
|
18904
|
+
"data-slot": "dialog-overlay",
|
|
18905
|
+
"data-ohw-link-modal-root": "",
|
|
18906
|
+
className: cn("fixed inset-0 z-[2147483646] bg-black/50", className),
|
|
18907
|
+
...props
|
|
18908
|
+
}
|
|
18909
|
+
);
|
|
18910
|
+
}
|
|
18911
|
+
var DialogContent = React9.forwardRef(
|
|
18912
|
+
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
18913
|
+
const positionMode = container ? "absolute" : "fixed";
|
|
18914
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(DialogPortal, { container: container ?? void 0, children: [
|
|
18915
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
18916
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
18917
|
+
import_radix_ui6.Dialog.Content,
|
|
18918
|
+
{
|
|
18919
|
+
ref,
|
|
18920
|
+
"data-slot": "dialog-content",
|
|
18921
|
+
className: cn(
|
|
18922
|
+
positionMode,
|
|
18923
|
+
"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",
|
|
18924
|
+
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
18925
|
+
container ? "max-h-[calc(100%-32px)]" : "max-h-[calc(100vh-32px)]",
|
|
18926
|
+
className
|
|
18927
|
+
),
|
|
18928
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
18929
|
+
...props,
|
|
18930
|
+
children: [
|
|
18931
|
+
children,
|
|
18932
|
+
showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18933
|
+
import_radix_ui6.Dialog.Close,
|
|
18934
|
+
{
|
|
18935
|
+
type: "button",
|
|
18936
|
+
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
18937
|
+
"aria-label": "Close",
|
|
18938
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react8.X, { size: 16, "aria-hidden": true })
|
|
18939
|
+
}
|
|
18940
|
+
) : null
|
|
18941
|
+
]
|
|
18942
|
+
}
|
|
18943
|
+
)
|
|
18944
|
+
] });
|
|
18945
|
+
}
|
|
18946
|
+
);
|
|
18947
|
+
DialogContent.displayName = import_radix_ui6.Dialog.Content.displayName;
|
|
18948
|
+
function DialogHeader({
|
|
18949
|
+
className,
|
|
18950
|
+
...props
|
|
18951
|
+
}) {
|
|
18952
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
18953
|
+
}
|
|
18954
|
+
function DialogFooter({
|
|
18955
|
+
className,
|
|
18956
|
+
...props
|
|
18957
|
+
}) {
|
|
18958
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18959
|
+
"div",
|
|
18960
|
+
{
|
|
18961
|
+
className: cn("flex items-center justify-end gap-2", className),
|
|
18962
|
+
...props
|
|
18963
|
+
}
|
|
18964
|
+
);
|
|
18965
|
+
}
|
|
18966
|
+
var DialogTitle = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18967
|
+
import_radix_ui6.Dialog.Title,
|
|
18968
|
+
{
|
|
18969
|
+
ref,
|
|
18970
|
+
className: cn(
|
|
18971
|
+
"text-lg font-semibold leading-none tracking-tight text-card-foreground",
|
|
18972
|
+
className
|
|
18973
|
+
),
|
|
18974
|
+
...props
|
|
18975
|
+
}
|
|
18976
|
+
));
|
|
18977
|
+
DialogTitle.displayName = import_radix_ui6.Dialog.Title.displayName;
|
|
18978
|
+
var DialogDescription = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18979
|
+
import_radix_ui6.Dialog.Description,
|
|
18980
|
+
{
|
|
18981
|
+
ref,
|
|
18982
|
+
className: cn("text-sm text-muted-foreground", className),
|
|
18983
|
+
...props
|
|
18984
|
+
}
|
|
18985
|
+
));
|
|
18986
|
+
DialogDescription.displayName = import_radix_ui6.Dialog.Description.displayName;
|
|
18987
|
+
var DialogClose = import_radix_ui6.Dialog.Close;
|
|
18988
|
+
|
|
18989
|
+
// src/ui/ai-section/AiMediaStripOverlay.tsx
|
|
18990
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
18991
|
+
var PRIMARY3 = "var(--ohw-primary, #0885FE)";
|
|
18992
|
+
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
18993
|
function findMediaStripItemElement(sectionId, index) {
|
|
18724
18994
|
const sectionEl = findByInstanceId(sectionId);
|
|
18725
18995
|
if (!sectionEl) return null;
|
|
@@ -18729,14 +18999,35 @@ function findMediaStripItemElement(sectionId, index) {
|
|
|
18729
18999
|
}
|
|
18730
19000
|
return null;
|
|
18731
19001
|
}
|
|
18732
|
-
function
|
|
18733
|
-
|
|
19002
|
+
function itemRefFromTarget(target) {
|
|
19003
|
+
if (!(target instanceof Element)) return null;
|
|
19004
|
+
if (target.closest(CHROME_SELECTOR)) return null;
|
|
19005
|
+
const itemEl = target.closest("[data-ohw-media-strip-item]");
|
|
19006
|
+
if (!itemEl) return null;
|
|
19007
|
+
const sectionEl = itemEl.closest("[data-ohw-section]");
|
|
19008
|
+
const unit = sectionEl ? movableUnit(sectionEl) : null;
|
|
19009
|
+
const sectionId = unit ? instanceIdOf(unit) || null : null;
|
|
19010
|
+
const index = Number(itemEl.dataset.ohwMediaStripIndex);
|
|
19011
|
+
if (!sectionId || Number.isNaN(index)) return null;
|
|
19012
|
+
return { sectionId, index };
|
|
19013
|
+
}
|
|
19014
|
+
function sameRef(a, b) {
|
|
19015
|
+
return a?.sectionId === b?.sectionId && a?.index === b?.index;
|
|
19016
|
+
}
|
|
19017
|
+
function rectOf(el) {
|
|
18734
19018
|
if (!el) return null;
|
|
18735
19019
|
const r2 = el.getBoundingClientRect();
|
|
18736
19020
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
18737
19021
|
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
18738
19022
|
}
|
|
18739
|
-
function
|
|
19023
|
+
function readRect2(ref) {
|
|
19024
|
+
return rectOf(ref && findMediaStripItemElement(ref.sectionId, ref.index));
|
|
19025
|
+
}
|
|
19026
|
+
function readStripRect(ref) {
|
|
19027
|
+
const item = ref && findMediaStripItemElement(ref.sectionId, ref.index);
|
|
19028
|
+
return rectOf(item?.closest("[data-ohw-media-strip]") ?? item);
|
|
19029
|
+
}
|
|
19030
|
+
function useLiveItemRect(ref, strip = false) {
|
|
18740
19031
|
const [rect, setRect] = (0, import_react10.useState)(null);
|
|
18741
19032
|
(0, import_react10.useEffect)(() => {
|
|
18742
19033
|
if (!ref) {
|
|
@@ -18744,7 +19035,7 @@ function useLiveItemRect(ref) {
|
|
|
18744
19035
|
return;
|
|
18745
19036
|
}
|
|
18746
19037
|
const update = () => {
|
|
18747
|
-
const next = readRect2(ref);
|
|
19038
|
+
const next = strip ? readStripRect(ref) : readRect2(ref);
|
|
18748
19039
|
setRect(
|
|
18749
19040
|
(prev) => prev && next && prev.top === next.top && prev.left === next.left && prev.width === next.width && prev.height === next.height ? prev : next
|
|
18750
19041
|
);
|
|
@@ -18759,9 +19050,49 @@ function useLiveItemRect(ref) {
|
|
|
18759
19050
|
window.removeEventListener("resize", update);
|
|
18760
19051
|
clearInterval(interval);
|
|
18761
19052
|
};
|
|
18762
|
-
}, [ref?.sectionId, ref?.index]);
|
|
19053
|
+
}, [ref?.sectionId, ref?.index, strip]);
|
|
18763
19054
|
return rect;
|
|
18764
19055
|
}
|
|
19056
|
+
var TOOLBAR_STRIP_GAP = 52;
|
|
19057
|
+
var TOOLBAR_STRIP_GAP_MOBILE = 42;
|
|
19058
|
+
var TOOLBAR_EDGE_MARGIN2 = 4;
|
|
19059
|
+
function StripToolbarSlot({ stripRect, children }) {
|
|
19060
|
+
const slotRef = (0, import_react10.useRef)(null);
|
|
19061
|
+
const [shift, setShift] = (0, import_react10.useState)(0);
|
|
19062
|
+
const centerX = stripRect.left + stripRect.width / 2;
|
|
19063
|
+
(0, import_react10.useLayoutEffect)(() => {
|
|
19064
|
+
const slot = slotRef.current;
|
|
19065
|
+
if (!slot) return;
|
|
19066
|
+
const clamp = () => {
|
|
19067
|
+
const w = slot.offsetWidth;
|
|
19068
|
+
if (w <= 0) return;
|
|
19069
|
+
const half = w / 2;
|
|
19070
|
+
const clamped = Math.max(TOOLBAR_EDGE_MARGIN2 + half, Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN2 - half));
|
|
19071
|
+
setShift((prev) => Math.abs(prev - (clamped - centerX)) < 0.5 ? prev : clamped - centerX);
|
|
19072
|
+
};
|
|
19073
|
+
clamp();
|
|
19074
|
+
const ro = new ResizeObserver(clamp);
|
|
19075
|
+
ro.observe(slot);
|
|
19076
|
+
return () => ro.disconnect();
|
|
19077
|
+
}, [centerX, children]);
|
|
19078
|
+
const mobile = window.innerWidth <= 480;
|
|
19079
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19080
|
+
"div",
|
|
19081
|
+
{
|
|
19082
|
+
ref: slotRef,
|
|
19083
|
+
"data-ohw-bridge": "",
|
|
19084
|
+
"data-ohw-item-interaction": "",
|
|
19085
|
+
className: "pointer-events-auto fixed",
|
|
19086
|
+
style: {
|
|
19087
|
+
top: stripRect.top - (mobile ? TOOLBAR_STRIP_GAP_MOBILE : TOOLBAR_STRIP_GAP),
|
|
19088
|
+
left: centerX + shift,
|
|
19089
|
+
transform: "translate(-50%, -100%)",
|
|
19090
|
+
zIndex: 2147483645
|
|
19091
|
+
},
|
|
19092
|
+
children
|
|
19093
|
+
}
|
|
19094
|
+
);
|
|
19095
|
+
}
|
|
18765
19096
|
function requestValidateTree(postToParent2, tree) {
|
|
18766
19097
|
return new Promise((resolve) => {
|
|
18767
19098
|
const id = `ai-validate-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
@@ -18798,116 +19129,72 @@ function requestAssetPick(postToParent2) {
|
|
|
18798
19129
|
postToParent2({ type: "ow:asset-pick", id });
|
|
18799
19130
|
});
|
|
18800
19131
|
}
|
|
18801
|
-
function
|
|
19132
|
+
function ToolbarAction({
|
|
18802
19133
|
label,
|
|
18803
19134
|
onClick,
|
|
18804
|
-
disabled,
|
|
18805
|
-
active
|
|
19135
|
+
disabled = false,
|
|
19136
|
+
active = false,
|
|
19137
|
+
children
|
|
18806
19138
|
}) {
|
|
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
|
-
);
|
|
19139
|
+
const button = /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CustomToolbarButton, { type: "button", "aria-label": label, disabled, active, onClick, className: "size-8", children });
|
|
19140
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Tooltip, { children: [
|
|
19141
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "inline-flex", children: button }) : button }),
|
|
19142
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: label })
|
|
19143
|
+
] });
|
|
18834
19144
|
}
|
|
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",
|
|
19145
|
+
function ToolbarSeparator() {
|
|
19146
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { "aria-hidden": true, className: "mx-0.5 block h-6 w-px shrink-0 bg-border" });
|
|
19147
|
+
}
|
|
19148
|
+
function OptionMenu({
|
|
19149
|
+
label,
|
|
19150
|
+
value,
|
|
19151
|
+
options,
|
|
19152
|
+
onChange
|
|
19153
|
+
}) {
|
|
19154
|
+
const current = options.find((o) => o.value === value) ?? options[0];
|
|
19155
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19156
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-xs text-muted-foreground", children: label }),
|
|
19157
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(DropdownMenu, { modal: false, children: [
|
|
19158
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
19159
|
+
"button",
|
|
19160
|
+
{
|
|
19161
|
+
type: "button",
|
|
19162
|
+
"aria-label": label,
|
|
19163
|
+
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",
|
|
19164
|
+
children: [
|
|
19165
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "flex-1 text-left", children: current.label }),
|
|
19166
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.ChevronDown, { size: 16, style: { pointerEvents: "none" } })
|
|
19167
|
+
]
|
|
19168
|
+
}
|
|
19169
|
+
) }),
|
|
19170
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DropdownMenuContent, { align: "end", sideOffset: 8, className: "w-[132px] min-w-[132px] p-1", children: options.map((option) => {
|
|
19171
|
+
const selected = option.value === value;
|
|
19172
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
19173
|
+
DropdownMenuItem,
|
|
18870
19174
|
{
|
|
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
|
-
);
|
|
19175
|
+
role: "menuitemradio",
|
|
19176
|
+
"aria-checked": selected,
|
|
19177
|
+
onSelect: () => onChange(option.value),
|
|
19178
|
+
className: cn("grid grid-cols-[1fr_16px] gap-2 py-2 pl-2 pr-2 text-[13px]", selected && "bg-muted"),
|
|
19179
|
+
children: [
|
|
19180
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: option.label }),
|
|
19181
|
+
selected && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Check, { size: 16, className: "text-bridge-primary" })
|
|
19182
|
+
]
|
|
19183
|
+
},
|
|
19184
|
+
option.value
|
|
19185
|
+
);
|
|
19186
|
+
}) })
|
|
19187
|
+
] })
|
|
19188
|
+
] });
|
|
18902
19189
|
}
|
|
18903
19190
|
var VARIANTS = [
|
|
18904
19191
|
{ value: "logos", label: "Logos" },
|
|
18905
19192
|
{ value: "reel", label: "Reel" }
|
|
18906
19193
|
];
|
|
18907
19194
|
var ALIGNS = [
|
|
18908
|
-
{ value: "left", label: "
|
|
18909
|
-
{ value: "center", label: "
|
|
18910
|
-
{ value: "right", label: "
|
|
19195
|
+
{ value: "left", label: "Align left", Icon: import_lucide_react9.AlignLeft },
|
|
19196
|
+
{ value: "center", label: "Align center", Icon: import_lucide_react9.AlignCenter },
|
|
19197
|
+
{ value: "right", label: "Align right", Icon: import_lucide_react9.AlignRight }
|
|
18911
19198
|
];
|
|
18912
19199
|
var HOVERS = [
|
|
18913
19200
|
{ value: "none", label: "None" },
|
|
@@ -18915,104 +19202,104 @@ var HOVERS = [
|
|
|
18915
19202
|
{ value: "zoom", label: "Zoom" },
|
|
18916
19203
|
{ value: "fade", label: "Fade" }
|
|
18917
19204
|
];
|
|
18918
|
-
var TREATMENTS = [
|
|
18919
|
-
{ value: "color", label: "Color" },
|
|
18920
|
-
{ value: "grayscale", label: "Grayscale" }
|
|
18921
|
-
];
|
|
18922
19205
|
var HTTP_URL_RE = /^https?:\/\/\S+$/i;
|
|
18923
|
-
function
|
|
18924
|
-
|
|
19206
|
+
function LinkModal({
|
|
19207
|
+
href,
|
|
19208
|
+
linkTarget,
|
|
19209
|
+
onClose,
|
|
19210
|
+
onSave
|
|
19211
|
+
}) {
|
|
19212
|
+
const [draft, setDraft] = (0, import_react10.useState)(href);
|
|
19213
|
+
const [newTab, setNewTab] = (0, import_react10.useState)(linkTarget !== "same-tab");
|
|
18925
19214
|
const [invalid, setInvalid] = (0, import_react10.useState)(false);
|
|
18926
|
-
|
|
18927
|
-
setDraft(value);
|
|
18928
|
-
setInvalid(false);
|
|
18929
|
-
}, [value]);
|
|
18930
|
-
const commit = () => {
|
|
19215
|
+
const save = () => {
|
|
18931
19216
|
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
|
-
]
|
|
19217
|
+
if (next && !HTTP_URL_RE.test(next)) {
|
|
19218
|
+
setInvalid(true);
|
|
19219
|
+
return;
|
|
19001
19220
|
}
|
|
19002
|
-
|
|
19221
|
+
onSave(next, newTab ? "new-tab" : "same-tab");
|
|
19222
|
+
onClose();
|
|
19223
|
+
};
|
|
19224
|
+
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: [
|
|
19225
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DialogHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DialogTitle, { className: "text-base", children: "Image link" }) }),
|
|
19226
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-col gap-3", children: [
|
|
19227
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19228
|
+
"input",
|
|
19229
|
+
{
|
|
19230
|
+
autoFocus: true,
|
|
19231
|
+
type: "text",
|
|
19232
|
+
inputMode: "url",
|
|
19233
|
+
value: draft,
|
|
19234
|
+
onChange: (e) => {
|
|
19235
|
+
setDraft(e.target.value);
|
|
19236
|
+
setInvalid(false);
|
|
19237
|
+
},
|
|
19238
|
+
onKeyDown: (e) => {
|
|
19239
|
+
if (e.key === "Enter") save();
|
|
19240
|
+
},
|
|
19241
|
+
placeholder: "https://example.com",
|
|
19242
|
+
"aria-label": "Image link URL",
|
|
19243
|
+
"aria-invalid": invalid,
|
|
19244
|
+
className: cn(
|
|
19245
|
+
"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",
|
|
19246
|
+
invalid && "border-destructive focus:border-destructive"
|
|
19247
|
+
)
|
|
19248
|
+
}
|
|
19249
|
+
),
|
|
19250
|
+
invalid && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-xs text-destructive", children: "Enter a full URL starting with http:// or https://" }),
|
|
19251
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex items-center gap-2 text-[13px] text-foreground", children: [
|
|
19252
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("input", { type: "checkbox", checked: newTab, onChange: (e) => setNewTab(e.target.checked) }),
|
|
19253
|
+
"Open in new tab"
|
|
19254
|
+
] })
|
|
19255
|
+
] }),
|
|
19256
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(DialogFooter, { children: [
|
|
19257
|
+
href && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19258
|
+
"button",
|
|
19259
|
+
{
|
|
19260
|
+
type: "button",
|
|
19261
|
+
onClick: () => {
|
|
19262
|
+
onSave("", "new-tab");
|
|
19263
|
+
onClose();
|
|
19264
|
+
},
|
|
19265
|
+
className: "mr-auto rounded-[6px] px-3 py-2 text-[13px] font-medium text-destructive transition-colors hover:bg-muted",
|
|
19266
|
+
children: "Remove link"
|
|
19267
|
+
}
|
|
19268
|
+
),
|
|
19269
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19270
|
+
"button",
|
|
19271
|
+
{
|
|
19272
|
+
type: "button",
|
|
19273
|
+
onClick: onClose,
|
|
19274
|
+
className: "rounded-[6px] px-3 py-2 text-[13px] font-medium text-foreground transition-colors hover:bg-muted",
|
|
19275
|
+
children: "Cancel"
|
|
19276
|
+
}
|
|
19277
|
+
),
|
|
19278
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19279
|
+
"button",
|
|
19280
|
+
{
|
|
19281
|
+
type: "button",
|
|
19282
|
+
onClick: save,
|
|
19283
|
+
className: "rounded-[6px] bg-bridge-primary px-3 py-2 text-[13px] font-medium text-primary-foreground transition-opacity hover:opacity-90",
|
|
19284
|
+
children: "Save"
|
|
19285
|
+
}
|
|
19286
|
+
)
|
|
19287
|
+
] })
|
|
19288
|
+
] }) });
|
|
19003
19289
|
}
|
|
19004
19290
|
function MediaStripToolbar({
|
|
19005
19291
|
entry,
|
|
19006
19292
|
index,
|
|
19007
19293
|
pending,
|
|
19008
19294
|
error,
|
|
19295
|
+
itemEditOn,
|
|
19296
|
+
onToggleItemEdit,
|
|
19009
19297
|
onSetVariant,
|
|
19010
19298
|
onSetAlign,
|
|
19011
19299
|
onSetHover,
|
|
19012
19300
|
onSetTreatment,
|
|
19013
19301
|
onResize,
|
|
19014
|
-
|
|
19015
|
-
onSetLink,
|
|
19302
|
+
onOpenLink,
|
|
19016
19303
|
onAddItem,
|
|
19017
19304
|
onRemoveItem,
|
|
19018
19305
|
onChangeImage,
|
|
@@ -19021,81 +19308,102 @@ function MediaStripToolbar({
|
|
|
19021
19308
|
}) {
|
|
19022
19309
|
const items = mediaStripItems(entry.tree);
|
|
19023
19310
|
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
19311
|
const slots = findMediaStripSlots(entry.tree);
|
|
19028
19312
|
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
19029
19313
|
const align = slots?.align === "left" || slots?.align === "right" ? slots.align : "center";
|
|
19030
19314
|
const hover = slots?.hover === "none" || slots?.hover === "lift" || slots?.hover === "zoom" || slots?.hover === "fade" ? slots.hover : "lift";
|
|
19031
19315
|
const treatment = slots?.treatment === "color" || slots?.treatment === "grayscale" ? slots.treatment : variant === "logos" ? "grayscale" : "color";
|
|
19032
19316
|
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)(
|
|
19317
|
+
const mobile = window.innerWidth <= 480;
|
|
19318
|
+
const gatedLabel = (label) => itemEditOn ? label : "Turn on the star to edit this image";
|
|
19319
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
19045
19320
|
"div",
|
|
19046
19321
|
{
|
|
19047
19322
|
"data-ohw-bridge": "",
|
|
19048
19323
|
"data-ohw-toolbar": "",
|
|
19049
19324
|
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
|
-
},
|
|
19325
|
+
className: cn("flex flex-col items-center gap-1.5 font-sans", pending && "pointer-events-none opacity-60"),
|
|
19326
|
+
style: { maxWidth: mobile ? "calc(100vw - 24px)" : void 0 },
|
|
19063
19327
|
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
|
-
|
|
19328
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
19329
|
+
"div",
|
|
19330
|
+
{
|
|
19331
|
+
className: cn(
|
|
19332
|
+
"flex items-center gap-1 rounded-[10px] border border-border bg-background p-1 whitespace-nowrap",
|
|
19333
|
+
"shadow-[0px_10px_15px_-3px_rgba(0,0,0,0.1),0px_4px_6px_-4px_rgba(0,0,0,0.1)]",
|
|
19334
|
+
mobile ? "flex-wrap justify-center" : "flex-nowrap"
|
|
19335
|
+
),
|
|
19336
|
+
children: [
|
|
19337
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Tooltip, { children: [
|
|
19338
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19339
|
+
CustomToolbarButton,
|
|
19340
|
+
{
|
|
19341
|
+
type: "button",
|
|
19342
|
+
"aria-label": itemEditOn ? "Done editing this image" : "Edit this image",
|
|
19343
|
+
"aria-pressed": itemEditOn,
|
|
19344
|
+
onClick: onToggleItemEdit,
|
|
19345
|
+
className: "group size-8",
|
|
19346
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19347
|
+
import_lucide_react9.Star,
|
|
19348
|
+
{
|
|
19349
|
+
size: 16,
|
|
19350
|
+
fill: "currentColor",
|
|
19351
|
+
strokeWidth: 0,
|
|
19352
|
+
className: cn(
|
|
19353
|
+
"transition-colors",
|
|
19354
|
+
itemEditOn ? "text-[#f59e0b] group-hover:text-[#d97706]" : "text-[#d6d3d1] group-hover:text-[#fbbf24]"
|
|
19355
|
+
),
|
|
19356
|
+
style: { pointerEvents: "none" }
|
|
19357
|
+
}
|
|
19358
|
+
)
|
|
19359
|
+
}
|
|
19360
|
+
) }),
|
|
19361
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: itemEditOn ? "Done editing this image" : "Edit this image" })
|
|
19362
|
+
] }),
|
|
19363
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19364
|
+
/* @__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" } }) }),
|
|
19365
|
+
/* @__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" } }) }),
|
|
19366
|
+
/* @__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" } }) }),
|
|
19367
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19368
|
+
ToolbarAction,
|
|
19369
|
+
{
|
|
19370
|
+
label: gatedLabel("Move right"),
|
|
19371
|
+
onClick: onMoveRight,
|
|
19372
|
+
disabled: !itemEditOn || index >= itemCount - 1,
|
|
19373
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.ArrowRight, { size: 16, style: { pointerEvents: "none" } })
|
|
19374
|
+
}
|
|
19375
|
+
),
|
|
19376
|
+
/* @__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" } }) }),
|
|
19377
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19378
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(OptionMenu, { label: "Layout", value: variant, options: VARIANTS, onChange: onSetVariant }),
|
|
19379
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(OptionMenu, { label: "Hover", value: hover, options: HOVERS, onChange: onSetHover }),
|
|
19380
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19381
|
+
ToolbarAction,
|
|
19382
|
+
{
|
|
19383
|
+
label: treatment === "grayscale" ? "Show in color" : "Show grayscale",
|
|
19384
|
+
active: treatment === "grayscale",
|
|
19385
|
+
onClick: () => onSetTreatment(treatment === "grayscale" ? "color" : "grayscale"),
|
|
19386
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Palette, { size: 16, style: { pointerEvents: "none" } })
|
|
19387
|
+
}
|
|
19388
|
+
),
|
|
19389
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19390
|
+
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)),
|
|
19391
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19392
|
+
/* @__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" } }) }),
|
|
19393
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "min-w-[40px] text-center text-xs tabular-nums text-muted-foreground", children: [
|
|
19394
|
+
sizeValue,
|
|
19395
|
+
"px"
|
|
19396
|
+
] }),
|
|
19397
|
+
/* @__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" } }) }),
|
|
19398
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19399
|
+
/* @__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" } }) })
|
|
19400
|
+
]
|
|
19401
|
+
}
|
|
19402
|
+
),
|
|
19403
|
+
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
19404
|
]
|
|
19097
19405
|
}
|
|
19098
|
-
);
|
|
19406
|
+
) });
|
|
19099
19407
|
}
|
|
19100
19408
|
function findMediaStripSlots(tree) {
|
|
19101
19409
|
const stack = tree.rows.flatMap((row) => row.blocks);
|
|
@@ -19114,31 +19422,23 @@ function AiMediaStripOverlay({
|
|
|
19114
19422
|
}) {
|
|
19115
19423
|
const [hover, setHover] = (0, import_react10.useState)(null);
|
|
19116
19424
|
const [active, setActive] = (0, import_react10.useState)(null);
|
|
19425
|
+
const [itemEditOn, setItemEditOn] = (0, import_react10.useState)(false);
|
|
19426
|
+
const [linkOpen, setLinkOpen] = (0, import_react10.useState)(false);
|
|
19117
19427
|
const [pending, setPending] = (0, import_react10.useState)(false);
|
|
19118
19428
|
const [error, setError] = (0, import_react10.useState)(null);
|
|
19119
19429
|
const activeRef = (0, import_react10.useRef)(null);
|
|
19120
19430
|
activeRef.current = active;
|
|
19431
|
+
const linkOpenRef = (0, import_react10.useRef)(false);
|
|
19432
|
+
linkOpenRef.current = linkOpen;
|
|
19121
19433
|
(0, import_react10.useEffect)(() => {
|
|
19122
19434
|
const onMove = (e) => {
|
|
19435
|
+
const ref = itemRefFromTarget(e.target);
|
|
19123
19436
|
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 });
|
|
19437
|
+
const overEditable = Boolean(t?.closest?.("[data-ohw-editable]"));
|
|
19438
|
+
setHover((prev) => {
|
|
19439
|
+
const next = ref && !overEditable ? ref : null;
|
|
19440
|
+
return sameRef(prev, next) ? prev : next;
|
|
19441
|
+
});
|
|
19142
19442
|
};
|
|
19143
19443
|
const onLeave = () => setHover(null);
|
|
19144
19444
|
document.addEventListener("mousemove", onMove, { passive: true });
|
|
@@ -19150,23 +19450,25 @@ function AiMediaStripOverlay({
|
|
|
19150
19450
|
}, []);
|
|
19151
19451
|
(0, import_react10.useEffect)(() => {
|
|
19152
19452
|
const onClick = (e) => {
|
|
19153
|
-
const current = activeRef.current;
|
|
19154
|
-
if (!current) return;
|
|
19155
19453
|
const t = e.target;
|
|
19156
|
-
if (!(t instanceof
|
|
19157
|
-
if (t.closest(
|
|
19158
|
-
const
|
|
19159
|
-
if (
|
|
19160
|
-
|
|
19454
|
+
if (!(t instanceof Element)) return;
|
|
19455
|
+
if (t.closest(CHROME_SELECTOR)) return;
|
|
19456
|
+
const ref = itemRefFromTarget(t);
|
|
19457
|
+
if (sameRef(activeRef.current, ref)) return;
|
|
19458
|
+
if (ref) clearInteractionChromeRef.current();
|
|
19459
|
+
setItemEditOn(false);
|
|
19161
19460
|
setError(null);
|
|
19461
|
+
setActive(ref);
|
|
19162
19462
|
};
|
|
19163
19463
|
document.addEventListener("click", onClick, true);
|
|
19164
19464
|
return () => document.removeEventListener("click", onClick, true);
|
|
19165
|
-
}, []);
|
|
19465
|
+
}, [clearInteractionChromeRef]);
|
|
19166
19466
|
(0, import_react10.useEffect)(() => {
|
|
19167
19467
|
const onBlur = () => {
|
|
19168
19468
|
if (!activeRef.current) return;
|
|
19169
19469
|
setActive(null);
|
|
19470
|
+
setItemEditOn(false);
|
|
19471
|
+
setLinkOpen(false);
|
|
19170
19472
|
setError(null);
|
|
19171
19473
|
};
|
|
19172
19474
|
window.addEventListener("blur", onBlur);
|
|
@@ -19176,7 +19478,10 @@ function AiMediaStripOverlay({
|
|
|
19176
19478
|
const onKeyDown = (e) => {
|
|
19177
19479
|
if (e.key !== "Escape") return;
|
|
19178
19480
|
if (!activeRef.current) return;
|
|
19481
|
+
if (linkOpenRef.current) return;
|
|
19482
|
+
if (document.querySelector('[data-ohw-more-menu][data-state="open"]')) return;
|
|
19179
19483
|
setActive(null);
|
|
19484
|
+
setItemEditOn(false);
|
|
19180
19485
|
setError(null);
|
|
19181
19486
|
};
|
|
19182
19487
|
document.addEventListener("keydown", onKeyDown);
|
|
@@ -19210,137 +19515,133 @@ function AiMediaStripOverlay({
|
|
|
19210
19515
|
tree: nextTree,
|
|
19211
19516
|
label: entry.label,
|
|
19212
19517
|
media: extraMedia ? { ...entry.media, ...extraMedia } : entry.media,
|
|
19213
|
-
...entry.brand ? { brand: entry.brand } : {}
|
|
19518
|
+
...entry.brand ? { brand: entry.brand } : {},
|
|
19519
|
+
// The user is already looking at the strip they just edited — recentering the viewport
|
|
19520
|
+
// on every edit reads as the section jumping around.
|
|
19521
|
+
skipScrollIntoView: true
|
|
19214
19522
|
});
|
|
19215
19523
|
return true;
|
|
19216
19524
|
},
|
|
19217
19525
|
[findEntry, postToParent2, applyTreeLocalRef]
|
|
19218
19526
|
);
|
|
19219
19527
|
const activeEntry = active ? findEntry(active.sectionId) : null;
|
|
19220
|
-
const hoverHandleRect = useLiveItemRect(!active && hover ? hover : null);
|
|
19221
19528
|
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) => {
|
|
19529
|
+
const activeStripRect = useLiveItemRect(active, true);
|
|
19530
|
+
const hoverRect = useLiveItemRect(hover && !sameRef(hover, active) ? hover : null);
|
|
19531
|
+
const activeItems = activeEntry ? mediaStripItems(activeEntry.tree) : [];
|
|
19532
|
+
const activeItem = active ? activeItems[active.index] : void 0;
|
|
19533
|
+
const activeHref = activeItem?.href ?? "";
|
|
19534
|
+
const activeTarget = activeItem?.linkTarget === "same-tab" ? "same-tab" : "new-tab";
|
|
19535
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
19536
|
+
hoverRect && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ItemInteractionLayer, { rect: hoverRect, state: "hover" }),
|
|
19537
|
+
activeItemRect && activeStripRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
19538
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ItemInteractionLayer, { rect: activeItemRect, state: "active-top" }),
|
|
19539
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StripToolbarSlot, { stripRect: activeStripRect, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19540
|
+
MediaStripToolbar,
|
|
19541
|
+
{
|
|
19542
|
+
entry: activeEntry,
|
|
19543
|
+
index: active.index,
|
|
19544
|
+
pending,
|
|
19545
|
+
error,
|
|
19546
|
+
itemEditOn,
|
|
19547
|
+
onToggleItemEdit: () => setItemEditOn((on) => !on),
|
|
19548
|
+
onSetVariant: (variant) => runMutation(active.sectionId, (tree) => setMediaStripVariant(tree, variant)),
|
|
19549
|
+
onSetAlign: (align) => runMutation(active.sectionId, (tree) => setMediaStripAlign(tree, align)),
|
|
19550
|
+
onSetHover: (hoverPreset) => runMutation(active.sectionId, (tree) => setMediaStripHover(tree, hoverPreset)),
|
|
19551
|
+
onSetTreatment: (treatment) => runMutation(active.sectionId, (tree) => setMediaStripTreatment(tree, treatment)),
|
|
19552
|
+
onResize: (delta) => {
|
|
19553
|
+
const slots = findMediaStripSlots(activeEntry.tree);
|
|
19554
|
+
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
19555
|
+
const current = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
19556
|
+
void runMutation(active.sectionId, (tree) => setMediaStripSizing(tree, current + delta));
|
|
19557
|
+
},
|
|
19558
|
+
onOpenLink: () => setLinkOpen(true),
|
|
19559
|
+
onAddItem: () => {
|
|
19560
|
+
void requestAssetPick(postToParent2).then((picked) => {
|
|
19561
|
+
if (!picked) return;
|
|
19562
|
+
const item = { assetId: picked.assetId, alt: "Logo" };
|
|
19282
19563
|
void runMutation(
|
|
19283
19564
|
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
|
-
});
|
|
19565
|
+
(tree) => addMediaStripItem(tree, item, active.index),
|
|
19566
|
+
{ [picked.assetId]: picked.url }
|
|
19567
|
+
).then((applied) => {
|
|
19568
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19298
19569
|
});
|
|
19299
|
-
}
|
|
19300
|
-
|
|
19301
|
-
|
|
19302
|
-
|
|
19303
|
-
|
|
19304
|
-
|
|
19305
|
-
|
|
19306
|
-
|
|
19307
|
-
|
|
19308
|
-
});
|
|
19309
|
-
},
|
|
19310
|
-
onRemoveItem: () => {
|
|
19311
|
-
void runMutation(active.sectionId, (tree) => removeMediaStripItem(tree, active.index)).then(
|
|
19312
|
-
(applied) => {
|
|
19313
|
-
if (applied) setActive(null);
|
|
19314
|
-
}
|
|
19315
|
-
);
|
|
19316
|
-
},
|
|
19317
|
-
onMoveLeft: () => {
|
|
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
|
-
}
|
|
19570
|
+
});
|
|
19571
|
+
},
|
|
19572
|
+
onChangeImage: () => {
|
|
19573
|
+
void requestAssetPick(postToParent2).then((picked) => {
|
|
19574
|
+
if (!picked) return;
|
|
19575
|
+
void runMutation(
|
|
19576
|
+
active.sectionId,
|
|
19577
|
+
(tree) => setMediaStripItemAsset(tree, active.index, picked.assetId),
|
|
19578
|
+
{ [picked.assetId]: picked.url }
|
|
19329
19579
|
);
|
|
19330
|
-
}
|
|
19580
|
+
});
|
|
19581
|
+
},
|
|
19582
|
+
onRemoveItem: () => {
|
|
19583
|
+
void runMutation(active.sectionId, (tree) => removeMediaStripItem(tree, active.index)).then(
|
|
19584
|
+
(applied) => {
|
|
19585
|
+
if (applied) setActive(null);
|
|
19586
|
+
}
|
|
19587
|
+
);
|
|
19588
|
+
},
|
|
19589
|
+
onMoveLeft: () => {
|
|
19590
|
+
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, -1)).then(
|
|
19591
|
+
(applied) => {
|
|
19592
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index - 1 });
|
|
19593
|
+
}
|
|
19594
|
+
);
|
|
19595
|
+
},
|
|
19596
|
+
onMoveRight: () => {
|
|
19597
|
+
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, 1)).then(
|
|
19598
|
+
(applied) => {
|
|
19599
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19600
|
+
}
|
|
19601
|
+
);
|
|
19331
19602
|
}
|
|
19332
|
-
|
|
19333
|
-
}
|
|
19334
|
-
|
|
19603
|
+
}
|
|
19604
|
+
) }),
|
|
19605
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19606
|
+
"div",
|
|
19607
|
+
{
|
|
19608
|
+
"data-ohw-bridge": "",
|
|
19609
|
+
"data-ohw-item-interaction": "",
|
|
19610
|
+
"aria-hidden": true,
|
|
19611
|
+
className: "pointer-events-none fixed rounded-[4px] px-[7px] py-[3px] font-sans text-[11px] font-medium leading-none text-primary-foreground whitespace-nowrap",
|
|
19612
|
+
style: {
|
|
19613
|
+
top: activeItemRect.top + activeItemRect.height + 10,
|
|
19614
|
+
left: activeItemRect.left - 5,
|
|
19615
|
+
background: PRIMARY3,
|
|
19616
|
+
zIndex: 2147483644
|
|
19617
|
+
},
|
|
19618
|
+
children: "Media item"
|
|
19619
|
+
}
|
|
19620
|
+
),
|
|
19621
|
+
linkOpen && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19622
|
+
LinkModal,
|
|
19623
|
+
{
|
|
19624
|
+
href: activeHref,
|
|
19625
|
+
linkTarget: activeTarget,
|
|
19626
|
+
onClose: () => setLinkOpen(false),
|
|
19627
|
+
onSave: (href, linkTarget) => {
|
|
19628
|
+
void runMutation(
|
|
19629
|
+
active.sectionId,
|
|
19630
|
+
(tree) => setMediaStripItemLink(tree, active.index, href ? { href, linkTarget } : {})
|
|
19631
|
+
);
|
|
19632
|
+
}
|
|
19633
|
+
}
|
|
19634
|
+
)
|
|
19635
|
+
] })
|
|
19335
19636
|
] });
|
|
19336
19637
|
}
|
|
19337
19638
|
|
|
19338
19639
|
// src/ui/ai-section/AiPricingCardOverlay.tsx
|
|
19339
19640
|
var import_react11 = require("react");
|
|
19340
|
-
var
|
|
19341
|
-
var
|
|
19641
|
+
var import_lucide_react10 = require("lucide-react");
|
|
19642
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
19342
19643
|
var PRIMARY4 = "var(--ohw-primary, #0885FE)";
|
|
19343
|
-
var
|
|
19644
|
+
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
19645
|
function findPricingCardElement(sectionId, index) {
|
|
19345
19646
|
const sectionEl = findByInstanceId(sectionId);
|
|
19346
19647
|
if (!sectionEl) return null;
|
|
@@ -19352,7 +19653,7 @@ function findPricingCardElement(sectionId, index) {
|
|
|
19352
19653
|
}
|
|
19353
19654
|
function cardRefFromTarget(target) {
|
|
19354
19655
|
if (!(target instanceof Element)) return null;
|
|
19355
|
-
if (target.closest(
|
|
19656
|
+
if (target.closest(CHROME_SELECTOR2)) return null;
|
|
19356
19657
|
const cardEl = target.closest("[data-ohw-pricing-card]");
|
|
19357
19658
|
if (!cardEl) return null;
|
|
19358
19659
|
const sectionEl = cardEl.closest("[data-ohw-section]");
|
|
@@ -19362,21 +19663,21 @@ function cardRefFromTarget(target) {
|
|
|
19362
19663
|
if (!sectionId || Number.isNaN(index)) return null;
|
|
19363
19664
|
return { sectionId, index };
|
|
19364
19665
|
}
|
|
19365
|
-
function
|
|
19666
|
+
function sameRef2(a, b) {
|
|
19366
19667
|
return a?.sectionId === b?.sectionId && a?.index === b?.index;
|
|
19367
19668
|
}
|
|
19368
|
-
function
|
|
19669
|
+
function rectOf2(el) {
|
|
19369
19670
|
if (!el) return null;
|
|
19370
19671
|
const r2 = el.getBoundingClientRect();
|
|
19371
19672
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
19372
19673
|
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
19373
19674
|
}
|
|
19374
19675
|
function readRect3(ref) {
|
|
19375
|
-
return
|
|
19676
|
+
return rectOf2(ref && findPricingCardElement(ref.sectionId, ref.index));
|
|
19376
19677
|
}
|
|
19377
19678
|
function readGridRect(ref) {
|
|
19378
19679
|
const card = ref && findPricingCardElement(ref.sectionId, ref.index);
|
|
19379
|
-
return
|
|
19680
|
+
return rectOf2(card?.closest("[data-ohw-pricing-collection]") ?? card);
|
|
19380
19681
|
}
|
|
19381
19682
|
function useLiveCardRect(ref, grid = false) {
|
|
19382
19683
|
const [rect, setRect] = (0, import_react11.useState)(null);
|
|
@@ -19406,7 +19707,7 @@ function useLiveCardRect(ref, grid = false) {
|
|
|
19406
19707
|
}
|
|
19407
19708
|
var TOOLBAR_GRID_GAP = 52;
|
|
19408
19709
|
var TOOLBAR_GRID_GAP_MOBILE = 42;
|
|
19409
|
-
var
|
|
19710
|
+
var TOOLBAR_EDGE_MARGIN3 = 4;
|
|
19410
19711
|
function GridToolbarSlot({ gridRect, children }) {
|
|
19411
19712
|
const slotRef = (0, import_react11.useRef)(null);
|
|
19412
19713
|
const [shift, setShift] = (0, import_react11.useState)(0);
|
|
@@ -19418,7 +19719,7 @@ function GridToolbarSlot({ gridRect, children }) {
|
|
|
19418
19719
|
const w = slot.offsetWidth;
|
|
19419
19720
|
if (w <= 0) return;
|
|
19420
19721
|
const half = w / 2;
|
|
19421
|
-
const clamped = Math.max(
|
|
19722
|
+
const clamped = Math.max(TOOLBAR_EDGE_MARGIN3 + half, Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN3 - half));
|
|
19422
19723
|
setShift((prev) => Math.abs(prev - (clamped - centerX)) < 0.5 ? prev : clamped - centerX);
|
|
19423
19724
|
};
|
|
19424
19725
|
clamp();
|
|
@@ -19427,7 +19728,7 @@ function GridToolbarSlot({ gridRect, children }) {
|
|
|
19427
19728
|
return () => ro.disconnect();
|
|
19428
19729
|
}, [centerX, children]);
|
|
19429
19730
|
const mobile = window.innerWidth <= 480;
|
|
19430
|
-
return /* @__PURE__ */ (0,
|
|
19731
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19431
19732
|
"div",
|
|
19432
19733
|
{
|
|
19433
19734
|
ref: slotRef,
|
|
@@ -19462,7 +19763,7 @@ function requestValidateTree2(postToParent2, tree) {
|
|
|
19462
19763
|
});
|
|
19463
19764
|
}
|
|
19464
19765
|
function StyleSwatch({ style }) {
|
|
19465
|
-
return /* @__PURE__ */ (0,
|
|
19766
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19466
19767
|
"span",
|
|
19467
19768
|
{
|
|
19468
19769
|
"aria-hidden": true,
|
|
@@ -19476,35 +19777,35 @@ function StyleSwatch({ style }) {
|
|
|
19476
19777
|
);
|
|
19477
19778
|
}
|
|
19478
19779
|
function ButtonGlyph() {
|
|
19479
|
-
return /* @__PURE__ */ (0,
|
|
19480
|
-
/* @__PURE__ */ (0,
|
|
19481
|
-
/* @__PURE__ */ (0,
|
|
19780
|
+
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: [
|
|
19781
|
+
/* @__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" }),
|
|
19782
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M5.5 6H12.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
|
|
19482
19783
|
] });
|
|
19483
19784
|
}
|
|
19484
19785
|
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,
|
|
19786
|
+
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: [
|
|
19787
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("circle", { cx: "8", cy: "8", r: "7.25", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
19788
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M5 8.2L7.2 10.3L11 6", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
19789
|
+
/* @__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" }),
|
|
19790
|
+
/* @__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" }),
|
|
19791
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M11.5 13.5H15.5", stroke: PRIMARY4, strokeWidth: "1.5", strokeLinecap: "round" }),
|
|
19792
|
+
mode === "add" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M13.5 11.5V15.5", stroke: PRIMARY4, strokeWidth: "1.5", strokeLinecap: "round" })
|
|
19492
19793
|
] });
|
|
19493
19794
|
}
|
|
19494
|
-
function
|
|
19795
|
+
function ToolbarAction2({
|
|
19495
19796
|
label,
|
|
19496
19797
|
onClick,
|
|
19497
19798
|
disabled = false,
|
|
19498
19799
|
children
|
|
19499
19800
|
}) {
|
|
19500
|
-
const button = /* @__PURE__ */ (0,
|
|
19501
|
-
return /* @__PURE__ */ (0,
|
|
19502
|
-
/* @__PURE__ */ (0,
|
|
19503
|
-
/* @__PURE__ */ (0,
|
|
19801
|
+
const button = /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CustomToolbarButton, { type: "button", "aria-label": label, disabled, onClick, className: "size-8", children });
|
|
19802
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Tooltip, { children: [
|
|
19803
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "inline-flex", children: button }) : button }),
|
|
19804
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: label })
|
|
19504
19805
|
] });
|
|
19505
19806
|
}
|
|
19506
|
-
function
|
|
19507
|
-
return /* @__PURE__ */ (0,
|
|
19807
|
+
function ToolbarSeparator2() {
|
|
19808
|
+
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
19809
|
}
|
|
19509
19810
|
function CardStyleMenu({
|
|
19510
19811
|
value,
|
|
@@ -19512,7 +19813,7 @@ function CardStyleMenu({
|
|
|
19512
19813
|
disabled = false
|
|
19513
19814
|
}) {
|
|
19514
19815
|
const current = PRICING_CARD_STYLES.find((s) => s.value === value) ?? PRICING_CARD_STYLES[0];
|
|
19515
|
-
const trigger = /* @__PURE__ */ (0,
|
|
19816
|
+
const trigger = /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
19516
19817
|
"button",
|
|
19517
19818
|
{
|
|
19518
19819
|
type: "button",
|
|
@@ -19523,28 +19824,28 @@ function CardStyleMenu({
|
|
|
19523
19824
|
disabled && "cursor-not-allowed opacity-40 hover:bg-transparent"
|
|
19524
19825
|
),
|
|
19525
19826
|
children: [
|
|
19526
|
-
/* @__PURE__ */ (0,
|
|
19527
|
-
/* @__PURE__ */ (0,
|
|
19528
|
-
/* @__PURE__ */ (0,
|
|
19827
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(StyleSwatch, { style: current.value }),
|
|
19828
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "flex-1 text-left", children: current.label }),
|
|
19829
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.ChevronDown, { size: 16, style: { pointerEvents: "none" } })
|
|
19529
19830
|
]
|
|
19530
19831
|
}
|
|
19531
19832
|
);
|
|
19532
19833
|
if (disabled) {
|
|
19533
|
-
return /* @__PURE__ */ (0,
|
|
19534
|
-
/* @__PURE__ */ (0,
|
|
19535
|
-
/* @__PURE__ */ (0,
|
|
19536
|
-
/* @__PURE__ */ (0,
|
|
19537
|
-
/* @__PURE__ */ (0,
|
|
19834
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19835
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-xs text-muted-foreground opacity-50", children: "Card style" }),
|
|
19836
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Tooltip, { children: [
|
|
19837
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "inline-flex", children: trigger }) }),
|
|
19838
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: "Mark as featured to edit card style" })
|
|
19538
19839
|
] })
|
|
19539
19840
|
] });
|
|
19540
19841
|
}
|
|
19541
|
-
return /* @__PURE__ */ (0,
|
|
19542
|
-
/* @__PURE__ */ (0,
|
|
19543
|
-
/* @__PURE__ */ (0,
|
|
19544
|
-
/* @__PURE__ */ (0,
|
|
19545
|
-
/* @__PURE__ */ (0,
|
|
19842
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19843
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-xs text-muted-foreground", children: "Card style" }),
|
|
19844
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(DropdownMenu, { modal: false, children: [
|
|
19845
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DropdownMenuTrigger, { asChild: true, children: trigger }),
|
|
19846
|
+
/* @__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
19847
|
const selected = style.value === value;
|
|
19547
|
-
return /* @__PURE__ */ (0,
|
|
19848
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
19548
19849
|
DropdownMenuItem,
|
|
19549
19850
|
{
|
|
19550
19851
|
role: "menuitemradio",
|
|
@@ -19552,9 +19853,9 @@ function CardStyleMenu({
|
|
|
19552
19853
|
onSelect: () => onChange(style.value),
|
|
19553
19854
|
className: cn("grid grid-cols-[18px_1fr_16px] gap-2 py-2 pl-2 pr-2 text-[13px]", selected && "bg-muted"),
|
|
19554
19855
|
children: [
|
|
19555
|
-
/* @__PURE__ */ (0,
|
|
19556
|
-
/* @__PURE__ */ (0,
|
|
19557
|
-
selected && /* @__PURE__ */ (0,
|
|
19856
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(StyleSwatch, { style: style.value }),
|
|
19857
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { children: style.label }),
|
|
19858
|
+
selected && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Check, { size: 16, className: "text-bridge-primary" })
|
|
19558
19859
|
]
|
|
19559
19860
|
},
|
|
19560
19861
|
style.value
|
|
@@ -19584,7 +19885,7 @@ function PricingCardToolbar({
|
|
|
19584
19885
|
const style = pricingCardStyle(entry.tree, index);
|
|
19585
19886
|
const featuredTag = pricingCardFeaturedTag(entry.tree, index);
|
|
19586
19887
|
const mobile = window.innerWidth <= 480;
|
|
19587
|
-
return /* @__PURE__ */ (0,
|
|
19888
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
19588
19889
|
"div",
|
|
19589
19890
|
{
|
|
19590
19891
|
"data-ohw-bridge": "",
|
|
@@ -19596,7 +19897,7 @@ function PricingCardToolbar({
|
|
|
19596
19897
|
),
|
|
19597
19898
|
style: { maxWidth: mobile ? "calc(100vw - 24px)" : void 0 },
|
|
19598
19899
|
children: [
|
|
19599
|
-
/* @__PURE__ */ (0,
|
|
19900
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
19600
19901
|
"div",
|
|
19601
19902
|
{
|
|
19602
19903
|
className: cn(
|
|
@@ -19605,8 +19906,8 @@ function PricingCardToolbar({
|
|
|
19605
19906
|
mobile ? "flex-wrap justify-center" : "flex-nowrap"
|
|
19606
19907
|
),
|
|
19607
19908
|
children: [
|
|
19608
|
-
/* @__PURE__ */ (0,
|
|
19609
|
-
/* @__PURE__ */ (0,
|
|
19909
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Tooltip, { children: [
|
|
19910
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19610
19911
|
CustomToolbarButton,
|
|
19611
19912
|
{
|
|
19612
19913
|
type: "button",
|
|
@@ -19614,8 +19915,8 @@ function PricingCardToolbar({
|
|
|
19614
19915
|
"aria-pressed": featuredTag,
|
|
19615
19916
|
onClick: () => onSetFeaturedTag(!featuredTag),
|
|
19616
19917
|
className: "group size-8",
|
|
19617
|
-
children: /* @__PURE__ */ (0,
|
|
19618
|
-
|
|
19918
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19919
|
+
import_lucide_react10.Star,
|
|
19619
19920
|
{
|
|
19620
19921
|
size: 16,
|
|
19621
19922
|
fill: "currentColor",
|
|
@@ -19629,25 +19930,25 @@ function PricingCardToolbar({
|
|
|
19629
19930
|
)
|
|
19630
19931
|
}
|
|
19631
19932
|
) }),
|
|
19632
|
-
/* @__PURE__ */ (0,
|
|
19933
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: featuredTag ? "Unmark featured" : "Mark as featured" })
|
|
19633
19934
|
] }),
|
|
19634
|
-
/* @__PURE__ */ (0,
|
|
19635
|
-
/* @__PURE__ */ (0,
|
|
19636
|
-
/* @__PURE__ */ (0,
|
|
19637
|
-
/* @__PURE__ */ (0,
|
|
19638
|
-
/* @__PURE__ */ (0,
|
|
19639
|
-
/* @__PURE__ */ (0,
|
|
19640
|
-
/* @__PURE__ */ (0,
|
|
19935
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarSeparator2, {}),
|
|
19936
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CardStyleMenu, { value: style, onChange: onSetStyle, disabled: !featuredTag }),
|
|
19937
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarSeparator2, {}),
|
|
19938
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarAction2, { label: "Add button", onClick: onAddButton, disabled: buttonCount >= 2, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ButtonGlyph, {}) }),
|
|
19939
|
+
/* @__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: [
|
|
19940
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ButtonGlyph, {}),
|
|
19941
|
+
/* @__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
19942
|
] }) }),
|
|
19642
|
-
/* @__PURE__ */ (0,
|
|
19643
|
-
/* @__PURE__ */ (0,
|
|
19644
|
-
/* @__PURE__ */ (0,
|
|
19645
|
-
/* @__PURE__ */ (0,
|
|
19646
|
-
/* @__PURE__ */ (0,
|
|
19943
|
+
/* @__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" }) }),
|
|
19944
|
+
/* @__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" }) }),
|
|
19945
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarSeparator2, {}),
|
|
19946
|
+
/* @__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" } }) }),
|
|
19947
|
+
/* @__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
19948
|
]
|
|
19648
19949
|
}
|
|
19649
19950
|
),
|
|
19650
|
-
error && /* @__PURE__ */ (0,
|
|
19951
|
+
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
19952
|
]
|
|
19652
19953
|
}
|
|
19653
19954
|
) });
|
|
@@ -19681,7 +19982,7 @@ function AiPricingCardOverlay({
|
|
|
19681
19982
|
const overEditable = Boolean(t?.closest?.("[data-ohw-editable], [data-ohw-role], a, button"));
|
|
19682
19983
|
setHover((prev) => {
|
|
19683
19984
|
const next = ref && !overEditable ? ref : null;
|
|
19684
|
-
return
|
|
19985
|
+
return sameRef2(prev, next) ? prev : next;
|
|
19685
19986
|
});
|
|
19686
19987
|
};
|
|
19687
19988
|
const onLeave = () => setHover(null);
|
|
@@ -19696,10 +19997,10 @@ function AiPricingCardOverlay({
|
|
|
19696
19997
|
const onClick = (e) => {
|
|
19697
19998
|
const t = e.target;
|
|
19698
19999
|
if (!(t instanceof Element)) return;
|
|
19699
|
-
if (t.closest(
|
|
20000
|
+
if (t.closest(CHROME_SELECTOR2)) return;
|
|
19700
20001
|
const ref = cardRefFromTarget(t);
|
|
19701
|
-
setActive((prev) =>
|
|
19702
|
-
if (!ref || !
|
|
20002
|
+
setActive((prev) => sameRef2(prev, ref) ? prev : ref);
|
|
20003
|
+
if (!ref || !sameRef2(activeRef.current, ref)) setError(null);
|
|
19703
20004
|
};
|
|
19704
20005
|
document.addEventListener("click", onClick, true);
|
|
19705
20006
|
return () => document.removeEventListener("click", onClick, true);
|
|
@@ -19764,12 +20065,12 @@ function AiPricingCardOverlay({
|
|
|
19764
20065
|
const activeEntry = active ? findEntry(active.sectionId) : null;
|
|
19765
20066
|
const activeCardRect = useLiveCardRect(active);
|
|
19766
20067
|
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,
|
|
20068
|
+
const hoverRect = useLiveCardRect(hover && !sameRef2(hover, active) ? hover : null);
|
|
20069
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
20070
|
+
hoverRect && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ItemInteractionLayer, { rect: hoverRect, state: "hover" }),
|
|
20071
|
+
activeCardRect && activeGridRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
20072
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ItemInteractionLayer, { rect: activeCardRect, state: "active-top" }),
|
|
20073
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(GridToolbarSlot, { gridRect: activeGridRect, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19773
20074
|
PricingCardToolbar,
|
|
19774
20075
|
{
|
|
19775
20076
|
entry: activeEntry,
|
|
@@ -19797,7 +20098,7 @@ function AiPricingCardOverlay({
|
|
|
19797
20098
|
onRemoveFeature: () => runMutation(active.sectionId, (tree) => removePricingCardFeature(tree, active.index))
|
|
19798
20099
|
}
|
|
19799
20100
|
) }),
|
|
19800
|
-
/* @__PURE__ */ (0,
|
|
20101
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19801
20102
|
"div",
|
|
19802
20103
|
{
|
|
19803
20104
|
"data-ohw-bridge": "",
|
|
@@ -19819,7 +20120,7 @@ function AiPricingCardOverlay({
|
|
|
19819
20120
|
|
|
19820
20121
|
// src/ui/ai-section/AiVideoOverlay.tsx
|
|
19821
20122
|
var import_react12 = require("react");
|
|
19822
|
-
var
|
|
20123
|
+
var import_lucide_react11 = require("lucide-react");
|
|
19823
20124
|
|
|
19824
20125
|
// src/lib/ai-video-tree.ts
|
|
19825
20126
|
function resolveVideoBlock(tree, path) {
|
|
@@ -19890,10 +20191,10 @@ function extractYouTubeId(input) {
|
|
|
19890
20191
|
}
|
|
19891
20192
|
|
|
19892
20193
|
// src/ui/ai-section/AiVideoOverlay.tsx
|
|
19893
|
-
var
|
|
20194
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
19894
20195
|
var PRIMARY5 = "#0885FE";
|
|
19895
|
-
var
|
|
19896
|
-
var
|
|
20196
|
+
var OHW_BLUE = `var(--ohw-primary, ${PRIMARY5})`;
|
|
20197
|
+
var OHW_BLUE_DARK = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY5}) 60%, #000000)`;
|
|
19897
20198
|
function findVideoBlockElement(sectionId, path) {
|
|
19898
20199
|
const sectionEl = findByInstanceId(sectionId);
|
|
19899
20200
|
if (!sectionEl) return null;
|
|
@@ -19953,12 +20254,12 @@ function requestValidateTree3(postToParent2, tree) {
|
|
|
19953
20254
|
postToParent2({ type: "ow:ai-validate-tree-request", id, tree });
|
|
19954
20255
|
});
|
|
19955
20256
|
}
|
|
19956
|
-
function
|
|
20257
|
+
function Pill({
|
|
19957
20258
|
label,
|
|
19958
20259
|
onClick,
|
|
19959
20260
|
disabled
|
|
19960
20261
|
}) {
|
|
19961
|
-
return /* @__PURE__ */ (0,
|
|
20262
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
19962
20263
|
"button",
|
|
19963
20264
|
{
|
|
19964
20265
|
type: "button",
|
|
@@ -19974,7 +20275,7 @@ function Pill2({
|
|
|
19974
20275
|
border: "none",
|
|
19975
20276
|
cursor: disabled ? "default" : "pointer",
|
|
19976
20277
|
background: "#ffffff",
|
|
19977
|
-
color:
|
|
20278
|
+
color: OHW_BLUE_DARK,
|
|
19978
20279
|
opacity: disabled ? 0.4 : 1,
|
|
19979
20280
|
fontSize: 12,
|
|
19980
20281
|
lineHeight: "16px",
|
|
@@ -19996,7 +20297,7 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
19996
20297
|
setDraft(value ? watchUrl(value) : "");
|
|
19997
20298
|
setInvalid(false);
|
|
19998
20299
|
}, [value]);
|
|
19999
|
-
const
|
|
20300
|
+
const commit2 = () => {
|
|
20000
20301
|
const next = draft.trim();
|
|
20001
20302
|
if (!next) {
|
|
20002
20303
|
setInvalid(false);
|
|
@@ -20017,8 +20318,8 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20017
20318
|
onCommit(id);
|
|
20018
20319
|
}
|
|
20019
20320
|
};
|
|
20020
|
-
return /* @__PURE__ */ (0,
|
|
20021
|
-
/* @__PURE__ */ (0,
|
|
20321
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 4, width: "100%", maxWidth: 280 }, children: [
|
|
20322
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
20022
20323
|
"div",
|
|
20023
20324
|
{
|
|
20024
20325
|
style: {
|
|
@@ -20034,12 +20335,12 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20034
20335
|
boxShadow: invalid ? "inset 0 0 0 1.5px #EF4444" : "none"
|
|
20035
20336
|
},
|
|
20036
20337
|
children: [
|
|
20037
|
-
/* @__PURE__ */ (0,
|
|
20338
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20038
20339
|
"span",
|
|
20039
20340
|
{
|
|
20040
20341
|
style: {
|
|
20041
20342
|
flex: "0 0 auto",
|
|
20042
|
-
color:
|
|
20343
|
+
color: OHW_BLUE_DARK,
|
|
20043
20344
|
fontSize: 10,
|
|
20044
20345
|
lineHeight: "16px",
|
|
20045
20346
|
fontWeight: 700,
|
|
@@ -20049,14 +20350,14 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20049
20350
|
children: "Video"
|
|
20050
20351
|
}
|
|
20051
20352
|
),
|
|
20052
|
-
/* @__PURE__ */ (0,
|
|
20353
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20053
20354
|
"input",
|
|
20054
20355
|
{
|
|
20055
20356
|
type: "text",
|
|
20056
20357
|
inputMode: "url",
|
|
20057
20358
|
value: draft,
|
|
20058
20359
|
onChange: (e) => handleChange(e.target.value),
|
|
20059
|
-
onBlur:
|
|
20360
|
+
onBlur: commit2,
|
|
20060
20361
|
onKeyDown: (e) => {
|
|
20061
20362
|
if (e.key === "Enter") e.currentTarget.blur();
|
|
20062
20363
|
if (e.key === "Escape") {
|
|
@@ -20086,7 +20387,7 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20086
20387
|
]
|
|
20087
20388
|
}
|
|
20088
20389
|
),
|
|
20089
|
-
invalid && /* @__PURE__ */ (0,
|
|
20390
|
+
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
20391
|
] });
|
|
20091
20392
|
}
|
|
20092
20393
|
function VideoToolbar({
|
|
@@ -20096,7 +20397,7 @@ function VideoToolbar({
|
|
|
20096
20397
|
onSetVideoId,
|
|
20097
20398
|
onRemove
|
|
20098
20399
|
}) {
|
|
20099
|
-
return /* @__PURE__ */ (0,
|
|
20400
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
20100
20401
|
"div",
|
|
20101
20402
|
{
|
|
20102
20403
|
"data-ohw-bridge": "",
|
|
@@ -20108,7 +20409,7 @@ function VideoToolbar({
|
|
|
20108
20409
|
gap: 6,
|
|
20109
20410
|
alignItems: "center",
|
|
20110
20411
|
width: 280,
|
|
20111
|
-
background:
|
|
20412
|
+
background: OHW_BLUE,
|
|
20112
20413
|
padding: 8,
|
|
20113
20414
|
borderRadius: 12,
|
|
20114
20415
|
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
@@ -20116,9 +20417,9 @@ function VideoToolbar({
|
|
|
20116
20417
|
opacity: pending ? 0.6 : 1
|
|
20117
20418
|
},
|
|
20118
20419
|
children: [
|
|
20119
|
-
/* @__PURE__ */ (0,
|
|
20120
|
-
/* @__PURE__ */ (0,
|
|
20121
|
-
error && /* @__PURE__ */ (0,
|
|
20420
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(VideoUrlInput, { value: videoId, onCommit: onSetVideoId }),
|
|
20421
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Pill, { label: "Remove video", onClick: onRemove, disabled: !videoId }),
|
|
20422
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { color: "#FCA5A5", fontSize: 11, maxWidth: 220, textAlign: "center" }, children: error })
|
|
20122
20423
|
]
|
|
20123
20424
|
}
|
|
20124
20425
|
);
|
|
@@ -20238,8 +20539,8 @@ function AiVideoOverlay({
|
|
|
20238
20539
|
const activeBlockRect = useLiveBlockRect(active);
|
|
20239
20540
|
const TOOLBAR_APPROX_H = 90;
|
|
20240
20541
|
const toolbarState = activeBlockRect && activeBlockRect.top < TOOLBAR_APPROX_H ? "active-bottom" : "active-top";
|
|
20241
|
-
return /* @__PURE__ */ (0,
|
|
20242
|
-
hoverHandleRect && hover && /* @__PURE__ */ (0,
|
|
20542
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
20543
|
+
hoverHandleRect && hover && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20243
20544
|
"button",
|
|
20244
20545
|
{
|
|
20245
20546
|
type: "button",
|
|
@@ -20267,15 +20568,15 @@ function AiVideoOverlay({
|
|
|
20267
20568
|
fontSize: 14,
|
|
20268
20569
|
fontWeight: 700
|
|
20269
20570
|
},
|
|
20270
|
-
children: /* @__PURE__ */ (0,
|
|
20571
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.Star, { size: 14, style: { pointerEvents: "none" } })
|
|
20271
20572
|
}
|
|
20272
20573
|
),
|
|
20273
|
-
activeBlockRect && active && activeEntry && /* @__PURE__ */ (0,
|
|
20574
|
+
activeBlockRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20274
20575
|
ItemInteractionLayer,
|
|
20275
20576
|
{
|
|
20276
20577
|
rect: activeBlockRect,
|
|
20277
20578
|
state: toolbarState,
|
|
20278
|
-
toolbar: /* @__PURE__ */ (0,
|
|
20579
|
+
toolbar: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20279
20580
|
VideoToolbar,
|
|
20280
20581
|
{
|
|
20281
20582
|
videoId: videoIdAt(activeEntry.tree, active.path),
|
|
@@ -20299,7 +20600,7 @@ function AiVideoOverlay({
|
|
|
20299
20600
|
|
|
20300
20601
|
// src/ui/ai-section/AiFadeCarouselOverlay.tsx
|
|
20301
20602
|
var import_react13 = require("react");
|
|
20302
|
-
var
|
|
20603
|
+
var import_lucide_react12 = require("lucide-react");
|
|
20303
20604
|
|
|
20304
20605
|
// src/lib/ai-carousel-tree.ts
|
|
20305
20606
|
function isCarouselBlock(node) {
|
|
@@ -20350,10 +20651,10 @@ function setCarouselAutoplay(tree, on) {
|
|
|
20350
20651
|
}
|
|
20351
20652
|
|
|
20352
20653
|
// src/ui/ai-section/AiFadeCarouselOverlay.tsx
|
|
20353
|
-
var
|
|
20654
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
20354
20655
|
var PRIMARY6 = "#0885FE";
|
|
20355
|
-
var
|
|
20356
|
-
var
|
|
20656
|
+
var OHW_BLUE2 = `var(--ohw-primary, ${PRIMARY6})`;
|
|
20657
|
+
var OHW_BLUE_DARK2 = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY6}) 60%, #000000)`;
|
|
20357
20658
|
function findCarouselItemElement(sectionId, index) {
|
|
20358
20659
|
const sectionEl = findByInstanceId(sectionId);
|
|
20359
20660
|
if (!sectionEl) return null;
|
|
@@ -20432,8 +20733,8 @@ function requestAssetPick2(postToParent2) {
|
|
|
20432
20733
|
postToParent2({ type: "ow:asset-pick", id });
|
|
20433
20734
|
});
|
|
20434
20735
|
}
|
|
20435
|
-
function
|
|
20436
|
-
return /* @__PURE__ */ (0,
|
|
20736
|
+
function Pill2({ label, onClick, disabled }) {
|
|
20737
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20437
20738
|
"button",
|
|
20438
20739
|
{
|
|
20439
20740
|
type: "button",
|
|
@@ -20449,7 +20750,7 @@ function Pill3({ label, onClick, disabled }) {
|
|
|
20449
20750
|
border: "none",
|
|
20450
20751
|
cursor: disabled ? "default" : "pointer",
|
|
20451
20752
|
background: "#ffffff",
|
|
20452
|
-
color:
|
|
20753
|
+
color: OHW_BLUE_DARK2,
|
|
20453
20754
|
opacity: disabled ? 0.4 : 1,
|
|
20454
20755
|
fontSize: 12,
|
|
20455
20756
|
lineHeight: "16px",
|
|
@@ -20467,7 +20768,7 @@ function TogglePill({
|
|
|
20467
20768
|
onToggle,
|
|
20468
20769
|
disabled
|
|
20469
20770
|
}) {
|
|
20470
|
-
return /* @__PURE__ */ (0,
|
|
20771
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
20471
20772
|
"button",
|
|
20472
20773
|
{
|
|
20473
20774
|
type: "button",
|
|
@@ -20486,7 +20787,7 @@ function TogglePill({
|
|
|
20486
20787
|
border: "none",
|
|
20487
20788
|
cursor: disabled ? "default" : "pointer",
|
|
20488
20789
|
background: "#ffffff",
|
|
20489
|
-
color:
|
|
20790
|
+
color: OHW_BLUE_DARK2,
|
|
20490
20791
|
opacity: disabled ? 0.4 : 1,
|
|
20491
20792
|
fontSize: 12,
|
|
20492
20793
|
lineHeight: "16px",
|
|
@@ -20496,7 +20797,7 @@ function TogglePill({
|
|
|
20496
20797
|
},
|
|
20497
20798
|
children: [
|
|
20498
20799
|
label,
|
|
20499
|
-
/* @__PURE__ */ (0,
|
|
20800
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20500
20801
|
"span",
|
|
20501
20802
|
{
|
|
20502
20803
|
"aria-hidden": true,
|
|
@@ -20509,10 +20810,10 @@ function TogglePill({
|
|
|
20509
20810
|
// Off is a grey track, not a washed-out blue: the pill's own white background already
|
|
20510
20811
|
// carries the brand colour in the text, and a pale blue track next to it read as
|
|
20511
20812
|
// "disabled control" rather than "switch that is off".
|
|
20512
|
-
background: on ?
|
|
20813
|
+
background: on ? OHW_BLUE_DARK2 : "#CBD5E1",
|
|
20513
20814
|
transition: "background 120ms ease"
|
|
20514
20815
|
},
|
|
20515
|
-
children: /* @__PURE__ */ (0,
|
|
20816
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20516
20817
|
"span",
|
|
20517
20818
|
{
|
|
20518
20819
|
style: {
|
|
@@ -20541,7 +20842,7 @@ function CarouselSlideToolbar({
|
|
|
20541
20842
|
onChangeImage,
|
|
20542
20843
|
onToggleAutoplay
|
|
20543
20844
|
}) {
|
|
20544
|
-
return /* @__PURE__ */ (0,
|
|
20845
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
20545
20846
|
"div",
|
|
20546
20847
|
{
|
|
20547
20848
|
"data-ohw-bridge": "",
|
|
@@ -20552,7 +20853,7 @@ function CarouselSlideToolbar({
|
|
|
20552
20853
|
flexDirection: "column",
|
|
20553
20854
|
gap: 6,
|
|
20554
20855
|
alignItems: "center",
|
|
20555
|
-
background:
|
|
20856
|
+
background: OHW_BLUE2,
|
|
20556
20857
|
padding: 8,
|
|
20557
20858
|
borderRadius: 12,
|
|
20558
20859
|
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
@@ -20564,11 +20865,11 @@ function CarouselSlideToolbar({
|
|
|
20564
20865
|
pointerEvents: pending ? "none" : "auto"
|
|
20565
20866
|
},
|
|
20566
20867
|
children: [
|
|
20567
|
-
/* @__PURE__ */ (0,
|
|
20568
|
-
/* @__PURE__ */ (0,
|
|
20569
|
-
/* @__PURE__ */ (0,
|
|
20868
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { display: "flex", gap: 6, alignItems: "center" }, children: [
|
|
20869
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Pill2, { label: "Change Image", onClick: onChangeImage }),
|
|
20870
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(TogglePill, { label: "Autoplay", on: autoplay, onToggle: onToggleAutoplay })
|
|
20570
20871
|
] }),
|
|
20571
|
-
error && /* @__PURE__ */ (0,
|
|
20872
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { color: "#FCA5A5", fontSize: 11, maxWidth: 220, textAlign: "center" }, children: error })
|
|
20572
20873
|
]
|
|
20573
20874
|
}
|
|
20574
20875
|
);
|
|
@@ -20708,8 +21009,8 @@ function AiFadeCarouselOverlay({
|
|
|
20708
21009
|
const activeItemRect = useLiveItemRect2(active);
|
|
20709
21010
|
const TOOLBAR_APPROX_H = 90;
|
|
20710
21011
|
const toolbarState = activeItemRect && activeItemRect.top < TOOLBAR_APPROX_H ? "active-bottom" : "active-top";
|
|
20711
|
-
return /* @__PURE__ */ (0,
|
|
20712
|
-
hoverHandleRect && hover && /* @__PURE__ */ (0,
|
|
21012
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
21013
|
+
hoverHandleRect && hover && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20713
21014
|
"button",
|
|
20714
21015
|
{
|
|
20715
21016
|
type: "button",
|
|
@@ -20738,10 +21039,10 @@ function AiFadeCarouselOverlay({
|
|
|
20738
21039
|
fontSize: 14,
|
|
20739
21040
|
fontWeight: 700
|
|
20740
21041
|
},
|
|
20741
|
-
children: /* @__PURE__ */ (0,
|
|
21042
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react12.Star, { size: 14, style: { pointerEvents: "none" } })
|
|
20742
21043
|
}
|
|
20743
21044
|
),
|
|
20744
|
-
swapping && /* @__PURE__ */ (0,
|
|
21045
|
+
swapping && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20745
21046
|
"div",
|
|
20746
21047
|
{
|
|
20747
21048
|
ref: skeletonRef,
|
|
@@ -20759,15 +21060,15 @@ function AiFadeCarouselOverlay({
|
|
|
20759
21060
|
zIndex: 2147483646,
|
|
20760
21061
|
pointerEvents: "none"
|
|
20761
21062
|
},
|
|
20762
|
-
children: /* @__PURE__ */ (0,
|
|
21063
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("style", { children: MEDIA_SKELETON_CSS })
|
|
20763
21064
|
}
|
|
20764
21065
|
),
|
|
20765
|
-
activeItemRect && active && activeEntry && /* @__PURE__ */ (0,
|
|
21066
|
+
activeItemRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20766
21067
|
ItemInteractionLayer,
|
|
20767
21068
|
{
|
|
20768
21069
|
rect: activeItemRect,
|
|
20769
21070
|
state: toolbarState,
|
|
20770
|
-
toolbar: /* @__PURE__ */ (0,
|
|
21071
|
+
toolbar: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20771
21072
|
CarouselSlideToolbar,
|
|
20772
21073
|
{
|
|
20773
21074
|
pending,
|
|
@@ -20985,113 +21286,6 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
|
|
|
20985
21286
|
// src/ui/link-modal/LinkPopover.tsx
|
|
20986
21287
|
var import_react17 = require("react");
|
|
20987
21288
|
|
|
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
21289
|
// src/ui/link-modal/LinkEditorPanel.tsx
|
|
21096
21290
|
var import_lucide_react16 = require("lucide-react");
|
|
21097
21291
|
|
|
@@ -22195,6 +22389,7 @@ function shouldUseDevFixtures() {
|
|
|
22195
22389
|
function getLogoElement(el) {
|
|
22196
22390
|
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
22197
22391
|
if (marked) return marked;
|
|
22392
|
+
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
22198
22393
|
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
22199
22394
|
if (!root) return null;
|
|
22200
22395
|
const anchor = el.closest("a");
|
|
@@ -23889,6 +24084,102 @@ function deleteSelectedNavFooterItem(deps) {
|
|
|
23889
24084
|
return false;
|
|
23890
24085
|
}
|
|
23891
24086
|
|
|
24087
|
+
// src/lib/nav-page-sync.ts
|
|
24088
|
+
function labelKeyFor(hrefKey) {
|
|
24089
|
+
return hrefKey.replace(/-href$/, "-label");
|
|
24090
|
+
}
|
|
24091
|
+
function isPageLinkKey(key) {
|
|
24092
|
+
return isNavbarHrefKey(key) || isFooterHrefKey(key);
|
|
24093
|
+
}
|
|
24094
|
+
function currentHref(key, anchor, content) {
|
|
24095
|
+
const stored = content[key];
|
|
24096
|
+
if (typeof stored === "string" && stored.length > 0) return stored;
|
|
24097
|
+
return anchor.getAttribute("href") ?? "";
|
|
24098
|
+
}
|
|
24099
|
+
function normalizePath2(value) {
|
|
24100
|
+
if (value.length > 1 && value.endsWith("/")) return value.slice(0, -1);
|
|
24101
|
+
return value;
|
|
24102
|
+
}
|
|
24103
|
+
function pointsAt(href, path) {
|
|
24104
|
+
const normalized = normalizePath2(href);
|
|
24105
|
+
const target = normalizePath2(path);
|
|
24106
|
+
if (normalized === target) return true;
|
|
24107
|
+
return (normalized.startsWith(`${target}#`) || normalized.startsWith(`${target}?`)) && target !== "/";
|
|
24108
|
+
}
|
|
24109
|
+
function retargetHref(href, oldPath, newPath) {
|
|
24110
|
+
const normalized = normalizePath2(href);
|
|
24111
|
+
const target = normalizePath2(oldPath);
|
|
24112
|
+
if (normalized === target) return newPath;
|
|
24113
|
+
return `${newPath}${normalized.slice(target.length)}`;
|
|
24114
|
+
}
|
|
24115
|
+
function setLabelText(key, text) {
|
|
24116
|
+
document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`).forEach((el) => {
|
|
24117
|
+
el.textContent = text;
|
|
24118
|
+
});
|
|
24119
|
+
}
|
|
24120
|
+
function commit(delta, deps) {
|
|
24121
|
+
if (Object.keys(delta).length === 0) return;
|
|
24122
|
+
deps.setEditContent({ ...deps.getEditContent(), ...delta });
|
|
24123
|
+
deps.postToParent({
|
|
24124
|
+
type: "ow:change",
|
|
24125
|
+
nodes: Object.entries(delta).map(([key, text]) => ({ key, text }))
|
|
24126
|
+
});
|
|
24127
|
+
}
|
|
24128
|
+
function navLinksTo(path, content) {
|
|
24129
|
+
return Array.from(document.querySelectorAll("[data-ohw-href-key]")).filter((anchor) => {
|
|
24130
|
+
const key = anchor.getAttribute("data-ohw-href-key");
|
|
24131
|
+
return isNavbarHrefKey(key) && pointsAt(currentHref(key, anchor, content), path);
|
|
24132
|
+
}).map((anchor) => anchor.getAttribute("data-ohw-href-key"));
|
|
24133
|
+
}
|
|
24134
|
+
function addNavLinkForPage(page, deps) {
|
|
24135
|
+
const content = deps.getEditContent();
|
|
24136
|
+
if (navLinksTo(page.path, content).length > 0) return false;
|
|
24137
|
+
const roots = listNavbarRootItems();
|
|
24138
|
+
const afterAnchor = roots[roots.length - 1] ?? null;
|
|
24139
|
+
let inserted;
|
|
24140
|
+
try {
|
|
24141
|
+
inserted = insertNavbarItem(page.path, page.title, afterAnchor);
|
|
24142
|
+
} catch {
|
|
24143
|
+
return false;
|
|
24144
|
+
}
|
|
24145
|
+
const { hrefKey, labelKey, index } = inserted;
|
|
24146
|
+
deps.applyLinkByKey(hrefKey, page.path);
|
|
24147
|
+
setLabelText(labelKey, page.title);
|
|
24148
|
+
commit(
|
|
24149
|
+
{
|
|
24150
|
+
[hrefKey]: page.path,
|
|
24151
|
+
[labelKey]: page.title,
|
|
24152
|
+
[NAV_COUNT_KEY]: String(index + 1),
|
|
24153
|
+
[NAV_ORDER_KEY]: getNavbarOrderJson()
|
|
24154
|
+
},
|
|
24155
|
+
deps
|
|
24156
|
+
);
|
|
24157
|
+
return true;
|
|
24158
|
+
}
|
|
24159
|
+
function retargetPageLinks(change, deps) {
|
|
24160
|
+
const { oldPath, newPath, oldTitle, newTitle } = change;
|
|
24161
|
+
if (!oldPath || !newPath || normalizePath2(oldPath) === normalizePath2(newPath)) return 0;
|
|
24162
|
+
const content = deps.getEditContent();
|
|
24163
|
+
const delta = {};
|
|
24164
|
+
for (const anchor of Array.from(document.querySelectorAll("[data-ohw-href-key]"))) {
|
|
24165
|
+
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
24166
|
+
if (!isPageLinkKey(hrefKey)) continue;
|
|
24167
|
+
const href = currentHref(hrefKey, anchor, content);
|
|
24168
|
+
if (!pointsAt(href, oldPath)) continue;
|
|
24169
|
+
const nextHref = retargetHref(href, oldPath, newPath);
|
|
24170
|
+
deps.applyLinkByKey(hrefKey, nextHref);
|
|
24171
|
+
delta[hrefKey] = nextHref;
|
|
24172
|
+
if (!oldTitle || !newTitle) continue;
|
|
24173
|
+
const labelKey = labelKeyFor(hrefKey);
|
|
24174
|
+
const label = content[labelKey] ?? anchor.querySelector('[data-ohw-editable="text"]')?.textContent ?? "";
|
|
24175
|
+
if (label.trim() !== oldTitle) continue;
|
|
24176
|
+
setLabelText(labelKey, newTitle);
|
|
24177
|
+
delta[labelKey] = newTitle;
|
|
24178
|
+
}
|
|
24179
|
+
commit(delta, deps);
|
|
24180
|
+
return Object.keys(delta).filter((key) => key.endsWith("-href")).length;
|
|
24181
|
+
}
|
|
24182
|
+
|
|
23892
24183
|
// src/ui/navbar-container-chrome.tsx
|
|
23893
24184
|
var import_lucide_react21 = require("lucide-react");
|
|
23894
24185
|
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
@@ -24031,6 +24322,7 @@ function applyEditableImageSrc(img, url) {
|
|
|
24031
24322
|
img.removeAttribute("srcset");
|
|
24032
24323
|
img.removeAttribute("sizes");
|
|
24033
24324
|
if (img.loading === "lazy") img.loading = "eager";
|
|
24325
|
+
releaseTemplateLogoIfReplaced(img, url);
|
|
24034
24326
|
img.src = url;
|
|
24035
24327
|
}
|
|
24036
24328
|
function fadeInBgImage(el, url, onReady) {
|
|
@@ -24775,7 +25067,7 @@ function getNavigationSelectionParent(el) {
|
|
|
24775
25067
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
24776
25068
|
return resolveFooterLinksContainerFrom(el);
|
|
24777
25069
|
}
|
|
24778
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
|
|
25070
|
+
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
25071
|
return getNavigationRoot(el);
|
|
24780
25072
|
}
|
|
24781
25073
|
return null;
|
|
@@ -24997,7 +25289,6 @@ var ICONS = {
|
|
|
24997
25289
|
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
25290
|
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
25291
|
};
|
|
25000
|
-
var HEIGHT_SETTLE_DELAYS = [150, 400, 800];
|
|
25001
25292
|
var SELECTION_CHROME_GAP2 = 4;
|
|
25002
25293
|
var TOOLBAR_STROKE_GAP2 = 4;
|
|
25003
25294
|
var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
|
|
@@ -25095,7 +25386,7 @@ function applyVisibleViewport(el, parentScroll) {
|
|
|
25095
25386
|
el.style.top = `${top}px`;
|
|
25096
25387
|
el.style.height = `${height}px`;
|
|
25097
25388
|
}
|
|
25098
|
-
var
|
|
25389
|
+
var TOOLBAR_EDGE_MARGIN4 = 4;
|
|
25099
25390
|
function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
25100
25391
|
const isAbove = transform.includes("translateY(-100%)");
|
|
25101
25392
|
let visualTop = isAbove ? top - approxH : top;
|
|
@@ -25122,8 +25413,8 @@ function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
|
25122
25413
|
function clampToolbarLeft(centerX, toolbarWidth) {
|
|
25123
25414
|
const half = toolbarWidth / 2;
|
|
25124
25415
|
return Math.max(
|
|
25125
|
-
|
|
25126
|
-
Math.min(centerX, window.innerWidth -
|
|
25416
|
+
TOOLBAR_EDGE_MARGIN4 + half,
|
|
25417
|
+
Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN4 - half)
|
|
25127
25418
|
);
|
|
25128
25419
|
}
|
|
25129
25420
|
function calcToolbarPos(rect, parentScroll, toolbarW = 306) {
|
|
@@ -26003,21 +26294,6 @@ function OhhwellsBridge() {
|
|
|
26003
26294
|
const [isItemDragging, setIsItemDragging] = (0, import_react21.useState)(false);
|
|
26004
26295
|
const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react21.useState)(false);
|
|
26005
26296
|
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
26297
|
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react21.useState)(null);
|
|
26022
26298
|
const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react21.useState)(null);
|
|
26023
26299
|
const footerDragRef = (0, import_react21.useRef)(null);
|
|
@@ -26043,6 +26319,21 @@ function OhhwellsBridge() {
|
|
|
26043
26319
|
const stylesRef = (0, import_react21.useRef)("");
|
|
26044
26320
|
const appliedDrawerRef = (0, import_react21.useRef)(null);
|
|
26045
26321
|
const pendingDeleteUndoRef = (0, import_react21.useRef)(null);
|
|
26322
|
+
const [floatingPanel, setFloatingPanel] = (0, import_react21.useState)(null);
|
|
26323
|
+
const floatingPanelOpenRef = (0, import_react21.useRef)(false);
|
|
26324
|
+
const floatingPanelRef = (0, import_react21.useRef)(null);
|
|
26325
|
+
floatingPanelRef.current = floatingPanel;
|
|
26326
|
+
const setFloatingPanelRef = (0, import_react21.useRef)(setFloatingPanel);
|
|
26327
|
+
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react21.useState)(null);
|
|
26328
|
+
const buttonCollectionDragRef = (0, import_react21.useRef)(null);
|
|
26329
|
+
const buttonDropInsertIndexRef = (0, import_react21.useRef)(null);
|
|
26330
|
+
const [buttonDropSlots, setButtonDropSlots] = (0, import_react21.useState)([]);
|
|
26331
|
+
const [activeButtonDropIndex, setActiveButtonDropIndex] = (0, import_react21.useState)(null);
|
|
26332
|
+
const buttonPointerDragRef = (0, import_react21.useRef)(null);
|
|
26333
|
+
const [buttonStyleTick, setButtonStyleTick] = (0, import_react21.useState)(0);
|
|
26334
|
+
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react21.useState)(null);
|
|
26335
|
+
const [editorViewport, setEditorViewport] = (0, import_react21.useState)("desktop");
|
|
26336
|
+
const [parentScrollSnap, setParentScrollSnap] = (0, import_react21.useState)(null);
|
|
26046
26337
|
const [sitePages, setSitePages] = (0, import_react21.useState)([]);
|
|
26047
26338
|
const collectionItemsRef = (0, import_react21.useRef)(/* @__PURE__ */ new Map());
|
|
26048
26339
|
const [sectionsByPath, setSectionsByPath] = (0, import_react21.useState)({});
|
|
@@ -26052,7 +26343,18 @@ function OhhwellsBridge() {
|
|
|
26052
26343
|
const linkPopoverOpenRef = (0, import_react21.useRef)(false);
|
|
26053
26344
|
const linkPopoverGraceUntilRef = (0, import_react21.useRef)(0);
|
|
26054
26345
|
setLinkPopoverRef.current = setLinkPopover;
|
|
26346
|
+
setFloatingPanelRef.current = setFloatingPanel;
|
|
26055
26347
|
linkPopoverSessionRef.current = linkPopover;
|
|
26348
|
+
floatingPanelOpenRef.current = Boolean(floatingPanel);
|
|
26349
|
+
(0, import_react21.useEffect)(() => {
|
|
26350
|
+
const syncViewport = () => {
|
|
26351
|
+
const next = window.innerWidth <= 480 ? "mobile" : "desktop";
|
|
26352
|
+
setEditorViewport((prev) => prev === next ? prev : next);
|
|
26353
|
+
};
|
|
26354
|
+
syncViewport();
|
|
26355
|
+
window.addEventListener("resize", syncViewport);
|
|
26356
|
+
return () => window.removeEventListener("resize", syncViewport);
|
|
26357
|
+
}, []);
|
|
26056
26358
|
(0, import_react21.useEffect)(() => {
|
|
26057
26359
|
setSectionOrderPersistHandler((entries) => {
|
|
26058
26360
|
const currentPath = window.location.pathname;
|
|
@@ -26201,6 +26503,43 @@ function OhhwellsBridge() {
|
|
|
26201
26503
|
if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
|
|
26202
26504
|
return () => window.removeEventListener("message", onSitePages);
|
|
26203
26505
|
}, [isEditMode, postToParent2]);
|
|
26506
|
+
(0, import_react21.useEffect)(() => {
|
|
26507
|
+
if (!isEditMode) return;
|
|
26508
|
+
const deps = {
|
|
26509
|
+
getEditContent: () => editContentRef.current,
|
|
26510
|
+
setEditContent: (next) => {
|
|
26511
|
+
editContentRef.current = next;
|
|
26512
|
+
},
|
|
26513
|
+
applyLinkByKey,
|
|
26514
|
+
postToParent: postToParent2
|
|
26515
|
+
};
|
|
26516
|
+
const onPageMessage = (e) => {
|
|
26517
|
+
if (e.data?.type === "ow:page-created") {
|
|
26518
|
+
const { path, title } = e.data;
|
|
26519
|
+
if (typeof path !== "string" || !path) return;
|
|
26520
|
+
if (addNavLinkForPage({ path, title: typeof title === "string" && title ? title : path }, deps)) {
|
|
26521
|
+
enforceLinkHrefs();
|
|
26522
|
+
}
|
|
26523
|
+
return;
|
|
26524
|
+
}
|
|
26525
|
+
if (e.data?.type === "ow:page-renamed") {
|
|
26526
|
+
const { oldPath, newPath, oldTitle, newTitle } = e.data;
|
|
26527
|
+
if (typeof oldPath !== "string" || typeof newPath !== "string") return;
|
|
26528
|
+
const moved = retargetPageLinks(
|
|
26529
|
+
{
|
|
26530
|
+
oldPath,
|
|
26531
|
+
newPath,
|
|
26532
|
+
oldTitle: typeof oldTitle === "string" ? oldTitle : void 0,
|
|
26533
|
+
newTitle: typeof newTitle === "string" ? newTitle : void 0
|
|
26534
|
+
},
|
|
26535
|
+
deps
|
|
26536
|
+
);
|
|
26537
|
+
if (moved > 0) enforceLinkHrefs();
|
|
26538
|
+
}
|
|
26539
|
+
};
|
|
26540
|
+
window.addEventListener("message", onPageMessage);
|
|
26541
|
+
return () => window.removeEventListener("message", onPageMessage);
|
|
26542
|
+
}, [isEditMode, postToParent2]);
|
|
26204
26543
|
(0, import_react21.useEffect)(() => {
|
|
26205
26544
|
if (!isEditMode || shouldUseDevFixtures()) return;
|
|
26206
26545
|
void loadAllSectionsManifest().then((manifest) => {
|
|
@@ -27749,6 +28088,7 @@ function OhhwellsBridge() {
|
|
|
27749
28088
|
applyAiFooterFromContent(content);
|
|
27750
28089
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
27751
28090
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
28091
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
27752
28092
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
27753
28093
|
}
|
|
27754
28094
|
applyBrandChrome(content);
|
|
@@ -27759,12 +28099,12 @@ function OhhwellsBridge() {
|
|
|
27759
28099
|
if (key === "__ohw_sections") continue;
|
|
27760
28100
|
if (key === AI_SECTIONS_KEY) continue;
|
|
27761
28101
|
if (key === AI_FOOTER_KEY) continue;
|
|
28102
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
28103
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27762
28104
|
if (key === BRAND_KIT_KEY) continue;
|
|
27763
28105
|
if (key === STYLE_STORE_KEY) continue;
|
|
27764
28106
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
27765
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
27766
28107
|
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
27767
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27768
28108
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
27769
28109
|
continue;
|
|
27770
28110
|
}
|
|
@@ -27995,17 +28335,18 @@ function OhhwellsBridge() {
|
|
|
27995
28335
|
}
|
|
27996
28336
|
applyAiFooterFromContent(content);
|
|
27997
28337
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
28338
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
27998
28339
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
27999
28340
|
}
|
|
28000
28341
|
for (const [key, val] of Object.entries(content)) {
|
|
28001
28342
|
if (key === "__ohw_sections") continue;
|
|
28002
28343
|
if (key === AI_SECTIONS_KEY) continue;
|
|
28003
28344
|
if (key === AI_FOOTER_KEY) continue;
|
|
28345
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
28346
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
28004
28347
|
if (key === BRAND_KIT_KEY) continue;
|
|
28005
28348
|
if (key === STYLE_STORE_KEY) continue;
|
|
28006
28349
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
28007
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
28008
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
28009
28350
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
28010
28351
|
continue;
|
|
28011
28352
|
}
|
|
@@ -28272,26 +28613,11 @@ function OhhwellsBridge() {
|
|
|
28272
28613
|
const t2 = setTimeout(measure, 500);
|
|
28273
28614
|
const ro = new ResizeObserver(schedule);
|
|
28274
28615
|
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
28616
|
return () => {
|
|
28289
28617
|
clearTimeout(t1);
|
|
28290
28618
|
clearTimeout(t2);
|
|
28291
28619
|
if (raf != null) cancelAnimationFrame(raf);
|
|
28292
28620
|
ro.disconnect();
|
|
28293
|
-
clearResizeTimers();
|
|
28294
|
-
window.removeEventListener("resize", handleResize);
|
|
28295
28621
|
};
|
|
28296
28622
|
}, [pathname, isEditMode, postToParent2]);
|
|
28297
28623
|
(0, import_react21.useEffect)(() => {
|
|
@@ -28588,6 +28914,13 @@ function OhhwellsBridge() {
|
|
|
28588
28914
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
28589
28915
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
28590
28916
|
if (isInsideLinkEditor(target)) return;
|
|
28917
|
+
if (isInsideFloatingPanel(target)) return;
|
|
28918
|
+
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
28919
|
+
if (target.closest(
|
|
28920
|
+
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
28921
|
+
)) {
|
|
28922
|
+
return;
|
|
28923
|
+
}
|
|
28591
28924
|
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
28592
28925
|
clearMediaSelectionRef.current();
|
|
28593
28926
|
}
|
|
@@ -28611,8 +28944,6 @@ function OhhwellsBridge() {
|
|
|
28611
28944
|
return;
|
|
28612
28945
|
}
|
|
28613
28946
|
}
|
|
28614
|
-
if (isInsideFloatingPanel(target)) return;
|
|
28615
|
-
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
28616
28947
|
const collectionItem = matchCollectionItemClick(target, collectionItemsRef.current);
|
|
28617
28948
|
if (collectionItem) {
|
|
28618
28949
|
e.preventDefault();
|
|
@@ -28624,11 +28955,6 @@ function OhhwellsBridge() {
|
|
|
28624
28955
|
});
|
|
28625
28956
|
return;
|
|
28626
28957
|
}
|
|
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
28958
|
{
|
|
28633
28959
|
const formEl = getFormElement(target);
|
|
28634
28960
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
@@ -28782,9 +29108,13 @@ function OhhwellsBridge() {
|
|
|
28782
29108
|
if (isIconEditable(editable) && !getSocialItem(editable)) {
|
|
28783
29109
|
e.preventDefault();
|
|
28784
29110
|
e.stopPropagation();
|
|
28785
|
-
selectIconElementRef.current(editable);
|
|
28786
29111
|
const aiIcon = editable.hasAttribute("data-ai-icon");
|
|
28787
29112
|
const featureIcon = aiIcon && /\.features\.\d+\.icon$/.test(editable.dataset.ohwKey ?? "");
|
|
29113
|
+
if (aiIcon) {
|
|
29114
|
+
aiSectionApiRef.current?.selectFromElement(editable);
|
|
29115
|
+
} else {
|
|
29116
|
+
selectIconElementRef.current(editable);
|
|
29117
|
+
}
|
|
28788
29118
|
postToParentRef.current({
|
|
28789
29119
|
type: "ow:icon-pick",
|
|
28790
29120
|
key: editable.dataset.ohwKey ?? "",
|
|
@@ -29012,6 +29342,9 @@ function OhhwellsBridge() {
|
|
|
29012
29342
|
setHoveredItemRect(null);
|
|
29013
29343
|
hoveredNavContainerRef.current = null;
|
|
29014
29344
|
setHoveredNavContainerRect(null);
|
|
29345
|
+
siblingHintElRef.current = null;
|
|
29346
|
+
setSiblingHintRect(null);
|
|
29347
|
+
setSiblingHintRects([]);
|
|
29015
29348
|
return;
|
|
29016
29349
|
}
|
|
29017
29350
|
{
|
|
@@ -29132,7 +29465,6 @@ function OhhwellsBridge() {
|
|
|
29132
29465
|
hoveredNavContainerRef.current = null;
|
|
29133
29466
|
setHoveredNavContainerRect(null);
|
|
29134
29467
|
hoveredItemElRef.current = editable;
|
|
29135
|
-
setHoveredItemRect(isSelectedForHoverRef.current(editable) ? null : editable.getBoundingClientRect());
|
|
29136
29468
|
}
|
|
29137
29469
|
}
|
|
29138
29470
|
}
|
|
@@ -29842,7 +30174,11 @@ function OhhwellsBridge() {
|
|
|
29842
30174
|
};
|
|
29843
30175
|
const handleMouseMove = (e) => {
|
|
29844
30176
|
const { clientX, clientY } = e;
|
|
29845
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
30177
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
30178
|
+
dismissImageHover();
|
|
30179
|
+
clearImageHover();
|
|
30180
|
+
return;
|
|
30181
|
+
}
|
|
29846
30182
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) {
|
|
29847
30183
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
29848
30184
|
formHoverElRef.current = null;
|
|
@@ -29871,7 +30207,12 @@ function OhhwellsBridge() {
|
|
|
29871
30207
|
setHoveredItemRect(null);
|
|
29872
30208
|
hoveredNavContainerRef.current = null;
|
|
29873
30209
|
setHoveredNavContainerRect(null);
|
|
30210
|
+
siblingHintElRef.current = null;
|
|
30211
|
+
setSiblingHintRect(null);
|
|
30212
|
+
setSiblingHintRects([]);
|
|
29874
30213
|
dismissImageHover();
|
|
30214
|
+
clearImageHover();
|
|
30215
|
+
setSectionGap(null);
|
|
29875
30216
|
return;
|
|
29876
30217
|
}
|
|
29877
30218
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
@@ -29883,7 +30224,11 @@ function OhhwellsBridge() {
|
|
|
29883
30224
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
29884
30225
|
const { clientX, clientY } = e.data;
|
|
29885
30226
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
29886
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
30227
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
30228
|
+
dismissImageHover();
|
|
30229
|
+
clearImageHover();
|
|
30230
|
+
return;
|
|
30231
|
+
}
|
|
29887
30232
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) return;
|
|
29888
30233
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
29889
30234
|
probeSectionGapAt(clientX, clientY);
|
|
@@ -30263,6 +30608,7 @@ function OhhwellsBridge() {
|
|
|
30263
30608
|
applyAiFooterFromContent(content);
|
|
30264
30609
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
30265
30610
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
30611
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
30266
30612
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
30267
30613
|
}
|
|
30268
30614
|
applyBrandChrome(content);
|
|
@@ -30277,12 +30623,12 @@ function OhhwellsBridge() {
|
|
|
30277
30623
|
}
|
|
30278
30624
|
if (key === AI_SECTIONS_KEY) continue;
|
|
30279
30625
|
if (key === AI_FOOTER_KEY) continue;
|
|
30626
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
30627
|
+
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
30280
30628
|
if (key === BRAND_KIT_KEY) continue;
|
|
30281
30629
|
if (key === STYLE_STORE_KEY) continue;
|
|
30282
30630
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
30283
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
30284
30631
|
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
30632
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
30287
30633
|
continue;
|
|
30288
30634
|
}
|
|
@@ -30918,6 +31264,12 @@ function OhhwellsBridge() {
|
|
|
30918
31264
|
closeLinkPopoverRef.current();
|
|
30919
31265
|
return;
|
|
30920
31266
|
}
|
|
31267
|
+
if (floatingPanelOpenRef.current) {
|
|
31268
|
+
setFloatingPanelRef.current(null);
|
|
31269
|
+
deselectRef.current();
|
|
31270
|
+
deactivateRef.current();
|
|
31271
|
+
return;
|
|
31272
|
+
}
|
|
30921
31273
|
deselectRef.current();
|
|
30922
31274
|
deactivateRef.current();
|
|
30923
31275
|
clearMediaSelectionRef.current();
|
|
@@ -31747,10 +32099,10 @@ function OhhwellsBridge() {
|
|
|
31747
32099
|
window.removeEventListener("message", handleDuplicateSection);
|
|
31748
32100
|
window.removeEventListener("message", handleDeactivate);
|
|
31749
32101
|
window.removeEventListener("message", handleSelectNav);
|
|
31750
|
-
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
31751
32102
|
window.removeEventListener("message", handleToastAction);
|
|
31752
32103
|
window.removeEventListener("message", handleFormCount);
|
|
31753
32104
|
window.removeEventListener("message", handleUiEscape);
|
|
32105
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
31754
32106
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
31755
32107
|
autoSaveTimers.current.clear();
|
|
31756
32108
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
@@ -32044,7 +32396,7 @@ function OhhwellsBridge() {
|
|
|
32044
32396
|
postToParent2({
|
|
32045
32397
|
type: "ow:ready",
|
|
32046
32398
|
version: "1",
|
|
32047
|
-
bridgeVersion: "0.1.
|
|
32399
|
+
bridgeVersion: "0.1.158-next.423",
|
|
32048
32400
|
path: pathname,
|
|
32049
32401
|
nodes: collectEditableNodes(editContentRef.current),
|
|
32050
32402
|
sections
|
|
@@ -33251,6 +33603,7 @@ function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey
|
|
|
33251
33603
|
OhwLoaderSurface,
|
|
33252
33604
|
SITE_OG_IMAGE_KEY,
|
|
33253
33605
|
SchedulingWidget,
|
|
33606
|
+
TEMPLATE_LOGO_ATTR,
|
|
33254
33607
|
Toggle,
|
|
33255
33608
|
ToggleGroup,
|
|
33256
33609
|
ToggleGroupItem,
|
|
@@ -33284,6 +33637,7 @@ function EmptySection({ title, homeHref = "/", eyebrowKey, titleKey, subtitleKey
|
|
|
33284
33637
|
parseAiSectionsState,
|
|
33285
33638
|
parseTarget,
|
|
33286
33639
|
recordOverriddenPaths,
|
|
33640
|
+
releaseTemplateLogoIfReplaced,
|
|
33287
33641
|
removeFooterBlock,
|
|
33288
33642
|
resetOverriddenPathsCache,
|
|
33289
33643
|
resolveFooterCopyright,
|