@ohhwells/bridge 0.1.148 → 0.1.149-next.402
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +860 -724
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +898 -746
- package/dist/index.js.map +1 -1
- package/dist/pages.cjs +1 -1
- package/dist/pages.cjs.map +1 -1
- package/dist/pages.js +1 -1
- package/dist/pages.js.map +1 -1
- package/dist/styles.css +116 -0
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -1726,7 +1726,8 @@ function labelElement2(el) {
|
|
|
1726
1726
|
return el.querySelector('[data-ohw-editable="text"], [data-ohw-editable="plain"]') ?? el.querySelector("[data-ohw-key]");
|
|
1727
1727
|
}
|
|
1728
1728
|
function buttonLabel(el) {
|
|
1729
|
-
|
|
1729
|
+
const label = labelElement2(el);
|
|
1730
|
+
return (label ? label.innerHTML : el.textContent ?? "").trim();
|
|
1730
1731
|
}
|
|
1731
1732
|
function buttonHref(el) {
|
|
1732
1733
|
return el.getAttribute("href") ?? "";
|
|
@@ -1865,7 +1866,7 @@ function duplicateButton(source, content) {
|
|
|
1865
1866
|
stampVariantClass(copy, copyAssignment.variant);
|
|
1866
1867
|
applyButtonStyle(copy, copyAssignment, paintedTokensOf(source) ?? tokens);
|
|
1867
1868
|
const copyLabelEl = labelElement2(copy);
|
|
1868
|
-
if (copyLabelEl) copyLabelEl.
|
|
1869
|
+
if (copyLabelEl) copyLabelEl.innerHTML = label;
|
|
1869
1870
|
let collection = buttonCollectionOf(source);
|
|
1870
1871
|
const collections = readCollections(content);
|
|
1871
1872
|
let collectionId = collection?.getAttribute(COLLECTION_ATTR) ?? "";
|
|
@@ -2191,7 +2192,7 @@ function applySnapshotContent(el, snapshot, content) {
|
|
|
2191
2192
|
const label = labelElement2(el);
|
|
2192
2193
|
if (label) {
|
|
2193
2194
|
if (label.getAttribute("data-ohw-key") !== labelKey) label.setAttribute("data-ohw-key", labelKey);
|
|
2194
|
-
if (label.
|
|
2195
|
+
if (label.innerHTML !== text) label.innerHTML = text;
|
|
2195
2196
|
}
|
|
2196
2197
|
}
|
|
2197
2198
|
function reconcileButtonCollections(doc, content) {
|
|
@@ -4276,7 +4277,7 @@ function buildNavLink(index, href, label, template) {
|
|
|
4276
4277
|
const span = document.createElement("span");
|
|
4277
4278
|
span.setAttribute("data-ohw-editable", "text");
|
|
4278
4279
|
span.setAttribute("data-ohw-key", `nav-${index}-label`);
|
|
4279
|
-
span.
|
|
4280
|
+
span.innerHTML = label;
|
|
4280
4281
|
anchor.appendChild(span);
|
|
4281
4282
|
return anchor;
|
|
4282
4283
|
}
|
|
@@ -6636,6 +6637,21 @@ function pricingCardFeatureCount(tree, index) {
|
|
|
6636
6637
|
const target = findPricingCollection(tree)?.children?.[index];
|
|
6637
6638
|
return target ? pricingFeatureList(target).length : 0;
|
|
6638
6639
|
}
|
|
6640
|
+
function prevailingFeatureIcon(features) {
|
|
6641
|
+
const counts = /* @__PURE__ */ new Map();
|
|
6642
|
+
for (const row of features) {
|
|
6643
|
+
const key = `${row.icon ?? ""}|${row.iconColor ?? ""}`;
|
|
6644
|
+
const entry = counts.get(key) ?? { count: 0, ...row.icon ? { icon: row.icon } : {}, ...row.iconColor ? { iconColor: row.iconColor } : {} };
|
|
6645
|
+
entry.count += 1;
|
|
6646
|
+
counts.set(key, entry);
|
|
6647
|
+
}
|
|
6648
|
+
let best = null;
|
|
6649
|
+
for (const entry of counts.values()) {
|
|
6650
|
+
if (!best || entry.count > best.count) best = entry;
|
|
6651
|
+
}
|
|
6652
|
+
if (!best) return {};
|
|
6653
|
+
return { ...best.icon ? { icon: best.icon } : {}, ...best.iconColor ? { iconColor: best.iconColor } : {} };
|
|
6654
|
+
}
|
|
6639
6655
|
function addPricingCardFeature(tree, index, text) {
|
|
6640
6656
|
return withPricingCollection(tree, (collection) => {
|
|
6641
6657
|
const children = collection.children;
|
|
@@ -6644,7 +6660,7 @@ function addPricingCardFeature(tree, index, text) {
|
|
|
6644
6660
|
const features = pricingFeatureList(target);
|
|
6645
6661
|
if (features.length >= PRICING_FEATURES_MAX) return false;
|
|
6646
6662
|
target.slots = target.slots ?? {};
|
|
6647
|
-
target.slots.features = [...features, { text }];
|
|
6663
|
+
target.slots.features = [...features, { text, ...prevailingFeatureIcon(features) }];
|
|
6648
6664
|
return true;
|
|
6649
6665
|
});
|
|
6650
6666
|
}
|
|
@@ -7827,7 +7843,7 @@ var AI_MOBILE_CSS = [
|
|
|
7827
7843
|
// page's first section. Top only (bottom needs no nav clearance); ~96px approximates the
|
|
7828
7844
|
// template nav's own height (measured ~94px) — there's no shared `--ohw-header-h` var to read
|
|
7829
7845
|
// an exact figure from (no live measurement exists), so this is a safe approximation, not a
|
|
7830
|
-
// pixel-exact fit. Horizontal spacing already comes from `data-ai-
|
|
7846
|
+
// pixel-exact fit. Horizontal spacing already comes from `data-ai-section-inner`.
|
|
7831
7847
|
'[data-ai-overlay-clearance] [data-ai-overlap-layer="overlay"]{padding-top:96px}',
|
|
7832
7848
|
// A full-bleed carousel's height is pure arithmetic: it spans the whole window, so 16/9 turns
|
|
7833
7849
|
// window width straight into height. Measured at 16/9 it came out ~90% of the viewport at EVERY
|
|
@@ -7843,8 +7859,10 @@ var AI_MOBILE_CSS = [
|
|
|
7843
7859
|
"[data-ai-section]{overflow-x:hidden}",
|
|
7844
7860
|
// `:not([data-ai-full-bleed])`: this `!important` gutter beat the inline `padding: 0` that a
|
|
7845
7861
|
// full-bleed section's container sets, so a carousel/media hero that is edge-to-edge on desktop
|
|
7846
|
-
// still got a 20px band of section background down both sides on a phone.
|
|
7847
|
-
|
|
7862
|
+
// still got a 20px band of section background down both sides on a phone. The footer's own
|
|
7863
|
+
// container keeps the unguarded rule below — `data-ai-full-bleed` can never appear on it.
|
|
7864
|
+
"[data-ai-section-inner]:not([data-ai-full-bleed]){padding:0 20px !important}",
|
|
7865
|
+
"[data-ai-container]{padding:0 20px !important}",
|
|
7848
7866
|
"[data-ai-row]{display:flex !important;flex-direction:column !important;align-items:stretch !important}",
|
|
7849
7867
|
"[data-ai-cell]{width:100%;min-width:0}",
|
|
7850
7868
|
// The rule above turns every row into a COLUMN flex container on phones, which silently breaks
|
|
@@ -8049,6 +8067,31 @@ function pricingCardEmphasis(featured, ctx, hasBg) {
|
|
|
8049
8067
|
function textAttrs(ctx, path) {
|
|
8050
8068
|
return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
|
|
8051
8069
|
}
|
|
8070
|
+
var AI_RESPONSIVE_CSS = [
|
|
8071
|
+
"@media (max-width: 960px) {",
|
|
8072
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: repeat(2, 1fr) !important; }",
|
|
8073
|
+
' [data-ai-responsive] [data-ai-grid="1"] { grid-template-columns: 1fr !important; }',
|
|
8074
|
+
"}",
|
|
8075
|
+
"@media (max-width: 640px) {",
|
|
8076
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
|
|
8077
|
+
" [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
|
|
8078
|
+
// Group containers flatten to a column on phones; span placements come along for free.
|
|
8079
|
+
// `:not([data-ai-group="overlap"])` for the same reason as the twin pair in AI_MOBILE_CSS — see
|
|
8080
|
+
// the comment there. This sheet's copy is the narrower selector, so without the exemption it
|
|
8081
|
+
// flattens an `overlap` hero below 640px even though the other rule stands down: measured a 390px
|
|
8082
|
+
// viewport with the heading/CTA in flow *under* the image, 219px of section background where the
|
|
8083
|
+
// layered text used to be.
|
|
8084
|
+
' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) { display: flex !important; flex-direction: column !important; }',
|
|
8085
|
+
' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) > * { grid-column: auto !important; }',
|
|
8086
|
+
// `:not([data-ai-full-bleed])` for the same reason as the twin rule in AI_MOBILE_CSS: this one
|
|
8087
|
+
// is narrower (0,2,0 vs 0,1,0) and also `!important`, so without the guard it wins outright and
|
|
8088
|
+
// a full-bleed hero gets its 20px side band back below 640px only — the one width where the
|
|
8089
|
+
// other rule had already been taught to stand down.
|
|
8090
|
+
" [data-ai-responsive] [data-ai-section-inner]:not([data-ai-full-bleed]) { padding-left: 20px !important; padding-right: 20px !important; }",
|
|
8091
|
+
" [data-ai-responsive] { overflow-x: hidden; }",
|
|
8092
|
+
" [data-ai-responsive] img { max-width: 100%; }",
|
|
8093
|
+
"}"
|
|
8094
|
+
].join("\n");
|
|
8052
8095
|
var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
8053
8096
|
function MediaBox({
|
|
8054
8097
|
refValue,
|
|
@@ -8103,7 +8146,7 @@ function MediaBox({
|
|
|
8103
8146
|
position: fill ? "absolute" : void 0,
|
|
8104
8147
|
inset: fill ? 0 : void 0,
|
|
8105
8148
|
width: fill ? "100%" : fixedSize ? "auto" : "100%",
|
|
8106
|
-
height: fill ? "100%" : void 0,
|
|
8149
|
+
height: fill ? "100%" : fixedSize ? height : void 0,
|
|
8107
8150
|
aspectRatio: fill ? void 0 : aspectRatio,
|
|
8108
8151
|
minHeight: fill || fixedSize ? void 0 : height ?? (aspectRatio ? void 0 : 180),
|
|
8109
8152
|
borderRadius: radius,
|
|
@@ -9599,7 +9642,7 @@ function CollectionBlock({ node, ctx, path }) {
|
|
|
9599
9642
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
9600
9643
|
"div",
|
|
9601
9644
|
{
|
|
9602
|
-
"data-ai-grid":
|
|
9645
|
+
"data-ai-grid": String(itemsPerRow),
|
|
9603
9646
|
"data-ohw-pricing-collection": isPricing ? "" : void 0,
|
|
9604
9647
|
style: {
|
|
9605
9648
|
display: "grid",
|
|
@@ -9901,7 +9944,7 @@ function renderNode(node, ctx, path, ambientAlign) {
|
|
|
9901
9944
|
},
|
|
9902
9945
|
children: [
|
|
9903
9946
|
i > 0 && ctx.heroOverlapFullBleed ? (
|
|
9904
|
-
// The section's `data-ai-
|
|
9947
|
+
// The section's `data-ai-section-inner` gave up its max-width/gutter so the base
|
|
9905
9948
|
// layer (this group's i===0 sibling) can span edge-to-edge — reintroduced here,
|
|
9906
9949
|
// scoped to just the overlay text, so a heading/copy/CTA stack doesn't stretch
|
|
9907
9950
|
// the full section width instead of reading at the usual content width.
|
|
@@ -10320,6 +10363,7 @@ function AiTreeRenderer({
|
|
|
10320
10363
|
...fillHeight ? { "data-ai-fill-height": "" } : {},
|
|
10321
10364
|
...needsOverlayClearance ? { "data-ai-overlay-clearance": "" } : {},
|
|
10322
10365
|
...bgAttrs,
|
|
10366
|
+
"data-ai-responsive": "",
|
|
10323
10367
|
style: {
|
|
10324
10368
|
position: "relative",
|
|
10325
10369
|
padding: `${padCss} 0`,
|
|
@@ -10333,12 +10377,13 @@ function AiTreeRenderer({
|
|
|
10333
10377
|
...fillHeight ? { display: "grid" } : {}
|
|
10334
10378
|
},
|
|
10335
10379
|
children: [
|
|
10336
|
-
|
|
10380
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_RESPONSIVE_CSS }),
|
|
10337
10381
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_MOBILE_CSS }),
|
|
10382
|
+
isOverlay && backgroundUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { position: "absolute", inset: 0, background: `rgba(255,255,255,${overlayAlpha})` } }),
|
|
10338
10383
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
10339
10384
|
"div",
|
|
10340
10385
|
{
|
|
10341
|
-
"data-ai-
|
|
10386
|
+
"data-ai-section-inner": "",
|
|
10342
10387
|
...fullBleedMedia ? { "data-ai-full-bleed": "" } : {},
|
|
10343
10388
|
style: {
|
|
10344
10389
|
position: "relative",
|
|
@@ -10355,7 +10400,7 @@ function AiTreeRenderer({
|
|
|
10355
10400
|
children: tree.rows.map((row, r2) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
10356
10401
|
"div",
|
|
10357
10402
|
{
|
|
10358
|
-
"data-ai-
|
|
10403
|
+
"data-ai-columns": "",
|
|
10359
10404
|
style: {
|
|
10360
10405
|
display: "grid",
|
|
10361
10406
|
gridTemplateColumns: "repeat(12, 1fr)",
|
|
@@ -10380,7 +10425,12 @@ function AiTreeRenderer({
|
|
|
10380
10425
|
// the full row height instead of clumping at the top.
|
|
10381
10426
|
...distributed === "space-between" ? { display: "flex", flexDirection: "column", justifyContent: "space-between" } : {}
|
|
10382
10427
|
},
|
|
10383
|
-
children: renderNode(
|
|
10428
|
+
children: renderNode(
|
|
10429
|
+
block,
|
|
10430
|
+
ctx,
|
|
10431
|
+
`r${r2}.b${b}`,
|
|
10432
|
+
settings.alignment === "center" ? "center" : "left"
|
|
10433
|
+
)
|
|
10384
10434
|
},
|
|
10385
10435
|
b
|
|
10386
10436
|
))
|
|
@@ -11012,9 +11062,10 @@ function applyAiSectionsToDom(state, options) {
|
|
|
11012
11062
|
if (existing && existing.serialized === serialized && existing.container.isConnected) {
|
|
11013
11063
|
continue;
|
|
11014
11064
|
}
|
|
11015
|
-
const isNewMount = !existing || !existing.container.isConnected;
|
|
11016
11065
|
let container = existing?.container;
|
|
11066
|
+
let isNewMount = false;
|
|
11017
11067
|
if (!container || !container.isConnected) {
|
|
11068
|
+
isNewMount = true;
|
|
11018
11069
|
existing?.root.unmount();
|
|
11019
11070
|
container?.remove();
|
|
11020
11071
|
container = document.createElement("div");
|
|
@@ -17456,6 +17507,7 @@ function MediaOverlay({
|
|
|
17456
17507
|
(prev) => prev && prev.fullWidth === width && prev.height === height ? prev : { fullWidth: width, height }
|
|
17457
17508
|
);
|
|
17458
17509
|
}, [isVideo]);
|
|
17510
|
+
const replaceLabel = isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image";
|
|
17459
17511
|
const replaceMode = buttonSize ? replaceButtonMode({ width: rect.width, height: rect.height }, buttonSize) : "none";
|
|
17460
17512
|
const box = {
|
|
17461
17513
|
position: "fixed",
|
|
@@ -17554,11 +17606,10 @@ function MediaOverlay({
|
|
|
17554
17606
|
className: "flex items-center justify-center cursor-pointer",
|
|
17555
17607
|
style: {
|
|
17556
17608
|
...box,
|
|
17557
|
-
//
|
|
17558
|
-
//
|
|
17559
|
-
//
|
|
17560
|
-
|
|
17561
|
-
pointerEvents: hover.hasTextOverlap || cueOnly ? "none" : "auto",
|
|
17609
|
+
// Visual only. `pointer-events: auto` on this full-bleed rect covered the navbar
|
|
17610
|
+
// (hero bg includes the absolute TopNav) and swallowed CTA press-drag. Text overlay
|
|
17611
|
+
// and cueOnly also need clicks to fall through — Replace / video controls opt back in.
|
|
17612
|
+
pointerEvents: "none",
|
|
17562
17613
|
// Selected: a firm component ring with no wash, so the image reads as chosen rather
|
|
17563
17614
|
// than hovered. Hover keeps the existing tinted preview.
|
|
17564
17615
|
boxShadow: selected ? "inset 0 0 0 2px var(--color-bridge-primary)" : "inset 0 0 0 1.5px var(--color-bridge-primary)",
|
|
@@ -17585,17 +17636,17 @@ function MediaOverlay({
|
|
|
17585
17636
|
},
|
|
17586
17637
|
children: [
|
|
17587
17638
|
isVideo ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react5.Film, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react5.ImageIcon, { size: 14 }),
|
|
17588
|
-
|
|
17639
|
+
replaceLabel
|
|
17589
17640
|
]
|
|
17590
17641
|
}
|
|
17591
17642
|
),
|
|
17592
|
-
replaceMode
|
|
17643
|
+
showChrome && replaceMode !== "none" && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
17593
17644
|
Button,
|
|
17594
17645
|
{
|
|
17595
17646
|
"data-ohw-media-overlay": "",
|
|
17596
17647
|
variant: "outline",
|
|
17597
17648
|
size: "sm",
|
|
17598
|
-
"aria-label":
|
|
17649
|
+
"aria-label": replaceLabel,
|
|
17599
17650
|
className: "gap-1.5 cursor-pointer hover:bg-background",
|
|
17600
17651
|
style: {
|
|
17601
17652
|
...OVERLAY_BUTTON_STYLE,
|
|
@@ -17618,7 +17669,7 @@ function MediaOverlay({
|
|
|
17618
17669
|
},
|
|
17619
17670
|
children: [
|
|
17620
17671
|
isVideo ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react5.Film, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react5.ImageIcon, { size: 14 }),
|
|
17621
|
-
replaceMode === "full" ?
|
|
17672
|
+
replaceMode === "full" ? replaceLabel : null
|
|
17622
17673
|
]
|
|
17623
17674
|
}
|
|
17624
17675
|
)
|
|
@@ -18128,7 +18179,7 @@ function AiSectionOverlay({
|
|
|
18128
18179
|
|
|
18129
18180
|
// src/ui/ai-section/AiMediaStripOverlay.tsx
|
|
18130
18181
|
var import_react10 = require("react");
|
|
18131
|
-
var
|
|
18182
|
+
var import_lucide_react9 = require("lucide-react");
|
|
18132
18183
|
|
|
18133
18184
|
// src/lib/ai-media-strip-tree.ts
|
|
18134
18185
|
var MEDIA_STRIP_ITEM_MIN = 1;
|
|
@@ -18242,14 +18293,6 @@ function setMediaStripItemAsset(tree, index, assetId) {
|
|
|
18242
18293
|
return true;
|
|
18243
18294
|
});
|
|
18244
18295
|
}
|
|
18245
|
-
function setMediaStripItemAlt(tree, index, alt) {
|
|
18246
|
-
return withMediaStrip(tree, (block) => {
|
|
18247
|
-
const items = block.items;
|
|
18248
|
-
if (index < 0 || index >= items.length) return false;
|
|
18249
|
-
items[index] = { ...items[index], alt };
|
|
18250
|
-
return true;
|
|
18251
|
-
});
|
|
18252
|
-
}
|
|
18253
18296
|
function setMediaStripItemLink(tree, index, link) {
|
|
18254
18297
|
return withMediaStrip(tree, (block) => {
|
|
18255
18298
|
const items = block.items;
|
|
@@ -18267,11 +18310,117 @@ function setMediaStripItemLink(tree, index, link) {
|
|
|
18267
18310
|
});
|
|
18268
18311
|
}
|
|
18269
18312
|
|
|
18270
|
-
// src/ui/
|
|
18313
|
+
// src/ui/dialog.tsx
|
|
18314
|
+
var React9 = __toESM(require("react"), 1);
|
|
18315
|
+
var import_radix_ui6 = require("radix-ui");
|
|
18316
|
+
var import_lucide_react8 = require("lucide-react");
|
|
18271
18317
|
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
18272
|
-
|
|
18273
|
-
|
|
18274
|
-
|
|
18318
|
+
function Dialog2({
|
|
18319
|
+
...props
|
|
18320
|
+
}) {
|
|
18321
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_radix_ui6.Dialog.Root, { "data-slot": "dialog", ...props });
|
|
18322
|
+
}
|
|
18323
|
+
function DialogPortal({
|
|
18324
|
+
...props
|
|
18325
|
+
}) {
|
|
18326
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_radix_ui6.Dialog.Portal, { ...props });
|
|
18327
|
+
}
|
|
18328
|
+
function DialogOverlay({
|
|
18329
|
+
className,
|
|
18330
|
+
...props
|
|
18331
|
+
}) {
|
|
18332
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
18333
|
+
import_radix_ui6.Dialog.Overlay,
|
|
18334
|
+
{
|
|
18335
|
+
"data-slot": "dialog-overlay",
|
|
18336
|
+
"data-ohw-link-modal-root": "",
|
|
18337
|
+
className: cn("fixed inset-0 z-[2147483646] bg-black/50", className),
|
|
18338
|
+
...props
|
|
18339
|
+
}
|
|
18340
|
+
);
|
|
18341
|
+
}
|
|
18342
|
+
var DialogContent = React9.forwardRef(
|
|
18343
|
+
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
18344
|
+
const positionMode = container ? "absolute" : "fixed";
|
|
18345
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(DialogPortal, { container: container ?? void 0, children: [
|
|
18346
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
18347
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
18348
|
+
import_radix_ui6.Dialog.Content,
|
|
18349
|
+
{
|
|
18350
|
+
ref,
|
|
18351
|
+
"data-slot": "dialog-content",
|
|
18352
|
+
className: cn(
|
|
18353
|
+
positionMode,
|
|
18354
|
+
"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",
|
|
18355
|
+
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
18356
|
+
container ? "max-h-[calc(100%-32px)]" : "max-h-[calc(100vh-32px)]",
|
|
18357
|
+
className
|
|
18358
|
+
),
|
|
18359
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
18360
|
+
...props,
|
|
18361
|
+
children: [
|
|
18362
|
+
children,
|
|
18363
|
+
showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
18364
|
+
import_radix_ui6.Dialog.Close,
|
|
18365
|
+
{
|
|
18366
|
+
type: "button",
|
|
18367
|
+
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
18368
|
+
"aria-label": "Close",
|
|
18369
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react8.X, { size: 16, "aria-hidden": true })
|
|
18370
|
+
}
|
|
18371
|
+
) : null
|
|
18372
|
+
]
|
|
18373
|
+
}
|
|
18374
|
+
)
|
|
18375
|
+
] });
|
|
18376
|
+
}
|
|
18377
|
+
);
|
|
18378
|
+
DialogContent.displayName = import_radix_ui6.Dialog.Content.displayName;
|
|
18379
|
+
function DialogHeader({
|
|
18380
|
+
className,
|
|
18381
|
+
...props
|
|
18382
|
+
}) {
|
|
18383
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
18384
|
+
}
|
|
18385
|
+
function DialogFooter({
|
|
18386
|
+
className,
|
|
18387
|
+
...props
|
|
18388
|
+
}) {
|
|
18389
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
18390
|
+
"div",
|
|
18391
|
+
{
|
|
18392
|
+
className: cn("flex items-center justify-end gap-2", className),
|
|
18393
|
+
...props
|
|
18394
|
+
}
|
|
18395
|
+
);
|
|
18396
|
+
}
|
|
18397
|
+
var DialogTitle = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
18398
|
+
import_radix_ui6.Dialog.Title,
|
|
18399
|
+
{
|
|
18400
|
+
ref,
|
|
18401
|
+
className: cn(
|
|
18402
|
+
"text-lg font-semibold leading-none tracking-tight text-card-foreground",
|
|
18403
|
+
className
|
|
18404
|
+
),
|
|
18405
|
+
...props
|
|
18406
|
+
}
|
|
18407
|
+
));
|
|
18408
|
+
DialogTitle.displayName = import_radix_ui6.Dialog.Title.displayName;
|
|
18409
|
+
var DialogDescription = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
18410
|
+
import_radix_ui6.Dialog.Description,
|
|
18411
|
+
{
|
|
18412
|
+
ref,
|
|
18413
|
+
className: cn("text-sm text-muted-foreground", className),
|
|
18414
|
+
...props
|
|
18415
|
+
}
|
|
18416
|
+
));
|
|
18417
|
+
DialogDescription.displayName = import_radix_ui6.Dialog.Description.displayName;
|
|
18418
|
+
var DialogClose = import_radix_ui6.Dialog.Close;
|
|
18419
|
+
|
|
18420
|
+
// src/ui/ai-section/AiMediaStripOverlay.tsx
|
|
18421
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
18422
|
+
var PRIMARY3 = "var(--ohw-primary, #0885FE)";
|
|
18423
|
+
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]";
|
|
18275
18424
|
function findMediaStripItemElement(sectionId, index) {
|
|
18276
18425
|
const sectionEl = findByInstanceId(sectionId);
|
|
18277
18426
|
if (!sectionEl) return null;
|
|
@@ -18281,14 +18430,35 @@ function findMediaStripItemElement(sectionId, index) {
|
|
|
18281
18430
|
}
|
|
18282
18431
|
return null;
|
|
18283
18432
|
}
|
|
18284
|
-
function
|
|
18285
|
-
|
|
18433
|
+
function itemRefFromTarget(target) {
|
|
18434
|
+
if (!(target instanceof Element)) return null;
|
|
18435
|
+
if (target.closest(CHROME_SELECTOR)) return null;
|
|
18436
|
+
const itemEl = target.closest("[data-ohw-media-strip-item]");
|
|
18437
|
+
if (!itemEl) return null;
|
|
18438
|
+
const sectionEl = itemEl.closest("[data-ohw-section]");
|
|
18439
|
+
const unit = sectionEl ? movableUnit(sectionEl) : null;
|
|
18440
|
+
const sectionId = unit ? instanceIdOf(unit) || null : null;
|
|
18441
|
+
const index = Number(itemEl.dataset.ohwMediaStripIndex);
|
|
18442
|
+
if (!sectionId || Number.isNaN(index)) return null;
|
|
18443
|
+
return { sectionId, index };
|
|
18444
|
+
}
|
|
18445
|
+
function sameRef(a, b) {
|
|
18446
|
+
return a?.sectionId === b?.sectionId && a?.index === b?.index;
|
|
18447
|
+
}
|
|
18448
|
+
function rectOf(el) {
|
|
18286
18449
|
if (!el) return null;
|
|
18287
18450
|
const r2 = el.getBoundingClientRect();
|
|
18288
18451
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
18289
18452
|
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
18290
18453
|
}
|
|
18291
|
-
function
|
|
18454
|
+
function readRect2(ref) {
|
|
18455
|
+
return rectOf(ref && findMediaStripItemElement(ref.sectionId, ref.index));
|
|
18456
|
+
}
|
|
18457
|
+
function readStripRect(ref) {
|
|
18458
|
+
const item = ref && findMediaStripItemElement(ref.sectionId, ref.index);
|
|
18459
|
+
return rectOf(item?.closest("[data-ohw-media-strip]") ?? item);
|
|
18460
|
+
}
|
|
18461
|
+
function useLiveItemRect(ref, strip = false) {
|
|
18292
18462
|
const [rect, setRect] = (0, import_react10.useState)(null);
|
|
18293
18463
|
(0, import_react10.useEffect)(() => {
|
|
18294
18464
|
if (!ref) {
|
|
@@ -18296,7 +18466,7 @@ function useLiveItemRect(ref) {
|
|
|
18296
18466
|
return;
|
|
18297
18467
|
}
|
|
18298
18468
|
const update = () => {
|
|
18299
|
-
const next = readRect2(ref);
|
|
18469
|
+
const next = strip ? readStripRect(ref) : readRect2(ref);
|
|
18300
18470
|
setRect(
|
|
18301
18471
|
(prev) => prev && next && prev.top === next.top && prev.left === next.left && prev.width === next.width && prev.height === next.height ? prev : next
|
|
18302
18472
|
);
|
|
@@ -18311,9 +18481,49 @@ function useLiveItemRect(ref) {
|
|
|
18311
18481
|
window.removeEventListener("resize", update);
|
|
18312
18482
|
clearInterval(interval);
|
|
18313
18483
|
};
|
|
18314
|
-
}, [ref?.sectionId, ref?.index]);
|
|
18484
|
+
}, [ref?.sectionId, ref?.index, strip]);
|
|
18315
18485
|
return rect;
|
|
18316
18486
|
}
|
|
18487
|
+
var TOOLBAR_STRIP_GAP = 52;
|
|
18488
|
+
var TOOLBAR_STRIP_GAP_MOBILE = 42;
|
|
18489
|
+
var TOOLBAR_EDGE_MARGIN2 = 4;
|
|
18490
|
+
function StripToolbarSlot({ stripRect, children }) {
|
|
18491
|
+
const slotRef = (0, import_react10.useRef)(null);
|
|
18492
|
+
const [shift, setShift] = (0, import_react10.useState)(0);
|
|
18493
|
+
const centerX = stripRect.left + stripRect.width / 2;
|
|
18494
|
+
(0, import_react10.useLayoutEffect)(() => {
|
|
18495
|
+
const slot = slotRef.current;
|
|
18496
|
+
if (!slot) return;
|
|
18497
|
+
const clamp = () => {
|
|
18498
|
+
const w = slot.offsetWidth;
|
|
18499
|
+
if (w <= 0) return;
|
|
18500
|
+
const half = w / 2;
|
|
18501
|
+
const clamped = Math.max(TOOLBAR_EDGE_MARGIN2 + half, Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN2 - half));
|
|
18502
|
+
setShift((prev) => Math.abs(prev - (clamped - centerX)) < 0.5 ? prev : clamped - centerX);
|
|
18503
|
+
};
|
|
18504
|
+
clamp();
|
|
18505
|
+
const ro = new ResizeObserver(clamp);
|
|
18506
|
+
ro.observe(slot);
|
|
18507
|
+
return () => ro.disconnect();
|
|
18508
|
+
}, [centerX, children]);
|
|
18509
|
+
const mobile = window.innerWidth <= 480;
|
|
18510
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18511
|
+
"div",
|
|
18512
|
+
{
|
|
18513
|
+
ref: slotRef,
|
|
18514
|
+
"data-ohw-bridge": "",
|
|
18515
|
+
"data-ohw-item-interaction": "",
|
|
18516
|
+
className: "pointer-events-auto fixed",
|
|
18517
|
+
style: {
|
|
18518
|
+
top: stripRect.top - (mobile ? TOOLBAR_STRIP_GAP_MOBILE : TOOLBAR_STRIP_GAP),
|
|
18519
|
+
left: centerX + shift,
|
|
18520
|
+
transform: "translate(-50%, -100%)",
|
|
18521
|
+
zIndex: 2147483645
|
|
18522
|
+
},
|
|
18523
|
+
children
|
|
18524
|
+
}
|
|
18525
|
+
);
|
|
18526
|
+
}
|
|
18317
18527
|
function requestValidateTree(postToParent2, tree) {
|
|
18318
18528
|
return new Promise((resolve) => {
|
|
18319
18529
|
const id = `ai-validate-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
@@ -18350,221 +18560,177 @@ function requestAssetPick(postToParent2) {
|
|
|
18350
18560
|
postToParent2({ type: "ow:asset-pick", id });
|
|
18351
18561
|
});
|
|
18352
18562
|
}
|
|
18353
|
-
function
|
|
18563
|
+
function ToolbarAction({
|
|
18354
18564
|
label,
|
|
18355
18565
|
onClick,
|
|
18356
|
-
disabled,
|
|
18357
|
-
active
|
|
18566
|
+
disabled = false,
|
|
18567
|
+
active = false,
|
|
18568
|
+
children
|
|
18358
18569
|
}) {
|
|
18359
|
-
|
|
18360
|
-
|
|
18361
|
-
{
|
|
18362
|
-
|
|
18363
|
-
|
|
18364
|
-
disabled,
|
|
18365
|
-
style: {
|
|
18366
|
-
height: 28,
|
|
18367
|
-
padding: "0 10px",
|
|
18368
|
-
display: "inline-flex",
|
|
18369
|
-
alignItems: "center",
|
|
18370
|
-
gap: 4,
|
|
18371
|
-
borderRadius: 999,
|
|
18372
|
-
border: "none",
|
|
18373
|
-
cursor: disabled ? "default" : "pointer",
|
|
18374
|
-
background: active ? OHW_BLUE_DARK : "#ffffff",
|
|
18375
|
-
color: active ? "#ffffff" : OHW_BLUE_DARK,
|
|
18376
|
-
opacity: disabled ? 0.4 : 1,
|
|
18377
|
-
fontSize: 12,
|
|
18378
|
-
lineHeight: "16px",
|
|
18379
|
-
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
18380
|
-
whiteSpace: "nowrap",
|
|
18381
|
-
flex: "0 0 auto"
|
|
18382
|
-
},
|
|
18383
|
-
children: label
|
|
18384
|
-
}
|
|
18385
|
-
);
|
|
18570
|
+
const button = /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(CustomToolbarButton, { type: "button", "aria-label": label, disabled, active, onClick, className: "size-8", children });
|
|
18571
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Tooltip, { children: [
|
|
18572
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "inline-flex", children: button }) : button }),
|
|
18573
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: label })
|
|
18574
|
+
] });
|
|
18386
18575
|
}
|
|
18387
|
-
function
|
|
18388
|
-
|
|
18389
|
-
(0, import_react10.useEffect)(() => setDraft(value), [value]);
|
|
18390
|
-
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
18391
|
-
"div",
|
|
18392
|
-
{
|
|
18393
|
-
style: {
|
|
18394
|
-
display: "flex",
|
|
18395
|
-
alignItems: "center",
|
|
18396
|
-
gap: 6,
|
|
18397
|
-
height: 28,
|
|
18398
|
-
padding: "0 12px",
|
|
18399
|
-
borderRadius: 999,
|
|
18400
|
-
background: "#ffffff",
|
|
18401
|
-
width: "100%",
|
|
18402
|
-
maxWidth: 260,
|
|
18403
|
-
boxSizing: "border-box"
|
|
18404
|
-
},
|
|
18405
|
-
children: [
|
|
18406
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
18407
|
-
"span",
|
|
18408
|
-
{
|
|
18409
|
-
style: {
|
|
18410
|
-
flex: "0 0 auto",
|
|
18411
|
-
color: OHW_BLUE_DARK,
|
|
18412
|
-
fontSize: 10,
|
|
18413
|
-
fontWeight: 700,
|
|
18414
|
-
textTransform: "uppercase",
|
|
18415
|
-
letterSpacing: 0.4
|
|
18416
|
-
},
|
|
18417
|
-
children: "Alt"
|
|
18418
|
-
}
|
|
18419
|
-
),
|
|
18420
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
18421
|
-
"input",
|
|
18422
|
-
{
|
|
18423
|
-
type: "text",
|
|
18424
|
-
value: draft,
|
|
18425
|
-
onChange: (e) => setDraft(e.target.value),
|
|
18426
|
-
onBlur: () => {
|
|
18427
|
-
if (draft !== value) onCommit(draft);
|
|
18428
|
-
},
|
|
18429
|
-
onKeyDown: (e) => {
|
|
18430
|
-
if (e.key === "Enter") e.currentTarget.blur();
|
|
18431
|
-
if (e.key === "Escape") {
|
|
18432
|
-
setDraft(value);
|
|
18433
|
-
e.currentTarget.blur();
|
|
18434
|
-
}
|
|
18435
|
-
},
|
|
18436
|
-
placeholder: "Describe this image",
|
|
18437
|
-
"aria-label": "Image alt text",
|
|
18438
|
-
style: {
|
|
18439
|
-
flex: 1,
|
|
18440
|
-
minWidth: 0,
|
|
18441
|
-
border: "none",
|
|
18442
|
-
outline: "none",
|
|
18443
|
-
background: "transparent",
|
|
18444
|
-
fontSize: 12,
|
|
18445
|
-
lineHeight: "16px",
|
|
18446
|
-
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
18447
|
-
color: "#1f2937"
|
|
18448
|
-
}
|
|
18449
|
-
}
|
|
18450
|
-
)
|
|
18451
|
-
]
|
|
18452
|
-
}
|
|
18453
|
-
);
|
|
18576
|
+
function ToolbarSeparator() {
|
|
18577
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { "aria-hidden": true, className: "mx-0.5 block h-6 w-px shrink-0 bg-border" });
|
|
18454
18578
|
}
|
|
18455
|
-
|
|
18456
|
-
|
|
18457
|
-
|
|
18458
|
-
|
|
18459
|
-
|
|
18460
|
-
|
|
18461
|
-
|
|
18462
|
-
|
|
18463
|
-
|
|
18464
|
-
|
|
18465
|
-
|
|
18466
|
-
|
|
18467
|
-
|
|
18468
|
-
|
|
18469
|
-
|
|
18470
|
-
|
|
18471
|
-
|
|
18472
|
-
|
|
18473
|
-
|
|
18474
|
-
|
|
18475
|
-
|
|
18476
|
-
|
|
18477
|
-
|
|
18478
|
-
|
|
18479
|
-
|
|
18480
|
-
|
|
18481
|
-
}, [value]);
|
|
18482
|
-
const commit = () => {
|
|
18483
|
-
const next = draft.trim();
|
|
18484
|
-
if (next === value) return setInvalid(false);
|
|
18485
|
-
if (next && !HTTP_URL_RE.test(next)) return setInvalid(true);
|
|
18486
|
-
setInvalid(false);
|
|
18487
|
-
onCommit(next);
|
|
18488
|
-
};
|
|
18489
|
-
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
18490
|
-
"div",
|
|
18491
|
-
{
|
|
18492
|
-
style: {
|
|
18493
|
-
display: "flex",
|
|
18494
|
-
alignItems: "center",
|
|
18495
|
-
gap: 6,
|
|
18496
|
-
height: 28,
|
|
18497
|
-
padding: "0 12px",
|
|
18498
|
-
borderRadius: 999,
|
|
18499
|
-
background: "#ffffff",
|
|
18500
|
-
width: "100%",
|
|
18501
|
-
maxWidth: 260,
|
|
18502
|
-
boxSizing: "border-box",
|
|
18503
|
-
boxShadow: invalid ? "inset 0 0 0 1.5px #EF4444" : "none"
|
|
18504
|
-
},
|
|
18505
|
-
children: [
|
|
18506
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
18507
|
-
"span",
|
|
18508
|
-
{
|
|
18509
|
-
style: {
|
|
18510
|
-
flex: "0 0 auto",
|
|
18511
|
-
color: OHW_BLUE_DARK,
|
|
18512
|
-
fontSize: 10,
|
|
18513
|
-
fontWeight: 700,
|
|
18514
|
-
textTransform: "uppercase",
|
|
18515
|
-
letterSpacing: 0.4
|
|
18516
|
-
},
|
|
18517
|
-
children: "Link"
|
|
18518
|
-
}
|
|
18519
|
-
),
|
|
18520
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
18521
|
-
"input",
|
|
18579
|
+
function OptionMenu({
|
|
18580
|
+
label,
|
|
18581
|
+
value,
|
|
18582
|
+
options,
|
|
18583
|
+
onChange
|
|
18584
|
+
}) {
|
|
18585
|
+
const current = options.find((o) => o.value === value) ?? options[0];
|
|
18586
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
18587
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "text-xs text-muted-foreground", children: label }),
|
|
18588
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(DropdownMenu, { modal: false, children: [
|
|
18589
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
18590
|
+
"button",
|
|
18591
|
+
{
|
|
18592
|
+
type: "button",
|
|
18593
|
+
"aria-label": label,
|
|
18594
|
+
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",
|
|
18595
|
+
children: [
|
|
18596
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "flex-1 text-left", children: current.label }),
|
|
18597
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.ChevronDown, { size: 16, style: { pointerEvents: "none" } })
|
|
18598
|
+
]
|
|
18599
|
+
}
|
|
18600
|
+
) }),
|
|
18601
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DropdownMenuContent, { align: "end", sideOffset: 8, className: "w-[132px] min-w-[132px] p-1", children: options.map((option) => {
|
|
18602
|
+
const selected = option.value === value;
|
|
18603
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
18604
|
+
DropdownMenuItem,
|
|
18522
18605
|
{
|
|
18523
|
-
|
|
18524
|
-
|
|
18525
|
-
|
|
18526
|
-
|
|
18527
|
-
|
|
18528
|
-
|
|
18529
|
-
|
|
18530
|
-
|
|
18531
|
-
|
|
18532
|
-
|
|
18533
|
-
|
|
18534
|
-
|
|
18535
|
-
|
|
18536
|
-
|
|
18537
|
-
|
|
18538
|
-
|
|
18539
|
-
|
|
18540
|
-
|
|
18541
|
-
|
|
18542
|
-
|
|
18543
|
-
|
|
18544
|
-
|
|
18545
|
-
|
|
18546
|
-
|
|
18547
|
-
|
|
18548
|
-
|
|
18549
|
-
|
|
18550
|
-
|
|
18551
|
-
|
|
18552
|
-
|
|
18606
|
+
role: "menuitemradio",
|
|
18607
|
+
"aria-checked": selected,
|
|
18608
|
+
onSelect: () => onChange(option.value),
|
|
18609
|
+
className: cn("grid grid-cols-[1fr_16px] gap-2 py-2 pl-2 pr-2 text-[13px]", selected && "bg-muted"),
|
|
18610
|
+
children: [
|
|
18611
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { children: option.label }),
|
|
18612
|
+
selected && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.Check, { size: 16, className: "text-bridge-primary" })
|
|
18613
|
+
]
|
|
18614
|
+
},
|
|
18615
|
+
option.value
|
|
18616
|
+
);
|
|
18617
|
+
}) })
|
|
18618
|
+
] })
|
|
18619
|
+
] });
|
|
18620
|
+
}
|
|
18621
|
+
var VARIANTS = [
|
|
18622
|
+
{ value: "logos", label: "Logos" },
|
|
18623
|
+
{ value: "reel", label: "Reel" }
|
|
18624
|
+
];
|
|
18625
|
+
var ALIGNS = [
|
|
18626
|
+
{ value: "left", label: "Align left", Icon: import_lucide_react9.AlignLeft },
|
|
18627
|
+
{ value: "center", label: "Align center", Icon: import_lucide_react9.AlignCenter },
|
|
18628
|
+
{ value: "right", label: "Align right", Icon: import_lucide_react9.AlignRight }
|
|
18629
|
+
];
|
|
18630
|
+
var HOVERS = [
|
|
18631
|
+
{ value: "none", label: "None" },
|
|
18632
|
+
{ value: "lift", label: "Lift" },
|
|
18633
|
+
{ value: "zoom", label: "Zoom" },
|
|
18634
|
+
{ value: "fade", label: "Fade" }
|
|
18635
|
+
];
|
|
18636
|
+
var HTTP_URL_RE = /^https?:\/\/\S+$/i;
|
|
18637
|
+
function LinkModal({
|
|
18638
|
+
href,
|
|
18639
|
+
linkTarget,
|
|
18640
|
+
onClose,
|
|
18641
|
+
onSave
|
|
18642
|
+
}) {
|
|
18643
|
+
const [draft, setDraft] = (0, import_react10.useState)(href);
|
|
18644
|
+
const [newTab, setNewTab] = (0, import_react10.useState)(linkTarget !== "same-tab");
|
|
18645
|
+
const [invalid, setInvalid] = (0, import_react10.useState)(false);
|
|
18646
|
+
const save = () => {
|
|
18647
|
+
const next = draft.trim();
|
|
18648
|
+
if (next && !HTTP_URL_RE.test(next)) {
|
|
18649
|
+
setInvalid(true);
|
|
18650
|
+
return;
|
|
18553
18651
|
}
|
|
18554
|
-
|
|
18652
|
+
onSave(next, newTab ? "new-tab" : "same-tab");
|
|
18653
|
+
onClose();
|
|
18654
|
+
};
|
|
18655
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Dialog2, { open: true, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(DialogContent, { "data-ohw-link-modal-root": "", className: "max-w-[400px] gap-4 p-5", children: [
|
|
18656
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DialogHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DialogTitle, { className: "text-base", children: "Image link" }) }),
|
|
18657
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex flex-col gap-3", children: [
|
|
18658
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18659
|
+
"input",
|
|
18660
|
+
{
|
|
18661
|
+
autoFocus: true,
|
|
18662
|
+
type: "text",
|
|
18663
|
+
inputMode: "url",
|
|
18664
|
+
value: draft,
|
|
18665
|
+
onChange: (e) => {
|
|
18666
|
+
setDraft(e.target.value);
|
|
18667
|
+
setInvalid(false);
|
|
18668
|
+
},
|
|
18669
|
+
onKeyDown: (e) => {
|
|
18670
|
+
if (e.key === "Enter") save();
|
|
18671
|
+
},
|
|
18672
|
+
placeholder: "https://example.com",
|
|
18673
|
+
"aria-label": "Image link URL",
|
|
18674
|
+
"aria-invalid": invalid,
|
|
18675
|
+
className: cn(
|
|
18676
|
+
"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",
|
|
18677
|
+
invalid && "border-destructive focus:border-destructive"
|
|
18678
|
+
)
|
|
18679
|
+
}
|
|
18680
|
+
),
|
|
18681
|
+
invalid && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-xs text-destructive", children: "Enter a full URL starting with http:// or https://" }),
|
|
18682
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("label", { className: "flex items-center gap-2 text-[13px] text-foreground", children: [
|
|
18683
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("input", { type: "checkbox", checked: newTab, onChange: (e) => setNewTab(e.target.checked) }),
|
|
18684
|
+
"Open in new tab"
|
|
18685
|
+
] })
|
|
18686
|
+
] }),
|
|
18687
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(DialogFooter, { children: [
|
|
18688
|
+
href && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18689
|
+
"button",
|
|
18690
|
+
{
|
|
18691
|
+
type: "button",
|
|
18692
|
+
onClick: () => {
|
|
18693
|
+
onSave("", "new-tab");
|
|
18694
|
+
onClose();
|
|
18695
|
+
},
|
|
18696
|
+
className: "mr-auto rounded-[6px] px-3 py-2 text-[13px] font-medium text-destructive transition-colors hover:bg-muted",
|
|
18697
|
+
children: "Remove link"
|
|
18698
|
+
}
|
|
18699
|
+
),
|
|
18700
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18701
|
+
"button",
|
|
18702
|
+
{
|
|
18703
|
+
type: "button",
|
|
18704
|
+
onClick: onClose,
|
|
18705
|
+
className: "rounded-[6px] px-3 py-2 text-[13px] font-medium text-foreground transition-colors hover:bg-muted",
|
|
18706
|
+
children: "Cancel"
|
|
18707
|
+
}
|
|
18708
|
+
),
|
|
18709
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18710
|
+
"button",
|
|
18711
|
+
{
|
|
18712
|
+
type: "button",
|
|
18713
|
+
onClick: save,
|
|
18714
|
+
className: "rounded-[6px] bg-bridge-primary px-3 py-2 text-[13px] font-medium text-primary-foreground transition-opacity hover:opacity-90",
|
|
18715
|
+
children: "Save"
|
|
18716
|
+
}
|
|
18717
|
+
)
|
|
18718
|
+
] })
|
|
18719
|
+
] }) });
|
|
18555
18720
|
}
|
|
18556
18721
|
function MediaStripToolbar({
|
|
18557
18722
|
entry,
|
|
18558
18723
|
index,
|
|
18559
18724
|
pending,
|
|
18560
18725
|
error,
|
|
18726
|
+
itemEditOn,
|
|
18727
|
+
onToggleItemEdit,
|
|
18561
18728
|
onSetVariant,
|
|
18562
18729
|
onSetAlign,
|
|
18563
18730
|
onSetHover,
|
|
18564
18731
|
onSetTreatment,
|
|
18565
18732
|
onResize,
|
|
18566
|
-
|
|
18567
|
-
onSetLink,
|
|
18733
|
+
onOpenLink,
|
|
18568
18734
|
onAddItem,
|
|
18569
18735
|
onRemoveItem,
|
|
18570
18736
|
onChangeImage,
|
|
@@ -18573,81 +18739,102 @@ function MediaStripToolbar({
|
|
|
18573
18739
|
}) {
|
|
18574
18740
|
const items = mediaStripItems(entry.tree);
|
|
18575
18741
|
const itemCount = items.length;
|
|
18576
|
-
const currentAlt = items[index]?.alt ?? "";
|
|
18577
|
-
const currentHref = items[index]?.href ?? "";
|
|
18578
|
-
const currentTarget = items[index]?.linkTarget === "same-tab" ? "same-tab" : "new-tab";
|
|
18579
18742
|
const slots = findMediaStripSlots(entry.tree);
|
|
18580
18743
|
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
18581
18744
|
const align = slots?.align === "left" || slots?.align === "right" ? slots.align : "center";
|
|
18582
18745
|
const hover = slots?.hover === "none" || slots?.hover === "lift" || slots?.hover === "zoom" || slots?.hover === "fade" ? slots.hover : "lift";
|
|
18583
18746
|
const treatment = slots?.treatment === "color" || slots?.treatment === "grayscale" ? slots.treatment : variant === "logos" ? "grayscale" : "color";
|
|
18584
18747
|
const sizeValue = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
18585
|
-
const
|
|
18586
|
-
const
|
|
18587
|
-
|
|
18588
|
-
gap: 6,
|
|
18589
|
-
flexWrap: "nowrap",
|
|
18590
|
-
justifyContent: "center",
|
|
18591
|
-
overflowX: "auto",
|
|
18592
|
-
WebkitOverflowScrolling: "touch",
|
|
18593
|
-
width: "100%",
|
|
18594
|
-
scrollbarWidth: "none"
|
|
18595
|
-
} : { display: "flex", gap: 6, flexWrap: "nowrap", justifyContent: "center" };
|
|
18596
|
-
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
18748
|
+
const mobile = window.innerWidth <= 480;
|
|
18749
|
+
const gatedLabel = (label) => itemEditOn ? label : "Turn on the star to edit this image";
|
|
18750
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
18597
18751
|
"div",
|
|
18598
18752
|
{
|
|
18599
18753
|
"data-ohw-bridge": "",
|
|
18600
18754
|
"data-ohw-toolbar": "",
|
|
18601
18755
|
onMouseDown: (e) => e.stopPropagation(),
|
|
18602
|
-
|
|
18603
|
-
|
|
18604
|
-
flexDirection: "column",
|
|
18605
|
-
gap: 6,
|
|
18606
|
-
alignItems: "center",
|
|
18607
|
-
background: OHW_BLUE,
|
|
18608
|
-
padding: 8,
|
|
18609
|
-
borderRadius: 12,
|
|
18610
|
-
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
18611
|
-
pointerEvents: pending ? "none" : "auto",
|
|
18612
|
-
opacity: pending ? 0.6 : 1,
|
|
18613
|
-
maxWidth: isMobile ? "calc(100vw - 24px)" : "none"
|
|
18614
|
-
},
|
|
18756
|
+
className: cn("flex flex-col items-center gap-1.5 font-sans", pending && "pointer-events-none opacity-60"),
|
|
18757
|
+
style: { maxWidth: mobile ? "calc(100vw - 24px)" : void 0 },
|
|
18615
18758
|
children: [
|
|
18616
|
-
/* @__PURE__ */ (0,
|
|
18617
|
-
|
|
18618
|
-
|
|
18619
|
-
|
|
18620
|
-
|
|
18621
|
-
|
|
18622
|
-
|
|
18623
|
-
|
|
18624
|
-
|
|
18625
|
-
|
|
18626
|
-
|
|
18627
|
-
|
|
18628
|
-
|
|
18629
|
-
|
|
18630
|
-
|
|
18631
|
-
|
|
18632
|
-
|
|
18633
|
-
|
|
18634
|
-
|
|
18635
|
-
|
|
18636
|
-
|
|
18637
|
-
|
|
18638
|
-
|
|
18639
|
-
|
|
18640
|
-
|
|
18641
|
-
|
|
18642
|
-
|
|
18643
|
-
|
|
18644
|
-
|
|
18645
|
-
|
|
18646
|
-
|
|
18647
|
-
|
|
18759
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
18760
|
+
"div",
|
|
18761
|
+
{
|
|
18762
|
+
className: cn(
|
|
18763
|
+
"flex items-center gap-1 rounded-[10px] border border-border bg-background p-1 whitespace-nowrap",
|
|
18764
|
+
"shadow-[0px_10px_15px_-3px_rgba(0,0,0,0.1),0px_4px_6px_-4px_rgba(0,0,0,0.1)]",
|
|
18765
|
+
mobile ? "flex-wrap justify-center" : "flex-nowrap"
|
|
18766
|
+
),
|
|
18767
|
+
children: [
|
|
18768
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Tooltip, { children: [
|
|
18769
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18770
|
+
CustomToolbarButton,
|
|
18771
|
+
{
|
|
18772
|
+
type: "button",
|
|
18773
|
+
"aria-label": itemEditOn ? "Done editing this image" : "Edit this image",
|
|
18774
|
+
"aria-pressed": itemEditOn,
|
|
18775
|
+
onClick: onToggleItemEdit,
|
|
18776
|
+
className: "group size-8",
|
|
18777
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18778
|
+
import_lucide_react9.Star,
|
|
18779
|
+
{
|
|
18780
|
+
size: 16,
|
|
18781
|
+
fill: "currentColor",
|
|
18782
|
+
strokeWidth: 0,
|
|
18783
|
+
className: cn(
|
|
18784
|
+
"transition-colors",
|
|
18785
|
+
itemEditOn ? "text-[#f59e0b] group-hover:text-[#d97706]" : "text-[#d6d3d1] group-hover:text-[#fbbf24]"
|
|
18786
|
+
),
|
|
18787
|
+
style: { pointerEvents: "none" }
|
|
18788
|
+
}
|
|
18789
|
+
)
|
|
18790
|
+
}
|
|
18791
|
+
) }),
|
|
18792
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: itemEditOn ? "Done editing this image" : "Edit this image" })
|
|
18793
|
+
] }),
|
|
18794
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarSeparator, {}),
|
|
18795
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarAction, { label: gatedLabel("Change image"), onClick: onChangeImage, disabled: !itemEditOn, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.Image, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
18796
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarAction, { label: gatedLabel("Link"), onClick: onOpenLink, disabled: !itemEditOn, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.Link, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
18797
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarAction, { label: gatedLabel("Move left"), onClick: onMoveLeft, disabled: !itemEditOn || index <= 0, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.ArrowLeft, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
18798
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18799
|
+
ToolbarAction,
|
|
18800
|
+
{
|
|
18801
|
+
label: gatedLabel("Move right"),
|
|
18802
|
+
onClick: onMoveRight,
|
|
18803
|
+
disabled: !itemEditOn || index >= itemCount - 1,
|
|
18804
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.ArrowRight, { size: 16, style: { pointerEvents: "none" } })
|
|
18805
|
+
}
|
|
18806
|
+
),
|
|
18807
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarAction, { label: gatedLabel("Remove image"), onClick: onRemoveItem, disabled: !itemEditOn || itemCount <= 1, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.ImageMinus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
18808
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarSeparator, {}),
|
|
18809
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(OptionMenu, { label: "Layout", value: variant, options: VARIANTS, onChange: onSetVariant }),
|
|
18810
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(OptionMenu, { label: "Hover", value: hover, options: HOVERS, onChange: onSetHover }),
|
|
18811
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18812
|
+
ToolbarAction,
|
|
18813
|
+
{
|
|
18814
|
+
label: treatment === "grayscale" ? "Show in color" : "Show grayscale",
|
|
18815
|
+
active: treatment === "grayscale",
|
|
18816
|
+
onClick: () => onSetTreatment(treatment === "grayscale" ? "color" : "grayscale"),
|
|
18817
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.Palette, { size: 16, style: { pointerEvents: "none" } })
|
|
18818
|
+
}
|
|
18819
|
+
),
|
|
18820
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarSeparator, {}),
|
|
18821
|
+
ALIGNS.map(({ value, label, Icon }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarAction, { label, active: align === value, onClick: () => onSetAlign(value), children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Icon, { size: 16, style: { pointerEvents: "none" } }) }, value)),
|
|
18822
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarSeparator, {}),
|
|
18823
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarAction, { label: "Smaller", onClick: () => onResize(-8), children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.Minus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
18824
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "min-w-[40px] text-center text-xs tabular-nums text-muted-foreground", children: [
|
|
18825
|
+
sizeValue,
|
|
18826
|
+
"px"
|
|
18827
|
+
] }),
|
|
18828
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarAction, { label: "Larger", onClick: () => onResize(8), children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.Plus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
18829
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarSeparator, {}),
|
|
18830
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ToolbarAction, { label: "Add image", onClick: onAddItem, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.ImagePlus, { size: 16, style: { pointerEvents: "none" } }) })
|
|
18831
|
+
]
|
|
18832
|
+
}
|
|
18833
|
+
),
|
|
18834
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "max-w-[260px] rounded-md bg-background px-2 py-1 text-center text-[11px] text-destructive shadow-sm", children: error })
|
|
18648
18835
|
]
|
|
18649
18836
|
}
|
|
18650
|
-
);
|
|
18837
|
+
) });
|
|
18651
18838
|
}
|
|
18652
18839
|
function findMediaStripSlots(tree) {
|
|
18653
18840
|
const stack = tree.rows.flatMap((row) => row.blocks);
|
|
@@ -18666,31 +18853,23 @@ function AiMediaStripOverlay({
|
|
|
18666
18853
|
}) {
|
|
18667
18854
|
const [hover, setHover] = (0, import_react10.useState)(null);
|
|
18668
18855
|
const [active, setActive] = (0, import_react10.useState)(null);
|
|
18856
|
+
const [itemEditOn, setItemEditOn] = (0, import_react10.useState)(false);
|
|
18857
|
+
const [linkOpen, setLinkOpen] = (0, import_react10.useState)(false);
|
|
18669
18858
|
const [pending, setPending] = (0, import_react10.useState)(false);
|
|
18670
18859
|
const [error, setError] = (0, import_react10.useState)(null);
|
|
18671
18860
|
const activeRef = (0, import_react10.useRef)(null);
|
|
18672
18861
|
activeRef.current = active;
|
|
18862
|
+
const linkOpenRef = (0, import_react10.useRef)(false);
|
|
18863
|
+
linkOpenRef.current = linkOpen;
|
|
18673
18864
|
(0, import_react10.useEffect)(() => {
|
|
18674
18865
|
const onMove = (e) => {
|
|
18866
|
+
const ref = itemRefFromTarget(e.target);
|
|
18675
18867
|
const t = e.target;
|
|
18676
|
-
|
|
18677
|
-
|
|
18678
|
-
|
|
18679
|
-
|
|
18680
|
-
|
|
18681
|
-
if (!itemEl) {
|
|
18682
|
-
setHover(null);
|
|
18683
|
-
return;
|
|
18684
|
-
}
|
|
18685
|
-
const sectionEl = itemEl.closest("[data-ohw-section]");
|
|
18686
|
-
const unit = sectionEl ? movableUnit(sectionEl) : null;
|
|
18687
|
-
const sectionId = unit ? instanceIdOf(unit) || null : null;
|
|
18688
|
-
const index = Number(itemEl.dataset.ohwMediaStripIndex);
|
|
18689
|
-
if (!sectionId || Number.isNaN(index)) {
|
|
18690
|
-
setHover(null);
|
|
18691
|
-
return;
|
|
18692
|
-
}
|
|
18693
|
-
setHover({ sectionId, index });
|
|
18868
|
+
const overEditable = Boolean(t?.closest?.("[data-ohw-editable]"));
|
|
18869
|
+
setHover((prev) => {
|
|
18870
|
+
const next = ref && !overEditable ? ref : null;
|
|
18871
|
+
return sameRef(prev, next) ? prev : next;
|
|
18872
|
+
});
|
|
18694
18873
|
};
|
|
18695
18874
|
const onLeave = () => setHover(null);
|
|
18696
18875
|
document.addEventListener("mousemove", onMove, { passive: true });
|
|
@@ -18702,23 +18881,25 @@ function AiMediaStripOverlay({
|
|
|
18702
18881
|
}, []);
|
|
18703
18882
|
(0, import_react10.useEffect)(() => {
|
|
18704
18883
|
const onClick = (e) => {
|
|
18705
|
-
const current = activeRef.current;
|
|
18706
|
-
if (!current) return;
|
|
18707
18884
|
const t = e.target;
|
|
18708
|
-
if (!(t instanceof
|
|
18709
|
-
if (t.closest(
|
|
18710
|
-
const
|
|
18711
|
-
if (
|
|
18712
|
-
|
|
18885
|
+
if (!(t instanceof Element)) return;
|
|
18886
|
+
if (t.closest(CHROME_SELECTOR)) return;
|
|
18887
|
+
const ref = itemRefFromTarget(t);
|
|
18888
|
+
if (sameRef(activeRef.current, ref)) return;
|
|
18889
|
+
if (ref) clearInteractionChromeRef.current();
|
|
18890
|
+
setItemEditOn(false);
|
|
18713
18891
|
setError(null);
|
|
18892
|
+
setActive(ref);
|
|
18714
18893
|
};
|
|
18715
18894
|
document.addEventListener("click", onClick, true);
|
|
18716
18895
|
return () => document.removeEventListener("click", onClick, true);
|
|
18717
|
-
}, []);
|
|
18896
|
+
}, [clearInteractionChromeRef]);
|
|
18718
18897
|
(0, import_react10.useEffect)(() => {
|
|
18719
18898
|
const onBlur = () => {
|
|
18720
18899
|
if (!activeRef.current) return;
|
|
18721
18900
|
setActive(null);
|
|
18901
|
+
setItemEditOn(false);
|
|
18902
|
+
setLinkOpen(false);
|
|
18722
18903
|
setError(null);
|
|
18723
18904
|
};
|
|
18724
18905
|
window.addEventListener("blur", onBlur);
|
|
@@ -18728,7 +18909,10 @@ function AiMediaStripOverlay({
|
|
|
18728
18909
|
const onKeyDown = (e) => {
|
|
18729
18910
|
if (e.key !== "Escape") return;
|
|
18730
18911
|
if (!activeRef.current) return;
|
|
18912
|
+
if (linkOpenRef.current) return;
|
|
18913
|
+
if (document.querySelector('[data-ohw-more-menu][data-state="open"]')) return;
|
|
18731
18914
|
setActive(null);
|
|
18915
|
+
setItemEditOn(false);
|
|
18732
18916
|
setError(null);
|
|
18733
18917
|
};
|
|
18734
18918
|
document.addEventListener("keydown", onKeyDown);
|
|
@@ -18762,137 +18946,133 @@ function AiMediaStripOverlay({
|
|
|
18762
18946
|
tree: nextTree,
|
|
18763
18947
|
label: entry.label,
|
|
18764
18948
|
media: extraMedia ? { ...entry.media, ...extraMedia } : entry.media,
|
|
18765
|
-
...entry.brand ? { brand: entry.brand } : {}
|
|
18949
|
+
...entry.brand ? { brand: entry.brand } : {},
|
|
18950
|
+
// The user is already looking at the strip they just edited — recentering the viewport
|
|
18951
|
+
// on every edit reads as the section jumping around.
|
|
18952
|
+
skipScrollIntoView: true
|
|
18766
18953
|
});
|
|
18767
18954
|
return true;
|
|
18768
18955
|
},
|
|
18769
18956
|
[findEntry, postToParent2, applyTreeLocalRef]
|
|
18770
18957
|
);
|
|
18771
18958
|
const activeEntry = active ? findEntry(active.sectionId) : null;
|
|
18772
|
-
const hoverHandleRect = useLiveItemRect(!active && hover ? hover : null);
|
|
18773
18959
|
const activeItemRect = useLiveItemRect(active);
|
|
18774
|
-
const
|
|
18775
|
-
const
|
|
18776
|
-
|
|
18777
|
-
|
|
18778
|
-
|
|
18779
|
-
|
|
18780
|
-
|
|
18781
|
-
|
|
18782
|
-
|
|
18783
|
-
|
|
18784
|
-
|
|
18785
|
-
|
|
18786
|
-
|
|
18787
|
-
|
|
18788
|
-
|
|
18789
|
-
|
|
18790
|
-
|
|
18791
|
-
|
|
18792
|
-
|
|
18793
|
-
|
|
18794
|
-
|
|
18795
|
-
|
|
18796
|
-
|
|
18797
|
-
|
|
18798
|
-
|
|
18799
|
-
|
|
18800
|
-
|
|
18801
|
-
|
|
18802
|
-
|
|
18803
|
-
|
|
18804
|
-
|
|
18805
|
-
|
|
18806
|
-
|
|
18807
|
-
|
|
18808
|
-
activeItemRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
18809
|
-
ItemInteractionLayer,
|
|
18810
|
-
{
|
|
18811
|
-
rect: activeItemRect,
|
|
18812
|
-
state: toolbarState,
|
|
18813
|
-
toolbar: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
18814
|
-
MediaStripToolbar,
|
|
18815
|
-
{
|
|
18816
|
-
entry: activeEntry,
|
|
18817
|
-
index: active.index,
|
|
18818
|
-
pending,
|
|
18819
|
-
error,
|
|
18820
|
-
onSetVariant: (variant) => runMutation(active.sectionId, (tree) => setMediaStripVariant(tree, variant)),
|
|
18821
|
-
onSetAlign: (align) => runMutation(active.sectionId, (tree) => setMediaStripAlign(tree, align)),
|
|
18822
|
-
onSetHover: (hoverPreset) => runMutation(active.sectionId, (tree) => setMediaStripHover(tree, hoverPreset)),
|
|
18823
|
-
onSetTreatment: (treatment) => runMutation(active.sectionId, (tree) => setMediaStripTreatment(tree, treatment)),
|
|
18824
|
-
onResize: (delta) => {
|
|
18825
|
-
const slots = findMediaStripSlots(activeEntry.tree);
|
|
18826
|
-
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
18827
|
-
const current = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
18828
|
-
void runMutation(active.sectionId, (tree) => setMediaStripSizing(tree, current + delta));
|
|
18829
|
-
},
|
|
18830
|
-
onSetAlt: (alt) => {
|
|
18831
|
-
void runMutation(active.sectionId, (tree) => setMediaStripItemAlt(tree, active.index, alt));
|
|
18832
|
-
},
|
|
18833
|
-
onSetLink: (href, linkTarget) => {
|
|
18960
|
+
const activeStripRect = useLiveItemRect(active, true);
|
|
18961
|
+
const hoverRect = useLiveItemRect(hover && !sameRef(hover, active) ? hover : null);
|
|
18962
|
+
const activeItems = activeEntry ? mediaStripItems(activeEntry.tree) : [];
|
|
18963
|
+
const activeItem = active ? activeItems[active.index] : void 0;
|
|
18964
|
+
const activeHref = activeItem?.href ?? "";
|
|
18965
|
+
const activeTarget = activeItem?.linkTarget === "same-tab" ? "same-tab" : "new-tab";
|
|
18966
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
|
|
18967
|
+
hoverRect && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ItemInteractionLayer, { rect: hoverRect, state: "hover" }),
|
|
18968
|
+
activeItemRect && activeStripRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
|
|
18969
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ItemInteractionLayer, { rect: activeItemRect, state: "active-top" }),
|
|
18970
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(StripToolbarSlot, { stripRect: activeStripRect, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18971
|
+
MediaStripToolbar,
|
|
18972
|
+
{
|
|
18973
|
+
entry: activeEntry,
|
|
18974
|
+
index: active.index,
|
|
18975
|
+
pending,
|
|
18976
|
+
error,
|
|
18977
|
+
itemEditOn,
|
|
18978
|
+
onToggleItemEdit: () => setItemEditOn((on) => !on),
|
|
18979
|
+
onSetVariant: (variant) => runMutation(active.sectionId, (tree) => setMediaStripVariant(tree, variant)),
|
|
18980
|
+
onSetAlign: (align) => runMutation(active.sectionId, (tree) => setMediaStripAlign(tree, align)),
|
|
18981
|
+
onSetHover: (hoverPreset) => runMutation(active.sectionId, (tree) => setMediaStripHover(tree, hoverPreset)),
|
|
18982
|
+
onSetTreatment: (treatment) => runMutation(active.sectionId, (tree) => setMediaStripTreatment(tree, treatment)),
|
|
18983
|
+
onResize: (delta) => {
|
|
18984
|
+
const slots = findMediaStripSlots(activeEntry.tree);
|
|
18985
|
+
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
18986
|
+
const current = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
18987
|
+
void runMutation(active.sectionId, (tree) => setMediaStripSizing(tree, current + delta));
|
|
18988
|
+
},
|
|
18989
|
+
onOpenLink: () => setLinkOpen(true),
|
|
18990
|
+
onAddItem: () => {
|
|
18991
|
+
void requestAssetPick(postToParent2).then((picked) => {
|
|
18992
|
+
if (!picked) return;
|
|
18993
|
+
const item = { assetId: picked.assetId, alt: "Logo" };
|
|
18834
18994
|
void runMutation(
|
|
18835
18995
|
active.sectionId,
|
|
18836
|
-
(tree) =>
|
|
18837
|
-
|
|
18838
|
-
|
|
18839
|
-
|
|
18840
|
-
void requestAssetPick(postToParent2).then((picked) => {
|
|
18841
|
-
if (!picked) return;
|
|
18842
|
-
const item = { assetId: picked.assetId, alt: "Logo" };
|
|
18843
|
-
void runMutation(
|
|
18844
|
-
active.sectionId,
|
|
18845
|
-
(tree) => addMediaStripItem(tree, item, active.index),
|
|
18846
|
-
{ [picked.assetId]: picked.url }
|
|
18847
|
-
).then((applied) => {
|
|
18848
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
18849
|
-
});
|
|
18850
|
-
});
|
|
18851
|
-
},
|
|
18852
|
-
onChangeImage: () => {
|
|
18853
|
-
void requestAssetPick(postToParent2).then((picked) => {
|
|
18854
|
-
if (!picked) return;
|
|
18855
|
-
void runMutation(
|
|
18856
|
-
active.sectionId,
|
|
18857
|
-
(tree) => setMediaStripItemAsset(tree, active.index, picked.assetId),
|
|
18858
|
-
{ [picked.assetId]: picked.url }
|
|
18859
|
-
);
|
|
18996
|
+
(tree) => addMediaStripItem(tree, item, active.index),
|
|
18997
|
+
{ [picked.assetId]: picked.url }
|
|
18998
|
+
).then((applied) => {
|
|
18999
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
18860
19000
|
});
|
|
18861
|
-
}
|
|
18862
|
-
|
|
18863
|
-
|
|
18864
|
-
|
|
18865
|
-
|
|
18866
|
-
|
|
18867
|
-
|
|
18868
|
-
|
|
18869
|
-
|
|
18870
|
-
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, -1)).then(
|
|
18871
|
-
(applied) => {
|
|
18872
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index - 1 });
|
|
18873
|
-
}
|
|
18874
|
-
);
|
|
18875
|
-
},
|
|
18876
|
-
onMoveRight: () => {
|
|
18877
|
-
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, 1)).then(
|
|
18878
|
-
(applied) => {
|
|
18879
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
18880
|
-
}
|
|
19001
|
+
});
|
|
19002
|
+
},
|
|
19003
|
+
onChangeImage: () => {
|
|
19004
|
+
void requestAssetPick(postToParent2).then((picked) => {
|
|
19005
|
+
if (!picked) return;
|
|
19006
|
+
void runMutation(
|
|
19007
|
+
active.sectionId,
|
|
19008
|
+
(tree) => setMediaStripItemAsset(tree, active.index, picked.assetId),
|
|
19009
|
+
{ [picked.assetId]: picked.url }
|
|
18881
19010
|
);
|
|
18882
|
-
}
|
|
19011
|
+
});
|
|
19012
|
+
},
|
|
19013
|
+
onRemoveItem: () => {
|
|
19014
|
+
void runMutation(active.sectionId, (tree) => removeMediaStripItem(tree, active.index)).then(
|
|
19015
|
+
(applied) => {
|
|
19016
|
+
if (applied) setActive(null);
|
|
19017
|
+
}
|
|
19018
|
+
);
|
|
19019
|
+
},
|
|
19020
|
+
onMoveLeft: () => {
|
|
19021
|
+
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, -1)).then(
|
|
19022
|
+
(applied) => {
|
|
19023
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index - 1 });
|
|
19024
|
+
}
|
|
19025
|
+
);
|
|
19026
|
+
},
|
|
19027
|
+
onMoveRight: () => {
|
|
19028
|
+
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, 1)).then(
|
|
19029
|
+
(applied) => {
|
|
19030
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19031
|
+
}
|
|
19032
|
+
);
|
|
18883
19033
|
}
|
|
18884
|
-
|
|
18885
|
-
}
|
|
18886
|
-
|
|
19034
|
+
}
|
|
19035
|
+
) }),
|
|
19036
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
19037
|
+
"div",
|
|
19038
|
+
{
|
|
19039
|
+
"data-ohw-bridge": "",
|
|
19040
|
+
"data-ohw-item-interaction": "",
|
|
19041
|
+
"aria-hidden": true,
|
|
19042
|
+
className: "pointer-events-none fixed rounded-[4px] px-[7px] py-[3px] font-sans text-[11px] font-medium leading-none text-primary-foreground whitespace-nowrap",
|
|
19043
|
+
style: {
|
|
19044
|
+
top: activeItemRect.top + activeItemRect.height + 10,
|
|
19045
|
+
left: activeItemRect.left - 5,
|
|
19046
|
+
background: PRIMARY3,
|
|
19047
|
+
zIndex: 2147483644
|
|
19048
|
+
},
|
|
19049
|
+
children: "Media item"
|
|
19050
|
+
}
|
|
19051
|
+
),
|
|
19052
|
+
linkOpen && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
19053
|
+
LinkModal,
|
|
19054
|
+
{
|
|
19055
|
+
href: activeHref,
|
|
19056
|
+
linkTarget: activeTarget,
|
|
19057
|
+
onClose: () => setLinkOpen(false),
|
|
19058
|
+
onSave: (href, linkTarget) => {
|
|
19059
|
+
void runMutation(
|
|
19060
|
+
active.sectionId,
|
|
19061
|
+
(tree) => setMediaStripItemLink(tree, active.index, href ? { href, linkTarget } : {})
|
|
19062
|
+
);
|
|
19063
|
+
}
|
|
19064
|
+
}
|
|
19065
|
+
)
|
|
19066
|
+
] })
|
|
18887
19067
|
] });
|
|
18888
19068
|
}
|
|
18889
19069
|
|
|
18890
19070
|
// src/ui/ai-section/AiPricingCardOverlay.tsx
|
|
18891
19071
|
var import_react11 = require("react");
|
|
18892
|
-
var
|
|
18893
|
-
var
|
|
19072
|
+
var import_lucide_react10 = require("lucide-react");
|
|
19073
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
18894
19074
|
var PRIMARY4 = "var(--ohw-primary, #0885FE)";
|
|
18895
|
-
var
|
|
19075
|
+
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]";
|
|
18896
19076
|
function findPricingCardElement(sectionId, index) {
|
|
18897
19077
|
const sectionEl = findByInstanceId(sectionId);
|
|
18898
19078
|
if (!sectionEl) return null;
|
|
@@ -18904,7 +19084,7 @@ function findPricingCardElement(sectionId, index) {
|
|
|
18904
19084
|
}
|
|
18905
19085
|
function cardRefFromTarget(target) {
|
|
18906
19086
|
if (!(target instanceof Element)) return null;
|
|
18907
|
-
if (target.closest(
|
|
19087
|
+
if (target.closest(CHROME_SELECTOR2)) return null;
|
|
18908
19088
|
const cardEl = target.closest("[data-ohw-pricing-card]");
|
|
18909
19089
|
if (!cardEl) return null;
|
|
18910
19090
|
const sectionEl = cardEl.closest("[data-ohw-section]");
|
|
@@ -18914,21 +19094,21 @@ function cardRefFromTarget(target) {
|
|
|
18914
19094
|
if (!sectionId || Number.isNaN(index)) return null;
|
|
18915
19095
|
return { sectionId, index };
|
|
18916
19096
|
}
|
|
18917
|
-
function
|
|
19097
|
+
function sameRef2(a, b) {
|
|
18918
19098
|
return a?.sectionId === b?.sectionId && a?.index === b?.index;
|
|
18919
19099
|
}
|
|
18920
|
-
function
|
|
19100
|
+
function rectOf2(el) {
|
|
18921
19101
|
if (!el) return null;
|
|
18922
19102
|
const r2 = el.getBoundingClientRect();
|
|
18923
19103
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
18924
19104
|
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
18925
19105
|
}
|
|
18926
19106
|
function readRect3(ref) {
|
|
18927
|
-
return
|
|
19107
|
+
return rectOf2(ref && findPricingCardElement(ref.sectionId, ref.index));
|
|
18928
19108
|
}
|
|
18929
19109
|
function readGridRect(ref) {
|
|
18930
19110
|
const card = ref && findPricingCardElement(ref.sectionId, ref.index);
|
|
18931
|
-
return
|
|
19111
|
+
return rectOf2(card?.closest("[data-ohw-pricing-collection]") ?? card);
|
|
18932
19112
|
}
|
|
18933
19113
|
function useLiveCardRect(ref, grid = false) {
|
|
18934
19114
|
const [rect, setRect] = (0, import_react11.useState)(null);
|
|
@@ -18958,7 +19138,7 @@ function useLiveCardRect(ref, grid = false) {
|
|
|
18958
19138
|
}
|
|
18959
19139
|
var TOOLBAR_GRID_GAP = 52;
|
|
18960
19140
|
var TOOLBAR_GRID_GAP_MOBILE = 42;
|
|
18961
|
-
var
|
|
19141
|
+
var TOOLBAR_EDGE_MARGIN3 = 4;
|
|
18962
19142
|
function GridToolbarSlot({ gridRect, children }) {
|
|
18963
19143
|
const slotRef = (0, import_react11.useRef)(null);
|
|
18964
19144
|
const [shift, setShift] = (0, import_react11.useState)(0);
|
|
@@ -18970,7 +19150,7 @@ function GridToolbarSlot({ gridRect, children }) {
|
|
|
18970
19150
|
const w = slot.offsetWidth;
|
|
18971
19151
|
if (w <= 0) return;
|
|
18972
19152
|
const half = w / 2;
|
|
18973
|
-
const clamped = Math.max(
|
|
19153
|
+
const clamped = Math.max(TOOLBAR_EDGE_MARGIN3 + half, Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN3 - half));
|
|
18974
19154
|
setShift((prev) => Math.abs(prev - (clamped - centerX)) < 0.5 ? prev : clamped - centerX);
|
|
18975
19155
|
};
|
|
18976
19156
|
clamp();
|
|
@@ -18979,7 +19159,7 @@ function GridToolbarSlot({ gridRect, children }) {
|
|
|
18979
19159
|
return () => ro.disconnect();
|
|
18980
19160
|
}, [centerX, children]);
|
|
18981
19161
|
const mobile = window.innerWidth <= 480;
|
|
18982
|
-
return /* @__PURE__ */ (0,
|
|
19162
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
18983
19163
|
"div",
|
|
18984
19164
|
{
|
|
18985
19165
|
ref: slotRef,
|
|
@@ -19014,7 +19194,7 @@ function requestValidateTree2(postToParent2, tree) {
|
|
|
19014
19194
|
});
|
|
19015
19195
|
}
|
|
19016
19196
|
function StyleSwatch({ style }) {
|
|
19017
|
-
return /* @__PURE__ */ (0,
|
|
19197
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19018
19198
|
"span",
|
|
19019
19199
|
{
|
|
19020
19200
|
"aria-hidden": true,
|
|
@@ -19028,35 +19208,35 @@ function StyleSwatch({ style }) {
|
|
|
19028
19208
|
);
|
|
19029
19209
|
}
|
|
19030
19210
|
function ButtonGlyph() {
|
|
19031
|
-
return /* @__PURE__ */ (0,
|
|
19032
|
-
/* @__PURE__ */ (0,
|
|
19033
|
-
/* @__PURE__ */ (0,
|
|
19211
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("svg", { width: "18", height: "12", viewBox: "0 0 18 12", fill: "none", "aria-hidden": true, style: { pointerEvents: "none" }, children: [
|
|
19212
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("rect", { x: "0.75", y: "0.75", width: "16.5", height: "10.5", rx: "3", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
19213
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("path", { d: "M5.5 6H12.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
|
|
19034
19214
|
] });
|
|
19035
19215
|
}
|
|
19036
19216
|
function FeatureGlyph({ mode }) {
|
|
19037
|
-
return /* @__PURE__ */ (0,
|
|
19038
|
-
/* @__PURE__ */ (0,
|
|
19039
|
-
/* @__PURE__ */ (0,
|
|
19040
|
-
/* @__PURE__ */ (0,
|
|
19041
|
-
/* @__PURE__ */ (0,
|
|
19042
|
-
/* @__PURE__ */ (0,
|
|
19043
|
-
mode === "add" && /* @__PURE__ */ (0,
|
|
19217
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "none", "aria-hidden": true, style: { pointerEvents: "none" }, children: [
|
|
19218
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("circle", { cx: "8", cy: "8", r: "7.25", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
19219
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("path", { d: "M5 8.2L7.2 10.3L11 6", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
19220
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("circle", { cx: "13.5", cy: "13.5", r: "4.25", fill: "var(--ohw-background, #ffffff)", stroke: "var(--ohw-background, #ffffff)", strokeWidth: "1" }),
|
|
19221
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("circle", { cx: "13.5", cy: "13.5", r: "3.75", fill: "var(--ohw-background, #ffffff)", stroke: PRIMARY4, strokeWidth: "1" }),
|
|
19222
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("path", { d: "M11.5 13.5H15.5", stroke: PRIMARY4, strokeWidth: "1.5", strokeLinecap: "round" }),
|
|
19223
|
+
mode === "add" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("path", { d: "M13.5 11.5V15.5", stroke: PRIMARY4, strokeWidth: "1.5", strokeLinecap: "round" })
|
|
19044
19224
|
] });
|
|
19045
19225
|
}
|
|
19046
|
-
function
|
|
19226
|
+
function ToolbarAction2({
|
|
19047
19227
|
label,
|
|
19048
19228
|
onClick,
|
|
19049
19229
|
disabled = false,
|
|
19050
19230
|
children
|
|
19051
19231
|
}) {
|
|
19052
|
-
const button = /* @__PURE__ */ (0,
|
|
19053
|
-
return /* @__PURE__ */ (0,
|
|
19054
|
-
/* @__PURE__ */ (0,
|
|
19055
|
-
/* @__PURE__ */ (0,
|
|
19232
|
+
const button = /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CustomToolbarButton, { type: "button", "aria-label": label, disabled, onClick, className: "size-8", children });
|
|
19233
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Tooltip, { children: [
|
|
19234
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "inline-flex", children: button }) : button }),
|
|
19235
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: label })
|
|
19056
19236
|
] });
|
|
19057
19237
|
}
|
|
19058
|
-
function
|
|
19059
|
-
return /* @__PURE__ */ (0,
|
|
19238
|
+
function ToolbarSeparator2() {
|
|
19239
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { "aria-hidden": true, className: "mx-0.5 block h-6 w-px shrink-0 bg-border" });
|
|
19060
19240
|
}
|
|
19061
19241
|
function CardStyleMenu({
|
|
19062
19242
|
value,
|
|
@@ -19064,7 +19244,7 @@ function CardStyleMenu({
|
|
|
19064
19244
|
disabled = false
|
|
19065
19245
|
}) {
|
|
19066
19246
|
const current = PRICING_CARD_STYLES.find((s) => s.value === value) ?? PRICING_CARD_STYLES[0];
|
|
19067
|
-
const trigger = /* @__PURE__ */ (0,
|
|
19247
|
+
const trigger = /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
19068
19248
|
"button",
|
|
19069
19249
|
{
|
|
19070
19250
|
type: "button",
|
|
@@ -19075,28 +19255,28 @@ function CardStyleMenu({
|
|
|
19075
19255
|
disabled && "cursor-not-allowed opacity-40 hover:bg-transparent"
|
|
19076
19256
|
),
|
|
19077
19257
|
children: [
|
|
19078
|
-
/* @__PURE__ */ (0,
|
|
19079
|
-
/* @__PURE__ */ (0,
|
|
19080
|
-
/* @__PURE__ */ (0,
|
|
19258
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StyleSwatch, { style: current.value }),
|
|
19259
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "flex-1 text-left", children: current.label }),
|
|
19260
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.ChevronDown, { size: 16, style: { pointerEvents: "none" } })
|
|
19081
19261
|
]
|
|
19082
19262
|
}
|
|
19083
19263
|
);
|
|
19084
19264
|
if (disabled) {
|
|
19085
|
-
return /* @__PURE__ */ (0,
|
|
19086
|
-
/* @__PURE__ */ (0,
|
|
19087
|
-
/* @__PURE__ */ (0,
|
|
19088
|
-
/* @__PURE__ */ (0,
|
|
19089
|
-
/* @__PURE__ */ (0,
|
|
19265
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19266
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-xs text-muted-foreground opacity-50", children: "Card style" }),
|
|
19267
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Tooltip, { children: [
|
|
19268
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "inline-flex", children: trigger }) }),
|
|
19269
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: "Mark as featured to edit card style" })
|
|
19090
19270
|
] })
|
|
19091
19271
|
] });
|
|
19092
19272
|
}
|
|
19093
|
-
return /* @__PURE__ */ (0,
|
|
19094
|
-
/* @__PURE__ */ (0,
|
|
19095
|
-
/* @__PURE__ */ (0,
|
|
19096
|
-
/* @__PURE__ */ (0,
|
|
19097
|
-
/* @__PURE__ */ (0,
|
|
19273
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19274
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-xs text-muted-foreground", children: "Card style" }),
|
|
19275
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(DropdownMenu, { modal: false, children: [
|
|
19276
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DropdownMenuTrigger, { asChild: true, children: trigger }),
|
|
19277
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DropdownMenuContent, { align: "end", sideOffset: 8, className: "w-[152px] min-w-[152px] p-1", children: PRICING_CARD_STYLES.map((style) => {
|
|
19098
19278
|
const selected = style.value === value;
|
|
19099
|
-
return /* @__PURE__ */ (0,
|
|
19279
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
19100
19280
|
DropdownMenuItem,
|
|
19101
19281
|
{
|
|
19102
19282
|
role: "menuitemradio",
|
|
@@ -19104,9 +19284,9 @@ function CardStyleMenu({
|
|
|
19104
19284
|
onSelect: () => onChange(style.value),
|
|
19105
19285
|
className: cn("grid grid-cols-[18px_1fr_16px] gap-2 py-2 pl-2 pr-2 text-[13px]", selected && "bg-muted"),
|
|
19106
19286
|
children: [
|
|
19107
|
-
/* @__PURE__ */ (0,
|
|
19108
|
-
/* @__PURE__ */ (0,
|
|
19109
|
-
selected && /* @__PURE__ */ (0,
|
|
19287
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StyleSwatch, { style: style.value }),
|
|
19288
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: style.label }),
|
|
19289
|
+
selected && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.Check, { size: 16, className: "text-bridge-primary" })
|
|
19110
19290
|
]
|
|
19111
19291
|
},
|
|
19112
19292
|
style.value
|
|
@@ -19136,7 +19316,7 @@ function PricingCardToolbar({
|
|
|
19136
19316
|
const style = pricingCardStyle(entry.tree, index);
|
|
19137
19317
|
const featuredTag = pricingCardFeaturedTag(entry.tree, index);
|
|
19138
19318
|
const mobile = window.innerWidth <= 480;
|
|
19139
|
-
return /* @__PURE__ */ (0,
|
|
19319
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
19140
19320
|
"div",
|
|
19141
19321
|
{
|
|
19142
19322
|
"data-ohw-bridge": "",
|
|
@@ -19148,7 +19328,7 @@ function PricingCardToolbar({
|
|
|
19148
19328
|
),
|
|
19149
19329
|
style: { maxWidth: mobile ? "calc(100vw - 24px)" : void 0 },
|
|
19150
19330
|
children: [
|
|
19151
|
-
/* @__PURE__ */ (0,
|
|
19331
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
19152
19332
|
"div",
|
|
19153
19333
|
{
|
|
19154
19334
|
className: cn(
|
|
@@ -19157,8 +19337,8 @@ function PricingCardToolbar({
|
|
|
19157
19337
|
mobile ? "flex-wrap justify-center" : "flex-nowrap"
|
|
19158
19338
|
),
|
|
19159
19339
|
children: [
|
|
19160
|
-
/* @__PURE__ */ (0,
|
|
19161
|
-
/* @__PURE__ */ (0,
|
|
19340
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Tooltip, { children: [
|
|
19341
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19162
19342
|
CustomToolbarButton,
|
|
19163
19343
|
{
|
|
19164
19344
|
type: "button",
|
|
@@ -19166,8 +19346,8 @@ function PricingCardToolbar({
|
|
|
19166
19346
|
"aria-pressed": featuredTag,
|
|
19167
19347
|
onClick: () => onSetFeaturedTag(!featuredTag),
|
|
19168
19348
|
className: "group size-8",
|
|
19169
|
-
children: /* @__PURE__ */ (0,
|
|
19170
|
-
|
|
19349
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19350
|
+
import_lucide_react10.Star,
|
|
19171
19351
|
{
|
|
19172
19352
|
size: 16,
|
|
19173
19353
|
fill: "currentColor",
|
|
@@ -19181,25 +19361,25 @@ function PricingCardToolbar({
|
|
|
19181
19361
|
)
|
|
19182
19362
|
}
|
|
19183
19363
|
) }),
|
|
19184
|
-
/* @__PURE__ */ (0,
|
|
19364
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: featuredTag ? "Unmark featured" : "Mark as featured" })
|
|
19185
19365
|
] }),
|
|
19186
|
-
/* @__PURE__ */ (0,
|
|
19187
|
-
/* @__PURE__ */ (0,
|
|
19188
|
-
/* @__PURE__ */ (0,
|
|
19189
|
-
/* @__PURE__ */ (0,
|
|
19190
|
-
/* @__PURE__ */ (0,
|
|
19191
|
-
/* @__PURE__ */ (0,
|
|
19192
|
-
/* @__PURE__ */ (0,
|
|
19366
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator2, {}),
|
|
19367
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CardStyleMenu, { value: style, onChange: onSetStyle, disabled: !featuredTag }),
|
|
19368
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator2, {}),
|
|
19369
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction2, { label: "Add button", onClick: onAddButton, disabled: buttonCount >= 2, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ButtonGlyph, {}) }),
|
|
19370
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction2, { label: "Remove button", onClick: onRemoveButton, disabled: buttonCount === 0, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "relative inline-flex", children: [
|
|
19371
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ButtonGlyph, {}),
|
|
19372
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.Minus, { size: 10, strokeWidth: 2.5, className: "absolute -right-1.5 -top-1.5 rounded-full bg-background text-bridge-primary" })
|
|
19193
19373
|
] }) }),
|
|
19194
|
-
/* @__PURE__ */ (0,
|
|
19195
|
-
/* @__PURE__ */ (0,
|
|
19196
|
-
/* @__PURE__ */ (0,
|
|
19197
|
-
/* @__PURE__ */ (0,
|
|
19198
|
-
/* @__PURE__ */ (0,
|
|
19374
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction2, { label: "Add feature", onClick: onAddFeature, disabled: featureCount >= 10, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(FeatureGlyph, { mode: "add" }) }),
|
|
19375
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction2, { label: "Remove feature", onClick: onRemoveFeature, disabled: featureCount <= 1, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(FeatureGlyph, { mode: "remove" }) }),
|
|
19376
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator2, {}),
|
|
19377
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction2, { label: "Add tier", onClick: onAddTier, disabled: collectionCount >= 4, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.Plus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19378
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction2, { label: "Remove tier", onClick: onRemoveTier, disabled: collectionCount <= 1, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.Minus, { size: 16, style: { pointerEvents: "none" } }) })
|
|
19199
19379
|
]
|
|
19200
19380
|
}
|
|
19201
19381
|
),
|
|
19202
|
-
error && /* @__PURE__ */ (0,
|
|
19382
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "max-w-[260px] rounded-md bg-background px-2 py-1 text-center text-[11px] text-destructive shadow-sm", children: error })
|
|
19203
19383
|
]
|
|
19204
19384
|
}
|
|
19205
19385
|
) });
|
|
@@ -19233,7 +19413,7 @@ function AiPricingCardOverlay({
|
|
|
19233
19413
|
const overEditable = Boolean(t?.closest?.("[data-ohw-editable], [data-ohw-role], a, button"));
|
|
19234
19414
|
setHover((prev) => {
|
|
19235
19415
|
const next = ref && !overEditable ? ref : null;
|
|
19236
|
-
return
|
|
19416
|
+
return sameRef2(prev, next) ? prev : next;
|
|
19237
19417
|
});
|
|
19238
19418
|
};
|
|
19239
19419
|
const onLeave = () => setHover(null);
|
|
@@ -19248,10 +19428,10 @@ function AiPricingCardOverlay({
|
|
|
19248
19428
|
const onClick = (e) => {
|
|
19249
19429
|
const t = e.target;
|
|
19250
19430
|
if (!(t instanceof Element)) return;
|
|
19251
|
-
if (t.closest(
|
|
19431
|
+
if (t.closest(CHROME_SELECTOR2)) return;
|
|
19252
19432
|
const ref = cardRefFromTarget(t);
|
|
19253
|
-
setActive((prev) =>
|
|
19254
|
-
if (!ref || !
|
|
19433
|
+
setActive((prev) => sameRef2(prev, ref) ? prev : ref);
|
|
19434
|
+
if (!ref || !sameRef2(activeRef.current, ref)) setError(null);
|
|
19255
19435
|
};
|
|
19256
19436
|
document.addEventListener("click", onClick, true);
|
|
19257
19437
|
return () => document.removeEventListener("click", onClick, true);
|
|
@@ -19316,12 +19496,12 @@ function AiPricingCardOverlay({
|
|
|
19316
19496
|
const activeEntry = active ? findEntry(active.sectionId) : null;
|
|
19317
19497
|
const activeCardRect = useLiveCardRect(active);
|
|
19318
19498
|
const activeGridRect = useLiveCardRect(active, true);
|
|
19319
|
-
const hoverRect = useLiveCardRect(hover && !
|
|
19320
|
-
return /* @__PURE__ */ (0,
|
|
19321
|
-
hoverRect && /* @__PURE__ */ (0,
|
|
19322
|
-
activeCardRect && activeGridRect && active && activeEntry && /* @__PURE__ */ (0,
|
|
19323
|
-
/* @__PURE__ */ (0,
|
|
19324
|
-
/* @__PURE__ */ (0,
|
|
19499
|
+
const hoverRect = useLiveCardRect(hover && !sameRef2(hover, active) ? hover : null);
|
|
19500
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
19501
|
+
hoverRect && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ItemInteractionLayer, { rect: hoverRect, state: "hover" }),
|
|
19502
|
+
activeCardRect && activeGridRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
19503
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ItemInteractionLayer, { rect: activeCardRect, state: "active-top" }),
|
|
19504
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(GridToolbarSlot, { gridRect: activeGridRect, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19325
19505
|
PricingCardToolbar,
|
|
19326
19506
|
{
|
|
19327
19507
|
entry: activeEntry,
|
|
@@ -19349,7 +19529,7 @@ function AiPricingCardOverlay({
|
|
|
19349
19529
|
onRemoveFeature: () => runMutation(active.sectionId, (tree) => removePricingCardFeature(tree, active.index))
|
|
19350
19530
|
}
|
|
19351
19531
|
) }),
|
|
19352
|
-
/* @__PURE__ */ (0,
|
|
19532
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19353
19533
|
"div",
|
|
19354
19534
|
{
|
|
19355
19535
|
"data-ohw-bridge": "",
|
|
@@ -19371,7 +19551,7 @@ function AiPricingCardOverlay({
|
|
|
19371
19551
|
|
|
19372
19552
|
// src/ui/ai-section/AiVideoOverlay.tsx
|
|
19373
19553
|
var import_react12 = require("react");
|
|
19374
|
-
var
|
|
19554
|
+
var import_lucide_react11 = require("lucide-react");
|
|
19375
19555
|
|
|
19376
19556
|
// src/lib/ai-video-tree.ts
|
|
19377
19557
|
function resolveVideoBlock(tree, path) {
|
|
@@ -19442,10 +19622,10 @@ function extractYouTubeId(input) {
|
|
|
19442
19622
|
}
|
|
19443
19623
|
|
|
19444
19624
|
// src/ui/ai-section/AiVideoOverlay.tsx
|
|
19445
|
-
var
|
|
19625
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
19446
19626
|
var PRIMARY5 = "#0885FE";
|
|
19447
|
-
var
|
|
19448
|
-
var
|
|
19627
|
+
var OHW_BLUE = `var(--ohw-primary, ${PRIMARY5})`;
|
|
19628
|
+
var OHW_BLUE_DARK = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY5}) 60%, #000000)`;
|
|
19449
19629
|
function findVideoBlockElement(sectionId, path) {
|
|
19450
19630
|
const sectionEl = findByInstanceId(sectionId);
|
|
19451
19631
|
if (!sectionEl) return null;
|
|
@@ -19505,12 +19685,12 @@ function requestValidateTree3(postToParent2, tree) {
|
|
|
19505
19685
|
postToParent2({ type: "ow:ai-validate-tree-request", id, tree });
|
|
19506
19686
|
});
|
|
19507
19687
|
}
|
|
19508
|
-
function
|
|
19688
|
+
function Pill({
|
|
19509
19689
|
label,
|
|
19510
19690
|
onClick,
|
|
19511
19691
|
disabled
|
|
19512
19692
|
}) {
|
|
19513
|
-
return /* @__PURE__ */ (0,
|
|
19693
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19514
19694
|
"button",
|
|
19515
19695
|
{
|
|
19516
19696
|
type: "button",
|
|
@@ -19526,7 +19706,7 @@ function Pill2({
|
|
|
19526
19706
|
border: "none",
|
|
19527
19707
|
cursor: disabled ? "default" : "pointer",
|
|
19528
19708
|
background: "#ffffff",
|
|
19529
|
-
color:
|
|
19709
|
+
color: OHW_BLUE_DARK,
|
|
19530
19710
|
opacity: disabled ? 0.4 : 1,
|
|
19531
19711
|
fontSize: 12,
|
|
19532
19712
|
lineHeight: "16px",
|
|
@@ -19569,8 +19749,8 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
19569
19749
|
onCommit(id);
|
|
19570
19750
|
}
|
|
19571
19751
|
};
|
|
19572
|
-
return /* @__PURE__ */ (0,
|
|
19573
|
-
/* @__PURE__ */ (0,
|
|
19752
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 4, width: "100%", maxWidth: 280 }, children: [
|
|
19753
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
19574
19754
|
"div",
|
|
19575
19755
|
{
|
|
19576
19756
|
style: {
|
|
@@ -19586,12 +19766,12 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
19586
19766
|
boxShadow: invalid ? "inset 0 0 0 1.5px #EF4444" : "none"
|
|
19587
19767
|
},
|
|
19588
19768
|
children: [
|
|
19589
|
-
/* @__PURE__ */ (0,
|
|
19769
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19590
19770
|
"span",
|
|
19591
19771
|
{
|
|
19592
19772
|
style: {
|
|
19593
19773
|
flex: "0 0 auto",
|
|
19594
|
-
color:
|
|
19774
|
+
color: OHW_BLUE_DARK,
|
|
19595
19775
|
fontSize: 10,
|
|
19596
19776
|
lineHeight: "16px",
|
|
19597
19777
|
fontWeight: 700,
|
|
@@ -19601,7 +19781,7 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
19601
19781
|
children: "Video"
|
|
19602
19782
|
}
|
|
19603
19783
|
),
|
|
19604
|
-
/* @__PURE__ */ (0,
|
|
19784
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19605
19785
|
"input",
|
|
19606
19786
|
{
|
|
19607
19787
|
type: "text",
|
|
@@ -19638,7 +19818,7 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
19638
19818
|
]
|
|
19639
19819
|
}
|
|
19640
19820
|
),
|
|
19641
|
-
invalid && /* @__PURE__ */ (0,
|
|
19821
|
+
invalid && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { color: "#FCA5A5", fontSize: 11, textAlign: "center" }, children: "That doesn't look like a YouTube link \u2014 try pasting the video URL again." })
|
|
19642
19822
|
] });
|
|
19643
19823
|
}
|
|
19644
19824
|
function VideoToolbar({
|
|
@@ -19648,7 +19828,7 @@ function VideoToolbar({
|
|
|
19648
19828
|
onSetVideoId,
|
|
19649
19829
|
onRemove
|
|
19650
19830
|
}) {
|
|
19651
|
-
return /* @__PURE__ */ (0,
|
|
19831
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
19652
19832
|
"div",
|
|
19653
19833
|
{
|
|
19654
19834
|
"data-ohw-bridge": "",
|
|
@@ -19660,7 +19840,7 @@ function VideoToolbar({
|
|
|
19660
19840
|
gap: 6,
|
|
19661
19841
|
alignItems: "center",
|
|
19662
19842
|
width: 280,
|
|
19663
|
-
background:
|
|
19843
|
+
background: OHW_BLUE,
|
|
19664
19844
|
padding: 8,
|
|
19665
19845
|
borderRadius: 12,
|
|
19666
19846
|
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
@@ -19668,9 +19848,9 @@ function VideoToolbar({
|
|
|
19668
19848
|
opacity: pending ? 0.6 : 1
|
|
19669
19849
|
},
|
|
19670
19850
|
children: [
|
|
19671
|
-
/* @__PURE__ */ (0,
|
|
19672
|
-
/* @__PURE__ */ (0,
|
|
19673
|
-
error && /* @__PURE__ */ (0,
|
|
19851
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(VideoUrlInput, { value: videoId, onCommit: onSetVideoId }),
|
|
19852
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Pill, { label: "Remove video", onClick: onRemove, disabled: !videoId }),
|
|
19853
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { color: "#FCA5A5", fontSize: 11, maxWidth: 220, textAlign: "center" }, children: error })
|
|
19674
19854
|
]
|
|
19675
19855
|
}
|
|
19676
19856
|
);
|
|
@@ -19790,8 +19970,8 @@ function AiVideoOverlay({
|
|
|
19790
19970
|
const activeBlockRect = useLiveBlockRect(active);
|
|
19791
19971
|
const TOOLBAR_APPROX_H = 90;
|
|
19792
19972
|
const toolbarState = activeBlockRect && activeBlockRect.top < TOOLBAR_APPROX_H ? "active-bottom" : "active-top";
|
|
19793
|
-
return /* @__PURE__ */ (0,
|
|
19794
|
-
hoverHandleRect && hover && /* @__PURE__ */ (0,
|
|
19973
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
19974
|
+
hoverHandleRect && hover && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19795
19975
|
"button",
|
|
19796
19976
|
{
|
|
19797
19977
|
type: "button",
|
|
@@ -19819,15 +19999,15 @@ function AiVideoOverlay({
|
|
|
19819
19999
|
fontSize: 14,
|
|
19820
20000
|
fontWeight: 700
|
|
19821
20001
|
},
|
|
19822
|
-
children: /* @__PURE__ */ (0,
|
|
20002
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react11.Star, { size: 14, style: { pointerEvents: "none" } })
|
|
19823
20003
|
}
|
|
19824
20004
|
),
|
|
19825
|
-
activeBlockRect && active && activeEntry && /* @__PURE__ */ (0,
|
|
20005
|
+
activeBlockRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19826
20006
|
ItemInteractionLayer,
|
|
19827
20007
|
{
|
|
19828
20008
|
rect: activeBlockRect,
|
|
19829
20009
|
state: toolbarState,
|
|
19830
|
-
toolbar: /* @__PURE__ */ (0,
|
|
20010
|
+
toolbar: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19831
20011
|
VideoToolbar,
|
|
19832
20012
|
{
|
|
19833
20013
|
videoId: videoIdAt(activeEntry.tree, active.path),
|
|
@@ -19851,7 +20031,7 @@ function AiVideoOverlay({
|
|
|
19851
20031
|
|
|
19852
20032
|
// src/ui/ai-section/AiFadeCarouselOverlay.tsx
|
|
19853
20033
|
var import_react13 = require("react");
|
|
19854
|
-
var
|
|
20034
|
+
var import_lucide_react12 = require("lucide-react");
|
|
19855
20035
|
|
|
19856
20036
|
// src/lib/ai-carousel-tree.ts
|
|
19857
20037
|
function isCarouselBlock(node) {
|
|
@@ -19902,10 +20082,10 @@ function setCarouselAutoplay(tree, on) {
|
|
|
19902
20082
|
}
|
|
19903
20083
|
|
|
19904
20084
|
// src/ui/ai-section/AiFadeCarouselOverlay.tsx
|
|
19905
|
-
var
|
|
20085
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
19906
20086
|
var PRIMARY6 = "#0885FE";
|
|
19907
|
-
var
|
|
19908
|
-
var
|
|
20087
|
+
var OHW_BLUE2 = `var(--ohw-primary, ${PRIMARY6})`;
|
|
20088
|
+
var OHW_BLUE_DARK2 = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY6}) 60%, #000000)`;
|
|
19909
20089
|
function findCarouselItemElement(sectionId, index) {
|
|
19910
20090
|
const sectionEl = findByInstanceId(sectionId);
|
|
19911
20091
|
if (!sectionEl) return null;
|
|
@@ -19984,8 +20164,8 @@ function requestAssetPick2(postToParent2) {
|
|
|
19984
20164
|
postToParent2({ type: "ow:asset-pick", id });
|
|
19985
20165
|
});
|
|
19986
20166
|
}
|
|
19987
|
-
function
|
|
19988
|
-
return /* @__PURE__ */ (0,
|
|
20167
|
+
function Pill2({ label, onClick, disabled }) {
|
|
20168
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
19989
20169
|
"button",
|
|
19990
20170
|
{
|
|
19991
20171
|
type: "button",
|
|
@@ -20001,7 +20181,7 @@ function Pill3({ label, onClick, disabled }) {
|
|
|
20001
20181
|
border: "none",
|
|
20002
20182
|
cursor: disabled ? "default" : "pointer",
|
|
20003
20183
|
background: "#ffffff",
|
|
20004
|
-
color:
|
|
20184
|
+
color: OHW_BLUE_DARK2,
|
|
20005
20185
|
opacity: disabled ? 0.4 : 1,
|
|
20006
20186
|
fontSize: 12,
|
|
20007
20187
|
lineHeight: "16px",
|
|
@@ -20019,7 +20199,7 @@ function TogglePill({
|
|
|
20019
20199
|
onToggle,
|
|
20020
20200
|
disabled
|
|
20021
20201
|
}) {
|
|
20022
|
-
return /* @__PURE__ */ (0,
|
|
20202
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
20023
20203
|
"button",
|
|
20024
20204
|
{
|
|
20025
20205
|
type: "button",
|
|
@@ -20038,7 +20218,7 @@ function TogglePill({
|
|
|
20038
20218
|
border: "none",
|
|
20039
20219
|
cursor: disabled ? "default" : "pointer",
|
|
20040
20220
|
background: "#ffffff",
|
|
20041
|
-
color:
|
|
20221
|
+
color: OHW_BLUE_DARK2,
|
|
20042
20222
|
opacity: disabled ? 0.4 : 1,
|
|
20043
20223
|
fontSize: 12,
|
|
20044
20224
|
lineHeight: "16px",
|
|
@@ -20048,7 +20228,7 @@ function TogglePill({
|
|
|
20048
20228
|
},
|
|
20049
20229
|
children: [
|
|
20050
20230
|
label,
|
|
20051
|
-
/* @__PURE__ */ (0,
|
|
20231
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20052
20232
|
"span",
|
|
20053
20233
|
{
|
|
20054
20234
|
"aria-hidden": true,
|
|
@@ -20061,10 +20241,10 @@ function TogglePill({
|
|
|
20061
20241
|
// Off is a grey track, not a washed-out blue: the pill's own white background already
|
|
20062
20242
|
// carries the brand colour in the text, and a pale blue track next to it read as
|
|
20063
20243
|
// "disabled control" rather than "switch that is off".
|
|
20064
|
-
background: on ?
|
|
20244
|
+
background: on ? OHW_BLUE_DARK2 : "#CBD5E1",
|
|
20065
20245
|
transition: "background 120ms ease"
|
|
20066
20246
|
},
|
|
20067
|
-
children: /* @__PURE__ */ (0,
|
|
20247
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20068
20248
|
"span",
|
|
20069
20249
|
{
|
|
20070
20250
|
style: {
|
|
@@ -20093,7 +20273,7 @@ function CarouselSlideToolbar({
|
|
|
20093
20273
|
onChangeImage,
|
|
20094
20274
|
onToggleAutoplay
|
|
20095
20275
|
}) {
|
|
20096
|
-
return /* @__PURE__ */ (0,
|
|
20276
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
20097
20277
|
"div",
|
|
20098
20278
|
{
|
|
20099
20279
|
"data-ohw-bridge": "",
|
|
@@ -20104,7 +20284,7 @@ function CarouselSlideToolbar({
|
|
|
20104
20284
|
flexDirection: "column",
|
|
20105
20285
|
gap: 6,
|
|
20106
20286
|
alignItems: "center",
|
|
20107
|
-
background:
|
|
20287
|
+
background: OHW_BLUE2,
|
|
20108
20288
|
padding: 8,
|
|
20109
20289
|
borderRadius: 12,
|
|
20110
20290
|
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
@@ -20116,11 +20296,11 @@ function CarouselSlideToolbar({
|
|
|
20116
20296
|
pointerEvents: pending ? "none" : "auto"
|
|
20117
20297
|
},
|
|
20118
20298
|
children: [
|
|
20119
|
-
/* @__PURE__ */ (0,
|
|
20120
|
-
/* @__PURE__ */ (0,
|
|
20121
|
-
/* @__PURE__ */ (0,
|
|
20299
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { display: "flex", gap: 6, alignItems: "center" }, children: [
|
|
20300
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Pill2, { label: "Change Image", onClick: onChangeImage }),
|
|
20301
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TogglePill, { label: "Autoplay", on: autoplay, onToggle: onToggleAutoplay })
|
|
20122
20302
|
] }),
|
|
20123
|
-
error && /* @__PURE__ */ (0,
|
|
20303
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { color: "#FCA5A5", fontSize: 11, maxWidth: 220, textAlign: "center" }, children: error })
|
|
20124
20304
|
]
|
|
20125
20305
|
}
|
|
20126
20306
|
);
|
|
@@ -20260,8 +20440,8 @@ function AiFadeCarouselOverlay({
|
|
|
20260
20440
|
const activeItemRect = useLiveItemRect2(active);
|
|
20261
20441
|
const TOOLBAR_APPROX_H = 90;
|
|
20262
20442
|
const toolbarState = activeItemRect && activeItemRect.top < TOOLBAR_APPROX_H ? "active-bottom" : "active-top";
|
|
20263
|
-
return /* @__PURE__ */ (0,
|
|
20264
|
-
hoverHandleRect && hover && /* @__PURE__ */ (0,
|
|
20443
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
20444
|
+
hoverHandleRect && hover && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20265
20445
|
"button",
|
|
20266
20446
|
{
|
|
20267
20447
|
type: "button",
|
|
@@ -20290,10 +20470,10 @@ function AiFadeCarouselOverlay({
|
|
|
20290
20470
|
fontSize: 14,
|
|
20291
20471
|
fontWeight: 700
|
|
20292
20472
|
},
|
|
20293
|
-
children: /* @__PURE__ */ (0,
|
|
20473
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react12.Star, { size: 14, style: { pointerEvents: "none" } })
|
|
20294
20474
|
}
|
|
20295
20475
|
),
|
|
20296
|
-
swapping && /* @__PURE__ */ (0,
|
|
20476
|
+
swapping && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20297
20477
|
"div",
|
|
20298
20478
|
{
|
|
20299
20479
|
ref: skeletonRef,
|
|
@@ -20311,15 +20491,15 @@ function AiFadeCarouselOverlay({
|
|
|
20311
20491
|
zIndex: 2147483646,
|
|
20312
20492
|
pointerEvents: "none"
|
|
20313
20493
|
},
|
|
20314
|
-
children: /* @__PURE__ */ (0,
|
|
20494
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("style", { children: MEDIA_SKELETON_CSS })
|
|
20315
20495
|
}
|
|
20316
20496
|
),
|
|
20317
|
-
activeItemRect && active && activeEntry && /* @__PURE__ */ (0,
|
|
20497
|
+
activeItemRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20318
20498
|
ItemInteractionLayer,
|
|
20319
20499
|
{
|
|
20320
20500
|
rect: activeItemRect,
|
|
20321
20501
|
state: toolbarState,
|
|
20322
|
-
toolbar: /* @__PURE__ */ (0,
|
|
20502
|
+
toolbar: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20323
20503
|
CarouselSlideToolbar,
|
|
20324
20504
|
{
|
|
20325
20505
|
pending,
|
|
@@ -20672,113 +20852,6 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
|
|
|
20672
20852
|
// src/ui/link-modal/LinkPopover.tsx
|
|
20673
20853
|
var import_react17 = require("react");
|
|
20674
20854
|
|
|
20675
|
-
// src/ui/dialog.tsx
|
|
20676
|
-
var React9 = __toESM(require("react"), 1);
|
|
20677
|
-
var import_radix_ui6 = require("radix-ui");
|
|
20678
|
-
var import_lucide_react12 = require("lucide-react");
|
|
20679
|
-
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
20680
|
-
function Dialog2({
|
|
20681
|
-
...props
|
|
20682
|
-
}) {
|
|
20683
|
-
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_radix_ui6.Dialog.Root, { "data-slot": "dialog", ...props });
|
|
20684
|
-
}
|
|
20685
|
-
function DialogPortal({
|
|
20686
|
-
...props
|
|
20687
|
-
}) {
|
|
20688
|
-
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_radix_ui6.Dialog.Portal, { ...props });
|
|
20689
|
-
}
|
|
20690
|
-
function DialogOverlay({
|
|
20691
|
-
className,
|
|
20692
|
-
...props
|
|
20693
|
-
}) {
|
|
20694
|
-
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20695
|
-
import_radix_ui6.Dialog.Overlay,
|
|
20696
|
-
{
|
|
20697
|
-
"data-slot": "dialog-overlay",
|
|
20698
|
-
"data-ohw-link-modal-root": "",
|
|
20699
|
-
className: cn("fixed inset-0 z-[2147483646] bg-black/50", className),
|
|
20700
|
-
...props
|
|
20701
|
-
}
|
|
20702
|
-
);
|
|
20703
|
-
}
|
|
20704
|
-
var DialogContent = React9.forwardRef(
|
|
20705
|
-
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
20706
|
-
const positionMode = container ? "absolute" : "fixed";
|
|
20707
|
-
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(DialogPortal, { container: container ?? void 0, children: [
|
|
20708
|
-
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
20709
|
-
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
20710
|
-
import_radix_ui6.Dialog.Content,
|
|
20711
|
-
{
|
|
20712
|
-
ref,
|
|
20713
|
-
"data-slot": "dialog-content",
|
|
20714
|
-
className: cn(
|
|
20715
|
-
positionMode,
|
|
20716
|
-
"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",
|
|
20717
|
-
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
20718
|
-
container ? "max-h-[calc(100%-32px)]" : "max-h-[calc(100vh-32px)]",
|
|
20719
|
-
className
|
|
20720
|
-
),
|
|
20721
|
-
onMouseDown: (e) => e.stopPropagation(),
|
|
20722
|
-
...props,
|
|
20723
|
-
children: [
|
|
20724
|
-
children,
|
|
20725
|
-
showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20726
|
-
import_radix_ui6.Dialog.Close,
|
|
20727
|
-
{
|
|
20728
|
-
type: "button",
|
|
20729
|
-
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
20730
|
-
"aria-label": "Close",
|
|
20731
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react12.X, { size: 16, "aria-hidden": true })
|
|
20732
|
-
}
|
|
20733
|
-
) : null
|
|
20734
|
-
]
|
|
20735
|
-
}
|
|
20736
|
-
)
|
|
20737
|
-
] });
|
|
20738
|
-
}
|
|
20739
|
-
);
|
|
20740
|
-
DialogContent.displayName = import_radix_ui6.Dialog.Content.displayName;
|
|
20741
|
-
function DialogHeader({
|
|
20742
|
-
className,
|
|
20743
|
-
...props
|
|
20744
|
-
}) {
|
|
20745
|
-
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
20746
|
-
}
|
|
20747
|
-
function DialogFooter({
|
|
20748
|
-
className,
|
|
20749
|
-
...props
|
|
20750
|
-
}) {
|
|
20751
|
-
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20752
|
-
"div",
|
|
20753
|
-
{
|
|
20754
|
-
className: cn("flex items-center justify-end gap-2", className),
|
|
20755
|
-
...props
|
|
20756
|
-
}
|
|
20757
|
-
);
|
|
20758
|
-
}
|
|
20759
|
-
var DialogTitle = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20760
|
-
import_radix_ui6.Dialog.Title,
|
|
20761
|
-
{
|
|
20762
|
-
ref,
|
|
20763
|
-
className: cn(
|
|
20764
|
-
"text-lg font-semibold leading-none tracking-tight text-card-foreground",
|
|
20765
|
-
className
|
|
20766
|
-
),
|
|
20767
|
-
...props
|
|
20768
|
-
}
|
|
20769
|
-
));
|
|
20770
|
-
DialogTitle.displayName = import_radix_ui6.Dialog.Title.displayName;
|
|
20771
|
-
var DialogDescription = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20772
|
-
import_radix_ui6.Dialog.Description,
|
|
20773
|
-
{
|
|
20774
|
-
ref,
|
|
20775
|
-
className: cn("text-sm text-muted-foreground", className),
|
|
20776
|
-
...props
|
|
20777
|
-
}
|
|
20778
|
-
));
|
|
20779
|
-
DialogDescription.displayName = import_radix_ui6.Dialog.Description.displayName;
|
|
20780
|
-
var DialogClose = import_radix_ui6.Dialog.Close;
|
|
20781
|
-
|
|
20782
20855
|
// src/ui/link-modal/LinkEditorPanel.tsx
|
|
20783
20856
|
var import_lucide_react16 = require("lucide-react");
|
|
20784
20857
|
|
|
@@ -21882,6 +21955,7 @@ function shouldUseDevFixtures() {
|
|
|
21882
21955
|
function getLogoElement(el) {
|
|
21883
21956
|
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
21884
21957
|
if (marked) return marked;
|
|
21958
|
+
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
21885
21959
|
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
21886
21960
|
if (!root) return null;
|
|
21887
21961
|
const anchor = el.closest("a");
|
|
@@ -24462,7 +24536,7 @@ function getNavigationSelectionParent(el) {
|
|
|
24462
24536
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
24463
24537
|
return resolveFooterLinksContainerFrom(el);
|
|
24464
24538
|
}
|
|
24465
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
|
|
24539
|
+
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)) {
|
|
24466
24540
|
return getNavigationRoot(el);
|
|
24467
24541
|
}
|
|
24468
24542
|
return null;
|
|
@@ -24684,7 +24758,6 @@ var ICONS = {
|
|
|
24684
24758
|
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"/>',
|
|
24685
24759
|
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"/>'
|
|
24686
24760
|
};
|
|
24687
|
-
var HEIGHT_SETTLE_DELAYS = [150, 400, 800];
|
|
24688
24761
|
var SELECTION_CHROME_GAP2 = 4;
|
|
24689
24762
|
var TOOLBAR_STROKE_GAP2 = 4;
|
|
24690
24763
|
var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
|
|
@@ -24782,7 +24855,7 @@ function applyVisibleViewport(el, parentScroll) {
|
|
|
24782
24855
|
el.style.top = `${top}px`;
|
|
24783
24856
|
el.style.height = `${height}px`;
|
|
24784
24857
|
}
|
|
24785
|
-
var
|
|
24858
|
+
var TOOLBAR_EDGE_MARGIN4 = 4;
|
|
24786
24859
|
function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
24787
24860
|
const isAbove = transform.includes("translateY(-100%)");
|
|
24788
24861
|
let visualTop = isAbove ? top - approxH : top;
|
|
@@ -24809,8 +24882,8 @@ function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
|
24809
24882
|
function clampToolbarLeft(centerX, toolbarWidth) {
|
|
24810
24883
|
const half = toolbarWidth / 2;
|
|
24811
24884
|
return Math.max(
|
|
24812
|
-
|
|
24813
|
-
Math.min(centerX, window.innerWidth -
|
|
24885
|
+
TOOLBAR_EDGE_MARGIN4 + half,
|
|
24886
|
+
Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN4 - half)
|
|
24814
24887
|
);
|
|
24815
24888
|
}
|
|
24816
24889
|
function calcToolbarPos(rect, parentScroll, toolbarW = 306) {
|
|
@@ -25700,21 +25773,6 @@ function OhhwellsBridge() {
|
|
|
25700
25773
|
const [isItemDragging, setIsItemDragging] = (0, import_react21.useState)(false);
|
|
25701
25774
|
const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react21.useState)(false);
|
|
25702
25775
|
isFooterFrameSelectionRef.current = isFooterFrameSelection;
|
|
25703
|
-
const [floatingPanel, setFloatingPanel] = (0, import_react21.useState)(null);
|
|
25704
|
-
const floatingPanelOpenRef = (0, import_react21.useRef)(false);
|
|
25705
|
-
floatingPanelOpenRef.current = floatingPanel !== null;
|
|
25706
|
-
const floatingPanelRef = (0, import_react21.useRef)(null);
|
|
25707
|
-
floatingPanelRef.current = floatingPanel;
|
|
25708
|
-
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react21.useState)(null);
|
|
25709
|
-
const buttonCollectionDragRef = (0, import_react21.useRef)(null);
|
|
25710
|
-
const buttonDropInsertIndexRef = (0, import_react21.useRef)(null);
|
|
25711
|
-
const [buttonDropSlots, setButtonDropSlots] = (0, import_react21.useState)([]);
|
|
25712
|
-
const [activeButtonDropIndex, setActiveButtonDropIndex] = (0, import_react21.useState)(null);
|
|
25713
|
-
const buttonPointerDragRef = (0, import_react21.useRef)(null);
|
|
25714
|
-
const [buttonStyleTick, setButtonStyleTick] = (0, import_react21.useState)(0);
|
|
25715
|
-
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react21.useState)(null);
|
|
25716
|
-
const [editorViewport, setEditorViewport] = (0, import_react21.useState)("desktop");
|
|
25717
|
-
const [parentScrollSnap, setParentScrollSnap] = (0, import_react21.useState)(null);
|
|
25718
25776
|
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react21.useState)(null);
|
|
25719
25777
|
const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react21.useState)(null);
|
|
25720
25778
|
const footerDragRef = (0, import_react21.useRef)(null);
|
|
@@ -25740,6 +25798,21 @@ function OhhwellsBridge() {
|
|
|
25740
25798
|
const stylesRef = (0, import_react21.useRef)("");
|
|
25741
25799
|
const appliedDrawerRef = (0, import_react21.useRef)(null);
|
|
25742
25800
|
const pendingDeleteUndoRef = (0, import_react21.useRef)(null);
|
|
25801
|
+
const [floatingPanel, setFloatingPanel] = (0, import_react21.useState)(null);
|
|
25802
|
+
const floatingPanelOpenRef = (0, import_react21.useRef)(false);
|
|
25803
|
+
const floatingPanelRef = (0, import_react21.useRef)(null);
|
|
25804
|
+
floatingPanelRef.current = floatingPanel;
|
|
25805
|
+
const setFloatingPanelRef = (0, import_react21.useRef)(setFloatingPanel);
|
|
25806
|
+
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react21.useState)(null);
|
|
25807
|
+
const buttonCollectionDragRef = (0, import_react21.useRef)(null);
|
|
25808
|
+
const buttonDropInsertIndexRef = (0, import_react21.useRef)(null);
|
|
25809
|
+
const [buttonDropSlots, setButtonDropSlots] = (0, import_react21.useState)([]);
|
|
25810
|
+
const [activeButtonDropIndex, setActiveButtonDropIndex] = (0, import_react21.useState)(null);
|
|
25811
|
+
const buttonPointerDragRef = (0, import_react21.useRef)(null);
|
|
25812
|
+
const [buttonStyleTick, setButtonStyleTick] = (0, import_react21.useState)(0);
|
|
25813
|
+
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react21.useState)(null);
|
|
25814
|
+
const [editorViewport, setEditorViewport] = (0, import_react21.useState)("desktop");
|
|
25815
|
+
const [parentScrollSnap, setParentScrollSnap] = (0, import_react21.useState)(null);
|
|
25743
25816
|
const [sitePages, setSitePages] = (0, import_react21.useState)([]);
|
|
25744
25817
|
const [sectionsByPath, setSectionsByPath] = (0, import_react21.useState)({});
|
|
25745
25818
|
const sectionsPrefetchGenRef = (0, import_react21.useRef)(0);
|
|
@@ -25748,7 +25821,18 @@ function OhhwellsBridge() {
|
|
|
25748
25821
|
const linkPopoverOpenRef = (0, import_react21.useRef)(false);
|
|
25749
25822
|
const linkPopoverGraceUntilRef = (0, import_react21.useRef)(0);
|
|
25750
25823
|
setLinkPopoverRef.current = setLinkPopover;
|
|
25824
|
+
setFloatingPanelRef.current = setFloatingPanel;
|
|
25751
25825
|
linkPopoverSessionRef.current = linkPopover;
|
|
25826
|
+
floatingPanelOpenRef.current = Boolean(floatingPanel);
|
|
25827
|
+
(0, import_react21.useEffect)(() => {
|
|
25828
|
+
const syncViewport = () => {
|
|
25829
|
+
const next = window.innerWidth <= 480 ? "mobile" : "desktop";
|
|
25830
|
+
setEditorViewport((prev) => prev === next ? prev : next);
|
|
25831
|
+
};
|
|
25832
|
+
syncViewport();
|
|
25833
|
+
window.addEventListener("resize", syncViewport);
|
|
25834
|
+
return () => window.removeEventListener("resize", syncViewport);
|
|
25835
|
+
}, []);
|
|
25752
25836
|
(0, import_react21.useEffect)(() => {
|
|
25753
25837
|
setSectionOrderPersistHandler((entries) => {
|
|
25754
25838
|
const currentPath = window.location.pathname;
|
|
@@ -27443,6 +27527,7 @@ function OhhwellsBridge() {
|
|
|
27443
27527
|
applyAiFooterFromContent(content);
|
|
27444
27528
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
27445
27529
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
27530
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
27446
27531
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
27447
27532
|
}
|
|
27448
27533
|
applyBrandChrome(content);
|
|
@@ -27453,12 +27538,12 @@ function OhhwellsBridge() {
|
|
|
27453
27538
|
if (key === "__ohw_sections") continue;
|
|
27454
27539
|
if (key === AI_SECTIONS_KEY) continue;
|
|
27455
27540
|
if (key === AI_FOOTER_KEY) continue;
|
|
27541
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
27542
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27456
27543
|
if (key === BRAND_KIT_KEY) continue;
|
|
27457
27544
|
if (key === STYLE_STORE_KEY) continue;
|
|
27458
27545
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
27459
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
27460
27546
|
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
27461
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27462
27547
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
27463
27548
|
continue;
|
|
27464
27549
|
}
|
|
@@ -27673,17 +27758,18 @@ function OhhwellsBridge() {
|
|
|
27673
27758
|
}
|
|
27674
27759
|
applyAiFooterFromContent(content);
|
|
27675
27760
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
27761
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
27676
27762
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
27677
27763
|
}
|
|
27678
27764
|
for (const [key, val] of Object.entries(content)) {
|
|
27679
27765
|
if (key === "__ohw_sections") continue;
|
|
27680
27766
|
if (key === AI_SECTIONS_KEY) continue;
|
|
27681
27767
|
if (key === AI_FOOTER_KEY) continue;
|
|
27768
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
27769
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27682
27770
|
if (key === BRAND_KIT_KEY) continue;
|
|
27683
27771
|
if (key === STYLE_STORE_KEY) continue;
|
|
27684
27772
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
27685
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
27686
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27687
27773
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
27688
27774
|
continue;
|
|
27689
27775
|
}
|
|
@@ -27940,26 +28026,11 @@ function OhhwellsBridge() {
|
|
|
27940
28026
|
const t2 = setTimeout(measure, 500);
|
|
27941
28027
|
const ro = new ResizeObserver(schedule);
|
|
27942
28028
|
ro.observe(document.body);
|
|
27943
|
-
let lastWidth = window.innerWidth;
|
|
27944
|
-
let resizeTimers = [];
|
|
27945
|
-
const clearResizeTimers = () => {
|
|
27946
|
-
resizeTimers.forEach(clearTimeout);
|
|
27947
|
-
resizeTimers = [];
|
|
27948
|
-
};
|
|
27949
|
-
const handleResize = () => {
|
|
27950
|
-
if (window.innerWidth === lastWidth) return;
|
|
27951
|
-
lastWidth = window.innerWidth;
|
|
27952
|
-
clearResizeTimers();
|
|
27953
|
-
resizeTimers = HEIGHT_SETTLE_DELAYS.map((delay) => setTimeout(measure, delay));
|
|
27954
|
-
};
|
|
27955
|
-
window.addEventListener("resize", handleResize);
|
|
27956
28029
|
return () => {
|
|
27957
28030
|
clearTimeout(t1);
|
|
27958
28031
|
clearTimeout(t2);
|
|
27959
28032
|
if (raf != null) cancelAnimationFrame(raf);
|
|
27960
28033
|
ro.disconnect();
|
|
27961
|
-
clearResizeTimers();
|
|
27962
|
-
window.removeEventListener("resize", handleResize);
|
|
27963
28034
|
};
|
|
27964
28035
|
}, [pathname, isEditMode, postToParent2]);
|
|
27965
28036
|
(0, import_react21.useEffect)(() => {
|
|
@@ -28258,6 +28329,13 @@ function OhhwellsBridge() {
|
|
|
28258
28329
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
28259
28330
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
28260
28331
|
if (isInsideLinkEditor(target)) return;
|
|
28332
|
+
if (isInsideFloatingPanel(target)) return;
|
|
28333
|
+
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
28334
|
+
if (target.closest(
|
|
28335
|
+
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
28336
|
+
)) {
|
|
28337
|
+
return;
|
|
28338
|
+
}
|
|
28261
28339
|
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
28262
28340
|
clearMediaSelectionRef.current();
|
|
28263
28341
|
}
|
|
@@ -28281,13 +28359,6 @@ function OhhwellsBridge() {
|
|
|
28281
28359
|
return;
|
|
28282
28360
|
}
|
|
28283
28361
|
}
|
|
28284
|
-
if (isInsideFloatingPanel(target)) return;
|
|
28285
|
-
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
28286
|
-
if (target.closest(
|
|
28287
|
-
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
28288
|
-
)) {
|
|
28289
|
-
return;
|
|
28290
|
-
}
|
|
28291
28362
|
{
|
|
28292
28363
|
const formEl = getFormElement(target);
|
|
28293
28364
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
@@ -28441,9 +28512,13 @@ function OhhwellsBridge() {
|
|
|
28441
28512
|
if (isIconEditable(editable) && !getSocialItem(editable)) {
|
|
28442
28513
|
e.preventDefault();
|
|
28443
28514
|
e.stopPropagation();
|
|
28444
|
-
selectIconElementRef.current(editable);
|
|
28445
28515
|
const aiIcon = editable.hasAttribute("data-ai-icon");
|
|
28446
28516
|
const featureIcon = aiIcon && /\.features\.\d+\.icon$/.test(editable.dataset.ohwKey ?? "");
|
|
28517
|
+
if (aiIcon) {
|
|
28518
|
+
aiSectionApiRef.current?.selectFromElement(editable);
|
|
28519
|
+
} else {
|
|
28520
|
+
selectIconElementRef.current(editable);
|
|
28521
|
+
}
|
|
28447
28522
|
postToParentRef.current({
|
|
28448
28523
|
type: "ow:icon-pick",
|
|
28449
28524
|
key: editable.dataset.ohwKey ?? "",
|
|
@@ -28671,6 +28746,9 @@ function OhhwellsBridge() {
|
|
|
28671
28746
|
setHoveredItemRect(null);
|
|
28672
28747
|
hoveredNavContainerRef.current = null;
|
|
28673
28748
|
setHoveredNavContainerRect(null);
|
|
28749
|
+
siblingHintElRef.current = null;
|
|
28750
|
+
setSiblingHintRect(null);
|
|
28751
|
+
setSiblingHintRects([]);
|
|
28674
28752
|
return;
|
|
28675
28753
|
}
|
|
28676
28754
|
{
|
|
@@ -28791,7 +28869,6 @@ function OhhwellsBridge() {
|
|
|
28791
28869
|
hoveredNavContainerRef.current = null;
|
|
28792
28870
|
setHoveredNavContainerRect(null);
|
|
28793
28871
|
hoveredItemElRef.current = editable;
|
|
28794
|
-
setHoveredItemRect(isSelectedForHoverRef.current(editable) ? null : editable.getBoundingClientRect());
|
|
28795
28872
|
}
|
|
28796
28873
|
}
|
|
28797
28874
|
}
|
|
@@ -29501,7 +29578,11 @@ function OhhwellsBridge() {
|
|
|
29501
29578
|
};
|
|
29502
29579
|
const handleMouseMove = (e) => {
|
|
29503
29580
|
const { clientX, clientY } = e;
|
|
29504
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
29581
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
29582
|
+
dismissImageHover();
|
|
29583
|
+
clearImageHover();
|
|
29584
|
+
return;
|
|
29585
|
+
}
|
|
29505
29586
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) {
|
|
29506
29587
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
29507
29588
|
formHoverElRef.current = null;
|
|
@@ -29530,7 +29611,12 @@ function OhhwellsBridge() {
|
|
|
29530
29611
|
setHoveredItemRect(null);
|
|
29531
29612
|
hoveredNavContainerRef.current = null;
|
|
29532
29613
|
setHoveredNavContainerRect(null);
|
|
29614
|
+
siblingHintElRef.current = null;
|
|
29615
|
+
setSiblingHintRect(null);
|
|
29616
|
+
setSiblingHintRects([]);
|
|
29533
29617
|
dismissImageHover();
|
|
29618
|
+
clearImageHover();
|
|
29619
|
+
setSectionGap(null);
|
|
29534
29620
|
return;
|
|
29535
29621
|
}
|
|
29536
29622
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
@@ -29542,7 +29628,11 @@ function OhhwellsBridge() {
|
|
|
29542
29628
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
29543
29629
|
const { clientX, clientY } = e.data;
|
|
29544
29630
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
29545
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
29631
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
29632
|
+
dismissImageHover();
|
|
29633
|
+
clearImageHover();
|
|
29634
|
+
return;
|
|
29635
|
+
}
|
|
29546
29636
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) return;
|
|
29547
29637
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
29548
29638
|
probeSectionGapAt(clientX, clientY);
|
|
@@ -29922,6 +30012,7 @@ function OhhwellsBridge() {
|
|
|
29922
30012
|
applyAiFooterFromContent(content);
|
|
29923
30013
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
29924
30014
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
30015
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
29925
30016
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
29926
30017
|
}
|
|
29927
30018
|
applyBrandChrome(content);
|
|
@@ -29936,12 +30027,12 @@ function OhhwellsBridge() {
|
|
|
29936
30027
|
}
|
|
29937
30028
|
if (key === AI_SECTIONS_KEY) continue;
|
|
29938
30029
|
if (key === AI_FOOTER_KEY) continue;
|
|
30030
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
30031
|
+
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
29939
30032
|
if (key === BRAND_KIT_KEY) continue;
|
|
29940
30033
|
if (key === STYLE_STORE_KEY) continue;
|
|
29941
30034
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
29942
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
29943
30035
|
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
29944
|
-
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
29945
30036
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
29946
30037
|
continue;
|
|
29947
30038
|
}
|
|
@@ -30316,6 +30407,44 @@ function OhhwellsBridge() {
|
|
|
30316
30407
|
});
|
|
30317
30408
|
};
|
|
30318
30409
|
window.addEventListener("message", handleAiSetStyles);
|
|
30410
|
+
const handleAiSetButtonStyle = (e) => {
|
|
30411
|
+
if (e.data?.type !== "ow:ai-set-button-style") return;
|
|
30412
|
+
const nodeKey = typeof e.data.hrefKey === "string" ? e.data.hrefKey : "";
|
|
30413
|
+
const keyed = nodeKey ? document.querySelector(
|
|
30414
|
+
`[data-ohw-href-key="${CSS.escape(nodeKey)}"], [data-ohw-key="${CSS.escape(nodeKey)}"]`
|
|
30415
|
+
) : null;
|
|
30416
|
+
const hrefKey = buttonId(keyed);
|
|
30417
|
+
const el = hrefKey ? document.querySelector(`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`) : null;
|
|
30418
|
+
const previous = editContentRef.current[BUTTON_ASSIGNMENTS_KEY] ?? "";
|
|
30419
|
+
if (!el || !hrefKey || !isCtaButton(el)) {
|
|
30420
|
+
postToParentRef.current({ type: "ow:ai-button-style-applied", ok: false, previous, value: previous });
|
|
30421
|
+
return;
|
|
30422
|
+
}
|
|
30423
|
+
const tokens = tokensFromButton(el);
|
|
30424
|
+
const current = assignmentFor(el, editContentRef.current, tokens);
|
|
30425
|
+
const patch = e.data.assignment;
|
|
30426
|
+
const next = {
|
|
30427
|
+
variant: patch?.variant ?? current.variant,
|
|
30428
|
+
size: patch?.size ?? current.size
|
|
30429
|
+
};
|
|
30430
|
+
const value = typeof e.data.assignments === "string" ? e.data.assignments : JSON.stringify(withAssignment(editContentRef.current, hrefKey, next));
|
|
30431
|
+
editContentRef.current = { ...editContentRef.current, [BUTTON_ASSIGNMENTS_KEY]: value };
|
|
30432
|
+
applyButtonStyle(el, next, tokens);
|
|
30433
|
+
postToParentRef.current({
|
|
30434
|
+
type: "ow:change",
|
|
30435
|
+
nodes: [{ key: BUTTON_ASSIGNMENTS_KEY, text: value }]
|
|
30436
|
+
});
|
|
30437
|
+
postToParentRef.current({
|
|
30438
|
+
type: "ow:ai-button-style-applied",
|
|
30439
|
+
ok: true,
|
|
30440
|
+
// The resolved id, which may differ from the key the editor sent — undo must target this one.
|
|
30441
|
+
hrefKey,
|
|
30442
|
+
previous,
|
|
30443
|
+
previousAssignment: current,
|
|
30444
|
+
value
|
|
30445
|
+
});
|
|
30446
|
+
};
|
|
30447
|
+
window.addEventListener("message", handleAiSetButtonStyle);
|
|
30319
30448
|
const handleGetBrand = (e) => {
|
|
30320
30449
|
if (e.data?.type !== "ow:get-brand") return;
|
|
30321
30450
|
const template = deriveTemplateBrand();
|
|
@@ -30539,6 +30668,12 @@ function OhhwellsBridge() {
|
|
|
30539
30668
|
closeLinkPopoverRef.current();
|
|
30540
30669
|
return;
|
|
30541
30670
|
}
|
|
30671
|
+
if (floatingPanelOpenRef.current) {
|
|
30672
|
+
setFloatingPanelRef.current(null);
|
|
30673
|
+
deselectRef.current();
|
|
30674
|
+
deactivateRef.current();
|
|
30675
|
+
return;
|
|
30676
|
+
}
|
|
30542
30677
|
deselectRef.current();
|
|
30543
30678
|
deactivateRef.current();
|
|
30544
30679
|
clearMediaSelectionRef.current();
|
|
@@ -31349,6 +31484,7 @@ function OhhwellsBridge() {
|
|
|
31349
31484
|
window.removeEventListener("message", handleAiSetSections);
|
|
31350
31485
|
window.removeEventListener("message", handleAiSetBrand);
|
|
31351
31486
|
window.removeEventListener("message", handleAiSetStyles);
|
|
31487
|
+
window.removeEventListener("message", handleAiSetButtonStyle);
|
|
31352
31488
|
window.removeEventListener("message", handleCollectItems);
|
|
31353
31489
|
window.removeEventListener("message", handleAiApplyItems);
|
|
31354
31490
|
window.removeEventListener("message", handleGetBrand);
|
|
@@ -31360,10 +31496,10 @@ function OhhwellsBridge() {
|
|
|
31360
31496
|
window.removeEventListener("message", handleDeleteSection);
|
|
31361
31497
|
window.removeEventListener("message", handleDuplicateSection);
|
|
31362
31498
|
window.removeEventListener("message", handleDeactivate);
|
|
31363
|
-
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
31364
31499
|
window.removeEventListener("message", handleToastAction);
|
|
31365
31500
|
window.removeEventListener("message", handleFormCount);
|
|
31366
31501
|
window.removeEventListener("message", handleUiEscape);
|
|
31502
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
31367
31503
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
31368
31504
|
autoSaveTimers.current.clear();
|
|
31369
31505
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
@@ -31657,7 +31793,7 @@ function OhhwellsBridge() {
|
|
|
31657
31793
|
postToParent2({
|
|
31658
31794
|
type: "ow:ready",
|
|
31659
31795
|
version: "1",
|
|
31660
|
-
bridgeVersion: "0.1.
|
|
31796
|
+
bridgeVersion: "0.1.149-next.402",
|
|
31661
31797
|
path: pathname,
|
|
31662
31798
|
nodes: collectEditableNodes(editContentRef.current),
|
|
31663
31799
|
sections
|