@ohhwells/bridge 0.1.147 → 0.1.149-next.400
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 +874 -731
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +914 -755
- 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.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
// src/OhhwellsBridge.tsx
|
|
4
|
-
import React12, { useCallback as useCallback12, useEffect as useEffect17, useLayoutEffect as
|
|
4
|
+
import React12, { useCallback as useCallback12, useEffect as useEffect17, useLayoutEffect as useLayoutEffect7, useRef as useRef14, useState as useState18 } from "react";
|
|
5
5
|
import { createRoot as createRoot3 } from "react-dom/client";
|
|
6
6
|
import { flushSync as flushSync3 } from "react-dom";
|
|
7
7
|
|
|
@@ -1476,7 +1476,19 @@ function brandTrackedFontFamily(doc, stack) {
|
|
|
1476
1476
|
}
|
|
1477
1477
|
var paintLockByEl = /* @__PURE__ */ new WeakMap();
|
|
1478
1478
|
var paintObserverByEl = /* @__PURE__ */ new WeakMap();
|
|
1479
|
-
var
|
|
1479
|
+
var PAINT_GUARD_ATTRS = {
|
|
1480
|
+
attributes: true,
|
|
1481
|
+
attributeFilter: ["style", "class"]
|
|
1482
|
+
};
|
|
1483
|
+
function paintGuarded(el, assignment, tokens) {
|
|
1484
|
+
const observer = paintObserverByEl.get(el);
|
|
1485
|
+
observer?.disconnect();
|
|
1486
|
+
try {
|
|
1487
|
+
paintButtonChrome(el, assignment, tokens);
|
|
1488
|
+
} finally {
|
|
1489
|
+
observer?.observe(el, PAINT_GUARD_ATTRS);
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1480
1492
|
function paintButtonChrome(el, assignment, tokens) {
|
|
1481
1493
|
const origin = captureButtonOrigin(el);
|
|
1482
1494
|
const chrome = tokens.variants[assignment.variant];
|
|
@@ -1515,14 +1527,11 @@ function paintButtonChrome(el, assignment, tokens) {
|
|
|
1515
1527
|
function guardTemplateHover(el) {
|
|
1516
1528
|
if (paintObserverByEl.has(el)) return;
|
|
1517
1529
|
const observer = new MutationObserver(() => {
|
|
1518
|
-
if (paintingButton) return;
|
|
1519
1530
|
const lock = paintLockByEl.get(el);
|
|
1520
1531
|
if (!lock) return;
|
|
1521
|
-
|
|
1522
|
-
paintButtonChrome(el, lock.assignment, lock.tokens);
|
|
1523
|
-
paintingButton = false;
|
|
1532
|
+
paintGuarded(el, lock.assignment, lock.tokens);
|
|
1524
1533
|
});
|
|
1525
|
-
observer.observe(el,
|
|
1534
|
+
observer.observe(el, PAINT_GUARD_ATTRS);
|
|
1526
1535
|
paintObserverByEl.set(el, observer);
|
|
1527
1536
|
}
|
|
1528
1537
|
function paintedTokensOf(el) {
|
|
@@ -1539,10 +1548,8 @@ function applyButtonStyle(el, assignment, tokens) {
|
|
|
1539
1548
|
}
|
|
1540
1549
|
};
|
|
1541
1550
|
paintLockByEl.set(el, { assignment, tokens: tracked });
|
|
1542
|
-
paintingButton = true;
|
|
1543
|
-
paintButtonChrome(el, assignment, tracked);
|
|
1544
|
-
paintingButton = false;
|
|
1545
1551
|
guardTemplateHover(el);
|
|
1552
|
+
paintGuarded(el, assignment, tracked);
|
|
1546
1553
|
}
|
|
1547
1554
|
function applyButtonStylesFromContent(doc, content) {
|
|
1548
1555
|
const assignments = readAssignments(content);
|
|
@@ -1624,7 +1631,8 @@ function labelElement2(el) {
|
|
|
1624
1631
|
return el.querySelector('[data-ohw-editable="text"], [data-ohw-editable="plain"]') ?? el.querySelector("[data-ohw-key]");
|
|
1625
1632
|
}
|
|
1626
1633
|
function buttonLabel(el) {
|
|
1627
|
-
|
|
1634
|
+
const label = labelElement2(el);
|
|
1635
|
+
return (label ? label.innerHTML : el.textContent ?? "").trim();
|
|
1628
1636
|
}
|
|
1629
1637
|
function buttonHref(el) {
|
|
1630
1638
|
return el.getAttribute("href") ?? "";
|
|
@@ -1763,7 +1771,7 @@ function duplicateButton(source, content) {
|
|
|
1763
1771
|
stampVariantClass(copy, copyAssignment.variant);
|
|
1764
1772
|
applyButtonStyle(copy, copyAssignment, paintedTokensOf(source) ?? tokens);
|
|
1765
1773
|
const copyLabelEl = labelElement2(copy);
|
|
1766
|
-
if (copyLabelEl) copyLabelEl.
|
|
1774
|
+
if (copyLabelEl) copyLabelEl.innerHTML = label;
|
|
1767
1775
|
let collection = buttonCollectionOf(source);
|
|
1768
1776
|
const collections = readCollections(content);
|
|
1769
1777
|
let collectionId = collection?.getAttribute(COLLECTION_ATTR) ?? "";
|
|
@@ -2089,7 +2097,7 @@ function applySnapshotContent(el, snapshot, content) {
|
|
|
2089
2097
|
const label = labelElement2(el);
|
|
2090
2098
|
if (label) {
|
|
2091
2099
|
if (label.getAttribute("data-ohw-key") !== labelKey) label.setAttribute("data-ohw-key", labelKey);
|
|
2092
|
-
if (label.
|
|
2100
|
+
if (label.innerHTML !== text) label.innerHTML = text;
|
|
2093
2101
|
}
|
|
2094
2102
|
}
|
|
2095
2103
|
function reconcileButtonCollections(doc, content) {
|
|
@@ -4174,7 +4182,7 @@ function buildNavLink(index, href, label, template) {
|
|
|
4174
4182
|
const span = document.createElement("span");
|
|
4175
4183
|
span.setAttribute("data-ohw-editable", "text");
|
|
4176
4184
|
span.setAttribute("data-ohw-key", `nav-${index}-label`);
|
|
4177
|
-
span.
|
|
4185
|
+
span.innerHTML = label;
|
|
4178
4186
|
anchor.appendChild(span);
|
|
4179
4187
|
return anchor;
|
|
4180
4188
|
}
|
|
@@ -6534,6 +6542,21 @@ function pricingCardFeatureCount(tree, index) {
|
|
|
6534
6542
|
const target = findPricingCollection(tree)?.children?.[index];
|
|
6535
6543
|
return target ? pricingFeatureList(target).length : 0;
|
|
6536
6544
|
}
|
|
6545
|
+
function prevailingFeatureIcon(features) {
|
|
6546
|
+
const counts = /* @__PURE__ */ new Map();
|
|
6547
|
+
for (const row of features) {
|
|
6548
|
+
const key = `${row.icon ?? ""}|${row.iconColor ?? ""}`;
|
|
6549
|
+
const entry = counts.get(key) ?? { count: 0, ...row.icon ? { icon: row.icon } : {}, ...row.iconColor ? { iconColor: row.iconColor } : {} };
|
|
6550
|
+
entry.count += 1;
|
|
6551
|
+
counts.set(key, entry);
|
|
6552
|
+
}
|
|
6553
|
+
let best = null;
|
|
6554
|
+
for (const entry of counts.values()) {
|
|
6555
|
+
if (!best || entry.count > best.count) best = entry;
|
|
6556
|
+
}
|
|
6557
|
+
if (!best) return {};
|
|
6558
|
+
return { ...best.icon ? { icon: best.icon } : {}, ...best.iconColor ? { iconColor: best.iconColor } : {} };
|
|
6559
|
+
}
|
|
6537
6560
|
function addPricingCardFeature(tree, index, text) {
|
|
6538
6561
|
return withPricingCollection(tree, (collection) => {
|
|
6539
6562
|
const children = collection.children;
|
|
@@ -6542,7 +6565,7 @@ function addPricingCardFeature(tree, index, text) {
|
|
|
6542
6565
|
const features = pricingFeatureList(target);
|
|
6543
6566
|
if (features.length >= PRICING_FEATURES_MAX) return false;
|
|
6544
6567
|
target.slots = target.slots ?? {};
|
|
6545
|
-
target.slots.features = [...features, { text }];
|
|
6568
|
+
target.slots.features = [...features, { text, ...prevailingFeatureIcon(features) }];
|
|
6546
6569
|
return true;
|
|
6547
6570
|
});
|
|
6548
6571
|
}
|
|
@@ -7725,7 +7748,7 @@ var AI_MOBILE_CSS = [
|
|
|
7725
7748
|
// page's first section. Top only (bottom needs no nav clearance); ~96px approximates the
|
|
7726
7749
|
// template nav's own height (measured ~94px) — there's no shared `--ohw-header-h` var to read
|
|
7727
7750
|
// an exact figure from (no live measurement exists), so this is a safe approximation, not a
|
|
7728
|
-
// pixel-exact fit. Horizontal spacing already comes from `data-ai-
|
|
7751
|
+
// pixel-exact fit. Horizontal spacing already comes from `data-ai-section-inner`.
|
|
7729
7752
|
'[data-ai-overlay-clearance] [data-ai-overlap-layer="overlay"]{padding-top:96px}',
|
|
7730
7753
|
// A full-bleed carousel's height is pure arithmetic: it spans the whole window, so 16/9 turns
|
|
7731
7754
|
// window width straight into height. Measured at 16/9 it came out ~90% of the viewport at EVERY
|
|
@@ -7741,8 +7764,10 @@ var AI_MOBILE_CSS = [
|
|
|
7741
7764
|
"[data-ai-section]{overflow-x:hidden}",
|
|
7742
7765
|
// `:not([data-ai-full-bleed])`: this `!important` gutter beat the inline `padding: 0` that a
|
|
7743
7766
|
// full-bleed section's container sets, so a carousel/media hero that is edge-to-edge on desktop
|
|
7744
|
-
// still got a 20px band of section background down both sides on a phone.
|
|
7745
|
-
|
|
7767
|
+
// still got a 20px band of section background down both sides on a phone. The footer's own
|
|
7768
|
+
// container keeps the unguarded rule below — `data-ai-full-bleed` can never appear on it.
|
|
7769
|
+
"[data-ai-section-inner]:not([data-ai-full-bleed]){padding:0 20px !important}",
|
|
7770
|
+
"[data-ai-container]{padding:0 20px !important}",
|
|
7746
7771
|
"[data-ai-row]{display:flex !important;flex-direction:column !important;align-items:stretch !important}",
|
|
7747
7772
|
"[data-ai-cell]{width:100%;min-width:0}",
|
|
7748
7773
|
// The rule above turns every row into a COLUMN flex container on phones, which silently breaks
|
|
@@ -7947,6 +7972,31 @@ function pricingCardEmphasis(featured, ctx, hasBg) {
|
|
|
7947
7972
|
function textAttrs(ctx, path) {
|
|
7948
7973
|
return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
|
|
7949
7974
|
}
|
|
7975
|
+
var AI_RESPONSIVE_CSS = [
|
|
7976
|
+
"@media (max-width: 960px) {",
|
|
7977
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: repeat(2, 1fr) !important; }",
|
|
7978
|
+
' [data-ai-responsive] [data-ai-grid="1"] { grid-template-columns: 1fr !important; }',
|
|
7979
|
+
"}",
|
|
7980
|
+
"@media (max-width: 640px) {",
|
|
7981
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
|
|
7982
|
+
" [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
|
|
7983
|
+
// Group containers flatten to a column on phones; span placements come along for free.
|
|
7984
|
+
// `:not([data-ai-group="overlap"])` for the same reason as the twin pair in AI_MOBILE_CSS — see
|
|
7985
|
+
// the comment there. This sheet's copy is the narrower selector, so without the exemption it
|
|
7986
|
+
// flattens an `overlap` hero below 640px even though the other rule stands down: measured a 390px
|
|
7987
|
+
// viewport with the heading/CTA in flow *under* the image, 219px of section background where the
|
|
7988
|
+
// layered text used to be.
|
|
7989
|
+
' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) { display: flex !important; flex-direction: column !important; }',
|
|
7990
|
+
' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) > * { grid-column: auto !important; }',
|
|
7991
|
+
// `:not([data-ai-full-bleed])` for the same reason as the twin rule in AI_MOBILE_CSS: this one
|
|
7992
|
+
// is narrower (0,2,0 vs 0,1,0) and also `!important`, so without the guard it wins outright and
|
|
7993
|
+
// a full-bleed hero gets its 20px side band back below 640px only — the one width where the
|
|
7994
|
+
// other rule had already been taught to stand down.
|
|
7995
|
+
" [data-ai-responsive] [data-ai-section-inner]:not([data-ai-full-bleed]) { padding-left: 20px !important; padding-right: 20px !important; }",
|
|
7996
|
+
" [data-ai-responsive] { overflow-x: hidden; }",
|
|
7997
|
+
" [data-ai-responsive] img { max-width: 100%; }",
|
|
7998
|
+
"}"
|
|
7999
|
+
].join("\n");
|
|
7950
8000
|
var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
7951
8001
|
function MediaBox({
|
|
7952
8002
|
refValue,
|
|
@@ -8001,7 +8051,7 @@ function MediaBox({
|
|
|
8001
8051
|
position: fill ? "absolute" : void 0,
|
|
8002
8052
|
inset: fill ? 0 : void 0,
|
|
8003
8053
|
width: fill ? "100%" : fixedSize ? "auto" : "100%",
|
|
8004
|
-
height: fill ? "100%" : void 0,
|
|
8054
|
+
height: fill ? "100%" : fixedSize ? height : void 0,
|
|
8005
8055
|
aspectRatio: fill ? void 0 : aspectRatio,
|
|
8006
8056
|
minHeight: fill || fixedSize ? void 0 : height ?? (aspectRatio ? void 0 : 180),
|
|
8007
8057
|
borderRadius: radius,
|
|
@@ -9497,7 +9547,7 @@ function CollectionBlock({ node, ctx, path }) {
|
|
|
9497
9547
|
return /* @__PURE__ */ jsx(
|
|
9498
9548
|
"div",
|
|
9499
9549
|
{
|
|
9500
|
-
"data-ai-grid":
|
|
9550
|
+
"data-ai-grid": String(itemsPerRow),
|
|
9501
9551
|
"data-ohw-pricing-collection": isPricing ? "" : void 0,
|
|
9502
9552
|
style: {
|
|
9503
9553
|
display: "grid",
|
|
@@ -9799,7 +9849,7 @@ function renderNode(node, ctx, path, ambientAlign) {
|
|
|
9799
9849
|
},
|
|
9800
9850
|
children: [
|
|
9801
9851
|
i > 0 && ctx.heroOverlapFullBleed ? (
|
|
9802
|
-
// The section's `data-ai-
|
|
9852
|
+
// The section's `data-ai-section-inner` gave up its max-width/gutter so the base
|
|
9803
9853
|
// layer (this group's i===0 sibling) can span edge-to-edge — reintroduced here,
|
|
9804
9854
|
// scoped to just the overlay text, so a heading/copy/CTA stack doesn't stretch
|
|
9805
9855
|
// the full section width instead of reading at the usual content width.
|
|
@@ -10218,6 +10268,7 @@ function AiTreeRenderer({
|
|
|
10218
10268
|
...fillHeight ? { "data-ai-fill-height": "" } : {},
|
|
10219
10269
|
...needsOverlayClearance ? { "data-ai-overlay-clearance": "" } : {},
|
|
10220
10270
|
...bgAttrs,
|
|
10271
|
+
"data-ai-responsive": "",
|
|
10221
10272
|
style: {
|
|
10222
10273
|
position: "relative",
|
|
10223
10274
|
padding: `${padCss} 0`,
|
|
@@ -10231,12 +10282,13 @@ function AiTreeRenderer({
|
|
|
10231
10282
|
...fillHeight ? { display: "grid" } : {}
|
|
10232
10283
|
},
|
|
10233
10284
|
children: [
|
|
10234
|
-
|
|
10285
|
+
/* @__PURE__ */ jsx("style", { children: AI_RESPONSIVE_CSS }),
|
|
10235
10286
|
/* @__PURE__ */ jsx("style", { children: AI_MOBILE_CSS }),
|
|
10287
|
+
isOverlay && backgroundUrl && /* @__PURE__ */ jsx("div", { style: { position: "absolute", inset: 0, background: `rgba(255,255,255,${overlayAlpha})` } }),
|
|
10236
10288
|
/* @__PURE__ */ jsx(
|
|
10237
10289
|
"div",
|
|
10238
10290
|
{
|
|
10239
|
-
"data-ai-
|
|
10291
|
+
"data-ai-section-inner": "",
|
|
10240
10292
|
...fullBleedMedia ? { "data-ai-full-bleed": "" } : {},
|
|
10241
10293
|
style: {
|
|
10242
10294
|
position: "relative",
|
|
@@ -10253,7 +10305,7 @@ function AiTreeRenderer({
|
|
|
10253
10305
|
children: tree.rows.map((row, r2) => /* @__PURE__ */ jsx(
|
|
10254
10306
|
"div",
|
|
10255
10307
|
{
|
|
10256
|
-
"data-ai-
|
|
10308
|
+
"data-ai-columns": "",
|
|
10257
10309
|
style: {
|
|
10258
10310
|
display: "grid",
|
|
10259
10311
|
gridTemplateColumns: "repeat(12, 1fr)",
|
|
@@ -10278,7 +10330,12 @@ function AiTreeRenderer({
|
|
|
10278
10330
|
// the full row height instead of clumping at the top.
|
|
10279
10331
|
...distributed === "space-between" ? { display: "flex", flexDirection: "column", justifyContent: "space-between" } : {}
|
|
10280
10332
|
},
|
|
10281
|
-
children: renderNode(
|
|
10333
|
+
children: renderNode(
|
|
10334
|
+
block,
|
|
10335
|
+
ctx,
|
|
10336
|
+
`r${r2}.b${b}`,
|
|
10337
|
+
settings.alignment === "center" ? "center" : "left"
|
|
10338
|
+
)
|
|
10282
10339
|
},
|
|
10283
10340
|
b
|
|
10284
10341
|
))
|
|
@@ -10910,9 +10967,10 @@ function applyAiSectionsToDom(state, options) {
|
|
|
10910
10967
|
if (existing && existing.serialized === serialized && existing.container.isConnected) {
|
|
10911
10968
|
continue;
|
|
10912
10969
|
}
|
|
10913
|
-
const isNewMount = !existing || !existing.container.isConnected;
|
|
10914
10970
|
let container = existing?.container;
|
|
10971
|
+
let isNewMount = false;
|
|
10915
10972
|
if (!container || !container.isConnected) {
|
|
10973
|
+
isNewMount = true;
|
|
10916
10974
|
existing?.root.unmount();
|
|
10917
10975
|
container?.remove();
|
|
10918
10976
|
container = document.createElement("div");
|
|
@@ -17354,6 +17412,7 @@ function MediaOverlay({
|
|
|
17354
17412
|
(prev) => prev && prev.fullWidth === width && prev.height === height ? prev : { fullWidth: width, height }
|
|
17355
17413
|
);
|
|
17356
17414
|
}, [isVideo]);
|
|
17415
|
+
const replaceLabel = isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image";
|
|
17357
17416
|
const replaceMode = buttonSize ? replaceButtonMode({ width: rect.width, height: rect.height }, buttonSize) : "none";
|
|
17358
17417
|
const box = {
|
|
17359
17418
|
position: "fixed",
|
|
@@ -17452,11 +17511,10 @@ function MediaOverlay({
|
|
|
17452
17511
|
className: "flex items-center justify-center cursor-pointer",
|
|
17453
17512
|
style: {
|
|
17454
17513
|
...box,
|
|
17455
|
-
//
|
|
17456
|
-
//
|
|
17457
|
-
//
|
|
17458
|
-
|
|
17459
|
-
pointerEvents: hover.hasTextOverlap || cueOnly ? "none" : "auto",
|
|
17514
|
+
// Visual only. `pointer-events: auto` on this full-bleed rect covered the navbar
|
|
17515
|
+
// (hero bg includes the absolute TopNav) and swallowed CTA press-drag. Text overlay
|
|
17516
|
+
// and cueOnly also need clicks to fall through — Replace / video controls opt back in.
|
|
17517
|
+
pointerEvents: "none",
|
|
17460
17518
|
// Selected: a firm component ring with no wash, so the image reads as chosen rather
|
|
17461
17519
|
// than hovered. Hover keeps the existing tinted preview.
|
|
17462
17520
|
boxShadow: selected ? "inset 0 0 0 2px var(--color-bridge-primary)" : "inset 0 0 0 1.5px var(--color-bridge-primary)",
|
|
@@ -17483,17 +17541,17 @@ function MediaOverlay({
|
|
|
17483
17541
|
},
|
|
17484
17542
|
children: [
|
|
17485
17543
|
isVideo ? /* @__PURE__ */ jsx16(Film, { size: 14 }) : /* @__PURE__ */ jsx16(ImageIcon, { size: 14 }),
|
|
17486
|
-
|
|
17544
|
+
replaceLabel
|
|
17487
17545
|
]
|
|
17488
17546
|
}
|
|
17489
17547
|
),
|
|
17490
|
-
replaceMode
|
|
17548
|
+
showChrome && replaceMode !== "none" && /* @__PURE__ */ jsxs7(
|
|
17491
17549
|
Button,
|
|
17492
17550
|
{
|
|
17493
17551
|
"data-ohw-media-overlay": "",
|
|
17494
17552
|
variant: "outline",
|
|
17495
17553
|
size: "sm",
|
|
17496
|
-
"aria-label":
|
|
17554
|
+
"aria-label": replaceLabel,
|
|
17497
17555
|
className: "gap-1.5 cursor-pointer hover:bg-background",
|
|
17498
17556
|
style: {
|
|
17499
17557
|
...OVERLAY_BUTTON_STYLE,
|
|
@@ -17516,7 +17574,7 @@ function MediaOverlay({
|
|
|
17516
17574
|
},
|
|
17517
17575
|
children: [
|
|
17518
17576
|
isVideo ? /* @__PURE__ */ jsx16(Film, { size: 14 }) : /* @__PURE__ */ jsx16(ImageIcon, { size: 14 }),
|
|
17519
|
-
replaceMode === "full" ?
|
|
17577
|
+
replaceMode === "full" ? replaceLabel : null
|
|
17520
17578
|
]
|
|
17521
17579
|
}
|
|
17522
17580
|
)
|
|
@@ -18025,8 +18083,24 @@ function AiSectionOverlay({
|
|
|
18025
18083
|
}
|
|
18026
18084
|
|
|
18027
18085
|
// src/ui/ai-section/AiMediaStripOverlay.tsx
|
|
18028
|
-
import { useCallback as useCallback3, useEffect as useEffect6, useRef as useRef5, useState as useState8 } from "react";
|
|
18029
|
-
import {
|
|
18086
|
+
import { useCallback as useCallback3, useEffect as useEffect6, useLayoutEffect as useLayoutEffect4, useRef as useRef5, useState as useState8 } from "react";
|
|
18087
|
+
import {
|
|
18088
|
+
AlignCenter,
|
|
18089
|
+
AlignLeft,
|
|
18090
|
+
AlignRight,
|
|
18091
|
+
ArrowLeft as ArrowLeft2,
|
|
18092
|
+
ArrowRight as ArrowRight2,
|
|
18093
|
+
Check as Check2,
|
|
18094
|
+
ChevronDown as ChevronDown3,
|
|
18095
|
+
Image as ImageIcon2,
|
|
18096
|
+
ImageMinus,
|
|
18097
|
+
ImagePlus,
|
|
18098
|
+
Link as LinkIcon,
|
|
18099
|
+
Minus,
|
|
18100
|
+
Palette,
|
|
18101
|
+
Plus as Plus2,
|
|
18102
|
+
Star
|
|
18103
|
+
} from "lucide-react";
|
|
18030
18104
|
|
|
18031
18105
|
// src/lib/ai-media-strip-tree.ts
|
|
18032
18106
|
var MEDIA_STRIP_ITEM_MIN = 1;
|
|
@@ -18140,14 +18214,6 @@ function setMediaStripItemAsset(tree, index, assetId) {
|
|
|
18140
18214
|
return true;
|
|
18141
18215
|
});
|
|
18142
18216
|
}
|
|
18143
|
-
function setMediaStripItemAlt(tree, index, alt) {
|
|
18144
|
-
return withMediaStrip(tree, (block) => {
|
|
18145
|
-
const items = block.items;
|
|
18146
|
-
if (index < 0 || index >= items.length) return false;
|
|
18147
|
-
items[index] = { ...items[index], alt };
|
|
18148
|
-
return true;
|
|
18149
|
-
});
|
|
18150
|
-
}
|
|
18151
18217
|
function setMediaStripItemLink(tree, index, link) {
|
|
18152
18218
|
return withMediaStrip(tree, (block) => {
|
|
18153
18219
|
const items = block.items;
|
|
@@ -18165,11 +18231,117 @@ function setMediaStripItemLink(tree, index, link) {
|
|
|
18165
18231
|
});
|
|
18166
18232
|
}
|
|
18167
18233
|
|
|
18234
|
+
// src/ui/dialog.tsx
|
|
18235
|
+
import * as React9 from "react";
|
|
18236
|
+
import { Dialog as DialogPrimitive } from "radix-ui";
|
|
18237
|
+
import { X as X2 } from "lucide-react";
|
|
18238
|
+
import { jsx as jsx19, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
18239
|
+
function Dialog2({
|
|
18240
|
+
...props
|
|
18241
|
+
}) {
|
|
18242
|
+
return /* @__PURE__ */ jsx19(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
|
|
18243
|
+
}
|
|
18244
|
+
function DialogPortal({
|
|
18245
|
+
...props
|
|
18246
|
+
}) {
|
|
18247
|
+
return /* @__PURE__ */ jsx19(DialogPrimitive.Portal, { ...props });
|
|
18248
|
+
}
|
|
18249
|
+
function DialogOverlay({
|
|
18250
|
+
className,
|
|
18251
|
+
...props
|
|
18252
|
+
}) {
|
|
18253
|
+
return /* @__PURE__ */ jsx19(
|
|
18254
|
+
DialogPrimitive.Overlay,
|
|
18255
|
+
{
|
|
18256
|
+
"data-slot": "dialog-overlay",
|
|
18257
|
+
"data-ohw-link-modal-root": "",
|
|
18258
|
+
className: cn("fixed inset-0 z-[2147483646] bg-black/50", className),
|
|
18259
|
+
...props
|
|
18260
|
+
}
|
|
18261
|
+
);
|
|
18262
|
+
}
|
|
18263
|
+
var DialogContent = React9.forwardRef(
|
|
18264
|
+
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
18265
|
+
const positionMode = container ? "absolute" : "fixed";
|
|
18266
|
+
return /* @__PURE__ */ jsxs10(DialogPortal, { container: container ?? void 0, children: [
|
|
18267
|
+
/* @__PURE__ */ jsx19(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
18268
|
+
/* @__PURE__ */ jsxs10(
|
|
18269
|
+
DialogPrimitive.Content,
|
|
18270
|
+
{
|
|
18271
|
+
ref,
|
|
18272
|
+
"data-slot": "dialog-content",
|
|
18273
|
+
className: cn(
|
|
18274
|
+
positionMode,
|
|
18275
|
+
"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",
|
|
18276
|
+
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
18277
|
+
container ? "max-h-[calc(100%-32px)]" : "max-h-[calc(100vh-32px)]",
|
|
18278
|
+
className
|
|
18279
|
+
),
|
|
18280
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
18281
|
+
...props,
|
|
18282
|
+
children: [
|
|
18283
|
+
children,
|
|
18284
|
+
showCloseButton ? /* @__PURE__ */ jsx19(
|
|
18285
|
+
DialogPrimitive.Close,
|
|
18286
|
+
{
|
|
18287
|
+
type: "button",
|
|
18288
|
+
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
18289
|
+
"aria-label": "Close",
|
|
18290
|
+
children: /* @__PURE__ */ jsx19(X2, { size: 16, "aria-hidden": true })
|
|
18291
|
+
}
|
|
18292
|
+
) : null
|
|
18293
|
+
]
|
|
18294
|
+
}
|
|
18295
|
+
)
|
|
18296
|
+
] });
|
|
18297
|
+
}
|
|
18298
|
+
);
|
|
18299
|
+
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
18300
|
+
function DialogHeader({
|
|
18301
|
+
className,
|
|
18302
|
+
...props
|
|
18303
|
+
}) {
|
|
18304
|
+
return /* @__PURE__ */ jsx19("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
18305
|
+
}
|
|
18306
|
+
function DialogFooter({
|
|
18307
|
+
className,
|
|
18308
|
+
...props
|
|
18309
|
+
}) {
|
|
18310
|
+
return /* @__PURE__ */ jsx19(
|
|
18311
|
+
"div",
|
|
18312
|
+
{
|
|
18313
|
+
className: cn("flex items-center justify-end gap-2", className),
|
|
18314
|
+
...props
|
|
18315
|
+
}
|
|
18316
|
+
);
|
|
18317
|
+
}
|
|
18318
|
+
var DialogTitle = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx19(
|
|
18319
|
+
DialogPrimitive.Title,
|
|
18320
|
+
{
|
|
18321
|
+
ref,
|
|
18322
|
+
className: cn(
|
|
18323
|
+
"text-lg font-semibold leading-none tracking-tight text-card-foreground",
|
|
18324
|
+
className
|
|
18325
|
+
),
|
|
18326
|
+
...props
|
|
18327
|
+
}
|
|
18328
|
+
));
|
|
18329
|
+
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
18330
|
+
var DialogDescription = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx19(
|
|
18331
|
+
DialogPrimitive.Description,
|
|
18332
|
+
{
|
|
18333
|
+
ref,
|
|
18334
|
+
className: cn("text-sm text-muted-foreground", className),
|
|
18335
|
+
...props
|
|
18336
|
+
}
|
|
18337
|
+
));
|
|
18338
|
+
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
18339
|
+
var DialogClose = DialogPrimitive.Close;
|
|
18340
|
+
|
|
18168
18341
|
// src/ui/ai-section/AiMediaStripOverlay.tsx
|
|
18169
|
-
import { Fragment as Fragment6, jsx as
|
|
18170
|
-
var PRIMARY3 = "#0885FE";
|
|
18171
|
-
var
|
|
18172
|
-
var OHW_BLUE_DARK = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY3}) 60%, #000000)`;
|
|
18342
|
+
import { Fragment as Fragment6, jsx as jsx20, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
18343
|
+
var PRIMARY3 = "var(--ohw-primary, #0885FE)";
|
|
18344
|
+
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]";
|
|
18173
18345
|
function findMediaStripItemElement(sectionId, index) {
|
|
18174
18346
|
const sectionEl = findByInstanceId(sectionId);
|
|
18175
18347
|
if (!sectionEl) return null;
|
|
@@ -18179,14 +18351,35 @@ function findMediaStripItemElement(sectionId, index) {
|
|
|
18179
18351
|
}
|
|
18180
18352
|
return null;
|
|
18181
18353
|
}
|
|
18182
|
-
function
|
|
18183
|
-
|
|
18354
|
+
function itemRefFromTarget(target) {
|
|
18355
|
+
if (!(target instanceof Element)) return null;
|
|
18356
|
+
if (target.closest(CHROME_SELECTOR)) return null;
|
|
18357
|
+
const itemEl = target.closest("[data-ohw-media-strip-item]");
|
|
18358
|
+
if (!itemEl) return null;
|
|
18359
|
+
const sectionEl = itemEl.closest("[data-ohw-section]");
|
|
18360
|
+
const unit = sectionEl ? movableUnit(sectionEl) : null;
|
|
18361
|
+
const sectionId = unit ? instanceIdOf(unit) || null : null;
|
|
18362
|
+
const index = Number(itemEl.dataset.ohwMediaStripIndex);
|
|
18363
|
+
if (!sectionId || Number.isNaN(index)) return null;
|
|
18364
|
+
return { sectionId, index };
|
|
18365
|
+
}
|
|
18366
|
+
function sameRef(a, b) {
|
|
18367
|
+
return a?.sectionId === b?.sectionId && a?.index === b?.index;
|
|
18368
|
+
}
|
|
18369
|
+
function rectOf(el) {
|
|
18184
18370
|
if (!el) return null;
|
|
18185
18371
|
const r2 = el.getBoundingClientRect();
|
|
18186
18372
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
18187
18373
|
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
18188
18374
|
}
|
|
18189
|
-
function
|
|
18375
|
+
function readRect2(ref) {
|
|
18376
|
+
return rectOf(ref && findMediaStripItemElement(ref.sectionId, ref.index));
|
|
18377
|
+
}
|
|
18378
|
+
function readStripRect(ref) {
|
|
18379
|
+
const item = ref && findMediaStripItemElement(ref.sectionId, ref.index);
|
|
18380
|
+
return rectOf(item?.closest("[data-ohw-media-strip]") ?? item);
|
|
18381
|
+
}
|
|
18382
|
+
function useLiveItemRect(ref, strip = false) {
|
|
18190
18383
|
const [rect, setRect] = useState8(null);
|
|
18191
18384
|
useEffect6(() => {
|
|
18192
18385
|
if (!ref) {
|
|
@@ -18194,7 +18387,7 @@ function useLiveItemRect(ref) {
|
|
|
18194
18387
|
return;
|
|
18195
18388
|
}
|
|
18196
18389
|
const update = () => {
|
|
18197
|
-
const next = readRect2(ref);
|
|
18390
|
+
const next = strip ? readStripRect(ref) : readRect2(ref);
|
|
18198
18391
|
setRect(
|
|
18199
18392
|
(prev) => prev && next && prev.top === next.top && prev.left === next.left && prev.width === next.width && prev.height === next.height ? prev : next
|
|
18200
18393
|
);
|
|
@@ -18209,9 +18402,49 @@ function useLiveItemRect(ref) {
|
|
|
18209
18402
|
window.removeEventListener("resize", update);
|
|
18210
18403
|
clearInterval(interval);
|
|
18211
18404
|
};
|
|
18212
|
-
}, [ref?.sectionId, ref?.index]);
|
|
18405
|
+
}, [ref?.sectionId, ref?.index, strip]);
|
|
18213
18406
|
return rect;
|
|
18214
18407
|
}
|
|
18408
|
+
var TOOLBAR_STRIP_GAP = 52;
|
|
18409
|
+
var TOOLBAR_STRIP_GAP_MOBILE = 42;
|
|
18410
|
+
var TOOLBAR_EDGE_MARGIN2 = 4;
|
|
18411
|
+
function StripToolbarSlot({ stripRect, children }) {
|
|
18412
|
+
const slotRef = useRef5(null);
|
|
18413
|
+
const [shift, setShift] = useState8(0);
|
|
18414
|
+
const centerX = stripRect.left + stripRect.width / 2;
|
|
18415
|
+
useLayoutEffect4(() => {
|
|
18416
|
+
const slot = slotRef.current;
|
|
18417
|
+
if (!slot) return;
|
|
18418
|
+
const clamp = () => {
|
|
18419
|
+
const w = slot.offsetWidth;
|
|
18420
|
+
if (w <= 0) return;
|
|
18421
|
+
const half = w / 2;
|
|
18422
|
+
const clamped = Math.max(TOOLBAR_EDGE_MARGIN2 + half, Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN2 - half));
|
|
18423
|
+
setShift((prev) => Math.abs(prev - (clamped - centerX)) < 0.5 ? prev : clamped - centerX);
|
|
18424
|
+
};
|
|
18425
|
+
clamp();
|
|
18426
|
+
const ro = new ResizeObserver(clamp);
|
|
18427
|
+
ro.observe(slot);
|
|
18428
|
+
return () => ro.disconnect();
|
|
18429
|
+
}, [centerX, children]);
|
|
18430
|
+
const mobile = window.innerWidth <= 480;
|
|
18431
|
+
return /* @__PURE__ */ jsx20(
|
|
18432
|
+
"div",
|
|
18433
|
+
{
|
|
18434
|
+
ref: slotRef,
|
|
18435
|
+
"data-ohw-bridge": "",
|
|
18436
|
+
"data-ohw-item-interaction": "",
|
|
18437
|
+
className: "pointer-events-auto fixed",
|
|
18438
|
+
style: {
|
|
18439
|
+
top: stripRect.top - (mobile ? TOOLBAR_STRIP_GAP_MOBILE : TOOLBAR_STRIP_GAP),
|
|
18440
|
+
left: centerX + shift,
|
|
18441
|
+
transform: "translate(-50%, -100%)",
|
|
18442
|
+
zIndex: 2147483645
|
|
18443
|
+
},
|
|
18444
|
+
children
|
|
18445
|
+
}
|
|
18446
|
+
);
|
|
18447
|
+
}
|
|
18215
18448
|
function requestValidateTree(postToParent2, tree) {
|
|
18216
18449
|
return new Promise((resolve) => {
|
|
18217
18450
|
const id = `ai-validate-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
@@ -18248,221 +18481,177 @@ function requestAssetPick(postToParent2) {
|
|
|
18248
18481
|
postToParent2({ type: "ow:asset-pick", id });
|
|
18249
18482
|
});
|
|
18250
18483
|
}
|
|
18251
|
-
function
|
|
18484
|
+
function ToolbarAction({
|
|
18252
18485
|
label,
|
|
18253
18486
|
onClick,
|
|
18254
|
-
disabled,
|
|
18255
|
-
active
|
|
18487
|
+
disabled = false,
|
|
18488
|
+
active = false,
|
|
18489
|
+
children
|
|
18256
18490
|
}) {
|
|
18257
|
-
|
|
18258
|
-
|
|
18259
|
-
{
|
|
18260
|
-
|
|
18261
|
-
|
|
18262
|
-
disabled,
|
|
18263
|
-
style: {
|
|
18264
|
-
height: 28,
|
|
18265
|
-
padding: "0 10px",
|
|
18266
|
-
display: "inline-flex",
|
|
18267
|
-
alignItems: "center",
|
|
18268
|
-
gap: 4,
|
|
18269
|
-
borderRadius: 999,
|
|
18270
|
-
border: "none",
|
|
18271
|
-
cursor: disabled ? "default" : "pointer",
|
|
18272
|
-
background: active ? OHW_BLUE_DARK : "#ffffff",
|
|
18273
|
-
color: active ? "#ffffff" : OHW_BLUE_DARK,
|
|
18274
|
-
opacity: disabled ? 0.4 : 1,
|
|
18275
|
-
fontSize: 12,
|
|
18276
|
-
lineHeight: "16px",
|
|
18277
|
-
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
18278
|
-
whiteSpace: "nowrap",
|
|
18279
|
-
flex: "0 0 auto"
|
|
18280
|
-
},
|
|
18281
|
-
children: label
|
|
18282
|
-
}
|
|
18283
|
-
);
|
|
18491
|
+
const button = /* @__PURE__ */ jsx20(CustomToolbarButton, { type: "button", "aria-label": label, disabled, active, onClick, className: "size-8", children });
|
|
18492
|
+
return /* @__PURE__ */ jsxs11(Tooltip, { children: [
|
|
18493
|
+
/* @__PURE__ */ jsx20(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ jsx20("span", { className: "inline-flex", children: button }) : button }),
|
|
18494
|
+
/* @__PURE__ */ jsx20(TooltipContent, { side: "bottom", sideOffset: 8, children: label })
|
|
18495
|
+
] });
|
|
18284
18496
|
}
|
|
18285
|
-
function
|
|
18286
|
-
|
|
18287
|
-
useEffect6(() => setDraft(value), [value]);
|
|
18288
|
-
return /* @__PURE__ */ jsxs10(
|
|
18289
|
-
"div",
|
|
18290
|
-
{
|
|
18291
|
-
style: {
|
|
18292
|
-
display: "flex",
|
|
18293
|
-
alignItems: "center",
|
|
18294
|
-
gap: 6,
|
|
18295
|
-
height: 28,
|
|
18296
|
-
padding: "0 12px",
|
|
18297
|
-
borderRadius: 999,
|
|
18298
|
-
background: "#ffffff",
|
|
18299
|
-
width: "100%",
|
|
18300
|
-
maxWidth: 260,
|
|
18301
|
-
boxSizing: "border-box"
|
|
18302
|
-
},
|
|
18303
|
-
children: [
|
|
18304
|
-
/* @__PURE__ */ jsx19(
|
|
18305
|
-
"span",
|
|
18306
|
-
{
|
|
18307
|
-
style: {
|
|
18308
|
-
flex: "0 0 auto",
|
|
18309
|
-
color: OHW_BLUE_DARK,
|
|
18310
|
-
fontSize: 10,
|
|
18311
|
-
fontWeight: 700,
|
|
18312
|
-
textTransform: "uppercase",
|
|
18313
|
-
letterSpacing: 0.4
|
|
18314
|
-
},
|
|
18315
|
-
children: "Alt"
|
|
18316
|
-
}
|
|
18317
|
-
),
|
|
18318
|
-
/* @__PURE__ */ jsx19(
|
|
18319
|
-
"input",
|
|
18320
|
-
{
|
|
18321
|
-
type: "text",
|
|
18322
|
-
value: draft,
|
|
18323
|
-
onChange: (e) => setDraft(e.target.value),
|
|
18324
|
-
onBlur: () => {
|
|
18325
|
-
if (draft !== value) onCommit(draft);
|
|
18326
|
-
},
|
|
18327
|
-
onKeyDown: (e) => {
|
|
18328
|
-
if (e.key === "Enter") e.currentTarget.blur();
|
|
18329
|
-
if (e.key === "Escape") {
|
|
18330
|
-
setDraft(value);
|
|
18331
|
-
e.currentTarget.blur();
|
|
18332
|
-
}
|
|
18333
|
-
},
|
|
18334
|
-
placeholder: "Describe this image",
|
|
18335
|
-
"aria-label": "Image alt text",
|
|
18336
|
-
style: {
|
|
18337
|
-
flex: 1,
|
|
18338
|
-
minWidth: 0,
|
|
18339
|
-
border: "none",
|
|
18340
|
-
outline: "none",
|
|
18341
|
-
background: "transparent",
|
|
18342
|
-
fontSize: 12,
|
|
18343
|
-
lineHeight: "16px",
|
|
18344
|
-
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
18345
|
-
color: "#1f2937"
|
|
18346
|
-
}
|
|
18347
|
-
}
|
|
18348
|
-
)
|
|
18349
|
-
]
|
|
18350
|
-
}
|
|
18351
|
-
);
|
|
18497
|
+
function ToolbarSeparator() {
|
|
18498
|
+
return /* @__PURE__ */ jsx20("span", { "aria-hidden": true, className: "mx-0.5 block h-6 w-px shrink-0 bg-border" });
|
|
18352
18499
|
}
|
|
18353
|
-
|
|
18354
|
-
|
|
18355
|
-
|
|
18356
|
-
|
|
18357
|
-
|
|
18358
|
-
|
|
18359
|
-
|
|
18360
|
-
|
|
18361
|
-
|
|
18362
|
-
|
|
18363
|
-
|
|
18364
|
-
|
|
18365
|
-
|
|
18366
|
-
|
|
18367
|
-
|
|
18368
|
-
|
|
18369
|
-
|
|
18370
|
-
|
|
18371
|
-
|
|
18372
|
-
|
|
18373
|
-
|
|
18374
|
-
|
|
18375
|
-
|
|
18376
|
-
|
|
18377
|
-
|
|
18378
|
-
|
|
18379
|
-
}, [value]);
|
|
18380
|
-
const commit = () => {
|
|
18381
|
-
const next = draft.trim();
|
|
18382
|
-
if (next === value) return setInvalid(false);
|
|
18383
|
-
if (next && !HTTP_URL_RE.test(next)) return setInvalid(true);
|
|
18384
|
-
setInvalid(false);
|
|
18385
|
-
onCommit(next);
|
|
18386
|
-
};
|
|
18387
|
-
return /* @__PURE__ */ jsxs10(
|
|
18388
|
-
"div",
|
|
18389
|
-
{
|
|
18390
|
-
style: {
|
|
18391
|
-
display: "flex",
|
|
18392
|
-
alignItems: "center",
|
|
18393
|
-
gap: 6,
|
|
18394
|
-
height: 28,
|
|
18395
|
-
padding: "0 12px",
|
|
18396
|
-
borderRadius: 999,
|
|
18397
|
-
background: "#ffffff",
|
|
18398
|
-
width: "100%",
|
|
18399
|
-
maxWidth: 260,
|
|
18400
|
-
boxSizing: "border-box",
|
|
18401
|
-
boxShadow: invalid ? "inset 0 0 0 1.5px #EF4444" : "none"
|
|
18402
|
-
},
|
|
18403
|
-
children: [
|
|
18404
|
-
/* @__PURE__ */ jsx19(
|
|
18405
|
-
"span",
|
|
18406
|
-
{
|
|
18407
|
-
style: {
|
|
18408
|
-
flex: "0 0 auto",
|
|
18409
|
-
color: OHW_BLUE_DARK,
|
|
18410
|
-
fontSize: 10,
|
|
18411
|
-
fontWeight: 700,
|
|
18412
|
-
textTransform: "uppercase",
|
|
18413
|
-
letterSpacing: 0.4
|
|
18414
|
-
},
|
|
18415
|
-
children: "Link"
|
|
18416
|
-
}
|
|
18417
|
-
),
|
|
18418
|
-
/* @__PURE__ */ jsx19(
|
|
18419
|
-
"input",
|
|
18500
|
+
function OptionMenu({
|
|
18501
|
+
label,
|
|
18502
|
+
value,
|
|
18503
|
+
options,
|
|
18504
|
+
onChange
|
|
18505
|
+
}) {
|
|
18506
|
+
const current = options.find((o) => o.value === value) ?? options[0];
|
|
18507
|
+
return /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
18508
|
+
/* @__PURE__ */ jsx20("span", { className: "text-xs text-muted-foreground", children: label }),
|
|
18509
|
+
/* @__PURE__ */ jsxs11(DropdownMenu, { modal: false, children: [
|
|
18510
|
+
/* @__PURE__ */ jsx20(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs11(
|
|
18511
|
+
"button",
|
|
18512
|
+
{
|
|
18513
|
+
type: "button",
|
|
18514
|
+
"aria-label": label,
|
|
18515
|
+
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",
|
|
18516
|
+
children: [
|
|
18517
|
+
/* @__PURE__ */ jsx20("span", { className: "flex-1 text-left", children: current.label }),
|
|
18518
|
+
/* @__PURE__ */ jsx20(ChevronDown3, { size: 16, style: { pointerEvents: "none" } })
|
|
18519
|
+
]
|
|
18520
|
+
}
|
|
18521
|
+
) }),
|
|
18522
|
+
/* @__PURE__ */ jsx20(DropdownMenuContent, { align: "end", sideOffset: 8, className: "w-[132px] min-w-[132px] p-1", children: options.map((option) => {
|
|
18523
|
+
const selected = option.value === value;
|
|
18524
|
+
return /* @__PURE__ */ jsxs11(
|
|
18525
|
+
DropdownMenuItem,
|
|
18420
18526
|
{
|
|
18421
|
-
|
|
18422
|
-
|
|
18423
|
-
|
|
18424
|
-
|
|
18425
|
-
|
|
18426
|
-
|
|
18427
|
-
|
|
18428
|
-
|
|
18429
|
-
|
|
18430
|
-
|
|
18431
|
-
|
|
18432
|
-
|
|
18433
|
-
|
|
18434
|
-
|
|
18435
|
-
|
|
18436
|
-
|
|
18437
|
-
|
|
18438
|
-
|
|
18439
|
-
|
|
18440
|
-
|
|
18441
|
-
|
|
18442
|
-
|
|
18443
|
-
|
|
18444
|
-
|
|
18445
|
-
|
|
18446
|
-
|
|
18447
|
-
|
|
18448
|
-
|
|
18449
|
-
|
|
18450
|
-
|
|
18527
|
+
role: "menuitemradio",
|
|
18528
|
+
"aria-checked": selected,
|
|
18529
|
+
onSelect: () => onChange(option.value),
|
|
18530
|
+
className: cn("grid grid-cols-[1fr_16px] gap-2 py-2 pl-2 pr-2 text-[13px]", selected && "bg-muted"),
|
|
18531
|
+
children: [
|
|
18532
|
+
/* @__PURE__ */ jsx20("span", { children: option.label }),
|
|
18533
|
+
selected && /* @__PURE__ */ jsx20(Check2, { size: 16, className: "text-bridge-primary" })
|
|
18534
|
+
]
|
|
18535
|
+
},
|
|
18536
|
+
option.value
|
|
18537
|
+
);
|
|
18538
|
+
}) })
|
|
18539
|
+
] })
|
|
18540
|
+
] });
|
|
18541
|
+
}
|
|
18542
|
+
var VARIANTS = [
|
|
18543
|
+
{ value: "logos", label: "Logos" },
|
|
18544
|
+
{ value: "reel", label: "Reel" }
|
|
18545
|
+
];
|
|
18546
|
+
var ALIGNS = [
|
|
18547
|
+
{ value: "left", label: "Align left", Icon: AlignLeft },
|
|
18548
|
+
{ value: "center", label: "Align center", Icon: AlignCenter },
|
|
18549
|
+
{ value: "right", label: "Align right", Icon: AlignRight }
|
|
18550
|
+
];
|
|
18551
|
+
var HOVERS = [
|
|
18552
|
+
{ value: "none", label: "None" },
|
|
18553
|
+
{ value: "lift", label: "Lift" },
|
|
18554
|
+
{ value: "zoom", label: "Zoom" },
|
|
18555
|
+
{ value: "fade", label: "Fade" }
|
|
18556
|
+
];
|
|
18557
|
+
var HTTP_URL_RE = /^https?:\/\/\S+$/i;
|
|
18558
|
+
function LinkModal({
|
|
18559
|
+
href,
|
|
18560
|
+
linkTarget,
|
|
18561
|
+
onClose,
|
|
18562
|
+
onSave
|
|
18563
|
+
}) {
|
|
18564
|
+
const [draft, setDraft] = useState8(href);
|
|
18565
|
+
const [newTab, setNewTab] = useState8(linkTarget !== "same-tab");
|
|
18566
|
+
const [invalid, setInvalid] = useState8(false);
|
|
18567
|
+
const save = () => {
|
|
18568
|
+
const next = draft.trim();
|
|
18569
|
+
if (next && !HTTP_URL_RE.test(next)) {
|
|
18570
|
+
setInvalid(true);
|
|
18571
|
+
return;
|
|
18451
18572
|
}
|
|
18452
|
-
|
|
18573
|
+
onSave(next, newTab ? "new-tab" : "same-tab");
|
|
18574
|
+
onClose();
|
|
18575
|
+
};
|
|
18576
|
+
return /* @__PURE__ */ jsx20(Dialog2, { open: true, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ jsxs11(DialogContent, { "data-ohw-link-modal-root": "", className: "max-w-[400px] gap-4 p-5", children: [
|
|
18577
|
+
/* @__PURE__ */ jsx20(DialogHeader, { children: /* @__PURE__ */ jsx20(DialogTitle, { className: "text-base", children: "Image link" }) }),
|
|
18578
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-3", children: [
|
|
18579
|
+
/* @__PURE__ */ jsx20(
|
|
18580
|
+
"input",
|
|
18581
|
+
{
|
|
18582
|
+
autoFocus: true,
|
|
18583
|
+
type: "text",
|
|
18584
|
+
inputMode: "url",
|
|
18585
|
+
value: draft,
|
|
18586
|
+
onChange: (e) => {
|
|
18587
|
+
setDraft(e.target.value);
|
|
18588
|
+
setInvalid(false);
|
|
18589
|
+
},
|
|
18590
|
+
onKeyDown: (e) => {
|
|
18591
|
+
if (e.key === "Enter") save();
|
|
18592
|
+
},
|
|
18593
|
+
placeholder: "https://example.com",
|
|
18594
|
+
"aria-label": "Image link URL",
|
|
18595
|
+
"aria-invalid": invalid,
|
|
18596
|
+
className: cn(
|
|
18597
|
+
"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",
|
|
18598
|
+
invalid && "border-destructive focus:border-destructive"
|
|
18599
|
+
)
|
|
18600
|
+
}
|
|
18601
|
+
),
|
|
18602
|
+
invalid && /* @__PURE__ */ jsx20("p", { className: "text-xs text-destructive", children: "Enter a full URL starting with http:// or https://" }),
|
|
18603
|
+
/* @__PURE__ */ jsxs11("label", { className: "flex items-center gap-2 text-[13px] text-foreground", children: [
|
|
18604
|
+
/* @__PURE__ */ jsx20("input", { type: "checkbox", checked: newTab, onChange: (e) => setNewTab(e.target.checked) }),
|
|
18605
|
+
"Open in new tab"
|
|
18606
|
+
] })
|
|
18607
|
+
] }),
|
|
18608
|
+
/* @__PURE__ */ jsxs11(DialogFooter, { children: [
|
|
18609
|
+
href && /* @__PURE__ */ jsx20(
|
|
18610
|
+
"button",
|
|
18611
|
+
{
|
|
18612
|
+
type: "button",
|
|
18613
|
+
onClick: () => {
|
|
18614
|
+
onSave("", "new-tab");
|
|
18615
|
+
onClose();
|
|
18616
|
+
},
|
|
18617
|
+
className: "mr-auto rounded-[6px] px-3 py-2 text-[13px] font-medium text-destructive transition-colors hover:bg-muted",
|
|
18618
|
+
children: "Remove link"
|
|
18619
|
+
}
|
|
18620
|
+
),
|
|
18621
|
+
/* @__PURE__ */ jsx20(
|
|
18622
|
+
"button",
|
|
18623
|
+
{
|
|
18624
|
+
type: "button",
|
|
18625
|
+
onClick: onClose,
|
|
18626
|
+
className: "rounded-[6px] px-3 py-2 text-[13px] font-medium text-foreground transition-colors hover:bg-muted",
|
|
18627
|
+
children: "Cancel"
|
|
18628
|
+
}
|
|
18629
|
+
),
|
|
18630
|
+
/* @__PURE__ */ jsx20(
|
|
18631
|
+
"button",
|
|
18632
|
+
{
|
|
18633
|
+
type: "button",
|
|
18634
|
+
onClick: save,
|
|
18635
|
+
className: "rounded-[6px] bg-bridge-primary px-3 py-2 text-[13px] font-medium text-primary-foreground transition-opacity hover:opacity-90",
|
|
18636
|
+
children: "Save"
|
|
18637
|
+
}
|
|
18638
|
+
)
|
|
18639
|
+
] })
|
|
18640
|
+
] }) });
|
|
18453
18641
|
}
|
|
18454
18642
|
function MediaStripToolbar({
|
|
18455
18643
|
entry,
|
|
18456
18644
|
index,
|
|
18457
18645
|
pending,
|
|
18458
18646
|
error,
|
|
18647
|
+
itemEditOn,
|
|
18648
|
+
onToggleItemEdit,
|
|
18459
18649
|
onSetVariant,
|
|
18460
18650
|
onSetAlign,
|
|
18461
18651
|
onSetHover,
|
|
18462
18652
|
onSetTreatment,
|
|
18463
18653
|
onResize,
|
|
18464
|
-
|
|
18465
|
-
onSetLink,
|
|
18654
|
+
onOpenLink,
|
|
18466
18655
|
onAddItem,
|
|
18467
18656
|
onRemoveItem,
|
|
18468
18657
|
onChangeImage,
|
|
@@ -18471,81 +18660,102 @@ function MediaStripToolbar({
|
|
|
18471
18660
|
}) {
|
|
18472
18661
|
const items = mediaStripItems(entry.tree);
|
|
18473
18662
|
const itemCount = items.length;
|
|
18474
|
-
const currentAlt = items[index]?.alt ?? "";
|
|
18475
|
-
const currentHref = items[index]?.href ?? "";
|
|
18476
|
-
const currentTarget = items[index]?.linkTarget === "same-tab" ? "same-tab" : "new-tab";
|
|
18477
18663
|
const slots = findMediaStripSlots(entry.tree);
|
|
18478
18664
|
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
18479
18665
|
const align = slots?.align === "left" || slots?.align === "right" ? slots.align : "center";
|
|
18480
18666
|
const hover = slots?.hover === "none" || slots?.hover === "lift" || slots?.hover === "zoom" || slots?.hover === "fade" ? slots.hover : "lift";
|
|
18481
18667
|
const treatment = slots?.treatment === "color" || slots?.treatment === "grayscale" ? slots.treatment : variant === "logos" ? "grayscale" : "color";
|
|
18482
18668
|
const sizeValue = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
18483
|
-
const
|
|
18484
|
-
const
|
|
18485
|
-
|
|
18486
|
-
gap: 6,
|
|
18487
|
-
flexWrap: "nowrap",
|
|
18488
|
-
justifyContent: "center",
|
|
18489
|
-
overflowX: "auto",
|
|
18490
|
-
WebkitOverflowScrolling: "touch",
|
|
18491
|
-
width: "100%",
|
|
18492
|
-
scrollbarWidth: "none"
|
|
18493
|
-
} : { display: "flex", gap: 6, flexWrap: "nowrap", justifyContent: "center" };
|
|
18494
|
-
return /* @__PURE__ */ jsxs10(
|
|
18669
|
+
const mobile = window.innerWidth <= 480;
|
|
18670
|
+
const gatedLabel = (label) => itemEditOn ? label : "Turn on the star to edit this image";
|
|
18671
|
+
return /* @__PURE__ */ jsx20(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs11(
|
|
18495
18672
|
"div",
|
|
18496
18673
|
{
|
|
18497
18674
|
"data-ohw-bridge": "",
|
|
18498
18675
|
"data-ohw-toolbar": "",
|
|
18499
18676
|
onMouseDown: (e) => e.stopPropagation(),
|
|
18500
|
-
|
|
18501
|
-
|
|
18502
|
-
flexDirection: "column",
|
|
18503
|
-
gap: 6,
|
|
18504
|
-
alignItems: "center",
|
|
18505
|
-
background: OHW_BLUE,
|
|
18506
|
-
padding: 8,
|
|
18507
|
-
borderRadius: 12,
|
|
18508
|
-
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
18509
|
-
pointerEvents: pending ? "none" : "auto",
|
|
18510
|
-
opacity: pending ? 0.6 : 1,
|
|
18511
|
-
maxWidth: isMobile ? "calc(100vw - 24px)" : "none"
|
|
18512
|
-
},
|
|
18677
|
+
className: cn("flex flex-col items-center gap-1.5 font-sans", pending && "pointer-events-none opacity-60"),
|
|
18678
|
+
style: { maxWidth: mobile ? "calc(100vw - 24px)" : void 0 },
|
|
18513
18679
|
children: [
|
|
18514
|
-
/* @__PURE__ */
|
|
18515
|
-
|
|
18516
|
-
|
|
18517
|
-
|
|
18518
|
-
|
|
18519
|
-
|
|
18520
|
-
|
|
18521
|
-
|
|
18522
|
-
|
|
18523
|
-
|
|
18524
|
-
|
|
18525
|
-
|
|
18526
|
-
|
|
18527
|
-
|
|
18528
|
-
|
|
18529
|
-
|
|
18530
|
-
|
|
18531
|
-
|
|
18532
|
-
|
|
18533
|
-
|
|
18534
|
-
|
|
18535
|
-
|
|
18536
|
-
|
|
18537
|
-
|
|
18538
|
-
|
|
18539
|
-
|
|
18540
|
-
|
|
18541
|
-
|
|
18542
|
-
|
|
18543
|
-
|
|
18544
|
-
|
|
18545
|
-
|
|
18680
|
+
/* @__PURE__ */ jsxs11(
|
|
18681
|
+
"div",
|
|
18682
|
+
{
|
|
18683
|
+
className: cn(
|
|
18684
|
+
"flex items-center gap-1 rounded-[10px] border border-border bg-background p-1 whitespace-nowrap",
|
|
18685
|
+
"shadow-[0px_10px_15px_-3px_rgba(0,0,0,0.1),0px_4px_6px_-4px_rgba(0,0,0,0.1)]",
|
|
18686
|
+
mobile ? "flex-wrap justify-center" : "flex-nowrap"
|
|
18687
|
+
),
|
|
18688
|
+
children: [
|
|
18689
|
+
/* @__PURE__ */ jsxs11(Tooltip, { children: [
|
|
18690
|
+
/* @__PURE__ */ jsx20(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx20(
|
|
18691
|
+
CustomToolbarButton,
|
|
18692
|
+
{
|
|
18693
|
+
type: "button",
|
|
18694
|
+
"aria-label": itemEditOn ? "Done editing this image" : "Edit this image",
|
|
18695
|
+
"aria-pressed": itemEditOn,
|
|
18696
|
+
onClick: onToggleItemEdit,
|
|
18697
|
+
className: "group size-8",
|
|
18698
|
+
children: /* @__PURE__ */ jsx20(
|
|
18699
|
+
Star,
|
|
18700
|
+
{
|
|
18701
|
+
size: 16,
|
|
18702
|
+
fill: "currentColor",
|
|
18703
|
+
strokeWidth: 0,
|
|
18704
|
+
className: cn(
|
|
18705
|
+
"transition-colors",
|
|
18706
|
+
itemEditOn ? "text-[#f59e0b] group-hover:text-[#d97706]" : "text-[#d6d3d1] group-hover:text-[#fbbf24]"
|
|
18707
|
+
),
|
|
18708
|
+
style: { pointerEvents: "none" }
|
|
18709
|
+
}
|
|
18710
|
+
)
|
|
18711
|
+
}
|
|
18712
|
+
) }),
|
|
18713
|
+
/* @__PURE__ */ jsx20(TooltipContent, { side: "bottom", sideOffset: 8, children: itemEditOn ? "Done editing this image" : "Edit this image" })
|
|
18714
|
+
] }),
|
|
18715
|
+
/* @__PURE__ */ jsx20(ToolbarSeparator, {}),
|
|
18716
|
+
/* @__PURE__ */ jsx20(ToolbarAction, { label: gatedLabel("Change image"), onClick: onChangeImage, disabled: !itemEditOn, children: /* @__PURE__ */ jsx20(ImageIcon2, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
18717
|
+
/* @__PURE__ */ jsx20(ToolbarAction, { label: gatedLabel("Link"), onClick: onOpenLink, disabled: !itemEditOn, children: /* @__PURE__ */ jsx20(LinkIcon, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
18718
|
+
/* @__PURE__ */ jsx20(ToolbarAction, { label: gatedLabel("Move left"), onClick: onMoveLeft, disabled: !itemEditOn || index <= 0, children: /* @__PURE__ */ jsx20(ArrowLeft2, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
18719
|
+
/* @__PURE__ */ jsx20(
|
|
18720
|
+
ToolbarAction,
|
|
18721
|
+
{
|
|
18722
|
+
label: gatedLabel("Move right"),
|
|
18723
|
+
onClick: onMoveRight,
|
|
18724
|
+
disabled: !itemEditOn || index >= itemCount - 1,
|
|
18725
|
+
children: /* @__PURE__ */ jsx20(ArrowRight2, { size: 16, style: { pointerEvents: "none" } })
|
|
18726
|
+
}
|
|
18727
|
+
),
|
|
18728
|
+
/* @__PURE__ */ jsx20(ToolbarAction, { label: gatedLabel("Remove image"), onClick: onRemoveItem, disabled: !itemEditOn || itemCount <= 1, children: /* @__PURE__ */ jsx20(ImageMinus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
18729
|
+
/* @__PURE__ */ jsx20(ToolbarSeparator, {}),
|
|
18730
|
+
/* @__PURE__ */ jsx20(OptionMenu, { label: "Layout", value: variant, options: VARIANTS, onChange: onSetVariant }),
|
|
18731
|
+
/* @__PURE__ */ jsx20(OptionMenu, { label: "Hover", value: hover, options: HOVERS, onChange: onSetHover }),
|
|
18732
|
+
/* @__PURE__ */ jsx20(
|
|
18733
|
+
ToolbarAction,
|
|
18734
|
+
{
|
|
18735
|
+
label: treatment === "grayscale" ? "Show in color" : "Show grayscale",
|
|
18736
|
+
active: treatment === "grayscale",
|
|
18737
|
+
onClick: () => onSetTreatment(treatment === "grayscale" ? "color" : "grayscale"),
|
|
18738
|
+
children: /* @__PURE__ */ jsx20(Palette, { size: 16, style: { pointerEvents: "none" } })
|
|
18739
|
+
}
|
|
18740
|
+
),
|
|
18741
|
+
/* @__PURE__ */ jsx20(ToolbarSeparator, {}),
|
|
18742
|
+
ALIGNS.map(({ value, label, Icon }) => /* @__PURE__ */ jsx20(ToolbarAction, { label, active: align === value, onClick: () => onSetAlign(value), children: /* @__PURE__ */ jsx20(Icon, { size: 16, style: { pointerEvents: "none" } }) }, value)),
|
|
18743
|
+
/* @__PURE__ */ jsx20(ToolbarSeparator, {}),
|
|
18744
|
+
/* @__PURE__ */ jsx20(ToolbarAction, { label: "Smaller", onClick: () => onResize(-8), children: /* @__PURE__ */ jsx20(Minus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
18745
|
+
/* @__PURE__ */ jsxs11("span", { className: "min-w-[40px] text-center text-xs tabular-nums text-muted-foreground", children: [
|
|
18746
|
+
sizeValue,
|
|
18747
|
+
"px"
|
|
18748
|
+
] }),
|
|
18749
|
+
/* @__PURE__ */ jsx20(ToolbarAction, { label: "Larger", onClick: () => onResize(8), children: /* @__PURE__ */ jsx20(Plus2, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
18750
|
+
/* @__PURE__ */ jsx20(ToolbarSeparator, {}),
|
|
18751
|
+
/* @__PURE__ */ jsx20(ToolbarAction, { label: "Add image", onClick: onAddItem, children: /* @__PURE__ */ jsx20(ImagePlus, { size: 16, style: { pointerEvents: "none" } }) })
|
|
18752
|
+
]
|
|
18753
|
+
}
|
|
18754
|
+
),
|
|
18755
|
+
error && /* @__PURE__ */ jsx20("div", { className: "max-w-[260px] rounded-md bg-background px-2 py-1 text-center text-[11px] text-destructive shadow-sm", children: error })
|
|
18546
18756
|
]
|
|
18547
18757
|
}
|
|
18548
|
-
);
|
|
18758
|
+
) });
|
|
18549
18759
|
}
|
|
18550
18760
|
function findMediaStripSlots(tree) {
|
|
18551
18761
|
const stack = tree.rows.flatMap((row) => row.blocks);
|
|
@@ -18564,31 +18774,23 @@ function AiMediaStripOverlay({
|
|
|
18564
18774
|
}) {
|
|
18565
18775
|
const [hover, setHover] = useState8(null);
|
|
18566
18776
|
const [active, setActive] = useState8(null);
|
|
18777
|
+
const [itemEditOn, setItemEditOn] = useState8(false);
|
|
18778
|
+
const [linkOpen, setLinkOpen] = useState8(false);
|
|
18567
18779
|
const [pending, setPending] = useState8(false);
|
|
18568
18780
|
const [error, setError] = useState8(null);
|
|
18569
18781
|
const activeRef = useRef5(null);
|
|
18570
18782
|
activeRef.current = active;
|
|
18783
|
+
const linkOpenRef = useRef5(false);
|
|
18784
|
+
linkOpenRef.current = linkOpen;
|
|
18571
18785
|
useEffect6(() => {
|
|
18572
18786
|
const onMove = (e) => {
|
|
18787
|
+
const ref = itemRefFromTarget(e.target);
|
|
18573
18788
|
const t = e.target;
|
|
18574
|
-
|
|
18575
|
-
|
|
18576
|
-
|
|
18577
|
-
|
|
18578
|
-
|
|
18579
|
-
if (!itemEl) {
|
|
18580
|
-
setHover(null);
|
|
18581
|
-
return;
|
|
18582
|
-
}
|
|
18583
|
-
const sectionEl = itemEl.closest("[data-ohw-section]");
|
|
18584
|
-
const unit = sectionEl ? movableUnit(sectionEl) : null;
|
|
18585
|
-
const sectionId = unit ? instanceIdOf(unit) || null : null;
|
|
18586
|
-
const index = Number(itemEl.dataset.ohwMediaStripIndex);
|
|
18587
|
-
if (!sectionId || Number.isNaN(index)) {
|
|
18588
|
-
setHover(null);
|
|
18589
|
-
return;
|
|
18590
|
-
}
|
|
18591
|
-
setHover({ sectionId, index });
|
|
18789
|
+
const overEditable = Boolean(t?.closest?.("[data-ohw-editable]"));
|
|
18790
|
+
setHover((prev) => {
|
|
18791
|
+
const next = ref && !overEditable ? ref : null;
|
|
18792
|
+
return sameRef(prev, next) ? prev : next;
|
|
18793
|
+
});
|
|
18592
18794
|
};
|
|
18593
18795
|
const onLeave = () => setHover(null);
|
|
18594
18796
|
document.addEventListener("mousemove", onMove, { passive: true });
|
|
@@ -18600,23 +18802,25 @@ function AiMediaStripOverlay({
|
|
|
18600
18802
|
}, []);
|
|
18601
18803
|
useEffect6(() => {
|
|
18602
18804
|
const onClick = (e) => {
|
|
18603
|
-
const current = activeRef.current;
|
|
18604
|
-
if (!current) return;
|
|
18605
18805
|
const t = e.target;
|
|
18606
|
-
if (!(t instanceof
|
|
18607
|
-
if (t.closest(
|
|
18608
|
-
const
|
|
18609
|
-
if (
|
|
18610
|
-
|
|
18806
|
+
if (!(t instanceof Element)) return;
|
|
18807
|
+
if (t.closest(CHROME_SELECTOR)) return;
|
|
18808
|
+
const ref = itemRefFromTarget(t);
|
|
18809
|
+
if (sameRef(activeRef.current, ref)) return;
|
|
18810
|
+
if (ref) clearInteractionChromeRef.current();
|
|
18811
|
+
setItemEditOn(false);
|
|
18611
18812
|
setError(null);
|
|
18813
|
+
setActive(ref);
|
|
18612
18814
|
};
|
|
18613
18815
|
document.addEventListener("click", onClick, true);
|
|
18614
18816
|
return () => document.removeEventListener("click", onClick, true);
|
|
18615
|
-
}, []);
|
|
18817
|
+
}, [clearInteractionChromeRef]);
|
|
18616
18818
|
useEffect6(() => {
|
|
18617
18819
|
const onBlur = () => {
|
|
18618
18820
|
if (!activeRef.current) return;
|
|
18619
18821
|
setActive(null);
|
|
18822
|
+
setItemEditOn(false);
|
|
18823
|
+
setLinkOpen(false);
|
|
18620
18824
|
setError(null);
|
|
18621
18825
|
};
|
|
18622
18826
|
window.addEventListener("blur", onBlur);
|
|
@@ -18626,7 +18830,10 @@ function AiMediaStripOverlay({
|
|
|
18626
18830
|
const onKeyDown = (e) => {
|
|
18627
18831
|
if (e.key !== "Escape") return;
|
|
18628
18832
|
if (!activeRef.current) return;
|
|
18833
|
+
if (linkOpenRef.current) return;
|
|
18834
|
+
if (document.querySelector('[data-ohw-more-menu][data-state="open"]')) return;
|
|
18629
18835
|
setActive(null);
|
|
18836
|
+
setItemEditOn(false);
|
|
18630
18837
|
setError(null);
|
|
18631
18838
|
};
|
|
18632
18839
|
document.addEventListener("keydown", onKeyDown);
|
|
@@ -18660,137 +18867,133 @@ function AiMediaStripOverlay({
|
|
|
18660
18867
|
tree: nextTree,
|
|
18661
18868
|
label: entry.label,
|
|
18662
18869
|
media: extraMedia ? { ...entry.media, ...extraMedia } : entry.media,
|
|
18663
|
-
...entry.brand ? { brand: entry.brand } : {}
|
|
18870
|
+
...entry.brand ? { brand: entry.brand } : {},
|
|
18871
|
+
// The user is already looking at the strip they just edited — recentering the viewport
|
|
18872
|
+
// on every edit reads as the section jumping around.
|
|
18873
|
+
skipScrollIntoView: true
|
|
18664
18874
|
});
|
|
18665
18875
|
return true;
|
|
18666
18876
|
},
|
|
18667
18877
|
[findEntry, postToParent2, applyTreeLocalRef]
|
|
18668
18878
|
);
|
|
18669
18879
|
const activeEntry = active ? findEntry(active.sectionId) : null;
|
|
18670
|
-
const hoverHandleRect = useLiveItemRect(!active && hover ? hover : null);
|
|
18671
18880
|
const activeItemRect = useLiveItemRect(active);
|
|
18672
|
-
const
|
|
18673
|
-
const
|
|
18674
|
-
|
|
18675
|
-
|
|
18676
|
-
|
|
18677
|
-
|
|
18678
|
-
|
|
18679
|
-
|
|
18680
|
-
|
|
18681
|
-
|
|
18682
|
-
|
|
18683
|
-
|
|
18684
|
-
|
|
18685
|
-
|
|
18686
|
-
|
|
18687
|
-
|
|
18688
|
-
|
|
18689
|
-
|
|
18690
|
-
|
|
18691
|
-
|
|
18692
|
-
|
|
18693
|
-
|
|
18694
|
-
|
|
18695
|
-
|
|
18696
|
-
|
|
18697
|
-
|
|
18698
|
-
|
|
18699
|
-
|
|
18700
|
-
|
|
18701
|
-
|
|
18702
|
-
|
|
18703
|
-
|
|
18704
|
-
|
|
18705
|
-
|
|
18706
|
-
activeItemRect && active && activeEntry && /* @__PURE__ */ jsx19(
|
|
18707
|
-
ItemInteractionLayer,
|
|
18708
|
-
{
|
|
18709
|
-
rect: activeItemRect,
|
|
18710
|
-
state: toolbarState,
|
|
18711
|
-
toolbar: /* @__PURE__ */ jsx19(
|
|
18712
|
-
MediaStripToolbar,
|
|
18713
|
-
{
|
|
18714
|
-
entry: activeEntry,
|
|
18715
|
-
index: active.index,
|
|
18716
|
-
pending,
|
|
18717
|
-
error,
|
|
18718
|
-
onSetVariant: (variant) => runMutation(active.sectionId, (tree) => setMediaStripVariant(tree, variant)),
|
|
18719
|
-
onSetAlign: (align) => runMutation(active.sectionId, (tree) => setMediaStripAlign(tree, align)),
|
|
18720
|
-
onSetHover: (hoverPreset) => runMutation(active.sectionId, (tree) => setMediaStripHover(tree, hoverPreset)),
|
|
18721
|
-
onSetTreatment: (treatment) => runMutation(active.sectionId, (tree) => setMediaStripTreatment(tree, treatment)),
|
|
18722
|
-
onResize: (delta) => {
|
|
18723
|
-
const slots = findMediaStripSlots(activeEntry.tree);
|
|
18724
|
-
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
18725
|
-
const current = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
18726
|
-
void runMutation(active.sectionId, (tree) => setMediaStripSizing(tree, current + delta));
|
|
18727
|
-
},
|
|
18728
|
-
onSetAlt: (alt) => {
|
|
18729
|
-
void runMutation(active.sectionId, (tree) => setMediaStripItemAlt(tree, active.index, alt));
|
|
18730
|
-
},
|
|
18731
|
-
onSetLink: (href, linkTarget) => {
|
|
18881
|
+
const activeStripRect = useLiveItemRect(active, true);
|
|
18882
|
+
const hoverRect = useLiveItemRect(hover && !sameRef(hover, active) ? hover : null);
|
|
18883
|
+
const activeItems = activeEntry ? mediaStripItems(activeEntry.tree) : [];
|
|
18884
|
+
const activeItem = active ? activeItems[active.index] : void 0;
|
|
18885
|
+
const activeHref = activeItem?.href ?? "";
|
|
18886
|
+
const activeTarget = activeItem?.linkTarget === "same-tab" ? "same-tab" : "new-tab";
|
|
18887
|
+
return /* @__PURE__ */ jsxs11(Fragment6, { children: [
|
|
18888
|
+
hoverRect && /* @__PURE__ */ jsx20(ItemInteractionLayer, { rect: hoverRect, state: "hover" }),
|
|
18889
|
+
activeItemRect && activeStripRect && active && activeEntry && /* @__PURE__ */ jsxs11(Fragment6, { children: [
|
|
18890
|
+
/* @__PURE__ */ jsx20(ItemInteractionLayer, { rect: activeItemRect, state: "active-top" }),
|
|
18891
|
+
/* @__PURE__ */ jsx20(StripToolbarSlot, { stripRect: activeStripRect, children: /* @__PURE__ */ jsx20(
|
|
18892
|
+
MediaStripToolbar,
|
|
18893
|
+
{
|
|
18894
|
+
entry: activeEntry,
|
|
18895
|
+
index: active.index,
|
|
18896
|
+
pending,
|
|
18897
|
+
error,
|
|
18898
|
+
itemEditOn,
|
|
18899
|
+
onToggleItemEdit: () => setItemEditOn((on) => !on),
|
|
18900
|
+
onSetVariant: (variant) => runMutation(active.sectionId, (tree) => setMediaStripVariant(tree, variant)),
|
|
18901
|
+
onSetAlign: (align) => runMutation(active.sectionId, (tree) => setMediaStripAlign(tree, align)),
|
|
18902
|
+
onSetHover: (hoverPreset) => runMutation(active.sectionId, (tree) => setMediaStripHover(tree, hoverPreset)),
|
|
18903
|
+
onSetTreatment: (treatment) => runMutation(active.sectionId, (tree) => setMediaStripTreatment(tree, treatment)),
|
|
18904
|
+
onResize: (delta) => {
|
|
18905
|
+
const slots = findMediaStripSlots(activeEntry.tree);
|
|
18906
|
+
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
18907
|
+
const current = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
18908
|
+
void runMutation(active.sectionId, (tree) => setMediaStripSizing(tree, current + delta));
|
|
18909
|
+
},
|
|
18910
|
+
onOpenLink: () => setLinkOpen(true),
|
|
18911
|
+
onAddItem: () => {
|
|
18912
|
+
void requestAssetPick(postToParent2).then((picked) => {
|
|
18913
|
+
if (!picked) return;
|
|
18914
|
+
const item = { assetId: picked.assetId, alt: "Logo" };
|
|
18732
18915
|
void runMutation(
|
|
18733
18916
|
active.sectionId,
|
|
18734
|
-
(tree) =>
|
|
18735
|
-
|
|
18736
|
-
|
|
18737
|
-
|
|
18738
|
-
void requestAssetPick(postToParent2).then((picked) => {
|
|
18739
|
-
if (!picked) return;
|
|
18740
|
-
const item = { assetId: picked.assetId, alt: "Logo" };
|
|
18741
|
-
void runMutation(
|
|
18742
|
-
active.sectionId,
|
|
18743
|
-
(tree) => addMediaStripItem(tree, item, active.index),
|
|
18744
|
-
{ [picked.assetId]: picked.url }
|
|
18745
|
-
).then((applied) => {
|
|
18746
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
18747
|
-
});
|
|
18748
|
-
});
|
|
18749
|
-
},
|
|
18750
|
-
onChangeImage: () => {
|
|
18751
|
-
void requestAssetPick(postToParent2).then((picked) => {
|
|
18752
|
-
if (!picked) return;
|
|
18753
|
-
void runMutation(
|
|
18754
|
-
active.sectionId,
|
|
18755
|
-
(tree) => setMediaStripItemAsset(tree, active.index, picked.assetId),
|
|
18756
|
-
{ [picked.assetId]: picked.url }
|
|
18757
|
-
);
|
|
18917
|
+
(tree) => addMediaStripItem(tree, item, active.index),
|
|
18918
|
+
{ [picked.assetId]: picked.url }
|
|
18919
|
+
).then((applied) => {
|
|
18920
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
18758
18921
|
});
|
|
18759
|
-
}
|
|
18760
|
-
|
|
18761
|
-
|
|
18762
|
-
|
|
18763
|
-
|
|
18764
|
-
|
|
18765
|
-
|
|
18766
|
-
|
|
18767
|
-
|
|
18768
|
-
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, -1)).then(
|
|
18769
|
-
(applied) => {
|
|
18770
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index - 1 });
|
|
18771
|
-
}
|
|
18772
|
-
);
|
|
18773
|
-
},
|
|
18774
|
-
onMoveRight: () => {
|
|
18775
|
-
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, 1)).then(
|
|
18776
|
-
(applied) => {
|
|
18777
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
18778
|
-
}
|
|
18922
|
+
});
|
|
18923
|
+
},
|
|
18924
|
+
onChangeImage: () => {
|
|
18925
|
+
void requestAssetPick(postToParent2).then((picked) => {
|
|
18926
|
+
if (!picked) return;
|
|
18927
|
+
void runMutation(
|
|
18928
|
+
active.sectionId,
|
|
18929
|
+
(tree) => setMediaStripItemAsset(tree, active.index, picked.assetId),
|
|
18930
|
+
{ [picked.assetId]: picked.url }
|
|
18779
18931
|
);
|
|
18780
|
-
}
|
|
18932
|
+
});
|
|
18933
|
+
},
|
|
18934
|
+
onRemoveItem: () => {
|
|
18935
|
+
void runMutation(active.sectionId, (tree) => removeMediaStripItem(tree, active.index)).then(
|
|
18936
|
+
(applied) => {
|
|
18937
|
+
if (applied) setActive(null);
|
|
18938
|
+
}
|
|
18939
|
+
);
|
|
18940
|
+
},
|
|
18941
|
+
onMoveLeft: () => {
|
|
18942
|
+
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, -1)).then(
|
|
18943
|
+
(applied) => {
|
|
18944
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index - 1 });
|
|
18945
|
+
}
|
|
18946
|
+
);
|
|
18947
|
+
},
|
|
18948
|
+
onMoveRight: () => {
|
|
18949
|
+
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, 1)).then(
|
|
18950
|
+
(applied) => {
|
|
18951
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
18952
|
+
}
|
|
18953
|
+
);
|
|
18781
18954
|
}
|
|
18782
|
-
|
|
18783
|
-
}
|
|
18784
|
-
|
|
18955
|
+
}
|
|
18956
|
+
) }),
|
|
18957
|
+
/* @__PURE__ */ jsx20(
|
|
18958
|
+
"div",
|
|
18959
|
+
{
|
|
18960
|
+
"data-ohw-bridge": "",
|
|
18961
|
+
"data-ohw-item-interaction": "",
|
|
18962
|
+
"aria-hidden": true,
|
|
18963
|
+
className: "pointer-events-none fixed rounded-[4px] px-[7px] py-[3px] font-sans text-[11px] font-medium leading-none text-primary-foreground whitespace-nowrap",
|
|
18964
|
+
style: {
|
|
18965
|
+
top: activeItemRect.top + activeItemRect.height + 10,
|
|
18966
|
+
left: activeItemRect.left - 5,
|
|
18967
|
+
background: PRIMARY3,
|
|
18968
|
+
zIndex: 2147483644
|
|
18969
|
+
},
|
|
18970
|
+
children: "Media item"
|
|
18971
|
+
}
|
|
18972
|
+
),
|
|
18973
|
+
linkOpen && /* @__PURE__ */ jsx20(
|
|
18974
|
+
LinkModal,
|
|
18975
|
+
{
|
|
18976
|
+
href: activeHref,
|
|
18977
|
+
linkTarget: activeTarget,
|
|
18978
|
+
onClose: () => setLinkOpen(false),
|
|
18979
|
+
onSave: (href, linkTarget) => {
|
|
18980
|
+
void runMutation(
|
|
18981
|
+
active.sectionId,
|
|
18982
|
+
(tree) => setMediaStripItemLink(tree, active.index, href ? { href, linkTarget } : {})
|
|
18983
|
+
);
|
|
18984
|
+
}
|
|
18985
|
+
}
|
|
18986
|
+
)
|
|
18987
|
+
] })
|
|
18785
18988
|
] });
|
|
18786
18989
|
}
|
|
18787
18990
|
|
|
18788
18991
|
// src/ui/ai-section/AiPricingCardOverlay.tsx
|
|
18789
|
-
import { useCallback as useCallback4, useEffect as useEffect7, useLayoutEffect as
|
|
18790
|
-
import { Check as
|
|
18791
|
-
import { Fragment as Fragment7, jsx as
|
|
18992
|
+
import { useCallback as useCallback4, useEffect as useEffect7, useLayoutEffect as useLayoutEffect5, useRef as useRef6, useState as useState9 } from "react";
|
|
18993
|
+
import { Check as Check3, ChevronDown as ChevronDown4, Minus as Minus2, Plus as Plus3, Star as Star2 } from "lucide-react";
|
|
18994
|
+
import { Fragment as Fragment7, jsx as jsx21, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
18792
18995
|
var PRIMARY4 = "var(--ohw-primary, #0885FE)";
|
|
18793
|
-
var
|
|
18996
|
+
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]";
|
|
18794
18997
|
function findPricingCardElement(sectionId, index) {
|
|
18795
18998
|
const sectionEl = findByInstanceId(sectionId);
|
|
18796
18999
|
if (!sectionEl) return null;
|
|
@@ -18802,7 +19005,7 @@ function findPricingCardElement(sectionId, index) {
|
|
|
18802
19005
|
}
|
|
18803
19006
|
function cardRefFromTarget(target) {
|
|
18804
19007
|
if (!(target instanceof Element)) return null;
|
|
18805
|
-
if (target.closest(
|
|
19008
|
+
if (target.closest(CHROME_SELECTOR2)) return null;
|
|
18806
19009
|
const cardEl = target.closest("[data-ohw-pricing-card]");
|
|
18807
19010
|
if (!cardEl) return null;
|
|
18808
19011
|
const sectionEl = cardEl.closest("[data-ohw-section]");
|
|
@@ -18812,21 +19015,21 @@ function cardRefFromTarget(target) {
|
|
|
18812
19015
|
if (!sectionId || Number.isNaN(index)) return null;
|
|
18813
19016
|
return { sectionId, index };
|
|
18814
19017
|
}
|
|
18815
|
-
function
|
|
19018
|
+
function sameRef2(a, b) {
|
|
18816
19019
|
return a?.sectionId === b?.sectionId && a?.index === b?.index;
|
|
18817
19020
|
}
|
|
18818
|
-
function
|
|
19021
|
+
function rectOf2(el) {
|
|
18819
19022
|
if (!el) return null;
|
|
18820
19023
|
const r2 = el.getBoundingClientRect();
|
|
18821
19024
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
18822
19025
|
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
18823
19026
|
}
|
|
18824
19027
|
function readRect3(ref) {
|
|
18825
|
-
return
|
|
19028
|
+
return rectOf2(ref && findPricingCardElement(ref.sectionId, ref.index));
|
|
18826
19029
|
}
|
|
18827
19030
|
function readGridRect(ref) {
|
|
18828
19031
|
const card = ref && findPricingCardElement(ref.sectionId, ref.index);
|
|
18829
|
-
return
|
|
19032
|
+
return rectOf2(card?.closest("[data-ohw-pricing-collection]") ?? card);
|
|
18830
19033
|
}
|
|
18831
19034
|
function useLiveCardRect(ref, grid = false) {
|
|
18832
19035
|
const [rect, setRect] = useState9(null);
|
|
@@ -18856,19 +19059,19 @@ function useLiveCardRect(ref, grid = false) {
|
|
|
18856
19059
|
}
|
|
18857
19060
|
var TOOLBAR_GRID_GAP = 52;
|
|
18858
19061
|
var TOOLBAR_GRID_GAP_MOBILE = 42;
|
|
18859
|
-
var
|
|
19062
|
+
var TOOLBAR_EDGE_MARGIN3 = 4;
|
|
18860
19063
|
function GridToolbarSlot({ gridRect, children }) {
|
|
18861
19064
|
const slotRef = useRef6(null);
|
|
18862
19065
|
const [shift, setShift] = useState9(0);
|
|
18863
19066
|
const centerX = gridRect.left + gridRect.width / 2;
|
|
18864
|
-
|
|
19067
|
+
useLayoutEffect5(() => {
|
|
18865
19068
|
const slot = slotRef.current;
|
|
18866
19069
|
if (!slot) return;
|
|
18867
19070
|
const clamp = () => {
|
|
18868
19071
|
const w = slot.offsetWidth;
|
|
18869
19072
|
if (w <= 0) return;
|
|
18870
19073
|
const half = w / 2;
|
|
18871
|
-
const clamped = Math.max(
|
|
19074
|
+
const clamped = Math.max(TOOLBAR_EDGE_MARGIN3 + half, Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN3 - half));
|
|
18872
19075
|
setShift((prev) => Math.abs(prev - (clamped - centerX)) < 0.5 ? prev : clamped - centerX);
|
|
18873
19076
|
};
|
|
18874
19077
|
clamp();
|
|
@@ -18877,7 +19080,7 @@ function GridToolbarSlot({ gridRect, children }) {
|
|
|
18877
19080
|
return () => ro.disconnect();
|
|
18878
19081
|
}, [centerX, children]);
|
|
18879
19082
|
const mobile = window.innerWidth <= 480;
|
|
18880
|
-
return /* @__PURE__ */
|
|
19083
|
+
return /* @__PURE__ */ jsx21(
|
|
18881
19084
|
"div",
|
|
18882
19085
|
{
|
|
18883
19086
|
ref: slotRef,
|
|
@@ -18912,7 +19115,7 @@ function requestValidateTree2(postToParent2, tree) {
|
|
|
18912
19115
|
});
|
|
18913
19116
|
}
|
|
18914
19117
|
function StyleSwatch({ style }) {
|
|
18915
|
-
return /* @__PURE__ */
|
|
19118
|
+
return /* @__PURE__ */ jsx21(
|
|
18916
19119
|
"span",
|
|
18917
19120
|
{
|
|
18918
19121
|
"aria-hidden": true,
|
|
@@ -18926,35 +19129,35 @@ function StyleSwatch({ style }) {
|
|
|
18926
19129
|
);
|
|
18927
19130
|
}
|
|
18928
19131
|
function ButtonGlyph() {
|
|
18929
|
-
return /* @__PURE__ */
|
|
18930
|
-
/* @__PURE__ */
|
|
18931
|
-
/* @__PURE__ */
|
|
19132
|
+
return /* @__PURE__ */ jsxs12("svg", { width: "18", height: "12", viewBox: "0 0 18 12", fill: "none", "aria-hidden": true, style: { pointerEvents: "none" }, children: [
|
|
19133
|
+
/* @__PURE__ */ jsx21("rect", { x: "0.75", y: "0.75", width: "16.5", height: "10.5", rx: "3", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
19134
|
+
/* @__PURE__ */ jsx21("path", { d: "M5.5 6H12.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
|
|
18932
19135
|
] });
|
|
18933
19136
|
}
|
|
18934
19137
|
function FeatureGlyph({ mode }) {
|
|
18935
|
-
return /* @__PURE__ */
|
|
18936
|
-
/* @__PURE__ */
|
|
18937
|
-
/* @__PURE__ */
|
|
18938
|
-
/* @__PURE__ */
|
|
18939
|
-
/* @__PURE__ */
|
|
18940
|
-
/* @__PURE__ */
|
|
18941
|
-
mode === "add" && /* @__PURE__ */
|
|
19138
|
+
return /* @__PURE__ */ jsxs12("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "none", "aria-hidden": true, style: { pointerEvents: "none" }, children: [
|
|
19139
|
+
/* @__PURE__ */ jsx21("circle", { cx: "8", cy: "8", r: "7.25", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
19140
|
+
/* @__PURE__ */ jsx21("path", { d: "M5 8.2L7.2 10.3L11 6", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
19141
|
+
/* @__PURE__ */ jsx21("circle", { cx: "13.5", cy: "13.5", r: "4.25", fill: "var(--ohw-background, #ffffff)", stroke: "var(--ohw-background, #ffffff)", strokeWidth: "1" }),
|
|
19142
|
+
/* @__PURE__ */ jsx21("circle", { cx: "13.5", cy: "13.5", r: "3.75", fill: "var(--ohw-background, #ffffff)", stroke: PRIMARY4, strokeWidth: "1" }),
|
|
19143
|
+
/* @__PURE__ */ jsx21("path", { d: "M11.5 13.5H15.5", stroke: PRIMARY4, strokeWidth: "1.5", strokeLinecap: "round" }),
|
|
19144
|
+
mode === "add" && /* @__PURE__ */ jsx21("path", { d: "M13.5 11.5V15.5", stroke: PRIMARY4, strokeWidth: "1.5", strokeLinecap: "round" })
|
|
18942
19145
|
] });
|
|
18943
19146
|
}
|
|
18944
|
-
function
|
|
19147
|
+
function ToolbarAction2({
|
|
18945
19148
|
label,
|
|
18946
19149
|
onClick,
|
|
18947
19150
|
disabled = false,
|
|
18948
19151
|
children
|
|
18949
19152
|
}) {
|
|
18950
|
-
const button = /* @__PURE__ */
|
|
18951
|
-
return /* @__PURE__ */
|
|
18952
|
-
/* @__PURE__ */
|
|
18953
|
-
/* @__PURE__ */
|
|
19153
|
+
const button = /* @__PURE__ */ jsx21(CustomToolbarButton, { type: "button", "aria-label": label, disabled, onClick, className: "size-8", children });
|
|
19154
|
+
return /* @__PURE__ */ jsxs12(Tooltip, { children: [
|
|
19155
|
+
/* @__PURE__ */ jsx21(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ jsx21("span", { className: "inline-flex", children: button }) : button }),
|
|
19156
|
+
/* @__PURE__ */ jsx21(TooltipContent, { side: "bottom", sideOffset: 8, children: label })
|
|
18954
19157
|
] });
|
|
18955
19158
|
}
|
|
18956
|
-
function
|
|
18957
|
-
return /* @__PURE__ */
|
|
19159
|
+
function ToolbarSeparator2() {
|
|
19160
|
+
return /* @__PURE__ */ jsx21("span", { "aria-hidden": true, className: "mx-0.5 block h-6 w-px shrink-0 bg-border" });
|
|
18958
19161
|
}
|
|
18959
19162
|
function CardStyleMenu({
|
|
18960
19163
|
value,
|
|
@@ -18962,7 +19165,7 @@ function CardStyleMenu({
|
|
|
18962
19165
|
disabled = false
|
|
18963
19166
|
}) {
|
|
18964
19167
|
const current = PRICING_CARD_STYLES.find((s) => s.value === value) ?? PRICING_CARD_STYLES[0];
|
|
18965
|
-
const trigger = /* @__PURE__ */
|
|
19168
|
+
const trigger = /* @__PURE__ */ jsxs12(
|
|
18966
19169
|
"button",
|
|
18967
19170
|
{
|
|
18968
19171
|
type: "button",
|
|
@@ -18973,28 +19176,28 @@ function CardStyleMenu({
|
|
|
18973
19176
|
disabled && "cursor-not-allowed opacity-40 hover:bg-transparent"
|
|
18974
19177
|
),
|
|
18975
19178
|
children: [
|
|
18976
|
-
/* @__PURE__ */
|
|
18977
|
-
/* @__PURE__ */
|
|
18978
|
-
/* @__PURE__ */
|
|
19179
|
+
/* @__PURE__ */ jsx21(StyleSwatch, { style: current.value }),
|
|
19180
|
+
/* @__PURE__ */ jsx21("span", { className: "flex-1 text-left", children: current.label }),
|
|
19181
|
+
/* @__PURE__ */ jsx21(ChevronDown4, { size: 16, style: { pointerEvents: "none" } })
|
|
18979
19182
|
]
|
|
18980
19183
|
}
|
|
18981
19184
|
);
|
|
18982
19185
|
if (disabled) {
|
|
18983
|
-
return /* @__PURE__ */
|
|
18984
|
-
/* @__PURE__ */
|
|
18985
|
-
/* @__PURE__ */
|
|
18986
|
-
/* @__PURE__ */
|
|
18987
|
-
/* @__PURE__ */
|
|
19186
|
+
return /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19187
|
+
/* @__PURE__ */ jsx21("span", { className: "text-xs text-muted-foreground opacity-50", children: "Card style" }),
|
|
19188
|
+
/* @__PURE__ */ jsxs12(Tooltip, { children: [
|
|
19189
|
+
/* @__PURE__ */ jsx21(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx21("span", { className: "inline-flex", children: trigger }) }),
|
|
19190
|
+
/* @__PURE__ */ jsx21(TooltipContent, { side: "bottom", sideOffset: 8, children: "Mark as featured to edit card style" })
|
|
18988
19191
|
] })
|
|
18989
19192
|
] });
|
|
18990
19193
|
}
|
|
18991
|
-
return /* @__PURE__ */
|
|
18992
|
-
/* @__PURE__ */
|
|
18993
|
-
/* @__PURE__ */
|
|
18994
|
-
/* @__PURE__ */
|
|
18995
|
-
/* @__PURE__ */
|
|
19194
|
+
return /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19195
|
+
/* @__PURE__ */ jsx21("span", { className: "text-xs text-muted-foreground", children: "Card style" }),
|
|
19196
|
+
/* @__PURE__ */ jsxs12(DropdownMenu, { modal: false, children: [
|
|
19197
|
+
/* @__PURE__ */ jsx21(DropdownMenuTrigger, { asChild: true, children: trigger }),
|
|
19198
|
+
/* @__PURE__ */ jsx21(DropdownMenuContent, { align: "end", sideOffset: 8, className: "w-[152px] min-w-[152px] p-1", children: PRICING_CARD_STYLES.map((style) => {
|
|
18996
19199
|
const selected = style.value === value;
|
|
18997
|
-
return /* @__PURE__ */
|
|
19200
|
+
return /* @__PURE__ */ jsxs12(
|
|
18998
19201
|
DropdownMenuItem,
|
|
18999
19202
|
{
|
|
19000
19203
|
role: "menuitemradio",
|
|
@@ -19002,9 +19205,9 @@ function CardStyleMenu({
|
|
|
19002
19205
|
onSelect: () => onChange(style.value),
|
|
19003
19206
|
className: cn("grid grid-cols-[18px_1fr_16px] gap-2 py-2 pl-2 pr-2 text-[13px]", selected && "bg-muted"),
|
|
19004
19207
|
children: [
|
|
19005
|
-
/* @__PURE__ */
|
|
19006
|
-
/* @__PURE__ */
|
|
19007
|
-
selected && /* @__PURE__ */
|
|
19208
|
+
/* @__PURE__ */ jsx21(StyleSwatch, { style: style.value }),
|
|
19209
|
+
/* @__PURE__ */ jsx21("span", { children: style.label }),
|
|
19210
|
+
selected && /* @__PURE__ */ jsx21(Check3, { size: 16, className: "text-bridge-primary" })
|
|
19008
19211
|
]
|
|
19009
19212
|
},
|
|
19010
19213
|
style.value
|
|
@@ -19034,7 +19237,7 @@ function PricingCardToolbar({
|
|
|
19034
19237
|
const style = pricingCardStyle(entry.tree, index);
|
|
19035
19238
|
const featuredTag = pricingCardFeaturedTag(entry.tree, index);
|
|
19036
19239
|
const mobile = window.innerWidth <= 480;
|
|
19037
|
-
return /* @__PURE__ */
|
|
19240
|
+
return /* @__PURE__ */ jsx21(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs12(
|
|
19038
19241
|
"div",
|
|
19039
19242
|
{
|
|
19040
19243
|
"data-ohw-bridge": "",
|
|
@@ -19046,7 +19249,7 @@ function PricingCardToolbar({
|
|
|
19046
19249
|
),
|
|
19047
19250
|
style: { maxWidth: mobile ? "calc(100vw - 24px)" : void 0 },
|
|
19048
19251
|
children: [
|
|
19049
|
-
/* @__PURE__ */
|
|
19252
|
+
/* @__PURE__ */ jsxs12(
|
|
19050
19253
|
"div",
|
|
19051
19254
|
{
|
|
19052
19255
|
className: cn(
|
|
@@ -19055,8 +19258,8 @@ function PricingCardToolbar({
|
|
|
19055
19258
|
mobile ? "flex-wrap justify-center" : "flex-nowrap"
|
|
19056
19259
|
),
|
|
19057
19260
|
children: [
|
|
19058
|
-
/* @__PURE__ */
|
|
19059
|
-
/* @__PURE__ */
|
|
19261
|
+
/* @__PURE__ */ jsxs12(Tooltip, { children: [
|
|
19262
|
+
/* @__PURE__ */ jsx21(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx21(
|
|
19060
19263
|
CustomToolbarButton,
|
|
19061
19264
|
{
|
|
19062
19265
|
type: "button",
|
|
@@ -19064,7 +19267,7 @@ function PricingCardToolbar({
|
|
|
19064
19267
|
"aria-pressed": featuredTag,
|
|
19065
19268
|
onClick: () => onSetFeaturedTag(!featuredTag),
|
|
19066
19269
|
className: "group size-8",
|
|
19067
|
-
children: /* @__PURE__ */
|
|
19270
|
+
children: /* @__PURE__ */ jsx21(
|
|
19068
19271
|
Star2,
|
|
19069
19272
|
{
|
|
19070
19273
|
size: 16,
|
|
@@ -19079,25 +19282,25 @@ function PricingCardToolbar({
|
|
|
19079
19282
|
)
|
|
19080
19283
|
}
|
|
19081
19284
|
) }),
|
|
19082
|
-
/* @__PURE__ */
|
|
19285
|
+
/* @__PURE__ */ jsx21(TooltipContent, { side: "bottom", sideOffset: 8, children: featuredTag ? "Unmark featured" : "Mark as featured" })
|
|
19083
19286
|
] }),
|
|
19084
|
-
/* @__PURE__ */
|
|
19085
|
-
/* @__PURE__ */
|
|
19086
|
-
/* @__PURE__ */
|
|
19087
|
-
/* @__PURE__ */
|
|
19088
|
-
/* @__PURE__ */
|
|
19089
|
-
/* @__PURE__ */
|
|
19090
|
-
/* @__PURE__ */
|
|
19287
|
+
/* @__PURE__ */ jsx21(ToolbarSeparator2, {}),
|
|
19288
|
+
/* @__PURE__ */ jsx21(CardStyleMenu, { value: style, onChange: onSetStyle, disabled: !featuredTag }),
|
|
19289
|
+
/* @__PURE__ */ jsx21(ToolbarSeparator2, {}),
|
|
19290
|
+
/* @__PURE__ */ jsx21(ToolbarAction2, { label: "Add button", onClick: onAddButton, disabled: buttonCount >= 2, children: /* @__PURE__ */ jsx21(ButtonGlyph, {}) }),
|
|
19291
|
+
/* @__PURE__ */ jsx21(ToolbarAction2, { label: "Remove button", onClick: onRemoveButton, disabled: buttonCount === 0, children: /* @__PURE__ */ jsxs12("span", { className: "relative inline-flex", children: [
|
|
19292
|
+
/* @__PURE__ */ jsx21(ButtonGlyph, {}),
|
|
19293
|
+
/* @__PURE__ */ jsx21(Minus2, { size: 10, strokeWidth: 2.5, className: "absolute -right-1.5 -top-1.5 rounded-full bg-background text-bridge-primary" })
|
|
19091
19294
|
] }) }),
|
|
19092
|
-
/* @__PURE__ */
|
|
19093
|
-
/* @__PURE__ */
|
|
19094
|
-
/* @__PURE__ */
|
|
19095
|
-
/* @__PURE__ */
|
|
19096
|
-
/* @__PURE__ */
|
|
19295
|
+
/* @__PURE__ */ jsx21(ToolbarAction2, { label: "Add feature", onClick: onAddFeature, disabled: featureCount >= 10, children: /* @__PURE__ */ jsx21(FeatureGlyph, { mode: "add" }) }),
|
|
19296
|
+
/* @__PURE__ */ jsx21(ToolbarAction2, { label: "Remove feature", onClick: onRemoveFeature, disabled: featureCount <= 1, children: /* @__PURE__ */ jsx21(FeatureGlyph, { mode: "remove" }) }),
|
|
19297
|
+
/* @__PURE__ */ jsx21(ToolbarSeparator2, {}),
|
|
19298
|
+
/* @__PURE__ */ jsx21(ToolbarAction2, { label: "Add tier", onClick: onAddTier, disabled: collectionCount >= 4, children: /* @__PURE__ */ jsx21(Plus3, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19299
|
+
/* @__PURE__ */ jsx21(ToolbarAction2, { label: "Remove tier", onClick: onRemoveTier, disabled: collectionCount <= 1, children: /* @__PURE__ */ jsx21(Minus2, { size: 16, style: { pointerEvents: "none" } }) })
|
|
19097
19300
|
]
|
|
19098
19301
|
}
|
|
19099
19302
|
),
|
|
19100
|
-
error && /* @__PURE__ */
|
|
19303
|
+
error && /* @__PURE__ */ jsx21("div", { className: "max-w-[260px] rounded-md bg-background px-2 py-1 text-center text-[11px] text-destructive shadow-sm", children: error })
|
|
19101
19304
|
]
|
|
19102
19305
|
}
|
|
19103
19306
|
) });
|
|
@@ -19131,7 +19334,7 @@ function AiPricingCardOverlay({
|
|
|
19131
19334
|
const overEditable = Boolean(t?.closest?.("[data-ohw-editable], [data-ohw-role], a, button"));
|
|
19132
19335
|
setHover((prev) => {
|
|
19133
19336
|
const next = ref && !overEditable ? ref : null;
|
|
19134
|
-
return
|
|
19337
|
+
return sameRef2(prev, next) ? prev : next;
|
|
19135
19338
|
});
|
|
19136
19339
|
};
|
|
19137
19340
|
const onLeave = () => setHover(null);
|
|
@@ -19146,10 +19349,10 @@ function AiPricingCardOverlay({
|
|
|
19146
19349
|
const onClick = (e) => {
|
|
19147
19350
|
const t = e.target;
|
|
19148
19351
|
if (!(t instanceof Element)) return;
|
|
19149
|
-
if (t.closest(
|
|
19352
|
+
if (t.closest(CHROME_SELECTOR2)) return;
|
|
19150
19353
|
const ref = cardRefFromTarget(t);
|
|
19151
|
-
setActive((prev) =>
|
|
19152
|
-
if (!ref || !
|
|
19354
|
+
setActive((prev) => sameRef2(prev, ref) ? prev : ref);
|
|
19355
|
+
if (!ref || !sameRef2(activeRef.current, ref)) setError(null);
|
|
19153
19356
|
};
|
|
19154
19357
|
document.addEventListener("click", onClick, true);
|
|
19155
19358
|
return () => document.removeEventListener("click", onClick, true);
|
|
@@ -19214,12 +19417,12 @@ function AiPricingCardOverlay({
|
|
|
19214
19417
|
const activeEntry = active ? findEntry(active.sectionId) : null;
|
|
19215
19418
|
const activeCardRect = useLiveCardRect(active);
|
|
19216
19419
|
const activeGridRect = useLiveCardRect(active, true);
|
|
19217
|
-
const hoverRect = useLiveCardRect(hover && !
|
|
19218
|
-
return /* @__PURE__ */
|
|
19219
|
-
hoverRect && /* @__PURE__ */
|
|
19220
|
-
activeCardRect && activeGridRect && active && activeEntry && /* @__PURE__ */
|
|
19221
|
-
/* @__PURE__ */
|
|
19222
|
-
/* @__PURE__ */
|
|
19420
|
+
const hoverRect = useLiveCardRect(hover && !sameRef2(hover, active) ? hover : null);
|
|
19421
|
+
return /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
19422
|
+
hoverRect && /* @__PURE__ */ jsx21(ItemInteractionLayer, { rect: hoverRect, state: "hover" }),
|
|
19423
|
+
activeCardRect && activeGridRect && active && activeEntry && /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
19424
|
+
/* @__PURE__ */ jsx21(ItemInteractionLayer, { rect: activeCardRect, state: "active-top" }),
|
|
19425
|
+
/* @__PURE__ */ jsx21(GridToolbarSlot, { gridRect: activeGridRect, children: /* @__PURE__ */ jsx21(
|
|
19223
19426
|
PricingCardToolbar,
|
|
19224
19427
|
{
|
|
19225
19428
|
entry: activeEntry,
|
|
@@ -19247,7 +19450,7 @@ function AiPricingCardOverlay({
|
|
|
19247
19450
|
onRemoveFeature: () => runMutation(active.sectionId, (tree) => removePricingCardFeature(tree, active.index))
|
|
19248
19451
|
}
|
|
19249
19452
|
) }),
|
|
19250
|
-
/* @__PURE__ */
|
|
19453
|
+
/* @__PURE__ */ jsx21(
|
|
19251
19454
|
"div",
|
|
19252
19455
|
{
|
|
19253
19456
|
"data-ohw-bridge": "",
|
|
@@ -19340,10 +19543,10 @@ function extractYouTubeId(input) {
|
|
|
19340
19543
|
}
|
|
19341
19544
|
|
|
19342
19545
|
// src/ui/ai-section/AiVideoOverlay.tsx
|
|
19343
|
-
import { Fragment as Fragment8, jsx as
|
|
19546
|
+
import { Fragment as Fragment8, jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
19344
19547
|
var PRIMARY5 = "#0885FE";
|
|
19345
|
-
var
|
|
19346
|
-
var
|
|
19548
|
+
var OHW_BLUE = `var(--ohw-primary, ${PRIMARY5})`;
|
|
19549
|
+
var OHW_BLUE_DARK = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY5}) 60%, #000000)`;
|
|
19347
19550
|
function findVideoBlockElement(sectionId, path) {
|
|
19348
19551
|
const sectionEl = findByInstanceId(sectionId);
|
|
19349
19552
|
if (!sectionEl) return null;
|
|
@@ -19403,12 +19606,12 @@ function requestValidateTree3(postToParent2, tree) {
|
|
|
19403
19606
|
postToParent2({ type: "ow:ai-validate-tree-request", id, tree });
|
|
19404
19607
|
});
|
|
19405
19608
|
}
|
|
19406
|
-
function
|
|
19609
|
+
function Pill({
|
|
19407
19610
|
label,
|
|
19408
19611
|
onClick,
|
|
19409
19612
|
disabled
|
|
19410
19613
|
}) {
|
|
19411
|
-
return /* @__PURE__ */
|
|
19614
|
+
return /* @__PURE__ */ jsx22(
|
|
19412
19615
|
"button",
|
|
19413
19616
|
{
|
|
19414
19617
|
type: "button",
|
|
@@ -19424,7 +19627,7 @@ function Pill2({
|
|
|
19424
19627
|
border: "none",
|
|
19425
19628
|
cursor: disabled ? "default" : "pointer",
|
|
19426
19629
|
background: "#ffffff",
|
|
19427
|
-
color:
|
|
19630
|
+
color: OHW_BLUE_DARK,
|
|
19428
19631
|
opacity: disabled ? 0.4 : 1,
|
|
19429
19632
|
fontSize: 12,
|
|
19430
19633
|
lineHeight: "16px",
|
|
@@ -19467,8 +19670,8 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
19467
19670
|
onCommit(id);
|
|
19468
19671
|
}
|
|
19469
19672
|
};
|
|
19470
|
-
return /* @__PURE__ */
|
|
19471
|
-
/* @__PURE__ */
|
|
19673
|
+
return /* @__PURE__ */ jsxs13("div", { style: { display: "flex", flexDirection: "column", gap: 4, width: "100%", maxWidth: 280 }, children: [
|
|
19674
|
+
/* @__PURE__ */ jsxs13(
|
|
19472
19675
|
"div",
|
|
19473
19676
|
{
|
|
19474
19677
|
style: {
|
|
@@ -19484,12 +19687,12 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
19484
19687
|
boxShadow: invalid ? "inset 0 0 0 1.5px #EF4444" : "none"
|
|
19485
19688
|
},
|
|
19486
19689
|
children: [
|
|
19487
|
-
/* @__PURE__ */
|
|
19690
|
+
/* @__PURE__ */ jsx22(
|
|
19488
19691
|
"span",
|
|
19489
19692
|
{
|
|
19490
19693
|
style: {
|
|
19491
19694
|
flex: "0 0 auto",
|
|
19492
|
-
color:
|
|
19695
|
+
color: OHW_BLUE_DARK,
|
|
19493
19696
|
fontSize: 10,
|
|
19494
19697
|
lineHeight: "16px",
|
|
19495
19698
|
fontWeight: 700,
|
|
@@ -19499,7 +19702,7 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
19499
19702
|
children: "Video"
|
|
19500
19703
|
}
|
|
19501
19704
|
),
|
|
19502
|
-
/* @__PURE__ */
|
|
19705
|
+
/* @__PURE__ */ jsx22(
|
|
19503
19706
|
"input",
|
|
19504
19707
|
{
|
|
19505
19708
|
type: "text",
|
|
@@ -19536,7 +19739,7 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
19536
19739
|
]
|
|
19537
19740
|
}
|
|
19538
19741
|
),
|
|
19539
|
-
invalid && /* @__PURE__ */
|
|
19742
|
+
invalid && /* @__PURE__ */ jsx22("div", { style: { color: "#FCA5A5", fontSize: 11, textAlign: "center" }, children: "That doesn't look like a YouTube link \u2014 try pasting the video URL again." })
|
|
19540
19743
|
] });
|
|
19541
19744
|
}
|
|
19542
19745
|
function VideoToolbar({
|
|
@@ -19546,7 +19749,7 @@ function VideoToolbar({
|
|
|
19546
19749
|
onSetVideoId,
|
|
19547
19750
|
onRemove
|
|
19548
19751
|
}) {
|
|
19549
|
-
return /* @__PURE__ */
|
|
19752
|
+
return /* @__PURE__ */ jsxs13(
|
|
19550
19753
|
"div",
|
|
19551
19754
|
{
|
|
19552
19755
|
"data-ohw-bridge": "",
|
|
@@ -19558,7 +19761,7 @@ function VideoToolbar({
|
|
|
19558
19761
|
gap: 6,
|
|
19559
19762
|
alignItems: "center",
|
|
19560
19763
|
width: 280,
|
|
19561
|
-
background:
|
|
19764
|
+
background: OHW_BLUE,
|
|
19562
19765
|
padding: 8,
|
|
19563
19766
|
borderRadius: 12,
|
|
19564
19767
|
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
@@ -19566,9 +19769,9 @@ function VideoToolbar({
|
|
|
19566
19769
|
opacity: pending ? 0.6 : 1
|
|
19567
19770
|
},
|
|
19568
19771
|
children: [
|
|
19569
|
-
/* @__PURE__ */
|
|
19570
|
-
/* @__PURE__ */
|
|
19571
|
-
error && /* @__PURE__ */
|
|
19772
|
+
/* @__PURE__ */ jsx22(VideoUrlInput, { value: videoId, onCommit: onSetVideoId }),
|
|
19773
|
+
/* @__PURE__ */ jsx22(Pill, { label: "Remove video", onClick: onRemove, disabled: !videoId }),
|
|
19774
|
+
error && /* @__PURE__ */ jsx22("div", { style: { color: "#FCA5A5", fontSize: 11, maxWidth: 220, textAlign: "center" }, children: error })
|
|
19572
19775
|
]
|
|
19573
19776
|
}
|
|
19574
19777
|
);
|
|
@@ -19688,8 +19891,8 @@ function AiVideoOverlay({
|
|
|
19688
19891
|
const activeBlockRect = useLiveBlockRect(active);
|
|
19689
19892
|
const TOOLBAR_APPROX_H = 90;
|
|
19690
19893
|
const toolbarState = activeBlockRect && activeBlockRect.top < TOOLBAR_APPROX_H ? "active-bottom" : "active-top";
|
|
19691
|
-
return /* @__PURE__ */
|
|
19692
|
-
hoverHandleRect && hover && /* @__PURE__ */
|
|
19894
|
+
return /* @__PURE__ */ jsxs13(Fragment8, { children: [
|
|
19895
|
+
hoverHandleRect && hover && /* @__PURE__ */ jsx22(
|
|
19693
19896
|
"button",
|
|
19694
19897
|
{
|
|
19695
19898
|
type: "button",
|
|
@@ -19717,15 +19920,15 @@ function AiVideoOverlay({
|
|
|
19717
19920
|
fontSize: 14,
|
|
19718
19921
|
fontWeight: 700
|
|
19719
19922
|
},
|
|
19720
|
-
children: /* @__PURE__ */
|
|
19923
|
+
children: /* @__PURE__ */ jsx22(Star3, { size: 14, style: { pointerEvents: "none" } })
|
|
19721
19924
|
}
|
|
19722
19925
|
),
|
|
19723
|
-
activeBlockRect && active && activeEntry && /* @__PURE__ */
|
|
19926
|
+
activeBlockRect && active && activeEntry && /* @__PURE__ */ jsx22(
|
|
19724
19927
|
ItemInteractionLayer,
|
|
19725
19928
|
{
|
|
19726
19929
|
rect: activeBlockRect,
|
|
19727
19930
|
state: toolbarState,
|
|
19728
|
-
toolbar: /* @__PURE__ */
|
|
19931
|
+
toolbar: /* @__PURE__ */ jsx22(
|
|
19729
19932
|
VideoToolbar,
|
|
19730
19933
|
{
|
|
19731
19934
|
videoId: videoIdAt(activeEntry.tree, active.path),
|
|
@@ -19800,10 +20003,10 @@ function setCarouselAutoplay(tree, on) {
|
|
|
19800
20003
|
}
|
|
19801
20004
|
|
|
19802
20005
|
// src/ui/ai-section/AiFadeCarouselOverlay.tsx
|
|
19803
|
-
import { Fragment as Fragment9, jsx as
|
|
20006
|
+
import { Fragment as Fragment9, jsx as jsx23, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
19804
20007
|
var PRIMARY6 = "#0885FE";
|
|
19805
|
-
var
|
|
19806
|
-
var
|
|
20008
|
+
var OHW_BLUE2 = `var(--ohw-primary, ${PRIMARY6})`;
|
|
20009
|
+
var OHW_BLUE_DARK2 = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY6}) 60%, #000000)`;
|
|
19807
20010
|
function findCarouselItemElement(sectionId, index) {
|
|
19808
20011
|
const sectionEl = findByInstanceId(sectionId);
|
|
19809
20012
|
if (!sectionEl) return null;
|
|
@@ -19882,8 +20085,8 @@ function requestAssetPick2(postToParent2) {
|
|
|
19882
20085
|
postToParent2({ type: "ow:asset-pick", id });
|
|
19883
20086
|
});
|
|
19884
20087
|
}
|
|
19885
|
-
function
|
|
19886
|
-
return /* @__PURE__ */
|
|
20088
|
+
function Pill2({ label, onClick, disabled }) {
|
|
20089
|
+
return /* @__PURE__ */ jsx23(
|
|
19887
20090
|
"button",
|
|
19888
20091
|
{
|
|
19889
20092
|
type: "button",
|
|
@@ -19899,7 +20102,7 @@ function Pill3({ label, onClick, disabled }) {
|
|
|
19899
20102
|
border: "none",
|
|
19900
20103
|
cursor: disabled ? "default" : "pointer",
|
|
19901
20104
|
background: "#ffffff",
|
|
19902
|
-
color:
|
|
20105
|
+
color: OHW_BLUE_DARK2,
|
|
19903
20106
|
opacity: disabled ? 0.4 : 1,
|
|
19904
20107
|
fontSize: 12,
|
|
19905
20108
|
lineHeight: "16px",
|
|
@@ -19917,7 +20120,7 @@ function TogglePill({
|
|
|
19917
20120
|
onToggle,
|
|
19918
20121
|
disabled
|
|
19919
20122
|
}) {
|
|
19920
|
-
return /* @__PURE__ */
|
|
20123
|
+
return /* @__PURE__ */ jsxs14(
|
|
19921
20124
|
"button",
|
|
19922
20125
|
{
|
|
19923
20126
|
type: "button",
|
|
@@ -19936,7 +20139,7 @@ function TogglePill({
|
|
|
19936
20139
|
border: "none",
|
|
19937
20140
|
cursor: disabled ? "default" : "pointer",
|
|
19938
20141
|
background: "#ffffff",
|
|
19939
|
-
color:
|
|
20142
|
+
color: OHW_BLUE_DARK2,
|
|
19940
20143
|
opacity: disabled ? 0.4 : 1,
|
|
19941
20144
|
fontSize: 12,
|
|
19942
20145
|
lineHeight: "16px",
|
|
@@ -19946,7 +20149,7 @@ function TogglePill({
|
|
|
19946
20149
|
},
|
|
19947
20150
|
children: [
|
|
19948
20151
|
label,
|
|
19949
|
-
/* @__PURE__ */
|
|
20152
|
+
/* @__PURE__ */ jsx23(
|
|
19950
20153
|
"span",
|
|
19951
20154
|
{
|
|
19952
20155
|
"aria-hidden": true,
|
|
@@ -19959,10 +20162,10 @@ function TogglePill({
|
|
|
19959
20162
|
// Off is a grey track, not a washed-out blue: the pill's own white background already
|
|
19960
20163
|
// carries the brand colour in the text, and a pale blue track next to it read as
|
|
19961
20164
|
// "disabled control" rather than "switch that is off".
|
|
19962
|
-
background: on ?
|
|
20165
|
+
background: on ? OHW_BLUE_DARK2 : "#CBD5E1",
|
|
19963
20166
|
transition: "background 120ms ease"
|
|
19964
20167
|
},
|
|
19965
|
-
children: /* @__PURE__ */
|
|
20168
|
+
children: /* @__PURE__ */ jsx23(
|
|
19966
20169
|
"span",
|
|
19967
20170
|
{
|
|
19968
20171
|
style: {
|
|
@@ -19991,7 +20194,7 @@ function CarouselSlideToolbar({
|
|
|
19991
20194
|
onChangeImage,
|
|
19992
20195
|
onToggleAutoplay
|
|
19993
20196
|
}) {
|
|
19994
|
-
return /* @__PURE__ */
|
|
20197
|
+
return /* @__PURE__ */ jsxs14(
|
|
19995
20198
|
"div",
|
|
19996
20199
|
{
|
|
19997
20200
|
"data-ohw-bridge": "",
|
|
@@ -20002,7 +20205,7 @@ function CarouselSlideToolbar({
|
|
|
20002
20205
|
flexDirection: "column",
|
|
20003
20206
|
gap: 6,
|
|
20004
20207
|
alignItems: "center",
|
|
20005
|
-
background:
|
|
20208
|
+
background: OHW_BLUE2,
|
|
20006
20209
|
padding: 8,
|
|
20007
20210
|
borderRadius: 12,
|
|
20008
20211
|
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
@@ -20014,11 +20217,11 @@ function CarouselSlideToolbar({
|
|
|
20014
20217
|
pointerEvents: pending ? "none" : "auto"
|
|
20015
20218
|
},
|
|
20016
20219
|
children: [
|
|
20017
|
-
/* @__PURE__ */
|
|
20018
|
-
/* @__PURE__ */
|
|
20019
|
-
/* @__PURE__ */
|
|
20220
|
+
/* @__PURE__ */ jsxs14("div", { style: { display: "flex", gap: 6, alignItems: "center" }, children: [
|
|
20221
|
+
/* @__PURE__ */ jsx23(Pill2, { label: "Change Image", onClick: onChangeImage }),
|
|
20222
|
+
/* @__PURE__ */ jsx23(TogglePill, { label: "Autoplay", on: autoplay, onToggle: onToggleAutoplay })
|
|
20020
20223
|
] }),
|
|
20021
|
-
error && /* @__PURE__ */
|
|
20224
|
+
error && /* @__PURE__ */ jsx23("div", { style: { color: "#FCA5A5", fontSize: 11, maxWidth: 220, textAlign: "center" }, children: error })
|
|
20022
20225
|
]
|
|
20023
20226
|
}
|
|
20024
20227
|
);
|
|
@@ -20158,8 +20361,8 @@ function AiFadeCarouselOverlay({
|
|
|
20158
20361
|
const activeItemRect = useLiveItemRect2(active);
|
|
20159
20362
|
const TOOLBAR_APPROX_H = 90;
|
|
20160
20363
|
const toolbarState = activeItemRect && activeItemRect.top < TOOLBAR_APPROX_H ? "active-bottom" : "active-top";
|
|
20161
|
-
return /* @__PURE__ */
|
|
20162
|
-
hoverHandleRect && hover && /* @__PURE__ */
|
|
20364
|
+
return /* @__PURE__ */ jsxs14(Fragment9, { children: [
|
|
20365
|
+
hoverHandleRect && hover && /* @__PURE__ */ jsx23(
|
|
20163
20366
|
"button",
|
|
20164
20367
|
{
|
|
20165
20368
|
type: "button",
|
|
@@ -20188,10 +20391,10 @@ function AiFadeCarouselOverlay({
|
|
|
20188
20391
|
fontSize: 14,
|
|
20189
20392
|
fontWeight: 700
|
|
20190
20393
|
},
|
|
20191
|
-
children: /* @__PURE__ */
|
|
20394
|
+
children: /* @__PURE__ */ jsx23(Star4, { size: 14, style: { pointerEvents: "none" } })
|
|
20192
20395
|
}
|
|
20193
20396
|
),
|
|
20194
|
-
swapping && /* @__PURE__ */
|
|
20397
|
+
swapping && /* @__PURE__ */ jsx23(
|
|
20195
20398
|
"div",
|
|
20196
20399
|
{
|
|
20197
20400
|
ref: skeletonRef,
|
|
@@ -20209,15 +20412,15 @@ function AiFadeCarouselOverlay({
|
|
|
20209
20412
|
zIndex: 2147483646,
|
|
20210
20413
|
pointerEvents: "none"
|
|
20211
20414
|
},
|
|
20212
|
-
children: /* @__PURE__ */
|
|
20415
|
+
children: /* @__PURE__ */ jsx23("style", { children: MEDIA_SKELETON_CSS })
|
|
20213
20416
|
}
|
|
20214
20417
|
),
|
|
20215
|
-
activeItemRect && active && activeEntry && /* @__PURE__ */
|
|
20418
|
+
activeItemRect && active && activeEntry && /* @__PURE__ */ jsx23(
|
|
20216
20419
|
ItemInteractionLayer,
|
|
20217
20420
|
{
|
|
20218
20421
|
rect: activeItemRect,
|
|
20219
20422
|
state: toolbarState,
|
|
20220
|
-
toolbar: /* @__PURE__ */
|
|
20423
|
+
toolbar: /* @__PURE__ */ jsx23(
|
|
20221
20424
|
CarouselSlideToolbar,
|
|
20222
20425
|
{
|
|
20223
20426
|
pending,
|
|
@@ -20570,118 +20773,11 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
|
|
|
20570
20773
|
// src/ui/link-modal/LinkPopover.tsx
|
|
20571
20774
|
import { useEffect as useEffect13 } from "react";
|
|
20572
20775
|
|
|
20573
|
-
// src/ui/dialog.tsx
|
|
20574
|
-
import * as React9 from "react";
|
|
20575
|
-
import { Dialog as DialogPrimitive } from "radix-ui";
|
|
20576
|
-
import { X as X2 } from "lucide-react";
|
|
20577
|
-
import { jsx as jsx23, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
20578
|
-
function Dialog2({
|
|
20579
|
-
...props
|
|
20580
|
-
}) {
|
|
20581
|
-
return /* @__PURE__ */ jsx23(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
|
|
20582
|
-
}
|
|
20583
|
-
function DialogPortal({
|
|
20584
|
-
...props
|
|
20585
|
-
}) {
|
|
20586
|
-
return /* @__PURE__ */ jsx23(DialogPrimitive.Portal, { ...props });
|
|
20587
|
-
}
|
|
20588
|
-
function DialogOverlay({
|
|
20589
|
-
className,
|
|
20590
|
-
...props
|
|
20591
|
-
}) {
|
|
20592
|
-
return /* @__PURE__ */ jsx23(
|
|
20593
|
-
DialogPrimitive.Overlay,
|
|
20594
|
-
{
|
|
20595
|
-
"data-slot": "dialog-overlay",
|
|
20596
|
-
"data-ohw-link-modal-root": "",
|
|
20597
|
-
className: cn("fixed inset-0 z-[2147483646] bg-black/50", className),
|
|
20598
|
-
...props
|
|
20599
|
-
}
|
|
20600
|
-
);
|
|
20601
|
-
}
|
|
20602
|
-
var DialogContent = React9.forwardRef(
|
|
20603
|
-
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
20604
|
-
const positionMode = container ? "absolute" : "fixed";
|
|
20605
|
-
return /* @__PURE__ */ jsxs14(DialogPortal, { container: container ?? void 0, children: [
|
|
20606
|
-
/* @__PURE__ */ jsx23(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
20607
|
-
/* @__PURE__ */ jsxs14(
|
|
20608
|
-
DialogPrimitive.Content,
|
|
20609
|
-
{
|
|
20610
|
-
ref,
|
|
20611
|
-
"data-slot": "dialog-content",
|
|
20612
|
-
className: cn(
|
|
20613
|
-
positionMode,
|
|
20614
|
-
"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",
|
|
20615
|
-
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
20616
|
-
container ? "max-h-[calc(100%-32px)]" : "max-h-[calc(100vh-32px)]",
|
|
20617
|
-
className
|
|
20618
|
-
),
|
|
20619
|
-
onMouseDown: (e) => e.stopPropagation(),
|
|
20620
|
-
...props,
|
|
20621
|
-
children: [
|
|
20622
|
-
children,
|
|
20623
|
-
showCloseButton ? /* @__PURE__ */ jsx23(
|
|
20624
|
-
DialogPrimitive.Close,
|
|
20625
|
-
{
|
|
20626
|
-
type: "button",
|
|
20627
|
-
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
20628
|
-
"aria-label": "Close",
|
|
20629
|
-
children: /* @__PURE__ */ jsx23(X2, { size: 16, "aria-hidden": true })
|
|
20630
|
-
}
|
|
20631
|
-
) : null
|
|
20632
|
-
]
|
|
20633
|
-
}
|
|
20634
|
-
)
|
|
20635
|
-
] });
|
|
20636
|
-
}
|
|
20637
|
-
);
|
|
20638
|
-
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
20639
|
-
function DialogHeader({
|
|
20640
|
-
className,
|
|
20641
|
-
...props
|
|
20642
|
-
}) {
|
|
20643
|
-
return /* @__PURE__ */ jsx23("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
20644
|
-
}
|
|
20645
|
-
function DialogFooter({
|
|
20646
|
-
className,
|
|
20647
|
-
...props
|
|
20648
|
-
}) {
|
|
20649
|
-
return /* @__PURE__ */ jsx23(
|
|
20650
|
-
"div",
|
|
20651
|
-
{
|
|
20652
|
-
className: cn("flex items-center justify-end gap-2", className),
|
|
20653
|
-
...props
|
|
20654
|
-
}
|
|
20655
|
-
);
|
|
20656
|
-
}
|
|
20657
|
-
var DialogTitle = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx23(
|
|
20658
|
-
DialogPrimitive.Title,
|
|
20659
|
-
{
|
|
20660
|
-
ref,
|
|
20661
|
-
className: cn(
|
|
20662
|
-
"text-lg font-semibold leading-none tracking-tight text-card-foreground",
|
|
20663
|
-
className
|
|
20664
|
-
),
|
|
20665
|
-
...props
|
|
20666
|
-
}
|
|
20667
|
-
));
|
|
20668
|
-
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
20669
|
-
var DialogDescription = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx23(
|
|
20670
|
-
DialogPrimitive.Description,
|
|
20671
|
-
{
|
|
20672
|
-
ref,
|
|
20673
|
-
className: cn("text-sm text-muted-foreground", className),
|
|
20674
|
-
...props
|
|
20675
|
-
}
|
|
20676
|
-
));
|
|
20677
|
-
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
20678
|
-
var DialogClose = DialogPrimitive.Close;
|
|
20679
|
-
|
|
20680
20776
|
// src/ui/link-modal/LinkEditorPanel.tsx
|
|
20681
20777
|
import { Info, X as X4 } from "lucide-react";
|
|
20682
20778
|
|
|
20683
20779
|
// src/ui/link-modal/DestinationBreadcrumb.tsx
|
|
20684
|
-
import { ArrowRight as
|
|
20780
|
+
import { ArrowRight as ArrowRight3, File, GalleryVertical } from "lucide-react";
|
|
20685
20781
|
import { jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
20686
20782
|
function DestinationBreadcrumb({
|
|
20687
20783
|
pageTitle,
|
|
@@ -20695,7 +20791,7 @@ function DestinationBreadcrumb({
|
|
|
20695
20791
|
/* @__PURE__ */ jsx24("span", { className: "text-sm font-medium leading-none text-foreground!", children: pageTitle })
|
|
20696
20792
|
] }),
|
|
20697
20793
|
/* @__PURE__ */ jsx24(
|
|
20698
|
-
|
|
20794
|
+
ArrowRight3,
|
|
20699
20795
|
{
|
|
20700
20796
|
size: 16,
|
|
20701
20797
|
className: "shrink-0 text-muted-foreground",
|
|
@@ -20807,7 +20903,7 @@ function Label({ className, ...props }) {
|
|
|
20807
20903
|
}
|
|
20808
20904
|
|
|
20809
20905
|
// src/ui/link-modal/UrlOrPageInput.tsx
|
|
20810
|
-
import { ChevronDown as
|
|
20906
|
+
import { ChevronDown as ChevronDown5, File as File2, X as X3 } from "lucide-react";
|
|
20811
20907
|
import { jsx as jsx28, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
20812
20908
|
function FieldChevron({
|
|
20813
20909
|
onClick
|
|
@@ -20820,7 +20916,7 @@ function FieldChevron({
|
|
|
20820
20916
|
onClick,
|
|
20821
20917
|
"aria-label": "Open page list",
|
|
20822
20918
|
tabIndex: -1,
|
|
20823
|
-
children: /* @__PURE__ */ jsx28(
|
|
20919
|
+
children: /* @__PURE__ */ jsx28(ChevronDown5, { size: 16 })
|
|
20824
20920
|
}
|
|
20825
20921
|
);
|
|
20826
20922
|
}
|
|
@@ -21050,7 +21146,7 @@ function LinkEditorPanel({ state, onClose }) {
|
|
|
21050
21146
|
// src/ui/link-modal/SectionPickerOverlay.tsx
|
|
21051
21147
|
import { useCallback as useCallback7, useEffect as useEffect11, useMemo as useMemo2, useRef as useRef10, useState as useState13 } from "react";
|
|
21052
21148
|
import { createPortal as createPortal2 } from "react-dom";
|
|
21053
|
-
import { ArrowLeft as
|
|
21149
|
+
import { ArrowLeft as ArrowLeft3, Check as Check4 } from "lucide-react";
|
|
21054
21150
|
import { usePathname, useRouter as useRouter2 } from "next/navigation";
|
|
21055
21151
|
|
|
21056
21152
|
// src/lib/parent-scroll.ts
|
|
@@ -21327,7 +21423,7 @@ function SectionPickerOverlay({
|
|
|
21327
21423
|
className: "h-8 min-w-0 gap-1 border-border bg-background px-2 py-1.5 shadow-sm hover:bg-muted cursor-pointer",
|
|
21328
21424
|
onClick: onBack,
|
|
21329
21425
|
children: [
|
|
21330
|
-
/* @__PURE__ */ jsx30(
|
|
21426
|
+
/* @__PURE__ */ jsx30(ArrowLeft3, { className: "size-4 shrink-0", "aria-hidden": true }),
|
|
21331
21427
|
"Back"
|
|
21332
21428
|
]
|
|
21333
21429
|
}
|
|
@@ -21396,7 +21492,7 @@ function SectionPickerOverlay({
|
|
|
21396
21492
|
className: "absolute right-3 top-3 flex size-8 items-center justify-center rounded-full text-white",
|
|
21397
21493
|
style: { backgroundColor: "var(--ohw-primary, #0885fe)" },
|
|
21398
21494
|
"aria-hidden": true,
|
|
21399
|
-
children: /* @__PURE__ */ jsx30(
|
|
21495
|
+
children: /* @__PURE__ */ jsx30(Check4, { className: "size-5" })
|
|
21400
21496
|
}
|
|
21401
21497
|
) : null
|
|
21402
21498
|
]
|
|
@@ -21780,6 +21876,7 @@ function shouldUseDevFixtures() {
|
|
|
21780
21876
|
function getLogoElement(el) {
|
|
21781
21877
|
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
21782
21878
|
if (marked) return marked;
|
|
21879
|
+
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
21783
21880
|
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
21784
21881
|
if (!root) return null;
|
|
21785
21882
|
const anchor = el.closest("a");
|
|
@@ -21849,7 +21946,7 @@ function addFooterColumnWithPersist({
|
|
|
21849
21946
|
import {
|
|
21850
21947
|
useCallback as useCallback9,
|
|
21851
21948
|
useEffect as useEffect14,
|
|
21852
|
-
useLayoutEffect as
|
|
21949
|
+
useLayoutEffect as useLayoutEffect6,
|
|
21853
21950
|
useRef as useRef11,
|
|
21854
21951
|
useState as useState15
|
|
21855
21952
|
} from "react";
|
|
@@ -21946,7 +22043,7 @@ function FloatingPanel({
|
|
|
21946
22043
|
return () => window.removeEventListener("message", onParentScroll);
|
|
21947
22044
|
}, [open]);
|
|
21948
22045
|
const positionRef = useRef11(position);
|
|
21949
|
-
|
|
22046
|
+
useLayoutEffect6(() => {
|
|
21950
22047
|
if (!open) {
|
|
21951
22048
|
positionRef.current = position;
|
|
21952
22049
|
return;
|
|
@@ -21956,7 +22053,7 @@ function FloatingPanel({
|
|
|
21956
22053
|
}
|
|
21957
22054
|
positionRef.current = position;
|
|
21958
22055
|
}, [open, position, liveScroll, parentScroll]);
|
|
21959
|
-
|
|
22056
|
+
useLayoutEffect6(() => {
|
|
21960
22057
|
if (!open || !panelRef.current) return;
|
|
21961
22058
|
const el = panelRef.current;
|
|
21962
22059
|
const header = el.querySelector("[data-ohw-floating-panel-header]");
|
|
@@ -22165,7 +22262,7 @@ function SocialsDisplayPanel({ display, onChange, className }) {
|
|
|
22165
22262
|
}
|
|
22166
22263
|
|
|
22167
22264
|
// src/ui/button-style-panel.tsx
|
|
22168
|
-
import { Check as
|
|
22265
|
+
import { Check as Check5 } from "lucide-react";
|
|
22169
22266
|
import { jsx as jsx34, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
22170
22267
|
var SIZE_LABEL = { s: "S", m: "M", l: "L" };
|
|
22171
22268
|
function ButtonStylePanel({
|
|
@@ -22236,7 +22333,7 @@ function ButtonStylePanel({
|
|
|
22236
22333
|
{
|
|
22237
22334
|
className: "absolute right-0.5 top-0.5 flex size-5 items-center justify-center rounded-full bg-primary text-primary-foreground",
|
|
22238
22335
|
"aria-hidden": true,
|
|
22239
|
-
children: /* @__PURE__ */ jsx34(
|
|
22336
|
+
children: /* @__PURE__ */ jsx34(Check5, { className: "size-3", strokeWidth: 3 })
|
|
22240
22337
|
}
|
|
22241
22338
|
) : null
|
|
22242
22339
|
]
|
|
@@ -23261,7 +23358,7 @@ function useSectionDrag({
|
|
|
23261
23358
|
}
|
|
23262
23359
|
|
|
23263
23360
|
// src/ui/footer-container-chrome.tsx
|
|
23264
|
-
import { Plus as
|
|
23361
|
+
import { Plus as Plus4 } from "lucide-react";
|
|
23265
23362
|
import { jsx as jsx35, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
23266
23363
|
function FooterContainerChrome({
|
|
23267
23364
|
rect,
|
|
@@ -23302,7 +23399,7 @@ function FooterContainerChrome({
|
|
|
23302
23399
|
if (addDisabled) return;
|
|
23303
23400
|
onAdd();
|
|
23304
23401
|
},
|
|
23305
|
-
children: /* @__PURE__ */ jsx35(
|
|
23402
|
+
children: /* @__PURE__ */ jsx35(Plus4, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
23306
23403
|
}
|
|
23307
23404
|
) }),
|
|
23308
23405
|
/* @__PURE__ */ jsx35(TooltipContent, { side: "bottom", sideOffset: 9, children: addDisabled ? "Maximum columns reached" : "Add item" })
|
|
@@ -23481,7 +23578,7 @@ function deleteSelectedNavFooterItem(deps) {
|
|
|
23481
23578
|
}
|
|
23482
23579
|
|
|
23483
23580
|
// src/ui/navbar-container-chrome.tsx
|
|
23484
|
-
import { Plus as
|
|
23581
|
+
import { Plus as Plus5 } from "lucide-react";
|
|
23485
23582
|
import { jsx as jsx36 } from "react/jsx-runtime";
|
|
23486
23583
|
function NavbarContainerChrome({
|
|
23487
23584
|
rect,
|
|
@@ -23517,7 +23614,7 @@ function NavbarContainerChrome({
|
|
|
23517
23614
|
e.stopPropagation();
|
|
23518
23615
|
onAdd();
|
|
23519
23616
|
},
|
|
23520
|
-
children: /* @__PURE__ */ jsx36(
|
|
23617
|
+
children: /* @__PURE__ */ jsx36(Plus5, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
|
|
23521
23618
|
}
|
|
23522
23619
|
)
|
|
23523
23620
|
}
|
|
@@ -23589,7 +23686,7 @@ function Badge({ className, variant, ...props }) {
|
|
|
23589
23686
|
}
|
|
23590
23687
|
|
|
23591
23688
|
// src/OhhwellsBridge.tsx
|
|
23592
|
-
import { Brush as Brush2, Link as Link2, Plus as
|
|
23689
|
+
import { Brush as Brush2, Link as Link2, Plus as Plus6, Settings } from "lucide-react";
|
|
23593
23690
|
import { Fragment as Fragment12, jsx as jsx39, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
23594
23691
|
var PRIMARY7 = "#0885FE";
|
|
23595
23692
|
var IMAGE_FADE_MS = 300;
|
|
@@ -24366,7 +24463,7 @@ function getNavigationSelectionParent(el) {
|
|
|
24366
24463
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
24367
24464
|
return resolveFooterLinksContainerFrom(el);
|
|
24368
24465
|
}
|
|
24369
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
|
|
24466
|
+
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)) {
|
|
24370
24467
|
return getNavigationRoot(el);
|
|
24371
24468
|
}
|
|
24372
24469
|
return null;
|
|
@@ -24588,7 +24685,6 @@ var ICONS = {
|
|
|
24588
24685
|
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"/>',
|
|
24589
24686
|
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"/>'
|
|
24590
24687
|
};
|
|
24591
|
-
var HEIGHT_SETTLE_DELAYS = [150, 400, 800];
|
|
24592
24688
|
var SELECTION_CHROME_GAP2 = 4;
|
|
24593
24689
|
var TOOLBAR_STROKE_GAP2 = 4;
|
|
24594
24690
|
var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
|
|
@@ -24686,7 +24782,7 @@ function applyVisibleViewport(el, parentScroll) {
|
|
|
24686
24782
|
el.style.top = `${top}px`;
|
|
24687
24783
|
el.style.height = `${height}px`;
|
|
24688
24784
|
}
|
|
24689
|
-
var
|
|
24785
|
+
var TOOLBAR_EDGE_MARGIN4 = 4;
|
|
24690
24786
|
function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
24691
24787
|
const isAbove = transform.includes("translateY(-100%)");
|
|
24692
24788
|
let visualTop = isAbove ? top - approxH : top;
|
|
@@ -24713,8 +24809,8 @@ function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
|
24713
24809
|
function clampToolbarLeft(centerX, toolbarWidth) {
|
|
24714
24810
|
const half = toolbarWidth / 2;
|
|
24715
24811
|
return Math.max(
|
|
24716
|
-
|
|
24717
|
-
Math.min(centerX, window.innerWidth -
|
|
24812
|
+
TOOLBAR_EDGE_MARGIN4 + half,
|
|
24813
|
+
Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN4 - half)
|
|
24718
24814
|
);
|
|
24719
24815
|
}
|
|
24720
24816
|
function calcToolbarPos(rect, parentScroll, toolbarW = 306) {
|
|
@@ -25153,7 +25249,7 @@ function OhhwellsBridge() {
|
|
|
25153
25249
|
}, []);
|
|
25154
25250
|
const subdomainFromQuery = searchParams.get("subdomain");
|
|
25155
25251
|
const [subdomain, setSubdomain] = useState18(() => resolveSubdomain(subdomainFromQuery));
|
|
25156
|
-
|
|
25252
|
+
useLayoutEffect7(() => {
|
|
25157
25253
|
const next = resolveSubdomain(subdomainFromQuery);
|
|
25158
25254
|
if (next !== subdomain) setSubdomain(next);
|
|
25159
25255
|
if (next) return;
|
|
@@ -25604,21 +25700,6 @@ function OhhwellsBridge() {
|
|
|
25604
25700
|
const [isItemDragging, setIsItemDragging] = useState18(false);
|
|
25605
25701
|
const [isFooterFrameSelection, setIsFooterFrameSelection] = useState18(false);
|
|
25606
25702
|
isFooterFrameSelectionRef.current = isFooterFrameSelection;
|
|
25607
|
-
const [floatingPanel, setFloatingPanel] = useState18(null);
|
|
25608
|
-
const floatingPanelOpenRef = useRef14(false);
|
|
25609
|
-
floatingPanelOpenRef.current = floatingPanel !== null;
|
|
25610
|
-
const floatingPanelRef = useRef14(null);
|
|
25611
|
-
floatingPanelRef.current = floatingPanel;
|
|
25612
|
-
const [floatingPanelPos, setFloatingPanelPos] = useState18(null);
|
|
25613
|
-
const buttonCollectionDragRef = useRef14(null);
|
|
25614
|
-
const buttonDropInsertIndexRef = useRef14(null);
|
|
25615
|
-
const [buttonDropSlots, setButtonDropSlots] = useState18([]);
|
|
25616
|
-
const [activeButtonDropIndex, setActiveButtonDropIndex] = useState18(null);
|
|
25617
|
-
const buttonPointerDragRef = useRef14(null);
|
|
25618
|
-
const [buttonStyleTick, setButtonStyleTick] = useState18(0);
|
|
25619
|
-
const [logoSizeDraft, setLogoSizeDraft] = useState18(null);
|
|
25620
|
-
const [editorViewport, setEditorViewport] = useState18("desktop");
|
|
25621
|
-
const [parentScrollSnap, setParentScrollSnap] = useState18(null);
|
|
25622
25703
|
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = useState18(null);
|
|
25623
25704
|
const [footerHeadingVisible, setFooterHeadingVisible] = useState18(null);
|
|
25624
25705
|
const footerDragRef = useRef14(null);
|
|
@@ -25644,6 +25725,21 @@ function OhhwellsBridge() {
|
|
|
25644
25725
|
const stylesRef = useRef14("");
|
|
25645
25726
|
const appliedDrawerRef = useRef14(null);
|
|
25646
25727
|
const pendingDeleteUndoRef = useRef14(null);
|
|
25728
|
+
const [floatingPanel, setFloatingPanel] = useState18(null);
|
|
25729
|
+
const floatingPanelOpenRef = useRef14(false);
|
|
25730
|
+
const floatingPanelRef = useRef14(null);
|
|
25731
|
+
floatingPanelRef.current = floatingPanel;
|
|
25732
|
+
const setFloatingPanelRef = useRef14(setFloatingPanel);
|
|
25733
|
+
const [floatingPanelPos, setFloatingPanelPos] = useState18(null);
|
|
25734
|
+
const buttonCollectionDragRef = useRef14(null);
|
|
25735
|
+
const buttonDropInsertIndexRef = useRef14(null);
|
|
25736
|
+
const [buttonDropSlots, setButtonDropSlots] = useState18([]);
|
|
25737
|
+
const [activeButtonDropIndex, setActiveButtonDropIndex] = useState18(null);
|
|
25738
|
+
const buttonPointerDragRef = useRef14(null);
|
|
25739
|
+
const [buttonStyleTick, setButtonStyleTick] = useState18(0);
|
|
25740
|
+
const [logoSizeDraft, setLogoSizeDraft] = useState18(null);
|
|
25741
|
+
const [editorViewport, setEditorViewport] = useState18("desktop");
|
|
25742
|
+
const [parentScrollSnap, setParentScrollSnap] = useState18(null);
|
|
25647
25743
|
const [sitePages, setSitePages] = useState18([]);
|
|
25648
25744
|
const [sectionsByPath, setSectionsByPath] = useState18({});
|
|
25649
25745
|
const sectionsPrefetchGenRef = useRef14(0);
|
|
@@ -25652,7 +25748,18 @@ function OhhwellsBridge() {
|
|
|
25652
25748
|
const linkPopoverOpenRef = useRef14(false);
|
|
25653
25749
|
const linkPopoverGraceUntilRef = useRef14(0);
|
|
25654
25750
|
setLinkPopoverRef.current = setLinkPopover;
|
|
25751
|
+
setFloatingPanelRef.current = setFloatingPanel;
|
|
25655
25752
|
linkPopoverSessionRef.current = linkPopover;
|
|
25753
|
+
floatingPanelOpenRef.current = Boolean(floatingPanel);
|
|
25754
|
+
useEffect17(() => {
|
|
25755
|
+
const syncViewport = () => {
|
|
25756
|
+
const next = window.innerWidth <= 480 ? "mobile" : "desktop";
|
|
25757
|
+
setEditorViewport((prev) => prev === next ? prev : next);
|
|
25758
|
+
};
|
|
25759
|
+
syncViewport();
|
|
25760
|
+
window.addEventListener("resize", syncViewport);
|
|
25761
|
+
return () => window.removeEventListener("resize", syncViewport);
|
|
25762
|
+
}, []);
|
|
25656
25763
|
useEffect17(() => {
|
|
25657
25764
|
setSectionOrderPersistHandler((entries) => {
|
|
25658
25765
|
const currentPath = window.location.pathname;
|
|
@@ -27320,7 +27427,7 @@ function OhhwellsBridge() {
|
|
|
27320
27427
|
isFooterFrameSelection,
|
|
27321
27428
|
postToParent2
|
|
27322
27429
|
]);
|
|
27323
|
-
|
|
27430
|
+
useLayoutEffect7(() => {
|
|
27324
27431
|
if (!subdomain || isEditMode) {
|
|
27325
27432
|
setFetchState("done");
|
|
27326
27433
|
return;
|
|
@@ -27347,6 +27454,7 @@ function OhhwellsBridge() {
|
|
|
27347
27454
|
applyAiFooterFromContent(content);
|
|
27348
27455
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
27349
27456
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
27457
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
27350
27458
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
27351
27459
|
}
|
|
27352
27460
|
applyBrandChrome(content);
|
|
@@ -27357,12 +27465,12 @@ function OhhwellsBridge() {
|
|
|
27357
27465
|
if (key === "__ohw_sections") continue;
|
|
27358
27466
|
if (key === AI_SECTIONS_KEY) continue;
|
|
27359
27467
|
if (key === AI_FOOTER_KEY) continue;
|
|
27468
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
27469
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27360
27470
|
if (key === BRAND_KIT_KEY) continue;
|
|
27361
27471
|
if (key === STYLE_STORE_KEY) continue;
|
|
27362
27472
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
27363
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
27364
27473
|
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
27365
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27366
27474
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
27367
27475
|
continue;
|
|
27368
27476
|
}
|
|
@@ -27577,17 +27685,18 @@ function OhhwellsBridge() {
|
|
|
27577
27685
|
}
|
|
27578
27686
|
applyAiFooterFromContent(content);
|
|
27579
27687
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
27688
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
27580
27689
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
27581
27690
|
}
|
|
27582
27691
|
for (const [key, val] of Object.entries(content)) {
|
|
27583
27692
|
if (key === "__ohw_sections") continue;
|
|
27584
27693
|
if (key === AI_SECTIONS_KEY) continue;
|
|
27585
27694
|
if (key === AI_FOOTER_KEY) continue;
|
|
27695
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
27696
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27586
27697
|
if (key === BRAND_KIT_KEY) continue;
|
|
27587
27698
|
if (key === STYLE_STORE_KEY) continue;
|
|
27588
27699
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
27589
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
27590
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27591
27700
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
27592
27701
|
continue;
|
|
27593
27702
|
}
|
|
@@ -27660,7 +27769,7 @@ function OhhwellsBridge() {
|
|
|
27660
27769
|
if (debounceTimer) clearTimeout(debounceTimer);
|
|
27661
27770
|
};
|
|
27662
27771
|
}, [subdomain, isEditMode, pathname]);
|
|
27663
|
-
|
|
27772
|
+
useLayoutEffect7(() => {
|
|
27664
27773
|
const el = document.getElementById("ohw-loader");
|
|
27665
27774
|
if (!el) return;
|
|
27666
27775
|
const visible = Boolean(subdomain) && fetchState !== "done";
|
|
@@ -27844,26 +27953,11 @@ function OhhwellsBridge() {
|
|
|
27844
27953
|
const t2 = setTimeout(measure, 500);
|
|
27845
27954
|
const ro = new ResizeObserver(schedule);
|
|
27846
27955
|
ro.observe(document.body);
|
|
27847
|
-
let lastWidth = window.innerWidth;
|
|
27848
|
-
let resizeTimers = [];
|
|
27849
|
-
const clearResizeTimers = () => {
|
|
27850
|
-
resizeTimers.forEach(clearTimeout);
|
|
27851
|
-
resizeTimers = [];
|
|
27852
|
-
};
|
|
27853
|
-
const handleResize = () => {
|
|
27854
|
-
if (window.innerWidth === lastWidth) return;
|
|
27855
|
-
lastWidth = window.innerWidth;
|
|
27856
|
-
clearResizeTimers();
|
|
27857
|
-
resizeTimers = HEIGHT_SETTLE_DELAYS.map((delay) => setTimeout(measure, delay));
|
|
27858
|
-
};
|
|
27859
|
-
window.addEventListener("resize", handleResize);
|
|
27860
27956
|
return () => {
|
|
27861
27957
|
clearTimeout(t1);
|
|
27862
27958
|
clearTimeout(t2);
|
|
27863
27959
|
if (raf != null) cancelAnimationFrame(raf);
|
|
27864
27960
|
ro.disconnect();
|
|
27865
|
-
clearResizeTimers();
|
|
27866
|
-
window.removeEventListener("resize", handleResize);
|
|
27867
27961
|
};
|
|
27868
27962
|
}, [pathname, isEditMode, postToParent2]);
|
|
27869
27963
|
useEffect17(() => {
|
|
@@ -28162,6 +28256,13 @@ function OhhwellsBridge() {
|
|
|
28162
28256
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
28163
28257
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
28164
28258
|
if (isInsideLinkEditor(target)) return;
|
|
28259
|
+
if (isInsideFloatingPanel(target)) return;
|
|
28260
|
+
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
28261
|
+
if (target.closest(
|
|
28262
|
+
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
28263
|
+
)) {
|
|
28264
|
+
return;
|
|
28265
|
+
}
|
|
28165
28266
|
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
28166
28267
|
clearMediaSelectionRef.current();
|
|
28167
28268
|
}
|
|
@@ -28185,13 +28286,6 @@ function OhhwellsBridge() {
|
|
|
28185
28286
|
return;
|
|
28186
28287
|
}
|
|
28187
28288
|
}
|
|
28188
|
-
if (isInsideFloatingPanel(target)) return;
|
|
28189
|
-
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
28190
|
-
if (target.closest(
|
|
28191
|
-
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
28192
|
-
)) {
|
|
28193
|
-
return;
|
|
28194
|
-
}
|
|
28195
28289
|
{
|
|
28196
28290
|
const formEl = getFormElement(target);
|
|
28197
28291
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
@@ -28345,9 +28439,13 @@ function OhhwellsBridge() {
|
|
|
28345
28439
|
if (isIconEditable(editable) && !getSocialItem(editable)) {
|
|
28346
28440
|
e.preventDefault();
|
|
28347
28441
|
e.stopPropagation();
|
|
28348
|
-
selectIconElementRef.current(editable);
|
|
28349
28442
|
const aiIcon = editable.hasAttribute("data-ai-icon");
|
|
28350
28443
|
const featureIcon = aiIcon && /\.features\.\d+\.icon$/.test(editable.dataset.ohwKey ?? "");
|
|
28444
|
+
if (aiIcon) {
|
|
28445
|
+
aiSectionApiRef.current?.selectFromElement(editable);
|
|
28446
|
+
} else {
|
|
28447
|
+
selectIconElementRef.current(editable);
|
|
28448
|
+
}
|
|
28351
28449
|
postToParentRef.current({
|
|
28352
28450
|
type: "ow:icon-pick",
|
|
28353
28451
|
key: editable.dataset.ohwKey ?? "",
|
|
@@ -28575,6 +28673,9 @@ function OhhwellsBridge() {
|
|
|
28575
28673
|
setHoveredItemRect(null);
|
|
28576
28674
|
hoveredNavContainerRef.current = null;
|
|
28577
28675
|
setHoveredNavContainerRect(null);
|
|
28676
|
+
siblingHintElRef.current = null;
|
|
28677
|
+
setSiblingHintRect(null);
|
|
28678
|
+
setSiblingHintRects([]);
|
|
28578
28679
|
return;
|
|
28579
28680
|
}
|
|
28580
28681
|
{
|
|
@@ -28695,7 +28796,6 @@ function OhhwellsBridge() {
|
|
|
28695
28796
|
hoveredNavContainerRef.current = null;
|
|
28696
28797
|
setHoveredNavContainerRect(null);
|
|
28697
28798
|
hoveredItemElRef.current = editable;
|
|
28698
|
-
setHoveredItemRect(isSelectedForHoverRef.current(editable) ? null : editable.getBoundingClientRect());
|
|
28699
28799
|
}
|
|
28700
28800
|
}
|
|
28701
28801
|
}
|
|
@@ -29405,7 +29505,11 @@ function OhhwellsBridge() {
|
|
|
29405
29505
|
};
|
|
29406
29506
|
const handleMouseMove = (e) => {
|
|
29407
29507
|
const { clientX, clientY } = e;
|
|
29408
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
29508
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
29509
|
+
dismissImageHover();
|
|
29510
|
+
clearImageHover();
|
|
29511
|
+
return;
|
|
29512
|
+
}
|
|
29409
29513
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) {
|
|
29410
29514
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
29411
29515
|
formHoverElRef.current = null;
|
|
@@ -29434,7 +29538,12 @@ function OhhwellsBridge() {
|
|
|
29434
29538
|
setHoveredItemRect(null);
|
|
29435
29539
|
hoveredNavContainerRef.current = null;
|
|
29436
29540
|
setHoveredNavContainerRect(null);
|
|
29541
|
+
siblingHintElRef.current = null;
|
|
29542
|
+
setSiblingHintRect(null);
|
|
29543
|
+
setSiblingHintRects([]);
|
|
29437
29544
|
dismissImageHover();
|
|
29545
|
+
clearImageHover();
|
|
29546
|
+
setSectionGap(null);
|
|
29438
29547
|
return;
|
|
29439
29548
|
}
|
|
29440
29549
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
@@ -29446,7 +29555,11 @@ function OhhwellsBridge() {
|
|
|
29446
29555
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
29447
29556
|
const { clientX, clientY } = e.data;
|
|
29448
29557
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
29449
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
29558
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
29559
|
+
dismissImageHover();
|
|
29560
|
+
clearImageHover();
|
|
29561
|
+
return;
|
|
29562
|
+
}
|
|
29450
29563
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) return;
|
|
29451
29564
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
29452
29565
|
probeSectionGapAt(clientX, clientY);
|
|
@@ -29826,6 +29939,7 @@ function OhhwellsBridge() {
|
|
|
29826
29939
|
applyAiFooterFromContent(content);
|
|
29827
29940
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
29828
29941
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
29942
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
29829
29943
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
29830
29944
|
}
|
|
29831
29945
|
applyBrandChrome(content);
|
|
@@ -29840,12 +29954,12 @@ function OhhwellsBridge() {
|
|
|
29840
29954
|
}
|
|
29841
29955
|
if (key === AI_SECTIONS_KEY) continue;
|
|
29842
29956
|
if (key === AI_FOOTER_KEY) continue;
|
|
29957
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
29958
|
+
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
29843
29959
|
if (key === BRAND_KIT_KEY) continue;
|
|
29844
29960
|
if (key === STYLE_STORE_KEY) continue;
|
|
29845
29961
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
29846
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
29847
29962
|
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
29848
|
-
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
29849
29963
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
29850
29964
|
continue;
|
|
29851
29965
|
}
|
|
@@ -30220,6 +30334,44 @@ function OhhwellsBridge() {
|
|
|
30220
30334
|
});
|
|
30221
30335
|
};
|
|
30222
30336
|
window.addEventListener("message", handleAiSetStyles);
|
|
30337
|
+
const handleAiSetButtonStyle = (e) => {
|
|
30338
|
+
if (e.data?.type !== "ow:ai-set-button-style") return;
|
|
30339
|
+
const nodeKey = typeof e.data.hrefKey === "string" ? e.data.hrefKey : "";
|
|
30340
|
+
const keyed = nodeKey ? document.querySelector(
|
|
30341
|
+
`[data-ohw-href-key="${CSS.escape(nodeKey)}"], [data-ohw-key="${CSS.escape(nodeKey)}"]`
|
|
30342
|
+
) : null;
|
|
30343
|
+
const hrefKey = buttonId(keyed);
|
|
30344
|
+
const el = hrefKey ? document.querySelector(`[data-ohw-href-key="${CSS.escape(hrefKey)}"]`) : null;
|
|
30345
|
+
const previous = editContentRef.current[BUTTON_ASSIGNMENTS_KEY] ?? "";
|
|
30346
|
+
if (!el || !hrefKey || !isCtaButton(el)) {
|
|
30347
|
+
postToParentRef.current({ type: "ow:ai-button-style-applied", ok: false, previous, value: previous });
|
|
30348
|
+
return;
|
|
30349
|
+
}
|
|
30350
|
+
const tokens = tokensFromButton(el);
|
|
30351
|
+
const current = assignmentFor(el, editContentRef.current, tokens);
|
|
30352
|
+
const patch = e.data.assignment;
|
|
30353
|
+
const next = {
|
|
30354
|
+
variant: patch?.variant ?? current.variant,
|
|
30355
|
+
size: patch?.size ?? current.size
|
|
30356
|
+
};
|
|
30357
|
+
const value = typeof e.data.assignments === "string" ? e.data.assignments : JSON.stringify(withAssignment(editContentRef.current, hrefKey, next));
|
|
30358
|
+
editContentRef.current = { ...editContentRef.current, [BUTTON_ASSIGNMENTS_KEY]: value };
|
|
30359
|
+
applyButtonStyle(el, next, tokens);
|
|
30360
|
+
postToParentRef.current({
|
|
30361
|
+
type: "ow:change",
|
|
30362
|
+
nodes: [{ key: BUTTON_ASSIGNMENTS_KEY, text: value }]
|
|
30363
|
+
});
|
|
30364
|
+
postToParentRef.current({
|
|
30365
|
+
type: "ow:ai-button-style-applied",
|
|
30366
|
+
ok: true,
|
|
30367
|
+
// The resolved id, which may differ from the key the editor sent — undo must target this one.
|
|
30368
|
+
hrefKey,
|
|
30369
|
+
previous,
|
|
30370
|
+
previousAssignment: current,
|
|
30371
|
+
value
|
|
30372
|
+
});
|
|
30373
|
+
};
|
|
30374
|
+
window.addEventListener("message", handleAiSetButtonStyle);
|
|
30223
30375
|
const handleGetBrand = (e) => {
|
|
30224
30376
|
if (e.data?.type !== "ow:get-brand") return;
|
|
30225
30377
|
const template = deriveTemplateBrand();
|
|
@@ -30443,6 +30595,12 @@ function OhhwellsBridge() {
|
|
|
30443
30595
|
closeLinkPopoverRef.current();
|
|
30444
30596
|
return;
|
|
30445
30597
|
}
|
|
30598
|
+
if (floatingPanelOpenRef.current) {
|
|
30599
|
+
setFloatingPanelRef.current(null);
|
|
30600
|
+
deselectRef.current();
|
|
30601
|
+
deactivateRef.current();
|
|
30602
|
+
return;
|
|
30603
|
+
}
|
|
30446
30604
|
deselectRef.current();
|
|
30447
30605
|
deactivateRef.current();
|
|
30448
30606
|
clearMediaSelectionRef.current();
|
|
@@ -31253,6 +31411,7 @@ function OhhwellsBridge() {
|
|
|
31253
31411
|
window.removeEventListener("message", handleAiSetSections);
|
|
31254
31412
|
window.removeEventListener("message", handleAiSetBrand);
|
|
31255
31413
|
window.removeEventListener("message", handleAiSetStyles);
|
|
31414
|
+
window.removeEventListener("message", handleAiSetButtonStyle);
|
|
31256
31415
|
window.removeEventListener("message", handleCollectItems);
|
|
31257
31416
|
window.removeEventListener("message", handleAiApplyItems);
|
|
31258
31417
|
window.removeEventListener("message", handleGetBrand);
|
|
@@ -31264,10 +31423,10 @@ function OhhwellsBridge() {
|
|
|
31264
31423
|
window.removeEventListener("message", handleDeleteSection);
|
|
31265
31424
|
window.removeEventListener("message", handleDuplicateSection);
|
|
31266
31425
|
window.removeEventListener("message", handleDeactivate);
|
|
31267
|
-
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
31268
31426
|
window.removeEventListener("message", handleToastAction);
|
|
31269
31427
|
window.removeEventListener("message", handleFormCount);
|
|
31270
31428
|
window.removeEventListener("message", handleUiEscape);
|
|
31429
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
31271
31430
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
31272
31431
|
autoSaveTimers.current.clear();
|
|
31273
31432
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
@@ -31561,7 +31720,7 @@ function OhhwellsBridge() {
|
|
|
31561
31720
|
postToParent2({
|
|
31562
31721
|
type: "ow:ready",
|
|
31563
31722
|
version: "1",
|
|
31564
|
-
bridgeVersion: "0.1.
|
|
31723
|
+
bridgeVersion: "0.1.149",
|
|
31565
31724
|
path: pathname,
|
|
31566
31725
|
nodes: collectEditableNodes(editContentRef.current),
|
|
31567
31726
|
sections
|
|
@@ -32297,7 +32456,7 @@ function OhhwellsBridge() {
|
|
|
32297
32456
|
className: "flex h-7 w-7 items-center justify-center rounded-md text-foreground transition-colors hover:bg-muted/80",
|
|
32298
32457
|
onClick: () => setFieldTypePickerOpen((open) => !open),
|
|
32299
32458
|
"data-ohw-add-field": "",
|
|
32300
|
-
children: /* @__PURE__ */ jsx39(
|
|
32459
|
+
children: /* @__PURE__ */ jsx39(Plus6, { size: 15, "aria-hidden": true })
|
|
32301
32460
|
}
|
|
32302
32461
|
),
|
|
32303
32462
|
/* @__PURE__ */ jsx39("div", { className: "mx-0.5 h-5 w-px bg-border" }),
|