@ohhwells/bridge 0.1.159 → 0.1.160-next.428
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 +1116 -754
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1157 -779
- package/dist/index.js.map +1 -1
- package/dist/pages.cjs +9 -1
- 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 +9 -1
- package/dist/pages.js.map +1 -1
- package/dist/styles.css +116 -0
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
// src/OhhwellsBridge.tsx
|
|
4
|
-
import React12, { useCallback as useCallback12, useEffect as useEffect17, useLayoutEffect as
|
|
4
|
+
import React12, { useCallback as useCallback12, useEffect as useEffect17, useLayoutEffect as useLayoutEffect7, useRef as useRef14, useState as useState18 } from "react";
|
|
5
5
|
import { createRoot as createRoot3 } from "react-dom/client";
|
|
6
6
|
import { flushSync as flushSync3 } from "react-dom";
|
|
7
7
|
|
|
@@ -1094,21 +1094,21 @@ function chromeFrom(sample) {
|
|
|
1094
1094
|
};
|
|
1095
1095
|
}
|
|
1096
1096
|
function filledPrimary(seed) {
|
|
1097
|
-
const
|
|
1098
|
-
const luminance = relativeLuminance(
|
|
1097
|
+
const paint2 = parseColor(paintColor(seed)) ?? { r: 15, g: 15, b: 15, a: 1 };
|
|
1098
|
+
const luminance = relativeLuminance(paint2);
|
|
1099
1099
|
return {
|
|
1100
|
-
background: toCss({ ...
|
|
1100
|
+
background: toCss({ ...paint2, a: 1 }),
|
|
1101
1101
|
color: luminance > 0.55 ? "rgb(15, 15, 15)" : "rgb(255, 255, 255)",
|
|
1102
1102
|
borderColor: TRANSPARENT,
|
|
1103
1103
|
borderWidth: "0px"
|
|
1104
1104
|
};
|
|
1105
1105
|
}
|
|
1106
1106
|
function generatedSecondary(primary) {
|
|
1107
|
-
const
|
|
1107
|
+
const paint2 = accentColor(primary);
|
|
1108
1108
|
return {
|
|
1109
1109
|
background: TRANSPARENT,
|
|
1110
|
-
color:
|
|
1111
|
-
borderColor:
|
|
1110
|
+
color: paint2,
|
|
1111
|
+
borderColor: paint2,
|
|
1112
1112
|
borderWidth: "1px"
|
|
1113
1113
|
};
|
|
1114
1114
|
}
|
|
@@ -1121,9 +1121,9 @@ function generatedGhost(primary) {
|
|
|
1121
1121
|
};
|
|
1122
1122
|
}
|
|
1123
1123
|
function normalizeOutlineChrome(outline, primary) {
|
|
1124
|
-
const
|
|
1124
|
+
const paint2 = accentColor(primary);
|
|
1125
1125
|
const text = parseColor(outline.color);
|
|
1126
|
-
const paintRgb = parseColor(
|
|
1126
|
+
const paintRgb = parseColor(paint2);
|
|
1127
1127
|
const primaryLabel = parseColor(primary.color);
|
|
1128
1128
|
const matchesOnPrimary = Boolean(text && primaryLabel) && colorKey(outline.color) === colorKey(primary.color);
|
|
1129
1129
|
const textTooLight = text ? relativeLuminance(text) > 0.7 : false;
|
|
@@ -1132,8 +1132,8 @@ function normalizeOutlineChrome(outline, primary) {
|
|
|
1132
1132
|
const hasBorder = parseFloat(outline.borderWidth) > 0;
|
|
1133
1133
|
return {
|
|
1134
1134
|
...outline,
|
|
1135
|
-
color:
|
|
1136
|
-
borderColor: hasBorder ?
|
|
1135
|
+
color: paint2,
|
|
1136
|
+
borderColor: hasBorder ? paint2 : outline.borderColor
|
|
1137
1137
|
};
|
|
1138
1138
|
}
|
|
1139
1139
|
function generateButtonVariants(samples) {
|
|
@@ -6649,6 +6649,21 @@ function pricingCardFeatureCount(tree, index) {
|
|
|
6649
6649
|
const target = findPricingCollection(tree)?.children?.[index];
|
|
6650
6650
|
return target ? pricingFeatureList(target).length : 0;
|
|
6651
6651
|
}
|
|
6652
|
+
function prevailingFeatureIcon(features) {
|
|
6653
|
+
const counts = /* @__PURE__ */ new Map();
|
|
6654
|
+
for (const row of features) {
|
|
6655
|
+
const key = `${row.icon ?? ""}|${row.iconColor ?? ""}`;
|
|
6656
|
+
const entry = counts.get(key) ?? { count: 0, ...row.icon ? { icon: row.icon } : {}, ...row.iconColor ? { iconColor: row.iconColor } : {} };
|
|
6657
|
+
entry.count += 1;
|
|
6658
|
+
counts.set(key, entry);
|
|
6659
|
+
}
|
|
6660
|
+
let best = null;
|
|
6661
|
+
for (const entry of counts.values()) {
|
|
6662
|
+
if (!best || entry.count > best.count) best = entry;
|
|
6663
|
+
}
|
|
6664
|
+
if (!best) return {};
|
|
6665
|
+
return { ...best.icon ? { icon: best.icon } : {}, ...best.iconColor ? { iconColor: best.iconColor } : {} };
|
|
6666
|
+
}
|
|
6652
6667
|
function addPricingCardFeature(tree, index, text) {
|
|
6653
6668
|
return withPricingCollection(tree, (collection) => {
|
|
6654
6669
|
const children = collection.children;
|
|
@@ -6657,7 +6672,7 @@ function addPricingCardFeature(tree, index, text) {
|
|
|
6657
6672
|
const features = pricingFeatureList(target);
|
|
6658
6673
|
if (features.length >= PRICING_FEATURES_MAX) return false;
|
|
6659
6674
|
target.slots = target.slots ?? {};
|
|
6660
|
-
target.slots.features = [...features, { text }];
|
|
6675
|
+
target.slots.features = [...features, { text, ...prevailingFeatureIcon(features) }];
|
|
6661
6676
|
return true;
|
|
6662
6677
|
});
|
|
6663
6678
|
}
|
|
@@ -7269,6 +7284,23 @@ function applyCustomCodeToHead(content) {
|
|
|
7269
7284
|
if (beforeNodes.length > 0) document.head.append(...beforeNodes);
|
|
7270
7285
|
}
|
|
7271
7286
|
|
|
7287
|
+
// src/lib/node-font-size.ts
|
|
7288
|
+
var TEXT_NODE_TYPES = /* @__PURE__ */ new Set(["text", "text/rich", "plain", "link"]);
|
|
7289
|
+
function escapeKey(key) {
|
|
7290
|
+
return typeof CSS !== "undefined" && typeof CSS.escape === "function" ? CSS.escape(key) : key.replace(/["\\]/g, "\\$&");
|
|
7291
|
+
}
|
|
7292
|
+
function measureNodeFontSize(key, type, root) {
|
|
7293
|
+
if (!TEXT_NODE_TYPES.has(type)) return void 0;
|
|
7294
|
+
const el = root.querySelector(`[data-ohw-editable][data-ohw-key="${escapeKey(key)}"]`);
|
|
7295
|
+
if (!el) return void 0;
|
|
7296
|
+
const size = Number.parseFloat(window.getComputedStyle(el).fontSize);
|
|
7297
|
+
return Number.isFinite(size) && size > 0 ? Math.round(size) : void 0;
|
|
7298
|
+
}
|
|
7299
|
+
function withNodeFontSize(node, root) {
|
|
7300
|
+
const fontSize = measureNodeFontSize(node.key, node.type, root);
|
|
7301
|
+
return fontSize === void 0 ? node : { ...node, fontSize };
|
|
7302
|
+
}
|
|
7303
|
+
|
|
7272
7304
|
// src/lib/selectNavContainer.ts
|
|
7273
7305
|
function isOnScreen(el) {
|
|
7274
7306
|
const rect = el.getBoundingClientRect();
|
|
@@ -7284,6 +7316,120 @@ function findSelectableNavContainer(doc = document) {
|
|
|
7284
7316
|
);
|
|
7285
7317
|
}
|
|
7286
7318
|
|
|
7319
|
+
// src/lib/youtube.ts
|
|
7320
|
+
var YOUTUBE_ID_PATTERN = /^[A-Za-z0-9_-]{11}$/;
|
|
7321
|
+
function extractYouTubeId(input) {
|
|
7322
|
+
const trimmed = input.trim();
|
|
7323
|
+
if (!trimmed) return null;
|
|
7324
|
+
if (YOUTUBE_ID_PATTERN.test(trimmed)) return trimmed;
|
|
7325
|
+
let url;
|
|
7326
|
+
try {
|
|
7327
|
+
url = new URL(trimmed);
|
|
7328
|
+
} catch {
|
|
7329
|
+
return null;
|
|
7330
|
+
}
|
|
7331
|
+
const host = url.hostname.replace(/^www\./, "");
|
|
7332
|
+
if (host !== "youtube.com" && host !== "m.youtube.com" && host !== "youtu.be" && host !== "youtube-nocookie.com") {
|
|
7333
|
+
return null;
|
|
7334
|
+
}
|
|
7335
|
+
let candidate = null;
|
|
7336
|
+
if (host === "youtu.be") {
|
|
7337
|
+
candidate = url.pathname.slice(1).split("/")[0] ?? null;
|
|
7338
|
+
} else if (url.pathname === "/watch") {
|
|
7339
|
+
candidate = url.searchParams.get("v");
|
|
7340
|
+
} else {
|
|
7341
|
+
const match = url.pathname.match(/^\/(?:embed|shorts)\/([^/]+)/);
|
|
7342
|
+
candidate = match ? match[1] : null;
|
|
7343
|
+
}
|
|
7344
|
+
return candidate && YOUTUBE_ID_PATTERN.test(candidate) ? candidate : null;
|
|
7345
|
+
}
|
|
7346
|
+
|
|
7347
|
+
// src/lib/section-embed.ts
|
|
7348
|
+
var SECTION_EMBED_SUFFIX = "__ohw_embed";
|
|
7349
|
+
function readStoredEmbed(value) {
|
|
7350
|
+
if (value.startsWith("start\n")) {
|
|
7351
|
+
return { raw: value.slice("start\n".length), at: "start" };
|
|
7352
|
+
}
|
|
7353
|
+
return { raw: value, at: "end" };
|
|
7354
|
+
}
|
|
7355
|
+
function embedFrameSrc(value) {
|
|
7356
|
+
const videoId = extractYouTubeId(value);
|
|
7357
|
+
if (videoId) {
|
|
7358
|
+
return { src: `https://www.youtube-nocookie.com/embed/${videoId}?rel=0`, title: "YouTube video" };
|
|
7359
|
+
}
|
|
7360
|
+
let url;
|
|
7361
|
+
try {
|
|
7362
|
+
url = new URL(value);
|
|
7363
|
+
} catch {
|
|
7364
|
+
return null;
|
|
7365
|
+
}
|
|
7366
|
+
const host = url.hostname.replace(/^www\./, "").toLowerCase();
|
|
7367
|
+
if (host === "google.com" && url.pathname.startsWith("/maps") || host === "maps.google.com") {
|
|
7368
|
+
const query = url.searchParams.get("q") || url.searchParams.get("query") || "";
|
|
7369
|
+
const src = query ? `https://maps.google.com/maps?q=${encodeURIComponent(query)}&output=embed` : `https://maps.google.com/maps?output=embed`;
|
|
7370
|
+
return { src, title: "Map" };
|
|
7371
|
+
}
|
|
7372
|
+
if (host === "maps.app.goo.gl") {
|
|
7373
|
+
return { src: value, title: "Map" };
|
|
7374
|
+
}
|
|
7375
|
+
if (host === "calendly.com" || host.endsWith(".calendly.com") || host === "calendar.google.com") {
|
|
7376
|
+
return { src: value, title: "Calendar" };
|
|
7377
|
+
}
|
|
7378
|
+
if (host === "docs.google.com" && url.pathname.includes("/forms/")) {
|
|
7379
|
+
return { src: value.replace(/\/edit(?:\?.*)?$/i, "/viewform"), title: "Form" };
|
|
7380
|
+
}
|
|
7381
|
+
if (host === "forms.gle") {
|
|
7382
|
+
return { src: value, title: "Form" };
|
|
7383
|
+
}
|
|
7384
|
+
return null;
|
|
7385
|
+
}
|
|
7386
|
+
function place(section, box, at) {
|
|
7387
|
+
if (at === "start") {
|
|
7388
|
+
section.insertBefore(box, section.firstChild);
|
|
7389
|
+
return;
|
|
7390
|
+
}
|
|
7391
|
+
section.appendChild(box);
|
|
7392
|
+
}
|
|
7393
|
+
function paint(section, key, src, title, at) {
|
|
7394
|
+
const existing = section.querySelector(`[data-ohw-section-embed="${CSS.escape(key)}"]`);
|
|
7395
|
+
const frame = existing?.querySelector("iframe");
|
|
7396
|
+
if (existing && frame) {
|
|
7397
|
+
if (frame.getAttribute("src") !== src) frame.setAttribute("src", src);
|
|
7398
|
+
frame.title = title;
|
|
7399
|
+
place(section, existing, at);
|
|
7400
|
+
return;
|
|
7401
|
+
}
|
|
7402
|
+
existing?.remove();
|
|
7403
|
+
const box = document.createElement("div");
|
|
7404
|
+
box.setAttribute("data-ohw-section-embed", key);
|
|
7405
|
+
box.style.cssText = at === "start" ? "width:100%;max-width:960px;margin:0 auto 32px;padding:32px 24px 0;box-sizing:border-box;" : "width:100%;max-width:960px;margin:32px auto 0;padding:0 24px 32px;box-sizing:border-box;";
|
|
7406
|
+
const frameWrap = document.createElement("div");
|
|
7407
|
+
frameWrap.style.cssText = "position:relative;width:100%;aspect-ratio:16/9;min-height:250px;border-radius:12px;overflow:hidden;background:#0f172a;";
|
|
7408
|
+
const iframe = document.createElement("iframe");
|
|
7409
|
+
iframe.src = src;
|
|
7410
|
+
iframe.title = title;
|
|
7411
|
+
iframe.style.cssText = "position:absolute;inset:0;width:100%;height:100%;border:0;";
|
|
7412
|
+
iframe.allow = "accelerometer; autoplay; clipboard-write; encrypted-media; fullscreen; gyroscope; picture-in-picture";
|
|
7413
|
+
iframe.setAttribute("allowfullscreen", "");
|
|
7414
|
+
frameWrap.appendChild(iframe);
|
|
7415
|
+
box.appendChild(frameWrap);
|
|
7416
|
+
place(section, box, at);
|
|
7417
|
+
}
|
|
7418
|
+
function applySectionEmbeds(content) {
|
|
7419
|
+
for (const [key, val] of Object.entries(content)) {
|
|
7420
|
+
if (!key.endsWith(SECTION_EMBED_SUFFIX)) continue;
|
|
7421
|
+
const sectionId = key.slice(0, -SECTION_EMBED_SUFFIX.length);
|
|
7422
|
+
const section = document.querySelector(`[data-ohw-section="${CSS.escape(sectionId)}"]`);
|
|
7423
|
+
const stored = typeof val === "string" ? readStoredEmbed(val) : null;
|
|
7424
|
+
const frame = stored ? embedFrameSrc(stored.raw) : null;
|
|
7425
|
+
if (!section || !stored || !frame) {
|
|
7426
|
+
section?.querySelector(`[data-ohw-section-embed="${CSS.escape(key)}"]`)?.remove();
|
|
7427
|
+
continue;
|
|
7428
|
+
}
|
|
7429
|
+
paint(section, key, frame.src, frame.title, stored.at);
|
|
7430
|
+
}
|
|
7431
|
+
}
|
|
7432
|
+
|
|
7287
7433
|
// src/ui/ai-tree/aiSectionsManager.tsx
|
|
7288
7434
|
import { flushSync } from "react-dom";
|
|
7289
7435
|
import { createRoot } from "react-dom/client";
|
|
@@ -7857,7 +8003,7 @@ var AI_MOBILE_CSS = [
|
|
|
7857
8003
|
// page's first section. Top only (bottom needs no nav clearance); ~96px approximates the
|
|
7858
8004
|
// template nav's own height (measured ~94px) — there's no shared `--ohw-header-h` var to read
|
|
7859
8005
|
// an exact figure from (no live measurement exists), so this is a safe approximation, not a
|
|
7860
|
-
// pixel-exact fit. Horizontal spacing already comes from `data-ai-
|
|
8006
|
+
// pixel-exact fit. Horizontal spacing already comes from `data-ai-section-inner`.
|
|
7861
8007
|
'[data-ai-overlay-clearance] [data-ai-overlap-layer="overlay"]{padding-top:96px}',
|
|
7862
8008
|
// A full-bleed carousel's height is pure arithmetic: it spans the whole window, so 16/9 turns
|
|
7863
8009
|
// window width straight into height. Measured at 16/9 it came out ~90% of the viewport at EVERY
|
|
@@ -7873,8 +8019,10 @@ var AI_MOBILE_CSS = [
|
|
|
7873
8019
|
"[data-ai-section]{overflow-x:hidden}",
|
|
7874
8020
|
// `:not([data-ai-full-bleed])`: this `!important` gutter beat the inline `padding: 0` that a
|
|
7875
8021
|
// full-bleed section's container sets, so a carousel/media hero that is edge-to-edge on desktop
|
|
7876
|
-
// still got a 20px band of section background down both sides on a phone.
|
|
7877
|
-
|
|
8022
|
+
// still got a 20px band of section background down both sides on a phone. The footer's own
|
|
8023
|
+
// container keeps the unguarded rule below — `data-ai-full-bleed` can never appear on it.
|
|
8024
|
+
"[data-ai-section-inner]:not([data-ai-full-bleed]){padding:0 20px !important}",
|
|
8025
|
+
"[data-ai-container]{padding:0 20px !important}",
|
|
7878
8026
|
"[data-ai-row]{display:flex !important;flex-direction:column !important;align-items:stretch !important}",
|
|
7879
8027
|
"[data-ai-cell]{width:100%;min-width:0}",
|
|
7880
8028
|
// The rule above turns every row into a COLUMN flex container on phones, which silently breaks
|
|
@@ -8079,6 +8227,31 @@ function pricingCardEmphasis(featured, ctx, hasBg) {
|
|
|
8079
8227
|
function textAttrs(ctx, path) {
|
|
8080
8228
|
return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
|
|
8081
8229
|
}
|
|
8230
|
+
var AI_RESPONSIVE_CSS = [
|
|
8231
|
+
"@media (max-width: 960px) {",
|
|
8232
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: repeat(2, 1fr) !important; }",
|
|
8233
|
+
' [data-ai-responsive] [data-ai-grid="1"] { grid-template-columns: 1fr !important; }',
|
|
8234
|
+
"}",
|
|
8235
|
+
"@media (max-width: 640px) {",
|
|
8236
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
|
|
8237
|
+
" [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
|
|
8238
|
+
// Group containers flatten to a column on phones; span placements come along for free.
|
|
8239
|
+
// `:not([data-ai-group="overlap"])` for the same reason as the twin pair in AI_MOBILE_CSS — see
|
|
8240
|
+
// the comment there. This sheet's copy is the narrower selector, so without the exemption it
|
|
8241
|
+
// flattens an `overlap` hero below 640px even though the other rule stands down: measured a 390px
|
|
8242
|
+
// viewport with the heading/CTA in flow *under* the image, 219px of section background where the
|
|
8243
|
+
// layered text used to be.
|
|
8244
|
+
' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) { display: flex !important; flex-direction: column !important; }',
|
|
8245
|
+
' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) > * { grid-column: auto !important; }',
|
|
8246
|
+
// `:not([data-ai-full-bleed])` for the same reason as the twin rule in AI_MOBILE_CSS: this one
|
|
8247
|
+
// is narrower (0,2,0 vs 0,1,0) and also `!important`, so without the guard it wins outright and
|
|
8248
|
+
// a full-bleed hero gets its 20px side band back below 640px only — the one width where the
|
|
8249
|
+
// other rule had already been taught to stand down.
|
|
8250
|
+
" [data-ai-responsive] [data-ai-section-inner]:not([data-ai-full-bleed]) { padding-left: 20px !important; padding-right: 20px !important; }",
|
|
8251
|
+
" [data-ai-responsive] { overflow-x: hidden; }",
|
|
8252
|
+
" [data-ai-responsive] img { max-width: 100%; }",
|
|
8253
|
+
"}"
|
|
8254
|
+
].join("\n");
|
|
8082
8255
|
var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
8083
8256
|
function MediaBox({
|
|
8084
8257
|
refValue,
|
|
@@ -8133,7 +8306,7 @@ function MediaBox({
|
|
|
8133
8306
|
position: fill ? "absolute" : void 0,
|
|
8134
8307
|
inset: fill ? 0 : void 0,
|
|
8135
8308
|
width: fill ? "100%" : fixedSize ? "auto" : "100%",
|
|
8136
|
-
height: fill ? "100%" : void 0,
|
|
8309
|
+
height: fill ? "100%" : fixedSize ? height : void 0,
|
|
8137
8310
|
aspectRatio: fill ? void 0 : aspectRatio,
|
|
8138
8311
|
minHeight: fill || fixedSize ? void 0 : height ?? (aspectRatio ? void 0 : 180),
|
|
8139
8312
|
borderRadius: radius,
|
|
@@ -9629,7 +9802,7 @@ function CollectionBlock({ node, ctx, path }) {
|
|
|
9629
9802
|
return /* @__PURE__ */ jsx(
|
|
9630
9803
|
"div",
|
|
9631
9804
|
{
|
|
9632
|
-
"data-ai-grid":
|
|
9805
|
+
"data-ai-grid": String(itemsPerRow),
|
|
9633
9806
|
"data-ohw-pricing-collection": isPricing ? "" : void 0,
|
|
9634
9807
|
style: {
|
|
9635
9808
|
display: "grid",
|
|
@@ -9931,7 +10104,7 @@ function renderNode(node, ctx, path, ambientAlign) {
|
|
|
9931
10104
|
},
|
|
9932
10105
|
children: [
|
|
9933
10106
|
i > 0 && ctx.heroOverlapFullBleed ? (
|
|
9934
|
-
// The section's `data-ai-
|
|
10107
|
+
// The section's `data-ai-section-inner` gave up its max-width/gutter so the base
|
|
9935
10108
|
// layer (this group's i===0 sibling) can span edge-to-edge — reintroduced here,
|
|
9936
10109
|
// scoped to just the overlay text, so a heading/copy/CTA stack doesn't stretch
|
|
9937
10110
|
// the full section width instead of reading at the usual content width.
|
|
@@ -10350,6 +10523,7 @@ function AiTreeRenderer({
|
|
|
10350
10523
|
...fillHeight ? { "data-ai-fill-height": "" } : {},
|
|
10351
10524
|
...needsOverlayClearance ? { "data-ai-overlay-clearance": "" } : {},
|
|
10352
10525
|
...bgAttrs,
|
|
10526
|
+
"data-ai-responsive": "",
|
|
10353
10527
|
style: {
|
|
10354
10528
|
position: "relative",
|
|
10355
10529
|
padding: `${padCss} 0`,
|
|
@@ -10363,12 +10537,13 @@ function AiTreeRenderer({
|
|
|
10363
10537
|
...fillHeight ? { display: "grid" } : {}
|
|
10364
10538
|
},
|
|
10365
10539
|
children: [
|
|
10366
|
-
|
|
10540
|
+
/* @__PURE__ */ jsx("style", { children: AI_RESPONSIVE_CSS }),
|
|
10367
10541
|
/* @__PURE__ */ jsx("style", { children: AI_MOBILE_CSS }),
|
|
10542
|
+
isOverlay && backgroundUrl && /* @__PURE__ */ jsx("div", { style: { position: "absolute", inset: 0, background: `rgba(255,255,255,${overlayAlpha})` } }),
|
|
10368
10543
|
/* @__PURE__ */ jsx(
|
|
10369
10544
|
"div",
|
|
10370
10545
|
{
|
|
10371
|
-
"data-ai-
|
|
10546
|
+
"data-ai-section-inner": "",
|
|
10372
10547
|
...fullBleedMedia ? { "data-ai-full-bleed": "" } : {},
|
|
10373
10548
|
style: {
|
|
10374
10549
|
position: "relative",
|
|
@@ -10385,7 +10560,7 @@ function AiTreeRenderer({
|
|
|
10385
10560
|
children: tree.rows.map((row, r2) => /* @__PURE__ */ jsx(
|
|
10386
10561
|
"div",
|
|
10387
10562
|
{
|
|
10388
|
-
"data-ai-
|
|
10563
|
+
"data-ai-columns": "",
|
|
10389
10564
|
style: {
|
|
10390
10565
|
display: "grid",
|
|
10391
10566
|
gridTemplateColumns: "repeat(12, 1fr)",
|
|
@@ -11047,9 +11222,10 @@ function applyAiSectionsToDom(state, options) {
|
|
|
11047
11222
|
if (existing && existing.serialized === serialized && existing.container.isConnected) {
|
|
11048
11223
|
continue;
|
|
11049
11224
|
}
|
|
11050
|
-
const isNewMount = !existing || !existing.container.isConnected;
|
|
11051
11225
|
let container = existing?.container;
|
|
11226
|
+
let isNewMount = false;
|
|
11052
11227
|
if (!container || !container.isConnected) {
|
|
11228
|
+
isNewMount = true;
|
|
11053
11229
|
existing?.root.unmount();
|
|
11054
11230
|
container?.remove();
|
|
11055
11231
|
container = document.createElement("div");
|
|
@@ -11387,6 +11563,34 @@ function minSpanForFooterBlock(type) {
|
|
|
11387
11563
|
return 3;
|
|
11388
11564
|
}
|
|
11389
11565
|
}
|
|
11566
|
+
function readLiveSocialItems() {
|
|
11567
|
+
const root = getFooterRoot();
|
|
11568
|
+
const row = root?.querySelector("[data-ohw-socials-row]");
|
|
11569
|
+
if (!row) return [];
|
|
11570
|
+
const items = [];
|
|
11571
|
+
for (const anchor of Array.from(row.querySelectorAll("a[href]"))) {
|
|
11572
|
+
const href = anchor.getAttribute("href")?.trim() ?? "";
|
|
11573
|
+
const aria = anchor.getAttribute("aria-label")?.trim().toLowerCase() ?? "";
|
|
11574
|
+
const platform = FOOTER_SOCIAL_PLATFORMS.find((name) => aria === name) ?? FOOTER_SOCIAL_PLATFORMS.find((name) => href.toLowerCase().includes(name));
|
|
11575
|
+
if (!platform || !/^https?:\/\//i.test(href)) continue;
|
|
11576
|
+
items.push({ platform, href });
|
|
11577
|
+
}
|
|
11578
|
+
return items;
|
|
11579
|
+
}
|
|
11580
|
+
function syncSocialRowsFromDom(tree) {
|
|
11581
|
+
const root = getFooterRoot();
|
|
11582
|
+
if (!root) return;
|
|
11583
|
+
const row = root.querySelector("[data-ohw-socials-row]");
|
|
11584
|
+
const live = readLiveSocialItems();
|
|
11585
|
+
if (row && live.length === 0) return;
|
|
11586
|
+
for (const col of tree.columns) {
|
|
11587
|
+
col.blocks = col.blocks.flatMap((block) => {
|
|
11588
|
+
if (block.type !== "social-row") return [block];
|
|
11589
|
+
if (!row) return [];
|
|
11590
|
+
return [{ ...block, items: live.map((item) => ({ platform: item.platform, href: item.href })) }];
|
|
11591
|
+
});
|
|
11592
|
+
}
|
|
11593
|
+
}
|
|
11390
11594
|
function collectBrandBlocks(tree) {
|
|
11391
11595
|
const brand = [];
|
|
11392
11596
|
for (const col of tree.columns) {
|
|
@@ -11632,6 +11836,7 @@ function textOf2(el) {
|
|
|
11632
11836
|
}
|
|
11633
11837
|
function syncFooterTreeLinksFromDom(tree) {
|
|
11634
11838
|
const next = cloneTree(tree);
|
|
11839
|
+
syncSocialRowsFromDom(next);
|
|
11635
11840
|
const domCols = listFooterColumns().map((col) => {
|
|
11636
11841
|
const heading = getFooterColumnHeadingEl(col);
|
|
11637
11842
|
const title = heading ? textOf2(heading) : void 0;
|
|
@@ -17208,7 +17413,7 @@ function apiBase() {
|
|
|
17208
17413
|
function bridgeVersion() {
|
|
17209
17414
|
try {
|
|
17210
17415
|
if (true) {
|
|
17211
|
-
return "0.1.
|
|
17416
|
+
return "0.1.160-next.428";
|
|
17212
17417
|
}
|
|
17213
17418
|
} catch {
|
|
17214
17419
|
}
|
|
@@ -17222,7 +17427,7 @@ function stampBridgeVersionOnDocument() {
|
|
|
17222
17427
|
return;
|
|
17223
17428
|
}
|
|
17224
17429
|
try {
|
|
17225
|
-
const v = true ? "0.1.
|
|
17430
|
+
const v = true ? "0.1.160-next.428" : "";
|
|
17226
17431
|
if (v) {
|
|
17227
17432
|
document.documentElement.setAttribute("data-ohw-bridge-version", v);
|
|
17228
17433
|
window.__OHW_BRIDGE_VERSION__ = v;
|
|
@@ -17900,6 +18105,7 @@ function MediaOverlay({
|
|
|
17900
18105
|
(prev) => prev && prev.fullWidth === width && prev.height === height ? prev : { fullWidth: width, height }
|
|
17901
18106
|
);
|
|
17902
18107
|
}, [isVideo]);
|
|
18108
|
+
const replaceLabel = isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image";
|
|
17903
18109
|
const replaceMode = buttonSize ? replaceButtonMode({ width: rect.width, height: rect.height }, buttonSize) : "none";
|
|
17904
18110
|
const box = {
|
|
17905
18111
|
position: "fixed",
|
|
@@ -17998,11 +18204,10 @@ function MediaOverlay({
|
|
|
17998
18204
|
className: "flex items-center justify-center cursor-pointer",
|
|
17999
18205
|
style: {
|
|
18000
18206
|
...box,
|
|
18001
|
-
//
|
|
18002
|
-
//
|
|
18003
|
-
//
|
|
18004
|
-
|
|
18005
|
-
pointerEvents: hover.hasTextOverlap || cueOnly ? "none" : "auto",
|
|
18207
|
+
// Visual only. `pointer-events: auto` on this full-bleed rect covered the navbar
|
|
18208
|
+
// (hero bg includes the absolute TopNav) and swallowed CTA press-drag. Text overlay
|
|
18209
|
+
// and cueOnly also need clicks to fall through — Replace / video controls opt back in.
|
|
18210
|
+
pointerEvents: "none",
|
|
18006
18211
|
// Selected: a firm component ring with no wash, so the image reads as chosen rather
|
|
18007
18212
|
// than hovered. Hover keeps the existing tinted preview.
|
|
18008
18213
|
boxShadow: selected ? "inset 0 0 0 2px var(--color-bridge-primary)" : "inset 0 0 0 1.5px var(--color-bridge-primary)",
|
|
@@ -18029,17 +18234,17 @@ function MediaOverlay({
|
|
|
18029
18234
|
},
|
|
18030
18235
|
children: [
|
|
18031
18236
|
isVideo ? /* @__PURE__ */ jsx17(Film, { size: 14 }) : /* @__PURE__ */ jsx17(ImageIcon, { size: 14 }),
|
|
18032
|
-
|
|
18237
|
+
replaceLabel
|
|
18033
18238
|
]
|
|
18034
18239
|
}
|
|
18035
18240
|
),
|
|
18036
|
-
replaceMode
|
|
18241
|
+
showChrome && replaceMode !== "none" && /* @__PURE__ */ jsxs8(
|
|
18037
18242
|
Button,
|
|
18038
18243
|
{
|
|
18039
18244
|
"data-ohw-media-overlay": "",
|
|
18040
18245
|
variant: "outline",
|
|
18041
18246
|
size: "sm",
|
|
18042
|
-
"aria-label":
|
|
18247
|
+
"aria-label": replaceLabel,
|
|
18043
18248
|
className: "gap-1.5 cursor-pointer hover:bg-background",
|
|
18044
18249
|
style: {
|
|
18045
18250
|
...OVERLAY_BUTTON_STYLE,
|
|
@@ -18062,7 +18267,7 @@ function MediaOverlay({
|
|
|
18062
18267
|
},
|
|
18063
18268
|
children: [
|
|
18064
18269
|
isVideo ? /* @__PURE__ */ jsx17(Film, { size: 14 }) : /* @__PURE__ */ jsx17(ImageIcon, { size: 14 }),
|
|
18065
|
-
replaceMode === "full" ?
|
|
18270
|
+
replaceMode === "full" ? replaceLabel : null
|
|
18066
18271
|
]
|
|
18067
18272
|
}
|
|
18068
18273
|
)
|
|
@@ -18655,8 +18860,24 @@ function AiSectionOverlay({
|
|
|
18655
18860
|
}
|
|
18656
18861
|
|
|
18657
18862
|
// src/ui/ai-section/AiMediaStripOverlay.tsx
|
|
18658
|
-
import { useCallback as useCallback3, useEffect as useEffect6, useRef as useRef5, useState as useState8 } from "react";
|
|
18659
|
-
import {
|
|
18863
|
+
import { useCallback as useCallback3, useEffect as useEffect6, useLayoutEffect as useLayoutEffect4, useRef as useRef5, useState as useState8 } from "react";
|
|
18864
|
+
import {
|
|
18865
|
+
AlignCenter,
|
|
18866
|
+
AlignLeft,
|
|
18867
|
+
AlignRight,
|
|
18868
|
+
ArrowLeft as ArrowLeft2,
|
|
18869
|
+
ArrowRight as ArrowRight2,
|
|
18870
|
+
Check as Check2,
|
|
18871
|
+
ChevronDown as ChevronDown3,
|
|
18872
|
+
Image as ImageIcon2,
|
|
18873
|
+
ImageMinus,
|
|
18874
|
+
ImagePlus,
|
|
18875
|
+
Link as LinkIcon,
|
|
18876
|
+
Minus,
|
|
18877
|
+
Palette,
|
|
18878
|
+
Plus as Plus2,
|
|
18879
|
+
Star
|
|
18880
|
+
} from "lucide-react";
|
|
18660
18881
|
|
|
18661
18882
|
// src/lib/ai-media-strip-tree.ts
|
|
18662
18883
|
var MEDIA_STRIP_ITEM_MIN = 1;
|
|
@@ -18770,14 +18991,6 @@ function setMediaStripItemAsset(tree, index, assetId) {
|
|
|
18770
18991
|
return true;
|
|
18771
18992
|
});
|
|
18772
18993
|
}
|
|
18773
|
-
function setMediaStripItemAlt(tree, index, alt) {
|
|
18774
|
-
return withMediaStrip(tree, (block) => {
|
|
18775
|
-
const items = block.items;
|
|
18776
|
-
if (index < 0 || index >= items.length) return false;
|
|
18777
|
-
items[index] = { ...items[index], alt };
|
|
18778
|
-
return true;
|
|
18779
|
-
});
|
|
18780
|
-
}
|
|
18781
18994
|
function setMediaStripItemLink(tree, index, link) {
|
|
18782
18995
|
return withMediaStrip(tree, (block) => {
|
|
18783
18996
|
const items = block.items;
|
|
@@ -18795,11 +19008,117 @@ function setMediaStripItemLink(tree, index, link) {
|
|
|
18795
19008
|
});
|
|
18796
19009
|
}
|
|
18797
19010
|
|
|
19011
|
+
// src/ui/dialog.tsx
|
|
19012
|
+
import * as React9 from "react";
|
|
19013
|
+
import { Dialog as DialogPrimitive } from "radix-ui";
|
|
19014
|
+
import { X as X2 } from "lucide-react";
|
|
19015
|
+
import { jsx as jsx20, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
19016
|
+
function Dialog2({
|
|
19017
|
+
...props
|
|
19018
|
+
}) {
|
|
19019
|
+
return /* @__PURE__ */ jsx20(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
|
|
19020
|
+
}
|
|
19021
|
+
function DialogPortal({
|
|
19022
|
+
...props
|
|
19023
|
+
}) {
|
|
19024
|
+
return /* @__PURE__ */ jsx20(DialogPrimitive.Portal, { ...props });
|
|
19025
|
+
}
|
|
19026
|
+
function DialogOverlay({
|
|
19027
|
+
className,
|
|
19028
|
+
...props
|
|
19029
|
+
}) {
|
|
19030
|
+
return /* @__PURE__ */ jsx20(
|
|
19031
|
+
DialogPrimitive.Overlay,
|
|
19032
|
+
{
|
|
19033
|
+
"data-slot": "dialog-overlay",
|
|
19034
|
+
"data-ohw-link-modal-root": "",
|
|
19035
|
+
className: cn("fixed inset-0 z-[2147483646] bg-black/50", className),
|
|
19036
|
+
...props
|
|
19037
|
+
}
|
|
19038
|
+
);
|
|
19039
|
+
}
|
|
19040
|
+
var DialogContent = React9.forwardRef(
|
|
19041
|
+
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
19042
|
+
const positionMode = container ? "absolute" : "fixed";
|
|
19043
|
+
return /* @__PURE__ */ jsxs11(DialogPortal, { container: container ?? void 0, children: [
|
|
19044
|
+
/* @__PURE__ */ jsx20(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
19045
|
+
/* @__PURE__ */ jsxs11(
|
|
19046
|
+
DialogPrimitive.Content,
|
|
19047
|
+
{
|
|
19048
|
+
ref,
|
|
19049
|
+
"data-slot": "dialog-content",
|
|
19050
|
+
className: cn(
|
|
19051
|
+
positionMode,
|
|
19052
|
+
"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",
|
|
19053
|
+
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
19054
|
+
container ? "max-h-[calc(100%-32px)]" : "max-h-[calc(100vh-32px)]",
|
|
19055
|
+
className
|
|
19056
|
+
),
|
|
19057
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
19058
|
+
...props,
|
|
19059
|
+
children: [
|
|
19060
|
+
children,
|
|
19061
|
+
showCloseButton ? /* @__PURE__ */ jsx20(
|
|
19062
|
+
DialogPrimitive.Close,
|
|
19063
|
+
{
|
|
19064
|
+
type: "button",
|
|
19065
|
+
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
19066
|
+
"aria-label": "Close",
|
|
19067
|
+
children: /* @__PURE__ */ jsx20(X2, { size: 16, "aria-hidden": true })
|
|
19068
|
+
}
|
|
19069
|
+
) : null
|
|
19070
|
+
]
|
|
19071
|
+
}
|
|
19072
|
+
)
|
|
19073
|
+
] });
|
|
19074
|
+
}
|
|
19075
|
+
);
|
|
19076
|
+
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
19077
|
+
function DialogHeader({
|
|
19078
|
+
className,
|
|
19079
|
+
...props
|
|
19080
|
+
}) {
|
|
19081
|
+
return /* @__PURE__ */ jsx20("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
19082
|
+
}
|
|
19083
|
+
function DialogFooter({
|
|
19084
|
+
className,
|
|
19085
|
+
...props
|
|
19086
|
+
}) {
|
|
19087
|
+
return /* @__PURE__ */ jsx20(
|
|
19088
|
+
"div",
|
|
19089
|
+
{
|
|
19090
|
+
className: cn("flex items-center justify-end gap-2", className),
|
|
19091
|
+
...props
|
|
19092
|
+
}
|
|
19093
|
+
);
|
|
19094
|
+
}
|
|
19095
|
+
var DialogTitle = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx20(
|
|
19096
|
+
DialogPrimitive.Title,
|
|
19097
|
+
{
|
|
19098
|
+
ref,
|
|
19099
|
+
className: cn(
|
|
19100
|
+
"text-lg font-semibold leading-none tracking-tight text-card-foreground",
|
|
19101
|
+
className
|
|
19102
|
+
),
|
|
19103
|
+
...props
|
|
19104
|
+
}
|
|
19105
|
+
));
|
|
19106
|
+
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
19107
|
+
var DialogDescription = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx20(
|
|
19108
|
+
DialogPrimitive.Description,
|
|
19109
|
+
{
|
|
19110
|
+
ref,
|
|
19111
|
+
className: cn("text-sm text-muted-foreground", className),
|
|
19112
|
+
...props
|
|
19113
|
+
}
|
|
19114
|
+
));
|
|
19115
|
+
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
19116
|
+
var DialogClose = DialogPrimitive.Close;
|
|
19117
|
+
|
|
18798
19118
|
// src/ui/ai-section/AiMediaStripOverlay.tsx
|
|
18799
|
-
import { Fragment as Fragment7, jsx as
|
|
18800
|
-
var PRIMARY3 = "#0885FE";
|
|
18801
|
-
var
|
|
18802
|
-
var OHW_BLUE_DARK = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY3}) 60%, #000000)`;
|
|
19119
|
+
import { Fragment as Fragment7, jsx as jsx21, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
19120
|
+
var PRIMARY3 = "var(--ohw-primary, #0885FE)";
|
|
19121
|
+
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]";
|
|
18803
19122
|
function findMediaStripItemElement(sectionId, index) {
|
|
18804
19123
|
const sectionEl = findByInstanceId(sectionId);
|
|
18805
19124
|
if (!sectionEl) return null;
|
|
@@ -18809,14 +19128,35 @@ function findMediaStripItemElement(sectionId, index) {
|
|
|
18809
19128
|
}
|
|
18810
19129
|
return null;
|
|
18811
19130
|
}
|
|
18812
|
-
function
|
|
18813
|
-
|
|
19131
|
+
function itemRefFromTarget(target) {
|
|
19132
|
+
if (!(target instanceof Element)) return null;
|
|
19133
|
+
if (target.closest(CHROME_SELECTOR)) return null;
|
|
19134
|
+
const itemEl = target.closest("[data-ohw-media-strip-item]");
|
|
19135
|
+
if (!itemEl) return null;
|
|
19136
|
+
const sectionEl = itemEl.closest("[data-ohw-section]");
|
|
19137
|
+
const unit = sectionEl ? movableUnit(sectionEl) : null;
|
|
19138
|
+
const sectionId = unit ? instanceIdOf(unit) || null : null;
|
|
19139
|
+
const index = Number(itemEl.dataset.ohwMediaStripIndex);
|
|
19140
|
+
if (!sectionId || Number.isNaN(index)) return null;
|
|
19141
|
+
return { sectionId, index };
|
|
19142
|
+
}
|
|
19143
|
+
function sameRef(a, b) {
|
|
19144
|
+
return a?.sectionId === b?.sectionId && a?.index === b?.index;
|
|
19145
|
+
}
|
|
19146
|
+
function rectOf(el) {
|
|
18814
19147
|
if (!el) return null;
|
|
18815
19148
|
const r2 = el.getBoundingClientRect();
|
|
18816
19149
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
18817
19150
|
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
18818
19151
|
}
|
|
18819
|
-
function
|
|
19152
|
+
function readRect2(ref) {
|
|
19153
|
+
return rectOf(ref && findMediaStripItemElement(ref.sectionId, ref.index));
|
|
19154
|
+
}
|
|
19155
|
+
function readStripRect(ref) {
|
|
19156
|
+
const item = ref && findMediaStripItemElement(ref.sectionId, ref.index);
|
|
19157
|
+
return rectOf(item?.closest("[data-ohw-media-strip]") ?? item);
|
|
19158
|
+
}
|
|
19159
|
+
function useLiveItemRect(ref, strip = false) {
|
|
18820
19160
|
const [rect, setRect] = useState8(null);
|
|
18821
19161
|
useEffect6(() => {
|
|
18822
19162
|
if (!ref) {
|
|
@@ -18824,7 +19164,7 @@ function useLiveItemRect(ref) {
|
|
|
18824
19164
|
return;
|
|
18825
19165
|
}
|
|
18826
19166
|
const update = () => {
|
|
18827
|
-
const next = readRect2(ref);
|
|
19167
|
+
const next = strip ? readStripRect(ref) : readRect2(ref);
|
|
18828
19168
|
setRect(
|
|
18829
19169
|
(prev) => prev && next && prev.top === next.top && prev.left === next.left && prev.width === next.width && prev.height === next.height ? prev : next
|
|
18830
19170
|
);
|
|
@@ -18839,9 +19179,49 @@ function useLiveItemRect(ref) {
|
|
|
18839
19179
|
window.removeEventListener("resize", update);
|
|
18840
19180
|
clearInterval(interval);
|
|
18841
19181
|
};
|
|
18842
|
-
}, [ref?.sectionId, ref?.index]);
|
|
19182
|
+
}, [ref?.sectionId, ref?.index, strip]);
|
|
18843
19183
|
return rect;
|
|
18844
19184
|
}
|
|
19185
|
+
var TOOLBAR_STRIP_GAP = 52;
|
|
19186
|
+
var TOOLBAR_STRIP_GAP_MOBILE = 42;
|
|
19187
|
+
var TOOLBAR_EDGE_MARGIN2 = 4;
|
|
19188
|
+
function StripToolbarSlot({ stripRect, children }) {
|
|
19189
|
+
const slotRef = useRef5(null);
|
|
19190
|
+
const [shift, setShift] = useState8(0);
|
|
19191
|
+
const centerX = stripRect.left + stripRect.width / 2;
|
|
19192
|
+
useLayoutEffect4(() => {
|
|
19193
|
+
const slot = slotRef.current;
|
|
19194
|
+
if (!slot) return;
|
|
19195
|
+
const clamp = () => {
|
|
19196
|
+
const w = slot.offsetWidth;
|
|
19197
|
+
if (w <= 0) return;
|
|
19198
|
+
const half = w / 2;
|
|
19199
|
+
const clamped = Math.max(TOOLBAR_EDGE_MARGIN2 + half, Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN2 - half));
|
|
19200
|
+
setShift((prev) => Math.abs(prev - (clamped - centerX)) < 0.5 ? prev : clamped - centerX);
|
|
19201
|
+
};
|
|
19202
|
+
clamp();
|
|
19203
|
+
const ro = new ResizeObserver(clamp);
|
|
19204
|
+
ro.observe(slot);
|
|
19205
|
+
return () => ro.disconnect();
|
|
19206
|
+
}, [centerX, children]);
|
|
19207
|
+
const mobile = window.innerWidth <= 480;
|
|
19208
|
+
return /* @__PURE__ */ jsx21(
|
|
19209
|
+
"div",
|
|
19210
|
+
{
|
|
19211
|
+
ref: slotRef,
|
|
19212
|
+
"data-ohw-bridge": "",
|
|
19213
|
+
"data-ohw-item-interaction": "",
|
|
19214
|
+
className: "pointer-events-auto fixed",
|
|
19215
|
+
style: {
|
|
19216
|
+
top: stripRect.top - (mobile ? TOOLBAR_STRIP_GAP_MOBILE : TOOLBAR_STRIP_GAP),
|
|
19217
|
+
left: centerX + shift,
|
|
19218
|
+
transform: "translate(-50%, -100%)",
|
|
19219
|
+
zIndex: 2147483645
|
|
19220
|
+
},
|
|
19221
|
+
children
|
|
19222
|
+
}
|
|
19223
|
+
);
|
|
19224
|
+
}
|
|
18845
19225
|
function requestValidateTree(postToParent2, tree) {
|
|
18846
19226
|
return new Promise((resolve) => {
|
|
18847
19227
|
const id = `ai-validate-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
@@ -18878,116 +19258,72 @@ function requestAssetPick(postToParent2) {
|
|
|
18878
19258
|
postToParent2({ type: "ow:asset-pick", id });
|
|
18879
19259
|
});
|
|
18880
19260
|
}
|
|
18881
|
-
function
|
|
19261
|
+
function ToolbarAction({
|
|
18882
19262
|
label,
|
|
18883
19263
|
onClick,
|
|
18884
|
-
disabled,
|
|
18885
|
-
active
|
|
19264
|
+
disabled = false,
|
|
19265
|
+
active = false,
|
|
19266
|
+
children
|
|
18886
19267
|
}) {
|
|
18887
|
-
|
|
18888
|
-
|
|
18889
|
-
{
|
|
18890
|
-
|
|
18891
|
-
|
|
18892
|
-
disabled,
|
|
18893
|
-
style: {
|
|
18894
|
-
height: 28,
|
|
18895
|
-
padding: "0 10px",
|
|
18896
|
-
display: "inline-flex",
|
|
18897
|
-
alignItems: "center",
|
|
18898
|
-
gap: 4,
|
|
18899
|
-
borderRadius: 999,
|
|
18900
|
-
border: "none",
|
|
18901
|
-
cursor: disabled ? "default" : "pointer",
|
|
18902
|
-
background: active ? OHW_BLUE_DARK : "#ffffff",
|
|
18903
|
-
color: active ? "#ffffff" : OHW_BLUE_DARK,
|
|
18904
|
-
opacity: disabled ? 0.4 : 1,
|
|
18905
|
-
fontSize: 12,
|
|
18906
|
-
lineHeight: "16px",
|
|
18907
|
-
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
18908
|
-
whiteSpace: "nowrap",
|
|
18909
|
-
flex: "0 0 auto"
|
|
18910
|
-
},
|
|
18911
|
-
children: label
|
|
18912
|
-
}
|
|
18913
|
-
);
|
|
19268
|
+
const button = /* @__PURE__ */ jsx21(CustomToolbarButton, { type: "button", "aria-label": label, disabled, active, onClick, className: "size-8", children });
|
|
19269
|
+
return /* @__PURE__ */ jsxs12(Tooltip, { children: [
|
|
19270
|
+
/* @__PURE__ */ jsx21(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ jsx21("span", { className: "inline-flex", children: button }) : button }),
|
|
19271
|
+
/* @__PURE__ */ jsx21(TooltipContent, { side: "bottom", sideOffset: 8, children: label })
|
|
19272
|
+
] });
|
|
18914
19273
|
}
|
|
18915
|
-
function
|
|
18916
|
-
|
|
18917
|
-
|
|
18918
|
-
|
|
18919
|
-
|
|
18920
|
-
|
|
18921
|
-
|
|
18922
|
-
|
|
18923
|
-
|
|
18924
|
-
|
|
18925
|
-
|
|
18926
|
-
|
|
18927
|
-
|
|
18928
|
-
|
|
18929
|
-
|
|
18930
|
-
|
|
18931
|
-
|
|
18932
|
-
|
|
18933
|
-
|
|
18934
|
-
|
|
18935
|
-
|
|
18936
|
-
|
|
18937
|
-
|
|
18938
|
-
|
|
18939
|
-
|
|
18940
|
-
|
|
18941
|
-
|
|
18942
|
-
|
|
18943
|
-
|
|
18944
|
-
},
|
|
18945
|
-
children: "Alt"
|
|
18946
|
-
}
|
|
18947
|
-
),
|
|
18948
|
-
/* @__PURE__ */ jsx20(
|
|
18949
|
-
"input",
|
|
19274
|
+
function ToolbarSeparator() {
|
|
19275
|
+
return /* @__PURE__ */ jsx21("span", { "aria-hidden": true, className: "mx-0.5 block h-6 w-px shrink-0 bg-border" });
|
|
19276
|
+
}
|
|
19277
|
+
function OptionMenu({
|
|
19278
|
+
label,
|
|
19279
|
+
value,
|
|
19280
|
+
options,
|
|
19281
|
+
onChange
|
|
19282
|
+
}) {
|
|
19283
|
+
const current = options.find((o) => o.value === value) ?? options[0];
|
|
19284
|
+
return /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19285
|
+
/* @__PURE__ */ jsx21("span", { className: "text-xs text-muted-foreground", children: label }),
|
|
19286
|
+
/* @__PURE__ */ jsxs12(DropdownMenu, { modal: false, children: [
|
|
19287
|
+
/* @__PURE__ */ jsx21(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs12(
|
|
19288
|
+
"button",
|
|
19289
|
+
{
|
|
19290
|
+
type: "button",
|
|
19291
|
+
"aria-label": label,
|
|
19292
|
+
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",
|
|
19293
|
+
children: [
|
|
19294
|
+
/* @__PURE__ */ jsx21("span", { className: "flex-1 text-left", children: current.label }),
|
|
19295
|
+
/* @__PURE__ */ jsx21(ChevronDown3, { size: 16, style: { pointerEvents: "none" } })
|
|
19296
|
+
]
|
|
19297
|
+
}
|
|
19298
|
+
) }),
|
|
19299
|
+
/* @__PURE__ */ jsx21(DropdownMenuContent, { align: "end", sideOffset: 8, className: "w-[132px] min-w-[132px] p-1", children: options.map((option) => {
|
|
19300
|
+
const selected = option.value === value;
|
|
19301
|
+
return /* @__PURE__ */ jsxs12(
|
|
19302
|
+
DropdownMenuItem,
|
|
18950
19303
|
{
|
|
18951
|
-
|
|
18952
|
-
|
|
18953
|
-
|
|
18954
|
-
|
|
18955
|
-
|
|
18956
|
-
|
|
18957
|
-
|
|
18958
|
-
|
|
18959
|
-
|
|
18960
|
-
|
|
18961
|
-
|
|
18962
|
-
|
|
18963
|
-
|
|
18964
|
-
|
|
18965
|
-
"aria-label": "Image alt text",
|
|
18966
|
-
style: {
|
|
18967
|
-
flex: 1,
|
|
18968
|
-
minWidth: 0,
|
|
18969
|
-
border: "none",
|
|
18970
|
-
outline: "none",
|
|
18971
|
-
background: "transparent",
|
|
18972
|
-
fontSize: 12,
|
|
18973
|
-
lineHeight: "16px",
|
|
18974
|
-
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
18975
|
-
color: "#1f2937"
|
|
18976
|
-
}
|
|
18977
|
-
}
|
|
18978
|
-
)
|
|
18979
|
-
]
|
|
18980
|
-
}
|
|
18981
|
-
);
|
|
19304
|
+
role: "menuitemradio",
|
|
19305
|
+
"aria-checked": selected,
|
|
19306
|
+
onSelect: () => onChange(option.value),
|
|
19307
|
+
className: cn("grid grid-cols-[1fr_16px] gap-2 py-2 pl-2 pr-2 text-[13px]", selected && "bg-muted"),
|
|
19308
|
+
children: [
|
|
19309
|
+
/* @__PURE__ */ jsx21("span", { children: option.label }),
|
|
19310
|
+
selected && /* @__PURE__ */ jsx21(Check2, { size: 16, className: "text-bridge-primary" })
|
|
19311
|
+
]
|
|
19312
|
+
},
|
|
19313
|
+
option.value
|
|
19314
|
+
);
|
|
19315
|
+
}) })
|
|
19316
|
+
] })
|
|
19317
|
+
] });
|
|
18982
19318
|
}
|
|
18983
19319
|
var VARIANTS = [
|
|
18984
19320
|
{ value: "logos", label: "Logos" },
|
|
18985
19321
|
{ value: "reel", label: "Reel" }
|
|
18986
19322
|
];
|
|
18987
19323
|
var ALIGNS = [
|
|
18988
|
-
{ value: "left", label: "
|
|
18989
|
-
{ value: "center", label: "
|
|
18990
|
-
{ value: "right", label: "
|
|
19324
|
+
{ value: "left", label: "Align left", Icon: AlignLeft },
|
|
19325
|
+
{ value: "center", label: "Align center", Icon: AlignCenter },
|
|
19326
|
+
{ value: "right", label: "Align right", Icon: AlignRight }
|
|
18991
19327
|
];
|
|
18992
19328
|
var HOVERS = [
|
|
18993
19329
|
{ value: "none", label: "None" },
|
|
@@ -18995,104 +19331,104 @@ var HOVERS = [
|
|
|
18995
19331
|
{ value: "zoom", label: "Zoom" },
|
|
18996
19332
|
{ value: "fade", label: "Fade" }
|
|
18997
19333
|
];
|
|
18998
|
-
var TREATMENTS = [
|
|
18999
|
-
{ value: "color", label: "Color" },
|
|
19000
|
-
{ value: "grayscale", label: "Grayscale" }
|
|
19001
|
-
];
|
|
19002
19334
|
var HTTP_URL_RE = /^https?:\/\/\S+$/i;
|
|
19003
|
-
function
|
|
19004
|
-
|
|
19335
|
+
function LinkModal({
|
|
19336
|
+
href,
|
|
19337
|
+
linkTarget,
|
|
19338
|
+
onClose,
|
|
19339
|
+
onSave
|
|
19340
|
+
}) {
|
|
19341
|
+
const [draft, setDraft] = useState8(href);
|
|
19342
|
+
const [newTab, setNewTab] = useState8(linkTarget !== "same-tab");
|
|
19005
19343
|
const [invalid, setInvalid] = useState8(false);
|
|
19006
|
-
|
|
19007
|
-
setDraft(value);
|
|
19008
|
-
setInvalid(false);
|
|
19009
|
-
}, [value]);
|
|
19010
|
-
const commit = () => {
|
|
19344
|
+
const save = () => {
|
|
19011
19345
|
const next = draft.trim();
|
|
19012
|
-
if (next
|
|
19013
|
-
|
|
19014
|
-
|
|
19015
|
-
onCommit(next);
|
|
19016
|
-
};
|
|
19017
|
-
return /* @__PURE__ */ jsxs11(
|
|
19018
|
-
"div",
|
|
19019
|
-
{
|
|
19020
|
-
style: {
|
|
19021
|
-
display: "flex",
|
|
19022
|
-
alignItems: "center",
|
|
19023
|
-
gap: 6,
|
|
19024
|
-
height: 28,
|
|
19025
|
-
padding: "0 12px",
|
|
19026
|
-
borderRadius: 999,
|
|
19027
|
-
background: "#ffffff",
|
|
19028
|
-
width: "100%",
|
|
19029
|
-
maxWidth: 260,
|
|
19030
|
-
boxSizing: "border-box",
|
|
19031
|
-
boxShadow: invalid ? "inset 0 0 0 1.5px #EF4444" : "none"
|
|
19032
|
-
},
|
|
19033
|
-
children: [
|
|
19034
|
-
/* @__PURE__ */ jsx20(
|
|
19035
|
-
"span",
|
|
19036
|
-
{
|
|
19037
|
-
style: {
|
|
19038
|
-
flex: "0 0 auto",
|
|
19039
|
-
color: OHW_BLUE_DARK,
|
|
19040
|
-
fontSize: 10,
|
|
19041
|
-
fontWeight: 700,
|
|
19042
|
-
textTransform: "uppercase",
|
|
19043
|
-
letterSpacing: 0.4
|
|
19044
|
-
},
|
|
19045
|
-
children: "Link"
|
|
19046
|
-
}
|
|
19047
|
-
),
|
|
19048
|
-
/* @__PURE__ */ jsx20(
|
|
19049
|
-
"input",
|
|
19050
|
-
{
|
|
19051
|
-
type: "text",
|
|
19052
|
-
inputMode: "url",
|
|
19053
|
-
value: draft,
|
|
19054
|
-
onChange: (e) => setDraft(e.target.value),
|
|
19055
|
-
onBlur: commit,
|
|
19056
|
-
onKeyDown: (e) => {
|
|
19057
|
-
if (e.key === "Enter") e.currentTarget.blur();
|
|
19058
|
-
if (e.key === "Escape") {
|
|
19059
|
-
setDraft(value);
|
|
19060
|
-
setInvalid(false);
|
|
19061
|
-
e.currentTarget.blur();
|
|
19062
|
-
}
|
|
19063
|
-
},
|
|
19064
|
-
placeholder: "https://example.com",
|
|
19065
|
-
"aria-label": "Image link URL",
|
|
19066
|
-
"aria-invalid": invalid,
|
|
19067
|
-
style: {
|
|
19068
|
-
flex: 1,
|
|
19069
|
-
minWidth: 0,
|
|
19070
|
-
border: "none",
|
|
19071
|
-
outline: "none",
|
|
19072
|
-
background: "transparent",
|
|
19073
|
-
fontSize: 12,
|
|
19074
|
-
lineHeight: "16px",
|
|
19075
|
-
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
19076
|
-
color: "#1f2937"
|
|
19077
|
-
}
|
|
19078
|
-
}
|
|
19079
|
-
)
|
|
19080
|
-
]
|
|
19346
|
+
if (next && !HTTP_URL_RE.test(next)) {
|
|
19347
|
+
setInvalid(true);
|
|
19348
|
+
return;
|
|
19081
19349
|
}
|
|
19082
|
-
|
|
19350
|
+
onSave(next, newTab ? "new-tab" : "same-tab");
|
|
19351
|
+
onClose();
|
|
19352
|
+
};
|
|
19353
|
+
return /* @__PURE__ */ jsx21(Dialog2, { open: true, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ jsxs12(DialogContent, { "data-ohw-link-modal-root": "", className: "max-w-[400px] gap-4 p-5", children: [
|
|
19354
|
+
/* @__PURE__ */ jsx21(DialogHeader, { children: /* @__PURE__ */ jsx21(DialogTitle, { className: "text-base", children: "Image link" }) }),
|
|
19355
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex flex-col gap-3", children: [
|
|
19356
|
+
/* @__PURE__ */ jsx21(
|
|
19357
|
+
"input",
|
|
19358
|
+
{
|
|
19359
|
+
autoFocus: true,
|
|
19360
|
+
type: "text",
|
|
19361
|
+
inputMode: "url",
|
|
19362
|
+
value: draft,
|
|
19363
|
+
onChange: (e) => {
|
|
19364
|
+
setDraft(e.target.value);
|
|
19365
|
+
setInvalid(false);
|
|
19366
|
+
},
|
|
19367
|
+
onKeyDown: (e) => {
|
|
19368
|
+
if (e.key === "Enter") save();
|
|
19369
|
+
},
|
|
19370
|
+
placeholder: "https://example.com",
|
|
19371
|
+
"aria-label": "Image link URL",
|
|
19372
|
+
"aria-invalid": invalid,
|
|
19373
|
+
className: cn(
|
|
19374
|
+
"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",
|
|
19375
|
+
invalid && "border-destructive focus:border-destructive"
|
|
19376
|
+
)
|
|
19377
|
+
}
|
|
19378
|
+
),
|
|
19379
|
+
invalid && /* @__PURE__ */ jsx21("p", { className: "text-xs text-destructive", children: "Enter a full URL starting with http:// or https://" }),
|
|
19380
|
+
/* @__PURE__ */ jsxs12("label", { className: "flex items-center gap-2 text-[13px] text-foreground", children: [
|
|
19381
|
+
/* @__PURE__ */ jsx21("input", { type: "checkbox", checked: newTab, onChange: (e) => setNewTab(e.target.checked) }),
|
|
19382
|
+
"Open in new tab"
|
|
19383
|
+
] })
|
|
19384
|
+
] }),
|
|
19385
|
+
/* @__PURE__ */ jsxs12(DialogFooter, { children: [
|
|
19386
|
+
href && /* @__PURE__ */ jsx21(
|
|
19387
|
+
"button",
|
|
19388
|
+
{
|
|
19389
|
+
type: "button",
|
|
19390
|
+
onClick: () => {
|
|
19391
|
+
onSave("", "new-tab");
|
|
19392
|
+
onClose();
|
|
19393
|
+
},
|
|
19394
|
+
className: "mr-auto rounded-[6px] px-3 py-2 text-[13px] font-medium text-destructive transition-colors hover:bg-muted",
|
|
19395
|
+
children: "Remove link"
|
|
19396
|
+
}
|
|
19397
|
+
),
|
|
19398
|
+
/* @__PURE__ */ jsx21(
|
|
19399
|
+
"button",
|
|
19400
|
+
{
|
|
19401
|
+
type: "button",
|
|
19402
|
+
onClick: onClose,
|
|
19403
|
+
className: "rounded-[6px] px-3 py-2 text-[13px] font-medium text-foreground transition-colors hover:bg-muted",
|
|
19404
|
+
children: "Cancel"
|
|
19405
|
+
}
|
|
19406
|
+
),
|
|
19407
|
+
/* @__PURE__ */ jsx21(
|
|
19408
|
+
"button",
|
|
19409
|
+
{
|
|
19410
|
+
type: "button",
|
|
19411
|
+
onClick: save,
|
|
19412
|
+
className: "rounded-[6px] bg-bridge-primary px-3 py-2 text-[13px] font-medium text-primary-foreground transition-opacity hover:opacity-90",
|
|
19413
|
+
children: "Save"
|
|
19414
|
+
}
|
|
19415
|
+
)
|
|
19416
|
+
] })
|
|
19417
|
+
] }) });
|
|
19083
19418
|
}
|
|
19084
19419
|
function MediaStripToolbar({
|
|
19085
19420
|
entry,
|
|
19086
19421
|
index,
|
|
19087
19422
|
pending,
|
|
19088
19423
|
error,
|
|
19424
|
+
itemEditOn,
|
|
19425
|
+
onToggleItemEdit,
|
|
19089
19426
|
onSetVariant,
|
|
19090
19427
|
onSetAlign,
|
|
19091
19428
|
onSetHover,
|
|
19092
19429
|
onSetTreatment,
|
|
19093
19430
|
onResize,
|
|
19094
|
-
|
|
19095
|
-
onSetLink,
|
|
19431
|
+
onOpenLink,
|
|
19096
19432
|
onAddItem,
|
|
19097
19433
|
onRemoveItem,
|
|
19098
19434
|
onChangeImage,
|
|
@@ -19101,81 +19437,102 @@ function MediaStripToolbar({
|
|
|
19101
19437
|
}) {
|
|
19102
19438
|
const items = mediaStripItems(entry.tree);
|
|
19103
19439
|
const itemCount = items.length;
|
|
19104
|
-
const currentAlt = items[index]?.alt ?? "";
|
|
19105
|
-
const currentHref = items[index]?.href ?? "";
|
|
19106
|
-
const currentTarget = items[index]?.linkTarget === "same-tab" ? "same-tab" : "new-tab";
|
|
19107
19440
|
const slots = findMediaStripSlots(entry.tree);
|
|
19108
19441
|
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
19109
19442
|
const align = slots?.align === "left" || slots?.align === "right" ? slots.align : "center";
|
|
19110
19443
|
const hover = slots?.hover === "none" || slots?.hover === "lift" || slots?.hover === "zoom" || slots?.hover === "fade" ? slots.hover : "lift";
|
|
19111
19444
|
const treatment = slots?.treatment === "color" || slots?.treatment === "grayscale" ? slots.treatment : variant === "logos" ? "grayscale" : "color";
|
|
19112
19445
|
const sizeValue = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
19113
|
-
const
|
|
19114
|
-
const
|
|
19115
|
-
|
|
19116
|
-
gap: 6,
|
|
19117
|
-
flexWrap: "nowrap",
|
|
19118
|
-
justifyContent: "center",
|
|
19119
|
-
overflowX: "auto",
|
|
19120
|
-
WebkitOverflowScrolling: "touch",
|
|
19121
|
-
width: "100%",
|
|
19122
|
-
scrollbarWidth: "none"
|
|
19123
|
-
} : { display: "flex", gap: 6, flexWrap: "nowrap", justifyContent: "center" };
|
|
19124
|
-
return /* @__PURE__ */ jsxs11(
|
|
19446
|
+
const mobile = window.innerWidth <= 480;
|
|
19447
|
+
const gatedLabel = (label) => itemEditOn ? label : "Turn on the star to edit this image";
|
|
19448
|
+
return /* @__PURE__ */ jsx21(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs12(
|
|
19125
19449
|
"div",
|
|
19126
19450
|
{
|
|
19127
19451
|
"data-ohw-bridge": "",
|
|
19128
19452
|
"data-ohw-toolbar": "",
|
|
19129
19453
|
onMouseDown: (e) => e.stopPropagation(),
|
|
19130
|
-
|
|
19131
|
-
|
|
19132
|
-
flexDirection: "column",
|
|
19133
|
-
gap: 6,
|
|
19134
|
-
alignItems: "center",
|
|
19135
|
-
background: OHW_BLUE,
|
|
19136
|
-
padding: 8,
|
|
19137
|
-
borderRadius: 12,
|
|
19138
|
-
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
19139
|
-
pointerEvents: pending ? "none" : "auto",
|
|
19140
|
-
opacity: pending ? 0.6 : 1,
|
|
19141
|
-
maxWidth: isMobile ? "calc(100vw - 24px)" : "none"
|
|
19142
|
-
},
|
|
19454
|
+
className: cn("flex flex-col items-center gap-1.5 font-sans", pending && "pointer-events-none opacity-60"),
|
|
19455
|
+
style: { maxWidth: mobile ? "calc(100vw - 24px)" : void 0 },
|
|
19143
19456
|
children: [
|
|
19144
|
-
/* @__PURE__ */
|
|
19145
|
-
|
|
19146
|
-
|
|
19147
|
-
|
|
19148
|
-
|
|
19149
|
-
|
|
19150
|
-
|
|
19151
|
-
|
|
19152
|
-
|
|
19153
|
-
|
|
19154
|
-
|
|
19155
|
-
|
|
19156
|
-
|
|
19157
|
-
|
|
19158
|
-
|
|
19159
|
-
|
|
19160
|
-
|
|
19161
|
-
|
|
19162
|
-
|
|
19163
|
-
|
|
19164
|
-
|
|
19165
|
-
|
|
19166
|
-
|
|
19167
|
-
|
|
19168
|
-
|
|
19169
|
-
|
|
19170
|
-
|
|
19171
|
-
|
|
19172
|
-
|
|
19173
|
-
|
|
19174
|
-
|
|
19175
|
-
|
|
19457
|
+
/* @__PURE__ */ jsxs12(
|
|
19458
|
+
"div",
|
|
19459
|
+
{
|
|
19460
|
+
className: cn(
|
|
19461
|
+
"flex items-center gap-1 rounded-[10px] border border-border bg-background p-1 whitespace-nowrap",
|
|
19462
|
+
"shadow-[0px_10px_15px_-3px_rgba(0,0,0,0.1),0px_4px_6px_-4px_rgba(0,0,0,0.1)]",
|
|
19463
|
+
mobile ? "flex-wrap justify-center" : "flex-nowrap"
|
|
19464
|
+
),
|
|
19465
|
+
children: [
|
|
19466
|
+
/* @__PURE__ */ jsxs12(Tooltip, { children: [
|
|
19467
|
+
/* @__PURE__ */ jsx21(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx21(
|
|
19468
|
+
CustomToolbarButton,
|
|
19469
|
+
{
|
|
19470
|
+
type: "button",
|
|
19471
|
+
"aria-label": itemEditOn ? "Done editing this image" : "Edit this image",
|
|
19472
|
+
"aria-pressed": itemEditOn,
|
|
19473
|
+
onClick: onToggleItemEdit,
|
|
19474
|
+
className: "group size-8",
|
|
19475
|
+
children: /* @__PURE__ */ jsx21(
|
|
19476
|
+
Star,
|
|
19477
|
+
{
|
|
19478
|
+
size: 16,
|
|
19479
|
+
fill: "currentColor",
|
|
19480
|
+
strokeWidth: 0,
|
|
19481
|
+
className: cn(
|
|
19482
|
+
"transition-colors",
|
|
19483
|
+
itemEditOn ? "text-[#f59e0b] group-hover:text-[#d97706]" : "text-[#d6d3d1] group-hover:text-[#fbbf24]"
|
|
19484
|
+
),
|
|
19485
|
+
style: { pointerEvents: "none" }
|
|
19486
|
+
}
|
|
19487
|
+
)
|
|
19488
|
+
}
|
|
19489
|
+
) }),
|
|
19490
|
+
/* @__PURE__ */ jsx21(TooltipContent, { side: "bottom", sideOffset: 8, children: itemEditOn ? "Done editing this image" : "Edit this image" })
|
|
19491
|
+
] }),
|
|
19492
|
+
/* @__PURE__ */ jsx21(ToolbarSeparator, {}),
|
|
19493
|
+
/* @__PURE__ */ jsx21(ToolbarAction, { label: gatedLabel("Change image"), onClick: onChangeImage, disabled: !itemEditOn, children: /* @__PURE__ */ jsx21(ImageIcon2, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19494
|
+
/* @__PURE__ */ jsx21(ToolbarAction, { label: gatedLabel("Link"), onClick: onOpenLink, disabled: !itemEditOn, children: /* @__PURE__ */ jsx21(LinkIcon, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19495
|
+
/* @__PURE__ */ jsx21(ToolbarAction, { label: gatedLabel("Move left"), onClick: onMoveLeft, disabled: !itemEditOn || index <= 0, children: /* @__PURE__ */ jsx21(ArrowLeft2, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19496
|
+
/* @__PURE__ */ jsx21(
|
|
19497
|
+
ToolbarAction,
|
|
19498
|
+
{
|
|
19499
|
+
label: gatedLabel("Move right"),
|
|
19500
|
+
onClick: onMoveRight,
|
|
19501
|
+
disabled: !itemEditOn || index >= itemCount - 1,
|
|
19502
|
+
children: /* @__PURE__ */ jsx21(ArrowRight2, { size: 16, style: { pointerEvents: "none" } })
|
|
19503
|
+
}
|
|
19504
|
+
),
|
|
19505
|
+
/* @__PURE__ */ jsx21(ToolbarAction, { label: gatedLabel("Remove image"), onClick: onRemoveItem, disabled: !itemEditOn || itemCount <= 1, children: /* @__PURE__ */ jsx21(ImageMinus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19506
|
+
/* @__PURE__ */ jsx21(ToolbarSeparator, {}),
|
|
19507
|
+
/* @__PURE__ */ jsx21(OptionMenu, { label: "Layout", value: variant, options: VARIANTS, onChange: onSetVariant }),
|
|
19508
|
+
/* @__PURE__ */ jsx21(OptionMenu, { label: "Hover", value: hover, options: HOVERS, onChange: onSetHover }),
|
|
19509
|
+
/* @__PURE__ */ jsx21(
|
|
19510
|
+
ToolbarAction,
|
|
19511
|
+
{
|
|
19512
|
+
label: treatment === "grayscale" ? "Show in color" : "Show grayscale",
|
|
19513
|
+
active: treatment === "grayscale",
|
|
19514
|
+
onClick: () => onSetTreatment(treatment === "grayscale" ? "color" : "grayscale"),
|
|
19515
|
+
children: /* @__PURE__ */ jsx21(Palette, { size: 16, style: { pointerEvents: "none" } })
|
|
19516
|
+
}
|
|
19517
|
+
),
|
|
19518
|
+
/* @__PURE__ */ jsx21(ToolbarSeparator, {}),
|
|
19519
|
+
ALIGNS.map(({ value, label, Icon }) => /* @__PURE__ */ jsx21(ToolbarAction, { label, active: align === value, onClick: () => onSetAlign(value), children: /* @__PURE__ */ jsx21(Icon, { size: 16, style: { pointerEvents: "none" } }) }, value)),
|
|
19520
|
+
/* @__PURE__ */ jsx21(ToolbarSeparator, {}),
|
|
19521
|
+
/* @__PURE__ */ jsx21(ToolbarAction, { label: "Smaller", onClick: () => onResize(-8), children: /* @__PURE__ */ jsx21(Minus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19522
|
+
/* @__PURE__ */ jsxs12("span", { className: "min-w-[40px] text-center text-xs tabular-nums text-muted-foreground", children: [
|
|
19523
|
+
sizeValue,
|
|
19524
|
+
"px"
|
|
19525
|
+
] }),
|
|
19526
|
+
/* @__PURE__ */ jsx21(ToolbarAction, { label: "Larger", onClick: () => onResize(8), children: /* @__PURE__ */ jsx21(Plus2, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19527
|
+
/* @__PURE__ */ jsx21(ToolbarSeparator, {}),
|
|
19528
|
+
/* @__PURE__ */ jsx21(ToolbarAction, { label: "Add image", onClick: onAddItem, children: /* @__PURE__ */ jsx21(ImagePlus, { size: 16, style: { pointerEvents: "none" } }) })
|
|
19529
|
+
]
|
|
19530
|
+
}
|
|
19531
|
+
),
|
|
19532
|
+
error && /* @__PURE__ */ jsx21("div", { className: "max-w-[260px] rounded-md bg-background px-2 py-1 text-center text-[11px] text-destructive shadow-sm", children: error })
|
|
19176
19533
|
]
|
|
19177
19534
|
}
|
|
19178
|
-
);
|
|
19535
|
+
) });
|
|
19179
19536
|
}
|
|
19180
19537
|
function findMediaStripSlots(tree) {
|
|
19181
19538
|
const stack = tree.rows.flatMap((row) => row.blocks);
|
|
@@ -19194,31 +19551,23 @@ function AiMediaStripOverlay({
|
|
|
19194
19551
|
}) {
|
|
19195
19552
|
const [hover, setHover] = useState8(null);
|
|
19196
19553
|
const [active, setActive] = useState8(null);
|
|
19554
|
+
const [itemEditOn, setItemEditOn] = useState8(false);
|
|
19555
|
+
const [linkOpen, setLinkOpen] = useState8(false);
|
|
19197
19556
|
const [pending, setPending] = useState8(false);
|
|
19198
19557
|
const [error, setError] = useState8(null);
|
|
19199
19558
|
const activeRef = useRef5(null);
|
|
19200
19559
|
activeRef.current = active;
|
|
19560
|
+
const linkOpenRef = useRef5(false);
|
|
19561
|
+
linkOpenRef.current = linkOpen;
|
|
19201
19562
|
useEffect6(() => {
|
|
19202
19563
|
const onMove = (e) => {
|
|
19564
|
+
const ref = itemRefFromTarget(e.target);
|
|
19203
19565
|
const t = e.target;
|
|
19204
|
-
|
|
19205
|
-
|
|
19206
|
-
|
|
19207
|
-
|
|
19208
|
-
|
|
19209
|
-
if (!itemEl) {
|
|
19210
|
-
setHover(null);
|
|
19211
|
-
return;
|
|
19212
|
-
}
|
|
19213
|
-
const sectionEl = itemEl.closest("[data-ohw-section]");
|
|
19214
|
-
const unit = sectionEl ? movableUnit(sectionEl) : null;
|
|
19215
|
-
const sectionId = unit ? instanceIdOf(unit) || null : null;
|
|
19216
|
-
const index = Number(itemEl.dataset.ohwMediaStripIndex);
|
|
19217
|
-
if (!sectionId || Number.isNaN(index)) {
|
|
19218
|
-
setHover(null);
|
|
19219
|
-
return;
|
|
19220
|
-
}
|
|
19221
|
-
setHover({ sectionId, index });
|
|
19566
|
+
const overEditable = Boolean(t?.closest?.("[data-ohw-editable]"));
|
|
19567
|
+
setHover((prev) => {
|
|
19568
|
+
const next = ref && !overEditable ? ref : null;
|
|
19569
|
+
return sameRef(prev, next) ? prev : next;
|
|
19570
|
+
});
|
|
19222
19571
|
};
|
|
19223
19572
|
const onLeave = () => setHover(null);
|
|
19224
19573
|
document.addEventListener("mousemove", onMove, { passive: true });
|
|
@@ -19230,23 +19579,25 @@ function AiMediaStripOverlay({
|
|
|
19230
19579
|
}, []);
|
|
19231
19580
|
useEffect6(() => {
|
|
19232
19581
|
const onClick = (e) => {
|
|
19233
|
-
const current = activeRef.current;
|
|
19234
|
-
if (!current) return;
|
|
19235
19582
|
const t = e.target;
|
|
19236
|
-
if (!(t instanceof
|
|
19237
|
-
if (t.closest(
|
|
19238
|
-
const
|
|
19239
|
-
if (
|
|
19240
|
-
|
|
19583
|
+
if (!(t instanceof Element)) return;
|
|
19584
|
+
if (t.closest(CHROME_SELECTOR)) return;
|
|
19585
|
+
const ref = itemRefFromTarget(t);
|
|
19586
|
+
if (sameRef(activeRef.current, ref)) return;
|
|
19587
|
+
if (ref) clearInteractionChromeRef.current();
|
|
19588
|
+
setItemEditOn(false);
|
|
19241
19589
|
setError(null);
|
|
19590
|
+
setActive(ref);
|
|
19242
19591
|
};
|
|
19243
19592
|
document.addEventListener("click", onClick, true);
|
|
19244
19593
|
return () => document.removeEventListener("click", onClick, true);
|
|
19245
|
-
}, []);
|
|
19594
|
+
}, [clearInteractionChromeRef]);
|
|
19246
19595
|
useEffect6(() => {
|
|
19247
19596
|
const onBlur = () => {
|
|
19248
19597
|
if (!activeRef.current) return;
|
|
19249
19598
|
setActive(null);
|
|
19599
|
+
setItemEditOn(false);
|
|
19600
|
+
setLinkOpen(false);
|
|
19250
19601
|
setError(null);
|
|
19251
19602
|
};
|
|
19252
19603
|
window.addEventListener("blur", onBlur);
|
|
@@ -19256,7 +19607,10 @@ function AiMediaStripOverlay({
|
|
|
19256
19607
|
const onKeyDown = (e) => {
|
|
19257
19608
|
if (e.key !== "Escape") return;
|
|
19258
19609
|
if (!activeRef.current) return;
|
|
19610
|
+
if (linkOpenRef.current) return;
|
|
19611
|
+
if (document.querySelector('[data-ohw-more-menu][data-state="open"]')) return;
|
|
19259
19612
|
setActive(null);
|
|
19613
|
+
setItemEditOn(false);
|
|
19260
19614
|
setError(null);
|
|
19261
19615
|
};
|
|
19262
19616
|
document.addEventListener("keydown", onKeyDown);
|
|
@@ -19290,137 +19644,133 @@ function AiMediaStripOverlay({
|
|
|
19290
19644
|
tree: nextTree,
|
|
19291
19645
|
label: entry.label,
|
|
19292
19646
|
media: extraMedia ? { ...entry.media, ...extraMedia } : entry.media,
|
|
19293
|
-
...entry.brand ? { brand: entry.brand } : {}
|
|
19647
|
+
...entry.brand ? { brand: entry.brand } : {},
|
|
19648
|
+
// The user is already looking at the strip they just edited — recentering the viewport
|
|
19649
|
+
// on every edit reads as the section jumping around.
|
|
19650
|
+
skipScrollIntoView: true
|
|
19294
19651
|
});
|
|
19295
19652
|
return true;
|
|
19296
19653
|
},
|
|
19297
19654
|
[findEntry, postToParent2, applyTreeLocalRef]
|
|
19298
19655
|
);
|
|
19299
19656
|
const activeEntry = active ? findEntry(active.sectionId) : null;
|
|
19300
|
-
const hoverHandleRect = useLiveItemRect(!active && hover ? hover : null);
|
|
19301
19657
|
const activeItemRect = useLiveItemRect(active);
|
|
19302
|
-
const
|
|
19303
|
-
const
|
|
19304
|
-
|
|
19305
|
-
|
|
19306
|
-
|
|
19307
|
-
|
|
19308
|
-
|
|
19309
|
-
|
|
19310
|
-
|
|
19311
|
-
|
|
19312
|
-
|
|
19313
|
-
|
|
19314
|
-
|
|
19315
|
-
|
|
19316
|
-
|
|
19317
|
-
|
|
19318
|
-
|
|
19319
|
-
|
|
19320
|
-
|
|
19321
|
-
|
|
19322
|
-
|
|
19323
|
-
|
|
19324
|
-
|
|
19325
|
-
|
|
19326
|
-
|
|
19327
|
-
|
|
19328
|
-
|
|
19329
|
-
|
|
19330
|
-
|
|
19331
|
-
|
|
19332
|
-
|
|
19333
|
-
|
|
19334
|
-
|
|
19335
|
-
|
|
19336
|
-
activeItemRect && active && activeEntry && /* @__PURE__ */ jsx20(
|
|
19337
|
-
ItemInteractionLayer,
|
|
19338
|
-
{
|
|
19339
|
-
rect: activeItemRect,
|
|
19340
|
-
state: toolbarState,
|
|
19341
|
-
toolbar: /* @__PURE__ */ jsx20(
|
|
19342
|
-
MediaStripToolbar,
|
|
19343
|
-
{
|
|
19344
|
-
entry: activeEntry,
|
|
19345
|
-
index: active.index,
|
|
19346
|
-
pending,
|
|
19347
|
-
error,
|
|
19348
|
-
onSetVariant: (variant) => runMutation(active.sectionId, (tree) => setMediaStripVariant(tree, variant)),
|
|
19349
|
-
onSetAlign: (align) => runMutation(active.sectionId, (tree) => setMediaStripAlign(tree, align)),
|
|
19350
|
-
onSetHover: (hoverPreset) => runMutation(active.sectionId, (tree) => setMediaStripHover(tree, hoverPreset)),
|
|
19351
|
-
onSetTreatment: (treatment) => runMutation(active.sectionId, (tree) => setMediaStripTreatment(tree, treatment)),
|
|
19352
|
-
onResize: (delta) => {
|
|
19353
|
-
const slots = findMediaStripSlots(activeEntry.tree);
|
|
19354
|
-
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
19355
|
-
const current = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
19356
|
-
void runMutation(active.sectionId, (tree) => setMediaStripSizing(tree, current + delta));
|
|
19357
|
-
},
|
|
19358
|
-
onSetAlt: (alt) => {
|
|
19359
|
-
void runMutation(active.sectionId, (tree) => setMediaStripItemAlt(tree, active.index, alt));
|
|
19360
|
-
},
|
|
19361
|
-
onSetLink: (href, linkTarget) => {
|
|
19658
|
+
const activeStripRect = useLiveItemRect(active, true);
|
|
19659
|
+
const hoverRect = useLiveItemRect(hover && !sameRef(hover, active) ? hover : null);
|
|
19660
|
+
const activeItems = activeEntry ? mediaStripItems(activeEntry.tree) : [];
|
|
19661
|
+
const activeItem = active ? activeItems[active.index] : void 0;
|
|
19662
|
+
const activeHref = activeItem?.href ?? "";
|
|
19663
|
+
const activeTarget = activeItem?.linkTarget === "same-tab" ? "same-tab" : "new-tab";
|
|
19664
|
+
return /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
19665
|
+
hoverRect && /* @__PURE__ */ jsx21(ItemInteractionLayer, { rect: hoverRect, state: "hover" }),
|
|
19666
|
+
activeItemRect && activeStripRect && active && activeEntry && /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
19667
|
+
/* @__PURE__ */ jsx21(ItemInteractionLayer, { rect: activeItemRect, state: "active-top" }),
|
|
19668
|
+
/* @__PURE__ */ jsx21(StripToolbarSlot, { stripRect: activeStripRect, children: /* @__PURE__ */ jsx21(
|
|
19669
|
+
MediaStripToolbar,
|
|
19670
|
+
{
|
|
19671
|
+
entry: activeEntry,
|
|
19672
|
+
index: active.index,
|
|
19673
|
+
pending,
|
|
19674
|
+
error,
|
|
19675
|
+
itemEditOn,
|
|
19676
|
+
onToggleItemEdit: () => setItemEditOn((on) => !on),
|
|
19677
|
+
onSetVariant: (variant) => runMutation(active.sectionId, (tree) => setMediaStripVariant(tree, variant)),
|
|
19678
|
+
onSetAlign: (align) => runMutation(active.sectionId, (tree) => setMediaStripAlign(tree, align)),
|
|
19679
|
+
onSetHover: (hoverPreset) => runMutation(active.sectionId, (tree) => setMediaStripHover(tree, hoverPreset)),
|
|
19680
|
+
onSetTreatment: (treatment) => runMutation(active.sectionId, (tree) => setMediaStripTreatment(tree, treatment)),
|
|
19681
|
+
onResize: (delta) => {
|
|
19682
|
+
const slots = findMediaStripSlots(activeEntry.tree);
|
|
19683
|
+
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
19684
|
+
const current = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
19685
|
+
void runMutation(active.sectionId, (tree) => setMediaStripSizing(tree, current + delta));
|
|
19686
|
+
},
|
|
19687
|
+
onOpenLink: () => setLinkOpen(true),
|
|
19688
|
+
onAddItem: () => {
|
|
19689
|
+
void requestAssetPick(postToParent2).then((picked) => {
|
|
19690
|
+
if (!picked) return;
|
|
19691
|
+
const item = { assetId: picked.assetId, alt: "Logo" };
|
|
19362
19692
|
void runMutation(
|
|
19363
19693
|
active.sectionId,
|
|
19364
|
-
(tree) =>
|
|
19365
|
-
|
|
19366
|
-
|
|
19367
|
-
|
|
19368
|
-
void requestAssetPick(postToParent2).then((picked) => {
|
|
19369
|
-
if (!picked) return;
|
|
19370
|
-
const item = { assetId: picked.assetId, alt: "Logo" };
|
|
19371
|
-
void runMutation(
|
|
19372
|
-
active.sectionId,
|
|
19373
|
-
(tree) => addMediaStripItem(tree, item, active.index),
|
|
19374
|
-
{ [picked.assetId]: picked.url }
|
|
19375
|
-
).then((applied) => {
|
|
19376
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19377
|
-
});
|
|
19378
|
-
});
|
|
19379
|
-
},
|
|
19380
|
-
onChangeImage: () => {
|
|
19381
|
-
void requestAssetPick(postToParent2).then((picked) => {
|
|
19382
|
-
if (!picked) return;
|
|
19383
|
-
void runMutation(
|
|
19384
|
-
active.sectionId,
|
|
19385
|
-
(tree) => setMediaStripItemAsset(tree, active.index, picked.assetId),
|
|
19386
|
-
{ [picked.assetId]: picked.url }
|
|
19387
|
-
);
|
|
19694
|
+
(tree) => addMediaStripItem(tree, item, active.index),
|
|
19695
|
+
{ [picked.assetId]: picked.url }
|
|
19696
|
+
).then((applied) => {
|
|
19697
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19388
19698
|
});
|
|
19389
|
-
}
|
|
19390
|
-
|
|
19391
|
-
|
|
19392
|
-
|
|
19393
|
-
|
|
19394
|
-
|
|
19395
|
-
|
|
19396
|
-
|
|
19397
|
-
|
|
19398
|
-
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, -1)).then(
|
|
19399
|
-
(applied) => {
|
|
19400
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index - 1 });
|
|
19401
|
-
}
|
|
19402
|
-
);
|
|
19403
|
-
},
|
|
19404
|
-
onMoveRight: () => {
|
|
19405
|
-
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, 1)).then(
|
|
19406
|
-
(applied) => {
|
|
19407
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19408
|
-
}
|
|
19699
|
+
});
|
|
19700
|
+
},
|
|
19701
|
+
onChangeImage: () => {
|
|
19702
|
+
void requestAssetPick(postToParent2).then((picked) => {
|
|
19703
|
+
if (!picked) return;
|
|
19704
|
+
void runMutation(
|
|
19705
|
+
active.sectionId,
|
|
19706
|
+
(tree) => setMediaStripItemAsset(tree, active.index, picked.assetId),
|
|
19707
|
+
{ [picked.assetId]: picked.url }
|
|
19409
19708
|
);
|
|
19410
|
-
}
|
|
19709
|
+
});
|
|
19710
|
+
},
|
|
19711
|
+
onRemoveItem: () => {
|
|
19712
|
+
void runMutation(active.sectionId, (tree) => removeMediaStripItem(tree, active.index)).then(
|
|
19713
|
+
(applied) => {
|
|
19714
|
+
if (applied) setActive(null);
|
|
19715
|
+
}
|
|
19716
|
+
);
|
|
19717
|
+
},
|
|
19718
|
+
onMoveLeft: () => {
|
|
19719
|
+
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, -1)).then(
|
|
19720
|
+
(applied) => {
|
|
19721
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index - 1 });
|
|
19722
|
+
}
|
|
19723
|
+
);
|
|
19724
|
+
},
|
|
19725
|
+
onMoveRight: () => {
|
|
19726
|
+
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, 1)).then(
|
|
19727
|
+
(applied) => {
|
|
19728
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19729
|
+
}
|
|
19730
|
+
);
|
|
19411
19731
|
}
|
|
19412
|
-
|
|
19413
|
-
}
|
|
19414
|
-
|
|
19732
|
+
}
|
|
19733
|
+
) }),
|
|
19734
|
+
/* @__PURE__ */ jsx21(
|
|
19735
|
+
"div",
|
|
19736
|
+
{
|
|
19737
|
+
"data-ohw-bridge": "",
|
|
19738
|
+
"data-ohw-item-interaction": "",
|
|
19739
|
+
"aria-hidden": true,
|
|
19740
|
+
className: "pointer-events-none fixed rounded-[4px] px-[7px] py-[3px] font-sans text-[11px] font-medium leading-none text-primary-foreground whitespace-nowrap",
|
|
19741
|
+
style: {
|
|
19742
|
+
top: activeItemRect.top + activeItemRect.height + 10,
|
|
19743
|
+
left: activeItemRect.left - 5,
|
|
19744
|
+
background: PRIMARY3,
|
|
19745
|
+
zIndex: 2147483644
|
|
19746
|
+
},
|
|
19747
|
+
children: "Media item"
|
|
19748
|
+
}
|
|
19749
|
+
),
|
|
19750
|
+
linkOpen && /* @__PURE__ */ jsx21(
|
|
19751
|
+
LinkModal,
|
|
19752
|
+
{
|
|
19753
|
+
href: activeHref,
|
|
19754
|
+
linkTarget: activeTarget,
|
|
19755
|
+
onClose: () => setLinkOpen(false),
|
|
19756
|
+
onSave: (href, linkTarget) => {
|
|
19757
|
+
void runMutation(
|
|
19758
|
+
active.sectionId,
|
|
19759
|
+
(tree) => setMediaStripItemLink(tree, active.index, href ? { href, linkTarget } : {})
|
|
19760
|
+
);
|
|
19761
|
+
}
|
|
19762
|
+
}
|
|
19763
|
+
)
|
|
19764
|
+
] })
|
|
19415
19765
|
] });
|
|
19416
19766
|
}
|
|
19417
19767
|
|
|
19418
19768
|
// src/ui/ai-section/AiPricingCardOverlay.tsx
|
|
19419
|
-
import { useCallback as useCallback4, useEffect as useEffect7, useLayoutEffect as
|
|
19420
|
-
import { Check as
|
|
19421
|
-
import { Fragment as Fragment8, jsx as
|
|
19769
|
+
import { useCallback as useCallback4, useEffect as useEffect7, useLayoutEffect as useLayoutEffect5, useRef as useRef6, useState as useState9 } from "react";
|
|
19770
|
+
import { Check as Check3, ChevronDown as ChevronDown4, Minus as Minus2, Plus as Plus3, Star as Star2 } from "lucide-react";
|
|
19771
|
+
import { Fragment as Fragment8, jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
19422
19772
|
var PRIMARY4 = "var(--ohw-primary, #0885FE)";
|
|
19423
|
-
var
|
|
19773
|
+
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]";
|
|
19424
19774
|
function findPricingCardElement(sectionId, index) {
|
|
19425
19775
|
const sectionEl = findByInstanceId(sectionId);
|
|
19426
19776
|
if (!sectionEl) return null;
|
|
@@ -19432,7 +19782,7 @@ function findPricingCardElement(sectionId, index) {
|
|
|
19432
19782
|
}
|
|
19433
19783
|
function cardRefFromTarget(target) {
|
|
19434
19784
|
if (!(target instanceof Element)) return null;
|
|
19435
|
-
if (target.closest(
|
|
19785
|
+
if (target.closest(CHROME_SELECTOR2)) return null;
|
|
19436
19786
|
const cardEl = target.closest("[data-ohw-pricing-card]");
|
|
19437
19787
|
if (!cardEl) return null;
|
|
19438
19788
|
const sectionEl = cardEl.closest("[data-ohw-section]");
|
|
@@ -19442,21 +19792,21 @@ function cardRefFromTarget(target) {
|
|
|
19442
19792
|
if (!sectionId || Number.isNaN(index)) return null;
|
|
19443
19793
|
return { sectionId, index };
|
|
19444
19794
|
}
|
|
19445
|
-
function
|
|
19795
|
+
function sameRef2(a, b) {
|
|
19446
19796
|
return a?.sectionId === b?.sectionId && a?.index === b?.index;
|
|
19447
19797
|
}
|
|
19448
|
-
function
|
|
19798
|
+
function rectOf2(el) {
|
|
19449
19799
|
if (!el) return null;
|
|
19450
19800
|
const r2 = el.getBoundingClientRect();
|
|
19451
19801
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
19452
19802
|
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
19453
19803
|
}
|
|
19454
19804
|
function readRect3(ref) {
|
|
19455
|
-
return
|
|
19805
|
+
return rectOf2(ref && findPricingCardElement(ref.sectionId, ref.index));
|
|
19456
19806
|
}
|
|
19457
19807
|
function readGridRect(ref) {
|
|
19458
19808
|
const card = ref && findPricingCardElement(ref.sectionId, ref.index);
|
|
19459
|
-
return
|
|
19809
|
+
return rectOf2(card?.closest("[data-ohw-pricing-collection]") ?? card);
|
|
19460
19810
|
}
|
|
19461
19811
|
function useLiveCardRect(ref, grid = false) {
|
|
19462
19812
|
const [rect, setRect] = useState9(null);
|
|
@@ -19486,19 +19836,19 @@ function useLiveCardRect(ref, grid = false) {
|
|
|
19486
19836
|
}
|
|
19487
19837
|
var TOOLBAR_GRID_GAP = 52;
|
|
19488
19838
|
var TOOLBAR_GRID_GAP_MOBILE = 42;
|
|
19489
|
-
var
|
|
19839
|
+
var TOOLBAR_EDGE_MARGIN3 = 4;
|
|
19490
19840
|
function GridToolbarSlot({ gridRect, children }) {
|
|
19491
19841
|
const slotRef = useRef6(null);
|
|
19492
19842
|
const [shift, setShift] = useState9(0);
|
|
19493
19843
|
const centerX = gridRect.left + gridRect.width / 2;
|
|
19494
|
-
|
|
19844
|
+
useLayoutEffect5(() => {
|
|
19495
19845
|
const slot = slotRef.current;
|
|
19496
19846
|
if (!slot) return;
|
|
19497
19847
|
const clamp = () => {
|
|
19498
19848
|
const w = slot.offsetWidth;
|
|
19499
19849
|
if (w <= 0) return;
|
|
19500
19850
|
const half = w / 2;
|
|
19501
|
-
const clamped = Math.max(
|
|
19851
|
+
const clamped = Math.max(TOOLBAR_EDGE_MARGIN3 + half, Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN3 - half));
|
|
19502
19852
|
setShift((prev) => Math.abs(prev - (clamped - centerX)) < 0.5 ? prev : clamped - centerX);
|
|
19503
19853
|
};
|
|
19504
19854
|
clamp();
|
|
@@ -19507,7 +19857,7 @@ function GridToolbarSlot({ gridRect, children }) {
|
|
|
19507
19857
|
return () => ro.disconnect();
|
|
19508
19858
|
}, [centerX, children]);
|
|
19509
19859
|
const mobile = window.innerWidth <= 480;
|
|
19510
|
-
return /* @__PURE__ */
|
|
19860
|
+
return /* @__PURE__ */ jsx22(
|
|
19511
19861
|
"div",
|
|
19512
19862
|
{
|
|
19513
19863
|
ref: slotRef,
|
|
@@ -19542,7 +19892,7 @@ function requestValidateTree2(postToParent2, tree) {
|
|
|
19542
19892
|
});
|
|
19543
19893
|
}
|
|
19544
19894
|
function StyleSwatch({ style }) {
|
|
19545
|
-
return /* @__PURE__ */
|
|
19895
|
+
return /* @__PURE__ */ jsx22(
|
|
19546
19896
|
"span",
|
|
19547
19897
|
{
|
|
19548
19898
|
"aria-hidden": true,
|
|
@@ -19556,35 +19906,35 @@ function StyleSwatch({ style }) {
|
|
|
19556
19906
|
);
|
|
19557
19907
|
}
|
|
19558
19908
|
function ButtonGlyph() {
|
|
19559
|
-
return /* @__PURE__ */
|
|
19560
|
-
/* @__PURE__ */
|
|
19561
|
-
/* @__PURE__ */
|
|
19909
|
+
return /* @__PURE__ */ jsxs13("svg", { width: "18", height: "12", viewBox: "0 0 18 12", fill: "none", "aria-hidden": true, style: { pointerEvents: "none" }, children: [
|
|
19910
|
+
/* @__PURE__ */ jsx22("rect", { x: "0.75", y: "0.75", width: "16.5", height: "10.5", rx: "3", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
19911
|
+
/* @__PURE__ */ jsx22("path", { d: "M5.5 6H12.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
|
|
19562
19912
|
] });
|
|
19563
19913
|
}
|
|
19564
19914
|
function FeatureGlyph({ mode }) {
|
|
19565
|
-
return /* @__PURE__ */
|
|
19566
|
-
/* @__PURE__ */
|
|
19567
|
-
/* @__PURE__ */
|
|
19568
|
-
/* @__PURE__ */
|
|
19569
|
-
/* @__PURE__ */
|
|
19570
|
-
/* @__PURE__ */
|
|
19571
|
-
mode === "add" && /* @__PURE__ */
|
|
19915
|
+
return /* @__PURE__ */ jsxs13("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "none", "aria-hidden": true, style: { pointerEvents: "none" }, children: [
|
|
19916
|
+
/* @__PURE__ */ jsx22("circle", { cx: "8", cy: "8", r: "7.25", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
19917
|
+
/* @__PURE__ */ jsx22("path", { d: "M5 8.2L7.2 10.3L11 6", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
19918
|
+
/* @__PURE__ */ jsx22("circle", { cx: "13.5", cy: "13.5", r: "4.25", fill: "var(--ohw-background, #ffffff)", stroke: "var(--ohw-background, #ffffff)", strokeWidth: "1" }),
|
|
19919
|
+
/* @__PURE__ */ jsx22("circle", { cx: "13.5", cy: "13.5", r: "3.75", fill: "var(--ohw-background, #ffffff)", stroke: PRIMARY4, strokeWidth: "1" }),
|
|
19920
|
+
/* @__PURE__ */ jsx22("path", { d: "M11.5 13.5H15.5", stroke: PRIMARY4, strokeWidth: "1.5", strokeLinecap: "round" }),
|
|
19921
|
+
mode === "add" && /* @__PURE__ */ jsx22("path", { d: "M13.5 11.5V15.5", stroke: PRIMARY4, strokeWidth: "1.5", strokeLinecap: "round" })
|
|
19572
19922
|
] });
|
|
19573
19923
|
}
|
|
19574
|
-
function
|
|
19924
|
+
function ToolbarAction2({
|
|
19575
19925
|
label,
|
|
19576
19926
|
onClick,
|
|
19577
19927
|
disabled = false,
|
|
19578
19928
|
children
|
|
19579
19929
|
}) {
|
|
19580
|
-
const button = /* @__PURE__ */
|
|
19581
|
-
return /* @__PURE__ */
|
|
19582
|
-
/* @__PURE__ */
|
|
19583
|
-
/* @__PURE__ */
|
|
19930
|
+
const button = /* @__PURE__ */ jsx22(CustomToolbarButton, { type: "button", "aria-label": label, disabled, onClick, className: "size-8", children });
|
|
19931
|
+
return /* @__PURE__ */ jsxs13(Tooltip, { children: [
|
|
19932
|
+
/* @__PURE__ */ jsx22(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ jsx22("span", { className: "inline-flex", children: button }) : button }),
|
|
19933
|
+
/* @__PURE__ */ jsx22(TooltipContent, { side: "bottom", sideOffset: 8, children: label })
|
|
19584
19934
|
] });
|
|
19585
19935
|
}
|
|
19586
|
-
function
|
|
19587
|
-
return /* @__PURE__ */
|
|
19936
|
+
function ToolbarSeparator2() {
|
|
19937
|
+
return /* @__PURE__ */ jsx22("span", { "aria-hidden": true, className: "mx-0.5 block h-6 w-px shrink-0 bg-border" });
|
|
19588
19938
|
}
|
|
19589
19939
|
function CardStyleMenu({
|
|
19590
19940
|
value,
|
|
@@ -19592,7 +19942,7 @@ function CardStyleMenu({
|
|
|
19592
19942
|
disabled = false
|
|
19593
19943
|
}) {
|
|
19594
19944
|
const current = PRICING_CARD_STYLES.find((s) => s.value === value) ?? PRICING_CARD_STYLES[0];
|
|
19595
|
-
const trigger = /* @__PURE__ */
|
|
19945
|
+
const trigger = /* @__PURE__ */ jsxs13(
|
|
19596
19946
|
"button",
|
|
19597
19947
|
{
|
|
19598
19948
|
type: "button",
|
|
@@ -19603,28 +19953,28 @@ function CardStyleMenu({
|
|
|
19603
19953
|
disabled && "cursor-not-allowed opacity-40 hover:bg-transparent"
|
|
19604
19954
|
),
|
|
19605
19955
|
children: [
|
|
19606
|
-
/* @__PURE__ */
|
|
19607
|
-
/* @__PURE__ */
|
|
19608
|
-
/* @__PURE__ */
|
|
19956
|
+
/* @__PURE__ */ jsx22(StyleSwatch, { style: current.value }),
|
|
19957
|
+
/* @__PURE__ */ jsx22("span", { className: "flex-1 text-left", children: current.label }),
|
|
19958
|
+
/* @__PURE__ */ jsx22(ChevronDown4, { size: 16, style: { pointerEvents: "none" } })
|
|
19609
19959
|
]
|
|
19610
19960
|
}
|
|
19611
19961
|
);
|
|
19612
19962
|
if (disabled) {
|
|
19613
|
-
return /* @__PURE__ */
|
|
19614
|
-
/* @__PURE__ */
|
|
19615
|
-
/* @__PURE__ */
|
|
19616
|
-
/* @__PURE__ */
|
|
19617
|
-
/* @__PURE__ */
|
|
19963
|
+
return /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19964
|
+
/* @__PURE__ */ jsx22("span", { className: "text-xs text-muted-foreground opacity-50", children: "Card style" }),
|
|
19965
|
+
/* @__PURE__ */ jsxs13(Tooltip, { children: [
|
|
19966
|
+
/* @__PURE__ */ jsx22(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx22("span", { className: "inline-flex", children: trigger }) }),
|
|
19967
|
+
/* @__PURE__ */ jsx22(TooltipContent, { side: "bottom", sideOffset: 8, children: "Mark as featured to edit card style" })
|
|
19618
19968
|
] })
|
|
19619
19969
|
] });
|
|
19620
19970
|
}
|
|
19621
|
-
return /* @__PURE__ */
|
|
19622
|
-
/* @__PURE__ */
|
|
19623
|
-
/* @__PURE__ */
|
|
19624
|
-
/* @__PURE__ */
|
|
19625
|
-
/* @__PURE__ */
|
|
19971
|
+
return /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19972
|
+
/* @__PURE__ */ jsx22("span", { className: "text-xs text-muted-foreground", children: "Card style" }),
|
|
19973
|
+
/* @__PURE__ */ jsxs13(DropdownMenu, { modal: false, children: [
|
|
19974
|
+
/* @__PURE__ */ jsx22(DropdownMenuTrigger, { asChild: true, children: trigger }),
|
|
19975
|
+
/* @__PURE__ */ jsx22(DropdownMenuContent, { align: "end", sideOffset: 8, className: "w-[152px] min-w-[152px] p-1", children: PRICING_CARD_STYLES.map((style) => {
|
|
19626
19976
|
const selected = style.value === value;
|
|
19627
|
-
return /* @__PURE__ */
|
|
19977
|
+
return /* @__PURE__ */ jsxs13(
|
|
19628
19978
|
DropdownMenuItem,
|
|
19629
19979
|
{
|
|
19630
19980
|
role: "menuitemradio",
|
|
@@ -19632,9 +19982,9 @@ function CardStyleMenu({
|
|
|
19632
19982
|
onSelect: () => onChange(style.value),
|
|
19633
19983
|
className: cn("grid grid-cols-[18px_1fr_16px] gap-2 py-2 pl-2 pr-2 text-[13px]", selected && "bg-muted"),
|
|
19634
19984
|
children: [
|
|
19635
|
-
/* @__PURE__ */
|
|
19636
|
-
/* @__PURE__ */
|
|
19637
|
-
selected && /* @__PURE__ */
|
|
19985
|
+
/* @__PURE__ */ jsx22(StyleSwatch, { style: style.value }),
|
|
19986
|
+
/* @__PURE__ */ jsx22("span", { children: style.label }),
|
|
19987
|
+
selected && /* @__PURE__ */ jsx22(Check3, { size: 16, className: "text-bridge-primary" })
|
|
19638
19988
|
]
|
|
19639
19989
|
},
|
|
19640
19990
|
style.value
|
|
@@ -19664,7 +20014,7 @@ function PricingCardToolbar({
|
|
|
19664
20014
|
const style = pricingCardStyle(entry.tree, index);
|
|
19665
20015
|
const featuredTag = pricingCardFeaturedTag(entry.tree, index);
|
|
19666
20016
|
const mobile = window.innerWidth <= 480;
|
|
19667
|
-
return /* @__PURE__ */
|
|
20017
|
+
return /* @__PURE__ */ jsx22(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs13(
|
|
19668
20018
|
"div",
|
|
19669
20019
|
{
|
|
19670
20020
|
"data-ohw-bridge": "",
|
|
@@ -19676,7 +20026,7 @@ function PricingCardToolbar({
|
|
|
19676
20026
|
),
|
|
19677
20027
|
style: { maxWidth: mobile ? "calc(100vw - 24px)" : void 0 },
|
|
19678
20028
|
children: [
|
|
19679
|
-
/* @__PURE__ */
|
|
20029
|
+
/* @__PURE__ */ jsxs13(
|
|
19680
20030
|
"div",
|
|
19681
20031
|
{
|
|
19682
20032
|
className: cn(
|
|
@@ -19685,8 +20035,8 @@ function PricingCardToolbar({
|
|
|
19685
20035
|
mobile ? "flex-wrap justify-center" : "flex-nowrap"
|
|
19686
20036
|
),
|
|
19687
20037
|
children: [
|
|
19688
|
-
/* @__PURE__ */
|
|
19689
|
-
/* @__PURE__ */
|
|
20038
|
+
/* @__PURE__ */ jsxs13(Tooltip, { children: [
|
|
20039
|
+
/* @__PURE__ */ jsx22(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx22(
|
|
19690
20040
|
CustomToolbarButton,
|
|
19691
20041
|
{
|
|
19692
20042
|
type: "button",
|
|
@@ -19694,7 +20044,7 @@ function PricingCardToolbar({
|
|
|
19694
20044
|
"aria-pressed": featuredTag,
|
|
19695
20045
|
onClick: () => onSetFeaturedTag(!featuredTag),
|
|
19696
20046
|
className: "group size-8",
|
|
19697
|
-
children: /* @__PURE__ */
|
|
20047
|
+
children: /* @__PURE__ */ jsx22(
|
|
19698
20048
|
Star2,
|
|
19699
20049
|
{
|
|
19700
20050
|
size: 16,
|
|
@@ -19709,25 +20059,25 @@ function PricingCardToolbar({
|
|
|
19709
20059
|
)
|
|
19710
20060
|
}
|
|
19711
20061
|
) }),
|
|
19712
|
-
/* @__PURE__ */
|
|
20062
|
+
/* @__PURE__ */ jsx22(TooltipContent, { side: "bottom", sideOffset: 8, children: featuredTag ? "Unmark featured" : "Mark as featured" })
|
|
19713
20063
|
] }),
|
|
19714
|
-
/* @__PURE__ */
|
|
19715
|
-
/* @__PURE__ */
|
|
19716
|
-
/* @__PURE__ */
|
|
19717
|
-
/* @__PURE__ */
|
|
19718
|
-
/* @__PURE__ */
|
|
19719
|
-
/* @__PURE__ */
|
|
19720
|
-
/* @__PURE__ */
|
|
20064
|
+
/* @__PURE__ */ jsx22(ToolbarSeparator2, {}),
|
|
20065
|
+
/* @__PURE__ */ jsx22(CardStyleMenu, { value: style, onChange: onSetStyle, disabled: !featuredTag }),
|
|
20066
|
+
/* @__PURE__ */ jsx22(ToolbarSeparator2, {}),
|
|
20067
|
+
/* @__PURE__ */ jsx22(ToolbarAction2, { label: "Add button", onClick: onAddButton, disabled: buttonCount >= 2, children: /* @__PURE__ */ jsx22(ButtonGlyph, {}) }),
|
|
20068
|
+
/* @__PURE__ */ jsx22(ToolbarAction2, { label: "Remove button", onClick: onRemoveButton, disabled: buttonCount === 0, children: /* @__PURE__ */ jsxs13("span", { className: "relative inline-flex", children: [
|
|
20069
|
+
/* @__PURE__ */ jsx22(ButtonGlyph, {}),
|
|
20070
|
+
/* @__PURE__ */ jsx22(Minus2, { size: 10, strokeWidth: 2.5, className: "absolute -right-1.5 -top-1.5 rounded-full bg-background text-bridge-primary" })
|
|
19721
20071
|
] }) }),
|
|
19722
|
-
/* @__PURE__ */
|
|
19723
|
-
/* @__PURE__ */
|
|
19724
|
-
/* @__PURE__ */
|
|
19725
|
-
/* @__PURE__ */
|
|
19726
|
-
/* @__PURE__ */
|
|
20072
|
+
/* @__PURE__ */ jsx22(ToolbarAction2, { label: "Add feature", onClick: onAddFeature, disabled: featureCount >= 10, children: /* @__PURE__ */ jsx22(FeatureGlyph, { mode: "add" }) }),
|
|
20073
|
+
/* @__PURE__ */ jsx22(ToolbarAction2, { label: "Remove feature", onClick: onRemoveFeature, disabled: featureCount <= 1, children: /* @__PURE__ */ jsx22(FeatureGlyph, { mode: "remove" }) }),
|
|
20074
|
+
/* @__PURE__ */ jsx22(ToolbarSeparator2, {}),
|
|
20075
|
+
/* @__PURE__ */ jsx22(ToolbarAction2, { label: "Add tier", onClick: onAddTier, disabled: collectionCount >= 4, children: /* @__PURE__ */ jsx22(Plus3, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
20076
|
+
/* @__PURE__ */ jsx22(ToolbarAction2, { label: "Remove tier", onClick: onRemoveTier, disabled: collectionCount <= 1, children: /* @__PURE__ */ jsx22(Minus2, { size: 16, style: { pointerEvents: "none" } }) })
|
|
19727
20077
|
]
|
|
19728
20078
|
}
|
|
19729
20079
|
),
|
|
19730
|
-
error && /* @__PURE__ */
|
|
20080
|
+
error && /* @__PURE__ */ jsx22("div", { className: "max-w-[260px] rounded-md bg-background px-2 py-1 text-center text-[11px] text-destructive shadow-sm", children: error })
|
|
19731
20081
|
]
|
|
19732
20082
|
}
|
|
19733
20083
|
) });
|
|
@@ -19761,7 +20111,7 @@ function AiPricingCardOverlay({
|
|
|
19761
20111
|
const overEditable = Boolean(t?.closest?.("[data-ohw-editable], [data-ohw-role], a, button"));
|
|
19762
20112
|
setHover((prev) => {
|
|
19763
20113
|
const next = ref && !overEditable ? ref : null;
|
|
19764
|
-
return
|
|
20114
|
+
return sameRef2(prev, next) ? prev : next;
|
|
19765
20115
|
});
|
|
19766
20116
|
};
|
|
19767
20117
|
const onLeave = () => setHover(null);
|
|
@@ -19776,10 +20126,10 @@ function AiPricingCardOverlay({
|
|
|
19776
20126
|
const onClick = (e) => {
|
|
19777
20127
|
const t = e.target;
|
|
19778
20128
|
if (!(t instanceof Element)) return;
|
|
19779
|
-
if (t.closest(
|
|
20129
|
+
if (t.closest(CHROME_SELECTOR2)) return;
|
|
19780
20130
|
const ref = cardRefFromTarget(t);
|
|
19781
|
-
setActive((prev) =>
|
|
19782
|
-
if (!ref || !
|
|
20131
|
+
setActive((prev) => sameRef2(prev, ref) ? prev : ref);
|
|
20132
|
+
if (!ref || !sameRef2(activeRef.current, ref)) setError(null);
|
|
19783
20133
|
};
|
|
19784
20134
|
document.addEventListener("click", onClick, true);
|
|
19785
20135
|
return () => document.removeEventListener("click", onClick, true);
|
|
@@ -19844,12 +20194,12 @@ function AiPricingCardOverlay({
|
|
|
19844
20194
|
const activeEntry = active ? findEntry(active.sectionId) : null;
|
|
19845
20195
|
const activeCardRect = useLiveCardRect(active);
|
|
19846
20196
|
const activeGridRect = useLiveCardRect(active, true);
|
|
19847
|
-
const hoverRect = useLiveCardRect(hover && !
|
|
19848
|
-
return /* @__PURE__ */
|
|
19849
|
-
hoverRect && /* @__PURE__ */
|
|
19850
|
-
activeCardRect && activeGridRect && active && activeEntry && /* @__PURE__ */
|
|
19851
|
-
/* @__PURE__ */
|
|
19852
|
-
/* @__PURE__ */
|
|
20197
|
+
const hoverRect = useLiveCardRect(hover && !sameRef2(hover, active) ? hover : null);
|
|
20198
|
+
return /* @__PURE__ */ jsxs13(Fragment8, { children: [
|
|
20199
|
+
hoverRect && /* @__PURE__ */ jsx22(ItemInteractionLayer, { rect: hoverRect, state: "hover" }),
|
|
20200
|
+
activeCardRect && activeGridRect && active && activeEntry && /* @__PURE__ */ jsxs13(Fragment8, { children: [
|
|
20201
|
+
/* @__PURE__ */ jsx22(ItemInteractionLayer, { rect: activeCardRect, state: "active-top" }),
|
|
20202
|
+
/* @__PURE__ */ jsx22(GridToolbarSlot, { gridRect: activeGridRect, children: /* @__PURE__ */ jsx22(
|
|
19853
20203
|
PricingCardToolbar,
|
|
19854
20204
|
{
|
|
19855
20205
|
entry: activeEntry,
|
|
@@ -19877,7 +20227,7 @@ function AiPricingCardOverlay({
|
|
|
19877
20227
|
onRemoveFeature: () => runMutation(active.sectionId, (tree) => removePricingCardFeature(tree, active.index))
|
|
19878
20228
|
}
|
|
19879
20229
|
) }),
|
|
19880
|
-
/* @__PURE__ */
|
|
20230
|
+
/* @__PURE__ */ jsx22(
|
|
19881
20231
|
"div",
|
|
19882
20232
|
{
|
|
19883
20233
|
"data-ohw-bridge": "",
|
|
@@ -19929,51 +20279,23 @@ function videoIdAt(tree, path) {
|
|
|
19929
20279
|
function setVideoId(tree, path, videoId) {
|
|
19930
20280
|
return withVideo(tree, path, (block) => {
|
|
19931
20281
|
block.slots = { ...block.slots, videoId };
|
|
19932
|
-
return true;
|
|
19933
|
-
});
|
|
19934
|
-
}
|
|
19935
|
-
function clearVideo(tree, path) {
|
|
19936
|
-
return withVideo(tree, path, (block) => {
|
|
19937
|
-
const slots = { ...block.slots };
|
|
19938
|
-
delete slots.videoId;
|
|
19939
|
-
block.slots = slots;
|
|
19940
|
-
return true;
|
|
19941
|
-
});
|
|
19942
|
-
}
|
|
19943
|
-
|
|
19944
|
-
// src/lib/youtube.ts
|
|
19945
|
-
var YOUTUBE_ID_PATTERN = /^[A-Za-z0-9_-]{11}$/;
|
|
19946
|
-
function extractYouTubeId(input) {
|
|
19947
|
-
const trimmed = input.trim();
|
|
19948
|
-
if (!trimmed) return null;
|
|
19949
|
-
if (YOUTUBE_ID_PATTERN.test(trimmed)) return trimmed;
|
|
19950
|
-
let url;
|
|
19951
|
-
try {
|
|
19952
|
-
url = new URL(trimmed);
|
|
19953
|
-
} catch {
|
|
19954
|
-
return null;
|
|
19955
|
-
}
|
|
19956
|
-
const host = url.hostname.replace(/^www\./, "");
|
|
19957
|
-
if (host !== "youtube.com" && host !== "m.youtube.com" && host !== "youtu.be" && host !== "youtube-nocookie.com") {
|
|
19958
|
-
return null;
|
|
19959
|
-
}
|
|
19960
|
-
let candidate = null;
|
|
19961
|
-
if (host === "youtu.be") {
|
|
19962
|
-
candidate = url.pathname.slice(1).split("/")[0] ?? null;
|
|
19963
|
-
} else if (url.pathname === "/watch") {
|
|
19964
|
-
candidate = url.searchParams.get("v");
|
|
19965
|
-
} else {
|
|
19966
|
-
const match = url.pathname.match(/^\/(?:embed|shorts)\/([^/]+)/);
|
|
19967
|
-
candidate = match ? match[1] : null;
|
|
19968
|
-
}
|
|
19969
|
-
return candidate && YOUTUBE_ID_PATTERN.test(candidate) ? candidate : null;
|
|
20282
|
+
return true;
|
|
20283
|
+
});
|
|
20284
|
+
}
|
|
20285
|
+
function clearVideo(tree, path) {
|
|
20286
|
+
return withVideo(tree, path, (block) => {
|
|
20287
|
+
const slots = { ...block.slots };
|
|
20288
|
+
delete slots.videoId;
|
|
20289
|
+
block.slots = slots;
|
|
20290
|
+
return true;
|
|
20291
|
+
});
|
|
19970
20292
|
}
|
|
19971
20293
|
|
|
19972
20294
|
// src/ui/ai-section/AiVideoOverlay.tsx
|
|
19973
|
-
import { Fragment as Fragment9, jsx as
|
|
20295
|
+
import { Fragment as Fragment9, jsx as jsx23, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
19974
20296
|
var PRIMARY5 = "#0885FE";
|
|
19975
|
-
var
|
|
19976
|
-
var
|
|
20297
|
+
var OHW_BLUE = `var(--ohw-primary, ${PRIMARY5})`;
|
|
20298
|
+
var OHW_BLUE_DARK = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY5}) 60%, #000000)`;
|
|
19977
20299
|
function findVideoBlockElement(sectionId, path) {
|
|
19978
20300
|
const sectionEl = findByInstanceId(sectionId);
|
|
19979
20301
|
if (!sectionEl) return null;
|
|
@@ -20033,12 +20355,12 @@ function requestValidateTree3(postToParent2, tree) {
|
|
|
20033
20355
|
postToParent2({ type: "ow:ai-validate-tree-request", id, tree });
|
|
20034
20356
|
});
|
|
20035
20357
|
}
|
|
20036
|
-
function
|
|
20358
|
+
function Pill({
|
|
20037
20359
|
label,
|
|
20038
20360
|
onClick,
|
|
20039
20361
|
disabled
|
|
20040
20362
|
}) {
|
|
20041
|
-
return /* @__PURE__ */
|
|
20363
|
+
return /* @__PURE__ */ jsx23(
|
|
20042
20364
|
"button",
|
|
20043
20365
|
{
|
|
20044
20366
|
type: "button",
|
|
@@ -20054,7 +20376,7 @@ function Pill2({
|
|
|
20054
20376
|
border: "none",
|
|
20055
20377
|
cursor: disabled ? "default" : "pointer",
|
|
20056
20378
|
background: "#ffffff",
|
|
20057
|
-
color:
|
|
20379
|
+
color: OHW_BLUE_DARK,
|
|
20058
20380
|
opacity: disabled ? 0.4 : 1,
|
|
20059
20381
|
fontSize: 12,
|
|
20060
20382
|
lineHeight: "16px",
|
|
@@ -20076,7 +20398,7 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20076
20398
|
setDraft(value ? watchUrl(value) : "");
|
|
20077
20399
|
setInvalid(false);
|
|
20078
20400
|
}, [value]);
|
|
20079
|
-
const
|
|
20401
|
+
const commit2 = () => {
|
|
20080
20402
|
const next = draft.trim();
|
|
20081
20403
|
if (!next) {
|
|
20082
20404
|
setInvalid(false);
|
|
@@ -20097,8 +20419,8 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20097
20419
|
onCommit(id);
|
|
20098
20420
|
}
|
|
20099
20421
|
};
|
|
20100
|
-
return /* @__PURE__ */
|
|
20101
|
-
/* @__PURE__ */
|
|
20422
|
+
return /* @__PURE__ */ jsxs14("div", { style: { display: "flex", flexDirection: "column", gap: 4, width: "100%", maxWidth: 280 }, children: [
|
|
20423
|
+
/* @__PURE__ */ jsxs14(
|
|
20102
20424
|
"div",
|
|
20103
20425
|
{
|
|
20104
20426
|
style: {
|
|
@@ -20114,12 +20436,12 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20114
20436
|
boxShadow: invalid ? "inset 0 0 0 1.5px #EF4444" : "none"
|
|
20115
20437
|
},
|
|
20116
20438
|
children: [
|
|
20117
|
-
/* @__PURE__ */
|
|
20439
|
+
/* @__PURE__ */ jsx23(
|
|
20118
20440
|
"span",
|
|
20119
20441
|
{
|
|
20120
20442
|
style: {
|
|
20121
20443
|
flex: "0 0 auto",
|
|
20122
|
-
color:
|
|
20444
|
+
color: OHW_BLUE_DARK,
|
|
20123
20445
|
fontSize: 10,
|
|
20124
20446
|
lineHeight: "16px",
|
|
20125
20447
|
fontWeight: 700,
|
|
@@ -20129,14 +20451,14 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20129
20451
|
children: "Video"
|
|
20130
20452
|
}
|
|
20131
20453
|
),
|
|
20132
|
-
/* @__PURE__ */
|
|
20454
|
+
/* @__PURE__ */ jsx23(
|
|
20133
20455
|
"input",
|
|
20134
20456
|
{
|
|
20135
20457
|
type: "text",
|
|
20136
20458
|
inputMode: "url",
|
|
20137
20459
|
value: draft,
|
|
20138
20460
|
onChange: (e) => handleChange(e.target.value),
|
|
20139
|
-
onBlur:
|
|
20461
|
+
onBlur: commit2,
|
|
20140
20462
|
onKeyDown: (e) => {
|
|
20141
20463
|
if (e.key === "Enter") e.currentTarget.blur();
|
|
20142
20464
|
if (e.key === "Escape") {
|
|
@@ -20166,7 +20488,7 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20166
20488
|
]
|
|
20167
20489
|
}
|
|
20168
20490
|
),
|
|
20169
|
-
invalid && /* @__PURE__ */
|
|
20491
|
+
invalid && /* @__PURE__ */ jsx23("div", { style: { color: "#FCA5A5", fontSize: 11, textAlign: "center" }, children: "That doesn't look like a YouTube link \u2014 try pasting the video URL again." })
|
|
20170
20492
|
] });
|
|
20171
20493
|
}
|
|
20172
20494
|
function VideoToolbar({
|
|
@@ -20176,7 +20498,7 @@ function VideoToolbar({
|
|
|
20176
20498
|
onSetVideoId,
|
|
20177
20499
|
onRemove
|
|
20178
20500
|
}) {
|
|
20179
|
-
return /* @__PURE__ */
|
|
20501
|
+
return /* @__PURE__ */ jsxs14(
|
|
20180
20502
|
"div",
|
|
20181
20503
|
{
|
|
20182
20504
|
"data-ohw-bridge": "",
|
|
@@ -20188,7 +20510,7 @@ function VideoToolbar({
|
|
|
20188
20510
|
gap: 6,
|
|
20189
20511
|
alignItems: "center",
|
|
20190
20512
|
width: 280,
|
|
20191
|
-
background:
|
|
20513
|
+
background: OHW_BLUE,
|
|
20192
20514
|
padding: 8,
|
|
20193
20515
|
borderRadius: 12,
|
|
20194
20516
|
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
@@ -20196,9 +20518,9 @@ function VideoToolbar({
|
|
|
20196
20518
|
opacity: pending ? 0.6 : 1
|
|
20197
20519
|
},
|
|
20198
20520
|
children: [
|
|
20199
|
-
/* @__PURE__ */
|
|
20200
|
-
/* @__PURE__ */
|
|
20201
|
-
error && /* @__PURE__ */
|
|
20521
|
+
/* @__PURE__ */ jsx23(VideoUrlInput, { value: videoId, onCommit: onSetVideoId }),
|
|
20522
|
+
/* @__PURE__ */ jsx23(Pill, { label: "Remove video", onClick: onRemove, disabled: !videoId }),
|
|
20523
|
+
error && /* @__PURE__ */ jsx23("div", { style: { color: "#FCA5A5", fontSize: 11, maxWidth: 220, textAlign: "center" }, children: error })
|
|
20202
20524
|
]
|
|
20203
20525
|
}
|
|
20204
20526
|
);
|
|
@@ -20318,8 +20640,8 @@ function AiVideoOverlay({
|
|
|
20318
20640
|
const activeBlockRect = useLiveBlockRect(active);
|
|
20319
20641
|
const TOOLBAR_APPROX_H = 90;
|
|
20320
20642
|
const toolbarState = activeBlockRect && activeBlockRect.top < TOOLBAR_APPROX_H ? "active-bottom" : "active-top";
|
|
20321
|
-
return /* @__PURE__ */
|
|
20322
|
-
hoverHandleRect && hover && /* @__PURE__ */
|
|
20643
|
+
return /* @__PURE__ */ jsxs14(Fragment9, { children: [
|
|
20644
|
+
hoverHandleRect && hover && /* @__PURE__ */ jsx23(
|
|
20323
20645
|
"button",
|
|
20324
20646
|
{
|
|
20325
20647
|
type: "button",
|
|
@@ -20347,15 +20669,15 @@ function AiVideoOverlay({
|
|
|
20347
20669
|
fontSize: 14,
|
|
20348
20670
|
fontWeight: 700
|
|
20349
20671
|
},
|
|
20350
|
-
children: /* @__PURE__ */
|
|
20672
|
+
children: /* @__PURE__ */ jsx23(Star3, { size: 14, style: { pointerEvents: "none" } })
|
|
20351
20673
|
}
|
|
20352
20674
|
),
|
|
20353
|
-
activeBlockRect && active && activeEntry && /* @__PURE__ */
|
|
20675
|
+
activeBlockRect && active && activeEntry && /* @__PURE__ */ jsx23(
|
|
20354
20676
|
ItemInteractionLayer,
|
|
20355
20677
|
{
|
|
20356
20678
|
rect: activeBlockRect,
|
|
20357
20679
|
state: toolbarState,
|
|
20358
|
-
toolbar: /* @__PURE__ */
|
|
20680
|
+
toolbar: /* @__PURE__ */ jsx23(
|
|
20359
20681
|
VideoToolbar,
|
|
20360
20682
|
{
|
|
20361
20683
|
videoId: videoIdAt(activeEntry.tree, active.path),
|
|
@@ -20430,10 +20752,10 @@ function setCarouselAutoplay(tree, on) {
|
|
|
20430
20752
|
}
|
|
20431
20753
|
|
|
20432
20754
|
// src/ui/ai-section/AiFadeCarouselOverlay.tsx
|
|
20433
|
-
import { Fragment as Fragment10, jsx as
|
|
20755
|
+
import { Fragment as Fragment10, jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
20434
20756
|
var PRIMARY6 = "#0885FE";
|
|
20435
|
-
var
|
|
20436
|
-
var
|
|
20757
|
+
var OHW_BLUE2 = `var(--ohw-primary, ${PRIMARY6})`;
|
|
20758
|
+
var OHW_BLUE_DARK2 = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY6}) 60%, #000000)`;
|
|
20437
20759
|
function findCarouselItemElement(sectionId, index) {
|
|
20438
20760
|
const sectionEl = findByInstanceId(sectionId);
|
|
20439
20761
|
if (!sectionEl) return null;
|
|
@@ -20512,8 +20834,8 @@ function requestAssetPick2(postToParent2) {
|
|
|
20512
20834
|
postToParent2({ type: "ow:asset-pick", id });
|
|
20513
20835
|
});
|
|
20514
20836
|
}
|
|
20515
|
-
function
|
|
20516
|
-
return /* @__PURE__ */
|
|
20837
|
+
function Pill2({ label, onClick, disabled }) {
|
|
20838
|
+
return /* @__PURE__ */ jsx24(
|
|
20517
20839
|
"button",
|
|
20518
20840
|
{
|
|
20519
20841
|
type: "button",
|
|
@@ -20529,7 +20851,7 @@ function Pill3({ label, onClick, disabled }) {
|
|
|
20529
20851
|
border: "none",
|
|
20530
20852
|
cursor: disabled ? "default" : "pointer",
|
|
20531
20853
|
background: "#ffffff",
|
|
20532
|
-
color:
|
|
20854
|
+
color: OHW_BLUE_DARK2,
|
|
20533
20855
|
opacity: disabled ? 0.4 : 1,
|
|
20534
20856
|
fontSize: 12,
|
|
20535
20857
|
lineHeight: "16px",
|
|
@@ -20547,7 +20869,7 @@ function TogglePill({
|
|
|
20547
20869
|
onToggle,
|
|
20548
20870
|
disabled
|
|
20549
20871
|
}) {
|
|
20550
|
-
return /* @__PURE__ */
|
|
20872
|
+
return /* @__PURE__ */ jsxs15(
|
|
20551
20873
|
"button",
|
|
20552
20874
|
{
|
|
20553
20875
|
type: "button",
|
|
@@ -20566,7 +20888,7 @@ function TogglePill({
|
|
|
20566
20888
|
border: "none",
|
|
20567
20889
|
cursor: disabled ? "default" : "pointer",
|
|
20568
20890
|
background: "#ffffff",
|
|
20569
|
-
color:
|
|
20891
|
+
color: OHW_BLUE_DARK2,
|
|
20570
20892
|
opacity: disabled ? 0.4 : 1,
|
|
20571
20893
|
fontSize: 12,
|
|
20572
20894
|
lineHeight: "16px",
|
|
@@ -20576,7 +20898,7 @@ function TogglePill({
|
|
|
20576
20898
|
},
|
|
20577
20899
|
children: [
|
|
20578
20900
|
label,
|
|
20579
|
-
/* @__PURE__ */
|
|
20901
|
+
/* @__PURE__ */ jsx24(
|
|
20580
20902
|
"span",
|
|
20581
20903
|
{
|
|
20582
20904
|
"aria-hidden": true,
|
|
@@ -20589,10 +20911,10 @@ function TogglePill({
|
|
|
20589
20911
|
// Off is a grey track, not a washed-out blue: the pill's own white background already
|
|
20590
20912
|
// carries the brand colour in the text, and a pale blue track next to it read as
|
|
20591
20913
|
// "disabled control" rather than "switch that is off".
|
|
20592
|
-
background: on ?
|
|
20914
|
+
background: on ? OHW_BLUE_DARK2 : "#CBD5E1",
|
|
20593
20915
|
transition: "background 120ms ease"
|
|
20594
20916
|
},
|
|
20595
|
-
children: /* @__PURE__ */
|
|
20917
|
+
children: /* @__PURE__ */ jsx24(
|
|
20596
20918
|
"span",
|
|
20597
20919
|
{
|
|
20598
20920
|
style: {
|
|
@@ -20621,7 +20943,7 @@ function CarouselSlideToolbar({
|
|
|
20621
20943
|
onChangeImage,
|
|
20622
20944
|
onToggleAutoplay
|
|
20623
20945
|
}) {
|
|
20624
|
-
return /* @__PURE__ */
|
|
20946
|
+
return /* @__PURE__ */ jsxs15(
|
|
20625
20947
|
"div",
|
|
20626
20948
|
{
|
|
20627
20949
|
"data-ohw-bridge": "",
|
|
@@ -20632,7 +20954,7 @@ function CarouselSlideToolbar({
|
|
|
20632
20954
|
flexDirection: "column",
|
|
20633
20955
|
gap: 6,
|
|
20634
20956
|
alignItems: "center",
|
|
20635
|
-
background:
|
|
20957
|
+
background: OHW_BLUE2,
|
|
20636
20958
|
padding: 8,
|
|
20637
20959
|
borderRadius: 12,
|
|
20638
20960
|
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
@@ -20644,11 +20966,11 @@ function CarouselSlideToolbar({
|
|
|
20644
20966
|
pointerEvents: pending ? "none" : "auto"
|
|
20645
20967
|
},
|
|
20646
20968
|
children: [
|
|
20647
|
-
/* @__PURE__ */
|
|
20648
|
-
/* @__PURE__ */
|
|
20649
|
-
/* @__PURE__ */
|
|
20969
|
+
/* @__PURE__ */ jsxs15("div", { style: { display: "flex", gap: 6, alignItems: "center" }, children: [
|
|
20970
|
+
/* @__PURE__ */ jsx24(Pill2, { label: "Change Image", onClick: onChangeImage }),
|
|
20971
|
+
/* @__PURE__ */ jsx24(TogglePill, { label: "Autoplay", on: autoplay, onToggle: onToggleAutoplay })
|
|
20650
20972
|
] }),
|
|
20651
|
-
error && /* @__PURE__ */
|
|
20973
|
+
error && /* @__PURE__ */ jsx24("div", { style: { color: "#FCA5A5", fontSize: 11, maxWidth: 220, textAlign: "center" }, children: error })
|
|
20652
20974
|
]
|
|
20653
20975
|
}
|
|
20654
20976
|
);
|
|
@@ -20788,8 +21110,8 @@ function AiFadeCarouselOverlay({
|
|
|
20788
21110
|
const activeItemRect = useLiveItemRect2(active);
|
|
20789
21111
|
const TOOLBAR_APPROX_H = 90;
|
|
20790
21112
|
const toolbarState = activeItemRect && activeItemRect.top < TOOLBAR_APPROX_H ? "active-bottom" : "active-top";
|
|
20791
|
-
return /* @__PURE__ */
|
|
20792
|
-
hoverHandleRect && hover && /* @__PURE__ */
|
|
21113
|
+
return /* @__PURE__ */ jsxs15(Fragment10, { children: [
|
|
21114
|
+
hoverHandleRect && hover && /* @__PURE__ */ jsx24(
|
|
20793
21115
|
"button",
|
|
20794
21116
|
{
|
|
20795
21117
|
type: "button",
|
|
@@ -20818,10 +21140,10 @@ function AiFadeCarouselOverlay({
|
|
|
20818
21140
|
fontSize: 14,
|
|
20819
21141
|
fontWeight: 700
|
|
20820
21142
|
},
|
|
20821
|
-
children: /* @__PURE__ */
|
|
21143
|
+
children: /* @__PURE__ */ jsx24(Star4, { size: 14, style: { pointerEvents: "none" } })
|
|
20822
21144
|
}
|
|
20823
21145
|
),
|
|
20824
|
-
swapping && /* @__PURE__ */
|
|
21146
|
+
swapping && /* @__PURE__ */ jsx24(
|
|
20825
21147
|
"div",
|
|
20826
21148
|
{
|
|
20827
21149
|
ref: skeletonRef,
|
|
@@ -20839,15 +21161,15 @@ function AiFadeCarouselOverlay({
|
|
|
20839
21161
|
zIndex: 2147483646,
|
|
20840
21162
|
pointerEvents: "none"
|
|
20841
21163
|
},
|
|
20842
|
-
children: /* @__PURE__ */
|
|
21164
|
+
children: /* @__PURE__ */ jsx24("style", { children: MEDIA_SKELETON_CSS })
|
|
20843
21165
|
}
|
|
20844
21166
|
),
|
|
20845
|
-
activeItemRect && active && activeEntry && /* @__PURE__ */
|
|
21167
|
+
activeItemRect && active && activeEntry && /* @__PURE__ */ jsx24(
|
|
20846
21168
|
ItemInteractionLayer,
|
|
20847
21169
|
{
|
|
20848
21170
|
rect: activeItemRect,
|
|
20849
21171
|
state: toolbarState,
|
|
20850
|
-
toolbar: /* @__PURE__ */
|
|
21172
|
+
toolbar: /* @__PURE__ */ jsx24(
|
|
20851
21173
|
CarouselSlideToolbar,
|
|
20852
21174
|
{
|
|
20853
21175
|
pending,
|
|
@@ -21065,118 +21387,11 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
|
|
|
21065
21387
|
// src/ui/link-modal/LinkPopover.tsx
|
|
21066
21388
|
import { useEffect as useEffect13 } from "react";
|
|
21067
21389
|
|
|
21068
|
-
// src/ui/dialog.tsx
|
|
21069
|
-
import * as React9 from "react";
|
|
21070
|
-
import { Dialog as DialogPrimitive } from "radix-ui";
|
|
21071
|
-
import { X as X2 } from "lucide-react";
|
|
21072
|
-
import { jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
21073
|
-
function Dialog2({
|
|
21074
|
-
...props
|
|
21075
|
-
}) {
|
|
21076
|
-
return /* @__PURE__ */ jsx24(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
|
|
21077
|
-
}
|
|
21078
|
-
function DialogPortal({
|
|
21079
|
-
...props
|
|
21080
|
-
}) {
|
|
21081
|
-
return /* @__PURE__ */ jsx24(DialogPrimitive.Portal, { ...props });
|
|
21082
|
-
}
|
|
21083
|
-
function DialogOverlay({
|
|
21084
|
-
className,
|
|
21085
|
-
...props
|
|
21086
|
-
}) {
|
|
21087
|
-
return /* @__PURE__ */ jsx24(
|
|
21088
|
-
DialogPrimitive.Overlay,
|
|
21089
|
-
{
|
|
21090
|
-
"data-slot": "dialog-overlay",
|
|
21091
|
-
"data-ohw-link-modal-root": "",
|
|
21092
|
-
className: cn("fixed inset-0 z-[2147483646] bg-black/50", className),
|
|
21093
|
-
...props
|
|
21094
|
-
}
|
|
21095
|
-
);
|
|
21096
|
-
}
|
|
21097
|
-
var DialogContent = React9.forwardRef(
|
|
21098
|
-
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
21099
|
-
const positionMode = container ? "absolute" : "fixed";
|
|
21100
|
-
return /* @__PURE__ */ jsxs15(DialogPortal, { container: container ?? void 0, children: [
|
|
21101
|
-
/* @__PURE__ */ jsx24(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
21102
|
-
/* @__PURE__ */ jsxs15(
|
|
21103
|
-
DialogPrimitive.Content,
|
|
21104
|
-
{
|
|
21105
|
-
ref,
|
|
21106
|
-
"data-slot": "dialog-content",
|
|
21107
|
-
className: cn(
|
|
21108
|
-
positionMode,
|
|
21109
|
-
"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",
|
|
21110
|
-
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
21111
|
-
container ? "max-h-[calc(100%-32px)]" : "max-h-[calc(100vh-32px)]",
|
|
21112
|
-
className
|
|
21113
|
-
),
|
|
21114
|
-
onMouseDown: (e) => e.stopPropagation(),
|
|
21115
|
-
...props,
|
|
21116
|
-
children: [
|
|
21117
|
-
children,
|
|
21118
|
-
showCloseButton ? /* @__PURE__ */ jsx24(
|
|
21119
|
-
DialogPrimitive.Close,
|
|
21120
|
-
{
|
|
21121
|
-
type: "button",
|
|
21122
|
-
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
21123
|
-
"aria-label": "Close",
|
|
21124
|
-
children: /* @__PURE__ */ jsx24(X2, { size: 16, "aria-hidden": true })
|
|
21125
|
-
}
|
|
21126
|
-
) : null
|
|
21127
|
-
]
|
|
21128
|
-
}
|
|
21129
|
-
)
|
|
21130
|
-
] });
|
|
21131
|
-
}
|
|
21132
|
-
);
|
|
21133
|
-
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
21134
|
-
function DialogHeader({
|
|
21135
|
-
className,
|
|
21136
|
-
...props
|
|
21137
|
-
}) {
|
|
21138
|
-
return /* @__PURE__ */ jsx24("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
21139
|
-
}
|
|
21140
|
-
function DialogFooter({
|
|
21141
|
-
className,
|
|
21142
|
-
...props
|
|
21143
|
-
}) {
|
|
21144
|
-
return /* @__PURE__ */ jsx24(
|
|
21145
|
-
"div",
|
|
21146
|
-
{
|
|
21147
|
-
className: cn("flex items-center justify-end gap-2", className),
|
|
21148
|
-
...props
|
|
21149
|
-
}
|
|
21150
|
-
);
|
|
21151
|
-
}
|
|
21152
|
-
var DialogTitle = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx24(
|
|
21153
|
-
DialogPrimitive.Title,
|
|
21154
|
-
{
|
|
21155
|
-
ref,
|
|
21156
|
-
className: cn(
|
|
21157
|
-
"text-lg font-semibold leading-none tracking-tight text-card-foreground",
|
|
21158
|
-
className
|
|
21159
|
-
),
|
|
21160
|
-
...props
|
|
21161
|
-
}
|
|
21162
|
-
));
|
|
21163
|
-
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
21164
|
-
var DialogDescription = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx24(
|
|
21165
|
-
DialogPrimitive.Description,
|
|
21166
|
-
{
|
|
21167
|
-
ref,
|
|
21168
|
-
className: cn("text-sm text-muted-foreground", className),
|
|
21169
|
-
...props
|
|
21170
|
-
}
|
|
21171
|
-
));
|
|
21172
|
-
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
21173
|
-
var DialogClose = DialogPrimitive.Close;
|
|
21174
|
-
|
|
21175
21390
|
// src/ui/link-modal/LinkEditorPanel.tsx
|
|
21176
21391
|
import { Info, X as X4 } from "lucide-react";
|
|
21177
21392
|
|
|
21178
21393
|
// src/ui/link-modal/DestinationBreadcrumb.tsx
|
|
21179
|
-
import { ArrowRight as
|
|
21394
|
+
import { ArrowRight as ArrowRight3, File, GalleryVertical } from "lucide-react";
|
|
21180
21395
|
import { jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
21181
21396
|
function DestinationBreadcrumb({
|
|
21182
21397
|
pageTitle,
|
|
@@ -21190,7 +21405,7 @@ function DestinationBreadcrumb({
|
|
|
21190
21405
|
/* @__PURE__ */ jsx25("span", { className: "text-sm font-medium leading-none text-foreground!", children: pageTitle })
|
|
21191
21406
|
] }),
|
|
21192
21407
|
/* @__PURE__ */ jsx25(
|
|
21193
|
-
|
|
21408
|
+
ArrowRight3,
|
|
21194
21409
|
{
|
|
21195
21410
|
size: 16,
|
|
21196
21411
|
className: "shrink-0 text-muted-foreground",
|
|
@@ -21302,7 +21517,7 @@ function Label({ className, ...props }) {
|
|
|
21302
21517
|
}
|
|
21303
21518
|
|
|
21304
21519
|
// src/ui/link-modal/UrlOrPageInput.tsx
|
|
21305
|
-
import { ChevronDown as
|
|
21520
|
+
import { ChevronDown as ChevronDown5, File as File2, X as X3 } from "lucide-react";
|
|
21306
21521
|
import { jsx as jsx29, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
21307
21522
|
function FieldChevron({
|
|
21308
21523
|
onClick
|
|
@@ -21315,7 +21530,7 @@ function FieldChevron({
|
|
|
21315
21530
|
onClick,
|
|
21316
21531
|
"aria-label": "Open page list",
|
|
21317
21532
|
tabIndex: -1,
|
|
21318
|
-
children: /* @__PURE__ */ jsx29(
|
|
21533
|
+
children: /* @__PURE__ */ jsx29(ChevronDown5, { size: 16 })
|
|
21319
21534
|
}
|
|
21320
21535
|
);
|
|
21321
21536
|
}
|
|
@@ -21545,7 +21760,7 @@ function LinkEditorPanel({ state, onClose }) {
|
|
|
21545
21760
|
// src/ui/link-modal/SectionPickerOverlay.tsx
|
|
21546
21761
|
import { useCallback as useCallback7, useEffect as useEffect11, useMemo as useMemo2, useRef as useRef10, useState as useState13 } from "react";
|
|
21547
21762
|
import { createPortal as createPortal2 } from "react-dom";
|
|
21548
|
-
import { ArrowLeft as
|
|
21763
|
+
import { ArrowLeft as ArrowLeft3, Check as Check4 } from "lucide-react";
|
|
21549
21764
|
import { usePathname, useRouter as useRouter2 } from "next/navigation";
|
|
21550
21765
|
|
|
21551
21766
|
// src/lib/parent-scroll.ts
|
|
@@ -21822,7 +22037,7 @@ function SectionPickerOverlay({
|
|
|
21822
22037
|
className: "h-8 min-w-0 gap-1 border-border bg-background px-2 py-1.5 shadow-sm hover:bg-muted cursor-pointer",
|
|
21823
22038
|
onClick: onBack,
|
|
21824
22039
|
children: [
|
|
21825
|
-
/* @__PURE__ */ jsx31(
|
|
22040
|
+
/* @__PURE__ */ jsx31(ArrowLeft3, { className: "size-4 shrink-0", "aria-hidden": true }),
|
|
21826
22041
|
"Back"
|
|
21827
22042
|
]
|
|
21828
22043
|
}
|
|
@@ -21891,7 +22106,7 @@ function SectionPickerOverlay({
|
|
|
21891
22106
|
className: "absolute right-3 top-3 flex size-8 items-center justify-center rounded-full text-white",
|
|
21892
22107
|
style: { backgroundColor: "var(--ohw-primary, #0885fe)" },
|
|
21893
22108
|
"aria-hidden": true,
|
|
21894
|
-
children: /* @__PURE__ */ jsx31(
|
|
22109
|
+
children: /* @__PURE__ */ jsx31(Check4, { className: "size-5" })
|
|
21895
22110
|
}
|
|
21896
22111
|
) : null
|
|
21897
22112
|
]
|
|
@@ -22275,6 +22490,7 @@ function shouldUseDevFixtures() {
|
|
|
22275
22490
|
function getLogoElement(el) {
|
|
22276
22491
|
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
22277
22492
|
if (marked) return marked;
|
|
22493
|
+
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
22278
22494
|
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
22279
22495
|
if (!root) return null;
|
|
22280
22496
|
const anchor = el.closest("a");
|
|
@@ -22344,7 +22560,7 @@ function addFooterColumnWithPersist({
|
|
|
22344
22560
|
import {
|
|
22345
22561
|
useCallback as useCallback9,
|
|
22346
22562
|
useEffect as useEffect14,
|
|
22347
|
-
useLayoutEffect as
|
|
22563
|
+
useLayoutEffect as useLayoutEffect6,
|
|
22348
22564
|
useRef as useRef11,
|
|
22349
22565
|
useState as useState15
|
|
22350
22566
|
} from "react";
|
|
@@ -22441,7 +22657,7 @@ function FloatingPanel({
|
|
|
22441
22657
|
return () => window.removeEventListener("message", onParentScroll);
|
|
22442
22658
|
}, [open]);
|
|
22443
22659
|
const positionRef = useRef11(position);
|
|
22444
|
-
|
|
22660
|
+
useLayoutEffect6(() => {
|
|
22445
22661
|
if (!open) {
|
|
22446
22662
|
positionRef.current = position;
|
|
22447
22663
|
return;
|
|
@@ -22451,7 +22667,7 @@ function FloatingPanel({
|
|
|
22451
22667
|
}
|
|
22452
22668
|
positionRef.current = position;
|
|
22453
22669
|
}, [open, position, liveScroll, parentScroll]);
|
|
22454
|
-
|
|
22670
|
+
useLayoutEffect6(() => {
|
|
22455
22671
|
if (!open || !panelRef.current) return;
|
|
22456
22672
|
const el = panelRef.current;
|
|
22457
22673
|
const header = el.querySelector("[data-ohw-floating-panel-header]");
|
|
@@ -22660,7 +22876,7 @@ function SocialsDisplayPanel({ display, onChange, className }) {
|
|
|
22660
22876
|
}
|
|
22661
22877
|
|
|
22662
22878
|
// src/ui/button-style-panel.tsx
|
|
22663
|
-
import { Check as
|
|
22879
|
+
import { Check as Check5 } from "lucide-react";
|
|
22664
22880
|
import { jsx as jsx35, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
22665
22881
|
var SIZE_LABEL = { s: "S", m: "M", l: "L" };
|
|
22666
22882
|
function ButtonStylePanel({
|
|
@@ -22731,7 +22947,7 @@ function ButtonStylePanel({
|
|
|
22731
22947
|
{
|
|
22732
22948
|
className: "absolute right-0.5 top-0.5 flex size-5 items-center justify-center rounded-full bg-primary text-primary-foreground",
|
|
22733
22949
|
"aria-hidden": true,
|
|
22734
|
-
children: /* @__PURE__ */ jsx35(
|
|
22950
|
+
children: /* @__PURE__ */ jsx35(Check5, { className: "size-3", strokeWidth: 3 })
|
|
22735
22951
|
}
|
|
22736
22952
|
) : null
|
|
22737
22953
|
]
|
|
@@ -23756,7 +23972,7 @@ function useSectionDrag({
|
|
|
23756
23972
|
}
|
|
23757
23973
|
|
|
23758
23974
|
// src/ui/footer-container-chrome.tsx
|
|
23759
|
-
import { Plus as
|
|
23975
|
+
import { Plus as Plus4 } from "lucide-react";
|
|
23760
23976
|
import { jsx as jsx36, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
23761
23977
|
function FooterContainerChrome({
|
|
23762
23978
|
rect,
|
|
@@ -23797,7 +24013,7 @@ function FooterContainerChrome({
|
|
|
23797
24013
|
if (addDisabled) return;
|
|
23798
24014
|
onAdd();
|
|
23799
24015
|
},
|
|
23800
|
-
children: /* @__PURE__ */ jsx36(
|
|
24016
|
+
children: /* @__PURE__ */ jsx36(Plus4, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
23801
24017
|
}
|
|
23802
24018
|
) }),
|
|
23803
24019
|
/* @__PURE__ */ jsx36(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
|
|
@@ -23975,8 +24191,104 @@ function deleteSelectedNavFooterItem(deps) {
|
|
|
23975
24191
|
return false;
|
|
23976
24192
|
}
|
|
23977
24193
|
|
|
24194
|
+
// src/lib/nav-page-sync.ts
|
|
24195
|
+
function labelKeyFor(hrefKey) {
|
|
24196
|
+
return hrefKey.replace(/-href$/, "-label");
|
|
24197
|
+
}
|
|
24198
|
+
function isPageLinkKey(key) {
|
|
24199
|
+
return isNavbarHrefKey(key) || isFooterHrefKey(key);
|
|
24200
|
+
}
|
|
24201
|
+
function currentHref(key, anchor, content) {
|
|
24202
|
+
const stored = content[key];
|
|
24203
|
+
if (typeof stored === "string" && stored.length > 0) return stored;
|
|
24204
|
+
return anchor.getAttribute("href") ?? "";
|
|
24205
|
+
}
|
|
24206
|
+
function normalizePath2(value) {
|
|
24207
|
+
if (value.length > 1 && value.endsWith("/")) return value.slice(0, -1);
|
|
24208
|
+
return value;
|
|
24209
|
+
}
|
|
24210
|
+
function pointsAt(href, path) {
|
|
24211
|
+
const normalized = normalizePath2(href);
|
|
24212
|
+
const target = normalizePath2(path);
|
|
24213
|
+
if (normalized === target) return true;
|
|
24214
|
+
return (normalized.startsWith(`${target}#`) || normalized.startsWith(`${target}?`)) && target !== "/";
|
|
24215
|
+
}
|
|
24216
|
+
function retargetHref(href, oldPath, newPath) {
|
|
24217
|
+
const normalized = normalizePath2(href);
|
|
24218
|
+
const target = normalizePath2(oldPath);
|
|
24219
|
+
if (normalized === target) return newPath;
|
|
24220
|
+
return `${newPath}${normalized.slice(target.length)}`;
|
|
24221
|
+
}
|
|
24222
|
+
function setLabelText(key, text) {
|
|
24223
|
+
document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`).forEach((el) => {
|
|
24224
|
+
el.textContent = text;
|
|
24225
|
+
});
|
|
24226
|
+
}
|
|
24227
|
+
function commit(delta, deps) {
|
|
24228
|
+
if (Object.keys(delta).length === 0) return;
|
|
24229
|
+
deps.setEditContent({ ...deps.getEditContent(), ...delta });
|
|
24230
|
+
deps.postToParent({
|
|
24231
|
+
type: "ow:change",
|
|
24232
|
+
nodes: Object.entries(delta).map(([key, text]) => ({ key, text }))
|
|
24233
|
+
});
|
|
24234
|
+
}
|
|
24235
|
+
function navLinksTo(path, content) {
|
|
24236
|
+
return Array.from(document.querySelectorAll("[data-ohw-href-key]")).filter((anchor) => {
|
|
24237
|
+
const key = anchor.getAttribute("data-ohw-href-key");
|
|
24238
|
+
return isNavbarHrefKey(key) && pointsAt(currentHref(key, anchor, content), path);
|
|
24239
|
+
}).map((anchor) => anchor.getAttribute("data-ohw-href-key"));
|
|
24240
|
+
}
|
|
24241
|
+
function addNavLinkForPage(page, deps) {
|
|
24242
|
+
const content = deps.getEditContent();
|
|
24243
|
+
if (navLinksTo(page.path, content).length > 0) return false;
|
|
24244
|
+
const roots = listNavbarRootItems();
|
|
24245
|
+
const afterAnchor = roots[roots.length - 1] ?? null;
|
|
24246
|
+
let inserted;
|
|
24247
|
+
try {
|
|
24248
|
+
inserted = insertNavbarItem(page.path, page.title, afterAnchor);
|
|
24249
|
+
} catch {
|
|
24250
|
+
return false;
|
|
24251
|
+
}
|
|
24252
|
+
const { hrefKey, labelKey, index } = inserted;
|
|
24253
|
+
deps.applyLinkByKey(hrefKey, page.path);
|
|
24254
|
+
setLabelText(labelKey, page.title);
|
|
24255
|
+
commit(
|
|
24256
|
+
{
|
|
24257
|
+
[hrefKey]: page.path,
|
|
24258
|
+
[labelKey]: page.title,
|
|
24259
|
+
[NAV_COUNT_KEY]: String(index + 1),
|
|
24260
|
+
[NAV_ORDER_KEY]: getNavbarOrderJson()
|
|
24261
|
+
},
|
|
24262
|
+
deps
|
|
24263
|
+
);
|
|
24264
|
+
return true;
|
|
24265
|
+
}
|
|
24266
|
+
function retargetPageLinks(change, deps) {
|
|
24267
|
+
const { oldPath, newPath, oldTitle, newTitle } = change;
|
|
24268
|
+
if (!oldPath || !newPath || normalizePath2(oldPath) === normalizePath2(newPath)) return 0;
|
|
24269
|
+
const content = deps.getEditContent();
|
|
24270
|
+
const delta = {};
|
|
24271
|
+
for (const anchor of Array.from(document.querySelectorAll("[data-ohw-href-key]"))) {
|
|
24272
|
+
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
24273
|
+
if (!isPageLinkKey(hrefKey)) continue;
|
|
24274
|
+
const href = currentHref(hrefKey, anchor, content);
|
|
24275
|
+
if (!pointsAt(href, oldPath)) continue;
|
|
24276
|
+
const nextHref = retargetHref(href, oldPath, newPath);
|
|
24277
|
+
deps.applyLinkByKey(hrefKey, nextHref);
|
|
24278
|
+
delta[hrefKey] = nextHref;
|
|
24279
|
+
if (!oldTitle || !newTitle) continue;
|
|
24280
|
+
const labelKey = labelKeyFor(hrefKey);
|
|
24281
|
+
const label = content[labelKey] ?? anchor.querySelector('[data-ohw-editable="text"]')?.textContent ?? "";
|
|
24282
|
+
if (label.trim() !== oldTitle) continue;
|
|
24283
|
+
setLabelText(labelKey, newTitle);
|
|
24284
|
+
delta[labelKey] = newTitle;
|
|
24285
|
+
}
|
|
24286
|
+
commit(delta, deps);
|
|
24287
|
+
return Object.keys(delta).filter((key) => key.endsWith("-href")).length;
|
|
24288
|
+
}
|
|
24289
|
+
|
|
23978
24290
|
// src/ui/navbar-container-chrome.tsx
|
|
23979
|
-
import { Plus as
|
|
24291
|
+
import { Plus as Plus5 } from "lucide-react";
|
|
23980
24292
|
import { jsx as jsx37 } from "react/jsx-runtime";
|
|
23981
24293
|
function NavbarContainerChrome({
|
|
23982
24294
|
rect,
|
|
@@ -24012,7 +24324,7 @@ function NavbarContainerChrome({
|
|
|
24012
24324
|
e.stopPropagation();
|
|
24013
24325
|
onAdd();
|
|
24014
24326
|
},
|
|
24015
|
-
children: /* @__PURE__ */ jsx37(
|
|
24327
|
+
children: /* @__PURE__ */ jsx37(Plus5, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
24016
24328
|
}
|
|
24017
24329
|
)
|
|
24018
24330
|
}
|
|
@@ -24084,7 +24396,7 @@ function Badge({ className, variant, ...props }) {
|
|
|
24084
24396
|
}
|
|
24085
24397
|
|
|
24086
24398
|
// src/OhhwellsBridge.tsx
|
|
24087
|
-
import { Brush as Brush2, Link as Link2, Plus as
|
|
24399
|
+
import { Brush as Brush2, Link as Link2, Plus as Plus6, Settings } from "lucide-react";
|
|
24088
24400
|
import { Fragment as Fragment13, jsx as jsx40, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
24089
24401
|
var PRIMARY7 = "#0885FE";
|
|
24090
24402
|
var IMAGE_FADE_MS = 300;
|
|
@@ -24862,7 +25174,7 @@ function getNavigationSelectionParent(el) {
|
|
|
24862
25174
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
24863
25175
|
return resolveFooterLinksContainerFrom(el);
|
|
24864
25176
|
}
|
|
24865
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
|
|
25177
|
+
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)) {
|
|
24866
25178
|
return getNavigationRoot(el);
|
|
24867
25179
|
}
|
|
24868
25180
|
return null;
|
|
@@ -25084,7 +25396,6 @@ var ICONS = {
|
|
|
25084
25396
|
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"/>',
|
|
25085
25397
|
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"/>'
|
|
25086
25398
|
};
|
|
25087
|
-
var HEIGHT_SETTLE_DELAYS = [150, 400, 800];
|
|
25088
25399
|
var SELECTION_CHROME_GAP2 = 4;
|
|
25089
25400
|
var TOOLBAR_STROKE_GAP2 = 4;
|
|
25090
25401
|
var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
|
|
@@ -25182,7 +25493,7 @@ function applyVisibleViewport(el, parentScroll) {
|
|
|
25182
25493
|
el.style.top = `${top}px`;
|
|
25183
25494
|
el.style.height = `${height}px`;
|
|
25184
25495
|
}
|
|
25185
|
-
var
|
|
25496
|
+
var TOOLBAR_EDGE_MARGIN4 = 4;
|
|
25186
25497
|
function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
25187
25498
|
const isAbove = transform.includes("translateY(-100%)");
|
|
25188
25499
|
let visualTop = isAbove ? top - approxH : top;
|
|
@@ -25209,8 +25520,8 @@ function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
|
25209
25520
|
function clampToolbarLeft(centerX, toolbarWidth) {
|
|
25210
25521
|
const half = toolbarWidth / 2;
|
|
25211
25522
|
return Math.max(
|
|
25212
|
-
|
|
25213
|
-
Math.min(centerX, window.innerWidth -
|
|
25523
|
+
TOOLBAR_EDGE_MARGIN4 + half,
|
|
25524
|
+
Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN4 - half)
|
|
25214
25525
|
);
|
|
25215
25526
|
}
|
|
25216
25527
|
function calcToolbarPos(rect, parentScroll, toolbarW = 306) {
|
|
@@ -25611,7 +25922,7 @@ function OhhwellsBridge() {
|
|
|
25611
25922
|
}, []);
|
|
25612
25923
|
const subdomainFromQuery = searchParams.get("subdomain");
|
|
25613
25924
|
const [subdomain, setSubdomain] = useState18(() => resolveSubdomain(subdomainFromQuery));
|
|
25614
|
-
|
|
25925
|
+
useLayoutEffect7(() => {
|
|
25615
25926
|
const next = resolveSubdomain(subdomainFromQuery);
|
|
25616
25927
|
if (next !== subdomain) setSubdomain(next);
|
|
25617
25928
|
if (next) return;
|
|
@@ -26090,21 +26401,6 @@ function OhhwellsBridge() {
|
|
|
26090
26401
|
const [isItemDragging, setIsItemDragging] = useState18(false);
|
|
26091
26402
|
const [isFooterFrameSelection, setIsFooterFrameSelection] = useState18(false);
|
|
26092
26403
|
isFooterFrameSelectionRef.current = isFooterFrameSelection;
|
|
26093
|
-
const [floatingPanel, setFloatingPanel] = useState18(null);
|
|
26094
|
-
const floatingPanelOpenRef = useRef14(false);
|
|
26095
|
-
floatingPanelOpenRef.current = floatingPanel !== null;
|
|
26096
|
-
const floatingPanelRef = useRef14(null);
|
|
26097
|
-
floatingPanelRef.current = floatingPanel;
|
|
26098
|
-
const [floatingPanelPos, setFloatingPanelPos] = useState18(null);
|
|
26099
|
-
const buttonCollectionDragRef = useRef14(null);
|
|
26100
|
-
const buttonDropInsertIndexRef = useRef14(null);
|
|
26101
|
-
const [buttonDropSlots, setButtonDropSlots] = useState18([]);
|
|
26102
|
-
const [activeButtonDropIndex, setActiveButtonDropIndex] = useState18(null);
|
|
26103
|
-
const buttonPointerDragRef = useRef14(null);
|
|
26104
|
-
const [buttonStyleTick, setButtonStyleTick] = useState18(0);
|
|
26105
|
-
const [logoSizeDraft, setLogoSizeDraft] = useState18(null);
|
|
26106
|
-
const [editorViewport, setEditorViewport] = useState18("desktop");
|
|
26107
|
-
const [parentScrollSnap, setParentScrollSnap] = useState18(null);
|
|
26108
26404
|
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = useState18(null);
|
|
26109
26405
|
const [footerHeadingVisible, setFooterHeadingVisible] = useState18(null);
|
|
26110
26406
|
const footerDragRef = useRef14(null);
|
|
@@ -26130,6 +26426,21 @@ function OhhwellsBridge() {
|
|
|
26130
26426
|
const stylesRef = useRef14("");
|
|
26131
26427
|
const appliedDrawerRef = useRef14(null);
|
|
26132
26428
|
const pendingDeleteUndoRef = useRef14(null);
|
|
26429
|
+
const [floatingPanel, setFloatingPanel] = useState18(null);
|
|
26430
|
+
const floatingPanelOpenRef = useRef14(false);
|
|
26431
|
+
const floatingPanelRef = useRef14(null);
|
|
26432
|
+
floatingPanelRef.current = floatingPanel;
|
|
26433
|
+
const setFloatingPanelRef = useRef14(setFloatingPanel);
|
|
26434
|
+
const [floatingPanelPos, setFloatingPanelPos] = useState18(null);
|
|
26435
|
+
const buttonCollectionDragRef = useRef14(null);
|
|
26436
|
+
const buttonDropInsertIndexRef = useRef14(null);
|
|
26437
|
+
const [buttonDropSlots, setButtonDropSlots] = useState18([]);
|
|
26438
|
+
const [activeButtonDropIndex, setActiveButtonDropIndex] = useState18(null);
|
|
26439
|
+
const buttonPointerDragRef = useRef14(null);
|
|
26440
|
+
const [buttonStyleTick, setButtonStyleTick] = useState18(0);
|
|
26441
|
+
const [logoSizeDraft, setLogoSizeDraft] = useState18(null);
|
|
26442
|
+
const [editorViewport, setEditorViewport] = useState18("desktop");
|
|
26443
|
+
const [parentScrollSnap, setParentScrollSnap] = useState18(null);
|
|
26133
26444
|
const [sitePages, setSitePages] = useState18([]);
|
|
26134
26445
|
const collectionItemsRef = useRef14(/* @__PURE__ */ new Map());
|
|
26135
26446
|
const [sectionsByPath, setSectionsByPath] = useState18({});
|
|
@@ -26139,7 +26450,18 @@ function OhhwellsBridge() {
|
|
|
26139
26450
|
const linkPopoverOpenRef = useRef14(false);
|
|
26140
26451
|
const linkPopoverGraceUntilRef = useRef14(0);
|
|
26141
26452
|
setLinkPopoverRef.current = setLinkPopover;
|
|
26453
|
+
setFloatingPanelRef.current = setFloatingPanel;
|
|
26142
26454
|
linkPopoverSessionRef.current = linkPopover;
|
|
26455
|
+
floatingPanelOpenRef.current = Boolean(floatingPanel);
|
|
26456
|
+
useEffect17(() => {
|
|
26457
|
+
const syncViewport = () => {
|
|
26458
|
+
const next = window.innerWidth <= 480 ? "mobile" : "desktop";
|
|
26459
|
+
setEditorViewport((prev) => prev === next ? prev : next);
|
|
26460
|
+
};
|
|
26461
|
+
syncViewport();
|
|
26462
|
+
window.addEventListener("resize", syncViewport);
|
|
26463
|
+
return () => window.removeEventListener("resize", syncViewport);
|
|
26464
|
+
}, []);
|
|
26143
26465
|
useEffect17(() => {
|
|
26144
26466
|
setSectionOrderPersistHandler((entries) => {
|
|
26145
26467
|
const currentPath = window.location.pathname;
|
|
@@ -26288,6 +26610,43 @@ function OhhwellsBridge() {
|
|
|
26288
26610
|
if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
|
|
26289
26611
|
return () => window.removeEventListener("message", onSitePages);
|
|
26290
26612
|
}, [isEditMode, postToParent2]);
|
|
26613
|
+
useEffect17(() => {
|
|
26614
|
+
if (!isEditMode) return;
|
|
26615
|
+
const deps = {
|
|
26616
|
+
getEditContent: () => editContentRef.current,
|
|
26617
|
+
setEditContent: (next) => {
|
|
26618
|
+
editContentRef.current = next;
|
|
26619
|
+
},
|
|
26620
|
+
applyLinkByKey,
|
|
26621
|
+
postToParent: postToParent2
|
|
26622
|
+
};
|
|
26623
|
+
const onPageMessage = (e) => {
|
|
26624
|
+
if (e.data?.type === "ow:page-created") {
|
|
26625
|
+
const { path, title } = e.data;
|
|
26626
|
+
if (typeof path !== "string" || !path) return;
|
|
26627
|
+
if (addNavLinkForPage({ path, title: typeof title === "string" && title ? title : path }, deps)) {
|
|
26628
|
+
enforceLinkHrefs();
|
|
26629
|
+
}
|
|
26630
|
+
return;
|
|
26631
|
+
}
|
|
26632
|
+
if (e.data?.type === "ow:page-renamed") {
|
|
26633
|
+
const { oldPath, newPath, oldTitle, newTitle } = e.data;
|
|
26634
|
+
if (typeof oldPath !== "string" || typeof newPath !== "string") return;
|
|
26635
|
+
const moved = retargetPageLinks(
|
|
26636
|
+
{
|
|
26637
|
+
oldPath,
|
|
26638
|
+
newPath,
|
|
26639
|
+
oldTitle: typeof oldTitle === "string" ? oldTitle : void 0,
|
|
26640
|
+
newTitle: typeof newTitle === "string" ? newTitle : void 0
|
|
26641
|
+
},
|
|
26642
|
+
deps
|
|
26643
|
+
);
|
|
26644
|
+
if (moved > 0) enforceLinkHrefs();
|
|
26645
|
+
}
|
|
26646
|
+
};
|
|
26647
|
+
window.addEventListener("message", onPageMessage);
|
|
26648
|
+
return () => window.removeEventListener("message", onPageMessage);
|
|
26649
|
+
}, [isEditMode, postToParent2]);
|
|
26291
26650
|
useEffect17(() => {
|
|
26292
26651
|
if (!isEditMode || shouldUseDevFixtures()) return;
|
|
26293
26652
|
void loadAllSectionsManifest().then((manifest) => {
|
|
@@ -27809,7 +28168,7 @@ function OhhwellsBridge() {
|
|
|
27809
28168
|
isFooterFrameSelection,
|
|
27810
28169
|
postToParent2
|
|
27811
28170
|
]);
|
|
27812
|
-
|
|
28171
|
+
useLayoutEffect7(() => {
|
|
27813
28172
|
if (!subdomain || isEditMode) {
|
|
27814
28173
|
setFetchState("done");
|
|
27815
28174
|
return;
|
|
@@ -27836,6 +28195,7 @@ function OhhwellsBridge() {
|
|
|
27836
28195
|
applyAiFooterFromContent(content);
|
|
27837
28196
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
27838
28197
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
28198
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
27839
28199
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
27840
28200
|
}
|
|
27841
28201
|
applyBrandChrome(content);
|
|
@@ -27846,15 +28206,16 @@ function OhhwellsBridge() {
|
|
|
27846
28206
|
if (key === "__ohw_sections") continue;
|
|
27847
28207
|
if (key === AI_SECTIONS_KEY) continue;
|
|
27848
28208
|
if (key === AI_FOOTER_KEY) continue;
|
|
28209
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
28210
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27849
28211
|
if (key === BRAND_KIT_KEY) continue;
|
|
27850
28212
|
if (key === STYLE_STORE_KEY) continue;
|
|
27851
28213
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
27852
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
27853
28214
|
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
27854
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27855
28215
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
27856
28216
|
continue;
|
|
27857
28217
|
}
|
|
28218
|
+
if (key.endsWith(SECTION_EMBED_SUFFIX)) continue;
|
|
27858
28219
|
if (applyVideoSettingNode(key, val)) continue;
|
|
27859
28220
|
if (applyCarouselNode(key, val)) continue;
|
|
27860
28221
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -27894,6 +28255,7 @@ function OhhwellsBridge() {
|
|
|
27894
28255
|
});
|
|
27895
28256
|
applyLinkByKey(key, val);
|
|
27896
28257
|
}
|
|
28258
|
+
applySectionEmbeds(content);
|
|
27897
28259
|
applyLogoFromContent(content);
|
|
27898
28260
|
applyLogoSizes(content);
|
|
27899
28261
|
reconcileNavbarItemsFromContent(content);
|
|
@@ -28082,20 +28444,22 @@ function OhhwellsBridge() {
|
|
|
28082
28444
|
}
|
|
28083
28445
|
applyAiFooterFromContent(content);
|
|
28084
28446
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
28447
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
28085
28448
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
28086
28449
|
}
|
|
28087
28450
|
for (const [key, val] of Object.entries(content)) {
|
|
28088
28451
|
if (key === "__ohw_sections") continue;
|
|
28089
28452
|
if (key === AI_SECTIONS_KEY) continue;
|
|
28090
28453
|
if (key === AI_FOOTER_KEY) continue;
|
|
28454
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
28455
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
28091
28456
|
if (key === BRAND_KIT_KEY) continue;
|
|
28092
28457
|
if (key === STYLE_STORE_KEY) continue;
|
|
28093
28458
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
28094
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
28095
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
28096
28459
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
28097
28460
|
continue;
|
|
28098
28461
|
}
|
|
28462
|
+
if (key.endsWith(SECTION_EMBED_SUFFIX)) continue;
|
|
28099
28463
|
if (applyVideoSettingNode(key, val)) continue;
|
|
28100
28464
|
if (applyCarouselNode(key, val)) continue;
|
|
28101
28465
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -28120,6 +28484,7 @@ function OhhwellsBridge() {
|
|
|
28120
28484
|
});
|
|
28121
28485
|
applyLinkByKey(key, val);
|
|
28122
28486
|
}
|
|
28487
|
+
applySectionEmbeds(content);
|
|
28123
28488
|
applyLogoFromContent(content);
|
|
28124
28489
|
reconcileNavbarItemsFromContent(content);
|
|
28125
28490
|
reconcileFooterOrderFromContent(content);
|
|
@@ -28175,7 +28540,7 @@ function OhhwellsBridge() {
|
|
|
28175
28540
|
if (debounceTimer) clearTimeout(debounceTimer);
|
|
28176
28541
|
};
|
|
28177
28542
|
}, [subdomain, isEditMode, pathname]);
|
|
28178
|
-
|
|
28543
|
+
useLayoutEffect7(() => {
|
|
28179
28544
|
const el = document.getElementById("ohw-loader");
|
|
28180
28545
|
if (!el) return;
|
|
28181
28546
|
const visible = Boolean(subdomain) && fetchState !== "done";
|
|
@@ -28359,26 +28724,11 @@ function OhhwellsBridge() {
|
|
|
28359
28724
|
const t2 = setTimeout(measure, 500);
|
|
28360
28725
|
const ro = new ResizeObserver(schedule);
|
|
28361
28726
|
ro.observe(document.body);
|
|
28362
|
-
let lastWidth = window.innerWidth;
|
|
28363
|
-
let resizeTimers = [];
|
|
28364
|
-
const clearResizeTimers = () => {
|
|
28365
|
-
resizeTimers.forEach(clearTimeout);
|
|
28366
|
-
resizeTimers = [];
|
|
28367
|
-
};
|
|
28368
|
-
const handleResize = () => {
|
|
28369
|
-
if (window.innerWidth === lastWidth) return;
|
|
28370
|
-
lastWidth = window.innerWidth;
|
|
28371
|
-
clearResizeTimers();
|
|
28372
|
-
resizeTimers = HEIGHT_SETTLE_DELAYS.map((delay) => setTimeout(measure, delay));
|
|
28373
|
-
};
|
|
28374
|
-
window.addEventListener("resize", handleResize);
|
|
28375
28727
|
return () => {
|
|
28376
28728
|
clearTimeout(t1);
|
|
28377
28729
|
clearTimeout(t2);
|
|
28378
28730
|
if (raf != null) cancelAnimationFrame(raf);
|
|
28379
28731
|
ro.disconnect();
|
|
28380
|
-
clearResizeTimers();
|
|
28381
|
-
window.removeEventListener("resize", handleResize);
|
|
28382
28732
|
};
|
|
28383
28733
|
}, [pathname, isEditMode, postToParent2]);
|
|
28384
28734
|
useEffect17(() => {
|
|
@@ -28675,6 +29025,13 @@ function OhhwellsBridge() {
|
|
|
28675
29025
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
28676
29026
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
28677
29027
|
if (isInsideLinkEditor(target)) return;
|
|
29028
|
+
if (isInsideFloatingPanel(target)) return;
|
|
29029
|
+
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
29030
|
+
if (target.closest(
|
|
29031
|
+
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
29032
|
+
)) {
|
|
29033
|
+
return;
|
|
29034
|
+
}
|
|
28678
29035
|
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
28679
29036
|
clearMediaSelectionRef.current();
|
|
28680
29037
|
}
|
|
@@ -28698,8 +29055,6 @@ function OhhwellsBridge() {
|
|
|
28698
29055
|
return;
|
|
28699
29056
|
}
|
|
28700
29057
|
}
|
|
28701
|
-
if (isInsideFloatingPanel(target)) return;
|
|
28702
|
-
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
28703
29058
|
const collectionItem = matchCollectionItemClick(target, collectionItemsRef.current);
|
|
28704
29059
|
if (collectionItem) {
|
|
28705
29060
|
e.preventDefault();
|
|
@@ -28711,11 +29066,6 @@ function OhhwellsBridge() {
|
|
|
28711
29066
|
});
|
|
28712
29067
|
return;
|
|
28713
29068
|
}
|
|
28714
|
-
if (target.closest(
|
|
28715
|
-
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
28716
|
-
)) {
|
|
28717
|
-
return;
|
|
28718
|
-
}
|
|
28719
29069
|
{
|
|
28720
29070
|
const formEl = getFormElement(target);
|
|
28721
29071
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
@@ -28869,9 +29219,13 @@ function OhhwellsBridge() {
|
|
|
28869
29219
|
if (isIconEditable(editable) && !getSocialItem(editable)) {
|
|
28870
29220
|
e.preventDefault();
|
|
28871
29221
|
e.stopPropagation();
|
|
28872
|
-
selectIconElementRef.current(editable);
|
|
28873
29222
|
const aiIcon = editable.hasAttribute("data-ai-icon");
|
|
28874
29223
|
const featureIcon = aiIcon && /\.features\.\d+\.icon$/.test(editable.dataset.ohwKey ?? "");
|
|
29224
|
+
if (aiIcon) {
|
|
29225
|
+
aiSectionApiRef.current?.selectFromElement(editable);
|
|
29226
|
+
} else {
|
|
29227
|
+
selectIconElementRef.current(editable);
|
|
29228
|
+
}
|
|
28875
29229
|
postToParentRef.current({
|
|
28876
29230
|
type: "ow:icon-pick",
|
|
28877
29231
|
key: editable.dataset.ohwKey ?? "",
|
|
@@ -29099,6 +29453,9 @@ function OhhwellsBridge() {
|
|
|
29099
29453
|
setHoveredItemRect(null);
|
|
29100
29454
|
hoveredNavContainerRef.current = null;
|
|
29101
29455
|
setHoveredNavContainerRect(null);
|
|
29456
|
+
siblingHintElRef.current = null;
|
|
29457
|
+
setSiblingHintRect(null);
|
|
29458
|
+
setSiblingHintRects([]);
|
|
29102
29459
|
return;
|
|
29103
29460
|
}
|
|
29104
29461
|
{
|
|
@@ -29219,7 +29576,6 @@ function OhhwellsBridge() {
|
|
|
29219
29576
|
hoveredNavContainerRef.current = null;
|
|
29220
29577
|
setHoveredNavContainerRect(null);
|
|
29221
29578
|
hoveredItemElRef.current = editable;
|
|
29222
|
-
setHoveredItemRect(isSelectedForHoverRef.current(editable) ? null : editable.getBoundingClientRect());
|
|
29223
29579
|
}
|
|
29224
29580
|
}
|
|
29225
29581
|
}
|
|
@@ -29929,7 +30285,11 @@ function OhhwellsBridge() {
|
|
|
29929
30285
|
};
|
|
29930
30286
|
const handleMouseMove = (e) => {
|
|
29931
30287
|
const { clientX, clientY } = e;
|
|
29932
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
30288
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
30289
|
+
dismissImageHover();
|
|
30290
|
+
clearImageHover();
|
|
30291
|
+
return;
|
|
30292
|
+
}
|
|
29933
30293
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) {
|
|
29934
30294
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
29935
30295
|
formHoverElRef.current = null;
|
|
@@ -29958,7 +30318,12 @@ function OhhwellsBridge() {
|
|
|
29958
30318
|
setHoveredItemRect(null);
|
|
29959
30319
|
hoveredNavContainerRef.current = null;
|
|
29960
30320
|
setHoveredNavContainerRect(null);
|
|
30321
|
+
siblingHintElRef.current = null;
|
|
30322
|
+
setSiblingHintRect(null);
|
|
30323
|
+
setSiblingHintRects([]);
|
|
29961
30324
|
dismissImageHover();
|
|
30325
|
+
clearImageHover();
|
|
30326
|
+
setSectionGap(null);
|
|
29962
30327
|
return;
|
|
29963
30328
|
}
|
|
29964
30329
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
@@ -29970,7 +30335,11 @@ function OhhwellsBridge() {
|
|
|
29970
30335
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
29971
30336
|
const { clientX, clientY } = e.data;
|
|
29972
30337
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
29973
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
30338
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
30339
|
+
dismissImageHover();
|
|
30340
|
+
clearImageHover();
|
|
30341
|
+
return;
|
|
30342
|
+
}
|
|
29974
30343
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) return;
|
|
29975
30344
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
29976
30345
|
probeSectionGapAt(clientX, clientY);
|
|
@@ -30350,6 +30719,7 @@ function OhhwellsBridge() {
|
|
|
30350
30719
|
applyAiFooterFromContent(content);
|
|
30351
30720
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
30352
30721
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
30722
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
30353
30723
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
30354
30724
|
}
|
|
30355
30725
|
applyBrandChrome(content);
|
|
@@ -30364,15 +30734,16 @@ function OhhwellsBridge() {
|
|
|
30364
30734
|
}
|
|
30365
30735
|
if (key === AI_SECTIONS_KEY) continue;
|
|
30366
30736
|
if (key === AI_FOOTER_KEY) continue;
|
|
30737
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
30738
|
+
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
30367
30739
|
if (key === BRAND_KIT_KEY) continue;
|
|
30368
30740
|
if (key === STYLE_STORE_KEY) continue;
|
|
30369
30741
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
30370
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
30371
30742
|
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
30372
|
-
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
30373
30743
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
30374
30744
|
continue;
|
|
30375
30745
|
}
|
|
30746
|
+
if (key.endsWith(SECTION_EMBED_SUFFIX)) continue;
|
|
30376
30747
|
if (applyVideoSettingNode(key, val)) continue;
|
|
30377
30748
|
if (applyCarouselNode(key, val)) continue;
|
|
30378
30749
|
document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
|
|
@@ -30398,6 +30769,7 @@ function OhhwellsBridge() {
|
|
|
30398
30769
|
});
|
|
30399
30770
|
applyLinkByKey(key, val);
|
|
30400
30771
|
}
|
|
30772
|
+
applySectionEmbeds(content);
|
|
30401
30773
|
applyLogoFromContent(content);
|
|
30402
30774
|
applyLogoSizes(content);
|
|
30403
30775
|
document.querySelectorAll('[data-ohw-editable="form"]').forEach((form) => {
|
|
@@ -31005,6 +31377,12 @@ function OhhwellsBridge() {
|
|
|
31005
31377
|
closeLinkPopoverRef.current();
|
|
31006
31378
|
return;
|
|
31007
31379
|
}
|
|
31380
|
+
if (floatingPanelOpenRef.current) {
|
|
31381
|
+
setFloatingPanelRef.current(null);
|
|
31382
|
+
deselectRef.current();
|
|
31383
|
+
deactivateRef.current();
|
|
31384
|
+
return;
|
|
31385
|
+
}
|
|
31008
31386
|
deselectRef.current();
|
|
31009
31387
|
deactivateRef.current();
|
|
31010
31388
|
clearMediaSelectionRef.current();
|
|
@@ -31393,7 +31771,7 @@ function OhhwellsBridge() {
|
|
|
31393
31771
|
const sectionEl = foundEl && !foundEl.hasAttribute("data-ohw-ai-template-hidden") && !foundEl.hasAttribute("data-ohw-ai-removed") && !foundEl.hasAttribute("data-ohw-ai-replaced-by") ? foundEl : null;
|
|
31394
31772
|
const nodes = sectionEl ? collectEditableNodes(void 0, sectionEl).filter(
|
|
31395
31773
|
(n) => n.key && !n.key.startsWith("__ohw_") && !["meta", "sections", "video-setting"].includes(n.type)
|
|
31396
|
-
).map((n) => ({ ...n, text: n.text ?? "", type: normalizeAiNodeType(n.type) })) : [];
|
|
31774
|
+
).map((n) => ({ ...n, text: n.text ?? "", type: normalizeAiNodeType(n.type) })).map((n) => withNodeFontSize(n, sectionEl)) : [];
|
|
31397
31775
|
const items = sectionEl ? collectItemGroups(sectionEl) : [];
|
|
31398
31776
|
const box = sectionEl?.getBoundingClientRect();
|
|
31399
31777
|
const rect = box ? {
|
|
@@ -31840,10 +32218,10 @@ function OhhwellsBridge() {
|
|
|
31840
32218
|
window.removeEventListener("message", handleDuplicateSection);
|
|
31841
32219
|
window.removeEventListener("message", handleDeactivate);
|
|
31842
32220
|
window.removeEventListener("message", handleSelectNav);
|
|
31843
|
-
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
31844
32221
|
window.removeEventListener("message", handleToastAction);
|
|
31845
32222
|
window.removeEventListener("message", handleFormCount);
|
|
31846
32223
|
window.removeEventListener("message", handleUiEscape);
|
|
32224
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
31847
32225
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
31848
32226
|
autoSaveTimers.current.clear();
|
|
31849
32227
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
@@ -32137,7 +32515,7 @@ function OhhwellsBridge() {
|
|
|
32137
32515
|
postToParent2({
|
|
32138
32516
|
type: "ow:ready",
|
|
32139
32517
|
version: "1",
|
|
32140
|
-
bridgeVersion: "0.1.
|
|
32518
|
+
bridgeVersion: "0.1.160-next.428",
|
|
32141
32519
|
path: pathname,
|
|
32142
32520
|
nodes: collectEditableNodes(editContentRef.current),
|
|
32143
32521
|
sections
|
|
@@ -32872,7 +33250,7 @@ function OhhwellsBridge() {
|
|
|
32872
33250
|
className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
|
|
32873
33251
|
onClick: () => setFieldTypePickerOpen((open) => !open),
|
|
32874
33252
|
"data-ohw-add-field": "",
|
|
32875
|
-
children: /* @__PURE__ */ jsx40(
|
|
33253
|
+
children: /* @__PURE__ */ jsx40(Plus6, { size: 15, "aria-hidden": true })
|
|
32876
33254
|
}
|
|
32877
33255
|
),
|
|
32878
33256
|
/* @__PURE__ */ jsx40("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|