@ohhwells/bridge 0.1.159 → 0.1.160-next.427
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.cjs +965 -724
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1004 -747
- package/dist/index.js.map +1 -1
- package/dist/pages.cjs +9 -1
- package/dist/pages.cjs.map +1 -1
- package/dist/pages.d.cts +2 -0
- package/dist/pages.d.ts +2 -0
- package/dist/pages.js +9 -1
- package/dist/pages.js.map +1 -1
- package/dist/styles.css +116 -0
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -6763,6 +6763,21 @@ function pricingCardFeatureCount(tree, index) {
|
|
|
6763
6763
|
const target = findPricingCollection(tree)?.children?.[index];
|
|
6764
6764
|
return target ? pricingFeatureList(target).length : 0;
|
|
6765
6765
|
}
|
|
6766
|
+
function prevailingFeatureIcon(features) {
|
|
6767
|
+
const counts = /* @__PURE__ */ new Map();
|
|
6768
|
+
for (const row of features) {
|
|
6769
|
+
const key = `${row.icon ?? ""}|${row.iconColor ?? ""}`;
|
|
6770
|
+
const entry = counts.get(key) ?? { count: 0, ...row.icon ? { icon: row.icon } : {}, ...row.iconColor ? { iconColor: row.iconColor } : {} };
|
|
6771
|
+
entry.count += 1;
|
|
6772
|
+
counts.set(key, entry);
|
|
6773
|
+
}
|
|
6774
|
+
let best = null;
|
|
6775
|
+
for (const entry of counts.values()) {
|
|
6776
|
+
if (!best || entry.count > best.count) best = entry;
|
|
6777
|
+
}
|
|
6778
|
+
if (!best) return {};
|
|
6779
|
+
return { ...best.icon ? { icon: best.icon } : {}, ...best.iconColor ? { iconColor: best.iconColor } : {} };
|
|
6780
|
+
}
|
|
6766
6781
|
function addPricingCardFeature(tree, index, text) {
|
|
6767
6782
|
return withPricingCollection(tree, (collection) => {
|
|
6768
6783
|
const children = collection.children;
|
|
@@ -6771,7 +6786,7 @@ function addPricingCardFeature(tree, index, text) {
|
|
|
6771
6786
|
const features = pricingFeatureList(target);
|
|
6772
6787
|
if (features.length >= PRICING_FEATURES_MAX) return false;
|
|
6773
6788
|
target.slots = target.slots ?? {};
|
|
6774
|
-
target.slots.features = [...features, { text }];
|
|
6789
|
+
target.slots.features = [...features, { text, ...prevailingFeatureIcon(features) }];
|
|
6775
6790
|
return true;
|
|
6776
6791
|
});
|
|
6777
6792
|
}
|
|
@@ -7383,6 +7398,23 @@ function applyCustomCodeToHead(content) {
|
|
|
7383
7398
|
if (beforeNodes.length > 0) document.head.append(...beforeNodes);
|
|
7384
7399
|
}
|
|
7385
7400
|
|
|
7401
|
+
// src/lib/node-font-size.ts
|
|
7402
|
+
var TEXT_NODE_TYPES = /* @__PURE__ */ new Set(["text", "text/rich", "plain", "link"]);
|
|
7403
|
+
function escapeKey(key) {
|
|
7404
|
+
return typeof CSS !== "undefined" && typeof CSS.escape === "function" ? CSS.escape(key) : key.replace(/["\\]/g, "\\$&");
|
|
7405
|
+
}
|
|
7406
|
+
function measureNodeFontSize(key, type, root) {
|
|
7407
|
+
if (!TEXT_NODE_TYPES.has(type)) return void 0;
|
|
7408
|
+
const el = root.querySelector(`[data-ohw-editable][data-ohw-key="${escapeKey(key)}"]`);
|
|
7409
|
+
if (!el) return void 0;
|
|
7410
|
+
const size = Number.parseFloat(window.getComputedStyle(el).fontSize);
|
|
7411
|
+
return Number.isFinite(size) && size > 0 ? Math.round(size) : void 0;
|
|
7412
|
+
}
|
|
7413
|
+
function withNodeFontSize(node, root) {
|
|
7414
|
+
const fontSize = measureNodeFontSize(node.key, node.type, root);
|
|
7415
|
+
return fontSize === void 0 ? node : { ...node, fontSize };
|
|
7416
|
+
}
|
|
7417
|
+
|
|
7386
7418
|
// src/lib/selectNavContainer.ts
|
|
7387
7419
|
function isOnScreen(el) {
|
|
7388
7420
|
const rect = el.getBoundingClientRect();
|
|
@@ -7971,7 +8003,7 @@ var AI_MOBILE_CSS = [
|
|
|
7971
8003
|
// page's first section. Top only (bottom needs no nav clearance); ~96px approximates the
|
|
7972
8004
|
// template nav's own height (measured ~94px) — there's no shared `--ohw-header-h` var to read
|
|
7973
8005
|
// an exact figure from (no live measurement exists), so this is a safe approximation, not a
|
|
7974
|
-
// pixel-exact fit. Horizontal spacing already comes from `data-ai-
|
|
8006
|
+
// pixel-exact fit. Horizontal spacing already comes from `data-ai-section-inner`.
|
|
7975
8007
|
'[data-ai-overlay-clearance] [data-ai-overlap-layer="overlay"]{padding-top:96px}',
|
|
7976
8008
|
// A full-bleed carousel's height is pure arithmetic: it spans the whole window, so 16/9 turns
|
|
7977
8009
|
// window width straight into height. Measured at 16/9 it came out ~90% of the viewport at EVERY
|
|
@@ -7987,8 +8019,10 @@ var AI_MOBILE_CSS = [
|
|
|
7987
8019
|
"[data-ai-section]{overflow-x:hidden}",
|
|
7988
8020
|
// `:not([data-ai-full-bleed])`: this `!important` gutter beat the inline `padding: 0` that a
|
|
7989
8021
|
// full-bleed section's container sets, so a carousel/media hero that is edge-to-edge on desktop
|
|
7990
|
-
// still got a 20px band of section background down both sides on a phone.
|
|
7991
|
-
|
|
8022
|
+
// still got a 20px band of section background down both sides on a phone. The footer's own
|
|
8023
|
+
// container keeps the unguarded rule below — `data-ai-full-bleed` can never appear on it.
|
|
8024
|
+
"[data-ai-section-inner]:not([data-ai-full-bleed]){padding:0 20px !important}",
|
|
8025
|
+
"[data-ai-container]{padding:0 20px !important}",
|
|
7992
8026
|
"[data-ai-row]{display:flex !important;flex-direction:column !important;align-items:stretch !important}",
|
|
7993
8027
|
"[data-ai-cell]{width:100%;min-width:0}",
|
|
7994
8028
|
// The rule above turns every row into a COLUMN flex container on phones, which silently breaks
|
|
@@ -8193,6 +8227,31 @@ function pricingCardEmphasis(featured, ctx, hasBg) {
|
|
|
8193
8227
|
function textAttrs(ctx, path) {
|
|
8194
8228
|
return ctx.keyFor ? { "data-ohw-key": ctx.keyFor(path), "data-ohw-editable": "text" } : {};
|
|
8195
8229
|
}
|
|
8230
|
+
var AI_RESPONSIVE_CSS = [
|
|
8231
|
+
"@media (max-width: 960px) {",
|
|
8232
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: repeat(2, 1fr) !important; }",
|
|
8233
|
+
' [data-ai-responsive] [data-ai-grid="1"] { grid-template-columns: 1fr !important; }',
|
|
8234
|
+
"}",
|
|
8235
|
+
"@media (max-width: 640px) {",
|
|
8236
|
+
" [data-ai-responsive] [data-ai-grid] { grid-template-columns: 1fr !important; }",
|
|
8237
|
+
" [data-ai-responsive] [data-ai-columns] > * { grid-column: 1 / -1 !important; }",
|
|
8238
|
+
// Group containers flatten to a column on phones; span placements come along for free.
|
|
8239
|
+
// `:not([data-ai-group="overlap"])` for the same reason as the twin pair in AI_MOBILE_CSS — see
|
|
8240
|
+
// the comment there. This sheet's copy is the narrower selector, so without the exemption it
|
|
8241
|
+
// flattens an `overlap` hero below 640px even though the other rule stands down: measured a 390px
|
|
8242
|
+
// viewport with the heading/CTA in flow *under* the image, 219px of section background where the
|
|
8243
|
+
// layered text used to be.
|
|
8244
|
+
' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) { display: flex !important; flex-direction: column !important; }',
|
|
8245
|
+
' [data-ai-responsive] [data-ai-group]:not([data-ai-group="overlap"]) > * { grid-column: auto !important; }',
|
|
8246
|
+
// `:not([data-ai-full-bleed])` for the same reason as the twin rule in AI_MOBILE_CSS: this one
|
|
8247
|
+
// is narrower (0,2,0 vs 0,1,0) and also `!important`, so without the guard it wins outright and
|
|
8248
|
+
// a full-bleed hero gets its 20px side band back below 640px only — the one width where the
|
|
8249
|
+
// other rule had already been taught to stand down.
|
|
8250
|
+
" [data-ai-responsive] [data-ai-section-inner]:not([data-ai-full-bleed]) { padding-left: 20px !important; padding-right: 20px !important; }",
|
|
8251
|
+
" [data-ai-responsive] { overflow-x: hidden; }",
|
|
8252
|
+
" [data-ai-responsive] img { max-width: 100%; }",
|
|
8253
|
+
"}"
|
|
8254
|
+
].join("\n");
|
|
8196
8255
|
var TRANSPARENT_PX = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
8197
8256
|
function MediaBox({
|
|
8198
8257
|
refValue,
|
|
@@ -8247,7 +8306,7 @@ function MediaBox({
|
|
|
8247
8306
|
position: fill ? "absolute" : void 0,
|
|
8248
8307
|
inset: fill ? 0 : void 0,
|
|
8249
8308
|
width: fill ? "100%" : fixedSize ? "auto" : "100%",
|
|
8250
|
-
height: fill ? "100%" : void 0,
|
|
8309
|
+
height: fill ? "100%" : fixedSize ? height : void 0,
|
|
8251
8310
|
aspectRatio: fill ? void 0 : aspectRatio,
|
|
8252
8311
|
minHeight: fill || fixedSize ? void 0 : height ?? (aspectRatio ? void 0 : 180),
|
|
8253
8312
|
borderRadius: radius,
|
|
@@ -9743,7 +9802,7 @@ function CollectionBlock({ node, ctx, path }) {
|
|
|
9743
9802
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
9744
9803
|
"div",
|
|
9745
9804
|
{
|
|
9746
|
-
"data-ai-grid":
|
|
9805
|
+
"data-ai-grid": String(itemsPerRow),
|
|
9747
9806
|
"data-ohw-pricing-collection": isPricing ? "" : void 0,
|
|
9748
9807
|
style: {
|
|
9749
9808
|
display: "grid",
|
|
@@ -10045,7 +10104,7 @@ function renderNode(node, ctx, path, ambientAlign) {
|
|
|
10045
10104
|
},
|
|
10046
10105
|
children: [
|
|
10047
10106
|
i > 0 && ctx.heroOverlapFullBleed ? (
|
|
10048
|
-
// The section's `data-ai-
|
|
10107
|
+
// The section's `data-ai-section-inner` gave up its max-width/gutter so the base
|
|
10049
10108
|
// layer (this group's i===0 sibling) can span edge-to-edge — reintroduced here,
|
|
10050
10109
|
// scoped to just the overlay text, so a heading/copy/CTA stack doesn't stretch
|
|
10051
10110
|
// the full section width instead of reading at the usual content width.
|
|
@@ -10464,6 +10523,7 @@ function AiTreeRenderer({
|
|
|
10464
10523
|
...fillHeight ? { "data-ai-fill-height": "" } : {},
|
|
10465
10524
|
...needsOverlayClearance ? { "data-ai-overlay-clearance": "" } : {},
|
|
10466
10525
|
...bgAttrs,
|
|
10526
|
+
"data-ai-responsive": "",
|
|
10467
10527
|
style: {
|
|
10468
10528
|
position: "relative",
|
|
10469
10529
|
padding: `${padCss} 0`,
|
|
@@ -10477,12 +10537,13 @@ function AiTreeRenderer({
|
|
|
10477
10537
|
...fillHeight ? { display: "grid" } : {}
|
|
10478
10538
|
},
|
|
10479
10539
|
children: [
|
|
10480
|
-
|
|
10540
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_RESPONSIVE_CSS }),
|
|
10481
10541
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: AI_MOBILE_CSS }),
|
|
10542
|
+
isOverlay && backgroundUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { position: "absolute", inset: 0, background: `rgba(255,255,255,${overlayAlpha})` } }),
|
|
10482
10543
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
10483
10544
|
"div",
|
|
10484
10545
|
{
|
|
10485
|
-
"data-ai-
|
|
10546
|
+
"data-ai-section-inner": "",
|
|
10486
10547
|
...fullBleedMedia ? { "data-ai-full-bleed": "" } : {},
|
|
10487
10548
|
style: {
|
|
10488
10549
|
position: "relative",
|
|
@@ -10499,7 +10560,7 @@ function AiTreeRenderer({
|
|
|
10499
10560
|
children: tree.rows.map((row, r2) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
10500
10561
|
"div",
|
|
10501
10562
|
{
|
|
10502
|
-
"data-ai-
|
|
10563
|
+
"data-ai-columns": "",
|
|
10503
10564
|
style: {
|
|
10504
10565
|
display: "grid",
|
|
10505
10566
|
gridTemplateColumns: "repeat(12, 1fr)",
|
|
@@ -11161,9 +11222,10 @@ function applyAiSectionsToDom(state, options) {
|
|
|
11161
11222
|
if (existing && existing.serialized === serialized && existing.container.isConnected) {
|
|
11162
11223
|
continue;
|
|
11163
11224
|
}
|
|
11164
|
-
const isNewMount = !existing || !existing.container.isConnected;
|
|
11165
11225
|
let container = existing?.container;
|
|
11226
|
+
let isNewMount = false;
|
|
11166
11227
|
if (!container || !container.isConnected) {
|
|
11228
|
+
isNewMount = true;
|
|
11167
11229
|
existing?.root.unmount();
|
|
11168
11230
|
container?.remove();
|
|
11169
11231
|
container = document.createElement("div");
|
|
@@ -17322,7 +17384,7 @@ function apiBase() {
|
|
|
17322
17384
|
function bridgeVersion() {
|
|
17323
17385
|
try {
|
|
17324
17386
|
if (true) {
|
|
17325
|
-
return "0.1.
|
|
17387
|
+
return "0.1.160-next.427";
|
|
17326
17388
|
}
|
|
17327
17389
|
} catch {
|
|
17328
17390
|
}
|
|
@@ -17336,7 +17398,7 @@ function stampBridgeVersionOnDocument() {
|
|
|
17336
17398
|
return;
|
|
17337
17399
|
}
|
|
17338
17400
|
try {
|
|
17339
|
-
const v = true ? "0.1.
|
|
17401
|
+
const v = true ? "0.1.160-next.427" : "";
|
|
17340
17402
|
if (v) {
|
|
17341
17403
|
document.documentElement.setAttribute("data-ohw-bridge-version", v);
|
|
17342
17404
|
window.__OHW_BRIDGE_VERSION__ = v;
|
|
@@ -18014,6 +18076,7 @@ function MediaOverlay({
|
|
|
18014
18076
|
(prev) => prev && prev.fullWidth === width && prev.height === height ? prev : { fullWidth: width, height }
|
|
18015
18077
|
);
|
|
18016
18078
|
}, [isVideo]);
|
|
18079
|
+
const replaceLabel = isVideo ? "Replace video" : hover.elementType === "bg-image" ? "Replace background" : "Replace image";
|
|
18017
18080
|
const replaceMode = buttonSize ? replaceButtonMode({ width: rect.width, height: rect.height }, buttonSize) : "none";
|
|
18018
18081
|
const box = {
|
|
18019
18082
|
position: "fixed",
|
|
@@ -18112,11 +18175,10 @@ function MediaOverlay({
|
|
|
18112
18175
|
className: "flex items-center justify-center cursor-pointer",
|
|
18113
18176
|
style: {
|
|
18114
18177
|
...box,
|
|
18115
|
-
//
|
|
18116
|
-
//
|
|
18117
|
-
//
|
|
18118
|
-
|
|
18119
|
-
pointerEvents: hover.hasTextOverlap || cueOnly ? "none" : "auto",
|
|
18178
|
+
// Visual only. `pointer-events: auto` on this full-bleed rect covered the navbar
|
|
18179
|
+
// (hero bg includes the absolute TopNav) and swallowed CTA press-drag. Text overlay
|
|
18180
|
+
// and cueOnly also need clicks to fall through — Replace / video controls opt back in.
|
|
18181
|
+
pointerEvents: "none",
|
|
18120
18182
|
// Selected: a firm component ring with no wash, so the image reads as chosen rather
|
|
18121
18183
|
// than hovered. Hover keeps the existing tinted preview.
|
|
18122
18184
|
boxShadow: selected ? "inset 0 0 0 2px var(--color-bridge-primary)" : "inset 0 0 0 1.5px var(--color-bridge-primary)",
|
|
@@ -18143,17 +18205,17 @@ function MediaOverlay({
|
|
|
18143
18205
|
},
|
|
18144
18206
|
children: [
|
|
18145
18207
|
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 }),
|
|
18146
|
-
|
|
18208
|
+
replaceLabel
|
|
18147
18209
|
]
|
|
18148
18210
|
}
|
|
18149
18211
|
),
|
|
18150
|
-
replaceMode
|
|
18212
|
+
showChrome && replaceMode !== "none" && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
18151
18213
|
Button,
|
|
18152
18214
|
{
|
|
18153
18215
|
"data-ohw-media-overlay": "",
|
|
18154
18216
|
variant: "outline",
|
|
18155
18217
|
size: "sm",
|
|
18156
|
-
"aria-label":
|
|
18218
|
+
"aria-label": replaceLabel,
|
|
18157
18219
|
className: "gap-1.5 cursor-pointer hover:bg-background",
|
|
18158
18220
|
style: {
|
|
18159
18221
|
...OVERLAY_BUTTON_STYLE,
|
|
@@ -18176,7 +18238,7 @@ function MediaOverlay({
|
|
|
18176
18238
|
},
|
|
18177
18239
|
children: [
|
|
18178
18240
|
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 }),
|
|
18179
|
-
replaceMode === "full" ?
|
|
18241
|
+
replaceMode === "full" ? replaceLabel : null
|
|
18180
18242
|
]
|
|
18181
18243
|
}
|
|
18182
18244
|
)
|
|
@@ -18770,7 +18832,7 @@ function AiSectionOverlay({
|
|
|
18770
18832
|
|
|
18771
18833
|
// src/ui/ai-section/AiMediaStripOverlay.tsx
|
|
18772
18834
|
var import_react10 = require("react");
|
|
18773
|
-
var
|
|
18835
|
+
var import_lucide_react9 = require("lucide-react");
|
|
18774
18836
|
|
|
18775
18837
|
// src/lib/ai-media-strip-tree.ts
|
|
18776
18838
|
var MEDIA_STRIP_ITEM_MIN = 1;
|
|
@@ -18884,14 +18946,6 @@ function setMediaStripItemAsset(tree, index, assetId) {
|
|
|
18884
18946
|
return true;
|
|
18885
18947
|
});
|
|
18886
18948
|
}
|
|
18887
|
-
function setMediaStripItemAlt(tree, index, alt) {
|
|
18888
|
-
return withMediaStrip(tree, (block) => {
|
|
18889
|
-
const items = block.items;
|
|
18890
|
-
if (index < 0 || index >= items.length) return false;
|
|
18891
|
-
items[index] = { ...items[index], alt };
|
|
18892
|
-
return true;
|
|
18893
|
-
});
|
|
18894
|
-
}
|
|
18895
18949
|
function setMediaStripItemLink(tree, index, link) {
|
|
18896
18950
|
return withMediaStrip(tree, (block) => {
|
|
18897
18951
|
const items = block.items;
|
|
@@ -18909,11 +18963,117 @@ function setMediaStripItemLink(tree, index, link) {
|
|
|
18909
18963
|
});
|
|
18910
18964
|
}
|
|
18911
18965
|
|
|
18912
|
-
// src/ui/
|
|
18966
|
+
// src/ui/dialog.tsx
|
|
18967
|
+
var React9 = __toESM(require("react"), 1);
|
|
18968
|
+
var import_radix_ui6 = require("radix-ui");
|
|
18969
|
+
var import_lucide_react8 = require("lucide-react");
|
|
18913
18970
|
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
18914
|
-
|
|
18915
|
-
|
|
18916
|
-
|
|
18971
|
+
function Dialog2({
|
|
18972
|
+
...props
|
|
18973
|
+
}) {
|
|
18974
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_radix_ui6.Dialog.Root, { "data-slot": "dialog", ...props });
|
|
18975
|
+
}
|
|
18976
|
+
function DialogPortal({
|
|
18977
|
+
...props
|
|
18978
|
+
}) {
|
|
18979
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_radix_ui6.Dialog.Portal, { ...props });
|
|
18980
|
+
}
|
|
18981
|
+
function DialogOverlay({
|
|
18982
|
+
className,
|
|
18983
|
+
...props
|
|
18984
|
+
}) {
|
|
18985
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
18986
|
+
import_radix_ui6.Dialog.Overlay,
|
|
18987
|
+
{
|
|
18988
|
+
"data-slot": "dialog-overlay",
|
|
18989
|
+
"data-ohw-link-modal-root": "",
|
|
18990
|
+
className: cn("fixed inset-0 z-[2147483646] bg-black/50", className),
|
|
18991
|
+
...props
|
|
18992
|
+
}
|
|
18993
|
+
);
|
|
18994
|
+
}
|
|
18995
|
+
var DialogContent = React9.forwardRef(
|
|
18996
|
+
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
18997
|
+
const positionMode = container ? "absolute" : "fixed";
|
|
18998
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(DialogPortal, { container: container ?? void 0, children: [
|
|
18999
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
19000
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
19001
|
+
import_radix_ui6.Dialog.Content,
|
|
19002
|
+
{
|
|
19003
|
+
ref,
|
|
19004
|
+
"data-slot": "dialog-content",
|
|
19005
|
+
className: cn(
|
|
19006
|
+
positionMode,
|
|
19007
|
+
"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",
|
|
19008
|
+
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
19009
|
+
container ? "max-h-[calc(100%-32px)]" : "max-h-[calc(100vh-32px)]",
|
|
19010
|
+
className
|
|
19011
|
+
),
|
|
19012
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
19013
|
+
...props,
|
|
19014
|
+
children: [
|
|
19015
|
+
children,
|
|
19016
|
+
showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
19017
|
+
import_radix_ui6.Dialog.Close,
|
|
19018
|
+
{
|
|
19019
|
+
type: "button",
|
|
19020
|
+
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
19021
|
+
"aria-label": "Close",
|
|
19022
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react8.X, { size: 16, "aria-hidden": true })
|
|
19023
|
+
}
|
|
19024
|
+
) : null
|
|
19025
|
+
]
|
|
19026
|
+
}
|
|
19027
|
+
)
|
|
19028
|
+
] });
|
|
19029
|
+
}
|
|
19030
|
+
);
|
|
19031
|
+
DialogContent.displayName = import_radix_ui6.Dialog.Content.displayName;
|
|
19032
|
+
function DialogHeader({
|
|
19033
|
+
className,
|
|
19034
|
+
...props
|
|
19035
|
+
}) {
|
|
19036
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
19037
|
+
}
|
|
19038
|
+
function DialogFooter({
|
|
19039
|
+
className,
|
|
19040
|
+
...props
|
|
19041
|
+
}) {
|
|
19042
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
19043
|
+
"div",
|
|
19044
|
+
{
|
|
19045
|
+
className: cn("flex items-center justify-end gap-2", className),
|
|
19046
|
+
...props
|
|
19047
|
+
}
|
|
19048
|
+
);
|
|
19049
|
+
}
|
|
19050
|
+
var DialogTitle = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
19051
|
+
import_radix_ui6.Dialog.Title,
|
|
19052
|
+
{
|
|
19053
|
+
ref,
|
|
19054
|
+
className: cn(
|
|
19055
|
+
"text-lg font-semibold leading-none tracking-tight text-card-foreground",
|
|
19056
|
+
className
|
|
19057
|
+
),
|
|
19058
|
+
...props
|
|
19059
|
+
}
|
|
19060
|
+
));
|
|
19061
|
+
DialogTitle.displayName = import_radix_ui6.Dialog.Title.displayName;
|
|
19062
|
+
var DialogDescription = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
19063
|
+
import_radix_ui6.Dialog.Description,
|
|
19064
|
+
{
|
|
19065
|
+
ref,
|
|
19066
|
+
className: cn("text-sm text-muted-foreground", className),
|
|
19067
|
+
...props
|
|
19068
|
+
}
|
|
19069
|
+
));
|
|
19070
|
+
DialogDescription.displayName = import_radix_ui6.Dialog.Description.displayName;
|
|
19071
|
+
var DialogClose = import_radix_ui6.Dialog.Close;
|
|
19072
|
+
|
|
19073
|
+
// src/ui/ai-section/AiMediaStripOverlay.tsx
|
|
19074
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
19075
|
+
var PRIMARY3 = "var(--ohw-primary, #0885FE)";
|
|
19076
|
+
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]";
|
|
18917
19077
|
function findMediaStripItemElement(sectionId, index) {
|
|
18918
19078
|
const sectionEl = findByInstanceId(sectionId);
|
|
18919
19079
|
if (!sectionEl) return null;
|
|
@@ -18923,14 +19083,35 @@ function findMediaStripItemElement(sectionId, index) {
|
|
|
18923
19083
|
}
|
|
18924
19084
|
return null;
|
|
18925
19085
|
}
|
|
18926
|
-
function
|
|
18927
|
-
|
|
19086
|
+
function itemRefFromTarget(target) {
|
|
19087
|
+
if (!(target instanceof Element)) return null;
|
|
19088
|
+
if (target.closest(CHROME_SELECTOR)) return null;
|
|
19089
|
+
const itemEl = target.closest("[data-ohw-media-strip-item]");
|
|
19090
|
+
if (!itemEl) return null;
|
|
19091
|
+
const sectionEl = itemEl.closest("[data-ohw-section]");
|
|
19092
|
+
const unit = sectionEl ? movableUnit(sectionEl) : null;
|
|
19093
|
+
const sectionId = unit ? instanceIdOf(unit) || null : null;
|
|
19094
|
+
const index = Number(itemEl.dataset.ohwMediaStripIndex);
|
|
19095
|
+
if (!sectionId || Number.isNaN(index)) return null;
|
|
19096
|
+
return { sectionId, index };
|
|
19097
|
+
}
|
|
19098
|
+
function sameRef(a, b) {
|
|
19099
|
+
return a?.sectionId === b?.sectionId && a?.index === b?.index;
|
|
19100
|
+
}
|
|
19101
|
+
function rectOf(el) {
|
|
18928
19102
|
if (!el) return null;
|
|
18929
19103
|
const r2 = el.getBoundingClientRect();
|
|
18930
19104
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
18931
19105
|
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
18932
19106
|
}
|
|
18933
|
-
function
|
|
19107
|
+
function readRect2(ref) {
|
|
19108
|
+
return rectOf(ref && findMediaStripItemElement(ref.sectionId, ref.index));
|
|
19109
|
+
}
|
|
19110
|
+
function readStripRect(ref) {
|
|
19111
|
+
const item = ref && findMediaStripItemElement(ref.sectionId, ref.index);
|
|
19112
|
+
return rectOf(item?.closest("[data-ohw-media-strip]") ?? item);
|
|
19113
|
+
}
|
|
19114
|
+
function useLiveItemRect(ref, strip = false) {
|
|
18934
19115
|
const [rect, setRect] = (0, import_react10.useState)(null);
|
|
18935
19116
|
(0, import_react10.useEffect)(() => {
|
|
18936
19117
|
if (!ref) {
|
|
@@ -18938,7 +19119,7 @@ function useLiveItemRect(ref) {
|
|
|
18938
19119
|
return;
|
|
18939
19120
|
}
|
|
18940
19121
|
const update = () => {
|
|
18941
|
-
const next = readRect2(ref);
|
|
19122
|
+
const next = strip ? readStripRect(ref) : readRect2(ref);
|
|
18942
19123
|
setRect(
|
|
18943
19124
|
(prev) => prev && next && prev.top === next.top && prev.left === next.left && prev.width === next.width && prev.height === next.height ? prev : next
|
|
18944
19125
|
);
|
|
@@ -18953,9 +19134,49 @@ function useLiveItemRect(ref) {
|
|
|
18953
19134
|
window.removeEventListener("resize", update);
|
|
18954
19135
|
clearInterval(interval);
|
|
18955
19136
|
};
|
|
18956
|
-
}, [ref?.sectionId, ref?.index]);
|
|
19137
|
+
}, [ref?.sectionId, ref?.index, strip]);
|
|
18957
19138
|
return rect;
|
|
18958
19139
|
}
|
|
19140
|
+
var TOOLBAR_STRIP_GAP = 52;
|
|
19141
|
+
var TOOLBAR_STRIP_GAP_MOBILE = 42;
|
|
19142
|
+
var TOOLBAR_EDGE_MARGIN2 = 4;
|
|
19143
|
+
function StripToolbarSlot({ stripRect, children }) {
|
|
19144
|
+
const slotRef = (0, import_react10.useRef)(null);
|
|
19145
|
+
const [shift, setShift] = (0, import_react10.useState)(0);
|
|
19146
|
+
const centerX = stripRect.left + stripRect.width / 2;
|
|
19147
|
+
(0, import_react10.useLayoutEffect)(() => {
|
|
19148
|
+
const slot = slotRef.current;
|
|
19149
|
+
if (!slot) return;
|
|
19150
|
+
const clamp = () => {
|
|
19151
|
+
const w = slot.offsetWidth;
|
|
19152
|
+
if (w <= 0) return;
|
|
19153
|
+
const half = w / 2;
|
|
19154
|
+
const clamped = Math.max(TOOLBAR_EDGE_MARGIN2 + half, Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN2 - half));
|
|
19155
|
+
setShift((prev) => Math.abs(prev - (clamped - centerX)) < 0.5 ? prev : clamped - centerX);
|
|
19156
|
+
};
|
|
19157
|
+
clamp();
|
|
19158
|
+
const ro = new ResizeObserver(clamp);
|
|
19159
|
+
ro.observe(slot);
|
|
19160
|
+
return () => ro.disconnect();
|
|
19161
|
+
}, [centerX, children]);
|
|
19162
|
+
const mobile = window.innerWidth <= 480;
|
|
19163
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19164
|
+
"div",
|
|
19165
|
+
{
|
|
19166
|
+
ref: slotRef,
|
|
19167
|
+
"data-ohw-bridge": "",
|
|
19168
|
+
"data-ohw-item-interaction": "",
|
|
19169
|
+
className: "pointer-events-auto fixed",
|
|
19170
|
+
style: {
|
|
19171
|
+
top: stripRect.top - (mobile ? TOOLBAR_STRIP_GAP_MOBILE : TOOLBAR_STRIP_GAP),
|
|
19172
|
+
left: centerX + shift,
|
|
19173
|
+
transform: "translate(-50%, -100%)",
|
|
19174
|
+
zIndex: 2147483645
|
|
19175
|
+
},
|
|
19176
|
+
children
|
|
19177
|
+
}
|
|
19178
|
+
);
|
|
19179
|
+
}
|
|
18959
19180
|
function requestValidateTree(postToParent2, tree) {
|
|
18960
19181
|
return new Promise((resolve) => {
|
|
18961
19182
|
const id = `ai-validate-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
@@ -18992,221 +19213,177 @@ function requestAssetPick(postToParent2) {
|
|
|
18992
19213
|
postToParent2({ type: "ow:asset-pick", id });
|
|
18993
19214
|
});
|
|
18994
19215
|
}
|
|
18995
|
-
function
|
|
19216
|
+
function ToolbarAction({
|
|
18996
19217
|
label,
|
|
18997
19218
|
onClick,
|
|
18998
|
-
disabled,
|
|
18999
|
-
active
|
|
19219
|
+
disabled = false,
|
|
19220
|
+
active = false,
|
|
19221
|
+
children
|
|
19000
19222
|
}) {
|
|
19001
|
-
|
|
19002
|
-
|
|
19003
|
-
{
|
|
19004
|
-
|
|
19005
|
-
|
|
19006
|
-
disabled,
|
|
19007
|
-
style: {
|
|
19008
|
-
height: 28,
|
|
19009
|
-
padding: "0 10px",
|
|
19010
|
-
display: "inline-flex",
|
|
19011
|
-
alignItems: "center",
|
|
19012
|
-
gap: 4,
|
|
19013
|
-
borderRadius: 999,
|
|
19014
|
-
border: "none",
|
|
19015
|
-
cursor: disabled ? "default" : "pointer",
|
|
19016
|
-
background: active ? OHW_BLUE_DARK : "#ffffff",
|
|
19017
|
-
color: active ? "#ffffff" : OHW_BLUE_DARK,
|
|
19018
|
-
opacity: disabled ? 0.4 : 1,
|
|
19019
|
-
fontSize: 12,
|
|
19020
|
-
lineHeight: "16px",
|
|
19021
|
-
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
19022
|
-
whiteSpace: "nowrap",
|
|
19023
|
-
flex: "0 0 auto"
|
|
19024
|
-
},
|
|
19025
|
-
children: label
|
|
19026
|
-
}
|
|
19027
|
-
);
|
|
19223
|
+
const button = /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(CustomToolbarButton, { type: "button", "aria-label": label, disabled, active, onClick, className: "size-8", children });
|
|
19224
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Tooltip, { children: [
|
|
19225
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "inline-flex", children: button }) : button }),
|
|
19226
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: label })
|
|
19227
|
+
] });
|
|
19028
19228
|
}
|
|
19029
|
-
function
|
|
19030
|
-
|
|
19031
|
-
(0, import_react10.useEffect)(() => setDraft(value), [value]);
|
|
19032
|
-
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
19033
|
-
"div",
|
|
19034
|
-
{
|
|
19035
|
-
style: {
|
|
19036
|
-
display: "flex",
|
|
19037
|
-
alignItems: "center",
|
|
19038
|
-
gap: 6,
|
|
19039
|
-
height: 28,
|
|
19040
|
-
padding: "0 12px",
|
|
19041
|
-
borderRadius: 999,
|
|
19042
|
-
background: "#ffffff",
|
|
19043
|
-
width: "100%",
|
|
19044
|
-
maxWidth: 260,
|
|
19045
|
-
boxSizing: "border-box"
|
|
19046
|
-
},
|
|
19047
|
-
children: [
|
|
19048
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
19049
|
-
"span",
|
|
19050
|
-
{
|
|
19051
|
-
style: {
|
|
19052
|
-
flex: "0 0 auto",
|
|
19053
|
-
color: OHW_BLUE_DARK,
|
|
19054
|
-
fontSize: 10,
|
|
19055
|
-
fontWeight: 700,
|
|
19056
|
-
textTransform: "uppercase",
|
|
19057
|
-
letterSpacing: 0.4
|
|
19058
|
-
},
|
|
19059
|
-
children: "Alt"
|
|
19060
|
-
}
|
|
19061
|
-
),
|
|
19062
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
19063
|
-
"input",
|
|
19064
|
-
{
|
|
19065
|
-
type: "text",
|
|
19066
|
-
value: draft,
|
|
19067
|
-
onChange: (e) => setDraft(e.target.value),
|
|
19068
|
-
onBlur: () => {
|
|
19069
|
-
if (draft !== value) onCommit(draft);
|
|
19070
|
-
},
|
|
19071
|
-
onKeyDown: (e) => {
|
|
19072
|
-
if (e.key === "Enter") e.currentTarget.blur();
|
|
19073
|
-
if (e.key === "Escape") {
|
|
19074
|
-
setDraft(value);
|
|
19075
|
-
e.currentTarget.blur();
|
|
19076
|
-
}
|
|
19077
|
-
},
|
|
19078
|
-
placeholder: "Describe this image",
|
|
19079
|
-
"aria-label": "Image alt text",
|
|
19080
|
-
style: {
|
|
19081
|
-
flex: 1,
|
|
19082
|
-
minWidth: 0,
|
|
19083
|
-
border: "none",
|
|
19084
|
-
outline: "none",
|
|
19085
|
-
background: "transparent",
|
|
19086
|
-
fontSize: 12,
|
|
19087
|
-
lineHeight: "16px",
|
|
19088
|
-
fontFamily: "Figtree, ui-sans-serif, system-ui, sans-serif",
|
|
19089
|
-
color: "#1f2937"
|
|
19090
|
-
}
|
|
19091
|
-
}
|
|
19092
|
-
)
|
|
19093
|
-
]
|
|
19094
|
-
}
|
|
19095
|
-
);
|
|
19229
|
+
function ToolbarSeparator() {
|
|
19230
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { "aria-hidden": true, className: "mx-0.5 block h-6 w-px shrink-0 bg-border" });
|
|
19096
19231
|
}
|
|
19097
|
-
|
|
19098
|
-
|
|
19099
|
-
|
|
19100
|
-
|
|
19101
|
-
|
|
19102
|
-
|
|
19103
|
-
|
|
19104
|
-
|
|
19105
|
-
|
|
19106
|
-
|
|
19107
|
-
|
|
19108
|
-
|
|
19109
|
-
|
|
19110
|
-
|
|
19111
|
-
|
|
19112
|
-
|
|
19113
|
-
|
|
19114
|
-
|
|
19115
|
-
|
|
19116
|
-
|
|
19117
|
-
|
|
19118
|
-
|
|
19119
|
-
|
|
19120
|
-
|
|
19121
|
-
|
|
19122
|
-
|
|
19123
|
-
}, [value]);
|
|
19124
|
-
const commit = () => {
|
|
19125
|
-
const next = draft.trim();
|
|
19126
|
-
if (next === value) return setInvalid(false);
|
|
19127
|
-
if (next && !HTTP_URL_RE.test(next)) return setInvalid(true);
|
|
19128
|
-
setInvalid(false);
|
|
19129
|
-
onCommit(next);
|
|
19130
|
-
};
|
|
19131
|
-
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
19132
|
-
"div",
|
|
19133
|
-
{
|
|
19134
|
-
style: {
|
|
19135
|
-
display: "flex",
|
|
19136
|
-
alignItems: "center",
|
|
19137
|
-
gap: 6,
|
|
19138
|
-
height: 28,
|
|
19139
|
-
padding: "0 12px",
|
|
19140
|
-
borderRadius: 999,
|
|
19141
|
-
background: "#ffffff",
|
|
19142
|
-
width: "100%",
|
|
19143
|
-
maxWidth: 260,
|
|
19144
|
-
boxSizing: "border-box",
|
|
19145
|
-
boxShadow: invalid ? "inset 0 0 0 1.5px #EF4444" : "none"
|
|
19146
|
-
},
|
|
19147
|
-
children: [
|
|
19148
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
19149
|
-
"span",
|
|
19150
|
-
{
|
|
19151
|
-
style: {
|
|
19152
|
-
flex: "0 0 auto",
|
|
19153
|
-
color: OHW_BLUE_DARK,
|
|
19154
|
-
fontSize: 10,
|
|
19155
|
-
fontWeight: 700,
|
|
19156
|
-
textTransform: "uppercase",
|
|
19157
|
-
letterSpacing: 0.4
|
|
19158
|
-
},
|
|
19159
|
-
children: "Link"
|
|
19160
|
-
}
|
|
19161
|
-
),
|
|
19162
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
19163
|
-
"input",
|
|
19232
|
+
function OptionMenu({
|
|
19233
|
+
label,
|
|
19234
|
+
value,
|
|
19235
|
+
options,
|
|
19236
|
+
onChange
|
|
19237
|
+
}) {
|
|
19238
|
+
const current = options.find((o) => o.value === value) ?? options[0];
|
|
19239
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19240
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-xs text-muted-foreground", children: label }),
|
|
19241
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(DropdownMenu, { modal: false, children: [
|
|
19242
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
19243
|
+
"button",
|
|
19244
|
+
{
|
|
19245
|
+
type: "button",
|
|
19246
|
+
"aria-label": label,
|
|
19247
|
+
className: "inline-flex h-8 min-w-[76px] items-center gap-[7px] rounded-[6px] bg-transparent px-2 text-[13px] font-medium text-foreground transition-colors hover:bg-muted data-[state=open]:bg-muted",
|
|
19248
|
+
children: [
|
|
19249
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "flex-1 text-left", children: current.label }),
|
|
19250
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.ChevronDown, { size: 16, style: { pointerEvents: "none" } })
|
|
19251
|
+
]
|
|
19252
|
+
}
|
|
19253
|
+
) }),
|
|
19254
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DropdownMenuContent, { align: "end", sideOffset: 8, className: "w-[132px] min-w-[132px] p-1", children: options.map((option) => {
|
|
19255
|
+
const selected = option.value === value;
|
|
19256
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
19257
|
+
DropdownMenuItem,
|
|
19164
19258
|
{
|
|
19165
|
-
|
|
19166
|
-
|
|
19167
|
-
|
|
19168
|
-
|
|
19169
|
-
|
|
19170
|
-
|
|
19171
|
-
|
|
19172
|
-
|
|
19173
|
-
|
|
19174
|
-
|
|
19175
|
-
|
|
19176
|
-
|
|
19177
|
-
|
|
19178
|
-
|
|
19179
|
-
|
|
19180
|
-
|
|
19181
|
-
|
|
19182
|
-
|
|
19183
|
-
|
|
19184
|
-
|
|
19185
|
-
|
|
19186
|
-
|
|
19187
|
-
|
|
19188
|
-
|
|
19189
|
-
|
|
19190
|
-
|
|
19191
|
-
|
|
19192
|
-
|
|
19193
|
-
|
|
19194
|
-
|
|
19259
|
+
role: "menuitemradio",
|
|
19260
|
+
"aria-checked": selected,
|
|
19261
|
+
onSelect: () => onChange(option.value),
|
|
19262
|
+
className: cn("grid grid-cols-[1fr_16px] gap-2 py-2 pl-2 pr-2 text-[13px]", selected && "bg-muted"),
|
|
19263
|
+
children: [
|
|
19264
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: option.label }),
|
|
19265
|
+
selected && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Check, { size: 16, className: "text-bridge-primary" })
|
|
19266
|
+
]
|
|
19267
|
+
},
|
|
19268
|
+
option.value
|
|
19269
|
+
);
|
|
19270
|
+
}) })
|
|
19271
|
+
] })
|
|
19272
|
+
] });
|
|
19273
|
+
}
|
|
19274
|
+
var VARIANTS = [
|
|
19275
|
+
{ value: "logos", label: "Logos" },
|
|
19276
|
+
{ value: "reel", label: "Reel" }
|
|
19277
|
+
];
|
|
19278
|
+
var ALIGNS = [
|
|
19279
|
+
{ value: "left", label: "Align left", Icon: import_lucide_react9.AlignLeft },
|
|
19280
|
+
{ value: "center", label: "Align center", Icon: import_lucide_react9.AlignCenter },
|
|
19281
|
+
{ value: "right", label: "Align right", Icon: import_lucide_react9.AlignRight }
|
|
19282
|
+
];
|
|
19283
|
+
var HOVERS = [
|
|
19284
|
+
{ value: "none", label: "None" },
|
|
19285
|
+
{ value: "lift", label: "Lift" },
|
|
19286
|
+
{ value: "zoom", label: "Zoom" },
|
|
19287
|
+
{ value: "fade", label: "Fade" }
|
|
19288
|
+
];
|
|
19289
|
+
var HTTP_URL_RE = /^https?:\/\/\S+$/i;
|
|
19290
|
+
function LinkModal({
|
|
19291
|
+
href,
|
|
19292
|
+
linkTarget,
|
|
19293
|
+
onClose,
|
|
19294
|
+
onSave
|
|
19295
|
+
}) {
|
|
19296
|
+
const [draft, setDraft] = (0, import_react10.useState)(href);
|
|
19297
|
+
const [newTab, setNewTab] = (0, import_react10.useState)(linkTarget !== "same-tab");
|
|
19298
|
+
const [invalid, setInvalid] = (0, import_react10.useState)(false);
|
|
19299
|
+
const save = () => {
|
|
19300
|
+
const next = draft.trim();
|
|
19301
|
+
if (next && !HTTP_URL_RE.test(next)) {
|
|
19302
|
+
setInvalid(true);
|
|
19303
|
+
return;
|
|
19195
19304
|
}
|
|
19196
|
-
|
|
19305
|
+
onSave(next, newTab ? "new-tab" : "same-tab");
|
|
19306
|
+
onClose();
|
|
19307
|
+
};
|
|
19308
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Dialog2, { open: true, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(DialogContent, { "data-ohw-link-modal-root": "", className: "max-w-[400px] gap-4 p-5", children: [
|
|
19309
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DialogHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DialogTitle, { className: "text-base", children: "Image link" }) }),
|
|
19310
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-col gap-3", children: [
|
|
19311
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19312
|
+
"input",
|
|
19313
|
+
{
|
|
19314
|
+
autoFocus: true,
|
|
19315
|
+
type: "text",
|
|
19316
|
+
inputMode: "url",
|
|
19317
|
+
value: draft,
|
|
19318
|
+
onChange: (e) => {
|
|
19319
|
+
setDraft(e.target.value);
|
|
19320
|
+
setInvalid(false);
|
|
19321
|
+
},
|
|
19322
|
+
onKeyDown: (e) => {
|
|
19323
|
+
if (e.key === "Enter") save();
|
|
19324
|
+
},
|
|
19325
|
+
placeholder: "https://example.com",
|
|
19326
|
+
"aria-label": "Image link URL",
|
|
19327
|
+
"aria-invalid": invalid,
|
|
19328
|
+
className: cn(
|
|
19329
|
+
"h-9 w-full rounded-[6px] border border-border bg-background px-3 text-[13px] text-foreground outline-none placeholder:text-muted-foreground/70 focus:border-bridge-primary",
|
|
19330
|
+
invalid && "border-destructive focus:border-destructive"
|
|
19331
|
+
)
|
|
19332
|
+
}
|
|
19333
|
+
),
|
|
19334
|
+
invalid && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-xs text-destructive", children: "Enter a full URL starting with http:// or https://" }),
|
|
19335
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex items-center gap-2 text-[13px] text-foreground", children: [
|
|
19336
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("input", { type: "checkbox", checked: newTab, onChange: (e) => setNewTab(e.target.checked) }),
|
|
19337
|
+
"Open in new tab"
|
|
19338
|
+
] })
|
|
19339
|
+
] }),
|
|
19340
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(DialogFooter, { children: [
|
|
19341
|
+
href && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19342
|
+
"button",
|
|
19343
|
+
{
|
|
19344
|
+
type: "button",
|
|
19345
|
+
onClick: () => {
|
|
19346
|
+
onSave("", "new-tab");
|
|
19347
|
+
onClose();
|
|
19348
|
+
},
|
|
19349
|
+
className: "mr-auto rounded-[6px] px-3 py-2 text-[13px] font-medium text-destructive transition-colors hover:bg-muted",
|
|
19350
|
+
children: "Remove link"
|
|
19351
|
+
}
|
|
19352
|
+
),
|
|
19353
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19354
|
+
"button",
|
|
19355
|
+
{
|
|
19356
|
+
type: "button",
|
|
19357
|
+
onClick: onClose,
|
|
19358
|
+
className: "rounded-[6px] px-3 py-2 text-[13px] font-medium text-foreground transition-colors hover:bg-muted",
|
|
19359
|
+
children: "Cancel"
|
|
19360
|
+
}
|
|
19361
|
+
),
|
|
19362
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19363
|
+
"button",
|
|
19364
|
+
{
|
|
19365
|
+
type: "button",
|
|
19366
|
+
onClick: save,
|
|
19367
|
+
className: "rounded-[6px] bg-bridge-primary px-3 py-2 text-[13px] font-medium text-primary-foreground transition-opacity hover:opacity-90",
|
|
19368
|
+
children: "Save"
|
|
19369
|
+
}
|
|
19370
|
+
)
|
|
19371
|
+
] })
|
|
19372
|
+
] }) });
|
|
19197
19373
|
}
|
|
19198
19374
|
function MediaStripToolbar({
|
|
19199
19375
|
entry,
|
|
19200
19376
|
index,
|
|
19201
19377
|
pending,
|
|
19202
19378
|
error,
|
|
19379
|
+
itemEditOn,
|
|
19380
|
+
onToggleItemEdit,
|
|
19203
19381
|
onSetVariant,
|
|
19204
19382
|
onSetAlign,
|
|
19205
19383
|
onSetHover,
|
|
19206
19384
|
onSetTreatment,
|
|
19207
19385
|
onResize,
|
|
19208
|
-
|
|
19209
|
-
onSetLink,
|
|
19386
|
+
onOpenLink,
|
|
19210
19387
|
onAddItem,
|
|
19211
19388
|
onRemoveItem,
|
|
19212
19389
|
onChangeImage,
|
|
@@ -19215,81 +19392,102 @@ function MediaStripToolbar({
|
|
|
19215
19392
|
}) {
|
|
19216
19393
|
const items = mediaStripItems(entry.tree);
|
|
19217
19394
|
const itemCount = items.length;
|
|
19218
|
-
const currentAlt = items[index]?.alt ?? "";
|
|
19219
|
-
const currentHref = items[index]?.href ?? "";
|
|
19220
|
-
const currentTarget = items[index]?.linkTarget === "same-tab" ? "same-tab" : "new-tab";
|
|
19221
19395
|
const slots = findMediaStripSlots(entry.tree);
|
|
19222
19396
|
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
19223
19397
|
const align = slots?.align === "left" || slots?.align === "right" ? slots.align : "center";
|
|
19224
19398
|
const hover = slots?.hover === "none" || slots?.hover === "lift" || slots?.hover === "zoom" || slots?.hover === "fade" ? slots.hover : "lift";
|
|
19225
19399
|
const treatment = slots?.treatment === "color" || slots?.treatment === "grayscale" ? slots.treatment : variant === "logos" ? "grayscale" : "color";
|
|
19226
19400
|
const sizeValue = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
19227
|
-
const
|
|
19228
|
-
const
|
|
19229
|
-
|
|
19230
|
-
gap: 6,
|
|
19231
|
-
flexWrap: "nowrap",
|
|
19232
|
-
justifyContent: "center",
|
|
19233
|
-
overflowX: "auto",
|
|
19234
|
-
WebkitOverflowScrolling: "touch",
|
|
19235
|
-
width: "100%",
|
|
19236
|
-
scrollbarWidth: "none"
|
|
19237
|
-
} : { display: "flex", gap: 6, flexWrap: "nowrap", justifyContent: "center" };
|
|
19238
|
-
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
19401
|
+
const mobile = window.innerWidth <= 480;
|
|
19402
|
+
const gatedLabel = (label) => itemEditOn ? label : "Turn on the star to edit this image";
|
|
19403
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
19239
19404
|
"div",
|
|
19240
19405
|
{
|
|
19241
19406
|
"data-ohw-bridge": "",
|
|
19242
19407
|
"data-ohw-toolbar": "",
|
|
19243
19408
|
onMouseDown: (e) => e.stopPropagation(),
|
|
19244
|
-
|
|
19245
|
-
|
|
19246
|
-
flexDirection: "column",
|
|
19247
|
-
gap: 6,
|
|
19248
|
-
alignItems: "center",
|
|
19249
|
-
background: OHW_BLUE,
|
|
19250
|
-
padding: 8,
|
|
19251
|
-
borderRadius: 12,
|
|
19252
|
-
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
19253
|
-
pointerEvents: pending ? "none" : "auto",
|
|
19254
|
-
opacity: pending ? 0.6 : 1,
|
|
19255
|
-
maxWidth: isMobile ? "calc(100vw - 24px)" : "none"
|
|
19256
|
-
},
|
|
19409
|
+
className: cn("flex flex-col items-center gap-1.5 font-sans", pending && "pointer-events-none opacity-60"),
|
|
19410
|
+
style: { maxWidth: mobile ? "calc(100vw - 24px)" : void 0 },
|
|
19257
19411
|
children: [
|
|
19258
|
-
/* @__PURE__ */ (0,
|
|
19259
|
-
|
|
19260
|
-
|
|
19261
|
-
|
|
19262
|
-
|
|
19263
|
-
|
|
19264
|
-
|
|
19265
|
-
|
|
19266
|
-
|
|
19267
|
-
|
|
19268
|
-
|
|
19269
|
-
|
|
19270
|
-
|
|
19271
|
-
|
|
19272
|
-
|
|
19273
|
-
|
|
19274
|
-
|
|
19275
|
-
|
|
19276
|
-
|
|
19277
|
-
|
|
19278
|
-
|
|
19279
|
-
|
|
19280
|
-
|
|
19281
|
-
|
|
19282
|
-
|
|
19283
|
-
|
|
19284
|
-
|
|
19285
|
-
|
|
19286
|
-
|
|
19287
|
-
|
|
19288
|
-
|
|
19289
|
-
|
|
19412
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
19413
|
+
"div",
|
|
19414
|
+
{
|
|
19415
|
+
className: cn(
|
|
19416
|
+
"flex items-center gap-1 rounded-[10px] border border-border bg-background p-1 whitespace-nowrap",
|
|
19417
|
+
"shadow-[0px_10px_15px_-3px_rgba(0,0,0,0.1),0px_4px_6px_-4px_rgba(0,0,0,0.1)]",
|
|
19418
|
+
mobile ? "flex-wrap justify-center" : "flex-nowrap"
|
|
19419
|
+
),
|
|
19420
|
+
children: [
|
|
19421
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Tooltip, { children: [
|
|
19422
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19423
|
+
CustomToolbarButton,
|
|
19424
|
+
{
|
|
19425
|
+
type: "button",
|
|
19426
|
+
"aria-label": itemEditOn ? "Done editing this image" : "Edit this image",
|
|
19427
|
+
"aria-pressed": itemEditOn,
|
|
19428
|
+
onClick: onToggleItemEdit,
|
|
19429
|
+
className: "group size-8",
|
|
19430
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19431
|
+
import_lucide_react9.Star,
|
|
19432
|
+
{
|
|
19433
|
+
size: 16,
|
|
19434
|
+
fill: "currentColor",
|
|
19435
|
+
strokeWidth: 0,
|
|
19436
|
+
className: cn(
|
|
19437
|
+
"transition-colors",
|
|
19438
|
+
itemEditOn ? "text-[#f59e0b] group-hover:text-[#d97706]" : "text-[#d6d3d1] group-hover:text-[#fbbf24]"
|
|
19439
|
+
),
|
|
19440
|
+
style: { pointerEvents: "none" }
|
|
19441
|
+
}
|
|
19442
|
+
)
|
|
19443
|
+
}
|
|
19444
|
+
) }),
|
|
19445
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: itemEditOn ? "Done editing this image" : "Edit this image" })
|
|
19446
|
+
] }),
|
|
19447
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19448
|
+
/* @__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" } }) }),
|
|
19449
|
+
/* @__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" } }) }),
|
|
19450
|
+
/* @__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" } }) }),
|
|
19451
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19452
|
+
ToolbarAction,
|
|
19453
|
+
{
|
|
19454
|
+
label: gatedLabel("Move right"),
|
|
19455
|
+
onClick: onMoveRight,
|
|
19456
|
+
disabled: !itemEditOn || index >= itemCount - 1,
|
|
19457
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.ArrowRight, { size: 16, style: { pointerEvents: "none" } })
|
|
19458
|
+
}
|
|
19459
|
+
),
|
|
19460
|
+
/* @__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" } }) }),
|
|
19461
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19462
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(OptionMenu, { label: "Layout", value: variant, options: VARIANTS, onChange: onSetVariant }),
|
|
19463
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(OptionMenu, { label: "Hover", value: hover, options: HOVERS, onChange: onSetHover }),
|
|
19464
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19465
|
+
ToolbarAction,
|
|
19466
|
+
{
|
|
19467
|
+
label: treatment === "grayscale" ? "Show in color" : "Show grayscale",
|
|
19468
|
+
active: treatment === "grayscale",
|
|
19469
|
+
onClick: () => onSetTreatment(treatment === "grayscale" ? "color" : "grayscale"),
|
|
19470
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.Palette, { size: 16, style: { pointerEvents: "none" } })
|
|
19471
|
+
}
|
|
19472
|
+
),
|
|
19473
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19474
|
+
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)),
|
|
19475
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19476
|
+
/* @__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" } }) }),
|
|
19477
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "min-w-[40px] text-center text-xs tabular-nums text-muted-foreground", children: [
|
|
19478
|
+
sizeValue,
|
|
19479
|
+
"px"
|
|
19480
|
+
] }),
|
|
19481
|
+
/* @__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" } }) }),
|
|
19482
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ToolbarSeparator, {}),
|
|
19483
|
+
/* @__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" } }) })
|
|
19484
|
+
]
|
|
19485
|
+
}
|
|
19486
|
+
),
|
|
19487
|
+
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 })
|
|
19290
19488
|
]
|
|
19291
19489
|
}
|
|
19292
|
-
);
|
|
19490
|
+
) });
|
|
19293
19491
|
}
|
|
19294
19492
|
function findMediaStripSlots(tree) {
|
|
19295
19493
|
const stack = tree.rows.flatMap((row) => row.blocks);
|
|
@@ -19308,31 +19506,23 @@ function AiMediaStripOverlay({
|
|
|
19308
19506
|
}) {
|
|
19309
19507
|
const [hover, setHover] = (0, import_react10.useState)(null);
|
|
19310
19508
|
const [active, setActive] = (0, import_react10.useState)(null);
|
|
19509
|
+
const [itemEditOn, setItemEditOn] = (0, import_react10.useState)(false);
|
|
19510
|
+
const [linkOpen, setLinkOpen] = (0, import_react10.useState)(false);
|
|
19311
19511
|
const [pending, setPending] = (0, import_react10.useState)(false);
|
|
19312
19512
|
const [error, setError] = (0, import_react10.useState)(null);
|
|
19313
19513
|
const activeRef = (0, import_react10.useRef)(null);
|
|
19314
19514
|
activeRef.current = active;
|
|
19515
|
+
const linkOpenRef = (0, import_react10.useRef)(false);
|
|
19516
|
+
linkOpenRef.current = linkOpen;
|
|
19315
19517
|
(0, import_react10.useEffect)(() => {
|
|
19316
19518
|
const onMove = (e) => {
|
|
19519
|
+
const ref = itemRefFromTarget(e.target);
|
|
19317
19520
|
const t = e.target;
|
|
19318
|
-
|
|
19319
|
-
|
|
19320
|
-
|
|
19321
|
-
|
|
19322
|
-
|
|
19323
|
-
if (!itemEl) {
|
|
19324
|
-
setHover(null);
|
|
19325
|
-
return;
|
|
19326
|
-
}
|
|
19327
|
-
const sectionEl = itemEl.closest("[data-ohw-section]");
|
|
19328
|
-
const unit = sectionEl ? movableUnit(sectionEl) : null;
|
|
19329
|
-
const sectionId = unit ? instanceIdOf(unit) || null : null;
|
|
19330
|
-
const index = Number(itemEl.dataset.ohwMediaStripIndex);
|
|
19331
|
-
if (!sectionId || Number.isNaN(index)) {
|
|
19332
|
-
setHover(null);
|
|
19333
|
-
return;
|
|
19334
|
-
}
|
|
19335
|
-
setHover({ sectionId, index });
|
|
19521
|
+
const overEditable = Boolean(t?.closest?.("[data-ohw-editable]"));
|
|
19522
|
+
setHover((prev) => {
|
|
19523
|
+
const next = ref && !overEditable ? ref : null;
|
|
19524
|
+
return sameRef(prev, next) ? prev : next;
|
|
19525
|
+
});
|
|
19336
19526
|
};
|
|
19337
19527
|
const onLeave = () => setHover(null);
|
|
19338
19528
|
document.addEventListener("mousemove", onMove, { passive: true });
|
|
@@ -19344,23 +19534,25 @@ function AiMediaStripOverlay({
|
|
|
19344
19534
|
}, []);
|
|
19345
19535
|
(0, import_react10.useEffect)(() => {
|
|
19346
19536
|
const onClick = (e) => {
|
|
19347
|
-
const current = activeRef.current;
|
|
19348
|
-
if (!current) return;
|
|
19349
19537
|
const t = e.target;
|
|
19350
|
-
if (!(t instanceof
|
|
19351
|
-
if (t.closest(
|
|
19352
|
-
const
|
|
19353
|
-
if (
|
|
19354
|
-
|
|
19538
|
+
if (!(t instanceof Element)) return;
|
|
19539
|
+
if (t.closest(CHROME_SELECTOR)) return;
|
|
19540
|
+
const ref = itemRefFromTarget(t);
|
|
19541
|
+
if (sameRef(activeRef.current, ref)) return;
|
|
19542
|
+
if (ref) clearInteractionChromeRef.current();
|
|
19543
|
+
setItemEditOn(false);
|
|
19355
19544
|
setError(null);
|
|
19545
|
+
setActive(ref);
|
|
19356
19546
|
};
|
|
19357
19547
|
document.addEventListener("click", onClick, true);
|
|
19358
19548
|
return () => document.removeEventListener("click", onClick, true);
|
|
19359
|
-
}, []);
|
|
19549
|
+
}, [clearInteractionChromeRef]);
|
|
19360
19550
|
(0, import_react10.useEffect)(() => {
|
|
19361
19551
|
const onBlur = () => {
|
|
19362
19552
|
if (!activeRef.current) return;
|
|
19363
19553
|
setActive(null);
|
|
19554
|
+
setItemEditOn(false);
|
|
19555
|
+
setLinkOpen(false);
|
|
19364
19556
|
setError(null);
|
|
19365
19557
|
};
|
|
19366
19558
|
window.addEventListener("blur", onBlur);
|
|
@@ -19370,7 +19562,10 @@ function AiMediaStripOverlay({
|
|
|
19370
19562
|
const onKeyDown = (e) => {
|
|
19371
19563
|
if (e.key !== "Escape") return;
|
|
19372
19564
|
if (!activeRef.current) return;
|
|
19565
|
+
if (linkOpenRef.current) return;
|
|
19566
|
+
if (document.querySelector('[data-ohw-more-menu][data-state="open"]')) return;
|
|
19373
19567
|
setActive(null);
|
|
19568
|
+
setItemEditOn(false);
|
|
19374
19569
|
setError(null);
|
|
19375
19570
|
};
|
|
19376
19571
|
document.addEventListener("keydown", onKeyDown);
|
|
@@ -19404,137 +19599,133 @@ function AiMediaStripOverlay({
|
|
|
19404
19599
|
tree: nextTree,
|
|
19405
19600
|
label: entry.label,
|
|
19406
19601
|
media: extraMedia ? { ...entry.media, ...extraMedia } : entry.media,
|
|
19407
|
-
...entry.brand ? { brand: entry.brand } : {}
|
|
19602
|
+
...entry.brand ? { brand: entry.brand } : {},
|
|
19603
|
+
// The user is already looking at the strip they just edited — recentering the viewport
|
|
19604
|
+
// on every edit reads as the section jumping around.
|
|
19605
|
+
skipScrollIntoView: true
|
|
19408
19606
|
});
|
|
19409
19607
|
return true;
|
|
19410
19608
|
},
|
|
19411
19609
|
[findEntry, postToParent2, applyTreeLocalRef]
|
|
19412
19610
|
);
|
|
19413
19611
|
const activeEntry = active ? findEntry(active.sectionId) : null;
|
|
19414
|
-
const hoverHandleRect = useLiveItemRect(!active && hover ? hover : null);
|
|
19415
19612
|
const activeItemRect = useLiveItemRect(active);
|
|
19416
|
-
const
|
|
19417
|
-
const
|
|
19418
|
-
|
|
19419
|
-
|
|
19420
|
-
|
|
19421
|
-
|
|
19422
|
-
|
|
19423
|
-
|
|
19424
|
-
|
|
19425
|
-
|
|
19426
|
-
|
|
19427
|
-
|
|
19428
|
-
|
|
19429
|
-
|
|
19430
|
-
|
|
19431
|
-
|
|
19432
|
-
|
|
19433
|
-
|
|
19434
|
-
|
|
19435
|
-
|
|
19436
|
-
|
|
19437
|
-
|
|
19438
|
-
|
|
19439
|
-
|
|
19440
|
-
|
|
19441
|
-
|
|
19442
|
-
|
|
19443
|
-
|
|
19444
|
-
|
|
19445
|
-
|
|
19446
|
-
|
|
19447
|
-
|
|
19448
|
-
|
|
19449
|
-
|
|
19450
|
-
activeItemRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
19451
|
-
ItemInteractionLayer,
|
|
19452
|
-
{
|
|
19453
|
-
rect: activeItemRect,
|
|
19454
|
-
state: toolbarState,
|
|
19455
|
-
toolbar: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
19456
|
-
MediaStripToolbar,
|
|
19457
|
-
{
|
|
19458
|
-
entry: activeEntry,
|
|
19459
|
-
index: active.index,
|
|
19460
|
-
pending,
|
|
19461
|
-
error,
|
|
19462
|
-
onSetVariant: (variant) => runMutation(active.sectionId, (tree) => setMediaStripVariant(tree, variant)),
|
|
19463
|
-
onSetAlign: (align) => runMutation(active.sectionId, (tree) => setMediaStripAlign(tree, align)),
|
|
19464
|
-
onSetHover: (hoverPreset) => runMutation(active.sectionId, (tree) => setMediaStripHover(tree, hoverPreset)),
|
|
19465
|
-
onSetTreatment: (treatment) => runMutation(active.sectionId, (tree) => setMediaStripTreatment(tree, treatment)),
|
|
19466
|
-
onResize: (delta) => {
|
|
19467
|
-
const slots = findMediaStripSlots(activeEntry.tree);
|
|
19468
|
-
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
19469
|
-
const current = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
19470
|
-
void runMutation(active.sectionId, (tree) => setMediaStripSizing(tree, current + delta));
|
|
19471
|
-
},
|
|
19472
|
-
onSetAlt: (alt) => {
|
|
19473
|
-
void runMutation(active.sectionId, (tree) => setMediaStripItemAlt(tree, active.index, alt));
|
|
19474
|
-
},
|
|
19475
|
-
onSetLink: (href, linkTarget) => {
|
|
19613
|
+
const activeStripRect = useLiveItemRect(active, true);
|
|
19614
|
+
const hoverRect = useLiveItemRect(hover && !sameRef(hover, active) ? hover : null);
|
|
19615
|
+
const activeItems = activeEntry ? mediaStripItems(activeEntry.tree) : [];
|
|
19616
|
+
const activeItem = active ? activeItems[active.index] : void 0;
|
|
19617
|
+
const activeHref = activeItem?.href ?? "";
|
|
19618
|
+
const activeTarget = activeItem?.linkTarget === "same-tab" ? "same-tab" : "new-tab";
|
|
19619
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
19620
|
+
hoverRect && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ItemInteractionLayer, { rect: hoverRect, state: "hover" }),
|
|
19621
|
+
activeItemRect && activeStripRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
19622
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ItemInteractionLayer, { rect: activeItemRect, state: "active-top" }),
|
|
19623
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StripToolbarSlot, { stripRect: activeStripRect, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19624
|
+
MediaStripToolbar,
|
|
19625
|
+
{
|
|
19626
|
+
entry: activeEntry,
|
|
19627
|
+
index: active.index,
|
|
19628
|
+
pending,
|
|
19629
|
+
error,
|
|
19630
|
+
itemEditOn,
|
|
19631
|
+
onToggleItemEdit: () => setItemEditOn((on) => !on),
|
|
19632
|
+
onSetVariant: (variant) => runMutation(active.sectionId, (tree) => setMediaStripVariant(tree, variant)),
|
|
19633
|
+
onSetAlign: (align) => runMutation(active.sectionId, (tree) => setMediaStripAlign(tree, align)),
|
|
19634
|
+
onSetHover: (hoverPreset) => runMutation(active.sectionId, (tree) => setMediaStripHover(tree, hoverPreset)),
|
|
19635
|
+
onSetTreatment: (treatment) => runMutation(active.sectionId, (tree) => setMediaStripTreatment(tree, treatment)),
|
|
19636
|
+
onResize: (delta) => {
|
|
19637
|
+
const slots = findMediaStripSlots(activeEntry.tree);
|
|
19638
|
+
const variant = slots?.variant === "reel" ? "reel" : "logos";
|
|
19639
|
+
const current = variant === "logos" ? typeof slots?.logoMaxHeight === "number" ? slots.logoMaxHeight : 48 : typeof slots?.cardWidth === "number" ? slots.cardWidth : 240;
|
|
19640
|
+
void runMutation(active.sectionId, (tree) => setMediaStripSizing(tree, current + delta));
|
|
19641
|
+
},
|
|
19642
|
+
onOpenLink: () => setLinkOpen(true),
|
|
19643
|
+
onAddItem: () => {
|
|
19644
|
+
void requestAssetPick(postToParent2).then((picked) => {
|
|
19645
|
+
if (!picked) return;
|
|
19646
|
+
const item = { assetId: picked.assetId, alt: "Logo" };
|
|
19476
19647
|
void runMutation(
|
|
19477
19648
|
active.sectionId,
|
|
19478
|
-
(tree) =>
|
|
19479
|
-
|
|
19480
|
-
|
|
19481
|
-
|
|
19482
|
-
void requestAssetPick(postToParent2).then((picked) => {
|
|
19483
|
-
if (!picked) return;
|
|
19484
|
-
const item = { assetId: picked.assetId, alt: "Logo" };
|
|
19485
|
-
void runMutation(
|
|
19486
|
-
active.sectionId,
|
|
19487
|
-
(tree) => addMediaStripItem(tree, item, active.index),
|
|
19488
|
-
{ [picked.assetId]: picked.url }
|
|
19489
|
-
).then((applied) => {
|
|
19490
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19491
|
-
});
|
|
19649
|
+
(tree) => addMediaStripItem(tree, item, active.index),
|
|
19650
|
+
{ [picked.assetId]: picked.url }
|
|
19651
|
+
).then((applied) => {
|
|
19652
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19492
19653
|
});
|
|
19493
|
-
}
|
|
19494
|
-
|
|
19495
|
-
|
|
19496
|
-
|
|
19497
|
-
|
|
19498
|
-
|
|
19499
|
-
|
|
19500
|
-
|
|
19501
|
-
|
|
19502
|
-
});
|
|
19503
|
-
},
|
|
19504
|
-
onRemoveItem: () => {
|
|
19505
|
-
void runMutation(active.sectionId, (tree) => removeMediaStripItem(tree, active.index)).then(
|
|
19506
|
-
(applied) => {
|
|
19507
|
-
if (applied) setActive(null);
|
|
19508
|
-
}
|
|
19509
|
-
);
|
|
19510
|
-
},
|
|
19511
|
-
onMoveLeft: () => {
|
|
19512
|
-
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, -1)).then(
|
|
19513
|
-
(applied) => {
|
|
19514
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index - 1 });
|
|
19515
|
-
}
|
|
19516
|
-
);
|
|
19517
|
-
},
|
|
19518
|
-
onMoveRight: () => {
|
|
19519
|
-
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, 1)).then(
|
|
19520
|
-
(applied) => {
|
|
19521
|
-
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19522
|
-
}
|
|
19654
|
+
});
|
|
19655
|
+
},
|
|
19656
|
+
onChangeImage: () => {
|
|
19657
|
+
void requestAssetPick(postToParent2).then((picked) => {
|
|
19658
|
+
if (!picked) return;
|
|
19659
|
+
void runMutation(
|
|
19660
|
+
active.sectionId,
|
|
19661
|
+
(tree) => setMediaStripItemAsset(tree, active.index, picked.assetId),
|
|
19662
|
+
{ [picked.assetId]: picked.url }
|
|
19523
19663
|
);
|
|
19524
|
-
}
|
|
19664
|
+
});
|
|
19665
|
+
},
|
|
19666
|
+
onRemoveItem: () => {
|
|
19667
|
+
void runMutation(active.sectionId, (tree) => removeMediaStripItem(tree, active.index)).then(
|
|
19668
|
+
(applied) => {
|
|
19669
|
+
if (applied) setActive(null);
|
|
19670
|
+
}
|
|
19671
|
+
);
|
|
19672
|
+
},
|
|
19673
|
+
onMoveLeft: () => {
|
|
19674
|
+
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, -1)).then(
|
|
19675
|
+
(applied) => {
|
|
19676
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index - 1 });
|
|
19677
|
+
}
|
|
19678
|
+
);
|
|
19679
|
+
},
|
|
19680
|
+
onMoveRight: () => {
|
|
19681
|
+
void runMutation(active.sectionId, (tree) => reorderMediaStripItem(tree, active.index, 1)).then(
|
|
19682
|
+
(applied) => {
|
|
19683
|
+
if (applied) setActive({ sectionId: active.sectionId, index: active.index + 1 });
|
|
19684
|
+
}
|
|
19685
|
+
);
|
|
19525
19686
|
}
|
|
19526
|
-
|
|
19527
|
-
}
|
|
19528
|
-
|
|
19687
|
+
}
|
|
19688
|
+
) }),
|
|
19689
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19690
|
+
"div",
|
|
19691
|
+
{
|
|
19692
|
+
"data-ohw-bridge": "",
|
|
19693
|
+
"data-ohw-item-interaction": "",
|
|
19694
|
+
"aria-hidden": true,
|
|
19695
|
+
className: "pointer-events-none fixed rounded-[4px] px-[7px] py-[3px] font-sans text-[11px] font-medium leading-none text-primary-foreground whitespace-nowrap",
|
|
19696
|
+
style: {
|
|
19697
|
+
top: activeItemRect.top + activeItemRect.height + 10,
|
|
19698
|
+
left: activeItemRect.left - 5,
|
|
19699
|
+
background: PRIMARY3,
|
|
19700
|
+
zIndex: 2147483644
|
|
19701
|
+
},
|
|
19702
|
+
children: "Media item"
|
|
19703
|
+
}
|
|
19704
|
+
),
|
|
19705
|
+
linkOpen && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
19706
|
+
LinkModal,
|
|
19707
|
+
{
|
|
19708
|
+
href: activeHref,
|
|
19709
|
+
linkTarget: activeTarget,
|
|
19710
|
+
onClose: () => setLinkOpen(false),
|
|
19711
|
+
onSave: (href, linkTarget) => {
|
|
19712
|
+
void runMutation(
|
|
19713
|
+
active.sectionId,
|
|
19714
|
+
(tree) => setMediaStripItemLink(tree, active.index, href ? { href, linkTarget } : {})
|
|
19715
|
+
);
|
|
19716
|
+
}
|
|
19717
|
+
}
|
|
19718
|
+
)
|
|
19719
|
+
] })
|
|
19529
19720
|
] });
|
|
19530
19721
|
}
|
|
19531
19722
|
|
|
19532
19723
|
// src/ui/ai-section/AiPricingCardOverlay.tsx
|
|
19533
19724
|
var import_react11 = require("react");
|
|
19534
|
-
var
|
|
19535
|
-
var
|
|
19725
|
+
var import_lucide_react10 = require("lucide-react");
|
|
19726
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
19536
19727
|
var PRIMARY4 = "var(--ohw-primary, #0885FE)";
|
|
19537
|
-
var
|
|
19728
|
+
var CHROME_SELECTOR2 = "[data-ohw-toolbar], [data-ohw-edit-chrome], [data-ohw-item-interaction], [data-ohw-link-modal-root], [data-ohw-section-picker], [data-ohw-ai-review], [data-ohw-more-menu]";
|
|
19538
19729
|
function findPricingCardElement(sectionId, index) {
|
|
19539
19730
|
const sectionEl = findByInstanceId(sectionId);
|
|
19540
19731
|
if (!sectionEl) return null;
|
|
@@ -19546,7 +19737,7 @@ function findPricingCardElement(sectionId, index) {
|
|
|
19546
19737
|
}
|
|
19547
19738
|
function cardRefFromTarget(target) {
|
|
19548
19739
|
if (!(target instanceof Element)) return null;
|
|
19549
|
-
if (target.closest(
|
|
19740
|
+
if (target.closest(CHROME_SELECTOR2)) return null;
|
|
19550
19741
|
const cardEl = target.closest("[data-ohw-pricing-card]");
|
|
19551
19742
|
if (!cardEl) return null;
|
|
19552
19743
|
const sectionEl = cardEl.closest("[data-ohw-section]");
|
|
@@ -19556,21 +19747,21 @@ function cardRefFromTarget(target) {
|
|
|
19556
19747
|
if (!sectionId || Number.isNaN(index)) return null;
|
|
19557
19748
|
return { sectionId, index };
|
|
19558
19749
|
}
|
|
19559
|
-
function
|
|
19750
|
+
function sameRef2(a, b) {
|
|
19560
19751
|
return a?.sectionId === b?.sectionId && a?.index === b?.index;
|
|
19561
19752
|
}
|
|
19562
|
-
function
|
|
19753
|
+
function rectOf2(el) {
|
|
19563
19754
|
if (!el) return null;
|
|
19564
19755
|
const r2 = el.getBoundingClientRect();
|
|
19565
19756
|
if (r2.width <= 0 || r2.height <= 0) return null;
|
|
19566
19757
|
return { top: r2.top, left: r2.left, width: r2.width, height: r2.height };
|
|
19567
19758
|
}
|
|
19568
19759
|
function readRect3(ref) {
|
|
19569
|
-
return
|
|
19760
|
+
return rectOf2(ref && findPricingCardElement(ref.sectionId, ref.index));
|
|
19570
19761
|
}
|
|
19571
19762
|
function readGridRect(ref) {
|
|
19572
19763
|
const card = ref && findPricingCardElement(ref.sectionId, ref.index);
|
|
19573
|
-
return
|
|
19764
|
+
return rectOf2(card?.closest("[data-ohw-pricing-collection]") ?? card);
|
|
19574
19765
|
}
|
|
19575
19766
|
function useLiveCardRect(ref, grid = false) {
|
|
19576
19767
|
const [rect, setRect] = (0, import_react11.useState)(null);
|
|
@@ -19600,7 +19791,7 @@ function useLiveCardRect(ref, grid = false) {
|
|
|
19600
19791
|
}
|
|
19601
19792
|
var TOOLBAR_GRID_GAP = 52;
|
|
19602
19793
|
var TOOLBAR_GRID_GAP_MOBILE = 42;
|
|
19603
|
-
var
|
|
19794
|
+
var TOOLBAR_EDGE_MARGIN3 = 4;
|
|
19604
19795
|
function GridToolbarSlot({ gridRect, children }) {
|
|
19605
19796
|
const slotRef = (0, import_react11.useRef)(null);
|
|
19606
19797
|
const [shift, setShift] = (0, import_react11.useState)(0);
|
|
@@ -19612,7 +19803,7 @@ function GridToolbarSlot({ gridRect, children }) {
|
|
|
19612
19803
|
const w = slot.offsetWidth;
|
|
19613
19804
|
if (w <= 0) return;
|
|
19614
19805
|
const half = w / 2;
|
|
19615
|
-
const clamped = Math.max(
|
|
19806
|
+
const clamped = Math.max(TOOLBAR_EDGE_MARGIN3 + half, Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN3 - half));
|
|
19616
19807
|
setShift((prev) => Math.abs(prev - (clamped - centerX)) < 0.5 ? prev : clamped - centerX);
|
|
19617
19808
|
};
|
|
19618
19809
|
clamp();
|
|
@@ -19621,7 +19812,7 @@ function GridToolbarSlot({ gridRect, children }) {
|
|
|
19621
19812
|
return () => ro.disconnect();
|
|
19622
19813
|
}, [centerX, children]);
|
|
19623
19814
|
const mobile = window.innerWidth <= 480;
|
|
19624
|
-
return /* @__PURE__ */ (0,
|
|
19815
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19625
19816
|
"div",
|
|
19626
19817
|
{
|
|
19627
19818
|
ref: slotRef,
|
|
@@ -19656,7 +19847,7 @@ function requestValidateTree2(postToParent2, tree) {
|
|
|
19656
19847
|
});
|
|
19657
19848
|
}
|
|
19658
19849
|
function StyleSwatch({ style }) {
|
|
19659
|
-
return /* @__PURE__ */ (0,
|
|
19850
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19660
19851
|
"span",
|
|
19661
19852
|
{
|
|
19662
19853
|
"aria-hidden": true,
|
|
@@ -19670,35 +19861,35 @@ function StyleSwatch({ style }) {
|
|
|
19670
19861
|
);
|
|
19671
19862
|
}
|
|
19672
19863
|
function ButtonGlyph() {
|
|
19673
|
-
return /* @__PURE__ */ (0,
|
|
19674
|
-
/* @__PURE__ */ (0,
|
|
19675
|
-
/* @__PURE__ */ (0,
|
|
19864
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("svg", { width: "18", height: "12", viewBox: "0 0 18 12", fill: "none", "aria-hidden": true, style: { pointerEvents: "none" }, children: [
|
|
19865
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("rect", { x: "0.75", y: "0.75", width: "16.5", height: "10.5", rx: "3", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
19866
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M5.5 6H12.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
|
|
19676
19867
|
] });
|
|
19677
19868
|
}
|
|
19678
19869
|
function FeatureGlyph({ mode }) {
|
|
19679
|
-
return /* @__PURE__ */ (0,
|
|
19680
|
-
/* @__PURE__ */ (0,
|
|
19681
|
-
/* @__PURE__ */ (0,
|
|
19682
|
-
/* @__PURE__ */ (0,
|
|
19683
|
-
/* @__PURE__ */ (0,
|
|
19684
|
-
/* @__PURE__ */ (0,
|
|
19685
|
-
mode === "add" && /* @__PURE__ */ (0,
|
|
19870
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "none", "aria-hidden": true, style: { pointerEvents: "none" }, children: [
|
|
19871
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("circle", { cx: "8", cy: "8", r: "7.25", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
19872
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M5 8.2L7.2 10.3L11 6", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
19873
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("circle", { cx: "13.5", cy: "13.5", r: "4.25", fill: "var(--ohw-background, #ffffff)", stroke: "var(--ohw-background, #ffffff)", strokeWidth: "1" }),
|
|
19874
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("circle", { cx: "13.5", cy: "13.5", r: "3.75", fill: "var(--ohw-background, #ffffff)", stroke: PRIMARY4, strokeWidth: "1" }),
|
|
19875
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M11.5 13.5H15.5", stroke: PRIMARY4, strokeWidth: "1.5", strokeLinecap: "round" }),
|
|
19876
|
+
mode === "add" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M13.5 11.5V15.5", stroke: PRIMARY4, strokeWidth: "1.5", strokeLinecap: "round" })
|
|
19686
19877
|
] });
|
|
19687
19878
|
}
|
|
19688
|
-
function
|
|
19879
|
+
function ToolbarAction2({
|
|
19689
19880
|
label,
|
|
19690
19881
|
onClick,
|
|
19691
19882
|
disabled = false,
|
|
19692
19883
|
children
|
|
19693
19884
|
}) {
|
|
19694
|
-
const button = /* @__PURE__ */ (0,
|
|
19695
|
-
return /* @__PURE__ */ (0,
|
|
19696
|
-
/* @__PURE__ */ (0,
|
|
19697
|
-
/* @__PURE__ */ (0,
|
|
19885
|
+
const button = /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CustomToolbarButton, { type: "button", "aria-label": label, disabled, onClick, className: "size-8", children });
|
|
19886
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Tooltip, { children: [
|
|
19887
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipTrigger, { asChild: true, children: disabled ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "inline-flex", children: button }) : button }),
|
|
19888
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: label })
|
|
19698
19889
|
] });
|
|
19699
19890
|
}
|
|
19700
|
-
function
|
|
19701
|
-
return /* @__PURE__ */ (0,
|
|
19891
|
+
function ToolbarSeparator2() {
|
|
19892
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { "aria-hidden": true, className: "mx-0.5 block h-6 w-px shrink-0 bg-border" });
|
|
19702
19893
|
}
|
|
19703
19894
|
function CardStyleMenu({
|
|
19704
19895
|
value,
|
|
@@ -19706,7 +19897,7 @@ function CardStyleMenu({
|
|
|
19706
19897
|
disabled = false
|
|
19707
19898
|
}) {
|
|
19708
19899
|
const current = PRICING_CARD_STYLES.find((s) => s.value === value) ?? PRICING_CARD_STYLES[0];
|
|
19709
|
-
const trigger = /* @__PURE__ */ (0,
|
|
19900
|
+
const trigger = /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
19710
19901
|
"button",
|
|
19711
19902
|
{
|
|
19712
19903
|
type: "button",
|
|
@@ -19717,28 +19908,28 @@ function CardStyleMenu({
|
|
|
19717
19908
|
disabled && "cursor-not-allowed opacity-40 hover:bg-transparent"
|
|
19718
19909
|
),
|
|
19719
19910
|
children: [
|
|
19720
|
-
/* @__PURE__ */ (0,
|
|
19721
|
-
/* @__PURE__ */ (0,
|
|
19722
|
-
/* @__PURE__ */ (0,
|
|
19911
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(StyleSwatch, { style: current.value }),
|
|
19912
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "flex-1 text-left", children: current.label }),
|
|
19913
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.ChevronDown, { size: 16, style: { pointerEvents: "none" } })
|
|
19723
19914
|
]
|
|
19724
19915
|
}
|
|
19725
19916
|
);
|
|
19726
19917
|
if (disabled) {
|
|
19727
|
-
return /* @__PURE__ */ (0,
|
|
19728
|
-
/* @__PURE__ */ (0,
|
|
19729
|
-
/* @__PURE__ */ (0,
|
|
19730
|
-
/* @__PURE__ */ (0,
|
|
19731
|
-
/* @__PURE__ */ (0,
|
|
19918
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19919
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-xs text-muted-foreground opacity-50", children: "Card style" }),
|
|
19920
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Tooltip, { children: [
|
|
19921
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "inline-flex", children: trigger }) }),
|
|
19922
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: "Mark as featured to edit card style" })
|
|
19732
19923
|
] })
|
|
19733
19924
|
] });
|
|
19734
19925
|
}
|
|
19735
|
-
return /* @__PURE__ */ (0,
|
|
19736
|
-
/* @__PURE__ */ (0,
|
|
19737
|
-
/* @__PURE__ */ (0,
|
|
19738
|
-
/* @__PURE__ */ (0,
|
|
19739
|
-
/* @__PURE__ */ (0,
|
|
19926
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-1.5 pl-1.5", children: [
|
|
19927
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-xs text-muted-foreground", children: "Card style" }),
|
|
19928
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(DropdownMenu, { modal: false, children: [
|
|
19929
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DropdownMenuTrigger, { asChild: true, children: trigger }),
|
|
19930
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DropdownMenuContent, { align: "end", sideOffset: 8, className: "w-[152px] min-w-[152px] p-1", children: PRICING_CARD_STYLES.map((style) => {
|
|
19740
19931
|
const selected = style.value === value;
|
|
19741
|
-
return /* @__PURE__ */ (0,
|
|
19932
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
19742
19933
|
DropdownMenuItem,
|
|
19743
19934
|
{
|
|
19744
19935
|
role: "menuitemradio",
|
|
@@ -19746,9 +19937,9 @@ function CardStyleMenu({
|
|
|
19746
19937
|
onSelect: () => onChange(style.value),
|
|
19747
19938
|
className: cn("grid grid-cols-[18px_1fr_16px] gap-2 py-2 pl-2 pr-2 text-[13px]", selected && "bg-muted"),
|
|
19748
19939
|
children: [
|
|
19749
|
-
/* @__PURE__ */ (0,
|
|
19750
|
-
/* @__PURE__ */ (0,
|
|
19751
|
-
selected && /* @__PURE__ */ (0,
|
|
19940
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(StyleSwatch, { style: style.value }),
|
|
19941
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { children: style.label }),
|
|
19942
|
+
selected && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Check, { size: 16, className: "text-bridge-primary" })
|
|
19752
19943
|
]
|
|
19753
19944
|
},
|
|
19754
19945
|
style.value
|
|
@@ -19778,7 +19969,7 @@ function PricingCardToolbar({
|
|
|
19778
19969
|
const style = pricingCardStyle(entry.tree, index);
|
|
19779
19970
|
const featuredTag = pricingCardFeaturedTag(entry.tree, index);
|
|
19780
19971
|
const mobile = window.innerWidth <= 480;
|
|
19781
|
-
return /* @__PURE__ */ (0,
|
|
19972
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
19782
19973
|
"div",
|
|
19783
19974
|
{
|
|
19784
19975
|
"data-ohw-bridge": "",
|
|
@@ -19790,7 +19981,7 @@ function PricingCardToolbar({
|
|
|
19790
19981
|
),
|
|
19791
19982
|
style: { maxWidth: mobile ? "calc(100vw - 24px)" : void 0 },
|
|
19792
19983
|
children: [
|
|
19793
|
-
/* @__PURE__ */ (0,
|
|
19984
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
19794
19985
|
"div",
|
|
19795
19986
|
{
|
|
19796
19987
|
className: cn(
|
|
@@ -19799,8 +19990,8 @@ function PricingCardToolbar({
|
|
|
19799
19990
|
mobile ? "flex-wrap justify-center" : "flex-nowrap"
|
|
19800
19991
|
),
|
|
19801
19992
|
children: [
|
|
19802
|
-
/* @__PURE__ */ (0,
|
|
19803
|
-
/* @__PURE__ */ (0,
|
|
19993
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Tooltip, { children: [
|
|
19994
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19804
19995
|
CustomToolbarButton,
|
|
19805
19996
|
{
|
|
19806
19997
|
type: "button",
|
|
@@ -19808,8 +19999,8 @@ function PricingCardToolbar({
|
|
|
19808
19999
|
"aria-pressed": featuredTag,
|
|
19809
20000
|
onClick: () => onSetFeaturedTag(!featuredTag),
|
|
19810
20001
|
className: "group size-8",
|
|
19811
|
-
children: /* @__PURE__ */ (0,
|
|
19812
|
-
|
|
20002
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
20003
|
+
import_lucide_react10.Star,
|
|
19813
20004
|
{
|
|
19814
20005
|
size: 16,
|
|
19815
20006
|
fill: "currentColor",
|
|
@@ -19823,25 +20014,25 @@ function PricingCardToolbar({
|
|
|
19823
20014
|
)
|
|
19824
20015
|
}
|
|
19825
20016
|
) }),
|
|
19826
|
-
/* @__PURE__ */ (0,
|
|
20017
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipContent, { side: "bottom", sideOffset: 8, children: featuredTag ? "Unmark featured" : "Mark as featured" })
|
|
19827
20018
|
] }),
|
|
19828
|
-
/* @__PURE__ */ (0,
|
|
19829
|
-
/* @__PURE__ */ (0,
|
|
19830
|
-
/* @__PURE__ */ (0,
|
|
19831
|
-
/* @__PURE__ */ (0,
|
|
19832
|
-
/* @__PURE__ */ (0,
|
|
19833
|
-
/* @__PURE__ */ (0,
|
|
19834
|
-
/* @__PURE__ */ (0,
|
|
20019
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarSeparator2, {}),
|
|
20020
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CardStyleMenu, { value: style, onChange: onSetStyle, disabled: !featuredTag }),
|
|
20021
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarSeparator2, {}),
|
|
20022
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarAction2, { label: "Add button", onClick: onAddButton, disabled: buttonCount >= 2, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ButtonGlyph, {}) }),
|
|
20023
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarAction2, { label: "Remove button", onClick: onRemoveButton, disabled: buttonCount === 0, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { className: "relative inline-flex", children: [
|
|
20024
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ButtonGlyph, {}),
|
|
20025
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Minus, { size: 10, strokeWidth: 2.5, className: "absolute -right-1.5 -top-1.5 rounded-full bg-background text-bridge-primary" })
|
|
19835
20026
|
] }) }),
|
|
19836
|
-
/* @__PURE__ */ (0,
|
|
19837
|
-
/* @__PURE__ */ (0,
|
|
19838
|
-
/* @__PURE__ */ (0,
|
|
19839
|
-
/* @__PURE__ */ (0,
|
|
19840
|
-
/* @__PURE__ */ (0,
|
|
20027
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarAction2, { label: "Add feature", onClick: onAddFeature, disabled: featureCount >= 10, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(FeatureGlyph, { mode: "add" }) }),
|
|
20028
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarAction2, { label: "Remove feature", onClick: onRemoveFeature, disabled: featureCount <= 1, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(FeatureGlyph, { mode: "remove" }) }),
|
|
20029
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarSeparator2, {}),
|
|
20030
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarAction2, { label: "Add tier", onClick: onAddTier, disabled: collectionCount >= 4, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Plus, { size: 16, style: { pointerEvents: "none" } }) }),
|
|
20031
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ToolbarAction2, { label: "Remove tier", onClick: onRemoveTier, disabled: collectionCount <= 1, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Minus, { size: 16, style: { pointerEvents: "none" } }) })
|
|
19841
20032
|
]
|
|
19842
20033
|
}
|
|
19843
20034
|
),
|
|
19844
|
-
error && /* @__PURE__ */ (0,
|
|
20035
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "max-w-[260px] rounded-md bg-background px-2 py-1 text-center text-[11px] text-destructive shadow-sm", children: error })
|
|
19845
20036
|
]
|
|
19846
20037
|
}
|
|
19847
20038
|
) });
|
|
@@ -19875,7 +20066,7 @@ function AiPricingCardOverlay({
|
|
|
19875
20066
|
const overEditable = Boolean(t?.closest?.("[data-ohw-editable], [data-ohw-role], a, button"));
|
|
19876
20067
|
setHover((prev) => {
|
|
19877
20068
|
const next = ref && !overEditable ? ref : null;
|
|
19878
|
-
return
|
|
20069
|
+
return sameRef2(prev, next) ? prev : next;
|
|
19879
20070
|
});
|
|
19880
20071
|
};
|
|
19881
20072
|
const onLeave = () => setHover(null);
|
|
@@ -19890,10 +20081,10 @@ function AiPricingCardOverlay({
|
|
|
19890
20081
|
const onClick = (e) => {
|
|
19891
20082
|
const t = e.target;
|
|
19892
20083
|
if (!(t instanceof Element)) return;
|
|
19893
|
-
if (t.closest(
|
|
20084
|
+
if (t.closest(CHROME_SELECTOR2)) return;
|
|
19894
20085
|
const ref = cardRefFromTarget(t);
|
|
19895
|
-
setActive((prev) =>
|
|
19896
|
-
if (!ref || !
|
|
20086
|
+
setActive((prev) => sameRef2(prev, ref) ? prev : ref);
|
|
20087
|
+
if (!ref || !sameRef2(activeRef.current, ref)) setError(null);
|
|
19897
20088
|
};
|
|
19898
20089
|
document.addEventListener("click", onClick, true);
|
|
19899
20090
|
return () => document.removeEventListener("click", onClick, true);
|
|
@@ -19958,12 +20149,12 @@ function AiPricingCardOverlay({
|
|
|
19958
20149
|
const activeEntry = active ? findEntry(active.sectionId) : null;
|
|
19959
20150
|
const activeCardRect = useLiveCardRect(active);
|
|
19960
20151
|
const activeGridRect = useLiveCardRect(active, true);
|
|
19961
|
-
const hoverRect = useLiveCardRect(hover && !
|
|
19962
|
-
return /* @__PURE__ */ (0,
|
|
19963
|
-
hoverRect && /* @__PURE__ */ (0,
|
|
19964
|
-
activeCardRect && activeGridRect && active && activeEntry && /* @__PURE__ */ (0,
|
|
19965
|
-
/* @__PURE__ */ (0,
|
|
19966
|
-
/* @__PURE__ */ (0,
|
|
20152
|
+
const hoverRect = useLiveCardRect(hover && !sameRef2(hover, active) ? hover : null);
|
|
20153
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
20154
|
+
hoverRect && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ItemInteractionLayer, { rect: hoverRect, state: "hover" }),
|
|
20155
|
+
activeCardRect && activeGridRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
20156
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ItemInteractionLayer, { rect: activeCardRect, state: "active-top" }),
|
|
20157
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(GridToolbarSlot, { gridRect: activeGridRect, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19967
20158
|
PricingCardToolbar,
|
|
19968
20159
|
{
|
|
19969
20160
|
entry: activeEntry,
|
|
@@ -19991,7 +20182,7 @@ function AiPricingCardOverlay({
|
|
|
19991
20182
|
onRemoveFeature: () => runMutation(active.sectionId, (tree) => removePricingCardFeature(tree, active.index))
|
|
19992
20183
|
}
|
|
19993
20184
|
) }),
|
|
19994
|
-
/* @__PURE__ */ (0,
|
|
20185
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
19995
20186
|
"div",
|
|
19996
20187
|
{
|
|
19997
20188
|
"data-ohw-bridge": "",
|
|
@@ -20013,7 +20204,7 @@ function AiPricingCardOverlay({
|
|
|
20013
20204
|
|
|
20014
20205
|
// src/ui/ai-section/AiVideoOverlay.tsx
|
|
20015
20206
|
var import_react12 = require("react");
|
|
20016
|
-
var
|
|
20207
|
+
var import_lucide_react11 = require("lucide-react");
|
|
20017
20208
|
|
|
20018
20209
|
// src/lib/ai-video-tree.ts
|
|
20019
20210
|
function resolveVideoBlock(tree, path) {
|
|
@@ -20084,10 +20275,10 @@ function extractYouTubeId(input) {
|
|
|
20084
20275
|
}
|
|
20085
20276
|
|
|
20086
20277
|
// src/ui/ai-section/AiVideoOverlay.tsx
|
|
20087
|
-
var
|
|
20278
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
20088
20279
|
var PRIMARY5 = "#0885FE";
|
|
20089
|
-
var
|
|
20090
|
-
var
|
|
20280
|
+
var OHW_BLUE = `var(--ohw-primary, ${PRIMARY5})`;
|
|
20281
|
+
var OHW_BLUE_DARK = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY5}) 60%, #000000)`;
|
|
20091
20282
|
function findVideoBlockElement(sectionId, path) {
|
|
20092
20283
|
const sectionEl = findByInstanceId(sectionId);
|
|
20093
20284
|
if (!sectionEl) return null;
|
|
@@ -20147,12 +20338,12 @@ function requestValidateTree3(postToParent2, tree) {
|
|
|
20147
20338
|
postToParent2({ type: "ow:ai-validate-tree-request", id, tree });
|
|
20148
20339
|
});
|
|
20149
20340
|
}
|
|
20150
|
-
function
|
|
20341
|
+
function Pill({
|
|
20151
20342
|
label,
|
|
20152
20343
|
onClick,
|
|
20153
20344
|
disabled
|
|
20154
20345
|
}) {
|
|
20155
|
-
return /* @__PURE__ */ (0,
|
|
20346
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20156
20347
|
"button",
|
|
20157
20348
|
{
|
|
20158
20349
|
type: "button",
|
|
@@ -20168,7 +20359,7 @@ function Pill2({
|
|
|
20168
20359
|
border: "none",
|
|
20169
20360
|
cursor: disabled ? "default" : "pointer",
|
|
20170
20361
|
background: "#ffffff",
|
|
20171
|
-
color:
|
|
20362
|
+
color: OHW_BLUE_DARK,
|
|
20172
20363
|
opacity: disabled ? 0.4 : 1,
|
|
20173
20364
|
fontSize: 12,
|
|
20174
20365
|
lineHeight: "16px",
|
|
@@ -20190,7 +20381,7 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20190
20381
|
setDraft(value ? watchUrl(value) : "");
|
|
20191
20382
|
setInvalid(false);
|
|
20192
20383
|
}, [value]);
|
|
20193
|
-
const
|
|
20384
|
+
const commit2 = () => {
|
|
20194
20385
|
const next = draft.trim();
|
|
20195
20386
|
if (!next) {
|
|
20196
20387
|
setInvalid(false);
|
|
@@ -20211,8 +20402,8 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20211
20402
|
onCommit(id);
|
|
20212
20403
|
}
|
|
20213
20404
|
};
|
|
20214
|
-
return /* @__PURE__ */ (0,
|
|
20215
|
-
/* @__PURE__ */ (0,
|
|
20405
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 4, width: "100%", maxWidth: 280 }, children: [
|
|
20406
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
20216
20407
|
"div",
|
|
20217
20408
|
{
|
|
20218
20409
|
style: {
|
|
@@ -20228,12 +20419,12 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20228
20419
|
boxShadow: invalid ? "inset 0 0 0 1.5px #EF4444" : "none"
|
|
20229
20420
|
},
|
|
20230
20421
|
children: [
|
|
20231
|
-
/* @__PURE__ */ (0,
|
|
20422
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20232
20423
|
"span",
|
|
20233
20424
|
{
|
|
20234
20425
|
style: {
|
|
20235
20426
|
flex: "0 0 auto",
|
|
20236
|
-
color:
|
|
20427
|
+
color: OHW_BLUE_DARK,
|
|
20237
20428
|
fontSize: 10,
|
|
20238
20429
|
lineHeight: "16px",
|
|
20239
20430
|
fontWeight: 700,
|
|
@@ -20243,14 +20434,14 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20243
20434
|
children: "Video"
|
|
20244
20435
|
}
|
|
20245
20436
|
),
|
|
20246
|
-
/* @__PURE__ */ (0,
|
|
20437
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20247
20438
|
"input",
|
|
20248
20439
|
{
|
|
20249
20440
|
type: "text",
|
|
20250
20441
|
inputMode: "url",
|
|
20251
20442
|
value: draft,
|
|
20252
20443
|
onChange: (e) => handleChange(e.target.value),
|
|
20253
|
-
onBlur:
|
|
20444
|
+
onBlur: commit2,
|
|
20254
20445
|
onKeyDown: (e) => {
|
|
20255
20446
|
if (e.key === "Enter") e.currentTarget.blur();
|
|
20256
20447
|
if (e.key === "Escape") {
|
|
@@ -20280,7 +20471,7 @@ function VideoUrlInput({ value, onCommit }) {
|
|
|
20280
20471
|
]
|
|
20281
20472
|
}
|
|
20282
20473
|
),
|
|
20283
|
-
invalid && /* @__PURE__ */ (0,
|
|
20474
|
+
invalid && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { color: "#FCA5A5", fontSize: 11, textAlign: "center" }, children: "That doesn't look like a YouTube link \u2014 try pasting the video URL again." })
|
|
20284
20475
|
] });
|
|
20285
20476
|
}
|
|
20286
20477
|
function VideoToolbar({
|
|
@@ -20290,7 +20481,7 @@ function VideoToolbar({
|
|
|
20290
20481
|
onSetVideoId,
|
|
20291
20482
|
onRemove
|
|
20292
20483
|
}) {
|
|
20293
|
-
return /* @__PURE__ */ (0,
|
|
20484
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
20294
20485
|
"div",
|
|
20295
20486
|
{
|
|
20296
20487
|
"data-ohw-bridge": "",
|
|
@@ -20302,7 +20493,7 @@ function VideoToolbar({
|
|
|
20302
20493
|
gap: 6,
|
|
20303
20494
|
alignItems: "center",
|
|
20304
20495
|
width: 280,
|
|
20305
|
-
background:
|
|
20496
|
+
background: OHW_BLUE,
|
|
20306
20497
|
padding: 8,
|
|
20307
20498
|
borderRadius: 12,
|
|
20308
20499
|
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
@@ -20310,9 +20501,9 @@ function VideoToolbar({
|
|
|
20310
20501
|
opacity: pending ? 0.6 : 1
|
|
20311
20502
|
},
|
|
20312
20503
|
children: [
|
|
20313
|
-
/* @__PURE__ */ (0,
|
|
20314
|
-
/* @__PURE__ */ (0,
|
|
20315
|
-
error && /* @__PURE__ */ (0,
|
|
20504
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(VideoUrlInput, { value: videoId, onCommit: onSetVideoId }),
|
|
20505
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Pill, { label: "Remove video", onClick: onRemove, disabled: !videoId }),
|
|
20506
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { style: { color: "#FCA5A5", fontSize: 11, maxWidth: 220, textAlign: "center" }, children: error })
|
|
20316
20507
|
]
|
|
20317
20508
|
}
|
|
20318
20509
|
);
|
|
@@ -20432,8 +20623,8 @@ function AiVideoOverlay({
|
|
|
20432
20623
|
const activeBlockRect = useLiveBlockRect(active);
|
|
20433
20624
|
const TOOLBAR_APPROX_H = 90;
|
|
20434
20625
|
const toolbarState = activeBlockRect && activeBlockRect.top < TOOLBAR_APPROX_H ? "active-bottom" : "active-top";
|
|
20435
|
-
return /* @__PURE__ */ (0,
|
|
20436
|
-
hoverHandleRect && hover && /* @__PURE__ */ (0,
|
|
20626
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
20627
|
+
hoverHandleRect && hover && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20437
20628
|
"button",
|
|
20438
20629
|
{
|
|
20439
20630
|
type: "button",
|
|
@@ -20461,15 +20652,15 @@ function AiVideoOverlay({
|
|
|
20461
20652
|
fontSize: 14,
|
|
20462
20653
|
fontWeight: 700
|
|
20463
20654
|
},
|
|
20464
|
-
children: /* @__PURE__ */ (0,
|
|
20655
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.Star, { size: 14, style: { pointerEvents: "none" } })
|
|
20465
20656
|
}
|
|
20466
20657
|
),
|
|
20467
|
-
activeBlockRect && active && activeEntry && /* @__PURE__ */ (0,
|
|
20658
|
+
activeBlockRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20468
20659
|
ItemInteractionLayer,
|
|
20469
20660
|
{
|
|
20470
20661
|
rect: activeBlockRect,
|
|
20471
20662
|
state: toolbarState,
|
|
20472
|
-
toolbar: /* @__PURE__ */ (0,
|
|
20663
|
+
toolbar: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
20473
20664
|
VideoToolbar,
|
|
20474
20665
|
{
|
|
20475
20666
|
videoId: videoIdAt(activeEntry.tree, active.path),
|
|
@@ -20493,7 +20684,7 @@ function AiVideoOverlay({
|
|
|
20493
20684
|
|
|
20494
20685
|
// src/ui/ai-section/AiFadeCarouselOverlay.tsx
|
|
20495
20686
|
var import_react13 = require("react");
|
|
20496
|
-
var
|
|
20687
|
+
var import_lucide_react12 = require("lucide-react");
|
|
20497
20688
|
|
|
20498
20689
|
// src/lib/ai-carousel-tree.ts
|
|
20499
20690
|
function isCarouselBlock(node) {
|
|
@@ -20544,10 +20735,10 @@ function setCarouselAutoplay(tree, on) {
|
|
|
20544
20735
|
}
|
|
20545
20736
|
|
|
20546
20737
|
// src/ui/ai-section/AiFadeCarouselOverlay.tsx
|
|
20547
|
-
var
|
|
20738
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
20548
20739
|
var PRIMARY6 = "#0885FE";
|
|
20549
|
-
var
|
|
20550
|
-
var
|
|
20740
|
+
var OHW_BLUE2 = `var(--ohw-primary, ${PRIMARY6})`;
|
|
20741
|
+
var OHW_BLUE_DARK2 = `color-mix(in srgb, var(--ohw-primary, ${PRIMARY6}) 60%, #000000)`;
|
|
20551
20742
|
function findCarouselItemElement(sectionId, index) {
|
|
20552
20743
|
const sectionEl = findByInstanceId(sectionId);
|
|
20553
20744
|
if (!sectionEl) return null;
|
|
@@ -20626,8 +20817,8 @@ function requestAssetPick2(postToParent2) {
|
|
|
20626
20817
|
postToParent2({ type: "ow:asset-pick", id });
|
|
20627
20818
|
});
|
|
20628
20819
|
}
|
|
20629
|
-
function
|
|
20630
|
-
return /* @__PURE__ */ (0,
|
|
20820
|
+
function Pill2({ label, onClick, disabled }) {
|
|
20821
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20631
20822
|
"button",
|
|
20632
20823
|
{
|
|
20633
20824
|
type: "button",
|
|
@@ -20643,7 +20834,7 @@ function Pill3({ label, onClick, disabled }) {
|
|
|
20643
20834
|
border: "none",
|
|
20644
20835
|
cursor: disabled ? "default" : "pointer",
|
|
20645
20836
|
background: "#ffffff",
|
|
20646
|
-
color:
|
|
20837
|
+
color: OHW_BLUE_DARK2,
|
|
20647
20838
|
opacity: disabled ? 0.4 : 1,
|
|
20648
20839
|
fontSize: 12,
|
|
20649
20840
|
lineHeight: "16px",
|
|
@@ -20661,7 +20852,7 @@ function TogglePill({
|
|
|
20661
20852
|
onToggle,
|
|
20662
20853
|
disabled
|
|
20663
20854
|
}) {
|
|
20664
|
-
return /* @__PURE__ */ (0,
|
|
20855
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
20665
20856
|
"button",
|
|
20666
20857
|
{
|
|
20667
20858
|
type: "button",
|
|
@@ -20680,7 +20871,7 @@ function TogglePill({
|
|
|
20680
20871
|
border: "none",
|
|
20681
20872
|
cursor: disabled ? "default" : "pointer",
|
|
20682
20873
|
background: "#ffffff",
|
|
20683
|
-
color:
|
|
20874
|
+
color: OHW_BLUE_DARK2,
|
|
20684
20875
|
opacity: disabled ? 0.4 : 1,
|
|
20685
20876
|
fontSize: 12,
|
|
20686
20877
|
lineHeight: "16px",
|
|
@@ -20690,7 +20881,7 @@ function TogglePill({
|
|
|
20690
20881
|
},
|
|
20691
20882
|
children: [
|
|
20692
20883
|
label,
|
|
20693
|
-
/* @__PURE__ */ (0,
|
|
20884
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20694
20885
|
"span",
|
|
20695
20886
|
{
|
|
20696
20887
|
"aria-hidden": true,
|
|
@@ -20703,10 +20894,10 @@ function TogglePill({
|
|
|
20703
20894
|
// Off is a grey track, not a washed-out blue: the pill's own white background already
|
|
20704
20895
|
// carries the brand colour in the text, and a pale blue track next to it read as
|
|
20705
20896
|
// "disabled control" rather than "switch that is off".
|
|
20706
|
-
background: on ?
|
|
20897
|
+
background: on ? OHW_BLUE_DARK2 : "#CBD5E1",
|
|
20707
20898
|
transition: "background 120ms ease"
|
|
20708
20899
|
},
|
|
20709
|
-
children: /* @__PURE__ */ (0,
|
|
20900
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20710
20901
|
"span",
|
|
20711
20902
|
{
|
|
20712
20903
|
style: {
|
|
@@ -20735,7 +20926,7 @@ function CarouselSlideToolbar({
|
|
|
20735
20926
|
onChangeImage,
|
|
20736
20927
|
onToggleAutoplay
|
|
20737
20928
|
}) {
|
|
20738
|
-
return /* @__PURE__ */ (0,
|
|
20929
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
20739
20930
|
"div",
|
|
20740
20931
|
{
|
|
20741
20932
|
"data-ohw-bridge": "",
|
|
@@ -20746,7 +20937,7 @@ function CarouselSlideToolbar({
|
|
|
20746
20937
|
flexDirection: "column",
|
|
20747
20938
|
gap: 6,
|
|
20748
20939
|
alignItems: "center",
|
|
20749
|
-
background:
|
|
20940
|
+
background: OHW_BLUE2,
|
|
20750
20941
|
padding: 8,
|
|
20751
20942
|
borderRadius: 12,
|
|
20752
20943
|
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
@@ -20758,11 +20949,11 @@ function CarouselSlideToolbar({
|
|
|
20758
20949
|
pointerEvents: pending ? "none" : "auto"
|
|
20759
20950
|
},
|
|
20760
20951
|
children: [
|
|
20761
|
-
/* @__PURE__ */ (0,
|
|
20762
|
-
/* @__PURE__ */ (0,
|
|
20763
|
-
/* @__PURE__ */ (0,
|
|
20952
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { display: "flex", gap: 6, alignItems: "center" }, children: [
|
|
20953
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Pill2, { label: "Change Image", onClick: onChangeImage }),
|
|
20954
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(TogglePill, { label: "Autoplay", on: autoplay, onToggle: onToggleAutoplay })
|
|
20764
20955
|
] }),
|
|
20765
|
-
error && /* @__PURE__ */ (0,
|
|
20956
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { color: "#FCA5A5", fontSize: 11, maxWidth: 220, textAlign: "center" }, children: error })
|
|
20766
20957
|
]
|
|
20767
20958
|
}
|
|
20768
20959
|
);
|
|
@@ -20902,8 +21093,8 @@ function AiFadeCarouselOverlay({
|
|
|
20902
21093
|
const activeItemRect = useLiveItemRect2(active);
|
|
20903
21094
|
const TOOLBAR_APPROX_H = 90;
|
|
20904
21095
|
const toolbarState = activeItemRect && activeItemRect.top < TOOLBAR_APPROX_H ? "active-bottom" : "active-top";
|
|
20905
|
-
return /* @__PURE__ */ (0,
|
|
20906
|
-
hoverHandleRect && hover && /* @__PURE__ */ (0,
|
|
21096
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
21097
|
+
hoverHandleRect && hover && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20907
21098
|
"button",
|
|
20908
21099
|
{
|
|
20909
21100
|
type: "button",
|
|
@@ -20932,10 +21123,10 @@ function AiFadeCarouselOverlay({
|
|
|
20932
21123
|
fontSize: 14,
|
|
20933
21124
|
fontWeight: 700
|
|
20934
21125
|
},
|
|
20935
|
-
children: /* @__PURE__ */ (0,
|
|
21126
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react12.Star, { size: 14, style: { pointerEvents: "none" } })
|
|
20936
21127
|
}
|
|
20937
21128
|
),
|
|
20938
|
-
swapping && /* @__PURE__ */ (0,
|
|
21129
|
+
swapping && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20939
21130
|
"div",
|
|
20940
21131
|
{
|
|
20941
21132
|
ref: skeletonRef,
|
|
@@ -20953,15 +21144,15 @@ function AiFadeCarouselOverlay({
|
|
|
20953
21144
|
zIndex: 2147483646,
|
|
20954
21145
|
pointerEvents: "none"
|
|
20955
21146
|
},
|
|
20956
|
-
children: /* @__PURE__ */ (0,
|
|
21147
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("style", { children: MEDIA_SKELETON_CSS })
|
|
20957
21148
|
}
|
|
20958
21149
|
),
|
|
20959
|
-
activeItemRect && active && activeEntry && /* @__PURE__ */ (0,
|
|
21150
|
+
activeItemRect && active && activeEntry && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20960
21151
|
ItemInteractionLayer,
|
|
20961
21152
|
{
|
|
20962
21153
|
rect: activeItemRect,
|
|
20963
21154
|
state: toolbarState,
|
|
20964
|
-
toolbar: /* @__PURE__ */ (0,
|
|
21155
|
+
toolbar: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
20965
21156
|
CarouselSlideToolbar,
|
|
20966
21157
|
{
|
|
20967
21158
|
pending,
|
|
@@ -21179,113 +21370,6 @@ function scrollToHashSectionWhenReady(behavior = "smooth") {
|
|
|
21179
21370
|
// src/ui/link-modal/LinkPopover.tsx
|
|
21180
21371
|
var import_react17 = require("react");
|
|
21181
21372
|
|
|
21182
|
-
// src/ui/dialog.tsx
|
|
21183
|
-
var React9 = __toESM(require("react"), 1);
|
|
21184
|
-
var import_radix_ui6 = require("radix-ui");
|
|
21185
|
-
var import_lucide_react12 = require("lucide-react");
|
|
21186
|
-
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
21187
|
-
function Dialog2({
|
|
21188
|
-
...props
|
|
21189
|
-
}) {
|
|
21190
|
-
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_radix_ui6.Dialog.Root, { "data-slot": "dialog", ...props });
|
|
21191
|
-
}
|
|
21192
|
-
function DialogPortal({
|
|
21193
|
-
...props
|
|
21194
|
-
}) {
|
|
21195
|
-
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_radix_ui6.Dialog.Portal, { ...props });
|
|
21196
|
-
}
|
|
21197
|
-
function DialogOverlay({
|
|
21198
|
-
className,
|
|
21199
|
-
...props
|
|
21200
|
-
}) {
|
|
21201
|
-
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
21202
|
-
import_radix_ui6.Dialog.Overlay,
|
|
21203
|
-
{
|
|
21204
|
-
"data-slot": "dialog-overlay",
|
|
21205
|
-
"data-ohw-link-modal-root": "",
|
|
21206
|
-
className: cn("fixed inset-0 z-[2147483646] bg-black/50", className),
|
|
21207
|
-
...props
|
|
21208
|
-
}
|
|
21209
|
-
);
|
|
21210
|
-
}
|
|
21211
|
-
var DialogContent = React9.forwardRef(
|
|
21212
|
-
({ className, children, showCloseButton = true, container, ...props }, ref) => {
|
|
21213
|
-
const positionMode = container ? "absolute" : "fixed";
|
|
21214
|
-
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(DialogPortal, { container: container ?? void 0, children: [
|
|
21215
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
|
|
21216
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
21217
|
-
import_radix_ui6.Dialog.Content,
|
|
21218
|
-
{
|
|
21219
|
-
ref,
|
|
21220
|
-
"data-slot": "dialog-content",
|
|
21221
|
-
className: cn(
|
|
21222
|
-
positionMode,
|
|
21223
|
-
"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",
|
|
21224
|
-
"rounded-xl border border-border bg-background font-sans shadow-lg outline-none",
|
|
21225
|
-
container ? "max-h-[calc(100%-32px)]" : "max-h-[calc(100vh-32px)]",
|
|
21226
|
-
className
|
|
21227
|
-
),
|
|
21228
|
-
onMouseDown: (e) => e.stopPropagation(),
|
|
21229
|
-
...props,
|
|
21230
|
-
children: [
|
|
21231
|
-
children,
|
|
21232
|
-
showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
21233
|
-
import_radix_ui6.Dialog.Close,
|
|
21234
|
-
{
|
|
21235
|
-
type: "button",
|
|
21236
|
-
className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
|
|
21237
|
-
"aria-label": "Close",
|
|
21238
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react12.X, { size: 16, "aria-hidden": true })
|
|
21239
|
-
}
|
|
21240
|
-
) : null
|
|
21241
|
-
]
|
|
21242
|
-
}
|
|
21243
|
-
)
|
|
21244
|
-
] });
|
|
21245
|
-
}
|
|
21246
|
-
);
|
|
21247
|
-
DialogContent.displayName = import_radix_ui6.Dialog.Content.displayName;
|
|
21248
|
-
function DialogHeader({
|
|
21249
|
-
className,
|
|
21250
|
-
...props
|
|
21251
|
-
}) {
|
|
21252
|
-
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
21253
|
-
}
|
|
21254
|
-
function DialogFooter({
|
|
21255
|
-
className,
|
|
21256
|
-
...props
|
|
21257
|
-
}) {
|
|
21258
|
-
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
21259
|
-
"div",
|
|
21260
|
-
{
|
|
21261
|
-
className: cn("flex items-center justify-end gap-2", className),
|
|
21262
|
-
...props
|
|
21263
|
-
}
|
|
21264
|
-
);
|
|
21265
|
-
}
|
|
21266
|
-
var DialogTitle = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
21267
|
-
import_radix_ui6.Dialog.Title,
|
|
21268
|
-
{
|
|
21269
|
-
ref,
|
|
21270
|
-
className: cn(
|
|
21271
|
-
"text-lg font-semibold leading-none tracking-tight text-card-foreground",
|
|
21272
|
-
className
|
|
21273
|
-
),
|
|
21274
|
-
...props
|
|
21275
|
-
}
|
|
21276
|
-
));
|
|
21277
|
-
DialogTitle.displayName = import_radix_ui6.Dialog.Title.displayName;
|
|
21278
|
-
var DialogDescription = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
21279
|
-
import_radix_ui6.Dialog.Description,
|
|
21280
|
-
{
|
|
21281
|
-
ref,
|
|
21282
|
-
className: cn("text-sm text-muted-foreground", className),
|
|
21283
|
-
...props
|
|
21284
|
-
}
|
|
21285
|
-
));
|
|
21286
|
-
DialogDescription.displayName = import_radix_ui6.Dialog.Description.displayName;
|
|
21287
|
-
var DialogClose = import_radix_ui6.Dialog.Close;
|
|
21288
|
-
|
|
21289
21373
|
// src/ui/link-modal/LinkEditorPanel.tsx
|
|
21290
21374
|
var import_lucide_react16 = require("lucide-react");
|
|
21291
21375
|
|
|
@@ -22389,6 +22473,7 @@ function shouldUseDevFixtures() {
|
|
|
22389
22473
|
function getLogoElement(el) {
|
|
22390
22474
|
const marked = el.closest('[data-ohw-role="logo"], [data-ohw-logo]');
|
|
22391
22475
|
if (marked) return marked;
|
|
22476
|
+
if (el.closest('[data-ohw-editable="icon"]')) return null;
|
|
22392
22477
|
const root = el.closest("nav, [data-ohw-nav-root], footer");
|
|
22393
22478
|
if (!root) return null;
|
|
22394
22479
|
const anchor = el.closest("a");
|
|
@@ -24083,6 +24168,102 @@ function deleteSelectedNavFooterItem(deps) {
|
|
|
24083
24168
|
return false;
|
|
24084
24169
|
}
|
|
24085
24170
|
|
|
24171
|
+
// src/lib/nav-page-sync.ts
|
|
24172
|
+
function labelKeyFor(hrefKey) {
|
|
24173
|
+
return hrefKey.replace(/-href$/, "-label");
|
|
24174
|
+
}
|
|
24175
|
+
function isPageLinkKey(key) {
|
|
24176
|
+
return isNavbarHrefKey(key) || isFooterHrefKey(key);
|
|
24177
|
+
}
|
|
24178
|
+
function currentHref(key, anchor, content) {
|
|
24179
|
+
const stored = content[key];
|
|
24180
|
+
if (typeof stored === "string" && stored.length > 0) return stored;
|
|
24181
|
+
return anchor.getAttribute("href") ?? "";
|
|
24182
|
+
}
|
|
24183
|
+
function normalizePath2(value) {
|
|
24184
|
+
if (value.length > 1 && value.endsWith("/")) return value.slice(0, -1);
|
|
24185
|
+
return value;
|
|
24186
|
+
}
|
|
24187
|
+
function pointsAt(href, path) {
|
|
24188
|
+
const normalized = normalizePath2(href);
|
|
24189
|
+
const target = normalizePath2(path);
|
|
24190
|
+
if (normalized === target) return true;
|
|
24191
|
+
return (normalized.startsWith(`${target}#`) || normalized.startsWith(`${target}?`)) && target !== "/";
|
|
24192
|
+
}
|
|
24193
|
+
function retargetHref(href, oldPath, newPath) {
|
|
24194
|
+
const normalized = normalizePath2(href);
|
|
24195
|
+
const target = normalizePath2(oldPath);
|
|
24196
|
+
if (normalized === target) return newPath;
|
|
24197
|
+
return `${newPath}${normalized.slice(target.length)}`;
|
|
24198
|
+
}
|
|
24199
|
+
function setLabelText(key, text) {
|
|
24200
|
+
document.querySelectorAll(`[data-ohw-key="${CSS.escape(key)}"]`).forEach((el) => {
|
|
24201
|
+
el.textContent = text;
|
|
24202
|
+
});
|
|
24203
|
+
}
|
|
24204
|
+
function commit(delta, deps) {
|
|
24205
|
+
if (Object.keys(delta).length === 0) return;
|
|
24206
|
+
deps.setEditContent({ ...deps.getEditContent(), ...delta });
|
|
24207
|
+
deps.postToParent({
|
|
24208
|
+
type: "ow:change",
|
|
24209
|
+
nodes: Object.entries(delta).map(([key, text]) => ({ key, text }))
|
|
24210
|
+
});
|
|
24211
|
+
}
|
|
24212
|
+
function navLinksTo(path, content) {
|
|
24213
|
+
return Array.from(document.querySelectorAll("[data-ohw-href-key]")).filter((anchor) => {
|
|
24214
|
+
const key = anchor.getAttribute("data-ohw-href-key");
|
|
24215
|
+
return isNavbarHrefKey(key) && pointsAt(currentHref(key, anchor, content), path);
|
|
24216
|
+
}).map((anchor) => anchor.getAttribute("data-ohw-href-key"));
|
|
24217
|
+
}
|
|
24218
|
+
function addNavLinkForPage(page, deps) {
|
|
24219
|
+
const content = deps.getEditContent();
|
|
24220
|
+
if (navLinksTo(page.path, content).length > 0) return false;
|
|
24221
|
+
const roots = listNavbarRootItems();
|
|
24222
|
+
const afterAnchor = roots[roots.length - 1] ?? null;
|
|
24223
|
+
let inserted;
|
|
24224
|
+
try {
|
|
24225
|
+
inserted = insertNavbarItem(page.path, page.title, afterAnchor);
|
|
24226
|
+
} catch {
|
|
24227
|
+
return false;
|
|
24228
|
+
}
|
|
24229
|
+
const { hrefKey, labelKey, index } = inserted;
|
|
24230
|
+
deps.applyLinkByKey(hrefKey, page.path);
|
|
24231
|
+
setLabelText(labelKey, page.title);
|
|
24232
|
+
commit(
|
|
24233
|
+
{
|
|
24234
|
+
[hrefKey]: page.path,
|
|
24235
|
+
[labelKey]: page.title,
|
|
24236
|
+
[NAV_COUNT_KEY]: String(index + 1),
|
|
24237
|
+
[NAV_ORDER_KEY]: getNavbarOrderJson()
|
|
24238
|
+
},
|
|
24239
|
+
deps
|
|
24240
|
+
);
|
|
24241
|
+
return true;
|
|
24242
|
+
}
|
|
24243
|
+
function retargetPageLinks(change, deps) {
|
|
24244
|
+
const { oldPath, newPath, oldTitle, newTitle } = change;
|
|
24245
|
+
if (!oldPath || !newPath || normalizePath2(oldPath) === normalizePath2(newPath)) return 0;
|
|
24246
|
+
const content = deps.getEditContent();
|
|
24247
|
+
const delta = {};
|
|
24248
|
+
for (const anchor of Array.from(document.querySelectorAll("[data-ohw-href-key]"))) {
|
|
24249
|
+
const hrefKey = anchor.getAttribute("data-ohw-href-key");
|
|
24250
|
+
if (!isPageLinkKey(hrefKey)) continue;
|
|
24251
|
+
const href = currentHref(hrefKey, anchor, content);
|
|
24252
|
+
if (!pointsAt(href, oldPath)) continue;
|
|
24253
|
+
const nextHref = retargetHref(href, oldPath, newPath);
|
|
24254
|
+
deps.applyLinkByKey(hrefKey, nextHref);
|
|
24255
|
+
delta[hrefKey] = nextHref;
|
|
24256
|
+
if (!oldTitle || !newTitle) continue;
|
|
24257
|
+
const labelKey = labelKeyFor(hrefKey);
|
|
24258
|
+
const label = content[labelKey] ?? anchor.querySelector('[data-ohw-editable="text"]')?.textContent ?? "";
|
|
24259
|
+
if (label.trim() !== oldTitle) continue;
|
|
24260
|
+
setLabelText(labelKey, newTitle);
|
|
24261
|
+
delta[labelKey] = newTitle;
|
|
24262
|
+
}
|
|
24263
|
+
commit(delta, deps);
|
|
24264
|
+
return Object.keys(delta).filter((key) => key.endsWith("-href")).length;
|
|
24265
|
+
}
|
|
24266
|
+
|
|
24086
24267
|
// src/ui/navbar-container-chrome.tsx
|
|
24087
24268
|
var import_lucide_react21 = require("lucide-react");
|
|
24088
24269
|
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
@@ -24970,7 +25151,7 @@ function getNavigationSelectionParent(el) {
|
|
|
24970
25151
|
if (!isFooterLinksContainer(el) && (el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isInferredFooterGroup2(el))) {
|
|
24971
25152
|
return resolveFooterLinksContainerFrom(el);
|
|
24972
25153
|
}
|
|
24973
|
-
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || isFooterLinksContainer(el)) {
|
|
25154
|
+
if (el.hasAttribute("data-ohw-nav-container") || el.hasAttribute("data-ohw-nav-drawer") || el.hasAttribute("data-ohw-footer-col") || el.hasAttribute("data-ohw-footer-column") || isFooterLinksContainer(el) || isInferredFooterGroup2(el)) {
|
|
24974
25155
|
return getNavigationRoot(el);
|
|
24975
25156
|
}
|
|
24976
25157
|
return null;
|
|
@@ -25192,7 +25373,6 @@ var ICONS = {
|
|
|
25192
25373
|
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"/>',
|
|
25193
25374
|
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"/>'
|
|
25194
25375
|
};
|
|
25195
|
-
var HEIGHT_SETTLE_DELAYS = [150, 400, 800];
|
|
25196
25376
|
var SELECTION_CHROME_GAP2 = 4;
|
|
25197
25377
|
var TOOLBAR_STROKE_GAP2 = 4;
|
|
25198
25378
|
var TOOLBAR_OFFSET_FROM_ELEMENT = SELECTION_CHROME_GAP2 + TOOLBAR_STROKE_GAP2;
|
|
@@ -25290,7 +25470,7 @@ function applyVisibleViewport(el, parentScroll) {
|
|
|
25290
25470
|
el.style.top = `${top}px`;
|
|
25291
25471
|
el.style.height = `${height}px`;
|
|
25292
25472
|
}
|
|
25293
|
-
var
|
|
25473
|
+
var TOOLBAR_EDGE_MARGIN4 = 4;
|
|
25294
25474
|
function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
25295
25475
|
const isAbove = transform.includes("translateY(-100%)");
|
|
25296
25476
|
let visualTop = isAbove ? top - approxH : top;
|
|
@@ -25317,8 +25497,8 @@ function clampToolbarToClip(top, transform, rect, clip, approxH, gap) {
|
|
|
25317
25497
|
function clampToolbarLeft(centerX, toolbarWidth) {
|
|
25318
25498
|
const half = toolbarWidth / 2;
|
|
25319
25499
|
return Math.max(
|
|
25320
|
-
|
|
25321
|
-
Math.min(centerX, window.innerWidth -
|
|
25500
|
+
TOOLBAR_EDGE_MARGIN4 + half,
|
|
25501
|
+
Math.min(centerX, window.innerWidth - TOOLBAR_EDGE_MARGIN4 - half)
|
|
25322
25502
|
);
|
|
25323
25503
|
}
|
|
25324
25504
|
function calcToolbarPos(rect, parentScroll, toolbarW = 306) {
|
|
@@ -26198,21 +26378,6 @@ function OhhwellsBridge() {
|
|
|
26198
26378
|
const [isItemDragging, setIsItemDragging] = (0, import_react21.useState)(false);
|
|
26199
26379
|
const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react21.useState)(false);
|
|
26200
26380
|
isFooterFrameSelectionRef.current = isFooterFrameSelection;
|
|
26201
|
-
const [floatingPanel, setFloatingPanel] = (0, import_react21.useState)(null);
|
|
26202
|
-
const floatingPanelOpenRef = (0, import_react21.useRef)(false);
|
|
26203
|
-
floatingPanelOpenRef.current = floatingPanel !== null;
|
|
26204
|
-
const floatingPanelRef = (0, import_react21.useRef)(null);
|
|
26205
|
-
floatingPanelRef.current = floatingPanel;
|
|
26206
|
-
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react21.useState)(null);
|
|
26207
|
-
const buttonCollectionDragRef = (0, import_react21.useRef)(null);
|
|
26208
|
-
const buttonDropInsertIndexRef = (0, import_react21.useRef)(null);
|
|
26209
|
-
const [buttonDropSlots, setButtonDropSlots] = (0, import_react21.useState)([]);
|
|
26210
|
-
const [activeButtonDropIndex, setActiveButtonDropIndex] = (0, import_react21.useState)(null);
|
|
26211
|
-
const buttonPointerDragRef = (0, import_react21.useRef)(null);
|
|
26212
|
-
const [buttonStyleTick, setButtonStyleTick] = (0, import_react21.useState)(0);
|
|
26213
|
-
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react21.useState)(null);
|
|
26214
|
-
const [editorViewport, setEditorViewport] = (0, import_react21.useState)("desktop");
|
|
26215
|
-
const [parentScrollSnap, setParentScrollSnap] = (0, import_react21.useState)(null);
|
|
26216
26381
|
const [navDropdownPreviewOpen, setNavDropdownPreviewOpen] = (0, import_react21.useState)(null);
|
|
26217
26382
|
const [footerHeadingVisible, setFooterHeadingVisible] = (0, import_react21.useState)(null);
|
|
26218
26383
|
const footerDragRef = (0, import_react21.useRef)(null);
|
|
@@ -26238,6 +26403,21 @@ function OhhwellsBridge() {
|
|
|
26238
26403
|
const stylesRef = (0, import_react21.useRef)("");
|
|
26239
26404
|
const appliedDrawerRef = (0, import_react21.useRef)(null);
|
|
26240
26405
|
const pendingDeleteUndoRef = (0, import_react21.useRef)(null);
|
|
26406
|
+
const [floatingPanel, setFloatingPanel] = (0, import_react21.useState)(null);
|
|
26407
|
+
const floatingPanelOpenRef = (0, import_react21.useRef)(false);
|
|
26408
|
+
const floatingPanelRef = (0, import_react21.useRef)(null);
|
|
26409
|
+
floatingPanelRef.current = floatingPanel;
|
|
26410
|
+
const setFloatingPanelRef = (0, import_react21.useRef)(setFloatingPanel);
|
|
26411
|
+
const [floatingPanelPos, setFloatingPanelPos] = (0, import_react21.useState)(null);
|
|
26412
|
+
const buttonCollectionDragRef = (0, import_react21.useRef)(null);
|
|
26413
|
+
const buttonDropInsertIndexRef = (0, import_react21.useRef)(null);
|
|
26414
|
+
const [buttonDropSlots, setButtonDropSlots] = (0, import_react21.useState)([]);
|
|
26415
|
+
const [activeButtonDropIndex, setActiveButtonDropIndex] = (0, import_react21.useState)(null);
|
|
26416
|
+
const buttonPointerDragRef = (0, import_react21.useRef)(null);
|
|
26417
|
+
const [buttonStyleTick, setButtonStyleTick] = (0, import_react21.useState)(0);
|
|
26418
|
+
const [logoSizeDraft, setLogoSizeDraft] = (0, import_react21.useState)(null);
|
|
26419
|
+
const [editorViewport, setEditorViewport] = (0, import_react21.useState)("desktop");
|
|
26420
|
+
const [parentScrollSnap, setParentScrollSnap] = (0, import_react21.useState)(null);
|
|
26241
26421
|
const [sitePages, setSitePages] = (0, import_react21.useState)([]);
|
|
26242
26422
|
const collectionItemsRef = (0, import_react21.useRef)(/* @__PURE__ */ new Map());
|
|
26243
26423
|
const [sectionsByPath, setSectionsByPath] = (0, import_react21.useState)({});
|
|
@@ -26247,7 +26427,18 @@ function OhhwellsBridge() {
|
|
|
26247
26427
|
const linkPopoverOpenRef = (0, import_react21.useRef)(false);
|
|
26248
26428
|
const linkPopoverGraceUntilRef = (0, import_react21.useRef)(0);
|
|
26249
26429
|
setLinkPopoverRef.current = setLinkPopover;
|
|
26430
|
+
setFloatingPanelRef.current = setFloatingPanel;
|
|
26250
26431
|
linkPopoverSessionRef.current = linkPopover;
|
|
26432
|
+
floatingPanelOpenRef.current = Boolean(floatingPanel);
|
|
26433
|
+
(0, import_react21.useEffect)(() => {
|
|
26434
|
+
const syncViewport = () => {
|
|
26435
|
+
const next = window.innerWidth <= 480 ? "mobile" : "desktop";
|
|
26436
|
+
setEditorViewport((prev) => prev === next ? prev : next);
|
|
26437
|
+
};
|
|
26438
|
+
syncViewport();
|
|
26439
|
+
window.addEventListener("resize", syncViewport);
|
|
26440
|
+
return () => window.removeEventListener("resize", syncViewport);
|
|
26441
|
+
}, []);
|
|
26251
26442
|
(0, import_react21.useEffect)(() => {
|
|
26252
26443
|
setSectionOrderPersistHandler((entries) => {
|
|
26253
26444
|
const currentPath = window.location.pathname;
|
|
@@ -26396,6 +26587,43 @@ function OhhwellsBridge() {
|
|
|
26396
26587
|
if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
|
|
26397
26588
|
return () => window.removeEventListener("message", onSitePages);
|
|
26398
26589
|
}, [isEditMode, postToParent2]);
|
|
26590
|
+
(0, import_react21.useEffect)(() => {
|
|
26591
|
+
if (!isEditMode) return;
|
|
26592
|
+
const deps = {
|
|
26593
|
+
getEditContent: () => editContentRef.current,
|
|
26594
|
+
setEditContent: (next) => {
|
|
26595
|
+
editContentRef.current = next;
|
|
26596
|
+
},
|
|
26597
|
+
applyLinkByKey,
|
|
26598
|
+
postToParent: postToParent2
|
|
26599
|
+
};
|
|
26600
|
+
const onPageMessage = (e) => {
|
|
26601
|
+
if (e.data?.type === "ow:page-created") {
|
|
26602
|
+
const { path, title } = e.data;
|
|
26603
|
+
if (typeof path !== "string" || !path) return;
|
|
26604
|
+
if (addNavLinkForPage({ path, title: typeof title === "string" && title ? title : path }, deps)) {
|
|
26605
|
+
enforceLinkHrefs();
|
|
26606
|
+
}
|
|
26607
|
+
return;
|
|
26608
|
+
}
|
|
26609
|
+
if (e.data?.type === "ow:page-renamed") {
|
|
26610
|
+
const { oldPath, newPath, oldTitle, newTitle } = e.data;
|
|
26611
|
+
if (typeof oldPath !== "string" || typeof newPath !== "string") return;
|
|
26612
|
+
const moved = retargetPageLinks(
|
|
26613
|
+
{
|
|
26614
|
+
oldPath,
|
|
26615
|
+
newPath,
|
|
26616
|
+
oldTitle: typeof oldTitle === "string" ? oldTitle : void 0,
|
|
26617
|
+
newTitle: typeof newTitle === "string" ? newTitle : void 0
|
|
26618
|
+
},
|
|
26619
|
+
deps
|
|
26620
|
+
);
|
|
26621
|
+
if (moved > 0) enforceLinkHrefs();
|
|
26622
|
+
}
|
|
26623
|
+
};
|
|
26624
|
+
window.addEventListener("message", onPageMessage);
|
|
26625
|
+
return () => window.removeEventListener("message", onPageMessage);
|
|
26626
|
+
}, [isEditMode, postToParent2]);
|
|
26399
26627
|
(0, import_react21.useEffect)(() => {
|
|
26400
26628
|
if (!isEditMode || shouldUseDevFixtures()) return;
|
|
26401
26629
|
void loadAllSectionsManifest().then((manifest) => {
|
|
@@ -27944,6 +28172,7 @@ function OhhwellsBridge() {
|
|
|
27944
28172
|
applyAiFooterFromContent(content);
|
|
27945
28173
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
27946
28174
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
28175
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
27947
28176
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
27948
28177
|
}
|
|
27949
28178
|
applyBrandChrome(content);
|
|
@@ -27954,12 +28183,12 @@ function OhhwellsBridge() {
|
|
|
27954
28183
|
if (key === "__ohw_sections") continue;
|
|
27955
28184
|
if (key === AI_SECTIONS_KEY) continue;
|
|
27956
28185
|
if (key === AI_FOOTER_KEY) continue;
|
|
28186
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
28187
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27957
28188
|
if (key === BRAND_KIT_KEY) continue;
|
|
27958
28189
|
if (key === STYLE_STORE_KEY) continue;
|
|
27959
28190
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
27960
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
27961
28191
|
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
27962
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
27963
28192
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
27964
28193
|
continue;
|
|
27965
28194
|
}
|
|
@@ -28190,17 +28419,18 @@ function OhhwellsBridge() {
|
|
|
28190
28419
|
}
|
|
28191
28420
|
applyAiFooterFromContent(content);
|
|
28192
28421
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
28422
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
28193
28423
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
28194
28424
|
}
|
|
28195
28425
|
for (const [key, val] of Object.entries(content)) {
|
|
28196
28426
|
if (key === "__ohw_sections") continue;
|
|
28197
28427
|
if (key === AI_SECTIONS_KEY) continue;
|
|
28198
28428
|
if (key === AI_FOOTER_KEY) continue;
|
|
28429
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
28430
|
+
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
28199
28431
|
if (key === BRAND_KIT_KEY) continue;
|
|
28200
28432
|
if (key === STYLE_STORE_KEY) continue;
|
|
28201
28433
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
28202
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
28203
|
-
if (LOGO_IMAGE_KEYS.includes(key)) continue;
|
|
28204
28434
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
28205
28435
|
continue;
|
|
28206
28436
|
}
|
|
@@ -28467,26 +28697,11 @@ function OhhwellsBridge() {
|
|
|
28467
28697
|
const t2 = setTimeout(measure, 500);
|
|
28468
28698
|
const ro = new ResizeObserver(schedule);
|
|
28469
28699
|
ro.observe(document.body);
|
|
28470
|
-
let lastWidth = window.innerWidth;
|
|
28471
|
-
let resizeTimers = [];
|
|
28472
|
-
const clearResizeTimers = () => {
|
|
28473
|
-
resizeTimers.forEach(clearTimeout);
|
|
28474
|
-
resizeTimers = [];
|
|
28475
|
-
};
|
|
28476
|
-
const handleResize = () => {
|
|
28477
|
-
if (window.innerWidth === lastWidth) return;
|
|
28478
|
-
lastWidth = window.innerWidth;
|
|
28479
|
-
clearResizeTimers();
|
|
28480
|
-
resizeTimers = HEIGHT_SETTLE_DELAYS.map((delay) => setTimeout(measure, delay));
|
|
28481
|
-
};
|
|
28482
|
-
window.addEventListener("resize", handleResize);
|
|
28483
28700
|
return () => {
|
|
28484
28701
|
clearTimeout(t1);
|
|
28485
28702
|
clearTimeout(t2);
|
|
28486
28703
|
if (raf != null) cancelAnimationFrame(raf);
|
|
28487
28704
|
ro.disconnect();
|
|
28488
|
-
clearResizeTimers();
|
|
28489
|
-
window.removeEventListener("resize", handleResize);
|
|
28490
28705
|
};
|
|
28491
28706
|
}, [pathname, isEditMode, postToParent2]);
|
|
28492
28707
|
(0, import_react21.useEffect)(() => {
|
|
@@ -28783,6 +28998,13 @@ function OhhwellsBridge() {
|
|
|
28783
28998
|
if (target.closest("[data-ohw-state-toggle]")) return;
|
|
28784
28999
|
if (target.closest("[data-ohw-max-badge]")) return;
|
|
28785
29000
|
if (isInsideLinkEditor(target)) return;
|
|
29001
|
+
if (isInsideFloatingPanel(target)) return;
|
|
29002
|
+
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
29003
|
+
if (target.closest(
|
|
29004
|
+
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
29005
|
+
)) {
|
|
29006
|
+
return;
|
|
29007
|
+
}
|
|
28786
29008
|
if (selectedMediaElRef.current && !selectedMediaElRef.current.contains(target) && !target.closest("[data-ohw-media-overlay], [data-ohw-edit-chrome], [data-ohw-item-interaction]")) {
|
|
28787
29009
|
clearMediaSelectionRef.current();
|
|
28788
29010
|
}
|
|
@@ -28806,8 +29028,6 @@ function OhhwellsBridge() {
|
|
|
28806
29028
|
return;
|
|
28807
29029
|
}
|
|
28808
29030
|
}
|
|
28809
|
-
if (isInsideFloatingPanel(target)) return;
|
|
28810
|
-
if (target.closest("[data-ohw-form-toolbar]")) return;
|
|
28811
29031
|
const collectionItem = matchCollectionItemClick(target, collectionItemsRef.current);
|
|
28812
29032
|
if (collectionItem) {
|
|
28813
29033
|
e.preventDefault();
|
|
@@ -28819,11 +29039,6 @@ function OhhwellsBridge() {
|
|
|
28819
29039
|
});
|
|
28820
29040
|
return;
|
|
28821
29041
|
}
|
|
28822
|
-
if (target.closest(
|
|
28823
|
-
'[data-ohw-field-toolbar], [data-ohw-field-type-picker], [data-radix-popper-content-wrapper], [role="menu"], [data-slot="dropdown-menu-content"]'
|
|
28824
|
-
)) {
|
|
28825
|
-
return;
|
|
28826
|
-
}
|
|
28827
29042
|
{
|
|
28828
29043
|
const formEl = getFormElement(target);
|
|
28829
29044
|
const onSuccessText = target.closest(`[${SUCCESS_TEXT_ATTR}]`);
|
|
@@ -28977,9 +29192,13 @@ function OhhwellsBridge() {
|
|
|
28977
29192
|
if (isIconEditable(editable) && !getSocialItem(editable)) {
|
|
28978
29193
|
e.preventDefault();
|
|
28979
29194
|
e.stopPropagation();
|
|
28980
|
-
selectIconElementRef.current(editable);
|
|
28981
29195
|
const aiIcon = editable.hasAttribute("data-ai-icon");
|
|
28982
29196
|
const featureIcon = aiIcon && /\.features\.\d+\.icon$/.test(editable.dataset.ohwKey ?? "");
|
|
29197
|
+
if (aiIcon) {
|
|
29198
|
+
aiSectionApiRef.current?.selectFromElement(editable);
|
|
29199
|
+
} else {
|
|
29200
|
+
selectIconElementRef.current(editable);
|
|
29201
|
+
}
|
|
28983
29202
|
postToParentRef.current({
|
|
28984
29203
|
type: "ow:icon-pick",
|
|
28985
29204
|
key: editable.dataset.ohwKey ?? "",
|
|
@@ -29207,6 +29426,9 @@ function OhhwellsBridge() {
|
|
|
29207
29426
|
setHoveredItemRect(null);
|
|
29208
29427
|
hoveredNavContainerRef.current = null;
|
|
29209
29428
|
setHoveredNavContainerRect(null);
|
|
29429
|
+
siblingHintElRef.current = null;
|
|
29430
|
+
setSiblingHintRect(null);
|
|
29431
|
+
setSiblingHintRects([]);
|
|
29210
29432
|
return;
|
|
29211
29433
|
}
|
|
29212
29434
|
{
|
|
@@ -29327,7 +29549,6 @@ function OhhwellsBridge() {
|
|
|
29327
29549
|
hoveredNavContainerRef.current = null;
|
|
29328
29550
|
setHoveredNavContainerRect(null);
|
|
29329
29551
|
hoveredItemElRef.current = editable;
|
|
29330
|
-
setHoveredItemRect(isSelectedForHoverRef.current(editable) ? null : editable.getBoundingClientRect());
|
|
29331
29552
|
}
|
|
29332
29553
|
}
|
|
29333
29554
|
}
|
|
@@ -30037,7 +30258,11 @@ function OhhwellsBridge() {
|
|
|
30037
30258
|
};
|
|
30038
30259
|
const handleMouseMove = (e) => {
|
|
30039
30260
|
const { clientX, clientY } = e;
|
|
30040
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
30261
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
30262
|
+
dismissImageHover();
|
|
30263
|
+
clearImageHover();
|
|
30264
|
+
return;
|
|
30265
|
+
}
|
|
30041
30266
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) {
|
|
30042
30267
|
document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
|
|
30043
30268
|
formHoverElRef.current = null;
|
|
@@ -30066,7 +30291,12 @@ function OhhwellsBridge() {
|
|
|
30066
30291
|
setHoveredItemRect(null);
|
|
30067
30292
|
hoveredNavContainerRef.current = null;
|
|
30068
30293
|
setHoveredNavContainerRect(null);
|
|
30294
|
+
siblingHintElRef.current = null;
|
|
30295
|
+
setSiblingHintRect(null);
|
|
30296
|
+
setSiblingHintRects([]);
|
|
30069
30297
|
dismissImageHover();
|
|
30298
|
+
clearImageHover();
|
|
30299
|
+
setSectionGap(null);
|
|
30070
30300
|
return;
|
|
30071
30301
|
}
|
|
30072
30302
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
@@ -30078,7 +30308,11 @@ function OhhwellsBridge() {
|
|
|
30078
30308
|
if (e.data?.type !== "ow:pointer-sync") return;
|
|
30079
30309
|
const { clientX, clientY } = e.data;
|
|
30080
30310
|
if (typeof clientX !== "number" || typeof clientY !== "number") return;
|
|
30081
|
-
if (pointOwnedByFloatingPanel(clientX, clientY))
|
|
30311
|
+
if (pointOwnedByFloatingPanel(clientX, clientY)) {
|
|
30312
|
+
dismissImageHover();
|
|
30313
|
+
clearImageHover();
|
|
30314
|
+
return;
|
|
30315
|
+
}
|
|
30082
30316
|
if (isNavDrawerOpen() && isPointOutsideOpenDrawer(clientX, clientY)) return;
|
|
30083
30317
|
if (probeSocialsRowAt(clientX, clientY)) return;
|
|
30084
30318
|
probeSectionGapAt(clientX, clientY);
|
|
@@ -30458,6 +30692,7 @@ function OhhwellsBridge() {
|
|
|
30458
30692
|
applyAiFooterFromContent(content);
|
|
30459
30693
|
if (typeof content[STYLE_STORE_KEY] === "string") {
|
|
30460
30694
|
stylesRef.current = content[STYLE_STORE_KEY];
|
|
30695
|
+
document.querySelectorAll('[data-ohw-editable="form"]').forEach((f) => markFormFields(f));
|
|
30461
30696
|
applyStylesToDom(parseStyleStore(content[STYLE_STORE_KEY]));
|
|
30462
30697
|
}
|
|
30463
30698
|
applyBrandChrome(content);
|
|
@@ -30472,12 +30707,12 @@ function OhhwellsBridge() {
|
|
|
30472
30707
|
}
|
|
30473
30708
|
if (key === AI_SECTIONS_KEY) continue;
|
|
30474
30709
|
if (key === AI_FOOTER_KEY) continue;
|
|
30710
|
+
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
30711
|
+
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
30475
30712
|
if (key === BRAND_KIT_KEY) continue;
|
|
30476
30713
|
if (key === STYLE_STORE_KEY) continue;
|
|
30477
30714
|
if (BRAND_CHROME_KEYS.has(key)) continue;
|
|
30478
|
-
if (key === LOGO_PLACEHOLDER_KEY) continue;
|
|
30479
30715
|
if (key === CUSTOM_CODE_AFTER_HEAD_KEY || key === CUSTOM_CODE_BEFORE_HEAD_KEY) continue;
|
|
30480
|
-
if (LOGO_IMAGE_KEYS.includes(key) && !String(val ?? "").trim()) continue;
|
|
30481
30716
|
if (typeof content[AI_FOOTER_KEY] === "string" && content[AI_FOOTER_KEY] && isAiFooterOwnedContentKey(key)) {
|
|
30482
30717
|
continue;
|
|
30483
30718
|
}
|
|
@@ -31113,6 +31348,12 @@ function OhhwellsBridge() {
|
|
|
31113
31348
|
closeLinkPopoverRef.current();
|
|
31114
31349
|
return;
|
|
31115
31350
|
}
|
|
31351
|
+
if (floatingPanelOpenRef.current) {
|
|
31352
|
+
setFloatingPanelRef.current(null);
|
|
31353
|
+
deselectRef.current();
|
|
31354
|
+
deactivateRef.current();
|
|
31355
|
+
return;
|
|
31356
|
+
}
|
|
31116
31357
|
deselectRef.current();
|
|
31117
31358
|
deactivateRef.current();
|
|
31118
31359
|
clearMediaSelectionRef.current();
|
|
@@ -31501,7 +31742,7 @@ function OhhwellsBridge() {
|
|
|
31501
31742
|
const sectionEl = foundEl && !foundEl.hasAttribute("data-ohw-ai-template-hidden") && !foundEl.hasAttribute("data-ohw-ai-removed") && !foundEl.hasAttribute("data-ohw-ai-replaced-by") ? foundEl : null;
|
|
31502
31743
|
const nodes = sectionEl ? collectEditableNodes(void 0, sectionEl).filter(
|
|
31503
31744
|
(n) => n.key && !n.key.startsWith("__ohw_") && !["meta", "sections", "video-setting"].includes(n.type)
|
|
31504
|
-
).map((n) => ({ ...n, text: n.text ?? "", type: normalizeAiNodeType(n.type) })) : [];
|
|
31745
|
+
).map((n) => ({ ...n, text: n.text ?? "", type: normalizeAiNodeType(n.type) })).map((n) => withNodeFontSize(n, sectionEl)) : [];
|
|
31505
31746
|
const items = sectionEl ? collectItemGroups(sectionEl) : [];
|
|
31506
31747
|
const box = sectionEl?.getBoundingClientRect();
|
|
31507
31748
|
const rect = box ? {
|
|
@@ -31948,10 +32189,10 @@ function OhhwellsBridge() {
|
|
|
31948
32189
|
window.removeEventListener("message", handleDuplicateSection);
|
|
31949
32190
|
window.removeEventListener("message", handleDeactivate);
|
|
31950
32191
|
window.removeEventListener("message", handleSelectNav);
|
|
31951
|
-
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
31952
32192
|
window.removeEventListener("message", handleToastAction);
|
|
31953
32193
|
window.removeEventListener("message", handleFormCount);
|
|
31954
32194
|
window.removeEventListener("message", handleUiEscape);
|
|
32195
|
+
document.documentElement.removeAttribute("data-ohw-panel-dragging");
|
|
31955
32196
|
autoSaveTimers.current.forEach(clearTimeout);
|
|
31956
32197
|
autoSaveTimers.current.clear();
|
|
31957
32198
|
if (imageUnhoverTimerRef.current) clearTimeout(imageUnhoverTimerRef.current);
|
|
@@ -32245,7 +32486,7 @@ function OhhwellsBridge() {
|
|
|
32245
32486
|
postToParent2({
|
|
32246
32487
|
type: "ow:ready",
|
|
32247
32488
|
version: "1",
|
|
32248
|
-
bridgeVersion: "0.1.
|
|
32489
|
+
bridgeVersion: "0.1.160-next.427",
|
|
32249
32490
|
path: pathname,
|
|
32250
32491
|
nodes: collectEditableNodes(editContentRef.current),
|
|
32251
32492
|
sections
|