@ohhwells/bridge 0.1.152-next.410 → 0.1.153
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 +716 -829
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +741 -870
- 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 +0 -116
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -6652,21 +6652,6 @@ function pricingCardFeatureCount(tree, index) {
|
|
|
6652
6652
|
const target = findPricingCollection(tree)?.children?.[index];
|
|
6653
6653
|
return target ? pricingFeatureList(target).length : 0;
|
|
6654
6654
|
}
|
|
6655
|
-
function prevailingFeatureIcon(features) {
|
|
6656
|
-
const counts = /* @__PURE__ */ new Map();
|
|
6657
|
-
for (const row of features) {
|
|
6658
|
-
const key = `${row.icon ?? ""}|${row.iconColor ?? ""}`;
|
|
6659
|
-
const entry = counts.get(key) ?? { count: 0, ...row.icon ? { icon: row.icon } : {}, ...row.iconColor ? { iconColor: row.iconColor } : {} };
|
|
6660
|
-
entry.count += 1;
|
|
6661
|
-
counts.set(key, entry);
|
|
6662
|
-
}
|
|
6663
|
-
let best = null;
|
|
6664
|
-
for (const entry of counts.values()) {
|
|
6665
|
-
if (!best || entry.count > best.count) best = entry;
|
|
6666
|
-
}
|
|
6667
|
-
if (!best) return {};
|
|
6668
|
-
return { ...best.icon ? { icon: best.icon } : {}, ...best.iconColor ? { iconColor: best.iconColor } : {} };
|
|
6669
|
-
}
|
|
6670
6655
|
function addPricingCardFeature(tree, index, text) {
|
|
6671
6656
|
return withPricingCollection(tree, (collection) => {
|
|
6672
6657
|
const children = collection.children;
|
|
@@ -6675,7 +6660,7 @@ function addPricingCardFeature(tree, index, text) {
|
|
|
6675
6660
|
const features = pricingFeatureList(target);
|
|
6676
6661
|
if (features.length >= PRICING_FEATURES_MAX) return false;
|
|
6677
6662
|
target.slots = target.slots ?? {};
|
|
6678
|
-
target.slots.features = [...features, { text
|
|
6663
|
+
target.slots.features = [...features, { text }];
|
|
6679
6664
|
return true;
|
|
6680
6665
|
});
|
|
6681
6666
|
}
|
|
@@ -7286,21 +7271,6 @@ function applyCustomCodeToHead(content) {
|
|
|
7286
7271
|
if (beforeNodes.length > 0) document.head.append(...beforeNodes);
|
|
7287
7272
|
}
|
|
7288
7273
|
|
|
7289
|
-
// src/lib/selectNavContainer.ts
|
|
7290
|
-
function isOnScreen(el) {
|
|
7291
|
-
const rect = el.getBoundingClientRect();
|
|
7292
|
-
if (rect.width <= 0 || rect.height <= 0) return false;
|
|
7293
|
-
if (el.offsetParent !== null) return true;
|
|
7294
|
-
return getComputedStyle(el).position === "fixed";
|
|
7295
|
-
}
|
|
7296
|
-
function findSelectableNavContainer(doc = document) {
|
|
7297
|
-
const visible = Array.from(doc.querySelectorAll("[data-ohw-nav-container]")).filter(isOnScreen);
|
|
7298
|
-
if (visible.length === 0) return null;
|
|
7299
|
-
return visible.reduce(
|
|
7300
|
-
(best, el) => el.getBoundingClientRect().top < best.getBoundingClientRect().top ? el : best
|
|
7301
|
-
);
|
|
7302
|
-
}
|
|
7303
|
-
|
|
7304
7274
|
// src/ui/ai-tree/aiSectionsManager.tsx
|
|
7305
7275
|
var import_react_dom = require("react-dom");
|
|
7306
7276
|
var import_client = require("react-dom/client");
|
|
@@ -7874,7 +7844,7 @@ var AI_MOBILE_CSS = [
|
|
|
7874
7844
|
// page's first section. Top only (bottom needs no nav clearance); ~96px approximates the
|
|
7875
7845
|
// template nav's own height (measured ~94px) — there's no shared `--ohw-header-h` var to read
|
|
7876
7846
|
// an exact figure from (no live measurement exists), so this is a safe approximation, not a
|
|
7877
|
-
// pixel-exact fit. Horizontal spacing already comes from `data-ai-
|
|
7847
|
+
// pixel-exact fit. Horizontal spacing already comes from `data-ai-container`.
|
|
7878
7848
|
'[data-ai-overlay-clearance] [data-ai-overlap-layer="overlay"]{padding-top:96px}',
|
|
7879
7849
|
// A full-bleed carousel's height is pure arithmetic: it spans the whole window, so 16/9 turns
|
|
7880
7850
|
// window width straight into height. Measured at 16/9 it came out ~90% of the viewport at EVERY
|
|
@@ -7890,10 +7860,8 @@ var AI_MOBILE_CSS = [
|
|
|
7890
7860
|
"[data-ai-section]{overflow-x:hidden}",
|
|
7891
7861
|
// `:not([data-ai-full-bleed])`: this `!important` gutter beat the inline `padding: 0` that a
|
|
7892
7862
|
// full-bleed section's container sets, so a carousel/media hero that is edge-to-edge on desktop
|
|
7893
|
-
// still got a 20px band of section background down both sides on a phone.
|
|
7894
|
-
|
|
7895
|
-
"[data-ai-section-inner]:not([data-ai-full-bleed]){padding:0 20px !important}",
|
|
7896
|
-
"[data-ai-container]{padding:0 20px !important}",
|
|
7863
|
+
// still got a 20px band of section background down both sides on a phone.
|
|
7864
|
+
"[data-ai-container]:not([data-ai-full-bleed]){padding:0 20px !important}",
|
|
7897
7865
|
"[data-ai-row]{display:flex !important;flex-direction:column !important;align-items:stretch !important}",
|
|
7898
7866
|
"[data-ai-cell]{width:100%;min-width:0}",
|
|
7899
7867
|
// The rule above turns every row into a COLUMN flex container on phones, which silently breaks
|
|
@@ -8098,31 +8066,6 @@ function pricingCardEmphasis(featured, ctx, hasBg) {
|
|
|
8098
8066
|
function textAttrs(ctx, path) {
|
|
8099
8067
|
return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
|
|
8100
8068
|
}
|
|
8101
|
-
var AI_RESPONSIVE_CSS = [
|
|
8102
|
-
"@media (max-width: 960px) {",
|
|
8103
|
-
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: repeat(2, 1fr) !important; }",
|
|
8104
|
-
' [data-ai-responsive] [data-ai-grid="1"] { grid-template-columns: 1fr !important; }',
|
|
8105
|
-
"}",
|
|
8106
|
-
"@media (max-width: 640px) {",
|
|
8107
|
-
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
|
|
8108
|
-
" [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
|
|
8109
|
-
// Group containers flatten to a column on phones; span placements come along for free.
|
|
8110
|
-
// `:not([data-ai-group="overlap"])` for the same reason as the twin pair in AI_MOBILE_CSS — see
|
|
8111
|
-
// the comment there. This sheet's copy is the narrower selector, so without the exemption it
|
|
8112
|
-
// flattens an `overlap` hero below 640px even though the other rule stands down: measured a 390px
|
|
8113
|
-
// viewport with the heading/CTA in flow *under* the image, 219px of section background where the
|
|
8114
|
-
// layered text used to be.
|
|
8115
|
-
' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) { display: flex !important; flex-direction: column !important; }',
|
|
8116
|
-
' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) > * { grid-column: auto !important; }',
|
|
8117
|
-
// `:not([data-ai-full-bleed])` for the same reason as the twin rule in AI_MOBILE_CSS: this one
|
|
8118
|
-
// is narrower (0,2,0 vs 0,1,0) and also `!important`, so without the guard it wins outright and
|
|
8119
|
-
// a full-bleed hero gets its 20px side band back below 640px only — the one width where the
|
|
8120
|
-
// other rule had already been taught to stand down.
|
|
8121
|
-
" [data-ai-responsive] [data-ai-section-inner]:not([data-ai-full-bleed]) { padding-left: 20px !important; padding-right: 20px !important; }",
|
|
8122
|
-
" [data-ai-responsive] { overflow-x: hidden; }",
|
|
8123
|
-
" [data-ai-responsive] img { max-width: 100%; }",
|
|
8124
|
-
"}"
|
|
8125
|
-
].join("\n");
|
|
8126
8069
|
var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
8127
8070
|
function MediaBox({
|
|
8128
8071
|
refValue,
|
|
@@ -8177,7 +8120,7 @@ function MediaBox({
|
|
|
8177
8120
|
position: fill ? "absolute" : void 0,
|
|
8178
8121
|
inset: fill ? 0 : void 0,
|
|
8179
8122
|
width: fill ? "100%" : fixedSize ? "auto" : "100%",
|
|
8180
|
-
height: fill ? "100%" :
|
|
8123
|
+
height: fill ? "100%" : void 0,
|
|
8181
8124
|
aspectRatio: fill ? void 0 : aspectRatio,
|
|
8182
8125
|
minHeight: fill || fixedSize ? void 0 : height ?? (aspectRatio ? void 0 : 180),
|
|
8183
8126
|
borderRadius: radius,
|
|
@@ -9673,7 +9616,7 @@ function CollectionBlock({ node, ctx, path }) {
|
|
|
9673
9616
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
9674
9617
|
"div",
|
|
9675
9618
|
{
|
|
9676
|
-
"data-ai-grid":
|
|
9619
|
+
"data-ai-grid": "",
|
|
9677
9620
|
"data-ohw-pricing-collection": isPricing ? "" : void 0,
|
|
9678
9621
|
style: {
|
|
9679
9622
|
display: "grid",
|
|
@@ -9975,7 +9918,7 @@ function renderNode(node, ctx, path, ambientAlign) {
|
|
|
9975
9918
|
},
|
|
9976
9919
|
children: [
|
|
9977
9920
|
i > 0 && ctx.heroOverlapFullBleed ? (
|
|
9978
|
-
// The section's `data-ai-
|
|
9921
|
+
// The section's `data-ai-container` gave up its max-width/gutter so the base
|
|
9979
9922
|
// layer (this group's i===0 sibling) can span edge-to-edge — reintroduced here,
|
|
9980
9923
|
// scoped to just the overlay text, so a heading/copy/CTA stack doesn't stretch
|
|
9981
9924
|
// the full section width instead of reading at the usual content width.
|
|
@@ -10394,7 +10337,6 @@ function AiTreeRenderer({
|
|
|
10394
10337
|
...fillHeight ? { "data-ai-fill-height": "" } : {},
|
|
10395
10338
|
...needsOverlayClearance ? { "data-ai-overlay-clearance": "" } : {},
|
|
10396
10339
|
...bgAttrs,
|
|
10397
|
-
"data-ai-responsive": "",
|
|
10398
10340
|
style: {
|
|
10399
10341
|
position: "relative",
|
|
10400
10342
|
padding: `${padCss} 0`,
|
|
@@ -10408,13 +10350,12 @@ function AiTreeRenderer({
|
|
|
10408
10350
|
...fillHeight ? { display: "grid" } : {}
|
|
10409
10351
|
},
|
|
10410
10352
|
children: [
|
|
10411
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_RESPONSIVE_CSS }),
|
|
10412
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_MOBILE_CSS }),
|
|
10413
10353
|
isOverlay && backgroundUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { position: "absolute", inset: 0, background: `rgba(255,255,255,${overlayAlpha})` } }),
|
|
10354
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_MOBILE_CSS }),
|
|
10414
10355
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
10415
10356
|
"div",
|
|
10416
10357
|
{
|
|
10417
|
-
"data-ai-
|
|
10358
|
+
"data-ai-container": "",
|
|
10418
10359
|
...fullBleedMedia ? { "data-ai-full-bleed": "" } : {},
|
|
10419
10360
|
style: {
|
|
10420
10361
|
position: "relative",
|
|
@@ -10431,7 +10372,7 @@ function AiTreeRenderer({
|
|
|
10431
10372
|
children: tree.rows.map((row, r2) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
10432
10373
|
"div",
|
|
10433
10374
|
{
|
|
10434
|
-
"data-ai-
|
|
10375
|
+
"data-ai-row": "",
|
|
10435
10376
|
style: {
|
|
10436
10377
|
display: "grid",
|
|
10437
10378
|
gridTemplateColumns: "repeat(12, 1fr)",
|
|
@@ -11093,10 +11034,9 @@ function applyAiSectionsToDom(state, options) {
|
|
|
11093
11034
|
if (existing && existing.serialized === serialized && existing.container.isConnected) {
|
|
11094
11035
|
continue;
|
|
11095
11036
|
}
|
|
11037
|
+
const isNewMount = !existing || !existing.container.isConnected;
|
|
11096
11038
|
let container = existing?.container;
|
|
11097
|
-
let isNewMount = false;
|
|
11098
11039
|
if (!container || !container.isConnected) {
|
|
11099
|
-
isNewMount = true;
|
|
11100
11040
|
existing?.root.unmount();
|
|
11101
11041
|
container?.remove();
|
|
11102
11042
|
container = document.createElement("div");
|
|
@@ -17089,7 +17029,7 @@ function apiBase() {
|
|
|
17089
17029
|
function bridgeVersion() {
|
|
17090
17030
|
try {
|
|
17091
17031
|
if (true) {
|
|
17092
|
-
return "0.1.
|
|
17032
|
+
return "0.1.153";
|
|
17093
17033
|
}
|
|
17094
17034
|
} catch {
|
|
17095
17035
|
}
|
|
@@ -17103,7 +17043,7 @@ function stampBridgeVersionOnDocument() {
|
|
|
17103
17043
|
return;
|
|
17104
17044
|
}
|
|
17105
17045
|
try {
|
|
17106
|
-
const v = true ? "0.1.
|
|
17046
|
+
const v = true ? "0.1.153" : "";
|
|
17107
17047
|
if (v) {
|
|
17108
17048
|
document.documentElement.setAttribute("data-ohw-bridge-version", v);
|
|
17109
17049
|
window.__OHW_BRIDGE_VERSION__ = v;
|
|
@@ -17768,7 +17708,6 @@ function MediaOverlay({
|
|
|
17768
17708
|
(prev) => prev && prev.fullWidth === width && prev.height === height ? prev : { fullWidth: width, height }
|
|
17769
17709
|
);
|
|
17770
17710
|
}, [isVideo]);
|
|
17771
|
-
const replaceLabel = isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image";
|
|
17772
17711
|
const replaceMode = buttonSize ? replaceButtonMode({ width: rect.width, height: rect.height }, buttonSize) : "none";
|
|
17773
17712
|
const box = {
|
|
17774
17713
|
position: "fixed",
|
|
@@ -17867,10 +17806,11 @@ function MediaOverlay({
|
|
|
17867
17806
|
className: "flex items-center justify-center cursor-pointer",
|
|
17868
17807
|
style: {
|
|
17869
17808
|
...box,
|
|
17870
|
-
//
|
|
17871
|
-
//
|
|
17872
|
-
//
|
|
17873
|
-
|
|
17809
|
+
// When text overlays this media, let clicks fall THROUGH to the text underneath. In the
|
|
17810
|
+
// parent this needed a whole `ow:click-at` round-trip to re-hit-test inside the iframe;
|
|
17811
|
+
// in-document, pointer-events does it natively. The button below opts back in, so
|
|
17812
|
+
// Replace still works.
|
|
17813
|
+
pointerEvents: hover.hasTextOverlap || cueOnly ? "none" : "auto",
|
|
17874
17814
|
// Selected: a firm component ring with no wash, so the image reads as chosen rather
|
|
17875
17815
|
// than hovered. Hover keeps the existing tinted preview.
|
|
17876
17816
|
boxShadow: selected ? "inset 0 0 0 2px var(--color-bridge-primary)" : "inset 0 0 0 1.5px var(--color-bridge-primary)",
|
|
@@ -17897,17 +17837,17 @@ function MediaOverlay({
|
|
|
17897
17837
|
},
|
|
17898
17838
|
children: [
|
|
17899
17839
|
isVideo ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react5.Film, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react5.ImageIcon, { size: 14 }),
|
|
17900
|
-
|
|
17840
|
+
isVideo ? "Replace video" : "Replace image"
|
|
17901
17841
|
]
|
|
17902
17842
|
}
|
|
17903
17843
|
),
|
|
17904
|
-
|
|
17844
|
+
replaceMode === "none" || cueOnly ? null : /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
17905
17845
|
Button,
|
|
17906
17846
|
{
|
|
17907
17847
|
"data-ohw-media-overlay": "",
|
|
17908
17848
|
variant: "outline",
|
|
17909
17849
|
size: "sm",
|
|
17910
|
-
"aria-label":
|
|
17850
|
+
"aria-label": isVideo ? "Replace video" : "Replace image",
|
|
17911
17851
|
className: "gap-1.5 cursor-pointer hover:bg-background",
|
|
17912
17852
|
style: {
|
|
17913
17853
|
...OVERLAY_BUTTON_STYLE,
|
|
@@ -17930,7 +17870,7 @@ function MediaOverlay({
|
|
|
17930
17870
|
},
|
|
17931
17871
|
children: [
|
|
17932
17872
|
isVideo ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react5.Film, { size: 14 }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react5.ImageIcon, { size: 14 }),
|
|
17933
|
-
replaceMode === "full" ?
|
|
17873
|
+
replaceMode === "full" ? isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image" : null
|
|
17934
17874
|
]
|
|
17935
17875
|
}
|
|
17936
17876
|
)
|
|
@@ -18440,7 +18380,7 @@ function AiSectionOverlay({
|
|
|
18440
18380
|
|
|
18441
18381
|
// src/ui/ai-section/AiMediaStripOverlay.tsx
|
|
18442
18382
|
var import_react10 = require("react");
|
|
18443
|
-
var
|
|
18383
|
+
var import_lucide_react8 = require("lucide-react");
|
|
18444
18384
|
|
|
18445
18385
|
// src/lib/ai-media-strip-tree.ts
|
|
18446
18386
|
var MEDIA_STRIP_ITEM_MIN = 1;
|
|
@@ -18554,6 +18494,14 @@ function setMediaStripItemAsset(tree, index, assetId) {
|
|
|
18554
18494
|
return true;
|
|
18555
18495
|
});
|
|
18556
18496
|
}
|
|
18497
|
+
function setMediaStripItemAlt(tree, index, alt) {
|
|
18498
|
+
return withMediaStrip(tree, (block) => {
|
|
18499
|
+
const items = block.items;
|
|
18500
|
+
if (index < 0 || index >= items.length) return false;
|
|
18501
|
+
items[index] = { ...items[index], alt };
|
|
18502
|
+
return true;
|
|
18503
|
+
});
|
|
18504
|
+
}
|
|
18557
18505
|
function setMediaStripItemLink(tree, index, link) {
|
|
18558
18506
|
return withMediaStrip(tree, (block) => {
|
|
18559
18507
|
const items = block.items;
|
|
@@ -18571,117 +18519,11 @@ function setMediaStripItemLink(tree, index, link) {
|
|
|
18571
18519
|
});
|
|
18572
18520
|
}
|
|
18573
18521
|
|
|
18574
|
-
// src/ui/dialog.tsx
|
|
18575
|
-
var React9 = __toESM(require("react"), 1);
|
|
18576
|
-
var import_radix_ui6 = require("radix-ui");
|
|
18577
|
-
var import_lucide_react8 = require("lucide-react");
|
|
18578
|
-
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
18579
|
-
function Dialog2({
|
|
18580
|
-
...props
|
|
18581
|
-
}) {
|
|
18582
|
-
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_radix_ui6.Dialog.Root, { "data-slot": "dialog", ...props });
|
|
18583
|
-
}
|
|
18584
|
-
function DialogPortal({
|
|
18585
|
-
...props
|
|
18586
|
-
}) {
|
|
18587
|
-
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_radix_ui6.Dialog.Portal, { ...props });
|
|
18588
|
-
}
|
|
18589
|
-
function DialogOverlay({
|
|
18590
|
-
className,
|
|
18591
|
-
...props
|
|
18592
|
-
}) {
|
|
18593
|
-
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18594
|
-
import_radix_ui6.Dialog.Overlay,
|
|
18595
|
-
{
|
|
18596
|
-
"data-slot": "dialog-overlay",
|
|
18597
|
-
"data-ohw-link-modal-root": "",
|
|
18598
|
-
className: cn("fixed inset-0 z-[2147483646] bg-black/50", className),
|
|
18599
|
-
...props
|
|
18600
|
-
}
|
|
18601
|
-
);
|
|
18602
|
-
}
|
|
18603
|
-
var DialogContent = React9.forwardRef(
|
|
18604
|
-
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
18605
|
-
const positionMode = container ? "absolute" : "fixed";
|
|
18606
|
-
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(DialogPortal, { container: container ?? void 0, children: [
|
|
18607
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
18608
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
18609
|
-
import_radix_ui6.Dialog.Content,
|
|
18610
|
-
{
|
|
18611
|
-
ref,
|
|
18612
|
-
"data-slot": "dialog-content",
|
|
18613
|
-
className: cn(
|
|
18614
|
-
positionMode,
|
|
18615
|
-
"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",
|
|
18616
|
-
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
18617
|
-
container ? "max-h-[calc(100%-32px)]" : "max-h-[calc(100vh-32px)]",
|
|
18618
|
-
className
|
|
18619
|
-
),
|
|
18620
|
-
onMouseDown: (e) => e.stopPropagation(),
|
|
18621
|
-
...props,
|
|
18622
|
-
children: [
|
|
18623
|
-
children,
|
|
18624
|
-
showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18625
|
-
import_radix_ui6.Dialog.Close,
|
|
18626
|
-
{
|
|
18627
|
-
type: "button",
|
|
18628
|
-
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
18629
|
-
"aria-label": "Close",
|
|
18630
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react8.X, { size: 16, "aria-hidden": true })
|
|
18631
|
-
}
|
|
18632
|
-
) : null
|
|
18633
|
-
]
|
|
18634
|
-
}
|
|
18635
|
-
)
|
|
18636
|
-
] });
|
|
18637
|
-
}
|
|
18638
|
-
);
|
|
18639
|
-
DialogContent.displayName = import_radix_ui6.Dialog.Content.displayName;
|
|
18640
|
-
function DialogHeader({
|
|
18641
|
-
className,
|
|
18642
|
-
...props
|
|
18643
|
-
}) {
|
|
18644
|
-
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
18645
|
-
}
|
|
18646
|
-
function DialogFooter({
|
|
18647
|
-
className,
|
|
18648
|
-
...props
|
|
18649
|
-
}) {
|
|
18650
|
-
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18651
|
-
"div",
|
|
18652
|
-
{
|
|
18653
|
-
className: cn("flex items-center justify-end gap-2", className),
|
|
18654
|
-
...props
|
|
18655
|
-
}
|
|
18656
|
-
);
|
|
18657
|
-
}
|
|
18658
|
-
var DialogTitle = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18659
|
-
import_radix_ui6.Dialog.Title,
|
|
18660
|
-
{
|
|
18661
|
-
ref,
|
|
18662
|
-
className: cn(
|
|
18663
|
-
"text-lg font-semibold leading-none tracking-tight text-card-foreground",
|
|
18664
|
-
className
|
|
18665
|
-
),
|
|
18666
|
-
...props
|
|
18667
|
-
}
|
|
18668
|
-
));
|
|
18669
|
-
DialogTitle.displayName = import_radix_ui6.Dialog.Title.displayName;
|
|
18670
|
-
var DialogDescription = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18671
|
-
import_radix_ui6.Dialog.Description,
|
|
18672
|
-
{
|
|
18673
|
-
ref,
|
|
18674
|
-
className: cn("text-sm text-muted-foreground", className),
|
|
18675
|
-
...props
|
|
18676
|
-
}
|
|
18677
|
-
));
|
|
18678
|
-
DialogDescription.displayName = import_radix_ui6.Dialog.Description.displayName;
|
|
18679
|
-
var DialogClose = import_radix_ui6.Dialog.Close;
|
|
18680
|
-
|
|
18681
18522
|
// src/ui/ai-section/AiMediaStripOverlay.tsx
|
|
18682
|
-
var
|
|
18683
|
-
var PRIMARY3 = "
|
|
18684
|
-
var
|
|
18523
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
18524
|
+
var PRIMARY3 = "#0885FE";
|
|
18525
|
+
var OHW_BLUE = `var(--ohw-primary, ${PRIMARY3})`;
|
|
18526
|
+
var OHW_BLUE_DARK = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY3}) 60%, #000000)`;
|
|
18685
18527
|
function findMediaStripItemElement(sectionId, index) {
|
|
18686
18528
|
const sectionEl = findByInstanceId(sectionId);
|
|
18687
18529
|
if (!sectionEl) return null;
|
|
@@ -18691,35 +18533,14 @@ function findMediaStripItemElement(sectionId, index) {
|
|
|
18691
18533
|
}
|
|
18692
18534
|
return null;
|
|
18693
18535
|
}
|
|
18694
|
-
function
|
|
18695
|
-
|
|
18696
|
-
if (target.closest(CHROME_SELECTOR)) return null;
|
|
18697
|
-
const itemEl = target.closest("[data-ohw-media-strip-item]");
|
|
18698
|
-
if (!itemEl) return null;
|
|
18699
|
-
const sectionEl = itemEl.closest("[data-ohw-section]");
|
|
18700
|
-
const unit = sectionEl ? movableUnit(sectionEl) : null;
|
|
18701
|
-
const sectionId = unit ? instanceIdOf(unit) || null : null;
|
|
18702
|
-
const index = Number(itemEl.dataset.ohwMediaStripIndex);
|
|
18703
|
-
if (!sectionId || Number.isNaN(index)) return null;
|
|
18704
|
-
return { sectionId, index };
|
|
18705
|
-
}
|
|
18706
|
-
function sameRef(a, b) {
|
|
18707
|
-
return a?.sectionId === b?.sectionId && a?.index === b?.index;
|
|
18708
|
-
}
|
|
18709
|
-
function rectOf(el) {
|
|
18536
|
+
function readRect2(ref) {
|
|
18537
|
+
const el = ref && findMediaStripItemElement(ref.sectionId, ref.index);
|
|
18710
18538
|
if (!el) return null;
|
|
18711
18539
|
const r2 = el.getBoundingClientRect();
|
|
18712
18540
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
18713
18541
|
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
18714
18542
|
}
|
|
18715
|
-
function
|
|
18716
|
-
return rectOf(ref && findMediaStripItemElement(ref.sectionId, ref.index));
|
|
18717
|
-
}
|
|
18718
|
-
function readStripRect(ref) {
|
|
18719
|
-
const item = ref && findMediaStripItemElement(ref.sectionId, ref.index);
|
|
18720
|
-
return rectOf(item?.closest("[data-ohw-media-strip]") ?? item);
|
|
18721
|
-
}
|
|
18722
|
-
function useLiveItemRect(ref, strip = false) {
|
|
18543
|
+
function useLiveItemRect(ref) {
|
|
18723
18544
|
const [rect, setRect] = (0, import_react10.useState)(null);
|
|
18724
18545
|
(0, import_react10.useEffect)(() => {
|
|
18725
18546
|
if (!ref) {
|
|
@@ -18727,7 +18548,7 @@ function useLiveItemRect(ref, strip = false) {
|
|
|
18727
18548
|
return;
|
|
18728
18549
|
}
|
|
18729
18550
|
const update = () => {
|
|
18730
|
-
const next =
|
|
18551
|
+
const next = readRect2(ref);
|
|
18731
18552
|
setRect(
|
|
18732
18553
|
(prev) => prev && next && prev.top === next.top && prev.left === next.left && prev.width === next.width && prev.height === next.height ? prev : next
|
|
18733
18554
|
);
|
|
@@ -18742,49 +18563,9 @@ function useLiveItemRect(ref, strip = false) {
|
|
|
18742
18563
|
window.removeEventListener("resize", update);
|
|
18743
18564
|
clearInterval(interval);
|
|
18744
18565
|
};
|
|
18745
|
-
}, [ref?.sectionId, ref?.index
|
|
18566
|
+
}, [ref?.sectionId, ref?.index]);
|
|
18746
18567
|
return rect;
|
|
18747
18568
|
}
|
|
18748
|
-
var TOOLBAR_STRIP_GAP = 52;
|
|
18749
|
-
var TOOLBAR_STRIP_GAP_MOBILE = 42;
|
|
18750
|
-
var TOOLBAR_EDGE_MARGIN2 = 4;
|
|
18751
|
-
function StripToolbarSlot({ stripRect, children }) {
|
|
18752
|
-
const slotRef = (0, import_react10.useRef)(null);
|
|
18753
|
-
const [shift, setShift] = (0, import_react10.useState)(0);
|
|
18754
|
-
const centerX = stripRect.left + stripRect.width / 2;
|
|
18755
|
-
(0, import_react10.useLayoutEffect)(() => {
|
|
18756
|
-
const slot = slotRef.current;
|
|
18757
|
-
if (!slot) return;
|
|
18758
|
-
const clamp = () => {
|
|
18759
|
-
const w = slot.offsetWidth;
|
|
18760
|
-
if (w <= 0) return;
|
|
18761
|
-
const half = w / 2;
|
|
18762
|
-
const clamped = Math.max(TOOLBAR_EDGE_MARGIN2 + half, Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN2 - half));
|
|
18763
|
-
setShift((prev) => Math.abs(prev - (clamped - centerX)) < 0.5 ? prev : clamped - centerX);
|
|
18764
|
-
};
|
|
18765
|
-
clamp();
|
|
18766
|
-
const ro = new ResizeObserver(clamp);
|
|
18767
|
-
ro.observe(slot);
|
|
18768
|
-
return () => ro.disconnect();
|
|
18769
|
-
}, [centerX, children]);
|
|
18770
|
-
const mobile = window.innerWidth <= 480;
|
|
18771
|
-
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
18772
|
-
"div",
|
|
18773
|
-
{
|
|
18774
|
-
ref: slotRef,
|
|
18775
|
-
"data-ohw-bridge": "",
|
|
18776
|
-
"data-ohw-item-interaction": "",
|
|
18777
|
-
className: "pointer-events-auto fixed",
|
|
18778
|
-
style: {
|
|
18779
|
-
top: stripRect.top - (mobile ? TOOLBAR_STRIP_GAP_MOBILE : TOOLBAR_STRIP_GAP),
|
|
18780
|
-
left: centerX + shift,
|
|
18781
|
-
transform: "translate(-50%, -100%)",
|
|
18782
|
-
zIndex: 2147483645
|
|
18783
|
-
},
|
|
18784
|
-
children
|
|
18785
|
-
}
|
|
18786
|
-
);
|
|
18787
|
-
}
|
|
18788
18569
|
function requestValidateTree(postToParent2, tree) {
|
|
18789
18570
|
return new Promise((resolve) => {
|
|
18790
18571
|
const id = `ai-validate-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
@@ -18821,177 +18602,221 @@ function requestAssetPick(postToParent2) {
|
|
|
18821
18602
|
postToParent2({ type: "ow:asset-pick", id });
|
|
18822
18603
|
});
|
|
18823
18604
|
}
|
|
18824
|
-
function
|
|
18605
|
+
function Pill({
|
|
18825
18606
|
label,
|
|
18826
18607
|
onClick,
|
|
18827
|
-
disabled
|
|
18828
|
-
active
|
|
18829
|
-
children
|
|
18608
|
+
disabled,
|
|
18609
|
+
active
|
|
18830
18610
|
}) {
|
|
18831
|
-
|
|
18832
|
-
|
|
18833
|
-
|
|
18834
|
-
|
|
18835
|
-
|
|
18836
|
-
|
|
18837
|
-
|
|
18838
|
-
|
|
18611
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18612
|
+
"button",
|
|
18613
|
+
{
|
|
18614
|
+
type: "button",
|
|
18615
|
+
onClick,
|
|
18616
|
+
disabled,
|
|
18617
|
+
style: {
|
|
18618
|
+
height: 28,
|
|
18619
|
+
padding: "0 10px",
|
|
18620
|
+
display: "inline-flex",
|
|
18621
|
+
alignItems: "center",
|
|
18622
|
+
gap: 4,
|
|
18623
|
+
borderRadius: 999,
|
|
18624
|
+
border: "none",
|
|
18625
|
+
cursor: disabled ? "default" : "pointer",
|
|
18626
|
+
background: active ? OHW_BLUE_DARK : "#ffffff",
|
|
18627
|
+
color: active ? "#ffffff" : OHW_BLUE_DARK,
|
|
18628
|
+
opacity: disabled ? 0.4 : 1,
|
|
18629
|
+
fontSize: 12,
|
|
18630
|
+
lineHeight: "16px",
|
|
18631
|
+
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
18632
|
+
whiteSpace: "nowrap",
|
|
18633
|
+
flex: "0 0 auto"
|
|
18634
|
+
},
|
|
18635
|
+
children: label
|
|
18636
|
+
}
|
|
18637
|
+
);
|
|
18839
18638
|
}
|
|
18840
|
-
function
|
|
18841
|
-
|
|
18842
|
-
value,
|
|
18843
|
-
|
|
18844
|
-
|
|
18845
|
-
|
|
18846
|
-
|
|
18847
|
-
|
|
18848
|
-
|
|
18849
|
-
|
|
18850
|
-
|
|
18851
|
-
"
|
|
18852
|
-
|
|
18853
|
-
|
|
18854
|
-
|
|
18855
|
-
|
|
18856
|
-
|
|
18857
|
-
|
|
18858
|
-
|
|
18859
|
-
|
|
18860
|
-
|
|
18861
|
-
) }),
|
|
18862
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DropdownMenuContent, { align: "end", sideOffset: 8, className: "w-[132px] min-w-[132px] p-1", children: options.map((option) => {
|
|
18863
|
-
const selected = option.value === value;
|
|
18864
|
-
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
18865
|
-
DropdownMenuItem,
|
|
18639
|
+
function AltInput({ value, onCommit }) {
|
|
18640
|
+
const [draft, setDraft] = (0, import_react10.useState)(value);
|
|
18641
|
+
(0, import_react10.useEffect)(() => setDraft(value), [value]);
|
|
18642
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
18643
|
+
"div",
|
|
18644
|
+
{
|
|
18645
|
+
style: {
|
|
18646
|
+
display: "flex",
|
|
18647
|
+
alignItems: "center",
|
|
18648
|
+
gap: 6,
|
|
18649
|
+
height: 28,
|
|
18650
|
+
padding: "0 12px",
|
|
18651
|
+
borderRadius: 999,
|
|
18652
|
+
background: "#ffffff",
|
|
18653
|
+
width: "100%",
|
|
18654
|
+
maxWidth: 260,
|
|
18655
|
+
boxSizing: "border-box"
|
|
18656
|
+
},
|
|
18657
|
+
children: [
|
|
18658
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18659
|
+
"span",
|
|
18866
18660
|
{
|
|
18867
|
-
|
|
18868
|
-
|
|
18869
|
-
|
|
18870
|
-
|
|
18871
|
-
|
|
18872
|
-
|
|
18873
|
-
|
|
18874
|
-
|
|
18875
|
-
|
|
18876
|
-
|
|
18877
|
-
)
|
|
18878
|
-
|
|
18879
|
-
|
|
18880
|
-
|
|
18881
|
-
|
|
18882
|
-
|
|
18883
|
-
|
|
18884
|
-
|
|
18885
|
-
|
|
18886
|
-
|
|
18887
|
-
|
|
18888
|
-
|
|
18889
|
-
|
|
18890
|
-
|
|
18891
|
-
|
|
18892
|
-
|
|
18893
|
-
|
|
18661
|
+
style: {
|
|
18662
|
+
flex: "0 0 auto",
|
|
18663
|
+
color: OHW_BLUE_DARK,
|
|
18664
|
+
fontSize: 10,
|
|
18665
|
+
fontWeight: 700,
|
|
18666
|
+
textTransform: "uppercase",
|
|
18667
|
+
letterSpacing: 0.4
|
|
18668
|
+
},
|
|
18669
|
+
children: "Alt"
|
|
18670
|
+
}
|
|
18671
|
+
),
|
|
18672
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18673
|
+
"input",
|
|
18674
|
+
{
|
|
18675
|
+
type: "text",
|
|
18676
|
+
value: draft,
|
|
18677
|
+
onChange: (e) => setDraft(e.target.value),
|
|
18678
|
+
onBlur: () => {
|
|
18679
|
+
if (draft !== value) onCommit(draft);
|
|
18680
|
+
},
|
|
18681
|
+
onKeyDown: (e) => {
|
|
18682
|
+
if (e.key === "Enter") e.currentTarget.blur();
|
|
18683
|
+
if (e.key === "Escape") {
|
|
18684
|
+
setDraft(value);
|
|
18685
|
+
e.currentTarget.blur();
|
|
18686
|
+
}
|
|
18687
|
+
},
|
|
18688
|
+
placeholder: "Describe this image",
|
|
18689
|
+
"aria-label": "Image alt text",
|
|
18690
|
+
style: {
|
|
18691
|
+
flex: 1,
|
|
18692
|
+
minWidth: 0,
|
|
18693
|
+
border: "none",
|
|
18694
|
+
outline: "none",
|
|
18695
|
+
background: "transparent",
|
|
18696
|
+
fontSize: 12,
|
|
18697
|
+
lineHeight: "16px",
|
|
18698
|
+
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
18699
|
+
color: "#1f2937"
|
|
18700
|
+
}
|
|
18701
|
+
}
|
|
18702
|
+
)
|
|
18703
|
+
]
|
|
18704
|
+
}
|
|
18705
|
+
);
|
|
18706
|
+
}
|
|
18707
|
+
var VARIANTS = [
|
|
18708
|
+
{ value: "logos", label: "Logos" },
|
|
18709
|
+
{ value: "reel", label: "Reel" }
|
|
18710
|
+
];
|
|
18711
|
+
var ALIGNS = [
|
|
18712
|
+
{ value: "left", label: "Left" },
|
|
18713
|
+
{ value: "center", label: "Center" },
|
|
18714
|
+
{ value: "right", label: "Right" }
|
|
18715
|
+
];
|
|
18716
|
+
var HOVERS = [
|
|
18717
|
+
{ value: "none", label: "None" },
|
|
18718
|
+
{ value: "lift", label: "Lift" },
|
|
18894
18719
|
{ value: "zoom", label: "Zoom" },
|
|
18895
18720
|
{ value: "fade", label: "Fade" }
|
|
18896
18721
|
];
|
|
18722
|
+
var TREATMENTS = [
|
|
18723
|
+
{ value: "color", label: "Color" },
|
|
18724
|
+
{ value: "grayscale", label: "Grayscale" }
|
|
18725
|
+
];
|
|
18897
18726
|
var HTTP_URL_RE = /^https?:\/\/\S+$/i;
|
|
18898
|
-
function
|
|
18899
|
-
|
|
18900
|
-
linkTarget,
|
|
18901
|
-
onClose,
|
|
18902
|
-
onSave
|
|
18903
|
-
}) {
|
|
18904
|
-
const [draft, setDraft] = (0, import_react10.useState)(href);
|
|
18905
|
-
const [newTab, setNewTab] = (0, import_react10.useState)(linkTarget !== "same-tab");
|
|
18727
|
+
function LinkInput({ value, onCommit }) {
|
|
18728
|
+
const [draft, setDraft] = (0, import_react10.useState)(value);
|
|
18906
18729
|
const [invalid, setInvalid] = (0, import_react10.useState)(false);
|
|
18907
|
-
|
|
18730
|
+
(0, import_react10.useEffect)(() => {
|
|
18731
|
+
setDraft(value);
|
|
18732
|
+
setInvalid(false);
|
|
18733
|
+
}, [value]);
|
|
18734
|
+
const commit = () => {
|
|
18908
18735
|
const next = draft.trim();
|
|
18909
|
-
if (next
|
|
18910
|
-
|
|
18911
|
-
|
|
18912
|
-
|
|
18913
|
-
onSave(next, newTab ? "new-tab" : "same-tab");
|
|
18914
|
-
onClose();
|
|
18736
|
+
if (next === value) return setInvalid(false);
|
|
18737
|
+
if (next && !HTTP_URL_RE.test(next)) return setInvalid(true);
|
|
18738
|
+
setInvalid(false);
|
|
18739
|
+
onCommit(next);
|
|
18915
18740
|
};
|
|
18916
|
-
return /* @__PURE__ */ (0,
|
|
18917
|
-
|
|
18918
|
-
|
|
18919
|
-
|
|
18920
|
-
"
|
|
18921
|
-
|
|
18922
|
-
|
|
18923
|
-
|
|
18924
|
-
|
|
18925
|
-
|
|
18926
|
-
|
|
18927
|
-
|
|
18928
|
-
|
|
18929
|
-
|
|
18930
|
-
|
|
18931
|
-
|
|
18932
|
-
|
|
18933
|
-
|
|
18934
|
-
"
|
|
18935
|
-
|
|
18936
|
-
|
|
18937
|
-
|
|
18938
|
-
|
|
18939
|
-
|
|
18940
|
-
|
|
18941
|
-
|
|
18942
|
-
|
|
18943
|
-
|
|
18944
|
-
|
|
18945
|
-
|
|
18946
|
-
|
|
18947
|
-
|
|
18948
|
-
|
|
18949
|
-
|
|
18950
|
-
|
|
18951
|
-
|
|
18952
|
-
|
|
18953
|
-
|
|
18954
|
-
|
|
18955
|
-
|
|
18956
|
-
|
|
18957
|
-
|
|
18958
|
-
|
|
18959
|
-
|
|
18960
|
-
|
|
18961
|
-
|
|
18962
|
-
|
|
18963
|
-
|
|
18964
|
-
|
|
18965
|
-
|
|
18966
|
-
|
|
18967
|
-
|
|
18968
|
-
|
|
18969
|
-
|
|
18970
|
-
|
|
18971
|
-
|
|
18972
|
-
|
|
18973
|
-
|
|
18974
|
-
|
|
18975
|
-
|
|
18976
|
-
|
|
18977
|
-
|
|
18978
|
-
|
|
18979
|
-
|
|
18980
|
-
|
|
18741
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
18742
|
+
"div",
|
|
18743
|
+
{
|
|
18744
|
+
style: {
|
|
18745
|
+
display: "flex",
|
|
18746
|
+
alignItems: "center",
|
|
18747
|
+
gap: 6,
|
|
18748
|
+
height: 28,
|
|
18749
|
+
padding: "0 12px",
|
|
18750
|
+
borderRadius: 999,
|
|
18751
|
+
background: "#ffffff",
|
|
18752
|
+
width: "100%",
|
|
18753
|
+
maxWidth: 260,
|
|
18754
|
+
boxSizing: "border-box",
|
|
18755
|
+
boxShadow: invalid ? "inset 0 0 0 1.5px #EF4444" : "none"
|
|
18756
|
+
},
|
|
18757
|
+
children: [
|
|
18758
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18759
|
+
"span",
|
|
18760
|
+
{
|
|
18761
|
+
style: {
|
|
18762
|
+
flex: "0 0 auto",
|
|
18763
|
+
color: OHW_BLUE_DARK,
|
|
18764
|
+
fontSize: 10,
|
|
18765
|
+
fontWeight: 700,
|
|
18766
|
+
textTransform: "uppercase",
|
|
18767
|
+
letterSpacing: 0.4
|
|
18768
|
+
},
|
|
18769
|
+
children: "Link"
|
|
18770
|
+
}
|
|
18771
|
+
),
|
|
18772
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18773
|
+
"input",
|
|
18774
|
+
{
|
|
18775
|
+
type: "text",
|
|
18776
|
+
inputMode: "url",
|
|
18777
|
+
value: draft,
|
|
18778
|
+
onChange: (e) => setDraft(e.target.value),
|
|
18779
|
+
onBlur: commit,
|
|
18780
|
+
onKeyDown: (e) => {
|
|
18781
|
+
if (e.key === "Enter") e.currentTarget.blur();
|
|
18782
|
+
if (e.key === "Escape") {
|
|
18783
|
+
setDraft(value);
|
|
18784
|
+
setInvalid(false);
|
|
18785
|
+
e.currentTarget.blur();
|
|
18786
|
+
}
|
|
18787
|
+
},
|
|
18788
|
+
placeholder: "https://example.com",
|
|
18789
|
+
"aria-label": "Image link URL",
|
|
18790
|
+
"aria-invalid": invalid,
|
|
18791
|
+
style: {
|
|
18792
|
+
flex: 1,
|
|
18793
|
+
minWidth: 0,
|
|
18794
|
+
border: "none",
|
|
18795
|
+
outline: "none",
|
|
18796
|
+
background: "transparent",
|
|
18797
|
+
fontSize: 12,
|
|
18798
|
+
lineHeight: "16px",
|
|
18799
|
+
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
18800
|
+
color: "#1f2937"
|
|
18801
|
+
}
|
|
18802
|
+
}
|
|
18803
|
+
)
|
|
18804
|
+
]
|
|
18805
|
+
}
|
|
18806
|
+
);
|
|
18981
18807
|
}
|
|
18982
18808
|
function MediaStripToolbar({
|
|
18983
18809
|
entry,
|
|
18984
18810
|
index,
|
|
18985
18811
|
pending,
|
|
18986
18812
|
error,
|
|
18987
|
-
itemEditOn,
|
|
18988
|
-
onToggleItemEdit,
|
|
18989
18813
|
onSetVariant,
|
|
18990
18814
|
onSetAlign,
|
|
18991
18815
|
onSetHover,
|
|
18992
18816
|
onSetTreatment,
|
|
18993
18817
|
onResize,
|
|
18994
|
-
|
|
18818
|
+
onSetAlt,
|
|
18819
|
+
onSetLink,
|
|
18995
18820
|
onAddItem,
|
|
18996
18821
|
onRemoveItem,
|
|
18997
18822
|
onChangeImage,
|
|
@@ -19000,102 +18825,81 @@ function MediaStripToolbar({
|
|
|
19000
18825
|
}) {
|
|
19001
18826
|
const items = mediaStripItems(entry.tree);
|
|
19002
18827
|
const itemCount = items.length;
|
|
18828
|
+
const currentAlt = items[index]?.alt ?? "";
|
|
18829
|
+
const currentHref = items[index]?.href ?? "";
|
|
18830
|
+
const currentTarget = items[index]?.linkTarget === "same-tab" ? "same-tab" : "new-tab";
|
|
19003
18831
|
const slots = findMediaStripSlots(entry.tree);
|
|
19004
18832
|
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
19005
18833
|
const align = slots?.align === "left" || slots?.align === "right" ? slots.align : "center";
|
|
19006
18834
|
const hover = slots?.hover === "none" || slots?.hover === "lift" || slots?.hover === "zoom" || slots?.hover === "fade" ? slots.hover : "lift";
|
|
19007
18835
|
const treatment = slots?.treatment === "color" || slots?.treatment === "grayscale" ? slots.treatment : variant === "logos" ? "grayscale" : "color";
|
|
19008
18836
|
const sizeValue = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
19009
|
-
const
|
|
19010
|
-
const
|
|
19011
|
-
|
|
18837
|
+
const isMobile = window.innerWidth <= 480;
|
|
18838
|
+
const rowStyle = isMobile ? {
|
|
18839
|
+
display: "flex",
|
|
18840
|
+
gap: 6,
|
|
18841
|
+
flexWrap: "nowrap",
|
|
18842
|
+
justifyContent: "center",
|
|
18843
|
+
overflowX: "auto",
|
|
18844
|
+
WebkitOverflowScrolling: "touch",
|
|
18845
|
+
width: "100%",
|
|
18846
|
+
scrollbarWidth: "none"
|
|
18847
|
+
} : { display: "flex", gap: 6, flexWrap: "nowrap", justifyContent: "center" };
|
|
18848
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
19012
18849
|
"div",
|
|
19013
18850
|
{
|
|
19014
18851
|
"data-ohw-bridge": "",
|
|
19015
18852
|
"data-ohw-toolbar": "",
|
|
19016
18853
|
onMouseDown: (e) => e.stopPropagation(),
|
|
19017
|
-
|
|
19018
|
-
|
|
18854
|
+
style: {
|
|
18855
|
+
display: "flex",
|
|
18856
|
+
flexDirection: "column",
|
|
18857
|
+
gap: 6,
|
|
18858
|
+
alignItems: "center",
|
|
18859
|
+
background: OHW_BLUE,
|
|
18860
|
+
padding: 8,
|
|
18861
|
+
borderRadius: 12,
|
|
18862
|
+
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
18863
|
+
pointerEvents: pending ? "none" : "auto",
|
|
18864
|
+
opacity: pending ? 0.6 : 1,
|
|
18865
|
+
maxWidth: isMobile ? "calc(100vw - 24px)" : "none"
|
|
18866
|
+
},
|
|
19019
18867
|
children: [
|
|
19020
|
-
/* @__PURE__ */ (0,
|
|
19021
|
-
|
|
19022
|
-
{
|
|
19023
|
-
|
|
19024
|
-
|
|
19025
|
-
|
|
19026
|
-
|
|
19027
|
-
|
|
19028
|
-
|
|
19029
|
-
|
|
19030
|
-
|
|
19031
|
-
|
|
19032
|
-
|
|
19033
|
-
|
|
19034
|
-
|
|
19035
|
-
|
|
19036
|
-
|
|
19037
|
-
|
|
19038
|
-
|
|
19039
|
-
|
|
19040
|
-
|
|
19041
|
-
|
|
19042
|
-
|
|
19043
|
-
|
|
19044
|
-
|
|
19045
|
-
|
|
19046
|
-
|
|
19047
|
-
|
|
19048
|
-
|
|
19049
|
-
|
|
19050
|
-
|
|
19051
|
-
|
|
19052
|
-
) }),
|
|
19053
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: itemEditOn ? "Done editing this image" : "Edit this image" })
|
|
19054
|
-
] }),
|
|
19055
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19056
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: gatedLabel("Change image"), onClick: onChangeImage, disabled: !itemEditOn, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Image, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19057
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: gatedLabel("Link"), onClick: onOpenLink, disabled: !itemEditOn, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Link, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19058
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: gatedLabel("Move left"), onClick: onMoveLeft, disabled: !itemEditOn || index <= 0, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.ArrowLeft, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19059
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19060
|
-
ToolbarAction,
|
|
19061
|
-
{
|
|
19062
|
-
label: gatedLabel("Move right"),
|
|
19063
|
-
onClick: onMoveRight,
|
|
19064
|
-
disabled: !itemEditOn || index >= itemCount - 1,
|
|
19065
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.ArrowRight, { size: 16, style: { pointerEvents: "none" } })
|
|
19066
|
-
}
|
|
19067
|
-
),
|
|
19068
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: gatedLabel("Remove image"), onClick: onRemoveItem, disabled: !itemEditOn || itemCount <= 1, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.ImageMinus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19069
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19070
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(OptionMenu, { label: "Layout", value: variant, options: VARIANTS, onChange: onSetVariant }),
|
|
19071
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(OptionMenu, { label: "Hover", value: hover, options: HOVERS, onChange: onSetHover }),
|
|
19072
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19073
|
-
ToolbarAction,
|
|
19074
|
-
{
|
|
19075
|
-
label: treatment === "grayscale" ? "Show in color" : "Show grayscale",
|
|
19076
|
-
active: treatment === "grayscale",
|
|
19077
|
-
onClick: () => onSetTreatment(treatment === "grayscale" ? "color" : "grayscale"),
|
|
19078
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Palette, { size: 16, style: { pointerEvents: "none" } })
|
|
19079
|
-
}
|
|
19080
|
-
),
|
|
19081
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19082
|
-
ALIGNS.map(({ value, label, Icon }) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label, active: align === value, onClick: () => onSetAlign(value), children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Icon, { size: 16, style: { pointerEvents: "none" } }) }, value)),
|
|
19083
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19084
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: "Smaller", onClick: () => onResize(-8), children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Minus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19085
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "min-w-[40px] text-center text-xs tabular-nums text-muted-foreground", children: [
|
|
19086
|
-
sizeValue,
|
|
19087
|
-
"px"
|
|
19088
|
-
] }),
|
|
19089
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: "Larger", onClick: () => onResize(8), children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Plus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19090
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19091
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: "Add image", onClick: onAddItem, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.ImagePlus, { size: 16, style: { pointerEvents: "none" } }) })
|
|
19092
|
-
]
|
|
19093
|
-
}
|
|
19094
|
-
),
|
|
19095
|
-
error && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "max-w-[260px] rounded-md bg-background px-2 py-1 text-center text-[11px] text-destructive shadow-sm", children: error })
|
|
18868
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: rowStyle, children: [
|
|
18869
|
+
VARIANTS.map((v) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Pill, { label: v.label, active: variant === v.value, onClick: () => onSetVariant(v.value) }, v.value)),
|
|
18870
|
+
ALIGNS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Pill, { label: a.label, active: align === a.value, onClick: () => onSetAlign(a.value) }, a.value))
|
|
18871
|
+
] }),
|
|
18872
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: rowStyle, children: [
|
|
18873
|
+
HOVERS.map((h) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Pill, { label: h.label, active: hover === h.value, onClick: () => onSetHover(h.value) }, h.value)),
|
|
18874
|
+
TREATMENTS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Pill, { label: t.label, active: treatment === t.value, onClick: () => onSetTreatment(t.value) }, t.value))
|
|
18875
|
+
] }),
|
|
18876
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { display: "flex", gap: 6, alignItems: "center" }, children: [
|
|
18877
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Pill, { label: "\u2212", onClick: () => onResize(-8) }),
|
|
18878
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { style: { color: "#ffffff", fontSize: 12, minWidth: 34, textAlign: "center" }, children: [
|
|
18879
|
+
sizeValue,
|
|
18880
|
+
"px"
|
|
18881
|
+
] }),
|
|
18882
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Pill, { label: "+", onClick: () => onResize(8) })
|
|
18883
|
+
] }),
|
|
18884
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { display: "flex", justifyContent: "center", width: "100%" }, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(AltInput, { value: currentAlt, onCommit: onSetAlt }) }),
|
|
18885
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { display: "flex", justifyContent: "center", width: "100%" }, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(LinkInput, { value: currentHref, onCommit: (href) => onSetLink(href, currentTarget) }) }),
|
|
18886
|
+
currentHref && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: rowStyle, children: [
|
|
18887
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Pill, { label: "New tab", active: currentTarget === "new-tab", onClick: () => onSetLink(currentHref, "new-tab") }),
|
|
18888
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Pill, { label: "Same tab", active: currentTarget === "same-tab", onClick: () => onSetLink(currentHref, "same-tab") })
|
|
18889
|
+
] }),
|
|
18890
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: rowStyle, children: [
|
|
18891
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Pill, { label: "Change Image", onClick: onChangeImage }),
|
|
18892
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Pill, { label: "+ Item", onClick: onAddItem }),
|
|
18893
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Pill, { label: "\u2212 Item", onClick: onRemoveItem, disabled: itemCount <= 1 })
|
|
18894
|
+
] }),
|
|
18895
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: rowStyle, children: [
|
|
18896
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Pill, { label: "\u2190 Move", onClick: onMoveLeft, disabled: index <= 0 }),
|
|
18897
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Pill, { label: "\u2192 Move", onClick: onMoveRight, disabled: index >= itemCount - 1 })
|
|
18898
|
+
] }),
|
|
18899
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { color: "#FCA5A5", fontSize: 11, maxWidth: 220, textAlign: "center" }, children: error })
|
|
19096
18900
|
]
|
|
19097
18901
|
}
|
|
19098
|
-
)
|
|
18902
|
+
);
|
|
19099
18903
|
}
|
|
19100
18904
|
function findMediaStripSlots(tree) {
|
|
19101
18905
|
const stack = tree.rows.flatMap((row) => row.blocks);
|
|
@@ -19114,23 +18918,31 @@ function AiMediaStripOverlay({
|
|
|
19114
18918
|
}) {
|
|
19115
18919
|
const [hover, setHover] = (0, import_react10.useState)(null);
|
|
19116
18920
|
const [active, setActive] = (0, import_react10.useState)(null);
|
|
19117
|
-
const [itemEditOn, setItemEditOn] = (0, import_react10.useState)(false);
|
|
19118
|
-
const [linkOpen, setLinkOpen] = (0, import_react10.useState)(false);
|
|
19119
18921
|
const [pending, setPending] = (0, import_react10.useState)(false);
|
|
19120
18922
|
const [error, setError] = (0, import_react10.useState)(null);
|
|
19121
18923
|
const activeRef = (0, import_react10.useRef)(null);
|
|
19122
18924
|
activeRef.current = active;
|
|
19123
|
-
const linkOpenRef = (0, import_react10.useRef)(false);
|
|
19124
|
-
linkOpenRef.current = linkOpen;
|
|
19125
18925
|
(0, import_react10.useEffect)(() => {
|
|
19126
18926
|
const onMove = (e) => {
|
|
19127
|
-
const ref = itemRefFromTarget(e.target);
|
|
19128
18927
|
const t = e.target;
|
|
19129
|
-
|
|
19130
|
-
|
|
19131
|
-
|
|
19132
|
-
|
|
19133
|
-
|
|
18928
|
+
if (!(t instanceof HTMLElement)) return;
|
|
18929
|
+
if (t.closest("[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-link-modal-root], [data-ohw-section-picker], [data-ohw-ai-review]")) {
|
|
18930
|
+
return;
|
|
18931
|
+
}
|
|
18932
|
+
const itemEl = t.closest("[data-ohw-media-strip-item]");
|
|
18933
|
+
if (!itemEl) {
|
|
18934
|
+
setHover(null);
|
|
18935
|
+
return;
|
|
18936
|
+
}
|
|
18937
|
+
const sectionEl = itemEl.closest("[data-ohw-section]");
|
|
18938
|
+
const unit = sectionEl ? movableUnit(sectionEl) : null;
|
|
18939
|
+
const sectionId = unit ? instanceIdOf(unit) || null : null;
|
|
18940
|
+
const index = Number(itemEl.dataset.ohwMediaStripIndex);
|
|
18941
|
+
if (!sectionId || Number.isNaN(index)) {
|
|
18942
|
+
setHover(null);
|
|
18943
|
+
return;
|
|
18944
|
+
}
|
|
18945
|
+
setHover({ sectionId, index });
|
|
19134
18946
|
};
|
|
19135
18947
|
const onLeave = () => setHover(null);
|
|
19136
18948
|
document.addEventListener("mousemove", onMove, { passive: true });
|
|
@@ -19142,25 +18954,23 @@ function AiMediaStripOverlay({
|
|
|
19142
18954
|
}, []);
|
|
19143
18955
|
(0, import_react10.useEffect)(() => {
|
|
19144
18956
|
const onClick = (e) => {
|
|
18957
|
+
const current = activeRef.current;
|
|
18958
|
+
if (!current) return;
|
|
19145
18959
|
const t = e.target;
|
|
19146
|
-
if (!(t instanceof
|
|
19147
|
-
if (t.closest(
|
|
19148
|
-
const
|
|
19149
|
-
if (
|
|
19150
|
-
|
|
19151
|
-
setItemEditOn(false);
|
|
18960
|
+
if (!(t instanceof HTMLElement)) return;
|
|
18961
|
+
if (t.closest("[data-ohw-item-interaction]")) return;
|
|
18962
|
+
const itemEl = findMediaStripItemElement(current.sectionId, current.index);
|
|
18963
|
+
if (itemEl && itemEl.contains(t)) return;
|
|
18964
|
+
setActive(null);
|
|
19152
18965
|
setError(null);
|
|
19153
|
-
setActive(ref);
|
|
19154
18966
|
};
|
|
19155
18967
|
document.addEventListener("click", onClick, true);
|
|
19156
18968
|
return () => document.removeEventListener("click", onClick, true);
|
|
19157
|
-
}, [
|
|
18969
|
+
}, []);
|
|
19158
18970
|
(0, import_react10.useEffect)(() => {
|
|
19159
18971
|
const onBlur = () => {
|
|
19160
18972
|
if (!activeRef.current) return;
|
|
19161
18973
|
setActive(null);
|
|
19162
|
-
setItemEditOn(false);
|
|
19163
|
-
setLinkOpen(false);
|
|
19164
18974
|
setError(null);
|
|
19165
18975
|
};
|
|
19166
18976
|
window.addEventListener("blur", onBlur);
|
|
@@ -19170,10 +18980,7 @@ function AiMediaStripOverlay({
|
|
|
19170
18980
|
const onKeyDown = (e) => {
|
|
19171
18981
|
if (e.key !== "Escape") return;
|
|
19172
18982
|
if (!activeRef.current) return;
|
|
19173
|
-
if (linkOpenRef.current) return;
|
|
19174
|
-
if (document.querySelector('[data-ohw-more-menu][data-state="open"]')) return;
|
|
19175
18983
|
setActive(null);
|
|
19176
|
-
setItemEditOn(false);
|
|
19177
18984
|
setError(null);
|
|
19178
18985
|
};
|
|
19179
18986
|
document.addEventListener("keydown", onKeyDown);
|
|
@@ -19207,133 +19014,137 @@ function AiMediaStripOverlay({
|
|
|
19207
19014
|
tree: nextTree,
|
|
19208
19015
|
label: entry.label,
|
|
19209
19016
|
media: extraMedia ? { ...entry.media, ...extraMedia } : entry.media,
|
|
19210
|
-
...entry.brand ? { brand: entry.brand } : {}
|
|
19211
|
-
// The user is already looking at the strip they just edited — recentering the viewport
|
|
19212
|
-
// on every edit reads as the section jumping around.
|
|
19213
|
-
skipScrollIntoView: true
|
|
19017
|
+
...entry.brand ? { brand: entry.brand } : {}
|
|
19214
19018
|
});
|
|
19215
19019
|
return true;
|
|
19216
19020
|
},
|
|
19217
19021
|
[findEntry, postToParent2, applyTreeLocalRef]
|
|
19218
19022
|
);
|
|
19219
19023
|
const activeEntry = active ? findEntry(active.sectionId) : null;
|
|
19024
|
+
const hoverHandleRect = useLiveItemRect(!active && hover ? hover : null);
|
|
19220
19025
|
const activeItemRect = useLiveItemRect(active);
|
|
19221
|
-
const
|
|
19222
|
-
const
|
|
19223
|
-
|
|
19224
|
-
|
|
19225
|
-
|
|
19226
|
-
|
|
19227
|
-
|
|
19228
|
-
|
|
19229
|
-
|
|
19230
|
-
|
|
19231
|
-
|
|
19232
|
-
|
|
19233
|
-
|
|
19234
|
-
|
|
19235
|
-
|
|
19236
|
-
|
|
19237
|
-
|
|
19238
|
-
|
|
19239
|
-
|
|
19240
|
-
|
|
19241
|
-
|
|
19242
|
-
|
|
19243
|
-
|
|
19244
|
-
|
|
19245
|
-
|
|
19246
|
-
|
|
19247
|
-
|
|
19248
|
-
|
|
19249
|
-
|
|
19250
|
-
|
|
19251
|
-
|
|
19252
|
-
|
|
19253
|
-
|
|
19254
|
-
|
|
19026
|
+
const TOOLBAR_APPROX_H = 170;
|
|
19027
|
+
const toolbarState = activeItemRect && activeItemRect.top < TOOLBAR_APPROX_H ? "active-bottom" : "active-top";
|
|
19028
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
|
|
19029
|
+
hoverHandleRect && hover && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
19030
|
+
"button",
|
|
19031
|
+
{
|
|
19032
|
+
type: "button",
|
|
19033
|
+
"data-ohw-toolbar": "",
|
|
19034
|
+
onClick: () => {
|
|
19035
|
+
clearInteractionChromeRef.current();
|
|
19036
|
+
setActive(hover);
|
|
19037
|
+
},
|
|
19038
|
+
"aria-label": "Configure media item",
|
|
19039
|
+
style: {
|
|
19040
|
+
position: "fixed",
|
|
19041
|
+
top: hoverHandleRect.top + 8,
|
|
19042
|
+
left: hoverHandleRect.left + hoverHandleRect.width - 36,
|
|
19043
|
+
width: 28,
|
|
19044
|
+
height: 28,
|
|
19045
|
+
borderRadius: 8,
|
|
19046
|
+
border: `1.5px dashed ${PRIMARY3}`,
|
|
19047
|
+
background: "#ffffff",
|
|
19048
|
+
color: PRIMARY3,
|
|
19049
|
+
display: "flex",
|
|
19050
|
+
alignItems: "center",
|
|
19051
|
+
justifyContent: "center",
|
|
19052
|
+
cursor: "pointer",
|
|
19053
|
+
zIndex: 2147483643,
|
|
19054
|
+
fontSize: 14,
|
|
19055
|
+
fontWeight: 700
|
|
19056
|
+
},
|
|
19057
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react8.Star, { size: 14, style: { pointerEvents: "none" } })
|
|
19058
|
+
}
|
|
19059
|
+
),
|
|
19060
|
+
activeItemRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
19061
|
+
ItemInteractionLayer,
|
|
19062
|
+
{
|
|
19063
|
+
rect: activeItemRect,
|
|
19064
|
+
state: toolbarState,
|
|
19065
|
+
toolbar: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
19066
|
+
MediaStripToolbar,
|
|
19067
|
+
{
|
|
19068
|
+
entry: activeEntry,
|
|
19069
|
+
index: active.index,
|
|
19070
|
+
pending,
|
|
19071
|
+
error,
|
|
19072
|
+
onSetVariant: (variant) => runMutation(active.sectionId, (tree) => setMediaStripVariant(tree, variant)),
|
|
19073
|
+
onSetAlign: (align) => runMutation(active.sectionId, (tree) => setMediaStripAlign(tree, align)),
|
|
19074
|
+
onSetHover: (hoverPreset) => runMutation(active.sectionId, (tree) => setMediaStripHover(tree, hoverPreset)),
|
|
19075
|
+
onSetTreatment: (treatment) => runMutation(active.sectionId, (tree) => setMediaStripTreatment(tree, treatment)),
|
|
19076
|
+
onResize: (delta) => {
|
|
19077
|
+
const slots = findMediaStripSlots(activeEntry.tree);
|
|
19078
|
+
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
19079
|
+
const current = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
19080
|
+
void runMutation(active.sectionId, (tree) => setMediaStripSizing(tree, current + delta));
|
|
19081
|
+
},
|
|
19082
|
+
onSetAlt: (alt) => {
|
|
19083
|
+
void runMutation(active.sectionId, (tree) => setMediaStripItemAlt(tree, active.index, alt));
|
|
19084
|
+
},
|
|
19085
|
+
onSetLink: (href, linkTarget) => {
|
|
19255
19086
|
void runMutation(
|
|
19256
19087
|
active.sectionId,
|
|
19257
|
-
(tree) =>
|
|
19258
|
-
|
|
19259
|
-
|
|
19260
|
-
|
|
19088
|
+
(tree) => setMediaStripItemLink(tree, active.index, href ? { href, linkTarget } : {})
|
|
19089
|
+
);
|
|
19090
|
+
},
|
|
19091
|
+
onAddItem: () => {
|
|
19092
|
+
void requestAssetPick(postToParent2).then((picked) => {
|
|
19093
|
+
if (!picked) return;
|
|
19094
|
+
const item = { assetId: picked.assetId, alt: "Logo" };
|
|
19095
|
+
void runMutation(
|
|
19096
|
+
active.sectionId,
|
|
19097
|
+
(tree) => addMediaStripItem(tree, item, active.index),
|
|
19098
|
+
{ [picked.assetId]: picked.url }
|
|
19099
|
+
).then((applied) => {
|
|
19100
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19101
|
+
});
|
|
19261
19102
|
});
|
|
19262
|
-
}
|
|
19263
|
-
|
|
19264
|
-
|
|
19265
|
-
|
|
19266
|
-
|
|
19267
|
-
|
|
19268
|
-
|
|
19269
|
-
|
|
19270
|
-
|
|
19103
|
+
},
|
|
19104
|
+
onChangeImage: () => {
|
|
19105
|
+
void requestAssetPick(postToParent2).then((picked) => {
|
|
19106
|
+
if (!picked) return;
|
|
19107
|
+
void runMutation(
|
|
19108
|
+
active.sectionId,
|
|
19109
|
+
(tree) => setMediaStripItemAsset(tree, active.index, picked.assetId),
|
|
19110
|
+
{ [picked.assetId]: picked.url }
|
|
19111
|
+
);
|
|
19112
|
+
});
|
|
19113
|
+
},
|
|
19114
|
+
onRemoveItem: () => {
|
|
19115
|
+
void runMutation(active.sectionId, (tree) => removeMediaStripItem(tree, active.index)).then(
|
|
19116
|
+
(applied) => {
|
|
19117
|
+
if (applied) setActive(null);
|
|
19118
|
+
}
|
|
19271
19119
|
);
|
|
19272
|
-
}
|
|
19273
|
-
|
|
19274
|
-
|
|
19275
|
-
|
|
19276
|
-
|
|
19277
|
-
|
|
19278
|
-
|
|
19279
|
-
|
|
19280
|
-
|
|
19281
|
-
|
|
19282
|
-
|
|
19283
|
-
|
|
19284
|
-
|
|
19285
|
-
|
|
19286
|
-
|
|
19287
|
-
},
|
|
19288
|
-
onMoveRight: () => {
|
|
19289
|
-
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, 1)).then(
|
|
19290
|
-
(applied) => {
|
|
19291
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19292
|
-
}
|
|
19293
|
-
);
|
|
19294
|
-
}
|
|
19295
|
-
}
|
|
19296
|
-
) }),
|
|
19297
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19298
|
-
"div",
|
|
19299
|
-
{
|
|
19300
|
-
"data-ohw-bridge": "",
|
|
19301
|
-
"data-ohw-item-interaction": "",
|
|
19302
|
-
"aria-hidden": true,
|
|
19303
|
-
className: "pointer-events-none fixed rounded-[4px] px-[7px] py-[3px] font-sans text-[11px] font-medium leading-none text-primary-foreground whitespace-nowrap",
|
|
19304
|
-
style: {
|
|
19305
|
-
top: activeItemRect.top + activeItemRect.height + 10,
|
|
19306
|
-
left: activeItemRect.left - 5,
|
|
19307
|
-
background: PRIMARY3,
|
|
19308
|
-
zIndex: 2147483644
|
|
19309
|
-
},
|
|
19310
|
-
children: "Media item"
|
|
19311
|
-
}
|
|
19312
|
-
),
|
|
19313
|
-
linkOpen && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19314
|
-
LinkModal,
|
|
19315
|
-
{
|
|
19316
|
-
href: activeHref,
|
|
19317
|
-
linkTarget: activeTarget,
|
|
19318
|
-
onClose: () => setLinkOpen(false),
|
|
19319
|
-
onSave: (href, linkTarget) => {
|
|
19320
|
-
void runMutation(
|
|
19321
|
-
active.sectionId,
|
|
19322
|
-
(tree) => setMediaStripItemLink(tree, active.index, href ? { href, linkTarget } : {})
|
|
19323
|
-
);
|
|
19120
|
+
},
|
|
19121
|
+
onMoveLeft: () => {
|
|
19122
|
+
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, -1)).then(
|
|
19123
|
+
(applied) => {
|
|
19124
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index - 1 });
|
|
19125
|
+
}
|
|
19126
|
+
);
|
|
19127
|
+
},
|
|
19128
|
+
onMoveRight: () => {
|
|
19129
|
+
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, 1)).then(
|
|
19130
|
+
(applied) => {
|
|
19131
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19132
|
+
}
|
|
19133
|
+
);
|
|
19134
|
+
}
|
|
19324
19135
|
}
|
|
19325
|
-
|
|
19326
|
-
|
|
19327
|
-
|
|
19136
|
+
)
|
|
19137
|
+
}
|
|
19138
|
+
)
|
|
19328
19139
|
] });
|
|
19329
19140
|
}
|
|
19330
19141
|
|
|
19331
19142
|
// src/ui/ai-section/AiPricingCardOverlay.tsx
|
|
19332
19143
|
var import_react11 = require("react");
|
|
19333
|
-
var
|
|
19334
|
-
var
|
|
19144
|
+
var import_lucide_react9 = require("lucide-react");
|
|
19145
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
19335
19146
|
var PRIMARY4 = "var(--ohw-primary, #0885FE)";
|
|
19336
|
-
var
|
|
19147
|
+
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]";
|
|
19337
19148
|
function findPricingCardElement(sectionId, index) {
|
|
19338
19149
|
const sectionEl = findByInstanceId(sectionId);
|
|
19339
19150
|
if (!sectionEl) return null;
|
|
@@ -19345,7 +19156,7 @@ function findPricingCardElement(sectionId, index) {
|
|
|
19345
19156
|
}
|
|
19346
19157
|
function cardRefFromTarget(target) {
|
|
19347
19158
|
if (!(target instanceof Element)) return null;
|
|
19348
|
-
if (target.closest(
|
|
19159
|
+
if (target.closest(CHROME_SELECTOR)) return null;
|
|
19349
19160
|
const cardEl = target.closest("[data-ohw-pricing-card]");
|
|
19350
19161
|
if (!cardEl) return null;
|
|
19351
19162
|
const sectionEl = cardEl.closest("[data-ohw-section]");
|
|
@@ -19355,21 +19166,21 @@ function cardRefFromTarget(target) {
|
|
|
19355
19166
|
if (!sectionId || Number.isNaN(index)) return null;
|
|
19356
19167
|
return { sectionId, index };
|
|
19357
19168
|
}
|
|
19358
|
-
function
|
|
19169
|
+
function sameRef(a, b) {
|
|
19359
19170
|
return a?.sectionId === b?.sectionId && a?.index === b?.index;
|
|
19360
19171
|
}
|
|
19361
|
-
function
|
|
19172
|
+
function rectOf(el) {
|
|
19362
19173
|
if (!el) return null;
|
|
19363
19174
|
const r2 = el.getBoundingClientRect();
|
|
19364
19175
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
19365
19176
|
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
19366
19177
|
}
|
|
19367
19178
|
function readRect3(ref) {
|
|
19368
|
-
return
|
|
19179
|
+
return rectOf(ref && findPricingCardElement(ref.sectionId, ref.index));
|
|
19369
19180
|
}
|
|
19370
19181
|
function readGridRect(ref) {
|
|
19371
19182
|
const card = ref && findPricingCardElement(ref.sectionId, ref.index);
|
|
19372
|
-
return
|
|
19183
|
+
return rectOf(card?.closest("[data-ohw-pricing-collection]") ?? card);
|
|
19373
19184
|
}
|
|
19374
19185
|
function useLiveCardRect(ref, grid = false) {
|
|
19375
19186
|
const [rect, setRect] = (0, import_react11.useState)(null);
|
|
@@ -19399,7 +19210,7 @@ function useLiveCardRect(ref, grid = false) {
|
|
|
19399
19210
|
}
|
|
19400
19211
|
var TOOLBAR_GRID_GAP = 52;
|
|
19401
19212
|
var TOOLBAR_GRID_GAP_MOBILE = 42;
|
|
19402
|
-
var
|
|
19213
|
+
var TOOLBAR_EDGE_MARGIN2 = 4;
|
|
19403
19214
|
function GridToolbarSlot({ gridRect, children }) {
|
|
19404
19215
|
const slotRef = (0, import_react11.useRef)(null);
|
|
19405
19216
|
const [shift, setShift] = (0, import_react11.useState)(0);
|
|
@@ -19411,7 +19222,7 @@ function GridToolbarSlot({ gridRect, children }) {
|
|
|
19411
19222
|
const w = slot.offsetWidth;
|
|
19412
19223
|
if (w <= 0) return;
|
|
19413
19224
|
const half = w / 2;
|
|
19414
|
-
const clamped = Math.max(
|
|
19225
|
+
const clamped = Math.max(TOOLBAR_EDGE_MARGIN2 + half, Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN2 - half));
|
|
19415
19226
|
setShift((prev) => Math.abs(prev - (clamped - centerX)) < 0.5 ? prev : clamped - centerX);
|
|
19416
19227
|
};
|
|
19417
19228
|
clamp();
|
|
@@ -19420,7 +19231,7 @@ function GridToolbarSlot({ gridRect, children }) {
|
|
|
19420
19231
|
return () => ro.disconnect();
|
|
19421
19232
|
}, [centerX, children]);
|
|
19422
19233
|
const mobile = window.innerWidth <= 480;
|
|
19423
|
-
return /* @__PURE__ */ (0,
|
|
19234
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19424
19235
|
"div",
|
|
19425
19236
|
{
|
|
19426
19237
|
ref: slotRef,
|
|
@@ -19455,7 +19266,7 @@ function requestValidateTree2(postToParent2, tree) {
|
|
|
19455
19266
|
});
|
|
19456
19267
|
}
|
|
19457
19268
|
function StyleSwatch({ style }) {
|
|
19458
|
-
return /* @__PURE__ */ (0,
|
|
19269
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19459
19270
|
"span",
|
|
19460
19271
|
{
|
|
19461
19272
|
"aria-hidden": true,
|
|
@@ -19469,35 +19280,35 @@ function StyleSwatch({ style }) {
|
|
|
19469
19280
|
);
|
|
19470
19281
|
}
|
|
19471
19282
|
function ButtonGlyph() {
|
|
19472
|
-
return /* @__PURE__ */ (0,
|
|
19473
|
-
/* @__PURE__ */ (0,
|
|
19474
|
-
/* @__PURE__ */ (0,
|
|
19283
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("svg", { width: "18", height: "12", viewBox: "0 0 18 12", fill: "none", "aria-hidden": true, style: { pointerEvents: "none" }, children: [
|
|
19284
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("rect", { x: "0.75", y: "0.75", width: "16.5", height: "10.5", rx: "3", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
19285
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("path", { d: "M5.5 6H12.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
|
|
19475
19286
|
] });
|
|
19476
19287
|
}
|
|
19477
19288
|
function FeatureGlyph({ mode }) {
|
|
19478
|
-
return /* @__PURE__ */ (0,
|
|
19479
|
-
/* @__PURE__ */ (0,
|
|
19480
|
-
/* @__PURE__ */ (0,
|
|
19481
|
-
/* @__PURE__ */ (0,
|
|
19482
|
-
/* @__PURE__ */ (0,
|
|
19483
|
-
/* @__PURE__ */ (0,
|
|
19484
|
-
mode === "add" && /* @__PURE__ */ (0,
|
|
19289
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "none", "aria-hidden": true, style: { pointerEvents: "none" }, children: [
|
|
19290
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("circle", { cx: "8", cy: "8", r: "7.25", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
19291
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("path", { d: "M5 8.2L7.2 10.3L11 6", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
19292
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("circle", { cx: "13.5", cy: "13.5", r: "4.25", fill: "var(--ohw-background, #ffffff)", stroke: "var(--ohw-background, #ffffff)", strokeWidth: "1" }),
|
|
19293
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("circle", { cx: "13.5", cy: "13.5", r: "3.75", fill: "var(--ohw-background, #ffffff)", stroke: PRIMARY4, strokeWidth: "1" }),
|
|
19294
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("path", { d: "M11.5 13.5H15.5", stroke: PRIMARY4, strokeWidth: "1.5", strokeLinecap: "round" }),
|
|
19295
|
+
mode === "add" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("path", { d: "M13.5 11.5V15.5", stroke: PRIMARY4, strokeWidth: "1.5", strokeLinecap: "round" })
|
|
19485
19296
|
] });
|
|
19486
19297
|
}
|
|
19487
|
-
function
|
|
19298
|
+
function ToolbarAction({
|
|
19488
19299
|
label,
|
|
19489
19300
|
onClick,
|
|
19490
19301
|
disabled = false,
|
|
19491
19302
|
children
|
|
19492
19303
|
}) {
|
|
19493
|
-
const button = /* @__PURE__ */ (0,
|
|
19494
|
-
return /* @__PURE__ */ (0,
|
|
19495
|
-
/* @__PURE__ */ (0,
|
|
19496
|
-
/* @__PURE__ */ (0,
|
|
19304
|
+
const button = /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CustomToolbarButton, { type: "button", "aria-label": label, disabled, onClick, className: "size-8", children });
|
|
19305
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Tooltip, { children: [
|
|
19306
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "inline-flex", children: button }) : button }),
|
|
19307
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: label })
|
|
19497
19308
|
] });
|
|
19498
19309
|
}
|
|
19499
|
-
function
|
|
19500
|
-
return /* @__PURE__ */ (0,
|
|
19310
|
+
function ToolbarSeparator() {
|
|
19311
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { "aria-hidden": true, className: "mx-0.5 block h-6 w-px shrink-0 bg-border" });
|
|
19501
19312
|
}
|
|
19502
19313
|
function CardStyleMenu({
|
|
19503
19314
|
value,
|
|
@@ -19505,7 +19316,7 @@ function CardStyleMenu({
|
|
|
19505
19316
|
disabled = false
|
|
19506
19317
|
}) {
|
|
19507
19318
|
const current = PRICING_CARD_STYLES.find((s) => s.value === value) ?? PRICING_CARD_STYLES[0];
|
|
19508
|
-
const trigger = /* @__PURE__ */ (0,
|
|
19319
|
+
const trigger = /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
19509
19320
|
"button",
|
|
19510
19321
|
{
|
|
19511
19322
|
type: "button",
|
|
@@ -19516,28 +19327,28 @@ function CardStyleMenu({
|
|
|
19516
19327
|
disabled && "cursor-not-allowed opacity-40 hover:bg-transparent"
|
|
19517
19328
|
),
|
|
19518
19329
|
children: [
|
|
19519
|
-
/* @__PURE__ */ (0,
|
|
19520
|
-
/* @__PURE__ */ (0,
|
|
19521
|
-
/* @__PURE__ */ (0,
|
|
19330
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StyleSwatch, { style: current.value }),
|
|
19331
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "flex-1 text-left", children: current.label }),
|
|
19332
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.ChevronDown, { size: 16, style: { pointerEvents: "none" } })
|
|
19522
19333
|
]
|
|
19523
19334
|
}
|
|
19524
19335
|
);
|
|
19525
19336
|
if (disabled) {
|
|
19526
|
-
return /* @__PURE__ */ (0,
|
|
19527
|
-
/* @__PURE__ */ (0,
|
|
19528
|
-
/* @__PURE__ */ (0,
|
|
19529
|
-
/* @__PURE__ */ (0,
|
|
19530
|
-
/* @__PURE__ */ (0,
|
|
19337
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19338
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-xs text-muted-foreground opacity-50", children: "Card style" }),
|
|
19339
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Tooltip, { children: [
|
|
19340
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "inline-flex", children: trigger }) }),
|
|
19341
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: "Mark as featured to edit card style" })
|
|
19531
19342
|
] })
|
|
19532
19343
|
] });
|
|
19533
19344
|
}
|
|
19534
|
-
return /* @__PURE__ */ (0,
|
|
19535
|
-
/* @__PURE__ */ (0,
|
|
19536
|
-
/* @__PURE__ */ (0,
|
|
19537
|
-
/* @__PURE__ */ (0,
|
|
19538
|
-
/* @__PURE__ */ (0,
|
|
19345
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19346
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-xs text-muted-foreground", children: "Card style" }),
|
|
19347
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(DropdownMenu, { modal: false, children: [
|
|
19348
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DropdownMenuTrigger, { asChild: true, children: trigger }),
|
|
19349
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DropdownMenuContent, { align: "end", sideOffset: 8, className: "w-[152px] min-w-[152px] p-1", children: PRICING_CARD_STYLES.map((style) => {
|
|
19539
19350
|
const selected = style.value === value;
|
|
19540
|
-
return /* @__PURE__ */ (0,
|
|
19351
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
19541
19352
|
DropdownMenuItem,
|
|
19542
19353
|
{
|
|
19543
19354
|
role: "menuitemradio",
|
|
@@ -19545,9 +19356,9 @@ function CardStyleMenu({
|
|
|
19545
19356
|
onSelect: () => onChange(style.value),
|
|
19546
19357
|
className: cn("grid grid-cols-[18px_1fr_16px] gap-2 py-2 pl-2 pr-2 text-[13px]", selected && "bg-muted"),
|
|
19547
19358
|
children: [
|
|
19548
|
-
/* @__PURE__ */ (0,
|
|
19549
|
-
/* @__PURE__ */ (0,
|
|
19550
|
-
selected && /* @__PURE__ */ (0,
|
|
19359
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StyleSwatch, { style: style.value }),
|
|
19360
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: style.label }),
|
|
19361
|
+
selected && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Check, { size: 16, className: "text-bridge-primary" })
|
|
19551
19362
|
]
|
|
19552
19363
|
},
|
|
19553
19364
|
style.value
|
|
@@ -19577,7 +19388,7 @@ function PricingCardToolbar({
|
|
|
19577
19388
|
const style = pricingCardStyle(entry.tree, index);
|
|
19578
19389
|
const featuredTag = pricingCardFeaturedTag(entry.tree, index);
|
|
19579
19390
|
const mobile = window.innerWidth <= 480;
|
|
19580
|
-
return /* @__PURE__ */ (0,
|
|
19391
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
19581
19392
|
"div",
|
|
19582
19393
|
{
|
|
19583
19394
|
"data-ohw-bridge": "",
|
|
@@ -19589,7 +19400,7 @@ function PricingCardToolbar({
|
|
|
19589
19400
|
),
|
|
19590
19401
|
style: { maxWidth: mobile ? "calc(100vw - 24px)" : void 0 },
|
|
19591
19402
|
children: [
|
|
19592
|
-
/* @__PURE__ */ (0,
|
|
19403
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
19593
19404
|
"div",
|
|
19594
19405
|
{
|
|
19595
19406
|
className: cn(
|
|
@@ -19598,8 +19409,8 @@ function PricingCardToolbar({
|
|
|
19598
19409
|
mobile ? "flex-wrap justify-center" : "flex-nowrap"
|
|
19599
19410
|
),
|
|
19600
19411
|
children: [
|
|
19601
|
-
/* @__PURE__ */ (0,
|
|
19602
|
-
/* @__PURE__ */ (0,
|
|
19412
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Tooltip, { children: [
|
|
19413
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19603
19414
|
CustomToolbarButton,
|
|
19604
19415
|
{
|
|
19605
19416
|
type: "button",
|
|
@@ -19607,8 +19418,8 @@ function PricingCardToolbar({
|
|
|
19607
19418
|
"aria-pressed": featuredTag,
|
|
19608
19419
|
onClick: () => onSetFeaturedTag(!featuredTag),
|
|
19609
19420
|
className: "group size-8",
|
|
19610
|
-
children: /* @__PURE__ */ (0,
|
|
19611
|
-
|
|
19421
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19422
|
+
import_lucide_react9.Star,
|
|
19612
19423
|
{
|
|
19613
19424
|
size: 16,
|
|
19614
19425
|
fill: "currentColor",
|
|
@@ -19622,25 +19433,25 @@ function PricingCardToolbar({
|
|
|
19622
19433
|
)
|
|
19623
19434
|
}
|
|
19624
19435
|
) }),
|
|
19625
|
-
/* @__PURE__ */ (0,
|
|
19436
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: featuredTag ? "Unmark featured" : "Mark as featured" })
|
|
19626
19437
|
] }),
|
|
19627
|
-
/* @__PURE__ */ (0,
|
|
19628
|
-
/* @__PURE__ */ (0,
|
|
19629
|
-
/* @__PURE__ */ (0,
|
|
19630
|
-
/* @__PURE__ */ (0,
|
|
19631
|
-
/* @__PURE__ */ (0,
|
|
19632
|
-
/* @__PURE__ */ (0,
|
|
19633
|
-
/* @__PURE__ */ (0,
|
|
19438
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19439
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CardStyleMenu, { value: style, onChange: onSetStyle, disabled: !featuredTag }),
|
|
19440
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19441
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: "Add button", onClick: onAddButton, disabled: buttonCount >= 2, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ButtonGlyph, {}) }),
|
|
19442
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: "Remove button", onClick: onRemoveButton, disabled: buttonCount === 0, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "relative inline-flex", children: [
|
|
19443
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ButtonGlyph, {}),
|
|
19444
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Minus, { size: 10, strokeWidth: 2.5, className: "absolute -right-1.5 -top-1.5 rounded-full bg-background text-bridge-primary" })
|
|
19634
19445
|
] }) }),
|
|
19635
|
-
/* @__PURE__ */ (0,
|
|
19636
|
-
/* @__PURE__ */ (0,
|
|
19637
|
-
/* @__PURE__ */ (0,
|
|
19638
|
-
/* @__PURE__ */ (0,
|
|
19639
|
-
/* @__PURE__ */ (0,
|
|
19446
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: "Add feature", onClick: onAddFeature, disabled: featureCount >= 10, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(FeatureGlyph, { mode: "add" }) }),
|
|
19447
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: "Remove feature", onClick: onRemoveFeature, disabled: featureCount <= 1, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(FeatureGlyph, { mode: "remove" }) }),
|
|
19448
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19449
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: "Add tier", onClick: onAddTier, disabled: collectionCount >= 4, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Plus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
19450
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarAction, { label: "Remove tier", onClick: onRemoveTier, disabled: collectionCount <= 1, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Minus, { size: 16, style: { pointerEvents: "none" } }) })
|
|
19640
19451
|
]
|
|
19641
19452
|
}
|
|
19642
19453
|
),
|
|
19643
|
-
error && /* @__PURE__ */ (0,
|
|
19454
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "max-w-[260px] rounded-md bg-background px-2 py-1 text-center text-[11px] text-destructive shadow-sm", children: error })
|
|
19644
19455
|
]
|
|
19645
19456
|
}
|
|
19646
19457
|
) });
|
|
@@ -19674,7 +19485,7 @@ function AiPricingCardOverlay({
|
|
|
19674
19485
|
const overEditable = Boolean(t?.closest?.("[data-ohw-editable], [data-ohw-role], a, button"));
|
|
19675
19486
|
setHover((prev) => {
|
|
19676
19487
|
const next = ref && !overEditable ? ref : null;
|
|
19677
|
-
return
|
|
19488
|
+
return sameRef(prev, next) ? prev : next;
|
|
19678
19489
|
});
|
|
19679
19490
|
};
|
|
19680
19491
|
const onLeave = () => setHover(null);
|
|
@@ -19689,10 +19500,10 @@ function AiPricingCardOverlay({
|
|
|
19689
19500
|
const onClick = (e) => {
|
|
19690
19501
|
const t = e.target;
|
|
19691
19502
|
if (!(t instanceof Element)) return;
|
|
19692
|
-
if (t.closest(
|
|
19503
|
+
if (t.closest(CHROME_SELECTOR)) return;
|
|
19693
19504
|
const ref = cardRefFromTarget(t);
|
|
19694
|
-
setActive((prev) =>
|
|
19695
|
-
if (!ref || !
|
|
19505
|
+
setActive((prev) => sameRef(prev, ref) ? prev : ref);
|
|
19506
|
+
if (!ref || !sameRef(activeRef.current, ref)) setError(null);
|
|
19696
19507
|
};
|
|
19697
19508
|
document.addEventListener("click", onClick, true);
|
|
19698
19509
|
return () => document.removeEventListener("click", onClick, true);
|
|
@@ -19757,12 +19568,12 @@ function AiPricingCardOverlay({
|
|
|
19757
19568
|
const activeEntry = active ? findEntry(active.sectionId) : null;
|
|
19758
19569
|
const activeCardRect = useLiveCardRect(active);
|
|
19759
19570
|
const activeGridRect = useLiveCardRect(active, true);
|
|
19760
|
-
const hoverRect = useLiveCardRect(hover && !
|
|
19761
|
-
return /* @__PURE__ */ (0,
|
|
19762
|
-
hoverRect && /* @__PURE__ */ (0,
|
|
19763
|
-
activeCardRect && activeGridRect && active && activeEntry && /* @__PURE__ */ (0,
|
|
19764
|
-
/* @__PURE__ */ (0,
|
|
19765
|
-
/* @__PURE__ */ (0,
|
|
19571
|
+
const hoverRect = useLiveCardRect(hover && !sameRef(hover, active) ? hover : null);
|
|
19572
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
19573
|
+
hoverRect && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ItemInteractionLayer, { rect: hoverRect, state: "hover" }),
|
|
19574
|
+
activeCardRect && activeGridRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
19575
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ItemInteractionLayer, { rect: activeCardRect, state: "active-top" }),
|
|
19576
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(GridToolbarSlot, { gridRect: activeGridRect, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19766
19577
|
PricingCardToolbar,
|
|
19767
19578
|
{
|
|
19768
19579
|
entry: activeEntry,
|
|
@@ -19790,7 +19601,7 @@ function AiPricingCardOverlay({
|
|
|
19790
19601
|
onRemoveFeature: () => runMutation(active.sectionId, (tree) => removePricingCardFeature(tree, active.index))
|
|
19791
19602
|
}
|
|
19792
19603
|
) }),
|
|
19793
|
-
/* @__PURE__ */ (0,
|
|
19604
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19794
19605
|
"div",
|
|
19795
19606
|
{
|
|
19796
19607
|
"data-ohw-bridge": "",
|
|
@@ -19812,7 +19623,7 @@ function AiPricingCardOverlay({
|
|
|
19812
19623
|
|
|
19813
19624
|
// src/ui/ai-section/AiVideoOverlay.tsx
|
|
19814
19625
|
var import_react12 = require("react");
|
|
19815
|
-
var
|
|
19626
|
+
var import_lucide_react10 = require("lucide-react");
|
|
19816
19627
|
|
|
19817
19628
|
// src/lib/ai-video-tree.ts
|
|
19818
19629
|
function resolveVideoBlock(tree, path) {
|
|
@@ -19883,10 +19694,10 @@ function extractYouTubeId(input) {
|
|
|
19883
19694
|
}
|
|
19884
19695
|
|
|
19885
19696
|
// src/ui/ai-section/AiVideoOverlay.tsx
|
|
19886
|
-
var
|
|
19697
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
19887
19698
|
var PRIMARY5 = "#0885FE";
|
|
19888
|
-
var
|
|
19889
|
-
var
|
|
19699
|
+
var OHW_BLUE2 = `var(--ohw-primary, ${PRIMARY5})`;
|
|
19700
|
+
var OHW_BLUE_DARK2 = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY5}) 60%, #000000)`;
|
|
19890
19701
|
function findVideoBlockElement(sectionId, path) {
|
|
19891
19702
|
const sectionEl = findByInstanceId(sectionId);
|
|
19892
19703
|
if (!sectionEl) return null;
|
|
@@ -19946,12 +19757,12 @@ function requestValidateTree3(postToParent2, tree) {
|
|
|
19946
19757
|
postToParent2({ type: "ow:ai-validate-tree-request", id, tree });
|
|
19947
19758
|
});
|
|
19948
19759
|
}
|
|
19949
|
-
function
|
|
19760
|
+
function Pill2({
|
|
19950
19761
|
label,
|
|
19951
19762
|
onClick,
|
|
19952
19763
|
disabled
|
|
19953
19764
|
}) {
|
|
19954
|
-
return /* @__PURE__ */ (0,
|
|
19765
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19955
19766
|
"button",
|
|
19956
19767
|
{
|
|
19957
19768
|
type: "button",
|
|
@@ -19967,7 +19778,7 @@ function Pill({
|
|
|
19967
19778
|
border: "none",
|
|
19968
19779
|
cursor: disabled ? "default" : "pointer",
|
|
19969
19780
|
background: "#ffffff",
|
|
19970
|
-
color:
|
|
19781
|
+
color: OHW_BLUE_DARK2,
|
|
19971
19782
|
opacity: disabled ? 0.4 : 1,
|
|
19972
19783
|
fontSize: 12,
|
|
19973
19784
|
lineHeight: "16px",
|
|
@@ -20010,8 +19821,8 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20010
19821
|
onCommit(id);
|
|
20011
19822
|
}
|
|
20012
19823
|
};
|
|
20013
|
-
return /* @__PURE__ */ (0,
|
|
20014
|
-
/* @__PURE__ */ (0,
|
|
19824
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 4, width: "100%", maxWidth: 280 }, children: [
|
|
19825
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
20015
19826
|
"div",
|
|
20016
19827
|
{
|
|
20017
19828
|
style: {
|
|
@@ -20027,12 +19838,12 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20027
19838
|
boxShadow: invalid ? "inset 0 0 0 1.5px #EF4444" : "none"
|
|
20028
19839
|
},
|
|
20029
19840
|
children: [
|
|
20030
|
-
/* @__PURE__ */ (0,
|
|
19841
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
20031
19842
|
"span",
|
|
20032
19843
|
{
|
|
20033
19844
|
style: {
|
|
20034
19845
|
flex: "0 0 auto",
|
|
20035
|
-
color:
|
|
19846
|
+
color: OHW_BLUE_DARK2,
|
|
20036
19847
|
fontSize: 10,
|
|
20037
19848
|
lineHeight: "16px",
|
|
20038
19849
|
fontWeight: 700,
|
|
@@ -20042,7 +19853,7 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20042
19853
|
children: "Video"
|
|
20043
19854
|
}
|
|
20044
19855
|
),
|
|
20045
|
-
/* @__PURE__ */ (0,
|
|
19856
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
20046
19857
|
"input",
|
|
20047
19858
|
{
|
|
20048
19859
|
type: "text",
|
|
@@ -20079,7 +19890,7 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20079
19890
|
]
|
|
20080
19891
|
}
|
|
20081
19892
|
),
|
|
20082
|
-
invalid && /* @__PURE__ */ (0,
|
|
19893
|
+
invalid && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { color: "#FCA5A5", fontSize: 11, textAlign: "center" }, children: "That doesn't look like a YouTube link \u2014 try pasting the video URL again." })
|
|
20083
19894
|
] });
|
|
20084
19895
|
}
|
|
20085
19896
|
function VideoToolbar({
|
|
@@ -20089,7 +19900,7 @@ function VideoToolbar({
|
|
|
20089
19900
|
onSetVideoId,
|
|
20090
19901
|
onRemove
|
|
20091
19902
|
}) {
|
|
20092
|
-
return /* @__PURE__ */ (0,
|
|
19903
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
20093
19904
|
"div",
|
|
20094
19905
|
{
|
|
20095
19906
|
"data-ohw-bridge": "",
|
|
@@ -20101,7 +19912,7 @@ function VideoToolbar({
|
|
|
20101
19912
|
gap: 6,
|
|
20102
19913
|
alignItems: "center",
|
|
20103
19914
|
width: 280,
|
|
20104
|
-
background:
|
|
19915
|
+
background: OHW_BLUE2,
|
|
20105
19916
|
padding: 8,
|
|
20106
19917
|
borderRadius: 12,
|
|
20107
19918
|
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
@@ -20109,9 +19920,9 @@ function VideoToolbar({
|
|
|
20109
19920
|
opacity: pending ? 0.6 : 1
|
|
20110
19921
|
},
|
|
20111
19922
|
children: [
|
|
20112
|
-
/* @__PURE__ */ (0,
|
|
20113
|
-
/* @__PURE__ */ (0,
|
|
20114
|
-
error && /* @__PURE__ */ (0,
|
|
19923
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(VideoUrlInput, { value: videoId, onCommit: onSetVideoId }),
|
|
19924
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Pill2, { label: "Remove video", onClick: onRemove, disabled: !videoId }),
|
|
19925
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { style: { color: "#FCA5A5", fontSize: 11, maxWidth: 220, textAlign: "center" }, children: error })
|
|
20115
19926
|
]
|
|
20116
19927
|
}
|
|
20117
19928
|
);
|
|
@@ -20231,8 +20042,8 @@ function AiVideoOverlay({
|
|
|
20231
20042
|
const activeBlockRect = useLiveBlockRect(active);
|
|
20232
20043
|
const TOOLBAR_APPROX_H = 90;
|
|
20233
20044
|
const toolbarState = activeBlockRect && activeBlockRect.top < TOOLBAR_APPROX_H ? "active-bottom" : "active-top";
|
|
20234
|
-
return /* @__PURE__ */ (0,
|
|
20235
|
-
hoverHandleRect && hover && /* @__PURE__ */ (0,
|
|
20045
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
20046
|
+
hoverHandleRect && hover && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
20236
20047
|
"button",
|
|
20237
20048
|
{
|
|
20238
20049
|
type: "button",
|
|
@@ -20260,15 +20071,15 @@ function AiVideoOverlay({
|
|
|
20260
20071
|
fontSize: 14,
|
|
20261
20072
|
fontWeight: 700
|
|
20262
20073
|
},
|
|
20263
|
-
children: /* @__PURE__ */ (0,
|
|
20074
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Star, { size: 14, style: { pointerEvents: "none" } })
|
|
20264
20075
|
}
|
|
20265
20076
|
),
|
|
20266
|
-
activeBlockRect && active && activeEntry && /* @__PURE__ */ (0,
|
|
20077
|
+
activeBlockRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
20267
20078
|
ItemInteractionLayer,
|
|
20268
20079
|
{
|
|
20269
20080
|
rect: activeBlockRect,
|
|
20270
20081
|
state: toolbarState,
|
|
20271
|
-
toolbar: /* @__PURE__ */ (0,
|
|
20082
|
+
toolbar: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
20272
20083
|
VideoToolbar,
|
|
20273
20084
|
{
|
|
20274
20085
|
videoId: videoIdAt(activeEntry.tree, active.path),
|
|
@@ -20292,7 +20103,7 @@ function AiVideoOverlay({
|
|
|
20292
20103
|
|
|
20293
20104
|
// src/ui/ai-section/AiFadeCarouselOverlay.tsx
|
|
20294
20105
|
var import_react13 = require("react");
|
|
20295
|
-
var
|
|
20106
|
+
var import_lucide_react11 = require("lucide-react");
|
|
20296
20107
|
|
|
20297
20108
|
// src/lib/ai-carousel-tree.ts
|
|
20298
20109
|
function isCarouselBlock(node) {
|
|
@@ -20343,10 +20154,10 @@ function setCarouselAutoplay(tree, on) {
|
|
|
20343
20154
|
}
|
|
20344
20155
|
|
|
20345
20156
|
// src/ui/ai-section/AiFadeCarouselOverlay.tsx
|
|
20346
|
-
var
|
|
20157
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
20347
20158
|
var PRIMARY6 = "#0885FE";
|
|
20348
|
-
var
|
|
20349
|
-
var
|
|
20159
|
+
var OHW_BLUE3 = `var(--ohw-primary, ${PRIMARY6})`;
|
|
20160
|
+
var OHW_BLUE_DARK3 = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY6}) 60%, #000000)`;
|
|
20350
20161
|
function findCarouselItemElement(sectionId, index) {
|
|
20351
20162
|
const sectionEl = findByInstanceId(sectionId);
|
|
20352
20163
|
if (!sectionEl) return null;
|
|
@@ -20425,8 +20236,8 @@ function requestAssetPick2(postToParent2) {
|
|
|
20425
20236
|
postToParent2({ type: "ow:asset-pick", id });
|
|
20426
20237
|
});
|
|
20427
20238
|
}
|
|
20428
|
-
function
|
|
20429
|
-
return /* @__PURE__ */ (0,
|
|
20239
|
+
function Pill3({ label, onClick, disabled }) {
|
|
20240
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20430
20241
|
"button",
|
|
20431
20242
|
{
|
|
20432
20243
|
type: "button",
|
|
@@ -20442,7 +20253,7 @@ function Pill2({ label, onClick, disabled }) {
|
|
|
20442
20253
|
border: "none",
|
|
20443
20254
|
cursor: disabled ? "default" : "pointer",
|
|
20444
20255
|
background: "#ffffff",
|
|
20445
|
-
color:
|
|
20256
|
+
color: OHW_BLUE_DARK3,
|
|
20446
20257
|
opacity: disabled ? 0.4 : 1,
|
|
20447
20258
|
fontSize: 12,
|
|
20448
20259
|
lineHeight: "16px",
|
|
@@ -20460,7 +20271,7 @@ function TogglePill({
|
|
|
20460
20271
|
onToggle,
|
|
20461
20272
|
disabled
|
|
20462
20273
|
}) {
|
|
20463
|
-
return /* @__PURE__ */ (0,
|
|
20274
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
20464
20275
|
"button",
|
|
20465
20276
|
{
|
|
20466
20277
|
type: "button",
|
|
@@ -20479,7 +20290,7 @@ function TogglePill({
|
|
|
20479
20290
|
border: "none",
|
|
20480
20291
|
cursor: disabled ? "default" : "pointer",
|
|
20481
20292
|
background: "#ffffff",
|
|
20482
|
-
color:
|
|
20293
|
+
color: OHW_BLUE_DARK3,
|
|
20483
20294
|
opacity: disabled ? 0.4 : 1,
|
|
20484
20295
|
fontSize: 12,
|
|
20485
20296
|
lineHeight: "16px",
|
|
@@ -20489,7 +20300,7 @@ function TogglePill({
|
|
|
20489
20300
|
},
|
|
20490
20301
|
children: [
|
|
20491
20302
|
label,
|
|
20492
|
-
/* @__PURE__ */ (0,
|
|
20303
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20493
20304
|
"span",
|
|
20494
20305
|
{
|
|
20495
20306
|
"aria-hidden": true,
|
|
@@ -20502,10 +20313,10 @@ function TogglePill({
|
|
|
20502
20313
|
// Off is a grey track, not a washed-out blue: the pill's own white background already
|
|
20503
20314
|
// carries the brand colour in the text, and a pale blue track next to it read as
|
|
20504
20315
|
// "disabled control" rather than "switch that is off".
|
|
20505
|
-
background: on ?
|
|
20316
|
+
background: on ? OHW_BLUE_DARK3 : "#CBD5E1",
|
|
20506
20317
|
transition: "background 120ms ease"
|
|
20507
20318
|
},
|
|
20508
|
-
children: /* @__PURE__ */ (0,
|
|
20319
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20509
20320
|
"span",
|
|
20510
20321
|
{
|
|
20511
20322
|
style: {
|
|
@@ -20534,7 +20345,7 @@ function CarouselSlideToolbar({
|
|
|
20534
20345
|
onChangeImage,
|
|
20535
20346
|
onToggleAutoplay
|
|
20536
20347
|
}) {
|
|
20537
|
-
return /* @__PURE__ */ (0,
|
|
20348
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
20538
20349
|
"div",
|
|
20539
20350
|
{
|
|
20540
20351
|
"data-ohw-bridge": "",
|
|
@@ -20545,7 +20356,7 @@ function CarouselSlideToolbar({
|
|
|
20545
20356
|
flexDirection: "column",
|
|
20546
20357
|
gap: 6,
|
|
20547
20358
|
alignItems: "center",
|
|
20548
|
-
background:
|
|
20359
|
+
background: OHW_BLUE3,
|
|
20549
20360
|
padding: 8,
|
|
20550
20361
|
borderRadius: 12,
|
|
20551
20362
|
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
@@ -20557,11 +20368,11 @@ function CarouselSlideToolbar({
|
|
|
20557
20368
|
pointerEvents: pending ? "none" : "auto"
|
|
20558
20369
|
},
|
|
20559
20370
|
children: [
|
|
20560
|
-
/* @__PURE__ */ (0,
|
|
20561
|
-
/* @__PURE__ */ (0,
|
|
20562
|
-
/* @__PURE__ */ (0,
|
|
20371
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { display: "flex", gap: 6, alignItems: "center" }, children: [
|
|
20372
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Pill3, { label: "Change Image", onClick: onChangeImage }),
|
|
20373
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TogglePill, { label: "Autoplay", on: autoplay, onToggle: onToggleAutoplay })
|
|
20563
20374
|
] }),
|
|
20564
|
-
error && /* @__PURE__ */ (0,
|
|
20375
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { color: "#FCA5A5", fontSize: 11, maxWidth: 220, textAlign: "center" }, children: error })
|
|
20565
20376
|
]
|
|
20566
20377
|
}
|
|
20567
20378
|
);
|
|
@@ -20701,8 +20512,8 @@ function AiFadeCarouselOverlay({
|
|
|
20701
20512
|
const activeItemRect = useLiveItemRect2(active);
|
|
20702
20513
|
const TOOLBAR_APPROX_H = 90;
|
|
20703
20514
|
const toolbarState = activeItemRect && activeItemRect.top < TOOLBAR_APPROX_H ? "active-bottom" : "active-top";
|
|
20704
|
-
return /* @__PURE__ */ (0,
|
|
20705
|
-
hoverHandleRect && hover && /* @__PURE__ */ (0,
|
|
20515
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
20516
|
+
hoverHandleRect && hover && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20706
20517
|
"button",
|
|
20707
20518
|
{
|
|
20708
20519
|
type: "button",
|
|
@@ -20731,10 +20542,10 @@ function AiFadeCarouselOverlay({
|
|
|
20731
20542
|
fontSize: 14,
|
|
20732
20543
|
fontWeight: 700
|
|
20733
20544
|
},
|
|
20734
|
-
children: /* @__PURE__ */ (0,
|
|
20545
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.Star, { size: 14, style: { pointerEvents: "none" } })
|
|
20735
20546
|
}
|
|
20736
20547
|
),
|
|
20737
|
-
swapping && /* @__PURE__ */ (0,
|
|
20548
|
+
swapping && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20738
20549
|
"div",
|
|
20739
20550
|
{
|
|
20740
20551
|
ref: skeletonRef,
|
|
@@ -20752,15 +20563,15 @@ function AiFadeCarouselOverlay({
|
|
|
20752
20563
|
zIndex: 2147483646,
|
|
20753
20564
|
pointerEvents: "none"
|
|
20754
20565
|
},
|
|
20755
|
-
children: /* @__PURE__ */ (0,
|
|
20566
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("style", { children: MEDIA_SKELETON_CSS })
|
|
20756
20567
|
}
|
|
20757
20568
|
),
|
|
20758
|
-
activeItemRect && active && activeEntry && /* @__PURE__ */ (0,
|
|
20569
|
+
activeItemRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20759
20570
|
ItemInteractionLayer,
|
|
20760
20571
|
{
|
|
20761
20572
|
rect: activeItemRect,
|
|
20762
20573
|
state: toolbarState,
|
|
20763
|
-
toolbar: /* @__PURE__ */ (0,
|
|
20574
|
+
toolbar: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20764
20575
|
CarouselSlideToolbar,
|
|
20765
20576
|
{
|
|
20766
20577
|
pending,
|
|
@@ -21113,6 +20924,113 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
|
|
|
21113
20924
|
// src/ui/link-modal/LinkPopover.tsx
|
|
21114
20925
|
var import_react17 = require("react");
|
|
21115
20926
|
|
|
20927
|
+
// src/ui/dialog.tsx
|
|
20928
|
+
var React9 = __toESM(require("react"), 1);
|
|
20929
|
+
var import_radix_ui6 = require("radix-ui");
|
|
20930
|
+
var import_lucide_react12 = require("lucide-react");
|
|
20931
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
20932
|
+
function Dialog2({
|
|
20933
|
+
...props
|
|
20934
|
+
}) {
|
|
20935
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_radix_ui6.Dialog.Root, { "data-slot": "dialog", ...props });
|
|
20936
|
+
}
|
|
20937
|
+
function DialogPortal({
|
|
20938
|
+
...props
|
|
20939
|
+
}) {
|
|
20940
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_radix_ui6.Dialog.Portal, { ...props });
|
|
20941
|
+
}
|
|
20942
|
+
function DialogOverlay({
|
|
20943
|
+
className,
|
|
20944
|
+
...props
|
|
20945
|
+
}) {
|
|
20946
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20947
|
+
import_radix_ui6.Dialog.Overlay,
|
|
20948
|
+
{
|
|
20949
|
+
"data-slot": "dialog-overlay",
|
|
20950
|
+
"data-ohw-link-modal-root": "",
|
|
20951
|
+
className: cn("fixed inset-0 z-[2147483646] bg-black/50", className),
|
|
20952
|
+
...props
|
|
20953
|
+
}
|
|
20954
|
+
);
|
|
20955
|
+
}
|
|
20956
|
+
var DialogContent = React9.forwardRef(
|
|
20957
|
+
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
20958
|
+
const positionMode = container ? "absolute" : "fixed";
|
|
20959
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(DialogPortal, { container: container ?? void 0, children: [
|
|
20960
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
20961
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
20962
|
+
import_radix_ui6.Dialog.Content,
|
|
20963
|
+
{
|
|
20964
|
+
ref,
|
|
20965
|
+
"data-slot": "dialog-content",
|
|
20966
|
+
className: cn(
|
|
20967
|
+
positionMode,
|
|
20968
|
+
"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",
|
|
20969
|
+
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
20970
|
+
container ? "max-h-[calc(100%-32px)]" : "max-h-[calc(100vh-32px)]",
|
|
20971
|
+
className
|
|
20972
|
+
),
|
|
20973
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
20974
|
+
...props,
|
|
20975
|
+
children: [
|
|
20976
|
+
children,
|
|
20977
|
+
showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20978
|
+
import_radix_ui6.Dialog.Close,
|
|
20979
|
+
{
|
|
20980
|
+
type: "button",
|
|
20981
|
+
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
20982
|
+
"aria-label": "Close",
|
|
20983
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react12.X, { size: 16, "aria-hidden": true })
|
|
20984
|
+
}
|
|
20985
|
+
) : null
|
|
20986
|
+
]
|
|
20987
|
+
}
|
|
20988
|
+
)
|
|
20989
|
+
] });
|
|
20990
|
+
}
|
|
20991
|
+
);
|
|
20992
|
+
DialogContent.displayName = import_radix_ui6.Dialog.Content.displayName;
|
|
20993
|
+
function DialogHeader({
|
|
20994
|
+
className,
|
|
20995
|
+
...props
|
|
20996
|
+
}) {
|
|
20997
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
20998
|
+
}
|
|
20999
|
+
function DialogFooter({
|
|
21000
|
+
className,
|
|
21001
|
+
...props
|
|
21002
|
+
}) {
|
|
21003
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
21004
|
+
"div",
|
|
21005
|
+
{
|
|
21006
|
+
className: cn("flex items-center justify-end gap-2", className),
|
|
21007
|
+
...props
|
|
21008
|
+
}
|
|
21009
|
+
);
|
|
21010
|
+
}
|
|
21011
|
+
var DialogTitle = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
21012
|
+
import_radix_ui6.Dialog.Title,
|
|
21013
|
+
{
|
|
21014
|
+
ref,
|
|
21015
|
+
className: cn(
|
|
21016
|
+
"text-lg font-semibold leading-none tracking-tight text-card-foreground",
|
|
21017
|
+
className
|
|
21018
|
+
),
|
|
21019
|
+
...props
|
|
21020
|
+
}
|
|
21021
|
+
));
|
|
21022
|
+
DialogTitle.displayName = import_radix_ui6.Dialog.Title.displayName;
|
|
21023
|
+
var DialogDescription = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
21024
|
+
import_radix_ui6.Dialog.Description,
|
|
21025
|
+
{
|
|
21026
|
+
ref,
|
|
21027
|
+
className: cn("text-sm text-muted-foreground", className),
|
|
21028
|
+
...props
|
|
21029
|
+
}
|
|
21030
|
+
));
|
|
21031
|
+
DialogDescription.displayName = import_radix_ui6.Dialog.Description.displayName;
|
|
21032
|
+
var DialogClose = import_radix_ui6.Dialog.Close;
|
|
21033
|
+
|
|
21116
21034
|
// src/ui/link-modal/LinkEditorPanel.tsx
|
|
21117
21035
|
var import_lucide_react16 = require("lucide-react");
|
|
21118
21036
|
|
|
@@ -22216,7 +22134,6 @@ function shouldUseDevFixtures() {
|
|
|
22216
22134
|
function getLogoElement(el) {
|
|
22217
22135
|
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
22218
22136
|
if (marked) return marked;
|
|
22219
|
-
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
22220
22137
|
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
22221
22138
|
if (!root) return null;
|
|
22222
22139
|
const anchor = el.closest("a");
|
|
@@ -24797,7 +24714,7 @@ function getNavigationSelectionParent(el) {
|
|
|
24797
24714
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
24798
24715
|
return resolveFooterLinksContainerFrom(el);
|
|
24799
24716
|
}
|
|
24800
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") ||
|
|
24717
|
+
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
|
|
24801
24718
|
return getNavigationRoot(el);
|
|
24802
24719
|
}
|
|
24803
24720
|
return null;
|
|
@@ -25019,6 +24936,7 @@ var ICONS = {
|
|
|
25019
24936
|
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"/>',
|
|
25020
24937
|
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"/>'
|
|
25021
24938
|
};
|
|
24939
|
+
var HEIGHT_SETTLE_DELAYS = [150, 400, 800];
|
|
25022
24940
|
var SELECTION_CHROME_GAP2 = 4;
|
|
25023
24941
|
var TOOLBAR_STROKE_GAP2 = 4;
|
|
25024
24942
|
var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
|
|
@@ -25116,7 +25034,7 @@ function applyVisibleViewport(el, parentScroll) {
|
|
|
25116
25034
|
el.style.top = `${top}px`;
|
|
25117
25035
|
el.style.height = `${height}px`;
|
|
25118
25036
|
}
|
|
25119
|
-
var
|
|
25037
|
+
var TOOLBAR_EDGE_MARGIN3 = 4;
|
|
25120
25038
|
function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
25121
25039
|
const isAbove = transform.includes("translateY(-100%)");
|
|
25122
25040
|
let visualTop = isAbove ? top - approxH : top;
|
|
@@ -25143,8 +25061,8 @@ function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
|
25143
25061
|
function clampToolbarLeft(centerX, toolbarWidth) {
|
|
25144
25062
|
const half = toolbarWidth / 2;
|
|
25145
25063
|
return Math.max(
|
|
25146
|
-
|
|
25147
|
-
Math.min(centerX, window.innerWidth -
|
|
25064
|
+
TOOLBAR_EDGE_MARGIN3 + half,
|
|
25065
|
+
Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN3 - half)
|
|
25148
25066
|
);
|
|
25149
25067
|
}
|
|
25150
25068
|
function calcToolbarPos(rect, parentScroll, toolbarW = 306) {
|
|
@@ -26024,6 +25942,21 @@ function OhhwellsBridge() {
|
|
|
26024
25942
|
const [isItemDragging, setIsItemDragging] = (0, import_react21.useState)(false);
|
|
26025
25943
|
const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react21.useState)(false);
|
|
26026
25944
|
isFooterFrameSelectionRef.current = isFooterFrameSelection;
|
|
25945
|
+
const [floatingPanel, setFloatingPanel] = (0, import_react21.useState)(null);
|
|
25946
|
+
const floatingPanelOpenRef = (0, import_react21.useRef)(false);
|
|
25947
|
+
floatingPanelOpenRef.current = floatingPanel !== null;
|
|
25948
|
+
const floatingPanelRef = (0, import_react21.useRef)(null);
|
|
25949
|
+
floatingPanelRef.current = floatingPanel;
|
|
25950
|
+
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react21.useState)(null);
|
|
25951
|
+
const buttonCollectionDragRef = (0, import_react21.useRef)(null);
|
|
25952
|
+
const buttonDropInsertIndexRef = (0, import_react21.useRef)(null);
|
|
25953
|
+
const [buttonDropSlots, setButtonDropSlots] = (0, import_react21.useState)([]);
|
|
25954
|
+
const [activeButtonDropIndex, setActiveButtonDropIndex] = (0, import_react21.useState)(null);
|
|
25955
|
+
const buttonPointerDragRef = (0, import_react21.useRef)(null);
|
|
25956
|
+
const [buttonStyleTick, setButtonStyleTick] = (0, import_react21.useState)(0);
|
|
25957
|
+
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react21.useState)(null);
|
|
25958
|
+
const [editorViewport, setEditorViewport] = (0, import_react21.useState)("desktop");
|
|
25959
|
+
const [parentScrollSnap, setParentScrollSnap] = (0, import_react21.useState)(null);
|
|
26027
25960
|
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react21.useState)(null);
|
|
26028
25961
|
const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react21.useState)(null);
|
|
26029
25962
|
const footerDragRef = (0, import_react21.useRef)(null);
|
|
@@ -26049,21 +25982,6 @@ function OhhwellsBridge() {
|
|
|
26049
25982
|
const stylesRef = (0, import_react21.useRef)("");
|
|
26050
25983
|
const appliedDrawerRef = (0, import_react21.useRef)(null);
|
|
26051
25984
|
const pendingDeleteUndoRef = (0, import_react21.useRef)(null);
|
|
26052
|
-
const [floatingPanel, setFloatingPanel] = (0, import_react21.useState)(null);
|
|
26053
|
-
const floatingPanelOpenRef = (0, import_react21.useRef)(false);
|
|
26054
|
-
const floatingPanelRef = (0, import_react21.useRef)(null);
|
|
26055
|
-
floatingPanelRef.current = floatingPanel;
|
|
26056
|
-
const setFloatingPanelRef = (0, import_react21.useRef)(setFloatingPanel);
|
|
26057
|
-
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react21.useState)(null);
|
|
26058
|
-
const buttonCollectionDragRef = (0, import_react21.useRef)(null);
|
|
26059
|
-
const buttonDropInsertIndexRef = (0, import_react21.useRef)(null);
|
|
26060
|
-
const [buttonDropSlots, setButtonDropSlots] = (0, import_react21.useState)([]);
|
|
26061
|
-
const [activeButtonDropIndex, setActiveButtonDropIndex] = (0, import_react21.useState)(null);
|
|
26062
|
-
const buttonPointerDragRef = (0, import_react21.useRef)(null);
|
|
26063
|
-
const [buttonStyleTick, setButtonStyleTick] = (0, import_react21.useState)(0);
|
|
26064
|
-
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react21.useState)(null);
|
|
26065
|
-
const [editorViewport, setEditorViewport] = (0, import_react21.useState)("desktop");
|
|
26066
|
-
const [parentScrollSnap, setParentScrollSnap] = (0, import_react21.useState)(null);
|
|
26067
25985
|
const [sitePages, setSitePages] = (0, import_react21.useState)([]);
|
|
26068
25986
|
const [sectionsByPath, setSectionsByPath] = (0, import_react21.useState)({});
|
|
26069
25987
|
const sectionsPrefetchGenRef = (0, import_react21.useRef)(0);
|
|
@@ -26072,18 +25990,7 @@ function OhhwellsBridge() {
|
|
|
26072
25990
|
const linkPopoverOpenRef = (0, import_react21.useRef)(false);
|
|
26073
25991
|
const linkPopoverGraceUntilRef = (0, import_react21.useRef)(0);
|
|
26074
25992
|
setLinkPopoverRef.current = setLinkPopover;
|
|
26075
|
-
setFloatingPanelRef.current = setFloatingPanel;
|
|
26076
25993
|
linkPopoverSessionRef.current = linkPopover;
|
|
26077
|
-
floatingPanelOpenRef.current = Boolean(floatingPanel);
|
|
26078
|
-
(0, import_react21.useEffect)(() => {
|
|
26079
|
-
const syncViewport = () => {
|
|
26080
|
-
const next = window.innerWidth <= 480 ? "mobile" : "desktop";
|
|
26081
|
-
setEditorViewport((prev) => prev === next ? prev : next);
|
|
26082
|
-
};
|
|
26083
|
-
syncViewport();
|
|
26084
|
-
window.addEventListener("resize", syncViewport);
|
|
26085
|
-
return () => window.removeEventListener("resize", syncViewport);
|
|
26086
|
-
}, []);
|
|
26087
25994
|
(0, import_react21.useEffect)(() => {
|
|
26088
25995
|
setSectionOrderPersistHandler((entries) => {
|
|
26089
25996
|
const currentPath = window.location.pathname;
|
|
@@ -27778,7 +27685,6 @@ function OhhwellsBridge() {
|
|
|
27778
27685
|
applyAiFooterFromContent(content);
|
|
27779
27686
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
27780
27687
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
27781
|
-
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
27782
27688
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
27783
27689
|
}
|
|
27784
27690
|
applyBrandChrome(content);
|
|
@@ -27789,12 +27695,12 @@ function OhhwellsBridge() {
|
|
|
27789
27695
|
if (key === "__ohw_sections") continue;
|
|
27790
27696
|
if (key === AI_SECTIONS_KEY) continue;
|
|
27791
27697
|
if (key === AI_FOOTER_KEY) continue;
|
|
27792
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
27793
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27794
27698
|
if (key === BRAND_KIT_KEY) continue;
|
|
27795
27699
|
if (key === STYLE_STORE_KEY) continue;
|
|
27796
27700
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
27701
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
27797
27702
|
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
27703
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27798
27704
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
27799
27705
|
continue;
|
|
27800
27706
|
}
|
|
@@ -28025,18 +27931,17 @@ function OhhwellsBridge() {
|
|
|
28025
27931
|
}
|
|
28026
27932
|
applyAiFooterFromContent(content);
|
|
28027
27933
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
28028
|
-
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
28029
27934
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
28030
27935
|
}
|
|
28031
27936
|
for (const [key, val] of Object.entries(content)) {
|
|
28032
27937
|
if (key === "__ohw_sections") continue;
|
|
28033
27938
|
if (key === AI_SECTIONS_KEY) continue;
|
|
28034
27939
|
if (key === AI_FOOTER_KEY) continue;
|
|
28035
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
28036
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
28037
27940
|
if (key === BRAND_KIT_KEY) continue;
|
|
28038
27941
|
if (key === STYLE_STORE_KEY) continue;
|
|
28039
27942
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
27943
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
27944
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
28040
27945
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
28041
27946
|
continue;
|
|
28042
27947
|
}
|
|
@@ -28303,11 +28208,26 @@ function OhhwellsBridge() {
|
|
|
28303
28208
|
const t2 = setTimeout(measure, 500);
|
|
28304
28209
|
const ro = new ResizeObserver(schedule);
|
|
28305
28210
|
ro.observe(document.body);
|
|
28211
|
+
let lastWidth = window.innerWidth;
|
|
28212
|
+
let resizeTimers = [];
|
|
28213
|
+
const clearResizeTimers = () => {
|
|
28214
|
+
resizeTimers.forEach(clearTimeout);
|
|
28215
|
+
resizeTimers = [];
|
|
28216
|
+
};
|
|
28217
|
+
const handleResize = () => {
|
|
28218
|
+
if (window.innerWidth === lastWidth) return;
|
|
28219
|
+
lastWidth = window.innerWidth;
|
|
28220
|
+
clearResizeTimers();
|
|
28221
|
+
resizeTimers = HEIGHT_SETTLE_DELAYS.map((delay) => setTimeout(measure, delay));
|
|
28222
|
+
};
|
|
28223
|
+
window.addEventListener("resize", handleResize);
|
|
28306
28224
|
return () => {
|
|
28307
28225
|
clearTimeout(t1);
|
|
28308
28226
|
clearTimeout(t2);
|
|
28309
28227
|
if (raf != null) cancelAnimationFrame(raf);
|
|
28310
28228
|
ro.disconnect();
|
|
28229
|
+
clearResizeTimers();
|
|
28230
|
+
window.removeEventListener("resize", handleResize);
|
|
28311
28231
|
};
|
|
28312
28232
|
}, [pathname, isEditMode, postToParent2]);
|
|
28313
28233
|
(0, import_react21.useEffect)(() => {
|
|
@@ -28604,13 +28524,6 @@ function OhhwellsBridge() {
|
|
|
28604
28524
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
28605
28525
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
28606
28526
|
if (isInsideLinkEditor(target)) return;
|
|
28607
|
-
if (isInsideFloatingPanel(target)) return;
|
|
28608
|
-
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
28609
|
-
if (target.closest(
|
|
28610
|
-
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
28611
|
-
)) {
|
|
28612
|
-
return;
|
|
28613
|
-
}
|
|
28614
28527
|
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
28615
28528
|
clearMediaSelectionRef.current();
|
|
28616
28529
|
}
|
|
@@ -28634,6 +28547,13 @@ function OhhwellsBridge() {
|
|
|
28634
28547
|
return;
|
|
28635
28548
|
}
|
|
28636
28549
|
}
|
|
28550
|
+
if (isInsideFloatingPanel(target)) return;
|
|
28551
|
+
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
28552
|
+
if (target.closest(
|
|
28553
|
+
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
28554
|
+
)) {
|
|
28555
|
+
return;
|
|
28556
|
+
}
|
|
28637
28557
|
{
|
|
28638
28558
|
const formEl = getFormElement(target);
|
|
28639
28559
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
@@ -28787,13 +28707,9 @@ function OhhwellsBridge() {
|
|
|
28787
28707
|
if (isIconEditable(editable) && !getSocialItem(editable)) {
|
|
28788
28708
|
e.preventDefault();
|
|
28789
28709
|
e.stopPropagation();
|
|
28710
|
+
selectIconElementRef.current(editable);
|
|
28790
28711
|
const aiIcon = editable.hasAttribute("data-ai-icon");
|
|
28791
28712
|
const featureIcon = aiIcon && /\.features\.\d+\.icon$/.test(editable.dataset.ohwKey ?? "");
|
|
28792
|
-
if (aiIcon) {
|
|
28793
|
-
aiSectionApiRef.current?.selectFromElement(editable);
|
|
28794
|
-
} else {
|
|
28795
|
-
selectIconElementRef.current(editable);
|
|
28796
|
-
}
|
|
28797
28713
|
postToParentRef.current({
|
|
28798
28714
|
type: "ow:icon-pick",
|
|
28799
28715
|
key: editable.dataset.ohwKey ?? "",
|
|
@@ -29021,9 +28937,6 @@ function OhhwellsBridge() {
|
|
|
29021
28937
|
setHoveredItemRect(null);
|
|
29022
28938
|
hoveredNavContainerRef.current = null;
|
|
29023
28939
|
setHoveredNavContainerRect(null);
|
|
29024
|
-
siblingHintElRef.current = null;
|
|
29025
|
-
setSiblingHintRect(null);
|
|
29026
|
-
setSiblingHintRects([]);
|
|
29027
28940
|
return;
|
|
29028
28941
|
}
|
|
29029
28942
|
{
|
|
@@ -29144,6 +29057,7 @@ function OhhwellsBridge() {
|
|
|
29144
29057
|
hoveredNavContainerRef.current = null;
|
|
29145
29058
|
setHoveredNavContainerRect(null);
|
|
29146
29059
|
hoveredItemElRef.current = editable;
|
|
29060
|
+
setHoveredItemRect(isSelectedForHoverRef.current(editable) ? null : editable.getBoundingClientRect());
|
|
29147
29061
|
}
|
|
29148
29062
|
}
|
|
29149
29063
|
}
|
|
@@ -29853,11 +29767,7 @@ function OhhwellsBridge() {
|
|
|
29853
29767
|
};
|
|
29854
29768
|
const handleMouseMove = (e) => {
|
|
29855
29769
|
const { clientX, clientY } = e;
|
|
29856
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
29857
|
-
dismissImageHover();
|
|
29858
|
-
clearImageHover();
|
|
29859
|
-
return;
|
|
29860
|
-
}
|
|
29770
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) return;
|
|
29861
29771
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) {
|
|
29862
29772
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
29863
29773
|
formHoverElRef.current = null;
|
|
@@ -29886,12 +29796,7 @@ function OhhwellsBridge() {
|
|
|
29886
29796
|
setHoveredItemRect(null);
|
|
29887
29797
|
hoveredNavContainerRef.current = null;
|
|
29888
29798
|
setHoveredNavContainerRect(null);
|
|
29889
|
-
siblingHintElRef.current = null;
|
|
29890
|
-
setSiblingHintRect(null);
|
|
29891
|
-
setSiblingHintRects([]);
|
|
29892
29799
|
dismissImageHover();
|
|
29893
|
-
clearImageHover();
|
|
29894
|
-
setSectionGap(null);
|
|
29895
29800
|
return;
|
|
29896
29801
|
}
|
|
29897
29802
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
@@ -29903,11 +29808,7 @@ function OhhwellsBridge() {
|
|
|
29903
29808
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
29904
29809
|
const { clientX, clientY } = e.data;
|
|
29905
29810
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
29906
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
29907
|
-
dismissImageHover();
|
|
29908
|
-
clearImageHover();
|
|
29909
|
-
return;
|
|
29910
|
-
}
|
|
29811
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) return;
|
|
29911
29812
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) return;
|
|
29912
29813
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
29913
29814
|
probeSectionGapAt(clientX, clientY);
|
|
@@ -30287,7 +30188,6 @@ function OhhwellsBridge() {
|
|
|
30287
30188
|
applyAiFooterFromContent(content);
|
|
30288
30189
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
30289
30190
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
30290
|
-
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
30291
30191
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
30292
30192
|
}
|
|
30293
30193
|
applyBrandChrome(content);
|
|
@@ -30302,12 +30202,12 @@ function OhhwellsBridge() {
|
|
|
30302
30202
|
}
|
|
30303
30203
|
if (key === AI_SECTIONS_KEY) continue;
|
|
30304
30204
|
if (key === AI_FOOTER_KEY) continue;
|
|
30305
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
30306
|
-
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
30307
30205
|
if (key === BRAND_KIT_KEY) continue;
|
|
30308
30206
|
if (key === STYLE_STORE_KEY) continue;
|
|
30309
30207
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
30208
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
30310
30209
|
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
30210
|
+
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
30311
30211
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
30312
30212
|
continue;
|
|
30313
30213
|
}
|
|
@@ -30943,24 +30843,12 @@ function OhhwellsBridge() {
|
|
|
30943
30843
|
closeLinkPopoverRef.current();
|
|
30944
30844
|
return;
|
|
30945
30845
|
}
|
|
30946
|
-
if (floatingPanelOpenRef.current) {
|
|
30947
|
-
setFloatingPanelRef.current(null);
|
|
30948
|
-
deselectRef.current();
|
|
30949
|
-
deactivateRef.current();
|
|
30950
|
-
return;
|
|
30951
|
-
}
|
|
30952
30846
|
deselectRef.current();
|
|
30953
30847
|
deactivateRef.current();
|
|
30954
30848
|
clearMediaSelectionRef.current();
|
|
30955
30849
|
clearIconSelectionRef.current();
|
|
30956
30850
|
};
|
|
30957
30851
|
window.addEventListener("message", handleDeactivate);
|
|
30958
|
-
const handleSelectNav = (e) => {
|
|
30959
|
-
if (e.data?.type !== "ow:select-nav") return;
|
|
30960
|
-
const navContainer = findSelectableNavContainer();
|
|
30961
|
-
if (navContainer) selectFrameRef.current(navContainer);
|
|
30962
|
-
};
|
|
30963
|
-
window.addEventListener("message", handleSelectNav);
|
|
30964
30852
|
const handleToastAction = (e) => {
|
|
30965
30853
|
if (e.data?.type !== "ow:toast-action") return;
|
|
30966
30854
|
const actionId = typeof e.data.actionId === "string" ? e.data.actionId : null;
|
|
@@ -31777,11 +31665,10 @@ function OhhwellsBridge() {
|
|
|
31777
31665
|
window.removeEventListener("message", handleDeleteSection);
|
|
31778
31666
|
window.removeEventListener("message", handleDuplicateSection);
|
|
31779
31667
|
window.removeEventListener("message", handleDeactivate);
|
|
31780
|
-
|
|
31668
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
31781
31669
|
window.removeEventListener("message", handleToastAction);
|
|
31782
31670
|
window.removeEventListener("message", handleFormCount);
|
|
31783
31671
|
window.removeEventListener("message", handleUiEscape);
|
|
31784
|
-
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
31785
31672
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
31786
31673
|
autoSaveTimers.current.clear();
|
|
31787
31674
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
@@ -32075,7 +31962,7 @@ function OhhwellsBridge() {
|
|
|
32075
31962
|
postToParent2({
|
|
32076
31963
|
type: "ow:ready",
|
|
32077
31964
|
version: "1",
|
|
32078
|
-
bridgeVersion: "0.1.
|
|
31965
|
+
bridgeVersion: "0.1.153",
|
|
32079
31966
|
path: pathname,
|
|
32080
31967
|
nodes: collectEditableNodes(editContentRef.current),
|
|
32081
31968
|
sections
|